aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--CMakeLists.txt167
-rw-r--r--CODE_OWNERS.TXT4
-rw-r--r--LICENSE.TXT2
-rw-r--r--NOTES.txt7
-rw-r--r--bindings/python/README.txt4
-rw-r--r--bindings/python/clang/cindex.py100
-rw-r--r--bindings/python/examples/cindex/cindex-dump.py2
-rw-r--r--bindings/python/tests/CMakeLists.txt46
-rw-r--r--bindings/python/tests/cindex/test_access_specifiers.py4
-rw-r--r--bindings/python/tests/cindex/test_cdb.py19
-rw-r--r--bindings/python/tests/cindex/test_code_completion.py41
-rw-r--r--bindings/python/tests/cindex/test_comment.py5
-rw-r--r--bindings/python/tests/cindex/test_cursor.py5
-rw-r--r--bindings/python/tests/cindex/test_cursor_kind.py5
-rw-r--r--bindings/python/tests/cindex/test_diagnostics.py9
-rw-r--r--bindings/python/tests/cindex/test_exception_specification_kind.py5
-rw-r--r--bindings/python/tests/cindex/test_file.py5
-rw-r--r--bindings/python/tests/cindex/test_index.py5
-rw-r--r--bindings/python/tests/cindex/test_linkage.py5
-rw-r--r--bindings/python/tests/cindex/test_location.py5
-rw-r--r--bindings/python/tests/cindex/test_tls_kind.py5
-rw-r--r--bindings/python/tests/cindex/test_token_kind.py5
-rw-r--r--bindings/python/tests/cindex/test_tokens.py5
-rw-r--r--bindings/python/tests/cindex/test_translation_unit.py80
-rw-r--r--bindings/python/tests/cindex/test_type.py30
-rw-r--r--bindings/python/tests/cindex/util.py15
-rw-r--r--cmake/caches/Fuchsia-stage2.cmake126
-rw-r--r--cmake/caches/Fuchsia.cmake65
-rw-r--r--cmake/modules/AddClang.cmake1
-rw-r--r--cmake/modules/FindZ3.cmake27
-rw-r--r--docs/AddressSanitizer.rst8
-rw-r--r--docs/AutomaticReferenceCounting.rst91
-rw-r--r--docs/Block-ABI-Apple.txt2
-rw-r--r--docs/ClangCommandLineReference.rst378
-rw-r--r--docs/ClangFormat.rst8
-rw-r--r--docs/ClangFormatStyleOptions.rst86
-rw-r--r--docs/ClangPlugins.rst4
-rw-r--r--docs/ClangTools.rst6
-rw-r--r--docs/CommandGuide/clang.rst7
-rw-r--r--docs/ControlFlowIntegrity.rst2
-rw-r--r--docs/ControlFlowIntegrityDesign.rst154
-rw-r--r--docs/CrossCompilation.rst2
-rw-r--r--docs/DiagnosticsReference.rst10
-rw-r--r--docs/HardwareAssistedAddressSanitizerDesign.rst18
-rw-r--r--docs/InternalsManual.rst30
-rw-r--r--docs/IntroductionToTheClangAST.rst46
-rw-r--r--docs/LanguageExtensions.rst173
-rw-r--r--docs/LibASTMatchers.rst4
-rw-r--r--docs/LibASTMatchersReference.html1834
-rw-r--r--docs/LibASTMatchersTutorial.rst9
-rw-r--r--docs/LibFormat.rst2
-rw-r--r--docs/LibTooling.rst2
-rw-r--r--docs/MSVCCompatibility.rst4
-rw-r--r--docs/MemorySanitizer.rst2
-rw-r--r--docs/Modules.rst7
-rw-r--r--docs/OpenMPSupport.rst15
-rw-r--r--docs/PCHInternals.rst6
-rw-r--r--docs/PTHInternals.rst163
-rw-r--r--docs/RAVFrontendAction.rst4
-rw-r--r--docs/ReleaseNotes.rst337
-rw-r--r--docs/SanitizerCoverage.rst2
-rw-r--r--docs/SourceBasedCodeCoverage.rst2
-rw-r--r--docs/ThinLTO.rst14
-rw-r--r--docs/ThreadSanitizer.rst2
-rw-r--r--docs/Toolchain.rst10
-rw-r--r--docs/Tooling.rst2
-rw-r--r--docs/UndefinedBehaviorSanitizer.rst44
-rw-r--r--docs/UsersManual.rst291
-rw-r--r--docs/analyzer/DebugChecks.rst22
-rw-r--r--docs/analyzer/RegionStore.txt4
-rw-r--r--docs/conf.py13
-rw-r--r--docs/index.rst1
-rw-r--r--docs/tools/dump_ast_matchers.py25
-rw-r--r--docs/tools/dump_format_style.py17
-rw-r--r--examples/AnnotateFunctions/CMakeLists.txt2
-rw-r--r--examples/PrintFunctionNames/CMakeLists.txt2
-rw-r--r--examples/analyzer-plugin/CMakeLists.txt2
-rw-r--r--examples/analyzer-plugin/MainCallChecker.cpp6
-rw-r--r--examples/clang-interpreter/CMakeLists.txt1
-rw-r--r--examples/clang-interpreter/Test.cxx2
-rw-r--r--examples/clang-interpreter/main.cpp8
-rw-r--r--include/clang-c/Index.h146
-rw-r--r--include/clang/AST/ASTContext.h97
-rw-r--r--include/clang/AST/ASTContextAllocate.h38
-rw-r--r--include/clang/AST/ASTDiagnostic.h12
-rw-r--r--include/clang/AST/ASTDumperUtils.h97
-rw-r--r--include/clang/AST/ASTImporter.h193
-rw-r--r--include/clang/AST/ASTImporterLookupTable.h75
-rw-r--r--include/clang/AST/ASTStructuralEquivalence.h14
-rw-r--r--include/clang/AST/ASTVector.h1
-rw-r--r--include/clang/AST/Attr.h14
-rw-r--r--include/clang/AST/AttrIterator.h19
-rw-r--r--include/clang/AST/AttrVisitor.h76
-rw-r--r--include/clang/AST/BaseSubobject.h1
-rw-r--r--include/clang/AST/CMakeLists.txt9
-rw-r--r--include/clang/AST/CanonicalType.h2
-rw-r--r--include/clang/AST/Comment.h35
-rw-r--r--include/clang/AST/CommentDiagnostic.h15
-rw-r--r--include/clang/AST/CommentVisitor.h34
-rw-r--r--include/clang/AST/Decl.h718
-rw-r--r--include/clang/AST/DeclBase.h621
-rw-r--r--include/clang/AST/DeclCXX.h154
-rw-r--r--include/clang/AST/DeclFriend.h2
-rw-r--r--include/clang/AST/DeclObjC.h191
-rw-r--r--include/clang/AST/DeclOpenMP.h120
-rw-r--r--include/clang/AST/DeclTemplate.h4
-rw-r--r--include/clang/AST/DeclVisitor.h13
-rw-r--r--include/clang/AST/DeclarationName.h621
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h18
-rw-r--r--include/clang/AST/Expr.h1312
-rw-r--r--include/clang/AST/ExprCXX.h1613
-rw-r--r--include/clang/AST/ExprObjC.h90
-rw-r--r--include/clang/AST/ExprOpenMP.h6
-rw-r--r--include/clang/AST/FormatString.h (renamed from include/clang/Analysis/Analyses/FormatString.h)37
-rw-r--r--include/clang/AST/GlobalDecl.h28
-rw-r--r--include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h4
-rw-r--r--include/clang/AST/Mangle.h1
-rw-r--r--include/clang/AST/NSAPI.h11
-rw-r--r--include/clang/AST/NestedNameSpecifier.h11
-rw-r--r--include/clang/AST/ODRHash.h10
-rw-r--r--include/clang/AST/OSLog.h (renamed from include/clang/Analysis/Analyses/OSLog.h)42
-rw-r--r--include/clang/AST/OpenMPClause.h448
-rw-r--r--include/clang/AST/OperationKinds.def16
-rw-r--r--include/clang/AST/PrettyPrinter.h62
-rw-r--r--include/clang/AST/RawCommentList.h6
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h104
-rw-r--r--include/clang/AST/Stmt.h1763
-rw-r--r--include/clang/AST/StmtCXX.h56
-rw-r--r--include/clang/AST/StmtDataCollectors.td6
-rw-r--r--include/clang/AST/StmtObjC.h38
-rw-r--r--include/clang/AST/StmtOpenMP.h40
-rw-r--r--include/clang/AST/StmtVisitor.h51
-rw-r--r--include/clang/AST/TemplateArgumentVisitor.h99
-rw-r--r--include/clang/AST/TemplateBase.h21
-rw-r--r--include/clang/AST/TemplateName.h1
-rw-r--r--include/clang/AST/TextNodeDumper.h298
-rw-r--r--include/clang/AST/Type.h909
-rw-r--r--include/clang/AST/TypeLoc.h93
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h252
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h2
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h1
-rw-r--r--include/clang/Analysis/Analyses/ExprMutationAnalyzer.h96
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h8
-rw-r--r--include/clang/Analysis/Analyses/PseudoConstantAnalysis.h45
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h2
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTIL.h8
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTraverse.h21
-rw-r--r--include/clang/Analysis/AnalysisDeclContext.h32
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h15
-rw-r--r--include/clang/Analysis/CallGraph.h1
-rw-r--r--include/clang/Analysis/CloneDetection.h2
-rw-r--r--include/clang/Analysis/ConstructionContext.h14
-rw-r--r--include/clang/Analysis/ProgramPoint.h28
-rw-r--r--include/clang/Analysis/SelectorExtras.h (renamed from lib/StaticAnalyzer/Checkers/SelectorExtras.h)13
-rw-r--r--include/clang/Basic/AlignedAllocation.h4
-rw-r--r--include/clang/Basic/AllDiagnostics.h22
-rw-r--r--include/clang/Basic/Attr.td278
-rw-r--r--include/clang/Basic/AttrDocs.td453
-rw-r--r--include/clang/Basic/Builtins.def35
-rw-r--r--include/clang/Basic/BuiltinsAArch64.def105
-rw-r--r--include/clang/Basic/BuiltinsAMDGPU.def37
-rw-r--r--include/clang/Basic/BuiltinsARM.def98
-rw-r--r--include/clang/Basic/BuiltinsHexagon.def3296
-rw-r--r--include/clang/Basic/BuiltinsNios2.def70
-rw-r--r--include/clang/Basic/BuiltinsPPC.def6
-rw-r--r--include/clang/Basic/BuiltinsWebAssembly.def90
-rw-r--r--include/clang/Basic/BuiltinsX86.def251
-rw-r--r--include/clang/Basic/BuiltinsX86_64.def7
-rw-r--r--include/clang/Basic/CodeGenOptions.def (renamed from include/clang/Frontend/CodeGenOptions.def)30
-rw-r--r--include/clang/Basic/CodeGenOptions.h (renamed from include/clang/Frontend/CodeGenOptions.h)36
-rw-r--r--include/clang/Basic/Cuda.h8
-rw-r--r--include/clang/Basic/DebugInfoOptions.h6
-rw-r--r--include/clang/Basic/DeclNodes.td1
-rw-r--r--include/clang/Basic/Diagnostic.h9
-rw-r--r--include/clang/Basic/DiagnosticAST.h29
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td39
-rw-r--r--include/clang/Basic/DiagnosticAnalysis.h29
-rw-r--r--include/clang/Basic/DiagnosticComment.h29
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td51
-rw-r--r--include/clang/Basic/DiagnosticCrossTU.h29
-rw-r--r--include/clang/Basic/DiagnosticCrossTUKinds.td9
-rw-r--r--include/clang/Basic/DiagnosticDriver.h29
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td41
-rw-r--r--include/clang/Basic/DiagnosticFrontend.h29
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td70
-rw-r--r--include/clang/Basic/DiagnosticGroups.td28
-rw-r--r--include/clang/Basic/DiagnosticIDs.h2
-rw-r--r--include/clang/Basic/DiagnosticLex.h29
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td23
-rw-r--r--include/clang/Basic/DiagnosticParse.h29
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td65
-rw-r--r--include/clang/Basic/DiagnosticRefactoring.h29
-rw-r--r--include/clang/Basic/DiagnosticSema.h29
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td408
-rw-r--r--include/clang/Basic/DiagnosticSerialization.h29
-rw-r--r--include/clang/Basic/Features.def40
-rw-r--r--include/clang/Basic/FileManager.h44
-rw-r--r--include/clang/Basic/FileSystemStatCache.h46
-rw-r--r--include/clang/Basic/FixedPoint.h138
-rw-r--r--include/clang/Basic/IdentifierTable.h237
-rw-r--r--include/clang/Basic/LangOptions.def17
-rw-r--r--include/clang/Basic/LangOptions.h83
-rw-r--r--include/clang/Basic/MSP430Target.def247
-rw-r--r--include/clang/Basic/ObjCRuntime.h74
-rw-r--r--include/clang/Basic/OpenCLExtensionTypes.def41
-rw-r--r--include/clang/Basic/OpenCLExtensions.def1
-rw-r--r--include/clang/Basic/OpenMPKinds.def37
-rw-r--r--include/clang/Basic/OpenMPKinds.h17
-rw-r--r--include/clang/Basic/PlistSupport.h25
-rw-r--r--include/clang/Basic/Sanitizers.def29
-rw-r--r--include/clang/Basic/Sanitizers.h2
-rw-r--r--include/clang/Basic/SourceLocation.h4
-rw-r--r--include/clang/Basic/SourceManager.h21
-rw-r--r--include/clang/Basic/Specifiers.h1
-rw-r--r--include/clang/Basic/StmtNodes.td6
-rw-r--r--include/clang/Basic/TargetBuiltins.h10
-rw-r--r--include/clang/Basic/TargetInfo.h36
-rw-r--r--include/clang/Basic/TargetOptions.h14
-rw-r--r--include/clang/Basic/TokenKinds.def85
-rw-r--r--include/clang/Basic/TokenKinds.h3
-rw-r--r--include/clang/Basic/TypeTraits.h6
-rw-r--r--include/clang/Basic/VirtualFileSystem.h454
-rw-r--r--include/clang/Basic/X86Target.def9
-rw-r--r--include/clang/Basic/XRayInstr.h2
-rw-r--r--include/clang/Basic/arm_neon.td109
-rw-r--r--include/clang/Basic/arm_neon_incl.td7
-rw-r--r--include/clang/CodeGen/CGFunctionInfo.h6
-rw-r--r--include/clang/CodeGen/SwiftCallingConv.h3
-rw-r--r--include/clang/CrossTU/CrossTUDiagnostic.h18
-rw-r--r--include/clang/CrossTU/CrossTranslationUnit.h30
-rw-r--r--include/clang/Driver/Action.h27
-rw-r--r--include/clang/Driver/CC1Options.td61
-rw-r--r--include/clang/Driver/CLCompatOptions.td83
-rw-r--r--include/clang/Driver/DarwinSDKInfo.h42
-rw-r--r--include/clang/Driver/Distro.h12
-rw-r--r--include/clang/Driver/Driver.h23
-rw-r--r--include/clang/Driver/DriverDiagnostic.h15
-rw-r--r--include/clang/Driver/Job.h15
-rw-r--r--include/clang/Driver/Options.td199
-rw-r--r--include/clang/Driver/SanitizerArgs.h5
-rw-r--r--include/clang/Driver/ToolChain.h42
-rw-r--r--include/clang/Driver/Types.def1
-rw-r--r--include/clang/Format/Format.h71
-rw-r--r--include/clang/Frontend/ASTConsumers.h4
-rw-r--r--include/clang/Frontend/ASTUnit.h48
-rw-r--r--include/clang/Frontend/CompilerInstance.h15
-rw-r--r--include/clang/Frontend/CompilerInvocation.h23
-rw-r--r--include/clang/Frontend/FrontendAction.h20
-rw-r--r--include/clang/Frontend/FrontendActions.h18
-rw-r--r--include/clang/Frontend/FrontendDiagnostic.h15
-rw-r--r--include/clang/Frontend/FrontendOptions.h9
-rw-r--r--include/clang/Frontend/LangStandards.def3
-rw-r--r--include/clang/Frontend/PCHContainerOperations.h106
-rw-r--r--include/clang/Frontend/PrecompiledPreamble.h26
-rw-r--r--include/clang/Frontend/Utils.h19
-rw-r--r--include/clang/Index/IndexDataConsumer.h5
-rw-r--r--include/clang/Index/IndexSymbol.h6
-rw-r--r--include/clang/Index/IndexingAction.h11
-rw-r--r--include/clang/Index/USRGeneration.h27
-rw-r--r--include/clang/Lex/CodeCompletionHandler.h7
-rw-r--r--include/clang/Lex/DirectoryLookup.h2
-rw-r--r--include/clang/Lex/HeaderMap.h3
-rw-r--r--include/clang/Lex/HeaderSearch.h26
-rw-r--r--include/clang/Lex/LexDiagnostic.h15
-rw-r--r--include/clang/Lex/Lexer.h26
-rw-r--r--include/clang/Lex/MacroInfo.h3
-rw-r--r--include/clang/Lex/ModuleMap.h16
-rw-r--r--include/clang/Lex/PPCallbacks.h13
-rw-r--r--include/clang/Lex/PTHLexer.h107
-rw-r--r--include/clang/Lex/PTHManager.h149
-rw-r--r--include/clang/Lex/Pragma.h2
-rw-r--r--include/clang/Lex/PreprocessingRecord.h1
-rw-r--r--include/clang/Lex/Preprocessor.h115
-rw-r--r--include/clang/Lex/PreprocessorLexer.h2
-rw-r--r--include/clang/Lex/PreprocessorOptions.h19
-rw-r--r--include/clang/Lex/TokenConcatenation.h4
-rw-r--r--include/clang/Lex/TokenLexer.h44
-rw-r--r--include/clang/Parse/LoopHint.h (renamed from include/clang/Sema/LoopHint.h)6
-rw-r--r--include/clang/Parse/ParseDiagnostic.h15
-rw-r--r--include/clang/Parse/Parser.h63
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h70
-rw-r--r--include/clang/Sema/CodeCompleteOptions.h3
-rw-r--r--include/clang/Sema/DeclSpec.h89
-rw-r--r--include/clang/Sema/Initialization.h25
-rw-r--r--include/clang/Sema/Lookup.h6
-rw-r--r--include/clang/Sema/Overload.h13
-rw-r--r--include/clang/Sema/ParsedAttr.h228
-rw-r--r--include/clang/Sema/Scope.h1
-rw-r--r--include/clang/Sema/ScopeInfo.h17
-rw-r--r--include/clang/Sema/Sema.h356
-rw-r--r--include/clang/Sema/SemaDiagnostic.h15
-rw-r--r--include/clang/Serialization/ASTBitCodes.h14
-rw-r--r--include/clang/Serialization/ASTReader.h37
-rw-r--r--include/clang/Serialization/ASTWriter.h18
-rw-r--r--include/clang/Serialization/ContinuousRangeMap.h2
-rw-r--r--include/clang/Serialization/GlobalModuleIndex.h17
-rw-r--r--include/clang/Serialization/PCHContainerOperations.h117
-rw-r--r--include/clang/Serialization/SerializationDiagnostic.h15
-rw-r--r--include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h (renamed from lib/StaticAnalyzer/Checkers/ClangSACheckers.h)2
-rw-r--r--include/clang/StaticAnalyzer/Checkers/CheckerBase.td50
-rw-r--r--include/clang/StaticAnalyzer/Checkers/Checkers.td579
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ClangCheckers.h22
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h232
-rw-r--r--include/clang/StaticAnalyzer/Core/Analyses.def1
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.def377
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h607
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h39
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h21
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h16
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerOptInfo.h44
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h11
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h3
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h80
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h50
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h1
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h72
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h50
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h65
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h42
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h108
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def1
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h281
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h31
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h753
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h731
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h29
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h1
-rw-r--r--include/clang/StaticAnalyzer/Core/RetainSummaryManager.h798
-rw-r--r--include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h4
-rw-r--r--include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (renamed from include/clang/StaticAnalyzer/Core/CheckerRegistry.h)31
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h7
-rw-r--r--include/clang/Tooling/AllTUsExecution.h4
-rw-r--r--include/clang/Tooling/CompilationDatabase.h21
-rw-r--r--include/clang/Tooling/CompilationDatabasePluginRegistry.h21
-rw-r--r--include/clang/Tooling/DiagnosticsYaml.h10
-rw-r--r--include/clang/Tooling/Execution.h9
-rw-r--r--include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h2
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringDiagnostic.h17
-rw-r--r--include/clang/Tooling/StandaloneExecution.h5
-rw-r--r--include/clang/Tooling/Tooling.h31
-rw-r--r--include/clang/module.modulemap22
-rw-r--r--lib/ARCMigrate/ARCMT.cpp6
-rw-r--r--lib/ARCMigrate/CMakeLists.txt1
-rw-r--r--lib/ARCMigrate/FileRemapper.cpp2
-rw-r--r--lib/ARCMigrate/ObjCMT.cpp124
-rw-r--r--lib/ARCMigrate/TransAPIUses.cpp2
-rw-r--r--lib/ARCMigrate/TransAutoreleasePool.cpp28
-rw-r--r--lib/ARCMigrate/TransGCAttrs.cpp17
-rw-r--r--lib/ARCMigrate/TransGCCalls.cpp2
-rw-r--r--lib/ARCMigrate/TransProtectedScope.cpp7
-rw-r--r--lib/ARCMigrate/TransRetainReleaseDealloc.cpp22
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp19
-rw-r--r--lib/ARCMigrate/TransformActions.cpp2
-rw-r--r--lib/ARCMigrate/Transforms.cpp6
-rw-r--r--lib/AST/APValue.cpp20
-rw-r--r--lib/AST/ASTContext.cpp629
-rw-r--r--lib/AST/ASTDiagnostic.cpp14
-rw-r--r--lib/AST/ASTDumper.cpp1721
-rw-r--r--lib/AST/ASTImporter.cpp8084
-rw-r--r--lib/AST/ASTImporterLookupTable.cpp129
-rw-r--r--lib/AST/ASTStructuralEquivalence.cpp285
-rw-r--r--lib/AST/CMakeLists.txt6
-rw-r--r--lib/AST/CXXInheritance.cpp2
-rw-r--r--lib/AST/CommentLexer.cpp2
-rw-r--r--lib/AST/CommentParser.cpp1
-rw-r--r--lib/AST/CommentSema.cpp7
-rw-r--r--lib/AST/Decl.cpp230
-rw-r--r--lib/AST/DeclBase.cpp135
-rw-r--r--lib/AST/DeclCXX.cpp122
-rw-r--r--lib/AST/DeclObjC.cpp70
-rw-r--r--lib/AST/DeclOpenMP.cpp42
-rw-r--r--lib/AST/DeclPrinter.cpp19
-rw-r--r--lib/AST/DeclTemplate.cpp46
-rw-r--r--lib/AST/DeclarationName.cpp399
-rw-r--r--lib/AST/Expr.cpp669
-rw-r--r--lib/AST/ExprCXX.cpp1017
-rw-r--r--lib/AST/ExprClassification.cpp3
-rw-r--r--lib/AST/ExprConstant.cpp570
-rw-r--r--lib/AST/ExternalASTMerger.cpp10
-rw-r--r--lib/AST/FormatString.cpp (renamed from lib/Analysis/FormatString.cpp)52
-rw-r--r--lib/AST/FormatStringParsing.h (renamed from lib/Analysis/FormatStringParsing.h)6
-rw-r--r--lib/AST/ItaniumMangle.cpp65
-rw-r--r--lib/AST/Linkage.h11
-rw-r--r--lib/AST/Mangle.cpp6
-rw-r--r--lib/AST/MicrosoftMangle.cpp302
-rw-r--r--lib/AST/NSAPI.cpp17
-rw-r--r--lib/AST/NestedNameSpecifier.cpp37
-rw-r--r--lib/AST/ODRHash.cpp264
-rw-r--r--lib/AST/OSLog.cpp (renamed from lib/Analysis/OSLog.cpp)21
-rw-r--r--lib/AST/OpenMPClause.cpp579
-rw-r--r--lib/AST/ParentMap.cpp2
-rw-r--r--lib/AST/PrintfFormatString.cpp (renamed from lib/Analysis/PrintfFormatString.cpp)70
-rw-r--r--lib/AST/RawCommentList.cpp14
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp13
-rw-r--r--lib/AST/ScanfFormatString.cpp (renamed from lib/Analysis/ScanfFormatString.cpp)4
-rw-r--r--lib/AST/SelectorLocationsKind.cpp4
-rw-r--r--lib/AST/Stmt.cpp357
-rw-r--r--lib/AST/StmtCXX.cpp3
-rw-r--r--lib/AST/StmtObjC.cpp8
-rw-r--r--lib/AST/StmtOpenMP.cpp12
-rw-r--r--lib/AST/StmtPrinter.cpp619
-rw-r--r--lib/AST/StmtProfile.cpp23
-rw-r--r--lib/AST/TextNodeDumper.cpp1168
-rw-r--r--lib/AST/Type.cpp344
-rw-r--r--lib/AST/TypeLoc.cpp13
-rw-r--r--lib/AST/TypePrinter.cpp247
-rw-r--r--lib/AST/VTableBuilder.cpp33
-rw-r--r--lib/ASTMatchers/ASTMatchFinder.cpp27
-rw-r--r--lib/ASTMatchers/ASTMatchersInternal.cpp22
-rw-r--r--lib/ASTMatchers/Dynamic/Parser.cpp106
-rw-r--r--lib/ASTMatchers/Dynamic/Registry.cpp47
-rw-r--r--lib/Analysis/AnalysisDeclContext.cpp19
-rw-r--r--lib/Analysis/BodyFarm.cpp60
-rw-r--r--lib/Analysis/CFG.cpp83
-rw-r--r--lib/Analysis/CMakeLists.txt7
-rw-r--r--lib/Analysis/CallGraph.cpp2
-rw-r--r--lib/Analysis/CloneDetection.cpp19
-rw-r--r--lib/Analysis/Consumed.cpp26
-rw-r--r--lib/Analysis/ExprMutationAnalyzer.cpp445
-rw-r--r--lib/Analysis/LiveVariables.cpp61
-rw-r--r--lib/Analysis/ProgramPoint.cpp175
-rw-r--r--lib/Analysis/PseudoConstantAnalysis.cpp226
-rw-r--r--lib/Analysis/ReachableCode.cpp22
-rw-r--r--lib/Analysis/ThreadSafety.cpp410
-rw-r--r--lib/Analysis/ThreadSafetyCommon.cpp59
-rw-r--r--lib/Analysis/ThreadSafetyTIL.cpp18
-rw-r--r--lib/Basic/Attributes.cpp9
-rw-r--r--lib/Basic/Builtins.cpp2
-rw-r--r--lib/Basic/CMakeLists.txt5
-rw-r--r--lib/Basic/CodeGenOptions.cpp (renamed from lib/Frontend/CodeGenOptions.cpp)4
-rw-r--r--lib/Basic/Cuda.cpp27
-rw-r--r--lib/Basic/Diagnostic.cpp15
-rw-r--r--lib/Basic/FileManager.cpp97
-rw-r--r--lib/Basic/FileSystemStatCache.cpp33
-rw-r--r--lib/Basic/FixedPoint.cpp115
-rw-r--r--lib/Basic/IdentifierTable.cpp110
-rw-r--r--lib/Basic/Module.cpp47
-rw-r--r--lib/Basic/OpenMPKinds.cpp46
-rw-r--r--lib/Basic/SourceLocation.cpp55
-rw-r--r--lib/Basic/SourceManager.cpp80
-rw-r--r--lib/Basic/TargetInfo.cpp7
-rw-r--r--lib/Basic/Targets.cpp26
-rw-r--r--lib/Basic/Targets/AArch64.cpp17
-rw-r--r--lib/Basic/Targets/AArch64.h1
-rw-r--r--lib/Basic/Targets/AMDGPU.cpp84
-rw-r--r--lib/Basic/Targets/AMDGPU.h214
-rw-r--r--lib/Basic/Targets/ARC.cpp25
-rw-r--r--lib/Basic/Targets/ARC.h74
-rw-r--r--lib/Basic/Targets/ARM.cpp17
-rw-r--r--lib/Basic/Targets/Hexagon.cpp18
-rw-r--r--lib/Basic/Targets/Mips.cpp65
-rw-r--r--lib/Basic/Targets/Mips.h29
-rw-r--r--lib/Basic/Targets/NVPTX.cpp5
-rw-r--r--lib/Basic/Targets/Nios2.cpp56
-rw-r--r--lib/Basic/Targets/Nios2.h151
-rw-r--r--lib/Basic/Targets/OSTargets.cpp2
-rw-r--r--lib/Basic/Targets/OSTargets.h49
-rw-r--r--lib/Basic/Targets/PPC.cpp34
-rw-r--r--lib/Basic/Targets/PPC.h5
-rw-r--r--lib/Basic/Targets/Sparc.h2
-rw-r--r--lib/Basic/Targets/WebAssembly.cpp49
-rw-r--r--lib/Basic/Targets/WebAssembly.h15
-rw-r--r--lib/Basic/Targets/X86.cpp30
-rw-r--r--lib/Basic/Targets/X86.h13
-rw-r--r--lib/Basic/VirtualFileSystem.cpp2026
-rw-r--r--lib/CodeGen/BackendUtil.cpp129
-rw-r--r--lib/CodeGen/CGAtomic.cpp28
-rw-r--r--lib/CodeGen/CGBlocks.cpp886
-rw-r--r--lib/CodeGen/CGBlocks.h10
-rw-r--r--lib/CodeGen/CGBuiltin.cpp1787
-rw-r--r--lib/CodeGen/CGCUDANV.cpp33
-rw-r--r--lib/CodeGen/CGCXX.cpp4
-rw-r--r--lib/CodeGen/CGCXXABI.cpp2
-rw-r--r--lib/CodeGen/CGCall.cpp128
-rw-r--r--lib/CodeGen/CGCall.h14
-rw-r--r--lib/CodeGen/CGClass.cpp33
-rw-r--r--lib/CodeGen/CGCleanup.cpp4
-rw-r--r--lib/CodeGen/CGCoroutine.cpp14
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp505
-rw-r--r--lib/CodeGen/CGDebugInfo.h64
-rw-r--r--lib/CodeGen/CGDecl.cpp568
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp103
-rw-r--r--lib/CodeGen/CGException.cpp45
-rw-r--r--lib/CodeGen/CGExpr.cpp159
-rw-r--r--lib/CodeGen/CGExprAgg.cpp9
-rw-r--r--lib/CodeGen/CGExprCXX.cpp36
-rw-r--r--lib/CodeGen/CGExprComplex.cpp8
-rw-r--r--lib/CodeGen/CGExprConstant.cpp46
-rw-r--r--lib/CodeGen/CGExprScalar.cpp455
-rw-r--r--lib/CodeGen/CGLoopInfo.cpp129
-rw-r--r--lib/CodeGen/CGLoopInfo.h33
-rw-r--r--lib/CodeGen/CGNonTrivialStruct.cpp31
-rw-r--r--lib/CodeGen/CGObjC.cpp511
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp335
-rw-r--r--lib/CodeGen/CGObjCMac.cpp84
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp60
-rw-r--r--lib/CodeGen/CGObjCRuntime.h7
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.cpp40
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.h5
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp1079
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.h117
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp2371
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.h99
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp2
-rw-r--r--lib/CodeGen/CGStmt.cpp54
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp443
-rw-r--r--lib/CodeGen/CGVTT.cpp6
-rw-r--r--lib/CodeGen/CGVTables.cpp27
-rw-r--r--lib/CodeGen/CGValue.h5
-rw-r--r--lib/CodeGen/CMakeLists.txt1
-rw-r--r--lib/CodeGen/CodeGenABITypes.cpp1
-rw-r--r--lib/CodeGen/CodeGenAction.cpp17
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp325
-rw-r--r--lib/CodeGen/CodeGenFunction.h179
-rw-r--r--lib/CodeGen/CodeGenModule.cpp648
-rw-r--r--lib/CodeGen/CodeGenModule.h50
-rw-r--r--lib/CodeGen/CodeGenPGO.cpp11
-rw-r--r--lib/CodeGen/CodeGenPGO.h1
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp2
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp3
-rw-r--r--lib/CodeGen/CodeGenTypes.h1
-rw-r--r--lib/CodeGen/ConstantEmitter.h3
-rw-r--r--lib/CodeGen/CoverageMappingGen.cpp107
-rw-r--r--lib/CodeGen/CoverageMappingGen.h1
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp103
-rw-r--r--lib/CodeGen/MacroPPCallbacks.cpp17
-rw-r--r--lib/CodeGen/MacroPPCallbacks.h5
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp22
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp34
-rw-r--r--lib/CodeGen/ObjectFilePCHContainerOperations.cpp5
-rw-r--r--lib/CodeGen/SwiftCallingConv.cpp40
-rw-r--r--lib/CodeGen/TargetInfo.cpp331
-rw-r--r--lib/CodeGen/VarBypassDetector.cpp2
-rw-r--r--lib/CodeGen/VarBypassDetector.h1
-rw-r--r--lib/CrossTU/CrossTranslationUnit.cpp138
-rw-r--r--lib/Driver/Action.cpp16
-rw-r--r--lib/Driver/CMakeLists.txt5
-rw-r--r--lib/Driver/Compilation.cpp2
-rw-r--r--lib/Driver/DarwinSDKInfo.cpp44
-rw-r--r--lib/Driver/Distro.cpp9
-rw-r--r--lib/Driver/Driver.cpp478
-rw-r--r--lib/Driver/Job.cpp19
-rw-r--r--lib/Driver/SanitizerArgs.cpp51
-rw-r--r--lib/Driver/ToolChain.cpp49
-rw-r--r--lib/Driver/ToolChains/AMDGPU.cpp13
-rw-r--r--lib/Driver/ToolChains/AMDGPU.h4
-rw-r--r--lib/Driver/ToolChains/Arch/AArch64.cpp185
-rw-r--r--lib/Driver/ToolChains/Arch/AArch64.h5
-rw-r--r--lib/Driver/ToolChains/Arch/ARM.cpp58
-rw-r--r--lib/Driver/ToolChains/Arch/ARM.h2
-rw-r--r--lib/Driver/ToolChains/Arch/Mips.cpp12
-rw-r--r--lib/Driver/ToolChains/Arch/PPC.cpp10
-rw-r--r--lib/Driver/ToolChains/Arch/PPC.h2
-rw-r--r--lib/Driver/ToolChains/Arch/X86.cpp34
-rw-r--r--lib/Driver/ToolChains/BareMetal.cpp9
-rw-r--r--lib/Driver/ToolChains/Clang.cpp889
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp200
-rw-r--r--lib/Driver/ToolChains/CommonArgs.h6
-rw-r--r--lib/Driver/ToolChains/CrossWindows.cpp1
-rw-r--r--lib/Driver/ToolChains/Cuda.cpp122
-rw-r--r--lib/Driver/ToolChains/Cuda.h2
-rw-r--r--lib/Driver/ToolChains/Darwin.cpp322
-rw-r--r--lib/Driver/ToolChains/Darwin.h21
-rw-r--r--lib/Driver/ToolChains/FreeBSD.cpp2
-rw-r--r--lib/Driver/ToolChains/Fuchsia.cpp22
-rw-r--r--lib/Driver/ToolChains/Gnu.cpp199
-rw-r--r--lib/Driver/ToolChains/HIP.cpp59
-rw-r--r--lib/Driver/ToolChains/HIP.h5
-rw-r--r--lib/Driver/ToolChains/Hexagon.cpp17
-rw-r--r--lib/Driver/ToolChains/Hexagon.h3
-rw-r--r--lib/Driver/ToolChains/Hurd.cpp169
-rw-r--r--lib/Driver/ToolChains/Hurd.h46
-rw-r--r--lib/Driver/ToolChains/Linux.cpp147
-rw-r--r--lib/Driver/ToolChains/Linux.h2
-rw-r--r--lib/Driver/ToolChains/MSP430.cpp233
-rw-r--r--lib/Driver/ToolChains/MSP430.h71
-rw-r--r--lib/Driver/ToolChains/MSVC.cpp35
-rw-r--r--lib/Driver/ToolChains/MSVC.h13
-rw-r--r--lib/Driver/ToolChains/MinGW.cpp66
-rw-r--r--lib/Driver/ToolChains/MinGW.h6
-rw-r--r--lib/Driver/ToolChains/Minix.cpp4
-rw-r--r--lib/Driver/ToolChains/MipsLinux.h2
-rw-r--r--lib/Driver/ToolChains/NetBSD.cpp14
-rw-r--r--lib/Driver/ToolChains/NetBSD.h4
-rw-r--r--lib/Driver/ToolChains/OpenBSD.cpp66
-rw-r--r--lib/Driver/ToolChains/OpenBSD.h8
-rw-r--r--lib/Driver/ToolChains/PS4CPU.cpp6
-rw-r--r--lib/Driver/ToolChains/RISCVToolchain.cpp (renamed from lib/Driver/ToolChains/RISCV.cpp)38
-rw-r--r--lib/Driver/ToolChains/RISCVToolchain.h (renamed from lib/Driver/ToolChains/RISCV.h)14
-rw-r--r--lib/Driver/ToolChains/Solaris.h2
-rw-r--r--lib/Driver/ToolChains/WebAssembly.cpp55
-rw-r--r--lib/Driver/ToolChains/WebAssembly.h17
-rw-r--r--lib/Driver/Types.cpp2
-rw-r--r--lib/Driver/XRayArgs.cpp33
-rw-r--r--lib/Edit/RewriteObjCFoundationAPI.cpp20
-rw-r--r--lib/Format/BreakableToken.cpp38
-rw-r--r--lib/Format/ContinuationIndenter.cpp54
-rw-r--r--lib/Format/Format.cpp216
-rw-r--r--lib/Format/FormatToken.h29
-rw-r--r--lib/Format/FormatTokenLexer.cpp11
-rw-r--r--lib/Format/FormatTokenLexer.h4
-rw-r--r--lib/Format/NamespaceEndCommentsFixer.cpp7
-rw-r--r--lib/Format/TokenAnnotator.cpp70
-rw-r--r--lib/Format/TokenAnnotator.h7
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp23
-rw-r--r--lib/Format/UnwrappedLineParser.cpp53
-rw-r--r--lib/Format/UnwrappedLineParser.h1
-rw-r--r--lib/Format/WhitespaceManager.cpp10
-rw-r--r--lib/Frontend/ASTConsumers.cpp362
-rw-r--r--lib/Frontend/ASTMerge.cpp11
-rw-r--r--lib/Frontend/ASTUnit.cpp52
-rw-r--r--lib/Frontend/CMakeLists.txt3
-rw-r--r--lib/Frontend/CacheTokens.cpp700
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp1
-rw-r--r--lib/Frontend/CompilerInstance.cpp69
-rw-r--r--lib/Frontend/CompilerInvocation.cpp409
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp2
-rw-r--r--lib/Frontend/DependencyFile.cpp38
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp4
-rw-r--r--lib/Frontend/FrontendAction.cpp67
-rw-r--r--lib/Frontend/FrontendActions.cpp103
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp27
-rw-r--r--lib/Frontend/InitPreprocessor.cpp41
-rw-r--r--lib/Frontend/ModuleDependencyCollector.cpp4
-rw-r--r--lib/Frontend/PrecompiledPreamble.cpp52
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp5
-rw-r--r--lib/Frontend/Rewrite/FrontendActions.cpp7
-rw-r--r--lib/Frontend/Rewrite/InclusionRewriter.cpp1
-rw-r--r--lib/Frontend/Rewrite/RewriteModernObjC.cpp339
-rw-r--r--lib/Frontend/Rewrite/RewriteObjC.cpp262
-rw-r--r--lib/FrontendTool/ExecuteCompilerInvocation.cpp25
-rw-r--r--lib/Headers/CMakeLists.txt6
-rw-r--r--lib/Headers/__clang_cuda_runtime_wrapper.h8
-rw-r--r--lib/Headers/adxintrin.h4
-rw-r--r--lib/Headers/altivec.h123
-rw-r--r--lib/Headers/avx512bwintrin.h839
-rw-r--r--lib/Headers/avx512dqintrin.h302
-rw-r--r--lib/Headers/avx512fintrin.h177
-rw-r--r--lib/Headers/avx512pfintrin.h32
-rw-r--r--lib/Headers/avx512vbmi2intrin.h158
-rw-r--r--lib/Headers/avx512vbmiintrin.h26
-rw-r--r--lib/Headers/avx512vbmivlintrin.h56
-rw-r--r--lib/Headers/avx512vlbwintrin.h75
-rw-r--r--lib/Headers/avx512vlintrin.h349
-rw-r--r--lib/Headers/avx512vlvbmi2intrin.h312
-rw-r--r--lib/Headers/bmiintrin.h10
-rw-r--r--lib/Headers/cuda_wrappers/new6
-rw-r--r--lib/Headers/emmintrin.h107
-rw-r--r--lib/Headers/float.h12
-rw-r--r--lib/Headers/immintrin.h59
-rw-r--r--lib/Headers/intrin.h546
-rw-r--r--lib/Headers/lzcntintrin.h22
-rw-r--r--lib/Headers/opencl-c.h659
-rw-r--r--lib/Headers/unwind.h4
-rw-r--r--lib/Headers/vecintrin.h6
-rw-r--r--lib/Index/CommentToXML.cpp1
-rw-r--r--lib/Index/IndexBody.cpp41
-rw-r--r--lib/Index/IndexDecl.cpp2
-rw-r--r--lib/Index/IndexSymbol.cpp5
-rw-r--r--lib/Index/IndexTypeSourceInfo.cpp14
-rw-r--r--lib/Index/IndexingAction.cpp24
-rw-r--r--lib/Index/IndexingContext.cpp26
-rw-r--r--lib/Index/SimpleFormatContext.h10
-rw-r--r--lib/Index/USRGeneration.cpp54
-rw-r--r--lib/Lex/CMakeLists.txt1
-rw-r--r--lib/Lex/HeaderMap.cpp5
-rw-r--r--lib/Lex/HeaderSearch.cpp49
-rw-r--r--lib/Lex/Lexer.cpp78
-rw-r--r--lib/Lex/LiteralSupport.cpp2
-rw-r--r--lib/Lex/MacroInfo.cpp3
-rw-r--r--lib/Lex/ModuleMap.cpp66
-rw-r--r--lib/Lex/PPDirectives.cpp201
-rw-r--r--lib/Lex/PPLexerChange.cpp109
-rw-r--r--lib/Lex/PPMacroExpansion.cpp13
-rw-r--r--lib/Lex/PTHLexer.cpp748
-rw-r--r--lib/Lex/Pragma.cpp57
-rw-r--r--lib/Lex/Preprocessor.cpp68
-rw-r--r--lib/Lex/TokenConcatenation.cpp4
-rw-r--r--lib/Parse/ParseAST.cpp34
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp10
-rw-r--r--lib/Parse/ParseDecl.cpp124
-rw-r--r--lib/Parse/ParseDeclCXX.cpp200
-rw-r--r--lib/Parse/ParseExpr.cpp86
-rw-r--r--lib/Parse/ParseExprCXX.cpp111
-rw-r--r--lib/Parse/ParseInit.cpp6
-rw-r--r--lib/Parse/ParseObjc.cpp41
-rw-r--r--lib/Parse/ParseOpenMP.cpp390
-rw-r--r--lib/Parse/ParsePragma.cpp273
-rw-r--r--lib/Parse/ParseStmt.cpp151
-rw-r--r--lib/Parse/ParseTemplate.cpp77
-rw-r--r--lib/Parse/ParseTentative.cpp105
-rw-r--r--lib/Parse/Parser.cpp23
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp2
-rw-r--r--lib/Rewrite/RewriteRope.cpp4
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp135
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp222
-rw-r--r--lib/Sema/DeclSpec.cpp63
-rw-r--r--lib/Sema/IdentifierResolver.cpp14
-rw-r--r--lib/Sema/JumpDiagnostics.cpp16
-rw-r--r--lib/Sema/ParsedAttr.cpp49
-rw-r--r--lib/Sema/ScopeInfo.cpp2
-rw-r--r--lib/Sema/Sema.cpp135
-rw-r--r--lib/Sema/SemaAccess.cpp47
-rw-r--r--lib/Sema/SemaAttr.cpp112
-rw-r--r--lib/Sema/SemaCUDA.cpp2
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp24
-rw-r--r--lib/Sema/SemaCast.cpp105
-rw-r--r--lib/Sema/SemaChecking.cpp2758
-rw-r--r--lib/Sema/SemaCodeComplete.cpp3022
-rw-r--r--lib/Sema/SemaCoroutine.cpp43
-rw-r--r--lib/Sema/SemaDecl.cpp959
-rw-r--r--lib/Sema/SemaDeclAttr.cpp1214
-rw-r--r--lib/Sema/SemaDeclCXX.cpp814
-rw-r--r--lib/Sema/SemaDeclObjC.cpp52
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp54
-rw-r--r--lib/Sema/SemaExpr.cpp1157
-rw-r--r--lib/Sema/SemaExprCXX.cpp389
-rw-r--r--lib/Sema/SemaExprMember.cpp30
-rw-r--r--lib/Sema/SemaExprObjC.cpp240
-rw-r--r--lib/Sema/SemaInit.cpp710
-rw-r--r--lib/Sema/SemaLambda.cpp157
-rw-r--r--lib/Sema/SemaLookup.cpp161
-rw-r--r--lib/Sema/SemaObjCProperty.cpp42
-rw-r--r--lib/Sema/SemaOpenMP.cpp1749
-rw-r--r--lib/Sema/SemaOverload.cpp628
-rw-r--r--lib/Sema/SemaPseudoObject.cpp2
-rw-r--r--lib/Sema/SemaStmt.cpp429
-rw-r--r--lib/Sema/SemaStmtAsm.cpp160
-rw-r--r--lib/Sema/SemaStmtAttr.cpp99
-rw-r--r--lib/Sema/SemaTemplate.cpp396
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp19
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp53
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp352
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp9
-rw-r--r--lib/Sema/SemaType.cpp1013
-rw-r--r--lib/Sema/TreeTransform.h703
-rw-r--r--lib/Serialization/ASTCommon.cpp6
-rw-r--r--lib/Serialization/ASTReader.cpp1024
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp300
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp1294
-rw-r--r--lib/Serialization/ASTWriter.cpp555
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp110
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp675
-rw-r--r--lib/Serialization/CMakeLists.txt1
-rw-r--r--lib/Serialization/GlobalModuleIndex.cpp2
-rw-r--r--lib/Serialization/ModuleManager.cpp19
-rw-r--r--lib/Serialization/PCHContainerOperations.cpp (renamed from lib/Frontend/PCHContainerOperations.cpp)4
-rw-r--r--lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp24
-rw-r--r--lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h31
-rw-r--r--lib/StaticAnalyzer/Checkers/AllocationState.h5
-rw-r--r--lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp27
-rw-r--r--lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp102
-rw-r--r--lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/CMakeLists.txt14
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringChecker.cpp150
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp46
-rw-r--r--lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp103
-rw-r--r--lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp22
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp31
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/ChrootChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ClangCheckers.cpp32
-rw-r--r--lib/StaticAnalyzer/Checkers/CloneChecker.cpp16
-rw-r--r--lib/StaticAnalyzer/Checkers/ConversionChecker.cpp57
-rw-r--r--lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/DebugCheckers.cpp25
-rw-r--r--lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp5
-rw-r--r--lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp15
-rw-r--r--lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp128
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp115
-rw-r--r--lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/GTestChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp216
-rw-r--r--lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp158
-rw-r--r--lib/StaticAnalyzer/Checkers/InterCheckerAPI.h3
-rw-r--r--lib/StaticAnalyzer/Checkers/IteratorChecker.cpp1414
-rw-r--r--lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp5
-rw-r--r--lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp5
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h1
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp5
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp53
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp161
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp525
-rw-r--r--lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/MoveChecker.cpp740
-rw-r--r--lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp42
-rw-r--r--lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp19
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/PaddingChecker.cpp45
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp4156
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp1547
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h393
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp794
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h85
-rw-r--r--lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp36
-rw-r--r--lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/StreamChecker.cpp36
-rw-r--r--lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/TraversalChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp195
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h349
-rw-r--r--lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp538
-rw-r--r--lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp282
-rw-r--r--lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp688
-rw-r--r--lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/ValistChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/VforkChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Core/AnalysisManager.cpp49
-rw-r--r--lib/StaticAnalyzer/Core/AnalyzerOptions.cpp483
-rw-r--r--lib/StaticAnalyzer/Core/BasicValueFactory.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp141
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp750
-rw-r--r--lib/StaticAnalyzer/Core/CMakeLists.txt9
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp162
-rw-r--r--lib/StaticAnalyzer/Core/Checker.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/CheckerHelpers.cpp8
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp9
-rw-r--r--lib/StaticAnalyzer/Core/CheckerRegistry.cpp190
-rw-r--r--lib/StaticAnalyzer/Core/CommonBugCategories.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp32
-rw-r--r--lib/StaticAnalyzer/Core/DynamicTypeMap.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/Environment.cpp22
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp30
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp545
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp18
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp125
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp93
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp18
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp63
-rw-r--r--lib/StaticAnalyzer/Core/LoopWidening.cpp11
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp81
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp44
-rw-r--r--lib/StaticAnalyzer/Core/PlistDiagnostics.cpp892
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp99
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/RangedConstraintManager.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp175
-rw-r--r--lib/StaticAnalyzer/Core/RetainSummaryManager.cpp1229
-rw-r--r--lib/StaticAnalyzer/Core/SMTConstraintManager.cpp181
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp15
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp6
-rw-r--r--lib/StaticAnalyzer/Core/SarifDiagnostics.cpp349
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp26
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp45
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp17
-rw-r--r--lib/StaticAnalyzer/Core/TaintManager.cpp23
-rw-r--r--lib/StaticAnalyzer/Core/WorkList.cpp62
-rw-r--r--lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp304
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp156
-rw-r--r--lib/StaticAnalyzer/Frontend/CMakeLists.txt1
-rw-r--r--lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp196
-rw-r--r--lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp247
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelInjector.cpp2
-rw-r--r--lib/StaticAnalyzer/README.txt12
-rw-r--r--lib/Tooling/ASTDiff/ASTDiff.cpp7
-rw-r--r--lib/Tooling/AllTUsExecution.cpp32
-rw-r--r--lib/Tooling/CMakeLists.txt1
-rw-r--r--lib/Tooling/CompilationDatabase.cpp39
-rw-r--r--lib/Tooling/Core/Diagnostic.cpp9
-rw-r--r--lib/Tooling/Core/Lookup.cpp44
-rw-r--r--lib/Tooling/Core/Replacement.cpp17
-rw-r--r--lib/Tooling/Execution.cpp2
-rw-r--r--lib/Tooling/Inclusions/HeaderIncludes.cpp12
-rw-r--r--lib/Tooling/InterpolatingCompilationDatabase.cpp277
-rw-r--r--lib/Tooling/JSONCompilationDatabase.cpp5
-rw-r--r--lib/Tooling/Refactoring/ASTSelection.cpp2
-rw-r--r--lib/Tooling/Refactoring/Extract/Extract.cpp6
-rw-r--r--lib/Tooling/Refactoring/Rename/USRFinder.cpp4
-rw-r--r--lib/Tooling/Refactoring/Rename/USRLocFinder.cpp8
-rw-r--r--lib/Tooling/StandaloneExecution.cpp2
-rw-r--r--lib/Tooling/Tooling.cpp123
-rw-r--r--runtime/CMakeLists.txt4
-rw-r--r--test/ARCMT/objcmt-arc-cf-annotations.m.result4
-rw-r--r--test/AST/Inputs/module.modulemap (renamed from test/Misc/Inputs/module.modulemap)0
-rw-r--r--test/AST/Inputs/std-coroutine.h37
-rw-r--r--test/AST/ast-dump-arm-attr.c (renamed from test/Misc/ast-dump-arm-attr.c)0
-rw-r--r--test/AST/ast-dump-array.cpp19
-rw-r--r--test/AST/ast-dump-attr.cpp (renamed from test/Misc/ast-dump-attr.cpp)24
-rw-r--r--test/AST/ast-dump-attr.m (renamed from test/Misc/ast-dump-attr.m)0
-rw-r--r--test/AST/ast-dump-c-attr.c (renamed from test/Misc/ast-dump-c-attr.c)93
-rw-r--r--test/AST/ast-dump-color.cpp (renamed from test/Misc/ast-dump-color.cpp)9
-rw-r--r--test/AST/ast-dump-comment.cpp (renamed from test/Misc/ast-dump-comment.cpp)0
-rw-r--r--test/AST/ast-dump-decl-stmts.cpp30
-rw-r--r--test/AST/ast-dump-decl.c (renamed from test/Misc/ast-dump-decl.c)6
-rw-r--r--test/AST/ast-dump-decl.cpp (renamed from test/Misc/ast-dump-decl.cpp)30
-rw-r--r--test/AST/ast-dump-decl.m (renamed from test/Misc/ast-dump-decl.m)8
-rw-r--r--test/AST/ast-dump-decl.mm (renamed from test/Misc/ast-dump-decl.mm)0
-rw-r--r--test/AST/ast-dump-expr.c339
-rw-r--r--test/AST/ast-dump-expr.cpp553
-rw-r--r--test/AST/ast-dump-funcs.cpp124
-rw-r--r--test/AST/ast-dump-invalid.cpp (renamed from test/Misc/ast-dump-invalid.cpp)126
-rw-r--r--test/AST/ast-dump-lookups.cpp (renamed from test/Misc/ast-dump-lookups.cpp)0
-rw-r--r--test/AST/ast-dump-msp430-attr.c (renamed from test/Misc/ast-dump-msp430-attr.c)0
-rw-r--r--test/AST/ast-dump-pipe.cl (renamed from test/Misc/ast-dump-pipe.cl)0
-rw-r--r--test/AST/ast-dump-record-definition-data.cpp190
-rw-r--r--test/AST/ast-dump-records.c150
-rw-r--r--test/AST/ast-dump-records.cpp276
-rw-r--r--test/AST/ast-dump-special-member-functions.cpp446
-rw-r--r--test/AST/ast-dump-stmt.c375
-rw-r--r--test/AST/ast-dump-stmt.cpp272
-rw-r--r--test/AST/ast-dump-stmt.m (renamed from test/Misc/ast-dump-stmt.m)0
-rw-r--r--test/AST/ast-dump-template-decls.cpp102
-rw-r--r--test/AST/ast-dump-templates.cpp (renamed from test/Misc/ast-dump-templates.cpp)0
-rw-r--r--test/AST/ast-dump-wchar.cpp (renamed from test/Misc/ast-dump-wchar.cpp)0
-rw-r--r--test/AST/ast-print-attr.c12
-rw-r--r--test/AST/ast-print-bool.c (renamed from test/Misc/ast-print-bool.c)0
-rw-r--r--test/AST/ast-print-char-literal.cpp (renamed from test/Misc/ast-print-char-literal.cpp)0
-rw-r--r--test/AST/ast-print-enum-decl.c (renamed from test/Misc/ast-print-enum-decl.c)0
-rw-r--r--test/AST/ast-print-objectivec.m (renamed from test/Misc/ast-print-objectivec.m)0
-rw-r--r--test/AST/ast-print-out-of-line-func.cpp (renamed from test/Misc/ast-print-out-of-line-func.cpp)0
-rw-r--r--test/AST/ast-print-pragmas-xfail.cpp (renamed from test/Misc/ast-print-pragmas-xfail.cpp)0
-rw-r--r--test/AST/ast-print-pragmas.cpp (renamed from test/Misc/ast-print-pragmas.cpp)17
-rw-r--r--test/AST/ast-print-record-decl.c (renamed from test/Misc/ast-print-record-decl.c)0
-rw-r--r--test/AST/attr-print-emit.cpp (renamed from test/Misc/attr-print-emit.cpp)0
-rw-r--r--test/AST/attr-target-ast.c (renamed from test/Sema/attr-target-ast.c)0
-rw-r--r--test/AST/auto-pragma.cpp (renamed from test/SemaCXX/auto-pragma.cpp)0
-rw-r--r--test/AST/bool-type.m (renamed from test/SemaObjC/bool-type.m)0
-rw-r--r--test/AST/builtins-arm-strex-rettype.c (renamed from test/Sema/builtins-arm-strex-rettype.c)0
-rw-r--r--test/AST/c-casts.c25
-rw-r--r--test/AST/category-attribute.m (renamed from test/SemaObjC/category-attribute.m)0
-rw-r--r--test/AST/coroutine-source-location-crash.cpp (renamed from test/SemaCXX/coroutine-source-location-crash.cpp)0
-rw-r--r--test/AST/dump.cpp (renamed from test/OpenMP/dump.cpp)35
-rw-r--r--test/AST/finally-msvc.m (renamed from test/SemaObjC/finally-msvc.m)0
-rw-r--r--test/AST/fixed_point.c (renamed from test/Frontend/fixed_point.c)0
-rw-r--r--test/AST/fixed_point_to_string.c21
-rw-r--r--test/AST/float16.cpp (renamed from test/Frontend/float16.cpp)652
-rw-r--r--test/AST/foreachtemplatized.mm (renamed from test/SemaObjC/foreachtemplatized.mm)0
-rw-r--r--test/AST/implicit-cast-dump.c (renamed from test/Sema/implicit-cast-dump.c)0
-rw-r--r--test/AST/multistep-explicit-cast.c (renamed from test/Sema/multistep-explicit-cast.c)0
-rw-r--r--test/AST/multistep-explicit-cast.cpp (renamed from test/SemaCXX/multistep-explicit-cast.cpp)0
-rw-r--r--test/AST/objc-default-ctor-init.mm (renamed from test/Parser/objc-default-ctor-init.mm)0
-rw-r--r--test/AST/pragma-attribute-cxx-subject-match-rules.cpp (renamed from test/Misc/pragma-attribute-cxx-subject-match-rules.cpp)0
-rw-r--r--test/AST/pragma-attribute-objc-subject-match-rules.m (renamed from test/Misc/pragma-attribute-objc-subject-match-rules.m)0
-rw-r--r--test/AST/property-atomic-bool.m (renamed from test/SemaObjC/property-atomic-bool.m)0
-rw-r--r--test/AST/rdr6094103-unordered-compare-promote.c (renamed from test/Sema/rdr6094103-unordered-compare-promote.c)0
-rw-r--r--test/AST/sourceranges.cpp (renamed from test/SemaCXX/sourceranges.cpp)7
-rw-r--r--test/AST/template-implicit-vars.cpp (renamed from test/SemaCXX/template-implicit-vars.cpp)0
-rw-r--r--test/AST/variadic-promotion.c (renamed from test/Sema/variadic-promotion.c)0
-rw-r--r--test/ASTMerge/unnamed_fields/Inputs/il.cpp3
-rw-r--r--test/ASTMerge/unnamed_fields/test.cpp3
-rw-r--r--test/Analysis/CFContainers.mm39
-rw-r--r--test/Analysis/CFDateGC.m85
-rw-r--r--test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m49
-rw-r--r--test/Analysis/Inputs/ctu-other.c49
-rw-r--r--test/Analysis/Inputs/ctu-other.c.externalDefMap.txt6
-rw-r--r--test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt (renamed from test/Analysis/Inputs/externalFnMap.txt)0
-rw-r--r--test/Analysis/Inputs/expected-plists/NewDelete-path-notes.cpp.plist464
-rw-r--r--test/Analysis/Inputs/expected-plists/conditional-path-notes.c.plist1772
-rw-r--r--test/Analysis/Inputs/expected-plists/cstring-plist.c.plist8
-rw-r--r--test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist1960
-rw-r--r--test/Analysis/Inputs/expected-plists/edges-new.mm.plist21452
-rw-r--r--test/Analysis/Inputs/expected-plists/generics.m.plist7196
-rw-r--r--test/Analysis/Inputs/expected-plists/inline-plist.c.plist1986
-rw-r--r--test/Analysis/Inputs/expected-plists/inline-unique-reports.c.plist278
-rw-r--r--test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist205
-rw-r--r--test/Analysis/Inputs/expected-plists/malloc-plist.c.plist5262
-rw-r--r--test/Analysis/Inputs/expected-plists/method-call-path-notes.cpp.plist845
-rw-r--r--test/Analysis/Inputs/expected-plists/model-file.cpp.plist309
-rw-r--r--test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist1028
-rw-r--r--test/Analysis/Inputs/expected-plists/nullability-notes.m.plist205
-rw-r--r--test/Analysis/Inputs/expected-plists/objc-arc.m.plist2089
-rw-r--r--test/Analysis/Inputs/expected-plists/objc-radar17039661.m.plist1309
-rw-r--r--test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist5452
-rw-r--r--test/Analysis/Inputs/expected-plists/plist-macros.cpp.plist1761
-rw-r--r--test/Analysis/Inputs/expected-plists/plist-output-alternate.m.plist1520
-rw-r--r--test/Analysis/Inputs/expected-plists/plist-output.m.plist6220
-rw-r--r--test/Analysis/Inputs/expected-plists/plist-stats-output.c.plist9
-rw-r--r--test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist5022
-rw-r--r--test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist26113
-rw-r--r--test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist26182
-rw-r--r--test/Analysis/Inputs/expected-plists/unix-fns.c.plist3021
-rw-r--r--test/Analysis/Inputs/expected-plists/yaccignore.c.plist4
-rw-r--r--test/Analysis/Inputs/system-header-simulator-cxx.h191
-rw-r--r--test/Analysis/Inputs/system-header-simulator-for-nullability.h51
-rw-r--r--test/Analysis/MismatchedDeallocator-path-notes.cpp292
-rw-r--r--test/Analysis/MissingDealloc.m15
-rw-r--r--test/Analysis/MisusedMovedObject.cpp680
-rw-r--r--test/Analysis/NewDelete-custom.cpp31
-rw-r--r--test/Analysis/NewDelete-path-notes.cpp432
-rw-r--r--test/Analysis/NewDelete-sized-deallocation.cpp39
-rw-r--r--test/Analysis/PR24184.cpp2
-rw-r--r--test/Analysis/PR2599.m63
-rw-r--r--test/Analysis/PR37855.c4
-rw-r--r--test/Analysis/additive-folding-range-constraints.c2
-rw-r--r--test/Analysis/additive-folding.cpp2
-rw-r--r--test/Analysis/analyzer-config.c37
-rw-r--r--test/Analysis/analyzer-config.cpp53
-rw-r--r--test/Analysis/analyzer-list-configs.c34
-rw-r--r--test/Analysis/analyzer_test.py7
-rw-r--r--test/Analysis/array-struct-region.c2
-rw-r--r--test/Analysis/asm.cpp12
-rw-r--r--test/Analysis/atomics.c2
-rw-r--r--test/Analysis/blocks-no-inline.c4
-rw-r--r--test/Analysis/bstring.c8
-rw-r--r--test/Analysis/bstring.cpp10
-rw-r--r--test/Analysis/builtin-functions.cpp6
-rw-r--r--test/Analysis/call-invalidation.cpp2
-rw-r--r--test/Analysis/casts.c67
-rw-r--r--test/Analysis/casts.cpp75
-rw-r--r--test/Analysis/cfg-rich-constructors.cpp80
-rw-r--r--test/Analysis/cfg.cpp22
-rw-r--r--test/Analysis/conditional-operator.cpp4
-rw-r--r--test/Analysis/conditional-path-notes.c1683
-rw-r--r--test/Analysis/const-method-call.cpp2
-rw-r--r--test/Analysis/constant-folding.c2
-rw-r--r--test/Analysis/conversion.c45
-rw-r--r--test/Analysis/copy-elision.cpp95
-rw-r--r--test/Analysis/copypaste/Inputs/expected-plists/MismatchedDeallocator-path-notes.cpp.plist303
-rw-r--r--test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics-notes-as-events.cpp.plist98
-rw-r--r--test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics.cpp.plist99
-rw-r--r--test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp80
-rw-r--r--test/Analysis/copypaste/plist-diagnostics.cpp81
-rw-r--r--test/Analysis/cstring-plist.c8
-rw-r--r--test/Analysis/cstring-syntax.c25
-rw-r--r--test/Analysis/ctor.mm8
-rw-r--r--test/Analysis/ctu-different-triples.cpp20
-rw-r--r--test/Analysis/ctu-main.c67
-rw-r--r--test/Analysis/ctu-main.cpp25
-rw-r--r--test/Analysis/ctu-unknown-parts-in-triples.cpp22
-rw-r--r--test/Analysis/cxx-for-range.cpp1596
-rw-r--r--test/Analysis/cxx-uninitialized-object-inheritance.cpp92
-rw-r--r--test/Analysis/cxx-uninitialized-object-no-dereference.cpp27
-rw-r--r--test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp5
-rw-r--r--test/Analysis/cxx-uninitialized-object-ptr-ref.cpp233
-rw-r--r--test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp136
-rw-r--r--test/Analysis/cxx-uninitialized-object.cpp53
-rw-r--r--test/Analysis/debug-CallGraph.cpp (renamed from test/Analysis/debug-CallGraph.c)22
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-plists/deref-track-symbolic-region.c.plist657
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-plists/plist-diagnostics-include-check.cpp.plist147
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist212
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-plists/report-issues-within-main-file.cpp.plist1835
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-plists/undef-value-caller.c.plist142
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.c.plist1344
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.m.plist1027
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif114
-rw-r--r--test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif320
-rw-r--r--test/Analysis/diagnostics/deref-track-symbolic-region.c622
-rw-r--r--test/Analysis/diagnostics/dtors.cpp25
-rw-r--r--test/Analysis/diagnostics/explicit-suppression.cpp2
-rw-r--r--test/Analysis/diagnostics/find_last_store.c17
-rw-r--r--test/Analysis/diagnostics/no-store-func-path-notes.c20
-rw-r--r--test/Analysis/diagnostics/no-store-func-path-notes.cpp205
-rw-r--r--test/Analysis/diagnostics/no-store-func-path-notes.m32
-rw-r--r--test/Analysis/diagnostics/plist-diagnostics-include-check.cpp132
-rw-r--r--test/Analysis/diagnostics/plist-multi-file.c199
-rw-r--r--test/Analysis/diagnostics/report-issues-within-main-file.cpp1709
-rw-r--r--test/Analysis/diagnostics/sarif-diagnostics-taint-test.c15
-rw-r--r--test/Analysis/diagnostics/sarif-multi-diagnostic-test.c29
-rw-r--r--test/Analysis/diagnostics/track_subexpressions.cpp19
-rw-r--r--test/Analysis/diagnostics/undef-value-caller.c117
-rw-r--r--test/Analysis/diagnostics/undef-value-param.c1289
-rw-r--r--test/Analysis/diagnostics/undef-value-param.m984
-rw-r--r--test/Analysis/disable-all-checks.c15
-rw-r--r--test/Analysis/dtor.cpp2
-rw-r--r--test/Analysis/dump_egraph.c16
-rw-r--r--test/Analysis/dump_egraph.cpp22
-rw-r--r--test/Analysis/edges-new.mm20758
-rw-r--r--test/Analysis/end-function-return-stmt.cpp34
-rw-r--r--test/Analysis/enum-cast-out-of-range.cpp192
-rw-r--r--test/Analysis/expr-inspection.cpp30
-rw-r--r--test/Analysis/func-mapping-test.cpp2
-rw-r--r--test/Analysis/func.c2
-rw-r--r--test/Analysis/generics.m6704
-rw-r--r--test/Analysis/global-region-invalidation.c2
-rw-r--r--test/Analysis/global_region_invalidation.mm2
-rw-r--r--test/Analysis/gtest.cpp4
-rw-r--r--test/Analysis/html_diagnostics/relevant_lines/synthesized_body.cpp25
-rw-r--r--test/Analysis/inline-plist.c1902
-rw-r--r--test/Analysis/inline-unique-reports.c257
-rw-r--r--test/Analysis/inline.cpp2
-rw-r--r--test/Analysis/inlining/InlineObjCClassMethod.m2
-rw-r--r--test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.c.plist653
-rw-r--r--test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.cpp.plist377
-rw-r--r--test/Analysis/inlining/Inputs/expected-plists/path-notes.c.plist3780
-rw-r--r--test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist5227
-rw-r--r--test/Analysis/inlining/Inputs/expected-plists/path-notes.m.plist2001
-rw-r--r--test/Analysis/inlining/containers.cpp8
-rw-r--r--test/Analysis/inlining/dyn-dispatch-bifurcate.cpp2
-rw-r--r--test/Analysis/inlining/eager-reclamation-path-notes.c615
-rw-r--r--test/Analysis/inlining/eager-reclamation-path-notes.cpp354
-rw-r--r--test/Analysis/inlining/false-positive-suppression.c6
-rw-r--r--test/Analysis/inlining/path-notes.c3628
-rw-r--r--test/Analysis/inlining/path-notes.cpp4991
-rw-r--r--test/Analysis/inlining/path-notes.m1920
-rw-r--r--test/Analysis/inlining/stl.cpp4
-rw-r--r--test/Analysis/inner-pointer.cpp316
-rw-r--r--test/Analysis/invalid-a-na-ly-zer-con-fig-value.c84
-rw-r--r--test/Analysis/invalid-analyzer-config-value.c80
-rw-r--r--test/Analysis/invalidated-iterator.cpp399
-rw-r--r--test/Analysis/iterator-range.cpp176
-rw-r--r--test/Analysis/ivars.m2
-rw-r--r--test/Analysis/keychainAPI.m14
-rw-r--r--test/Analysis/lambda-notes.cpp195
-rw-r--r--test/Analysis/lambdas.cpp30
-rw-r--r--test/Analysis/lifetime-extension.cpp12
-rw-r--r--test/Analysis/lit.local.cfg11
-rw-r--r--test/Analysis/live-stmts.cpp167
-rw-r--r--test/Analysis/llvm-conventions.cpp225
-rw-r--r--test/Analysis/localization-aggressive.m6
-rw-r--r--test/Analysis/logical-ops.c2
-rw-r--r--test/Analysis/loop-block-counts.c26
-rw-r--r--test/Analysis/loop-widening-ignore-static-methods.cpp12
-rw-r--r--test/Analysis/loop-widening-notes.cpp2
-rw-r--r--test/Analysis/loop-widening.c4
-rw-r--r--test/Analysis/malloc-annotations.c6
-rw-r--r--test/Analysis/malloc-free-after-return.cpp21
-rw-r--r--test/Analysis/malloc-plist.c5039
-rw-r--r--test/Analysis/malloc.c7
-rw-r--r--test/Analysis/member-expr.cpp2
-rw-r--r--test/Analysis/method-call-path-notes.cpp779
-rw-r--r--test/Analysis/misc-ps-eager-assume.m8
-rw-r--r--test/Analysis/misc-ps.c2
-rw-r--r--test/Analysis/mismatched-iterator.cpp191
-rw-r--r--test/Analysis/missing-bind-temporary.cpp4
-rw-r--r--test/Analysis/model-file.cpp282
-rw-r--r--test/Analysis/new-aligned.cpp14
-rw-r--r--test/Analysis/new-ctor-conservative.cpp2
-rw-r--r--test/Analysis/new-ctor-inlined.cpp2
-rw-r--r--test/Analysis/new-ctor-recursive.cpp2
-rw-r--r--test/Analysis/new-ctor-symbolic.cpp2
-rw-r--r--test/Analysis/new.cpp4
-rw-r--r--test/Analysis/null-deref-path-notes.cpp2
-rw-r--r--test/Analysis/null-deref-path-notes.m976
-rw-r--r--test/Analysis/nullability-arc.mm39
-rw-r--r--test/Analysis/nullability-notes.m185
-rw-r--r--test/Analysis/nullability.mm35
-rw-r--r--test/Analysis/objc-arc.m1912
-rw-r--r--test/Analysis/objc-for.m2
-rw-r--r--test/Analysis/objc-radar17039661.m1276
-rw-r--r--test/Analysis/objcpp-uninitialized-object.mm32
-rw-r--r--test/Analysis/osobject-retain-release.cpp611
-rw-r--r--test/Analysis/padding_inherit.cpp28
-rw-r--r--test/Analysis/plist-macros-with-expansion.cpp442
-rw-r--r--test/Analysis/plist-macros.cpp1671
-rw-r--r--test/Analysis/plist-output-alternate.m1439
-rw-r--r--test/Analysis/plist-output.m5976
-rw-r--r--test/Analysis/plist-stats-output.c3
-rw-r--r--test/Analysis/pr22954.c4
-rw-r--r--test/Analysis/properties.m4
-rw-r--r--test/Analysis/ptr-arith.c4
-rw-r--r--test/Analysis/reference.cpp2
-rw-r--r--test/Analysis/region-store.c2
-rw-r--r--test/Analysis/retain-release-arc.m5
-rw-r--r--test/Analysis/retain-release-cpp-classes.cpp33
-rw-r--r--test/Analysis/retain-release-gc-only.m434
-rw-r--r--test/Analysis/retain-release-path-notes-gc.m1245
-rw-r--r--test/Analysis/retain-release-path-notes.m5176
-rw-r--r--test/Analysis/retain-release.m24064
-rw-r--r--test/Analysis/retain-release.mm15
-rw-r--r--test/Analysis/retaincountchecker-compoundregion.m4
-rw-r--r--test/Analysis/scopes-cfg-output.cpp5
-rw-r--r--test/Analysis/security-syntax-checks.m5
-rw-r--r--test/Analysis/self-assign.cpp9
-rw-r--r--test/Analysis/simple-stream-checks.c5
-rw-r--r--test/Analysis/std-c-library-functions-inlined.c17
-rw-r--r--test/Analysis/std-c-library-functions.c10
-rw-r--r--test/Analysis/std-c-library-functions.cpp2
-rw-r--r--test/Analysis/string.c66
-rw-r--r--test/Analysis/string.cpp28
-rw-r--r--test/Analysis/svalbuilder-float-cast.c20
-rw-r--r--test/Analysis/svalbuilder-rearrange-comparisons.c1100
-rw-r--r--test/Analysis/switch-case.c2
-rw-r--r--test/Analysis/symbol-reaper.c3
-rw-r--r--test/Analysis/temp-obj-dtors-option.cpp4
-rw-r--r--test/Analysis/templates.cpp4
-rw-r--r--test/Analysis/temporaries.cpp280
-rw-r--r--test/Analysis/temporaries.mm8
-rw-r--r--test/Analysis/test-after-div-zero.c4
-rw-r--r--test/Analysis/test-separate-retaincount.cpp38
-rw-r--r--test/Analysis/trustnonnullchecker_test.m130
-rw-r--r--test/Analysis/ubigraph-viz.cpp7
-rw-r--r--test/Analysis/undef-call.c2
-rw-r--r--test/Analysis/uninit-const.cpp10
-rw-r--r--test/Analysis/uninit-vals-ps-region.m93
-rw-r--r--test/Analysis/uninit-vals.c (renamed from test/Analysis/uninit-vals-ps.c)58
-rw-r--r--test/Analysis/uninit-vals.cpp3
-rw-r--r--test/Analysis/uninit-vals.m173
-rw-r--r--test/Analysis/unions.cpp5
-rw-r--r--test/Analysis/unix-fns.c2837
-rw-r--r--test/Analysis/use-after-move.cpp1139
-rw-r--r--test/Analysis/weak-functions.c2
-rw-r--r--test/CMakeLists.txt31
-rw-r--r--test/CXX/class.access/class.friend/p1.cpp5
-rw-r--r--test/CXX/class.access/class.friend/p11.cpp11
-rw-r--r--test/CXX/class.access/class.friend/p3-cxx0x.cpp15
-rw-r--r--test/CXX/class.derived/class.abstract/p16.cpp4
-rw-r--r--test/CXX/class/class.friend/p1.cpp4
-rw-r--r--test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp29
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp27
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp13
-rw-r--r--test/CXX/dcl.decl/dcl.decomp/p3.cpp77
-rw-r--r--test/CXX/dcl.decl/dcl.decomp/p4.cpp51
-rw-r--r--test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp51
-rw-r--r--test/CXX/drs/dr13xx.cpp6
-rw-r--r--test/CXX/drs/dr1xx.cpp5
-rw-r--r--test/CXX/drs/dr22xx.cpp11
-rw-r--r--test/CXX/drs/dr2xx.cpp4
-rw-r--r--test/CXX/drs/dr5xx.cpp8
-rw-r--r--test/CXX/drs/dr6xx.cpp54
-rw-r--r--test/CXX/expr/expr.const/p6.cpp39
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp4
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp8
-rw-r--r--test/CXX/special/class.copy/p12-0x.cpp2
-rw-r--r--test/CXX/special/class.copy/p23-cxx11.cpp2
-rw-r--r--test/CXX/special/class.ctor/p5-0x.cpp2
-rw-r--r--test/CXX/special/class.dtor/p5-0x.cpp2
-rw-r--r--test/CXX/special/class.temporary/p6.cpp240
-rw-r--r--test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp61
-rw-r--r--test/CXX/stmt.stmt/stmt.select/p3.cpp9
-rw-r--r--test/CXX/temp/temp.param/p2.cpp9
-rw-r--r--test/CXX/temp/temp.param/p3.cpp4
-rw-r--r--test/CXX/temp/temp.spec/temp.inst/p7.cpp12
-rw-r--r--test/CodeCompletion/accessibility-crash.cpp23
-rw-r--r--test/CodeCompletion/accessibility.cpp122
-rw-r--r--test/CodeCompletion/call.cpp2
-rw-r--r--test/CodeCompletion/crash-func-decl.cpp5
-rw-r--r--test/CodeCompletion/ctor-initializer.cpp85
-rw-r--r--test/CodeCompletion/function-overloads.cpp43
-rw-r--r--test/CodeCompletion/included-files.cpp35
-rw-r--r--test/CodeCompletion/member-access.c19
-rw-r--r--test/CodeCompletion/member-access.cpp70
-rw-r--r--test/CodeCompletion/objc-message.mm2
-rw-r--r--test/CodeCompletion/objc-protocol-member-access.m4
-rw-r--r--test/CodeCompletion/ordinary-name-cxx11.cpp1
-rw-r--r--test/CodeCompletion/ordinary-name.cpp1
-rw-r--r--test/CodeCompletion/overrides.cpp33
-rw-r--r--test/CodeCompletion/paren_locs.cpp33
-rw-r--r--test/CodeCompletion/pragma-macro-token-caching.c2
-rw-r--r--test/CodeCompletion/preferred-type.cpp15
-rw-r--r--test/CodeCompletion/self-inits.cpp3
-rw-r--r--test/CodeCompletion/signatures-crash.cpp15
-rw-r--r--test/CodeCompletion/this-quals.cpp21
-rw-r--r--test/CodeGen/2007-06-18-SextAttrAggregate.c2
-rw-r--r--test/CodeGen/2008-07-31-asm-labels.c2
-rw-r--r--test/CodeGen/64bit-swiftcall.c93
-rw-r--r--test/CodeGen/Inputs/code-coverage-filter1.h1
-rw-r--r--test/CodeGen/Inputs/code-coverage-filter2.h1
-rw-r--r--test/CodeGen/Inputs/thinlto_backend_local_name_conflict1.ll13
-rw-r--r--test/CodeGen/Inputs/thinlto_backend_local_name_conflict2.ll13
-rw-r--r--test/CodeGen/aapcs-align.cpp (renamed from test/CodeGen/aapcs-align.cc)0
-rw-r--r--test/CodeGen/aapcs64-align.cpp (renamed from test/CodeGen/aapcs64-align.cc)0
-rw-r--r--test/CodeGen/aarch64-neon-3v.c83
-rw-r--r--test/CodeGen/aarch64-neon-across.c147
-rw-r--r--test/CodeGen/aarch64-neon-extract.c24
-rw-r--r--test/CodeGen/aarch64-neon-fma.c41
-rw-r--r--test/CodeGen/aarch64-neon-fp16fml.c196
-rw-r--r--test/CodeGen/aarch64-neon-ldst-one.c460
-rw-r--r--test/CodeGen/aarch64-neon-scalar-copy.c26
-rw-r--r--test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c43
-rw-r--r--test/CodeGen/aarch64-neon-tbl.c207
-rw-r--r--test/CodeGen/aarch64-neon-vget.c51
-rw-r--r--test/CodeGen/aarch64-poly128.c58
-rw-r--r--test/CodeGen/aarch64-poly64.c71
-rw-r--r--test/CodeGen/aarch64-sign-return-address.c27
-rw-r--r--test/CodeGen/aarch64-vpcs.c23
-rw-r--r--test/CodeGen/adc-builtins.c20
-rw-r--r--test/CodeGen/address-sanitizer-and-array-cookie.cpp2
-rw-r--r--test/CodeGen/adx-builtins.c10
-rw-r--r--test/CodeGen/annotations-field.c3
-rw-r--r--test/CodeGen/arc/arguments.c135
-rw-r--r--test/CodeGen/arc/struct-align.c26
-rw-r--r--test/CodeGen/arm-neon-fma.c11
-rw-r--r--test/CodeGen/arm-neon-numeric-maxmin.c15
-rw-r--r--test/CodeGen/arm-neon-vcvtX.c51
-rw-r--r--test/CodeGen/arm-neon-vld.c4
-rw-r--r--test/CodeGen/arm-neon-vst.c4
-rw-r--r--test/CodeGen/arm-target-features.c4
-rw-r--r--test/CodeGen/arm-vfp16-arguments.c76
-rw-r--r--test/CodeGen/arm64-microsoft-intrinsics.c29
-rw-r--r--test/CodeGen/arm64-microsoft-status-reg.cpp119
-rw-r--r--test/CodeGen/arm64_vdupq_n_f64.c4
-rw-r--r--test/CodeGen/arm_neon_intrinsics.c237
-rw-r--r--test/CodeGen/asan-globals-odr.cpp30
-rw-r--r--test/CodeGen/asan-static-odr.cpp17
-rw-r--r--test/CodeGen/asan-strings.c17
-rw-r--r--test/CodeGen/atomic-ops.c47
-rw-r--r--test/CodeGen/atomics-inlining.c3
-rw-r--r--test/CodeGen/atomics-sema-alignment.c8
-rw-r--r--test/CodeGen/attr-cpuspecific.c290
-rw-r--r--test/CodeGen/attr-speculative-load-hardening.c15
-rw-r--r--test/CodeGen/attr-speculative-load-hardening.cpp18
-rw-r--r--test/CodeGen/attr-speculative-load-hardening.m9
-rw-r--r--test/CodeGen/attr-target-mv-func-ptrs.c41
-rw-r--r--test/CodeGen/attr-target-mv-va-args.c53
-rw-r--r--test/CodeGen/attr-target-mv.c265
-rw-r--r--test/CodeGen/attr-target-x86.c2
-rw-r--r--test/CodeGen/avr-inline-asm-constraints.c48
-rw-r--r--test/CodeGen/avr/attributes/interrupt.c2
-rw-r--r--test/CodeGen/avr/attributes/signal.c2
-rw-r--r--test/CodeGen/avx2-builtins.c68
-rw-r--r--test/CodeGen/avx512bitalg-builtins.c5
-rw-r--r--test/CodeGen/avx512bw-builtins.c594
-rw-r--r--test/CodeGen/avx512dq-builtins.c246
-rw-r--r--test/CodeGen/avx512f-builtins.c365
-rw-r--r--test/CodeGen/avx512vbmi-builtins.c8
-rw-r--r--test/CodeGen/avx512vbmi2-builtins.c106
-rw-r--r--test/CodeGen/avx512vbmivl-builtin.c16
-rw-r--r--test/CodeGen/avx512vl-builtins.c561
-rw-r--r--test/CodeGen/avx512vlbitalg-builtins.c10
-rw-r--r--test/CodeGen/avx512vlbw-builtins.c212
-rw-r--r--test/CodeGen/avx512vlvbmi2-builtins.c208
-rw-r--r--test/CodeGen/block-byref-aggr.c4
-rw-r--r--test/CodeGen/blocks-1.c8
-rw-r--r--test/CodeGen/blocks-seq.c1
-rw-r--r--test/CodeGen/blocks.c64
-rw-r--r--test/CodeGen/bmi-builtins.c26
-rw-r--r--test/CodeGen/bool_test.c14
-rw-r--r--test/CodeGen/builtin-constant-p.c179
-rw-r--r--test/CodeGen/builtin-cpu-is.c2
-rw-r--r--test/CodeGen/builtin-cpu-supports.c14
-rw-r--r--test/CodeGen/builtin-memfns.c18
-rw-r--r--test/CodeGen/builtin-rotate.c66
-rw-r--r--test/CodeGen/builtin-unpredictable.c12
-rw-r--r--test/CodeGen/builtin_clrsb.c22
-rw-r--r--test/CodeGen/builtins-hexagon-v66-128B.c67
-rw-r--r--test/CodeGen/builtins-hexagon-v66.c91
-rw-r--r--test/CodeGen/builtins-hexagon.c4
-rw-r--r--test/CodeGen/builtins-mips-msa-error.c759
-rw-r--r--test/CodeGen/builtins-mips-msa.c16
-rw-r--r--test/CodeGen/builtins-overflow.c21
-rw-r--r--test/CodeGen/builtins-ppc-altivec.c156
-rw-r--r--test/CodeGen/builtins-ppc-error.c6
-rw-r--r--test/CodeGen/builtins-ppc-p7-disabled.c8
-rw-r--r--test/CodeGen/builtins-ppc-p8vector.c12
-rw-r--r--test/CodeGen/builtins-ppc-p9-f128.c12
-rw-r--r--test/CodeGen/builtins-ppc-quadword.c32
-rw-r--r--test/CodeGen/builtins-ppc-vsx.c65
-rw-r--r--test/CodeGen/builtins-systemz-zvector.c1529
-rw-r--r--test/CodeGen/builtins-systemz-zvector2.c303
-rw-r--r--test/CodeGen/builtins-wasm.c424
-rw-r--r--test/CodeGen/builtins.c52
-rw-r--r--test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp40
-rw-r--r--test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp32
-rw-r--r--test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp52
-rw-r--r--test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp46
-rw-r--r--test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp44
-rw-r--r--test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp43
-rw-r--r--test/CodeGen/catch-alignment-assumption-blacklist.c28
-rw-r--r--test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp36
-rw-r--r--test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp33
-rw-r--r--test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp32
-rw-r--r--test/CodeGen/catch-alignment-assumption-openmp.cpp32
-rw-r--r--test/CodeGen/catch-implicit-conversions-basics.c125
-rw-r--r--test/CodeGen/catch-implicit-integer-arithmetic-value-change-basics.c123
-rw-r--r--test/CodeGen/catch-implicit-integer-conversions-basics.c125
-rw-r--r--test/CodeGen/catch-implicit-integer-sign-changes-CompoundAssignOperator.c2561
-rw-r--r--test/CodeGen/catch-implicit-integer-sign-changes-basics.c157
-rw-r--r--test/CodeGen/catch-implicit-integer-sign-changes-true-negatives.c152
-rw-r--r--test/CodeGen/catch-implicit-integer-sign-changes.c273
-rw-r--r--test/CodeGen/catch-implicit-integer-truncations-CompoundAssignOperator.c2745
-rw-r--r--test/CodeGen/catch-implicit-integer-truncations-basics-negatives.c86
-rw-r--r--test/CodeGen/catch-implicit-integer-truncations-basics.c115
-rw-r--r--test/CodeGen/catch-implicit-integer-truncations.c133
-rw-r--r--test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change-CompoundAssignOperator.c2553
-rw-r--r--test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change.c152
-rw-r--r--test/CodeGen/catch-implicit-signed-integer-truncations-basics-negatives.c40
-rw-r--r--test/CodeGen/catch-implicit-signed-integer-truncations-basics.c113
-rw-r--r--test/CodeGen/catch-implicit-unsigned-integer-truncations-basics-negatives.c40
-rw-r--r--test/CodeGen/catch-implicit-unsigned-integer-truncations-basics.c109
-rw-r--r--test/CodeGen/cf-runtime-abi.c60
-rw-r--r--test/CodeGen/cfguardtable.c6
-rw-r--r--test/CodeGen/cfstring-elf-cfbuild-x86_64.c36
-rw-r--r--test/CodeGen/cfstring-elf-sections-x86_64.c23
-rw-r--r--test/CodeGen/cfstring3.c (renamed from test/CodeGen/CFStrings.c)20
-rw-r--r--test/CodeGen/cleanup-destslot-simple.c1
-rw-r--r--test/CodeGen/code-coverage-filter.c84
-rw-r--r--test/CodeGen/code-coverage.c3
-rw-r--r--test/CodeGen/codemodels.c18
-rw-r--r--test/CodeGen/coff-aarch64-type-sizes.c2
-rw-r--r--test/CodeGen/darwin-ppc-varargs.c28
-rw-r--r--test/CodeGen/darwin-sdk-version.c4
-rw-r--r--test/CodeGen/darwin-string-literals.c8
-rw-r--r--test/CodeGen/debug-info-abspath.c34
-rw-r--r--test/CodeGen/debug-info-compilation-dir.c4
-rw-r--r--test/CodeGen/debug-info-enum.cpp18
-rw-r--r--test/CodeGen/debug-info-gline-tables-only.c3
-rw-r--r--test/CodeGen/debug-info-gline-tables-only2.c3
-rw-r--r--test/CodeGen/debug-info-global-constant.c2
-rw-r--r--test/CodeGen/debug-info-line.c1
-rw-r--r--test/CodeGen/debug-info-macro.c3
-rw-r--r--test/CodeGen/debug-info-names.c10
-rw-r--r--test/CodeGen/debug-info-ranges-base-address.c9
-rw-r--r--test/CodeGen/debug-info-scope-file.c4
-rw-r--r--test/CodeGen/debug-info-scope.c1
-rw-r--r--test/CodeGen/debug-info-vla.c4
-rw-r--r--test/CodeGen/debug-nvptx.c6
-rw-r--r--test/CodeGen/debug-prefix-map.c32
-rw-r--r--test/CodeGen/decl.c4
-rw-r--r--test/CodeGen/default-function-attr.c6
-rw-r--r--test/CodeGen/designated-initializers.c14
-rw-r--r--test/CodeGen/dllimport.c3
-rw-r--r--test/CodeGen/dso-local-executable.c11
-rw-r--r--test/CodeGen/dump-struct-builtin.c36
-rw-r--r--test/CodeGen/dwarf-version.c24
-rw-r--r--test/CodeGen/exceptions-seh-nested-finally.c26
-rw-r--r--test/CodeGen/exceptions-seh.c12
-rw-r--r--test/CodeGen/exceptions.c1
-rw-r--r--test/CodeGen/global-blocks-win32.c18
-rw-r--r--test/CodeGen/indirect-tls-seg-refs.c10
-rw-r--r--test/CodeGen/inline-asm-matching-ppc-vsx.c20
-rw-r--r--test/CodeGen/keep-static-consts.cpp11
-rw-r--r--test/CodeGen/lifetime-debuginfo-1.c1
-rw-r--r--test/CodeGen/lifetime-debuginfo-2.c1
-rw-r--r--test/CodeGen/lto-newpm-pipeline.c3
-rw-r--r--test/CodeGen/lzcnt-builtins.c10
-rw-r--r--test/CodeGen/microsoft-no-common-align.c8
-rw-r--r--test/CodeGen/mips-zero-sized-struct.c14
-rw-r--r--test/CodeGen/movbe-builtins.c49
-rw-r--r--test/CodeGen/ms-intrinsics-cpuid.c18
-rw-r--r--test/CodeGen/ms-intrinsics-other.c48
-rw-r--r--test/CodeGen/ms-intrinsics-rotations.c99
-rw-r--r--test/CodeGen/ms-intrinsics.c770
-rw-r--r--test/CodeGen/ms-setjmp.c4
-rw-r--r--test/CodeGen/ms-x86-intrinsics.c72
-rw-r--r--test/CodeGen/pch-dllexport.cpp12
-rw-r--r--test/CodeGen/personality.c1
-rw-r--r--test/CodeGen/pr18235.c2
-rw-r--r--test/CodeGen/rd-builtins.c9
-rw-r--r--test/CodeGen/sanitize-thread-no-checking-at-run-time.m2
-rw-r--r--test/CodeGen/split-debug-single-file.c17
-rw-r--r--test/CodeGen/sse2-builtins.c164
-rw-r--r--test/CodeGen/stack-arg-probe.c9
-rw-r--r--test/CodeGen/stackrealign-main.c19
-rw-r--r--test/CodeGen/summary-index-unnamed-global.ll11
-rw-r--r--test/CodeGen/swift-call-conv.c9
-rw-r--r--test/CodeGen/target-builtin-noerror.c10
-rw-r--r--test/CodeGen/target-data.c40
-rw-r--r--test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll7
-rw-r--r--test/CodeGen/thinlto-distributed-cfi-devirt.ll4
-rw-r--r--test/CodeGen/thinlto-distributed-cfi.ll2
-rw-r--r--test/CodeGen/thinlto_backend.ll3
-rw-r--r--test/CodeGen/thinlto_backend_local_name_conflict.ll36
-rw-r--r--test/CodeGen/tsan-instrprof-atomic.c6
-rw-r--r--test/CodeGen/ubsan-debuglog-return.c10
-rw-r--r--test/CodeGen/vector.c2
-rw-r--r--test/CodeGen/wasm-arguments.c1
-rw-r--r--test/CodeGen/wasm-varargs.c6
-rw-r--r--test/CodeGen/win64-i128.c16
-rw-r--r--test/CodeGen/windows-swiftcall.c77
-rw-r--r--test/CodeGen/x86-inline-asm-min-vector-width.c45
-rw-r--r--test/CodeGen/x86-vector-width.c61
-rw-r--r--test/CodeGen/xop-builtins.c16
-rw-r--r--test/CodeGen/xray-attributes-noxray-supported.cpp29
-rw-r--r--test/CodeGen/xray-attributes-supported.cpp45
-rw-r--r--test/CodeGenCUDA/builtins-amdgcn.cu18
-rw-r--r--test/CodeGenCUDA/device-stub.cu39
-rw-r--r--test/CodeGenCUDA/device-var-init.cu203
-rw-r--r--test/CodeGenCUDA/link-device-bitcode.cu10
-rw-r--r--test/CodeGenCUDA/propagate-metadata.cu8
-rw-r--r--test/CodeGenCUDA/usual-deallocators.cu133
-rw-r--r--test/CodeGenCXX/Inputs/override-layout-packed-base.layout10
-rw-r--r--test/CodeGenCXX/Inputs/profile-remap.map2
-rw-r--r--test/CodeGenCXX/Inputs/profile-remap.proftext7
-rw-r--r--test/CodeGenCXX/Inputs/profile-remap.samples3
-rw-r--r--test/CodeGenCXX/PR20038.cpp4
-rw-r--r--test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp41
-rw-r--r--test/CodeGenCXX/address-space-cast-coerce.cpp53
-rw-r--r--test/CodeGenCXX/address-space-cast.cpp56
-rw-r--r--test/CodeGenCXX/always_destroy.cpp31
-rw-r--r--test/CodeGenCXX/amdgcn-string-literal.cpp2
-rw-r--r--test/CodeGenCXX/atomic-inline.cpp61
-rw-r--r--test/CodeGenCXX/attr-cpuspecific.cpp26
-rw-r--r--test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp84
-rw-r--r--test/CodeGenCXX/attr-no-destroy-d54344.cpp42
-rw-r--r--test/CodeGenCXX/attr-target-mv-diff-ns.cpp108
-rw-r--r--test/CodeGenCXX/attr-target-mv-func-ptrs.cpp25
-rw-r--r--test/CodeGenCXX/attr-target-mv-inalloca.cpp81
-rw-r--r--test/CodeGenCXX/attr-target-mv-member-funcs.cpp225
-rw-r--r--test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp56
-rw-r--r--test/CodeGenCXX/attr-target-mv-overloads.cpp104
-rw-r--r--test/CodeGenCXX/auto-var-init.cpp1350
-rw-r--r--test/CodeGenCXX/block-byref-cxx-objc.cpp48
-rw-r--r--test/CodeGenCXX/block-byref.cpp15
-rw-r--r--test/CodeGenCXX/block-capture.cpp2
-rw-r--r--test/CodeGenCXX/blocks.cpp57
-rw-r--r--test/CodeGenCXX/builtin-constant-p.cpp24
-rw-r--r--test/CodeGenCXX/builtin-launder.cpp321
-rw-r--r--test/CodeGenCXX/castexpr-basepathsize-threshold.cpp6
-rw-r--r--test/CodeGenCXX/catch-implicit-integer-sign-changes-true-negatives.cpp149
-rw-r--r--test/CodeGenCXX/catch-implicit-integer-truncations.cpp6
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp47
-rw-r--r--test/CodeGenCXX/cfi-cross-dso.cpp2
-rw-r--r--test/CodeGenCXX/cfi-icall.cpp2
-rw-r--r--test/CodeGenCXX/conditional-temporaries.cpp164
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp4
-rw-r--r--test/CodeGenCXX/crash.cpp1
-rw-r--r--test/CodeGenCXX/cxx-block-objects.cpp4
-rw-r--r--test/CodeGenCXX/cxx11-thread-local.cpp2
-rw-r--r--test/CodeGenCXX/cxx1y-init-captures.cpp13
-rw-r--r--test/CodeGenCXX/cxx2a-init-statement.cpp10
-rw-r--r--test/CodeGenCXX/dbg-info-all-calls-described.cpp61
-rw-r--r--test/CodeGenCXX/debug-info-access.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-blocks.cpp10
-rw-r--r--test/CodeGenCXX/debug-info-byval.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-class-limited-plugin.test2
-rw-r--r--test/CodeGenCXX/debug-info-ctor2.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-cxx1y.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-decl-nested.cpp12
-rw-r--r--test/CodeGenCXX/debug-info-enum-class.cpp7
-rw-r--r--test/CodeGenCXX/debug-info-function-context.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-gline-tables-only.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-global-ctor-dtor.cpp16
-rw-r--r--test/CodeGenCXX/debug-info-inlined.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-lambda.cpp16
-rw-r--r--test/CodeGenCXX/debug-info-line.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-member.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-method-spec.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-ms-abi.cpp13
-rw-r--r--test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp1
-rw-r--r--test/CodeGenCXX/debug-info-namespace.cpp13
-rw-r--r--test/CodeGenCXX/debug-info-static-fns.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-template-explicit-specialization.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-template-member.cpp25
-rw-r--r--test/CodeGenCXX/debug-info-thunk-msabi.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-thunk.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-vla.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-windows-dtor.cpp1
-rw-r--r--test/CodeGenCXX/debug-info.cpp2
-rw-r--r--test/CodeGenCXX/debug-lambda-expressions.cpp8
-rw-r--r--test/CodeGenCXX/debug-prefix-map-lambda.cpp10
-rw-r--r--test/CodeGenCXX/dllexport-missing-key.cpp22
-rw-r--r--test/CodeGenCXX/dllexport-no-dllexport-inlines.cpp133
-rw-r--r--test/CodeGenCXX/dllexport.cpp18
-rw-r--r--test/CodeGenCXX/dllimport-members.cpp2
-rw-r--r--test/CodeGenCXX/dllimport.cpp27
-rw-r--r--test/CodeGenCXX/dso-local-executable.cpp18
-rw-r--r--test/CodeGenCXX/empty-struct-init-list.cpp12
-rw-r--r--test/CodeGenCXX/exceptions-seh-filter-captures.cpp6
-rw-r--r--test/CodeGenCXX/float128-declarations.cpp35
-rw-r--r--test/CodeGenCXX/float16-declarations.cpp6
-rw-r--r--test/CodeGenCXX/globalinit-loc.cpp4
-rw-r--r--test/CodeGenCXX/inalloca-lambda.cpp11
-rw-r--r--test/CodeGenCXX/inheriting-constructor-cleanup.cpp52
-rw-r--r--test/CodeGenCXX/inline-template-hint.cpp34
-rw-r--r--test/CodeGenCXX/lifetime-asan.cpp42
-rw-r--r--test/CodeGenCXX/linetable-fnbegin.cpp2
-rw-r--r--test/CodeGenCXX/linetable-virtual-variadic.cpp1
-rw-r--r--test/CodeGenCXX/mangle-address-space.cpp55
-rw-r--r--test/CodeGenCXX/mangle-long-double.cpp4
-rw-r--r--test/CodeGenCXX/mangle-ms-exception-spec.cpp42
-rw-r--r--test/CodeGenCXX/mangle-ms-templates.cpp30
-rw-r--r--test/CodeGenCXX/mangle-ms-thunks-covariant.cpp29
-rw-r--r--test/CodeGenCXX/mangle-ms-vector-types.cpp4
-rw-r--r--test/CodeGenCXX/mangle-ms.cpp2
-rw-r--r--test/CodeGenCXX/mangle-win-ccs.cpp70
-rw-r--r--test/CodeGenCXX/mangle-win64-ccs.cpp26
-rw-r--r--test/CodeGenCXX/merge-functions.cpp6
-rw-r--r--test/CodeGenCXX/microsoft-abi-static-initializers.cpp10
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-throw.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-thunks.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-vbtables.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-vftables.cpp6
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp8
-rw-r--r--test/CodeGenCXX/msabi-swiftcall-cc.cpp8
-rw-r--r--test/CodeGenCXX/no-lto-unit.cpp2
-rw-r--r--test/CodeGenCXX/no_destroy.cpp31
-rw-r--r--test/CodeGenCXX/noescape.cpp31
-rw-r--r--test/CodeGenCXX/override-layout-packed-base.cpp20
-rw-r--r--test/CodeGenCXX/pragma-init_seg.cpp8
-rw-r--r--test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp32
-rw-r--r--test/CodeGenCXX/pragma-loop-safety-nested.cpp27
-rw-r--r--test/CodeGenCXX/pragma-loop-safety-outer.cpp22
-rw-r--r--test/CodeGenCXX/pragma-loop-safety.cpp32
-rw-r--r--test/CodeGenCXX/pragma-pipeline.cpp47
-rw-r--r--test/CodeGenCXX/pragma-unroll-and-jam.cpp55
-rw-r--r--test/CodeGenCXX/profile-remap.cpp29
-rw-r--r--test/CodeGenCXX/speculative-vtt.cpp13
-rw-r--r--test/CodeGenCXX/static-init-wasm.cpp2
-rw-r--r--test/CodeGenCXX/thunk-returning-memptr.cpp27
-rw-r--r--test/CodeGenCXX/trivial-auto-var-init-attribute.cpp23
-rw-r--r--test/CodeGenCXX/trivial-auto-var-init.cpp216
-rw-r--r--test/CodeGenCXX/trivial_abi.cpp19
-rw-r--r--test/CodeGenCXX/type-metadata-thinlto.cpp4
-rw-r--r--test/CodeGenCXX/type-metadata.cpp14
-rw-r--r--test/CodeGenCXX/ubsan-check-debuglocs.cpp17
-rw-r--r--test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp111
-rw-r--r--test/CodeGenCXX/vtable-align.cpp5
-rw-r--r--test/CodeGenCXX/vtable-debug-info.cpp2
-rw-r--r--test/CodeGenCXX/vtable-linkage.cpp28
-rw-r--r--test/CodeGenCXX/wasm-args-returns.cpp26
-rw-r--r--test/CodeGenObjC/arc-arm.m4
-rw-r--r--test/CodeGenObjC/arc-block-copy-escape.m4
-rw-r--r--test/CodeGenObjC/arc-blocks.m249
-rw-r--r--test/CodeGenObjC/arc-bridged-cast.m16
-rw-r--r--test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m3
-rw-r--r--test/CodeGenObjC/arc-exceptions.m8
-rw-r--r--test/CodeGenObjC/arc-foreach.m36
-rw-r--r--test/CodeGenObjC/arc-i386.m4
-rw-r--r--test/CodeGenObjC/arc-linetable-autorelease.m4
-rw-r--r--test/CodeGenObjC/arc-linetable.m12
-rw-r--r--test/CodeGenObjC/arc-literals.m66
-rw-r--r--test/CodeGenObjC/arc-loadweakretained-release.m12
-rw-r--r--test/CodeGenObjC/arc-no-arc-exceptions.m1
-rw-r--r--test/CodeGenObjC/arc-no-runtime.m8
-rw-r--r--test/CodeGenObjC/arc-precise-lifetime.m54
-rw-r--r--test/CodeGenObjC/arc-property.m20
-rw-r--r--test/CodeGenObjC/arc-related-result-type.m8
-rw-r--r--test/CodeGenObjC/arc-ternary-op.m28
-rw-r--r--test/CodeGenObjC/arc-unbridged-cast.m2
-rw-r--r--test/CodeGenObjC/arc-unopt.m8
-rw-r--r--test/CodeGenObjC/arc-unoptimized-byref-var.m5
-rw-r--r--test/CodeGenObjC/arc-unsafeclaim.m44
-rw-r--r--test/CodeGenObjC/arc-weak-property.m8
-rw-r--r--test/CodeGenObjC/arc-weak.m4
-rw-r--r--test/CodeGenObjC/arc-with-atthrow.m4
-rw-r--r--test/CodeGenObjC/arc.ll10
-rw-r--r--test/CodeGenObjC/arc.m328
-rw-r--r--test/CodeGenObjC/autorelease.m6
-rw-r--r--test/CodeGenObjC/block-byref-debuginfo.m27
-rw-r--r--test/CodeGenObjC/block-desc-str.m14
-rw-r--r--test/CodeGenObjC/blocks-1.m49
-rw-r--r--test/CodeGenObjC/convert-messages-to-runtime-calls.m164
-rw-r--r--test/CodeGenObjC/debug-info-block-helper.m2
-rw-r--r--test/CodeGenObjC/debug-info-block-line.m8
-rw-r--r--test/CodeGenObjC/debug-info-blocks.m4
-rw-r--r--test/CodeGenObjC/debug-info-category.m29
-rw-r--r--test/CodeGenObjC/debug-info-synthesis.m2
-rw-r--r--test/CodeGenObjC/debug-property-synth.m4
-rw-r--r--test/CodeGenObjC/debuginfo-properties.m8
-rw-r--r--test/CodeGenObjC/empty-collection-literals.m12
-rw-r--r--test/CodeGenObjC/extern-void-class-decl.m14
-rw-r--r--test/CodeGenObjC/externally-retained.m115
-rw-r--r--test/CodeGenObjC/forward-declare-protocol-gnu.m10
-rw-r--r--test/CodeGenObjC/forward-protocol-metadata-symbols.m6
-rw-r--r--test/CodeGenObjC/fragile-arc.m28
-rw-r--r--test/CodeGenObjC/gnu-deterministic-selectors.m16
-rw-r--r--test/CodeGenObjC/gnu-init.m39
-rw-r--r--test/CodeGenObjC/gnustep2-category-protocol.m25
-rw-r--r--test/CodeGenObjC/gnustep2-proto.m6
-rw-r--r--test/CodeGenObjC/hidden-visibility.m2
-rw-r--r--test/CodeGenObjC/link-errors.m2
-rw-r--r--test/CodeGenObjC/mrc-weak.m56
-rw-r--r--test/CodeGenObjC/noescape.m64
-rw-r--r--test/CodeGenObjC/ns_consume_null_check.m16
-rw-r--r--test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m24
-rw-r--r--test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m24
-rw-r--r--test/CodeGenObjC/objc-arc-container-subscripting.m6
-rw-r--r--test/CodeGenObjC/os_log.m12
-rw-r--r--test/CodeGenObjC/parameterized_classes.m6
-rw-r--r--test/CodeGenObjC/protocol-comdat.m4
-rw-r--r--test/CodeGenObjC/protocols-lazy.m19
-rw-r--r--test/CodeGenObjC/protocols.m3
-rw-r--r--test/CodeGenObjC/stret-lifetime.m2
-rw-r--r--test/CodeGenObjC/strong-in-c-struct.m55
-rw-r--r--test/CodeGenObjC/ubsan-check-debuglocs.m30
-rw-r--r--test/CodeGenObjC/weak-in-c-struct.m20
-rw-r--r--test/CodeGenObjCXX/arc-attrs.mm8
-rw-r--r--test/CodeGenObjCXX/arc-blocks.mm105
-rw-r--r--test/CodeGenObjCXX/arc-constexpr.mm47
-rw-r--r--test/CodeGenObjCXX/arc-cxx11-init-list.mm10
-rw-r--r--test/CodeGenObjCXX/arc-exceptions.mm20
-rw-r--r--test/CodeGenObjCXX/arc-forwarded-lambda-call.mm8
-rw-r--r--test/CodeGenObjCXX/arc-globals.mm8
-rw-r--r--test/CodeGenObjCXX/arc-indirect.mm2
-rw-r--r--test/CodeGenObjCXX/arc-list-init-destruct.mm34
-rw-r--r--test/CodeGenObjCXX/arc-move.mm10
-rw-r--r--test/CodeGenObjCXX/arc-new-delete.mm28
-rw-r--r--test/CodeGenObjCXX/arc-pseudo-destructors.mm8
-rw-r--r--test/CodeGenObjCXX/arc-references.mm22
-rw-r--r--test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm4
-rw-r--r--test/CodeGenObjCXX/arc-special-member-functions.mm20
-rw-r--r--test/CodeGenObjCXX/arc-weak.mm8
-rw-r--r--test/CodeGenObjCXX/arc.mm98
-rw-r--r--test/CodeGenObjCXX/block-nested-in-lambda.cpp23
-rw-r--r--test/CodeGenObjCXX/block-nested-in-lambda.mm82
-rw-r--r--test/CodeGenObjCXX/crash-function-type.mm9
-rw-r--r--test/CodeGenObjCXX/debug-info-line.mm1
-rw-r--r--test/CodeGenObjCXX/destroy.mm4
-rw-r--r--test/CodeGenObjCXX/inheriting-constructor-cleanup.mm43
-rw-r--r--test/CodeGenObjCXX/lambda-expressions.mm10
-rw-r--r--test/CodeGenObjCXX/lambda-to-block.mm60
-rw-r--r--test/CodeGenObjCXX/literals.mm44
-rw-r--r--test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm4
-rw-r--r--test/CodeGenObjCXX/mrc-weak.mm48
-rw-r--r--test/CodeGenObjCXX/msabi-objc-extensions.mm31
-rw-r--r--test/CodeGenObjCXX/objc-weak.mm14
-rw-r--r--test/CodeGenObjCXX/pr14474-gline-tables-only.mm2
-rw-r--r--test/CodeGenOpenCL/addr-space-struct-arg.cl15
-rw-r--r--test/CodeGenOpenCL/address-spaces.cl4
-rw-r--r--test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl16
-rw-r--r--test/CodeGenOpenCL/amdgpu-features.cl12
-rw-r--r--test/CodeGenOpenCL/amdgpu-nullptr.cl4
-rw-r--r--test/CodeGenOpenCL/blocks.cl97
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-ci.cl19
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl28
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-vi.cl16
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn.cl73
-rw-r--r--test/CodeGenOpenCL/builtins.cl83
-rw-r--r--test/CodeGenOpenCL/cl20-device-side-enqueue.cl269
-rw-r--r--test/CodeGenOpenCL/constant-addr-space-globals.cl4
-rw-r--r--test/CodeGenOpenCL/denorms-are-zero.cl36
-rw-r--r--test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl33
-rw-r--r--test/CodeGenOpenCL/fpmath.cl12
-rw-r--r--test/CodeGenOpenCL/intel-subgroups-avc-ext-types.cl81
-rw-r--r--test/CodeGenOpenCL/numbered-address-space.cl34
-rw-r--r--test/CodeGenOpenCL/partial_initializer.cl4
-rw-r--r--test/CodeGenOpenCL/pipe_builtin.cl22
-rw-r--r--test/CodeGenOpenCL/printf.cl39
-rw-r--r--test/CodeGenOpenCL/private-array-initialization.cl4
-rw-r--r--test/CodeGenOpenCLCXX/address-space-deduction.cl46
-rw-r--r--test/CodeGenOpenCLCXX/address-space-deduction2.cl20
-rw-r--r--test/CodeGenOpenCLCXX/addrspace-of-this.cl188
-rw-r--r--test/CodeGenOpenCLCXX/template-address-spaces.cl31
-rw-r--r--test/Coverage/ast-printing.c1
-rw-r--r--test/Coverage/ast-printing.cpp1
-rw-r--r--test/Coverage/targets.c2
-rw-r--r--test/CoverageMapping/default-method.cpp17
-rw-r--r--test/CoverageMapping/macros.c10
-rw-r--r--test/Driver/Inputs/MacOSX10.14.sdk/SDKSettings.json1
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/c++/v1/.keep (renamed from test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc)0
-rw-r--r--test/Driver/Inputs/basic_hurd_tree/include/.keep0
-rw-r--r--test/Driver/Inputs/basic_hurd_tree/lib/i386-gnu/.keep0
-rw-r--r--test/Driver/Inputs/basic_hurd_tree/lib32/.keep0
-rw-r--r--test/Driver/Inputs/basic_hurd_tree/usr/include/i386-gnu/.keep0
-rw-r--r--test/Driver/Inputs/basic_hurd_tree/usr/lib/i386-gnu/.keep0
-rw-r--r--test/Driver/Inputs/basic_hurd_tree/usr/lib32/.keep0
-rwxr-xr-xtest/Driver/Inputs/basic_msp430_tree/bin/msp430-elf-ld0
-rw-r--r--test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o0
-rw-r--r--test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o0
-rw-r--r--test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crt0.o0
-rw-r--r--test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crtn.o0
-rw-r--r--test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/include/g++/backward/.keep0
-rw-r--r--test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o0
-rw-r--r--test/Driver/Inputs/cray_suse_gcc_tree/usr/include/c++/4.8/.keep0
-rw-r--r--test/Driver/Inputs/cray_suse_gcc_tree/usr/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o0
-rw-r--r--test/Driver/Inputs/hip_dev_lib/hip.amdgcn.bc0
-rw-r--r--test/Driver/Inputs/in.so1
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_tvos.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_watchos.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.ios.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.osx.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_tvos.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_watchos.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tvos.a0
-rw-r--r--test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.watchos.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/asan/.keep0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan-preinit.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan.so0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.builtins.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.fuzzer.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.scudo.so0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray-basic.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/libclang_rt.builtins.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/asan/.keep0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan-preinit.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan.so0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.builtins.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.fuzzer.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.scudo.so0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray-basic.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray.a0
-rw-r--r--test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/libclang_rt.builtins.a0
-rw-r--r--test/Driver/XRay/lit.local.cfg2
-rw-r--r--test/Driver/XRay/xray-instrument-os.c2
-rw-r--r--test/Driver/XRay/xray-instrumentation-bundles-flags.cpp11
-rw-r--r--test/Driver/XRay/xray-mode-flags.cpp14
-rw-r--r--test/Driver/Xarch.c19
-rw-r--r--test/Driver/aarch64-call-saved-x-register.c58
-rw-r--r--test/Driver/aarch64-cpus.c189
-rw-r--r--test/Driver/aarch64-fixed-call-saved-x-register.c8
-rw-r--r--test/Driver/aarch64-fixed-x-register.c71
-rw-r--r--test/Driver/aarch64-fixed-x18.c4
-rw-r--r--test/Driver/aarch64-fixed-x20.c4
-rw-r--r--test/Driver/aarch64-mte.c13
-rw-r--r--test/Driver/aarch64-rand.c13
-rw-r--r--test/Driver/aarch64-security-options.c54
-rw-r--r--test/Driver/aarch64-ssbs.c9
-rw-r--r--test/Driver/addrsig.c6
-rw-r--r--test/Driver/amdgpu-features.c12
-rw-r--r--test/Driver/amdgpu-macros.cl7
-rw-r--r--test/Driver/amdgpu-mcpu.cl2
-rw-r--r--test/Driver/amdgpu-visibility.cl7
-rw-r--r--test/Driver/android-aarch64-link.cpp5
-rw-r--r--test/Driver/android-gcc-toolchain.c8
-rw-r--r--test/Driver/android-ndk-standalone.cpp120
-rw-r--r--test/Driver/arm-cortex-cpus.c160
-rw-r--r--test/Driver/arm-features.c39
-rw-r--r--test/Driver/arm-ias-Wa.s2
-rw-r--r--test/Driver/arm-mfpu.c64
-rw-r--r--test/Driver/arm-target-as-mthumb.s4
-rw-r--r--test/Driver/autocomplete.c12
-rw-r--r--test/Driver/baremetal.cpp2
-rw-r--r--test/Driver/biarch.c16
-rw-r--r--test/Driver/cf-runtime-abi.c22
-rw-r--r--test/Driver/cl-idl.cpp18
-rw-r--r--test/Driver/cl-options.c41
-rw-r--r--test/Driver/cl-pch.cpp86
-rw-r--r--test/Driver/cl-showfilenames.c23
-rw-r--r--test/Driver/cl-zc.cpp6
-rw-r--r--test/Driver/clang-offload-bundler.c2
-rw-r--r--test/Driver/clang-translation.c99
-rw-r--r--test/Driver/clang_f_opts.c35
-rw-r--r--test/Driver/code-model.c2
-rw-r--r--test/Driver/coverage_no_integrated_as.c2
-rw-r--r--test/Driver/crash-report-null.test2
-rw-r--r--test/Driver/cuda-detect.cu10
-rw-r--r--test/Driver/cuda-dwarf-2.cu30
-rw-r--r--test/Driver/cuda-external-tools.cu22
-rw-r--r--test/Driver/cuda-macosx.cu2
-rw-r--r--test/Driver/cuda-no-pgo-or-coverage.cu2
-rw-r--r--test/Driver/cuda-no-sanitizers.cu2
-rw-r--r--test/Driver/cuda-no-stack-protector.cu2
-rw-r--r--test/Driver/cuda-options.cu12
-rw-r--r--test/Driver/cuda-output-asm.cu2
-rw-r--r--test/Driver/cuda-phases.cu43
-rw-r--r--test/Driver/cxa-atexit.cpp2
-rw-r--r--test/Driver/darwin-infer-simulator-sdkroot.c2
-rw-r--r--test/Driver/darwin-ld-lto.c11
-rw-r--r--test/Driver/darwin-ld.c83
-rw-r--r--test/Driver/darwin-sdk-version.c37
-rw-r--r--test/Driver/darwin-stdlib.cpp21
-rw-r--r--test/Driver/debug-options.c92
-rw-r--r--test/Driver/embed-bitcode.s12
-rw-r--r--test/Driver/fast-math.c2
-rw-r--r--test/Driver/fembed-bitcode.c28
-rw-r--r--test/Driver/fopenmp.c21
-rw-r--r--test/Driver/fsanitize-coverage.c1
-rw-r--r--test/Driver/fsanitize.c200
-rw-r--r--test/Driver/fuchsia.c90
-rw-r--r--test/Driver/fuchsia.cpp23
-rw-r--r--test/Driver/gcodeview-ghash.c19
-rw-r--r--test/Driver/header-module.cpp24
-rw-r--r--test/Driver/hexagon-hvx.c7
-rw-r--r--test/Driver/hexagon-toolchain-elf.c72
-rw-r--r--test/Driver/hip-binding.hip2
-rw-r--r--test/Driver/hip-device-libs.hip3
-rw-r--r--test/Driver/hip-link-shared-library.hip12
-rw-r--r--test/Driver/hip-output-file-name.hip9
-rw-r--r--test/Driver/hip-toolchain-no-rdc.hip158
-rw-r--r--test/Driver/hip-toolchain-rdc.hip (renamed from test/Driver/hip-toolchain.hip)30
-rw-r--r--test/Driver/hurd.c62
-rw-r--r--test/Driver/indirect-tls-seg-refs.c8
-rw-r--r--test/Driver/inhibit-downstream-commands.c2
-rw-r--r--test/Driver/integrated-as.c2
-rw-r--r--test/Driver/integrated-as.s6
-rw-r--r--test/Driver/linker-opts.c2
-rw-r--r--test/Driver/linux-as.c87
-rw-r--r--test/Driver/linux-header-search.cpp14
-rw-r--r--test/Driver/linux-ld.c216
-rw-r--r--test/Driver/linux-per-target-runtime-dir.c6
-rw-r--r--test/Driver/miamcu-opt.c2
-rw-r--r--test/Driver/mingw-lto.c4
-rw-r--r--test/Driver/mingw-sanitizers.c11
-rw-r--r--test/Driver/mingw.cpp5
-rw-r--r--test/Driver/mips-abi.c25
-rw-r--r--test/Driver/mips-abicalls-error.c2
-rw-r--r--test/Driver/mips-mti-linux.c4
-rw-r--r--test/Driver/msan.c28
-rw-r--r--test/Driver/msp430-hwmult.c42
-rw-r--r--test/Driver/msp430-mmcu.c16
-rw-r--r--test/Driver/msp430-toolchain.c78
-rw-r--r--test/Driver/msvc-link.c12
-rw-r--r--test/Driver/nacl-direct.c2
-rw-r--r--test/Driver/netbsd.c160
-rw-r--r--test/Driver/netbsd.cpp136
-rw-r--r--test/Driver/nios2-cpu.c26
-rw-r--r--test/Driver/no-integrated-as.c7
-rw-r--r--test/Driver/no-integrated-as.s2
-rw-r--r--test/Driver/nostdlibxx.cpp9
-rw-r--r--test/Driver/objc-convert-messages-to-runtime-calls.m7
-rw-r--r--test/Driver/offloading-interoperability.c2
-rw-r--r--test/Driver/openbsd.c35
-rw-r--r--test/Driver/openbsd.cpp19
-rw-r--r--test/Driver/openmp-offload-gpu.c81
-rw-r--r--test/Driver/openmp-offload.c142
-rw-r--r--test/Driver/output-file-cleanup.c1
-rw-r--r--test/Driver/parse-progname.c2
-rw-r--r--test/Driver/ppc-abi.c42
-rw-r--r--test/Driver/print-effective-triple.c6
-rw-r--r--test/Driver/print-multi-directory.c28
-rw-r--r--test/Driver/print-target-triple.c6
-rw-r--r--test/Driver/pth.c12
-rw-r--r--test/Driver/rewrite-legacy-objc.m2
-rw-r--r--test/Driver/riscv32-toolchain.c37
-rw-r--r--test/Driver/ropi-rwpi.c4
-rw-r--r--test/Driver/sanitizer-ld.c12
-rw-r--r--test/Driver/split-debug.c15
-rw-r--r--test/Driver/split-debug.s7
-rw-r--r--test/Driver/split-lto-unit.c10
-rw-r--r--test/Driver/unavailable_aligned_allocation.cpp13
-rw-r--r--test/Driver/unknown-arg.c2
-rw-r--r--test/Driver/unknown-std.c4
-rw-r--r--test/Driver/wasm-toolchain.c29
-rw-r--r--test/Driver/wasm-toolchain.cpp29
-rw-r--r--test/Driver/wasm32-unknown-unknown.cpp17
-rw-r--r--test/Driver/wasm64-unknown-unknown.cpp17
-rw-r--r--test/Driver/windows-arm-minimal-arch.c2
-rw-r--r--test/Driver/windows-exceptions.cpp3
-rw-r--r--test/Driver/x86-march.c4
-rw-r--r--test/Driver/x86-target-features.c13
-rw-r--r--test/FixIt/fixit-cxx11-attributes.cpp3
-rw-r--r--test/Frontend/ast-main.c6
-rw-r--r--test/Frontend/ast-main.cpp6
-rw-r--r--test/Frontend/dependency-gen-escaping.c2
-rw-r--r--test/Frontend/dependency-gen-has-include.c40
-rw-r--r--test/Frontend/dependency-gen.c10
-rw-r--r--test/Frontend/fixed_point_conversions.c283
-rw-r--r--test/Frontend/fixed_point_declarations.c16
-rw-r--r--test/Frontend/fixed_point_to_bool.c53
-rw-r--r--test/Frontend/fixed_point_unknown_conversions.c49
-rw-r--r--test/Frontend/noderef.c209
-rw-r--r--test/Frontend/noderef.cpp102
-rw-r--r--test/Frontend/noderef_on_non_pointers.m11
-rw-r--r--test/Frontend/noderef_templates.cpp15
-rw-r--r--test/Frontend/optimization-remark-with-hotness.c4
-rw-r--r--test/Frontend/plugin-unknown.c5
-rw-r--r--test/Frontend/warning-stdlibcxx-darwin.cpp3
-rw-r--r--test/Frontend/windows-exceptions.cpp12
-rw-r--r--test/Headers/arm-fp16-header.c19
-rw-r--r--test/Headers/arm-neon-header.c18
-rw-r--r--test/Headers/float.c24
-rw-r--r--test/Headers/ms-arm64-intrin.cpp29
-rw-r--r--test/Headers/ms-intrin.cpp2
-rw-r--r--test/Headers/opencl-c-header.cl18
-rw-r--r--test/Headers/thumbv7-apple-ios-types.cpp6
-rw-r--r--test/Import/array-init-loop-expr/Inputs/S.cpp8
-rw-r--r--test/Import/array-init-loop-expr/test.cpp10
-rw-r--r--test/Import/call-expr/Inputs/F.cpp10
-rw-r--r--test/Import/call-expr/test.cpp8
-rw-r--r--test/Import/compound-assign-op/Inputs/F.cpp18
-rw-r--r--test/Import/compound-assign-op/test.cpp45
-rw-r--r--test/Import/conversion-decl/Inputs/F.cpp10
-rw-r--r--test/Import/conversion-decl/test.cpp5
-rw-r--r--test/Import/cxx-casts/Inputs/F.cpp12
-rw-r--r--test/Import/cxx-casts/test.cpp21
-rw-r--r--test/Import/cxx-default-init-expr/Inputs/S.cpp9
-rw-r--r--test/Import/cxx-default-init-expr/test.cpp22
-rw-r--r--test/Import/cxx-for-range/Inputs/F.cpp10
-rw-r--r--test/Import/cxx-for-range/test.cpp58
-rw-r--r--test/Import/cxx-member-pointers/Inputs/S.cpp7
-rw-r--r--test/Import/cxx-member-pointers/test.cpp16
-rw-r--r--test/Import/cxx-noexcept-expr/Inputs/F.cpp1
-rw-r--r--test/Import/cxx-noexcept-expr/test.cpp8
-rw-r--r--test/Import/cxx-scalar-value-init/Inputs/S.cpp2
-rw-r--r--test/Import/cxx-scalar-value-init/test.cpp11
-rw-r--r--test/Import/cxx-try-catch/Inputs/F.cpp18
-rw-r--r--test/Import/cxx-try-catch/test.cpp39
-rw-r--r--test/Import/do-stmt/Inputs/F.cpp7
-rw-r--r--test/Import/do-stmt/test.cpp15
-rw-r--r--test/Import/enum/Inputs/S.cpp2
-rw-r--r--test/Import/enum/test.cpp6
-rw-r--r--test/Import/expr-with-cleanups/Inputs/S.cpp8
-rw-r--r--test/Import/expr-with-cleanups/test.cpp8
-rw-r--r--test/Import/for-stmt/Inputs/F.cpp11
-rw-r--r--test/Import/for-stmt/test.cpp50
-rw-r--r--test/Import/if-stmt/Inputs/F.cpp21
-rw-r--r--test/Import/if-stmt/test.cpp36
-rw-r--r--test/Import/indirect-goto/Inputs/F.cpp6
-rw-r--r--test/Import/indirect-goto/test.cpp10
-rw-r--r--test/Import/objc-autoreleasepool/Inputs/F.m5
-rw-r--r--test/Import/objc-autoreleasepool/test.m9
-rw-r--r--test/Import/objc-param-decl/Inputs/S.m5
-rw-r--r--test/Import/objc-param-decl/test.m11
-rw-r--r--test/Import/objc-try-catch/Inputs/F.m28
-rw-r--r--test/Import/objc-try-catch/test.m43
-rw-r--r--test/Import/pack-expansion-expr/Inputs/F.cpp11
-rw-r--r--test/Import/pack-expansion-expr/test.cpp12
-rw-r--r--test/Import/switch-stmt/Inputs/F.cpp23
-rw-r--r--test/Import/switch-stmt/test.cpp57
-rw-r--r--test/Import/while-stmt/Inputs/F.cpp8
-rw-r--r--test/Import/while-stmt/test.cpp21
-rw-r--r--test/Index/Core/Inputs/module/SubModA.h2
-rw-r--r--test/Index/Core/Inputs/module/SubSubModA.h2
-rw-r--r--test/Index/Core/Inputs/module/module.modulemap12
-rw-r--r--test/Index/Core/external-source-symbol-attr.m2
-rw-r--r--test/Index/Core/index-source.cpp2
-rw-r--r--test/Index/Core/index-source.m22
-rw-r--r--test/Index/Core/index-with-module.m10
-rw-r--r--test/Index/Inputs/cycle.h1
-rw-r--r--test/Index/annotate-comments-availability-attrs.cpp2
-rw-r--r--test/Index/annotate-operator-call-expr.cpp84
-rw-r--r--test/Index/attributes.c6
-rw-r--r--test/Index/availability.c5
-rw-r--r--test/Index/complete-access-checks.cpp25
-rw-r--r--test/Index/complete-block-properties.m12
-rw-r--r--test/Index/complete-block-property-assignment.m19
-rw-r--r--test/Index/complete-ctor-inits.cpp40
-rw-r--r--test/Index/complete-cxx-inline-methods.cpp21
-rw-r--r--test/Index/complete-exprs.c13
-rw-r--r--test/Index/complete-member-access.m8
-rw-r--r--test/Index/complete-pch-skip.cpp9
-rw-r--r--test/Index/complete-properties.m22
-rw-r--r--test/Index/complete-switch.c10
-rw-r--r--test/Index/complete-template-keywords.cpp5
-rw-r--r--test/Index/complete-type-factors.m2
-rw-r--r--test/Index/complete-with-annotations.cpp2
-rw-r--r--test/Index/coroutines.cpp24
-rw-r--r--test/Index/cxx11-lambdas.cpp5
-rw-r--r--test/Index/implicit-attrs.m6
-rw-r--r--test/Index/index-attrs.m39
-rw-r--r--test/Index/index-local-symbol.cpp6
-rw-r--r--test/Index/index-template-specialization.cpp10
-rw-r--r--test/Index/keep-going-include-cycle.c10
-rw-r--r--test/Index/keep-going.cpp11
-rw-r--r--test/Index/nullability.c10
-rw-r--r--test/Index/objc-typeargs-protocols.m28
-rw-r--r--test/Index/opencl-types.cl10
-rw-r--r--test/Index/print-type.cpp22
-rw-r--r--test/Index/print-type.m7
-rw-r--r--test/Index/property-getter-setter.m10
-rw-r--r--test/Index/skipped-bodies-unused.cpp8
-rw-r--r--test/Lexer/aligned-allocation.cpp23
-rw-r--r--test/Lexer/cross-windows-on-linux.cpp2
-rw-r--r--test/Lexer/cxx-features.cpp138
-rw-r--r--test/Lexer/has_feature_memory_sanitizer.cpp1
-rw-r--r--test/Lexer/has_feature_undefined_behavior_sanitizer.cpp13
-rw-r--r--test/Lexer/has_feature_xray_instrument.cpp11
-rw-r--r--test/Lexer/unicode.c12
-rw-r--r--test/Misc/ast-dump-stmt.c67
-rw-r--r--test/Misc/ast-dump-stmt.cpp83
-rw-r--r--test/Misc/backend-optimization-failure-nodbg.cpp2
-rw-r--r--test/Misc/backend-optimization-failure.cpp2
-rw-r--r--test/Misc/pragma-attribute-supported-attributes-list.test67
-rw-r--r--test/Misc/target-invalid-cpu-note.c10
-rw-r--r--test/Misc/warning-flags.c4
-rw-r--r--test/Modules/ExtDebugInfo.cpp4
-rw-r--r--test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h1
-rw-r--r--test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h1
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/A/ADT.h45
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/B/B.h14
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/C/C.h13
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/module.modulemap9
-rw-r--r--test/Modules/Inputs/no-module-map/a.h4
-rw-r--r--test/Modules/Inputs/no-module-map/b.h5
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/class.h1
-rw-r--r--test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h1
-rw-r--r--test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map5
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/a.h4
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/b.h13
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/module.modulemap9
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/x.h4
-rw-r--r--test/Modules/autolink.m4
-rw-r--r--test/Modules/crash-vfs-headermaps.m1
-rw-r--r--test/Modules/crash-vfs-include-pch.m1
-rw-r--r--test/Modules/crash-vfs-ivfsoverlay.m1
-rw-r--r--test/Modules/crash-vfs-path-emptydir-entries.m2
-rw-r--r--test/Modules/crash-vfs-path-symlink-component.m2
-rw-r--r--test/Modules/crash-vfs-path-symlink-topheader.m2
-rw-r--r--test/Modules/crash-vfs-path-traversal.m2
-rw-r--r--test/Modules/crash-vfs-relative-incdir.m1
-rw-r--r--test/Modules/crash-vfs-relative-overlay.m2
-rw-r--r--test/Modules/crash-vfs-run-reproducer.m1
-rw-r--r--test/Modules/crash-vfs-umbrella-frameworks.m2
-rw-r--r--test/Modules/cxx-templates.cpp2
-rw-r--r--test/Modules/double-quotes.m3
-rw-r--r--test/Modules/exception-spec.cpp36
-rw-r--r--test/Modules/friend-definition.cpp2
-rwxr-xr-xtest/Modules/lsv-debuginfo.cpp39
-rw-r--r--test/Modules/merge-deduced-return.cpp6
-rw-r--r--test/Modules/merge-lambdas.cpp5
-rw-r--r--test/Modules/merge-template-pattern-visibility-2.cpp34
-rw-r--r--test/Modules/merge-template-pattern-visibility-3.cpp34
-rw-r--r--test/Modules/mismatch-diagnostics.cpp22
-rw-r--r--test/Modules/module-debuginfo-prefix.m25
-rw-r--r--test/Modules/module_file_info.m3
-rw-r--r--test/Modules/no-module-map.cpp48
-rw-r--r--test/Modules/odr_hash-Friend.cpp10
-rw-r--r--test/Modules/odr_hash-blocks.cpp4
-rw-r--r--test/Modules/odr_hash-gnu.cpp130
-rw-r--r--test/Modules/odr_hash-vector.cpp128
-rw-r--r--test/Modules/odr_hash.cl80
-rw-r--r--test/Modules/odr_hash.cpp584
-rw-r--r--test/Modules/odr_hash.mm299
-rw-r--r--test/Modules/prune.m3
-rw-r--r--test/Modules/relative-dep-gen.cpp6
-rw-r--r--test/Modules/strict-decluse-headers.cpp17
-rw-r--r--test/Modules/subdirectory-module-maps-working-dir.m13
-rw-r--r--test/Modules/submodules-merge-defs.cpp2
-rw-r--r--test/Modules/target-platform-features.m79
-rw-r--r--test/Modules/templates.mm8
-rw-r--r--test/Modules/unavailable-local-visibility.test2
-rw-r--r--test/OpenMP/Inputs/declare_target_include.h3
-rw-r--r--test/OpenMP/cancel_messages.cpp40
-rw-r--r--test/OpenMP/cancellation_point_messages.cpp40
-rw-r--r--test/OpenMP/debug-info-openmp-array.cpp2
-rw-r--r--test/OpenMP/declare_reduction_ast_print.cpp14
-rw-r--r--test/OpenMP/declare_reduction_codegen.cpp12
-rw-r--r--test/OpenMP/declare_reduction_messages.cpp22
-rw-r--r--test/OpenMP/declare_target_ast_print.cpp81
-rw-r--r--test/OpenMP/declare_target_codegen.cpp132
-rw-r--r--test/OpenMP/declare_target_codegen_globalization.cpp29
-rw-r--r--test/OpenMP/declare_target_link_codegen.cpp4
-rw-r--r--test/OpenMP/declare_target_messages.cpp22
-rw-r--r--test/OpenMP/distribute_ast_print.cpp8
-rw-r--r--test/OpenMP/distribute_codegen.cpp4
-rw-r--r--test/OpenMP/distribute_firstprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_firstprivate_messages.cpp6
-rw-r--r--test/OpenMP/distribute_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_parallel_for_ast_print.cpp8
-rw-r--r--test/OpenMP/distribute_parallel_for_codegen.cpp220
-rw-r--r--test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp30
-rw-r--r--test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp18
-rw-r--r--test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp34
-rw-r--r--test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_private_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_reduction_messages.cpp40
-rw-r--r--test/OpenMP/distribute_parallel_for_shared_messages.cpp8
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_ast_print.cpp8
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_codegen.cpp220
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp30
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp6
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp24
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp8
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp6
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp2
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp40
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp16
-rw-r--r--test/OpenMP/distribute_private_messages.cpp16
-rw-r--r--test/OpenMP/distribute_simd_aligned_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_ast_print.cpp8
-rw-r--r--test/OpenMP/distribute_simd_codegen.cpp4
-rw-r--r--test/OpenMP/distribute_simd_firstprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_simd_firstprivate_messages.cpp18
-rw-r--r--test/OpenMP/distribute_simd_lastprivate_codegen.cpp32
-rw-r--r--test/OpenMP/distribute_simd_lastprivate_messages.cpp34
-rw-r--r--test/OpenMP/distribute_simd_linear_messages.cpp6
-rw-r--r--test/OpenMP/distribute_simd_loop_messages.cpp32
-rw-r--r--test/OpenMP/distribute_simd_private_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_reduction_messages.cpp42
-rw-r--r--test/OpenMP/for_ast_print.cpp4
-rw-r--r--test/OpenMP/for_codegen.cpp45
-rw-r--r--test/OpenMP/for_firstprivate_codegen.cpp2
-rw-r--r--test/OpenMP/for_lastprivate_codegen.cpp2
-rw-r--r--test/OpenMP/for_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/for_linear_codegen.cpp2
-rw-r--r--test/OpenMP/for_linear_messages.cpp4
-rw-r--r--test/OpenMP/for_loop_messages.cpp2
-rw-r--r--test/OpenMP/for_reduction_codegen.cpp6
-rw-r--r--test/OpenMP/for_reduction_codegen_UDR.cpp6
-rw-r--r--test/OpenMP/for_reduction_messages.cpp40
-rw-r--r--test/OpenMP/for_simd_codegen.cpp89
-rw-r--r--test/OpenMP/for_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/for_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/loops_explicit_clauses_codegen.cpp32
-rw-r--r--test/OpenMP/nvptx_SPMD_codegen.cpp483
-rw-r--r--test/OpenMP/nvptx_data_sharing.cpp24
-rw-r--r--test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp11
-rw-r--r--test/OpenMP/nvptx_force_full_runtime_SPMD_codegen.cpp326
-rw-r--r--test/OpenMP/nvptx_lambda_capturing.cpp156
-rw-r--r--test/OpenMP/nvptx_parallel_codegen.cpp56
-rw-r--r--test/OpenMP/nvptx_parallel_for_codegen.cpp134
-rw-r--r--test/OpenMP/nvptx_target_codegen.cpp162
-rw-r--r--test/OpenMP/nvptx_target_parallel_codegen.cpp8
-rw-r--r--test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp12
-rw-r--r--test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp160
-rw-r--r--test/OpenMP/nvptx_target_printf_codegen.c5
-rw-r--r--test/OpenMP/nvptx_target_teams_codegen.cpp20
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_codegen.cpp90
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp159
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp4
-rw-r--r--test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp49
-rw-r--r--test/OpenMP/nvptx_teams_codegen.cpp44
-rw-r--r--test/OpenMP/nvptx_teams_reduction_codegen.cpp822
-rw-r--r--test/OpenMP/openmp_offload_registration.cpp49
-rw-r--r--test/OpenMP/ordered_codegen.cpp14
-rw-r--r--test/OpenMP/ordered_doacross_codegen.c28
-rw-r--r--test/OpenMP/ordered_doacross_codegen.cpp107
-rw-r--r--test/OpenMP/parallel_codegen.cpp4
-rw-r--r--test/OpenMP/parallel_copyin_codegen.cpp44
-rw-r--r--test/OpenMP/parallel_default_messages.cpp14
-rw-r--r--test/OpenMP/parallel_for_ast_print.cpp23
-rw-r--r--test/OpenMP/parallel_for_codegen.cpp90
-rw-r--r--test/OpenMP/parallel_for_default_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/parallel_for_linear_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_reduction_messages.cpp28
-rw-r--r--test/OpenMP/parallel_for_simd_ast_print.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_codegen.cpp89
-rw-r--r--test/OpenMP/parallel_for_simd_default_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/parallel_for_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/parallel_if_codegen.cpp4
-rw-r--r--test/OpenMP/parallel_num_threads_codegen.cpp2
-rw-r--r--test/OpenMP/parallel_private_messages.cpp16
-rw-r--r--test/OpenMP/parallel_proc_bind_codegen.cpp2
-rw-r--r--test/OpenMP/parallel_reduction_codegen.cpp2
-rw-r--r--test/OpenMP/parallel_reduction_messages.cpp28
-rw-r--r--test/OpenMP/parallel_sections_default_messages.cpp2
-rw-r--r--test/OpenMP/parallel_sections_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/parallel_sections_reduction_messages.cpp28
-rw-r--r--test/OpenMP/requires_acq_rel_print.cpp16
-rw-r--r--test/OpenMP/requires_ast_print.cpp28
-rw-r--r--test/OpenMP/requires_codegen.cpp25
-rw-r--r--test/OpenMP/requires_messages.cpp68
-rw-r--r--test/OpenMP/requires_relaxed_print.cpp16
-rw-r--r--test/OpenMP/schedule_codegen.cpp84
-rw-r--r--test/OpenMP/sections_codegen.cpp4
-rw-r--r--test/OpenMP/sections_firstprivate_codegen.cpp2
-rw-r--r--test/OpenMP/sections_lastprivate_codegen.cpp2
-rw-r--r--test/OpenMP/sections_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/sections_reduction_codegen.cpp4
-rw-r--r--test/OpenMP/sections_reduction_messages.cpp28
-rw-r--r--test/OpenMP/simd_codegen.cpp279
-rw-r--r--test/OpenMP/simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/simd_metadata.c29
-rw-r--r--test/OpenMP/simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/single_codegen.cpp8
-rw-r--r--test/OpenMP/single_firstprivate_codegen.cpp4
-rw-r--r--test/OpenMP/target_ast_print.cpp111
-rw-r--r--test/OpenMP/target_codegen.cpp50
-rw-r--r--test/OpenMP/target_data_ast_print.cpp26
-rw-r--r--test/OpenMP/target_map_codegen.cpp157
-rw-r--r--test/OpenMP/target_map_messages.cpp58
-rw-r--r--test/OpenMP/target_messages.cpp24
-rw-r--r--test/OpenMP/target_parallel_codegen.cpp72
-rw-r--r--test/OpenMP/target_parallel_debug_codegen.cpp17
-rw-r--r--test/OpenMP/target_parallel_default_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_codegen.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/target_parallel_for_linear_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_map_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_parallel_for_simd_codegen.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/target_parallel_for_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_for_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_parallel_if_codegen.cpp2
-rw-r--r--test/OpenMP/target_parallel_map_messages.cpp4
-rw-r--r--test/OpenMP/target_parallel_num_threads_codegen.cpp2
-rw-r--r--test/OpenMP/target_parallel_private_messages.cpp26
-rw-r--r--test/OpenMP/target_parallel_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_simd_codegen.cpp2
-rw-r--r--test/OpenMP/target_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/target_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_teams_codegen.cpp23
-rw-r--r--test/OpenMP/target_teams_default_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_codegen.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/target_teams_distribute_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp5
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp7
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp5
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_teams_distribute_private_messages.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_teams_distribute_simd_codegen.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/target_teams_distribute_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_simd_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_distribute_simd_private_messages.cpp16
-rw-r--r--test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_teams_map_messages.cpp4
-rw-r--r--test/OpenMP/target_teams_messages.cpp10
-rw-r--r--test/OpenMP/target_teams_num_teams_codegen.cpp2
-rw-r--r--test/OpenMP/target_teams_private_messages.cpp16
-rw-r--r--test/OpenMP/target_teams_reduction_messages.cpp28
-rw-r--r--test/OpenMP/target_teams_thread_limit_codegen.cpp2
-rw-r--r--test/OpenMP/task_codegen.cpp14
-rw-r--r--test/OpenMP/task_default_messages.cpp2
-rw-r--r--test/OpenMP/task_firstprivate_messages.cpp6
-rw-r--r--test/OpenMP/task_in_reduction_message.cpp28
-rw-r--r--test/OpenMP/task_messages.cpp36
-rw-r--r--test/OpenMP/task_private_messages.cpp16
-rw-r--r--test/OpenMP/taskgroup_task_reduction_codegen.cpp2
-rw-r--r--test/OpenMP/taskgroup_task_reduction_messages.cpp28
-rw-r--r--test/OpenMP/taskloop_codegen.cpp10
-rw-r--r--test/OpenMP/taskloop_firstprivate_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_firstprivate_messages.cpp7
-rw-r--r--test/OpenMP/taskloop_in_reduction_messages.cpp28
-rw-r--r--test/OpenMP/taskloop_lastprivate_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/taskloop_loop_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_private_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_reduction_codegen.cpp6
-rw-r--r--test/OpenMP/taskloop_reduction_messages.cpp28
-rw-r--r--test/OpenMP/taskloop_simd_codegen.cpp46
-rw-r--r--test/OpenMP/taskloop_simd_firstprivate_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_simd_firstprivate_messages.cpp3
-rw-r--r--test/OpenMP/taskloop_simd_in_reduction_messages.cpp28
-rw-r--r--test/OpenMP/taskloop_simd_lastprivate_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/taskloop_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/taskloop_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_private_codegen.cpp8
-rw-r--r--test/OpenMP/taskloop_simd_reduction_codegen.cpp4
-rw-r--r--test/OpenMP/taskloop_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/teams_codegen.cpp4
-rw-r--r--test/OpenMP/teams_default_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_ast_print.cpp8
-rw-r--r--test/OpenMP/teams_distribute_codegen.cpp6
-rw-r--r--test/OpenMP/teams_distribute_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/teams_distribute_loop_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_ast_print.cpp8
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_codegen.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_private_messages.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp28
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp8
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp16
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/teams_distribute_private_messages.cpp16
-rw-r--r--test/OpenMP/teams_distribute_reduction_messages.cpp28
-rw-r--r--test/OpenMP/teams_distribute_simd_ast_print.cpp10
-rw-r--r--test/OpenMP/teams_distribute_simd_codegen.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp20
-rw-r--r--test/OpenMP/teams_distribute_simd_linear_messages.cpp4
-rw-r--r--test/OpenMP/teams_distribute_simd_loop_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_simd_private_messages.cpp16
-rw-r--r--test/OpenMP/teams_distribute_simd_reduction_messages.cpp28
-rw-r--r--test/OpenMP/teams_private_messages.cpp16
-rw-r--r--test/OpenMP/teams_reduction_messages.cpp28
-rw-r--r--test/OpenMP/threadprivate_codegen.cpp2
-rw-r--r--test/PCH/Inputs/pch-hdrstop-use.cpp13
-rw-r--r--test/PCH/Inputs/pch-no-hdrstop-use.cpp11
-rw-r--r--test/PCH/Inputs/pch-through-use3c.cpp2
-rw-r--r--test/PCH/Inputs/pch-through3c.h1
-rw-r--r--test/PCH/block-helpers.cpp35
-rw-r--r--test/PCH/block-helpers.h12
-rw-r--r--test/PCH/case-insensitive-include.c2
-rw-r--r--test/PCH/cxx-static_assert.cpp4
-rw-r--r--test/PCH/cxx2a-for-init-statement.cpp8
-rw-r--r--test/PCH/debug-info-pch-path.c4
-rw-r--r--test/PCH/emit-pth.c7
-rw-r--r--test/PCH/no-escaping-block-tail-calls.cpp14
-rw-r--r--test/PCH/no-escaping-block-tail-calls.h16
-rw-r--r--test/PCH/objc_exprs.h4
-rw-r--r--test/PCH/pch-hdrstop-err.cpp14
-rw-r--r--test/PCH/pch-hdrstop-warn.cpp10
-rw-r--r--test/PCH/pch-hdrstop.cpp28
-rw-r--r--test/PCH/pch-no-hdrstop.cpp18
-rw-r--r--test/PCH/pch-through3c.cpp9
-rw-r--r--test/PCH/pragma-loop.cpp21
-rw-r--r--test/PCH/pth.c7
-rw-r--r--test/Parser/DelayedTemplateParsing.cpp30
-rw-r--r--test/Parser/cuda-kernel-call-c++11.cu6
-rw-r--r--test/Parser/cuda-kernel-call.cu4
-rw-r--r--test/Parser/cxx0x-attributes.cpp8
-rw-r--r--test/Parser/cxx1z-decomposition.cpp1
-rw-r--r--test/Parser/cxx1z-init-statement.cpp8
-rw-r--r--test/Parser/cxx2a-init-statement.cpp34
-rw-r--r--test/Parser/cxx2a-inline-nested-namespace-definition.cpp51
-rw-r--r--test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp64
-rw-r--r--test/Parser/extra-semi-resulting-in-nullstmt.cpp96
-rw-r--r--test/Parser/message-expr-alt-op.mm41
-rw-r--r--test/Parser/objc-cxx-keyword-identifiers.mm4
-rw-r--r--test/Parser/pragma-attribute.cpp13
-rw-r--r--test/Parser/pragma-loop-safety.cpp8
-rw-r--r--test/Parser/pragma-loop.cpp59
-rw-r--r--test/Parser/pragma-pipeline.cpp33
-rw-r--r--test/Parser/pragma-unroll-and-jam.cpp78
-rw-r--r--test/Parser/pragma-unroll.cpp32
-rw-r--r--test/Parser/switch-recovery.cpp2
-rw-r--r--test/Preprocessor/aarch64-target-features.c135
-rw-r--r--test/Preprocessor/arm-acle-6.4.c19
-rw-r--r--test/Preprocessor/arm-target-features.c61
-rw-r--r--test/Preprocessor/c17.c1
-rw-r--r--test/Preprocessor/empty_file_to_include.h7
-rw-r--r--test/Preprocessor/feature_tests.c1
-rw-r--r--test/Preprocessor/has_attribute.cpp24
-rw-r--r--test/Preprocessor/hexagon-predefines.c24
-rw-r--r--test/Preprocessor/include-leading-nonalpha-no-suggest.c3
-rw-r--r--test/Preprocessor/include-likely-typo.c4
-rw-r--r--test/Preprocessor/include-nonalpha-no-crash.c3
-rw-r--r--test/Preprocessor/include-pth.c3
-rw-r--r--test/Preprocessor/init.c116
-rw-r--r--test/Preprocessor/pragma.c8
-rw-r--r--test/Preprocessor/predefined-arch-macros.c153
-rw-r--r--test/Preprocessor/wasm-target-features.c9
-rw-r--r--test/Preprocessor/woa-defaults.c2
-rw-r--r--test/Sema/Inputs/pragma-pack1.h2
-rw-r--r--test/Sema/aarch64-vpcs.c19
-rw-r--r--test/Sema/address_spaces.c16
-rw-r--r--test/Sema/alias-unused.c7
-rw-r--r--test/Sema/align-x86-abi7.c21
-rw-r--r--test/Sema/align-x86.c69
-rw-r--r--test/Sema/altivec-generic-overload.c100
-rw-r--r--test/Sema/arm-no-fp16.c210
-rw-r--r--test/Sema/assign.c34
-rw-r--r--test/Sema/atomic-implicit-seq_cst.c325
-rw-r--r--test/Sema/atomic-ops.c4
-rw-r--r--test/Sema/attr-availability-ios.c4
-rw-r--r--test/Sema/attr-availability-swift.c29
-rw-r--r--test/Sema/attr-availability-tvos.c14
-rw-r--r--test/Sema/attr-availability-watchos.c4
-rw-r--r--test/Sema/attr-availability.c10
-rw-r--r--test/Sema/attr-capabilities.c14
-rw-r--r--test/Sema/attr-coldhot.c4
-rw-r--r--test/Sema/attr-cpuspecific.c26
-rw-r--r--test/Sema/attr-disable-tail-calls.c4
-rw-r--r--test/Sema/attr-ifunc.c4
-rw-r--r--test/Sema/attr-long-call.c4
-rw-r--r--test/Sema/attr-micromips.c4
-rw-r--r--test/Sema/attr-notail.c4
-rw-r--r--test/Sema/attr-osobject.cpp74
-rw-r--r--test/Sema/attr-osobject.mm15
-rw-r--r--test/Sema/attr-ownership.c6
-rw-r--r--test/Sema/attr-ownership.cpp4
-rw-r--r--test/Sema/attr-print.c8
-rw-r--r--test/Sema/attr-target-mv-bad-target.c1
-rw-r--r--test/Sema/attr-target-mv.c3
-rw-r--r--test/Sema/attr-uninitialized.c21
-rw-r--r--test/Sema/attr-visibility.c4
-rw-r--r--test/Sema/availability-guard-format.mm4
-rw-r--r--test/Sema/builtin-object-size.c4
-rw-r--r--test/Sema/builtins-microsoft-arm64.c15
-rw-r--r--test/Sema/builtins.c46
-rw-r--r--test/Sema/callingconv.c2
-rw-r--r--test/Sema/conditional-expr.c4
-rw-r--r--test/Sema/conditional.c7
-rw-r--r--test/Sema/constant-builtins-2.c13
-rw-r--r--test/Sema/conversion.c2
-rw-r--r--test/Sema/div-sizeof-ptr.cpp28
-rw-r--r--test/Sema/enum.c23
-rw-r--r--test/Sema/ext-typecheck-comparison-of-pointer-integer.c12
-rw-r--r--test/Sema/fixed-enum.c18
-rw-r--r--test/Sema/format-strings-bitfield-promotion.c18
-rw-r--r--test/Sema/format-strings-bitfield-promotion.cxx21
-rw-r--r--test/Sema/format-strings-ms.c2
-rw-r--r--test/Sema/format-strings.c9
-rw-r--r--test/Sema/implicit-int-conversion.c15
-rw-r--r--test/Sema/integer-overflow.c3
-rw-r--r--test/Sema/internal_linkage.c4
-rw-r--r--test/Sema/mips-interrupt-attr.c8
-rw-r--r--test/Sema/nullability.c4
-rw-r--r--test/Sema/pr32985.c20
-rw-r--r--test/Sema/pragma-attribute-namespace.c41
-rw-r--r--test/Sema/pragma-attribute.c23
-rw-r--r--test/Sema/pragma-pipeline.cpp34
-rw-r--r--test/Sema/statements.c9
-rw-r--r--test/Sema/static-assert.c2
-rw-r--r--test/Sema/suspicious-pragma-pack.c2
-rw-r--r--test/Sema/swift-call-conv.c7
-rw-r--r--test/Sema/switch-availability.c27
-rw-r--r--test/Sema/sync-implicit-seq_cst.c26
-rw-r--r--test/Sema/unary-minus-integer-impcast.c20
-rw-r--r--test/Sema/uninit-variables.c1
-rw-r--r--test/Sema/warn-documentation.cpp9
-rw-r--r--test/Sema/warn-duplicate-enum.c10
-rw-r--r--test/Sema/warn-shadow.c12
-rw-r--r--test/Sema/zvector.c43
-rw-r--r--test/Sema/zvector2.c7
-rw-r--r--test/SemaCUDA/call-host-fn-from-device.cu6
-rw-r--r--test/SemaCUDA/extern-shared.cu4
-rw-r--r--test/SemaCUDA/implicit-member-target-inherited.cu205
-rw-r--r--test/SemaCUDA/implicit-member-target.cu2
-rw-r--r--test/SemaCUDA/inherited-ctor.cu89
-rw-r--r--test/SemaCUDA/usual-deallocators.cu95
-rw-r--r--test/SemaCXX/MicrosoftCompatibility.cpp20
-rw-r--r--test/SemaCXX/PR38913.cpp12
-rw-r--r--test/SemaCXX/addr-of-overloaded-function.cpp14
-rw-r--r--test/SemaCXX/aggregate-initialization.cpp48
-rw-r--r--test/SemaCXX/alias-template.cpp16
-rw-r--r--test/SemaCXX/align-x86-abi7.cpp25
-rw-r--r--test/SemaCXX/align-x86.cpp62
-rw-r--r--test/SemaCXX/alignof.cpp19
-rw-r--r--test/SemaCXX/array-bounds.cpp12
-rw-r--r--test/SemaCXX/attr-cpuspecific.cpp3
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp36
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp45
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp69
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp43
-rw-r--r--test/SemaCXX/attr-gnu.cpp21
-rw-r--r--test/SemaCXX/attr-on-explicit-template-instantiation.cpp25
-rw-r--r--test/SemaCXX/attr-optnone.cpp8
-rw-r--r--test/SemaCXX/attr-print.cpp4
-rw-r--r--test/SemaCXX/attr-reinitializes.cpp15
-rw-r--r--test/SemaCXX/attr-speculative-load-hardening.cpp34
-rw-r--r--test/SemaCXX/builtins.cpp92
-rw-r--r--test/SemaCXX/calling-conv-compat.cpp43
-rw-r--r--test/SemaCXX/char8_t.cpp10
-rw-r--r--test/SemaCXX/compound-literal.cpp14
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp6
-rw-r--r--test/SemaCXX/constant-expression-cxx1y.cpp41
-rw-r--r--test/SemaCXX/constant-expression-cxx2a.cpp7
-rw-r--r--test/SemaCXX/constexpr-string.cpp252
-rw-r--r--test/SemaCXX/constructor.cpp11
-rw-r--r--test/SemaCXX/coreturn-eh.cpp45
-rw-r--r--test/SemaCXX/coroutine-rvo.cpp69
-rw-r--r--test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp21
-rw-r--r--test/SemaCXX/cxx0x-defaulted-functions.cpp8
-rw-r--r--test/SemaCXX/cxx0x-deleted-default-ctor.cpp6
-rw-r--r--test/SemaCXX/cxx0x-initializer-scalars.cpp23
-rw-r--r--test/SemaCXX/cxx11-compat.cpp (renamed from test/SemaCXX/cxx0x-compat.cpp)26
-rw-r--r--test/SemaCXX/cxx14-compat.cpp34
-rw-r--r--test/SemaCXX/cxx17-compat.cpp38
-rw-r--r--test/SemaCXX/cxx1y-deduced-return-type.cpp68
-rw-r--r--test/SemaCXX/cxx1y-init-captures.cpp8
-rw-r--r--test/SemaCXX/cxx1z-class-template-argument-deduction.cpp7
-rw-r--r--test/SemaCXX/cxx1z-init-statement.cpp8
-rw-r--r--test/SemaCXX/cxx2a-compat.cpp39
-rw-r--r--test/SemaCXX/cxx2a-initializer-aggregates.cpp23
-rw-r--r--test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp37
-rw-r--r--test/SemaCXX/cxx98-compat.cpp3
-rw-r--r--test/SemaCXX/delete-non-virtual-dtor.cpp30
-rw-r--r--test/SemaCXX/designated-initializers.cpp1
-rw-r--r--test/SemaCXX/dr1301.cpp6
-rw-r--r--test/SemaCXX/enable_if.cpp3
-rw-r--r--test/SemaCXX/enum.cpp2
-rw-r--r--test/SemaCXX/exception-spec.cpp47
-rw-r--r--test/SemaCXX/for-range-dereference.cpp6
-rw-r--r--test/SemaCXX/for-range-examples.cpp2
-rw-r--r--test/SemaCXX/friend-template-redecl.cpp20
-rw-r--r--test/SemaCXX/friend.cpp53
-rw-r--r--test/SemaCXX/friend2.cpp89
-rw-r--r--test/SemaCXX/implicit-exception-spec.cpp22
-rw-r--r--test/SemaCXX/lambda-invalid-capture.cpp18
-rw-r--r--test/SemaCXX/member-init.cpp20
-rw-r--r--test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp4
-rw-r--r--test/SemaCXX/microsoft-varargs.cpp1
-rw-r--r--test/SemaCXX/ms-uuid.cpp8
-rw-r--r--test/SemaCXX/no_destroy.cpp46
-rw-r--r--test/SemaCXX/rdar42746401.cpp7
-rw-r--r--test/SemaCXX/static-assert-cxx17.cpp104
-rw-r--r--test/SemaCXX/static-assert.cpp124
-rw-r--r--test/SemaCXX/string-plus-int.cpp23
-rw-r--r--test/SemaCXX/struct-class-redecl.cpp31
-rw-r--r--test/SemaCXX/subst-restrict.cpp18
-rw-r--r--test/SemaCXX/switch-implicit-fallthrough.cpp15
-rw-r--r--test/SemaCXX/thread-safety-annotations.h42
-rw-r--r--test/SemaCXX/unavailable_aligned_allocation.cpp77
-rw-r--r--test/SemaCXX/uninitialized.cpp6
-rw-r--r--test/SemaCXX/vector.cpp8
-rw-r--r--test/SemaCXX/warn-comma-operator.cpp245
-rw-r--r--test/SemaCXX/warn-exit-time-destructors.cpp5
-rw-r--r--test/SemaCXX/warn-float-conversion.cpp26
-rw-r--r--test/SemaCXX/warn-loop-analysis.cpp23
-rw-r--r--test/SemaCXX/warn-overloaded-virtual.cpp2
-rw-r--r--test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp2
-rw-r--r--test/SemaCXX/warn-shadow-in-lambdas.cpp5
-rw-r--r--test/SemaCXX/warn-shadow.cpp69
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp479
-rw-r--r--test/SemaCXX/warn-thread-safety-negative.cpp42
-rw-r--r--test/SemaCXX/warn-thread-safety-parsing.cpp82
-rw-r--r--test/SemaCXX/warn-thread-safety-verbose.cpp40
-rw-r--r--test/SemaCXX/warn-unsequenced-cxx17.cpp8
-rw-r--r--test/SemaCXX/warn-unsequenced.cpp1
-rw-r--r--test/SemaCXX/warn-unused-result.cpp40
-rw-r--r--test/SemaObjC/arc-objc-lifetime-conflict.m14
-rw-r--r--test/SemaObjC/arc-repeated-weak.mm19
-rw-r--r--test/SemaObjC/arc.m2
-rw-r--r--test/SemaObjC/attr-availability.m18
-rw-r--r--test/SemaObjC/call-unavailable-init-in-self.m68
-rw-r--r--test/SemaObjC/enum-fixed-type.m5
-rw-r--r--test/SemaObjC/externally-retained-no-arc.m7
-rw-r--r--test/SemaObjC/externally-retained.m114
-rw-r--r--test/SemaObjC/format-strings-oslog.m4
-rw-r--r--test/SemaObjC/infer-availability-from-init.m58
-rw-r--r--test/SemaObjC/multiple-method-names-in-class-self.m39
-rw-r--r--test/SemaObjC/nullability.m14
-rw-r--r--test/SemaObjC/property-assign-on-object-type.m19
-rw-r--r--test/SemaObjC/property-deprecated-warning.m11
-rw-r--r--test/SemaObjC/property-in-class-extension-1.m4
-rw-r--r--test/SemaObjC/protocol-expr-neg-1.m6
-rw-r--r--test/SemaObjC/unguarded-availability-new.m8
-rw-r--r--test/SemaObjC/unguarded-availability.m36
-rw-r--r--test/SemaObjCXX/blocks.mm8
-rw-r--r--test/SemaObjCXX/foreach.mm8
-rw-r--r--test/SemaObjCXX/noescape.mm25
-rw-r--r--test/SemaObjCXX/warn-thread-safety-analysis.mm44
-rw-r--r--test/SemaOpenCL/access-qualifier.cl32
-rw-r--r--test/SemaOpenCL/address-spaces-conversions-cl2.0.cl299
-rw-r--r--test/SemaOpenCL/address-spaces.cl58
-rw-r--r--test/SemaOpenCL/atomic-ops.cl5
-rw-r--r--test/SemaOpenCL/block-array-capturing.cl16
-rw-r--r--test/SemaOpenCL/builtins-amdgcn-error-ci.cl8
-rw-r--r--test/SemaOpenCL/builtins-amdgcn-error-vi.cl8
-rw-r--r--test/SemaOpenCL/builtins-amdgcn-error.cl9
-rw-r--r--test/SemaOpenCL/cl20-device-side-enqueue.cl8
-rw-r--r--test/SemaOpenCL/clang-builtin-version.cl2
-rw-r--r--test/SemaOpenCL/clk_event_t.cl25
-rw-r--r--test/SemaOpenCL/extension-begin.cl60
-rw-r--r--test/SemaOpenCL/extension-begin.h26
-rw-r--r--test/SemaOpenCL/extension-version.cl21
-rw-r--r--test/SemaOpenCL/extensions.cl7
-rw-r--r--test/SemaOpenCL/format-strings-fixit.cl24
-rw-r--r--test/SemaOpenCL/intel-subgroup-avc-ext-types.cl105
-rw-r--r--test/SemaOpenCL/invalid-clk-events-cl2.0.cl3
-rw-r--r--test/SemaOpenCL/invalid-kernel-attrs.cl7
-rw-r--r--test/SemaOpenCL/null_queue.cl26
-rw-r--r--test/SemaOpenCL/numbered-address-space.cl31
-rw-r--r--test/SemaOpenCL/printf-format-string-warnings.cl13
-rw-r--r--test/SemaOpenCL/printf-format-strings.cl94
-rw-r--r--test/SemaOpenCL/sampler_t.cl2
-rw-r--r--test/SemaOpenCL/to_addr_builtin.cl82
-rw-r--r--test/SemaOpenCLCXX/address-space-templates.cl31
-rw-r--r--test/SemaTemplate/attributes.cpp4
-rw-r--r--test/SemaTemplate/exception-spec-crash.cpp4
-rw-r--r--test/SemaTemplate/friend.cpp75
-rw-r--r--test/SemaTemplate/instantiate-init.cpp6
-rw-r--r--test/SemaTemplate/instantiation-depth-default.cpp2
-rw-r--r--test/SemaTemplate/member-specialization.cpp11
-rw-r--r--test/SemaTemplate/temp_arg_nontype_cxx1z.cpp43
-rw-r--r--test/SemaTemplate/temp_arg_pack.cpp16
-rw-r--r--test/SemaTemplate/typename-specifier-3.cpp56
-rw-r--r--test/Tooling/Inputs/mock-libcxx/bin/clang1
-rw-r--r--test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector1
-rw-r--r--test/Tooling/auto-detect-from-source.cpp10
-rw-r--r--test/Tooling/clang-check-analyzer.cpp3
-rw-r--r--test/Tooling/clang-check-ast-dump.cpp3
-rw-r--r--test/Tooling/clang-check-extra-arg.cpp4
-rw-r--r--test/Tooling/clang-check-mac-libcxx-abspath.cpp17
-rw-r--r--test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp16
-rw-r--r--test/Tooling/clang-check-mac-libcxx-relpath.cpp17
-rw-r--r--test/Tooling/clang-diff-json.cpp6
-rw-r--r--test/VFS/Inputs/Broken.framework/Headers/Error.h3
-rw-r--r--test/VFS/Inputs/Broken.framework/Modules/module.modulemap6
-rw-r--r--test/VFS/Inputs/Broken.framework/VFSHeaders/A.h1
-rw-r--r--test/VFS/Inputs/MissingVFS/vfsoverlay.yaml1
-rw-r--r--test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml1
-rw-r--r--test/VFS/Inputs/bar-headers.yaml1
-rw-r--r--test/VFS/Inputs/vfsoverlay2.yaml1
-rw-r--r--test/VFS/Inputs/vfsroot.yaml55
-rw-r--r--test/VFS/subframework-symlink.m23
-rw-r--r--test/VFS/umbrella-framework-import-skipnonexist.m2
-rw-r--r--test/VFS/vfsroot-include.c17
-rw-r--r--test/VFS/vfsroot-module.m10
-rw-r--r--test/VFS/vfsroot-with-overlay.c12
-rw-r--r--test/lit.cfg.py17
-rw-r--r--test/lit.site.cfg.py.in4
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/arcmt-test/CMakeLists.txt1
-rw-r--r--tools/arcmt-test/arcmt-test.cpp4
-rw-r--r--tools/c-index-test/c-index-test.c130
-rw-r--r--tools/c-index-test/core_main.cpp30
-rw-r--r--tools/clang-check/CMakeLists.txt1
-rw-r--r--tools/clang-check/ClangCheck.cpp5
-rw-r--r--tools/clang-diff/CMakeLists.txt1
-rw-r--r--tools/clang-extdef-mapping/CMakeLists.txt (renamed from tools/clang-func-mapping/CMakeLists.txt)12
-rw-r--r--tools/clang-extdef-mapping/ClangExtDefMapGen.cpp (renamed from tools/clang-func-mapping/ClangFnMapGen.cpp)44
-rw-r--r--tools/clang-format/ClangFormat.cpp10
-rwxr-xr-xtools/clang-format/clang-format-diff.py27
-rw-r--r--tools/clang-format/clang-format-sublime.py2
-rw-r--r--tools/clang-format/clang-format.py2
-rwxr-xr-xtools/clang-format/git-clang-format2
-rw-r--r--tools/clang-fuzzer/Dockerfile4
-rw-r--r--tools/clang-fuzzer/README.txt34
-rw-r--r--tools/clang-fuzzer/cxx_loop_proto.proto12
-rw-r--r--tools/clang-fuzzer/handle-cxx/CMakeLists.txt1
-rw-r--r--tools/clang-fuzzer/handle-llvm/handle_llvm.cpp83
-rw-r--r--tools/clang-fuzzer/handle-llvm/handle_llvm.h2
-rw-r--r--tools/clang-fuzzer/handle-llvm/input_arrays.h118
-rw-r--r--tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp49
-rw-r--r--tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp88
-rw-r--r--tools/clang-import-test/CMakeLists.txt1
-rw-r--r--tools/clang-import-test/clang-import-test.cpp7
-rw-r--r--tools/clang-refactor/CMakeLists.txt1
-rw-r--r--tools/clang-refactor/TestSupport.h3
-rw-r--r--tools/clang-rename/CMakeLists.txt1
-rw-r--r--tools/clang-rename/clang-rename.py13
-rw-r--r--tools/diagtool/DiagTool.cpp2
-rw-r--r--tools/diagtool/ListWarnings.cpp1
-rw-r--r--tools/diagtool/TreeView.cpp1
-rw-r--r--tools/driver/CMakeLists.txt1
-rw-r--r--tools/driver/cc1_main.cpp7
-rw-r--r--tools/driver/cc1as_main.cpp26
-rw-r--r--tools/driver/cc1gen_reproducer_main.cpp2
-rw-r--r--tools/driver/driver.cpp6
-rw-r--r--tools/libclang/BuildSystem.cpp6
-rw-r--r--tools/libclang/CIndex.cpp344
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp13
-rw-r--r--tools/libclang/CIndexDiagnostic.cpp1
-rw-r--r--tools/libclang/CMakeLists.txt20
-rw-r--r--tools/libclang/CXCursor.cpp63
-rw-r--r--tools/libclang/CXCursor.h17
-rw-r--r--tools/libclang/CXIndexDataConsumer.cpp6
-rw-r--r--tools/libclang/CXIndexDataConsumer.h2
-rw-r--r--tools/libclang/CXStoredDiagnostic.cpp2
-rw-r--r--tools/libclang/CXType.cpp132
-rw-r--r--tools/libclang/libclang.exports9
-rw-r--r--tools/scan-build-py/README.md2
-rw-r--r--tools/scan-build-py/libscanbuild/__init__.py2
-rw-r--r--tools/scan-build-py/libscanbuild/analyze.py120
-rw-r--r--tools/scan-build-py/libscanbuild/arguments.py29
-rw-r--r--tools/scan-build-py/libscanbuild/clang.py6
-rw-r--r--tools/scan-build-py/tests/unit/test_analyze.py18
-rw-r--r--tools/scan-build-py/tests/unit/test_clang.py2
-rwxr-xr-xtools/scan-build/bin/scan-build62
-rwxr-xr-xtools/scan-build/libexec/ccc-analyzer10
-rwxr-xr-xtools/scan-view/bin/scan-view31
-rw-r--r--tools/scan-view/share/Reporter.py16
-rw-r--r--tools/scan-view/share/ScanView.py114
-rw-r--r--tools/scan-view/share/startfile.py11
-rw-r--r--unittests/AST/ASTContextParentMapTest.cpp39
-rw-r--r--unittests/AST/ASTImporterTest.cpp2027
-rw-r--r--unittests/AST/CMakeLists.txt5
-rw-r--r--unittests/AST/CommentTextTest.cpp2
-rw-r--r--unittests/AST/StmtPrinterTest.cpp103
-rw-r--r--unittests/AST/StructuralEquivalenceTest.cpp158
-rw-r--r--unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp99
-rw-r--r--unittests/ASTMatchers/ASTMatchersNodeTest.cpp70
-rw-r--r--unittests/ASTMatchers/ASTMatchersTraversalTest.cpp67
-rw-r--r--unittests/ASTMatchers/CMakeLists.txt1
-rw-r--r--unittests/ASTMatchers/Dynamic/CMakeLists.txt1
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp57
-rw-r--r--unittests/ASTMatchers/Dynamic/RegistryTest.cpp3
-rw-r--r--unittests/Analysis/CMakeLists.txt2
-rw-r--r--unittests/Analysis/ExprMutationAnalyzerTest.cpp1112
-rw-r--r--unittests/Basic/CMakeLists.txt3
-rw-r--r--unittests/Basic/FileManagerTest.cpp98
-rw-r--r--unittests/Basic/FixedPointTest.cpp645
-rw-r--r--unittests/Basic/SourceManagerTest.cpp48
-rw-r--r--unittests/Basic/VirtualFileSystemTest.cpp1431
-rw-r--r--unittests/CMakeLists.txt1
-rw-r--r--unittests/CodeGen/CMakeLists.txt1
-rw-r--r--unittests/CrossTU/CMakeLists.txt1
-rw-r--r--unittests/Driver/DistroTest.cpp60
-rw-r--r--unittests/Driver/ToolChainTest.cpp16
-rw-r--r--unittests/Format/CMakeLists.txt2
-rw-r--r--unittests/Format/FormatTest.cpp411
-rw-r--r--unittests/Format/FormatTestComments.cpp6
-rw-r--r--unittests/Format/FormatTestJS.cpp98
-rw-r--r--unittests/Format/FormatTestJava.cpp25
-rw-r--r--unittests/Format/FormatTestObjC.cpp10
-rw-r--r--unittests/Format/FormatTestProto.cpp12
-rw-r--r--unittests/Format/FormatTestRawStrings.cpp97
-rw-r--r--unittests/Format/FormatTestTableGen.cpp56
-rw-r--r--unittests/Format/FormatTestTextProto.cpp2
-rw-r--r--unittests/Format/SortImportsTestJava.cpp267
-rw-r--r--unittests/Frontend/CMakeLists.txt2
-rw-r--r--unittests/Frontend/FixedPointString.cpp107
-rw-r--r--unittests/Index/CMakeLists.txt19
-rw-r--r--unittests/Index/IndexTests.cpp125
-rw-r--r--unittests/Lex/HeaderSearchTest.cpp4
-rw-r--r--unittests/Lex/PPCallbacksTest.cpp119
-rw-r--r--unittests/Rename/CMakeLists.txt1
-rw-r--r--unittests/Rename/ClangRenameTest.h7
-rw-r--r--unittests/Sema/CMakeLists.txt1
-rw-r--r--unittests/Sema/CodeCompleteTest.cpp258
-rw-r--r--unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp22
-rw-r--r--unittests/StaticAnalyzer/CMakeLists.txt1
-rw-r--r--unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp56
-rw-r--r--unittests/Tooling/CMakeLists.txt2
-rw-r--r--unittests/Tooling/CompilationDatabaseTest.cpp94
-rw-r--r--unittests/Tooling/DiagnosticsYamlTest.cpp58
-rw-r--r--unittests/Tooling/ExecutionTest.cpp9
-rw-r--r--unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp2
-rw-r--r--unittests/Tooling/LookupTest.cpp34
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp4
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp10
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp62
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp51
-rw-r--r--unittests/Tooling/RefactoringActionRulesTest.cpp4
-rw-r--r--unittests/Tooling/RefactoringTest.cpp16
-rw-r--r--unittests/Tooling/ReplacementsYamlTest.cpp6
-rw-r--r--unittests/Tooling/RewriterTestContext.h16
-rw-r--r--unittests/Tooling/TestVisitor.h4
-rw-r--r--unittests/Tooling/ToolingTest.cpp24
-rw-r--r--unittests/libclang/LibclangTest.cpp42
-rwxr-xr-xutils/ABITest/ABITestGen.py149
-rw-r--r--utils/ABITest/Enumeration.py36
-rw-r--r--utils/ABITest/TypeGen.py24
-rwxr-xr-xutils/CIndex/completion_logger_server.py5
-rw-r--r--utils/ClangVisualizers/clang.natvis181
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp275
-rw-r--r--utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp2
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp18
-rw-r--r--utils/TableGen/ClangOptionDocEmitter.cpp6
-rw-r--r--utils/TableGen/ClangSACheckersEmitter.cpp276
-rw-r--r--utils/TableGen/NeonEmitter.cpp43
-rw-r--r--utils/TableGen/TableGen.cpp28
-rw-r--r--utils/TableGen/TableGenBackends.h90
-rwxr-xr-xutils/TestUtils/deep-stack.py17
-rwxr-xr-xutils/analyzer/CmpRuns.py35
-rw-r--r--utils/analyzer/SATestAdd.py17
-rw-r--r--utils/analyzer/SATestBuild.py78
-rwxr-xr-xutils/analyzer/SATestUpdateDiffs.py13
-rw-r--r--utils/analyzer/SumTimerInfo.py29
-rwxr-xr-xutils/analyzer/ubiviz76
-rwxr-xr-xutils/check_cfc/check_cfc.py15
-rwxr-xr-xutils/check_cfc/obj_diff.py8
-rw-r--r--utils/check_cfc/setup.py5
-rwxr-xr-xutils/check_cfc/test_check_cfc.py2
-rwxr-xr-xutils/clangdiag.py4
-rwxr-xr-xutils/hmaptool/hmaptool2
-rw-r--r--utils/modfuzz.py11
-rw-r--r--utils/perf-training/perf-helper.py12
-rwxr-xr-xutils/token-delta.py25
-rw-r--r--www/analyzer/alpha_checks.html562
-rw-r--r--www/analyzer/annotations.html56
-rw-r--r--www/analyzer/available_checks.html303
-rw-r--r--www/analyzer/checker_dev_manual.html37
-rw-r--r--www/analyzer/images/example_cf_returns_retained_gc.pngbin46925 -> 0 bytes
-rw-r--r--www/analyzer/open_projects.html310
-rwxr-xr-xwww/builtins.py2
-rw-r--r--www/clang_video-05-25-2007.html16
-rw-r--r--www/clang_video-07-25-2007.html19
-rw-r--r--www/cxx_dr_status.html314
-rw-r--r--www/cxx_status.html101
-rw-r--r--www/diagnostics.html12
-rw-r--r--www/features.html7
-rw-r--r--www/get_involved.html2
-rw-r--r--www/get_started.html111
-rw-r--r--www/hacking.html7
-rw-r--r--www/index.html20
-rwxr-xr-xwww/make_cxx_dr_status2
-rw-r--r--www/menu.html.incl2
2900 files changed, 285585 insertions, 169241 deletions
diff --git a/.gitignore b/.gitignore
index fc842489a038..3ea38b6e0054 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@
#==============================================================================#
cscope.files
cscope.out
+/tags
#==============================================================================#
# Directories to ignore (do not add trailing '/'s, they skip symlinks).
@@ -35,3 +36,8 @@ docs/_build
docs/analyzer/_build
# debug info testsuite
test/debuginfo-tests
+
+# VS2017 and VSCode config files.
+.vscode
+.vs
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 52b881939499..c2016a45ca6b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.4.3)
+if(POLICY CMP0075)
+ cmake_policy(SET CMP0075 NEW)
+endif()
+
# If we are not building as a part of LLVM, build Clang as an
# standalone project, using LLVM as an external library:
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
@@ -7,9 +11,14 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
# Rely on llvm-config.
set(CONFIG_OUTPUT)
- find_program(LLVM_CONFIG "llvm-config")
if(LLVM_CONFIG)
+ set (LLVM_CONFIG_FOUND 1)
message(STATUS "Found LLVM_CONFIG as ${LLVM_CONFIG}")
+ message(DEPRECATION "Using llvm-config to detect the LLVM installation is \
+ deprecated. The installed cmake files should be used \
+ instead. CMake should be able to detect your LLVM install \
+ automatically, but you can also use LLVM_DIR to specify \
+ the path containing LLVMConfig.cmake.")
set(CONFIG_COMMAND ${LLVM_CONFIG}
"--assertion-mode"
"--bindir"
@@ -32,17 +41,20 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
message(STATUS "${CONFIG_COMMAND_STR}")
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
endif()
- else()
- message(FATAL_ERROR "llvm-config not found -- ${LLVM_CONFIG}")
+
+ list(GET CONFIG_OUTPUT 0 ENABLE_ASSERTIONS)
+ list(GET CONFIG_OUTPUT 1 TOOLS_BINARY_DIR)
+ list(GET CONFIG_OUTPUT 2 LIBRARY_DIR)
+ list(GET CONFIG_OUTPUT 3 INCLUDE_DIR)
+ list(GET CONFIG_OUTPUT 4 LLVM_OBJ_ROOT)
+ list(GET CONFIG_OUTPUT 5 MAIN_SRC_DIR)
+ list(GET CONFIG_OUTPUT 6 LLVM_CONFIG_CMAKE_PATH)
+
+ # Normalize LLVM_CMAKE_PATH. --cmakedir might contain backslashes.
+ # CMake assumes slashes as PATH.
+ file(TO_CMAKE_PATH ${LLVM_CONFIG_CMAKE_PATH} LLVM_CMAKE_PATH)
endif()
- list(GET CONFIG_OUTPUT 0 ENABLE_ASSERTIONS)
- list(GET CONFIG_OUTPUT 1 TOOLS_BINARY_DIR)
- list(GET CONFIG_OUTPUT 2 LIBRARY_DIR)
- list(GET CONFIG_OUTPUT 3 INCLUDE_DIR)
- list(GET CONFIG_OUTPUT 4 LLVM_OBJ_ROOT)
- list(GET CONFIG_OUTPUT 5 MAIN_SRC_DIR)
- list(GET CONFIG_OUTPUT 6 LLVM_CONFIG_CMAKE_PATH)
if(NOT MSVC_IDE)
set(LLVM_ENABLE_ASSERTIONS ${ENABLE_ASSERTIONS}
@@ -51,27 +63,29 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
mark_as_advanced(LLVM_ENABLE_ASSERTIONS)
endif()
+ find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_PATH}")
+ list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR})
+
+ # We can't check LLVM_CONFIG here, because find_package(LLVM ...) also sets
+ # LLVM_CONFIG.
+ if (NOT LLVM_CONFIG_FOUND)
+ # Pull values from LLVMConfig.cmake. We can drop this once the llvm-config
+ # path is removed.
+ set(TOOLS_BINARY_DIR ${LLVM_TOOLS_BINARY_DIR})
+ set(LIBRARY_DIR ${LLVM_LIBRARY_DIR})
+ set(INCLUDE_DIR ${LLVM_INCLUDE_DIR})
+ set(LLVM_OBJ_DIR ${LLVM_BINARY_DIR})
+ endif()
+
set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin")
set(LLVM_LIBRARY_DIR ${LIBRARY_DIR} CACHE PATH "Path to llvm/lib")
set(LLVM_MAIN_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include")
set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
- # Normalize LLVM_CMAKE_PATH. --cmakedir might contain backslashes.
- # CMake assumes slashes as PATH.
- file(TO_CMAKE_PATH ${LLVM_CONFIG_CMAKE_PATH} LLVM_CMAKE_PATH)
-
find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR}
NO_DEFAULT_PATH)
- set(LLVMCONFIG_FILE "${LLVM_CMAKE_PATH}/LLVMConfig.cmake")
- if(EXISTS ${LLVMCONFIG_FILE})
- list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
- include(${LLVMCONFIG_FILE})
- else()
- message(FATAL_ERROR "Not found: ${LLVMCONFIG_FILE}")
- endif()
-
# They are used as destination of target generators.
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin)
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
@@ -89,6 +103,7 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
option(LLVM_FORCE_USE_OLD_HOST_TOOLCHAIN
"Set to ON to force using an old, unsupported host toolchain." OFF)
option(CLANG_ENABLE_BOOTSTRAP "Generate the clang bootstrap target" OFF)
+ option(LLVM_ENABLE_LIBXML2 "Use libxml2 if available." ON)
include(AddLLVM)
include(TableGen)
@@ -184,13 +199,15 @@ endif()
# we can include cmake files from this directory.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
-# Don't look for libxml if we're using MSan, since uninstrumented third party
-# code may call MSan interceptors like strlen, leading to false positives.
-if(NOT LLVM_USE_SANITIZER MATCHES "Memory.*")
- set (LIBXML2_FOUND 0)
- find_package(LibXml2 2.5.3 QUIET)
- if (LIBXML2_FOUND)
- set(CLANG_HAVE_LIBXML 1)
+if(LLVM_ENABLE_LIBXML2)
+ # Don't look for libxml if we're using MSan, since uninstrumented third party
+ # code may call MSan interceptors like strlen, leading to false positives.
+ if(NOT LLVM_USE_SANITIZER MATCHES "Memory.*")
+ set (LIBXML2_FOUND 0)
+ find_package(LibXml2 2.5.3 QUIET)
+ if (LIBXML2_FOUND)
+ set(CLANG_HAVE_LIBXML 1)
+ endif()
endif()
endif()
@@ -279,6 +296,9 @@ endif()
set(CLANG_VENDOR_UTI "org.llvm.clang" CACHE STRING
"Vendor-specific uti.")
+set(CLANG_PYTHON_BINDINGS_VERSIONS "" CACHE STRING
+ "Python versions to install libclang python bindings for")
+
# The libdir suffix must exactly match whatever LLVM's configuration used.
set(CLANG_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}")
@@ -286,25 +306,13 @@ set(CLANG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(CLANG_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE )
- message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite "
-"the makefiles distributed with LLVM. Please create a directory and run cmake "
+ message(FATAL_ERROR "In-source builds are not allowed. "
+"Please create a directory and run cmake "
"from there, passing the path to this source directory as the last argument. "
"This process created the file `CMakeCache.txt' and the directory "
"`CMakeFiles'. Please delete them.")
endif()
-if( NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
- file(GLOB_RECURSE
- tablegenned_files_on_include_dir
- "${CLANG_SOURCE_DIR}/include/clang/*.inc")
- if( tablegenned_files_on_include_dir )
- message(FATAL_ERROR "Apparently there is a previous in-source build, "
-"probably as the result of running `configure' and `make' on "
-"${CLANG_SOURCE_DIR}. This may cause problems. The suspicious files are:\n"
-"${tablegenned_files_on_include_dir}\nPlease clean the source directory.")
- endif()
-endif()
-
# If CLANG_VERSION_* is specified, use it, if not use LLVM_VERSION_*.
if(NOT DEFINED CLANG_VERSION_MAJOR)
set(CLANG_VERSION_MAJOR ${LLVM_VERSION_MAJOR})
@@ -403,22 +411,35 @@ option(CLANG_BUILD_TOOLS
option(CLANG_ENABLE_ARCMT "Build ARCMT." ON)
option(CLANG_ENABLE_STATIC_ANALYZER "Build static analyzer." ON)
-option(CLANG_ANALYZER_BUILD_Z3
- "Build the static analyzer with the Z3 constraint manager." OFF)
+set(CLANG_ANALYZER_Z3_INSTALL_DIR "" CACHE STRING "Install directory of the Z3 solver.")
-option(CLANG_ENABLE_PROTO_FUZZER "Build Clang protobuf fuzzer." OFF)
+find_package(Z3 4.7.1)
-if(NOT CLANG_ENABLE_STATIC_ANALYZER AND (CLANG_ENABLE_ARCMT OR CLANG_ANALYZER_BUILD_Z3))
- message(FATAL_ERROR "Cannot disable static analyzer while enabling ARCMT or Z3")
+if (CLANG_ANALYZER_Z3_INSTALL_DIR)
+ if (NOT Z3_FOUND)
+ message(FATAL_ERROR "Z3 4.7.1 has not been found in CLANG_ANALYZER_Z3_INSTALL_DIR: ${CLANG_ANALYZER_Z3_INSTALL_DIR}.")
+ endif()
endif()
-if(CLANG_ANALYZER_BUILD_Z3)
- find_package(Z3 4.5)
- if(Z3_FOUND)
- set(CLANG_ANALYZER_WITH_Z3 1)
- else()
- message(FATAL_ERROR "Cannot find Z3 header file or shared library")
+set(CLANG_ANALYZER_ENABLE_Z3_SOLVER_DEFAULT "${Z3_FOUND}")
+
+option(CLANG_ANALYZER_ENABLE_Z3_SOLVER
+ "Enable Support for the Z3 constraint solver in the Clang Static Analyzer."
+ ${CLANG_ANALYZER_ENABLE_Z3_SOLVER_DEFAULT}
+)
+
+if (CLANG_ANALYZER_ENABLE_Z3_SOLVER)
+ if (NOT Z3_FOUND)
+ message(FATAL_ERROR "CLANG_ANALYZER_ENABLE_Z3_SOLVER cannot be enabled when Z3 is not available.")
endif()
+
+ set(CLANG_ANALYZER_WITH_Z3 1)
+endif()
+
+option(CLANG_ENABLE_PROTO_FUZZER "Build Clang protobuf fuzzer." OFF)
+
+if(NOT CLANG_ENABLE_STATIC_ANALYZER AND (CLANG_ENABLE_ARCMT OR CLANG_ANALYZER_ENABLE_Z3_SOLVER))
+ message(FATAL_ERROR "Cannot disable static analyzer while enabling ARCMT or Z3")
endif()
if(CLANG_ENABLE_ARCMT)
@@ -494,6 +515,7 @@ if( CLANG_INCLUDE_TESTS )
)
endif()
add_subdirectory(test)
+ add_subdirectory(bindings/python/tests)
if(CLANG_BUILT_STANDALONE)
# Add a global check rule now that all subdirectories have been traversed
@@ -502,11 +524,13 @@ if( CLANG_INCLUDE_TESTS )
get_property(LLVM_LIT_PARAMS GLOBAL PROPERTY LLVM_LIT_PARAMS)
get_property(LLVM_LIT_DEPENDS GLOBAL PROPERTY LLVM_LIT_DEPENDS)
get_property(LLVM_LIT_EXTRA_ARGS GLOBAL PROPERTY LLVM_LIT_EXTRA_ARGS)
+ get_property(LLVM_ADDITIONAL_TEST_TARGETS
+ GLOBAL PROPERTY LLVM_ADDITIONAL_TEST_TARGETS)
add_lit_target(check-all
"Running all regression tests"
${LLVM_LIT_TESTSUITES}
PARAMS ${LLVM_LIT_PARAMS}
- DEPENDS ${LLVM_LIT_DEPENDS}
+ DEPENDS ${LLVM_LIT_DEPENDS} ${LLVM_ADDITIONAL_TEST_TARGETS}
ARGS ${LLVM_LIT_EXTRA_ARGS}
)
endif()
@@ -578,8 +602,8 @@ if (CLANG_ENABLE_BOOTSTRAP)
if(NOT BOOTSTRAP_LLVM_ENABLE_LLD AND LLVM_BINUTILS_INCDIR)
add_dependencies(clang-bootstrap-deps LLVMgold)
endif()
- set(LTO_AR -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar)
- set(LTO_RANLIB -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib)
+ set(${CLANG_STAGE}_AR -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar)
+ set(${CLANG_STAGE}_RANLIB -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib)
endif()
endif()
@@ -645,6 +669,26 @@ if (CLANG_ENABLE_BOOTSTRAP)
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/${C_COMPILER}
-DCMAKE_ASM_COMPILER_ID=Clang)
+ if(BOOTSTRAP_CMAKE_SYSTEM_NAME)
+ set(${CLANG_STAGE}_CONFIG -DLLVM_CONFIG_PATH=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-config)
+ set(${CLANG_STAGE}_TABLEGEN
+ -DLLVM_TABLEGEN=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-tblgen
+ -DCLANG_TABLEGEN=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-tblgen)
+ if(BOOTSTRAP_CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ if(BOOTSTRAP_LLVM_ENABLE_LLD)
+ set(${CLANG_STAGE}_LINKER -DCMAKE_LINKER=${LLVM_RUNTIME_OUTPUT_INTDIR}/ld.lld)
+ endif()
+ if(NOT BOOTSTRAP_LLVM_ENABLE_LTO)
+ add_dependencies(clang-bootstrap-deps llvm-ar llvm-ranlib)
+ set(${CLANG_STAGE}_AR -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar)
+ set(${CLANG_STAGE}_RANLIB -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib)
+ endif()
+ add_dependencies(clang-bootstrap-deps llvm-objcopy llvm-strip)
+ set(${CLANG_STAGE}_OBJCOPY -DCMAKE_OBJCOPY=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objcopy)
+ set(${CLANG_STAGE}_STRIP -DCMAKE_STRIP=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-strip)
+ endif()
+ endif()
+
if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
add_dependencies(clang-bootstrap-deps llvm-profdata)
set(PGO_OPT -DLLVM_PROFDATA=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profdata)
@@ -713,7 +757,14 @@ if (CLANG_ENABLE_BOOTSTRAP)
${PASSTHROUGH_VARIABLES}
-DCLANG_STAGE=${NEXT_CLANG_STAGE}
${COMPILER_OPTIONS}
- ${LTO_LIBRARY} ${LTO_AR} ${LTO_RANLIB} ${verbose} ${PGO_OPT}
+ ${${CLANG_STAGE}_CONFIG}
+ ${${CLANG_STAGE}_TABLEGEN}
+ ${LTO_LIBRARY} ${verbose} ${PGO_OPT}
+ ${${CLANG_STAGE}_LINKER}
+ ${${CLANG_STAGE}_AR}
+ ${${CLANG_STAGE}_RANLIB}
+ ${${CLANG_STAGE}_OBJCOPY}
+ ${${CLANG_STAGE}_STRIP}
INSTALL_COMMAND ""
STEP_TARGETS configure build
USES_TERMINAL_CONFIGURE 1
diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT
index 2fa9f215b66d..faf9575a2898 100644
--- a/CODE_OWNERS.TXT
+++ b/CODE_OWNERS.TXT
@@ -49,6 +49,10 @@ N: John McCall
E: rjmccall@apple.com
D: Clang LLVM IR generation
+N: Brad Smith
+E: brad@comstyle.com
+D: OpenBSD driver
+
N: Richard Smith
E: richard@metafoo.co.uk
D: All parts of Clang not covered by someone else
diff --git a/LICENSE.TXT b/LICENSE.TXT
index 547f6a489382..9e71121218a6 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -4,7 +4,7 @@ LLVM Release License
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:
diff --git a/NOTES.txt b/NOTES.txt
index 53f35a01863a..f06ea8c70cd3 100644
--- a/NOTES.txt
+++ b/NOTES.txt
@@ -10,13 +10,6 @@ This is similar to -Eonly.
//===---------------------------------------------------------------------===//
-Creating and using a PTH file for performance measurement (use a release build).
-
-$ clang -ccc-pch-is-pth -x objective-c-header INPUTS/Cocoa_h.m -o /tmp/tokencache
-$ clang -cc1 -token-cache /tmp/tokencache INPUTS/Cocoa_h.m
-
-//===---------------------------------------------------------------------===//
-
C++ Template Instantiation benchmark:
http://users.rcn.com/abrahams/instantiation_speed/index.html
diff --git a/bindings/python/README.txt b/bindings/python/README.txt
index 8a0bf99b30e3..b0f0142a56f1 100644
--- a/bindings/python/README.txt
+++ b/bindings/python/README.txt
@@ -4,12 +4,12 @@
This directory implements Python bindings for Clang.
-You may need to alter LD_LIBRARY_PATH so that the Clang library can be
+You may need to set CLANG_LIBRARY_PATH so that the Clang library can be
found. The unit tests are designed to be run with any standard test
runner. For example:
--
$ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \
- LD_LIBRARY_PATH=$(llvm-config --libdir) \
+ CLANG_LIBRARY_PATH=$(llvm-config --libdir) \
python -m unittest discover -v
tests.cindex.test_index.test_create ... ok
...
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 56fcc78763e3..8b23ae90b982 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -44,6 +44,7 @@ The major indexing objects are:
Most object information is exposed using properties, when the underlying API
call is efficient.
"""
+from __future__ import absolute_import, division, print_function
# TODO
# ====
@@ -63,10 +64,10 @@ call is efficient.
# o implement additional SourceLocation, SourceRange, and File methods.
from ctypes import *
-import collections
import clang.enumerations
+import os
import sys
if sys.version_info[0] == 3:
# Python 3 strings are unicode, translate them to/from utf8 for C-interop.
@@ -108,8 +109,6 @@ if sys.version_info[0] == 3:
return x
return x.encode('utf8')
- xrange = range
-
elif sys.version_info[0] == 2:
# Python 2 strings are utf8 byte strings, no translation is needed for
# C-interop.
@@ -123,6 +122,22 @@ elif sys.version_info[0] == 2:
def b(x):
return x
+# Importing ABC-s directly from collections is deprecated since Python 3.7,
+# will stop working in Python 3.8.
+# See: https://docs.python.org/dev/whatsnew/3.7.html#id3
+if sys.version_info[:2] >= (3, 7):
+ from collections import abc as collections_abc
+else:
+ import collections as collections_abc
+
+# We only support PathLike objects on Python version with os.fspath present
+# to be consistent with the Python standard library. On older Python versions
+# we only support strings and we have dummy fspath to just pass them through.
+try:
+ fspath = os.fspath
+except AttributeError:
+ def fspath(x):
+ return x
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
# object. This is a problem, because it means that from_parameter will see an
@@ -391,7 +406,7 @@ class Diagnostic(object):
@property
def ranges(self):
- class RangeIterator:
+ class RangeIterator(object):
def __init__(self, diag):
self.diag = diag
@@ -407,7 +422,7 @@ class Diagnostic(object):
@property
def fixits(self):
- class FixItIterator:
+ class FixItIterator(object):
def __init__(self, diag):
self.diag = diag
@@ -427,7 +442,7 @@ class Diagnostic(object):
@property
def children(self):
- class ChildDiagnosticsIterator:
+ class ChildDiagnosticsIterator(object):
def __init__(self, diag):
self.diag_set = conf.lib.clang_getChildDiagnostics(diag)
@@ -547,7 +562,7 @@ class TokenGroup(object):
token_group = TokenGroup(tu, tokens_memory, tokens_count)
- for i in xrange(0, count):
+ for i in range(0, count):
token = Token()
token.int_data = tokens_array[i].int_data
token.ptr_data = tokens_array[i].ptr_data
@@ -2173,7 +2188,7 @@ class Type(Structure):
The returned object is iterable and indexable. Each item in the
container is a Type instance.
"""
- class ArgumentsIterator(collections.Sequence):
+ class ArgumentsIterator(collections_abc.Sequence):
def __init__(self, parent):
self.parent = parent
self.length = None
@@ -2254,6 +2269,12 @@ class Type(Structure):
return res
+ def get_num_template_arguments(self):
+ return conf.lib.clang_Type_getNumTemplateArguments(self)
+
+ def get_template_argument_type(self, num):
+ return conf.lib.clang_Type_getTemplateArgumentAsType(self, num)
+
def get_canonical(self):
"""
Return the canonical type for a Type.
@@ -2460,8 +2481,8 @@ SpellingCache = {
# 20: CompletionChunk.Kind("VerticalSpace")
}
-class CompletionChunk:
- class Kind:
+class CompletionChunk(object):
+ class Kind(object):
def __init__(self, name):
self.name = name
@@ -2548,7 +2569,7 @@ completionChunkKindMap = {
20: CompletionChunk.Kind("VerticalSpace")}
class CompletionString(ClangObject):
- class Availability:
+ class Availability(object):
def __init__(self, name):
self.name = name
@@ -2641,7 +2662,7 @@ class CodeCompletionResults(ClangObject):
@property
def diagnostics(self):
- class DiagnosticsItr:
+ class DiagnosticsItr(object):
def __init__(self, ccr):
self.ccr= ccr
@@ -2746,11 +2767,11 @@ class TranslationUnit(ClangObject):
etc. e.g. ["-Wall", "-I/path/to/include"].
In-memory file content can be provided via unsaved_files. This is an
- iterable of 2-tuples. The first element is the str filename. The
- second element defines the content. Content can be provided as str
- source code or as file objects (anything with a read() method). If
- a file object is being used, content will be read until EOF and the
- read cursor will not be reset to its original position.
+ iterable of 2-tuples. The first element is the filename (str or
+ PathLike). The second element defines the content. Content can be
+ provided as str source code or as file objects (anything with a read()
+ method). If a file object is being used, content will be read until EOF
+ and the read cursor will not be reset to its original position.
options is a bitwise or of TranslationUnit.PARSE_XXX flags which will
control parsing behavior.
@@ -2795,11 +2816,13 @@ class TranslationUnit(ClangObject):
if hasattr(contents, "read"):
contents = contents.read()
- unsaved_array[i].name = b(name)
+ unsaved_array[i].name = b(fspath(name))
unsaved_array[i].contents = b(contents)
unsaved_array[i].length = len(contents)
- ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array,
+ ptr = conf.lib.clang_parseTranslationUnit(index,
+ fspath(filename) if filename is not None else None,
+ args_array,
len(args), unsaved_array,
len(unsaved_files), options)
@@ -2820,11 +2843,13 @@ class TranslationUnit(ClangObject):
index is optional and is the Index instance to use. If not provided,
a default Index will be created.
+
+ filename can be str or PathLike.
"""
if index is None:
index = Index.create()
- ptr = conf.lib.clang_createTranslationUnit(index, filename)
+ ptr = conf.lib.clang_createTranslationUnit(index, fspath(filename))
if not ptr:
raise TranslationUnitLoadError(filename)
@@ -2939,7 +2964,7 @@ class TranslationUnit(ClangObject):
"""
Return an iterable (and indexable) object containing the diagnostics.
"""
- class DiagIterator:
+ class DiagIterator(object):
def __init__(self, tu):
self.tu = tu
@@ -2977,7 +3002,7 @@ class TranslationUnit(ClangObject):
print(value)
if not isinstance(value, str):
raise TypeError('Unexpected unsaved file contents.')
- unsaved_files_array[i].name = name
+ unsaved_files_array[i].name = fspath(name)
unsaved_files_array[i].contents = value
unsaved_files_array[i].length = len(value)
ptr = conf.lib.clang_reparseTranslationUnit(self, len(unsaved_files),
@@ -2996,10 +3021,10 @@ class TranslationUnit(ClangObject):
case, the reason(s) why should be available via
TranslationUnit.diagnostics().
- filename -- The path to save the translation unit to.
+ filename -- The path to save the translation unit to (str or PathLike).
"""
options = conf.lib.clang_defaultSaveOptions(self)
- result = int(conf.lib.clang_saveTranslationUnit(self, filename,
+ result = int(conf.lib.clang_saveTranslationUnit(self, fspath(filename),
options))
if result != 0:
raise TranslationUnitSaveError(result,
@@ -3041,10 +3066,10 @@ class TranslationUnit(ClangObject):
print(value)
if not isinstance(value, str):
raise TypeError('Unexpected unsaved file contents.')
- unsaved_files_array[i].name = b(name)
+ unsaved_files_array[i].name = b(fspath(name))
unsaved_files_array[i].contents = b(value)
unsaved_files_array[i].length = len(value)
- ptr = conf.lib.clang_codeCompleteAt(self, path, line, column,
+ ptr = conf.lib.clang_codeCompleteAt(self, fspath(path), line, column,
unsaved_files_array, len(unsaved_files), options)
if ptr:
return CodeCompletionResults(ptr)
@@ -3072,7 +3097,7 @@ class File(ClangObject):
@staticmethod
def from_name(translation_unit, file_name):
"""Retrieve a file handle within the given translation unit."""
- return File(conf.lib.clang_getFile(translation_unit, file_name))
+ return File(conf.lib.clang_getFile(translation_unit, fspath(file_name)))
@property
def name(self):
@@ -3171,7 +3196,7 @@ class CompileCommand(object):
Invariant : the first argument is the compiler executable
"""
length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd)
- for i in xrange(length):
+ for i in range(length):
yield conf.lib.clang_CompileCommand_getArg(self.cmd, i)
class CompileCommands(object):
@@ -3223,7 +3248,7 @@ class CompilationDatabase(ClangObject):
"""Builds a CompilationDatabase from the database found in buildDir"""
errorCode = c_uint()
try:
- cdb = conf.lib.clang_CompilationDatabase_fromDirectory(buildDir,
+ cdb = conf.lib.clang_CompilationDatabase_fromDirectory(fspath(buildDir),
byref(errorCode))
except CompilationDatabaseError as e:
raise CompilationDatabaseError(int(errorCode.value),
@@ -3236,7 +3261,7 @@ class CompilationDatabase(ClangObject):
build filename. Returns None if filename is not found in the database.
"""
return conf.lib.clang_CompilationDatabase_getCompileCommands(self,
- filename)
+ fspath(filename))
def getAllCompileCommands(self):
"""
@@ -3999,6 +4024,15 @@ functionList = [
Type,
Type.from_result),
+ ("clang_Type_getNumTemplateArguments",
+ [Type],
+ c_int),
+
+ ("clang_Type_getTemplateArgumentAsType",
+ [Type, c_uint],
+ Type,
+ Type.from_result),
+
("clang_Type_getOffsetOf",
[Type, c_interop_string],
c_longlong),
@@ -4062,7 +4096,7 @@ def register_functions(lib, ignore_errors):
for f in functionList:
register(f)
-class Config:
+class Config(object):
library_path = None
library_file = None
compatibility_check = True
@@ -4075,7 +4109,7 @@ class Config:
raise Exception("library path must be set before before using " \
"any other functionalities in libclang.")
- Config.library_path = path
+ Config.library_path = fspath(path)
@staticmethod
def set_library_file(filename):
@@ -4084,7 +4118,7 @@ class Config:
raise Exception("library file must be set before before using " \
"any other functionalities in libclang.")
- Config.library_file = filename
+ Config.library_file = fspath(filename)
@staticmethod
def set_compatibility_check(check_status):
diff --git a/bindings/python/examples/cindex/cindex-dump.py b/bindings/python/examples/cindex/cindex-dump.py
index 5556ad121a3e..acec7e0e0054 100644
--- a/bindings/python/examples/cindex/cindex-dump.py
+++ b/bindings/python/examples/cindex/cindex-dump.py
@@ -79,7 +79,7 @@ def main():
if not tu:
parser.error("unable to load input")
- pprint(('diags', map(get_diag_info, tu.diagnostics)))
+ pprint(('diags', [get_diag_info(d) for d in tu.diagnostics]))
pprint(('nodes', get_info(tu.cursor)))
if __name__ == '__main__':
diff --git a/bindings/python/tests/CMakeLists.txt b/bindings/python/tests/CMakeLists.txt
new file mode 100644
index 000000000000..7af6503f1588
--- /dev/null
+++ b/bindings/python/tests/CMakeLists.txt
@@ -0,0 +1,46 @@
+# Test target to run Python test suite from main build.
+
+add_custom_target(check-clang-python
+ COMMAND ${CMAKE_COMMAND} -E env
+ CLANG_LIBRARY_PATH=$<TARGET_FILE_DIR:libclang>
+ ${PYTHON_EXECUTABLE} -m unittest discover
+ DEPENDS libclang
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+set(RUN_PYTHON_TESTS TRUE)
+set_target_properties(check-clang-python PROPERTIES FOLDER "Clang tests")
+
+# Tests require libclang.so which is only built with LLVM_ENABLE_PIC=ON
+if(NOT LLVM_ENABLE_PIC)
+ set(RUN_PYTHON_TESTS FALSE)
+endif()
+
+# Do not try to run if libclang was built with ASan because
+# the sanitizer library will likely be loaded too late to perform
+# interception and will then fail.
+# We could use LD_PRELOAD/DYLD_INSERT_LIBRARIES but this isn't
+# portable so its easier just to not run the tests when building
+# with ASan.
+list(FIND LLVM_USE_SANITIZER "Address" LLVM_USE_ASAN_INDEX)
+if(NOT LLVM_USE_ASAN_INDEX EQUAL -1)
+ set(RUN_PYTHON_TESTS FALSE)
+endif()
+
+# Tests fail on Windows, and need someone knowledgeable to fix.
+# It's not clear whether it's a test or a valid binding problem.
+if(WIN32)
+ set(RUN_PYTHON_TESTS FALSE)
+endif()
+
+# AArch64 and Hexagon have known test failures that need to be
+# addressed.
+# SystemZ has broken Python/FFI interface:
+# https://reviews.llvm.org/D52840#1265716
+if(${LLVM_NATIVE_ARCH} MATCHES "^(AArch64|Hexagon|SystemZ)$")
+ set(RUN_PYTHON_TESTS FALSE)
+endif()
+
+if(RUN_PYTHON_TESTS)
+ set_property(GLOBAL APPEND PROPERTY
+ LLVM_ADDITIONAL_TEST_TARGETS check-clang-python)
+endif()
diff --git a/bindings/python/tests/cindex/test_access_specifiers.py b/bindings/python/tests/cindex/test_access_specifiers.py
index 2f6144be082c..e36424f240aa 100644
--- a/bindings/python/tests/cindex/test_access_specifiers.py
+++ b/bindings/python/tests/cindex/test_access_specifiers.py
@@ -1,3 +1,7 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
from clang.cindex import AccessSpecifier
from clang.cindex import Cursor
diff --git a/bindings/python/tests/cindex/test_cdb.py b/bindings/python/tests/cindex/test_cdb.py
index 64651af31732..589fc72856bd 100644
--- a/bindings/python/tests/cindex/test_cdb.py
+++ b/bindings/python/tests/cindex/test_cdb.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import CompilationDatabase
from clang.cindex import CompilationDatabaseError
from clang.cindex import CompileCommands
@@ -6,6 +11,8 @@ import os
import gc
import unittest
import sys
+from .util import skip_if_no_fspath
+from .util import str_to_path
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
@@ -26,17 +33,19 @@ class TestCDB(unittest.TestCase):
"""Check we can load a compilation database"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
- def test_lookup_fail(self):
- """Check file lookup failure"""
- cdb = CompilationDatabase.fromDirectory(kInputsDir)
- self.assertIsNone(cdb.getCompileCommands('file_do_not_exist.cpp'))
-
def test_lookup_succeed(self):
"""Check we get some results if the file exists in the db"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp')
self.assertNotEqual(len(cmds), 0)
+ @skip_if_no_fspath
+ def test_lookup_succeed_pathlike(self):
+ """Same as test_lookup_succeed, but with PathLikes"""
+ cdb = CompilationDatabase.fromDirectory(str_to_path(kInputsDir))
+ cmds = cdb.getCompileCommands(str_to_path('/home/john.doe/MyProject/project.cpp'))
+ self.assertNotEqual(len(cmds), 0)
+
def test_all_compilecommand(self):
"""Check we get all results from the db"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
diff --git a/bindings/python/tests/cindex/test_code_completion.py b/bindings/python/tests/cindex/test_code_completion.py
index a56bb304cd71..e0b41577aeb3 100644
--- a/bindings/python/tests/cindex/test_code_completion.py
+++ b/bindings/python/tests/cindex/test_code_completion.py
@@ -1,6 +1,13 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import TranslationUnit
import unittest
+from .util import skip_if_no_fspath
+from .util import str_to_path
class TestCodeCompletion(unittest.TestCase):
@@ -38,6 +45,32 @@ void f() {
]
self.check_completion_results(cr, expected)
+ @skip_if_no_fspath
+ def test_code_complete_pathlike(self):
+ files = [(str_to_path('fake.c'), """
+/// Aaa.
+int test1;
+
+/// Bbb.
+void test2(void);
+
+void f() {
+
+}
+""")]
+
+ tu = TranslationUnit.from_source(str_to_path('fake.c'), ['-std=c99'], unsaved_files=files,
+ options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION)
+
+ cr = tu.codeComplete(str_to_path('fake.c'), 9, 1, unsaved_files=files, include_brief_comments=True)
+
+ expected = [
+ "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.",
+ "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.",
+ "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None"
+ ]
+ self.check_completion_results(cr, expected)
+
def test_code_complete_availability(self):
files = [('fake.cpp', """
class P {
@@ -61,11 +94,11 @@ void f(P x, Q y) {
cr = tu.codeComplete('fake.cpp', 12, 5, unsaved_files=files)
expected = [
- "{'const', TypedText} || Priority: 40 || Availability: Available || Brief comment: None",
- "{'volatile', TypedText} || Priority: 40 || Availability: Available || Brief comment: None",
+ "{'const', TypedText} || Priority: 50 || Availability: Available || Brief comment: None",
+ "{'volatile', TypedText} || Priority: 50 || Availability: Available || Brief comment: None",
"{'operator', TypedText} || Priority: 40 || Availability: Available || Brief comment: None",
- "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None",
- "{'Q', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None"
+ "{'P', TypedText} || Priority: 50 || Availability: Available || Brief comment: None",
+ "{'Q', TypedText} || Priority: 50 || Availability: Available || Brief comment: None"
]
self.check_completion_results(cr, expected)
diff --git a/bindings/python/tests/cindex/test_comment.py b/bindings/python/tests/cindex/test_comment.py
index d6c6d8e5c5b0..73fb617ae168 100644
--- a/bindings/python/tests/cindex/test_comment.py
+++ b/bindings/python/tests/cindex/test_comment.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import TranslationUnit
from tests.cindex.util import get_cursor
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
index f5733fd15879..ef875e972474 100644
--- a/bindings/python/tests/cindex/test_cursor.py
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
import ctypes
import gc
import unittest
diff --git a/bindings/python/tests/cindex/test_cursor_kind.py b/bindings/python/tests/cindex/test_cursor_kind.py
index f1ee753ef8b1..e6b9558b3cc1 100644
--- a/bindings/python/tests/cindex/test_cursor_kind.py
+++ b/bindings/python/tests/cindex/test_cursor_kind.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import CursorKind
import unittest
diff --git a/bindings/python/tests/cindex/test_diagnostics.py b/bindings/python/tests/cindex/test_diagnostics.py
index 78b327daa72c..c17d5b28efe9 100644
--- a/bindings/python/tests/cindex/test_diagnostics.py
+++ b/bindings/python/tests/cindex/test_diagnostics.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import *
from .util import get_tu
@@ -46,7 +51,7 @@ class TestDiagnostics(unittest.TestCase):
self.assertEqual(tu.diagnostics[0].fixits[0].value, '.f0 = ')
def test_diagnostic_range(self):
- tu = get_tu('void f() { int i = "a" + 1; }')
+ tu = get_tu('void f() { int i = "a"; }')
self.assertEqual(len(tu.diagnostics), 1)
self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning)
self.assertEqual(tu.diagnostics[0].location.line, 1)
@@ -58,7 +63,7 @@ class TestDiagnostics(unittest.TestCase):
self.assertEqual(tu.diagnostics[0].ranges[0].start.line, 1)
self.assertEqual(tu.diagnostics[0].ranges[0].start.column, 20)
self.assertEqual(tu.diagnostics[0].ranges[0].end.line, 1)
- self.assertEqual(tu.diagnostics[0].ranges[0].end.column, 27)
+ self.assertEqual(tu.diagnostics[0].ranges[0].end.column, 23)
with self.assertRaises(IndexError):
tu.diagnostics[0].ranges[1].start.line
diff --git a/bindings/python/tests/cindex/test_exception_specification_kind.py b/bindings/python/tests/cindex/test_exception_specification_kind.py
index 80b3639a8ab3..6c13f70fb256 100644
--- a/bindings/python/tests/cindex/test_exception_specification_kind.py
+++ b/bindings/python/tests/cindex/test_exception_specification_kind.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
import clang.cindex
from clang.cindex import ExceptionSpecificationKind
from .util import get_tu
diff --git a/bindings/python/tests/cindex/test_file.py b/bindings/python/tests/cindex/test_file.py
index 98f6575262cc..a146fe5c9239 100644
--- a/bindings/python/tests/cindex/test_file.py
+++ b/bindings/python/tests/cindex/test_file.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import Index, File
import unittest
diff --git a/bindings/python/tests/cindex/test_index.py b/bindings/python/tests/cindex/test_index.py
index cfdf98e628ac..46aafcf222e7 100644
--- a/bindings/python/tests/cindex/test_index.py
+++ b/bindings/python/tests/cindex/test_index.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import *
import os
import unittest
diff --git a/bindings/python/tests/cindex/test_linkage.py b/bindings/python/tests/cindex/test_linkage.py
index 6b482f8081b3..cdd97fc2df0d 100644
--- a/bindings/python/tests/cindex/test_linkage.py
+++ b/bindings/python/tests/cindex/test_linkage.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import LinkageKind
from clang.cindex import Cursor
from clang.cindex import TranslationUnit
diff --git a/bindings/python/tests/cindex/test_location.py b/bindings/python/tests/cindex/test_location.py
index cbc32deb4bd5..fbe9770d7ebc 100644
--- a/bindings/python/tests/cindex/test_location.py
+++ b/bindings/python/tests/cindex/test_location.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import Cursor
from clang.cindex import File
from clang.cindex import SourceLocation
diff --git a/bindings/python/tests/cindex/test_tls_kind.py b/bindings/python/tests/cindex/test_tls_kind.py
index fbc3418a64ef..c828ac83a468 100644
--- a/bindings/python/tests/cindex/test_tls_kind.py
+++ b/bindings/python/tests/cindex/test_tls_kind.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import TLSKind
from clang.cindex import Cursor
from clang.cindex import TranslationUnit
diff --git a/bindings/python/tests/cindex/test_token_kind.py b/bindings/python/tests/cindex/test_token_kind.py
index 700f95a64624..904e007cafc5 100644
--- a/bindings/python/tests/cindex/test_token_kind.py
+++ b/bindings/python/tests/cindex/test_token_kind.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import TokenKind
import unittest
diff --git a/bindings/python/tests/cindex/test_tokens.py b/bindings/python/tests/cindex/test_tokens.py
index c93353dc9da2..dd6d3a3259ed 100644
--- a/bindings/python/tests/cindex/test_tokens.py
+++ b/bindings/python/tests/cindex/test_tokens.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from clang.cindex import CursorKind
from clang.cindex import Index
from clang.cindex import SourceLocation
diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py
index d3ee535f4d0d..f3e770a93611 100644
--- a/bindings/python/tests/cindex/test_translation_unit.py
+++ b/bindings/python/tests/cindex/test_translation_unit.py
@@ -1,6 +1,12 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
from contextlib import contextmanager
import gc
import os
+import sys
import tempfile
import unittest
@@ -15,6 +21,8 @@ from clang.cindex import TranslationUnitLoadError
from clang.cindex import TranslationUnit
from .util import get_cursor
from .util import get_tu
+from .util import skip_if_no_fspath
+from .util import str_to_path
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
@@ -31,6 +39,17 @@ def save_tu(tu):
yield t.name
+@contextmanager
+def save_tu_pathlike(tu):
+ """Convenience API to save a TranslationUnit to a file.
+
+ Returns the filename it was saved to.
+ """
+ with tempfile.NamedTemporaryFile() as t:
+ tu.save(str_to_path(t.name))
+ yield t.name
+
+
class TestTranslationUnit(unittest.TestCase):
def test_spelling(self):
path = os.path.join(kInputsDir, 'hello.cpp')
@@ -75,15 +94,31 @@ int SOME_DEFINE;
self.assertEqual(spellings[-1], 'y')
def test_unsaved_files_2(self):
- try:
- from StringIO import StringIO
- except:
+ if sys.version_info.major >= 3:
from io import StringIO
+ else:
+ from io import BytesIO as StringIO
tu = TranslationUnit.from_source('fake.c', unsaved_files = [
('fake.c', StringIO('int x;'))])
spellings = [c.spelling for c in tu.cursor.get_children()]
self.assertEqual(spellings[-1], 'x')
+ @skip_if_no_fspath
+ def test_from_source_accepts_pathlike(self):
+ tu = TranslationUnit.from_source(str_to_path('fake.c'), ['-Iincludes'], unsaved_files = [
+ (str_to_path('fake.c'), """
+#include "fake.h"
+ int x;
+ int SOME_DEFINE;
+ """),
+ (str_to_path('includes/fake.h'), """
+#define SOME_DEFINE y
+ """)
+ ])
+ spellings = [c.spelling for c in tu.cursor.get_children()]
+ self.assertEqual(spellings[-2], 'x')
+ self.assertEqual(spellings[-1], 'y')
+
def assert_normpaths_equal(self, path1, path2):
""" Compares two paths for equality after normalizing them with
os.path.normpath
@@ -130,6 +165,16 @@ int SOME_DEFINE;
self.assertTrue(os.path.exists(path))
self.assertGreater(os.path.getsize(path), 0)
+ @skip_if_no_fspath
+ def test_save_pathlike(self):
+ """Ensure TranslationUnit.save() works with PathLike filename."""
+
+ tu = get_tu('int foo();')
+
+ with save_tu_pathlike(tu) as path:
+ self.assertTrue(os.path.exists(path))
+ self.assertGreater(os.path.getsize(path), 0)
+
def test_save_translation_errors(self):
"""Ensure that saving to an invalid directory raises."""
@@ -162,6 +207,22 @@ int SOME_DEFINE;
# Just in case there is an open file descriptor somewhere.
del tu2
+ @skip_if_no_fspath
+ def test_load_pathlike(self):
+ """Ensure TranslationUnits can be constructed from saved files -
+ PathLike variant."""
+ tu = get_tu('int foo();')
+ self.assertEqual(len(tu.diagnostics), 0)
+ with save_tu(tu) as path:
+ tu2 = TranslationUnit.from_ast_file(filename=str_to_path(path))
+ self.assertEqual(len(tu2.diagnostics), 0)
+
+ foo = get_cursor(tu2, 'foo')
+ self.assertIsNotNone(foo)
+
+ # Just in case there is an open file descriptor somewhere.
+ del tu2
+
def test_index_parse(self):
path = os.path.join(kInputsDir, 'hello.cpp')
index = Index.create()
@@ -180,6 +241,19 @@ int SOME_DEFINE;
with self.assertRaises(Exception):
f = tu.get_file('foobar.cpp')
+ @skip_if_no_fspath
+ def test_get_file_pathlike(self):
+ """Ensure tu.get_file() works appropriately with PathLike filenames."""
+
+ tu = get_tu('int foo();')
+
+ f = tu.get_file(str_to_path('t.c'))
+ self.assertIsInstance(f, File)
+ self.assertEqual(f.name, 't.c')
+
+ with self.assertRaises(Exception):
+ f = tu.get_file(str_to_path('foobar.cpp'))
+
def test_get_source_location(self):
"""Ensure tu.get_source_location() works."""
diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py
index 4dec0583c7b0..bcdbeff9d99c 100644
--- a/bindings/python/tests/cindex/test_type.py
+++ b/bindings/python/tests/cindex/test_type.py
@@ -1,3 +1,8 @@
+import os
+from clang.cindex import Config
+if 'CLANG_LIBRARY_PATH' in os.environ:
+ Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
+
import gc
import unittest
@@ -436,3 +441,28 @@ class TestType(unittest.TestCase):
self.assertIsNotNone(testInteger, "Could not find testInteger.")
self.assertEqual(testInteger.type.get_address_space(), 2)
+
+ def test_template_arguments(self):
+ source = """
+ class Foo {
+ };
+ template <typename T>
+ class Template {
+ };
+ Template<Foo> instance;
+ int bar;
+ """
+ tu = get_tu(source, lang='cpp')
+
+ # Varible with a template argument.
+ cursor = get_cursor(tu, 'instance')
+ cursor_type = cursor.type
+ self.assertEqual(cursor.kind, CursorKind.VAR_DECL)
+ self.assertEqual(cursor_type.spelling, 'Template<Foo>')
+ self.assertEqual(cursor_type.get_num_template_arguments(), 1)
+ template_type = cursor_type.get_template_argument_type(0)
+ self.assertEqual(template_type.spelling, 'Foo')
+
+ # Variable without a template argument.
+ cursor = get_cursor(tu, 'bar')
+ self.assertEqual(cursor.get_num_template_arguments(), -1)
diff --git a/bindings/python/tests/cindex/util.py b/bindings/python/tests/cindex/util.py
index c53ba7c81bde..57e17941c558 100644
--- a/bindings/python/tests/cindex/util.py
+++ b/bindings/python/tests/cindex/util.py
@@ -1,5 +1,15 @@
# This file provides common utility functions for the test suite.
+import os
+HAS_FSPATH = hasattr(os, 'fspath')
+
+if HAS_FSPATH:
+ from pathlib import Path as str_to_path
+else:
+ str_to_path = None
+
+import unittest
+
from clang.cindex import Cursor
from clang.cindex import TranslationUnit
@@ -68,8 +78,13 @@ def get_cursors(source, spelling):
return cursors
+skip_if_no_fspath = unittest.skipUnless(HAS_FSPATH,
+ "Requires file system path protocol / Python 3.6+")
+
__all__ = [
'get_cursor',
'get_cursors',
'get_tu',
+ 'skip_if_no_fspath',
+ 'str_to_path',
]
diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake
index 28e179513475..8708231a6af1 100644
--- a/cmake/caches/Fuchsia-stage2.cmake
+++ b/cmake/caches/Fuchsia-stage2.cmake
@@ -1,29 +1,33 @@
-# This file sets up a CMakeCache for the second stage of a Fuchsia toolchain
-# build.
+# This file sets up a CMakeCache for the second stage of a Fuchsia toolchain build.
set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "")
set(PACKAGE_VENDOR Fuchsia CACHE STRING "")
-set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
-set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
+if(NOT APPLE)
+ set(LLVM_ENABLE_LLD ON CACHE BOOL "")
+endif()
+set(LLVM_ENABLE_LTO ON CACHE BOOL "")
+set(LLVM_ENABLE_MODULES ON CACHE BOOL "")
set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "")
set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "")
set(LLVM_ENABLE_ZLIB ON CACHE BOOL "")
set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "")
-set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
+set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
+set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
-set(LLVM_ENABLE_LTO ON CACHE BOOL "")
+set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "")
if(NOT APPLE)
- set(LLVM_ENABLE_LLD ON CACHE BOOL "")
set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "")
endif()
-set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "")
set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "")
+set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
+
+set(ENABLE_LINKER_BUILD_ID ON CACHE BOOL "")
+set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "")
-set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
@@ -31,39 +35,50 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRIN
if(APPLE)
list(APPEND BUILTIN_TARGETS "default")
list(APPEND RUNTIME_TARGETS "default")
-elseif(UNIX)
- foreach(target i386;x86_64;armhf;aarch64)
- if(LINUX_${target}_SYSROOT)
- # Set the per-target builtins options.
- list(APPEND BUILTIN_TARGETS "${target}-linux-gnu")
- set(BUILTINS_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
- set(BUILTINS_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "")
- set(BUILTINS_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "")
-
- # Set the per-target runtimes options.
- list(APPEND RUNTIME_TARGETS "${target}-linux-gnu")
- set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
- set(RUNTIMES_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "")
- set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "")
- set(RUNTIMES_${target}-linux-gnu_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_SANITIZER_CXX_ABI "libc++" CACHE STRING "")
- set(RUNTIMES_${target}-linux-gnu_SANITIZER_CXX_ABI_INTREE ON CACHE BOOL "")
- set(RUNTIMES_${target}-linux-gnu_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "")
- endif()
- endforeach()
+
+ set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "")
+ set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "")
+ set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "")
endif()
+foreach(target aarch64-linux-gnu;armv7-linux-gnueabihf;i386-linux-gnu;x86_64-linux-gnu)
+ if(LINUX_${target}_SYSROOT)
+ # Set the per-target builtins options.
+ list(APPEND BUILTIN_TARGETS "${target}")
+ set(BUILTINS_${target}_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
+ set(BUILTINS_${target}_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(BUILTINS_${target}_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "")
+ set(BUILTINS_${target}_CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
+ set(BUILTINS_${target}_CMAKE_MODULE_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
+ set(BUILTINS_${target}_CMAKE_EXE_LINKER_FLAG "-fuse-ld=lld" CACHE STRING "")
+
+ # Set the per-target runtimes options.
+ list(APPEND RUNTIME_TARGETS "${target}")
+ set(RUNTIMES_${target}_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_MODULE_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
+ set(RUNTIMES_${target}_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_ABI_VERSION 2 CACHE STRING "")
+ set(RUNTIMES_${target}_SANITIZER_CXX_ABI "libc++" CACHE STRING "")
+ set(RUNTIMES_${target}_SANITIZER_CXX_ABI_INTREE ON CACHE BOOL "")
+ set(RUNTIMES_${target}_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "")
+ endif()
+endforeach()
+
if(FUCHSIA_SDK)
set(FUCHSIA_aarch64_NAME arm64)
set(FUCHSIA_x86_64_NAME x64)
@@ -78,25 +93,25 @@ if(FUCHSIA_SDK)
list(APPEND BUILTIN_TARGETS "${target}-fuchsia")
set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
set(BUILTINS_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "")
- set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
- set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
- set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
- set(BUILTINS_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
- set(BUILTINS_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
- set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "")
+ set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "")
set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
# Set the per-target runtimes options.
list(APPEND RUNTIME_TARGETS "${target}-fuchsia")
set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE STRING "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
- set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "")
+ set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE STRING "")
set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "")
set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
@@ -109,6 +124,8 @@ if(FUCHSIA_SDK)
set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
set(RUNTIMES_${target}-fuchsia_LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXX_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "")
+ set(RUNTIMES_${target}-fuchsia_LIBCXX_ABI_VERSION 2 CACHE STRING "")
endforeach()
set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "")
@@ -127,6 +144,7 @@ set(LLVM_TOOLCHAIN_TOOLS
llvm-cov
llvm-cxxfilt
llvm-dwarfdump
+ llvm-dwp
llvm-lib
llvm-nm
llvm-objcopy
@@ -138,6 +156,7 @@ set(LLVM_TOOLCHAIN_TOOLS
llvm-size
llvm-strip
llvm-symbolizer
+ llvm-xray
opt
sancov
CACHE STRING "")
@@ -147,6 +166,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS
libclang
lld
LTO
+ clang-apply-replacements
clang-format
clang-headers
clang-include-fixer
diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake
index fc7dae849935..e4a130ecfcfe 100644
--- a/cmake/caches/Fuchsia.cmake
+++ b/cmake/caches/Fuchsia.cmake
@@ -1,29 +1,29 @@
# This file sets up a CMakeCache for a Fuchsia toolchain build.
-set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
+set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "")
set(PACKAGE_VENDOR Fuchsia CACHE STRING "")
-set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
-set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "")
-set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "")
set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "")
set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "")
-set(CLANG_INCLUDE_TESTS OFF CACHE BOOL "")
-set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
-
-set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
-set(CMAKE_BUILD_TYPE Release CACHE STRING "")
+set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
+set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
-set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "")
+set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "")
if(NOT APPLE)
- set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "")
+ set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
+ set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "")
endif()
-
-set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "")
set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "")
+set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
+
+set(ENABLE_LINKER_BUILD_ID ON CACHE BOOL "")
+set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "")
+
+set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
+set(CMAKE_BUILD_TYPE Release CACHE STRING "")
if(APPLE)
set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "")
@@ -43,18 +43,57 @@ elseif(UNIX)
set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
endif()
+if(BOOTSTRAP_CMAKE_SYSTEM_NAME)
+ set(target "${BOOTSTRAP_CMAKE_CXX_COMPILER_TARGET}")
+ if(STAGE2_LINUX_${target}_SYSROOT)
+ set(BUILTINS_${target}_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
+ set(BUILTINS_${target}_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(BUILTINS_${target}_CMAKE_SYSROOT ${STAGE2_LINUX_${target}_SYSROOT} CACHE STRING "")
+ set(LLVM_BUILTIN_TARGETS "${target}" CACHE STRING "")
+
+ set(RUNTIMES_${target}_CMAKE_SYSTEM_NAME Linux CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_BUILD_TYPE Release CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_SYSROOT ${STAGE2_LINUX_${target}_SYSROOT} CACHE STRING "")
+ set(RUNTIMES_${target}_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
+ set(RUNTIMES_${target}_LIBCXX_ABI_VERSION 2 CACHE STRING "")
+ set(RUNTIMES_${target}_SANITIZER_CXX_ABI "libc++" CACHE STRING "")
+ set(RUNTIMES_${target}_SANITIZER_CXX_ABI_INTREE ON CACHE BOOL "")
+ set(RUNTIMES_${target}_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "")
+ set(LLVM_RUNTIME_TARGETS "${target}" CACHE STRING "")
+ endif()
+endif()
+
+set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "")
+if(NOT APPLE)
+ set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "")
+endif()
+
set(CLANG_BOOTSTRAP_TARGETS
check-all
check-llvm
check-clang
+ check-lld
llvm-config
test-suite
test-depends
llvm-test-depends
clang-test-depends
+ lld-test-depends
distribution
install-distribution
install-distribution-stripped
+ install-distribution-toolchain
clang CACHE STRING "")
get_cmake_property(variableNames VARIABLES)
diff --git a/cmake/modules/AddClang.cmake b/cmake/modules/AddClang.cmake
index c09a8423f9f6..7e22f16f365b 100644
--- a/cmake/modules/AddClang.cmake
+++ b/cmake/modules/AddClang.cmake
@@ -131,6 +131,7 @@ macro(add_clang_tool name)
endif()
add_clang_executable(${name} ${ARGN})
+ add_dependencies(${name} clang-headers)
if (CLANG_BUILD_TOOLS)
if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
diff --git a/cmake/modules/FindZ3.cmake b/cmake/modules/FindZ3.cmake
index 779ef928da1b..7a224f789ec1 100644
--- a/cmake/modules/FindZ3.cmake
+++ b/cmake/modules/FindZ3.cmake
@@ -1,13 +1,36 @@
+# Looking for Z3 in CLANG_ANALYZER_Z3_INSTALL_DIR
find_path(Z3_INCLUDE_DIR NAMES z3.h
+ NO_DEFAULT_PATH
+ PATHS ${CLANG_ANALYZER_Z3_INSTALL_DIR}/include
PATH_SUFFIXES libz3 z3
)
find_library(Z3_LIBRARIES NAMES z3 libz3
+ NO_DEFAULT_PATH
+ PATHS ${CLANG_ANALYZER_Z3_INSTALL_DIR}
+ PATH_SUFFIXES lib bin
)
-find_program(Z3_EXECUTABLE z3)
+find_program(Z3_EXECUTABLE z3
+ NO_DEFAULT_PATH
+ PATHS ${CLANG_ANALYZER_Z3_INSTALL_DIR}
+ PATH_SUFFIXES bin
+ )
+
+# If Z3 has not been found in CLANG_ANALYZER_Z3_INSTALL_DIR look in the default directories
+find_path(Z3_INCLUDE_DIR NAMES z3.h
+ PATH_SUFFIXES libz3 z3
+ )
+
+find_library(Z3_LIBRARIES NAMES z3 libz3
+ PATH_SUFFIXES lib bin
+ )
+
+find_program(Z3_EXECUTABLE z3
+ PATH_SUFFIXES bin
+ )
-if(Z3_INCLUDE_DIR AND Z3_EXECUTABLE)
+if(Z3_INCLUDE_DIR AND Z3_LIBRARIES AND Z3_EXECUTABLE)
execute_process (COMMAND ${Z3_EXECUTABLE} -version
OUTPUT_VARIABLE libz3_version_str
ERROR_QUIET
diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst
index 7549159a39ab..67ef59b5ea2a 100644
--- a/docs/AddressSanitizer.rst
+++ b/docs/AddressSanitizer.rst
@@ -24,7 +24,7 @@ Typical slowdown introduced by AddressSanitizer is **2x**.
How to build
============
-Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
+Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.
Usage
=====
@@ -265,7 +265,7 @@ Limitations
* On 64-bit platforms AddressSanitizer maps (but not reserves) 16+ Terabytes of
virtual address space. This means that tools like ``ulimit`` may not work as
usually expected.
-* Static linking is not supported.
+* Static linking of executables is not supported.
Supported Platforms
===================
@@ -278,6 +278,7 @@ AddressSanitizer is supported on:
* Android ARM
* NetBSD i386/x86\_64
* FreeBSD i386/x86\_64 (tested on FreeBSD 11-current)
+* Windows 8.1+ (i386/x86\_64)
Ports to various other platforms are in progress.
@@ -288,6 +289,9 @@ AddressSanitizer is fully functional on supported platforms starting from LLVM
3.1. The test suite is integrated into CMake build and can be run with ``make
check-asan`` command.
+The Windows port is functional and is used by Chrome and Firefox, but it is not
+as well supported as the other ports.
+
More Information
================
diff --git a/docs/AutomaticReferenceCounting.rst b/docs/AutomaticReferenceCounting.rst
index bf4d0945672a..3e51d2f5d79e 100644
--- a/docs/AutomaticReferenceCounting.rst
+++ b/docs/AutomaticReferenceCounting.rst
@@ -1734,20 +1734,78 @@ A program is ill-formed if it refers to the ``NSAutoreleasePool`` class.
rest of the language. Not draining the pool during an unwind is apparently
required by the Objective-C exceptions implementation.
+.. _arc.misc.externally_retained:
+
+Externally-Retained Variables
+-----------------------------
+
+In some situations, variables with strong ownership are considered
+externally-retained by the implementation. This means that the variable is
+retained elsewhere, and therefore the implementation can elide retaining and
+releasing its value. Such a variable is implicitly ``const`` for safety. In
+contrast with ``__unsafe_unretained``, an externally-retained variable still
+behaves as a strong variable outside of initialization and destruction. For
+instance, when an externally-retained variable is captured in a block the value
+of the variable is retained and released on block capture and destruction. It
+also affects C++ features such as lambda capture, ``decltype``, and template
+argument deduction.
+
+Implicitly, the implementation assumes that the :ref:`self parameter in a
+non-init method <arc.misc.self>` and the :ref:`variable in a for-in loop
+<arc.misc.enumeration>` are externally-retained.
+
+Externally-retained semantics can also be opted into with the
+``objc_externally_retained`` attribute. This attribute can apply to strong local
+variables, functions, methods, or blocks:
+
+.. code-block:: objc
+
+ @class WobbleAmount;
+
+ @interface Widget : NSObject
+ -(void)wobble:(WobbleAmount *)amount;
+ @end
+
+ @implementation Widget
+
+ -(void)wobble:(WobbleAmount *)amount
+ __attribute__((objc_externally_retained)) {
+ // 'amount' and 'alias' aren't retained on entry, nor released on exit.
+ __attribute__((objc_externally_retained)) WobbleAmount *alias = amount;
+ }
+ @end
+
+Annotating a function with this attribute makes every parameter with strong
+retainable object pointer type externally-retained, unless the variable was
+explicitly qualified with ``__strong``. For instance, ``first_param`` is
+externally-retained (and therefore ``const``) below, but not ``second_param``:
+
+.. code-block:: objc
+
+ __attribute__((objc_externally_retained))
+ void f(NSArray *first_param, __strong NSArray *second_param) {
+ // ...
+ }
+
+You can test if your compiler has support for ``objc_externally_retained`` with
+``__has_attribute``:
+
+.. code-block:: objc
+
+ #if __has_attribute(objc_externally_retained)
+ // Use externally retained...
+ #endif
+
.. _arc.misc.self:
``self``
--------
-The ``self`` parameter variable of an Objective-C method is never actually
-retained by the implementation. It is undefined behavior, or at least
-dangerous, to cause an object to be deallocated during a message send to that
-object.
-
-To make this safe, for Objective-C instance methods ``self`` is implicitly
-``const`` unless the method is in the :ref:`init family
-<arc.family.semantics.init>`. Further, ``self`` is **always** implicitly
-``const`` within a class method.
+The ``self`` parameter variable of an non-init Objective-C method is considered
+:ref:`externally-retained <arc.misc.externally_retained>` by the implementation.
+It is undefined behavior, or at least dangerous, to cause an object to be
+deallocated during a message send to that object. In an init method, ``self``
+follows the :ref:``init family rules <arc.family.semantics.init>``.
.. admonition:: Rationale
@@ -1758,9 +1816,9 @@ To make this safe, for Objective-C instance methods ``self`` is implicitly
without this retain and release. Since it's extremely uncommon to actually
do so, even unintentionally, and since there's no natural way for the
programmer to remove this retain/release pair otherwise (as there is for
- other parameters by, say, making the variable ``__unsafe_unretained``), we
- chose to make this optimizing assumption and shift some amount of risk to the
- user.
+ other parameters by, say, making the variable ``objc_externally_retained`` or
+ qualifying it with ``__unsafe_unretained``), we chose to make this optimizing
+ assumption and shift some amount of risk to the user.
.. _arc.misc.enumeration:
@@ -1769,8 +1827,9 @@ Fast enumeration iteration variables
If a variable is declared in the condition of an Objective-C fast enumeration
loop, and the variable has no explicit ownership qualifier, then it is
-qualified with ``const __strong`` and objects encountered during the
-enumeration are not actually retained.
+implicitly :ref:`externally-retained <arc.misc.externally_retained>` so that
+objects encountered during the enumeration are not actually retained and
+released.
.. admonition:: Rationale
@@ -2284,8 +2343,8 @@ block exactly as if it had been sent the ``retain`` message.
.. _arc.runtime.objc_storeStrong:
-``id objc_storeStrong(id *object, id value);``
-----------------------------------------------
+``void objc_storeStrong(id *object, id value);``
+------------------------------------------------
*Precondition:* ``object`` is a valid pointer to a ``__strong`` object which is
adequately aligned for a pointer. ``value`` is null or a pointer to a valid
diff --git a/docs/Block-ABI-Apple.txt b/docs/Block-ABI-Apple.txt
index 94a4d18e08f0..1b04cc9e133c 100644
--- a/docs/Block-ABI-Apple.txt
+++ b/docs/Block-ABI-Apple.txt
@@ -1 +1 @@
-*NOTE* This document has moved to http://clang.llvm.org/docs/Block-ABI-Apple.html.
+*NOTE* This document has moved to https://clang.llvm.org/docs/Block-ABI-Apple.html.
diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst
index 5c15482cb251..e852c3e38798 100644
--- a/docs/ClangCommandLineReference.rst
+++ b/docs/ClangCommandLineReference.rst
@@ -36,7 +36,7 @@ Treat source input files as Objective-C inputs
Treat source input files as Objective-C++ inputs
-.. option:: -Qn
+.. option:: -Qn, -fno-ident
Do not emit metadata containing compiler name and version
@@ -44,7 +44,7 @@ Do not emit metadata containing compiler name and version
Don't emit warning for unused driver arguments
-.. option:: -Qy
+.. option:: -Qy, -fident
Emit metadata containing compiler name and version
@@ -158,7 +158,7 @@ Compile CUDA code for host only. Has no effect on non-CUDA compilations.
.. option:: --cuda-include-ptx=<arg>, --no-cuda-include-ptx=<arg>
-Include PTX for the follwing GPU architecture (e.g. sm\_35) or 'all'. May be specified more than once.
+Include PTX for the following GPU architecture (e.g. sm\_35) or 'all'. May be specified more than once.
.. option:: --cuda-noopt-device-debug, --no-cuda-noopt-device-debug
@@ -214,9 +214,13 @@ Flush denormal floating point values to zero in CUDA device mode.
Generate relocatable device code, also known as separate compilation mode.
+.. option:: -fcuda-short-ptr, -fno-cuda-short-ptr
+
+Use 32-bit pointers for accessing const/local/shared address spaces.
+
.. option:: -ffixed-r19
-Reserve the r19 register (Hexagon only)
+Reserve register r19 (Hexagon only)
.. option:: -fheinous-gnu-extensions
@@ -260,6 +264,10 @@ Display available options
Display help for hidden options
+.. option:: --hip-link
+
+Link clang-offload-bundler bundles for HIP
+
.. option:: -image\_base <arg>
.. option:: -index-header-map
@@ -452,6 +460,10 @@ Use pipes between commands, when possible
.. option:: --print-diagnostic-categories
+.. option:: -print-effective-triple, --print-effective-triple
+
+Print the effective target triple
+
.. option:: -print-file-name=<file>, --print-file-name=<file>, --print-file-name <arg>
Print the full library path of <file>
@@ -480,6 +492,10 @@ Print the resource directory pathname
Print the paths used for finding libraries and programs
+.. option:: -print-target-triple, --print-target-triple
+
+Print the normalized target triple
+
.. option:: -private\_bundle
.. option:: -pthread, -no-pthread
@@ -558,6 +574,8 @@ Serialize compiler diagnostics to a file
.. option:: -shared-libsan, -shared-libasan
+Dynamically link the sanitizer runtime
+
.. option:: -single\_module
.. option:: -specs=<arg>, --specs=<arg>
@@ -568,6 +586,8 @@ Serialize compiler diagnostics to a file
.. option:: -static-libsan
+Statically link the sanitizer runtime
+
.. option:: -static-libstdc++
.. option:: -std-default=<arg>
@@ -712,6 +732,12 @@ Attempt to match the ABI of Clang <version>
Treat each comma separated argument in <arg> as a documentation comment block command
+.. option:: -fcomplete-member-pointers, -fno-complete-member-pointers
+
+Require member pointer base types to be complete if they would be significant under the Microsoft ABI
+
+.. option:: -fcrash-diagnostics-dir=<arg>
+
.. option:: -fdeclspec, -fno-declspec
Allow \_\_declspec as a keyword
@@ -746,7 +772,7 @@ Enables an experimental new pass manager in LLVM.
.. option:: -ffine-grained-bitfield-accesses, -fno-fine-grained-bitfield-accesses
-Use separate accesses for bitfields with legal widths and alignments.
+Use separate accesses for consecutive bitfield runs with legal widths and alignments.
.. option:: -finline-functions, -fno-inline-functions
@@ -766,6 +792,16 @@ Don't use blacklist file for sanitizers
.. option:: -fparse-all-comments
+.. option:: -frecord-command-line, -frecord-gcc-switches, -fno-record-command-line, -fno-record-gcc-switches
+
+Generate a section named ".GCC.command.line" containing the clang driver
+command-line. After linking, the section may contain multiple command lines,
+which will be individually terminated by null bytes. Separate arguments within
+a command line are combined with spaces; spaces and backslashes within an
+argument are escaped with backslashes. This format differs from the format of
+the equivalent section produced by GCC with the -frecord-gcc-switches flag.
+This option is currently only supported on ELF targets.
+
.. option:: -fsanitize-address-field-padding=<arg>
Level of field padding for AddressSanitizer
@@ -774,9 +810,15 @@ Level of field padding for AddressSanitizer
Enable linker dead stripping of globals in AddressSanitizer
-.. option:: -fsanitize-address-poison-class-member-array-new-cookie, -fno-sanitize-address-poison-class-member-array-new-cookie
+.. option:: -fsanitize-address-use-odr-indicator, -fno-sanitize-address-use-odr-indicator
+
+Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size
-Enable poisoning array cookies when using class member operator new\[\] in AddressSanitizer
+.. option:: -fsanitize-address-poison-custom-array-cookie, -fno-sanitize-address-poison-custom-array-cookie
+
+Enable "poisoning" array cookies when allocating arrays with a custom operator new\[\] in Address Sanitizer, preventing accesses to the cookies from user code. An array cookie is a small implementation-defined header added to certain array allocations to record metadata such as the length of the array. Accesses to array cookies from user code are technically allowed by the standard but are more likely to be the result of an out-of-bounds array access.
+
+An operator new\[\] is "custom" if it is not one of the allocation functions provided by the C++ standard library. Array cookies from non-custom allocation functions are always poisoned.
.. option:: -fsanitize-address-use-after-scope, -fno-sanitize-address-use-after-scope
@@ -854,6 +896,10 @@ Strip (or keep only, if negative) a given number of path components when emittin
Turn on runtime checks for various forms of undefined or suspicious behavior. See user manual for available checks
+.. option:: -moutline, -mno-outline
+
+Enable function outlining (AArch64 only)
+
.. option:: --param <arg>, --param=<arg>
.. option:: -std=<arg>, --std=<arg>, --std <arg>
@@ -1151,6 +1197,10 @@ Target-independent compilation options
.. option:: -faccess-control, -fno-access-control
+.. option:: -faddrsig, -fno-addrsig
+
+Emit an address-significance table
+
.. option:: -falign-functions, -fno-align-functions
.. program:: clang1
@@ -1223,12 +1273,20 @@ Accept non-standard constructs supported by the Borland compiler
Load the clang builtins module map file.
+.. option:: -fc++-static-destructors, -fno-c++-static-destructors
+
+Enable C++ static destructor registration (the default)
+
.. option:: -fcaret-diagnostics, -fno-caret-diagnostics
.. option:: -fcf-protection=<arg>, -fcf-protection (equivalent to -fcf-protection=full)
Instrument control-flow architecture protection. Options: return, branch, full, none.
+.. option:: -fchar8\_t, -fno-char8\_t
+
+Enable C++ builtin type char8\_t
+
.. option:: -fclasspath=<arg>, --CLASSPATH <arg>, --CLASSPATH=<arg>, --classpath <arg>, --classpath=<arg>
.. option:: -fcolor-diagnostics, -fno-color-diagnostics
@@ -1293,6 +1351,10 @@ Place debug types in their own section (ELF Only)
Parse templated function definitions at the end of the translation unit
+.. option:: -fdelete-null-pointer-checks, -fno-delete-null-pointer-checks
+
+Treat usage of null pointers as undefined behavior.
+
.. option:: -fdenormal-fp-math=<arg>
.. option:: -fdiagnostics-absolute-paths
@@ -1325,6 +1387,10 @@ Print option name with mappable diagnostics
Print a template comparison tree for differing templates
+.. option:: -fdigraphs, -fno-digraphs
+
+Enable alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:' (default)
+
.. option:: -fdollars-in-identifiers, -fno-dollars-in-identifiers
Allow '$' in identifiers
@@ -1375,8 +1441,16 @@ Allow aggressive, lossy floating-point optimizations
.. option:: -ffinite-math-only, -fno-finite-math-only
+.. option:: -ffixed-point, -fno-fixed-point
+
+Enable fixed point types
+
.. option:: -ffor-scope, -fno-for-scope
+.. option:: -fforce-emit-vtables, -fno-force-emit-vtables
+
+Emits more virtual tables to improve devirtualization
+
.. option:: -fforce-enable-int128, -fno-force-enable-int128
Enable support for int128\_t type
@@ -1439,6 +1513,10 @@ Enable the integrated assembler
.. option:: -fjump-tables, -fno-jump-tables
+.. option:: -fkeep-static-consts
+
+Keep static const variables even if unused
+
.. option:: -flax-vector-conversions, -fno-lax-vector-conversions
.. option:: -flimited-precision=<arg>
@@ -1543,14 +1621,6 @@ Specifies the largest alignment guaranteed by '::operator new(size\_t)'
Disable implicit builtin knowledge of a specific function
-.. option:: -fdelete-null-pointer-checks, -fno-delete-null-pointer-checks
-
-When enabled, treat null pointer dereference, creation of a reference to null,
-or passing a null pointer to a function parameter annotated with the "nonnull"
-attribute as undefined behavior. (And, thus the optimizer may assume that any
-pointer used in such a way must not have been null and optimize away the
-branches accordingly.) On by default.
-
.. option:: -fno-elide-type
Do not elide types when printing diagnostics
@@ -1834,6 +1904,10 @@ Emit full debug info for all types used by the program
Enable optimizations based on the strict definition of an enum's value range
+.. option:: -fstrict-float-cast-overflow, -fno-strict-float-cast-overflow
+
+Assume that overflowing float-to-int casts are undefined (default)
+
.. option:: -fstrict-overflow, -fno-strict-overflow
.. option:: -fstrict-return, -fno-strict-return
@@ -1942,12 +2016,6 @@ Set the default symbol visibility for all global declarations
Enables whole-program vtable optimization. Requires -flto
-.. option:: -fforce-emit-vtables, -fno-force-emit-vtables
-
-In order to improve devirtualization, forces emitting of vtables even in
-modules where it isn't necessary. It causes more inline virtual functions
-to be emitted.
-
.. option:: -fwrapv, -fno-wrapv
Treat signed integer overflow as two's complement
@@ -2078,12 +2146,6 @@ Put objects of at most <size> bytes into small data section (MIPS / Hexagon)
.. option:: -mabi=<arg>
-.. option:: -mabicalls, -mno-abicalls
-
-Enable SVR4-style position-independent code (Mips only)
-
-.. option:: -mabs=<arg>
-
.. option:: -malign-double
Align doubles to two words in structs (x86 only)
@@ -2096,25 +2158,19 @@ Align doubles to two words in structs (x86 only)
Link stack frames through backchain on System Z
-.. option:: -mcheck-zero-division, -mno-check-zero-division
-
.. option:: -mcmodel=<arg>
-.. option:: -mcompact-branches=<arg>
-
.. option:: -mconsole<arg>
-.. option:: -mcpu=<arg>, -mv4 (equivalent to -mcpu=hexagonv4), -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65)
+.. option:: -mcpu=<arg>, -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65)
-.. option:: -mdefault-build-attributes<arg>, -mno-default-build-attributes<arg>
+.. option:: -mcrc, -mno-crc
-.. option:: -mdll<arg>
+Allow use of CRC instructions (ARM/Mips only)
-.. option:: -mdouble-float
-
-.. option:: -mdsp, -mno-dsp
+.. option:: -mdefault-build-attributes<arg>, -mno-default-build-attributes<arg>
-.. option:: -mdspr2, -mno-dspr2
+.. option:: -mdll<arg>
.. option:: -mdynamic-no-pic<arg>
@@ -2122,28 +2178,12 @@ Link stack frames through backchain on System Z
Set EABI type, e.g. 4, 5 or gnu (default depends on triple)
-.. option:: -membedded-data, -mno-embedded-data
-
-Place constants in the .rodata section instead of the .sdata section even if they meet the -G <size> threshold (MIPS)
-
-.. option:: -mextern-sdata, -mno-extern-sdata
-
-Assume that externally defined data is in the small data if it meets the -G <size> threshold (MIPS)
-
.. option:: -mfentry
Insert calls to fentry at function entry (x86 only)
.. option:: -mfloat-abi=<arg>
-.. option:: -mfp32
-
-Use 32-bit floating point registers (MIPS only)
-
-.. option:: -mfp64
-
-Use 64-bit floating point registers (MIPS only)
-
.. option:: -mfpmath=<arg>
.. option:: -mfpu=<arg>
@@ -2152,10 +2192,6 @@ Use 64-bit floating point registers (MIPS only)
Enable merging of globals
-.. option:: -mgpopt, -mno-gpopt
-
-Use GP relative accesses for symbols known to be in a small data section (MIPS)
-
.. option:: -mhard-float
.. option:: -mhwdiv=<arg>, --mhwdiv <arg>, --mhwdiv=<arg>
@@ -2172,22 +2208,10 @@ Use Intel MCU ABI
(integrated-as) Emit an object file which can be used with an incremental linker
-.. option:: -mindirect-jump=<arg>
-
-Change indirect jump instructions to inhibit speculation
-
.. option:: -miphoneos-version-min=<arg>, -mios-version-min=<arg>
-.. option:: -mips16
-
.. option:: -mkernel
-.. option:: -mldc1-sdc1, -mno-ldc1-sdc1
-
-.. option:: -mlocal-sdata, -mno-local-sdata
-
-Extend the -G behaviour to object local data (MIPS)
-
.. option:: -mlong-calls, -mno-long-calls
Generate branches with extended addressability, usually via indirect jumps.
@@ -2196,30 +2220,12 @@ Generate branches with extended addressability, usually via indirect jumps.
Set Mac OS X deployment target
-.. option:: -mmadd4, -mno-madd4
-
-Enable the generation of 4-operand madd.s, madd.d and related instructions.
-
.. option:: -mmcu=<arg>
-.. option:: -mmicromips, -mno-micromips
-
.. option:: -mms-bitfields, -mno-ms-bitfields
Set the default structure layout to be compatible with the Microsoft compiler standard
-.. option:: -mmsa, -mno-msa
-
-Enable MSA ASE (MIPS only)
-
-.. option:: -mmt, -mno-mt
-
-Enable MT ASE (MIPS only)
-
-.. option:: -mnan=<arg>
-
-.. option:: -mno-mips16
-
.. option:: -momit-leaf-frame-pointer, -mno-omit-leaf-frame-pointer
Omit frame pointer setup for leaf functions
@@ -2252,11 +2258,15 @@ Enable hexagon-qdsp6 backward compatibility
(integrated-as) Relax all machine instructions
+.. option:: -mretpoline, -mno-retpoline
+
.. option:: -mrtd, -mno-rtd
Make StdCall calling convention the default
-.. option:: -msingle-float
+.. option:: -msign-return-address=<arg>
+
+Select return address signing scope
.. option:: -msoft-float, -mno-soft-float
@@ -2302,10 +2312,36 @@ The thread model to use, e.g. posix, single (posix by default)
.. option:: -mx32
-.. option:: -mxgot, -mno-xgot
-
AARCH64
-------
+.. option:: -ffixed-x1
+
+Reserve the x1 register (AArch64 only)
+
+.. option:: -ffixed-x2
+
+Reserve the x2 register (AArch64 only)
+
+.. option:: -ffixed-x3
+
+Reserve the x3 register (AArch64 only)
+
+.. option:: -ffixed-x4
+
+Reserve the x4 register (AArch64 only)
+
+.. option:: -ffixed-x5
+
+Reserve the x5 register (AArch64 only)
+
+.. option:: -ffixed-x6
+
+Reserve the x6 register (AArch64 only)
+
+.. option:: -ffixed-x7
+
+Reserve the x7 register (AArch64 only)
+
.. option:: -ffixed-x18
Reserve the x18 register (AArch64 only)
@@ -2314,6 +2350,42 @@ Reserve the x18 register (AArch64 only)
Reserve the x20 register (AArch64 only)
+.. option:: -fcall-saved-x8
+
+Make the x8 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x9
+
+Make the x9 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x10
+
+Make the x10 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x11
+
+Make the x11 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x12
+
+Make the x12 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x13
+
+Make the x13 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x14
+
+Make the x14 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x15
+
+Make the x15 register call-saved (AArch64 only)
+
+.. option:: -fcall-saved-x18
+
+Make the x18 register call-saved (AArch64 only)
+
.. option:: -mfix-cortex-a53-835769, -mno-fix-cortex-a53-835769
Workaround Cortex-A53 erratum 835769 (AArch64 only)
@@ -2334,10 +2406,6 @@ ARM
Reserve the r9 register (ARM only)
-.. option:: -mcrc
-
-Allow use of CRC instructions (ARM only)
-
.. option:: -mexecute-only, -mno-execute-only, -mpure-code
Disallow generation of data access to code sections (ARM only)
@@ -2370,6 +2438,18 @@ Hexagon
-------
.. option:: -mieee-rnd-near
+.. option:: -mmemops, -mno-memops
+
+Enable generation of memop instructions
+
+.. option:: -mnvj, -mno-nvj
+
+Enable generation of new-value jumps
+
+.. option:: -mnvs, -mno-nvs
+
+Enable generation of new-value stores
+
.. option:: -mpackets, -mno-packets
Enable generation of instruction packets
@@ -2390,6 +2470,82 @@ Set Hexagon Vector Length
Enable Hexagon Vector eXtensions
+MIPS
+----
+.. option:: -mabicalls, -mno-abicalls
+
+Enable SVR4-style position-independent code (Mips only)
+
+.. option:: -mabs=<arg>
+
+.. option:: -mcheck-zero-division, -mno-check-zero-division
+
+.. option:: -mcompact-branches=<arg>
+
+.. option:: -mdouble-float
+
+.. option:: -mdsp, -mno-dsp
+
+.. option:: -mdspr2, -mno-dspr2
+
+.. option:: -membedded-data, -mno-embedded-data
+
+Place constants in the .rodata section instead of the .sdata section even if they meet the -G <size> threshold (MIPS)
+
+.. option:: -mextern-sdata, -mno-extern-sdata
+
+Assume that externally defined data is in the small data if it meets the -G <size> threshold (MIPS)
+
+.. option:: -mfp32
+
+Use 32-bit floating point registers (MIPS only)
+
+.. option:: -mfp64
+
+Use 64-bit floating point registers (MIPS only)
+
+.. option:: -mginv, -mno-ginv
+
+.. option:: -mgpopt, -mno-gpopt
+
+Use GP relative accesses for symbols known to be in a small data section (MIPS)
+
+.. option:: -mindirect-jump=<arg>
+
+Change indirect jump instructions to inhibit speculation
+
+.. option:: -mips16
+
+.. option:: -mldc1-sdc1, -mno-ldc1-sdc1
+
+.. option:: -mlocal-sdata, -mno-local-sdata
+
+Extend the -G behaviour to object local data (MIPS)
+
+.. option:: -mmadd4, -mno-madd4
+
+Enable the generation of 4-operand madd.s, madd.d and related instructions.
+
+.. option:: -mmicromips, -mno-micromips
+
+.. option:: -mmsa, -mno-msa
+
+Enable MSA ASE (MIPS only)
+
+.. option:: -mmt, -mno-mt
+
+Enable MT ASE (MIPS only)
+
+.. option:: -mnan=<arg>
+
+.. option:: -mno-mips16
+
+.. option:: -msingle-float
+
+.. option:: -mvirt, -mno-virt
+
+.. option:: -mxgot, -mno-xgot
+
PowerPC
-------
.. option:: -maltivec, -mno-altivec
@@ -2504,6 +2660,8 @@ X86
.. option:: -mgfni, -mno-gfni
+.. option:: -minvpcid, -mno-invpcid
+
.. option:: -mlwp, -mno-lwp
.. option:: -mlzcnt, -mno-lzcnt
@@ -2512,16 +2670,18 @@ X86
.. option:: -mmovbe, -mno-movbe
-.. option:: -mmovdiri, -mno-movdiri
-
.. option:: -mmovdir64b, -mno-movdir64b
+.. option:: -mmovdiri, -mno-movdiri
+
.. option:: -mmpx, -mno-mpx
.. option:: -mmwaitx, -mno-mwaitx
.. option:: -mpclmul, -mno-pclmul
+.. option:: -mpconfig, -mno-pconfig
+
.. option:: -mpku, -mno-pku
.. option:: -mpopcnt, -mno-popcnt
@@ -2530,14 +2690,14 @@ X86
.. option:: -mprfchw, -mno-prfchw
+.. option:: -mptwrite, -mno-ptwrite
+
.. option:: -mrdpid, -mno-rdpid
.. option:: -mrdrnd, -mno-rdrnd
.. option:: -mrdseed, -mno-rdseed
-.. option:: -mretpoline, -mno-retpoline
-
.. option:: -mretpoline-external-thunk, -mno-retpoline-external-thunk
.. option:: -mrtm, -mno-rtm
@@ -2588,6 +2748,12 @@ X86
.. option:: -mxsaves, -mno-xsaves
+RISCV
+-----
+.. option:: -mrelax, -mno-relax
+
+Enable linker relaxation
+
Optimization level
~~~~~~~~~~~~~~~~~~
@@ -2671,9 +2837,11 @@ Debug information flags
Embed source text in DWARF debug sections
-.. option:: -ggnu-pubnames
+.. option:: -ggnu-pubnames, -gno-gnu-pubnames
-.. option:: -grecord-gcc-switches, -gno-record-gcc-switches
+.. option:: -gpubnames, -gno-pubnames
+
+.. option:: -grecord-command-line, -grecord-gcc-switches, -gno-record-command-line, -gno-record-gcc-switches
.. option:: -gsplit-dwarf
@@ -2886,6 +3054,14 @@ Pass <arg> to the linker
.. option:: -filelist <arg>
+.. option:: --hip-device-lib-path=<arg>
+
+HIP device library path
+
+.. option:: --hip-device-lib=<arg>
+
+HIP device library
+
.. option:: -l<arg>
.. option:: -r
diff --git a/docs/ClangFormat.rst b/docs/ClangFormat.rst
index f53c02ae90d7..f2228c57505b 100644
--- a/docs/ClangFormat.rst
+++ b/docs/ClangFormat.rst
@@ -169,7 +169,7 @@ Visual Studio Integration
=========================
Download the latest Visual Studio extension from the `alpha build site
-<http://llvm.org/builds/>`_. The default key-binding is Ctrl-R,Ctrl-F.
+<https://llvm.org/builds/>`_. The default key-binding is Ctrl-R,Ctrl-F.
Script for patch reformatting
@@ -200,6 +200,12 @@ So to reformat all the lines in the latest :program:`git` commit, just do:
git diff -U0 --no-color HEAD^ | clang-format-diff.py -i -p1
+With Mercurial/:program:`hg`:
+
+.. code-block:: console
+
+ hg diff -U0 --color=never | clang-format-diff.py -i -p1
+
In an SVN client, you can do:
.. code-block:: console
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index 49f9f68088bc..054d5c32c6f2 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -108,7 +108,7 @@ Configuring Style in Code
When using ``clang::format::reformat(...)`` functions, the format is specified
by supplying the `clang::format::FormatStyle
-<http://clang.llvm.org/doxygen/structclang_1_1format_1_1FormatStyle.html>`_
+<https://clang.llvm.org/doxygen/structclang_1_1format_1_1FormatStyle.html>`_
structure.
@@ -131,7 +131,7 @@ the configuration (without a prefix: ``Auto``).
* ``LLVM``
A style complying with the `LLVM coding standards
- <http://llvm.org/docs/CodingStandards.html>`_
+ <https://llvm.org/docs/CodingStandards.html>`_
* ``Google``
A style complying with `Google's C++ style guide
<http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml>`_
@@ -908,20 +908,17 @@ the configuration (without a prefix: ``Auto``).
try {
foo();
- } catch () {
+ }
+ catch () {
}
void foo() { bar(); }
- class foo
- {
+ class foo {
};
if (foo()) {
- } else {
}
- enum X : int
- {
- A,
- B
- };
+ else {
+ }
+ enum X : int { A, B };
* ``BS_Allman`` (in configuration: ``Allman``)
Always break before braces.
@@ -1134,21 +1131,17 @@ the configuration (without a prefix: ``Auto``).
.. code-block:: c++
true:
- FitsOnOneLine::Constructor()
- : aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}
-
- DoesntFit::Constructor()
- : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),
- aaaaaaaaaaaaa(aaaaaaaaaaaaaa),
- aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}
+ SomeClass::Constructor()
+ : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) {
+ return 0;
+ }
false:
- FitsOnOneLine::Constructor()
- : aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}
-
- DoesntFit::Constructor()
- : aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaa(aaaaaaaaaaaaaa),
- aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}
+ SomeClass::Constructor()
+ : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa),
+ aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) {
+ return 0;
+ }
**ConstructorInitializerIndentWidth** (``unsigned``)
The number of characters to use for indentation of constructor
@@ -1297,7 +1290,7 @@ the configuration (without a prefix: ``Auto``).
If none of the regular expressions match, INT_MAX is assigned as
category. The main header for a source file automatically gets category 0.
so that it is generally kept at the beginning of the ``#includes``
- (http://llvm.org/docs/CodingStandards.html#include-style). However, you
+ (https://llvm.org/docs/CodingStandards.html#include-style). However, you
can also assign negative priorities if you have certain headers that
always need to be first.
@@ -1402,6 +1395,39 @@ the configuration (without a prefix: ``Auto``).
LoooooooooooooooooooooooooooooooooooooooongReturnType
LoooooooooooooooooooooooooooooooongFunctionDeclaration();
+**JavaImportGroups** (``std::vector<std::string>``)
+ A vector of prefixes ordered by the desired groups for Java imports.
+
+ Each group is separated by a newline. Static imports will also follow the
+ same grouping convention above all non-static imports. One group's prefix
+ can be a subset of another - the longest prefix is always matched. Within
+ a group, the imports are ordered lexicographically.
+
+ In the .clang-format configuration file, this can be configured like
+ in the following yaml example. This will result in imports being
+ formatted as in the Java example below.
+
+ .. code-block:: yaml
+
+ JavaImportGroups: ['com.example', 'com', 'org']
+
+
+ .. code-block:: java
+
+ import static com.example.function1;
+
+ import static com.test.function2;
+
+ import static org.example.function3;
+
+ import com.example.ClassA;
+ import com.example.Test;
+ import com.example.a.ClassB;
+
+ import com.test.ClassC;
+
+ import org.example.ClassD;
+
**JavaScriptQuotes** (``JavaScriptQuoteStyle``)
The JavaScriptQuoteStyle to use for JavaScript strings.
@@ -1979,6 +2005,16 @@ the configuration (without a prefix: ``Auto``).
+**StatementMacros** (``std::vector<std::string>``)
+ A vector of macros that should be interpreted as complete
+ statements.
+
+ Typical macros are expressions, and require a semi-colon to be
+ added; sometimes this is not the case, and this allows to make
+ clang-format aware of such cases.
+
+ For example: Q_UNUSED
+
**TabWidth** (``unsigned``)
The number of columns used for tab stops.
diff --git a/docs/ClangPlugins.rst b/docs/ClangPlugins.rst
index 833f0dd39f77..5e6082e90340 100644
--- a/docs/ClangPlugins.rst
+++ b/docs/ClangPlugins.rst
@@ -69,7 +69,7 @@ Putting it all together
Let's look at an example plugin that prints top-level function names. This
example is checked into the clang repository; please take a look at
the `latest version of PrintFunctionNames.cpp
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/PrintFunctionNames.cpp?view=markup>`_.
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/PrintFunctionNames.cpp?view=markup>`_.
Running the plugin
==================
@@ -110,7 +110,7 @@ source tree:
-plugin -Xclang print-fns
Also see the print-function-name plugin example's
-`README <http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/README.txt?view=markup>`_
+`README <https://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/README.txt?view=markup>`_
Using the clang command line
diff --git a/docs/ClangTools.rst b/docs/ClangTools.rst
index e371596b240c..99e8a5e4f685 100644
--- a/docs/ClangTools.rst
+++ b/docs/ClangTools.rst
@@ -19,12 +19,12 @@ LLVM/Clang checkout:
- With Subversion:
- ``cd llvm/tools/clang/tools``
- - ``svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra``
+ - ``svn co https://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra``
- Or with Git:
- ``cd llvm/tools/clang/tools``
- - ``git clone http://llvm.org/git/clang-tools-extra.git extra``
+ - ``git clone https://llvm.org/git/clang-tools-extra.git extra``
This document describes a high-level overview of the organization of
Clang Tools within the project as well as giving an introduction to some
@@ -105,7 +105,7 @@ provide its own user-focused documentation.
``clang-tidy``
--------------
-`clang-tidy <http://clang.llvm.org/extra/clang-tidy/>`_ is a clang-based C++
+`clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`_ is a clang-based C++
linter tool. It provides an extensible framework for building compiler-based
static analyses detecting and fixing bug-prone patterns, performance,
portability and maintainability issues.
diff --git a/docs/CommandGuide/clang.rst b/docs/CommandGuide/clang.rst
index d440d915d686..a75b6c911571 100644
--- a/docs/CommandGuide/clang.rst
+++ b/docs/CommandGuide/clang.rst
@@ -60,7 +60,7 @@ Linker
The Clang Static Analyzer is a tool that scans source code to try to find bugs
through code analysis. This tool uses many parts of Clang and is built into
-the same driver. Please see <http://clang-analyzer.llvm.org> for more details
+the same driver. Please see <https://clang-analyzer.llvm.org> for more details
on how to use the static analyzer.
OPTIONS
@@ -361,7 +361,7 @@ Code Generation Options
:option:`-Oz` Like :option:`-Os` (and thus :option:`-O2`), but reduces code
size further.
- :option:`-Og` Like :option:`-O1`. In future versions, this option might
+ :option:`-Og` Like :option:`-O1`. In future versions, this option might
disable different optimizations in order to improve debuggability.
:option:`-O` Equivalent to :option:`-O2`.
@@ -625,7 +625,7 @@ ENVIRONMENT
BUGS
----
-To report bugs, please visit <http://llvm.org/bugs/>. Most bug reports should
+To report bugs, please visit <https://bugs.llvm.org/>. Most bug reports should
include preprocessed source files (use the :option:`-E` option) and the full
output of the compiler, along with information to reproduce.
@@ -633,4 +633,3 @@ SEE ALSO
--------
:manpage:`as(1)`, :manpage:`ld(1)`
-
diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst
index fcc640988897..b0b37f83f1c7 100644
--- a/docs/ControlFlowIntegrity.rst
+++ b/docs/ControlFlowIntegrity.rst
@@ -45,7 +45,7 @@ Experimental support for :ref:`cross-DSO control flow integrity
<cfi-cross-dso>` exists that does not require classes to have hidden LTO
visibility. This cross-DSO support has unstable ABI at this time.
-.. _gold plugin: http://llvm.org/docs/GoldPlugin.html
+.. _gold plugin: https://llvm.org/docs/GoldPlugin.html
.. _cfi-schemes:
diff --git a/docs/ControlFlowIntegrityDesign.rst b/docs/ControlFlowIntegrityDesign.rst
index 15e20e1e1d8e..bb1770da5af4 100644
--- a/docs/ControlFlowIntegrityDesign.rst
+++ b/docs/ControlFlowIntegrityDesign.rst
@@ -93,8 +93,8 @@ the bit vectors for the whole program. It currently does this using LLVM's
`type metadata`_ mechanism together with link-time optimization.
.. _address point: http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-general
-.. _type metadata: http://llvm.org/docs/TypeMetadata.html
-.. _ByteArrayBuilder: http://llvm.org/docs/doxygen/html/structllvm_1_1ByteArrayBuilder.html
+.. _type metadata: https://llvm.org/docs/TypeMetadata.html
+.. _ByteArrayBuilder: https://llvm.org/docs/doxygen/html/structllvm_1_1ByteArrayBuilder.html
Optimizations
-------------
@@ -196,7 +196,7 @@ those sub-hierarchies need to be (see "Stripping Leading/Trailing Zeros in Bit
Vectors" above). The `GlobalLayoutBuilder`_ class is responsible for laying
out the globals efficiently to minimize the sizes of the underlying bitsets.
-.. _GlobalLayoutBuilder: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerTypeTests.h?view=markup
+.. _GlobalLayoutBuilder: https://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerTypeTests.h?view=markup
Alignment
~~~~~~~~~
@@ -274,6 +274,154 @@ If the bit vector is all ones, the bit vector check is redundant; we simply
need to check that the address is in range and well aligned. This is more
likely to occur if the virtual tables are padded.
+Forward-Edge CFI for Virtual Calls by Interleaving Virtual Tables
+-----------------------------------------------------------------
+
+Dimitar et. al. proposed a novel approach that interleaves virtual tables in [1]_.
+This approach is more efficient in terms of space because padding and bit vectors are no longer needed.
+At the same time, it is also more efficient in terms of performance because in the interleaved layout
+address points of the virtual tables are consecutive, thus the validity check of a virtual
+vtable pointer is always a range check.
+
+At a high level, the interleaving scheme consists of three steps: 1) split virtual table groups into
+separate virtual tables, 2) order virtual tables by a pre-order traversal of the class hierarchy
+and 3) interleave virtual tables.
+
+The interleaving scheme implemented in LLVM is inspired by [1]_ but has its own
+enhancements (more in `Interleave virtual tables`_).
+
+.. [1] `Protecting C++ Dynamic Dispatch Through VTable Interleaving <https://cseweb.ucsd.edu/~lerner/papers/ivtbl-ndss16.pdf>`_. Dimitar Bounov, Rami Gökhan Kıcı, Sorin Lerner.
+
+Split virtual table groups into separate virtual tables
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Itanium C++ ABI glues multiple individual virtual tables for a class into a combined virtual table (virtual table group).
+The interleaving scheme, however, can only work with individual virtual tables so it must split the combined virtual tables first.
+In comparison, the old scheme does not require the splitting but it is more efficient when the combined virtual tables have been split.
+The `GlobalSplit`_ pass is responsible for splitting combined virtual tables into individual ones.
+
+.. _GlobalSplit: https://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalSplit.cpp?view=markup
+
+Order virtual tables by a pre-order traversal of the class hierarchy
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This step is common to both the old scheme described above and the interleaving scheme.
+For the interleaving scheme, since the combined virtual tables have been split in the previous step,
+this step ensures that for any class all the compatible virtual tables will appear consecutively.
+For the old scheme, the same property may not hold since it may work on combined virtual tables.
+
+For example, consider the following four C++ classes:
+
+.. code-block:: c++
+
+ struct A {
+ virtual void f1();
+ };
+
+ struct B : A {
+ virtual void f1();
+ virtual void f2();
+ };
+
+ struct C : A {
+ virtual void f1();
+ virtual void f3();
+ };
+
+ struct D : B {
+ virtual void f1();
+ virtual void f2();
+ };
+
+This step will arrange the virtual tables for A, B, C, and D in the order of *vtable-of-A, vtable-of-B, vtable-of-D, vtable-of-C*.
+
+Interleave virtual tables
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This step is where the interleaving scheme deviates from the old scheme. Instead of laying out
+whole virtual tables in the previously computed order, the interleaving scheme lays out table
+entries of the virtual tables strategically to ensure the following properties:
+
+(1) offset-to-top and RTTI fields layout property
+
+The Itanium C++ ABI specifies that offset-to-top and RTTI fields appear at the offsets behind the
+address point. Note that libraries like libcxxabi do assume this property.
+
+(2) virtual function entry layout property
+
+For each virtual function the distance between an virtual table entry for this function and the corresponding
+address point is always the same. This property ensures that dynamic dispatch still works with the interleaving layout.
+
+Note that the interleaving scheme in the CFI implementation guarantees both properties above whereas the original scheme proposed
+in [1]_ only guarantees the second property.
+
+To illustrate how the interleaving algorithm works, let us continue with the running example.
+The algorithm first separates all the virtual table entries into two work lists. To do so,
+it starts by allocating two work lists, one initialized with all the offset-to-top entries of virtual tables in the order
+computed in the last step, one initialized with all the RTTI entries in the same order.
+
+.. csv-table:: Work list 1 Layout
+ :header: 0, 1, 2, 3
+
+ A::offset-to-top, B::offset-to-top, D::offset-to-top, C::offset-to-top
+
+
+.. csv-table:: Work list 2 layout
+ :header: 0, 1, 2, 3,
+
+ &A::rtti, &B::rtti, &D::rtti, &C::rtti
+
+Then for each virtual function the algorithm goes through all the virtual tables in the previously computed order
+to collect all the related entries into a virtual function list.
+After this step, there are the following virtual function lists:
+
+.. csv-table:: f1 list
+ :header: 0, 1, 2, 3
+
+ &A::f1, &B::f1, &D::f1, &C::f1
+
+
+.. csv-table:: f2 list
+ :header: 0, 1
+
+ &B::f2, &D::f2
+
+
+.. csv-table:: f3 list
+ :header: 0
+
+ &C::f3
+
+Next, the algorithm picks the longest remaining virtual function list and appends the whole list to the shortest work list
+until no function lists are left, and pads the shorter work list so that they are of the same length.
+In the example, f1 list will be first added to work list 1, then f2 list will be added
+to work list 2, and finally f3 list will be added to the work list 2. Since work list 1 now has one more entry than
+work list 2, a padding entry is added to the latter. After this step, the two work lists look like:
+
+.. csv-table:: Work list 1 Layout
+ :header: 0, 1, 2, 3, 4, 5, 6, 7
+
+ A::offset-to-top, B::offset-to-top, D::offset-to-top, C::offset-to-top, &A::f1, &B::f1, &D::f1, &C::f1
+
+
+.. csv-table:: Work list 2 layout
+ :header: 0, 1, 2, 3, 4, 5, 6, 7
+
+ &A::rtti, &B::rtti, &D::rtti, &C::rtti, &B::f2, &D::f2, &C::f3, padding
+
+Finally, the algorithm merges the two work lists into the interleaved layout by alternatingly
+moving the head of each list to the final layout. After this step, the final interleaved layout looks like:
+
+.. csv-table:: Interleaved layout
+ :header: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+
+ A::offset-to-top, &A::rtti, B::offset-to-top, &B::rtti, D::offset-to-top, &D::rtti, C::offset-to-top, &C::rtti, &A::f1, &B::f2, &B::f1, &D::f2, &D::f1, &C::f3, &C::f1, padding
+
+In the above interleaved layout, each virtual table's offset-to-top and RTTI are always adjacent, which shows that the layout has the first property.
+For the second property, let us look at f2 as an example. In the interleaved layout,
+there are two entries for f2: B::f2 and D::f2. The distance between &B::f2
+and its address point D::offset-to-top (the entry immediately after &B::rtti) is 5 entry-length, so is the distance between &D::f2 and C::offset-to-top (the entry immediately after &D::rtti).
+
Forward-Edge CFI for Indirect Function Calls
============================================
diff --git a/docs/CrossCompilation.rst b/docs/CrossCompilation.rst
index 5e1253ddf853..932e0525366e 100644
--- a/docs/CrossCompilation.rst
+++ b/docs/CrossCompilation.rst
@@ -15,7 +15,7 @@ build system or Makefiles, nor choosing the right CMake options, etc.
Also, it does not cover all the possible options, nor does it contain
specific examples for specific architectures. For a concrete example, the
`instructions for cross-compiling LLVM itself
-<http://llvm.org/docs/HowToCrossCompileLLVM.html>`_ may be of interest.
+<https://llvm.org/docs/HowToCrossCompileLLVM.html>`_ may be of interest.
After reading this document, you should be familiar with the main issues
related to cross-compilation, and what main compiler options Clang provides
diff --git a/docs/DiagnosticsReference.rst b/docs/DiagnosticsReference.rst
index 734a45902484..7d9b1e8359a8 100644
--- a/docs/DiagnosticsReference.rst
+++ b/docs/DiagnosticsReference.rst
@@ -7885,6 +7885,10 @@ This diagnostic is enabled by default.
| |+---------------------+|
+-----------------------------------------------------------------------------------------------+-----------------------+
+-Woverride-init
+---------------
+Synonym for `-Winitializer-overrides`_.
+
-Woverride-module
-----------------
@@ -8637,9 +8641,9 @@ Also controls `-Wpragma-pack-suspicious-include`_.
**Diagnostic text:**
-+---------------------------------------------------------------------------------------------------------------+
-|:warning:`warning:` |nbsp| :diagtext:`the current #pragma pack aligment value is modified in the included file`|
-+---------------------------------------------------------------------------------------------------------------+
++----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`the current #pragma pack alignment value is modified in the included file`|
++----------------------------------------------------------------------------------------------------------------+
+---------------------------------------------------------------------------------------------+
|:warning:`warning:` |nbsp| :diagtext:`unterminated '#pragma pack (push, ...)' at end of file`|
diff --git a/docs/HardwareAssistedAddressSanitizerDesign.rst b/docs/HardwareAssistedAddressSanitizerDesign.rst
index 2578914376ae..4e6f5d14cde4 100644
--- a/docs/HardwareAssistedAddressSanitizerDesign.rst
+++ b/docs/HardwareAssistedAddressSanitizerDesign.rst
@@ -47,21 +47,21 @@ All memory accesses are prefixed with an inline instruction sequence that
verifies the tags. Currently, the following sequence is used:
-.. code-block:: asm
+.. code-block:: none
// int foo(int *a) { return *a; }
// clang -O2 --target=aarch64-linux -fsanitize=hwaddress -c load.c
foo:
0: 08 00 00 90 adrp x8, 0 <__hwasan_shadow>
- 4: 08 01 40 f9 ldr x8, [x8] // shadow base (to be resolved by the loader)
- 8: 09 dc 44 d3 ubfx x9, x0, #4, #52 // shadow offset
- c: 28 69 68 38 ldrb w8, [x9, x8] // load shadow tag
- 10: 09 fc 78 d3 lsr x9, x0, #56 // extract address tag
- 14: 3f 01 08 6b cmp w9, w8 // compare tags
- 18: 61 00 00 54 b.ne 24 // jump on mismatch
- 1c: 00 00 40 b9 ldr w0, [x0] // original load
+ 4: 08 01 40 f9 ldr x8, [x8] // shadow base (to be resolved by the loader)
+ 8: 09 dc 44 d3 ubfx x9, x0, #4, #52 // shadow offset
+ c: 28 69 68 38 ldrb w8, [x9, x8] // load shadow tag
+ 10: 09 fc 78 d3 lsr x9, x0, #56 // extract address tag
+ 14: 3f 01 08 6b cmp w9, w8 // compare tags
+ 18: 61 00 00 54 b.ne 24 // jump on mismatch
+ 1c: 00 00 40 b9 ldr w0, [x0] // original load
20: c0 03 5f d6 ret
- 24: 40 20 21 d4 brk #0x902 // trap
+ 24: 40 20 21 d4 brk #0x902 // trap
Alternatively, memory accesses are prefixed with a function call.
diff --git a/docs/InternalsManual.rst b/docs/InternalsManual.rst
index af15b2e51e1c..b6b49d7547b0 100644
--- a/docs/InternalsManual.rst
+++ b/docs/InternalsManual.rst
@@ -19,7 +19,7 @@ LLVM Support Library
====================
The LLVM ``libSupport`` library provides many underlying libraries and
-`data-structures <http://llvm.org/docs/ProgrammersManual.html>`_, including
+`data-structures <https://llvm.org/docs/ProgrammersManual.html>`_, including
command line option processing, various containers and a system abstraction
layer, which is used for file system access.
@@ -559,13 +559,9 @@ The clang Driver and library are documented :doc:`here <DriverInternals>`.
Precompiled Headers
===================
-Clang supports two implementations of precompiled headers. The default
-implementation, precompiled headers (:doc:`PCH <PCHInternals>`) uses a
+Clang supports precompiled headers (:doc:`PCH <PCHInternals>`), which uses a
serialized representation of Clang's internal data structures, encoded with the
-`LLVM bitstream format <http://llvm.org/docs/BitCodeFormat.html>`_.
-Pretokenized headers (:doc:`PTH <PTHInternals>`), on the other hand, contain a
-serialized representation of the tokens encountered when preprocessing a header
-(and anything that header includes).
+`LLVM bitstream format <https://llvm.org/docs/BitCodeFormat.html>`_.
The Frontend Library
====================
@@ -1690,7 +1686,7 @@ semantic checking for some attributes, etc.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The first step to adding a new attribute to Clang is to add its definition to
`include/clang/Basic/Attr.td
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?view=markup>`_.
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?view=markup>`_.
This tablegen definition must derive from the ``Attr`` (tablegen, not
semantic) type, or one of its derivatives. Most attributes will derive from the
``InheritableAttr`` type, which specifies that the attribute can be inherited by
@@ -1752,10 +1748,10 @@ the ``SubjectList``. The diagnostics generated for subject list violations are
either ``diag::warn_attribute_wrong_decl_type`` or
``diag::err_attribute_wrong_decl_type``, and the parameter enumeration is found
in `include/clang/Sema/ParsedAttr.h
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ParsedAttr.h?view=markup>`_
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ParsedAttr.h?view=markup>`_
If a previously unused Decl node is added to the ``SubjectList``, the logic used
to automatically determine the diagnostic parameter in `utils/TableGen/ClangAttrEmitter.cpp
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_
may need to be updated.
By default, all subjects in the SubjectList must either be a Decl node defined
@@ -1777,7 +1773,7 @@ All attributes must have some form of documentation associated with them.
Documentation is table generated on the public web server by a server-side
process that runs daily. Generally, the documentation for an attribute is a
stand-alone definition in `include/clang/Basic/AttrDocs.td
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttdDocs.td?view=markup>`_
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttdDocs.td?view=markup>`_
that is named after the attribute being documented.
If the attribute is not for public consumption, or is an implicitly-created
@@ -1828,7 +1824,7 @@ All arguments have a name and a flag that specifies whether the argument is
optional. The associated C++ type of the argument is determined by the argument
definition type. If the existing argument types are insufficient, new types can
be created, but it requires modifying `utils/TableGen/ClangAttrEmitter.cpp
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_
to properly support the type.
Other Properties
@@ -1840,7 +1836,7 @@ document, however a few deserve mention.
If the parsed form of the attribute is more complex, or differs from the
semantic form, the ``HasCustomParsing`` bit can be set to ``1`` for the class,
and the parsing code in `Parser::ParseGNUAttributeArgs()
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?view=markup>`_
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?view=markup>`_
can be updated for the special case. Note that this only applies to arguments
with a GNU spelling -- attributes with a __declspec spelling currently ignore
this flag and are handled by ``Parser::ParseMicrosoftDeclSpec``.
@@ -1903,7 +1899,7 @@ semantic attribute class object, with ``public`` access.
Boilerplate
^^^^^^^^^^^
All semantic processing of declaration attributes happens in `lib/Sema/SemaDeclAttr.cpp
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?view=markup>`_,
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?view=markup>`_,
and generally starts in the ``ProcessDeclAttribute()`` function. If the
attribute is a "simple" attribute -- meaning that it requires no custom semantic
processing aside from what is automatically provided, add a call to
@@ -1919,11 +1915,11 @@ correct minimum number of arguments are passed, etc.
If the attribute adds additional warnings, define a ``DiagGroup`` in
`include/clang/Basic/DiagnosticGroups.td
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?view=markup>`_
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?view=markup>`_
named after the attribute's ``Spelling`` with "_"s replaced by "-"s. If there
is only a single diagnostic, it is permissible to use ``InGroup<DiagGroup<"your-attribute">>``
directly in `DiagnosticSemaKinds.td
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?view=markup>`_
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?view=markup>`_
All semantic diagnostics generated for your attribute, including automatically-
generated ones (such as subjects and argument counts), should have a
@@ -2075,7 +2071,7 @@ are similar.
exception-handling directly.
* Testing is extremely important in IR generation. Use ``clang -cc1
-emit-llvm`` and `FileCheck
- <http://llvm.org/docs/CommandGuide/FileCheck.html>`_ to verify that you're
+ <https://llvm.org/docs/CommandGuide/FileCheck.html>`_ to verify that you're
generating the right IR.
#. Teach template instantiation how to cope with your AST node, which requires
diff --git a/docs/IntroductionToTheClangAST.rst b/docs/IntroductionToTheClangAST.rst
index 600a6c884cb9..f357c03507d3 100644
--- a/docs/IntroductionToTheClangAST.rst
+++ b/docs/IntroductionToTheClangAST.rst
@@ -11,7 +11,7 @@ matchers.
<center><iframe width="560" height="315" src="http://www.youtube.com/embed/VqCkCDFLSsc?vq=hd720" frameborder="0" allowfullscreen></iframe></center>
-`Slides <http://llvm.org/devmtg/2013-04/klimek-slides.pdf>`_
+`Slides <https://llvm.org/devmtg/2013-04/klimek-slides.pdf>`_
Introduction
============
@@ -23,7 +23,7 @@ constants are available in an unreduced form in the AST. This makes
Clang's AST a good fit for refactoring tools.
Documentation for all Clang AST nodes is available via the generated
-`Doxygen <http://clang.llvm.org/doxygen>`_. The doxygen online
+`Doxygen <https://clang.llvm.org/doxygen>`_. The doxygen online
documentation is also indexed by your favorite search engine, which will
make a search for clang and the AST node's class name usually turn up
the doxygen of the class you're looking for (for example, search for:
@@ -67,26 +67,26 @@ Let's look at a simple example AST:
The toplevel declaration in
a translation unit is always the `translation unit
-declaration <http://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html>`_.
+declaration <https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html>`_.
In this example, our first user written declaration is the `function
-declaration <http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html>`_
+declaration <https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html>`_
of "``f``". The body of "``f``" is a `compound
-statement <http://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html>`_,
+statement <https://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html>`_,
whose child nodes are a `declaration
-statement <http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html>`_
+statement <https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html>`_
that declares our result variable, and the `return
-statement <http://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html>`_.
+statement <https://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html>`_.
AST Context
===========
All information about the AST for a translation unit is bundled up in
the class
-`ASTContext <http://clang.llvm.org/doxygen/classclang_1_1ASTContext.html>`_.
+`ASTContext <https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html>`_.
It allows traversal of the whole translation unit starting from
-`getTranslationUnitDecl <http://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#abd909fb01ef10cfd0244832a67b1dd64>`_,
+`getTranslationUnitDecl <https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#abd909fb01ef10cfd0244832a67b1dd64>`_,
or to access Clang's `table of
-identifiers <http://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#a4f95adb9958e22fbe55212ae6482feb4>`_
+identifiers <https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#a4f95adb9958e22fbe55212ae6482feb4>`_
for the parsed translation unit.
AST Nodes
@@ -95,32 +95,32 @@ AST Nodes
Clang's AST nodes are modeled on a class hierarchy that does not have a
common ancestor. Instead, there are multiple larger hierarchies for
basic node types like
-`Decl <http://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_ and
-`Stmt <http://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_. Many
+`Decl <https://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_ and
+`Stmt <https://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_. Many
important AST nodes derive from
-`Type <http://clang.llvm.org/doxygen/classclang_1_1Type.html>`_,
-`Decl <http://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_,
-`DeclContext <http://clang.llvm.org/doxygen/classclang_1_1DeclContext.html>`_
-or `Stmt <http://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_, with
+`Type <https://clang.llvm.org/doxygen/classclang_1_1Type.html>`_,
+`Decl <https://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_,
+`DeclContext <https://clang.llvm.org/doxygen/classclang_1_1DeclContext.html>`_
+or `Stmt <https://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_, with
some classes deriving from both Decl and DeclContext.
There are also a multitude of nodes in the AST that are not part of a
larger hierarchy, and are only reachable from specific other nodes, like
-`CXXBaseSpecifier <http://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html>`_.
+`CXXBaseSpecifier <https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html>`_.
Thus, to traverse the full AST, one starts from the
-`TranslationUnitDecl <http://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html>`_
+`TranslationUnitDecl <https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html>`_
and then recursively traverses everything that can be reached from that
node - this information has to be encoded for each specific node type.
This algorithm is encoded in the
-`RecursiveASTVisitor <http://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html>`_.
+`RecursiveASTVisitor <https://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html>`_.
See the `RecursiveASTVisitor
-tutorial <http://clang.llvm.org/docs/RAVFrontendAction.html>`_.
+tutorial <https://clang.llvm.org/docs/RAVFrontendAction.html>`_.
The two most basic nodes in the Clang AST are statements
-(`Stmt <http://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_) and
+(`Stmt <https://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_) and
declarations
-(`Decl <http://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_). Note
+(`Decl <https://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_). Note
that expressions
-(`Expr <http://clang.llvm.org/doxygen/classclang_1_1Expr.html>`_) are
+(`Expr <https://clang.llvm.org/doxygen/classclang_1_1Expr.html>`_) are
also statements in Clang's AST.
diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst
index 1aef265a8589..e155cefb7890 100644
--- a/docs/LanguageExtensions.rst
+++ b/docs/LanguageExtensions.rst
@@ -112,18 +112,22 @@ of ``cxx_rvalue_references``.
``__has_cpp_attribute``
-----------------------
-This function-like macro takes a single argument that is the name of a
-C++11-style attribute. The argument can either be a single identifier, or a
-scoped identifier. If the attribute is supported, a nonzero value is returned.
-If the attribute is a standards-based attribute, this macro returns a nonzero
-value based on the year and month in which the attribute was voted into the
-working draft. If the attribute is not supported by the current compliation
-target, this macro evaluates to 0. It can be used like this:
+This function-like macro is available in C++2a by default, and is provided as an
+extension in earlier language standards. It takes a single argument that is the
+name of a double-square-bracket-style attribute. The argument can either be a
+single identifier or a scoped identifier. If the attribute is supported, a
+nonzero value is returned. If the attribute is a standards-based attribute, this
+macro returns a nonzero value based on the year and month in which the attribute
+was voted into the working draft. See `WG21 SD-6
+<https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations>`_
+for the list of values returned for standards-based attributes. If the attribute
+is not supported by the current compliation target, this macro evaluates to 0.
+It can be used like this:
.. code-block:: c++
- #ifndef __has_cpp_attribute // Optional of course.
- #define __has_cpp_attribute(x) 0 // Compatibility with non-clang compilers.
+ #ifndef __has_cpp_attribute // For backwards compatibility
+ #define __has_cpp_attribute(x) 0
#endif
...
@@ -134,10 +138,11 @@ target, this macro evaluates to 0. It can be used like this:
#endif
...
-The attribute identifier (but not scope) can also be specified with a preceding
-and following ``__`` (double underscore) to avoid interference from a macro with
-the same name. For instance, ``gnu::__const__`` can be used instead of
-``gnu::const``.
+The attribute scope tokens ``clang`` and ``_Clang`` are interchangeable, as are
+the attribute scope tokens ``gnu`` and ``__gnu__``. Attribute tokens in either
+of these namespaces can be specified with a preceding and following ``__``
+(double underscore) to avoid interference from a macro with the same name. For
+instance, ``gnu::__const__`` can be used instead of ``gnu::const``.
``__has_c_attribute``
---------------------
@@ -162,11 +167,11 @@ current compilation target, this macro evaluates to 0. It can be used like this:
#endif
...
-The attribute identifier (but not scope) can also be specified with a preceding
-and following ``__`` (double underscore) to avoid interference from a macro with
-the same name. For instance, ``gnu::__const__`` can be used instead of
-``gnu::const``.
-
+The attribute scope tokens ``clang`` and ``_Clang`` are interchangeable, as are
+the attribute scope tokens ``gnu`` and ``__gnu__``. Attribute tokens in either
+of these namespaces can be specified with a preceding and following ``__``
+(double underscore) to avoid interference from a macro with the same name. For
+instance, ``gnu::__const__`` can be used instead of ``gnu::const``.
``__has_attribute``
-------------------
@@ -590,7 +595,7 @@ which does not provide them. The features which can be tested are listed here.
Since Clang 3.4, the C++ SD-6 feature test macros are also supported.
These are macros with names of the form ``__cpp_<feature_name>``, and are
intended to be a portable way to query the supported features of the compiler.
-See `the C++ status page <http://clang.llvm.org/cxx_status.html#ts>`_ for
+See `the C++ status page <https://clang.llvm.org/cxx_status.html#ts>`_ for
information on the version of SD-6 supported by each Clang release, and the
macros provided by that revision of the recommendations.
@@ -1013,7 +1018,7 @@ Modules
Use ``__has_feature(modules)`` to determine if Modules have been enabled.
For example, compiling code with ``-fmodules`` enables the use of Modules.
-More information could be found `here <http://clang.llvm.org/docs/Modules.html>`_.
+More information could be found `here <https://clang.llvm.org/docs/Modules.html>`_.
Checks for Type Trait Primitives
================================
@@ -1353,7 +1358,7 @@ In Objective-C, functions and methods are generally assumed to follow the
conventions for ownership of object arguments and
return values. However, there are exceptions, and so Clang provides attributes
to allow these exceptions to be documented. This are used by ARC and the
-`static analyzer <http://clang-analyzer.llvm.org>`_ Some exceptions may be
+`static analyzer <https://clang-analyzer.llvm.org>`_ Some exceptions may be
better described using the ``objc_method_family`` attribute instead.
**Usage**: The ``ns_returns_retained``, ``ns_returns_not_retained``,
@@ -1390,7 +1395,7 @@ method; it specifies that the method expects its ``self`` parameter to have a
- (void) baz:(id) __attribute__((ns_consumed)) x;
Further examples of these attributes are available in the static analyzer's `list of annotations for analysis
-<http://clang-analyzer.llvm.org/annotations.html#cocoa_mem>`_.
+<https://clang-analyzer.llvm.org/annotations.html#cocoa_mem>`_.
Query for these features with ``__has_attribute(ns_consumed)``,
``__has_attribute(ns_returns_retained)``, etc.
@@ -1411,7 +1416,7 @@ Objective-C methods. If such a check was missed, the program would compile
fine, run fine on newer systems, but crash on older systems.
As of LLVM 5.0, ``-Wunguarded-availability`` uses the `availability attributes
-<http://clang.llvm.org/docs/AttributeReference.html#availability>`_ together
+<https://clang.llvm.org/docs/AttributeReference.html#availability>`_ together
with the new ``@available()`` keyword to assist with this issue.
When a method that's introduced in the OS newer than the target OS is called, a
-Wunguarded-availability warning is emitted if that call is not guarded:
@@ -1454,7 +1459,7 @@ More than one platform can be listed in ``@available()``:
If the caller of ``my_fun()`` already checks that ``my_fun()`` is only called
on 10.12, then add an `availability attribute
-<http://clang.llvm.org/docs/AttributeReference.html#availability>`_ to it,
+<https://clang.llvm.org/docs/AttributeReference.html#availability>`_ to it,
which will also suppress the warning and require that calls to my_fun() are
checked:
@@ -1739,6 +1744,70 @@ The '``__builtin_bitreverse``' family of builtins is used to reverse
the bitpattern of an integer value; for example ``0b10110110`` becomes
``0b01101101``.
+``__builtin_rotateleft``
+------------------------
+
+* ``__builtin_rotateleft8``
+* ``__builtin_rotateleft16``
+* ``__builtin_rotateleft32``
+* ``__builtin_rotateleft64``
+
+**Syntax**:
+
+.. code-block:: c++
+
+ __builtin_rotateleft32(x, y)
+
+**Examples**:
+
+.. code-block:: c++
+
+ uint8_t rot_x = __builtin_rotateleft8(x, y);
+ uint16_t rot_x = __builtin_rotateleft16(x, y);
+ uint32_t rot_x = __builtin_rotateleft32(x, y);
+ uint64_t rot_x = __builtin_rotateleft64(x, y);
+
+**Description**:
+
+The '``__builtin_rotateleft``' family of builtins is used to rotate
+the bits in the first argument by the amount in the second argument.
+For example, ``0b10000110`` rotated left by 11 becomes ``0b00110100``.
+The shift value is treated as an unsigned amount modulo the size of
+the arguments. Both arguments and the result have the bitwidth specified
+by the name of the builtin.
+
+``__builtin_rotateright``
+_------------------------
+
+* ``__builtin_rotateright8``
+* ``__builtin_rotateright16``
+* ``__builtin_rotateright32``
+* ``__builtin_rotateright64``
+
+**Syntax**:
+
+.. code-block:: c++
+
+ __builtin_rotateright32(x, y)
+
+**Examples**:
+
+.. code-block:: c++
+
+ uint8_t rot_x = __builtin_rotateright8(x, y);
+ uint16_t rot_x = __builtin_rotateright16(x, y);
+ uint32_t rot_x = __builtin_rotateright32(x, y);
+ uint64_t rot_x = __builtin_rotateright64(x, y);
+
+**Description**:
+
+The '``__builtin_rotateright``' family of builtins is used to rotate
+the bits in the first argument by the amount in the second argument.
+For example, ``0b10000110`` rotated right by 3 becomes ``0b11010000``.
+The shift value is treated as an unsigned amount modulo the size of
+the arguments. Both arguments and the result have the bitwidth specified
+by the name of the builtin.
+
``__builtin_unreachable``
-------------------------
@@ -1977,7 +2046,7 @@ Floating point builtins
Returns the platform specific canonical encoding of a floating point
number. This canonicalization is useful for implementing certain
numeric primitives such as frexp. See `LLVM canonicalize intrinsic
-<http://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic>`_ for
+<https://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic>`_ for
more information on the semantics.
String builtins
@@ -2191,7 +2260,7 @@ standard library to implement `std::experimental::coroutine_handle` type.
Other coroutine builtins are either for internal clang use or for use during
development of the coroutine feature. See `Coroutines in LLVM
-<http://llvm.org/docs/Coroutines.html#intrinsics>`_ for
+<https://llvm.org/docs/Coroutines.html#intrinsics>`_ for
more information on their semantics. Note that builtins matching the intrinsics
that take token as the first parameter (llvm.coro.begin, llvm.coro.alloc,
llvm.coro.free and llvm.coro.suspend) omit the token parameter and fill it to
@@ -2298,9 +2367,9 @@ Extensions for Static Analysis
Clang supports additional attributes that are useful for documenting program
invariants and rules for static analysis tools, such as the `Clang Static
-Analyzer <http://clang-analyzer.llvm.org/>`_. These attributes are documented
+Analyzer <https://clang-analyzer.llvm.org/>`_. These attributes are documented
in the analyzer's `list of source-level annotations
-<http://clang-analyzer.llvm.org/annotations.html>`_.
+<https://clang-analyzer.llvm.org/annotations.html>`_.
Extensions for Dynamic Analysis
@@ -2587,17 +2656,19 @@ Specifying an attribute for multiple declarations (#pragma clang attribute)
The ``#pragma clang attribute`` directive can be used to apply an attribute to
multiple declarations. The ``#pragma clang attribute push`` variation of the
-directive pushes a new attribute to the attribute stack. The declarations that
-follow the pragma receive the attributes that are on the attribute stack, until
-the stack is cleared using a ``#pragma clang attribute pop`` directive. Multiple
-push directives can be nested inside each other.
+directive pushes a new "scope" of ``#pragma clang attribute`` that attributes
+can be added to. The ``#pragma clang attribute (...)`` variation adds an
+attribute to that scope, and the ``#pragma clang attribute pop`` variation pops
+the scope. You can also use ``#pragma clang attribute push (...)``, which is a
+shorthand for when you want to add one attribute to a new scope. Multiple push
+directives can be nested inside each other.
The attributes that are used in the ``#pragma clang attribute`` directives
can be written using the GNU-style syntax:
.. code-block:: c++
- #pragma clang attribute push(__attribute__((annotate("custom"))), apply_to = function)
+ #pragma clang attribute push (__attribute__((annotate("custom"))), apply_to = function)
void function(); // The function now has the annotate("custom") attribute
@@ -2607,7 +2678,7 @@ The attributes can also be written using the C++11 style syntax:
.. code-block:: c++
- #pragma clang attribute push([[noreturn]], apply_to = function)
+ #pragma clang attribute push ([[noreturn]], apply_to = function)
void function(); // The function now has the [[noreturn]] attribute
@@ -2617,7 +2688,7 @@ The ``__declspec`` style syntax is also supported:
.. code-block:: c++
- #pragma clang attribute push(__declspec(dllexport), apply_to = function)
+ #pragma clang attribute push (__declspec(dllexport), apply_to = function)
void function(); // The function now has the __declspec(dllexport) attribute
@@ -2626,6 +2697,38 @@ The ``__declspec`` style syntax is also supported:
A single push directive accepts only one attribute regardless of the syntax
used.
+Because multiple push directives can be nested, if you're writing a macro that
+expands to ``_Pragma("clang attribute")`` it's good hygiene (though not
+required) to add a namespace to your push/pop directives. A pop directive with a
+namespace will pop the innermost push that has that same namespace. This will
+ensure that another macro's ``pop`` won't inadvertently pop your attribute. Note
+that an ``pop`` without a namespace will pop the innermost ``push`` without a
+namespace. ``push``es with a namespace can only be popped by ``pop`` with the
+same namespace. For instance:
+
+.. code-block:: c++
+
+ #define ASSUME_NORETURN_BEGIN _Pragma("clang attribute AssumeNoreturn.push ([[noreturn]], apply_to = function)")
+ #define ASSUME_NORETURN_END _Pragma("clang attribute AssumeNoreturn.pop")
+
+ #define ASSUME_UNAVAILABLE_BEGIN _Pragma("clang attribute Unavailable.push (__attribute__((unavailable)), apply_to=function)")
+ #define ASSUME_UNAVAILABLE_END _Pragma("clang attribute Unavailable.pop")
+
+
+ ASSUME_NORETURN_BEGIN
+ ASSUME_UNAVAILABLE_BEGIN
+ void function(); // function has [[noreturn]] and __attribute__((unavailable))
+ ASSUME_NORETURN_END
+ void other_function(); // function has __attribute__((unavailable))
+ ASSUME_UNAVAILABLE_END
+
+Without the namespaces on the macros, ``other_function`` will be annotated with
+``[[noreturn]]`` instead of ``__attribute__((unavailable))``. This may seem like
+a contrived example, but its very possible for this kind of situation to appear
+in real code if the pragmas are spread out across a large file. You can test if
+your version of clang supports namespaces on ``#pragma clang attribute`` with
+``__has_extension(pragma_clang_attribute_namespaces)``.
+
Subject Match Rules
-------------------
diff --git a/docs/LibASTMatchers.rst b/docs/LibASTMatchers.rst
index aea9f3233b4b..3b9f0a66db13 100644
--- a/docs/LibASTMatchers.rst
+++ b/docs/LibASTMatchers.rst
@@ -81,7 +81,7 @@ To that end, matchers that match specific AST nodes (so called node matchers)
are bindable; for example, ``recordDecl(hasName("MyClass")).bind("id")`` will
bind the matched ``recordDecl`` node to the string "``id``", to be later
retrieved in the `match callback
-<http://clang.llvm.org/doxygen/classclang_1_1ast__matchers_1_1MatchFinder_1_1MatchCallback.html>`_.
+<https://clang.llvm.org/doxygen/classclang_1_1ast__matchers_1_1MatchFinder_1_1MatchCallback.html>`_.
.. FIXME: Introduce link to ASTMatchersTutorial.html
.. FIXME: Introduce link to ASTMatchersCookbook.html
@@ -116,7 +116,7 @@ corresponding matcher.
There are multiple matcher definition macros that deal with polymorphic return
values and different parameter counts. See `ASTMatchersMacros.h
-<http://clang.llvm.org/doxygen/ASTMatchersMacros_8h.html>`_.
+<https://clang.llvm.org/doxygen/ASTMatchersMacros_8h.html>`_.
.. _astmatchers-writing:
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html
index cf32a5ce4a0f..2af0a7c9e33d 100644
--- a/docs/LibASTMatchersReference.html
+++ b/docs/LibASTMatchersReference.html
@@ -100,7 +100,7 @@ recordDecl(decl().bind("id"), hasName("::MyClass"))
<tr style="text-align:left"><th>Return type</th><th>Name</th><th>Parameters</th></tr>
<!-- START_DECL_MATCHERS -->
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('cxxCtorInitializer0')"><a name="cxxCtorInitializer0Anchor">cxxCtorInitializer</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('cxxCtorInitializer0')"><a name="cxxCtorInitializer0Anchor">cxxCtorInitializer</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxCtorInitializer0"><pre>Matches constructor initializers.
Examples matches i(42).
@@ -111,7 +111,7 @@ Examples matches i(42).
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('accessSpecDecl0')"><a name="accessSpecDecl0Anchor">accessSpecDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AccessSpecDecl.html">AccessSpecDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('accessSpecDecl0')"><a name="accessSpecDecl0Anchor">accessSpecDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AccessSpecDecl.html">AccessSpecDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="accessSpecDecl0"><pre>Matches C++ access specifier declarations.
Given
@@ -124,7 +124,7 @@ accessSpecDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('blockDecl0')"><a name="blockDecl0Anchor">blockDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('blockDecl0')"><a name="blockDecl0Anchor">blockDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="blockDecl0"><pre>Matches block declarations.
Example matches the declaration of the nameless block printing an input
@@ -136,7 +136,7 @@ integer.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('classTemplateDecl0')"><a name="classTemplateDecl0Anchor">classTemplateDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateDecl.html">ClassTemplateDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('classTemplateDecl0')"><a name="classTemplateDecl0Anchor">classTemplateDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateDecl.html">ClassTemplateDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="classTemplateDecl0"><pre>Matches C++ class template declarations.
Example matches Z
@@ -144,7 +144,24 @@ Example matches Z
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('classTemplateSpecializationDecl0')"><a name="classTemplateSpecializationDecl0Anchor">classTemplateSpecializationDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('classTemplatePartialSpecializationDecl0')"><a name="classTemplatePartialSpecializationDecl0Anchor">classTemplatePartialSpecializationDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplatePartialSpecializationDecl.html">ClassTemplatePartialSpecializationDecl</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="classTemplatePartialSpecializationDecl0"><pre>Matches C++ class template partial specializations.
+
+Given
+ template&lt;class T1, class T2, int I&gt;
+ class A {};
+
+ template&lt;class T, int I&gt;
+ class A&lt;T, T*, I&gt; {};
+
+ template&lt;&gt;
+ class A&lt;int, int, 1&gt; {};
+classTemplatePartialSpecializationDecl()
+ matches the specialization A&lt;T,T*,I&gt; but not A&lt;int,int,1&gt;
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('classTemplateSpecializationDecl0')"><a name="classTemplateSpecializationDecl0Anchor">classTemplateSpecializationDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="classTemplateSpecializationDecl0"><pre>Matches C++ class template specializations.
Given
@@ -156,7 +173,7 @@ classTemplateSpecializationDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxConstructorDecl0')"><a name="cxxConstructorDecl0Anchor">cxxConstructorDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxConstructorDecl0')"><a name="cxxConstructorDecl0Anchor">cxxConstructorDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConstructorDecl0"><pre>Matches C++ constructor declarations.
Example matches Foo::Foo() and Foo::Foo(int)
@@ -169,7 +186,7 @@ Example matches Foo::Foo() and Foo::Foo(int)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxConversionDecl0')"><a name="cxxConversionDecl0Anchor">cxxConversionDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConversionDecl.html">CXXConversionDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxConversionDecl0')"><a name="cxxConversionDecl0Anchor">cxxConversionDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConversionDecl.html">CXXConversionDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConversionDecl0"><pre>Matches conversion operator declarations.
Example matches the operator.
@@ -177,7 +194,7 @@ Example matches the operator.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxDestructorDecl0')"><a name="cxxDestructorDecl0Anchor">cxxDestructorDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXDestructorDecl.html">CXXDestructorDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxDestructorDecl0')"><a name="cxxDestructorDecl0Anchor">cxxDestructorDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDestructorDecl.html">CXXDestructorDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDestructorDecl0"><pre>Matches explicit C++ destructor declarations.
Example matches Foo::~Foo()
@@ -188,7 +205,7 @@ Example matches Foo::~Foo()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxMethodDecl0')"><a name="cxxMethodDecl0Anchor">cxxMethodDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxMethodDecl0')"><a name="cxxMethodDecl0Anchor">cxxMethodDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxMethodDecl0"><pre>Matches method declarations.
Example matches y
@@ -196,7 +213,7 @@ Example matches y
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxRecordDecl0')"><a name="cxxRecordDecl0Anchor">cxxRecordDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('cxxRecordDecl0')"><a name="cxxRecordDecl0Anchor">cxxRecordDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxRecordDecl0"><pre>Matches C++ class declarations.
Example matches X, Z
@@ -205,7 +222,7 @@ Example matches X, Z
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('decl0')"><a name="decl0Anchor">decl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('decl0')"><a name="decl0Anchor">decl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="decl0"><pre>Matches declarations.
Examples matches X, C, and the friend declaration inside C;
@@ -216,7 +233,7 @@ Examples matches X, C, and the friend declaration inside C;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('declaratorDecl0')"><a name="declaratorDecl0Anchor">declaratorDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('declaratorDecl0')"><a name="declaratorDecl0Anchor">declaratorDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="declaratorDecl0"><pre>Matches declarator declarations (field, variable, function
and non-type template parameter declarations).
@@ -227,7 +244,7 @@ declaratorDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('enumConstantDecl0')"><a name="enumConstantDecl0Anchor">enumConstantDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumConstantDecl.html">EnumConstantDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('enumConstantDecl0')"><a name="enumConstantDecl0Anchor">enumConstantDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumConstantDecl.html">EnumConstantDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="enumConstantDecl0"><pre>Matches enum constants.
Example matches A, B, C
@@ -237,7 +254,7 @@ Example matches A, B, C
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('enumDecl0')"><a name="enumDecl0Anchor">enumDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumDecl.html">EnumDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('enumDecl0')"><a name="enumDecl0Anchor">enumDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumDecl.html">EnumDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="enumDecl0"><pre>Matches enum declarations.
Example matches X
@@ -247,7 +264,7 @@ Example matches X
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('fieldDecl0')"><a name="fieldDecl0Anchor">fieldDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('fieldDecl0')"><a name="fieldDecl0Anchor">fieldDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="fieldDecl0"><pre>Matches field declarations.
Given
@@ -257,7 +274,7 @@ fieldDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('friendDecl0')"><a name="friendDecl0Anchor">friendDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('friendDecl0')"><a name="friendDecl0Anchor">friendDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="friendDecl0"><pre>Matches friend declarations.
Given
@@ -267,7 +284,7 @@ friendDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('functionDecl0')"><a name="functionDecl0Anchor">functionDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('functionDecl0')"><a name="functionDecl0Anchor">functionDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="functionDecl0"><pre>Matches function declarations.
Example matches f
@@ -275,7 +292,7 @@ Example matches f
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('functionTemplateDecl0')"><a name="functionTemplateDecl0Anchor">functionTemplateDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionTemplateDecl.html">FunctionTemplateDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('functionTemplateDecl0')"><a name="functionTemplateDecl0Anchor">functionTemplateDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionTemplateDecl.html">FunctionTemplateDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="functionTemplateDecl0"><pre>Matches C++ function template declarations.
Example matches f
@@ -283,7 +300,17 @@ Example matches f
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('labelDecl0')"><a name="labelDecl0Anchor">labelDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelDecl.html">LabelDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('indirectFieldDecl0')"><a name="indirectFieldDecl0Anchor">indirectFieldDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IndirectFieldDecl.html">IndirectFieldDecl</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="indirectFieldDecl0"><pre>Matches indirect field declarations.
+
+Given
+ struct X { struct { int a; }; };
+indirectFieldDecl()
+ matches 'a'.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('labelDecl0')"><a name="labelDecl0Anchor">labelDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelDecl.html">LabelDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="labelDecl0"><pre>Matches a declaration of label.
Given
@@ -294,7 +321,7 @@ labelDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('linkageSpecDecl0')"><a name="linkageSpecDecl0Anchor">linkageSpecDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LinkageSpecDecl.html">LinkageSpecDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('linkageSpecDecl0')"><a name="linkageSpecDecl0Anchor">linkageSpecDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LinkageSpecDecl.html">LinkageSpecDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="linkageSpecDecl0"><pre>Matches a declaration of a linkage specification.
Given
@@ -304,7 +331,7 @@ linkageSpecDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('namedDecl0')"><a name="namedDecl0Anchor">namedDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('namedDecl0')"><a name="namedDecl0Anchor">namedDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="namedDecl0"><pre>Matches a declaration of anything that could have a name.
Example matches X, S, the anonymous union type, i, and U;
@@ -317,7 +344,7 @@ Example matches X, S, the anonymous union type, i, and U;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('namespaceAliasDecl0')"><a name="namespaceAliasDecl0Anchor">namespaceAliasDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamespaceAliasDecl.html">NamespaceAliasDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('namespaceAliasDecl0')"><a name="namespaceAliasDecl0Anchor">namespaceAliasDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamespaceAliasDecl.html">NamespaceAliasDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="namespaceAliasDecl0"><pre>Matches a declaration of a namespace alias.
Given
@@ -328,7 +355,7 @@ namespaceAliasDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('namespaceDecl0')"><a name="namespaceDecl0Anchor">namespaceDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('namespaceDecl0')"><a name="namespaceDecl0Anchor">namespaceDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="namespaceDecl0"><pre>Matches a declaration of a namespace.
Given
@@ -339,7 +366,7 @@ namespaceDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('nonTypeTemplateParmDecl0')"><a name="nonTypeTemplateParmDecl0Anchor">nonTypeTemplateParmDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NonTypeTemplateParmDecl.html">NonTypeTemplateParmDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('nonTypeTemplateParmDecl0')"><a name="nonTypeTemplateParmDecl0Anchor">nonTypeTemplateParmDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NonTypeTemplateParmDecl.html">NonTypeTemplateParmDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="nonTypeTemplateParmDecl0"><pre>Matches non-type template parameter declarations.
Given
@@ -349,7 +376,7 @@ nonTypeTemplateParmDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcCategoryDecl0')"><a name="objcCategoryDecl0Anchor">objcCategoryDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCCategoryDecl.html">ObjCCategoryDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcCategoryDecl0')"><a name="objcCategoryDecl0Anchor">objcCategoryDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCCategoryDecl.html">ObjCCategoryDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcCategoryDecl0"><pre>Matches Objective-C category declarations.
Example matches Foo (Additions)
@@ -358,7 +385,7 @@ Example matches Foo (Additions)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcCategoryImplDecl0')"><a name="objcCategoryImplDecl0Anchor">objcCategoryImplDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCCategoryImplDecl.html">ObjCCategoryImplDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcCategoryImplDecl0')"><a name="objcCategoryImplDecl0Anchor">objcCategoryImplDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCCategoryImplDecl.html">ObjCCategoryImplDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcCategoryImplDecl0"><pre>Matches Objective-C category definitions.
Example matches Foo (Additions)
@@ -367,7 +394,7 @@ Example matches Foo (Additions)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcImplementationDecl0')"><a name="objcImplementationDecl0Anchor">objcImplementationDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCImplementationDecl.html">ObjCImplementationDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcImplementationDecl0')"><a name="objcImplementationDecl0Anchor">objcImplementationDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCImplementationDecl.html">ObjCImplementationDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcImplementationDecl0"><pre>Matches Objective-C implementation declarations.
Example matches Foo
@@ -376,7 +403,7 @@ Example matches Foo
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcInterfaceDecl0')"><a name="objcInterfaceDecl0Anchor">objcInterfaceDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcInterfaceDecl0')"><a name="objcInterfaceDecl0Anchor">objcInterfaceDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcInterfaceDecl0"><pre>Matches Objective-C interface declarations.
Example matches Foo
@@ -385,7 +412,7 @@ Example matches Foo
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcIvarDecl0')"><a name="objcIvarDecl0Anchor">objcIvarDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCIvarDecl.html">ObjCIvarDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcIvarDecl0')"><a name="objcIvarDecl0Anchor">objcIvarDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCIvarDecl.html">ObjCIvarDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcIvarDecl0"><pre>Matches Objective-C instance variable declarations.
Example matches _enabled
@@ -396,7 +423,7 @@ Example matches _enabled
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcMethodDecl0')"><a name="objcMethodDecl0Anchor">objcMethodDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcMethodDecl0')"><a name="objcMethodDecl0Anchor">objcMethodDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcMethodDecl0"><pre>Matches Objective-C method declarations.
Example matches both declaration and definition of -[Foo method]
@@ -410,7 +437,7 @@ Example matches both declaration and definition of -[Foo method]
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcPropertyDecl0')"><a name="objcPropertyDecl0Anchor">objcPropertyDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcPropertyDecl0')"><a name="objcPropertyDecl0Anchor">objcPropertyDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcPropertyDecl0"><pre>Matches Objective-C property declarations.
Example matches enabled
@@ -420,7 +447,7 @@ Example matches enabled
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcProtocolDecl0')"><a name="objcProtocolDecl0Anchor">objcProtocolDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCProtocolDecl.html">ObjCProtocolDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('objcProtocolDecl0')"><a name="objcProtocolDecl0Anchor">objcProtocolDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCProtocolDecl.html">ObjCProtocolDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcProtocolDecl0"><pre>Matches Objective-C protocol declarations.
Example matches FooDelegate
@@ -429,7 +456,7 @@ Example matches FooDelegate
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('parmVarDecl0')"><a name="parmVarDecl0Anchor">parmVarDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('parmVarDecl0')"><a name="parmVarDecl0Anchor">parmVarDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="parmVarDecl0"><pre>Matches parameter variable declarations.
Given
@@ -439,7 +466,7 @@ parmVarDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('recordDecl0')"><a name="recordDecl0Anchor">recordDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('recordDecl0')"><a name="recordDecl0Anchor">recordDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="recordDecl0"><pre>Matches class, struct, and union declarations.
Example matches X, Z, U, and S
@@ -450,7 +477,7 @@ Example matches X, Z, U, and S
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('staticAssertDecl0')"><a name="staticAssertDecl0Anchor">staticAssertDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1StaticAssertDecl.html">StaticAssertDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('staticAssertDecl0')"><a name="staticAssertDecl0Anchor">staticAssertDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1StaticAssertDecl.html">StaticAssertDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="staticAssertDecl0"><pre>Matches a C++ static_assert declaration.
Example:
@@ -465,7 +492,7 @@ in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('templateTypeParmDecl0')"><a name="templateTypeParmDecl0Anchor">templateTypeParmDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmDecl.html">TemplateTypeParmDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('templateTypeParmDecl0')"><a name="templateTypeParmDecl0Anchor">templateTypeParmDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmDecl.html">TemplateTypeParmDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="templateTypeParmDecl0"><pre>Matches template type parameter declarations.
Given
@@ -475,20 +502,20 @@ templateTypeParmDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('translationUnitDecl0')"><a name="translationUnitDecl0Anchor">translationUnitDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html">TranslationUnitDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('translationUnitDecl0')"><a name="translationUnitDecl0Anchor">translationUnitDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html">TranslationUnitDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="translationUnitDecl0"><pre>Matches the top declaration context.
Given
int X;
namespace NS {
int Y;
- } namespace NS
+ } // namespace NS
decl(hasDeclContext(translationUnitDecl()))
matches "int X", but not "int Y".
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typeAliasDecl0')"><a name="typeAliasDecl0Anchor">typeAliasDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeAliasDecl.html">TypeAliasDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typeAliasDecl0')"><a name="typeAliasDecl0Anchor">typeAliasDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeAliasDecl.html">TypeAliasDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typeAliasDecl0"><pre>Matches type alias declarations.
Given
@@ -499,7 +526,7 @@ typeAliasDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typeAliasTemplateDecl0')"><a name="typeAliasTemplateDecl0Anchor">typeAliasTemplateDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeAliasTemplateDecl.html">TypeAliasTemplateDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typeAliasTemplateDecl0')"><a name="typeAliasTemplateDecl0Anchor">typeAliasTemplateDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeAliasTemplateDecl.html">TypeAliasTemplateDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typeAliasTemplateDecl0"><pre>Matches type alias template declarations.
typeAliasTemplateDecl() matches
@@ -508,7 +535,7 @@ typeAliasTemplateDecl() matches
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typedefDecl0')"><a name="typedefDecl0Anchor">typedefDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefDecl.html">TypedefDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typedefDecl0')"><a name="typedefDecl0Anchor">typedefDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefDecl.html">TypedefDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typedefDecl0"><pre>Matches typedef declarations.
Given
@@ -519,7 +546,7 @@ typedefDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typedefNameDecl0')"><a name="typedefNameDecl0Anchor">typedefNameDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typedefNameDecl0')"><a name="typedefNameDecl0Anchor">typedefNameDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typedefNameDecl0"><pre>Matches typedef name declarations.
Given
@@ -530,7 +557,7 @@ typedefNameDecl()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('unresolvedUsingTypenameDecl0')"><a name="unresolvedUsingTypenameDecl0Anchor">unresolvedUsingTypenameDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingTypenameDecl.html">UnresolvedUsingTypenameDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('unresolvedUsingTypenameDecl0')"><a name="unresolvedUsingTypenameDecl0Anchor">unresolvedUsingTypenameDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingTypenameDecl.html">UnresolvedUsingTypenameDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="unresolvedUsingTypenameDecl0"><pre>Matches unresolved using value declarations that involve the
typename.
@@ -546,7 +573,7 @@ unresolvedUsingTypenameDecl()
matches using Base&lt;T&gt;::Foo </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('unresolvedUsingValueDecl0')"><a name="unresolvedUsingValueDecl0Anchor">unresolvedUsingValueDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingValueDecl.html">UnresolvedUsingValueDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('unresolvedUsingValueDecl0')"><a name="unresolvedUsingValueDecl0Anchor">unresolvedUsingValueDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingValueDecl.html">UnresolvedUsingValueDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="unresolvedUsingValueDecl0"><pre>Matches unresolved using value declarations.
Given
@@ -558,7 +585,7 @@ unresolvedUsingValueDecl()
matches using X::x </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('usingDecl0')"><a name="usingDecl0Anchor">usingDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UsingDecl.html">UsingDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('usingDecl0')"><a name="usingDecl0Anchor">usingDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingDecl.html">UsingDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="usingDecl0"><pre>Matches using declarations.
Given
@@ -568,7 +595,7 @@ usingDecl()
matches using X::x </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('usingDirectiveDecl0')"><a name="usingDirectiveDecl0Anchor">usingDirectiveDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UsingDirectiveDecl.html">UsingDirectiveDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('usingDirectiveDecl0')"><a name="usingDirectiveDecl0Anchor">usingDirectiveDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingDirectiveDecl.html">UsingDirectiveDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="usingDirectiveDecl0"><pre>Matches using namespace declarations.
Given
@@ -578,7 +605,7 @@ usingDirectiveDecl()
matches using namespace X </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('valueDecl0')"><a name="valueDecl0Anchor">valueDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('valueDecl0')"><a name="valueDecl0Anchor">valueDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="valueDecl0"><pre>Matches any value declaration.
Example matches A, B, C and F
@@ -587,7 +614,7 @@ Example matches A, B, C and F
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('varDecl0')"><a name="varDecl0Anchor">varDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('varDecl0')"><a name="varDecl0Anchor">varDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="varDecl0"><pre>Matches variable declarations.
Note: this does not match declarations of member variables, which are
@@ -598,12 +625,12 @@ Example matches a
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('nestedNameSpecifierLoc0')"><a name="nestedNameSpecifierLoc0Anchor">nestedNameSpecifierLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('nestedNameSpecifierLoc0')"><a name="nestedNameSpecifierLoc0Anchor">nestedNameSpecifierLoc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="nestedNameSpecifierLoc0"><pre>Same as nestedNameSpecifier but matches NestedNameSpecifierLoc.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('nestedNameSpecifier0')"><a name="nestedNameSpecifier0Anchor">nestedNameSpecifier</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('nestedNameSpecifier0')"><a name="nestedNameSpecifier0Anchor">nestedNameSpecifier</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="nestedNameSpecifier0"><pre>Matches nested name specifiers.
Given
@@ -618,12 +645,12 @@ nestedNameSpecifier()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('qualType0')"><a name="qualType0Anchor">qualType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('qualType0')"><a name="qualType0Anchor">qualType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="qualType0"><pre>Matches QualTypes in the clang AST.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('addrLabelExpr0')"><a name="addrLabelExpr0Anchor">addrLabelExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('addrLabelExpr0')"><a name="addrLabelExpr0Anchor">addrLabelExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="addrLabelExpr0"><pre>Matches address of label statements (GNU extension).
Given
@@ -635,7 +662,7 @@ addrLabelExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('arraySubscriptExpr0')"><a name="arraySubscriptExpr0Anchor">arraySubscriptExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('arraySubscriptExpr0')"><a name="arraySubscriptExpr0Anchor">arraySubscriptExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="arraySubscriptExpr0"><pre>Matches array subscript expressions.
Given
@@ -645,7 +672,7 @@ arraySubscriptExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('asmStmt0')"><a name="asmStmt0Anchor">asmStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AsmStmt.html">AsmStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('asmStmt0')"><a name="asmStmt0Anchor">asmStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AsmStmt.html">AsmStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="asmStmt0"><pre>Matches asm statements.
int i = 100;
@@ -655,14 +682,14 @@ asmStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('atomicExpr0')"><a name="atomicExpr0Anchor">atomicExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AtomicExpr.html">AtomicExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('atomicExpr0')"><a name="atomicExpr0Anchor">atomicExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AtomicExpr.html">AtomicExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="atomicExpr0"><pre>Matches atomic builtins.
Example matches __atomic_load_n(ptr, 1)
void foo() { int *ptr; __atomic_load_n(ptr, 1); }
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('autoreleasePoolStmt0')"><a name="autoreleasePoolStmt0Anchor">autoreleasePoolStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCAutoreleasePoolStmt.html">ObjCAutoreleasePoolStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('autoreleasePoolStmt0')"><a name="autoreleasePoolStmt0Anchor">autoreleasePoolStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAutoreleasePoolStmt.html">ObjCAutoreleasePoolStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="autoreleasePoolStmt0"><pre>Matches an Objective-C autorelease pool statement.
Given
@@ -674,7 +701,7 @@ inside the autorelease pool.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('binaryConditionalOperator0')"><a name="binaryConditionalOperator0Anchor">binaryConditionalOperator</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryConditionalOperator.html">BinaryConditionalOperator</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('binaryConditionalOperator0')"><a name="binaryConditionalOperator0Anchor">binaryConditionalOperator</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryConditionalOperator.html">BinaryConditionalOperator</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="binaryConditionalOperator0"><pre>Matches binary conditional operator expressions (GNU extension).
Example matches a ?: b
@@ -682,7 +709,7 @@ Example matches a ?: b
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('binaryOperator0')"><a name="binaryOperator0Anchor">binaryOperator</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('binaryOperator0')"><a name="binaryOperator0Anchor">binaryOperator</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="binaryOperator0"><pre>Matches binary operator expressions.
Example matches a || b
@@ -690,7 +717,15 @@ Example matches a || b
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('breakStmt0')"><a name="breakStmt0Anchor">breakStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BreakStmt.html">BreakStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('blockExpr0')"><a name="blockExpr0Anchor">blockExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockExpr.html">BlockExpr</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="blockExpr0"><pre>Matches a reference to a block.
+
+Example: matches "^{}":
+ void f() { ^{}(); }
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('breakStmt0')"><a name="breakStmt0Anchor">breakStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BreakStmt.html">BreakStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="breakStmt0"><pre>Matches break statements.
Given
@@ -700,7 +735,7 @@ breakStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cStyleCastExpr0')"><a name="cStyleCastExpr0Anchor">cStyleCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CStyleCastExpr.html">CStyleCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cStyleCastExpr0')"><a name="cStyleCastExpr0Anchor">cStyleCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CStyleCastExpr.html">CStyleCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cStyleCastExpr0"><pre>Matches a C-style cast expression.
Example: Matches (int) 2.2f in
@@ -708,7 +743,7 @@ Example: Matches (int) 2.2f in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('callExpr0')"><a name="callExpr0Anchor">callExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('callExpr0')"><a name="callExpr0Anchor">callExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="callExpr0"><pre>Matches call expressions.
Example matches x.y() and y()
@@ -718,7 +753,7 @@ Example matches x.y() and y()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('caseStmt0')"><a name="caseStmt0Anchor">caseStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CaseStmt.html">CaseStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('caseStmt0')"><a name="caseStmt0Anchor">caseStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CaseStmt.html">CaseStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="caseStmt0"><pre>Matches case statements inside switch statements.
Given
@@ -728,7 +763,7 @@ caseStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('castExpr0')"><a name="castExpr0Anchor">castExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('castExpr0')"><a name="castExpr0Anchor">castExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="castExpr0"><pre>Matches any cast nodes of Clang's AST.
Example: castExpr() matches each of the following:
@@ -741,7 +776,7 @@ but does not match
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('characterLiteral0')"><a name="characterLiteral0Anchor">characterLiteral</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('characterLiteral0')"><a name="characterLiteral0Anchor">characterLiteral</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="characterLiteral0"><pre>Matches character literals (also matches wchar_t).
Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral),
@@ -753,7 +788,7 @@ Example matches 'a', L'a'
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('compoundLiteralExpr0')"><a name="compoundLiteralExpr0Anchor">compoundLiteralExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('compoundLiteralExpr0')"><a name="compoundLiteralExpr0Anchor">compoundLiteralExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="compoundLiteralExpr0"><pre>Matches compound (i.e. non-scalar) literals
Example match: {1}, (1, 2)
@@ -762,7 +797,7 @@ Example match: {1}, (1, 2)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('compoundStmt0')"><a name="compoundStmt0Anchor">compoundStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('compoundStmt0')"><a name="compoundStmt0Anchor">compoundStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="compoundStmt0"><pre>Matches compound statements.
Example matches '{}' and '{{}}' in 'for (;;) {{}}'
@@ -770,7 +805,7 @@ Example matches '{}' and '{{}}' in 'for (;;) {{}}'
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('conditionalOperator0')"><a name="conditionalOperator0Anchor">conditionalOperator</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ConditionalOperator.html">ConditionalOperator</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('conditionalOperator0')"><a name="conditionalOperator0Anchor">conditionalOperator</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ConditionalOperator.html">ConditionalOperator</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="conditionalOperator0"><pre>Matches conditional operator expressions.
Example matches a ? b : c
@@ -778,7 +813,18 @@ Example matches a ? b : c
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('continueStmt0')"><a name="continueStmt0Anchor">continueStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ContinueStmt.html">ContinueStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('constantExpr0')"><a name="constantExpr0Anchor">constantExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ConstantExpr.html">ConstantExpr</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="constantExpr0"><pre>Matches a constant expression wrapper.
+
+Example matches the constant in the case statement:
+ (matcher = constantExpr())
+ switch (a) {
+ case 37: break;
+ }
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('continueStmt0')"><a name="continueStmt0Anchor">continueStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ContinueStmt.html">ContinueStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="continueStmt0"><pre>Matches continue statements.
Given
@@ -788,7 +834,7 @@ continueStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cudaKernelCallExpr0')"><a name="cudaKernelCallExpr0Anchor">cudaKernelCallExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CUDAKernelCallExpr.html">CUDAKernelCallExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cudaKernelCallExpr0')"><a name="cudaKernelCallExpr0Anchor">cudaKernelCallExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CUDAKernelCallExpr.html">CUDAKernelCallExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cudaKernelCallExpr0"><pre>Matches CUDA kernel call expression.
Example matches,
@@ -796,7 +842,7 @@ Example matches,
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxBindTemporaryExpr0')"><a name="cxxBindTemporaryExpr0Anchor">cxxBindTemporaryExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBindTemporaryExpr.html">CXXBindTemporaryExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxBindTemporaryExpr0')"><a name="cxxBindTemporaryExpr0Anchor">cxxBindTemporaryExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBindTemporaryExpr.html">CXXBindTemporaryExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxBindTemporaryExpr0"><pre>Matches nodes where temporaries are created.
Example matches FunctionTakesString(GetStringByValue())
@@ -806,7 +852,7 @@ Example matches FunctionTakesString(GetStringByValue())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxBoolLiteral0')"><a name="cxxBoolLiteral0Anchor">cxxBoolLiteral</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxBoolLiteral0')"><a name="cxxBoolLiteral0Anchor">cxxBoolLiteral</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxBoolLiteral0"><pre>Matches bool literals.
Example matches true
@@ -814,7 +860,7 @@ Example matches true
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxCatchStmt0')"><a name="cxxCatchStmt0Anchor">cxxCatchStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCatchStmt.html">CXXCatchStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxCatchStmt0')"><a name="cxxCatchStmt0Anchor">cxxCatchStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCatchStmt.html">CXXCatchStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxCatchStmt0"><pre>Matches catch statements.
try {} catch(int i) {}
@@ -823,7 +869,7 @@ cxxCatchStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxConstCastExpr0')"><a name="cxxConstCastExpr0Anchor">cxxConstCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstCastExpr.html">CXXConstCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxConstCastExpr0')"><a name="cxxConstCastExpr0Anchor">cxxConstCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstCastExpr.html">CXXConstCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConstCastExpr0"><pre>Matches a const_cast expression.
Example: Matches const_cast&lt;int*&gt;(&amp;r) in
@@ -833,7 +879,7 @@ Example: Matches const_cast&lt;int*&gt;(&amp;r) in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxConstructExpr0')"><a name="cxxConstructExpr0Anchor">cxxConstructExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxConstructExpr0')"><a name="cxxConstructExpr0Anchor">cxxConstructExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConstructExpr0"><pre>Matches constructor call expressions (including implicit ones).
Example matches string(ptr, n) and ptr within arguments of f
@@ -845,7 +891,7 @@ Example matches string(ptr, n) and ptr within arguments of f
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDefaultArgExpr0')"><a name="cxxDefaultArgExpr0Anchor">cxxDefaultArgExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXDefaultArgExpr.html">CXXDefaultArgExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDefaultArgExpr0')"><a name="cxxDefaultArgExpr0Anchor">cxxDefaultArgExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDefaultArgExpr.html">CXXDefaultArgExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDefaultArgExpr0"><pre>Matches the value of a default argument at the call site.
Example matches the CXXDefaultArgExpr placeholder inserted for the
@@ -856,7 +902,7 @@ Example matches the CXXDefaultArgExpr placeholder inserted for the
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDeleteExpr0')"><a name="cxxDeleteExpr0Anchor">cxxDeleteExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXDeleteExpr.html">CXXDeleteExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDeleteExpr0')"><a name="cxxDeleteExpr0Anchor">cxxDeleteExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDeleteExpr.html">CXXDeleteExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDeleteExpr0"><pre>Matches delete expressions.
Given
@@ -866,7 +912,18 @@ cxxDeleteExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDynamicCastExpr0')"><a name="cxxDynamicCastExpr0Anchor">cxxDynamicCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXDynamicCastExpr.html">CXXDynamicCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDependentScopeMemberExpr0')"><a name="cxxDependentScopeMemberExpr0Anchor">cxxDependentScopeMemberExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="cxxDependentScopeMemberExpr0"><pre>Matches member expressions where the actual member referenced could not be
+resolved because the base expression or the member name was dependent.
+
+Given
+ template &lt;class T&gt; void f() { T t; t.g(); }
+cxxDependentScopeMemberExpr()
+ matches t.g
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxDynamicCastExpr0')"><a name="cxxDynamicCastExpr0Anchor">cxxDynamicCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDynamicCastExpr.html">CXXDynamicCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDynamicCastExpr0"><pre>Matches a dynamic_cast expression.
Example:
@@ -880,7 +937,7 @@ in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxForRangeStmt0')"><a name="cxxForRangeStmt0Anchor">cxxForRangeStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxForRangeStmt0')"><a name="cxxForRangeStmt0Anchor">cxxForRangeStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxForRangeStmt0"><pre>Matches range-based for statements.
cxxForRangeStmt() matches 'for (auto a : i)'
@@ -889,7 +946,7 @@ cxxForRangeStmt() matches 'for (auto a : i)'
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxFunctionalCastExpr0')"><a name="cxxFunctionalCastExpr0Anchor">cxxFunctionalCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxFunctionalCastExpr0')"><a name="cxxFunctionalCastExpr0Anchor">cxxFunctionalCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxFunctionalCastExpr0"><pre>Matches functional cast expressions
Example: Matches Foo(bar);
@@ -899,7 +956,7 @@ Example: Matches Foo(bar);
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxMemberCallExpr0')"><a name="cxxMemberCallExpr0Anchor">cxxMemberCallExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxMemberCallExpr0')"><a name="cxxMemberCallExpr0Anchor">cxxMemberCallExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxMemberCallExpr0"><pre>Matches member call expressions.
Example matches x.y()
@@ -908,7 +965,7 @@ Example matches x.y()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxNewExpr0')"><a name="cxxNewExpr0Anchor">cxxNewExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxNewExpr0')"><a name="cxxNewExpr0Anchor">cxxNewExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxNewExpr0"><pre>Matches new expressions.
Given
@@ -918,12 +975,12 @@ cxxNewExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxNullPtrLiteralExpr0')"><a name="cxxNullPtrLiteralExpr0Anchor">cxxNullPtrLiteralExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNullPtrLiteralExpr.html">CXXNullPtrLiteralExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxNullPtrLiteralExpr0')"><a name="cxxNullPtrLiteralExpr0Anchor">cxxNullPtrLiteralExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNullPtrLiteralExpr.html">CXXNullPtrLiteralExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxNullPtrLiteralExpr0"><pre>Matches nullptr literal.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxOperatorCallExpr0')"><a name="cxxOperatorCallExpr0Anchor">cxxOperatorCallExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxOperatorCallExpr0')"><a name="cxxOperatorCallExpr0Anchor">cxxOperatorCallExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxOperatorCallExpr0"><pre>Matches overloaded operator calls.
Note that if an operator isn't overloaded, it won't match. Instead, use
@@ -939,7 +996,7 @@ Example matches both operator&lt;&lt;((o &lt;&lt; b), c) and operator&lt;&lt;(o,
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxReinterpretCastExpr0')"><a name="cxxReinterpretCastExpr0Anchor">cxxReinterpretCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXReinterpretCastExpr.html">CXXReinterpretCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxReinterpretCastExpr0')"><a name="cxxReinterpretCastExpr0Anchor">cxxReinterpretCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXReinterpretCastExpr.html">CXXReinterpretCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxReinterpretCastExpr0"><pre>Matches a reinterpret_cast expression.
Either the source expression or the destination type can be matched
@@ -951,7 +1008,7 @@ Example matches reinterpret_cast&lt;char*&gt;(&amp;p) in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStaticCastExpr0')"><a name="cxxStaticCastExpr0Anchor">cxxStaticCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXStaticCastExpr.html">CXXStaticCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStaticCastExpr0')"><a name="cxxStaticCastExpr0Anchor">cxxStaticCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXStaticCastExpr.html">CXXStaticCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxStaticCastExpr0"><pre>Matches a C++ static_cast expression.
See also: hasDestinationType
@@ -966,7 +1023,7 @@ in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStdInitializerListExpr0')"><a name="cxxStdInitializerListExpr0Anchor">cxxStdInitializerListExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXStdInitializerListExpr.html">CXXStdInitializerListExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStdInitializerListExpr0')"><a name="cxxStdInitializerListExpr0Anchor">cxxStdInitializerListExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXStdInitializerListExpr.html">CXXStdInitializerListExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxStdInitializerListExpr0"><pre>Matches C++ initializer list expressions.
Given
@@ -979,7 +1036,7 @@ cxxStdInitializerListExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxTemporaryObjectExpr0')"><a name="cxxTemporaryObjectExpr0Anchor">cxxTemporaryObjectExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxTemporaryObjectExpr0')"><a name="cxxTemporaryObjectExpr0Anchor">cxxTemporaryObjectExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxTemporaryObjectExpr0"><pre>Matches functional cast expressions having N != 1 arguments
Example: Matches Foo(bar, bar)
@@ -987,7 +1044,7 @@ Example: Matches Foo(bar, bar)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxThisExpr0')"><a name="cxxThisExpr0Anchor">cxxThisExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXThisExpr.html">CXXThisExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxThisExpr0')"><a name="cxxThisExpr0Anchor">cxxThisExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXThisExpr.html">CXXThisExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxThisExpr0"><pre>Matches implicit and explicit this expressions.
Example matches the implicit this expression in "return i".
@@ -999,7 +1056,7 @@ struct foo {
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxThrowExpr0')"><a name="cxxThrowExpr0Anchor">cxxThrowExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXThrowExpr.html">CXXThrowExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxThrowExpr0')"><a name="cxxThrowExpr0Anchor">cxxThrowExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXThrowExpr.html">CXXThrowExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxThrowExpr0"><pre>Matches throw expressions.
try { throw 5; } catch(int i) {}
@@ -1008,7 +1065,7 @@ cxxThrowExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxTryStmt0')"><a name="cxxTryStmt0Anchor">cxxTryStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXTryStmt.html">CXXTryStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxTryStmt0')"><a name="cxxTryStmt0Anchor">cxxTryStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTryStmt.html">CXXTryStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxTryStmt0"><pre>Matches try statements.
try {} catch(int i) {}
@@ -1017,7 +1074,7 @@ cxxTryStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxUnresolvedConstructExpr0')"><a name="cxxUnresolvedConstructExpr0Anchor">cxxUnresolvedConstructExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxUnresolvedConstructExpr0')"><a name="cxxUnresolvedConstructExpr0Anchor">cxxUnresolvedConstructExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxUnresolvedConstructExpr0"><pre>Matches unresolved constructor call expressions.
Example matches T(t) in return statement of f
@@ -1027,7 +1084,7 @@ Example matches T(t) in return statement of f
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('declRefExpr0')"><a name="declRefExpr0Anchor">declRefExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('declRefExpr0')"><a name="declRefExpr0Anchor">declRefExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="declRefExpr0"><pre>Matches expressions that refer to declarations.
Example matches x in if (x)
@@ -1036,7 +1093,7 @@ Example matches x in if (x)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('declStmt0')"><a name="declStmt0Anchor">declStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('declStmt0')"><a name="declStmt0Anchor">declStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="declStmt0"><pre>Matches declaration statements.
Given
@@ -1046,7 +1103,7 @@ declStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('defaultStmt0')"><a name="defaultStmt0Anchor">defaultStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DefaultStmt.html">DefaultStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('defaultStmt0')"><a name="defaultStmt0Anchor">defaultStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DefaultStmt.html">DefaultStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="defaultStmt0"><pre>Matches default statements inside switch statements.
Given
@@ -1056,7 +1113,7 @@ defaultStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('designatedInitExpr0')"><a name="designatedInitExpr0Anchor">designatedInitExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DesignatedInitExpr.html">DesignatedInitExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('designatedInitExpr0')"><a name="designatedInitExpr0Anchor">designatedInitExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DesignatedInitExpr.html">DesignatedInitExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="designatedInitExpr0"><pre>Matches C99 designated initializer expressions [C99 6.7.8].
Example: Matches { [2].y = 1.0, [0].x = 1.0 }
@@ -1064,7 +1121,7 @@ Example: Matches { [2].y = 1.0, [0].x = 1.0 }
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('doStmt0')"><a name="doStmt0Anchor">doStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('doStmt0')"><a name="doStmt0Anchor">doStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="doStmt0"><pre>Matches do statements.
Given
@@ -1074,7 +1131,7 @@ doStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('explicitCastExpr0')"><a name="explicitCastExpr0Anchor">explicitCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('explicitCastExpr0')"><a name="explicitCastExpr0Anchor">explicitCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="explicitCastExpr0"><pre>Matches explicit cast expressions.
Matches any cast expression written in user code, whether it be a
@@ -1095,7 +1152,7 @@ but does not match the implicit conversion in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('expr0')"><a name="expr0Anchor">expr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('expr0')"><a name="expr0Anchor">expr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="expr0"><pre>Matches expressions.
Example matches x()
@@ -1103,7 +1160,7 @@ Example matches x()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('exprWithCleanups0')"><a name="exprWithCleanups0Anchor">exprWithCleanups</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ExprWithCleanups.html">ExprWithCleanups</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('exprWithCleanups0')"><a name="exprWithCleanups0Anchor">exprWithCleanups</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ExprWithCleanups.html">ExprWithCleanups</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="exprWithCleanups0"><pre>Matches expressions that introduce cleanups to be run at the end
of the sub-expression's evaluation.
@@ -1112,8 +1169,8 @@ Example matches std::string()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('floatLiteral0')"><a name="floatLiteral0Anchor">floatLiteral</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;...</td></tr>
-<tr><td colspan="4" class="doc" id="floatLiteral0"><pre>Matches float literals of all sizes encodings, e.g.
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('floatLiteral0')"><a name="floatLiteral0Anchor">floatLiteral</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="floatLiteral0"><pre>Matches float literals of all sizes / encodings, e.g.
1.0, 1.0f, 1.0L and 1e10.
Does not match implicit conversions such as
@@ -1121,7 +1178,7 @@ Does not match implicit conversions such as
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('forStmt0')"><a name="forStmt0Anchor">forStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('forStmt0')"><a name="forStmt0Anchor">forStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="forStmt0"><pre>Matches for statements.
Example matches 'for (;;) {}'
@@ -1130,12 +1187,12 @@ Example matches 'for (;;) {}'
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('gnuNullExpr0')"><a name="gnuNullExpr0Anchor">gnuNullExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1GNUNullExpr.html">GNUNullExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('gnuNullExpr0')"><a name="gnuNullExpr0Anchor">gnuNullExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1GNUNullExpr.html">GNUNullExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="gnuNullExpr0"><pre>Matches GNU __null expression.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('gotoStmt0')"><a name="gotoStmt0Anchor">gotoStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1GotoStmt.html">GotoStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('gotoStmt0')"><a name="gotoStmt0Anchor">gotoStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1GotoStmt.html">GotoStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="gotoStmt0"><pre>Matches goto statements.
Given
@@ -1146,7 +1203,7 @@ gotoStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('ifStmt0')"><a name="ifStmt0Anchor">ifStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('ifStmt0')"><a name="ifStmt0Anchor">ifStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="ifStmt0"><pre>Matches if statements.
Example matches 'if (x) {}'
@@ -1154,7 +1211,13 @@ Example matches 'if (x) {}'
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('implicitCastExpr0')"><a name="implicitCastExpr0Anchor">implicitCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ImplicitCastExpr.html">ImplicitCastExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('imaginaryLiteral0')"><a name="imaginaryLiteral0Anchor">imaginaryLiteral</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ImaginaryLiteral.html">ImaginaryLiteral</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="imaginaryLiteral0"><pre>Matches imaginary literals, which are based on integer and floating
+point literals e.g.: 1i, 1.0i
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('implicitCastExpr0')"><a name="implicitCastExpr0Anchor">implicitCastExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ImplicitCastExpr.html">ImplicitCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="implicitCastExpr0"><pre>Matches the implicit cast nodes of Clang's AST.
This matches many different places, including function call return value
@@ -1162,7 +1225,7 @@ eliding, as well as any type conversions.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('implicitValueInitExpr0')"><a name="implicitValueInitExpr0Anchor">implicitValueInitExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ImplicitValueInitExpr.html">ImplicitValueInitExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('implicitValueInitExpr0')"><a name="implicitValueInitExpr0Anchor">implicitValueInitExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ImplicitValueInitExpr.html">ImplicitValueInitExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="implicitValueInitExpr0"><pre>Matches implicit initializers of init list expressions.
Given
@@ -1172,7 +1235,7 @@ implicitValueInitExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('initListExpr0')"><a name="initListExpr0Anchor">initListExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('initListExpr0')"><a name="initListExpr0Anchor">initListExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="initListExpr0"><pre>Matches init list expressions.
Given
@@ -1184,15 +1247,15 @@ initListExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('integerLiteral0')"><a name="integerLiteral0Anchor">integerLiteral</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;...</td></tr>
-<tr><td colspan="4" class="doc" id="integerLiteral0"><pre>Matches integer literals of all sizes encodings, e.g.
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('integerLiteral0')"><a name="integerLiteral0Anchor">integerLiteral</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="integerLiteral0"><pre>Matches integer literals of all sizes / encodings, e.g.
1, 1L, 0x1 and 1U.
Does not match character-encoded integers such as L'a'.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('labelStmt0')"><a name="labelStmt0Anchor">labelStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('labelStmt0')"><a name="labelStmt0Anchor">labelStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="labelStmt0"><pre>Matches label statements.
Given
@@ -1203,7 +1266,7 @@ labelStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('lambdaExpr0')"><a name="lambdaExpr0Anchor">lambdaExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html">LambdaExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('lambdaExpr0')"><a name="lambdaExpr0Anchor">lambdaExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html">LambdaExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="lambdaExpr0"><pre>Matches lambda expressions.
Example matches [&amp;](){return 5;}
@@ -1211,7 +1274,7 @@ Example matches [&amp;](){return 5;}
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('materializeTemporaryExpr0')"><a name="materializeTemporaryExpr0Anchor">materializeTemporaryExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MaterializeTemporaryExpr.html">MaterializeTemporaryExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('materializeTemporaryExpr0')"><a name="materializeTemporaryExpr0Anchor">materializeTemporaryExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MaterializeTemporaryExpr.html">MaterializeTemporaryExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="materializeTemporaryExpr0"><pre>Matches nodes where temporaries are materialized.
Example: Given
@@ -1227,7 +1290,7 @@ but does not match
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('memberExpr0')"><a name="memberExpr0Anchor">memberExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('memberExpr0')"><a name="memberExpr0Anchor">memberExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="memberExpr0"><pre>Matches member expressions.
Given
@@ -1240,7 +1303,7 @@ memberExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('nullStmt0')"><a name="nullStmt0Anchor">nullStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NullStmt.html">NullStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('nullStmt0')"><a name="nullStmt0Anchor">nullStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NullStmt.html">NullStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="nullStmt0"><pre>Matches null statements.
foo();;
@@ -1249,7 +1312,7 @@ nullStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcCatchStmt0')"><a name="objcCatchStmt0Anchor">objcCatchStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCAtCatchStmt.html">ObjCAtCatchStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcCatchStmt0')"><a name="objcCatchStmt0Anchor">objcCatchStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtCatchStmt.html">ObjCAtCatchStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcCatchStmt0"><pre>Matches Objective-C @catch statements.
Example matches @catch
@@ -1258,7 +1321,7 @@ Example matches @catch
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcFinallyStmt0')"><a name="objcFinallyStmt0Anchor">objcFinallyStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCAtFinallyStmt.html">ObjCAtFinallyStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcFinallyStmt0')"><a name="objcFinallyStmt0Anchor">objcFinallyStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtFinallyStmt.html">ObjCAtFinallyStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcFinallyStmt0"><pre>Matches Objective-C @finally statements.
Example matches @finally
@@ -1267,7 +1330,7 @@ Example matches @finally
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcIvarRefExpr0')"><a name="objcIvarRefExpr0Anchor">objcIvarRefExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCIvarRefExpr.html">ObjCIvarRefExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcIvarRefExpr0')"><a name="objcIvarRefExpr0Anchor">objcIvarRefExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCIvarRefExpr.html">ObjCIvarRefExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcIvarRefExpr0"><pre>Matches a reference to an ObjCIvar.
Example: matches "a" in "init" method:
@@ -1277,11 +1340,10 @@ Example: matches "a" in "init" method:
- (void) init {
a = @"hello";
}
-}
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcMessageExpr0')"><a name="objcMessageExpr0Anchor">objcMessageExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcMessageExpr0')"><a name="objcMessageExpr0Anchor">objcMessageExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcMessageExpr0"><pre>Matches ObjectiveC Message invocation expressions.
The innermost message send invokes the "alloc" class method on the
@@ -1292,14 +1354,14 @@ NSString's "alloc". This matcher should match both message sends.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcThrowStmt0')"><a name="objcThrowStmt0Anchor">objcThrowStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCAtThrowStmt.html">ObjCAtThrowStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcThrowStmt0')"><a name="objcThrowStmt0Anchor">objcThrowStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtThrowStmt.html">ObjCAtThrowStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcThrowStmt0"><pre>Matches Objective-C statements.
Example matches @throw obj;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcTryStmt0')"><a name="objcTryStmt0Anchor">objcTryStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCAtTryStmt.html">ObjCAtTryStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('objcTryStmt0')"><a name="objcTryStmt0Anchor">objcTryStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAtTryStmt.html">ObjCAtTryStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcTryStmt0"><pre>Matches Objective-C @try statements.
Example matches @try
@@ -1308,7 +1370,7 @@ Example matches @try
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('opaqueValueExpr0')"><a name="opaqueValueExpr0Anchor">opaqueValueExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('opaqueValueExpr0')"><a name="opaqueValueExpr0Anchor">opaqueValueExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="opaqueValueExpr0"><pre>Matches opaque value expressions. They are used as helpers
to reference another expressions and can be met
in BinaryConditionalOperators, for example.
@@ -1318,7 +1380,7 @@ Example matches 'a'
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('parenExpr0')"><a name="parenExpr0Anchor">parenExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenExpr.html">ParenExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('parenExpr0')"><a name="parenExpr0Anchor">parenExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParenExpr.html">ParenExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="parenExpr0"><pre>Matches parentheses used in expressions.
Example matches (foo() + 1)
@@ -1327,7 +1389,7 @@ Example matches (foo() + 1)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('parenListExpr0')"><a name="parenListExpr0Anchor">parenListExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenListExpr.html">ParenListExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('parenListExpr0')"><a name="parenListExpr0Anchor">parenListExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParenListExpr.html">ParenListExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="parenListExpr0"><pre>Matches paren list expressions.
ParenListExprs don't have a predefined type and are used for late parsing.
In the final AST, they can be met in template declarations.
@@ -1344,7 +1406,7 @@ has a predefined type and is a ParenExpr, not a ParenListExpr.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('predefinedExpr0')"><a name="predefinedExpr0Anchor">predefinedExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PredefinedExpr.html">PredefinedExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('predefinedExpr0')"><a name="predefinedExpr0Anchor">predefinedExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1PredefinedExpr.html">PredefinedExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="predefinedExpr0"><pre>Matches predefined identifier expressions [C99 6.4.2.2].
Example: Matches __func__
@@ -1352,7 +1414,7 @@ Example: Matches __func__
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('returnStmt0')"><a name="returnStmt0Anchor">returnStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html">ReturnStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('returnStmt0')"><a name="returnStmt0Anchor">returnStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html">ReturnStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="returnStmt0"><pre>Matches return statements.
Given
@@ -1362,7 +1424,7 @@ returnStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('stmt0')"><a name="stmt0Anchor">stmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('stmt0')"><a name="stmt0Anchor">stmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="stmt0"><pre>Matches statements.
Given
@@ -1372,7 +1434,7 @@ stmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('stmtExpr0')"><a name="stmtExpr0Anchor">stmtExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1StmtExpr.html">StmtExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('stmtExpr0')"><a name="stmtExpr0Anchor">stmtExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1StmtExpr.html">StmtExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="stmtExpr0"><pre>Matches statement expression (GNU extension).
Example match: ({ int X = 4; X; })
@@ -1380,7 +1442,7 @@ Example match: ({ int X = 4; X; })
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('stringLiteral0')"><a name="stringLiteral0Anchor">stringLiteral</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1StringLiteral.html">StringLiteral</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('stringLiteral0')"><a name="stringLiteral0Anchor">stringLiteral</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1StringLiteral.html">StringLiteral</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="stringLiteral0"><pre>Matches string literals (also matches wide string literals).
Example matches "abcd", L"abcd"
@@ -1389,7 +1451,7 @@ Example matches "abcd", L"abcd"
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('substNonTypeTemplateParmExpr0')"><a name="substNonTypeTemplateParmExpr0Anchor">substNonTypeTemplateParmExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SubstNonTypeTemplateParmExpr.html">SubstNonTypeTemplateParmExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('substNonTypeTemplateParmExpr0')"><a name="substNonTypeTemplateParmExpr0Anchor">substNonTypeTemplateParmExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SubstNonTypeTemplateParmExpr.html">SubstNonTypeTemplateParmExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="substNonTypeTemplateParmExpr0"><pre>Matches substitutions of non-type template parameters.
Given
@@ -1401,7 +1463,7 @@ substNonTypeTemplateParmExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('switchCase0')"><a name="switchCase0Anchor">switchCase</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchCase.html">SwitchCase</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('switchCase0')"><a name="switchCase0Anchor">switchCase</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SwitchCase.html">SwitchCase</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="switchCase0"><pre>Matches case and default statements inside switch statements.
Given
@@ -1411,7 +1473,7 @@ switchCase()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('switchStmt0')"><a name="switchStmt0Anchor">switchStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('switchStmt0')"><a name="switchStmt0Anchor">switchStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="switchStmt0"><pre>Matches switch statements.
Given
@@ -1421,7 +1483,7 @@ switchStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('unaryExprOrTypeTraitExpr0')"><a name="unaryExprOrTypeTraitExpr0Anchor">unaryExprOrTypeTraitExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('unaryExprOrTypeTraitExpr0')"><a name="unaryExprOrTypeTraitExpr0Anchor">unaryExprOrTypeTraitExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="unaryExprOrTypeTraitExpr0"><pre>Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
Given
@@ -1432,7 +1494,7 @@ unaryExprOrTypeTraitExpr()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('unaryOperator0')"><a name="unaryOperator0Anchor">unaryOperator</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('unaryOperator0')"><a name="unaryOperator0Anchor">unaryOperator</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="unaryOperator0"><pre>Matches unary operator expressions.
Example matches !a
@@ -1440,7 +1502,7 @@ Example matches !a
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('unresolvedLookupExpr0')"><a name="unresolvedLookupExpr0Anchor">unresolvedLookupExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedLookupExpr.html">UnresolvedLookupExpr</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('unresolvedLookupExpr0')"><a name="unresolvedLookupExpr0Anchor">unresolvedLookupExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedLookupExpr.html">UnresolvedLookupExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="unresolvedLookupExpr0"><pre>Matches reference to a name that can be looked up during parsing
but could not be resolved to a specific declaration.
@@ -1455,14 +1517,28 @@ unresolvedLookupExpr()
matches foo&lt;T&gt;() </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('userDefinedLiteral0')"><a name="userDefinedLiteral0Anchor">userDefinedLiteral</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UserDefinedLiteral.html">UserDefinedLiteral</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('unresolvedMemberExpr0')"><a name="unresolvedMemberExpr0Anchor">unresolvedMemberExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html">UnresolvedMemberExpr</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="unresolvedMemberExpr0"><pre>Matches unresolved member expressions.
+
+Given
+ struct X {
+ template &lt;class T&gt; void f();
+ void g();
+ };
+ template &lt;class T&gt; void h() { X x; x.f&lt;T&gt;(); x.g(); }
+unresolvedMemberExpr()
+ matches x.f&lt;T&gt;
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('userDefinedLiteral0')"><a name="userDefinedLiteral0Anchor">userDefinedLiteral</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UserDefinedLiteral.html">UserDefinedLiteral</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="userDefinedLiteral0"><pre>Matches user defined literal operator call.
Example match: "foo"_suffix
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('whileStmt0')"><a name="whileStmt0Anchor">whileStmt</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1WhileStmt.html">WhileStmt</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('whileStmt0')"><a name="whileStmt0Anchor">whileStmt</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1WhileStmt.html">WhileStmt</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="whileStmt0"><pre>Matches while statements.
Given
@@ -1472,7 +1548,7 @@ whileStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('templateArgument0')"><a name="templateArgument0Anchor">templateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('templateArgument0')"><a name="templateArgument0Anchor">templateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="templateArgument0"><pre>Matches template arguments.
Given
@@ -1483,7 +1559,7 @@ templateArgument()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;</td><td class="name" onclick="toggle('templateName0')"><a name="templateName0Anchor">templateName</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;</td><td class="name" onclick="toggle('templateName0')"><a name="templateName0Anchor">templateName</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="templateName0"><pre>Matches template name.
Given
@@ -1494,12 +1570,12 @@ templateName()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('typeLoc0')"><a name="typeLoc0Anchor">typeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('typeLoc0')"><a name="typeLoc0Anchor">typeLoc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typeLoc0"><pre>Matches TypeLocs in the clang AST.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('arrayType0')"><a name="arrayType0Anchor">arrayType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('arrayType0')"><a name="arrayType0Anchor">arrayType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="arrayType0"><pre>Matches all kinds of arrays.
Given
@@ -1511,7 +1587,7 @@ arrayType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('atomicType0')"><a name="atomicType0Anchor">atomicType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('atomicType0')"><a name="atomicType0Anchor">atomicType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="atomicType0"><pre>Matches atomic types.
Given
@@ -1521,7 +1597,7 @@ atomicType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('autoType0')"><a name="autoType0Anchor">autoType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('autoType0')"><a name="autoType0Anchor">autoType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="autoType0"><pre>Matches types nodes representing C++11 auto types.
Given:
@@ -1533,7 +1609,7 @@ autoType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('blockPointerType0')"><a name="blockPointerType0Anchor">blockPointerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('blockPointerType0')"><a name="blockPointerType0Anchor">blockPointerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="blockPointerType0"><pre>Matches block pointer types, i.e. types syntactically represented as
"void (^)(int)".
@@ -1541,7 +1617,7 @@ The pointee is always required to be a FunctionType.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('builtinType0')"><a name="builtinType0Anchor">builtinType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BuiltinType.html">BuiltinType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('builtinType0')"><a name="builtinType0Anchor">builtinType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BuiltinType.html">BuiltinType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="builtinType0"><pre>Matches builtin Types.
Given
@@ -1555,7 +1631,7 @@ builtinType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('complexType0')"><a name="complexType0Anchor">complexType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('complexType0')"><a name="complexType0Anchor">complexType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="complexType0"><pre>Matches C99 complex types.
Given
@@ -1565,7 +1641,7 @@ complexType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('constantArrayType0')"><a name="constantArrayType0Anchor">constantArrayType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ConstantArrayType.html">ConstantArrayType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('constantArrayType0')"><a name="constantArrayType0Anchor">constantArrayType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ConstantArrayType.html">ConstantArrayType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="constantArrayType0"><pre>Matches C arrays with a specified constant size.
Given
@@ -1579,7 +1655,7 @@ constantArrayType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('decayedType0')"><a name="decayedType0Anchor">decayedType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecayedType.html">DecayedType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('decayedType0')"><a name="decayedType0Anchor">decayedType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DecayedType.html">DecayedType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="decayedType0"><pre>Matches decayed type
Example matches i[] in declaration of f.
(matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))
@@ -1591,19 +1667,19 @@ Example matches i[1].
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('decltypeType0')"><a name="decltypeType0Anchor">decltypeType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('decltypeType0')"><a name="decltypeType0Anchor">decltypeType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="decltypeType0"><pre>Matches types nodes representing C++11 decltype(&lt;expr&gt;) types.
Given:
short i = 1;
int j = 42;
decltype(i + j) result = i + j;
-decltypeType()
+decltypeType()
matches "decltype(i + j)"
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('dependentSizedArrayType0')"><a name="dependentSizedArrayType0Anchor">dependentSizedArrayType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DependentSizedArrayType.html">DependentSizedArrayType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('dependentSizedArrayType0')"><a name="dependentSizedArrayType0Anchor">dependentSizedArrayType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DependentSizedArrayType.html">DependentSizedArrayType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="dependentSizedArrayType0"><pre>Matches C++ arrays whose size is a value-dependent expression.
Given
@@ -1616,7 +1692,7 @@ dependentSizedArrayType
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('elaboratedType0')"><a name="elaboratedType0Anchor">elaboratedType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('elaboratedType0')"><a name="elaboratedType0Anchor">elaboratedType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="elaboratedType0"><pre>Matches types specified with an elaborated type keyword or with a
qualified name.
@@ -1636,7 +1712,7 @@ c and d.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('enumType0')"><a name="enumType0Anchor">enumType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('enumType0')"><a name="enumType0Anchor">enumType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="enumType0"><pre>Matches enum types.
Given
@@ -1651,7 +1727,7 @@ s.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('functionProtoType0')"><a name="functionProtoType0Anchor">functionProtoType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('functionProtoType0')"><a name="functionProtoType0Anchor">functionProtoType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="functionProtoType0"><pre>Matches FunctionProtoType nodes.
Given
@@ -1663,7 +1739,7 @@ functionProtoType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('functionType0')"><a name="functionType0Anchor">functionType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionType.html">FunctionType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('functionType0')"><a name="functionType0Anchor">functionType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionType.html">FunctionType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="functionType0"><pre>Matches FunctionType nodes.
Given
@@ -1674,7 +1750,7 @@ functionType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('incompleteArrayType0')"><a name="incompleteArrayType0Anchor">incompleteArrayType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IncompleteArrayType.html">IncompleteArrayType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('incompleteArrayType0')"><a name="incompleteArrayType0Anchor">incompleteArrayType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IncompleteArrayType.html">IncompleteArrayType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="incompleteArrayType0"><pre>Matches C arrays with unspecified size.
Given
@@ -1686,7 +1762,7 @@ incompleteArrayType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('injectedClassNameType0')"><a name="injectedClassNameType0Anchor">injectedClassNameType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('injectedClassNameType0')"><a name="injectedClassNameType0Anchor">injectedClassNameType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="injectedClassNameType0"><pre>Matches injected class name types.
Example matches S s, but not S&lt;T&gt; s.
@@ -1698,7 +1774,7 @@ Example matches S s, but not S&lt;T&gt; s.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('lValueReferenceType0')"><a name="lValueReferenceType0Anchor">lValueReferenceType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LValueReferenceType.html">LValueReferenceType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('lValueReferenceType0')"><a name="lValueReferenceType0Anchor">lValueReferenceType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LValueReferenceType.html">LValueReferenceType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="lValueReferenceType0"><pre>Matches lvalue reference types.
Given:
@@ -1715,7 +1791,7 @@ matched since the type is deduced as int&amp; by reference collapsing rules.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('memberPointerType0')"><a name="memberPointerType0Anchor">memberPointerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('memberPointerType0')"><a name="memberPointerType0Anchor">memberPointerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="memberPointerType0"><pre>Matches member pointer types.
Given
struct A { int i; }
@@ -1725,7 +1801,7 @@ memberPointerType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('objcObjectPointerType0')"><a name="objcObjectPointerType0Anchor">objcObjectPointerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCObjectPointerType.html">ObjCObjectPointerType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('objcObjectPointerType0')"><a name="objcObjectPointerType0Anchor">objcObjectPointerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCObjectPointerType.html">ObjCObjectPointerType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="objcObjectPointerType0"><pre>Matches an Objective-C object pointer type, which is different from
a pointer type, despite being syntactically similar.
@@ -1740,7 +1816,7 @@ pointerType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('parenType0')"><a name="parenType0Anchor">parenType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('parenType0')"><a name="parenType0Anchor">parenType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="parenType0"><pre>Matches ParenType nodes.
Given
@@ -1752,7 +1828,7 @@ array_of_ptrs.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('pointerType0')"><a name="pointerType0Anchor">pointerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('pointerType0')"><a name="pointerType0Anchor">pointerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="pointerType0"><pre>Matches pointer types, but does not match Objective-C object pointer
types.
@@ -1769,7 +1845,7 @@ pointerType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('rValueReferenceType0')"><a name="rValueReferenceType0Anchor">rValueReferenceType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RValueReferenceType.html">RValueReferenceType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('rValueReferenceType0')"><a name="rValueReferenceType0Anchor">rValueReferenceType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RValueReferenceType.html">RValueReferenceType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="rValueReferenceType0"><pre>Matches rvalue reference types.
Given:
@@ -1786,7 +1862,7 @@ matched as it is deduced to int&amp; by reference collapsing rules.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('recordType0')"><a name="recordType0Anchor">recordType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('recordType0')"><a name="recordType0Anchor">recordType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="recordType0"><pre>Matches record types (e.g. structs, classes).
Given
@@ -1801,7 +1877,7 @@ and s.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('referenceType0')"><a name="referenceType0Anchor">referenceType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('referenceType0')"><a name="referenceType0Anchor">referenceType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="referenceType0"><pre>Matches both lvalue and rvalue reference types.
Given
@@ -1817,7 +1893,7 @@ referenceType() matches the types of b, c, d, e, and f.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('substTemplateTypeParmType0')"><a name="substTemplateTypeParmType0Anchor">substTemplateTypeParmType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SubstTemplateTypeParmType.html">SubstTemplateTypeParmType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('substTemplateTypeParmType0')"><a name="substTemplateTypeParmType0Anchor">substTemplateTypeParmType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SubstTemplateTypeParmType.html">SubstTemplateTypeParmType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="substTemplateTypeParmType0"><pre>Matches types that represent the result of substituting a type for a
template type parameter.
@@ -1831,7 +1907,7 @@ substTemplateTypeParmType() matches the type of 't' but not '1'
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('tagType0')"><a name="tagType0Anchor">tagType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('tagType0')"><a name="tagType0Anchor">tagType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="tagType0"><pre>Matches tag types (record and enum types).
Given
@@ -1846,22 +1922,22 @@ and c.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('templateSpecializationType0')"><a name="templateSpecializationType0Anchor">templateSpecializationType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('templateSpecializationType0')"><a name="templateSpecializationType0Anchor">templateSpecializationType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="templateSpecializationType0"><pre>Matches template specialization types.
Given
template &lt;typename T&gt;
class C { };
- template class C&lt;int&gt;; A
- C&lt;char&gt; var; B
+ template class C&lt;int&gt;; // A
+ C&lt;char&gt; var; // B
templateSpecializationType() matches the type of the explicit
instantiation in A and the type of the variable declaration in B.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('templateTypeParmType0')"><a name="templateTypeParmType0Anchor">templateTypeParmType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('templateTypeParmType0')"><a name="templateTypeParmType0Anchor">templateTypeParmType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="templateTypeParmType0"><pre>Matches template type parameter types.
Example matches T, but not int.
@@ -1870,12 +1946,12 @@ Example matches T, but not int.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('type0')"><a name="type0Anchor">type</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('type0')"><a name="type0Anchor">type</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="type0"><pre>Matches Types in the clang AST.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('typedefType0')"><a name="typedefType0Anchor">typedefType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('typedefType0')"><a name="typedefType0Anchor">typedefType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typedefType0"><pre>Matches typedef types.
Given
@@ -1885,7 +1961,7 @@ typedefType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('unaryTransformType0')"><a name="unaryTransformType0Anchor">unaryTransformType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryTransformType.html">UnaryTransformType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('unaryTransformType0')"><a name="unaryTransformType0Anchor">unaryTransformType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryTransformType.html">UnaryTransformType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="unaryTransformType0"><pre>Matches types nodes representing unary type transformations.
Given:
@@ -1895,7 +1971,7 @@ unaryTransformType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('variableArrayType0')"><a name="variableArrayType0Anchor">variableArrayType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VariableArrayType.html">VariableArrayType</a>&gt;...</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('variableArrayType0')"><a name="variableArrayType0Anchor">variableArrayType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VariableArrayType.html">VariableArrayType</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="variableArrayType0"><pre>Matches C arrays with a specified size that is not an
integer-constant-expression.
@@ -1967,7 +2043,7 @@ Usable as: Any Matcher
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasOperatorName0')"><a name="hasOperatorName0Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasOperatorName0')"><a name="hasOperatorName0Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
<tr><td colspan="4" class="doc" id="hasOperatorName0"><pre>Matches the operator Name of operator expressions (binary or
unary).
@@ -1976,7 +2052,7 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator0')"><a name="isAssignmentOperator0Anchor">isAssignmentOperator</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator0')"><a name="isAssignmentOperator0Anchor">isAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAssignmentOperator0"><pre>Matches all kinds of assignment operators.
Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
@@ -1990,11 +2066,11 @@ Example 2: matches s1 = s2
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals5')"><a name="equals5Anchor">equals</a></td><td>bool Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals5')"><a name="equals5Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals5"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals2')"><a name="equals2Anchor">equals</a></td><td>const ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals2')"><a name="equals2Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals2"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -2015,36 +2091,35 @@ matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals11')"><a name="equals11Anchor">equals</a></td><td>double Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals11')"><a name="equals11Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals11"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals8')"><a name="equals8Anchor">equals</a></td><td>unsigned Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals8')"><a name="equals8Anchor">equals</a></td><td>unsigned Value</td></tr>
<tr><td colspan="4" class="doc" id="equals8"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCatchStmt.html">CXXCatchStmt</a>&gt;</td><td class="name" onclick="toggle('isCatchAll0')"><a name="isCatchAll0Anchor">isCatchAll</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCatchStmt.html">CXXCatchStmt</a>&gt;</td><td class="name" onclick="toggle('isCatchAll0')"><a name="isCatchAll0Anchor">isCatchAll</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isCatchAll0"><pre>Matches a C++ catch statement that has a catch-all handler.
Given
try {
- ...
+ // ...
} catch (int) {
- ...
+ // ...
} catch (...) {
- ...
+ // ...
}
-endcode
cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int).
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('argumentCountIs1')"><a name="argumentCountIs1Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('argumentCountIs1')"><a name="argumentCountIs1Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="argumentCountIs1"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
@@ -2054,12 +2129,12 @@ Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('isListInitialization0')"><a name="isListInitialization0Anchor">isListInitialization</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('isListInitialization0')"><a name="isListInitialization0Anchor">isListInitialization</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isListInitialization0"><pre>Matches a constructor call expression which uses list initialization.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('requiresZeroInitialization0')"><a name="requiresZeroInitialization0Anchor">requiresZeroInitialization</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('requiresZeroInitialization0')"><a name="requiresZeroInitialization0Anchor">requiresZeroInitialization</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="requiresZeroInitialization0"><pre>Matches a constructor call expression which requires
zero initialization.
@@ -2073,93 +2148,93 @@ will match the implicit array filler for pt[1].
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isCopyConstructor0')"><a name="isCopyConstructor0Anchor">isCopyConstructor</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isCopyConstructor0')"><a name="isCopyConstructor0Anchor">isCopyConstructor</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isCopyConstructor0"><pre>Matches constructor declarations that are copy constructors.
Given
struct S {
- S(); #1
- S(const S &amp;); #2
- S(S &amp;&amp;); #3
+ S(); // #1
+ S(const S &amp;); // #2
+ S(S &amp;&amp;); // #3
};
cxxConstructorDecl(isCopyConstructor()) will match #2, but not #1 or #3.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isDefaultConstructor0')"><a name="isDefaultConstructor0Anchor">isDefaultConstructor</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isDefaultConstructor0')"><a name="isDefaultConstructor0Anchor">isDefaultConstructor</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefaultConstructor0"><pre>Matches constructor declarations that are default constructors.
Given
struct S {
- S(); #1
- S(const S &amp;); #2
- S(S &amp;&amp;); #3
+ S(); // #1
+ S(const S &amp;); // #2
+ S(S &amp;&amp;); // #3
};
cxxConstructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isDelegatingConstructor0')"><a name="isDelegatingConstructor0Anchor">isDelegatingConstructor</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isDelegatingConstructor0')"><a name="isDelegatingConstructor0Anchor">isDelegatingConstructor</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDelegatingConstructor0"><pre>Matches constructors that delegate to another constructor.
Given
struct S {
- S(); #1
- S(int) {} #2
- S(S &amp;&amp;) : S() {} #3
+ S(); // #1
+ S(int) {} // #2
+ S(S &amp;&amp;) : S() {} // #3
};
- S::S() : S(0) {} #4
+ S::S() : S(0) {} // #4
cxxConstructorDecl(isDelegatingConstructor()) will match #3 and #4, but not
#1 or #2.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicit0')"><a name="isExplicit0Anchor">isExplicit</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicit0')"><a name="isExplicit0Anchor">isExplicit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExplicit0"><pre>Matches constructor and conversion declarations that are marked with
the explicit keyword.
Given
struct S {
- S(int); #1
- explicit S(double); #2
- operator int(); #3
- explicit operator bool(); #4
+ S(int); // #1
+ explicit S(double); // #2
+ operator int(); // #3
+ explicit operator bool(); // #4
};
cxxConstructorDecl(isExplicit()) will match #2, but not #1.
cxxConversionDecl(isExplicit()) will match #4, but not #3.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isMoveConstructor0')"><a name="isMoveConstructor0Anchor">isMoveConstructor</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('isMoveConstructor0')"><a name="isMoveConstructor0Anchor">isMoveConstructor</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isMoveConstructor0"><pre>Matches constructor declarations that are move constructors.
Given
struct S {
- S(); #1
- S(const S &amp;); #2
- S(S &amp;&amp;); #3
+ S(); // #1
+ S(const S &amp;); // #2
+ S(S &amp;&amp;); // #3
};
cxxConstructorDecl(isMoveConstructor()) will match #3, but not #1 or #2.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConversionDecl.html">CXXConversionDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicit1')"><a name="isExplicit1Anchor">isExplicit</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConversionDecl.html">CXXConversionDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicit1')"><a name="isExplicit1Anchor">isExplicit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExplicit1"><pre>Matches constructor and conversion declarations that are marked with
the explicit keyword.
Given
struct S {
- S(int); #1
- explicit S(double); #2
- operator int(); #3
- explicit operator bool(); #4
+ S(int); // #1
+ explicit S(double); // #2
+ operator int(); // #3
+ explicit operator bool(); // #4
};
cxxConstructorDecl(isExplicit()) will match #2, but not #1.
cxxConversionDecl(isExplicit()) will match #4, but not #3.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('isBaseInitializer0')"><a name="isBaseInitializer0Anchor">isBaseInitializer</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('isBaseInitializer0')"><a name="isBaseInitializer0Anchor">isBaseInitializer</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isBaseInitializer0"><pre>Matches a constructor initializer if it is initializing a base, as
opposed to a member.
@@ -2177,7 +2252,7 @@ cxxConstructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('isMemberInitializer0')"><a name="isMemberInitializer0Anchor">isMemberInitializer</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('isMemberInitializer0')"><a name="isMemberInitializer0Anchor">isMemberInitializer</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isMemberInitializer0"><pre>Matches a constructor initializer if it is initializing a member, as
opposed to a base.
@@ -2195,7 +2270,7 @@ cxxConstructorDecl(hasAnyConstructorInitializer(isMemberInitializer()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('isWritten0')"><a name="isWritten0Anchor">isWritten</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('isWritten0')"><a name="isWritten0Anchor">isWritten</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isWritten0"><pre>Matches a constructor initializer if it is explicitly written in
code (as opposed to implicitly added by the compiler).
@@ -2210,7 +2285,33 @@ cxxConstructorDecl(hasAnyConstructorInitializer(isWritten()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isConst0')"><a name="isConst0Anchor">isConst</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>&gt;</td><td class="name" onclick="toggle('isArrow2')"><a name="isArrow2Anchor">isArrow</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isArrow2"><pre>Matches member expressions that are called with '-&gt;' as opposed
+to '.'.
+
+Member calls on the implicit this pointer match as called with '-&gt;'.
+
+Given
+ class Y {
+ void x() { this-&gt;x(); x(); Y y; y.x(); a; this-&gt;b; Y::b; }
+ template &lt;class T&gt; void f() { this-&gt;f&lt;T&gt;(); f&lt;T&gt;(); }
+ int a;
+ static int b;
+ };
+ template &lt;class T&gt;
+ class Z {
+ void x() { this-&gt;m; }
+ };
+memberExpr(isArrow())
+ matches this-&gt;x, x, y.x, a, this-&gt;b
+cxxDependentScopeMemberExpr(isArrow())
+ matches this-&gt;m
+unresolvedMemberExpr(isArrow())
+ matches this-&gt;f&lt;T&gt;, f&lt;T&gt;
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isConst0')"><a name="isConst0Anchor">isConst</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isConst0"><pre>Matches if the given method declaration is const.
Given
@@ -2223,7 +2324,7 @@ cxxMethodDecl(isConst()) matches A::foo() but not A::bar()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isCopyAssignmentOperator0')"><a name="isCopyAssignmentOperator0Anchor">isCopyAssignmentOperator</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isCopyAssignmentOperator0')"><a name="isCopyAssignmentOperator0Anchor">isCopyAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isCopyAssignmentOperator0"><pre>Matches if the given method declaration declares a copy assignment
operator.
@@ -2238,7 +2339,7 @@ the second one.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isFinal1')"><a name="isFinal1Anchor">isFinal</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isFinal1')"><a name="isFinal1Anchor">isFinal</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isFinal1"><pre>Matches if the given method or class declaration is final.
Given:
@@ -2255,7 +2356,7 @@ matches A and C::f, but not B, C, or B::f
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isMoveAssignmentOperator0')"><a name="isMoveAssignmentOperator0Anchor">isMoveAssignmentOperator</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isMoveAssignmentOperator0')"><a name="isMoveAssignmentOperator0Anchor">isMoveAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isMoveAssignmentOperator0"><pre>Matches if the given method declaration declares a move assignment
operator.
@@ -2270,7 +2371,7 @@ the first one.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isOverride0')"><a name="isOverride0Anchor">isOverride</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isOverride0')"><a name="isOverride0Anchor">isOverride</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isOverride0"><pre>Matches if the given method declaration overrides another method.
Given
@@ -2286,7 +2387,7 @@ Given
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isPure0')"><a name="isPure0Anchor">isPure</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isPure0')"><a name="isPure0Anchor">isPure</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isPure0"><pre>Matches if the given method declaration is pure.
Given
@@ -2298,20 +2399,20 @@ Given
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isUserProvided0')"><a name="isUserProvided0Anchor">isUserProvided</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isUserProvided0')"><a name="isUserProvided0Anchor">isUserProvided</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isUserProvided0"><pre>Matches method declarations that are user-provided.
Given
struct S {
- S(); #1
- S(const S &amp;) = default; #2
- S(S &amp;&amp;) = delete; #3
+ S(); // #1
+ S(const S &amp;) = default; // #2
+ S(S &amp;&amp;) = delete; // #3
};
cxxConstructorDecl(isUserProvided()) will match #1, but not #2 or #3.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isVirtual0')"><a name="isVirtual0Anchor">isVirtual</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isVirtual0')"><a name="isVirtual0Anchor">isVirtual</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isVirtual0"><pre>Matches if the given method declaration is virtual.
Given
@@ -2323,7 +2424,7 @@ Given
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isVirtualAsWritten0')"><a name="isVirtualAsWritten0Anchor">isVirtualAsWritten</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isVirtualAsWritten0')"><a name="isVirtualAsWritten0Anchor">isVirtualAsWritten</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isVirtualAsWritten0"><pre>Matches if the given method declaration has an explicit "virtual".
Given
@@ -2339,7 +2440,7 @@ Given
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('isArray0')"><a name="isArray0Anchor">isArray</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('isArray0')"><a name="isArray0Anchor">isArray</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isArray0"><pre>Matches array new expressions.
Given:
@@ -2349,7 +2450,7 @@ cxxNewExpr(isArray())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;</td><td class="name" onclick="toggle('hasOverloadedOperatorName1')"><a name="hasOverloadedOperatorName1Anchor">hasOverloadedOperatorName</a></td><td>StringRef Name</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;</td><td class="name" onclick="toggle('hasOverloadedOperatorName1')"><a name="hasOverloadedOperatorName1Anchor">hasOverloadedOperatorName</a></td><td>StringRef Name</td></tr>
<tr><td colspan="4" class="doc" id="hasOverloadedOperatorName1"><pre>Matches overloaded operator names.
Matches overloaded operator names specified in strings without the
@@ -2359,18 +2460,18 @@ Given:
class A { int operator*(); };
const A &amp;operator&lt;&lt;(const A &amp;a, const A &amp;b);
A a;
- a &lt;&lt; a; &lt;-- This matches
+ a &lt;&lt; a; // &lt;-- This matches
cxxOperatorCallExpr(hasOverloadedOperatorName("&lt;&lt;"))) matches the
specified line and
cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
matches the declaration of A.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator1')"><a name="isAssignmentOperator1Anchor">isAssignmentOperator</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator1')"><a name="isAssignmentOperator1Anchor">isAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAssignmentOperator1"><pre>Matches all kinds of assignment operators.
Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
@@ -2384,7 +2485,7 @@ Example 2: matches s1 = s2
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('hasDefinition0')"><a name="hasDefinition0Anchor">hasDefinition</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('hasDefinition0')"><a name="hasDefinition0Anchor">hasDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDefinition0"><pre>Matches a class declaration that is defined.
Example matches x (matcher = cxxRecordDecl(hasDefinition()))
@@ -2393,12 +2494,12 @@ class y;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isDerivedFrom1')"><a name="isDerivedFrom1Anchor">isDerivedFrom</a></td><td>std::string BaseName</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isDerivedFrom1')"><a name="isDerivedFrom1Anchor">isDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isDerivedFrom1"><pre>Overloaded method as shortcut for isDerivedFrom(hasName(...)).
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicitTemplateSpecialization2')"><a name="isExplicitTemplateSpecialization2Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicitTemplateSpecialization2')"><a name="isExplicitTemplateSpecialization2Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExplicitTemplateSpecialization2"><pre>Matches explicit template specializations of function, class, or
static member variable template instantiations.
@@ -2408,11 +2509,11 @@ Given
functionDecl(isExplicitTemplateSpecialization())
matches the specialization A&lt;int&gt;().
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isFinal0')"><a name="isFinal0Anchor">isFinal</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isFinal0')"><a name="isFinal0Anchor">isFinal</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isFinal0"><pre>Matches if the given method or class declaration is final.
Given:
@@ -2429,7 +2530,7 @@ matches A and C::f, but not B, C, or B::f
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isLambda0')"><a name="isLambda0Anchor">isLambda</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isLambda0')"><a name="isLambda0Anchor">isLambda</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isLambda0"><pre>Matches the generated class of lambda expressions.
Given:
@@ -2440,13 +2541,13 @@ decltype(x)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isSameOrDerivedFrom1')"><a name="isSameOrDerivedFrom1Anchor">isSameOrDerivedFrom</a></td><td>std::string BaseName</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isSameOrDerivedFrom1')"><a name="isSameOrDerivedFrom1Anchor">isSameOrDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom1"><pre>Overloaded method as shortcut for
isSameOrDerivedFrom(hasName(...)).
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isTemplateInstantiation2')"><a name="isTemplateInstantiation2Anchor">isTemplateInstantiation</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isTemplateInstantiation2')"><a name="isTemplateInstantiation2Anchor">isTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isTemplateInstantiation2"><pre>Matches template instantiations of function, class, or static
member variable template instantiations.
@@ -2465,11 +2566,11 @@ But given
cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
does not match, as X&lt;A&gt; is an explicit template specialization.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('argumentCountIs0')"><a name="argumentCountIs0Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('argumentCountIs0')"><a name="argumentCountIs0Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="argumentCountIs0"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
@@ -2479,7 +2580,29 @@ Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>&gt;</td><td class="name" onclick="toggle('hasCastKind0')"><a name="hasCastKind0Anchor">hasCastKind</a></td><td>CastKind Kind</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('usesADL0')"><a name="usesADL0Anchor">usesADL</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="usesADL0"><pre>Matches call expressions which were resolved using ADL.
+
+Example matches y(x) but not y(42) or NS::y(x).
+ namespace NS {
+ struct X {};
+ void y(X);
+ }
+
+ void y(...);
+
+ void test() {
+ NS::X x;
+ y(x); // Matches
+ NS::y(x); // Doesn't match
+ y(42); // Doesn't match
+ using NS::y;
+ y(x); // Found by both unqualified lookup and ADL, doesn't match
+ }
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>&gt;</td><td class="name" onclick="toggle('hasCastKind0')"><a name="hasCastKind0Anchor">hasCastKind</a></td><td>CastKind Kind</td></tr>
<tr><td colspan="4" class="doc" id="hasCastKind0"><pre>Matches casts that has a given cast kind.
Example: matches the implicit cast around 0
@@ -2488,11 +2611,11 @@ Example: matches the implicit cast around 0
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals4')"><a name="equals4Anchor">equals</a></td><td>bool Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals4')"><a name="equals4Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals4"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals3')"><a name="equals3Anchor">equals</a></td><td>const ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals3')"><a name="equals3Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals3"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -2513,20 +2636,20 @@ matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals10')"><a name="equals10Anchor">equals</a></td><td>double Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals10')"><a name="equals10Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals10"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals7')"><a name="equals7Anchor">equals</a></td><td>unsigned Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;</td><td class="name" onclick="toggle('equals7')"><a name="equals7Anchor">equals</a></td><td>unsigned Value</td></tr>
<tr><td colspan="4" class="doc" id="equals7"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs0')"><a name="templateArgumentCountIs0Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs0')"><a name="templateArgumentCountIs0Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="templateArgumentCountIs0"><pre>Matches if the number of template arguments equals N.
Given
@@ -2537,7 +2660,7 @@ classTemplateSpecializationDecl(templateArgumentCountIs(1))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>&gt;</td><td class="name" onclick="toggle('statementCountIs0')"><a name="statementCountIs0Anchor">statementCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>&gt;</td><td class="name" onclick="toggle('statementCountIs0')"><a name="statementCountIs0Anchor">statementCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="statementCountIs0"><pre>Checks that a compound statement contains a specific number of
child statements.
@@ -2549,7 +2672,7 @@ compoundStmt(statementCountIs(0)))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ConstantArrayType.html">ConstantArrayType</a>&gt;</td><td class="name" onclick="toggle('hasSize0')"><a name="hasSize0Anchor">hasSize</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ConstantArrayType.html">ConstantArrayType</a>&gt;</td><td class="name" onclick="toggle('hasSize0')"><a name="hasSize0Anchor">hasSize</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="hasSize0"><pre>Matches nodes that have the specified size.
Given
@@ -2566,7 +2689,7 @@ stringLiteral(hasSize(4))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;</td><td class="name" onclick="toggle('declCountIs0')"><a name="declCountIs0Anchor">declCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;</td><td class="name" onclick="toggle('declCountIs0')"><a name="declCountIs0Anchor">declCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="declCountIs0"><pre>Matches declaration statements that contain a specific number of
declarations.
@@ -2579,7 +2702,7 @@ declCountIs(2)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode1')"><a name="equalsBoundNode1Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode1')"><a name="equalsBoundNode1Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
<tr><td colspan="4" class="doc" id="equalsBoundNode1"><pre>Matches if a node equals a previously bound node.
Matches a node if it equals the node previously bound to ID.
@@ -2602,14 +2725,14 @@ and reference to that variable declaration within a compound statement.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('equalsNode0')"><a name="equalsNode0Anchor">equalsNode</a></td><td>const Decl* Other</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('equalsNode0')"><a name="equalsNode0Anchor">equalsNode</a></td><td>const Decl* Other</td></tr>
<tr><td colspan="4" class="doc" id="equalsNode0"><pre>Matches if a node equals another node.
Decl has pointer identity in the AST.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasAttr0')"><a name="hasAttr0Anchor">hasAttr</a></td><td>attr::Kind AttrKind</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasAttr0')"><a name="hasAttr0Anchor">hasAttr</a></td><td>attr::Kind AttrKind</td></tr>
<tr><td colspan="4" class="doc" id="hasAttr0"><pre>Matches declaration that has a given attribute.
Given
@@ -2620,7 +2743,7 @@ passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isExpansionInFileMatching0')"><a name="isExpansionInFileMatching0Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isExpansionInFileMatching0')"><a name="isExpansionInFileMatching0Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching0"><pre>Matches AST nodes that were expanded within files whose name is
partially matching a given regex.
@@ -2631,11 +2754,11 @@ Example matches Y but not X
ASTMatcher.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isExpansionInMainFile0')"><a name="isExpansionInMainFile0Anchor">isExpansionInMainFile</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isExpansionInMainFile0')"><a name="isExpansionInMainFile0Anchor">isExpansionInMainFile</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInMainFile0"><pre>Matches AST nodes that were expanded within the main-file.
Example matches X but not Y
@@ -2645,11 +2768,11 @@ Example matches X but not Y
Y.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isExpansionInSystemHeader0')"><a name="isExpansionInSystemHeader0Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isExpansionInSystemHeader0')"><a name="isExpansionInSystemHeader0Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader0"><pre>Matches AST nodes that were expanded within system-header-files.
Example matches Y but not X
@@ -2659,17 +2782,17 @@ Example matches Y but not X
SystemHeader.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isImplicit0')"><a name="isImplicit0Anchor">isImplicit</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isImplicit0')"><a name="isImplicit0Anchor">isImplicit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isImplicit0"><pre>Matches a declaration that has been implicitly added
-by the compiler (eg. implicit defaultcopy constructors).
+by the compiler (eg. implicit default/copy constructors).
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isPrivate0')"><a name="isPrivate0Anchor">isPrivate</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isPrivate0')"><a name="isPrivate0Anchor">isPrivate</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isPrivate0"><pre>Matches private C++ declarations.
Given
@@ -2683,7 +2806,7 @@ fieldDecl(isPrivate())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isProtected0')"><a name="isProtected0Anchor">isProtected</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isProtected0')"><a name="isProtected0Anchor">isProtected</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isProtected0"><pre>Matches protected C++ declarations.
Given
@@ -2697,7 +2820,7 @@ fieldDecl(isProtected())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isPublic0')"><a name="isPublic0Anchor">isPublic</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isPublic0')"><a name="isPublic0Anchor">isPublic</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isPublic0"><pre>Matches public C++ declarations.
Given
@@ -2711,7 +2834,7 @@ fieldDecl(isPublic())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DesignatedInitExpr.html">DesignatedInitExpr</a>&gt;</td><td class="name" onclick="toggle('designatorCountIs0')"><a name="designatorCountIs0Anchor">designatorCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DesignatedInitExpr.html">DesignatedInitExpr</a>&gt;</td><td class="name" onclick="toggle('designatorCountIs0')"><a name="designatorCountIs0Anchor">designatorCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="designatorCountIs0"><pre>Matches designated initializer expressions that contain
a specific number of designators.
@@ -2724,7 +2847,7 @@ designatorCountIs(2)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumDecl.html">EnumDecl</a>&gt;</td><td class="name" onclick="toggle('isScoped0')"><a name="isScoped0Anchor">isScoped</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumDecl.html">EnumDecl</a>&gt;</td><td class="name" onclick="toggle('isScoped0')"><a name="isScoped0Anchor">isScoped</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isScoped0"><pre>Matches C++11 scoped enum declaration.
Example matches Y (matcher = enumDecl(isScoped()))
@@ -2733,7 +2856,47 @@ enum class Y {};
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('hasBitWidth0')"><a name="hasBitWidth0Anchor">hasBitWidth</a></td><td>unsigned Width</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('isInstantiationDependent0')"><a name="isInstantiationDependent0Anchor">isInstantiationDependent</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isInstantiationDependent0"><pre>Matches expressions that are instantiation-dependent even if it is
+neither type- nor value-dependent.
+
+In the following example, the expression sizeof(sizeof(T() + T()))
+is instantiation-dependent (since it involves a template parameter T),
+but is neither type- nor value-dependent, since the type of the inner
+sizeof is known (std::size_t) and therefore the size of the outer
+sizeof is known.
+ template&lt;typename T&gt;
+ void f(T x, T y) { sizeof(sizeof(T() + T()); }
+expr(isInstantiationDependent()) matches sizeof(sizeof(T() + T())
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('isTypeDependent0')"><a name="isTypeDependent0Anchor">isTypeDependent</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isTypeDependent0"><pre>Matches expressions that are type-dependent because the template type
+is not yet instantiated.
+
+For example, the expressions "x" and "x + y" are type-dependent in
+the following code, but "y" is not type-dependent:
+ template&lt;typename T&gt;
+ void add(T x, int y) {
+ x + y;
+ }
+expr(isTypeDependent()) matches x + y
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('isValueDependent0')"><a name="isValueDependent0Anchor">isValueDependent</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isValueDependent0"><pre>Matches expression that are value-dependent because they contain a
+non-type template parameter.
+
+For example, the array bound of "Chars" in the following example is
+value-dependent.
+ template&lt;int Size&gt; int f() { return Size; }
+expr(isValueDependent()) matches return Size
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('hasBitWidth0')"><a name="hasBitWidth0Anchor">hasBitWidth</a></td><td>unsigned Width</td></tr>
<tr><td colspan="4" class="doc" id="hasBitWidth0"><pre>Matches non-static data members that are bit-fields of the specified
bit width.
@@ -2748,7 +2911,7 @@ fieldDecl(hasBitWidth(2))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('isBitField0')"><a name="isBitField0Anchor">isBitField</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('isBitField0')"><a name="isBitField0Anchor">isBitField</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isBitField0"><pre>Matches non-static data members that are bit-fields.
Given
@@ -2761,7 +2924,7 @@ fieldDecl(isBitField())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals1')"><a name="equals1Anchor">equals</a></td><td>const ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals1')"><a name="equals1Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals1"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -2782,16 +2945,16 @@ matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals12')"><a name="equals12Anchor">equals</a></td><td>double Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals12')"><a name="equals12Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals12"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasDynamicExceptionSpec0')"><a name="hasDynamicExceptionSpec0Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasDynamicExceptionSpec0')"><a name="hasDynamicExceptionSpec0Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDynamicExceptionSpec0"><pre>Matches functions that have a dynamic exception specification.
Given:
@@ -2808,7 +2971,7 @@ functionDecl(hasDynamicExceptionSpec()) and
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasOverloadedOperatorName0')"><a name="hasOverloadedOperatorName0Anchor">hasOverloadedOperatorName</a></td><td>StringRef Name</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasOverloadedOperatorName0')"><a name="hasOverloadedOperatorName0Anchor">hasOverloadedOperatorName</a></td><td>StringRef Name</td></tr>
<tr><td colspan="4" class="doc" id="hasOverloadedOperatorName0"><pre>Matches overloaded operator names.
Matches overloaded operator names specified in strings without the
@@ -2818,18 +2981,18 @@ Given:
class A { int operator*(); };
const A &amp;operator&lt;&lt;(const A &amp;a, const A &amp;b);
A a;
- a &lt;&lt; a; &lt;-- This matches
+ a &lt;&lt; a; // &lt;-- This matches
cxxOperatorCallExpr(hasOverloadedOperatorName("&lt;&lt;"))) matches the
specified line and
cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
matches the declaration of A.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasTrailingReturn0')"><a name="hasTrailingReturn0Anchor">hasTrailingReturn</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasTrailingReturn0')"><a name="hasTrailingReturn0Anchor">hasTrailingReturn</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasTrailingReturn0"><pre>Matches a function declared with a trailing return type.
Example matches Y (matcher = functionDecl(hasTrailingReturn()))
@@ -2838,7 +3001,7 @@ auto Y() -&gt; int {}
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isConstexpr1')"><a name="isConstexpr1Anchor">isConstexpr</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isConstexpr1')"><a name="isConstexpr1Anchor">isConstexpr</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isConstexpr1"><pre>Matches constexpr variable and function declarations,
and if constexpr.
@@ -2855,7 +3018,7 @@ ifStmt(isConstexpr())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isDefaulted0')"><a name="isDefaulted0Anchor">isDefaulted</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isDefaulted0')"><a name="isDefaulted0Anchor">isDefaulted</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefaulted0"><pre>Matches defaulted function declarations.
Given:
@@ -2866,29 +3029,29 @@ functionDecl(isDefaulted())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition3')"><a name="isDefinition3Anchor">isDefinition</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition3')"><a name="isDefinition3Anchor">isDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefinition3"><pre>Matches if a declaration has a body attached.
Example matches A, va, fa
class A {};
- class B; Doesn't match, as it has no body.
+ class B; // Doesn't match, as it has no body.
int va;
- extern int vb; Doesn't match, as it doesn't define the variable.
+ extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
- void fb(); Doesn't match, as it has no body.
+ void fb(); // Doesn't match, as it has no body.
@interface X
- - (void)ma; Doesn't match, interface is declaration.
+ - (void)ma; // Doesn't match, interface is declaration.
@end
@implementation X
- (void)ma {}
@end
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isDeleted0')"><a name="isDeleted0Anchor">isDeleted</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isDeleted0')"><a name="isDeleted0Anchor">isDeleted</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDeleted0"><pre>Matches deleted function declarations.
Given:
@@ -2899,7 +3062,7 @@ functionDecl(isDeleted())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicitTemplateSpecialization0')"><a name="isExplicitTemplateSpecialization0Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicitTemplateSpecialization0')"><a name="isExplicitTemplateSpecialization0Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExplicitTemplateSpecialization0"><pre>Matches explicit template specializations of function, class, or
static member variable template instantiations.
@@ -2909,11 +3072,11 @@ Given
functionDecl(isExplicitTemplateSpecialization())
matches the specialization A&lt;int&gt;().
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isExternC0')"><a name="isExternC0Anchor">isExternC</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isExternC0')"><a name="isExternC0Anchor">isExternC</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExternC0"><pre>Matches extern "C" function or variable declarations.
Given:
@@ -2930,7 +3093,7 @@ varDecl(isExternC())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isInline1')"><a name="isInline1Anchor">isInline</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isInline1')"><a name="isInline1Anchor">isInline</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInline1"><pre>Matches function and namespace declarations that are marked with
the inline keyword.
@@ -2945,13 +3108,13 @@ namespaceDecl(isInline()) will match n::m.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isMain0')"><a name="isMain0Anchor">isMain</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isMain0')"><a name="isMain0Anchor">isMain</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isMain0"><pre>Determines whether the function is "main", which is the entry point
into an executable program.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isNoReturn0')"><a name="isNoReturn0Anchor">isNoReturn</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isNoReturn0')"><a name="isNoReturn0Anchor">isNoReturn</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isNoReturn0"><pre>Matches FunctionDecls that have a noreturn attribute.
Given
@@ -2965,7 +3128,7 @@ functionDecl(isNoReturn())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isNoThrow0')"><a name="isNoThrow0Anchor">isNoThrow</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isNoThrow0')"><a name="isNoThrow0Anchor">isNoThrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isNoThrow0"><pre>Matches functions that have a non-throwing exception specification.
Given:
@@ -2979,8 +3142,8 @@ functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isStaticStorageClass0')"><a name="isStaticStorageClass0Anchor">isStaticStorageClass</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isStaticStorageClass0"><pre>Matches variablefunction declarations that have "static" storage
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isStaticStorageClass0')"><a name="isStaticStorageClass0Anchor">isStaticStorageClass</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isStaticStorageClass0"><pre>Matches variable/function declarations that have "static" storage
class specifier ("static" keyword) written in the source.
Given:
@@ -2995,7 +3158,7 @@ varDecl(isStaticStorageClass())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isTemplateInstantiation0')"><a name="isTemplateInstantiation0Anchor">isTemplateInstantiation</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isTemplateInstantiation0')"><a name="isTemplateInstantiation0Anchor">isTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isTemplateInstantiation0"><pre>Matches template instantiations of function, class, or static
member variable template instantiations.
@@ -3014,11 +3177,11 @@ But given
cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
does not match, as X&lt;A&gt; is an explicit template specialization.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isVariadic0')"><a name="isVariadic0Anchor">isVariadic</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('isVariadic0')"><a name="isVariadic0Anchor">isVariadic</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isVariadic0"><pre>Matches if a function declaration is variadic.
Example matches f, but not g or h. The function i will not match, even when
@@ -3030,7 +3193,7 @@ compiled in C mode.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('parameterCountIs0')"><a name="parameterCountIs0Anchor">parameterCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('parameterCountIs0')"><a name="parameterCountIs0Anchor">parameterCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="parameterCountIs0"><pre>Matches FunctionDecls and FunctionProtoTypes that have a
specific parameter count.
@@ -3049,7 +3212,7 @@ functionProtoType(parameterCountIs(3))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('hasDynamicExceptionSpec1')"><a name="hasDynamicExceptionSpec1Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('hasDynamicExceptionSpec1')"><a name="hasDynamicExceptionSpec1Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDynamicExceptionSpec1"><pre>Matches functions that have a dynamic exception specification.
Given:
@@ -3066,7 +3229,7 @@ functionDecl(hasDynamicExceptionSpec()) and
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('isNoThrow1')"><a name="isNoThrow1Anchor">isNoThrow</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('isNoThrow1')"><a name="isNoThrow1Anchor">isNoThrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isNoThrow1"><pre>Matches functions that have a non-throwing exception specification.
Given:
@@ -3080,7 +3243,7 @@ functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('parameterCountIs1')"><a name="parameterCountIs1Anchor">parameterCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('parameterCountIs1')"><a name="parameterCountIs1Anchor">parameterCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="parameterCountIs1"><pre>Matches FunctionDecls and FunctionProtoTypes that have a
specific parameter count.
@@ -3099,7 +3262,7 @@ functionProtoType(parameterCountIs(3))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('isConstexpr2')"><a name="isConstexpr2Anchor">isConstexpr</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('isConstexpr2')"><a name="isConstexpr2Anchor">isConstexpr</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isConstexpr2"><pre>Matches constexpr variable and function declarations,
and if constexpr.
@@ -3116,11 +3279,11 @@ ifStmt(isConstexpr())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals6')"><a name="equals6Anchor">equals</a></td><td>bool Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals6')"><a name="equals6Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals6"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals0')"><a name="equals0Anchor">equals</a></td><td>const ValueT Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals0')"><a name="equals0Anchor">equals</a></td><td>const ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals0"><pre>Matches literals that are equal to the given value of type ValueT.
Given
@@ -3141,20 +3304,20 @@ matcher to match the minus sign:
unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral(equals(13))))
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals13')"><a name="equals13Anchor">equals</a></td><td>double Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals13')"><a name="equals13Anchor">equals</a></td><td>double Value</td></tr>
<tr><td colspan="4" class="doc" id="equals13"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals9')"><a name="equals9Anchor">equals</a></td><td>unsigned Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>&gt;</td><td class="name" onclick="toggle('equals9')"><a name="equals9Anchor">equals</a></td><td>unsigned Value</td></tr>
<tr><td colspan="4" class="doc" id="equals9"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('isArrow0')"><a name="isArrow0Anchor">isArrow</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('isArrow0')"><a name="isArrow0Anchor">isArrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isArrow0"><pre>Matches member expressions that are called with '-&gt;' as opposed
to '.'.
@@ -3163,15 +3326,24 @@ Member calls on the implicit this pointer match as called with '-&gt;'.
Given
class Y {
void x() { this-&gt;x(); x(); Y y; y.x(); a; this-&gt;b; Y::b; }
+ template &lt;class T&gt; void f() { this-&gt;f&lt;T&gt;(); f&lt;T&gt;(); }
int a;
static int b;
};
+ template &lt;class T&gt;
+ class Z {
+ void x() { this-&gt;m; }
+ };
memberExpr(isArrow())
matches this-&gt;x, x, y.x, a, this-&gt;b
+cxxDependentScopeMemberExpr(isArrow())
+ matches this-&gt;m
+unresolvedMemberExpr(isArrow())
+ matches this-&gt;f&lt;T&gt;, f&lt;T&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasExternalFormalLinkage0')"><a name="hasExternalFormalLinkage0Anchor">hasExternalFormalLinkage</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasExternalFormalLinkage0')"><a name="hasExternalFormalLinkage0Anchor">hasExternalFormalLinkage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasExternalFormalLinkage0"><pre>Matches a declaration that has external formal linkage.
Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
@@ -3191,7 +3363,7 @@ void f() {}
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>const std::string Name</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>const std::string Name</td></tr>
<tr><td colspan="4" class="doc" id="hasName0"><pre>Matches NamedDecl nodes that have the specified name.
Supports specifying enclosing namespaces or classes by prefixing the name
@@ -3206,7 +3378,7 @@ Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X")
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('matchesName0')"><a name="matchesName0Anchor">matchesName</a></td><td>std::string RegExp</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('matchesName0')"><a name="matchesName0Anchor">matchesName</a></td><td>std::string RegExp</td></tr>
<tr><td colspan="4" class="doc" id="matchesName0"><pre>Matches NamedDecl nodes whose fully qualified names contain
a substring matched by the given RegExp.
@@ -3222,18 +3394,18 @@ Example matches X (regexp is one of "::X", "^foo::.*X", among others)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt;</td><td class="name" onclick="toggle('isAnonymous0')"><a name="isAnonymous0Anchor">isAnonymous</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt;</td><td class="name" onclick="toggle('isAnonymous0')"><a name="isAnonymous0Anchor">isAnonymous</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAnonymous0"><pre>Matches anonymous namespace declarations.
Given
namespace n {
- namespace {} #1
+ namespace {} // #1
}
namespaceDecl(isAnonymous()) will match #1 but not ::n.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt;</td><td class="name" onclick="toggle('isInline0')"><a name="isInline0Anchor">isInline</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt;</td><td class="name" onclick="toggle('isInline0')"><a name="isInline0Anchor">isInline</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInline0"><pre>Matches function and namespace declarations that are marked with
the inline keyword.
@@ -3248,7 +3420,7 @@ namespaceDecl(isInline()) will match n::m.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('argumentCountIs2')"><a name="argumentCountIs2Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('argumentCountIs2')"><a name="argumentCountIs2Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="argumentCountIs2"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
@@ -3258,7 +3430,7 @@ Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasKeywordSelector0')"><a name="hasKeywordSelector0Anchor">hasKeywordSelector</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasKeywordSelector0')"><a name="hasKeywordSelector0Anchor">hasKeywordSelector</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasKeywordSelector0"><pre>Matches when the selector is a keyword selector
objCMessageExpr(hasKeywordSelector()) matches the generated setFrame
@@ -3268,11 +3440,11 @@ message expression in
CGRect bodyFrame = webView.frame;
bodyFrame.size.height = self.bodyContentHeight;
webView.frame = bodyFrame;
- ^---- matches here
+ // ^---- matches here
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasNullSelector0')"><a name="hasNullSelector0Anchor">hasNullSelector</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasNullSelector0')"><a name="hasNullSelector0Anchor">hasNullSelector</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasNullSelector0"><pre>Matches when the selector is the empty selector
Matches only when the selector of the objCMessageExpr is NULL. This may
@@ -3280,7 +3452,7 @@ represent an error condition in the tree!
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasSelector0')"><a name="hasSelector0Anchor">hasSelector</a></td><td>std::string BaseName</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasSelector0')"><a name="hasSelector0Anchor">hasSelector</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="hasSelector0"><pre>Matches when BaseName == Selector.getAsString()
matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
@@ -3290,7 +3462,7 @@ represent an error condition in the tree!
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasUnarySelector0')"><a name="hasUnarySelector0Anchor">hasUnarySelector</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasUnarySelector0')"><a name="hasUnarySelector0Anchor">hasUnarySelector</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasUnarySelector0"><pre>Matches when the selector is a Unary Selector
matcher = objCMessageExpr(matchesSelector(hasUnarySelector());
@@ -3300,7 +3472,7 @@ represent an error condition in the tree!
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('isInstanceMessage0')"><a name="isInstanceMessage0Anchor">isInstanceMessage</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('isInstanceMessage0')"><a name="isInstanceMessage0Anchor">isInstanceMessage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInstanceMessage0"><pre>Returns true when the Objective-C message is sent to an instance.
Example
@@ -3313,7 +3485,7 @@ but not
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('matchesSelector0')"><a name="matchesSelector0Anchor">matchesSelector</a></td><td>std::string RegExp</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('matchesSelector0')"><a name="matchesSelector0Anchor">matchesSelector</a></td><td>std::string RegExp</td></tr>
<tr><td colspan="4" class="doc" id="matchesSelector0"><pre>Matches ObjC selectors whose name contains
a substring matched by the given RegExp.
matcher = objCMessageExpr(matchesSelector("loadHTMLStringmatches the outer message expr in the code below, but NOT the message
@@ -3322,7 +3494,7 @@ a substring matched by the given RegExp.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('numSelectorArgs0')"><a name="numSelectorArgs0Anchor">numSelectorArgs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('numSelectorArgs0')"><a name="numSelectorArgs0Anchor">numSelectorArgs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="numSelectorArgs0"><pre>Matches when the selector has the specified number of arguments
matcher = objCMessageExpr(numSelectorArgs(0));
@@ -3335,29 +3507,29 @@ a substring matched by the given RegExp.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition2')"><a name="isDefinition2Anchor">isDefinition</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition2')"><a name="isDefinition2Anchor">isDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefinition2"><pre>Matches if a declaration has a body attached.
Example matches A, va, fa
class A {};
- class B; Doesn't match, as it has no body.
+ class B; // Doesn't match, as it has no body.
int va;
- extern int vb; Doesn't match, as it doesn't define the variable.
+ extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
- void fb(); Doesn't match, as it has no body.
+ void fb(); // Doesn't match, as it has no body.
@interface X
- - (void)ma; Doesn't match, interface is declaration.
+ - (void)ma; // Doesn't match, interface is declaration.
@end
@implementation X
- (void)ma {}
@end
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt;</td><td class="name" onclick="toggle('hasDefaultArgument0')"><a name="hasDefaultArgument0Anchor">hasDefaultArgument</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt;</td><td class="name" onclick="toggle('hasDefaultArgument0')"><a name="hasDefaultArgument0Anchor">hasDefaultArgument</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDefaultArgument0"><pre>Matches a declaration that has default arguments.
Example matches y (matcher = parmVarDecl(hasDefaultArgument()))
@@ -3366,7 +3538,7 @@ void y(int val = 0) {}
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('asString0')"><a name="asString0Anchor">asString</a></td><td>std::string Name</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('asString0')"><a name="asString0Anchor">asString</a></td><td>std::string Name</td></tr>
<tr><td colspan="4" class="doc" id="asString0"><pre>Matches if the matched type is represented by the given string.
Given
@@ -3377,7 +3549,7 @@ cxxMemberCallExpr(on(hasType(asString("class Y *"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode3')"><a name="equalsBoundNode3Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode3')"><a name="equalsBoundNode3Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
<tr><td colspan="4" class="doc" id="equalsBoundNode3"><pre>Matches if a node equals a previously bound node.
Matches a node if it equals the node previously bound to ID.
@@ -3400,7 +3572,7 @@ and reference to that variable declaration within a compound statement.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasLocalQualifiers0')"><a name="hasLocalQualifiers0Anchor">hasLocalQualifiers</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasLocalQualifiers0')"><a name="hasLocalQualifiers0Anchor">hasLocalQualifiers</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasLocalQualifiers0"><pre>Matches QualType nodes that have local CV-qualifiers attached to
the node, not hidden within a typedef.
@@ -3415,7 +3587,7 @@ i is const-qualified but the qualifier is not local.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isAnyCharacter0')"><a name="isAnyCharacter0Anchor">isAnyCharacter</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isAnyCharacter0')"><a name="isAnyCharacter0Anchor">isAnyCharacter</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAnyCharacter0"><pre>Matches QualType nodes that are of character type.
Given
@@ -3427,7 +3599,7 @@ matches "a(char)", "b(wchar_t)", but not "c(double)".
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isAnyPointer0')"><a name="isAnyPointer0Anchor">isAnyPointer</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isAnyPointer0')"><a name="isAnyPointer0Anchor">isAnyPointer</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAnyPointer0"><pre>Matches QualType nodes that are of any pointer type; this includes
the Objective-C object pointer type, which is different despite being
syntactically similar.
@@ -3445,7 +3617,7 @@ varDecl(hasType(isAnyPointer()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isConstQualified0')"><a name="isConstQualified0Anchor">isConstQualified</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isConstQualified0')"><a name="isConstQualified0Anchor">isConstQualified</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isConstQualified0"><pre>Matches QualType nodes that are const-qualified, i.e., that
include "top-level" const.
@@ -3462,7 +3634,7 @@ functionDecl(hasAnyParameter(hasType(isConstQualified())))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isInteger0')"><a name="isInteger0Anchor">isInteger</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isInteger0')"><a name="isInteger0Anchor">isInteger</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInteger0"><pre>Matches QualType nodes that are of integer type.
Given
@@ -3474,7 +3646,7 @@ matches "a(int)", "b(long)", but not "c(double)".
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isSignedInteger0')"><a name="isSignedInteger0Anchor">isSignedInteger</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isSignedInteger0')"><a name="isSignedInteger0Anchor">isSignedInteger</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isSignedInteger0"><pre>Matches QualType nodes that are of signed integer type.
Given
@@ -3486,7 +3658,7 @@ matches "a(int)", but not "b(unsigned long)" and "c(double)".
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isUnsignedInteger0')"><a name="isUnsignedInteger0Anchor">isUnsignedInteger</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isUnsignedInteger0')"><a name="isUnsignedInteger0Anchor">isUnsignedInteger</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isUnsignedInteger0"><pre>Matches QualType nodes that are of unsigned integer type.
Given
@@ -3498,7 +3670,7 @@ matches "b(unsigned long)", but not "a(int)" and "c(double)".
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isVolatileQualified0')"><a name="isVolatileQualified0Anchor">isVolatileQualified</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('isVolatileQualified0')"><a name="isVolatileQualified0Anchor">isVolatileQualified</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isVolatileQualified0"><pre>Matches QualType nodes that are volatile-qualified, i.e., that
include "top-level" volatile.
@@ -3515,7 +3687,7 @@ functionDecl(hasAnyParameter(hasType(isVolatileQualified())))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;</td><td class="name" onclick="toggle('isClass0')"><a name="isClass0Anchor">isClass</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;</td><td class="name" onclick="toggle('isClass0')"><a name="isClass0Anchor">isClass</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isClass0"><pre>Matches RecordDecl object that are spelled with "class."
Example matches C, but not S or U.
@@ -3525,7 +3697,7 @@ Example matches C, but not S or U.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;</td><td class="name" onclick="toggle('isStruct0')"><a name="isStruct0Anchor">isStruct</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;</td><td class="name" onclick="toggle('isStruct0')"><a name="isStruct0Anchor">isStruct</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isStruct0"><pre>Matches RecordDecl object that are spelled with "struct."
Example matches S, but not C or U.
@@ -3535,7 +3707,7 @@ Example matches S, but not C or U.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;</td><td class="name" onclick="toggle('isUnion0')"><a name="isUnion0Anchor">isUnion</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>&gt;</td><td class="name" onclick="toggle('isUnion0')"><a name="isUnion0Anchor">isUnion</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isUnion0"><pre>Matches RecordDecl object that are spelled with "union."
Example matches U, but not C or S.
@@ -3545,7 +3717,7 @@ Example matches U, but not C or S.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode0')"><a name="equalsBoundNode0Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode0')"><a name="equalsBoundNode0Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
<tr><td colspan="4" class="doc" id="equalsBoundNode0"><pre>Matches if a node equals a previously bound node.
Matches a node if it equals the node previously bound to ID.
@@ -3568,14 +3740,14 @@ and reference to that variable declaration within a compound statement.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('equalsNode1')"><a name="equalsNode1Anchor">equalsNode</a></td><td>const Stmt* Other</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('equalsNode1')"><a name="equalsNode1Anchor">equalsNode</a></td><td>const Stmt* Other</td></tr>
<tr><td colspan="4" class="doc" id="equalsNode1"><pre>Matches if a node equals another node.
Stmt has pointer identity in the AST.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('isExpansionInFileMatching1')"><a name="isExpansionInFileMatching1Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('isExpansionInFileMatching1')"><a name="isExpansionInFileMatching1Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching1"><pre>Matches AST nodes that were expanded within files whose name is
partially matching a given regex.
@@ -3586,11 +3758,11 @@ Example matches Y but not X
ASTMatcher.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('isExpansionInMainFile1')"><a name="isExpansionInMainFile1Anchor">isExpansionInMainFile</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('isExpansionInMainFile1')"><a name="isExpansionInMainFile1Anchor">isExpansionInMainFile</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInMainFile1"><pre>Matches AST nodes that were expanded within the main-file.
Example matches X but not Y
@@ -3600,11 +3772,11 @@ Example matches X but not Y
Y.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('isExpansionInSystemHeader1')"><a name="isExpansionInSystemHeader1Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('isExpansionInSystemHeader1')"><a name="isExpansionInSystemHeader1Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader1"><pre>Matches AST nodes that were expanded within system-header-files.
Example matches Y but not X
@@ -3614,11 +3786,11 @@ Example matches Y but not X
SystemHeader.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1StringLiteral.html">StringLiteral</a>&gt;</td><td class="name" onclick="toggle('hasSize1')"><a name="hasSize1Anchor">hasSize</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1StringLiteral.html">StringLiteral</a>&gt;</td><td class="name" onclick="toggle('hasSize1')"><a name="hasSize1Anchor">hasSize</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="hasSize1"><pre>Matches nodes that have the specified size.
Given
@@ -3635,29 +3807,29 @@ stringLiteral(hasSize(4))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition0')"><a name="isDefinition0Anchor">isDefinition</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition0')"><a name="isDefinition0Anchor">isDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefinition0"><pre>Matches if a declaration has a body attached.
Example matches A, va, fa
class A {};
- class B; Doesn't match, as it has no body.
+ class B; // Doesn't match, as it has no body.
int va;
- extern int vb; Doesn't match, as it doesn't define the variable.
+ extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
- void fb(); Doesn't match, as it has no body.
+ void fb(); // Doesn't match, as it has no body.
@interface X
- - (void)ma; Doesn't match, interface is declaration.
+ - (void)ma; // Doesn't match, interface is declaration.
@end
@implementation X
- (void)ma {}
@end
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('equalsIntegralValue0')"><a name="equalsIntegralValue0Anchor">equalsIntegralValue</a></td><td>std::string Value</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('equalsIntegralValue0')"><a name="equalsIntegralValue0Anchor">equalsIntegralValue</a></td><td>std::string Value</td></tr>
<tr><td colspan="4" class="doc" id="equalsIntegralValue0"><pre>Matches a TemplateArgument of integral type with a given value.
Note that 'Value' is a string as the template argument's value is
@@ -3673,7 +3845,7 @@ classTemplateSpecializationDecl(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('isIntegral0')"><a name="isIntegral0Anchor">isIntegral</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('isIntegral0')"><a name="isIntegral0Anchor">isIntegral</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isIntegral0"><pre>Matches a TemplateArgument that is an integral value.
Given
@@ -3686,7 +3858,7 @@ classTemplateSpecializationDecl(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs1')"><a name="templateArgumentCountIs1Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs1')"><a name="templateArgumentCountIs1Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="templateArgumentCountIs1"><pre>Matches if the number of template arguments equals N.
Given
@@ -3697,7 +3869,7 @@ classTemplateSpecializationDecl(templateArgumentCountIs(1))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('isExpansionInFileMatching2')"><a name="isExpansionInFileMatching2Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('isExpansionInFileMatching2')"><a name="isExpansionInFileMatching2Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching2"><pre>Matches AST nodes that were expanded within files whose name is
partially matching a given regex.
@@ -3708,11 +3880,11 @@ Example matches Y but not X
ASTMatcher.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('isExpansionInMainFile2')"><a name="isExpansionInMainFile2Anchor">isExpansionInMainFile</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('isExpansionInMainFile2')"><a name="isExpansionInMainFile2Anchor">isExpansionInMainFile</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInMainFile2"><pre>Matches AST nodes that were expanded within the main-file.
Example matches X but not Y
@@ -3722,11 +3894,11 @@ Example matches X but not Y
Y.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('isExpansionInSystemHeader2')"><a name="isExpansionInSystemHeader2Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('isExpansionInSystemHeader2')"><a name="isExpansionInSystemHeader2Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader2"><pre>Matches AST nodes that were expanded within system-header-files.
Example matches Y but not X
@@ -3736,11 +3908,11 @@ Example matches Y but not X
SystemHeader.h:
class Y {};
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('booleanType0')"><a name="booleanType0Anchor">booleanType</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('booleanType0')"><a name="booleanType0Anchor">booleanType</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="booleanType0"><pre>Matches type bool.
Given
@@ -3750,7 +3922,7 @@ functionDecl(returns(booleanType()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode2')"><a name="equalsBoundNode2Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('equalsBoundNode2')"><a name="equalsBoundNode2Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
<tr><td colspan="4" class="doc" id="equalsBoundNode2"><pre>Matches if a node equals a previously bound node.
Matches a node if it equals the node previously bound to ID.
@@ -3773,14 +3945,14 @@ and reference to that variable declaration within a compound statement.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('equalsNode2')"><a name="equalsNode2Anchor">equalsNode</a></td><td>const Type* Other</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('equalsNode2')"><a name="equalsNode2Anchor">equalsNode</a></td><td>const Type* Other</td></tr>
<tr><td colspan="4" class="doc" id="equalsNode2"><pre>Matches if a node equals another node.
Type has pointer identity in the AST.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('realFloatingPointType0')"><a name="realFloatingPointType0Anchor">realFloatingPointType</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('realFloatingPointType0')"><a name="realFloatingPointType0Anchor">realFloatingPointType</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="realFloatingPointType0"><pre>Matches any real floating-point type (float, double, long double).
Given
@@ -3791,7 +3963,7 @@ realFloatingPointType()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('voidType0')"><a name="voidType0Anchor">voidType</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('voidType0')"><a name="voidType0Anchor">voidType</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="voidType0"><pre>Matches type void.
Given
@@ -3801,7 +3973,7 @@ functionDecl(returns(voidType()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt;</td><td class="name" onclick="toggle('ofKind0')"><a name="ofKind0Anchor">ofKind</a></td><td>UnaryExprOrTypeTrait Kind</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt;</td><td class="name" onclick="toggle('ofKind0')"><a name="ofKind0Anchor">ofKind</a></td><td>UnaryExprOrTypeTrait Kind</td></tr>
<tr><td colspan="4" class="doc" id="ofKind0"><pre>Matches unary expressions of a certain kind.
Given
@@ -3812,7 +3984,7 @@ unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasOperatorName1')"><a name="hasOperatorName1Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasOperatorName1')"><a name="hasOperatorName1Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
<tr><td colspan="4" class="doc" id="hasOperatorName1"><pre>Matches the operator Name of operator expressions (binary or
unary).
@@ -3821,7 +3993,33 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasAutomaticStorageDuration0')"><a name="hasAutomaticStorageDuration0Anchor">hasAutomaticStorageDuration</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html">UnresolvedMemberExpr</a>&gt;</td><td class="name" onclick="toggle('isArrow1')"><a name="isArrow1Anchor">isArrow</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isArrow1"><pre>Matches member expressions that are called with '-&gt;' as opposed
+to '.'.
+
+Member calls on the implicit this pointer match as called with '-&gt;'.
+
+Given
+ class Y {
+ void x() { this-&gt;x(); x(); Y y; y.x(); a; this-&gt;b; Y::b; }
+ template &lt;class T&gt; void f() { this-&gt;f&lt;T&gt;(); f&lt;T&gt;(); }
+ int a;
+ static int b;
+ };
+ template &lt;class T&gt;
+ class Z {
+ void x() { this-&gt;m; }
+ };
+memberExpr(isArrow())
+ matches this-&gt;x, x, y.x, a, this-&gt;b
+cxxDependentScopeMemberExpr(isArrow())
+ matches this-&gt;m
+unresolvedMemberExpr(isArrow())
+ matches this-&gt;f&lt;T&gt;, f&lt;T&gt;
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasAutomaticStorageDuration0')"><a name="hasAutomaticStorageDuration0Anchor">hasAutomaticStorageDuration</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasAutomaticStorageDuration0"><pre>Matches a variable declaration that has automatic storage duration.
Example matches x, but not y, z, or a.
@@ -3835,7 +4033,7 @@ int a;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasGlobalStorage0')"><a name="hasGlobalStorage0Anchor">hasGlobalStorage</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasGlobalStorage0')"><a name="hasGlobalStorage0Anchor">hasGlobalStorage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasGlobalStorage0"><pre>Matches a variable declaration that does not have local storage.
Example matches y and z (matcher = varDecl(hasGlobalStorage())
@@ -3847,7 +4045,7 @@ int z;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasLocalStorage0')"><a name="hasLocalStorage0Anchor">hasLocalStorage</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasLocalStorage0')"><a name="hasLocalStorage0Anchor">hasLocalStorage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasLocalStorage0"><pre>Matches a variable declaration that has function scope and is a
non-static local variable.
@@ -3860,7 +4058,7 @@ int z;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasStaticStorageDuration0')"><a name="hasStaticStorageDuration0Anchor">hasStaticStorageDuration</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasStaticStorageDuration0')"><a name="hasStaticStorageDuration0Anchor">hasStaticStorageDuration</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasStaticStorageDuration0"><pre>Matches a variable declaration that has static storage duration.
It includes the variable declared at namespace scope and those declared
with "static" and "extern" storage class specifiers.
@@ -3878,7 +4076,7 @@ varDecl(hasStaticStorageDuration())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasThreadStorageDuration0')"><a name="hasThreadStorageDuration0Anchor">hasThreadStorageDuration</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasThreadStorageDuration0')"><a name="hasThreadStorageDuration0Anchor">hasThreadStorageDuration</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasThreadStorageDuration0"><pre>Matches a variable declaration that has thread storage duration.
Example matches z, but not x, z, or a.
@@ -3892,7 +4090,7 @@ int a;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isConstexpr0')"><a name="isConstexpr0Anchor">isConstexpr</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isConstexpr0')"><a name="isConstexpr0Anchor">isConstexpr</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isConstexpr0"><pre>Matches constexpr variable and function declarations,
and if constexpr.
@@ -3909,29 +4107,29 @@ ifStmt(isConstexpr())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition1')"><a name="isDefinition1Anchor">isDefinition</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition1')"><a name="isDefinition1Anchor">isDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefinition1"><pre>Matches if a declaration has a body attached.
Example matches A, va, fa
class A {};
- class B; Doesn't match, as it has no body.
+ class B; // Doesn't match, as it has no body.
int va;
- extern int vb; Doesn't match, as it doesn't define the variable.
+ extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
- void fb(); Doesn't match, as it has no body.
+ void fb(); // Doesn't match, as it has no body.
@interface X
- - (void)ma; Doesn't match, interface is declaration.
+ - (void)ma; // Doesn't match, interface is declaration.
@end
@implementation X
- (void)ma {}
@end
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isExceptionVariable0')"><a name="isExceptionVariable0Anchor">isExceptionVariable</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isExceptionVariable0')"><a name="isExceptionVariable0Anchor">isExceptionVariable</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExceptionVariable0"><pre>Matches a variable declaration that is an exception variable from
a C++ catch block, or an Objective-C statement.
@@ -3944,7 +4142,7 @@ void f(int y) {
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicitTemplateSpecialization1')"><a name="isExplicitTemplateSpecialization1Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicitTemplateSpecialization1')"><a name="isExplicitTemplateSpecialization1Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExplicitTemplateSpecialization1"><pre>Matches explicit template specializations of function, class, or
static member variable template instantiations.
@@ -3954,11 +4152,11 @@ Given
functionDecl(isExplicitTemplateSpecialization())
matches the specialization A&lt;int&gt;().
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isExternC1')"><a name="isExternC1Anchor">isExternC</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isExternC1')"><a name="isExternC1Anchor">isExternC</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExternC1"><pre>Matches extern "C" function or variable declarations.
Given:
@@ -3975,8 +4173,20 @@ varDecl(isExternC())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isStaticStorageClass1')"><a name="isStaticStorageClass1Anchor">isStaticStorageClass</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isStaticStorageClass1"><pre>Matches variablefunction declarations that have "static" storage
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isStaticLocal0')"><a name="isStaticLocal0Anchor">isStaticLocal</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isStaticLocal0"><pre>Matches a static variable with local scope.
+
+Example matches y (matcher = varDecl(isStaticLocal()))
+void f() {
+ int x;
+ static int y;
+}
+static int z;
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isStaticStorageClass1')"><a name="isStaticStorageClass1Anchor">isStaticStorageClass</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isStaticStorageClass1"><pre>Matches variable/function declarations that have "static" storage
class specifier ("static" keyword) written in the source.
Given:
@@ -3991,7 +4201,7 @@ varDecl(isStaticStorageClass())
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isTemplateInstantiation1')"><a name="isTemplateInstantiation1Anchor">isTemplateInstantiation</a></td><td></td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isTemplateInstantiation1')"><a name="isTemplateInstantiation1Anchor">isTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isTemplateInstantiation1"><pre>Matches template instantiations of function, class, or static
member variable template instantiations.
@@ -4010,11 +4220,11 @@ But given
cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
does not match, as X&lt;A&gt; is an explicit template specialization.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;&gt;</td><td class="name" onclick="toggle('isInstantiated0')"><a name="isInstantiated0Anchor">isInstantiated</a></td><td></td></tr>
+<tr><td>Matcher&lt;internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;&gt;</td><td class="name" onclick="toggle('isInstantiated0')"><a name="isInstantiated0Anchor">isInstantiated</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInstantiated0"><pre>Matches declarations that are template instantiations or are inside
template instantiations.
@@ -4027,14 +4237,14 @@ functionDecl(isInstantiated())
</pre></td></tr>
-<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;&gt;</td><td class="name" onclick="toggle('nullPointerConstant0')"><a name="nullPointerConstant0Anchor">nullPointerConstant</a></td><td></td></tr>
+<tr><td>Matcher&lt;internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;&gt;</td><td class="name" onclick="toggle('nullPointerConstant0')"><a name="nullPointerConstant0Anchor">nullPointerConstant</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="nullPointerConstant0"><pre>Matches expressions that resolve to a null pointer constant, such as
GNU's __null, C++11's nullptr, or C's NULL macro.
Given:
void *v1 = NULL;
void *v2 = nullptr;
- void *v3 = __null; GNU extension
+ void *v3 = __null; // GNU extension
char *cp = (char *)0;
int *ip = 0;
int i = 0;
@@ -4044,7 +4254,7 @@ expr(nullPointerConstant())
</pre></td></tr>
-<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;&gt;</td><td class="name" onclick="toggle('hasAnyName0')"><a name="hasAnyName0Anchor">hasAnyName</a></td><td>StringRef, ..., StringRef</td></tr>
+<tr><td>Matcher&lt;internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;&gt;</td><td class="name" onclick="toggle('hasAnyName0')"><a name="hasAnyName0Anchor">hasAnyName</a></td><td>StringRef, ..., StringRef</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyName0"><pre>Matches NamedDecl nodes that have any of the specified names.
This matcher is only provided as a performance optimization of hasName.
@@ -4054,7 +4264,7 @@ This matcher is only provided as a performance optimization of hasName.
</pre></td></tr>
-<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;&gt;</td><td class="name" onclick="toggle('hasAnySelector0')"><a name="hasAnySelector0Anchor">hasAnySelector</a></td><td>StringRef, ..., StringRef</td></tr>
+<tr><td>Matcher&lt;internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;&gt;</td><td class="name" onclick="toggle('hasAnySelector0')"><a name="hasAnySelector0Anchor">hasAnySelector</a></td><td>StringRef, ..., StringRef</td></tr>
<tr><td colspan="4" class="doc" id="hasAnySelector0"><pre>Matches when at least one of the supplied string equals to the
Selector.getAsString()
@@ -4065,7 +4275,7 @@ Selector.getAsString()
</pre></td></tr>
-<tr><td>Matcher&lt;internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;&gt;</td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
+<tr><td>Matcher&lt;internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;&gt;</td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation.
Given
@@ -4124,8 +4334,8 @@ provided matcher.
Example matches X, A, A::X, B, B::C, B::C::X
(matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
class X {};
- class A { class X {}; }; Matches A, because A::X is a class of name
- X inside A.
+ class A { class X {}; }; // Matches A, because A::X is a class of name
+ // X inside A.
class B { class C { class X {}; }; };
DescendantT must be an AST base type.
@@ -4151,9 +4361,9 @@ provided matcher.
Example matches X, Y, Y::X, Z::Y, Z::Y::X
(matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
class X {};
- class Y { class X {}; }; Matches Y, because Y::X is a class of name X
- inside Y.
- class Z { class Y { class X {}; }; }; Does not match Z.
+ class Y { class X {}; }; // Matches Y, because Y::X is a class of name X
+ // inside Y.
+ class Z { class Y { class X {}; }; }; // Does not match Z.
ChildT must be an AST base type.
@@ -4183,7 +4393,7 @@ provided matcher.
Example matches X, Y, Z
(matcher = cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X")))))
- class X {}; Matches X, because X::X is a class of name X inside X.
+ class X {}; // Matches X, because X::X is a class of name X inside X.
class Y { class X {}; };
class Z { class Y { class X {}; }; };
@@ -4199,9 +4409,9 @@ provided matcher.
Example matches X, Y
(matcher = cxxRecordDecl(has(cxxRecordDecl(hasName("X")))
- class X {}; Matches X, because X::X is a class of name X inside X.
+ class X {}; // Matches X, because X::X is a class of name X inside X.
class Y { class X {}; };
- class Z { class Y { class X {}; }; }; Does not match Z.
+ class Z { class Y { class X {}; }; }; // Does not match Z.
ChildT must be an AST base type.
@@ -4225,7 +4435,7 @@ Usable as: Any Matcher
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasCondition5')"><a name="hasCondition5Anchor">hasCondition</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasCondition5')"><a name="hasCondition5Anchor">hasCondition</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCondition5"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
@@ -4234,7 +4444,7 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasFalseExpression0')"><a name="hasFalseExpression0Anchor">hasFalseExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasFalseExpression0')"><a name="hasFalseExpression0Anchor">hasFalseExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasFalseExpression0"><pre>Matches the false branch expression of a conditional operator
(binary or ternary).
@@ -4244,7 +4454,7 @@ Example matches b
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasTrueExpression0')"><a name="hasTrueExpression0Anchor">hasTrueExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasTrueExpression0')"><a name="hasTrueExpression0Anchor">hasTrueExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasTrueExpression0"><pre>Matches the true branch expression of a conditional operator.
Example 1 (conditional ternary operator): matches a
@@ -4255,7 +4465,7 @@ Example 2 (conditional binary operator): matches opaqueValueExpr(condition)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration15')"><a name="hasDeclaration15Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration15')"><a name="hasDeclaration15Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration15"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4279,17 +4489,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasBase0')"><a name="hasBase0Anchor">hasBase</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasBase0')"><a name="hasBase0Anchor">hasBase</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBase0"><pre>Matches the base expression of an array subscript expression.
Given
@@ -4301,7 +4511,7 @@ arraySubscriptExpression(hasBase(implicitCastExpr(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasIndex0')"><a name="hasIndex0Anchor">hasIndex</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasIndex0')"><a name="hasIndex0Anchor">hasIndex</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasIndex0"><pre>Matches the index expression of an array subscript expression.
Given
@@ -4312,7 +4522,7 @@ arraySubscriptExpression(hasIndex(integerLiteral()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasLHS1')"><a name="hasLHS1Anchor">hasLHS</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasLHS1')"><a name="hasLHS1Anchor">hasLHS</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLHS1"><pre>Matches the left hand side of binary operator expressions.
Example matches a (matcher = binaryOperator(hasLHS()))
@@ -4320,7 +4530,7 @@ Example matches a (matcher = binaryOperator(hasLHS()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasRHS1')"><a name="hasRHS1Anchor">hasRHS</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>&gt;</td><td class="name" onclick="toggle('hasRHS1')"><a name="hasRHS1Anchor">hasRHS</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRHS1"><pre>Matches the right hand side of binary operator expressions.
Example matches b (matcher = binaryOperator(hasRHS()))
@@ -4328,22 +4538,7 @@ Example matches b (matcher = binaryOperator(hasRHS()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayTypeLoc.html">ArrayTypeLoc</a>&gt;</td><td class="name" onclick="toggle('hasElementTypeLoc0')"><a name="hasElementTypeLoc0Anchor">hasElementTypeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
-<tr><td colspan="4" class="doc" id="hasElementTypeLoc0"><pre>Matches arrays and C99 complex types that have a specific element
-type.
-
-Given
- struct A {};
- A a[7];
- int b[7];
-arrayType(hasElementType(builtinType()))
- matches "int b[7]"
-
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;</td><td class="name" onclick="toggle('hasElementType0')"><a name="hasElementType0Anchor">hasElementType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;</td><td class="name" onclick="toggle('hasElementType0')"><a name="hasElementType0Anchor">hasElementType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="hasElementType0"><pre>Matches arrays and C99 complex types that have a specific element
type.
@@ -4354,24 +4549,11 @@ Given
arrayType(hasElementType(builtinType()))
matches "int b[7]"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AtomicTypeLoc.html">AtomicTypeLoc</a>&gt;</td><td class="name" onclick="toggle('hasValueTypeLoc0')"><a name="hasValueTypeLoc0Anchor">hasValueTypeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
-<tr><td colspan="4" class="doc" id="hasValueTypeLoc0"><pre>Matches atomic types with a specific value type.
-
-Given
- _Atomic(int) i;
- _Atomic(float) f;
-atomicType(hasValueType(isInteger()))
- matches "_Atomic(int) i"
-
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>&gt;
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>&gt;</td><td class="name" onclick="toggle('hasValueType0')"><a name="hasValueType0Anchor">hasValueType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>&gt;</td><td class="name" onclick="toggle('hasValueType0')"><a name="hasValueType0Anchor">hasValueType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="hasValueType0"><pre>Matches atomic types with a specific value type.
Given
@@ -4380,11 +4562,11 @@ Given
atomicType(hasValueType(isInteger()))
matches "_Atomic(int) i"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>&gt;</td><td class="name" onclick="toggle('hasDeducedType0')"><a name="hasDeducedType0Anchor">hasDeducedType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>&gt;</td><td class="name" onclick="toggle('hasDeducedType0')"><a name="hasDeducedType0Anchor">hasDeducedType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="hasDeducedType0"><pre>Matches AutoType nodes where the deduced type is a specific type.
Note: There is no TypeLoc for the deduced type and thus no
@@ -4396,17 +4578,17 @@ Given
autoType(hasDeducedType(isInteger()))
matches "auto a"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasEitherOperand0"><pre>Matches if either the left hand side or the right hand side of a
binary operator matches.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasLHS0')"><a name="hasLHS0Anchor">hasLHS</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasLHS0')"><a name="hasLHS0Anchor">hasLHS</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLHS0"><pre>Matches the left hand side of binary operator expressions.
Example matches a (matcher = binaryOperator(hasLHS()))
@@ -4414,7 +4596,7 @@ Example matches a (matcher = binaryOperator(hasLHS()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasRHS0')"><a name="hasRHS0Anchor">hasRHS</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasRHS0')"><a name="hasRHS0Anchor">hasRHS</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRHS0"><pre>Matches the right hand side of binary operator expressions.
Example matches b (matcher = binaryOperator(hasRHS()))
@@ -4422,7 +4604,7 @@ Example matches b (matcher = binaryOperator(hasRHS()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter2')"><a name="hasAnyParameter2Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter2')"><a name="hasAnyParameter2Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyParameter2"><pre>Matches any parameter of a function or an ObjC method declaration or a
block.
@@ -4451,7 +4633,7 @@ matching y.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter2')"><a name="hasParameter2Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter2')"><a name="hasParameter2Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasParameter2"><pre>Matches the n'th parameter of a function or an ObjC method
declaration or a block.
@@ -4471,23 +4653,7 @@ matching y.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerTypeLoc.html">BlockPointerTypeLoc</a>&gt;</td><td class="name" onclick="toggle('pointeeLoc0')"><a name="pointeeLoc0Anchor">pointeeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc0"><pre>Narrows PointerType (and similar) matchers to those where the
-pointee matches a given matcher.
-
-Given
- int *a;
- int const *b;
- float const *f;
-pointerType(pointee(isConstQualified(), isInteger()))
- matches "int const *b"
-
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;</td><td class="name" onclick="toggle('pointee0')"><a name="pointee0Anchor">pointee</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;</td><td class="name" onclick="toggle('pointee0')"><a name="pointee0Anchor">pointee</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="pointee0"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
@@ -4498,12 +4664,12 @@ Given
pointerType(pointee(isConstQualified(), isInteger()))
matches "int const *b"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('forEachArgumentWithParam1')"><a name="forEachArgumentWithParam1Anchor">forEachArgumentWithParam</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; ArgMatcher, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; ParamMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('forEachArgumentWithParam1')"><a name="forEachArgumentWithParam1Anchor">forEachArgumentWithParam</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; ArgMatcher, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; ParamMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachArgumentWithParam1"><pre>Matches all arguments and their respective ParmVarDecl.
Given
@@ -4523,7 +4689,7 @@ and parmVarDecl(...)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument1')"><a name="hasAnyArgument1Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument1')"><a name="hasAnyArgument1Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyArgument1"><pre>Matches any argument of a call expression or a constructor call
expression, or an ObjC-message-send expression.
@@ -4542,7 +4708,7 @@ objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgument1')"><a name="hasArgument1Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgument1')"><a name="hasArgument1Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArgument1"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
@@ -4552,7 +4718,7 @@ Example matches y in x(y)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration13')"><a name="hasDeclaration13Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration13')"><a name="hasDeclaration13Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration13"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4576,17 +4742,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('forEachConstructorInitializer0')"><a name="forEachConstructorInitializer0Anchor">forEachConstructorInitializer</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('forEachConstructorInitializer0')"><a name="forEachConstructorInitializer0Anchor">forEachConstructorInitializer</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachConstructorInitializer0"><pre>Matches each constructor initializer in a constructor definition.
Given
@@ -4598,7 +4764,7 @@ cxxConstructorDecl(forEachConstructorInitializer(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyConstructorInitializer0')"><a name="hasAnyConstructorInitializer0Anchor">hasAnyConstructorInitializer</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyConstructorInitializer0')"><a name="hasAnyConstructorInitializer0Anchor">hasAnyConstructorInitializer</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyConstructorInitializer0"><pre>Matches a constructor initializer.
Given
@@ -4613,7 +4779,7 @@ cxxRecordDecl(has(cxxConstructorDecl(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('forField0')"><a name="forField0Anchor">forField</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('forField0')"><a name="forField0Anchor">forField</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forField0"><pre>Matches the field declaration of a constructor initializer.
Given
@@ -4628,7 +4794,7 @@ with forField matching foo_
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('withInitializer0')"><a name="withInitializer0Anchor">withInitializer</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('withInitializer0')"><a name="withInitializer0Anchor">withInitializer</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="withInitializer0"><pre>Matches the initializer expression of a constructor initializer.
Given
@@ -4643,7 +4809,21 @@ with withInitializer matching (1)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody3')"><a name="hasBody3Anchor">hasBody</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasObjectExpression2')"><a name="hasObjectExpression2Anchor">hasObjectExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasObjectExpression2"><pre>Matches a member expression where the object expression is
+matched by a given matcher.
+
+Given
+ struct X { int m; };
+ void f(X x) { x.m; m; }
+memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
+ matches "x.m" and "m"
+with hasObjectExpression(...)
+ matching "x" and the implicit object expression of "m" which has type X*.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody3')"><a name="hasBody3Anchor">hasBody</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBody3"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -4656,7 +4836,7 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;</td><td class="name" onclick="toggle('hasLoopVariable0')"><a name="hasLoopVariable0Anchor">hasLoopVariable</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;</td><td class="name" onclick="toggle('hasLoopVariable0')"><a name="hasLoopVariable0Anchor">hasLoopVariable</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLoopVariable0"><pre>Matches the initialization statement of a for loop.
Example:
@@ -4666,7 +4846,7 @@ matches 'int x' in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;</td><td class="name" onclick="toggle('hasRangeInit0')"><a name="hasRangeInit0Anchor">hasRangeInit</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>&gt;</td><td class="name" onclick="toggle('hasRangeInit0')"><a name="hasRangeInit0Anchor">hasRangeInit</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRangeInit0"><pre>Matches the range initialization statement of a for loop.
Example:
@@ -4676,11 +4856,11 @@ matches 'a' in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('onImplicitObjectArgument0')"><a name="onImplicitObjectArgument0Anchor">onImplicitObjectArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('onImplicitObjectArgument0')"><a name="onImplicitObjectArgument0Anchor">onImplicitObjectArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="onImplicitObjectArgument0"><pre></pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('on0')"><a name="on0Anchor">on</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('on0')"><a name="on0Anchor">on</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="on0"><pre>Matches on the implicit object argument of a member call expression.
Example matches y.x()
@@ -4692,18 +4872,18 @@ FIXME: Overload to allow directly matching types?
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('thisPointerType1')"><a name="thisPointerType1Anchor">thisPointerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('thisPointerType1')"><a name="thisPointerType1Anchor">thisPointerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="thisPointerType1"><pre>Overloaded to match the type's declaration.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('thisPointerType0')"><a name="thisPointerType0Anchor">thisPointerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>&gt;</td><td class="name" onclick="toggle('thisPointerType0')"><a name="thisPointerType0Anchor">thisPointerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="thisPointerType0"><pre>Matches if the expression's type either matches the specified
matcher, or is a pointer to a type that matches the InnerMatcher.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('forEachOverridden0')"><a name="forEachOverridden0Anchor">forEachOverridden</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('forEachOverridden0')"><a name="forEachOverridden0Anchor">forEachOverridden</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachOverridden0"><pre>Matches each method overridden by the given method. This matcher may
produce multiple matches.
@@ -4727,7 +4907,7 @@ cxxMethodDecl(ofClass(hasName("C")),
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('ofClass0')"><a name="ofClass0Anchor">ofClass</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('ofClass0')"><a name="ofClass0Anchor">ofClass</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ofClass0"><pre>Matches the class declaration that the given method declaration
belongs to.
@@ -4746,7 +4926,7 @@ Example matches A() in the last line
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('hasArraySize0')"><a name="hasArraySize0Anchor">hasArraySize</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('hasArraySize0')"><a name="hasArraySize0Anchor">hasArraySize</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArraySize0"><pre>Matches array new expressions with a given array size.
Given:
@@ -4756,7 +4936,7 @@ cxxNewExpr(hasArraySize(intgerLiteral(equals(10))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration12')"><a name="hasDeclaration12Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration12')"><a name="hasDeclaration12Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration12"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4780,17 +4960,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasMethod0"><pre>Matches the first method of a class or struct that satisfies InnerMatcher.
Given:
@@ -4802,7 +4982,7 @@ A but not B.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isDerivedFrom0')"><a name="isDerivedFrom0Anchor">isDerivedFrom</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; Base</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isDerivedFrom0')"><a name="isDerivedFrom0Anchor">isDerivedFrom</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; Base</td></tr>
<tr><td colspan="4" class="doc" id="isDerivedFrom0"><pre>Matches C++ classes that are directly or indirectly derived from
a class matching Base.
@@ -4810,26 +4990,45 @@ Note that a class is not considered to be derived from itself.
Example matches Y, Z, C (Base == hasName("X"))
class X;
- class Y : public X {}; directly derived
- class Z : public Y {}; indirectly derived
+ class Y : public X {}; // directly derived
+ class Z : public Y {}; // indirectly derived
typedef X A;
typedef A B;
- class C : public B {}; derived from a typedef of X
+ class C : public B {}; // derived from a typedef of X
In the following example, Bar matches isDerivedFrom(hasName("X")):
class Foo;
typedef Foo X;
- class Bar : public Foo {}; derived from a type that X is a typedef of
+ class Bar : public Foo {}; // derived from a type that X is a typedef of
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isSameOrDerivedFrom0')"><a name="isSameOrDerivedFrom0Anchor">isSameOrDerivedFrom</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; Base</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isSameOrDerivedFrom0')"><a name="isSameOrDerivedFrom0Anchor">isSameOrDerivedFrom</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; Base</td></tr>
<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom0"><pre>Similar to isDerivedFrom(), but also matches classes that directly
match Base.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('callee1')"><a name="callee1Anchor">callee</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument2')"><a name="hasAnyArgument2Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyArgument2"><pre>Matches any argument of a call expression or a constructor call
+expression, or an ObjC-message-send expression.
+
+Given
+ void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+ matches x(1, y, 42)
+with hasAnyArgument(...)
+ matching y
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+ void foo(I *i) { [i f:12]; }
+objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+ matches [i f:12]
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('callee1')"><a name="callee1Anchor">callee</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="callee1"><pre>Matches if the call expression's callee's declaration matches the
given matcher.
@@ -4840,7 +5039,7 @@ Example matches y.x() (matcher = callExpr(callee(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('callee0')"><a name="callee0Anchor">callee</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('callee0')"><a name="callee0Anchor">callee</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="callee0"><pre>Matches if the call expression's callee expression matches.
Given
@@ -4851,14 +5050,14 @@ callExpr(callee(expr()))
with callee(...)
matching this-&gt;x, x, y.x, f respectively
-Note: Callee cannot take the more general internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;
+Note: Callee cannot take the more general internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;
because this introduces ambiguous overloads with calls to Callee taking a
-internal::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, as the matcher hierarchy is purely
+internal::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;, as the matcher hierarchy is purely
implemented in terms of implicit casts.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('forEachArgumentWithParam0')"><a name="forEachArgumentWithParam0Anchor">forEachArgumentWithParam</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; ArgMatcher, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; ParamMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('forEachArgumentWithParam0')"><a name="forEachArgumentWithParam0Anchor">forEachArgumentWithParam</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; ArgMatcher, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; ParamMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachArgumentWithParam0"><pre>Matches all arguments and their respective ParmVarDecl.
Given
@@ -4878,7 +5077,7 @@ and parmVarDecl(...)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument0')"><a name="hasAnyArgument0Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument0')"><a name="hasAnyArgument0Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyArgument0"><pre>Matches any argument of a call expression or a constructor call
expression, or an ObjC-message-send expression.
@@ -4897,7 +5096,7 @@ objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgument0')"><a name="hasArgument0Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgument0')"><a name="hasArgument0Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArgument0"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
@@ -4907,7 +5106,7 @@ Example matches y in x(y)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration14')"><a name="hasDeclaration14Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration14')"><a name="hasDeclaration14Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration14"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -4931,17 +5130,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CaseStmt.html">CaseStmt</a>&gt;</td><td class="name" onclick="toggle('hasCaseConstant0')"><a name="hasCaseConstant0Anchor">hasCaseConstant</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CaseStmt.html">CaseStmt</a>&gt;</td><td class="name" onclick="toggle('hasCaseConstant0')"><a name="hasCaseConstant0Anchor">hasCaseConstant</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCaseConstant0"><pre>If the given case statement does not use the GNU case range
extension, matches the constant given in the statement.
@@ -4952,7 +5151,7 @@ caseStmt(hasCaseConstant(integerLiteral()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression0')"><a name="hasSourceExpression0Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression0')"><a name="hasSourceExpression0Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSourceExpression0"><pre>Matches if the cast's source expression
or opaque value's source expression matches the given matcher.
@@ -4967,7 +5166,7 @@ int a = b ?: 1;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument0')"><a name="hasAnyTemplateArgument0Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument0')"><a name="hasAnyTemplateArgument0Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and
functionDecl that have at least one TemplateArgument matching the given
InnerMatcher.
@@ -4989,19 +5188,19 @@ functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasSpecializedTemplate0')"><a name="hasSpecializedTemplate0Anchor">hasSpecializedTemplate</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateDecl.html">ClassTemplateDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasSpecializedTemplate0')"><a name="hasSpecializedTemplate0Anchor">hasSpecializedTemplate</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateDecl.html">ClassTemplateDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSpecializedTemplate0"><pre>Matches the specialized template of a specialization declaration.
Given
- tempalate&lt;typename T&gt; class A {};
- typedef A&lt;int&gt; B;
+ template&lt;typename T&gt; class A {}; #1
+ template&lt;&gt; class A&lt;int&gt; {}; #2
classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl()))
- matches 'B' with classTemplateDecl() matching the class template
- declaration of 'A'.
+ matches '#2' with classTemplateDecl() matching the class template
+ declaration of 'A' at #1.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument0')"><a name="hasTemplateArgument0Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument0')"><a name="hasTemplateArgument0Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and
functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
@@ -5021,22 +5220,7 @@ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexTypeLoc.html">ComplexTypeLoc</a>&gt;</td><td class="name" onclick="toggle('hasElementTypeLoc1')"><a name="hasElementTypeLoc1Anchor">hasElementTypeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
-<tr><td colspan="4" class="doc" id="hasElementTypeLoc1"><pre>Matches arrays and C99 complex types that have a specific element
-type.
-
-Given
- struct A {};
- A a[7];
- int b[7];
-arrayType(hasElementType(builtinType()))
- matches "int b[7]"
-
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;</td><td class="name" onclick="toggle('hasElementType1')"><a name="hasElementType1Anchor">hasElementType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;</td><td class="name" onclick="toggle('hasElementType1')"><a name="hasElementType1Anchor">hasElementType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="hasElementType1"><pre>Matches arrays and C99 complex types that have a specific element
type.
@@ -5047,11 +5231,11 @@ Given
arrayType(hasElementType(builtinType()))
matches "int b[7]"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>&gt;</td><td class="name" onclick="toggle('hasAnySubstatement0')"><a name="hasAnySubstatement0Anchor">hasAnySubstatement</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>&gt;</td><td class="name" onclick="toggle('hasAnySubstatement0')"><a name="hasAnySubstatement0Anchor">hasAnySubstatement</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnySubstatement0"><pre>Matches compound statements where at least one substatement matches
a given matcher. Also matches StmtExprs that have CompoundStmt as children.
@@ -5064,12 +5248,12 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecayedType.html">DecayedType</a>&gt;</td><td class="name" onclick="toggle('hasDecayedType0')"><a name="hasDecayedType0Anchor">hasDecayedType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerType</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DecayedType.html">DecayedType</a>&gt;</td><td class="name" onclick="toggle('hasDecayedType0')"><a name="hasDecayedType0Anchor">hasDecayedType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerType</td></tr>
<tr><td colspan="4" class="doc" id="hasDecayedType0"><pre>Matches the decayed type, whos decayed type matches InnerMatcher
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration11')"><a name="hasDeclaration11Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration11')"><a name="hasDeclaration11Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration11"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5093,17 +5277,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('throughUsingDecl0')"><a name="throughUsingDecl0Anchor">throughUsingDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UsingShadowDecl.html">UsingShadowDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('throughUsingDecl0')"><a name="throughUsingDecl0Anchor">throughUsingDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingShadowDecl.html">UsingShadowDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="throughUsingDecl0"><pre>Matches a DeclRefExpr that refers to a declaration through a
specific using shadow declaration.
@@ -5111,15 +5295,15 @@ Given
namespace a { void f() {} }
using a::f;
void g() {
- f(); Matches this ..
- a::f(); .. but not this.
+ f(); // Matches this ..
+ a::f(); // .. but not this.
}
declRefExpr(throughUsingDecl(anything()))
matches f()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('to0')"><a name="to0Anchor">to</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;</td><td class="name" onclick="toggle('to0')"><a name="to0Anchor">to</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="to0"><pre>Matches a DeclRefExpr that refers to a declaration that matches the
specified matcher.
@@ -5130,7 +5314,7 @@ Example matches x in if(x)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;</td><td class="name" onclick="toggle('containsDeclaration0')"><a name="containsDeclaration0Anchor">containsDeclaration</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;</td><td class="name" onclick="toggle('containsDeclaration0')"><a name="containsDeclaration0Anchor">containsDeclaration</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="containsDeclaration0"><pre>Matches the n'th declaration of a declaration statement.
Note that this does not work for global declarations because the AST
@@ -5149,7 +5333,7 @@ declStmt(containsDeclaration(1, varDecl()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;</td><td class="name" onclick="toggle('hasSingleDecl0')"><a name="hasSingleDecl0Anchor">hasSingleDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt;</td><td class="name" onclick="toggle('hasSingleDecl0')"><a name="hasSingleDecl0Anchor">hasSingleDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSingleDecl0"><pre>Matches the Decl of a DeclStmt which has a single declaration.
Given
@@ -5160,7 +5344,7 @@ declStmt(hasSingleDecl(anything()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>&gt;</td><td class="name" onclick="toggle('hasTypeLoc0')"><a name="hasTypeLoc0Anchor">hasTypeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt; Inner</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>&gt;</td><td class="name" onclick="toggle('hasTypeLoc0')"><a name="hasTypeLoc0Anchor">hasTypeLoc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt; Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc0"><pre>Matches if the type location of the declarator decl's type matches
the inner matcher.
@@ -5171,7 +5355,7 @@ declaratorDecl(hasTypeLoc(loc(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasDeclContext0')"><a name="hasDeclContext0Anchor">hasDeclContext</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasDeclContext0')"><a name="hasDeclContext0Anchor">hasDeclContext</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclContext0"><pre>Matches declarations whose declaration context, interpreted as a
Decl, matches InnerMatcher.
@@ -5187,20 +5371,20 @@ declaration of class D.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;</td><td class="name" onclick="toggle('hasUnderlyingType0')"><a name="hasUnderlyingType0Anchor">hasUnderlyingType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;</td><td class="name" onclick="toggle('hasUnderlyingType0')"><a name="hasUnderlyingType0Anchor">hasUnderlyingType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="hasUnderlyingType0"><pre>Matches DecltypeType nodes to find out the underlying type.
Given
decltype(1) a = 1;
decltype(2.0) b = 2.0;
decltypeType(hasUnderlyingType(isInteger()))
- matches "auto a"
+ matches the type of "a"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody0')"><a name="hasBody0Anchor">hasBody</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody0')"><a name="hasBody0Anchor">hasBody</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBody0"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -5213,7 +5397,7 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition3')"><a name="hasCondition3Anchor">hasCondition</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition3')"><a name="hasCondition3Anchor">hasCondition</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCondition3"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
@@ -5222,7 +5406,7 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>&gt;</td><td class="name" onclick="toggle('hasQualifier0')"><a name="hasQualifier0Anchor">hasQualifier</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>&gt;</td><td class="name" onclick="toggle('hasQualifier0')"><a name="hasQualifier0Anchor">hasQualifier</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasQualifier0"><pre>Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
matches InnerMatcher if the qualifier exists.
@@ -5239,7 +5423,7 @@ matches the type of the variable declaration of d.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>&gt;</td><td class="name" onclick="toggle('namesType0')"><a name="namesType0Anchor">namesType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>&gt;</td><td class="name" onclick="toggle('namesType0')"><a name="namesType0Anchor">namesType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="namesType0"><pre>Matches ElaboratedTypes whose named type matches InnerMatcher.
Given
@@ -5256,7 +5440,7 @@ declaration of d.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration10')"><a name="hasDeclaration10Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration10')"><a name="hasDeclaration10Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration10"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5280,17 +5464,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>&gt;</td><td class="name" onclick="toggle('hasDestinationType0')"><a name="hasDestinationType0Anchor">hasDestinationType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>&gt;</td><td class="name" onclick="toggle('hasDestinationType0')"><a name="hasDestinationType0Anchor">hasDestinationType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDestinationType0"><pre>Matches casts whose destination type matches a given matcher.
(Note: Clang's AST refers to other conversions as "casts" too, and calls
@@ -5298,7 +5482,7 @@ actual casts "explicit" casts.)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('hasType4')"><a name="hasType4Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('hasType4')"><a name="hasType4Anchor">hasType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasType4"><pre>Overloaded to match the declaration of the expression's or value
declaration's type.
@@ -5315,11 +5499,11 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
void y(X &amp;x) { x; X z; }
class Y { friend class X; };
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('hasType0')"><a name="hasType0Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('hasType0')"><a name="hasType0Anchor">hasType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasType0"><pre>Matches if the expression's or declaration's type matches a type
matcher.
@@ -5334,7 +5518,7 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringImpCasts0')"><a name="ignoringImpCasts0Anchor">ignoringImpCasts</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringImpCasts0')"><a name="ignoringImpCasts0Anchor">ignoringImpCasts</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringImpCasts0"><pre>Matches expressions that match InnerMatcher after any implicit casts
are stripped off.
@@ -5357,7 +5541,7 @@ only match the declarations for b, c, and d.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringImplicit0')"><a name="ignoringImplicit0Anchor">ignoringImplicit</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringImplicit0')"><a name="ignoringImplicit0Anchor">ignoringImplicit</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringImplicit0"><pre>Matches expressions that match InnerMatcher after any implicit AST
nodes are stripped off.
@@ -5376,7 +5560,7 @@ only match the declarations for b and c.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringParenCasts0')"><a name="ignoringParenCasts0Anchor">ignoringParenCasts</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringParenCasts0')"><a name="ignoringParenCasts0Anchor">ignoringParenCasts</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringParenCasts0"><pre>Matches expressions that match InnerMatcher after parentheses and
casts are stripped off.
@@ -5395,7 +5579,7 @@ only match the declaration for a.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringParenImpCasts0')"><a name="ignoringParenImpCasts0Anchor">ignoringParenImpCasts</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringParenImpCasts0')"><a name="ignoringParenImpCasts0Anchor">ignoringParenImpCasts</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringParenImpCasts0"><pre>Matches expressions that match InnerMatcher after implicit casts and
parentheses are stripped off.
@@ -5418,7 +5602,18 @@ would only match the declaration for a.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('hasInClassInitializer0')"><a name="hasInClassInitializer0Anchor">hasInClassInitializer</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringParens1')"><a name="ignoringParens1Anchor">ignoringParens</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="ignoringParens1"><pre>Overload ignoringParens for Expr.
+
+Given
+ const char* str = ("my-string");
+The matcher
+ implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))
+would match the implicit cast resulting from the assignment.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('hasInClassInitializer0')"><a name="hasInClassInitializer0Anchor">hasInClassInitializer</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasInClassInitializer0"><pre>Matches non-static data members that have an in-class initializer.
Given
@@ -5434,7 +5629,7 @@ fieldDecl(hasInClassInitializer(anything()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody1')"><a name="hasBody1Anchor">hasBody</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody1')"><a name="hasBody1Anchor">hasBody</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBody1"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -5447,7 +5642,7 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition1')"><a name="hasCondition1Anchor">hasCondition</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition1')"><a name="hasCondition1Anchor">hasCondition</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCondition1"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
@@ -5456,7 +5651,7 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasIncrement0')"><a name="hasIncrement0Anchor">hasIncrement</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasIncrement0')"><a name="hasIncrement0Anchor">hasIncrement</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasIncrement0"><pre>Matches the increment statement of a for loop.
Example:
@@ -5466,7 +5661,7 @@ matches '++x' in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasLoopInit0')"><a name="hasLoopInit0Anchor">hasLoopInit</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasLoopInit0')"><a name="hasLoopInit0Anchor">hasLoopInit</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLoopInit0"><pre>Matches the initialization statement of a for loop.
Example:
@@ -5476,7 +5671,7 @@ matches 'int x = 0' in
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;</td><td class="name" onclick="toggle('hasType5')"><a name="hasType5Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;</td><td class="name" onclick="toggle('hasType5')"><a name="hasType5Anchor">hasType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasType5"><pre>Overloaded to match the declaration of the expression's or value
declaration's type.
@@ -5493,11 +5688,11 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
void y(X &amp;x) { x; X z; }
class Y { friend class X; };
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;</td><td class="name" onclick="toggle('hasType1')"><a name="hasType1Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>&gt;</td><td class="name" onclick="toggle('hasType1')"><a name="hasType1Anchor">hasType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasType1"><pre>Matches if the expression's or declaration's type matches a type
matcher.
@@ -5512,7 +5707,7 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter0')"><a name="hasAnyParameter0Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter0')"><a name="hasAnyParameter0Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function or an ObjC method declaration or a
block.
@@ -5541,7 +5736,7 @@ matching y.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument2')"><a name="hasAnyTemplateArgument2Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument2')"><a name="hasAnyTemplateArgument2Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and
functionDecl that have at least one TemplateArgument matching the given
InnerMatcher.
@@ -5563,7 +5758,7 @@ functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasBody4')"><a name="hasBody4Anchor">hasBody</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasBody4')"><a name="hasBody4Anchor">hasBody</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBody4"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -5576,7 +5771,7 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter0')"><a name="hasParameter0Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter0')"><a name="hasParameter0Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function or an ObjC method
declaration or a block.
@@ -5596,7 +5791,7 @@ matching y.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument2')"><a name="hasTemplateArgument2Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument2')"><a name="hasTemplateArgument2Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and
functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
@@ -5616,7 +5811,7 @@ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('returns0')"><a name="returns0Anchor">returns</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('returns0')"><a name="returns0Anchor">returns</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="returns0"><pre>Matches the return type of a function declaration.
Given:
@@ -5626,7 +5821,7 @@ cxxMethodDecl(returns(asString("int")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition0')"><a name="hasCondition0Anchor">hasCondition</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition0')"><a name="hasCondition0Anchor">hasCondition</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCondition0"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
@@ -5635,7 +5830,7 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasConditionVariableStatement0')"><a name="hasConditionVariableStatement0Anchor">hasConditionVariableStatement</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasConditionVariableStatement0')"><a name="hasConditionVariableStatement0Anchor">hasConditionVariableStatement</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">DeclStmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasConditionVariableStatement0"><pre>Matches the condition variable statement in an if statement.
Given
@@ -5645,7 +5840,7 @@ hasConditionVariableStatement(...)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasElse0')"><a name="hasElse0Anchor">hasElse</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasElse0')"><a name="hasElse0Anchor">hasElse</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasElse0"><pre>Matches the else-statement of an if statement.
Examples matches the if statement
@@ -5654,7 +5849,7 @@ Examples matches the if statement
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasThen0')"><a name="hasThen0Anchor">hasThen</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasThen0')"><a name="hasThen0Anchor">hasThen</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasThen0"><pre>Matches the then-statement of an if statement.
Examples matches the if statement
@@ -5663,7 +5858,7 @@ Examples matches the if statement
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ImplicitCastExpr.html">ImplicitCastExpr</a>&gt;</td><td class="name" onclick="toggle('hasImplicitDestinationType0')"><a name="hasImplicitDestinationType0Anchor">hasImplicitDestinationType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ImplicitCastExpr.html">ImplicitCastExpr</a>&gt;</td><td class="name" onclick="toggle('hasImplicitDestinationType0')"><a name="hasImplicitDestinationType0Anchor">hasImplicitDestinationType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasImplicitDestinationType0"><pre>Matches implicit casts whose destination type matches a given
matcher.
@@ -5671,13 +5866,22 @@ FIXME: Unit test this matcher
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>&gt;</td><td class="name" onclick="toggle('hasSyntacticForm0')"><a name="hasSyntacticForm0Anchor">hasSyntacticForm</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>&gt;</td><td class="name" onclick="toggle('hasInit0')"><a name="hasInit0Anchor">hasInit</a></td><td>unsigned N, ast_matchers::Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasInit0"><pre>Matches the n'th item of an initializer list expression.
+
+Example matches y.
+ (matcher = initListExpr(hasInit(0, expr())))
+ int x{y}.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>&gt;</td><td class="name" onclick="toggle('hasSyntacticForm0')"><a name="hasSyntacticForm0Anchor">hasSyntacticForm</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSyntacticForm0"><pre>Matches the syntactic form of init list expressions
(if expression have it).
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration9')"><a name="hasDeclaration9Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration9')"><a name="hasDeclaration9Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration9"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5701,17 +5905,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration8')"><a name="hasDeclaration8Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration8')"><a name="hasDeclaration8Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration8"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5735,17 +5939,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration7')"><a name="hasDeclaration7Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration7')"><a name="hasDeclaration7Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration7"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5769,17 +5973,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasObjectExpression0')"><a name="hasObjectExpression0Anchor">hasObjectExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasObjectExpression0')"><a name="hasObjectExpression0Anchor">hasObjectExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasObjectExpression0"><pre>Matches a member expression where the object expression is
matched by a given matcher.
@@ -5793,7 +5997,7 @@ with hasObjectExpression(...)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('member0')"><a name="member0Anchor">member</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('member0')"><a name="member0Anchor">member</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="member0"><pre>Matches a member expression where the member is matched by a
given matcher.
@@ -5807,23 +6011,7 @@ memberExpr(member(hasName("first")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerTypeLoc.html">MemberPointerTypeLoc</a>&gt;</td><td class="name" onclick="toggle('pointeeLoc1')"><a name="pointeeLoc1Anchor">pointeeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc1"><pre>Narrows PointerType (and similar) matchers to those where the
-pointee matches a given matcher.
-
-Given
- int *a;
- int const *b;
- float const *f;
-pointerType(pointee(isConstQualified(), isInteger()))
- matches "int const *b"
-
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;</td><td class="name" onclick="toggle('pointee1')"><a name="pointee1Anchor">pointee</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;</td><td class="name" onclick="toggle('pointee1')"><a name="pointee1Anchor">pointee</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="pointee1"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
@@ -5834,12 +6022,12 @@ Given
pointerType(pointee(isConstQualified(), isInteger()))
matches "int const *b"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasUnderlyingDecl0')"><a name="hasUnderlyingDecl0Anchor">hasUnderlyingDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt;</td><td class="name" onclick="toggle('hasUnderlyingDecl0')"><a name="hasUnderlyingDecl0Anchor">hasUnderlyingDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasUnderlyingDecl0"><pre>Matches a NamedDecl whose underlying declaration matches the given
matcher.
@@ -5852,7 +6040,7 @@ unresolvedLookupExpr(hasAnyDeclaration(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('hasPrefix1')"><a name="hasPrefix1Anchor">hasPrefix</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('hasPrefix1')"><a name="hasPrefix1Anchor">hasPrefix</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasPrefix1"><pre>Matches on the prefix of a NestedNameSpecifierLoc.
Given
@@ -5863,7 +6051,7 @@ nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A")))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('specifiesTypeLoc0')"><a name="specifiesTypeLoc0Anchor">specifiesTypeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('specifiesTypeLoc0')"><a name="specifiesTypeLoc0Anchor">specifiesTypeLoc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="specifiesTypeLoc0"><pre>Matches nested name specifier locs that specify a type matching the
given TypeLoc.
@@ -5876,7 +6064,7 @@ nestedNameSpecifierLoc(specifiesTypeLoc(loc(type(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('hasPrefix0')"><a name="hasPrefix0Anchor">hasPrefix</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('hasPrefix0')"><a name="hasPrefix0Anchor">hasPrefix</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasPrefix0"><pre>Matches on the prefix of a NestedNameSpecifier.
Given
@@ -5887,7 +6075,7 @@ nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('specifiesNamespace0')"><a name="specifiesNamespace0Anchor">specifiesNamespace</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('specifiesNamespace0')"><a name="specifiesNamespace0Anchor">specifiesNamespace</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">NamespaceDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="specifiesNamespace0"><pre>Matches nested name specifiers that specify a namespace matching the
given namespace matcher.
@@ -5899,7 +6087,7 @@ nestedNameSpecifier(specifiesNamespace(hasName("ns")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('specifiesType0')"><a name="specifiesType0Anchor">specifiesType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt;</td><td class="name" onclick="toggle('specifiesType0')"><a name="specifiesType0Anchor">specifiesType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="specifiesType0"><pre>Matches nested name specifiers that specify a type matching the
given QualType matcher without qualifiers.
@@ -5913,8 +6101,8 @@ nestedNameSpecifier(specifiesType(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument2')"><a name="hasAnyArgument2Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyArgument2"><pre>Matches any argument of a call expression or a constructor call
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyArgument3')"><a name="hasAnyArgument3Anchor">hasAnyArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyArgument3"><pre>Matches any argument of a call expression or a constructor call
expression, or an ObjC-message-send expression.
Given
@@ -5932,7 +6120,7 @@ objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgument2')"><a name="hasArgument2Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgument2')"><a name="hasArgument2Anchor">hasArgument</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArgument2"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
@@ -5942,7 +6130,7 @@ Example matches y in x(y)
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasReceiver0')"><a name="hasReceiver0Anchor">hasReceiver</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasReceiver0')"><a name="hasReceiver0Anchor">hasReceiver</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasReceiver0"><pre>Matches if the Objective-C message is sent to an instance,
and the inner matcher matches on that instance.
@@ -5954,7 +6142,7 @@ objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasReceiverType0')"><a name="hasReceiverType0Anchor">hasReceiverType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</td><td class="name" onclick="toggle('hasReceiverType0')"><a name="hasReceiverType0Anchor">hasReceiverType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasReceiverType0"><pre>Matches on the receiver of an ObjectiveC Message expression.
Example
@@ -5966,7 +6154,7 @@ matches the [webView ...] message invocation.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter1')"><a name="hasAnyParameter1Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter1')"><a name="hasAnyParameter1Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyParameter1"><pre>Matches any parameter of a function or an ObjC method declaration or a
block.
@@ -5995,7 +6183,7 @@ matching y.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter1')"><a name="hasParameter1Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter1')"><a name="hasParameter1Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasParameter1"><pre>Matches the n'th parameter of a function or an ObjC method
declaration or a block.
@@ -6015,7 +6203,7 @@ matching y.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre>Matches if the cast's source expression
or opaque value's source expression matches the given matcher.
@@ -6030,7 +6218,7 @@ int a = b ?: 1;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OverloadExpr.html">OverloadExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyDeclaration0')"><a name="hasAnyDeclaration0Anchor">hasAnyDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OverloadExpr.html">OverloadExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnyDeclaration0')"><a name="hasAnyDeclaration0Anchor">hasAnyDeclaration</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyDeclaration0"><pre>Matches an OverloadExpr if any of the declarations in the set of
overloads matches the given matcher.
@@ -6047,7 +6235,7 @@ unresolvedLookupExpr(hasAnyDeclaration(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>&gt;</td><td class="name" onclick="toggle('innerType0')"><a name="innerType0Anchor">innerType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>&gt;</td><td class="name" onclick="toggle('innerType0')"><a name="innerType0Anchor">innerType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="innerType0"><pre>Matches ParenType nodes where the inner type is a specific type.
Given
@@ -6057,27 +6245,11 @@ Given
varDecl(hasType(pointsTo(parenType(innerType(functionType()))))) matches
ptr_to_func but not ptr_to_array.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerTypeLoc.html">PointerTypeLoc</a>&gt;</td><td class="name" onclick="toggle('pointeeLoc2')"><a name="pointeeLoc2Anchor">pointeeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc2"><pre>Narrows PointerType (and similar) matchers to those where the
-pointee matches a given matcher.
-
-Given
- int *a;
- int const *b;
- float const *f;
-pointerType(pointee(isConstQualified(), isInteger()))
- matches "int const *b"
-
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;</td><td class="name" onclick="toggle('pointee2')"><a name="pointee2Anchor">pointee</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;</td><td class="name" onclick="toggle('pointee2')"><a name="pointee2Anchor">pointee</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="pointee2"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
@@ -6088,12 +6260,12 @@ Given
pointerType(pointee(isConstQualified(), isInteger()))
matches "int const *b"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasCanonicalType0')"><a name="hasCanonicalType0Anchor">hasCanonicalType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasCanonicalType0')"><a name="hasCanonicalType0Anchor">hasCanonicalType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCanonicalType0"><pre>Matches QualTypes whose canonical type matches InnerMatcher.
Given:
@@ -6106,7 +6278,7 @@ declaration of b but varDecl(hasType(qualType(hasCanonicalType(referenceType()))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration6')"><a name="hasDeclaration6Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration6')"><a name="hasDeclaration6Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration6"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6130,17 +6302,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('ignoringParens0')"><a name="ignoringParens0Anchor">ignoringParens</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('ignoringParens0')"><a name="ignoringParens0Anchor">ignoringParens</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringParens0"><pre>Matches types that match InnerMatcher after any parens are stripped.
Given
@@ -6151,12 +6323,12 @@ would match the declaration for fp.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('pointsTo1')"><a name="pointsTo1Anchor">pointsTo</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('pointsTo1')"><a name="pointsTo1Anchor">pointsTo</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="pointsTo1"><pre>Overloaded to match the pointee type's declaration.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('pointsTo0')"><a name="pointsTo0Anchor">pointsTo</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('pointsTo0')"><a name="pointsTo0Anchor">pointsTo</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="pointsTo0"><pre>Matches if the matched type is a pointer type and the pointee type
matches the specified matcher.
@@ -6168,12 +6340,12 @@ Example matches y-&gt;x()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('references1')"><a name="references1Anchor">references</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('references1')"><a name="references1Anchor">references</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="references1"><pre>Overloaded to match the referenced type's declaration.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('references0')"><a name="references0Anchor">references</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('references0')"><a name="references0Anchor">references</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="references0"><pre>Matches if the matched type is a reference type and the referenced
type matches the specified matcher.
@@ -6188,7 +6360,7 @@ Example matches X &amp;x and const X &amp;y
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration5')"><a name="hasDeclaration5Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration5')"><a name="hasDeclaration5Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration5"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6212,33 +6384,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceTypeLoc.html">ReferenceTypeLoc</a>&gt;</td><td class="name" onclick="toggle('pointeeLoc3')"><a name="pointeeLoc3Anchor">pointeeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td></tr>
-<tr><td colspan="4" class="doc" id="pointeeLoc3"><pre>Narrows PointerType (and similar) matchers to those where the
-pointee matches a given matcher.
-
-Given
- int *a;
- int const *b;
- float const *f;
-pointerType(pointee(isConstQualified(), isInteger()))
- matches "int const *b"
-
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;</td><td class="name" onclick="toggle('pointee3')"><a name="pointee3Anchor">pointee</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;</td><td class="name" onclick="toggle('pointee3')"><a name="pointee3Anchor">pointee</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="pointee3"><pre>Narrows PointerType (and similar) matchers to those where the
pointee matches a given matcher.
@@ -6249,12 +6405,12 @@ Given
pointerType(pointee(isConstQualified(), isInteger()))
matches "int const *b"
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html">ReturnStmt</a>&gt;</td><td class="name" onclick="toggle('hasReturnValue0')"><a name="hasReturnValue0Anchor">hasReturnValue</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html">ReturnStmt</a>&gt;</td><td class="name" onclick="toggle('hasReturnValue0')"><a name="hasReturnValue0Anchor">hasReturnValue</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasReturnValue0"><pre>Matches the return value expression of a return statement
Given
@@ -6266,7 +6422,7 @@ with binaryOperator()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1StmtExpr.html">StmtExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnySubstatement1')"><a name="hasAnySubstatement1Anchor">hasAnySubstatement</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1StmtExpr.html">StmtExpr</a>&gt;</td><td class="name" onclick="toggle('hasAnySubstatement1')"><a name="hasAnySubstatement1Anchor">hasAnySubstatement</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnySubstatement1"><pre>Matches compound statements where at least one substatement matches
a given matcher. Also matches StmtExprs that have CompoundStmt as children.
@@ -6279,13 +6435,13 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('alignOfExpr0')"><a name="alignOfExpr0Anchor">alignOfExpr</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('alignOfExpr0')"><a name="alignOfExpr0Anchor">alignOfExpr</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="alignOfExpr0"><pre>Same as unaryExprOrTypeTraitExpr, but only matching
alignof.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('forFunction0')"><a name="forFunction0Anchor">forFunction</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('forFunction0')"><a name="forFunction0Anchor">forFunction</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forFunction0"><pre>Matches declaration of the function the statement belongs to
Given:
@@ -6299,13 +6455,13 @@ returnStmt(forFunction(hasName("operator=")))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('sizeOfExpr0')"><a name="sizeOfExpr0Anchor">sizeOfExpr</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('sizeOfExpr0')"><a name="sizeOfExpr0Anchor">sizeOfExpr</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="sizeOfExpr0"><pre>Same as unaryExprOrTypeTraitExpr, but only matching
sizeof.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SubstTemplateTypeParmType.html">SubstTemplateTypeParmType</a>&gt;</td><td class="name" onclick="toggle('hasReplacementType0')"><a name="hasReplacementType0Anchor">hasReplacementType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SubstTemplateTypeParmType.html">SubstTemplateTypeParmType</a>&gt;</td><td class="name" onclick="toggle('hasReplacementType0')"><a name="hasReplacementType0Anchor">hasReplacementType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td></tr>
<tr><td colspan="4" class="doc" id="hasReplacementType0"><pre>Matches template type parameter substitutions that have a replacement
type that matches the provided matcher.
@@ -6319,7 +6475,7 @@ substTemplateTypeParmType(hasReplacementType(type())) matches int
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;</td><td class="name" onclick="toggle('forEachSwitchCase0')"><a name="forEachSwitchCase0Anchor">forEachSwitchCase</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchCase.html">SwitchCase</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;</td><td class="name" onclick="toggle('forEachSwitchCase0')"><a name="forEachSwitchCase0Anchor">forEachSwitchCase</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SwitchCase.html">SwitchCase</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachSwitchCase0"><pre>Matches each case or default statement belonging to the given switch
statement. This matcher may produce multiple matches.
@@ -6332,7 +6488,7 @@ switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s")
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition4')"><a name="hasCondition4Anchor">hasCondition</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition4')"><a name="hasCondition4Anchor">hasCondition</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCondition4"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
@@ -6341,7 +6497,7 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration4"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6365,17 +6521,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('isExpr0')"><a name="isExpr0Anchor">isExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('isExpr0')"><a name="isExpr0Anchor">isExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="isExpr0"><pre>Matches a sugar TemplateArgument that refers to a certain expression.
Given
@@ -6389,7 +6545,7 @@ templateSpecializationType(hasAnyTemplateArgument(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToDeclaration0')"><a name="refersToDeclaration0Anchor">refersToDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToDeclaration0')"><a name="refersToDeclaration0Anchor">refersToDeclaration</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="refersToDeclaration0"><pre>Matches a canonical TemplateArgument that refers to a certain
declaration.
@@ -6404,7 +6560,7 @@ classTemplateSpecializationDecl(hasAnyTemplateArgument(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToIntegralType0')"><a name="refersToIntegralType0Anchor">refersToIntegralType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToIntegralType0')"><a name="refersToIntegralType0Anchor">refersToIntegralType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="refersToIntegralType0"><pre>Matches a TemplateArgument that referes to an integral type.
Given
@@ -6416,12 +6572,12 @@ classTemplateSpecializationDecl(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToTemplate0')"><a name="refersToTemplate0Anchor">refersToTemplate</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToTemplate0')"><a name="refersToTemplate0Anchor">refersToTemplate</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="refersToTemplate0"><pre>Matches a TemplateArgument that refers to a certain template.
Given
template&lt;template &lt;typename&gt; class S&gt; class X {};
- template&lt;typename T&gt; class Y {};"
+ template&lt;typename T&gt; class Y {};
X&lt;Y&gt; xi;
classTemplateSpecializationDecl(hasAnyTemplateArgument(
refersToTemplate(templateName())))
@@ -6429,7 +6585,7 @@ classTemplateSpecializationDecl(hasAnyTemplateArgument(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToType0')"><a name="refersToType0Anchor">refersToType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToType0')"><a name="refersToType0Anchor">refersToType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="refersToType0"><pre>Matches a TemplateArgument that refers to a certain type.
Given
@@ -6442,7 +6598,7 @@ classTemplateSpecializationDecl(hasAnyTemplateArgument(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument1')"><a name="hasAnyTemplateArgument1Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument1')"><a name="hasAnyTemplateArgument1Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and
functionDecl that have at least one TemplateArgument matching the given
InnerMatcher.
@@ -6464,7 +6620,7 @@ functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6488,17 +6644,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument1')"><a name="hasTemplateArgument1Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument1')"><a name="hasTemplateArgument1Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and
functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
@@ -6518,7 +6674,7 @@ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration2"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6542,13 +6698,13 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -6568,7 +6724,7 @@ Usable as: Any Matcher
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>&gt;</td><td class="name" onclick="toggle('hasType2')"><a name="hasType2Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>&gt;</td><td class="name" onclick="toggle('hasType2')"><a name="hasType2Anchor">hasType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasType2"><pre>Matches if the expression's or declaration's type matches a type
matcher.
@@ -6583,7 +6739,7 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6607,17 +6763,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('hasUnqualifiedDesugaredType0')"><a name="hasUnqualifiedDesugaredType0Anchor">hasUnqualifiedDesugaredType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('hasUnqualifiedDesugaredType0')"><a name="hasUnqualifiedDesugaredType0Anchor">hasUnqualifiedDesugaredType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasUnqualifiedDesugaredType0"><pre>Matches if the matched type matches the unqualified desugared
type of the matched node.
@@ -6629,7 +6785,7 @@ both B and A.
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgumentOfType0')"><a name="hasArgumentOfType0Anchor">hasArgumentOfType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt;</td><td class="name" onclick="toggle('hasArgumentOfType0')"><a name="hasArgumentOfType0Anchor">hasArgumentOfType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArgumentOfType0"><pre>Matches unary expressions that have a specific type of argument.
Given
@@ -6639,7 +6795,7 @@ unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int"))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasUnaryOperand0')"><a name="hasUnaryOperand0Anchor">hasUnaryOperand</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasUnaryOperand0')"><a name="hasUnaryOperand0Anchor">hasUnaryOperand</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasUnaryOperand0"><pre>Matches if the operand of a unary operator matches.
Example matches true (matcher = hasUnaryOperand(
@@ -6648,7 +6804,21 @@ Example matches true (matcher = hasUnaryOperand(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html">UnresolvedMemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasObjectExpression1')"><a name="hasObjectExpression1Anchor">hasObjectExpression</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasObjectExpression1"><pre>Matches a member expression where the object expression is
+matched by a given matcher.
+
+Given
+ struct X { int m; };
+ void f(X x) { x.m; m; }
+memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
+ matches "x.m" and "m"
+with hasObjectExpression(...)
+ matching "x" and the implicit object expression of "m" which has type X*.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>const Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -6672,17 +6842,17 @@ This can be achieved by using the hasUnqualifiedDesugaredType matcher:
recordType(hasDeclaration(decl())))))
In this matcher, the decl will match the CXXRecordDecl of class X.
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UsingDecl.html">UsingDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyUsingShadowDecl0')"><a name="hasAnyUsingShadowDecl0Anchor">hasAnyUsingShadowDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UsingShadowDecl.html">UsingShadowDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingDecl.html">UsingDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyUsingShadowDecl0')"><a name="hasAnyUsingShadowDecl0Anchor">hasAnyUsingShadowDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingShadowDecl.html">UsingShadowDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyUsingShadowDecl0"><pre>Matches any using shadow declaration.
Given
@@ -6692,7 +6862,7 @@ usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
matches using X::b </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UsingShadowDecl.html">UsingShadowDecl</a>&gt;</td><td class="name" onclick="toggle('hasTargetDecl0')"><a name="hasTargetDecl0Anchor">hasTargetDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingShadowDecl.html">UsingShadowDecl</a>&gt;</td><td class="name" onclick="toggle('hasTargetDecl0')"><a name="hasTargetDecl0Anchor">hasTargetDecl</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasTargetDecl0"><pre>Matches a using shadow declaration where the target declaration is
matched by the given matcher.
@@ -6704,7 +6874,7 @@ usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl())))
matches using X::b but not using X::a </pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType6')"><a name="hasType6Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType6')"><a name="hasType6Anchor">hasType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasType6"><pre>Overloaded to match the declaration of the expression's or value
declaration's type.
@@ -6721,11 +6891,11 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
void y(X &amp;x) { x; X z; }
class Y { friend class X; };
-Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
+Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType3')"><a name="hasType3Anchor">hasType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>&gt;</td><td class="name" onclick="toggle('hasType3')"><a name="hasType3Anchor">hasType</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasType3"><pre>Matches if the expression's or declaration's type matches a type
matcher.
@@ -6740,7 +6910,7 @@ Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasInitializer0')"><a name="hasInitializer0Anchor">hasInitializer</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasInitializer0')"><a name="hasInitializer0Anchor">hasInitializer</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasInitializer0"><pre>Matches a variable declaration that has an initializer expression
that matches the given matcher.
@@ -6750,7 +6920,7 @@ Example matches x (matcher = varDecl(hasInitializer(callExpr())))
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VariableArrayType.html">VariableArrayType</a>&gt;</td><td class="name" onclick="toggle('hasSizeExpr0')"><a name="hasSizeExpr0Anchor">hasSizeExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VariableArrayType.html">VariableArrayType</a>&gt;</td><td class="name" onclick="toggle('hasSizeExpr0')"><a name="hasSizeExpr0Anchor">hasSizeExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSizeExpr0"><pre>Matches VariableArrayType nodes that have a specific size
expression.
@@ -6764,7 +6934,7 @@ variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1WhileStmt.html">WhileStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody2')"><a name="hasBody2Anchor">hasBody</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1WhileStmt.html">WhileStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody2')"><a name="hasBody2Anchor">hasBody</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBody2"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -6777,7 +6947,7 @@ with compoundStmt()
</pre></td></tr>
-<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1WhileStmt.html">WhileStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition2')"><a name="hasCondition2Anchor">hasCondition</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1WhileStmt.html">WhileStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition2')"><a name="hasCondition2Anchor">hasCondition</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCondition2"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
@@ -6786,13 +6956,13 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
</pre></td></tr>
-<tr><td>Matcher&lt;internal::BindableMatcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;&gt;</td><td class="name" onclick="toggle('loc1')"><a name="loc1Anchor">loc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;internal::BindableMatcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;&gt;</td><td class="name" onclick="toggle('loc1')"><a name="loc1Anchor">loc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="loc1"><pre>Matches NestedNameSpecifierLocs for which the given inner
NestedNameSpecifier-matcher matches.
</pre></td></tr>
-<tr><td>Matcher&lt;internal::BindableMatcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;&gt;</td><td class="name" onclick="toggle('loc0')"><a name="loc0Anchor">loc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
+<tr><td>Matcher&lt;internal::BindableMatcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;&gt;</td><td class="name" onclick="toggle('loc0')"><a name="loc0Anchor">loc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="loc0"><pre>Matches TypeLocs for which the given inner
QualType-matcher matches.
</pre></td></tr>
diff --git a/docs/LibASTMatchersTutorial.rst b/docs/LibASTMatchersTutorial.rst
index 832b47efd1b8..8b7ee7f98fa2 100644
--- a/docs/LibASTMatchersTutorial.rst
+++ b/docs/LibASTMatchersTutorial.rst
@@ -19,16 +19,16 @@ As Clang is part of the LLVM project, you'll need to download LLVM's
source code first. Both Clang and LLVM are maintained as Subversion
repositories, but we'll be accessing them through the git mirror. For
further information, see the `getting started
-guide <http://llvm.org/docs/GettingStarted.html>`_.
+guide <https://llvm.org/docs/GettingStarted.html>`_.
.. code-block:: console
mkdir ~/clang-llvm && cd ~/clang-llvm
- git clone http://llvm.org/git/llvm.git
+ git clone https://llvm.org/git/llvm.git
cd llvm/tools
- git clone http://llvm.org/git/clang.git
+ git clone https://llvm.org/git/clang.git
cd clang/tools
- git clone http://llvm.org/git/clang-tools-extra.git extra
+ git clone https://llvm.org/git/clang-tools-extra.git extra
Next you need to obtain the CMake build system and Ninja build tool. You
may already have CMake installed, but current binary versions of CMake
@@ -113,6 +113,7 @@ CMakeLists.txt should have the following contents:
LoopConvert.cpp
)
target_link_libraries(loop-convert
+ PRIVATE
clangTooling
clangBasic
clangASTMatchers
diff --git a/docs/LibFormat.rst b/docs/LibFormat.rst
index 2863a076edf4..889fbbac8c7a 100644
--- a/docs/LibFormat.rst
+++ b/docs/LibFormat.rst
@@ -45,7 +45,7 @@ two style guides are hard-coded:
.. code-block:: c++
/// Returns a format style complying with the LLVM coding standards:
- /// http://llvm.org/docs/CodingStandards.html.
+ /// https://llvm.org/docs/CodingStandards.html.
FormatStyle getLLVMStyle();
/// Returns a format style complying with Google's C++ style guide:
diff --git a/docs/LibTooling.rst b/docs/LibTooling.rst
index a422a1d5665a..41110f5d3149 100644
--- a/docs/LibTooling.rst
+++ b/docs/LibTooling.rst
@@ -198,4 +198,4 @@ Linking
For a list of libraries to link, look at one of the tools' Makefiles (for
example `clang-check/Makefile
-<http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/Makefile?view=markup>`_).
+<https://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/Makefile?view=markup>`_).
diff --git a/docs/MSVCCompatibility.rst b/docs/MSVCCompatibility.rst
index b82869b267cd..cd2acae97029 100644
--- a/docs/MSVCCompatibility.rst
+++ b/docs/MSVCCompatibility.rst
@@ -70,7 +70,7 @@ The status of major ABI-impacting C++ features:
.. _#pragma pointers_to_members:
http://msdn.microsoft.com/en-us/library/83cch5a6.aspx
.. _/vm: http://msdn.microsoft.com/en-us/library/yad46a6z.aspx
-.. _pointer to a member of a virtual base class: http://llvm.org/PR15713
+.. _pointer to a member of a virtual base class: https://llvm.org/PR15713
* Debug info: :good:`Mostly complete`. Clang emits relatively complete CodeView
debug information if ``/Z7`` or ``/Zi`` is passed. Microsoft's link.exe will
@@ -137,7 +137,7 @@ following program, Clang will recover as if the user had written the
commented-out code:
.. _frequently asked question:
- http://clang.llvm.org/compatibility.html#dep_lookup
+ https://clang.llvm.org/compatibility.html#dep_lookup
.. code-block:: c++
diff --git a/docs/MemorySanitizer.rst b/docs/MemorySanitizer.rst
index 4e033fa1941d..f513b009a32f 100644
--- a/docs/MemorySanitizer.rst
+++ b/docs/MemorySanitizer.rst
@@ -16,7 +16,7 @@ Typical slowdown introduced by MemorySanitizer is **3x**.
How to build
============
-Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
+Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.
Usage
=====
diff --git a/docs/Modules.rst b/docs/Modules.rst
index 493c54d3913a..7aee4ffee2df 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -411,7 +411,7 @@ A *requires-declaration* specifies the requirements that an importing translatio
*feature*:
``!``:sub:`opt` *identifier*
-The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. When building a module for use by a compilation, submodules requiring unavailable features are ignored. The optional ``!`` indicates that a feature is incompatible with the module.
+The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects, platforms, environments and target specific features. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. When building a module for use by a compilation, submodules requiring unavailable features are ignored. The optional ``!`` indicates that a feature is incompatible with the module.
The following features are defined:
@@ -466,6 +466,11 @@ tls
*target feature*
A specific target feature (e.g., ``sse4``, ``avx``, ``neon``) is available.
+*platform/os*
+ A os/platform variant (e.g. ``freebsd``, ``win32``, ``windows``, ``linux``, ``ios``, ``macos``, ``iossimulator``) is available.
+
+*environment*
+ A environment variant (e.g. ``gnu``, ``gnueabi``, ``android``, ``msvc``) is available.
**Example:** The ``std`` module can be extended to also include C++ and C++11 headers using a *requires-declaration*:
diff --git a/docs/OpenMPSupport.rst b/docs/OpenMPSupport.rst
index e8ec1e371b04..04a9648ca294 100644
--- a/docs/OpenMPSupport.rst
+++ b/docs/OpenMPSupport.rst
@@ -66,12 +66,11 @@ Combined directives
* #pragma omp target teams distribute parallel for [simd]: :good:`Complete`.
-Clang does not support any constructs/updates from upcoming OpenMP 5.0 except
+Clang does not support any constructs/updates from OpenMP 5.0 except
for `reduction`-based clauses in the `task` and `target`-based directives.
In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools
Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and mac OS.
-ows, and mac OS.
.. _basic support for Cuda devices:
@@ -109,11 +108,19 @@ are stored in the global memory. In `Cuda` mode local variables are not shared
between the threads and it is user responsibility to share the required data
between the threads in the parallel regions.
+Collapsed loop nest counter
+---------------------------
+
+When using the collapse clause on a loop nest the default behaviour is to
+automatically extend the representation of the loop counter to 64 bits for
+the cases where the sizes of the collapsed loops are not known at compile
+time. To prevent this conservative choice and use at most 32 bits,
+compile your program with the `-fopenmp-optimistic-collapse`.
+
+
Features not supported or with limited support for Cuda devices
---------------------------------------------------------------
-- Reductions across the teams are not supported yet.
-
- Cancellation constructs are not supported.
- Doacross loop nest is not supported.
diff --git a/docs/PCHInternals.rst b/docs/PCHInternals.rst
index b0372cb931ad..109260da9050 100644
--- a/docs/PCHInternals.rst
+++ b/docs/PCHInternals.rst
@@ -70,7 +70,7 @@ minimizes both creation time and the time required to initially load the AST
file. The AST file itself contains a serialized representation of Clang's
abstract syntax trees and supporting data structures, stored using the same
compressed bitstream as `LLVM's bitcode file format
-<http://llvm.org/docs/BitCodeFormat.html>`_.
+<https://llvm.org/docs/BitCodeFormat.html>`_.
Clang's AST files are loaded "lazily" from disk. When an AST file is initially
loaded, Clang reads only a small amount of data from the AST file to establish
@@ -134,7 +134,7 @@ only contain the serialized AST.
The ``clangast`` section is organized into several different blocks, each of
which contains the serialized representation of a part of Clang's internal
representation. Each of the blocks corresponds to either a block or a record
-within `LLVM's bitstream format <http://llvm.org/docs/BitCodeFormat.html>`_.
+within `LLVM's bitstream format <https://llvm.org/docs/BitCodeFormat.html>`_.
The contents of each of these logical blocks are described below.
.. image:: PCHLayout.png
@@ -142,7 +142,7 @@ The contents of each of these logical blocks are described below.
The ``llvm-objdump`` utility provides a ``-raw-clang-ast`` option to extract the
binary contents of the AST section from an object file container.
-The `llvm-bcanalyzer <http://llvm.org/docs/CommandGuide/llvm-bcanalyzer.html>`_
+The `llvm-bcanalyzer <https://llvm.org/docs/CommandGuide/llvm-bcanalyzer.html>`_
utility can be used to examine the actual structure of the bitstream for the AST
section. This information can be used both to help understand the structure of
the AST section and to isolate areas where the AST representation can still be
diff --git a/docs/PTHInternals.rst b/docs/PTHInternals.rst
deleted file mode 100644
index 7401cf9b4d4b..000000000000
--- a/docs/PTHInternals.rst
+++ /dev/null
@@ -1,163 +0,0 @@
-==========================
-Pretokenized Headers (PTH)
-==========================
-
-This document first describes the low-level interface for using PTH and
-then briefly elaborates on its design and implementation. If you are
-interested in the end-user view, please see the :ref:`User's Manual
-<usersmanual-precompiled-headers>`.
-
-Using Pretokenized Headers with ``clang`` (Low-level Interface)
-===============================================================
-
-The Clang compiler frontend, ``clang -cc1``, supports three command line
-options for generating and using PTH files.
-
-To generate PTH files using ``clang -cc1``, use the option ``-emit-pth``:
-
-.. code-block:: console
-
- $ clang -cc1 test.h -emit-pth -o test.h.pth
-
-This option is transparently used by ``clang`` when generating PTH
-files. Similarly, PTH files can be used as prefix headers using the
-``-include-pth`` option:
-
-.. code-block:: console
-
- $ clang -cc1 -include-pth test.h.pth test.c -o test.s
-
-Alternatively, Clang's PTH files can be used as a raw "token-cache" (or
-"content" cache) of the source included by the original header file.
-This means that the contents of the PTH file are searched as substitutes
-for *any* source files that are used by ``clang -cc1`` to process a
-source file. This is done by specifying the ``-token-cache`` option:
-
-.. code-block:: console
-
- $ cat test.h
- #include <stdio.h>
- $ clang -cc1 -emit-pth test.h -o test.h.pth
- $ cat test.c
- #include "test.h"
- $ clang -cc1 test.c -o test -token-cache test.h.pth
-
-In this example the contents of ``stdio.h`` (and the files it includes)
-will be retrieved from ``test.h.pth``, as the PTH file is being used in
-this case as a raw cache of the contents of ``test.h``. This is a
-low-level interface used to both implement the high-level PTH interface
-as well as to provide alternative means to use PTH-style caching.
-
-PTH Design and Implementation
-=============================
-
-Unlike GCC's precompiled headers, which cache the full ASTs and
-preprocessor state of a header file, Clang's pretokenized header files
-mainly cache the raw lexer *tokens* that are needed to segment the
-stream of characters in a source file into keywords, identifiers, and
-operators. Consequently, PTH serves to mainly directly speed up the
-lexing and preprocessing of a source file, while parsing and
-type-checking must be completely redone every time a PTH file is used.
-
-Basic Design Tradeoffs
-----------------------
-
-In the long term there are plans to provide an alternate PCH
-implementation for Clang that also caches the work for parsing and type
-checking the contents of header files. The current implementation of PCH
-in Clang as pretokenized header files was motivated by the following
-factors:
-
-**Language independence**
- PTH files work with any language that
- Clang's lexer can handle, including C, Objective-C, and (in the early
- stages) C++. This means development on language features at the
- parsing level or above (which is basically almost all interesting
- pieces) does not require PTH to be modified.
-
-**Simple design**
- Relatively speaking, PTH has a simple design and
- implementation, making it easy to test. Further, because the
- machinery for PTH resides at the lower-levels of the Clang library
- stack it is fairly straightforward to profile and optimize.
-
-Further, compared to GCC's PCH implementation (which is the dominate
-precompiled header file implementation that Clang can be directly
-compared against) the PTH design in Clang yields several attractive
-features:
-
-**Architecture independence**
- In contrast to GCC's PCH files (and
- those of several other compilers), Clang's PTH files are architecture
- independent, requiring only a single PTH file when building a
- program for multiple architectures.
-
- For example, on Mac OS X one may wish to compile a "universal binary"
- that runs on PowerPC, 32-bit Intel (i386), and 64-bit Intel
- architectures. In contrast, GCC requires a PCH file for each
- architecture, as the definitions of types in the AST are
- architecture-specific. Since a Clang PTH file essentially represents
- a lexical cache of header files, a single PTH file can be safely used
- when compiling for multiple architectures. This can also reduce
- compile times because only a single PTH file needs to be generated
- during a build instead of several.
-
-**Reduced memory pressure**
- Similar to GCC, Clang reads PTH files
- via the use of memory mapping (i.e., ``mmap``). Clang, however,
- memory maps PTH files as read-only, meaning that multiple invocations
- of ``clang -cc1`` can share the same pages in memory from a
- memory-mapped PTH file. In comparison, GCC also memory maps its PCH
- files but also modifies those pages in memory, incurring the
- copy-on-write costs. The read-only nature of PTH can greatly reduce
- memory pressure for builds involving multiple cores, thus improving
- overall scalability.
-
-**Fast generation**
- PTH files can be generated in a small fraction
- of the time needed to generate GCC's PCH files. Since PTH/PCH
- generation is a serial operation that typically blocks progress
- during a build, faster generation time leads to improved processor
- utilization with parallel builds on multicore machines.
-
-Despite these strengths, PTH's simple design suffers some algorithmic
-handicaps compared to other PCH strategies such as those used by GCC.
-While PTH can greatly speed up the processing time of a header file, the
-amount of work required to process a header file is still roughly linear
-in the size of the header file. In contrast, the amount of work done by
-GCC to process a precompiled header is (theoretically) constant (the
-ASTs for the header are literally memory mapped into the compiler). This
-means that only the pieces of the header file that are referenced by the
-source file including the header are the only ones the compiler needs to
-process during actual compilation. While GCC's particular implementation
-of PCH mitigates some of these algorithmic strengths via the use of
-copy-on-write pages, the approach itself can fundamentally dominate at
-an algorithmic level, especially when one considers header files of
-arbitrary size.
-
-There is also a PCH implementation for Clang based on the lazy
-deserialization of ASTs. This approach theoretically has the same
-constant-time algorithmic advantages just mentioned but also retains some
-of the strengths of PTH such as reduced memory pressure (ideal for
-multi-core builds).
-
-Internal PTH Optimizations
---------------------------
-
-While the main optimization employed by PTH is to reduce lexing time of
-header files by caching pre-lexed tokens, PTH also employs several other
-optimizations to speed up the processing of header files:
-
-- ``stat`` caching: PTH files cache information obtained via calls to
- ``stat`` that ``clang -cc1`` uses to resolve which files are included
- by ``#include`` directives. This greatly reduces the overhead
- involved in context-switching to the kernel to resolve included
- files.
-
-- Fast skipping of ``#ifdef`` ... ``#endif`` chains: PTH files
- record the basic structure of nested preprocessor blocks. When the
- condition of the preprocessor block is false, all of its tokens are
- immediately skipped instead of requiring them to be handled by
- Clang's preprocessor.
-
-
diff --git a/docs/RAVFrontendAction.rst b/docs/RAVFrontendAction.rst
index c37d3c0e812e..dea23733bc48 100644
--- a/docs/RAVFrontendAction.rst
+++ b/docs/RAVFrontendAction.rst
@@ -128,7 +128,7 @@ locations:
if (Declaration->getQualifiedNameAsString() == "n::m::C") {
// getFullLoc uses the ASTContext's SourceManager to resolve the source
// location and break it up into its line and column parts.
- FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getLocStart());
+ FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());
if (FullLocation.isValid())
llvm::outs() << "Found declaration at "
<< FullLocation.getSpellingLineNumber() << ":"
@@ -160,7 +160,7 @@ Now we can combine all of the above into a small example program:
bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
if (Declaration->getQualifiedNameAsString() == "n::m::C") {
- FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getLocStart());
+ FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());
if (FullLocation.isValid())
llvm::outs() << "Found declaration at "
<< FullLocation.getSpellingLineNumber() << ":"
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 1e45a13ef916..b6a405dbc78b 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,41 +1,41 @@
=======================================
-Clang 7.0.0 (In-Progress) Release Notes
+Clang 8.0.0 (In-Progress) Release Notes
=======================================
.. contents::
:local:
:depth: 2
-Written by the `LLVM Team <http://llvm.org/>`_
+Written by the `LLVM Team <https://llvm.org/>`_
.. warning::
- These are in-progress notes for the upcoming Clang 7 release.
+ These are in-progress notes for the upcoming Clang 8 release.
Release notes for previous releases can be found on
- `the Download Page <http://releases.llvm.org/download.html>`_.
+ `the Download Page <https://releases.llvm.org/download.html>`_.
Introduction
============
This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release 7.0.0. Here we
+frontend, part of the LLVM Compiler Infrastructure, release 8.0.0. Here we
describe the status of Clang in some detail, including major
improvements from the previous release and new feature work. For the
general LLVM release notes, see `the LLVM
-documentation <http://llvm.org/docs/ReleaseNotes.html>`_. All LLVM
+documentation <https://llvm.org/docs/ReleaseNotes.html>`_. All LLVM
releases may be downloaded from the `LLVM releases web
-site <http://llvm.org/releases/>`_.
+site <https://llvm.org/releases/>`_.
For more information about Clang or LLVM, including information about the
-latest release, please see the `Clang Web Site <http://clang.llvm.org>`_ or the
-`LLVM Web Site <http://llvm.org>`_.
+latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
+`LLVM Web Site <https://llvm.org>`_.
Note that if you are reading this file from a Subversion checkout or the
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 <http://llvm.org/releases/>`_.
+see the `releases page <https://llvm.org/releases/>`_.
-What's New in Clang 7.0.0?
+What's New in Clang 8.0.0?
==========================
Some of the major new features and improvements to Clang are listed
@@ -46,86 +46,95 @@ sections with improvements to Clang's support for those languages.
Major New Features
------------------
-- A new Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) group
- was added. Please refer to the :ref:`release-notes-ubsan` section of the
- release notes for the details.
+- Clang supports use of a profile remapping file, which permits
+ profile data captured for one version of a program to be applied
+ when building another version where symbols have changed (for
+ example, due to renaming a class or namespace).
+ See the :doc:`UsersManual` for details.
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- ``-Wc++98-compat-extra-semi`` is a new flag, which was previously inseparable
- from ``-Wc++98-compat-pedantic``. The latter still controls the new flag.
+- ``-Wextra-semi-stmt`` is a new diagnostic that diagnoses extra semicolons,
+ much like ``-Wextra-semi``. This new diagnostic diagnoses all *unnecessary*
+ null statements (expression statements without an expression), unless: the
+ semicolon directly follows a macro that was expanded to nothing or if the
+ semicolon is within the macro itself. This applies to macros defined in system
+ headers as well as user-defined macros.
-- ``-Wextra-semi`` now also controls ``-Wc++98-compat-extra-semi``.
- Please do note that if you pass ``-Wno-c++98-compat-pedantic``, it implies
- ``-Wno-c++98-compat-extra-semi``, so if you want that diagnostic, you need
- to explicitly re-enable it (e.g. by appending ``-Wextra-semi``).
+ .. code-block:: c++
+
+ #define MACRO(x) int x;
+ #define NULLMACRO(varname)
+
+ void test() {
+ ; // <- warning: ';' with no preceding expression is a null statement
+
+ while (true)
+ ; // OK, it is needed.
+
+ switch (my_enum) {
+ case E1:
+ // stuff
+ break;
+ case E2:
+ ; // OK, it is needed.
+ }
+
+ MACRO(v0;) // Extra semicolon, but within macro, so ignored.
+
+ MACRO(v1); // <- warning: ';' with no preceding expression is a null statement
+
+ NULLMACRO(v2); // ignored, NULLMACRO expanded to nothing.
+ }
+
+- ``-Wempty-init-stmt`` is a new diagnostic that diagnoses empty init-statements
+ of ``if``, ``switch``, ``range-based for``, unless: the semicolon directly
+ follows a macro that was expanded to nothing or if the semicolon is within the
+ macro itself (both macros from system headers, and normal macros). This
+ diagnostic is in the ``-Wextra-semi-stmt`` group and is enabled in
+ ``-Wextra``.
+
+ .. code-block:: c++
+
+ void test() {
+ if(; // <- warning: init-statement of 'if' is a null statement
+ true)
+ ;
+
+ switch (; // <- warning: init-statement of 'switch' is a null statement
+ x) {
+ ...
+ }
+
+ for (; // <- warning: init-statement of 'range-based for' is a null statement
+ int y : S())
+ ;
+ }
-- ``-Wself-assign`` and ``-Wself-assign-field`` were extended to diagnose
- self-assignment operations using overloaded operators (i.e. classes).
- If you are doing such an assignment intentionally, e.g. in a unit test for
- a data structure, the first warning can be disabled by passing
- ``-Wno-self-assign-overloaded``, also the warning can be suppressed by adding
- ``*&`` to the right-hand side or casting it to the appropriate reference type.
Non-comprehensive list of changes in this release
-------------------------------------------------
-- Clang binary and libraries have been renamed from 7.0 to 7.
- For example, the ``clang`` binary will be called ``clang-7``
- instead of ``clang-7.0``.
-
-- Clang implements a collection of recent fixes to the C++ standard's definition
- of "standard-layout". In particular, a class is only considered to be
- standard-layout if all base classes and the first data member (or bit-field)
- can be laid out at offset zero.
-
-- Clang's handling of the GCC ``packed`` class attribute in C++ has been fixed
- to apply only to non-static data members and not to base classes. This fixes
- an ABI difference between Clang and GCC, but creates an ABI difference between
- Clang 7 and earlier versions. The old behavior can be restored by setting
- ``-fclang-abi-compat`` to ``6`` or earlier.
-
-- Clang implements the proposed resolution of LWG issue 2358, along with the
- `corresponding change to the Itanium C++ ABI
- <https://github.com/itanium-cxx-abi/cxx-abi/pull/51>`_, which make classes
- containing only unnamed non-zero-length bit-fields be considered non-empty.
- This is an ABI break compared to prior Clang releases, but makes Clang
- generate code that is ABI-compatible with other compilers. The old
- behavior can be restored by setting ``-fclang-abi-compat`` to ``6`` or
- lower.
-
-- An existing tool named ``diagtool`` has been added to the release. As the
- name suggests, it helps with dealing with diagnostics in ``clang``, such as
- finding out the warning hierarchy, and which of them are enabled by default
- or for a particular compiler invocation.
-
-- By default, Clang emits an address-significance table into
- every ELF object file when using the integrated assembler.
- Address-significance tables allow linkers to implement `safe ICF
- <https://research.google.com/pubs/archive/36912.pdf>`_ without the false
- positives that can result from other implementation techniques such as
- relocation scanning. The ``-faddrsig`` and ``-fno-addrsig`` flags can be
- used to control whether to emit the address-significance table.
+- The experimental feature Pretokenized Headers (PTH) was removed in its
+ entirely from Clang. The feature did not properly work with about 1/3 of the
+ possible tokens available and was unmaintained.
-- ...
+- The internals of libc++ include directory detection on MacOS have changed.
+ Instead of running a search based on the ``-resource-dir`` flag, the search
+ is now based on the path of the compiler in the filesystem. The default
+ behaviour should not change. However, if you override ``-resource-dir``
+ manually and rely on the old behaviour you will need to add appropriate
+ compiler flags for finding the corresponding libc++ include directory.
New Compiler Flags
------------------
-- ``-fstrict-float-cast-overflow`` and ``-fno-strict-float-cast-overflow``.
-
- When a floating-point value is not representable in a destination integer
- type, the code has undefined behavior according to the language standard. By
- default, Clang will not guarantee any particular result in that case. With the
- 'no-strict' option, Clang attempts to match the overflowing behavior of the
- target's native float-to-int conversion instructions.
-
-- ``-fforce-emit-vtables`` and ``-fno-force-emit-vtables``.
+- ``-fprofile-filter-files=[regexes]`` and ``-fprofile-exclude-files=[regexes]``.
- In order to improve devirtualization, forces emitting of vtables even in
- modules where it isn't necessary. It causes more inline virtual functions
- to be emitted.
+ Clang has now options to filter or exclude some files when
+ instrumenting for gcov-based profiling.
+ See the :doc:`UsersManual` for details.
- ...
@@ -140,46 +149,36 @@ future versions of Clang.
Modified Compiler Flags
-----------------------
-- Before Clang 7, we prepended the `#` character to the `--autocomplete`
- argument to enable cc1 flags. For example, when the `-cc1` or `-Xclang` flag
- is in the :program:`clang` invocation, the shell executed
- `clang --autocomplete=#-<flag to be completed>`. Clang 7 now requires the
- whole invocation including all flags to be passed to the `--autocomplete` like
- this: `clang --autocomplete=-cc1,-xc++,-fsyn`.
+- As of clang 8, `alignof` and `_Alignof` return the ABI alignment of a type,
+ as opposed to the preferred alignment. `__alignof` still returns the
+ preferred alignment. `-fclang-abi-compat=7` (and previous) will make
+ `alignof` and `_Alignof` return preferred alignment again.
+
New Pragmas in Clang
--------------------
-Clang now supports the ...
-
+- Clang now supports adding multiple `#pragma clang attribute` attributes into
+ a scope of pushed attributes.
Attribute Changes in Clang
--------------------------
-- Clang now supports function multiversioning with attribute 'target' on ELF
- based x86/x86-64 environments by using indirect functions. This implementation
- has a few minor limitations over the GCC implementation for the sake of AST
- sanity, however it is otherwise compatible with existing code using this
- feature for GCC. Consult the documentation for the target attribute for more
- information.
-
- ...
Windows Support
---------------
-- clang-cl's support for precompiled headers has been much improved:
-
- - When using a pch file, clang-cl now no longer redundantly emits inline
- methods that are already stored in the obj that was built together with
- the pch file (matching cl.exe). This speeds up builds using pch files
- by around 30%.
-
- - The /Ycfoo.h and /Yufoo.h flags can now be used without /FIfoo.h when
- foo.h is instead included by an explicit `#include` directive. This means
- Visual Studio's default stdafx.h setup now uses precompiled headers with
- clang-cl.
+- clang-cl now supports the use of the precompiled header options /Yc and /Yu
+ without the filename argument. When these options are used without the
+ filename, a `#pragma hdrstop` inside the source marks the end of the
+ precompiled code.
+- clang-cl has a new command-line option, ``/Zc:dllexportInlines-``, similar to
+ ``-fvisibility-inlines-hidden`` on non-Windows, that makes class-level
+ `dllexport` and `dllimport` attributes not apply to inline member functions.
+ This can significantly reduce compile and link times. See the `User's Manual
+ <UsersManual.html#the-zc-dllexportinlines-option>`_ for more info.
- ...
@@ -215,41 +214,52 @@ OpenCL C Language Changes in Clang
...
+ABI Changes in Clang
+--------------------
+
+- `_Alignof` and `alignof` now return the ABI alignment of a type, as opposed
+ to the preferred alignment.
+
+ - This is more in keeping with the language of the standards, as well as
+ being compatible with gcc
+ - `__alignof` and `__alignof__` still return the preferred alignment of
+ a type
+ - This shouldn't break any ABI except for things that explicitly ask for
+ `alignas(alignof(T))`.
+ - If you have interfaces that break with this change, you may wish to switch
+ to `alignas(__alignof(T))`, instead of using the `-fclang-abi-compat`
+ switch.
+
OpenMP Support in Clang
----------------------------------
-- Clang gained basic support for OpenMP 4.5 offloading for NVPTX target.
- To compile your program for NVPTX target use the following options:
- `-fopenmp -fopenmp-targets=nvptx64-nvidia-cuda` for 64 bit platforms or
- `-fopenmp -fopenmp-targets=nvptx-nvidia-cuda` for 32 bit platform.
+- Support relational-op != (not-equal) as one of the canonical forms of random
+ access iterator.
+
+- Added support for mapping of the lambdas in target regions.
-- Passing options to the OpenMP device offloading toolchain can be done using
- the `-Xopenmp-target=<triple> -opt=val` flag. In this way the `-opt=val`
- option will be forwarded to the respective OpenMP device offloading toolchain
- described by the triple. For example passing the compute capability to
- the OpenMP NVPTX offloading toolchain can be done as follows:
- `-Xopenmp-target=nvptx64-nvidia-cuda -march=sm_60`. For the case when only one
- target offload toolchain is specified under the `-fopenmp-targets=<triples>`
- option, then the triple can be skipped: `-Xopenmp-target -march=sm_60`.
+- Added parsing/sema analysis for OpenMP 5.0 requires directive.
-- Other bugfixes.
+- Various bugfixes and improvements.
+
+New features supported for Cuda devices:
+
+- Added support for the reductions across the teams.
+
+- Extended number of constructs that can be executed in SPMD mode.
+
+- Fixed support for lastprivate/reduction variables in SPMD constructs.
+
+- General performance improvement.
CUDA Support in Clang
---------------------
-- Clang will now try to locate the CUDA installation next to :program:`ptxas`
- in the `PATH` environment variable. This behavior can be turned off by passing
- the new flag `--cuda-path-ignore-env`.
-
-- Clang now supports generating object files with relocatable device code. This
- feature needs to be enabled with `-fcuda-rdc` and my result in performance
- penalties compared to whole program compilation. Please note that NVIDIA's
- :program:`nvcc` must be used for linking.
Internal API Changes
--------------------
-These are major API changes that have happened since the 6.0.0 release of
+These are major API changes that have happened since the 7.0.0 release of
Clang. If upgrading an external codebase that uses Clang as a library,
this section should help get you past the largest hurdles of upgrading.
@@ -263,9 +273,6 @@ AST Matchers
clang-format
------------
-- Clang-format will now support detecting and formatting code snippets in raw
- string literals. This is configured through the `RawStringFormats` style
- option.
- ...
@@ -287,31 +294,75 @@ Static Analyzer
Undefined Behavior Sanitizer (UBSan)
------------------------------------
-* A new Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) group
- was added.
-
- Currently, only one type of issues is caught - implicit integer truncation
- (``-fsanitize=implicit-integer-truncation``), also known as integer demotion.
- While there is a ``-Wconversion`` diagnostic group that catches this kind of
- issues, it is both noisy, and does not catch **all** the cases.
+* The Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) group
+ was extended. One more type of issues is caught - implicit integer sign change.
+ (``-fsanitize=implicit-integer-sign-change``).
+ This makes the Implicit Conversion Sanitizer feature-complete,
+ with only missing piece being bitfield handling.
+ While there is a ``-Wsign-conversion`` diagnostic group that catches this kind
+ of issues, it is both noisy, and does not catch **all** the cases.
.. code-block:: c++
- unsigned char store = 0;
-
bool consume(unsigned int val);
- void test(unsigned long val) {
- if (consume(val)) // the value may have been silently truncated.
- store = store + 768; // before addition, 'store' was promoted to int.
- (void)consume((unsigned int)val); // OK, the truncation is explicit.
+ void test(int val) {
+ (void)consume(val); // If the value was negative, it is now large positive.
+ (void)consume((unsigned int)val); // OK, the conversion is explicit.
}
- Just like other ``-fsanitize=integer`` checks, these issues are **not**
+ Like some other ``-fsanitize=integer`` checks, these issues are **not**
undefined behaviour. But they are not *always* intentional, and are somewhat
hard to track down. This group is **not** enabled by ``-fsanitize=undefined``,
- but the ``-fsanitize=implicit-integer-truncation`` check
+ but the ``-fsanitize=implicit-integer-sign-change`` check
is enabled by ``-fsanitize=integer``.
+ (as is ``-fsanitize=implicit-integer-truncation`` check)
+
+* The Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) has
+ learned to sanitize compound assignment operators.
+
+* ``alignment`` check has learned to sanitize the assume_aligned-like attributes:
+
+ .. code-block:: c++
+
+ typedef char **__attribute__((align_value(1024))) aligned_char;
+ struct ac_struct {
+ aligned_char a;
+ };
+ char **load_from_ac_struct(struct ac_struct *x) {
+ return x->a; // <- check that loaded 'a' is aligned
+ }
+
+ char **passthrough(__attribute__((align_value(1024))) char **x) {
+ return x; // <- check the pointer passed as function argument
+ }
+
+ char **__attribute__((alloc_align(2)))
+ alloc_align(int size, unsigned long alignment);
+
+ char **caller(int size) {
+ return alloc_align(size, 1024); // <- check returned pointer
+ }
+
+ char **__attribute__((assume_aligned(1024))) get_ptr();
+
+ char **caller2() {
+ return get_ptr(); // <- check returned pointer
+ }
+
+ void *caller3(char **x) {
+ return __builtin_assume_aligned(x, 1024); // <- check returned pointer
+ }
+
+ void *caller4(char **x, unsigned long offset) {
+ return __builtin_assume_aligned(x, 1024, offset); // <- check returned pointer accounting for the offest
+ }
+
+ void process(char *data, int width) {
+ #pragma omp for simd aligned(data : 1024) // <- aligned clause will be checked.
+ for (int x = 0; x < width; x++)
+ data[x] *= data[x];
+ }
Core Analysis Improvements
==========================
@@ -337,7 +388,7 @@ Additional Information
======================
A wide variety of additional information is available on the `Clang web
-page <http://clang.llvm.org/>`_. The web page contains versions of the
+page <https://clang.llvm.org/>`_. The web page contains versions of the
API documentation which are up-to-date with the Subversion version of
the source code. You can access versions of these documents specific to
this release by going into the "``clang/docs/``" directory in the Clang
@@ -345,4 +396,4 @@ tree.
If you have any questions or comments about Clang, please feel free to
contact us via the `mailing
-list <http://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
+list <https://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
diff --git a/docs/SanitizerCoverage.rst b/docs/SanitizerCoverage.rst
index e1c3fc91d32c..f3f13c831760 100644
--- a/docs/SanitizerCoverage.rst
+++ b/docs/SanitizerCoverage.rst
@@ -245,7 +245,7 @@ around comparison instructions and switch statements.
Similarly, with ``-fsanitize-coverage=trace-div`` the compiler will instrument
integer division instructions (to capture the right argument of division)
and with ``-fsanitize-coverage=trace-gep`` --
-the `LLVM GEP instructions <http://llvm.org/docs/GetElementPtr.html>`_
+the `LLVM GEP instructions <https://llvm.org/docs/GetElementPtr.html>`_
(to capture array indices).
.. code-block:: c++
diff --git a/docs/SourceBasedCodeCoverage.rst b/docs/SourceBasedCodeCoverage.rst
index 805c98794804..27a1950a1602 100644
--- a/docs/SourceBasedCodeCoverage.rst
+++ b/docs/SourceBasedCodeCoverage.rst
@@ -156,7 +156,7 @@ line-oriented report, try:
The ``llvm-cov`` tool supports specifying a custom demangler, writing out
reports in a directory structure, and generating html reports. For the full
list of options, please refer to the `command guide
-<http://llvm.org/docs/CommandGuide/llvm-cov.html>`_.
+<https://llvm.org/docs/CommandGuide/llvm-cov.html>`_.
A few final notes:
diff --git a/docs/ThinLTO.rst b/docs/ThinLTO.rst
index 38873f464c29..6e6cb801f522 100644
--- a/docs/ThinLTO.rst
+++ b/docs/ThinLTO.rst
@@ -47,7 +47,7 @@ The 3.9 release of clang includes ThinLTO support. However, ThinLTO
is under active development, and new features, improvements and bugfixes
are being added for the next release. For the latest ThinLTO support,
`build a recent version of clang and LLVM
-<http://llvm.org/docs/CMake.html>`_.
+<https://llvm.org/docs/CMake.html>`_.
Linkers
-------
@@ -59,7 +59,7 @@ ThinLTO is currently supported for the following linkers:
- **gold (via the gold-plugin)**:
Similar to monolithic LTO, this requires using
a `gold linker configured with plugins enabled
- <http://llvm.org/docs/GoldPlugin.html>`_.
+ <https://llvm.org/docs/GoldPlugin.html>`_.
- **ld64**:
Starting with `Xcode 8 <https://developer.apple.com/xcode/>`_.
- **lld**:
@@ -99,13 +99,15 @@ With gold, if you see an error during the link of the form:
Then either gold was not configured with plugins enabled, or clang
was not built with ``-DLLVM_BINUTILS_INCDIR`` set properly. See
the instructions for the
-`LLVM gold plugin <http://llvm.org/docs/GoldPlugin.html#how-to-build-it>`_.
+`LLVM gold plugin <https://llvm.org/docs/GoldPlugin.html#how-to-build-it>`_.
Controlling Backend Parallelism
-------------------------------
.. _parallelism:
-By default, the ThinLTO link step will launch up to
+By default, the ThinLTO link step will launch as many
+threads in parallel as there are cores. If the number of
+cores can't be computed for the architecture, then it will launch
``std::thread::hardware_concurrency`` number of threads in parallel.
For machines with hyper-threading, this is the total number of
virtual cores. For some applications and machine configurations this
@@ -196,9 +198,9 @@ To bootstrap clang/LLVM with ThinLTO, follow these steps:
1. The host compiler_ must be a version of clang that supports ThinLTO.
#. The host linker_ must support ThinLTO (and in the case of gold, must be
- `configured with plugins enabled <http://llvm.org/docs/GoldPlugin.html>`_.
+ `configured with plugins enabled <https://llvm.org/docs/GoldPlugin.html>`_.
#. Use the following additional `CMake variables
- <http://llvm.org/docs/CMake.html#options-and-variables>`_
+ <https://llvm.org/docs/CMake.html#options-and-variables>`_
when configuring the bootstrap compiler build:
* ``-DLLVM_ENABLE_LTO=Thin``
diff --git a/docs/ThreadSanitizer.rst b/docs/ThreadSanitizer.rst
index d1e2c65ec5f1..0d039bd5b25a 100644
--- a/docs/ThreadSanitizer.rst
+++ b/docs/ThreadSanitizer.rst
@@ -12,7 +12,7 @@ ThreadSanitizer is about **5x-10x**.
How to build
------------
-Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
+Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.
Supported Platforms
-------------------
diff --git a/docs/Toolchain.rst b/docs/Toolchain.rst
index 06bde35c3da6..3540708a382c 100644
--- a/docs/Toolchain.rst
+++ b/docs/Toolchain.rst
@@ -100,14 +100,14 @@ currently-supported languages are:
In each case, GCC will be invoked to compile the input.
-Assember
---------
+Assembler
+---------
Clang can either use LLVM's integrated assembler or an external system-specific
tool (for instance, the GNU Assembler on GNU OSes) to produce machine code from
assembly.
By default, Clang uses LLVM's integrated assembler on all targets where it is
-supported. If you wish to use the system assember instead, use the
+supported. If you wish to use the system assembler instead, use the
``-fno-integrated-as`` option.
Linker
@@ -121,7 +121,7 @@ Clang can be configured to use one of several different linkers:
* MSVC's link.exe
Link-time optimization is natively supported by lld, and supported via
-a `linker plugin <http://llvm.org/docs/GoldPlugin.html>`_ when using gold.
+a `linker plugin <https://llvm.org/docs/GoldPlugin.html>`_ when using gold.
The default linker varies between targets, and can be overridden via the
``-fuse-ld=<linker name>`` flag.
@@ -233,7 +233,7 @@ LLVM's unwinder library can be obtained from subversion:
.. code-block:: console
- llvm-src$ svn co http://llvm.org/svn/llvm-project/libunwind/trunk projects/libunwind
+ llvm-src$ svn co https://llvm.org/svn/llvm-project/libunwind/trunk projects/libunwind
When checked out into projects/libunwind within an LLVM checkout,
it should be automatically picked up by the LLVM build system.
diff --git a/docs/Tooling.rst b/docs/Tooling.rst
index 25ee21589022..141d4d8d8959 100644
--- a/docs/Tooling.rst
+++ b/docs/Tooling.rst
@@ -9,7 +9,7 @@ the different ways to write clang tools, and their pros and cons.
LibClang
--------
-`LibClang <http://clang.llvm.org/doxygen/group__CINDEX.html>`_ is a stable high
+`LibClang <https://clang.llvm.org/doxygen/group__CINDEX.html>`_ is a stable high
level C interface to clang. When in doubt LibClang is probably the interface
you want to use. Consider the other interfaces only when you have a good
reason not to use LibClang.
diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst
index 86d0193a23c2..3700d4962d36 100644
--- a/docs/UndefinedBehaviorSanitizer.rst
+++ b/docs/UndefinedBehaviorSanitizer.rst
@@ -25,7 +25,7 @@ The checks have small runtime cost and no impact on address space layout or ABI.
How to build
============
-Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
+Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.
Usage
=====
@@ -72,7 +72,7 @@ Available checks
Available checks are:
- ``-fsanitize=alignment``: Use of a misaligned pointer or creation
- of a misaligned reference.
+ of a misaligned reference. Also sanitizes assume_aligned-like attributes.
- ``-fsanitize=bool``: Load of a ``bool`` value which is neither
``true`` nor ``false``.
- ``-fsanitize=builtin``: Passing invalid values to compiler builtins.
@@ -89,10 +89,21 @@ Available checks are:
- ``-fsanitize=function``: Indirect call of a function through a
function pointer of the wrong type (Darwin/Linux, C++ and x86/x86_64
only).
- - ``-fsanitize=implicit-integer-truncation``: Implicit conversion from
+ - ``-fsanitize=implicit-unsigned-integer-truncation``,
+ ``-fsanitize=implicit-signed-integer-truncation``: Implicit conversion from
integer of larger bit width to smaller bit width, if that results in data
loss. That is, if the demoted value, after casting back to the original
width, is not equal to the original value before the downcast.
+ The ``-fsanitize=implicit-unsigned-integer-truncation`` handles conversions
+ between two ``unsigned`` types, while
+ ``-fsanitize=implicit-signed-integer-truncation`` handles the rest of the
+ conversions - when either one, or both of the types are signed.
+ Issues caught by these sanitizers are not undefined behavior,
+ but are often unintentional.
+ - ``-fsanitize=implicit-integer-sign-change``: Implicit conversion between
+ integer types, if that changes the sign of the value. That is, if the the
+ original value was negative and the new value is positive (or zero),
+ or the original value was positive, and the new value is negative.
Issues caught by this sanitizer are not undefined behavior,
but are often unintentional.
- ``-fsanitize=integer-divide-by-zero``: Integer division by zero.
@@ -156,13 +167,24 @@ You can also use the following check groups:
``nullability-*`` group of checks.
- ``-fsanitize=undefined-trap``: Deprecated alias of
``-fsanitize=undefined``.
+ - ``-fsanitize=implicit-integer-truncation``: Catches lossy integral
+ conversions. Enables ``implicit-signed-integer-truncation`` and
+ ``implicit-unsigned-integer-truncation``.
+ - ``-fsanitize=implicit-integer-arithmetic-value-change``: Catches implicit
+ conversions that change the arithmetic value of the integer. Enables
+ ``implicit-signed-integer-truncation`` and ``implicit-integer-sign-change``.
+ - ``-fsanitize=implicit-conversion``: Checks for suspicious
+ behaviour of implicit conversions. Enables
+ ``implicit-unsigned-integer-truncation``,
+ ``implicit-signed-integer-truncation`` and
+ ``implicit-integer-sign-change``.
- ``-fsanitize=integer``: Checks for undefined or suspicious integer
behavior (e.g. unsigned integer overflow).
Enables ``signed-integer-overflow``, ``unsigned-integer-overflow``,
- ``shift``, ``integer-divide-by-zero``, and ``implicit-integer-truncation``.
- - ``-fsanitize=implicit-conversion``: Checks for suspicious behaviours of
- implicit conversions.
- Currently, only ``-fsanitize=implicit-integer-truncation`` is implemented.
+ ``shift``, ``integer-divide-by-zero``,
+ ``implicit-unsigned-integer-truncation``,
+ ``implicit-signed-integer-truncation`` and
+ ``implicit-integer-sign-change``.
- ``-fsanitize=nullability``: Enables ``nullability-arg``,
``nullability-assign``, and ``nullability-return``. While violating
nullability does not have undefined behavior, it is often unintentional,
@@ -266,7 +288,7 @@ There are several limitations:
Supported Platforms
===================
-UndefinedBehaviorSanitizer is supported on the following OS:
+UndefinedBehaviorSanitizer is supported on the following operating systems:
* Android
* Linux
@@ -274,6 +296,11 @@ UndefinedBehaviorSanitizer is supported on the following OS:
* FreeBSD
* OpenBSD
* OS X 10.6 onwards
+* Windows
+
+The runtime library is relatively portable and platform independent. If the OS
+you need is not listed above, UndefinedBehaviorSanitizer may already work for
+it, or could be made to work with a minor porting effort.
Current Status
==============
@@ -296,6 +323,7 @@ Example
-------
For a file called ``/code/library/file.cpp``, here is what would be emitted:
+
* Default (No flag, or ``-fsanitize-undefined-strip-path-components=0``): ``/code/library/file.cpp``
* ``-fsanitize-undefined-strip-path-components=1``: ``code/library/file.cpp``
* ``-fsanitize-undefined-strip-path-components=2``: ``library/file.cpp``
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 363bb4e461a6..7634d24eb5a6 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -22,7 +22,7 @@ This document describes important notes about using Clang as a compiler
for an end-user, documenting the supported features, command line
options, etc. If you are interested in using Clang to build a tool that
processes code, please see :doc:`InternalsManual`. If you are interested in the
-`Clang Static Analyzer <http://clang-analyzer.llvm.org>`_, please see its web
+`Clang Static Analyzer <https://clang-analyzer.llvm.org>`_, please see its web
page.
Clang is one component in a complete toolchain for C family languages.
@@ -587,7 +587,7 @@ Options to Control Clang Crash Diagnostics
As unbelievable as it may sound, Clang does crash from time to time.
Generally, this only occurs to those living on the `bleeding
-edge <http://llvm.org/releases/download.html#svn>`_. Clang goes to great
+edge <https://llvm.org/releases/download.html#svn>`_. Clang goes to great
lengths to assist you in filing a bug report. Specifically, Clang
generates preprocessed source file(s) and associated run script(s) upon
a crash. These files should be attached to a bug report to ease
@@ -982,11 +982,11 @@ Controlling Static Analyzer Diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
While not strictly part of the compiler, the diagnostics from Clang's
-`static analyzer <http://clang-analyzer.llvm.org>`_ can also be
+`static analyzer <https://clang-analyzer.llvm.org>`_ can also be
influenced by the user via changes to the source code. See the available
-`annotations <http://clang-analyzer.llvm.org/annotations.html>`_ and the
+`annotations <https://clang-analyzer.llvm.org/annotations.html>`_ and the
analyzer's `FAQ
-page <http://clang-analyzer.llvm.org/faq.html#exclude_code>`_ for more
+page <https://clang-analyzer.llvm.org/faq.html#exclude_code>`_ for more
information.
.. _usersmanual-precompiled-headers:
@@ -1799,6 +1799,127 @@ In these cases, you can use the flag ``-fno-profile-instr-generate`` (or
Note that these flags should appear after the corresponding profile
flags to have an effect.
+Profile remapping
+^^^^^^^^^^^^^^^^^
+
+When the program is compiled after a change that affects many symbol names,
+pre-existing profile data may no longer match the program. For example:
+
+ * switching from libstdc++ to libc++ will result in the mangled names of all
+ functions taking standard library types to change
+ * renaming a widely-used type in C++ will result in the mangled names of all
+ functions that have parameters involving that type to change
+ * moving from a 32-bit compilation to a 64-bit compilation may change the
+ underlying type of ``size_t`` and similar types, resulting in changes to
+ manglings
+
+Clang allows use of a profile remapping file to specify that such differences
+in mangled names should be ignored when matching the profile data against the
+program.
+
+.. option:: -fprofile-remapping-file=<file>
+
+ Specifies a file containing profile remapping information, that will be
+ used to match mangled names in the profile data to mangled names in the
+ program.
+
+The profile remapping file is a text file containing lines of the form
+
+.. code-block:: text
+
+ fragmentkind fragment1 fragment2
+
+where ``fragmentkind`` is one of ``name``, ``type``, or ``encoding``,
+indicating whether the following mangled name fragments are
+<`name <http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.name>`_>s,
+<`type <http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.type>`_>s, or
+<`encoding <http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.encoding>`_>s,
+respectively.
+Blank lines and lines starting with ``#`` are ignored.
+
+For convenience, built-in <substitution>s such as ``St`` and ``Ss``
+are accepted as <name>s (even though they technically are not <name>s).
+
+For example, to specify that ``absl::string_view`` and ``std::string_view``
+should be treated as equivalent when matching profile data, the following
+remapping file could be used:
+
+.. code-block:: text
+
+ # absl::string_view is considered equivalent to std::string_view
+ type N4absl11string_viewE St17basic_string_viewIcSt11char_traitsIcEE
+
+ # std:: might be std::__1:: in libc++ or std::__cxx11:: in libstdc++
+ name 3std St3__1
+ name 3std St7__cxx11
+
+Matching profile data using a profile remapping file is supported on a
+best-effort basis. For example, information regarding indirect call targets is
+currently not remapped. For best results, you are encouraged to generate new
+profile data matching the updated program, or to remap the profile data
+using the ``llvm-cxxmap`` and ``llvm-profdata merge`` tools.
+
+.. note::
+
+ Profile data remapping support is currently only implemented for LLVM's
+ new pass manager, which can be enabled with
+ ``-fexperimental-new-pass-manager``.
+
+.. note::
+
+ Profile data remapping is currently only supported for C++ mangled names
+ following the Itanium C++ ABI mangling scheme. This covers all C++ targets
+ supported by Clang other than Windows.
+
+GCOV-based Profiling
+--------------------
+
+GCOV is a test coverage program, it helps to know how often a line of code
+is executed. When instrumenting the code with ``--coverage`` option, some
+counters are added for each edge linking basic blocks.
+
+At compile time, gcno files are generated containing information about
+blocks and edges between them. At runtime the counters are incremented and at
+exit the counters are dumped in gcda files.
+
+The tool ``llvm-cov gcov`` will parse gcno, gcda and source files to generate
+a report ``.c.gcov``.
+
+.. option:: -fprofile-filter-files=[regexes]
+
+ Define a list of regexes separated by a semi-colon.
+ If a file name matches any of the regexes then the file is instrumented.
+
+ .. code-block:: console
+
+ $ clang --coverage -fprofile-filter-files=".*\.c$" foo.c
+
+ For example, this will only instrument files finishing with ``.c``, skipping ``.h`` files.
+
+.. option:: -fprofile-exclude-files=[regexes]
+
+ Define a list of regexes separated by a semi-colon.
+ If a file name doesn't match all the regexes then the file is instrumented.
+
+ .. code-block:: console
+
+ $ clang --coverage -fprofile-exclude-files="^/usr/include/.*$" foo.c
+
+ For example, this will instrument all the files except the ones in ``/usr/include``.
+
+If both options are used then a file is instrumented if its name matches any
+of the regexes from ``-fprofile-filter-list`` and doesn't match all the regexes
+from ``-fprofile-exclude-list``.
+
+.. code-block:: console
+
+ $ clang --coverage -fprofile-exclude-files="^/usr/include/.*$" \
+ -fprofile-filter-files="^/usr/.*$"
+
+In that case ``/usr/foo/oof.h`` is instrumented since it matches the filter regex and
+doesn't match the exclude regex, but ``/usr/include/foo.h`` doesn't since it matches
+the exclude regex.
+
Controlling Debug Information
-----------------------------
@@ -2086,7 +2207,7 @@ comment(lib)`` are well supported.
clang has a ``-fms-compatibility`` flag that makes clang accept enough
invalid C++ to be able to parse most Microsoft headers. For example, it
allows `unqualified lookup of dependent base class members
-<http://clang.llvm.org/compatibility.html#dep_lookup_bases>`_, which is
+<https://clang.llvm.org/compatibility.html#dep_lookup_bases>`_, which is
a common compatibility issue with clang. This flag is enabled by default
for Windows targets.
@@ -2711,16 +2832,17 @@ Command Prompt or a regular Command Prompt where the environment has been set
up using e.g. `vcvarsall.bat <http://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx>`_.
clang-cl can also be used from inside Visual Studio by selecting the LLVM
-Platform Toolset. The toolset is installed by the LLVM installer, which can be
-downloaded from the `LLVM release <http://releases.llvm.org/download.html>`_ or
-`snapshot build <http://llvm.org/builds/>`_ web pages. To use the toolset,
-select a project in Solution Explorer, open its Property Page (Alt+F7), and in
-the "General" section of "Configuration Properties" change "Platform Toolset"
-to e.g. LLVM-vs2014.
+Platform Toolset. The toolset is not part of the installer, but may be installed
+separately from the
+`Visual Studio Marketplace <https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.llvm-toolchain>`_.
+To use the toolset, select a project in Solution Explorer, open its Property
+Page (Alt+F7), and in the "General" section of "Configuration Properties"
+change "Platform Toolset" to LLVM. Doing so enables an additional Property
+Page for selecting the clang-cl executable to use for builds.
To use the toolset with MSBuild directly, invoke it with e.g.
-``/p:PlatformToolset=LLVM-vs2014``. This allows trying out the clang-cl
-toolchain without modifying your project files.
+``/p:PlatformToolset=LLVM``. This allows trying out the clang-cl toolchain
+without modifying your project files.
It's also possible to point MSBuild at clang-cl without changing toolset by
passing ``/p:CLToolPath=c:\llvm\bin /p:CLToolExe=clang-cl.exe``.
@@ -2729,7 +2851,7 @@ When using CMake and the Visual Studio generators, the toolset can be set with t
::
- cmake -G"Visual Studio 15 2017" -T LLVM-vs2014 ..
+ cmake -G"Visual Studio 15 2017" -T LLVM ..
When using CMake with the Ninja generator, set the ``CMAKE_C_COMPILER`` and
``CMAKE_CXX_COMPILER`` variables to clang-cl:
@@ -2776,6 +2898,7 @@ Execute ``clang-cl /?`` to see a list of supported options:
/arch:<value> Set architecture for code generation
/Brepro- Emit an object file which cannot be reproduced over time
/Brepro Emit an object file which can be reproduced over time
+ /clang:<arg> Pass <arg> to the clang driver
/C Don't discard comments when preprocessing
/c Compile only
/d1PP Retain macro definitions in /E mode
@@ -2805,20 +2928,23 @@ Execute ``clang-cl /?`` to see a list of supported options:
/GA Assume thread-local variables are defined in the executable
/Gd Set __cdecl as a default calling convention
/GF- Disable string pooling
+ /GF Enable string pooling (default)
/GR- Disable emission of RTTI data
/Gregcall Set __regcall as a default calling convention
/GR Enable emission of RTTI data
/Gr Set __fastcall as a default calling convention
/GS- Disable buffer security check
- /GS Enable buffer security check
- /Gs<value> Set stack probe size
- /guard:<value> Enable Control Flow Guard with /guard:cf
+ /GS Enable buffer security check (default)
+ /Gs Use stack probes (default)
+ /Gs<value> Set stack probe size (default 4096)
+ /guard:<value> Enable Control Flow Guard with /guard:cf,
+ or only the table with /guard:cf,nochecks
/Gv Set __vectorcall as a default calling convention
/Gw- Don't put each data item in its own section
/Gw Put each data item in its own section
/GX- Disable exception handling
/GX Enable exception handling
- /Gy- Don't put each function in its own section
+ /Gy- Don't put each function in its own section (default)
/Gy Put each function in its own section
/Gz Set __stdcall as a default calling convention
/help Display available options
@@ -2832,16 +2958,28 @@ Execute ``clang-cl /?`` to see a list of supported options:
/MD Use DLL run-time
/MTd Use static debug run-time
/MT Use static run-time
+ /O0 Disable optimization
+ /O1 Optimize for size (same as /Og /Os /Oy /Ob2 /GF /Gy)
+ /O2 Optimize for speed (same as /Og /Oi /Ot /Oy /Ob2 /GF /Gy)
+ /Ob0 Disable function inlining
+ /Ob1 Only inline functions which are (explicitly or implicitly) marked inline
+ /Ob2 Inline functions as deemed beneficial by the compiler
/Od Disable optimization
+ /Og No effect
/Oi- Disable use of builtin functions
/Oi Enable use of builtin functions
/Os Optimize for size
/Ot Optimize for speed
- /O<value> Optimization level
+ /Ox Deprecated (same as /Og /Oi /Ot /Oy /Ob2); use /O2 instead
+ /Oy- Disable frame pointer omission (x86 only, default)
+ /Oy Enable frame pointer omission (x86 only)
+ /O<flags> Set multiple /O flags at once; e.g. '/O2y-' for '/O2 /Oy-'
/o <file or directory> Set output file or directory (ends in / or \)
/P Preprocess to file
/Qvec- Disable the loop vectorization passes
/Qvec Enable the loop vectorization passes
+ /showFilenames- Don't print the name of each compiled file (default)
+ /showFilenames Print the name of each compiled file
/showIncludes Print info about included files to stderr
/source-charset:<value> Source encoding, supports only UTF-8
/std:<value> Language standard to compile for
@@ -2873,6 +3011,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
/Yc<filename> Generate a pch file for all code up to and including <filename>
/Yu<filename> Load a pch file and use it instead of all code up to and including <filename>
/Z7 Enable CodeView debug information in object files
+ /Zc:dllexportInlines- Don't dllexport/dllimport inline member functions of dllexport/import classes
+ /Zc:dllexportInlines dllexport/dllimport inline member functions of dllexport/import classes (default)
/Zc:sizedDealloc- Disable C++14 sized global deallocation functions
/Zc:sizedDealloc Enable C++14 sized global deallocation functions
/Zc:strictStrings Treat string literals as const
@@ -2924,13 +3064,16 @@ Execute ``clang-cl /?`` to see a list of supported options:
-fno-complete-member-pointers
Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI
-fno-coverage-mapping Disable code coverage analysis
+ -fno-crash-diagnostics Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash
-fno-debug-macro Do not emit macro debug information
-fno-delayed-template-parsing
Disable delayed template parsing
- -fno-sanitize-address-poison-class-member-array-new-cookie
- Disable poisoning array cookies when using class member operator new[] in AddressSanitizer
+ -fno-sanitize-address-poison-custom-array-cookie
+ Disable poisoning array cookies when using custom operator new[] in AddressSanitizer
-fno-sanitize-address-use-after-scope
Disable use-after-scope detection in AddressSanitizer
+ -fno-sanitize-address-use-odr-indicator
+ Disable ODR indicator globals
-fno-sanitize-blacklist Don't use blacklist file for sanitizers
-fno-sanitize-cfi-cross-dso
Disable control flow integrity (CFI) checks for cross-DSO calls.
@@ -2952,6 +3095,11 @@ Execute ``clang-cl /?`` to see a list of supported options:
-fno-sanitize-trap=<value>
Disable trapping for specified sanitizers
-fno-standalone-debug Limit debug information produced to reduce size of debug binary
+ -fobjc-runtime=<value> Specify the target Objective-C runtime kind and version
+ -fprofile-exclude-files=<value>
+ Instrument only functions from files where names don't match all the regexes separated by a semi-colon
+ -fprofile-filter-files=<value>
+ Instrument only functions from files where names match any regex separated by a semi-colon
-fprofile-instr-generate=<file>
Generate instrumented code to collect execution counts into <file>
(overridden by LLVM_PROFILE_FILE env var)
@@ -2960,14 +3108,18 @@ Execute ``clang-cl /?`` to see a list of supported options:
(overridden by '=' form of option or LLVM_PROFILE_FILE env var)
-fprofile-instr-use=<value>
Use instrumentation data for profile-guided optimization
+ -fprofile-remapping-file=<file>
+ Use the remappings described in <file> to match the profile data against names in the program
-fsanitize-address-field-padding=<value>
Level of field padding for AddressSanitizer
-fsanitize-address-globals-dead-stripping
Enable linker dead stripping of globals in AddressSanitizer
- -fsanitize-address-poison-class-member-array-new-cookie
- Enable poisoning array cookies when using class member operator new[] in AddressSanitizer
+ -fsanitize-address-poison-custom-array-cookie
+ Enable poisoning array cookies when using custom operator new[] in AddressSanitizer
-fsanitize-address-use-after-scope
Enable use-after-scope detection in AddressSanitizer
+ -fsanitize-address-use-odr-indicator
+ Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size
-fsanitize-blacklist=<value>
Path to blacklist file for sanitizers
-fsanitize-cfi-cross-dso
@@ -2976,6 +3128,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
Generalize pointers in CFI indirect call type signature checks
-fsanitize-coverage=<value>
Specify the type of coverage instrumentation for Sanitizers
+ -fsanitize-hwaddress-abi=<value>
+ Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor)
-fsanitize-memory-track-origins=<value>
Enable origins tracking in MemorySanitizer
-fsanitize-memory-track-origins
@@ -2996,9 +3150,12 @@ Execute ``clang-cl /?`` to see a list of supported options:
Strip (or keep only, if negative) a given number of path components when emitting check metadata.
-fsanitize=<check> Turn on runtime checks for various forms of undefined or suspicious
behavior. See user manual for available checks
+ -fsplit-lto-unit Enables splitting of the LTO unit.
-fstandalone-debug Emit full debug info for all types used by the program
-fwhole-program-vtables Enables whole-program vtable optimization. Requires -flto
+ -gcodeview-ghash Emit type record hashes in a .debug$H section
-gcodeview Generate CodeView debug information
+ -gline-directives-only Emit debug line info directives only
-gline-tables-only Emit debug line number tables only
-miamcu Use Intel MCU ABI
-mllvm <value> Additional arguments to forward to LLVM's option processing
@@ -3011,6 +3168,92 @@ Execute ``clang-cl /?`` to see a list of supported options:
-W<warning> Enable the specified warning
-Xclang <arg> Pass <arg> to the clang compiler
+The /clang: Option
+^^^^^^^^^^^^^^^^^^
+
+When clang-cl is run with a set of ``/clang:<arg>`` options, it will gather all
+of the ``<arg>`` arguments and process them as if they were passed to the clang
+driver. This mechanism allows you to pass flags that are not exposed in the
+clang-cl options or flags that have a different meaning when passed to the clang
+driver. Regardless of where they appear in the command line, the ``/clang:``
+arguments are treated as if they were passed at the end of the clang-cl command
+line.
+
+The /Zc:dllexportInlines- Option
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This causes the class-level `dllexport` and `dllimport` attributes to not apply
+to inline member functions, as they otherwise would. For example, in the code
+below `S::foo()` would normally be defined and exported by the DLL, but when
+using the ``/Zc:dllexportInlines-`` flag it is not:
+
+.. code-block:: c
+
+ struct __declspec(dllexport) S {
+ void foo() {}
+ }
+
+This has the benefit that the compiler doesn't need to emit a definition of
+`S::foo()` in every translation unit where the declaration is included, as it
+would otherwise do to ensure there's a definition in the DLL even if it's not
+used there. If the declaration occurs in a header file that's widely used, this
+can save significant compilation time and output size. It also reduces the
+number of functions exported by the DLL similarly to what
+``-fvisibility-inlines-hidden`` does for shared objects on ELF and Mach-O.
+Since the function declaration comes with an inline definition, users of the
+library can use that definition directly instead of importing it from the DLL.
+
+Note that the Microsoft Visual C++ compiler does not support this option, and
+if code in a DLL is compiled with ``/Zc:dllexportInlines-``, the code using the
+DLL must be compiled in the same way so that it doesn't attempt to dllimport
+the inline member functions. The reverse scenario should generally work though:
+a DLL compiled without this flag (such as a system library compiled with Visual
+C++) can be referenced from code compiled using the flag, meaning that the
+referencing code will use the inline definitions instead of importing them from
+the DLL.
+
+Also note that like when using ``-fvisibility-inlines-hidden``, the address of
+`S::foo()` will be different inside and outside the DLL, breaking the C/C++
+standard requirement that functions have a unique address.
+
+The flag does not apply to explicit class template instantiation definitions or
+declarations, as those are typically used to explicitly provide a single
+definition in a DLL, (dllexported instantiation definition) or to signal that
+the definition is available elsewhere (dllimport instantiation declaration). It
+also doesn't apply to inline members with static local variables, to ensure
+that the same instance of the variable is used inside and outside the DLL.
+
+Using this flag can cause problems when inline functions that would otherwise
+be dllexported refer to internal symbols of a DLL. For example:
+
+.. code-block:: c
+
+ void internal();
+
+ struct __declspec(dllimport) S {
+ void foo() { internal(); }
+ }
+
+Normally, references to `S::foo()` would use the definition in the DLL from
+which it was exported, and which presumably also has the definition of
+`internal()`. However, when using ``/Zc:dllexportInlines-``, the inline
+definition of `S::foo()` is used directly, resulting in a link error since
+`internal()` is not available. Even worse, if there is an inline definition of
+`internal()` containing a static local variable, we will now refer to a
+different instance of that variable than in the DLL:
+
+.. code-block:: c
+
+ inline int internal() { static int x; return x++; }
+
+ struct __declspec(dllimport) S {
+ int foo() { return internal(); }
+ }
+
+This could lead to very subtle bugs. Using ``-fvisibility-inlines-hidden`` can
+lead to the same issue. To avoid it in this case, make `S::foo()` or
+`internal()` non-inline, or mark them `dllimport/dllexport` explicitly.
+
The /fallback Option
^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/analyzer/DebugChecks.rst b/docs/analyzer/DebugChecks.rst
index 67521b82cabc..bb2f37f33955 100644
--- a/docs/analyzer/DebugChecks.rst
+++ b/docs/analyzer/DebugChecks.rst
@@ -30,9 +30,12 @@ using a 'dot' format viewer (such as Graphviz on OS X) instead.
- debug.DumpLiveVars: Show the results of live variable analysis for each
top-level function being analyzed.
+- debug.DumpLiveStmts: Show the results of live statement analysis for each
+ top-level function being analyzed.
+
- debug.ViewExplodedGraph: Show the Exploded Graphs generated for the
analysis of different functions in the input translation unit. When there
- are several functions analyzed, display one graph per function. Beware
+ are several functions analyzed, display one graph per function. Beware
that these graphs may grow very large, even for small functions.
Path Tracking
@@ -255,6 +258,23 @@ ExprInspection checks
clang_analyzer_hashDump(x); // expected-warning{{hashed string for x}}
}
+- ``void clang_analyzer_denote(int, const char *);``
+
+ Denotes symbols with strings. A subsequent call to clang_analyzer_express()
+ will expresses another symbol in terms of these string. Useful for testing
+ relationships between different symbols.
+
+ Example usage::
+
+ void foo(int x) {
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(x + 1); // expected-warning{{$x + 1}}
+ }
+
+- ``void clang_analyzer_express(int);``
+
+ See clang_analyzer_denote().
+
Statistics
==========
diff --git a/docs/analyzer/RegionStore.txt b/docs/analyzer/RegionStore.txt
index 5d37cf7bed99..ef994b6401e2 100644
--- a/docs/analyzer/RegionStore.txt
+++ b/docs/analyzer/RegionStore.txt
@@ -118,7 +118,7 @@ sometimes zero, for static data, or "uninitialized", for stack variables).
int manyInts[10];
manyInts[1] = 42; // Creates a Direct binding for manyInts[1].
print(manyInts[1]); // Retrieves the Direct binding for manyInts[1];
- print(manyInts[0]); // There is no Direct binding for manyInts[1].
+ print(manyInts[0]); // There is no Direct binding for manyInts[0].
// Is there a Default binding for the entire array?
// There is not, but it is a stack variable, so we use
// "uninitialized" as the default value (and emit a
@@ -166,6 +166,6 @@ Here's a concrete example:
return p2.x; // The binding for FieldRegion 'p2.x' is requested.
// There is no Direct binding, so we look for a Default
// binding to 'p2' and find the LCV.
- // Because it's an LCV, we look at our requested region
+ // Because it's a LCV, we look at our requested region
// and see that it's the '.x' field. We ask for the value
// of 'p.x' within the snapshot, and get back 42.
diff --git a/docs/conf.py b/docs/conf.py
index b38c93af23c2..19113d0d5a70 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -11,6 +11,7 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
+from __future__ import absolute_import, division, print_function
import sys, os
from datetime import date
@@ -49,9 +50,9 @@ copyright = u'2007-%d, The Clang Team' % date.today().year
# built documents.
#
# The short version.
-version = '7'
+version = '8'
# The full version, including alpha/beta/rc tags.
-release = '7'
+release = '8'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -233,14 +234,14 @@ for name in os.listdir(command_guide_path):
header = f.readline().rstrip('\n')
if len(header) != len(title):
- print >>sys.stderr, (
+ print((
"error: invalid header in %r (does not match title)" % (
- file_subpath,))
+ file_subpath,)), file=sys.stderr)
if ' - ' not in title:
- print >>sys.stderr, (
+ print((
("error: invalid title in %r "
"(expected '<name> - <description>')") % (
- file_subpath,))
+ file_subpath,)), file=sys.stderr)
# Split the name out of the title.
name,description = title.split(' - ', 1)
diff --git a/docs/index.rst b/docs/index.rst
index be7a371cd711..3eb1d160c756 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -83,7 +83,6 @@ Design Documents
InternalsManual
DriverInternals
- PTHInternals
PCHInternals
ItaniumMangleAbiTags
HardwareAssistedAddressSanitizerDesign.rst
diff --git a/docs/tools/dump_ast_matchers.py b/docs/tools/dump_ast_matchers.py
index d38977548fd9..c96c1ca27acb 100644
--- a/docs/tools/dump_ast_matchers.py
+++ b/docs/tools/dump_ast_matchers.py
@@ -5,7 +5,10 @@
import collections
import re
-import urllib2
+try:
+ from urllib.request import urlopen
+except ImportError:
+ from urllib2 import urlopen
MATCHERS_FILE = '../../include/clang/ASTMatchers/ASTMatchers.h'
@@ -38,11 +41,11 @@ def esc(text):
text = re.sub(r'>', '&gt;', text)
def link_if_exists(m):
name = m.group(1)
- url = 'http://clang.llvm.org/doxygen/classclang_1_1%s.html' % name
+ url = 'https://clang.llvm.org/doxygen/classclang_1_1%s.html' % name
if url not in doxygen_probes:
try:
- print 'Probing %s...' % url
- urllib2.urlopen(url)
+ print('Probing %s...' % url)
+ urlopen(url)
doxygen_probes[url] = True
except:
doxygen_probes[url] = False
@@ -181,9 +184,9 @@ def act_on_decl(declaration, comment, allowed_types):
raise Exception('Inconsistent documentation for: %s' % name)
for result_type in result_types:
add_matcher(result_type, name, 'Matcher<Type>', comment)
- if loc:
- add_matcher('%sLoc' % result_type, '%sLoc' % name, 'Matcher<TypeLoc>',
- comment)
+ # if loc:
+ # add_matcher('%sLoc' % result_type, '%sLoc' % name, 'Matcher<TypeLoc>',
+ # comment)
return
m = re.match(r"""^\s*AST_POLYMORPHIC_MATCHER(_P)?(.?)(?:_OVERLOAD)?\(
@@ -307,14 +310,14 @@ def act_on_decl(declaration, comment, allowed_types):
if not result_types:
if not comment:
# Only overloads don't have their own doxygen comments; ignore those.
- print 'Ignoring "%s"' % name
+ print('Ignoring "%s"' % name)
else:
- print 'Cannot determine result type for "%s"' % name
+ print('Cannot determine result type for "%s"' % name)
else:
for result_type in result_types:
add_matcher(result_type, name, args, comment)
else:
- print '*** Unparsable: "' + declaration + '" ***'
+ print('*** Unparsable: "' + declaration + '" ***')
def sort_table(matcher_type, matcher_map):
"""Returns the sorted html table for the given row map."""
@@ -354,7 +357,7 @@ for line in open(MATCHERS_FILE).read().splitlines():
allowed_types += [m.group(1)]
continue
if line.strip() and line.lstrip()[0] == '/':
- comment += re.sub(r'/+\s?', '', line) + '\n'
+ comment += re.sub(r'^/+\s?', '', line) + '\n'
else:
declaration += ' ' + line
if ((not line.strip()) or
diff --git a/docs/tools/dump_format_style.py b/docs/tools/dump_format_style.py
index 3d61227f7361..5feb793a4d70 100644
--- a/docs/tools/dump_format_style.py
+++ b/docs/tools/dump_format_style.py
@@ -6,7 +6,6 @@
import collections
import os
import re
-import urllib2
CLANG_DIR = os.path.join(os.path.dirname(__file__), '../..')
FORMAT_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Format/Format.h')
@@ -32,7 +31,7 @@ def indent(text, columns, indent_first_line=True):
return s
return indent + s
-class Option:
+class Option(object):
def __init__(self, name, type, comment):
self.name = name
self.type = type
@@ -50,7 +49,7 @@ class Option:
2)
return s
-class NestedStruct:
+class NestedStruct(object):
def __init__(self, name, comment):
self.name = name
self.comment = comment.strip()
@@ -59,7 +58,7 @@ class NestedStruct:
def __str__(self):
return '\n'.join(map(str, self.values))
-class NestedField:
+class NestedField(object):
def __init__(self, name, comment):
self.name = name
self.comment = comment.strip()
@@ -69,7 +68,7 @@ class NestedField:
self.name,
doxygen2rst(indent(self.comment, 2, indent_first_line=False)))
-class Enum:
+class Enum(object):
def __init__(self, name, comment):
self.name = name
self.comment = comment.strip()
@@ -78,7 +77,7 @@ class Enum:
def __str__(self):
return '\n'.join(map(str, self.values))
-class EnumValue:
+class EnumValue(object):
def __init__(self, name, comment):
self.name = name
self.comment = comment
@@ -101,7 +100,7 @@ def clean_comment_line(line):
return line[4:] + '\n'
def read_options(header):
- class State:
+ class State(object):
BeforeStruct, Finished, InStruct, InNestedStruct, InNestedFieldComent, \
InFieldComment, InEnum, InEnumMemberComment = range(8)
state = State.BeforeStruct
@@ -180,9 +179,9 @@ def read_options(header):
'std::vector<std::string>',
'std::vector<IncludeCategory>',
'std::vector<RawStringFormat>']:
- if enums.has_key(option.type):
+ if option.type in enums:
option.enum = enums[option.type]
- elif nested_structs.has_key(option.type):
+ elif option.type in nested_structs:
option.nested_struct = nested_structs[option.type]
else:
raise Exception('Unknown type: %s' % option.type)
diff --git a/examples/AnnotateFunctions/CMakeLists.txt b/examples/AnnotateFunctions/CMakeLists.txt
index 5684abf2380d..44b6317e72af 100644
--- a/examples/AnnotateFunctions/CMakeLists.txt
+++ b/examples/AnnotateFunctions/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_loadable_module(AnnotateFunctions AnnotateFunctions.cpp PLUGIN_TOOL clang)
+add_llvm_library(AnnotateFunctions MODULE AnnotateFunctions.cpp PLUGIN_TOOL clang)
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
target_link_libraries(AnnotateFunctions PRIVATE
diff --git a/examples/PrintFunctionNames/CMakeLists.txt b/examples/PrintFunctionNames/CMakeLists.txt
index e582b2c45a86..68c6f76dff05 100644
--- a/examples/PrintFunctionNames/CMakeLists.txt
+++ b/examples/PrintFunctionNames/CMakeLists.txt
@@ -9,7 +9,7 @@ if( NOT MSVC ) # MSVC mangles symbols differently, and
endif()
endif()
-add_llvm_loadable_module(PrintFunctionNames PrintFunctionNames.cpp PLUGIN_TOOL clang)
+add_llvm_library(PrintFunctionNames MODULE PrintFunctionNames.cpp PLUGIN_TOOL clang)
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
target_link_libraries(PrintFunctionNames PRIVATE
diff --git a/examples/analyzer-plugin/CMakeLists.txt b/examples/analyzer-plugin/CMakeLists.txt
index 0d5b2754cafe..7c7b2aec1988 100644
--- a/examples/analyzer-plugin/CMakeLists.txt
+++ b/examples/analyzer-plugin/CMakeLists.txt
@@ -1,5 +1,5 @@
set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/SampleAnalyzerPlugin.exports)
-add_llvm_loadable_module(SampleAnalyzerPlugin MainCallChecker.cpp PLUGIN_TOOL clang)
+add_llvm_library(SampleAnalyzerPlugin MODULE MainCallChecker.cpp PLUGIN_TOOL clang)
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
target_link_libraries(SampleAnalyzerPlugin PRIVATE
diff --git a/examples/analyzer-plugin/MainCallChecker.cpp b/examples/analyzer-plugin/MainCallChecker.cpp
index 74fe663e981f..77316d696de3 100644
--- a/examples/analyzer-plugin/MainCallChecker.cpp
+++ b/examples/analyzer-plugin/MainCallChecker.cpp
@@ -1,6 +1,6 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
using namespace clang;
@@ -45,7 +45,9 @@ void MainCallChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const
// Register plugin!
extern "C"
void clang_registerCheckers (CheckerRegistry &registry) {
- registry.addChecker<MainCallChecker>("example.MainCallChecker", "Disallows calls to functions called main");
+ registry.addChecker<MainCallChecker>(
+ "example.MainCallChecker", "Disallows calls to functions called main",
+ "");
}
extern "C"
diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt
index 7b9657ec1abf..b69a82e0541b 100644
--- a/examples/clang-interpreter/CMakeLists.txt
+++ b/examples/clang-interpreter/CMakeLists.txt
@@ -25,6 +25,7 @@ target_link_libraries(clang-interpreter
clangCodeGen
clangDriver
clangFrontend
+ clangSerialization
)
export_executable_symbols(clang-interpreter)
diff --git a/examples/clang-interpreter/Test.cxx b/examples/clang-interpreter/Test.cxx
index d2cbb0baac5c..d39249214dc5 100644
--- a/examples/clang-interpreter/Test.cxx
+++ b/examples/clang-interpreter/Test.cxx
@@ -21,7 +21,7 @@ static void ThrowerAnError(const char* Name) {
int main(int argc, const char** argv) {
for (int I = 0; I < argc; ++I)
printf("arg[%d]='%s'\n", I, argv[I]);
-
+
try {
ThrowerAnError("In JIT");
} catch (const std::exception& E) {
diff --git a/examples/clang-interpreter/main.cpp b/examples/clang-interpreter/main.cpp
index 3f87be29a979..1c83b1d3e75f 100644
--- a/examples/clang-interpreter/main.cpp
+++ b/examples/clang-interpreter/main.cpp
@@ -54,8 +54,8 @@ private:
std::shared_ptr<SymbolResolver> Resolver;
std::unique_ptr<TargetMachine> TM;
const DataLayout DL;
- RTDyldObjectLinkingLayer ObjectLayer;
- IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
+ LegacyRTDyldObjectLinkingLayer ObjectLayer;
+ LegacyIRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
public:
SimpleJIT()
@@ -75,7 +75,7 @@ public:
TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer(ES,
[this](VModuleKey) {
- return RTDyldObjectLinkingLayer::Resources{
+ return LegacyRTDyldObjectLinkingLayer::Resources{
std::make_shared<SectionMemoryManager>(), Resolver};
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
@@ -164,7 +164,7 @@ int main(int argc, const char **argv) {
}
// Initialize a compiler invocation object from the clang (-cc1) arguments.
- const driver::ArgStringList &CCArgs = Cmd.getArguments();
+ const llvm::opt::ArgStringList &CCArgs = Cmd.getArguments();
std::unique_ptr<CompilerInvocation> CI(new CompilerInvocation);
CompilerInvocation::CreateFromArgs(*CI,
const_cast<const char **>(CCArgs.data()),
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 65dada38b050..c51dfb1598b9 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 49
+#define CINDEX_VERSION_MINOR 50
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -178,7 +178,6 @@ typedef struct CXVersion {
* A negative value indicates that the cursor is not a function declaration.
*/
enum CXCursor_ExceptionSpecificationKind {
-
/**
* The cursor has no exception specification.
*/
@@ -1332,7 +1331,17 @@ enum CXTranslationUnit_Flags {
*
* The function bodies of the main file are not skipped.
*/
- CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800
+ CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800,
+
+ /**
+ * Used to indicate that attributed types should be included in CXType.
+ */
+ CXTranslationUnit_IncludeAttributedTypes = 0x1000,
+
+ /**
+ * Used to indicate that implicit attributes should be visited.
+ */
+ CXTranslationUnit_VisitImplicitAttributes = 0x2000
};
/**
@@ -2559,7 +2568,25 @@ enum CXCursorKind {
CXCursor_VisibilityAttr = 417,
CXCursor_DLLExport = 418,
CXCursor_DLLImport = 419,
- CXCursor_LastAttr = CXCursor_DLLImport,
+ CXCursor_NSReturnsRetained = 420,
+ CXCursor_NSReturnsNotRetained = 421,
+ CXCursor_NSReturnsAutoreleased = 422,
+ CXCursor_NSConsumesSelf = 423,
+ CXCursor_NSConsumed = 424,
+ CXCursor_ObjCException = 425,
+ CXCursor_ObjCNSObject = 426,
+ CXCursor_ObjCIndependentClass = 427,
+ CXCursor_ObjCPreciseLifetime = 428,
+ CXCursor_ObjCReturnsInnerPointer = 429,
+ CXCursor_ObjCRequiresSuper = 430,
+ CXCursor_ObjCRootClass = 431,
+ CXCursor_ObjCSubclassingRestricted = 432,
+ CXCursor_ObjCExplicitProtocolImpl = 433,
+ CXCursor_ObjCDesignatedInitializer = 434,
+ CXCursor_ObjCRuntimeVisible = 435,
+ CXCursor_ObjCBoxable = 436,
+ CXCursor_FlagEnum = 437,
+ CXCursor_LastAttr = CXCursor_FlagEnum,
/* Preprocessing */
CXCursor_PreprocessingDirective = 500,
@@ -3266,7 +3293,25 @@ enum CXTypeKind {
CXType_OCLSampler = 157,
CXType_OCLEvent = 158,
CXType_OCLQueue = 159,
- CXType_OCLReserveID = 160
+ CXType_OCLReserveID = 160,
+
+ CXType_ObjCObject = 161,
+ CXType_ObjCTypeParam = 162,
+ CXType_Attributed = 163,
+
+ CXType_OCLIntelSubgroupAVCMcePayload = 164,
+ CXType_OCLIntelSubgroupAVCImePayload = 165,
+ CXType_OCLIntelSubgroupAVCRefPayload = 166,
+ CXType_OCLIntelSubgroupAVCSicPayload = 167,
+ CXType_OCLIntelSubgroupAVCMceResult = 168,
+ CXType_OCLIntelSubgroupAVCImeResult = 169,
+ CXType_OCLIntelSubgroupAVCRefResult = 170,
+ CXType_OCLIntelSubgroupAVCSicResult = 171,
+ CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172,
+ CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173,
+ CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174,
+
+ CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175
};
/**
@@ -3291,6 +3336,7 @@ enum CXCallingConv {
CXCallingConv_Swift = 13,
CXCallingConv_PreserveMost = 14,
CXCallingConv_PreserveAll = 15,
+ CXCallingConv_AArch64VectorCall = 16,
CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
@@ -3628,6 +3674,43 @@ CINDEX_LINKAGE int clang_getNumArgTypes(CXType T);
CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i);
/**
+ * Retrieves the base type of the ObjCObjectType.
+ *
+ * If the type is not an ObjC object, an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_Type_getObjCObjectBaseType(CXType T);
+
+/**
+ * Retrieve the number of protocol references associated with an ObjC object/id.
+ *
+ * If the type is not an ObjC object, 0 is returned.
+ */
+CINDEX_LINKAGE unsigned clang_Type_getNumObjCProtocolRefs(CXType T);
+
+/**
+ * Retrieve the decl for a protocol reference for an ObjC object/id.
+ *
+ * If the type is not an ObjC object or there are not enough protocol
+ * references, an invalid cursor is returned.
+ */
+CINDEX_LINKAGE CXCursor clang_Type_getObjCProtocolDecl(CXType T, unsigned i);
+
+/**
+ * Retreive the number of type arguments associated with an ObjC object.
+ *
+ * If the type is not an ObjC object, 0 is returned.
+ */
+CINDEX_LINKAGE unsigned clang_Type_getNumObjCTypeArgs(CXType T);
+
+/**
+ * Retrieve a type argument associated with an ObjC object.
+ *
+ * If the type is not an ObjC or the index is not valid,
+ * an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_Type_getObjCTypeArg(CXType T, unsigned i);
+
+/**
* Return 1 if the CXType is a variadic function type, and 0 otherwise.
*/
CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T);
@@ -3700,6 +3783,33 @@ CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T);
*/
CINDEX_LINKAGE unsigned clang_Type_isTransparentTagTypedef(CXType T);
+enum CXTypeNullabilityKind {
+ /**
+ * Values of this type can never be null.
+ */
+ CXTypeNullability_NonNull = 0,
+ /**
+ * Values of this type can be null.
+ */
+ CXTypeNullability_Nullable = 1,
+ /**
+ * Whether values of this type can be null is (explicitly)
+ * unspecified. This captures a (fairly rare) case where we
+ * can't conclude anything about the nullability of the type even
+ * though it has been considered.
+ */
+ CXTypeNullability_Unspecified = 2,
+ /**
+ * Nullability is not applicable to this type.
+ */
+ CXTypeNullability_Invalid = 3
+};
+
+/**
+ * Retrieve the nullability kind of a pointer type.
+ */
+CINDEX_LINKAGE enum CXTypeNullabilityKind clang_Type_getNullability(CXType T);
+
/**
* List the possible error codes for \c clang_Type_getSizeOf,
* \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and
@@ -3779,6 +3889,13 @@ CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T);
CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S);
/**
+ * Return the type that was modified by this attributed type.
+ *
+ * If the type is not an attributed type, an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_Type_getModifiedType(CXType T);
+
+/**
* Return the offset of the field represented by the Cursor.
*
* If the cursor is not a field declaration, -1 is returned.
@@ -4348,6 +4465,18 @@ CINDEX_LINKAGE unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C,
unsigned reserved);
/**
+ * Given a cursor that represents a property declaration, return the
+ * name of the method that implements the getter.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C);
+
+/**
+ * Given a cursor that represents a property declaration, return the
+ * name of the method that implements the setter, if any.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertySetterName(CXCursor C);
+
+/**
* 'Qualifiers' written next to the return and parameter types in
* Objective-C method declarations.
*/
@@ -5492,9 +5621,14 @@ enum CXCompletionContext {
CXCompletionContext_NaturalLanguage = 1 << 21,
/**
+ * #include file completions should be included in the results.
+ */
+ CXCompletionContext_IncludedFile = 1 << 22,
+
+ /**
* The current context is unknown, so set all contexts.
*/
- CXCompletionContext_Unknown = ((1 << 22) - 1)
+ CXCompletionContext_Unknown = ((1 << 23) - 1)
};
/**
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index a9ab687a8de9..13870116c7fd 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
#define LLVM_CLANG_AST_ASTCONTEXT_H
+#include "clang/AST/ASTContextAllocate.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CommentCommandTraits.h"
@@ -22,6 +23,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
@@ -30,6 +32,7 @@
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
@@ -79,6 +82,7 @@ struct fltSemantics;
namespace clang {
+class APFixedPoint;
class APValue;
class ASTMutationListener;
class ASTRecordLayout;
@@ -92,6 +96,7 @@ class CXXMethodDecl;
class CXXRecordDecl;
class DiagnosticsEngine;
class Expr;
+class FixedPointSemantics;
class MangleContext;
class MangleNumberingContext;
class MaterializeTemporaryExpr;
@@ -148,6 +153,22 @@ struct TypeInfo {
/// Holds long-lived AST nodes (such as types and decls) that can be
/// referred to throughout the semantic analysis of a file.
class ASTContext : public RefCountedBase<ASTContext> {
+public:
+ /// Copy initialization expr of a __block variable and a boolean flag that
+ /// indicates whether the expression can throw.
+ struct BlockVarCopyInit {
+ BlockVarCopyInit() = default;
+ BlockVarCopyInit(Expr *CopyExpr, bool CanThrow)
+ : ExprAndFlag(CopyExpr, CanThrow) {}
+ void setExprAndFlag(Expr *CopyExpr, bool CanThrow) {
+ ExprAndFlag.setPointerAndInt(CopyExpr, CanThrow);
+ }
+ Expr *getCopyExpr() const { return ExprAndFlag.getPointer(); }
+ bool canThrow() const { return ExprAndFlag.getInt(); }
+ llvm::PointerIntPair<Expr *, 1, bool> ExprAndFlag;
+ };
+
+private:
friend class NestedNameSpecifier;
mutable SmallVector<Type *, 0> Types;
@@ -242,8 +263,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// interface.
llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls;
- /// Mapping from __block VarDecls to their copy initialization expr.
- llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
+ /// Mapping from __block VarDecls to BlockVarCopyInit.
+ llvm::DenseMap<const VarDecl *, BlockVarCopyInit> BlockVarCopyInits;
/// Mapping from class scope functions specialization to their
/// template patterns.
@@ -316,7 +337,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable IdentifierInfo *BoolName = nullptr;
/// The identifier 'NSObject'.
- IdentifierInfo *NSObjectName = nullptr;
+ mutable IdentifierInfo *NSObjectName = nullptr;
/// The identifier 'NSCopying'.
IdentifierInfo *NSCopyingName = nullptr;
@@ -549,26 +570,6 @@ public:
IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
ASTMutationListener *Listener = nullptr;
- /// Contains parents of a node.
- using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>;
-
- /// Maps from a node to its parents. This is used for nodes that have
- /// pointer identity only, which are more common and we can save space by
- /// only storing a unique pointer to them.
- using ParentMapPointers =
- llvm::DenseMap<const void *,
- llvm::PointerUnion4<const Decl *, const Stmt *,
- ast_type_traits::DynTypedNode *,
- ParentVector *>>;
-
- /// Parent map for nodes without pointer identity. We store a full
- /// DynTypedNode for all keys.
- using ParentMapOtherNodes =
- llvm::DenseMap<ast_type_traits::DynTypedNode,
- llvm::PointerUnion4<const Decl *, const Stmt *,
- ast_type_traits::DynTypedNode *,
- ParentVector *>>;
-
/// Container for either a single DynTypedNode or for an ArrayRef to
/// DynTypedNode. For use with ParentMap.
class DynTypedNodeList {
@@ -610,7 +611,17 @@ public:
}
};
- /// Returns the parents of the given node.
+ // A traversal scope limits the parts of the AST visible to certain analyses.
+ // RecursiveASTVisitor::TraverseAST will only visit reachable nodes, and
+ // getParents() will only observe reachable parent edges.
+ //
+ // The scope is defined by a set of "top-level" declarations.
+ // Initially, it is the entire TU: {getTranslationUnitDecl()}.
+ // Changing the scope clears the parent cache, which is expensive to rebuild.
+ std::vector<Decl *> getTraversalScope() const { return TraversalScope; }
+ void setTraversalScope(const std::vector<Decl *> &);
+
+ /// Returns the parents of the given node (within the traversal scope).
///
/// Note that this will lazily compute the parents of all nodes
/// and store them for later retrieval. Thus, the first call is O(n)
@@ -977,7 +988,8 @@ public:
/// Get the additional modules in which the definition \p Def has
/// been merged.
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) {
- auto MergedIt = MergedDefModules.find(Def);
+ auto MergedIt =
+ MergedDefModules.find(cast<NamedDecl>(Def->getCanonicalDecl()));
if (MergedIt == MergedDefModules.end())
return None;
return MergedIt->second;
@@ -1041,6 +1053,9 @@ public:
CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
CanQualType OCLQueueTy, OCLReserveIDTy;
CanQualType OMPArraySectionTy;
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ CanQualType Id##Ty;
+#include "clang/Basic/OpenCLExtensionTypes.def"
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
mutable QualType AutoDeductTy; // Deduction against 'auto'.
@@ -1403,7 +1418,7 @@ public:
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
- QualType getAttributedType(AttributedType::Kind attrKind,
+ QualType getAttributedType(attr::Kind attrKind,
QualType modifiedType,
QualType equivalentType);
@@ -1656,7 +1671,7 @@ public:
}
/// Retrieve the identifier 'NSObject'.
- IdentifierInfo *getNSObjectName() {
+ IdentifierInfo *getNSObjectName() const {
if (!NSObjectName) {
NSObjectName = &Idents.get("NSObject");
}
@@ -1961,6 +1976,9 @@ public:
unsigned char getFixedPointScale(QualType Ty) const;
unsigned char getFixedPointIBits(QualType Ty) const;
+ FixedPointSemantics getFixedPointSemantics(QualType Ty) const;
+ APFixedPoint getFixedPointMax(QualType Ty) const;
+ APFixedPoint getFixedPointMin(QualType Ty) const;
DeclarationNameInfo getNameForTemplate(TemplateName Name,
SourceLocation NameLoc) const;
@@ -2488,6 +2506,8 @@ public:
unsigned getTargetAddressSpace(LangAS AS) const;
+ LangAS getLangASForBuiltinAddressSpace(unsigned AS) const;
+
/// Get target-dependent integer value for null pointer which is used for
/// constant folding.
uint64_t getTargetNullPointerValue(QualType QT) const;
@@ -2657,12 +2677,13 @@ public:
/// otherwise returns null.
const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const;
- /// Set the copy inialization expression of a block var decl.
- void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
+ /// Set the copy inialization expression of a block var decl. \p CanThrow
+ /// indicates whether the copy expression can throw or not.
+ void setBlockVarCopyInit(const VarDecl* VD, Expr *CopyExpr, bool CanThrow);
/// Get the copy initialization expression of the VarDecl \p VD, or
/// nullptr if none exists.
- Expr *getBlockVarCopyInits(const VarDecl* VD);
+ BlockVarCopyInit getBlockVarCopyInit(const VarDecl* VD) const;
/// Allocate an uninitialized TypeSourceInfo.
///
@@ -2718,7 +2739,7 @@ public:
/// predicate.
void forEachMultiversionedFunctionVersion(
const FunctionDecl *FD,
- llvm::function_ref<void(const FunctionDecl *)> Pred) const;
+ llvm::function_ref<void(FunctionDecl *)> Pred) const;
const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
@@ -2894,13 +2915,13 @@ private:
// but we include it here so that ASTContext can quickly deallocate them.
llvm::PointerIntPair<StoredDeclsMap *, 1> LastSDM;
- std::unique_ptr<ParentMapPointers> PointerParents;
- std::unique_ptr<ParentMapOtherNodes> OtherParents;
+ std::vector<Decl *> TraversalScope;
+ class ParentMap;
+ std::unique_ptr<ParentMap> Parents;
std::unique_ptr<VTableContextBase> VTContext;
void ReleaseDeclContextMaps();
- void ReleaseParentMapEntries();
public:
enum PragmaSectionFlag : unsigned {
@@ -2949,8 +2970,8 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
/// This placement form of operator new uses the ASTContext's allocator for
/// obtaining memory.
///
-/// IMPORTANT: These are also declared in clang/AST/AttrIterator.h! Any changes
-/// here need to also be made there.
+/// IMPORTANT: These are also declared in clang/AST/ASTContextAllocate.h!
+/// Any changes here need to also be made there.
///
/// We intentionally avoid using a nothrow specification here so that the calls
/// to this operator will not perform a null check on the result -- the
@@ -2973,7 +2994,7 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
/// allocator supports it).
/// @return The allocated memory. Could be nullptr.
inline void *operator new(size_t Bytes, const clang::ASTContext &C,
- size_t Alignment) {
+ size_t Alignment /* = 8 */) {
return C.Allocate(Bytes, Alignment);
}
@@ -3011,7 +3032,7 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) {
/// allocator supports it).
/// @return The allocated memory. Could be nullptr.
inline void *operator new[](size_t Bytes, const clang::ASTContext& C,
- size_t Alignment = 8) {
+ size_t Alignment /* = 8 */) {
return C.Allocate(Bytes, Alignment);
}
diff --git a/include/clang/AST/ASTContextAllocate.h b/include/clang/AST/ASTContextAllocate.h
new file mode 100644
index 000000000000..5b9eed208a4d
--- /dev/null
+++ b/include/clang/AST/ASTContextAllocate.h
@@ -0,0 +1,38 @@
+//===- ASTContextAllocate.h - ASTContext allocate functions -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares ASTContext allocation functions separate from the main
+// code in ASTContext.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H
+#define LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H
+
+#include <cstddef>
+
+namespace clang {
+
+class ASTContext;
+
+} // namespace clang
+
+// Defined in ASTContext.h
+void *operator new(size_t Bytes, const clang::ASTContext &C,
+ size_t Alignment = 8);
+void *operator new[](size_t Bytes, const clang::ASTContext &C,
+ size_t Alignment = 8);
+
+// It is good practice to pair new/delete operators. Also, MSVC gives many
+// warnings if a matching delete overload is not declared, even though the
+// throw() spec guarantees it will not be implicitly called.
+void operator delete(void *Ptr, const clang::ASTContext &C, size_t);
+void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
+
+#endif // LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 2534272da3a3..fe92604587ef 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -11,19 +11,9 @@
#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticAST.h"
namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define ASTSTART
-#include "clang/Basic/DiagnosticASTKinds.inc"
-#undef DIAG
- NUM_BUILTIN_AST_DIAGNOSTICS
- };
- } // end namespace diag
-
/// DiagnosticsEngine argument formatting function for diagnostics that
/// involve AST nodes.
///
diff --git a/include/clang/AST/ASTDumperUtils.h b/include/clang/AST/ASTDumperUtils.h
new file mode 100644
index 000000000000..5e62e902b423
--- /dev/null
+++ b/include/clang/AST/ASTDumperUtils.h
@@ -0,0 +1,97 @@
+//===--- ASTDumperUtils.h - Printing of AST nodes -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AST utilities for traversal down the tree.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTDUMPERUTILS_H
+#define LLVM_CLANG_AST_ASTDUMPERUTILS_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+// Colors used for various parts of the AST dump
+// Do not use bold yellow for any text. It is hard to read on white screens.
+
+struct TerminalColor {
+ llvm::raw_ostream::Colors Color;
+ bool Bold;
+};
+
+// Red - CastColor
+// Green - TypeColor
+// Bold Green - DeclKindNameColor, UndeserializedColor
+// Yellow - AddressColor, LocationColor
+// Blue - CommentColor, NullColor, IndentColor
+// Bold Blue - AttrColor
+// Bold Magenta - StmtColor
+// Cyan - ValueKindColor, ObjectKindColor
+// Bold Cyan - ValueColor, DeclNameColor
+
+// Decl kind names (VarDecl, FunctionDecl, etc)
+static const TerminalColor DeclKindNameColor = {llvm::raw_ostream::GREEN, true};
+// Attr names (CleanupAttr, GuardedByAttr, etc)
+static const TerminalColor AttrColor = {llvm::raw_ostream::BLUE, true};
+// Statement names (DeclStmt, ImplicitCastExpr, etc)
+static const TerminalColor StmtColor = {llvm::raw_ostream::MAGENTA, true};
+// Comment names (FullComment, ParagraphComment, TextComment, etc)
+static const TerminalColor CommentColor = {llvm::raw_ostream::BLUE, false};
+
+// Type names (int, float, etc, plus user defined types)
+static const TerminalColor TypeColor = {llvm::raw_ostream::GREEN, false};
+
+// Pointer address
+static const TerminalColor AddressColor = {llvm::raw_ostream::YELLOW, false};
+// Source locations
+static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false};
+
+// lvalue/xvalue
+static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false};
+// bitfield/objcproperty/objcsubscript/vectorcomponent
+static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false};
+
+// Null statements
+static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false};
+
+// Undeserialized entities
+static const TerminalColor UndeserializedColor = {llvm::raw_ostream::GREEN,
+ true};
+
+// CastKind from CastExpr's
+static const TerminalColor CastColor = {llvm::raw_ostream::RED, false};
+
+// Value of the statement
+static const TerminalColor ValueColor = {llvm::raw_ostream::CYAN, true};
+// Decl names
+static const TerminalColor DeclNameColor = {llvm::raw_ostream::CYAN, true};
+
+// Indents ( `, -. | )
+static const TerminalColor IndentColor = {llvm::raw_ostream::BLUE, false};
+
+class ColorScope {
+ llvm::raw_ostream &OS;
+ const bool ShowColors;
+
+public:
+ ColorScope(llvm::raw_ostream &OS, bool ShowColors, TerminalColor Color)
+ : OS(OS), ShowColors(ShowColors) {
+ if (ShowColors)
+ OS.changeColor(Color.Color, Color.Bold);
+ }
+ ~ColorScope() {
+ if (ShowColors)
+ OS.resetColor();
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_ASTDUMPERUTILS_H
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 2e9a8775a8a2..dbb9cf35ddea 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -25,12 +25,15 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Error.h"
#include <utility>
namespace clang {
class ASTContext;
+class ASTImporterLookupTable;
class CXXBaseSpecifier;
class CXXCtorInitializer;
class Decl;
@@ -43,6 +46,29 @@ class TagDecl;
class TypeSourceInfo;
class Attr;
+ class ImportError : public llvm::ErrorInfo<ImportError> {
+ public:
+ /// \brief Kind of error when importing an AST component.
+ enum ErrorKind {
+ NameConflict, /// Naming ambiguity (likely ODR violation).
+ UnsupportedConstruct, /// Not supported node or case.
+ Unknown /// Other error.
+ };
+
+ ErrorKind Error;
+
+ static char ID;
+
+ ImportError() : Error(Unknown) { }
+ ImportError(const ImportError &Other) : Error(Other.Error) { }
+ ImportError(ErrorKind Error) : Error(Error) { }
+
+ std::string toString() const;
+
+ void log(raw_ostream &OS) const override;
+ std::error_code convertToErrorCode() const override;
+ };
+
// \brief Returns with a list of declarations started from the canonical decl
// then followed by subsequent decls in the translation unit.
// This gives a canonical list for each entry in the redecl chain.
@@ -55,12 +81,21 @@ class Attr;
/// Imports selected nodes from one AST context into another context,
/// merging AST nodes where appropriate.
class ASTImporter {
+ friend class ASTNodeImporter;
public:
using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>;
using ImportedCXXBaseSpecifierMap =
llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>;
private:
+
+ /// Pointer to the import specific lookup table, which may be shared
+ /// amongst several ASTImporter objects.
+ /// This is an externally managed resource (and should exist during the
+ /// lifetime of the ASTImporter object)
+ /// If not set then the original C/C++ lookup is used.
+ ASTImporterLookupTable *LookupTable = nullptr;
+
/// The contexts we're importing to and from.
ASTContext &ToContext, &FromContext;
@@ -98,9 +133,13 @@ class Attr;
/// (which we have already complained about).
NonEquivalentDeclSet NonEquivalentDecls;
+ using FoundDeclsTy = SmallVector<NamedDecl *, 2>;
+ FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name);
+
+ void AddToLookupTable(Decl *ToD);
+
public:
- /// Create a new AST importer.
- ///
+
/// \param ToContext The context we'll be importing into.
///
/// \param ToFileManager The file manager we'll be importing into.
@@ -112,9 +151,14 @@ class Attr;
/// \param MinimalImport If true, the importer will attempt to import
/// as little as it can, e.g., by importing declarations as forward
/// declarations that can be completed at a later point.
+ ///
+ /// \param LookupTable The importer specific lookup table which may be
+ /// shared amongst several ASTImporter objects.
+ /// If not set then the original C/C++ lookup is used.
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
- bool MinimalImport);
+ bool MinimalImport,
+ ASTImporterLookupTable *LookupTable = nullptr);
virtual ~ASTImporter();
@@ -122,31 +166,60 @@ class Attr;
/// to-be-completed forward declarations when possible.
bool isMinimalImport() const { return Minimal; }
+ /// \brief Import the given object, returns the result.
+ ///
+ /// \param To Import the object into this variable.
+ /// \param From Object to import.
+ /// \return Error information (success or error).
+ template <typename ImportT>
+ LLVM_NODISCARD llvm::Error importInto(ImportT &To, const ImportT &From) {
+ To = Import(From);
+ if (From && !To)
+ return llvm::make_error<ImportError>();
+ return llvm::Error::success();
+ // FIXME: this should be the final code
+ //auto ToOrErr = Import(From);
+ //if (ToOrErr)
+ // To = *ToOrErr;
+ //return ToOrErr.takeError();
+ }
+
/// Import the given type from the "from" context into the "to"
- /// context.
+ /// context. A null type is imported as a null type (no error).
///
- /// \returns the equivalent type in the "to" context, or a NULL type if
- /// an error occurred.
+ /// \returns The equivalent type in the "to" context, or the import error.
+ llvm::Expected<QualType> Import_New(QualType FromT);
+ // FIXME: Remove this version.
QualType Import(QualType FromT);
/// Import the given type source information from the
/// "from" context into the "to" context.
///
- /// \returns the equivalent type source information in the "to"
- /// context, or NULL if an error occurred.
+ /// \returns The equivalent type source information in the "to"
+ /// context, or the import error.
+ llvm::Expected<TypeSourceInfo *> Import_New(TypeSourceInfo *FromTSI);
+ // FIXME: Remove this version.
TypeSourceInfo *Import(TypeSourceInfo *FromTSI);
/// Import the given attribute from the "from" context into the
/// "to" context.
///
- /// \returns the equivalent attribute in the "to" context.
+ /// \returns The equivalent attribute in the "to" context, or the import
+ /// error.
+ llvm::Expected<Attr *> Import_New(const Attr *FromAttr);
+ // FIXME: Remove this version.
Attr *Import(const Attr *FromAttr);
/// Import the given declaration from the "from" context into the
/// "to" context.
///
- /// \returns the equivalent declaration in the "to" context, or a NULL type
- /// if an error occurred.
+ /// \returns The equivalent declaration in the "to" context, or the import
+ /// error.
+ llvm::Expected<Decl *> Import_New(Decl *FromD);
+ llvm::Expected<Decl *> Import_New(const Decl *FromD) {
+ return Import_New(const_cast<Decl *>(FromD));
+ }
+ // FIXME: Remove this version.
Decl *Import(Decl *FromD);
Decl *Import(const Decl *FromD) {
return Import(const_cast<Decl *>(FromD));
@@ -155,104 +228,137 @@ class Attr;
/// Return the copy of the given declaration in the "to" context if
/// it has already been imported from the "from" context. Otherwise return
/// NULL.
- Decl *GetAlreadyImportedOrNull(Decl *FromD);
+ Decl *GetAlreadyImportedOrNull(const Decl *FromD) const;
/// Import the given declaration context from the "from"
/// AST context into the "to" AST context.
///
/// \returns the equivalent declaration context in the "to"
- /// context, or a NULL type if an error occurred.
- DeclContext *ImportContext(DeclContext *FromDC);
+ /// context, or error value.
+ llvm::Expected<DeclContext *> ImportContext(DeclContext *FromDC);
/// Import the given expression from the "from" context into the
/// "to" context.
///
- /// \returns the equivalent expression in the "to" context, or NULL if
- /// an error occurred.
+ /// \returns The equivalent expression in the "to" context, or the import
+ /// error.
+ llvm::Expected<Expr *> Import_New(Expr *FromE);
+ // FIXME: Remove this version.
Expr *Import(Expr *FromE);
/// Import the given statement from the "from" context into the
/// "to" context.
///
- /// \returns the equivalent statement in the "to" context, or NULL if
- /// an error occurred.
+ /// \returns The equivalent statement in the "to" context, or the import
+ /// error.
+ llvm::Expected<Stmt *> Import_New(Stmt *FromS);
+ // FIXME: Remove this version.
Stmt *Import(Stmt *FromS);
/// Import the given nested-name-specifier from the "from"
/// context into the "to" context.
///
- /// \returns the equivalent nested-name-specifier in the "to"
- /// context, or NULL if an error occurred.
+ /// \returns The equivalent nested-name-specifier in the "to"
+ /// context, or the import error.
+ llvm::Expected<NestedNameSpecifier *>
+ Import_New(NestedNameSpecifier *FromNNS);
+ // FIXME: Remove this version.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
- /// Import the given nested-name-specifier from the "from"
+ /// Import the given nested-name-specifier-loc from the "from"
/// context into the "to" context.
///
- /// \returns the equivalent nested-name-specifier in the "to"
- /// context.
+ /// \returns The equivalent nested-name-specifier-loc in the "to"
+ /// context, or the import error.
+ llvm::Expected<NestedNameSpecifierLoc>
+ Import_New(NestedNameSpecifierLoc FromNNS);
+ // FIXME: Remove this version.
NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS);
- /// Import the goven template name from the "from" context into the
- /// "to" context.
+ /// Import the given template name from the "from" context into the
+ /// "to" context, or the import error.
+ llvm::Expected<TemplateName> Import_New(TemplateName From);
+ // FIXME: Remove this version.
TemplateName Import(TemplateName From);
/// Import the given source location from the "from" context into
/// the "to" context.
///
- /// \returns the equivalent source location in the "to" context, or an
- /// invalid source location if an error occurred.
+ /// \returns The equivalent source location in the "to" context, or the
+ /// import error.
+ llvm::Expected<SourceLocation> Import_New(SourceLocation FromLoc);
+ // FIXME: Remove this version.
SourceLocation Import(SourceLocation FromLoc);
/// Import the given source range from the "from" context into
/// the "to" context.
///
- /// \returns the equivalent source range in the "to" context, or an
- /// invalid source location if an error occurred.
+ /// \returns The equivalent source range in the "to" context, or the import
+ /// error.
+ llvm::Expected<SourceRange> Import_New(SourceRange FromRange);
+ // FIXME: Remove this version.
SourceRange Import(SourceRange FromRange);
/// Import the given declaration name from the "from"
/// context into the "to" context.
///
- /// \returns the equivalent declaration name in the "to" context,
- /// or an empty declaration name if an error occurred.
+ /// \returns The equivalent declaration name in the "to" context, or the
+ /// import error.
+ llvm::Expected<DeclarationName> Import_New(DeclarationName FromName);
+ // FIXME: Remove this version.
DeclarationName Import(DeclarationName FromName);
/// Import the given identifier from the "from" context
/// into the "to" context.
///
- /// \returns the equivalent identifier in the "to" context.
+ /// \returns The equivalent identifier in the "to" context. Note: It
+ /// returns nullptr only if the FromId was nullptr.
IdentifierInfo *Import(const IdentifierInfo *FromId);
/// Import the given Objective-C selector from the "from"
/// context into the "to" context.
///
- /// \returns the equivalent selector in the "to" context.
+ /// \returns The equivalent selector in the "to" context, or the import
+ /// error.
+ llvm::Expected<Selector> Import_New(Selector FromSel);
+ // FIXME: Remove this version.
Selector Import(Selector FromSel);
/// Import the given file ID from the "from" context into the
/// "to" context.
///
- /// \returns the equivalent file ID in the source manager of the "to"
- /// context.
+ /// \returns The equivalent file ID in the source manager of the "to"
+ /// context, or the import error.
+ llvm::Expected<FileID> Import_New(FileID);
+ // FIXME: Remove this version.
FileID Import(FileID);
/// Import the given C++ constructor initializer from the "from"
/// context into the "to" context.
///
- /// \returns the equivalent initializer in the "to" context.
+ /// \returns The equivalent initializer in the "to" context, or the import
+ /// error.
+ llvm::Expected<CXXCtorInitializer *>
+ Import_New(CXXCtorInitializer *FromInit);
+ // FIXME: Remove this version.
CXXCtorInitializer *Import(CXXCtorInitializer *FromInit);
/// Import the given CXXBaseSpecifier from the "from" context into
/// the "to" context.
///
- /// \returns the equivalent CXXBaseSpecifier in the source manager of the
- /// "to" context.
+ /// \returns The equivalent CXXBaseSpecifier in the source manager of the
+ /// "to" context, or the import error.
+ llvm::Expected<CXXBaseSpecifier *>
+ Import_New(const CXXBaseSpecifier *FromSpec);
+ // FIXME: Remove this version.
CXXBaseSpecifier *Import(const CXXBaseSpecifier *FromSpec);
/// Import the definition of the given declaration, including all of
/// the declarations it contains.
- ///
- /// This routine is intended to be used
+ LLVM_NODISCARD llvm::Error ImportDefinition_New(Decl *From);
+
+ // FIXME: Compatibility function.
+ // Usages of this should be changed to ImportDefinition_New.
void ImportDefinition(Decl *From);
/// Cope with a name conflict when importing a declaration into the
@@ -333,6 +439,13 @@ class Attr;
/// equivalent.
bool IsStructurallyEquivalent(QualType From, QualType To,
bool Complain = true);
+
+ /// Determine the index of a field in its parent record.
+ /// F should be a field (or indirect field) declaration.
+ /// \returns The index of the field in its parent context (starting from 0).
+ /// On error `None` is returned (parent context is non-record).
+ static llvm::Optional<unsigned> getFieldIndex(Decl *F);
+
};
} // namespace clang
diff --git a/include/clang/AST/ASTImporterLookupTable.h b/include/clang/AST/ASTImporterLookupTable.h
new file mode 100644
index 000000000000..14cafe817ddc
--- /dev/null
+++ b/include/clang/AST/ASTImporterLookupTable.h
@@ -0,0 +1,75 @@
+//===- ASTImporterLookupTable.h - ASTImporter specific lookup--*- C++ -*---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ASTImporterLookupTable class which implements a
+// lookup procedure for the import mechanism.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H
+#define LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H
+
+#include "clang/AST/DeclBase.h" // lookup_result
+#include "clang/AST/DeclarationName.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+
+class ASTContext;
+class NamedDecl;
+class DeclContext;
+
+// There are certain cases when normal C/C++ lookup (localUncachedLookup)
+// does not find AST nodes. E.g.:
+// Example 1:
+// template <class T>
+// struct X {
+// friend void foo(); // this is never found in the DC of the TU.
+// };
+// Example 2:
+// // The fwd decl to Foo is not found in the lookupPtr of the DC of the
+// // translation unit decl.
+// // Here we could find the node by doing a traverse throught the list of
+// // the Decls in the DC, but that would not scale.
+// struct A { struct Foo *p; };
+// This is a severe problem because the importer decides if it has to create a
+// new Decl or not based on the lookup results.
+// To overcome these cases we need an importer specific lookup table which
+// holds every node and we are not interested in any C/C++ specific visibility
+// considerations. Simply, we must know if there is an existing Decl in a
+// given DC. Once we found it then we can handle any visibility related tasks.
+class ASTImporterLookupTable {
+
+ // We store a list of declarations for each name.
+ // And we collect these lists for each DeclContext.
+ // We could have a flat map with (DeclContext, Name) tuple as key, but a two
+ // level map seems easier to handle.
+ using DeclList = llvm::SmallSetVector<NamedDecl *, 2>;
+ using NameMap = llvm::SmallDenseMap<DeclarationName, DeclList, 4>;
+ using DCMap = llvm::DenseMap<DeclContext *, NameMap>;
+
+ void add(DeclContext *DC, NamedDecl *ND);
+ void remove(DeclContext *DC, NamedDecl *ND);
+
+ DCMap LookupTable;
+
+public:
+ ASTImporterLookupTable(TranslationUnitDecl &TU);
+ void add(NamedDecl *ND);
+ void remove(NamedDecl *ND);
+ using LookupResult = DeclList;
+ LookupResult lookup(DeclContext *DC, DeclarationName Name) const;
+ void dump(DeclContext *DC) const;
+ void dump() const;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H
diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h
index d32f87d43e04..f8847505bc72 100644
--- a/include/clang/AST/ASTStructuralEquivalence.h
+++ b/include/clang/AST/ASTStructuralEquivalence.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
#define LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
+#include "clang/AST/DeclBase.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
@@ -114,8 +115,19 @@ struct StructuralEquivalenceContext {
private:
/// Finish checking all of the structural equivalences.
///
- /// \returns true if an error occurred, false otherwise.
+ /// \returns true if the equivalence check failed (non-equivalence detected),
+ /// false if equivalence was detected.
bool Finish();
+
+ /// Check for common properties at Finish.
+ /// \returns true if D1 and D2 may be equivalent,
+ /// false if they are for sure not.
+ bool CheckCommonEquivalence(Decl *D1, Decl *D2);
+
+ /// Check for class dependent properties at Finish.
+ /// \returns true if D1 and D2 may be equivalent,
+ /// false if they are for sure not.
+ bool CheckKindSpecificEquivalence(Decl *D1, Decl *D2);
};
} // namespace clang
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index 80cd6b7007a6..51de119f080e 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -18,6 +18,7 @@
#ifndef LLVM_CLANG_AST_ASTVECTOR_H
#define LLVM_CLANG_AST_ASTVECTOR_H
+#include "clang/AST/ASTContextAllocate.h"
#include "llvm/ADT/PointerIntPair.h"
#include <algorithm>
#include <cassert>
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 20922742f687..3a319326d269 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
+#include "clang/AST/ASTContextAllocate.h" // For Attrs.inc
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
@@ -113,6 +114,19 @@ public:
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
};
+class TypeAttr : public Attr {
+protected:
+ TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ bool IsLateParsed)
+ : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
+
+public:
+ static bool classof(const Attr *A) {
+ return A->getKind() >= attr::FirstTypeAttr &&
+ A->getKind() <= attr::LastTypeAttr;
+ }
+};
+
class StmtAttr : public Attr {
protected:
StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h
index 2087ecc0e70c..43ad1c931967 100644
--- a/include/clang/AST/AttrIterator.h
+++ b/include/clang/AST/AttrIterator.h
@@ -26,25 +26,6 @@ namespace clang {
class ASTContext;
class Attr;
-} // namespace clang
-
-// Defined in ASTContext.h
-void *operator new(size_t Bytes, const clang::ASTContext &C,
- size_t Alignment = 8);
-
-// FIXME: Being forced to not have a default argument here due to redeclaration
-// rules on default arguments sucks
-void *operator new[](size_t Bytes, const clang::ASTContext &C,
- size_t Alignment);
-
-// It is good practice to pair new/delete operators. Also, MSVC gives many
-// warnings if a matching delete overload is not declared, even though the
-// throw() spec guarantees it will not be implicitly called.
-void operator delete(void *Ptr, const clang::ASTContext &C, size_t);
-void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
-
-namespace clang {
-
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
using AttrVec = SmallVector<Attr *, 4>;
diff --git a/include/clang/AST/AttrVisitor.h b/include/clang/AST/AttrVisitor.h
new file mode 100644
index 000000000000..867f9e7ad18d
--- /dev/null
+++ b/include/clang/AST/AttrVisitor.h
@@ -0,0 +1,76 @@
+//===- AttrVisitor.h - Visitor for Attr subclasses --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AttrVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ATTRVISITOR_H
+#define LLVM_CLANG_AST_ATTRVISITOR_H
+
+#include "clang/AST/Attr.h"
+
+namespace clang {
+
+namespace attrvisitor {
+
+/// A simple visitor class that helps create attribute visitors.
+template <template <typename> class Ptr, typename ImplClass,
+ typename RetTy = void, class... ParamTys>
+class Base {
+public:
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(NAME) \
+ return static_cast<ImplClass *>(this)->Visit##NAME(static_cast<PTR(NAME)>(A))
+
+ RetTy Visit(PTR(Attr) A) {
+ switch (A->getKind()) {
+
+#define ATTR(NAME) \
+ case attr::NAME: \
+ DISPATCH(NAME##Attr);
+#include "clang/Basic/AttrList.inc"
+ }
+ llvm_unreachable("Attr that isn't part of AttrList.inc!");
+ }
+
+ // If the implementation chooses not to implement a certain visit
+ // method, fall back to the parent.
+#define ATTR(NAME) \
+ RetTy Visit##NAME##Attr(PTR(NAME##Attr) A) { DISPATCH(Attr); }
+#include "clang/Basic/AttrList.inc"
+
+ RetTy VisitAttr(PTR(Attr)) { return RetTy(); }
+
+#undef PTR
+#undef DISPATCH
+};
+
+} // namespace attrvisitor
+
+/// A simple visitor class that helps create attribute visitors.
+///
+/// This class does not preserve constness of Attr pointers (see
+/// also ConstAttrVisitor).
+template <typename ImplClass, typename RetTy = void, typename... ParamTys>
+class AttrVisitor : public attrvisitor::Base<std::add_pointer, ImplClass, RetTy,
+ ParamTys...> {};
+
+/// A simple visitor class that helps create attribute visitors.
+///
+/// This class preserves constness of Attr pointers (see also
+/// AttrVisitor).
+template <typename ImplClass, typename RetTy = void, typename... ParamTys>
+class ConstAttrVisitor
+ : public attrvisitor::Base<llvm::make_const_ptr, ImplClass, RetTy,
+ ParamTys...> {};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_ATTRVISITOR_H
diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h
index 2b702c76b2fa..8fd4ac69ebd6 100644
--- a/include/clang/AST/BaseSubobject.h
+++ b/include/clang/AST/BaseSubobject.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_BASESUBOBJECT_H
#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/type_traits.h"
#include <cstdint>
diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt
index 942d08d585fe..da16987141c2 100644
--- a/include/clang/AST/CMakeLists.txt
+++ b/include/clang/AST/CMakeLists.txt
@@ -8,10 +8,15 @@ clang_tablegen(AttrImpl.inc -gen-clang-attr-impl
SOURCE ../Basic/Attr.td
TARGET ClangAttrImpl)
-clang_tablegen(AttrDump.inc -gen-clang-attr-dump
+clang_tablegen(AttrTextNodeDump.inc -gen-clang-attr-text-node-dump
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
- TARGET ClangAttrDump)
+ TARGET ClangAttrTextDump)
+
+clang_tablegen(AttrNodeTraverse.inc -gen-clang-attr-node-traverse
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE ../Basic/Attr.td
+ TARGET ClangAttrTraverse)
clang_tablegen(AttrVisitor.inc -gen-clang-attr-ast-visitor
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 0e738da43ad4..c2f01e7d5460 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -510,7 +510,7 @@ struct CanProxyAdaptor<FunctionProtoType>
}
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getTypeQuals)
using param_type_iterator =
CanTypeIterator<FunctionProtoType::param_type_iterator>;
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index f5538dec2a14..1b590562e152 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -215,13 +215,9 @@ public:
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return Range.getBegin();
- }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return Range.getEnd();
- }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceLocation getLocation() const LLVM_READONLY { return Loc; }
@@ -351,8 +347,7 @@ public:
}
SourceRange getCommandNameRange() const {
- return SourceRange(getLocStart().getLocWithOffset(-1),
- getLocEnd());
+ return SourceRange(getBeginLoc().getLocWithOffset(-1), getEndLoc());
}
RenderKind getRenderKind() const {
@@ -566,9 +561,9 @@ public:
ParagraphCommentBits.IsWhitespaceValid = false;
- setSourceRange(SourceRange(Content.front()->getLocStart(),
- Content.back()->getLocEnd()));
- setLocation(Content.front()->getLocStart());
+ setSourceRange(SourceRange(Content.front()->getBeginLoc(),
+ Content.back()->getEndLoc()));
+ setLocation(Content.front()->getBeginLoc());
}
static bool classof(const Comment *C) {
@@ -662,13 +657,13 @@ public:
}
SourceLocation getCommandNameBeginLoc() const {
- return getLocStart().getLocWithOffset(1);
+ return getBeginLoc().getLocWithOffset(1);
}
SourceRange getCommandNameRange(const CommandTraits &Traits) const {
StringRef Name = getCommandName(Traits);
return SourceRange(getCommandNameBeginLoc(),
- getLocStart().getLocWithOffset(1 + Name.size()));
+ getBeginLoc().getLocWithOffset(1 + Name.size()));
}
unsigned getNumArgs() const {
@@ -688,7 +683,7 @@ public:
if (Args.size() > 0) {
SourceLocation NewLocEnd = Args.back().Range.getEnd();
if (NewLocEnd.isValid())
- setSourceRange(SourceRange(getLocStart(), NewLocEnd));
+ setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
}
}
@@ -702,9 +697,9 @@ public:
void setParagraph(ParagraphComment *PC) {
Paragraph = PC;
- SourceLocation NewLocEnd = PC->getLocEnd();
+ SourceLocation NewLocEnd = PC->getEndLoc();
if (NewLocEnd.isValid())
- setSourceRange(SourceRange(getLocStart(), NewLocEnd));
+ setSourceRange(SourceRange(getBeginLoc(), NewLocEnd));
}
CommandMarkerKind getCommandMarker() const LLVM_READONLY {
@@ -978,7 +973,7 @@ public:
}
SourceRange getTextRange() const {
- return SourceRange(TextBegin, getLocEnd());
+ return SourceRange(TextBegin, getEndLoc());
}
};
@@ -1105,9 +1100,9 @@ public:
if (Blocks.empty())
return;
- setSourceRange(SourceRange(Blocks.front()->getLocStart(),
- Blocks.back()->getLocEnd()));
- setLocation(Blocks.front()->getLocStart());
+ setSourceRange(
+ SourceRange(Blocks.front()->getBeginLoc(), Blocks.back()->getEndLoc()));
+ setLocation(Blocks.front()->getBeginLoc());
}
static bool classof(const Comment *C) {
diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h
index f3a209bf6e7c..b9816f1a8e62 100644
--- a/include/clang/AST/CommentDiagnostic.h
+++ b/include/clang/AST/CommentDiagnostic.h
@@ -10,20 +10,7 @@
#ifndef LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define COMMENTSTART
-#include "clang/Basic/DiagnosticCommentKinds.inc"
-#undef DIAG
- NUM_BUILTIN_COMMENT_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticComment.h"
#endif
diff --git a/include/clang/AST/CommentVisitor.h b/include/clang/AST/CommentVisitor.h
index d1cc2d0a4e5e..e37e9d6cd299 100644
--- a/include/clang/AST/CommentVisitor.h
+++ b/include/clang/AST/CommentVisitor.h
@@ -11,22 +11,21 @@
#define LLVM_CLANG_AST_COMMENTVISITOR_H
#include "clang/AST/Comment.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace comments {
-
-template <typename T> struct make_ptr { using type = T *; };
-template <typename T> struct make_const_ptr { using type = const T *; };
-
-template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
+template <template <typename> class Ptr, typename ImplClass,
+ typename RetTy = void, class... ParamTys>
class CommentVisitorBase {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
-#define DISPATCH(NAME, CLASS) \
- return static_cast<ImplClass*>(this)->visit ## NAME(static_cast<PTR(CLASS)>(C))
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass *>(this)->visit##NAME( \
+ static_cast<PTR(CLASS)>(C), std::forward<ParamTys>(P)...)
- RetTy visit(PTR(Comment) C) {
+ RetTy visit(PTR(Comment) C, ParamTys... P) {
if (!C)
return RetTy();
@@ -44,25 +43,26 @@ public:
// If the derived class does not implement a certain Visit* method, fall back
// on Visit* method for the superclass.
#define ABSTRACT_COMMENT(COMMENT) COMMENT
-#define COMMENT(CLASS, PARENT) \
- RetTy visit ## CLASS(PTR(CLASS) C) { DISPATCH(PARENT, PARENT); }
+#define COMMENT(CLASS, PARENT) \
+ RetTy visit##CLASS(PTR(CLASS) C, ParamTys... P) { DISPATCH(PARENT, PARENT); }
#include "clang/AST/CommentNodes.inc"
#undef ABSTRACT_COMMENT
#undef COMMENT
- RetTy visitComment(PTR(Comment) C) { return RetTy(); }
+ RetTy visitComment(PTR(Comment) C, ParamTys... P) { return RetTy(); }
#undef PTR
#undef DISPATCH
};
-template<typename ImplClass, typename RetTy=void>
-class CommentVisitor :
- public CommentVisitorBase<make_ptr, ImplClass, RetTy> {};
+template <typename ImplClass, typename RetTy = void, class... ParamTys>
+class CommentVisitor : public CommentVisitorBase<std::add_pointer, ImplClass,
+ RetTy, ParamTys...> {};
-template<typename ImplClass, typename RetTy=void>
-class ConstCommentVisitor :
- public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {};
+template <typename ImplClass, typename RetTy = void, class... ParamTys>
+class ConstCommentVisitor
+ : public CommentVisitorBase<llvm::make_const_ptr, ImplClass, RetTy,
+ ParamTys...> {};
} // namespace comments
} // namespace clang
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index ebdb2890daf5..de2765391f0f 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECL_H
#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContextAllocate.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
@@ -81,7 +82,7 @@ class VarTemplateDecl;
/// A client can read the relevant info using TypeLoc wrappers, e.g:
/// @code
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
-/// TL.getStartLoc().print(OS, SrcMgr);
+/// TL.getBeginLoc().print(OS, SrcMgr);
/// @endcode
class alignas(8) TypeSourceInfo {
// Contains a memory block after the class, used for type source information,
@@ -614,7 +615,7 @@ public:
return SourceRange(LocStart, RBraceLoc);
}
- SourceLocation getLocStart() const LLVM_READONLY { return LocStart; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LocStart; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setLocStart(SourceLocation L) { LocStart = L; }
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
@@ -735,7 +736,7 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY;
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
return getOuterLocStart();
}
@@ -866,8 +867,12 @@ private:
unsigned SClass : 3;
unsigned TSCSpec : 2;
unsigned InitStyle : 2;
+
+ /// Whether this variable is an ARC pseudo-__strong variable; see
+ /// isARCPseudoStrong() for details.
+ unsigned ARCPseudoStrong : 1;
};
- enum { NumVarDeclBits = 7 };
+ enum { NumVarDeclBits = 8 };
protected:
enum { NumParameterIndexBits = 8 };
@@ -940,10 +945,6 @@ protected:
/// Whether this variable is the for-in loop declaration in Objective-C.
unsigned ObjCForDecl : 1;
- /// Whether this variable is an ARC pseudo-__strong
- /// variable; see isARCPseudoStrong() for details.
- unsigned ARCPseudoStrong : 1;
-
/// Whether this variable is (C++1z) inline.
unsigned IsInline : 1;
@@ -965,6 +966,8 @@ protected:
/// Defines kind of the ImplicitParamDecl: 'this', 'self', 'vtt', '_cmd' or
/// something else.
unsigned ImplicitParamKind : 3;
+
+ unsigned EscapingByref : 1;
};
union {
@@ -1347,17 +1350,15 @@ public:
NonParmVarDeclBits.ObjCForDecl = FRD;
}
- /// Determine whether this variable is an ARC pseudo-__strong
- /// variable. A pseudo-__strong variable has a __strong-qualified
- /// type but does not actually retain the object written into it.
- /// Generally such variables are also 'const' for safety.
- bool isARCPseudoStrong() const {
- return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ARCPseudoStrong;
- }
- void setARCPseudoStrong(bool ps) {
- assert(!isa<ParmVarDecl>(this));
- NonParmVarDeclBits.ARCPseudoStrong = ps;
- }
+ /// Determine whether this variable is an ARC pseudo-__strong variable. A
+ /// pseudo-__strong variable has a __strong-qualified type but does not
+ /// actually retain the object written into it. Generally such variables are
+ /// also 'const' for safety. There are 3 cases where this will be set, 1) if
+ /// the variable is annotated with the objc_externally_retained attribute, 2)
+ /// if its 'self' in a non-init method, or 3) if its the variable in an for-in
+ /// loop.
+ bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; }
+ void setARCPseudoStrong(bool PS) { VarDeclBits.ARCPseudoStrong = PS; }
/// Whether this variable is (C++1z) inline.
bool isInline() const {
@@ -1407,6 +1408,19 @@ public:
NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same;
}
+ /// Indicates the capture is a __block variable that is captured by a block
+ /// that can potentially escape (a block for which BlockDecl::doesNotEscape
+ /// returns false).
+ bool isEscapingByref() const;
+
+ /// Indicates the capture is a __block variable that is never captured by an
+ /// escaping block.
+ bool isNonEscapingByref() const;
+
+ void setEscapingByref() {
+ NonParmVarDeclBits.EscapingByref = true;
+ }
+
/// Retrieve the variable declaration from which this variable could
/// be instantiated, if it is an instantiation (rather than a non-template).
VarDecl *getTemplateInstantiationPattern() const;
@@ -1461,6 +1475,9 @@ public:
// has no definition within this source file.
bool isKnownToBeDefined() const;
+ /// Do we need to emit an exit-time destructor for this variable?
+ bool isNoDestroy(const ASTContext &) const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }
@@ -1701,6 +1718,13 @@ private:
unsigned getParameterIndexLarge() const;
};
+enum class MultiVersionKind {
+ None,
+ Target,
+ CPUSpecific,
+ CPUDispatch
+};
+
/// Represents a function declaration or definition.
///
/// Since a given function can be declared several times in a program,
@@ -1711,8 +1735,11 @@ private:
/// contains all of the information known about the function. Other,
/// previous declarations of the function are available via the
/// getPreviousDecl() chain.
-class FunctionDecl : public DeclaratorDecl, public DeclContext,
+class FunctionDecl : public DeclaratorDecl,
+ public DeclContext,
public Redeclarable<FunctionDecl> {
+ // This class stores some data in DeclContext::FunctionDeclBits
+ // to save some space. Use the provided accessors to access it.
public:
/// The kind of templated function a FunctionDecl can be.
enum TemplatedKind {
@@ -1731,64 +1758,6 @@ private:
LazyDeclStmtPtr Body;
- // FIXME: This can be packed into the bitfields in DeclContext.
- // NOTE: VC++ packs bitfields poorly if the types differ.
- unsigned SClass : 3;
- unsigned IsInline : 1;
- unsigned IsInlineSpecified : 1;
-
-protected:
- // This is shared by CXXConstructorDecl, CXXConversionDecl, and
- // CXXDeductionGuideDecl.
- unsigned IsExplicitSpecified : 1;
-
-private:
- unsigned IsVirtualAsWritten : 1;
- unsigned IsPure : 1;
- unsigned HasInheritedPrototype : 1;
- unsigned HasWrittenPrototype : 1;
- unsigned IsDeleted : 1;
- unsigned IsTrivial : 1; // sunk from CXXMethodDecl
-
- /// This flag indicates whether this function is trivial for the purpose of
- /// calls. This is meaningful only when this function is a copy/move
- /// constructor or a destructor.
- unsigned IsTrivialForCall : 1;
-
- unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
- unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
- unsigned HasImplicitReturnZero : 1;
- unsigned IsLateTemplateParsed : 1;
- unsigned IsConstexpr : 1;
- unsigned InstantiationIsPending : 1;
-
- /// Indicates if the function uses __try.
- unsigned UsesSEHTry : 1;
-
- /// Indicates if the function was a definition but its body was
- /// skipped.
- unsigned HasSkippedBody : 1;
-
- /// Indicates if the function declaration will have a body, once we're done
- /// parsing it.
- unsigned WillHaveBody : 1;
-
- /// Indicates that this function is a multiversioned function using attribute
- /// 'target'.
- unsigned IsMultiVersion : 1;
-
-protected:
- /// [C++17] Only used by CXXDeductionGuideDecl. Declared here to avoid
- /// increasing the size of CXXDeductionGuideDecl by the size of an unsigned
- /// int as opposed to adding a single bit to FunctionDecl.
- /// Indicates that the Deduction Guide is the implicitly generated 'copy
- /// deduction candidate' (is used during overload resolution).
- unsigned IsCopyDeductionCandidate : 1;
-
-private:
-
- /// Store the ODRHash after first calculation.
- unsigned HasODRHash : 1;
unsigned ODRHash;
/// End part of this FunctionDecl's source range.
@@ -1858,25 +1827,22 @@ private:
void setParams(ASTContext &C, ArrayRef<ParmVarDecl *> NewParamInfo);
+ // This is unfortunately needed because ASTDeclWriter::VisitFunctionDecl
+ // need to access this bit but we want to avoid making ASTDeclWriter
+ // a friend of FunctionDeclBitfields just for this.
+ bool isDeletedBit() const { return FunctionDeclBits.IsDeleted; }
+
+ /// Whether an ODRHash has been stored.
+ bool hasODRHash() const { return FunctionDeclBits.HasODRHash; }
+
+ /// State that an ODRHash has been stored.
+ void setHasODRHash(bool B = true) { FunctionDeclBits.HasODRHash = B; }
+
protected:
FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified,
- bool isConstexprSpecified)
- : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
- StartLoc),
- DeclContext(DK), redeclarable_base(C), SClass(S),
- IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
- IsExplicitSpecified(false), IsVirtualAsWritten(false), IsPure(false),
- HasInheritedPrototype(false), HasWrittenPrototype(true),
- IsDeleted(false), IsTrivial(false), IsTrivialForCall(false),
- IsDefaulted(false),
- IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
- IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
- InstantiationIsPending(false), UsesSEHTry(false), HasSkippedBody(false),
- WillHaveBody(false), IsMultiVersion(false),
- IsCopyDeductionCandidate(false), HasODRHash(false), ODRHash(0),
- EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {}
+ bool isConstexprSpecified);
using redeclarable_base = Redeclarable<FunctionDecl>;
@@ -2015,13 +1981,13 @@ public:
/// This does not determine whether the function has been defined (e.g., in a
/// previous definition); for that information, use isDefined.
bool isThisDeclarationADefinition() const {
- return IsDeleted || IsDefaulted || Body || HasSkippedBody ||
- IsLateTemplateParsed || WillHaveBody || hasDefiningAttr();
+ return isDeletedAsWritten() || isDefaulted() || Body || hasSkippedBody() ||
+ isLateTemplateParsed() || willHaveBody() || hasDefiningAttr();
}
/// Returns whether this specific declaration of the function has a body.
bool doesThisDeclarationHaveABody() const {
- return Body || IsLateTemplateParsed;
+ return Body || isLateTemplateParsed();
}
void setBody(Stmt *B);
@@ -2031,62 +1997,102 @@ public:
bool isVariadic() const;
/// Whether this function is marked as virtual explicitly.
- bool isVirtualAsWritten() const { return IsVirtualAsWritten; }
- void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; }
+ bool isVirtualAsWritten() const {
+ return FunctionDeclBits.IsVirtualAsWritten;
+ }
+
+ /// State that this function is marked as virtual explicitly.
+ void setVirtualAsWritten(bool V) { FunctionDeclBits.IsVirtualAsWritten = V; }
/// Whether this virtual function is pure, i.e. makes the containing class
/// abstract.
- bool isPure() const { return IsPure; }
+ bool isPure() const { return FunctionDeclBits.IsPure; }
void setPure(bool P = true);
/// Whether this templated function will be late parsed.
- bool isLateTemplateParsed() const { return IsLateTemplateParsed; }
- void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; }
+ bool isLateTemplateParsed() const {
+ return FunctionDeclBits.IsLateTemplateParsed;
+ }
+
+ /// State that this templated function will be late parsed.
+ void setLateTemplateParsed(bool ILT = true) {
+ FunctionDeclBits.IsLateTemplateParsed = ILT;
+ }
/// Whether this function is "trivial" in some specialized C++ senses.
/// Can only be true for default constructors, copy constructors,
/// copy assignment operators, and destructors. Not meaningful until
/// the class has been fully built by Sema.
- bool isTrivial() const { return IsTrivial; }
- void setTrivial(bool IT) { IsTrivial = IT; }
+ bool isTrivial() const { return FunctionDeclBits.IsTrivial; }
+ void setTrivial(bool IT) { FunctionDeclBits.IsTrivial = IT; }
- bool isTrivialForCall() const { return IsTrivialForCall; }
- void setTrivialForCall(bool IT) { IsTrivialForCall = IT; }
+ bool isTrivialForCall() const { return FunctionDeclBits.IsTrivialForCall; }
+ void setTrivialForCall(bool IT) { FunctionDeclBits.IsTrivialForCall = IT; }
/// Whether this function is defaulted per C++0x. Only valid for
/// special member functions.
- bool isDefaulted() const { return IsDefaulted; }
- void setDefaulted(bool D = true) { IsDefaulted = D; }
+ bool isDefaulted() const { return FunctionDeclBits.IsDefaulted; }
+ void setDefaulted(bool D = true) { FunctionDeclBits.IsDefaulted = D; }
/// Whether this function is explicitly defaulted per C++0x. Only valid
/// for special member functions.
- bool isExplicitlyDefaulted() const { return IsExplicitlyDefaulted; }
- void setExplicitlyDefaulted(bool ED = true) { IsExplicitlyDefaulted = ED; }
+ bool isExplicitlyDefaulted() const {
+ return FunctionDeclBits.IsExplicitlyDefaulted;
+ }
+
+ /// State that this function is explicitly defaulted per C++0x. Only valid
+ /// for special member functions.
+ void setExplicitlyDefaulted(bool ED = true) {
+ FunctionDeclBits.IsExplicitlyDefaulted = ED;
+ }
/// Whether falling off this function implicitly returns null/zero.
/// If a more specific implicit return value is required, front-ends
/// should synthesize the appropriate return statements.
- bool hasImplicitReturnZero() const { return HasImplicitReturnZero; }
- void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; }
+ bool hasImplicitReturnZero() const {
+ return FunctionDeclBits.HasImplicitReturnZero;
+ }
+
+ /// State that falling off this function implicitly returns null/zero.
+ /// If a more specific implicit return value is required, front-ends
+ /// should synthesize the appropriate return statements.
+ void setHasImplicitReturnZero(bool IRZ) {
+ FunctionDeclBits.HasImplicitReturnZero = IRZ;
+ }
/// Whether this function has a prototype, either because one
/// was explicitly written or because it was "inherited" by merging
/// a declaration without a prototype with a declaration that has a
/// prototype.
bool hasPrototype() const {
- return HasWrittenPrototype || HasInheritedPrototype;
+ return hasWrittenPrototype() || hasInheritedPrototype();
+ }
+
+ /// Whether this function has a written prototype.
+ bool hasWrittenPrototype() const {
+ return FunctionDeclBits.HasWrittenPrototype;
}
- bool hasWrittenPrototype() const { return HasWrittenPrototype; }
+ /// State that this function has a written prototype.
+ void setHasWrittenPrototype(bool P = true) {
+ FunctionDeclBits.HasWrittenPrototype = P;
+ }
/// Whether this function inherited its prototype from a
/// previous declaration.
- bool hasInheritedPrototype() const { return HasInheritedPrototype; }
- void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; }
+ bool hasInheritedPrototype() const {
+ return FunctionDeclBits.HasInheritedPrototype;
+ }
+
+ /// State that this function inherited its prototype from a
+ /// previous declaration.
+ void setHasInheritedPrototype(bool P = true) {
+ FunctionDeclBits.HasInheritedPrototype = P;
+ }
/// Whether this is a (C++11) constexpr function or constexpr constructor.
- bool isConstexpr() const { return IsConstexpr; }
- void setConstexpr(bool IC) { IsConstexpr = IC; }
+ bool isConstexpr() const { return FunctionDeclBits.IsConstexpr; }
+ void setConstexpr(bool IC) { FunctionDeclBits.IsConstexpr = IC; }
/// Whether the instantiation of this function is pending.
/// This bit is set when the decision to instantiate this function is made
@@ -2094,12 +2100,19 @@ public:
/// cases where instantiation did not happen because the template definition
/// was not seen in this TU. This bit remains set in those cases, under the
/// assumption that the instantiation will happen in some other TU.
- bool instantiationIsPending() const { return InstantiationIsPending; }
- void setInstantiationIsPending(bool IC) { InstantiationIsPending = IC; }
+ bool instantiationIsPending() const {
+ return FunctionDeclBits.InstantiationIsPending;
+ }
+
+ /// State that the instantiation of this function is pending.
+ /// (see instantiationIsPending)
+ void setInstantiationIsPending(bool IC) {
+ FunctionDeclBits.InstantiationIsPending = IC;
+ }
/// Indicates the function uses __try.
- bool usesSEHTry() const { return UsesSEHTry; }
- void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
+ bool usesSEHTry() const { return FunctionDeclBits.UsesSEHTry; }
+ void setUsesSEHTry(bool UST) { FunctionDeclBits.UsesSEHTry = UST; }
/// Whether this function has been deleted.
///
@@ -2120,9 +2133,15 @@ public:
/// };
/// @endcode
// If a function is deleted, its first declaration must be.
- bool isDeleted() const { return getCanonicalDecl()->IsDeleted; }
- bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; }
- void setDeletedAsWritten(bool D = true) { IsDeleted = D; }
+ bool isDeleted() const {
+ return getCanonicalDecl()->FunctionDeclBits.IsDeleted;
+ }
+
+ bool isDeletedAsWritten() const {
+ return FunctionDeclBits.IsDeleted && !isDefaulted();
+ }
+
+ void setDeletedAsWritten(bool D = true) { FunctionDeclBits.IsDeleted = D; }
/// Determines whether this function is "main", which is the
/// entry point into an executable program.
@@ -2193,22 +2212,32 @@ public:
bool isNoReturn() const;
/// True if the function was a definition but its body was skipped.
- bool hasSkippedBody() const { return HasSkippedBody; }
- void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
+ bool hasSkippedBody() const { return FunctionDeclBits.HasSkippedBody; }
+ void setHasSkippedBody(bool Skipped = true) {
+ FunctionDeclBits.HasSkippedBody = Skipped;
+ }
/// True if this function will eventually have a body, once it's fully parsed.
- bool willHaveBody() const { return WillHaveBody; }
- void setWillHaveBody(bool V = true) { WillHaveBody = V; }
+ bool willHaveBody() const { return FunctionDeclBits.WillHaveBody; }
+ void setWillHaveBody(bool V = true) { FunctionDeclBits.WillHaveBody = V; }
/// True if this function is considered a multiversioned function.
- bool isMultiVersion() const { return getCanonicalDecl()->IsMultiVersion; }
+ bool isMultiVersion() const {
+ return getCanonicalDecl()->FunctionDeclBits.IsMultiVersion;
+ }
/// Sets the multiversion state for this declaration and all of its
/// redeclarations.
void setIsMultiVersion(bool V = true) {
- getCanonicalDecl()->IsMultiVersion = V;
+ getCanonicalDecl()->FunctionDeclBits.IsMultiVersion = V;
}
+ /// Gets the kind of multiversioning attribute this declaration has. Note that
+ /// this can return a value even if the function is not multiversion, such as
+ /// the case of 'target'.
+ MultiVersionKind getMultiVersionKind() const;
+
+
/// True if this function is a multiversioned dispatch function as a part of
/// the cpu_specific/cpu_dispatch functionality.
bool isCPUDispatchMultiVersion() const;
@@ -2216,6 +2245,10 @@ public:
/// part of the cpu_specific/cpu_dispatch functionality.
bool isCPUSpecificMultiVersion() const;
+ /// True if this function is a multiversioned dispatch function as a part of
+ /// the target functionality.
+ bool isTargetMultiVersion() const;
+
void setPreviousDeclaration(FunctionDecl * PrevDecl);
FunctionDecl *getCanonicalDecl() override;
@@ -2267,8 +2300,7 @@ public:
unsigned getMinRequiredArguments() const;
QualType getReturnType() const {
- assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
- return getType()->getAs<FunctionType>()->getReturnType();
+ return getType()->castAs<FunctionType>()->getReturnType();
}
/// Attempt to compute an informative source range covering the
@@ -2276,47 +2308,62 @@ public:
/// limited representation in the AST.
SourceRange getReturnTypeSourceRange() const;
+ /// Get the declared return type, which may differ from the actual return
+ /// type if the return type is deduced.
+ QualType getDeclaredReturnType() const {
+ auto *TSI = getTypeSourceInfo();
+ QualType T = TSI ? TSI->getType() : getType();
+ return T->castAs<FunctionType>()->getReturnType();
+ }
+
/// Attempt to compute an informative source range covering the
/// function exception specification, if any.
SourceRange getExceptionSpecSourceRange() const;
/// Determine the type of an expression that calls this function.
QualType getCallResultType() const {
- assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
- return getType()->getAs<FunctionType>()->getCallResultType(getASTContext());
+ return getType()->castAs<FunctionType>()->getCallResultType(
+ getASTContext());
}
- /// Returns the WarnUnusedResultAttr that is either declared on this
- /// function, or its return type declaration.
- const Attr *getUnusedResultAttr() const;
-
- /// Returns true if this function or its return type has the
- /// warn_unused_result attribute.
- bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; }
-
/// Returns the storage class as written in the source. For the
/// computed linkage of symbol, see getLinkage.
- StorageClass getStorageClass() const { return StorageClass(SClass); }
+ StorageClass getStorageClass() const {
+ return static_cast<StorageClass>(FunctionDeclBits.SClass);
+ }
+
+ /// Sets the storage class as written in the source.
+ void setStorageClass(StorageClass SClass) {
+ FunctionDeclBits.SClass = SClass;
+ }
/// Determine whether the "inline" keyword was specified for this
/// function.
- bool isInlineSpecified() const { return IsInlineSpecified; }
+ bool isInlineSpecified() const { return FunctionDeclBits.IsInlineSpecified; }
/// Set whether the "inline" keyword was specified for this function.
void setInlineSpecified(bool I) {
- IsInlineSpecified = I;
- IsInline = I;
+ FunctionDeclBits.IsInlineSpecified = I;
+ FunctionDeclBits.IsInline = I;
}
/// Flag that this function is implicitly inline.
- void setImplicitlyInline() {
- IsInline = true;
- }
+ void setImplicitlyInline(bool I = true) { FunctionDeclBits.IsInline = I; }
/// Determine whether this function should be inlined, because it is
/// either marked "inline" or "constexpr" or is a member function of a class
/// that was defined in the class body.
- bool isInlined() const { return IsInline; }
+ bool isInlined() const { return FunctionDeclBits.IsInline; }
+
+ /// Whether this function is marked as explicit explicitly.
+ bool isExplicitSpecified() const {
+ return FunctionDeclBits.IsExplicitSpecified;
+ }
+
+ /// State that this function is marked as explicit explicitly.
+ void setExplicitSpecified(bool ExpSpec = true) {
+ FunctionDeclBits.IsExplicitSpecified = ExpSpec;
+ }
bool isInlineDefinitionExternallyVisible() const;
@@ -2851,7 +2898,7 @@ public:
const Type *getTypeForDecl() const { return TypeForDecl; }
void setTypeForDecl(const Type *TD) { TypeForDecl = TD; }
- SourceLocation getLocStart() const LLVM_READONLY { return LocStart; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LocStart; }
void setLocStart(SourceLocation L) { LocStart = L; }
SourceRange getSourceRange() const override LLVM_READONLY {
if (LocStart.isValid())
@@ -3014,64 +3061,16 @@ public:
};
/// Represents the declaration of a struct/union/class/enum.
-class TagDecl
- : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
+class TagDecl : public TypeDecl,
+ public DeclContext,
+ public Redeclarable<TagDecl> {
+ // This class stores some data in DeclContext::TagDeclBits
+ // to save some space. Use the provided accessors to access it.
public:
// This is really ugly.
using TagKind = TagTypeKind;
private:
- // FIXME: This can be packed into the bitfields in Decl.
- /// The TagKind enum.
- unsigned TagDeclKind : 3;
-
- /// True if this is a definition ("struct foo {};"), false if it is a
- /// declaration ("struct foo;"). It is not considered a definition
- /// until the definition has been fully processed.
- unsigned IsCompleteDefinition : 1;
-
-protected:
- /// True if this is currently being defined.
- unsigned IsBeingDefined : 1;
-
-private:
- /// True if this tag declaration is "embedded" (i.e., defined or declared
- /// for the very first time) in the syntax of a declarator.
- unsigned IsEmbeddedInDeclarator : 1;
-
- /// True if this tag is free standing, e.g. "struct foo;".
- unsigned IsFreeStanding : 1;
-
-protected:
- // These are used by (and only defined for) EnumDecl.
- unsigned NumPositiveBits : 8;
- unsigned NumNegativeBits : 8;
-
- /// True if this tag declaration is a scoped enumeration. Only
- /// possible in C++11 mode.
- unsigned IsScoped : 1;
-
- /// If this tag declaration is a scoped enum,
- /// then this is true if the scoped enum was declared using the class
- /// tag, false if it was declared with the struct tag. No meaning is
- /// associated if this tag declaration is not a scoped enum.
- unsigned IsScopedUsingClassTag : 1;
-
- /// True if this is an enumeration with fixed underlying type. Only
- /// possible in C++11, Microsoft extensions, or Objective C mode.
- unsigned IsFixed : 1;
-
- /// Indicates whether it is possible for declarations of this kind
- /// to have an out-of-date definition.
- ///
- /// This option is only enabled when modules are enabled.
- unsigned MayHaveOutOfDateDef : 1;
-
- /// Has the full definition of this type been required by a use somewhere in
- /// the TU.
- unsigned IsCompleteDefinitionRequired : 1;
-
-private:
SourceRange BraceRange;
// A struct representing syntactic qualifier info,
@@ -3097,16 +3096,7 @@ private:
protected:
TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
- SourceLocation StartL)
- : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
- TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
- IsEmbeddedInDeclarator(false), IsFreeStanding(false),
- IsCompleteDefinitionRequired(false),
- TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
- assert((DK != Enum || TK == TTK_Enum) &&
- "EnumDecl not matched with TTK_Enum");
- setPreviousDecl(PrevDecl);
- }
+ SourceLocation StartL);
using redeclarable_base = Redeclarable<TagDecl>;
@@ -3127,6 +3117,17 @@ protected:
/// This is a helper function for derived classes.
void completeDefinition();
+ /// True if this decl is currently being defined.
+ void setBeingDefined(bool V = true) { TagDeclBits.IsBeingDefined = V; }
+
+ /// Indicates whether it is possible for declarations of this kind
+ /// to have an out-of-date definition.
+ ///
+ /// This option is only enabled when modules are enabled.
+ void setMayHaveOutOfDateDef(bool V = true) {
+ TagDeclBits.MayHaveOutOfDateDef = V;
+ }
+
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
@@ -3146,7 +3147,7 @@ public:
/// Return SourceLocation representing start of source
/// range ignoring outer template declarations.
- SourceLocation getInnerLocStart() const { return getLocStart(); }
+ SourceLocation getInnerLocStart() const { return getBeginLoc(); }
/// Return SourceLocation representing start of source
/// range taking into account any outer template declarations.
@@ -3165,33 +3166,54 @@ public:
}
/// Return true if this decl has its body fully specified.
- bool isCompleteDefinition() const {
- return IsCompleteDefinition;
+ bool isCompleteDefinition() const { return TagDeclBits.IsCompleteDefinition; }
+
+ /// True if this decl has its body fully specified.
+ void setCompleteDefinition(bool V = true) {
+ TagDeclBits.IsCompleteDefinition = V;
}
/// Return true if this complete decl is
/// required to be complete for some existing use.
bool isCompleteDefinitionRequired() const {
- return IsCompleteDefinitionRequired;
+ return TagDeclBits.IsCompleteDefinitionRequired;
}
- /// Return true if this decl is currently being defined.
- bool isBeingDefined() const {
- return IsBeingDefined;
+ /// True if this complete decl is
+ /// required to be complete for some existing use.
+ void setCompleteDefinitionRequired(bool V = true) {
+ TagDeclBits.IsCompleteDefinitionRequired = V;
}
+ /// Return true if this decl is currently being defined.
+ bool isBeingDefined() const { return TagDeclBits.IsBeingDefined; }
+
+ /// True if this tag declaration is "embedded" (i.e., defined or declared
+ /// for the very first time) in the syntax of a declarator.
bool isEmbeddedInDeclarator() const {
- return IsEmbeddedInDeclarator;
+ return TagDeclBits.IsEmbeddedInDeclarator;
}
+
+ /// True if this tag declaration is "embedded" (i.e., defined or declared
+ /// for the very first time) in the syntax of a declarator.
void setEmbeddedInDeclarator(bool isInDeclarator) {
- IsEmbeddedInDeclarator = isInDeclarator;
+ TagDeclBits.IsEmbeddedInDeclarator = isInDeclarator;
}
- bool isFreeStanding() const { return IsFreeStanding; }
+ /// True if this tag is free standing, e.g. "struct foo;".
+ bool isFreeStanding() const { return TagDeclBits.IsFreeStanding; }
+
+ /// True if this tag is free standing, e.g. "struct foo;".
void setFreeStanding(bool isFreeStanding = true) {
- IsFreeStanding = isFreeStanding;
+ TagDeclBits.IsFreeStanding = isFreeStanding;
}
+ /// Indicates whether it is possible for declarations of this kind
+ /// to have an out-of-date definition.
+ ///
+ /// This option is only enabled when modules are enabled.
+ bool mayHaveOutOfDateDef() const { return TagDeclBits.MayHaveOutOfDateDef; }
+
/// Whether this declaration declares a type that is
/// dependent, i.e., a type that somehow depends on template
/// parameters.
@@ -3214,21 +3236,15 @@ public:
/// the struct/union/class/enum.
TagDecl *getDefinition() const;
- void setCompleteDefinition(bool V) { IsCompleteDefinition = V; }
-
- void setCompleteDefinitionRequired(bool V = true) {
- IsCompleteDefinitionRequired = V;
- }
-
StringRef getKindName() const {
return TypeWithKeyword::getTagTypeKindName(getTagKind());
}
TagKind getTagKind() const {
- return TagKind(TagDeclKind);
+ return static_cast<TagKind>(TagDeclBits.TagDeclKind);
}
- void setTagKind(TagKind TK) { TagDeclKind = TK; }
+ void setTagKind(TagKind TK) { TagDeclBits.TagDeclKind = TK; }
bool isStruct() const { return getTagKind() == TTK_Struct; }
bool isInterface() const { return getTagKind() == TTK_Interface; }
@@ -3308,6 +3324,9 @@ public:
/// with a fixed underlying type, and in C we allow them to be forward-declared
/// with no underlying type as an extension.
class EnumDecl : public TagDecl {
+ // This class stores some data in DeclContext::EnumDeclBits
+ // to save some space. Use the provided accessors to access it.
+
/// This represent the integer type that the enum corresponds
/// to for code generation purposes. Note that the enumerator constants may
/// have a different type than this does.
@@ -3336,28 +3355,50 @@ class EnumDecl : public TagDecl {
MemberSpecializationInfo *SpecializationInfo = nullptr;
/// Store the ODRHash after first calculation.
- unsigned HasODRHash : 1;
+ /// The corresponding flag HasODRHash is in EnumDeclBits
+ /// and can be accessed with the provided accessors.
unsigned ODRHash;
EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
- bool Scoped, bool ScopedUsingClassTag, bool Fixed)
- : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
- assert(Scoped || !ScopedUsingClassTag);
- IntegerType = (const Type *)nullptr;
- NumNegativeBits = 0;
- NumPositiveBits = 0;
- IsScoped = Scoped;
- IsScopedUsingClassTag = ScopedUsingClassTag;
- IsFixed = Fixed;
- HasODRHash = false;
- ODRHash = 0;
- }
+ bool Scoped, bool ScopedUsingClassTag, bool Fixed);
void anchor() override;
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
TemplateSpecializationKind TSK);
+
+ /// Sets the width in bits required to store all the
+ /// non-negative enumerators of this enum.
+ void setNumPositiveBits(unsigned Num) {
+ EnumDeclBits.NumPositiveBits = Num;
+ assert(EnumDeclBits.NumPositiveBits == Num && "can't store this bitcount");
+ }
+
+ /// Returns the width in bits required to store all the
+ /// negative enumerators of this enum. (see getNumNegativeBits)
+ void setNumNegativeBits(unsigned Num) { EnumDeclBits.NumNegativeBits = Num; }
+
+ /// True if this tag declaration is a scoped enumeration. Only
+ /// possible in C++11 mode.
+ void setScoped(bool Scoped = true) { EnumDeclBits.IsScoped = Scoped; }
+
+ /// If this tag declaration is a scoped enum,
+ /// then this is true if the scoped enum was declared using the class
+ /// tag, false if it was declared with the struct tag. No meaning is
+ /// associated if this tag declaration is not a scoped enum.
+ void setScopedUsingClassTag(bool ScopedUCT = true) {
+ EnumDeclBits.IsScopedUsingClassTag = ScopedUCT;
+ }
+
+ /// True if this is an Objective-C, C++11, or
+ /// Microsoft-style enumeration with a fixed underlying type.
+ void setFixed(bool Fixed = true) { EnumDeclBits.IsFixed = Fixed; }
+
+ /// True if a valid hash is stored in ODRHash.
+ bool hasODRHash() const { return EnumDeclBits.HasODRHash; }
+ void setHasODRHash(bool Hash = true) { EnumDeclBits.HasODRHash = Hash; }
+
public:
friend class ASTDeclReader;
@@ -3462,13 +3503,7 @@ public:
/// Returns the width in bits required to store all the
/// non-negative enumerators of this enum.
- unsigned getNumPositiveBits() const {
- return NumPositiveBits;
- }
- void setNumPositiveBits(unsigned Num) {
- NumPositiveBits = Num;
- assert(NumPositiveBits == Num && "can't store this bitcount");
- }
+ unsigned getNumPositiveBits() const { return EnumDeclBits.NumPositiveBits; }
/// Returns the width in bits required to store all the
/// negative enumerators of this enum. These widths include
@@ -3479,28 +3514,19 @@ public:
/// -1 1111111 1
/// -10 1110110 5
/// -101 1001011 8
- unsigned getNumNegativeBits() const {
- return NumNegativeBits;
- }
- void setNumNegativeBits(unsigned Num) {
- NumNegativeBits = Num;
- }
+ unsigned getNumNegativeBits() const { return EnumDeclBits.NumNegativeBits; }
/// Returns true if this is a C++11 scoped enumeration.
- bool isScoped() const {
- return IsScoped;
- }
+ bool isScoped() const { return EnumDeclBits.IsScoped; }
/// Returns true if this is a C++11 scoped enumeration.
bool isScopedUsingClassTag() const {
- return IsScopedUsingClassTag;
+ return EnumDeclBits.IsScopedUsingClassTag;
}
/// Returns true if this is an Objective-C, C++11, or
/// Microsoft-style enumeration with a fixed underlying type.
- bool isFixed() const {
- return IsFixed;
- }
+ bool isFixed() const { return EnumDeclBits.IsFixed; }
unsigned getODRHash();
@@ -3565,7 +3591,10 @@ public:
/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
/// This decl will be marked invalid if *any* members are invalid.
class RecordDecl : public TagDecl {
+ // This class stores some data in DeclContext::RecordDeclBits
+ // to save some space. Use the provided accessors to access it.
public:
+ friend class DeclContext;
/// Enum that represents the different ways arguments are passed to and
/// returned from function calls. This takes into account the target-specific
/// and version-specific rules along with the rules determined by the
@@ -3589,46 +3618,6 @@ public:
APK_CanNeverPassInRegs
};
-private:
- friend class DeclContext;
-
- // FIXME: This can be packed into the bitfields in Decl.
- /// This is true if this struct ends with a flexible
- /// array member (e.g. int X[]) or if this union contains a struct that does.
- /// If so, this cannot be contained in arrays or other structs as a member.
- unsigned HasFlexibleArrayMember : 1;
-
- /// Whether this is the type of an anonymous struct or union.
- unsigned AnonymousStructOrUnion : 1;
-
- /// This is true if this struct has at least one member
- /// containing an Objective-C object pointer type.
- unsigned HasObjectMember : 1;
-
- /// This is true if struct has at least one member of
- /// 'volatile' type.
- unsigned HasVolatileMember : 1;
-
- /// Whether the field declarations of this record have been loaded
- /// from external storage. To avoid unnecessary deserialization of
- /// methods/nested types we allow deserialization of just the fields
- /// when needed.
- mutable unsigned LoadedFieldsFromExternalStorage : 1;
-
- /// Basic properties of non-trivial C structs.
- unsigned NonTrivialToPrimitiveDefaultInitialize : 1;
- unsigned NonTrivialToPrimitiveCopy : 1;
- unsigned NonTrivialToPrimitiveDestroy : 1;
-
- /// Indicates whether this struct is destroyed in the callee.
- ///
- /// Please note that MSVC won't merge adjacent bitfields if they don't have
- /// the same type.
- unsigned ParamDestroyedInCallee : 1;
-
- /// Represents the way this type is passed to a function.
- unsigned ArgPassingRestrictions : 2;
-
protected:
RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -3655,8 +3644,13 @@ public:
return const_cast<RecordDecl*>(this)->getMostRecentDecl();
}
- bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
- void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
+ bool hasFlexibleArrayMember() const {
+ return RecordDeclBits.HasFlexibleArrayMember;
+ }
+
+ void setHasFlexibleArrayMember(bool V) {
+ RecordDeclBits.HasFlexibleArrayMember = V;
+ }
/// Whether this is an anonymous struct or union. To be an anonymous
/// struct or union, it must have been declared without a name and
@@ -3669,47 +3663,54 @@ public:
/// union X { int i; float f; };
/// union { int i; float f; } obj;
/// @endcode
- bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; }
+ bool isAnonymousStructOrUnion() const {
+ return RecordDeclBits.AnonymousStructOrUnion;
+ }
+
void setAnonymousStructOrUnion(bool Anon) {
- AnonymousStructOrUnion = Anon;
+ RecordDeclBits.AnonymousStructOrUnion = Anon;
}
- bool hasObjectMember() const { return HasObjectMember; }
- void setHasObjectMember (bool val) { HasObjectMember = val; }
+ bool hasObjectMember() const { return RecordDeclBits.HasObjectMember; }
+ void setHasObjectMember(bool val) { RecordDeclBits.HasObjectMember = val; }
+
+ bool hasVolatileMember() const { return RecordDeclBits.HasVolatileMember; }
- bool hasVolatileMember() const { return HasVolatileMember; }
- void setHasVolatileMember (bool val) { HasVolatileMember = val; }
+ void setHasVolatileMember(bool val) {
+ RecordDeclBits.HasVolatileMember = val;
+ }
bool hasLoadedFieldsFromExternalStorage() const {
- return LoadedFieldsFromExternalStorage;
+ return RecordDeclBits.LoadedFieldsFromExternalStorage;
}
- void setHasLoadedFieldsFromExternalStorage(bool val) {
- LoadedFieldsFromExternalStorage = val;
+
+ void setHasLoadedFieldsFromExternalStorage(bool val) const {
+ RecordDeclBits.LoadedFieldsFromExternalStorage = val;
}
/// Functions to query basic properties of non-trivial C structs.
bool isNonTrivialToPrimitiveDefaultInitialize() const {
- return NonTrivialToPrimitiveDefaultInitialize;
+ return RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize;
}
void setNonTrivialToPrimitiveDefaultInitialize(bool V) {
- NonTrivialToPrimitiveDefaultInitialize = V;
+ RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize = V;
}
bool isNonTrivialToPrimitiveCopy() const {
- return NonTrivialToPrimitiveCopy;
+ return RecordDeclBits.NonTrivialToPrimitiveCopy;
}
void setNonTrivialToPrimitiveCopy(bool V) {
- NonTrivialToPrimitiveCopy = V;
+ RecordDeclBits.NonTrivialToPrimitiveCopy = V;
}
bool isNonTrivialToPrimitiveDestroy() const {
- return NonTrivialToPrimitiveDestroy;
+ return RecordDeclBits.NonTrivialToPrimitiveDestroy;
}
void setNonTrivialToPrimitiveDestroy(bool V) {
- NonTrivialToPrimitiveDestroy = V;
+ RecordDeclBits.NonTrivialToPrimitiveDestroy = V;
}
/// Determine whether this class can be passed in registers. In C++ mode,
@@ -3720,19 +3721,19 @@ public:
}
ArgPassingKind getArgPassingRestrictions() const {
- return static_cast<ArgPassingKind>(ArgPassingRestrictions);
+ return static_cast<ArgPassingKind>(RecordDeclBits.ArgPassingRestrictions);
}
void setArgPassingRestrictions(ArgPassingKind Kind) {
- ArgPassingRestrictions = static_cast<uint8_t>(Kind);
+ RecordDeclBits.ArgPassingRestrictions = Kind;
}
bool isParamDestroyedInCallee() const {
- return ParamDestroyedInCallee;
+ return RecordDeclBits.ParamDestroyedInCallee;
}
void setParamDestroyedInCallee(bool V) {
- ParamDestroyedInCallee = V;
+ RecordDeclBits.ParamDestroyedInCallee = V;
}
/// Determines whether this declaration represents the
@@ -3855,6 +3856,8 @@ public:
/// unnamed FunctionDecl. For example:
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
class BlockDecl : public Decl, public DeclContext {
+ // This class stores some data in DeclContext::BlockDeclBits
+ // to save some space. Use the provided accessors to access it.
public:
/// A class which contains all the information about a particular
/// captured value.
@@ -3885,6 +3888,14 @@ public:
/// variable.
bool isByRef() const { return VariableAndFlags.getInt() & flag_isByRef; }
+ bool isEscapingByref() const {
+ return getVariable()->isEscapingByref();
+ }
+
+ bool isNonEscapingByref() const {
+ return getVariable()->isNonEscapingByref();
+ }
+
/// Whether this is a nested capture, i.e. the variable captured
/// is not from outside the immediately enclosing function/block.
bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; }
@@ -3895,16 +3906,6 @@ public:
};
private:
- // FIXME: This can be packed into the bitfields in Decl.
- bool IsVariadic : 1;
- bool CapturesCXXThis : 1;
- bool BlockMissingReturnType : 1;
- bool IsConversionFromLambda : 1;
-
- /// A bit that indicates this block is passed directly to a function as a
- /// non-escaping parameter.
- bool DoesNotEscape : 1;
-
/// A new[]'d array of pointers to ParmVarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals.
@@ -3921,10 +3922,7 @@ private:
Decl *ManglingContextDecl = nullptr;
protected:
- BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
- : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false),
- CapturesCXXThis(false), BlockMissingReturnType(true),
- IsConversionFromLambda(false), DoesNotEscape(false) {}
+ BlockDecl(DeclContext *DC, SourceLocation CaretLoc);
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
@@ -3932,8 +3930,8 @@ public:
SourceLocation getCaretLocation() const { return getLocation(); }
- bool isVariadic() const { return IsVariadic; }
- void setIsVariadic(bool value) { IsVariadic = value; }
+ bool isVariadic() const { return BlockDeclBits.IsVariadic; }
+ void setIsVariadic(bool value) { BlockDeclBits.IsVariadic = value; }
CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; }
Stmt *getBody() const override { return (Stmt*) Body; }
@@ -3976,7 +3974,7 @@ public:
/// True if this block (or its nested blocks) captures
/// anything of local storage from its enclosing scopes.
- bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; }
+ bool hasCaptures() const { return NumCaptures || capturesCXXThis(); }
/// Returns the number of captured variables.
/// Does not include an entry for 'this'.
@@ -3989,15 +3987,27 @@ public:
capture_const_iterator capture_begin() const { return captures().begin(); }
capture_const_iterator capture_end() const { return captures().end(); }
- bool capturesCXXThis() const { return CapturesCXXThis; }
- bool blockMissingReturnType() const { return BlockMissingReturnType; }
- void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; }
+ bool capturesCXXThis() const { return BlockDeclBits.CapturesCXXThis; }
+ void setCapturesCXXThis(bool B = true) { BlockDeclBits.CapturesCXXThis = B; }
+
+ bool blockMissingReturnType() const {
+ return BlockDeclBits.BlockMissingReturnType;
+ }
+
+ void setBlockMissingReturnType(bool val = true) {
+ BlockDeclBits.BlockMissingReturnType = val;
+ }
- bool isConversionFromLambda() const { return IsConversionFromLambda; }
- void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; }
+ bool isConversionFromLambda() const {
+ return BlockDeclBits.IsConversionFromLambda;
+ }
+
+ void setIsConversionFromLambda(bool val = true) {
+ BlockDeclBits.IsConversionFromLambda = val;
+ }
- bool doesNotEscape() const { return DoesNotEscape; }
- void setDoesNotEscape() { DoesNotEscape = true; }
+ bool doesNotEscape() const { return BlockDeclBits.DoesNotEscape; }
+ void setDoesNotEscape(bool B = true) { BlockDeclBits.DoesNotEscape = B; }
bool capturesVariable(const VarDecl *var) const;
@@ -4223,16 +4233,16 @@ public:
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
if (RBraceLoc.isValid())
return RBraceLoc;
// No braces: get the end location of the (only) declaration in context
// (if present).
- return decls_empty() ? getLocation() : decls_begin()->getLocEnd();
+ return decls_empty() ? getLocation() : decls_begin()->getEndLoc();
}
SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange(getLocation(), getLocEnd());
+ return SourceRange(getLocation(), getEndLoc());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index d6b89d971d94..8405a43fa098 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -16,6 +16,7 @@
#include "clang/AST/AttrIterator.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
@@ -406,11 +407,11 @@ public:
return SourceRange(getLocation(), getLocation());
}
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
return getSourceRange().getBegin();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
return getSourceRange().getEnd();
}
@@ -481,13 +482,7 @@ public:
const AttrVec &getAttrs() const;
void dropAttrs();
-
- void addAttr(Attr *A) {
- if (hasAttrs())
- getAttrs().push_back(A);
- else
- setAttrs(AttrVec(1, A));
- }
+ void addAttr(Attr *A);
using attr_iterator = AttrVec::const_iterator;
using attr_range = llvm::iterator_range<attr_iterator>;
@@ -1070,11 +1065,11 @@ public:
unsigned OldNS = IdentifierNamespace;
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
IDNS_TagFriend | IDNS_OrdinaryFriend |
- IDNS_LocalExtern)) &&
+ IDNS_LocalExtern | IDNS_NonMemberOperator)) &&
"namespace includes neither ordinary nor tag");
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
IDNS_TagFriend | IDNS_OrdinaryFriend |
- IDNS_LocalExtern)) &&
+ IDNS_LocalExtern | IDNS_NonMemberOperator)) &&
"namespace includes other than ordinary or tag");
Decl *Prev = getPreviousDecl();
@@ -1087,7 +1082,8 @@ public:
IdentifierNamespace |= IDNS_Tag | IDNS_Type;
}
- if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend | IDNS_LocalExtern)) {
+ if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend |
+ IDNS_LocalExtern | IDNS_NonMemberOperator)) {
IdentifierNamespace |= IDNS_OrdinaryFriend;
if (PerformFriendInjection ||
(Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary))
@@ -1141,6 +1137,9 @@ public:
void dump(raw_ostream &Out, bool Deserialize = false) const;
+ /// \return Unique reproducible object identifier
+ int64_t getID() const;
+
/// Looks through the Decl's underlying type to extract a FunctionType
/// when possible. Will return null if the type underlying the Decl does not
/// have a FunctionType.
@@ -1214,7 +1213,6 @@ public:
value_type SingleElement;
public:
- iterator() = default;
explicit iterator(pointer Pos, value_type Single = nullptr)
: IteratorBase(Pos), SingleElement(Single) {}
@@ -1250,47 +1248,424 @@ public:
/// that directly derive from DeclContext are mentioned, not their subclasses):
///
/// TranslationUnitDecl
+/// ExternCContext
/// NamespaceDecl
-/// FunctionDecl
/// TagDecl
+/// OMPDeclareReductionDecl
+/// FunctionDecl
/// ObjCMethodDecl
/// ObjCContainerDecl
/// LinkageSpecDecl
/// ExportDecl
/// BlockDecl
-/// OMPDeclareReductionDecl
+/// CapturedDecl
class DeclContext {
- /// DeclKind - This indicates which class this is.
- unsigned DeclKind : 8;
+ /// For makeDeclVisibleInContextImpl
+ friend class ASTDeclReader;
+ /// For reconcileExternalVisibleStorage, CreateStoredDeclsMap,
+ /// hasNeedToReconcileExternalVisibleStorage
+ friend class ExternalASTSource;
+ /// For CreateStoredDeclsMap
+ friend class DependentDiagnostic;
+ /// For hasNeedToReconcileExternalVisibleStorage,
+ /// hasLazyLocalLexicalLookups, hasLazyExternalLexicalLookups
+ friend class ASTWriter;
- /// Whether this declaration context also has some external
- /// storage that contains additional declarations that are lexically
- /// part of this context.
- mutable bool ExternalLexicalStorage : 1;
+ // We use uint64_t in the bit-fields below since some bit-fields
+ // cross the unsigned boundary and this breaks the packing.
+
+ /// Stores the bits used by DeclContext.
+ /// If modified NumDeclContextBit, the ctor of DeclContext and the accessor
+ /// methods in DeclContext should be updated appropriately.
+ class DeclContextBitfields {
+ friend class DeclContext;
+ /// DeclKind - This indicates which class this is.
+ uint64_t DeclKind : 7;
+
+ /// Whether this declaration context also has some external
+ /// storage that contains additional declarations that are lexically
+ /// part of this context.
+ mutable uint64_t ExternalLexicalStorage : 1;
+
+ /// Whether this declaration context also has some external
+ /// storage that contains additional declarations that are visible
+ /// in this context.
+ mutable uint64_t ExternalVisibleStorage : 1;
+
+ /// Whether this declaration context has had externally visible
+ /// storage added since the last lookup. In this case, \c LookupPtr's
+ /// invariant may not hold and needs to be fixed before we perform
+ /// another lookup.
+ mutable uint64_t NeedToReconcileExternalVisibleStorage : 1;
+
+ /// If \c true, this context may have local lexical declarations
+ /// that are missing from the lookup table.
+ mutable uint64_t HasLazyLocalLexicalLookups : 1;
+
+ /// If \c true, the external source may have lexical declarations
+ /// that are missing from the lookup table.
+ mutable uint64_t HasLazyExternalLexicalLookups : 1;
+
+ /// If \c true, lookups should only return identifier from
+ /// DeclContext scope (for example TranslationUnit). Used in
+ /// LookupQualifiedName()
+ mutable uint64_t UseQualifiedLookup : 1;
+ };
- /// Whether this declaration context also has some external
- /// storage that contains additional declarations that are visible
- /// in this context.
- mutable bool ExternalVisibleStorage : 1;
+ /// Number of bits in DeclContextBitfields.
+ enum { NumDeclContextBits = 13 };
- /// Whether this declaration context has had external visible
- /// storage added since the last lookup. In this case, \c LookupPtr's
- /// invariant may not hold and needs to be fixed before we perform
- /// another lookup.
- mutable bool NeedToReconcileExternalVisibleStorage : 1;
+ /// Stores the bits used by TagDecl.
+ /// If modified NumTagDeclBits and the accessor
+ /// methods in TagDecl should be updated appropriately.
+ class TagDeclBitfields {
+ friend class TagDecl;
+ /// For the bits in DeclContextBitfields
+ uint64_t : NumDeclContextBits;
- /// If \c true, this context may have local lexical declarations
- /// that are missing from the lookup table.
- mutable bool HasLazyLocalLexicalLookups : 1;
+ /// The TagKind enum.
+ uint64_t TagDeclKind : 3;
- /// If \c true, the external source may have lexical declarations
- /// that are missing from the lookup table.
- mutable bool HasLazyExternalLexicalLookups : 1;
+ /// True if this is a definition ("struct foo {};"), false if it is a
+ /// declaration ("struct foo;"). It is not considered a definition
+ /// until the definition has been fully processed.
+ uint64_t IsCompleteDefinition : 1;
+
+ /// True if this is currently being defined.
+ uint64_t IsBeingDefined : 1;
+
+ /// True if this tag declaration is "embedded" (i.e., defined or declared
+ /// for the very first time) in the syntax of a declarator.
+ uint64_t IsEmbeddedInDeclarator : 1;
+
+ /// True if this tag is free standing, e.g. "struct foo;".
+ uint64_t IsFreeStanding : 1;
+
+ /// Indicates whether it is possible for declarations of this kind
+ /// to have an out-of-date definition.
+ ///
+ /// This option is only enabled when modules are enabled.
+ uint64_t MayHaveOutOfDateDef : 1;
+
+ /// Has the full definition of this type been required by a use somewhere in
+ /// the TU.
+ uint64_t IsCompleteDefinitionRequired : 1;
+ };
+
+ /// Number of non-inherited bits in TagDeclBitfields.
+ enum { NumTagDeclBits = 9 };
+
+ /// Stores the bits used by EnumDecl.
+ /// If modified NumEnumDeclBit and the accessor
+ /// methods in EnumDecl should be updated appropriately.
+ class EnumDeclBitfields {
+ friend class EnumDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+ /// For the bits in TagDeclBitfields.
+ uint64_t : NumTagDeclBits;
+
+ /// Width in bits required to store all the non-negative
+ /// enumerators of this enum.
+ uint64_t NumPositiveBits : 8;
+
+ /// Width in bits required to store all the negative
+ /// enumerators of this enum.
+ uint64_t NumNegativeBits : 8;
+
+ /// True if this tag declaration is a scoped enumeration. Only
+ /// possible in C++11 mode.
+ uint64_t IsScoped : 1;
+
+ /// If this tag declaration is a scoped enum,
+ /// then this is true if the scoped enum was declared using the class
+ /// tag, false if it was declared with the struct tag. No meaning is
+ /// associated if this tag declaration is not a scoped enum.
+ uint64_t IsScopedUsingClassTag : 1;
+
+ /// True if this is an enumeration with fixed underlying type. Only
+ /// possible in C++11, Microsoft extensions, or Objective C mode.
+ uint64_t IsFixed : 1;
+
+ /// True if a valid hash is stored in ODRHash.
+ uint64_t HasODRHash : 1;
+ };
+
+ /// Number of non-inherited bits in EnumDeclBitfields.
+ enum { NumEnumDeclBits = 20 };
+
+ /// Stores the bits used by RecordDecl.
+ /// If modified NumRecordDeclBits and the accessor
+ /// methods in RecordDecl should be updated appropriately.
+ class RecordDeclBitfields {
+ friend class RecordDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+ /// For the bits in TagDeclBitfields.
+ uint64_t : NumTagDeclBits;
+
+ /// This is true if this struct ends with a flexible
+ /// array member (e.g. int X[]) or if this union contains a struct that does.
+ /// If so, this cannot be contained in arrays or other structs as a member.
+ uint64_t HasFlexibleArrayMember : 1;
+
+ /// Whether this is the type of an anonymous struct or union.
+ uint64_t AnonymousStructOrUnion : 1;
+
+ /// This is true if this struct has at least one member
+ /// containing an Objective-C object pointer type.
+ uint64_t HasObjectMember : 1;
+
+ /// This is true if struct has at least one member of
+ /// 'volatile' type.
+ uint64_t HasVolatileMember : 1;
+
+ /// Whether the field declarations of this record have been loaded
+ /// from external storage. To avoid unnecessary deserialization of
+ /// methods/nested types we allow deserialization of just the fields
+ /// when needed.
+ mutable uint64_t LoadedFieldsFromExternalStorage : 1;
+
+ /// Basic properties of non-trivial C structs.
+ uint64_t NonTrivialToPrimitiveDefaultInitialize : 1;
+ uint64_t NonTrivialToPrimitiveCopy : 1;
+ uint64_t NonTrivialToPrimitiveDestroy : 1;
+
+ /// Indicates whether this struct is destroyed in the callee.
+ uint64_t ParamDestroyedInCallee : 1;
+
+ /// Represents the way this type is passed to a function.
+ uint64_t ArgPassingRestrictions : 2;
+ };
+
+ /// Number of non-inherited bits in RecordDeclBitfields.
+ enum { NumRecordDeclBits = 11 };
+
+ /// Stores the bits used by OMPDeclareReductionDecl.
+ /// If modified NumOMPDeclareReductionDeclBits and the accessor
+ /// methods in OMPDeclareReductionDecl should be updated appropriately.
+ class OMPDeclareReductionDeclBitfields {
+ friend class OMPDeclareReductionDecl;
+ /// For the bits in DeclContextBitfields
+ uint64_t : NumDeclContextBits;
+
+ /// Kind of initializer,
+ /// function call or omp_priv<init_expr> initializtion.
+ uint64_t InitializerKind : 2;
+ };
+
+ /// Number of non-inherited bits in OMPDeclareReductionDeclBitfields.
+ enum { NumOMPDeclareReductionDeclBits = 2 };
+
+ /// Stores the bits used by FunctionDecl.
+ /// If modified NumFunctionDeclBits and the accessor
+ /// methods in FunctionDecl and CXXDeductionGuideDecl
+ /// (for IsCopyDeductionCandidate) should be updated appropriately.
+ class FunctionDeclBitfields {
+ friend class FunctionDecl;
+ /// For IsCopyDeductionCandidate
+ friend class CXXDeductionGuideDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ uint64_t SClass : 3;
+ uint64_t IsInline : 1;
+ uint64_t IsInlineSpecified : 1;
+
+ /// This is shared by CXXConstructorDecl,
+ /// CXXConversionDecl, and CXXDeductionGuideDecl.
+ uint64_t IsExplicitSpecified : 1;
+
+ uint64_t IsVirtualAsWritten : 1;
+ uint64_t IsPure : 1;
+ uint64_t HasInheritedPrototype : 1;
+ uint64_t HasWrittenPrototype : 1;
+ uint64_t IsDeleted : 1;
+ /// Used by CXXMethodDecl
+ uint64_t IsTrivial : 1;
+
+ /// This flag indicates whether this function is trivial for the purpose of
+ /// calls. This is meaningful only when this function is a copy/move
+ /// constructor or a destructor.
+ uint64_t IsTrivialForCall : 1;
+
+ /// Used by CXXMethodDecl
+ uint64_t IsDefaulted : 1;
+ /// Used by CXXMethodDecl
+ uint64_t IsExplicitlyDefaulted : 1;
+ uint64_t HasImplicitReturnZero : 1;
+ uint64_t IsLateTemplateParsed : 1;
+ uint64_t IsConstexpr : 1;
+ uint64_t InstantiationIsPending : 1;
+
+ /// Indicates if the function uses __try.
+ uint64_t UsesSEHTry : 1;
+
+ /// Indicates if the function was a definition
+ /// but its body was skipped.
+ uint64_t HasSkippedBody : 1;
+
+ /// Indicates if the function declaration will
+ /// have a body, once we're done parsing it.
+ uint64_t WillHaveBody : 1;
+
+ /// Indicates that this function is a multiversioned
+ /// function using attribute 'target'.
+ uint64_t IsMultiVersion : 1;
+
+ /// [C++17] Only used by CXXDeductionGuideDecl. Indicates that
+ /// the Deduction Guide is the implicitly generated 'copy
+ /// deduction candidate' (is used during overload resolution).
+ uint64_t IsCopyDeductionCandidate : 1;
+
+ /// Store the ODRHash after first calculation.
+ uint64_t HasODRHash : 1;
+ };
+
+ /// Number of non-inherited bits in FunctionDeclBitfields.
+ enum { NumFunctionDeclBits = 25 };
+
+ /// Stores the bits used by CXXConstructorDecl. If modified
+ /// NumCXXConstructorDeclBits and the accessor
+ /// methods in CXXConstructorDecl should be updated appropriately.
+ class CXXConstructorDeclBitfields {
+ friend class CXXConstructorDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+ /// For the bits in FunctionDeclBitfields.
+ uint64_t : NumFunctionDeclBits;
+
+ /// 25 bits to fit in the remaining availible space.
+ /// Note that this makes CXXConstructorDeclBitfields take
+ /// exactly 64 bits and thus the width of NumCtorInitializers
+ /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
+ /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
+ uint64_t NumCtorInitializers : 25;
+ uint64_t IsInheritingConstructor : 1;
+ };
+
+ /// Number of non-inherited bits in CXXConstructorDeclBitfields.
+ enum { NumCXXConstructorDeclBits = 26 };
+
+ /// Stores the bits used by ObjCMethodDecl.
+ /// If modified NumObjCMethodDeclBits and the accessor
+ /// methods in ObjCMethodDecl should be updated appropriately.
+ class ObjCMethodDeclBitfields {
+ friend class ObjCMethodDecl;
+
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ /// The conventional meaning of this method; an ObjCMethodFamily.
+ /// This is not serialized; instead, it is computed on demand and
+ /// cached.
+ mutable uint64_t Family : ObjCMethodFamilyBitWidth;
+
+ /// instance (true) or class (false) method.
+ uint64_t IsInstance : 1;
+ uint64_t IsVariadic : 1;
+
+ /// True if this method is the getter or setter for an explicit property.
+ uint64_t IsPropertyAccessor : 1;
+
+ /// Method has a definition.
+ uint64_t IsDefined : 1;
+
+ /// Method redeclaration in the same interface.
+ uint64_t IsRedeclaration : 1;
+
+ /// Is redeclared in the same interface.
+ mutable uint64_t HasRedeclaration : 1;
+
+ /// \@required/\@optional
+ uint64_t DeclImplementation : 2;
+
+ /// in, inout, etc.
+ uint64_t objcDeclQualifier : 7;
+
+ /// Indicates whether this method has a related result type.
+ uint64_t RelatedResultType : 1;
- /// If \c true, lookups should only return identifier from
- /// DeclContext scope (for example TranslationUnit). Used in
- /// LookupQualifiedName()
- mutable bool UseQualifiedLookup : 1;
+ /// Whether the locations of the selector identifiers are in a
+ /// "standard" position, a enum SelectorLocationsKind.
+ uint64_t SelLocsKind : 2;
+
+ /// Whether this method overrides any other in the class hierarchy.
+ ///
+ /// A method is said to override any method in the class's
+ /// base classes, its protocols, or its categories' protocols, that has
+ /// the same selector and is of the same kind (class or instance).
+ /// A method in an implementation is not considered as overriding the same
+ /// method in the interface or its categories.
+ uint64_t IsOverriding : 1;
+
+ /// Indicates if the method was a definition but its body was skipped.
+ uint64_t HasSkippedBody : 1;
+ };
+
+ /// Number of non-inherited bits in ObjCMethodDeclBitfields.
+ enum { NumObjCMethodDeclBits = 24 };
+
+ /// Stores the bits used by ObjCContainerDecl.
+ /// If modified NumObjCContainerDeclBits and the accessor
+ /// methods in ObjCContainerDecl should be updated appropriately.
+ class ObjCContainerDeclBitfields {
+ friend class ObjCContainerDecl;
+ /// For the bits in DeclContextBitfields
+ uint32_t : NumDeclContextBits;
+
+ // Not a bitfield but this saves space.
+ // Note that ObjCContainerDeclBitfields is full.
+ SourceLocation AtStart;
+ };
+
+ /// Number of non-inherited bits in ObjCContainerDeclBitfields.
+ /// Note that here we rely on the fact that SourceLocation is 32 bits
+ /// wide. We check this with the static_assert in the ctor of DeclContext.
+ enum { NumObjCContainerDeclBits = 64 - NumDeclContextBits };
+
+ /// Stores the bits used by LinkageSpecDecl.
+ /// If modified NumLinkageSpecDeclBits and the accessor
+ /// methods in LinkageSpecDecl should be updated appropriately.
+ class LinkageSpecDeclBitfields {
+ friend class LinkageSpecDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ /// The language for this linkage specification with values
+ /// in the enum LinkageSpecDecl::LanguageIDs.
+ uint64_t Language : 3;
+
+ /// True if this linkage spec has braces.
+ /// This is needed so that hasBraces() returns the correct result while the
+ /// linkage spec body is being parsed. Once RBraceLoc has been set this is
+ /// not used, so it doesn't need to be serialized.
+ uint64_t HasBraces : 1;
+ };
+
+ /// Number of non-inherited bits in LinkageSpecDeclBitfields.
+ enum { NumLinkageSpecDeclBits = 4 };
+
+ /// Stores the bits used by BlockDecl.
+ /// If modified NumBlockDeclBits and the accessor
+ /// methods in BlockDecl should be updated appropriately.
+ class BlockDeclBitfields {
+ friend class BlockDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ uint64_t IsVariadic : 1;
+ uint64_t CapturesCXXThis : 1;
+ uint64_t BlockMissingReturnType : 1;
+ uint64_t IsConversionFromLambda : 1;
+
+ /// A bit that indicates this block is passed directly to a function as a
+ /// non-escaping parameter.
+ uint64_t DoesNotEscape : 1;
+ };
+
+ /// Number of non-inherited bits in BlockDeclBitfields.
+ enum { NumBlockDeclBits = 5 };
/// Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
@@ -1301,9 +1676,50 @@ class DeclContext {
mutable StoredDeclsMap *LookupPtr = nullptr;
protected:
- friend class ASTDeclReader;
- friend class ASTWriter;
- friend class ExternalASTSource;
+ /// This anonymous union stores the bits belonging to DeclContext and classes
+ /// deriving from it. The goal is to use otherwise wasted
+ /// space in DeclContext to store data belonging to derived classes.
+ /// The space saved is especially significient when pointers are aligned
+ /// to 8 bytes. In this case due to alignment requirements we have a
+ /// little less than 8 bytes free in DeclContext which we can use.
+ /// We check that none of the classes in this union is larger than
+ /// 8 bytes with static_asserts in the ctor of DeclContext.
+ union {
+ DeclContextBitfields DeclContextBits;
+ TagDeclBitfields TagDeclBits;
+ EnumDeclBitfields EnumDeclBits;
+ RecordDeclBitfields RecordDeclBits;
+ OMPDeclareReductionDeclBitfields OMPDeclareReductionDeclBits;
+ FunctionDeclBitfields FunctionDeclBits;
+ CXXConstructorDeclBitfields CXXConstructorDeclBits;
+ ObjCMethodDeclBitfields ObjCMethodDeclBits;
+ ObjCContainerDeclBitfields ObjCContainerDeclBits;
+ LinkageSpecDeclBitfields LinkageSpecDeclBits;
+ BlockDeclBitfields BlockDeclBits;
+
+ static_assert(sizeof(DeclContextBitfields) <= 8,
+ "DeclContextBitfields is larger than 8 bytes!");
+ static_assert(sizeof(TagDeclBitfields) <= 8,
+ "TagDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(EnumDeclBitfields) <= 8,
+ "EnumDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(RecordDeclBitfields) <= 8,
+ "RecordDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(OMPDeclareReductionDeclBitfields) <= 8,
+ "OMPDeclareReductionDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(FunctionDeclBitfields) <= 8,
+ "FunctionDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(CXXConstructorDeclBitfields) <= 8,
+ "CXXConstructorDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ObjCMethodDeclBitfields) <= 8,
+ "ObjCMethodDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ObjCContainerDeclBitfields) <= 8,
+ "ObjCContainerDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(LinkageSpecDeclBitfields) <= 8,
+ "LinkageSpecDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(BlockDeclBitfields) <= 8,
+ "BlockDeclBitfields is larger than 8 bytes!");
+ };
/// FirstDecl - The first declaration stored within this declaration
/// context.
@@ -1321,18 +1737,13 @@ protected:
static std::pair<Decl *, Decl *>
BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded);
- DeclContext(Decl::Kind K)
- : DeclKind(K), ExternalLexicalStorage(false),
- ExternalVisibleStorage(false),
- NeedToReconcileExternalVisibleStorage(false),
- HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
- UseQualifiedLookup(false) {}
+ DeclContext(Decl::Kind K);
public:
~DeclContext();
Decl::Kind getDeclKind() const {
- return static_cast<Decl::Kind>(DeclKind);
+ return static_cast<Decl::Kind>(DeclContextBits.DeclKind);
}
const char *getDeclKindName() const;
@@ -1371,54 +1782,54 @@ public:
return cast<Decl>(this)->getASTContext();
}
- bool isClosure() const {
- return DeclKind == Decl::Block;
- }
+ bool isClosure() const { return getDeclKind() == Decl::Block; }
bool isObjCContainer() const {
- switch (DeclKind) {
- case Decl::ObjCCategory:
- case Decl::ObjCCategoryImpl:
- case Decl::ObjCImplementation:
- case Decl::ObjCInterface:
- case Decl::ObjCProtocol:
- return true;
+ switch (getDeclKind()) {
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCInterface:
+ case Decl::ObjCProtocol:
+ return true;
+ default:
+ return false;
}
- return false;
}
bool isFunctionOrMethod() const {
- switch (DeclKind) {
+ switch (getDeclKind()) {
case Decl::Block:
case Decl::Captured:
case Decl::ObjCMethod:
return true;
default:
- return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction;
+ return getDeclKind() >= Decl::firstFunction &&
+ getDeclKind() <= Decl::lastFunction;
}
}
/// Test whether the context supports looking up names.
bool isLookupContext() const {
- return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec &&
- DeclKind != Decl::Export;
+ return !isFunctionOrMethod() && getDeclKind() != Decl::LinkageSpec &&
+ getDeclKind() != Decl::Export;
}
bool isFileContext() const {
- return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
+ return getDeclKind() == Decl::TranslationUnit ||
+ getDeclKind() == Decl::Namespace;
}
bool isTranslationUnit() const {
- return DeclKind == Decl::TranslationUnit;
+ return getDeclKind() == Decl::TranslationUnit;
}
bool isRecord() const {
- return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord;
+ return getDeclKind() >= Decl::firstRecord &&
+ getDeclKind() <= Decl::lastRecord;
}
- bool isNamespace() const {
- return DeclKind == Decl::Namespace;
- }
+ bool isNamespace() const { return getDeclKind() == Decl::Namespace; }
bool isStdNamespace() const;
@@ -1886,7 +2297,7 @@ public:
void setMustBuildLookupTable() {
assert(this == getPrimaryContext() &&
"should only be called on primary context");
- HasLazyExternalLexicalLookups = true;
+ DeclContextBits.HasLazyExternalLexicalLookups = true;
}
/// Retrieve the internal representation of the lookup structure.
@@ -1898,24 +2309,28 @@ public:
/// Whether this DeclContext has external storage containing
/// additional declarations that are lexically in this context.
- bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; }
+ bool hasExternalLexicalStorage() const {
+ return DeclContextBits.ExternalLexicalStorage;
+ }
/// State whether this DeclContext has external storage for
/// declarations lexically in this context.
- void setHasExternalLexicalStorage(bool ES = true) {
- ExternalLexicalStorage = ES;
+ void setHasExternalLexicalStorage(bool ES = true) const {
+ DeclContextBits.ExternalLexicalStorage = ES;
}
/// Whether this DeclContext has external storage containing
/// additional declarations that are visible in this context.
- bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; }
+ bool hasExternalVisibleStorage() const {
+ return DeclContextBits.ExternalVisibleStorage;
+ }
/// State whether this DeclContext has external storage for
/// declarations visible in this context.
- void setHasExternalVisibleStorage(bool ES = true) {
- ExternalVisibleStorage = ES;
+ void setHasExternalVisibleStorage(bool ES = true) const {
+ DeclContextBits.ExternalVisibleStorage = ES;
if (ES && LookupPtr)
- NeedToReconcileExternalVisibleStorage = true;
+ DeclContextBits.NeedToReconcileExternalVisibleStorage = true;
}
/// Determine whether the given declaration is stored in the list of
@@ -1925,14 +2340,14 @@ public:
D == LastDecl);
}
- bool setUseQualifiedLookup(bool use = true) {
- bool old_value = UseQualifiedLookup;
- UseQualifiedLookup = use;
+ bool setUseQualifiedLookup(bool use = true) const {
+ bool old_value = DeclContextBits.UseQualifiedLookup;
+ DeclContextBits.UseQualifiedLookup = use;
return old_value;
}
bool shouldUseQualifiedLookup() const {
- return UseQualifiedLookup;
+ return DeclContextBits.UseQualifiedLookup;
}
static bool classof(const Decl *D);
@@ -1944,7 +2359,45 @@ public:
bool Deserialize = false) const;
private:
- friend class DependentDiagnostic;
+ /// Whether this declaration context has had externally visible
+ /// storage added since the last lookup. In this case, \c LookupPtr's
+ /// invariant may not hold and needs to be fixed before we perform
+ /// another lookup.
+ bool hasNeedToReconcileExternalVisibleStorage() const {
+ return DeclContextBits.NeedToReconcileExternalVisibleStorage;
+ }
+
+ /// State that this declaration context has had externally visible
+ /// storage added since the last lookup. In this case, \c LookupPtr's
+ /// invariant may not hold and needs to be fixed before we perform
+ /// another lookup.
+ void setNeedToReconcileExternalVisibleStorage(bool Need = true) const {
+ DeclContextBits.NeedToReconcileExternalVisibleStorage = Need;
+ }
+
+ /// If \c true, this context may have local lexical declarations
+ /// that are missing from the lookup table.
+ bool hasLazyLocalLexicalLookups() const {
+ return DeclContextBits.HasLazyLocalLexicalLookups;
+ }
+
+ /// If \c true, this context may have local lexical declarations
+ /// that are missing from the lookup table.
+ void setHasLazyLocalLexicalLookups(bool HasLLLL = true) const {
+ DeclContextBits.HasLazyLocalLexicalLookups = HasLLLL;
+ }
+
+ /// If \c true, the external source may have lexical declarations
+ /// that are missing from the lookup table.
+ bool hasLazyExternalLexicalLookups() const {
+ return DeclContextBits.HasLazyExternalLexicalLookups;
+ }
+
+ /// If \c true, the external source may have lexical declarations
+ /// that are missing from the lookup table.
+ void setHasLazyExternalLexicalLookups(bool HasLELL = true) const {
+ DeclContextBits.HasLazyExternalLexicalLookups = HasLELL;
+ }
void reconcileExternalVisibleStorage() const;
bool LoadLexicalDeclsFromExternalStorage() const;
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 4353f66a34e4..d3357c245d86 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -233,12 +233,12 @@ public:
/// Retrieves the source range that contains the entire base specifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
/// Get the location at which the base class type was written.
SourceLocation getBaseTypeLoc() const LLVM_READONLY {
- return BaseTypeInfo->getTypeLoc().getLocStart();
+ return BaseTypeInfo->getTypeLoc().getBeginLoc();
}
/// Determines whether the base class is a virtual base class (or not).
@@ -974,10 +974,7 @@ public:
bool needsImplicitDefaultConstructor() const {
return !data().UserDeclaredConstructor &&
!(data().DeclaredSpecialMembers & SMF_DefaultConstructor) &&
- // C++14 [expr.prim.lambda]p20:
- // The closure type associated with a lambda-expression has no
- // default constructor.
- !isLambda();
+ (!isLambda() || lambdaIsDefaultConstructibleAndAssignable());
}
/// Determine whether this class has any user-declared constructors.
@@ -1167,10 +1164,7 @@ public:
!hasUserDeclaredCopyAssignment() &&
!hasUserDeclaredMoveConstructor() &&
!hasUserDeclaredDestructor() &&
- // C++1z [expr.prim.lambda]p21: "the closure type has a deleted copy
- // assignment operator". The intent is that this counts as a user
- // declared copy assignment, but we do not model it that way.
- !isLambda();
+ (!isLambda() || lambdaIsDefaultConstructibleAndAssignable());
}
/// Determine whether we need to eagerly declare a move assignment
@@ -1210,6 +1204,10 @@ public:
/// a template).
bool isGenericLambda() const;
+ /// Determine whether this lambda should have an implicit default constructor
+ /// and copy and move assignment operators.
+ bool lambdaIsDefaultConstructibleAndAssignable() const;
+
/// Retrieve the lambda call operator of the closure type
/// if this is a closure type.
CXXMethodDecl *getLambdaCallOperator() const;
@@ -1543,7 +1541,7 @@ public:
///
/// C++11 [class]p6:
/// "A trivial class is a class that has a trivial default constructor and
- /// is trivially copiable."
+ /// is trivially copyable."
bool isTrivial() const {
return isTriviallyCopyable() && hasTrivialDefaultConstructor();
}
@@ -1999,7 +1997,8 @@ private:
SC_None, false, false) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
- IsExplicitSpecified = IsExplicit;
+ setExplicitSpecified(IsExplicit);
+ setIsCopyDeductionCandidate(false);
}
public:
@@ -2015,21 +2014,20 @@ public:
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID);
/// Whether this deduction guide is explicit.
- bool isExplicit() const { return IsExplicitSpecified; }
-
- /// Whether this deduction guide was declared with the 'explicit' specifier.
- bool isExplicitSpecified() const { return IsExplicitSpecified; }
+ bool isExplicit() const { return isExplicitSpecified(); }
/// Get the template for which this guide performs deduction.
TemplateDecl *getDeducedTemplate() const {
return getDeclName().getCXXDeductionGuideTemplate();
}
- void setIsCopyDeductionCandidate() {
- IsCopyDeductionCandidate = true;
+ void setIsCopyDeductionCandidate(bool isCDC = true) {
+ FunctionDeclBits.IsCopyDeductionCandidate = isCDC;
}
- bool isCopyDeductionCandidate() const { return IsCopyDeductionCandidate; }
+ bool isCopyDeductionCandidate() const {
+ return FunctionDeclBits.IsCopyDeductionCandidate;
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2109,10 +2107,15 @@ public:
Base, IsAppleKext);
}
- /// Determine whether this is a usual deallocation function
- /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded
- /// delete or delete[] operator with a particular signature.
- bool isUsualDeallocationFunction() const;
+ /// Determine whether this is a usual deallocation function (C++
+ /// [basic.stc.dynamic.deallocation]p2), which is an overloaded delete or
+ /// delete[] operator with a particular signature. Populates \p PreventedBy
+ /// with the declarations of the functions of the same kind if they were the
+ /// reason for this function returning false. This is used by
+ /// Sema::isUsualDeallocationFunction to reconsider the answer based on the
+ /// context.
+ bool isUsualDeallocationFunction(
+ SmallVectorImpl<const FunctionDecl *> &PreventedBy) const;
/// Determine whether this is a copy-assignment operator, regardless
/// of whether it was declared implicitly or explicitly.
@@ -2177,9 +2180,12 @@ public:
/// that for the call operator of a lambda closure type, this returns the
/// desugared 'this' type (a pointer to the closure type), not the captured
/// 'this' type.
- QualType getThisType(ASTContext &C) const;
+ QualType getThisType() const;
+
+ static QualType getThisType(const FunctionProtoType *FPT,
+ const CXXRecordDecl *Decl);
- unsigned getTypeQualifiers() const {
+ Qualifiers getTypeQualifiers() const {
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
}
@@ -2312,6 +2318,9 @@ public:
CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo,
SourceLocation L, Expr *Init, SourceLocation R);
+ /// \return Unique reproducible object identifier.
+ int64_t getID(const ASTContext &Context) const;
+
/// Determine whether this initializer is initializing a base class.
bool isBaseInitializer() const {
return Initializee.is<TypeSourceInfo*>() && !IsDelegating;
@@ -2475,31 +2484,20 @@ public:
class CXXConstructorDecl final
: public CXXMethodDecl,
private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> {
+ // This class stores some data in DeclContext::CXXConstructorDeclBits
+ // to save some space. Use the provided accessors to access it.
+
/// \name Support for base and member initializers.
/// \{
/// The arguments used to initialize the base or member.
LazyCXXCtorInitializersPtr CtorInitializers;
- unsigned NumCtorInitializers : 31;
- /// \}
-
- /// Whether this constructor declaration is an implicitly-declared
- /// inheriting constructor.
- unsigned IsInheritingConstructor : 1;
CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared, bool isConstexpr,
- InheritedConstructor Inherited)
- : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
- SC_None, isInline, isConstexpr, SourceLocation()),
- NumCtorInitializers(0), IsInheritingConstructor((bool)Inherited) {
- setImplicit(isImplicitlyDeclared);
- if (Inherited)
- *getTrailingObjects<InheritedConstructor>() = Inherited;
- IsExplicitSpecified = isExplicitSpecified;
- }
+ InheritedConstructor Inherited);
void anchor() override;
@@ -2542,12 +2540,12 @@ public:
/// Retrieve an iterator past the last initializer.
init_iterator init_end() {
- return init_begin() + NumCtorInitializers;
+ return init_begin() + getNumCtorInitializers();
}
/// Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
- return init_begin() + NumCtorInitializers;
+ return init_begin() + getNumCtorInitializers();
}
using init_reverse_iterator = std::reverse_iterator<init_iterator>;
@@ -2571,20 +2569,22 @@ public:
/// Determine the number of arguments used to initialize the member
/// or base.
unsigned getNumCtorInitializers() const {
- return NumCtorInitializers;
+ return CXXConstructorDeclBits.NumCtorInitializers;
}
void setNumCtorInitializers(unsigned numCtorInitializers) {
- NumCtorInitializers = numCtorInitializers;
+ CXXConstructorDeclBits.NumCtorInitializers = numCtorInitializers;
+ // This assert added because NumCtorInitializers is stored
+ // in CXXConstructorDeclBits as a bitfield and its width has
+ // been shrunk from 32 bits to fit into CXXConstructorDeclBitfields.
+ assert(CXXConstructorDeclBits.NumCtorInitializers ==
+ numCtorInitializers && "NumCtorInitializers overflow!");
}
void setCtorInitializers(CXXCtorInitializer **Initializers) {
CtorInitializers = Initializers;
}
- /// Whether this function is marked as explicit explicitly.
- bool isExplicitSpecified() const { return IsExplicitSpecified; }
-
/// Whether this function is explicit.
bool isExplicit() const {
return getCanonicalDecl()->isExplicitSpecified();
@@ -2665,12 +2665,20 @@ public:
/// Determine whether this is an implicit constructor synthesized to
/// model a call to a constructor inherited from a base class.
- bool isInheritingConstructor() const { return IsInheritingConstructor; }
+ bool isInheritingConstructor() const {
+ return CXXConstructorDeclBits.IsInheritingConstructor;
+ }
+
+ /// State that this is an implicit constructor synthesized to
+ /// model a call to a constructor inherited from a base class.
+ void setInheritingConstructor(bool isIC = true) {
+ CXXConstructorDeclBits.IsInheritingConstructor = isIC;
+ }
/// Get the constructor that this inheriting constructor is based on.
InheritedConstructor getInheritedConstructor() const {
- return IsInheritingConstructor ? *getTrailingObjects<InheritedConstructor>()
- : InheritedConstructor();
+ return isInheritingConstructor() ?
+ *getTrailingObjects<InheritedConstructor>() : InheritedConstructor();
}
CXXConstructorDecl *getCanonicalDecl() override {
@@ -2765,7 +2773,7 @@ class CXXConversionDecl : public CXXMethodDecl {
SourceLocation EndLocation)
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, isConstexpr, EndLocation) {
- IsExplicitSpecified = isExplicitSpecified;
+ setExplicitSpecified(isExplicitSpecified);
}
void anchor() override;
@@ -2783,9 +2791,6 @@ public:
SourceLocation EndLocation);
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// Whether this function is marked as explicit explicitly.
- bool isExplicitSpecified() const { return IsExplicitSpecified; }
-
/// Whether this function is explicit.
bool isExplicit() const {
return getCanonicalDecl()->isExplicitSpecified();
@@ -2820,7 +2825,8 @@ public:
/// \endcode
class LinkageSpecDecl : public Decl, public DeclContext {
virtual void anchor();
-
+ // This class stores some data in DeclContext::LinkageSpecDeclBits to save
+ // some space. Use the provided accessors to access it.
public:
/// Represents the language in a linkage specification.
///
@@ -2834,16 +2840,6 @@ public:
};
private:
- /// The language for this linkage specification.
- unsigned Language : 3;
-
- /// True if this linkage spec has braces.
- ///
- /// This is needed so that hasBraces() returns the correct result while the
- /// linkage spec body is being parsed. Once RBraceLoc has been set this is
- /// not used, so it doesn't need to be serialized.
- unsigned HasBraces : 1;
-
/// The source location for the extern keyword.
SourceLocation ExternLoc;
@@ -2851,10 +2847,7 @@ private:
SourceLocation RBraceLoc;
LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
- SourceLocation LangLoc, LanguageIDs lang, bool HasBraces)
- : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
- Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc),
- RBraceLoc(SourceLocation()) {}
+ SourceLocation LangLoc, LanguageIDs lang, bool HasBraces);
public:
static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2864,16 +2857,18 @@ public:
static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
/// Return the language specified by this linkage specification.
- LanguageIDs getLanguage() const { return LanguageIDs(Language); }
+ LanguageIDs getLanguage() const {
+ return static_cast<LanguageIDs>(LinkageSpecDeclBits.Language);
+ }
/// Set the language specified by this linkage specification.
- void setLanguage(LanguageIDs L) { Language = L; }
+ void setLanguage(LanguageIDs L) { LinkageSpecDeclBits.Language = L; }
/// Determines whether this linkage specification had braces in
/// its syntactic form.
bool hasBraces() const {
- assert(!RBraceLoc.isValid() || HasBraces);
- return HasBraces;
+ assert(!RBraceLoc.isValid() || LinkageSpecDeclBits.HasBraces);
+ return LinkageSpecDeclBits.HasBraces;
}
SourceLocation getExternLoc() const { return ExternLoc; }
@@ -2881,19 +2876,19 @@ public:
void setExternLoc(SourceLocation L) { ExternLoc = L; }
void setRBraceLoc(SourceLocation L) {
RBraceLoc = L;
- HasBraces = RBraceLoc.isValid();
+ LinkageSpecDeclBits.HasBraces = RBraceLoc.isValid();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
if (hasBraces())
return getRBraceLoc();
// No braces: get the end location of the (only) declaration in context
// (if present).
- return decls_empty() ? getLocation() : decls_begin()->getLocEnd();
+ return decls_empty() ? getLocation() : decls_begin()->getEndLoc();
}
SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange(ExternLoc, getLocEnd());
+ return SourceRange(ExternLoc, getEndLoc());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -3698,7 +3693,7 @@ class UnresolvedUsingTypenameDecl
public:
/// Returns the source location of the 'using' keyword.
- SourceLocation getUsingLoc() const { return getLocStart(); }
+ SourceLocation getUsingLoc() const { return getBeginLoc(); }
/// Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
@@ -3923,6 +3918,7 @@ class MSPropertyDecl : public DeclaratorDecl {
: DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL),
GetterId(Getter), SetterId(Setter) {}
+ void anchor() override;
public:
friend class ASTDeclReader;
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index a8de8ed16840..b5808f23de6f 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -158,7 +158,7 @@ public:
if (DD->getOuterLocStart() != DD->getInnerLocStart())
return DD->getSourceRange();
}
- return SourceRange(getFriendLoc(), ND->getLocEnd());
+ return SourceRange(getFriendLoc(), ND->getEndLoc());
}
else if (TypeSourceInfo *TInfo = getFriendType()) {
SourceLocation StartL =
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index c1cc726e3152..5b57411f9785 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -137,62 +137,17 @@ public:
/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
///
class ObjCMethodDecl : public NamedDecl, public DeclContext {
+ // This class stores some data in DeclContext::ObjCMethodDeclBits
+ // to save some space. Use the provided accessors to access it.
+
public:
enum ImplementationControl { None, Required, Optional };
private:
- // The conventional meaning of this method; an ObjCMethodFamily.
- // This is not serialized; instead, it is computed on demand and
- // cached.
- mutable unsigned Family : ObjCMethodFamilyBitWidth;
-
- /// instance (true) or class (false) method.
- unsigned IsInstance : 1;
- unsigned IsVariadic : 1;
-
- /// True if this method is the getter or setter for an explicit property.
- unsigned IsPropertyAccessor : 1;
-
- // Method has a definition.
- unsigned IsDefined : 1;
-
- /// Method redeclaration in the same interface.
- unsigned IsRedeclaration : 1;
-
- /// Is redeclared in the same interface.
- mutable unsigned HasRedeclaration : 1;
-
- // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
- /// \@required/\@optional
- unsigned DeclImplementation : 2;
-
- // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
- /// in, inout, etc.
- unsigned objcDeclQualifier : 7;
-
- /// Indicates whether this method has a related result type.
- unsigned RelatedResultType : 1;
-
- /// Whether the locations of the selector identifiers are in a
- /// "standard" position, a enum SelectorLocationsKind.
- unsigned SelLocsKind : 2;
-
- /// Whether this method overrides any other in the class hierarchy.
- ///
- /// A method is said to override any method in the class's
- /// base classes, its protocols, or its categories' protocols, that has
- /// the same selector and is of the same kind (class or instance).
- /// A method in an implementation is not considered as overriding the same
- /// method in the interface or its categories.
- unsigned IsOverriding : 1;
-
- /// Indicates if the method was a definition but its body was skipped.
- unsigned HasSkippedBody : 1;
-
- // Return type of this method.
+ /// Return type of this method.
QualType MethodDeclType;
- // Type source information for the return type.
+ /// Type source information for the return type.
TypeSourceInfo *ReturnTInfo;
/// Array of ParmVarDecls for the formal parameters of this method
@@ -203,7 +158,7 @@ private:
/// List of attributes for this method declaration.
SourceLocation DeclEndLoc; // the location of the ';' or '{'.
- // The following are only used for method definitions, null otherwise.
+ /// The following are only used for method definitions, null otherwise.
LazyDeclStmtPtr Body;
/// SelfDecl - Decl for the implicit self parameter. This is lazily
@@ -220,21 +175,14 @@ private:
bool isVariadic = false, bool isPropertyAccessor = false,
bool isImplicitlyDeclared = false, bool isDefined = false,
ImplementationControl impControl = None,
- bool HasRelatedResultType = false)
- : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
- DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
- IsInstance(isInstance), IsVariadic(isVariadic),
- IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined),
- IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl),
- objcDeclQualifier(OBJC_TQ_None),
- RelatedResultType(HasRelatedResultType),
- SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0),
- MethodDeclType(T), ReturnTInfo(ReturnTInfo), DeclEndLoc(endLoc) {
- setImplicit(isImplicitlyDeclared);
- }
+ bool HasRelatedResultType = false);
SelectorLocationsKind getSelLocsKind() const {
- return (SelectorLocationsKind)SelLocsKind;
+ return static_cast<SelectorLocationsKind>(ObjCMethodDeclBits.SelLocsKind);
+ }
+
+ void setSelLocsKind(SelectorLocationsKind Kind) {
+ ObjCMethodDeclBits.SelLocsKind = Kind;
}
bool hasStandardSelLocs() const {
@@ -244,10 +192,10 @@ private:
/// Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
- return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
+ return reinterpret_cast<SourceLocation *>(getParams() + NumParams);
}
const SourceLocation *getStoredSelLocs() const {
- return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
+ return reinterpret_cast<const SourceLocation *>(getParams() + NumParams);
}
/// Get a pointer to the stored selector identifiers locations array.
@@ -297,36 +245,50 @@ public:
}
ObjCDeclQualifier getObjCDeclQualifier() const {
- return ObjCDeclQualifier(objcDeclQualifier);
+ return static_cast<ObjCDeclQualifier>(ObjCMethodDeclBits.objcDeclQualifier);
+ }
+
+ void setObjCDeclQualifier(ObjCDeclQualifier QV) {
+ ObjCMethodDeclBits.objcDeclQualifier = QV;
}
- void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
/// Determine whether this method has a result type that is related
/// to the message receiver's type.
- bool hasRelatedResultType() const { return RelatedResultType; }
+ bool hasRelatedResultType() const {
+ return ObjCMethodDeclBits.RelatedResultType;
+ }
/// Note whether this method has a related result type.
- void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }
+ void setRelatedResultType(bool RRT = true) {
+ ObjCMethodDeclBits.RelatedResultType = RRT;
+ }
/// True if this is a method redeclaration in the same interface.
- bool isRedeclaration() const { return IsRedeclaration; }
+ bool isRedeclaration() const { return ObjCMethodDeclBits.IsRedeclaration; }
+ void setIsRedeclaration(bool RD) { ObjCMethodDeclBits.IsRedeclaration = RD; }
void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
+ /// True if redeclared in the same interface.
+ bool hasRedeclaration() const { return ObjCMethodDeclBits.HasRedeclaration; }
+ void setHasRedeclaration(bool HRD) const {
+ ObjCMethodDeclBits.HasRedeclaration = HRD;
+ }
+
/// Returns the location where the declarator ends. It will be
/// the location of ';' for a method declaration and the location of '{'
/// for a method definition.
SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
// Location information, modeled after the Stmt API.
- SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getLocation(); }
+ SourceLocation getEndLoc() const LLVM_READONLY;
SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange(getLocation(), getLocEnd());
+ return SourceRange(getLocation(), getEndLoc());
}
SourceLocation getSelectorStartLoc() const {
if (isImplicit())
- return getLocStart();
+ return getBeginLoc();
return getSelectorLoc(0);
}
@@ -407,6 +369,14 @@ public:
NumParams);
}
+ ParmVarDecl *getParamDecl(unsigned Idx) {
+ assert(Idx < NumParams && "Index out of bounds!");
+ return getParams()[Idx];
+ }
+ const ParmVarDecl *getParamDecl(unsigned Idx) const {
+ return const_cast<ObjCMethodDecl *>(this)->getParamDecl(Idx);
+ }
+
/// Sets the method's parameters and selector source locations.
/// If the method is implicit (not coming from source) \p SelLocs is
/// ignored.
@@ -449,18 +419,26 @@ public:
/// Determines the family of this method.
ObjCMethodFamily getMethodFamily() const;
- bool isInstanceMethod() const { return IsInstance; }
- void setInstanceMethod(bool isInst) { IsInstance = isInst; }
- bool isVariadic() const { return IsVariadic; }
- void setVariadic(bool isVar) { IsVariadic = isVar; }
+ bool isInstanceMethod() const { return ObjCMethodDeclBits.IsInstance; }
+ void setInstanceMethod(bool isInst) {
+ ObjCMethodDeclBits.IsInstance = isInst;
+ }
- bool isClassMethod() const { return !IsInstance; }
+ bool isVariadic() const { return ObjCMethodDeclBits.IsVariadic; }
+ void setVariadic(bool isVar) { ObjCMethodDeclBits.IsVariadic = isVar; }
- bool isPropertyAccessor() const { return IsPropertyAccessor; }
- void setPropertyAccessor(bool isAccessor) { IsPropertyAccessor = isAccessor; }
+ bool isClassMethod() const { return !isInstanceMethod(); }
- bool isDefined() const { return IsDefined; }
- void setDefined(bool isDefined) { IsDefined = isDefined; }
+ bool isPropertyAccessor() const {
+ return ObjCMethodDeclBits.IsPropertyAccessor;
+ }
+
+ void setPropertyAccessor(bool isAccessor) {
+ ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
+ }
+
+ bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
+ void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
/// Whether this method overrides any other in the class hierarchy.
///
@@ -469,8 +447,8 @@ public:
/// the same selector and is of the same kind (class or instance).
/// A method in an implementation is not considered as overriding the same
/// method in the interface or its categories.
- bool isOverriding() const { return IsOverriding; }
- void setOverriding(bool isOverriding) { IsOverriding = isOverriding; }
+ bool isOverriding() const { return ObjCMethodDeclBits.IsOverriding; }
+ void setOverriding(bool IsOver) { ObjCMethodDeclBits.IsOverriding = IsOver; }
/// Return overridden methods for the given \p Method.
///
@@ -484,8 +462,10 @@ public:
SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
/// True if the method was a definition but its body was skipped.
- bool hasSkippedBody() const { return HasSkippedBody; }
- void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
+ bool hasSkippedBody() const { return ObjCMethodDeclBits.HasSkippedBody; }
+ void setHasSkippedBody(bool Skipped = true) {
+ ObjCMethodDeclBits.HasSkippedBody = Skipped;
+ }
/// Returns the property associated with this method's selector.
///
@@ -496,11 +476,11 @@ public:
// Related to protocols declared in \@protocol
void setDeclImplementation(ImplementationControl ic) {
- DeclImplementation = ic;
+ ObjCMethodDeclBits.DeclImplementation = ic;
}
ImplementationControl getImplementationControl() const {
- return ImplementationControl(DeclImplementation);
+ return ImplementationControl(ObjCMethodDeclBits.DeclImplementation);
}
bool isOptional() const {
@@ -534,6 +514,9 @@ public:
/// Returns whether this specific method is a definition.
bool isThisDeclarationADefinition() const { return hasBody(); }
+ /// Is this method defined in the NSObject base class?
+ bool definedInNSObject(const ASTContext &) const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCMethod; }
@@ -984,7 +967,8 @@ public:
/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
- SourceLocation AtStart;
+ // This class stores some data in DeclContext::ObjCContainerDeclBits
+ // to save some space. Use the provided accessors to access it.
// These two locations in the range mark the end of the method container.
// The first points to the '@' token, and the second to the 'end' token.
@@ -993,10 +977,8 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
void anchor() override;
public:
- ObjCContainerDecl(Kind DK, DeclContext *DC,
- IdentifierInfo *Id, SourceLocation nameLoc,
- SourceLocation atStartLoc)
- : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {}
+ ObjCContainerDecl(Kind DK, DeclContext *DC, IdentifierInfo *Id,
+ SourceLocation nameLoc, SourceLocation atStartLoc);
// Iterator access to instance/class properties.
using prop_iterator = specific_decl_iterator<ObjCPropertyDecl>;
@@ -1130,20 +1112,19 @@ public:
virtual void collectPropertiesToImplement(PropertyMap &PM,
PropertyDeclOrder &PO) const {}
- SourceLocation getAtStartLoc() const { return AtStart; }
- void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; }
+ SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; }
- // Marks the end of the container.
- SourceRange getAtEndRange() const {
- return AtEnd;
+ void setAtStartLoc(SourceLocation Loc) {
+ ObjCContainerDeclBits.AtStart = Loc;
}
- void setAtEndRange(SourceRange atEnd) {
- AtEnd = atEnd;
- }
+ // Marks the end of the container.
+ SourceRange getAtEndRange() const { return AtEnd; }
+
+ void setAtEndRange(SourceRange atEnd) { AtEnd = atEnd; }
SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange(AtStart, getAtEndRange().getEnd());
+ return SourceRange(getAtStartLoc(), getAtEndRange().getEnd());
}
// Implement isa/cast/dyncast/etc.
@@ -2831,7 +2812,7 @@ public:
SourceRange getSourceRange() const override LLVM_READONLY;
- SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
ObjCPropertyDecl *getPropertyDecl() const {
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index bec3acffc433..8540cc5b25b6 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -18,6 +18,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/TrailingObjects.h"
@@ -100,6 +101,8 @@ public:
///
/// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer.
class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
+ // This class stores some data in DeclContext::OMPDeclareReductionDeclBits
+ // to save some space. Use the provided accessors to access it.
public:
enum InitKind {
CallInit, // Initialized by function call.
@@ -110,11 +113,17 @@ public:
private:
friend class ASTDeclReader;
/// Combiner for declare reduction construct.
- Expr *Combiner;
+ Expr *Combiner = nullptr;
/// Initializer for declare reduction construct.
- Expr *Initializer;
- /// Kind of initializer - function call or omp_priv<init_expr> initializtion.
- InitKind InitializerKind = CallInit;
+ Expr *Initializer = nullptr;
+ /// In parameter of the combiner.
+ Expr *In = nullptr;
+ /// Out parameter of the combiner.
+ Expr *Out = nullptr;
+ /// Priv parameter of the initializer.
+ Expr *Priv = nullptr;
+ /// Orig parameter of the initializer.
+ Expr *Orig = nullptr;
/// Reference to the previous declare reduction construct in the same
/// scope with the same name. Required for proper templates instantiation if
@@ -125,10 +134,7 @@ private:
OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, QualType Ty,
- OMPDeclareReductionDecl *PrevDeclInScope)
- : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr),
- Initializer(nullptr), InitializerKind(CallInit),
- PrevDeclInScope(PrevDeclInScope) {}
+ OMPDeclareReductionDecl *PrevDeclInScope);
void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) {
PrevDeclInScope = Prev;
@@ -146,19 +152,43 @@ public:
/// Get combiner expression of the declare reduction construct.
Expr *getCombiner() { return Combiner; }
const Expr *getCombiner() const { return Combiner; }
+ /// Get In variable of the combiner.
+ Expr *getCombinerIn() { return In; }
+ const Expr *getCombinerIn() const { return In; }
+ /// Get Out variable of the combiner.
+ Expr *getCombinerOut() { return Out; }
+ const Expr *getCombinerOut() const { return Out; }
/// Set combiner expression for the declare reduction construct.
void setCombiner(Expr *E) { Combiner = E; }
+ /// Set combiner In and Out vars.
+ void setCombinerData(Expr *InE, Expr *OutE) {
+ In = InE;
+ Out = OutE;
+ }
/// Get initializer expression (if specified) of the declare reduction
/// construct.
Expr *getInitializer() { return Initializer; }
const Expr *getInitializer() const { return Initializer; }
/// Get initializer kind.
- InitKind getInitializerKind() const { return InitializerKind; }
+ InitKind getInitializerKind() const {
+ return static_cast<InitKind>(OMPDeclareReductionDeclBits.InitializerKind);
+ }
+ /// Get Orig variable of the initializer.
+ Expr *getInitOrig() { return Orig; }
+ const Expr *getInitOrig() const { return Orig; }
+ /// Get Priv variable of the initializer.
+ Expr *getInitPriv() { return Priv; }
+ const Expr *getInitPriv() const { return Priv; }
/// Set initializer expression for the declare reduction construct.
void setInitializer(Expr *E, InitKind IK) {
Initializer = E;
- InitializerKind = IK;
+ OMPDeclareReductionDeclBits.InitializerKind = IK;
+ }
+ /// Set initializer Orig and Priv vars.
+ void setInitializerData(Expr *OrigE, Expr *PrivE) {
+ Orig = OrigE;
+ Priv = PrivE;
}
/// Get reference to previous declare reduction construct in the same
@@ -210,6 +240,76 @@ public:
static bool classofKind(Kind K) { return K == OMPCapturedExpr; }
};
+/// This represents '#pragma omp requires...' directive.
+/// For example
+///
+/// \code
+/// #pragma omp requires unified_address
+/// \endcode
+///
+class OMPRequiresDecl final
+ : public Decl,
+ private llvm::TrailingObjects<OMPRequiresDecl, OMPClause *> {
+ friend class ASTDeclReader;
+ friend TrailingObjects;
+
+ // Number of clauses associated with this requires declaration
+ unsigned NumClauses = 0;
+
+ virtual void anchor();
+
+ OMPRequiresDecl(Kind DK, DeclContext *DC, SourceLocation L)
+ : Decl(DK, DC, L), NumClauses(0) {}
+
+ /// Returns an array of immutable clauses associated with this requires
+ /// declaration
+ ArrayRef<const OMPClause *> getClauses() const {
+ return llvm::makeArrayRef(getTrailingObjects<OMPClause *>(), NumClauses);
+ }
+
+ /// Returns an array of clauses associated with this requires declaration
+ MutableArrayRef<OMPClause *> getClauses() {
+ return MutableArrayRef<OMPClause *>(getTrailingObjects<OMPClause *>(),
+ NumClauses);
+ }
+
+ /// Sets an array of clauses to this requires declaration
+ void setClauses(ArrayRef<OMPClause *> CL);
+
+public:
+ /// Create requires node.
+ static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, ArrayRef<OMPClause *> CL);
+ /// Create deserialized requires node.
+ static OMPRequiresDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned N);
+
+ using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
+ using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
+ using clauselist_range = llvm::iterator_range<clauselist_iterator>;
+ using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
+
+ unsigned clauselist_size() const { return NumClauses; }
+ bool clauselist_empty() const { return NumClauses == 0; }
+
+ clauselist_range clauselists() {
+ return clauselist_range(clauselist_begin(), clauselist_end());
+ }
+ clauselist_const_range clauselists() const {
+ return clauselist_const_range(clauselist_begin(), clauselist_end());
+ }
+ clauselist_iterator clauselist_begin() { return getClauses().begin(); }
+ clauselist_iterator clauselist_end() { return getClauses().end(); }
+ clauselist_const_iterator clauselist_begin() const {
+ return getClauses().begin();
+ }
+ clauselist_const_iterator clauselist_end() const {
+ return getClauses().end();
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == OMPRequires; }
+};
} // end namespace clang
#endif
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index e0ea7cb8b1b8..f6e3d8f300ba 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -751,6 +751,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
return getMostRecentDecl();
}
+ void anchor() override;
protected:
template <typename EntryType> struct SpecEntryTraits {
using DeclType = EntryType;
@@ -1093,6 +1094,9 @@ public:
/// template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
+ /// Merge \p Prev with our RedeclarableTemplateDecl::Common.
+ void mergePrevDecl(FunctionTemplateDecl *Prev);
+
/// Create a function template node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h
index 520a4a10bfe1..c6cbc9ff7faa 100644
--- a/include/clang/AST/DeclVisitor.h
+++ b/include/clang/AST/DeclVisitor.h
@@ -21,15 +21,12 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace declvisitor {
-
-template <typename T> struct make_ptr { using type = T *; };
-template <typename T> struct make_const_ptr { using type = const T *; };
-
/// A simple visitor class that helps create declaration visitors.
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class Base {
@@ -66,16 +63,16 @@ public:
///
/// This class does not preserve constness of Decl pointers (see also
/// ConstDeclVisitor).
-template<typename ImplClass, typename RetTy = void>
+template <typename ImplClass, typename RetTy = void>
class DeclVisitor
- : public declvisitor::Base<declvisitor::make_ptr, ImplClass, RetTy> {};
+ : public declvisitor::Base<std::add_pointer, ImplClass, RetTy> {};
/// A simple visitor class that helps create declaration visitors.
///
/// This class preserves constness of Decl pointers (see also DeclVisitor).
-template<typename ImplClass, typename RetTy = void>
+template <typename ImplClass, typename RetTy = void>
class ConstDeclVisitor
- : public declvisitor::Base<declvisitor::make_const_ptr, ImplClass, RetTy> {};
+ : public declvisitor::Base<llvm::make_const_ptr, ImplClass, RetTy> {};
} // namespace clang
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 856f3ab5720e..62afae23ec79 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -14,11 +14,14 @@
#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
#define LLVM_CLANG_AST_DECLARATIONNAME_H
+#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
@@ -30,67 +33,195 @@ namespace clang {
class ASTContext;
template <typename> class CanQual;
-class CXXDeductionGuideNameExtra;
-class CXXLiteralOperatorIdName;
-class CXXOperatorIdName;
-class CXXSpecialName;
-class DeclarationNameExtra;
-class IdentifierInfo;
+class DeclarationName;
+class DeclarationNameTable;
class MultiKeywordSelector;
-enum OverloadedOperatorKind : int;
struct PrintingPolicy;
-class QualType;
class TemplateDecl;
-class Type;
class TypeSourceInfo;
class UsingDirectiveDecl;
using CanQualType = CanQual<Type>;
-/// DeclarationName - The name of a declaration. In the common case,
-/// this just stores an IdentifierInfo pointer to a normal
-/// name. However, it also provides encodings for Objective-C
-/// selectors (optimizing zero- and one-argument selectors, which make
-/// up 78% percent of all selectors in Cocoa.h) and special C++ names
-/// for constructors, destructors, and conversion functions.
-class DeclarationName {
+namespace detail {
+
+/// CXXSpecialNameExtra records the type associated with one of the "special"
+/// kinds of declaration names in C++, e.g., constructors, destructors, and
+/// conversion functions. Note that CXXSpecialName is used for C++ constructor,
+/// destructor and conversion functions, but the actual kind is not stored in
+/// CXXSpecialName. Instead we use three different FoldingSet<CXXSpecialName>
+/// in DeclarationNameTable.
+class alignas(IdentifierInfoAlignment) CXXSpecialNameExtra
+ : public llvm::FoldingSetNode {
+ friend class clang::DeclarationName;
+ friend class clang::DeclarationNameTable;
+
+ /// The type associated with this declaration name.
+ QualType Type;
+
+ /// Extra information associated with this declaration name that
+ /// can be used by the front end. All bits are really needed
+ /// so it is not possible to stash something in the low order bits.
+ void *FETokenInfo;
+
+ CXXSpecialNameExtra(QualType QT) : Type(QT), FETokenInfo(nullptr) {}
+
public:
- /// NameKind - The kind of name this object contains.
- enum NameKind {
- Identifier,
- ObjCZeroArgSelector,
- ObjCOneArgSelector,
- ObjCMultiArgSelector,
- CXXConstructorName,
- CXXDestructorName,
- CXXConversionFunctionName,
- CXXDeductionGuideName,
- CXXOperatorName,
- CXXLiteralOperatorName,
- CXXUsingDirective
- };
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ ID.AddPointer(Type.getAsOpaquePtr());
+ }
+};
- static const unsigned NumNameKinds = CXXUsingDirective + 1;
+/// Contains extra information for the name of a C++ deduction guide.
+class alignas(IdentifierInfoAlignment) CXXDeductionGuideNameExtra
+ : public detail::DeclarationNameExtra,
+ public llvm::FoldingSetNode {
+ friend class clang::DeclarationName;
+ friend class clang::DeclarationNameTable;
-private:
+ /// The template named by the deduction guide.
+ TemplateDecl *Template;
+
+ /// Extra information associated with this operator name that
+ /// can be used by the front end. All bits are really needed
+ /// so it is not possible to stash something in the low order bits.
+ void *FETokenInfo;
+
+ CXXDeductionGuideNameExtra(TemplateDecl *TD)
+ : DeclarationNameExtra(CXXDeductionGuideName), Template(TD),
+ FETokenInfo(nullptr) {}
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) { ID.AddPointer(Template); }
+};
+
+/// Contains extra information for the name of an overloaded operator
+/// in C++, such as "operator+. This do not includes literal or conversion
+/// operators. For literal operators see CXXLiteralOperatorIdName and for
+/// conversion operators see CXXSpecialNameExtra.
+class alignas(IdentifierInfoAlignment) CXXOperatorIdName {
+ friend class clang::DeclarationName;
+ friend class clang::DeclarationNameTable;
+
+ /// The kind of this operator.
+ OverloadedOperatorKind Kind = OO_None;
+
+ /// Extra information associated with this operator name that
+ /// can be used by the front end. All bits are really needed
+ /// so it is not possible to stash something in the low order bits.
+ void *FETokenInfo = nullptr;
+};
+
+/// Contains the actual identifier that makes up the
+/// name of a C++ literal operator.
+class alignas(IdentifierInfoAlignment) CXXLiteralOperatorIdName
+ : public detail::DeclarationNameExtra,
+ public llvm::FoldingSetNode {
+ friend class clang::DeclarationName;
+ friend class clang::DeclarationNameTable;
+
+ IdentifierInfo *ID;
+
+ /// Extra information associated with this operator name that
+ /// can be used by the front end. All bits are really needed
+ /// so it is not possible to stash something in the low order bits.
+ void *FETokenInfo;
+
+ CXXLiteralOperatorIdName(IdentifierInfo *II)
+ : DeclarationNameExtra(CXXLiteralOperatorName), ID(II),
+ FETokenInfo(nullptr) {}
+
+public:
+ void Profile(llvm::FoldingSetNodeID &FSID) { FSID.AddPointer(ID); }
+};
+
+} // namespace detail
+
+/// The name of a declaration. In the common case, this just stores
+/// an IdentifierInfo pointer to a normal name. However, it also provides
+/// encodings for Objective-C selectors (optimizing zero- and one-argument
+/// selectors, which make up 78% percent of all selectors in Cocoa.h),
+/// special C++ names for constructors, destructors, and conversion functions,
+/// and C++ overloaded operators.
+class DeclarationName {
friend class DeclarationNameTable;
friend class NamedDecl;
- /// StoredNameKind - The kind of name that is actually stored in the
+ /// StoredNameKind represent the kind of name that is actually stored in the
/// upper bits of the Ptr field. This is only used internally.
///
- /// Note: The entries here are synchronized with the entries in Selector,
- /// for efficient translation between the two.
+ /// NameKind, StoredNameKind, and DeclarationNameExtra::ExtraKind
+ /// must satisfy the following properties. These properties enable
+ /// efficient conversion between the various kinds.
+ ///
+ /// * The first seven enumerators of StoredNameKind must have the same
+ /// numerical value as the first seven enumerators of NameKind.
+ /// This enable efficient conversion between the two enumerations
+ /// in the usual case.
+ ///
+ /// * The enumerations values of DeclarationNameExtra::ExtraKind must start
+ /// at zero, and correspond to the numerical value of the first non-inline
+ /// enumeration values of NameKind minus an offset. This makes conversion
+ /// between DeclarationNameExtra::ExtraKind and NameKind possible with
+ /// a single addition/substraction.
+ ///
+ /// * The enumeration values of Selector::IdentifierInfoFlag must correspond
+ /// to the relevant enumeration values of StoredNameKind.
+ /// More specifically:
+ /// * ZeroArg == StoredObjCZeroArgSelector,
+ /// * OneArg == StoredObjCOneArgSelector,
+ /// * MultiArg == StoredDeclarationNameExtra
+ ///
+ /// * PtrMask must mask the low 3 bits of Ptr.
enum StoredNameKind {
StoredIdentifier = 0,
- StoredObjCZeroArgSelector = 0x01,
- StoredObjCOneArgSelector = 0x02,
- StoredDeclarationNameExtra = 0x03,
- PtrMask = 0x03
+ StoredObjCZeroArgSelector = Selector::ZeroArg,
+ StoredObjCOneArgSelector = Selector::OneArg,
+ StoredCXXConstructorName = 3,
+ StoredCXXDestructorName = 4,
+ StoredCXXConversionFunctionName = 5,
+ StoredCXXOperatorName = 6,
+ StoredDeclarationNameExtra = Selector::MultiArg,
+ PtrMask = 7,
+ UncommonNameKindOffset = 8
+ };
+
+ static_assert(alignof(IdentifierInfo) >= 8 &&
+ alignof(detail::DeclarationNameExtra) >= 8 &&
+ alignof(detail::CXXSpecialNameExtra) >= 8 &&
+ alignof(detail::CXXOperatorIdName) >= 8 &&
+ alignof(detail::CXXDeductionGuideNameExtra) >= 8 &&
+ alignof(detail::CXXLiteralOperatorIdName) >= 8,
+ "The various classes that DeclarationName::Ptr can point to"
+ " must be at least aligned to 8 bytes!");
+
+public:
+ /// The kind of the name stored in this DeclarationName.
+ /// The first 7 enumeration values are stored inline and correspond
+ /// to frequently used kinds. The rest is stored in DeclarationNameExtra
+ /// and correspond to infrequently used kinds.
+ enum NameKind {
+ Identifier = StoredIdentifier,
+ ObjCZeroArgSelector = StoredObjCZeroArgSelector,
+ ObjCOneArgSelector = StoredObjCOneArgSelector,
+ CXXConstructorName = StoredCXXConstructorName,
+ CXXDestructorName = StoredCXXDestructorName,
+ CXXConversionFunctionName = StoredCXXConversionFunctionName,
+ CXXOperatorName = StoredCXXOperatorName,
+ CXXDeductionGuideName = UncommonNameKindOffset +
+ detail::DeclarationNameExtra::CXXDeductionGuideName,
+ CXXLiteralOperatorName =
+ UncommonNameKindOffset +
+ detail::DeclarationNameExtra::CXXLiteralOperatorName,
+ CXXUsingDirective = UncommonNameKindOffset +
+ detail::DeclarationNameExtra::CXXUsingDirective,
+ ObjCMultiArgSelector = UncommonNameKindOffset +
+ detail::DeclarationNameExtra::ObjCMultiArgSelector
};
- /// Ptr - The lowest two bits are used to express what kind of name
- /// we're actually storing, using the values of NameKind. Depending
+private:
+ /// The lowest three bits of Ptr are used to express what kind of name
+ /// we're actually storing, using the values of StoredNameKind. Depending
/// on the kind of name this is, the upper bits of Ptr may have one
/// of several different meanings:
///
@@ -105,99 +236,141 @@ private:
/// with one argument, and Ptr is an IdentifierInfo pointer
/// pointing to the selector name.
///
+ /// StoredCXXConstructorName - The name of a C++ constructor,
+ /// Ptr points to a CXXSpecialNameExtra.
+ ///
+ /// StoredCXXDestructorName - The name of a C++ destructor,
+ /// Ptr points to a CXXSpecialNameExtra.
+ ///
+ /// StoredCXXConversionFunctionName - The name of a C++ conversion function,
+ /// Ptr points to a CXXSpecialNameExtra.
+ ///
+ /// StoredCXXOperatorName - The name of an overloaded C++ operator,
+ /// Ptr points to a CXXOperatorIdName.
+ ///
/// StoredDeclarationNameExtra - Ptr is actually a pointer to a
/// DeclarationNameExtra structure, whose first value will tell us
- /// whether this is an Objective-C selector, C++ operator-id name,
- /// or special C++ name.
+ /// whether this is an Objective-C selector, C++ deduction guide,
+ /// C++ literal operator, or C++ using directive.
uintptr_t Ptr = 0;
- // Construct a declaration name from the name of a C++ constructor,
- // destructor, or conversion function.
- DeclarationName(DeclarationNameExtra *Name)
- : Ptr(reinterpret_cast<uintptr_t>(Name)) {
- assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra");
- Ptr |= StoredDeclarationNameExtra;
+ StoredNameKind getStoredNameKind() const {
+ return static_cast<StoredNameKind>(Ptr & PtrMask);
}
- /// Construct a declaration name from a raw pointer.
- DeclarationName(uintptr_t Ptr) : Ptr(Ptr) {}
+ void *getPtr() const { return reinterpret_cast<void *>(Ptr & ~PtrMask); }
- /// getStoredNameKind - Return the kind of object that is stored in
- /// Ptr.
- StoredNameKind getStoredNameKind() const {
- return static_cast<StoredNameKind>(Ptr & PtrMask);
+ void setPtrAndKind(const void *P, StoredNameKind Kind) {
+ uintptr_t PAsInteger = reinterpret_cast<uintptr_t>(P);
+ assert((Kind & ~PtrMask) == 0 &&
+ "Invalid StoredNameKind in setPtrAndKind!");
+ assert((PAsInteger & PtrMask) == 0 &&
+ "Improperly aligned pointer in setPtrAndKind!");
+ Ptr = PAsInteger | Kind;
}
- /// getExtra - Get the "extra" information associated with this
- /// multi-argument selector or C++ special name.
- DeclarationNameExtra *getExtra() const {
- assert(getStoredNameKind() == StoredDeclarationNameExtra &&
- "Declaration name does not store an Extra structure");
- return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
+ /// Construct a declaration name from a DeclarationNameExtra.
+ DeclarationName(detail::DeclarationNameExtra *Name) {
+ setPtrAndKind(Name, StoredDeclarationNameExtra);
}
- /// getAsCXXSpecialName - If the stored pointer is actually a
- /// CXXSpecialName, returns a pointer to it. Otherwise, returns
- /// a NULL pointer.
- CXXSpecialName *getAsCXXSpecialName() const {
- NameKind Kind = getNameKind();
- if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName)
- return reinterpret_cast<CXXSpecialName *>(getExtra());
- return nullptr;
+ /// Construct a declaration name from a CXXSpecialNameExtra.
+ DeclarationName(detail::CXXSpecialNameExtra *Name,
+ StoredNameKind StoredKind) {
+ assert((StoredKind == StoredCXXConstructorName ||
+ StoredKind == StoredCXXDestructorName ||
+ StoredKind == StoredCXXConversionFunctionName) &&
+ "Invalid StoredNameKind when constructing a DeclarationName"
+ " from a CXXSpecialNameExtra!");
+ setPtrAndKind(Name, StoredKind);
}
- /// If the stored pointer is actually a CXXDeductionGuideNameExtra, returns a
- /// pointer to it. Otherwise, returns a NULL pointer.
- CXXDeductionGuideNameExtra *getAsCXXDeductionGuideNameExtra() const {
- if (getNameKind() == CXXDeductionGuideName)
- return reinterpret_cast<CXXDeductionGuideNameExtra *>(getExtra());
- return nullptr;
+ /// Construct a DeclarationName from a CXXOperatorIdName.
+ DeclarationName(detail::CXXOperatorIdName *Name) {
+ setPtrAndKind(Name, StoredCXXOperatorName);
}
- /// getAsCXXOperatorIdName
- CXXOperatorIdName *getAsCXXOperatorIdName() const {
- if (getNameKind() == CXXOperatorName)
- return reinterpret_cast<CXXOperatorIdName *>(getExtra());
- return nullptr;
+ /// Assert that the stored pointer points to an IdentifierInfo and return it.
+ IdentifierInfo *castAsIdentifierInfo() const {
+ assert((getStoredNameKind() == StoredIdentifier) &&
+ "DeclarationName does not store an IdentifierInfo!");
+ return static_cast<IdentifierInfo *>(getPtr());
}
- CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
- if (getNameKind() == CXXLiteralOperatorName)
- return reinterpret_cast<CXXLiteralOperatorIdName *>(getExtra());
- return nullptr;
+ /// Assert that the stored pointer points to a DeclarationNameExtra
+ /// and return it.
+ detail::DeclarationNameExtra *castAsExtra() const {
+ assert((getStoredNameKind() == StoredDeclarationNameExtra) &&
+ "DeclarationName does not store an Extra structure!");
+ return static_cast<detail::DeclarationNameExtra *>(getPtr());
}
- /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer
- /// for this name as a void pointer if it's not an identifier.
- void *getFETokenInfoAsVoidSlow() const;
+ /// Assert that the stored pointer points to a CXXSpecialNameExtra
+ /// and return it.
+ detail::CXXSpecialNameExtra *castAsCXXSpecialNameExtra() const {
+ assert((getStoredNameKind() == StoredCXXConstructorName ||
+ getStoredNameKind() == StoredCXXDestructorName ||
+ getStoredNameKind() == StoredCXXConversionFunctionName) &&
+ "DeclarationName does not store a CXXSpecialNameExtra!");
+ return static_cast<detail::CXXSpecialNameExtra *>(getPtr());
+ }
+
+ /// Assert that the stored pointer points to a CXXOperatorIdName
+ /// and return it.
+ detail::CXXOperatorIdName *castAsCXXOperatorIdName() const {
+ assert((getStoredNameKind() == StoredCXXOperatorName) &&
+ "DeclarationName does not store a CXXOperatorIdName!");
+ return static_cast<detail::CXXOperatorIdName *>(getPtr());
+ }
+
+ /// Assert that the stored pointer points to a CXXDeductionGuideNameExtra
+ /// and return it.
+ detail::CXXDeductionGuideNameExtra *castAsCXXDeductionGuideNameExtra() const {
+ assert(getNameKind() == CXXDeductionGuideName &&
+ "DeclarationName does not store a CXXDeductionGuideNameExtra!");
+ return static_cast<detail::CXXDeductionGuideNameExtra *>(getPtr());
+ }
+
+ /// Assert that the stored pointer points to a CXXLiteralOperatorIdName
+ /// and return it.
+ detail::CXXLiteralOperatorIdName *castAsCXXLiteralOperatorIdName() const {
+ assert(getNameKind() == CXXLiteralOperatorName &&
+ "DeclarationName does not store a CXXLiteralOperatorIdName!");
+ return static_cast<detail::CXXLiteralOperatorIdName *>(getPtr());
+ }
+
+ /// Get and set the FETokenInfo in the less common cases where the
+ /// declaration name do not point to an identifier.
+ void *getFETokenInfoSlow() const;
+ void setFETokenInfoSlow(void *T);
public:
- /// DeclarationName - Used to create an empty selector.
- DeclarationName() = default;
+ /// Construct an empty declaration name.
+ DeclarationName() { setPtrAndKind(nullptr, StoredIdentifier); }
- // Construct a declaration name from an IdentifierInfo *.
- DeclarationName(const IdentifierInfo *II)
- : Ptr(reinterpret_cast<uintptr_t>(II)) {
- assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
+ /// Construct a declaration name from an IdentifierInfo *.
+ DeclarationName(const IdentifierInfo *II) {
+ setPtrAndKind(II, StoredIdentifier);
}
- // Construct a declaration name from an Objective-C selector.
+ /// Construct a declaration name from an Objective-C selector.
DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) {}
- /// getUsingDirectiveName - Return name for all using-directives.
- static DeclarationName getUsingDirectiveName();
+ /// Returns the name for all C++ using-directives.
+ static DeclarationName getUsingDirectiveName() {
+ // Single instance of DeclarationNameExtra for using-directive
+ static detail::DeclarationNameExtra UDirExtra(
+ detail::DeclarationNameExtra::CXXUsingDirective);
+ return DeclarationName(&UDirExtra);
+ }
- // operator bool() - Evaluates true when this declaration name is
- // non-empty.
+ /// Evaluates true when this declaration name is non-empty.
explicit operator bool() const {
- return ((Ptr & PtrMask) != 0) ||
- (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
+ return getPtr() || (getStoredNameKind() != StoredIdentifier);
}
/// Evaluates true when this declaration name is empty.
- bool isEmpty() const {
- return !*this;
- }
+ bool isEmpty() const { return !*this; }
/// Predicate functions for querying what type of name this is.
bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
@@ -208,8 +381,19 @@ public:
return getStoredNameKind() == StoredObjCOneArgSelector;
}
- /// getNameKind - Determine what kind of name this is.
- NameKind getNameKind() const;
+ /// Determine what kind of name this is.
+ NameKind getNameKind() const {
+ // We rely on the fact that the first 7 NameKind and StoredNameKind
+ // have the same numerical value. This makes the usual case efficient.
+ StoredNameKind StoredKind = getStoredNameKind();
+ if (StoredKind != StoredDeclarationNameExtra)
+ return static_cast<NameKind>(StoredKind);
+ // We have to consult DeclarationNameExtra. We rely on the fact that the
+ // enumeration values of ExtraKind correspond to the enumeration values of
+ // NameKind minus an offset of UncommonNameKindOffset.
+ unsigned ExtraKind = castAsExtra()->getKind();
+ return static_cast<NameKind>(UncommonNameKindOffset + ExtraKind);
+ }
/// Determines whether the name itself is dependent, e.g., because it
/// involves a C++ type that is itself dependent.
@@ -219,95 +403,128 @@ public:
/// callee in a call expression with dependent arguments.
bool isDependentName() const;
- /// getNameAsString - Retrieve the human-readable string for this name.
+ /// Retrieve the human-readable string for this name.
std::string getAsString() const;
- /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
- /// this declaration name, or NULL if this declaration name isn't a
- /// simple identifier.
+ /// Retrieve the IdentifierInfo * stored in this declaration name,
+ /// or null if this declaration name isn't a simple identifier.
IdentifierInfo *getAsIdentifierInfo() const {
if (isIdentifier())
- return reinterpret_cast<IdentifierInfo *>(Ptr);
+ return castAsIdentifierInfo();
return nullptr;
}
- /// getAsOpaqueInteger - Get the representation of this declaration
- /// name as an opaque integer.
+ /// Get the representation of this declaration name as an opaque integer.
uintptr_t getAsOpaqueInteger() const { return Ptr; }
- /// getAsOpaquePtr - Get the representation of this declaration name as
- /// an opaque pointer.
- void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
+ /// Get the representation of this declaration name as an opaque pointer.
+ void *getAsOpaquePtr() const { return reinterpret_cast<void *>(Ptr); }
+ /// Get a declaration name from an opaque pointer returned by getAsOpaquePtr.
static DeclarationName getFromOpaquePtr(void *P) {
DeclarationName N;
- N.Ptr = reinterpret_cast<uintptr_t> (P);
+ N.Ptr = reinterpret_cast<uintptr_t>(P);
return N;
}
+ /// Get a declaration name from an opaque integer
+ /// returned by getAsOpaqueInteger.
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
DeclarationName N;
N.Ptr = P;
return N;
}
- /// getCXXNameType - If this name is one of the C++ names (of a
- /// constructor, destructor, or conversion function), return the
- /// type associated with that name.
- QualType getCXXNameType() const;
+ /// If this name is one of the C++ names (of a constructor, destructor,
+ /// or conversion function), return the type associated with that name.
+ QualType getCXXNameType() const {
+ if (getStoredNameKind() == StoredCXXConstructorName ||
+ getStoredNameKind() == StoredCXXDestructorName ||
+ getStoredNameKind() == StoredCXXConversionFunctionName) {
+ assert(getPtr() && "getCXXNameType on a null DeclarationName!");
+ return castAsCXXSpecialNameExtra()->Type;
+ }
+ return QualType();
+ }
/// If this name is the name of a C++ deduction guide, return the
/// template associated with that name.
- TemplateDecl *getCXXDeductionGuideTemplate() const;
+ TemplateDecl *getCXXDeductionGuideTemplate() const {
+ if (getNameKind() == CXXDeductionGuideName) {
+ assert(getPtr() &&
+ "getCXXDeductionGuideTemplate on a null DeclarationName!");
+ return castAsCXXDeductionGuideNameExtra()->Template;
+ }
+ return nullptr;
+ }
- /// getCXXOverloadedOperator - If this name is the name of an
- /// overloadable operator in C++ (e.g., @c operator+), retrieve the
- /// kind of overloaded operator.
- OverloadedOperatorKind getCXXOverloadedOperator() const;
+ /// If this name is the name of an overloadable operator in C++
+ /// (e.g., @c operator+), retrieve the kind of overloaded operator.
+ OverloadedOperatorKind getCXXOverloadedOperator() const {
+ if (getStoredNameKind() == StoredCXXOperatorName) {
+ assert(getPtr() && "getCXXOverloadedOperator on a null DeclarationName!");
+ return castAsCXXOperatorIdName()->Kind;
+ }
+ return OO_None;
+ }
- /// getCXXLiteralIdentifier - If this name is the name of a literal
- /// operator, retrieve the identifier associated with it.
- IdentifierInfo *getCXXLiteralIdentifier() const;
+ /// If this name is the name of a literal operator,
+ /// retrieve the identifier associated with it.
+ IdentifierInfo *getCXXLiteralIdentifier() const {
+ if (getNameKind() == CXXLiteralOperatorName) {
+ assert(getPtr() && "getCXXLiteralIdentifier on a null DeclarationName!");
+ return castAsCXXLiteralOperatorIdName()->ID;
+ }
+ return nullptr;
+ }
- /// getObjCSelector - Get the Objective-C selector stored in this
- /// declaration name.
+ /// Get the Objective-C selector stored in this declaration name.
Selector getObjCSelector() const {
assert((getNameKind() == ObjCZeroArgSelector ||
getNameKind() == ObjCOneArgSelector ||
- getNameKind() == ObjCMultiArgSelector ||
- Ptr == 0) && "Not a selector!");
+ getNameKind() == ObjCMultiArgSelector || !getPtr()) &&
+ "Not a selector!");
return Selector(Ptr);
}
- /// getFETokenInfo/setFETokenInfo - The language front-end is
- /// allowed to associate arbitrary metadata with some kinds of
- /// declaration names, including normal identifiers and C++
- /// constructors, destructors, and conversion functions.
- template<typename T>
- T *getFETokenInfo() const {
- if (const IdentifierInfo *Info = getAsIdentifierInfo())
- return Info->getFETokenInfo<T>();
- return static_cast<T*>(getFETokenInfoAsVoidSlow());
+ /// Get and set FETokenInfo. The language front-end is allowed to associate
+ /// arbitrary metadata with some kinds of declaration names, including normal
+ /// identifiers and C++ constructors, destructors, and conversion functions.
+ void *getFETokenInfo() const {
+ assert(getPtr() && "getFETokenInfo on an empty DeclarationName!");
+ if (getStoredNameKind() == StoredIdentifier)
+ return castAsIdentifierInfo()->getFETokenInfo();
+ return getFETokenInfoSlow();
}
- void setFETokenInfo(void *T);
+ void setFETokenInfo(void *T) {
+ assert(getPtr() && "setFETokenInfo on an empty DeclarationName!");
+ if (getStoredNameKind() == StoredIdentifier)
+ castAsIdentifierInfo()->setFETokenInfo(T);
+ else
+ setFETokenInfoSlow(T);
+ }
- /// operator== - Determine whether the specified names are identical..
+ /// Determine whether the specified names are identical.
friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
return LHS.Ptr == RHS.Ptr;
}
- /// operator!= - Determine whether the specified names are different.
+ /// Determine whether the specified names are different.
friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
return LHS.Ptr != RHS.Ptr;
}
static DeclarationName getEmptyMarker() {
- return DeclarationName(uintptr_t(-1));
+ DeclarationName Name;
+ Name.Ptr = uintptr_t(-1);
+ return Name;
}
static DeclarationName getTombstoneMarker() {
- return DeclarationName(uintptr_t(-2));
+ DeclarationName Name;
+ Name.Ptr = uintptr_t(-2);
+ return Name;
}
static int compare(DeclarationName LHS, DeclarationName RHS);
@@ -343,67 +560,88 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
return DeclarationName::compare(LHS, RHS) >= 0;
}
-/// DeclarationNameTable - Used to store and retrieve DeclarationName
+/// DeclarationNameTable is used to store and retrieve DeclarationName
/// instances for the various kinds of declaration names, e.g., normal
/// identifiers, C++ constructor names, etc. This class contains
/// uniqued versions of each of the C++ special names, which can be
-/// retrieved using its member functions (e.g.,
-/// getCXXConstructorName).
+/// retrieved using its member functions (e.g., getCXXConstructorName).
class DeclarationNameTable {
+ /// Used to allocate elements in the FoldingSets below.
const ASTContext &Ctx;
- // Actually a FoldingSet<CXXSpecialName> *
- void *CXXSpecialNamesImpl;
-
- // Operator names
- CXXOperatorIdName *CXXOperatorNames;
-
- // Actually a CXXOperatorIdName*
- void *CXXLiteralOperatorNames;
-
- // FoldingSet<CXXDeductionGuideNameExtra> *
- void *CXXDeductionGuideNames;
+ /// Manage the uniqued CXXSpecialNameExtra representing C++ constructors.
+ /// getCXXConstructorName and getCXXSpecialName can be used to obtain
+ /// a DeclarationName from the corresponding type of the constructor.
+ llvm::FoldingSet<detail::CXXSpecialNameExtra> CXXConstructorNames;
+
+ /// Manage the uniqued CXXSpecialNameExtra representing C++ destructors.
+ /// getCXXDestructorName and getCXXSpecialName can be used to obtain
+ /// a DeclarationName from the corresponding type of the destructor.
+ llvm::FoldingSet<detail::CXXSpecialNameExtra> CXXDestructorNames;
+
+ /// Manage the uniqued CXXSpecialNameExtra representing C++ conversion
+ /// functions. getCXXConversionFunctionName and getCXXSpecialName can be
+ /// used to obtain a DeclarationName from the corresponding type of the
+ /// conversion function.
+ llvm::FoldingSet<detail::CXXSpecialNameExtra> CXXConversionFunctionNames;
+
+ /// Manage the uniqued CXXOperatorIdName, which contain extra information
+ /// for the name of overloaded C++ operators. getCXXOperatorName
+ /// can be used to obtain a DeclarationName from the operator kind.
+ detail::CXXOperatorIdName CXXOperatorNames[NUM_OVERLOADED_OPERATORS];
+
+ /// Manage the uniqued CXXLiteralOperatorIdName, which contain extra
+ /// information for the name of C++ literal operators.
+ /// getCXXLiteralOperatorName can be used to obtain a DeclarationName
+ /// from the corresponding IdentifierInfo.
+ llvm::FoldingSet<detail::CXXLiteralOperatorIdName> CXXLiteralOperatorNames;
+
+ /// Manage the uniqued CXXDeductionGuideNameExtra, which contain
+ /// extra information for the name of a C++ deduction guide.
+ /// getCXXDeductionGuideName can be used to obtain a DeclarationName
+ /// from the corresponding template declaration.
+ llvm::FoldingSet<detail::CXXDeductionGuideNameExtra> CXXDeductionGuideNames;
public:
DeclarationNameTable(const ASTContext &C);
DeclarationNameTable(const DeclarationNameTable &) = delete;
DeclarationNameTable &operator=(const DeclarationNameTable &) = delete;
+ DeclarationNameTable(DeclarationNameTable &&) = delete;
+ DeclarationNameTable &operator=(DeclarationNameTable &&) = delete;
+ ~DeclarationNameTable() = default;
- ~DeclarationNameTable();
-
- /// getIdentifier - Create a declaration name that is a simple
- /// identifier.
+ /// Create a declaration name that is a simple identifier.
DeclarationName getIdentifier(const IdentifierInfo *ID) {
return DeclarationName(ID);
}
- /// getCXXConstructorName - Returns the name of a C++ constructor
- /// for the given Type.
+ /// Returns the name of a C++ constructor for the given Type.
DeclarationName getCXXConstructorName(CanQualType Ty);
- /// getCXXDestructorName - Returns the name of a C++ destructor
- /// for the given Type.
+ /// Returns the name of a C++ destructor for the given Type.
DeclarationName getCXXDestructorName(CanQualType Ty);
/// Returns the name of a C++ deduction guide for the given template.
DeclarationName getCXXDeductionGuideName(TemplateDecl *TD);
- /// getCXXConversionFunctionName - Returns the name of a C++
- /// conversion function for the given Type.
+ /// Returns the name of a C++ conversion function for the given Type.
DeclarationName getCXXConversionFunctionName(CanQualType Ty);
- /// getCXXSpecialName - Returns a declaration name for special kind
- /// of C++ name, e.g., for a constructor, destructor, or conversion
- /// function.
+ /// Returns a declaration name for special kind of C++ name,
+ /// e.g., for a constructor, destructor, or conversion function.
+ /// Kind must be one of:
+ /// * DeclarationName::CXXConstructorName,
+ /// * DeclarationName::CXXDestructorName or
+ /// * DeclarationName::CXXConversionFunctionName
DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
CanQualType Ty);
- /// getCXXOperatorName - Get the name of the overloadable C++
- /// operator corresponding to Op.
- DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
+ /// Get the name of the overloadable C++ operator corresponding to Op.
+ DeclarationName getCXXOperatorName(OverloadedOperatorKind Op) {
+ return DeclarationName(&CXXOperatorNames[Op]);
+ }
- /// getCXXLiteralOperatorName - Get the name of the literal operator function
- /// with II as the identifier.
+ /// Get the name of the literal operator function with II as the identifier.
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
};
@@ -491,9 +729,10 @@ public:
/// getNamedTypeInfo - Returns the source type info associated to
/// the name. Assumes it is a constructor, destructor or conversion.
TypeSourceInfo *getNamedTypeInfo() const {
- assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
- Name.getNameKind() == DeclarationName::CXXDestructorName ||
- Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
+ if (Name.getNameKind() != DeclarationName::CXXConstructorName &&
+ Name.getNameKind() != DeclarationName::CXXDestructorName &&
+ Name.getNameKind() != DeclarationName::CXXConversionFunctionName)
+ return nullptr;
return LocInfo.NamedType.TInfo;
}
@@ -509,7 +748,8 @@ public:
/// getCXXOperatorNameRange - Gets the range of the operator name
/// (without the operator keyword). Assumes it is a (non-literal) operator.
SourceRange getCXXOperatorNameRange() const {
- assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
+ if (Name.getNameKind() != DeclarationName::CXXOperatorName)
+ return SourceRange();
return SourceRange(
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
@@ -528,7 +768,8 @@ public:
/// operator name (not the operator keyword).
/// Assumes it is a literal operator.
SourceLocation getCXXLiteralOperatorNameLoc() const {
- assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
+ if (Name.getNameKind() != DeclarationName::CXXLiteralOperatorName)
+ return SourceLocation();
return SourceLocation::
getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
}
@@ -557,22 +798,16 @@ public:
/// getBeginLoc - Retrieve the location of the first token.
SourceLocation getBeginLoc() const { return NameLoc; }
- /// getEndLoc - Retrieve the location of the last token.
- SourceLocation getEndLoc() const { return getLocEnd(); }
-
/// getSourceRange - The range of the declaration name.
SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(getLocStart(), getLocEnd());
+ return SourceRange(getBeginLoc(), getEndLoc());
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getBeginLoc();
- }
-
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
SourceLocation EndLoc = getEndLocPrivate();
- return EndLoc.isValid() ? EndLoc : getLocStart();
+ return EndLoc.isValid() ? EndLoc : getBeginLoc();
}
+
private:
SourceLocation getEndLocPrivate() const;
};
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index 1aec5ae842d4..f356584144e6 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/STLExtras.h"
namespace clang {
@@ -107,23 +108,22 @@ public:
};
/// EvaluatedExprVisitor - This class visits 'Expr *'s
-template<typename ImplClass>
+template <typename ImplClass>
class EvaluatedExprVisitor
- : public EvaluatedExprVisitorBase<make_ptr, ImplClass> {
+ : public EvaluatedExprVisitorBase<std::add_pointer, ImplClass> {
public:
- explicit EvaluatedExprVisitor(const ASTContext &Context) :
- EvaluatedExprVisitorBase<make_ptr, ImplClass>(Context) { }
+ explicit EvaluatedExprVisitor(const ASTContext &Context)
+ : EvaluatedExprVisitorBase<std::add_pointer, ImplClass>(Context) {}
};
/// ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
-template<typename ImplClass>
+template <typename ImplClass>
class ConstEvaluatedExprVisitor
- : public EvaluatedExprVisitorBase<make_const_ptr, ImplClass> {
+ : public EvaluatedExprVisitorBase<llvm::make_const_ptr, ImplClass> {
public:
- explicit ConstEvaluatedExprVisitor(const ASTContext &Context) :
- EvaluatedExprVisitorBase<make_const_ptr, ImplClass>(Context) { }
+ explicit ConstEvaluatedExprVisitor(const ASTContext &Context)
+ : EvaluatedExprVisitorBase<llvm::make_const_ptr, ImplClass>(Context) {}
};
-
}
#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index c18fbf05df68..3de73428829b 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -32,6 +32,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
namespace clang {
class APValue;
@@ -99,10 +100,9 @@ struct SubobjectAdjustment {
}
};
-/// Expr - This represents one expression. Note that Expr's are subclasses of
-/// Stmt. This allows an expression to be transparently used any place a Stmt
-/// is required.
-///
+/// This represents one expression. Note that Expr's are subclasses of Stmt.
+/// This allows an expression to be transparently used any place a Stmt is
+/// required.
class Expr : public Stmt {
QualType TR;
@@ -583,7 +583,8 @@ public:
/// this function returns true, it returns the folded constant in Result. If
/// the expression is a glvalue, an lvalue-to-rvalue conversion will be
/// applied.
- bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const;
+ bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
+ bool InConstantContext = false) const;
/// EvaluateAsBooleanCondition - Return true if this is a constant
/// which we can fold and convert to a boolean condition using
@@ -600,7 +601,7 @@ public:
/// EvaluateAsInt - Return true if this is a constant which we can fold and
/// convert to an integer, using any crazy technique that we want to.
- bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx,
+ bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// EvaluateAsFloat - Return true if this is a constant which we can fold and
@@ -632,8 +633,13 @@ public:
/// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
/// integer. This must be called on an expression that constant folds to an
/// integer.
- llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
- SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
+ llvm::APSInt EvaluateKnownConstInt(
+ const ASTContext &Ctx,
+ SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
+
+ llvm::APSInt EvaluateKnownConstIntCheckOverflow(
+ const ASTContext &Ctx,
+ SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
void EvaluateForOverflow(const ASTContext &Ctx) const;
@@ -864,6 +870,70 @@ public:
};
//===----------------------------------------------------------------------===//
+// Wrapper Expressions.
+//===----------------------------------------------------------------------===//
+
+/// FullExpr - Represents a "full-expression" node.
+class FullExpr : public Expr {
+protected:
+ Stmt *SubExpr;
+
+ FullExpr(StmtClass SC, Expr *subexpr)
+ : Expr(SC, subexpr->getType(),
+ subexpr->getValueKind(), subexpr->getObjectKind(),
+ subexpr->isTypeDependent(), subexpr->isValueDependent(),
+ subexpr->isInstantiationDependent(),
+ subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) {}
+ FullExpr(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty) {}
+public:
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+
+ /// As with any mutator of the AST, be very careful when modifying an
+ /// existing AST to preserve its invariants.
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstFullExprConstant &&
+ T->getStmtClass() <= lastFullExprConstant;
+ }
+};
+
+/// ConstantExpr - An expression that occurs in a constant context.
+class ConstantExpr : public FullExpr {
+ ConstantExpr(Expr *subexpr)
+ : FullExpr(ConstantExprClass, subexpr) {}
+
+public:
+ static ConstantExpr *Create(const ASTContext &Context, Expr *E) {
+ assert(!isa<ConstantExpr>(E));
+ return new (Context) ConstantExpr(E);
+ }
+
+ /// Build an empty constant expression wrapper.
+ explicit ConstantExpr(EmptyShell Empty)
+ : FullExpr(ConstantExprClass, Empty) {}
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SubExpr->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExpr->getEndLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConstantExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+ const_child_range children() const {
+ return const_child_range(&SubExpr, &SubExpr + 1);
+ }
+};
+
+//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
@@ -875,7 +945,6 @@ public:
class OpaqueValueExpr : public Expr {
friend class ASTStmtReader;
Expr *SourceExpr;
- SourceLocation Loc;
public:
OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
@@ -889,8 +958,9 @@ public:
T->isInstantiationDependentType() ||
(SourceExpr && SourceExpr->isInstantiationDependent()),
false),
- SourceExpr(SourceExpr), Loc(Loc) {
+ SourceExpr(SourceExpr) {
setIsUnique(false);
+ OpaqueValueExprBits.Loc = Loc;
}
/// Given an expression which invokes a copy constructor --- i.e. a
@@ -899,20 +969,19 @@ public:
static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);
explicit OpaqueValueExpr(EmptyShell Empty)
- : Expr(OpaqueValueExprClass, Empty) { }
+ : Expr(OpaqueValueExprClass, Empty) {}
/// Retrieve the location of this expression.
- SourceLocation getLocation() const { return Loc; }
+ SourceLocation getLocation() const { return OpaqueValueExprBits.Loc; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return SourceExpr ? SourceExpr->getLocStart() : Loc;
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SourceExpr ? SourceExpr->getBeginLoc() : getLocation();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SourceExpr ? SourceExpr->getLocEnd() : Loc;
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SourceExpr ? SourceExpr->getEndLoc() : getLocation();
}
SourceLocation getExprLoc() const LLVM_READONLY {
- if (SourceExpr) return SourceExpr->getExprLoc();
- return Loc;
+ return SourceExpr ? SourceExpr->getExprLoc() : getLocation();
}
child_range children() {
@@ -974,63 +1043,52 @@ class DeclRefExpr final
private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
NamedDecl *, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// The declaration that we are referencing.
ValueDecl *D;
- /// The location of the declaration name itself.
- SourceLocation Loc;
-
/// Provides source/type location info for the declaration name
/// embedded in D.
DeclarationNameLoc DNLoc;
size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
- return hasQualifier() ? 1 : 0;
+ return hasQualifier();
}
size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
- return hasFoundDecl() ? 1 : 0;
+ return hasFoundDecl();
}
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return hasTemplateKWAndArgsInfo() ? 1 : 0;
+ return hasTemplateKWAndArgsInfo();
}
/// Test whether there is a distinct FoundDecl attached to the end of
/// this DRE.
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
- DeclRefExpr(const ASTContext &Ctx,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *D, bool RefersToEnlosingVariableOrCapture,
- const DeclarationNameInfo &NameInfo,
- NamedDecl *FoundD,
- const TemplateArgumentListInfo *TemplateArgs,
- QualType T, ExprValueKind VK);
+ DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
+ bool RefersToEnlosingVariableOrCapture,
+ const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
+ const TemplateArgumentListInfo *TemplateArgs, QualType T,
+ ExprValueKind VK);
/// Construct an empty declaration reference expression.
- explicit DeclRefExpr(EmptyShell Empty)
- : Expr(DeclRefExprClass, Empty) { }
+ explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {}
/// Computes the type- and value-dependence flags for this
/// declaration reference expression.
- void computeDependence(const ASTContext &C);
+ void computeDependence(const ASTContext &Ctx);
public:
- DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T,
+ DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
+ bool RefersToEnclosingVariableOrCapture, QualType T,
ExprValueKind VK, SourceLocation L,
- const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
- : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
- D(D), Loc(L), DNLoc(LocInfo) {
- DeclRefExprBits.HasQualifier = 0;
- DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
- DeclRefExprBits.HasFoundDecl = 0;
- DeclRefExprBits.HadMultipleCandidates = 0;
- DeclRefExprBits.RefersToEnclosingVariableOrCapture =
- RefersToEnclosingVariableOrCapture;
- computeDependence(D->getASTContext());
- }
+ const DeclarationNameLoc &LocInfo = DeclarationNameLoc());
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
@@ -1048,8 +1106,7 @@ public:
const TemplateArgumentListInfo *TemplateArgs = nullptr);
/// Construct an empty declaration reference expression.
- static DeclRefExpr *CreateEmpty(const ASTContext &Context,
- bool HasQualifier,
+ static DeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
bool HasFoundDecl,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
@@ -1059,13 +1116,13 @@ public:
void setDecl(ValueDecl *NewD) { D = NewD; }
DeclarationNameInfo getNameInfo() const {
- return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
+ return DeclarationNameInfo(getDecl()->getDeclName(), getLocation(), DNLoc);
}
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getLocation() const { return DeclRefExprBits.Loc; }
+ void setLocation(SourceLocation L) { DeclRefExprBits.Loc = L; }
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
/// Determine whether this declaration reference was preceded by a
/// C++ nested-name-specifier, e.g., \c N::foo.
@@ -1108,21 +1165,24 @@ public:
/// Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
- if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
- if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
- if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
@@ -1147,7 +1207,6 @@ public:
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return nullptr;
-
return getTrailingObjects<TemplateArgumentLoc>();
}
@@ -1156,7 +1215,6 @@ public:
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return 0;
-
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
@@ -1194,68 +1252,6 @@ public:
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
-
- friend TrailingObjects;
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-};
-
-/// [C99 6.4.2.2] - A predefined identifier such as __func__.
-class PredefinedExpr : public Expr {
-public:
- enum IdentType {
- Func,
- Function,
- LFunction, // Same as Function, but as wide string.
- FuncDName,
- FuncSig,
- LFuncSig, // Same as FuncSig, but as as wide string
- PrettyFunction,
- /// The same as PrettyFunction, except that the
- /// 'virtual' keyword is omitted for virtual member functions.
- PrettyFunctionNoVirtual
- };
-
-private:
- SourceLocation Loc;
- IdentType Type;
- Stmt *FnName;
-
-public:
- PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
- StringLiteral *SL);
-
- /// Construct an empty predefined expression.
- explicit PredefinedExpr(EmptyShell Empty)
- : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {}
-
- IdentType getIdentType() const { return Type; }
-
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
-
- StringLiteral *getFunctionName();
- const StringLiteral *getFunctionName() const {
- return const_cast<PredefinedExpr *>(this)->getFunctionName();
- }
-
- static StringRef getIdentTypeName(IdentType IT);
- static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
-
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == PredefinedExprClass;
- }
-
- // Iterators
- child_range children() { return child_range(&FnName, &FnName + 1); }
- const_child_range children() const {
- return const_child_range(&FnName, &FnName + 1);
- }
-
- friend class ASTStmtReader;
};
/// Used by IntegerLiteral/FloatingLiteral to store the numeric without
@@ -1331,8 +1327,8 @@ public:
/// Returns a new empty integer literal.
static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty);
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
/// Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
@@ -1370,8 +1366,8 @@ class FixedPointLiteral : public Expr, public APIntStorage {
QualType type, SourceLocation l,
unsigned Scale);
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
/// \brief Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
@@ -1424,8 +1420,8 @@ public:
return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
}
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
unsigned getValue() const { return Value; }
@@ -1497,8 +1493,8 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == FloatingLiteralClass;
@@ -1534,8 +1530,10 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return Val->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Val->getEndLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImaginaryLiteralClass;
@@ -1549,14 +1547,15 @@ public:
};
/// StringLiteral - This represents a string literal expression, e.g. "foo"
-/// or L"bar" (wide strings). The actual string is returned by getBytes()
-/// is NOT null-terminated, and the length of the string is determined by
-/// calling getByteLength(). The C type for a string is always a
-/// ConstantArrayType. In C++, the char type is const qualified, in C it is
-/// not.
+/// or L"bar" (wide strings). The actual string data can be obtained with
+/// getBytes() and is NOT null-terminated. The length of the string data is
+/// determined by calling getByteLength().
+///
+/// The C type for a string is always a ConstantArrayType. In C++, the char
+/// type is const qualified, in C it is not.
///
/// Note that strings in C can be formed by concatenation of multiple string
-/// literal pptokens in translation phase #6. This keeps track of the locations
+/// literal pptokens in translation phase #6. This keeps track of the locations
/// of each of these pieces.
///
/// Strings in C can also be truncated and extended by assigning into arrays,
@@ -1564,131 +1563,156 @@ public:
/// char X[2] = "foobar";
/// In this case, getByteLength() will return 6, but the string literal will
/// have type "char[2]".
-class StringLiteral : public Expr {
+class StringLiteral final
+ : public Expr,
+ private llvm::TrailingObjects<StringLiteral, unsigned, SourceLocation,
+ char> {
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
+ /// StringLiteral is followed by several trailing objects. They are in order:
+ ///
+ /// * A single unsigned storing the length in characters of this string. The
+ /// length in bytes is this length times the width of a single character.
+ /// Always present and stored as a trailing objects because storing it in
+ /// StringLiteral would increase the size of StringLiteral by sizeof(void *)
+ /// due to alignment requirements. If you add some data to StringLiteral,
+ /// consider moving it inside StringLiteral.
+ ///
+ /// * An array of getNumConcatenated() SourceLocation, one for each of the
+ /// token this string is made of.
+ ///
+ /// * An array of getByteLength() char used to store the string data.
+
public:
- enum StringKind {
- Ascii,
- Wide,
- UTF8,
- UTF16,
- UTF32
- };
+ enum StringKind { Ascii, Wide, UTF8, UTF16, UTF32 };
private:
- friend class ASTStmtReader;
+ unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; }
+ unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
+ return getNumConcatenated();
+ }
- union {
- const char *asChar;
- const uint16_t *asUInt16;
- const uint32_t *asUInt32;
- } StrData;
- unsigned Length;
- unsigned CharByteWidth : 4;
- unsigned Kind : 3;
- unsigned IsPascal : 1;
- unsigned NumConcatenated;
- SourceLocation TokLocs[1];
-
- StringLiteral(QualType Ty) :
- Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
- false) {}
-
- static int mapCharByteWidth(TargetInfo const &target,StringKind k);
+ unsigned numTrailingObjects(OverloadToken<char>) const {
+ return getByteLength();
+ }
+
+ char *getStrDataAsChar() { return getTrailingObjects<char>(); }
+ const char *getStrDataAsChar() const { return getTrailingObjects<char>(); }
+
+ const uint16_t *getStrDataAsUInt16() const {
+ return reinterpret_cast<const uint16_t *>(getTrailingObjects<char>());
+ }
+
+ const uint32_t *getStrDataAsUInt32() const {
+ return reinterpret_cast<const uint32_t *>(getTrailingObjects<char>());
+ }
+
+ /// Build a string literal.
+ StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind,
+ bool Pascal, QualType Ty, const SourceLocation *Loc,
+ unsigned NumConcatenated);
+
+ /// Build an empty string literal.
+ StringLiteral(EmptyShell Empty, unsigned NumConcatenated, unsigned Length,
+ unsigned CharByteWidth);
+
+ /// Map a target and string kind to the appropriate character width.
+ static unsigned mapCharByteWidth(TargetInfo const &Target, StringKind SK);
+
+ /// Set one of the string literal token.
+ void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
+ assert(TokNum < getNumConcatenated() && "Invalid tok number");
+ getTrailingObjects<SourceLocation>()[TokNum] = L;
+ }
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
- static StringLiteral *Create(const ASTContext &C, StringRef Str,
+ static StringLiteral *Create(const ASTContext &Ctx, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
- const SourceLocation *Loc, unsigned NumStrs);
+ const SourceLocation *Loc,
+ unsigned NumConcatenated);
/// Simple constructor for string literals made from one token.
- static StringLiteral *Create(const ASTContext &C, StringRef Str,
+ static StringLiteral *Create(const ASTContext &Ctx, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
SourceLocation Loc) {
- return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
+ return Create(Ctx, Str, Kind, Pascal, Ty, &Loc, 1);
}
/// Construct an empty string literal.
- static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs);
+ static StringLiteral *CreateEmpty(const ASTContext &Ctx,
+ unsigned NumConcatenated, unsigned Length,
+ unsigned CharByteWidth);
StringRef getString() const {
- assert(CharByteWidth==1
- && "This function is used in places that assume strings use char");
- return StringRef(StrData.asChar, getByteLength());
+ assert(getCharByteWidth() == 1 &&
+ "This function is used in places that assume strings use char");
+ return StringRef(getStrDataAsChar(), getByteLength());
}
/// Allow access to clients that need the byte representation, such as
/// ASTWriterStmt::VisitStringLiteral().
StringRef getBytes() const {
// FIXME: StringRef may not be the right type to use as a result for this.
- if (CharByteWidth == 1)
- return StringRef(StrData.asChar, getByteLength());
- if (CharByteWidth == 4)
- return StringRef(reinterpret_cast<const char*>(StrData.asUInt32),
- getByteLength());
- assert(CharByteWidth == 2 && "unsupported CharByteWidth");
- return StringRef(reinterpret_cast<const char*>(StrData.asUInt16),
- getByteLength());
+ return StringRef(getStrDataAsChar(), getByteLength());
}
void outputString(raw_ostream &OS) const;
uint32_t getCodeUnit(size_t i) const {
- assert(i < Length && "out of bounds access");
- if (CharByteWidth == 1)
- return static_cast<unsigned char>(StrData.asChar[i]);
- if (CharByteWidth == 4)
- return StrData.asUInt32[i];
- assert(CharByteWidth == 2 && "unsupported CharByteWidth");
- return StrData.asUInt16[i];
+ assert(i < getLength() && "out of bounds access");
+ switch (getCharByteWidth()) {
+ case 1:
+ return static_cast<unsigned char>(getStrDataAsChar()[i]);
+ case 2:
+ return getStrDataAsUInt16()[i];
+ case 4:
+ return getStrDataAsUInt32()[i];
+ }
+ llvm_unreachable("Unsupported character width!");
}
- unsigned getByteLength() const { return CharByteWidth*Length; }
- unsigned getLength() const { return Length; }
- unsigned getCharByteWidth() const { return CharByteWidth; }
-
- /// Sets the string data to the given string data.
- void setString(const ASTContext &C, StringRef Str,
- StringKind Kind, bool IsPascal);
-
- StringKind getKind() const { return static_cast<StringKind>(Kind); }
+ unsigned getByteLength() const { return getCharByteWidth() * getLength(); }
+ unsigned getLength() const { return *getTrailingObjects<unsigned>(); }
+ unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; }
+ StringKind getKind() const {
+ return static_cast<StringKind>(StringLiteralBits.Kind);
+ }
- bool isAscii() const { return Kind == Ascii; }
- bool isWide() const { return Kind == Wide; }
- bool isUTF8() const { return Kind == UTF8; }
- bool isUTF16() const { return Kind == UTF16; }
- bool isUTF32() const { return Kind == UTF32; }
- bool isPascal() const { return IsPascal; }
+ bool isAscii() const { return getKind() == Ascii; }
+ bool isWide() const { return getKind() == Wide; }
+ bool isUTF8() const { return getKind() == UTF8; }
+ bool isUTF16() const { return getKind() == UTF16; }
+ bool isUTF32() const { return getKind() == UTF32; }
+ bool isPascal() const { return StringLiteralBits.IsPascal; }
bool containsNonAscii() const {
- StringRef Str = getString();
- for (unsigned i = 0, e = Str.size(); i != e; ++i)
- if (!isASCII(Str[i]))
+ for (auto c : getString())
+ if (!isASCII(c))
return true;
return false;
}
bool containsNonAsciiOrNull() const {
- StringRef Str = getString();
- for (unsigned i = 0, e = Str.size(); i != e; ++i)
- if (!isASCII(Str[i]) || !Str[i])
+ for (auto c : getString())
+ if (!isASCII(c) || !c)
return true;
return false;
}
/// getNumConcatenated - Get the number of string literal tokens that were
/// concatenated in translation phase #6 to form this string literal.
- unsigned getNumConcatenated() const { return NumConcatenated; }
+ unsigned getNumConcatenated() const {
+ return StringLiteralBits.NumConcatenated;
+ }
+ /// Get one of the string literal token.
SourceLocation getStrTokenLoc(unsigned TokNum) const {
- assert(TokNum < NumConcatenated && "Invalid tok number");
- return TokLocs[TokNum];
- }
- void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
- assert(TokNum < NumConcatenated && "Invalid tok number");
- TokLocs[TokNum] = L;
+ assert(TokNum < getNumConcatenated() && "Invalid tok number");
+ return getTrailingObjects<SourceLocation>()[TokNum];
}
/// getLocationOfByte - Return a source location that points to the specified
@@ -1705,14 +1729,18 @@ public:
unsigned *StartTokenByteOffset = nullptr) const;
typedef const SourceLocation *tokloc_iterator;
- tokloc_iterator tokloc_begin() const { return TokLocs; }
- tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; }
- SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return TokLocs[NumConcatenated - 1];
+ tokloc_iterator tokloc_begin() const {
+ return getTrailingObjects<SourceLocation>();
}
+ tokloc_iterator tokloc_end() const {
+ return getTrailingObjects<SourceLocation>() + getNumConcatenated();
+ }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY { return *tokloc_begin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return *(tokloc_end() - 1); }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == StringLiteralClass;
}
@@ -1726,6 +1754,91 @@ public:
}
};
+/// [C99 6.4.2.2] - A predefined identifier such as __func__.
+class PredefinedExpr final
+ : public Expr,
+ private llvm::TrailingObjects<PredefinedExpr, Stmt *> {
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
+ // PredefinedExpr is optionally followed by a single trailing
+ // "Stmt *" for the predefined identifier. It is present if and only if
+ // hasFunctionName() is true and is always a "StringLiteral *".
+
+public:
+ enum IdentKind {
+ Func,
+ Function,
+ LFunction, // Same as Function, but as wide string.
+ FuncDName,
+ FuncSig,
+ LFuncSig, // Same as FuncSig, but as as wide string
+ PrettyFunction,
+ /// The same as PrettyFunction, except that the
+ /// 'virtual' keyword is omitted for virtual member functions.
+ PrettyFunctionNoVirtual
+ };
+
+private:
+ PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
+ StringLiteral *SL);
+
+ explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);
+
+ /// True if this PredefinedExpr has storage for a function name.
+ bool hasFunctionName() const { return PredefinedExprBits.HasFunctionName; }
+
+ void setFunctionName(StringLiteral *SL) {
+ assert(hasFunctionName() &&
+ "This PredefinedExpr has no storage for a function name!");
+ *getTrailingObjects<Stmt *>() = SL;
+ }
+
+public:
+ /// Create a PredefinedExpr.
+ static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
+ QualType FNTy, IdentKind IK, StringLiteral *SL);
+
+ /// Create an empty PredefinedExpr.
+ static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
+ bool HasFunctionName);
+
+ IdentKind getIdentKind() const {
+ return static_cast<IdentKind>(PredefinedExprBits.Kind);
+ }
+
+ SourceLocation getLocation() const { return PredefinedExprBits.Loc; }
+ void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; }
+
+ StringLiteral *getFunctionName() {
+ return hasFunctionName()
+ ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
+ : nullptr;
+ }
+
+ const StringLiteral *getFunctionName() const {
+ return hasFunctionName()
+ ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
+ : nullptr;
+ }
+
+ static StringRef getIdentKindName(IdentKind IK);
+ static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl);
+
+ SourceLocation getBeginLoc() const { return getLocation(); }
+ SourceLocation getEndLoc() const { return getLocation(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PredefinedExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() + hasFunctionName());
+ }
+};
+
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
/// AST node is only formed if full location information is requested.
class ParenExpr : public Expr {
@@ -1748,8 +1861,8 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- SourceLocation getLocStart() const LLVM_READONLY { return L; }
- SourceLocation getLocEnd() const LLVM_READONLY { return R; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return L; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return R; }
/// Get the location of the left parentheses '('.
SourceLocation getLParen() const { return L; }
@@ -1781,15 +1894,11 @@ public:
/// later returns zero in the type of the operand.
///
class UnaryOperator : public Expr {
+ Stmt *Val;
+
public:
typedef UnaryOperatorKind Opcode;
-private:
- unsigned Opc : 5;
- unsigned CanOverflow : 1;
- SourceLocation Loc;
- Stmt *Val;
-public:
UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK,
ExprObjectKind OK, SourceLocation l, bool CanOverflow)
: Expr(UnaryOperatorClass, type, VK, OK,
@@ -1798,21 +1907,28 @@ public:
(input->isInstantiationDependent() ||
type->isInstantiationDependentType()),
input->containsUnexpandedParameterPack()),
- Opc(opc), CanOverflow(CanOverflow), Loc(l), Val(input) {}
+ Val(input) {
+ UnaryOperatorBits.Opc = opc;
+ UnaryOperatorBits.CanOverflow = CanOverflow;
+ UnaryOperatorBits.Loc = l;
+ }
/// Build an empty unary operator.
- explicit UnaryOperator(EmptyShell Empty)
- : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
+ explicit UnaryOperator(EmptyShell Empty) : Expr(UnaryOperatorClass, Empty) {
+ UnaryOperatorBits.Opc = UO_AddrOf;
+ }
- Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
- void setOpcode(Opcode O) { Opc = O; }
+ Opcode getOpcode() const {
+ return static_cast<Opcode>(UnaryOperatorBits.Opc);
+ }
+ void setOpcode(Opcode Opc) { UnaryOperatorBits.Opc = Opc; }
Expr *getSubExpr() const { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
/// getOperatorLoc - Return the location of the operator.
- SourceLocation getOperatorLoc() const { return Loc; }
- void setOperatorLoc(SourceLocation L) { Loc = L; }
+ SourceLocation getOperatorLoc() const { return UnaryOperatorBits.Loc; }
+ void setOperatorLoc(SourceLocation L) { UnaryOperatorBits.Loc = L; }
/// Returns true if the unary operator can cause an overflow. For instance,
/// signed int i = INT_MAX; i++;
@@ -1820,8 +1936,8 @@ public:
/// Due to integer promotions, c++ is promoted to an int before the postfix
/// increment, and the result is an int that cannot overflow. However, i++
/// can overflow.
- bool canOverflow() const { return CanOverflow; }
- void setCanOverflow(bool C) { CanOverflow = C; }
+ bool canOverflow() const { return UnaryOperatorBits.CanOverflow; }
+ void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; }
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op) {
@@ -1872,13 +1988,13 @@ public:
/// the given unary opcode.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
- SourceLocation getLocStart() const LLVM_READONLY {
- return isPostfix() ? Val->getLocStart() : Loc;
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return isPostfix() ? Val->getBeginLoc() : getOperatorLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return isPostfix() ? Loc : Val->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return isPostfix() ? getOperatorLoc() : Val->getEndLoc();
}
- SourceLocation getExprLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getExprLoc() const { return getOperatorLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryOperatorClass;
@@ -1980,8 +2096,8 @@ public:
/// contains the location of the period (if there is one) and the
/// identifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
};
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
@@ -2080,8 +2196,8 @@ public:
return NumExprs;
}
- SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OffsetOfExprClass;
@@ -2176,8 +2292,8 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return OpLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryExprOrTypeTraitExprClass;
@@ -2194,9 +2310,11 @@ public:
/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
class ArraySubscriptExpr : public Expr {
- enum { LHS, RHS, END_EXPR=2 };
- Stmt* SubExprs[END_EXPR];
- SourceLocation RBracketLoc;
+ enum { LHS, RHS, END_EXPR };
+ Stmt *SubExprs[END_EXPR];
+
+ bool lhsIsBase() const { return getRHS()->getType()->isIntegerType(); }
+
public:
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
ExprValueKind VK, ExprObjectKind OK,
@@ -2207,10 +2325,10 @@ public:
(lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(lhs->containsUnexpandedParameterPack() ||
- rhs->containsUnexpandedParameterPack())),
- RBracketLoc(rbracketloc) {
+ rhs->containsUnexpandedParameterPack())) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
+ ArraySubscriptExprBits.RBracketLoc = rbracketloc;
}
/// Create an empty array subscript expression.
@@ -2234,29 +2352,23 @@ public:
const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
- Expr *getBase() {
- return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS();
- }
+ Expr *getBase() { return lhsIsBase() ? getLHS() : getRHS(); }
+ const Expr *getBase() const { return lhsIsBase() ? getLHS() : getRHS(); }
- const Expr *getBase() const {
- return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS();
- }
+ Expr *getIdx() { return lhsIsBase() ? getRHS() : getLHS(); }
+ const Expr *getIdx() const { return lhsIsBase() ? getRHS() : getLHS(); }
- Expr *getIdx() {
- return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getLHS()->getBeginLoc();
}
+ SourceLocation getEndLoc() const { return getRBracketLoc(); }
- const Expr *getIdx() const {
- return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS();
+ SourceLocation getRBracketLoc() const {
+ return ArraySubscriptExprBits.RBracketLoc;
}
-
- SourceLocation getLocStart() const LLVM_READONLY {
- return getLHS()->getLocStart();
+ void setRBracketLoc(SourceLocation L) {
+ ArraySubscriptExprBits.RBracketLoc = L;
}
- SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
-
- SourceLocation getRBracketLoc() const { return RBracketLoc; }
- void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
SourceLocation getExprLoc() const LLVM_READONLY {
return getBase()->getExprLoc();
@@ -2282,127 +2394,221 @@ public:
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
/// "str1 + str2" to resolve to a function call.
class CallExpr : public Expr {
- enum { FN=0, PREARGS_START=1 };
- Stmt **SubExprs;
+ enum { FN = 0, PREARGS_START = 1 };
+
+ /// The number of arguments in the call expression.
unsigned NumArgs;
+
+ /// The location of the right parenthese. This has a different meaning for
+ /// the derived classes of CallExpr.
SourceLocation RParenLoc;
void updateDependenciesFromArg(Expr *Arg);
+ // CallExpr store some data in trailing objects. However since CallExpr
+ // is used a base of other expression classes we cannot use
+ // llvm::TrailingObjects. Instead we manually perform the pointer arithmetic
+ // and casts.
+ //
+ // The trailing objects are in order:
+ //
+ // * A single "Stmt *" for the callee expression.
+ //
+ // * An array of getNumPreArgs() "Stmt *" for the pre-argument expressions.
+ //
+ // * An array of getNumArgs() "Stmt *" for the argument expressions.
+ //
+ // Note that we store the offset in bytes from the this pointer to the start
+ // of the trailing objects. It would be perfectly possible to compute it
+ // based on the dynamic kind of the CallExpr. However 1.) we have plenty of
+ // space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to
+ // compute this once and then load the offset from the bit-fields of Stmt,
+ // instead of re-computing the offset each time the trailing objects are
+ // accessed.
+
+ /// Return a pointer to the start of the trailing array of "Stmt *".
+ Stmt **getTrailingStmts() {
+ return reinterpret_cast<Stmt **>(reinterpret_cast<char *>(this) +
+ CallExprBits.OffsetToTrailingObjects);
+ }
+ Stmt *const *getTrailingStmts() const {
+ return const_cast<CallExpr *>(this)->getTrailingStmts();
+ }
+
+ /// Map a statement class to the appropriate offset in bytes from the
+ /// this pointer to the trailing objects.
+ static unsigned offsetToTrailingObjects(StmtClass SC);
+
+public:
+ enum class ADLCallKind : bool { NotADL, UsesADL };
+ static constexpr ADLCallKind NotADL = ADLCallKind::NotADL;
+ static constexpr ADLCallKind UsesADL = ADLCallKind::UsesADL;
+
protected:
- // These versions of the constructor are for derived classes.
- CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
- ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t,
- ExprValueKind VK, SourceLocation rparenloc);
- CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args,
- QualType t, ExprValueKind VK, SourceLocation rparenloc);
- CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
+ /// Build a call expression, assuming that appropriate storage has been
+ /// allocated for the trailing objects.
+ CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL);
+
+ /// Build an empty call expression, for deserialization.
+ CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
EmptyShell Empty);
- Stmt *getPreArg(unsigned i) {
- assert(i < getNumPreArgs() && "Prearg access out of range!");
- return SubExprs[PREARGS_START+i];
+ /// Return the size in bytes needed for the trailing objects.
+ /// Used by the derived classes to allocate the right amount of storage.
+ static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs) {
+ return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *);
}
- const Stmt *getPreArg(unsigned i) const {
- assert(i < getNumPreArgs() && "Prearg access out of range!");
- return SubExprs[PREARGS_START+i];
+
+ Stmt *getPreArg(unsigned I) {
+ assert(I < getNumPreArgs() && "Prearg access out of range!");
+ return getTrailingStmts()[PREARGS_START + I];
+ }
+ const Stmt *getPreArg(unsigned I) const {
+ assert(I < getNumPreArgs() && "Prearg access out of range!");
+ return getTrailingStmts()[PREARGS_START + I];
}
- void setPreArg(unsigned i, Stmt *PreArg) {
- assert(i < getNumPreArgs() && "Prearg access out of range!");
- SubExprs[PREARGS_START+i] = PreArg;
+ void setPreArg(unsigned I, Stmt *PreArg) {
+ assert(I < getNumPreArgs() && "Prearg access out of range!");
+ getTrailingStmts()[PREARGS_START + I] = PreArg;
}
unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
public:
- CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
- ExprValueKind VK, SourceLocation rparenloc);
+ /// Create a call expression. Fn is the callee expression, Args is the
+ /// argument array, Ty is the type of the call expression (which is *not*
+ /// the return type in general), VK is the value kind of the call expression
+ /// (lvalue, rvalue, ...), and RParenLoc is the location of the right
+ /// parenthese in the call expression. MinNumArgs specifies the minimum
+ /// number of arguments. The actual number of arguments will be the greater
+ /// of Args.size() and MinNumArgs. This is used in a few places to allocate
+ /// enough storage for the default arguments. UsesADL specifies whether the
+ /// callee was found through argument-dependent lookup.
+ ///
+ /// Note that you can use CreateTemporary if you need a temporary call
+ /// expression on the stack.
+ static CallExpr *Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation RParenLoc, unsigned MinNumArgs = 0,
+ ADLCallKind UsesADL = NotADL);
+
+ /// Create a temporary call expression with no arguments in the memory
+ /// pointed to by Mem. Mem must points to at least sizeof(CallExpr)
+ /// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr):
+ ///
+ /// \code{.cpp}
+ /// llvm::AlignedCharArray<alignof(CallExpr),
+ /// sizeof(CallExpr) + sizeof(Stmt *)> Buffer;
+ /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.buffer, etc);
+ /// \endcode
+ static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
+ ExprValueKind VK, SourceLocation RParenLoc,
+ ADLCallKind UsesADL = NotADL);
- /// Build an empty call expression.
- CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty);
+ /// Create an empty call expression, for deserialization.
+ static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
+ EmptyShell Empty);
- const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
- Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
- void setCallee(Expr *F) { SubExprs[FN] = F; }
+ Expr *getCallee() { return cast<Expr>(getTrailingStmts()[FN]); }
+ const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); }
+ void setCallee(Expr *F) { getTrailingStmts()[FN] = F; }
- Decl *getCalleeDecl();
+ ADLCallKind getADLCallKind() const {
+ return static_cast<ADLCallKind>(CallExprBits.UsesADL);
+ }
+ void setADLCallKind(ADLCallKind V = UsesADL) {
+ CallExprBits.UsesADL = static_cast<bool>(V);
+ }
+ bool usesADL() const { return getADLCallKind() == UsesADL; }
+
+ Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); }
const Decl *getCalleeDecl() const {
- return const_cast<CallExpr*>(this)->getCalleeDecl();
+ return getCallee()->getReferencedDeclOfCallee();
}
- /// If the callee is a FunctionDecl, return it. Otherwise return 0.
- FunctionDecl *getDirectCallee();
+ /// If the callee is a FunctionDecl, return it. Otherwise return null.
+ FunctionDecl *getDirectCallee() {
+ return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
+ }
const FunctionDecl *getDirectCallee() const {
- return const_cast<CallExpr*>(this)->getDirectCallee();
+ return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
}
/// getNumArgs - Return the number of actual arguments to this call.
- ///
unsigned getNumArgs() const { return NumArgs; }
/// Retrieve the call arguments.
Expr **getArgs() {
- return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
+ return reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START +
+ getNumPreArgs());
}
const Expr *const *getArgs() const {
- return reinterpret_cast<Expr **>(SubExprs + getNumPreArgs() +
- PREARGS_START);
+ return reinterpret_cast<const Expr *const *>(
+ getTrailingStmts() + PREARGS_START + getNumPreArgs());
}
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
- assert(Arg < NumArgs && "Arg access out of range!");
- return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
+ assert(Arg < getNumArgs() && "Arg access out of range!");
+ return getArgs()[Arg];
}
const Expr *getArg(unsigned Arg) const {
- assert(Arg < NumArgs && "Arg access out of range!");
- return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
+ assert(Arg < getNumArgs() && "Arg access out of range!");
+ return getArgs()[Arg];
}
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
- assert(Arg < NumArgs && "Arg access out of range!");
- SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
+ assert(Arg < getNumArgs() && "Arg access out of range!");
+ getArgs()[Arg] = ArgExpr;
}
- /// setNumArgs - This changes the number of arguments present in this call.
- /// Any orphaned expressions are deleted by this, and any new operands are set
- /// to null.
- void setNumArgs(const ASTContext& C, unsigned NumArgs);
+ /// Reduce the number of arguments in this call expression. This is used for
+ /// example during error recovery to drop extra arguments. There is no way
+ /// to perform the opposite because: 1.) We don't track how much storage
+ /// we have for the argument array 2.) This would potentially require growing
+ /// the argument array, something we cannot support since the arguments are
+ /// stored in a trailing array.
+ void shrinkNumArgs(unsigned NewNumArgs) {
+ assert((NewNumArgs <= getNumArgs()) &&
+ "shrinkNumArgs cannot increase the number of arguments!");
+ NumArgs = NewNumArgs;
+ }
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
typedef llvm::iterator_range<arg_iterator> arg_range;
- typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
+ typedef llvm::iterator_range<const_arg_iterator> const_arg_range;
arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
- arg_const_range arguments() const {
- return arg_const_range(arg_begin(), arg_end());
+ const_arg_range arguments() const {
+ return const_arg_range(arg_begin(), arg_end());
}
- arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); }
- arg_iterator arg_end() {
- return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ arg_iterator arg_begin() {
+ return getTrailingStmts() + PREARGS_START + getNumPreArgs();
}
+ arg_iterator arg_end() { return arg_begin() + getNumArgs(); }
+
const_arg_iterator arg_begin() const {
- return SubExprs+PREARGS_START+getNumPreArgs();
- }
- const_arg_iterator arg_end() const {
- return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ return getTrailingStmts() + PREARGS_START + getNumPreArgs();
}
+ const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); }
/// This method provides fast access to all the subexpressions of
/// a CallExpr without going through the slower virtual child_iterator
/// interface. This provides efficient reverse iteration of the
/// subexpressions. This is currently used for CFG construction.
- ArrayRef<Stmt*> getRawSubExprs() {
- return llvm::makeArrayRef(SubExprs,
- getNumPreArgs() + PREARGS_START + getNumArgs());
+ ArrayRef<Stmt *> getRawSubExprs() {
+ return llvm::makeArrayRef(getTrailingStmts(),
+ PREARGS_START + getNumPreArgs() + getNumArgs());
}
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
- unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
+ unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; }
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID
/// of the callee. If not, return 0.
@@ -2417,18 +2623,27 @@ public:
/// type.
QualType getCallReturnType(const ASTContext &Ctx) const;
+ /// Returns the WarnUnusedResultAttr that is either declared on the called
+ /// function, or its return type declaration.
+ const Attr *getUnusedResultAttr(const ASTContext &Ctx) const;
+
+ /// Returns true if this call expression should warn on unused results.
+ bool hasUnusedResultAttr(const ASTContext &Ctx) const {
+ return getUnusedResultAttr(Ctx) != nullptr;
+ }
+
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
/// Return true if this is a call to __assume() or __builtin_assume() with
/// a non-value-dependent constant parameter evaluating as false.
bool isBuiltinAssumeFalse(const ASTContext &Ctx) const;
bool isCallToStdMove() const {
- const FunctionDecl* FD = getDirectCallee();
+ const FunctionDecl *FD = getDirectCallee();
return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
FD->getIdentifier() && FD->getIdentifier()->isStr("move");
}
@@ -2440,13 +2655,14 @@ public:
// Iterators
child_range children() {
- return child_range(&SubExprs[0],
- &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
+ return child_range(getTrailingStmts(), getTrailingStmts() + PREARGS_START +
+ getNumPreArgs() + getNumArgs());
}
const_child_range children() const {
- return const_child_range(&SubExprs[0], &SubExprs[0] + NumArgs +
- getNumPreArgs() + PREARGS_START);
+ return const_child_range(getTrailingStmts(),
+ getTrailingStmts() + PREARGS_START +
+ getNumPreArgs() + getNumArgs());
}
};
@@ -2468,6 +2684,10 @@ class MemberExpr final
private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier,
ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
+ friend class ASTReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
@@ -2483,35 +2703,20 @@ class MemberExpr final
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
- /// This is the location of the -> or . in the expression.
- SourceLocation OperatorLoc;
-
- /// IsArrow - True if this is "X->F", false if this is "X.F".
- bool IsArrow : 1;
-
- /// True if this member expression used a nested-name-specifier to
- /// refer to the member, e.g., "x->Base::f", or found its member via a using
- /// declaration. When true, a MemberExprNameQualifier
- /// structure is allocated immediately after the MemberExpr.
- bool HasQualifierOrFoundDecl : 1;
-
- /// True if this member expression specified a template keyword
- /// and/or a template argument list explicitly, e.g., x->f<int>,
- /// x->template f, x->template f<int>.
- /// When true, an ASTTemplateKWAndArgsInfo structure and its
- /// TemplateArguments (if any) are present.
- bool HasTemplateKWAndArgsInfo : 1;
-
- /// True if this member expression refers to a method that
- /// was resolved from an overloaded set having size greater than 1.
- bool HadMultipleCandidates : 1;
-
size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const {
- return HasQualifierOrFoundDecl ? 1 : 0;
+ return hasQualifierOrFoundDecl();
}
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
+ return hasTemplateKWAndArgsInfo();
+ }
+
+ bool hasQualifierOrFoundDecl() const {
+ return MemberExprBits.HasQualifierOrFoundDecl;
+ }
+
+ bool hasTemplateKWAndArgsInfo() const {
+ return MemberExprBits.HasTemplateKWAndArgsInfo;
}
public:
@@ -2522,10 +2727,13 @@ public:
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
- MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc),
- IsArrow(isarrow), HasQualifierOrFoundDecl(false),
- HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {
+ MemberLoc(NameInfo.getLoc()) {
assert(memberdecl->getDeclName() == NameInfo.getName());
+ MemberExprBits.IsArrow = isarrow;
+ MemberExprBits.HasQualifierOrFoundDecl = false;
+ MemberExprBits.HasTemplateKWAndArgsInfo = false;
+ MemberExprBits.HadMultipleCandidates = false;
+ MemberExprBits.OperatorLoc = operatorloc;
}
// NOTE: this constructor should be used only when it is known that
@@ -2538,10 +2746,13 @@ public:
: Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
- Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
- OperatorLoc(operatorloc), IsArrow(isarrow),
- HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
- HadMultipleCandidates(false) {}
+ Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l) {
+ MemberExprBits.IsArrow = isarrow;
+ MemberExprBits.HasQualifierOrFoundDecl = false;
+ MemberExprBits.HasTemplateKWAndArgsInfo = false;
+ MemberExprBits.HadMultipleCandidates = false;
+ MemberExprBits.OperatorLoc = operatorloc;
+ }
static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
SourceLocation OperatorLoc,
@@ -2564,7 +2775,7 @@ public:
/// Retrieves the declaration found by lookup.
DeclAccessPair getFoundDecl() const {
- if (!HasQualifierOrFoundDecl)
+ if (!hasQualifierOrFoundDecl())
return DeclAccessPair::make(getMemberDecl(),
getMemberDecl()->getAccess());
return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
@@ -2579,9 +2790,8 @@ public:
/// nested-name-specifier that precedes the member name, with source-location
/// information.
NestedNameSpecifierLoc getQualifierLoc() const {
- if (!HasQualifierOrFoundDecl)
+ if (!hasQualifierOrFoundDecl())
return NestedNameSpecifierLoc();
-
return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
}
@@ -2595,21 +2805,24 @@ public:
/// Retrieve the location of the template keyword preceding
/// the member name, if any.
SourceLocation getTemplateKeywordLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
@@ -2656,18 +2869,18 @@ public:
MemberLoc, MemberDNLoc);
}
- SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; }
+ SourceLocation getOperatorLoc() const { return MemberExprBits.OperatorLoc; }
- bool isArrow() const { return IsArrow; }
- void setArrow(bool A) { IsArrow = A; }
+ bool isArrow() const { return MemberExprBits.IsArrow; }
+ void setArrow(bool A) { MemberExprBits.IsArrow = A; }
/// getMemberLoc - Return the location of the "member", in X->F, it is the
/// location of 'F'.
SourceLocation getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; }
@@ -2679,13 +2892,13 @@ public:
/// Returns true if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
- return HadMultipleCandidates;
+ return MemberExprBits.HadMultipleCandidates;
}
/// Sets the flag telling whether this expression refers to
/// a method that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
- HadMultipleCandidates = V;
+ MemberExprBits.HadMultipleCandidates = V;
}
/// Returns true if virtual dispatch is performed.
@@ -2705,10 +2918,6 @@ public:
const_child_range children() const {
return const_child_range(&Base, &Base + 1);
}
-
- friend TrailingObjects;
- friend class ASTReader;
- friend class ASTStmtWriter;
};
/// CompoundLiteralExpr - [C99 6.5.2.5]
@@ -2756,19 +2965,19 @@ public:
TInfoAndScope.setPointer(tinfo);
}
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
// FIXME: Init should never be null.
if (!Init)
return SourceLocation();
if (LParenLoc.isInvalid())
- return Init->getLocStart();
+ return Init->getBeginLoc();
return LParenLoc;
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
// FIXME: Init should never be null.
if (!Init)
return SourceLocation();
- return Init->getLocEnd();
+ return Init->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -2787,28 +2996,15 @@ public:
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
-public:
- using BasePathSizeTy = unsigned int;
- static_assert(std::numeric_limits<BasePathSizeTy>::max() >= 16384,
- "[implimits] Direct and indirect base classes [16384].");
-
-private:
Stmt *Op;
bool CastConsistency() const;
- BasePathSizeTy *BasePathSize();
-
const CXXBaseSpecifier * const *path_buffer() const {
return const_cast<CastExpr*>(this)->path_buffer();
}
CXXBaseSpecifier **path_buffer();
- void setBasePathSize(BasePathSizeTy basePathSize) {
- assert(!path_empty() && basePathSize != 0);
- *(BasePathSize()) = basePathSize;
- }
-
protected:
CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,
Expr *op, unsigned BasePathSize)
@@ -2829,9 +3025,9 @@ protected:
Op(op) {
CastExprBits.Kind = kind;
CastExprBits.PartOfExplicitCast = false;
- CastExprBits.BasePathIsEmpty = BasePathSize == 0;
- if (!path_empty())
- setBasePathSize(BasePathSize);
+ CastExprBits.BasePathSize = BasePathSize;
+ assert((CastExprBits.BasePathSize == BasePathSize) &&
+ "BasePathSize overflow!");
assert(CastConsistency());
}
@@ -2839,9 +3035,9 @@ protected:
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
: Expr(SC, Empty) {
CastExprBits.PartOfExplicitCast = false;
- CastExprBits.BasePathIsEmpty = BasePathSize == 0;
- if (!path_empty())
- setBasePathSize(BasePathSize);
+ CastExprBits.BasePathSize = BasePathSize;
+ assert((CastExprBits.BasePathSize == BasePathSize) &&
+ "BasePathSize overflow!");
}
public:
@@ -2868,13 +3064,9 @@ public:
NamedDecl *getConversionFunction() const;
typedef CXXBaseSpecifier **path_iterator;
- typedef const CXXBaseSpecifier * const *path_const_iterator;
- bool path_empty() const { return CastExprBits.BasePathIsEmpty; }
- unsigned path_size() const {
- if (path_empty())
- return 0U;
- return *(const_cast<CastExpr *>(this)->BasePathSize());
- }
+ typedef const CXXBaseSpecifier *const *path_const_iterator;
+ bool path_empty() const { return path_size() == 0; }
+ unsigned path_size() const { return CastExprBits.BasePathSize; }
path_iterator path_begin() { return path_buffer(); }
path_iterator path_end() { return path_buffer() + path_size(); }
path_const_iterator path_begin() const { return path_buffer(); }
@@ -2922,17 +3114,11 @@ public:
/// @endcode
class ImplicitCastExpr final
: public CastExpr,
- private llvm::TrailingObjects<ImplicitCastExpr, CastExpr::BasePathSizeTy,
- CXXBaseSpecifier *> {
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
+ private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
-private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
- : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
- }
+ : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { }
/// Construct an empty implicit cast.
explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
@@ -2958,11 +3144,11 @@ public:
static ImplicitCastExpr *CreateEmpty(const ASTContext &Context,
unsigned PathSize);
- SourceLocation getLocStart() const LLVM_READONLY {
- return getSubExpr()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getSubExpr()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getSubExpr()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getSubExpr()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -2975,8 +3161,13 @@ public:
inline Expr *Expr::IgnoreImpCasts() {
Expr *e = this;
- while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
- e = ice->getSubExpr();
+ while (true)
+ if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
+ e = ice->getSubExpr();
+ else if (FullExpr *fe = dyn_cast<FullExpr>(e))
+ e = fe->getSubExpr();
+ else
+ break;
return e;
}
@@ -3032,8 +3223,7 @@ public:
/// (Type)expr. For example: @c (int)f.
class CStyleCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<CStyleCastExpr, CastExpr::BasePathSizeTy,
- CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
@@ -3047,10 +3237,6 @@ class CStyleCastExpr final
explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
-
public:
static CStyleCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K,
@@ -3067,9 +3253,9 @@ public:
SourceLocation getRParenLoc() const { return RPLoc; }
void setRParenLoc(SourceLocation L) { RPLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return LPLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getSubExpr()->getLocEnd();
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getSubExpr()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -3099,20 +3285,11 @@ public:
/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will
/// be used to express the computation.
class BinaryOperator : public Expr {
-public:
- typedef BinaryOperatorKind Opcode;
-
-private:
- unsigned Opc : 6;
-
- // This is only meaningful for operations on floating point types and 0
- // otherwise.
- unsigned FPFeatures : 2;
- SourceLocation OpLoc;
-
enum { LHS, RHS, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+ Stmt *SubExprs[END_EXPR];
+
public:
+ typedef BinaryOperatorKind Opcode;
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
ExprValueKind VK, ExprObjectKind OK,
@@ -3123,8 +3300,10 @@ public:
(lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(lhs->containsUnexpandedParameterPack() ||
- rhs->containsUnexpandedParameterPack())),
- Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) {
+ rhs->containsUnexpandedParameterPack())) {
+ BinaryOperatorBits.Opc = opc;
+ BinaryOperatorBits.FPFeatures = FPFeatures.getInt();
+ BinaryOperatorBits.OpLoc = opLoc;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
assert(!isCompoundAssignmentOp() &&
@@ -3132,26 +3311,29 @@ public:
}
/// Construct an empty binary operator.
- explicit BinaryOperator(EmptyShell Empty)
- : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
+ explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) {
+ BinaryOperatorBits.Opc = BO_Comma;
+ }
- SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; }
- SourceLocation getOperatorLoc() const { return OpLoc; }
- void setOperatorLoc(SourceLocation L) { OpLoc = L; }
+ SourceLocation getExprLoc() const { return getOperatorLoc(); }
+ SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; }
+ void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; }
- Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
- void setOpcode(Opcode O) { Opc = O; }
+ Opcode getOpcode() const {
+ return static_cast<Opcode>(BinaryOperatorBits.Opc);
+ }
+ void setOpcode(Opcode Opc) { BinaryOperatorBits.Opc = Opc; }
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
void setLHS(Expr *E) { SubExprs[LHS] = E; }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return getLHS()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getLHS()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getRHS()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getRHS()->getEndLoc();
}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
@@ -3169,7 +3351,11 @@ public:
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
/// predicates to categorize the respective opcodes.
- bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
+ static bool isPtrMemOp(Opcode Opc) {
+ return Opc == BO_PtrMemD || Opc == BO_PtrMemI;
+ }
+ bool isPtrMemOp() const { return isPtrMemOp(getOpcode()); }
+
static bool isMultiplicativeOp(Opcode Opc) {
return Opc >= BO_Mul && Opc <= BO_Rem;
}
@@ -3268,16 +3454,24 @@ public:
// Set the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
- void setFPFeatures(FPOptions F) { FPFeatures = F.getInt(); }
+ void setFPFeatures(FPOptions F) {
+ BinaryOperatorBits.FPFeatures = F.getInt();
+ }
- FPOptions getFPFeatures() const { return FPOptions(FPFeatures); }
+ FPOptions getFPFeatures() const {
+ return FPOptions(BinaryOperatorBits.FPFeatures);
+ }
// Get the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
bool isFPContractableWithinStatement() const {
- return FPOptions(FPFeatures).allowFPContractWithinStatement();
+ return getFPFeatures().allowFPContractWithinStatement();
}
+ // Get the FENV_ACCESS status of this operator. Only meaningful for
+ // operations on floating point types.
+ bool isFEnvAccessOn() const { return getFPFeatures().allowFEnvAccess(); }
+
protected:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
ExprValueKind VK, ExprObjectKind OK,
@@ -3288,14 +3482,17 @@ protected:
(lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(lhs->containsUnexpandedParameterPack() ||
- rhs->containsUnexpandedParameterPack())),
- Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) {
+ rhs->containsUnexpandedParameterPack())) {
+ BinaryOperatorBits.Opc = opc;
+ BinaryOperatorBits.FPFeatures = FPFeatures.getInt();
+ BinaryOperatorBits.OpLoc = opLoc;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
- BinaryOperator(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), Opc(BO_MulAssign) { }
+ BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
+ BinaryOperatorBits.Opc = BO_MulAssign;
+ }
};
/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
@@ -3430,11 +3627,11 @@ public:
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
- SourceLocation getLocStart() const LLVM_READONLY {
- return getCond()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getCond()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getRHS()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getRHS()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -3518,11 +3715,11 @@ public:
return cast<Expr>(SubExprs[RHS]);
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getCommon()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getCommon()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getFalseExpr()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getFalseExpr()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -3576,8 +3773,8 @@ public:
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return AmpAmpLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AmpAmpLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return LabelLoc; }
LabelDecl *getLabel() const { return Label; }
void setLabel(LabelDecl *L) { Label = L; }
@@ -3621,8 +3818,8 @@ public:
const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); }
void setSubStmt(CompoundStmt *S) { SubStmt = S; }
- SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
@@ -3670,8 +3867,8 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ShuffleVectorExprClass;
@@ -3754,8 +3951,8 @@ public:
/// getRParenLoc - Return the location of final right parenthesis.
SourceLocation getRParenLoc() const { return RParenLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ConvertVectorExprClass;
@@ -3835,8 +4032,8 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ChooseExprClass;
@@ -3874,8 +4071,8 @@ public:
SourceLocation getTokenLocation() const { return TokenLoc; }
void setTokenLocation(SourceLocation L) { TokenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return TokenLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return TokenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return TokenLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return TokenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GNUNullExprClass;
@@ -3926,8 +4123,8 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == VAArgExprClass;
@@ -4160,8 +4357,8 @@ public:
InitListExprBits.HadArrayRangeDesignator = ARD;
}
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == InitListExprClass;
@@ -4395,17 +4592,17 @@ public:
return ArrayOrRange.Index;
}
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
if (Kind == FieldDesignator)
return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
else
return getLBracketLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc();
}
SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(getLocStart(), getLocEnd());
+ return SourceRange(getBeginLoc(), getEndLoc());
}
};
@@ -4484,8 +4681,8 @@ public:
SourceRange getDesignatorsSourceRange() const;
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == DesignatedInitExprClass;
@@ -4526,8 +4723,8 @@ public:
return T->getStmtClass() == NoInitExprClass;
}
- SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); }
// Iterators
child_range children() {
@@ -4561,8 +4758,8 @@ public:
explicit DesignatedInitUpdateExpr(EmptyShell Empty)
: Expr(DesignatedInitUpdateExprClass, Empty) { }
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == DesignatedInitUpdateExprClass;
@@ -4636,11 +4833,11 @@ public:
return S->getStmtClass() == ArrayInitLoopExprClass;
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getCommonExpr()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getCommonExpr()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getCommonExpr()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getCommonExpr()->getEndLoc();
}
child_range children() {
@@ -4671,8 +4868,8 @@ public:
return S->getStmtClass() == ArrayInitIndexExprClass;
}
- SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); }
child_range children() {
return child_range(child_iterator(), child_iterator());
@@ -4707,8 +4904,8 @@ public:
return T->getStmtClass() == ImplicitValueInitExprClass;
}
- SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); }
// Iterators
child_range children() {
@@ -4719,31 +4916,46 @@ public:
}
};
-class ParenListExpr : public Expr {
- Stmt **Exprs;
- unsigned NumExprs;
+class ParenListExpr final
+ : public Expr,
+ private llvm::TrailingObjects<ParenListExpr, Stmt *> {
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
+ /// The location of the left and right parentheses.
SourceLocation LParenLoc, RParenLoc;
-public:
- ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
- ArrayRef<Expr*> exprs, SourceLocation rparenloc);
+ /// Build a paren list.
+ ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs,
+ SourceLocation RParenLoc);
/// Build an empty paren list.
- explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
+ ParenListExpr(EmptyShell Empty, unsigned NumExprs);
+
+public:
+ /// Create a paren list.
+ static ParenListExpr *Create(const ASTContext &Ctx, SourceLocation LParenLoc,
+ ArrayRef<Expr *> Exprs,
+ SourceLocation RParenLoc);
- unsigned getNumExprs() const { return NumExprs; }
+ /// Create an empty paren list.
+ static ParenListExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs);
- const Expr* getExpr(unsigned Init) const {
+ /// Return the number of expressions in this paren list.
+ unsigned getNumExprs() const { return ParenListExprBits.NumExprs; }
+
+ Expr *getExpr(unsigned Init) {
assert(Init < getNumExprs() && "Initializer access out of range!");
- return cast_or_null<Expr>(Exprs[Init]);
+ return getExprs()[Init];
}
- Expr* getExpr(unsigned Init) {
- assert(Init < getNumExprs() && "Initializer access out of range!");
- return cast_or_null<Expr>(Exprs[Init]);
+ const Expr *getExpr(unsigned Init) const {
+ return const_cast<ParenListExpr *>(this)->getExpr(Init);
}
- Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }
+ Expr **getExprs() {
+ return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>());
+ }
ArrayRef<Expr *> exprs() {
return llvm::makeArrayRef(getExprs(), getNumExprs());
@@ -4751,9 +4963,8 @@ public:
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
-
- SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const { return getLParenLoc(); }
+ SourceLocation getEndLoc() const { return getRParenLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ParenListExprClass;
@@ -4761,14 +4972,13 @@ public:
// Iterators
child_range children() {
- return child_range(&Exprs[0], &Exprs[0]+NumExprs);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() + getNumExprs());
}
const_child_range children() const {
- return const_child_range(&Exprs[0], &Exprs[0] + NumExprs);
+ return const_child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() + getNumExprs());
}
-
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
};
/// Represents a C11 generic selection.
@@ -4876,8 +5086,8 @@ public:
const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); }
Expr *getResultExpr() { return getAssocExpr(getResultIndex()); }
- SourceLocation getLocStart() const LLVM_READONLY { return GenericLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return GenericLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GenericSelectionExprClass;
@@ -4942,10 +5152,10 @@ public:
/// aggregate Constant of ConstantInt(s).
void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const;
- SourceLocation getLocStart() const LLVM_READONLY {
- return getBase()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getBase()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return AccessorLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return AccessorLoc; }
/// isArrow - Return true if the base expression is a pointer to vector,
/// return false if the base expression is a vector.
@@ -4987,8 +5197,12 @@ public:
const Stmt *getBody() const;
Stmt *getBody();
- SourceLocation getLocStart() const LLVM_READONLY { return getCaretLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getBody()->getLocEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getCaretLocation();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getBody()->getEndLoc();
+ }
/// getFunctionType - Return the underlying function type for this block.
const FunctionProtoType *getFunctionType() const;
@@ -5040,8 +5254,8 @@ public:
/// getRParenLoc - Return the location of final right parenthesis.
SourceLocation getRParenLoc() const { return RParenLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AsTypeExprClass;
@@ -5182,11 +5396,11 @@ public:
return getSyntacticForm()->getExprLoc();
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getSyntacticForm()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getSyntacticForm()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getSyntacticForm()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getSyntacticForm()->getEndLoc();
}
child_range children() {
@@ -5309,8 +5523,8 @@ public:
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AtomicExprClass;
@@ -5363,8 +5577,8 @@ public:
return const_child_range(const_child_iterator(), const_child_iterator());
}
- SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == TypoExprClass;
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 7ab8020dec64..6ef837a2fc40 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -75,43 +75,46 @@ class TemplateParameterList;
/// function itself will be a (possibly empty) set of functions and
/// function templates that were found by name lookup at template
/// definition time.
-class CXXOperatorCallExpr : public CallExpr {
- /// The overloaded operator.
- OverloadedOperatorKind Operator;
+class CXXOperatorCallExpr final : public CallExpr {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
SourceRange Range;
- // Only meaningful for floating point types.
- FPOptions FPFeatures;
+ // CXXOperatorCallExpr has some trailing objects belonging
+ // to CallExpr. See CallExpr for the details.
SourceRange getSourceRangeImpl() const LLVM_READONLY;
-public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
+ CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation OperatorLoc, FPOptions FPFeatures,
+ ADLCallKind UsesADL);
- CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
- ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
- SourceLocation operatorloc, FPOptions FPFeatures)
- : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc),
- Operator(Op), FPFeatures(FPFeatures) {
- Range = getSourceRangeImpl();
- }
+ CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty);
- explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty)
- : CallExpr(C, CXXOperatorCallExprClass, Empty) {}
+public:
+ static CXXOperatorCallExpr *
+ Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation OperatorLoc, FPOptions FPFeatures,
+ ADLCallKind UsesADL = NotADL);
- /// Returns the kind of overloaded operator that this
- /// expression refers to.
- OverloadedOperatorKind getOperator() const { return Operator; }
+ static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs, EmptyShell Empty);
+
+ /// Returns the kind of overloaded operator that this expression refers to.
+ OverloadedOperatorKind getOperator() const {
+ return static_cast<OverloadedOperatorKind>(
+ CXXOperatorCallExprBits.OperatorKind);
+ }
static bool isAssignmentOp(OverloadedOperatorKind Opc) {
- return Opc == OO_Equal || Opc == OO_StarEqual ||
- Opc == OO_SlashEqual || Opc == OO_PercentEqual ||
- Opc == OO_PlusEqual || Opc == OO_MinusEqual ||
- Opc == OO_LessLessEqual || Opc == OO_GreaterGreaterEqual ||
- Opc == OO_AmpEqual || Opc == OO_CaretEqual ||
- Opc == OO_PipeEqual;
+ return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual ||
+ Opc == OO_PercentEqual || Opc == OO_PlusEqual ||
+ Opc == OO_MinusEqual || Opc == OO_LessLessEqual ||
+ Opc == OO_GreaterGreaterEqual || Opc == OO_AmpEqual ||
+ Opc == OO_CaretEqual || Opc == OO_PipeEqual;
}
bool isAssignmentOp() const { return isAssignmentOp(getOperator()); }
@@ -126,14 +129,15 @@ public:
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
SourceLocation getExprLoc() const LLVM_READONLY {
+ OverloadedOperatorKind Operator = getOperator();
return (Operator < OO_Plus || Operator >= OO_Arrow ||
Operator == OO_PlusPlus || Operator == OO_MinusMinus)
- ? getLocStart()
+ ? getBeginLoc()
: getOperatorLoc();
}
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const { return Range.getBegin(); }
+ SourceLocation getEndLoc() const { return Range.getEnd(); }
SourceRange getSourceRange() const { return Range; }
static bool classof(const Stmt *T) {
@@ -142,14 +146,17 @@ public:
// Set the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
- void setFPFeatures(FPOptions F) { FPFeatures = F; }
-
- FPOptions getFPFeatures() const { return FPFeatures; }
+ void setFPFeatures(FPOptions F) {
+ CXXOperatorCallExprBits.FPFeatures = F.getInt();
+ }
+ FPOptions getFPFeatures() const {
+ return FPOptions(CXXOperatorCallExprBits.FPFeatures);
+ }
// Get the FP contractability status of this operator. Only meaningful for
// operations on floating point types.
bool isFPContractableWithinStatement() const {
- return FPFeatures.allowFPContractWithinStatement();
+ return getFPFeatures().allowFPContractWithinStatement();
}
};
@@ -161,14 +168,23 @@ public:
/// both the object argument and the member function, while the
/// arguments are the arguments within the parentheses (not including
/// the object argument).
-class CXXMemberCallExpr : public CallExpr {
+class CXXMemberCallExpr final : public CallExpr {
+ // CXXMemberCallExpr has some trailing objects belonging
+ // to CallExpr. See CallExpr for the details.
+
+ CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs);
+
+ CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty);
+
public:
- CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr*> args,
- QualType t, ExprValueKind VK, SourceLocation RP)
- : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {}
+ static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK, SourceLocation RP,
+ unsigned MinNumArgs = 0);
- CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
- : CallExpr(C, CXXMemberCallExprClass, Empty) {}
+ static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
+ EmptyShell Empty);
/// Retrieves the implicit object argument for the member call.
///
@@ -191,7 +207,7 @@ public:
if (CLoc.isValid())
return CLoc;
- return getLocStart();
+ return getBeginLoc();
}
static bool classof(const Stmt *T) {
@@ -200,18 +216,26 @@ public:
};
/// Represents a call to a CUDA kernel function.
-class CUDAKernelCallExpr : public CallExpr {
-private:
+class CUDAKernelCallExpr final : public CallExpr {
enum { CONFIG, END_PREARG };
+ // CUDAKernelCallExpr has some trailing objects belonging
+ // to CallExpr. See CallExpr for the details.
+
+ CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK, SourceLocation RP,
+ unsigned MinNumArgs);
+
+ CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty);
+
public:
- CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config,
- ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
- SourceLocation RP)
- : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP) {}
+ static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
+ CallExpr *Config, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation RP, unsigned MinNumArgs = 0);
- CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty)
- : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) {}
+ static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs, EmptyShell Empty);
const CallExpr *getConfig() const {
return cast_or_null<CallExpr>(getPreArg(CONFIG));
@@ -278,8 +302,8 @@ public:
/// Retrieve the location of the closing parenthesis.
SourceLocation getRParenLoc() const { return RParenLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; }
static bool classof(const Stmt *T) {
@@ -301,8 +325,7 @@ public:
/// \c static_cast<int>(1.0).
class CXXStaticCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXStaticCastExpr, CastExpr::BasePathSizeTy,
- CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> {
CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -313,10 +336,6 @@ class CXXStaticCastExpr final
explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {}
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
-
public:
friend class CastExpr;
friend TrailingObjects;
@@ -342,8 +361,7 @@ public:
/// check to determine how to perform the type conversion.
class CXXDynamicCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<
- CXXDynamicCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -354,10 +372,6 @@ class CXXDynamicCastExpr final
explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {}
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
-
public:
friend class CastExpr;
friend TrailingObjects;
@@ -390,7 +404,6 @@ public:
class CXXReinterpretCastExpr final
: public CXXNamedCastExpr,
private llvm::TrailingObjects<CXXReinterpretCastExpr,
- CastExpr::BasePathSizeTy,
CXXBaseSpecifier *> {
CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
Expr *op, unsigned pathSize,
@@ -403,10 +416,6 @@ class CXXReinterpretCastExpr final
CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {}
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
-
public:
friend class CastExpr;
friend TrailingObjects;
@@ -434,8 +443,7 @@ public:
/// value.
class CXXConstCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXConstCastExpr, CastExpr::BasePathSizeTy,
- CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> {
CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc, SourceRange AngleBrackets)
@@ -445,10 +453,6 @@ class CXXConstCastExpr final
explicit CXXConstCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {}
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
-
public:
friend class CastExpr;
friend TrailingObjects;
@@ -474,22 +478,30 @@ public:
///
/// Since literal operators are never found by ADL and can only be declared at
/// namespace scope, a user-defined literal is never dependent.
-class UserDefinedLiteral : public CallExpr {
+class UserDefinedLiteral final : public CallExpr {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
/// The location of a ud-suffix within the literal.
SourceLocation UDSuffixLoc;
-public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
+ // UserDefinedLiteral has some trailing objects belonging
+ // to CallExpr. See CallExpr for the details.
- UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args,
- QualType T, ExprValueKind VK, SourceLocation LitEndLoc,
- SourceLocation SuffixLoc)
- : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc),
- UDSuffixLoc(SuffixLoc) {}
+ UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK, SourceLocation LitEndLoc,
+ SourceLocation SuffixLoc);
- explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty)
- : CallExpr(C, UserDefinedLiteralClass, Empty) {}
+ UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty);
+
+public:
+ static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK, SourceLocation LitEndLoc,
+ SourceLocation SuffixLoc);
+
+ static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs, EmptyShell Empty);
/// The kind of literal operator which is invoked.
enum LiteralOperatorKind {
@@ -524,13 +536,13 @@ public:
return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral();
}
- SourceLocation getLocStart() const {
+ SourceLocation getBeginLoc() const {
if (getLiteralOperatorKind() == LOK_Template)
return getRParenLoc();
- return getArg(0)->getLocStart();
+ return getArg(0)->getBeginLoc();
}
- SourceLocation getLocEnd() const { return getRParenLoc(); }
+ SourceLocation getEndLoc() const { return getRParenLoc(); }
/// Returns the location of a ud-suffix in the expression.
///
@@ -548,26 +560,25 @@ public:
/// A boolean literal, per ([C++ lex.bool] Boolean literals).
class CXXBoolLiteralExpr : public Expr {
- bool Value;
- SourceLocation Loc;
-
public:
- CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l)
+ CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc)
: Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
- false, false),
- Value(val), Loc(l) {}
+ false, false) {
+ CXXBoolLiteralExprBits.Value = Val;
+ CXXBoolLiteralExprBits.Loc = Loc;
+ }
explicit CXXBoolLiteralExpr(EmptyShell Empty)
: Expr(CXXBoolLiteralExprClass, Empty) {}
- bool getValue() const { return Value; }
- void setValue(bool V) { Value = V; }
+ bool getValue() const { return CXXBoolLiteralExprBits.Value; }
+ void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; }
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const { return getLocation(); }
+ SourceLocation getEndLoc() const { return getLocation(); }
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
+ SourceLocation getLocation() const { return CXXBoolLiteralExprBits.Loc; }
+ void setLocation(SourceLocation L) { CXXBoolLiteralExprBits.Loc = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXBoolLiteralExprClass;
@@ -583,22 +594,21 @@ public:
///
/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
class CXXNullPtrLiteralExpr : public Expr {
- SourceLocation Loc;
-
public:
- CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l)
+ CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc)
: Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false,
- false, false, false),
- Loc(l) {}
+ false, false, false) {
+ CXXNullPtrLiteralExprBits.Loc = Loc;
+ }
explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
: Expr(CXXNullPtrLiteralExprClass, Empty) {}
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const { return getLocation(); }
+ SourceLocation getEndLoc() const { return getLocation(); }
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
+ SourceLocation getLocation() const { return CXXNullPtrLiteralExprBits.Loc; }
+ void setLocation(SourceLocation L) { CXXNullPtrLiteralExprBits.Loc = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXNullPtrLiteralExprClass;
@@ -631,12 +641,12 @@ public:
Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); }
const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); }
- SourceLocation getLocStart() const LLVM_READONLY {
- return SubExpr->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SubExpr->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExpr->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExpr->getEndLoc();
}
/// Retrieve the source range of the expression.
@@ -723,8 +733,8 @@ public:
Operand = E;
}
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
void setSourceRange(SourceRange R) { Range = R; }
@@ -771,23 +781,23 @@ public:
MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}
SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(getLocStart(), getLocEnd());
+ return SourceRange(getBeginLoc(), getEndLoc());
}
bool isImplicitAccess() const {
return getBaseExpr() && getBaseExpr()->isImplicitCXXThis();
}
- SourceLocation getLocStart() const {
+ SourceLocation getBeginLoc() const {
if (!isImplicitAccess())
- return BaseExpr->getLocStart();
+ return BaseExpr->getBeginLoc();
else if (QualifierLoc)
return QualifierLoc.getBeginLoc();
else
return MemberLoc;
}
- SourceLocation getLocEnd() const { return getMemberLoc(); }
+ SourceLocation getEndLoc() const { return getMemberLoc(); }
child_range children() {
return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1);
@@ -847,11 +857,11 @@ public:
Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); }
const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); }
- SourceLocation getLocStart() const LLVM_READONLY {
- return getBase()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getBase()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
SourceLocation getRBracketLoc() const { return RBracketLoc; }
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
@@ -933,8 +943,8 @@ public:
void setUuidStr(StringRef US) { UuidStr = US; }
StringRef getUuidStr() const { return UuidStr; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
void setSourceRange(SourceRange R) { Range = R; }
@@ -964,29 +974,28 @@ public:
/// };
/// \endcode
class CXXThisExpr : public Expr {
- SourceLocation Loc;
- bool Implicit : 1;
-
public:
- CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit)
- : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary,
+ CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit)
+ : Expr(CXXThisExprClass, Ty, VK_RValue, OK_Ordinary,
// 'this' is type-dependent if the class type of the enclosing
// member function is dependent (C++ [temp.dep.expr]p2)
- Type->isDependentType(), Type->isDependentType(),
- Type->isInstantiationDependentType(),
- /*ContainsUnexpandedParameterPack=*/false),
- Loc(L), Implicit(isImplicit) {}
+ Ty->isDependentType(), Ty->isDependentType(),
+ Ty->isInstantiationDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false) {
+ CXXThisExprBits.IsImplicit = IsImplicit;
+ CXXThisExprBits.Loc = L;
+ }
CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
+ SourceLocation getLocation() const { return CXXThisExprBits.Loc; }
+ void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const { return getLocation(); }
+ SourceLocation getEndLoc() const { return getLocation(); }
- bool isImplicit() const { return Implicit; }
- void setImplicit(bool I) { Implicit = I; }
+ bool isImplicit() const { return CXXThisExprBits.IsImplicit; }
+ void setImplicit(bool I) { CXXThisExprBits.IsImplicit = I; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXThisExprClass;
@@ -1006,43 +1015,44 @@ public:
class CXXThrowExpr : public Expr {
friend class ASTStmtReader;
- Stmt *Op;
- SourceLocation ThrowLoc;
-
- /// Whether the thrown variable (if any) is in scope.
- unsigned IsThrownVariableInScope : 1;
+ /// The optional expression in the throw statement.
+ Stmt *Operand;
public:
// \p Ty is the void type which is used as the result type of the
- // expression. The \p l is the location of the throw keyword. \p expr
- // can by null, if the optional expression to throw isn't present.
- CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l,
+ // expression. The \p Loc is the location of the throw keyword.
+ // \p Operand is the expression in the throw statement, and can be
+ // null if not present.
+ CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc,
bool IsThrownVariableInScope)
: Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
- expr && expr->isInstantiationDependent(),
- expr && expr->containsUnexpandedParameterPack()),
- Op(expr), ThrowLoc(l),
- IsThrownVariableInScope(IsThrownVariableInScope) {}
+ Operand && Operand->isInstantiationDependent(),
+ Operand && Operand->containsUnexpandedParameterPack()),
+ Operand(Operand) {
+ CXXThrowExprBits.ThrowLoc = Loc;
+ CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope;
+ }
CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}
- const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); }
- Expr *getSubExpr() { return cast_or_null<Expr>(Op); }
+ const Expr *getSubExpr() const { return cast_or_null<Expr>(Operand); }
+ Expr *getSubExpr() { return cast_or_null<Expr>(Operand); }
- SourceLocation getThrowLoc() const { return ThrowLoc; }
+ SourceLocation getThrowLoc() const { return CXXThrowExprBits.ThrowLoc; }
/// Determines whether the variable thrown by this expression (if any!)
/// is within the innermost try block.
///
/// This information is required to determine whether the NRVO can apply to
/// this variable.
- bool isThrownVariableInScope() const { return IsThrownVariableInScope; }
-
- SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; }
+ bool isThrownVariableInScope() const {
+ return CXXThrowExprBits.IsThrownVariableInScope;
+ }
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const { return getThrowLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
if (!getSubExpr())
- return ThrowLoc;
- return getSubExpr()->getLocEnd();
+ return getThrowLoc();
+ return getSubExpr()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -1051,7 +1061,7 @@ public:
// Iterators
child_range children() {
- return child_range(&Op, Op ? &Op+1 : &Op);
+ return child_range(&Operand, Operand ? &Operand + 1 : &Operand);
}
};
@@ -1061,26 +1071,24 @@ public:
/// corresponding parameter's default argument, when the call did not
/// explicitly supply arguments for all of the parameters.
class CXXDefaultArgExpr final : public Expr {
+ friend class ASTStmtReader;
+
/// The parameter whose default is being used.
ParmVarDecl *Param;
- /// The location where the default argument expression was used.
- SourceLocation Loc;
-
- CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param)
+ CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param)
: Expr(SC,
- param->hasUnparsedDefaultArg()
- ? param->getType().getNonReferenceType()
- : param->getDefaultArg()->getType(),
- param->getDefaultArg()->getValueKind(),
- param->getDefaultArg()->getObjectKind(), false, false, false,
+ Param->hasUnparsedDefaultArg()
+ ? Param->getType().getNonReferenceType()
+ : Param->getDefaultArg()->getType(),
+ Param->getDefaultArg()->getValueKind(),
+ Param->getDefaultArg()->getObjectKind(), false, false, false,
false),
- Param(param), Loc(Loc) {}
+ Param(Param) {
+ CXXDefaultArgExprBits.Loc = Loc;
+ }
public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
// \p Param is the parameter whose default argument is used by this
@@ -1095,23 +1103,18 @@ public:
ParmVarDecl *getParam() { return Param; }
// Retrieve the actual argument to the function call.
- const Expr *getExpr() const {
- return getParam()->getDefaultArg();
- }
- Expr *getExpr() {
- return getParam()->getDefaultArg();
- }
+ const Expr *getExpr() const { return getParam()->getDefaultArg(); }
+ Expr *getExpr() { return getParam()->getDefaultArg(); }
- /// Retrieve the location where this default argument was actually
- /// used.
- SourceLocation getUsedLocation() const { return Loc; }
+ /// Retrieve the location where this default argument was actually used.
+ SourceLocation getUsedLocation() const { return CXXDefaultArgExprBits.Loc; }
/// Default argument expressions have no representation in the
/// source, so they have an empty source range.
- SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getBeginLoc() const { return SourceLocation(); }
+ SourceLocation getEndLoc() const { return SourceLocation(); }
- SourceLocation getExprLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getExprLoc() const { return getUsedLocation(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDefaultArgExprClass;
@@ -1132,26 +1135,23 @@ public:
/// (C++11 [class.base.init]p8) or in aggregate initialization
/// (C++1y [dcl.init.aggr]p7).
class CXXDefaultInitExpr : public Expr {
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
/// The field whose default is being used.
FieldDecl *Field;
- /// The location where the default initializer expression was used.
- SourceLocation Loc;
-
- CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field,
- QualType T);
+ CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
+ FieldDecl *Field, QualType Ty);
CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}
public:
- friend class ASTReader;
- friend class ASTStmtReader;
-
/// \p Field is the non-static data member whose default initializer is used
/// by this expression.
- static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc,
+ static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc,
FieldDecl *Field) {
- return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType());
+ return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType());
}
/// Get the field whose initializer will be used.
@@ -1168,8 +1168,8 @@ public:
return Field->getInClassInitializer();
}
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const { return CXXDefaultInitExprBits.Loc; }
+ SourceLocation getEndLoc() const { return CXXDefaultInitExprBits.Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDefaultInitExprClass;
@@ -1241,11 +1241,13 @@ public:
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return SubExpr->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SubExpr->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();}
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExpr->getEndLoc();
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Stmt *T) {
@@ -1258,6 +1260,8 @@ public:
/// Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr {
+ friend class ASTStmtReader;
+
public:
enum ConstructionKind {
CK_Complete,
@@ -1267,150 +1271,173 @@ public:
};
private:
- CXXConstructorDecl *Constructor = nullptr;
- SourceLocation Loc;
+ /// A pointer to the constructor which will be ultimately called.
+ CXXConstructorDecl *Constructor;
+
SourceRange ParenOrBraceRange;
- unsigned NumArgs : 16;
- unsigned Elidable : 1;
- unsigned HadMultipleCandidates : 1;
- unsigned ListInitialization : 1;
- unsigned StdInitListInitialization : 1;
- unsigned ZeroInitialization : 1;
- unsigned ConstructKind : 2;
- Stmt **Args = nullptr;
- void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
+ /// The number of arguments.
+ unsigned NumArgs;
+
+ // We would like to stash the arguments of the constructor call after
+ // CXXConstructExpr. However CXXConstructExpr is used as a base class of
+ // CXXTemporaryObjectExpr which makes the use of llvm::TrailingObjects
+ // impossible.
+ //
+ // Instead we manually stash the trailing object after the full object
+ // containing CXXConstructExpr (that is either CXXConstructExpr or
+ // CXXTemporaryObjectExpr).
+ //
+ // The trailing objects are:
+ //
+ // * An array of getNumArgs() "Stmt *" for the arguments of the
+ // constructor call.
+
+ /// Return a pointer to the start of the trailing arguments.
+ /// Defined just after CXXTemporaryObjectExpr.
+ inline Stmt **getTrailingArgs();
+ const Stmt *const *getTrailingArgs() const {
+ return const_cast<CXXConstructExpr *>(this)->getTrailingArgs();
+ }
protected:
- CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T,
- SourceLocation Loc,
- CXXConstructorDecl *Ctor,
- bool Elidable,
- ArrayRef<Expr *> Args,
- bool HadMultipleCandidates,
- bool ListInitialization,
- bool StdInitListInitialization,
- bool ZeroInitialization,
- ConstructionKind ConstructKind,
+ /// Build a C++ construction expression.
+ CXXConstructExpr(StmtClass SC, QualType Ty, SourceLocation Loc,
+ CXXConstructorDecl *Ctor, bool Elidable,
+ ArrayRef<Expr *> Args, bool HadMultipleCandidates,
+ bool ListInitialization, bool StdInitListInitialization,
+ bool ZeroInitialization, ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange);
- /// Construct an empty C++ construction expression.
- CXXConstructExpr(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), NumArgs(0), Elidable(false),
- HadMultipleCandidates(false), ListInitialization(false),
- ZeroInitialization(false), ConstructKind(0) {}
+ /// Build an empty C++ construction expression.
+ CXXConstructExpr(StmtClass SC, EmptyShell Empty, unsigned NumArgs);
+
+ /// Return the size in bytes of the trailing objects. Used by
+ /// CXXTemporaryObjectExpr to allocate the right amount of storage.
+ static unsigned sizeOfTrailingObjects(unsigned NumArgs) {
+ return NumArgs * sizeof(Stmt *);
+ }
public:
- friend class ASTStmtReader;
+ /// Create a C++ construction expression.
+ static CXXConstructExpr *
+ Create(const ASTContext &Ctx, QualType Ty, SourceLocation Loc,
+ CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args,
+ bool HadMultipleCandidates, bool ListInitialization,
+ bool StdInitListInitialization, bool ZeroInitialization,
+ ConstructionKind ConstructKind, SourceRange ParenOrBraceRange);
- /// Construct an empty C++ construction expression.
- explicit CXXConstructExpr(EmptyShell Empty)
- : CXXConstructExpr(CXXConstructExprClass, Empty) {}
-
- static CXXConstructExpr *Create(const ASTContext &C, QualType T,
- SourceLocation Loc,
- CXXConstructorDecl *Ctor,
- bool Elidable,
- ArrayRef<Expr *> Args,
- bool HadMultipleCandidates,
- bool ListInitialization,
- bool StdInitListInitialization,
- bool ZeroInitialization,
- ConstructionKind ConstructKind,
- SourceRange ParenOrBraceRange);
+ /// Create an empty C++ construction expression.
+ static CXXConstructExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs);
/// Get the constructor that this expression will (ultimately) call.
CXXConstructorDecl *getConstructor() const { return Constructor; }
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation Loc) { this->Loc = Loc; }
+ SourceLocation getLocation() const { return CXXConstructExprBits.Loc; }
+ void setLocation(SourceLocation Loc) { CXXConstructExprBits.Loc = Loc; }
/// Whether this construction is elidable.
- bool isElidable() const { return Elidable; }
- void setElidable(bool E) { Elidable = E; }
+ bool isElidable() const { return CXXConstructExprBits.Elidable; }
+ void setElidable(bool E) { CXXConstructExprBits.Elidable = E; }
/// Whether the referred constructor was resolved from
/// an overloaded set having size greater than 1.
- bool hadMultipleCandidates() const { return HadMultipleCandidates; }
- void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; }
+ bool hadMultipleCandidates() const {
+ return CXXConstructExprBits.HadMultipleCandidates;
+ }
+ void setHadMultipleCandidates(bool V) {
+ CXXConstructExprBits.HadMultipleCandidates = V;
+ }
/// Whether this constructor call was written as list-initialization.
- bool isListInitialization() const { return ListInitialization; }
- void setListInitialization(bool V) { ListInitialization = V; }
+ bool isListInitialization() const {
+ return CXXConstructExprBits.ListInitialization;
+ }
+ void setListInitialization(bool V) {
+ CXXConstructExprBits.ListInitialization = V;
+ }
/// Whether this constructor call was written as list-initialization,
/// but was interpreted as forming a std::initializer_list<T> from the list
/// and passing that as a single constructor argument.
/// See C++11 [over.match.list]p1 bullet 1.
- bool isStdInitListInitialization() const { return StdInitListInitialization; }
- void setStdInitListInitialization(bool V) { StdInitListInitialization = V; }
+ bool isStdInitListInitialization() const {
+ return CXXConstructExprBits.StdInitListInitialization;
+ }
+ void setStdInitListInitialization(bool V) {
+ CXXConstructExprBits.StdInitListInitialization = V;
+ }
/// Whether this construction first requires
/// zero-initialization before the initializer is called.
- bool requiresZeroInitialization() const { return ZeroInitialization; }
+ bool requiresZeroInitialization() const {
+ return CXXConstructExprBits.ZeroInitialization;
+ }
void setRequiresZeroInitialization(bool ZeroInit) {
- ZeroInitialization = ZeroInit;
+ CXXConstructExprBits.ZeroInitialization = ZeroInit;
}
/// Determine whether this constructor is actually constructing
/// a base class (rather than a complete object).
ConstructionKind getConstructionKind() const {
- return (ConstructionKind)ConstructKind;
+ return static_cast<ConstructionKind>(CXXConstructExprBits.ConstructionKind);
}
void setConstructionKind(ConstructionKind CK) {
- ConstructKind = CK;
+ CXXConstructExprBits.ConstructionKind = CK;
}
using arg_iterator = ExprIterator;
using const_arg_iterator = ConstExprIterator;
using arg_range = llvm::iterator_range<arg_iterator>;
- using arg_const_range = llvm::iterator_range<const_arg_iterator>;
+ using const_arg_range = llvm::iterator_range<const_arg_iterator>;
arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
- arg_const_range arguments() const {
- return arg_const_range(arg_begin(), arg_end());
+ const_arg_range arguments() const {
+ return const_arg_range(arg_begin(), arg_end());
}
- arg_iterator arg_begin() { return Args; }
- arg_iterator arg_end() { return Args + NumArgs; }
- const_arg_iterator arg_begin() const { return Args; }
- const_arg_iterator arg_end() const { return Args + NumArgs; }
+ arg_iterator arg_begin() { return getTrailingArgs(); }
+ arg_iterator arg_end() { return arg_begin() + getNumArgs(); }
+ const_arg_iterator arg_begin() const { return getTrailingArgs(); }
+ const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); }
- Expr **getArgs() { return reinterpret_cast<Expr **>(Args); }
+ Expr **getArgs() { return reinterpret_cast<Expr **>(getTrailingArgs()); }
const Expr *const *getArgs() const {
- return const_cast<CXXConstructExpr *>(this)->getArgs();
+ return reinterpret_cast<const Expr *const *>(getTrailingArgs());
}
+
+ /// Return the number of arguments to the constructor call.
unsigned getNumArgs() const { return NumArgs; }
/// Return the specified argument.
Expr *getArg(unsigned Arg) {
- assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(Args[Arg]);
+ assert(Arg < getNumArgs() && "Arg access out of range!");
+ return getArgs()[Arg];
}
const Expr *getArg(unsigned Arg) const {
- assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(Args[Arg]);
+ assert(Arg < getNumArgs() && "Arg access out of range!");
+ return getArgs()[Arg];
}
/// Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
- assert(Arg < NumArgs && "Arg access out of range!");
- Args[Arg] = ArgExpr;
+ assert(Arg < getNumArgs() && "Arg access out of range!");
+ getArgs()[Arg] = ArgExpr;
}
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; }
void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstructExprClass ||
- T->getStmtClass() == CXXTemporaryObjectExprClass;
+ T->getStmtClass() == CXXTemporaryObjectExprClass;
}
// Iterators
child_range children() {
- return child_range(&Args[0], &Args[0]+NumArgs);
+ return child_range(getTrailingArgs(), getTrailingArgs() + getNumArgs());
}
};
@@ -1470,8 +1497,8 @@ public:
bool inheritedFromVBase() const { return InheritedFromVirtualBase; }
SourceLocation getLocation() const LLVM_READONLY { return Loc; }
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXInheritedCtorInitExprClass;
@@ -1491,8 +1518,7 @@ public:
/// \endcode
class CXXFunctionalCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<
- CXXFunctionalCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> {
SourceLocation LParenLoc;
SourceLocation RParenLoc;
@@ -1507,10 +1533,6 @@ class CXXFunctionalCastExpr final
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {}
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
-
public:
friend class CastExpr;
friend TrailingObjects;
@@ -1533,8 +1555,8 @@ public:
/// Determine whether this expression models list-initialization.
bool isListInitialization() const { return LParenLoc.isInvalid(); }
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXFunctionalCastExprClass;
@@ -1556,35 +1578,53 @@ public:
/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr
/// };
/// \endcode
-class CXXTemporaryObjectExpr : public CXXConstructExpr {
- TypeSourceInfo *Type = nullptr;
-
-public:
+class CXXTemporaryObjectExpr final : public CXXConstructExpr {
friend class ASTStmtReader;
- CXXTemporaryObjectExpr(const ASTContext &C,
- CXXConstructorDecl *Cons,
- QualType Type,
- TypeSourceInfo *TSI,
- ArrayRef<Expr *> Args,
+ // CXXTemporaryObjectExpr has some trailing objects belonging
+ // to CXXConstructExpr. See the comment inside CXXConstructExpr
+ // for more details.
+
+ TypeSourceInfo *TSI;
+
+ CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType Ty,
+ TypeSourceInfo *TSI, ArrayRef<Expr *> Args,
SourceRange ParenOrBraceRange,
- bool HadMultipleCandidates,
- bool ListInitialization,
+ bool HadMultipleCandidates, bool ListInitialization,
bool StdInitListInitialization,
bool ZeroInitialization);
- explicit CXXTemporaryObjectExpr(EmptyShell Empty)
- : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) {}
- TypeSourceInfo *getTypeSourceInfo() const { return Type; }
+ CXXTemporaryObjectExpr(EmptyShell Empty, unsigned NumArgs);
+
+public:
+ static CXXTemporaryObjectExpr *
+ Create(const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty,
+ TypeSourceInfo *TSI, ArrayRef<Expr *> Args,
+ SourceRange ParenOrBraceRange, bool HadMultipleCandidates,
+ bool ListInitialization, bool StdInitListInitialization,
+ bool ZeroInitialization);
+
+ static CXXTemporaryObjectExpr *CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs);
+
+ TypeSourceInfo *getTypeSourceInfo() const { return TSI; }
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTemporaryObjectExprClass;
}
};
+Stmt **CXXConstructExpr::getTrailingArgs() {
+ if (auto *E = dyn_cast<CXXTemporaryObjectExpr>(this))
+ return reinterpret_cast<Stmt **>(E + 1);
+ assert((getStmtClass() == CXXConstructExprClass) &&
+ "Unexpected class deriving from CXXConstructExpr!");
+ return reinterpret_cast<Stmt **>(this + 1);
+}
+
/// A C++ lambda expression, which produces a function object
/// (of unspecified type) that can be invoked later.
///
@@ -1814,11 +1854,11 @@ public:
return T->getStmtClass() == LambdaExprClass;
}
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
return IntroducerRange.getBegin();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return ClosingBrace; }
child_range children() {
// Includes initialization exprs plus body stmt
@@ -1831,18 +1871,19 @@ public:
class CXXScalarValueInitExpr : public Expr {
friend class ASTStmtReader;
- SourceLocation RParenLoc;
TypeSourceInfo *TypeInfo;
public:
/// Create an explicitly-written scalar-value initialization
/// expression.
CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo,
- SourceLocation rParenLoc)
- : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
- false, false, Type->isInstantiationDependentType(),
+ SourceLocation RParenLoc)
+ : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, false,
+ false, Type->isInstantiationDependentType(),
Type->containsUnexpandedParameterPack()),
- RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
+ TypeInfo(TypeInfo) {
+ CXXScalarValueInitExprBits.RParenLoc = RParenLoc;
+ }
explicit CXXScalarValueInitExpr(EmptyShell Shell)
: Expr(CXXScalarValueInitExprClass, Shell) {}
@@ -1851,10 +1892,12 @@ public:
return TypeInfo;
}
- SourceLocation getRParenLoc() const { return RParenLoc; }
+ SourceLocation getRParenLoc() const {
+ return CXXScalarValueInitExprBits.RParenLoc;
+ }
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const { return getRParenLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXScalarValueInitExprClass;
@@ -1868,54 +1911,56 @@ public:
/// Represents a new-expression for memory allocation and constructor
/// calls, e.g: "new CXXNewExpr(foo)".
-class CXXNewExpr : public Expr {
+class CXXNewExpr final
+ : public Expr,
+ private llvm::TrailingObjects<CXXNewExpr, Stmt *, SourceRange> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
-
- /// Contains an optional array size expression, an optional initialization
- /// expression, and any number of optional placement arguments, in that order.
- Stmt **SubExprs = nullptr;
+ friend TrailingObjects;
/// Points to the allocation function used.
FunctionDecl *OperatorNew;
- /// Points to the deallocation function used in case of error. May be
- /// null.
+ /// Points to the deallocation function used in case of error. May be null.
FunctionDecl *OperatorDelete;
/// The allocated type-source information, as written in the source.
TypeSourceInfo *AllocatedTypeInfo;
- /// If the allocated type was expressed as a parenthesized type-id,
- /// the source range covering the parenthesized type-id.
- SourceRange TypeIdParens;
-
/// Range of the entire new expression.
SourceRange Range;
/// Source-range of a paren-delimited initializer.
SourceRange DirectInitRange;
- /// Was the usage ::new, i.e. is the global new to be used?
- unsigned GlobalNew : 1;
-
- /// Do we allocate an array? If so, the first SubExpr is the size expression.
- unsigned Array : 1;
-
- /// Should the alignment be passed to the allocation function?
- unsigned PassAlignment : 1;
-
- /// If this is an array allocation, does the usual deallocation
- /// function for the allocated type want to know the allocated size?
- unsigned UsualArrayDeleteWantsSize : 1;
+ // CXXNewExpr is followed by several optional trailing objects.
+ // They are in order:
+ //
+ // * An optional "Stmt *" for the array size expression.
+ // Present if and ony if isArray().
+ //
+ // * An optional "Stmt *" for the init expression.
+ // Present if and only if hasInitializer().
+ //
+ // * An array of getNumPlacementArgs() "Stmt *" for the placement new
+ // arguments, if any.
+ //
+ // * An optional SourceRange for the range covering the parenthesized type-id
+ // if the allocated type was expressed as a parenthesized type-id.
+ // Present if and only if isParenTypeId().
+ unsigned arraySizeOffset() const { return 0; }
+ unsigned initExprOffset() const { return arraySizeOffset() + isArray(); }
+ unsigned placementNewArgsOffset() const {
+ return initExprOffset() + hasInitializer();
+ }
- /// The number of placement new arguments.
- unsigned NumPlacementArgs : 26;
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return isArray() + hasInitializer() + getNumPlacementArgs();
+ }
- /// What kind of initializer do we have? Could be none, parens, or braces.
- /// In storage, we distinguish between "none, and no initializer expr", and
- /// "none, but an implicit initializer expr".
- unsigned StoredInitializationStyle : 2;
+ unsigned numTrailingObjects(OverloadToken<SourceRange>) const {
+ return isParenTypeId();
+ }
public:
enum InitializationStyle {
@@ -1929,18 +1974,35 @@ public:
ListInit
};
- CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
- FunctionDecl *operatorDelete, bool PassAlignment,
- bool usualArrayDeleteWantsSize, ArrayRef<Expr*> placementArgs,
- SourceRange typeIdParens, Expr *arraySize,
- InitializationStyle initializationStyle, Expr *initializer,
- QualType ty, TypeSourceInfo *AllocatedTypeInfo,
- SourceRange Range, SourceRange directInitRange);
- explicit CXXNewExpr(EmptyShell Shell)
- : Expr(CXXNewExprClass, Shell) {}
+private:
+ /// Build a c++ new expression.
+ CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
+ FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
+ bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
+ SourceRange TypeIdParens, Expr *ArraySize,
+ InitializationStyle InitializationStyle, Expr *Initializer,
+ QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
+ SourceRange DirectInitRange);
+
+ /// Build an empty c++ new expression.
+ CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs,
+ bool IsParenTypeId);
- void AllocateArgsArray(const ASTContext &C, bool isArray,
- unsigned numPlaceArgs, bool hasInitializer);
+public:
+ /// Create a c++ new expression.
+ static CXXNewExpr *
+ Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew,
+ FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
+ bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
+ SourceRange TypeIdParens, Expr *ArraySize,
+ InitializationStyle InitializationStyle, Expr *Initializer,
+ QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
+ SourceRange DirectInitRange);
+
+ /// Create an empty c++ new expression.
+ static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray,
+ bool HasInit, unsigned NumPlacementArgs,
+ bool IsParenTypeId);
QualType getAllocatedType() const {
assert(getType()->isPointerType());
@@ -1966,58 +2028,74 @@ public:
/// has a non-throwing exception-specification. The '03 rule is
/// identical except that the definition of a non-throwing
/// exception specification is just "is it throw()?".
- bool shouldNullCheckAllocation(const ASTContext &Ctx) const;
+ bool shouldNullCheckAllocation() const;
FunctionDecl *getOperatorNew() const { return OperatorNew; }
void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; }
- bool isArray() const { return Array; }
+ bool isArray() const { return CXXNewExprBits.IsArray; }
Expr *getArraySize() {
- return Array ? cast<Expr>(SubExprs[0]) : nullptr;
+ return isArray()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])
+ : nullptr;
}
const Expr *getArraySize() const {
- return Array ? cast<Expr>(SubExprs[0]) : nullptr;
+ return isArray()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])
+ : nullptr;
}
- unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+ unsigned getNumPlacementArgs() const {
+ return CXXNewExprBits.NumPlacementArgs;
+ }
Expr **getPlacementArgs() {
- return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer());
+ return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>() +
+ placementNewArgsOffset());
}
- Expr *getPlacementArg(unsigned i) {
- assert(i < NumPlacementArgs && "Index out of range");
- return getPlacementArgs()[i];
+ Expr *getPlacementArg(unsigned I) {
+ assert((I < getNumPlacementArgs()) && "Index out of range!");
+ return getPlacementArgs()[I];
}
- const Expr *getPlacementArg(unsigned i) const {
- assert(i < NumPlacementArgs && "Index out of range");
- return const_cast<CXXNewExpr*>(this)->getPlacementArg(i);
+ const Expr *getPlacementArg(unsigned I) const {
+ return const_cast<CXXNewExpr *>(this)->getPlacementArg(I);
}
- bool isParenTypeId() const { return TypeIdParens.isValid(); }
- SourceRange getTypeIdParens() const { return TypeIdParens; }
+ bool isParenTypeId() const { return CXXNewExprBits.IsParenTypeId; }
+ SourceRange getTypeIdParens() const {
+ return isParenTypeId() ? getTrailingObjects<SourceRange>()[0]
+ : SourceRange();
+ }
- bool isGlobalNew() const { return GlobalNew; }
+ bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; }
/// Whether this new-expression has any initializer at all.
- bool hasInitializer() const { return StoredInitializationStyle > 0; }
+ bool hasInitializer() const {
+ return CXXNewExprBits.StoredInitializationStyle > 0;
+ }
/// The kind of initializer this new-expression has.
InitializationStyle getInitializationStyle() const {
- if (StoredInitializationStyle == 0)
+ if (CXXNewExprBits.StoredInitializationStyle == 0)
return NoInit;
- return static_cast<InitializationStyle>(StoredInitializationStyle-1);
+ return static_cast<InitializationStyle>(
+ CXXNewExprBits.StoredInitializationStyle - 1);
}
/// The initializer of this new-expression.
Expr *getInitializer() {
- return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
+ return hasInitializer()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()])
+ : nullptr;
}
const Expr *getInitializer() const {
- return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
+ return hasInitializer()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()])
+ : nullptr;
}
/// Returns the CXXConstructExpr from this new-expression, or null.
@@ -2027,15 +2105,13 @@ public:
/// Indicates whether the required alignment should be implicitly passed to
/// the allocation function.
- bool passAlignment() const {
- return PassAlignment;
- }
+ bool passAlignment() const { return CXXNewExprBits.ShouldPassAlignment; }
/// Answers whether the usual array deallocation function for the
/// allocated type expects the size of the allocation as a
/// parameter.
bool doesUsualArrayDeleteWantSize() const {
- return UsualArrayDeleteWantsSize;
+ return CXXNewExprBits.UsualArrayDeleteWantsSize;
}
using arg_iterator = ExprIterator;
@@ -2050,103 +2126,85 @@ public:
}
arg_iterator placement_arg_begin() {
- return SubExprs + Array + hasInitializer();
+ return getTrailingObjects<Stmt *>() + placementNewArgsOffset();
}
arg_iterator placement_arg_end() {
- return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ return placement_arg_begin() + getNumPlacementArgs();
}
const_arg_iterator placement_arg_begin() const {
- return SubExprs + Array + hasInitializer();
+ return getTrailingObjects<Stmt *>() + placementNewArgsOffset();
}
const_arg_iterator placement_arg_end() const {
- return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ return placement_arg_begin() + getNumPlacementArgs();
}
using raw_arg_iterator = Stmt **;
- raw_arg_iterator raw_arg_begin() { return SubExprs; }
+ raw_arg_iterator raw_arg_begin() { return getTrailingObjects<Stmt *>(); }
raw_arg_iterator raw_arg_end() {
- return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>());
+ }
+ const_arg_iterator raw_arg_begin() const {
+ return getTrailingObjects<Stmt *>();
}
- const_arg_iterator raw_arg_begin() const { return SubExprs; }
const_arg_iterator raw_arg_end() const {
- return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>());
}
- SourceLocation getStartLoc() const { return Range.getBegin(); }
+ SourceLocation getBeginLoc() const { return Range.getBegin(); }
SourceLocation getEndLoc() const { return Range.getEnd(); }
SourceRange getDirectInitRange() const { return DirectInitRange; }
-
- SourceRange getSourceRange() const LLVM_READONLY {
- return Range;
- }
-
- SourceLocation getLocStart() const LLVM_READONLY { return getStartLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceRange getSourceRange() const { return Range; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXNewExprClass;
}
// Iterators
- child_range children() {
- return child_range(raw_arg_begin(), raw_arg_end());
- }
+ child_range children() { return child_range(raw_arg_begin(), raw_arg_end()); }
};
/// Represents a \c delete expression for memory deallocation and
/// destructor calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {
+ friend class ASTStmtReader;
+
/// Points to the operator delete overload that is used. Could be a member.
FunctionDecl *OperatorDelete = nullptr;
/// The pointer expression to be deleted.
Stmt *Argument = nullptr;
- /// Location of the expression.
- SourceLocation Loc;
-
- /// Is this a forced global delete, i.e. "::delete"?
- bool GlobalDelete : 1;
-
- /// Is this the array form of delete, i.e. "delete[]"?
- bool ArrayForm : 1;
-
- /// ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied
- /// to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm
- /// will be true).
- bool ArrayFormAsWritten : 1;
-
- /// Does the usual deallocation function for the element type require
- /// a size_t argument?
- bool UsualArrayDeleteWantsSize : 1;
-
public:
- friend class ASTStmtReader;
+ CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm,
+ bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize,
+ FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc)
+ : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ Arg->isInstantiationDependent(),
+ Arg->containsUnexpandedParameterPack()),
+ OperatorDelete(OperatorDelete), Argument(Arg) {
+ CXXDeleteExprBits.GlobalDelete = GlobalDelete;
+ CXXDeleteExprBits.ArrayForm = ArrayForm;
+ CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten;
+ CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize;
+ CXXDeleteExprBits.Loc = Loc;
+ }
- CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
- bool arrayFormAsWritten, bool usualArrayDeleteWantsSize,
- FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
- : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false,
- arg->isInstantiationDependent(),
- arg->containsUnexpandedParameterPack()),
- OperatorDelete(operatorDelete), Argument(arg), Loc(loc),
- GlobalDelete(globalDelete),
- ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
- UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {}
explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {}
- bool isGlobalDelete() const { return GlobalDelete; }
- bool isArrayForm() const { return ArrayForm; }
- bool isArrayFormAsWritten() const { return ArrayFormAsWritten; }
+ bool isGlobalDelete() const { return CXXDeleteExprBits.GlobalDelete; }
+ bool isArrayForm() const { return CXXDeleteExprBits.ArrayForm; }
+ bool isArrayFormAsWritten() const {
+ return CXXDeleteExprBits.ArrayFormAsWritten;
+ }
/// Answers whether the usual array deallocation function for the
/// allocated type expects the size of the allocation as a
/// parameter. This can be true even if the actual deallocation
/// function that we're using doesn't want a size.
bool doesUsualArrayDeleteWantSize() const {
- return UsualArrayDeleteWantsSize;
+ return CXXDeleteExprBits.UsualArrayDeleteWantsSize;
}
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
@@ -2160,15 +2218,17 @@ public:
/// be a pointer, return an invalid type.
QualType getDestroyedType() const;
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY {return Argument->getLocEnd();}
+ SourceLocation getBeginLoc() const { return CXXDeleteExprBits.Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return Argument->getEndLoc();
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDeleteExprClass;
}
// Iterators
- child_range children() { return child_range(&Argument, &Argument+1); }
+ child_range children() { return child_range(&Argument, &Argument + 1); }
};
/// Stores the type being destroyed by a pseudo-destructor expression.
@@ -2346,8 +2406,10 @@ public:
DestroyedType = PseudoDestructorTypeStorage(Info);
}
- SourceLocation getLocStart() const LLVM_READONLY {return Base->getLocStart();}
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return Base->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXPseudoDestructorExprClass;
@@ -2428,8 +2490,8 @@ public:
getNumArgs());
}
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == TypeTraitExprClass;
@@ -2468,8 +2530,6 @@ class ArrayTypeTraitExpr : public Expr {
/// The type being queried.
TypeSourceInfo *QueriedType = nullptr;
- virtual void anchor();
-
public:
friend class ASTStmtReader;
@@ -2487,10 +2547,8 @@ public:
explicit ArrayTypeTraitExpr(EmptyShell Empty)
: Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {}
- virtual ~ArrayTypeTraitExpr() = default;
-
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParen; }
ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); }
@@ -2553,8 +2611,8 @@ public:
explicit ExpressionTraitExpr(EmptyShell Empty)
: Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {}
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParen; }
ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); }
@@ -2575,58 +2633,54 @@ public:
/// A reference to an overloaded function set, either an
/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
class OverloadExpr : public Expr {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
/// The common name of these declarations.
DeclarationNameInfo NameInfo;
/// The nested-name-specifier that qualifies the name, if any.
NestedNameSpecifierLoc QualifierLoc;
- /// The results. These are undesugared, which is to say, they may
- /// include UsingShadowDecls. Access is relative to the naming
- /// class.
- // FIXME: Allocate this data after the OverloadExpr subclass.
- DeclAccessPair *Results = nullptr;
-
- unsigned NumResults = 0;
-
protected:
- /// Whether the name includes info for explicit template
- /// keyword and arguments.
- bool HasTemplateKWAndArgsInfo = false;
-
- OverloadExpr(StmtClass K, const ASTContext &C,
+ OverloadExpr(StmtClass SC, const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
- bool KnownDependent,
- bool KnownInstantiationDependent,
+ bool KnownDependent, bool KnownInstantiationDependent,
bool KnownContainsUnexpandedParameterPack);
- OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty) {}
+ OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo);
- /// Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *
- getTrailingASTTemplateKWAndArgsInfo(); // defined far below.
+ /// Return the results. Defined after UnresolvedMemberExpr.
+ inline DeclAccessPair *getTrailingResults();
+ const DeclAccessPair *getTrailingResults() const {
+ return const_cast<OverloadExpr *>(this)->getTrailingResults();
+ }
/// Return the optional template keyword and arguments info.
+ /// Defined after UnresolvedMemberExpr.
+ inline ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo();
const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const {
return const_cast<OverloadExpr *>(this)
->getTrailingASTTemplateKWAndArgsInfo();
}
- /// Return the optional template arguments.
- TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below
+ /// Return the optional template arguments. Defined after
+ /// UnresolvedMemberExpr.
+ inline TemplateArgumentLoc *getTrailingTemplateArgumentLoc();
+ const TemplateArgumentLoc *getTrailingTemplateArgumentLoc() const {
+ return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc();
+ }
- void initializeResults(const ASTContext &C,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End);
+ bool hasTemplateKWAndArgsInfo() const {
+ return OverloadExprBits.HasTemplateKWAndArgsInfo;
+ }
public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
struct FindResult {
OverloadExpr *Expression;
bool IsAddressOfOperand;
@@ -2662,20 +2716,26 @@ public:
}
/// Gets the naming class of this lookup, if any.
- CXXRecordDecl *getNamingClass() const;
+ /// Defined after UnresolvedMemberExpr.
+ inline CXXRecordDecl *getNamingClass();
+ const CXXRecordDecl *getNamingClass() const {
+ return const_cast<OverloadExpr *>(this)->getNamingClass();
+ }
using decls_iterator = UnresolvedSetImpl::iterator;
- decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); }
+ decls_iterator decls_begin() const {
+ return UnresolvedSetIterator(getTrailingResults());
+ }
decls_iterator decls_end() const {
- return UnresolvedSetIterator(Results + NumResults);
+ return UnresolvedSetIterator(getTrailingResults() + getNumDecls());
}
llvm::iterator_range<decls_iterator> decls() const {
return llvm::make_range(decls_begin(), decls_end());
}
/// Gets the number of declarations in the unresolved set.
- unsigned getNumDecls() const { return NumResults; }
+ unsigned getNumDecls() const { return OverloadExprBits.NumResults; }
/// Gets the full name info.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
@@ -2698,21 +2758,24 @@ public:
/// Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc;
}
/// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc;
}
/// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc;
}
@@ -2764,97 +2827,93 @@ public:
/// members and therefore appear only in UnresolvedMemberLookupExprs.
class UnresolvedLookupExpr final
: public OverloadExpr,
- private llvm::TrailingObjects<
- UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
+ private llvm::TrailingObjects<UnresolvedLookupExpr, DeclAccessPair,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
friend class ASTStmtReader;
friend class OverloadExpr;
friend TrailingObjects;
- /// True if these lookup results should be extended by
- /// argument-dependent lookup if this is the operand of a function
- /// call.
- bool RequiresADL = false;
-
- /// True if these lookup results are overloaded. This is pretty
- /// trivially rederivable if we urgently need to kill this field.
- bool Overloaded = false;
-
/// The naming class (C++ [class.access.base]p5) of the lookup, if
/// any. This can generally be recalculated from the context chain,
- /// but that can be fairly expensive for unqualified lookups. If we
- /// want to improve memory use here, this could go in a union
- /// against the qualified-lookup bits.
- CXXRecordDecl *NamingClass = nullptr;
-
- UnresolvedLookupExpr(const ASTContext &C,
- CXXRecordDecl *NamingClass,
+ /// but that can be fairly expensive for unqualified lookups.
+ CXXRecordDecl *NamingClass;
+
+ // UnresolvedLookupExpr is followed by several trailing objects.
+ // They are in order:
+ //
+ // * An array of getNumResults() DeclAccessPair for the results. These are
+ // undesugared, which is to say, they may include UsingShadowDecls.
+ // Access is relative to the naming class.
+ //
+ // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified
+ // template keyword and arguments. Present if and only if
+ // hasTemplateKWAndArgsInfo().
+ //
+ // * An array of getNumTemplateArgs() TemplateArgumentLoc containing
+ // location information for the explicitly specified template arguments.
+
+ UnresolvedLookupExpr(const ASTContext &Context, CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- bool RequiresADL, bool Overloaded,
+ const DeclarationNameInfo &NameInfo, bool RequiresADL,
+ bool Overloaded,
const TemplateArgumentListInfo *TemplateArgs,
- UnresolvedSetIterator Begin, UnresolvedSetIterator End)
- : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc,
- NameInfo, TemplateArgs, Begin, End, false, false, false),
- RequiresADL(RequiresADL),
- Overloaded(Overloaded), NamingClass(NamingClass) {}
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End);
- UnresolvedLookupExpr(EmptyShell Empty)
- : OverloadExpr(UnresolvedLookupExprClass, Empty) {}
+ UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo);
- size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
+ unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const {
+ return getNumDecls();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return hasTemplateKWAndArgsInfo();
}
public:
- static UnresolvedLookupExpr *Create(const ASTContext &C,
- CXXRecordDecl *NamingClass,
- NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo,
- bool ADL, bool Overloaded,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End) {
- return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
- SourceLocation(), NameInfo,
- ADL, Overloaded, nullptr, Begin, End);
- }
-
- static UnresolvedLookupExpr *Create(const ASTContext &C,
- CXXRecordDecl *NamingClass,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- bool ADL,
- const TemplateArgumentListInfo *Args,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End);
-
- static UnresolvedLookupExpr *CreateEmpty(const ASTContext &C,
+ static UnresolvedLookupExpr *
+ Create(const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End);
+
+ static UnresolvedLookupExpr *
+ Create(const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo, bool RequiresADL,
+ const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
+
+ static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context,
+ unsigned NumResults,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
/// True if this declaration should be extended by
/// argument-dependent lookup.
- bool requiresADL() const { return RequiresADL; }
+ bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; }
/// True if this lookup is overloaded.
- bool isOverloaded() const { return Overloaded; }
+ bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; }
/// Gets the 'naming class' (in the sense of C++0x
/// [class.access.base]p5) of the lookup. This is the scope
/// that was looked in to find these results.
- CXXRecordDecl *getNamingClass() const { return NamingClass; }
+ CXXRecordDecl *getNamingClass() { return NamingClass; }
+ const CXXRecordDecl *getNamingClass() const { return NamingClass; }
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
if (NestedNameSpecifierLoc l = getQualifierLoc())
return l.getBeginLoc();
- return getNameInfo().getLocStart();
+ return getNameInfo().getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
- return getNameInfo().getLocEnd();
+ return getNameInfo().getEndLoc();
}
child_range children() {
@@ -2885,6 +2944,10 @@ class DependentScopeDeclRefExpr final
private llvm::TrailingObjects<DependentScopeDeclRefExpr,
ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// The nested-name-specifier that qualifies this unresolved
/// declaration name.
NestedNameSpecifierLoc QualifierLoc;
@@ -2892,32 +2955,26 @@ class DependentScopeDeclRefExpr final
/// The name of the entity we will be referencing.
DeclarationNameInfo NameInfo;
- /// Whether the name includes info for explicit template
- /// keyword and arguments.
- bool HasTemplateKWAndArgsInfo;
-
- DependentScopeDeclRefExpr(QualType T,
- NestedNameSpecifierLoc QualifierLoc,
+ DependentScopeDeclRefExpr(QualType Ty, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args);
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
+ return hasTemplateKWAndArgsInfo();
}
-public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
- friend TrailingObjects;
+ bool hasTemplateKWAndArgsInfo() const {
+ return DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo;
+ }
- static DependentScopeDeclRefExpr *Create(const ASTContext &C,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
+public:
+ static DependentScopeDeclRefExpr *
+ Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
- static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C,
+ static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &Context,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
@@ -2945,21 +3002,24 @@ public:
/// Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
@@ -2995,13 +3055,13 @@ public:
return {getTemplateArgs(), getNumTemplateArgs()};
}
- /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr,
+ /// Note: getBeginLoc() is the start of the whole DependentScopeDeclRefExpr,
/// and differs from getLocation().getStart().
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
return QualifierLoc.getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
return getLocation();
@@ -3027,7 +3087,7 @@ public:
/// potentially-evaluated block literal. The lifetime of a block
/// literal is the extent of the enclosing scope.
class ExprWithCleanups final
- : public Expr,
+ : public FullExpr,
private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
public:
/// The type of objects that are kept in the cleanup.
@@ -3040,8 +3100,6 @@ private:
friend class ASTStmtReader;
friend TrailingObjects;
- Stmt *SubExpr;
-
ExprWithCleanups(EmptyShell, unsigned NumObjects);
ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> Objects);
@@ -3066,22 +3124,17 @@ public:
return getObjects()[i];
}
- Expr *getSubExpr() { return cast<Expr>(SubExpr); }
- const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
-
bool cleanupsHaveSideEffects() const {
return ExprWithCleanupsBits.CleanupsHaveSideEffects;
}
- /// As with any mutator of the AST, be very careful
- /// when modifying an existing AST to preserve its invariants.
- void setSubExpr(Expr *E) { SubExpr = E; }
-
- SourceLocation getLocStart() const LLVM_READONLY {
- return SubExpr->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SubExpr->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();}
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExpr->getEndLoc();
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Stmt *T) {
@@ -3120,7 +3173,7 @@ class CXXUnresolvedConstructExpr final
friend TrailingObjects;
/// The type being constructed.
- TypeSourceInfo *Type = nullptr;
+ TypeSourceInfo *TSI;
/// The location of the left parentheses ('(').
SourceLocation LParenLoc;
@@ -3128,34 +3181,31 @@ class CXXUnresolvedConstructExpr final
/// The location of the right parentheses (')').
SourceLocation RParenLoc;
- /// The number of arguments used to construct the type.
- unsigned NumArgs;
-
- CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
- SourceLocation LParenLoc,
- ArrayRef<Expr*> Args,
- SourceLocation RParenLoc);
+ CXXUnresolvedConstructExpr(TypeSourceInfo *TSI, SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args, SourceLocation RParenLoc);
CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
- : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) {}
+ : Expr(CXXUnresolvedConstructExprClass, Empty) {
+ CXXUnresolvedConstructExprBits.NumArgs = NumArgs;
+ }
public:
- static CXXUnresolvedConstructExpr *Create(const ASTContext &C,
+ static CXXUnresolvedConstructExpr *Create(const ASTContext &Context,
TypeSourceInfo *Type,
SourceLocation LParenLoc,
- ArrayRef<Expr*> Args,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc);
- static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C,
+ static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context,
unsigned NumArgs);
/// Retrieve the type that is being constructed, as specified
/// in the source code.
- QualType getTypeAsWritten() const { return Type->getType(); }
+ QualType getTypeAsWritten() const { return TSI->getType(); }
/// Retrieve the type source information for the type being
/// constructed.
- TypeSourceInfo *getTypeSourceInfo() const { return Type; }
+ TypeSourceInfo *getTypeSourceInfo() const { return TSI; }
/// Retrieve the location of the left parentheses ('(') that
/// precedes the argument list.
@@ -3173,40 +3223,43 @@ public:
bool isListInitialization() const { return LParenLoc.isInvalid(); }
/// Retrieve the number of arguments.
- unsigned arg_size() const { return NumArgs; }
+ unsigned arg_size() const { return CXXUnresolvedConstructExprBits.NumArgs; }
using arg_iterator = Expr **;
+ using arg_range = llvm::iterator_range<arg_iterator>;
arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); }
- arg_iterator arg_end() { return arg_begin() + NumArgs; }
+ arg_iterator arg_end() { return arg_begin() + arg_size(); }
+ arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
using const_arg_iterator = const Expr* const *;
+ using const_arg_range = llvm::iterator_range<const_arg_iterator>;
const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); }
- const_arg_iterator arg_end() const {
- return arg_begin() + NumArgs;
+ const_arg_iterator arg_end() const { return arg_begin() + arg_size(); }
+ const_arg_range arguments() const {
+ return const_arg_range(arg_begin(), arg_end());
}
Expr *getArg(unsigned I) {
- assert(I < NumArgs && "Argument index out-of-range");
- return *(arg_begin() + I);
+ assert(I < arg_size() && "Argument index out-of-range");
+ return arg_begin()[I];
}
const Expr *getArg(unsigned I) const {
- assert(I < NumArgs && "Argument index out-of-range");
- return *(arg_begin() + I);
+ assert(I < arg_size() && "Argument index out-of-range");
+ return arg_begin()[I];
}
void setArg(unsigned I, Expr *E) {
- assert(I < NumArgs && "Argument index out-of-range");
- *(arg_begin() + I) = E;
+ assert(I < arg_size() && "Argument index out-of-range");
+ arg_begin()[I] = E;
}
- SourceLocation getLocStart() const LLVM_READONLY;
-
- SourceLocation getLocEnd() const LLVM_READONLY {
- if (!RParenLoc.isValid() && NumArgs > 0)
- return getArg(NumArgs - 1)->getLocEnd();
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ if (!RParenLoc.isValid() && arg_size() > 0)
+ return getArg(arg_size() - 1)->getEndLoc();
return RParenLoc;
}
@@ -3217,7 +3270,7 @@ public:
// Iterators
child_range children() {
auto **begin = reinterpret_cast<Stmt **>(arg_begin());
- return child_range(begin, begin + NumArgs);
+ return child_range(begin, begin + arg_size());
}
};
@@ -3232,7 +3285,11 @@ class CXXDependentScopeMemberExpr final
: public Expr,
private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc> {
+ TemplateArgumentLoc, NamedDecl *> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
/// The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. Can be null in implicit accesses.
Stmt *Base;
@@ -3241,40 +3298,53 @@ class CXXDependentScopeMemberExpr final
/// implicit accesses.
QualType BaseType;
- /// Whether this member expression used the '->' operator or
- /// the '.' operator.
- bool IsArrow : 1;
-
- /// Whether this member expression has info for explicit template
- /// keyword and arguments.
- bool HasTemplateKWAndArgsInfo : 1;
-
- /// The location of the '->' or '.' operator.
- SourceLocation OperatorLoc;
-
/// The nested-name-specifier that precedes the member name, if any.
+ /// FIXME: This could be in principle store as a trailing object.
+ /// However the performance impact of doing so should be investigated first.
NestedNameSpecifierLoc QualifierLoc;
- /// In a qualified member access expression such as t->Base::f, this
- /// member stores the resolves of name lookup in the context of the member
- /// access expression, to be used at instantiation time.
- ///
- /// FIXME: This member, along with the QualifierLoc, could
- /// be stuck into a structure that is optionally allocated at the end of
- /// the CXXDependentScopeMemberExpr, to save space in the common case.
- NamedDecl *FirstQualifierFoundInScope;
-
/// The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
///
/// FIXME: could also be a template-id
DeclarationNameInfo MemberNameInfo;
- size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
+ // CXXDependentScopeMemberExpr is followed by several trailing objects,
+ // some of which optional. They are in order:
+ //
+ // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified
+ // template keyword and arguments. Present if and only if
+ // hasTemplateKWAndArgsInfo().
+ //
+ // * An array of getNumTemplateArgs() TemplateArgumentLoc containing location
+ // information for the explicitly specified template arguments.
+ //
+ // * An optional NamedDecl *. In a qualified member access expression such
+ // as t->Base::f, this member stores the resolves of name lookup in the
+ // context of the member access expression, to be used at instantiation
+ // time. Present if and only if hasFirstQualifierFoundInScope().
+
+ bool hasTemplateKWAndArgsInfo() const {
+ return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo;
+ }
+
+ bool hasFirstQualifierFoundInScope() const {
+ return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return hasTemplateKWAndArgsInfo();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
+ return getNumTemplateArgs();
}
- CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
+ unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const {
+ return hasFirstQualifierFoundInScope();
+ }
+
+ CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base,
QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
@@ -3283,33 +3353,29 @@ class CXXDependentScopeMemberExpr final
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
-public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
- friend TrailingObjects;
-
- CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
- QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- NamedDecl *FirstQualifierFoundInScope,
- DeclarationNameInfo MemberNameInfo);
+ CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
+ bool HasFirstQualifierFoundInScope);
+public:
static CXXDependentScopeMemberExpr *
- Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow,
+ Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
- CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
- unsigned NumTemplateArgs);
+ CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope);
/// True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
/// location of the operator is invalid in this case.
- bool isImplicitAccess() const;
+ bool isImplicitAccess() const {
+ if (!Base)
+ return true;
+ return cast<Expr>(Base)->isImplicitCXXThis();
+ }
/// Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m.
@@ -3322,13 +3388,14 @@ public:
/// Determine whether this member expression used the '->'
/// operator; otherwise, it used the '.' operator.
- bool isArrow() const { return IsArrow; }
+ bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; }
/// Retrieve the location of the '->' or '.' operator.
- SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ SourceLocation getOperatorLoc() const {
+ return CXXDependentScopeMemberExprBits.OperatorLoc;
+ }
- /// Retrieve the nested-name-specifier that qualifies the member
- /// name.
+ /// Retrieve the nested-name-specifier that qualifies the member name.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -3349,17 +3416,17 @@ public:
/// combined with the results of name lookup into the type of the object
/// expression itself (the class type of x).
NamedDecl *getFirstQualifierFoundInScope() const {
- return FirstQualifierFoundInScope;
+ if (!hasFirstQualifierFoundInScope())
+ return nullptr;
+ return *getTrailingObjects<NamedDecl *>();
}
- /// Retrieve the name of the member that this expression
- /// refers to.
+ /// Retrieve the name of the member that this expression refers to.
const DeclarationNameInfo &getMemberNameInfo() const {
return MemberNameInfo;
}
- /// Retrieve the name of the member that this expression
- /// refers to.
+ /// Retrieve the name of the member that this expression refers to.
DeclarationName getMember() const { return MemberNameInfo.getName(); }
// Retrieve the location of the name of the member that this
@@ -3369,21 +3436,24 @@ public:
/// Retrieve the location of the template keyword preceding the
/// member name, if any.
SourceLocation getTemplateKeywordLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const {
- if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ if (!hasTemplateKWAndArgsInfo())
+ return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
@@ -3424,15 +3494,15 @@ public:
return {getTemplateArgs(), getNumTemplateArgs()};
}
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
if (!isImplicitAccess())
- return Base->getLocStart();
+ return Base->getBeginLoc();
if (getQualifier())
return getQualifierLoc().getBeginLoc();
return MemberNameInfo.getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
return MemberNameInfo.getEndLoc();
@@ -3467,25 +3537,18 @@ public:
/// DeclRefExpr, depending on whether the member is static.
class UnresolvedMemberExpr final
: public OverloadExpr,
- private llvm::TrailingObjects<
- UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
+ private llvm::TrailingObjects<UnresolvedMemberExpr, DeclAccessPair,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
friend class ASTStmtReader;
friend class OverloadExpr;
friend TrailingObjects;
- /// Whether this member expression used the '->' operator or
- /// the '.' operator.
- bool IsArrow : 1;
-
- /// Whether the lookup results contain an unresolved using
- /// declaration.
- bool HasUnresolvedUsing : 1;
-
/// The expression for the base pointer or class reference,
/// e.g., the \c x in x.f.
///
/// This can be null if this is an 'unbased' member expression.
- Stmt *Base = nullptr;
+ Stmt *Base;
/// The type of the base expression; never null.
QualType BaseType;
@@ -3493,7 +3556,21 @@ class UnresolvedMemberExpr final
/// The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
- UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing,
+ // UnresolvedMemberExpr is followed by several trailing objects.
+ // They are in order:
+ //
+ // * An array of getNumResults() DeclAccessPair for the results. These are
+ // undesugared, which is to say, they may include UsingShadowDecls.
+ // Access is relative to the naming class.
+ //
+ // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified
+ // template keyword and arguments. Present if and only if
+ // hasTemplateKWAndArgsInfo().
+ //
+ // * An array of getNumTemplateArgs() TemplateArgumentLoc containing
+ // location information for the explicitly specified template arguments.
+
+ UnresolvedMemberExpr(const ASTContext &Context, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
@@ -3502,28 +3579,30 @@ class UnresolvedMemberExpr final
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
- UnresolvedMemberExpr(EmptyShell Empty)
- : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false),
- HasUnresolvedUsing(false) {}
+ UnresolvedMemberExpr(EmptyShell Empty, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo);
- size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
- return HasTemplateKWAndArgsInfo ? 1 : 0;
+ unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const {
+ return getNumDecls();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return hasTemplateKWAndArgsInfo();
}
public:
static UnresolvedMemberExpr *
- Create(const ASTContext &C, bool HasUnresolvedUsing,
- Expr *Base, QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
+ Create(const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base,
+ QualType BaseType, bool IsArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
- static UnresolvedMemberExpr *
- CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
- unsigned NumTemplateArgs);
+ static UnresolvedMemberExpr *CreateEmpty(const ASTContext &Context,
+ unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs);
/// True if this is an implicit access, i.e., one in which the
/// member being accessed was not written in the source.
@@ -3546,46 +3625,50 @@ public:
/// Determine whether the lookup results contain an unresolved using
/// declaration.
- bool hasUnresolvedUsing() const { return HasUnresolvedUsing; }
+ bool hasUnresolvedUsing() const {
+ return UnresolvedMemberExprBits.HasUnresolvedUsing;
+ }
/// Determine whether this member expression used the '->'
/// operator; otherwise, it used the '.' operator.
- bool isArrow() const { return IsArrow; }
+ bool isArrow() const { return UnresolvedMemberExprBits.IsArrow; }
/// Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
/// Retrieve the naming class of this lookup.
- CXXRecordDecl *getNamingClass() const;
+ CXXRecordDecl *getNamingClass();
+ const CXXRecordDecl *getNamingClass() const {
+ return const_cast<UnresolvedMemberExpr *>(this)->getNamingClass();
+ }
/// Retrieve the full name info for the member that this expression
/// refers to.
const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); }
- /// Retrieve the name of the member that this expression
- /// refers to.
+ /// Retrieve the name of the member that this expression refers to.
DeclarationName getMemberName() const { return getName(); }
- // Retrieve the location of the name of the member that this
- // expression refers to.
+ /// Retrieve the location of the name of the member that this
+ /// expression refers to.
SourceLocation getMemberLoc() const { return getNameLoc(); }
- // Return the preferred location (the member name) for the arrow when
- // diagnosing a problem with this expression.
+ /// Return the preferred location (the member name) for the arrow when
+ /// diagnosing a problem with this expression.
SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); }
- SourceLocation getLocStart() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const LLVM_READONLY {
if (!isImplicitAccess())
- return Base->getLocStart();
+ return Base->getBeginLoc();
if (NestedNameSpecifierLoc l = getQualifierLoc())
return l.getBeginLoc();
- return getMemberNameInfo().getLocStart();
+ return getMemberNameInfo().getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getEndLoc() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
- return getMemberNameInfo().getLocEnd();
+ return getMemberNameInfo().getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -3600,26 +3683,33 @@ public:
}
};
-inline ASTTemplateKWAndArgsInfo *
-OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo)
+DeclAccessPair *OverloadExpr::getTrailingResults() {
+ if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
+ return ULE->getTrailingObjects<DeclAccessPair>();
+ return cast<UnresolvedMemberExpr>(this)->getTrailingObjects<DeclAccessPair>();
+}
+
+ASTTemplateKWAndArgsInfo *OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() {
+ if (!hasTemplateKWAndArgsInfo())
return nullptr;
- if (isa<UnresolvedLookupExpr>(this))
- return cast<UnresolvedLookupExpr>(this)
- ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
- else
- return cast<UnresolvedMemberExpr>(this)
- ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+ if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
+ return ULE->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+ return cast<UnresolvedMemberExpr>(this)
+ ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
}
-inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
- if (isa<UnresolvedLookupExpr>(this))
- return cast<UnresolvedLookupExpr>(this)
- ->getTrailingObjects<TemplateArgumentLoc>();
- else
- return cast<UnresolvedMemberExpr>(this)
- ->getTrailingObjects<TemplateArgumentLoc>();
+TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
+ if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
+ return ULE->getTrailingObjects<TemplateArgumentLoc>();
+ return cast<UnresolvedMemberExpr>(this)
+ ->getTrailingObjects<TemplateArgumentLoc>();
+}
+
+CXXRecordDecl *OverloadExpr::getNamingClass() {
+ if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
+ return ULE->getNamingClass();
+ return cast<UnresolvedMemberExpr>(this)->getNamingClass();
}
/// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
@@ -3629,7 +3719,6 @@ inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
class CXXNoexceptExpr : public Expr {
friend class ASTStmtReader;
- bool Value : 1;
Stmt *Operand;
SourceRange Range;
@@ -3637,21 +3726,23 @@ public:
CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val,
SourceLocation Keyword, SourceLocation RParen)
: Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary,
- /*TypeDependent*/false,
- /*ValueDependent*/Val == CT_Dependent,
+ /*TypeDependent*/ false,
+ /*ValueDependent*/ Val == CT_Dependent,
Val == CT_Dependent || Operand->isInstantiationDependent(),
Operand->containsUnexpandedParameterPack()),
- Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) {}
+ Operand(Operand), Range(Keyword, RParen) {
+ CXXNoexceptExprBits.Value = Val == CT_Cannot;
+ }
CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {}
- Expr *getOperand() const { return static_cast<Expr*>(Operand); }
+ Expr *getOperand() const { return static_cast<Expr *>(Operand); }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
- SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getBeginLoc() const { return Range.getBegin(); }
+ SourceLocation getEndLoc() const { return Range.getEnd(); }
+ SourceRange getSourceRange() const { return Range; }
- bool getValue() const { return Value; }
+ bool getValue() const { return CXXNoexceptExprBits.Value; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXNoexceptExprClass;
@@ -3725,11 +3816,11 @@ public:
return None;
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return Pattern->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return Pattern->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return EllipsisLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == PackExpansionExprClass;
@@ -3849,8 +3940,8 @@ public:
return llvm::makeArrayRef(Args, Args + Length);
}
- SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == SizeOfPackExprClass;
@@ -3874,27 +3965,27 @@ class SubstNonTypeTemplateParmExpr : public Expr {
/// The replacement expression.
Stmt *Replacement;
- /// The location of the non-type template parameter reference.
- SourceLocation NameLoc;
-
explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
: Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
public:
- SubstNonTypeTemplateParmExpr(QualType type,
- ExprValueKind valueKind,
- SourceLocation loc,
- NonTypeTemplateParmDecl *param,
- Expr *replacement)
- : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary,
- replacement->isTypeDependent(), replacement->isValueDependent(),
- replacement->isInstantiationDependent(),
- replacement->containsUnexpandedParameterPack()),
- Param(param), Replacement(replacement), NameLoc(loc) {}
-
- SourceLocation getNameLoc() const { return NameLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; }
+ SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
+ SourceLocation Loc,
+ NonTypeTemplateParmDecl *Param,
+ Expr *Replacement)
+ : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary,
+ Replacement->isTypeDependent(), Replacement->isValueDependent(),
+ Replacement->isInstantiationDependent(),
+ Replacement->containsUnexpandedParameterPack()),
+ Param(Param), Replacement(Replacement) {
+ SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
+ }
+
+ SourceLocation getNameLoc() const {
+ return SubstNonTypeTemplateParmExprBits.NameLoc;
+ }
+ SourceLocation getBeginLoc() const { return getNameLoc(); }
+ SourceLocation getEndLoc() const { return getNameLoc(); }
Expr *getReplacement() const { return cast<Expr>(Replacement); }
@@ -3905,7 +3996,7 @@ public:
}
// Iterators
- child_range children() { return child_range(&Replacement, &Replacement+1); }
+ child_range children() { return child_range(&Replacement, &Replacement + 1); }
};
/// Represents a reference to a non-type template parameter pack that
@@ -3957,8 +4048,8 @@ public:
/// template arguments.
TemplateArgument getArgumentPack() const;
- SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass;
@@ -4030,8 +4121,8 @@ public:
/// Get an expansion of the parameter pack by index.
ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; }
- SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == FunctionParmPackExprClass;
@@ -4142,12 +4233,12 @@ public:
return getValueKind() == VK_LValue;
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getTemporary()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getTemporary()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getTemporary()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getTemporary()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -4217,13 +4308,9 @@ public:
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
BinaryOperatorKind getOperator() const { return Opcode; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return LParenLoc;
- }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return RParenLoc;
- }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXFoldExprClass;
@@ -4312,12 +4399,10 @@ public:
return static_cast<Expr*>(SubExprs[SubExpr::Resume]);
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return KeywordLoc;
- }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getCommonExpr()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getCommonExpr()->getEndLoc();
}
child_range children() {
@@ -4400,10 +4485,10 @@ public:
SourceLocation getKeywordLoc() const { return KeywordLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getOperand()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getOperand()->getEndLoc();
}
child_range children() { return child_range(SubExprs, SubExprs + 2); }
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index bb0402c27080..c7b305f3304e 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -67,8 +67,8 @@ public:
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return String->getEndLoc(); }
// Iterators
child_range children() { return child_range(&String, &String+1); }
@@ -94,8 +94,8 @@ public:
bool getValue() const { return Value; }
void setValue(bool V) { Value = V; }
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@@ -141,8 +141,8 @@ public:
SourceLocation getAtLoc() const { return Range.getBegin(); }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY {
return Range;
@@ -194,8 +194,8 @@ public:
static ObjCArrayLiteral *CreateEmpty(const ASTContext &C,
unsigned NumElements);
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
/// Retrieve elements of array of literals.
@@ -359,8 +359,8 @@ public:
return DictWithObjectsMethod;
}
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
// Iterators
@@ -412,8 +412,8 @@ public:
EncodedType = EncType;
}
- SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
// Iterators
child_range children() {
@@ -447,8 +447,8 @@ public:
void setAtLoc(SourceLocation L) { AtLoc = L; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
/// getNumArgs - Return the number of actual arguments to this call.
unsigned getNumArgs() const { return SelName.getNumArgs(); }
@@ -496,8 +496,8 @@ public:
void setAtLoc(SourceLocation L) { AtLoc = L; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
// Iterators
child_range children() {
@@ -556,10 +556,10 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return isFreeIvar() ? Loc : getBase()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return isFreeIvar() ? Loc : getBase()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
SourceLocation getOpLoc() const { return OpLoc; }
void setOpLoc(SourceLocation L) { OpLoc = L; }
@@ -742,11 +742,12 @@ public:
/// Determine the type of the base, regardless of the kind of receiver.
QualType getReceiverType(const ASTContext &ctx) const;
- SourceLocation getLocStart() const LLVM_READONLY {
- return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return isObjectReceiver() ? getBase()->getBeginLoc()
+ : getReceiverLocation();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return IdLoc; }
// Iterators
child_range children() {
@@ -838,11 +839,11 @@ public:
SourceLocation getRBracket() const { return RBracket; }
void setRBracket(SourceLocation RB) { RBracket = RB; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return SubExprs[BASE]->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SubExprs[BASE]->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RBracket; }
Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
@@ -1364,7 +1365,7 @@ public:
SourceLocation getSelectorStartLoc() const {
if (isImplicit())
- return getLocStart();
+ return getBeginLoc();
return getSelectorLoc(0);
}
@@ -1395,8 +1396,8 @@ public:
RBracLoc = R.getEnd();
}
- SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LBracLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RBracLoc; }
// Iterators
child_range children();
@@ -1472,15 +1473,15 @@ public:
SourceLocation getOpLoc() const { return OpLoc; }
void setOpLoc(SourceLocation L) { OpLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return getBase()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getBase()->getBeginLoc();
}
SourceLocation getBaseLocEnd() const LLVM_READONLY {
- return getBase()->getLocEnd();
+ return getBase()->getEndLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return IsaMemberLoc; }
SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }
@@ -1549,10 +1550,12 @@ public:
child_range children() { return child_range(&Operand, &Operand+1); }
// Source locations are determined by the subexpression.
- SourceLocation getLocStart() const LLVM_READONLY {
- return Operand->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return Operand->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return Operand->getEndLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return Operand->getLocEnd();}
SourceLocation getExprLoc() const LLVM_READONLY {
return getSubExpr()->getExprLoc();
@@ -1571,8 +1574,7 @@ public:
/// \endcode
class ObjCBridgedCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<
- ObjCBridgedCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class CastExpr;
@@ -1582,10 +1584,6 @@ class ObjCBridgedCastExpr final
SourceLocation BridgeKeywordLoc;
unsigned Kind : 2;
- size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const {
- return path_empty() ? 0 : 1;
- }
-
public:
ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
CastKind CK, SourceLocation BridgeKeywordLoc,
@@ -1611,10 +1609,10 @@ public:
/// The location of the bridge keyword.
SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getSubExpr()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getSubExpr()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -1651,8 +1649,8 @@ public:
explicit ObjCAvailabilityCheckExpr(EmptyShell Shell)
: Expr(ObjCAvailabilityCheckExprClass, Shell) {}
- SourceLocation getLocStart() const { return AtLoc; }
- SourceLocation getLocEnd() const { return RParen; }
+ SourceLocation getBeginLoc() const { return AtLoc; }
+ SourceLocation getEndLoc() const { return RParen; }
SourceRange getSourceRange() const { return {AtLoc, RParen}; }
/// This may be '*', in which case this should fold to true.
diff --git a/include/clang/AST/ExprOpenMP.h b/include/clang/AST/ExprOpenMP.h
index 2b4b5ec4d0e4..d88eebf5e54f 100644
--- a/include/clang/AST/ExprOpenMP.h
+++ b/include/clang/AST/ExprOpenMP.h
@@ -101,10 +101,10 @@ public:
/// Set length of the array section.
void setLength(Expr *E) { SubExprs[LENGTH] = E; }
- SourceLocation getLocStart() const LLVM_READONLY {
- return getBase()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getBase()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation L) { ColonLoc = L; }
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/AST/FormatString.h
index 598d341ac829..4a89c797b648 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/AST/FormatString.h
@@ -303,6 +303,8 @@ public:
QualType getRepresentativeType(ASTContext &C) const;
+ ArgType makeVectorType(ASTContext &C, unsigned NumElts) const;
+
std::string getRepresentativeTypeName(ASTContext &C) const;
};
@@ -322,6 +324,10 @@ public:
: start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
UsesPositionalArg(0), UsesDotPrefix(0) {}
+ explicit OptionalAmount(unsigned Amount)
+ : start(nullptr), length(0), hs(Constant), amt(Amount),
+ UsesPositionalArg(false), UsesDotPrefix(false) {}
+
bool isInvalid() const {
return hs == Invalid;
}
@@ -379,6 +385,8 @@ protected:
LengthModifier LM;
OptionalAmount FieldWidth;
ConversionSpecifier CS;
+ OptionalAmount VectorNumElts;
+
/// Positional arguments, an IEEE extension:
/// IEEE Std 1003.1, 2004 Edition
/// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
@@ -386,7 +394,8 @@ protected:
unsigned argIndex;
public:
FormatSpecifier(bool isPrintf)
- : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
+ : CS(isPrintf), VectorNumElts(false),
+ UsesPositionalArg(false), argIndex(0) {}
void setLengthModifier(LengthModifier lm) {
LM = lm;
@@ -414,6 +423,14 @@ public:
return FieldWidth;
}
+ void setVectorNumElts(const OptionalAmount &Amt) {
+ VectorNumElts = Amt;
+ }
+
+ const OptionalAmount &getVectorNumElts() const {
+ return VectorNumElts;
+ }
+
void setFieldWidth(const OptionalAmount &Amt) {
FieldWidth = Amt;
}
@@ -475,13 +492,19 @@ class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
OptionalFlag HasObjCTechnicalTerm; // '[tt]'
OptionalFlag IsPrivate; // '{private}'
OptionalFlag IsPublic; // '{public}'
+ OptionalFlag IsSensitive; // '{sensitive}'
OptionalAmount Precision;
+ StringRef MaskType;
+
+ ArgType getScalarArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
+
public:
PrintfSpecifier()
: FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),
IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
HasAlternativeForm("#"), HasLeadingZeroes("0"),
- HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public") {}
+ HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public"),
+ IsSensitive("sensitive") {}
static PrintfSpecifier Parse(const char *beg, const char *end);
@@ -512,6 +535,9 @@ public:
}
void setIsPrivate(const char *position) { IsPrivate.setPosition(position); }
void setIsPublic(const char *position) { IsPublic.setPosition(position); }
+ void setIsSensitive(const char *position) {
+ IsSensitive.setPosition(position);
+ }
void setUsesPositionalArg() { UsesPositionalArg = true; }
// Methods for querying the format specifier.
@@ -551,8 +577,12 @@ public:
const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }
const OptionalFlag &isPrivate() const { return IsPrivate; }
const OptionalFlag &isPublic() const { return IsPublic; }
+ const OptionalFlag &isSensitive() const { return IsSensitive; }
bool usesPositionalArg() const { return UsesPositionalArg; }
+ StringRef getMaskType() const { return MaskType; }
+ void setMaskType(StringRef S) { MaskType = S; }
+
/// Changes the specifier and length according to a QualType, retaining any
/// flags or options. Returns true on success, or false when a conversion
/// was not successful.
@@ -685,6 +715,9 @@ public:
return true;
}
+ /// Handle mask types whose sizes are not between one and eight bytes.
+ virtual void handleInvalidMaskType(StringRef MaskType) {}
+
// Scanf-specific handlers.
virtual bool HandleInvalidScanfConversionSpecifier(
diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h
index 7f017994216f..a3c0cab3799f 100644
--- a/include/clang/AST/GlobalDecl.h
+++ b/include/clang/AST/GlobalDecl.h
@@ -34,6 +34,7 @@ namespace clang {
/// a VarDecl, a FunctionDecl or a BlockDecl.
class GlobalDecl {
llvm::PointerIntPair<const Decl *, 2> Value;
+ unsigned MultiVersionIndex = 0;
void Init(const Decl *D) {
assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
@@ -45,7 +46,10 @@ class GlobalDecl {
public:
GlobalDecl() = default;
GlobalDecl(const VarDecl *D) { Init(D);}
- GlobalDecl(const FunctionDecl *D) { Init(D); }
+ GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0)
+ : MultiVersionIndex(MVIndex) {
+ Init(D);
+ }
GlobalDecl(const BlockDecl *D) { Init(D); }
GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
@@ -57,6 +61,7 @@ public:
GlobalDecl CanonGD;
CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
CanonGD.Value.setInt(Value.getInt());
+ CanonGD.MultiVersionIndex = MultiVersionIndex;
return CanonGD;
}
@@ -73,8 +78,17 @@ public:
return static_cast<CXXDtorType>(Value.getInt());
}
+ unsigned getMultiVersionIndex() const {
+ assert(isa<FunctionDecl>(getDecl()) &&
+ !isa<CXXConstructorDecl>(getDecl()) &&
+ !isa<CXXDestructorDecl>(getDecl()) &&
+ "Decl is not a plain FunctionDecl!");
+ return MultiVersionIndex;
+ }
+
friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
- return LHS.Value == RHS.Value;
+ return LHS.Value == RHS.Value &&
+ LHS.MultiVersionIndex == RHS.MultiVersionIndex;
}
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
@@ -90,6 +104,16 @@ public:
Result.Value.setPointer(D);
return Result;
}
+
+ GlobalDecl getWithMultiVersionIndex(unsigned Index) {
+ assert(isa<FunctionDecl>(getDecl()) &&
+ !isa<CXXConstructorDecl>(getDecl()) &&
+ !isa<CXXDestructorDecl>(getDecl()) &&
+ "Decl is not a plain FunctionDecl!");
+ GlobalDecl Result(*this);
+ Result.MultiVersionIndex = Index;
+ return Result;
+ }
};
} // namespace clang
diff --git a/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h b/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h
index 264f20f19ad5..47dac4362c8e 100644
--- a/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h
+++ b/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h
@@ -99,8 +99,8 @@ public:
LexicallyNestedDeclarations.clear();
for (++I; I != E; ++I) {
Decl *Sibling = *I;
- if (!SM.isBeforeInTranslationUnit(Sibling->getLocStart(),
- Child->getLocEnd()))
+ if (!SM.isBeforeInTranslationUnit(Sibling->getBeginLoc(),
+ Child->getEndLoc()))
break;
if (!BaseType::canIgnoreChildDeclWhileTraversingDeclContext(Sibling))
LexicallyNestedDeclarations.push_back(Sibling);
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index c42fe91b3246..309ed5a1a5d2 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_MANGLE_H
#define LLVM_CLANG_AST_MANGLE_H
+#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index bf2afe38cbca..f9340c64f3eb 100644
--- a/include/clang/AST/NSAPI.h
+++ b/include/clang/AST/NSAPI.h
@@ -166,6 +166,14 @@ public:
return getOrInitSelector(StringRef("isEqual"), isEqualSel);
}
+ Selector getNewSelector() const {
+ return getOrInitNullarySelector("new", NewSel);
+ }
+
+ Selector getInitSelector() const {
+ return getOrInitNullarySelector("init", InitSel);
+ }
+
/// Enumerates the NSNumber methods used to generate literals.
enum NSNumberLiteralMethodKind {
NSNumberWithChar,
@@ -229,6 +237,7 @@ private:
bool isObjCEnumerator(const Expr *E,
StringRef name, IdentifierInfo *&II) const;
Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
+ Selector getOrInitNullarySelector(StringRef Id, Selector &Sel) const;
ASTContext &Ctx;
@@ -251,7 +260,7 @@ private:
mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
- isEqualSel;
+ isEqualSel, InitSel, NewSel;
mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 3a7b45767dac..8befe9ae4258 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -212,9 +212,12 @@ public:
/// parameter pack (for C++11 variadic templates).
bool containsUnexpandedParameterPack() const;
- /// Print this nested name specifier to the given output
- /// stream.
- void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
+ /// Print this nested name specifier to the given output stream. If
+ /// `ResolveTemplateArguments` is true, we'll print actual types, e.g.
+ /// `ns::SomeTemplate<int, MyClass>` instead of
+ /// `ns::SomeTemplate<Container::value_type, T>`.
+ void print(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool ResolveTemplateArguments = false) const;
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(Prefix.getOpaqueValue());
@@ -225,6 +228,8 @@ public:
/// in debugging.
void dump(const LangOptions &LO) const;
void dump() const;
+ void dump(llvm::raw_ostream &OS) const;
+ void dump(llvm::raw_ostream &OS, const LangOptions &LO) const;
};
/// A C++ nested-name-specifier augmented with source location
diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h
index 75b361789211..feaa83844a1a 100644
--- a/include/clang/AST/ODRHash.h
+++ b/include/clang/AST/ODRHash.h
@@ -13,6 +13,9 @@
///
//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_ODRHASH_H
+#define LLVM_CLANG_AST_ODRHASH_H
+
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TemplateBase.h"
@@ -80,7 +83,7 @@ public:
void AddIdentifierInfo(const IdentifierInfo *II);
void AddNestedNameSpecifier(const NestedNameSpecifier *NNS);
void AddTemplateName(TemplateName Name);
- void AddDeclarationName(DeclarationName Name);
+ void AddDeclarationName(DeclarationName Name, bool TreatAsDecl = false);
void AddTemplateArgument(TemplateArgument TA);
void AddTemplateParameterList(const TemplateParameterList *TPL);
@@ -88,6 +91,11 @@ public:
void AddBoolean(bool value);
static bool isWhitelistedDecl(const Decl* D, const DeclContext *Parent);
+
+private:
+ void AddDeclarationNameImpl(DeclarationName Name);
};
} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/Analyses/OSLog.h b/include/clang/AST/OSLog.h
index 1e60a237b770..2b21855e7a6e 100644
--- a/include/clang/Analysis/Analyses/OSLog.h
+++ b/include/clang/AST/OSLog.h
@@ -52,7 +52,10 @@ public:
// The item is corresponding to the '%m' format specifier, no value is
// populated in the buffer and the runtime is loading the errno value.
- ErrnoKind
+ ErrnoKind,
+
+ // The item is a mask type.
+ MaskKind
};
enum {
@@ -60,7 +63,10 @@ public:
IsPrivate = 0x1,
// The item is marked "public" in the format string.
- IsPublic = 0x2
+ IsPublic = 0x2,
+
+ // The item is marked "sensitive" in the format string.
+ IsSensitive = 0x4 | IsPrivate
};
private:
@@ -69,21 +75,24 @@ private:
CharUnits ConstValue;
CharUnits Size; // size of the data, not including the header bytes
unsigned Flags = 0;
+ StringRef MaskType;
public:
- OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)
- : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}
+ OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags,
+ StringRef maskType = StringRef())
+ : TheKind(kind), TheExpr(expr), Size(size), Flags(flags),
+ MaskType(maskType) {
+ assert(((Flags == 0) || (Flags == IsPrivate) || (Flags == IsPublic) ||
+ (Flags == IsSensitive)) &&
+ "unexpected privacy flag");
+ }
OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
: TheKind(CountKind), ConstValue(value),
Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
unsigned char getDescriptorByte() const {
- unsigned char result = 0;
- if (getIsPrivate())
- result |= IsPrivate;
- if (getIsPublic())
- result |= IsPublic;
+ unsigned char result = Flags;
result |= ((unsigned)getKind()) << 4;
return result;
}
@@ -92,11 +101,12 @@ public:
Kind getKind() const { return TheKind; }
bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
- bool getIsPublic() const { return (Flags & IsPublic) != 0; }
const Expr *getExpr() const { return TheExpr; }
CharUnits getConstValue() const { return ConstValue; }
CharUnits size() const { return Size; }
+
+ StringRef getMaskType() const { return MaskType; }
};
class OSLogBufferLayout {
@@ -120,14 +130,10 @@ public:
Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
}
- bool hasPublicItems() const {
- return llvm::any_of(
- Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });
- }
-
- bool hasNonScalar() const {
+ bool hasNonScalarOrMask() const {
return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
- return Item.getKind() != OSLogBufferItem::ScalarKind;
+ return Item.getKind() != OSLogBufferItem::ScalarKind ||
+ !Item.getMaskType().empty();
});
}
@@ -135,7 +141,7 @@ public:
unsigned char result = 0;
if (hasPrivateItems())
result |= HasPrivateItems;
- if (hasNonScalar())
+ if (hasNonScalarOrMask())
result |= HasNonScalarItems;
return result;
}
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index a28609f8cdf9..bdcdf74b2630 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -64,10 +64,10 @@ protected:
public:
/// Returns the starting location of the clause.
- SourceLocation getLocStart() const { return StartLoc; }
+ SourceLocation getBeginLoc() const { return StartLoc; }
/// Returns the ending location of the clause.
- SourceLocation getLocEnd() const { return EndLoc; }
+ SourceLocation getEndLoc() const { return EndLoc; }
/// Sets the starting location of the clause.
void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
@@ -734,6 +734,210 @@ public:
}
};
+/// This represents 'unified_address' clause in the '#pragma omp requires'
+/// directive.
+///
+/// \code
+/// #pragma omp requires unified_address
+/// \endcode
+/// In this example directive '#pragma omp requires' has 'unified_address'
+/// clause.
+class OMPUnifiedAddressClause final : public OMPClause {
+public:
+ friend class OMPClauseReader;
+ /// Build 'unified_address' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_unified_address, StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPUnifiedAddressClause()
+ : OMPClause(OMPC_unified_address, SourceLocation(), SourceLocation()) {}
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_unified_address;
+ }
+};
+
+/// This represents 'unified_shared_memory' clause in the '#pragma omp requires'
+/// directive.
+///
+/// \code
+/// #pragma omp requires unified_shared_memory
+/// \endcode
+/// In this example directive '#pragma omp requires' has 'unified_shared_memory'
+/// clause.
+class OMPUnifiedSharedMemoryClause final : public OMPClause {
+public:
+ friend class OMPClauseReader;
+ /// Build 'unified_shared_memory' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_unified_shared_memory, StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPUnifiedSharedMemoryClause()
+ : OMPClause(OMPC_unified_shared_memory, SourceLocation(), SourceLocation()) {}
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_unified_shared_memory;
+ }
+};
+
+/// This represents 'reverse_offload' clause in the '#pragma omp requires'
+/// directive.
+///
+/// \code
+/// #pragma omp requires reverse_offload
+/// \endcode
+/// In this example directive '#pragma omp requires' has 'reverse_offload'
+/// clause.
+class OMPReverseOffloadClause final : public OMPClause {
+public:
+ friend class OMPClauseReader;
+ /// Build 'reverse_offload' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_reverse_offload, StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPReverseOffloadClause()
+ : OMPClause(OMPC_reverse_offload, SourceLocation(), SourceLocation()) {}
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_reverse_offload;
+ }
+};
+
+/// This represents 'dynamic_allocators' clause in the '#pragma omp requires'
+/// directive.
+///
+/// \code
+/// #pragma omp requires dynamic_allocators
+/// \endcode
+/// In this example directive '#pragma omp requires' has 'dynamic_allocators'
+/// clause.
+class OMPDynamicAllocatorsClause final : public OMPClause {
+public:
+ friend class OMPClauseReader;
+ /// Build 'dynamic_allocators' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_dynamic_allocators, StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPDynamicAllocatorsClause()
+ : OMPClause(OMPC_dynamic_allocators, SourceLocation(), SourceLocation()) {
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_dynamic_allocators;
+ }
+};
+
+/// This represents 'atomic_default_mem_order' clause in the '#pragma omp
+/// requires' directive.
+///
+/// \code
+/// #pragma omp requires atomic_default_mem_order(seq_cst)
+/// \endcode
+/// In this example directive '#pragma omp requires' has simple
+/// atomic_default_mem_order' clause with kind 'seq_cst'.
+class OMPAtomicDefaultMemOrderClause final : public OMPClause {
+ friend class OMPClauseReader;
+
+ /// Location of '('
+ SourceLocation LParenLoc;
+
+ /// A kind of the 'atomic_default_mem_order' clause.
+ OpenMPAtomicDefaultMemOrderClauseKind Kind =
+ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown;
+
+ /// Start location of the kind in source code.
+ SourceLocation KindKwLoc;
+
+ /// Set kind of the clause.
+ ///
+ /// \param K Kind of clause.
+ void setAtomicDefaultMemOrderKind(OpenMPAtomicDefaultMemOrderClauseKind K) {
+ Kind = K;
+ }
+
+ /// Set clause kind location.
+ ///
+ /// \param KLoc Kind location.
+ void setAtomicDefaultMemOrderKindKwLoc(SourceLocation KLoc) {
+ KindKwLoc = KLoc;
+ }
+
+public:
+ /// Build 'atomic_default_mem_order' clause with argument \a A ('seq_cst',
+ /// 'acq_rel' or 'relaxed').
+ ///
+ /// \param A Argument of the clause ('seq_cst', 'acq_rel' or 'relaxed').
+ /// \param ALoc Starting location of the argument.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ OMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind A,
+ SourceLocation ALoc, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_atomic_default_mem_order, StartLoc, EndLoc),
+ LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {}
+
+ /// Build an empty clause.
+ OMPAtomicDefaultMemOrderClause()
+ : OMPClause(OMPC_atomic_default_mem_order, SourceLocation(),
+ SourceLocation()) {}
+
+ /// Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+ /// Returns the locaiton of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// Returns kind of the clause.
+ OpenMPAtomicDefaultMemOrderClauseKind getAtomicDefaultMemOrderKind() const {
+ return Kind;
+ }
+
+ /// Returns location of clause kind.
+ SourceLocation getAtomicDefaultMemOrderKindKwLoc() const { return KindKwLoc; }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_atomic_default_mem_order;
+ }
+};
+
/// This represents 'schedule' clause in the '#pragma omp ...' directive.
///
/// \code
@@ -922,8 +1126,11 @@ public:
/// \endcode
/// In this example directive '#pragma omp for' has 'ordered' clause with
/// parameter 2.
-class OMPOrderedClause : public OMPClause {
+class OMPOrderedClause final
+ : public OMPClause,
+ private llvm::TrailingObjects<OMPOrderedClause, Expr *> {
friend class OMPClauseReader;
+ friend TrailingObjects;
/// Location of '('.
SourceLocation LParenLoc;
@@ -931,6 +1138,26 @@ class OMPOrderedClause : public OMPClause {
/// Number of for-loops.
Stmt *NumForLoops = nullptr;
+ /// Real number of loops.
+ unsigned NumberOfLoops = 0;
+
+ /// Build 'ordered' clause.
+ ///
+ /// \param Num Expression, possibly associated with this clause.
+ /// \param NumLoops Number of loops, associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ OMPOrderedClause(Expr *Num, unsigned NumLoops, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumForLoops(Num), NumberOfLoops(NumLoops) {}
+
+ /// Build an empty clause.
+ explicit OMPOrderedClause(unsigned NumLoops)
+ : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()),
+ NumberOfLoops(NumLoops) {}
+
/// Set the number of associated for-loops.
void setNumForLoops(Expr *Num) { NumForLoops = Num; }
@@ -938,17 +1165,17 @@ public:
/// Build 'ordered' clause.
///
/// \param Num Expression, possibly associated with this clause.
+ /// \param NumLoops Number of loops, associated with this clause.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- OMPOrderedClause(Expr *Num, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc)
- : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
- NumForLoops(Num) {}
+ static OMPOrderedClause *Create(const ASTContext &C, Expr *Num,
+ unsigned NumLoops, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Build an empty clause.
- explicit OMPOrderedClause()
- : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {}
+ static OMPOrderedClause* CreateEmpty(const ASTContext &C, unsigned NumLoops);
/// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
@@ -959,6 +1186,17 @@ public:
/// Return the number of associated for-loops.
Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
+ /// Set number of iterations for the specified loop.
+ void setLoopNumIterations(unsigned NumLoop, Expr *NumIterations);
+ /// Get number of iterations for all the loops.
+ ArrayRef<Expr *> getLoopNumIterations() const;
+
+ /// Set loop counter for the specified loop.
+ void setLoopCounter(unsigned NumLoop, Expr *Counter);
+ /// Get loops counter for the specified loop.
+ Expr *getLoopCounter(unsigned NumLoop);
+ const Expr *getLoopCounter(unsigned NumLoop) const;
+
child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
static bool classof(const OMPClause *T) {
@@ -3087,24 +3325,32 @@ class OMPDependClause final
/// Colon location.
SourceLocation ColonLoc;
+ /// Number of loops, associated with the depend clause.
+ unsigned NumLoops = 0;
+
/// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, unsigned N)
+ SourceLocation EndLoc, unsigned N, unsigned NumLoops)
: OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc,
- EndLoc, N) {}
+ EndLoc, N), NumLoops(NumLoops) {}
/// Build an empty clause.
///
/// \param N Number of variables.
- explicit OMPDependClause(unsigned N)
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
+ explicit OMPDependClause(unsigned N, unsigned NumLoops)
: OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(),
SourceLocation(), SourceLocation(),
- N) {}
+ N),
+ NumLoops(NumLoops) {}
/// Set dependency kind.
void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; }
@@ -3126,16 +3372,23 @@ public:
/// \param DepLoc Location of the dependency type.
/// \param ColonLoc Colon location.
/// \param VL List of references to the variables.
- static OMPDependClause *
- Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
- SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL);
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
+ static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VL, unsigned NumLoops);
/// Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
- static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N);
+ /// \param NumLoops Number of loops that is associated with this depend
+ /// clause.
+ static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N,
+ unsigned NumLoops);
/// Get dependency type.
OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
@@ -3146,15 +3399,16 @@ public:
/// Get colon location.
SourceLocation getColonLoc() const { return ColonLoc; }
- /// Set the loop counter value for the depend clauses with 'sink|source' kind
- /// of dependency. Required for codegen.
- void setCounterValue(Expr *V);
+ /// Get number of loops associated with the clause.
+ unsigned getNumLoops() const { return NumLoops; }
- /// Get the loop counter value.
- Expr *getCounterValue();
+ /// Set the loop data for the depend clauses with 'sink|source' kind of
+ /// dependency.
+ void setLoopData(unsigned NumLoop, Expr *Cnt);
- /// Get the loop counter value.
- const Expr *getCounterValue() const;
+ /// Get the loop data.
+ Expr *getLoopData(unsigned NumLoop);
+ const Expr *getLoopData(unsigned NumLoop) const;
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
@@ -3807,8 +4061,19 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
- /// Map type modifier for the 'map' clause.
- OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+public:
+ /// Number of allowed map-type-modifiers.
+ static constexpr unsigned NumberOfModifiers =
+ OMPC_MAP_MODIFIER_last - OMPC_MAP_MODIFIER_unknown - 1;
+
+private:
+ /// Map-type-modifiers for the 'map' clause.
+ OpenMPMapModifierKind MapTypeModifiers[NumberOfModifiers] = {
+ OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown
+ };
+
+ /// Location of map-type-modifiers for the 'map' clause.
+ SourceLocation MapTypeModifiersLoc[NumberOfModifiers];
/// Map type for the 'map' clause.
OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
@@ -3826,7 +4091,8 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
/// NumUniqueDeclarations declarations, \a NumComponentLists total component
/// lists, and \a NumComponents total expression components.
///
- /// \param MapTypeModifier Map type modifier.
+ /// \param MapModifiers Map-type-modifiers.
+ /// \param MapModifiersLoc Locations of map-type-modifiers.
/// \param MapType Map type.
/// \param MapTypeIsImplicit Map type is inferred implicitly.
/// \param MapLoc Location of the map type.
@@ -3837,7 +4103,8 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
/// clause.
/// \param NumComponentLists Number of component lists in this clause.
/// \param NumComponents Total number of expression components in the clause.
- explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+ explicit OMPMapClause(ArrayRef<OpenMPMapModifierKind> MapModifiers,
+ ArrayRef<SourceLocation> MapModifiersLoc,
OpenMPMapClauseKind MapType, bool MapTypeIsImplicit,
SourceLocation MapLoc, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
@@ -3846,8 +4113,17 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
: OMPMappableExprListClause(OMPC_map, StartLoc, LParenLoc, EndLoc,
NumVars, NumUniqueDeclarations,
NumComponentLists, NumComponents),
- MapTypeModifier(MapTypeModifier), MapType(MapType),
- MapTypeIsImplicit(MapTypeIsImplicit), MapLoc(MapLoc) {}
+ MapType(MapType), MapTypeIsImplicit(MapTypeIsImplicit),
+ MapLoc(MapLoc) {
+ assert(llvm::array_lengthof(MapTypeModifiers) == MapModifiers.size()
+ && "Unexpected number of map type modifiers.");
+ llvm::copy(MapModifiers, std::begin(MapTypeModifiers));
+
+ assert(llvm::array_lengthof(MapTypeModifiersLoc) ==
+ MapModifiersLoc.size() &&
+ "Unexpected number of map type modifier locations.");
+ llvm::copy(MapModifiersLoc, std::begin(MapTypeModifiersLoc));
+ }
/// Build an empty clause.
///
@@ -3862,10 +4138,25 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
OMPC_map, SourceLocation(), SourceLocation(), SourceLocation(),
NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {}
- /// Set type modifier for the clause.
+ /// Set map-type-modifier for the clause.
+ ///
+ /// \param I index for map-type-modifier.
+ /// \param T map-type-modifier for the clause.
+ void setMapTypeModifier(unsigned I, OpenMPMapModifierKind T) {
+ assert(I < NumberOfModifiers &&
+ "Unexpected index to store map type modifier, exceeds array size.");
+ MapTypeModifiers[I] = T;
+ }
+
+ /// Set location for the map-type-modifier.
///
- /// \param T Type Modifier for the clause.
- void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; }
+ /// \param I index for map-type-modifier location.
+ /// \param TLoc map-type-modifier location.
+ void setMapTypeModifierLoc(unsigned I, SourceLocation TLoc) {
+ assert(I < NumberOfModifiers &&
+ "Index to store map type modifier location exceeds array size.");
+ MapTypeModifiersLoc[I] = TLoc;
+ }
/// Set type for the clause.
///
@@ -3889,7 +4180,8 @@ public:
/// \param Vars The original expression used in the clause.
/// \param Declarations Declarations used in the clause.
/// \param ComponentLists Component lists used in the clause.
- /// \param TypeModifier Map type modifier.
+ /// \param MapModifiers Map-type-modifiers.
+ /// \param MapModifiersLoc Location of map-type-modifiers.
/// \param Type Map type.
/// \param TypeIsImplicit Map type is inferred implicitly.
/// \param TypeLoc Location of the map type.
@@ -3898,7 +4190,8 @@ public:
ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists,
- OpenMPMapClauseKind TypeModifier,
+ ArrayRef<OpenMPMapModifierKind> MapModifiers,
+ ArrayRef<SourceLocation> MapModifiersLoc,
OpenMPMapClauseKind Type, bool TypeIsImplicit,
SourceLocation TypeLoc);
@@ -3928,9 +4221,33 @@ public:
/// messages for some target directives.
bool isImplicitMapType() const LLVM_READONLY { return MapTypeIsImplicit; }
- /// Fetches the map type modifier for the clause.
- OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY {
- return MapTypeModifier;
+ /// Fetches the map-type-modifier at 'Cnt' index of array of modifiers.
+ ///
+ /// \param Cnt index for map-type-modifier.
+ OpenMPMapModifierKind getMapTypeModifier(unsigned Cnt) const LLVM_READONLY {
+ assert(Cnt < NumberOfModifiers &&
+ "Requested modifier exceeds the total number of modifiers.");
+ return MapTypeModifiers[Cnt];
+ }
+
+ /// Fetches the map-type-modifier location at 'Cnt' index of array of
+ /// modifiers' locations.
+ ///
+ /// \param Cnt index for map-type-modifier location.
+ SourceLocation getMapTypeModifierLoc(unsigned Cnt) const LLVM_READONLY {
+ assert(Cnt < NumberOfModifiers &&
+ "Requested modifier location exceeds total number of modifiers.");
+ return MapTypeModifiersLoc[Cnt];
+ }
+
+ /// Fetches ArrayRef of map-type-modifiers.
+ ArrayRef<OpenMPMapModifierKind> getMapTypeModifiers() const LLVM_READONLY {
+ return llvm::makeArrayRef(MapTypeModifiers);
+ }
+
+ /// Fetches ArrayRef of location of map-type-modifiers.
+ ArrayRef<SourceLocation> getMapTypeModifiersLoc() const LLVM_READONLY {
+ return llvm::makeArrayRef(MapTypeModifiersLoc);
}
/// Fetches location of clause mapping kind.
@@ -4991,6 +5308,59 @@ public:
}
};
+/// This class implements a simple visitor for OMPClause
+/// subclasses.
+template<class ImplClass, template <typename> class Ptr, typename RetTy>
+class OMPClauseVisitorBase {
+public:
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(CLASS) \
+ return static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<PTR(CLASS)>(S))
+
+#define OPENMP_CLAUSE(Name, Class) \
+ RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); }
+#include "clang/Basic/OpenMPKinds.def"
+
+ RetTy Visit(PTR(OMPClause) S) {
+ // Top switch clause: visit each OMPClause.
+ switch (S->getClauseKind()) {
+ default: llvm_unreachable("Unknown clause kind!");
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_ ## Name : return Visit ## Class(static_cast<PTR(Class)>(S));
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ }
+ // Base case, ignore it. :)
+ RetTy VisitOMPClause(PTR(OMPClause) Node) { return RetTy(); }
+#undef PTR
+#undef DISPATCH
+};
+
+template <typename T>
+using const_ptr = typename std::add_pointer<typename std::add_const<T>::type>;
+
+template<class ImplClass, typename RetTy = void>
+class OMPClauseVisitor :
+ public OMPClauseVisitorBase <ImplClass, std::add_pointer, RetTy> {};
+template<class ImplClass, typename RetTy = void>
+class ConstOMPClauseVisitor :
+ public OMPClauseVisitorBase <ImplClass, const_ptr, RetTy> {};
+
+class OMPClausePrinter final : public OMPClauseVisitor<OMPClausePrinter> {
+ raw_ostream &OS;
+ const PrintingPolicy &Policy;
+
+ /// Process clauses with list of variables.
+ template <typename T> void VisitOMPClauseList(T *Node, char StartSym);
+
+public:
+ OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
+ : OS(OS), Policy(Policy) {}
+
+#define OPENMP_CLAUSE(Name, Class) void Visit##Class(Class *S);
+#include "clang/Basic/OpenMPKinds.def"
+};
+
} // namespace clang
#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
diff --git a/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def
index e2d65d84880c..cd19091e31d6 100644
--- a/include/clang/AST/OperationKinds.def
+++ b/include/clang/AST/OperationKinds.def
@@ -197,6 +197,14 @@ CAST_OPERATION(IntegralToBoolean)
/// float f = i;
CAST_OPERATION(IntegralToFloating)
+/// CK_FixedPointCast - Fixed point to fixed point.
+/// (_Accum) 0.5r
+CAST_OPERATION(FixedPointCast)
+
+/// CK_FixedPointToBoolean - Fixed point to boolean.
+/// (bool) 0.5r
+CAST_OPERATION(FixedPointToBoolean)
+
/// CK_FloatingToIntegral - Floating point to integral. Rounds
/// towards zero, discarding any fractional component.
/// (int) f
@@ -318,11 +326,9 @@ CAST_OPERATION(CopyAndAutoreleaseBlockObject)
// callee of a call expression.
CAST_OPERATION(BuiltinFnToFnPtr)
-// Convert a zero value for OpenCL event_t initialization.
-CAST_OPERATION(ZeroToOCLEvent)
-
-// Convert a zero value for OpenCL queue_t initialization.
-CAST_OPERATION(ZeroToOCLQueue)
+// Convert a zero value for OpenCL opaque types initialization (event_t,
+// queue_t, etc.)
+CAST_OPERATION(ZeroToOCLOpaqueType)
// Convert a pointer to a different address space.
CAST_OPERATION(AddressSpaceConversion)
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index b49f5be1b1e6..3c877f5ea19c 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -38,21 +38,20 @@ public:
struct PrintingPolicy {
/// Create a default printing policy for the specified language.
PrintingPolicy(const LangOptions &LO)
- : Indentation(2), SuppressSpecifiers(false),
- SuppressTagKeyword(LO.CPlusPlus),
- IncludeTagDefinition(false), SuppressScope(false),
- SuppressUnwrittenScope(false), SuppressInitializers(false),
- ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
- SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
- SuppressTemplateArgsInCXXConstructors(false),
- Bool(LO.Bool), Restrict(LO.C99),
- Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11),
- UseVoidForZeroParams(!LO.CPlusPlus),
- TerseOutput(false), PolishForDeclaration(false),
- Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
- IncludeNewlines(true), MSVCFormatting(false),
- ConstantsAsWritten(false), SuppressImplicitBase(false),
- FullyQualifiedName(false) { }
+ : Indentation(2), SuppressSpecifiers(false),
+ SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
+ SuppressScope(false), SuppressUnwrittenScope(false),
+ SuppressInitializers(false), ConstantArraySizeAsWritten(false),
+ AnonymousTagLocations(true), SuppressStrongLifetime(false),
+ SuppressLifetimeQualifiers(false),
+ SuppressTemplateArgsInCXXConstructors(false), Bool(LO.Bool),
+ Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11),
+ UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false),
+ PolishForDeclaration(false), Half(LO.Half),
+ MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
+ MSVCFormatting(false), ConstantsAsWritten(false),
+ SuppressImplicitBase(false), FullyQualifiedName(false),
+ RemapFilePaths(false), PrintCanonicalTypes(false) {}
/// Adjust this printing policy for cases where it's known that we're
/// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -81,7 +80,7 @@ struct PrintingPolicy {
/// declaration for "x", so that we will print "int *x"; it will be
/// \c true when we print "y", so that we suppress printing the
/// "const int" type specifier and instead only print the "*y".
- bool SuppressSpecifiers : 1;
+ unsigned SuppressSpecifiers : 1;
/// Whether type printing should skip printing the tag keyword.
///
@@ -91,7 +90,7 @@ struct PrintingPolicy {
/// \code
/// struct Geometry::Point;
/// \endcode
- bool SuppressTagKeyword : 1;
+ unsigned SuppressTagKeyword : 1;
/// When true, include the body of a tag definition.
///
@@ -101,14 +100,14 @@ struct PrintingPolicy {
/// \code
/// typedef struct { int x, y; } Point;
/// \endcode
- bool IncludeTagDefinition : 1;
+ unsigned IncludeTagDefinition : 1;
/// Suppresses printing of scope specifiers.
- bool SuppressScope : 1;
+ unsigned SuppressScope : 1;
/// Suppress printing parts of scope specifiers that don't need
/// to be written, e.g., for inline or anonymous namespaces.
- bool SuppressUnwrittenScope : 1;
+ unsigned SuppressUnwrittenScope : 1;
/// Suppress printing of variable initializers.
///
@@ -121,7 +120,7 @@ struct PrintingPolicy {
///
/// SuppressInitializers will be true when printing "auto x", so that the
/// internal initializer constructed for x will not be printed.
- bool SuppressInitializers : 1;
+ unsigned SuppressInitializers : 1;
/// Whether we should print the sizes of constant array expressions as written
/// in the sources.
@@ -139,12 +138,12 @@ struct PrintingPolicy {
/// int a[104];
/// char a[9] = "A string";
/// \endcode
- bool ConstantArraySizeAsWritten : 1;
+ unsigned ConstantArraySizeAsWritten : 1;
/// When printing an anonymous tag name, also print the location of that
/// entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just prints
/// "(anonymous)" for the name.
- bool AnonymousTagLocations : 1;
+ unsigned AnonymousTagLocations : 1;
/// When true, suppress printing of the __strong lifetime qualifier in ARC.
unsigned SuppressStrongLifetime : 1;
@@ -199,7 +198,7 @@ struct PrintingPolicy {
/// Use whitespace and punctuation like MSVC does. In particular, this prints
/// anonymous namespaces as `anonymous namespace' and does not insert spaces
/// after template arguments.
- bool MSVCFormatting : 1;
+ unsigned MSVCFormatting : 1;
/// Whether we should print the constant expressions as written in the
/// sources.
@@ -217,14 +216,23 @@ struct PrintingPolicy {
/// 0x10
/// 2.5e3
/// \endcode
- bool ConstantsAsWritten : 1;
+ unsigned ConstantsAsWritten : 1;
/// When true, don't print the implicit 'self' or 'this' expressions.
- bool SuppressImplicitBase : 1;
+ unsigned SuppressImplicitBase : 1;
/// When true, print the fully qualified name of function declarations.
/// This is the opposite of SuppressScope and thus overrules it.
- bool FullyQualifiedName : 1;
+ unsigned FullyQualifiedName : 1;
+
+ /// Whether to apply -fdebug-prefix-map to any file paths.
+ unsigned RemapFilePaths : 1;
+
+ /// Whether to print types as written or canonically.
+ unsigned PrintCanonicalTypes : 1;
+
+ /// When RemapFilePaths is true, this function performs the action.
+ std::function<std::string(StringRef)> remapPath;
};
} // end namespace clang
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index 8327efc750fd..d17c9df67e41 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/include/clang/AST/RawCommentList.h
@@ -101,8 +101,8 @@ public:
}
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
const char *getBriefText(const ASTContext &Context) const {
if (BriefTextValid)
@@ -180,7 +180,7 @@ public:
explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { }
bool operator()(const RawComment &LHS, const RawComment &RHS) {
- return SM.isBeforeInTranslationUnit(LHS.getLocStart(), RHS.getLocStart());
+ return SM.isBeforeInTranslationUnit(LHS.getBeginLoc(), RHS.getBeginLoc());
}
bool operator()(const RawComment *LHS, const RawComment *RHS) {
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 0d2b670507c1..44aba6355758 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -176,6 +176,16 @@ public:
/// Return whether this visitor should traverse post-order.
bool shouldTraversePostOrder() const { return false; }
+ /// Recursively visits an entire AST, starting from the top-level Decls
+ /// in the AST traversal scope (by default, the TranslationUnitDecl).
+ /// \returns false if visitation was terminated early.
+ bool TraverseAST(ASTContext &AST) {
+ for (Decl *D : AST.getTraversalScope())
+ if (!getDerived().TraverseDecl(D))
+ return false;
+ return true;
+ }
+
/// Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
///
@@ -288,14 +298,6 @@ public:
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
Expr *Init);
- /// Recursively visit the body of a lambda expression.
- ///
- /// This provides a hook for visitors that need more context when visiting
- /// \c LE->getBody().
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);
-
/// Recursively visit the syntactic or semantic form of an
/// initialization list.
///
@@ -926,13 +928,6 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
return true;
}
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(
- LambdaExpr *LE, DataRecursionQueue *Queue) {
- TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody());
- return true;
-}
-
// ----------------- Type traversal -----------------
// This macro makes available a variable T, the passed-in type.
@@ -1373,9 +1368,14 @@ DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
template <typename Derived>
bool RecursiveASTVisitor<Derived>::canIgnoreChildDeclWhileTraversingDeclContext(
const Decl *Child) {
- // BlockDecls and CapturedDecls are traversed through BlockExprs and
- // CapturedStmts respectively.
- return isa<BlockDecl>(Child) || isa<CapturedDecl>(Child);
+ // BlockDecls are traversed through BlockExprs,
+ // CapturedDecls are traversed through CapturedStmts.
+ if (isa<BlockDecl>(Child) || isa<CapturedDecl>(Child))
+ return true;
+ // Lambda classes are traversed through LambdaExprs.
+ if (const CXXRecordDecl* Cls = dyn_cast<CXXRecordDecl>(Child))
+ return Cls->isLambda();
+ return false;
}
template <typename Derived>
@@ -1589,6 +1589,12 @@ DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
for (auto *I : D->varlists()) {
TRY_TO(TraverseStmt(I));
}
+ })
+
+DEF_TRAVERSE_DECL(OMPRequiresDecl, {
+ for (auto *C : D->clauselists()) {
+ TRY_TO(TraverseOMPClause(C));
+ }
})
DEF_TRAVERSE_DECL(OMPDeclareReductionDecl, {
@@ -2174,6 +2180,8 @@ DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
DEF_TRAVERSE_STMT(CXXForRangeStmt, {
if (!getDerived().shouldVisitImplicitCode()) {
+ if (S->getInit())
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInit());
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt());
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit());
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
@@ -2191,6 +2199,8 @@ DEF_TRAVERSE_STMT(ReturnStmt, {})
DEF_TRAVERSE_STMT(SwitchStmt, {})
DEF_TRAVERSE_STMT(WhileStmt, {})
+DEF_TRAVERSE_STMT(ConstantExpr, {})
+
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
@@ -2384,6 +2394,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
// Walk only the visible parts of lambda expressions.
DEF_TRAVERSE_STMT(LambdaExpr, {
+ // Visit the capture list.
for (unsigned I = 0, N = S->capture_size(); I != N; ++I) {
const LambdaCapture *C = S->capture_begin() + I;
if (C->isExplicit() || getDerived().shouldVisitImplicitCode()) {
@@ -2391,32 +2402,31 @@ DEF_TRAVERSE_STMT(LambdaExpr, {
}
}
- TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
- FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
-
- if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
- // Visit the whole type.
- TRY_TO(TraverseTypeLoc(TL));
+ if (getDerived().shouldVisitImplicitCode()) {
+ // The implicit model is simple: everything else is in the lambda class.
+ TRY_TO(TraverseDecl(S->getLambdaClass()));
} else {
+ // We need to poke around to find the bits that might be explicitly written.
+ TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
+
if (S->hasExplicitParameters()) {
// Visit parameters.
- for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I)
TRY_TO(TraverseDecl(Proto.getParam(I)));
- }
- } else if (S->hasExplicitResultType()) {
- TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
}
+ if (S->hasExplicitResultType())
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
auto *T = Proto.getTypePtr();
- for (const auto &E : T->exceptions()) {
+ for (const auto &E : T->exceptions())
TRY_TO(TraverseType(E));
- }
if (Expr *NE = T->getNoexceptExpr())
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
- }
- ReturnValue = TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue);
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
+ }
ShouldVisitChildren = false;
})
@@ -2854,6 +2864,36 @@ bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPUnifiedAddressClause(
+ OMPUnifiedAddressClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPUnifiedSharedMemoryClause(
+ OMPUnifiedSharedMemoryClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPReverseOffloadClause(
+ OMPReverseOffloadClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDynamicAllocatorsClause(
+ OMPDynamicAllocatorsClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPAtomicDefaultMemOrderClause(
+ OMPAtomicDefaultMemOrderClause *) {
+ return true;
+}
+
+template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
TRY_TO(VisitOMPClauseWithPreInit(C));
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index aa0f88b71023..ff5baa21adff 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -89,6 +89,8 @@ protected:
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
}
+ //===--- Statement bitfields classes ---===//
+
class StmtBitfields {
friend class Stmt;
@@ -97,22 +99,186 @@ protected:
};
enum { NumStmtBits = 8 };
+ class NullStmtBitfields {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend class NullStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if the null statement was preceded by an empty macro, e.g:
+ /// @code
+ /// #define CALL(x)
+ /// CALL(0);
+ /// @endcode
+ unsigned HasLeadingEmptyMacro : 1;
+
+ /// The location of the semi-colon.
+ SourceLocation SemiLoc;
+ };
+
class CompoundStmtBitfields {
+ friend class ASTStmtReader;
friend class CompoundStmt;
unsigned : NumStmtBits;
unsigned NumStmts : 32 - NumStmtBits;
+
+ /// The location of the opening "{".
+ SourceLocation LBraceLoc;
+ };
+
+ class LabelStmtBitfields {
+ friend class LabelStmt;
+
+ unsigned : NumStmtBits;
+
+ SourceLocation IdentLoc;
+ };
+
+ class AttributedStmtBitfields {
+ friend class ASTStmtReader;
+ friend class AttributedStmt;
+
+ unsigned : NumStmtBits;
+
+ /// Number of attributes.
+ unsigned NumAttrs : 32 - NumStmtBits;
+
+ /// The location of the attribute.
+ SourceLocation AttrLoc;
};
class IfStmtBitfields {
+ friend class ASTStmtReader;
friend class IfStmt;
unsigned : NumStmtBits;
+ /// True if this if statement is a constexpr if.
unsigned IsConstexpr : 1;
+
+ /// True if this if statement has storage for an else statement.
+ unsigned HasElse : 1;
+
+ /// True if this if statement has storage for a variable declaration.
+ unsigned HasVar : 1;
+
+ /// True if this if statement has storage for an init statement.
+ unsigned HasInit : 1;
+
+ /// The location of the "if".
+ SourceLocation IfLoc;
+ };
+
+ class SwitchStmtBitfields {
+ friend class SwitchStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if the SwitchStmt has storage for an init statement.
+ unsigned HasInit : 1;
+
+ /// True if the SwitchStmt has storage for a condition variable.
+ unsigned HasVar : 1;
+
+ /// If the SwitchStmt is a switch on an enum value, records whether all
+ /// the enum values were covered by CaseStmts. The coverage information
+ /// value is meant to be a hint for possible clients.
+ unsigned AllEnumCasesCovered : 1;
+
+ /// The location of the "switch".
+ SourceLocation SwitchLoc;
+ };
+
+ class WhileStmtBitfields {
+ friend class ASTStmtReader;
+ friend class WhileStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if the WhileStmt has storage for a condition variable.
+ unsigned HasVar : 1;
+
+ /// The location of the "while".
+ SourceLocation WhileLoc;
+ };
+
+ class DoStmtBitfields {
+ friend class DoStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "do".
+ SourceLocation DoLoc;
+ };
+
+ class ForStmtBitfields {
+ friend class ForStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "for".
+ SourceLocation ForLoc;
+ };
+
+ class GotoStmtBitfields {
+ friend class GotoStmt;
+ friend class IndirectGotoStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "goto".
+ SourceLocation GotoLoc;
+ };
+
+ class ContinueStmtBitfields {
+ friend class ContinueStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "continue".
+ SourceLocation ContinueLoc;
+ };
+
+ class BreakStmtBitfields {
+ friend class BreakStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "break".
+ SourceLocation BreakLoc;
+ };
+
+ class ReturnStmtBitfields {
+ friend class ReturnStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if this ReturnStmt has storage for an NRVO candidate.
+ unsigned HasNRVOCandidate : 1;
+
+ /// The location of the "return".
+ SourceLocation RetLoc;
+ };
+
+ class SwitchCaseBitfields {
+ friend class SwitchCase;
+ friend class CaseStmt;
+
+ unsigned : NumStmtBits;
+
+ /// Used by CaseStmt to store whether it is a case statement
+ /// of the form case LHS ... RHS (a GNU extension).
+ unsigned CaseStmtIsGNURange : 1;
+
+ /// The location of the "case" or "default" keyword.
+ SourceLocation KeywordLoc;
};
+ //===--- Expression bitfields classes ---===//
+
class ExprBitfields {
friend class ASTStmtReader; // deserialization
friend class AtomicExpr; // ctor
@@ -146,14 +312,40 @@ protected:
unsigned InstantiationDependent : 1;
unsigned ContainsUnexpandedParameterPack : 1;
};
- enum { NumExprBits = 17 };
+ enum { NumExprBits = NumStmtBits + 9 };
- class CharacterLiteralBitfields {
- friend class CharacterLiteral;
+ class PredefinedExprBitfields {
+ friend class ASTStmtReader;
+ friend class PredefinedExpr;
unsigned : NumExprBits;
- unsigned Kind : 3;
+ /// The kind of this PredefinedExpr. One of the enumeration values
+ /// in PredefinedExpr::IdentKind.
+ unsigned Kind : 4;
+
+ /// True if this PredefinedExpr has a trailing "StringLiteral *"
+ /// for the predefined identifier.
+ unsigned HasFunctionName : 1;
+
+ /// The location of this PredefinedExpr.
+ SourceLocation Loc;
+ };
+
+ class DeclRefExprBitfields {
+ friend class ASTStmtReader; // deserialization
+ friend class DeclRefExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned HasQualifier : 1;
+ unsigned HasTemplateKWAndArgsInfo : 1;
+ unsigned HasFoundDecl : 1;
+ unsigned HadMultipleCandidates : 1;
+ unsigned RefersToEnclosingVariableOrCapture : 1;
+
+ /// The location of the declaration name itself.
+ SourceLocation Loc;
};
enum APFloatSemantics {
@@ -174,26 +366,111 @@ protected:
unsigned IsExact : 1;
};
+ class StringLiteralBitfields {
+ friend class ASTStmtReader;
+ friend class StringLiteral;
+
+ unsigned : NumExprBits;
+
+ /// The kind of this string literal.
+ /// One of the enumeration values of StringLiteral::StringKind.
+ unsigned Kind : 3;
+
+ /// The width of a single character in bytes. Only values of 1, 2,
+ /// and 4 bytes are supported. StringLiteral::mapCharByteWidth maps
+ /// the target + string kind to the appropriate CharByteWidth.
+ unsigned CharByteWidth : 3;
+
+ unsigned IsPascal : 1;
+
+ /// The number of concatenated token this string is made of.
+ /// This is the number of trailing SourceLocation.
+ unsigned NumConcatenated;
+ };
+
+ class CharacterLiteralBitfields {
+ friend class CharacterLiteral;
+
+ unsigned : NumExprBits;
+
+ unsigned Kind : 3;
+ };
+
+ class UnaryOperatorBitfields {
+ friend class UnaryOperator;
+
+ unsigned : NumExprBits;
+
+ unsigned Opc : 5;
+ unsigned CanOverflow : 1;
+
+ SourceLocation Loc;
+ };
+
class UnaryExprOrTypeTraitExprBitfields {
friend class UnaryExprOrTypeTraitExpr;
unsigned : NumExprBits;
- unsigned Kind : 2;
+ unsigned Kind : 3;
unsigned IsType : 1; // true if operand is a type, false if an expression.
};
- class DeclRefExprBitfields {
- friend class ASTStmtReader; // deserialization
- friend class DeclRefExpr;
+ class ArraySubscriptExprBitfields {
+ friend class ArraySubscriptExpr;
unsigned : NumExprBits;
- unsigned HasQualifier : 1;
+ SourceLocation RBracketLoc;
+ };
+
+ class CallExprBitfields {
+ friend class CallExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned NumPreArgs : 1;
+
+ /// True if the callee of the call expression was found using ADL.
+ unsigned UsesADL : 1;
+
+ /// Padding used to align OffsetToTrailingObjects to a byte multiple.
+ unsigned : 24 - 2 - NumExprBits;
+
+ /// The offset in bytes from the this pointer to the start of the
+ /// trailing objects belonging to CallExpr. Intentionally byte sized
+ /// for faster access.
+ unsigned OffsetToTrailingObjects : 8;
+ };
+ enum { NumCallExprBits = 32 };
+
+ class MemberExprBitfields {
+ friend class MemberExpr;
+
+ unsigned : NumExprBits;
+
+ /// IsArrow - True if this is "X->F", false if this is "X.F".
+ unsigned IsArrow : 1;
+
+ /// True if this member expression used a nested-name-specifier to
+ /// refer to the member, e.g., "x->Base::f", or found its member via
+ /// a using declaration. When true, a MemberExprNameQualifier
+ /// structure is allocated immediately after the MemberExpr.
+ unsigned HasQualifierOrFoundDecl : 1;
+
+ /// True if this member expression specified a template keyword
+ /// and/or a template argument list explicitly, e.g., x->f<int>,
+ /// x->template f, x->template f<int>.
+ /// When true, an ASTTemplateKWAndArgsInfo structure and its
+ /// TemplateArguments (if any) are present.
unsigned HasTemplateKWAndArgsInfo : 1;
- unsigned HasFoundDecl : 1;
+
+ /// True if this member expression refers to a method that
+ /// was resolved from an overloaded set having size greater than 1.
unsigned HadMultipleCandidates : 1;
- unsigned RefersToEnclosingVariableOrCapture : 1;
+
+ /// This is the location of the -> or . in the expression.
+ SourceLocation OperatorLoc;
};
class CastExprBitfields {
@@ -204,27 +481,44 @@ protected:
unsigned Kind : 6;
unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr.
- unsigned BasePathIsEmpty : 1;
+
+ /// The number of CXXBaseSpecifiers in the cast. 14 bits would be enough
+ /// here. ([implimits] Direct and indirect base classes [16384]).
+ unsigned BasePathSize;
};
- class CallExprBitfields {
- friend class CallExpr;
+ class BinaryOperatorBitfields {
+ friend class BinaryOperator;
unsigned : NumExprBits;
- unsigned NumPreArgs : 1;
+ unsigned Opc : 6;
+
+ /// This is only meaningful for operations on floating point
+ /// types and 0 otherwise.
+ unsigned FPFeatures : 3;
+
+ SourceLocation OpLoc;
};
- class ExprWithCleanupsBitfields {
- friend class ASTStmtReader; // deserialization
- friend class ExprWithCleanups;
+ class InitListExprBitfields {
+ friend class InitListExpr;
unsigned : NumExprBits;
- // When false, it must not have side effects.
- unsigned CleanupsHaveSideEffects : 1;
+ /// Whether this initializer list originally had a GNU array-range
+ /// designator in it. This is a temporary marker used by CodeGen.
+ unsigned HadArrayRangeDesignator : 1;
+ };
- unsigned NumObjects : 32 - 1 - NumExprBits;
+ class ParenListExprBitfields {
+ friend class ASTStmtReader;
+ friend class ParenListExpr;
+
+ unsigned : NumExprBits;
+
+ /// The number of expressions in the paren list.
+ unsigned NumExprs;
};
class PseudoObjectExprBitfields {
@@ -239,32 +533,153 @@ protected:
unsigned ResultIndex : 32 - 8 - NumExprBits;
};
- class OpaqueValueExprBitfields {
- friend class OpaqueValueExpr;
+ //===--- C++ Expression bitfields classes ---===//
+
+ class CXXOperatorCallExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXOperatorCallExpr;
+
+ unsigned : NumCallExprBits;
+
+ /// The kind of this overloaded operator. One of the enumerator
+ /// value of OverloadedOperatorKind.
+ unsigned OperatorKind : 6;
+
+ // Only meaningful for floating point types.
+ unsigned FPFeatures : 3;
+ };
+
+ class CXXBoolLiteralExprBitfields {
+ friend class CXXBoolLiteralExpr;
unsigned : NumExprBits;
- /// The OVE is a unique semantic reference to its source expressio if this
- /// bit is set to true.
- unsigned IsUnique : 1;
+ /// The value of the boolean literal.
+ unsigned Value : 1;
+
+ /// The location of the boolean literal.
+ SourceLocation Loc;
};
- class ObjCIndirectCopyRestoreExprBitfields {
- friend class ObjCIndirectCopyRestoreExpr;
+ class CXXNullPtrLiteralExprBitfields {
+ friend class CXXNullPtrLiteralExpr;
unsigned : NumExprBits;
- unsigned ShouldCopy : 1;
+ /// The location of the null pointer literal.
+ SourceLocation Loc;
};
- class InitListExprBitfields {
- friend class InitListExpr;
+ class CXXThisExprBitfields {
+ friend class CXXThisExpr;
unsigned : NumExprBits;
- /// Whether this initializer list originally had a GNU array-range
- /// designator in it. This is a temporary marker used by CodeGen.
- unsigned HadArrayRangeDesignator : 1;
+ /// Whether this is an implicit "this".
+ unsigned IsImplicit : 1;
+
+ /// The location of the "this".
+ SourceLocation Loc;
+ };
+
+ class CXXThrowExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXThrowExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether the thrown variable (if any) is in scope.
+ unsigned IsThrownVariableInScope : 1;
+
+ /// The location of the "throw".
+ SourceLocation ThrowLoc;
+ };
+
+ class CXXDefaultArgExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDefaultArgExpr;
+
+ unsigned : NumExprBits;
+
+ /// The location where the default argument expression was used.
+ SourceLocation Loc;
+ };
+
+ class CXXDefaultInitExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDefaultInitExpr;
+
+ unsigned : NumExprBits;
+
+ /// The location where the default initializer expression was used.
+ SourceLocation Loc;
+ };
+
+ class CXXScalarValueInitExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXScalarValueInitExpr;
+
+ unsigned : NumExprBits;
+
+ SourceLocation RParenLoc;
+ };
+
+ class CXXNewExprBitfields {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend class CXXNewExpr;
+
+ unsigned : NumExprBits;
+
+ /// Was the usage ::new, i.e. is the global new to be used?
+ unsigned IsGlobalNew : 1;
+
+ /// Do we allocate an array? If so, the first trailing "Stmt *" is the
+ /// size expression.
+ unsigned IsArray : 1;
+
+ /// Should the alignment be passed to the allocation function?
+ unsigned ShouldPassAlignment : 1;
+
+ /// If this is an array allocation, does the usual deallocation
+ /// function for the allocated type want to know the allocated size?
+ unsigned UsualArrayDeleteWantsSize : 1;
+
+ /// What kind of initializer do we have? Could be none, parens, or braces.
+ /// In storage, we distinguish between "none, and no initializer expr", and
+ /// "none, but an implicit initializer expr".
+ unsigned StoredInitializationStyle : 2;
+
+ /// True if the allocated type was expressed as a parenthesized type-id.
+ unsigned IsParenTypeId : 1;
+
+ /// The number of placement new arguments.
+ unsigned NumPlacementArgs;
+ };
+
+ class CXXDeleteExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDeleteExpr;
+
+ unsigned : NumExprBits;
+
+ /// Is this a forced global delete, i.e. "::delete"?
+ unsigned GlobalDelete : 1;
+
+ /// Is this the array form of delete, i.e. "delete[]"?
+ unsigned ArrayForm : 1;
+
+ /// ArrayFormAsWritten can be different from ArrayForm if 'delete' is
+ /// applied to pointer-to-array type (ArrayFormAsWritten will be false
+ /// while ArrayForm will be true).
+ unsigned ArrayFormAsWritten : 1;
+
+ /// Does the usual deallocation function for the element type require
+ /// a size_t argument?
+ unsigned UsualArrayDeleteWantsSize : 1;
+
+ /// Location of the expression.
+ SourceLocation Loc;
};
class TypeTraitExprBitfields {
@@ -285,6 +700,154 @@ protected:
unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
};
+ class DependentScopeDeclRefExprBitfields {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend class DependentScopeDeclRefExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether the name includes info for explicit template
+ /// keyword and arguments.
+ unsigned HasTemplateKWAndArgsInfo : 1;
+ };
+
+ class CXXConstructExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXConstructExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned Elidable : 1;
+ unsigned HadMultipleCandidates : 1;
+ unsigned ListInitialization : 1;
+ unsigned StdInitListInitialization : 1;
+ unsigned ZeroInitialization : 1;
+ unsigned ConstructionKind : 3;
+
+ SourceLocation Loc;
+ };
+
+ class ExprWithCleanupsBitfields {
+ friend class ASTStmtReader; // deserialization
+ friend class ExprWithCleanups;
+
+ unsigned : NumExprBits;
+
+ // When false, it must not have side effects.
+ unsigned CleanupsHaveSideEffects : 1;
+
+ unsigned NumObjects : 32 - 1 - NumExprBits;
+ };
+
+ class CXXUnresolvedConstructExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXUnresolvedConstructExpr;
+
+ unsigned : NumExprBits;
+
+ /// The number of arguments used to construct the type.
+ unsigned NumArgs;
+ };
+
+ class CXXDependentScopeMemberExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDependentScopeMemberExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ unsigned IsArrow : 1;
+
+ /// Whether this member expression has info for explicit template
+ /// keyword and arguments.
+ unsigned HasTemplateKWAndArgsInfo : 1;
+
+ /// See getFirstQualifierFoundInScope() and the comment listing
+ /// the trailing objects.
+ unsigned HasFirstQualifierFoundInScope : 1;
+
+ /// The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+ };
+
+ class OverloadExprBitfields {
+ friend class ASTStmtReader;
+ friend class OverloadExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether the name includes info for explicit template
+ /// keyword and arguments.
+ unsigned HasTemplateKWAndArgsInfo : 1;
+
+ /// Padding used by the derived classes to store various bits. If you
+ /// need to add some data here, shrink this padding and add your data
+ /// above. NumOverloadExprBits also needs to be updated.
+ unsigned : 32 - NumExprBits - 1;
+
+ /// The number of results.
+ unsigned NumResults;
+ };
+ enum { NumOverloadExprBits = NumExprBits + 1 };
+
+ class UnresolvedLookupExprBitfields {
+ friend class ASTStmtReader;
+ friend class UnresolvedLookupExpr;
+
+ unsigned : NumOverloadExprBits;
+
+ /// True if these lookup results should be extended by
+ /// argument-dependent lookup if this is the operand of a function call.
+ unsigned RequiresADL : 1;
+
+ /// True if these lookup results are overloaded. This is pretty trivially
+ /// rederivable if we urgently need to kill this field.
+ unsigned Overloaded : 1;
+ };
+ static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4,
+ "UnresolvedLookupExprBitfields must be <= than 4 bytes to"
+ "avoid trashing OverloadExprBitfields::NumResults!");
+
+ class UnresolvedMemberExprBitfields {
+ friend class ASTStmtReader;
+ friend class UnresolvedMemberExpr;
+
+ unsigned : NumOverloadExprBits;
+
+ /// Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ unsigned IsArrow : 1;
+
+ /// Whether the lookup results contain an unresolved using declaration.
+ unsigned HasUnresolvedUsing : 1;
+ };
+ static_assert(sizeof(UnresolvedMemberExprBitfields) <= 4,
+ "UnresolvedMemberExprBitfields must be <= than 4 bytes to"
+ "avoid trashing OverloadExprBitfields::NumResults!");
+
+ class CXXNoexceptExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXNoexceptExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned Value : 1;
+ };
+
+ class SubstNonTypeTemplateParmExprBitfields {
+ friend class ASTStmtReader;
+ friend class SubstNonTypeTemplateParmExpr;
+
+ unsigned : NumExprBits;
+
+ /// The location of the non-type template parameter reference.
+ SourceLocation NameLoc;
+ };
+
+ //===--- C++ Coroutines TS bitfields classes ---===//
+
class CoawaitExprBitfields {
friend class CoawaitExpr;
@@ -293,24 +856,99 @@ protected:
unsigned IsImplicit : 1;
};
+ //===--- Obj-C Expression bitfields classes ---===//
+
+ class ObjCIndirectCopyRestoreExprBitfields {
+ friend class ObjCIndirectCopyRestoreExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned ShouldCopy : 1;
+ };
+
+ //===--- Clang Extensions bitfields classes ---===//
+
+ class OpaqueValueExprBitfields {
+ friend class ASTStmtReader;
+ friend class OpaqueValueExpr;
+
+ unsigned : NumExprBits;
+
+ /// The OVE is a unique semantic reference to its source expression if this
+ /// bit is set to true.
+ unsigned IsUnique : 1;
+
+ SourceLocation Loc;
+ };
+
union {
+ // Same order as in StmtNodes.td.
+ // Statements
StmtBitfields StmtBits;
+ NullStmtBitfields NullStmtBits;
CompoundStmtBitfields CompoundStmtBits;
+ LabelStmtBitfields LabelStmtBits;
+ AttributedStmtBitfields AttributedStmtBits;
IfStmtBitfields IfStmtBits;
+ SwitchStmtBitfields SwitchStmtBits;
+ WhileStmtBitfields WhileStmtBits;
+ DoStmtBitfields DoStmtBits;
+ ForStmtBitfields ForStmtBits;
+ GotoStmtBitfields GotoStmtBits;
+ ContinueStmtBitfields ContinueStmtBits;
+ BreakStmtBitfields BreakStmtBits;
+ ReturnStmtBitfields ReturnStmtBits;
+ SwitchCaseBitfields SwitchCaseBits;
+
+ // Expressions
ExprBitfields ExprBits;
- CharacterLiteralBitfields CharacterLiteralBits;
+ PredefinedExprBitfields PredefinedExprBits;
+ DeclRefExprBitfields DeclRefExprBits;
FloatingLiteralBitfields FloatingLiteralBits;
+ StringLiteralBitfields StringLiteralBits;
+ CharacterLiteralBitfields CharacterLiteralBits;
+ UnaryOperatorBitfields UnaryOperatorBits;
UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits;
- DeclRefExprBitfields DeclRefExprBits;
- CastExprBitfields CastExprBits;
+ ArraySubscriptExprBitfields ArraySubscriptExprBits;
CallExprBitfields CallExprBits;
- ExprWithCleanupsBitfields ExprWithCleanupsBits;
- PseudoObjectExprBitfields PseudoObjectExprBits;
- OpaqueValueExprBitfields OpaqueValueExprBits;
- ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
+ MemberExprBitfields MemberExprBits;
+ CastExprBitfields CastExprBits;
+ BinaryOperatorBitfields BinaryOperatorBits;
InitListExprBitfields InitListExprBits;
+ ParenListExprBitfields ParenListExprBits;
+ PseudoObjectExprBitfields PseudoObjectExprBits;
+
+ // C++ Expressions
+ CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
+ CXXBoolLiteralExprBitfields CXXBoolLiteralExprBits;
+ CXXNullPtrLiteralExprBitfields CXXNullPtrLiteralExprBits;
+ CXXThisExprBitfields CXXThisExprBits;
+ CXXThrowExprBitfields CXXThrowExprBits;
+ CXXDefaultArgExprBitfields CXXDefaultArgExprBits;
+ CXXDefaultInitExprBitfields CXXDefaultInitExprBits;
+ CXXScalarValueInitExprBitfields CXXScalarValueInitExprBits;
+ CXXNewExprBitfields CXXNewExprBits;
+ CXXDeleteExprBitfields CXXDeleteExprBits;
TypeTraitExprBitfields TypeTraitExprBits;
+ DependentScopeDeclRefExprBitfields DependentScopeDeclRefExprBits;
+ CXXConstructExprBitfields CXXConstructExprBits;
+ ExprWithCleanupsBitfields ExprWithCleanupsBits;
+ CXXUnresolvedConstructExprBitfields CXXUnresolvedConstructExprBits;
+ CXXDependentScopeMemberExprBitfields CXXDependentScopeMemberExprBits;
+ OverloadExprBitfields OverloadExprBits;
+ UnresolvedLookupExprBitfields UnresolvedLookupExprBits;
+ UnresolvedMemberExprBitfields UnresolvedMemberExprBits;
+ CXXNoexceptExprBitfields CXXNoexceptExprBits;
+ SubstNonTypeTemplateParmExprBitfields SubstNonTypeTemplateParmExprBits;
+
+ // C++ Coroutines TS expressions
CoawaitExprBitfields CoawaitBits;
+
+ // Obj-C Expressions
+ ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
+
+ // Clang Extensions
+ OpaqueValueExprBitfields OpaqueValueExprBits;
};
public:
@@ -380,7 +1018,7 @@ protected:
public:
Stmt(StmtClass SC) {
- static_assert(sizeof(*this) == sizeof(void *),
+ static_assert(sizeof(*this) <= 8,
"changing bitfields changed sizeof(Stmt)");
static_assert(sizeof(*this) % alignof(void *) == 0,
"Insufficient alignment!");
@@ -398,8 +1036,8 @@ public:
/// value objects created/interpreted by SourceManager. We assume AST
/// clients will have a pointer to the respective SourceManager.
SourceRange getSourceRange() const LLVM_READONLY;
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
// global temp stats (until we have a per-module visitor)
static void addStmtClass(const StmtClass s);
@@ -413,6 +1051,9 @@ public:
void dump(raw_ostream &OS, SourceManager &SM) const;
void dump(raw_ostream &OS) const;
+ /// \return Unique reproducible object identifier
+ int64_t getID(const ASTContext &Context) const;
+
/// dumpColor - same as dump(), but forces color highlighting.
void dumpColor() const;
@@ -421,6 +1062,7 @@ public:
void dumpPretty(const ASTContext &Context) const;
void printPretty(raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy, unsigned Indentation = 0,
+ StringRef NewlineSymbol = "\n",
const ASTContext *Context = nullptr) const;
/// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
@@ -511,9 +1153,7 @@ public:
/// isSingleDecl - This method returns true if this DeclStmt refers
/// to a single Decl.
- bool isSingleDecl() const {
- return DG.isSingleDecl();
- }
+ bool isSingleDecl() const { return DG.isSingleDecl(); }
const Decl *getSingleDecl() const { return DG.getSingleDecl(); }
Decl *getSingleDecl() { return DG.getSingleDecl(); }
@@ -522,13 +1162,11 @@ public:
DeclGroupRef getDeclGroup() { return DG; }
void setDeclGroup(DeclGroupRef DGR) { DG = DGR; }
- SourceLocation getStartLoc() const { return StartLoc; }
void setStartLoc(SourceLocation L) { StartLoc = L; }
SourceLocation getEndLoc() const { return EndLoc; }
void setEndLoc(SourceLocation L) { EndLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return StartLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return StartLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclStmtClass;
@@ -570,33 +1208,25 @@ public:
/// NullStmt - This is the null statement ";": C99 6.8.3p3.
///
class NullStmt : public Stmt {
- SourceLocation SemiLoc;
-
- /// True if the null statement was preceded by an empty macro, e.g:
- /// @code
- /// #define CALL(x)
- /// CALL(0);
- /// @endcode
- bool HasLeadingEmptyMacro = false;
-
public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false)
- : Stmt(NullStmtClass), SemiLoc(L),
- HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}
+ : Stmt(NullStmtClass) {
+ NullStmtBits.HasLeadingEmptyMacro = hasLeadingEmptyMacro;
+ setSemiLoc(L);
+ }
/// Build an empty null statement.
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {}
- SourceLocation getSemiLoc() const { return SemiLoc; }
- void setSemiLoc(SourceLocation L) { SemiLoc = L; }
+ SourceLocation getSemiLoc() const { return NullStmtBits.SemiLoc; }
+ void setSemiLoc(SourceLocation L) { NullStmtBits.SemiLoc = L; }
- bool hasLeadingEmptyMacro() const { return HasLeadingEmptyMacro; }
+ bool hasLeadingEmptyMacro() const {
+ return NullStmtBits.HasLeadingEmptyMacro;
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return SemiLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SemiLoc; }
+ SourceLocation getBeginLoc() const { return getSemiLoc(); }
+ SourceLocation getEndLoc() const { return getSemiLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == NullStmtClass;
@@ -613,7 +1243,8 @@ class CompoundStmt final : public Stmt,
friend class ASTStmtReader;
friend TrailingObjects;
- SourceLocation LBraceLoc, RBraceLoc;
+ /// The location of the closing "}". LBraceLoc is stored in CompoundStmtBits.
+ SourceLocation RBraceLoc;
CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, SourceLocation RB);
explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) {}
@@ -626,8 +1257,9 @@ public:
// Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
- : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) {
+ : Stmt(CompoundStmtClass), RBraceLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
+ CompoundStmtBits.LBraceLoc = Loc;
}
// Build an empty compound statement.
@@ -653,7 +1285,7 @@ public:
body_begin()[size() - 1] = S;
}
- using const_body_iterator = Stmt* const *;
+ using const_body_iterator = Stmt *const *;
using body_const_range = llvm::iterator_range<const_body_iterator>;
body_const_range body() const {
@@ -695,10 +1327,10 @@ public:
return const_reverse_body_iterator(body_begin());
}
- SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; }
+ SourceLocation getBeginLoc() const { return CompoundStmtBits.LBraceLoc; }
+ SourceLocation getEndLoc() const { return RBraceLoc; }
- SourceLocation getLBracLoc() const { return LBraceLoc; }
+ SourceLocation getLBracLoc() const { return CompoundStmtBits.LBraceLoc; }
SourceLocation getRBracLoc() const { return RBraceLoc; }
static bool classof(const Stmt *T) {
@@ -716,36 +1348,40 @@ public:
// SwitchCase is the base class for CaseStmt and DefaultStmt,
class SwitchCase : public Stmt {
protected:
- // A pointer to the following CaseStmt or DefaultStmt class,
- // used by SwitchStmt.
- SwitchCase *NextSwitchCase = nullptr;
- SourceLocation KeywordLoc;
+ /// The location of the ":".
SourceLocation ColonLoc;
+ // The location of the "case" or "default" keyword. Stored in SwitchCaseBits.
+ // SourceLocation KeywordLoc;
+
+ /// A pointer to the following CaseStmt or DefaultStmt class,
+ /// used by SwitchStmt.
+ SwitchCase *NextSwitchCase = nullptr;
+
SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc)
- : Stmt(SC), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {}
+ : Stmt(SC), ColonLoc(ColonLoc) {
+ setKeywordLoc(KWLoc);
+ }
SwitchCase(StmtClass SC, EmptyShell) : Stmt(SC) {}
public:
const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
-
SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
-
void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
- SourceLocation getKeywordLoc() const { return KeywordLoc; }
- void setKeywordLoc(SourceLocation L) { KeywordLoc = L; }
+ SourceLocation getKeywordLoc() const { return SwitchCaseBits.KeywordLoc; }
+ void setKeywordLoc(SourceLocation L) { SwitchCaseBits.KeywordLoc = L; }
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation L) { ColonLoc = L; }
- Stmt *getSubStmt();
+ inline Stmt *getSubStmt();
const Stmt *getSubStmt() const {
- return const_cast<SwitchCase*>(this)->getSubStmt();
+ return const_cast<SwitchCase *>(this)->getSubStmt();
}
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const { return getKeywordLoc(); }
+ inline SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CaseStmtClass ||
@@ -753,59 +1389,144 @@ public:
}
};
-class CaseStmt : public SwitchCase {
- SourceLocation EllipsisLoc;
- enum { LHS, RHS, SUBSTMT, END_EXPR };
- Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
- // GNU "case 1 ... 4" extension
+/// CaseStmt - Represent a case statement. It can optionally be a GNU case
+/// statement of the form LHS ... RHS representing a range of cases.
+class CaseStmt final
+ : public SwitchCase,
+ private llvm::TrailingObjects<CaseStmt, Stmt *, SourceLocation> {
+ friend TrailingObjects;
-public:
+ // CaseStmt is followed by several trailing objects, some of which optional.
+ // Note that it would be more convenient to put the optional trailing objects
+ // at the end but this would impact children().
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the LHS of the case statement. Always present.
+ //
+ // * A "Stmt *" for the RHS of the case statement. This is a GNU extension
+ // which allow ranges in cases statement of the form LHS ... RHS.
+ // Present if and only if caseStmtIsGNURange() is true.
+ //
+ // * A "Stmt *" for the substatement of the case statement. Always present.
+ //
+ // * A SourceLocation for the location of the ... if this is a case statement
+ // with a range. Present if and only if caseStmtIsGNURange() is true.
+ enum { LhsOffset = 0, SubStmtOffsetFromRhs = 1 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + caseStmtIsGNURange();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
+ return caseStmtIsGNURange();
+ }
+
+ unsigned lhsOffset() const { return LhsOffset; }
+ unsigned rhsOffset() const { return LhsOffset + caseStmtIsGNURange(); }
+ unsigned subStmtOffset() const { return rhsOffset() + SubStmtOffsetFromRhs; }
+
+ /// Build a case statement assuming that the storage for the
+ /// trailing objects has been properly allocated.
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
SourceLocation ellipsisLoc, SourceLocation colonLoc)
- : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
- SubExprs[SUBSTMT] = nullptr;
- SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
- SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
- EllipsisLoc = ellipsisLoc;
+ : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
+ // Handle GNU case statements of the form LHS ... RHS.
+ bool IsGNURange = rhs != nullptr;
+ SwitchCaseBits.CaseStmtIsGNURange = IsGNURange;
+ setLHS(lhs);
+ setSubStmt(nullptr);
+ if (IsGNURange) {
+ setRHS(rhs);
+ setEllipsisLoc(ellipsisLoc);
+ }
}
/// Build an empty switch case statement.
- explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {}
+ explicit CaseStmt(EmptyShell Empty, bool CaseStmtIsGNURange)
+ : SwitchCase(CaseStmtClass, Empty) {
+ SwitchCaseBits.CaseStmtIsGNURange = CaseStmtIsGNURange;
+ }
- SourceLocation getCaseLoc() const { return KeywordLoc; }
- void setCaseLoc(SourceLocation L) { KeywordLoc = L; }
- SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
- void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; }
- SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation L) { ColonLoc = L; }
+public:
+ /// Build a case statement.
+ static CaseStmt *Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
+ SourceLocation caseLoc, SourceLocation ellipsisLoc,
+ SourceLocation colonLoc);
+
+ /// Build an empty case statement.
+ static CaseStmt *CreateEmpty(const ASTContext &Ctx, bool CaseStmtIsGNURange);
+
+ /// True if this case statement is of the form case LHS ... RHS, which
+ /// is a GNU extension. In this case the RHS can be obtained with getRHS()
+ /// and the location of the ellipsis can be obtained with getEllipsisLoc().
+ bool caseStmtIsGNURange() const { return SwitchCaseBits.CaseStmtIsGNURange; }
+
+ SourceLocation getCaseLoc() const { return getKeywordLoc(); }
+ void setCaseLoc(SourceLocation L) { setKeywordLoc(L); }
+
+ /// Get the location of the ... in a case statement of the form LHS ... RHS.
+ SourceLocation getEllipsisLoc() const {
+ return caseStmtIsGNURange() ? *getTrailingObjects<SourceLocation>()
+ : SourceLocation();
+ }
- Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
- Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
- Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
+ /// Set the location of the ... in a case statement of the form LHS ... RHS.
+ /// Assert that this case statement is of this form.
+ void setEllipsisLoc(SourceLocation L) {
+ assert(
+ caseStmtIsGNURange() &&
+ "setEllipsisLoc but this is not a case stmt of the form LHS ... RHS!");
+ *getTrailingObjects<SourceLocation>() = L;
+ }
+
+ Expr *getLHS() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[lhsOffset()]);
+ }
const Expr *getLHS() const {
- return reinterpret_cast<const Expr*>(SubExprs[LHS]);
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[lhsOffset()]);
+ }
+
+ void setLHS(Expr *Val) {
+ getTrailingObjects<Stmt *>()[lhsOffset()] = reinterpret_cast<Stmt *>(Val);
+ }
+
+ Expr *getRHS() {
+ return caseStmtIsGNURange() ? reinterpret_cast<Expr *>(
+ getTrailingObjects<Stmt *>()[rhsOffset()])
+ : nullptr;
}
const Expr *getRHS() const {
- return reinterpret_cast<const Expr*>(SubExprs[RHS]);
+ return caseStmtIsGNURange() ? reinterpret_cast<Expr *>(
+ getTrailingObjects<Stmt *>()[rhsOffset()])
+ : nullptr;
}
- const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
+ void setRHS(Expr *Val) {
+ assert(caseStmtIsGNURange() &&
+ "setRHS but this is not a case stmt of the form LHS ... RHS!");
+ getTrailingObjects<Stmt *>()[rhsOffset()] = reinterpret_cast<Stmt *>(Val);
+ }
- void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
- void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
- void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
+ Stmt *getSubStmt() { return getTrailingObjects<Stmt *>()[subStmtOffset()]; }
+ const Stmt *getSubStmt() const {
+ return getTrailingObjects<Stmt *>()[subStmtOffset()];
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+ void setSubStmt(Stmt *S) {
+ getTrailingObjects<Stmt *>()[subStmtOffset()] = S;
+ }
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const { return getKeywordLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
// Handle deeply nested case statements with iteration instead of recursion.
const CaseStmt *CS = this;
while (const auto *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
CS = CS2;
- return CS->getSubStmt()->getLocEnd();
+ return CS->getSubStmt()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -814,16 +1535,18 @@ public:
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
};
class DefaultStmt : public SwitchCase {
- Stmt* SubStmt;
+ Stmt *SubStmt;
public:
- DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
- SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
+ DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt)
+ : SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
/// Build an empty default statement.
explicit DefaultStmt(EmptyShell Empty)
@@ -833,59 +1556,70 @@ public:
const Stmt *getSubStmt() const { return SubStmt; }
void setSubStmt(Stmt *S) { SubStmt = S; }
- SourceLocation getDefaultLoc() const { return KeywordLoc; }
- void setDefaultLoc(SourceLocation L) { KeywordLoc = L; }
- SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation L) { ColonLoc = L; }
+ SourceLocation getDefaultLoc() const { return getKeywordLoc(); }
+ void setDefaultLoc(SourceLocation L) { setKeywordLoc(L); }
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const { return getKeywordLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubStmt->getEndLoc();
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() == DefaultStmtClass;
}
// Iterators
- child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+ child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
};
-inline SourceLocation SwitchCase::getLocEnd() const {
+SourceLocation SwitchCase::getEndLoc() const {
if (const auto *CS = dyn_cast<CaseStmt>(this))
- return CS->getLocEnd();
- return cast<DefaultStmt>(this)->getLocEnd();
+ return CS->getEndLoc();
+ else if (const auto *DS = dyn_cast<DefaultStmt>(this))
+ return DS->getEndLoc();
+ llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!");
+}
+
+Stmt *SwitchCase::getSubStmt() {
+ if (auto *CS = dyn_cast<CaseStmt>(this))
+ return CS->getSubStmt();
+ else if (auto *DS = dyn_cast<DefaultStmt>(this))
+ return DS->getSubStmt();
+ llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!");
}
/// LabelStmt - Represents a label, which has a substatement. For example:
/// foo: return;
class LabelStmt : public Stmt {
- SourceLocation IdentLoc;
LabelDecl *TheDecl;
Stmt *SubStmt;
public:
+ /// Build a label statement.
LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
- : Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) {
- static_assert(sizeof(LabelStmt) ==
- 2 * sizeof(SourceLocation) + 2 * sizeof(void *),
- "LabelStmt too big");
+ : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt) {
+ setIdentLoc(IL);
}
- // Build an empty label statement.
+ /// Build an empty label statement.
explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {}
- SourceLocation getIdentLoc() const { return IdentLoc; }
+ SourceLocation getIdentLoc() const { return LabelStmtBits.IdentLoc; }
+ void setIdentLoc(SourceLocation L) { LabelStmtBits.IdentLoc = L; }
+
LabelDecl *getDecl() const { return TheDecl; }
void setDecl(LabelDecl *D) { TheDecl = D; }
+
const char *getName() const;
Stmt *getSubStmt() { return SubStmt; }
+
const Stmt *getSubStmt() const { return SubStmt; }
- void setIdentLoc(SourceLocation L) { IdentLoc = L; }
void setSubStmt(Stmt *SS) { SubStmt = SS; }
- SourceLocation getLocStart() const LLVM_READONLY { return IdentLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const { return getIdentLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SubStmt->getEndLoc();}
- child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+ child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == LabelStmtClass;
@@ -903,17 +1637,19 @@ class AttributedStmt final
friend TrailingObjects;
Stmt *SubStmt;
- SourceLocation AttrLoc;
- unsigned NumAttrs;
- AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
- : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
- NumAttrs(Attrs.size()) {
+ AttributedStmt(SourceLocation Loc, ArrayRef<const Attr *> Attrs,
+ Stmt *SubStmt)
+ : Stmt(AttributedStmtClass), SubStmt(SubStmt) {
+ AttributedStmtBits.NumAttrs = Attrs.size();
+ AttributedStmtBits.AttrLoc = Loc;
std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr());
}
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
- : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
+ : Stmt(AttributedStmtClass, Empty) {
+ AttributedStmtBits.NumAttrs = NumAttrs;
+ AttributedStmtBits.AttrLoc = SourceLocation{};
std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
}
@@ -924,21 +1660,21 @@ class AttributedStmt final
public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
- ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
+ ArrayRef<const Attr *> Attrs, Stmt *SubStmt);
// Build an empty attributed statement.
static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs);
- SourceLocation getAttrLoc() const { return AttrLoc; }
- ArrayRef<const Attr*> getAttrs() const {
- return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs);
+ SourceLocation getAttrLoc() const { return AttributedStmtBits.AttrLoc; }
+ ArrayRef<const Attr *> getAttrs() const {
+ return llvm::makeArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs);
}
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
- SourceLocation getLocStart() const LLVM_READONLY { return AttrLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const { return getAttrLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SubStmt->getEndLoc();}
child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
@@ -948,21 +1684,117 @@ public:
};
/// IfStmt - This represents an if/then/else.
-class IfStmt : public Stmt {
- enum { INIT, VAR, COND, THEN, ELSE, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+class IfStmt final
+ : public Stmt,
+ private llvm::TrailingObjects<IfStmt, Stmt *, SourceLocation> {
+ friend TrailingObjects;
- SourceLocation IfLoc;
- SourceLocation ElseLoc;
+ // IfStmt is followed by several trailing objects, some of which optional.
+ // Note that it would be more convenient to put the optional trailing
+ // objects at then end but this would change the order of the children.
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the init statement.
+ // Present if and only if hasInitStorage().
+ //
+ // * A "Stmt *" for the condition variable.
+ // Present if and only if hasVarStorage(). This is in fact a "DeclStmt *".
+ //
+ // * A "Stmt *" for the condition.
+ // Always present. This is in fact a "Expr *".
+ //
+ // * A "Stmt *" for the then statement.
+ // Always present.
+ //
+ // * A "Stmt *" for the else statement.
+ // Present if and only if hasElseStorage().
+ //
+ // * A "SourceLocation" for the location of the "else".
+ // Present if and only if hasElseStorage().
+ enum { InitOffset = 0, ThenOffsetFromCond = 1, ElseOffsetFromCond = 2 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + hasElseStorage() + hasVarStorage() +
+ hasInitStorage();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
+ return hasElseStorage();
+ }
+
+ unsigned initOffset() const { return InitOffset; }
+ unsigned varOffset() const { return InitOffset + hasInitStorage(); }
+ unsigned condOffset() const {
+ return InitOffset + hasInitStorage() + hasVarStorage();
+ }
+ unsigned thenOffset() const { return condOffset() + ThenOffsetFromCond; }
+ unsigned elseOffset() const { return condOffset() + ElseOffsetFromCond; }
+
+ /// Build an if/then/else statement.
+ IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, Stmt *Init,
+ VarDecl *Var, Expr *Cond, Stmt *Then, SourceLocation EL, Stmt *Else);
+
+ /// Build an empty if/then/else statement.
+ explicit IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit);
public:
- IfStmt(const ASTContext &C, SourceLocation IL,
- bool IsConstexpr, Stmt *init, VarDecl *var, Expr *cond,
- Stmt *then, SourceLocation EL = SourceLocation(),
- Stmt *elsev = nullptr);
+ /// Create an IfStmt.
+ static IfStmt *Create(const ASTContext &Ctx, SourceLocation IL,
+ bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
+ Stmt *Then, SourceLocation EL = SourceLocation(),
+ Stmt *Else = nullptr);
+
+ /// Create an empty IfStmt optionally with storage for an else statement,
+ /// condition variable and init expression.
+ static IfStmt *CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
+ bool HasInit);
- /// Build an empty if/then/else statement
- explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) {}
+ /// True if this IfStmt has the storage for an init statement.
+ bool hasInitStorage() const { return IfStmtBits.HasInit; }
+
+ /// True if this IfStmt has storage for a variable declaration.
+ bool hasVarStorage() const { return IfStmtBits.HasVar; }
+
+ /// True if this IfStmt has storage for an else statement.
+ bool hasElseStorage() const { return IfStmtBits.HasElse; }
+
+ Expr *getCond() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ void setCond(Expr *Cond) {
+ getTrailingObjects<Stmt *>()[condOffset()] = reinterpret_cast<Stmt *>(Cond);
+ }
+
+ Stmt *getThen() { return getTrailingObjects<Stmt *>()[thenOffset()]; }
+ const Stmt *getThen() const {
+ return getTrailingObjects<Stmt *>()[thenOffset()];
+ }
+
+ void setThen(Stmt *Then) {
+ getTrailingObjects<Stmt *>()[thenOffset()] = Then;
+ }
+
+ Stmt *getElse() {
+ return hasElseStorage() ? getTrailingObjects<Stmt *>()[elseOffset()]
+ : nullptr;
+ }
+
+ const Stmt *getElse() const {
+ return hasElseStorage() ? getTrailingObjects<Stmt *>()[elseOffset()]
+ : nullptr;
+ }
+
+ void setElse(Stmt *Else) {
+ assert(hasElseStorage() &&
+ "This if statement has no storage for an else statement!");
+ getTrailingObjects<Stmt *>()[elseOffset()] = Else;
+ }
/// Retrieve the variable declared in this "if" statement, if any.
///
@@ -972,52 +1804,77 @@ public:
/// printf("x is %d", x);
/// }
/// \endcode
- VarDecl *getConditionVariable() const;
- void setConditionVariable(const ASTContext &C, VarDecl *V);
+ VarDecl *getConditionVariable();
+ const VarDecl *getConditionVariable() const {
+ return const_cast<IfStmt *>(this)->getConditionVariable();
+ }
+
+ /// Set the condition variable for this if statement.
+ /// The if statement must have storage for the condition variable.
+ void setConditionVariable(const ASTContext &Ctx, VarDecl *V);
/// If this IfStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
+ DeclStmt *getConditionVariableDeclStmt() {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
+ }
+
const DeclStmt *getConditionVariableDeclStmt() const {
- return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
}
- Stmt *getInit() { return SubExprs[INIT]; }
- const Stmt *getInit() const { return SubExprs[INIT]; }
- void setInit(Stmt *S) { SubExprs[INIT] = S; }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
- const Stmt *getThen() const { return SubExprs[THEN]; }
- void setThen(Stmt *S) { SubExprs[THEN] = S; }
- const Stmt *getElse() const { return SubExprs[ELSE]; }
- void setElse(Stmt *S) { SubExprs[ELSE] = S; }
+ Stmt *getInit() {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
- Stmt *getThen() { return SubExprs[THEN]; }
- Stmt *getElse() { return SubExprs[ELSE]; }
+ const Stmt *getInit() const {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
- SourceLocation getIfLoc() const { return IfLoc; }
- void setIfLoc(SourceLocation L) { IfLoc = L; }
- SourceLocation getElseLoc() const { return ElseLoc; }
- void setElseLoc(SourceLocation L) { ElseLoc = L; }
+ void setInit(Stmt *Init) {
+ assert(hasInitStorage() &&
+ "This if statement has no storage for an init statement!");
+ getTrailingObjects<Stmt *>()[initOffset()] = Init;
+ }
+
+ SourceLocation getIfLoc() const { return IfStmtBits.IfLoc; }
+ void setIfLoc(SourceLocation IfLoc) { IfStmtBits.IfLoc = IfLoc; }
+
+ SourceLocation getElseLoc() const {
+ return hasElseStorage() ? *getTrailingObjects<SourceLocation>()
+ : SourceLocation();
+ }
+
+ void setElseLoc(SourceLocation ElseLoc) {
+ assert(hasElseStorage() &&
+ "This if statement has no storage for an else statement!");
+ *getTrailingObjects<SourceLocation>() = ElseLoc;
+ }
bool isConstexpr() const { return IfStmtBits.IsConstexpr; }
void setConstexpr(bool C) { IfStmtBits.IsConstexpr = C; }
bool isObjCAvailabilityCheck() const;
- SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; }
-
- SourceLocation getLocEnd() const LLVM_READONLY {
- if (SubExprs[ELSE])
- return SubExprs[ELSE]->getLocEnd();
- else
- return SubExprs[THEN]->getLocEnd();
+ SourceLocation getBeginLoc() const { return getIfLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ if (getElse())
+ return getElse()->getEndLoc();
+ return getThen()->getEndLoc();
}
// Iterators over subexpressions. The iterators will include iterating
// over the initialization expression referenced by the condition variable.
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
static bool classof(const Stmt *T) {
@@ -1026,22 +1883,102 @@ public:
};
/// SwitchStmt - This represents a 'switch' stmt.
-class SwitchStmt : public Stmt {
- SourceLocation SwitchLoc;
- enum { INIT, VAR, COND, BODY, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+class SwitchStmt final : public Stmt,
+ private llvm::TrailingObjects<SwitchStmt, Stmt *> {
+ friend TrailingObjects;
- // This points to a linked list of case and default statements and, if the
- // SwitchStmt is a switch on an enum value, records whether all the enum
- // values were covered by CaseStmts. The coverage information value is meant
- // to be a hint for possible clients.
- llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase;
+ /// Points to a linked list of case and default statements.
+ SwitchCase *FirstCase;
+
+ // SwitchStmt is followed by several trailing objects,
+ // some of which optional. Note that it would be more convenient to
+ // put the optional trailing objects at the end but this would change
+ // the order in children().
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the init statement.
+ // Present if and only if hasInitStorage().
+ //
+ // * A "Stmt *" for the condition variable.
+ // Present if and only if hasVarStorage(). This is in fact a "DeclStmt *".
+ //
+ // * A "Stmt *" for the condition.
+ // Always present. This is in fact an "Expr *".
+ //
+ // * A "Stmt *" for the body.
+ // Always present.
+ enum { InitOffset = 0, BodyOffsetFromCond = 1 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + hasInitStorage() + hasVarStorage();
+ }
+
+ unsigned initOffset() const { return InitOffset; }
+ unsigned varOffset() const { return InitOffset + hasInitStorage(); }
+ unsigned condOffset() const {
+ return InitOffset + hasInitStorage() + hasVarStorage();
+ }
+ unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; }
+
+ /// Build a switch statement.
+ SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, Expr *Cond);
+
+ /// Build a empty switch statement.
+ explicit SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar);
public:
- SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond);
+ /// Create a switch statement.
+ static SwitchStmt *Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
+ Expr *Cond);
- /// Build a empty switch statement.
- explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) {}
+ /// Create an empty switch statement optionally with storage for
+ /// an init expression and a condition variable.
+ static SwitchStmt *CreateEmpty(const ASTContext &Ctx, bool HasInit,
+ bool HasVar);
+
+ /// True if this SwitchStmt has storage for an init statement.
+ bool hasInitStorage() const { return SwitchStmtBits.HasInit; }
+
+ /// True if this SwitchStmt has storage for a condition variable.
+ bool hasVarStorage() const { return SwitchStmtBits.HasVar; }
+
+ Expr *getCond() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ void setCond(Expr *Cond) {
+ getTrailingObjects<Stmt *>()[condOffset()] = reinterpret_cast<Stmt *>(Cond);
+ }
+
+ Stmt *getBody() { return getTrailingObjects<Stmt *>()[bodyOffset()]; }
+ const Stmt *getBody() const {
+ return getTrailingObjects<Stmt *>()[bodyOffset()];
+ }
+
+ void setBody(Stmt *Body) {
+ getTrailingObjects<Stmt *>()[bodyOffset()] = Body;
+ }
+
+ Stmt *getInit() {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
+
+ const Stmt *getInit() const {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
+
+ void setInit(Stmt *Init) {
+ assert(hasInitStorage() &&
+ "This switch statement has no storage for an init statement!");
+ getTrailingObjects<Stmt *>()[initOffset()] = Init;
+ }
/// Retrieve the variable declared in this "switch" statement, if any.
///
@@ -1052,63 +1989,69 @@ public:
/// // ...
/// }
/// \endcode
- VarDecl *getConditionVariable() const;
- void setConditionVariable(const ASTContext &C, VarDecl *V);
+ VarDecl *getConditionVariable();
+ const VarDecl *getConditionVariable() const {
+ return const_cast<SwitchStmt *>(this)->getConditionVariable();
+ }
+
+ /// Set the condition variable in this switch statement.
+ /// The switch statement must have storage for it.
+ void setConditionVariable(const ASTContext &Ctx, VarDecl *VD);
/// If this SwitchStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
- const DeclStmt *getConditionVariableDeclStmt() const {
- return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ DeclStmt *getConditionVariableDeclStmt() {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
}
- Stmt *getInit() { return SubExprs[INIT]; }
- const Stmt *getInit() const { return SubExprs[INIT]; }
- void setInit(Stmt *S) { SubExprs[INIT] = S; }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- const Stmt *getBody() const { return SubExprs[BODY]; }
- const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); }
-
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
- Stmt *getBody() { return SubExprs[BODY]; }
- void setBody(Stmt *S) { SubExprs[BODY] = S; }
- SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); }
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
+ }
- /// Set the case list for this switch statement.
- void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); }
+ SwitchCase *getSwitchCaseList() { return FirstCase; }
+ const SwitchCase *getSwitchCaseList() const { return FirstCase; }
+ void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
- SourceLocation getSwitchLoc() const { return SwitchLoc; }
- void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
+ SourceLocation getSwitchLoc() const { return SwitchStmtBits.SwitchLoc; }
+ void setSwitchLoc(SourceLocation L) { SwitchStmtBits.SwitchLoc = L; }
void setBody(Stmt *S, SourceLocation SL) {
- SubExprs[BODY] = S;
- SwitchLoc = SL;
+ setBody(S);
+ setSwitchLoc(SL);
}
void addSwitchCase(SwitchCase *SC) {
- assert(!SC->getNextSwitchCase()
- && "case/default already added to a switch");
- SC->setNextSwitchCase(FirstCase.getPointer());
- FirstCase.setPointer(SC);
+ assert(!SC->getNextSwitchCase() &&
+ "case/default already added to a switch");
+ SC->setNextSwitchCase(FirstCase);
+ FirstCase = SC;
}
/// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
/// switch over an enum value then all cases have been explicitly covered.
- void setAllEnumCasesCovered() { FirstCase.setInt(true); }
+ void setAllEnumCasesCovered() { SwitchStmtBits.AllEnumCasesCovered = true; }
/// Returns true if the SwitchStmt is a switch of an enum value and all cases
/// have been explicitly covered.
- bool isAllEnumCasesCovered() const { return FirstCase.getInt(); }
-
- SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
+ bool isAllEnumCasesCovered() const {
+ return SwitchStmtBits.AllEnumCasesCovered;
+ }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd();
+ SourceLocation getBeginLoc() const { return getSwitchLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getBody() ? getBody()->getEndLoc()
+ : reinterpret_cast<const Stmt *>(getCond())->getEndLoc();
}
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
static bool classof(const Stmt *T) {
@@ -1117,17 +2060,75 @@ public:
};
/// WhileStmt - This represents a 'while' stmt.
-class WhileStmt : public Stmt {
- SourceLocation WhileLoc;
- enum { VAR, COND, BODY, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+class WhileStmt final : public Stmt,
+ private llvm::TrailingObjects<WhileStmt, Stmt *> {
+ friend TrailingObjects;
-public:
- WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
+ // WhileStmt is followed by several trailing objects,
+ // some of which optional. Note that it would be more
+ // convenient to put the optional trailing object at the end
+ // but this would affect children().
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the condition variable.
+ // Present if and only if hasVarStorage(). This is in fact a "DeclStmt *".
+ //
+ // * A "Stmt *" for the condition.
+ // Always present. This is in fact an "Expr *".
+ //
+ // * A "Stmt *" for the body.
+ // Always present.
+ //
+ enum { VarOffset = 0, BodyOffsetFromCond = 1 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned varOffset() const { return VarOffset; }
+ unsigned condOffset() const { return VarOffset + hasVarStorage(); }
+ unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; }
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + hasVarStorage();
+ }
+
+ /// Build a while statement.
+ WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, Stmt *Body,
SourceLocation WL);
/// Build an empty while statement.
- explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) {}
+ explicit WhileStmt(EmptyShell Empty, bool HasVar);
+
+public:
+ /// Create a while statement.
+ static WhileStmt *Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
+ Stmt *Body, SourceLocation WL);
+
+ /// Create an empty while statement optionally with storage for
+ /// a condition variable.
+ static WhileStmt *CreateEmpty(const ASTContext &Ctx, bool HasVar);
+
+ /// True if this WhileStmt has storage for a condition variable.
+ bool hasVarStorage() const { return WhileStmtBits.HasVar; }
+
+ Expr *getCond() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ void setCond(Expr *Cond) {
+ getTrailingObjects<Stmt *>()[condOffset()] = reinterpret_cast<Stmt *>(Cond);
+ }
+
+ Stmt *getBody() { return getTrailingObjects<Stmt *>()[bodyOffset()]; }
+ const Stmt *getBody() const {
+ return getTrailingObjects<Stmt *>()[bodyOffset()];
+ }
+
+ void setBody(Stmt *Body) {
+ getTrailingObjects<Stmt *>()[bodyOffset()] = Body;
+ }
/// Retrieve the variable declared in this "while" statement, if any.
///
@@ -1137,29 +2138,35 @@ public:
/// // ...
/// }
/// \endcode
- VarDecl *getConditionVariable() const;
- void setConditionVariable(const ASTContext &C, VarDecl *V);
+ VarDecl *getConditionVariable();
+ const VarDecl *getConditionVariable() const {
+ return const_cast<WhileStmt *>(this)->getConditionVariable();
+ }
+
+ /// Set the condition variable of this while statement.
+ /// The while statement must have storage for it.
+ void setConditionVariable(const ASTContext &Ctx, VarDecl *V);
/// If this WhileStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
- const DeclStmt *getConditionVariableDeclStmt() const {
- return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ DeclStmt *getConditionVariableDeclStmt() {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
}
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
- Stmt *getBody() { return SubExprs[BODY]; }
- const Stmt *getBody() const { return SubExprs[BODY]; }
- void setBody(Stmt *S) { SubExprs[BODY] = S; }
-
- SourceLocation getWhileLoc() const { return WhileLoc; }
- void setWhileLoc(SourceLocation L) { WhileLoc = L; }
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; }
+ SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; }
+ void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY]->getLocEnd();
+ SourceLocation getBeginLoc() const { return getWhileLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getBody()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -1168,46 +2175,51 @@ public:
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
};
/// DoStmt - This represents a 'do/while' stmt.
class DoStmt : public Stmt {
- SourceLocation DoLoc;
enum { BODY, COND, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+ Stmt *SubExprs[END_EXPR];
SourceLocation WhileLoc;
- SourceLocation RParenLoc; // Location of final ')' in do stmt condition.
+ SourceLocation RParenLoc; // Location of final ')' in do stmt condition.
public:
- DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL,
+ DoStmt(Stmt *Body, Expr *Cond, SourceLocation DL, SourceLocation WL,
SourceLocation RP)
- : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) {
- SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
- SubExprs[BODY] = body;
+ : Stmt(DoStmtClass), WhileLoc(WL), RParenLoc(RP) {
+ setCond(Cond);
+ setBody(Body);
+ setDoLoc(DL);
}
/// Build an empty do-while statement.
explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) {}
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ Expr *getCond() { return reinterpret_cast<Expr *>(SubExprs[COND]); }
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(SubExprs[COND]);
+ }
+
+ void setCond(Expr *Cond) { SubExprs[COND] = reinterpret_cast<Stmt *>(Cond); }
+
Stmt *getBody() { return SubExprs[BODY]; }
const Stmt *getBody() const { return SubExprs[BODY]; }
- void setBody(Stmt *S) { SubExprs[BODY] = S; }
+ void setBody(Stmt *Body) { SubExprs[BODY] = Body; }
- SourceLocation getDoLoc() const { return DoLoc; }
- void setDoLoc(SourceLocation L) { DoLoc = L; }
+ SourceLocation getDoLoc() const { return DoStmtBits.DoLoc; }
+ void setDoLoc(SourceLocation L) { DoStmtBits.DoLoc = L; }
SourceLocation getWhileLoc() const { return WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileLoc = L; }
-
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return DoLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const { return getDoLoc(); }
+ SourceLocation getEndLoc() const { return getRParenLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == DoStmtClass;
@@ -1215,7 +2227,7 @@ public:
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
}
};
@@ -1223,7 +2235,6 @@ public:
/// the init/cond/inc parts of the ForStmt will be null if they were not
/// specified in the source.
class ForStmt : public Stmt {
- SourceLocation ForLoc;
enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
SourceLocation LParenLoc, RParenLoc;
@@ -1269,18 +2280,15 @@ public:
void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
- SourceLocation getForLoc() const { return ForLoc; }
- void setForLoc(SourceLocation L) { ForLoc = L; }
+ SourceLocation getForLoc() const { return ForStmtBits.ForLoc; }
+ void setForLoc(SourceLocation L) { ForStmtBits.ForLoc = L; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
-
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY]->getLocEnd();
- }
+ SourceLocation getBeginLoc() const { return getForLoc(); }
+ SourceLocation getEndLoc() const { return getBody()->getEndLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ForStmtClass;
@@ -1295,12 +2303,13 @@ public:
/// GotoStmt - This represents a direct goto.
class GotoStmt : public Stmt {
LabelDecl *Label;
- SourceLocation GotoLoc;
SourceLocation LabelLoc;
public:
GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL)
- : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
+ : Stmt(GotoStmtClass), Label(label), LabelLoc(LL) {
+ setGotoLoc(GL);
+ }
/// Build an empty goto statement.
explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) {}
@@ -1308,13 +2317,13 @@ public:
LabelDecl *getLabel() const { return Label; }
void setLabel(LabelDecl *D) { Label = D; }
- SourceLocation getGotoLoc() const { return GotoLoc; }
- void setGotoLoc(SourceLocation L) { GotoLoc = L; }
+ SourceLocation getGotoLoc() const { return GotoStmtBits.GotoLoc; }
+ void setGotoLoc(SourceLocation L) { GotoStmtBits.GotoLoc = L; }
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; }
+ SourceLocation getBeginLoc() const { return getGotoLoc(); }
+ SourceLocation getEndLoc() const { return getLabelLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GotoStmtClass;
@@ -1328,62 +2337,64 @@ public:
/// IndirectGotoStmt - This represents an indirect goto.
class IndirectGotoStmt : public Stmt {
- SourceLocation GotoLoc;
SourceLocation StarLoc;
Stmt *Target;
public:
- IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
- Expr *target)
- : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
- Target((Stmt*)target) {}
+ IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, Expr *target)
+ : Stmt(IndirectGotoStmtClass), StarLoc(starLoc) {
+ setTarget(target);
+ setGotoLoc(gotoLoc);
+ }
/// Build an empty indirect goto statement.
explicit IndirectGotoStmt(EmptyShell Empty)
: Stmt(IndirectGotoStmtClass, Empty) {}
- void setGotoLoc(SourceLocation L) { GotoLoc = L; }
- SourceLocation getGotoLoc() const { return GotoLoc; }
+ void setGotoLoc(SourceLocation L) { GotoStmtBits.GotoLoc = L; }
+ SourceLocation getGotoLoc() const { return GotoStmtBits.GotoLoc; }
void setStarLoc(SourceLocation L) { StarLoc = L; }
SourceLocation getStarLoc() const { return StarLoc; }
- Expr *getTarget() { return reinterpret_cast<Expr*>(Target); }
- const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);}
- void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
+ Expr *getTarget() { return reinterpret_cast<Expr *>(Target); }
+ const Expr *getTarget() const {
+ return reinterpret_cast<const Expr *>(Target);
+ }
+ void setTarget(Expr *E) { Target = reinterpret_cast<Stmt *>(E); }
/// getConstantTarget - Returns the fixed target of this indirect
/// goto, if one exists.
LabelDecl *getConstantTarget();
const LabelDecl *getConstantTarget() const {
- return const_cast<IndirectGotoStmt*>(this)->getConstantTarget();
+ return const_cast<IndirectGotoStmt *>(this)->getConstantTarget();
}
- SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Target->getLocEnd(); }
+ SourceLocation getBeginLoc() const { return getGotoLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Target->getEndLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == IndirectGotoStmtClass;
}
// Iterators
- child_range children() { return child_range(&Target, &Target+1); }
+ child_range children() { return child_range(&Target, &Target + 1); }
};
/// ContinueStmt - This represents a continue.
class ContinueStmt : public Stmt {
- SourceLocation ContinueLoc;
-
public:
- ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
+ ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass) {
+ setContinueLoc(CL);
+ }
/// Build an empty continue statement.
explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {}
- SourceLocation getContinueLoc() const { return ContinueLoc; }
- void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
+ SourceLocation getContinueLoc() const { return ContinueStmtBits.ContinueLoc; }
+ void setContinueLoc(SourceLocation L) { ContinueStmtBits.ContinueLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return ContinueLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return ContinueLoc; }
+ SourceLocation getBeginLoc() const { return getContinueLoc(); }
+ SourceLocation getEndLoc() const { return getContinueLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ContinueStmtClass;
@@ -1397,22 +2408,19 @@ public:
/// BreakStmt - This represents a break.
class BreakStmt : public Stmt {
- SourceLocation BreakLoc;
-
public:
- BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {
- static_assert(sizeof(BreakStmt) == 2 * sizeof(SourceLocation),
- "BreakStmt too large");
+ BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass) {
+ setBreakLoc(BL);
}
/// Build an empty break statement.
explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {}
- SourceLocation getBreakLoc() const { return BreakLoc; }
- void setBreakLoc(SourceLocation L) { BreakLoc = L; }
+ SourceLocation getBreakLoc() const { return BreakStmtBits.BreakLoc; }
+ void setBreakLoc(SourceLocation L) { BreakStmtBits.BreakLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return BreakLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return BreakLoc; }
+ SourceLocation getBeginLoc() const { return getBreakLoc(); }
+ SourceLocation getEndLoc() const { return getBreakLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == BreakStmtClass;
@@ -1432,40 +2440,68 @@ public:
/// return a value, and it allows returning a value in functions declared to
/// return void. We explicitly model this in the AST, which means you can't
/// depend on the return type of the function and the presence of an argument.
-class ReturnStmt : public Stmt {
- SourceLocation RetLoc;
+class ReturnStmt final
+ : public Stmt,
+ private llvm::TrailingObjects<ReturnStmt, const VarDecl *> {
+ friend TrailingObjects;
+
+ /// The return expression.
Stmt *RetExpr;
- const VarDecl *NRVOCandidate;
-public:
- explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {}
+ // ReturnStmt is followed optionally by a trailing "const VarDecl *"
+ // for the NRVO candidate. Present if and only if hasNRVOCandidate().
- ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
- : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),
- NRVOCandidate(NRVOCandidate) {}
+ /// True if this ReturnStmt has storage for an NRVO candidate.
+ bool hasNRVOCandidate() const { return ReturnStmtBits.HasNRVOCandidate; }
- /// Build an empty return expression.
- explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) {}
+ unsigned numTrailingObjects(OverloadToken<const VarDecl *>) const {
+ return hasNRVOCandidate();
+ }
+
+ /// Build a return statement.
+ ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate);
+
+ /// Build an empty return statement.
+ explicit ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate);
+
+public:
+ /// Create a return statement.
+ static ReturnStmt *Create(const ASTContext &Ctx, SourceLocation RL, Expr *E,
+ const VarDecl *NRVOCandidate);
- const Expr *getRetValue() const;
- Expr *getRetValue();
- void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); }
+ /// Create an empty return statement, optionally with
+ /// storage for an NRVO candidate.
+ static ReturnStmt *CreateEmpty(const ASTContext &Ctx, bool HasNRVOCandidate);
- SourceLocation getReturnLoc() const { return RetLoc; }
- void setReturnLoc(SourceLocation L) { RetLoc = L; }
+ Expr *getRetValue() { return reinterpret_cast<Expr *>(RetExpr); }
+ const Expr *getRetValue() const { return reinterpret_cast<Expr *>(RetExpr); }
+ void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt *>(E); }
/// Retrieve the variable that might be used for the named return
/// value optimization.
///
/// The optimization itself can only be performed if the variable is
/// also marked as an NRVO object.
- const VarDecl *getNRVOCandidate() const { return NRVOCandidate; }
- void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; }
+ const VarDecl *getNRVOCandidate() const {
+ return hasNRVOCandidate() ? *getTrailingObjects<const VarDecl *>()
+ : nullptr;
+ }
+
+ /// Set the variable that might be used for the named return value
+ /// optimization. The return statement must have storage for it,
+ /// which is the case if and only if hasNRVOCandidate() is true.
+ void setNRVOCandidate(const VarDecl *Var) {
+ assert(hasNRVOCandidate() &&
+ "This return statement has no storage for an NRVO candidate!");
+ *getTrailingObjects<const VarDecl *>() = Var;
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; }
+ SourceLocation getReturnLoc() const { return ReturnStmtBits.RetLoc; }
+ void setReturnLoc(SourceLocation L) { ReturnStmtBits.RetLoc = L; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return RetExpr ? RetExpr->getLocEnd() : RetLoc;
+ SourceLocation getBeginLoc() const { return getReturnLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return RetExpr ? RetExpr->getEndLoc() : getReturnLoc();
}
static bool classof(const Stmt *T) {
@@ -1474,7 +2510,8 @@ public:
// Iterators
child_range children() {
- if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
+ if (RetExpr)
+ return child_range(&RetExpr, &RetExpr + 1);
return child_range(child_iterator(), child_iterator());
}
};
@@ -1519,8 +2556,8 @@ public:
bool isVolatile() const { return IsVolatile; }
void setVolatile(bool V) { IsVolatile = V; }
- SourceLocation getLocStart() const LLVM_READONLY { return {}; }
- SourceLocation getLocEnd() const LLVM_READONLY { return {}; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return {}; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return {}; }
//===--- Asm String Analysis ---===//
@@ -1801,8 +2838,8 @@ public:
return Clobbers[i];
}
- SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AsmLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GCCAsmStmtClass;
@@ -1899,8 +2936,7 @@ private:
ArrayRef<Expr*> Exprs, ArrayRef<StringRef> Clobbers);
public:
- SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AsmLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == MSAsmStmtClass;
@@ -1929,11 +2965,10 @@ public:
Expr *FilterExpr,
Stmt *Block);
- SourceLocation getLocStart() const LLVM_READONLY { return getExceptLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getExceptLoc(); }
SourceLocation getExceptLoc() const { return Loc; }
- SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); }
+ SourceLocation getEndLoc() const { return getBlock()->getEndLoc(); }
Expr *getFilterExpr() const {
return reinterpret_cast<Expr*>(Children[FILTER_EXPR]);
@@ -1967,11 +3002,10 @@ public:
SourceLocation FinallyLoc,
Stmt *Block);
- SourceLocation getLocStart() const LLVM_READONLY { return getFinallyLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getFinallyLoc(); }
SourceLocation getFinallyLoc() const { return Loc; }
- SourceLocation getEndLoc() const { return Block->getLocEnd(); }
+ SourceLocation getEndLoc() const { return Block->getEndLoc(); }
CompoundStmt *getBlock() const { return cast<CompoundStmt>(Block); }
@@ -2006,11 +3040,10 @@ public:
SourceLocation TryLoc, Stmt *TryBlock,
Stmt *Handler);
- SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getTryLoc(); }
SourceLocation getTryLoc() const { return TryLoc; }
- SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); }
+ SourceLocation getEndLoc() const { return Children[HANDLER]->getEndLoc(); }
bool getIsCXXTry() const { return IsCXXTry; }
@@ -2047,8 +3080,8 @@ public:
SourceLocation getLeaveLoc() const { return LeaveLoc; }
void setLeaveLoc(SourceLocation L) { LeaveLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return LeaveLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return LeaveLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LeaveLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return LeaveLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == SEHLeaveStmtClass;
@@ -2261,12 +3294,12 @@ public:
return capture_init_begin() + NumCaptures;
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getCapturedStmt()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getCapturedStmt()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getCapturedStmt()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getCapturedStmt()->getEndLoc();
}
SourceRange getSourceRange() const LLVM_READONLY {
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 34553741eb38..d3a3cf783c66 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -41,9 +41,9 @@ public:
CXXCatchStmt(EmptyShell Empty)
: Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {}
- SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return HandlerBlock->getLocEnd();
+ SourceLocation getBeginLoc() const LLVM_READONLY { return CatchLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return HandlerBlock->getEndLoc();
}
SourceLocation getCatchLoc() const { return CatchLoc; }
@@ -86,12 +86,11 @@ public:
static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty,
unsigned numHandlers);
- SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getTryLoc(); }
SourceLocation getTryLoc() const { return TryLoc; }
SourceLocation getEndLoc() const {
- return getStmts()[NumHandlers]->getLocEnd();
+ return getStmts()[NumHandlers]->getEndLoc();
}
CompoundStmt *getTryBlock() {
@@ -119,14 +118,15 @@ public:
};
/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for
-/// statement, represented as 'for (range-declarator : range-expression)'.
+/// statement, represented as 'for (range-declarator : range-expression)'
+/// or 'for (init-statement range-declarator : range-expression)'.
///
/// This is stored in a partially-desugared form to allow full semantic
/// analysis of the constituent components. The original syntactic components
/// can be extracted using getLoopVariable and getRangeInit.
class CXXForRangeStmt : public Stmt {
SourceLocation ForLoc;
- enum { RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END };
+ enum { INIT, RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END };
// SubExprs[RANGE] is an expression or declstmt.
// SubExprs[COND] and SubExprs[INC] are expressions.
Stmt *SubExprs[END];
@@ -136,16 +136,17 @@ class CXXForRangeStmt : public Stmt {
friend class ASTStmtReader;
public:
- CXXForRangeStmt(DeclStmt *Range, DeclStmt *Begin, DeclStmt *End,
- Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body,
- SourceLocation FL, SourceLocation CAL, SourceLocation CL,
- SourceLocation RPL);
+ CXXForRangeStmt(Stmt *InitStmt, DeclStmt *Range, DeclStmt *Begin,
+ DeclStmt *End, Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
+ Stmt *Body, SourceLocation FL, SourceLocation CAL,
+ SourceLocation CL, SourceLocation RPL);
CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
-
+ Stmt *getInit() { return SubExprs[INIT]; }
VarDecl *getLoopVariable();
Expr *getRangeInit();
+ const Stmt *getInit() const { return SubExprs[INIT]; }
const VarDecl *getLoopVariable() const;
const Expr *getRangeInit() const;
@@ -180,6 +181,7 @@ public:
}
const Stmt *getBody() const { return SubExprs[BODY]; }
+ void setInit(Stmt *S) { SubExprs[INIT] = S; }
void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); }
void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; }
void setBeginStmt(Stmt *S) { SubExprs[BEGINSTMT] = S; }
@@ -194,9 +196,9 @@ public:
SourceLocation getColonLoc() const { return ColonLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY]->getLocEnd();
+ SourceLocation getBeginLoc() const LLVM_READONLY { return ForLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExprs[BODY]->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -280,8 +282,10 @@ public:
return reinterpret_cast<CompoundStmt *>(SubStmt);
}
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubStmt->getEndLoc();
+ }
child_range children() {
return child_range(&SubStmt, &SubStmt+1);
@@ -399,12 +403,12 @@ public:
return {getStoredStmts() + SubStmt::FirstParamMove, NumParams};
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getBody() ? getBody()->getLocStart()
- : getPromiseDecl()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getBody() ? getBody()->getBeginLoc()
+ : getPromiseDecl()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getBody() ? getBody()->getLocEnd() : getPromiseDecl()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getBody() ? getBody()->getEndLoc() : getPromiseDecl()->getEndLoc();
}
child_range children() {
@@ -464,9 +468,9 @@ public:
bool isImplicit() const { return IsImplicit; }
void setIsImplicit(bool value = true) { IsImplicit = value; }
- SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getOperand() ? getOperand()->getLocEnd() : getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY { return CoreturnLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getOperand() ? getOperand()->getEndLoc() : getBeginLoc();
}
child_range children() {
diff --git a/include/clang/AST/StmtDataCollectors.td b/include/clang/AST/StmtDataCollectors.td
index bf5f8c21707f..90ca08027330 100644
--- a/include/clang/AST/StmtDataCollectors.td
+++ b/include/clang/AST/StmtDataCollectors.td
@@ -3,8 +3,8 @@ class Stmt {
addData(S->getStmtClass());
// This ensures that non-macro-generated code isn't identical to
// macro-generated code.
- addData(data_collection::getMacroStack(S->getLocStart(), Context));
- addData(data_collection::getMacroStack(S->getLocEnd(), Context));
+ addData(data_collection::getMacroStack(S->getBeginLoc(), Context));
+ addData(data_collection::getMacroStack(S->getEndLoc(), Context));
}];
}
@@ -27,7 +27,7 @@ class ExpressionTraitExpr {
}
class PredefinedExpr {
code Code = [{
- addData(S->getIdentType());
+ addData(S->getIdentKind());
}];
}
class TypeTraitExpr {
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index 0b2cc78b65be..f0c0a9aeb6ac 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/include/clang/AST/StmtObjC.h
@@ -55,9 +55,9 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
- SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY]->getLocEnd();
+ SourceLocation getBeginLoc() const LLVM_READONLY { return ForLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExprs[BODY]->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -104,8 +104,8 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtCatchLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Body->getEndLoc(); }
bool hasEllipsis() const { return getCatchParamDecl() == nullptr; }
@@ -133,9 +133,9 @@ public:
Stmt *getFinallyBody() { return AtFinallyStmt; }
void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtFinallyLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return AtFinallyStmt->getLocEnd();
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtFinallyLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return AtFinallyStmt->getEndLoc();
}
SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
@@ -238,8 +238,8 @@ public:
getStmts()[1 + NumCatchStmts] = S;
}
- SourceLocation getLocStart() const LLVM_READONLY { return AtTryLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtTryLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtTryStmtClass;
@@ -295,9 +295,9 @@ public:
}
void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtSynchronizedLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getSynchBody()->getLocEnd();
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtSynchronizedLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getSynchBody()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -329,9 +329,9 @@ public:
SourceLocation getThrowLoc() const LLVM_READONLY { return AtThrowLoc; }
void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return Throw ? Throw->getLocEnd() : AtThrowLoc;
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtThrowLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return Throw ? Throw->getEndLoc() : AtThrowLoc;
}
static bool classof(const Stmt *T) {
@@ -357,8 +357,10 @@ public:
Stmt *getSubStmt() { return SubStmt; }
void setSubStmt(Stmt *S) { SubStmt = S; }
- SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubStmt->getEndLoc();
+ }
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index d23375e7606b..d1eedd62b372 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -165,9 +165,9 @@ public:
}
/// Returns starting location of directive kind.
- SourceLocation getLocStart() const { return StartLoc; }
+ SourceLocation getBeginLoc() const { return StartLoc; }
/// Returns ending location of directive.
- SourceLocation getLocEnd() const { return EndLoc; }
+ SourceLocation getEndLoc() const { return EndLoc; }
/// Set starting location of directive kind.
///
@@ -392,9 +392,11 @@ class OMPLoopDirective : public OMPExecutableDirective {
CombinedConditionOffset = 25,
CombinedNextLowerBoundOffset = 26,
CombinedNextUpperBoundOffset = 27,
+ CombinedDistConditionOffset = 28,
+ CombinedParForInDistConditionOffset = 29,
// Offset to the end (and start of the following counters/updates/finals
// arrays) for combined distribute loop directives.
- CombinedDistributeEnd = 28,
+ CombinedDistributeEnd = 30,
};
/// Get the counters storage.
@@ -605,6 +607,17 @@ protected:
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedNextUpperBoundOffset) = CombNUB;
}
+ void setCombinedDistCond(Expr *CombDistCond) {
+ assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
+ "expected loop bound distribute sharing directive");
+ *std::next(child_begin(), CombinedDistConditionOffset) = CombDistCond;
+ }
+ void setCombinedParForInDistCond(Expr *CombParForInDistCond) {
+ assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
+ "expected loop bound distribute sharing directive");
+ *std::next(child_begin(),
+ CombinedParForInDistConditionOffset) = CombParForInDistCond;
+ }
void setCounters(ArrayRef<Expr *> A);
void setPrivateCounters(ArrayRef<Expr *> A);
void setInits(ArrayRef<Expr *> A);
@@ -637,6 +650,13 @@ public:
/// Update of UpperBound for statically scheduled omp loops for
/// outer loop in combined constructs (e.g. 'distribute parallel for')
Expr *NUB;
+ /// Distribute Loop condition used when composing 'omp distribute'
+ /// with 'omp for' in a same construct when schedule is chunked.
+ Expr *DistCond;
+ /// 'omp parallel for' loop condition used when composed with
+ /// 'omp distribute' in the same construct and when schedule is
+ /// chunked and the chunk size is 1.
+ Expr *ParForInDistCond;
};
/// The expressions built for the OpenMP loop CodeGen for the
@@ -754,6 +774,8 @@ public:
DistCombinedFields.Cond = nullptr;
DistCombinedFields.NLB = nullptr;
DistCombinedFields.NUB = nullptr;
+ DistCombinedFields.DistCond = nullptr;
+ DistCombinedFields.ParForInDistCond = nullptr;
}
};
@@ -922,6 +944,18 @@ public:
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedNextUpperBoundOffset)));
}
+ Expr *getCombinedDistCond() const {
+ assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
+ "expected loop bound distribute sharing directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), CombinedDistConditionOffset)));
+ }
+ Expr *getCombinedParForInDistCond() const {
+ assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
+ "expected loop bound distribute sharing directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), CombinedParForInDistConditionOffset)));
+ }
const Stmt *getBody() const {
// This relies on the loop form is already checked by Sema.
const Stmt *Body =
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index 30bc257c7e79..ea40e0497307 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/include/clang/AST/StmtVisitor.h
@@ -22,15 +22,12 @@
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <utility>
namespace clang {
-
-template <typename T> struct make_ptr { using type = T *; };
-template <typename T> struct make_const_ptr { using type = const T *; };
-
/// StmtVisitorBase - This class implements a simple visitor for Stmt
/// subclasses. Since Expr derives from Stmt, this also includes support for
/// visiting Exprs.
@@ -182,53 +179,19 @@ public:
///
/// This class does not preserve constness of Stmt pointers (see also
/// ConstStmtVisitor).
-template<typename ImplClass, typename RetTy=void, typename... ParamTys>
+template <typename ImplClass, typename RetTy = void, typename... ParamTys>
class StmtVisitor
- : public StmtVisitorBase<make_ptr, ImplClass, RetTy, ParamTys...> {};
+ : public StmtVisitorBase<std::add_pointer, ImplClass, RetTy, ParamTys...> {
+};
/// ConstStmtVisitor - This class implements a simple visitor for Stmt
/// subclasses. Since Expr derives from Stmt, this also includes support for
/// visiting Exprs.
///
/// This class preserves constness of Stmt pointers (see also StmtVisitor).
-template<typename ImplClass, typename RetTy=void, typename... ParamTys>
-class ConstStmtVisitor
- : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy, ParamTys...> {};
-
-/// This class implements a simple visitor for OMPClause
-/// subclasses.
-template<class ImplClass, template <typename> class Ptr, typename RetTy>
-class OMPClauseVisitorBase {
-public:
-#define PTR(CLASS) typename Ptr<CLASS>::type
-#define DISPATCH(CLASS) \
- return static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<PTR(CLASS)>(S))
-
-#define OPENMP_CLAUSE(Name, Class) \
- RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); }
-#include "clang/Basic/OpenMPKinds.def"
-
- RetTy Visit(PTR(OMPClause) S) {
- // Top switch clause: visit each OMPClause.
- switch (S->getClauseKind()) {
- default: llvm_unreachable("Unknown clause kind!");
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_ ## Name : return Visit ## Class(static_cast<PTR(Class)>(S));
-#include "clang/Basic/OpenMPKinds.def"
- }
- }
- // Base case, ignore it. :)
- RetTy VisitOMPClause(PTR(OMPClause) Node) { return RetTy(); }
-#undef PTR
-#undef DISPATCH
-};
-
-template<class ImplClass, typename RetTy = void>
-class OMPClauseVisitor :
- public OMPClauseVisitorBase <ImplClass, make_ptr, RetTy> {};
-template<class ImplClass, typename RetTy = void>
-class ConstOMPClauseVisitor :
- public OMPClauseVisitorBase <ImplClass, make_const_ptr, RetTy> {};
+template <typename ImplClass, typename RetTy = void, typename... ParamTys>
+class ConstStmtVisitor : public StmtVisitorBase<llvm::make_const_ptr, ImplClass,
+ RetTy, ParamTys...> {};
} // namespace clang
diff --git a/include/clang/AST/TemplateArgumentVisitor.h b/include/clang/AST/TemplateArgumentVisitor.h
new file mode 100644
index 000000000000..e1cc392a1705
--- /dev/null
+++ b/include/clang/AST/TemplateArgumentVisitor.h
@@ -0,0 +1,99 @@
+//===- TemplateArgumentVisitor.h - Visitor for TArg subclasses --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TemplateArgumentVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TEMPLATEARGUMENTVISITOR_H
+#define LLVM_CLANG_AST_TEMPLATEARGUMENTVISITOR_H
+
+#include "clang/AST/TemplateBase.h"
+
+namespace clang {
+
+namespace templateargumentvisitor {
+
+/// A simple visitor class that helps create template argument visitors.
+template <template <typename> class Ref, typename ImplClass,
+ typename RetTy = void, typename... ParamTys>
+class Base {
+public:
+#define REF(CLASS) typename Ref<CLASS>::type
+#define DISPATCH(NAME) \
+ case TemplateArgument::NAME: \
+ return static_cast<ImplClass *>(this)->Visit##NAME##TemplateArgument( \
+ TA, std::forward<ParamTys>(P)...)
+
+ RetTy Visit(REF(TemplateArgument) TA, ParamTys... P) {
+ switch (TA.getKind()) {
+ DISPATCH(Null);
+ DISPATCH(Type);
+ DISPATCH(Declaration);
+ DISPATCH(NullPtr);
+ DISPATCH(Integral);
+ DISPATCH(Template);
+ DISPATCH(TemplateExpansion);
+ DISPATCH(Expression);
+ DISPATCH(Pack);
+ }
+ llvm_unreachable("TemplateArgument is not covered in switch!");
+ }
+
+ // If the implementation chooses not to implement a certain visit
+ // method, fall back to the parent.
+
+#define VISIT_METHOD(CATEGORY) \
+ RetTy Visit##CATEGORY##TemplateArgument(REF(TemplateArgument) TA, \
+ ParamTys... P) { \
+ return VisitTemplateArgument(TA, std::forward<ParamTys>(P)...); \
+ }
+
+ VISIT_METHOD(Null);
+ VISIT_METHOD(Type);
+ VISIT_METHOD(Declaration);
+ VISIT_METHOD(NullPtr);
+ VISIT_METHOD(Integral);
+ VISIT_METHOD(Template);
+ VISIT_METHOD(TemplateExpansion);
+ VISIT_METHOD(Expression);
+ VISIT_METHOD(Pack);
+
+ RetTy VisitTemplateArgument(REF(TemplateArgument), ParamTys...) {
+ return RetTy();
+ }
+
+#undef REF
+#undef DISPATCH
+#undef VISIT_METHOD
+};
+
+} // namespace templateargumentvisitor
+
+/// A simple visitor class that helps create template argument visitors.
+///
+/// This class does not preserve constness of TemplateArgument references (see
+/// also ConstTemplateArgumentVisitor).
+template <typename ImplClass, typename RetTy = void, typename... ParamTys>
+class TemplateArgumentVisitor
+ : public templateargumentvisitor::Base<std::add_lvalue_reference, ImplClass,
+ RetTy, ParamTys...> {};
+
+/// A simple visitor class that helps create template argument visitors.
+///
+/// This class preserves constness of TemplateArgument references (see also
+/// TemplateArgumentVisitor).
+template <typename ImplClass, typename RetTy = void, typename... ParamTys>
+class ConstTemplateArgumentVisitor
+ : public templateargumentvisitor::Base<llvm::make_const_ref, ImplClass,
+ RetTy, ParamTys...> {};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_TEMPLATEARGUMENTVISITOR_H
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 6898ef4e1b8a..e3a773b4e490 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -467,7 +467,7 @@ public:
: Argument(Argument), LocInfo(E) {
// Permit any kind of template argument that can be represented with an
- // expression
+ // expression.
assert(Argument.getKind() == TemplateArgument::NullPtr ||
Argument.getKind() == TemplateArgument::Integral ||
Argument.getKind() == TemplateArgument::Declaration ||
@@ -530,19 +530,22 @@ public:
}
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
- assert(Argument.getKind() == TemplateArgument::Template ||
- Argument.getKind() == TemplateArgument::TemplateExpansion);
+ if (Argument.getKind() != TemplateArgument::Template &&
+ Argument.getKind() != TemplateArgument::TemplateExpansion)
+ return NestedNameSpecifierLoc();
return LocInfo.getTemplateQualifierLoc();
}
SourceLocation getTemplateNameLoc() const {
- assert(Argument.getKind() == TemplateArgument::Template ||
- Argument.getKind() == TemplateArgument::TemplateExpansion);
+ if (Argument.getKind() != TemplateArgument::Template &&
+ Argument.getKind() != TemplateArgument::TemplateExpansion)
+ return SourceLocation();
return LocInfo.getTemplateNameLoc();
}
SourceLocation getTemplateEllipsisLoc() const {
- assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
+ if (Argument.getKind() != TemplateArgument::TemplateExpansion)
+ return SourceLocation();
return LocInfo.getTemplateEllipsisLoc();
}
};
@@ -617,13 +620,17 @@ public:
/// The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;
+ SourceLocation getLAngleLoc() const { return LAngleLoc; }
+ SourceLocation getRAngleLoc() const { return RAngleLoc; }
+
/// Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
return getTrailingObjects<TemplateArgumentLoc>();
}
+ unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
- return llvm::makeArrayRef(getTemplateArgs(), NumTemplateArgs);
+ return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
}
const TemplateArgumentLoc &operator[](unsigned I) const {
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index d88d58d0a2aa..48272597d4d1 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
#define LLVM_CLANG_AST_TEMPLATENAME_H
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
diff --git a/include/clang/AST/TextNodeDumper.h b/include/clang/AST/TextNodeDumper.h
new file mode 100644
index 000000000000..794066376300
--- /dev/null
+++ b/include/clang/AST/TextNodeDumper.h
@@ -0,0 +1,298 @@
+//===--- TextNodeDumper.h - Printing of AST nodes -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AST dumping of components of individual AST nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TEXTNODEDUMPER_H
+#define LLVM_CLANG_AST_TEXTNODEDUMPER_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDumperUtils.h"
+#include "clang/AST/AttrVisitor.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/CommentVisitor.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TemplateArgumentVisitor.h"
+#include "clang/AST/TypeVisitor.h"
+
+namespace clang {
+
+class TextTreeStructure {
+ raw_ostream &OS;
+ const bool ShowColors;
+
+ /// Pending[i] is an action to dump an entity at level i.
+ llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
+
+ /// Indicates whether we're at the top level.
+ bool TopLevel = true;
+
+ /// Indicates if we're handling the first child after entering a new depth.
+ bool FirstChild = true;
+
+ /// Prefix for currently-being-dumped entity.
+ std::string Prefix;
+
+public:
+ /// Add a child of the current node. Calls DoAddChild without arguments
+ template <typename Fn> void AddChild(Fn DoAddChild) {
+ return AddChild("", DoAddChild);
+ }
+
+ /// Add a child of the current node with an optional label.
+ /// Calls DoAddChild without arguments.
+ template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) {
+ // If we're at the top level, there's nothing interesting to do; just
+ // run the dumper.
+ if (TopLevel) {
+ TopLevel = false;
+ DoAddChild();
+ while (!Pending.empty()) {
+ Pending.back()(true);
+ Pending.pop_back();
+ }
+ Prefix.clear();
+ OS << "\n";
+ TopLevel = true;
+ return;
+ }
+
+ // We need to capture an owning-string in the lambda because the lambda
+ // is invoked in a deferred manner.
+ std::string LabelStr = Label;
+ auto DumpWithIndent = [this, DoAddChild, LabelStr](bool IsLastChild) {
+ // Print out the appropriate tree structure and work out the prefix for
+ // children of this node. For instance:
+ //
+ // A Prefix = ""
+ // |-B Prefix = "| "
+ // | `-C Prefix = "| "
+ // `-D Prefix = " "
+ // |-E Prefix = " | "
+ // `-F Prefix = " "
+ // G Prefix = ""
+ //
+ // Note that the first level gets no prefix.
+ {
+ OS << '\n';
+ ColorScope Color(OS, ShowColors, IndentColor);
+ OS << Prefix << (IsLastChild ? '`' : '|') << '-';
+ if (!LabelStr.empty())
+ OS << LabelStr << ": ";
+
+ this->Prefix.push_back(IsLastChild ? ' ' : '|');
+ this->Prefix.push_back(' ');
+ }
+
+ FirstChild = true;
+ unsigned Depth = Pending.size();
+
+ DoAddChild();
+
+ // If any children are left, they're the last at their nesting level.
+ // Dump those ones out now.
+ while (Depth < Pending.size()) {
+ Pending.back()(true);
+ this->Pending.pop_back();
+ }
+
+ // Restore the old prefix.
+ this->Prefix.resize(Prefix.size() - 2);
+ };
+
+ if (FirstChild) {
+ Pending.push_back(std::move(DumpWithIndent));
+ } else {
+ Pending.back()(false);
+ Pending.back() = std::move(DumpWithIndent);
+ }
+ FirstChild = false;
+ }
+
+ TextTreeStructure(raw_ostream &OS, bool ShowColors)
+ : OS(OS), ShowColors(ShowColors) {}
+};
+
+class TextNodeDumper
+ : public TextTreeStructure,
+ public comments::ConstCommentVisitor<TextNodeDumper, void,
+ const comments::FullComment *>,
+ public ConstAttrVisitor<TextNodeDumper>,
+ public ConstTemplateArgumentVisitor<TextNodeDumper>,
+ public ConstStmtVisitor<TextNodeDumper>,
+ public TypeVisitor<TextNodeDumper> {
+ raw_ostream &OS;
+ const bool ShowColors;
+
+ /// Keep track of the last location we print out so that we can
+ /// print out deltas from then on out.
+ const char *LastLocFilename = "";
+ unsigned LastLocLine = ~0U;
+
+ const SourceManager *SM;
+
+ /// The policy to use for printing; can be defaulted.
+ PrintingPolicy PrintPolicy;
+
+ const comments::CommandTraits *Traits;
+
+ const char *getCommandName(unsigned CommandID);
+
+public:
+ TextNodeDumper(raw_ostream &OS, bool ShowColors, const SourceManager *SM,
+ const PrintingPolicy &PrintPolicy,
+ const comments::CommandTraits *Traits);
+
+ void Visit(const comments::Comment *C, const comments::FullComment *FC);
+
+ void Visit(const Attr *A);
+
+ void Visit(const TemplateArgument &TA, SourceRange R,
+ const Decl *From = nullptr, StringRef Label = {});
+
+ void Visit(const Stmt *Node);
+
+ void Visit(const Type *T);
+
+ void Visit(QualType T);
+
+ void Visit(const Decl *D);
+
+ void Visit(const CXXCtorInitializer *Init);
+
+ void Visit(const OMPClause *C);
+
+ void Visit(const BlockDecl::Capture &C);
+
+ void dumpPointer(const void *Ptr);
+ void dumpLocation(SourceLocation Loc);
+ void dumpSourceRange(SourceRange R);
+ void dumpBareType(QualType T, bool Desugar = true);
+ void dumpType(QualType T);
+ void dumpBareDeclRef(const Decl *D);
+ void dumpName(const NamedDecl *ND);
+ void dumpAccessSpecifier(AccessSpecifier AS);
+
+ void dumpDeclRef(const Decl *D, StringRef Label = {});
+
+ void visitTextComment(const comments::TextComment *C,
+ const comments::FullComment *);
+ void visitInlineCommandComment(const comments::InlineCommandComment *C,
+ const comments::FullComment *);
+ void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C,
+ const comments::FullComment *);
+ void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C,
+ const comments::FullComment *);
+ void visitBlockCommandComment(const comments::BlockCommandComment *C,
+ const comments::FullComment *);
+ void visitParamCommandComment(const comments::ParamCommandComment *C,
+ const comments::FullComment *FC);
+ void visitTParamCommandComment(const comments::TParamCommandComment *C,
+ const comments::FullComment *FC);
+ void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C,
+ const comments::FullComment *);
+ void
+ visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C,
+ const comments::FullComment *);
+ void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
+ const comments::FullComment *);
+
+// Implements Visit methods for Attrs.
+#include "clang/AST/AttrTextNodeDump.inc"
+
+ void VisitNullTemplateArgument(const TemplateArgument &TA);
+ void VisitTypeTemplateArgument(const TemplateArgument &TA);
+ void VisitDeclarationTemplateArgument(const TemplateArgument &TA);
+ void VisitNullPtrTemplateArgument(const TemplateArgument &TA);
+ void VisitIntegralTemplateArgument(const TemplateArgument &TA);
+ void VisitTemplateTemplateArgument(const TemplateArgument &TA);
+ void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA);
+ void VisitExpressionTemplateArgument(const TemplateArgument &TA);
+ void VisitPackTemplateArgument(const TemplateArgument &TA);
+
+ void VisitIfStmt(const IfStmt *Node);
+ void VisitSwitchStmt(const SwitchStmt *Node);
+ void VisitWhileStmt(const WhileStmt *Node);
+ void VisitLabelStmt(const LabelStmt *Node);
+ void VisitGotoStmt(const GotoStmt *Node);
+ void VisitCaseStmt(const CaseStmt *Node);
+ void VisitCallExpr(const CallExpr *Node);
+ void VisitCastExpr(const CastExpr *Node);
+ void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
+ void VisitDeclRefExpr(const DeclRefExpr *Node);
+ void VisitPredefinedExpr(const PredefinedExpr *Node);
+ void VisitCharacterLiteral(const CharacterLiteral *Node);
+ void VisitIntegerLiteral(const IntegerLiteral *Node);
+ void VisitFixedPointLiteral(const FixedPointLiteral *Node);
+ void VisitFloatingLiteral(const FloatingLiteral *Node);
+ void VisitStringLiteral(const StringLiteral *Str);
+ void VisitInitListExpr(const InitListExpr *ILE);
+ void VisitUnaryOperator(const UnaryOperator *Node);
+ void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
+ void VisitMemberExpr(const MemberExpr *Node);
+ void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node);
+ void VisitBinaryOperator(const BinaryOperator *Node);
+ void VisitCompoundAssignOperator(const CompoundAssignOperator *Node);
+ void VisitAddrLabelExpr(const AddrLabelExpr *Node);
+ void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
+ void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);
+ void VisitCXXThisExpr(const CXXThisExpr *Node);
+ void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
+ void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node);
+ void VisitCXXConstructExpr(const CXXConstructExpr *Node);
+ void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
+ void VisitCXXNewExpr(const CXXNewExpr *Node);
+ void VisitCXXDeleteExpr(const CXXDeleteExpr *Node);
+ void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
+ void VisitExprWithCleanups(const ExprWithCleanups *Node);
+ void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
+ void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
+ void
+ VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node);
+ void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
+ void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node);
+ void VisitObjCMessageExpr(const ObjCMessageExpr *Node);
+ void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node);
+ void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node);
+ void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node);
+ void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node);
+ void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node);
+ void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node);
+ void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node);
+
+ void VisitRValueReferenceType(const ReferenceType *T);
+ void VisitArrayType(const ArrayType *T);
+ void VisitConstantArrayType(const ConstantArrayType *T);
+ void VisitVariableArrayType(const VariableArrayType *T);
+ void VisitDependentSizedArrayType(const DependentSizedArrayType *T);
+ void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T);
+ void VisitVectorType(const VectorType *T);
+ void VisitFunctionType(const FunctionType *T);
+ void VisitFunctionProtoType(const FunctionProtoType *T);
+ void VisitUnresolvedUsingType(const UnresolvedUsingType *T);
+ void VisitTypedefType(const TypedefType *T);
+ void VisitUnaryTransformType(const UnaryTransformType *T);
+ void VisitTagType(const TagType *T);
+ void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
+ void VisitAutoType(const AutoType *T);
+ void VisitTemplateSpecializationType(const TemplateSpecializationType *T);
+ void VisitInjectedClassNameType(const InjectedClassNameType *T);
+ void VisitObjCInterfaceType(const ObjCInterfaceType *T);
+ void VisitPackExpansionType(const PackExpansionType *T);
+
+private:
+ void dumpCXXTemporary(const CXXTemporary *Temporary);
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_TEXTNODEDUMPER_H
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 9a8dd6faff31..d4c97b1b5efc 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -21,6 +21,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/LLVM.h"
@@ -45,6 +46,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/type_traits.h"
+#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
@@ -100,48 +102,33 @@ namespace llvm {
namespace clang {
-class ArrayType;
class ASTContext;
-class AttributedType;
-class AutoType;
-class BuiltinType;
template <typename> class CanQual;
-class ComplexType;
class CXXRecordDecl;
class DeclContext;
-class DeducedType;
class EnumDecl;
class Expr;
class ExtQualsTypeCommonBase;
class FunctionDecl;
-class FunctionNoProtoType;
-class FunctionProtoType;
class IdentifierInfo;
-class InjectedClassNameType;
class NamedDecl;
class ObjCInterfaceDecl;
-class ObjCObjectPointerType;
-class ObjCObjectType;
class ObjCProtocolDecl;
class ObjCTypeParamDecl;
-class ParenType;
struct PrintingPolicy;
class RecordDecl;
-class RecordType;
class Stmt;
class TagDecl;
class TemplateArgument;
class TemplateArgumentListInfo;
class TemplateArgumentLoc;
-class TemplateSpecializationType;
class TemplateTypeParmDecl;
class TypedefNameDecl;
-class TypedefType;
class UnresolvedUsingTypenameDecl;
using CanQualType = CanQual<Type>;
- // Provide forward declarations for all of the *Type classes
+// Provide forward declarations for all of the *Type classes.
#define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.def"
@@ -269,28 +256,24 @@ public:
}
bool hasConst() const { return Mask & Const; }
- void setConst(bool flag) {
- Mask = (Mask & ~Const) | (flag ? Const : 0);
- }
+ bool hasOnlyConst() const { return Mask == Const; }
void removeConst() { Mask &= ~Const; }
void addConst() { Mask |= Const; }
bool hasVolatile() const { return Mask & Volatile; }
- void setVolatile(bool flag) {
- Mask = (Mask & ~Volatile) | (flag ? Volatile : 0);
- }
+ bool hasOnlyVolatile() const { return Mask == Volatile; }
void removeVolatile() { Mask &= ~Volatile; }
void addVolatile() { Mask |= Volatile; }
bool hasRestrict() const { return Mask & Restrict; }
- void setRestrict(bool flag) {
- Mask = (Mask & ~Restrict) | (flag ? Restrict : 0);
- }
+ bool hasOnlyRestrict() const { return Mask == Restrict; }
void removeRestrict() { Mask &= ~Restrict; }
void addRestrict() { Mask |= Restrict; }
bool hasCVRQualifiers() const { return getCVRQualifiers(); }
unsigned getCVRQualifiers() const { return Mask & CVRMask; }
+ unsigned getCVRUQualifiers() const { return Mask & (CVRMask | UMask); }
+
void setCVRQualifiers(unsigned mask) {
assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
Mask = (Mask & ~CVRMask) | mask;
@@ -997,9 +980,7 @@ public:
void print(raw_ostream &OS, const PrintingPolicy &Policy,
const Twine &PlaceHolder = Twine(),
- unsigned Indentation = 0) const {
- print(split(), OS, Policy, PlaceHolder, Indentation);
- }
+ unsigned Indentation = 0) const;
static void print(SplitQualType split, raw_ostream &OS,
const PrintingPolicy &policy, const Twine &PlaceHolder,
@@ -1013,9 +994,7 @@ public:
unsigned Indentation = 0);
void getAsStringInternal(std::string &Str,
- const PrintingPolicy &Policy) const {
- return getAsStringInternal(split(), Str, Policy);
- }
+ const PrintingPolicy &Policy) const;
static void getAsStringInternal(SplitQualType split, std::string &out,
const PrintingPolicy &policy) {
@@ -1515,6 +1494,9 @@ protected:
unsigned Kind : 8;
};
+ /// FunctionTypeBitfields store various bits belonging to FunctionProtoType.
+ /// Only common bits are stored here. Additional uncommon bits are stored
+ /// in a trailing object after FunctionProtoType.
class FunctionTypeBitfields {
friend class FunctionProtoType;
friend class FunctionType;
@@ -1525,18 +1507,38 @@ protected:
/// regparm and the calling convention.
unsigned ExtInfo : 12;
+ /// The ref-qualifier associated with a \c FunctionProtoType.
+ ///
+ /// This is a value of type \c RefQualifierKind.
+ unsigned RefQualifier : 2;
+
/// Used only by FunctionProtoType, put here to pack with the
/// other bitfields.
/// The qualifiers are part of FunctionProtoType because...
///
/// C++ 8.3.5p4: The return type, the parameter type list and the
/// cv-qualifier-seq, [...], are part of the function type.
- unsigned TypeQuals : 4;
+ unsigned FastTypeQuals : Qualifiers::FastWidth;
+ /// Whether this function has extended Qualifiers.
+ unsigned HasExtQuals : 1;
- /// The ref-qualifier associated with a \c FunctionProtoType.
- ///
- /// This is a value of type \c RefQualifierKind.
- unsigned RefQualifier : 2;
+ /// The number of parameters this function has, not counting '...'.
+ /// According to [implimits] 8 bits should be enough here but this is
+ /// somewhat easy to exceed with metaprogramming and so we would like to
+ /// keep NumParams as wide as reasonably possible.
+ unsigned NumParams : 16;
+
+ /// The type of exception specification this function has.
+ unsigned ExceptionSpecType : 4;
+
+ /// Whether this function has extended parameter information.
+ unsigned HasExtParameterInfos : 1;
+
+ /// Whether the function is variadic.
+ unsigned Variadic : 1;
+
+ /// Whether this function has a trailing return type.
+ unsigned HasTrailingReturn : 1;
};
class ObjCObjectTypeBitfields {
@@ -1554,8 +1556,6 @@ protected:
unsigned IsKindOf : 1;
};
- static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned");
-
class ReferenceTypeBitfields {
friend class ReferenceType;
@@ -1588,6 +1588,18 @@ protected:
unsigned Keyword : 8;
};
+ enum { NumTypeWithKeywordBits = 8 };
+
+ class ElaboratedTypeBitfields {
+ friend class ElaboratedType;
+
+ unsigned : NumTypeBits;
+ unsigned : NumTypeWithKeywordBits;
+
+ /// Whether the ElaboratedType has a trailing OwnedTagDecl.
+ unsigned HasOwnedTagDecl : 1;
+ };
+
class VectorTypeBitfields {
friend class VectorType;
friend class DependentVectorType;
@@ -1623,6 +1635,74 @@ protected:
unsigned Keyword : 2;
};
+ class SubstTemplateTypeParmPackTypeBitfields {
+ friend class SubstTemplateTypeParmPackType;
+
+ unsigned : NumTypeBits;
+
+ /// The number of template arguments in \c Arguments, which is
+ /// expected to be able to hold at least 1024 according to [implimits].
+ /// However as this limit is somewhat easy to hit with template
+ /// metaprogramming we'd prefer to keep it as large as possible.
+ /// At the moment it has been left as a non-bitfield since this type
+ /// safely fits in 64 bits as an unsigned, so there is no reason to
+ /// introduce the performance impact of a bitfield.
+ unsigned NumArgs;
+ };
+
+ class TemplateSpecializationTypeBitfields {
+ friend class TemplateSpecializationType;
+
+ unsigned : NumTypeBits;
+
+ /// Whether this template specialization type is a substituted type alias.
+ unsigned TypeAlias : 1;
+
+ /// The number of template arguments named in this class template
+ /// specialization, which is expected to be able to hold at least 1024
+ /// according to [implimits]. However, as this limit is somewhat easy to
+ /// hit with template metaprogramming we'd prefer to keep it as large
+ /// as possible. At the moment it has been left as a non-bitfield since
+ /// this type safely fits in 64 bits as an unsigned, so there is no reason
+ /// to introduce the performance impact of a bitfield.
+ unsigned NumArgs;
+ };
+
+ class DependentTemplateSpecializationTypeBitfields {
+ friend class DependentTemplateSpecializationType;
+
+ unsigned : NumTypeBits;
+ unsigned : NumTypeWithKeywordBits;
+
+ /// The number of template arguments named in this class template
+ /// specialization, which is expected to be able to hold at least 1024
+ /// according to [implimits]. However, as this limit is somewhat easy to
+ /// hit with template metaprogramming we'd prefer to keep it as large
+ /// as possible. At the moment it has been left as a non-bitfield since
+ /// this type safely fits in 64 bits as an unsigned, so there is no reason
+ /// to introduce the performance impact of a bitfield.
+ unsigned NumArgs;
+ };
+
+ class PackExpansionTypeBitfields {
+ friend class PackExpansionType;
+
+ unsigned : NumTypeBits;
+
+ /// The number of expansions that this pack expansion will
+ /// generate when substituted (+1), which is expected to be able to
+ /// hold at least 1024 according to [implimits]. However, as this limit
+ /// is somewhat easy to hit with template metaprogramming we'd prefer to
+ /// keep it as large as possible. At the moment it has been left as a
+ /// non-bitfield since this type safely fits in 64 bits as an unsigned, so
+ /// there is no reason to introduce the performance impact of a bitfield.
+ ///
+ /// This field will only have a non-zero value when some of the parameter
+ /// packs that occur within the pattern have been substituted but others
+ /// have not.
+ unsigned NumExpansions;
+ };
+
union {
TypeBitfields TypeBits;
ArrayTypeBitfields ArrayTypeBits;
@@ -1633,7 +1713,47 @@ protected:
ObjCObjectTypeBitfields ObjCObjectTypeBits;
ReferenceTypeBitfields ReferenceTypeBits;
TypeWithKeywordBitfields TypeWithKeywordBits;
+ ElaboratedTypeBitfields ElaboratedTypeBits;
VectorTypeBitfields VectorTypeBits;
+ SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits;
+ TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits;
+ DependentTemplateSpecializationTypeBitfields
+ DependentTemplateSpecializationTypeBits;
+ PackExpansionTypeBitfields PackExpansionTypeBits;
+
+ static_assert(sizeof(TypeBitfields) <= 8,
+ "TypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ArrayTypeBitfields) <= 8,
+ "ArrayTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(AttributedTypeBitfields) <= 8,
+ "AttributedTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(AutoTypeBitfields) <= 8,
+ "AutoTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(BuiltinTypeBitfields) <= 8,
+ "BuiltinTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(FunctionTypeBitfields) <= 8,
+ "FunctionTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ObjCObjectTypeBitfields) <= 8,
+ "ObjCObjectTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ReferenceTypeBitfields) <= 8,
+ "ReferenceTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(TypeWithKeywordBitfields) <= 8,
+ "TypeWithKeywordBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ElaboratedTypeBitfields) <= 8,
+ "ElaboratedTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(VectorTypeBitfields) <= 8,
+ "VectorTypeBitfields is larger than 8 bytes!");
+ static_assert(sizeof(SubstTemplateTypeParmPackTypeBitfields) <= 8,
+ "SubstTemplateTypeParmPackTypeBitfields is larger"
+ " than 8 bytes!");
+ static_assert(sizeof(TemplateSpecializationTypeBitfields) <= 8,
+ "TemplateSpecializationTypeBitfields is larger"
+ " than 8 bytes!");
+ static_assert(sizeof(DependentTemplateSpecializationTypeBitfields) <= 8,
+ "DependentTemplateSpecializationTypeBitfields is larger"
+ " than 8 bytes!");
+ static_assert(sizeof(PackExpansionTypeBitfields) <= 8,
+ "PackExpansionTypeBitfields is larger than 8 bytes");
};
private:
@@ -1866,7 +1986,16 @@ public:
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
- bool isObjCInertUnsafeUnretainedType() const;
+
+ /// Was this type written with the special inert-in-ARC __unsafe_unretained
+ /// qualifier?
+ ///
+ /// This approximates the answer to the following question: if this
+ /// translation unit were compiled in ARC, would this type be qualified
+ /// with __unsafe_unretained?
+ bool isObjCInertUnsafeUnretainedType() const {
+ return hasAttr(attr::ObjCInertUnsafeUnretained);
+ }
/// Whether the type is Objective-C 'id' or a __kindof type of an
/// object type, e.g., __kindof NSView * or __kindof id
@@ -1911,6 +2040,13 @@ public:
bool isQueueT() const; // OpenCL queue_t
bool isReserveIDT() const; // OpenCL reserve_id_t
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ bool is##Id##Type() const;
+#include "clang/Basic/OpenCLExtensionTypes.def"
+ // Type defined in cl_intel_device_side_avc_motion_estimation OpenCL extension
+ bool isOCLIntelSubgroupAVCType() const;
+ bool isOCLExtOpaqueType() const; // Any OpenCL extension type
+
bool isPipeType() const; // OpenCL pipe type
bool isOpenCLSpecificType() const; // Any OpenCL specific type
@@ -1931,7 +2067,8 @@ public:
STK_Integral,
STK_Floating,
STK_IntegralComplex,
- STK_FloatingComplex
+ STK_FloatingComplex,
+ STK_FixedPoint
};
/// Given that this is a scalar type, classify it.
@@ -2080,6 +2217,10 @@ public:
/// qualifiers from the outermost type.
const ArrayType *castAsArrayTypeUnsafe() const;
+ /// Determine whether this type had the specified attribute applied to it
+ /// (looking through top-level type sugar).
+ bool hasAttr(attr::Kind AK) const;
+
/// Get the base element type of this type, potentially discarding type
/// qualifiers. This should never be used when type qualifiers
/// are meaningful.
@@ -2253,6 +2394,9 @@ public:
// OpenCL image types
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) Id,
#include "clang/Basic/OpenCLImageTypes.def"
+// OpenCL extension types
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) Id,
+#include "clang/Basic/OpenCLExtensionTypes.def"
// All other builtin types
#define BUILTIN_TYPE(Id, SingletonId) Id,
#define LAST_BUILTIN_TYPE(Id) LastKind = Id
@@ -3213,6 +3357,92 @@ class FunctionType : public Type {
QualType ResultType;
public:
+ /// Interesting information about a specific parameter that can't simply
+ /// be reflected in parameter's type. This is only used by FunctionProtoType
+ /// but is in FunctionType to make this class available during the
+ /// specification of the bases of FunctionProtoType.
+ ///
+ /// It makes sense to model language features this way when there's some
+ /// sort of parameter-specific override (such as an attribute) that
+ /// affects how the function is called. For example, the ARC ns_consumed
+ /// attribute changes whether a parameter is passed at +0 (the default)
+ /// or +1 (ns_consumed). This must be reflected in the function type,
+ /// but isn't really a change to the parameter type.
+ ///
+ /// One serious disadvantage of modelling language features this way is
+ /// that they generally do not work with language features that attempt
+ /// to destructure types. For example, template argument deduction will
+ /// not be able to match a parameter declared as
+ /// T (*)(U)
+ /// against an argument of type
+ /// void (*)(__attribute__((ns_consumed)) id)
+ /// because the substitution of T=void, U=id into the former will
+ /// not produce the latter.
+ class ExtParameterInfo {
+ enum {
+ ABIMask = 0x0F,
+ IsConsumed = 0x10,
+ HasPassObjSize = 0x20,
+ IsNoEscape = 0x40,
+ };
+ unsigned char Data = 0;
+
+ public:
+ ExtParameterInfo() = default;
+
+ /// Return the ABI treatment of this parameter.
+ ParameterABI getABI() const { return ParameterABI(Data & ABIMask); }
+ ExtParameterInfo withABI(ParameterABI kind) const {
+ ExtParameterInfo copy = *this;
+ copy.Data = (copy.Data & ~ABIMask) | unsigned(kind);
+ return copy;
+ }
+
+ /// Is this parameter considered "consumed" by Objective-C ARC?
+ /// Consumed parameters must have retainable object type.
+ bool isConsumed() const { return (Data & IsConsumed); }
+ ExtParameterInfo withIsConsumed(bool consumed) const {
+ ExtParameterInfo copy = *this;
+ if (consumed)
+ copy.Data |= IsConsumed;
+ else
+ copy.Data &= ~IsConsumed;
+ return copy;
+ }
+
+ bool hasPassObjectSize() const { return Data & HasPassObjSize; }
+ ExtParameterInfo withHasPassObjectSize() const {
+ ExtParameterInfo Copy = *this;
+ Copy.Data |= HasPassObjSize;
+ return Copy;
+ }
+
+ bool isNoEscape() const { return Data & IsNoEscape; }
+ ExtParameterInfo withIsNoEscape(bool NoEscape) const {
+ ExtParameterInfo Copy = *this;
+ if (NoEscape)
+ Copy.Data |= IsNoEscape;
+ else
+ Copy.Data &= ~IsNoEscape;
+ return Copy;
+ }
+
+ unsigned char getOpaqueValue() const { return Data; }
+ static ExtParameterInfo getFromOpaqueValue(unsigned char data) {
+ ExtParameterInfo result;
+ result.Data = data;
+ return result;
+ }
+
+ friend bool operator==(ExtParameterInfo lhs, ExtParameterInfo rhs) {
+ return lhs.Data == rhs.Data;
+ }
+
+ friend bool operator!=(ExtParameterInfo lhs, ExtParameterInfo rhs) {
+ return lhs.Data != rhs.Data;
+ }
+ };
+
/// A class which abstracts out some details necessary for
/// making a call.
///
@@ -3347,6 +3577,22 @@ public:
}
};
+ /// A simple holder for a QualType representing a type in an
+ /// exception specification. Unfortunately needed by FunctionProtoType
+ /// because TrailingObjects cannot handle repeated types.
+ struct ExceptionType { QualType Type; };
+
+ /// A simple holder for various uncommon bits which do not fit in
+ /// FunctionTypeBitfields. Aligned to alignof(void *) to maintain the
+ /// alignment of subsequent objects in TrailingObjects. You must update
+ /// hasExtraBitfields in FunctionProtoType after adding extra data here.
+ struct alignas(void *) FunctionTypeExtraBitfields {
+ /// The number of types in the exception specification.
+ /// A whole unsigned is not needed here and according to
+ /// [implimits] 8 bits would be enough here.
+ unsigned NumExceptionType;
+ };
+
protected:
FunctionType(TypeClass tc, QualType res,
QualType Canonical, bool Dependent,
@@ -3359,7 +3605,9 @@ protected:
FunctionTypeBits.ExtInfo = Info.Bits;
}
- unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
+ Qualifiers getFastTypeQuals() const {
+ return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals);
+ }
public:
QualType getReturnType() const { return ResultType; }
@@ -3374,9 +3622,14 @@ public:
CallingConv getCallConv() const { return getExtInfo().getCC(); }
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
- bool isConst() const { return getTypeQuals() & Qualifiers::Const; }
- bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; }
- bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; }
+
+ static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0,
+ "Const, volatile and restrict are assumed to be a subset of "
+ "the fast qualifiers.");
+
+ bool isConst() const { return getFastTypeQuals().hasConst(); }
+ bool isVolatile() const { return getFastTypeQuals().hasVolatile(); }
+ bool isRestrict() const { return getFastTypeQuals().hasRestrict(); }
/// Determine the type of an expression that calls a function of
/// this type.
@@ -3426,104 +3679,65 @@ public:
/// Represents a prototype with parameter type info, e.g.
/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
-/// parameters, not as having a single void parameter. Such a type can have an
-/// exception specification, but this specification is not part of the canonical
-/// type.
-class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
-public:
- /// Interesting information about a specific parameter that can't simply
- /// be reflected in parameter's type.
- ///
- /// It makes sense to model language features this way when there's some
- /// sort of parameter-specific override (such as an attribute) that
- /// affects how the function is called. For example, the ARC ns_consumed
- /// attribute changes whether a parameter is passed at +0 (the default)
- /// or +1 (ns_consumed). This must be reflected in the function type,
- /// but isn't really a change to the parameter type.
- ///
- /// One serious disadvantage of modelling language features this way is
- /// that they generally do not work with language features that attempt
- /// to destructure types. For example, template argument deduction will
- /// not be able to match a parameter declared as
- /// T (*)(U)
- /// against an argument of type
- /// void (*)(__attribute__((ns_consumed)) id)
- /// because the substitution of T=void, U=id into the former will
- /// not produce the latter.
- class ExtParameterInfo {
- enum {
- ABIMask = 0x0F,
- IsConsumed = 0x10,
- HasPassObjSize = 0x20,
- IsNoEscape = 0x40,
- };
- unsigned char Data = 0;
-
- public:
- ExtParameterInfo() = default;
-
- /// Return the ABI treatment of this parameter.
- ParameterABI getABI() const {
- return ParameterABI(Data & ABIMask);
- }
- ExtParameterInfo withABI(ParameterABI kind) const {
- ExtParameterInfo copy = *this;
- copy.Data = (copy.Data & ~ABIMask) | unsigned(kind);
- return copy;
- }
-
- /// Is this parameter considered "consumed" by Objective-C ARC?
- /// Consumed parameters must have retainable object type.
- bool isConsumed() const {
- return (Data & IsConsumed);
- }
- ExtParameterInfo withIsConsumed(bool consumed) const {
- ExtParameterInfo copy = *this;
- if (consumed) {
- copy.Data |= IsConsumed;
- } else {
- copy.Data &= ~IsConsumed;
- }
- return copy;
- }
-
- bool hasPassObjectSize() const {
- return Data & HasPassObjSize;
- }
- ExtParameterInfo withHasPassObjectSize() const {
- ExtParameterInfo Copy = *this;
- Copy.Data |= HasPassObjSize;
- return Copy;
- }
-
- bool isNoEscape() const {
- return Data & IsNoEscape;
- }
-
- ExtParameterInfo withIsNoEscape(bool NoEscape) const {
- ExtParameterInfo Copy = *this;
- if (NoEscape)
- Copy.Data |= IsNoEscape;
- else
- Copy.Data &= ~IsNoEscape;
- return Copy;
- }
-
- unsigned char getOpaqueValue() const { return Data; }
- static ExtParameterInfo getFromOpaqueValue(unsigned char data) {
- ExtParameterInfo result;
- result.Data = data;
- return result;
- }
+/// parameters, not as having a single void parameter. Such a type can have
+/// an exception specification, but this specification is not part of the
+/// canonical type. FunctionProtoType has several trailing objects, some of
+/// which optional. For more information about the trailing objects see
+/// the first comment inside FunctionProtoType.
+class FunctionProtoType final
+ : public FunctionType,
+ public llvm::FoldingSetNode,
+ private llvm::TrailingObjects<
+ FunctionProtoType, QualType, FunctionType::FunctionTypeExtraBitfields,
+ FunctionType::ExceptionType, Expr *, FunctionDecl *,
+ FunctionType::ExtParameterInfo, Qualifiers> {
+ friend class ASTContext; // ASTContext creates these.
+ friend TrailingObjects;
- friend bool operator==(ExtParameterInfo lhs, ExtParameterInfo rhs) {
- return lhs.Data == rhs.Data;
- }
- friend bool operator!=(ExtParameterInfo lhs, ExtParameterInfo rhs) {
- return lhs.Data != rhs.Data;
- }
- };
+ // FunctionProtoType is followed by several trailing objects, some of
+ // which optional. They are in order:
+ //
+ // * An array of getNumParams() QualType holding the parameter types.
+ // Always present. Note that for the vast majority of FunctionProtoType,
+ // these will be the only trailing objects.
+ //
+ // * Optionally if some extra data is stored in FunctionTypeExtraBitfields
+ // (see FunctionTypeExtraBitfields and FunctionTypeBitfields):
+ // a single FunctionTypeExtraBitfields. Present if and only if
+ // hasExtraBitfields() is true.
+ //
+ // * Optionally exactly one of:
+ // * an array of getNumExceptions() ExceptionType,
+ // * a single Expr *,
+ // * a pair of FunctionDecl *,
+ // * a single FunctionDecl *
+ // used to store information about the various types of exception
+ // specification. See getExceptionSpecSize for the details.
+ //
+ // * Optionally an array of getNumParams() ExtParameterInfo holding
+ // an ExtParameterInfo for each of the parameters. Present if and
+ // only if hasExtParameterInfos() is true.
+ //
+ // * Optionally a Qualifiers object to represent extra qualifiers that can't
+ // be represented by FunctionTypeBitfields.FastTypeQuals. Present if and only
+ // if hasExtQualifiers() is true.
+ //
+ // The optional FunctionTypeExtraBitfields has to be before the data
+ // related to the exception specification since it contains the number
+ // of exception types.
+ //
+ // We put the ExtParameterInfos last. If all were equal, it would make
+ // more sense to put these before the exception specification, because
+ // it's much easier to skip past them compared to the elaborate switch
+ // required to skip the exception specification. However, all is not
+ // equal; ExtParameterInfos are used to model very uncommon features,
+ // and it's better not to burden the more common paths.
+public:
+ /// Holds information about the various types of exception specification.
+ /// ExceptionSpecInfo is not stored as such in FunctionProtoType but is
+ /// used to group together the various bits of information about the
+ /// exception specification.
struct ExceptionSpecInfo {
/// The kind of exception specification this is.
ExceptionSpecificationType Type = EST_None;
@@ -3547,31 +3761,54 @@ public:
ExceptionSpecInfo(ExceptionSpecificationType EST) : Type(EST) {}
};
- /// Extra information about a function prototype.
+ /// Extra information about a function prototype. ExtProtoInfo is not
+ /// stored as such in FunctionProtoType but is used to group together
+ /// the various bits of extra information about a function prototype.
struct ExtProtoInfo {
FunctionType::ExtInfo ExtInfo;
bool Variadic : 1;
bool HasTrailingReturn : 1;
- unsigned char TypeQuals = 0;
+ Qualifiers TypeQuals;
RefQualifierKind RefQualifier = RQ_None;
ExceptionSpecInfo ExceptionSpec;
const ExtParameterInfo *ExtParameterInfos = nullptr;
- ExtProtoInfo()
- : Variadic(false), HasTrailingReturn(false) {}
+ ExtProtoInfo() : Variadic(false), HasTrailingReturn(false) {}
ExtProtoInfo(CallingConv CC)
: ExtInfo(CC), Variadic(false), HasTrailingReturn(false) {}
- ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) {
+ ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &ESI) {
ExtProtoInfo Result(*this);
- Result.ExceptionSpec = O;
+ Result.ExceptionSpec = ESI;
return Result;
}
};
private:
- friend class ASTContext; // ASTContext creates these.
+ unsigned numTrailingObjects(OverloadToken<QualType>) const {
+ return getNumParams();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<FunctionTypeExtraBitfields>) const {
+ return hasExtraBitfields();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<ExceptionType>) const {
+ return getExceptionSpecSize().NumExceptionType;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<Expr *>) const {
+ return getExceptionSpecSize().NumExprPtr;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<FunctionDecl *>) const {
+ return getExceptionSpecSize().NumFunctionDeclPtr;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
+ return hasExtParameterInfos() ? getNumParams() : 0;
+ }
/// Determine whether there are any argument types that
/// contain an unexpanded parameter pack.
@@ -3587,88 +3824,71 @@ private:
FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType canonical, const ExtProtoInfo &epi);
- /// The number of parameters this function has, not counting '...'.
- unsigned NumParams : 15;
-
- /// The number of types in the exception spec, if any.
- unsigned NumExceptions : 9;
-
- /// The type of exception specification this function has.
- unsigned ExceptionSpecType : 4;
-
- /// Whether this function has extended parameter information.
- unsigned HasExtParameterInfos : 1;
-
- /// Whether the function is variadic.
- unsigned Variadic : 1;
-
- /// Whether this function has a trailing return type.
- unsigned HasTrailingReturn : 1;
-
- // ParamInfo - There is an variable size array after the class in memory that
- // holds the parameter types.
-
- // Exceptions - There is another variable size array after ArgInfo that
- // holds the exception types.
-
- // NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing
- // to the expression in the noexcept() specifier.
-
- // ExceptionSpecDecl, ExceptionSpecTemplate - Instead of Exceptions, there may
- // be a pair of FunctionDecl* pointing to the function which should be used to
- // instantiate this function type's exception specification, and the function
- // from which it should be instantiated.
-
- // ExtParameterInfos - A variable size array, following the exception
- // specification and of length NumParams, holding an ExtParameterInfo
- // for each of the parameters. This only appears if HasExtParameterInfos
- // is true.
-
- const ExtParameterInfo *getExtParameterInfosBuffer() const {
- assert(hasExtParameterInfos());
-
- // Find the end of the exception specification.
- const auto *ptr = reinterpret_cast<const char *>(exception_begin());
- ptr += getExceptionSpecSize();
-
- return reinterpret_cast<const ExtParameterInfo *>(ptr);
- }
+ /// This struct is returned by getExceptionSpecSize and is used to
+ /// translate an ExceptionSpecificationType to the number and kind
+ /// of trailing objects related to the exception specification.
+ struct ExceptionSpecSizeHolder {
+ unsigned NumExceptionType;
+ unsigned NumExprPtr;
+ unsigned NumFunctionDeclPtr;
+ };
- static size_t getExceptionSpecSize(ExceptionSpecificationType EST,
- unsigned NumExceptions) {
+ /// Return the number and kind of trailing objects
+ /// related to the exception specification.
+ static ExceptionSpecSizeHolder
+ getExceptionSpecSize(ExceptionSpecificationType EST, unsigned NumExceptions) {
switch (EST) {
case EST_None:
case EST_DynamicNone:
case EST_MSAny:
case EST_BasicNoexcept:
case EST_Unparsed:
- return 0;
+ return {0, 0, 0};
case EST_Dynamic:
- return NumExceptions * sizeof(QualType);
+ return {NumExceptions, 0, 0};
case EST_DependentNoexcept:
case EST_NoexceptFalse:
case EST_NoexceptTrue:
- return sizeof(Expr *);
+ return {0, 1, 0};
case EST_Uninstantiated:
- return 2 * sizeof(FunctionDecl *);
+ return {0, 0, 2};
case EST_Unevaluated:
- return sizeof(FunctionDecl *);
+ return {0, 0, 1};
}
llvm_unreachable("bad exception specification kind");
}
- size_t getExceptionSpecSize() const {
+
+ /// Return the number and kind of trailing objects
+ /// related to the exception specification.
+ ExceptionSpecSizeHolder getExceptionSpecSize() const {
return getExceptionSpecSize(getExceptionSpecType(), getNumExceptions());
}
+ /// Whether the trailing FunctionTypeExtraBitfields is present.
+ static bool hasExtraBitfields(ExceptionSpecificationType EST) {
+ // If the exception spec type is EST_Dynamic then we have > 0 exception
+ // types and the exact number is stored in FunctionTypeExtraBitfields.
+ return EST == EST_Dynamic;
+ }
+
+ /// Whether the trailing FunctionTypeExtraBitfields is present.
+ bool hasExtraBitfields() const {
+ return hasExtraBitfields(getExceptionSpecType());
+ }
+
+ bool hasExtQualifiers() const {
+ return FunctionTypeBits.HasExtQuals;
+ }
+
public:
- unsigned getNumParams() const { return NumParams; }
+ unsigned getNumParams() const { return FunctionTypeBits.NumParams; }
QualType getParamType(unsigned i) const {
- assert(i < NumParams && "invalid parameter index");
+ assert(i < getNumParams() && "invalid parameter index");
return param_type_begin()[i];
}
@@ -3682,7 +3902,7 @@ public:
EPI.Variadic = isVariadic();
EPI.HasTrailingReturn = hasTrailingReturn();
EPI.ExceptionSpec.Type = getExceptionSpecType();
- EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
+ EPI.TypeQuals = getTypeQuals();
EPI.RefQualifier = getRefQualifier();
if (EPI.ExceptionSpec.Type == EST_Dynamic) {
EPI.ExceptionSpec.Exceptions = exceptions();
@@ -3694,20 +3914,18 @@ public:
} else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
}
- if (hasExtParameterInfos())
- EPI.ExtParameterInfos = getExtParameterInfosBuffer();
+ EPI.ExtParameterInfos = getExtParameterInfosOrNull();
return EPI;
}
/// Get the kind of exception specification on this function.
ExceptionSpecificationType getExceptionSpecType() const {
- return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
+ return static_cast<ExceptionSpecificationType>(
+ FunctionTypeBits.ExceptionSpecType);
}
/// Return whether this function has any kind of exception spec.
- bool hasExceptionSpec() const {
- return getExceptionSpecType() != EST_None;
- }
+ bool hasExceptionSpec() const { return getExceptionSpecType() != EST_None; }
/// Return whether this function has a dynamic (throw) exception spec.
bool hasDynamicExceptionSpec() const {
@@ -3726,16 +3944,26 @@ public:
/// spec.
bool hasInstantiationDependentExceptionSpec() const;
- unsigned getNumExceptions() const { return NumExceptions; }
+ /// Return the number of types in the exception specification.
+ unsigned getNumExceptions() const {
+ return getExceptionSpecType() == EST_Dynamic
+ ? getTrailingObjects<FunctionTypeExtraBitfields>()
+ ->NumExceptionType
+ : 0;
+ }
+
+ /// Return the ith exception type, where 0 <= i < getNumExceptions().
QualType getExceptionType(unsigned i) const {
- assert(i < NumExceptions && "Invalid exception number!");
+ assert(i < getNumExceptions() && "Invalid exception number!");
return exception_begin()[i];
}
+
+ /// Return the expression inside noexcept(expression), or a null pointer
+ /// if there is none (because the exception spec is not of this form).
Expr *getNoexceptExpr() const {
if (!isComputedNoexcept(getExceptionSpecType()))
return nullptr;
- // NoexceptExpr sits where the arguments end.
- return *reinterpret_cast<Expr *const *>(param_type_end());
+ return *getTrailingObjects<Expr *>();
}
/// If this function type has an exception specification which hasn't
@@ -3746,7 +3974,7 @@ public:
if (getExceptionSpecType() != EST_Uninstantiated &&
getExceptionSpecType() != EST_Unevaluated)
return nullptr;
- return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0];
+ return getTrailingObjects<FunctionDecl *>()[0];
}
/// If this function type has an uninstantiated exception
@@ -3756,7 +3984,7 @@ public:
FunctionDecl *getExceptionSpecTemplate() const {
if (getExceptionSpecType() != EST_Uninstantiated)
return nullptr;
- return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1];
+ return getTrailingObjects<FunctionDecl *>()[1];
}
/// Determine whether this function type has a non-throwing exception
@@ -3767,11 +3995,11 @@ public:
/// specification. If this depends on template arguments, returns
/// \c ResultIfDependent.
bool isNothrow(bool ResultIfDependent = false) const {
- return ResultIfDependent ? canThrow() != CT_Can
- : canThrow() == CT_Cannot;
+ return ResultIfDependent ? canThrow() != CT_Can : canThrow() == CT_Cannot;
}
- bool isVariadic() const { return Variadic; }
+ /// Whether this function prototype is variadic.
+ bool isVariadic() const { return FunctionTypeBits.Variadic; }
/// Determines whether this function prototype contains a
/// parameter pack at the end.
@@ -3781,9 +4009,15 @@ public:
/// function.
bool isTemplateVariadic() const;
- bool hasTrailingReturn() const { return HasTrailingReturn; }
+ /// Whether this function prototype has a trailing return type.
+ bool hasTrailingReturn() const { return FunctionTypeBits.HasTrailingReturn; }
- unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
+ Qualifiers getTypeQuals() const {
+ if (hasExtQualifiers())
+ return *getTrailingObjects<Qualifiers>();
+ else
+ return getFastTypeQuals();
+ }
/// Retrieve the ref-qualifier associated with this function type.
RefQualifierKind getRefQualifier() const {
@@ -3798,11 +4032,11 @@ public:
}
param_type_iterator param_type_begin() const {
- return reinterpret_cast<const QualType *>(this+1);
+ return getTrailingObjects<QualType>();
}
param_type_iterator param_type_end() const {
- return param_type_begin() + NumParams;
+ return param_type_begin() + getNumParams();
}
using exception_iterator = const QualType *;
@@ -3812,22 +4046,23 @@ public:
}
exception_iterator exception_begin() const {
- // exceptions begin where arguments end
- return param_type_end();
+ return reinterpret_cast<exception_iterator>(
+ getTrailingObjects<ExceptionType>());
}
exception_iterator exception_end() const {
- if (getExceptionSpecType() != EST_Dynamic)
- return exception_begin();
- return exception_begin() + NumExceptions;
+ return exception_begin() + getNumExceptions();
}
/// Is there any interesting extra information for any of the parameters
/// of this function type?
- bool hasExtParameterInfos() const { return HasExtParameterInfos; }
+ bool hasExtParameterInfos() const {
+ return FunctionTypeBits.HasExtParameterInfos;
+ }
+
ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
assert(hasExtParameterInfos());
- return ArrayRef<ExtParameterInfo>(getExtParameterInfosBuffer(),
+ return ArrayRef<ExtParameterInfo>(getTrailingObjects<ExtParameterInfo>(),
getNumParams());
}
@@ -3837,27 +4072,27 @@ public:
const ExtParameterInfo *getExtParameterInfosOrNull() const {
if (!hasExtParameterInfos())
return nullptr;
- return getExtParameterInfosBuffer();
+ return getTrailingObjects<ExtParameterInfo>();
}
ExtParameterInfo getExtParameterInfo(unsigned I) const {
assert(I < getNumParams() && "parameter index out of range");
if (hasExtParameterInfos())
- return getExtParameterInfosBuffer()[I];
+ return getTrailingObjects<ExtParameterInfo>()[I];
return ExtParameterInfo();
}
ParameterABI getParameterABI(unsigned I) const {
assert(I < getNumParams() && "parameter index out of range");
if (hasExtParameterInfos())
- return getExtParameterInfosBuffer()[I].getABI();
+ return getTrailingObjects<ExtParameterInfo>()[I].getABI();
return ParameterABI::Ordinary;
}
bool isParamConsumed(unsigned I) const {
assert(I < getNumParams() && "parameter index out of range");
if (hasExtParameterInfos())
- return getExtParameterInfosBuffer()[I].isConsumed();
+ return getTrailingObjects<ExtParameterInfo>()[I].isConsumed();
return false;
}
@@ -4189,56 +4424,7 @@ public:
/// - the canonical type is VectorType(16, int)
class AttributedType : public Type, public llvm::FoldingSetNode {
public:
- // It is really silly to have yet another attribute-kind enum, but
- // clang::attr::Kind doesn't currently cover the pure type attrs.
- enum Kind {
- // Expression operand.
- attr_address_space,
- attr_regparm,
- attr_vector_size,
- attr_neon_vector_type,
- attr_neon_polyvector_type,
-
- FirstExprOperandKind = attr_address_space,
- LastExprOperandKind = attr_neon_polyvector_type,
-
- // Enumerated operand (string or keyword).
- attr_objc_gc,
- attr_objc_ownership,
- attr_pcs,
- attr_pcs_vfp,
-
- FirstEnumOperandKind = attr_objc_gc,
- LastEnumOperandKind = attr_pcs_vfp,
-
- // No operand.
- attr_noreturn,
- attr_nocf_check,
- attr_cdecl,
- attr_fastcall,
- attr_stdcall,
- attr_thiscall,
- attr_regcall,
- attr_pascal,
- attr_swiftcall,
- attr_vectorcall,
- attr_inteloclbicc,
- attr_ms_abi,
- attr_sysv_abi,
- attr_preserve_most,
- attr_preserve_all,
- attr_ptr32,
- attr_ptr64,
- attr_sptr,
- attr_uptr,
- attr_nonnull,
- attr_ns_returns_retained,
- attr_nullable,
- attr_null_unspecified,
- attr_objc_kindof,
- attr_objc_inert_unsafe_unretained,
- attr_lifetimebound,
- };
+ using Kind = attr::Kind;
private:
friend class ASTContext; // ASTContext creates these
@@ -4246,7 +4432,7 @@ private:
QualType ModifiedType;
QualType EquivalentType;
- AttributedType(QualType canon, Kind attrKind, QualType modified,
+ AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
QualType equivalent)
: Type(Attributed, canon, equivalent->isDependentType(),
equivalent->isInstantiationDependentType(),
@@ -4295,13 +4481,13 @@ public:
static Kind getNullabilityAttrKind(NullabilityKind kind) {
switch (kind) {
case NullabilityKind::NonNull:
- return attr_nonnull;
+ return attr::TypeNonNull;
case NullabilityKind::Nullable:
- return attr_nullable;
+ return attr::TypeNullable;
case NullabilityKind::Unspecified:
- return attr_null_unspecified;
+ return attr::TypeNullUnspecified;
}
llvm_unreachable("Unknown nullability kind.");
}
@@ -4480,9 +4666,6 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
/// parameter pack is instantiated with.
const TemplateArgument *Arguments;
- /// The number of template arguments in \c Arguments.
- unsigned NumArguments;
-
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
QualType Canon,
const TemplateArgument &ArgPack);
@@ -4495,6 +4678,10 @@ public:
return Replaced;
}
+ unsigned getNumArgs() const {
+ return SubstTemplateTypeParmPackTypeBits.NumArgs;
+ }
+
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -4665,13 +4852,6 @@ class alignas(8) TemplateSpecializationType
/// replacement must, recursively, be one of these).
TemplateName Template;
- /// The number of template arguments named in this class template
- /// specialization.
- unsigned NumArgs : 31;
-
- /// Whether this template specialization type is a substituted type alias.
- unsigned TypeAlias : 1;
-
TemplateSpecializationType(TemplateName T,
ArrayRef<TemplateArgument> Args,
QualType Canon,
@@ -4706,7 +4886,7 @@ public:
/// typedef A<Ts...> type; // not a type alias
/// };
/// \endcode
- bool isTypeAlias() const { return TypeAlias; }
+ bool isTypeAlias() const { return TemplateSpecializationTypeBits.TypeAlias; }
/// Get the aliased type, if this is a specialization of a type alias
/// template.
@@ -4729,21 +4909,25 @@ public:
}
/// Retrieve the number of template arguments.
- unsigned getNumArgs() const { return NumArgs; }
+ unsigned getNumArgs() const {
+ return TemplateSpecializationTypeBits.NumArgs;
+ }
/// Retrieve a specific template argument as a type.
/// \pre \c isArgType(Arg)
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
ArrayRef<TemplateArgument> template_arguments() const {
- return {getArgs(), NumArgs};
+ return {getArgs(), getNumArgs()};
}
bool isSugared() const {
return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
}
- QualType desugar() const { return getCanonicalTypeInternal(); }
+ QualType desugar() const {
+ return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal();
+ }
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
Profile(ID, Template, template_arguments(), Ctx);
@@ -4942,8 +5126,12 @@ public:
/// source code, including tag keywords and any nested-name-specifiers.
/// The type itself is always "sugar", used to express what was written
/// in the source code but containing no additional semantic information.
-class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
+class ElaboratedType final
+ : public TypeWithKeyword,
+ public llvm::FoldingSetNode,
+ private llvm::TrailingObjects<ElaboratedType, TagDecl *> {
friend class ASTContext; // ASTContext creates these
+ friend TrailingObjects;
/// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
@@ -4951,26 +5139,29 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
/// The type that this qualified name refers to.
QualType NamedType;
- /// The (re)declaration of this tag type owned by this occurrence, or nullptr
- /// if none.
- TagDecl *OwnedTagDecl;
+ /// The (re)declaration of this tag type owned by this occurrence is stored
+ /// as a trailing object if there is one. Use getOwnedTagDecl to obtain
+ /// it, or obtain a null pointer if there is none.
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl)
- : TypeWithKeyword(Keyword, Elaborated, CanonType,
- NamedType->isDependentType(),
- NamedType->isInstantiationDependentType(),
- NamedType->isVariablyModifiedType(),
- NamedType->containsUnexpandedParameterPack()),
- NNS(NNS), NamedType(NamedType), OwnedTagDecl(OwnedTagDecl) {
+ : TypeWithKeyword(Keyword, Elaborated, CanonType,
+ NamedType->isDependentType(),
+ NamedType->isInstantiationDependentType(),
+ NamedType->isVariablyModifiedType(),
+ NamedType->containsUnexpandedParameterPack()),
+ NNS(NNS), NamedType(NamedType) {
+ ElaboratedTypeBits.HasOwnedTagDecl = false;
+ if (OwnedTagDecl) {
+ ElaboratedTypeBits.HasOwnedTagDecl = true;
+ *getTrailingObjects<TagDecl *>() = OwnedTagDecl;
+ }
assert(!(Keyword == ETK_None && NNS == nullptr) &&
"ElaboratedType cannot have elaborated type keyword "
"and name qualifier both null.");
}
public:
- ~ElaboratedType();
-
/// Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
@@ -4984,11 +5175,14 @@ public:
bool isSugared() const { return true; }
/// Return the (re)declaration of this type owned by this occurrence of this
- /// type, or nullptr if none.
- TagDecl *getOwnedTagDecl() const { return OwnedTagDecl; }
+ /// type, or nullptr if there is none.
+ TagDecl *getOwnedTagDecl() const {
+ return ElaboratedTypeBits.HasOwnedTagDecl ? *getTrailingObjects<TagDecl *>()
+ : nullptr;
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getKeyword(), NNS, NamedType, OwnedTagDecl);
+ Profile(ID, getKeyword(), NNS, NamedType, getOwnedTagDecl());
}
static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword,
@@ -5000,9 +5194,7 @@ public:
ID.AddPointer(OwnedTagDecl);
}
- static bool classof(const Type *T) {
- return T->getTypeClass() == Elaborated;
- }
+ static bool classof(const Type *T) { return T->getTypeClass() == Elaborated; }
};
/// Represents a qualified type name for which the type name is
@@ -5080,10 +5272,6 @@ class alignas(8) DependentTemplateSpecializationType
/// The identifier of the template.
const IdentifierInfo *Name;
- /// The number of template arguments named in this class template
- /// specialization.
- unsigned NumArgs;
-
DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
@@ -5108,12 +5296,14 @@ public:
}
/// Retrieve the number of template arguments.
- unsigned getNumArgs() const { return NumArgs; }
+ unsigned getNumArgs() const {
+ return DependentTemplateSpecializationTypeBits.NumArgs;
+ }
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
ArrayRef<TemplateArgument> template_arguments() const {
- return {getArgs(), NumArgs};
+ return {getArgs(), getNumArgs()};
}
using iterator = const TemplateArgument *;
@@ -5125,7 +5315,7 @@ public:
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
- Profile(ID, Context, getKeyword(), NNS, Name, {getArgs(), NumArgs});
+ Profile(ID, Context, getKeyword(), NNS, Name, {getArgs(), getNumArgs()});
}
static void Profile(llvm::FoldingSetNodeID &ID,
@@ -5168,22 +5358,16 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
/// The pattern of the pack expansion.
QualType Pattern;
- /// The number of expansions that this pack expansion will
- /// generate when substituted (+1), or indicates that
- ///
- /// This field will only have a non-zero value when some of the parameter
- /// packs that occur within the pattern have been substituted but others have
- /// not.
- unsigned NumExpansions;
-
PackExpansionType(QualType Pattern, QualType Canon,
Optional<unsigned> NumExpansions)
: Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(),
/*InstantiationDependent=*/true,
/*VariablyModified=*/Pattern->isVariablyModifiedType(),
/*ContainsUnexpandedParameterPack=*/false),
- Pattern(Pattern),
- NumExpansions(NumExpansions ? *NumExpansions + 1 : 0) {}
+ Pattern(Pattern) {
+ PackExpansionTypeBits.NumExpansions =
+ NumExpansions ? *NumExpansions + 1 : 0;
+ }
public:
/// Retrieve the pattern of this pack expansion, which is the
@@ -5194,9 +5378,8 @@ public:
/// Retrieve the number of expansions that this pack expansion will
/// generate, if known.
Optional<unsigned> getNumExpansions() const {
- if (NumExpansions)
- return NumExpansions - 1;
-
+ if (PackExpansionTypeBits.NumExpansions)
+ return PackExpansionTypeBits.NumExpansions - 1;
return None;
}
@@ -6295,9 +6478,30 @@ inline bool Type::isPipeType() const {
return isa<PipeType>(CanonicalType);
}
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ inline bool Type::is##Id##Type() const { \
+ return isSpecificBuiltinType(BuiltinType::Id); \
+ }
+#include "clang/Basic/OpenCLExtensionTypes.def"
+
+inline bool Type::isOCLIntelSubgroupAVCType() const {
+#define INTEL_SUBGROUP_AVC_TYPE(ExtType, Id) \
+ isOCLIntelSubgroupAVC##Id##Type() ||
+ return
+#include "clang/Basic/OpenCLExtensionTypes.def"
+ false; // end of boolean or operation
+}
+
+inline bool Type::isOCLExtOpaqueType() const {
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) is##Id##Type() ||
+ return
+#include "clang/Basic/OpenCLExtensionTypes.def"
+ false; // end of boolean or operation
+}
+
inline bool Type::isOpenCLSpecificType() const {
return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
- isQueueT() || isReserveIDT() || isPipeType();
+ isQueueT() || isReserveIDT() || isPipeType() || isOCLExtOpaqueType();
}
inline bool Type::isTemplateTypeParmType() const {
@@ -6497,6 +6701,24 @@ inline const Type *Type::getPointeeOrArrayElementType() const {
return type;
}
+/// Insertion operator for diagnostics. This allows sending Qualifiers into a
+/// diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ Qualifiers Q) {
+ DB.AddTaggedVal(Q.getAsOpaqueValue(),
+ DiagnosticsEngine::ArgumentKind::ak_qual);
+ return DB;
+}
+
+/// Insertion operator for partial diagnostics. This allows sending Qualifiers
+/// into a diagnostic with <<.
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ Qualifiers Q) {
+ PD.AddTaggedVal(Q.getAsOpaqueValue(),
+ DiagnosticsEngine::ArgumentKind::ak_qual);
+ return PD;
+}
+
/// Insertion operator for diagnostics. This allows sending QualType's into a
/// diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -6619,9 +6841,8 @@ QualType DecayedType::getPointeeType() const {
// Get the decimal string representation of a fixed point type, represented
// as a scaled integer.
-void FixedPointValueToString(SmallVectorImpl<char> &Str,
- const llvm::APSInt &Val,
- unsigned Scale, unsigned Radix);
+void FixedPointValueToString(SmallVectorImpl<char> &Str, llvm::APSInt Val,
+ unsigned Scale);
} // namespace clang
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index c69f4aa4abcf..1e89e9386719 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_AST_TYPELOC_H
#define LLVM_CLANG_AST_TYPELOC_H
+#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
@@ -151,8 +152,6 @@ public:
return SourceRange(getBeginLoc(), getEndLoc());
}
- SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
/// Get the local source range.
SourceRange getLocalSourceRange() const {
@@ -843,16 +842,7 @@ class SubstTemplateTypeParmPackTypeLoc :
};
struct AttributedLocInfo {
- union {
- Expr *ExprOperand;
-
- /// A raw SourceLocation.
- unsigned EnumOperandLoc;
- };
-
- SourceRange OperandParens;
-
- SourceLocation AttrLoc;
+ const Attr *TypeAttr;
};
/// Type source information for an attributed type.
@@ -861,24 +851,10 @@ class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
AttributedType,
AttributedLocInfo> {
public:
- AttributedType::Kind getAttrKind() const {
+ attr::Kind getAttrKind() const {
return getTypePtr()->getAttrKind();
}
- bool hasAttrExprOperand() const {
- return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
- getAttrKind() <= AttributedType::LastExprOperandKind);
- }
-
- bool hasAttrEnumOperand() const {
- return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
- getAttrKind() <= AttributedType::LastEnumOperandKind);
- }
-
- bool hasAttrOperand() const {
- return hasAttrExprOperand() || hasAttrEnumOperand();
- }
-
bool isQualifier() const {
return getTypePtr()->isQualifier();
}
@@ -891,51 +867,16 @@ public:
return getInnerTypeLoc();
}
- /// The location of the attribute name, i.e.
- /// __attribute__((regparm(1000)))
- /// ^~~~~~~
- SourceLocation getAttrNameLoc() const {
- return getLocalData()->AttrLoc;
+ /// The type attribute.
+ const Attr *getAttr() const {
+ return getLocalData()->TypeAttr;
}
- void setAttrNameLoc(SourceLocation loc) {
- getLocalData()->AttrLoc = loc;
+ void setAttr(const Attr *A) {
+ getLocalData()->TypeAttr = A;
}
- /// The attribute's expression operand, if it has one.
- /// void *cur_thread __attribute__((address_space(21)))
- /// ^~
- Expr *getAttrExprOperand() const {
- assert(hasAttrExprOperand());
- return getLocalData()->ExprOperand;
- }
- void setAttrExprOperand(Expr *e) {
- assert(hasAttrExprOperand());
- getLocalData()->ExprOperand = e;
- }
-
- /// The location of the attribute's enumerated operand, if it has one.
- /// void * __attribute__((objc_gc(weak)))
- /// ^~~~
- SourceLocation getAttrEnumOperandLoc() const {
- assert(hasAttrEnumOperand());
- return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
- }
- void setAttrEnumOperandLoc(SourceLocation loc) {
- assert(hasAttrEnumOperand());
- getLocalData()->EnumOperandLoc = loc.getRawEncoding();
- }
-
- /// The location of the parentheses around the operand, if there is
- /// an operand.
- /// void * __attribute__((objc_gc(weak)))
- /// ^ ^
- SourceRange getAttrOperandParensRange() const {
- assert(hasAttrOperand());
- return getLocalData()->OperandParens;
- }
- void setAttrOperandParensRange(SourceRange range) {
- assert(hasAttrOperand());
- getLocalData()->OperandParens = range;
+ template<typename T> const T *getAttrAs() {
+ return dyn_cast_or_null<T>(getAttr());
}
SourceRange getLocalSourceRange() const {
@@ -948,21 +889,11 @@ public:
// ^~ ~~
// That enclosure doesn't necessarily belong to a single attribute
// anyway.
- SourceRange range(getAttrNameLoc());
- if (hasAttrOperand())
- range.setEnd(getAttrOperandParensRange().getEnd());
- return range;
+ return getAttr() ? getAttr()->getRange() : SourceRange();
}
void initializeLocal(ASTContext &Context, SourceLocation loc) {
- setAttrNameLoc(loc);
- if (hasAttrExprOperand()) {
- setAttrOperandParensRange(SourceRange(loc));
- setAttrExprOperand(nullptr);
- } else if (hasAttrEnumOperand()) {
- setAttrOperandParensRange(SourceRange(loc));
- setAttrEnumOperandLoc(loc);
- }
+ setAttr(nullptr);
}
QualType getInnerType() const {
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 51f2ce2af75c..5cdb964a92c2 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -245,7 +245,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) {
auto &SourceManager = Finder->getASTContext().getSourceManager();
return SourceManager.isInMainFile(
- SourceManager.getExpansionLoc(Node.getLocStart()));
+ SourceManager.getExpansionLoc(Node.getBeginLoc()));
}
/// Matches AST nodes that were expanded within system-header-files.
@@ -265,7 +265,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) {
auto &SourceManager = Finder->getASTContext().getSourceManager();
- auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getBeginLoc());
if (ExpansionLoc.isInvalid()) {
return false;
}
@@ -291,7 +291,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc),
std::string, RegExp) {
auto &SourceManager = Finder->getASTContext().getSourceManager();
- auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getBeginLoc());
if (ExpansionLoc.isInvalid()) {
return false;
}
@@ -420,6 +420,25 @@ extern const internal::VariadicDynCastAllOfMatcher<
Decl, ClassTemplateSpecializationDecl>
classTemplateSpecializationDecl;
+/// Matches C++ class template partial specializations.
+///
+/// Given
+/// \code
+/// template<class T1, class T2, int I>
+/// class A {};
+///
+/// template<class T, int I>
+/// class A<T, T*, I> {};
+///
+/// template<>
+/// class A<int, int, 1> {};
+/// \endcode
+/// classTemplatePartialSpecializationDecl()
+/// matches the specialization \c A<T,T*,I> but not \c A<int,int,1>
+extern const internal::VariadicDynCastAllOfMatcher<
+ Decl, ClassTemplatePartialSpecializationDecl>
+ classTemplatePartialSpecializationDecl;
+
/// Matches declarator declarations (field, variable, function
/// and non-type template parameter declarations).
///
@@ -626,12 +645,12 @@ AST_MATCHER(FunctionDecl, isMain) {
///
/// Given
/// \code
-/// tempalate<typename T> class A {};
-/// typedef A<int> B;
+/// template<typename T> class A {}; #1
+/// template<> class A<int> {}; #2
/// \endcode
/// classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl()))
-/// matches 'B' with classTemplateDecl() matching the class template
-/// declaration of 'A'.
+/// matches '#2' with classTemplateDecl() matching the class template
+/// declaration of 'A' at #1.
AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate,
internal::Matcher<ClassTemplateDecl>, InnerMatcher) {
const ClassTemplateDecl* Decl = Node.getSpecializedTemplate();
@@ -792,11 +811,70 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts,
/// varDecl(hasType(pointerType(pointee(ignoringParens(functionType())))))
/// \endcode
/// would match the declaration for fp.
-AST_MATCHER_P(QualType, ignoringParens,
- internal::Matcher<QualType>, InnerMatcher) {
+AST_MATCHER_P_OVERLOAD(QualType, ignoringParens, internal::Matcher<QualType>,
+ InnerMatcher, 0) {
return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder);
}
+/// Overload \c ignoringParens for \c Expr.
+///
+/// Given
+/// \code
+/// const char* str = ("my-string");
+/// \endcode
+/// The matcher
+/// \code
+/// implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))
+/// \endcode
+/// would match the implicit cast resulting from the assignment.
+AST_MATCHER_P_OVERLOAD(Expr, ignoringParens, internal::Matcher<Expr>,
+ InnerMatcher, 1) {
+ const Expr *E = Node.IgnoreParens();
+ return InnerMatcher.matches(*E, Finder, Builder);
+}
+
+/// Matches expressions that are instantiation-dependent even if it is
+/// neither type- nor value-dependent.
+///
+/// In the following example, the expression sizeof(sizeof(T() + T()))
+/// is instantiation-dependent (since it involves a template parameter T),
+/// but is neither type- nor value-dependent, since the type of the inner
+/// sizeof is known (std::size_t) and therefore the size of the outer
+/// sizeof is known.
+/// \code
+/// template<typename T>
+/// void f(T x, T y) { sizeof(sizeof(T() + T()); }
+/// \endcode
+/// expr(isInstantiationDependent()) matches sizeof(sizeof(T() + T())
+AST_MATCHER(Expr, isInstantiationDependent) {
+ return Node.isInstantiationDependent();
+}
+
+/// Matches expressions that are type-dependent because the template type
+/// is not yet instantiated.
+///
+/// For example, the expressions "x" and "x + y" are type-dependent in
+/// the following code, but "y" is not type-dependent:
+/// \code
+/// template<typename T>
+/// void add(T x, int y) {
+/// x + y;
+/// }
+/// \endcode
+/// expr(isTypeDependent()) matches x + y
+AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); }
+
+/// Matches expression that are value-dependent because they contain a
+/// non-type template parameter.
+///
+/// For example, the array bound of "Chars" in the following example is
+/// value-dependent.
+/// \code
+/// template<int Size> int f() { return Size; }
+/// \endcode
+/// expr(isValueDependent()) matches return Size
+AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
+
/// Matches classTemplateSpecializations, templateSpecializationType and
/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
///
@@ -868,7 +946,7 @@ AST_MATCHER_P(TemplateArgument, refersToType,
/// Given
/// \code
/// template<template <typename> class S> class X {};
-/// template<typename T> class Y {};"
+/// template<typename T> class Y {};
/// X<Y> xi;
/// \endcode
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
@@ -1080,6 +1158,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
/// matches 'm'.
extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
+/// Matches indirect field declarations.
+///
+/// Given
+/// \code
+/// struct X { struct { int a; }; };
+/// \endcode
+/// indirectFieldDecl()
+/// matches 'a'.
+extern const internal::VariadicDynCastAllOfMatcher<Decl, IndirectFieldDecl>
+ indirectFieldDecl;
+
/// Matches function declarations.
///
/// Example matches f
@@ -1141,6 +1230,34 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
/// matches this->x, x, y.x, a, this->b
extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
+/// Matches unresolved member expressions.
+///
+/// Given
+/// \code
+/// struct X {
+/// template <class T> void f();
+/// void g();
+/// };
+/// template <class T> void h() { X x; x.f<T>(); x.g(); }
+/// \endcode
+/// unresolvedMemberExpr()
+/// matches x.f<T>
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedMemberExpr>
+ unresolvedMemberExpr;
+
+/// Matches member expressions where the actual member referenced could not be
+/// resolved because the base expression or the member name was dependent.
+///
+/// Given
+/// \code
+/// template <class T> void f() { T t; t.g(); }
+/// \endcode
+/// cxxDependentScopeMemberExpr()
+/// matches t.g
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+ CXXDependentScopeMemberExpr>
+ cxxDependentScopeMemberExpr;
+
/// Matches call expressions.
///
/// Example matches x.y() and y()
@@ -1151,6 +1268,28 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
+/// Matches call expressions which were resolved using ADL.
+///
+/// Example matches y(x) but not y(42) or NS::y(x).
+/// \code
+/// namespace NS {
+/// struct X {};
+/// void y(X);
+/// }
+///
+/// void y(...);
+///
+/// void test() {
+/// NS::X x;
+/// y(x); // Matches
+/// NS::y(x); // Doesn't match
+/// y(42); // Doesn't match
+/// using NS::y;
+/// y(x); // Found by both unqualified lookup and ADL, doesn't match
+// }
+/// \endcode
+AST_MATCHER(CallExpr, usesADL) { return Node.usesADL(); }
+
/// Matches lambda expressions.
///
/// Example matches [&](){return 5;}
@@ -1485,6 +1624,18 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
UnresolvedUsingTypenameDecl>
unresolvedUsingTypenameDecl;
+/// Matches a constant expression wrapper.
+///
+/// Example matches the constant in the case statement:
+/// (matcher = constantExpr())
+/// \code
+/// switch (a) {
+/// case 37: break;
+/// }
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConstantExpr>
+ constantExpr;
+
/// Matches parentheses used in expressions.
///
/// Example matches (foo() + 1)
@@ -1658,6 +1809,14 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr>
objcIvarRefExpr;
+/// Matches a reference to a block.
+///
+/// Example: matches "^{}":
+/// \code
+/// void f() { ^{}(); }
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, BlockExpr> blockExpr;
+
/// Matches if statements.
///
/// Example matches 'if (x) {}'
@@ -1975,6 +2134,11 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral>
floatLiteral;
+/// Matches imaginary literals, which are based on integer and floating
+/// point literals e.g.: 1i, 1.0i
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral>
+ imaginaryLiteral;
+
/// Matches user defined literal operator call.
///
/// Example match: "foo"_suffix
@@ -2331,8 +2495,9 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
/// alignof.
inline internal::Matcher<Stmt> alignOfExpr(
const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
- return stmt(unaryExprOrTypeTraitExpr(allOf(
- ofKind(UETT_AlignOf), InnerMatcher)));
+ return stmt(unaryExprOrTypeTraitExpr(
+ allOf(anyOf(ofKind(UETT_AlignOf), ofKind(UETT_PreferredAlignOf)),
+ InnerMatcher)));
}
/// Same as unaryExprOrTypeTraitExpr, but only matching
@@ -3205,6 +3370,20 @@ AST_MATCHER_P(
InnerMatcher.matches(*Initializer, Finder, Builder));
}
+/// \brief Matches a static variable with local scope.
+///
+/// Example matches y (matcher = varDecl(isStaticLocal()))
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// }
+/// static int z;
+/// \endcode
+AST_MATCHER(VarDecl, isStaticLocal) {
+ return Node.isStaticLocal();
+}
+
/// Matches a variable declaration that has function scope and is a
/// non-static local variable.
///
@@ -3335,6 +3514,19 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
}
+/// Matches the n'th item of an initializer list expression.
+///
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr())))
+/// \code
+/// int x{y}.
+/// \endcode
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
+ ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+ return N < Node.getNumInits() &&
+ InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
+}
+
/// Matches declaration statements that contain a specific number of
/// declarations.
///
@@ -3390,7 +3582,7 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
/// } catch (...) {
/// // ...
/// }
-/// /endcode
+/// \endcode
/// cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int).
AST_MATCHER(CXXCatchStmt, isCatchAll) {
return Node.getExceptionDecl() == nullptr;
@@ -3532,9 +3724,9 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
/// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
/// matches [i f:12]
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
- AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
- CXXConstructExpr,
- ObjCMessageExpr),
+ AST_POLYMORPHIC_SUPPORTED_TYPES(
+ CallExpr, CXXConstructExpr,
+ CXXUnresolvedConstructExpr, ObjCMessageExpr),
internal::Matcher<Expr>, InnerMatcher) {
for (const Expr *Arg : Node.arguments()) {
BoundNodesTreeBuilder Result(*Builder);
@@ -4603,13 +4795,24 @@ AST_MATCHER(CXXMethodDecl, isUserProvided) {
/// \code
/// class Y {
/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
+/// template <class T> void f() { this->f<T>(); f<T>(); }
/// int a;
/// static int b;
/// };
+/// template <class T>
+/// class Z {
+/// void x() { this->m; }
+/// };
/// \endcode
/// memberExpr(isArrow())
/// matches this->x, x, y.x, a, this->b
-AST_MATCHER(MemberExpr, isArrow) {
+/// cxxDependentScopeMemberExpr(isArrow())
+/// matches this->m
+/// unresolvedMemberExpr(isArrow())
+/// matches this->f<T>, f<T>
+AST_POLYMORPHIC_MATCHER(
+ isArrow, AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr,
+ CXXDependentScopeMemberExpr)) {
return Node.isArrow();
}
@@ -4773,8 +4976,17 @@ AST_MATCHER_P(MemberExpr, member,
/// matches "x.m" and "m"
/// with hasObjectExpression(...)
/// matching "x" and the implicit object expression of "m" which has type X*.
-AST_MATCHER_P(MemberExpr, hasObjectExpression,
- internal::Matcher<Expr>, InnerMatcher) {
+AST_POLYMORPHIC_MATCHER_P(
+ hasObjectExpression,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr,
+ CXXDependentScopeMemberExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ if (const auto *E = dyn_cast<UnresolvedMemberExpr>(&Node))
+ if (E->isImplicitAccess())
+ return false;
+ if (const auto *E = dyn_cast<CXXDependentScopeMemberExpr>(&Node))
+ if (E->isImplicitAccess())
+ return false;
return InnerMatcher.matches(*Node.getBase(), Finder, Builder);
}
@@ -5169,7 +5381,7 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
/// decltype(2.0) b = 2.0;
/// \endcode
/// decltypeType(hasUnderlyingType(isInteger()))
-/// matches "auto a"
+/// matches the type of "a"
///
/// Usable as: Matcher<DecltypeType>
AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType,
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 9d9f867d053a..34851a907e0d 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -261,7 +261,7 @@ public:
}
private:
- SmallVector<BoundNodesMap, 16> Bindings;
+ SmallVector<BoundNodesMap, 1> Bindings;
};
class ASTMatchFinder;
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
index 907db69529d2..136265d32847 100644
--- a/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -234,6 +234,7 @@ private:
const NamedValueMap *NamedValues,
Diagnostics *Error);
+ bool parseBindID(std::string &BindID);
bool parseExpressionImpl(VariantValue *Value);
bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
VariantValue *Value);
diff --git a/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h b/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
new file mode 100644
index 000000000000..edc6e00f1d00
--- /dev/null
+++ b/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
@@ -0,0 +1,96 @@
+//===---------- ExprMutationAnalyzer.h ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
+
+#include <type_traits>
+
+#include "clang/AST/AST.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class FunctionParmMutationAnalyzer;
+
+/// Analyzes whether any mutative operations are applied to an expression within
+/// a given statement.
+class ExprMutationAnalyzer {
+public:
+ ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
+ : Stm(Stm), Context(Context) {}
+
+ bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
+ bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; }
+ const Stmt *findMutation(const Expr *Exp);
+ const Stmt *findMutation(const Decl *Dec);
+
+ bool isPointeeMutated(const Expr *Exp) {
+ return findPointeeMutation(Exp) != nullptr;
+ }
+ bool isPointeeMutated(const Decl *Dec) {
+ return findPointeeMutation(Dec) != nullptr;
+ }
+ const Stmt *findPointeeMutation(const Expr *Exp);
+ const Stmt *findPointeeMutation(const Decl *Dec);
+
+private:
+ using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *);
+ using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
+
+ const Stmt *findMutationMemoized(const Expr *Exp,
+ llvm::ArrayRef<MutationFinder> Finders,
+ ResultMap &MemoizedResults);
+ const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
+
+ bool isUnevaluated(const Expr *Exp);
+
+ const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
+ const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
+ const Stmt *
+ findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
+ const Stmt *
+ findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
+
+ const Stmt *findDirectMutation(const Expr *Exp);
+ const Stmt *findMemberMutation(const Expr *Exp);
+ const Stmt *findArrayElementMutation(const Expr *Exp);
+ const Stmt *findCastMutation(const Expr *Exp);
+ const Stmt *findRangeLoopMutation(const Expr *Exp);
+ const Stmt *findReferenceMutation(const Expr *Exp);
+ const Stmt *findFunctionArgMutation(const Expr *Exp);
+
+ const Stmt &Stm;
+ ASTContext &Context;
+ llvm::DenseMap<const FunctionDecl *,
+ std::unique_ptr<FunctionParmMutationAnalyzer>>
+ FuncParmAnalyzer;
+ ResultMap Results;
+ ResultMap PointeeResults;
+};
+
+// A convenient wrapper around ExprMutationAnalyzer for analyzing function
+// params.
+class FunctionParmMutationAnalyzer {
+public:
+ FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context);
+
+ bool isMutated(const ParmVarDecl *Parm) {
+ return findMutation(Parm) != nullptr;
+ }
+ const Stmt *findMutation(const ParmVarDecl *Parm);
+
+private:
+ ExprMutationAnalyzer BodyAnalyzer;
+ llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 0cb500fffb95..114597661a67 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -88,9 +88,13 @@ public:
/// before the given block-level expression (see runOnAllBlocks).
bool isLive(const Stmt *Loc, const Stmt *StmtVal);
- /// Print to stderr the liveness information associated with
+ /// Print to stderr the variable liveness information associated with
/// each basic block.
- void dumpBlockLiveness(const SourceManager& M);
+ void dumpBlockLiveness(const SourceManager &M);
+
+ /// Print to stderr the statement liveness information associated with
+ /// each basic block.
+ void dumpStmtLiveness(const SourceManager &M);
void runOnAllBlocks(Observer &obs);
diff --git a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
deleted file mode 100644
index c4ec2f22eca0..000000000000
--- a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//== PseudoConstantAnalysis.h - Find Pseudo-constants in the AST -*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file tracks the usage of variables in a Decl body to see if they are
-// never written to, implying that they constant. This is useful in static
-// analysis to see if a developer might have intended a variable to be const.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
-#define LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
-
-#include "clang/AST/Stmt.h"
-
-namespace clang {
-
-class PseudoConstantAnalysis {
-public:
- PseudoConstantAnalysis(const Stmt *DeclBody);
- ~PseudoConstantAnalysis();
-
- bool isPseudoConstant(const VarDecl *VD);
- bool wasReferenced(const VarDecl *VD);
-
-private:
- void RunAnalysis();
- inline static const Decl *getDecl(const Expr *E);
-
- // for storing the result of analyzed ValueDecls
- void *NonConstantsImpl;
- void *UsedVarsImpl;
-
- const Stmt *DeclBody;
- bool Analyzed;
-};
-
-}
-
-#endif
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 599c164923cb..422a1db7f6fd 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -397,6 +397,8 @@ private:
CallingContext *Ctx) ;
til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx);
+ til::SExpr *translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE,
+ CallingContext *Ctx);
til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx,
const Expr *SelfE = nullptr);
til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME,
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index 810f2052b7a5..c106a9a42731 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -1643,10 +1643,10 @@ private:
friend class SCFG;
// assign unique ids to all instructions
- int renumberInstrs(int id);
+ unsigned renumberInstrs(unsigned id);
- int topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID);
- int topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks, int ID);
+ unsigned topologicalSort(SimpleArray<BasicBlock *> &Blocks, unsigned ID);
+ unsigned topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks, unsigned ID);
void computeDominator();
void computePostDominator();
@@ -1657,7 +1657,7 @@ private:
SCFG *CFGPtr = nullptr;
// Unique ID for this BB in the containing CFG. IDs are in topological order.
- int BlockID : 31;
+ unsigned BlockID : 31;
// Bit to determine if a block has been visited during a traversal.
bool Visited : 1;
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index 49031010a75b..32aadf526587 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -785,7 +785,26 @@ protected:
void printCast(const Cast *E, StreamType &SS) {
if (!CStyle) {
SS << "cast[";
- SS << E->castOpcode();
+ switch (E->castOpcode()) {
+ case CAST_none:
+ SS << "none";
+ break;
+ case CAST_extendNum:
+ SS << "extendNum";
+ break;
+ case CAST_truncNum:
+ SS << "truncNum";
+ break;
+ case CAST_toFloat:
+ SS << "toFloat";
+ break;
+ case CAST_toInt:
+ SS << "toInt";
+ break;
+ case CAST_objToPtr:
+ SS << "objToPtr";
+ break;
+ }
SS << "](";
self()->printSExpr(E->expr(), SS, Prec_Unary);
SS << ")";
diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h
index 19531d92e645..490d2ce346be 100644
--- a/include/clang/Analysis/AnalysisDeclContext.h
+++ b/include/clang/Analysis/AnalysisDeclContext.h
@@ -40,7 +40,6 @@ class ImplicitParamDecl;
class LocationContext;
class LocationContextManager;
class ParentMap;
-class PseudoConstantAnalysis;
class StackFrameContext;
class Stmt;
class VarDecl;
@@ -84,7 +83,6 @@ class AnalysisDeclContext {
bool builtCFG = false;
bool builtCompleteCFG = false;
std::unique_ptr<ParentMap> PM;
- std::unique_ptr<PseudoConstantAnalysis> PCA;
std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
llvm::BumpPtrAllocator A;
@@ -175,7 +173,6 @@ public:
bool isCFGBuilt() const { return builtCFG; }
ParentMap &getParentMap();
- PseudoConstantAnalysis *getPseudoConstantAnalysis();
using referenced_decls_iterator = const VarDecl * const *;
@@ -230,17 +227,23 @@ private:
AnalysisDeclContext *Ctx;
const LocationContext *Parent;
+ int64_t ID;
protected:
LocationContext(ContextKind k, AnalysisDeclContext *ctx,
- const LocationContext *parent)
- : Kind(k), Ctx(ctx), Parent(parent) {}
+ const LocationContext *parent,
+ int64_t ID)
+ : Kind(k), Ctx(ctx), Parent(parent), ID(ID) {}
public:
virtual ~LocationContext();
ContextKind getKind() const { return Kind; }
+ int64_t getID() const {
+ return ID;
+ }
+
AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
const LocationContext *getParent() const { return Parent; }
@@ -300,8 +303,9 @@ class StackFrameContext : public LocationContext {
StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
const Stmt *s, const CFGBlock *blk,
- unsigned idx)
- : LocationContext(StackFrame, ctx, parent), CallSite(s),
+ unsigned idx,
+ int64_t ID)
+ : LocationContext(StackFrame, ctx, parent, ID), CallSite(s),
Block(blk), Index(idx) {}
public:
@@ -337,8 +341,8 @@ class ScopeContext : public LocationContext {
const Stmt *Enter;
ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
- const Stmt *s)
- : LocationContext(Scope, ctx, parent), Enter(s) {}
+ const Stmt *s, int64_t ID)
+ : LocationContext(Scope, ctx, parent, ID), Enter(s) {}
public:
~ScopeContext() override = default;
@@ -364,9 +368,10 @@ class BlockInvocationContext : public LocationContext {
const void *ContextData;
BlockInvocationContext(AnalysisDeclContext *ctx,
- const LocationContext *parent,
- const BlockDecl *bd, const void *contextData)
- : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
+ const LocationContext *parent, const BlockDecl *bd,
+ const void *contextData, int64_t ID)
+ : LocationContext(Block, ctx, parent, ID), BD(bd),
+ ContextData(contextData) {}
public:
~BlockInvocationContext() override = default;
@@ -392,6 +397,9 @@ public:
class LocationContextManager {
llvm::FoldingSet<LocationContext> Contexts;
+ /// ID used for generating a new location context.
+ int64_t NewID = 0;
+
public:
~LocationContextManager();
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index 8d28971cfe5c..087ffdcde90c 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -10,19 +10,6 @@
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H
#define LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define ANALYSISSTART
-#include "clang/Basic/DiagnosticAnalysisKinds.inc"
-#undef DIAG
- NUM_BUILTIN_ANALYSIS_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticAnalysis.h"
#endif
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index ae0f392ed969..e230930b59e0 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -131,6 +131,7 @@ public:
bool TraverseStmt(Stmt *S) { return true; }
bool shouldWalkTypesOfTypeLocs() const { return false; }
+ bool shouldVisitTemplateInstantiations() const { return true; }
private:
/// Add the given declaration to the call graph.
diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h
index 915ec58a5144..fadca137b88d 100644
--- a/include/clang/Analysis/CloneDetection.h
+++ b/include/clang/Analysis/CloneDetection.h
@@ -122,7 +122,7 @@ public:
/// Returns the start sourcelocation of the first statement in this sequence.
///
/// This method should only be called on a non-empty StmtSequence object.
- SourceLocation getStartLoc() const;
+ SourceLocation getBeginLoc() const;
/// Returns the end sourcelocation of the last statement in this sequence.
///
diff --git a/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h
index aee67865df25..27c1d5b9f1a5 100644
--- a/include/clang/Analysis/ConstructionContext.h
+++ b/include/clang/Analysis/ConstructionContext.h
@@ -19,6 +19,7 @@
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
namespace clang {
@@ -623,9 +624,16 @@ public:
};
class ArgumentConstructionContext : public ConstructionContext {
- const Expr *CE; // The call of which the context is an argument.
- unsigned Index; // Which argument we're constructing.
- const CXXBindTemporaryExpr *BTE; // Whether the object needs to be destroyed.
+ // The call of which the context is an argument.
+ const Expr *CE;
+
+ // Which argument we're constructing. Note that when numbering between
+ // arguments and parameters is inconsistent (eg., operator calls),
+ // this is the index of the argument, not of the parameter.
+ unsigned Index;
+
+ // Whether the object needs to be destroyed.
+ const CXXBindTemporaryExpr *BTE;
friend class ConstructionContext; // Allows to create<>() itself.
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 25ae93fae6b8..d78174ecd70e 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -80,6 +80,7 @@ public:
CallEnterKind,
CallExitBeginKind,
CallExitEndKind,
+ FunctionExitKind,
PreImplicitCallKind,
PostImplicitCallKind,
MinImplicitCallKind = PreImplicitCallKind,
@@ -214,6 +215,10 @@ public:
ID.AddPointer(getTag());
}
+ void print(StringRef CR, llvm::raw_ostream &Out) const;
+
+ LLVM_DUMP_METHOD void dump() const;
+
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
const LocationContext *LC,
const ProgramPointTag *tag);
@@ -329,6 +334,29 @@ private:
}
};
+class FunctionExitPoint : public ProgramPoint {
+public:
+ explicit FunctionExitPoint(const ReturnStmt *S,
+ const LocationContext *LC,
+ const ProgramPointTag *tag = nullptr)
+ : ProgramPoint(S, FunctionExitKind, LC, tag) {}
+
+ const CFGBlock *getBlock() const {
+ return &getLocationContext()->getCFG()->getExit();
+ }
+
+ const ReturnStmt *getStmt() const {
+ return reinterpret_cast<const ReturnStmt *>(getData1());
+ }
+
+private:
+ friend class ProgramPoint;
+ FunctionExitPoint() = default;
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == FunctionExitKind;
+ }
+};
+
// PostCondition represents the post program point of a branch condition.
class PostCondition : public PostStmt {
public:
diff --git a/lib/StaticAnalyzer/Checkers/SelectorExtras.h b/include/clang/Analysis/SelectorExtras.h
index b11d070c629b..767063e835e4 100644
--- a/lib/StaticAnalyzer/Checkers/SelectorExtras.h
+++ b/include/clang/Analysis/SelectorExtras.h
@@ -7,13 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_SELECTOREXTRAS_H
-#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_SELECTOREXTRAS_H
+#ifndef LLVM_CLANG_LIB_ANALYSIS_SELECTOREXTRAS_H
+#define LLVM_CLANG_LIB_ANALYSIS_SELECTOREXTRAS_H
#include "clang/AST/ASTContext.h"
namespace clang {
-namespace ento {
template <typename... IdentifierInfos>
static inline Selector getKeywordSelector(ASTContext &Ctx,
@@ -33,14 +32,6 @@ static inline void lazyInitKeywordSelector(Selector &Sel, ASTContext &Ctx,
Sel = getKeywordSelector(Ctx, IIs...);
}
-static inline void lazyInitNullarySelector(Selector &Sel, ASTContext &Ctx,
- const char *Name) {
- if (!Sel.isNull())
- return;
- Sel = GetNullarySelector(Name, Ctx);
-}
-
-} // end namespace ento
} // end namespace clang
#endif
diff --git a/include/clang/Basic/AlignedAllocation.h b/include/clang/Basic/AlignedAllocation.h
index 9751f4118447..c995f47a7d74 100644
--- a/include/clang/Basic/AlignedAllocation.h
+++ b/include/clang/Basic/AlignedAllocation.h
@@ -27,8 +27,8 @@ inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) {
default:
break;
case llvm::Triple::Darwin:
- case llvm::Triple::MacOSX: // Earliest supporting version is 10.13.
- return llvm::VersionTuple(10U, 13U);
+ case llvm::Triple::MacOSX: // Earliest supporting version is 10.14.
+ return llvm::VersionTuple(10U, 14U);
case llvm::Triple::IOS:
case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0.
return llvm::VersionTuple(11U);
diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h
index afec2d7e0f2f..6c7f95658970 100644
--- a/include/clang/Basic/AllDiagnostics.h
+++ b/include/clang/Basic/AllDiagnostics.h
@@ -15,17 +15,17 @@
#ifndef LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
#define LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
-#include "clang/AST/ASTDiagnostic.h"
-#include "clang/AST/CommentDiagnostic.h"
-#include "clang/Analysis/AnalysisDiagnostic.h"
-#include "clang/CrossTU/CrossTUDiagnostic.h"
-#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "clang/Serialization/SerializationDiagnostic.h"
-#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h"
+#include "clang/Basic/DiagnosticAST.h"
+#include "clang/Basic/DiagnosticAnalysis.h"
+#include "clang/Basic/DiagnosticComment.h"
+#include "clang/Basic/DiagnosticCrossTU.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/DiagnosticLex.h"
+#include "clang/Basic/DiagnosticParse.h"
+#include "clang/Basic/DiagnosticSema.h"
+#include "clang/Basic/DiagnosticSerialization.h"
+#include "clang/Basic/DiagnosticRefactoring.h"
namespace clang {
template <size_t SizeOfStr, typename FieldType>
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index fea8e129d7da..1fe1dd39948a 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -90,6 +90,15 @@ def NonBitField : SubsetSubject<Field,
[{!S->isBitField()}],
"non-bit-field non-static data members">;
+def NonStaticCXXMethod : SubsetSubject<CXXMethod,
+ [{!S->isStatic()}],
+ "non-static member functions">;
+
+def NonStaticNonConstCXXMethod
+ : SubsetSubject<CXXMethod,
+ [{!S->isStatic() && !S->isConst()}],
+ "non-static non-const member functions">;
+
def ObjCInstanceMethod : SubsetSubject<ObjCMethod,
[{S->isInstanceMethod()}],
"Objective-C instance methods">;
@@ -145,8 +154,9 @@ def HasFunctionProto : SubsetSubject<DeclBase,
// function. Accepted as a function type attribute on the type of such a
// member function.
// FIXME: This does not actually ever match currently.
-def ImplicitObjectParameter : SubsetSubject<Function, [{false}],
- "implicit object parameters">;
+def ImplicitObjectParameter
+ : SubsetSubject<Function, [{static_cast<void>(S), false}],
+ "implicit object parameters">;
// A single argument to an attribute
class Argument<string name, bit optional, bit fake = 0> {
@@ -288,8 +298,9 @@ def COnly : LangOpt<"CPlusPlus", 1>;
def CPlusPlus : LangOpt<"CPlusPlus">;
def OpenCL : LangOpt<"OpenCL">;
def RenderScript : LangOpt<"RenderScript">;
-def ObjC : LangOpt<"ObjC1">;
+def ObjC : LangOpt<"ObjC">;
def BlocksSupported : LangOpt<"Blocks">;
+def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">;
// Defines targets for target-specific attributes. Empty lists are unchecked.
class TargetSpec {
@@ -467,13 +478,12 @@ class Attr {
// in a class template definition.
bit MeaningfulToClassTemplateDefinition = 0;
// Set to true if this attribute can be used with '#pragma clang attribute'.
- // By default, when this value is false, an attribute is supported by the
- // '#pragma clang attribute' only when:
- // - It has documentation.
+ // By default, an attribute is supported by the '#pragma clang attribute'
+ // only when:
// - It has a subject list whose subjects can be represented using subject
// match rules.
// - It has GNU/CXX11 spelling and doesn't require delayed parsing.
- bit ForcePragmaAttributeSupport = 0;
+ bit PragmaAttributeSupport;
// Lists language options, one of which is required to be true for the
// attribute to be applicable. If empty, no language options are required.
list<LangOpt> LangOpts = [];
@@ -488,10 +498,7 @@ class Attr {
}
/// A type attribute is not processed on a declaration or a statement.
-class TypeAttr : Attr {
- // By default, type attributes do not get an AST node.
- let ASTNode = 0;
-}
+class TypeAttr : Attr;
/// A stmt attribute is not processed on a declaration or a type.
class StmtAttr : Attr;
@@ -657,6 +664,7 @@ def AnalyzerNoReturn : InheritableAttr {
// vendor namespace, or should it use a vendor namespace specific to the
// analyzer?
let Spellings = [GNU<"analyzer_noreturn">];
+ // TODO: Add subject list.
let Documentation = [Undocumented];
}
@@ -665,7 +673,7 @@ def Annotate : InheritableParamAttr {
let Args = [StringArgument<"Annotation">];
// Ensure that the annotate attribute can be used with
// '#pragma clang attribute' even though it has no subject list.
- let ForcePragmaAttributeSupport = 1;
+ let PragmaAttributeSupport = 1;
let Documentation = [Undocumented];
}
@@ -720,6 +728,7 @@ def Availability : InheritableAttr {
.Case("macos_app_extension", "macOS (App Extension)")
.Case("tvos_app_extension", "tvOS (App Extension)")
.Case("watchos_app_extension", "watchOS (App Extension)")
+ .Case("swift", "Swift")
.Default(llvm::StringRef());
}
static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) {
@@ -808,19 +817,56 @@ def CFUnknownTransfer : InheritableAttr {
def CFReturnsRetained : InheritableAttr {
let Spellings = [Clang<"cf_returns_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
}
def CFReturnsNotRetained : InheritableAttr {
let Spellings = [Clang<"cf_returns_not_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
}
def CFConsumed : InheritableParamAttr {
let Spellings = [Clang<"cf_consumed">];
let Subjects = SubjectList<[ParmVar]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
+}
+
+// OSObject-based attributes.
+def OSConsumed : InheritableParamAttr {
+ let Spellings = [Clang<"os_consumed">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [RetainBehaviorDocs];
+}
+
+def OSReturnsRetained : InheritableAttr {
+ let Spellings = [Clang<"os_returns_retained">];
+ let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty, ParmVar]>;
+ let Documentation = [RetainBehaviorDocs];
+}
+
+def OSReturnsNotRetained : InheritableAttr {
+ let Spellings = [Clang<"os_returns_not_retained">];
+ let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty, ParmVar]>;
+ let Documentation = [RetainBehaviorDocs];
+}
+
+def OSReturnsRetainedOnZero : InheritableAttr {
+ let Spellings = [Clang<"os_returns_retained_on_zero">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [RetainBehaviorDocs];
+}
+
+def OSReturnsRetainedOnNonZero : InheritableAttr {
+ let Spellings = [Clang<"os_returns_retained_on_non_zero">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [RetainBehaviorDocs];
+}
+
+def OSConsumesThis : InheritableAttr {
+ let Spellings = [Clang<"os_consumes_this">];
+ let Subjects = SubjectList<[NonStaticCXXMethod]>;
+ let Documentation = [RetainBehaviorDocs];
}
def Cleanup : InheritableAttr {
@@ -855,21 +901,19 @@ def Constructor : InheritableAttr {
}
def CPUSpecific : InheritableAttr {
- let Spellings = [Clang<"cpu_specific">];
+ let Spellings = [Clang<"cpu_specific">, Declspec<"cpu_specific">];
let Args = [VariadicIdentifierArgument<"Cpus">];
let Subjects = SubjectList<[Function]>;
let Documentation = [CPUSpecificCPUDispatchDocs];
let AdditionalMembers = [{
- unsigned ActiveArgIndex = 0;
-
- IdentifierInfo *getCurCPUName() const {
- return *(cpus_begin() + ActiveArgIndex);
+ IdentifierInfo *getCPUName(unsigned Index) const {
+ return *(cpus_begin() + Index);
}
}];
}
def CPUDispatch : InheritableAttr {
- let Spellings = [Clang<"cpu_dispatch">];
+ let Spellings = [Clang<"cpu_dispatch">, Declspec<"cpu_dispatch">];
let Args = [VariadicIdentifierArgument<"Cpus">];
let Subjects = SubjectList<[Function]>;
let Documentation = [CPUSpecificCPUDispatchDocs];
@@ -1089,10 +1133,14 @@ def EnableIf : InheritableAttr {
def ExtVectorType : Attr {
// This is an OpenCL-related attribute and does not receive a [[]] spelling.
let Spellings = [GNU<"ext_vector_type">];
+ // FIXME: This subject list is wrong; this is a type attribute.
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
let Args = [ExprArgument<"NumElements">];
let ASTNode = 0;
let Documentation = [Undocumented];
+ // This is a type attribute with an incorrect subject list, so should not be
+ // permitted by #pragma clang attribute.
+ let PragmaAttributeSupport = 0;
}
def FallThrough : StmtAttr {
@@ -1165,7 +1213,7 @@ def FormatArg : InheritableAttr {
def GNUInline : InheritableAttr {
let Spellings = [GCC<"gnu_inline">];
let Subjects = SubjectList<[Function]>;
- let Documentation = [Undocumented];
+ let Documentation = [GnuInlineDocs];
}
def Hot : InheritableAttr {
@@ -1218,7 +1266,7 @@ def LayoutVersion : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Documentation = [LayoutVersionDocs];
}
-def LifetimeBound : InheritableAttr {
+def LifetimeBound : DeclOrTypeAttr {
let Spellings = [Clang<"lifetimebound", 0>];
let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
let Documentation = [LifetimeBoundDocs];
@@ -1309,6 +1357,9 @@ def Mode : Attr {
let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag>;
let Args = [IdentifierArgument<"Mode">];
let Documentation = [Undocumented];
+ // This is notionally a type attribute, which #pragma clang attribute
+ // generally does not support.
+ let PragmaAttributeSupport = 0;
}
def Naked : InheritableAttr {
@@ -1321,12 +1372,16 @@ def NeonPolyVectorType : TypeAttr {
let Spellings = [Clang<"neon_polyvector_type">];
let Args = [IntArgument<"NumElements">];
let Documentation = [Undocumented];
+ // Represented as VectorType instead.
+ let ASTNode = 0;
}
def NeonVectorType : TypeAttr {
let Spellings = [Clang<"neon_vector_type">];
let Args = [IntArgument<"NumElements">];
let Documentation = [Undocumented];
+ // Represented as VectorType instead.
+ let ASTNode = 0;
}
def ReturnsTwice : InheritableAttr {
@@ -1501,6 +1556,14 @@ def TypeNullUnspecified : TypeAttr {
let Documentation = [TypeNullUnspecifiedDocs];
}
+// This is a marker used to indicate that an __unsafe_unretained qualifier was
+// ignored because ARC is not enabled. The usual representation for this
+// qualifier is as an ObjCOwnership attribute with Kind == "none".
+def ObjCInertUnsafeUnretained : TypeAttr {
+ let Spellings = [Keyword<"__unsafe_unretained">];
+ let Documentation = [Undocumented];
+}
+
def ObjCKindOf : TypeAttr {
let Spellings = [Keyword<"__kindof">];
let Documentation = [Undocumented];
@@ -1588,34 +1651,34 @@ def ObjCBridgeRelated : InheritableAttr {
let Documentation = [Undocumented];
}
-def NSReturnsRetained : InheritableAttr {
+def NSReturnsRetained : DeclOrTypeAttr {
let Spellings = [Clang<"ns_returns_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
}
def NSReturnsNotRetained : InheritableAttr {
let Spellings = [Clang<"ns_returns_not_retained">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
}
def NSReturnsAutoreleased : InheritableAttr {
let Spellings = [Clang<"ns_returns_autoreleased">];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
}
def NSConsumesSelf : InheritableAttr {
let Spellings = [Clang<"ns_consumes_self">];
let Subjects = SubjectList<[ObjCMethod]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
}
def NSConsumed : InheritableParamAttr {
let Spellings = [Clang<"ns_consumed">];
let Subjects = SubjectList<[ParmVar]>;
- let Documentation = [Undocumented];
+ let Documentation = [RetainBehaviorDocs];
}
def ObjCException : InheritableAttr {
@@ -1764,6 +1827,11 @@ def Pcs : DeclOrTypeAttr {
let Documentation = [PcsDocs];
}
+def AArch64VectorPcs: DeclOrTypeAttr {
+ let Spellings = [Clang<"aarch64_vector_pcs">];
+ let Documentation = [AArch64VectorPcsDocs];
+}
+
def Pure : InheritableAttr {
let Spellings = [GCC<"pure">];
let Documentation = [Undocumented];
@@ -1773,6 +1841,13 @@ def Regparm : TypeAttr {
let Spellings = [GCC<"regparm">];
let Args = [UnsignedArgument<"NumParams">];
let Documentation = [RegparmDocs];
+ // Represented as part of the enclosing function type.
+ let ASTNode = 0;
+}
+
+def NoDeref : TypeAttr {
+ let Spellings = [Clang<"noderef">];
+ let Documentation = [NoDerefDocs];
}
def ReqdWorkGroupSize : InheritableAttr {
@@ -1953,6 +2028,39 @@ def Target : InheritableAttr {
return parse(getFeaturesStr());
}
+ StringRef getArchitecture() const {
+ StringRef Features = getFeaturesStr();
+ if (Features == "default") return {};
+
+ SmallVector<StringRef, 1> AttrFeatures;
+ Features.split(AttrFeatures, ",");
+
+ for (auto &Feature : AttrFeatures) {
+ Feature = Feature.trim();
+ if (Feature.startswith("arch="))
+ return Feature.drop_front(sizeof("arch=") - 1);
+ }
+ return "";
+ }
+
+ // Gets the list of features as simple string-refs with no +/- or 'no-'.
+ // Only adds the items to 'Out' that are additions.
+ void getAddedFeatures(llvm::SmallVectorImpl<StringRef> &Out) const {
+ StringRef Features = getFeaturesStr();
+ if (Features == "default") return;
+
+ SmallVector<StringRef, 1> AttrFeatures;
+ Features.split(AttrFeatures, ",");
+
+ for (auto &Feature : AttrFeatures) {
+ Feature = Feature.trim();
+
+ if (!Feature.startswith("no-") && !Feature.startswith("arch=") &&
+ !Feature.startswith("fpmath=") && !Feature.startswith("tune="))
+ Out.push_back(Feature);
+ }
+ }
+
template<class Compare>
ParsedTargetAttr parse(Compare cmp) const {
ParsedTargetAttr Attrs = parse();
@@ -2061,10 +2169,9 @@ def ObjCGC : TypeAttr {
let Documentation = [Undocumented];
}
-def ObjCOwnership : InheritableAttr {
+def ObjCOwnership : DeclOrTypeAttr {
let Spellings = [Clang<"objc_ownership">];
let Args = [IdentifierArgument<"Kind">];
- let ASTNode = 0;
let Documentation = [Undocumented];
}
@@ -2102,6 +2209,8 @@ def VectorSize : TypeAttr {
let Spellings = [GCC<"vector_size">];
let Args = [ExprArgument<"NumBytes">];
let Documentation = [Undocumented];
+ // Represented as VectorType instead.
+ let ASTNode = 0;
}
def VecTypeHint : InheritableAttr {
@@ -2196,7 +2305,7 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr,
let Documentation = [AnyX86NoCallerSavedRegistersDocs];
}
-def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{
+def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{
let Spellings = [GCC<"nocf_check">];
let Subjects = SubjectList<[FunctionLike]>;
let Documentation = [AnyX86NoCfCheckDocs];
@@ -2625,6 +2734,17 @@ def DLLExport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
let Documentation = [DLLExportDocs];
}
+def DLLExportStaticLocal : InheritableAttr, TargetSpecificAttr<TargetWindows> {
+ // This attribute is used internally only when -fno-dllexport-inlines is
+ // passed. This attribute is added to inline function of class having
+ // dllexport attribute. And if the function has static local variables, this
+ // attribute is used to whether the variables are exported or not. Also if
+ // function has local static variables, the function is dllexported too.
+ let Spellings = [];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
let Spellings = [Declspec<"dllimport">, GCC<"dllimport">];
let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>;
@@ -2641,6 +2761,16 @@ public:
}];
}
+def DLLImportStaticLocal : InheritableAttr, TargetSpecificAttr<TargetWindows> {
+ // This attribute is used internally only when -fno-dllexport-inlines is
+ // passed. This attribute is added to inline function of class having
+ // dllimport attribute. And if the function has static local variables, this
+ // attribute is used to whether the variables are imported or not.
+ let Spellings = [];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
def SelectAny : InheritableAttr {
let Spellings = [Declspec<"selectany">, GCC<"selectany">];
let Documentation = [SelectAnyDocs];
@@ -2748,7 +2878,11 @@ def LoopHint : Attr {
/// interleave_count: interleaves 'Value' loop iterations.
/// unroll: fully unroll loop if State == Enable.
/// unroll_count: unrolls loop 'Value' times.
- /// distribute: attempt to distribute loop if State == Enable
+ /// unroll_and_jam: attempt to unroll and jam loop if State == Enable.
+ /// unroll_and_jam_count: unroll and jams loop 'Value' times.
+ /// distribute: attempt to distribute loop if State == Enable.
+ /// pipeline: disable pipelining loop if State == Disable.
+ /// pipeline_initiation_interval: create loop schedule with initiation interval equal to 'Value'.
/// #pragma unroll <argument> directive
/// <no arg>: fully unrolls loop.
@@ -2756,14 +2890,17 @@ def LoopHint : Attr {
/// expression: unrolls loop 'Value' times.
let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">,
- Pragma<"", "nounroll">];
+ Pragma<"", "nounroll">, Pragma<"", "unroll_and_jam">,
+ Pragma<"", "nounroll_and_jam">];
/// State of the loop optimization specified by the spelling.
let Args = [EnumArgument<"Option", "OptionType",
["vectorize", "vectorize_width", "interleave", "interleave_count",
- "unroll", "unroll_count", "distribute"],
+ "unroll", "unroll_count", "unroll_and_jam", "unroll_and_jam_count",
+ "pipeline", "pipeline_initiation_interval", "distribute"],
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
- "Unroll", "UnrollCount", "Distribute"]>,
+ "Unroll", "UnrollCount", "UnrollAndJam", "UnrollAndJamCount",
+ "PipelineDisabled", "PipelineInitiationInterval", "Distribute"]>,
EnumArgument<"State", "LoopHintState",
["enable", "disable", "numeric", "assume_safety", "full"],
["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
@@ -2778,6 +2915,10 @@ def LoopHint : Attr {
case InterleaveCount: return "interleave_count";
case Unroll: return "unroll";
case UnrollCount: return "unroll_count";
+ case UnrollAndJam: return "unroll_and_jam";
+ case UnrollAndJamCount: return "unroll_and_jam_count";
+ case PipelineDisabled: return "pipeline";
+ case PipelineInitiationInterval: return "pipeline_initiation_interval";
case Distribute: return "distribute";
}
llvm_unreachable("Unhandled LoopHint option.");
@@ -2787,9 +2928,9 @@ def LoopHint : Attr {
unsigned SpellingIndex = getSpellingListIndex();
// For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
// "nounroll" is already emitted as the pragma name.
- if (SpellingIndex == Pragma_nounroll)
+ if (SpellingIndex == Pragma_nounroll || SpellingIndex == Pragma_nounroll_and_jam)
return;
- else if (SpellingIndex == Pragma_unroll) {
+ else if (SpellingIndex == Pragma_unroll || SpellingIndex == Pragma_unroll_and_jam) {
OS << ' ' << getValueString(Policy);
return;
}
@@ -2825,6 +2966,11 @@ def LoopHint : Attr {
return "#pragma nounroll";
else if (SpellingIndex == Pragma_unroll)
return "#pragma unroll" + (option == UnrollCount ? getValueString(Policy) : "");
+ else if (SpellingIndex == Pragma_nounroll_and_jam)
+ return "#pragma nounroll_and_jam";
+ else if (SpellingIndex == Pragma_unroll_and_jam)
+ return "#pragma unroll_and_jam" +
+ (option == UnrollAndJamCount ? getValueString(Policy) : "");
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
return getOptionName(option) + getValueString(Policy);
@@ -2938,9 +3084,10 @@ def OMPDeclareSimdDecl : Attr {
}];
}
-def OMPDeclareTargetDecl : Attr {
+def OMPDeclareTargetDecl : InheritableAttr {
let Spellings = [Pragma<"omp", "declare target">];
let SemaHandler = 0;
+ let Subjects = SubjectList<[Function, SharedVar]>;
let Documentation = [OMPDeclareTargetDocs];
let Args = [
EnumArgument<"MapType", "MapTypeTy",
@@ -2953,6 +3100,15 @@ def OMPDeclareTargetDecl : Attr {
if (getMapType() != MT_To)
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
}
+ static llvm::Optional<MapTypeTy>
+ isDeclareTargetDeclaration(const ValueDecl *VD) {
+ if (!VD->hasAttrs())
+ return llvm::None;
+ if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getMapType();
+
+ return llvm::None;
+ }
}];
}
@@ -2961,3 +3117,47 @@ def InternalLinkage : InheritableAttr {
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
let Documentation = [InternalLinkageDocs];
}
+
+def ExcludeFromExplicitInstantiation : InheritableAttr {
+ let Spellings = [Clang<"exclude_from_explicit_instantiation">];
+ let Subjects = SubjectList<[Var, Function, CXXRecord]>;
+ let Documentation = [ExcludeFromExplicitInstantiationDocs];
+ let MeaningfulToClassTemplateDefinition = 1;
+}
+
+def Reinitializes : InheritableAttr {
+ let Spellings = [Clang<"reinitializes", 0>];
+ let Subjects = SubjectList<[NonStaticNonConstCXXMethod], ErrorDiag>;
+ let Documentation = [ReinitializesDocs];
+}
+
+def NoDestroy : InheritableAttr {
+ let Spellings = [Clang<"no_destroy", 0>];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [NoDestroyDocs];
+}
+
+def AlwaysDestroy : InheritableAttr {
+ let Spellings = [Clang<"always_destroy", 0>];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [AlwaysDestroyDocs];
+}
+
+def SpeculativeLoadHardening : InheritableAttr {
+ let Spellings = [Clang<"speculative_load_hardening">];
+ let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
+ let Documentation = [SpeculativeLoadHardeningDocs];
+}
+
+def Uninitialized : InheritableAttr {
+ let Spellings = [Clang<"uninitialized", 0>];
+ let Subjects = SubjectList<[LocalVar]>;
+ let Documentation = [UninitializedDocs];
+}
+
+def ObjCExternallyRetained : InheritableAttr {
+ let LangOpts = [ObjCAutoRefCount];
+ let Spellings = [Clang<"objc_externally_retained">];
+ let Subjects = SubjectList<[NonParmVar, Function, Block, ObjCMethod]>;
+ let Documentation = [ObjCExternallyRetainedDocs];
+}
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index bb2993eab4bc..5773a92c9c15 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -38,6 +38,10 @@ Attributes in Clang
.. contents::
:local:
+.. |br| raw:: html
+
+ <br/>
+
Introduction
============
@@ -51,7 +55,7 @@ def SectionDocs : Documentation {
The ``section`` attribute allows you to specify a specific section a
global variable or function should be in after translation.
}];
- let Heading = "section (gnu::section, __declspec(allocate))";
+ let Heading = "section, __declspec(allocate)";
}
def InitSegDocs : Documentation {
@@ -270,7 +274,7 @@ that appears to be capable of returning to its caller.
def AssertCapabilityDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "assert_capability (assert_shared_capability, clang::assert_capability, clang::assert_shared_capability)";
+ let Heading = "assert_capability, assert_shared_capability";
let Content = [{
Marks a function that dynamically tests whether a capability is held, and halts
the program if it is not held.
@@ -279,7 +283,7 @@ the program if it is not held.
def AcquireCapabilityDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "acquire_capability (acquire_shared_capability, clang::acquire_capability, clang::acquire_shared_capability)";
+ let Heading = "acquire_capability, acquire_shared_capability";
let Content = [{
Marks a function as acquiring a capability.
}];
@@ -287,7 +291,7 @@ Marks a function as acquiring a capability.
def TryAcquireCapabilityDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "try_acquire_capability (try_acquire_shared_capability, clang::try_acquire_capability, clang::try_acquire_shared_capability)";
+ let Heading = "try_acquire_capability, try_acquire_shared_capability";
let Content = [{
Marks a function that attempts to acquire a capability. This function may fail to
actually acquire the capability; they accept a Boolean value determining
@@ -298,7 +302,7 @@ the capability means success (false).
def ReleaseCapabilityDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "release_capability (release_shared_capability, clang::release_capability, clang::release_shared_capability)";
+ let Heading = "release_capability, release_shared_capability";
let Content = [{
Marks a function as releasing a capability.
}];
@@ -550,9 +554,9 @@ certain user-defined criteria. For example:
.. code-block:: c
- void abs(int a)
+ int abs(int a)
__attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning")));
- void must_abs(int a)
+ int must_abs(int a)
__attribute__((diagnose_if(a >= 0, "Redundant abs call", "error")));
int val = abs(1); // warning: Redundant abs call
@@ -843,6 +847,73 @@ Query for this feature with ``__has_attribute(objc_method_family)``.
}];
}
+def RetainBehaviorDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The behavior of a function with respect to reference counting for Foundation
+(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming
+convention (e.g. functions starting with "get" are assumed to return at
+``+0``).
+
+It can be overriden using a family of the following attributes. In
+Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to
+a function communicates that the object is returned at ``+1``, and the caller
+is responsible for freeing it.
+Similiarly, the annotation ``__attribute__((ns_returns_not_retained))``
+specifies that the object is returned at ``+0`` and the ownership remains with
+the callee.
+The annotation ``__attribute__((ns_consumes_self))`` specifies that
+the Objective-C method call consumes the reference to ``self``, e.g. by
+attaching it to a supplied parameter.
+Additionally, parameters can have an annotation
+``__attribute__((ns_consumed))``, which specifies that passing an owned object
+as that parameter effectively transfers the ownership, and the caller is no
+longer responsible for it.
+These attributes affect code generation when interacting with ARC code, and
+they are used by the Clang Static Analyzer.
+
+In C programs using CoreFoundation, a similar set of attributes:
+``__attribute__((cf_returns_not_retained))``,
+``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))``
+have the same respective semantics when applied to CoreFoundation objects.
+These attributes affect code generation when interacting with ARC code, and
+they are used by the Clang Static Analyzer.
+
+Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject),
+the same attribute family is present:
+``__attribute__((os_returns_not_retained))``,
+``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``,
+with the same respective semantics.
+Similar to ``__attribute__((ns_consumes_self))``,
+``__attribute__((os_consumes_this))`` specifies that the method call consumes
+the reference to "this" (e.g., when attaching it to a different object supplied
+as a parameter).
+Out parameters (parameters the function is meant to write into,
+either via pointers-to-pointers or references-to-pointers)
+may be annotated with ``__attribute__((os_returns_retained))``
+or ``__attribute__((os_returns_not_retained))`` which specifies that the object
+written into the out parameter should (or respectively should not) be released
+after use.
+Since often out parameters may or may not be written depending on the exit
+code of the function,
+annotations ``__attribute__((os_returns_retained_on_zero))``
+and ``__attribute__((os_returns_retained_on_non_zero))`` specify that
+an out parameter at ``+1`` is written if and only if the function returns a zero
+(respectively non-zero) error code.
+Observe that return-code-dependent out parameter annotations are only
+available for retained out parameters, as non-retained object do not have to be
+released by the callee.
+These attributes are only used by the Clang Static Analyzer.
+
+The family of attributes ``X_returns_X_retained`` can be added to functions,
+C++ methods, and Objective-C methods and properties.
+Attributes ``X_consumed`` can be added to parameters of methods, functions,
+and Objective-C methods.
+ }];
+}
+
+
+
def NoDebugDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
@@ -1261,7 +1332,7 @@ of silently falling back on dynamic initialization.
def WarnMaybeUnusedDocs : Documentation {
let Category = DocCatVariable;
- let Heading = "maybe_unused, unused, gnu::unused";
+ let Heading = "maybe_unused, unused";
let Content = [{
When passing the ``-Wunused`` flag to Clang, entities that are unused by the
program may be diagnosed. The ``[[maybe_unused]]`` (or
@@ -1287,7 +1358,7 @@ enumerator, a non-static data member, or a label.
def WarnUnusedResultsDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "nodiscard, warn_unused_result, clang::warn_unused_result, gnu::warn_unused_result";
+ let Heading = "nodiscard, warn_unused_result";
let Content = [{
Clang supports the ability to diagnose when the results of a function call
expression are discarded under suspicious circumstances. A diagnostic is
@@ -1312,7 +1383,7 @@ potentially-evaluated discarded-value expression that is not explicitly cast to
def FallthroughDocs : Documentation {
let Category = DocCatStmt;
- let Heading = "fallthrough, clang::fallthrough";
+ let Heading = "fallthrough";
let Content = [{
The ``fallthrough`` (or ``clang::fallthrough``) attribute is used
to annotate intentional fall-through
@@ -1460,7 +1531,7 @@ on the command line.
def MipsLongCallStyleDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "long_call (gnu::long_call, gnu::far)";
+ let Heading = "long_call, far";
let Content = [{
Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
and ``__attribute__((near))`` attributes on MIPS targets. These attributes may
@@ -1481,7 +1552,7 @@ as ``-mlong-calls`` and ``-mno-long-calls``.
def MipsShortCallStyleDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "short_call (gnu::short_call, gnu::near)";
+ let Heading = "short_call, near";
let Content = [{
Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
``__attribute__((short__call))``, and ``__attribute__((near))`` attributes
@@ -1738,6 +1809,31 @@ similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and
}];
}
+def AArch64VectorPcsDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On AArch64 targets, this attribute changes the calling convention of a
+function to preserve additional floating-point and Advanced SIMD registers
+relative to the default calling convention used for AArch64.
+
+This means it is more efficient to call such functions from code that performs
+extensive floating-point and vector calculations, because fewer live SIMD and FP
+registers need to be saved. This property makes it well-suited for e.g.
+floating-point or vector math library functions, which are typically leaf
+functions that require a small number of registers.
+
+However, using this attribute also means that it is more expensive to call
+a function that adheres to the default calling convention from within such
+a function. Therefore, it is recommended that this attribute is only used
+for leaf functions.
+
+For more information, see the documentation for `aarch64_vector_pcs`_ on
+the Arm Developer website.
+
+.. _`aarch64_vector_pcs`: https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi
+ }];
+}
+
def RegparmDocs : Documentation {
let Category = DocCatCallingConvs;
let Content = [{
@@ -1940,7 +2036,7 @@ def NoSanitizeAddressDocs : Documentation {
let Category = DocCatFunction;
// This function has multiple distinct spellings, and so it requires a custom
// heading to be specified. The most common spelling is sufficient.
- let Heading = "no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address)";
+ let Heading = "no_sanitize_address, no_address_safety_analysis";
let Content = [{
.. _langext-address_sanitizer:
@@ -2497,10 +2593,10 @@ def LoopHintDocs : Documentation {
let Heading = "#pragma clang loop";
let Content = [{
The ``#pragma clang loop`` directive allows loop optimization hints to be
-specified for the subsequent loop. The directive allows vectorization,
-interleaving, and unrolling to be enabled or disabled. Vector width as well
-as interleave and unrolling count can be manually specified. See
-`language extensions
+specified for the subsequent loop. The directive allows pipelining to be
+disabled, or vectorization, interleaving, and unrolling to be enabled or disabled.
+Vector width, interleave count, unrolling count, and the initiation interval
+for pipelining can be explicitly specified. See `language extensions
<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
for details.
}];
@@ -2561,9 +2657,58 @@ for further details including limitations of the unroll hints.
}];
}
+def PipelineHintDocs : Documentation {
+ let Category = DocCatStmt;
+ let Heading = "#pragma clang loop pipeline, #pragma clang loop pipeline_initiation_interval";
+ let Content = [{
+ Software Pipelining optimization is a technique used to optimize loops by
+ utilizing instruction-level parallelism. It reorders loop instructions to
+ overlap iterations. As a result, the next iteration starts before the previous
+ iteration has finished. The module scheduling technique creates a schedule for
+ one iteration such that when repeating at regular intervals, no inter-iteration
+ dependencies are violated. This constant interval(in cycles) between the start
+ of iterations is called the initiation interval. i.e. The initiation interval
+ is the number of cycles between two iterations of an unoptimized loop in the
+ newly created schedule. A new, optimized loop is created such that a single iteration
+ of the loop executes in the same number of cycles as the initiation interval.
+ For further details see <https://llvm.org/pubs/2005-06-17-LattnerMSThesis-book.pdf>.
+
+ ``#pragma clang loop pipeline and #pragma loop pipeline_initiation_interval``
+ could be used as hints for the software pipelining optimization. The pragma is
+ placed immediately before a for, while, do-while, or a C++11 range-based for
+ loop.
+
+ Using ``#pragma clang loop pipeline(disable)`` avoids the software pipelining
+ optimization. The disable state can only be specified:
+
+ .. code-block:: c++
+
+ #pragma clang loop pipeline(disable)
+ for (...) {
+ ...
+ }
+
+ Using ``#pragma loop pipeline_initiation_interval`` instructs
+ the software pipeliner to try the specified initiation interval.
+ If a schedule was found then the resulting loop iteration would have
+ the specified cycle count. If a schedule was not found then loop
+ remains unchanged. The initiation interval must be a positive number
+ greater than zero:
+
+ .. code-block:: c++
+
+ #pragma loop pipeline_initiation_interval(10)
+ for (...) {
+ ...
+ }
+
+ }];
+}
+
+
+
def OpenCLUnrollHintDocs : Documentation {
let Category = DocCatStmt;
- let Heading = "__attribute__((opencl_unroll_hint))";
let Content = [{
The opencl_unroll_hint attribute qualifier can be used to specify that a loop
(for, while and do loops) can be unrolled. This attribute qualifier can be
@@ -2576,7 +2721,6 @@ s6.11.5 for details.
def OpenCLIntelReqdSubGroupSizeDocs : Documentation {
let Category = DocCatStmt;
- let Heading = "__attribute__((intel_reqd_sub_group_size))";
let Content = [{
The optional attribute intel_reqd_sub_group_size can be used to indicate that
the kernel must be compiled and executed with the specified subgroup size. When
@@ -2973,6 +3117,68 @@ This can be used to contain the ABI of a C++ library by excluding unwanted class
}];
}
+def ExcludeFromExplicitInstantiationDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``exclude_from_explicit_instantiation`` attribute opts-out a member of a
+class template from being part of explicit template instantiations of that
+class template. This means that an explicit instantiation will not instantiate
+members of the class template marked with the attribute, but also that code
+where an extern template declaration of the enclosing class template is visible
+will not take for granted that an external instantiation of the class template
+would provide those members (which would otherwise be a link error, since the
+explicit instantiation won't provide those members). For example, let's say we
+don't want the ``data()`` method to be part of libc++'s ABI. To make sure it
+is not exported from the dylib, we give it hidden visibility:
+
+ .. code-block:: c++
+
+ // in <string>
+ template <class CharT>
+ class basic_string {
+ public:
+ __attribute__((__visibility__("hidden")))
+ const value_type* data() const noexcept { ... }
+ };
+
+ template class basic_string<char>;
+
+Since an explicit template instantiation declaration for ``basic_string<char>``
+is provided, the compiler is free to assume that ``basic_string<char>::data()``
+will be provided by another translation unit, and it is free to produce an
+external call to this function. However, since ``data()`` has hidden visibility
+and the explicit template instantiation is provided in a shared library (as
+opposed to simply another translation unit), ``basic_string<char>::data()``
+won't be found and a link error will ensue. This happens because the compiler
+assumes that ``basic_string<char>::data()`` is part of the explicit template
+instantiation declaration, when it really isn't. To tell the compiler that
+``data()`` is not part of the explicit template instantiation declaration, the
+``exclude_from_explicit_instantiation`` attribute can be used:
+
+ .. code-block:: c++
+
+ // in <string>
+ template <class CharT>
+ class basic_string {
+ public:
+ __attribute__((__visibility__("hidden")))
+ __attribute__((exclude_from_explicit_instantiation))
+ const value_type* data() const noexcept { ... }
+ };
+
+ template class basic_string<char>;
+
+Now, the compiler won't assume that ``basic_string<char>::data()`` is provided
+externally despite there being an explicit template instantiation declaration:
+the compiler will implicitly instantiate ``basic_string<char>::data()`` in the
+TUs where it is used.
+
+This attribute can be used on static and non-static member functions of class
+templates, static data members of class templates and member classes of class
+templates.
+ }];
+}
+
def DisableTailCallsDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -3364,11 +3570,11 @@ def IFuncDocs : Documentation {
let Content = [{
``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function.
-The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should take no arguments and return a pointer.
+The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should return a pointer.
The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline.
-Not all targets support this attribute. ELF targets support this attribute when using binutils v2.20.1 or higher and glibc v2.11.1 or higher. Non-ELF targets currently do not support this attribute.
+Not all targets support this attribute. ELF target support depends on both the linker and runtime linker, and is available in at least lld 4.0 and later, binutils 2.20.1 and later, glibc v2.11.1 and later, and FreeBSD 9.1 and later. Non-ELF targets currently do not support this attribute.
}];
}
@@ -3396,7 +3602,7 @@ See the RenderScript_ documentation for more information.
def XRayDocs : Documentation {
let Category = DocCatFunction;
- let Heading = "xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument), xray_log_args (clang::xray_log_args)";
+ let Heading = "xray_always_instrument, xray_never_instrument, xray_log_args";
let Content = [{
``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching.
@@ -3458,3 +3664,206 @@ the resulting instructions with the call site, rather than with the
corresponding line within the inlined callee.
}];
}
+
+def NoDerefDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+The ``noderef`` attribute causes clang to diagnose dereferences of annotated pointer types.
+This is ideally used with pointers that point to special memory which cannot be read
+from or written to, but allowing for the pointer to be used in pointer arithmetic.
+The following are examples of valid expressions where dereferences are diagnosed:
+
+.. code-block:: c
+
+ int __attribute__((noderef)) *p;
+ int x = *p; // warning
+
+ int __attribute__((noderef)) **p2;
+ x = **p2; // warning
+
+ int * __attribute__((noderef)) *p3;
+ p = *p3; // warning
+
+ struct S {
+ int a;
+ };
+ struct S __attribute__((noderef)) *s;
+ x = s->a; // warning
+ x = (*s).a; // warning
+
+Not all dereferences may diagnose a warning if the value directed by the pointer may not be
+accessed. The following are examples of valid expressions where may not be diagnosed:
+
+.. code-block:: c
+
+ int *q;
+ int __attribute__((noderef)) *p;
+ q = &*p;
+ q = *&p;
+
+ struct S {
+ int a;
+ };
+ struct S __attribute__((noderef)) *s;
+ p = &s->a;
+ p = &(*s).a;
+
+``noderef`` is currently only supported for pointers and arrays and not usable for
+references or Objective-C object pointers.
+
+.. code-block: c++
+
+ int x = 2;
+ int __attribute__((noderef)) &y = x; // warning: 'noderef' can only be used on an array or pointer type
+
+.. code-block: objc
+
+ id __attribute__((noderef)) obj = [NSObject new]; // warning: 'noderef' can only be used on an array or pointer type
+}];
+}
+
+def ReinitializesDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``reinitializes`` attribute can be applied to a non-static, non-const C++
+member function to indicate that this member function reinitializes the entire
+object to a known state, independent of the previous state of the object.
+
+This attribute can be interpreted by static analyzers that warn about uses of an
+object that has been left in an indeterminate state by a move operation. If a
+member function marked with the ``reinitializes`` attribute is called on a
+moved-from object, the analyzer can conclude that the object is no longer in an
+indeterminate state.
+
+A typical example where this attribute would be used is on functions that clear
+a container class:
+
+.. code-block:: c++
+
+ template <class T>
+ class Container {
+ public:
+ ...
+ [[clang::reinitializes]] void Clear();
+ ...
+ };
+ }];
+}
+
+def AlwaysDestroyDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``always_destroy`` attribute specifies that a variable with static or thread
+storage duration should have its exit-time destructor run. This attribute is the
+default unless clang was invoked with -fno-c++-static-destructors.
+ }];
+}
+
+def NoDestroyDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``no_destroy`` attribute specifies that a variable with static or thread
+storage duration shouldn't have its exit-time destructor run. Annotating every
+static and thread duration variable with this attribute is equivalent to
+invoking clang with -fno-c++-static-destructors.
+ }];
+}
+
+def UninitializedDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The command-line parameter ``-ftrivial-auto-var-init=*`` can be used to
+initialize trivial automatic stack variables. By default, trivial automatic
+stack variables are uninitialized. This attribute is used to override the
+command-line parameter, forcing variables to remain uninitialized. It has no
+semantic meaning in that using uninitialized values is undefined behavior,
+it rather documents the programmer's intent.
+ }];
+}
+
+def GnuInlineDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``gnu_inline`` changes the meaning of ``extern inline`` to use GNU inline
+semantics, meaning:
+
+* If any declaration that is declared ``inline`` is not declared ``extern``,
+then the ``inline`` keyword is just a hint. In particular, an out-of-line
+definition is still emitted for a function with external linkage, even if all
+call sites are inlined, unlike in C99 and C++ inline semantics.
+
+* If all declarations that are declared ``inline`` are also declared
+``extern``, then the function body is present only for inlining and no
+out-of-line version is emitted.
+
+Some important consequences: ``static inline`` emits an out-of-line
+version if needed, a plain ``inline`` definition emits an out-of-line version
+always, and an ``extern inline`` definition (in a header) followed by a
+(non-``extern``) ``inline`` declaration in a source file emits an out-of-line
+version of the function in that source file but provides the function body for
+inlining to all includers of the header.
+
+Either ``__GNUC_GNU_INLINE__`` (GNU inline semantics) or
+``__GNUC_STDC_INLINE__`` (C99 semantics) will be defined (they are mutually
+exclusive). If ``__GNUC_STDC_INLINE__`` is defined, then the ``gnu_inline``
+function attribute can be used to get GNU inline semantics on a per function
+basis. If ``__GNUC_GNU_INLINE__`` is defined, then the translation unit is
+already being compiled with GNU inline semantics as the implied default. It is
+unspecified which macro is defined in a C++ compilation.
+
+GNU inline semantics are the default behavior with ``-std=gnu89``,
+``-std=c89``, ``-std=c94``, or ``-fgnu89-inline``.
+ }];
+}
+
+def SpeculativeLoadHardeningDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+ This attribute can be applied to a function declaration in order to indicate
+ that `Speculative Load Hardening <https://llvm.org/docs/SpeculativeLoadHardening.html>`_
+ should be enabled for the function body. This can also be applied to a method
+ in Objective C.
+
+ Speculative Load Hardening is a best-effort mitigation against
+ information leak attacks that make use of control flow
+ miss-speculation - specifically miss-speculation of whether a branch
+ is taken or not. Typically vulnerabilities enabling such attacks are
+ classified as "Spectre variant #1". Notably, this does not attempt to
+ mitigate against miss-speculation of branch target, classified as
+ "Spectre variant #2" vulnerabilities.
+
+ When inlining, the attribute is sticky. Inlining a function that
+ carries this attribute will cause the caller to gain the
+ attribute. This is intended to provide a maximally conservative model
+ where the code in a function annotated with this attribute will always
+ (even after inlining) end up hardened.
+ }];
+}
+
+def ObjCExternallyRetainedDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``objc_externally_retained`` attribute can be applied to strong local
+variables, functions, methods, or blocks to opt into
+`externally-retained semantics
+<https://clang.llvm.org/docs/AutomaticReferenceCounting.html#externally-retained-variables>`_.
+
+When applied to the definition of a function, method, or block, every parameter
+of the function with implicit strong retainable object pointer type is
+considered externally-retained, and becomes ``const``. By explicitly annotating
+a parameter with ``__strong``, you can opt back into the default
+non-externally-retained behaviour for that parameter. For instance,
+``first_param`` is externally-retained below, but not ``second_param``:
+
+.. code-block:: objc
+
+ __attribute__((objc_externally_retained))
+ void f(NSArray *first_param, __strong NSArray *second_param) {
+ // ...
+ }
+
+Likewise, when applied to a strong local variable, that variable becomes
+``const`` and is considered externally-retained.
+
+When compiled without ``-fobjc-arc``, this attribute is ignored.
+}]; }
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index c4d11cd827c1..fa031ce09f6b 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -413,6 +413,9 @@ BUILTIN(__builtin_parityll, "iULLi", "nc")
BUILTIN(__builtin_popcount , "iUi" , "nc")
BUILTIN(__builtin_popcountl , "iULi" , "nc")
BUILTIN(__builtin_popcountll, "iULLi", "nc")
+BUILTIN(__builtin_clrsb , "ii" , "nc")
+BUILTIN(__builtin_clrsbl , "iLi" , "nc")
+BUILTIN(__builtin_clrsbll, "iLLi", "nc")
// FIXME: These type signatures are not correct for targets with int != 32-bits
// or with ULL != 64-bits.
@@ -425,6 +428,15 @@ BUILTIN(__builtin_bitreverse16, "UsUs", "nc")
BUILTIN(__builtin_bitreverse32, "UiUi", "nc")
BUILTIN(__builtin_bitreverse64, "ULLiULLi", "nc")
+BUILTIN(__builtin_rotateleft8, "UcUcUc", "nc")
+BUILTIN(__builtin_rotateleft16, "UsUsUs", "nc")
+BUILTIN(__builtin_rotateleft32, "UiUiUi", "nc")
+BUILTIN(__builtin_rotateleft64, "ULLiULLiULLi", "nc")
+BUILTIN(__builtin_rotateright8, "UcUcUc", "nc")
+BUILTIN(__builtin_rotateright16, "UsUsUs", "nc")
+BUILTIN(__builtin_rotateright32, "UiUiUi", "nc")
+BUILTIN(__builtin_rotateright64, "ULLiULLiULLi", "nc")
+
// Random GCC builtins
BUILTIN(__builtin_constant_p, "i.", "nctu")
BUILTIN(__builtin_classify_type, "i.", "nctu")
@@ -486,6 +498,7 @@ BUILTIN(__builtin_snprintf, "ic*zcC*.", "nFp:2:")
BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:")
BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:")
BUILTIN(__builtin_thread_pointer, "v*", "nc")
+BUILTIN(__builtin_launder, "v*v*", "nt")
// GCC exception builtins
BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t!
@@ -526,7 +539,7 @@ BUILTIN(__builtin_readcyclecounter, "ULLi", "n")
BUILTIN(__builtin_trap, "v", "nr")
BUILTIN(__builtin_debugtrap, "v", "n")
BUILTIN(__builtin_unreachable, "v", "nr")
-BUILTIN(__builtin_shufflevector, "v." , "nc")
+BUILTIN(__builtin_shufflevector, "v." , "nct")
BUILTIN(__builtin_convertvector, "v." , "nct")
BUILTIN(__builtin_alloca, "v*z" , "Fn")
BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn")
@@ -774,6 +787,7 @@ LANGBUILTIN(_InterlockedCompareExchange16, "ssD*ss", "n", ALL_MS_LANGUA
LANGBUILTIN(_InterlockedCompareExchange, "NiNiD*NiNi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange64, "LLiLLiD*LLiLLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchangePointer_nf, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement16, "ssD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "NiNiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
@@ -805,20 +819,23 @@ LANGBUILTIN(_interlockedbittestandset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_interlockedbittestandset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_interlockedbittestandset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt64, "ULLiULLi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt16, "UsUs", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt, "UiUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt64, "UWiUWi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt64, "UWiUWi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl8, "UcUcUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl16, "UsUsUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl, "UiUii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotl, "UNiUNii", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_rotl64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotl64, "UWiUWii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr8, "UcUcUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr16, "UsUsUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotr, "UiUii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_lrotr, "UNiUNii", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_rotr64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotr64, "UWiUWii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES)
@@ -1385,9 +1402,9 @@ BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n")
BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n")
// Checked Arithmetic Builtins for Security.
-BUILTIN(__builtin_add_overflow, "v.", "nt")
-BUILTIN(__builtin_sub_overflow, "v.", "nt")
-BUILTIN(__builtin_mul_overflow, "v.", "nt")
+BUILTIN(__builtin_add_overflow, "b.", "nt")
+BUILTIN(__builtin_sub_overflow, "b.", "nt")
+BUILTIN(__builtin_mul_overflow, "b.", "nt")
BUILTIN(__builtin_uadd_overflow, "bUiCUiCUi*", "n")
BUILTIN(__builtin_uaddl_overflow, "bULiCULiCULi*", "n")
BUILTIN(__builtin_uaddll_overflow, "bULLiCULLiCULLi*", "n")
diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
index b5d971d0bc6e..1892ff11a31d 100644
--- a/include/clang/Basic/BuiltinsAArch64.def
+++ b/include/clang/Basic/BuiltinsAArch64.def
@@ -94,6 +94,7 @@ TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LAN
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAdd, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -103,6 +104,110 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h"
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedExchange8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_acq, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_nf, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_rel, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_acq, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_nf, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_rel, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedOr8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedXor8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedAnd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedIncrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedDecrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_ReadStatusReg, "ii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_WriteStatusReg, "vii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
#undef BUILTIN
#undef LANGBUILTIN
#undef TARGET_HEADER_BUILTIN
diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def
index 4a447eb9f6a8..a25e45fe3fb8 100644
--- a/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/include/clang/Basic/BuiltinsAMDGPU.def
@@ -21,9 +21,10 @@
// SI+ only builtins.
//===----------------------------------------------------------------------===//
-BUILTIN(__builtin_amdgcn_dispatch_ptr, "Uc*4", "nc")
-BUILTIN(__builtin_amdgcn_kernarg_segment_ptr, "Uc*4", "nc")
-BUILTIN(__builtin_amdgcn_implicitarg_ptr, "Uc*4", "nc")
+BUILTIN(__builtin_amdgcn_dispatch_ptr, "v*4", "nc")
+BUILTIN(__builtin_amdgcn_kernarg_segment_ptr, "v*4", "nc")
+BUILTIN(__builtin_amdgcn_implicitarg_ptr, "v*4", "nc")
+BUILTIN(__builtin_amdgcn_queue_ptr, "v*4", "nc")
BUILTIN(__builtin_amdgcn_workgroup_id_x, "Ui", "nc")
BUILTIN(__builtin_amdgcn_workgroup_id_y, "Ui", "nc")
@@ -45,6 +46,8 @@ BUILTIN(__builtin_amdgcn_s_barrier, "v", "n")
BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n")
BUILTIN(__builtin_amdgcn_s_dcache_inv, "v", "n")
BUILTIN(__builtin_amdgcn_buffer_wbinvl1, "v", "n")
+
+// FIXME: Need to disallow constant address space.
BUILTIN(__builtin_amdgcn_div_scale, "dddbb*", "n")
BUILTIN(__builtin_amdgcn_div_scalef, "fffbb*", "n")
BUILTIN(__builtin_amdgcn_div_fmas, "ddddb", "nc")
@@ -93,9 +96,15 @@ BUILTIN(__builtin_amdgcn_ds_bpermute, "iii", "nc")
BUILTIN(__builtin_amdgcn_readfirstlane, "ii", "nc")
BUILTIN(__builtin_amdgcn_readlane, "iii", "nc")
BUILTIN(__builtin_amdgcn_fmed3f, "ffff", "nc")
-BUILTIN(__builtin_amdgcn_ds_faddf, "ff*fIiIiIb", "n")
-BUILTIN(__builtin_amdgcn_ds_fminf, "ff*fIiIiIb", "n")
-BUILTIN(__builtin_amdgcn_ds_fmaxf, "ff*fIiIiIb", "n")
+BUILTIN(__builtin_amdgcn_ds_faddf, "ff*3fIiIiIb", "n")
+BUILTIN(__builtin_amdgcn_ds_fminf, "ff*3fIiIiIb", "n")
+BUILTIN(__builtin_amdgcn_ds_fmaxf, "ff*3fIiIiIb", "n")
+
+//===----------------------------------------------------------------------===//
+// CI+ only builtins.
+//===----------------------------------------------------------------------===//
+TARGET_BUILTIN(__builtin_amdgcn_s_dcache_inv_vol, "v", "n", "ci-insts")
+TARGET_BUILTIN(__builtin_amdgcn_buffer_wbinvl1_vol, "v", "n", "ci-insts")
//===----------------------------------------------------------------------===//
// VI+ only builtins.
@@ -113,6 +122,8 @@ TARGET_BUILTIN(__builtin_amdgcn_fracth, "hh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_classh, "bhi", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_memrealtime, "LUi", "n", "s-memrealtime")
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nc", "dpp")
+TARGET_BUILTIN(__builtin_amdgcn_update_dpp, "iiiIiIiIiIb", "nc", "dpp")
+TARGET_BUILTIN(__builtin_amdgcn_s_dcache_wb, "v", "n", "vi-insts")
//===----------------------------------------------------------------------===//
// GFX9+ only builtins.
@@ -124,13 +135,13 @@ TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts")
// Deep learning builtins.
//===----------------------------------------------------------------------===//
-TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dl-insts")
-TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSiIb", "nc", "dl-insts")
-TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUiIb", "nc", "dl-insts")
-TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSiIb", "nc", "dl-insts")
-TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dl-insts")
-TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dl-insts")
-TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dl-insts")
+TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dot-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSiIb", "nc", "dot-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUiIb", "nc", "dot-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSiIb", "nc", "dot-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dot-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dot-insts")
+TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dot-insts")
//===----------------------------------------------------------------------===//
// Special builtins.
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 941d320d729f..ad778527b212 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -230,6 +230,104 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h"
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedExchange8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_acq, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_nf, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_rel, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_acq, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_nf, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_rel, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedOr8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedXor8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedAnd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedIncrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedDecrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
#undef BUILTIN
#undef LANGBUILTIN
#undef TARGET_HEADER_BUILTIN
diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def
index f976720d116d..bb040c06fd07 100644
--- a/include/clang/Basic/BuiltinsHexagon.def
+++ b/include/clang/Basic/BuiltinsHexagon.def
@@ -63,1676 +63,1756 @@ BUILTIN(__builtin_HEXAGON_S2_storerf_pcr, "vv*iivC*", "")
BUILTIN(__builtin_HEXAGON_S2_storeri_pcr, "vv*iivC*", "")
BUILTIN(__builtin_HEXAGON_S2_storerd_pcr, "vv*iLLivC*", "")
-// The builtins above are not autogenerated from iset.py.
-// Make sure you do not overwrite these.
+BUILTIN(__builtin_HEXAGON_prefetch,"vv*","")
+BUILTIN(__builtin_HEXAGON_Y2_dccleana,"vv*","")
+BUILTIN(__builtin_HEXAGON_Y2_dccleaninva,"vv*","")
+BUILTIN(__builtin_HEXAGON_Y2_dcinva,"vv*","")
+BUILTIN(__builtin_HEXAGON_Y2_dczeroa,"vv*","")
+BUILTIN(__builtin_HEXAGON_Y4_l2fetch,"vv*Ui","")
+BUILTIN(__builtin_HEXAGON_Y5_l2fetch,"vv*LLUi","")
-BUILTIN(__builtin_HEXAGON_C2_cmpeq,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpgt,"iii","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai_128B,"vV32iv*V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai_128B,"vV32iv*V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B,"vV32iv*V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B,"vV32iv*V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq,"vV16iv*V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq_128B,"vV32iv*V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq_128B,"vV32iv*V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq_128B,"vV32iv*V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq_128B,"vV32iv*V32i","")
+
+BUILTIN(__builtin_HEXAGON_V6_vgathermw,"vv*iiV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermw_128B,"vv*iiV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermh,"vv*iiV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermh_128B,"vv*iiV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhw,"vv*iiV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhw_128B,"vv*iiV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermwq,"vv*V16iiiV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermwq_128B,"vv*V32iiiV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhq,"vv*V16iiiV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhq_128B,"vv*V32iiiV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhwq,"vv*V16iiiV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgathermhwq_128B,"vv*V32iiiV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw,"viiV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw_128B,"viiV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh,"viiV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh_128B,"viiV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw_add,"viiV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermw_add_128B,"viiV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh_add,"viiV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermh_add_128B,"viiV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermwq,"vV16iiiV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermwq_128B,"vV32iiiV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhq,"vV16iiiV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhq_128B,"vV32iiiV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw,"viiV32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw_128B,"viiV64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhwq,"vV16iiiV32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhwq_128B,"vV32iiiV64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add,"viiV32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add_128B,"viiV64iV32i","")
+
+// ---------------------------------------------------------------------
+// Auto-generated definitions.
+
+// V5 Scalar Instructions.
+
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax,"iiiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpysu_up,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyi_whc,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax,"iiiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffoh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_sfmax,"fff","")
+BUILTIN(__builtin_HEXAGON_A2_vabswsat,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_combineri,"LLiiIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_vpmpyh_acc,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_notp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_C4_or_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_brevp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_pmpyw_acc,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_cl1,"ii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplte,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddws,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_maxup,"ULLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmphgti,"iLLiIi","")
+BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_abssat,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu,"iLLiLLi","")
BUILTIN(__builtin_HEXAGON_C2_cmpgtu,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpeqp,"iLLiLLi","")
BUILTIN(__builtin_HEXAGON_C2_cmpgtp,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_C2_cmpgtup,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_rcmpeqi,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_rcmpneqi,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_rcmpeq,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_rcmpneq,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_bitsset,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_bitsclr,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_nbitsset,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_nbitsclr,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpeqi,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpgti,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpgtui,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpgei,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpgeui,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmplt,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_cmpltu,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_bitsclri,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_nbitsclri,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_cmpneqi,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_cmpltei,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_cmplteui,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_cmpneq,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_cmplte,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_cmplteu,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_and,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_or,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_xor,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_andn,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgtui,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgti,"iiIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyi,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2uw_chop,"id","")
+BUILTIN(__builtin_HEXAGON_A4_cmpheq,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_vrcnegh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_extractup,"LLiLLiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S4_ntstbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_w2sf,"fi","")
BUILTIN(__builtin_HEXAGON_C2_not,"ii","")
-BUILTIN(__builtin_HEXAGON_C2_orn,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_and_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_C4_and_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_C4_or_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_C4_or_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_C4_and_andn,"iiii","")
-BUILTIN(__builtin_HEXAGON_C4_and_orn,"iiii","")
-BUILTIN(__builtin_HEXAGON_C4_or_andn,"iiii","")
-BUILTIN(__builtin_HEXAGON_C4_or_orn,"iiii","")
-BUILTIN(__builtin_HEXAGON_C2_pxfer_map,"ii","")
-BUILTIN(__builtin_HEXAGON_C2_any8,"ii","")
-BUILTIN(__builtin_HEXAGON_C2_all8,"ii","")
-BUILTIN(__builtin_HEXAGON_C2_vitpack,"iii","")
-BUILTIN(__builtin_HEXAGON_C2_mux,"iiii","")
-BUILTIN(__builtin_HEXAGON_C2_muxii,"iiii","")
-BUILTIN(__builtin_HEXAGON_C2_muxir,"iiii","")
-BUILTIN(__builtin_HEXAGON_C2_muxri,"iiii","")
-BUILTIN(__builtin_HEXAGON_C2_vmux,"LLiiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_C2_mask,"LLii","")
-BUILTIN(__builtin_HEXAGON_A2_vcmpbeq,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpbeqi,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpbeq_any,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpbgtui,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpbgt,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpbgti,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_cmpbeq,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmpbeqi,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmpbgtu,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmpbgtui,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_tfrpr,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0,"iii","")
BUILTIN(__builtin_HEXAGON_A4_cmpbgt,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmpbgti,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_vcmpheq,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vcmphgt,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vcmphgtu,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpheqi,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vcmphgti,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vcmphgtui,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_cmpheq,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmphgt,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmphgtu,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmpheqi,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmphgti,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cmphgtui,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_vcmpweq,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vcmpwgt,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpweqi,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpwgti,"iLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vcmpwgtui,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpneqi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_subacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_orp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_up,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_vh,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_vw,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgtu,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbeq_any,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgti,"iiIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_addsp,"LLiiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpheqi,"iLLiIi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_pmpyw,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_pxorf,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgei,"iiIi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_vrminuw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_F2_sffma,"ffff","")
+BUILTIN(__builtin_HEXAGON_A2_absp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_all8,"ii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminuh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_F2_sffma_lib,"ffff","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_bitsset,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpysip,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpysin,"iiUIi","")
BUILTIN(__builtin_HEXAGON_A4_boundscheck,"iiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_tlbmatch,"iLLii","")
-BUILTIN(__builtin_HEXAGON_C2_tfrpr,"ii","")
-BUILTIN(__builtin_HEXAGON_C2_tfrrp,"ii","")
+BUILTIN(__builtin_HEXAGON_M5_vrmpybuu,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_C4_fastcorner9,"iii","")
-BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp,"iLLii","")
+BUILTIN(__builtin_HEXAGON_A2_neg,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_subsat,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgh,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_ud2df,"dLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S4_subi_lsr_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_vzxthw,"LLii","")
+BUILTIN(__builtin_HEXAGON_F2_sfadd,"fff","")
+BUILTIN(__builtin_HEXAGON_A2_sub,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2su_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2su_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_insert,"iiiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_packhl,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpwgti,"iLLiIi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_and_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_d2df,"dLLi","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtui,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_vconj,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_clbp,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_any8,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_togglebit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_togglebit_i,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_uw2sf,"fi","")
+BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmacs_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacs_s1,"LLiLLiii","")
BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s0,"iii","")
BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_clrbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_C4_or_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpwgtui,"iLLiUIi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpbeq,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmphgt,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgwcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgwcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_vnavghr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyi_wh,"iLLii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrsi,"iIi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_svnavgh,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmphgtui,"iLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_svavgh,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_combine_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_negsat,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_bitsplit,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_vabshsat,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyui,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_C2_cmplt,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacr_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyrr_addi,"iUIiii","")
+BUILTIN(__builtin_HEXAGON_S4_or_andi,"iiiIi","")
BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s0,"iii","")
BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyrr_addr,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupn,"fff","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1,"LLiLLiii","")
BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s0,"iii","")
BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vadduhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubuhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_xorp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_tfrpcp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_zxtb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_zxth,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_or_xor,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmacbsu,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0,"LLiLLiii","")
BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s0,"iii","")
BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_F2_sffms_lib,"ffff","")
+BUILTIN(__builtin_HEXAGON_C4_cmpneqi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_M4_and_xor,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_sat,"iLLi","")
BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A2_addsat,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svavghs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_bitsclri,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vradduh,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_addp_c,"LLiLLiLLiv*","")
+BUILTIN(__builtin_HEXAGON_C2_xor,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2ud_chop,"LLid","")
+BUILTIN(__builtin_HEXAGON_C4_or_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_vxaddsubhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsathub,"iLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2sf,"fd","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vavgwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax,"iiiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_sxth,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_sxtb,"ii","")
+BUILTIN(__builtin_HEXAGON_C4_or_orn,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_sxtw,"LLii","")
+BUILTIN(__builtin_HEXAGON_M2_vabsdiffh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_cl1p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vabsdiffw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_andnp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_vmux,"LLiiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_parityp,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or,"iiiUIi","")
BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s0,"iiii","")
BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s1,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpeq,"iff","")
+BUILTIN(__builtin_HEXAGON_A2_vaddb_map,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpheq,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_clbnorm,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S4_subaddi,"iiIii","")
BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpysmi,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_macsip,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_macsin,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0,"ULLiii","")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_up,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_tstbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_vrcrotate,"LLiLLiiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_tstbit_i,"iiUIi","")
BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1_sat,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyu_up,"Uiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpysu_up,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M4_mac_up_s1_sat,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_nac_up_s1_sat,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyi,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mpyui,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_maci,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_acci,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_accii,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_nacci,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_naccii,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_subacc,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_mpyrr_addr,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_mpyri_addr_u2,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_mpyri_addr,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_mpyri_addi,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_mpyrr_addi,"iiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2su_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2su_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vmac2es,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrmac_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_extractu_rp,"iiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_or_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_w2df,"di","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpeqi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_vcnegh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpweqi,"iLLiIi","")
BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s0,"iLLiLLi","")
BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s1,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M5_vrmpybuu,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M5_vrmacbuu,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M5_vrmpybsu,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M5_vrmacbsu,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M5_vmpybuu,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M5_vmpybsu,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M5_vmacbuu,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M5_vmacbsu,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M5_vdmpybsu,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M5_vdmacbsu,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_xor_xacc,"LLiLLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_M2_vdmpys_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_cmacs_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cmacs_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgubr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_cl0p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_valignib,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupd,"fff","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0,"iii","")
BUILTIN(__builtin_HEXAGON_M2_cmacsc_s0,"LLiLLiii","")
BUILTIN(__builtin_HEXAGON_M2_cmacsc_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpys_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpys_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cnacs_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cnacs_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp,"iLLii","")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_hmmpyl_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_hmmpyh_s1,"iii","")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_ct1,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_ct0,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0,"LLiLLiii","")
BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_ntstbit_i,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupr,"ff","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmphgtu,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_andn,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_addaddi,"iiiIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpeqi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_M4_xor_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and,"LLiLLiLLiUIi","")
BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs1,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_cmaci_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cmacr_s0,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M4_cmpyi_wh,"iLLii","")
-BUILTIN(__builtin_HEXAGON_M4_cmpyr_wh,"iLLii","")
-BUILTIN(__builtin_HEXAGON_M4_cmpyi_whc,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_A4_round_ri,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_max,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_round_rr,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_combineii,"LLiIiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_combineir,"LLiIii","")
+BUILTIN(__builtin_HEXAGON_C4_and_orn,"iiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmacbuu,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpeq,"iii","")
BUILTIN(__builtin_HEXAGON_M4_cmpyr_whc,"iLLii","")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vcrotate,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S4_vrcrotate_acc,"LLiLLiLLiii","")
-BUILTIN(__builtin_HEXAGON_S4_vrcrotate,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_S2_vcnegh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_vrcnegh,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_M4_pmpyw,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M4_vpmpyh,"LLiii","")
-BUILTIN(__builtin_HEXAGON_M4_pmpyw_acc,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_M4_vpmpyh_acc,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_A2_add,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_sub,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addsat,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subsat,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addi,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_vzxtbh,"LLii","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combinew,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S4_ori_asl_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsset,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0,"Uiii","")
BUILTIN(__builtin_HEXAGON_A2_addh_l16_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_aslh,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_asrh,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_addp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_addpsat,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_addsp,"LLiiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_subp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_neg,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_negsat,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_abs,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_abssat,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_vconj,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_negp,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_absp,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_max,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_maxu,"Uiii","")
-BUILTIN(__builtin_HEXAGON_A2_min,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_A4_modwrapu,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpneq,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_F2_sfimm_p,"fUIi","")
+BUILTIN(__builtin_HEXAGON_F2_sfimm_n,"fUIi","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyr_wh,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_vavgub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_d2sf,"fLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbeqi,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpuo,"iff","")
+BUILTIN(__builtin_HEXAGON_A2_vavguw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or,"LLiLLiLLii","")
BUILTIN(__builtin_HEXAGON_A2_minu,"Uiii","")
-BUILTIN(__builtin_HEXAGON_A2_maxp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_maxup,"ULLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_minp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_minup,"ULLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_tfr,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_tfrsi,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_tfrp,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_tfrpi,"LLii","")
-BUILTIN(__builtin_HEXAGON_A2_zxtb,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_sxtb,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_zxth,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_sxth,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_combinew,"LLiii","")
-BUILTIN(__builtin_HEXAGON_A4_combineri,"LLiii","")
-BUILTIN(__builtin_HEXAGON_A4_combineir,"LLiii","")
-BUILTIN(__builtin_HEXAGON_A2_combineii,"LLiii","")
-BUILTIN(__builtin_HEXAGON_A2_combine_hh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_combine_hl,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_combine_lh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_combine_ll,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_tfril,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_tfrih,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_and,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_or,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_xor,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_not,"ii","")
-BUILTIN(__builtin_HEXAGON_M2_xor_xacc,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_xor_xacc,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_andn,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_orn,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_andnp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_ornp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S4_addaddi,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_subaddi,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_and_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_and_andn,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_and_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_and_xor,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_or_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1,"iii","")
BUILTIN(__builtin_HEXAGON_M4_or_andn,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_or_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_or_xor,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_or_andix,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_or_andi,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_or_ori,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_xor_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_xor_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_M4_xor_andn,"iiii","")
-BUILTIN(__builtin_HEXAGON_A2_subri,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_andir,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_orir,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_andp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_orp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_xorp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_notp,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_sxtw,"LLii","")
-BUILTIN(__builtin_HEXAGON_A2_sat,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_minp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_or_andix,"iiiIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpge,"iff","")
+BUILTIN(__builtin_HEXAGON_F2_sfmin,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpgt,"iff","")
+BUILTIN(__builtin_HEXAGON_M4_vpmpyh,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0,"LLiii","")
BUILTIN(__builtin_HEXAGON_A2_roundsat,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S4_extract_rp,"iiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplteui,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S4_addi_lsr_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_tfrcpp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun,"iLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgti,"iiIi","")
+BUILTIN(__builtin_HEXAGON_A4_vrminh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgtu,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_insertp_rp,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavghcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_subi_asl_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vsubws,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_A2_sath,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_satuh,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_satub,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_xor,"LLiLLiLLii","")
BUILTIN(__builtin_HEXAGON_A2_satb,"ii","")
-BUILTIN(__builtin_HEXAGON_A2_vaddub,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vaddb_map,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vaddubs,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vaddh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vaddhs,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vadduhs,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A5_vaddhubs,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vaddw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vaddws,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_cmpltu,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_insertp,"LLiLLiLLiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_extractup_rp,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_S4_vxaddsubw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S4_vxsubaddw,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_S4_vxaddsubh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S4_vxsubaddh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S4_vxaddsubhr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S4_vxsubaddhr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_svavgh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svavghs,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svnavgh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svaddh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svaddhs,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svadduhs,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svsubh,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svsubhs,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_svsubuhs,"iii","")
-BUILTIN(__builtin_HEXAGON_A2_vraddub,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vraddub_acc,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vraddh,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vradduh,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vsubub,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vsubb_map,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_asrh,"ii","")
+BUILTIN(__builtin_HEXAGON_S4_extractp_rp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_C2_or,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_xor,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_add,"iii","")
BUILTIN(__builtin_HEXAGON_A2_vsububs,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vsubh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vsubhs,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vsubuhs,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vsubw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vsubws,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vabsh,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vabshsat,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vabsw,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vabswsat,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vabsdiffw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_M2_vabsdiffh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_vraddub_acc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_sfinvsqrta,"ff","")
+BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_svaddh,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_vcrotate,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_aslh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplatrh,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplatrb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_muxri,"iiIii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_pxfer_map,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_vaddw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpeqp,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addi,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_not,"ii","")
+BUILTIN(__builtin_HEXAGON_S4_andi_lsr_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_macsip,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_tfrcrr,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_macsin,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_C2_orn,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_and_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_F2_sfmpy,"fff","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_M4_and_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_C2_mask,"LLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgt,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmacbsu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax,"iiiUIiUIi","")
BUILTIN(__builtin_HEXAGON_A2_vrsadub,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavgub,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavguh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavgh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vnavgh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavgw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vnavgw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavgwr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vnavgwr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavgwcr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vnavgwcr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavghcr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vnavghcr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavguw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavguwr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavgubr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavguhr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vavghr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vnavghr,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_round_ri,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_round_rr,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_round_ri_sat,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_round_rr_sat,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cround_ri,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_cround_rr,"iii","")
-BUILTIN(__builtin_HEXAGON_A4_vrminh,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vrmaxh,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vrminuh,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vrmaxuh,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vrminw,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vrmaxw,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vrminuw,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A4_vrmaxuw,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_A2_vminb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_tfrrcr,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpge,"idd","")
+BUILTIN(__builtin_HEXAGON_M2_accii,"iiiIi","")
+BUILTIN(__builtin_HEXAGON_A5_vaddhubs,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxw,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_A2_vmaxb,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vminub,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vmaxub,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vminh,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_A2_vmaxh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vminuh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vmaxuh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vminw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vmaxw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vminuw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A2_vmaxuw,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_A4_modwrapu,"iii","")
-BUILTIN(__builtin_HEXAGON_F2_sfadd,"fff","")
-BUILTIN(__builtin_HEXAGON_F2_sfsub,"fff","")
-BUILTIN(__builtin_HEXAGON_F2_sfmpy,"fff","")
-BUILTIN(__builtin_HEXAGON_F2_sffma,"ffff","")
-BUILTIN(__builtin_HEXAGON_F2_sffma_sc,"ffffi","")
-BUILTIN(__builtin_HEXAGON_F2_sffms,"ffff","")
-BUILTIN(__builtin_HEXAGON_F2_sffma_lib,"ffff","")
-BUILTIN(__builtin_HEXAGON_F2_sffms_lib,"ffff","")
-BUILTIN(__builtin_HEXAGON_F2_sfcmpeq,"iff","")
-BUILTIN(__builtin_HEXAGON_F2_sfcmpgt,"iff","")
-BUILTIN(__builtin_HEXAGON_F2_sfcmpge,"iff","")
-BUILTIN(__builtin_HEXAGON_F2_sfcmpuo,"iff","")
-BUILTIN(__builtin_HEXAGON_F2_sfmax,"fff","")
-BUILTIN(__builtin_HEXAGON_F2_sfmin,"fff","")
-BUILTIN(__builtin_HEXAGON_F2_sfclass,"ifi","")
-BUILTIN(__builtin_HEXAGON_F2_sfimm_p,"fi","")
-BUILTIN(__builtin_HEXAGON_F2_sfimm_n,"fi","")
-BUILTIN(__builtin_HEXAGON_F2_sffixupn,"fff","")
-BUILTIN(__builtin_HEXAGON_F2_sffixupd,"fff","")
-BUILTIN(__builtin_HEXAGON_F2_sffixupr,"ff","")
-BUILTIN(__builtin_HEXAGON_F2_dfcmpeq,"idd","")
-BUILTIN(__builtin_HEXAGON_F2_dfcmpgt,"idd","")
-BUILTIN(__builtin_HEXAGON_F2_dfcmpge,"idd","")
-BUILTIN(__builtin_HEXAGON_F2_dfcmpuo,"idd","")
-BUILTIN(__builtin_HEXAGON_F2_dfclass,"idi","")
-BUILTIN(__builtin_HEXAGON_F2_dfimm_p,"di","")
-BUILTIN(__builtin_HEXAGON_F2_dfimm_n,"di","")
-BUILTIN(__builtin_HEXAGON_F2_conv_sf2df,"df","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2sf,"fd","")
-BUILTIN(__builtin_HEXAGON_F2_conv_uw2sf,"fi","")
-BUILTIN(__builtin_HEXAGON_F2_conv_uw2df,"di","")
-BUILTIN(__builtin_HEXAGON_F2_conv_w2sf,"fi","")
-BUILTIN(__builtin_HEXAGON_F2_conv_w2df,"di","")
-BUILTIN(__builtin_HEXAGON_F2_conv_ud2sf,"fLLi","")
-BUILTIN(__builtin_HEXAGON_F2_conv_ud2df,"dLLi","")
-BUILTIN(__builtin_HEXAGON_F2_conv_d2sf,"fLLi","")
-BUILTIN(__builtin_HEXAGON_F2_conv_d2df,"dLLi","")
-BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw,"if","")
+BUILTIN(__builtin_HEXAGON_S2_vsxthw,"LLii","")
+BUILTIN(__builtin_HEXAGON_S4_andi_asl_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgt,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2d_chop,"LLid","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1,"iiii","")
BUILTIN(__builtin_HEXAGON_F2_conv_sf2w,"if","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_F2_sfclass,"ifUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_addasl_rrri,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_M5_vdmpybsu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_addi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_A2_addp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_clbpnorm,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A4_round_rr_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_nacci,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_shuffeh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw,"if","")
+BUILTIN(__builtin_HEXAGON_A2_vsubh,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud,"LLif","")
-BUILTIN(__builtin_HEXAGON_F2_conv_sf2d,"LLif","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2uw,"id","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2w,"id","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2ud,"LLid","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2d,"LLid","")
+BUILTIN(__builtin_HEXAGON_A2_vsubw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpwgt,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_xor_or,"iiii","")
BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw_chop,"if","")
-BUILTIN(__builtin_HEXAGON_F2_conv_sf2w_chop,"if","")
-BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud_chop,"LLif","")
-BUILTIN(__builtin_HEXAGON_F2_conv_sf2d_chop,"LLif","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2uw_chop,"id","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2w_chop,"id","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2ud_chop,"LLid","")
-BUILTIN(__builtin_HEXAGON_F2_conv_df2d_chop,"LLid","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubuhs,"iii","")
+BUILTIN(__builtin_HEXAGON_M5_vmpybsu,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_C4_and_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0,"iiii","")
BUILTIN(__builtin_HEXAGON_S2_lsr_r_p,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_subp_c,"LLiLLiLLiv*","")
+BUILTIN(__builtin_HEXAGON_A2_vsubhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_vitpack,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vavguhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsplicerb,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsclr,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmpys_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpys_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpuo,"idd","")
+BUILTIN(__builtin_HEXAGON_S2_shuffob,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_and,"iii","")
+BUILTIN(__builtin_HEXAGON_S5_popcountp,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S4_extractp,"LLiLLiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_cl0,"ii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgti,"iLLiIi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C4_cmpneq,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_S2_clb,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_maci,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxuh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_bitspliti,"LLiiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrmac_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2d,"LLif","")
BUILTIN(__builtin_HEXAGON_S2_asr_r_r_nac,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_F2_dfimm_n,"dUIi","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgt,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_dfimm_p,"dUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addr_u2,"iiUIii","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_nac,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M5_vrmacbuu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,"iLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_vspliceib,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacs_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacs_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A2_maxu,"Uiii","")
+BUILTIN(__builtin_HEXAGON_A2_maxp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_andir,"iiIi","")
+BUILTIN(__builtin_HEXAGON_F2_sfrecipa,"fff","")
+BUILTIN(__builtin_HEXAGON_A2_combineii,"LLiIiIi","")
+BUILTIN(__builtin_HEXAGON_A4_orn,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgtui,"iiUIi","")
BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbeqi,"iLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_or,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpeq,"idd","")
+BUILTIN(__builtin_HEXAGON_C2_cmpeq,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_C4_and_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_satuh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_satub,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S4_or_ori,"iiiIi","")
+BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrih,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_tfril,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addr,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunehb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabsw,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabsh,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_sfsub,"fff","")
+BUILTIN(__builtin_HEXAGON_C2_muxii,"iiIiIi","")
+BUILTIN(__builtin_HEXAGON_C2_muxir,"iiiIi","")
+BUILTIN(__builtin_HEXAGON_A2_swiz,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vraddub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_tlbmatch,"iLLii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2w_chop,"id","")
+BUILTIN(__builtin_HEXAGON_A2_and,"iii","")
BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_and,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_p_xor,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_p_xor,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_xor,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_xor,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S4_lsli,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_addasl_rrri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_andi_asl_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_ori_asl_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_addi_asl_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_subi_asl_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_andi_lsr_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_ori_lsr_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_addi_lsr_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S4_subi_lsr_ri,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_valignib,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_valignrb,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_vspliceib,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_vsplicerb,"LLiLLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_vsplatrh,"LLii","")
-BUILTIN(__builtin_HEXAGON_S2_vsplatrb,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_insert,"iiiii","")
-BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax,"iiiii","")
-BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax,"iiiii","")
-BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax,"iiiii","")
-BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax,"iiiii","")
-BUILTIN(__builtin_HEXAGON_A4_bitspliti,"LLiii","")
-BUILTIN(__builtin_HEXAGON_A4_bitsplit,"LLiii","")
-BUILTIN(__builtin_HEXAGON_S4_extract,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_extractu,"iiii","")
-BUILTIN(__builtin_HEXAGON_S2_insertp,"LLiLLiLLiii","")
-BUILTIN(__builtin_HEXAGON_S4_extractp,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_S2_extractup,"LLiLLiii","")
-BUILTIN(__builtin_HEXAGON_S2_insert_rp,"iiiLLi","")
-BUILTIN(__builtin_HEXAGON_S4_extract_rp,"iiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_extractu_rp,"iiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_insertp_rp,"LLiLLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S4_extractp_rp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_extractup_rp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_tstbit_i,"iii","")
-BUILTIN(__builtin_HEXAGON_S4_ntstbit_i,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_setbit_i,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_togglebit_i,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_clrbit_i,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_tstbit_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S4_ntstbit_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_setbit_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_togglebit_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_clrbit_r,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_vh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_vh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_vh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,"iLLii","")
-BUILTIN(__builtin_HEXAGON_S5_asrhub_sat,"iLLii","")
-BUILTIN(__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_vh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_vw,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun,"iLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun,"iLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_i_vw,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asr_r_vw,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_asl_r_vw,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw,"LLiLLii","")
-BUILTIN(__builtin_HEXAGON_S2_vrndpackwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_extract,"iiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpweq,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_acci,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_ud2sf,"fLLi","")
+BUILTIN(__builtin_HEXAGON_A2_tfr,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_subri,"iIii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxuw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M5_vmpybuu,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxuh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_vw,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_brev,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_vavgh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_clrbit_i,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_vh,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_naccii,"iiiIi","")
BUILTIN(__builtin_HEXAGON_S2_vrndpackwhs,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vsxtbh,"LLii","")
-BUILTIN(__builtin_HEXAGON_S2_vzxtbh,"LLii","")
-BUILTIN(__builtin_HEXAGON_S2_vsathub,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_svsathub,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_svsathb,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_vsathb,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vtrunohb,"iLLi","")
BUILTIN(__builtin_HEXAGON_S2_vtrunewh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_mac_up_s1_sat,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_vrcrotate_acc,"LLiLLiLLiiUIi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_uw2df,"di","")
+BUILTIN(__builtin_HEXAGON_A2_vaddubs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_orir,"iiIi","")
+BUILTIN(__builtin_HEXAGON_A2_andp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lfsp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_min,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpysmi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2df,"df","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunohb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2d_chop,"LLif","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2w,"id","")
+BUILTIN(__builtin_HEXAGON_S5_asrhub_sat,"iLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2d,"LLid","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_svadduhs,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2w_chop,"if","")
+BUILTIN(__builtin_HEXAGON_S2_svsathub,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_setbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vavghr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_sffma_sc,"ffffi","")
+BUILTIN(__builtin_HEXAGON_F2_dfclass,"idUIi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2ud,"LLid","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2uw,"id","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_C4_cmpltei,"iiIi","")
+BUILTIN(__builtin_HEXAGON_C4_cmplteu,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vsubb_map,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_minup,"ULLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_valignrb,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_combine_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_M5_vdmacbsu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_combine_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_addpsat,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_svaddhs,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_ori_lsr_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vminw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_lsli,"iIii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_vraddh,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_tfrrp,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1,"iiii","")
BUILTIN(__builtin_HEXAGON_S2_vtrunowh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vtrunehb,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vsxthw,"LLii","")
-BUILTIN(__builtin_HEXAGON_S2_vzxthw,"LLii","")
-BUILTIN(__builtin_HEXAGON_S2_vsatwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_abs,"ii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbeq,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_negp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl,"iii","")
BUILTIN(__builtin_HEXAGON_S2_vsatwuh,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_packhl,"LLiii","")
-BUILTIN(__builtin_HEXAGON_A2_swiz,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_shuffob,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpgt,"idd","")
+BUILTIN(__builtin_HEXAGON_S2_svsathb,"ii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtup,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_cround_ri,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S4_clbpaddi,"iLLiIi","")
+BUILTIN(__builtin_HEXAGON_A4_cround_rr,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_mux,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0,"ULLiii","")
BUILTIN(__builtin_HEXAGON_S2_shuffeb,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_shuffoh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_shuffeh,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S5_popcountp,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminuw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_insert_rp,"iiiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminuh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_extractu,"iiUIiUIi","")
+BUILTIN(__builtin_HEXAGON_A2_svsubh,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_clbaddi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_F2_sffms,"ffff","")
+BUILTIN(__builtin_HEXAGON_S2_vsxtbh,"LLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A2_subp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0,"LLiLLiLLi","")
BUILTIN(__builtin_HEXAGON_S4_parity,"iii","")
-BUILTIN(__builtin_HEXAGON_S2_parityp,"iLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_lfsp,"LLiLLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_clbnorm,"ii","")
-BUILTIN(__builtin_HEXAGON_S4_clbaddi,"iii","")
-BUILTIN(__builtin_HEXAGON_S4_clbpnorm,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S4_clbpaddi,"iLLii","")
-BUILTIN(__builtin_HEXAGON_S2_clb,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_cl0,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_cl1,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_clbp,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_cl0p,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_cl1p,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_brev,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_brevp,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_ct0,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_ct1,"ii","")
-BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","")
-BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","")
-BUILTIN(__builtin_HEXAGON_prefetch,"vv*","")
-BUILTIN(__builtin_HEXAGON_Y2_dccleana,"vv*","")
-BUILTIN(__builtin_HEXAGON_Y2_dccleaninva,"vv*","")
-BUILTIN(__builtin_HEXAGON_Y2_dcinva,"vv*","")
-BUILTIN(__builtin_HEXAGON_Y2_dczeroa,"vv*","")
-BUILTIN(__builtin_HEXAGON_Y4_l2fetch,"vv*Ui","")
-BUILTIN(__builtin_HEXAGON_Y5_l2fetch,"vv*LLUi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_addi_asl_ri,"iUIiiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_cmpheqi,"iiIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud_chop,"LLif","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgeui,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_nac_up_s1_sat,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A4_round_ri_sat,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_vavghcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmaci_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_setbit_i,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_andn,"iii","")
+BUILTIN(__builtin_HEXAGON_M5_vrmpybsu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vrndpackwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxuw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_bitsclr,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_xor_xacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgtui,"iLLiUIi","")
+BUILTIN(__builtin_HEXAGON_A4_ornp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_tfrpi,"LLiIi","")
+BUILTIN(__builtin_HEXAGON_C4_and_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsclri,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc,"LLiLLiLLiUIi","")
+
+// V55 Scalar Instructions.
+
+BUILTIN(__builtin_HEXAGON_A5_ACS,"LLiLLiLLiLLi","")
+
+// V60 Scalar Instructions.
+
+BUILTIN(__builtin_HEXAGON_S6_rol_i_p_and,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_r_xacc,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_r_and,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_r_acc,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_p_xacc,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_p,"LLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_p_nac,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_p_acc,"LLiLLiLLiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_r_or,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_r,"iiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_r_nac,"iiiUIi","")
+BUILTIN(__builtin_HEXAGON_S6_rol_i_p_or,"LLiLLiLLiUIi","")
+
+// V62 Scalar Instructions.
+
+BUILTIN(__builtin_HEXAGON_S6_vtrunehb_ppp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_V6_ldntnt0,"V16ii","")
+BUILTIN(__builtin_HEXAGON_M6_vabsdiffub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S6_vtrunohb_ppp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M6_vabsdiffb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A6_vminub_RdP,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S6_vsplatrbp,"LLii","")
+
+// V65 Scalar Instructions.
+
+BUILTIN(__builtin_HEXAGON_A6_vcmpbeq_notany,"iLLiLLi","")
+
+// V66 Scalar Instructions.
+
+BUILTIN(__builtin_HEXAGON_F2_dfsub,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfadd,"ddd","")
+BUILTIN(__builtin_HEXAGON_M2_mnaci,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_mask,"iUIiUIi","")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_r,"iii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_p,"LLiLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_r_acc,"iiii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_p_acc,"LLiLLiLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_r_nac,"iiii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_p_nac,"LLiLLiLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_r_xacc,"iiii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_p_xacc,"LLiLLiLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_r_and,"iiii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_r_or,"iiii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_p_and,"LLiLLiLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_S6_rol_i_p_or,"LLiLLiLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_S2_cabacencbin,"LLiLLiLLii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_valignb,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_valignb_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlalignb,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlalignb_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_valignbi,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_valignbi_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlalignbi,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlalignbi_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vror,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vror_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackub,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackub_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackb,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackb_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackuh,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackuh_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackh,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackh_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackob,"V32iV32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackob_128B,"V64iV64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackoh,"V32iV32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vunpackoh_128B,"V64iV64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackeb,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackeb_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackeh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackeh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackob,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackob_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackoh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackoh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackhub_sat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackhub_sat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackhb_sat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackhb_sat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackwuh_sat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackwuh_sat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackwh_sat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpackwh_sat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vzb,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vzb_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsb,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsb_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vzh,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vzh_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsh,"V32iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsh_128B,"V64iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat_acc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat,"V16iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat_128B,"V32iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat_acc,"V16iV16iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat_acc_128B,"V32iV32iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat,"V16iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat_128B,"V32iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat_acc,"V16iV16iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B,"V32iV32iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyb,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyb_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyb_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyb_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpybus,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpybus_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpybus_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpybus_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyhb,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyhb_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyhb_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vtmpyhb_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubv_acc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubv_acc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybv_acc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybv_acc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubi,"V32iV32iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubi_128B,"V64iV64iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubi_acc,"V32iV32iV32iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyubi_acc_128B,"V64iV64iV64iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybus,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybus_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybus_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybus_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusi,"V32iV32iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusi_128B,"V64iV64iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusi_acc,"V32iV32iV32iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusi_acc_128B,"V64iV64iV64iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusv_acc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybusv_acc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdsaduh,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdsaduh_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdsaduh_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdsaduh_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrsadubi,"V32iV32iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrsadubi_128B,"V64iV64iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrsadubi_acc,"V32iV32iV32iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrsadubi_acc_128B,"V64iV64iV64iii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrw,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrw_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslw,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslw_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrw,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrw_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslwv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslwv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrwv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrwv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrh,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrh_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslh,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslh_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrh,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrh_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslhv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslhv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrhv,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrhv_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwh,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwh_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwhsat,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwhsat_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwhrndsat,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwhrndsat_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwuhsat,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwuhsat_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundwh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundwh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundwuh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundwuh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhubsat,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhubsat_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhubrndsat,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhubrndsat_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhbrndsat,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhbrndsat_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundhb,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundhb_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundhub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vroundhub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslw_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaslw_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrw_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vasrw_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddb,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddb_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubb,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubb_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddb_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddb_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubb_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubb_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddh_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddh_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubh_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubh_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddw_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddw_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubw_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubw_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsububsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsububsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsububsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsububsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuhsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuhsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuhsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuhsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwsat,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwsat_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwsat_dv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwsat_dv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgubrnd,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgubrnd_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavguh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavguh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavguhrnd,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavguhrnd_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavghrnd,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavghrnd_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgwrnd,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vavgwrnd_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffuh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffuh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsdiffw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubh,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubh_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsububh,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsububh_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhw,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhw_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhw,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhw_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhw,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhw_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuhw,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuhw_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vd0,"V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vd0_128B,"V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbnq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbnq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbnq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbnq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhnq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhnq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhnq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubhnq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwnq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vaddwnq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwnq,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsubwnq_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsh,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsh_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsh_sat,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsh_sat_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsw,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsw_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsw_sat,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vabsw_sat_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybv,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybv_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybv_acc,"V32iV32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybv_acc_128B,"V64iV64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyubv,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyubv_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyubv_acc,"V32iV32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyubv_acc_128B,"V64iV64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybusv,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybusv_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybusv_acc,"V32iV32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybusv_acc_128B,"V64iV64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabusv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabusv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabuuv,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabuuv_128B,"V64iV64iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhv,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhv_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhv_acc,"V32iV32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhv_acc_128B,"V64iV64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhv,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhv_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhv_acc,"V32iV32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhv_acc_128B,"V64iV64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhvsrs,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhvsrs_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhus,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhus_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhus_acc,"V32iV32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhus_acc_128B,"V64iV64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyih,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyih_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyih_acc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyih_acc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyewuh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_sacc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_sacc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd_sacc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyieoh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyieoh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiowh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiowh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiewh_acc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiewh_acc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh_acc,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh_acc_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyub,"V32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyub_128B,"V64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyub_acc,"V32iV32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyub_acc_128B,"V64iV64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybus,"V32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybus_128B,"V64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybus_acc,"V32iV32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpybus_acc_128B,"V64iV64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabus,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabus_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabus_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabus_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpahb,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpahb_128B,"V64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpahb_acc,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpahb_acc_128B,"V64iV64iV64ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyh,"V32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyh_128B,"V64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhsat_acc,"V32iV32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhsat_acc_128B,"V64iV64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhss,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhss_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhsrs,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyhsrs_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuh,"V32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuh_128B,"V64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuh_acc,"V32iV32iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuh_acc_128B,"V64iV64iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyihb,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyihb_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyihb_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyihb_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwb,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwb_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwb_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwb_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwh,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwh_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwh_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwh_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vand,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vand_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vor,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vor_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vxor,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vxor_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnot,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnot_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandqrt,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandqrt_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandvrt,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandvrt_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtw_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqw_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgth_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqh_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtb_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_veqb_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub_and,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub_and_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub_or,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub_or_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub_xor,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vgtub_xor_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_or,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_or_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_and,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_and_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_not,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_not_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_xor,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_xor_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_and_n,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_and_n_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_or_n,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_or_n_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_scalar2,"V16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_pred_scalar2_128B,"V32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmux,"V16iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmux_128B,"V32iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vswap,"V32iV16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vswap_128B,"V64iV32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxuh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxuh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminuh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminuh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminw,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vminw_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsathub,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsathub_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsatwh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vsatwh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffeb,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffeb_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffob,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffob_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufeh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufeh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufoh,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufoh_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffvdd,"V32iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffvdd_128B,"V64iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealvdd,"V32iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealvdd_128B,"V64iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufoeh,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufoeh_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufoeb,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshufoeb_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealh,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealh_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealb,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealb_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealb4w,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdealb4w_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffh,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffh_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffb,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vshuffb_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_extractw,"iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_extractw_128B,"iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vinsertwr,"V16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vinsertwr_128B,"V32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_lvsplatw,"V16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_lvsplatw_128B,"V32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vassign,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vassign_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vcombine,"V32iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vcombine_128B,"V64iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdelta,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vdelta_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrdelta,"V16iV16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vrdelta_128B,"V32iV32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vcl0w,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vcl0w_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vcl0h,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vcl0h_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnormamtw,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnormamtw_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnormamth,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vnormamth_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpopcounth,"V16iV16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vpopcounth_128B,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb,"V16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb_128B,"V32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracc,"V16iV16iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracc_128B,"V32iV32iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh,"V32iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh_128B,"V64iV32iV32ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracc,"V32iV32iV16iV16ii","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracc_128B,"V64iV64iV32iV32ii","v:60:")
+// V60 HVX Instructions.
-BUILTIN(__builtin_HEXAGON_V6_hi,"V16iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_lo,"V16iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_hi_128B,"V32iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_lo_128B,"V32iV64i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vassignp,"V32iV32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vassignp_128B,"V64iV64i","v:60:")
+BUILTIN(__builtin_HEXAGON_V6_veqb_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqb_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vminub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vminub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaslw_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaslw_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhvsrs,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhvsrs_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsathub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsathub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddh_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddh_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusi,"V32iV32iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusi_128B,"V64iV64iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vshufoh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshufoh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat,"V16iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat_128B,"V32iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrsadubi_acc,"V32iV32iV32iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vrsadubi_acc_128B,"V64iV64iV64iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgubrnd,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgubrnd_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbnq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbnq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundhb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundhb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vsububsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsububsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabus_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabus_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmux,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmux_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhus,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhus_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackeb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackeb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhnq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhnq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vavghrnd,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavghrnd_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vtran2x2_map,"V16iV16iv*i","")
+BUILTIN(__builtin_HEXAGON_V6_vtran2x2_map_128B,"V32iV32iv*i","")
+BUILTIN(__builtin_HEXAGON_V6_vdelta,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vdelta_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyhb,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyhb_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vpackob,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackob_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpybus_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpybus_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuhsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuhsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrw_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrw_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_pred_or,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_or_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_lo,"V16iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_lo_128B,"V32iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubb_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubb_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwh,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwh_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwb,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwb_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_ldu0,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_ldu0_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgth_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgth_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlalignb,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlalignb_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsh,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsh_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_and_n,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_and_n_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsb,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsb_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundwuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundwuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffh,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffh_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vnormamth,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vnormamth_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vavguh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavguh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrwv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrwv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrhv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrhv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat,"V16iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat_128B,"V32iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vzh,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vzh_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhv_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhv_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vshufoeh,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshufoeh_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhv_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhv_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_veqh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuuv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuuv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwhsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwhsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vminuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vminuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vror,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vror_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd_sacc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsh_sat,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsh_sat_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_or_n,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_or_n_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdealb,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vdealb_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybusv,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybusv_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vzb,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vzb_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhubrndsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhubrndsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhubsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhubsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vshufoeb,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshufoeb_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackhub_sat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackhub_sat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwh_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwh_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyb,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyb_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabusv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabusv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_and,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_and_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwnq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwnq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackwuh_sat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackwuh_sat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vswap,"V32iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vswap_128B,"V64iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubv_acc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubv_acc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaslw,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaslw_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vpackhb_sat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackhb_sat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyih_acc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyih_acc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffvdd,"V32iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffvdd_128B,"V64iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddb_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddb_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackub,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackub_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh,"V32iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_128B,"V64iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyieoh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyieoh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_extractw,"iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_extractw_128B,"iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vavgwrnd,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgwrnd_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyub,"V32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyub_128B,"V64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuh,"V32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuh_128B,"V64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackob,"V32iV32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackob_128B,"V64iV64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpahb,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpahb_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_veqw_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqw_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vandqrt,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandqrt_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vxor,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vxor_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwhrndsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwhrndsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhsat_acc,"V32iV32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhsat_acc_128B,"V64iV64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybus_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybus_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhw,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhw_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdealb4w,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vdealb4w_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_sacc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_sacc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybv,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybv_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffob,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffob_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyub_acc,"V32iV32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyub_acc_128B,"V64iV64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vnormamtw,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vnormamtw_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackuh,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackuh_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh_acc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh_acc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackoh,"V32iV32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackoh_128B,"V64iV64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsat_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyubv,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyubv_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhss,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhss_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_hi,"V16iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_hi_128B,"V32iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwuhsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwuhsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_veqw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdsaduh,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdsaduh_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubw_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubw_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_veqb_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqb_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyih,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyih_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyb_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyb_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybus,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybus_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybus_acc,"V32iV32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybus_acc_128B,"V64iV64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgth_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgth_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubi_acc,"V32iV32iV32iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubi_acc_128B,"V64iV64iV64iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vabsw,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsw_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrw,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrw_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vabsh,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsh_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrh,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrh_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_valignb,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_valignb_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubhq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackoh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackoh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat_acc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybv_acc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybv_acc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vcombine,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vcombine_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandqrt_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaslhv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaslhv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vinsertwr,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vinsertwr_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubh_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubh_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffb,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffb_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vand,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vand_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhv,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhv_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat_acc,"V16iV16iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B,"V32iV32iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsububsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsububsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdsaduh_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdsaduh_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuh_acc,"V32iV32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuh_acc_128B,"V64iV64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vcl0h,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vcl0h_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhus_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhus_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybv_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybv_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrsadubi,"V32iV32iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vrsadubi_128B,"V64iV64iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vshufeh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshufeh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyewuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhsrs,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyhsrs_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubh,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubh_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwh,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwh_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_ld0,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_ld0_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vpopcounth,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpopcounth_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_ldnt0,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_ldnt0_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgth_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgth_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackeh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackeh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyh,"V32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyh_128B,"V64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vminh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vminh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_scalar2,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_pred_scalar2_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdealh,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vdealh_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackwh_sat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vpackwh_sat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaslh,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaslh_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vor,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vor_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiowh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiowh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracc,"V16iV16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracc_128B,"V32iV32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandvrt,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandvrt_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_veqh_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqh_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhw,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhw_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vcl0w,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vcl0w_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyihb,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyihb_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpybus,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpybus_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vd0,"V16i","")
+BUILTIN(__builtin_HEXAGON_V6_vd0_128B,"V32i","")
+BUILTIN(__builtin_HEXAGON_V6_veqh_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqh_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpybus_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybus,"V32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybus_128B,"V64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandvrt_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vassign,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vassign_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwnq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwnq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtub_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhb_dv_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackb,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackb_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackh,"V32iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vunpackh_128B,"V64iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpahb_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpahb_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbnq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbnq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlalignbi,"V16iV16iV16iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vlalignbi_128B,"V32iV32iV32iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vsatwh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsatwh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyihb_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyihb_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusv_acc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusv_acc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrdelta,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrdelta_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundwh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundwh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddw_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddw_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwb_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwb_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_veqh_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqh_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_valignbi,"V16iV16iV16iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_valignbi_128B,"V32iV32iV32iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddwsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_veqw_and,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqw_and_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffeb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vshuffeb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_veqw_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqw_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgth,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgth_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vnot,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vnot_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtb_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw_or,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtuw_or_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaslwv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaslwv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsw_sat,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsw_sat_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundhub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vroundhub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat_acc,"V16iV16iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhisat_acc_128B,"V32iV32iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabus,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabus_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vassignp,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vassignp_128B,"V64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_veqb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsububh,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsububh_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_lvsplatw,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_lvsplatw_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhnq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhnq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_pred_not,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_not_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracc,"V32iV32iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracc_128B,"V64iV64iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiewh_acc,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiewh_acc_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdealvdd,"V32iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdealvdd_128B,"V64iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vavgw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vgtw_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyhb_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vtmpyhb_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhw,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhw_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhq,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhq_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubi,"V32iV32iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyubi_128B,"V64iV64iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vminw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vminw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyubv_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyubv_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_xor,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_pred_xor_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_veqb_xor,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_veqb_xor_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiewuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybusv_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpybusv_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vavguhrnd,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavguhrnd_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_rnd_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubwsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuhw,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuhw_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusi_acc,"V32iV32iV32iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybusi_acc_128B,"V64iV64iV64iiUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vasrw,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrw_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrh,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrh_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhv,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhv_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhbrndsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhbrndsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuhsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuhsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsdiffw_128B,"V32iV32iV32i","")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai_128B,"vV32iv*V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai_128B,"vV32iv*V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B,"vV32iv*V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B,"vV32iv*V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq,"vV16iv*V16i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq_128B,"vV32iv*V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq_128B,"vV32iv*V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq_128B,"vV32iv*V32i","v:60:")
-BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq_128B,"vV32iv*V32i","v:60:")
+// V62 HVX Instructions.
-BUILTIN(__builtin_HEXAGON_M6_vabsdiffb,"LLiLLiLLi","v:62:")
-BUILTIN(__builtin_HEXAGON_M6_vabsdiffub,"LLiLLiLLi","v:62:")
-BUILTIN(__builtin_HEXAGON_A6_vminub_RdP,"LLiLLiLLi","v:62:")
-BUILTIN(__builtin_HEXAGON_S6_vsplatrbp,"LLii","v:62:")
-BUILTIN(__builtin_HEXAGON_S6_vtrunehb_ppp,"LLiLLiLLi","v:62:")
-BUILTIN(__builtin_HEXAGON_S6_vtrunohb_ppp,"LLiLLiLLi","v:62:")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64,"V32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64_128B,"V64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsatuwuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsatuwuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_shuffeqw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_ldcnpnt0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldcnpnt0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubcarry,"V16iV16iV16iv*","")
+BUILTIN(__builtin_HEXAGON_V6_vsubcarry_128B,"V32iV32iV32iv*","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhbsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrhbsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vminb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vminb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrb,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlsrb_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwhi,"V32iV16iV16iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwhi_128B,"V64iV32iV32iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_ldtp0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldtp0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci,"V16iV16iV16iV16iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci_128B,"V32iV32iV32iV32iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_ldpnt0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldpnt0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vandvnqv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vandvnqv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_lvsplatb,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_lvsplatb_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_lvsplath,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_lvsplath_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_ldtpnt0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldtpnt0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm,"V32iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm_128B,"V64iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_ldnpnt0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldnpnt0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhb_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_ldtnp0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldtnp0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vrounduhub,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrounduhub_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_ldcp0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldcp0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_ldtnpnt0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldtnpnt0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vandnqrt_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vmaxb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vandvqv,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vandvqv_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddcarry,"V16iV16iV16iv*","")
+BUILTIN(__builtin_HEXAGON_V6_vaddcarry_128B,"V32iV32iV32iv*","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvbi,"V16iV16iV16iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvbi_128B,"V32iV32iV32iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_ldnp0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldnp0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrounduwuh,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrounduwuh_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2,"V16ii","")
+BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2_128B,"V32ii","")
+BUILTIN(__builtin_HEXAGON_V6_ldp0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldp0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddclbw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_ldcpnt0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldcpnt0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv_128B,"V64iV64iV64i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_ldcnp0,"V16iii","")
+BUILTIN(__builtin_HEXAGON_V6_ldcnp0_128B,"V32iii","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci,"V32iV32iV16iV16iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci_128B,"V64iV64iV32iV32iUIi","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsubbsat_128B,"V32iV32iV32i","")
-BUILTIN(__builtin_HEXAGON_V6_vlsrb,"V16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlsrb_128B,"V32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat,"V16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat_128B,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat,"V16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat_128B,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhbsat,"V16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vasrhbsat_128B,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vrounduwuh,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vrounduwuh_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vrounduhub,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vrounduhub_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vadduwsat,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vadduwsat_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv_128B,"V64iV64iV64i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuwsat,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv_128B,"V64iV64iV64i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbsat,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbsat_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv_128B,"V64iV64iV64i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbsat,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbsat_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv_128B,"V64iV64iV64i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc,"V32iV32iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc_128B,"V64iV64iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc,"V32iV32iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc_128B,"V64iV64iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc,"V32iV32iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc_128B,"V64iV64iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64,"V32iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64_128B,"V64iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc,"V32iV32iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc_128B,"V64iV64iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpauhb,"V32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpauhb_128B,"V64iV64ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc_128B,"V64iV64iV64ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwub,"V16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_128B,"V32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc,"V16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc_128B,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandnqrt,"V16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandnqrt_128B,"V32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc,"V16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc_128B,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandvqv,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandvqv_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandvnqv,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vandvnqv_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2,"V16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2_128B,"V32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_shuffeqw,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_shuffeqw_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_shuffeqh,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_shuffeqh_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxb,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vmaxb_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vminb,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vminb_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsatuwuh,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsatuwuh_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_lvsplath,"V16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_lvsplath_128B,"V32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_lvsplatb,"V16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_lvsplatb_128B,"V32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddclbw,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddclbw_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddclbh,"V16iV16iV16i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddclbh_128B,"V32iV32iV32i","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvbi,"V16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvbi_128B,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci,"V16iV16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci_128B,"V32iV32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwhi,"V32iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwhi_128B,"V64iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci,"V32iV32iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci_128B,"V64iV64iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm,"V16iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm_128B,"V32iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm,"V32iV16iV16ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm_128B,"V64iV32iV32ii","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddcarry,"V16iV16iV16iv*","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vaddcarry_128B,"V32iV32iV32iv*","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubcarry,"V16iV16iV16iv*","v:62:")
-BUILTIN(__builtin_HEXAGON_V6_vsubcarry_128B,"V32iV32iV32iv*","v:62:")
+// V65 HVX Instructions.
-BUILTIN(__builtin_HEXAGON_A6_vcmpbeq_notany,"iLLiLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_A6_vcmpbeq_notany_128B,"iLLiLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt,"V32iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_128B,"V64iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc,"V32iV32iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B,"V64iV64iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt,"V32iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_128B,"V64iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc,"V32iV32iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B,"V64iV64iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat,"V16iV16iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat_128B,"V32iV32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasruhubsat,"V16iV16iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasruhubsat_128B,"V32iV32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat,"V16iV16iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat_128B,"V32iV32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vaslh_acc,"V16iV16iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vaslh_acc_128B,"V32iV32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasrh_acc,"V16iV16iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vasrh_acc_128B,"V32iV32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavguw,"V16iV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavguw_128B,"V32iV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavguwrnd,"V16iV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavguwrnd_128B,"V32iV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavgb,"V16iV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavgb_128B,"V32iV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavgbrnd,"V16iV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vavgbrnd_128B,"V32iV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgb,"V16iV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vnavgb_128B,"V32iV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vabsb,"V16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vabsb_128B,"V32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vabsb_sat,"V16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vabsb_sat_128B,"V32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabuu,"V32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabuu_128B,"V64iV64ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc,"V32iV32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc_128B,"V64iV64iV64ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc,"V32iV32iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc_128B,"V64iV64iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpahhsat,"V16iV16iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpahhsat_128B,"V32iV32iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat,"V16iV16iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat_128B,"V32iV32iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat,"V16iV16iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat_128B,"V32iV32iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vlut4,"V16iV16iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vlut4_128B,"V32iV32iLLi","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhe,"V16iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_128B,"V32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc,"V16iV16iV16ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc_128B,"V32iV32iV32ii","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermw,"vv*iiV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermw_128B,"vv*iiV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermh,"vv*iiV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermh_128B,"vv*iiV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermhw,"vv*iiV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermhw_128B,"vv*iiV64i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermwq,"vv*V16iiiV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermwq_128B,"vv*V32iiiV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermhq,"vv*V16iiiV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermhq_128B,"vv*V32iiiV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermhwq,"vv*V16iiiV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vgathermhwq_128B,"vv*V32iiiV64i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermw,"viiV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermw_128B,"viiV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermh,"viiV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermh_128B,"viiV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermw_add,"viiV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermw_add_128B,"viiV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermh_add,"viiV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermh_add_128B,"viiV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermwq,"vV16iiiV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermwq_128B,"vV32iiiV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhq,"vV16iiiV16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhq_128B,"vV32iiiV32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhw,"viiV32iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhw_128B,"viiV64iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhwq,"vV16iiiV32iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhwq_128B,"vV32iiiV64iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add,"viiV32iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add_128B,"viiV64iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vprefixqb,"V16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vprefixqb_128B,"V32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vprefixqh,"V16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vprefixqh_128B,"V32iV32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vprefixqw,"V16iV16i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vprefixqw_128B,"V32iV32i","v:65:")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt,"V32iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_128B,"V64iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vmpahhsat,"V16iV16iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vmpahhsat_128B,"V32iV32iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vavguwrnd,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavguwrnd_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vnavgb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasrh_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasrh_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat,"V16iV16iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat_128B,"V32iV32iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc,"V32iV32iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc_128B,"V64iV64iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc,"V32iV32iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B,"V64iV64iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vavgb,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgb_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vaslh_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vaslh_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vavguw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavguw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vlut4,"V16iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vlut4_128B,"V32iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt,"V32iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_128B,"V64iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat,"V16iV16iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat_128B,"V32iV32iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasruhubsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe,"V16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_128B,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc,"V32iV32iV16iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B,"V64iV64iV32iLLi","")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat,"V16iV16iV16ii","")
+BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat_128B,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc,"V32iV32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc_128B,"V64iV64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqw,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqw_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqh,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqh_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqb,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vprefixqb_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsb,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsb_128B,"V32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgbrnd,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vavgbrnd_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdd0,"V32i","")
+BUILTIN(__builtin_HEXAGON_V6_vdd0_128B,"V64i","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu,"V32iV32ii","")
+BUILTIN(__builtin_HEXAGON_V6_vmpabuu_128B,"V64iV64ii","")
+BUILTIN(__builtin_HEXAGON_V6_vabsb_sat,"V16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vabsb_sat_128B,"V32iV32i","")
-BUILTIN(__builtin_HEXAGON_V6_vdd0,"V32i","v:65:")
-BUILTIN(__builtin_HEXAGON_V6_vdd0_128B,"V64i","v:65:")
+// V66 HVX Instructions.
+BUILTIN(__builtin_HEXAGON_V6_vaddcarrysat,"V16iV16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vaddcarrysat_128B,"V32iV32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vasr_into,"V32iV32iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vasr_into_128B,"V64iV64iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vsatdw,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vsatdw_128B,"V32iV32iV32i","")
+BUILTIN(__builtin_HEXAGON_V6_vrotr,"V16iV16iV16i","")
+BUILTIN(__builtin_HEXAGON_V6_vrotr_128B,"V32iV32iV32i","")
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsNios2.def b/include/clang/Basic/BuiltinsNios2.def
deleted file mode 100644
index d9697e795c44..000000000000
--- a/include/clang/Basic/BuiltinsNios2.def
+++ /dev/null
@@ -1,70 +0,0 @@
-//===-- BuiltinsNios2.def - Nios2 Builtin function database --------*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the Nios2-specific builtin function database. Users of
-// this file must define the BUILTIN macro to make use of this information.
-//
-//===----------------------------------------------------------------------===//
-
-// The format of this database matches clang/Basic/Builtins.def.
-
-#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
-# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
-#endif
-
-// Nios2 R1 builtins:
-
-//int __builtin_ldbio(volatile const void *);
-BUILTIN(__builtin_ldbio, "ivDC*", "")
-//int __builtin_ldbuio(volatile const void *);
-BUILTIN(__builtin_ldbuio, "ivDC*", "")
-//int __builtin_ldhio(volatile const void *);
-BUILTIN(__builtin_ldhio, "ivDC*", "")
-//int __builtin_ldhuio(volatile const void *);
-BUILTIN(__builtin_ldhuio, "ivDC*", "")
-//int __builtin_ldwio(volatile const void *);
-BUILTIN(__builtin_ldwio, "ivDC*", "")
-//int __builtin_ldwuio(int);
-BUILTIN(__builtin_ldwuio, "ii", "")
-// int __builtin_rdctl(int);
-BUILTIN(__builtin_rdctl, "iIi", "")
-// void __builtin_wrctl(int, int);
-BUILTIN(__builtin_wrctl, "vIii", "")
-// int __builtin_rdprs(int, int);
-BUILTIN(__builtin_rdprs, "iii", "")
-//void __builtin_stbio(volatile void *, int);
-BUILTIN(__builtin_stbio, "vvD*i", "")
-//void __builtin_sthio(volatile void *, int);
-BUILTIN(__builtin_sthio, "vvD*i", "")
-//void __builtin_stwio(volatile void *, int);
-BUILTIN(__builtin_stwio, "vvD*i", "")
-//void __builtin_sync(void);
-BUILTIN(__builtin_sync, "v", "")
-// void __builtin_flushd(volatile void *);
-BUILTIN(__builtin_flushd, "vvD*", "")
-// void __builtin_flushda(volatile void *);
-BUILTIN(__builtin_flushda, "vvD*", "")
-
-// Nios2 R2 builtins:
-
-// int __builtin_wrpie(int);
-TARGET_BUILTIN(__builtin_wrpie, "ii", "", "nios2r2mandatory")
-// void __builtin_eni(int);
-TARGET_BUILTIN(__builtin_eni, "vi", "", "nios2r2mandatory")
-// int __builtin_ldex(volatile const void *);
-TARGET_BUILTIN(__builtin_ldex, "ivDC*", "", "nios2r2mandatory")
-// int __builtin_stex(volatile void *, int);
-TARGET_BUILTIN(__builtin_stex, "ivD*i", "", "nios2r2mandatory")
-// int __builtin_ldsex(volatile const void *);
-TARGET_BUILTIN(__builtin_ldsex, "ivDC*", "", "nios2r2mpx")
-// int __builtin_stsex(volatile void *, int);
-TARGET_BUILTIN(__builtin_stsex, "ivDC*i", "", "nios2r2mpx")
-
-#undef BUILTIN
-#undef TARGET_BUILTIN
diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def
index 9be760853d50..d31cb06f05f5 100644
--- a/include/clang/Basic/BuiltinsPPC.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -431,6 +431,8 @@ BUILTIN(__builtin_mulf128_round_to_odd, "LLdLLdLLd", "")
BUILTIN(__builtin_divf128_round_to_odd, "LLdLLdLLd", "")
BUILTIN(__builtin_fmaf128_round_to_odd, "LLdLLdLLdLLd", "")
BUILTIN(__builtin_truncf128_round_to_odd, "dLLd", "")
+BUILTIN(__builtin_vsx_scalar_extract_expq, "ULLiLLd", "")
+BUILTIN(__builtin_vsx_scalar_insert_exp_qp, "LLdLLdULLi", "")
// HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "")
@@ -470,6 +472,10 @@ BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "")
BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "")
BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "")
+// Vector int128 (un)pack
+BUILTIN(__builtin_unpack_vector_int128, "ULLiV1LLLii", "")
+BUILTIN(__builtin_pack_vector_int128, "V1LLLiULLiULLi", "")
+
// FIXME: Obviously incomplete.
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def
index b3d877dcedf3..55931edc5ca3 100644
--- a/include/clang/Basic/BuiltinsWebAssembly.def
+++ b/include/clang/Basic/BuiltinsWebAssembly.def
@@ -16,22 +16,94 @@
// The format of this database matches clang/Basic/Builtins.def.
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
// Query the current memory size, and increase the current memory size.
// Note that memory.size is not "c" (readnone) because it must be sequenced
// with respect to memory.grow calls.
BUILTIN(__builtin_wasm_memory_size, "zIi", "n")
BUILTIN(__builtin_wasm_memory_grow, "zIiz", "n")
-// These are the old names.
-BUILTIN(__builtin_wasm_mem_size, "zIi", "n")
-BUILTIN(__builtin_wasm_mem_grow, "zIiz", "n")
-
-// These are the old old names. They also lack the immediate field.
-BUILTIN(__builtin_wasm_current_memory, "z", "n")
-BUILTIN(__builtin_wasm_grow_memory, "zz", "n")
+// Floating point min/max
+BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
+BUILTIN(__builtin_wasm_max_f32, "fff", "nc")
+BUILTIN(__builtin_wasm_min_f64, "ddd", "nc")
+BUILTIN(__builtin_wasm_max_f64, "ddd", "nc")
// Exception handling builtins.
-BUILTIN(__builtin_wasm_throw, "vUiv*", "r")
-BUILTIN(__builtin_wasm_rethrow, "v", "r")
+TARGET_BUILTIN(__builtin_wasm_throw, "vUiv*", "r", "exception-handling")
+TARGET_BUILTIN(__builtin_wasm_rethrow, "v", "r", "exception-handling")
+
+// Atomic wait and notify.
+BUILTIN(__builtin_wasm_atomic_wait_i32, "ii*iLLi", "n")
+BUILTIN(__builtin_wasm_atomic_wait_i64, "iLLi*LLiLLi", "n")
+BUILTIN(__builtin_wasm_atomic_notify, "Uii*Ui", "n")
+
+// Saturating fp-to-int conversions
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f32, "if", "nc", "nontrapping-fptoint")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f32, "if", "nc", "nontrapping-fptoint")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f64, "id", "nc", "nontrapping-fptoint")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f64, "id", "nc", "nontrapping-fptoint")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f32, "LLif", "nc", "nontrapping-fptoint")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f32, "LLif", "nc", "nontrapping-fptoint")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f64, "LLid", "nc", "nontrapping-fptoint")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f64, "LLid", "nc", "nontrapping-fptoint")
+
+// SIMD builtins
+TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i8x16, "iV16cIi", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_extract_lane_u_i8x16, "iV16cIi", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i16x8, "iV8sIi", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_extract_lane_u_i16x8, "iV8sIi", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_extract_lane_i32x4, "iV4iIi", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_extract_lane_i64x2, "LLiV2LLiIi", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_extract_lane_f32x4, "fV4fIi", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_extract_lane_f64x2, "dV2dIi", "nc", "unimplemented-simd128")
+
+TARGET_BUILTIN(__builtin_wasm_replace_lane_i8x16, "V16cV16cIii", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_replace_lane_i16x8, "V8sV8sIii", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_replace_lane_i32x4, "V4iV4iIii", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_replace_lane_i64x2, "V2LLiV2LLiIiLLi", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_replace_lane_f32x4, "V4fV4fIif", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_replace_lane_f64x2, "V2dV2dIid", "nc", "unimplemented-simd128")
+
+TARGET_BUILTIN(__builtin_wasm_add_saturate_s_i8x16, "V16cV16cV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_add_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_add_saturate_s_i16x8, "V8sV8sV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_add_saturate_u_i16x8, "V8sV8sV8s", "nc", "simd128")
+
+TARGET_BUILTIN(__builtin_wasm_sub_saturate_s_i8x16, "V16cV16cV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_sub_saturate_s_i16x8, "V8sV8sV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i16x8, "V8sV8sV8s", "nc", "simd128")
+
+TARGET_BUILTIN(__builtin_wasm_bitselect, "V4iV4iV4iV4i", "nc", "simd128")
+
+TARGET_BUILTIN(__builtin_wasm_any_true_i8x16, "iV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_any_true_i16x8, "iV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_any_true_i32x4, "iV4i", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_any_true_i64x2, "iV2LLi", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_all_true_i8x16, "iV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_all_true_i16x8, "iV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_all_true_i32x4, "iV4i", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_all_true_i64x2, "iV2LLi", "nc", "unimplemented-simd128")
+
+TARGET_BUILTIN(__builtin_wasm_abs_f32x4, "V4fV4f", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_abs_f64x2, "V2dV2d", "nc", "unimplemented-simd128")
+
+TARGET_BUILTIN(__builtin_wasm_min_f32x4, "V4fV4fV4f", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_max_f32x4, "V4fV4fV4f", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128")
+
+TARGET_BUILTIN(__builtin_wasm_sqrt_f32x4, "V4fV4f", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc", "unimplemented-simd128")
+
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32x4_f32x4, "V4iV4f", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32x4_f32x4, "V4iV4f", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128")
#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index e98f7d612c3c..b3564b957e99 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -719,16 +719,21 @@ TARGET_BUILTIN(__builtin_ia32_wbinvd, "v", "n", "")
TARGET_BUILTIN(__builtin_ia32_wbnoinvd, "v", "n", "wbnoinvd")
// ADX
-TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "n", "adx")
-TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "n", "")
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "n", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "n", "")
// RDSEED
TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "n", "rdseed")
TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "n", "rdseed")
+// LZCNT
+TARGET_BUILTIN(__builtin_ia32_lzcnt_u16, "UsUs", "nc", "lzcnt")
+TARGET_BUILTIN(__builtin_ia32_lzcnt_u32, "UiUi", "nc", "lzcnt")
+
// BMI
TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "nc", "bmi")
+TARGET_BUILTIN(__builtin_ia32_tzcnt_u16, "UsUs", "nc", "")
+TARGET_BUILTIN(__builtin_ia32_tzcnt_u32, "UiUi", "nc", "")
// BMI2
TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "nc", "bmi2")
@@ -963,49 +968,52 @@ TARGET_BUILTIN(__builtin_ia32_vpdpwssds128, "V4iV4iV4iV4i", "ncV:128:", "avx512v
TARGET_BUILTIN(__builtin_ia32_vpdpwssds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni")
TARGET_BUILTIN(__builtin_ia32_vpdpwssds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni")
-TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "nV:512:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "nV:512:", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "nV:512:", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "nV:512:", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "nV:512:", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "nV:512:", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "nV:512:", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "nV:512:", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "nV:512:", "avx512pf")
-TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "nV:512:", "avx512pf")
-
+TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2dvC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLivC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4dvC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLivC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4fvC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4ivC*V2LLiUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4fvC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4ivC*V4LLiUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2dvC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLivC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4dvC*V4iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLivC*V4iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4fvC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4ivC*V4iUcIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8fvC*V8iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8ivC*V8iUcIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*V16iUsIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*V16iUsIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUcIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8dIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8dIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiIi", "nV:512:", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iIi", "nV:512:", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*IiIi", "nV:512:", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*IiIi", "nV:512:", "avx512pf")
+
+TARGET_BUILTIN(__builtin_ia32_knotqi, "UcUc", "nc", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_knotsi, "UiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_knotdi, "ULLiULLi", "nc", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "ncV:128:", "avx512vl,avx512bw")
TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "ncV:128:", "avx512vl")
@@ -1038,10 +1046,10 @@ TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "ncV:512:", "avx512bw
TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pmaxsb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pmaxsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pmaxub512, "V64cV64cV64c", "ncV:512:", "avx512bw")
@@ -1051,10 +1059,10 @@ TARGET_BUILTIN(__builtin_ia32_pminsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pminub512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pminuw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512cd,avx512vl")
TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512cd,avx512vl")
@@ -1202,22 +1210,22 @@ TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "ncV:256:", "a
TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "ncV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "nV:128:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "nV:256:", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vv*UcV2LLiV2dIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vv*UcV2LLiV2LLiIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vv*UcV4LLiV4dIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vv*UcV4LLiV4LLiIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vv*UcV2LLiV4fIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vv*UcV2LLiV4iIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vv*UcV4LLiV4fIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vv*UcV4LLiV4iIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vv*UcV4iV2dIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vv*UcV4iV2LLiIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vv*UcV4iV4dIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vv*UcV4iV4LLiIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vv*UcV4iV4fIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vv*UcV4iV4iIi", "nV:128:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vv*UcV8iV8fIi", "nV:256:", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vv*UcV8iV8iIi", "nV:256:", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_vpermi2vard128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_vpermi2vard256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl")
@@ -1248,43 +1256,25 @@ TARGET_BUILTIN(__builtin_ia32_vpshldw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,a
TARGET_BUILTIN(__builtin_ia32_vpshldw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2")
TARGET_BUILTIN(__builtin_ia32_vpshldw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
-
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2")
-TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw128, "V8sV8sV8sV8s", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw256, "V16sV16sV16sV16s", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshldvw512, "V32sV32sV32sV32s", "ncV:512:", "avx512vbmi2")
+
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw128, "V8sV8sV8sV8s", "ncV:128:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw256, "V16sV16sV16sV16s", "ncV:256:", "avx512vl,avx512vbmi2")
+TARGET_BUILTIN(__builtin_ia32_vpshrdvw512, "V32sV32sV32sV32s", "ncV:512:", "avx512vbmi2")
TARGET_BUILTIN(__builtin_ia32_vpshrdd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2")
TARGET_BUILTIN(__builtin_ia32_vpshrdd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2")
@@ -1734,14 +1724,59 @@ TARGET_BUILTIN(__builtin_ia32_fpclassps512_mask, "UsV16fIiUs", "ncV:512:", "avx5
TARGET_BUILTIN(__builtin_ia32_fpclasspd512_mask, "UcV8dIiUc", "ncV:512:", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_fpclasssd_mask, "UcV2dIiUc", "ncV:128:", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_fpclassss_mask, "UcV4fIiUc", "ncV:128:", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kaddqi, "UcUcUc", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kaddhi, "UsUsUs", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kaddsi, "UiUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kadddi, "ULLiULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kandqi, "UcUcUc", "nc", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_kandhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kandsi, "UiUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kanddi, "ULLiULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kandnqi, "UcUcUc", "nc", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_kandnhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kandnsi, "UiUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kandndi, "ULLiULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_korqi, "UcUcUc", "nc", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_korhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_korsi, "UiUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kordi, "ULLiULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kortestcqi, "iUcUc", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kortestzqi, "iUcUc", "nc", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_kortestchi, "iUsUs", "nc", "avx512f")
TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kortestcsi, "iUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kortestzsi, "iUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kortestcdi, "iULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kortestzdi, "iULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ktestcqi, "iUcUc", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_ktestzqi, "iUcUc", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_ktestchi, "iUsUs", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_ktestzhi, "iUsUs", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_ktestcsi, "iUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ktestzsi, "iUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ktestcdi, "iULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ktestzdi, "iULLiULLi", "nc", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kxnorqi, "UcUcUc", "nc", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kxnorsi, "UiUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kxnordi, "ULLiULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kxorqi, "UcUcUc", "nc", "avx512dq")
TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kxorsi, "UiUiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kxordi, "ULLiULLiULLi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kshiftliqi, "UcUcIUi", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kshiftlihi, "UsUsIUi", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kshiftlisi, "UiUiIUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kshiftlidi, "ULLiULLiIUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kshiftriqi, "UcUcIUi", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kshiftrihi, "UsUsIUi", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kshiftrisi, "UiUiIUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kshiftridi, "ULLiULLiIUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kmovb, "UcUc", "nc", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_kmovw, "UsUs", "nc", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_kmovd, "UiUi", "nc", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_kmovq, "ULLiULLi", "nc", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_palignr512, "V64cV64cV64cIi", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_dbpsadbw128, "V8sV16cV16cIi", "ncV:128:", "avx512bw,avx512vl")
TARGET_BUILTIN(__builtin_ia32_dbpsadbw256, "V16sV32cV32cIi", "ncV:256:", "avx512bw,avx512vl")
@@ -1786,9 +1821,9 @@ TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi", "ncV:128:
TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi", "ncV:128:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi", "ncV:128:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi", "ncV:128:", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512vbmi")
-TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs", "ncV:128:", "avx512vbmi,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi", "ncV:256:", "avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512, "V64cV64cV64c", "ncV:512:", "avx512vbmi")
+TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128, "V16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256, "V32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl")
// generic select intrinsics
TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "ncV:128:", "avx512bw,avx512vl")
diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def
index cc400c0697f9..5e8cce5c6e5e 100644
--- a/include/clang/Basic/BuiltinsX86_64.def
+++ b/include/clang/Basic/BuiltinsX86_64.def
@@ -31,6 +31,8 @@ TARGET_HEADER_BUILTIN(_mul128, "LLiLLiLLiLLi*", "nch", "intrin.h", ALL_MS
TARGET_HEADER_BUILTIN(_umul128, "ULLiULLiULLiULLi*", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__faststorefence, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__shiftleft128, "ULLiULLiULLiUc", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__shiftright128, "ULLiULLiULLiUc", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -74,12 +76,13 @@ TARGET_BUILTIN(__builtin_ia32_incsspq, "vULLi", "n", "shstk")
TARGET_BUILTIN(__builtin_ia32_rdsspq, "ULLiULLi", "n", "shstk")
TARGET_BUILTIN(__builtin_ia32_wrssq, "vULLiv*", "n", "shstk")
TARGET_BUILTIN(__builtin_ia32_wrussq, "vULLiv*", "n", "shstk")
-TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "n", "adx")
-TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "n", "")
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "n", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "n", "")
TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "n", "rdrnd")
TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "n", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_lzcnt_u64, "ULLiULLi", "nc", "lzcnt")
TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "nc", "bmi")
+TARGET_BUILTIN(__builtin_ia32_tzcnt_u64, "ULLiULLi", "nc", "")
TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "nc", "bmi2")
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Basic/CodeGenOptions.def
index a7e71f7ac016..ed2387b9a2e2 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Basic/CodeGenOptions.def
@@ -62,6 +62,8 @@ CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental
CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
+CODEGENOPT(IndirectTlsSegRefs, 1, 0) ///< Set when -mno-tls-direct-seg-refs
+ ///< is specified.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
CODEGENOPT(NoEscapingBlockTailCalls, 1, 0) ///< Do not emit tail calls from
///< escaping blocks.
@@ -114,6 +116,10 @@ CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the
///< compile step.
CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole
///< program vtable opt).
+CODEGENOPT(EnableSplitLTOUnit, 1, 0) ///< Enable LTO unit splitting to support
+ /// CFI and traditional whole program
+ /// devirtualization that require whole
+ /// program IR support.
CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can
///< be used with an incremental
///< linker.
@@ -147,6 +153,8 @@ CODEGENOPT(UniformWGSize , 1, 0) ///< -cl-uniform-work-group-size
CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
/// Method of Objective-C dispatch to use.
ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
+/// Replace certain message sends with calls to ObjC runtime entrypoints
+CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
///< enabled.
@@ -172,11 +180,12 @@ CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-
CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels.
CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection
///< in AddressSanitizer
-CODEGENOPT(SanitizeAddressPoisonClassMemberArrayNewCookie, 1,
+CODEGENOPT(SanitizeAddressPoisonCustomArrayCookie, 1,
0) ///< Enable poisoning operator new[] which is not a replaceable
///< global allocation function in AddressSanitizer
CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping
///< of globals in AddressSanitizer
+CODEGENOPT(SanitizeAddressUseOdrIndicator, 1, 0) ///< Enable ODR indicator globals
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
///< MemorySanitizer
CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
@@ -211,6 +220,7 @@ CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing
CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers.
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
+CODEGENOPT(SpeculativeLoadHardening, 1, 0) ///< Enable speculative load hardening.
CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses.
CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition.
CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers
@@ -249,7 +259,9 @@ CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain
CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
///< contain explicit imports for
///< anonymous namespaces
-CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF
+
+ENUM_CODEGENOPT(SplitDwarfMode, DwarfFissionKind, 2, NoFission) ///< DWARF fission mode to use.
+
CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the
///< skeleton CU to allow for symbolication
///< of inline stack frames without .dwo files.
@@ -292,6 +304,9 @@ VALUE_CODEGENOPT(DwarfVersion, 3, 0)
/// CodeView and DWARF into the same object.
CODEGENOPT(EmitCodeView, 1, 0)
+/// Whether to emit the .debug$H section containing hashes of CodeView types.
+CODEGENOPT(CodeViewGHash, 1, 0)
+
/// The kind of inlining to perform.
ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining)
@@ -326,7 +341,10 @@ CODEGENOPT(DebugInfoForProfiling, 1, 0)
CODEGENOPT(PreserveVec3Type, 1, 0)
/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames.
-CODEGENOPT(GnuPubnames, 1, 0)
+CODEGENOPT(DebugNameTable, 2, 0)
+
+/// Whether to use DWARF base address specifiers in .debug_ranges.
+CODEGENOPT(DebugRangesBaseAddress, 1, 0)
CODEGENOPT(NoPLT, 1, 0)
@@ -339,6 +357,12 @@ CODEGENOPT(ForceEmitVTables, 1, 0)
/// Whether to emit an address-significance table into the object file.
CODEGENOPT(Addrsig, 1, 0)
+ENUM_CODEGENOPT(SignReturnAddress, SignReturnAddressScope, 2, None)
+ENUM_CODEGENOPT(SignReturnAddressKey, SignReturnAddressKeyValue, 1, AKey)
+CODEGENOPT(BranchTargetEnforcement, 1, 0)
+
+/// Whether to emit unused static constants.
+CODEGENOPT(KeepStaticConsts, 1, 0)
#undef CODEGENOPT
#undef ENUM_CODEGENOPT
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Basic/CodeGenOptions.h
index a6d061acf0f4..ec6eda7fb788 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Basic/CodeGenOptions.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H
-#define LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H
+#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
+#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H
#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Basic/Sanitizers.h"
@@ -33,12 +33,12 @@ class CodeGenOptionsBase {
public:
#define CODEGENOPT(Name, Bits, Default) unsigned Name : Bits;
#define ENUM_CODEGENOPT(Name, Type, Bits, Default)
-#include "clang/Frontend/CodeGenOptions.def"
+#include "clang/Basic/CodeGenOptions.def"
protected:
#define CODEGENOPT(Name, Bits, Default)
#define ENUM_CODEGENOPT(Name, Type, Bits, Default) unsigned Name : Bits;
-#include "clang/Frontend/CodeGenOptions.def"
+#include "clang/Basic/CodeGenOptions.def"
};
/// CodeGenOptions - Track various options which control how the code
@@ -71,6 +71,8 @@ public:
LocalExecTLSModel
};
+ enum DwarfFissionKind { NoFission, SplitFileFission, SingleFileFission };
+
/// Clang versions with different platform ABI conformance.
enum class ClangABI {
/// Attempt to be ABI-compatible with code generated by Clang 3.8.x
@@ -108,6 +110,14 @@ public:
Embed_Marker // Embed a marker as a placeholder for bitcode.
};
+ enum SignReturnAddressScope {
+ None, // No signing for any function
+ NonLeaf, // Sign the return address of functions that spill LR
+ All // Sign the return address of all functions
+ };
+
+ enum SignReturnAddressKeyValue { AKey, BKey };
+
/// The code model to use (-mcmodel).
std::string CodeModel;
@@ -119,6 +129,12 @@ public:
/// The filename with path we use for coverage notes files.
std::string CoverageNotesFile;
+ /// Regexes separated by a semi-colon to filter the files to instrument.
+ std::string ProfileFilterFiles;
+
+ /// Regexes separated by a semi-colon to filter the files to not instrument.
+ std::string ProfileExcludeFiles;
+
/// The version string to put into coverage files.
char CoverageVersion[4];
@@ -132,6 +148,10 @@ public:
/// non-empty.
std::string DwarfDebugFlags;
+ /// The string containing the commandline for the llvm.commandline metadata,
+ /// if non-empty.
+ std::string RecordCommandLine;
+
std::map<std::string, std::string> DebugPrefixMap;
/// The ABI to use for passing floating point arguments.
@@ -194,6 +214,10 @@ public:
/// Name of the profile file to use as input for -fprofile-instr-use
std::string ProfileInstrumentUsePath;
+ /// Name of the profile remapping file to apply to the profile data supplied
+ /// by -fprofile-sample-use or -fprofile-instr-use.
+ std::string ProfileRemappingFile;
+
/// Name of the function summary index file to use for ThinLTO function
/// importing.
std::string ThinLTOIndexFile;
@@ -262,13 +286,15 @@ public:
/// Set of XRay instrumentation kinds to emit.
XRayInstrSet XRayInstrumentationBundle;
+ std::vector<std::string> DefaultFunctionAttrs;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \
Type get##Name() const { return static_cast<Type>(Name); } \
void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
-#include "clang/Frontend/CodeGenOptions.def"
+#include "clang/Basic/CodeGenOptions.def"
CodeGenOptions();
diff --git a/include/clang/Basic/Cuda.h b/include/clang/Basic/Cuda.h
index 24159e160f3f..0575e703338e 100644
--- a/include/clang/Basic/Cuda.h
+++ b/include/clang/Basic/Cuda.h
@@ -24,7 +24,8 @@ enum class CudaVersion {
CUDA_90,
CUDA_91,
CUDA_92,
- LATEST = CUDA_92,
+ CUDA_100,
+ LATEST = CUDA_100,
};
const char *CudaVersionToString(CudaVersion V);
@@ -47,6 +48,7 @@ enum class CudaArch {
SM_62,
SM_70,
SM_72,
+ SM_75,
GFX600,
GFX601,
GFX700,
@@ -60,6 +62,9 @@ enum class CudaArch {
GFX810,
GFX900,
GFX902,
+ GFX904,
+ GFX906,
+ GFX909,
LAST,
};
const char *CudaArchToString(CudaArch A);
@@ -82,6 +87,7 @@ enum class CudaVirtualArch {
COMPUTE_62,
COMPUTE_70,
COMPUTE_72,
+ COMPUTE_75,
COMPUTE_AMDGCN,
};
const char *CudaVirtualArchToString(CudaVirtualArch A);
diff --git a/include/clang/Basic/DebugInfoOptions.h b/include/clang/Basic/DebugInfoOptions.h
index 037c813c6114..f3be0fe52d31 100644
--- a/include/clang/Basic/DebugInfoOptions.h
+++ b/include/clang/Basic/DebugInfoOptions.h
@@ -13,6 +13,11 @@
namespace clang {
namespace codegenoptions {
+enum DebugInfoFormat {
+ DIF_DWARF,
+ DIF_CodeView,
+};
+
enum DebugInfoKind {
NoDebugInfo, /// Don't generate debug info.
LocTrackingOnly, /// Emit location information but do not generate
@@ -21,6 +26,7 @@ enum DebugInfoKind {
/// locations for instructions without actually
/// emitting debug info for them (e.g., when -Rpass
/// is used).
+ DebugDirectivesOnly, /// Emit only debug directives with the line numbers data
DebugLineTablesOnly, /// Emit only debug info necessary for generating
/// line number tables (-gline-tables-only).
LimitedDebugInfo, /// Limit generated debug info to reduce size
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index 67ca9e5c6c62..a184b480f7c0 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -97,5 +97,6 @@ def Captured : Decl, DeclContext;
def ClassScopeFunctionSpecialization : Decl;
def Import : Decl;
def OMPThreadPrivate : Decl;
+def OMPRequires : Decl;
def Empty : Decl;
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index d30ac14e02fe..a516721ace6d 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -177,6 +177,9 @@ public:
/// IdentifierInfo
ak_identifierinfo,
+ /// Qualifiers
+ ak_qual,
+
/// QualType
ak_qualtype,
@@ -486,10 +489,8 @@ public:
DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete;
~DiagnosticsEngine();
- LLVM_DUMP_METHOD void dump() const { DiagStatesByLoc.dump(*SourceMgr); }
- LLVM_DUMP_METHOD void dump(StringRef DiagName) const {
- DiagStatesByLoc.dump(*SourceMgr, DiagName);
- }
+ LLVM_DUMP_METHOD void dump() const;
+ LLVM_DUMP_METHOD void dump(StringRef DiagName) const;
const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
return Diags;
diff --git a/include/clang/Basic/DiagnosticAST.h b/include/clang/Basic/DiagnosticAST.h
new file mode 100644
index 000000000000..b0e9178d9b0b
--- /dev/null
+++ b/include/clang/Basic/DiagnosticAST.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticAST.h - Diagnostics for the AST library ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICAST_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICAST_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define ASTSTART
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_AST_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICAST_H
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 3358fc3d70c7..c39673a44ac0 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -121,6 +121,8 @@ def note_constexpr_ltor_non_const_int : Note<
"read of non-const variable %0 is not allowed in a constant expression">;
def note_constexpr_ltor_non_constexpr : Note<
"read of non-constexpr variable %0 is not allowed in a constant expression">;
+def note_constexpr_ltor_incomplete_type : Note<
+ "read of incomplete type %0 is not allowed in a constant expression">;
def note_constexpr_access_null : Note<
"%select{read of|assignment to|increment of|decrement of}0 "
"dereferenced null pointer is not allowed in a constant expression">;
@@ -163,12 +165,19 @@ def note_constexpr_unsupported_unsized_array : Note<
def note_constexpr_unsized_array_indexed : Note<
"indexing of array without known bound is not allowed "
"in a constant expression">;
+def note_constexpr_memcpy_null : Note<
+ "%select{source|destination}2 of "
+ "'%select{%select{memcpy|wmemcpy}1|%select{memmove|wmemmove}1}0' "
+ "is %3">;
def note_constexpr_memcpy_type_pun : Note<
"cannot constant evaluate '%select{memcpy|memmove}0' from object of "
"type %1 to object of type %2">;
def note_constexpr_memcpy_nontrivial : Note<
"cannot constant evaluate '%select{memcpy|memmove}0' between objects of "
"non-trivially-copyable type %1">;
+def note_constexpr_memcpy_incomplete_type : Note<
+ "cannot constant evaluate '%select{memcpy|memmove}0' between objects of "
+ "incomplete type %1">;
def note_constexpr_memcpy_overlap : Note<
"'%select{memcpy|wmemcpy}0' between overlapping memory regions">;
def note_constexpr_memcpy_unsupported : Note<
@@ -305,4 +314,34 @@ def err_odr_non_type_parameter_type_inconsistent : Error<
"non-type template parameter declared with incompatible types in different "
"translation units (%0 vs. %1)">;
def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">;
+
+def remark_sanitize_address_insert_extra_padding_accepted : Remark<
+ "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader,
+ InGroup<SanitizeAddressRemarks>;
+def remark_sanitize_address_insert_extra_padding_rejected : Remark<
+ "-fsanitize-address-field-padding ignored for %0 because it "
+ "%select{is not C++|is packed|is a union|is trivially copyable|"
+ "has trivial destructor|is standard layout|is in a blacklisted file|"
+ "is blacklisted}1">, ShowInSystemHeader,
+ InGroup<SanitizeAddressRemarks>;
+
+def warn_npot_ms_struct : Warning<
+ "ms_struct may not produce Microsoft-compatible layouts with fundamental "
+ "data types with sizes that aren't a power of two">,
+ DefaultError, InGroup<IncompatibleMSStruct>;
+
+// -Wpadded, -Wpacked
+def warn_padded_struct_field : Warning<
+ "padding %select{struct|interface|class}0 %1 with %2 "
+ "%select{byte|bit}3%s2 to align %4">,
+ InGroup<Padded>, DefaultIgnore;
+def warn_padded_struct_anon_field : Warning<
+ "padding %select{struct|interface|class}0 %1 with %2 "
+ "%select{byte|bit}3%s2 to align anonymous bit-field">,
+ InGroup<Padded>, DefaultIgnore;
+def warn_padded_struct_size : Warning<
+ "padding size of %0 with %1 %select{byte|bit}2%s1 to alignment boundary">,
+ InGroup<Padded>, DefaultIgnore;
+def warn_unnecessary_packed : Warning<
+ "packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
}
diff --git a/include/clang/Basic/DiagnosticAnalysis.h b/include/clang/Basic/DiagnosticAnalysis.h
new file mode 100644
index 000000000000..3748b538d2d2
--- /dev/null
+++ b/include/clang/Basic/DiagnosticAnalysis.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticAnalysis.h - Diagnostics for libanalysis -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICANALYSIS_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICANALYSIS_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define ANALYSISSTART
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_ANALYSIS_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICANALYSIS_H
diff --git a/include/clang/Basic/DiagnosticComment.h b/include/clang/Basic/DiagnosticComment.h
new file mode 100644
index 000000000000..a6c5f182cb32
--- /dev/null
+++ b/include/clang/Basic/DiagnosticComment.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticComment.h - Diagnostics for the AST library --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICCOMMENT_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICCOMMENT_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define COMMENTSTART
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_COMMENT_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICCOMMENT_H
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index b98b183c9d6f..34ce489e50b2 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -131,6 +131,36 @@ def err_nullability_conflicting : Error<
}
+// OpenCL Section 6.8.g
+def err_opencl_unknown_type_specifier : Error<
+ "OpenCL %select{C|C++}0 version %1 does not support the '%2' "
+ "%select{type qualifier|storage class specifier}3">;
+
+def warn_unknown_attribute_ignored : Warning<
+ "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def err_use_of_tag_name_without_tag : Error<
+ "must use '%1' tag to refer to type %0%select{| in this scope}2">;
+
+def duplicate_declspec : TextSubstitution<
+ "duplicate '%0' declaration specifier">;
+
+def ext_duplicate_declspec : Extension<"%sub{duplicate_declspec}0">,
+ InGroup<DuplicateDeclSpecifier>;
+def ext_warn_duplicate_declspec : ExtWarn<"%sub{duplicate_declspec}0">,
+ InGroup<DuplicateDeclSpecifier>;
+def warn_duplicate_declspec : Warning<"%sub{duplicate_declspec}0">,
+ InGroup<DuplicateDeclSpecifier>;
+
+def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
+
+def err_invalid_member_in_interface : Error<
+ "%select{data member |non-public member function |static member function |"
+ "user-declared constructor|user-declared destructor|operator |"
+ "nested class }0%1 is not permitted within an interface type">;
+
+def err_attribute_uuid_malformed_guid : Error<
+ "uuid attribute contains a malformed GUID">;
+
// Sema && Lex
def ext_c99_longlong : Extension<
"'long long' is an extension when C99 mode is not enabled">,
@@ -172,6 +202,8 @@ def err_too_large_for_fixed_point : Error<
"this value is too large for this fixed point type">;
def err_fixed_point_not_enabled : Error<"compile with "
"'-ffixed-point' to enable fixed point types">;
+def err_unimplemented_conversion_with_fixed_point_type : Error<
+ "conversion between fixed point and %0 is not yet supported">;
// SEH
def err_seh_expected_handler : Error<
@@ -187,6 +219,16 @@ def err_seh___finally_block : Error<
def note_invalid_subexpr_in_const_expr : Note<
"subexpression not valid in a constant expression">;
+// Sema && Frontend
+let CategoryName = "Inline Assembly Issue" in {
+ def err_asm_invalid_type_in_input : Error<
+ "invalid type %0 in asm input for constraint '%1'">;
+}
+
+// Sema && Serialization
+def warn_dup_category_def : Warning<
+ "duplicate definition of category %1 on interface %0">;
+
// Targets
def err_target_unknown_triple : Error<
@@ -199,6 +241,9 @@ def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">;
def err_target_unsupported_abi_for_triple : Error<
"ABI '%0' is not supported for '%1'">;
+def err_unsupported_abi_for_opt : Error<"'%0' can only be used with the '%1' ABI">;
+def err_mips_fp64_req : Error<
+ "'%0' can only be used if the target supports the mfhc1 and mthc1 instructions">;
def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">;
def err_target_unsupported_fpmath : Error<
"the '%0' unit is not supported with this instruction set">;
@@ -245,4 +290,10 @@ def err_openclcxx_not_supported : Error<
// OpenMP
def err_omp_more_one_clause : Error<
"directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
+
+// Static Analyzer Core
+def err_unknown_analyzer_checker : Error<
+ "no analyzer checkers are associated with '%0'">;
+def note_suggest_disabling_all_checkers : Note<
+ "use -analyzer-disable-all-checks to disable all static analyzer checkers">;
}
diff --git a/include/clang/Basic/DiagnosticCrossTU.h b/include/clang/Basic/DiagnosticCrossTU.h
new file mode 100644
index 000000000000..8cff33479f43
--- /dev/null
+++ b/include/clang/Basic/DiagnosticCrossTU.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticCrossTU.h - Diagnostics for Cross TU ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICCROSSTU_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICCROSSTU_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define CROSSTUSTART
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_CROSSTU_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICCROSSTU_H
diff --git a/include/clang/Basic/DiagnosticCrossTUKinds.td b/include/clang/Basic/DiagnosticCrossTUKinds.td
index 8b6d8b681445..89e261c84bc6 100644
--- a/include/clang/Basic/DiagnosticCrossTUKinds.td
+++ b/include/clang/Basic/DiagnosticCrossTUKinds.td
@@ -9,10 +9,17 @@
let Component = "CrossTU" in {
-def err_fnmap_parsing : Error<
+def err_ctu_error_opening : Error<
+ "error opening '%0': required by the CrossTU functionality">;
+
+def err_extdefmap_parsing : Error<
"error parsing index file: '%0' line: %1 'UniqueID filename' format "
"expected">;
def err_multiple_def_index : Error<
"multiple definitions are found for the same key in index ">;
+
+def warn_ctu_incompat_triple : Warning<
+ "imported AST from '%0' had been generated for a different target, "
+ "current: %1, imported: %2">, InGroup<CrossTU>;
}
diff --git a/include/clang/Basic/DiagnosticDriver.h b/include/clang/Basic/DiagnosticDriver.h
new file mode 100644
index 000000000000..2ab9b3e08366
--- /dev/null
+++ b/include/clang/Basic/DiagnosticDriver.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticDriver.h - Diagnostics for libdriver ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICDRIVER_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICDRIVER_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define DRIVERSTART
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_DRIVER_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICDRIVER_H
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 7f75f45c6578..5475e28ed754 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -151,9 +151,6 @@ def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning<
"unknown argument ignored in clang-cl '%0' (did you mean '%1'?)">,
InGroup<UnknownArgument>;
-def warn_drv_ycyu_no_arg_clang_cl : Warning<
- "support for '%0' without a filename not implemented yet; flag ignored">,
- InGroup<ClangClPch>;
def warn_drv_ycyu_different_arg_clang_cl : Warning<
"support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored">,
InGroup<ClangClPch>;
@@ -164,6 +161,9 @@ def warn_drv_yc_multiple_inputs_clang_cl : Warning<
"support for '/Yc' with more than one source file not implemented yet; flag ignored">,
InGroup<ClangClPch>;
+def err_drv_dllexport_inlines_and_fallback : Error<
+ "option '/Zc:dllexportInlines-' is ABI-changing and not compatible with '/fallback'">;
+
def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
def err_drv_invalid_remap_file : Error<
@@ -193,6 +193,9 @@ def err_drv_mg_requires_m_or_mm : Error<
"option '-MG' requires '-M' or '-MM'">;
def err_drv_unknown_objc_runtime : Error<
"unknown or ill-formed Objective-C runtime '%0'">;
+def err_drv_invalid_cf_runtime_abi
+ : Error<"invalid CoreFoundation Runtime ABI '%0'; must be one of "
+ "'objc', 'standalone', 'swift', 'swift-5.0', 'swift-4.2', 'swift-4.1'">;
def err_drv_gnustep_objc_runtime_incompatible_binary : Error<
"GNUstep Objective-C runtime version %0 incompatible with target binary format">;
def err_drv_emit_llvm_link : Error<
@@ -213,6 +216,8 @@ def warn_drv_omp_offload_target_duplicate : Warning<
def warn_drv_omp_offload_target_missingbcruntime : Warning<
"No library '%0' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.">,
InGroup<OpenMPTarget>;
+def err_drv_unsupported_embed_bitcode
+ : Error<"%0 is not supported with -fembed-bitcode">;
def err_drv_bitcode_unsupported_on_toolchain : Error<
"-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
@@ -277,6 +282,8 @@ def warn_drv_disabling_vptr_no_rtti_default : Warning<
def warn_drv_object_size_disabled_O0 : Warning<
"the object size sanitizer has no effect at -O0, but is explicitly enabled: %0">,
InGroup<InvalidCommandLineArgument>, DefaultWarnNoWerror;
+def err_invalid_branch_protection: Error <
+ "invalid branch protection option '%0' in '%1'">;
def note_drv_command_failed_diag_msg : Note<
"diagnostic msg: %0">;
@@ -292,6 +299,9 @@ def err_analyzer_config_no_value : Error<
"analyzer-config option '%0' has a key but no value">;
def err_analyzer_config_multiple_values : Error<
"analyzer-config option '%0' should contain only one '='">;
+def err_analyzer_config_invalid_input : Error<
+ "invalid input for analyzer-config option '%0', that expects %1 value">;
+def err_analyzer_config_unknown : Error<"unknown analyzer-config '%0'">;
def err_drv_invalid_hvx_length : Error<
"-mhvx-length is not supported without a -mhvx/-mhvx= flag">;
@@ -299,6 +309,9 @@ def warn_drv_vectorize_needs_hvx : Warning<
"auto-vectorization requires HVX, use -mhvx to enable it">,
InGroup<OptionIgnored>;
+def err_drv_module_header_wrong_kind : Error<
+ "header file '%0' input type '%1' does not match type of prior input "
+ "in module compilation; use '-x %2' to override">;
def err_drv_modules_validate_once_requires_timestamp : Error<
"option '-fmodules-validate-once-per-build-session' requires "
"'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">;
@@ -347,7 +360,7 @@ def warn_drv_unsupported_pic_with_mabicalls : Warning<
"%select{implicit usage of|}1 -mabicalls and the N64 ABI">,
InGroup<OptionIgnored>;
def err_drv_unsupported_noabicalls_pic : Error<
- "position-independent code requires ‘-mabicalls’">;
+ "position-independent code requires '-mabicalls'">;
def err_drv_unsupported_indirect_jump_opt : Error<
"'-mindirect-jump=%0' is unsupported with the '%1' architecture">;
def err_drv_unknown_indirect_jump_opt : Error<
@@ -392,4 +405,24 @@ def warn_drv_experimental_isel_incomplete_opt : Warning<
def warn_drv_moutline_unsupported_opt : Warning<
"The '%0' architecture does not support -moutline; flag ignored">,
InGroup<OptionIgnored>;
+
+def warn_drv_darwin_sdk_invalid_settings : Warning<
+ "SDK settings were ignored as 'SDKSettings.json' could not be parsed">,
+ InGroup<DiagGroup<"darwin-sdk-settings">>;
+
+def err_drv_trivial_auto_var_init_zero_disabled : Error<
+ "-ftrivial-auto-var-init=zero hasn't been enabled. Enable it at your own peril for benchmarking purpose only with "
+ "-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">;
+
+def warn_drv_msp430_hwmult_unsupported : Warning<"the given MCU does not "
+ "support hardware multiply, but -mhwmult is set to %0.">,
+ InGroup<InvalidCommandLineArgument>;
+def warn_drv_msp430_hwmult_mismatch : Warning<"the given MCU supports %0 "
+ "hardware multiply, but -mhwmult is set to %1.">,
+ InGroup<InvalidCommandLineArgument>;
+def warn_drv_msp430_hwmult_no_device : Warning<"no MCU device specified, but "
+ "'-mhwmult' is set to 'auto', assuming no hardware multiply. Use -mmcu to "
+ "specify a MSP430 device, or -mhwmult to set hardware multiply type "
+ "explicitly.">, InGroup<InvalidCommandLineArgument>;
+
}
diff --git a/include/clang/Basic/DiagnosticFrontend.h b/include/clang/Basic/DiagnosticFrontend.h
new file mode 100644
index 000000000000..1f066cf491ae
--- /dev/null
+++ b/include/clang/Basic/DiagnosticFrontend.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticFrontend.h - Diagnostics for frontend --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICFRONTEND_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICFRONTEND_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define FRONTENDSTART
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_FRONTEND_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICFRONTEND_H
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 66287933b7ca..927b8cbc2477 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -63,16 +63,6 @@ def note_fe_backend_invalid_loc : Note<"could "
def err_fe_backend_unsupported : Error<"%0">, BackendInfo;
-def remark_sanitize_address_insert_extra_padding_accepted : Remark<
- "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader,
- InGroup<SanitizeAddressRemarks>;
-def remark_sanitize_address_insert_extra_padding_rejected : Remark<
- "-fsanitize-address-field-padding ignored for %0 because it "
- "%select{is not C++|is packed|is a union|is trivially copyable|"
- "has trivial destructor|is standard layout|is in a blacklisted file|"
- "is blacklisted}1">, ShowInSystemHeader,
- InGroup<SanitizeAddressRemarks>;
-
def err_fe_invalid_code_complete_file : Error<
"cannot locate code-completion file %0">, DefaultFatal;
def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
@@ -99,8 +89,6 @@ def err_fe_unable_to_interface_with_target : Error<
"unable to interface with target machine">;
def err_fe_unable_to_open_output : Error<
"unable to open output file '%0': '%1'">;
-def err_fe_pth_file_has_no_source_header : Error<
- "PTH file '%0' does not designate an original source header file for -include-pth">;
def warn_fe_macro_contains_embedded_newline : Warning<
"macro '%0' contains embedded newline; text after the newline is ignored">;
def warn_fe_cc_print_header_failure : Warning<
@@ -172,11 +160,6 @@ def warn_unknown_warning_specifier : Warning<
"unknown %0 warning specifier: '%1'">,
InGroup<UnknownWarningOption>;
-def err_unknown_analyzer_checker : Error<
- "no analyzer checkers are associated with '%0'">;
-def note_suggest_disabling_all_checkers : Note<
- "use -analyzer-disable-all-checks to disable all static analyzer checkers">;
-
def warn_incompatible_analyzer_plugin_api : Warning<
"checker plugin '%0' is not compatible with this version of the analyzer">,
InGroup<DiagGroup<"analyzer-incompatible-plugin"> >;
@@ -187,6 +170,8 @@ def err_module_build_requires_fmodules : Error<
"module compilation requires '-fmodules'">;
def err_module_interface_requires_modules_ts : Error<
"module interface compilation requires '-fmodules-ts'">;
+def err_header_module_requires_modules : Error<
+ "header module compilation requires '-fmodules' or '-fmodules-ts'">;
def warn_module_config_mismatch : Warning<
"module file %0 cannot be loaded due to a configuration mismatch with the current "
"compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
@@ -224,6 +209,10 @@ def remark_module_build_done : Remark<"finished building module '%0'">,
def err_modules_embed_file_not_found :
Error<"file '%0' specified by '-fmodules-embed-file=' not found">,
DefaultFatal;
+def err_module_header_file_not_found :
+ Error<"module header file '%0' not found">, DefaultFatal;
+def err_module_header_file_invalid :
+ Error<"unexpected module header file input '%0'">, DefaultFatal;
def err_test_module_file_extension_version : Error<
"test module file extension '%0' has different version (%1.%2) than expected "
@@ -238,7 +227,52 @@ def warn_option_invalid_ocl_version : Warning<
"OpenCL version %0 does not support the option '%1'">, InGroup<Deprecated>;
def warn_stdlibcxx_not_found : Warning<
- "include path for stdlibc++ headers not found; pass '-std=libc++' on the "
+ "include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the "
"command line to use the libc++ standard library instead">,
InGroup<DiagGroup<"stdlibcxx-not-found">>;
+
+def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
+def err_function_needs_feature : Error<
+ "always_inline function %1 requires target feature '%2', but would "
+ "be inlined into function %0 that is compiled without support for '%2'">;
+
+def err_alias_to_undefined : Error<
+ "%select{alias|ifunc}0 must point to a defined "
+ "%select{variable or |}1function">;
+def warn_alias_to_weak_alias : Warning<
+ "%select{alias|ifunc}2 will always resolve to %0 even if weak definition of "
+ "%1 is overridden">,
+ InGroup<IgnoredAttributes>;
+def err_duplicate_mangled_name : Error<
+ "definition with same mangled name '%0' as another definition">;
+def err_cyclic_alias : Error<
+ "%select{alias|ifunc}0 definition is part of a cycle">;
+def err_ifunc_resolver_return : Error<
+ "ifunc resolver function must return a pointer">;
+
+def warn_atomic_op_misaligned : Warning<
+ "%select{large|misaligned}0 atomic operation may incur "
+ "significant performance penalty">, InGroup<DiagGroup<"atomic-alignment">>;
+
+def warn_alias_with_section : Warning<
+ "%select{alias|ifunc}1 will not be in section '%0' but in the same section "
+ "as the %select{aliasee|resolver}2">,
+ InGroup<IgnoredAttributes>;
+
+let CategoryName = "Instrumentation Issue" in {
+def warn_profile_data_out_of_date : Warning<
+ "profile data may be out of date: of %0 function%s0, %1 %plural{1:has|:have}1"
+ " mismatched data that will be ignored">,
+ InGroup<ProfileInstrOutOfDate>;
+def warn_profile_data_missing : Warning<
+ "profile data may be incomplete: of %0 function%s0, %1 %plural{1:has|:have}1"
+ " no data">,
+ InGroup<ProfileInstrMissing>,
+ DefaultIgnore;
+def warn_profile_data_unprofiled : Warning<
+ "no profile data available for file \"%0\"">,
+ InGroup<ProfileInstrUnprofiled>;
+
+} // end of instrumentation issue category
+
}
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 2156ef93c19f..19e187cc5d93 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -59,6 +59,8 @@ def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
UndefinedBoolConversion]>;
def IntConversion : DiagGroup<"int-conversion">;
def EnumConversion : DiagGroup<"enum-conversion">;
+def ImplicitIntConversion : DiagGroup<"implicit-int-conversion">;
+def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion">;
def FloatOverflowConversion : DiagGroup<"float-overflow-conversion">;
def FloatZeroConversion : DiagGroup<"float-zero-conversion">;
@@ -102,7 +104,11 @@ def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">;
def MissingNoEscape : DiagGroup<"missing-noescape">;
def DeleteIncomplete : DiagGroup<"delete-incomplete">;
-def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
+def DeleteNonAbstractNonVirtualDtor : DiagGroup<"delete-non-abstract-non-virtual-dtor">;
+def DeleteAbstractNonVirtualDtor : DiagGroup<"delete-abstract-non-virtual-dtor">;
+def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor",
+ [DeleteNonAbstractNonVirtualDtor,
+ DeleteAbstractNonVirtualDtor]>;
def AbstractFinalClass : DiagGroup<"abstract-final-class">;
def CXX11CompatDeprecatedWritableStr :
@@ -160,6 +166,8 @@ def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">;
def ExtraTokens : DiagGroup<"extra-tokens">;
def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">;
def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
+def EmptyInitStatement : DiagGroup<"empty-init-stmt">;
+def ExtraSemiStmt : DiagGroup<"extra-semi-stmt", [EmptyInitStatement]>;
def ExtraSemi : DiagGroup<"extra-semi", [CXX98CompatExtraSemi,
CXX11ExtraSemi]>;
@@ -283,6 +291,7 @@ def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
def FlagEnum : DiagGroup<"flag-enum">;
def IncrementBool : DiagGroup<"increment-bool", [DeprecatedIncrementBool]>;
def InfiniteRecursion : DiagGroup<"infinite-recursion">;
+def PureVirtualCallFromCtorDtor: DiagGroup<"call-to-pure-virtual-from-ctor-dtor">;
def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
@@ -356,6 +365,8 @@ def NullArithmetic : DiagGroup<"null-arithmetic">;
def NullCharacter : DiagGroup<"null-character">;
def NullDereference : DiagGroup<"null-dereference">;
def InitializerOverrides : DiagGroup<"initializer-overrides">;
+// For compatibility with GCC; -Woverride-init = -Winitializer-overrides
+def : DiagGroup<"override-init", [InitializerOverrides]>;
def NonNull : DiagGroup<"nonnull">;
def NonPODVarargs : DiagGroup<"non-pod-varargs">;
def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>;
@@ -364,7 +375,6 @@ def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
def NullPointerArithmetic : DiagGroup<"null-pointer-arithmetic">;
def : DiagGroup<"effc++", [NonVirtualDtor]>;
def OveralignedType : DiagGroup<"over-aligned">;
-def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">;
def OldStyleCast : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
@@ -381,6 +391,7 @@ def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">;
def BadFunctionCast : DiagGroup<"bad-function-cast">;
def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">;
def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
+def ObjCPropertyAssignOnObjectType : DiagGroup<"objc-property-assign-on-object-type">;
def ObjCProtocolQualifiers : DiagGroup<"objc-protocol-qualifiers">;
def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
def ObjCDesignatedInit : DiagGroup<"objc-designated-initializers">;
@@ -621,7 +632,8 @@ def DeallocInCategory:DiagGroup<"dealloc-in-category">;
def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
def Protocol : DiagGroup<"protocol">;
-def AtProtocol : DiagGroup<"at-protocol">;
+// No longer in use, preserve for backwards compatibility.
+def : DiagGroup<"at-protocol">;
def PropertyAccessDotSyntax: DiagGroup<"property-access-dot-syntax">;
def PropertyAttr : DiagGroup<"property-attribute-mismatch">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
@@ -708,6 +720,8 @@ def Conversion : DiagGroup<"conversion",
FloatConversion,
Shorten64To32,
IntConversion,
+ ImplicitIntConversion,
+ ImplicitFloatConversion,
LiteralConversion,
NonLiteralNullConversion, // (1-1)->pointer (etc)
NullConversion, // NULL->non-pointer
@@ -763,7 +777,8 @@ def Extra : DiagGroup<"extra", [
MissingMethodReturnType,
SignCompare,
UnusedParameter,
- NullPointerArithmetic
+ NullPointerArithmetic,
+ EmptyInitStatement
]>;
def Most : DiagGroup<"most", [
@@ -1030,3 +1045,8 @@ def ExperimentalISel : DiagGroup<"experimental-isel">;
// A warning group specifically for warnings related to function
// multiversioning.
def FunctionMultiVersioning : DiagGroup<"function-multiversion">;
+
+def NoDeref : DiagGroup<"noderef">;
+
+// A group for cross translation unit static analysis related warnings.
+def CrossTU : DiagGroup<"ctu">;
diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
index 983dcb21cfdf..876629f373a1 100644
--- a/include/clang/Basic/DiagnosticIDs.h
+++ b/include/clang/Basic/DiagnosticIDs.h
@@ -30,7 +30,7 @@ namespace clang {
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 200,
- DIAG_SIZE_FRONTEND = 100,
+ DIAG_SIZE_FRONTEND = 150,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 400,
DIAG_SIZE_PARSE = 500,
diff --git a/include/clang/Basic/DiagnosticLex.h b/include/clang/Basic/DiagnosticLex.h
new file mode 100644
index 000000000000..6ec4da80338f
--- /dev/null
+++ b/include/clang/Basic/DiagnosticLex.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticLex.h - Diagnostics for liblex ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICLEX_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICLEX_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define LEXSTART
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_LEX_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICLEX_H
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 1c960711bccb..14e306246ba3 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -122,6 +122,9 @@ def ext_unicode_whitespace : ExtWarn<
def warn_utf8_symbol_homoglyph : Warning<
"treating Unicode character <U+%0> as identifier character rather than "
"as '%1' symbol">, InGroup<DiagGroup<"unicode-homoglyph">>;
+def warn_utf8_symbol_zero_width : Warning<
+ "identifier contains Unicode character <U+%0> that is invisible in "
+ "some environments">, InGroup<DiagGroup<"unicode-zero-width">>;
def err_hex_escape_no_digits : Error<
"\\%0 used with no following hex digits">;
@@ -255,13 +258,6 @@ def warn_bad_character_encoding : ExtWarn<
def err_lexing_string : Error<"failure when lexing a string">;
def err_placeholder_in_source : Error<"editor placeholder in source file">;
-
-//===----------------------------------------------------------------------===//
-// PTH Diagnostics
-//===----------------------------------------------------------------------===//
-def err_invalid_pth_file : Error<
- "invalid or corrupt PTH file '%0'">;
-
//===----------------------------------------------------------------------===//
// Preprocessor Diagnostics
//===----------------------------------------------------------------------===//
@@ -409,11 +405,20 @@ def err_pp_through_header_not_found : Error<
def err_pp_through_header_not_seen : Error<
"#include of '%0' not seen while attempting to "
"%select{create|use}1 precompiled header">, DefaultFatal;
+def err_pp_pragma_hdrstop_not_seen : Error<
+ "#pragma hdrstop not seen while attempting to use precompiled header">,
+ DefaultFatal;
def warn_pp_macro_def_mismatch_with_pch : Warning<
"definition of macro %0 does not match definition in precompiled header">,
InGroup<ClangClPch>;
-def err_pp_file_not_found_not_fatal : Error<
+def warn_pp_hdrstop_filename_ignored : Warning<
+ "#pragma hdrstop filename not supported, "
+ "/Fp can be used to specify precompiled header filename">,
+ InGroup<ClangClPch>;
+def err_pp_file_not_found_angled_include_not_fatal : Error<
"'%0' file not found with <angled> include; use \"quotes\" instead">;
+def err_pp_file_not_found_typo_not_fatal
+ : Error<"'%0' file not found, did you mean '%1'?">;
def err_pp_error_opening_file : Error<
"error opening file '%0': %1">, DefaultFatal;
def err_pp_empty_filename : Error<"empty filename">;
@@ -558,8 +563,6 @@ def err_pp_module_end_without_module_begin : Error<
"'#pragma clang module end'">;
def note_pp_module_begin_here : Note<
"entering module '%0' due to this pragma">;
-def err_pp_module_build_pth : Error<
- "'#pragma clang module build' not supported in pretokenized header">;
def err_pp_module_build_missing_end : Error<
"no matching '#pragma clang module endbuild' for this '#pragma clang module build'">;
diff --git a/include/clang/Basic/DiagnosticParse.h b/include/clang/Basic/DiagnosticParse.h
new file mode 100644
index 000000000000..2113b03262d7
--- /dev/null
+++ b/include/clang/Basic/DiagnosticParse.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticParse.h - Diagnostics for libparse -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICPARSE_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICPARSE_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define PARSESTART
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_PARSE_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICPARSE_H
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 609dca4f075c..06281e2904c7 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -53,6 +53,10 @@ def ext_extra_semi_cxx11 : Extension<
def warn_extra_semi_after_mem_fn_def : Warning<
"extra ';' after member function definition">,
InGroup<ExtraSemi>, DefaultIgnore;
+def warn_null_statement : Warning<
+ "empty expression statement has no effect; "
+ "remove unnecessary ';' to silence this warning">,
+ InGroup<ExtraSemiStmt>, DefaultIgnore;
def ext_thread_before : Extension<"'__thread' before '%0'">;
def ext_keyword_as_ident : ExtWarn<
@@ -88,9 +92,12 @@ def err_enumerator_unnamed_no_def : Error<
def ext_cxx11_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a C++11 extension">,
InGroup<CXX11>;
-def ext_c_enum_fixed_underlying_type : Extension<
+def ext_ms_c_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a Microsoft extension">,
InGroup<MicrosoftFixedEnum>;
+def ext_clang_c_enum_fixed_underlying_type : Extension<
+ "enumeration types with a fixed underlying type are a Clang extension">,
+ InGroup<DiagGroup<"fixed-enum-extension">>;
def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
"enumeration types with a fixed underlying type are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -219,6 +226,11 @@ def ext_nested_namespace_definition : ExtWarn<
def warn_cxx14_compat_nested_namespace_definition : Warning<
"nested namespace definition is incompatible with C++ standards before C++17">,
InGroup<CXXPre17Compat>, DefaultIgnore;
+def ext_inline_nested_namespace_definition : ExtWarn<
+ "inline nested namespace definition is a C++2a extension">, InGroup<CXX2a>;
+def warn_cxx17_compat_inline_nested_namespace_definition : Warning<
+ "inline nested namespace definition is incompatible with C++ standards before"
+ " C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore;
def err_inline_nested_namespace_definition : Error<
"nested namespace definition cannot be 'inline'">;
def err_expected_semi_after_attribute_list : Error<
@@ -331,6 +343,10 @@ def err_expected_parentheses_around_typename : Error<
def err_expected_case_before_expression: Error<
"expected 'case' keyword before expression">;
+def ext_warn_gnu_final : ExtWarn<
+ "__final is a GNU extension, consider using C++11 final">,
+ InGroup<GccCompat>;
+
// Declarations.
def err_typename_requires_specqual : Error<
"type name requires a specifier or qualifier">;
@@ -358,6 +374,12 @@ def ext_c11_static_assert : Extension<
def warn_cxx98_compat_static_assert : Warning<
"static_assert declarations are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def ext_static_assert_no_message : ExtWarn<
+ "static_assert with no message is a C++17 extension">, InGroup<CXX17>;
+def warn_cxx14_compat_static_assert_no_message : Warning<
+ "static_assert with no message is incompatible with C++ standards before "
+ "C++17">,
+ DefaultIgnore, InGroup<CXXPre17Compat>;
def err_function_definition_not_allowed : Error<
"function definition is not allowed here">;
def err_expected_end_of_enumerator : Error<
@@ -488,6 +510,13 @@ def err_dynamic_and_noexcept_specification : Error<
"cannot have both throw() and noexcept() clause on the same function">;
def err_except_spec_unparsed : Error<
"unexpected end of exception specification">;
+def ext_dynamic_exception_spec : ExtWarn<
+ "ISO C++17 does not allow dynamic exception specifications">,
+ InGroup<DynamicExceptionSpec>, DefaultError;
+def warn_exception_spec_deprecated : Warning<
+ "dynamic exception specifications are deprecated">,
+ InGroup<DeprecatedDynamicExceptionSpec>, DefaultIgnore;
+def note_exception_spec_deprecated : Note<"use '%0' instead">;
def warn_cxx98_compat_noexcept_decl : Warning<
"noexcept specifications are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -540,6 +569,15 @@ def ext_init_statement : ExtWarn<
def warn_cxx14_compat_init_statement : Warning<
"%select{if|switch}0 initialization statements are incompatible with "
"C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre17Compat>;
+def ext_for_range_init_stmt : ExtWarn<
+ "range-based for loop initialization statements are a C++2a extension">,
+ InGroup<CXX2a>;
+def warn_cxx17_compat_for_range_init_stmt : Warning<
+ "range-based for loop initialization statements are incompatible with "
+ "C++ standards before C++2a">, DefaultIgnore, InGroup<CXXPre2aCompat>;
+def warn_empty_init_statement : Warning<
+ "empty initialization statement of '%select{if|switch|range-based for}0' "
+ "has no effect">, InGroup<EmptyInitStatement>, DefaultIgnore;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -566,6 +604,9 @@ def warn_cxx98_compat_noexcept_expr : Warning<
def warn_cxx98_compat_nullptr : Warning<
"'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+def warn_wrong_clang_attr_namespace : Warning<
+ "'__clang__' is a predefined macro name, not an attribute scope specifier; "
+ "did you mean '_Clang' instead?">, InGroup<IgnoredAttributes>;
def ext_ns_enum_attribute : Extension<
"attributes on %select{a namespace|an enumerator}0 declaration are "
"a C++17 extension">, InGroup<CXX17>;
@@ -1023,8 +1064,8 @@ def err_pragma_optimize_invalid_argument : Error<
def err_pragma_optimize_extra_argument : Error<
"unexpected extra argument '%0' to '#pragma clang optimize'">;
// - #pragma clang attribute
-def err_pragma_attribute_expected_push_pop : Error<
- "expected 'push' or 'pop' after '#pragma clang attribute'">;
+def err_pragma_attribute_expected_push_pop_paren : Error<
+ "expected 'push', 'pop', or '(' after '#pragma clang attribute'">;
def err_pragma_attribute_invalid_argument : Error<
"unexpected argument '%0' to '#pragma clang attribute'; "
"expected 'push' or 'pop'">;
@@ -1059,6 +1100,13 @@ def err_pragma_attribute_unknown_subject_sub_rule : Error<
"sub-rules: %3}2">;
def err_pragma_attribute_duplicate_subject : Error<
"duplicate attribute subject matcher '%0'">;
+def err_pragma_attribute_expected_period : Error<
+ "expected '.' after pragma attribute namespace %0">;
+def err_pragma_attribute_namespace_on_attribute : Error<
+ "namespace can only apply to 'push' or 'pop' directives">;
+def note_pragma_attribute_namespace_on_attribute : Note<
+ "omit the namespace to add attributes to the most-recently"
+ " pushed attribute group">;
def err_opencl_unroll_hint_on_non_loop : Error<
"OpenCL only supports 'opencl_unroll_hint' attribute on for, while, and do statements">;
@@ -1116,15 +1164,19 @@ def err_omp_decl_in_declare_simd : Error<
def err_omp_unknown_map_type : Error<
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
def err_omp_unknown_map_type_modifier : Error<
- "incorrect map type modifier, expected 'always'">;
+ "incorrect map type modifier, expected 'always' or 'close'">;
def err_omp_map_type_missing : Error<
"missing map type">;
+def err_omp_map_type_modifier_missing : Error<
+ "missing map type modifier">;
def err_omp_declare_simd_inbranch_notinbranch : Error<
"unexpected '%0' clause, '%1' is specified already">;
def err_expected_end_declare_target : Error<
"expected '#pragma omp end declare target'">;
def err_omp_declare_target_unexpected_clause: Error<
"unexpected '%0' clause, only 'to' or 'link' clauses expected">;
+def err_omp_expected_clause: Error<
+ "expected at least one clause on '#pragma omp %0' directive">;
// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
@@ -1132,7 +1184,8 @@ def err_pragma_loop_missing_argument : Error<
"'enable'%select{|, 'full'}1%select{|, 'assume_safety'}2 or 'disable'}0">;
def err_pragma_loop_invalid_option : Error<
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
- "vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute">;
+ "vectorize_width, interleave, interleave_count, unroll, unroll_count, "
+ "pipeline, pipeline_initiation_interval, or distribute">;
def err_pragma_fp_invalid_option : Error<
"%select{invalid|missing}0 option%select{ %1|}0; expected contract">;
@@ -1145,6 +1198,8 @@ def err_pragma_fp_scope : Error<
def err_pragma_invalid_keyword : Error<
"invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">;
+def err_pragma_pipeline_invalid_keyword : Error<
+ "invalid argument; expected 'disable'">;
// Pragma unroll support.
def warn_pragma_unroll_cuda_value_in_parens : Warning<
diff --git a/include/clang/Basic/DiagnosticRefactoring.h b/include/clang/Basic/DiagnosticRefactoring.h
new file mode 100644
index 000000000000..8d3914f25289
--- /dev/null
+++ b/include/clang/Basic/DiagnosticRefactoring.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticRefactoring.h - ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICREFACTORING_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICREFACTORING_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define REFACTORINGSTART
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_REFACTORING_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICREFACTORING_H
diff --git a/include/clang/Basic/DiagnosticSema.h b/include/clang/Basic/DiagnosticSema.h
new file mode 100644
index 000000000000..b05b24db5609
--- /dev/null
+++ b/include/clang/Basic/DiagnosticSema.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticSema.h - Diagnostics for libsema -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICSEMA_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICSEMA_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define SEMASTART
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_SEMA_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICSEMA_H
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 586f65e9201c..5feb877e46c5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -192,10 +192,6 @@ def ext_flexible_array_init : Extension<
"flexible array initialization is a GNU extension">, InGroup<GNUFlexibleArrayInitializer>;
// Declarations.
-def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">,
- InGroup<DuplicateDeclSpecifier>;
-def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
- InGroup<DuplicateDeclSpecifier>;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
def ext_imaginary_constant : Extension<
@@ -209,7 +205,6 @@ def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
def err_invalid_width_spec : Error<
"'%select{|short|long|long long}0 %1' is invalid">;
def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
-def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
def ext_auto_type_specifier : ExtWarn<
"'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
@@ -250,9 +245,6 @@ def err_invalid_vector_long_double_decl_spec : Error<
def warn_vector_long_decl_spec_combination : Warning<
"Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
-def err_use_of_tag_name_without_tag : Error<
- "must use '%1' tag to refer to type %0%select{| in this scope}2">;
-
def err_redeclaration_different_type : Error<
"redeclaration of %0 with a different type%diff{: $ vs $|}1,2">;
def err_bad_variable_name : Error<
@@ -369,7 +361,7 @@ def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
def ext_implicit_function_decl : ExtWarn<
- "implicit declaration of function %0 is invalid in %select{C99|OpenCL}1">,
+ "implicit declaration of function %0 is invalid in C99">,
InGroup<ImplicitFunctionDeclare>;
def note_function_suggestion : Note<"did you mean %0?">;
@@ -452,10 +444,12 @@ def err_decomp_decl_multiple_bases_with_members : Error<
"have non-static data members">;
def err_decomp_decl_ambiguous_base : Error<
"cannot decompose members of ambiguous base class %1 of %0:%2">;
-def err_decomp_decl_non_public_base : Error<
- "cannot decompose members of non-public base class %1 of %0">;
-def err_decomp_decl_non_public_member : Error<
- "cannot decompose non-public member %0 of %1">;
+def err_decomp_decl_inaccessible_base : Error<
+ "cannot decompose members of inaccessible base class %1 of %0">,
+ AccessControl;
+def err_decomp_decl_inaccessible_field : Error<
+ "cannot decompose %select{private|protected}0 member %1 of %3">,
+ AccessControl;
def err_decomp_decl_anon_union_member : Error<
"cannot decompose class type %0 because it has an anonymous "
"%select{struct|union}1 member">;
@@ -526,13 +520,6 @@ def warn_access_decl_deprecated : Warning<
def err_access_decl : Error<
"ISO C++11 does not allow access declarations; "
"use using declarations instead">;
-def ext_dynamic_exception_spec : ExtWarn<
- "ISO C++17 does not allow dynamic exception specifications">,
- InGroup<DynamicExceptionSpec>, DefaultError;
-def warn_exception_spec_deprecated : Warning<
- "dynamic exception specifications are deprecated">,
- InGroup<DeprecatedDynamicExceptionSpec>, DefaultIgnore;
-def note_exception_spec_deprecated : Note<"use '%0' instead">;
def warn_deprecated_copy_operation : Warning<
"definition of implicit copy %select{constructor|assignment operator}1 "
"for %0 is deprecated because it has a user-declared "
@@ -618,11 +605,6 @@ def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
def err_invalid_cpu_is : Error<"invalid cpu name for builtin">;
def err_invalid_cpu_specific_dispatch_value : Error<
"invalid option '%0' for %select{cpu_specific|cpu_dispatch}1">;
-def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
-def err_function_needs_feature
- : Error<"always_inline function %1 requires target feature '%2', but would "
- "be inlined into function %0 that is compiled without support for "
- "'%2'">;
def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
InGroup<ImplicitFunctionDeclare>, DefaultError;
def warn_cstruct_memaccess : Warning<
@@ -694,7 +676,8 @@ def warn_assume_side_effects : Warning<
InGroup<DiagGroup<"assume">>;
def warn_memcpy_chk_overflow : Warning<
- "%0 will always overflow destination buffer">,
+ "'%0' will always overflow; destination buffer has size %1,"
+ " but size argument is %2">,
InGroup<DiagGroup<"builtin-memcpy-chk-size">>;
/// main()
@@ -773,7 +756,7 @@ def warn_pragma_pack_non_default_at_include : Warning<
"members in the included file">, InGroup<PragmaPackSuspiciousInclude>,
DefaultIgnore;
def warn_pragma_pack_modified_after_include : Warning<
- "the current #pragma pack aligment value is modified in the included "
+ "the current #pragma pack alignment value is modified in the included "
"file">, InGroup<PragmaPack>;
def warn_pragma_pack_no_pop_eof : Warning<"unterminated "
"'#pragma pack (push, ...)' at end of file">, InGroup<PragmaPack>;
@@ -791,10 +774,6 @@ def warn_cxx_ms_struct :
Warning<"ms_struct may not produce Microsoft-compatible layouts for classes "
"with base classes or virtual functions">,
DefaultError, InGroup<IncompatibleMSStruct>;
-def warn_npot_ms_struct :
- Warning<"ms_struct may not produce Microsoft-compatible layouts with fundamental "
- "data types with sizes that aren't a power of two">,
- DefaultError, InGroup<IncompatibleMSStruct>;
def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">;
def err_invalid_super_scope : Error<"invalid use of '__super', "
@@ -836,7 +815,8 @@ def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error<
def err_pragma_attribute_invalid_matchers : Error<
"attribute %0 can't be applied to %1">;
def err_pragma_attribute_stack_mismatch : Error<
- "'#pragma clang attribute pop' with no matching '#pragma clang attribute push'">;
+ "'#pragma clang attribute %select{%1.|}0pop' with no matching"
+ " '#pragma clang attribute %select{%1.|}0push'">;
def warn_pragma_attribute_unused : Warning<
"unused attribute %0 in '#pragma clang attribute push' region">,
InGroup<PragmaClangAttribute>;
@@ -846,6 +826,9 @@ def err_pragma_attribute_no_pop_eof : Error<"unterminated "
"'#pragma clang attribute push' at end of file">;
def note_pragma_attribute_applied_decl_here : Note<
"when applied to this declaration">;
+def err_pragma_attr_attr_no_push : Error<
+ "'#pragma clang attribute' attribute with no matching "
+ "'#pragma clang attribute push'">;
/// Objective-C parser diagnostics
def err_duplicate_class_def : Error<
@@ -867,8 +850,8 @@ def err_protocol_has_circular_dependency : Error<
"protocol has circular dependency">;
def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">;
def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">;
-def warn_atprotocol_protocol : Warning<
- "@protocol is using a forward protocol declaration of %0">, InGroup<AtProtocol>;
+def err_atprotocol_protocol : Error<
+ "@protocol is using a forward protocol declaration of %0">;
def warn_readonly_property : Warning<
"attribute 'readonly' of property %0 restricts attribute "
"'readwrite' of property inherited from %1">,
@@ -920,8 +903,6 @@ def err_objc_runtime_visible_subclass : Error<
"Objective-C runtime">;
def note_objc_needs_superclass : Note<
"add a super class to fix this problem">;
-def warn_dup_category_def : Warning<
- "duplicate definition of category %1 on interface %0">;
def err_conflicting_super_class : Error<"conflicting super class name %0">;
def err_dup_implementation_class : Error<"reimplementation of class %0">;
def err_dup_implementation_category : Error<
@@ -1046,6 +1027,9 @@ def err_objc_property_attr_mutually_exclusive : Error<
"property attributes '%0' and '%1' are mutually exclusive">;
def err_objc_property_requires_object : Error<
"property with '%0' attribute must be of object type">;
+def warn_objc_property_assign_on_object : Warning<
+ "'assign' property of object type may become a dangling reference; consider using 'unsafe_unretained'">,
+ InGroup<ObjCPropertyAssignOnObjectType>, DefaultIgnore;
def warn_objc_property_no_assignment_attribute : Warning<
"no 'assign', 'retain', or 'copy' attribute is specified - "
"'assign' is assumed">,
@@ -1278,11 +1262,6 @@ def err_static_assert_expression_is_not_constant : Error<
def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">;
def err_static_assert_requirement_failed : Error<
"static_assert failed due to requirement '%0'%select{ %2|}1">;
-def ext_static_assert_no_message : ExtWarn<
- "static_assert with no message is a C++17 extension">, InGroup<CXX17>;
-def warn_cxx14_compat_static_assert_no_message : Warning<
- "static_assert with no message is incompatible with C++ standards before C++17">,
- DefaultIgnore, InGroup<CXXPre17Compat>;
def ext_inline_variable : ExtWarn<
"inline variables are a C++17 extension">, InGroup<CXX17>;
@@ -1319,8 +1298,8 @@ def ext_unelaborated_friend_type : ExtWarn<
def warn_cxx98_compat_unelaborated_friend_type : Warning<
"befriending %1 without '%select{struct|interface|union|class|enum}0' "
"keyword is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
-def err_qualified_friend_not_found : Error<
- "no function named %0 with type %1 was found in the specified scope">;
+def err_qualified_friend_no_match : Error<
+ "friend declaration of %0 does not match any declaration in %1">;
def err_introducing_special_friend : Error<
"%plural{[0,2]:must use a qualified name when declaring|3:cannot declare}0"
" a %select{constructor|destructor|conversion operator|deduction guide}0 "
@@ -1355,10 +1334,6 @@ def ext_friend_tag_redecl_outside_namespace : ExtWarn<
InGroup<MicrosoftUnqualifiedFriend>;
def err_pure_friend : Error<"friend declaration cannot have a pure-specifier">;
-def err_invalid_member_in_interface : Error<
- "%select{data member |non-public member function |static member function |"
- "user-declared constructor|user-declared destructor|operator |"
- "nested class }0%1 is not permitted within an interface type">;
def err_invalid_base_in_interface : Error<
"interface type cannot inherit from "
"%select{struct|non-public interface|class}0 %1">;
@@ -1464,6 +1439,10 @@ def err_noexcept_needs_constant_expression : Error<
"argument to noexcept specifier must be a constant expression">;
def err_exception_spec_not_parsed : Error<
"exception specification is not available until end of class definition">;
+def err_exception_spec_cycle : Error<
+ "exception specification of %0 uses itself">;
+def err_exception_spec_incomplete_type : Error<
+ "exception specification needed for member of incomplete class %0">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
@@ -1644,7 +1623,7 @@ def err_member_function_call_bad_type : Error<
def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
"call to pure virtual member function %0 has undefined behavior; "
"overrides of %0 in subclasses are not available in the "
- "%select{constructor|destructor}1 of %2">;
+ "%select{constructor|destructor}1 of %2">, InGroup<PureVirtualCallFromCtorDtor>;
def select_special_member_kind : TextSubstitution<
"%select{default constructor|copy constructor|move constructor|"
@@ -1809,6 +1788,10 @@ def err_destructor_expr_type_mismatch : Error<
def note_destructor_type_here : Note<
"type %0 is declared here">;
+def err_destroy_attr_on_non_static_var : Error<
+ "%select{no_destroy|always_destroy}0 attribute can only be applied to a"
+ " variable with static or thread storage duration">;
+
def err_destructor_template : Error<
"destructor cannot be declared as a template">;
@@ -1826,11 +1809,7 @@ def err_init_conversion_failed : Error<
"|: different number of parameters (%5 vs %6)"
"|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7"
"|: different return type%diff{ ($ vs $)|}5,6"
- "|: different qualifiers ("
- "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}5 vs "
- "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}6)"
+ "|: different qualifiers (%5 vs %6)"
"|: different exception specifications}4">;
def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot "
@@ -1858,6 +1837,9 @@ def err_reference_bind_init_list : Error<
def err_init_list_bad_dest_type : Error<
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
"list">;
+def warn_cxx2a_compat_aggregate_init_with_ctors : Warning<
+ "aggregate initialization of type %0 with user-declared constructors "
+ "is incompatible with C++2a">, DefaultIgnore, InGroup<CXX2aCompat>;
def err_reference_bind_to_bitfield : Error<
"%select{non-const|volatile}0 reference cannot bind to "
@@ -2139,8 +2121,12 @@ def note_deduction_guide_template_access : Note<
"member template declared %0 here">;
def note_deduction_guide_access : Note<
"deduction guide declared %0 by intervening access specifier">;
+def warn_cxx14_compat_class_template_argument_deduction : Warning<
+ "class template argument deduction is incompatible with C++ standards "
+ "before C++17%select{|; for compatibility, use explicit type name %1}0">,
+ InGroup<CXXPre17Compat>, DefaultIgnore;
-// C++1y deduced return types
+// C++14 deduced return types
def err_auto_fn_deduction_failure : Error<
"cannot deduce return type %0 from returned value of type %1">;
def err_auto_fn_different_deductions : Error<
@@ -2156,6 +2142,9 @@ def err_auto_fn_return_init_list : Error<
"cannot deduce return type from initializer list">;
def err_auto_fn_virtual : Error<
"function with deduced return type cannot be virtual">;
+def warn_cxx11_compat_deduced_return_type : Warning<
+ "return type deduction is incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
// C++11 override control
def override_keyword_only_allowed_on_virtual_member_functions : Error<
@@ -2235,8 +2224,6 @@ def err_for_range_incomplete_type : Error<
"cannot use incomplete type %0 as a range">;
def err_for_range_iter_deduction_failure : Error<
"cannot use type %0 as an iterator">;
-def err_for_range_member_begin_end_mismatch : Error<
- "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">;
def ext_for_range_begin_end_types_differ : ExtWarn<
"'begin' and 'end' returning different types (%0 and %1) is a C++17 extension">,
InGroup<CXX17>;
@@ -2249,6 +2236,8 @@ def note_in_for_range: Note<
def err_for_range_invalid: Error<
"invalid range expression of type %0; no viable '%select{begin|end}1' "
"function available">;
+def note_for_range_member_begin_end_ignored : Note<
+ "member is not a candidate because range type %0 has no '%select{end|begin}1' member">;
def err_range_on_array_parameter : Error<
"cannot build range expression with array function parameter %0 since "
"parameter with array type %1 is treated as pointer type %2">;
@@ -2275,6 +2264,9 @@ def warn_for_range_copy : Warning<
"loop variable %0 of type %1 creates a copy from type %2">,
InGroup<RangeLoopAnalysis>, DefaultIgnore;
def note_use_reference_type : Note<"use reference type %0 to prevent copying">;
+def err_objc_for_range_init_stmt : Error<
+ "initialization statement is not supported when iterating over Objective-C "
+ "collection">;
// C++11 constexpr
def warn_cxx98_compat_constexpr : Warning<
@@ -2330,6 +2322,13 @@ def warn_cxx11_compat_constexpr_body_invalid_stmt : Warning<
"use of this statement in a constexpr %select{function|constructor}0 "
"is incompatible with C++ standards before C++14">,
InGroup<CXXPre14Compat>, DefaultIgnore;
+def ext_constexpr_body_invalid_stmt_cxx2a : ExtWarn<
+ "use of this statement in a constexpr %select{function|constructor}0 "
+ "is a C++2a extension">, InGroup<CXX2a>;
+def warn_cxx17_compat_constexpr_body_invalid_stmt : Warning<
+ "use of this statement in a constexpr %select{function|constructor}0 "
+ "is incompatible with C++ standards before C++2a">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
def ext_constexpr_type_definition : ExtWarn<
"type definition in a constexpr %select{function|constructor}0 "
"is a C++14 extension">, InGroup<CXX14>;
@@ -2382,6 +2381,16 @@ def note_constexpr_body_previous_return : Note<
"previous return statement is here">;
def err_constexpr_function_try_block : Error<
"function try block not allowed in constexpr %select{function|constructor}0">;
+
+// c++2a function try blocks in constexpr
+def ext_constexpr_function_try_block_cxx2a : ExtWarn<
+ "function try block in constexpr %select{function|constructor}0 is "
+ "a C++2a extension">, InGroup<CXX2a>;
+def warn_cxx17_compat_constexpr_function_try_block : Warning<
+ "function try block in constexpr %select{function|constructor}0 is "
+ "incompatible with C++ standards before C++2a">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
+
def err_constexpr_union_ctor_no_init : Error<
"constexpr union constructor does not initialize any member">;
def err_constexpr_ctor_missing_init : Error<
@@ -2479,7 +2488,8 @@ def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
def err_attribute_bad_neon_vector_size : Error<
"Neon vector size must be 64 or 128 bits">;
def err_attribute_requires_positive_integer : Error<
- "%0 attribute requires a positive integral compile time constant expression">;
+ "%0 attribute requires a %select{positive|non-negative}1 "
+ "integral compile time constant expression">;
def err_attribute_requires_opencl_version : Error<
"%0 attribute requires OpenCL version %1%select{| or above}2">;
def warn_unsupported_target_attribute
@@ -2521,8 +2531,6 @@ def err_attribute_argument_out_of_bounds : Error<
"%0 attribute parameter %1 is out of bounds">;
def err_attribute_only_once_per_parameter : Error<
"%0 attribute can only be applied once per parameter">;
-def err_attribute_uuid_malformed_guid : Error<
- "uuid attribute contains a malformed GUID">;
def err_mismatched_uuid : Error<"uuid does not match previous declaration">;
def note_previous_uuid : Note<"previous uuid specified here">;
def warn_attribute_pointers_only : Warning<
@@ -2599,6 +2607,10 @@ def err_arg_with_address_space : Error<
"parameter may not be qualified with an address space">;
def err_field_with_address_space : Error<
"field may not be qualified with an address space">;
+def err_compound_literal_with_address_space : Error<
+ "compound literal in function scope may not be qualified with an address space">;
+def err_address_space_mismatch_templ_inst : Error<
+ "conflicting address space qualifiers are provided between types %0 and %1">;
def err_attr_objc_ownership_redundant : Error<
"the type %0 is already explicitly ownership-qualified">;
def err_invalid_nsnumber_type : Error<
@@ -2742,8 +2754,6 @@ def warn_nocf_check_attribute_ignored :
def warn_attribute_after_definition_ignored : Warning<
"attribute %0 after definition is ignored">,
InGroup<IgnoredAttributes>;
-def warn_unknown_attribute_ignored : Warning<
- "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
def warn_cxx11_gnu_attribute_on_type : Warning<
"attribute %0 ignored, because it cannot be applied to a type">,
InGroup<IgnoredAttributes>;
@@ -2843,22 +2853,6 @@ def err_attribute_weakref_without_alias : Error<
"weakref declaration of %0 must also have an alias attribute">;
def err_alias_not_supported_on_darwin : Error <
"aliases are not supported on darwin">;
-def err_alias_to_undefined : Error<
- "%select{alias|ifunc}0 must point to a defined %select{variable or |}1function">;
-def warn_alias_to_weak_alias : Warning<
- "%select{alias|ifunc}2 will always resolve to %0 even if weak definition of %1 is overridden">,
- InGroup<IgnoredAttributes>;
-def warn_alias_with_section : Warning<
- "%select{alias|ifunc}1 will not be in section '%0' but in the same section as the %select{aliasee|resolver}2">,
- InGroup<IgnoredAttributes>;
-def err_duplicate_mangled_name : Error<
- "definition with same mangled name '%0' as another definition">;
-def err_cyclic_alias : Error<
- "%select{alias|ifunc}0 definition is part of a cycle">;
-def err_ifunc_resolver_return : Error<
- "ifunc resolver function must return a pointer">;
-def err_ifunc_resolver_params : Error<
- "ifunc resolver function must have no parameters">;
def warn_attribute_wrong_decl_type_str : Warning<
"%0 attribute only applies to %1">, InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type_str : Error<
@@ -2960,6 +2954,9 @@ def warn_availability_on_static_initializer : Warning<
InGroup<Availability>;
def note_overridden_method : Note<
"overridden method is here">;
+def warn_availability_swift_unavailable_deprecated_only : Warning<
+ "only 'unavailable' and 'deprecated' are supported for Swift availability">,
+ InGroup<Availability>;
def note_protocol_method : Note<
"protocol method is here">;
@@ -2986,6 +2983,14 @@ def warn_invalid_capability_name : Warning<
def warn_thread_attribute_ignored : Warning<
"ignoring %0 attribute because its argument is invalid">,
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_not_on_non_static_member : Warning<
+ "%0 attribute without capability arguments can only be applied to non-static "
+ "methods of a class">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_not_on_capability_member : Warning<
+ "%0 attribute without capability arguments refers to 'this', but %1 isn't "
+ "annotated with 'capability' or 'scoped_lockable' attribute">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
def warn_thread_attribute_argument_not_lockable : Warning<
"%0 attribute requires arguments whose type is annotated "
"with 'capability' attribute; type here is %1">,
@@ -3143,10 +3148,10 @@ def err_impcast_complex_scalar : Error<
"implicit conversion from %0 to %1 is not permitted in C++">;
def warn_impcast_float_precision : Warning<
"implicit conversion loses floating-point precision: %0 to %1">,
- InGroup<Conversion>, DefaultIgnore;
+ InGroup<ImplicitFloatConversion>, DefaultIgnore;
def warn_impcast_float_result_precision : Warning<
"implicit conversion when assigning computation result loses floating-point precision: %0 to %1">,
- InGroup<Conversion>, DefaultIgnore;
+ InGroup<ImplicitFloatConversion>, DefaultIgnore;
def warn_impcast_double_promotion : Warning<
"implicit conversion increases floating-point precision: %0 to %1">,
InGroup<DoublePromotion>, DefaultIgnore;
@@ -3158,7 +3163,13 @@ def warn_impcast_integer_sign_conditional : Warning<
InGroup<SignConversion>, DefaultIgnore;
def warn_impcast_integer_precision : Warning<
"implicit conversion loses integer precision: %0 to %1">,
- InGroup<Conversion>, DefaultIgnore;
+ InGroup<ImplicitIntConversion>, DefaultIgnore;
+def warn_impcast_high_order_zero_bits : Warning<
+ "higher order bits are zeroes after implicit conversion">,
+ InGroup<ImplicitIntConversion>, DefaultIgnore;
+def warn_impcast_nonnegative_result : Warning<
+ "the resulting value is always non-negative after implicit conversion">,
+ InGroup<SignConversion>, DefaultIgnore;
def warn_impcast_integer_64_32 : Warning<
"implicit conversion loses integer precision: %0 to %1">,
InGroup<Shorten64To32>, DefaultIgnore;
@@ -3247,6 +3258,10 @@ def warn_address_of_reference_null_compare : Warning<
InGroup<TautologicalUndefinedCompare>;
def note_reference_is_return_value : Note<"%0 returns a reference">;
+def warn_division_sizeof_ptr : Warning<
+ "'%0' will return the size of the pointer, not the array itself">,
+ InGroup<DiagGroup<"sizeof-pointer-div">>;
+
def note_function_warning_silence : Note<
"prefix with the address-of operator to silence this warning">;
def note_function_to_function_call : Note<
@@ -3410,7 +3425,7 @@ def err_ns_attribute_wrong_parameter_type : Error<
"%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">;
def warn_ns_attribute_wrong_parameter_type : Warning<
"%0 attribute only applies to "
- "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">,
+ "%select{Objective-C object|pointer|pointer-to-CF-pointer|pointer/reference-to-OSObject-pointer}1 parameters">,
InGroup<IgnoredAttributes>;
def warn_objc_requires_super_protocol : Warning<
"%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">,
@@ -3470,6 +3485,11 @@ def err_objc_bridged_related_known_method : Error<
def err_objc_attr_protocol_requires_definition : Error<
"attribute %0 can only be applied to @protocol definitions, not forward declarations">;
+def warn_ignored_objc_externally_retained : Warning<
+ "'objc_externally_retained' can only be applied to local variables "
+ "%select{of retainable type|with strong ownership}0">,
+ InGroup<IgnoredAttributes>;
+
// Function Parameter Semantic Analysis.
def err_param_with_void_type : Error<"argument may not have 'void' type">;
def err_void_only_param : Error<
@@ -3574,11 +3594,7 @@ def note_ovl_candidate : Note<
"| has type mismatch at %ordinal5 parameter"
"%diff{ (expected $ but has $)|}6,7"
"| has different return type%diff{ ($ expected but has $)|}5,6"
- "| has different qualifiers (expected "
- "%select{none|const|restrict|const and restrict|volatile|const and volatile"
- "|volatile and restrict|const, volatile, and restrict}5 but found "
- "%select{none|const|restrict|const and restrict|volatile|const and volatile"
- "|volatile and restrict|const, volatile, and restrict}6)"
+ "| has different qualifiers (expected %5 but found %6)"
"| has different exception specification}4">;
def note_ovl_candidate_inherited_constructor : Note<
@@ -3630,7 +3646,7 @@ def warn_diagnose_if_succeeded : Warning<"%0">, InGroup<UserDefinedWarnings>,
def note_ovl_candidate_disabled_by_function_cond_attr : Note<
"candidate disabled: %0">;
def note_ovl_candidate_disabled_by_extension : Note<
- "candidate disabled due to OpenCL extension">;
+ "candidate unavailable as it requires OpenCL extension '%0' to be enabled">;
def err_addrof_function_disabled_by_enable_if_attr : Error<
"cannot take address of function %0 because it has one or more "
"non-tautological enable_if conditions">;
@@ -4255,6 +4271,8 @@ def note_forward_template_decl : Note<
def note_inst_declaration_hint : Note<"add an explicit instantiation "
"declaration to suppress this warning if %q0 is explicitly instantiated in "
"another translation unit">;
+def note_evaluating_exception_spec_here : Note<
+ "in evaluation of exception specification for %q0 needed here">;
def note_default_arg_instantiation_here : Note<
"in instantiation of default argument for '%0' required here">;
@@ -4547,7 +4565,10 @@ def warn_unavailable_fwdclass_message : Warning<
InGroup<UnavailableDeclarations>;
def note_availability_specified_here : Note<
"%0 has been explicitly marked "
- "%select{unavailable|deleted|deprecated|partial}1 here">;
+ "%select{unavailable|deleted|deprecated}1 here">;
+def note_partial_availability_specified_here : Note<
+ "%0 has been marked as being introduced in %1 %2 here, "
+ "but the deployment target is %1 %3">;
def note_implicitly_deleted : Note<
"explicitly defaulted function was implicitly deleted here">;
def warn_not_enough_argument : Warning<
@@ -4750,16 +4771,18 @@ def err_nested_redefinition : Error<"nested redefinition of %0">;
def err_use_with_wrong_tag : Error<
"use of %0 with tag type that does not match previous declaration">;
def warn_struct_class_tag_mismatch : Warning<
- "%select{struct|interface|class}0%select{| template}1 %2 was previously "
- "declared as a %select{struct|interface|class}3%select{| template}1">,
- InGroup<MismatchedTags>, DefaultIgnore;
+ "%select{struct|interface|class}0%select{| template}1 %2 was previously "
+ "declared as a %select{struct|interface|class}3%select{| template}1; "
+ "this is valid, but may result in linker errors under the Microsoft C++ ABI">,
+ InGroup<MismatchedTags>, DefaultIgnore;
def warn_struct_class_previous_tag_mismatch : Warning<
- "%2 defined as %select{a struct|an interface|a class}0%select{| template}1 "
- "here but previously declared as "
- "%select{a struct|an interface|a class}3%select{| template}1">,
- InGroup<MismatchedTags>, DefaultIgnore;
+ "%2 defined as %select{a struct|an interface|a class}0%select{| template}1 "
+ "here but previously declared as "
+ "%select{a struct|an interface|a class}3%select{| template}1; "
+ "this is valid, but may result in linker errors under the Microsoft C++ ABI">,
+ InGroup<MismatchedTags>, DefaultIgnore;
def note_struct_class_suggestion : Note<
- "did you mean %select{struct|interface|class}0 here?">;
+ "did you mean %select{struct|interface|class}0 here?">;
def ext_forward_ref_enum : Extension<
"ISO C forbids forward references to 'enum' types">;
def err_forward_ref_enum : Error<
@@ -4804,21 +4827,6 @@ def err_vm_func_decl : Error<
def err_array_too_large : Error<
"array is too large (%0 elements)">;
-// -Wpadded, -Wpacked
-def warn_padded_struct_field : Warning<
- "padding %select{struct|interface|class}0 %1 with %2 "
- "%select{byte|bit}3%s2 to align %4">,
- InGroup<Padded>, DefaultIgnore;
-def warn_padded_struct_anon_field : Warning<
- "padding %select{struct|interface|class}0 %1 with %2 "
- "%select{byte|bit}3%s2 to align anonymous bit-field">,
- InGroup<Padded>, DefaultIgnore;
-def warn_padded_struct_size : Warning<
- "padding size of %0 with %1 %select{byte|bit}2%s1 to alignment boundary">,
- InGroup<Padded>, DefaultIgnore;
-def warn_unnecessary_packed : Warning<
- "packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
-
def err_typecheck_negative_array_size : Error<"array size is negative">;
def warn_typecheck_function_qualifiers_ignored : Warning<
"'%0' qualifier on function type %1 has no effect">,
@@ -4873,7 +4881,7 @@ def warn_braces_around_scalar_init : Warning<
"braces around scalar initializer">, InGroup<DiagGroup<"braced-scalar-init">>;
def ext_many_braces_around_scalar_init : ExtWarn<
"too many braces around scalar initializer">,
- InGroup<DiagGroup<"many-braces-around-scalar-init">>;
+ InGroup<DiagGroup<"many-braces-around-scalar-init">>, SFINAEFailure;
def ext_complex_component_init : Extension<
"complex initialization specifying real and imaginary components "
"is an extension">, InGroup<DiagGroup<"complex-component-init">>;
@@ -5254,6 +5262,9 @@ def err_typecheck_arc_assign_self_class_method : Error<
def err_typecheck_arr_assign_enumeration : Error<
"fast enumeration variables cannot be modified in ARC by default; "
"declare the variable __strong to allow this">;
+def err_typecheck_arc_assign_externally_retained : Error<
+ "variable declared with 'objc_externally_retained' "
+ "cannot be modified in ARC">;
def warn_arc_retained_assign : Warning<
"assigning retained object to %select{weak|unsafe_unretained}0 "
"%select{property|variable}1"
@@ -5428,20 +5439,24 @@ def err_atomic_specifier_bad_type : Error<
"%1 %select{||||||which is not trivially copyable}0">;
// Expressions.
+def select_unary_expr_or_type_trait_kind : TextSubstitution<
+ "%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align|"
+ "__alignof}0">;
def ext_sizeof_alignof_function_type : Extension<
- "invalid application of '%select{sizeof|alignof|vec_step}0' to a "
- "function type">, InGroup<PointerArith>;
+ "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+ "to a function type">, InGroup<PointerArith>;
def ext_sizeof_alignof_void_type : Extension<
- "invalid application of '%select{sizeof|alignof|vec_step}0' to a void "
- "type">, InGroup<PointerArith>;
+ "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+ "to a void type">, InGroup<PointerArith>;
def err_opencl_sizeof_alignof_type : Error<
- "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a void type">;
+ "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+ "to a void type">;
def err_sizeof_alignof_incomplete_type : Error<
- "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to an "
- "incomplete type %1">;
+ "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+ "to an incomplete type %1">;
def err_sizeof_alignof_function_type : Error<
- "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a "
- "function type">;
+ "invalid application of '%sub{select_unary_expr_or_type_trait_kind}0' "
+ "to a function type">;
def err_openmp_default_simd_align_expr : Error<
"invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed">;
def err_sizeof_alignof_typeof_bitfield : Error<
@@ -5749,8 +5764,14 @@ def err_array_init_plain_string_into_char8_t : Error<
def note_array_init_plain_string_into_char8_t : Note<
"add 'u8' prefix to form a 'char8_t' string literal">;
def err_array_init_utf8_string_into_char : Error<
- "initialization of char array with UTF-8 string literal is not permitted "
- "by '-fchar8_t'">;
+ "%select{|ISO C++20 does not permit }0initialization of char array with "
+ "UTF-8 string literal%select{ is not permitted by '-fchar8_t'|}0">;
+def warn_cxx2a_compat_utf8_string : Warning<
+ "type of UTF-8 string literal will change from array of const char to "
+ "array of const char8_t in C++2a">, InGroup<CXX2aCompat>, DefaultIgnore;
+def note_cxx2a_compat_utf8_string_remove_u8 : Note<
+ "remove 'u8' prefix to avoid a change of behavior; "
+ "Clang encodes unprefixed narrow string literals as UTF-8">;
def err_array_init_different_type : Error<
"cannot initialize array %diff{of type $ with array of type $|"
"with different type of array}0,1">;
@@ -5857,7 +5878,8 @@ def ext_typecheck_comparison_of_fptr_to_void : Extension<
def err_typecheck_comparison_of_fptr_to_void : Error<
"equality comparison between function pointer and void pointer (%0 and %1)">;
def ext_typecheck_comparison_of_pointer_integer : ExtWarn<
- "comparison between pointer and integer (%0 and %1)">;
+ "comparison between pointer and integer (%0 and %1)">,
+ InGroup<DiagGroup<"pointer-integer-compare">>;
def err_typecheck_comparison_of_pointer_integer : Error<
"comparison between pointer and integer (%0 and %1)">;
def ext_typecheck_comparison_of_distinct_pointers : ExtWarn<
@@ -6437,12 +6459,12 @@ def warn_non_virtual_dtor : Warning<
def warn_delete_non_virtual_dtor : Warning<
"%select{delete|destructor}0 called on non-final %1 that has "
"virtual functions but non-virtual destructor">,
- InGroup<DeleteNonVirtualDtor>, DefaultIgnore, ShowInSystemHeader;
+ InGroup<DeleteNonAbstractNonVirtualDtor>, DefaultIgnore, ShowInSystemHeader;
def note_delete_non_virtual : Note<
"qualify call to silence this warning">;
def warn_delete_abstract_non_virtual_dtor : Warning<
"%select{delete|destructor}0 called on %1 that is abstract but has "
- "non-virtual destructor">, InGroup<DeleteNonVirtualDtor>, ShowInSystemHeader;
+ "non-virtual destructor">, InGroup<DeleteAbstractNonVirtualDtor>, ShowInSystemHeader;
def warn_overloaded_virtual : Warning<
"%q0 hides overloaded virtual %select{function|functions}1">,
InGroup<OverloadedVirtual>, DefaultIgnore;
@@ -6452,11 +6474,7 @@ def note_hidden_overloaded_virtual_declared_here : Note<
"|: different number of parameters (%2 vs %3)"
"|: type mismatch at %ordinal2 parameter%diff{ ($ vs $)|}3,4"
"|: different return type%diff{ ($ vs $)|}2,3"
- "|: different qualifiers ("
- "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}2 vs "
- "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}3)"
+ "|: different qualifiers (%2 vs %3)"
"|: different exception specifications}1">;
def warn_using_directive_in_header : Warning<
"using namespace directive in global context in header">,
@@ -6465,12 +6483,12 @@ def warn_overaligned_type : Warning<
"type %0 requires %1 bytes of alignment and the default allocator only "
"guarantees %2 bytes">,
InGroup<OveralignedType>, DefaultIgnore;
-def warn_aligned_allocation_unavailable :Warning<
+def err_aligned_allocation_unavailable : Error<
"aligned %select{allocation|deallocation}0 function of type '%1' is only "
- "available on %2 %3 or newer">, InGroup<AlignedAllocationUnavailable>, DefaultError;
-def note_silence_unligned_allocation_unavailable : Note<
+ "available on %2 %3 or newer">;
+def note_silence_aligned_allocation_unavailable : Note<
"if you supply your own aligned allocation functions, use "
- "-Wno-aligned-allocation-unavailable to silence this diagnostic">;
+ "-faligned-allocation to silence this diagnostic">;
def err_conditional_void_nonvoid : Error<
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
@@ -6572,6 +6590,11 @@ let CategoryName = "Lambda Issue" in {
def err_init_capture_deduction_failure_from_init_list : Error<
"cannot deduce type for lambda capture %0 from initializer list">;
+ // C++14 generic lambdas.
+ def warn_cxx11_compat_generic_lambda : Warning<
+ "generic lambdas are incompatible with C++11">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
+
// C++17 '*this' captures.
def warn_cxx14_compat_star_this_lambda_capture : Warning<
"by value capture of '*this' is incompatible with C++ standards before C++17">,
@@ -6579,6 +6602,10 @@ let CategoryName = "Lambda Issue" in {
def ext_star_this_lambda_capture_cxx17 : ExtWarn<
"capture of '*this' by copy is a C++17 extension">, InGroup<CXX17>;
+ // C++17 parameter shadows capture
+ def err_parameter_shadow_capture : Error<
+ "a lambda parameter cannot shadow an explicitly captured entity">;
+
// C++2a [=, this] captures.
def warn_cxx17_compat_equals_this_lambda_capture : Warning<
"explicit capture of 'this' with a capture default of '=' is incompatible "
@@ -6591,6 +6618,11 @@ let CategoryName = "Lambda Issue" in {
InGroup<DeprecatedThisCapture>, DefaultIgnore;
def note_deprecated_this_capture : Note<
"add an explicit capture of 'this' to capture '*this' by reference">;
+
+ // C++2a default constructible / assignable lambdas.
+ def warn_cxx17_compat_lambda_def_ctor_assign : Warning<
+ "%select{default construction|assignment}0 of lambda is incompatible with "
+ "C++ standards before C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore;
}
def err_return_in_captured_stmt : Error<
@@ -6716,11 +6748,7 @@ def err_typecheck_convert_incompatible : Error<
"|: different number of parameters (%5 vs %6)"
"|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7"
"|: different return type%diff{ ($ vs $)|}5,6"
- "|: different qualifiers ("
- "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}5 vs "
- "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}6)"
+ "|: different qualifiers (%5 vs %6)"
"|: different exception specifications}4">;
def err_typecheck_missing_return_type_incompatible : Error<
"%diff{return type $ must match previous return type $|"
@@ -7063,9 +7091,9 @@ def warn_atomic_op_has_invalid_memory_order : Warning<
InGroup<DiagGroup<"atomic-memory-ordering">>;
def err_atomic_op_has_invalid_synch_scope : Error<
"synchronization scope argument to atomic operation is invalid">;
-def warn_atomic_op_misaligned : Warning<
- "misaligned or large atomic operation may incur significant performance penalty">,
- InGroup<DiagGroup<"atomic-alignment">>;
+def warn_atomic_implicit_seq_cst : Warning<
+ "implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary">,
+ InGroup<DiagGroup<"atomic-implicit-seq-cst">>, DefaultIgnore;
def err_overflow_builtin_must_be_int : Error<
"operand argument to overflow builtin must be an integer (%0 invalid)">;
@@ -7326,8 +7354,6 @@ let CategoryName = "Inline Assembly Issue" in {
"invalid input constraint '%0' in asm">;
def err_asm_immediate_expected : Error<"constraint '%0' expects "
"an integer constant expression">;
- def err_asm_invalid_type_in_input : Error<
- "invalid type %0 in asm input for constraint '%1'">;
def err_asm_tying_incompatible_types : Error<
"unsupported inline asm: input with type "
"%diff{$ matching output with type $|}0,1">;
@@ -7451,8 +7477,6 @@ def note_in_class_initializer_not_yet_parsed : Note<
"default member initializer declared here">;
def err_in_class_initializer_cycle
: Error<"default member initializer for %0 uses itself">;
-def err_exception_spec_cycle
- : Error<"exception specification of %0 uses itself">;
def ext_in_class_initializer_non_constant : Extension<
"in-class initializer for static data member is not a constant expression; "
@@ -7712,9 +7736,19 @@ def err_incorrect_defaulted_exception_spec : Error<
def err_incorrect_defaulted_constexpr : Error<
"defaulted definition of %sub{select_special_member_kind}0 "
"is not constexpr">;
+def warn_defaulted_method_deleted : Warning<
+ "explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
+ "deleted">, InGroup<DiagGroup<"defaulted-function-deleted">>;
def err_out_of_line_default_deletes : Error<
"defaulting this %sub{select_special_member_kind}0 "
"would delete it after its first declaration">;
+def note_deleted_type_mismatch : Note<
+ "function is implicitly deleted because its declared type does not match "
+ "the type of an implicit %sub{select_special_member_kind}0">;
+def warn_cxx17_compat_defaulted_method_type_mismatch : Warning<
+ "explicitly defaulting this %sub{select_special_member_kind}0 with a type "
+ "different from the implicit type is incompatible with C++ standards before "
+ "C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore;
def warn_vbase_moved_multiple_times : Warning<
"defaulted move assignment operator of %0 will move assign virtual base "
"class %1 multiple times">, InGroup<DiagGroup<"multiple-move-vbase">>;
@@ -7820,6 +7854,8 @@ def warn_format_non_standard: Warning<
def warn_format_non_standard_conversion_spec: Warning<
"using length modifier '%0' with conversion specifier '%1' is not supported by ISO C">,
InGroup<FormatNonStandard>, DefaultIgnore;
+def err_invalid_mask_type_size : Error<
+ "mask type size must be between 1-byte and 8-bytes">;
def warn_format_invalid_annotation : Warning<
"using '%0' format specifier annotation outside of os_log()/os_trace()">,
InGroup<Format>;
@@ -8518,6 +8554,8 @@ def err_opencl_scalar_type_rank_greater_than_vector_type : Error<
"element. (%0 and %1)">;
def err_bad_kernel_param_type : Error<
"%0 cannot be used as the type of a kernel parameter">;
+def err_opencl_implicit_function_decl : Error<
+ "implicit declaration of function %0 is invalid in OpenCL">;
def err_record_with_pointers_kernel_param : Error<
"%select{struct|union}0 kernel parameters may not contain pointers">;
def note_within_field_of_type : Note<
@@ -8575,6 +8613,10 @@ def err_opencl_variadic_function : Error<
"invalid prototype, variadic arguments are not allowed in OpenCL">;
def err_opencl_requires_extension : Error<
"use of %select{type|declaration}0 %1 requires %2 extension to be enabled">;
+def warn_opencl_generic_address_space_arg : Warning<
+ "passing non-generic address space pointer to %0"
+ " may cause dynamic conversion affecting performance">,
+ InGroup<Conversion>, DefaultIgnore;
// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
def err_opencl_builtin_pipe_first_arg : Error<
@@ -8596,11 +8638,6 @@ def err_opencl_multiple_access_qualifiers : Error<
def note_opencl_typedef_access_qualifier : Note<
"previously declared '%0' here">;
-// OpenCL Section 6.8.g
-def err_opencl_unknown_type_specifier : Error<
- "OpenCL %select{C|C++}0 version %1 does not support the '%2' "
- "%select{type qualifier|storage class specifier}3">;
-
// OpenCL v2.0 s6.12.5 Blocks restrictions
def err_opencl_block_storage_type : Error<
"the __block storage type is not permitted">;
@@ -8685,6 +8722,8 @@ def err_omp_expected_access_to_data_field : Error<
"expected access to data field">;
def err_omp_multiple_array_items_in_map_clause : Error<
"multiple array elements associated with the same variable are not allowed in map clauses of the same construct">;
+def err_omp_duplicate_map_type_modifier : Error<
+ "same map type modifier has been specified more than once">;
def err_omp_pointer_mapped_along_with_derived_section : Error<
"pointer cannot be mapped along with a section derived from itself">;
def err_omp_original_storage_is_shared_and_does_not_contain : Error<
@@ -8743,8 +8782,10 @@ def err_omp_required_access : Error<
"%0 variable must be %1">;
def err_omp_const_variable : Error<
"const-qualified variable cannot be %0">;
-def err_omp_const_reduction_list_item : Error<
- "const-qualified list item cannot be reduction">;
+def err_omp_const_not_mutable_variable : Error<
+ "const-qualified variable without mutable fields cannot be %0">;
+def err_omp_const_list_item : Error<
+ "const-qualified list item cannot be %0">;
def err_omp_linear_incomplete_type : Error<
"a linear variable with incomplete type %0">;
def err_omp_linear_expected_int_or_ptr : Error<
@@ -8756,8 +8797,6 @@ def warn_omp_linear_step_zero : Warning<
def warn_omp_alignment_not_power_of_two : Warning<
"aligned clause will be ignored because the requested alignment is not a power of 2">,
InGroup<OpenMPClauses>;
-def err_omp_enclosed_declare_target : Error<
- "declare target region may not be enclosed within another declare target region">;
def err_omp_invalid_target_decl : Error<
"%0 used in declare target directive is not a variable or a function name">;
def err_omp_declare_target_multiple : Error<
@@ -9029,6 +9068,20 @@ def err_omp_linear_distribute_var_non_loop_iteration : Error<
def warn_omp_non_trivial_type_mapped : Warning<
"Non-trivial type %0 is mapped, only trivial types are guaranteed to be mapped correctly">,
InGroup<OpenMPTarget>;
+def err_omp_requires_clause_redeclaration : Error <
+ "Only one %0 clause can appear on a requires directive in a single translation unit">;
+def note_omp_requires_previous_clause : Note <
+ "%0 clause previously used here">;
+def err_omp_invalid_scope : Error <
+ "'#pragma omp %0' directive must appear only in file scope">;
+def note_omp_invalid_length_on_this_ptr_mapping : Note <
+ "expected length on mapping of 'this' array section expression to be '1'">;
+def note_omp_invalid_lower_bound_on_this_ptr_mapping : Note <
+ "expected lower bound on mapping of 'this' array section expression to be '0' or not specified">;
+def note_omp_invalid_subscript_on_this_ptr_map : Note <
+ "expected 'this' subscript expression on map clause to be 'this[0]'">;
+def err_omp_invalid_map_this_expr : Error <
+ "invalid 'this' expression on 'map' clause">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
@@ -9061,6 +9114,8 @@ def err_invalid_type_for_program_scope_var : Error<
let CategoryName = "Modules Issue" in {
def err_module_decl_in_module_map_module : Error<
"'module' declaration found while building module from module map">;
+def err_module_decl_in_header_module : Error<
+ "'module' declaration found while building header module">;
def err_module_interface_implementation_mismatch : Error<
"missing 'export' specifier in module declaration while "
"building module interface">;
@@ -9209,22 +9264,6 @@ def warn_not_a_doxygen_trailing_member_comment : Warning<
"not a Doxygen trailing comment">, InGroup<Documentation>, DefaultIgnore;
} // end of documentation issue category
-let CategoryName = "Instrumentation Issue" in {
-def warn_profile_data_out_of_date : Warning<
- "profile data may be out of date: of %0 function%s0, %1 %plural{1:has|:have}1"
- " mismatched data that will be ignored">,
- InGroup<ProfileInstrOutOfDate>;
-def warn_profile_data_missing : Warning<
- "profile data may be incomplete: of %0 function%s0, %1 %plural{1:has|:have}1"
- " no data">,
- InGroup<ProfileInstrMissing>,
- DefaultIgnore;
-def warn_profile_data_unprofiled : Warning<
- "no profile data available for file \"%0\"">,
- InGroup<ProfileInstrUnprofiled>;
-
-} // end of instrumentation issue category
-
let CategoryName = "Nullability Issue" in {
def warn_mismatched_nullability_attr : Warning<
@@ -9372,14 +9411,9 @@ def warn_block_literal_qualifiers_on_omitted_return_type : Warning<
"'%0' qualifier on omitted return type %1 has no effect">,
InGroup<IgnoredQualifiers>;
-def ext_warn_gnu_final : ExtWarn<
- "__final is a GNU extension, consider using C++11 final">,
- InGroup<GccCompat>;
-
-def warn_shadow_field :
- Warning<"non-static data member %0 of %1 shadows member inherited from "
- "type %2">,
- InGroup<ShadowField>, DefaultIgnore;
+def warn_shadow_field : Warning<
+ "%select{parameter|non-static data member}3 %0 %select{|of %1 }3shadows "
+ "member inherited from type %2">, InGroup<ShadowField>, DefaultIgnore;
def note_shadow_field : Note<"declared here">;
def err_multiversion_required_in_redecl : Error<
@@ -9440,4 +9474,18 @@ def err_std_compare_type_not_supported : Error<
"member '%2' is missing|"
"the type is not trivially copyable|"
"the type does not have the expected form}1">;
+
+def warn_dereference_of_noderef_type : Warning<
+ "dereferencing %0; was declared with a 'noderef' type">, InGroup<NoDeref>;
+def warn_dereference_of_noderef_type_no_decl : Warning<
+ "dereferencing expression marked as 'noderef'">, InGroup<NoDeref>;
+def warn_noderef_on_non_pointer_or_array : Warning<
+ "'noderef' can only be used on an array or pointer type">, InGroup<IgnoredAttributes>;
+def warn_noderef_to_dereferenceable_pointer : Warning<
+ "casting to dereferenceable pointer removes 'noderef' attribute">, InGroup<NoDeref>;
+
+def err_builtin_launder_invalid_arg : Error<
+ "%select{non-pointer|function pointer|void pointer}0 argument to "
+ "'__builtin_launder' is not allowed">;
+
} // end of sema component.
diff --git a/include/clang/Basic/DiagnosticSerialization.h b/include/clang/Basic/DiagnosticSerialization.h
new file mode 100644
index 000000000000..d19e638dcf13
--- /dev/null
+++ b/include/clang/Basic/DiagnosticSerialization.h
@@ -0,0 +1,29 @@
+//===--- DiagnosticSerialization.h - Serialization Diagnostics -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICSERIALIZATION_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICSERIALIZATION_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define SERIALIZATIONSTART
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_SERIALIZATION_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_DIAGNOSTICSERIALIZATION_H
diff --git a/include/clang/Basic/Features.def b/include/clang/Basic/Features.def
index a0e0ce4560ab..05464ed85f13 100644
--- a/include/clang/Basic/Features.def
+++ b/include/clang/Basic/Features.def
@@ -17,6 +17,12 @@
//
// The Predicate field dictates the conditions under which the feature or
// extension will be made available.
+//
+// FEATURE(...) should be used to advertise support for standard language
+// features, whereas EXTENSION(...) should be used for clang extensions. Note
+// that many of the identifiers in this file don't follow this rule for backward
+// compatibility reasons.
+//
//===----------------------------------------------------------------------===//
#if !defined(FEATURE) && !defined(EXTENSION)
@@ -37,6 +43,9 @@ FEATURE(address_sanitizer,
FEATURE(hwaddress_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress |
SanitizerKind::KernelHWAddress))
+FEATURE(xray_instrument, LangOpts.XRayInstrument)
+FEATURE(undefined_behavior_sanitizer,
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::Undefined))
FEATURE(assume_nonnull, true)
FEATURE(attribute_analyzer_noreturn, true)
FEATURE(attribute_availability, true)
@@ -48,6 +57,7 @@ FEATURE(attribute_availability_watchos, true)
FEATURE(attribute_availability_with_strict, true)
FEATURE(attribute_availability_with_replacement, true)
FEATURE(attribute_availability_in_templates, true)
+FEATURE(attribute_availability_swift, true)
FEATURE(attribute_cf_returns_not_retained, true)
FEATURE(attribute_cf_returns_retained, true)
FEATURE(attribute_cf_returns_on_parameters, true)
@@ -72,7 +82,9 @@ FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData)
FEATURE(enumerator_attributes, true)
FEATURE(nullability, true)
FEATURE(nullability_on_arrays, true)
-FEATURE(memory_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Memory))
+FEATURE(memory_sanitizer,
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
+ SanitizerKind::KernelMemory))
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
FEATURE(efficiency_sanitizer,
@@ -83,11 +95,11 @@ FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
FEATURE(objc_arc, LangOpts.ObjCAutoRefCount)
FEATURE(objc_arc_fields, true)
FEATURE(objc_arc_weak, LangOpts.ObjCWeak)
-FEATURE(objc_default_synthesize_properties, LangOpts.ObjC2)
-FEATURE(objc_fixed_enum, LangOpts.ObjC2)
-FEATURE(objc_instancetype, LangOpts.ObjC2)
-FEATURE(objc_kindof, LangOpts.ObjC2)
-FEATURE(objc_modules, LangOpts.ObjC2 &&LangOpts.Modules)
+FEATURE(objc_default_synthesize_properties, LangOpts.ObjC)
+FEATURE(objc_fixed_enum, true)
+FEATURE(objc_instancetype, LangOpts.ObjC)
+FEATURE(objc_kindof, LangOpts.ObjC)
+FEATURE(objc_modules, LangOpts.ObjC && LangOpts.Modules)
FEATURE(objc_nonfragile_abi, LangOpts.ObjCRuntime.isNonFragile())
FEATURE(objc_property_explicit_atomic, true)
FEATURE(objc_protocol_qualifier_mangling, true)
@@ -97,16 +109,16 @@ FEATURE(ownership_returns, true)
FEATURE(ownership_takes, true)
FEATURE(objc_bool, true)
FEATURE(objc_subscripting, LangOpts.ObjCRuntime.isNonFragile())
-FEATURE(objc_array_literals, LangOpts.ObjC2)
-FEATURE(objc_dictionary_literals, LangOpts.ObjC2)
-FEATURE(objc_boxed_expressions, LangOpts.ObjC2)
-FEATURE(objc_boxed_nsvalue_expressions, LangOpts.ObjC2)
+FEATURE(objc_array_literals, LangOpts.ObjC)
+FEATURE(objc_dictionary_literals, LangOpts.ObjC)
+FEATURE(objc_boxed_expressions, LangOpts.ObjC)
+FEATURE(objc_boxed_nsvalue_expressions, LangOpts.ObjC)
FEATURE(arc_cf_code_audited, true)
FEATURE(objc_bridge_id, true)
FEATURE(objc_bridge_id_on_typedefs, true)
-FEATURE(objc_generics, LangOpts.ObjC2)
-FEATURE(objc_generics_variance, LangOpts.ObjC2)
-FEATURE(objc_class_property, LangOpts.ObjC2)
+FEATURE(objc_generics, LangOpts.ObjC)
+FEATURE(objc_generics_variance, LangOpts.ObjC)
+FEATURE(objc_class_property, LangOpts.ObjC)
// C11 features
FEATURE(c_alignas, LangOpts.C11)
FEATURE(c_alignof, LangOpts.C11)
@@ -227,12 +239,14 @@ EXTENSION(cxx_range_for, LangOpts.CPlusPlus)
EXTENSION(cxx_reference_qualified_functions, LangOpts.CPlusPlus)
EXTENSION(cxx_rvalue_references, LangOpts.CPlusPlus)
EXTENSION(cxx_variadic_templates, LangOpts.CPlusPlus)
+EXTENSION(cxx_fixed_enum, true)
// C++14 features supported by other languages as extensions.
EXTENSION(cxx_binary_literals, true)
EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11)
EXTENSION(cxx_variable_templates, LangOpts.CPlusPlus)
// Miscellaneous language extensions
EXTENSION(overloadable_unmarked, true)
+EXTENSION(pragma_clang_attribute_namespaces, true)
#undef EXTENSION
#undef FEATURE
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index ab5dfca71639..e7891baf5304 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -16,7 +16,7 @@
#define LLVM_CLANG_BASIC_FILEMANAGER_H
#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -25,9 +25,10 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <ctime>
-#include <memory>
#include <map>
+#include <memory>
#include <string>
namespace llvm {
@@ -69,14 +70,15 @@ class FileEntry {
bool IsNamedPipe;
bool InPCH;
bool IsValid; // Is this \c FileEntry initialized and valid?
+ bool DeferredOpen; // Created by getFile(OpenFile=0); may open later.
/// The open file, if it is owned by the \p FileEntry.
- mutable std::unique_ptr<vfs::File> File;
+ mutable std::unique_ptr<llvm::vfs::File> File;
public:
FileEntry()
- : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
- {}
+ : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false),
+ DeferredOpen(false) {}
FileEntry(const FileEntry &) = delete;
FileEntry &operator=(const FileEntry &) = delete;
@@ -102,6 +104,10 @@ public:
void closeFile() const {
File.reset(); // rely on destructor to close File
}
+
+ // Only for use in tests to see if deferred opens are happening, rather than
+ // relying on RealPathName being empty.
+ bool isOpenForTests() const { return File != nullptr; }
};
struct FileData;
@@ -114,7 +120,7 @@ struct FileData;
/// as a single file.
///
class FileManager : public RefCountedBase<FileManager> {
- IntrusiveRefCntPtr<vfs::FileSystem> FS;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
FileSystemOptions FileSystemOpts;
/// Cache for existing real directories.
@@ -165,15 +171,18 @@ class FileManager : public RefCountedBase<FileManager> {
std::unique_ptr<FileSystemStatCache> StatCache;
bool getStatValue(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F);
+ std::unique_ptr<llvm::vfs::File> *F);
/// Add all ancestors of the given path (pointing to either a file
/// or a directory) as virtual directories.
void addAncestorsAsVirtualDirs(StringRef Path);
+ /// Fills the RealPathName in file entry.
+ void fillRealPathName(FileEntry *UFE, llvm::StringRef FileName);
+
public:
FileManager(const FileSystemOptions &FileSystemOpts,
- IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
~FileManager();
/// Installs the provided FileSystemStatCache object within
@@ -183,18 +192,10 @@ public:
///
/// \param statCache the new stat cache to install. Ownership of this
/// object is transferred to the FileManager.
- ///
- /// \param AtBeginning whether this new stat cache must be installed at the
- /// beginning of the chain of stat caches. Otherwise, it will be added to
- /// the end of the chain.
- void addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
- bool AtBeginning = false);
-
- /// Removes the specified FileSystemStatCache object from the manager.
- void removeStatCache(FileSystemStatCache *statCache);
+ void setStatCache(std::unique_ptr<FileSystemStatCache> statCache);
- /// Removes all FileSystemStatCache objects from the manager.
- void clearStatCaches();
+ /// Removes the FileSystemStatCache object from the manager.
+ void clearStatCache();
/// Lookup, cache, and verify the specified directory (real or
/// virtual).
@@ -222,7 +223,7 @@ public:
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
- IntrusiveRefCntPtr<vfs::FileSystem> getVirtualFileSystem() const {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystem() const {
return FS;
}
@@ -247,8 +248,7 @@ public:
/// FileManager's FileSystemOptions.
///
/// \returns false on success, true on error.
- bool getNoncachedStatValue(StringRef Path,
- vfs::Status &Result);
+ bool getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result);
/// Remove the real file \p Entry from the cache.
void invalidateCache(const FileEntry *Entry);
diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
index 1ec344623a0d..f93170c754d5 100644
--- a/include/clang/Basic/FileSystemStatCache.h
+++ b/include/clang/Basic/FileSystemStatCache.h
@@ -26,7 +26,7 @@
#include <string>
#include <utility>
-namespace clang {
+namespace llvm {
namespace vfs {
@@ -34,6 +34,9 @@ class File;
class FileSystem;
} // namespace vfs
+} // namespace llvm
+
+namespace clang {
// FIXME: should probably replace this with vfs::Status
struct FileData {
@@ -57,9 +60,6 @@ struct FileData {
class FileSystemStatCache {
virtual void anchor();
-protected:
- std::unique_ptr<FileSystemStatCache> NextStatCache;
-
public:
virtual ~FileSystemStatCache() = default;
@@ -82,42 +82,16 @@ public:
/// implementation can optionally fill in \p F with a valid \p File object and
/// the client guarantees that it will close it.
static bool get(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F, FileSystemStatCache *Cache,
- vfs::FileSystem &FS);
-
- /// Sets the next stat call cache in the chain of stat caches.
- /// Takes ownership of the given stat cache.
- void setNextStatCache(std::unique_ptr<FileSystemStatCache> Cache) {
- NextStatCache = std::move(Cache);
- }
-
- /// Retrieve the next stat call cache in the chain.
- FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); }
-
- /// Retrieve the next stat call cache in the chain, transferring
- /// ownership of this cache (and, transitively, all of the remaining caches)
- /// to the caller.
- std::unique_ptr<FileSystemStatCache> takeNextStatCache() {
- return std::move(NextStatCache);
- }
+ std::unique_ptr<llvm::vfs::File> *F,
+ FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS);
protected:
// FIXME: The pointer here is a non-owning/optional reference to the
// unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but
// Optional needs some work to support references so this isn't possible yet.
virtual LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F,
- vfs::FileSystem &FS) = 0;
-
- LookupResult statChained(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
- if (FileSystemStatCache *Next = getNextStatCache())
- return Next->getStat(Path, Data, isFile, F, FS);
-
- // If we hit the end of the list of stat caches to try, just compute and
- // return it without a cache.
- return get(Path, Data, isFile, F, nullptr, FS) ? CacheMissing : CacheExists;
- }
+ std::unique_ptr<llvm::vfs::File> *F,
+ llvm::vfs::FileSystem &FS) = 0;
};
/// A stat "cache" that can be used by FileManager to keep
@@ -135,8 +109,8 @@ public:
iterator end() const { return StatCalls.end(); }
LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F,
- vfs::FileSystem &FS) override;
+ std::unique_ptr<llvm::vfs::File> *F,
+ llvm::vfs::FileSystem &FS) override;
};
} // namespace clang
diff --git a/include/clang/Basic/FixedPoint.h b/include/clang/Basic/FixedPoint.h
new file mode 100644
index 000000000000..9a9b7cc9c1fb
--- /dev/null
+++ b/include/clang/Basic/FixedPoint.h
@@ -0,0 +1,138 @@
+//===- FixedPoint.h - Fixed point constant handling -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Defines the fixed point number interface.
+/// This is a class for abstracting various operations performed on fixed point
+/// types described in ISO/IEC JTC1 SC22 WG14 N1169 starting at clause 4.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_FIXEDPOINT_H
+#define LLVM_CLANG_BASIC_FIXEDPOINT_H
+
+#include "llvm/ADT/APSInt.h"
+
+namespace clang {
+
+class ASTContext;
+class QualType;
+
+/// The fixed point semantics work similarly to llvm::fltSemantics. The width
+/// specifies the whole bit width of the underlying scaled integer (with padding
+/// if any). The scale represents the number of fractional bits in this type.
+/// When HasUnsignedPadding is true and this type is signed, the first bit
+/// in the value this represents is treaded as padding.
+class FixedPointSemantics {
+public:
+ FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned,
+ bool IsSaturated, bool HasUnsignedPadding)
+ : Width(Width), Scale(Scale), IsSigned(IsSigned),
+ IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) {
+ assert(Width >= Scale && "Not enough room for the scale");
+ }
+
+ unsigned getWidth() const { return Width; }
+ unsigned getScale() const { return Scale; }
+ bool isSigned() const { return IsSigned; }
+ bool isSaturated() const { return IsSaturated; }
+ bool hasUnsignedPadding() const { return HasUnsignedPadding; }
+
+ void setSaturated(bool Saturated) { IsSaturated = Saturated; }
+
+ unsigned getIntegralBits() const {
+ if (IsSigned || (!IsSigned && HasUnsignedPadding))
+ return Width - Scale - 1;
+ else
+ return Width - Scale;
+ }
+
+private:
+ unsigned Width;
+ unsigned Scale;
+ bool IsSigned;
+ bool IsSaturated;
+ bool HasUnsignedPadding;
+};
+
+/// The APFixedPoint class works similarly to APInt/APSInt in that it is a
+/// functional replacement for a scaled integer. It is meant to replicate the
+/// fixed point types proposed in ISO/IEC JTC1 SC22 WG14 N1169. The class carries
+/// info about the fixed point type's width, sign, scale, and saturation, and
+/// provides different operations that would normally be performed on fixed point
+/// types.
+///
+/// Semantically this does not represent any existing C type other than fixed
+/// point types and should eventually be moved to LLVM if fixed point types gain
+/// native IR support.
+class APFixedPoint {
+ public:
+ APFixedPoint(const llvm::APInt &Val, const FixedPointSemantics &Sema)
+ : Val(Val, !Sema.isSigned()), Sema(Sema) {
+ assert(Val.getBitWidth() == Sema.getWidth() &&
+ "The value should have a bit width that matches the Sema width");
+ }
+
+ APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema)
+ : APFixedPoint(llvm::APInt(Sema.getWidth(), Val, Sema.isSigned()),
+ Sema) {}
+
+ llvm::APSInt getValue() const { return llvm::APSInt(Val, !Sema.isSigned()); }
+ inline unsigned getWidth() const { return Sema.getWidth(); }
+ inline unsigned getScale() const { return Sema.getScale(); }
+ inline bool isSaturated() const { return Sema.isSaturated(); }
+ inline bool isSigned() const { return Sema.isSigned(); }
+ inline bool hasPadding() const { return Sema.hasUnsignedPadding(); }
+
+ // Convert this number to match the semantics provided.
+ APFixedPoint convert(const FixedPointSemantics &DstSema) const;
+
+ APFixedPoint shr(unsigned Amt) const {
+ return APFixedPoint(Val >> Amt, Sema);
+ }
+
+ APFixedPoint shl(unsigned Amt) const {
+ return APFixedPoint(Val << Amt, Sema);
+ }
+
+ llvm::APSInt getIntPart() const {
+ if (Val < 0 && Val != -Val) // Cover the case when we have the min val
+ return -(-Val >> getScale());
+ else
+ return Val >> getScale();
+ }
+
+ // If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1.
+ int compare(const APFixedPoint &Other) const;
+ bool operator==(const APFixedPoint &Other) const {
+ return compare(Other) == 0;
+ }
+ bool operator!=(const APFixedPoint &Other) const {
+ return compare(Other) != 0;
+ }
+ bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; }
+ bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; }
+ bool operator>=(const APFixedPoint &Other) const {
+ return compare(Other) >= 0;
+ }
+ bool operator<=(const APFixedPoint &Other) const {
+ return compare(Other) <= 0;
+ }
+
+ static APFixedPoint getMax(const FixedPointSemantics &Sema);
+ static APFixedPoint getMin(const FixedPointSemantics &Sema);
+
+private:
+ llvm::APSInt Val;
+ FixedPointSemantics Sema;
+};
+
+} // namespace clang
+
+#endif
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index c2e9c71b0f0d..82e8c8c34951 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -34,6 +34,8 @@
namespace clang {
+class DeclarationName;
+class DeclarationNameTable;
class IdentifierInfo;
class LangOptions;
class MultiKeywordSelector;
@@ -42,52 +44,91 @@ class SourceLocation;
/// A simple pair of identifier info and location.
using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
+/// IdentifierInfo and other related classes are aligned to
+/// 8 bytes so that DeclarationName can use the lower 3 bits
+/// of a pointer to one of these classes.
+enum { IdentifierInfoAlignment = 8 };
+
/// One of these records is kept for each identifier that
/// is lexed. This contains information about whether the token was \#define'd,
/// is a language keyword, or if it is a front-end token of some sort (e.g. a
/// variable or function name). The preprocessor keeps this information in a
/// set, and all tok::identifier tokens have a pointer to one of these.
-class IdentifierInfo {
+/// It is aligned to 8 bytes because DeclarationName needs the lower 3 bits.
+class alignas(IdentifierInfoAlignment) IdentifierInfo {
friend class IdentifierTable;
- unsigned TokenID : 9; // Front-end token ID or tok::identifier.
- // Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
- // First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
- // are for builtins.
- unsigned ObjCOrBuiltinID :13;
- bool HasMacro : 1; // True if there is a #define for this.
- bool HadMacro : 1; // True if there was a #define for this.
- bool IsExtension : 1; // True if identifier is a lang extension.
- bool IsFutureCompatKeyword : 1; // True if identifier is a keyword in a
- // newer Standard or proposed Standard.
- bool IsPoisoned : 1; // True if identifier is poisoned.
- bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
- bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
- bool IsFromAST : 1; // True if identifier was loaded (at least
- // partially) from an AST file.
- bool ChangedAfterLoad : 1; // True if identifier has changed from the
- // definition loaded from an AST file.
- bool FEChangedAfterLoad : 1; // True if identifier's frontend information
- // has changed from the definition loaded
- // from an AST file.
- bool RevertedTokenID : 1; // True if revertTokenIDToIdentifier was
- // called.
- bool OutOfDate : 1; // True if there may be additional
- // information about this identifier
- // stored externally.
- bool IsModulesImport : 1; // True if this is the 'import' contextual
- // keyword.
- // 29 bit left in 64-bit word.
+ // Front-end token ID or tok::identifier.
+ unsigned TokenID : 9;
+
+ // ObjC keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
+ // First NUM_OBJC_KEYWORDS values are for Objective-C,
+ // the remaining values are for builtins.
+ unsigned ObjCOrBuiltinID : 13;
+
+ // True if there is a #define for this.
+ unsigned HasMacro : 1;
+
+ // True if there was a #define for this.
+ unsigned HadMacro : 1;
+
+ // True if the identifier is a language extension.
+ unsigned IsExtension : 1;
+
+ // True if the identifier is a keyword in a newer or proposed Standard.
+ unsigned IsFutureCompatKeyword : 1;
+
+ // True if the identifier is poisoned.
+ unsigned IsPoisoned : 1;
+
+ // True if the identifier is a C++ operator keyword.
+ unsigned IsCPPOperatorKeyword : 1;
+
+ // Internal bit set by the member function RecomputeNeedsHandleIdentifier.
+ // See comment about RecomputeNeedsHandleIdentifier for more info.
+ unsigned NeedsHandleIdentifier : 1;
+
+ // True if the identifier was loaded (at least partially) from an AST file.
+ unsigned IsFromAST : 1;
+
+ // True if the identifier has changed from the definition
+ // loaded from an AST file.
+ unsigned ChangedAfterLoad : 1;
+
+ // True if the identifier's frontend information has changed from the
+ // definition loaded from an AST file.
+ unsigned FEChangedAfterLoad : 1;
+
+ // True if revertTokenIDToIdentifier was called.
+ unsigned RevertedTokenID : 1;
+
+ // True if there may be additional information about
+ // this identifier stored externally.
+ unsigned OutOfDate : 1;
+
+ // True if this is the 'import' contextual keyword.
+ unsigned IsModulesImport : 1;
+
+ // 29 bits left in a 64-bit word.
// Managed by the language front-end.
void *FETokenInfo = nullptr;
llvm::StringMapEntry<IdentifierInfo *> *Entry = nullptr;
+ IdentifierInfo()
+ : TokenID(tok::identifier), ObjCOrBuiltinID(0), HasMacro(false),
+ HadMacro(false), IsExtension(false), IsFutureCompatKeyword(false),
+ IsPoisoned(false), IsCPPOperatorKeyword(false),
+ NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false),
+ FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false),
+ IsModulesImport(false) {}
+
public:
- IdentifierInfo();
IdentifierInfo(const IdentifierInfo &) = delete;
IdentifierInfo &operator=(const IdentifierInfo &) = delete;
+ IdentifierInfo(IdentifierInfo &&) = delete;
+ IdentifierInfo &operator=(IdentifierInfo &&) = delete;
/// Return true if this is the identifier for the specified string.
///
@@ -106,31 +147,10 @@ public:
/// Return the beginning of the actual null-terminated string for this
/// identifier.
- const char *getNameStart() const {
- if (Entry) return Entry->getKeyData();
- // FIXME: This is gross. It would be best not to embed specific details
- // of the PTH file format here.
- // The 'this' pointer really points to a
- // std::pair<IdentifierInfo, const char*>, where internal pointer
- // points to the external string data.
- using actualtype = std::pair<IdentifierInfo, const char *>;
-
- return ((const actualtype*) this)->second;
- }
+ const char *getNameStart() const { return Entry->getKeyData(); }
/// Efficiently return the length of this identifier info.
- unsigned getLength() const {
- if (Entry) return Entry->getKeyLength();
- // FIXME: This is gross. It would be best not to embed specific details
- // of the PTH file format here.
- // The 'this' pointer really points to a
- // std::pair<IdentifierInfo, const char*>, where internal pointer
- // points to the external string data.
- using actualtype = std::pair<IdentifierInfo, const char *>;
-
- const char* p = ((const actualtype*) this)->second - 2;
- return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1;
- }
+ unsigned getLength() const { return Entry->getKeyLength(); }
/// Return the actual identifier string.
StringRef getName() const {
@@ -284,10 +304,9 @@ public:
/// language.
bool isCPlusPlusKeyword(const LangOptions &LangOpts) const;
- /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
- /// associate arbitrary metadata with this token.
- template<typename T>
- T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
+ /// Get and set FETokenInfo. The language front-end is allowed to associate
+ /// arbitrary metadata with this token.
+ void *getFETokenInfo() const { return FETokenInfo; }
void setFETokenInfo(void *T) { FETokenInfo = T; }
/// Return true if the Preprocessor::HandleIdentifier must be called
@@ -653,16 +672,22 @@ enum ObjCStringFormatFamily {
/// accounts for 78% of all selectors in Cocoa.h.
class Selector {
friend class Diagnostic;
+ friend class SelectorTable; // only the SelectorTable can create these
+ friend class DeclarationName; // and the AST's DeclarationName.
enum IdentifierInfoFlag {
- // Empty selector = 0.
- ZeroArg = 0x1,
- OneArg = 0x2,
- MultiArg = 0x3,
- ArgFlags = ZeroArg|OneArg
+ // Empty selector = 0. Note that these enumeration values must
+ // correspond to the enumeration values of DeclarationName::StoredNameKind
+ ZeroArg = 0x01,
+ OneArg = 0x02,
+ MultiArg = 0x07,
+ ArgFlags = 0x07
};
- // a pointer to the MultiKeywordSelector or IdentifierInfo.
+ /// A pointer to the MultiKeywordSelector or IdentifierInfo. We use the low
+ /// three bits of InfoPtr to store an IdentifierInfoFlag. Note that in any
+ /// case IdentifierInfo and MultiKeywordSelector are already aligned to
+ /// 8 bytes even on 32 bits archs because of DeclarationName.
uintptr_t InfoPtr = 0;
Selector(IdentifierInfo *II, unsigned nArgs) {
@@ -697,13 +722,10 @@ class Selector {
static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel);
public:
- friend class SelectorTable; // only the SelectorTable can create these
- friend class DeclarationName; // and the AST's DeclarationName.
-
/// The default ctor should only be used when creating data structures that
/// will contain selectors.
Selector() = default;
- Selector(uintptr_t V) : InfoPtr(V) {}
+ explicit Selector(uintptr_t V) : InfoPtr(V) {}
/// operator==/!= - Indicate whether the specified selectors are identical.
bool operator==(Selector RHS) const {
@@ -832,39 +854,68 @@ public:
static std::string getPropertyNameFromSetterSelector(Selector Sel);
};
-/// DeclarationNameExtra - Common base of the MultiKeywordSelector,
-/// CXXSpecialName, and CXXOperatorIdName classes, all of which are
-/// private classes that describe different kinds of names.
-class DeclarationNameExtra {
-public:
- /// ExtraKind - The kind of "extra" information stored in the
- /// DeclarationName. See @c ExtraKindOrNumArgs for an explanation of
- /// how these enumerator values are used.
+namespace detail {
+
+/// DeclarationNameExtra is used as a base of various uncommon special names.
+/// This class is needed since DeclarationName has not enough space to store
+/// the kind of every possible names. Therefore the kind of common names is
+/// stored directly in DeclarationName, and the kind of uncommon names is
+/// stored in DeclarationNameExtra. It is aligned to 8 bytes because
+/// DeclarationName needs the lower 3 bits to store the kind of common names.
+/// DeclarationNameExtra is tightly coupled to DeclarationName and any change
+/// here is very likely to require changes in DeclarationName(Table).
+class alignas(IdentifierInfoAlignment) DeclarationNameExtra {
+ friend class clang::DeclarationName;
+ friend class clang::DeclarationNameTable;
+
+protected:
+ /// The kind of "extra" information stored in the DeclarationName. See
+ /// @c ExtraKindOrNumArgs for an explanation of how these enumerator values
+ /// are used. Note that DeclarationName depends on the numerical values
+ /// of the enumerators in this enum. See DeclarationName::StoredNameKind
+ /// for more info.
enum ExtraKind {
- CXXConstructor = 0,
- CXXDestructor,
- CXXConversionFunction,
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- CXXOperator##Name,
-#include "clang/Basic/OperatorKinds.def"
- CXXDeductionGuide,
- CXXLiteralOperator,
+ CXXDeductionGuideName,
+ CXXLiteralOperatorName,
CXXUsingDirective,
- NUM_EXTRA_KINDS
+ ObjCMultiArgSelector
};
- /// ExtraKindOrNumArgs - Either the kind of C++ special name or
- /// operator-id (if the value is one of the CXX* enumerators of
- /// ExtraKind), in which case the DeclarationNameExtra is also a
- /// CXXSpecialName, (for CXXConstructor, CXXDestructor, or
- /// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName,
- /// it may be also name common to C++ using-directives (CXXUsingDirective),
- /// otherwise it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
- /// arguments in the Objective-C selector, in which case the
- /// DeclarationNameExtra is also a MultiKeywordSelector.
+ /// ExtraKindOrNumArgs has one of the following meaning:
+ /// * The kind of an uncommon C++ special name. This DeclarationNameExtra
+ /// is in this case in fact either a CXXDeductionGuideNameExtra or
+ /// a CXXLiteralOperatorIdName.
+ ///
+ /// * It may be also name common to C++ using-directives (CXXUsingDirective),
+ ///
+ /// * Otherwise it is ObjCMultiArgSelector+NumArgs, where NumArgs is
+ /// the number of arguments in the Objective-C selector, in which
+ /// case the DeclarationNameExtra is also a MultiKeywordSelector.
unsigned ExtraKindOrNumArgs;
+
+ DeclarationNameExtra(ExtraKind Kind) : ExtraKindOrNumArgs(Kind) {}
+ DeclarationNameExtra(unsigned NumArgs)
+ : ExtraKindOrNumArgs(ObjCMultiArgSelector + NumArgs) {}
+
+ /// Return the corresponding ExtraKind.
+ ExtraKind getKind() const {
+ return static_cast<ExtraKind>(ExtraKindOrNumArgs >
+ (unsigned)ObjCMultiArgSelector
+ ? (unsigned)ObjCMultiArgSelector
+ : ExtraKindOrNumArgs);
+ }
+
+ /// Return the number of arguments in an ObjC selector. Only valid when this
+ /// is indeed an ObjCMultiArgSelector.
+ unsigned getNumArgs() const {
+ assert(ExtraKindOrNumArgs >= (unsigned)ObjCMultiArgSelector &&
+ "getNumArgs called but this is not an ObjC selector!");
+ return ExtraKindOrNumArgs - (unsigned)ObjCMultiArgSelector;
+ }
};
+} // namespace detail
+
} // namespace clang
namespace llvm {
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index fc38af5b03f6..49961856c965 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -92,8 +92,7 @@ LANGOPT(CPlusPlus11 , 1, 0, "C++11")
LANGOPT(CPlusPlus14 , 1, 0, "C++14")
LANGOPT(CPlusPlus17 , 1, 0, "C++17")
LANGOPT(CPlusPlus2a , 1, 0, "C++2a")
-LANGOPT(ObjC1 , 1, 0, "Objective-C 1")
-LANGOPT(ObjC2 , 1, 0, "Objective-C 2")
+LANGOPT(ObjC , 1, 0, "Objective-C")
BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0,
"Objective-C auto-synthesized properties")
BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0,
@@ -139,6 +138,7 @@ LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
LANGOPT(CoroutinesTS , 1, 0, "C++ coroutines TS")
+LANGOPT(DllExportInlines , 1, 1, "dllexported classes dllexport inline methods")
LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments")
LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
@@ -203,14 +203,18 @@ LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.")
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")
LANGOPT(OpenMPCUDAMode , 1, 0, "Generate code for OpenMP pragmas in SIMT/SPMD mode")
+LANGOPT(OpenMPCUDAForceFullRuntime , 1, 0, "Force to use full runtime in all constructs when offloading to CUDA devices")
LANGOPT(OpenMPHostCXXExceptions , 1, 0, "C++ exceptions handling in the host code.")
+LANGOPT(OpenMPCUDANumSMs , 32, 0, "Number of SMs for CUDA devices.")
+LANGOPT(OpenMPCUDABlocksPerSM , 32, 0, "Number of blocks per SM for CUDA devices.")
+LANGOPT(OpenMPOptimisticCollapse , 1, 0, "Use at most 32 bits to represent the collapsed loop nest counter.")
LANGOPT(RenderScript , 1, 0, "RenderScript")
LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device")
LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA device code")
LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr functions as __host__ __device__")
LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental functions")
-LANGOPT(CUDARelocatableDeviceCode, 1, 0, "generate relocatable device code")
+LANGOPT(GPURelocatableDeviceCode, 1, 0, "generate relocatable device code")
LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
@@ -224,7 +228,8 @@ BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records"
BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form")
BENIGN_LANGOPT(DumpVTableLayouts , 1, 0, "dumping the layouts of emitted vtables")
LANGOPT(NoConstantCFStrings , 1, 0, "no constant CoreFoundation strings")
-BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden default visibility for inline C++ methods")
+BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden visibility for inline C++ methods")
+LANGOPT(GlobalAllocationFunctionVisibilityHidden , 1, 0, "hidden visibility for global operator new and delete declaration")
BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype")
BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support")
BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type")
@@ -259,6 +264,8 @@ ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility,
"type symbol visibility")
ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff,
"stack protector mode")
+ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKind::Uninitialized,
+ "trivial automatic variable initialization")
ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
"signed integer overflow handling")
@@ -308,6 +315,8 @@ LANGOPT(FixedPoint, 1, 0, "fixed point types")
LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0,
"unsigned fixed point types having one extra padding bit")
+LANGOPT(RegisterStaticDestructors, 1, 1, "Register C++ static destructors")
+
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index a1396f84352f..9cff7c516043 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -54,6 +54,11 @@ public:
enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
+ // Automatic variables live on the stack, and when trivial they're usually
+ // uninitialized because it's undefined behavior to use them without
+ // initializing them.
+ enum class TrivialAutoVarInitKind { Uninitialized, Zero, Pattern };
+
enum SignedOverflowBehaviorTy {
// Default C standard behavior.
SOB_Undefined,
@@ -73,8 +78,11 @@ public:
/// Compiling a module from a module map.
CMK_ModuleMap,
+ /// Compiling a module from a list of header files.
+ CMK_HeaderModule,
+
/// Compiling a C++ modules TS module interface unit.
- CMK_ModuleInterface
+ CMK_ModuleInterface,
};
enum PragmaMSPointersToMembersKind {
@@ -95,11 +103,14 @@ public:
enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
+ // Corresponds to _MSC_VER
enum MSVCMajorVersion {
- MSVC2010 = 16,
- MSVC2012 = 17,
- MSVC2013 = 18,
- MSVC2015 = 19
+ MSVC2010 = 1600,
+ MSVC2012 = 1700,
+ MSVC2013 = 1800,
+ MSVC2015 = 1900,
+ MSVC2017 = 1910,
+ MSVC2017_5 = 1912
};
/// Clang versions with different platform ABI conformance.
@@ -121,11 +132,34 @@ public:
/// whether we reuse base class tail padding in some ABIs.
Ver6,
+ /// Attempt to be ABI-compatible with code generated by Clang 7.0.x
+ /// (SVN r338536). This causes alignof (C++) and _Alignof (C11) to be
+ /// compatible with __alignof (i.e., return the preferred alignment)
+ /// rather than returning the required alignment.
+ Ver7,
+
/// Conform to the underlying platform's C and C++ ABIs as closely
/// as we can.
Latest
};
+ enum class CoreFoundationABI {
+ /// No interoperability ABI has been specified
+ Unspecified,
+ /// CoreFoundation does not have any language interoperability
+ Standalone,
+ /// Interoperability with the ObjectiveC runtime
+ ObjectiveC,
+ /// Interoperability with the latest known version of the Swift runtime
+ Swift,
+ /// Interoperability with the Swift 5.0 runtime
+ Swift5_0,
+ /// Interoperability with the Swift 4.2 runtime
+ Swift4_2,
+ /// Interoperability with the Swift 4.1 runtime
+ Swift4_1,
+ };
+
enum FPContractModeKind {
// Form fused FP ops only where result will not be affected.
FPC_Off,
@@ -137,6 +171,14 @@ public:
FPC_Fast
};
+ // TODO: merge FEnvAccessModeKind and FPContractModeKind
+ enum FEnvAccessModeKind {
+ FEA_Off,
+
+ FEA_On
+ };
+
+
public:
/// Set of enabled sanitizers.
SanitizerSet Sanitize;
@@ -164,6 +206,8 @@ public:
clang::ObjCRuntime ObjCRuntime;
+ CoreFoundationABI CFRuntime = CoreFoundationABI::Unspecified;
+
std::string ObjCConstantStringClass;
/// The name of the handler function to be called when -ftrapv is
@@ -235,7 +279,7 @@ public:
}
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const {
- return MSCompatibilityVersion >= MajorVersion * 10000000U;
+ return MSCompatibilityVersion >= MajorVersion * 100000U;
}
/// Reset all of the options that are not considered when building a
@@ -262,14 +306,19 @@ public:
/// Floating point control options
class FPOptions {
public:
- FPOptions() : fp_contract(LangOptions::FPC_Off) {}
+ FPOptions() : fp_contract(LangOptions::FPC_Off),
+ fenv_access(LangOptions::FEA_Off) {}
// Used for serializing.
explicit FPOptions(unsigned I)
- : fp_contract(static_cast<LangOptions::FPContractModeKind>(I)) {}
+ : fp_contract(static_cast<LangOptions::FPContractModeKind>(I & 3)),
+ fenv_access(static_cast<LangOptions::FEnvAccessModeKind>((I >> 2) & 1))
+ {}
explicit FPOptions(const LangOptions &LangOpts)
- : fp_contract(LangOpts.getDefaultFPContractMode()) {}
+ : fp_contract(LangOpts.getDefaultFPContractMode()),
+ fenv_access(LangOptions::FEA_Off) {}
+ // FIXME: Use getDefaultFEnvAccessMode() when available.
bool allowFPContractWithinStatement() const {
return fp_contract == LangOptions::FPC_On;
@@ -289,12 +338,24 @@ public:
void setDisallowFPContract() { fp_contract = LangOptions::FPC_Off; }
+ bool allowFEnvAccess() const {
+ return fenv_access == LangOptions::FEA_On;
+ }
+
+ void setAllowFEnvAccess() {
+ fenv_access = LangOptions::FEA_On;
+ }
+
+ void setDisallowFEnvAccess() { fenv_access = LangOptions::FEA_Off; }
+
/// Used to serialize this.
- unsigned getInt() const { return fp_contract; }
+ unsigned getInt() const { return fp_contract | (fenv_access << 2); }
private:
- /// Adjust BinaryOperator::FPFeatures to match the bit-field size of this.
+ /// Adjust BinaryOperator::FPFeatures to match the total bit-field size
+ /// of these two.
unsigned fp_contract : 2;
+ unsigned fenv_access : 1;
};
/// Describes the kind of translation unit being processed.
diff --git a/include/clang/Basic/MSP430Target.def b/include/clang/Basic/MSP430Target.def
new file mode 100644
index 000000000000..758113c5f575
--- /dev/null
+++ b/include/clang/Basic/MSP430Target.def
@@ -0,0 +1,247 @@
+//===--- MSP430Target.def - MSP430 Feature/Processor Database----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the MSP430 devices and their features.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MSP430_MCU_FEAT
+#define MSP430_MCU_FEAT(NAME, HWMULT) MSP430_MCU(NAME)
+#endif
+
+#ifndef MSP430_MCU
+#define MSP430_MCU(NAME)
+#endif
+
+MSP430_MCU("msp430c111")
+MSP430_MCU("msp430c1111")
+MSP430_MCU("msp430c112")
+MSP430_MCU("msp430c1121")
+MSP430_MCU("msp430c1331")
+MSP430_MCU("msp430c1351")
+MSP430_MCU("msp430e112")
+MSP430_MCU("msp430f110")
+MSP430_MCU("msp430f1101")
+MSP430_MCU("msp430f1101a")
+MSP430_MCU("msp430f1111")
+MSP430_MCU("msp430f1111a")
+MSP430_MCU("msp430f112")
+MSP430_MCU("msp430f1121")
+MSP430_MCU("msp430f1121a")
+MSP430_MCU("msp430f1122")
+MSP430_MCU("msp430f1132")
+MSP430_MCU("msp430f122")
+MSP430_MCU("msp430f1222")
+MSP430_MCU("msp430f123")
+MSP430_MCU("msp430f1232")
+MSP430_MCU("msp430f133")
+MSP430_MCU("msp430f135")
+MSP430_MCU("msp430f155")
+MSP430_MCU("msp430f156")
+MSP430_MCU("msp430f157")
+MSP430_MCU("msp430p112")
+MSP430_MCU("msp430f2001")
+MSP430_MCU("msp430f2011")
+MSP430_MCU("msp430f2002")
+MSP430_MCU("msp430f2012")
+MSP430_MCU("msp430f2003")
+MSP430_MCU("msp430f2013")
+MSP430_MCU("msp430f2101")
+MSP430_MCU("msp430f2111")
+MSP430_MCU("msp430f2121")
+MSP430_MCU("msp430f2131")
+MSP430_MCU("msp430f2112")
+MSP430_MCU("msp430f2122")
+MSP430_MCU("msp430f2132")
+MSP430_MCU("msp430f2232")
+MSP430_MCU("msp430f2252")
+MSP430_MCU("msp430f2272")
+MSP430_MCU("msp430f2234")
+MSP430_MCU("msp430f2254")
+MSP430_MCU("msp430f2274")
+MSP430_MCU("msp430g2211")
+MSP430_MCU("msp430g2201")
+MSP430_MCU("msp430g2111")
+MSP430_MCU("msp430g2101")
+MSP430_MCU("msp430g2001")
+MSP430_MCU("msp430g2231")
+MSP430_MCU("msp430g2221")
+MSP430_MCU("msp430g2131")
+MSP430_MCU("msp430g2121")
+MSP430_MCU("msp430g2102")
+MSP430_MCU("msp430g2202")
+MSP430_MCU("msp430g2302")
+MSP430_MCU("msp430g2402")
+MSP430_MCU("msp430g2132")
+MSP430_MCU("msp430g2232")
+MSP430_MCU("msp430g2332")
+MSP430_MCU("msp430g2432")
+MSP430_MCU("msp430g2112")
+MSP430_MCU("msp430g2212")
+MSP430_MCU("msp430g2312")
+MSP430_MCU("msp430g2412")
+MSP430_MCU("msp430g2152")
+MSP430_MCU("msp430g2252")
+MSP430_MCU("msp430g2352")
+MSP430_MCU("msp430g2452")
+MSP430_MCU("msp430g2113")
+MSP430_MCU("msp430g2213")
+MSP430_MCU("msp430g2313")
+MSP430_MCU("msp430g2413")
+MSP430_MCU("msp430g2513")
+MSP430_MCU("msp430g2153")
+MSP430_MCU("msp430g2253")
+MSP430_MCU("msp430g2353")
+MSP430_MCU("msp430g2453")
+MSP430_MCU("msp430g2553")
+MSP430_MCU("msp430g2203")
+MSP430_MCU("msp430g2303")
+MSP430_MCU("msp430g2403")
+MSP430_MCU("msp430g2233")
+MSP430_MCU("msp430g2333")
+MSP430_MCU("msp430g2433")
+MSP430_MCU("msp430g2533")
+MSP430_MCU("msp430tch5e")
+MSP430_MCU("msp430g2444")
+MSP430_MCU("msp430g2544")
+MSP430_MCU("msp430g2744")
+MSP430_MCU("msp430g2755")
+MSP430_MCU("msp430g2855")
+MSP430_MCU("msp430g2955")
+MSP430_MCU("msp430g2230")
+MSP430_MCU("msp430g2210")
+MSP430_MCU("msp430c311s")
+MSP430_MCU("msp430c312")
+MSP430_MCU("msp430c313")
+MSP430_MCU("msp430c314")
+MSP430_MCU("msp430c315")
+MSP430_MCU("msp430c323")
+MSP430_MCU("msp430c325")
+MSP430_MCU("msp430c412")
+MSP430_MCU("msp430c413")
+MSP430_MCU("msp430e313")
+MSP430_MCU("msp430e315")
+MSP430_MCU("msp430e325")
+MSP430_MCU("msp430p313")
+MSP430_MCU("msp430p315")
+MSP430_MCU("msp430p315s")
+MSP430_MCU("msp430p325")
+MSP430_MCU("msp430f412")
+MSP430_MCU("msp430f413")
+MSP430_MCU("msp430f415")
+MSP430_MCU("msp430f417")
+MSP430_MCU("msp430f4132")
+MSP430_MCU("msp430f4152")
+MSP430_MCU("msp430f435")
+MSP430_MCU("msp430f436")
+MSP430_MCU("msp430f437")
+MSP430_MCU("msp430f4351")
+MSP430_MCU("msp430f4361")
+MSP430_MCU("msp430f4371")
+MSP430_MCU("msp430fe423")
+MSP430_MCU("msp430fe425")
+MSP430_MCU("msp430fe427")
+MSP430_MCU("msp430fe423a")
+MSP430_MCU("msp430fe425a")
+MSP430_MCU("msp430fe427a")
+MSP430_MCU("msp430fe4232")
+MSP430_MCU("msp430fe4242")
+MSP430_MCU("msp430fe4252")
+MSP430_MCU("msp430fe4272")
+MSP430_MCU("msp430f4250")
+MSP430_MCU("msp430f4260")
+MSP430_MCU("msp430f4270")
+MSP430_MCU("msp430fg4250")
+MSP430_MCU("msp430fg4260")
+MSP430_MCU("msp430fg4270")
+MSP430_MCU("msp430fw423")
+MSP430_MCU("msp430fw425")
+MSP430_MCU("msp430fw427")
+MSP430_MCU("msp430fw428")
+MSP430_MCU("msp430fw429")
+MSP430_MCU("msp430fg437")
+MSP430_MCU("msp430fg438")
+MSP430_MCU("msp430fg439")
+MSP430_MCU("msp430f438")
+MSP430_MCU("msp430f439")
+MSP430_MCU("msp430f477")
+MSP430_MCU("msp430f478")
+MSP430_MCU("msp430f479")
+MSP430_MCU("msp430fg477")
+MSP430_MCU("msp430fg478")
+MSP430_MCU("msp430fg479")
+
+// With 16-bit hardware multiplier
+MSP430_MCU_FEAT("msp430f147", "16bit")
+MSP430_MCU_FEAT("msp430f148", "16bit")
+MSP430_MCU_FEAT("msp430f149", "16bit")
+MSP430_MCU_FEAT("msp430f1471", "16bit")
+MSP430_MCU_FEAT("msp430f1481", "16bit")
+MSP430_MCU_FEAT("msp430f1491", "16bit")
+MSP430_MCU_FEAT("msp430f167", "16bit")
+MSP430_MCU_FEAT("msp430f168", "16bit")
+MSP430_MCU_FEAT("msp430f169", "16bit")
+MSP430_MCU_FEAT("msp430f1610", "16bit")
+MSP430_MCU_FEAT("msp430f1611", "16bit")
+MSP430_MCU_FEAT("msp430f1612", "16bit")
+MSP430_MCU_FEAT("msp430c336", "16bit")
+MSP430_MCU_FEAT("msp430c337", "16bit")
+MSP430_MCU_FEAT("msp430e337", "16bit")
+MSP430_MCU_FEAT("msp430p337", "16bit")
+MSP430_MCU_FEAT("msp430f423", "16bit")
+MSP430_MCU_FEAT("msp430f425", "16bit")
+MSP430_MCU_FEAT("msp430f427", "16bit")
+MSP430_MCU_FEAT("msp430f423a", "16bit")
+MSP430_MCU_FEAT("msp430f425a", "16bit")
+MSP430_MCU_FEAT("msp430f427a", "16bit")
+MSP430_MCU_FEAT("msp430f4481", "16bit")
+MSP430_MCU_FEAT("msp430f4491", "16bit")
+MSP430_MCU_FEAT("msp430f447", "16bit")
+MSP430_MCU_FEAT("msp430f448", "16bit")
+MSP430_MCU_FEAT("msp430f449", "16bit")
+MSP430_MCU_FEAT("msp430f2330", "16bit")
+MSP430_MCU_FEAT("msp430f2350", "16bit")
+MSP430_MCU_FEAT("msp430f2370", "16bit")
+MSP430_MCU_FEAT("msp430f233", "16bit")
+MSP430_MCU_FEAT("msp430f235", "16bit")
+MSP430_MCU_FEAT("msp430f247", "16bit")
+MSP430_MCU_FEAT("msp430f248", "16bit")
+MSP430_MCU_FEAT("msp430f249", "16bit")
+MSP430_MCU_FEAT("msp430f2410", "16bit")
+MSP430_MCU_FEAT("msp430f2471", "16bit")
+MSP430_MCU_FEAT("msp430f2481", "16bit")
+MSP430_MCU_FEAT("msp430f2491", "16bit")
+MSP430_MCU_FEAT("msp430i2020", "16bit")
+MSP430_MCU_FEAT("msp430i2021", "16bit")
+MSP430_MCU_FEAT("msp430i2030", "16bit")
+MSP430_MCU_FEAT("msp430i2031", "16bit")
+MSP430_MCU_FEAT("msp430i2040", "16bit")
+MSP430_MCU_FEAT("msp430i2041", "16bit")
+MSP430_MCU_FEAT("msp430afe221", "16bit")
+MSP430_MCU_FEAT("msp430afe231", "16bit")
+MSP430_MCU_FEAT("msp430afe251", "16bit")
+MSP430_MCU_FEAT("msp430afe222", "16bit")
+MSP430_MCU_FEAT("msp430afe232", "16bit")
+MSP430_MCU_FEAT("msp430afe252", "16bit")
+MSP430_MCU_FEAT("msp430afe223", "16bit")
+MSP430_MCU_FEAT("msp430afe233", "16bit")
+MSP430_MCU_FEAT("msp430afe253", "16bit")
+
+// With 32 Bit Hardware Multiplier
+MSP430_MCU_FEAT("msp430f4783", "32bit")
+MSP430_MCU_FEAT("msp430f4793", "32bit")
+MSP430_MCU_FEAT("msp430f4784", "32bit")
+MSP430_MCU_FEAT("msp430f4794", "32bit")
+
+// Generic MSUs
+MSP430_MCU("msp430")
+MSP430_MCU("msp430i2xxgeneric")
+
+#undef MSP430_MCU
+#undef MSP430_MCU_FEAT
diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
index c307c9643390..fcfbe56b496f 100644
--- a/include/clang/Basic/ObjCRuntime.h
+++ b/include/clang/Basic/ObjCRuntime.h
@@ -173,6 +173,80 @@ public:
llvm_unreachable("bad kind");
}
+ /// Does this runtime provide ARC entrypoints that are likely to be faster
+ /// than an ordinary message send of the appropriate selector?
+ ///
+ /// The ARC entrypoints are guaranteed to be equivalent to just sending the
+ /// corresponding message. If the entrypoint is implemented naively as just a
+ /// message send, using it is a trade-off: it sacrifices a few cycles of
+ /// overhead to save a small amount of code. However, it's possible for
+ /// runtimes to detect and special-case classes that use "standard"
+ /// retain/release behavior; if that's dynamically a large proportion of all
+ /// retained objects, using the entrypoint will also be faster than using a
+ /// message send.
+ ///
+ /// When this method returns true, Clang will turn non-super message sends of
+ /// certain selectors into calls to the correspond entrypoint:
+ /// retain => objc_retain
+ /// release => objc_release
+ /// autorelease => objc_autorelease
+ bool shouldUseARCFunctionsForRetainRelease() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ return false;
+ case MacOSX:
+ return getVersion() >= VersionTuple(10, 10);
+ case iOS:
+ return getVersion() >= VersionTuple(8);
+ case WatchOS:
+ return true;
+ case GCC:
+ return false;
+ case GNUstep:
+ return false;
+ case ObjFW:
+ return false;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// Does this runtime provide entrypoints that are likely to be faster
+ /// than an ordinary message send of the "alloc" selector?
+ ///
+ /// The "alloc" entrypoint is guaranteed to be equivalent to just sending the
+ /// corresponding message. If the entrypoint is implemented naively as just a
+ /// message send, using it is a trade-off: it sacrifices a few cycles of
+ /// overhead to save a small amount of code. However, it's possible for
+ /// runtimes to detect and special-case classes that use "standard"
+ /// alloc behavior; if that's dynamically a large proportion of all
+ /// objects, using the entrypoint will also be faster than using a message
+ /// send.
+ ///
+ /// When this method returns true, Clang will turn non-super message sends of
+ /// certain selectors into calls to the corresponding entrypoint:
+ /// alloc => objc_alloc
+ /// allocWithZone:nil => objc_allocWithZone
+ bool shouldUseRuntimeFunctionsForAlloc() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ return false;
+ case MacOSX:
+ return getVersion() >= VersionTuple(10, 10);
+ case iOS:
+ return getVersion() >= VersionTuple(8);
+ case WatchOS:
+ return true;
+
+ case GCC:
+ return false;
+ case GNUstep:
+ return false;
+ case ObjFW:
+ return false;
+ }
+ llvm_unreachable("bad kind");
+ }
+
/// Does this runtime supports optimized setter entrypoints?
bool hasOptimizedSetter() const {
switch (getKind()) {
diff --git a/include/clang/Basic/OpenCLExtensionTypes.def b/include/clang/Basic/OpenCLExtensionTypes.def
new file mode 100644
index 000000000000..b72f7efd6f28
--- /dev/null
+++ b/include/clang/Basic/OpenCLExtensionTypes.def
@@ -0,0 +1,41 @@
+//===-- OpenCLExtensionTypes.def - Metadata about BuiltinTypes ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file extends builtin types database with OpenCL extension types.
+// Custom code should define this macro:
+// EXT_OPAQUE_TYPE(Name, Id, Ext)
+
+#ifdef EXT_OPAQUE_TYPE
+
+#ifndef INTEL_SUBGROUP_AVC_TYPE
+#define INTEL_SUBGROUP_AVC_TYPE(Name, Id) \
+ EXT_OPAQUE_TYPE(intel_sub_group_avc_##Name, OCLIntelSubgroupAVC##Id, \
+ cl_intel_device_side_avc_motion_estimation)
+#endif
+
+#endif
+
+#ifdef INTEL_SUBGROUP_AVC_TYPE
+INTEL_SUBGROUP_AVC_TYPE(mce_payload_t, McePayload)
+INTEL_SUBGROUP_AVC_TYPE(ime_payload_t, ImePayload)
+INTEL_SUBGROUP_AVC_TYPE(ref_payload_t, RefPayload)
+INTEL_SUBGROUP_AVC_TYPE(sic_payload_t, SicPayload)
+INTEL_SUBGROUP_AVC_TYPE(mce_result_t, MceResult)
+INTEL_SUBGROUP_AVC_TYPE(ime_result_t, ImeResult)
+INTEL_SUBGROUP_AVC_TYPE(ref_result_t, RefResult)
+INTEL_SUBGROUP_AVC_TYPE(sic_result_t, SicResult)
+INTEL_SUBGROUP_AVC_TYPE(ime_result_single_reference_streamout_t, ImeResultSingleRefStreamout)
+INTEL_SUBGROUP_AVC_TYPE(ime_result_dual_reference_streamout_t, ImeResultDualRefStreamout)
+INTEL_SUBGROUP_AVC_TYPE(ime_single_reference_streamin_t, ImeSingleRefStreamin)
+INTEL_SUBGROUP_AVC_TYPE(ime_dual_reference_streamin_t, ImeDualRefStreamin)
+
+#undef INTEL_SUBGROUP_AVC_TYPE
+#endif // INTEL_SUBGROUP_AVC_TYPE
+
+#undef EXT_OPAQUE_TYPE
+
diff --git a/include/clang/Basic/OpenCLExtensions.def b/include/clang/Basic/OpenCLExtensions.def
index 13cb12e7c581..5e7d2cb473c7 100644
--- a/include/clang/Basic/OpenCLExtensions.def
+++ b/include/clang/Basic/OpenCLExtensions.def
@@ -85,6 +85,7 @@ OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U)
// Intel OpenCL extensions
OPENCLEXT_INTERNAL(cl_intel_subgroups, 120, ~0U)
OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U)
+OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120, ~0U)
#undef OPENCLEXT_INTERNAL
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 4ed7053b679b..f86721b1b07e 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -57,6 +57,9 @@
#ifndef OPENMP_TARGET_CLAUSE
# define OPENMP_TARGET_CLAUSE(Name)
#endif
+#ifndef OPENMP_REQUIRES_CLAUSE
+# define OPENMP_REQUIRES_CLAUSE(Name)
+#endif
#ifndef OPENMP_TARGET_DATA_CLAUSE
# define OPENMP_TARGET_DATA_CLAUSE(Name)
#endif
@@ -117,12 +120,18 @@
#ifndef OPENMP_MAP_KIND
#define OPENMP_MAP_KIND(Name)
#endif
+#ifndef OPENMP_MAP_MODIFIER_KIND
+#define OPENMP_MAP_MODIFIER_KIND(Name)
+#endif
#ifndef OPENMP_DIST_SCHEDULE_KIND
#define OPENMP_DIST_SCHEDULE_KIND(Name)
#endif
#ifndef OPENMP_DEFAULTMAP_KIND
#define OPENMP_DEFAULTMAP_KIND(Name)
#endif
+#ifndef OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND
+#define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name)
+#endif
#ifndef OPENMP_DEFAULTMAP_MODIFIER
#define OPENMP_DEFAULTMAP_MODIFIER(Name)
#endif
@@ -193,6 +202,7 @@ OPENMP_DIRECTIVE(atomic)
OPENMP_DIRECTIVE(target)
OPENMP_DIRECTIVE(teams)
OPENMP_DIRECTIVE(cancel)
+OPENMP_DIRECTIVE(requires)
OPENMP_DIRECTIVE_EXT(target_data, "target data")
OPENMP_DIRECTIVE_EXT(target_enter_data, "target enter data")
OPENMP_DIRECTIVE_EXT(target_exit_data, "target exit data")
@@ -275,6 +285,11 @@ OPENMP_CLAUSE(use_device_ptr, OMPUseDevicePtrClause)
OPENMP_CLAUSE(is_device_ptr, OMPIsDevicePtrClause)
OPENMP_CLAUSE(task_reduction, OMPTaskReductionClause)
OPENMP_CLAUSE(in_reduction, OMPInReductionClause)
+OPENMP_CLAUSE(unified_address, OMPUnifiedAddressClause)
+OPENMP_CLAUSE(unified_shared_memory, OMPUnifiedSharedMemoryClause)
+OPENMP_CLAUSE(reverse_offload, OMPReverseOffloadClause)
+OPENMP_CLAUSE(dynamic_allocators, OMPDynamicAllocatorsClause)
+OPENMP_CLAUSE(atomic_default_mem_order, OMPAtomicDefaultMemOrderClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
@@ -456,6 +471,18 @@ OPENMP_TARGET_CLAUSE(firstprivate)
OPENMP_TARGET_CLAUSE(is_device_ptr)
OPENMP_TARGET_CLAUSE(reduction)
+// Clauses allowed for OpenMP directive 'requires'.
+OPENMP_REQUIRES_CLAUSE(unified_address)
+OPENMP_REQUIRES_CLAUSE(unified_shared_memory)
+OPENMP_REQUIRES_CLAUSE(reverse_offload)
+OPENMP_REQUIRES_CLAUSE(dynamic_allocators)
+OPENMP_REQUIRES_CLAUSE(atomic_default_mem_order)
+
+// Modifiers for 'atomic_default_mem_order' clause.
+OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(seq_cst)
+OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(acq_rel)
+OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(relaxed)
+
// Clauses allowed for OpenMP directive 'target data'.
OPENMP_TARGET_DATA_CLAUSE(if)
OPENMP_TARGET_DATA_CLAUSE(device)
@@ -535,14 +562,17 @@ OPENMP_ORDERED_CLAUSE(threads)
OPENMP_ORDERED_CLAUSE(simd)
OPENMP_ORDERED_CLAUSE(depend)
-// Map types and map type modifier for 'map' clause.
+// Map types for 'map' clause.
OPENMP_MAP_KIND(alloc)
OPENMP_MAP_KIND(to)
OPENMP_MAP_KIND(from)
OPENMP_MAP_KIND(tofrom)
OPENMP_MAP_KIND(delete)
OPENMP_MAP_KIND(release)
-OPENMP_MAP_KIND(always)
+
+// Map-type-modifiers for 'map' clause.
+OPENMP_MAP_MODIFIER_KIND(always)
+OPENMP_MAP_MODIFIER_KIND(close)
// Clauses allowed for OpenMP directive 'taskloop'.
OPENMP_TASKLOOP_CLAUSE(if)
@@ -883,6 +913,8 @@ OPENMP_TASKGROUP_CLAUSE(task_reduction)
#undef OPENMP_TASK_CLAUSE
#undef OPENMP_ATOMIC_CLAUSE
#undef OPENMP_TARGET_CLAUSE
+#undef OPENMP_REQUIRES_CLAUSE
+#undef OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND
#undef OPENMP_TARGET_DATA_CLAUSE
#undef OPENMP_TARGET_ENTER_DATA_CLAUSE
#undef OPENMP_TARGET_EXIT_DATA_CLAUSE
@@ -893,6 +925,7 @@ OPENMP_TASKGROUP_CLAUSE(task_reduction)
#undef OPENMP_FOR_CLAUSE
#undef OPENMP_FOR_SIMD_CLAUSE
#undef OPENMP_MAP_KIND
+#undef OPENMP_MAP_MODIFIER_KIND
#undef OPENMP_DISTRIBUTE_CLAUSE
#undef OPENMP_DIST_SCHEDULE_KIND
#undef OPENMP_DEFAULTMAP_KIND
diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h
index c47973e53a8a..3e03a48cf68e 100644
--- a/include/clang/Basic/OpenMPKinds.h
+++ b/include/clang/Basic/OpenMPKinds.h
@@ -96,6 +96,15 @@ enum OpenMPMapClauseKind {
OMPC_MAP_unknown
};
+/// OpenMP modifier kind for 'map' clause.
+enum OpenMPMapModifierKind {
+ OMPC_MAP_MODIFIER_unknown = OMPC_MAP_unknown,
+#define OPENMP_MAP_MODIFIER_KIND(Name) \
+ OMPC_MAP_MODIFIER_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_MAP_MODIFIER_last
+};
+
/// OpenMP attributes for 'dist_schedule' clause.
enum OpenMPDistScheduleClauseKind {
#define OPENMP_DIST_SCHEDULE_KIND(Name) OMPC_DIST_SCHEDULE_##Name,
@@ -120,6 +129,14 @@ enum OpenMPDefaultmapClauseModifier {
OMPC_DEFAULTMAP_MODIFIER_last
};
+/// OpenMP attributes for 'atomic_default_mem_order' clause.
+enum OpenMPAtomicDefaultMemOrderClauseKind {
+#define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name) \
+ OMPC_ATOMIC_DEFAULT_MEM_ORDER_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
+};
+
/// Scheduling data for loop-based OpenMP directives.
struct OpenMPScheduleTy final {
OpenMPScheduleClauseKind Schedule = OMPC_SCHEDULE_unknown;
diff --git a/include/clang/Basic/PlistSupport.h b/include/clang/Basic/PlistSupport.h
index be92bbfde185..e41c24737798 100644
--- a/include/clang/Basic/PlistSupport.h
+++ b/include/clang/Basic/PlistSupport.h
@@ -25,24 +25,35 @@ namespace markup {
using FIDMap = llvm::DenseMap<FileID, unsigned>;
-inline void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
- const SourceManager &SM, SourceLocation L) {
- FileID FID = SM.getFileID(SM.getExpansionLoc(L));
+inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
+ FileID FID) {
FIDMap::iterator I = FIDs.find(FID);
if (I != FIDs.end())
- return;
- FIDs[FID] = V.size();
+ return I->second;
+ unsigned NewValue = V.size();
+ FIDs[FID] = NewValue;
V.push_back(FID);
+ return NewValue;
}
-inline unsigned GetFID(const FIDMap &FIDs, const SourceManager &SM,
- SourceLocation L) {
+inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
+ const SourceManager &SM, SourceLocation L) {
FileID FID = SM.getFileID(SM.getExpansionLoc(L));
+ return AddFID(FIDs, V, FID);
+}
+
+inline unsigned GetFID(const FIDMap &FIDs, FileID FID) {
FIDMap::const_iterator I = FIDs.find(FID);
assert(I != FIDs.end());
return I->second;
}
+inline unsigned GetFID(const FIDMap &FIDs, const SourceManager &SM,
+ SourceLocation L) {
+ FileID FID = SM.getFileID(SM.getExpansionLoc(L));
+ return GetFID(FIDs, FID);
+}
+
inline raw_ostream &Indent(raw_ostream &o, const unsigned indent) {
for (unsigned i = 0; i < indent; ++i)
o << ' ';
diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def
index ae5c75fc5bbd..0287468d71f5 100644
--- a/include/clang/Basic/Sanitizers.def
+++ b/include/clang/Basic/Sanitizers.def
@@ -53,6 +53,9 @@ SANITIZER("kernel-hwaddress", KernelHWAddress)
// MemorySanitizer
SANITIZER("memory", Memory)
+// Kernel MemorySanitizer (KMSAN)
+SANITIZER("kernel-memory", KernelMemory)
+
// libFuzzer
SANITIZER("fuzzer", Fuzzer)
@@ -132,12 +135,32 @@ SANITIZER_GROUP("undefined", Undefined,
SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
// ImplicitConversionSanitizer
-SANITIZER("implicit-integer-truncation", ImplicitIntegerTruncation)
+SANITIZER("implicit-unsigned-integer-truncation",
+ ImplicitUnsignedIntegerTruncation)
+SANITIZER("implicit-signed-integer-truncation", ImplicitSignedIntegerTruncation)
+SANITIZER_GROUP("implicit-integer-truncation", ImplicitIntegerTruncation,
+ ImplicitUnsignedIntegerTruncation |
+ ImplicitSignedIntegerTruncation)
+
+SANITIZER("implicit-integer-sign-change", ImplicitIntegerSignChange)
+
+SANITIZER_GROUP("implicit-integer-arithmetic-value-change",
+ ImplicitIntegerArithmeticValueChange,
+ ImplicitIntegerSignChange | ImplicitSignedIntegerTruncation)
+
+// FIXME:
+//SANITIZER_GROUP("implicit-integer-conversion", ImplicitIntegerConversion,
+// ImplicitIntegerArithmeticValueChange |
+// ImplicitUnsignedIntegerTruncation)
+//SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
+// ImplicitIntegerConversion)
+
SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
- ImplicitIntegerTruncation)
+ ImplicitIntegerArithmeticValueChange |
+ ImplicitUnsignedIntegerTruncation)
SANITIZER_GROUP("integer", Integer,
- ImplicitIntegerTruncation | IntegerDivideByZero | Shift |
+ ImplicitConversion | IntegerDivideByZero | Shift |
SignedIntegerOverflow | UnsignedIntegerOverflow)
SANITIZER("local-bounds", LocalBounds)
diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h
index 2ecbde821599..fe9e76a1e325 100644
--- a/include/clang/Basic/Sanitizers.h
+++ b/include/clang/Basic/Sanitizers.h
@@ -66,7 +66,7 @@ struct SanitizerSet {
/// Disable the sanitizers specified in \p K.
void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
- /// Returns true if at least one sanitizer is enabled.
+ /// Returns true if no sanitizers are enabled.
bool empty() const { return Mask == 0; }
/// Bitmask of enabled sanitizers.
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 488a604a452f..014bdc3f3f0b 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -220,6 +220,10 @@ public:
bool operator!=(const SourceRange &X) const {
return B != X.B || E != X.E;
}
+
+ void print(raw_ostream &OS, const SourceManager &SM) const;
+ std::string printToString(const SourceManager &SM) const;
+ void dump(const SourceManager &SM) const;
};
/// Represents a character-granular source range.
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index af7dbbc13ca7..dcc4a37e239c 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -449,7 +449,7 @@ namespace SrcMgr {
}
static SLocEntry get(unsigned Offset, const FileInfo &FI) {
- assert(!(Offset & (1 << 31)) && "Offset is too large");
+ assert(!(Offset & (1u << 31)) && "Offset is too large");
SLocEntry E;
E.Offset = Offset;
E.IsExpansion = false;
@@ -458,7 +458,7 @@ namespace SrcMgr {
}
static SLocEntry get(unsigned Offset, const ExpansionInfo &Expansion) {
- assert(!(Offset & (1 << 31)) && "Offset is too large");
+ assert(!(Offset & (1u << 31)) && "Offset is too large");
SLocEntry E;
E.Offset = Offset;
E.IsExpansion = true;
@@ -1024,13 +1024,14 @@ public:
/// Set the number of FileIDs (files and macros) that were created
/// during preprocessing of \p FID, including it.
- void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const {
+ void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs,
+ bool Force = false) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
if (Invalid || !Entry.isFile())
return;
- assert(Entry.getFile().NumCreatedFIDs == 0 && "Already set!");
+ assert((Force || Entry.getFile().NumCreatedFIDs == 0) && "Already set!");
const_cast<SrcMgr::FileInfo &>(Entry.getFile()).NumCreatedFIDs = NumFIDs;
}
@@ -1428,6 +1429,18 @@ public:
return getFileID(Loc) == getMainFileID();
}
+ /// Returns whether \p Loc is located in a <built-in> file.
+ bool isWrittenInBuiltinFile(SourceLocation Loc) const {
+ StringRef Filename(getPresumedLoc(Loc).getFilename());
+ return Filename.equals("<built-in>");
+ }
+
+ /// Returns whether \p Loc is located in a <command line> file.
+ bool isWrittenInCommandLineFile(SourceLocation Loc) const {
+ StringRef Filename(getPresumedLoc(Loc).getFilename());
+ return Filename.equals("<command line>");
+ }
+
/// Returns if a SourceLocation is in a system header.
bool isInSystemHeader(SourceLocation Loc) const {
return isSystem(getFileCharacteristic(Loc));
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index cd8213f6cfd4..0af01e45437d 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -251,6 +251,7 @@ namespace clang {
CC_Swift, // __attribute__((swiftcall))
CC_PreserveMost, // __attribute__((preserve_most))
CC_PreserveAll, // __attribute__((preserve_all))
+ CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
};
/// Checks whether the given calling convention supports variadic
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 1517d741cb3c..9054fb11a6ff 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -93,6 +93,10 @@ def VAArgExpr : DStmt<Expr>;
def GenericSelectionExpr : DStmt<Expr>;
def PseudoObjectExpr : DStmt<Expr>;
+// Wrapper expressions
+def FullExpr : DStmt<Expr, 1>;
+def ConstantExpr : DStmt<FullExpr>;
+
// Atomic expressions
def AtomicExpr : DStmt<Expr>;
@@ -131,7 +135,7 @@ def DependentScopeDeclRefExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>;
def CXXInheritedCtorInitExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>;
-def ExprWithCleanups : DStmt<Expr>;
+def ExprWithCleanups : DStmt<FullExpr>;
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
def CXXUnresolvedConstructExpr : DStmt<Expr>;
def CXXDependentScopeMemberExpr : DStmt<Expr>;
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index 75a3811007cc..ab4b1c43f7cf 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -150,16 +150,6 @@ namespace clang {
};
}
- /// Nios2 builtins
- namespace Nios2 {
- enum {
- LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
-#include "clang/Basic/BuiltinsNios2.def"
- LastTSBuiltin
- };
- }
-
/// MIPS builtins
namespace Mips {
enum {
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 958b9106bc99..786b1c251ca8 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -312,6 +312,14 @@ public:
}
}
+ /// In the event this target uses the same number of fractional bits for its
+ /// unsigned types as it does with its signed counterparts, there will be
+ /// exactly one bit of padding.
+ /// Return true if unsigned fixed point types have padding for this target.
+ bool doUnsignedFixedPointTypesHavePadding() const {
+ return PaddingOnUnsignedFixedPoint;
+ }
+
/// Return the width (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntWidth().
@@ -1074,9 +1082,15 @@ public:
return false;
}
- /// Identify whether this taret supports multiversioning of functions,
+ /// Identify whether this target supports multiversioning of functions,
/// which requires support for cpu_supports and cpu_is functionality.
- virtual bool supportsMultiVersioning() const { return false; }
+ bool supportsMultiVersioning() const {
+ return getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64;
+ }
+
+ /// Identify whether this target supports IFuncs.
+ bool supportsIFunc() const { return getTriple().isOSBinFormatELF(); }
// Validate the contents of the __builtin_cpu_supports(const char*)
// argument.
@@ -1168,6 +1182,18 @@ public:
const LangASMap &getAddressSpaceMap() const { return *AddrSpaceMap; }
+ /// Map from the address space field in builtin description strings to the
+ /// language address space.
+ virtual LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const {
+ return getLangASFromTargetAS(AS);
+ }
+
+ /// Map from the address space field in builtin description strings to the
+ /// language address space.
+ virtual LangAS getCUDABuiltinAddressSpace(unsigned AS) const {
+ return getLangASFromTargetAS(AS);
+ }
+
/// Return an AST address space which can be used opportunistically
/// for constant global memory. It must be possible to convert pointers into
/// this address space to LangAS::Default. If no such address space exists,
@@ -1295,6 +1321,12 @@ public:
return None;
}
+ /// \returns The version of the SDK which was used during the compilation if
+ /// one was specified, or an empty version otherwise.
+ const llvm::VersionTuple &getSDKVersion() const {
+ return getTargetOpts().SDKVersion;
+ }
+
/// Check the target is valid after it is fully initialized.
virtual bool validateTarget(DiagnosticsEngine &Diags) const {
return true;
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index 31a674287915..fcccc5331a97 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -15,10 +15,11 @@
#ifndef LLVM_CLANG_BASIC_TARGETOPTIONS_H
#define LLVM_CLANG_BASIC_TARGETOPTIONS_H
-#include <string>
-#include <vector>
#include "clang/Basic/OpenCLOptions.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Target/TargetOptions.h"
+#include <string>
+#include <vector>
namespace clang {
@@ -67,6 +68,15 @@ public:
/// \brief If enabled, use 32-bit pointers for accessing const/local/shared
/// address space.
bool NVPTXUseShortPointers = false;
+
+ // The code model to be used as specified by the user. Corresponds to
+ // CodeModel::Model enum defined in include/llvm/Support/CodeGen.h, plus
+ // "default" for the case when the user has not explicitly specified a
+ // code model.
+ std::string CodeModel;
+
+ /// The version of the SDK which was used during the compilation.
+ llvm::VersionTuple SDKVersion;
};
} // end namespace clang
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 30cb022f1cba..e4616c9a6ab4 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -57,11 +57,8 @@
#ifndef CXX_KEYWORD_OPERATOR
#define CXX_KEYWORD_OPERATOR(X,Y)
#endif
-#ifndef OBJC1_AT_KEYWORD
-#define OBJC1_AT_KEYWORD(X)
-#endif
-#ifndef OBJC2_AT_KEYWORD
-#define OBJC2_AT_KEYWORD(X)
+#ifndef OBJC_AT_KEYWORD
+#define OBJC_AT_KEYWORD(X)
#endif
#ifndef TESTING_KEYWORD
#define TESTING_KEYWORD(X, L) KEYWORD(X, L)
@@ -579,15 +576,15 @@ ALIAS("__fp16", half , KEYALL)
KEYWORD(half , HALFSUPPORT)
// Objective-C ARC keywords.
-KEYWORD(__bridge , KEYARC)
-KEYWORD(__bridge_transfer , KEYARC)
-KEYWORD(__bridge_retained , KEYARC)
-KEYWORD(__bridge_retain , KEYARC)
+KEYWORD(__bridge , KEYOBJC)
+KEYWORD(__bridge_transfer , KEYOBJC)
+KEYWORD(__bridge_retained , KEYOBJC)
+KEYWORD(__bridge_retain , KEYOBJC)
// Objective-C keywords.
-KEYWORD(__covariant , KEYOBJC2)
-KEYWORD(__contravariant , KEYOBJC2)
-KEYWORD(__kindof , KEYOBJC2)
+KEYWORD(__covariant , KEYOBJC)
+KEYWORD(__contravariant , KEYOBJC)
+KEYWORD(__kindof , KEYOBJC)
// Alternate spelling for various tokens. There are GCC extensions in all
// languages, but should not be disabled in strict conformance mode.
@@ -677,34 +674,34 @@ TESTING_KEYWORD(__unknown_anytype , KEYALL)
// These have meaning after an '@' in Objective-C mode. These define enums in
// the tok::objc_* namespace.
-OBJC1_AT_KEYWORD(not_keyword)
-OBJC1_AT_KEYWORD(class)
-OBJC1_AT_KEYWORD(compatibility_alias)
-OBJC1_AT_KEYWORD(defs)
-OBJC1_AT_KEYWORD(encode)
-OBJC1_AT_KEYWORD(end)
-OBJC1_AT_KEYWORD(implementation)
-OBJC1_AT_KEYWORD(interface)
-OBJC1_AT_KEYWORD(private)
-OBJC1_AT_KEYWORD(protected)
-OBJC1_AT_KEYWORD(protocol)
-OBJC1_AT_KEYWORD(public)
-OBJC1_AT_KEYWORD(selector)
-OBJC1_AT_KEYWORD(throw)
-OBJC1_AT_KEYWORD(try)
-OBJC1_AT_KEYWORD(catch)
-OBJC1_AT_KEYWORD(finally)
-OBJC1_AT_KEYWORD(synchronized)
-OBJC1_AT_KEYWORD(autoreleasepool)
-
-OBJC2_AT_KEYWORD(property)
-OBJC2_AT_KEYWORD(package)
-OBJC2_AT_KEYWORD(required)
-OBJC2_AT_KEYWORD(optional)
-OBJC2_AT_KEYWORD(synthesize)
-OBJC2_AT_KEYWORD(dynamic)
-OBJC2_AT_KEYWORD(import)
-OBJC2_AT_KEYWORD(available)
+OBJC_AT_KEYWORD(not_keyword)
+OBJC_AT_KEYWORD(class)
+OBJC_AT_KEYWORD(compatibility_alias)
+OBJC_AT_KEYWORD(defs)
+OBJC_AT_KEYWORD(encode)
+OBJC_AT_KEYWORD(end)
+OBJC_AT_KEYWORD(implementation)
+OBJC_AT_KEYWORD(interface)
+OBJC_AT_KEYWORD(private)
+OBJC_AT_KEYWORD(protected)
+OBJC_AT_KEYWORD(protocol)
+OBJC_AT_KEYWORD(public)
+OBJC_AT_KEYWORD(selector)
+OBJC_AT_KEYWORD(throw)
+OBJC_AT_KEYWORD(try)
+OBJC_AT_KEYWORD(catch)
+OBJC_AT_KEYWORD(finally)
+OBJC_AT_KEYWORD(synchronized)
+OBJC_AT_KEYWORD(autoreleasepool)
+
+OBJC_AT_KEYWORD(property)
+OBJC_AT_KEYWORD(package)
+OBJC_AT_KEYWORD(required)
+OBJC_AT_KEYWORD(optional)
+OBJC_AT_KEYWORD(synthesize)
+OBJC_AT_KEYWORD(dynamic)
+OBJC_AT_KEYWORD(import)
+OBJC_AT_KEYWORD(available)
// TODO: What to do about context-sensitive keywords like:
// bycopy/byref/in/inout/oneway/out?
@@ -780,6 +777,11 @@ ANNOTATION(pragma_redefine_extname)
// handles them.
ANNOTATION(pragma_fp_contract)
+// Annotation for #pragma STDC FENV_ACCESS
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_fenv_access)
+
// Annotation for #pragma pointers_to_members...
// The lexer produces these so that they only take effect when the parser
// handles them.
@@ -823,8 +825,7 @@ ANNOTATION(module_end)
#undef ANNOTATION
#undef TESTING_KEYWORD
-#undef OBJC2_AT_KEYWORD
-#undef OBJC1_AT_KEYWORD
+#undef OBJC_AT_KEYWORD
#undef CXX_KEYWORD_OPERATOR
#undef PPKEYWORD
#undef ALIAS
diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
index fb4b5252b70b..e046f0027044 100644
--- a/include/clang/Basic/TokenKinds.h
+++ b/include/clang/Basic/TokenKinds.h
@@ -39,8 +39,7 @@ enum PPKeywordKind {
/// Provides a namespace for Objective-C keywords which start with
/// an '@'.
enum ObjCKeywordKind {
-#define OBJC1_AT_KEYWORD(X) objc_##X,
-#define OBJC2_AT_KEYWORD(X) objc_##X,
+#define OBJC_AT_KEYWORD(X) objc_##X,
#include "clang/Basic/TokenKinds.def"
NUM_OBJC_KEYWORDS
};
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index bdb426834a8c..8b8b2cbbd4a7 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -96,9 +96,15 @@ namespace clang {
/// Names for the "expression or type" traits.
enum UnaryExprOrTypeTrait {
UETT_SizeOf,
+ /// Used for C's _Alignof and C++'s alignof.
+ /// _Alignof and alignof return the required ABI alignment.
UETT_AlignOf,
UETT_VecStep,
UETT_OpenMPRequiredSimdAlign,
+ /// Used for GCC's __alignof.
+ /// __alignof returns the preferred alignment of a type, the alignment
+ /// clang will attempt to give an object of the type if allowed by ABI.
+ UETT_PreferredAlignOf,
};
}
diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h
deleted file mode 100644
index 2480b91123c1..000000000000
--- a/include/clang/Basic/VirtualFileSystem.h
+++ /dev/null
@@ -1,454 +0,0 @@
-//===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file
-/// Defines the virtual file system interface vfs::FileSystem.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
-#define LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Chrono.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/SourceMgr.h"
-#include <cassert>
-#include <cstdint>
-#include <ctime>
-#include <memory>
-#include <stack>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-
-class MemoryBuffer;
-
-} // namespace llvm
-
-namespace clang {
-namespace vfs {
-
-/// The result of a \p status operation.
-class Status {
- std::string Name;
- llvm::sys::fs::UniqueID UID;
- llvm::sys::TimePoint<> MTime;
- uint32_t User;
- uint32_t Group;
- uint64_t Size;
- llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::status_error;
- llvm::sys::fs::perms Perms;
-
-public:
- // FIXME: remove when files support multiple names
- bool IsVFSMapped = false;
-
- Status() = default;
- Status(const llvm::sys::fs::file_status &Status);
- Status(StringRef Name, llvm::sys::fs::UniqueID UID,
- llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
- uint64_t Size, llvm::sys::fs::file_type Type,
- llvm::sys::fs::perms Perms);
-
- /// Get a copy of a Status with a different name.
- static Status copyWithNewName(const Status &In, StringRef NewName);
- static Status copyWithNewName(const llvm::sys::fs::file_status &In,
- StringRef NewName);
-
- /// Returns the name that should be used for this file or directory.
- StringRef getName() const { return Name; }
-
- /// @name Status interface from llvm::sys::fs
- /// @{
- llvm::sys::fs::file_type getType() const { return Type; }
- llvm::sys::fs::perms getPermissions() const { return Perms; }
- llvm::sys::TimePoint<> getLastModificationTime() const { return MTime; }
- llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
- uint32_t getUser() const { return User; }
- uint32_t getGroup() const { return Group; }
- uint64_t getSize() const { return Size; }
- /// @}
- /// @name Status queries
- /// These are static queries in llvm::sys::fs.
- /// @{
- bool equivalent(const Status &Other) const;
- bool isDirectory() const;
- bool isRegularFile() const;
- bool isOther() const;
- bool isSymlink() const;
- bool isStatusKnown() const;
- bool exists() const;
- /// @}
-};
-
-/// Represents an open file.
-class File {
-public:
- /// Destroy the file after closing it (if open).
- /// Sub-classes should generally call close() inside their destructors. We
- /// cannot do that from the base class, since close is virtual.
- virtual ~File();
-
- /// Get the status of the file.
- virtual llvm::ErrorOr<Status> status() = 0;
-
- /// Get the name of the file
- virtual llvm::ErrorOr<std::string> getName() {
- if (auto Status = status())
- return Status->getName().str();
- else
- return Status.getError();
- }
-
- /// Get the contents of the file as a \p MemoryBuffer.
- virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBuffer(const Twine &Name, int64_t FileSize = -1,
- bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
-
- /// Closes the file.
- virtual std::error_code close() = 0;
-};
-
-namespace detail {
-
-/// An interface for virtual file systems to provide an iterator over the
-/// (non-recursive) contents of a directory.
-struct DirIterImpl {
- virtual ~DirIterImpl();
-
- /// Sets \c CurrentEntry to the next entry in the directory on success,
- /// or returns a system-defined \c error_code.
- virtual std::error_code increment() = 0;
-
- Status CurrentEntry;
-};
-
-} // namespace detail
-
-/// An input iterator over the entries in a virtual path, similar to
-/// llvm::sys::fs::directory_iterator.
-class directory_iterator {
- std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
-
-public:
- directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
- : Impl(std::move(I)) {
- assert(Impl.get() != nullptr && "requires non-null implementation");
- if (!Impl->CurrentEntry.isStatusKnown())
- Impl.reset(); // Normalize the end iterator to Impl == nullptr.
- }
-
- /// Construct an 'end' iterator.
- directory_iterator() = default;
-
- /// Equivalent to operator++, with an error code.
- directory_iterator &increment(std::error_code &EC) {
- assert(Impl && "attempting to increment past end");
- EC = Impl->increment();
- if (!Impl->CurrentEntry.isStatusKnown())
- Impl.reset(); // Normalize the end iterator to Impl == nullptr.
- return *this;
- }
-
- const Status &operator*() const { return Impl->CurrentEntry; }
- const Status *operator->() const { return &Impl->CurrentEntry; }
-
- bool operator==(const directory_iterator &RHS) const {
- if (Impl && RHS.Impl)
- return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry);
- return !Impl && !RHS.Impl;
- }
- bool operator!=(const directory_iterator &RHS) const {
- return !(*this == RHS);
- }
-};
-
-class FileSystem;
-
-/// An input iterator over the recursive contents of a virtual path,
-/// similar to llvm::sys::fs::recursive_directory_iterator.
-class recursive_directory_iterator {
- using IterState =
- std::stack<directory_iterator, std::vector<directory_iterator>>;
-
- FileSystem *FS;
- std::shared_ptr<IterState> State; // Input iterator semantics on copy.
-
-public:
- recursive_directory_iterator(FileSystem &FS, const Twine &Path,
- std::error_code &EC);
-
- /// Construct an 'end' iterator.
- recursive_directory_iterator() = default;
-
- /// Equivalent to operator++, with an error code.
- recursive_directory_iterator &increment(std::error_code &EC);
-
- const Status &operator*() const { return *State->top(); }
- const Status *operator->() const { return &*State->top(); }
-
- bool operator==(const recursive_directory_iterator &Other) const {
- return State == Other.State; // identity
- }
- bool operator!=(const recursive_directory_iterator &RHS) const {
- return !(*this == RHS);
- }
-
- /// Gets the current level. Starting path is at level 0.
- int level() const {
- assert(!State->empty() && "Cannot get level without any iteration state");
- return State->size()-1;
- }
-};
-
-/// The virtual file system interface.
-class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
-public:
- virtual ~FileSystem();
-
- /// Get the status of the entry at \p Path, if one exists.
- virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
-
- /// Get a \p File object for the file at \p Path, if one exists.
- virtual llvm::ErrorOr<std::unique_ptr<File>>
- openFileForRead(const Twine &Path) = 0;
-
- /// This is a convenience method that opens a file, gets its content and then
- /// closes the file.
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBufferForFile(const Twine &Name, int64_t FileSize = -1,
- bool RequiresNullTerminator = true, bool IsVolatile = false);
-
- /// Get a directory_iterator for \p Dir.
- /// \note The 'end' iterator is directory_iterator().
- virtual directory_iterator dir_begin(const Twine &Dir,
- std::error_code &EC) = 0;
-
- /// Set the working directory. This will affect all following operations on
- /// this file system and may propagate down for nested file systems.
- virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
-
- /// Get the working directory of this file system.
- virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
-
- /// Gets real path of \p Path e.g. collapse all . and .. patterns, resolve
- /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`.
- /// This returns errc::operation_not_permitted if not implemented by subclass.
- virtual std::error_code getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const;
-
- /// Check whether a file exists. Provided for convenience.
- bool exists(const Twine &Path);
-
- /// Make \a Path an absolute path.
- ///
- /// Makes \a Path absolute using the current directory if it is not already.
- /// An empty \a Path will result in the current directory.
- ///
- /// /absolute/path => /absolute/path
- /// relative/../path => <current-directory>/relative/../path
- ///
- /// \param Path A path that is modified to be an absolute path.
- /// \returns success if \a path has been made absolute, otherwise a
- /// platform-specific error_code.
- std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
-};
-
-/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
-/// the operating system.
-IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
-
-/// A file system that allows overlaying one \p AbstractFileSystem on top
-/// of another.
-///
-/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
-/// one merged file system. When there is a directory that exists in more than
-/// one file system, the \p OverlayFileSystem contains a directory containing
-/// the union of their contents. The attributes (permissions, etc.) of the
-/// top-most (most recently added) directory are used. When there is a file
-/// that exists in more than one file system, the file in the top-most file
-/// system overrides the other(s).
-class OverlayFileSystem : public FileSystem {
- using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>;
-
- /// The stack of file systems, implemented as a list in order of
- /// their addition.
- FileSystemList FSList;
-
-public:
- OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base);
-
- /// Pushes a file system on top of the stack.
- void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
-
- llvm::ErrorOr<Status> status(const Twine &Path) override;
- llvm::ErrorOr<std::unique_ptr<File>>
- openFileForRead(const Twine &Path) override;
- directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
- llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
- std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
- std::error_code getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const override;
-
- using iterator = FileSystemList::reverse_iterator;
- using const_iterator = FileSystemList::const_reverse_iterator;
-
- /// Get an iterator pointing to the most recently added file system.
- iterator overlays_begin() { return FSList.rbegin(); }
- const_iterator overlays_begin() const { return FSList.rbegin(); }
-
- /// Get an iterator pointing one-past the least recently added file
- /// system.
- iterator overlays_end() { return FSList.rend(); }
- const_iterator overlays_end() const { return FSList.rend(); }
-};
-
-namespace detail {
-
-class InMemoryDirectory;
-
-} // namespace detail
-
-/// An in-memory file system.
-class InMemoryFileSystem : public FileSystem {
- std::unique_ptr<detail::InMemoryDirectory> Root;
- std::string WorkingDirectory;
- bool UseNormalizedPaths = true;
-
-public:
- explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
- ~InMemoryFileSystem() override;
-
- /// Add a file containing a buffer or a directory to the VFS with a
- /// path. The VFS owns the buffer. If present, User, Group, Type
- /// and Perms apply to the newly-created file or directory.
- /// \return true if the file or directory was successfully added,
- /// false if the file or directory already exists in the file system with
- /// different contents.
- bool addFile(const Twine &Path, time_t ModificationTime,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- Optional<uint32_t> User = None, Optional<uint32_t> Group = None,
- Optional<llvm::sys::fs::file_type> Type = None,
- Optional<llvm::sys::fs::perms> Perms = None);
-
- /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
- /// If present, User, Group, Type and Perms apply to the newly-created file
- /// or directory.
- /// \return true if the file or directory was successfully added,
- /// false if the file or directory already exists in the file system with
- /// different contents.
- bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
- llvm::MemoryBuffer *Buffer,
- Optional<uint32_t> User = None,
- Optional<uint32_t> Group = None,
- Optional<llvm::sys::fs::file_type> Type = None,
- Optional<llvm::sys::fs::perms> Perms = None);
-
- std::string toString() const;
-
- /// Return true if this file system normalizes . and .. in paths.
- bool useNormalizedPaths() const { return UseNormalizedPaths; }
-
- llvm::ErrorOr<Status> status(const Twine &Path) override;
- llvm::ErrorOr<std::unique_ptr<File>>
- openFileForRead(const Twine &Path) override;
- directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
-
- llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
- return WorkingDirectory;
- }
- /// Canonicalizes \p Path by combining with the current working
- /// directory and normalizing the path (e.g. remove dots). If the current
- /// working directory is not set, this returns errc::operation_not_permitted.
- ///
- /// This doesn't resolve symlinks as they are not supported in in-memory file
- /// system.
- std::error_code getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const override;
-
- std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
-};
-
-/// Get a globally unique ID for a virtual file or directory.
-llvm::sys::fs::UniqueID getNextVirtualUniqueID();
-
-/// Gets a \p FileSystem for a virtual file system described in YAML
-/// format.
-IntrusiveRefCntPtr<FileSystem>
-getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
- llvm::SourceMgr::DiagHandlerTy DiagHandler,
- StringRef YAMLFilePath,
- void *DiagContext = nullptr,
- IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
-
-struct YAMLVFSEntry {
- template <typename T1, typename T2> YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
- : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
- std::string VPath;
- std::string RPath;
-};
-
-/// Collect all pairs of <virtual path, real path> entries from the
-/// \p YAMLFilePath. This is used by the module dependency collector to forward
-/// the entries into the reproducer output VFS YAML file.
-void collectVFSFromYAML(
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
- SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
- void *DiagContext = nullptr,
- IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
-
-class YAMLVFSWriter {
- std::vector<YAMLVFSEntry> Mappings;
- Optional<bool> IsCaseSensitive;
- Optional<bool> IsOverlayRelative;
- Optional<bool> UseExternalNames;
- Optional<bool> IgnoreNonExistentContents;
- std::string OverlayDir;
-
-public:
- YAMLVFSWriter() = default;
-
- void addFileMapping(StringRef VirtualPath, StringRef RealPath);
-
- void setCaseSensitivity(bool CaseSensitive) {
- IsCaseSensitive = CaseSensitive;
- }
-
- void setUseExternalNames(bool UseExtNames) {
- UseExternalNames = UseExtNames;
- }
-
- void setIgnoreNonExistentContents(bool IgnoreContents) {
- IgnoreNonExistentContents = IgnoreContents;
- }
-
- void setOverlayDir(StringRef OverlayDirectory) {
- IsOverlayRelative = true;
- OverlayDir.assign(OverlayDirectory.str());
- }
-
- void write(llvm::raw_ostream &OS);
-};
-
-} // namespace vfs
-} // namespace clang
-
-#endif // LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
diff --git a/include/clang/Basic/X86Target.def b/include/clang/Basic/X86Target.def
index d2d2540e5005..8c203c4db21e 100644
--- a/include/clang/Basic/X86Target.def
+++ b/include/clang/Basic/X86Target.def
@@ -154,6 +154,10 @@ PROC_WITH_FEAT(SkylakeClient, "skylake", PROC_64_BIT, FEATURE_AVX2)
PROC_WITH_FEAT(SkylakeServer, "skylake-avx512", PROC_64_BIT, FEATURE_AVX512F)
PROC_ALIAS(SkylakeServer, "skx")
+/// \name Cascadelake Server
+/// Cascadelake Server microarchitecture based processors.
+PROC_WITH_FEAT(Cascadelake, "cascadelake", PROC_64_BIT, FEATURE_AVX512VNNI)
+
/// \name Cannonlake Client
/// Cannonlake client microarchitecture based processors.
PROC_WITH_FEAT(Cannonlake, "cannonlake", PROC_64_BIT, FEATURE_AVX512VBMI)
@@ -283,6 +287,11 @@ FEATURE(FEATURE_AVX512IFMA)
FEATURE(FEATURE_AVX5124VNNIW)
FEATURE(FEATURE_AVX5124FMAPS)
FEATURE(FEATURE_AVX512VPOPCNTDQ)
+FEATURE(FEATURE_AVX512VBMI2)
+FEATURE(FEATURE_GFNI)
+FEATURE(FEATURE_VPCLMULQDQ)
+FEATURE(FEATURE_AVX512VNNI)
+FEATURE(FEATURE_AVX512BITALG)
// FIXME: When commented out features are supported in LLVM, enable them here.
diff --git a/include/clang/Basic/XRayInstr.h b/include/clang/Basic/XRayInstr.h
index 13c3032a5cca..6efefcb33ac8 100644
--- a/include/clang/Basic/XRayInstr.h
+++ b/include/clang/Basic/XRayInstr.h
@@ -60,6 +60,8 @@ struct XRayInstrSet {
bool empty() const { return Mask == 0; }
+ bool full() const { return Mask == XRayInstrKind::All; }
+
XRayInstrMask Mask = 0;
};
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index c35336166c39..af049be7e295 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -206,6 +206,15 @@ def OP_DOT_LNQ
: Op<(call "vdot", $p0, $p1,
(bitcast $p1, (splat(bitcast "uint32x4_t", $p2), $p3)))>;
+def OP_FMLAL_LN : Op<(call "vfmlal_low", $p0, $p1,
+ (dup_typed $p1, (call "vget_lane", $p2, $p3)))>;
+def OP_FMLSL_LN : Op<(call "vfmlsl_low", $p0, $p1,
+ (dup_typed $p1, (call "vget_lane", $p2, $p3)))>;
+def OP_FMLAL_LN_Hi : Op<(call "vfmlal_high", $p0, $p1,
+ (dup_typed $p1, (call "vget_lane", $p2, $p3)))>;
+def OP_FMLSL_LN_Hi : Op<(call "vfmlsl_high", $p0, $p1,
+ (dup_typed $p1, (call "vget_lane", $p2, $p3)))>;
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -337,48 +346,78 @@ def VSLI_N : WInst<"vsli_n", "dddi",
////////////////////////////////////////////////////////////////////////////////
// E.3.14 Loads and stores of a single vector
def VLD1 : WInst<"vld1", "dc",
- "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+ "QUcQUsQUiQUlQcQsQiQlQfQPcQPsUcUsUiUlcsilfPcPs">;
def VLD1_X2 : WInst<"vld1_x2", "2c",
- "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+ "cfilsUcUiUlUsQcQfQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VLD1_X3 : WInst<"vld1_x3", "3c",
- "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+ "cfilsUcUiUlUsQcQfQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VLD1_X4 : WInst<"vld1_x4", "4c",
- "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+ "cfilsUcUiUlUsQcQfQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VLD1_LANE : WInst<"vld1_lane", "dcdi",
- "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+ "QUcQUsQUiQUlQcQsQiQlQfQPcQPsUcUsUiUlcsilfPcPs">;
def VLD1_DUP : WInst<"vld1_dup", "dc",
- "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+ "QUcQUsQUiQUlQcQsQiQlQfQPcQPsUcUsUiUlcsilfPcPs">;
def VST1 : WInst<"vst1", "vpd",
- "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+ "QUcQUsQUiQUlQcQsQiQlQfQPcQPsUcUsUiUlcsilfPcPs">;
def VST1_X2 : WInst<"vst1_x2", "vp2",
- "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+ "cfilsUcUiUlUsQcQfQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VST1_X3 : WInst<"vst1_x3", "vp3",
- "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+ "cfilsUcUiUlUsQcQfQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VST1_X4 : WInst<"vst1_x4", "vp4",
- "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
+ "cfilsUcUiUlUsQcQfQiQlQsQUcQUiQUlQUsPcPsQPcQPs">;
def VST1_LANE : WInst<"vst1_lane", "vpdi",
- "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+ "QUcQUsQUiQUlQcQsQiQlQfQPcQPsUcUsUiUlcsilfPcPs">;
+let ArchGuard = "(__ARM_FP & 2)" in {
+def VLD1_F16 : WInst<"vld1", "dc", "hQh">;
+def VLD1_X2_F16 : WInst<"vld1_x2", "2c", "hQh">;
+def VLD1_X3_F16 : WInst<"vld1_x3", "3c", "hQh">;
+def VLD1_X4_F16 : WInst<"vld1_x4", "4c", "hQh">;
+def VLD1_LANE_F16 : WInst<"vld1_lane", "dcdi", "hQh">;
+def VLD1_DUP_F16 : WInst<"vld1_dup", "dc", "hQh">;
+def VST1_F16 : WInst<"vst1", "vpd", "hQh">;
+def VST1_X2_F16 : WInst<"vst1_x2", "vp2", "hQh">;
+def VST1_X3_F16 : WInst<"vst1_x3", "vp3", "hQh">;
+def VST1_X4_F16 : WInst<"vst1_x4", "vp4", "hQh">;
+def VST1_LANE_F16 : WInst<"vst1_lane", "vpdi", "hQh">;
+}
////////////////////////////////////////////////////////////////////////////////
// E.3.15 Loads and stores of an N-element structure
-def VLD2 : WInst<"vld2", "2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD3 : WInst<"vld3", "3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD4 : WInst<"vld4", "4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD2 : WInst<"vld2", "2c", "QUcQUsQUiQcQsQiQfQPcQPsUcUsUiUlcsilfPcPs">;
+def VLD3 : WInst<"vld3", "3c", "QUcQUsQUiQcQsQiQfQPcQPsUcUsUiUlcsilfPcPs">;
+def VLD4 : WInst<"vld4", "4c", "QUcQUsQUiQcQsQiQfQPcQPsUcUsUiUlcsilfPcPs">;
def VLD2_DUP : WInst<"vld2_dup", "2c",
- "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">;
+ "UcUsUiUlcsilfPcPsQcQfQiQlQsQPcQPsQUcQUiQUlQUs">;
def VLD3_DUP : WInst<"vld3_dup", "3c",
- "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">;
+ "UcUsUiUlcsilfPcPsQcQfQiQlQsQPcQPsQUcQUiQUlQUs">;
def VLD4_DUP : WInst<"vld4_dup", "4c",
- "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">;
-def VLD2_LANE : WInst<"vld2_lane", "2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VLD3_LANE : WInst<"vld3_lane", "3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VLD4_LANE : WInst<"vld4_lane", "4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VST2 : WInst<"vst2", "vp2", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST3 : WInst<"vst3", "vp3", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST4 : WInst<"vst4", "vp4", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST2_LANE : WInst<"vst2_lane", "vp2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VST3_LANE : WInst<"vst3_lane", "vp3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VST4_LANE : WInst<"vst4_lane", "vp4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+ "UcUsUiUlcsilfPcPsQcQfQiQlQsQPcQPsQUcQUiQUlQUs">;
+def VLD2_LANE : WInst<"vld2_lane", "2c2i", "QUsQUiQsQiQfQPsUcUsUicsifPcPs">;
+def VLD3_LANE : WInst<"vld3_lane", "3c3i", "QUsQUiQsQiQfQPsUcUsUicsifPcPs">;
+def VLD4_LANE : WInst<"vld4_lane", "4c4i", "QUsQUiQsQiQfQPsUcUsUicsifPcPs">;
+def VST2 : WInst<"vst2", "vp2", "QUcQUsQUiQcQsQiQfQPcQPsUcUsUiUlcsilfPcPs">;
+def VST3 : WInst<"vst3", "vp3", "QUcQUsQUiQcQsQiQfQPcQPsUcUsUiUlcsilfPcPs">;
+def VST4 : WInst<"vst4", "vp4", "QUcQUsQUiQcQsQiQfQPcQPsUcUsUiUlcsilfPcPs">;
+def VST2_LANE : WInst<"vst2_lane", "vp2i", "QUsQUiQsQiQfQPsUcUsUicsifPcPs">;
+def VST3_LANE : WInst<"vst3_lane", "vp3i", "QUsQUiQsQiQfQPsUcUsUicsifPcPs">;
+def VST4_LANE : WInst<"vst4_lane", "vp4i", "QUsQUiQsQiQfQPsUcUsUicsifPcPs">;
+let ArchGuard = "(__ARM_FP & 2)" in {
+def VLD2_F16 : WInst<"vld2", "2c", "hQh">;
+def VLD3_F16 : WInst<"vld3", "3c", "hQh">;
+def VLD4_F16 : WInst<"vld4", "4c", "hQh">;
+def VLD2_DUP_F16 : WInst<"vld2_dup", "2c", "hQh">;
+def VLD3_DUP_F16 : WInst<"vld3_dup", "3c", "hQh">;
+def VLD4_DUP_F16 : WInst<"vld4_dup", "4c", "hQh">;
+def VLD2_LANE_F16 : WInst<"vld2_lane", "2c2i", "hQh">;
+def VLD3_LANE_F16 : WInst<"vld3_lane", "3c3i", "hQh">;
+def VLD4_LANE_F16 : WInst<"vld4_lane", "4c4i", "hQh">;
+def VST2_F16 : WInst<"vst2", "vp2", "hQh">;
+def VST3_F16 : WInst<"vst3", "vp3", "hQh">;
+def VST4_F16 : WInst<"vst4", "vp4", "hQh">;
+def VST2_LANE_F16 : WInst<"vst2_lane", "vp2i", "hQh">;
+def VST3_LANE_F16 : WInst<"vst3_lane", "vp3i", "hQh">;
+def VST4_LANE_F16 : WInst<"vst4_lane", "vp4i", "hQh">;
+}
////////////////////////////////////////////////////////////////////////////////
// E.3.16 Extract lanes from a vector
@@ -1610,3 +1649,21 @@ let ArchGuard = "defined(__ARM_FEATURE_DOTPROD) && defined(__aarch64__)" in {
// Variants indexing into a 128-bit vector are A64 only.
def UDOT_LANEQ : SOpInst<"vdot_laneq", "dd89i", "iUiQiQUi", OP_DOT_LNQ>;
}
+
+// v8.2-A FP16 fused multiply-add long instructions.
+let ArchGuard = "defined(__ARM_FEATURE_FP16FML) && defined(__aarch64__)" in {
+ def VFMLAL_LOW : SInst<"vfmlal_low", "ffHH", "UiQUi">;
+ def VFMLSL_LOW : SInst<"vfmlsl_low", "ffHH", "UiQUi">;
+ def VFMLAL_HIGH : SInst<"vfmlal_high", "ffHH", "UiQUi">;
+ def VFMLSL_HIGH : SInst<"vfmlsl_high", "ffHH", "UiQUi">;
+
+ def VFMLAL_LANE_LOW : SOpInst<"vfmlal_lane_low", "ffH0i", "UiQUi", OP_FMLAL_LN>;
+ def VFMLSL_LANE_LOW : SOpInst<"vfmlsl_lane_low", "ffH0i", "UiQUi", OP_FMLSL_LN>;
+ def VFMLAL_LANE_HIGH : SOpInst<"vfmlal_lane_high", "ffH0i", "UiQUi", OP_FMLAL_LN_Hi>;
+ def VFMLSL_LANE_HIGH : SOpInst<"vfmlsl_lane_high", "ffH0i", "UiQUi", OP_FMLSL_LN_Hi>;
+
+ def VFMLAL_LANEQ_LOW : SOpInst<"vfmlal_laneq_low", "ffH1i", "UiQUi", OP_FMLAL_LN>;
+ def VFMLSL_LANEQ_LOW : SOpInst<"vfmlsl_laneq_low", "ffH1i", "UiQUi", OP_FMLSL_LN>;
+ def VFMLAL_LANEQ_HIGH : SOpInst<"vfmlal_laneq_high", "ffH1i", "UiQUi", OP_FMLAL_LN_Hi>;
+ def VFMLSL_LANEQ_HIGH : SOpInst<"vfmlsl_laneq_high", "ffH1i", "UiQUi", OP_FMLSL_LN_Hi>;
+}
diff --git a/include/clang/Basic/arm_neon_incl.td b/include/clang/Basic/arm_neon_incl.td
index 5f3aa6fc0221..09df22ea5ca2 100644
--- a/include/clang/Basic/arm_neon_incl.td
+++ b/include/clang/Basic/arm_neon_incl.td
@@ -96,6 +96,11 @@ def bitcast;
// example: (dup $p1) -> "(uint32x2_t) {__p1, __p1}" (assuming the base type
// is uint32x2_t).
def dup;
+// dup_typed - Take a vector and a scalar argument, and create a new vector of
+// the same type by duplicating the scalar value into all lanes.
+// example: (dup_typed $p1, $p2) -> "(float16x4_t) {__p2, __p2, __p2, __p2}"
+// (assuming __p1 is float16x4_t, and __p2 is a compatible scalar).
+def dup_typed;
// splat - Take a vector and a lane index, and return a vector of the same type
// containing repeated instances of the source vector at the lane index.
// example: (splat $p0, $p1) ->
@@ -229,6 +234,8 @@ def OP_UNAVAILABLE : Operation {
// f: float (int args)
// F: double (int args)
// H: half (int args)
+// 0: half (int args), ignore 'Q' size modifier.
+// 1: half (int args), force 'Q' size modifier.
// d: default
// g: default, ignore 'Q' size modifier.
// j: default, force 'Q' size modifier.
diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
index cf64e9f3eeff..58d1f0d71c74 100644
--- a/include/clang/CodeGen/CGFunctionInfo.h
+++ b/include/clang/CodeGen/CGFunctionInfo.h
@@ -581,11 +581,11 @@ public:
typedef ArgInfo *arg_iterator;
typedef llvm::iterator_range<arg_iterator> arg_range;
- typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
+ typedef llvm::iterator_range<const_arg_iterator> const_arg_range;
arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
- arg_const_range arguments() const {
- return arg_const_range(arg_begin(), arg_end());
+ const_arg_range arguments() const {
+ return const_arg_range(arg_begin(), arg_end());
}
const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
diff --git a/include/clang/CodeGen/SwiftCallingConv.h b/include/clang/CodeGen/SwiftCallingConv.h
index 45b3145ed9f1..5aa9be2d67c1 100644
--- a/include/clang/CodeGen/SwiftCallingConv.h
+++ b/include/clang/CodeGen/SwiftCallingConv.h
@@ -114,6 +114,9 @@ private:
void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
void addEntry(llvm::Type *type, CharUnits begin, CharUnits end);
void splitVectorEntry(unsigned index);
+ static bool shouldMergeEntries(const StorageEntry &first,
+ const StorageEntry &second,
+ CharUnits chunkSize);
};
/// Should an aggregate which expands to the given type sequence
diff --git a/include/clang/CrossTU/CrossTUDiagnostic.h b/include/clang/CrossTU/CrossTUDiagnostic.h
index dad38309fd1a..56c83a5ad25c 100644
--- a/include/clang/CrossTU/CrossTUDiagnostic.h
+++ b/include/clang/CrossTU/CrossTUDiagnostic.h
@@ -10,20 +10,6 @@
#ifndef LLVM_CLANG_CROSSTU_CROSSTUDIAGNOSTIC_H
#define LLVM_CLANG_CROSSTU_CROSSTUDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticCrossTU.h"
-namespace clang {
-namespace diag {
-enum {
-#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, CATEGORY) \
- ENUM,
-#define CROSSTUSTART
-#include "clang/Basic/DiagnosticCrossTUKinds.inc"
-#undef DIAG
- NUM_BUILTIN_CROSSTU_DIAGNOSTICS
-};
-} // end namespace diag
-} // end namespace clang
-
-#endif // LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H
+#endif // LLVM_CLANG_CROSSTU_CROSSTUDIAGNOSTIC_H
diff --git a/include/clang/CrossTU/CrossTranslationUnit.h b/include/clang/CrossTU/CrossTranslationUnit.h
index 041f1a8eea59..52e3ae27490f 100644
--- a/include/clang/CrossTU/CrossTranslationUnit.h
+++ b/include/clang/CrossTU/CrossTranslationUnit.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
#define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
+#include "clang/AST/ASTImporterLookupTable.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -41,7 +42,9 @@ enum class index_error_code {
missing_definition,
failed_import,
failed_to_get_external_ast,
- failed_to_generate_usr
+ failed_to_generate_usr,
+ triple_mismatch,
+ lang_mismatch
};
class IndexError : public llvm::ErrorInfo<IndexError> {
@@ -50,16 +53,25 @@ public:
IndexError(index_error_code C) : Code(C), LineNo(0) {}
IndexError(index_error_code C, std::string FileName, int LineNo = 0)
: Code(C), FileName(std::move(FileName)), LineNo(LineNo) {}
+ IndexError(index_error_code C, std::string FileName, std::string TripleToName,
+ std::string TripleFromName)
+ : Code(C), FileName(std::move(FileName)),
+ TripleToName(std::move(TripleToName)),
+ TripleFromName(std::move(TripleFromName)) {}
void log(raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
index_error_code getCode() const { return Code; }
int getLineNum() const { return LineNo; }
std::string getFileName() const { return FileName; }
+ std::string getTripleToName() const { return TripleToName; }
+ std::string getTripleFromName() const { return TripleFromName; }
private:
index_error_code Code;
std::string FileName;
int LineNo;
+ std::string TripleToName;
+ std::string TripleFromName;
};
/// This function parses an index file that determines which
@@ -78,11 +90,11 @@ std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index);
/// This class is used for tools that requires cross translation
/// unit capability.
///
-/// This class can load function definitions from external AST files.
+/// This class can load definitions from external AST files.
/// The loaded definition will be merged back to the original AST using the
/// AST Importer.
/// In order to use this class, an index file is required that describes
-/// the locations of the AST files for each function definition.
+/// the locations of the AST files for each definition.
///
/// Note that this class also implements caching.
class CrossTranslationUnitContext {
@@ -108,7 +120,7 @@ public:
/// Note that the AST files should also be in the \p CrossTUDir.
llvm::Expected<const FunctionDecl *>
getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir,
- StringRef IndexName);
+ StringRef IndexName, bool DisplayCTUProgress = false);
/// This function loads a function definition from an external AST
/// file.
@@ -118,13 +130,15 @@ public:
/// \p IndexName. In case the declaration is found in the index the
/// corresponding AST file will be loaded.
///
- /// \return Returns an ASTUnit that contains the definition of the looked up
- /// function.
+ /// \return Returns a pointer to the ASTUnit that contains the definition of
+ /// the looked up function or an Error.
+ /// The returned pointer is never a nullptr.
///
/// Note that the AST files should also be in the \p CrossTUDir.
llvm::Expected<ASTUnit *> loadExternalAST(StringRef LookupName,
StringRef CrossTUDir,
- StringRef IndexName);
+ StringRef IndexName,
+ bool DisplayCTUProgress = false);
/// This function merges a definition from a separate AST Unit into
/// the current one which was created by the compiler instance that
@@ -140,6 +154,7 @@ public:
void emitCrossTUDiagnostics(const IndexError &IE);
private:
+ void lazyInitLookupTable(TranslationUnitDecl *ToTU);
ASTImporter &getOrCreateASTImporter(ASTContext &From);
const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC,
StringRef LookupFnName);
@@ -151,6 +166,7 @@ private:
ASTUnitImporterMap;
CompilerInstance &CI;
ASTContext &Context;
+ std::unique_ptr<ASTImporterLookupTable> LookupTable;
};
} // namespace cross_tu
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 723fbbed3598..f4aaa6c544ac 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -59,6 +59,7 @@ public:
OffloadClass,
PreprocessJobClass,
PrecompileJobClass,
+ HeaderModulePrecompileJobClass,
AnalyzeJobClass,
MigrateJobClass,
CompileJobClass,
@@ -398,12 +399,36 @@ public:
class PrecompileJobAction : public JobAction {
void anchor() override;
+protected:
+ PrecompileJobAction(ActionClass Kind, Action *Input, types::ID OutputType);
+
public:
PrecompileJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
- return A->getKind() == PrecompileJobClass;
+ return A->getKind() == PrecompileJobClass ||
+ A->getKind() == HeaderModulePrecompileJobClass;
+ }
+};
+
+class HeaderModulePrecompileJobAction : public PrecompileJobAction {
+ void anchor() override;
+
+ const char *ModuleName;
+
+public:
+ HeaderModulePrecompileJobAction(Action *Input, types::ID OutputType,
+ const char *ModuleName);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == HeaderModulePrecompileJobClass;
}
+
+ void addModuleHeaderInput(Action *Input) {
+ getInputs().push_back(Input);
+ }
+
+ const char *getModuleName() const { return ModuleName; }
};
class AnalyzeJobAction : public JobAction {
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 672231e70fad..07c76884063f 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -27,6 +27,8 @@ def triple : Separate<["-"], "triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
def target_abi : Separate<["-"], "target-abi">,
HelpText<"Target a particular ABI type">;
+def target_sdk_version_EQ : Joined<["-"], "target-sdk-version=">,
+ HelpText<"The version of target SDK used for compilation">;
}
@@ -76,14 +78,13 @@ def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">,
def analyze_function : Separate<["-"], "analyze-function">,
HelpText<"Run analysis on specific function (for C++ include parameters in name)">;
def analyze_function_EQ : Joined<["-"], "analyze-function=">, Alias<analyze_function>;
-def analyzer_eagerly_assume : Flag<["-"], "analyzer-eagerly-assume">,
- HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
def trim_egraph : Flag<["-"], "trim-egraph">,
HelpText<"Only show error-related paths in the analysis graph">;
def analyzer_viz_egraph_graphviz : Flag<["-"], "analyzer-viz-egraph-graphviz">,
HelpText<"Display exploded graph using GraphViz">;
-def analyzer_viz_egraph_ubigraph : Flag<["-"], "analyzer-viz-egraph-ubigraph">,
- HelpText<"Display exploded graph using Ubigraph">;
+def analyzer_dump_egraph : Separate<["-"], "analyzer-dump-egraph">,
+ HelpText<"Dump exploded graph to the specified file">;
+def analyzer_dump_egraph_EQ : Joined<["-"], "analyzer-dump-egraph=">, Alias<analyzer_dump_egraph>;
def analyzer_inline_max_stack_depth : Separate<["-"], "analyzer-inline-max-stack-depth">,
HelpText<"Bound on stack depth while inlining (4 by default)">;
@@ -107,11 +108,11 @@ def analyzer_checker : Separate<["-"], "analyzer-checker">,
ValuesCode<[{
const char *Values =
#define GET_CHECKERS
- #define CHECKER(FULLNAME, CLASS, DESCFILE, HT, G, H) FULLNAME ","
+ #define CHECKER(FULLNAME, CLASS, HT, DOC_URI) FULLNAME ","
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef GET_CHECKERS
#define GET_PACKAGES
- #define PACKAGE(FULLNAME, G, D) FULLNAME ","
+ #define PACKAGE(FULLNAME) FULLNAME ","
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef GET_PACKAGES
;
@@ -130,12 +131,21 @@ def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">,
def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">,
HelpText<"Display the list of analyzer checkers that are available">;
+def analyzer_config_help : Flag<["-"], "analyzer-config-help">,
+ HelpText<"Display the list of -analyzer-config options">;
+
def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">,
HelpText<"Display the list of enabled analyzer checkers">;
def analyzer_config : Separate<["-"], "analyzer-config">,
HelpText<"Choose analyzer options to enable">;
+def analyzer_config_compatibility_mode : Separate<["-"], "analyzer-config-compatibility-mode">,
+ HelpText<"Don't emit errors on invalid analyzer-config inputs">;
+
+def analyzer_config_compatibility_mode_EQ : Joined<["-"], "analyzer-config-compatibility-mode=">,
+ Alias<analyzer_config_compatibility_mode>;
+
//===----------------------------------------------------------------------===//
// Migrator Options
//===----------------------------------------------------------------------===//
@@ -153,12 +163,16 @@ let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
def debug_info_macro : Flag<["-"], "debug-info-macro">,
HelpText<"Emit macro debug information">;
+def default_function_attr : Separate<["-"], "default-function-attr">,
+ HelpText<"Apply given attribute to all functions">;
def dwarf_version_EQ : Joined<["-"], "dwarf-version=">;
def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">;
def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
HelpText<"The compilation directory to embed in the debug info.">;
def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
HelpText<"The string to embed in the Dwarf debug flags record.">;
+def record_command_line : Separate<["-"], "record-command-line">,
+ HelpText<"The string to embed in the .LLVM.command.line section.">;
def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">,
HelpText<"DWARF debug sections compression">;
def compress_debug_sections_EQ : Joined<["-"], "compress-debug-sections=">,
@@ -197,10 +211,6 @@ def dwarf_column_info : Flag<["-"], "dwarf-column-info">,
HelpText<"Turn on column location information.">;
def split_dwarf : Flag<["-"], "split-dwarf">,
HelpText<"Split out the dwarf .dwo sections">;
-def gnu_pubnames : Flag<["-"], "gnu-pubnames">,
- HelpText<"Emit newer GNU style pubnames">;
-def arange_sections : Flag<["-"], "arange_sections">,
- HelpText<"Emit DWARF .debug_arange sections">;
def dwarf_ext_refs : Flag<["-"], "dwarf-ext-refs">,
HelpText<"Generate debug info with external references to clang modules"
" or precompiled headers">;
@@ -253,7 +263,7 @@ def new_struct_path_tbaa : Flag<["-"], "new-struct-path-tbaa">,
def masm_verbose : Flag<["-"], "masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<["-"], "mcode-model">,
- HelpText<"The code model to use">, Values<"small,kernel,medium,large">;
+ HelpText<"The code model to use">, Values<"tiny,small,kernel,medium,large">;
def mdebug_pass : Separate<["-"], "mdebug-pass">,
HelpText<"Enable additional debug output">;
def mdisable_fp_elim : Flag<["-"], "mdisable-fp-elim">,
@@ -287,9 +297,11 @@ def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">,
HelpText<"Emit complete constructors and destructors as aliases when possible">;
def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
HelpText<"Link the given bitcode file before performing optimizations.">;
-def mlink_cuda_bitcode : Separate<["-"], "mlink-cuda-bitcode">,
+def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">,
HelpText<"Link and internalize needed symbols from the given bitcode file "
"before performing optimizations.">;
+def mlink_cuda_bitcode : Separate<["-"], "mlink-cuda-bitcode">,
+ Alias<mlink_builtin_bitcode>;
def vectorize_loops : Flag<["-"], "vectorize-loops">,
HelpText<"Run the Loop vectorization passes">;
def vectorize_slp : Flag<["-"], "vectorize-slp">,
@@ -357,6 +369,13 @@ def fdebug_pass_manager : Flag<["-"], "fdebug-pass-manager">,
HelpText<"Prints debug information for the new pass manager">;
def fno_debug_pass_manager : Flag<["-"], "fno-debug-pass-manager">,
HelpText<"Disables debug printing for the new pass manager">;
+// The driver option takes the key as a parameter to the -msign-return-address=
+// and -mbranch-protection= options, but CC1 has a separate option so we
+// don't have to parse the parameter twice.
+def msign_return_address_key_EQ : Joined<["-"], "msign-return-address-key=">,
+ Values<"a_key,b_key">;
+def mbranch_target_enforce : Flag<["-"], "mbranch-target-enforce">;
+def fno_dllexport_inlines : Flag<["-"], "fno-dllexport-inlines">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
@@ -543,14 +562,12 @@ def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">,
HelpText<"Build ASTs and then debug dump their name lookup tables">;
def ast_view : Flag<["-"], "ast-view">,
HelpText<"Build ASTs and view them with GraphViz">;
-def print_decl_contexts : Flag<["-"], "print-decl-contexts">,
- HelpText<"Print DeclContexts and their Decls">;
def emit_module : Flag<["-"], "emit-module">,
HelpText<"Generate pre-compiled module file from a module map">;
def emit_module_interface : Flag<["-"], "emit-module-interface">,
HelpText<"Generate pre-compiled module file from a C++ module interface">;
-def emit_pth : Flag<["-"], "emit-pth">,
- HelpText<"Generate pre-tokenized header file">;
+def emit_header_module : Flag<["-"], "emit-header-module">,
+ HelpText<"Generate pre-compiled module file from a set of header files">;
def emit_pch : Flag<["-"], "emit-pch">,
HelpText<"Generate pre-compiled header file">;
def emit_llvm_bc : Flag<["-"], "emit-llvm-bc">,
@@ -610,6 +627,10 @@ def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">,
def pch_through_header_EQ : Joined<["-"], "pch-through-header=">,
HelpText<"Stop PCH generation after including this file. When using a PCH, "
"skip tokens until after this file is included.">;
+def pch_through_hdrstop_create : Flag<["-"], "pch-through-hdrstop-create">,
+ HelpText<"When creating a PCH, stop PCH generation after #pragma hdrstop.">;
+def pch_through_hdrstop_use : Flag<["-"], "pch-through-hdrstop-use">,
+ HelpText<"When using a PCH, skip tokens until after a #pragma hdrstop.">;
def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">,
HelpText<"Disable inclusion of timestamp in precompiled headers">;
def building_pch_with_obj : Flag<["-"], "building-pch-with-obj">,
@@ -638,7 +659,9 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">,
HelpText<"Assume all functions with C linkage do not unwind">;
def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">,
- HelpText<"Use split dwarf/Fission">;
+ HelpText<"Use DWARF fission in 'split' mode">;
+def enable_split_dwarf_EQ : Joined<["-"], "enable-split-dwarf=">,
+ HelpText<"Set DWARF fission mode to either 'split' or 'single'">, Values<"split,single">;
def fno_wchar : Flag<["-"], "fno-wchar">,
HelpText<"Disable C++ builtin type wchar_t">;
def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
@@ -775,15 +798,11 @@ def internal_externc_isystem : JoinedOrSeparate<["-"], "internal-externc-isystem
// Preprocessor Options
//===----------------------------------------------------------------------===//
-def include_pth : Separate<["-"], "include-pth">, MetaVarName<"<file>">,
- HelpText<"Include file before parsing">;
def chain_include : Separate<["-"], "chain-include">, MetaVarName<"<file>">,
HelpText<"Include and chain a header file after turning it into PCH">;
def preamble_bytes_EQ : Joined<["-"], "preamble-bytes=">,
HelpText<"Assume that the precompiled header is a precompiled preamble "
"covering the first N bytes of the main file">;
-def token_cache : Separate<["-"], "token-cache">, MetaVarName<"<path>">,
- HelpText<"Use specified token cache file">;
def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">,
HelpText<"include a detailed record of preprocessing actions">;
diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
index 78667851ca19..3e0dc2db7d07 100644
--- a/include/clang/Driver/CLCompatOptions.td
+++ b/include/clang/Driver/CLCompatOptions.td
@@ -85,16 +85,19 @@ def _SLASH_GA : CLFlag<"GA">, Alias<ftlsmodel_EQ>, AliasArgs<["local-exec"]>,
HelpText<"Assume thread-local variables are defined in the executable">;
def _SLASH_GR : CLFlag<"GR">, HelpText<"Enable emission of RTTI data">;
def _SLASH_GR_ : CLFlag<"GR-">, HelpText<"Disable emission of RTTI data">;
+def _SLASH_GF : CLIgnoredFlag<"GF">, HelpText<"Enable string pooling (default)">;
def _SLASH_GF_ : CLFlag<"GF-">, HelpText<"Disable string pooling">,
Alias<fwritable_strings>;
-def _SLASH_GS : CLFlag<"GS">, HelpText<"Enable buffer security check">;
+def _SLASH_GS : CLFlag<"GS">, HelpText<"Enable buffer security check (default)">;
def _SLASH_GS_ : CLFlag<"GS-">, HelpText<"Disable buffer security check">;
-def _SLASH_Gs : CLJoined<"Gs">, HelpText<"Set stack probe size">,
- Alias<mstack_probe_size>;
+def : CLFlag<"Gs">, HelpText<"Use stack probes (default)">,
+ Alias<mstack_probe_size>, AliasArgs<["4096"]>;
+def _SLASH_Gs : CLJoined<"Gs">,
+ HelpText<"Set stack probe size (default 4096)">, Alias<mstack_probe_size>;
def _SLASH_Gy : CLFlag<"Gy">, HelpText<"Put each function in its own section">,
Alias<ffunction_sections>;
def _SLASH_Gy_ : CLFlag<"Gy-">,
- HelpText<"Don't put each function in its own section">,
+ HelpText<"Don't put each function in its own section (default)">,
Alias<fno_function_sections>;
def _SLASH_Gw : CLFlag<"Gw">, HelpText<"Put each data item in its own section">,
Alias<fdata_sections>;
@@ -109,18 +112,43 @@ def _SLASH_I : CLJoinedOrSeparate<"I">,
Alias<I>;
def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">,
Alias<funsigned_char>;
-def _SLASH_O0 : CLFlag<"O0">, Alias<O0>;
-// /Oy- is handled by the /O option because /Oy- only has an effect on 32-bit.
-def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">;
-def _SLASH_Od : CLFlag<"Od">, HelpText<"Disable optimization">, Alias<O0>;
-def _SLASH_Oi : CLFlag<"Oi">, HelpText<"Enable use of builtin functions">,
- Alias<fbuiltin>;
-def _SLASH_Oi_ : CLFlag<"Oi-">, HelpText<"Disable use of builtin functions">,
- Alias<fno_builtin>;
-def _SLASH_Os : CLFlag<"Os">, HelpText<"Optimize for size">, Alias<O>,
- AliasArgs<["s"]>;
-def _SLASH_Ot : CLFlag<"Ot">, HelpText<"Optimize for speed">, Alias<O>,
- AliasArgs<["2"]>;
+
+// The _SLASH_O option handles all the /O flags, but we also provide separate
+// aliased options to provide separate help messages.
+def _SLASH_O : CLJoined<"O">,
+ HelpText<"Set multiple /O flags at once; e.g. '/O2y-' for '/O2 /Oy-'">,
+ MetaVarName<"<flags>">;
+// FIXME: Not sure why we have -O0 here; MSVC doesn't support that.
+def : CLFlag<"O0">, Alias<O0>, HelpText<"Disable optimization">;
+def : CLFlag<"O1">, Alias<_SLASH_O>, AliasArgs<["1"]>,
+ HelpText<"Optimize for size (same as /Og /Os /Oy /Ob2 /GF /Gy)">;
+def : CLFlag<"O2">, Alias<_SLASH_O>, AliasArgs<["2"]>,
+ HelpText<"Optimize for speed (same as /Og /Oi /Ot /Oy /Ob2 /GF /Gy)">;
+def : CLFlag<"Ob0">, Alias<_SLASH_O>, AliasArgs<["b0"]>,
+ HelpText<"Disable function inlining">;
+def : CLFlag<"Ob1">, Alias<_SLASH_O>, AliasArgs<["b1"]>,
+ HelpText<"Only inline functions which are (explicitly or implicitly) marked inline">;
+def : CLFlag<"Ob2">, Alias<_SLASH_O>, AliasArgs<["b2"]>,
+ HelpText<"Inline functions as deemed beneficial by the compiler">;
+def : CLFlag<"Od">, Alias<_SLASH_O>, AliasArgs<["d"]>,
+ HelpText<"Disable optimization">;
+def : CLFlag<"Og">, Alias<_SLASH_O>, AliasArgs<["g"]>,
+ HelpText<"No effect">;
+def : CLFlag<"Oi">, Alias<_SLASH_O>, AliasArgs<["i"]>,
+ HelpText<"Enable use of builtin functions">;
+def : CLFlag<"Oi-">, Alias<_SLASH_O>, AliasArgs<["i-"]>,
+ HelpText<"Disable use of builtin functions">;
+def : CLFlag<"Os">, Alias<_SLASH_O>, AliasArgs<["s"]>,
+ HelpText<"Optimize for size">;
+def : CLFlag<"Ot">, Alias<_SLASH_O>, AliasArgs<["t"]>,
+ HelpText<"Optimize for speed">;
+def : CLFlag<"Ox">, Alias<_SLASH_O>, AliasArgs<["x"]>,
+ HelpText<"Deprecated (same as /Og /Oi /Ot /Oy /Ob2); use /O2 instead">;
+def : CLFlag<"Oy">, Alias<_SLASH_O>, AliasArgs<["y"]>,
+ HelpText<"Enable frame pointer omission (x86 only)">;
+def : CLFlag<"Oy-">, Alias<_SLASH_O>, AliasArgs<["y-"]>,
+ HelpText<"Disable frame pointer omission (x86 only, default)">;
+
def _SLASH_QUESTION : CLFlag<"?">, Alias<help>,
HelpText<"Display available options">;
def _SLASH_Qvec : CLFlag<"Qvec">,
@@ -130,6 +158,10 @@ def _SLASH_Qvec_ : CLFlag<"Qvec-">,
def _SLASH_showIncludes : CLFlag<"showIncludes">,
HelpText<"Print info about included files to stderr">,
Alias<show_includes>;
+def _SLASH_showFilenames : CLFlag<"showFilenames">,
+ HelpText<"Print the name of each compiled file">;
+def _SLASH_showFilenames_ : CLFlag<"showFilenames-">,
+ HelpText<"Don't print the name of each compiled file (default)">;
def _SLASH_source_charset : CLCompileJoined<"source-charset:">,
HelpText<"Source encoding, supports only UTF-8">, Alias<finput_charset_EQ>;
def _SLASH_execution_charset : CLCompileJoined<"execution-charset:">,
@@ -175,6 +207,12 @@ def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">,
def _SLASH_Zc_sizedDealloc_ : CLFlag<"Zc:sizedDealloc-">,
HelpText<"Disable C++14 sized global deallocation functions">,
Alias<fno_sized_deallocation>;
+def _SLASH_Zc_alignedNew : CLFlag<"Zc:alignedNew">,
+ HelpText<"Enable C++17 aligned allocation functions">,
+ Alias<faligned_allocation>;
+def _SLASH_Zc_alignedNew_ : CLFlag<"Zc:alignedNew-">,
+ HelpText<"Disable C++17 aligned allocation functions">,
+ Alias<fno_aligned_allocation>;
def _SLASH_Zc_strictStrings : CLFlag<"Zc:strictStrings">,
HelpText<"Treat string literals as const">, Alias<W_Joined>,
AliasArgs<["error=c++11-compat-deprecated-writable-strings"]>;
@@ -240,8 +278,8 @@ def _SLASH_Fi : CLCompileJoined<"Fi">,
def _SLASH_Fo : CLCompileJoined<"Fo">,
HelpText<"Set output object file, or directory (ends in / or \\) (with /c)">,
MetaVarName<"<file or directory>">;
-def _SLASH_Guard : CLJoined<"guard:">,
- HelpText<"Enable Control Flow Guard with /guard:cf">;
+def _SLASH_guard : CLJoined<"guard:">,
+ HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks">;
def _SLASH_GX : CLFlag<"GX">,
HelpText<"Enable exception handling">;
def _SLASH_GX_ : CLFlag<"GX-">,
@@ -289,6 +327,8 @@ def _SLASH_vmv : CLFlag<"vmv">,
def _SLASH_volatile_ms : Option<["/", "-"], "volatile:ms", KIND_FLAG>,
Group<_SLASH_volatile_Group>, Flags<[CLOption, DriverOption]>,
HelpText<"Volatile loads and stores have acquire and release semantics">;
+def _SLASH_clang : CLJoined<"clang:">,
+ HelpText<"Pass <arg> to the clang driver">, MetaVarName<"<arg>">;
def _SLASH_Zl : CLFlag<"Zl">,
HelpText<"Don't mention any default libraries in the object file">;
@@ -301,6 +341,10 @@ def _SLASH_Yu : CLJoined<"Yu">,
MetaVarName<"<filename>">;
def _SLASH_Y_ : CLFlag<"Y-">,
HelpText<"Disable precompiled headers, overrides /Yc and /Yu">;
+def _SLASH_Zc_dllexportInlines : CLFlag<"Zc:dllexportInlines">,
+ HelpText<"dllexport/dllimport inline member functions of dllexport/import classes (default)">;
+def _SLASH_Zc_dllexportInlines_ : CLFlag<"Zc:dllexportInlines-">,
+ HelpText<"Don't dllexport/dllimport inline member functions of dllexport/import classes">;
def _SLASH_Fp : CLJoined<"Fp">,
HelpText<"Set pch filename (with /Yc and /Yu)">, MetaVarName<"<filename>">;
@@ -326,10 +370,9 @@ def _SLASH_errorReport : CLIgnoredJoined<"errorReport">;
def _SLASH_FC : CLIgnoredFlag<"FC">;
def _SLASH_Fd : CLIgnoredJoined<"Fd">;
def _SLASH_FS : CLIgnoredFlag<"FS">;
-def _SLASH_GF : CLIgnoredFlag<"GF">;
+def _SLASH_JMC : CLIgnoredFlag<"JMC">;
def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
def _SLASH_nologo : CLIgnoredFlag<"nologo">;
-def _SLASH_Og : CLIgnoredFlag<"Og">;
def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
def _SLASH_permissive_ : CLIgnoredFlag<"permissive-">;
def _SLASH_RTC : CLIgnoredJoined<"RTC">;
diff --git a/include/clang/Driver/DarwinSDKInfo.h b/include/clang/Driver/DarwinSDKInfo.h
new file mode 100644
index 000000000000..4ffb02fea345
--- /dev/null
+++ b/include/clang/Driver/DarwinSDKInfo.h
@@ -0,0 +1,42 @@
+//===--- DarwinSDKInfo.h - SDK Information parser for darwin ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H
+#define LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+namespace clang {
+namespace driver {
+
+/// The information about the darwin SDK that was used during this compilation.
+class DarwinSDKInfo {
+public:
+ DarwinSDKInfo(llvm::VersionTuple Version) : Version(Version) {}
+
+ const llvm::VersionTuple &getVersion() const { return Version; }
+
+private:
+ llvm::VersionTuple Version;
+};
+
+/// Parse the SDK information from the SDKSettings.json file.
+///
+/// \returns an error if the SDKSettings.json file is invalid, None if the
+/// SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise.
+Expected<Optional<DarwinSDKInfo>> parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS,
+ StringRef SDKRootPath);
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H
diff --git a/include/clang/Driver/Distro.h b/include/clang/Driver/Distro.h
index 7b34a0925603..5651ebb6d42c 100644
--- a/include/clang/Driver/Distro.h
+++ b/include/clang/Driver/Distro.h
@@ -10,7 +10,7 @@
#ifndef LLVM_CLANG_DRIVER_DISTRO_H
#define LLVM_CLANG_DRIVER_DISTRO_H
-#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/Support/VirtualFileSystem.h"
namespace clang {
namespace driver {
@@ -39,6 +39,7 @@ public:
RHEL6,
RHEL7,
Fedora,
+ Gentoo,
OpenSUSE,
UbuntuHardy,
UbuntuIntrepid,
@@ -62,6 +63,7 @@ public:
UbuntuArtful,
UbuntuBionic,
UbuntuCosmic,
+ UbuntuDisco,
UnknownDistro
};
@@ -80,7 +82,7 @@ public:
Distro(DistroType D) : DistroVal(D) {}
/// Detects the distribution using specified VFS.
- explicit Distro(clang::vfs::FileSystem& VFS);
+ explicit Distro(llvm::vfs::FileSystem &VFS);
bool operator==(const Distro &Other) const {
return DistroVal == Other.DistroVal;
@@ -115,13 +117,17 @@ public:
}
bool IsUbuntu() const {
- return DistroVal >= UbuntuHardy && DistroVal <= UbuntuCosmic;
+ return DistroVal >= UbuntuHardy && DistroVal <= UbuntuDisco;
}
bool IsAlpineLinux() const {
return DistroVal == AlpineLinux;
}
+ bool IsGentoo() const {
+ return DistroVal == Gentoo;
+ }
+
/// @}
};
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index b7b802221180..494336d672c2 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -28,13 +28,12 @@
namespace llvm {
class Triple;
-}
-
-namespace clang {
-
namespace vfs {
class FileSystem;
}
+} // namespace llvm
+
+namespace clang {
namespace driver {
@@ -61,7 +60,7 @@ class Driver {
DiagnosticsEngine &Diags;
- IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
enum DriverMode {
GCCMode,
@@ -228,9 +227,6 @@ private:
unsigned CheckInputsExist : 1;
public:
- /// Use lazy precompiled headers for PCH support.
- unsigned CCCUsePCH : 1;
-
/// Force clang to emit reproducer for driver invocation. This is enabled
/// indirectly by setting FORCE_CLANG_DIAGNOSTICS_CRASH environment variable
/// or when using the -gen-reproducer driver flag.
@@ -284,7 +280,7 @@ private:
public:
Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
/// @name Accessors
/// @{
@@ -298,7 +294,7 @@ public:
const DiagnosticsEngine &getDiags() const { return Diags; }
- vfs::FileSystem &getVFS() const { return *VFS; }
+ llvm::vfs::FileSystem &getVFS() const { return *VFS; }
bool getCheckInputsExist() const { return CheckInputsExist; }
@@ -363,6 +359,7 @@ public:
/// ParseArgStrings - Parse the given list of strings into an
/// ArgList.
llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args,
+ bool IsClCompatMode,
bool &ContainsError);
/// BuildInputs - Construct the list of inputs and their types from
@@ -508,6 +505,10 @@ public:
/// GCC goes to extra lengths here to be a bit more robust.
std::string GetTemporaryPath(StringRef Prefix, StringRef Suffix) const;
+ /// GetTemporaryDirectory - Return the pathname of a temporary directory to
+ /// use as part of compilation; the directory will have the given prefix.
+ std::string GetTemporaryDirectory(StringRef Prefix) const;
+
/// Return the pathname of the pch file in clang-cl mode.
std::string GetClPchPath(Compilation &C, StringRef BaseName) const;
@@ -553,7 +554,7 @@ private:
/// Get bitmasks for which option flags to include and exclude based on
/// the driver mode.
- std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks() const;
+ std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const;
/// Helper used in BuildJobsForAction. Doesn't use the cache when building
/// jobs specifically for the given action, but will use the cache when
diff --git a/include/clang/Driver/DriverDiagnostic.h b/include/clang/Driver/DriverDiagnostic.h
index 680338a2ea7a..ad160ec6c64f 100644
--- a/include/clang/Driver/DriverDiagnostic.h
+++ b/include/clang/Driver/DriverDiagnostic.h
@@ -10,19 +10,6 @@
#ifndef LLVM_CLANG_DRIVER_DRIVERDIAGNOSTIC_H
#define LLVM_CLANG_DRIVER_DRIVERDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define DRIVERSTART
-#include "clang/Basic/DiagnosticDriverKinds.inc"
-#undef DIAG
- NUM_BUILTIN_DRIVER_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticDriver.h"
#endif
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index 47d9e992ba50..870a31c52093 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -29,9 +29,6 @@ class Action;
class InputInfo;
class Tool;
-// Re-export this as clang::driver::ArgStringList.
-using llvm::opt::ArgStringList;
-
struct CrashReportInfo {
StringRef Filename;
StringRef VFSPath;
@@ -59,6 +56,9 @@ class Command {
/// The list of program arguments which are inputs.
llvm::opt::ArgStringList InputFilenames;
+ /// Whether to print the input filenames when executing.
+ bool PrintInputFilenames = false;
+
/// Response file name, if this command is set to use one, or nullptr
/// otherwise
const char *ResponseFile = nullptr;
@@ -128,6 +128,9 @@ public:
/// Print a command argument, and optionally quote it.
static void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
+
+ /// Set whether to print the input filenames when executing.
+ void setPrintInputFilenames(bool P) { PrintInputFilenames = P; }
};
/// Like Command, but with a fallback which is executed in case
@@ -135,7 +138,8 @@ public:
class FallbackCommand : public Command {
public:
FallbackCommand(const Action &Source_, const Tool &Creator_,
- const char *Executable_, const ArgStringList &Arguments_,
+ const char *Executable_,
+ const llvm::opt::ArgStringList &Arguments_,
ArrayRef<InputInfo> Inputs,
std::unique_ptr<Command> Fallback_);
@@ -153,7 +157,8 @@ private:
class ForceSuccessCommand : public Command {
public:
ForceSuccessCommand(const Action &Source_, const Tool &Creator_,
- const char *Executable_, const ArgStringList &Arguments_,
+ const char *Executable_,
+ const llvm::opt::ArgStringList &Arguments_,
ArrayRef<InputInfo> Inputs);
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 2470638bec66..f02a7190f5a7 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -258,10 +258,6 @@ def rsp_quoting : Joined<["--"], "rsp-quoting=">, Group<internal_driver_Group>,
def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, InternalDriverOpt,
HelpText<"Name for native GCC compiler">,
MetaVarName<"<gcc-path>">;
-def ccc_pch_is_pch : Flag<["-"], "ccc-pch-is-pch">, InternalDriverOpt,
- HelpText<"Use lazy PCH for precompiled headers">;
-def ccc_pch_is_pth : Flag<["-"], "ccc-pch-is-pth">, InternalDriverOpt,
- HelpText<"Use pretokenized headers for precompiled headers">;
class InternalDebugOpt : Group<internal_debug_Group>,
Flags<[DriverOption, HelpHidden, CoreOption]>;
@@ -584,9 +580,11 @@ def fno_cuda_flush_denormals_to_zero : Flag<["-"], "fno-cuda-flush-denormals-to-
def fcuda_approx_transcendentals : Flag<["-"], "fcuda-approx-transcendentals">,
Flags<[CC1Option]>, HelpText<"Use approximate transcendental functions">;
def fno_cuda_approx_transcendentals : Flag<["-"], "fno-cuda-approx-transcendentals">;
-def fcuda_rdc : Flag<["-"], "fcuda-rdc">, Flags<[CC1Option]>,
+def fgpu_rdc : Flag<["-"], "fgpu-rdc">, Flags<[CC1Option]>,
HelpText<"Generate relocatable device code, also known as separate compilation mode.">;
-def fno_cuda_rdc : Flag<["-"], "fno-cuda-rdc">;
+def fno_gpu_rdc : Flag<["-"], "fno-gpu-rdc">;
+def : Flag<["-"], "fcuda-rdc">, Alias<fgpu_rdc>;
+def : Flag<["-"], "fno-cuda-rdc">, Alias<fno_gpu_rdc>;
def fcuda_short_ptr : Flag<["-"], "fcuda-short-ptr">, Flags<[CC1Option]>,
HelpText<"Use 32-bit pointers for accessing const/local/shared address spaces.">;
def fno_cuda_short_ptr : Flag<["-"], "fno-cuda-short-ptr">;
@@ -596,6 +594,8 @@ def hip_device_lib_EQ : Joined<["--"], "hip-device-lib=">, Group<Link_Group>,
HelpText<"HIP device library">;
def fhip_dump_offload_linker_script : Flag<["-"], "fhip-dump-offload-linker-script">,
Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
+def libomptarget_nvptx_path_EQ : Joined<["--"], "libomptarget-nvptx-path=">, Group<i_Group>,
+ HelpText<"Path to libomptarget-nvptx libraries">;
def dA : Flag<["-"], "dA">, Group<d_Group>;
def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
@@ -639,8 +639,10 @@ def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>
HelpText<"Use Apple's kernel extensions ABI">;
def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
-def shared_libsan : Flag<["-"], "shared-libsan">;
-def static_libsan : Flag<["-"], "static-libsan">;
+def shared_libsan : Flag<["-"], "shared-libsan">,
+ HelpText<"Dynamically link the sanitizer runtime">;
+def static_libsan : Flag<["-"], "static-libsan">,
+ HelpText<"Statically link the sanitizer runtime">;
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
def fasm : Flag<["-"], "fasm">, Group<f_Group>;
@@ -673,7 +675,7 @@ def fno_coroutines_ts : Flag <["-"], "fno-coroutines-ts">, Group<f_Group>,
Flags<[DriverOption]>;
def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
- Group<f_Group>, Flags<[DriverOption, CC1Option]>, MetaVarName<"<option>">,
+ Group<f_Group>, Flags<[DriverOption, CC1Option, CC1AsOption]>, MetaVarName<"<option>">,
HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;
def fembed_bitcode : Flag<["-"], "fembed-bitcode">, Group<f_Group>,
Alias<fembed_bitcode_EQ>, AliasArgs<["all"]>,
@@ -729,6 +731,11 @@ def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>,
def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Use instrumentation data for profile-guided optimization">;
+def fprofile_remapping_file_EQ : Joined<["-"], "fprofile-remapping-file=">,
+ Group<f_Group>, Flags<[CC1Option, CoreOption]>, MetaVarName<"<file>">,
+ HelpText<"Use the remappings described in <file> to match the profile data against names in the program">;
+def fprofile_remapping_file : Separate<["-"], "fprofile-remapping-file">,
+ Group<f_Group>, Flags<[CoreOption]>, Alias<fprofile_remapping_file_EQ>;
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Generate coverage mapping to enable code coverage analysis">;
@@ -757,6 +764,12 @@ def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
HelpText<"Disable using instrumentation data for profile-guided optimization">;
def fno_profile_use : Flag<["-"], "fno-profile-use">,
Alias<fno_profile_instr_use>;
+def fprofile_filter_files_EQ : Joined<["-"], "fprofile-filter-files=">,
+ Group<f_Group>, Flags<[CC1Option, CoreOption]>,
+ HelpText<"Instrument only functions from files where names match any regex separated by a semi-colon">;
+def fprofile_exclude_files_EQ : Joined<["-"], "fprofile-exclude-files=">,
+ Group<f_Group>, Flags<[CC1Option, CoreOption]>,
+ HelpText<"Instrument only functions from files where names don't match all the regexes separated by a semi-colon">;
def faddrsig : Flag<["-"], "faddrsig">, Group<f_Group>, Flags<[CoreOption, CC1Option]>,
HelpText<"Emit an address-significance table">;
@@ -786,6 +799,12 @@ def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Gr
HelpText<"Treat each comma separated argument in <arg> as a documentation comment block command">,
MetaVarName<"<arg>">;
def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Group>, Flags<[CC1Option]>;
+def frecord_command_line : Flag<["-"], "frecord-command-line">,
+ Group<f_clang_Group>;
+def fno_record_command_line : Flag<["-"], "fno-record-command-line">,
+ Group<f_clang_Group>;
+def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>;
+def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>;
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>;
def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>;
def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<f_clang_Group>,
@@ -794,15 +813,17 @@ def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<
def fno_complete_member_pointers : Flag<["-"], "fno-complete-member-pointers">, Group<f_clang_Group>,
Flags<[CoreOption]>,
HelpText<"Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI">;
+def fcf_runtime_abi_EQ : Joined<["-"], "fcf-runtime-abi=">, Group<f_Group>,
+ Flags<[CC1Option]>;
def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>;
def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group<f_Group>;
def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">,
Group<f_Group>;
-def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>,
+def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused, CoreOption]>,
HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">;
-def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>;
+def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group<f_clang_Group>, Flags<[NoArgumentUnused, CoreOption]>;
def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>,
HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
@@ -893,11 +914,19 @@ def fforce_enable_int128 : Flag<["-"], "fforce-enable-int128">,
def fno_force_enable_int128 : Flag<["-"], "fno-force-enable-int128">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable support for int128_t type">;
-
+def fkeep_static_consts : Flag<["-"], "fkeep-static-consts">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Keep static const variables even if unused">;
def ffixed_point : Flag<["-"], "ffixed-point">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Enable fixed point types">;
def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group<f_Group>,
HelpText<"Disable fixed point types">;
+def fcxx_static_destructors : Flag<["-"], "fc++-static-destructors">,
+ Group<f_Group>,
+ HelpText<"Enable C++ static destructor registration (the default)">;
+def fno_cxx_static_destructors : Flag<["-"], "fno-c++-static-destructors">,
+ Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Disable C++ static destructor registration">;
// Begin sanitizer flags. These should all be core options exposed in all driver
// modes.
@@ -950,17 +979,29 @@ def fno_sanitize_address_use_after_scope : Flag<["-"], "fno-sanitize-address-use
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable use-after-scope detection in AddressSanitizer">;
-def fsanitize_address_poison_class_member_array_new_cookie
- : Flag<[ "-" ], "fsanitize-address-poison-class-member-array-new-cookie">,
+def fsanitize_address_poison_custom_array_cookie
+ : Flag<[ "-" ], "fsanitize-address-poison-custom-array-cookie">,
Group<f_clang_Group>,
- HelpText<"Enable poisoning array cookies when using class member operator new[] in AddressSanitizer">;
-def fno_sanitize_address_poison_class_member_array_new_cookie
- : Flag<[ "-" ], "fno-sanitize-address-poison-class-member-array-new-cookie">,
+ HelpText<"Enable poisoning array cookies when using custom operator new[] in AddressSanitizer">;
+def fno_sanitize_address_poison_custom_array_cookie
+ : Flag<[ "-" ], "fno-sanitize-address-poison-custom-array-cookie">,
Group<f_clang_Group>,
- HelpText<"Disable poisoning array cookies when using class member operator new[] in AddressSanitizer">;
+ HelpText<"Disable poisoning array cookies when using custom operator new[] in AddressSanitizer">;
def fsanitize_address_globals_dead_stripping : Flag<["-"], "fsanitize-address-globals-dead-stripping">,
Group<f_clang_Group>,
HelpText<"Enable linker dead stripping of globals in AddressSanitizer">;
+def fsanitize_address_use_odr_indicator
+ : Flag<["-"], "fsanitize-address-use-odr-indicator">,
+ Group<f_clang_Group>,
+ HelpText<"Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size">;
+def fno_sanitize_address_use_odr_indicator
+ : Flag<["-"], "fno-sanitize-address-use-odr-indicator">,
+ Group<f_clang_Group>,
+ HelpText<"Disable ODR indicator globals">;
+def fsanitize_hwaddress_abi_EQ
+ : Joined<["-"], "fsanitize-hwaddress-abi=">,
+ Group<f_clang_Group>,
+ HelpText<"Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor)">;
def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>;
def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">,
Flags<[CoreOption, DriverOption]>,
@@ -1442,6 +1483,10 @@ def fno_zero_initialized_in_bss : Flag<["-"], "fno-zero-initialized-in-bss">, Gr
def fobjc_arc : Flag<["-"], "fobjc-arc">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Synthesize retain and release calls for Objective-C pointers">;
def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group<f_Group>;
+def fobjc_convert_messages_to_runtime_calls :
+ Flag<["-"], "fobjc-convert-messages-to-runtime-calls">, Group<f_Group>;
+def fno_objc_convert_messages_to_runtime_calls :
+ Flag<["-"], "fno-objc-convert-messages-to-runtime-calls">, Group<f_Group>, Flags<[CC1Option]>;
def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">;
def fno_objc_arc_exceptions : Flag<["-"], "fno-objc-arc-exceptions">, Group<f_Group>;
@@ -1488,7 +1533,7 @@ def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable ARC-style weak references in Objective-C">;
// Objective-C ABI options.
-def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>,
+def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Specify the target Objective-C runtime kind and version">;
def fobjc_abi_version_EQ : Joined<["-"], "fobjc-abi-version=">, Group<f_Group>;
def fobjc_nonfragile_abi_version_EQ : Joined<["-"], "fobjc-nonfragile-abi-version=">, Group<f_Group>;
@@ -1521,6 +1566,18 @@ def fopenmp_cuda_mode : Flag<["-"], "fopenmp-cuda-mode">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fno_openmp_cuda_mode : Flag<["-"], "fno-openmp-cuda-mode">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>;
+def fopenmp_cuda_force_full_runtime : Flag<["-"], "fopenmp-cuda-force-full-runtime">, Group<f_Group>,
+ Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
+def fno_openmp_cuda_force_full_runtime : Flag<["-"], "fno-openmp-cuda-force-full-runtime">, Group<f_Group>,
+ Flags<[NoArgumentUnused, HelpHidden]>;
+def fopenmp_cuda_number_of_sm_EQ : Joined<["-"], "fopenmp-cuda-number-of-sm=">, Group<f_Group>,
+ Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
+def fopenmp_cuda_blocks_per_sm_EQ : Joined<["-"], "fopenmp-cuda-blocks-per-sm=">, Group<f_Group>,
+ Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
+def fopenmp_optimistic_collapse : Flag<["-"], "fopenmp-optimistic-collapse">, Group<f_Group>,
+ Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
+def fno_openmp_optimistic_collapse : Flag<["-"], "fno-openmp-optimistic-collapse">, Group<f_Group>,
+ Flags<[NoArgumentUnused, HelpHidden]>;
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
def fno_escaping_block_tail_calls : Flag<["-"], "fno-escaping-block-tail-calls">, Group<f_Group>, Flags<[CC1Option]>;
@@ -1571,7 +1628,7 @@ def fshort_enums : Flag<["-"], "fshort-enums">, Group<f_Group>, Flags<[CC1Option
HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
def fchar8__t : Flag<["-"], "fchar8_t">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable C++ builtin type char8_t">;
-def fno_char8__t : Flag<["-"], "fno-char8_t">, Group<f_Group>,
+def fno_char8__t : Flag<["-"], "fno-char8_t">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable C++ builtin type char8_t">;
def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>,
HelpText<"Force wchar_t to be a short unsigned int">;
@@ -1590,11 +1647,24 @@ def fno_signed_char : Flag<["-"], "fno-signed-char">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Char is unsigned">;
def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>,
- HelpText<"Force the usage of stack protectors for all functions">;
+ HelpText<"Enable stack protectors for all functions">;
def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group<f_Group>,
- HelpText<"Use a strong heuristic to apply stack protectors to functions">;
+ HelpText<"Enable stack protectors for some functions vulnerable to stack smashing. "
+ "Compared to -fstack-protector, this uses a stronger heuristic "
+ "that includes functions containing arrays of any size (and any type), "
+ "as well as any calls to alloca or the taking of an address from a local variable">;
def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>,
- HelpText<"Enable stack protectors for functions potentially vulnerable to stack smashing">;
+ HelpText<"Enable stack protectors for some functions vulnerable to stack smashing. "
+ "This uses a loose heuristic which considers functions vulnerable "
+ "if they contain a char (or 8bit integer) array or constant sized calls to "
+ "alloca, which are of greater size than ssp-buffer-size (default: 8 bytes). "
+ "All variable sized calls to alloca are considered vulnerable">;
+def ftrivial_auto_var_init : Joined<["-"], "ftrivial-auto-var-init=">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Initialize trivial automatic stack variables: uninitialized (default)"
+ " | pattern">, Values<"uninitialized,pattern">;
+def enable_trivial_var_init_zero : Joined<["-"], "enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">,
+ Flags<[CC1Option]>,
+ HelpText<"Trivial automatic variable initialization to zero is only here for benchmarks, it'll eventually be removed, and I'm OK with that because I'm only using it to benchmark">;
def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Emit full debug info for all types used by the program">;
def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CoreOption]>,
@@ -1699,11 +1769,18 @@ def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Grou
def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>,
HelpText<"Give global types 'default' visibility and global functions and "
"variables 'hidden' visibility by default">;
+def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group<f_Group>,
+ HelpText<"Give global C++ operator new and delete declarations hidden visibility">, Flags<[CC1Option]>;
def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>,
HelpText<"Enables whole-program vtable optimization. Requires -flto">;
def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>,
Flags<[CoreOption]>;
+def fsplit_lto_unit : Flag<["-"], "fsplit-lto-unit">, Group<f_Group>,
+ Flags<[CoreOption, CC1Option]>,
+ HelpText<"Enables splitting of the LTO unit.">;
+def fno_split_lto_unit : Flag<["-"], "fno-split-lto-unit">, Group<f_Group>,
+ Flags<[CoreOption]>;
def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Emits more virtual tables to improve devirtualization">;
@@ -1751,6 +1828,10 @@ def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>,
Flags<[CC1Option]>;
+def fdebug_ranges_base_address: Flag <["-"], "fdebug-ranges-base-address">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Use DWARF base address selection entries in debug_ranges">;
+def fno_debug_ranges_base_address: Flag <["-"], "fno-debug-ranges-base-address">, Group<f_Group>,
+ Flags<[CC1Option]>;
def fsplit_dwarf_inlining: Flag <["-"], "fsplit-dwarf-inlining">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF">;
def fno_split_dwarf_inlining: Flag<["-"], "fno-split-dwarf-inlining">, Group<f_Group>,
@@ -1763,6 +1844,8 @@ def g_Flag : Flag<["-"], "g">, Group<g_Group>,
HelpText<"Generate source-level debug information">;
def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<gN_Group>,
Flags<[CoreOption]>, HelpText<"Emit debug line number tables only">;
+def gline_directives_only : Flag<["-"], "gline-directives-only">, Group<gN_Group>,
+ Flags<[CoreOption]>, HelpText<"Emit debug line info directives only">;
def gmlt : Flag<["-"], "gmlt">, Alias<gline_tables_only>;
def g0 : Flag<["-"], "g0">, Group<gN_Group>;
def g1 : Flag<["-"], "g1">, Group<gN_Group>, Alias<gline_tables_only>;
@@ -1783,9 +1866,15 @@ def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 4">;
def gdwarf_5 : Flag<["-"], "gdwarf-5">, Group<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 5">;
+
def gcodeview : Flag<["-"], "gcodeview">,
HelpText<"Generate CodeView debug information">,
Flags<[CC1Option, CC1AsOption, CoreOption]>;
+def gcodeview_ghash : Flag<["-"], "gcodeview-ghash">,
+ HelpText<"Emit type record hashes in a .debug$H section">,
+ Flags<[CC1Option, CoreOption]>;
+def gno_codeview_ghash : Flag<["-"], "gno-codeview-ghash">, Flags<[CoreOption]>;
+
// Equivalent to our default dwarf version. Forces usual dwarf emission when
// CodeView is enabled.
def gdwarf : Flag<["-"], "gdwarf">, Alias<gdwarf_4>, Flags<[CoreOption]>;
@@ -1797,16 +1886,24 @@ def gcoff : Joined<["-"], "gcoff">, Group<g_Group>, Flags<[Unsupported]>;
def gxcoff : Joined<["-"], "gxcoff">, Group<g_Group>, Flags<[Unsupported]>;
def gvms : Joined<["-"], "gvms">, Group<g_Group>, Flags<[Unsupported]>;
def gtoggle : Flag<["-"], "gtoggle">, Group<g_flags_Group>, Flags<[Unsupported]>;
-def grecord_gcc_switches : Flag<["-"], "grecord-gcc-switches">, Group<g_flags_Group>;
-def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">,
+def grecord_command_line : Flag<["-"], "grecord-command-line">,
+ Group<g_flags_Group>;
+def gno_record_command_line : Flag<["-"], "gno-record-command-line">,
Group<g_flags_Group>;
+def : Flag<["-"], "grecord-gcc-switches">, Alias<grecord_command_line>;
+def : Flag<["-"], "gno-record-gcc-switches">, Alias<gno_record_command_line>;
def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>;
def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
+def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
+ HelpText<"Set DWARF fission mode to either 'split' or 'single'">,
+ Values<"split,single">;
def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gno_gnu_pubnames : Flag<["-"], "gno-gnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
+def gpubnames : Flag<["-"], "gpubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
+def gno_pubnames : Flag<["-"], "gno-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>;
def gmodules : Flag <["-"], "gmodules">, Group<gN_Group>,
HelpText<"Generate debug info with external references to clang modules"
@@ -1913,7 +2010,7 @@ def mappletvsimulator_version_min_EQ : Joined<["-"], "mappletvsimulator-version-
def mwatchos_version_min_EQ : Joined<["-"], "mwatchos-version-min=">, Group<m_Group>;
def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">;
def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias<mwatchos_simulator_version_min_EQ>;
-def march_EQ : Joined<["-"], "march=">, Group<m_Group>;
+def march_EQ : Joined<["-"], "march=">, Group<m_Group>, Flags<[CoreOption]>;
def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>;
def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>;
def mimplicit_it_EQ : Joined<["-"], "mimplicit-it=">, Group<m_Group>;
@@ -1938,6 +2035,7 @@ def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>, Values<"soft,s
def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
+def mhwmult_EQ : Joined<["-"], "mhwmult=">, Group<m_Group>;
def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Enable merging of globals">;
def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>;
@@ -1984,11 +2082,20 @@ def mno_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[C
def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">,
Alias<fno_pascal_strings>;
def mno_red_zone : Flag<["-"], "mno-red-zone">, Group<m_Group>;
+def mno_tls_direct_seg_refs : Flag<["-"], "mno-tls-direct-seg-refs">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable direct TLS access through segment registers">;
def mno_relax_all : Flag<["-"], "mno-relax-all">, Group<m_Group>;
def mno_rtd: Flag<["-"], "mno-rtd">, Group<m_Group>;
def mno_soft_float : Flag<["-"], "mno-soft-float">, Group<m_Group>;
def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group<m_Group>;
+def mretpoline : Flag<["-"], "mretpoline">, Group<m_Group>, Flags<[CoreOption,DriverOption]>;
+def mno_retpoline : Flag<["-"], "mno-retpoline">, Group<m_Group>, Flags<[CoreOption,DriverOption]>;
+def mspeculative_load_hardening : Flag<["-"], "mspeculative-load-hardening">,
+ Group<m_Group>, Flags<[CoreOption,CC1Option]>;
+def mno_speculative_load_hardening : Flag<["-"], "mno-speculative-load-hardening">,
+ Group<m_Group>, Flags<[CoreOption]>;
+
def mrelax : Flag<["-"], "mrelax">, Group<m_riscv_Features_Group>,
HelpText<"Enable linker relaxation">;
def mno_relax : Flag<["-"], "mno-relax">, Group<m_riscv_Features_Group>,
@@ -2025,12 +2132,23 @@ def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">,
def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
Group<m_aarch64_Features_Group>,
HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
-def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>,
- HelpText<"Reserve the x18 register (AArch64 only)">;
-def ffixed_x20 : Flag<["-"], "ffixed-x20">, Group<m_aarch64_Features_Group>,
- HelpText<"Reserve the x20 register (AArch64 only)">;
+foreach i = {1-7,18,20} in
+ def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_aarch64_Features_Group>,
+ HelpText<"Reserve the "#i#" register (AArch64 only)">;
+
+foreach i = {8-15,18} in
+ def fcall_saved_x#i : Flag<["-"], "fcall-saved-x"#i>, Group<m_aarch64_Features_Group>,
+ HelpText<"Make the x"#i#" register call-saved (AArch64 only)">;
+
+def msign_return_address_EQ : Joined<["-"], "msign-return-address=">,
+ Flags<[CC1Option]>, Group<m_Group>, Values<"none,all,non-leaf">,
+ HelpText<"Select return address signing scope">;
+def mbranch_protection_EQ : Joined<["-"], "mbranch-protection=">,
+ HelpText<"Enforce targets of indirect branches and function returns">;
def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
+def munimplemented_simd128 : Flag<["-"], "munimplemented-simd128">, Group<m_wasm_Features_Group>;
+def mno_unimplemented_simd128 : Flag<["-"], "mno-unimplemented-simd128">, Group<m_wasm_Features_Group>;
def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>;
def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>;
@@ -2044,10 +2162,19 @@ def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">,
Group<m_Group>,
HelpText<"Generate additional code for specified <version> of debugger ABI (AMDGPU only)">,
MetaVarName<"<version>">;
+
+def mcode_object_v3 : Flag<["-"], "mcode-object-v3">, Group<m_amdgpu_Features_Group>,
+ HelpText<"Enable code object v3 (AMDGPU only)">;
+def mno_code_object_v3 : Flag<["-"], "mno-code-object-v3">, Group<m_amdgpu_Features_Group>,
+ HelpText<"Disable code object v3 (AMDGPU only)">;
def mxnack : Flag<["-"], "mxnack">, Group<m_amdgpu_Features_Group>,
HelpText<"Enable XNACK (AMDGPU only)">;
def mno_xnack : Flag<["-"], "mno-xnack">, Group<m_amdgpu_Features_Group>,
HelpText<"Disable XNACK (AMDGPU only)">;
+def msram_ecc : Flag<["-"], "msram-ecc">, Group<m_amdgpu_Features_Group>,
+ HelpText<"Enable SRAM ECC (AMDGPU only)">;
+def mno_sram_ecc : Flag<["-"], "mno-sram-ecc">, Group<m_amdgpu_Features_Group>,
+ HelpText<"Disable SRAM ECC (AMDGPU only)">;
def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[DriverOption]>;
def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[DriverOption]>;
@@ -2125,6 +2252,8 @@ def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group<m_
def moslib_EQ : Joined<["-"], "moslib=">, Group<m_Group>;
def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias<fpascal_strings>;
def mred_zone : Flag<["-"], "mred-zone">, Group<m_Group>;
+def mtls_direct_seg_refs : Flag<["-"], "mtls-direct-seg-refs">, Group<m_Group>,
+ HelpText<"Enable direct TLS access through segment registers (default)">;
def mregparm_EQ : Joined<["-"], "mregparm=">, Group<m_Group>;
def mrelax_all : Flag<["-"], "mrelax-all">, Group<m_Group>, Flags<[CC1Option,CC1AsOption]>,
HelpText<"(integrated-as) Relax all machine instructions">;
@@ -2348,6 +2477,10 @@ def print_multi_directory : Flag<["-", "--"], "print-multi-directory">;
def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
Flags<[Unsupported]>;
+def print_target_triple : Flag<["-", "--"], "print-target-triple">,
+ HelpText<"Print the normalized target triple">;
+def print_effective_triple : Flag<["-", "--"], "print-effective-triple">,
+ HelpText<"Print the effective target triple">;
def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">,
HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">;
def print_resource_dir : Flag<["-", "--"], "print-resource-dir">,
@@ -2607,8 +2740,6 @@ def _ : Joined<["--"], "">, Flags<[Unsupported]>;
// Hexagon feature flags.
def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">,
Group<m_hexagon_Features_Group>;
-def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>,
- Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>;
def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>,
AliasArgs<["hexagonv5"]>;
def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>,
@@ -2619,6 +2750,8 @@ def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>;
def mv65 : Flag<["-"], "mv65">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv65"]>;
+def mv66 : Flag<["-"], "mv66">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv66"]>;
def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_HVX_Group>,
HelpText<"Enable Hexagon Vector eXtensions">;
def mhexagon_hvx_EQ : Joined<["-"], "mhvx=">,
@@ -2806,8 +2939,6 @@ def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>;
def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>;
def mshstk : Flag<["-"], "mshstk">, Group<m_x86_Features_Group>;
def mno_shstk : Flag<["-"], "mno-shstk">, Group<m_x86_Features_Group>;
-def mretpoline : Flag<["-"], "mretpoline">, Group<m_x86_Features_Group>;
-def mno_retpoline : Flag<["-"], "mno-retpoline">, Group<m_x86_Features_Group>;
def mretpoline_external_thunk : Flag<["-"], "mretpoline-external-thunk">, Group<m_x86_Features_Group>;
def mno_retpoline_external_thunk : Flag<["-"], "mno-retpoline-external-thunk">, Group<m_x86_Features_Group>;
diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h
index d144e488b56b..e590a49deea3 100644
--- a/include/clang/Driver/SanitizerArgs.h
+++ b/include/clang/Driver/SanitizerArgs.h
@@ -36,7 +36,10 @@ class SanitizerArgs {
int AsanFieldPadding = 0;
bool SharedRuntime = false;
bool AsanUseAfterScope = true;
+ bool AsanPoisonCustomArrayCookie = false;
bool AsanGlobalsDeadStripping = false;
+ bool AsanUseOdrIndicator = false;
+ std::string HwasanAbi;
bool LinkCXXRuntimes = false;
bool NeedPIE = false;
bool SafeStackRuntime = false;
@@ -78,8 +81,10 @@ class SanitizerArgs {
bool requiresPIE() const;
bool needsUnwindTables() const;
+ bool needsLTO() const;
bool linkCXXRuntimes() const { return LinkCXXRuntimes; }
bool hasCrossDsoCfi() const { return CfiCrossDso; }
+ bool hasAnySanitizer() const { return !Sanitizers.empty(); }
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
};
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 2f9c2c190e32..d5f75b827110 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -10,7 +10,9 @@
#ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H
#define LLVM_CLANG_DRIVER_TOOLCHAIN_H
+#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Multilib.h"
@@ -36,17 +38,16 @@ class ArgList;
class DerivedArgList;
} // namespace opt
-} // namespace llvm
-
-namespace clang {
-
-class ObjCRuntime;
-
namespace vfs {
class FileSystem;
} // namespace vfs
+} // namespace llvm
+
+namespace clang {
+
+class ObjCRuntime;
namespace driver {
@@ -116,6 +117,9 @@ private:
const RTTIMode CachedRTTIMode;
+ /// The list of toolchain specific path prefixes to search for libraries.
+ path_list LibraryPaths;
+
/// The list of toolchain specific path prefixes to search for files.
path_list FilePaths;
@@ -146,6 +150,7 @@ private:
protected:
MultilibSet Multilibs;
+ Multilib SelectedMultilib;
ToolChain(const Driver &D, const llvm::Triple &T,
const llvm::opt::ArgList &Args);
@@ -179,7 +184,7 @@ public:
// Accessors
const Driver &getDriver() const { return D; }
- vfs::FileSystem &getVFS() const;
+ llvm::vfs::FileSystem &getVFS() const;
const llvm::Triple &getTriple() const { return Triple; }
/// Get the toolchain's aux triple, if it has one.
@@ -213,6 +218,9 @@ public:
return EffectiveTriple;
}
+ path_list &getLibraryPaths() { return LibraryPaths; }
+ const path_list &getLibraryPaths() const { return LibraryPaths; }
+
path_list &getFilePaths() { return FilePaths; }
const path_list &getFilePaths() const { return FilePaths; }
@@ -221,6 +229,8 @@ public:
const MultilibSet &getMultilibs() const { return Multilibs; }
+ const Multilib &getMultilib() const { return SelectedMultilib; }
+
const SanitizerArgs& getSanitizerArgs() const;
const XRayArgs& getXRayArgs() const;
@@ -340,6 +350,12 @@ public:
return 0;
}
+ /// Get the default trivial automatic variable initialization.
+ virtual LangOptions::TrivialAutoVarInitKind
+ GetDefaultTrivialAutoVarInit() const {
+ return LangOptions::TrivialAutoVarInitKind::Uninitialized;
+ }
+
/// GetDefaultLinker - Get the default linker to use.
virtual const char *getDefaultLinker() const { return "ld"; }
@@ -372,6 +388,9 @@ public:
/// needsProfileRT - returns true if instrumentation profile is on.
static bool needsProfileRT(const llvm::opt::ArgList &Args);
+ /// Returns true if gcov instrumentation (-fprofile-arcs or --coverage) is on.
+ static bool needsGCovInstrumentation(const llvm::opt::ArgList &Args);
+
/// IsUnwindTablesDefault - Does this tool chain use -funwind-tables
/// by default.
virtual bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const;
@@ -394,6 +413,11 @@ public:
/// Complain if this tool chain doesn't support Objective-C ARC.
virtual void CheckObjCARC() const {}
+ /// Get the default debug info format. Typically, this is DWARF.
+ virtual codegenoptions::DebugInfoFormat getDefaultDebugFormat() const {
+ return codegenoptions::DIF_DWARF;
+ }
+
/// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf
/// compile unit information.
virtual bool UseDwarfDebugFlags() const { return false; }
@@ -418,6 +442,10 @@ public:
return true;
}
+ /// Adjust debug information kind considering all passed options.
+ virtual void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind,
+ const llvm::opt::ArgList &Args) const {}
+
/// GetExceptionModel - Return the tool chain exception model.
virtual llvm::ExceptionHandling
GetExceptionModel(const llvm::opt::ArgList &Args) const;
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index c23f1f13361f..c25bc4b08084 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -101,4 +101,5 @@ TYPE("image", Image, INVALID, "out", "")
TYPE("dSYM", dSYM, INVALID, "dSYM", "A")
TYPE("dependencies", Dependencies, INVALID, "d", "")
TYPE("cuda-fatbin", CUDA_FATBIN, INVALID, "fatbin","A")
+TYPE("hip-fatbin", HIP_FATBIN, INVALID, "hipfb", "A")
TYPE("none", Nothing, INVALID, nullptr, "u")
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 85dda948c11f..cb37b0c890c3 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -22,16 +22,18 @@
#include "llvm/Support/Regex.h"
#include <system_error>
+namespace llvm {
+namespace vfs {
+class FileSystem;
+}
+} // namespace llvm
+
namespace clang {
class Lexer;
class SourceManager;
class DiagnosticConsumer;
-namespace vfs {
-class FileSystem;
-}
-
namespace format {
enum class ParseError { Success = 0, Error, Unsuitable };
@@ -531,20 +533,17 @@ struct FormatStyle {
/// \code
/// try {
/// foo();
- /// } catch () {
+ /// }
+ /// catch () {
/// }
/// void foo() { bar(); }
- /// class foo
- /// {
+ /// class foo {
/// };
/// if (foo()) {
- /// } else {
/// }
- /// enum X : int
- /// {
- /// A,
- /// B
- /// };
+ /// else {
+ /// }
+ /// enum X : int { A, B };
/// \endcode
BS_Stroustrup,
/// Always break before braces.
@@ -1051,6 +1050,16 @@ struct FormatStyle {
/// For example: BOOST_FOREACH.
std::vector<std::string> ForEachMacros;
+ /// A vector of macros that should be interpreted as complete
+ /// statements.
+ ///
+ /// Typical macros are expressions, and require a semi-colon to be
+ /// added; sometimes this is not the case, and this allows to make
+ /// clang-format aware of such cases.
+ ///
+ /// For example: Q_UNUSED
+ std::vector<std::string> StatementMacros;
+
tooling::IncludeStyle IncludeStyle;
/// Indent case labels one level from the switch statement.
@@ -1120,6 +1129,37 @@ struct FormatStyle {
/// \endcode
bool IndentWrappedFunctionNames;
+ /// A vector of prefixes ordered by the desired groups for Java imports.
+ ///
+ /// Each group is seperated by a newline. Static imports will also follow the
+ /// same grouping convention above all non-static imports. One group's prefix
+ /// can be a subset of another - the longest prefix is always matched. Within
+ /// a group, the imports are ordered lexicographically.
+ ///
+ /// In the .clang-format configuration file, this can be configured like
+ /// in the following yaml example. This will result in imports being
+ /// formatted as in the Java example below.
+ /// \code{.yaml}
+ /// JavaImportGroups: ['com.example', 'com', 'org']
+ /// \endcode
+ ///
+ /// \code{.java}
+ /// import static com.example.function1;
+ ///
+ /// import static com.test.function2;
+ ///
+ /// import static org.example.function3;
+ ///
+ /// import com.example.ClassA;
+ /// import com.example.Test;
+ /// import com.example.a.ClassB;
+ ///
+ /// import com.test.ClassC;
+ ///
+ /// import org.example.ClassD;
+ /// \endcode
+ std::vector<std::string> JavaImportGroups;
+
/// Quotation styles for JavaScript strings. Does not affect template
/// strings.
enum JavaScriptQuoteStyle {
@@ -1724,6 +1764,7 @@ struct FormatStyle {
IndentPPDirectives == R.IndentPPDirectives &&
IndentWidth == R.IndentWidth && Language == R.Language &&
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
+ JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports &&
KeepEmptyLinesAtTheStartOfBlocks ==
@@ -1766,7 +1807,7 @@ struct FormatStyle {
SpacesInParentheses == R.SpacesInParentheses &&
SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
Standard == R.Standard && TabWidth == R.TabWidth &&
- UseTab == R.UseTab;
+ StatementMacros == R.StatementMacros && UseTab == R.UseTab;
}
llvm::Optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const;
@@ -1999,7 +2040,7 @@ extern const char *DefaultFallbackStyle;
llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
StringRef FallbackStyle,
StringRef Code = "",
- vfs::FileSystem *FS = nullptr);
+ llvm::vfs::FileSystem *FS = nullptr);
// Guesses the language from the ``FileName`` and ``Code`` to be formatted.
// Defaults to FormatStyle::LK_Cpp.
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index 2a13527df135..c2144da054f0 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -50,10 +50,6 @@ std::unique_ptr<ASTConsumer> CreateASTDeclNodeLister();
// function declarations to stderr.
std::unique_ptr<ASTConsumer> CreateASTViewer();
-// DeclContext printer: prints out the DeclContext tree in human-readable form
-// to stderr; this is intended for debugging.
-std::unique_ptr<ASTConsumer> CreateDeclContextPrinter();
-
} // end clang namespace
#endif
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index ba145965462f..d0b532cf2d34 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -51,6 +51,11 @@ namespace llvm {
class MemoryBuffer;
+namespace vfs {
+
+class FileSystem;
+
+} // namespace vfs
} // namespace llvm
namespace clang {
@@ -75,12 +80,6 @@ class PreprocessorOptions;
class Sema;
class TargetInfo;
-namespace vfs {
-
-class FileSystem;
-
-} // namespace vfs
-
/// \brief Enumerates the available scopes for skipping function bodies.
enum class SkipFunctionBodiesScope { None, Preamble, PreambleAndMainFile };
@@ -365,12 +364,12 @@ private:
bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
CompilerInvocation &PreambleInvocationIn,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild = true,
unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble();
@@ -698,17 +697,17 @@ private:
/// of this translation unit should be precompiled, to improve the performance
/// of reparsing. Set to zero to disable preambles.
///
- /// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that
- /// preamble is saved to a temporary directory on a RealFileSystem, so in order
- /// for it to be loaded correctly, VFS should have access to it(i.e., be an
- /// overlay over RealFileSystem).
+ /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+ /// Note that preamble is saved to a temporary directory on a RealFileSystem,
+ /// so in order for it to be loaded correctly, VFS should have access to
+ /// it(i.e., be an overlay over RealFileSystem).
///
/// \returns \c true if a catastrophic failure occurred (which means that the
/// \c ASTUnit itself is invalid), or \c false otherwise.
bool LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
unsigned PrecompilePreambleAfterNParses,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
public:
/// Create an ASTUnit from a source file, via a CompilerInvocation
@@ -798,10 +797,11 @@ public:
/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
/// mainly to allow the caller to see the diagnostics.
///
- /// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that
- /// preamble is saved to a temporary directory on a RealFileSystem, so in order
- /// for it to be loaded correctly, VFS should have access to it(i.e., be an
- /// overlay over RealFileSystem). RealFileSystem will be used if \p VFS is nullptr.
+ /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+ /// Note that preamble is saved to a temporary directory on a RealFileSystem,
+ /// so in order for it to be loaded correctly, VFS should have access to
+ /// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used
+ /// if \p VFS is nullptr.
///
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
// shouldn't need to specify them at construction time.
@@ -823,22 +823,22 @@ public:
bool ForSerialization = false,
llvm::Optional<StringRef> ModuleFormat = llvm::None,
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
/// Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit.
///
- /// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that
- /// preamble is saved to a temporary directory on a RealFileSystem, so in order
- /// for it to be loaded correctly, VFS should give an access to this(i.e. be an
- /// overlay over RealFileSystem). FileMgr->getVirtualFileSystem() will be used if
- /// \p VFS is nullptr.
+ /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses.
+ /// Note that preamble is saved to a temporary directory on a RealFileSystem,
+ /// so in order for it to be loaded correctly, VFS should give an access to
+ /// this(i.e. be an overlay over RealFileSystem).
+ /// FileMgr->getVirtualFileSystem() will be used if \p VFS is nullptr.
///
/// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise.
bool Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> RemappedFiles = None,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
/// Free data that will be re-generated on the next parse.
///
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 818c733982d9..83ce079d5e23 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -22,6 +22,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/BuryPointer.h"
#include <cassert>
#include <list>
#include <memory>
@@ -83,7 +84,7 @@ class CompilerInstance : public ModuleLoader {
IntrusiveRefCntPtr<TargetInfo> AuxTarget;
/// The virtual file system.
- IntrusiveRefCntPtr<vfs::FileSystem> VirtualFileSystem;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VirtualFileSystem;
/// The file manager.
IntrusiveRefCntPtr<FileManager> FileMgr;
@@ -384,7 +385,7 @@ public:
bool hasVirtualFileSystem() const { return VirtualFileSystem != nullptr; }
- vfs::FileSystem &getVirtualFileSystem() const {
+ llvm::vfs::FileSystem &getVirtualFileSystem() const {
assert(hasVirtualFileSystem() &&
"Compiler instance has no virtual file system");
return *VirtualFileSystem;
@@ -394,7 +395,7 @@ public:
///
/// \note Most clients should use setFileManager, which will implicitly reset
/// the virtual file system to the one contained in the file manager.
- void setVirtualFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> FS) {
+ void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
VirtualFileSystem = std::move(FS);
}
@@ -411,7 +412,7 @@ public:
}
void resetAndLeakFileManager() {
- BuryPointer(FileMgr.get());
+ llvm::BuryPointer(FileMgr.get());
FileMgr.resetWithoutRelease();
}
@@ -431,7 +432,7 @@ public:
}
void resetAndLeakSourceManager() {
- BuryPointer(SourceMgr.get());
+ llvm::BuryPointer(SourceMgr.get());
SourceMgr.resetWithoutRelease();
}
@@ -453,7 +454,7 @@ public:
std::shared_ptr<Preprocessor> getPreprocessorPtr() { return PP; }
void resetAndLeakPreprocessor() {
- BuryPointer(new std::shared_ptr<Preprocessor>(PP));
+ llvm::BuryPointer(new std::shared_ptr<Preprocessor>(PP));
}
/// Replace the current preprocessor.
@@ -471,7 +472,7 @@ public:
}
void resetAndLeakASTContext() {
- BuryPointer(Context.get());
+ llvm::BuryPointer(Context.get());
Context.resetWithoutRelease();
}
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 1d421f09fdcc..a1874655b040 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -10,11 +10,11 @@
#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/LangStandard.h"
@@ -35,6 +35,12 @@ class ArgList;
} // namespace opt
+namespace vfs {
+
+class FileSystem;
+
+} // namespace vfs
+
} // namespace llvm
namespace clang {
@@ -217,20 +223,13 @@ public:
/// @}
};
-namespace vfs {
-
-class FileSystem;
-
-} // namespace vfs
-
-IntrusiveRefCntPtr<vfs::FileSystem>
+IntrusiveRefCntPtr<llvm::vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags);
-IntrusiveRefCntPtr<vfs::FileSystem>
-createVFSFromCompilerInvocation(const CompilerInvocation &CI,
- DiagnosticsEngine &Diags,
- IntrusiveRefCntPtr<vfs::FileSystem> BaseFS);
+IntrusiveRefCntPtr<llvm::vfs::FileSystem> createVFSFromCompilerInvocation(
+ const CompilerInvocation &CI, DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS);
} // namespace clang
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index 2a4077d34391..22314386e060 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -48,6 +48,12 @@ protected:
/// @name Implementation Action Interface
/// @{
+ /// Prepare to execute the action on the given CompilerInstance.
+ ///
+ /// This is called before executing the action on any inputs, and can modify
+ /// the configuration as needed (including adjusting the input list).
+ virtual bool PrepareToExecuteAction(CompilerInstance &CI) { return true; }
+
/// Create the AST consumer object for this action, if supported.
///
/// This routine is called as part of BeginSourceFile(), which will
@@ -130,11 +136,18 @@ public:
return CurrentInput;
}
- const StringRef getCurrentFile() const {
+ StringRef getCurrentFile() const {
assert(!CurrentInput.isEmpty() && "No current file!");
return CurrentInput.getFile();
}
+ StringRef getCurrentFileOrBufferName() const {
+ assert(!CurrentInput.isEmpty() && "No current file!");
+ return CurrentInput.isFile()
+ ? CurrentInput.getFile()
+ : CurrentInput.getBuffer()->getBufferIdentifier();
+ }
+
InputKind getCurrentFileKind() const {
assert(!CurrentInput.isEmpty() && "No current file!");
return CurrentInput.getKind();
@@ -190,6 +203,11 @@ public:
/// @name Public Action Interface
/// @{
+ /// Prepare the action to execute on the given compiler instance.
+ bool PrepareToExecute(CompilerInstance &CI) {
+ return PrepareToExecuteAction(CI);
+ }
+
/// Prepare the action for processing the input file \p Input.
///
/// This is run after the options and frontend have been initialized,
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 54539a5b3cee..eb1cd688429d 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -142,6 +142,19 @@ private:
CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
};
+class GenerateHeaderModuleAction : public GenerateModuleAction {
+ /// The synthesized module input buffer for the current compilation.
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
+ std::vector<std::string> ModuleHeaders;
+
+private:
+ bool PrepareToExecuteAction(CompilerInstance &CI) override;
+ bool BeginSourceFileAction(CompilerInstance &CI) override;
+
+ std::unique_ptr<raw_pwrite_stream>
+ CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
+};
+
class SyntaxOnlyAction : public ASTFrontendAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
@@ -248,11 +261,6 @@ protected:
void ExecuteAction() override;
};
-class GeneratePTHAction : public PreprocessorFrontendAction {
-protected:
- void ExecuteAction() override;
-};
-
class PreprocessOnlyAction : public PreprocessorFrontendAction {
protected:
void ExecuteAction() override;
diff --git a/include/clang/Frontend/FrontendDiagnostic.h b/include/clang/Frontend/FrontendDiagnostic.h
index 0f37b7ece7e0..14a28845d45a 100644
--- a/include/clang/Frontend/FrontendDiagnostic.h
+++ b/include/clang/Frontend/FrontendDiagnostic.h
@@ -10,19 +10,6 @@
#ifndef LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H
#define LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define FRONTENDSTART
-#include "clang/Basic/DiagnosticFrontendKinds.inc"
-#undef DIAG
- NUM_BUILTIN_FRONTEND_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticFrontend.h"
#endif
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 668df83274eb..92191ebd12a6 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -82,12 +82,12 @@ enum ActionKind {
/// Generate pre-compiled module from a C++ module interface file.
GenerateModuleInterface,
+ /// Generate pre-compiled module from a set of header files.
+ GenerateHeaderModule,
+
/// Generate pre-compiled header.
GeneratePCH,
- /// Generate pre-tokenized header.
- GeneratePTH,
-
/// Only execute frontend initialization.
InitOnly,
@@ -103,9 +103,6 @@ enum ActionKind {
/// Run a plugin action, \see ActionName.
PluginAction,
- /// Print DeclContext and their Decls.
- PrintDeclContext,
-
/// Print the "preamble" of the input file
PrintPreamble,
diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def
index 1e895d785d15..0fdd35f32034 100644
--- a/include/clang/Frontend/LangStandards.def
+++ b/include/clang/Frontend/LangStandards.def
@@ -82,9 +82,12 @@ LANGSTANDARD(c17, "c17",
C, "ISO C 2017",
LineComment | C99 | C11 | C17 | Digraphs | HexFloat)
LANGSTANDARD_ALIAS(c17, "iso9899:2017")
+LANGSTANDARD_ALIAS(c17, "c18")
+LANGSTANDARD_ALIAS(c17, "iso9899:2018")
LANGSTANDARD(gnu17, "gnu17",
C, "ISO C 2017 with GNU extensions",
LineComment | C99 | C11 | C17 | Digraphs | GNUMode | HexFloat)
+LANGSTANDARD_ALIAS(gnu17, "gnu18")
// C++ modes
LANGSTANDARD(cxx98, "c++98",
diff --git a/include/clang/Frontend/PCHContainerOperations.h b/include/clang/Frontend/PCHContainerOperations.h
index 7a12ebc862e7..675efbaf56eb 100644
--- a/include/clang/Frontend/PCHContainerOperations.h
+++ b/include/clang/Frontend/PCHContainerOperations.h
@@ -10,110 +10,6 @@
#ifndef LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H
#define LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H
-#include "clang/Basic/Module.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <memory>
-
-namespace llvm {
-class raw_pwrite_stream;
-}
-
-using llvm::StringRef;
-
-namespace clang {
-
-class ASTConsumer;
-class CodeGenOptions;
-class DiagnosticsEngine;
-class CompilerInstance;
-
-struct PCHBuffer {
- ASTFileSignature Signature;
- llvm::SmallVector<char, 0> Data;
- bool IsComplete;
-};
-
-/// This abstract interface provides operations for creating
-/// containers for serialized ASTs (precompiled headers and clang
-/// modules).
-class PCHContainerWriter {
-public:
- virtual ~PCHContainerWriter() = 0;
- virtual StringRef getFormat() const = 0;
-
- /// Return an ASTConsumer that can be chained with a
- /// PCHGenerator that produces a wrapper file format containing a
- /// serialized AST bitstream.
- virtual std::unique_ptr<ASTConsumer>
- CreatePCHContainerGenerator(CompilerInstance &CI,
- const std::string &MainFileName,
- const std::string &OutputFileName,
- std::unique_ptr<llvm::raw_pwrite_stream> OS,
- std::shared_ptr<PCHBuffer> Buffer) const = 0;
-};
-
-/// This abstract interface provides operations for unwrapping
-/// containers for serialized ASTs (precompiled headers and clang
-/// modules).
-class PCHContainerReader {
-public:
- virtual ~PCHContainerReader() = 0;
- /// Equivalent to the format passed to -fmodule-format=
- virtual StringRef getFormat() const = 0;
-
- /// Returns the serialized AST inside the PCH container Buffer.
- virtual StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0;
-};
-
-/// Implements write operations for a raw pass-through PCH container.
-class RawPCHContainerWriter : public PCHContainerWriter {
- StringRef getFormat() const override { return "raw"; }
-
- /// Return an ASTConsumer that can be chained with a
- /// PCHGenerator that writes the module to a flat file.
- std::unique_ptr<ASTConsumer>
- CreatePCHContainerGenerator(CompilerInstance &CI,
- const std::string &MainFileName,
- const std::string &OutputFileName,
- std::unique_ptr<llvm::raw_pwrite_stream> OS,
- std::shared_ptr<PCHBuffer> Buffer) const override;
-};
-
-/// Implements read operations for a raw pass-through PCH container.
-class RawPCHContainerReader : public PCHContainerReader {
- StringRef getFormat() const override { return "raw"; }
-
- /// Simply returns the buffer contained in Buffer.
- StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
-};
-
-/// A registry of PCHContainerWriter and -Reader objects for different formats.
-class PCHContainerOperations {
- llvm::StringMap<std::unique_ptr<PCHContainerWriter>> Writers;
- llvm::StringMap<std::unique_ptr<PCHContainerReader>> Readers;
-public:
- /// Automatically registers a RawPCHContainerWriter and
- /// RawPCHContainerReader.
- PCHContainerOperations();
- void registerWriter(std::unique_ptr<PCHContainerWriter> Writer) {
- Writers[Writer->getFormat()] = std::move(Writer);
- }
- void registerReader(std::unique_ptr<PCHContainerReader> Reader) {
- Readers[Reader->getFormat()] = std::move(Reader);
- }
- const PCHContainerWriter *getWriterOrNull(StringRef Format) {
- return Writers[Format].get();
- }
- const PCHContainerReader *getReaderOrNull(StringRef Format) {
- return Readers[Format].get();
- }
- const PCHContainerReader &getRawReader() {
- return *getReaderOrNull("raw");
- }
-};
-
-}
+#include "clang/Serialization/PCHContainerOperations.h"
#endif
diff --git a/include/clang/Frontend/PrecompiledPreamble.h b/include/clang/Frontend/PrecompiledPreamble.h
index 6abdbe3a1e1b..6c79895ce1b9 100644
--- a/include/clang/Frontend/PrecompiledPreamble.h
+++ b/include/clang/Frontend/PrecompiledPreamble.h
@@ -26,13 +26,12 @@
namespace llvm {
class MemoryBuffer;
-}
-
-namespace clang {
namespace vfs {
class FileSystem;
}
+} // namespace llvm
+namespace clang {
class CompilerInstance;
class CompilerInvocation;
class DeclGroupRef;
@@ -80,7 +79,8 @@ public:
static llvm::ErrorOr<PrecompiledPreamble>
Build(const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
- DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ DiagnosticsEngine &Diagnostics,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
bool StoreInMemory, PreambleCallbacks &Callbacks);
@@ -99,7 +99,7 @@ public:
/// MainFileBuffer) of the main file.
bool CanReuse(const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
- vfs::FileSystem *VFS) const;
+ llvm::vfs::FileSystem *VFS) const;
/// Changes options inside \p CI to use PCH from this preamble. Also remaps
/// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
@@ -110,14 +110,14 @@ public:
/// responsible for making sure the PrecompiledPreamble instance outlives the
/// compiler run and the AST that will be using the PCH.
void AddImplicitPreamble(CompilerInvocation &CI,
- IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
llvm::MemoryBuffer *MainFileBuffer) const;
/// Configure \p CI to use this preamble.
/// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
/// If this preamble does not match the file, it may parse differently.
void OverridePreamble(CompilerInvocation &CI,
- IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
llvm::MemoryBuffer *MainFileBuffer) const;
private:
@@ -233,15 +233,16 @@ private:
/// Helper function to set up PCH for the preamble into \p CI and \p VFS to
/// with the specified \p Bounds.
void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI,
- IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
llvm::MemoryBuffer *MainFileBuffer) const;
/// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
/// Storage is accessible to clang. This method is an implementation detail of
/// AddImplicitPreamble.
- static void setupPreambleStorage(const PCHStorage &Storage,
- PreprocessorOptions &PreprocessorOpts,
- IntrusiveRefCntPtr<vfs::FileSystem> &VFS);
+ static void
+ setupPreambleStorage(const PCHStorage &Storage,
+ PreprocessorOptions &PreprocessorOpts,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS);
/// Manages the memory buffer or temporary file that stores the PCH.
PCHStorage Storage;
@@ -286,8 +287,7 @@ public:
};
enum class BuildPreambleError {
- PreambleIsEmpty = 1,
- CouldntCreateTempFile,
+ CouldntCreateTempFile = 1,
CouldntCreateTargetInfo,
BeginSourceFileFailed,
CouldntEmitPCH
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 67912a8dfcdd..89a6b90f293f 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -16,13 +16,13 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Basic/VirtualFileSystem.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/OptSpecifier.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <cstdint>
#include <memory>
#include <string>
@@ -134,7 +134,7 @@ class ModuleDependencyCollector : public DependencyCollector {
std::string DestDir;
bool HasErrors = false;
llvm::StringSet<> Seen;
- vfs::YAMLVFSWriter VFSWriter;
+ llvm::vfs::YAMLVFSWriter VFSWriter;
llvm::StringMap<std::string> SymLinkMap;
bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
@@ -183,9 +183,6 @@ void AttachHeaderIncludeGen(Preprocessor &PP,
StringRef OutputPath = {},
bool ShowDepth = true, bool MSStyle = false);
-/// Cache tokens for use with PCH. Note that this requires a seekable stream.
-void CacheTokens(Preprocessor &PP, raw_pwrite_stream *OS);
-
/// The ChainedIncludesSource class converts headers to chained PCHs in
/// memory, mainly for testing.
IntrusiveRefCntPtr<ExternalSemaSource>
@@ -201,7 +198,7 @@ std::unique_ptr<CompilerInvocation> createInvocationFromCommandLine(
ArrayRef<const char *> Args,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
IntrusiveRefCntPtr<DiagnosticsEngine>(),
- IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
/// Return the value of the last argument as an integer, or a default. If Diags
/// is non-null, emits an error if the argument is given, but non-integral.
@@ -226,14 +223,6 @@ inline uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args,
return getLastArgUInt64Value(Args, Id, Default, &Diags);
}
-// When Clang->getFrontendOpts().DisableFree is set we don't delete some of the
-// global objects, but we don't want LeakDetectors to complain, so we bury them
-// in a globally visible array.
-void BuryPointer(const void *Ptr);
-template <typename T> void BuryPointer(std::unique_ptr<T> Ptr) {
- BuryPointer(Ptr.release());
-}
-
// Frontend timing utils
/// If the user specifies the -ftime-report argument on an Clang command line
diff --git a/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h
index 6e11455661a0..c79f6be3e13b 100644
--- a/include/clang/Index/IndexDataConsumer.h
+++ b/include/clang/Index/IndexDataConsumer.h
@@ -50,7 +50,12 @@ public:
SourceLocation Loc);
/// \returns true to continue indexing, or false to abort.
+ ///
+ /// This will be called for each module reference in an import decl.
+ /// For "@import MyMod.SubMod", there will be a call for 'MyMod' with the
+ /// 'reference' role, and a call for 'SubMod' with the 'declaration' role.
virtual bool handleModuleOccurence(const ImportDecl *ImportD,
+ const Module *Mod,
SymbolRoleSet Roles, SourceLocation Loc);
virtual void finish() {}
diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h
index 068796141df8..8aaaa695456c 100644
--- a/include/clang/Index/IndexSymbol.h
+++ b/include/clang/Index/IndexSymbol.h
@@ -75,7 +75,7 @@ enum class SymbolSubKind : uint8_t {
UsingValue,
};
-typedef uint8_t SymbolPropertySet;
+typedef uint16_t SymbolPropertySet;
/// Set of properties that provide additional info about a symbol.
enum class SymbolProperty : SymbolPropertySet {
Generic = 1 << 0,
@@ -86,8 +86,10 @@ enum class SymbolProperty : SymbolPropertySet {
IBOutletCollection = 1 << 5,
GKInspectable = 1 << 6,
Local = 1 << 7,
+ /// Symbol is part of a protocol interface.
+ ProtocolInterface = 1 << 8,
};
-static const unsigned SymbolPropertyBitNum = 8;
+static const unsigned SymbolPropertyBitNum = 9;
/// Set of roles that are attributed to symbol occurrences.
///
diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h
index 0d09c403483d..63e38975ce16 100644
--- a/include/clang/Index/IndexingAction.h
+++ b/include/clang/Index/IndexingAction.h
@@ -12,6 +12,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/ArrayRef.h"
#include <memory>
@@ -40,6 +41,10 @@ struct IndexingOptions {
= SystemSymbolFilterKind::DeclarationsOnly;
bool IndexFunctionLocals = false;
bool IndexImplicitInstantiation = false;
+ // Whether to index macro definitions in the Preprocesor when preprocessor
+ // callback is not available (e.g. after parsing has finished). Note that
+ // macro references are not available in Proprocessor.
+ bool IndexMacrosInPreprocessor = false;
};
/// Creates a frontend action that indexes all symbols (macros and AST decls).
@@ -50,13 +55,12 @@ createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
std::unique_ptr<FrontendAction> WrappedAction);
/// Recursively indexes all decls in the AST.
-/// Note that this does not index macros.
void indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
IndexingOptions Opts);
/// Recursively indexes \p Decls.
-/// Note that this does not index macros.
-void indexTopLevelDecls(ASTContext &Ctx, ArrayRef<const Decl *> Decls,
+void indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP,
+ ArrayRef<const Decl *> Decls,
IndexDataConsumer &DataConsumer, IndexingOptions Opts);
/// Creates a PPCallbacks that indexes macros and feeds macros to \p Consumer.
@@ -65,7 +69,6 @@ std::unique_ptr<PPCallbacks> indexMacrosCallback(IndexDataConsumer &Consumer,
IndexingOptions Opts);
/// Recursively indexes all top-level decls in the module.
-/// FIXME: make this index macros as well.
void indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,
IndexDataConsumer &DataConsumer, IndexingOptions Opts);
diff --git a/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h
index 1ece321746a6..f1389ecc9593 100644
--- a/include/clang/Index/USRGeneration.h
+++ b/include/clang/Index/USRGeneration.h
@@ -14,10 +14,13 @@
#include "llvm/ADT/StringRef.h"
namespace clang {
+class ASTContext;
class Decl;
class MacroDefinitionRecord;
+class Module;
class SourceLocation;
class SourceManager;
+class QualType;
namespace index {
@@ -70,8 +73,30 @@ bool generateUSRForMacro(const MacroDefinitionRecord *MD,
bool generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
const SourceManager &SM, SmallVectorImpl<char> &Buf);
+/// Generates a USR for a type.
+///
+/// \return true on error, false on success.
+bool generateUSRForType(QualType T, ASTContext &Ctx, SmallVectorImpl<char> &Buf);
+
+/// Generate a USR for a module, including the USR prefix.
+/// \returns true on error, false on success.
+bool generateFullUSRForModule(const Module *Mod, raw_ostream &OS);
+
+/// Generate a USR for a top-level module name, including the USR prefix.
+/// \returns true on error, false on success.
+bool generateFullUSRForTopLevelModuleName(StringRef ModName, raw_ostream &OS);
+
+/// Generate a USR fragment for a module.
+/// \returns true on error, false on success.
+bool generateUSRFragmentForModule(const Module *Mod, raw_ostream &OS);
+
+/// Generate a USR fragment for a module name.
+/// \returns true on error, false on success.
+bool generateUSRFragmentForModuleName(StringRef ModName, raw_ostream &OS);
+
+
} // namespace index
} // namespace clang
-#endif // LLVM_CLANG_IDE_USRGENERATION_H
+#endif // LLVM_CLANG_INDEX_USRGENERATION_H
diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h
index 87089fd7d50b..bef804beed00 100644
--- a/include/clang/Lex/CodeCompletionHandler.h
+++ b/include/clang/Lex/CodeCompletionHandler.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
#define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+#include "llvm/ADT/StringRef.h"
+
namespace clang {
class IdentifierInfo;
@@ -60,6 +62,11 @@ public:
MacroInfo *MacroInfo,
unsigned ArgumentIndex) { }
+ /// Callback invoked when performing code completion inside the filename
+ /// part of an #include directive. (Also #import, #include_next, etc).
+ /// \p Dir is the directory relative to the include path.
+ virtual void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) {}
+
/// Callback invoked when performing code completion in a part of the
/// file where we expect natural language, e.g., a comment, string, or
/// \#error directive.
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index 55065b7d8547..bfb496be5072 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -191,7 +191,7 @@ private:
SmallVectorImpl<char> *RelativePath,
Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
- bool &InUserSpecifiedSystemHeader) const;
+ bool &InUserSpecifiedSystemFramework) const;
};
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index 58bf79579a6a..793e7edc2752 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -71,7 +71,8 @@ class HeaderMap : private HeaderMapImpl {
public:
/// This attempts to load the specified file as a header map. If it doesn't
/// look like a HeaderMap, it gives up and returns null.
- static const HeaderMap *Create(const FileEntry *FE, FileManager &FM);
+ static std::unique_ptr<HeaderMap> Create(const FileEntry *FE,
+ FileManager &FM);
/// Check to see if the specified relative filename is located in this
/// HeaderMap. If so, open it and return its FileEntry. If RawPath is not
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 6bb0f58f2db9..7c69e219cb57 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -17,6 +17,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/ModuleMap.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -38,7 +39,6 @@ class DirectoryEntry;
class ExternalPreprocessorSource;
class FileEntry;
class FileManager;
-class HeaderMap;
class HeaderSearchOptions;
class IdentifierInfo;
class LangOptions;
@@ -55,7 +55,7 @@ struct HeaderFileInfo {
/// True if this is a \#pragma once file.
unsigned isPragmaOnce : 1;
- /// DirInfo - Keep track of whether this is a system header, and if so,
+ /// Keep track of whether this is a system header, and if so,
/// whether it is C++ clean or not. This can be set by the include paths or
/// by \#pragma gcc system_header. This is an instance of
/// SrcMgr::CharacteristicKind.
@@ -219,16 +219,15 @@ class HeaderSearch {
/// name like "Carbon" to the Carbon.framework directory.
llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap;
- /// IncludeAliases - maps include file names (including the quotes or
+ /// Maps include file names (including the quotes or
/// angle brackets) to other include file names. This is used to support the
/// include_alias pragma for Microsoft compatibility.
using IncludeAliasMap =
llvm::StringMap<std::string, llvm::BumpPtrAllocator>;
std::unique_ptr<IncludeAliasMap> IncludeAliases;
- /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
- /// headermaps. This vector owns the headermap.
- std::vector<std::pair<const FileEntry *, const HeaderMap *>> HeaderMaps;
+ /// This is a mapping from FileEntry -> HeaderMap, uniquing headermaps.
+ std::vector<std::pair<const FileEntry *, std::unique_ptr<HeaderMap>>> HeaderMaps;
/// The mapping between modules and headers.
mutable ModuleMap ModMap;
@@ -264,7 +263,6 @@ public:
const LangOptions &LangOpts, const TargetInfo *Target);
HeaderSearch(const HeaderSearch &) = delete;
HeaderSearch &operator=(const HeaderSearch &) = delete;
- ~HeaderSearch();
/// Retrieve the header-search options with which this header search
/// was initialized.
@@ -314,7 +312,7 @@ public:
(*IncludeAliases)[Source] = Dest;
}
- /// MapHeaderToIncludeAlias - Maps one header file name to a different header
+ /// Maps one header file name to a different header
/// file name, for use with the include_alias pragma. Note that the source
/// file name should include the angle brackets or quotes. Returns StringRef
/// as null if the header cannot be mapped.
@@ -408,7 +406,7 @@ public:
/// HIToolbox is a subframework within Carbon.framework. If so, return
/// the FileEntry for the designated file, otherwise return null.
const FileEntry *LookupSubframeworkHeader(
- StringRef Filename, const FileEntry *RelativeFileEnt,
+ StringRef Filename, const FileEntry *ContextFileEnt,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
@@ -425,7 +423,7 @@ public:
/// if we should include it.
bool ShouldEnterIncludeFile(Preprocessor &PP, const FileEntry *File,
bool isImport, bool ModulesEnabled,
- Module *CorrespondingModule);
+ Module *M);
/// Return whether the specified file is a normal header,
/// a system header, or a C++ friendly system header.
@@ -448,9 +446,9 @@ public:
}
/// Mark the specified file as part of a module.
- void MarkFileModuleHeader(const FileEntry *File,
+ void MarkFileModuleHeader(const FileEntry *FE,
ModuleMap::ModuleHeaderRole Role,
- bool IsCompiledModuleHeader);
+ bool isCompilingModuleHeader);
/// Increment the count for the number of times the specified
/// FileEntry has been entered.
@@ -479,7 +477,7 @@ public:
/// This routine does not consider the effect of \#import
bool isFileMultipleIncludeGuarded(const FileEntry *File);
- /// CreateHeaderMap - This method returns a HeaderMap for the specified
+ /// This method returns a HeaderMap for the specified
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
@@ -641,7 +639,7 @@ private:
/// \return \c true if the file can be used, \c false if we are not permitted to
/// find this file due to requirements from \p RequestingModule.
bool findUsableModuleForFrameworkHeader(
- const FileEntry *File, StringRef FrameworkDir, Module *RequestingModule,
+ const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework);
/// Look up the file with the specified name and determine its owning
diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h
index 5d724c0de879..3a677b834543 100644
--- a/include/clang/Lex/LexDiagnostic.h
+++ b/include/clang/Lex/LexDiagnostic.h
@@ -10,19 +10,6 @@
#ifndef LLVM_CLANG_LEX_LEXDIAGNOSTIC_H
#define LLVM_CLANG_LEX_LEXDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define LEXSTART
-#include "clang/Basic/DiagnosticLexKinds.inc"
-#undef DIAG
- NUM_BUILTIN_LEX_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticLex.h"
#endif
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 624151ef877b..a9b10b627320 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -139,7 +139,7 @@ public:
/// with the specified preprocessor managing the lexing process. This lexer
/// assumes that the associated file buffer and Preprocessor objects will
/// outlive it, so it doesn't take ownership of either of them.
- Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, Preprocessor &PP);
+ Lexer(FileID FID, const llvm::MemoryBuffer *InputFile, Preprocessor &PP);
/// Lexer constructor - Create a new raw lexer object. This object is only
/// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the
@@ -150,7 +150,7 @@ public:
/// Lexer constructor - Create a new raw lexer object. This object is only
/// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the
/// text range will outlive it, so it doesn't take ownership of it.
- Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer,
+ Lexer(FileID FID, const llvm::MemoryBuffer *FromFile,
const SourceManager &SM, const LangOptions &LangOpts);
Lexer(const Lexer &) = delete;
@@ -310,8 +310,8 @@ public:
/// location.
static StringRef getSpelling(SourceLocation loc,
SmallVectorImpl<char> &buffer,
- const SourceManager &SourceMgr,
- const LangOptions &LangOpts,
+ const SourceManager &SM,
+ const LangOptions &options,
bool *invalid = nullptr);
/// MeasureTokenLength - Relex the token at the specified location and return
@@ -339,7 +339,7 @@ public:
/// Get the physical length (including trigraphs and escaped newlines) of the
/// first \p Characters characters of the token starting at TokStart.
static unsigned getTokenPrefixLength(SourceLocation TokStart,
- unsigned Characters,
+ unsigned CharNo,
const SourceManager &SM,
const LangOptions &LangOpts);
@@ -711,20 +711,22 @@ private:
bool isHexaLiteral(const char *Start, const LangOptions &LangOpts);
+ void codeCompleteIncludedFile(const char *PathStart,
+ const char *CompletionPoint, bool IsAngled);
/// Read a universal character name.
///
- /// \param CurPtr The position in the source buffer after the initial '\'.
- /// If the UCN is syntactically well-formed (but not necessarily
- /// valid), this parameter will be updated to point to the
- /// character after the UCN.
+ /// \param StartPtr The position in the source buffer after the initial '\'.
+ /// If the UCN is syntactically well-formed (but not
+ /// necessarily valid), this parameter will be updated to
+ /// point to the character after the UCN.
/// \param SlashLoc The position in the source buffer of the '\'.
- /// \param Tok The token being formed. Pass \c nullptr to suppress diagnostics
- /// and handle token formation in the caller.
+ /// \param Result The token being formed. Pass \c nullptr to suppress
+ /// diagnostics and handle token formation in the caller.
///
/// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is
/// invalid.
- uint32_t tryReadUCN(const char *&CurPtr, const char *SlashLoc, Token *Tok);
+ uint32_t tryReadUCN(const char *&StartPtr, const char *SlashLoc, Token *Result);
/// Try to consume a UCN as part of an identifier at the current
/// location.
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 0cc1cb92e67e..a06de132b496 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -395,7 +395,8 @@ public:
/// Find macro definition active in the specified source location. If
/// this macro was not defined there, return NULL.
- const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const;
+ const DefInfo findDirectiveAtLoc(SourceLocation L,
+ const SourceManager &SM) const;
void dump() const;
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index aa519891c1ce..a38c8d7819db 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -45,6 +45,8 @@ class SourceManager;
/// A mechanism to observe the actions of the module map parser as it
/// reads module map files.
class ModuleMapCallbacks {
+ virtual void anchor();
+
public:
virtual ~ModuleMapCallbacks() = default;
@@ -92,9 +94,9 @@ class ModuleMap {
/// named LangOpts::CurrentModule, if we've loaded it).
Module *SourceModule = nullptr;
- /// The global module for the current TU, if we still own it. (Ownership is
- /// transferred if/when we create an enclosing module.
- std::unique_ptr<Module> PendingGlobalModule;
+ /// Submodules of the current module that have not yet been attached to it.
+ /// (Ownership is transferred if/when we create an enclosing module.)
+ llvm::SmallVector<std::unique_ptr<Module>, 8> PendingSubmodules;
/// The top-level modules that are known.
llvm::StringMap<Module *> Modules;
@@ -519,8 +521,7 @@ public:
bool IsFramework,
bool IsExplicit);
- /// Create a 'global module' for a C++ Modules TS module interface
- /// unit.
+ /// Create a 'global module' for a C++ Modules TS module interface unit.
///
/// We model the global module as a submodule of the module interface unit.
/// Unfortunately, we can't create the module interface unit's Module until
@@ -537,6 +538,9 @@ public:
Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name,
Module *GlobalModule);
+ /// Create a header module from the specified list of headers.
+ Module *createHeaderModule(StringRef Name, ArrayRef<Module::Header> Headers);
+
/// Infer the contents of a framework module map from the given
/// framework directory.
Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
@@ -580,7 +584,7 @@ public:
/// getContainingModuleMapFile().
const FileEntry *getModuleMapFileForUniquing(const Module *M) const;
- void setInferredModuleAllowedBy(Module *M, const FileEntry *ModuleMap);
+ void setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap);
/// Get any module map files other than getModuleMapFileForUniquing(M)
/// that define submodules of a top-level module \p M. This is cheaper than
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 45c2d18da6e2..2448b34c8af4 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -276,6 +276,12 @@ public:
SourceRange Range) {
}
+ /// Hook called when a '__has_include' or '__has_include_next' directive is
+ /// read.
+ virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
+ const FileEntry *File,
+ SrcMgr::CharacteristicKind FileType) {}
+
/// Hook called when a source range is skipped.
/// \param Range The SourceRange that was skipped. The range begins at the
/// \#if/\#else directive and ends after the \#endif/\#else directive.
@@ -443,6 +449,13 @@ public:
Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
}
+ void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
+ const FileEntry *File,
+ SrcMgr::CharacteristicKind FileType) override {
+ First->HasInclude(Loc, FileName, IsAngled, File, FileType);
+ Second->HasInclude(Loc, FileName, IsAngled, File, FileType);
+ }
+
void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name,
SourceLocation StateLoc, unsigned State) override {
First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h
deleted file mode 100644
index 0b84df1434ae..000000000000
--- a/include/clang/Lex/PTHLexer.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//===- PTHLexer.h - Lexer based on Pre-tokenized input ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the PTHLexer interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LEX_PTHLEXER_H
-#define LLVM_CLANG_LEX_PTHLEXER_H
-
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/TokenKinds.h"
-#include "clang/Lex/PreprocessorLexer.h"
-#include "clang/Lex/Token.h"
-
-namespace clang {
-
-class Preprocessor;
-class PTHManager;
-
-class PTHLexer : public PreprocessorLexer {
- SourceLocation FileStartLoc;
-
- /// TokBuf - Buffer from PTH file containing raw token data.
- const unsigned char* TokBuf;
-
- /// CurPtr - Pointer into current offset of the token buffer where
- /// the next token will be read.
- const unsigned char* CurPtr;
-
- /// LastHashTokPtr - Pointer into TokBuf of the last processed '#'
- /// token that appears at the start of a line.
- const unsigned char* LastHashTokPtr = nullptr;
-
- /// PPCond - Pointer to a side table in the PTH file that provides a
- /// a concise summary of the preprocessor conditional block structure.
- /// This is used to perform quick skipping of conditional blocks.
- const unsigned char* PPCond;
-
- /// CurPPCondPtr - Pointer inside PPCond that refers to the next entry
- /// to process when doing quick skipping of preprocessor blocks.
- const unsigned char* CurPPCondPtr;
-
- /// ReadToken - Used by PTHLexer to read tokens TokBuf.
- void ReadToken(Token &T);
-
- bool LexEndOfFile(Token &Result);
-
- /// PTHMgr - The PTHManager object that created this PTHLexer.
- PTHManager& PTHMgr;
-
- Token EofToken;
-
-protected:
- friend class PTHManager;
-
- /// Create a PTHLexer for the specified token stream.
- PTHLexer(Preprocessor &pp, FileID FID, const unsigned char *D,
- const unsigned char* ppcond, PTHManager &PM);
-
-public:
- PTHLexer(const PTHLexer &) = delete;
- PTHLexer &operator=(const PTHLexer &) = delete;
- ~PTHLexer() override = default;
-
- /// Lex - Return the next token.
- bool Lex(Token &Tok);
-
- void getEOF(Token &Tok);
-
- /// DiscardToEndOfLine - Read the rest of the current preprocessor line as an
- /// uninterpreted string. This switches the lexer out of directive mode.
- void DiscardToEndOfLine();
-
- /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
- /// tok::l_paren token, 0 if it is something else and 2 if there are no more
- /// tokens controlled by this lexer.
- unsigned isNextPPTokenLParen() {
- // isNextPPTokenLParen is not on the hot path, and all we care about is
- // whether or not we are at a token with kind tok::eof or tok::l_paren.
- // Just read the first byte from the current token pointer to determine
- // its kind.
- tok::TokenKind x = (tok::TokenKind)*CurPtr;
- return x == tok::eof ? 2 : x == tok::l_paren;
- }
-
- /// IndirectLex - An indirect call to 'Lex' that can be invoked via
- /// the PreprocessorLexer interface.
- void IndirectLex(Token &Result) override { Lex(Result); }
-
- /// getSourceLocation - Return a source location for the token in
- /// the current file.
- SourceLocation getSourceLocation() override;
-
- /// SkipBlock - Used by Preprocessor to skip the current conditional block.
- bool SkipBlock();
-};
-
-} // namespace clang
-
-#endif // LLVM_CLANG_LEX_PTHLEXER_H
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
deleted file mode 100644
index 483b69f23a9c..000000000000
--- a/include/clang/Lex/PTHManager.h
+++ /dev/null
@@ -1,149 +0,0 @@
-//===- PTHManager.h - Manager object for PTH processing ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the PTHManager interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LEX_PTHMANAGER_H
-#define LLVM_CLANG_LEX_PTHMANAGER_H
-
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/OnDiskHashTable.h"
-#include <memory>
-
-namespace llvm {
-
-class MemoryBuffer;
-
-} // namespace llvm
-
-namespace clang {
-
-class DiagnosticsEngine;
-class FileSystemStatCache;
-class Preprocessor;
-class PTHLexer;
-
-class PTHManager : public IdentifierInfoLookup {
- friend class PTHLexer;
- friend class PTHStatCache;
-
- class PTHFileLookupTrait;
- class PTHStringLookupTrait;
-
- using PTHStringIdLookup = llvm::OnDiskChainedHashTable<PTHStringLookupTrait>;
- using PTHFileLookup = llvm::OnDiskChainedHashTable<PTHFileLookupTrait>;
-
- /// The memory mapped PTH file.
- std::unique_ptr<const llvm::MemoryBuffer> Buf;
-
- /// Alloc - Allocator used for IdentifierInfo objects.
- llvm::BumpPtrAllocator Alloc;
-
- /// IdMap - A lazily generated cache mapping from persistent identifiers to
- /// IdentifierInfo*.
- std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> PerIDCache;
-
- /// FileLookup - Abstract data structure used for mapping between files
- /// and token data in the PTH file.
- std::unique_ptr<PTHFileLookup> FileLookup;
-
- /// IdDataTable - Array representing the mapping from persistent IDs to the
- /// data offset within the PTH file containing the information to
- /// reconsitute an IdentifierInfo.
- const unsigned char* const IdDataTable;
-
- /// SortedIdTable - Abstract data structure mapping from strings to
- /// persistent IDs. This is used by get().
- std::unique_ptr<PTHStringIdLookup> StringIdLookup;
-
- /// NumIds - The number of identifiers in the PTH file.
- const unsigned NumIds;
-
- /// PP - The Preprocessor object that will use this PTHManager to create
- /// PTHLexer objects.
- Preprocessor* PP = nullptr;
-
- /// SpellingBase - The base offset within the PTH memory buffer that
- /// contains the cached spellings for literals.
- const unsigned char* const SpellingBase;
-
- /// OriginalSourceFile - A null-terminated C-string that specifies the name
- /// if the file (if any) that was to used to generate the PTH cache.
- const char* OriginalSourceFile;
-
- /// This constructor is intended to only be called by the static 'Create'
- /// method.
- PTHManager(std::unique_ptr<const llvm::MemoryBuffer> buf,
- std::unique_ptr<PTHFileLookup> fileLookup,
- const unsigned char *idDataTable,
- std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> perIDCache,
- std::unique_ptr<PTHStringIdLookup> stringIdLookup, unsigned numIds,
- const unsigned char *spellingBase, const char *originalSourceFile);
-
- /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached
- /// spelling for a token.
- unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer);
-
- /// GetIdentifierInfo - Used to reconstruct IdentifierInfo objects from the
- /// PTH file.
- IdentifierInfo *GetIdentifierInfo(unsigned PersistentID) {
- // Check if the IdentifierInfo has already been resolved.
- if (IdentifierInfo* II = PerIDCache[PersistentID])
- return II;
- return LazilyCreateIdentifierInfo(PersistentID);
- }
- IdentifierInfo* LazilyCreateIdentifierInfo(unsigned PersistentID);
-
-public:
- // The current PTH version.
- enum { Version = 10 };
-
- PTHManager(const PTHManager &) = delete;
- PTHManager &operator=(const PTHManager &) = delete;
- ~PTHManager() override;
-
- /// getOriginalSourceFile - Return the full path to the original header
- /// file name that was used to generate the PTH cache.
- const char* getOriginalSourceFile() const {
- return OriginalSourceFile;
- }
-
- /// get - Return the identifier token info for the specified named identifier.
- /// Unlike the version in IdentifierTable, this returns a pointer instead
- /// of a reference. If the pointer is nullptr then the IdentifierInfo cannot
- /// be found.
- IdentifierInfo *get(StringRef Name) override;
-
- /// Create - This method creates PTHManager objects. The 'file' argument
- /// is the name of the PTH file. This method returns nullptr upon failure.
- static PTHManager *Create(StringRef file, DiagnosticsEngine &Diags);
-
- void setPreprocessor(Preprocessor *pp) { PP = pp; }
-
- /// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the
- /// specified file. This method returns nullptr if no cached tokens exist.
- /// It is the responsibility of the caller to 'delete' the returned object.
- PTHLexer *CreateLexer(FileID FID);
-
- /// createStatCache - Returns a FileSystemStatCache object for use with
- /// FileManager objects. These objects use the PTH data to speed up
- /// calls to stat by memoizing their results from when the PTH file
- /// was generated.
- std::unique_ptr<FileSystemStatCache> createStatCache();
-};
-
-} // namespace clang
-
-#endif // LLVM_CLANG_LEX_PTHMANAGER_H
diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h
index 4d74face5275..fb2942f0916b 100644
--- a/include/clang/Lex/Pragma.h
+++ b/include/clang/Lex/Pragma.h
@@ -113,7 +113,7 @@ public:
bool IsEmpty() const { return Handlers.empty(); }
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken) override;
+ Token &Tok) override;
PragmaNamespace *getIfNamespace() override { return this; }
};
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 44d79d9b6229..027dd3ac5d55 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/PPCallbacks.h"
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index e718f5b6bbd0..64ddb5307fb0 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -29,7 +29,6 @@
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
-#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
@@ -79,7 +78,6 @@ class PragmaNamespace;
class PreprocessingRecord;
class PreprocessorLexer;
class PreprocessorOptions;
-class PTHManager;
class ScratchBuffer;
class TargetInfo;
@@ -143,10 +141,6 @@ class Preprocessor {
/// External source of macros.
ExternalPreprocessorSource *ExternalSource;
- /// An optional PTHManager object used for getting tokens from
- /// a token cache rather than lexing the original source file.
- std::unique_ptr<PTHManager> PTH;
-
/// A BumpPtrAllocator object used to quickly allocate and release
/// objects internal to the Preprocessor.
llvm::BumpPtrAllocator BP;
@@ -310,6 +304,9 @@ class Preprocessor {
/// on the stem that is to be code completed.
IdentifierInfo *CodeCompletionII = nullptr;
+ /// Range for the code completion token.
+ SourceRange CodeCompletionTokenRange;
+
/// The directory that the main file should be considered to occupy,
/// if it does not correspond to a real file (as happens when building a
/// module).
@@ -322,6 +319,10 @@ class Preprocessor {
/// This is used when loading a precompiled preamble.
std::pair<int, bool> SkipMainFilePreamble;
+ /// Whether we hit an error due to reaching max allowed include depth. Allows
+ /// to avoid hitting the same error over and over again.
+ bool HasReachedMaxIncludeDepth = false;
+
public:
struct PreambleSkipInfo {
SourceLocation HashTokenLoc;
@@ -389,19 +390,13 @@ private:
/// The current top of the stack that we're lexing from if
/// not expanding a macro and we are lexing directly from source code.
///
- /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
+ /// Only one of CurLexer, or CurTokenLexer will be non-null.
std::unique_ptr<Lexer> CurLexer;
- /// The current top of stack that we're lexing from if
- /// not expanding from a macro and we are lexing from a PTH cache.
- ///
- /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
- std::unique_ptr<PTHLexer> CurPTHLexer;
-
/// The current top of the stack what we're lexing from
/// if not expanding a macro.
///
- /// This is an alias for either CurLexer or CurPTHLexer.
+ /// This is an alias for CurLexer.
PreprocessorLexer *CurPPLexer = nullptr;
/// Used to find the current FileEntry, if CurLexer is non-null
@@ -419,7 +414,6 @@ private:
/// The kind of lexer we're currently working with.
enum CurLexerKind {
CLK_Lexer,
- CLK_PTHLexer,
CLK_TokenLexer,
CLK_CachingLexer,
CLK_LexAfterModuleImport
@@ -436,7 +430,6 @@ private:
enum CurLexerKind CurLexerKind;
Module *TheSubmodule;
std::unique_ptr<Lexer> TheLexer;
- std::unique_ptr<PTHLexer> ThePTHLexer;
PreprocessorLexer *ThePPLexer;
std::unique_ptr<TokenLexer> TheTokenLexer;
const DirectoryLookup *TheDirLookup;
@@ -445,13 +438,11 @@ private:
// versions, only needed to pacify MSVC.
IncludeStackInfo(enum CurLexerKind CurLexerKind, Module *TheSubmodule,
std::unique_ptr<Lexer> &&TheLexer,
- std::unique_ptr<PTHLexer> &&ThePTHLexer,
PreprocessorLexer *ThePPLexer,
std::unique_ptr<TokenLexer> &&TheTokenLexer,
const DirectoryLookup *TheDirLookup)
: CurLexerKind(std::move(CurLexerKind)),
TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)),
- ThePTHLexer(std::move(ThePTHLexer)),
ThePPLexer(std::move(ThePPLexer)),
TheTokenLexer(std::move(TheTokenLexer)),
TheDirLookup(std::move(TheDirLookup)) {}
@@ -723,6 +714,9 @@ private:
/// The file ID for the PCH through header.
FileID PCHThroughHeaderFileID;
+ /// Whether tokens are being skipped until a #pragma hdrstop is seen.
+ bool SkippingUntilPragmaHdrStop = false;
+
/// Whether tokens are being skipped until the through header is seen.
bool SkippingUntilPCHThroughHeader = false;
@@ -832,10 +826,6 @@ public:
Builtin::Context &getBuiltinInfo() { return BuiltinInfo; }
llvm::BumpPtrAllocator &getPreprocessorAllocator() { return BP; }
- void setPTHManager(PTHManager* pm);
-
- PTHManager *getPTHManager() { return PTH.get(); }
-
void setExternalSource(ExternalPreprocessorSource *Source) {
ExternalSource = Source;
}
@@ -1122,6 +1112,10 @@ public:
CodeComplete = nullptr;
}
+ /// Hook used by the lexer to invoke the "included file" code
+ /// completion point.
+ void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled);
+
/// Hook used by the lexer to invoke the "natural language" code
/// completion point.
void CodeCompleteNaturalLanguage();
@@ -1131,6 +1125,16 @@ public:
CodeCompletionII = Filter;
}
+ /// Set the code completion token range for detecting replacement range later
+ /// on.
+ void setCodeCompletionTokenRange(const SourceLocation Start,
+ const SourceLocation End) {
+ CodeCompletionTokenRange = {Start, End};
+ }
+ SourceRange getCodeCompletionTokenRange() const {
+ return CodeCompletionTokenRange;
+ }
+
/// Get the code completion token for filtering purposes.
StringRef getCodeCompletionFilter() {
if (CodeCompletionII)
@@ -1147,7 +1151,7 @@ public:
void createPreprocessingRecord();
/// Returns true if the FileEntry is the PCH through header.
- bool isPCHThroughHeader(const FileEntry *File);
+ bool isPCHThroughHeader(const FileEntry *FE);
/// True if creating a PCH with a through header.
bool creatingPCHWithThroughHeader();
@@ -1155,11 +1159,19 @@ public:
/// True if using a PCH with a through header.
bool usingPCHWithThroughHeader();
- /// Skip tokens until after the #include of the through header.
- void SkipTokensUntilPCHThroughHeader();
+ /// True if creating a PCH with a #pragma hdrstop.
+ bool creatingPCHWithPragmaHdrStop();
+
+ /// True if using a PCH with a #pragma hdrstop.
+ bool usingPCHWithPragmaHdrStop();
- /// Process directives while skipping until the through header is found.
- void HandleSkippedThroughHeaderDirective(Token &Result,
+ /// Skip tokens until after the #include of the through header or
+ /// until after a #pragma hdrstop.
+ void SkipTokensWhileUsingPCH();
+
+ /// Process directives while skipping until the through header or
+ /// #pragma hdrstop is found.
+ void HandleSkippedDirectiveWhileUsingPCH(Token &Result,
SourceLocation HashLoc);
/// Enter the specified FileID as the main source file,
@@ -1173,7 +1185,7 @@ public:
/// start lexing tokens from it instead of the current buffer.
///
/// Emits a diagnostic, doesn't enter the file, and returns true on error.
- bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
+ bool EnterSourceFile(FileID FID, const DirectoryLookup *Dir,
SourceLocation Loc);
/// Add a Macro to the top of the include stack and start lexing
@@ -1182,7 +1194,7 @@ public:
/// \param Args specifies the tokens input to a function-like macro.
/// \param ILEnd specifies the location of the ')' for a function-like macro
/// or the identifier for an object-like macro.
- void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroInfo *Macro,
+ void EnterMacro(Token &Tok, SourceLocation ILEnd, MacroInfo *Macro,
MacroArgs *Args);
/// Add a "macro" context to the top of the include stack,
@@ -1428,7 +1440,7 @@ public:
CachedTokens[CachedLexPos-1] = Tok;
}
- /// Recompute the current lexer kind based on the CurLexer/CurPTHLexer/
+ /// Recompute the current lexer kind based on the CurLexer/
/// CurTokenLexer pointers.
void recomputeCurLexerKind();
@@ -1736,7 +1748,7 @@ public:
void SetPoisonReason(IdentifierInfo *II, unsigned DiagID);
/// Display reason for poisoned identifier.
- void HandlePoisonedIdentifier(Token & Tok);
+ void HandlePoisonedIdentifier(Token & Identifier);
void MaybeHandlePoisonedIdentifier(Token & Identifier) {
if(IdentifierInfo * II = Identifier.getIdentifierInfo()) {
@@ -1801,7 +1813,7 @@ public:
/// If not, emit a diagnostic and consume up until the eod.
/// If \p EnableMacros is true, then we consider macros that expand to zero
/// tokens as being ok.
- void CheckEndOfDirective(const char *Directive, bool EnableMacros = false);
+ void CheckEndOfDirective(const char *DirType, bool EnableMacros = false);
/// Read and discard all tokens remaining on the current line until
/// the tok::eod token is found.
@@ -1830,7 +1842,7 @@ public:
///
/// \returns true if the input filename was in <>'s or false if it was
/// in ""'s.
- bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Filename);
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Buffer);
/// Given a "foo" or \<foo> reference, look up the indicated file.
///
@@ -1873,7 +1885,7 @@ public:
/// Lex an on-off-switch (C99 6.10.6p2) and verify that it is
/// followed by EOD. Return true if the token is not a valid on-off-switch.
- bool LexOnOffSwitch(tok::OnOffSwitch &OOS);
+ bool LexOnOffSwitch(tok::OnOffSwitch &Result);
bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
bool *ShadowFlag = nullptr);
@@ -1887,15 +1899,13 @@ private:
void PushIncludeMacroStack() {
assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer");
IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule,
- std::move(CurLexer), std::move(CurPTHLexer),
- CurPPLexer, std::move(CurTokenLexer),
- CurDirLookup);
+ std::move(CurLexer), CurPPLexer,
+ std::move(CurTokenLexer), CurDirLookup);
CurPPLexer = nullptr;
}
void PopIncludeMacroStack() {
CurLexer = std::move(IncludeMacroStack.back().TheLexer);
- CurPTHLexer = std::move(IncludeMacroStack.back().ThePTHLexer);
CurPPLexer = IncludeMacroStack.back().ThePPLexer;
CurTokenLexer = std::move(IncludeMacroStack.back().TheTokenLexer);
CurDirLookup = IncludeMacroStack.back().TheDirLookup;
@@ -1964,9 +1974,6 @@ private:
bool FoundNonSkipPortion, bool FoundElse,
SourceLocation ElseLoc = SourceLocation());
- /// A fast PTH version of SkipExcludedConditionalBlock.
- void PTHSkipExcludedConditionalBlock();
-
/// Information about the result for evaluating an expression for a
/// preprocessor directive.
struct DirectiveEvalResult {
@@ -1993,7 +2000,7 @@ private:
/// If an identifier token is read that is to be expanded as a macro, handle
/// it and return the next token as 'Tok'. If we lexed a token, return true;
/// otherwise the caller should lex again.
- bool HandleMacroExpandedIdentifier(Token &Tok, const MacroDefinition &MD);
+ bool HandleMacroExpandedIdentifier(Token &Identifier, const MacroDefinition &MD);
/// Cache macro expanded tokens for TokenLexers.
//
@@ -2013,7 +2020,7 @@ private:
/// After reading "MACRO(", this method is invoked to read all of the formal
/// arguments specified for the macro invocation. Returns null on error.
MacroArgs *ReadMacroCallArgumentList(Token &MacroName, MacroInfo *MI,
- SourceLocation &ExpansionEnd);
+ SourceLocation &MacroEnd);
/// If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
@@ -2032,10 +2039,6 @@ private:
/// start lexing tokens from it instead of the current buffer.
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
- /// Add a lexer to the top of the include stack and
- /// start getting tokens from it using the PTH cache.
- void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
-
/// Set the FileID for the preprocessor predefines.
void setPredefinesFileID(FileID FID) {
assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!");
@@ -2066,8 +2069,7 @@ private:
bool InCachingLexMode() const {
// If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
// that we are past EOF, not that we are in CachingLex mode.
- return !CurPPLexer && !CurTokenLexer && !CurPTHLexer &&
- !IncludeMacroStack.empty();
+ return !CurPPLexer && !CurTokenLexer && !IncludeMacroStack.empty();
}
void EnterCachingLexMode();
@@ -2164,17 +2166,17 @@ private:
void replayPreambleConditionalStack();
// Macro handling.
- void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
+ void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterHeaderGuard);
void HandleUndefDirective();
// Conditional Inclusion.
- void HandleIfdefDirective(Token &Tok, const Token &HashToken,
+ void HandleIfdefDirective(Token &Result, const Token &HashToken,
bool isIfndef, bool ReadAnyTokensBeforeDirective);
- void HandleIfDirective(Token &Tok, const Token &HashToken,
+ void HandleIfDirective(Token &IfToken, const Token &HashToken,
bool ReadAnyTokensBeforeDirective);
- void HandleEndifDirective(Token &Tok);
- void HandleElseDirective(Token &Tok, const Token &HashToken);
- void HandleElifDirective(Token &Tok, const Token &HashToken);
+ void HandleEndifDirective(Token &EndifToken);
+ void HandleElseDirective(Token &Result, const Token &HashToken);
+ void HandleElifDirective(Token &ElifToken, const Token &HashToken);
// Pragmas.
void HandlePragmaDirective(SourceLocation IntroducerLoc,
@@ -2190,11 +2192,12 @@ public:
void HandlePragmaPopMacro(Token &Tok);
void HandlePragmaIncludeAlias(Token &Tok);
void HandlePragmaModuleBuild(Token &Tok);
+ void HandlePragmaHdrstop(Token &Tok);
IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok);
// Return true and store the first token only if any CommentHandler
// has inserted some tokens and getCommentRetentionState() is false.
- bool HandleComment(Token &Token, SourceRange Comment);
+ bool HandleComment(Token &result, SourceRange Comment);
/// A macro is used, update information about macros that need unused
/// warnings.
diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h
index b619f192f530..de918a215302 100644
--- a/include/clang/Lex/PreprocessorLexer.h
+++ b/include/clang/Lex/PreprocessorLexer.h
@@ -135,7 +135,7 @@ public:
///
/// If the sequence parsed is not lexically legal, emit a diagnostic and
/// return a result EOD token.
- void LexIncludeFilename(Token &Result);
+ void LexIncludeFilename(Token &FilenameTok);
/// Inform the lexer whether or not we are currently lexing a
/// preprocessor directive.
diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h
index 5134aeaa6a29..f1ac72c47428 100644
--- a/include/clang/Lex/PreprocessorOptions.h
+++ b/include/clang/Lex/PreprocessorOptions.h
@@ -54,6 +54,16 @@ public:
/// definitions and expansions.
bool DetailedRecord = false;
+ /// When true, we are creating or using a PCH where a #pragma hdrstop is
+ /// expected to indicate the beginning or end of the PCH.
+ bool PCHWithHdrStop = false;
+
+ /// When true, we are creating a PCH or creating the PCH object while
+ /// expecting a #pragma hdrstop to separate the two. Allow for a
+ /// missing #pragma hdrstop, which generates a PCH for the whole file,
+ /// and creates an empty PCH object.
+ bool PCHWithHdrStopCreate = false;
+
/// If non-empty, the filename used in an #include directive in the primary
/// source file (or command-line preinclude) that is used to implement
/// MSVC-style precompiled headers. When creating a PCH, after the #include
@@ -100,13 +110,6 @@ public:
/// clients don't use them.
bool WriteCommentListToPCH = true;
- /// The implicit PTH input included at the start of the translation unit, or
- /// empty.
- std::string ImplicitPTHInclude;
-
- /// If given, a PTH cache file to use for speeding up header parsing.
- std::string TokenCache;
-
/// When enabled, preprocessor is in a mode for parsing a single file only.
///
/// Disables #includes of other files and if there are unresolved identifiers
@@ -194,8 +197,6 @@ public:
ChainedIncludes.clear();
DumpDeserializedPCHDecls = false;
ImplicitPCHInclude.clear();
- ImplicitPTHInclude.clear();
- TokenCache.clear();
SingleFileParseMode = false;
LexEditorPlaceholders = true;
RetainRemappedFileBuffers = true;
diff --git a/include/clang/Lex/TokenConcatenation.h b/include/clang/Lex/TokenConcatenation.h
index 60c182b509a4..3199e36f0d26 100644
--- a/include/clang/Lex/TokenConcatenation.h
+++ b/include/clang/Lex/TokenConcatenation.h
@@ -29,7 +29,7 @@ namespace clang {
/// and ")" next to each other is safe.
///
class TokenConcatenation {
- Preprocessor &PP;
+ const Preprocessor &PP;
enum AvoidConcatInfo {
/// By default, a token never needs to avoid concatenation. Most tokens
@@ -56,7 +56,7 @@ namespace clang {
/// method.
char TokenInfo[tok::NUM_TOKENS];
public:
- TokenConcatenation(Preprocessor &PP);
+ TokenConcatenation(const Preprocessor &PP);
bool AvoidConcat(const Token &PrevPrevTok,
const Token &PrevTok,
diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h
index 98935ad9c4fa..6aae9eec7bfa 100644
--- a/include/clang/Lex/TokenLexer.h
+++ b/include/clang/Lex/TokenLexer.h
@@ -31,18 +31,17 @@ class VAOptExpansionContext;
class TokenLexer {
friend class Preprocessor;
- /// Macro - The macro we are expanding from. This is null if expanding a
- /// token stream.
+ /// The macro we are expanding from. This is null if expanding a token stream.
MacroInfo *Macro = nullptr;
- /// ActualArgs - The actual arguments specified for a function-like macro, or
- /// null. The TokenLexer owns the pointed-to object.
+ /// The actual arguments specified for a function-like macro, or null. The
+ /// TokenLexer owns the pointed-to object.
MacroArgs *ActualArgs = nullptr;
- /// PP - The current preprocessor object we are expanding for.
+ /// The current preprocessor object we are expanding for.
Preprocessor &PP;
- /// Tokens - This is the pointer to an array of tokens that the macro is
+ /// This is the pointer to an array of tokens that the macro is
/// defined to, with arguments expanded for function-like macros. If this is
/// a token stream, these are the tokens we are returning. This points into
/// the macro definition we are lexing from, a cache buffer that is owned by
@@ -52,14 +51,13 @@ class TokenLexer {
/// may update the pointer as needed.
const Token *Tokens;
- /// NumTokens - This is the length of the Tokens array.
+ /// This is the length of the Tokens array.
unsigned NumTokens;
/// This is the index of the next token that Lex will return.
unsigned CurTokenIdx;
- /// ExpandLocStart/End - The source location range where this macro was
- /// expanded.
+ /// The source location range where this macro was expanded.
SourceLocation ExpandLocStart, ExpandLocEnd;
/// Source location pointing at the source location entry chunk that
@@ -81,7 +79,7 @@ class TokenLexer {
bool AtStartOfLine : 1;
bool HasLeadingSpace : 1;
- // NextTokGetsSpace - When this is true, the next token appended to the
+ // When this is true, the next token appended to the
// output list during function argument expansion will get a leading space,
// regardless of whether it had one to begin with or not. This is used for
// placemarker support. If still true after function argument expansion, the
@@ -89,13 +87,13 @@ class TokenLexer {
// expansion.
bool NextTokGetsSpace : 1;
- /// OwnsTokens - This is true if this TokenLexer allocated the Tokens
+ /// This is true if this TokenLexer allocated the Tokens
/// array, and thus needs to free it when destroyed. For simple object-like
/// macros (for example) we just point into the token buffer of the macro
/// definition, we don't make a copy of it.
bool OwnsTokens : 1;
- /// DisableMacroExpansion - This is true when tokens lexed from the TokenLexer
+ /// This is true when tokens lexed from the TokenLexer
/// should not be subject to further macro expansion.
bool DisableMacroExpansion : 1;
@@ -123,14 +121,14 @@ public:
TokenLexer &operator=(const TokenLexer &) = delete;
~TokenLexer() { destroy(); }
- /// Init - Initialize this TokenLexer to expand from the specified macro
+ /// Initialize this TokenLexer to expand from the specified macro
/// with the specified argument information. Note that this ctor takes
/// ownership of the ActualArgs pointer. ILEnd specifies the location of the
/// ')' for a function-like macro or the identifier for an object-like macro.
- void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
- MacroArgs *ActualArgs);
+ void Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI,
+ MacroArgs *Actuals);
- /// Init - Initialize this TokenLexer with the specified token stream.
+ /// Initialize this TokenLexer with the specified token stream.
/// This does not take ownership of the specified token vector.
///
/// DisableExpansion is true when macro expansion of tokens lexed from this
@@ -138,12 +136,12 @@ public:
void Init(const Token *TokArray, unsigned NumToks,
bool DisableMacroExpansion, bool OwnsTokens);
- /// isNextTokenLParen - If the next token lexed will pop this macro off the
+ /// If the next token lexed will pop this macro off the
/// expansion stack, return 2. If the next unexpanded token is a '(', return
/// 1, otherwise return 0.
unsigned isNextTokenLParen() const;
- /// Lex - Lex and return a token from this macro stream.
+ /// Lex and return a token from this macro stream.
bool Lex(Token &Tok);
/// isParsingPreprocessorDirective - Return true if we are in the middle of a
@@ -153,8 +151,8 @@ public:
private:
void destroy();
- /// isAtEnd - Return true if the next lex call will pop this macro off the
- /// include stack.
+ /// Return true if the next lex call will pop this macro off the include
+ /// stack.
bool isAtEnd() const {
return CurTokenIdx == NumTokens;
}
@@ -193,7 +191,7 @@ private:
/// them into a string. \p VCtx is used to determine which token represents
/// the first __VA_OPT__ replacement token.
///
- /// \param[in,out] ReplacementToks - Contains the current Replacement Tokens
+ /// \param[in,out] ResultToks - Contains the current Replacement Tokens
/// (prior to rescanning and token pasting), the tail end of which represents
/// the tokens just expanded through __VA_OPT__ processing. These (sub)
/// sequence of tokens are folded into one stringified token.
@@ -201,7 +199,7 @@ private:
/// \param[in] VCtx - contains relevant contextual information about the
/// state of the tokens around and including the __VA_OPT__ token, necessary
/// for stringification.
- void stringifyVAOPTContents(SmallVectorImpl<Token> &ReplacementToks,
+ void stringifyVAOPTContents(SmallVectorImpl<Token> &ResultToks,
const VAOptExpansionContext &VCtx,
SourceLocation VAOPTClosingParenLoc);
@@ -209,7 +207,7 @@ private:
/// return preexpanded tokens from Tokens.
void ExpandFunctionArguments();
- /// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes
+ /// In microsoft compatibility mode, /##/ pastes
/// together to form a comment that comments out everything in the current
/// macro, other active macros, and anything left on the current physical
/// source line of the expanded buffer. Handle this by returning the
diff --git a/include/clang/Sema/LoopHint.h b/include/clang/Parse/LoopHint.h
index 171435e69bc8..be133703268d 100644
--- a/include/clang/Sema/LoopHint.h
+++ b/include/clang/Parse/LoopHint.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_LOOPHINT_H
-#define LLVM_CLANG_SEMA_LOOPHINT_H
+#ifndef LLVM_CLANG_PARSE_LOOPHINT_H
+#define LLVM_CLANG_PARSE_LOOPHINT_H
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
@@ -42,4 +42,4 @@ struct LoopHint {
} // end namespace clang
-#endif // LLVM_CLANG_SEMA_LOOPHINT_H
+#endif // LLVM_CLANG_PARSE_LOOPHINT_H
diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h
index f3a7f3b7a8d7..c7c62688cbaa 100644
--- a/include/clang/Parse/ParseDiagnostic.h
+++ b/include/clang/Parse/ParseDiagnostic.h
@@ -10,19 +10,6 @@
#ifndef LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H
#define LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define PARSESTART
-#include "clang/Basic/DiagnosticParseKinds.inc"
-#undef DIAG
- NUM_BUILTIN_PARSE_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticParse.h"
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 69bf88a371db..438ff0e2ed45 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_PARSE_PARSER_H
#define LLVM_CLANG_PARSE_PARSER_H
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Availability.h"
#include "clang/Basic/BitmaskEnum.h"
#include "clang/Basic/OpenMPKinds.h"
@@ -22,7 +23,6 @@
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/LoopHint.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
@@ -38,6 +38,7 @@ namespace clang {
class CorrectionCandidateCallback;
class DeclGroupRef;
class DiagnosticBuilder;
+ struct LoopHint;
class Parser;
class ParsingDeclRAIIObject;
class ParsingDeclSpec;
@@ -119,7 +120,7 @@ class Parser : public CodeCompletionHandler {
IdentifierInfo *Ident_pixel;
/// Objective-C contextual keywords.
- mutable IdentifierInfo *Ident_instancetype;
+ IdentifierInfo *Ident_instancetype;
/// Identifier for "introduced".
IdentifierInfo *Ident_introduced;
@@ -185,6 +186,8 @@ class Parser : public CodeCompletionHandler {
std::unique_ptr<PragmaHandler> LoopHintHandler;
std::unique_ptr<PragmaHandler> UnrollHintHandler;
std::unique_ptr<PragmaHandler> NoUnrollHintHandler;
+ std::unique_ptr<PragmaHandler> UnrollAndJamHintHandler;
+ std::unique_ptr<PragmaHandler> NoUnrollAndJamHintHandler;
std::unique_ptr<PragmaHandler> FPHandler;
std::unique_ptr<PragmaHandler> STDCFENVHandler;
std::unique_ptr<PragmaHandler> STDCCXLIMITHandler;
@@ -212,6 +215,11 @@ class Parser : public CodeCompletionHandler {
/// should not be set directly.
bool InMessageExpression;
+ /// Gets set to true after calling ProduceSignatureHelp, it is for a
+ /// workaround to make sure ProduceSignatureHelp is only called at the deepest
+ /// function call.
+ bool CalledSignatureHelp = false;
+
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;
@@ -352,6 +360,11 @@ class Parser : public CodeCompletionHandler {
/// just a regular sub-expression.
SourceLocation ExprStatementTokLoc;
+ /// Tests whether an expression value is discarded based on token lookahead.
+ /// It will return true if the lexer is currently processing the })
+ /// terminating a GNU statement expression and false otherwise.
+ bool isExprValueDiscarded();
+
public:
Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
~Parser() override;
@@ -668,6 +681,10 @@ private:
void HandlePragmaFPContract();
/// Handle the annotation token produced for
+ /// #pragma STDC FENV_ACCESS...
+ void HandlePragmaFEnvAccess();
+
+ /// \brief Handle the annotation token produced for
/// #pragma clang fp ...
void HandlePragmaFP();
@@ -793,7 +810,7 @@ private:
///
/// Should only be used in Objective-C language modes.
bool isObjCInstancetype() {
- assert(getLangOpts().ObjC1);
+ assert(getLangOpts().ObjC);
if (Tok.isAnnotation())
return false;
if (!Ident_instancetype)
@@ -1782,10 +1799,12 @@ private:
SourceLocation Start);
//===--------------------------------------------------------------------===//
- // C++ if/switch/while condition expression.
+ // C++ if/switch/while/for condition expression.
+ struct ForRangeInfo;
Sema::ConditionResult ParseCXXCondition(StmtResult *InitStmt,
SourceLocation Loc,
- Sema::ConditionKind CK);
+ Sema::ConditionKind CK,
+ ForRangeInfo *FRI = nullptr);
//===--------------------------------------------------------------------===//
// C++ Coroutines
@@ -1875,6 +1894,7 @@ private:
StmtResult ParseCompoundStatement(bool isStmtExpr,
unsigned ScopeFlags);
void ParseCompoundStatementLeadingPragmas();
+ bool ConsumeNullStmt(StmtVector &Stmts);
StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(StmtResult *InitStmt,
Sema::ConditionResult &CondResult,
@@ -2034,6 +2054,9 @@ private:
bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); }
};
+ struct ForRangeInfo : ForRangeInit {
+ StmtResult LoopVar;
+ };
DeclGroupPtrTy ParseDeclaration(DeclaratorContext Context,
SourceLocation &DeclEnd,
@@ -2128,6 +2151,8 @@ private:
// 'for-init-statement' part of a 'for' statement.
/// Returns true for declaration, false for expression.
bool isForInitDeclaration() {
+ if (getLangOpts().OpenMP)
+ Actions.startOpenMPLoop();
if (getLangOpts().CPlusPlus)
return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/true);
return isDeclarationSpecifier(true);
@@ -2204,13 +2229,15 @@ private:
Expression, ///< Disambiguated as an expression (either kind).
ConditionDecl, ///< Disambiguated as the declaration form of condition.
InitStmtDecl, ///< Disambiguated as a simple-declaration init-statement.
+ ForRangeDecl, ///< Disambiguated as a for-range declaration.
Error ///< Can't be any of the above!
};
/// Disambiguates between the different kinds of things that can happen
/// after 'if (' or 'switch ('. This could be one of two different kinds of
/// declaration (depending on whether there is a ';' later) or an expression.
ConditionOrInitStatement
- isCXXConditionDeclarationOrInitStatement(bool CanBeInitStmt);
+ isCXXConditionDeclarationOrInitStatement(bool CanBeInitStmt,
+ bool CanBeForRangeDecl);
bool isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous);
bool isCXXTypeId(TentativeCXXTypeIdContext Context) {
@@ -2639,9 +2666,16 @@ private:
DeclGroupPtrTy ParseNamespace(DeclaratorContext Context,
SourceLocation &DeclEnd,
SourceLocation InlineLoc = SourceLocation());
- void ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
- std::vector<IdentifierInfo *> &Ident,
- std::vector<SourceLocation> &NamespaceLoc,
+
+ struct InnerNamespaceInfo {
+ SourceLocation NamespaceLoc;
+ SourceLocation InlineLoc;
+ SourceLocation IdentLoc;
+ IdentifierInfo *Ident;
+ };
+ using InnerNamespaceInfoList = llvm::SmallVector<InnerNamespaceInfo, 4>;
+
+ void ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
unsigned int index, SourceLocation &InlineLoc,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker);
@@ -2747,6 +2781,11 @@ private:
DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr,
CachedTokens &Toks,
SourceLocation Loc);
+ /// Parse clauses for '#pragma omp declare target'.
+ DeclGroupPtrTy ParseOMPDeclareTargetClauses();
+ /// Parse '#pragma omp end declare target'.
+ void ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
+ SourceLocation Loc);
/// Parses declarative OpenMP directives.
DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
@@ -2843,7 +2882,10 @@ public:
DeclarationNameInfo ReductionId;
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
OpenMPLinearClauseKind LinKind = OMPC_LINEAR_val;
- OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+ SmallVector<OpenMPMapModifierKind, OMPMapClause::NumberOfModifiers>
+ MapTypeModifiers;
+ SmallVector<SourceLocation, OMPMapClause::NumberOfModifiers>
+ MapTypeModifiersLoc;
OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
bool IsMapTypeImplicit = false;
SourceLocation DepLinMapLoc;
@@ -2958,6 +3000,7 @@ private:
void CodeCompletePreprocessorExpression() override;
void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo,
unsigned ArgumentIndex) override;
+ void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) override;
void CodeCompleteNaturalLanguage() override;
};
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index ede3ddf91993..5e46a84128d5 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -17,6 +17,7 @@
#include "clang-c/Index.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Lex/MacroInfo.h"
#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/ArrayRef.h"
@@ -271,11 +272,15 @@ public:
CCC_Type,
/// Code completion occurred where a new name is expected.
- CCC_Name,
+ CCC_NewName,
- /// Code completion occurred where a new name is expected and a
- /// qualified name is permissible.
- CCC_PotentiallyQualifiedName,
+ /// Code completion occurred where both a new name and an existing symbol is
+ /// permissible.
+ CCC_SymbolOrNewName,
+
+ /// Code completion occurred where an existing name(such as type, function
+ /// or variable) is expected.
+ CCC_Symbol,
/// Code completion occurred where an macro is being defined.
CCC_MacroName,
@@ -322,6 +327,9 @@ public:
/// Code completion where an Objective-C category name is expected.
CCC_ObjCCategoryName,
+ /// Code completion inside the filename part of a #include directive.
+ CCC_IncludedFile,
+
/// An unknown context, in which we are recovering from a parsing
/// error and don't know which completions we should give.
CCC_Recovery
@@ -817,6 +825,9 @@ public:
/// Whether this result is hidden by another name.
bool Hidden : 1;
+ /// Whether this is a class member from base class.
+ bool InBaseClass : 1;
+
/// Whether this result was found via lookup into a base class.
bool QualifierIsInformative : 1;
@@ -843,6 +854,11 @@ public:
/// corresponding `using decl::qualified::name;` nearby.
const UsingShadowDecl *ShadowDecl = nullptr;
+ /// If the result is RK_Macro, this can store the information about the macro
+ /// definition. This should be set in most cases but can be missing when
+ /// the macro has been undefined.
+ const MacroInfo *MacroDefInfo = nullptr;
+
/// Build a result that refers to a declaration.
CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority,
NestedNameSpecifier *Qualifier = nullptr,
@@ -850,7 +866,7 @@ public:
bool Accessible = true,
std::vector<FixItHint> FixIts = std::vector<FixItHint>())
: Declaration(Declaration), Priority(Priority), Kind(RK_Declaration),
- FixIts(std::move(FixIts)), Hidden(false),
+ FixIts(std::move(FixIts)), Hidden(false), InBaseClass(false),
QualifierIsInformative(QualifierIsInformative),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
DeclaringEntity(false), Qualifier(Qualifier) {
@@ -861,35 +877,38 @@ public:
/// Build a result that refers to a keyword or symbol.
CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
: Keyword(Keyword), Priority(Priority), Kind(RK_Keyword),
- CursorKind(CXCursor_NotImplemented), Hidden(false),
+ CursorKind(CXCursor_NotImplemented), Hidden(false), InBaseClass(false),
QualifierIsInformative(false), StartsNestedNameSpecifier(false),
AllParametersAreInformative(false), DeclaringEntity(false) {}
/// Build a result that refers to a macro.
CodeCompletionResult(const IdentifierInfo *Macro,
+ const MacroInfo *MI = nullptr,
unsigned Priority = CCP_Macro)
: Macro(Macro), Priority(Priority), Kind(RK_Macro),
- CursorKind(CXCursor_MacroDefinition), Hidden(false),
+ CursorKind(CXCursor_MacroDefinition), Hidden(false), InBaseClass(false),
QualifierIsInformative(false), StartsNestedNameSpecifier(false),
- AllParametersAreInformative(false), DeclaringEntity(false) {}
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ MacroDefInfo(MI) {}
/// Build a result that refers to a pattern.
- CodeCompletionResult(CodeCompletionString *Pattern,
- unsigned Priority = CCP_CodePattern,
- CXCursorKind CursorKind = CXCursor_NotImplemented,
- CXAvailabilityKind Availability = CXAvailability_Available,
- const NamedDecl *D = nullptr)
+ CodeCompletionResult(
+ CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern,
+ CXCursorKind CursorKind = CXCursor_NotImplemented,
+ CXAvailabilityKind Availability = CXAvailability_Available,
+ const NamedDecl *D = nullptr)
: Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
CursorKind(CursorKind), Availability(Availability), Hidden(false),
- QualifierIsInformative(false), StartsNestedNameSpecifier(false),
- AllParametersAreInformative(false), DeclaringEntity(false) {}
+ InBaseClass(false), QualifierIsInformative(false),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false) {}
/// Build a result that refers to a pattern with an associated
/// declaration.
CodeCompletionResult(CodeCompletionString *Pattern, const NamedDecl *D,
unsigned Priority)
: Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
- Hidden(false), QualifierIsInformative(false),
+ Hidden(false), InBaseClass(false), QualifierIsInformative(false),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
DeclaringEntity(false) {
computeCursorKindAndAvailability();
@@ -935,6 +954,16 @@ public:
CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo);
+ CodeCompletionString *createCodeCompletionStringForDecl(
+ Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
+ bool IncludeBriefComments, const CodeCompletionContext &CCContext,
+ PrintingPolicy &Policy);
+
+ CodeCompletionString *createCodeCompletionStringForOverride(
+ Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
+ bool IncludeBriefComments, const CodeCompletionContext &CCContext,
+ PrintingPolicy &Policy);
+
/// Retrieve the name that should be used to order a result.
///
/// If the name needs to be constructed as a string, that string will be
@@ -1114,9 +1143,13 @@ public:
/// \param Candidates an array of overload candidates.
///
/// \param NumCandidates the number of overload candidates
+ ///
+ /// \param OpenParLoc location of the opening parenthesis of the argument
+ /// list.
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
- unsigned NumCandidates) {}
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc) {}
//@}
/// Retrieve the allocator that will be used to allocate
@@ -1166,7 +1199,8 @@ public:
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
- unsigned NumCandidates) override;
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc) override;
bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h
index 1d3bbb4e585d..26f7f9d19f8e 100644
--- a/include/clang/Sema/CodeCompleteOptions.h
+++ b/include/clang/Sema/CodeCompleteOptions.h
@@ -36,7 +36,8 @@ public:
unsigned IncludeBriefComments : 1;
/// Hint whether to load data from the external AST to provide full results.
- /// If false, namespace-level declarations from the preamble may be omitted.
+ /// If false, namespace-level declarations and macros from the preamble may be
+ /// omitted.
unsigned LoadExternal : 1;
/// Include results after corrections (small fix-its), e.g. change '.' to '->'
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 2e70203c6cc0..8d6f0bc9148b 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -505,8 +505,8 @@ public:
const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceLocation getTypeSpecWidthLoc() const { return TSWRange.getBegin(); }
SourceRange getTypeSpecWidthRange() const { return TSWRange; }
@@ -593,6 +593,18 @@ public:
FS_noreturnLoc = SourceLocation();
}
+ /// This method calls the passed in handler on each CVRU qual being
+ /// set.
+ /// Handle - a handler to be invoked.
+ void forEachCVRUQualifier(
+ llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle);
+
+ /// This method calls the passed in handler on each qual being
+ /// set.
+ /// Handle - a handler to be invoked.
+ void forEachQualifier(
+ llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle);
+
/// Return true if any type-specifier has been found.
bool hasTypeSpecifier() const {
return getTypeSpecType() != DeclSpec::TST_unspecified ||
@@ -683,6 +695,8 @@ public:
ExprRep = Rep;
}
+ bool SetTypeQual(TQ T, SourceLocation Loc);
+
bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, const LangOptions &Lang);
@@ -1120,8 +1134,8 @@ public:
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(StartLocation, EndLocation);
}
- SourceLocation getLocStart() const LLVM_READONLY { return StartLocation; }
- SourceLocation getLocEnd() const LLVM_READONLY { return EndLocation; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return StartLocation; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return EndLocation; }
};
/// A set of tokens that has been cached for later parsing.
@@ -1250,10 +1264,6 @@ struct DeclaratorChunk {
/// Otherwise, it's an rvalue reference.
unsigned RefQualifierIsLValueRef : 1;
- /// The type qualifiers: const/volatile/restrict/__unaligned
- /// The qualifier bitmask values are the same as in QualType.
- unsigned TypeQuals : 4;
-
/// ExceptionSpecType - An ExceptionSpecificationType value.
unsigned ExceptionSpecType : 4;
@@ -1287,21 +1297,6 @@ struct DeclaratorChunk {
/// If this is an invalid location, there is no ref-qualifier.
unsigned RefQualifierLoc;
- /// The location of the const-qualifier, if any.
- ///
- /// If this is an invalid location, there is no const-qualifier.
- unsigned ConstQualifierLoc;
-
- /// The location of the volatile-qualifier, if any.
- ///
- /// If this is an invalid location, there is no volatile-qualifier.
- unsigned VolatileQualifierLoc;
-
- /// The location of the restrict-qualifier, if any.
- ///
- /// If this is an invalid location, there is no restrict-qualifier.
- unsigned RestrictQualifierLoc;
-
/// The location of the 'mutable' qualifer in a lambda-declarator, if
/// any.
unsigned MutableLoc;
@@ -1317,6 +1312,12 @@ struct DeclaratorChunk {
/// there are no parameters specified.
ParamInfo *Params;
+ /// DeclSpec for the function with the qualifier related info.
+ DeclSpec *MethodQualifiers;
+
+ /// AtttibuteFactory for the MethodQualifiers.
+ AttributeFactory *QualAttrFactory;
+
union {
/// Pointer to a new[]'d array of TypeAndRange objects that
/// contain the types in the function's dynamic exception specification
@@ -1356,6 +1357,8 @@ struct DeclaratorChunk {
void destroy() {
freeParams();
+ delete QualAttrFactory;
+ delete MethodQualifiers;
switch (getExceptionSpecType()) {
default:
break;
@@ -1372,6 +1375,14 @@ struct DeclaratorChunk {
}
}
+ DeclSpec &getOrCreateMethodQualifiers() {
+ if (!MethodQualifiers) {
+ QualAttrFactory = new AttributeFactory();
+ MethodQualifiers = new DeclSpec(*QualAttrFactory);
+ }
+ return *MethodQualifiers;
+ }
+
/// isKNRPrototype - Return true if this is a K&R style identifier list,
/// like "void foo(a,b,c)". In a function definition, this will be followed
/// by the parameter type definitions.
@@ -1406,19 +1417,22 @@ struct DeclaratorChunk {
return SourceLocation::getFromRawEncoding(RefQualifierLoc);
}
- /// Retrieve the location of the 'const' qualifier, if any.
+ /// Retrieve the location of the 'const' qualifier.
SourceLocation getConstQualifierLoc() const {
- return SourceLocation::getFromRawEncoding(ConstQualifierLoc);
+ assert(MethodQualifiers);
+ return MethodQualifiers->getConstSpecLoc();
}
- /// Retrieve the location of the 'volatile' qualifier, if any.
+ /// Retrieve the location of the 'volatile' qualifier.
SourceLocation getVolatileQualifierLoc() const {
- return SourceLocation::getFromRawEncoding(VolatileQualifierLoc);
+ assert(MethodQualifiers);
+ return MethodQualifiers->getVolatileSpecLoc();
}
- /// Retrieve the location of the 'restrict' qualifier, if any.
+ /// Retrieve the location of the 'restrict' qualifier.
SourceLocation getRestrictQualifierLoc() const {
- return SourceLocation::getFromRawEncoding(RestrictQualifierLoc);
+ assert(MethodQualifiers);
+ return MethodQualifiers->getRestrictSpecLoc();
}
/// Retrieve the location of the 'mutable' qualifier, if any.
@@ -1434,6 +1448,12 @@ struct DeclaratorChunk {
/// qualifier.
bool hasMutableQualifier() const { return getMutableLoc().isValid(); }
+ /// Determine whether this method has qualifiers.
+ bool hasMethodTypeQualifiers() const {
+ return MethodQualifiers && (MethodQualifiers->getTypeQualifiers() ||
+ MethodQualifiers->getAttributes().size());
+ }
+
/// Get the type of exception specification this function has.
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
@@ -1574,12 +1594,8 @@ struct DeclaratorChunk {
ParamInfo *Params, unsigned NumParams,
SourceLocation EllipsisLoc,
SourceLocation RParenLoc,
- unsigned TypeQuals,
bool RefQualifierIsLvalueRef,
SourceLocation RefQualifierLoc,
- SourceLocation ConstQualifierLoc,
- SourceLocation VolatileQualifierLoc,
- SourceLocation RestrictQualifierLoc,
SourceLocation MutableLoc,
ExceptionSpecificationType ESpecType,
SourceRange ESpecRange,
@@ -1593,7 +1609,8 @@ struct DeclaratorChunk {
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
TypeResult TrailingReturnType =
- TypeResult());
+ TypeResult(),
+ DeclSpec *MethodQualifiers = nullptr);
/// Return a DeclaratorChunk for a block.
static DeclaratorChunk getBlockPointer(unsigned TypeQuals,
@@ -1870,8 +1887,8 @@ public:
/// Get the source range that spans this declarator.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
void SetSourceRange(SourceRange R) { Range = R; }
/// SetRangeBegin - Set the start of the source range to Loc, unless it's
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 8582e971d0b6..3a2d6275650d 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -671,10 +671,11 @@ public:
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit,
Expr *Init) {
if (!Init) return CreateDefault(Loc);
- if (!DirectInit) return CreateCopy(Loc, Init->getLocStart());
+ if (!DirectInit)
+ return CreateCopy(Loc, Init->getBeginLoc());
if (isa<InitListExpr>(Init))
- return CreateDirectList(Loc, Init->getLocStart(), Init->getLocEnd());
- return CreateDirect(Loc, Init->getLocStart(), Init->getLocEnd());
+ return CreateDirectList(Loc, Init->getBeginLoc(), Init->getEndLoc());
+ return CreateDirect(Loc, Init->getBeginLoc(), Init->getEndLoc());
}
/// Determine the initialization kind.
@@ -892,11 +893,8 @@ public:
/// Initialize an OpenCL sampler from an integer.
SK_OCLSamplerInit,
- /// Initialize queue_t from 0.
- SK_OCLZeroQueue,
-
- /// Passing zero to a function where OpenCL event_t is expected.
- SK_OCLZeroEvent
+ /// Initialize an opaque OpenCL type (event_t, queue_t, etc.) with zero
+ SK_OCLZeroOpaqueType
};
/// A single step in the initialization sequence.
@@ -1333,12 +1331,13 @@ public:
/// constant.
void AddOCLSamplerInitStep(QualType T);
- /// Add a step to initialize an OpenCL event_t from a NULL
- /// constant.
- void AddOCLZeroEventStep(QualType T);
+ /// Add a step to initialzie an OpenCL opaque type (event_t, queue_t, etc.)
+ /// from a zero constant.
+ void AddOCLZeroOpaqueTypeStep(QualType T);
- /// Add a step to initialize an OpenCL queue_t from 0.
- void AddOCLZeroQueueStep(QualType T);
+ /// Add a step to initialize by zero types defined in the
+ /// cl_intel_device_side_avc_motion_estimation OpenCL extension
+ void AddOCLIntelSubgroupAVCZeroInitStep(QualType T);
/// Add steps to unwrap a initializer list for a reference around a
/// single element and rewrap it at the end.
diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index e28b847f4ae5..4f7da851e232 100644
--- a/include/clang/Sema/Lookup.h
+++ b/include/clang/Sema/Lookup.h
@@ -540,7 +540,7 @@ public:
}
/// Clears out any current state.
- void clear() {
+ LLVM_ATTRIBUTE_REINITIALIZES void clear() {
ResultKind = NotFound;
Decls.clear();
if (Paths) deletePaths(Paths);
@@ -709,7 +709,9 @@ private:
// Results.
LookupResultKind ResultKind = NotFound;
- AmbiguityKind Ambiguity; // ill-defined unless ambiguous
+ // ill-defined unless ambiguous. Still need to be initialized it will be
+ // copied/moved.
+ AmbiguityKind Ambiguity = {};
UnresolvedSet<8> Decls;
CXXBasePaths *Paths = nullptr;
CXXRecordDecl *NamingClass = nullptr;
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 6ded010ee8ed..96fd5892daae 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -755,12 +755,12 @@ class Sema;
ConversionFixItGenerator Fix;
/// Viable - True to indicate that this overload candidate is viable.
- bool Viable;
+ bool Viable : 1;
/// IsSurrogate - True to indicate that this candidate is a
/// surrogate for a conversion to a function pointer or reference
/// (C++ [over.call.object]).
- bool IsSurrogate;
+ bool IsSurrogate : 1;
/// IgnoreObjectArgument - True to indicate that the first
/// argument's conversion, which for this function represents the
@@ -769,7 +769,10 @@ class Sema;
/// implicit object argument is just a placeholder) or a
/// non-static member function when the call doesn't have an
/// object argument.
- bool IgnoreObjectArgument;
+ bool IgnoreObjectArgument : 1;
+
+ /// True if the candidate was found using ADL.
+ CallExpr::ADLCallKind IsADLCandidate : 1;
/// FailureKind - The reason why this candidate is not viable.
/// Actually an OverloadFailureKind.
@@ -823,6 +826,10 @@ class Sema;
return Function->getNumParams();
return ExplicitCallArguments;
}
+
+ private:
+ friend class OverloadCandidateSet;
+ OverloadCandidate() : IsADLCandidate(CallExpr::NotADL) {}
};
/// OverloadCandidateSet - A set of overload candidates, used in C++
diff --git a/include/clang/Sema/ParsedAttr.h b/include/clang/Sema/ParsedAttr.h
index cfb91af78370..11202cb137b5 100644
--- a/include/clang/Sema/ParsedAttr.h
+++ b/include/clang/Sema/ParsedAttr.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
#include "clang/Basic/AttrSubjectMatchRules.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Ownership.h"
@@ -54,8 +55,7 @@ struct AvailabilityChange {
bool isValid() const { return !Version.empty(); }
};
-namespace {
-
+namespace detail {
enum AvailabilitySlot {
IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots
};
@@ -77,6 +77,18 @@ struct AvailabilityData {
}
};
+struct TypeTagForDatatypeData {
+ ParsedType MatchingCType;
+ unsigned LayoutCompatible : 1;
+ unsigned MustBeNull : 1;
+};
+struct PropertyData {
+ IdentifierInfo *GetterId, *SetterId;
+
+ PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
+ : GetterId(getterId), SetterId(setterId) {}
+};
+
} // namespace
/// Wraps an identifier and optional source location for the identifier.
@@ -102,7 +114,27 @@ using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
///
-class ParsedAttr { // TODO: This should really be called ParsedAttribute
+class ParsedAttr final
+ : private llvm::TrailingObjects<
+ ParsedAttr, ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
+ friend TrailingObjects;
+
+ size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; }
+ size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const {
+ return IsAvailability;
+ }
+ size_t
+ numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const {
+ return IsTypeTagForDatatype;
+ }
+ size_t numTrailingObjects(OverloadToken<ParsedType>) const {
+ return HasParsedType;
+ }
+ size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const {
+ return IsProperty;
+ }
+
public:
/// The style used to specify an attribute.
enum Syntax {
@@ -182,34 +214,18 @@ private:
const Expr *MessageExpr;
- /// Arguments, if any, are stored immediately following the object.
- ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
+ ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); }
ArgsUnion const *getArgsBuffer() const {
- return reinterpret_cast<ArgsUnion const *>(this + 1);
+ return getTrailingObjects<ArgsUnion>();
}
- /// Availability information is stored immediately following the arguments,
- /// if any, at the end of the object.
- AvailabilityData *getAvailabilityData() {
- return reinterpret_cast<AvailabilityData*>(getArgsBuffer() + NumArgs);
+ detail::AvailabilityData *getAvailabilityData() {
+ return getTrailingObjects<detail::AvailabilityData>();
}
- const AvailabilityData *getAvailabilityData() const {
- return reinterpret_cast<const AvailabilityData*>(getArgsBuffer() + NumArgs);
+ const detail::AvailabilityData *getAvailabilityData() const {
+ return getTrailingObjects<detail::AvailabilityData>();
}
-public:
- struct TypeTagForDatatypeData {
- ParsedType *MatchingCType;
- unsigned LayoutCompatible : 1;
- unsigned MustBeNull : 1;
- };
- struct PropertyData {
- IdentifierInfo *GetterId, *SetterId;
-
- PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
- : GetterId(getterId), SetterId(setterId) {}
- };
-
private:
friend class AttributeFactory;
friend class AttributePool;
@@ -244,7 +260,7 @@ private:
MessageExpr(messageExpr) {
ArgsUnion PVal(Parm);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
- new (getAvailabilityData()) AvailabilityData(
+ new (getAvailabilityData()) detail::AvailabilityData(
introduced, deprecated, obsoleted, strict, replacementExpr);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
@@ -278,7 +294,7 @@ private:
HasProcessingCache(false) {
ArgsUnion PVal(ArgKind);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
- TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
+ detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
new (&ExtraData.MatchingCType) ParsedType(matchingCType);
ExtraData.LayoutCompatible = layoutCompatible;
ExtraData.MustBeNull = mustBeNull;
@@ -308,46 +324,45 @@ private:
UsedAsTypeAttr(false), IsAvailability(false),
IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
HasProcessingCache(false) {
- new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
+ new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Type tag information is stored immediately following the arguments, if
/// any, at the end of the object. They are mutually exclusive with
/// availability slots.
- TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
- return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
+ detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
+ return *getTrailingObjects<detail::TypeTagForDatatypeData>();
}
- const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
- return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
- + NumArgs);
+ const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
+ return *getTrailingObjects<detail::TypeTagForDatatypeData>();
}
/// The type buffer immediately follows the object and are mutually exclusive
/// with arguments.
- ParsedType &getTypeBuffer() {
- return *reinterpret_cast<ParsedType *>(this + 1);
- }
+ ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); }
const ParsedType &getTypeBuffer() const {
- return *reinterpret_cast<const ParsedType *>(this + 1);
+ return *getTrailingObjects<ParsedType>();
}
/// The property data immediately follows the object is is mutually exclusive
/// with arguments.
- PropertyData &getPropertyDataBuffer() {
+ detail::PropertyData &getPropertyDataBuffer() {
assert(IsProperty);
- return *reinterpret_cast<PropertyData*>(this + 1);
+ return *getTrailingObjects<detail::PropertyData>();
}
- const PropertyData &getPropertyDataBuffer() const {
+ const detail::PropertyData &getPropertyDataBuffer() const {
assert(IsProperty);
- return *reinterpret_cast<const PropertyData*>(this + 1);
+ return *getTrailingObjects<detail::PropertyData>();
}
size_t allocated_size() const;
public:
ParsedAttr(const ParsedAttr &) = delete;
+ ParsedAttr(ParsedAttr &&) = delete;
ParsedAttr &operator=(const ParsedAttr &) = delete;
+ ParsedAttr &operator=(ParsedAttr &&) = delete;
~ParsedAttr() = delete;
void operator delete(void *) = delete;
@@ -368,6 +383,11 @@ public:
IdentifierInfo *getScopeName() const { return ScopeName; }
SourceLocation getScopeLoc() const { return ScopeLoc; }
+ bool isGNUScope() const {
+ return ScopeName &&
+ (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
+ }
+
bool hasParsedType() const { return HasParsedType; }
/// Is this the Microsoft __declspec(property) attribute?
@@ -451,17 +471,17 @@ public:
const AvailabilityChange &getAvailabilityIntroduced() const {
assert(getKind() == AT_Availability && "Not an availability attribute");
- return getAvailabilityData()->Changes[IntroducedSlot];
+ return getAvailabilityData()->Changes[detail::IntroducedSlot];
}
const AvailabilityChange &getAvailabilityDeprecated() const {
assert(getKind() == AT_Availability && "Not an availability attribute");
- return getAvailabilityData()->Changes[DeprecatedSlot];
+ return getAvailabilityData()->Changes[detail::DeprecatedSlot];
}
const AvailabilityChange &getAvailabilityObsoleted() const {
assert(getKind() == AT_Availability && "Not an availability attribute");
- return getAvailabilityData()->Changes[ObsoletedSlot];
+ return getAvailabilityData()->Changes[detail::ObsoletedSlot];
}
SourceLocation getStrictLoc() const {
@@ -487,7 +507,7 @@ public:
const ParsedType &getMatchingCType() const {
assert(getKind() == AT_TypeTagForDatatype &&
"Not a type_tag_for_datatype attribute");
- return *getTypeTagForDatatypeDataSlot().MatchingCType;
+ return getTypeTagForDatatypeDataSlot().MatchingCType;
}
bool getLayoutCompatible() const {
@@ -507,9 +527,16 @@ public:
return getTypeBuffer();
}
- const PropertyData &getPropertyData() const {
- assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute");
- return getPropertyDataBuffer();
+ IdentifierInfo *getPropertyDataGetter() const {
+ assert(isDeclspecPropertyAttribute() &&
+ "Not a __delcspec(property) attribute");
+ return getPropertyDataBuffer().GetterId;
+ }
+
+ IdentifierInfo *getPropertyDataSetter() const {
+ assert(isDeclspecPropertyAttribute() &&
+ "Not a __delcspec(property) attribute");
+ return getPropertyDataBuffer().SetterId;
}
/// Get an index into the attribute spelling list
@@ -552,20 +579,18 @@ class AttributePool;
class AttributeFactory {
public:
enum {
- /// The required allocation size of an availability attribute,
- /// which we want to ensure is a multiple of sizeof(void*).
AvailabilityAllocSize =
- sizeof(ParsedAttr) +
- ((sizeof(AvailabilityData) + sizeof(void *) + sizeof(ArgsUnion) - 1) /
- sizeof(void *) * sizeof(void *)),
- TypeTagForDatatypeAllocSize = sizeof(ParsedAttr) +
- (sizeof(ParsedAttr::TypeTagForDatatypeData) +
- sizeof(void *) + sizeof(ArgsUnion) - 1) /
- sizeof(void *) * sizeof(void *),
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(1, 1, 0, 0, 0),
+ TypeTagForDatatypeAllocSize =
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(1, 0, 1, 0, 0),
PropertyAllocSize =
- sizeof(ParsedAttr) +
- (sizeof(ParsedAttr::PropertyData) + sizeof(void *) - 1) /
- sizeof(void *) * sizeof(void *)
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(0, 0, 0, 0, 1),
};
private:
@@ -656,7 +681,16 @@ public:
ArgsUnion *args, unsigned numArgs,
ParsedAttr::Syntax syntax,
SourceLocation ellipsisLoc = SourceLocation()) {
- void *memory = allocate(sizeof(ParsedAttr) + numArgs * sizeof(ArgsUnion));
+ size_t temp =
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(numArgs, 0, 0, 0, 0);
+ (void)temp;
+ void *memory = allocate(
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(numArgs, 0, 0, 0,
+ 0));
return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
args, numArgs, syntax, ellipsisLoc));
}
@@ -679,8 +713,10 @@ public:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierLoc *Param1, IdentifierLoc *Param2,
IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
- size_t size = sizeof(ParsedAttr) + 3 * sizeof(ArgsUnion);
- void *memory = allocate(size);
+ void *memory = allocate(
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(3, 0, 0, 0, 0));
return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
Param1, Param2, Param3, syntax));
}
@@ -702,7 +738,10 @@ public:
IdentifierInfo *scopeName,
SourceLocation scopeLoc, ParsedType typeArg,
ParsedAttr::Syntax syntaxUsed) {
- void *memory = allocate(sizeof(ParsedAttr) + sizeof(void *));
+ void *memory = allocate(
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(0, 0, 0, 1, 0));
return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
typeArg, syntaxUsed));
}
@@ -728,10 +767,6 @@ public:
ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; }
const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; }
- void addAtStart(ParsedAttr *newAttr) {
- assert(newAttr);
- AttrList.insert(AttrList.begin(), newAttr);
- }
void addAtEnd(ParsedAttr *newAttr) {
assert(newAttr);
AttrList.push_back(newAttr);
@@ -785,6 +820,23 @@ public:
iterator end() { return iterator(AttrList.end()); }
const_iterator end() const { return const_iterator(AttrList.end()); }
+ ParsedAttr &front() {
+ assert(!empty());
+ return *AttrList.front();
+ }
+ const ParsedAttr &front() const {
+ assert(!empty());
+ return *AttrList.front();
+ }
+ ParsedAttr &back() {
+ assert(!empty());
+ return *AttrList.back();
+ }
+ const ParsedAttr &back() const {
+ assert(!empty());
+ return *AttrList.back();
+ }
+
bool hasAttribute(ParsedAttr::Kind K) const {
return llvm::any_of(
AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; });
@@ -826,7 +878,7 @@ public:
SourceLocation ellipsisLoc = SourceLocation()) {
ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
args, numArgs, syntax, ellipsisLoc);
- addAtStart(attr);
+ addAtEnd(attr);
return attr;
}
@@ -842,7 +894,7 @@ public:
ParsedAttr *attr = pool.create(
attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr);
- addAtStart(attr);
+ addAtEnd(attr);
return attr;
}
@@ -853,7 +905,7 @@ public:
IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
Param1, Param2, Param3, syntax);
- addAtStart(attr);
+ addAtEnd(attr);
return attr;
}
@@ -867,7 +919,7 @@ public:
ParsedAttr *attr = pool.createTypeTagForDatatype(
attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType,
layoutCompatible, mustBeNull, syntax);
- addAtStart(attr);
+ addAtEnd(attr);
return attr;
}
@@ -878,7 +930,7 @@ public:
ParsedAttr::Syntax syntaxUsed) {
ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName,
scopeLoc, typeArg, syntaxUsed);
- addAtStart(attr);
+ addAtEnd(attr);
return attr;
}
@@ -891,7 +943,7 @@ public:
ParsedAttr *attr =
pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
getterId, setterId, syntaxUsed);
- addAtStart(attr);
+ addAtEnd(attr);
return attr;
}
@@ -926,6 +978,34 @@ enum AttributeDeclKind {
ExpectedFunctionWithProtoType,
};
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const ParsedAttr &At) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const ParsedAttr &At) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return PD;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const ParsedAttr *At) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const ParsedAttr *At) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return PD;
+}
+
} // namespace clang
#endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index 11fa0362124b..9d9ab0514fb5 100644
--- a/include/clang/Sema/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_SEMA_SCOPE_H
#define LLVM_CLANG_SEMA_SCOPE_H
+#include "clang/AST/Decl.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 5925fd6ccead..e09a68aba707 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -31,6 +31,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -202,6 +203,12 @@ public:
/// function.
SmallVector<CompoundScopeInfo, 4> CompoundScopes;
+ /// The set of blocks that are introduced in this function.
+ llvm::SmallPtrSet<const BlockDecl *, 1> Blocks;
+
+ /// The set of __block variables that are introduced in this function.
+ llvm::TinyPtrVector<VarDecl *> ByrefBlockVars;
+
/// A list of PartialDiagnostics created but delayed within the
/// current function scope. These diagnostics are vetted for reachability
/// prior to being emitted.
@@ -426,6 +433,16 @@ public:
(HasBranchProtectedScope && HasBranchIntoScope));
}
+ // Add a block introduced in this function.
+ void addBlock(const BlockDecl *BD) {
+ Blocks.insert(BD);
+ }
+
+ // Add a __block variable introduced in this function.
+ void addByrefBlockVar(VarDecl *VD) {
+ ByrefBlockVars.push_back(VD);
+ }
+
bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); }
void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) {
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index b1077c620f8a..e5b7465820a9 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -153,6 +153,7 @@ namespace clang {
class ObjCPropertyDecl;
class ObjCProtocolDecl;
class OMPThreadPrivateDecl;
+ class OMPRequiresDecl;
class OMPDeclareReductionDecl;
class OMPDeclareSimdDecl;
class OMPClause;
@@ -306,6 +307,10 @@ class Sema {
}
bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
+ void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
+ QualType ResultTy,
+ ArrayRef<QualType> Args);
+
public:
typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
typedef OpaquePtr<TemplateName> TemplateTy;
@@ -490,15 +495,24 @@ public:
/// VisContext - Manages the stack for \#pragma GCC visibility.
void *VisContext; // Really a "PragmaVisStack*"
- /// This represents the stack of attributes that were pushed by
- /// \#pragma clang attribute.
+ /// This an attribute introduced by \#pragma clang attribute.
struct PragmaAttributeEntry {
SourceLocation Loc;
ParsedAttr *Attribute;
SmallVector<attr::SubjectMatchRule, 4> MatchRules;
bool IsUsed;
};
- SmallVector<PragmaAttributeEntry, 2> PragmaAttributeStack;
+
+ /// A push'd group of PragmaAttributeEntries.
+ struct PragmaAttributeGroup {
+ /// The location of the push attribute.
+ SourceLocation Loc;
+ /// The namespace of this push group.
+ const IdentifierInfo *Namespace;
+ SmallVector<PragmaAttributeEntry, 2> Entries;
+ };
+
+ SmallVector<PragmaAttributeGroup, 2> PragmaAttributeStack;
/// The declaration that is currently receiving an attribute from the
/// #pragma attribute stack.
@@ -608,7 +622,15 @@ public:
/// that had their exception spec checks delayed, plus the overridden
/// function.
SmallVector<std::pair<const CXXMethodDecl*, const CXXMethodDecl*>, 2>
- DelayedExceptionSpecChecks;
+ DelayedOverridingExceptionSpecChecks;
+
+ /// All the function redeclarations seen during a class definition that had
+ /// their exception spec checks delayed, plus the prior declaration they
+ /// should be checked against. Except during error recovery, the new decl
+ /// should always be a friend declaration, as that's the only valid way to
+ /// redeclare a special member before its class is complete.
+ SmallVector<std::pair<FunctionDecl*, FunctionDecl*>, 2>
+ DelayedEquivalentExceptionSpecChecks;
/// All the members seen during a class definition which were both
/// explicitly defaulted and had explicitly-specified exception
@@ -983,6 +1005,8 @@ public:
/// expressions for which we have deferred checking the destructor.
SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
+ llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
+
/// \brief Describes whether we are in an expression constext which we have
/// to handle differently.
enum ExpressionKind {
@@ -1016,6 +1040,9 @@ public:
/// A stack of expression evaluation contexts.
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+ /// Emit a warning for all pending noderef expressions that we recorded.
+ void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
+
/// Compute the mangling number context for a lambda expression or
/// block literal.
///
@@ -1342,6 +1369,7 @@ public:
void PopCompoundScope();
sema::CompoundScopeInfo &getCurCompoundScope() const;
+ bool isCurCompoundStmtAStmtExpr() const;
bool hasAnyUnrecoverableErrorsInThisFunction() const;
@@ -1435,8 +1463,6 @@ public:
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
- TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
- TypeSourceInfo *ReturnTypeInfo);
/// Package the given type and TSI into a ParsedType.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
@@ -1530,6 +1556,17 @@ public:
};
private:
+ /// Methods for marking which expressions involve dereferencing a pointer
+ /// marked with the 'noderef' attribute. Expressions are checked bottom up as
+ /// they are parsed, meaning that a noderef pointer may not be accessed. For
+ /// example, in `&*p` where `p` is a noderef pointer, we will first parse the
+ /// `*p`, but need to check that `address of` is called on it. This requires
+ /// keeping a container of all pending expressions and checking if the address
+ /// of them are eventually taken.
+ void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E);
+ void CheckAddressOfNoDeref(const Expr *E);
+ void CheckMemberAccessOfNoDeref(const MemberExpr *E);
+
bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser *Diagnoser);
@@ -1556,7 +1593,7 @@ public:
/// visible at the specified location.
void makeMergedDefinitionVisible(NamedDecl *ND);
- bool isModuleVisible(const Module *M) { return VisibleModules.isVisible(M); }
+ bool isModuleVisible(const Module *M, bool ModulePrivate = false);
/// Determine whether a declaration is visible to name lookup.
bool isVisible(const NamedDecl *D) {
@@ -1613,6 +1650,8 @@ public:
SourceLocation Loc, const NamedDecl *D,
ArrayRef<const NamedDecl *> Equiv);
+ bool isUsualDeallocationFunction(const CXXMethodDecl *FD);
+
bool isCompleteType(SourceLocation Loc, QualType T) {
return !RequireCompleteTypeImpl(Loc, T, nullptr);
}
@@ -1925,7 +1964,7 @@ public:
bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
void CheckVariableDeclarationType(VarDecl *NewVD);
bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
- Expr *Init);
+ Expr *&Init);
void CheckCompleteVariableDeclaration(VarDecl *VD);
void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD);
void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
@@ -1950,6 +1989,8 @@ public:
FunctionDecl *NewFD, LookupResult &Previous,
bool IsMemberSpecialization);
bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl);
+ bool canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD,
+ QualType NewT, QualType OldT);
void CheckMain(FunctionDecl *FD, const DeclSpec &D);
void CheckMSVCRTEntryPoint(FunctionDecl *FD);
Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition);
@@ -1983,6 +2024,7 @@ public:
SourceLocation AttrEnd);
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
+ void CheckStaticLocalForDllExport(VarDecl *VD);
void FinalizeDeclaration(Decl *D);
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
ArrayRef<Decl *> Group);
@@ -2456,11 +2498,11 @@ public:
unsigned AttrSpellingListIndex);
OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex);
- InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, SourceRange Range,
- IdentifierInfo *Ident,
- unsigned AttrSpellingListIndex);
- CommonAttr *mergeCommonAttr(Decl *D, SourceRange Range, IdentifierInfo *Ident,
- unsigned AttrSpellingListIndex);
+ InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
+ InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D,
+ const InternalLinkageAttr &AL);
+ CommonAttr *mergeCommonAttr(Decl *D, const ParsedAttr &AL);
+ CommonAttr *mergeCommonAttr(Decl *D, const CommonAttr &AL);
void mergeDeclAttributes(NamedDecl *New, Decl *Old,
AvailabilityMergeKind AMK = AMK_Redeclaration);
@@ -2714,13 +2756,15 @@ public:
typedef llvm::SmallSetVector<DeclContext *, 16> AssociatedNamespaceSet;
typedef llvm::SmallSetVector<CXXRecordDecl *, 16> AssociatedClassSet;
- void AddOverloadCandidate(FunctionDecl *Function,
- DeclAccessPair FoundDecl,
+ using ADLCallKind = CallExpr::ADLCallKind;
+
+ void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false,
bool AllowExplicit = false,
+ ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
ConversionSequenceList EarlyConversions = None);
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
ArrayRef<Expr *> Args,
@@ -2754,13 +2798,12 @@ public:
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false);
- void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
- DeclAccessPair FoundDecl,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions = false,
- bool PartialOverloading = false);
+ void AddTemplateOverloadCandidate(
+ FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+ bool PartialOverloading = false,
+ ADLCallKind IsADLCandidate = ADLCallKind::NotADL);
bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
ArrayRef<QualType> ParamTypes,
ArrayRef<Expr *> Args,
@@ -2826,11 +2869,7 @@ public:
/// Find the failed Boolean condition within a given Boolean
/// constant expression, and describe it with a string.
- ///
- /// \param AllowTopLevelCond Whether to allow the result to be the
- /// complete top-level condition.
- std::pair<Expr *, std::string>
- findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond);
+ std::pair<Expr *, std::string> findFailedBooleanCondition(Expr *Cond);
/// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
/// non-ArgDependent DiagnoseIfAttrs.
@@ -3378,30 +3417,6 @@ public:
/// Valid types should not have multiple attributes with different CCs.
const AttributedType *getCallingConvAttributedType(QualType T) const;
- /// Check whether a nullability type specifier can be added to the given
- /// type.
- ///
- /// \param type The type to which the nullability specifier will be
- /// added. On success, this type will be updated appropriately.
- ///
- /// \param nullability The nullability specifier to add.
- ///
- /// \param nullabilityLoc The location of the nullability specifier.
- ///
- /// \param isContextSensitive Whether this nullability specifier was
- /// written as a context-sensitive keyword (in an Objective-C
- /// method) or an Objective-C property attribute, rather than as an
- /// underscored type specifier.
- ///
- /// \param allowArrayTypes Whether to accept nullability specifiers on an
- /// array type (e.g., because it will decay to a pointer).
- ///
- /// \returns true if nullability cannot be applied, false otherwise.
- bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability,
- SourceLocation nullabilityLoc,
- bool isContextSensitive,
- bool allowArrayTypes);
-
/// Stmt attributes - this routine is the top level dispatcher.
StmtResult ProcessStmtAttributes(Stmt *Stmt,
const ParsedAttributesView &Attrs,
@@ -3675,16 +3690,17 @@ public:
return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
}
FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
- return FullExprArg(ActOnFinishFullExpr(Arg, CC).get());
+ return FullExprArg(
+ ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get());
}
FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) {
ExprResult FE =
- ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
- /*DiscardedValue*/ true);
+ ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
+ /*DiscardedValue*/ true);
return FullExprArg(FE.get());
}
- StmtResult ActOnExprStmt(ExprResult Arg);
+ StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
StmtResult ActOnExprStmtError();
StmtResult ActOnNullStmt(SourceLocation SemiLoc,
@@ -3790,12 +3806,14 @@ public:
StmtResult ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
SourceLocation CoawaitLoc,
+ Stmt *InitStmt,
Stmt *LoopVar,
SourceLocation ColonLoc, Expr *Collection,
SourceLocation RParenLoc,
BuildForRangeKind Kind);
StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc,
SourceLocation CoawaitLoc,
+ Stmt *InitStmt,
SourceLocation ColonLoc,
Stmt *RangeDecl, Stmt *Begin, Stmt *End,
Expr *Cond, Expr *Inc,
@@ -3983,7 +4001,8 @@ public:
void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
- bool AvoidPartialAvailabilityChecks = false);
+ bool AvoidPartialAvailabilityChecks = false,
+ ObjCInterfaceDecl *ClassReceiver = nullptr);
bool makeUnavailableInSystemHeader(SourceLocation loc,
UnavailableAttr::ImplicitReason reason);
@@ -3998,7 +4017,8 @@ public:
bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass = nullptr,
bool ObjCPropertyAccess = false,
- bool AvoidPartialAvailabilityChecks = false);
+ bool AvoidPartialAvailabilityChecks = false,
+ ObjCInterfaceDecl *ClassReciever = nullptr);
void NoteDeletedFunction(FunctionDecl *FD);
void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD);
std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
@@ -4223,7 +4243,7 @@ public:
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
ExprResult BuildPredefinedExpr(SourceLocation Loc,
- PredefinedExpr::IdentType IT);
+ PredefinedExpr::IdentKind IK);
ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
@@ -4376,12 +4396,11 @@ public:
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig = nullptr,
bool IsExecConfig = false);
- ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
- SourceLocation LParenLoc,
- ArrayRef<Expr *> Arg,
- SourceLocation RParenLoc,
- Expr *Config = nullptr,
- bool IsExecConfig = false);
+ ExprResult
+ BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
+ ArrayRef<Expr *> Arg, SourceLocation RParenLoc,
+ Expr *Config = nullptr, bool IsExecConfig = false,
+ ADLCallKind UsesADL = ADLCallKind::NotADL);
ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
MultiExprArg ExecConfig,
@@ -4582,6 +4601,11 @@ private:
// of a ComparisonCategoryType enumerator.
llvm::SmallBitVector FullyCheckedComparisonCategories;
+ ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+ CXXScopeSpec &SS,
+ ParsedType TemplateTypeTy,
+ IdentifierInfo *MemberOrBase);
+
public:
/// Lookup the specified comparison category types in the standard
/// library, an check the VarDecls possibly returned by the operator<=>
@@ -4799,7 +4823,7 @@ public:
ImplicitExceptionSpecification
ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD);
- /// Determine what sort of exception specification a defautled
+ /// Determine what sort of exception specification a defaulted
/// copy assignment operator of a class will have, and whether the
/// parameter will be const.
ImplicitExceptionSpecification
@@ -4898,8 +4922,7 @@ public:
///
/// C++11 says that user-defined destructors with no exception spec get one
/// that looks as if the destructor was implicitly declared.
- void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
- CXXDestructorDecl *Destructor);
+ void AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor);
/// Define the specified inheriting constructor.
void DefineInheritingConstructor(SourceLocation UseLoc,
@@ -5100,7 +5123,7 @@ public:
/// using the given declaration (which is either a class template or a
/// class) along with the given qualifiers.
/// along with the qualifiers placed on '*this'.
- CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals,
+ CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals,
bool Enabled = true);
~CXXThisScopeRAII();
@@ -5185,6 +5208,15 @@ public:
SourceRange DirectInitRange,
Expr *Initializer);
+ /// Determine whether \p FD is an aligned allocation or deallocation
+ /// function that is unavailable.
+ bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
+
+ /// Produce diagnostics if \p FD is an aligned allocation or deallocation
+ /// function that is unavailable.
+ void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
+ SourceLocation Loc);
+
bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
SourceRange R);
@@ -5314,14 +5346,12 @@ public:
CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
bool BoundToLvalueReference);
- ExprResult ActOnFinishFullExpr(Expr *Expr) {
- return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc()
- : SourceLocation());
+ ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) {
+ return ActOnFinishFullExpr(
+ Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue);
}
ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
- bool DiscardedValue = false,
- bool IsConstexpr = false,
- bool IsLambdaInitCaptureInitializer = false);
+ bool DiscardedValue, bool IsConstexpr = false);
StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type.
@@ -5586,7 +5616,9 @@ public:
void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
/// Introduce the lambda parameters into scope.
- void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
+ void addLambdaParameters(
+ ArrayRef<LambdaIntroducer::LambdaCapture> Captures,
+ CXXMethodDecl *CallOperator, Scope *CurScope);
/// Deduce a block or lambda's return type based on the return
/// statements present in the body.
@@ -6044,6 +6076,10 @@ public:
AccessResult CheckMemberAccess(SourceLocation UseLoc,
CXXRecordDecl *NamingClass,
DeclAccessPair Found);
+ AccessResult
+ CheckStructuredBindingMemberAccess(SourceLocation UseLoc,
+ CXXRecordDecl *DecomposedClass,
+ DeclAccessPair Field);
AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
Expr *ObjectExpr,
Expr *ArgExpr,
@@ -6057,7 +6093,8 @@ public:
bool ForceCheck = false,
bool ForceUnprivileged = false);
void CheckLookupAccess(const LookupResult &R);
- bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
+ bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass,
+ QualType BaseType);
bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
AccessSpecifier access,
QualType objectType);
@@ -6202,7 +6239,8 @@ public:
bool CheckTemplateParameterList(TemplateParameterList *NewParams,
TemplateParameterList *OldParams,
- TemplateParamListContext TPC);
+ TemplateParamListContext TPC,
+ SkipBodyInfo *SkipBody = nullptr);
TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
SourceLocation DeclStartLoc, SourceLocation DeclLoc,
const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
@@ -6322,9 +6360,9 @@ public:
const TemplateArgumentListInfo &ExplicitTemplateArgs,
LookupResult &Previous);
- bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- LookupResult &Previous);
+ bool CheckFunctionTemplateSpecialization(
+ FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous, bool QualifiedFriend = false);
bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
@@ -7061,7 +7099,7 @@ public:
QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
QualType Type, TypeSourceInfo *TSI,
SourceRange Range, bool DirectInit,
- Expr *Init);
+ Expr *&Init);
TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
@@ -7168,6 +7206,10 @@ public:
/// has been used when naming a template-id.
DefaultTemplateArgumentChecking,
+ /// We are computing the exception specification for a defaulted special
+ /// member function.
+ ExceptionSpecEvaluation,
+
/// We are instantiating the exception specification for a function
/// template which was deferred until it was needed.
ExceptionSpecInstantiation,
@@ -7726,7 +7768,7 @@ public:
SourceLocation Loc,
DeclarationName Entity,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals);
+ Qualifiers ThisTypeQuals);
void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
const MultiLevelTemplateArgumentList &Args);
bool SubstExceptionSpec(SourceLocation Loc,
@@ -8071,10 +8113,6 @@ public:
SourceLocation ProtocolRAngleLoc,
bool FailOnError = false);
- /// Check the application of the Objective-C '__kindof' qualifier to
- /// the given type.
- bool checkObjCKindOfType(QualType &type, SourceLocation loc);
-
/// Ensure attributes are consistent with type.
/// \param [in, out] Attributes The attributes to check; they will
/// be modified to be consistent with \p PropertyTy.
@@ -8434,6 +8472,10 @@ public:
/// \#pragma clang fp contract
void ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC);
+ /// ActOnPragmaFenvAccess - Called on well formed
+ /// \#pragma STDC FENV_ACCESS
+ void ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC);
+
/// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
/// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
void AddAlignmentAttributesForRecord(RecordDecl *RD);
@@ -8465,12 +8507,15 @@ public:
/// the appropriate attribute.
void AddCFAuditedAttribute(Decl *D);
- /// Called on well-formed '\#pragma clang attribute push'.
- void ActOnPragmaAttributePush(ParsedAttr &Attribute, SourceLocation PragmaLoc,
- attr::ParsedSubjectMatchRuleSet Rules);
+ void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
+ SourceLocation PragmaLoc,
+ attr::ParsedSubjectMatchRuleSet Rules);
+ void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace);
/// Called on well-formed '\#pragma clang attribute pop'.
- void ActOnPragmaAttributePop(SourceLocation PragmaLoc);
+ void ActOnPragmaAttributePop(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace);
/// Adds the attributes that have been specified using the
/// '\#pragma clang attribute push' directives to the given declaration.
@@ -8530,9 +8575,9 @@ public:
void AddParameterABIAttr(SourceRange AttrRange, Decl *D,
ParameterABI ABI, unsigned SpellingListIndex);
- void AddNSConsumedAttr(SourceRange AttrRange, Decl *D,
- unsigned SpellingListIndex, bool isNSConsumed,
- bool isTemplateInstantiation);
+ enum class RetainOwnershipKind {NS, CF, OS};
+ void AddXConsumedAttr(Decl *D, SourceRange SR, unsigned SpellingIndex,
+ RetainOwnershipKind K, bool IsTemplateInstantiation);
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
@@ -8572,6 +8617,21 @@ public:
llvm::StringRef getCurrentOpenCLExtension() const {
return CurrOpenCLExtension;
}
+
+ /// Check if a function declaration \p FD associates with any
+ /// extensions present in OpenCLDeclExtMap and if so return the
+ /// extension(s) name(s).
+ std::string getOpenCLExtensionsFromDeclExtMap(FunctionDecl *FD);
+
+ /// Check if a function type \p FT associates with any
+ /// extensions present in OpenCLTypeExtMap and if so return the
+ /// extension(s) name(s).
+ std::string getOpenCLExtensionsFromTypeExtMap(FunctionType *FT);
+
+ /// Find an extension in an appropriate extension map and return its name
+ template<typename T, typename MapT>
+ std::string getOpenCLExtensionsFromExtMap(T* FT, MapT &Map);
+
void setCurrentOpenCLExtension(llvm::StringRef Ext) {
CurrOpenCLExtension = Ext;
}
@@ -8616,8 +8676,8 @@ public:
//
private:
void *VarDataSharingAttributesStack;
- /// Set to true inside '#pragma omp declare target' region.
- bool IsInOpenMPDeclareTargetContext = false;
+ /// Number of nested '#pragma omp declare target' directives.
+ unsigned DeclareTargetNestingLevel = 0;
/// Initialization of data-sharing attributes stack.
void InitDataSharingAttributesStack();
void DestroyDataSharingAttributesStack();
@@ -8662,10 +8722,14 @@ public:
/// Check if the specified variable is used in one of the private
/// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
/// constructs.
- VarDecl *isOpenMPCapturedDecl(ValueDecl *D) const;
+ VarDecl *isOpenMPCapturedDecl(ValueDecl *D);
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
ExprObjectKind OK, SourceLocation Loc);
+ /// If the current region is a loop-based region, mark the start of the loop
+ /// construct.
+ void startOpenMPLoop();
+
/// Check if the specified variable is used in 'private' clause.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
@@ -8713,6 +8777,12 @@ public:
/// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
ArrayRef<Expr *> VarList);
+ /// Called on well-formed '#pragma omp requires'.
+ DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc,
+ ArrayRef<OMPClause *> ClauseList);
+ /// Check restrictions on Requires directive
+ OMPRequiresDecl *CheckOMPRequiresDecl(SourceLocation Loc,
+ ArrayRef<OMPClause *> Clauses);
/// Check if the specified type is allowed to be used in 'omp declare
/// reduction' construct.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
@@ -8746,11 +8816,12 @@ public:
OMPDeclareTargetDeclAttr::MapTypeTy MT,
NamedDeclSetType &SameDirectiveDecls);
/// Check declaration inside target region.
- void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
- SourceLocation IdLoc = SourceLocation());
+ void
+ checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+ SourceLocation IdLoc = SourceLocation());
/// Return true inside OpenMP declare target region.
bool isInOpenMPDeclareTargetContext() const {
- return IsInOpenMPDeclareTargetContext;
+ return DeclareTargetNestingLevel > 0;
}
/// Return true inside OpenMP target region.
bool isInOpenMPTargetExecutionDirective() const;
@@ -9105,7 +9176,7 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
-
+
OMPClause *ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
SourceLocation StartLoc, SourceLocation LParenLoc,
@@ -9153,6 +9224,26 @@ public:
/// Called on well-formed 'nogroup' clause.
OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc,
SourceLocation EndLoc);
+ /// Called on well-formed 'unified_address' clause.
+ OMPClause *ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'unified_address' clause.
+ OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'reverse_offload' clause.
+ OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'dynamic_allocators' clause.
+ OMPClause *ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'atomic_default_mem_order' clause.
+ OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause(
+ OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
OMPClause *ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *TailExpr,
@@ -9160,7 +9251,9 @@ public:
SourceLocation ColonLoc, SourceLocation EndLoc,
CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
- OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPLinearClauseKind LinKind,
+ ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
SourceLocation DepLinMapLoc);
/// Called on well-formed 'private' clause.
@@ -9244,7 +9337,8 @@ public:
SourceLocation EndLoc);
/// Called on well-formed 'map' clause.
OMPClause *
- ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+ ActOnOpenMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
SourceLocation MapLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
@@ -9571,6 +9665,10 @@ public:
AssignmentAction Action,
CheckedConversionKind CCK);
+ ExprResult PerformQualificationConversion(
+ Expr *E, QualType Ty, ExprValueKind VK = VK_RValue,
+ CheckedConversionKind CCK = CCK_ImplicitConversion);
+
/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).
@@ -9762,21 +9860,20 @@ public:
/// \param Method - May be null.
/// \param [out] ReturnType - The return type of the send.
/// \return true iff there were any incompatible types.
- bool CheckMessageArgumentTypes(QualType ReceiverType,
+ bool CheckMessageArgumentTypes(const Expr *Receiver, QualType ReceiverType,
MultiExprArg Args, Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
ObjCMethodDecl *Method, bool isClassMessage,
- bool isSuperMessage,
- SourceLocation lbrac, SourceLocation rbrac,
- SourceRange RecRange,
+ bool isSuperMessage, SourceLocation lbrac,
+ SourceLocation rbrac, SourceRange RecRange,
QualType &ReturnType, ExprValueKind &VK);
/// Determine the result of a message send expression based on
/// the type of the receiver, the method expected to receive the message,
/// and the form of the message send.
- QualType getMessageSendResultType(QualType ReceiverType,
- ObjCMethodDecl *Method,
- bool isClassMessage, bool isSuperMessage);
+ QualType getMessageSendResultType(const Expr *Receiver, QualType ReceiverType,
+ ObjCMethodDecl *Method, bool isClassMessage,
+ bool isSuperMessage);
/// If the given expression involves a message send to a method
/// with a related result type, emit a note describing what happened.
@@ -10245,6 +10342,7 @@ public:
struct CodeCompleteExpressionData;
void CodeCompleteExpression(Scope *S,
const CodeCompleteExpressionData &Data);
+ void CodeCompleteExpression(Scope *S, QualType PreferredType);
void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase,
SourceLocation OpLoc, bool IsArrow,
bool IsBaseExprStatement);
@@ -10255,16 +10353,27 @@ public:
const VirtSpecifiers *VS = nullptr);
void CodeCompleteBracketDeclarator(Scope *S);
void CodeCompleteCase(Scope *S);
- void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args);
- void CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
- ArrayRef<Expr *> Args);
+ /// Reports signatures for a call to CodeCompleteConsumer and returns the
+ /// preferred type for the current argument. Returned type can be null.
+ QualType ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc);
+ QualType ProduceConstructorSignatureHelp(Scope *S, QualType Type,
+ SourceLocation Loc,
+ ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc);
+ QualType ProduceCtorInitMemberSignatureHelp(Scope *S, Decl *ConstructorDecl,
+ CXXScopeSpec SS,
+ ParsedType TemplateTypeTy,
+ ArrayRef<Expr *> ArgExprs,
+ IdentifierInfo *II,
+ SourceLocation OpenParLoc);
void CodeCompleteInitializer(Scope *S, Decl *D);
void CodeCompleteReturn(Scope *S);
void CodeCompleteAfterIf(Scope *S);
- void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS);
+ void CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op);
void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
- bool EnteringContext);
+ bool EnteringContext, QualType BaseType);
void CodeCompleteUsing(Scope *S);
void CodeCompleteUsingDirective(Scope *S);
void CodeCompleteNamespaceDecl(Scope *S);
@@ -10337,6 +10446,7 @@ public:
IdentifierInfo *Macro,
MacroInfo *MacroInfo,
unsigned Argument);
+ void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled);
void CodeCompleteNaturalLanguage();
void CodeCompleteAvailabilityPlatformName();
void GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
@@ -10515,7 +10625,8 @@ private:
/// Check if there is a field shadowing.
void CheckShadowInheritedFields(const SourceLocation &Loc,
DeclarationName FieldName,
- const CXXRecordDecl *RD);
+ const CXXRecordDecl *RD,
+ bool DeclIsField = true);
/// Check if the given expression contains 'break' or 'continue'
/// statement that produces control flow different from GCC.
@@ -10658,7 +10769,9 @@ private:
SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); }
~SavePendingParsedClassStateRAII() {
- assert(S.DelayedExceptionSpecChecks.empty() &&
+ assert(S.DelayedOverridingExceptionSpecChecks.empty() &&
+ "there shouldn't be any pending delayed exception spec checks");
+ assert(S.DelayedEquivalentExceptionSpecChecks.empty() &&
"there shouldn't be any pending delayed exception spec checks");
assert(S.DelayedDefaultedMemberExceptionSpecs.empty() &&
"there shouldn't be any pending delayed defaulted member "
@@ -10670,13 +10783,19 @@ private:
private:
Sema &S;
- decltype(DelayedExceptionSpecChecks) SavedExceptionSpecChecks;
+ decltype(DelayedOverridingExceptionSpecChecks)
+ SavedOverridingExceptionSpecChecks;
+ decltype(DelayedEquivalentExceptionSpecChecks)
+ SavedEquivalentExceptionSpecChecks;
decltype(DelayedDefaultedMemberExceptionSpecs)
SavedDefaultedMemberExceptionSpecs;
decltype(DelayedDllExportClasses) SavedDllExportClasses;
void swapSavedState() {
- SavedExceptionSpecChecks.swap(S.DelayedExceptionSpecChecks);
+ SavedOverridingExceptionSpecChecks.swap(
+ S.DelayedOverridingExceptionSpecChecks);
+ SavedEquivalentExceptionSpecChecks.swap(
+ S.DelayedEquivalentExceptionSpecChecks);
SavedDefaultedMemberExceptionSpecs.swap(
S.DelayedDefaultedMemberExceptionSpecs);
SavedDllExportClasses.swap(S.DelayedDllExportClasses);
@@ -10790,7 +10909,6 @@ struct LateParsedTemplate {
/// The template function declaration to be late parsed.
Decl *D;
};
-
} // end namespace clang
namespace llvm {
diff --git a/include/clang/Sema/SemaDiagnostic.h b/include/clang/Sema/SemaDiagnostic.h
index 7740d5e29c00..30a2497a3e87 100644
--- a/include/clang/Sema/SemaDiagnostic.h
+++ b/include/clang/Sema/SemaDiagnostic.h
@@ -10,19 +10,6 @@
#ifndef LLVM_CLANG_SEMA_SEMADIAGNOSTIC_H
#define LLVM_CLANG_SEMA_SEMADIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define SEMASTART
-#include "clang/Basic/DiagnosticSemaKinds.inc"
-#undef DIAG
- NUM_BUILTIN_SEMA_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticSema.h"
#endif
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 430fc48379fe..ec752fb7c796 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1015,6 +1015,10 @@ namespace serialization {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
#include "clang/Basic/OpenCLImageTypes.def"
+ /// \brief OpenCL extension types with auto numeration
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ PREDEF_TYPE_##Id##_ID,
+#include "clang/Basic/OpenCLExtensionTypes.def"
};
/// The number of predefined type IDs that are reserved for
@@ -1516,6 +1520,9 @@ namespace serialization {
/// An OMPThreadPrivateDecl record.
DECL_OMP_THREADPRIVATE,
+ /// An OMPRequiresDecl record.
+ DECL_OMP_REQUIRES,
+
/// An EmptyDecl record.
DECL_EMPTY,
@@ -1533,6 +1540,8 @@ namespace serialization {
/// An OMPDeclareReductionDecl record.
DECL_OMP_DECLARE_REDUCTION,
+
+ DECL_LAST = DECL_OMP_DECLARE_REDUCTION
};
/// Record codes for each kind of statement or expression.
@@ -1545,7 +1554,7 @@ namespace serialization {
enum StmtCode {
/// A marker record that indicates that we are at the end
/// of an expression.
- STMT_STOP = 128,
+ STMT_STOP = DECL_LAST + 1,
/// A NULL expression.
STMT_NULL_PTR,
@@ -1613,6 +1622,9 @@ namespace serialization {
/// A MS-style AsmStmt record.
STMT_MSASM,
+ /// A constant expression context.
+ EXPR_CONSTANT,
+
/// A PredefinedExpr record.
EXPR_PREDEFINED,
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 0eecb6f5d65a..f97f545852f4 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -18,6 +18,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -232,7 +233,7 @@ public:
/// If needsImportVisitation returns \c true, this is called for each
/// AST file imported by this AST file.
- virtual void visitImport(StringRef Filename) {}
+ virtual void visitImport(StringRef ModuleName, StringRef Filename) {}
/// Indicates that a particular module file extension has been read.
virtual void readModuleFileExtension(
@@ -539,6 +540,11 @@ private:
/// declaration that has an exception specification.
llvm::SmallMapVector<Decl *, FunctionDecl *, 4> PendingExceptionSpecUpdates;
+ /// Deduced return type updates that have been loaded but not yet propagated
+ /// across the relevant redeclaration chain. The map key is the canonical
+ /// declaration and the value is the deduced return type.
+ llvm::SmallMapVector<FunctionDecl *, QualType, 4> PendingDeducedTypeUpdates;
+
/// Declarations that have been imported and have typedef names for
/// linkage purposes.
llvm::DenseMap<std::pair<DeclContext *, IdentifierInfo *>, NamedDecl *>
@@ -1056,6 +1062,12 @@ private:
/// Objective-C protocols.
std::deque<InterestingDecl> PotentiallyInterestingDecls;
+ /// The list of deduced function types that we have not yet read, because
+ /// they might contain a deduced return type that refers to a local type
+ /// declared within the function.
+ SmallVector<std::pair<FunctionDecl *, serialization::TypeID>, 16>
+ PendingFunctionTypes;
+
/// The list of redeclaration chains that still need to be
/// reconstructed, and the local offset to the corresponding list
/// of redeclarations.
@@ -2234,6 +2246,9 @@ public:
CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record,
unsigned &Idx);
+ /// Reads one attribute from the current stream position.
+ Attr *ReadAttr(ModuleFile &M, const RecordData &Record, unsigned &Idx);
+
/// Reads attributes from the current stream position.
void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs);
@@ -2619,6 +2634,11 @@ public:
return ASTReader::ReadVersionTuple(Record, Idx);
}
+ /// Reads one attribute from the current stream position, advancing Idx.
+ Attr *readAttr() {
+ return Reader->ReadAttr(*F, Record, Idx);
+ }
+
/// Reads attributes from the current stream position, advancing Idx.
void readAttributes(AttrVec &Attrs) {
return Reader->ReadAttributes(*this, Attrs);
@@ -2658,6 +2678,21 @@ inline void PCHValidator::Error(const char *Msg) {
Reader.Error(Msg);
}
+class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> {
+ ASTRecordReader &Record;
+ ASTContext &Context;
+
+public:
+ OMPClauseReader(ASTRecordReader &Record)
+ : Record(Record), Context(Record.getContext()) {}
+
+#define OPENMP_CLAUSE(Name, Class) void Visit##Class(Class *C);
+#include "clang/Basic/OpenMPKinds.def"
+ OMPClause *readClause();
+ void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
+ void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);
+};
+
} // namespace clang
#endif // LLVM_CLANG_SERIALIZATION_ASTREADER_H
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 7ff5d65bd7d0..11af30ac8373 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -19,16 +19,17 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@@ -955,6 +956,9 @@ public:
return Writer->AddVersionTuple(Version, *Record);
}
+ // Emit an attribute.
+ void AddAttr(const Attr *A);
+
/// Emit a list of attributes.
void AddAttributes(ArrayRef<const Attr*> Attrs);
};
@@ -990,6 +994,18 @@ public:
bool hasEmittedPCH() const { return Buffer->IsComplete; }
};
+class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> {
+ ASTRecordWriter &Record;
+
+public:
+ OMPClauseWriter(ASTRecordWriter &Record) : Record(Record) {}
+#define OPENMP_CLAUSE(Name, Class) void Visit##Class(Class *S);
+#include "clang/Basic/OpenMPKinds.def"
+ void writeClause(OMPClause *C);
+ void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
+ void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);
+};
+
} // namespace clang
#endif // LLVM_CLANG_SERIALIZATION_ASTWRITER_H
diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h
index 73bf2ed10f04..ad827e37db2d 100644
--- a/include/clang/Serialization/ContinuousRangeMap.h
+++ b/include/clang/Serialization/ContinuousRangeMap.h
@@ -118,7 +118,7 @@ public:
Builder &operator=(const Builder&) = delete;
~Builder() {
- llvm::sort(Self.Rep.begin(), Self.Rep.end(), Compare());
+ llvm::sort(Self.Rep, Compare());
std::unique(Self.Rep.begin(), Self.Rep.end(),
[](const_reference A, const_reference B) {
// FIXME: we should not allow any duplicate keys, but there are a lot of
diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h
index d47fe9517d76..5791fc024a32 100644
--- a/include/clang/Serialization/GlobalModuleIndex.h
+++ b/include/clang/Serialization/GlobalModuleIndex.h
@@ -42,11 +42,6 @@ namespace serialization {
class ModuleFile;
}
-using llvm::SmallVector;
-using llvm::SmallVectorImpl;
-using llvm::StringRef;
-using serialization::ModuleFile;
-
/// A global index for a set of module files, providing information about
/// the identifiers within those module files.
///
@@ -59,6 +54,8 @@ using serialization::ModuleFile;
/// imported, and can be queried to determine which modules the current
/// translation could or should load to fix a problem.
class GlobalModuleIndex {
+ using ModuleFile = serialization::ModuleFile;
+
/// Buffer containing the index file, which is lazily accessed so long
/// as the global module index is live.
std::unique_ptr<llvm::MemoryBuffer> Buffer;
@@ -147,7 +144,7 @@ public:
/// \returns A pair containing the global module index (if it exists) and
/// the error code.
static std::pair<GlobalModuleIndex *, ErrorCode>
- readIndex(StringRef Path);
+ readIndex(llvm::StringRef Path);
/// Returns an iterator for identifiers stored in the index table.
///
@@ -158,12 +155,12 @@ public:
///
/// \param ModuleFiles Will be populated with the set of module files that
/// have been indexed.
- void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles);
+ void getKnownModules(llvm::SmallVectorImpl<ModuleFile *> &ModuleFiles);
/// Retrieve the set of module files on which the given module file
/// directly depends.
void getModuleDependencies(ModuleFile *File,
- SmallVectorImpl<ModuleFile *> &Dependencies);
+ llvm::SmallVectorImpl<ModuleFile *> &Dependencies);
/// A set of module files in which we found a result.
typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet;
@@ -177,7 +174,7 @@ public:
/// information about this name.
///
/// \returns true if the identifier is known to the index, false otherwise.
- bool lookupIdentifier(StringRef Name, HitSet &Hits);
+ bool lookupIdentifier(llvm::StringRef Name, HitSet &Hits);
/// Note that the given module file has been loaded.
///
@@ -200,7 +197,7 @@ public:
/// which the global index will be written.
static ErrorCode writeIndex(FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
- StringRef Path);
+ llvm::StringRef Path);
};
}
diff --git a/include/clang/Serialization/PCHContainerOperations.h b/include/clang/Serialization/PCHContainerOperations.h
new file mode 100644
index 000000000000..2a91d9830af3
--- /dev/null
+++ b/include/clang/Serialization/PCHContainerOperations.h
@@ -0,0 +1,117 @@
+//===--- Serialization/PCHContainerOperations.h - PCH Containers --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_PCHCONTAINEROPERATIONS_H
+#define LLVM_CLANG_SERIALIZATION_PCHCONTAINEROPERATIONS_H
+
+#include "clang/Basic/Module.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
+
+namespace llvm {
+class raw_pwrite_stream;
+}
+
+namespace clang {
+
+class ASTConsumer;
+class CodeGenOptions;
+class DiagnosticsEngine;
+class CompilerInstance;
+
+struct PCHBuffer {
+ ASTFileSignature Signature;
+ llvm::SmallVector<char, 0> Data;
+ bool IsComplete;
+};
+
+/// This abstract interface provides operations for creating
+/// containers for serialized ASTs (precompiled headers and clang
+/// modules).
+class PCHContainerWriter {
+public:
+ virtual ~PCHContainerWriter() = 0;
+ virtual llvm::StringRef getFormat() const = 0;
+
+ /// Return an ASTConsumer that can be chained with a
+ /// PCHGenerator that produces a wrapper file format containing a
+ /// serialized AST bitstream.
+ virtual std::unique_ptr<ASTConsumer>
+ CreatePCHContainerGenerator(CompilerInstance &CI,
+ const std::string &MainFileName,
+ const std::string &OutputFileName,
+ std::unique_ptr<llvm::raw_pwrite_stream> OS,
+ std::shared_ptr<PCHBuffer> Buffer) const = 0;
+};
+
+/// This abstract interface provides operations for unwrapping
+/// containers for serialized ASTs (precompiled headers and clang
+/// modules).
+class PCHContainerReader {
+public:
+ virtual ~PCHContainerReader() = 0;
+ /// Equivalent to the format passed to -fmodule-format=
+ virtual llvm::StringRef getFormat() const = 0;
+
+ /// Returns the serialized AST inside the PCH container Buffer.
+ virtual llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0;
+};
+
+/// Implements write operations for a raw pass-through PCH container.
+class RawPCHContainerWriter : public PCHContainerWriter {
+ llvm::StringRef getFormat() const override { return "raw"; }
+
+ /// Return an ASTConsumer that can be chained with a
+ /// PCHGenerator that writes the module to a flat file.
+ std::unique_ptr<ASTConsumer>
+ CreatePCHContainerGenerator(CompilerInstance &CI,
+ const std::string &MainFileName,
+ const std::string &OutputFileName,
+ std::unique_ptr<llvm::raw_pwrite_stream> OS,
+ std::shared_ptr<PCHBuffer> Buffer) const override;
+};
+
+/// Implements read operations for a raw pass-through PCH container.
+class RawPCHContainerReader : public PCHContainerReader {
+ llvm::StringRef getFormat() const override { return "raw"; }
+
+ /// Simply returns the buffer contained in Buffer.
+ llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
+};
+
+/// A registry of PCHContainerWriter and -Reader objects for different formats.
+class PCHContainerOperations {
+ llvm::StringMap<std::unique_ptr<PCHContainerWriter>> Writers;
+ llvm::StringMap<std::unique_ptr<PCHContainerReader>> Readers;
+public:
+ /// Automatically registers a RawPCHContainerWriter and
+ /// RawPCHContainerReader.
+ PCHContainerOperations();
+ void registerWriter(std::unique_ptr<PCHContainerWriter> Writer) {
+ Writers[Writer->getFormat()] = std::move(Writer);
+ }
+ void registerReader(std::unique_ptr<PCHContainerReader> Reader) {
+ Readers[Reader->getFormat()] = std::move(Reader);
+ }
+ const PCHContainerWriter *getWriterOrNull(llvm::StringRef Format) {
+ return Writers[Format].get();
+ }
+ const PCHContainerReader *getReaderOrNull(llvm::StringRef Format) {
+ return Readers[Format].get();
+ }
+ const PCHContainerReader &getRawReader() {
+ return *getReaderOrNull("raw");
+ }
+};
+
+}
+
+#endif
diff --git a/include/clang/Serialization/SerializationDiagnostic.h b/include/clang/Serialization/SerializationDiagnostic.h
index d50422aa466c..2decd1c2f67b 100644
--- a/include/clang/Serialization/SerializationDiagnostic.h
+++ b/include/clang/Serialization/SerializationDiagnostic.h
@@ -10,19 +10,6 @@
#ifndef LLVM_CLANG_SERIALIZATION_SERIALIZATIONDIAGNOSTIC_H
#define LLVM_CLANG_SERIALIZATION_SERIALIZATIONDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-
-namespace clang {
- namespace diag {
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
-#define SERIALIZATIONSTART
-#include "clang/Basic/DiagnosticSerializationKinds.inc"
-#undef DIAG
- NUM_BUILTIN_SERIALIZATION_DIAGNOSTICS
- };
- } // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticSerialization.h"
#endif
diff --git a/lib/StaticAnalyzer/Checkers/ClangSACheckers.h b/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h
index d6e96f27a75e..192ac1261c76 100644
--- a/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
+++ b/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h
@@ -24,7 +24,7 @@ class CheckerManager;
class CheckerRegistry;
#define GET_CHECKERS
-#define CHECKER(FULLNAME,CLASS,CXXFILE,HELPTEXT,GROUPINDEX,HIDDEN) \
+#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
void register##CLASS(CheckerManager &mgr);
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef CHECKER
diff --git a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
index 11f1e5d4bd51..453e189fccb0 100644
--- a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
+++ b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
@@ -11,29 +11,47 @@
//
//===----------------------------------------------------------------------===//
-class CheckerGroup<string name> {
- string GroupName = name;
-}
-class InGroup<CheckerGroup G> { CheckerGroup Group = G; }
-
+/// Describes a package. Every checker is a part of a package, for example,
+/// 'NullDereference' is part of the 'core' package, hence it's full name is
+/// 'core.NullDereference'.
+/// Example:
+/// def Core : Package<"core">;
class Package<string name> {
string PackageName = name;
- bit Hidden = 0;
Package ParentPackage;
- CheckerGroup Group;
}
-class InPackage<Package P> { Package ParentPackage = P; }
-// All checkers are an indirect subclass of this.
+/// Describes a 'super' package that holds another package inside it. This is
+/// used to nest packages in one another. One may, for example, create the
+/// 'builtin' package inside 'core', thus creating the package 'core.builtin'.
+/// Example:
+/// def CoreBuiltin : Package<"builtin">, ParentPackage<Core>;
+class ParentPackage<Package P> { Package ParentPackage = P; }
+
+/// A description. May be displayed to the user when clang is invoked with
+/// a '-help'-like command line option.
+class HelpText<string text> { string HelpText = text; }
+
+/// Describes what kind of documentation exists for the checker.
+class DocumentationEnum<bits<2> val> {
+ bits<2> Documentation = val;
+}
+def NotDocumented : DocumentationEnum<0>;
+def HasDocumentation : DocumentationEnum<1>;
+def HasAlphaDocumentation : DocumentationEnum<2>;
+
+class Documentation<DocumentationEnum val> {
+ bits<2> Documentation = val.Documentation;
+}
+
+/// Describes a checker. Every builtin checker has to be registered with the use
+/// of this class (out-of-trunk checkers loaded from plugins obviously don't).
+/// Note that a checker has a name (e.g.: 'NullDereference'), and a fullname,
+/// that is autogenerated with the help of the ParentPackage field, that also
+/// includes package names (e.g.: 'core.NullDereference').
class Checker<string name = ""> {
string CheckerName = name;
- string DescFile;
string HelpText;
- bit Hidden = 0;
+ bits<2> Documentation;
Package ParentPackage;
- CheckerGroup Group;
}
-
-class DescFile<string filename> { string DescFile = filename; }
-class HelpText<string text> { string HelpText = text; }
-class Hidden { bit Hidden = 1; }
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 9e53460f6e93..1bb3da7a2458 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -21,9 +21,9 @@ include "CheckerBase.td"
def Alpha : Package<"alpha">;
def Core : Package<"core">;
-def CoreBuiltin : Package<"builtin">, InPackage<Core>;
-def CoreUninitialized : Package<"uninitialized">, InPackage<Core>;
-def CoreAlpha : Package<"core">, InPackage<Alpha>, Hidden;
+def CoreBuiltin : Package<"builtin">, ParentPackage<Core>;
+def CoreUninitialized : Package<"uninitialized">, ParentPackage<Core>;
+def CoreAlpha : Package<"core">, ParentPackage<Alpha>;
// The OptIn package is for checkers that are not alpha and that would normally
// be on by default but where the driver does not have enough information to
@@ -41,58 +41,59 @@ def OptIn : Package<"optin">;
// In the Portability package reside checkers for finding code that relies on
// implementation-defined behavior. Such checks are wanted for cross-platform
// development, but unwanted for developers who target only a single platform.
-def PortabilityOptIn : Package<"portability">, InPackage<OptIn>;
+def PortabilityOptIn : Package<"portability">, ParentPackage<OptIn>;
def Nullability : Package<"nullability">;
def Cplusplus : Package<"cplusplus">;
-def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden;
-def CplusplusOptIn : Package<"cplusplus">, InPackage<OptIn>;
+def CplusplusAlpha : Package<"cplusplus">, ParentPackage<Alpha>;
+def CplusplusOptIn : Package<"cplusplus">, ParentPackage<OptIn>;
def Valist : Package<"valist">;
def DeadCode : Package<"deadcode">;
-def DeadCodeAlpha : Package<"deadcode">, InPackage<Alpha>, Hidden;
+def DeadCodeAlpha : Package<"deadcode">, ParentPackage<Alpha>;
-def Performance : Package<"performance">, InPackage<OptIn>;
+def Performance : Package<"performance">, ParentPackage<OptIn>;
def Security : Package <"security">;
-def InsecureAPI : Package<"insecureAPI">, InPackage<Security>;
-def SecurityAlpha : Package<"security">, InPackage<Alpha>, Hidden;
-def Taint : Package<"taint">, InPackage<SecurityAlpha>, Hidden;
+def InsecureAPI : Package<"insecureAPI">, ParentPackage<Security>;
+def SecurityAlpha : Package<"security">, ParentPackage<Alpha>;
+def Taint : Package<"taint">, ParentPackage<SecurityAlpha>;
def Unix : Package<"unix">;
-def UnixAlpha : Package<"unix">, InPackage<Alpha>, Hidden;
-def CString : Package<"cstring">, InPackage<Unix>, Hidden;
-def CStringAlpha : Package<"cstring">, InPackage<UnixAlpha>, Hidden;
+def UnixAlpha : Package<"unix">, ParentPackage<Alpha>;
+def CString : Package<"cstring">, ParentPackage<Unix>;
+def CStringAlpha : Package<"cstring">, ParentPackage<UnixAlpha>;
def OSX : Package<"osx">;
-def OSXAlpha : Package<"osx">, InPackage<Alpha>, Hidden;
-def OSXOptIn : Package<"osx">, InPackage<OptIn>;
+def OSXAlpha : Package<"osx">, ParentPackage<Alpha>;
+def OSXOptIn : Package<"osx">, ParentPackage<OptIn>;
-def Cocoa : Package<"cocoa">, InPackage<OSX>;
-def CocoaAlpha : Package<"cocoa">, InPackage<OSXAlpha>, Hidden;
-def CocoaOptIn : Package<"cocoa">, InPackage<OSXOptIn>;
+def Cocoa : Package<"cocoa">, ParentPackage<OSX>;
+def CocoaAlpha : Package<"cocoa">, ParentPackage<OSXAlpha>;
+def CocoaOptIn : Package<"cocoa">, ParentPackage<OSXOptIn>;
-def CoreFoundation : Package<"coreFoundation">, InPackage<OSX>;
-def Containers : Package<"containers">, InPackage<CoreFoundation>;
+def CoreFoundation : Package<"coreFoundation">, ParentPackage<OSX>;
+def Containers : Package<"containers">, ParentPackage<CoreFoundation>;
-def LocalizabilityAlpha : Package<"localizability">, InPackage<CocoaAlpha>;
-def LocalizabilityOptIn : Package<"localizability">, InPackage<CocoaOptIn>;
+def LocalizabilityAlpha : Package<"localizability">, ParentPackage<CocoaAlpha>;
+def LocalizabilityOptIn : Package<"localizability">, ParentPackage<CocoaOptIn>;
-def MPI : Package<"mpi">, InPackage<OptIn>;
+def MPI : Package<"mpi">, ParentPackage<OptIn>;
def LLVM : Package<"llvm">;
+def LLVMAlpha : Package<"llvm">, ParentPackage<Alpha>;
// The APIModeling package is for checkers that model APIs and don't perform
// any diagnostics. These checkers are always turned on; this package is
// intended for API modeling that is not controlled by the target triple.
-def APIModeling : Package<"apiModeling">, Hidden;
-def GoogleAPIModeling : Package<"google">, InPackage<APIModeling>;
+def APIModeling : Package<"apiModeling">;
+def GoogleAPIModeling : Package<"google">, ParentPackage<APIModeling>;
def Debug : Package<"debug">;
-def CloneDetectionAlpha : Package<"clone">, InPackage<Alpha>, Hidden;
+def CloneDetectionAlpha : Package<"clone">, ParentPackage<Alpha>;
//===----------------------------------------------------------------------===//
// Core Checkers.
@@ -102,39 +103,42 @@ let ParentPackage = Core in {
def DereferenceChecker : Checker<"NullDereference">,
HelpText<"Check for dereferences of null pointers">,
- DescFile<"DereferenceChecker.cpp">;
+ Documentation<HasDocumentation>;
def CallAndMessageChecker : Checker<"CallAndMessage">,
- HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)">,
- DescFile<"CallAndMessageChecker.cpp">;
+ HelpText<"Check for logical errors for function calls and Objective-C "
+ "message expressions (e.g., uninitialized arguments, null function "
+ "pointers)">,
+ Documentation<HasDocumentation>;
def NonNullParamChecker : Checker<"NonNullParamChecker">,
- HelpText<"Check for null pointers passed as arguments to a function whose arguments are references or marked with the 'nonnull' attribute">,
- DescFile<"NonNullParamChecker.cpp">;
+ HelpText<"Check for null pointers passed as arguments to a function whose "
+ "arguments are references or marked with the 'nonnull' attribute">,
+ Documentation<HasDocumentation>;
def VLASizeChecker : Checker<"VLASize">,
HelpText<"Check for declarations of VLA of undefined or zero size">,
- DescFile<"VLASizeChecker.cpp">;
+ Documentation<HasDocumentation>;
def DivZeroChecker : Checker<"DivideZero">,
HelpText<"Check for division by zero">,
- DescFile<"DivZeroChecker.cpp">;
+ Documentation<HasDocumentation>;
def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">,
HelpText<"Check for undefined results of binary operators">,
- DescFile<"UndefResultChecker.cpp">;
+ Documentation<HasDocumentation>;
def StackAddrEscapeChecker : Checker<"StackAddressEscape">,
HelpText<"Check that addresses to stack memory do not escape the function">,
- DescFile<"StackAddrEscapeChecker.cpp">;
+ Documentation<HasDocumentation>;
def DynamicTypePropagation : Checker<"DynamicTypePropagation">,
HelpText<"Generate dynamic type information">,
- DescFile<"DynamicTypePropagation.cpp">;
+ Documentation<NotDocumented>;
def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">,
HelpText<"Assume that const string-like globals are non-null">,
- DescFile<"NonilStringConstantsChecker.cpp">;
+ Documentation<NotDocumented>;
} // end "core"
@@ -142,89 +146,105 @@ let ParentPackage = CoreAlpha in {
def BoolAssignmentChecker : Checker<"BoolAssignment">,
HelpText<"Warn about assigning non-{0,1} values to Boolean variables">,
- DescFile<"BoolAssignmentChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def CastSizeChecker : Checker<"CastSize">,
- HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">,
- DescFile<"CastSizeChecker.cpp">;
+ HelpText<"Check when casting a malloc'ed type T, whether the size is a "
+ "multiple of the size of T">,
+ Documentation<HasAlphaDocumentation>;
def CastToStructChecker : Checker<"CastToStruct">,
HelpText<"Check for cast from non-struct pointer to struct pointer">,
- DescFile<"CastToStructChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def ConversionChecker : Checker<"Conversion">,
HelpText<"Loss of sign/precision in implicit conversions">,
- DescFile<"ConversionChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def IdenticalExprChecker : Checker<"IdenticalExpr">,
HelpText<"Warn about unintended use of identical expressions in operators">,
- DescFile<"IdenticalExprChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def FixedAddressChecker : Checker<"FixedAddr">,
HelpText<"Check for assignment of a fixed address to a pointer">,
- DescFile<"FixedAddressChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def PointerArithChecker : Checker<"PointerArithm">,
- HelpText<"Check for pointer arithmetic on locations other than array elements">,
- DescFile<"PointerArithChecker">;
+ HelpText<"Check for pointer arithmetic on locations other than array "
+ "elements">,
+ Documentation<HasAlphaDocumentation>;
def PointerSubChecker : Checker<"PointerSub">,
- HelpText<"Check for pointer subtractions on two pointers pointing to different memory chunks">,
- DescFile<"PointerSubChecker">;
+ HelpText<"Check for pointer subtractions on two pointers pointing to "
+ "different memory chunks">,
+ Documentation<HasAlphaDocumentation>;
def SizeofPointerChecker : Checker<"SizeofPtr">,
HelpText<"Warn about unintended use of sizeof() on pointer expressions">,
- DescFile<"CheckSizeofPointer.cpp">;
+ Documentation<HasAlphaDocumentation>;
def CallAndMessageUnInitRefArg : Checker<"CallAndMessageUnInitRefArg">,
- HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables)">,
- DescFile<"CallAndMessageChecker.cpp">;
+ HelpText<"Check for logical errors for function calls and Objective-C "
+ "message expressions (e.g., uninitialized arguments, null function "
+ "pointers, and pointer to undefined variables)">,
+ Documentation<HasAlphaDocumentation>;
def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
- HelpText<"Check for division by variable that is later compared against 0. Either the comparison is useless or there is division by zero.">,
- DescFile<"TestAfterDivZeroChecker.cpp">;
+ HelpText<"Check for division by variable that is later compared against 0. "
+ "Either the comparison is useless or there is division by zero.">,
+ Documentation<HasAlphaDocumentation>;
def DynamicTypeChecker : Checker<"DynamicTypeChecker">,
- HelpText<"Check for cases where the dynamic and the static type of an object are unrelated.">,
- DescFile<"DynamicTypeChecker.cpp">;
+ HelpText<"Check for cases where the dynamic and the static type of an object "
+ "are unrelated.">,
+ Documentation<HasAlphaDocumentation>;
def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
HelpText<"Check that addresses to stack memory do not escape the function">,
- DescFile<"StackAddrEscapeChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
} // end "alpha.core"
let ParentPackage = Nullability in {
def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">,
- HelpText<"Warns when a null pointer is passed to a pointer which has a _Nonnull type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a null pointer is passed to a pointer which has a "
+ "_Nonnull type.">,
+ Documentation<HasDocumentation>;
def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">,
- HelpText<"Warns when a null pointer is returned from a function that has _Nonnull return type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a null pointer is returned from a function that has "
+ "_Nonnull return type.">,
+ Documentation<HasDocumentation>;
def NullableDereferencedChecker : Checker<"NullableDereferenced">,
HelpText<"Warns when a nullable pointer is dereferenced.">,
- DescFile<"NullabilityChecker.cpp">;
+ Documentation<HasDocumentation>;
def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">,
- HelpText<"Warns when a nullable pointer is passed to a pointer which has a _Nonnull type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a nullable pointer is passed to a pointer which has a "
+ "_Nonnull type.">,
+ Documentation<HasDocumentation>;
def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">,
- HelpText<"Warns when a nullable pointer is returned from a function that has _Nonnull return type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a nullable pointer is returned from a function that has "
+ "_Nonnull return type.">,
+ Documentation<NotDocumented>;
} // end "nullability"
let ParentPackage = APIModeling in {
+def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
+ HelpText<"Improve modeling of the C standard library functions">,
+ Documentation<NotDocumented>;
+
def TrustNonnullChecker : Checker<"TrustNonnull">,
- HelpText<"Trust that returns from framework methods annotated with _Nonnull are not null">,
- DescFile<"TrustNonnullChecker.cpp">;
+ HelpText<"Trust that returns from framework methods annotated with _Nonnull "
+ "are not null">,
+ Documentation<NotDocumented>;
-}
+} // end "apiModeling"
//===----------------------------------------------------------------------===//
// Evaluate "builtin" functions.
@@ -233,12 +253,13 @@ def TrustNonnullChecker : Checker<"TrustNonnull">,
let ParentPackage = CoreBuiltin in {
def NoReturnFunctionChecker : Checker<"NoReturnFunctions">,
- HelpText<"Evaluate \"panic\" functions that are known to not return to the caller">,
- DescFile<"NoReturnFunctionChecker.cpp">;
+ HelpText<"Evaluate \"panic\" functions that are known to not return to the "
+ "caller">,
+ Documentation<NotDocumented>;
def BuiltinFunctionChecker : Checker<"BuiltinFunctions">,
HelpText<"Evaluate compiler builtin functions (e.g., alloca())">,
- DescFile<"BuiltinFunctionChecker.cpp">;
+ Documentation<NotDocumented>;
} // end "core.builtin"
@@ -250,23 +271,23 @@ let ParentPackage = CoreUninitialized in {
def UndefinedArraySubscriptChecker : Checker<"ArraySubscript">,
HelpText<"Check for uninitialized values used as array subscripts">,
- DescFile<"UndefinedArraySubscriptChecker.cpp">;
+ Documentation<HasDocumentation>;
def UndefinedAssignmentChecker : Checker<"Assign">,
HelpText<"Check for assigning uninitialized values">,
- DescFile<"UndefinedAssignmentChecker.cpp">;
+ Documentation<HasDocumentation>;
def UndefBranchChecker : Checker<"Branch">,
HelpText<"Check for uninitialized values used as branch conditions">,
- DescFile<"UndefBranchChecker.cpp">;
+ Documentation<HasDocumentation>;
def UndefCapturedBlockVarChecker : Checker<"CapturedBlockVariable">,
HelpText<"Check for blocks that capture uninitialized values">,
- DescFile<"UndefCapturedBlockVarChecker.cpp">;
+ Documentation<NotDocumented>;
def ReturnUndefChecker : Checker<"UndefReturn">,
HelpText<"Check for uninitialized values being returned to the caller">,
- DescFile<"ReturnUndefChecker.cpp">;
+ Documentation<HasDocumentation>;
} // end "core.uninitialized"
@@ -277,20 +298,26 @@ def ReturnUndefChecker : Checker<"UndefReturn">,
let ParentPackage = Cplusplus in {
def InnerPointerChecker : Checker<"InnerPointer">,
- HelpText<"Check for inner pointers of C++ containers used after re/deallocation">,
- DescFile<"InnerPointerChecker.cpp">;
+ HelpText<"Check for inner pointers of C++ containers used after "
+ "re/deallocation">,
+ Documentation<NotDocumented>;
def NewDeleteChecker : Checker<"NewDelete">,
- HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,
- DescFile<"MallocChecker.cpp">;
+ HelpText<"Check for double-free and use-after-free problems. Traces memory "
+ "managed by new/delete.">,
+ Documentation<HasDocumentation>;
def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,
- DescFile<"MallocChecker.cpp">;
+ Documentation<HasDocumentation>;
def CXXSelfAssignmentChecker : Checker<"SelfAssignment">,
HelpText<"Checks C++ copy and move assignment operators for self assignment">,
- DescFile<"CXXSelfAssignmentChecker.cpp">;
+ Documentation<NotDocumented>;
+
+def MoveChecker: Checker<"Move">,
+ HelpText<"Find use-after-move bugs in C++">,
+ Documentation<HasDocumentation>;
} // end: "cplusplus"
@@ -298,7 +325,7 @@ let ParentPackage = CplusplusOptIn in {
def VirtualCallChecker : Checker<"VirtualCall">,
HelpText<"Check virtual function calls during construction or destruction">,
- DescFile<"VirtualCallChecker.cpp">;
+ Documentation<HasDocumentation>;
} // end: "optin.cplusplus"
@@ -307,20 +334,28 @@ let ParentPackage = CplusplusAlpha in {
def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">,
HelpText<"Reports destructions of polymorphic objects with a non-virtual "
"destructor in their base class">,
- DescFile<"DeleteWithNonVirtualDtorChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
+
+def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">,
+ HelpText<"Check integer to enumeration casts for out of range values">,
+ Documentation<HasAlphaDocumentation>;
+
+def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
+ HelpText<"Check for use of invalidated iterators">,
+ Documentation<HasAlphaDocumentation>;
def IteratorRangeChecker : Checker<"IteratorRange">,
HelpText<"Check for iterators used outside their valid ranges">,
- DescFile<"IteratorChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
-def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
- HelpText<"Method calls on a moved-from object and copying a moved-from "
- "object will be reported">,
- DescFile<"MisusedMovedObjectChecker.cpp">;
+def MismatchedIteratorChecker : Checker<"MismatchedIterator">,
+ HelpText<"Check for use of iterators of different containers where iterators "
+ "of the same container are expected">,
+ Documentation<HasAlphaDocumentation>;
def UninitializedObjectChecker: Checker<"UninitializedObject">,
HelpText<"Reports uninitialized fields after object construction">,
- DescFile<"UninitializedObjectChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
} // end: "alpha.cplusplus"
@@ -333,15 +368,15 @@ let ParentPackage = Valist in {
def UninitializedChecker : Checker<"Uninitialized">,
HelpText<"Check for usages of uninitialized (or already released) va_lists.">,
- DescFile<"ValistChecker.cpp">;
+ Documentation<NotDocumented>;
def UnterminatedChecker : Checker<"Unterminated">,
HelpText<"Check for va_lists which are not released by a va_end call.">,
- DescFile<"ValistChecker.cpp">;
+ Documentation<NotDocumented>;
def CopyToSelfChecker : Checker<"CopyToSelf">,
HelpText<"Check for va_lists which are copied onto itself.">,
- DescFile<"ValistChecker.cpp">;
+ Documentation<NotDocumented>;
} // end : "valist"
@@ -352,15 +387,17 @@ def CopyToSelfChecker : Checker<"CopyToSelf">,
let ParentPackage = DeadCode in {
def DeadStoresChecker : Checker<"DeadStores">,
- HelpText<"Check for values stored to variables that are never read afterwards">,
- DescFile<"DeadStoresChecker.cpp">;
+ HelpText<"Check for values stored to variables that are never read "
+ "afterwards">,
+ Documentation<HasDocumentation>;
+
} // end DeadCode
let ParentPackage = DeadCodeAlpha in {
def UnreachableCodeChecker : Checker<"UnreachableCode">,
HelpText<"Check unreachable code">,
- DescFile<"UnreachableCodeChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
} // end "alpha.deadcode"
@@ -372,7 +409,7 @@ let ParentPackage = Performance in {
def PaddingChecker : Checker<"Padding">,
HelpText<"Check for excessively padded structs.">,
- DescFile<"PaddingChecker.cpp">;
+ Documentation<NotDocumented>;
} // end: "padding"
@@ -381,70 +418,78 @@ def PaddingChecker : Checker<"Padding">,
//===----------------------------------------------------------------------===//
let ParentPackage = InsecureAPI in {
- def bcmp : Checker<"bcmp">,
- HelpText<"Warn on uses of the 'bcmp' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def bcopy : Checker<"bcopy">,
- HelpText<"Warn on uses of the 'bcopy' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def bzero : Checker<"bzero">,
- HelpText<"Warn on uses of the 'bzero' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def gets : Checker<"gets">,
- HelpText<"Warn on uses of the 'gets' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def getpw : Checker<"getpw">,
- HelpText<"Warn on uses of the 'getpw' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def mktemp : Checker<"mktemp">,
- HelpText<"Warn on uses of the 'mktemp' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def mkstemp : Checker<"mkstemp">,
- HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format string">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def rand : Checker<"rand">,
- HelpText<"Warn on uses of the 'rand', 'random', and related functions">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def strcpy : Checker<"strcpy">,
- HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def vfork : Checker<"vfork">,
- HelpText<"Warn on uses of the 'vfork' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def UncheckedReturn : Checker<"UncheckedReturn">,
- HelpText<"Warn on uses of functions whose return values must be always checked">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
-}
+
+def bcmp : Checker<"bcmp">,
+ HelpText<"Warn on uses of the 'bcmp' function">,
+ Documentation<HasDocumentation>;
+def bcopy : Checker<"bcopy">,
+ HelpText<"Warn on uses of the 'bcopy' function">,
+ Documentation<HasDocumentation>;
+def bzero : Checker<"bzero">,
+ HelpText<"Warn on uses of the 'bzero' function">,
+ Documentation<HasDocumentation>;
+def gets : Checker<"gets">,
+ HelpText<"Warn on uses of the 'gets' function">,
+ Documentation<HasDocumentation>;
+def getpw : Checker<"getpw">,
+ HelpText<"Warn on uses of the 'getpw' function">,
+ Documentation<HasDocumentation>;
+def mktemp : Checker<"mktemp">,
+ HelpText<"Warn on uses of the 'mktemp' function">,
+ Documentation<HasDocumentation>;
+def mkstemp : Checker<"mkstemp">,
+ HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format "
+ "string">,
+ Documentation<HasDocumentation>;
+def rand : Checker<"rand">,
+ HelpText<"Warn on uses of the 'rand', 'random', and related functions">,
+ Documentation<HasDocumentation>;
+def strcpy : Checker<"strcpy">,
+ HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">,
+ Documentation<HasDocumentation>;
+def vfork : Checker<"vfork">,
+ HelpText<"Warn on uses of the 'vfork' function">,
+ Documentation<HasDocumentation>;
+def UncheckedReturn : Checker<"UncheckedReturn">,
+ HelpText<"Warn on uses of functions whose return values must be always "
+ "checked">,
+ Documentation<HasDocumentation>;
+
+} // end "security.insecureAPI"
+
let ParentPackage = Security in {
- def FloatLoopCounter : Checker<"FloatLoopCounter">,
- HelpText<"Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP)">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
-}
+
+def FloatLoopCounter : Checker<"FloatLoopCounter">,
+ HelpText<"Warn on using a floating point value as a loop counter (CERT: "
+ "FLP30-C, FLP30-CPP)">,
+ Documentation<HasDocumentation>;
+
+} // end "security"
let ParentPackage = SecurityAlpha in {
def ArrayBoundChecker : Checker<"ArrayBound">,
HelpText<"Warn about buffer overflows (older checker)">,
- DescFile<"ArrayBoundChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def ArrayBoundCheckerV2 : Checker<"ArrayBoundV2">,
HelpText<"Warn about buffer overflows (newer checker)">,
- DescFile<"ArrayBoundCheckerV2.cpp">;
+ Documentation<HasAlphaDocumentation>;
def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
HelpText<"Check for an out-of-bound pointer being returned to callers">,
- DescFile<"ReturnPointerRangeChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def MallocOverflowSecurityChecker : Checker<"MallocOverflow">,
HelpText<"Check for overflows in the arguments to malloc()">,
- DescFile<"MallocOverflowSecurityChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
// Operating systems specific PROT_READ/PROT_WRITE values is not implemented,
// the defaults are correct for several common operating systems though,
// but may need to be overridden via the related analyzer-config flags.
def MmapWriteExecChecker : Checker<"MmapWriteExec">,
HelpText<"Warn on mmap() calls that are both writable and executable">,
- DescFile<"MmapWriteExecChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
} // end "alpha.security"
@@ -456,7 +501,7 @@ let ParentPackage = Taint in {
def GenericTaintChecker : Checker<"TaintPropagation">,
HelpText<"Generate taint information used by other checkers">,
- DescFile<"GenericTaintChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
} // end "alpha.security.taint"
@@ -468,27 +513,24 @@ let ParentPackage = Unix in {
def UnixAPIMisuseChecker : Checker<"API">,
HelpText<"Check calls to various UNIX/Posix functions">,
- DescFile<"UnixAPIChecker.cpp">;
+ Documentation<HasDocumentation>;
def MallocChecker: Checker<"Malloc">,
- HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().">,
- DescFile<"MallocChecker.cpp">;
+ HelpText<"Check for memory leaks, double free, and use-after-free problems. "
+ "Traces memory managed by malloc()/free().">,
+ Documentation<HasDocumentation>;
def MallocSizeofChecker : Checker<"MallocSizeof">,
HelpText<"Check for dubious malloc arguments involving sizeof">,
- DescFile<"MallocSizeofChecker.cpp">;
+ Documentation<HasDocumentation>;
def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">,
HelpText<"Check for mismatched deallocators.">,
- DescFile<"MallocChecker.cpp">;
+ Documentation<HasDocumentation>;
def VforkChecker : Checker<"Vfork">,
HelpText<"Check for proper usage of vfork">,
- DescFile<"VforkChecker.cpp">;
-
-def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
- HelpText<"Improve modeling of the C standard library functions">,
- DescFile<"StdLibraryFunctionsChecker.cpp">;
+ Documentation<HasDocumentation>;
} // end "unix"
@@ -496,51 +538,55 @@ let ParentPackage = UnixAlpha in {
def ChrootChecker : Checker<"Chroot">,
HelpText<"Check improper use of chroot">,
- DescFile<"ChrootChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def PthreadLockChecker : Checker<"PthreadLock">,
HelpText<"Simple lock -> unlock checker">,
- DescFile<"PthreadLockChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def StreamChecker : Checker<"Stream">,
HelpText<"Check stream handling functions">,
- DescFile<"StreamChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def SimpleStreamChecker : Checker<"SimpleStream">,
HelpText<"Check for misuses of stream APIs">,
- DescFile<"SimpleStreamChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
HelpText<"Check for calls to blocking functions inside a critical section">,
- DescFile<"BlockInCriticalSectionChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
} // end "alpha.unix"
let ParentPackage = CString in {
def CStringNullArg : Checker<"NullArg">,
- HelpText<"Check for null pointers being passed as arguments to C string functions">,
- DescFile<"CStringChecker.cpp">;
+ HelpText<"Check for null pointers being passed as arguments to C string "
+ "functions">,
+ Documentation<HasDocumentation>;
def CStringSyntaxChecker : Checker<"BadSizeArg">,
- HelpText<"Check the size argument passed into C string functions for common erroneous patterns">,
- DescFile<"CStringSyntaxChecker.cpp">;
-}
+ HelpText<"Check the size argument passed into C string functions for common "
+ "erroneous patterns">,
+ Documentation<HasDocumentation>;
+
+} // end "unix.cstring"
let ParentPackage = CStringAlpha in {
def CStringOutOfBounds : Checker<"OutOfBounds">,
HelpText<"Check for out-of-bounds access in string functions">,
- DescFile<"CStringChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def CStringBufferOverlap : Checker<"BufferOverlap">,
HelpText<"Checks for overlap in two buffer arguments">,
- DescFile<"CStringChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
def CStringNotNullTerm : Checker<"NotNullTerminated">,
HelpText<"Check for arguments which are not null-terminating strings">,
- DescFile<"CStringChecker.cpp">;
-}
+ Documentation<HasAlphaDocumentation>;
+
+} // end "alpha.unix.cstring"
//===----------------------------------------------------------------------===//
// Mac OS X, Cocoa, and Core Foundation checkers.
@@ -549,123 +595,142 @@ def CStringNotNullTerm : Checker<"NotNullTerminated">,
let ParentPackage = OSX in {
def NumberObjectConversionChecker : Checker<"NumberObjectConversion">,
- HelpText<"Check for erroneous conversions of objects representing numbers into numbers">,
- DescFile<"NumberObjectConversionChecker.cpp">;
+ HelpText<"Check for erroneous conversions of objects representing numbers "
+ "into numbers">,
+ Documentation<NotDocumented>;
def MacOSXAPIChecker : Checker<"API">,
HelpText<"Check for proper uses of various Apple APIs">,
- DescFile<"MacOSXAPIChecker.cpp">;
+ Documentation<HasDocumentation>;
def MacOSKeychainAPIChecker : Checker<"SecKeychainAPI">,
HelpText<"Check for proper uses of Secure Keychain APIs">,
- DescFile<"MacOSKeychainAPIChecker.cpp">;
+ Documentation<HasDocumentation>;
def ObjCPropertyChecker : Checker<"ObjCProperty">,
HelpText<"Check for proper uses of Objective-C properties">,
- DescFile<"ObjCPropertyChecker.cpp">;
+ Documentation<NotDocumented>;
+
+def OSObjectRetainCountChecker : Checker<"OSObjectRetainCount">,
+ HelpText<"Check for leaks and improper reference count management for OSObject">,
+ Documentation<NotDocumented>;
} // end "osx"
let ParentPackage = Cocoa in {
def RunLoopAutoreleaseLeakChecker : Checker<"RunLoopAutoreleaseLeak">,
- HelpText<"Check for leaked memory in autorelease pools that will never be drained">,
- DescFile<"RunLoopAutoreleaseLeakChecker.cpp">;
+ HelpText<"Check for leaked memory in autorelease pools that will never be "
+ "drained">,
+ Documentation<NotDocumented>;
def ObjCAtSyncChecker : Checker<"AtSync">,
HelpText<"Check for nil pointers used as mutexes for @synchronized">,
- DescFile<"ObjCAtSyncChecker.cpp">;
+ Documentation<HasDocumentation>;
def NilArgChecker : Checker<"NilArg">,
HelpText<"Check for prohibited nil arguments to ObjC method calls">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ Documentation<HasDocumentation>;
def ClassReleaseChecker : Checker<"ClassRelease">,
- HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly to a Class">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly "
+ "to a Class">,
+ Documentation<HasDocumentation>;
def VariadicMethodTypeChecker : Checker<"VariadicMethodTypes">,
HelpText<"Check for passing non-Objective-C types to variadic collection "
"initialization methods that expect only Objective-C types">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ Documentation<HasDocumentation>;
def NSAutoreleasePoolChecker : Checker<"NSAutoreleasePool">,
- HelpText<"Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode">,
- DescFile<"NSAutoreleasePoolChecker.cpp">;
+ HelpText<"Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC "
+ "mode">,
+ Documentation<HasDocumentation>;
def ObjCMethSigsChecker : Checker<"IncompatibleMethodTypes">,
- HelpText<"Warn about Objective-C method signatures with type incompatibilities">,
- DescFile<"CheckObjCInstMethSignature.cpp">;
+ HelpText<"Warn about Objective-C method signatures with type "
+ "incompatibilities">,
+ Documentation<HasDocumentation>;
def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">,
HelpText<"Warn about private ivars that are never used">,
- DescFile<"ObjCUnusedIVarsChecker.cpp">;
+ Documentation<HasDocumentation>;
def ObjCSelfInitChecker : Checker<"SelfInit">,
- HelpText<"Check that 'self' is properly initialized inside an initializer method">,
- DescFile<"ObjCSelfInitChecker.cpp">;
+ HelpText<"Check that 'self' is properly initialized inside an initializer "
+ "method">,
+ Documentation<HasDocumentation>;
def ObjCLoopChecker : Checker<"Loops">,
HelpText<"Improved modeling of loops using Cocoa collection types">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ Documentation<NotDocumented>;
def ObjCNonNilReturnValueChecker : Checker<"NonNilReturnValue">,
HelpText<"Model the APIs that are guaranteed to return a non-nil value">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ Documentation<NotDocumented>;
def ObjCSuperCallChecker : Checker<"MissingSuperCall">,
- HelpText<"Warn about Objective-C methods that lack a necessary call to super">,
- DescFile<"ObjCMissingSuperCallChecker.cpp">;
+ HelpText<"Warn about Objective-C methods that lack a necessary call to "
+ "super">,
+ Documentation<NotDocumented>;
def NSErrorChecker : Checker<"NSError">,
HelpText<"Check usage of NSError** parameters">,
- DescFile<"NSErrorChecker.cpp">;
+ Documentation<HasDocumentation>;
def RetainCountChecker : Checker<"RetainCount">,
HelpText<"Check for leaks and improper reference count management">,
- DescFile<"RetainCountChecker.cpp">;
+ Documentation<HasDocumentation>;
def ObjCGenericsChecker : Checker<"ObjCGenerics">,
HelpText<"Check for type errors when using Objective-C generics">,
- DescFile<"DynamicTypePropagation.cpp">;
+ Documentation<HasDocumentation>;
def ObjCDeallocChecker : Checker<"Dealloc">,
- HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">,
- DescFile<"CheckObjCDealloc.cpp">;
+ HelpText<"Warn about Objective-C classes that lack a correct implementation "
+ "of -dealloc">,
+ Documentation<HasDocumentation>;
def ObjCSuperDeallocChecker : Checker<"SuperDealloc">,
HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">,
- DescFile<"ObjCSuperDeallocChecker.cpp">;
+ Documentation<HasDocumentation>;
def AutoreleaseWriteChecker : Checker<"AutoreleaseWrite">,
- HelpText<"Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C">,
- DescFile<"ObjCAutoreleaseWriteChecker.cpp">;
+ HelpText<"Warn about potentially crashing writes to autoreleasing objects "
+ "from different autoreleasing pools in Objective-C">,
+ Documentation<NotDocumented>;
+
} // end "osx.cocoa"
let ParentPackage = Performance in {
def GCDAntipattern : Checker<"GCDAntipattern">,
- HelpText<"Check for performance anti-patterns when using Grand Central Dispatch">,
- DescFile<"GCDAntipatternChecker.cpp">;
+ HelpText<"Check for performance anti-patterns when using Grand Central "
+ "Dispatch">,
+ Documentation<NotDocumented>;
} // end "optin.performance"
let ParentPackage = CocoaAlpha in {
def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">,
- HelpText<"Check that the invalidatable instance variables are invalidated in the methods annotated with objc_instance_variable_invalidator">,
- DescFile<"IvarInvalidationChecker.cpp">;
+ HelpText<"Check that the invalidatable instance variables are invalidated in "
+ "the methods annotated with objc_instance_variable_invalidator">,
+ Documentation<HasAlphaDocumentation>;
def MissingInvalidationMethod : Checker<"MissingInvalidationMethod">,
- HelpText<"Check that the invalidation methods are present in classes that contain invalidatable instance variables">,
- DescFile<"IvarInvalidationChecker.cpp">;
+ HelpText<"Check that the invalidation methods are present in classes that "
+ "contain invalidatable instance variables">,
+ Documentation<HasAlphaDocumentation>;
def DirectIvarAssignment : Checker<"DirectIvarAssignment">,
HelpText<"Check for direct assignments to instance variables">,
- DescFile<"DirectIvarAssignment.cpp">;
+ Documentation<HasAlphaDocumentation>;
-def DirectIvarAssignmentForAnnotatedFunctions : Checker<"DirectIvarAssignmentForAnnotatedFunctions">,
- HelpText<"Check for direct assignments to instance variables in the methods annotated with objc_no_direct_instance_variable_assignment">,
- DescFile<"DirectIvarAssignment.cpp">;
+def DirectIvarAssignmentForAnnotatedFunctions :
+ Checker<"DirectIvarAssignmentForAnnotatedFunctions">,
+ HelpText<"Check for direct assignments to instance variables in the methods "
+ "annotated with objc_no_direct_instance_variable_assignment">,
+ Documentation<HasAlphaDocumentation>;
} // end "alpha.osx.cocoa"
@@ -673,69 +738,85 @@ let ParentPackage = CoreFoundation in {
def CFNumberChecker : Checker<"CFNumber">,
HelpText<"Check for proper uses of CFNumber APIs">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ Documentation<HasDocumentation>;
def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
HelpText<"Check for null arguments to CFRetain/CFRelease/CFMakeCollectable">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ Documentation<HasDocumentation>;
def CFErrorChecker : Checker<"CFError">,
HelpText<"Check usage of CFErrorRef* parameters">,
- DescFile<"NSErrorChecker.cpp">;
-}
+ Documentation<HasDocumentation>;
+
+} // end "osx.coreFoundation"
let ParentPackage = Containers in {
+
def ObjCContainersASTChecker : Checker<"PointerSizedValues">,
- HelpText<"Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values">,
- DescFile<"ObjCContainersASTChecker.cpp">;
+ HelpText<"Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with "
+ "non-pointer-size values">,
+ Documentation<HasDocumentation>;
def ObjCContainersChecker : Checker<"OutOfBounds">,
HelpText<"Checks for index out-of-bounds when using 'CFArray' API">,
- DescFile<"ObjCContainersChecker.cpp">;
+ Documentation<HasDocumentation>;
-}
+} // end "osx.coreFoundation.containers"
let ParentPackage = LocalizabilityOptIn in {
+
def NonLocalizedStringChecker : Checker<"NonLocalizedStringChecker">,
- HelpText<"Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings">,
- DescFile<"LocalizationChecker.cpp">;
+ HelpText<"Warns about uses of non-localized NSStrings passed to UI methods "
+ "expecting localized NSStrings">,
+ Documentation<HasDocumentation>;
-def EmptyLocalizationContextChecker : Checker<"EmptyLocalizationContextChecker">,
+def EmptyLocalizationContextChecker :
+ Checker<"EmptyLocalizationContextChecker">,
HelpText<"Check that NSLocalizedString macros include a comment for context">,
- DescFile<"LocalizationChecker.cpp">;
-}
+ Documentation<HasDocumentation>;
+
+} // end "optin.osx.cocoa.localizability"
let ParentPackage = LocalizabilityAlpha in {
+
def PluralMisuseChecker : Checker<"PluralMisuseChecker">,
- HelpText<"Warns against using one vs. many plural pattern in code when generating localized strings.">,
- DescFile<"LocalizationChecker.cpp">;
-}
+ HelpText<"Warns against using one vs. many plural pattern in code when "
+ "generating localized strings.">,
+ Documentation<HasAlphaDocumentation>;
+
+} // end "alpha.osx.cocoa.localizability"
let ParentPackage = MPI in {
- def MPIChecker : Checker<"MPI-Checker">,
+
+def MPIChecker : Checker<"MPI-Checker">,
HelpText<"Checks MPI code">,
- DescFile<"MPIChecker.cpp">;
-}
+ Documentation<HasDocumentation>;
+
+} // end "optin.mpi"
//===----------------------------------------------------------------------===//
// Checkers for LLVM development.
//===----------------------------------------------------------------------===//
+let ParentPackage = LLVMAlpha in {
+
def LLVMConventionsChecker : Checker<"Conventions">,
- InPackage<LLVM>,
HelpText<"Check code for LLVM codebase conventions">,
- DescFile<"LLVMConventionsChecker.cpp">;
-
+ Documentation<HasAlphaDocumentation>;
+} // end "llvm"
//===----------------------------------------------------------------------===//
// Checkers modeling Google APIs.
//===----------------------------------------------------------------------===//
+let ParentPackage = GoogleAPIModeling in {
+
def GTestChecker : Checker<"GTest">,
- InPackage<GoogleAPIModeling>,
HelpText<"Model gtest assertion APIs">,
- DescFile<"GTestChecker.cpp">;
+ Documentation<NotDocumented>;
+
+} // end "apiModeling.google"
//===----------------------------------------------------------------------===//
// Debugging checkers (for analyzer development).
@@ -745,59 +826,63 @@ let ParentPackage = Debug in {
def AnalysisOrderChecker : Checker<"AnalysisOrder">,
HelpText<"Print callbacks that are called during analysis in order">,
- DescFile<"AnalysisOrder.cpp">;
+ Documentation<NotDocumented>;
def DominatorsTreeDumper : Checker<"DumpDominators">,
HelpText<"Print the dominance tree for a given CFG">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
def LiveVariablesDumper : Checker<"DumpLiveVars">,
HelpText<"Print results of live variable analysis">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
+
+def LiveStatementsDumper : Checker<"DumpLiveStmts">,
+ HelpText<"Print results of live statement analysis">,
+ Documentation<NotDocumented>;
def CFGViewer : Checker<"ViewCFG">,
HelpText<"View Control-Flow Graphs using GraphViz">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
def CFGDumper : Checker<"DumpCFG">,
HelpText<"Display Control-Flow Graphs">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
def CallGraphViewer : Checker<"ViewCallGraph">,
HelpText<"View Call Graph using GraphViz">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
def CallGraphDumper : Checker<"DumpCallGraph">,
HelpText<"Display Call Graph">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
def ConfigDumper : Checker<"ConfigDumper">,
HelpText<"Dump config table">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
def TraversalDumper : Checker<"DumpTraversal">,
HelpText<"Print branch conditions as they are traversed by the engine">,
- DescFile<"TraversalChecker.cpp">;
+ Documentation<NotDocumented>;
def CallDumper : Checker<"DumpCalls">,
HelpText<"Print calls as they are traversed by the engine">,
- DescFile<"TraversalChecker.cpp">;
+ Documentation<NotDocumented>;
def AnalyzerStatsChecker : Checker<"Stats">,
HelpText<"Emit warnings with analyzer statistics">,
- DescFile<"AnalyzerStatsChecker.cpp">;
+ Documentation<NotDocumented>;
def TaintTesterChecker : Checker<"TaintTest">,
HelpText<"Mark tainted symbols as such.">,
- DescFile<"TaintTesterChecker.cpp">;
+ Documentation<NotDocumented>;
def ExprInspectionChecker : Checker<"ExprInspection">,
HelpText<"Check the analyzer's understanding of expressions">,
- DescFile<"ExprInspectionChecker.cpp">;
+ Documentation<NotDocumented>;
def ExplodedGraphViewer : Checker<"ViewExplodedGraph">,
HelpText<"View Exploded Graphs using GraphViz">,
- DescFile<"DebugCheckers.cpp">;
+ Documentation<NotDocumented>;
} // end "debug"
@@ -810,7 +895,7 @@ let ParentPackage = CloneDetectionAlpha in {
def CloneChecker : Checker<"CloneChecker">,
HelpText<"Reports similar pieces of code.">,
- DescFile<"CloneChecker.cpp">;
+ Documentation<HasAlphaDocumentation>;
} // end "clone"
@@ -822,6 +907,6 @@ let ParentPackage = PortabilityOptIn in {
def UnixAPIPortabilityChecker : Checker<"UnixAPI">,
HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">,
- DescFile<"UnixAPIChecker.cpp">;
+ Documentation<NotDocumented>;
} // end optin.portability
diff --git a/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h b/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h
deleted file mode 100644
index cf0a30a73d8c..000000000000
--- a/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//===--- ClangCheckers.h - Provides builtin checkers ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_CLANGCHECKERS_H
-#define LLVM_CLANG_STATICANALYZER_CHECKERS_CLANGCHECKERS_H
-
-namespace clang {
-namespace ento {
-class CheckerRegistry;
-
-void registerBuiltinCheckers(CheckerRegistry &registry);
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
deleted file mode 100644
index f5a06394b187..000000000000
--- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ /dev/null
@@ -1,232 +0,0 @@
-//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the core data structures for retain count "summaries"
-// for Objective-C and Core Foundation APIs. These summaries are used
-// by the static analyzer to summarize the retain/release effects of
-// function and method calls. This drives a path-sensitive typestate
-// analysis in the static analyzer, but can also potentially be used by
-// other clients.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
-#define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
-
-namespace clang {
-class FunctionDecl;
-class ObjCMethodDecl;
-
-namespace ento { namespace objc_retain {
-
-/// An ArgEffect summarizes the retain count behavior on an argument or receiver
-/// to a function or method.
-enum ArgEffect {
- /// There is no effect.
- DoNothing,
-
- /// The argument is treated as if an -autorelease message had been sent to
- /// the referenced object.
- Autorelease,
-
- /// The argument is treated as if an -dealloc message had been sent to
- /// the referenced object.
- Dealloc,
-
- /// The argument has its reference count decreased by 1. This is as
- /// if CFRelease has been called on the argument.
- DecRef,
-
- /// The argument has its reference count decreased by 1. This is as
- /// if a -release message has been sent to the argument. This differs
- /// in behavior from DecRef when GC is enabled.
- DecRefMsg,
-
- /// The argument has its reference count decreased by 1 to model
- /// a transferred bridge cast under ARC.
- DecRefBridgedTransferred,
-
- /// The argument has its reference count increased by 1. This is as
- /// if a -retain message has been sent to the argument. This differs
- /// in behavior from IncRef when GC is enabled.
- IncRefMsg,
-
- /// The argument has its reference count increased by 1. This is as
- /// if CFRetain has been called on the argument.
- IncRef,
-
- /// The argument acts as if has been passed to CFMakeCollectable, which
- /// transfers the object to the Garbage Collector under GC.
- MakeCollectable,
-
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +0 value or NULL.
- UnretainedOutParameter,
-
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +1 value or NULL.
- RetainedOutParameter,
-
- /// The argument is treated as potentially escaping, meaning that
- /// even when its reference count hits 0 it should be treated as still
- /// possibly being alive as someone else *may* be holding onto the object.
- MayEscape,
-
- /// All typestate tracking of the object ceases. This is usually employed
- /// when the effect of the call is completely unknown.
- StopTracking,
-
- /// All typestate tracking of the object ceases. Unlike StopTracking,
- /// this is also enforced when the method body is inlined.
- ///
- /// In some cases, we obtain a better summary for this checker
- /// by looking at the call site than by inlining the function.
- /// Signifies that we should stop tracking the symbol even if
- /// the function is inlined.
- StopTrackingHard,
-
- /// Performs the combined functionality of DecRef and StopTrackingHard.
- ///
- /// The models the effect that the called function decrements the reference
- /// count of the argument and all typestate tracking on that argument
- /// should cease.
- DecRefAndStopTrackingHard,
-
- /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
- ///
- /// The models the effect that the called function decrements the reference
- /// count of the argument and all typestate tracking on that argument
- /// should cease.
- DecRefMsgAndStopTrackingHard
-};
-
-/// RetEffect summarizes a call's retain/release behavior with respect
-/// to its return value.
-class RetEffect {
-public:
- enum Kind {
- /// Indicates that no retain count information is tracked for
- /// the return value.
- NoRet,
- /// Indicates that the returned value is an owned (+1) symbol.
- OwnedSymbol,
- /// Indicates that the returned value is an object with retain count
- /// semantics but that it is not owned (+0). This is the default
- /// for getters, etc.
- NotOwnedSymbol,
- /// Indicates that the object is not owned and controlled by the
- /// Garbage collector.
- GCNotOwnedSymbol,
- /// Indicates that the return value is an owned object when the
- /// receiver is also a tracked object.
- OwnedWhenTrackedReceiver,
- // Treat this function as returning a non-tracked symbol even if
- // the function has been inlined. This is used where the call
- // site summary is more presise than the summary indirectly produced
- // by inlining the function
- NoRetHard
- };
-
- /// Determines the object kind of a tracked object.
- enum ObjKind {
- /// Indicates that the tracked object is a CF object. This is
- /// important between GC and non-GC code.
- CF,
- /// Indicates that the tracked object is an Objective-C object.
- ObjC,
- /// Indicates that the tracked object could be a CF or Objective-C object.
- AnyObj,
- /// Indicates that the tracked object is a generalized object.
- Generalized
- };
-
-private:
- Kind K;
- ObjKind O;
-
- RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
-
-public:
- Kind getKind() const { return K; }
-
- ObjKind getObjKind() const { return O; }
-
- bool isOwned() const {
- return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
- }
-
- bool notOwned() const {
- return K == NotOwnedSymbol;
- }
-
- bool operator==(const RetEffect &Other) const {
- return K == Other.K && O == Other.O;
- }
-
- static RetEffect MakeOwnedWhenTrackedReceiver() {
- return RetEffect(OwnedWhenTrackedReceiver, ObjC);
- }
-
- static RetEffect MakeOwned(ObjKind o) {
- return RetEffect(OwnedSymbol, o);
- }
- static RetEffect MakeNotOwned(ObjKind o) {
- return RetEffect(NotOwnedSymbol, o);
- }
- static RetEffect MakeGCNotOwned() {
- return RetEffect(GCNotOwnedSymbol, ObjC);
- }
- static RetEffect MakeNoRet() {
- return RetEffect(NoRet);
- }
- static RetEffect MakeNoRetHard() {
- return RetEffect(NoRetHard);
- }
-};
-
-/// Encapsulates the retain count semantics on the arguments, return value,
-/// and receiver (if any) of a function/method call.
-///
-/// Note that construction of these objects is not highly efficient. That
-/// is okay for clients where creating these objects isn't really a bottleneck.
-/// The purpose of the API is to provide something simple. The actual
-/// static analyzer checker that implements retain/release typestate
-/// tracking uses something more efficient.
-class CallEffects {
- llvm::SmallVector<ArgEffect, 10> Args;
- RetEffect Ret;
- ArgEffect Receiver;
-
- CallEffects(const RetEffect &R) : Ret(R) {}
-
-public:
- /// Returns the argument effects for a call.
- ArrayRef<ArgEffect> getArgs() const { return Args; }
-
- /// Returns the effects on the receiver.
- ArgEffect getReceiver() const { return Receiver; }
-
- /// Returns the effect on the return value.
- RetEffect getReturnValue() const { return Ret; }
-
- /// Return the CallEfect for a given Objective-C method.
- static CallEffects getEffect(const ObjCMethodDecl *MD);
-
- /// Return the CallEfect for a given C/C++ function.
- static CallEffects getEffect(const FunctionDecl *FD);
-};
-
-}}}
-
-#endif
-
diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def
index 281a2ac3a66f..99e26c75e1c2 100644
--- a/include/clang/StaticAnalyzer/Core/Analyses.def
+++ b/include/clang/StaticAnalyzer/Core/Analyses.def
@@ -33,6 +33,7 @@ ANALYSIS_DIAGNOSTICS(HTML_SINGLE_FILE, "html-single-file", "Output analysis resu
ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for multi-file bugs)", createPlistMultiFileDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(SARIF, "sarif", "Output analysis results in a SARIF file", createSarifDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
#ifndef ANALYSIS_PURGE
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
new file mode 100644
index 000000000000..3cd54df7b179
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -0,0 +1,377 @@
+//===-- AnalyzerOptions.def - Metadata about Static Analyses ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the analyzer options avaible with -analyzer-config.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGREF_H
+#error This .def file is expected to be included in translation units where \
+"llvm/ADT/StringRef.h" is already included!
+#endif
+
+#ifdef ANALYZER_OPTION
+#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+#error If you didnt include this file with the intent of generating methods, \
+define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros!
+#endif
+#endif
+
+#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+#ifdef ANALYZER_OPTION
+#error If you didnt include this file with the intent of generating methods, \
+define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros!
+#endif
+#endif
+
+#ifndef ANALYZER_OPTION
+/// Create a new analyzer option, but dont generate a method for it in
+/// AnalyzerOptions.
+///
+/// TYPE - The type of the option object that will be stored in
+/// AnalyzerOptions. This file is expected to be icluded in translation
+/// units where AnalyzerOptions.h is included, so types from that
+/// header should be used.
+/// NAME - The name of the option object.
+/// CMDFLAG - The command line flag for the option.
+/// (-analyzer-config CMDFLAG=VALUE)
+/// DESC - Description of the flag.
+/// DEFAULT_VAL - The default value for CMDFLAG.
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)
+#endif
+
+#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+/// Create a new analyzer option, but dont generate a method for it in
+/// AnalyzerOptions. It's value depends on the option "user-mode".
+///
+/// TYPE - The type of the option object that will be stored in
+/// AnalyzerOptions. This file is expected to be icluded in translation
+/// units where AnalyzerOptions.h is included, so types from that
+/// header should be used.
+/// NAME - The name of the option object.
+/// CMDFLAG - The command line flag for the option.
+/// (-analyzer-config CMDFLAG=VALUE)
+/// DESC - Description of the flag.
+/// SHALLOW_VAL - The default value for CMDFLAG, when "user-mode" was set to
+/// "shallow".
+/// DEEP_VAL - The default value for CMDFLAG, when "user-mode" was set to
+/// "deep".
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL)
+#endif
+
+//===----------------------------------------------------------------------===//
+// The "mode" option. Since some options depend on this, we list it on top of
+// this file in order to make sure that the generated field for it is
+// initialized before the rest.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(
+ StringRef, UserMode, "mode",
+ "(string) Controls the high-level analyzer mode, which influences the "
+ "default settings for some of the lower-level config options (such as "
+ "IPAMode). Value: \"deep\", \"shallow\".",
+ "deep")
+
+//===----------------------------------------------------------------------===//
+// Boolean analyzer options.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(bool, ShouldIncludeImplicitDtorsInCFG, "cfg-implicit-dtors",
+ "Whether or not implicit destructors for C++ objects "
+ "should be included in the CFG.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldIncludeTemporaryDtorsInCFG, "cfg-temporary-dtors",
+ "Whether or not the destructors for C++ temporary "
+ "objects should be included in the CFG.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldIncludeLifetimeInCFG, "cfg-lifetime",
+ "Whether or not end-of-lifetime information should be included in the CFG.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldIncludeLoopExitInCFG, "cfg-loopexit",
+ "Whether or not the end of the loop information should "
+ "be included in the CFG.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldIncludeRichConstructorsInCFG,
+ "cfg-rich-constructors",
+ "Whether or not construction site information should be "
+ "included in the CFG C++ constructor elements.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldIncludeScopesInCFG, "cfg-scopes",
+ "Whether or not scope information should be included in the CFG.", false)
+
+ANALYZER_OPTION(
+ bool, MayInlineTemplateFunctions, "c++-template-inlining",
+ "Whether or not templated functions may be considered for inlining.", true)
+
+ANALYZER_OPTION(bool, MayInlineCXXStandardLibrary, "c++-stdlib-inlining",
+ "Whether or not C++ standard library functions may be "
+ "considered for inlining.",
+ true)
+
+ANALYZER_OPTION(bool, MayInlineCXXAllocator, "c++-allocator-inlining",
+ "Whether or not allocator call may be considered for inlining.",
+ true)
+
+ANALYZER_OPTION(
+ bool, MayInlineCXXSharedPtrDtor, "c++-shared_ptr-inlining",
+ "Whether or not the destructor of C++ 'shared_ptr' may be considered for "
+ "inlining. This covers std::shared_ptr, std::tr1::shared_ptr, and "
+ "boost::shared_ptr, and indeed any destructor named '~shared_ptr'.",
+ false)
+
+ANALYZER_OPTION(bool, MayInlineCXXTemporaryDtors, "c++-temp-dtor-inlining",
+ "Whether C++ temporary destructors should be inlined "
+ "during analysis. If temporary destructors are disabled "
+ "in the CFG via the 'cfg-temporary-dtors' option, "
+ "temporary destructors would not be inlined anyway.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldSuppressNullReturnPaths, "suppress-null-return-paths",
+ "Whether or not paths that go through null returns should be suppressed. "
+ "This is a heuristic for avoiding bug reports with paths that go through "
+ "inlined functions that are more defensive than their callers.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldAvoidSuppressingNullArgumentPaths,
+ "avoid-suppressing-null-argument-paths",
+ "Whether a bug report should not be suppressed if its path includes a call "
+ "with a null argument, even if that call has a null return. This option "
+ "has no effect when ShouldSuppressNullReturnPaths is false. This is a "
+ "counter-heuristic to avoid false negatives.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldSuppressInlinedDefensiveChecks,
+ "suppress-inlined-defensive-checks",
+ "Whether or not diagnostics containing inlined "
+ "defensive NULL checks should be suppressed.",
+ true)
+
+ANALYZER_OPTION(bool, MayInlineCXXContainerMethods, "c++-container-inlining",
+ "Whether or not methods of C++ container objects may be "
+ "considered for inlining.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldSuppressFromCXXStandardLibrary,
+ "suppress-c++-stdlib",
+ "Whether or not diagnostics reported within the C++ "
+ "standard library should be suppressed.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldCrosscheckWithZ3, "crosscheck-with-z3",
+ "Whether bug reports should be crosschecked with the Z3 "
+ "constraint manager backend.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldReportIssuesInMainSourceFile,
+ "report-in-main-source-file",
+ "Whether or not the diagnostic report should be always "
+ "reported in the main source file and not the headers.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldWriteStableReportFilename, "stable-report-filename",
+ "Whether or not the report filename should be random or not.",
+ false)
+
+ANALYZER_OPTION(
+ bool, ShouldSerializeStats, "serialize-stats",
+ "Whether the analyzer should serialize statistics to plist output. "
+ "Statistics would be serialized in JSON format inside the main dictionary "
+ "under the statistics key. Available only if compiled in assert mode or "
+ "with LLVM statistics explicitly enabled.",
+ false)
+
+ANALYZER_OPTION(bool, MayInlineObjCMethod, "objc-inlining",
+ "Whether ObjectiveC inlining is enabled, false otherwise.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldPrunePaths, "prune-paths",
+ "Whether irrelevant parts of a bug report path should "
+ "be pruned out of the final output.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldConditionalizeStaticInitializers,
+ "cfg-conditional-static-initializers",
+ "Whether 'static' initializers should be in conditional logic in the CFG.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldSynthesizeBodies, "faux-bodies",
+ "Whether the analyzer engine should synthesize fake "
+ "bodies for well-known functions.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldElideConstructors, "elide-constructors",
+ "Whether elidable C++ copy-constructors and move-constructors should be "
+ "actually elided during analysis. Both behaviors are allowed by the C++ "
+ "standard, and the analyzer, like CodeGen, defaults to eliding. Starting "
+ "with C++17 some elisions become mandatory, and in these cases the option "
+ "will be ignored.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldInlineLambdas, "inline-lambdas",
+ "Whether lambdas should be inlined. Otherwise a sink node will be "
+ "generated each time a LambdaExpr is visited.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldWidenLoops, "widen-loops",
+ "Whether the analysis should try to widen loops.", false)
+
+ANALYZER_OPTION(
+ bool, ShouldUnrollLoops, "unroll-loops",
+ "Whether the analysis should try to unroll loops with known bounds.", false)
+
+ANALYZER_OPTION(
+ bool, ShouldDisplayNotesAsEvents, "notes-as-events",
+ "Whether the bug reporter should transparently treat extra note diagnostic "
+ "pieces as event diagnostic pieces. Useful when the diagnostic consumer "
+ "doesn't support the extra note pieces.",
+ false)
+
+ANALYZER_OPTION(
+ bool, ShouldAggressivelySimplifyBinaryOperation,
+ "aggressive-binary-operation-simplification",
+ "Whether SValBuilder should rearrange comparisons and additive operations "
+ "of symbolic expressions which consist of a sum of a symbol and a concrete "
+ "integer into the format where symbols are on the left-hand side and the "
+ "integer is on the right. This is only done if both symbols and both "
+ "concrete integers are signed, greater than or equal to the quarter of the "
+ "minimum value of the type and less than or equal to the quarter of the "
+ "maximum value of that type. A + n <OP> B + m becomes A - B <OP> m - n, "
+ "where A and B symbolic, n and m are integers. <OP> is any of '==', '!=', "
+ "'<', '<=', '>', '>=', '+' or '-'. The rearrangement also happens with '-' "
+ "instead of '+' on either or both side and also if any or both integers "
+ "are missing.",
+ false)
+
+ANALYZER_OPTION(
+ bool, ShouldEagerlyAssume, "eagerly-assume",
+ "Whether we should eagerly assume evaluations of conditionals, thus, "
+ "bifurcating the path. This indicates how the engine should handle "
+ "expressions such as: 'x = (y != 0)'. When this is true then the "
+ "subexpression 'y != 0' will be eagerly assumed to be true or false, thus "
+ "evaluating it to the integers 0 or 1 respectively. The upside is that "
+ "this can increase analysis precision until we have a better way to lazily "
+ "evaluate such logic. The downside is that it eagerly bifurcates paths.",
+ true)
+
+ANALYZER_OPTION(
+ bool, IsNaiveCTUEnabled, "experimental-enable-naive-ctu-analysis",
+ "Whether naive cross translation unit analysis is enabled. This is an "
+ "experimental feature to inline functions from other translation units.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldDisplayMacroExpansions, "expand-macros",
+ "Whether macros related to the bugpath should be "
+ "expanded and included in the plist output.",
+ false)
+
+ANALYZER_OPTION(bool, DisplayCTUProgress, "display-ctu-progress",
+ "Whether to emit verbose output about "
+ "the analyzer's progress related to ctu.",
+ false)
+
+//===----------------------------------------------------------------------===//
+// Unsinged analyzer options.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(
+ unsigned, AlwaysInlineSize, "ipa-always-inline-size",
+ "The size of the functions (in basic blocks), which should be considered "
+ "to be small enough to always inline.",
+ 3)
+
+ANALYZER_OPTION(
+ unsigned, GraphTrimInterval, "graph-trim-interval",
+ "How often nodes in the ExplodedGraph should be recycled to save memory. "
+ "To disable node reclamation, set the option to 0.",
+ 1000)
+
+ANALYZER_OPTION(
+ unsigned, MinCFGSizeTreatFunctionsAsLarge,
+ "min-cfg-size-treat-functions-as-large",
+ "The number of basic blocks a function needs to have to be considered "
+ "large for the 'max-times-inline-large' config option.",
+ 14)
+
+ANALYZER_OPTION(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
+ "The maximum complexity of symbolic constraint.", 35)
+
+ANALYZER_OPTION(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
+ "The maximum times a large function could be inlined.", 32)
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ unsigned, MaxInlinableSize, "max-inlinable-size",
+ "The bound on the number of basic blocks in an inlined function.",
+ /* SHALLOW_VAL */ 4, /* DEEP_VAL */ 100)
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ unsigned, MaxNodesPerTopLevelFunction, "max-nodes",
+ "The maximum number of nodes the analyzer can generate while exploring a "
+ "top level function (for each exploded graph). 0 means no limit.",
+ /* SHALLOW_VAL */ 75000, /* DEEP_VAL */ 225000)
+
+ANALYZER_OPTION(
+ unsigned, RegionStoreSmallStructLimit, "region-store-small-struct-limit",
+ "The largest number of fields a struct can have and still be considered "
+ "small This is currently used to decide whether or not it is worth forcing "
+ "a LazyCompoundVal on bind. To disable all small-struct-dependent "
+ "behavior, set the option to 0.",
+ 2)
+
+//===----------------------------------------------------------------------===//
+// String analyzer options.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(StringRef, CTUDir, "ctu-dir",
+ "The directory containing the CTU related files.", "")
+
+ANALYZER_OPTION(StringRef, CTUIndexName, "ctu-index-name",
+ "the name of the file containing the CTU index of definitions.",
+ "externalDefMap.txt")
+
+ANALYZER_OPTION(
+ StringRef, ModelPath, "model-path",
+ "The analyzer can inline an alternative implementation written in C at the "
+ "call site if the called function's body is not available. This is a path "
+ "where to look for those alternative implementations (called models).",
+ "")
+
+ANALYZER_OPTION(
+ StringRef, CXXMemberInliningMode, "c++-inlining",
+ "Controls which C++ member functions will be considered for inlining. "
+ "Value: \"constructors\", \"destructors\", \"methods\".",
+ "destructors")
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ StringRef, IPAMode, "ipa",
+ "Controls the mode of inter-procedural analysis. Value: \"none\", "
+ "\"basic-inlining\", \"inlining\", \"dynamic\", \"dynamic-bifurcate\".",
+ /* SHALLOW_VAL */ "inlining", /* DEEP_VAL */ "dynamic-bifurcate")
+
+ANALYZER_OPTION(
+ StringRef, ExplorationStrategy, "exploration_strategy",
+ "Value: \"dfs\", \"bfs\", \"unexplored_first\", "
+ "\"unexplored_first_queue\", \"unexplored_first_location_queue\", "
+ "\"bfs_block_dfs_contents\".",
+ "unexplored_first_queue")
+
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+#undef ANALYZER_OPTION
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 7586f7e0835b..7745e459e19b 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include <string>
#include <utility>
#include <vector>
@@ -85,7 +86,7 @@ enum CXXInlineableMemberKind {
// Uninitialized = 0,
/// A dummy mode in which no C++ inlining is enabled.
- CIMK_None = 1,
+ CIMK_None,
/// Refers to regular member function and operator calls.
CIMK_MemberFunctions,
@@ -102,8 +103,6 @@ enum CXXInlineableMemberKind {
/// Describes the different modes of inter-procedural analysis.
enum IPAKind {
- IPAK_NotSet = 0,
-
/// Perform only intra-procedural analysis.
IPAK_None = 1,
@@ -121,6 +120,46 @@ enum IPAKind {
IPAK_DynamicDispatchBifurcate = 5
};
+enum class ExplorationStrategyKind {
+ DFS,
+ BFS,
+ UnexploredFirst,
+ UnexploredFirstQueue,
+ UnexploredFirstLocationQueue,
+ BFSBlockDFSContents,
+};
+
+/// Describes the kinds for high-level analyzer mode.
+enum UserModeKind {
+ /// Perform shallow but fast analyzes.
+ UMK_Shallow = 1,
+
+ /// Perform deep analyzes.
+ UMK_Deep = 2
+};
+
+/// Stores options for the analyzer from the command line.
+///
+/// Some options are frontend flags (e.g.: -analyzer-output), but some are
+/// analyzer configuration options, which are preceded by -analyzer-config
+/// (e.g.: -analyzer-config notes-as-events=true).
+///
+/// If you'd like to add a new frontend flag, add it to
+/// include/clang/Driver/CC1Options.td, add a new field to store the value of
+/// that flag in this class, and initialize it in
+/// lib/Frontend/CompilerInvocation.cpp.
+///
+/// If you'd like to add a new non-checker configuration, register it in
+/// include/clang/StaticAnalyzer/Core/AnalyzerOptions.def, and refer to the
+/// top of the file for documentation.
+///
+/// If you'd like to add a new checker option, call getChecker*Option()
+/// whenever.
+///
+/// Some of the options are controlled by raw frontend flags for no good reason,
+/// and should be eventually converted into -analyzer-config flags. New analyzer
+/// options should not be implemented as frontend flags. Frontend flags still
+/// make sense for things that do not affect the actual analysis.
class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
public:
using ConfigTable = llvm::StringMap<std::string>;
@@ -132,6 +171,7 @@ public:
std::vector<std::pair<std::string, bool>> CheckersControlList;
/// A key-value table of use-specified configuration values.
+ // TODO: This shouldn't be public.
ConfigTable Config;
AnalysisStores AnalysisStoreOpt = RegionStoreModel;
AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
@@ -140,6 +180,9 @@ public:
std::string AnalyzeSpecificFunction;
+ /// File path to which the exploded graph should be dumped.
+ std::string DumpExplodedGraphTo;
+
/// Store full compiler invocation for reproducible instructions in the
/// generated report.
std::string FullCompilerInvocation;
@@ -156,24 +199,16 @@ public:
unsigned ShowCheckerHelp : 1;
unsigned ShowEnabledCheckerList : 1;
+ unsigned ShowConfigOptionsList : 1;
+ unsigned ShouldEmitErrorsOnInvalidConfigValue : 1;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
- /// The flag regulates if we should eagerly assume evaluations of
- /// conditionals, thus, bifurcating the path.
- ///
- /// This flag indicates how the engine should handle expressions such as: 'x =
- /// (y != 0)'. When this flag is true then the subexpression 'y != 0' will be
- /// eagerly assumed to be true or false, thus evaluating it to the integers 0
- /// or 1 respectively. The upside is that this can increase analysis
- /// precision until we have a better way to lazily evaluate such logic. The
- /// downside is that it eagerly bifurcates paths.
unsigned eagerlyAssumeBinOpBifurcation : 1;
unsigned TrimGraph : 1;
unsigned visualizeExplodedGraphWithGraphViz : 1;
- unsigned visualizeExplodedGraphWithUbiGraph : 1;
unsigned UnoptimizedCFG : 1;
unsigned PrintStats : 1;
@@ -188,187 +223,51 @@ public:
/// The mode of function selection used during inlining.
AnalysisInliningMode InliningMode = NoRedundancy;
- enum class ExplorationStrategyKind {
- DFS,
- BFS,
- UnexploredFirst,
- UnexploredFirstQueue,
- BFSBlockDFSContents,
- NotSet
- };
-
-private:
- ExplorationStrategyKind ExplorationStrategy = ExplorationStrategyKind::NotSet;
-
- /// Describes the kinds for high-level analyzer mode.
- enum UserModeKind {
- UMK_NotSet = 0,
-
- /// Perform shallow but fast analyzes.
- UMK_Shallow = 1,
-
- /// Perform deep analyzes.
- UMK_Deep = 2
- };
-
- /// Controls the high-level analyzer mode, which influences the default
- /// settings for some of the lower-level config options (such as IPAMode).
- /// \sa getUserMode
- UserModeKind UserMode = UMK_NotSet;
-
- /// Controls the mode of inter-procedural analysis.
- IPAKind IPAMode = IPAK_NotSet;
-
- /// Controls which C++ member functions will be considered for inlining.
- CXXInlineableMemberKind CXXMemberInliningMode;
-
- /// \sa includeImplicitDtorsInCFG
- Optional<bool> IncludeImplicitDtorsInCFG;
-
- /// \sa includeTemporaryDtorsInCFG
- Optional<bool> IncludeTemporaryDtorsInCFG;
-
- /// \sa IncludeLifetimeInCFG
- Optional<bool> IncludeLifetimeInCFG;
-
- /// \sa IncludeLoopExitInCFG
- Optional<bool> IncludeLoopExitInCFG;
-
- /// \sa IncludeRichConstructorsInCFG
- Optional<bool> IncludeRichConstructorsInCFG;
-
- /// \sa mayInlineCXXStandardLibrary
- Optional<bool> InlineCXXStandardLibrary;
-
- /// \sa includeScopesInCFG
- Optional<bool> IncludeScopesInCFG;
-
- /// \sa mayInlineTemplateFunctions
- Optional<bool> InlineTemplateFunctions;
-
- /// \sa mayInlineCXXAllocator
- Optional<bool> InlineCXXAllocator;
-
- /// \sa mayInlineCXXContainerMethods
- Optional<bool> InlineCXXContainerMethods;
-
- /// \sa mayInlineCXXSharedPtrDtor
- Optional<bool> InlineCXXSharedPtrDtor;
-
- /// \sa mayInlineCXXTemporaryDtors
- Optional<bool> InlineCXXTemporaryDtors;
+ // Create a field for each -analyzer-config option.
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL) \
+ ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
- /// \sa mayInlineObjCMethod
- Optional<bool> ObjCInliningMode;
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
+ TYPE NAME;
- // Cache of the "ipa-always-inline-size" setting.
- // \sa getAlwaysInlineSize
- Optional<unsigned> AlwaysInlineSize;
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
- /// \sa shouldSuppressNullReturnPaths
- Optional<bool> SuppressNullReturnPaths;
+ // Create an array of all -analyzer-config command line options. Sort it in
+ // the constructor.
+ std::vector<StringRef> AnalyzerConfigCmdFlags = {
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL) \
+ ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
- // \sa getMaxInlinableSize
- Optional<unsigned> MaxInlinableSize;
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
+ CMDFLAG,
- /// \sa shouldAvoidSuppressingNullArgumentPaths
- Optional<bool> AvoidSuppressingNullArgumentPaths;
-
- /// \sa shouldSuppressInlinedDefensiveChecks
- Optional<bool> SuppressInlinedDefensiveChecks;
-
- /// \sa shouldSuppressFromCXXStandardLibrary
- Optional<bool> SuppressFromCXXStandardLibrary;
-
- /// \sa shouldCrosscheckWithZ3
- Optional<bool> CrosscheckWithZ3;
-
- /// \sa reportIssuesInMainSourceFile
- Optional<bool> ReportIssuesInMainSourceFile;
-
- /// \sa StableReportFilename
- Optional<bool> StableReportFilename;
-
- Optional<bool> SerializeStats;
-
- /// \sa getGraphTrimInterval
- Optional<unsigned> GraphTrimInterval;
-
- /// \sa getMaxSymbolComplexity
- Optional<unsigned> MaxSymbolComplexity;
-
- /// \sa getMaxTimesInlineLarge
- Optional<unsigned> MaxTimesInlineLarge;
-
- /// \sa getMinCFGSizeTreatFunctionsAsLarge
- Optional<unsigned> MinCFGSizeTreatFunctionsAsLarge;
-
- /// \sa getMaxNodesPerTopLevelFunction
- Optional<unsigned> MaxNodesPerTopLevelFunction;
-
- /// \sa shouldInlineLambdas
- Optional<bool> InlineLambdas;
-
- /// \sa shouldWidenLoops
- Optional<bool> WidenLoops;
-
- /// \sa shouldUnrollLoops
- Optional<bool> UnrollLoops;
-
- /// \sa shouldDisplayNotesAsEvents
- Optional<bool> DisplayNotesAsEvents;
-
- /// \sa shouldAggressivelySimplifyBinaryOperation
- Optional<bool> AggressiveBinaryOperationSimplification;
-
- /// \sa getCTUDir
- Optional<StringRef> CTUDir;
-
- /// \sa getCTUIndexName
- Optional<StringRef> CTUIndexName;
-
- /// \sa naiveCTUEnabled
- Optional<bool> NaiveCTU;
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+ };
- /// \sa shouldElideConstructors
- Optional<bool> ElideConstructors;
+ bool isUnknownAnalyzerConfig(StringRef Name) const {
+ assert(std::is_sorted(AnalyzerConfigCmdFlags.begin(),
+ AnalyzerConfigCmdFlags.end()));
- /// A helper function that retrieves option for a given full-qualified
- /// checker name.
- /// Options for checkers can be specified via 'analyzer-config' command-line
- /// option.
- /// Example:
- /// @code-analyzer-config unix.Malloc:OptionName=CheckerOptionValue @endcode
- /// or @code-analyzer-config unix:OptionName=GroupOptionValue @endcode
- /// for groups of checkers.
- /// @param [in] CheckerName Full-qualified checker name, like
- /// alpha.unix.StreamChecker.
- /// @param [in] OptionName Name of the option to get.
- /// @param [in] Default Default value if no option is specified.
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- /// @retval CheckerOptionValue An option for a checker if it was specified.
- /// @retval GroupOptionValue An option for group if it was specified and no
- /// checker-specific options were found. The closer group to checker,
- /// the more priority it has. For example, @c coregroup.subgroup has more
- /// priority than @c coregroup for @c coregroup.subgroup.CheckerName checker.
- /// @retval Default If nor checker option, nor group option was found.
- StringRef getCheckerOption(StringRef CheckerName, StringRef OptionName,
- StringRef Default,
- bool SearchInParents = false);
+ return !std::binary_search(AnalyzerConfigCmdFlags.begin(),
+ AnalyzerConfigCmdFlags.end(), Name);
+ }
-public:
AnalyzerOptions()
: DisableAllChecks(false), ShowCheckerHelp(false),
- ShowEnabledCheckerList(false), AnalyzeAll(false),
- AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false),
- eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
- visualizeExplodedGraphWithGraphViz(false),
- visualizeExplodedGraphWithUbiGraph(false), UnoptimizedCFG(false),
- PrintStats(false), NoRetryExhausted(false), CXXMemberInliningMode() {}
+ ShowEnabledCheckerList(false), ShowConfigOptionsList(false),
+ AnalyzeAll(false), AnalyzerDisplayProgress(false),
+ AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false),
+ TrimGraph(false), visualizeExplodedGraphWithGraphViz(false),
+ UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false) {
+ llvm::sort(AnalyzerConfigCmdFlags);
+ }
/// Interprets an option's string value as a boolean. The "true" string is
/// interpreted as true and the "false" string is interpreted as false.
@@ -377,34 +276,17 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- bool getBooleanOption(StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ bool getCheckerBooleanOption(StringRef Name, bool DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
- /// Variant that accepts a Optional value to cache the result.
- ///
- /// @param [in,out] V Return value storage, returned if parameter contains
- /// an existing valid option, else it is used to store a return value
- /// @param [in] Name Name for option to retrieve.
- /// @param [in] DefaultVal Default value returned if no such option was
- /// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- bool getBooleanOption(Optional<bool> &V, StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
/// Interprets an option's string value as an integer value.
///
@@ -412,16 +294,16 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- int getOptionAsInteger(StringRef Name, int DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ int getCheckerIntegerOption(StringRef Name, int DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
/// Query an option's string value.
///
@@ -429,26 +311,26 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- StringRef getOptionAsString(StringRef Name, StringRef DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ StringRef getCheckerStringOption(StringRef Name, StringRef DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
/// Retrieves and sets the UserMode. This is a high-level option,
/// which is used to set other low-level options. It is not accessible
/// outside of AnalyzerOptions.
- UserModeKind getUserMode();
+ UserModeKind getUserMode() const;
- ExplorationStrategyKind getExplorationStrategy();
+ ExplorationStrategyKind getExplorationStrategy() const;
/// Returns the inter-procedural analysis mode.
- IPAKind getIPAMode();
+ IPAKind getIPAMode() const;
/// Returns the option controlling which C++ member functions will be
/// considered for inlining.
@@ -456,275 +338,28 @@ public:
/// This is controlled by the 'c++-inlining' config option.
///
/// \sa CXXMemberInliningMode
- bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
-
- /// Returns true if ObjectiveC inlining is enabled, false otherwise.
- bool mayInlineObjCMethod();
-
- /// Returns whether or not the destructors for C++ temporary objects should
- /// be included in the CFG.
- ///
- /// This is controlled by the 'cfg-temporary-dtors' config option, which
- /// accepts the values "true" and "false".
- bool includeTemporaryDtorsInCFG();
-
- /// Returns whether or not implicit destructors for C++ objects should
- /// be included in the CFG.
- ///
- /// This is controlled by the 'cfg-implicit-dtors' config option, which
- /// accepts the values "true" and "false".
- bool includeImplicitDtorsInCFG();
-
- /// Returns whether or not end-of-lifetime information should be included in
- /// the CFG.
- ///
- /// This is controlled by the 'cfg-lifetime' config option, which accepts
- /// the values "true" and "false".
- bool includeLifetimeInCFG();
-
- /// Returns whether or not the end of the loop information should be included
- /// in the CFG.
- ///
- /// This is controlled by the 'cfg-loopexit' config option, which accepts
- /// the values "true" and "false".
- bool includeLoopExitInCFG();
-
- /// Returns whether or not construction site information should be included
- /// in the CFG C++ constructor elements.
- ///
- /// This is controlled by the 'cfg-rich-constructors' config options,
- /// which accepts the values "true" and "false".
- bool includeRichConstructorsInCFG();
-
- /// Returns whether or not scope information should be included in the CFG.
- ///
- /// This is controlled by the 'cfg-scope-info' config option, which accepts
- /// the values "true" and "false".
- bool includeScopesInCFG();
-
- /// Returns whether or not C++ standard library functions may be considered
- /// for inlining.
- ///
- /// This is controlled by the 'c++-stdlib-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXStandardLibrary();
-
- /// Returns whether or not templated functions may be considered for inlining.
- ///
- /// This is controlled by the 'c++-template-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineTemplateFunctions();
-
- /// Returns whether or not allocator call may be considered for inlining.
- ///
- /// This is controlled by the 'c++-allocator-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXAllocator();
-
- /// Returns whether or not methods of C++ container objects may be considered
- /// for inlining.
- ///
- /// This is controlled by the 'c++-container-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXContainerMethods();
-
- /// Returns whether or not the destructor of C++ 'shared_ptr' may be
- /// considered for inlining.
- ///
- /// This covers std::shared_ptr, std::tr1::shared_ptr, and boost::shared_ptr,
- /// and indeed any destructor named "~shared_ptr".
- ///
- /// This is controlled by the 'c++-shared_ptr-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXSharedPtrDtor();
-
- /// Returns true if C++ temporary destructors should be inlined during
- /// analysis.
- ///
- /// If temporary destructors are disabled in the CFG via the
- /// 'cfg-temporary-dtors' option, temporary destructors would not be
- /// inlined anyway.
- ///
- /// This is controlled by the 'c++-temp-dtor-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXTemporaryDtors();
-
- /// Returns whether or not paths that go through null returns should be
- /// suppressed.
- ///
- /// This is a heuristic for avoiding bug reports with paths that go through
- /// inlined functions that are more defensive than their callers.
- ///
- /// This is controlled by the 'suppress-null-return-paths' config option,
- /// which accepts the values "true" and "false".
- bool shouldSuppressNullReturnPaths();
-
- /// Returns whether a bug report should \em not be suppressed if its path
- /// includes a call with a null argument, even if that call has a null return.
- ///
- /// This option has no effect when #shouldSuppressNullReturnPaths() is false.
- ///
- /// This is a counter-heuristic to avoid false negatives.
- ///
- /// This is controlled by the 'avoid-suppressing-null-argument-paths' config
- /// option, which accepts the values "true" and "false".
- bool shouldAvoidSuppressingNullArgumentPaths();
-
- /// Returns whether or not diagnostics containing inlined defensive NULL
- /// checks should be suppressed.
- ///
- /// This is controlled by the 'suppress-inlined-defensive-checks' config
- /// option, which accepts the values "true" and "false".
- bool shouldSuppressInlinedDefensiveChecks();
-
- /// Returns whether or not diagnostics reported within the C++ standard
- /// library should be suppressed.
- ///
- /// This is controlled by the 'suppress-c++-stdlib' config option,
- /// which accepts the values "true" and "false".
- bool shouldSuppressFromCXXStandardLibrary();
-
- /// Returns whether bug reports should be crosschecked with the Z3
- /// constraint manager backend.
- ///
- /// This is controlled by the 'crosscheck-with-z3' config option,
- /// which accepts the values "true" and "false".
- bool shouldCrosscheckWithZ3();
-
- /// Returns whether or not the diagnostic report should be always reported
- /// in the main source file and not the headers.
- ///
- /// This is controlled by the 'report-in-main-source-file' config option,
- /// which accepts the values "true" and "false".
- bool shouldReportIssuesInMainSourceFile();
-
- /// Returns whether or not the report filename should be random or not.
- ///
- /// This is controlled by the 'stable-report-filename' config option,
- /// which accepts the values "true" and "false". Default = false
- bool shouldWriteStableReportFilename();
-
- /// \return Whether the analyzer should
- /// serialize statistics to plist output.
- /// Statistics would be serialized in JSON format inside the main dictionary
- /// under the \c statistics key.
- /// Available only if compiled in assert mode or with LLVM statistics
- /// explicitly enabled.
- bool shouldSerializeStats();
-
- /// Returns whether irrelevant parts of a bug report path should be pruned
- /// out of the final output.
- ///
- /// This is controlled by the 'prune-paths' config option, which accepts the
- /// values "true" and "false".
- bool shouldPrunePaths();
-
- /// Returns true if 'static' initializers should be in conditional logic
- /// in the CFG.
- bool shouldConditionalizeStaticInitializers();
-
- // Returns the size of the functions (in basic blocks), which should be
- // considered to be small enough to always inline.
- //
- // This is controlled by "ipa-always-inline-size" analyzer-config option.
- unsigned getAlwaysInlineSize();
-
- // Returns the bound on the number of basic blocks in an inlined function
- // (50 by default).
- //
- // This is controlled by "-analyzer-config max-inlinable-size" option.
- unsigned getMaxInlinableSize();
-
- /// Returns true if the analyzer engine should synthesize fake bodies
- /// for well-known functions.
- bool shouldSynthesizeBodies();
-
- /// Returns how often nodes in the ExplodedGraph should be recycled to save
- /// memory.
- ///
- /// This is controlled by the 'graph-trim-interval' config option. To disable
- /// node reclamation, set the option to "0".
- unsigned getGraphTrimInterval();
-
- /// Returns the maximum complexity of symbolic constraint (50 by default).
- ///
- /// This is controlled by "-analyzer-config max-symbol-complexity" option.
- unsigned getMaxSymbolComplexity();
-
- /// Returns the maximum times a large function could be inlined.
- ///
- /// This is controlled by the 'max-times-inline-large' config option.
- unsigned getMaxTimesInlineLarge();
-
- /// Returns the number of basic blocks a function needs to have to be
- /// considered large for the 'max-times-inline-large' config option.
- ///
- /// This is controlled by the 'min-cfg-size-treat-functions-as-large' config
- /// option.
- unsigned getMinCFGSizeTreatFunctionsAsLarge();
-
- /// Returns the maximum number of nodes the analyzer can generate while
- /// exploring a top level function (for each exploded graph).
- /// 150000 is default; 0 means no limit.
- ///
- /// This is controlled by the 'max-nodes' config option.
- unsigned getMaxNodesPerTopLevelFunction();
-
- /// Returns true if lambdas should be inlined. Otherwise a sink node will be
- /// generated each time a LambdaExpr is visited.
- bool shouldInlineLambdas();
-
- /// Returns true if the analysis should try to widen loops.
- /// This is controlled by the 'widen-loops' config option.
- bool shouldWidenLoops();
-
- /// Returns true if the analysis should try to unroll loops with known bounds.
- /// This is controlled by the 'unroll-loops' config option.
- bool shouldUnrollLoops();
-
- /// Returns true if the bug reporter should transparently treat extra note
- /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic
- /// consumer doesn't support the extra note pieces.
- ///
- /// This is controlled by the 'extra-notes-as-events' option, which defaults
- /// to false when unset.
- bool shouldDisplayNotesAsEvents();
-
- /// Returns true if SValBuilder should rearrange comparisons and additive
- /// operations of symbolic expressions which consist of a sum of a symbol and
- /// a concrete integer into the format where symbols are on the left-hand
- /// side and the integer is on the right. This is only done if both symbols
- /// and both concrete integers are signed, greater than or equal to the
- /// quarter of the minimum value of the type and less than or equal to the
- /// quarter of the maximum value of that type.
- ///
- /// A + n <OP> B + m becomes A - B <OP> m - n, where A and B symbolic,
- /// n and m are integers. <OP> is any of '==', '!=', '<', '<=', '>', '>=',
- /// '+' or '-'. The rearrangement also happens with '-' instead of '+' on
- // either or both side and also if any or both integers are missing.
- bool shouldAggressivelySimplifyBinaryOperation();
-
- /// Returns the directory containing the CTU related files.
- StringRef getCTUDir();
-
- /// Returns the name of the file containing the CTU index of functions.
- StringRef getCTUIndexName();
-
- /// Returns true when naive cross translation unit analysis is enabled.
- /// This is an experimental feature to inline functions from another
- /// translation units.
- bool naiveCTUEnabled();
-
- /// Returns true if elidable C++ copy-constructors and move-constructors
- /// should be actually elided during analysis. Both behaviors are allowed
- /// by the C++ standard, and the analyzer, like CodeGen, defaults to eliding.
- /// Starting with C++17 some elisions become mandatory, and in these cases
- /// the option will be ignored.
- bool shouldElideConstructors();
+ bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
};
using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
+//===----------------------------------------------------------------------===//
+// We'll use AnalyzerOptions in the frontend, but we can't link the frontend
+// with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on
+// clangFrontend.
+//
+// For this reason, implement some methods in this header file.
+//===----------------------------------------------------------------------===//
+
+inline UserModeKind AnalyzerOptions::getUserMode() const {
+ auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(UserMode)
+ .Case("shallow", UMK_Shallow)
+ .Case("deep", UMK_Deep)
+ .Default(None);
+ assert(K.hasValue() && "User mode is invalid.");
+ return K.getValue();
+}
+
} // namespace clang
#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index da019f83c214..c023ed5641a3 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -58,7 +58,7 @@ public:
/// The last parameter can be used to register a new visitor with the given
/// BugReport while processing a node.
virtual std::shared_ptr<PathDiagnosticPiece>
- VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred,
+ VisitNode(const ExplodedNode *Succ,
BugReporterContext &BRC, BugReport &BR) = 0;
/// Last function called on the visitor, no further calls to VisitNode
@@ -83,6 +83,8 @@ public:
BugReport &BR);
};
+/// Finds last store into the given region,
+/// which is different from a given symbolic value.
class FindLastStoreBRVisitor final : public BugReporterVisitor {
const MemRegion *R;
SVal V;
@@ -105,7 +107,6 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -132,7 +133,6 @@ public:
static const char *getTag();
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -151,7 +151,6 @@ public:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -177,12 +176,10 @@ public:
static const char *getTag();
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
BugReporterContext &BRC,
BugReport &BR) override;
std::shared_ptr<PathDiagnosticPiece> VisitNodeImpl(const ExplodedNode *N,
- const ExplodedNode *Prev,
BugReporterContext &BRC,
BugReport &BR);
@@ -235,10 +232,9 @@ public:
ID.AddPointer(getTag());
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR) override {
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *,
+ BugReporterContext &,
+ BugReport &) override {
return nullptr;
}
@@ -265,7 +261,6 @@ public:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -295,7 +290,6 @@ public:
static const char *getTag();
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -309,7 +303,6 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override {}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -325,7 +318,6 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); }
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -344,7 +336,6 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -354,30 +345,22 @@ public:
namespace bugreporter {
-/// Attempts to add visitors to trace a null or undefined value back to its
-/// point of origin, whether it is a symbol constrained to null or an explicit
-/// assignment.
+/// Attempts to add visitors to track expression value back to its point of
+/// origin.
///
/// \param N A node "downstream" from the evaluation of the statement.
-/// \param S The statement whose value is null or undefined.
+/// \param E The expression value which we are tracking
/// \param R The bug report to which visitors should be attached.
-/// \param IsArg Whether the statement is an argument to an inlined function.
-/// If this is the case, \p N \em must be the CallEnter node for
-/// the function.
/// \param EnableNullFPSuppression Whether we should employ false positive
/// suppression (inlined defensive checks, returned null).
///
/// \return Whether or not the function was able to add visitors for this
/// statement. Note that returning \c true does not actually imply
/// that any visitors were added.
-bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R,
- bool IsArg = false,
- bool EnableNullFPSuppression = true);
+bool trackExpressionValue(const ExplodedNode *N, const Expr *E, BugReport &R,
+ bool EnableNullFPSuppression = true);
const Expr *getDerefExpr(const Stmt *S);
-const Stmt *GetDenomExpr(const ExplodedNode *N);
-const Stmt *GetRetValExpr(const ExplodedNode *N);
-bool isDeclRefExprToReference(const Expr *E);
} // namespace bugreporter
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 3c1f8f718a3b..727ec7c66a89 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -65,8 +65,6 @@ public:
/// by a sink node.
bool isSuppressOnSink() const { return SuppressOnSink; }
void setSuppressOnSink(bool x) { SuppressOnSink = x; }
-
- virtual void FlushReports(BugReporter& BR);
};
class BuiltinBug : public BugType {
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
index 0e80e7bc19ba..d07525661a6c 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
@@ -16,7 +16,7 @@ namespace clang {
namespace categories {
extern const char * const CoreFoundationObjectiveC;
extern const char * const LogicError;
- extern const char * const MemoryCoreFoundationObjectiveC;
+ extern const char * const MemoryRefCount;
extern const char * const MemoryError;
extern const char * const UnixAPI;
}
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index b0bb12feba20..e9c682d7986c 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -118,7 +118,7 @@ public:
/// Only runs visitors, no output generated.
None,
- /// Used for HTML and text output.
+ /// Used for HTML, SARIF, and text output.
Minimal,
/// Used for plist output, used for "arrows" generation.
@@ -178,10 +178,9 @@ public:
PathDiagnosticLocation() = default;
/// Create a location corresponding to the given statement.
- PathDiagnosticLocation(const Stmt *s,
- const SourceManager &sm,
+ PathDiagnosticLocation(const Stmt *s, const SourceManager &sm,
LocationOrAnalysisDeclContext lac)
- : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
+ : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
S(K == StmtK ? s : nullptr), SM(&sm),
Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) {
assert(K == SingleLocK || S);
@@ -633,7 +632,7 @@ public:
}
static std::shared_ptr<PathDiagnosticCallPiece>
- construct(const ExplodedNode *N, const CallExitEnd &CE,
+ construct(const CallExitEnd &CE,
const SourceManager &SM);
static PathDiagnosticCallPiece *construct(PathPieces &pieces,
@@ -760,7 +759,7 @@ public:
};
/// File IDs mapped to sets of line numbers.
-using FilesToLineNumsMap = std::map<unsigned, std::set<unsigned>>;
+using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>;
/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
@@ -859,13 +858,13 @@ public:
meta_iterator meta_end() const { return OtherDesc.end(); }
void addMeta(StringRef s) { OtherDesc.push_back(s); }
- using filesmap_iterator = FilesToLineNumsMap::const_iterator;
-
- filesmap_iterator executedLines_begin() const {
- return ExecutedLines->begin();
+ const FilesToLineNumsMap &getExecutedLines() const {
+ return *ExecutedLines;
}
- filesmap_iterator executedLines_end() const { return ExecutedLines->end(); }
+ FilesToLineNumsMap &getExecutedLines() {
+ return *ExecutedLines;
+ }
PathDiagnosticLocation getLocation() const {
return Loc;
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index 8484cfe4c956..786465cee855 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -558,6 +558,8 @@ struct ImplicitNullDerefEvent {
// dereference might happen later (for example pointer passed to a parameter
// that is marked with nonnull attribute.)
bool IsDirectDereference;
+
+ static int Tag;
};
/// A helper class which wraps a boolean value set to false by default.
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 7c353326be46..538ed19f7eef 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -115,13 +115,14 @@ enum class ObjCMessageVisitKind {
};
class CheckerManager {
+ ASTContext &Context;
const LangOptions LangOpts;
AnalyzerOptions &AOptions;
CheckName CurrentCheckName;
public:
- CheckerManager(const LangOptions &langOpts, AnalyzerOptions &AOptions)
- : LangOpts(langOpts), AOptions(AOptions) {}
+ CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions)
+ : Context(Context), LangOpts(Context.getLangOpts()), AOptions(AOptions) {}
~CheckerManager();
@@ -134,6 +135,7 @@ public:
const LangOptions &getLangOpts() const { return LangOpts; }
AnalyzerOptions &getAnalyzerOptions() { return AOptions; }
+ ASTContext &getASTContext() { return Context; }
using CheckerRef = CheckerBase *;
using CheckerTag = const void *;
@@ -149,13 +151,13 @@ public:
///
/// \returns a pointer to the checker object.
template <typename CHECKER, typename... AT>
- CHECKER *registerChecker(AT... Args) {
+ CHECKER *registerChecker(AT &&... Args) {
CheckerTag tag = getTag<CHECKER>();
CheckerRef &ref = CheckerTags[tag];
if (ref)
return static_cast<CHECKER *>(ref); // already registered.
- CHECKER *checker = new CHECKER(Args...);
+ CHECKER *checker = new CHECKER(std::forward<AT>(Args)...);
checker->Name = CurrentCheckName;
CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
CHECKER::_register(checker, *this);
@@ -530,19 +532,19 @@ public:
template <typename EVENT>
void _registerListenerForEvent(CheckEventFunc checkfn) {
- EventInfo &info = Events[getTag<EVENT>()];
+ EventInfo &info = Events[&EVENT::Tag];
info.Checkers.push_back(checkfn);
}
template <typename EVENT>
void _registerDispatcherForEvent() {
- EventInfo &info = Events[getTag<EVENT>()];
+ EventInfo &info = Events[&EVENT::Tag];
info.HasDispatcher = true;
}
template <typename EVENT>
void _dispatchEvent(const EVENT &event) const {
- EventsTy::const_iterator I = Events.find(getTag<EVENT>());
+ EventsTy::const_iterator I = Events.find(&EVENT::Tag);
if (I == Events.end())
return;
const EventInfo &info = I->second;
diff --git a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h b/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
deleted file mode 100644
index 2d13bf34cd15..000000000000
--- a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===--- CheckerOptInfo.h - Specifies which checkers to use -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H
-#define LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace clang {
-namespace ento {
-
-/// Represents a request to include or exclude a checker or package from a
-/// specific analysis run.
-///
-/// \sa CheckerRegistry::initializeManager
-class CheckerOptInfo {
- StringRef Name;
- bool Enable;
- bool Claimed;
-
-public:
- CheckerOptInfo(StringRef name, bool enable)
- : Name(name), Enable(enable), Claimed(false) { }
-
- StringRef getName() const { return Name; }
- bool isEnabled() const { return Enable; }
- bool isDisabled() const { return !isEnabled(); }
-
- bool isClaimed() const { return Claimed; }
- bool isUnclaimed() const { return !isClaimed(); }
- void claim() { Claimed = true; }
-};
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 85369509efcd..50b9b566edc3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -46,14 +46,12 @@ class AnalysisManager : public BugReporterData {
public:
AnalyzerOptions &options;
- AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,
- const LangOptions &lang,
+ AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
const PathDiagnosticConsumers &Consumers,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
- CheckerManager *checkerMgr,
- AnalyzerOptions &Options,
- CodeInjector* injector = nullptr);
+ CheckerManager *checkerMgr, AnalyzerOptions &Options,
+ CodeInjector *injector = nullptr);
~AnalysisManager() override;
@@ -102,8 +100,7 @@ public:
void FlushDiagnostics();
bool shouldVisualize() const {
- return options.visualizeExplodedGraphWithGraphViz ||
- options.visualizeExplodedGraphWithUbiGraph;
+ return options.visualizeExplodedGraphWithGraphViz;
}
bool shouldInlineCall() const {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index b72b158194c7..1c5d4eb2de32 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -211,7 +211,8 @@ public:
}
const llvm::APSInt &getTruthValue(bool b, QualType T) {
- return getValue(b ? 1 : 0, Ctx.getIntWidth(T), true);
+ return getValue(b ? 1 : 0, Ctx.getIntWidth(T),
+ T->isUnsignedIntegerOrEnumerationType());
}
const llvm::APSInt &getTruthValue(bool b) {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 9078fb94d282..81dd83fc1071 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -80,7 +80,9 @@ class CallDescription {
mutable IdentifierInfo *II = nullptr;
mutable bool IsLookupDone = false;
- StringRef FuncName;
+ // The list of the qualified names used to identify the specified CallEvent,
+ // e.g. "{a, b}" represent the qualified names, like "a::b".
+ std::vector<const char *> QualifiedName;
unsigned RequiredArgs;
public:
@@ -88,16 +90,20 @@ public:
/// Constructs a CallDescription object.
///
- /// @param FuncName The name of the function that will be matched.
+ /// @param QualifiedName The list of the name qualifiers of the function that
+ /// will be matched. The user is allowed to skip any of the qualifiers.
+ /// For example, {"std", "basic_string", "c_str"} would match both
+ /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str().
///
/// @param RequiredArgs The number of arguments that is expected to match a
/// call. Omit this parameter to match every occurrence of call with a given
/// name regardless the number of arguments.
- CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement)
- : FuncName(FuncName), RequiredArgs(RequiredArgs) {}
+ CallDescription(ArrayRef<const char *> QualifiedName,
+ unsigned RequiredArgs = NoArgRequirement)
+ : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {}
/// Get the name of the function that this object matches.
- StringRef getFunctionName() const { return FuncName; }
+ StringRef getFunctionName() const { return QualifiedName.back(); }
};
template<typename T = CallEvent>
@@ -428,21 +434,23 @@ public:
bool isArgumentConstructedDirectly(unsigned Index) const {
// This assumes that the object was not yet removed from the state.
return ExprEngine::getObjectUnderConstruction(
- getState(), {getOriginExpr(), Index}, getCalleeStackFrame()).hasValue();
+ getState(), {getOriginExpr(), Index}, getLocationContext()).hasValue();
}
/// Some calls have parameter numbering mismatched from argument numbering.
/// This function converts an argument index to the corresponding
/// parameter index. Returns None is the argument doesn't correspond
/// to any parameter variable.
- Optional<unsigned> getAdjustedParameterIndex(unsigned ArgumentIndex) const {
- if (dyn_cast_or_null<CXXOperatorCallExpr>(getOriginExpr()) &&
- dyn_cast_or_null<CXXMethodDecl>(getDecl())) {
- // For member operator calls argument 0 on the expression corresponds
- // to implicit this-parameter on the declaration.
- return (ArgumentIndex > 0) ? Optional<unsigned>(ArgumentIndex - 1) : None;
- }
- return ArgumentIndex;
+ virtual Optional<unsigned>
+ getAdjustedParameterIndex(unsigned ASTArgumentIndex) const {
+ return ASTArgumentIndex;
+ }
+
+ /// Some call event sub-classes conveniently adjust mismatching AST indices
+ /// to match parameter indices. This function converts an argument index
+ /// as understood by CallEvent to the argument index as understood by the AST.
+ virtual unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const {
+ return CallArgumentIndex;
}
// Iterator access to formal parameters and their types.
@@ -769,6 +777,20 @@ public:
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_CXXMemberOperator;
}
+
+ Optional<unsigned>
+ getAdjustedParameterIndex(unsigned ASTArgumentIndex) const override {
+ // For member operator calls argument 0 on the expression corresponds
+ // to implicit this-parameter on the declaration.
+ return (ASTArgumentIndex > 0) ? Optional<unsigned>(ASTArgumentIndex - 1)
+ : None;
+ }
+
+ unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const override {
+ // For member operator calls argument 0 on the expression corresponds
+ // to implicit this-parameter on the declaration.
+ return CallArgumentIndex + 1;
+ }
};
/// Represents an implicit call to a C++ destructor.
@@ -793,7 +815,7 @@ protected:
ProgramStateRef St, const LocationContext *LCtx)
: CXXInstanceCall(DD, St, LCtx) {
Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue();
- Location = Trigger->getLocEnd();
+ Location = Trigger->getEndLoc();
}
CXXDestructorCall(const CXXDestructorCall &Other) = default;
@@ -899,15 +921,30 @@ public:
return getOriginExpr()->getOperatorNew();
}
+ /// Number of non-placement arguments to the call. It is equal to 2 for
+ /// C++17 aligned operator new() calls that have alignment implicitly
+ /// passed as the second argument, and to 1 for other operator new() calls.
+ unsigned getNumImplicitArgs() const {
+ return getOriginExpr()->passAlignment() ? 2 : 1;
+ }
+
unsigned getNumArgs() const override {
- return getOriginExpr()->getNumPlacementArgs() + 1;
+ return getOriginExpr()->getNumPlacementArgs() + getNumImplicitArgs();
}
const Expr *getArgExpr(unsigned Index) const override {
// The first argument of an allocator call is the size of the allocation.
- if (Index == 0)
+ if (Index < getNumImplicitArgs())
return nullptr;
- return getOriginExpr()->getPlacementArg(Index - 1);
+ return getOriginExpr()->getPlacementArg(Index - getNumImplicitArgs());
+ }
+
+ /// Number of placement arguments to the operator new() call. For example,
+ /// standard std::nothrow operator new and standard placement new both have
+ /// 1 implicit argument (size) and 1 placement argument, while regular
+ /// operator new() has 1 implicit argument and 0 placement arguments.
+ const Expr *getPlacementArgExpr(unsigned Index) const {
+ return getOriginExpr()->getPlacementArg(Index);
}
Kind getKind() const override { return CE_CXXAllocator; }
@@ -1101,9 +1138,16 @@ class CallEventManager {
public:
CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {}
+ /// Gets an outside caller given a callee context.
CallEventRef<>
getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State);
+ /// Gets a call event for a function call, Objective-C method call,
+ /// or a 'new' call.
+ CallEventRef<>
+ getCall(const Stmt *S, ProgramStateRef State,
+ const LocationContext *LC);
+
CallEventRef<>
getSimpleCall(const CallExpr *E, ProgramStateRef State,
const LocationContext *LCtx);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index ce2b711a4a1b..6ee75b738465 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -21,52 +21,6 @@
namespace clang {
namespace ento {
- /// Declares an immutable map of type \p NameTy, suitable for placement into
- /// the ProgramState. This is implementing using llvm::ImmutableMap.
- ///
- /// \code
- /// State = State->set<Name>(K, V);
- /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map.
- /// State = State->remove<Name>(K);
- /// NameTy Map = State->get<Name>();
- /// \endcode
- ///
- /// The macro should not be used inside namespaces, or for traits that must
- /// be accessible from more than one translation unit.
- #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \
- REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \
- CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value))
-
- /// Declares an immutable set of type \p NameTy, suitable for placement into
- /// the ProgramState. This is implementing using llvm::ImmutableSet.
- ///
- /// \code
- /// State = State->add<Name>(E);
- /// State = State->remove<Name>(E);
- /// bool Present = State->contains<Name>(E);
- /// NameTy Set = State->get<Name>();
- /// \endcode
- ///
- /// The macro should not be used inside namespaces, or for traits that must
- /// be accessible from more than one translation unit.
- #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \
- REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>)
-
- /// Declares an immutable list of type \p NameTy, suitable for placement into
- /// the ProgramState. This is implementing using llvm::ImmutableList.
- ///
- /// \code
- /// State = State->add<Name>(E); // Adds to the /end/ of the list.
- /// bool Present = State->contains<Name>(E);
- /// NameTy List = State->get<Name>();
- /// \endcode
- ///
- /// The macro should not be used inside namespaces, or for traits that must
- /// be accessible from more than one translation unit.
- #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \
- REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>)
-
-
class CheckerContext {
ExprEngine &Eng;
/// The current exploded(symbolic execution) graph node.
@@ -162,10 +116,6 @@ public:
return getSValBuilder().getSymbolManager();
}
- bool isObjCGCEnabled() const {
- return Eng.isObjCGCEnabled();
- }
-
ProgramStateManager &getStateManager() {
return Eng.getStateManager();
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
index 2f8ead0746ca..b0d514dc2863 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
@@ -36,10 +36,7 @@ using DynamicTypeMapImpl =
template <>
struct ProgramStateTrait<DynamicTypeMap>
: public ProgramStatePartialTrait<DynamicTypeMapImpl> {
- static void *GDMIndex() {
- static int index = 0;
- return &index;
- }
+ static void *GDMIndex();
};
/// Get dynamic type information for a region.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index 77e35398077c..6d498031bea0 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -93,6 +93,7 @@ public:
}
void print(raw_ostream &Out, const char *NL, const char *Sep,
+ const ASTContext &Context,
const LocationContext *WithLC = nullptr) const;
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 4e0c02e6d65b..bf460df278aa 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -210,10 +210,14 @@ public:
return const_cast<ExplodedNode*>(this)->getFirstPred();
}
- const ExplodedNode *getFirstSucc() const {
+ ExplodedNode *getFirstSucc() {
return succ_empty() ? nullptr : *(succ_begin());
}
+ const ExplodedNode *getFirstSucc() const {
+ return const_cast<ExplodedNode*>(this)->getFirstSucc();
+ }
+
// Iterators over successor and predecessor vertices.
using succ_iterator = ExplodedNode * const *;
using const_succ_iterator = const ExplodedNode * const *;
@@ -240,17 +244,14 @@ public:
return const_cast<ExplodedNode*>(this)->succ_end();
}
- // For debugging.
-
-public:
- class Auditor {
- public:
- virtual ~Auditor();
-
- virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
- };
+ int64_t getID(ExplodedGraph *G) const;
- static void SetAuditor(Auditor* A);
+ /// The node is trivial if it has only one successor, only one predecessor,
+ /// it's predecessor has only one successor,
+ /// and its program state is the same as the program state of the previous
+ /// node.
+ /// Trivial nodes may be skipped while printing exploded graph.
+ bool isTrivial() const;
private:
void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
@@ -465,39 +466,40 @@ public:
// GraphTraits
namespace llvm {
-
- template<> struct GraphTraits<clang::ento::ExplodedNode*> {
+ template <> struct GraphTraits<clang::ento::ExplodedGraph *> {
+ using GraphTy = clang::ento::ExplodedGraph *;
using NodeRef = clang::ento::ExplodedNode *;
using ChildIteratorType = clang::ento::ExplodedNode::succ_iterator;
- using nodes_iterator = llvm::df_iterator<NodeRef>;
-
- static NodeRef getEntryNode(NodeRef N) { return N; }
-
- static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
+ using nodes_iterator = llvm::df_iterator<GraphTy>;
- static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
-
- static nodes_iterator nodes_begin(NodeRef N) { return df_begin(N); }
-
- static nodes_iterator nodes_end(NodeRef N) { return df_end(N); }
- };
-
- template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
- using NodeRef = const clang::ento::ExplodedNode *;
- using ChildIteratorType = clang::ento::ExplodedNode::const_succ_iterator;
- using nodes_iterator = llvm::df_iterator<NodeRef>;
+ static NodeRef getEntryNode(const GraphTy G) {
+ return *G->roots_begin();
+ }
- static NodeRef getEntryNode(NodeRef N) { return N; }
+ static bool predecessorOfTrivial(NodeRef N) {
+ return N->succ_size() == 1 && N->getFirstSucc()->isTrivial();
+ }
- static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
+ static ChildIteratorType child_begin(NodeRef N) {
+ if (predecessorOfTrivial(N))
+ return child_begin(*N->succ_begin());
+ return N->succ_begin();
+ }
- static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
+ static ChildIteratorType child_end(NodeRef N) {
+ if (predecessorOfTrivial(N))
+ return child_end(N->getFirstSucc());
+ return N->succ_end();
+ }
- static nodes_iterator nodes_begin(NodeRef N) { return df_begin(N); }
+ static nodes_iterator nodes_begin(const GraphTy G) {
+ return df_begin(G);
+ }
- static nodes_iterator nodes_end(NodeRef N) { return df_end(N); }
+ static nodes_iterator nodes_end(const GraphTy G) {
+ return df_end(G);
+ }
};
-
} // namespace llvm
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 06a90fa847a6..86b776afb822 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -141,9 +141,6 @@ private:
/// implicitly never returns.
ObjCNoReturn ObjCNoRet;
- /// Whether or not GC is enabled in this analysis.
- bool ObjCGCEnabled;
-
/// The BugReporter associated with this engine. It is important that
/// this object be placed at the very end of member variables so that its
/// destructor is called before the rest of the ExprEngine is destroyed.
@@ -158,7 +155,7 @@ private:
public:
ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr,
- bool gcEnabled, SetOfConstDecls *VisitedCalleesIn,
+ SetOfConstDecls *VisitedCalleesIn,
FunctionSummariesTy *FS, InliningModes HowToInlineIn);
~ExprEngine() override;
@@ -201,14 +198,24 @@ public:
return *currBldrCtx;
}
- bool isObjCGCEnabled() { return ObjCGCEnabled; }
-
const Stmt *getStmt() const;
void GenerateAutoTransition(ExplodedNode *N);
void enqueueEndOfPath(ExplodedNodeSet &S);
void GenerateCallExitNode(ExplodedNode *N);
+
+ /// Dump graph to the specified filename.
+ /// If filename is empty, generate a temporary one.
+ /// \return The filename the graph is written into.
+ std::string DumpGraph(bool trim = false, StringRef Filename="");
+
+ /// Dump the graph consisting of the given nodes to a specified filename.
+ /// Generate a temporary filename if it's not provided.
+ /// \return The filename the graph is written into.
+ std::string DumpGraph(ArrayRef<const ExplodedNode *> Nodes,
+ StringRef Filename = "");
+
/// Visualize the ExplodedGraph created by executing the simulation.
void ViewGraph(bool trim = false);
@@ -286,7 +293,7 @@ public:
/// ProcessBranch - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- void processBranch(const Stmt *Condition, const Stmt *Term,
+ void processBranch(const Stmt *Condition,
NodeBuilderContext& BuilderCtx,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
@@ -345,7 +352,7 @@ public:
void processCallExit(ExplodedNode *Pred) override;
/// Called by CoreEngine when the analysis worklist has terminated.
- void processEndWorklist(bool hasWorkRemaining) override;
+ void processEndWorklist() override;
/// evalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values.
@@ -608,7 +615,6 @@ protected:
ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) override;
@@ -662,6 +668,11 @@ public:
const EvalCallOptions &CallOpts = {});
private:
+ ProgramStateRef finishArgumentConstruction(ProgramStateRef State,
+ const CallEvent &Call);
+ void finishArgumentConstruction(ExplodedNodeSet &Dst, ExplodedNode *Pred,
+ const CallEvent &Call);
+
void evalLoadCommon(ExplodedNodeSet &Dst,
const Expr *NodeEx, /* Eventually will be a CFGStmt */
const Expr *BoundEx,
@@ -671,14 +682,13 @@ private:
const ProgramPointTag *tag,
QualType LoadTy);
- // FIXME: 'tag' should be removed, and a LocationContext should be used
- // instead.
void evalLocation(ExplodedNodeSet &Dst,
const Stmt *NodeEx, /* This will eventually be a CFGStmt */
const Stmt *BoundEx,
ExplodedNode *Pred,
- ProgramStateRef St, SVal location,
- const ProgramPointTag *tag, bool isLoad);
+ ProgramStateRef St,
+ SVal location,
+ bool isLoad);
/// Count the stack depth and determine if the call is recursive.
void examineStackFrames(const Decl *D, const LocationContext *LCtx,
@@ -729,10 +739,14 @@ private:
///
/// If \p Result is provided, the new region will be bound to this expression
/// instead of \p InitWithAdjustments.
- ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
- const LocationContext *LC,
- const Expr *InitWithAdjustments,
- const Expr *Result = nullptr);
+ ///
+ /// Returns the temporary region with adjustments into the optional
+ /// OutRegionWithAdjustments out-parameter if a new region was indeed needed,
+ /// otherwise sets it to nullptr.
+ ProgramStateRef createTemporaryRegionIfNeeded(
+ ProgramStateRef State, const LocationContext *LC,
+ const Expr *InitWithAdjustments, const Expr *Result = nullptr,
+ const SubRegion **OutRegionWithAdjustments = nullptr);
/// Returns a region representing the first element of a (possibly
/// multi-dimensional) array, for the purposes of element construction or
@@ -818,7 +832,7 @@ struct ReplayWithoutInlining{};
template <>
struct ProgramStateTrait<ReplayWithoutInlining> :
public ProgramStatePartialTrait<const void*> {
- static void *GDMIndex() { static int index = 0; return &index; }
+ static void *GDMIndex();
};
} // namespace ento
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 3a93aae5a9bc..3d0ff4efa1d7 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -24,6 +24,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
@@ -118,11 +119,15 @@ public:
const MemRegion *getBaseRegion() const;
+ /// Recursively retrieve the region of the most derived class instance of
+ /// regions of C++ base class instances.
+ const MemRegion *getMostDerivedObjectRegion() const;
+
/// Check if the region is a subregion of the given region.
/// Each region is a subregion of itself.
virtual bool isSubRegionOf(const MemRegion *R) const;
- const MemRegion *StripCasts(bool StripBaseCasts = true) const;
+ const MemRegion *StripCasts(bool StripBaseAndDerivedCasts = true) const;
/// If this is a symbolic region, returns the region. Otherwise,
/// goes up the base chain looking for the first symbolic base region.
@@ -763,10 +768,15 @@ class SymbolicRegion : public SubRegion {
SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg)
: SubRegion(sreg, SymbolicRegionKind), sym(s) {
- assert(s);
+ // Because pointer arithmetic is represented by ElementRegion layers,
+ // the base symbol here should not contain any arithmetic.
+ assert(s && isa<SymbolData>(s));
assert(s->getType()->isAnyPointerType() ||
s->getType()->isReferenceType() ||
s->getType()->isBlockPointerType());
+
+ // populateWorklistFromSymbol() relies on this assertion, and needs to be
+ // updated if more cases are introduced.
assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg));
}
@@ -1072,7 +1082,7 @@ public:
void dump() const;
};
-/// ElementRegin is used to represent both array elements and casts.
+/// ElementRegion is used to represent both array elements and casts.
class ElementRegion : public TypedValueRegion {
friend class MemRegionManager;
@@ -1176,6 +1186,47 @@ public:
}
};
+// CXXDerivedObjectRegion represents a derived-class object that surrounds
+// a C++ object. It is identified by the derived class declaration and the
+// region of its parent object. It is a bit counter-intuitive (but not otherwise
+// unseen) that this region represents a larger segment of memory that its
+// super-region.
+class CXXDerivedObjectRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ const CXXRecordDecl *DerivedD;
+
+ CXXDerivedObjectRegion(const CXXRecordDecl *DerivedD, const SubRegion *SReg)
+ : TypedValueRegion(SReg, CXXDerivedObjectRegionKind), DerivedD(DerivedD) {
+ assert(DerivedD);
+ // In case of a concrete region, it should always be possible to model
+ // the base-to-derived cast by undoing a previous derived-to-base cast,
+ // otherwise the cast is most likely ill-formed.
+ assert(SReg->getSymbolicBase() &&
+ "Should have unwrapped a base region instead!");
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
+ const MemRegion *SReg);
+
+public:
+ const CXXRecordDecl *getDecl() const { return DerivedD; }
+
+ QualType getValueType() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ bool canPrintPrettyAsExpr() const override;
+
+ void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *region) {
+ return region->getKind() == CXXDerivedObjectRegionKind;
+ }
+};
+
template<typename RegionTy>
const RegionTy* MemRegion::getAs() const {
if (const auto *RT = dyn_cast<RegionTy>(this))
@@ -1326,6 +1377,14 @@ public:
baseReg->isVirtual());
}
+ /// Create a CXXDerivedObjectRegion with the given derived class for region
+ /// \p Super. This should not be used for casting an existing
+ /// CXXBaseObjectRegion back to the derived type; instead, CXXBaseObjectRegion
+ /// should be removed.
+ const CXXDerivedObjectRegion *
+ getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass,
+ const SubRegion *Super);
+
const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
CanQualType locTy,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index b86301a03470..c3a7028d8755 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -107,6 +107,8 @@ public:
~ProgramState();
+ int64_t getID() const;
+
/// Return the ProgramStateManager associated with this state.
ProgramStateManager &getStateManager() const {
return *stateMgr;
@@ -346,6 +348,8 @@ public:
/// a value of such type.
SVal getSValAsScalarOrLoc(const MemRegion *R) const;
+ using region_iterator = const MemRegion **;
+
/// Visits the symbols reachable from the given SVal using the provided
/// SymbolVisitor.
///
@@ -355,24 +359,14 @@ public:
/// \sa ScanReachableSymbols
bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
- /// Visits the symbols reachable from the SVals in the given range
- /// using the provided SymbolVisitor.
- bool scanReachableSymbols(const SVal *I, const SVal *E,
- SymbolVisitor &visitor) const;
-
/// Visits the symbols reachable from the regions in the given
/// MemRegions range using the provided SymbolVisitor.
- bool scanReachableSymbols(const MemRegion * const *I,
- const MemRegion * const *E,
+ bool scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable,
SymbolVisitor &visitor) const;
template <typename CB> CB scanReachableSymbols(SVal val) const;
- template <typename CB> CB scanReachableSymbols(const SVal *beg,
- const SVal *end) const;
-
template <typename CB> CB
- scanReachableSymbols(const MemRegion * const *beg,
- const MemRegion * const *end) const;
+ scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable) const;
/// Create a new state in which the statement is marked as tainted.
LLVM_NODISCARD ProgramStateRef
@@ -469,8 +463,7 @@ public:
const LocationContext *CurrentLC = nullptr) const;
void printDOT(raw_ostream &Out,
const LocationContext *CurrentLC = nullptr) const;
- void printTaint(raw_ostream &Out, const char *nl = "\n",
- const char *sep = "") const;
+ void printTaint(raw_ostream &Out, const char *nl = "\n") const;
void dump() const;
void dumpTaint() const;
@@ -562,15 +555,15 @@ public:
MemRegionManager& getRegionManager() {
return svalBuilder->getRegionManager();
}
- const MemRegionManager& getRegionManager() const {
+ const MemRegionManager &getRegionManager() const {
return svalBuilder->getRegionManager();
}
CallEventManager &getCallEventManager() { return *CallEventMgr; }
- StoreManager& getStoreManager() { return *StoreMgr; }
- ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
- SubEngine* getOwningEngine() { return Eng; }
+ StoreManager &getStoreManager() { return *StoreMgr; }
+ ConstraintManager &getConstraintManager() { return *ConstraintMgr; }
+ SubEngine &getOwningEngine() { return *Eng; }
ProgramStateRef removeDeadBindings(ProgramStateRef St,
const StackFrameContext *LCtx,
@@ -882,17 +875,10 @@ CB ProgramState::scanReachableSymbols(SVal val) const {
}
template <typename CB>
-CB ProgramState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
- CB cb(this);
- scanReachableSymbols(beg, end, cb);
- return cb;
-}
-
-template <typename CB>
-CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
- const MemRegion * const *end) const {
+CB ProgramState::scanReachableSymbols(
+ llvm::iterator_range<region_iterator> Reachable) const {
CB cb(this);
- scanReachableSymbols(beg, end, cb);
+ scanReachableSymbols(Reachable, cb);
return cb;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
index 5555b292534c..64de736c7e9f 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -30,8 +30,7 @@ namespace ento {
/// Declares a program state trait for type \p Type called \p Name, and
/// introduce a type named \c NameTy.
- /// The macro should not be used inside namespaces, or for traits that must
- /// be accessible from more than one translation unit.
+ /// The macro should not be used inside namespaces.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
namespace { \
class Name {}; \
@@ -47,6 +46,102 @@ namespace ento {
} \
}
+ /// Declares a factory for objects of type \p Type in the program state
+ /// manager. The type must provide a ::Factory sub-class. Commonly used for
+ /// ImmutableMap, ImmutableSet, ImmutableList. The macro should not be used
+ /// inside namespaces.
+ #define REGISTER_FACTORY_WITH_PROGRAMSTATE(Type) \
+ namespace clang { \
+ namespace ento { \
+ template <> \
+ struct ProgramStateTrait<Type> \
+ : public ProgramStatePartialTrait<Type> { \
+ static void *GDMIndex() { static int Index; return &Index; } \
+ }; \
+ } \
+ }
+
+ /// Helper for registering a map trait.
+ ///
+ /// If the map type were written directly in the invocation of
+ /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
+ /// would be treated as a macro argument separator, which is wrong.
+ /// This allows the user to specify a map type in a way that the preprocessor
+ /// can deal with.
+ #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
+
+ /// Declares an immutable map of type \p NameTy, suitable for placement into
+ /// the ProgramState. This is implementing using llvm::ImmutableMap.
+ ///
+ /// \code
+ /// State = State->set<Name>(K, V);
+ /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map.
+ /// State = State->remove<Name>(K);
+ /// NameTy Map = State->get<Name>();
+ /// \endcode
+ ///
+ /// The macro should not be used inside namespaces, or for traits that must
+ /// be accessible from more than one translation unit.
+ #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \
+ REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \
+ CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value))
+
+ /// Declares an immutable map type \p Name and registers the factory
+ /// for such maps in the program state, but does not add the map itself
+ /// to the program state. Useful for managing lifetime of maps that are used
+ /// as elements of other program state data structures.
+ #define REGISTER_MAP_FACTORY_WITH_PROGRAMSTATE(Name, Key, Value) \
+ using Name = llvm::ImmutableMap<Key, Value>; \
+ REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
+
+
+ /// Declares an immutable set of type \p NameTy, suitable for placement into
+ /// the ProgramState. This is implementing using llvm::ImmutableSet.
+ ///
+ /// \code
+ /// State = State->add<Name>(E);
+ /// State = State->remove<Name>(E);
+ /// bool Present = State->contains<Name>(E);
+ /// NameTy Set = State->get<Name>();
+ /// \endcode
+ ///
+ /// The macro should not be used inside namespaces, or for traits that must
+ /// be accessible from more than one translation unit.
+ #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \
+ REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>)
+
+ /// Declares an immutable set type \p Name and registers the factory
+ /// for such sets in the program state, but does not add the set itself
+ /// to the program state. Useful for managing lifetime of sets that are used
+ /// as elements of other program state data structures.
+ #define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \
+ using Name = llvm::ImmutableSet<Elem>; \
+ REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
+
+
+ /// Declares an immutable list type \p NameTy, suitable for placement into
+ /// the ProgramState. This is implementing using llvm::ImmutableList.
+ ///
+ /// \code
+ /// State = State->add<Name>(E); // Adds to the /end/ of the list.
+ /// bool Present = State->contains<Name>(E);
+ /// NameTy List = State->get<Name>();
+ /// \endcode
+ ///
+ /// The macro should not be used inside namespaces, or for traits that must
+ /// be accessible from more than one translation unit.
+ #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \
+ REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>)
+
+ /// Declares an immutable list of type \p Name and registers the factory
+ /// for such lists in the program state, but does not add the list itself
+ /// to the program state. Useful for managing lifetime of lists that are used
+ /// as elements of other program state data structures.
+ #define REGISTER_LIST_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \
+ using Name = llvm::ImmutableList<Elem>; \
+ REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
+
+
// Partial-specialization for ImmutableMap.
template <typename Key, typename Data, typename Info>
struct ProgramStatePartialTrait<llvm::ImmutableMap<Key, Data, Info>> {
@@ -95,15 +190,6 @@ namespace ento {
}
};
- /// Helper for registering a map trait.
- ///
- /// If the map type were written directly in the invocation of
- /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
- /// would be treated as a macro argument separator, which is wrong.
- /// This allows the user to specify a map type in a way that the preprocessor
- /// can deal with.
- #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
-
// Partial-specialization for ImmutableSet.
template <typename Key, typename Info>
struct ProgramStatePartialTrait<llvm::ImmutableSet<Key, Info>> {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
index d2ba1f7c9529..1b12a4edc205 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
@@ -131,7 +131,7 @@ using ConstraintRangeTy = llvm::ImmutableMap<SymbolRef, RangeSet>;
template <>
struct ProgramStateTrait<ConstraintRange>
: public ProgramStatePartialTrait<ConstraintRangeTy> {
- static void *GDMIndex() { static int Index; return &Index; }
+ static void *GDMIndex();
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def b/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
index c84a1ff13f8b..10f89ecc55a5 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
@@ -68,6 +68,7 @@ ABSTRACT_REGION(SubRegion, MemRegion)
ABSTRACT_REGION(TypedValueRegion, TypedRegion)
REGION(CompoundLiteralRegion, TypedValueRegion)
REGION(CXXBaseObjectRegion, TypedValueRegion)
+ REGION(CXXDerivedObjectRegion, TypedValueRegion)
REGION(CXXTempObjectRegion, TypedValueRegion)
REGION(CXXThisRegion, TypedValueRegion)
ABSTRACT_REGION(DeclRegion, TypedValueRegion)
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
index 19d3d5973e0f..8eaa9365be1d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
@@ -16,11 +16,12 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
namespace clang {
namespace ento {
+template <typename ConstraintSMT, typename SMTExprTy>
class SMTConstraintManager : public clang::ento::SimpleConstraintManager {
SMTSolverRef &Solver;
@@ -34,25 +35,234 @@ public:
// Implementation for interface from SimpleConstraintManager.
//===------------------------------------------------------------------===//
- ProgramStateRef assumeSym(ProgramStateRef state, SymbolRef Sym,
- bool Assumption) override;
+ ProgramStateRef assumeSym(ProgramStateRef State, SymbolRef Sym,
+ bool Assumption) override {
+ ASTContext &Ctx = getBasicVals().getContext();
+
+ QualType RetTy;
+ bool hasComparison;
+
+ SMTExprRef Exp = SMTConv::getExpr(Solver, Ctx, Sym, &RetTy, &hasComparison);
+
+ // Create zero comparison for implicit boolean cast, with reversed
+ // assumption
+ if (!hasComparison && !RetTy->isBooleanType())
+ return assumeExpr(
+ State, Sym,
+ SMTConv::getZeroExpr(Solver, Ctx, Exp, RetTy, !Assumption));
+
+ return assumeExpr(State, Sym, Assumption ? Exp : Solver->mkNot(Exp));
+ }
ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym,
const llvm::APSInt &From,
const llvm::APSInt &To,
- bool InRange) override;
+ bool InRange) override {
+ ASTContext &Ctx = getBasicVals().getContext();
+ return assumeExpr(
+ State, Sym, SMTConv::getRangeExpr(Solver, Ctx, Sym, From, To, InRange));
+ }
ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym,
- bool Assumption) override;
+ bool Assumption) override {
+ // Skip anything that is unsupported
+ return State;
+ }
//===------------------------------------------------------------------===//
// Implementation for interface from ConstraintManager.
//===------------------------------------------------------------------===//
- ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
+ ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override {
+ ASTContext &Ctx = getBasicVals().getContext();
+
+ QualType RetTy;
+ // The expression may be casted, so we cannot call getZ3DataExpr() directly
+ SMTExprRef VarExp = SMTConv::getExpr(Solver, Ctx, Sym, &RetTy);
+ SMTExprRef Exp =
+ SMTConv::getZeroExpr(Solver, Ctx, VarExp, RetTy, /*Assumption=*/true);
+
+ // Negate the constraint
+ SMTExprRef NotExp =
+ SMTConv::getZeroExpr(Solver, Ctx, VarExp, RetTy, /*Assumption=*/false);
+
+ ConditionTruthVal isSat = checkModel(State, Sym, Exp);
+ ConditionTruthVal isNotSat = checkModel(State, Sym, NotExp);
+
+ // Zero is the only possible solution
+ if (isSat.isConstrainedTrue() && isNotSat.isConstrainedFalse())
+ return true;
+
+ // Zero is not a solution
+ if (isSat.isConstrainedFalse() && isNotSat.isConstrainedTrue())
+ return false;
+
+ // Zero may be a solution
+ return ConditionTruthVal();
+ }
const llvm::APSInt *getSymVal(ProgramStateRef State,
- SymbolRef Sym) const override;
+ SymbolRef Sym) const override {
+ BasicValueFactory &BVF = getBasicVals();
+ ASTContext &Ctx = BVF.getContext();
+
+ if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
+ QualType Ty = Sym->getType();
+ assert(!Ty->isRealFloatingType());
+ llvm::APSInt Value(Ctx.getTypeSize(Ty),
+ !Ty->isSignedIntegerOrEnumerationType());
+
+ // TODO: this should call checkModel so we can use the cache, however,
+ // this method tries to get the interpretation (the actual value) from
+ // the solver, which is currently not cached.
+
+ SMTExprRef Exp =
+ SMTConv::fromData(Solver, SD->getSymbolID(), Ty, Ctx.getTypeSize(Ty));
+
+ Solver->reset();
+ addStateConstraints(State);
+
+ // Constraints are unsatisfiable
+ Optional<bool> isSat = Solver->check();
+ if (!isSat.hasValue() || !isSat.getValue())
+ return nullptr;
+
+ // Model does not assign interpretation
+ if (!Solver->getInterpretation(Exp, Value))
+ return nullptr;
+
+ // A value has been obtained, check if it is the only value
+ SMTExprRef NotExp = SMTConv::fromBinOp(
+ Solver, Exp, BO_NE,
+ Ty->isBooleanType() ? Solver->mkBoolean(Value.getBoolValue())
+ : Solver->mkBitvector(Value, Value.getBitWidth()),
+ /*isSigned=*/false);
+
+ Solver->addConstraint(NotExp);
+
+ Optional<bool> isNotSat = Solver->check();
+ if (!isSat.hasValue() || isNotSat.getValue())
+ return nullptr;
+
+ // This is the only solution, store it
+ return &BVF.getValue(Value);
+ }
+
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
+ SymbolRef CastSym = SC->getOperand();
+ QualType CastTy = SC->getType();
+ // Skip the void type
+ if (CastTy->isVoidType())
+ return nullptr;
+
+ const llvm::APSInt *Value;
+ if (!(Value = getSymVal(State, CastSym)))
+ return nullptr;
+ return &BVF.Convert(SC->getType(), *Value);
+ }
+
+ if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
+ const llvm::APSInt *LHS, *RHS;
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
+ LHS = getSymVal(State, SIE->getLHS());
+ RHS = &SIE->getRHS();
+ } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
+ LHS = &ISE->getLHS();
+ RHS = getSymVal(State, ISE->getRHS());
+ } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
+ // Early termination to avoid expensive call
+ LHS = getSymVal(State, SSM->getLHS());
+ RHS = LHS ? getSymVal(State, SSM->getRHS()) : nullptr;
+ } else {
+ llvm_unreachable("Unsupported binary expression to get symbol value!");
+ }
+
+ if (!LHS || !RHS)
+ return nullptr;
+
+ llvm::APSInt ConvertedLHS, ConvertedRHS;
+ QualType LTy, RTy;
+ std::tie(ConvertedLHS, LTy) = SMTConv::fixAPSInt(Ctx, *LHS);
+ std::tie(ConvertedRHS, RTy) = SMTConv::fixAPSInt(Ctx, *RHS);
+ SMTConv::doIntTypeConversion<llvm::APSInt, &SMTConv::castAPSInt>(
+ Solver, Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
+ return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
+ }
+
+ llvm_unreachable("Unsupported expression to get symbol value!");
+ }
+
+ ProgramStateRef removeDeadBindings(ProgramStateRef State,
+ SymbolReaper &SymReaper) override {
+ auto CZ = State->get<ConstraintSMT>();
+ auto &CZFactory = State->get_context<ConstraintSMT>();
+
+ for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) {
+ if (SymReaper.isDead(I->first))
+ CZ = CZFactory.remove(CZ, *I);
+ }
+
+ return State->set<ConstraintSMT>(CZ);
+ }
+
+ void print(ProgramStateRef St, raw_ostream &OS, const char *nl,
+ const char *sep) override {
+
+ auto CZ = St->get<ConstraintSMT>();
+
+ OS << nl << sep << "Constraints:";
+ for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) {
+ OS << nl << ' ' << I->first << " : ";
+ I->second.print(OS);
+ }
+ OS << nl;
+ }
+
+ bool canReasonAbout(SVal X) const override {
+ const TargetInfo &TI = getBasicVals().getContext().getTargetInfo();
+
+ Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
+ if (!SymVal)
+ return true;
+
+ const SymExpr *Sym = SymVal->getSymbol();
+ QualType Ty = Sym->getType();
+
+ // Complex types are not modeled
+ if (Ty->isComplexType() || Ty->isComplexIntegerType())
+ return false;
+
+ // Non-IEEE 754 floating-point types are not modeled
+ if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+ (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() ||
+ &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())))
+ return false;
+
+ if (Ty->isRealFloatingType())
+ return Solver->isFPSupported();
+
+ if (isa<SymbolData>(Sym))
+ return true;
+
+ SValBuilder &SVB = getSValBuilder();
+
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
+ return canReasonAbout(SVB.makeSymbolVal(SC->getOperand()));
+
+ if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS()));
+
+ if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS()));
+
+ if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) &&
+ canReasonAbout(SVB.makeSymbolVal(SSE->getRHS()));
+ }
+
+ llvm_unreachable("Unsupported expression to reason about!");
+ }
/// Dumps SMT formula
LLVM_DUMP_METHOD void dump() const { Solver->dump(); }
@@ -60,15 +270,64 @@ public:
protected:
// Check whether a new model is satisfiable, and update the program state.
virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym,
- const SMTExprRef &Exp) = 0;
+ const SMTExprRef &Exp) {
+ // Check the model, avoid simplifying AST to save time
+ if (checkModel(State, Sym, Exp).isConstrainedTrue())
+ return State->add<ConstraintSMT>(
+ std::make_pair(Sym, static_cast<const SMTExprTy &>(*Exp)));
+
+ return nullptr;
+ }
/// Given a program state, construct the logical conjunction and add it to
/// the solver
- virtual void addStateConstraints(ProgramStateRef State) const = 0;
+ virtual void addStateConstraints(ProgramStateRef State) const {
+ // TODO: Don't add all the constraints, only the relevant ones
+ auto CZ = State->get<ConstraintSMT>();
+ auto I = CZ.begin(), IE = CZ.end();
+
+ // Construct the logical AND of all the constraints
+ if (I != IE) {
+ std::vector<SMTExprRef> ASTs;
+
+ SMTExprRef Constraint = Solver->newExprRef(I++->second);
+ while (I != IE) {
+ Constraint = Solver->mkAnd(Constraint, Solver->newExprRef(I++->second));
+ }
+
+ Solver->addConstraint(Constraint);
+ }
+ }
// Generate and check a Z3 model, using the given constraint.
- ConditionTruthVal checkModel(ProgramStateRef State,
- const SMTExprRef &Exp) const;
+ ConditionTruthVal checkModel(ProgramStateRef State, SymbolRef Sym,
+ const SMTExprRef &Exp) const {
+ ProgramStateRef NewState = State->add<ConstraintSMT>(
+ std::make_pair(Sym, static_cast<const SMTExprTy &>(*Exp)));
+
+ llvm::FoldingSetNodeID ID;
+ NewState->get<ConstraintSMT>().Profile(ID);
+
+ unsigned hash = ID.ComputeHash();
+ auto I = Cached.find(hash);
+ if (I != Cached.end())
+ return I->second;
+
+ Solver->reset();
+ addStateConstraints(NewState);
+
+ Optional<bool> res = Solver->check();
+ if (!res.hasValue())
+ Cached[hash] = ConditionTruthVal();
+ else
+ Cached[hash] = ConditionTruthVal(res.getValue());
+
+ return Cached[hash];
+ }
+
+ // Cache the result of an SMT query (true, false, unknown). The key is the
+ // hash of the constraints in a state
+ mutable llvm::DenseMap<unsigned, ConditionTruthVal> Cached;
}; // end class SMTConstraintManager
} // namespace ento
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h
deleted file mode 100644
index 45c9df4ef401..000000000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//== SMTContext.h -----------------------------------------------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a SMT generic Context API, which will be the base class
-// for every SMT solver context specific class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H
-
-namespace clang {
-namespace ento {
-
-/// Generic base class for SMT contexts
-class SMTContext {
-public:
- SMTContext() = default;
- virtual ~SMTContext() = default;
-};
-
-} // namespace ento
-} // namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
new file mode 100644
index 000000000000..cdca2a09700d
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
@@ -0,0 +1,753 @@
+//== SMTConv.h --------------------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a set of functions to create SMT expressions
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H
+
+#include "clang/AST/Expr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+
+namespace clang {
+namespace ento {
+
+class SMTConv {
+public:
+ // Returns an appropriate sort, given a QualType and it's bit width.
+ static inline SMTSortRef mkSort(SMTSolverRef &Solver, const QualType &Ty,
+ unsigned BitWidth) {
+ if (Ty->isBooleanType())
+ return Solver->getBoolSort();
+
+ if (Ty->isRealFloatingType())
+ return Solver->getFloatSort(BitWidth);
+
+ return Solver->getBitvectorSort(BitWidth);
+ }
+
+ /// Constructs an SMTExprRef from an unary operator.
+ static inline SMTExprRef fromUnOp(SMTSolverRef &Solver,
+ const UnaryOperator::Opcode Op,
+ const SMTExprRef &Exp) {
+ switch (Op) {
+ case UO_Minus:
+ return Solver->mkBVNeg(Exp);
+
+ case UO_Not:
+ return Solver->mkBVNot(Exp);
+
+ case UO_LNot:
+ return Solver->mkNot(Exp);
+
+ default:;
+ }
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Constructs an SMTExprRef from a floating-point unary operator.
+ static inline SMTExprRef fromFloatUnOp(SMTSolverRef &Solver,
+ const UnaryOperator::Opcode Op,
+ const SMTExprRef &Exp) {
+ switch (Op) {
+ case UO_Minus:
+ return Solver->mkFPNeg(Exp);
+
+ case UO_LNot:
+ return fromUnOp(Solver, Op, Exp);
+
+ default:;
+ }
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a n-ary binary operator.
+ static inline SMTExprRef fromNBinOp(SMTSolverRef &Solver,
+ const BinaryOperator::Opcode Op,
+ const std::vector<SMTExprRef> &ASTs) {
+ assert(!ASTs.empty());
+
+ if (Op != BO_LAnd && Op != BO_LOr)
+ llvm_unreachable("Unimplemented opcode");
+
+ SMTExprRef res = ASTs.front();
+ for (std::size_t i = 1; i < ASTs.size(); ++i)
+ res = (Op == BO_LAnd) ? Solver->mkAnd(res, ASTs[i])
+ : Solver->mkOr(res, ASTs[i]);
+ return res;
+ }
+
+ /// Construct an SMTExprRef from a binary operator.
+ static inline SMTExprRef fromBinOp(SMTSolverRef &Solver,
+ const SMTExprRef &LHS,
+ const BinaryOperator::Opcode Op,
+ const SMTExprRef &RHS, bool isSigned) {
+ assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
+ "AST's must have the same sort!");
+
+ switch (Op) {
+ // Multiplicative operators
+ case BO_Mul:
+ return Solver->mkBVMul(LHS, RHS);
+
+ case BO_Div:
+ return isSigned ? Solver->mkBVSDiv(LHS, RHS) : Solver->mkBVUDiv(LHS, RHS);
+
+ case BO_Rem:
+ return isSigned ? Solver->mkBVSRem(LHS, RHS) : Solver->mkBVURem(LHS, RHS);
+
+ // Additive operators
+ case BO_Add:
+ return Solver->mkBVAdd(LHS, RHS);
+
+ case BO_Sub:
+ return Solver->mkBVSub(LHS, RHS);
+
+ // Bitwise shift operators
+ case BO_Shl:
+ return Solver->mkBVShl(LHS, RHS);
+
+ case BO_Shr:
+ return isSigned ? Solver->mkBVAshr(LHS, RHS) : Solver->mkBVLshr(LHS, RHS);
+
+ // Relational operators
+ case BO_LT:
+ return isSigned ? Solver->mkBVSlt(LHS, RHS) : Solver->mkBVUlt(LHS, RHS);
+
+ case BO_GT:
+ return isSigned ? Solver->mkBVSgt(LHS, RHS) : Solver->mkBVUgt(LHS, RHS);
+
+ case BO_LE:
+ return isSigned ? Solver->mkBVSle(LHS, RHS) : Solver->mkBVUle(LHS, RHS);
+
+ case BO_GE:
+ return isSigned ? Solver->mkBVSge(LHS, RHS) : Solver->mkBVUge(LHS, RHS);
+
+ // Equality operators
+ case BO_EQ:
+ return Solver->mkEqual(LHS, RHS);
+
+ case BO_NE:
+ return fromUnOp(Solver, UO_LNot,
+ fromBinOp(Solver, LHS, BO_EQ, RHS, isSigned));
+
+ // Bitwise operators
+ case BO_And:
+ return Solver->mkBVAnd(LHS, RHS);
+
+ case BO_Xor:
+ return Solver->mkBVXor(LHS, RHS);
+
+ case BO_Or:
+ return Solver->mkBVOr(LHS, RHS);
+
+ // Logical operators
+ case BO_LAnd:
+ return Solver->mkAnd(LHS, RHS);
+
+ case BO_LOr:
+ return Solver->mkOr(LHS, RHS);
+
+ default:;
+ }
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a special floating-point binary operator.
+ static inline SMTExprRef
+ fromFloatSpecialBinOp(SMTSolverRef &Solver, const SMTExprRef &LHS,
+ const BinaryOperator::Opcode Op,
+ const llvm::APFloat::fltCategory &RHS) {
+ switch (Op) {
+ // Equality operators
+ case BO_EQ:
+ switch (RHS) {
+ case llvm::APFloat::fcInfinity:
+ return Solver->mkFPIsInfinite(LHS);
+
+ case llvm::APFloat::fcNaN:
+ return Solver->mkFPIsNaN(LHS);
+
+ case llvm::APFloat::fcNormal:
+ return Solver->mkFPIsNormal(LHS);
+
+ case llvm::APFloat::fcZero:
+ return Solver->mkFPIsZero(LHS);
+ }
+ break;
+
+ case BO_NE:
+ return fromFloatUnOp(Solver, UO_LNot,
+ fromFloatSpecialBinOp(Solver, LHS, BO_EQ, RHS));
+
+ default:;
+ }
+
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a floating-point binary operator.
+ static inline SMTExprRef fromFloatBinOp(SMTSolverRef &Solver,
+ const SMTExprRef &LHS,
+ const BinaryOperator::Opcode Op,
+ const SMTExprRef &RHS) {
+ assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
+ "AST's must have the same sort!");
+
+ switch (Op) {
+ // Multiplicative operators
+ case BO_Mul:
+ return Solver->mkFPMul(LHS, RHS);
+
+ case BO_Div:
+ return Solver->mkFPDiv(LHS, RHS);
+
+ case BO_Rem:
+ return Solver->mkFPRem(LHS, RHS);
+
+ // Additive operators
+ case BO_Add:
+ return Solver->mkFPAdd(LHS, RHS);
+
+ case BO_Sub:
+ return Solver->mkFPSub(LHS, RHS);
+
+ // Relational operators
+ case BO_LT:
+ return Solver->mkFPLt(LHS, RHS);
+
+ case BO_GT:
+ return Solver->mkFPGt(LHS, RHS);
+
+ case BO_LE:
+ return Solver->mkFPLe(LHS, RHS);
+
+ case BO_GE:
+ return Solver->mkFPGe(LHS, RHS);
+
+ // Equality operators
+ case BO_EQ:
+ return Solver->mkFPEqual(LHS, RHS);
+
+ case BO_NE:
+ return fromFloatUnOp(Solver, UO_LNot,
+ fromFloatBinOp(Solver, LHS, BO_EQ, RHS));
+
+ // Logical operators
+ case BO_LAnd:
+ case BO_LOr:
+ return fromBinOp(Solver, LHS, Op, RHS, /*isSigned=*/false);
+
+ default:;
+ }
+
+ llvm_unreachable("Unimplemented opcode");
+ }
+
+ /// Construct an SMTExprRef from a QualType FromTy to a QualType ToTy, and
+ /// their bit widths.
+ static inline SMTExprRef fromCast(SMTSolverRef &Solver, const SMTExprRef &Exp,
+ QualType ToTy, uint64_t ToBitWidth,
+ QualType FromTy, uint64_t FromBitWidth) {
+ if ((FromTy->isIntegralOrEnumerationType() &&
+ ToTy->isIntegralOrEnumerationType()) ||
+ (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) ||
+ (FromTy->isBlockPointerType() ^ ToTy->isBlockPointerType()) ||
+ (FromTy->isReferenceType() ^ ToTy->isReferenceType())) {
+
+ if (FromTy->isBooleanType()) {
+ assert(ToBitWidth > 0 && "BitWidth must be positive!");
+ return Solver->mkIte(
+ Exp, Solver->mkBitvector(llvm::APSInt("1"), ToBitWidth),
+ Solver->mkBitvector(llvm::APSInt("0"), ToBitWidth));
+ }
+
+ if (ToBitWidth > FromBitWidth)
+ return FromTy->isSignedIntegerOrEnumerationType()
+ ? Solver->mkBVSignExt(ToBitWidth - FromBitWidth, Exp)
+ : Solver->mkBVZeroExt(ToBitWidth - FromBitWidth, Exp);
+
+ if (ToBitWidth < FromBitWidth)
+ return Solver->mkBVExtract(ToBitWidth - 1, 0, Exp);
+
+ // Both are bitvectors with the same width, ignore the type cast
+ return Exp;
+ }
+
+ if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) {
+ if (ToBitWidth != FromBitWidth)
+ return Solver->mkFPtoFP(Exp, Solver->getFloatSort(ToBitWidth));
+
+ return Exp;
+ }
+
+ if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) {
+ SMTSortRef Sort = Solver->getFloatSort(ToBitWidth);
+ return FromTy->isSignedIntegerOrEnumerationType()
+ ? Solver->mkSBVtoFP(Exp, Sort)
+ : Solver->mkUBVtoFP(Exp, Sort);
+ }
+
+ if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType())
+ return ToTy->isSignedIntegerOrEnumerationType()
+ ? Solver->mkFPtoSBV(Exp, ToBitWidth)
+ : Solver->mkFPtoUBV(Exp, ToBitWidth);
+
+ llvm_unreachable("Unsupported explicit type cast!");
+ }
+
+ // Callback function for doCast parameter on APSInt type.
+ static inline llvm::APSInt castAPSInt(SMTSolverRef &Solver,
+ const llvm::APSInt &V, QualType ToTy,
+ uint64_t ToWidth, QualType FromTy,
+ uint64_t FromWidth) {
+ APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType());
+ return TargetType.convert(V);
+ }
+
+ /// Construct an SMTExprRef from a SymbolData.
+ static inline SMTExprRef fromData(SMTSolverRef &Solver, const SymbolID ID,
+ const QualType &Ty, uint64_t BitWidth) {
+ llvm::Twine Name = "$" + llvm::Twine(ID);
+ return Solver->mkSymbol(Name.str().c_str(), mkSort(Solver, Ty, BitWidth));
+ }
+
+ // Wrapper to generate SMTExprRef from SymbolCast data.
+ static inline SMTExprRef getCastExpr(SMTSolverRef &Solver, ASTContext &Ctx,
+ const SMTExprRef &Exp, QualType FromTy,
+ QualType ToTy) {
+ return fromCast(Solver, Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy,
+ Ctx.getTypeSize(FromTy));
+ }
+
+ // Wrapper to generate SMTExprRef from unpacked binary symbolic expression.
+ // Sets the RetTy parameter. See getSMTExprRef().
+ static inline SMTExprRef getBinExpr(SMTSolverRef &Solver, ASTContext &Ctx,
+ const SMTExprRef &LHS, QualType LTy,
+ BinaryOperator::Opcode Op,
+ const SMTExprRef &RHS, QualType RTy,
+ QualType *RetTy) {
+ SMTExprRef NewLHS = LHS;
+ SMTExprRef NewRHS = RHS;
+ doTypeConversion(Solver, Ctx, NewLHS, NewRHS, LTy, RTy);
+
+ // Update the return type parameter if the output type has changed.
+ if (RetTy) {
+ // A boolean result can be represented as an integer type in C/C++, but at
+ // this point we only care about the SMT sorts. Set it as a boolean type
+ // to avoid subsequent SMT errors.
+ if (BinaryOperator::isComparisonOp(Op) ||
+ BinaryOperator::isLogicalOp(Op)) {
+ *RetTy = Ctx.BoolTy;
+ } else {
+ *RetTy = LTy;
+ }
+
+ // If the two operands are pointers and the operation is a subtraction,
+ // the result is of type ptrdiff_t, which is signed
+ if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) {
+ *RetTy = Ctx.getPointerDiffType();
+ }
+ }
+
+ return LTy->isRealFloatingType()
+ ? fromFloatBinOp(Solver, NewLHS, Op, NewRHS)
+ : fromBinOp(Solver, NewLHS, Op, NewRHS,
+ LTy->isSignedIntegerOrEnumerationType());
+ }
+
+ // Wrapper to generate SMTExprRef from BinarySymExpr.
+ // Sets the hasComparison and RetTy parameters. See getSMTExprRef().
+ static inline SMTExprRef getSymBinExpr(SMTSolverRef &Solver, ASTContext &Ctx,
+ const BinarySymExpr *BSE,
+ bool *hasComparison, QualType *RetTy) {
+ QualType LTy, RTy;
+ BinaryOperator::Opcode Op = BSE->getOpcode();
+
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
+ SMTExprRef LHS =
+ getSymExpr(Solver, Ctx, SIE->getLHS(), &LTy, hasComparison);
+ llvm::APSInt NewRInt;
+ std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS());
+ SMTExprRef RHS = Solver->mkBitvector(NewRInt, NewRInt.getBitWidth());
+ return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
+ }
+
+ if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
+ llvm::APSInt NewLInt;
+ std::tie(NewLInt, LTy) = fixAPSInt(Ctx, ISE->getLHS());
+ SMTExprRef LHS = Solver->mkBitvector(NewLInt, NewLInt.getBitWidth());
+ SMTExprRef RHS =
+ getSymExpr(Solver, Ctx, ISE->getRHS(), &RTy, hasComparison);
+ return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
+ }
+
+ if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
+ SMTExprRef LHS =
+ getSymExpr(Solver, Ctx, SSM->getLHS(), &LTy, hasComparison);
+ SMTExprRef RHS =
+ getSymExpr(Solver, Ctx, SSM->getRHS(), &RTy, hasComparison);
+ return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
+ }
+
+ llvm_unreachable("Unsupported BinarySymExpr type!");
+ }
+
+ // Recursive implementation to unpack and generate symbolic expression.
+ // Sets the hasComparison and RetTy parameters. See getExpr().
+ static inline SMTExprRef getSymExpr(SMTSolverRef &Solver, ASTContext &Ctx,
+ SymbolRef Sym, QualType *RetTy,
+ bool *hasComparison) {
+ if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
+ if (RetTy)
+ *RetTy = Sym->getType();
+
+ return fromData(Solver, SD->getSymbolID(), Sym->getType(),
+ Ctx.getTypeSize(Sym->getType()));
+ }
+
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
+ if (RetTy)
+ *RetTy = Sym->getType();
+
+ QualType FromTy;
+ SMTExprRef Exp =
+ getSymExpr(Solver, Ctx, SC->getOperand(), &FromTy, hasComparison);
+
+ // Casting an expression with a comparison invalidates it. Note that this
+ // must occur after the recursive call above.
+ // e.g. (signed char) (x > 0)
+ if (hasComparison)
+ *hasComparison = false;
+ return getCastExpr(Solver, Ctx, Exp, FromTy, Sym->getType());
+ }
+
+ if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
+ SMTExprRef Exp = getSymBinExpr(Solver, Ctx, BSE, hasComparison, RetTy);
+ // Set the hasComparison parameter, in post-order traversal order.
+ if (hasComparison)
+ *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode());
+ return Exp;
+ }
+
+ llvm_unreachable("Unsupported SymbolRef type!");
+ }
+
+ // Generate an SMTExprRef that represents the given symbolic expression.
+ // Sets the hasComparison parameter if the expression has a comparison
+ // operator. Sets the RetTy parameter to the final return type after
+ // promotions and casts.
+ static inline SMTExprRef getExpr(SMTSolverRef &Solver, ASTContext &Ctx,
+ SymbolRef Sym, QualType *RetTy = nullptr,
+ bool *hasComparison = nullptr) {
+ if (hasComparison) {
+ *hasComparison = false;
+ }
+
+ return getSymExpr(Solver, Ctx, Sym, RetTy, hasComparison);
+ }
+
+ // Generate an SMTExprRef that compares the expression to zero.
+ static inline SMTExprRef getZeroExpr(SMTSolverRef &Solver, ASTContext &Ctx,
+ const SMTExprRef &Exp, QualType Ty,
+ bool Assumption) {
+
+ if (Ty->isRealFloatingType()) {
+ llvm::APFloat Zero =
+ llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty));
+ return fromFloatBinOp(Solver, Exp, Assumption ? BO_EQ : BO_NE,
+ Solver->mkFloat(Zero));
+ }
+
+ if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() ||
+ Ty->isBlockPointerType() || Ty->isReferenceType()) {
+
+ // Skip explicit comparison for boolean types
+ bool isSigned = Ty->isSignedIntegerOrEnumerationType();
+ if (Ty->isBooleanType())
+ return Assumption ? fromUnOp(Solver, UO_LNot, Exp) : Exp;
+
+ return fromBinOp(
+ Solver, Exp, Assumption ? BO_EQ : BO_NE,
+ Solver->mkBitvector(llvm::APSInt("0"), Ctx.getTypeSize(Ty)),
+ isSigned);
+ }
+
+ llvm_unreachable("Unsupported type for zero value!");
+ }
+
+ // Wrapper to generate SMTExprRef from a range. If From == To, an equality
+ // will be created instead.
+ static inline SMTExprRef getRangeExpr(SMTSolverRef &Solver, ASTContext &Ctx,
+ SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, bool InRange) {
+ // Convert lower bound
+ QualType FromTy;
+ llvm::APSInt NewFromInt;
+ std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From);
+ SMTExprRef FromExp =
+ Solver->mkBitvector(NewFromInt, NewFromInt.getBitWidth());
+
+ // Convert symbol
+ QualType SymTy;
+ SMTExprRef Exp = getExpr(Solver, Ctx, Sym, &SymTy);
+
+ // Construct single (in)equality
+ if (From == To)
+ return getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE,
+ FromExp, FromTy, /*RetTy=*/nullptr);
+
+ QualType ToTy;
+ llvm::APSInt NewToInt;
+ std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To);
+ SMTExprRef ToExp = Solver->mkBitvector(NewToInt, NewToInt.getBitWidth());
+ assert(FromTy == ToTy && "Range values have different types!");
+
+ // Construct two (in)equalities, and a logical and/or
+ SMTExprRef LHS =
+ getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp,
+ FromTy, /*RetTy=*/nullptr);
+ SMTExprRef RHS = getBinExpr(Solver, Ctx, Exp, SymTy,
+ InRange ? BO_LE : BO_GT, ToExp, ToTy,
+ /*RetTy=*/nullptr);
+
+ return fromBinOp(Solver, LHS, InRange ? BO_LAnd : BO_LOr, RHS,
+ SymTy->isSignedIntegerOrEnumerationType());
+ }
+
+ // Recover the QualType of an APSInt.
+ // TODO: Refactor to put elsewhere
+ static inline QualType getAPSIntType(ASTContext &Ctx,
+ const llvm::APSInt &Int) {
+ return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned());
+ }
+
+ // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1.
+ static inline std::pair<llvm::APSInt, QualType>
+ fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int) {
+ llvm::APSInt NewInt;
+
+ // FIXME: This should be a cast from a 1-bit integer type to a boolean type,
+ // but the former is not available in Clang. Instead, extend the APSInt
+ // directly.
+ if (Int.getBitWidth() == 1 && getAPSIntType(Ctx, Int).isNull()) {
+ NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy));
+ } else
+ NewInt = Int;
+
+ return std::make_pair(NewInt, getAPSIntType(Ctx, NewInt));
+ }
+
+ // Perform implicit type conversion on binary symbolic expressions.
+ // May modify all input parameters.
+ // TODO: Refactor to use built-in conversion functions
+ static inline void doTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx,
+ SMTExprRef &LHS, SMTExprRef &RHS,
+ QualType &LTy, QualType &RTy) {
+ assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!");
+
+ // Perform type conversion
+ if ((LTy->isIntegralOrEnumerationType() &&
+ RTy->isIntegralOrEnumerationType()) &&
+ (LTy->isArithmeticType() && RTy->isArithmeticType())) {
+ SMTConv::doIntTypeConversion<SMTExprRef, &fromCast>(Solver, Ctx, LHS, LTy,
+ RHS, RTy);
+ return;
+ }
+
+ if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) {
+ SMTConv::doFloatTypeConversion<SMTExprRef, &fromCast>(Solver, Ctx, LHS,
+ LTy, RHS, RTy);
+ return;
+ }
+
+ if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) ||
+ (LTy->isBlockPointerType() || RTy->isBlockPointerType()) ||
+ (LTy->isReferenceType() || RTy->isReferenceType())) {
+ // TODO: Refactor to Sema::FindCompositePointerType(), and
+ // Sema::CheckCompareOperands().
+
+ uint64_t LBitWidth = Ctx.getTypeSize(LTy);
+ uint64_t RBitWidth = Ctx.getTypeSize(RTy);
+
+ // Cast the non-pointer type to the pointer type.
+ // TODO: Be more strict about this.
+ if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) ||
+ (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) ||
+ (LTy->isReferenceType() ^ RTy->isReferenceType())) {
+ if (LTy->isNullPtrType() || LTy->isBlockPointerType() ||
+ LTy->isReferenceType()) {
+ LHS = fromCast(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ } else {
+ RHS = fromCast(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ }
+ }
+
+ // Cast the void pointer type to the non-void pointer type.
+ // For void types, this assumes that the casted value is equal to the
+ // value of the original pointer, and does not account for alignment
+ // requirements.
+ if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) {
+ assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) &&
+ "Pointer types have different bitwidths!");
+ if (RTy->isVoidPointerType())
+ RTy = LTy;
+ else
+ LTy = RTy;
+ }
+
+ if (LTy == RTy)
+ return;
+ }
+
+ // Fallback: for the solver, assume that these types don't really matter
+ if ((LTy.getCanonicalType() == RTy.getCanonicalType()) ||
+ (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) {
+ LTy = RTy;
+ return;
+ }
+
+ // TODO: Refine behavior for invalid type casts
+ }
+
+ // Perform implicit integer type conversion.
+ // May modify all input parameters.
+ // TODO: Refactor to use Sema::handleIntegerConversion()
+ template <typename T, T (*doCast)(SMTSolverRef &Solver, const T &, QualType,
+ uint64_t, QualType, uint64_t)>
+ static inline void doIntTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx,
+ T &LHS, QualType &LTy, T &RHS,
+ QualType &RTy) {
+
+ uint64_t LBitWidth = Ctx.getTypeSize(LTy);
+ uint64_t RBitWidth = Ctx.getTypeSize(RTy);
+
+ assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!");
+ // Always perform integer promotion before checking type equality.
+ // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion
+ if (LTy->isPromotableIntegerType()) {
+ QualType NewTy = Ctx.getPromotedIntegerType(LTy);
+ uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
+ LHS = (*doCast)(Solver, LHS, NewTy, NewBitWidth, LTy, LBitWidth);
+ LTy = NewTy;
+ LBitWidth = NewBitWidth;
+ }
+ if (RTy->isPromotableIntegerType()) {
+ QualType NewTy = Ctx.getPromotedIntegerType(RTy);
+ uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
+ RHS = (*doCast)(Solver, RHS, NewTy, NewBitWidth, RTy, RBitWidth);
+ RTy = NewTy;
+ RBitWidth = NewBitWidth;
+ }
+
+ if (LTy == RTy)
+ return;
+
+ // Perform integer type conversion
+ // Note: Safe to skip updating bitwidth because this must terminate
+ bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType();
+ bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType();
+
+ int order = Ctx.getIntegerTypeOrder(LTy, RTy);
+ if (isLSignedTy == isRSignedTy) {
+ // Same signedness; use the higher-ranked type
+ if (order == 1) {
+ RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else {
+ LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ }
+ } else if (order != (isLSignedTy ? 1 : -1)) {
+ // The unsigned type has greater than or equal rank to the
+ // signed type, so use the unsigned type
+ if (isRSignedTy) {
+ RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else {
+ LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ }
+ } else if (LBitWidth != RBitWidth) {
+ // The two types are different widths; if we are here, that
+ // means the signed type is larger than the unsigned type, so
+ // use the signed type.
+ if (isLSignedTy) {
+ RHS = (doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else {
+ LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ }
+ } else {
+ // The signed type is higher-ranked than the unsigned type,
+ // but isn't actually any bigger (like unsigned int and long
+ // on most 32-bit systems). Use the unsigned type corresponding
+ // to the signed type.
+ QualType NewTy =
+ Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy);
+ RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = NewTy;
+ LHS = (doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = NewTy;
+ }
+ }
+
+ // Perform implicit floating-point type conversion.
+ // May modify all input parameters.
+ // TODO: Refactor to use Sema::handleFloatConversion()
+ template <typename T, T (*doCast)(SMTSolverRef &Solver, const T &, QualType,
+ uint64_t, QualType, uint64_t)>
+ static inline void
+ doFloatTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx, T &LHS,
+ QualType &LTy, T &RHS, QualType &RTy) {
+
+ uint64_t LBitWidth = Ctx.getTypeSize(LTy);
+ uint64_t RBitWidth = Ctx.getTypeSize(RTy);
+
+ // Perform float-point type promotion
+ if (!LTy->isRealFloatingType()) {
+ LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ LBitWidth = RBitWidth;
+ }
+ if (!RTy->isRealFloatingType()) {
+ RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ RBitWidth = LBitWidth;
+ }
+
+ if (LTy == RTy)
+ return;
+
+ // If we have two real floating types, convert the smaller operand to the
+ // bigger result
+ // Note: Safe to skip updating bitwidth because this must terminate
+ int order = Ctx.getFloatingTypeOrder(LTy, RTy);
+ if (order > 0) {
+ RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
+ RTy = LTy;
+ } else if (order == 0) {
+ LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
+ LTy = RTy;
+ } else {
+ llvm_unreachable("Unsupported floating-point type cast!");
+ }
+ }
+};
+} // namespace ento
+} // namespace clang
+
+#endif \ No newline at end of file
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
index a43ca486901b..2abe5fc98744 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
@@ -15,12 +15,9 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H
-#include "clang/AST/Expr.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/APSInt.h"
namespace clang {
namespace ento {
@@ -53,683 +50,6 @@ public:
llvm_unreachable("Unsupported floating-point bitwidth!");
}
- // Returns an appropriate sort, given a QualType and it's bit width.
- SMTSortRef mkSort(const QualType &Ty, unsigned BitWidth) {
- if (Ty->isBooleanType())
- return getBoolSort();
-
- if (Ty->isRealFloatingType())
- return getFloatSort(BitWidth);
-
- return getBitvectorSort(BitWidth);
- }
-
- /// Constructs an SMTExprRef from an unary operator.
- SMTExprRef fromUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp) {
- switch (Op) {
- case UO_Minus:
- return mkBVNeg(Exp);
-
- case UO_Not:
- return mkBVNot(Exp);
-
- case UO_LNot:
- return mkNot(Exp);
-
- default:;
- }
- llvm_unreachable("Unimplemented opcode");
- }
-
- /// Constructs an SMTExprRef from a floating-point unary operator.
- SMTExprRef fromFloatUnOp(const UnaryOperator::Opcode Op,
- const SMTExprRef &Exp) {
- switch (Op) {
- case UO_Minus:
- return mkFPNeg(Exp);
-
- case UO_LNot:
- return fromUnOp(Op, Exp);
-
- default:;
- }
- llvm_unreachable("Unimplemented opcode");
- }
-
- /// Construct an SMTExprRef from a n-ary binary operator.
- SMTExprRef fromNBinOp(const BinaryOperator::Opcode Op,
- const std::vector<SMTExprRef> &ASTs) {
- assert(!ASTs.empty());
-
- if (Op != BO_LAnd && Op != BO_LOr)
- llvm_unreachable("Unimplemented opcode");
-
- SMTExprRef res = ASTs.front();
- for (std::size_t i = 1; i < ASTs.size(); ++i)
- res = (Op == BO_LAnd) ? mkAnd(res, ASTs[i]) : mkOr(res, ASTs[i]);
- return res;
- }
-
- /// Construct an SMTExprRef from a binary operator.
- SMTExprRef fromBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op,
- const SMTExprRef &RHS, bool isSigned) {
- assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!");
-
- switch (Op) {
- // Multiplicative operators
- case BO_Mul:
- return mkBVMul(LHS, RHS);
-
- case BO_Div:
- return isSigned ? mkBVSDiv(LHS, RHS) : mkBVUDiv(LHS, RHS);
-
- case BO_Rem:
- return isSigned ? mkBVSRem(LHS, RHS) : mkBVURem(LHS, RHS);
-
- // Additive operators
- case BO_Add:
- return mkBVAdd(LHS, RHS);
-
- case BO_Sub:
- return mkBVSub(LHS, RHS);
-
- // Bitwise shift operators
- case BO_Shl:
- return mkBVShl(LHS, RHS);
-
- case BO_Shr:
- return isSigned ? mkBVAshr(LHS, RHS) : mkBVLshr(LHS, RHS);
-
- // Relational operators
- case BO_LT:
- return isSigned ? mkBVSlt(LHS, RHS) : mkBVUlt(LHS, RHS);
-
- case BO_GT:
- return isSigned ? mkBVSgt(LHS, RHS) : mkBVUgt(LHS, RHS);
-
- case BO_LE:
- return isSigned ? mkBVSle(LHS, RHS) : mkBVUle(LHS, RHS);
-
- case BO_GE:
- return isSigned ? mkBVSge(LHS, RHS) : mkBVUge(LHS, RHS);
-
- // Equality operators
- case BO_EQ:
- return mkEqual(LHS, RHS);
-
- case BO_NE:
- return fromUnOp(UO_LNot, fromBinOp(LHS, BO_EQ, RHS, isSigned));
-
- // Bitwise operators
- case BO_And:
- return mkBVAnd(LHS, RHS);
-
- case BO_Xor:
- return mkBVXor(LHS, RHS);
-
- case BO_Or:
- return mkBVOr(LHS, RHS);
-
- // Logical operators
- case BO_LAnd:
- return mkAnd(LHS, RHS);
-
- case BO_LOr:
- return mkOr(LHS, RHS);
-
- default:;
- }
- llvm_unreachable("Unimplemented opcode");
- }
-
- /// Construct an SMTExprRef from a special floating-point binary operator.
- SMTExprRef fromFloatSpecialBinOp(const SMTExprRef &LHS,
- const BinaryOperator::Opcode Op,
- const llvm::APFloat::fltCategory &RHS) {
- switch (Op) {
- // Equality operators
- case BO_EQ:
- switch (RHS) {
- case llvm::APFloat::fcInfinity:
- return mkFPIsInfinite(LHS);
-
- case llvm::APFloat::fcNaN:
- return mkFPIsNaN(LHS);
-
- case llvm::APFloat::fcNormal:
- return mkFPIsNormal(LHS);
-
- case llvm::APFloat::fcZero:
- return mkFPIsZero(LHS);
- }
- break;
-
- case BO_NE:
- return fromFloatUnOp(UO_LNot, fromFloatSpecialBinOp(LHS, BO_EQ, RHS));
-
- default:;
- }
-
- llvm_unreachable("Unimplemented opcode");
- }
-
- /// Construct an SMTExprRef from a floating-point binary operator.
- SMTExprRef fromFloatBinOp(const SMTExprRef &LHS,
- const BinaryOperator::Opcode Op,
- const SMTExprRef &RHS) {
- assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!");
-
- switch (Op) {
- // Multiplicative operators
- case BO_Mul:
- return mkFPMul(LHS, RHS);
-
- case BO_Div:
- return mkFPDiv(LHS, RHS);
-
- case BO_Rem:
- return mkFPRem(LHS, RHS);
-
- // Additive operators
- case BO_Add:
- return mkFPAdd(LHS, RHS);
-
- case BO_Sub:
- return mkFPSub(LHS, RHS);
-
- // Relational operators
- case BO_LT:
- return mkFPLt(LHS, RHS);
-
- case BO_GT:
- return mkFPGt(LHS, RHS);
-
- case BO_LE:
- return mkFPLe(LHS, RHS);
-
- case BO_GE:
- return mkFPGe(LHS, RHS);
-
- // Equality operators
- case BO_EQ:
- return mkFPEqual(LHS, RHS);
-
- case BO_NE:
- return fromFloatUnOp(UO_LNot, fromFloatBinOp(LHS, BO_EQ, RHS));
-
- // Logical operators
- case BO_LAnd:
- case BO_LOr:
- return fromBinOp(LHS, Op, RHS, false);
-
- default:;
- }
-
- llvm_unreachable("Unimplemented opcode");
- }
-
- /// Construct an SMTExprRef from a QualType FromTy to a QualType ToTy, and
- /// their bit widths.
- SMTExprRef fromCast(const SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth,
- QualType FromTy, uint64_t FromBitWidth) {
- if ((FromTy->isIntegralOrEnumerationType() &&
- ToTy->isIntegralOrEnumerationType()) ||
- (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) ||
- (FromTy->isBlockPointerType() ^ ToTy->isBlockPointerType()) ||
- (FromTy->isReferenceType() ^ ToTy->isReferenceType())) {
-
- if (FromTy->isBooleanType()) {
- assert(ToBitWidth > 0 && "BitWidth must be positive!");
- return mkIte(Exp, mkBitvector(llvm::APSInt("1"), ToBitWidth),
- mkBitvector(llvm::APSInt("0"), ToBitWidth));
- }
-
- if (ToBitWidth > FromBitWidth)
- return FromTy->isSignedIntegerOrEnumerationType()
- ? mkBVSignExt(ToBitWidth - FromBitWidth, Exp)
- : mkBVZeroExt(ToBitWidth - FromBitWidth, Exp);
-
- if (ToBitWidth < FromBitWidth)
- return mkBVExtract(ToBitWidth - 1, 0, Exp);
-
- // Both are bitvectors with the same width, ignore the type cast
- return Exp;
- }
-
- if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) {
- if (ToBitWidth != FromBitWidth)
- return mkFPtoFP(Exp, getFloatSort(ToBitWidth));
-
- return Exp;
- }
-
- if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) {
- SMTSortRef Sort = getFloatSort(ToBitWidth);
- return FromTy->isSignedIntegerOrEnumerationType() ? mkFPtoSBV(Exp, Sort)
- : mkFPtoUBV(Exp, Sort);
- }
-
- if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType())
- return ToTy->isSignedIntegerOrEnumerationType()
- ? mkSBVtoFP(Exp, ToBitWidth)
- : mkUBVtoFP(Exp, ToBitWidth);
-
- llvm_unreachable("Unsupported explicit type cast!");
- }
-
- // Callback function for doCast parameter on APSInt type.
- llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy,
- uint64_t ToWidth, QualType FromTy,
- uint64_t FromWidth) {
- APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType());
- return TargetType.convert(V);
- }
-
- // Generate an SMTExprRef that represents the given symbolic expression.
- // Sets the hasComparison parameter if the expression has a comparison
- // operator.
- // Sets the RetTy parameter to the final return type after promotions and
- // casts.
- SMTExprRef getExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy = nullptr,
- bool *hasComparison = nullptr) {
- if (hasComparison) {
- *hasComparison = false;
- }
-
- return getSymExpr(Ctx, Sym, RetTy, hasComparison);
- }
-
- // Generate an SMTExprRef that compares the expression to zero.
- SMTExprRef getZeroExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType Ty,
- bool Assumption) {
-
- if (Ty->isRealFloatingType()) {
- llvm::APFloat Zero =
- llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty));
- return fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, fromAPFloat(Zero));
- }
-
- if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() ||
- Ty->isBlockPointerType() || Ty->isReferenceType()) {
-
- // Skip explicit comparison for boolean types
- bool isSigned = Ty->isSignedIntegerOrEnumerationType();
- if (Ty->isBooleanType())
- return Assumption ? fromUnOp(UO_LNot, Exp) : Exp;
-
- return fromBinOp(Exp, Assumption ? BO_EQ : BO_NE,
- fromInt("0", Ctx.getTypeSize(Ty)), isSigned);
- }
-
- llvm_unreachable("Unsupported type for zero value!");
- }
-
- // Recursive implementation to unpack and generate symbolic expression.
- // Sets the hasComparison and RetTy parameters. See getExpr().
- SMTExprRef getSymExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy,
- bool *hasComparison) {
- if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
- if (RetTy)
- *RetTy = Sym->getType();
-
- return fromData(SD->getSymbolID(), Sym->getType(),
- Ctx.getTypeSize(Sym->getType()));
- }
-
- if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
- if (RetTy)
- *RetTy = Sym->getType();
-
- QualType FromTy;
- SMTExprRef Exp =
- getSymExpr(Ctx, SC->getOperand(), &FromTy, hasComparison);
- // Casting an expression with a comparison invalidates it. Note that this
- // must occur after the recursive call above.
- // e.g. (signed char) (x > 0)
- if (hasComparison)
- *hasComparison = false;
- return getCastExpr(Ctx, Exp, FromTy, Sym->getType());
- }
-
- if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
- SMTExprRef Exp = getSymBinExpr(Ctx, BSE, hasComparison, RetTy);
- // Set the hasComparison parameter, in post-order traversal order.
- if (hasComparison)
- *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode());
- return Exp;
- }
-
- llvm_unreachable("Unsupported SymbolRef type!");
- }
-
- // Wrapper to generate SMTExprRef from SymbolCast data.
- SMTExprRef getCastExpr(ASTContext &Ctx, const SMTExprRef &Exp,
- QualType FromTy, QualType ToTy) {
- return fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy,
- Ctx.getTypeSize(FromTy));
- }
-
- // Wrapper to generate SMTExprRef from BinarySymExpr.
- // Sets the hasComparison and RetTy parameters. See getSMTExprRef().
- SMTExprRef getSymBinExpr(ASTContext &Ctx, const BinarySymExpr *BSE,
- bool *hasComparison, QualType *RetTy) {
- QualType LTy, RTy;
- BinaryOperator::Opcode Op = BSE->getOpcode();
-
- if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
- SMTExprRef LHS = getSymExpr(Ctx, SIE->getLHS(), &LTy, hasComparison);
- llvm::APSInt NewRInt;
- std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS());
- SMTExprRef RHS = fromAPSInt(NewRInt);
- return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
- }
-
- if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
- llvm::APSInt NewLInt;
- std::tie(NewLInt, LTy) = fixAPSInt(Ctx, ISE->getLHS());
- SMTExprRef LHS = fromAPSInt(NewLInt);
- SMTExprRef RHS = getSymExpr(Ctx, ISE->getRHS(), &RTy, hasComparison);
- return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
- }
-
- if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
- SMTExprRef LHS = getSymExpr(Ctx, SSM->getLHS(), &LTy, hasComparison);
- SMTExprRef RHS = getSymExpr(Ctx, SSM->getRHS(), &RTy, hasComparison);
- return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
- }
-
- llvm_unreachable("Unsupported BinarySymExpr type!");
- }
-
- // Wrapper to generate SMTExprRef from unpacked binary symbolic expression.
- // Sets the RetTy parameter. See getSMTExprRef().
- SMTExprRef getBinExpr(ASTContext &Ctx, const SMTExprRef &LHS, QualType LTy,
- BinaryOperator::Opcode Op, const SMTExprRef &RHS,
- QualType RTy, QualType *RetTy) {
- SMTExprRef NewLHS = LHS;
- SMTExprRef NewRHS = RHS;
- doTypeConversion(Ctx, NewLHS, NewRHS, LTy, RTy);
-
- // Update the return type parameter if the output type has changed.
- if (RetTy) {
- // A boolean result can be represented as an integer type in C/C++, but at
- // this point we only care about the SMT sorts. Set it as a boolean type
- // to avoid subsequent SMT errors.
- if (BinaryOperator::isComparisonOp(Op) ||
- BinaryOperator::isLogicalOp(Op)) {
- *RetTy = Ctx.BoolTy;
- } else {
- *RetTy = LTy;
- }
-
- // If the two operands are pointers and the operation is a subtraction,
- // the result is of type ptrdiff_t, which is signed
- if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) {
- *RetTy = Ctx.getPointerDiffType();
- }
- }
-
- return LTy->isRealFloatingType()
- ? fromFloatBinOp(NewLHS, Op, NewRHS)
- : fromBinOp(NewLHS, Op, NewRHS,
- LTy->isSignedIntegerOrEnumerationType());
- }
-
- // Wrapper to generate SMTExprRef from a range. If From == To, an equality
- // will be created instead.
- SMTExprRef getRangeExpr(ASTContext &Ctx, SymbolRef Sym,
- const llvm::APSInt &From, const llvm::APSInt &To,
- bool InRange) {
- // Convert lower bound
- QualType FromTy;
- llvm::APSInt NewFromInt;
- std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From);
- SMTExprRef FromExp = fromAPSInt(NewFromInt);
-
- // Convert symbol
- QualType SymTy;
- SMTExprRef Exp = getExpr(Ctx, Sym, &SymTy);
-
- // Construct single (in)equality
- if (From == To)
- return getBinExpr(Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp,
- FromTy, /*RetTy=*/nullptr);
-
- QualType ToTy;
- llvm::APSInt NewToInt;
- std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To);
- SMTExprRef ToExp = fromAPSInt(NewToInt);
- assert(FromTy == ToTy && "Range values have different types!");
-
- // Construct two (in)equalities, and a logical and/or
- SMTExprRef LHS = getBinExpr(Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT,
- FromExp, FromTy, /*RetTy=*/nullptr);
- SMTExprRef RHS =
- getBinExpr(Ctx, Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy,
- /*RetTy=*/nullptr);
-
- return fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS,
- SymTy->isSignedIntegerOrEnumerationType());
- }
-
- // Recover the QualType of an APSInt.
- // TODO: Refactor to put elsewhere
- QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int) {
- return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned());
- }
-
- // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1.
- std::pair<llvm::APSInt, QualType> fixAPSInt(ASTContext &Ctx,
- const llvm::APSInt &Int) {
- llvm::APSInt NewInt;
-
- // FIXME: This should be a cast from a 1-bit integer type to a boolean type,
- // but the former is not available in Clang. Instead, extend the APSInt
- // directly.
- if (Int.getBitWidth() == 1 && getAPSIntType(Ctx, Int).isNull()) {
- NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy));
- } else
- NewInt = Int;
-
- return std::make_pair(NewInt, getAPSIntType(Ctx, NewInt));
- }
-
- // Perform implicit type conversion on binary symbolic expressions.
- // May modify all input parameters.
- // TODO: Refactor to use built-in conversion functions
- void doTypeConversion(ASTContext &Ctx, SMTExprRef &LHS, SMTExprRef &RHS,
- QualType &LTy, QualType &RTy) {
- assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!");
-
- // Perform type conversion
- if ((LTy->isIntegralOrEnumerationType() &&
- RTy->isIntegralOrEnumerationType()) &&
- (LTy->isArithmeticType() && RTy->isArithmeticType())) {
- doIntTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy, RHS,
- RTy);
- return;
- }
-
- if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) {
- doFloatTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy,
- RHS, RTy);
- return;
- }
-
- if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) ||
- (LTy->isBlockPointerType() || RTy->isBlockPointerType()) ||
- (LTy->isReferenceType() || RTy->isReferenceType())) {
- // TODO: Refactor to Sema::FindCompositePointerType(), and
- // Sema::CheckCompareOperands().
-
- uint64_t LBitWidth = Ctx.getTypeSize(LTy);
- uint64_t RBitWidth = Ctx.getTypeSize(RTy);
-
- // Cast the non-pointer type to the pointer type.
- // TODO: Be more strict about this.
- if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) ||
- (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) ||
- (LTy->isReferenceType() ^ RTy->isReferenceType())) {
- if (LTy->isNullPtrType() || LTy->isBlockPointerType() ||
- LTy->isReferenceType()) {
- LHS = fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- } else {
- RHS = fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- }
- }
-
- // Cast the void pointer type to the non-void pointer type.
- // For void types, this assumes that the casted value is equal to the
- // value of the original pointer, and does not account for alignment
- // requirements.
- if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) {
- assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) &&
- "Pointer types have different bitwidths!");
- if (RTy->isVoidPointerType())
- RTy = LTy;
- else
- LTy = RTy;
- }
-
- if (LTy == RTy)
- return;
- }
-
- // Fallback: for the solver, assume that these types don't really matter
- if ((LTy.getCanonicalType() == RTy.getCanonicalType()) ||
- (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) {
- LTy = RTy;
- return;
- }
-
- // TODO: Refine behavior for invalid type casts
- }
-
- // Perform implicit integer type conversion.
- // May modify all input parameters.
- // TODO: Refactor to use Sema::handleIntegerConversion()
- template <typename T, T (SMTSolver::*doCast)(const T &, QualType, uint64_t,
- QualType, uint64_t)>
- void doIntTypeConversion(ASTContext &Ctx, T &LHS, QualType &LTy, T &RHS,
- QualType &RTy) {
-
- uint64_t LBitWidth = Ctx.getTypeSize(LTy);
- uint64_t RBitWidth = Ctx.getTypeSize(RTy);
-
- assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!");
- // Always perform integer promotion before checking type equality.
- // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion
- if (LTy->isPromotableIntegerType()) {
- QualType NewTy = Ctx.getPromotedIntegerType(LTy);
- uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
- LHS = (this->*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth);
- LTy = NewTy;
- LBitWidth = NewBitWidth;
- }
- if (RTy->isPromotableIntegerType()) {
- QualType NewTy = Ctx.getPromotedIntegerType(RTy);
- uint64_t NewBitWidth = Ctx.getTypeSize(NewTy);
- RHS = (this->*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth);
- RTy = NewTy;
- RBitWidth = NewBitWidth;
- }
-
- if (LTy == RTy)
- return;
-
- // Perform integer type conversion
- // Note: Safe to skip updating bitwidth because this must terminate
- bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType();
- bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType();
-
- int order = Ctx.getIntegerTypeOrder(LTy, RTy);
- if (isLSignedTy == isRSignedTy) {
- // Same signedness; use the higher-ranked type
- if (order == 1) {
- RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else {
- LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- }
- } else if (order != (isLSignedTy ? 1 : -1)) {
- // The unsigned type has greater than or equal rank to the
- // signed type, so use the unsigned type
- if (isRSignedTy) {
- RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else {
- LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- }
- } else if (LBitWidth != RBitWidth) {
- // The two types are different widths; if we are here, that
- // means the signed type is larger than the unsigned type, so
- // use the signed type.
- if (isLSignedTy) {
- RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else {
- LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- }
- } else {
- // The signed type is higher-ranked than the unsigned type,
- // but isn't actually any bigger (like unsigned int and long
- // on most 32-bit systems). Use the unsigned type corresponding
- // to the signed type.
- QualType NewTy =
- Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy);
- RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = NewTy;
- LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = NewTy;
- }
- }
-
- // Perform implicit floating-point type conversion.
- // May modify all input parameters.
- // TODO: Refactor to use Sema::handleFloatConversion()
- template <typename T, T (SMTSolver::*doCast)(const T &, QualType, uint64_t,
- QualType, uint64_t)>
- void doFloatTypeConversion(ASTContext &Ctx, T &LHS, QualType &LTy, T &RHS,
- QualType &RTy) {
-
- uint64_t LBitWidth = Ctx.getTypeSize(LTy);
- uint64_t RBitWidth = Ctx.getTypeSize(RTy);
-
- // Perform float-point type promotion
- if (!LTy->isRealFloatingType()) {
- LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- LBitWidth = RBitWidth;
- }
- if (!RTy->isRealFloatingType()) {
- RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- RBitWidth = LBitWidth;
- }
-
- if (LTy == RTy)
- return;
-
- // If we have two real floating types, convert the smaller operand to the
- // bigger result
- // Note: Safe to skip updating bitwidth because this must terminate
- int order = Ctx.getFloatingTypeOrder(LTy, RTy);
- if (order > 0) {
- RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
- RTy = LTy;
- } else if (order == 0) {
- LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
- LTy = RTy;
- } else {
- llvm_unreachable("Unsupported floating-point type cast!");
- }
- }
-
// Returns a boolean sort.
virtual SMTSortRef getBoolSort() = 0;
@@ -906,23 +226,23 @@ public:
/// operation
virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0;
- /// Creates a floating-point conversion from floatint-point to signed
- /// bitvector operation
- virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From,
- const SMTSortRef &To) = 0;
-
- /// Creates a floating-point conversion from floatint-point to unsigned
- /// bitvector operation
- virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From,
- const SMTSortRef &To) = 0;
-
/// Creates a floating-point conversion from signed bitvector to
/// floatint-point operation
- virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0;
+ virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
/// Creates a floating-point conversion from unsigned bitvector to
/// floatint-point operation
- virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0;
+ virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to signed
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to unsigned
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) = 0;
/// Creates a new symbol, given a name and a sort
virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0;
@@ -953,24 +273,8 @@ public:
virtual bool getInterpretation(const SMTExprRef &Exp,
llvm::APFloat &Float) = 0;
- /// Construct an SMTExprRef value from a boolean.
- virtual SMTExprRef fromBoolean(const bool Bool) = 0;
-
- /// Construct an SMTExprRef value from a finite APFloat.
- virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float) = 0;
-
- /// Construct an SMTExprRef value from an APSInt.
- virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int) = 0;
-
- /// Construct an SMTExprRef value from an integer.
- virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth) = 0;
-
- /// Construct an SMTExprRef from a SymbolData.
- virtual SMTExprRef fromData(const SymbolID ID, const QualType &Ty,
- uint64_t BitWidth) = 0;
-
/// Check if the constraints are satisfiable
- virtual ConditionTruthVal check() const = 0;
+ virtual Optional<bool> check() const = 0;
/// Push the current solver state
virtual void push() = 0;
@@ -979,7 +283,10 @@ public:
virtual void pop(unsigned NumStates = 1) = 0;
/// Reset the solver and remove all constraints.
- virtual void reset() const = 0;
+ virtual void reset() = 0;
+
+ /// Checks if the solver supports floating-points.
+ virtual bool isFPSupported() = 0;
virtual void print(raw_ostream &OS) const = 0;
};
@@ -988,7 +295,7 @@ public:
using SMTSolverRef = std::shared_ptr<SMTSolver>;
/// Convenience method to create and Z3Solver object
-std::unique_ptr<SMTSolver> CreateZ3Solver();
+SMTSolverRef CreateZ3Solver();
} // namespace ento
} // namespace clang
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 865014b22830..c9e284a1a3e8 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -139,8 +139,8 @@ public:
virtual SVal simplifySVal(ProgramStateRef State, SVal Val) = 0;
/// Constructs a symbolic expression for two non-location values.
- SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op,
- NonLoc lhs, NonLoc rhs, QualType resultTy);
+ SVal makeSymExprValNN(BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy);
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
SVal lhs, SVal rhs, QualType type);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 1b79bfc3f8cf..0efe96f67f8e 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -530,9 +530,7 @@ public:
return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data));
}
- bool isNullMemberPointer() const {
- return getPTMData().isNull();
- }
+ bool isNullMemberPointer() const;
const DeclaratorDecl *getDecl() const;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index fc072a380074..f49f761c77eb 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -130,6 +130,8 @@ public:
/// used to query and manipulate MemRegion objects.
MemRegionManager& getRegionManager() { return MRMgr; }
+ SValBuilder& getSValBuilder() { return svalBuilder; }
+
virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
}
@@ -252,19 +254,18 @@ public:
virtual bool scanReachableSymbols(Store S, const MemRegion *R,
ScanReachableSymbols &Visitor) = 0;
- virtual void print(Store store, raw_ostream &Out,
- const char* nl, const char *sep) = 0;
+ virtual void print(Store store, raw_ostream &Out, const char* nl) = 0;
class BindingsHandler {
public:
virtual ~BindingsHandler();
+ /// \return whether the iteration should continue.
virtual bool HandleBinding(StoreManager& SMgr, Store store,
const MemRegion *region, SVal val) = 0;
};
- class FindUniqueBinding :
- public BindingsHandler {
+ class FindUniqueBinding : public BindingsHandler {
SymbolRef Sym;
const MemRegion* Binding = nullptr;
bool First = true;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index d6aa4feddff2..d745b0f51ab0 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -72,7 +72,7 @@ public:
/// Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- virtual void processBranch(const Stmt *Condition, const Stmt *Term,
+ virtual void processBranch(const Stmt *Condition,
NodeBuilderContext& BuilderCtx,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
@@ -156,7 +156,6 @@ public:
notifyCheckersOfPointerEscape(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &HTraits) = 0;
@@ -167,7 +166,7 @@ public:
/// Called by CoreEngine when the analysis worklist is either empty or the
// maximum number of analysis steps have been reached.
- virtual void processEndWorklist(bool hasWorkRemaining) = 0;
+ virtual void processEndWorklist() = 0;
};
} // end GR namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 074551962607..d02a8abd1148 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -309,7 +309,10 @@ protected:
BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t)
: SymExpr(k), Op(op), T(t) {
assert(classof(this));
- assert(isValidTypeForSymbol(t));
+ // Binary expressions are results of arithmetic. Pointer arithmetic is not
+ // handled by binary expressions, but it is instead handled by applying
+ // sub-regions to regions.
+ assert(isValidTypeForSymbol(t) && !Loc::isLocType(t));
}
public:
@@ -555,7 +558,6 @@ class SymbolReaper {
SymbolMapTy TheLiving;
SymbolSetTy MetadataInUse;
- SymbolSetTy TheDead;
RegionSetTy RegionRoots;
@@ -600,21 +602,6 @@ public:
/// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
void markInUse(SymbolRef sym);
- /// If a symbol is known to be live, marks the symbol as live.
- ///
- /// Otherwise, if the symbol cannot be proven live, it is marked as dead.
- /// Returns true if the symbol is dead, false if live.
- bool maybeDead(SymbolRef sym);
-
- using dead_iterator = SymbolSetTy::const_iterator;
-
- dead_iterator dead_begin() const { return TheDead.begin(); }
- dead_iterator dead_end() const { return TheDead.end(); }
-
- bool hasDeadSymbols() const {
- return !TheDead.empty();
- }
-
using region_iterator = RegionSetTy::const_iterator;
region_iterator region_begin() const { return RegionRoots.begin(); }
@@ -623,9 +610,9 @@ public:
/// Returns whether or not a symbol has been confirmed dead.
///
/// This should only be called once all marking of dead symbols has completed.
- /// (For checkers, this means only in the evalDeadSymbols callback.)
- bool isDead(SymbolRef sym) const {
- return TheDead.count(sym);
+ /// (For checkers, this means only in the checkDeadSymbols callback.)
+ bool isDead(SymbolRef sym) {
+ return !isLive(sym);
}
void markLive(const MemRegion *region);
@@ -654,7 +641,7 @@ public:
/// The method returns \c true if symbols should continue be scanned and \c
/// false otherwise.
virtual bool VisitSymbol(SymbolRef sym) = 0;
- virtual bool VisitMemRegion(const MemRegion *region) { return true; }
+ virtual bool VisitMemRegion(const MemRegion *) { return true; }
};
} // namespace ento
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
index ce19b7131d42..8218fb1eeafe 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
@@ -34,10 +34,7 @@ using TaintMapImpl = llvm::ImmutableMap<SymbolRef, TaintTagType>;
template<> struct ProgramStateTrait<TaintMap>
: public ProgramStatePartialTrait<TaintMapImpl> {
- static void *GDMIndex() {
- static int index = 0;
- return &index;
- }
+ static void *GDMIndex();
};
/// The GDM component mapping derived symbols' parent symbols to their
@@ -49,10 +46,7 @@ using DerivedSymTaintImpl = llvm::ImmutableMap<SymbolRef, TaintedSubRegions>;
template<> struct ProgramStateTrait<DerivedSymTaint>
: public ProgramStatePartialTrait<DerivedSymTaintImpl> {
- static void *GDMIndex() {
- static int index;
- return &index;
- }
+ static void *GDMIndex();
};
class TaintManager {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index 07edd35ff944..ef3c2694b283 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -85,6 +85,7 @@ public:
static std::unique_ptr<WorkList> makeBFSBlockDFSContents();
static std::unique_ptr<WorkList> makeUnexploredFirst();
static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue();
+ static std::unique_ptr<WorkList> makeUnexploredFirstPriorityLocationQueue();
};
} // end ento namespace
diff --git a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
new file mode 100644
index 000000000000..4fcaa794c17b
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
@@ -0,0 +1,798 @@
+//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines summaries implementation for retain counting, which
+// implements a reference count checker for Core Foundation and Cocoa
+// on (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER
+#define LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/SelectorExtras.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "llvm/ADT/STLExtras.h"
+
+//===----------------------------------------------------------------------===//
+// Adapters for FoldingSet.
+//===----------------------------------------------------------------------===//
+
+using namespace clang;
+using namespace ento;
+
+namespace clang {
+namespace ento {
+
+/// Determines the object kind of a tracked object.
+enum class ObjKind {
+ /// Indicates that the tracked object is a CF object.
+ CF,
+
+ /// Indicates that the tracked object is an Objective-C object.
+ ObjC,
+
+ /// Indicates that the tracked object could be a CF or Objective-C object.
+ AnyObj,
+
+ /// Indicates that the tracked object is a generalized object.
+ Generalized,
+
+ /// Indicates that the tracking object is a descendant of a
+ /// referenced-counted OSObject, used in the Darwin kernel.
+ OS
+};
+
+enum ArgEffectKind {
+ /// There is no effect.
+ DoNothing,
+
+ /// The argument is treated as if an -autorelease message had been sent to
+ /// the referenced object.
+ Autorelease,
+
+ /// The argument is treated as if the referenced object was deallocated.
+ Dealloc,
+
+ /// The argument has its reference count decreased by 1.
+ DecRef,
+
+ /// The argument has its reference count decreased by 1 to model
+ /// a transferred bridge cast under ARC.
+ DecRefBridgedTransferred,
+
+ /// The argument has its reference count increased by 1.
+ IncRef,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +0 value.
+ UnretainedOutParameter,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value.
+ RetainedOutParameter,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value iff the return code is zero.
+ RetainedOutParameterOnZero,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value iff the return code is non-zero.
+ RetainedOutParameterOnNonZero,
+
+ /// The argument is treated as potentially escaping, meaning that
+ /// even when its reference count hits 0 it should be treated as still
+ /// possibly being alive as someone else *may* be holding onto the object.
+ MayEscape,
+
+ /// All typestate tracking of the object ceases. This is usually employed
+ /// when the effect of the call is completely unknown.
+ StopTracking,
+
+ /// All typestate tracking of the object ceases. Unlike StopTracking,
+ /// this is also enforced when the method body is inlined.
+ ///
+ /// In some cases, we obtain a better summary for this checker
+ /// by looking at the call site than by inlining the function.
+ /// Signifies that we should stop tracking the symbol even if
+ /// the function is inlined.
+ StopTrackingHard,
+
+ /// Performs the combined functionality of DecRef and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefAndStopTrackingHard,
+};
+
+/// An ArgEffect summarizes the retain count behavior on an argument or receiver
+/// to a function or method.
+class ArgEffect {
+ ArgEffectKind K;
+ ObjKind O;
+public:
+ explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
+ : K(K), O(O) {}
+
+ ArgEffectKind getKind() const { return K; }
+ ObjKind getObjKind() const { return O; }
+
+ ArgEffect withKind(ArgEffectKind NewK) {
+ return ArgEffect(NewK, O);
+ }
+
+ bool operator==(const ArgEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+};
+
+/// RetEffect summarizes a call's retain/release behavior with respect
+/// to its return value.
+class RetEffect {
+public:
+ enum Kind {
+ /// Indicates that no retain count information is tracked for
+ /// the return value.
+ NoRet,
+
+ /// Indicates that the returned value is an owned (+1) symbol.
+ OwnedSymbol,
+
+ /// Indicates that the returned value is an object with retain count
+ /// semantics but that it is not owned (+0). This is the default
+ /// for getters, etc.
+ NotOwnedSymbol,
+
+ /// Indicates that the return value is an owned object when the
+ /// receiver is also a tracked object.
+ OwnedWhenTrackedReceiver,
+
+ // Treat this function as returning a non-tracked symbol even if
+ // the function has been inlined. This is used where the call
+ // site summary is more precise than the summary indirectly produced
+ // by inlining the function
+ NoRetHard
+ };
+
+private:
+ Kind K;
+ ObjKind O;
+
+ RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
+
+public:
+ Kind getKind() const { return K; }
+
+ ObjKind getObjKind() const { return O; }
+
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
+ }
+
+ bool notOwned() const {
+ return K == NotOwnedSymbol;
+ }
+
+ bool operator==(const RetEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+
+ static RetEffect MakeOwnedWhenTrackedReceiver() {
+ return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
+ }
+
+ static RetEffect MakeOwned(ObjKind o) {
+ return RetEffect(OwnedSymbol, o);
+ }
+ static RetEffect MakeNotOwned(ObjKind o) {
+ return RetEffect(NotOwnedSymbol, o);
+ }
+ static RetEffect MakeNoRet() {
+ return RetEffect(NoRet);
+ }
+ static RetEffect MakeNoRetHard() {
+ return RetEffect(NoRetHard);
+ }
+};
+
+/// Encapsulates the retain count semantics on the arguments, return value,
+/// and receiver (if any) of a function/method call.
+///
+/// Note that construction of these objects is not highly efficient. That
+/// is okay for clients where creating these objects isn't really a bottleneck.
+/// The purpose of the API is to provide something simple. The actual
+/// static analyzer checker that implements retain/release typestate
+/// tracking uses something more efficient.
+class CallEffects {
+ llvm::SmallVector<ArgEffect, 10> Args;
+ RetEffect Ret;
+ ArgEffect Receiver;
+
+ CallEffects(const RetEffect &R,
+ ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj))
+ : Ret(R), Receiver(Receiver) {}
+
+public:
+ /// Returns the argument effects for a call.
+ ArrayRef<ArgEffect> getArgs() const { return Args; }
+
+ /// Returns the effects on the receiver.
+ ArgEffect getReceiver() const { return Receiver; }
+
+ /// Returns the effect on the return value.
+ RetEffect getReturnValue() const { return Ret; }
+
+ /// Return the CallEfect for a given Objective-C method.
+ static CallEffects getEffect(const ObjCMethodDecl *MD);
+
+ /// Return the CallEfect for a given C/C++ function.
+ static CallEffects getEffect(const FunctionDecl *FD);
+};
+
+/// A key identifying a summary.
+class ObjCSummaryKey {
+ IdentifierInfo* II;
+ Selector S;
+public:
+ ObjCSummaryKey(IdentifierInfo* ii, Selector s)
+ : II(ii), S(s) {}
+
+ ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
+ : II(d ? d->getIdentifier() : nullptr), S(s) {}
+
+ ObjCSummaryKey(Selector s)
+ : II(nullptr), S(s) {}
+
+ IdentifierInfo *getIdentifier() const { return II; }
+ Selector getSelector() const { return S; }
+};
+
+} // end namespace ento
+} // end namespace clang
+
+
+namespace llvm {
+
+template <> struct FoldingSetTrait<ArgEffect> {
+static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
+ ID.AddInteger((unsigned) X.getKind());
+ ID.AddInteger((unsigned) X.getObjKind());
+}
+};
+template <> struct FoldingSetTrait<RetEffect> {
+ static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
+ ID.AddInteger((unsigned) X.getKind());
+ ID.AddInteger((unsigned) X.getObjKind());
+}
+};
+
+template <> struct DenseMapInfo<ObjCSummaryKey> {
+ static inline ObjCSummaryKey getEmptyKey() {
+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
+ DenseMapInfo<Selector>::getEmptyKey());
+ }
+
+ static inline ObjCSummaryKey getTombstoneKey() {
+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
+ DenseMapInfo<Selector>::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const ObjCSummaryKey &V) {
+ typedef std::pair<IdentifierInfo*, Selector> PairTy;
+ return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
+ V.getSelector()));
+ }
+
+ static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
+ return LHS.getIdentifier() == RHS.getIdentifier() &&
+ LHS.getSelector() == RHS.getSelector();
+ }
+
+};
+
+} // end llvm namespace
+
+
+namespace clang {
+namespace ento {
+
+/// ArgEffects summarizes the effects of a function/method call on all of
+/// its arguments.
+typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
+
+/// Summary for a function with respect to ownership changes.
+class RetainSummary {
+ /// Args - a map of (index, ArgEffect) pairs, where index
+ /// specifies the argument (starting from 0). This can be sparsely
+ /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
+ ArgEffects Args;
+
+ /// DefaultArgEffect - The default ArgEffect to apply to arguments that
+ /// do not have an entry in Args.
+ ArgEffect DefaultArgEffect;
+
+ /// Receiver - If this summary applies to an Objective-C message expression,
+ /// this is the effect applied to the state of the receiver.
+ ArgEffect Receiver;
+
+ /// Effect on "this" pointer - applicable only to C++ method calls.
+ ArgEffect This;
+
+ /// Ret - The effect on the return value. Used to indicate if the
+ /// function/method call returns a new tracked symbol.
+ RetEffect Ret;
+
+public:
+ RetainSummary(ArgEffects A,
+ RetEffect R,
+ ArgEffect defaultEff,
+ ArgEffect ReceiverEff,
+ ArgEffect ThisEff)
+ : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
+ This(ThisEff), Ret(R) {}
+
+ /// getArg - Return the argument effect on the argument specified by
+ /// idx (starting from 0).
+ ArgEffect getArg(unsigned idx) const {
+ if (const ArgEffect *AE = Args.lookup(idx))
+ return *AE;
+
+ return DefaultArgEffect;
+ }
+
+ void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
+ Args = af.add(Args, idx, e);
+ }
+
+ /// setDefaultArgEffect - Set the default argument effect.
+ void setDefaultArgEffect(ArgEffect E) {
+ DefaultArgEffect = E;
+ }
+
+ /// getRetEffect - Returns the effect on the return value of the call.
+ RetEffect getRetEffect() const { return Ret; }
+
+ /// setRetEffect - Set the effect of the return value of the call.
+ void setRetEffect(RetEffect E) { Ret = E; }
+
+
+ /// Sets the effect on the receiver of the message.
+ void setReceiverEffect(ArgEffect e) { Receiver = e; }
+
+ /// getReceiverEffect - Returns the effect on the receiver of the call.
+ /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
+ ArgEffect getReceiverEffect() const { return Receiver; }
+
+ /// \return the effect on the "this" receiver of the method call.
+ /// This is only meaningful if the summary applies to CXXMethodDecl*.
+ ArgEffect getThisEffect() const { return This; }
+
+ /// Set the effect of the method on "this".
+ void setThisEffect(ArgEffect e) { This = e; }
+
+ bool isNoop() const {
+ return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
+ && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
+ && Args.isEmpty();
+ }
+
+ /// Test if two retain summaries are identical. Note that merely equivalent
+ /// summaries are not necessarily identical (for example, if an explicit
+ /// argument effect matches the default effect).
+ bool operator==(const RetainSummary &Other) const {
+ return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
+ Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
+ }
+
+ /// Profile this summary for inclusion in a FoldingSet.
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.Add(Args);
+ ID.Add(DefaultArgEffect);
+ ID.Add(Receiver);
+ ID.Add(This);
+ ID.Add(Ret);
+ }
+
+ /// A retain summary is simple if it has no ArgEffects other than the default.
+ bool isSimple() const {
+ return Args.isEmpty();
+ }
+
+ ArgEffects getArgEffects() const { return Args; }
+
+private:
+ ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
+
+ friend class RetainSummaryManager;
+};
+
+class ObjCSummaryCache {
+ typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
+ MapTy M;
+public:
+ ObjCSummaryCache() {}
+
+ const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
+ // Do a lookup with the (D,S) pair. If we find a match return
+ // the iterator.
+ ObjCSummaryKey K(D, S);
+ MapTy::iterator I = M.find(K);
+
+ if (I != M.end())
+ return I->second;
+ if (!D)
+ return nullptr;
+
+ // Walk the super chain. If we find a hit with a parent, we'll end
+ // up returning that summary. We actually allow that key (null,S), as
+ // we cache summaries for the null ObjCInterfaceDecl* to allow us to
+ // generate initial summaries without having to worry about NSObject
+ // being declared.
+ // FIXME: We may change this at some point.
+ for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
+ if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
+ break;
+
+ if (!C)
+ return nullptr;
+ }
+
+ // Cache the summary with original key to make the next lookup faster
+ // and return the iterator.
+ const RetainSummary *Summ = I->second;
+ M[K] = Summ;
+ return Summ;
+ }
+
+ const RetainSummary *find(IdentifierInfo* II, Selector S) {
+ // FIXME: Class method lookup. Right now we don't have a good way
+ // of going between IdentifierInfo* and the class hierarchy.
+ MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
+
+ if (I == M.end())
+ I = M.find(ObjCSummaryKey(S));
+
+ return I == M.end() ? nullptr : I->second;
+ }
+
+ const RetainSummary *& operator[](ObjCSummaryKey K) {
+ return M[K];
+ }
+
+ const RetainSummary *& operator[](Selector S) {
+ return M[ ObjCSummaryKey(S) ];
+ }
+};
+
+class RetainSummaryTemplate;
+
+class RetainSummaryManager {
+ typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
+ FuncSummariesTy;
+
+ typedef ObjCSummaryCache ObjCMethodSummariesTy;
+
+ typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
+
+ /// Ctx - The ASTContext object for the analyzed ASTs.
+ ASTContext &Ctx;
+
+ /// Records whether or not the analyzed code runs in ARC mode.
+ const bool ARCEnabled;
+
+ /// Track Objective-C and CoreFoundation objects.
+ const bool TrackObjCAndCFObjects;
+
+ /// Track sublcasses of OSObject.
+ const bool TrackOSObjects;
+
+ /// FuncSummaries - A map from FunctionDecls to summaries.
+ FuncSummariesTy FuncSummaries;
+
+ /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
+ /// to summaries.
+ ObjCMethodSummariesTy ObjCClassMethodSummaries;
+
+ /// ObjCMethodSummaries - A map from selectors to summaries.
+ ObjCMethodSummariesTy ObjCMethodSummaries;
+
+ /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
+ /// and all other data used by the checker.
+ llvm::BumpPtrAllocator BPAlloc;
+
+ /// AF - A factory for ArgEffects objects.
+ ArgEffects::Factory AF;
+
+ /// ObjCAllocRetE - Default return effect for methods returning Objective-C
+ /// objects.
+ RetEffect ObjCAllocRetE;
+
+ /// ObjCInitRetE - Default return effect for init methods returning
+ /// Objective-C objects.
+ RetEffect ObjCInitRetE;
+
+ /// SimpleSummaries - Used for uniquing summaries that don't have special
+ /// effects.
+ llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
+
+ /// Create an OS object at +1.
+ const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
+
+ /// Get an OS object at +0.
+ const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
+
+ /// Increment the reference count on OS object.
+ const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
+
+ /// Decrement the reference count on OS object.
+ const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
+
+ /// Free the OS object.
+ const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
+
+ const RetainSummary *getUnarySummary(const FunctionType* FT,
+ ArgEffectKind AE);
+
+ const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
+ const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
+ const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
+
+ const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
+
+ const RetainSummary *
+ getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
+ ArgEffect ReceiverEff = ArgEffect(DoNothing),
+ ArgEffect DefaultEff = ArgEffect(MayEscape),
+ ArgEffect ThisEff = ArgEffect(DoNothing)) {
+ RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
+ return getPersistentSummary(Summ);
+ }
+
+ const RetainSummary *getDoNothingSummary() {
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ArgEffects(AF.getEmptyMap()),
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ }
+
+ const RetainSummary *getDefaultSummary() {
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ArgEffects(AF.getEmptyMap()),
+ ArgEffect(DoNothing), ArgEffect(MayEscape));
+ }
+
+ const RetainSummary *getPersistentStopSummary() {
+ return getPersistentSummary(
+ RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
+ ArgEffect(StopTracking), ArgEffect(StopTracking));
+ }
+
+ void InitializeClassMethodSummaries();
+ void InitializeMethodSummaries();
+
+ void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
+ ObjCClassMethodSummaries[S] = Summ;
+ }
+
+ void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
+ ObjCMethodSummaries[S] = Summ;
+ }
+
+ void addClassMethSummary(const char* Cls, const char* name,
+ const RetainSummary *Summ, bool isNullary = true) {
+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+ Selector S = isNullary ? GetNullarySelector(name, Ctx)
+ : GetUnarySelector(name, Ctx);
+ ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ void addInstMethSummary(const char* Cls, const char* nullaryName,
+ const RetainSummary *Summ) {
+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+ Selector S = GetNullarySelector(nullaryName, Ctx);
+ ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ template <typename... Keywords>
+ void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
+ const RetainSummary *Summ, Keywords *... Kws) {
+ Selector S = getKeywordSelector(Ctx, Kws...);
+ Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ template <typename... Keywords>
+ void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
+ Keywords *... Kws) {
+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
+ }
+
+ template <typename... Keywords>
+ void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
+ Keywords *... Kws) {
+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
+ Kws...);
+ }
+
+ template <typename... Keywords>
+ void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
+ Keywords *... Kws) {
+ addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
+ }
+
+ const RetainSummary * generateSummary(const FunctionDecl *FD,
+ bool &AllowAnnotations);
+
+ /// Return a summary for OSObject, or nullptr if not found.
+ const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
+ StringRef FName, QualType RetTy);
+
+ /// Return a summary for Objective-C or CF object, or nullptr if not found.
+ const RetainSummary *getSummaryForObjCOrCFObject(
+ const FunctionDecl *FD,
+ StringRef FName,
+ QualType RetTy,
+ const FunctionType *FT,
+ bool &AllowAnnotations);
+
+ /// Apply the annotation of {@code pd} in function {@code FD}
+ /// to the resulting summary stored in out-parameter {@code Template}.
+ /// \return whether an annotation was applied.
+ bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
+ const NamedDecl *FD,
+ RetainSummaryTemplate &Template);
+
+public:
+ RetainSummaryManager(ASTContext &ctx,
+ bool usesARC,
+ bool trackObjCAndCFObjects,
+ bool trackOSObjects)
+ : Ctx(ctx),
+ ARCEnabled(usesARC),
+ TrackObjCAndCFObjects(trackObjCAndCFObjects),
+ TrackOSObjects(trackOSObjects),
+ AF(BPAlloc),
+ ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC)
+ : RetEffect::MakeOwned(ObjKind::ObjC)),
+ ObjCInitRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC)
+ : RetEffect::MakeOwnedWhenTrackedReceiver()) {
+ InitializeClassMethodSummaries();
+ InitializeMethodSummaries();
+ }
+
+ enum class BehaviorSummary {
+ // Function does not return.
+ NoOp,
+
+ // Function returns the first argument.
+ Identity,
+
+ // Function either returns zero, or the input parameter.
+ IdentityOrZero
+ };
+
+ Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD,
+ bool &hasTrustedImplementationAnnotation);
+
+ bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
+
+ const RetainSummary *getSummary(const CallEvent &Call,
+ QualType ReceiverType=QualType());
+
+ const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
+
+ const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy,
+ ObjCMethodSummariesTy &CachedSummaries);
+
+ const RetainSummary *
+ getInstanceMethodSummary(const ObjCMethodCall &M,
+ QualType ReceiverType);
+
+ const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
+ assert(!M.isInstanceMessage());
+ const ObjCInterfaceDecl *Class = M.getReceiverInterface();
+
+ return getMethodSummary(M.getSelector(), Class, M.getDecl(),
+ M.getResultType(), ObjCClassMethodSummaries);
+ }
+
+ /// getMethodSummary - This version of getMethodSummary is used to query
+ /// the summary for the current method being analyzed.
+ const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
+ const ObjCInterfaceDecl *ID = MD->getClassInterface();
+ Selector S = MD->getSelector();
+ QualType ResultTy = MD->getReturnType();
+
+ ObjCMethodSummariesTy *CachedSummaries;
+ if (MD->isInstanceMethod())
+ CachedSummaries = &ObjCMethodSummaries;
+ else
+ CachedSummaries = &ObjCClassMethodSummaries;
+
+ return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
+ }
+
+ const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
+ Selector S, QualType RetTy);
+
+ /// Determine if there is a special return effect for this function or method.
+ Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
+ const Decl *D);
+
+ void updateSummaryFromAnnotations(const RetainSummary *&Summ,
+ const ObjCMethodDecl *MD);
+
+ void updateSummaryFromAnnotations(const RetainSummary *&Summ,
+ const FunctionDecl *FD);
+
+
+ void updateSummaryForCall(const RetainSummary *&Summ,
+ const CallEvent &Call);
+
+ bool isARCEnabled() const { return ARCEnabled; }
+
+ RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+
+ /// Determine whether a declaration {@code D} of correspondent type (return
+ /// type for functions/methods) {@code QT} has any of the given attributes,
+ /// provided they pass necessary validation checks AND tracking the given
+ /// attribute is enabled.
+ /// Returns the object kind corresponding to the present attribute, or None,
+ /// if none of the specified attributes are present.
+ /// Crashes if passed an attribute which is not explicitly handled.
+ template <class T>
+ Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
+
+ template <class T1, class T2, class... Others>
+ Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
+
+ friend class RetainSummaryTemplate;
+};
+
+
+// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
+// summaries. If a function or method looks like it has a default summary, but
+// it has annotations, the annotations are added to the stack-based template
+// and then copied into managed memory.
+class RetainSummaryTemplate {
+ RetainSummaryManager &Manager;
+ const RetainSummary *&RealSummary;
+ RetainSummary ScratchSummary;
+ bool Accessed;
+public:
+ RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
+ : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
+
+ ~RetainSummaryTemplate() {
+ if (Accessed)
+ RealSummary = Manager.getPersistentSummary(ScratchSummary);
+ }
+
+ RetainSummary &operator*() {
+ Accessed = true;
+ return ScratchSummary;
+ }
+
+ RetainSummary *operator->() {
+ Accessed = true;
+ return &ScratchSummary;
+ }
+};
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
index 216a2359efba..61709548aed1 100644
--- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
#define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/LLVM.h"
#include <functional>
#include <memory>
@@ -25,7 +26,8 @@ namespace ento {
class CheckerRegistry;
std::unique_ptr<CheckerManager> createCheckerManager(
- AnalyzerOptions &opts, const LangOptions &langOpts,
+ ASTContext &context,
+ AnalyzerOptions &opts,
ArrayRef<std::string> plugins,
ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
DiagnosticsEngine &diags);
diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
index d580dda73488..966234492fe0 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -73,8 +73,6 @@ class DiagnosticsEngine;
namespace ento {
-class CheckerOptInfo;
-
/// Manages a set of available checkers for running a static analysis.
/// The checkers are organized into packages by full name, where including
/// a package will recursively include all subpackages and checkers within it.
@@ -83,6 +81,8 @@ class CheckerOptInfo;
/// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker".
class CheckerRegistry {
public:
+ CheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine &diags);
+
/// Initialization functions perform any necessary setup for a checker.
/// They should include a call to CheckerManager::registerChecker.
using InitializationFunction = void (*)(CheckerManager &);
@@ -91,12 +91,16 @@ public:
InitializationFunction Initialize;
StringRef FullName;
StringRef Desc;
+ StringRef DocumentationUri;
- CheckerInfo(InitializationFunction fn, StringRef name, StringRef desc)
- : Initialize(fn), FullName(name), Desc(desc) {}
+ CheckerInfo(InitializationFunction Fn, StringRef Name, StringRef Desc,
+ StringRef DocsUri)
+ : Initialize(Fn), FullName(Name), Desc(Desc),
+ DocumentationUri(DocsUri) {}
};
using CheckerInfoList = std::vector<CheckerInfo>;
+ using CheckerInfoSet = llvm::SetVector<const CheckerRegistry::CheckerInfo *>;
private:
template <typename T>
@@ -107,16 +111,16 @@ private:
public:
/// Adds a checker to the registry. Use this non-templated overload when your
/// checker requires custom initialization.
- void addChecker(InitializationFunction fn, StringRef fullName,
- StringRef desc);
+ void addChecker(InitializationFunction Fn, StringRef FullName, StringRef Desc,
+ StringRef DocsUri);
/// Adds a checker to the registry. Use this templated overload when your
/// checker does not require any custom initialization.
template <class T>
- void addChecker(StringRef fullName, StringRef desc) {
+ void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri) {
// Avoid MSVC's Compiler Error C2276:
// http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
- addChecker(&CheckerRegistry::initializeManager<T>, fullName, desc);
+ addChecker(&CheckerRegistry::initializeManager<T>, FullName, Desc, DocsUri);
}
/// Initializes a CheckerManager by calling the initialization functions for
@@ -124,21 +128,22 @@ public:
/// list is significant; later options can be used to reverse earlier ones.
/// This can be used to exclude certain checkers in an included package.
void initializeManager(CheckerManager &mgr,
- SmallVectorImpl<CheckerOptInfo> &opts) const;
+ const AnalyzerOptions &Opts) const;
/// Check if every option corresponds to a specific checker or package.
- void validateCheckerOptions(const AnalyzerOptions &opts,
- DiagnosticsEngine &diags) const;
+ void validateCheckerOptions(const AnalyzerOptions &opts) const;
/// Prints the name and description of all checkers in this registry.
/// This output is not intended to be machine-parseable.
void printHelp(raw_ostream &out, size_t maxNameChars = 30) const;
- void printList(raw_ostream &out,
- SmallVectorImpl<CheckerOptInfo> &opts) const;
+ void printList(raw_ostream &out, const AnalyzerOptions &opts) const;
private:
+ CheckerInfoSet getEnabledCheckers(const AnalyzerOptions &Opts) const;
+
mutable CheckerInfoList Checkers;
mutable llvm::StringMap<size_t> Packages;
+ DiagnosticsEngine &Diags;
};
} // namespace ento
diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index ba37b7f59a02..2e9d0502e6f3 100644
--- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -52,9 +52,12 @@ private:
llvm::StringMap<Stmt *> &Bodies;
};
-void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins);
+void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins,
+ DiagnosticsEngine &diags);
void printEnabledCheckerList(raw_ostream &OS, ArrayRef<std::string> plugins,
- const AnalyzerOptions &opts);
+ const AnalyzerOptions &opts,
+ DiagnosticsEngine &diags);
+void printAnalyzerConfigList(raw_ostream &OS);
} // end GR namespace
diff --git a/include/clang/Tooling/AllTUsExecution.h b/include/clang/Tooling/AllTUsExecution.h
index f199365dc815..94bf01632fb4 100644
--- a/include/clang/Tooling/AllTUsExecution.h
+++ b/include/clang/Tooling/AllTUsExecution.h
@@ -45,6 +45,8 @@ public:
StringRef getExecutorName() const override { return ExecutorName; }
+ bool isSingleProcess() const override { return true; }
+
using ToolExecutor::execute;
llvm::Error
@@ -70,6 +72,8 @@ private:
unsigned ThreadCount;
};
+extern llvm::cl::opt<std::string> Filter;
+
} // end namespace tooling
} // end namespace clang
diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index 37e515fdc09e..aa07cc30e5f5 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -141,27 +141,6 @@ public:
virtual std::vector<CompileCommand> getAllCompileCommands() const;
};
-/// Interface for compilation database plugins.
-///
-/// A compilation database plugin allows the user to register custom compilation
-/// databases that are picked up as compilation database if the corresponding
-/// library is linked in. To register a plugin, declare a static variable like:
-///
-/// \code
-/// static CompilationDatabasePluginRegistry::Add<MyDatabasePlugin>
-/// X("my-compilation-database", "Reads my own compilation database");
-/// \endcode
-class CompilationDatabasePlugin {
-public:
- virtual ~CompilationDatabasePlugin();
-
- /// Loads a compilation database from a build directory.
- ///
- /// \see CompilationDatabase::loadFromDirectory().
- virtual std::unique_ptr<CompilationDatabase>
- loadFromDirectory(StringRef Directory, std::string &ErrorMessage) = 0;
-};
-
/// A compilation database that returns a single compile command line.
///
/// Useful when we want a tool to behave more like a compiler invocation.
diff --git a/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/include/clang/Tooling/CompilationDatabasePluginRegistry.h
index 051a08e2a91e..748ddbcf9d8d 100644
--- a/include/clang/Tooling/CompilationDatabasePluginRegistry.h
+++ b/include/clang/Tooling/CompilationDatabasePluginRegistry.h
@@ -16,6 +16,27 @@
namespace clang {
namespace tooling {
+/// Interface for compilation database plugins.
+///
+/// A compilation database plugin allows the user to register custom compilation
+/// databases that are picked up as compilation database if the corresponding
+/// library is linked in. To register a plugin, declare a static variable like:
+///
+/// \code
+/// static CompilationDatabasePluginRegistry::Add<MyDatabasePlugin>
+/// X("my-compilation-database", "Reads my own compilation database");
+/// \endcode
+class CompilationDatabasePlugin {
+public:
+ virtual ~CompilationDatabasePlugin();
+
+ /// Loads a compilation database from a build directory.
+ ///
+ /// \see CompilationDatabase::loadFromDirectory().
+ virtual std::unique_ptr<CompilationDatabase>
+ loadFromDirectory(StringRef Directory, std::string &ErrorMessage) = 0;
+};
+
using CompilationDatabasePluginRegistry =
llvm::Registry<CompilationDatabasePlugin>;
diff --git a/include/clang/Tooling/DiagnosticsYaml.h b/include/clang/Tooling/DiagnosticsYaml.h
index bf0732bf0042..d869450529bc 100644
--- a/include/clang/Tooling/DiagnosticsYaml.h
+++ b/include/clang/Tooling/DiagnosticsYaml.h
@@ -22,10 +22,19 @@
#include <string>
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Diagnostic)
+LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::DiagnosticMessage)
namespace llvm {
namespace yaml {
+template <> struct MappingTraits<clang::tooling::DiagnosticMessage> {
+ static void mapping(IO &Io, clang::tooling::DiagnosticMessage &M) {
+ Io.mapRequired("Message", M.Message);
+ Io.mapOptional("FilePath", M.FilePath);
+ Io.mapOptional("FileOffset", M.FileOffset);
+ }
+};
+
template <> struct MappingTraits<clang::tooling::Diagnostic> {
/// Helper to (de)serialize a Diagnostic since we don't have direct
/// access to its data members.
@@ -59,6 +68,7 @@ template <> struct MappingTraits<clang::tooling::Diagnostic> {
Io.mapRequired("Message", Keys->Message.Message);
Io.mapRequired("FileOffset", Keys->Message.FileOffset);
Io.mapRequired("FilePath", Keys->Message.FilePath);
+ Io.mapOptional("Notes", Keys->Notes);
// FIXME: Export properly all the different fields.
diff --git a/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h
index 68aef53cb58f..6bf1cf391b75 100644
--- a/include/clang/Tooling/Execution.h
+++ b/include/clang/Tooling/Execution.h
@@ -37,6 +37,8 @@
namespace clang {
namespace tooling {
+extern llvm::cl::opt<std::string> ExecutorName;
+
/// An abstraction for the result of a tool execution. For example, the
/// underlying result can be in-memory or on-disk.
///
@@ -114,6 +116,13 @@ public:
/// Returns the name of a specific executor.
virtual StringRef getExecutorName() const = 0;
+ /// Should return true iff executor runs all actions in a single process.
+ /// Clients can use this signal to find out if they can collect results
+ /// in-memory (e.g. to avoid serialization costs of using ToolResults).
+ /// The single-process executors can still run multiple threads, but all
+ /// executions are guaranteed to share the same memory.
+ virtual bool isSingleProcess() const = 0;
+
/// Executes each action with a corresponding arguments adjuster.
virtual llvm::Error
execute(llvm::ArrayRef<
diff --git a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index d2d47ddc2c61..bd314f03cd3a 100644
--- a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -74,7 +74,7 @@ public:
for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
const OffsetOfNode &Component = S->getComponent(I);
if (Component.getKind() == OffsetOfNode::Field) {
- if (!visit(Component.getField(), Component.getLocEnd()))
+ if (!visit(Component.getField(), Component.getEndLoc()))
return false;
}
// FIXME: Try to resolve dependent field references.
diff --git a/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h b/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
index 6767dc708e01..dc1d998396db 100644
--- a/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
+++ b/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
@@ -10,21 +10,6 @@
#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/PartialDiagnostic.h"
-
-namespace clang {
-namespace diag {
-enum {
-#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, CATEGORY) \
- ENUM,
-#define REFACTORINGSTART
-#include "clang/Basic/DiagnosticRefactoringKinds.inc"
-#undef DIAG
- NUM_BUILTIN_REFACTORING_DIAGNOSTICS
-};
-} // end namespace diag
-} // end namespace clang
+#include "clang/Basic/DiagnosticRefactoring.h"
#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
diff --git a/include/clang/Tooling/StandaloneExecution.h b/include/clang/Tooling/StandaloneExecution.h
index 572330e4cc22..96487b4bb1dd 100644
--- a/include/clang/Tooling/StandaloneExecution.h
+++ b/include/clang/Tooling/StandaloneExecution.h
@@ -37,7 +37,8 @@ public:
StandaloneToolExecutor(
const CompilationDatabase &Compilations,
llvm::ArrayRef<std::string> SourcePaths,
- IntrusiveRefCntPtr<vfs::FileSystem> BaseFS = vfs::getRealFileSystem(),
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS =
+ llvm::vfs::getRealFileSystem(),
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
@@ -52,6 +53,8 @@ public:
StringRef getExecutorName() const override { return ExecutorName; }
+ bool isSingleProcess() const override { return true; }
+
using ToolExecutor::execute;
llvm::Error
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index c056894b1a7a..662a980547df 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -33,7 +33,6 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
@@ -44,6 +43,7 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <memory>
#include <string>
#include <utility>
@@ -190,7 +190,7 @@ bool runToolOnCodeWithArgs(
// Similar to the overload except this takes a VFS.
bool runToolOnCodeWithArgs(
FrontendAction *ToolAction, const Twine &Code,
- llvm::IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
const Twine &ToolName = "clang-tool",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
@@ -205,7 +205,7 @@ bool runToolOnCodeWithArgs(
///
/// \return The resulting AST or null if an error occurred.
std::unique_ptr<ASTUnit>
-buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc",
+buildASTFromCode(StringRef Code, StringRef FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
@@ -223,10 +223,10 @@ buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc",
///
/// \return The resulting AST or null if an error occurred.
std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
- const Twine &Code, const std::vector<std::string> &Args,
- const Twine &FileName = "input.cc", const Twine &ToolName = "clang-tool",
+ StringRef Code, const std::vector<std::string> &Args,
+ StringRef FileName = "input.cc", StringRef ToolName = "clang-tool",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
- std::make_shared<PCHContainerOperations>(),
+ std::make_shared<PCHContainerOperations>(),
ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster());
/// Utility to run a FrontendAction in a single clang invocation.
@@ -319,8 +319,8 @@ public:
ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>(),
- IntrusiveRefCntPtr<vfs::FileSystem> BaseFS =
- vfs::getRealFileSystem());
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS =
+ llvm::vfs::getRealFileSystem());
~ClangTool();
@@ -356,6 +356,11 @@ public:
/// append them to ASTs.
int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
+ /// Sets whether working directory should be restored after calling run(). By
+ /// default, working directory is restored. However, it could be useful to
+ /// turn this off when running on multiple threads to avoid the raciness.
+ void setRestoreWorkingDir(bool RestoreCWD);
+
/// Returns the file manager used in the tool.
///
/// The file manager is shared between all translation units.
@@ -368,8 +373,8 @@ private:
std::vector<std::string> SourcePaths;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
llvm::IntrusiveRefCntPtr<FileManager> Files;
// Contains a list of pairs (<file name>, <file content>).
@@ -380,6 +385,8 @@ private:
ArgumentsAdjuster ArgsAdjuster;
DiagnosticConsumer *DiagConsumer = nullptr;
+
+ bool RestoreCWD = true;
};
template <typename T>
@@ -459,6 +466,10 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
/// \param File Either an absolute or relative path.
std::string getAbsolutePath(StringRef File);
+/// An overload of getAbsolutePath that works over the provided \p FS.
+llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS,
+ StringRef File);
+
/// Changes CommandLine to contain implicit flags that would have been
/// defined had the compiler driver been invoked through the path InvokedAs.
///
diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap
index 8d525c5ffbac..1f32ffe0c159 100644
--- a/include/clang/module.modulemap
+++ b/include/clang/module.modulemap
@@ -5,6 +5,12 @@ module Clang_Analysis {
textual header "Analysis/Analyses/ThreadSafetyOps.def"
module * { export * }
+
+ // FIXME: Exclude these headers to avoid pulling all of the AST matchers
+ // library into clang. Due to inline key functions in the headers,
+ // importing the AST matchers library gives a link dependency on the AST
+ // matchers (and thus the AST), which clang-format should not have.
+ exclude header "Analysis/Analyses/ExprMutationAnalyzer.h"
}
module Clang_AST {
@@ -33,7 +39,6 @@ module Clang_Basic {
textual header "Basic/BuiltinsLe64.def"
textual header "Basic/BuiltinsMips.def"
textual header "Basic/BuiltinsNEON.def"
- textual header "Basic/BuiltinsNios2.def"
textual header "Basic/BuiltinsNVPTX.def"
textual header "Basic/BuiltinsPPC.def"
textual header "Basic/BuiltinsSystemZ.def"
@@ -41,11 +46,14 @@ module Clang_Basic {
textual header "Basic/BuiltinsX86.def"
textual header "Basic/BuiltinsX86_64.def"
textual header "Basic/BuiltinsXCore.def"
+ textual header "Basic/CodeGenOptions.def"
textual header "Basic/DiagnosticOptions.def"
textual header "Basic/Features.def"
+ textual header "Basic/MSP430Target.def"
textual header "Basic/LangOptions.def"
textual header "Basic/OpenCLExtensions.def"
textual header "Basic/OpenCLImageTypes.def"
+ textual header "Basic/OpenCLExtensionTypes.def"
textual header "Basic/OpenMPKinds.def"
textual header "Basic/OperatorKinds.def"
textual header "Basic/Sanitizers.def"
@@ -95,17 +103,6 @@ module Clang_Frontend {
textual header "Frontend/LangStandards.def"
module * { export * }
-
- // FIXME: This violates layers.
- exclude header "Frontend/PCHContainerOperations.h"
-}
-
-// Used in clangBasic
-module Clang_Frontend_CodeGenOptions {
- requires cplusplus
- header "Frontend/CodeGenOptions.h"
- textual header "Frontend/CodeGenOptions.def"
- export *
}
module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } }
@@ -122,6 +119,7 @@ module Clang_StaticAnalyzer_Core {
umbrella "StaticAnalyzer/Core"
textual header "StaticAnalyzer/Core/Analyses.def"
+ textual header "StaticAnalyzer/Core/AnalyzerOptions.def"
textual header "StaticAnalyzer/Core/PathSensitive/SVals.def"
textual header "StaticAnalyzer/Core/PathSensitive/Symbols.def"
textual header "StaticAnalyzer/Core/PathSensitive/Regions.def"
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index 3c7b593be6d4..6da87903a488 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -190,8 +190,6 @@ createInvocationForMigration(CompilerInvocation &origCI,
PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile);
PPOpts.ImplicitPCHInclude.clear();
}
- // FIXME: Get the original header of a PTH as well.
- CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
std::string define = getARCMTMacroName();
define += '=';
CInvok->getPreprocessorOpts().addMacroDef(define);
@@ -241,7 +239,7 @@ bool arcmt::checkForManualIssues(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors,
StringRef plistOut) {
- if (!origCI.getLangOpts()->ObjC1)
+ if (!origCI.getLangOpts()->ObjC)
return false;
LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
@@ -342,7 +340,7 @@ applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagClient, StringRef outputDir,
bool emitPremigrationARCErrors, StringRef plistOut) {
- if (!origCI.getLangOpts()->ObjC1)
+ if (!origCI.getLangOpts()->ObjC)
return false;
LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
diff --git a/lib/ARCMigrate/CMakeLists.txt b/lib/ARCMigrate/CMakeLists.txt
index b716a20fe63f..efdff279aaed 100644
--- a/lib/ARCMigrate/CMakeLists.txt
+++ b/lib/ARCMigrate/CMakeLists.txt
@@ -35,4 +35,5 @@ add_clang_library(clangARCMigrate
clangSema
clangSerialization
clangStaticAnalyzerCheckers
+ clangStaticAnalyzerCore
)
diff --git a/lib/ARCMigrate/FileRemapper.cpp b/lib/ARCMigrate/FileRemapper.cpp
index ccc8c9ee30ff..225f47119b00 100644
--- a/lib/ARCMigrate/FileRemapper.cpp
+++ b/lib/ARCMigrate/FileRemapper.cpp
@@ -226,7 +226,7 @@ void FileRemapper::remap(const FileEntry *file, const FileEntry *newfile) {
const FileEntry *FileRemapper::getOriginalFile(StringRef filePath) {
const FileEntry *file = FileMgr->getFile(filePath);
- // If we are updating a file that overriden an original file,
+ // If we are updating a file that overridden an original file,
// actually update the original file.
llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
I = ToFromMappings.find(file);
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 7e9bc6a5bdc6..6950ce0e12f3 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -27,7 +27,7 @@
#include "clang/Lex/PPConditionalDirectiveRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h"
+#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Path.h"
@@ -36,7 +36,7 @@
using namespace clang;
using namespace arcmt;
-using namespace ento::objc_retain;
+using namespace ento;
namespace {
@@ -261,7 +261,7 @@ namespace {
if (IsGetter) {
// Find space location range between receiver expression and getter method.
SourceLocation BegLoc =
- ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd();
+ ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
BegLoc = PP.getLocForEndOfToken(BegLoc);
SourceLocation EndLoc = Msg->getSelectorLoc(0);
SourceRange SpaceRange(BegLoc, EndLoc);
@@ -269,7 +269,7 @@ namespace {
// rewrite getter method expression into: receiver.property or
// (receiver).property
if (NeedsParen) {
- commit.insertBefore(receiver->getLocStart(), "(");
+ commit.insertBefore(receiver->getBeginLoc(), "(");
PropertyDotString = ").";
}
else
@@ -291,9 +291,9 @@ namespace {
if (!RHS)
return false;
SourceLocation BegLoc =
- ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd();
+ ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
BegLoc = PP.getLocForEndOfToken(BegLoc);
- SourceLocation EndLoc = RHS->getLocStart();
+ SourceLocation EndLoc = RHS->getBeginLoc();
EndLoc = EndLoc.getLocWithOffset(-1);
const char *colon = PP.getSourceManager().getCharacterData(EndLoc);
// Add a space after '=' if there is no space between RHS and '='
@@ -545,14 +545,14 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
SourceLocation EndGetterSelectorLoc =
StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
- commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
+ commit.replace(CharSourceRange::getCharRange(Getter->getBeginLoc(),
EndGetterSelectorLoc),
PropertyString);
if (Setter && AvailabilityArgsMatch) {
SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
// Get location past ';'
EndLoc = EndLoc.getLocWithOffset(1);
- SourceLocation BeginOfSetterDclLoc = Setter->getLocStart();
+ SourceLocation BeginOfSetterDclLoc = Setter->getBeginLoc();
// FIXME. This assumes that setter decl; is immediately preceded by eoln.
// It is trying to remove the setter method decl. line entirely.
BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);
@@ -720,32 +720,33 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
ClassString += TypedefDcl->getIdentifier()->getName();
ClassString += ')';
- SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
+ SourceRange R(EnumDcl->getBeginLoc(), EnumDcl->getBeginLoc());
commit.replace(R, ClassString);
- SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd();
+ SourceLocation EndOfEnumDclLoc = EnumDcl->getEndLoc();
EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
NS.getASTContext(), /*IsDecl*/true);
if (EndOfEnumDclLoc.isValid()) {
- SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc);
- commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange);
+ SourceRange EnumDclRange(EnumDcl->getBeginLoc(), EndOfEnumDclLoc);
+ commit.insertFromRange(TypedefDcl->getBeginLoc(), EnumDclRange);
}
else
return false;
- SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
+ SourceLocation EndTypedefDclLoc = TypedefDcl->getEndLoc();
EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
NS.getASTContext(), /*IsDecl*/true);
if (EndTypedefDclLoc.isValid()) {
- SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc);
+ SourceRange TDRange(TypedefDcl->getBeginLoc(), EndTypedefDclLoc);
commit.remove(TDRange);
}
else
return false;
- EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(),
- /*IsDecl*/true);
+ EndOfEnumDclLoc =
+ trans::findLocationAfterSemi(EnumDcl->getEndLoc(), NS.getASTContext(),
+ /*IsDecl*/ true);
if (EndOfEnumDclLoc.isValid()) {
- SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart();
+ SourceLocation BeginOfEnumDclLoc = EnumDcl->getBeginLoc();
// FIXME. This assumes that enum decl; is immediately preceded by eoln.
// It is trying to remove the enum decl. lines entirely.
BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
@@ -775,12 +776,13 @@ static void rewriteToNSMacroDecl(ASTContext &Ctx,
SourceLocation EndLoc = EnumDcl->getBraceRange().getBegin();
if (EndLoc.isInvalid())
return;
- CharSourceRange R = CharSourceRange::getCharRange(EnumDcl->getLocStart(), EndLoc);
+ CharSourceRange R =
+ CharSourceRange::getCharRange(EnumDcl->getBeginLoc(), EndLoc);
commit.replace(R, ClassString);
// This is to remove spaces between '}' and typedef name.
- SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
+ SourceLocation StartTypedefLoc = EnumDcl->getEndLoc();
StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
- SourceLocation EndTypedefLoc = TypedefDcl->getLocEnd();
+ SourceLocation EndTypedefLoc = TypedefDcl->getEndLoc();
commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc));
}
@@ -811,7 +813,7 @@ static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
}
if (AllHexdecimalEnumerator && EnumVal) {
bool FoundHexdecimalEnumerator = false;
- SourceLocation EndLoc = Enumerator->getLocEnd();
+ SourceLocation EndLoc = Enumerator->getEndLoc();
Token Tok;
if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true))
if (Tok.isLiteral() && Tok.getLength() > 2) {
@@ -928,7 +930,7 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
if (EnumTy->getDecl() == EnumDcl) {
bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
- if (!InsertFoundation(Ctx, TypedefDcl->getLocStart()))
+ if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
return false;
edit::Commit commit(*Editor);
rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
@@ -941,7 +943,7 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
// We may still use NS_OPTIONS based on what we find in the enumertor list.
bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
- if (!InsertFoundation(Ctx, TypedefDcl->getLocStart()))
+ if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
return false;
edit::Commit commit(*Editor);
bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
@@ -964,7 +966,7 @@ static void ReplaceWithInstancetype(ASTContext &Ctx,
ClassString = "instancetype";
}
else {
- R = SourceRange(OM->getLocStart(), OM->getLocStart());
+ R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
ClassString = OM->isInstanceMethod() ? '-' : '+';
ClassString += " (instancetype)";
}
@@ -986,7 +988,7 @@ static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC,
}
}
else {
- R = SourceRange(OM->getLocStart(), OM->getLocStart());
+ R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
ClassString = "+ (";
ClassString += IDecl->getName(); ClassString += "*)";
}
@@ -1257,7 +1259,7 @@ void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
return;
edit::Commit commit(*Editor);
- commit.insertBefore(OM->getLocEnd(), " NS_RETURNS_INNER_POINTER");
+ commit.insertBefore(OM->getEndLoc(), " NS_RETURNS_INNER_POINTER");
Editor->commit(commit);
}
@@ -1269,7 +1271,7 @@ void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ct
!NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
return;
edit::Commit commit(*Editor);
- commit.insertBefore(P->getLocEnd(), " NS_RETURNS_INNER_POINTER ");
+ commit.insertBefore(P->getEndLoc(), " NS_RETURNS_INNER_POINTER ");
Editor->commit(commit);
}
@@ -1395,9 +1397,9 @@ void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
edit::Commit commit(*Editor);
- commit.insertBefore(FirstFD->getLocStart(), PragmaString);
+ commit.insertBefore(FirstFD->getBeginLoc(), PragmaString);
PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
- SourceLocation EndLoc = LastFD->getLocEnd();
+ SourceLocation EndLoc = LastFD->getEndLoc();
// get location just past end of function location.
EndLoc = PP.getLocForEndOfToken(EndLoc);
if (isa<FunctionDecl>(LastFD)) {
@@ -1458,21 +1460,21 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
if (!ResultAnnotated) {
RetEffect Ret = CE.getReturnValue();
const char *AnnotationString = nullptr;
- if (Ret.getObjKind() == RetEffect::CF) {
+ if (Ret.getObjKind() == ObjKind::CF) {
if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
AnnotationString = " CF_RETURNS_RETAINED";
else if (Ret.notOwned() &&
NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
AnnotationString = " CF_RETURNS_NOT_RETAINED";
}
- else if (Ret.getObjKind() == RetEffect::ObjC) {
+ else if (Ret.getObjKind() == ObjKind::ObjC) {
if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
AnnotationString = " NS_RETURNS_RETAINED";
}
if (AnnotationString) {
edit::Commit commit(*Editor);
- commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString);
+ commit.insertAfterToken(FuncDecl->getEndLoc(), AnnotationString);
Editor->commit(commit);
}
}
@@ -1482,14 +1484,15 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
+ if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::CF &&
+ !pd->hasAttr<CFConsumedAttr>() &&
NSAPIObj->isMacroDefined("CF_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
Editor->commit(commit);
- }
- else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
- NSAPIObj->isMacroDefined("NS_CONSUMED")) {
+ } else if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::ObjC &&
+ !pd->hasAttr<NSConsumedAttr>() &&
+ NSAPIObj->isMacroDefined("NS_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
Editor->commit(commit);
@@ -1518,7 +1521,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
bool ReturnCFAudited = false;
if (!FuncIsReturnAnnotated) {
RetEffect Ret = CE.getReturnValue();
- if (Ret.getObjKind() == RetEffect::CF &&
+ if (Ret.getObjKind() == ObjKind::CF &&
(Ret.isOwned() || Ret.notOwned()))
ReturnCFAudited = true;
else if (!AuditedType(FuncDecl->getReturnType()))
@@ -1534,13 +1537,13 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
- if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>())
+ if ((AE.getKind() == DecRef /*CFConsumed annotated*/ ||
+ AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) {
+ if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
ArgCFAudited = true;
- else if (AE == IncRef)
+ else if (AE.getKind() == IncRef)
ArgCFAudited = true;
- }
- else {
+ } else {
QualType AT = pd->getType();
if (!AuditedType(AT)) {
AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
@@ -1572,14 +1575,14 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
if (!ResultAnnotated) {
RetEffect Ret = CE.getReturnValue();
const char *AnnotationString = nullptr;
- if (Ret.getObjKind() == RetEffect::CF) {
+ if (Ret.getObjKind() == ObjKind::CF) {
if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
AnnotationString = " CF_RETURNS_RETAINED";
else if (Ret.notOwned() &&
NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
AnnotationString = " CF_RETURNS_NOT_RETAINED";
}
- else if (Ret.getObjKind() == RetEffect::ObjC) {
+ else if (Ret.getObjKind() == ObjKind::ObjC) {
ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
switch (OMF) {
case clang::OMF_alloc:
@@ -1598,7 +1601,7 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
if (AnnotationString) {
edit::Commit commit(*Editor);
- commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString);
+ commit.insertBefore(MethodDecl->getEndLoc(), AnnotationString);
Editor->commit(commit);
}
}
@@ -1608,7 +1611,9 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
+ if (AE.getKind() == DecRef
+ && AE.getObjKind() == ObjKind::CF
+ && !pd->hasAttr<CFConsumedAttr>() &&
NSAPIObj->isMacroDefined("CF_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
@@ -1624,19 +1629,20 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
return;
CallEffects CE = CallEffects::getEffect(MethodDecl);
- bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
- MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
-
- if (CE.getReceiver() == DecRefMsg &&
+ bool MethodIsReturnAnnotated =
+ (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
+ MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
+ MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
+ MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
+ MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
+
+ if (CE.getReceiver().getKind() == DecRef &&
!MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
MethodDecl->getMethodFamily() != OMF_init &&
MethodDecl->getMethodFamily() != OMF_release &&
NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
edit::Commit commit(*Editor);
- commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF");
+ commit.insertBefore(MethodDecl->getEndLoc(), " NS_CONSUMES_SELF");
Editor->commit(commit);
}
@@ -1647,8 +1653,8 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
if (!MethodIsReturnAnnotated) {
RetEffect Ret = CE.getReturnValue();
- if ((Ret.getObjKind() == RetEffect::CF ||
- Ret.getObjKind() == RetEffect::ObjC) &&
+ if ((Ret.getObjKind() == ObjKind::CF ||
+ Ret.getObjKind() == ObjKind::ObjC) &&
(Ret.isOwned() || Ret.notOwned())) {
AddCFAnnotations(Ctx, CE, MethodDecl, false);
return;
@@ -1664,8 +1670,8 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef ||
- !AuditedType(pd->getType())) {
+ if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
+ AE.getKind() == IncRef || !AuditedType(pd->getType())) {
AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
return;
}
@@ -1713,7 +1719,7 @@ void ObjCMigrateASTConsumer::inferDesignatedInitializers(
continue;
if (hasSuperInitCall(MD)) {
edit::Commit commit(*Editor);
- commit.insert(IFaceM->getLocEnd(), " NS_DESIGNATED_INITIALIZER");
+ commit.insert(IFaceM->getEndLoc(), " NS_DESIGNATED_INITIALIZER");
Editor->commit(commit);
}
}
diff --git a/lib/ARCMigrate/TransAPIUses.cpp b/lib/ARCMigrate/TransAPIUses.cpp
index 40c8a070f813..6146e07b1d2a 100644
--- a/lib/ARCMigrate/TransAPIUses.cpp
+++ b/lib/ARCMigrate/TransAPIUses.cpp
@@ -75,7 +75,7 @@ public:
return true;
if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone)
- Pass.TA.report(parm->getLocStart(),
+ Pass.TA.report(parm->getBeginLoc(),
diag::err_arcmt_nsinvocation_ownership,
parm->getSourceRange())
<< selName;
diff --git a/lib/ARCMigrate/TransAutoreleasePool.cpp b/lib/ARCMigrate/TransAutoreleasePool.cpp
index 2d35655d186f..9d20774a89a6 100644
--- a/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -128,21 +128,21 @@ public:
Pass.TA.removeStmt(*scope.End);
Stmt::child_iterator retI = scope.End;
++retI;
- SourceLocation afterSemi = findLocationAfterSemi((*retI)->getLocEnd(),
- Pass.Ctx);
+ SourceLocation afterSemi =
+ findLocationAfterSemi((*retI)->getEndLoc(), Pass.Ctx);
assert(afterSemi.isValid() &&
"Didn't we check before setting IsFollowedBySimpleReturnStmt "
"to true?");
Pass.TA.insertAfterToken(afterSemi, "\n}");
Pass.TA.increaseIndentation(
- SourceRange(scope.getIndentedRange().getBegin(),
- (*retI)->getLocEnd()),
- scope.CompoundParent->getLocStart());
+ SourceRange(scope.getIndentedRange().getBegin(),
+ (*retI)->getEndLoc()),
+ scope.CompoundParent->getBeginLoc());
} else {
Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
Pass.TA.replaceStmt(*scope.End, "}");
Pass.TA.increaseIndentation(scope.getIndentedRange(),
- scope.CompoundParent->getLocStart());
+ scope.CompoundParent->getBeginLoc());
}
}
@@ -241,7 +241,7 @@ private:
Stmt::child_iterator rangeE = Begin;
for (Stmt::child_iterator I = rangeS; I != End; ++I)
++rangeE;
- return SourceRange((*rangeS)->getLocStart(), (*rangeE)->getLocEnd());
+ return SourceRange((*rangeS)->getBeginLoc(), (*rangeE)->getEndLoc());
}
};
@@ -256,8 +256,8 @@ private:
SourceLocation &declarationLoc)
: Ctx(ctx), referenceLoc(referenceLoc),
declarationLoc(declarationLoc) {
- ScopeRange = SourceRange((*scope.Begin)->getLocStart(),
- (*scope.End)->getLocStart());
+ ScopeRange = SourceRange((*scope.Begin)->getBeginLoc(),
+ (*scope.End)->getBeginLoc());
}
bool VisitDeclRefExpr(DeclRefExpr *E) {
@@ -307,7 +307,7 @@ private:
if (ReturnStmt *retS = dyn_cast<ReturnStmt>(*SI))
if ((retS->getRetValue() == nullptr ||
isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) &&
- findLocationAfterSemi(retS->getLocEnd(), Pass.Ctx).isValid()) {
+ findLocationAfterSemi(retS->getEndLoc(), Pass.Ctx).isValid()) {
scope.IsFollowedBySimpleReturnStmt = true;
++SI; // the return will be included in scope, don't check it.
}
@@ -328,9 +328,9 @@ private:
"NSAutoreleasePool scope that it was declared in", referenceLoc);
Pass.TA.reportNote("name declared here", declarationLoc);
Pass.TA.reportNote("intended @autoreleasepool scope begins here",
- (*scope.Begin)->getLocStart());
+ (*scope.Begin)->getBeginLoc());
Pass.TA.reportNote("intended @autoreleasepool scope ends here",
- (*scope.End)->getLocStart());
+ (*scope.End)->getBeginLoc());
return;
}
}
@@ -403,8 +403,8 @@ private:
return cast<Expr>(getEssential((Stmt*)E));
}
static Stmt *getEssential(Stmt *S) {
- if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
- S = EWC->getSubExpr();
+ if (FullExpr *FE = dyn_cast<FullExpr>(S))
+ S = FE->getSubExpr();
if (Expr *E = dyn_cast<Expr>(S))
S = E->IgnoreParenCasts();
return S;
diff --git a/lib/ARCMigrate/TransGCAttrs.cpp b/lib/ARCMigrate/TransGCAttrs.cpp
index fb45cd92c1f6..7697d3f048e6 100644
--- a/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/lib/ARCMigrate/TransGCAttrs.cpp
@@ -81,10 +81,11 @@ public:
}
bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
- if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
+ auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>();
+ if (!OwnershipAttr)
return false;
- SourceLocation Loc = TL.getAttrNameLoc();
+ SourceLocation Loc = OwnershipAttr->getLocation();
unsigned RawLoc = Loc.getRawEncoding();
if (MigrateCtx.AttrSet.count(RawLoc))
return true;
@@ -93,13 +94,7 @@ public:
SourceManager &SM = Ctx.getSourceManager();
if (Loc.isMacroID())
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
- SmallString<32> Buf;
- bool Invalid = false;
- StringRef Spell = Lexer::getSpelling(
- SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),
- Buf, SM, Ctx.getLangOpts(), &Invalid);
- if (Invalid)
- return false;
+ StringRef Spell = OwnershipAttr->getKind()->getName();
MigrationContext::GCAttrOccurrence::AttrKind Kind;
if (Spell == "strong")
Kind = MigrationContext::GCAttrOccurrence::Strong;
@@ -284,7 +279,7 @@ static void checkAllAtProps(MigrationContext &MigrateCtx,
}
for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
- SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
+ SourceLocation Loc = ATLs[i].first.getAttr()->getLocation();
if (Loc.isMacroID())
Loc = MigrateCtx.Pass.Ctx.getSourceManager()
.getImmediateExpansionRange(Loc)
@@ -340,7 +335,7 @@ void MigrationContext::dumpGCAttrs() {
llvm::errs() << "KIND: "
<< (Attr.Kind == GCAttrOccurrence::Strong ? "strong" : "weak");
llvm::errs() << "\nLOC: ";
- Attr.Loc.dump(Pass.Ctx.getSourceManager());
+ Attr.Loc.print(llvm::errs(), Pass.Ctx.getSourceManager());
llvm::errs() << "\nTYPE: ";
Attr.ModifiedType.dump();
if (Attr.Dcl) {
diff --git a/lib/ARCMigrate/TransGCCalls.cpp b/lib/ARCMigrate/TransGCCalls.cpp
index 3a236d34cd4b..eff142ba3922 100644
--- a/lib/ARCMigrate/TransGCCalls.cpp
+++ b/lib/ARCMigrate/TransGCCalls.cpp
@@ -38,7 +38,7 @@ public:
TransformActions &TA = MigrateCtx.Pass.TA;
if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
- TA.report(E->getLocStart(), diag::warn_arcmt_nsalloc_realloc,
+ TA.report(E->getBeginLoc(), diag::warn_arcmt_nsalloc_realloc,
E->getSourceRange());
return true;
}
diff --git a/lib/ARCMigrate/TransProtectedScope.cpp b/lib/ARCMigrate/TransProtectedScope.cpp
index 1bb4c1f4e449..bfc542e7497c 100644
--- a/lib/ARCMigrate/TransProtectedScope.cpp
+++ b/lib/ARCMigrate/TransProtectedScope.cpp
@@ -73,12 +73,13 @@ public:
Curr = Curr->getNextSwitchCase();
}
- SourceLocation NextLoc = S->getLocEnd();
+ SourceLocation NextLoc = S->getEndLoc();
Curr = S->getSwitchCaseList();
// We iterate over case statements in reverse source-order.
while (Curr) {
- Cases.push_back(CaseInfo(Curr,SourceRange(Curr->getLocStart(), NextLoc)));
- NextLoc = Curr->getLocStart();
+ Cases.push_back(
+ CaseInfo(Curr, SourceRange(Curr->getBeginLoc(), NextLoc)));
+ NextLoc = Curr->getBeginLoc();
Curr = Curr->getNextSwitchCase();
}
return true;
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index c411044ecde3..d199bb936547 100644
--- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -71,9 +71,10 @@ public:
// will likely die immediately while previously it was kept alive
// by the autorelease pool. This is bad practice in general, leave it
// and emit an error to force the user to restructure their code.
- Pass.TA.reportError("it is not safe to remove an unused 'autorelease' "
+ Pass.TA.reportError(
+ "it is not safe to remove an unused 'autorelease' "
"message; its receiver may be destroyed immediately",
- E->getLocStart(), E->getSourceRange());
+ E->getBeginLoc(), E->getSourceRange());
return true;
}
}
@@ -89,7 +90,7 @@ public:
std::string err = "it is not safe to remove '";
err += E->getSelector().getAsString() + "' message on "
"an __unsafe_unretained type";
- Pass.TA.reportError(err, rec->getLocStart());
+ Pass.TA.reportError(err, rec->getBeginLoc());
return true;
}
@@ -98,18 +99,21 @@ public:
std::string err = "it is not safe to remove '";
err += E->getSelector().getAsString() + "' message on "
"a global variable";
- Pass.TA.reportError(err, rec->getLocStart());
+ Pass.TA.reportError(err, rec->getBeginLoc());
return true;
}
if (E->getMethodFamily() == OMF_release && isDelegateMessage(rec)) {
- Pass.TA.reportError("it is not safe to remove 'retain' "
+ Pass.TA.reportError(
+ "it is not safe to remove 'retain' "
"message on the result of a 'delegate' message; "
"the object that was passed to 'setDelegate:' may not be "
- "properly retained", rec->getLocStart());
+ "properly retained",
+ rec->getBeginLoc());
return true;
}
}
+ break;
case OMF_dealloc:
break;
}
@@ -250,7 +254,7 @@ private:
}
while (OuterS && (isa<ParenExpr>(OuterS) ||
isa<CastExpr>(OuterS) ||
- isa<ExprWithCleanups>(OuterS)));
+ isa<FullExpr>(OuterS)));
if (!OuterS)
return std::make_pair(prevStmt, nextStmt);
@@ -373,8 +377,8 @@ private:
RecContainer = StmtE;
Rec = Init->IgnoreParenImpCasts();
- if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Rec))
- Rec = EWC->getSubExpr()->IgnoreParenImpCasts();
+ if (FullExpr *FE = dyn_cast<FullExpr>(Rec))
+ Rec = FE->getSubExpr()->IgnoreParenImpCasts();
RecRange = Rec->getSourceRange();
if (SM.isMacroArgExpansion(RecRange.getBegin()))
RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 66167d37ac95..9d46d8c5fcae 100644
--- a/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -209,7 +209,7 @@ private:
// We will remove the compiler diagnostic.
if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
diag::err_arc_cast_requires_bridge,
- E->getLocStart())) {
+ E->getBeginLoc())) {
Trans.abort();
return;
}
@@ -225,13 +225,12 @@ private:
}
TA.clearDiagnostic(diag::err_arc_mismatched_cast,
- diag::err_arc_cast_requires_bridge,
- E->getLocStart());
+ diag::err_arc_cast_requires_bridge, E->getBeginLoc());
if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
TA.insertAfterToken(CCE->getLParenLoc(), bridge);
} else {
- SourceLocation insertLoc = E->getSubExpr()->getLocStart();
+ SourceLocation insertLoc = E->getSubExpr()->getBeginLoc();
SmallString<128> newCast;
newCast += '(';
newCast += bridge;
@@ -243,7 +242,7 @@ private:
} else {
newCast += '(';
TA.insert(insertLoc, newCast.str());
- TA.insertAfterToken(E->getLocEnd(), ")");
+ TA.insertAfterToken(E->getEndLoc(), ")");
}
}
} else {
@@ -251,7 +250,7 @@ private:
SmallString<32> BridgeCall;
Expr *WrapE = E->getSubExpr();
- SourceLocation InsertLoc = WrapE->getLocStart();
+ SourceLocation InsertLoc = WrapE->getBeginLoc();
SourceManager &SM = Pass.Ctx.getSourceManager();
char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
@@ -268,7 +267,7 @@ private:
} else {
BridgeCall += '(';
TA.insert(InsertLoc, BridgeCall);
- TA.insertAfterToken(WrapE->getLocEnd(), ")");
+ TA.insertAfterToken(WrapE->getEndLoc(), ")");
}
}
}
@@ -368,19 +367,19 @@ private:
err += family == OMF_autorelease ? "autorelease" : "release";
err += "' message; a __bridge cast may result in a pointer to a "
"destroyed object and a __bridge_retained may leak the object";
- Pass.TA.reportError(err, E->getLocStart(),
+ Pass.TA.reportError(err, E->getBeginLoc(),
E->getSubExpr()->getSourceRange());
Stmt *parent = E;
do {
parent = StmtMap->getParentIgnoreParenImpCasts(parent);
- } while (parent && isa<ExprWithCleanups>(parent));
+ } while (parent && isa<FullExpr>(parent));
if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
std::string note = "remove the cast and change return type of function "
"to '";
note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
note += "' to have the object automatically autoreleased";
- Pass.TA.reportNote(note, retS->getLocStart());
+ Pass.TA.reportNote(note, retS->getBeginLoc());
}
}
diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp
index 3f79cc441e85..d1768bc56cfc 100644
--- a/lib/ARCMigrate/TransformActions.cpp
+++ b/lib/ARCMigrate/TransformActions.cpp
@@ -350,7 +350,7 @@ void TransformActionsImpl::replaceText(SourceLocation loc, StringRef text,
void TransformActionsImpl::replaceStmt(Stmt *S, StringRef text) {
assert(IsInTransaction && "Actions only allowed during a transaction");
text = getUniqueText(text);
- insert(S->getLocStart(), text);
+ insert(S->getBeginLoc(), text);
removeStmt(S);
}
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 4a7af2858879..8bd2b407aee9 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -74,8 +74,8 @@ bool trans::isPlusOneAssign(const BinaryOperator *E) {
bool trans::isPlusOne(const Expr *E) {
if (!E)
return false;
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E))
- E = EWC->getSubExpr();
+ if (const FullExpr *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
if (const ObjCMessageExpr *
ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
@@ -359,7 +359,7 @@ MigrationContext::~MigrationContext() {
bool MigrationContext::isGCOwnedNonObjC(QualType T) {
while (!T.isNull()) {
if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
- if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
+ if (AttrT->getAttrKind() == attr::ObjCOwnership)
return !AttrT->getModifiedType()->isObjCRetainableType();
}
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index c45b52a65a4d..c05b160b8e3d 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -416,18 +416,26 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
<< GetApproxValue(getComplexFloatImag()) << "i";
return;
case APValue::LValue: {
- LValueBase Base = getLValueBase();
- if (!Base) {
- Out << "0";
- return;
- }
-
bool IsReference = Ty->isReferenceType();
QualType InnerTy
= IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
if (InnerTy.isNull())
InnerTy = Ty;
+ LValueBase Base = getLValueBase();
+ if (!Base) {
+ if (isNullPointer()) {
+ Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0");
+ } else if (IsReference) {
+ Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)"
+ << getLValueOffset().getQuantity();
+ } else {
+ Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")"
+ << getLValueOffset().getQuantity();
+ }
+ return;
+ }
+
if (!hasLValuePath()) {
// No lvalue path: just print the offset.
CharUnits O = getLValueOffset();
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d50f4493788a..21b6f36e9aa7 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -48,6 +48,7 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
@@ -192,7 +193,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
isa<ObjCPropertyDecl>(D) ||
isa<RedeclarableTemplateDecl>(D) ||
isa<ClassTemplateSpecializationDecl>(D))
- DeclLoc = D->getLocStart();
+ DeclLoc = D->getBeginLoc();
else {
DeclLoc = D->getLocation();
if (DeclLoc.isMacroID()) {
@@ -200,7 +201,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
// If location of the typedef name is in a macro, it is because being
// declared via a macro. Try using declaration's starting location as
// the "declaration location".
- DeclLoc = D->getLocStart();
+ DeclLoc = D->getBeginLoc();
} else if (const auto *TD = dyn_cast<TagDecl>(D)) {
// If location of the tag decl is inside a macro, but the spelling of
// the tag name comes from a macro argument, it looks like a special
@@ -795,11 +796,10 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
CompCategories(this_()), LastSDM(nullptr, 0) {
TUDecl = TranslationUnitDecl::Create(*this);
+ TraversalScope = {TUDecl};
}
ASTContext::~ASTContext() {
- ReleaseParentMapEntries();
-
// Release the DenseMaps associated with DeclContext objects.
// FIXME: Is this the ideal solution?
ReleaseDeclContextMaps();
@@ -837,22 +837,80 @@ ASTContext::~ASTContext() {
Value.second->~PerModuleInitializers();
}
-void ASTContext::ReleaseParentMapEntries() {
- if (!PointerParents) return;
- for (const auto &Entry : *PointerParents) {
- if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
- delete Entry.second.get<ast_type_traits::DynTypedNode *>();
- } else if (Entry.second.is<ParentVector *>()) {
- delete Entry.second.get<ParentVector *>();
+class ASTContext::ParentMap {
+ /// Contains parents of a node.
+ using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>;
+
+ /// Maps from a node to its parents. This is used for nodes that have
+ /// pointer identity only, which are more common and we can save space by
+ /// only storing a unique pointer to them.
+ using ParentMapPointers = llvm::DenseMap<
+ const void *,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *, ParentVector *>>;
+
+ /// Parent map for nodes without pointer identity. We store a full
+ /// DynTypedNode for all keys.
+ using ParentMapOtherNodes = llvm::DenseMap<
+ ast_type_traits::DynTypedNode,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *, ParentVector *>>;
+
+ ParentMapPointers PointerParents;
+ ParentMapOtherNodes OtherParents;
+ class ASTVisitor;
+
+ static ast_type_traits::DynTypedNode
+ getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) {
+ if (const auto *D = U.dyn_cast<const Decl *>())
+ return ast_type_traits::DynTypedNode::create(*D);
+ if (const auto *S = U.dyn_cast<const Stmt *>())
+ return ast_type_traits::DynTypedNode::create(*S);
+ return *U.get<ast_type_traits::DynTypedNode *>();
+ }
+
+ template <typename NodeTy, typename MapTy>
+ static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
+ const MapTy &Map) {
+ auto I = Map.find(Node);
+ if (I == Map.end()) {
+ return llvm::ArrayRef<ast_type_traits::DynTypedNode>();
+ }
+ if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
+ return llvm::makeArrayRef(*V);
+ }
+ return getSingleDynTypedNodeFromParentMap(I->second);
+ }
+
+public:
+ ParentMap(ASTContext &Ctx);
+ ~ParentMap() {
+ for (const auto &Entry : PointerParents) {
+ if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
+ delete Entry.second.get<ast_type_traits::DynTypedNode *>();
+ } else if (Entry.second.is<ParentVector *>()) {
+ delete Entry.second.get<ParentVector *>();
+ }
}
- }
- for (const auto &Entry : *OtherParents) {
- if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
- delete Entry.second.get<ast_type_traits::DynTypedNode *>();
- } else if (Entry.second.is<ParentVector *>()) {
- delete Entry.second.get<ParentVector *>();
+ for (const auto &Entry : OtherParents) {
+ if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
+ delete Entry.second.get<ast_type_traits::DynTypedNode *>();
+ } else if (Entry.second.is<ParentVector *>()) {
+ delete Entry.second.get<ParentVector *>();
+ }
}
}
+
+ DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node) {
+ if (Node.getNodeKind().hasPointerIdentity())
+ return getDynNodeFromMap(Node.getMemoizationData(), PointerParents);
+ return getDynNodeFromMap(Node, OtherParents);
+ }
+};
+
+void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) {
+ TraversalScope = TopLevelDecls;
+ Parents.reset();
}
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
@@ -885,7 +943,9 @@ void ASTContext::PrintStats() const {
#define TYPE(Name, Parent) \
if (counts[Idx]) \
llvm::errs() << " " << counts[Idx] << " " << #Name \
- << " types\n"; \
+ << " types, " << sizeof(Name##Type) << " each " \
+ << "(" << counts[Idx] * sizeof(Name##Type) \
+ << " bytes)\n"; \
TotalBytes += counts[Idx] * sizeof(Name##Type); \
++Idx;
#define ABSTRACT_TYPE(Name, Parent)
@@ -929,14 +989,11 @@ void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
if (auto *Listener = getASTMutationListener())
Listener->RedefinedHiddenDefinition(ND, M);
- if (getLangOpts().ModulesLocalVisibility)
- MergedDefModules[ND].push_back(M);
- else
- ND->setVisibleDespiteOwningModule();
+ MergedDefModules[cast<NamedDecl>(ND->getCanonicalDecl())].push_back(M);
}
void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
- auto It = MergedDefModules.find(ND);
+ auto It = MergedDefModules.find(cast<NamedDecl>(ND->getCanonicalDecl()));
if (It == MergedDefModules.end())
return;
@@ -1241,6 +1298,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
InitBuiltinType(OCLClkEventTy, BuiltinType::OCLClkEvent);
InitBuiltinType(OCLQueueTy, BuiltinType::OCLQueue);
InitBuiltinType(OCLReserveIDTy, BuiltinType::OCLReserveID);
+
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ InitBuiltinType(Id##Ty, BuiltinType::Id);
+#include "clang/Basic/OpenCLExtensionTypes.def"
}
// Builtin type for __objc_yes and __objc_no
@@ -1892,6 +1953,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
AS = getTargetAddressSpace(
Target->getOpenCLTypeAddrSpace(getOpenCLTypeKind(T)));
Width = Target->getPointerWidth(AS);
@@ -2295,12 +2359,11 @@ structHasUniqueObjectRepresentations(const ASTContext &Context,
}
}
- llvm::sort(
- Bases.begin(), Bases.end(), [&](const std::pair<QualType, int64_t> &L,
- const std::pair<QualType, int64_t> &R) {
- return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) <
- Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl());
- });
+ llvm::sort(Bases, [&](const std::pair<QualType, int64_t> &L,
+ const std::pair<QualType, int64_t> &R) {
+ return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) <
+ Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl());
+ });
for (const auto Base : Bases) {
int64_t BaseOffset = Context.toBits(
@@ -2500,21 +2563,24 @@ const ObjCInterfaceDecl *ASTContext::getObjContainingInterface(
/// Get the copy initialization expression of VarDecl, or nullptr if
/// none exists.
-Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
+ASTContext::BlockVarCopyInit
+ASTContext::getBlockVarCopyInit(const VarDecl*VD) const {
assert(VD && "Passed null params");
assert(VD->hasAttr<BlocksAttr>() &&
"getBlockVarCopyInits - not __block var");
- llvm::DenseMap<const VarDecl*, Expr*>::iterator
- I = BlockVarCopyInits.find(VD);
- return (I != BlockVarCopyInits.end()) ? I->second : nullptr;
+ auto I = BlockVarCopyInits.find(VD);
+ if (I != BlockVarCopyInits.end())
+ return I->second;
+ return {nullptr, false};
}
/// Set the copy inialization expression of a block var decl.
-void ASTContext::setBlockVarCopyInits(VarDecl*VD, Expr* Init) {
- assert(VD && Init && "Passed null params");
+void ASTContext::setBlockVarCopyInit(const VarDecl*VD, Expr *CopyExpr,
+ bool CanThrow) {
+ assert(VD && CopyExpr && "Passed null params");
assert(VD->hasAttr<BlocksAttr>() &&
"setBlockVarCopyInits - not __block var");
- BlockVarCopyInits[VD] = Init;
+ BlockVarCopyInits[VD].setExprAndFlag(CopyExpr, CanThrow);
}
TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T,
@@ -3695,30 +3761,20 @@ QualType ASTContext::getFunctionTypeInternal(
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- // FunctionProtoType objects are allocated with extra bytes after
- // them for three variable size arrays at the end:
- // - parameter types
- // - exception types
- // - extended parameter information
- // Instead of the exception types, there could be a noexcept
- // expression, or information used to resolve the exception
- // specification.
- size_t Size =
- sizeof(FunctionProtoType) + NumArgs * sizeof(QualType) +
- FunctionProtoType::getExceptionSpecSize(
- EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size());
-
- // Put the ExtParameterInfos last. If all were equal, it would make
- // more sense to put these before the exception specification, because
- // it's much easier to skip past them compared to the elaborate switch
- // required to skip the exception specification. However, all is not
- // equal; ExtParameterInfos are used to model very uncommon features,
- // and it's better not to burden the more common paths.
- if (EPI.ExtParameterInfos) {
- Size += NumArgs * sizeof(FunctionProtoType::ExtParameterInfo);
- }
-
- auto *FTP = (FunctionProtoType *) Allocate(Size, TypeAlignment);
+ // Compute the needed size to hold this FunctionProtoType and the
+ // various trailing objects.
+ auto ESH = FunctionProtoType::getExceptionSpecSize(
+ EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size());
+ size_t Size = FunctionProtoType::totalSizeToAlloc<
+ QualType, FunctionType::FunctionTypeExtraBitfields,
+ FunctionType::ExceptionType, Expr *, FunctionDecl *,
+ FunctionProtoType::ExtParameterInfo, Qualifiers>(
+ NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type),
+ ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
+ EPI.ExtParameterInfos ? NumArgs : 0,
+ EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0);
+
+ auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI;
new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI);
Types.push_back(FTP);
@@ -3870,7 +3926,7 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
return QualType(newType, 0);
}
-QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
+QualType ASTContext::getAttributedType(attr::Kind attrKind,
QualType modifiedType,
QualType equivalentType) {
llvm::FoldingSetNodeID id;
@@ -4130,8 +4186,10 @@ QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
(void)CheckT;
}
- T = new (*this, TypeAlignment)
- ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl);
+ void *Mem = Allocate(ElaboratedType::totalSizeToAlloc<TagDecl *>(!!OwnedTagDecl),
+ TypeAlignment);
+ T = new (Mem) ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl);
+
Types.push_back(T);
ElaboratedTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
@@ -4262,7 +4320,7 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
Arg = TemplateArgument(ArgType);
} else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
Expr *E = new (*this) DeclRefExpr(
- NTTP, /*enclosing*/false,
+ *this, NTTP, /*enclosing*/ false,
NTTP->getType().getNonLValueExprType(*this),
Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
@@ -4542,8 +4600,8 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
if (!protocols.empty()) {
// Apply the protocol qualifers.
bool hasError;
- Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError,
- true/*allowOnPointerType*/);
+ Canonical = getCanonicalType(applyObjCProtocolQualifiers(
+ Canonical, protocols, hasError, true /*allowOnPointerType*/));
assert(!hasError && "Error when apply protocol qualifier to bound type");
}
}
@@ -5098,7 +5156,7 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2) {
return true;
}
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
const auto *T1OPType = T1->getAs<ObjCObjectPointerType>();
const auto *T2OPType = T2->getAs<ObjCObjectPointerType>();
if (T1OPType && T2OPType) {
@@ -5762,50 +5820,86 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const {
}
TypedefDecl *ASTContext::getCFConstantStringDecl() const {
- if (!CFConstantStringTypeDecl) {
- assert(!CFConstantStringTagDecl &&
- "tag and typedef should be initialized together");
- CFConstantStringTagDecl = buildImplicitRecord("__NSConstantString_tag");
- CFConstantStringTagDecl->startDefinition();
-
- QualType FieldTypes[4];
- const char *FieldNames[4];
-
- // const int *isa;
- FieldTypes[0] = getPointerType(IntTy.withConst());
- FieldNames[0] = "isa";
- // int flags;
- FieldTypes[1] = IntTy;
- FieldNames[1] = "flags";
- // const char *str;
- FieldTypes[2] = getPointerType(CharTy.withConst());
- FieldNames[2] = "str";
- // long length;
- FieldTypes[3] = LongTy;
- FieldNames[3] = "length";
-
- // Create fields
- for (unsigned i = 0; i < 4; ++i) {
- FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTagDecl,
- SourceLocation(),
- SourceLocation(),
- &Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/nullptr,
- /*BitWidth=*/nullptr,
- /*Mutable=*/false,
- ICIS_NoInit);
- Field->setAccess(AS_public);
- CFConstantStringTagDecl->addDecl(Field);
- }
+ if (CFConstantStringTypeDecl)
+ return CFConstantStringTypeDecl;
+
+ assert(!CFConstantStringTagDecl &&
+ "tag and typedef should be initialized together");
+ CFConstantStringTagDecl = buildImplicitRecord("__NSConstantString_tag");
+ CFConstantStringTagDecl->startDefinition();
- CFConstantStringTagDecl->completeDefinition();
- // This type is designed to be compatible with NSConstantString, but cannot
- // use the same name, since NSConstantString is an interface.
- auto tagType = getTagDeclType(CFConstantStringTagDecl);
- CFConstantStringTypeDecl =
- buildImplicitTypedef(tagType, "__NSConstantString");
+ struct {
+ QualType Type;
+ const char *Name;
+ } Fields[5];
+ unsigned Count = 0;
+
+ /// Objective-C ABI
+ ///
+ /// typedef struct __NSConstantString_tag {
+ /// const int *isa;
+ /// int flags;
+ /// const char *str;
+ /// long length;
+ /// } __NSConstantString;
+ ///
+ /// Swift ABI (4.1, 4.2)
+ ///
+ /// typedef struct __NSConstantString_tag {
+ /// uintptr_t _cfisa;
+ /// uintptr_t _swift_rc;
+ /// _Atomic(uint64_t) _cfinfoa;
+ /// const char *_ptr;
+ /// uint32_t _length;
+ /// } __NSConstantString;
+ ///
+ /// Swift ABI (5.0)
+ ///
+ /// typedef struct __NSConstantString_tag {
+ /// uintptr_t _cfisa;
+ /// uintptr_t _swift_rc;
+ /// _Atomic(uint64_t) _cfinfoa;
+ /// const char *_ptr;
+ /// uintptr_t _length;
+ /// } __NSConstantString;
+
+ const auto CFRuntime = getLangOpts().CFRuntime;
+ if (static_cast<unsigned>(CFRuntime) <
+ static_cast<unsigned>(LangOptions::CoreFoundationABI::Swift)) {
+ Fields[Count++] = { getPointerType(IntTy.withConst()), "isa" };
+ Fields[Count++] = { IntTy, "flags" };
+ Fields[Count++] = { getPointerType(CharTy.withConst()), "str" };
+ Fields[Count++] = { LongTy, "length" };
+ } else {
+ Fields[Count++] = { getUIntPtrType(), "_cfisa" };
+ Fields[Count++] = { getUIntPtrType(), "_swift_rc" };
+ Fields[Count++] = { getFromTargetType(Target->getUInt64Type()), "_swift_rc" };
+ Fields[Count++] = { getPointerType(CharTy.withConst()), "_ptr" };
+ if (CFRuntime == LangOptions::CoreFoundationABI::Swift4_1 ||
+ CFRuntime == LangOptions::CoreFoundationABI::Swift4_2)
+ Fields[Count++] = { IntTy, "_ptr" };
+ else
+ Fields[Count++] = { getUIntPtrType(), "_ptr" };
}
+ // Create fields
+ for (unsigned i = 0; i < Count; ++i) {
+ FieldDecl *Field =
+ FieldDecl::Create(*this, CFConstantStringTagDecl, SourceLocation(),
+ SourceLocation(), &Idents.get(Fields[i].Name),
+ Fields[i].Type, /*TInfo=*/nullptr,
+ /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit);
+ Field->setAccess(AS_public);
+ CFConstantStringTagDecl->addDecl(Field);
+ }
+
+ CFConstantStringTagDecl->completeDefinition();
+ // This type is designed to be compatible with NSConstantString, but cannot
+ // use the same name, since NSConstantString is an interface.
+ auto tagType = getTagDeclType(CFConstantStringTagDecl);
+ CFConstantStringTypeDecl =
+ buildImplicitTypedef(tagType, "__NSConstantString");
+
return CFConstantStringTypeDecl;
}
@@ -5959,7 +6053,7 @@ LangAS ASTContext::getOpenCLTypeAddrSpace(const Type *T) const {
bool ASTContext::BlockRequiresCopying(QualType Ty,
const VarDecl *D) {
if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) {
- const Expr *copyExpr = getBlockVarCopyInits(D);
+ const Expr *copyExpr = getBlockVarCopyInit(D).getCopyExpr();
if (!copyExpr && record->hasTrivialDestructor()) return false;
return true;
@@ -5999,7 +6093,7 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
bool ASTContext::getByrefLifetime(QualType Ty,
Qualifiers::ObjCLifetime &LifeTime,
bool &HasByrefExtendedLayout) const {
- if (!getLangOpts().ObjC1 ||
+ if (!getLangOpts().ObjC ||
getLangOpts().getGC() != LangOptions::NonGC)
return false;
@@ -6471,6 +6565,9 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
@@ -7677,7 +7774,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const {
if (getLangOpts().getGC() == LangOptions::NonGC)
return Qualifiers::GCNone;
- assert(getLangOpts().ObjC1);
+ assert(getLangOpts().ObjC);
Qualifiers::GC GCAttrs = Ty.getObjCGCAttr();
// Default behaviour under objective-C's gc is for ObjC pointers
@@ -8033,7 +8130,7 @@ void getIntersectionOfProtocols(ASTContext &Context,
// Also add the protocols associated with the LHS interface.
Context.CollectInheritedProtocols(LHS->getInterface(), LHSProtocolSet);
- // Add all of the protocls for the RHS.
+ // Add all of the protocols for the RHS.
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSProtocolSet;
// Start with the protocol qualifiers.
@@ -9384,9 +9481,11 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
// qualified with an address space.
char *End;
unsigned AddrSpace = strtoul(Str, &End, 10);
- if (End != Str && AddrSpace != 0) {
- Type = Context.getAddrSpaceQualType(Type,
- getLangASFromTargetAS(AddrSpace));
+ if (End != Str) {
+ // Note AddrSpace == 0 is not the same as an unspecified address space.
+ Type = Context.getAddrSpaceQualType(
+ Type,
+ Context.getLangASForBuiltinAddressSpace(AddrSpace));
Str = End;
}
if (c == '*')
@@ -9717,6 +9816,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
cast<FunctionDecl>(D)->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition;
+ // Implicit member function definitions, such as operator= might not be
+ // marked as template specializations, since they're not coming from a
+ // template but synthesized directly on the class.
+ IsExpInstDef |=
+ isa<CXXMethodDecl>(D) &&
+ cast<CXXMethodDecl>(D)->getParent()->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+
if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef)
return false;
}
@@ -9766,6 +9873,12 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
const auto *VD = cast<VarDecl>(D);
assert(VD->isFileVarDecl() && "Expected file scoped var");
+ // If the decl is marked as `declare target to`, it should be emitted for the
+ // host and for the device.
+ if (LangOpts.OpenMP &&
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ return true;
+
if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly &&
!isMSStaticDataMemberInlineDefinition(VD))
return false;
@@ -9797,27 +9910,18 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (DeclMustBeEmitted(BindingVD))
return true;
- // If the decl is marked as `declare target`, it should be emitted.
- for (const auto *Decl : D->redecls()) {
- if (!Decl->hasAttrs())
- continue;
- if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>())
- if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link)
- return true;
- }
-
return false;
}
void ASTContext::forEachMultiversionedFunctionVersion(
const FunctionDecl *FD,
- llvm::function_ref<void(const FunctionDecl *)> Pred) const {
+ llvm::function_ref<void(FunctionDecl *)> Pred) const {
assert(FD->isMultiVersion() && "Only valid for multiversioned functions");
llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls;
- FD = FD->getCanonicalDecl();
+ FD = FD->getMostRecentDecl();
for (auto *CurDecl :
FD->getDeclContext()->getRedeclContext()->lookup(FD->getDeclName())) {
- FunctionDecl *CurFD = CurDecl->getAsFunction()->getCanonicalDecl();
+ FunctionDecl *CurFD = CurDecl->getAsFunction()->getMostRecentDecl();
if (CurFD && hasSameType(CurFD->getType(), FD->getType()) &&
std::end(SeenDecls) == llvm::find(SeenDecls, CurFD)) {
SeenDecls.insert(CurFD);
@@ -10054,21 +10158,10 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
return (Size != Align || toBits(sizeChars) > MaxInlineWidthInBits);
}
-static ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap(
- ASTContext::ParentMapPointers::mapped_type U) {
- if (const auto *D = U.dyn_cast<const Decl *>())
- return ast_type_traits::DynTypedNode::create(*D);
- if (const auto *S = U.dyn_cast<const Stmt *>())
- return ast_type_traits::DynTypedNode::create(*S);
- return *U.get<ast_type_traits::DynTypedNode *>();
-}
-
-namespace {
-
/// Template specializations to abstract away from pointers and TypeLocs.
/// @{
template <typename T>
-ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) {
+static ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) {
return ast_type_traits::DynTypedNode::create(*Node);
}
template <>
@@ -10082,160 +10175,121 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
}
/// @}
- /// A \c RecursiveASTVisitor that builds a map from nodes to their
- /// parents as defined by the \c RecursiveASTVisitor.
- ///
- /// Note that the relationship described here is purely in terms of AST
- /// traversal - there are other relationships (for example declaration context)
- /// in the AST that are better modeled by special matchers.
- ///
- /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
- class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> {
- public:
- /// Builds and returns the translation unit's parent map.
- ///
- /// The caller takes ownership of the returned \c ParentMap.
- static std::pair<ASTContext::ParentMapPointers *,
- ASTContext::ParentMapOtherNodes *>
- buildMap(TranslationUnitDecl &TU) {
- ParentMapASTVisitor Visitor(new ASTContext::ParentMapPointers,
- new ASTContext::ParentMapOtherNodes);
- Visitor.TraverseDecl(&TU);
- return std::make_pair(Visitor.Parents, Visitor.OtherParents);
- }
+/// A \c RecursiveASTVisitor that builds a map from nodes to their
+/// parents as defined by the \c RecursiveASTVisitor.
+///
+/// Note that the relationship described here is purely in terms of AST
+/// traversal - there are other relationships (for example declaration context)
+/// in the AST that are better modeled by special matchers.
+///
+/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
+class ASTContext::ParentMap::ASTVisitor
+ : public RecursiveASTVisitor<ASTVisitor> {
+public:
+ ASTVisitor(ParentMap &Map) : Map(Map) {}
- private:
- friend class RecursiveASTVisitor<ParentMapASTVisitor>;
+private:
+ friend class RecursiveASTVisitor<ASTVisitor>;
- using VisitorBase = RecursiveASTVisitor<ParentMapASTVisitor>;
+ using VisitorBase = RecursiveASTVisitor<ASTVisitor>;
- ParentMapASTVisitor(ASTContext::ParentMapPointers *Parents,
- ASTContext::ParentMapOtherNodes *OtherParents)
- : Parents(Parents), OtherParents(OtherParents) {}
+ bool shouldVisitTemplateInstantiations() const { return true; }
- bool shouldVisitTemplateInstantiations() const {
- return true;
- }
+ bool shouldVisitImplicitCode() const { return true; }
- bool shouldVisitImplicitCode() const {
+ template <typename T, typename MapNodeTy, typename BaseTraverseFn,
+ typename MapTy>
+ bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
+ MapTy *Parents) {
+ if (!Node)
return true;
- }
-
- template <typename T, typename MapNodeTy, typename BaseTraverseFn,
- typename MapTy>
- bool TraverseNode(T Node, MapNodeTy MapNode,
- BaseTraverseFn BaseTraverse, MapTy *Parents) {
- if (!Node)
- return true;
- if (ParentStack.size() > 0) {
- // FIXME: Currently we add the same parent multiple times, but only
- // when no memoization data is available for the type.
- // For example when we visit all subexpressions of template
- // instantiations; this is suboptimal, but benign: the only way to
- // visit those is with hasAncestor / hasParent, and those do not create
- // new matches.
- // The plan is to enable DynTypedNode to be storable in a map or hash
- // map. The main problem there is to implement hash functions /
- // comparison operators for all types that DynTypedNode supports that
- // do not have pointer identity.
- auto &NodeOrVector = (*Parents)[MapNode];
- if (NodeOrVector.isNull()) {
- if (const auto *D = ParentStack.back().get<Decl>())
- NodeOrVector = D;
- else if (const auto *S = ParentStack.back().get<Stmt>())
- NodeOrVector = S;
- else
- NodeOrVector =
- new ast_type_traits::DynTypedNode(ParentStack.back());
- } else {
- if (!NodeOrVector.template is<ASTContext::ParentVector *>()) {
- auto *Vector = new ASTContext::ParentVector(
- 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
- delete NodeOrVector
- .template dyn_cast<ast_type_traits::DynTypedNode *>();
- NodeOrVector = Vector;
- }
-
- auto *Vector =
- NodeOrVector.template get<ASTContext::ParentVector *>();
- // Skip duplicates for types that have memoization data.
- // We must check that the type has memoization data before calling
- // std::find() because DynTypedNode::operator== can't compare all
- // types.
- bool Found = ParentStack.back().getMemoizationData() &&
- std::find(Vector->begin(), Vector->end(),
- ParentStack.back()) != Vector->end();
- if (!Found)
- Vector->push_back(ParentStack.back());
+ if (ParentStack.size() > 0) {
+ // FIXME: Currently we add the same parent multiple times, but only
+ // when no memoization data is available for the type.
+ // For example when we visit all subexpressions of template
+ // instantiations; this is suboptimal, but benign: the only way to
+ // visit those is with hasAncestor / hasParent, and those do not create
+ // new matches.
+ // The plan is to enable DynTypedNode to be storable in a map or hash
+ // map. The main problem there is to implement hash functions /
+ // comparison operators for all types that DynTypedNode supports that
+ // do not have pointer identity.
+ auto &NodeOrVector = (*Parents)[MapNode];
+ if (NodeOrVector.isNull()) {
+ if (const auto *D = ParentStack.back().get<Decl>())
+ NodeOrVector = D;
+ else if (const auto *S = ParentStack.back().get<Stmt>())
+ NodeOrVector = S;
+ else
+ NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back());
+ } else {
+ if (!NodeOrVector.template is<ParentVector *>()) {
+ auto *Vector = new ParentVector(
+ 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
+ delete NodeOrVector
+ .template dyn_cast<ast_type_traits::DynTypedNode *>();
+ NodeOrVector = Vector;
}
- }
- ParentStack.push_back(createDynTypedNode(Node));
- bool Result = BaseTraverse();
- ParentStack.pop_back();
- return Result;
- }
- bool TraverseDecl(Decl *DeclNode) {
- return TraverseNode(DeclNode, DeclNode,
- [&] { return VisitorBase::TraverseDecl(DeclNode); },
- Parents);
+ auto *Vector = NodeOrVector.template get<ParentVector *>();
+ // Skip duplicates for types that have memoization data.
+ // We must check that the type has memoization data before calling
+ // std::find() because DynTypedNode::operator== can't compare all
+ // types.
+ bool Found = ParentStack.back().getMemoizationData() &&
+ std::find(Vector->begin(), Vector->end(),
+ ParentStack.back()) != Vector->end();
+ if (!Found)
+ Vector->push_back(ParentStack.back());
+ }
}
+ ParentStack.push_back(createDynTypedNode(Node));
+ bool Result = BaseTraverse();
+ ParentStack.pop_back();
+ return Result;
+ }
- bool TraverseStmt(Stmt *StmtNode) {
- return TraverseNode(StmtNode, StmtNode,
- [&] { return VisitorBase::TraverseStmt(StmtNode); },
- Parents);
- }
+ bool TraverseDecl(Decl *DeclNode) {
+ return TraverseNode(
+ DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); },
+ &Map.PointerParents);
+ }
- bool TraverseTypeLoc(TypeLoc TypeLocNode) {
- return TraverseNode(
- TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode),
- [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
- OtherParents);
- }
+ bool TraverseStmt(Stmt *StmtNode) {
+ return TraverseNode(
+ StmtNode, StmtNode, [&] { return VisitorBase::TraverseStmt(StmtNode); },
+ &Map.PointerParents);
+ }
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
- return TraverseNode(
- NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode),
- [&] {
- return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode);
- },
- OtherParents);
- }
+ bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+ return TraverseNode(
+ TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode),
+ [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
+ &Map.OtherParents);
+ }
- ASTContext::ParentMapPointers *Parents;
- ASTContext::ParentMapOtherNodes *OtherParents;
- llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
- };
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
+ return TraverseNode(
+ NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode),
+ [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); },
+ &Map.OtherParents);
+ }
-} // namespace
+ ParentMap &Map;
+ llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
+};
-template <typename NodeTy, typename MapTy>
-static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
- const MapTy &Map) {
- auto I = Map.find(Node);
- if (I == Map.end()) {
- return llvm::ArrayRef<ast_type_traits::DynTypedNode>();
- }
- if (const auto *V =
- I->second.template dyn_cast<ASTContext::ParentVector *>()) {
- return llvm::makeArrayRef(*V);
- }
- return getSingleDynTypedNodeFromParentMap(I->second);
+ASTContext::ParentMap::ParentMap(ASTContext &Ctx) {
+ ASTVisitor(*this).TraverseAST(Ctx);
}
ASTContext::DynTypedNodeList
ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
- if (!PointerParents) {
- // We always need to run over the whole translation unit, as
+ if (!Parents)
+ // We build the parent map for the traversal scope (usually whole TU), as
// hasAncestor can escape any subtree.
- auto Maps = ParentMapASTVisitor::buildMap(*getTranslationUnitDecl());
- PointerParents.reset(Maps.first);
- OtherParents.reset(Maps.second);
- }
- if (Node.getNodeKind().hasPointerIdentity())
- return getDynNodeFromMap(Node.getMemoizationData(), *PointerParents);
- return getDynNodeFromMap(Node, *OtherParents);
+ Parents = llvm::make_unique<ParentMap>(*this);
+ return Parents->getParents(Node);
}
bool
@@ -10322,6 +10376,16 @@ QualType ASTContext::getCorrespondingSaturatedType(QualType Ty) const {
}
}
+LangAS ASTContext::getLangASForBuiltinAddressSpace(unsigned AS) const {
+ if (LangOpts.OpenCL)
+ return getTargetInfo().getOpenCLBuiltinAddressSpace(AS);
+
+ if (LangOpts.CUDA)
+ return getTargetInfo().getCUDABuiltinAddressSpace(AS);
+
+ return getLangASFromTargetAS(AS);
+}
+
// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that
// doesn't include ASTContext.h
template
@@ -10419,3 +10483,22 @@ unsigned char ASTContext::getFixedPointIBits(QualType Ty) const {
return 0;
}
}
+
+FixedPointSemantics ASTContext::getFixedPointSemantics(QualType Ty) const {
+ assert(Ty->isFixedPointType());
+ bool isSigned = Ty->isSignedFixedPointType();
+ return FixedPointSemantics(
+ static_cast<unsigned>(getTypeSize(Ty)), getFixedPointScale(Ty), isSigned,
+ Ty->isSaturatedFixedPointType(),
+ !isSigned && getTargetInfo().doUnsignedFixedPointTypesHavePadding());
+}
+
+APFixedPoint ASTContext::getFixedPointMax(QualType Ty) const {
+ assert(Ty->isFixedPointType());
+ return APFixedPoint::getMax(getFixedPointSemantics(Ty));
+}
+
+APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const {
+ assert(Ty->isFixedPointType());
+ return APFixedPoint::getMin(getFixedPointSemantics(Ty));
+}
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 50d2d2999e51..dd0585558572 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -334,6 +334,20 @@ void clang::FormatASTNodeDiagnosticArgument(
switch (Kind) {
default: llvm_unreachable("unknown ArgumentKind");
+ case DiagnosticsEngine::ak_qual: {
+ assert(Modifier.empty() && Argument.empty() &&
+ "Invalid modifier for Qualfiers argument");
+
+ Qualifiers Q(Qualifiers::fromOpaqueValue(Val));
+ auto S = Q.getAsString();
+ if (S.empty()) {
+ OS << "unqualified";
+ NeedQuotes = false;
+ } else {
+ OS << Q.getAsString();
+ }
+ break;
+ }
case DiagnosticsEngine::ak_qualtype_pair: {
TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);
QualType FromType =
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 8a653ecebae3..b52ec21943e6 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -13,7 +13,9 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDumperUtils.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/AttrVisitor.h"
#include "clang/AST/CommentVisitor.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclLookups.h"
@@ -22,6 +24,8 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/LocInfoType.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TemplateArgumentVisitor.h"
+#include "clang/AST/TextNodeDumper.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Module.h"
@@ -35,177 +39,35 @@ using namespace clang::comments;
//===----------------------------------------------------------------------===//
namespace {
- // Colors used for various parts of the AST dump
- // Do not use bold yellow for any text. It is hard to read on white screens.
- struct TerminalColor {
- raw_ostream::Colors Color;
- bool Bold;
- };
+ class ASTDumper
+ : public ConstDeclVisitor<ASTDumper>,
+ public ConstStmtVisitor<ASTDumper>,
+ public ConstCommentVisitor<ASTDumper, void, const FullComment *>,
+ public TypeVisitor<ASTDumper>,
+ public ConstAttrVisitor<ASTDumper>,
+ public ConstTemplateArgumentVisitor<ASTDumper> {
- // Red - CastColor
- // Green - TypeColor
- // Bold Green - DeclKindNameColor, UndeserializedColor
- // Yellow - AddressColor, LocationColor
- // Blue - CommentColor, NullColor, IndentColor
- // Bold Blue - AttrColor
- // Bold Magenta - StmtColor
- // Cyan - ValueKindColor, ObjectKindColor
- // Bold Cyan - ValueColor, DeclNameColor
-
- // Decl kind names (VarDecl, FunctionDecl, etc)
- static const TerminalColor DeclKindNameColor = { raw_ostream::GREEN, true };
- // Attr names (CleanupAttr, GuardedByAttr, etc)
- static const TerminalColor AttrColor = { raw_ostream::BLUE, true };
- // Statement names (DeclStmt, ImplicitCastExpr, etc)
- static const TerminalColor StmtColor = { raw_ostream::MAGENTA, true };
- // Comment names (FullComment, ParagraphComment, TextComment, etc)
- static const TerminalColor CommentColor = { raw_ostream::BLUE, false };
-
- // Type names (int, float, etc, plus user defined types)
- static const TerminalColor TypeColor = { raw_ostream::GREEN, false };
-
- // Pointer address
- static const TerminalColor AddressColor = { raw_ostream::YELLOW, false };
- // Source locations
- static const TerminalColor LocationColor = { raw_ostream::YELLOW, false };
-
- // lvalue/xvalue
- static const TerminalColor ValueKindColor = { raw_ostream::CYAN, false };
- // bitfield/objcproperty/objcsubscript/vectorcomponent
- static const TerminalColor ObjectKindColor = { raw_ostream::CYAN, false };
-
- // Null statements
- static const TerminalColor NullColor = { raw_ostream::BLUE, false };
-
- // Undeserialized entities
- static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true };
-
- // CastKind from CastExpr's
- static const TerminalColor CastColor = { raw_ostream::RED, false };
-
- // Value of the statement
- static const TerminalColor ValueColor = { raw_ostream::CYAN, true };
- // Decl names
- static const TerminalColor DeclNameColor = { raw_ostream::CYAN, true };
-
- // Indents ( `, -. | )
- static const TerminalColor IndentColor = { raw_ostream::BLUE, false };
+ TextNodeDumper NodeDumper;
- class ASTDumper
- : public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>,
- public ConstCommentVisitor<ASTDumper>, public TypeVisitor<ASTDumper> {
raw_ostream &OS;
- const CommandTraits *Traits;
- const SourceManager *SM;
/// The policy to use for printing; can be defaulted.
PrintingPolicy PrintPolicy;
- /// Pending[i] is an action to dump an entity at level i.
- llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending;
-
/// Indicates whether we should trigger deserialization of nodes that had
/// not already been loaded.
bool Deserialize = false;
- /// Indicates whether we're at the top level.
- bool TopLevel = true;
-
- /// Indicates if we're handling the first child after entering a new depth.
- bool FirstChild = true;
-
- /// Prefix for currently-being-dumped entity.
- std::string Prefix;
-
- /// Keep track of the last location we print out so that we can
- /// print out deltas from then on out.
- const char *LastLocFilename = "";
- unsigned LastLocLine = ~0U;
-
- /// The \c FullComment parent of the comment being dumped.
- const FullComment *FC = nullptr;
-
- bool ShowColors;
+ const bool ShowColors;
/// Dump a child of the current node.
- template<typename Fn> void dumpChild(Fn doDumpChild) {
- // If we're at the top level, there's nothing interesting to do; just
- // run the dumper.
- if (TopLevel) {
- TopLevel = false;
- doDumpChild();
- while (!Pending.empty()) {
- Pending.back()(true);
- Pending.pop_back();
- }
- Prefix.clear();
- OS << "\n";
- TopLevel = true;
- return;
- }
-
- const FullComment *OrigFC = FC;
- auto dumpWithIndent = [this, doDumpChild, OrigFC](bool isLastChild) {
- // Print out the appropriate tree structure and work out the prefix for
- // children of this node. For instance:
- //
- // A Prefix = ""
- // |-B Prefix = "| "
- // | `-C Prefix = "| "
- // `-D Prefix = " "
- // |-E Prefix = " | "
- // `-F Prefix = " "
- // G Prefix = ""
- //
- // Note that the first level gets no prefix.
- {
- OS << '\n';
- ColorScope Color(*this, IndentColor);
- OS << Prefix << (isLastChild ? '`' : '|') << '-';
- this->Prefix.push_back(isLastChild ? ' ' : '|');
- this->Prefix.push_back(' ');
- }
-
- FirstChild = true;
- unsigned Depth = Pending.size();
-
- FC = OrigFC;
- doDumpChild();
-
- // If any children are left, they're the last at their nesting level.
- // Dump those ones out now.
- while (Depth < Pending.size()) {
- Pending.back()(true);
- this->Pending.pop_back();
- }
-
- // Restore the old prefix.
- this->Prefix.resize(Prefix.size() - 2);
- };
-
- if (FirstChild) {
- Pending.push_back(std::move(dumpWithIndent));
- } else {
- Pending.back()(false);
- Pending.back() = std::move(dumpWithIndent);
- }
- FirstChild = false;
+ template<typename Fn> void dumpChild(Fn DoDumpChild) {
+ NodeDumper.AddChild(DoDumpChild);
+ }
+ template <typename Fn> void dumpChild(StringRef Label, Fn DoDumpChild) {
+ NodeDumper.AddChild(Label, DoDumpChild);
}
-
- class ColorScope {
- ASTDumper &Dumper;
- public:
- ColorScope(ASTDumper &Dumper, TerminalColor Color)
- : Dumper(Dumper) {
- if (Dumper.ShowColors)
- Dumper.OS.changeColor(Color.Color, Color.Bold);
- }
- ~ColorScope() {
- if (Dumper.ShowColors)
- Dumper.OS.resetColor();
- }
- };
public:
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
@@ -219,40 +81,39 @@ namespace {
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM, bool ShowColors,
const PrintingPolicy &PrintPolicy)
- : OS(OS), Traits(Traits), SM(SM), PrintPolicy(PrintPolicy),
- ShowColors(ShowColors) {}
+ : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS),
+ PrintPolicy(PrintPolicy), ShowColors(ShowColors) {}
void setDeserialize(bool D) { Deserialize = D; }
void dumpDecl(const Decl *D);
- void dumpStmt(const Stmt *S);
- void dumpFullComment(const FullComment *C);
+ void dumpStmt(const Stmt *S, StringRef Label = {});
// Utilities
- void dumpPointer(const void *Ptr);
- void dumpSourceRange(SourceRange R);
- void dumpLocation(SourceLocation Loc);
- void dumpBareType(QualType T, bool Desugar = true);
- void dumpType(QualType T);
void dumpTypeAsChild(QualType T);
void dumpTypeAsChild(const Type *T);
- void dumpBareDeclRef(const Decl *Node);
- void dumpDeclRef(const Decl *Node, const char *Label = nullptr);
- void dumpName(const NamedDecl *D);
- bool hasNodes(const DeclContext *DC);
void dumpDeclContext(const DeclContext *DC);
void dumpLookups(const DeclContext *DC, bool DumpDecls);
void dumpAttr(const Attr *A);
// C++ Utilities
- void dumpAccessSpecifier(AccessSpecifier AS);
void dumpCXXCtorInitializer(const CXXCtorInitializer *Init);
void dumpTemplateParameters(const TemplateParameterList *TPL);
void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI);
- void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A);
+ void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A,
+ const Decl *From = nullptr,
+ const char *Label = nullptr);
void dumpTemplateArgumentList(const TemplateArgumentList &TAL);
void dumpTemplateArgument(const TemplateArgument &A,
- SourceRange R = SourceRange());
+ SourceRange R = SourceRange(),
+ const Decl *From = nullptr,
+ const char *Label = nullptr);
+ template <typename SpecializationDecl>
+ void dumpTemplateDeclSpecialization(const SpecializationDecl *D,
+ bool DumpExplicitInst,
+ bool DumpRefOnly);
+ template <typename TemplateDecl>
+ void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
// Objective-C utilities.
void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams);
@@ -261,6 +122,9 @@ namespace {
void VisitComplexType(const ComplexType *T) {
dumpTypeAsChild(T->getElementType());
}
+ void VisitLocInfoType(const LocInfoType *T) {
+ dumpTypeAsChild(T->getTypeSourceInfo()->getType());
+ }
void VisitPointerType(const PointerType *T) {
dumpTypeAsChild(T->getPointeeType());
}
@@ -270,92 +134,39 @@ namespace {
void VisitReferenceType(const ReferenceType *T) {
dumpTypeAsChild(T->getPointeeType());
}
- void VisitRValueReferenceType(const ReferenceType *T) {
- if (T->isSpelledAsLValue())
- OS << " written as lvalue reference";
- VisitReferenceType(T);
- }
void VisitMemberPointerType(const MemberPointerType *T) {
dumpTypeAsChild(T->getClass());
dumpTypeAsChild(T->getPointeeType());
}
void VisitArrayType(const ArrayType *T) {
- switch (T->getSizeModifier()) {
- case ArrayType::Normal: break;
- case ArrayType::Static: OS << " static"; break;
- case ArrayType::Star: OS << " *"; break;
- }
- OS << " " << T->getIndexTypeQualifiers().getAsString();
dumpTypeAsChild(T->getElementType());
}
- void VisitConstantArrayType(const ConstantArrayType *T) {
- OS << " " << T->getSize();
- VisitArrayType(T);
- }
void VisitVariableArrayType(const VariableArrayType *T) {
- OS << " ";
- dumpSourceRange(T->getBracketsRange());
VisitArrayType(T);
dumpStmt(T->getSizeExpr());
}
void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
- VisitArrayType(T);
- OS << " ";
- dumpSourceRange(T->getBracketsRange());
+ dumpTypeAsChild(T->getElementType());
dumpStmt(T->getSizeExpr());
}
void VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
- OS << " ";
- dumpLocation(T->getAttributeLoc());
dumpTypeAsChild(T->getElementType());
dumpStmt(T->getSizeExpr());
}
void VisitVectorType(const VectorType *T) {
- switch (T->getVectorKind()) {
- case VectorType::GenericVector: break;
- case VectorType::AltiVecVector: OS << " altivec"; break;
- case VectorType::AltiVecPixel: OS << " altivec pixel"; break;
- case VectorType::AltiVecBool: OS << " altivec bool"; break;
- case VectorType::NeonVector: OS << " neon"; break;
- case VectorType::NeonPolyVector: OS << " neon poly"; break;
- }
- OS << " " << T->getNumElements();
dumpTypeAsChild(T->getElementType());
}
void VisitFunctionType(const FunctionType *T) {
- auto EI = T->getExtInfo();
- if (EI.getNoReturn()) OS << " noreturn";
- if (EI.getProducesResult()) OS << " produces_result";
- if (EI.getHasRegParm()) OS << " regparm " << EI.getRegParm();
- OS << " " << FunctionType::getNameForCallConv(EI.getCC());
dumpTypeAsChild(T->getReturnType());
}
void VisitFunctionProtoType(const FunctionProtoType *T) {
- auto EPI = T->getExtProtoInfo();
- if (EPI.HasTrailingReturn) OS << " trailing_return";
- if (T->isConst()) OS << " const";
- if (T->isVolatile()) OS << " volatile";
- if (T->isRestrict()) OS << " restrict";
- switch (EPI.RefQualifier) {
- case RQ_None: break;
- case RQ_LValue: OS << " &"; break;
- case RQ_RValue: OS << " &&"; break;
- }
- // FIXME: Exception specification.
- // FIXME: Consumed parameters.
VisitFunctionType(T);
for (QualType PT : T->getParamTypes())
dumpTypeAsChild(PT);
- if (EPI.Variadic)
+ if (T->getExtProtoInfo().Variadic)
dumpChild([=] { OS << "..."; });
}
- void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
- dumpDeclRef(T->getDecl());
- }
- void VisitTypedefType(const TypedefType *T) {
- dumpDeclRef(T->getDecl());
- }
void VisitTypeOfExprType(const TypeOfExprType *T) {
dumpStmt(T->getUnderlyingExpr());
}
@@ -363,25 +174,12 @@ namespace {
dumpStmt(T->getUnderlyingExpr());
}
void VisitUnaryTransformType(const UnaryTransformType *T) {
- switch (T->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- OS << " underlying_type";
- break;
- }
dumpTypeAsChild(T->getBaseType());
}
- void VisitTagType(const TagType *T) {
- dumpDeclRef(T->getDecl());
- }
void VisitAttributedType(const AttributedType *T) {
// FIXME: AttrKind
dumpTypeAsChild(T->getModifiedType());
}
- void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
- OS << " depth " << T->getDepth() << " index " << T->getIndex();
- if (T->isParameterPack()) OS << " pack";
- dumpDeclRef(T->getDecl());
- }
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
dumpTypeAsChild(T->getReplacedParameter());
}
@@ -390,25 +188,12 @@ namespace {
dumpTypeAsChild(T->getReplacedParameter());
dumpTemplateArgument(T->getArgumentPack());
}
- void VisitAutoType(const AutoType *T) {
- if (T->isDecltypeAuto()) OS << " decltype(auto)";
- if (!T->isDeduced())
- OS << " undeduced";
- }
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
- if (T->isTypeAlias()) OS << " alias";
- OS << " "; T->getTemplateName().dump(OS);
for (auto &Arg : *T)
dumpTemplateArgument(Arg);
if (T->isTypeAlias())
dumpTypeAsChild(T->getAliasedType());
}
- void VisitInjectedClassNameType(const InjectedClassNameType *T) {
- dumpDeclRef(T->getDecl());
- }
- void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
- dumpDeclRef(T->getDecl());
- }
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
dumpTypeAsChild(T->getPointeeType());
}
@@ -422,7 +207,6 @@ namespace {
dumpTypeAsChild(T->getOriginalType());
}
void VisitPackExpansionType(const PackExpansionType *T) {
- if (auto N = T->getNumExpansions()) OS << " expansions " << *N;
if (!T->isSugared())
dumpTypeAsChild(T->getPattern());
}
@@ -450,6 +234,7 @@ namespace {
// OpenMP decls
void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D);
void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D);
+ void VisitOMPRequiresDecl(const OMPRequiresDecl *D);
void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D);
// C++ Decls
@@ -460,12 +245,6 @@ namespace {
void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D);
void VisitCXXRecordDecl(const CXXRecordDecl *D);
void VisitStaticAssertDecl(const StaticAssertDecl *D);
- template<typename SpecializationDecl>
- void VisitTemplateDeclSpecialization(const SpecializationDecl *D,
- bool DumpExplicitInst,
- bool DumpRefOnly);
- template<typename TemplateDecl>
- void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
void VisitClassTemplateDecl(const ClassTemplateDecl *D);
void VisitClassTemplateSpecializationDecl(
@@ -504,96 +283,47 @@ namespace {
void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
+ void Visit(const BlockDecl::Capture &C);
void VisitBlockDecl(const BlockDecl *D);
// Stmts.
- void VisitStmt(const Stmt *Node);
void VisitDeclStmt(const DeclStmt *Node);
void VisitAttributedStmt(const AttributedStmt *Node);
- void VisitLabelStmt(const LabelStmt *Node);
- void VisitGotoStmt(const GotoStmt *Node);
void VisitCXXCatchStmt(const CXXCatchStmt *Node);
void VisitCapturedStmt(const CapturedStmt *Node);
// OpenMP
+ void Visit(const OMPClause *C);
void VisitOMPExecutableDirective(const OMPExecutableDirective *Node);
// Exprs
- void VisitExpr(const Expr *Node);
- void VisitCastExpr(const CastExpr *Node);
- void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
- void VisitDeclRefExpr(const DeclRefExpr *Node);
- void VisitPredefinedExpr(const PredefinedExpr *Node);
- void VisitCharacterLiteral(const CharacterLiteral *Node);
- void VisitIntegerLiteral(const IntegerLiteral *Node);
- void VisitFixedPointLiteral(const FixedPointLiteral *Node);
- void VisitFloatingLiteral(const FloatingLiteral *Node);
- void VisitStringLiteral(const StringLiteral *Str);
void VisitInitListExpr(const InitListExpr *ILE);
- void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *ILE);
- void VisitArrayInitIndexExpr(const ArrayInitIndexExpr *ILE);
- void VisitUnaryOperator(const UnaryOperator *Node);
- void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
- void VisitMemberExpr(const MemberExpr *Node);
- void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node);
- void VisitBinaryOperator(const BinaryOperator *Node);
- void VisitCompoundAssignOperator(const CompoundAssignOperator *Node);
- void VisitAddrLabelExpr(const AddrLabelExpr *Node);
void VisitBlockExpr(const BlockExpr *Node);
void VisitOpaqueValueExpr(const OpaqueValueExpr *Node);
void VisitGenericSelectionExpr(const GenericSelectionExpr *E);
// C++
- void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
- void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);
- void VisitCXXThisExpr(const CXXThisExpr *Node);
- void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
- void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node);
- void VisitCXXConstructExpr(const CXXConstructExpr *Node);
- void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
- void VisitCXXNewExpr(const CXXNewExpr *Node);
- void VisitCXXDeleteExpr(const CXXDeleteExpr *Node);
- void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
- void VisitExprWithCleanups(const ExprWithCleanups *Node);
- void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
- void dumpCXXTemporary(const CXXTemporary *Temporary);
void VisitLambdaExpr(const LambdaExpr *Node) {
- VisitExpr(Node);
dumpDecl(Node->getLambdaClass());
}
void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
- void
- VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node);
// ObjC
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
- void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node);
- void VisitObjCMessageExpr(const ObjCMessageExpr *Node);
- void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node);
- void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node);
- void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node);
- void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node);
- void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node);
- void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node);
- void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node);
// Comments.
- const char *getCommandName(unsigned CommandID);
- void dumpComment(const Comment *C);
-
- // Inline comments.
- void visitTextComment(const TextComment *C);
- void visitInlineCommandComment(const InlineCommandComment *C);
- void visitHTMLStartTagComment(const HTMLStartTagComment *C);
- void visitHTMLEndTagComment(const HTMLEndTagComment *C);
-
- // Block comments.
- void visitBlockCommandComment(const BlockCommandComment *C);
- void visitParamCommandComment(const ParamCommandComment *C);
- void visitTParamCommandComment(const TParamCommandComment *C);
- void visitVerbatimBlockComment(const VerbatimBlockComment *C);
- void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
- void visitVerbatimLineComment(const VerbatimLineComment *C);
+ void dumpComment(const Comment *C, const FullComment *FC);
+
+ void VisitExpressionTemplateArgument(const TemplateArgument &TA) {
+ dumpStmt(TA.getAsExpr());
+ }
+ void VisitPackTemplateArgument(const TemplateArgument &TA) {
+ for (const auto &TArg : TA.pack_elements())
+ dumpTemplateArgument(TArg);
+ }
+
+// Implements Visit methods for Attrs.
+#include "clang/AST/AttrNodeTraverse.inc"
};
}
@@ -601,188 +331,31 @@ namespace {
// Utilities
//===----------------------------------------------------------------------===//
-void ASTDumper::dumpPointer(const void *Ptr) {
- ColorScope Color(*this, AddressColor);
- OS << ' ' << Ptr;
-}
-
-void ASTDumper::dumpLocation(SourceLocation Loc) {
- if (!SM)
- return;
-
- ColorScope Color(*this, LocationColor);
- SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
-
- // The general format we print out is filename:line:col, but we drop pieces
- // that haven't changed since the last loc printed.
- PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
-
- if (PLoc.isInvalid()) {
- OS << "<invalid sloc>";
- return;
- }
-
- if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
- OS << PLoc.getFilename() << ':' << PLoc.getLine()
- << ':' << PLoc.getColumn();
- LastLocFilename = PLoc.getFilename();
- LastLocLine = PLoc.getLine();
- } else if (PLoc.getLine() != LastLocLine) {
- OS << "line" << ':' << PLoc.getLine()
- << ':' << PLoc.getColumn();
- LastLocLine = PLoc.getLine();
- } else {
- OS << "col" << ':' << PLoc.getColumn();
- }
-}
-
-void ASTDumper::dumpSourceRange(SourceRange R) {
- // Can't translate locations if a SourceManager isn't available.
- if (!SM)
- return;
-
- OS << " <";
- dumpLocation(R.getBegin());
- if (R.getBegin() != R.getEnd()) {
- OS << ", ";
- dumpLocation(R.getEnd());
- }
- OS << ">";
-
- // <t2.c:123:421[blah], t2.c:412:321>
-
-}
-
-void ASTDumper::dumpBareType(QualType T, bool Desugar) {
- ColorScope Color(*this, TypeColor);
-
- SplitQualType T_split = T.split();
- OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'";
-
- if (Desugar && !T.isNull()) {
- // If the type is sugared, also dump a (shallow) desugared type.
- SplitQualType D_split = T.getSplitDesugaredType();
- if (T_split != D_split)
- OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
- }
-}
-
-void ASTDumper::dumpType(QualType T) {
- OS << ' ';
- dumpBareType(T);
-}
-
void ASTDumper::dumpTypeAsChild(QualType T) {
SplitQualType SQT = T.split();
if (!SQT.Quals.hasQualifiers())
return dumpTypeAsChild(SQT.Ty);
dumpChild([=] {
- OS << "QualType";
- dumpPointer(T.getAsOpaquePtr());
- OS << " ";
- dumpBareType(T, false);
- OS << " " << T.split().Quals.getAsString();
+ NodeDumper.Visit(T);
dumpTypeAsChild(T.split().Ty);
});
}
void ASTDumper::dumpTypeAsChild(const Type *T) {
dumpChild([=] {
- if (!T) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
- return;
- }
- if (const LocInfoType *LIT = llvm::dyn_cast<LocInfoType>(T)) {
- {
- ColorScope Color(*this, TypeColor);
- OS << "LocInfo Type";
- }
- dumpPointer(T);
- dumpTypeAsChild(LIT->getTypeSourceInfo()->getType());
+ NodeDumper.Visit(T);
+ if (!T)
return;
- }
-
- {
- ColorScope Color(*this, TypeColor);
- OS << T->getTypeClassName() << "Type";
- }
- dumpPointer(T);
- OS << " ";
- dumpBareType(QualType(T, 0), false);
+ TypeVisitor<ASTDumper>::Visit(T);
QualType SingleStepDesugar =
T->getLocallyUnqualifiedSingleStepDesugaredType();
if (SingleStepDesugar != QualType(T, 0))
- OS << " sugar";
- if (T->isDependentType())
- OS << " dependent";
- else if (T->isInstantiationDependentType())
- OS << " instantiation_dependent";
- if (T->isVariablyModifiedType())
- OS << " variably_modified";
- if (T->containsUnexpandedParameterPack())
- OS << " contains_unexpanded_pack";
- if (T->isFromAST())
- OS << " imported";
-
- TypeVisitor<ASTDumper>::Visit(T);
-
- if (SingleStepDesugar != QualType(T, 0))
dumpTypeAsChild(SingleStepDesugar);
});
}
-void ASTDumper::dumpBareDeclRef(const Decl *D) {
- if (!D) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
- return;
- }
-
- {
- ColorScope Color(*this, DeclKindNameColor);
- OS << D->getDeclKindName();
- }
- dumpPointer(D);
-
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- ColorScope Color(*this, DeclNameColor);
- OS << " '" << ND->getDeclName() << '\'';
- }
-
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
- dumpType(VD->getType());
-}
-
-void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) {
- if (!D)
- return;
-
- dumpChild([=]{
- if (Label)
- OS << Label << ' ';
- dumpBareDeclRef(D);
- });
-}
-
-void ASTDumper::dumpName(const NamedDecl *ND) {
- if (ND->getDeclName()) {
- ColorScope Color(*this, DeclNameColor);
- OS << ' ' << ND->getNameAsString();
- }
-}
-
-bool ASTDumper::hasNodes(const DeclContext *DC) {
- if (!DC)
- return false;
-
- return DC->hasExternalLexicalStorage() ||
- (Deserialize ? DC->decls_begin() != DC->decls_end()
- : DC->noload_decls_begin() != DC->noload_decls_end());
-}
-
void ASTDumper::dumpDeclContext(const DeclContext *DC) {
if (!DC)
return;
@@ -791,8 +364,8 @@ void ASTDumper::dumpDeclContext(const DeclContext *DC) {
dumpDecl(D);
if (DC->hasExternalLexicalStorage()) {
- dumpChild([=]{
- ColorScope Color(*this, UndeserializedColor);
+ dumpChild([=] {
+ ColorScope Color(OS, ShowColors, UndeserializedColor);
OS << "<undeserialized declarations>";
});
}
@@ -801,12 +374,12 @@ void ASTDumper::dumpDeclContext(const DeclContext *DC) {
void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
dumpChild([=] {
OS << "StoredDeclsMap ";
- dumpBareDeclRef(cast<Decl>(DC));
+ NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
const DeclContext *Primary = DC->getPrimaryContext();
if (Primary != DC) {
OS << " primary";
- dumpPointer(cast<Decl>(Primary));
+ NodeDumper.dumpPointer(cast<Decl>(Primary));
}
bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
@@ -821,14 +394,14 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
dumpChild([=] {
OS << "DeclarationName ";
{
- ColorScope Color(*this, DeclNameColor);
+ ColorScope Color(OS, ShowColors, DeclNameColor);
OS << '\'' << Name << '\'';
}
for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
RI != RE; ++RI) {
dumpChild([=] {
- dumpBareDeclRef(*RI);
+ NodeDumper.dumpBareDeclRef(*RI);
if ((*RI)->isHidden())
OS << " hidden";
@@ -850,7 +423,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
if (HasUndeserializedLookups) {
dumpChild([=] {
- ColorScope Color(*this, UndeserializedColor);
+ ColorScope Color(OS, ShowColors, UndeserializedColor);
OS << "<undeserialized lookups>";
});
}
@@ -859,87 +432,18 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
void ASTDumper::dumpAttr(const Attr *A) {
dumpChild([=] {
- {
- ColorScope Color(*this, AttrColor);
-
- switch (A->getKind()) {
-#define ATTR(X) case attr::X: OS << #X; break;
-#include "clang/Basic/AttrList.inc"
- }
- OS << "Attr";
- }
- dumpPointer(A);
- dumpSourceRange(A->getRange());
- if (A->isInherited())
- OS << " Inherited";
- if (A->isImplicit())
- OS << " Implicit";
-#include "clang/AST/AttrDump.inc"
+ NodeDumper.Visit(A);
+ ConstAttrVisitor<ASTDumper>::Visit(A);
});
}
-static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
-
-template<typename T>
-static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) {
- const T *First = D->getFirstDecl();
- if (First != D)
- OS << " first " << First;
-}
-
-template<typename T>
-static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) {
- const T *Prev = D->getPreviousDecl();
- if (Prev)
- OS << " prev " << Prev;
-}
-
-/// Dump the previous declaration in the redeclaration chain for a declaration,
-/// if any.
-static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
- switch (D->getKind()) {
-#define DECL(DERIVED, BASE) \
- case Decl::DERIVED: \
- return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D));
-#define ABSTRACT_DECL(DECL)
-#include "clang/AST/DeclNodes.inc"
- }
- llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
-}
-
//===----------------------------------------------------------------------===//
// C++ Utilities
//===----------------------------------------------------------------------===//
-void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) {
- switch (AS) {
- case AS_none:
- break;
- case AS_public:
- OS << "public";
- break;
- case AS_protected:
- OS << "protected";
- break;
- case AS_private:
- OS << "private";
- break;
- }
-}
-
void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) {
dumpChild([=] {
- OS << "CXXCtorInitializer";
- if (Init->isAnyMemberInitializer()) {
- OS << ' ';
- dumpBareDeclRef(Init->getAnyMember());
- } else if (Init->isBaseInitializer()) {
- dumpType(QualType(Init->getBaseClass(), 0));
- } else if (Init->isDelegatingInitializer()) {
- dumpType(Init->getTypeSourceInfo()->getType());
- } else {
- llvm_unreachable("Unknown initializer type");
- }
+ NodeDumper.Visit(Init);
dumpStmt(Init->getInit());
});
}
@@ -959,8 +463,9 @@ void ASTDumper::dumpTemplateArgumentListInfo(
dumpTemplateArgumentLoc(TALI[i]);
}
-void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) {
- dumpTemplateArgument(A.getArgument(), A.getSourceRange());
+void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A,
+ const Decl *From, const char *Label) {
+ dumpTemplateArgument(A.getArgument(), A.getSourceRange(), From, Label);
}
void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) {
@@ -968,49 +473,11 @@ void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) {
dumpTemplateArgument(TAL[i]);
}
-void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) {
+void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R,
+ const Decl *From, const char *Label) {
dumpChild([=] {
- OS << "TemplateArgument";
- if (R.isValid())
- dumpSourceRange(R);
-
- switch (A.getKind()) {
- case TemplateArgument::Null:
- OS << " null";
- break;
- case TemplateArgument::Type:
- OS << " type";
- dumpType(A.getAsType());
- break;
- case TemplateArgument::Declaration:
- OS << " decl";
- dumpDeclRef(A.getAsDecl());
- break;
- case TemplateArgument::NullPtr:
- OS << " nullptr";
- break;
- case TemplateArgument::Integral:
- OS << " integral " << A.getAsIntegral();
- break;
- case TemplateArgument::Template:
- OS << " template ";
- A.getAsTemplate().dump(OS);
- break;
- case TemplateArgument::TemplateExpansion:
- OS << " template expansion";
- A.getAsTemplateOrTemplatePattern().dump(OS);
- break;
- case TemplateArgument::Expression:
- OS << " expr";
- dumpStmt(A.getAsExpr());
- break;
- case TemplateArgument::Pack:
- OS << " pack";
- for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end();
- I != E; ++I)
- dumpTemplateArgument(*I);
- break;
- }
+ NodeDumper.Visit(A, R, From, Label);
+ ConstTemplateArgumentVisitor<ASTDumper>::Visit(A);
});
}
@@ -1032,46 +499,9 @@ void ASTDumper::dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) {
void ASTDumper::dumpDecl(const Decl *D) {
dumpChild([=] {
- if (!D) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
+ NodeDumper.Visit(D);
+ if (!D)
return;
- }
-
- {
- ColorScope Color(*this, DeclKindNameColor);
- OS << D->getDeclKindName() << "Decl";
- }
- dumpPointer(D);
- if (D->getLexicalDeclContext() != D->getDeclContext())
- OS << " parent " << cast<Decl>(D->getDeclContext());
- dumpPreviousDecl(OS, D);
- dumpSourceRange(D->getSourceRange());
- OS << ' ';
- dumpLocation(D->getLocation());
- if (D->isFromASTFile())
- OS << " imported";
- if (Module *M = D->getOwningModule())
- OS << " in " << M->getFullModuleName();
- if (auto *ND = dyn_cast<NamedDecl>(D))
- for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
- const_cast<NamedDecl *>(ND)))
- dumpChild([=] { OS << "also in " << M->getFullModuleName(); });
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- if (ND->isHidden())
- OS << " hidden";
- if (D->isImplicit())
- OS << " implicit";
- if (D->isUsed())
- OS << " used";
- else if (D->isThisDeclarationReferenced())
- OS << " referenced";
- if (D->isInvalidDecl())
- OS << " invalid";
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- if (FD->isConstexpr())
- OS << " constexpr";
-
ConstDeclVisitor<ASTDumper>::Visit(D);
@@ -1081,22 +511,25 @@ void ASTDumper::dumpDecl(const Decl *D) {
if (const FullComment *Comment =
D->getASTContext().getLocalCommentForDeclUncached(D))
- dumpFullComment(Comment);
+ dumpComment(Comment, Comment);
// Decls within functions are visited by the body.
- if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) &&
- hasNodes(dyn_cast<DeclContext>(D)))
- dumpDeclContext(cast<DeclContext>(D));
+ if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) {
+ auto DC = dyn_cast<DeclContext>(D);
+ if (DC &&
+ (DC->hasExternalLexicalStorage() ||
+ (Deserialize ? DC->decls_begin() != DC->decls_end()
+ : DC->noload_decls_begin() != DC->noload_decls_end())))
+ dumpDeclContext(DC);
+ }
});
}
-void ASTDumper::VisitLabelDecl(const LabelDecl *D) {
- dumpName(D);
-}
+void ASTDumper::VisitLabelDecl(const LabelDecl *D) { NodeDumper.dumpName(D); }
void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
- dumpName(D);
- dumpType(D->getUnderlyingType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getUnderlyingType());
if (D->isModulePrivate())
OS << " __module_private__";
dumpTypeAsChild(D->getUnderlyingType());
@@ -1109,16 +542,16 @@ void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
else
OS << " struct";
}
- dumpName(D);
+ NodeDumper.dumpName(D);
if (D->isModulePrivate())
OS << " __module_private__";
if (D->isFixed())
- dumpType(D->getIntegerType());
+ NodeDumper.dumpType(D->getIntegerType());
}
void ASTDumper::VisitRecordDecl(const RecordDecl *D) {
OS << ' ' << D->getKindName();
- dumpName(D);
+ NodeDumper.dumpName(D);
if (D->isModulePrivate())
OS << " __module_private__";
if (D->isCompleteDefinition())
@@ -1126,23 +559,23 @@ void ASTDumper::VisitRecordDecl(const RecordDecl *D) {
}
void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
if (const Expr *Init = D->getInitExpr())
dumpStmt(Init);
}
void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
for (auto *Child : D->chain())
- dumpDeclRef(Child);
+ NodeDumper.dumpDeclRef(Child);
}
void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
StorageClass SC = D->getStorageClass();
if (SC != SC_None)
@@ -1166,7 +599,7 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
if (D->isTrivial())
OS << " trivial";
- if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) {
+ if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
switch (EPI.ExceptionSpec.Type) {
default: break;
@@ -1179,23 +612,7 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
}
}
- if (const FunctionTemplateSpecializationInfo *FTSI =
- D->getTemplateSpecializationInfo())
- dumpTemplateArgumentList(*FTSI->TemplateArguments);
-
- if (!D->param_begin() && D->getNumParams())
- dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; });
- else
- for (const ParmVarDecl *Parameter : D->parameters())
- dumpDecl(Parameter);
-
- if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D))
- for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
- E = C->init_end();
- I != E; ++I)
- dumpCXXCtorInitializer(*I);
-
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->size_overridden_methods() != 0) {
auto dumpOverride = [=](const CXXMethodDecl *D) {
SplitQualType T_split = D->getType().split();
@@ -1218,13 +635,26 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
}
}
+ if (const auto *FTSI = D->getTemplateSpecializationInfo())
+ dumpTemplateArgumentList(*FTSI->TemplateArguments);
+
+ if (!D->param_begin() && D->getNumParams())
+ dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; });
+ else
+ for (const ParmVarDecl *Parameter : D->parameters())
+ dumpDecl(Parameter);
+
+ if (const auto *C = dyn_cast<CXXConstructorDecl>(D))
+ for (const auto *I : C->inits())
+ dumpCXXCtorInitializer(I);
+
if (D->doesThisDeclarationHaveABody())
dumpStmt(D->getBody());
}
void ASTDumper::VisitFieldDecl(const FieldDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
if (D->isMutable())
OS << " mutable";
if (D->isModulePrivate())
@@ -1237,8 +667,8 @@ void ASTDumper::VisitFieldDecl(const FieldDecl *D) {
}
void ASTDumper::VisitVarDecl(const VarDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
StorageClass SC = D->getStorageClass();
if (SC != SC_None)
OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
@@ -1272,8 +702,8 @@ void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) {
}
void ASTDumper::VisitBindingDecl(const BindingDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
if (auto *E = D->getBinding())
dumpStmt(E);
}
@@ -1320,12 +750,13 @@ void ASTDumper::VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
}
void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
OS << " combiner";
- dumpStmt(D->getCombiner());
- if (auto *Initializer = D->getInitializer()) {
+ NodeDumper.dumpPointer(D->getCombiner());
+ if (const auto *Initializer = D->getInitializer()) {
OS << " initializer";
+ NodeDumper.dumpPointer(Initializer);
switch (D->getInitializerKind()) {
case OMPDeclareReductionDecl::DirectInit:
OS << " omp_priv = ";
@@ -1336,13 +767,36 @@ void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) {
case OMPDeclareReductionDecl::CallInit:
break;
}
+ }
+
+ dumpStmt(D->getCombiner());
+ if (const auto *Initializer = D->getInitializer())
dumpStmt(Initializer);
+}
+
+void ASTDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) {
+ for (auto *C : D->clauselists()) {
+ dumpChild([=] {
+ if (!C) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>> OMPClause";
+ return;
+ }
+ {
+ ColorScope Color(OS, ShowColors, AttrColor);
+ StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
+ OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
+ << ClauseName.drop_front() << "Clause";
+ }
+ NodeDumper.dumpPointer(C);
+ NodeDumper.dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
+ });
}
}
void ASTDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
dumpStmt(D->getInit());
}
@@ -1351,31 +805,31 @@ void ASTDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
//===----------------------------------------------------------------------===//
void ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
- dumpName(D);
+ NodeDumper.dumpName(D);
if (D->isInline())
OS << " inline";
if (!D->isOriginalNamespace())
- dumpDeclRef(D->getOriginalNamespace(), "original");
+ NodeDumper.dumpDeclRef(D->getOriginalNamespace(), "original");
}
void ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
OS << ' ';
- dumpBareDeclRef(D->getNominatedNamespace());
+ NodeDumper.dumpBareDeclRef(D->getNominatedNamespace());
}
void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
- dumpName(D);
- dumpDeclRef(D->getAliasedNamespace());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpDeclRef(D->getAliasedNamespace());
}
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
- dumpName(D);
- dumpType(D->getUnderlyingType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getUnderlyingType());
dumpTypeAsChild(D->getUnderlyingType());
}
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
- dumpName(D);
+ NodeDumper.dumpName(D);
dumpTemplateParameters(D->getTemplateParameters());
dumpDecl(D->getTemplatedDecl());
}
@@ -1387,7 +841,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
{
- ColorScope Color(*this, DeclKindNameColor);
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "DefinitionData";
}
#define FLAG(fn, name) if (D->fn()) OS << " " #name;
@@ -1415,7 +869,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
{
- ColorScope Color(*this, DeclKindNameColor);
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "DefaultConstructor";
}
FLAG(hasDefaultConstructor, exists);
@@ -1429,7 +883,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
{
- ColorScope Color(*this, DeclKindNameColor);
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "CopyConstructor";
}
FLAG(hasSimpleCopyConstructor, simple);
@@ -1447,7 +901,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
{
- ColorScope Color(*this, DeclKindNameColor);
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "MoveConstructor";
}
FLAG(hasMoveConstructor, exists);
@@ -1464,7 +918,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
{
- ColorScope Color(*this, DeclKindNameColor);
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "CopyAssignment";
}
FLAG(hasTrivialCopyAssignment, trivial);
@@ -1478,7 +932,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
{
- ColorScope Color(*this, DeclKindNameColor);
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "MoveAssignment";
}
FLAG(hasMoveAssignment, exists);
@@ -1492,7 +946,7 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
{
- ColorScope Color(*this, DeclKindNameColor);
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
OS << "Destructor";
}
FLAG(hasSimpleDestructor, simple);
@@ -1511,8 +965,8 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
dumpChild([=] {
if (I.isVirtual())
OS << "virtual ";
- dumpAccessSpecifier(I.getAccessSpecifier());
- dumpType(I.getType());
+ NodeDumper.dumpAccessSpecifier(I.getAccessSpecifier());
+ NodeDumper.dumpType(I.getType());
if (I.isPackExpansion())
OS << "...";
});
@@ -1524,10 +978,10 @@ void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) {
dumpStmt(D->getMessage());
}
-template<typename SpecializationDecl>
-void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D,
- bool DumpExplicitInst,
- bool DumpRefOnly) {
+template <typename SpecializationDecl>
+void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
+ bool DumpExplicitInst,
+ bool DumpRefOnly) {
bool DumpedAny = false;
for (auto *RedeclWithBadType : D->redecls()) {
// FIXME: The redecls() range sometimes has elements of a less-specific
@@ -1551,7 +1005,7 @@ void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D,
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
if (DumpRefOnly)
- dumpDeclRef(Redecl);
+ NodeDumper.dumpDeclRef(Redecl);
else
dumpDecl(Redecl);
DumpedAny = true;
@@ -1563,31 +1017,30 @@ void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D,
// Ensure we dump at least one decl for each specialization.
if (!DumpedAny)
- dumpDeclRef(D);
+ NodeDumper.dumpDeclRef(D);
}
-template<typename TemplateDecl>
-void ASTDumper::VisitTemplateDecl(const TemplateDecl *D,
- bool DumpExplicitInst) {
- dumpName(D);
+template <typename TemplateDecl>
+void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
+ NodeDumper.dumpName(D);
dumpTemplateParameters(D->getTemplateParameters());
dumpDecl(D->getTemplatedDecl());
for (auto *Child : D->specializations())
- VisitTemplateDeclSpecialization(Child, DumpExplicitInst,
- !D->isCanonicalDecl());
+ dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
+ !D->isCanonicalDecl());
}
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
// FIXME: We don't add a declaration of a function template specialization
// to its context when it's explicitly instantiated, so dump explicit
// instantiations when we dump the template itself.
- VisitTemplateDecl(D, true);
+ dumpTemplateDecl(D, true);
}
void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
- VisitTemplateDecl(D, false);
+ dumpTemplateDecl(D, false);
}
void ASTDumper::VisitClassTemplateSpecializationDecl(
@@ -1610,11 +1063,11 @@ void ASTDumper::VisitClassScopeFunctionSpecializationDecl(
}
void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
- VisitTemplateDecl(D, false);
+ dumpTemplateDecl(D, false);
}
void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
- dumpName(D);
+ NodeDumper.dumpName(D);
dumpTemplateParameters(D->getTemplateParameters());
}
@@ -1638,19 +1091,25 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
OS << " depth " << D->getDepth() << " index " << D->getIndex();
if (D->isParameterPack())
OS << " ...";
- dumpName(D);
+ NodeDumper.dumpName(D);
if (D->hasDefaultArgument())
- dumpTemplateArgument(D->getDefaultArgument());
+ dumpTemplateArgument(D->getDefaultArgument(), SourceRange(),
+ D->getDefaultArgStorage().getInheritedFrom(),
+ D->defaultArgumentWasInherited() ? "inherited from"
+ : "previous");
}
void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
- dumpType(D->getType());
+ NodeDumper.dumpType(D->getType());
OS << " depth " << D->getDepth() << " index " << D->getIndex();
if (D->isParameterPack())
OS << " ...";
- dumpName(D);
+ NodeDumper.dumpName(D);
if (D->hasDefaultArgument())
- dumpTemplateArgument(D->getDefaultArgument());
+ dumpTemplateArgument(D->getDefaultArgument(), SourceRange(),
+ D->getDefaultArgStorage().getInheritedFrom(),
+ D->defaultArgumentWasInherited() ? "inherited from"
+ : "previous");
}
void ASTDumper::VisitTemplateTemplateParmDecl(
@@ -1658,10 +1117,12 @@ void ASTDumper::VisitTemplateTemplateParmDecl(
OS << " depth " << D->getDepth() << " index " << D->getIndex();
if (D->isParameterPack())
OS << " ...";
- dumpName(D);
+ NodeDumper.dumpName(D);
dumpTemplateParameters(D->getTemplateParameters());
if (D->hasDefaultArgument())
- dumpTemplateArgumentLoc(D->getDefaultArgument());
+ dumpTemplateArgumentLoc(
+ D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(),
+ D->defaultArgumentWasInherited() ? "inherited from" : "previous");
}
void ASTDumper::VisitUsingDecl(const UsingDecl *D) {
@@ -1684,12 +1145,12 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D)
if (D->getQualifier())
D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getNameAsString();
- dumpType(D->getType());
+ NodeDumper.dumpType(D->getType());
}
void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
OS << ' ';
- dumpBareDeclRef(D->getTargetDecl());
+ NodeDumper.dumpBareDeclRef(D->getTargetDecl());
if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
dumpTypeAsChild(TD->getTypeForDecl());
}
@@ -1701,21 +1162,21 @@ void ASTDumper::VisitConstructorUsingShadowDecl(
dumpChild([=] {
OS << "target ";
- dumpBareDeclRef(D->getTargetDecl());
+ NodeDumper.dumpBareDeclRef(D->getTargetDecl());
});
dumpChild([=] {
OS << "nominated ";
- dumpBareDeclRef(D->getNominatedBaseClass());
+ NodeDumper.dumpBareDeclRef(D->getNominatedBaseClass());
OS << ' ';
- dumpBareDeclRef(D->getNominatedBaseClassShadowDecl());
+ NodeDumper.dumpBareDeclRef(D->getNominatedBaseClassShadowDecl());
});
dumpChild([=] {
OS << "constructed ";
- dumpBareDeclRef(D->getConstructedBaseClass());
+ NodeDumper.dumpBareDeclRef(D->getConstructedBaseClass());
OS << ' ';
- dumpBareDeclRef(D->getConstructedBaseClassShadowDecl());
+ NodeDumper.dumpBareDeclRef(D->getConstructedBaseClassShadowDecl());
});
}
@@ -1728,12 +1189,12 @@ void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) {
OS << ' ';
- dumpAccessSpecifier(D->getAccess());
+ NodeDumper.dumpAccessSpecifier(D->getAccess());
}
void ASTDumper::VisitFriendDecl(const FriendDecl *D) {
if (TypeSourceInfo *T = D->getFriendType())
- dumpType(T->getType());
+ NodeDumper.dumpType(T->getType());
else
dumpDecl(D->getFriendDecl());
}
@@ -1743,8 +1204,8 @@ void ASTDumper::VisitFriendDecl(const FriendDecl *D) {
//===----------------------------------------------------------------------===//
void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
if (D->getSynthesize())
OS << " synthesize";
@@ -1772,8 +1233,8 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
OS << " -";
else
OS << " +";
- dumpName(D);
- dumpType(D->getReturnType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getReturnType());
if (D->isThisDeclarationADefinition()) {
dumpDeclContext(D);
@@ -1790,7 +1251,7 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
}
void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
- dumpName(D);
+ NodeDumper.dumpName(D);
switch (D->getVariance()) {
case ObjCTypeParamVariance::Invariant:
break;
@@ -1806,47 +1267,47 @@ void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
if (D->hasExplicitBound())
OS << " bounded";
- dumpType(D->getUnderlyingType());
+ NodeDumper.dumpType(D->getUnderlyingType());
}
void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
- dumpName(D);
- dumpDeclRef(D->getClassInterface());
- dumpObjCTypeParamList(D->getTypeParamList());
- dumpDeclRef(D->getImplementation());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpDeclRef(D->getClassInterface());
+ NodeDumper.dumpDeclRef(D->getImplementation());
for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(),
E = D->protocol_end();
I != E; ++I)
- dumpDeclRef(*I);
+ NodeDumper.dumpDeclRef(*I);
+ dumpObjCTypeParamList(D->getTypeParamList());
}
void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
- dumpName(D);
- dumpDeclRef(D->getClassInterface());
- dumpDeclRef(D->getCategoryDecl());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpDeclRef(D->getClassInterface());
+ NodeDumper.dumpDeclRef(D->getCategoryDecl());
}
void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
- dumpName(D);
+ NodeDumper.dumpName(D);
for (auto *Child : D->protocols())
- dumpDeclRef(Child);
+ NodeDumper.dumpDeclRef(Child);
}
void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
- dumpName(D);
- dumpObjCTypeParamList(D->getTypeParamListAsWritten());
- dumpDeclRef(D->getSuperClass(), "super");
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpDeclRef(D->getSuperClass(), "super");
- dumpDeclRef(D->getImplementation());
+ NodeDumper.dumpDeclRef(D->getImplementation());
for (auto *Child : D->protocols())
- dumpDeclRef(Child);
+ NodeDumper.dumpDeclRef(Child);
+ dumpObjCTypeParamList(D->getTypeParamListAsWritten());
}
void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
- dumpName(D);
- dumpDeclRef(D->getSuperClass(), "super");
- dumpDeclRef(D->getClassInterface());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpDeclRef(D->getSuperClass(), "super");
+ NodeDumper.dumpDeclRef(D->getClassInterface());
for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(),
E = D->init_end();
I != E; ++I)
@@ -1854,13 +1315,13 @@ void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
}
void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) {
- dumpName(D);
- dumpDeclRef(D->getClassInterface());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpDeclRef(D->getClassInterface());
}
void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
- dumpName(D);
- dumpType(D->getType());
+ NodeDumper.dumpName(D);
+ NodeDumper.dumpType(D->getType());
if (D->getPropertyImplementation() == ObjCPropertyDecl::Required)
OS << " required";
@@ -1892,20 +1353,28 @@ void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
if (Attrs & ObjCPropertyDecl::OBJC_PR_class)
OS << " class";
if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
- dumpDeclRef(D->getGetterMethodDecl(), "getter");
+ NodeDumper.dumpDeclRef(D->getGetterMethodDecl(), "getter");
if (Attrs & ObjCPropertyDecl::OBJC_PR_setter)
- dumpDeclRef(D->getSetterMethodDecl(), "setter");
+ NodeDumper.dumpDeclRef(D->getSetterMethodDecl(), "setter");
}
}
void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
- dumpName(D->getPropertyDecl());
+ NodeDumper.dumpName(D->getPropertyDecl());
if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
OS << " synthesize";
else
OS << " dynamic";
- dumpDeclRef(D->getPropertyDecl());
- dumpDeclRef(D->getPropertyIvarDecl());
+ NodeDumper.dumpDeclRef(D->getPropertyDecl());
+ NodeDumper.dumpDeclRef(D->getPropertyIvarDecl());
+}
+
+void ASTDumper::Visit(const BlockDecl::Capture &C) {
+ dumpChild([=] {
+ NodeDumper.Visit(C);
+ if (C.hasCopyExpr())
+ dumpStmt(C.getCopyExpr());
+ });
}
void ASTDumper::VisitBlockDecl(const BlockDecl *D) {
@@ -1918,21 +1387,8 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) {
if (D->capturesCXXThis())
dumpChild([=]{ OS << "capture this"; });
- for (const auto &I : D->captures()) {
- dumpChild([=] {
- OS << "capture";
- if (I.isByRef())
- OS << " byref";
- if (I.isNested())
- OS << " nested";
- if (I.getVariable()) {
- OS << ' ';
- dumpBareDeclRef(I.getVariable());
- }
- if (I.hasCopyExpr())
- dumpStmt(I.getCopyExpr());
- });
- }
+ for (const auto &I : D->captures())
+ Visit(I);
dumpStmt(D->getBody());
}
@@ -1940,42 +1396,27 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) {
// Stmt dumping methods.
//===----------------------------------------------------------------------===//
-void ASTDumper::dumpStmt(const Stmt *S) {
- dumpChild([=] {
+void ASTDumper::dumpStmt(const Stmt *S, StringRef Label) {
+ dumpChild(Label, [=] {
+ NodeDumper.Visit(S);
+
if (!S) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
return;
}
+ ConstStmtVisitor<ASTDumper>::Visit(S);
+
// Some statements have custom mechanisms for dumping their children.
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
- VisitDeclStmt(DS);
- return;
- }
- if (const GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(S)) {
- VisitGenericSelectionExpr(GSE);
+ if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) {
return;
}
- ConstStmtVisitor<ASTDumper>::Visit(S);
-
for (const Stmt *SubStmt : S->children())
dumpStmt(SubStmt);
});
}
-void ASTDumper::VisitStmt(const Stmt *Node) {
- {
- ColorScope Color(*this, StmtColor);
- OS << Node->getStmtClassName();
- }
- dumpPointer(Node);
- dumpSourceRange(Node->getSourceRange());
-}
-
void ASTDumper::VisitDeclStmt(const DeclStmt *Node) {
- VisitStmt(Node);
for (DeclStmt::const_decl_iterator I = Node->decl_begin(),
E = Node->decl_end();
I != E; ++I)
@@ -1983,31 +1424,17 @@ void ASTDumper::VisitDeclStmt(const DeclStmt *Node) {
}
void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) {
- VisitStmt(Node);
for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(),
E = Node->getAttrs().end();
I != E; ++I)
dumpAttr(*I);
}
-void ASTDumper::VisitLabelStmt(const LabelStmt *Node) {
- VisitStmt(Node);
- OS << " '" << Node->getName() << "'";
-}
-
-void ASTDumper::VisitGotoStmt(const GotoStmt *Node) {
- VisitStmt(Node);
- OS << " '" << Node->getLabel()->getName() << "'";
- dumpPointer(Node->getLabel());
-}
-
void ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) {
- VisitStmt(Node);
dumpDecl(Node->getExceptionDecl());
}
void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) {
- VisitStmt(Node);
dumpDecl(Node->getCapturedDecl());
}
@@ -2015,287 +1442,41 @@ void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) {
// OpenMP dumping methods.
//===----------------------------------------------------------------------===//
+void ASTDumper::Visit(const OMPClause *C) {
+ dumpChild([=] {
+ NodeDumper.Visit(C);
+ for (auto *S : C->children())
+ dumpStmt(S);
+ });
+}
+
void ASTDumper::VisitOMPExecutableDirective(
const OMPExecutableDirective *Node) {
- VisitStmt(Node);
- for (auto *C : Node->clauses()) {
- dumpChild([=] {
- if (!C) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>> OMPClause";
- return;
- }
- {
- ColorScope Color(*this, AttrColor);
- StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
- OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
- << ClauseName.drop_front() << "Clause";
- }
- dumpPointer(C);
- dumpSourceRange(SourceRange(C->getLocStart(), C->getLocEnd()));
- if (C->isImplicit())
- OS << " <implicit>";
- for (auto *S : C->children())
- dumpStmt(S);
- });
- }
+ for (const auto *C : Node->clauses())
+ Visit(C);
}
//===----------------------------------------------------------------------===//
// Expr dumping methods.
//===----------------------------------------------------------------------===//
-void ASTDumper::VisitExpr(const Expr *Node) {
- VisitStmt(Node);
- dumpType(Node->getType());
-
- {
- ColorScope Color(*this, ValueKindColor);
- switch (Node->getValueKind()) {
- case VK_RValue:
- break;
- case VK_LValue:
- OS << " lvalue";
- break;
- case VK_XValue:
- OS << " xvalue";
- break;
- }
- }
-
- {
- ColorScope Color(*this, ObjectKindColor);
- switch (Node->getObjectKind()) {
- case OK_Ordinary:
- break;
- case OK_BitField:
- OS << " bitfield";
- break;
- case OK_ObjCProperty:
- OS << " objcproperty";
- break;
- case OK_ObjCSubscript:
- OS << " objcsubscript";
- break;
- case OK_VectorComponent:
- OS << " vectorcomponent";
- break;
- }
- }
-}
-
-static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
- if (Node->path_empty())
- return;
-
- OS << " (";
- bool First = true;
- for (CastExpr::path_const_iterator I = Node->path_begin(),
- E = Node->path_end();
- I != E; ++I) {
- const CXXBaseSpecifier *Base = *I;
- if (!First)
- OS << " -> ";
-
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
- if (Base->isVirtual())
- OS << "virtual ";
- OS << RD->getName();
- First = false;
- }
-
- OS << ')';
-}
-
-void ASTDumper::VisitCastExpr(const CastExpr *Node) {
- VisitExpr(Node);
- OS << " <";
- {
- ColorScope Color(*this, CastColor);
- OS << Node->getCastKindName();
- }
- dumpBasePath(OS, Node);
- OS << ">";
-}
-
-void ASTDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) {
- VisitCastExpr(Node);
- if (Node->isPartOfExplicitCast())
- OS << " part_of_explicit_cast";
-}
-
-void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
- VisitExpr(Node);
-
- OS << " ";
- dumpBareDeclRef(Node->getDecl());
- if (Node->getDecl() != Node->getFoundDecl()) {
- OS << " (";
- dumpBareDeclRef(Node->getFoundDecl());
- OS << ")";
- }
-}
-
-void ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) {
- VisitExpr(Node);
- OS << " (";
- if (!Node->requiresADL())
- OS << "no ";
- OS << "ADL) = '" << Node->getName() << '\'';
-
- UnresolvedLookupExpr::decls_iterator
- I = Node->decls_begin(), E = Node->decls_end();
- if (I == E)
- OS << " empty";
- for (; I != E; ++I)
- dumpPointer(*I);
-}
-
-void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
- VisitExpr(Node);
-
- {
- ColorScope Color(*this, DeclKindNameColor);
- OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
- }
- OS << "='" << *Node->getDecl() << "'";
- dumpPointer(Node->getDecl());
- if (Node->isFreeIvar())
- OS << " isFreeIvar";
-}
-
-void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
- VisitExpr(Node);
- OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType());
-}
-
-void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
- VisitExpr(Node);
- ColorScope Color(*this, ValueColor);
- OS << " " << Node->getValue();
-}
-
-void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
- VisitExpr(Node);
-
- bool isSigned = Node->getType()->isSignedIntegerType();
- ColorScope Color(*this, ValueColor);
- OS << " " << Node->getValue().toString(10, isSigned);
-}
-
-void ASTDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
- VisitExpr(Node);
-
- ColorScope Color(*this, ValueColor);
- OS << " " << Node->getValueAsString(/*Radix=*/10);
-}
-
-void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
- VisitExpr(Node);
- ColorScope Color(*this, ValueColor);
- OS << " " << Node->getValueAsApproximateDouble();
-}
-
-void ASTDumper::VisitStringLiteral(const StringLiteral *Str) {
- VisitExpr(Str);
- ColorScope Color(*this, ValueColor);
- OS << " ";
- Str->outputString(OS);
-}
void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) {
- VisitExpr(ILE);
if (auto *Filler = ILE->getArrayFiller()) {
- dumpChild([=] {
- OS << "array filler";
- dumpStmt(Filler);
- });
- }
- if (auto *Field = ILE->getInitializedFieldInUnion()) {
- OS << " field ";
- dumpBareDeclRef(Field);
- }
-}
-
-void ASTDumper::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
- VisitExpr(E);
-}
-
-void ASTDumper::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
- VisitExpr(E);
-}
-
-void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) {
- VisitExpr(Node);
- OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
- << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
- if (!Node->canOverflow())
- OS << " cannot overflow";
-}
-
-void ASTDumper::VisitUnaryExprOrTypeTraitExpr(
- const UnaryExprOrTypeTraitExpr *Node) {
- VisitExpr(Node);
- switch(Node->getKind()) {
- case UETT_SizeOf:
- OS << " sizeof";
- break;
- case UETT_AlignOf:
- OS << " alignof";
- break;
- case UETT_VecStep:
- OS << " vec_step";
- break;
- case UETT_OpenMPRequiredSimdAlign:
- OS << " __builtin_omp_required_simd_align";
- break;
+ dumpStmt(Filler, "array_filler");
}
- if (Node->isArgumentType())
- dumpType(Node->getArgumentType());
-}
-
-void ASTDumper::VisitMemberExpr(const MemberExpr *Node) {
- VisitExpr(Node);
- OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
- dumpPointer(Node->getMemberDecl());
-}
-
-void ASTDumper::VisitExtVectorElementExpr(const ExtVectorElementExpr *Node) {
- VisitExpr(Node);
- OS << " " << Node->getAccessor().getNameStart();
-}
-
-void ASTDumper::VisitBinaryOperator(const BinaryOperator *Node) {
- VisitExpr(Node);
- OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
-}
-
-void ASTDumper::VisitCompoundAssignOperator(
- const CompoundAssignOperator *Node) {
- VisitExpr(Node);
- OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
- << "' ComputeLHSTy=";
- dumpBareType(Node->getComputationLHSType());
- OS << " ComputeResultTy=";
- dumpBareType(Node->getComputationResultType());
}
void ASTDumper::VisitBlockExpr(const BlockExpr *Node) {
- VisitExpr(Node);
dumpDecl(Node->getBlockDecl());
}
void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
- VisitExpr(Node);
-
if (Expr *Source = Node->getSourceExpr())
dumpStmt(Source);
}
void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
- VisitExpr(E);
if (E->isResultDependent())
OS << " result_dependent";
dumpStmt(E->getControllingExpr());
@@ -2305,7 +1486,7 @@ void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
dumpChild([=] {
if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) {
OS << "case ";
- dumpType(TSI->getType());
+ NodeDumper.dumpType(TSI->getType());
} else {
OS << "default";
}
@@ -2320,394 +1501,42 @@ void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
}
}
-// GNU extensions.
-
-void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
- VisitExpr(Node);
- OS << " " << Node->getLabel()->getName();
- dumpPointer(Node->getLabel());
-}
-
//===----------------------------------------------------------------------===//
// C++ Expressions
//===----------------------------------------------------------------------===//
-void ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
- VisitExpr(Node);
- OS << " " << Node->getCastName()
- << "<" << Node->getTypeAsWritten().getAsString() << ">"
- << " <" << Node->getCastKindName();
- dumpBasePath(OS, Node);
- OS << ">";
-}
-
-void ASTDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
- VisitExpr(Node);
- OS << " " << (Node->getValue() ? "true" : "false");
-}
-
-void ASTDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
- VisitExpr(Node);
- OS << " this";
-}
-
-void ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) {
- VisitExpr(Node);
- OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
- << " <" << Node->getCastKindName() << ">";
-}
-
-void ASTDumper::VisitCXXUnresolvedConstructExpr(
- const CXXUnresolvedConstructExpr *Node) {
- VisitExpr(Node);
- dumpType(Node->getTypeAsWritten());
- if (Node->isListInitialization())
- OS << " list";
-}
-
-void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
- VisitExpr(Node);
- CXXConstructorDecl *Ctor = Node->getConstructor();
- dumpType(Ctor->getType());
- if (Node->isElidable())
- OS << " elidable";
- if (Node->isListInitialization())
- OS << " list";
- if (Node->isStdInitListInitialization())
- OS << " std::initializer_list";
- if (Node->requiresZeroInitialization())
- OS << " zeroing";
-}
-
-void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) {
- VisitExpr(Node);
- OS << " ";
- dumpCXXTemporary(Node->getTemporary());
-}
-
-void ASTDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
- VisitExpr(Node);
- if (Node->isGlobalNew())
- OS << " global";
- if (Node->isArray())
- OS << " array";
- if (Node->getOperatorNew()) {
- OS << ' ';
- dumpBareDeclRef(Node->getOperatorNew());
- }
- // We could dump the deallocation function used in case of error, but it's
- // usually not that interesting.
-}
-
-void ASTDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
- VisitExpr(Node);
- if (Node->isGlobalDelete())
- OS << " global";
- if (Node->isArrayForm())
- OS << " array";
- if (Node->getOperatorDelete()) {
- OS << ' ';
- dumpBareDeclRef(Node->getOperatorDelete());
- }
-}
-
-void
-ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) {
- VisitExpr(Node);
- if (const ValueDecl *VD = Node->getExtendingDecl()) {
- OS << " extended by ";
- dumpBareDeclRef(VD);
- }
-}
-
-void ASTDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
- VisitExpr(Node);
- for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
- dumpDeclRef(Node->getObject(i), "cleanup");
-}
-
-void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
- OS << "(CXXTemporary";
- dumpPointer(Temporary);
- OS << ")";
-}
-
void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
- VisitExpr(Node);
- dumpPointer(Node->getPack());
- dumpName(Node->getPack());
if (Node->isPartiallySubstituted())
for (const auto &A : Node->getPartialArguments())
dumpTemplateArgument(A);
}
-void ASTDumper::VisitCXXDependentScopeMemberExpr(
- const CXXDependentScopeMemberExpr *Node) {
- VisitExpr(Node);
- OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
-}
-
//===----------------------------------------------------------------------===//
// Obj-C Expressions
//===----------------------------------------------------------------------===//
-void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
- VisitExpr(Node);
- OS << " selector=";
- Node->getSelector().print(OS);
- switch (Node->getReceiverKind()) {
- case ObjCMessageExpr::Instance:
- break;
-
- case ObjCMessageExpr::Class:
- OS << " class=";
- dumpBareType(Node->getClassReceiver());
- break;
-
- case ObjCMessageExpr::SuperInstance:
- OS << " super (instance)";
- break;
-
- case ObjCMessageExpr::SuperClass:
- OS << " super (class)";
- break;
- }
-}
-
-void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
- VisitExpr(Node);
- if (auto *BoxingMethod = Node->getBoxingMethod()) {
- OS << " selector=";
- BoxingMethod->getSelector().print(OS);
- }
-}
-
void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
- VisitStmt(Node);
if (const VarDecl *CatchParam = Node->getCatchParamDecl())
dumpDecl(CatchParam);
- else
- OS << " catch all";
-}
-
-void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
- VisitExpr(Node);
- dumpType(Node->getEncodedType());
-}
-
-void ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
- VisitExpr(Node);
-
- OS << " ";
- Node->getSelector().print(OS);
-}
-
-void ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
- VisitExpr(Node);
-
- OS << ' ' << *Node->getProtocol();
-}
-
-void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
- VisitExpr(Node);
- if (Node->isImplicitProperty()) {
- OS << " Kind=MethodRef Getter=\"";
- if (Node->getImplicitPropertyGetter())
- Node->getImplicitPropertyGetter()->getSelector().print(OS);
- else
- OS << "(null)";
-
- OS << "\" Setter=\"";
- if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
- Setter->getSelector().print(OS);
- else
- OS << "(null)";
- OS << "\"";
- } else {
- OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"';
- }
-
- if (Node->isSuperReceiver())
- OS << " super";
-
- OS << " Messaging=";
- if (Node->isMessagingGetter() && Node->isMessagingSetter())
- OS << "Getter&Setter";
- else if (Node->isMessagingGetter())
- OS << "Getter";
- else if (Node->isMessagingSetter())
- OS << "Setter";
-}
-
-void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) {
- VisitExpr(Node);
- if (Node->isArraySubscriptRefExpr())
- OS << " Kind=ArraySubscript GetterForArray=\"";
- else
- OS << " Kind=DictionarySubscript GetterForDictionary=\"";
- if (Node->getAtIndexMethodDecl())
- Node->getAtIndexMethodDecl()->getSelector().print(OS);
- else
- OS << "(null)";
-
- if (Node->isArraySubscriptRefExpr())
- OS << "\" SetterForArray=\"";
- else
- OS << "\" SetterForDictionary=\"";
- if (Node->setAtIndexMethodDecl())
- Node->setAtIndexMethodDecl()->getSelector().print(OS);
- else
- OS << "(null)";
-}
-
-void ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
- VisitExpr(Node);
- OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
}
//===----------------------------------------------------------------------===//
// Comments
//===----------------------------------------------------------------------===//
-const char *ASTDumper::getCommandName(unsigned CommandID) {
- if (Traits)
- return Traits->getCommandInfo(CommandID)->Name;
- const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
- if (Info)
- return Info->Name;
- return "<not a builtin command>";
-}
-
-void ASTDumper::dumpFullComment(const FullComment *C) {
- if (!C)
- return;
-
- FC = C;
- dumpComment(C);
- FC = nullptr;
-}
-
-void ASTDumper::dumpComment(const Comment *C) {
+void ASTDumper::dumpComment(const Comment *C, const FullComment *FC) {
dumpChild([=] {
+ NodeDumper.Visit(C, FC);
if (!C) {
- ColorScope Color(*this, NullColor);
- OS << "<<<NULL>>>";
return;
}
-
- {
- ColorScope Color(*this, CommentColor);
- OS << C->getCommentKindName();
- }
- dumpPointer(C);
- dumpSourceRange(C->getSourceRange());
- ConstCommentVisitor<ASTDumper>::visit(C);
+ ConstCommentVisitor<ASTDumper, void, const FullComment *>::visit(C, FC);
for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
I != E; ++I)
- dumpComment(*I);
+ dumpComment(*I, FC);
});
}
-void ASTDumper::visitTextComment(const TextComment *C) {
- OS << " Text=\"" << C->getText() << "\"";
-}
-
-void ASTDumper::visitInlineCommandComment(const InlineCommandComment *C) {
- OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
- switch (C->getRenderKind()) {
- case InlineCommandComment::RenderNormal:
- OS << " RenderNormal";
- break;
- case InlineCommandComment::RenderBold:
- OS << " RenderBold";
- break;
- case InlineCommandComment::RenderMonospaced:
- OS << " RenderMonospaced";
- break;
- case InlineCommandComment::RenderEmphasized:
- OS << " RenderEmphasized";
- break;
- }
-
- for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
- OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
-}
-
-void ASTDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) {
- OS << " Name=\"" << C->getTagName() << "\"";
- if (C->getNumAttrs() != 0) {
- OS << " Attrs: ";
- for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
- const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
- OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
- }
- }
- if (C->isSelfClosing())
- OS << " SelfClosing";
-}
-
-void ASTDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
- OS << " Name=\"" << C->getTagName() << "\"";
-}
-
-void ASTDumper::visitBlockCommandComment(const BlockCommandComment *C) {
- OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
- for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
- OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
-}
-
-void ASTDumper::visitParamCommandComment(const ParamCommandComment *C) {
- OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection());
-
- if (C->isDirectionExplicit())
- OS << " explicitly";
- else
- OS << " implicitly";
-
- if (C->hasParamName()) {
- if (C->isParamIndexValid())
- OS << " Param=\"" << C->getParamName(FC) << "\"";
- else
- OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
- }
-
- if (C->isParamIndexValid() && !C->isVarArgParam())
- OS << " ParamIndex=" << C->getParamIndex();
-}
-
-void ASTDumper::visitTParamCommandComment(const TParamCommandComment *C) {
- if (C->hasParamName()) {
- if (C->isPositionValid())
- OS << " Param=\"" << C->getParamName(FC) << "\"";
- else
- OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
- }
-
- if (C->isPositionValid()) {
- OS << " Position=<";
- for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
- OS << C->getIndex(i);
- if (i != e - 1)
- OS << ", ";
- }
- OS << ">";
- }
-}
-
-void ASTDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
- OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""
- " CloseName=\"" << C->getCloseName() << "\"";
-}
-
-void ASTDumper::visitVerbatimBlockLineComment(
- const VerbatimBlockLineComment *C) {
- OS << " Text=\"" << C->getText() << "\"";
-}
-
-void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) {
- OS << " Text=\"" << C->getText() << "\"";
-}
-
//===----------------------------------------------------------------------===//
// Type method implementations
//===----------------------------------------------------------------------===//
@@ -2816,12 +1645,16 @@ LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const {
void Comment::dump(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM) const {
const FullComment *FC = dyn_cast<FullComment>(this);
+ if (!FC)
+ return;
ASTDumper D(OS, Traits, SM);
- D.dumpFullComment(FC);
+ D.dumpComment(FC, FC);
}
LLVM_DUMP_METHOD void Comment::dumpColor() const {
const FullComment *FC = dyn_cast<FullComment>(this);
+ if (!FC)
+ return;
ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
- D.dumpFullComment(FC);
+ D.dumpComment(FC, FC);
}
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index b360b3910636..44832557e97b 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTStructuralEquivalence.h"
@@ -71,10 +72,43 @@
namespace clang {
+ using llvm::make_error;
+ using llvm::Error;
+ using llvm::Expected;
+ using ExpectedType = llvm::Expected<QualType>;
+ using ExpectedStmt = llvm::Expected<Stmt *>;
+ using ExpectedExpr = llvm::Expected<Expr *>;
+ using ExpectedDecl = llvm::Expected<Decl *>;
+ using ExpectedSLoc = llvm::Expected<SourceLocation>;
+
+ std::string ImportError::toString() const {
+ // FIXME: Improve error texts.
+ switch (Error) {
+ case NameConflict:
+ return "NameConflict";
+ case UnsupportedConstruct:
+ return "UnsupportedConstruct";
+ case Unknown:
+ return "Unknown error";
+ }
+ llvm_unreachable("Invalid error code.");
+ return "Invalid error code.";
+ }
+
+ void ImportError::log(raw_ostream &OS) const {
+ OS << toString();
+ }
+
+ std::error_code ImportError::convertToErrorCode() const {
+ llvm_unreachable("Function not implemented.");
+ }
+
+ char ImportError::ID;
+
template <class T>
- SmallVector<Decl*, 2>
+ SmallVector<Decl *, 2>
getCanonicalForwardRedeclChain(Redeclarable<T>* D) {
- SmallVector<Decl*, 2> Redecls;
+ SmallVector<Decl *, 2> Redecls;
for (auto *R : D->getFirstDecl()->redecls()) {
if (R != D->getFirstDecl())
Redecls.push_back(R);
@@ -85,9 +119,13 @@ namespace clang {
}
SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) {
- // Currently only FunctionDecl is supported
- auto FD = cast<FunctionDecl>(D);
- return getCanonicalForwardRedeclChain<FunctionDecl>(FD);
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ return getCanonicalForwardRedeclChain<FunctionDecl>(FD);
+ if (auto *VD = dyn_cast<VarDecl>(D))
+ return getCanonicalForwardRedeclChain<VarDecl>(VD);
+ if (auto *TD = dyn_cast<TagDecl>(D))
+ return getCanonicalForwardRedeclChain<TagDecl>(TD);
+ llvm_unreachable("Bad declaration kind");
}
void updateFlags(const Decl *From, Decl *To) {
@@ -97,12 +135,110 @@ namespace clang {
To->setIsUsed();
}
- class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,
- public DeclVisitor<ASTNodeImporter, Decl *>,
- public StmtVisitor<ASTNodeImporter, Stmt *> {
+ // FIXME: Temporary until every import returns Expected.
+ template <>
+ LLVM_NODISCARD Error
+ ASTImporter::importInto(SourceLocation &To, const SourceLocation &From) {
+ To = Import(From);
+ if (From.isValid() && To.isInvalid())
+ return llvm::make_error<ImportError>();
+ return Error::success();
+ }
+ // FIXME: Temporary until every import returns Expected.
+ template <>
+ LLVM_NODISCARD Error
+ ASTImporter::importInto(QualType &To, const QualType &From) {
+ To = Import(From);
+ if (!From.isNull() && To.isNull())
+ return llvm::make_error<ImportError>();
+ return Error::success();
+ }
+
+ class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>,
+ public DeclVisitor<ASTNodeImporter, ExpectedDecl>,
+ public StmtVisitor<ASTNodeImporter, ExpectedStmt> {
ASTImporter &Importer;
- // Wrapper for an overload set.
+ // Use this instead of Importer.importInto .
+ template <typename ImportT>
+ LLVM_NODISCARD Error importInto(ImportT &To, const ImportT &From) {
+ return Importer.importInto(To, From);
+ }
+
+ // Use this to import pointers of specific type.
+ template <typename ImportT>
+ LLVM_NODISCARD Error importInto(ImportT *&To, ImportT *From) {
+ auto ToI = Importer.Import(From);
+ if (!ToI && From)
+ return make_error<ImportError>();
+ To = cast_or_null<ImportT>(ToI);
+ return Error::success();
+ // FIXME: This should be the final code.
+ //auto ToOrErr = Importer.Import(From);
+ //if (ToOrErr) {
+ // To = cast_or_null<ImportT>(*ToOrErr);
+ //}
+ //return ToOrErr.takeError();
+ }
+
+ // Call the import function of ASTImporter for a baseclass of type `T` and
+ // cast the return value to `T`.
+ template <typename T>
+ Expected<T *> import(T *From) {
+ auto *To = Importer.Import(From);
+ if (!To && From)
+ return make_error<ImportError>();
+ return cast_or_null<T>(To);
+ // FIXME: This should be the final code.
+ //auto ToOrErr = Importer.Import(From);
+ //if (!ToOrErr)
+ // return ToOrErr.takeError();
+ //return cast_or_null<T>(*ToOrErr);
+ }
+
+ template <typename T>
+ Expected<T *> import(const T *From) {
+ return import(const_cast<T *>(From));
+ }
+
+ // Call the import function of ASTImporter for type `T`.
+ template <typename T>
+ Expected<T> import(const T &From) {
+ T To = Importer.Import(From);
+ T DefaultT;
+ if (To == DefaultT && !(From == DefaultT))
+ return make_error<ImportError>();
+ return To;
+ // FIXME: This should be the final code.
+ //return Importer.Import(From);
+ }
+
+ template <class T>
+ Expected<std::tuple<T>>
+ importSeq(const T &From) {
+ Expected<T> ToOrErr = import(From);
+ if (!ToOrErr)
+ return ToOrErr.takeError();
+ return std::make_tuple<T>(std::move(*ToOrErr));
+ }
+
+ // Import multiple objects with a single function call.
+ // This should work for every type for which a variant of `import` exists.
+ // The arguments are processed from left to right and import is stopped on
+ // first error.
+ template <class THead, class... TTail>
+ Expected<std::tuple<THead, TTail...>>
+ importSeq(const THead &FromHead, const TTail &...FromTail) {
+ Expected<std::tuple<THead>> ToHeadOrErr = importSeq(FromHead);
+ if (!ToHeadOrErr)
+ return ToHeadOrErr.takeError();
+ Expected<std::tuple<TTail...>> ToTailOrErr = importSeq(FromTail...);
+ if (!ToTailOrErr)
+ return ToTailOrErr.takeError();
+ return std::tuple_cat(*ToHeadOrErr, *ToTailOrErr);
+ }
+
+// Wrapper for an overload set.
template <typename ToDeclT> struct CallOverloadedCreateFun {
template <typename... Args>
auto operator()(Args &&... args)
@@ -147,16 +283,23 @@ namespace clang {
LLVM_NODISCARD bool
GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun,
FromDeclT *FromD, Args &&... args) {
+ // FIXME: This code is needed later.
+ //if (Importer.getImportDeclErrorIfAny(FromD)) {
+ // ToD = nullptr;
+ // return true; // Already imported but with error.
+ //}
ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD));
if (ToD)
return true; // Already imported.
ToD = CreateFun(std::forward<Args>(args)...);
+ // Keep track of imported Decls.
+ Importer.MapImported(FromD, ToD);
+ Importer.AddToLookupTable(ToD);
InitializeImportedDecl(FromD, ToD);
return false; // A new Decl is created.
}
void InitializeImportedDecl(Decl *FromD, Decl *ToD) {
- Importer.MapImported(FromD, ToD);
ToD->IdentifierNamespace = FromD->IdentifierNamespace;
if (FromD->hasAttrs())
for (const Attr *FromAttr : FromD->getAttrs())
@@ -170,84 +313,82 @@ namespace clang {
public:
explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {}
- using TypeVisitor<ASTNodeImporter, QualType>::Visit;
- using DeclVisitor<ASTNodeImporter, Decl *>::Visit;
- using StmtVisitor<ASTNodeImporter, Stmt *>::Visit;
+ using TypeVisitor<ASTNodeImporter, ExpectedType>::Visit;
+ using DeclVisitor<ASTNodeImporter, ExpectedDecl>::Visit;
+ using StmtVisitor<ASTNodeImporter, ExpectedStmt>::Visit;
// Importing types
- QualType VisitType(const Type *T);
- QualType VisitAtomicType(const AtomicType *T);
- QualType VisitBuiltinType(const BuiltinType *T);
- QualType VisitDecayedType(const DecayedType *T);
- QualType VisitComplexType(const ComplexType *T);
- QualType VisitPointerType(const PointerType *T);
- QualType VisitBlockPointerType(const BlockPointerType *T);
- QualType VisitLValueReferenceType(const LValueReferenceType *T);
- QualType VisitRValueReferenceType(const RValueReferenceType *T);
- QualType VisitMemberPointerType(const MemberPointerType *T);
- QualType VisitConstantArrayType(const ConstantArrayType *T);
- QualType VisitIncompleteArrayType(const IncompleteArrayType *T);
- QualType VisitVariableArrayType(const VariableArrayType *T);
- QualType VisitDependentSizedArrayType(const DependentSizedArrayType *T);
+ ExpectedType VisitType(const Type *T);
+ ExpectedType VisitAtomicType(const AtomicType *T);
+ ExpectedType VisitBuiltinType(const BuiltinType *T);
+ ExpectedType VisitDecayedType(const DecayedType *T);
+ ExpectedType VisitComplexType(const ComplexType *T);
+ ExpectedType VisitPointerType(const PointerType *T);
+ ExpectedType VisitBlockPointerType(const BlockPointerType *T);
+ ExpectedType VisitLValueReferenceType(const LValueReferenceType *T);
+ ExpectedType VisitRValueReferenceType(const RValueReferenceType *T);
+ ExpectedType VisitMemberPointerType(const MemberPointerType *T);
+ ExpectedType VisitConstantArrayType(const ConstantArrayType *T);
+ ExpectedType VisitIncompleteArrayType(const IncompleteArrayType *T);
+ ExpectedType VisitVariableArrayType(const VariableArrayType *T);
+ ExpectedType VisitDependentSizedArrayType(const DependentSizedArrayType *T);
// FIXME: DependentSizedExtVectorType
- QualType VisitVectorType(const VectorType *T);
- QualType VisitExtVectorType(const ExtVectorType *T);
- QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T);
- QualType VisitFunctionProtoType(const FunctionProtoType *T);
- QualType VisitUnresolvedUsingType(const UnresolvedUsingType *T);
- QualType VisitParenType(const ParenType *T);
- QualType VisitTypedefType(const TypedefType *T);
- QualType VisitTypeOfExprType(const TypeOfExprType *T);
+ ExpectedType VisitVectorType(const VectorType *T);
+ ExpectedType VisitExtVectorType(const ExtVectorType *T);
+ ExpectedType VisitFunctionNoProtoType(const FunctionNoProtoType *T);
+ ExpectedType VisitFunctionProtoType(const FunctionProtoType *T);
+ ExpectedType VisitUnresolvedUsingType(const UnresolvedUsingType *T);
+ ExpectedType VisitParenType(const ParenType *T);
+ ExpectedType VisitTypedefType(const TypedefType *T);
+ ExpectedType VisitTypeOfExprType(const TypeOfExprType *T);
// FIXME: DependentTypeOfExprType
- QualType VisitTypeOfType(const TypeOfType *T);
- QualType VisitDecltypeType(const DecltypeType *T);
- QualType VisitUnaryTransformType(const UnaryTransformType *T);
- QualType VisitAutoType(const AutoType *T);
- QualType VisitInjectedClassNameType(const InjectedClassNameType *T);
+ ExpectedType VisitTypeOfType(const TypeOfType *T);
+ ExpectedType VisitDecltypeType(const DecltypeType *T);
+ ExpectedType VisitUnaryTransformType(const UnaryTransformType *T);
+ ExpectedType VisitAutoType(const AutoType *T);
+ ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T);
// FIXME: DependentDecltypeType
- QualType VisitRecordType(const RecordType *T);
- QualType VisitEnumType(const EnumType *T);
- QualType VisitAttributedType(const AttributedType *T);
- QualType VisitTemplateTypeParmType(const TemplateTypeParmType *T);
- QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
- QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
- QualType VisitElaboratedType(const ElaboratedType *T);
- QualType VisitDependentNameType(const DependentNameType *T);
- QualType VisitPackExpansionType(const PackExpansionType *T);
- QualType VisitDependentTemplateSpecializationType(
+ ExpectedType VisitRecordType(const RecordType *T);
+ ExpectedType VisitEnumType(const EnumType *T);
+ ExpectedType VisitAttributedType(const AttributedType *T);
+ ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T);
+ ExpectedType VisitSubstTemplateTypeParmType(
+ const SubstTemplateTypeParmType *T);
+ ExpectedType VisitTemplateSpecializationType(
+ const TemplateSpecializationType *T);
+ ExpectedType VisitElaboratedType(const ElaboratedType *T);
+ ExpectedType VisitDependentNameType(const DependentNameType *T);
+ ExpectedType VisitPackExpansionType(const PackExpansionType *T);
+ ExpectedType VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T);
- QualType VisitObjCInterfaceType(const ObjCInterfaceType *T);
- QualType VisitObjCObjectType(const ObjCObjectType *T);
- QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+ ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T);
+ ExpectedType VisitObjCObjectType(const ObjCObjectType *T);
+ ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
// Importing declarations
- bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
- DeclContext *&LexicalDC, DeclarationName &Name,
- NamedDecl *&ToD, SourceLocation &Loc);
- void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
- void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
- DeclarationNameInfo& To);
- void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
- void ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To);
-
- bool ImportCastPath(CastExpr *E, CXXCastPath &Path);
+ Error ImportDeclParts(
+ NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC,
+ DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc);
+ Error ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
+ Error ImportDeclarationNameLoc(
+ const DeclarationNameInfo &From, DeclarationNameInfo &To);
+ Error ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
+ Error ImportDeclContext(
+ Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC);
+ Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To);
+
+ Expected<CXXCastPath> ImportCastPath(CastExpr *E);
using Designator = DesignatedInitExpr::Designator;
- Designator ImportDesignator(const Designator &D);
-
- Optional<LambdaCapture> ImportLambdaCapture(const LambdaCapture &From);
-
/// What we should import from the definition.
enum ImportDefinitionKind {
/// Import the default subset of the definition, which might be
/// nothing (if minimal import is set) or might be everything (if minimal
/// import is not set).
IDK_Default,
-
/// Import everything.
IDK_Everything,
-
/// Import only the bare bones needed to establish a valid
/// DeclContext.
IDK_Basic
@@ -258,42 +399,44 @@ namespace clang {
(IDK == IDK_Default && !Importer.isMinimalImport());
}
- bool ImportDefinition(RecordDecl *From, RecordDecl *To,
- ImportDefinitionKind Kind = IDK_Default);
- bool ImportDefinition(VarDecl *From, VarDecl *To,
- ImportDefinitionKind Kind = IDK_Default);
- bool ImportDefinition(EnumDecl *From, EnumDecl *To,
- ImportDefinitionKind Kind = IDK_Default);
- bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
- ImportDefinitionKind Kind = IDK_Default);
- bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To,
- ImportDefinitionKind Kind = IDK_Default);
- TemplateParameterList *ImportTemplateParameterList(
+ Error ImportInitializer(VarDecl *From, VarDecl *To);
+ Error ImportDefinition(
+ RecordDecl *From, RecordDecl *To,
+ ImportDefinitionKind Kind = IDK_Default);
+ Error ImportDefinition(
+ EnumDecl *From, EnumDecl *To,
+ ImportDefinitionKind Kind = IDK_Default);
+ Error ImportDefinition(
+ ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
+ ImportDefinitionKind Kind = IDK_Default);
+ Error ImportDefinition(
+ ObjCProtocolDecl *From, ObjCProtocolDecl *To,
+ ImportDefinitionKind Kind = IDK_Default);
+ Expected<TemplateParameterList *> ImportTemplateParameterList(
TemplateParameterList *Params);
- TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
- Optional<TemplateArgumentLoc> ImportTemplateArgumentLoc(
- const TemplateArgumentLoc &TALoc);
- bool ImportTemplateArguments(const TemplateArgument *FromArgs,
- unsigned NumFromArgs,
- SmallVectorImpl<TemplateArgument> &ToArgs);
+ Error ImportTemplateArguments(
+ const TemplateArgument *FromArgs, unsigned NumFromArgs,
+ SmallVectorImpl<TemplateArgument> &ToArgs);
+ Expected<TemplateArgument>
+ ImportTemplateArgument(const TemplateArgument &From);
template <typename InContainerTy>
- bool ImportTemplateArgumentListInfo(const InContainerTy &Container,
- TemplateArgumentListInfo &ToTAInfo);
+ Error ImportTemplateArgumentListInfo(
+ const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo);
template<typename InContainerTy>
- bool ImportTemplateArgumentListInfo(SourceLocation FromLAngleLoc,
- SourceLocation FromRAngleLoc,
- const InContainerTy &Container,
- TemplateArgumentListInfo &Result);
+ Error ImportTemplateArgumentListInfo(
+ SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
+ const InContainerTy &Container, TemplateArgumentListInfo &Result);
using TemplateArgsTy = SmallVector<TemplateArgument, 8>;
- using OptionalTemplateArgsTy = Optional<TemplateArgsTy>;
- std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy>
+ using FunctionTemplateAndArgsTy =
+ std::tuple<FunctionTemplateDecl *, TemplateArgsTy>;
+ Expected<FunctionTemplateAndArgsTy>
ImportFunctionTemplateWithTemplateArgsFromSpecialization(
FunctionDecl *FromFD);
- bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
+ Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
bool IsStructuralMatch(Decl *From, Decl *To, bool Complain);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
@@ -307,257 +450,498 @@ namespace clang {
bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
- Decl *VisitDecl(Decl *D);
- Decl *VisitEmptyDecl(EmptyDecl *D);
- Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
- Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
- Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
- Decl *VisitNamespaceDecl(NamespaceDecl *D);
- Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
- Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
- Decl *VisitTypedefDecl(TypedefDecl *D);
- Decl *VisitTypeAliasDecl(TypeAliasDecl *D);
- Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
- Decl *VisitLabelDecl(LabelDecl *D);
- Decl *VisitEnumDecl(EnumDecl *D);
- Decl *VisitRecordDecl(RecordDecl *D);
- Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
- Decl *VisitFunctionDecl(FunctionDecl *D);
- Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
- Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
- Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
- Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
- Decl *VisitFieldDecl(FieldDecl *D);
- Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
- Decl *VisitFriendDecl(FriendDecl *D);
- Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);
- Decl *VisitVarDecl(VarDecl *D);
- Decl *VisitImplicitParamDecl(ImplicitParamDecl *D);
- Decl *VisitParmVarDecl(ParmVarDecl *D);
- Decl *VisitObjCMethodDecl(ObjCMethodDecl *D);
- Decl *VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
- Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D);
- Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D);
- Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D);
- Decl *VisitUsingDecl(UsingDecl *D);
- Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
- Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
- Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
- Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
-
- ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list);
- Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
- Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
- Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
- Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D);
- Decl *VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
- Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
- Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
- Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
- Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
- Decl *VisitClassTemplateSpecializationDecl(
+ ExpectedDecl VisitDecl(Decl *D);
+ ExpectedDecl VisitImportDecl(ImportDecl *D);
+ ExpectedDecl VisitEmptyDecl(EmptyDecl *D);
+ ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D);
+ ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D);
+ ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D);
+ ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
+ ExpectedDecl VisitTypedefDecl(TypedefDecl *D);
+ ExpectedDecl VisitTypeAliasDecl(TypeAliasDecl *D);
+ ExpectedDecl VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
+ ExpectedDecl VisitLabelDecl(LabelDecl *D);
+ ExpectedDecl VisitEnumDecl(EnumDecl *D);
+ ExpectedDecl VisitRecordDecl(RecordDecl *D);
+ ExpectedDecl VisitEnumConstantDecl(EnumConstantDecl *D);
+ ExpectedDecl VisitFunctionDecl(FunctionDecl *D);
+ ExpectedDecl VisitCXXMethodDecl(CXXMethodDecl *D);
+ ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D);
+ ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D);
+ ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D);
+ ExpectedDecl VisitFieldDecl(FieldDecl *D);
+ ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D);
+ ExpectedDecl VisitFriendDecl(FriendDecl *D);
+ ExpectedDecl VisitObjCIvarDecl(ObjCIvarDecl *D);
+ ExpectedDecl VisitVarDecl(VarDecl *D);
+ ExpectedDecl VisitImplicitParamDecl(ImplicitParamDecl *D);
+ ExpectedDecl VisitParmVarDecl(ParmVarDecl *D);
+ ExpectedDecl VisitObjCMethodDecl(ObjCMethodDecl *D);
+ ExpectedDecl VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
+ ExpectedDecl VisitObjCCategoryDecl(ObjCCategoryDecl *D);
+ ExpectedDecl VisitObjCProtocolDecl(ObjCProtocolDecl *D);
+ ExpectedDecl VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ ExpectedDecl VisitUsingDecl(UsingDecl *D);
+ ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D);
+ ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+ Expected<ObjCTypeParamList *>
+ ImportObjCTypeParamList(ObjCTypeParamList *list);
+
+ ExpectedDecl VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+ ExpectedDecl VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+ ExpectedDecl VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+ ExpectedDecl VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+ ExpectedDecl VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+ ExpectedDecl VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ ExpectedDecl VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ ExpectedDecl VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ ExpectedDecl VisitClassTemplateDecl(ClassTemplateDecl *D);
+ ExpectedDecl VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D);
- Decl *VisitVarTemplateDecl(VarTemplateDecl *D);
- Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
- Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D);
+ ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
+ ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
// Importing statements
- DeclGroupRef ImportDeclGroup(DeclGroupRef DG);
-
- Stmt *VisitStmt(Stmt *S);
- Stmt *VisitGCCAsmStmt(GCCAsmStmt *S);
- Stmt *VisitDeclStmt(DeclStmt *S);
- Stmt *VisitNullStmt(NullStmt *S);
- Stmt *VisitCompoundStmt(CompoundStmt *S);
- Stmt *VisitCaseStmt(CaseStmt *S);
- Stmt *VisitDefaultStmt(DefaultStmt *S);
- Stmt *VisitLabelStmt(LabelStmt *S);
- Stmt *VisitAttributedStmt(AttributedStmt *S);
- Stmt *VisitIfStmt(IfStmt *S);
- Stmt *VisitSwitchStmt(SwitchStmt *S);
- Stmt *VisitWhileStmt(WhileStmt *S);
- Stmt *VisitDoStmt(DoStmt *S);
- Stmt *VisitForStmt(ForStmt *S);
- Stmt *VisitGotoStmt(GotoStmt *S);
- Stmt *VisitIndirectGotoStmt(IndirectGotoStmt *S);
- Stmt *VisitContinueStmt(ContinueStmt *S);
- Stmt *VisitBreakStmt(BreakStmt *S);
- Stmt *VisitReturnStmt(ReturnStmt *S);
+ ExpectedStmt VisitStmt(Stmt *S);
+ ExpectedStmt VisitGCCAsmStmt(GCCAsmStmt *S);
+ ExpectedStmt VisitDeclStmt(DeclStmt *S);
+ ExpectedStmt VisitNullStmt(NullStmt *S);
+ ExpectedStmt VisitCompoundStmt(CompoundStmt *S);
+ ExpectedStmt VisitCaseStmt(CaseStmt *S);
+ ExpectedStmt VisitDefaultStmt(DefaultStmt *S);
+ ExpectedStmt VisitLabelStmt(LabelStmt *S);
+ ExpectedStmt VisitAttributedStmt(AttributedStmt *S);
+ ExpectedStmt VisitIfStmt(IfStmt *S);
+ ExpectedStmt VisitSwitchStmt(SwitchStmt *S);
+ ExpectedStmt VisitWhileStmt(WhileStmt *S);
+ ExpectedStmt VisitDoStmt(DoStmt *S);
+ ExpectedStmt VisitForStmt(ForStmt *S);
+ ExpectedStmt VisitGotoStmt(GotoStmt *S);
+ ExpectedStmt VisitIndirectGotoStmt(IndirectGotoStmt *S);
+ ExpectedStmt VisitContinueStmt(ContinueStmt *S);
+ ExpectedStmt VisitBreakStmt(BreakStmt *S);
+ ExpectedStmt VisitReturnStmt(ReturnStmt *S);
// FIXME: MSAsmStmt
// FIXME: SEHExceptStmt
// FIXME: SEHFinallyStmt
// FIXME: SEHTryStmt
// FIXME: SEHLeaveStmt
// FIXME: CapturedStmt
- Stmt *VisitCXXCatchStmt(CXXCatchStmt *S);
- Stmt *VisitCXXTryStmt(CXXTryStmt *S);
- Stmt *VisitCXXForRangeStmt(CXXForRangeStmt *S);
+ ExpectedStmt VisitCXXCatchStmt(CXXCatchStmt *S);
+ ExpectedStmt VisitCXXTryStmt(CXXTryStmt *S);
+ ExpectedStmt VisitCXXForRangeStmt(CXXForRangeStmt *S);
// FIXME: MSDependentExistsStmt
- Stmt *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
- Stmt *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
- Stmt *VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S);
- Stmt *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
- Stmt *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
- Stmt *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
- Stmt *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
+ ExpectedStmt VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
+ ExpectedStmt VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
+ ExpectedStmt VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S);
+ ExpectedStmt VisitObjCAtTryStmt(ObjCAtTryStmt *S);
+ ExpectedStmt VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
+ ExpectedStmt VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
+ ExpectedStmt VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
// Importing expressions
- Expr *VisitExpr(Expr *E);
- Expr *VisitVAArgExpr(VAArgExpr *E);
- Expr *VisitGNUNullExpr(GNUNullExpr *E);
- Expr *VisitPredefinedExpr(PredefinedExpr *E);
- Expr *VisitDeclRefExpr(DeclRefExpr *E);
- Expr *VisitImplicitValueInitExpr(ImplicitValueInitExpr *ILE);
- Expr *VisitDesignatedInitExpr(DesignatedInitExpr *E);
- Expr *VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
- Expr *VisitIntegerLiteral(IntegerLiteral *E);
- Expr *VisitFloatingLiteral(FloatingLiteral *E);
- Expr *VisitCharacterLiteral(CharacterLiteral *E);
- Expr *VisitStringLiteral(StringLiteral *E);
- Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
- Expr *VisitAtomicExpr(AtomicExpr *E);
- Expr *VisitAddrLabelExpr(AddrLabelExpr *E);
- Expr *VisitParenExpr(ParenExpr *E);
- Expr *VisitParenListExpr(ParenListExpr *E);
- Expr *VisitStmtExpr(StmtExpr *E);
- Expr *VisitUnaryOperator(UnaryOperator *E);
- Expr *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
- Expr *VisitBinaryOperator(BinaryOperator *E);
- Expr *VisitConditionalOperator(ConditionalOperator *E);
- Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
- Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E);
- Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
- Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E);
- Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
- Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
- Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
- Expr *VisitExplicitCastExpr(ExplicitCastExpr *E);
- Expr *VisitOffsetOfExpr(OffsetOfExpr *OE);
- Expr *VisitCXXThrowExpr(CXXThrowExpr *E);
- Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
- Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
- Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
- Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
- Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
- Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
- Expr *VisitPackExpansionExpr(PackExpansionExpr *E);
- Expr *VisitSizeOfPackExpr(SizeOfPackExpr *E);
- Expr *VisitCXXNewExpr(CXXNewExpr *CE);
- Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
- Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
- Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
- Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
- Expr *VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
- Expr *VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *CE);
- Expr *VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
- Expr *VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
- Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
- Expr *VisitCXXThisExpr(CXXThisExpr *E);
- Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
- Expr *VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
- Expr *VisitMemberExpr(MemberExpr *E);
- Expr *VisitCallExpr(CallExpr *E);
- Expr *VisitLambdaExpr(LambdaExpr *LE);
- Expr *VisitInitListExpr(InitListExpr *E);
- Expr *VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
- Expr *VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E);
- Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
- Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
- Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
- Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
- Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
- Expr *VisitTypeTraitExpr(TypeTraitExpr *E);
- Expr *VisitCXXTypeidExpr(CXXTypeidExpr *E);
+ ExpectedStmt VisitExpr(Expr *E);
+ ExpectedStmt VisitVAArgExpr(VAArgExpr *E);
+ ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E);
+ ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E);
+ ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E);
+ ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+ ExpectedStmt VisitDesignatedInitExpr(DesignatedInitExpr *E);
+ ExpectedStmt VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
+ ExpectedStmt VisitIntegerLiteral(IntegerLiteral *E);
+ ExpectedStmt VisitFloatingLiteral(FloatingLiteral *E);
+ ExpectedStmt VisitImaginaryLiteral(ImaginaryLiteral *E);
+ ExpectedStmt VisitCharacterLiteral(CharacterLiteral *E);
+ ExpectedStmt VisitStringLiteral(StringLiteral *E);
+ ExpectedStmt VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+ ExpectedStmt VisitAtomicExpr(AtomicExpr *E);
+ ExpectedStmt VisitAddrLabelExpr(AddrLabelExpr *E);
+ ExpectedStmt VisitConstantExpr(ConstantExpr *E);
+ ExpectedStmt VisitParenExpr(ParenExpr *E);
+ ExpectedStmt VisitParenListExpr(ParenListExpr *E);
+ ExpectedStmt VisitStmtExpr(StmtExpr *E);
+ ExpectedStmt VisitUnaryOperator(UnaryOperator *E);
+ ExpectedStmt VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
+ ExpectedStmt VisitBinaryOperator(BinaryOperator *E);
+ ExpectedStmt VisitConditionalOperator(ConditionalOperator *E);
+ ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
+ ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E);
+ ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
+ ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E);
+ ExpectedStmt VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+ ExpectedStmt VisitCompoundAssignOperator(CompoundAssignOperator *E);
+ ExpectedStmt VisitImplicitCastExpr(ImplicitCastExpr *E);
+ ExpectedStmt VisitExplicitCastExpr(ExplicitCastExpr *E);
+ ExpectedStmt VisitOffsetOfExpr(OffsetOfExpr *OE);
+ ExpectedStmt VisitCXXThrowExpr(CXXThrowExpr *E);
+ ExpectedStmt VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
+ ExpectedStmt VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ ExpectedStmt VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+ ExpectedStmt VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
+ ExpectedStmt VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
+ ExpectedStmt VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
+ ExpectedStmt VisitPackExpansionExpr(PackExpansionExpr *E);
+ ExpectedStmt VisitSizeOfPackExpr(SizeOfPackExpr *E);
+ ExpectedStmt VisitCXXNewExpr(CXXNewExpr *E);
+ ExpectedStmt VisitCXXDeleteExpr(CXXDeleteExpr *E);
+ ExpectedStmt VisitCXXConstructExpr(CXXConstructExpr *E);
+ ExpectedStmt VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+ ExpectedStmt VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+ ExpectedStmt VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
+ ExpectedStmt VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
+ ExpectedStmt VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
+ ExpectedStmt VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
+ ExpectedStmt VisitExprWithCleanups(ExprWithCleanups *E);
+ ExpectedStmt VisitCXXThisExpr(CXXThisExpr *E);
+ ExpectedStmt VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
+ ExpectedStmt VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
+ ExpectedStmt VisitMemberExpr(MemberExpr *E);
+ ExpectedStmt VisitCallExpr(CallExpr *E);
+ ExpectedStmt VisitLambdaExpr(LambdaExpr *LE);
+ ExpectedStmt VisitInitListExpr(InitListExpr *E);
+ ExpectedStmt VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
+ ExpectedStmt VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E);
+ ExpectedStmt VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
+ ExpectedStmt VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
+ ExpectedStmt VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
+ ExpectedStmt VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+ ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
+ ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E);
+ ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E);
template<typename IIter, typename OIter>
- void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) {
+ Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
using ItemT = typename std::remove_reference<decltype(*Obegin)>::type;
-
- ASTImporter &ImporterRef = Importer;
- std::transform(Ibegin, Iend, Obegin,
- [&ImporterRef](ItemT From) -> ItemT {
- return ImporterRef.Import(From);
- });
- }
-
- template<typename IIter, typename OIter>
- bool ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
- using ItemT = typename std::remove_reference<decltype(**Obegin)>::type;
-
- ASTImporter &ImporterRef = Importer;
- bool Failed = false;
- std::transform(Ibegin, Iend, Obegin,
- [&ImporterRef, &Failed](ItemT *From) -> ItemT * {
- auto *To = cast_or_null<ItemT>(ImporterRef.Import(From));
- if (!To && From)
- Failed = true;
- return To;
- });
- return Failed;
+ for (; Ibegin != Iend; ++Ibegin, ++Obegin) {
+ Expected<ItemT> ToOrErr = import(*Ibegin);
+ if (!ToOrErr)
+ return ToOrErr.takeError();
+ *Obegin = *ToOrErr;
+ }
+ return Error::success();
}
+ // Import every item from a container structure into an output container.
+ // If error occurs, stops at first error and returns the error.
+ // The output container should have space for all needed elements (it is not
+ // expanded, new items are put into from the beginning).
template<typename InContainerTy, typename OutContainerTy>
- bool ImportContainerChecked(const InContainerTy &InContainer,
- OutContainerTy &OutContainer) {
- return ImportArrayChecked(InContainer.begin(), InContainer.end(),
- OutContainer.begin());
+ Error ImportContainerChecked(
+ const InContainerTy &InContainer, OutContainerTy &OutContainer) {
+ return ImportArrayChecked(
+ InContainer.begin(), InContainer.end(), OutContainer.begin());
}
template<typename InContainerTy, typename OIter>
- bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
+ Error ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
}
- // Importing overrides.
void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod);
- FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD);
+ Expected<FunctionDecl *> FindFunctionTemplateSpecialization(
+ FunctionDecl *FromFD);
};
+// FIXME: Temporary until every import returns Expected.
+template <>
+Expected<TemplateName> ASTNodeImporter::import(const TemplateName &From) {
+ TemplateName To = Importer.Import(From);
+ if (To.isNull() && !From.isNull())
+ return make_error<ImportError>();
+ return To;
+}
+
template <typename InContainerTy>
-bool ASTNodeImporter::ImportTemplateArgumentListInfo(
+Error ASTNodeImporter::ImportTemplateArgumentListInfo(
SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
const InContainerTy &Container, TemplateArgumentListInfo &Result) {
- TemplateArgumentListInfo ToTAInfo(Importer.Import(FromLAngleLoc),
- Importer.Import(FromRAngleLoc));
- if (ImportTemplateArgumentListInfo(Container, ToTAInfo))
- return true;
+ auto ToLAngleLocOrErr = import(FromLAngleLoc);
+ if (!ToLAngleLocOrErr)
+ return ToLAngleLocOrErr.takeError();
+ auto ToRAngleLocOrErr = import(FromRAngleLoc);
+ if (!ToRAngleLocOrErr)
+ return ToRAngleLocOrErr.takeError();
+
+ TemplateArgumentListInfo ToTAInfo(*ToLAngleLocOrErr, *ToRAngleLocOrErr);
+ if (auto Err = ImportTemplateArgumentListInfo(Container, ToTAInfo))
+ return Err;
Result = ToTAInfo;
- return false;
+ return Error::success();
}
template <>
-bool ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>(
+Error ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>(
const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) {
return ImportTemplateArgumentListInfo(
From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result);
}
template <>
-bool ASTNodeImporter::ImportTemplateArgumentListInfo<
- ASTTemplateArgumentListInfo>(const ASTTemplateArgumentListInfo &From,
- TemplateArgumentListInfo &Result) {
- return ImportTemplateArgumentListInfo(From.LAngleLoc, From.RAngleLoc,
- From.arguments(), Result);
+Error ASTNodeImporter::ImportTemplateArgumentListInfo<
+ ASTTemplateArgumentListInfo>(
+ const ASTTemplateArgumentListInfo &From,
+ TemplateArgumentListInfo &Result) {
+ return ImportTemplateArgumentListInfo(
+ From.LAngleLoc, From.RAngleLoc, From.arguments(), Result);
}
-std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy>
+Expected<ASTNodeImporter::FunctionTemplateAndArgsTy>
ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(
FunctionDecl *FromFD) {
assert(FromFD->getTemplatedKind() ==
- FunctionDecl::TK_FunctionTemplateSpecialization);
+ FunctionDecl::TK_FunctionTemplateSpecialization);
+
+ FunctionTemplateAndArgsTy Result;
+
auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
- auto *Template = cast_or_null<FunctionTemplateDecl>(
- Importer.Import(FTSInfo->getTemplate()));
+ if (Error Err = importInto(std::get<0>(Result), FTSInfo->getTemplate()))
+ return std::move(Err);
// Import template arguments.
auto TemplArgs = FTSInfo->TemplateArguments->asArray();
- TemplateArgsTy ToTemplArgs;
- if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),
- ToTemplArgs)) // Error during import.
- return std::make_tuple(Template, OptionalTemplateArgsTy());
+ if (Error Err = ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),
+ std::get<1>(Result)))
+ return std::move(Err);
- return std::make_tuple(Template, ToTemplArgs);
+ return Result;
+}
+
+template <>
+Expected<TemplateParameterList *>
+ASTNodeImporter::import(TemplateParameterList *From) {
+ SmallVector<NamedDecl *, 4> To(From->size());
+ if (Error Err = ImportContainerChecked(*From, To))
+ return std::move(Err);
+
+ ExpectedExpr ToRequiresClause = import(From->getRequiresClause());
+ if (!ToRequiresClause)
+ return ToRequiresClause.takeError();
+
+ auto ToTemplateLocOrErr = import(From->getTemplateLoc());
+ if (!ToTemplateLocOrErr)
+ return ToTemplateLocOrErr.takeError();
+ auto ToLAngleLocOrErr = import(From->getLAngleLoc());
+ if (!ToLAngleLocOrErr)
+ return ToLAngleLocOrErr.takeError();
+ auto ToRAngleLocOrErr = import(From->getRAngleLoc());
+ if (!ToRAngleLocOrErr)
+ return ToRAngleLocOrErr.takeError();
+
+ return TemplateParameterList::Create(
+ Importer.getToContext(),
+ *ToTemplateLocOrErr,
+ *ToLAngleLocOrErr,
+ To,
+ *ToRAngleLocOrErr,
+ *ToRequiresClause);
+}
+
+template <>
+Expected<TemplateArgument>
+ASTNodeImporter::import(const TemplateArgument &From) {
+ switch (From.getKind()) {
+ case TemplateArgument::Null:
+ return TemplateArgument();
+
+ case TemplateArgument::Type: {
+ ExpectedType ToTypeOrErr = import(From.getAsType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+ return TemplateArgument(*ToTypeOrErr);
+ }
+
+ case TemplateArgument::Integral: {
+ ExpectedType ToTypeOrErr = import(From.getIntegralType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+ return TemplateArgument(From, *ToTypeOrErr);
+ }
+
+ case TemplateArgument::Declaration: {
+ Expected<ValueDecl *> ToOrErr = import(From.getAsDecl());
+ if (!ToOrErr)
+ return ToOrErr.takeError();
+ ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+ return TemplateArgument(*ToOrErr, *ToTypeOrErr);
+ }
+
+ case TemplateArgument::NullPtr: {
+ ExpectedType ToTypeOrErr = import(From.getNullPtrType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+ return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true);
+ }
+
+ case TemplateArgument::Template: {
+ Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
+ if (!ToTemplateOrErr)
+ return ToTemplateOrErr.takeError();
+
+ return TemplateArgument(*ToTemplateOrErr);
+ }
+
+ case TemplateArgument::TemplateExpansion: {
+ Expected<TemplateName> ToTemplateOrErr =
+ import(From.getAsTemplateOrTemplatePattern());
+ if (!ToTemplateOrErr)
+ return ToTemplateOrErr.takeError();
+
+ return TemplateArgument(
+ *ToTemplateOrErr, From.getNumTemplateExpansions());
+ }
+
+ case TemplateArgument::Expression:
+ if (ExpectedExpr ToExpr = import(From.getAsExpr()))
+ return TemplateArgument(*ToExpr);
+ else
+ return ToExpr.takeError();
+
+ case TemplateArgument::Pack: {
+ SmallVector<TemplateArgument, 2> ToPack;
+ ToPack.reserve(From.pack_size());
+ if (Error Err = ImportTemplateArguments(
+ From.pack_begin(), From.pack_size(), ToPack))
+ return std::move(Err);
+
+ return TemplateArgument(
+ llvm::makeArrayRef(ToPack).copy(Importer.getToContext()));
+ }
+ }
+
+ llvm_unreachable("Invalid template argument kind");
+}
+
+template <>
+Expected<TemplateArgumentLoc>
+ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) {
+ Expected<TemplateArgument> ArgOrErr = import(TALoc.getArgument());
+ if (!ArgOrErr)
+ return ArgOrErr.takeError();
+ TemplateArgument Arg = *ArgOrErr;
+
+ TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
+
+ TemplateArgumentLocInfo ToInfo;
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ ExpectedExpr E = import(FromInfo.getAsExpr());
+ if (!E)
+ return E.takeError();
+ ToInfo = TemplateArgumentLocInfo(*E);
+ } else if (Arg.getKind() == TemplateArgument::Type) {
+ if (auto TSIOrErr = import(FromInfo.getAsTypeSourceInfo()))
+ ToInfo = TemplateArgumentLocInfo(*TSIOrErr);
+ else
+ return TSIOrErr.takeError();
+ } else {
+ auto ToTemplateQualifierLocOrErr =
+ import(FromInfo.getTemplateQualifierLoc());
+ if (!ToTemplateQualifierLocOrErr)
+ return ToTemplateQualifierLocOrErr.takeError();
+ auto ToTemplateNameLocOrErr = import(FromInfo.getTemplateNameLoc());
+ if (!ToTemplateNameLocOrErr)
+ return ToTemplateNameLocOrErr.takeError();
+ auto ToTemplateEllipsisLocOrErr =
+ import(FromInfo.getTemplateEllipsisLoc());
+ if (!ToTemplateEllipsisLocOrErr)
+ return ToTemplateEllipsisLocOrErr.takeError();
+
+ ToInfo = TemplateArgumentLocInfo(
+ *ToTemplateQualifierLocOrErr,
+ *ToTemplateNameLocOrErr,
+ *ToTemplateEllipsisLocOrErr);
+ }
+
+ return TemplateArgumentLoc(Arg, ToInfo);
+}
+
+template <>
+Expected<DeclGroupRef> ASTNodeImporter::import(const DeclGroupRef &DG) {
+ if (DG.isNull())
+ return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0);
+ size_t NumDecls = DG.end() - DG.begin();
+ SmallVector<Decl *, 1> ToDecls;
+ ToDecls.reserve(NumDecls);
+ for (Decl *FromD : DG) {
+ if (auto ToDOrErr = import(FromD))
+ ToDecls.push_back(*ToDOrErr);
+ else
+ return ToDOrErr.takeError();
+ }
+ return DeclGroupRef::Create(Importer.getToContext(),
+ ToDecls.begin(),
+ NumDecls);
+}
+
+template <>
+Expected<ASTNodeImporter::Designator>
+ASTNodeImporter::import(const Designator &D) {
+ if (D.isFieldDesignator()) {
+ IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName());
+
+ ExpectedSLoc ToDotLocOrErr = import(D.getDotLoc());
+ if (!ToDotLocOrErr)
+ return ToDotLocOrErr.takeError();
+
+ ExpectedSLoc ToFieldLocOrErr = import(D.getFieldLoc());
+ if (!ToFieldLocOrErr)
+ return ToFieldLocOrErr.takeError();
+
+ return Designator(ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr);
+ }
+
+ ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc());
+ if (!ToLBracketLocOrErr)
+ return ToLBracketLocOrErr.takeError();
+
+ ExpectedSLoc ToRBracketLocOrErr = import(D.getRBracketLoc());
+ if (!ToRBracketLocOrErr)
+ return ToRBracketLocOrErr.takeError();
+
+ if (D.isArrayDesignator())
+ return Designator(D.getFirstExprIndex(),
+ *ToLBracketLocOrErr, *ToRBracketLocOrErr);
+
+ ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc());
+ if (!ToEllipsisLocOrErr)
+ return ToEllipsisLocOrErr.takeError();
+
+ assert(D.isArrayRangeDesignator());
+ return Designator(
+ D.getFirstExprIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr,
+ *ToRBracketLocOrErr);
+}
+
+template <>
+Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
+ VarDecl *Var = nullptr;
+ if (From.capturesVariable()) {
+ if (auto VarOrErr = import(From.getCapturedVar()))
+ Var = *VarOrErr;
+ else
+ return VarOrErr.takeError();
+ }
+
+ auto LocationOrErr = import(From.getLocation());
+ if (!LocationOrErr)
+ return LocationOrErr.takeError();
+
+ SourceLocation EllipsisLoc;
+ if (From.isPackExpansion())
+ if (Error Err = importInto(EllipsisLoc, From.getEllipsisLoc()))
+ return std::move(Err);
+
+ return LambdaCapture(
+ *LocationOrErr, From.isImplicit(), From.getCaptureKind(), Var,
+ EllipsisLoc);
}
} // namespace clang
@@ -568,26 +952,30 @@ ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(
using namespace clang;
-QualType ASTNodeImporter::VisitType(const Type *T) {
+ExpectedType ASTNodeImporter::VisitType(const Type *T) {
Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
<< T->getTypeClassName();
- return {};
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
-QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
- QualType UnderlyingType = Importer.Import(T->getValueType());
- if(UnderlyingType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
+ ExpectedType UnderlyingTypeOrErr = import(T->getValueType());
+ if (!UnderlyingTypeOrErr)
+ return UnderlyingTypeOrErr.takeError();
- return Importer.getToContext().getAtomicType(UnderlyingType);
+ return Importer.getToContext().getAtomicType(*UnderlyingTypeOrErr);
}
-QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
+ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
switch (T->getKind()) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
return Importer.getToContext().SingletonId;
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id: \
+ return Importer.getToContext().Id##Ty;
+#include "clang/Basic/OpenCLExtensionTypes.def"
#define SHARED_SINGLETON_TYPE(Expansion)
#define BUILTIN_TYPE(Id, SingletonId) \
case BuiltinType::Id: return Importer.getToContext().SingletonId;
@@ -627,183 +1015,196 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
llvm_unreachable("Invalid BuiltinType Kind!");
}
-QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
- QualType OrigT = Importer.Import(T->getOriginalType());
- if (OrigT.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
+ ExpectedType ToOriginalTypeOrErr = import(T->getOriginalType());
+ if (!ToOriginalTypeOrErr)
+ return ToOriginalTypeOrErr.takeError();
- return Importer.getToContext().getDecayedType(OrigT);
+ return Importer.getToContext().getDecayedType(*ToOriginalTypeOrErr);
}
-QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
+ ExpectedType ToElementTypeOrErr = import(T->getElementType());
+ if (!ToElementTypeOrErr)
+ return ToElementTypeOrErr.takeError();
- return Importer.getToContext().getComplexType(ToElementType);
+ return Importer.getToContext().getComplexType(*ToElementTypeOrErr);
}
-QualType ASTNodeImporter::VisitPointerType(const PointerType *T) {
- QualType ToPointeeType = Importer.Import(T->getPointeeType());
- if (ToPointeeType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitPointerType(const PointerType *T) {
+ ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
+ if (!ToPointeeTypeOrErr)
+ return ToPointeeTypeOrErr.takeError();
- return Importer.getToContext().getPointerType(ToPointeeType);
+ return Importer.getToContext().getPointerType(*ToPointeeTypeOrErr);
}
-QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
+ExpectedType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
// FIXME: Check for blocks support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeType());
- if (ToPointeeType.isNull())
- return {};
+ ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
+ if (!ToPointeeTypeOrErr)
+ return ToPointeeTypeOrErr.takeError();
- return Importer.getToContext().getBlockPointerType(ToPointeeType);
+ return Importer.getToContext().getBlockPointerType(*ToPointeeTypeOrErr);
}
-QualType
+ExpectedType
ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) {
// FIXME: Check for C++ support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
- if (ToPointeeType.isNull())
- return {};
+ ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten());
+ if (!ToPointeeTypeOrErr)
+ return ToPointeeTypeOrErr.takeError();
- return Importer.getToContext().getLValueReferenceType(ToPointeeType);
+ return Importer.getToContext().getLValueReferenceType(*ToPointeeTypeOrErr);
}
-QualType
+ExpectedType
ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) {
// FIXME: Check for C++0x support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
- if (ToPointeeType.isNull())
- return {};
+ ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten());
+ if (!ToPointeeTypeOrErr)
+ return ToPointeeTypeOrErr.takeError();
- return Importer.getToContext().getRValueReferenceType(ToPointeeType);
+ return Importer.getToContext().getRValueReferenceType(*ToPointeeTypeOrErr);
}
-QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
+ExpectedType
+ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
// FIXME: Check for C++ support in "to" context.
- QualType ToPointeeType = Importer.Import(T->getPointeeType());
- if (ToPointeeType.isNull())
- return {};
+ ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
+ if (!ToPointeeTypeOrErr)
+ return ToPointeeTypeOrErr.takeError();
- QualType ClassType = Importer.Import(QualType(T->getClass(), 0));
- return Importer.getToContext().getMemberPointerType(ToPointeeType,
- ClassType.getTypePtr());
+ ExpectedType ClassTypeOrErr = import(QualType(T->getClass(), 0));
+ if (!ClassTypeOrErr)
+ return ClassTypeOrErr.takeError();
+
+ return Importer.getToContext().getMemberPointerType(
+ *ToPointeeTypeOrErr, (*ClassTypeOrErr).getTypePtr());
}
-QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return {};
+ExpectedType
+ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
+ ExpectedType ToElementTypeOrErr = import(T->getElementType());
+ if (!ToElementTypeOrErr)
+ return ToElementTypeOrErr.takeError();
- return Importer.getToContext().getConstantArrayType(ToElementType,
+ return Importer.getToContext().getConstantArrayType(*ToElementTypeOrErr,
T->getSize(),
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
-QualType
+ExpectedType
ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return {};
+ ExpectedType ToElementTypeOrErr = import(T->getElementType());
+ if (!ToElementTypeOrErr)
+ return ToElementTypeOrErr.takeError();
- return Importer.getToContext().getIncompleteArrayType(ToElementType,
+ return Importer.getToContext().getIncompleteArrayType(*ToElementTypeOrErr,
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
-QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return {};
-
- Expr *Size = Importer.Import(T->getSizeExpr());
- if (!Size)
- return {};
+ExpectedType
+ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
+ QualType ToElementType;
+ Expr *ToSizeExpr;
+ SourceRange ToBracketsRange;
+ if (auto Imp = importSeq(
+ T->getElementType(), T->getSizeExpr(), T->getBracketsRange()))
+ std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp;
+ else
+ return Imp.takeError();
- SourceRange Brackets = Importer.Import(T->getBracketsRange());
- return Importer.getToContext().getVariableArrayType(ToElementType, Size,
- T->getSizeModifier(),
- T->getIndexTypeCVRQualifiers(),
- Brackets);
+ return Importer.getToContext().getVariableArrayType(
+ ToElementType, ToSizeExpr, T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers(), ToBracketsRange);
}
-QualType ASTNodeImporter::VisitDependentSizedArrayType(
+ExpectedType ASTNodeImporter::VisitDependentSizedArrayType(
const DependentSizedArrayType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return {};
-
+ QualType ToElementType;
+ Expr *ToSizeExpr;
+ SourceRange ToBracketsRange;
+ if (auto Imp = importSeq(
+ T->getElementType(), T->getSizeExpr(), T->getBracketsRange()))
+ std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp;
+ else
+ return Imp.takeError();
// SizeExpr may be null if size is not specified directly.
// For example, 'int a[]'.
- Expr *Size = Importer.Import(T->getSizeExpr());
- if (!Size && T->getSizeExpr())
- return {};
- SourceRange Brackets = Importer.Import(T->getBracketsRange());
return Importer.getToContext().getDependentSizedArrayType(
- ToElementType, Size, T->getSizeModifier(), T->getIndexTypeCVRQualifiers(),
- Brackets);
+ ToElementType, ToSizeExpr, T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers(), ToBracketsRange);
}
-QualType ASTNodeImporter::VisitVectorType(const VectorType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitVectorType(const VectorType *T) {
+ ExpectedType ToElementTypeOrErr = import(T->getElementType());
+ if (!ToElementTypeOrErr)
+ return ToElementTypeOrErr.takeError();
- return Importer.getToContext().getVectorType(ToElementType,
+ return Importer.getToContext().getVectorType(*ToElementTypeOrErr,
T->getNumElements(),
T->getVectorKind());
}
-QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
- QualType ToElementType = Importer.Import(T->getElementType());
- if (ToElementType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
+ ExpectedType ToElementTypeOrErr = import(T->getElementType());
+ if (!ToElementTypeOrErr)
+ return ToElementTypeOrErr.takeError();
- return Importer.getToContext().getExtVectorType(ToElementType,
+ return Importer.getToContext().getExtVectorType(*ToElementTypeOrErr,
T->getNumElements());
}
-QualType
+ExpectedType
ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
// FIXME: What happens if we're importing a function without a prototype
// into C++? Should we make it variadic?
- QualType ToResultType = Importer.Import(T->getReturnType());
- if (ToResultType.isNull())
- return {};
+ ExpectedType ToReturnTypeOrErr = import(T->getReturnType());
+ if (!ToReturnTypeOrErr)
+ return ToReturnTypeOrErr.takeError();
- return Importer.getToContext().getFunctionNoProtoType(ToResultType,
+ return Importer.getToContext().getFunctionNoProtoType(*ToReturnTypeOrErr,
T->getExtInfo());
}
-QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
- QualType ToResultType = Importer.Import(T->getReturnType());
- if (ToResultType.isNull())
- return {};
+ExpectedType
+ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
+ ExpectedType ToReturnTypeOrErr = import(T->getReturnType());
+ if (!ToReturnTypeOrErr)
+ return ToReturnTypeOrErr.takeError();
// Import argument types
SmallVector<QualType, 4> ArgTypes;
for (const auto &A : T->param_types()) {
- QualType ArgType = Importer.Import(A);
- if (ArgType.isNull())
- return {};
- ArgTypes.push_back(ArgType);
+ ExpectedType TyOrErr = import(A);
+ if (!TyOrErr)
+ return TyOrErr.takeError();
+ ArgTypes.push_back(*TyOrErr);
}
// Import exception types
SmallVector<QualType, 4> ExceptionTypes;
for (const auto &E : T->exceptions()) {
- QualType ExceptionType = Importer.Import(E);
- if (ExceptionType.isNull())
- return {};
- ExceptionTypes.push_back(ExceptionType);
+ ExpectedType TyOrErr = import(E);
+ if (!TyOrErr)
+ return TyOrErr.takeError();
+ ExceptionTypes.push_back(*TyOrErr);
}
FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo ToEPI;
+ auto Imp = importSeq(
+ FromEPI.ExceptionSpec.NoexceptExpr,
+ FromEPI.ExceptionSpec.SourceDecl,
+ FromEPI.ExceptionSpec.SourceTemplate);
+ if (!Imp)
+ return Imp.takeError();
+
ToEPI.ExtInfo = FromEPI.ExtInfo;
ToEPI.Variadic = FromEPI.Variadic;
ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
@@ -811,112 +1212,108 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
ToEPI.RefQualifier = FromEPI.RefQualifier;
ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type;
ToEPI.ExceptionSpec.Exceptions = ExceptionTypes;
- ToEPI.ExceptionSpec.NoexceptExpr =
- Importer.Import(FromEPI.ExceptionSpec.NoexceptExpr);
- ToEPI.ExceptionSpec.SourceDecl = cast_or_null<FunctionDecl>(
- Importer.Import(FromEPI.ExceptionSpec.SourceDecl));
- ToEPI.ExceptionSpec.SourceTemplate = cast_or_null<FunctionDecl>(
- Importer.Import(FromEPI.ExceptionSpec.SourceTemplate));
+ std::tie(
+ ToEPI.ExceptionSpec.NoexceptExpr,
+ ToEPI.ExceptionSpec.SourceDecl,
+ ToEPI.ExceptionSpec.SourceTemplate) = *Imp;
- return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI);
+ return Importer.getToContext().getFunctionType(
+ *ToReturnTypeOrErr, ArgTypes, ToEPI);
}
-QualType ASTNodeImporter::VisitUnresolvedUsingType(
+ExpectedType ASTNodeImporter::VisitUnresolvedUsingType(
const UnresolvedUsingType *T) {
- const auto *ToD =
- cast_or_null<UnresolvedUsingTypenameDecl>(Importer.Import(T->getDecl()));
- if (!ToD)
- return {};
-
- auto *ToPrevD =
- cast_or_null<UnresolvedUsingTypenameDecl>(
- Importer.Import(T->getDecl()->getPreviousDecl()));
- if (!ToPrevD && T->getDecl()->getPreviousDecl())
- return {};
+ UnresolvedUsingTypenameDecl *ToD;
+ Decl *ToPrevD;
+ if (auto Imp = importSeq(T->getDecl(), T->getDecl()->getPreviousDecl()))
+ std::tie(ToD, ToPrevD) = *Imp;
+ else
+ return Imp.takeError();
- return Importer.getToContext().getTypeDeclType(ToD, ToPrevD);
+ return Importer.getToContext().getTypeDeclType(
+ ToD, cast_or_null<TypeDecl>(ToPrevD));
}
-QualType ASTNodeImporter::VisitParenType(const ParenType *T) {
- QualType ToInnerType = Importer.Import(T->getInnerType());
- if (ToInnerType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitParenType(const ParenType *T) {
+ ExpectedType ToInnerTypeOrErr = import(T->getInnerType());
+ if (!ToInnerTypeOrErr)
+ return ToInnerTypeOrErr.takeError();
- return Importer.getToContext().getParenType(ToInnerType);
+ return Importer.getToContext().getParenType(*ToInnerTypeOrErr);
}
-QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
- auto *ToDecl =
- dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl()));
- if (!ToDecl)
- return {};
+ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
+ Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl());
+ if (!ToDeclOrErr)
+ return ToDeclOrErr.takeError();
- return Importer.getToContext().getTypeDeclType(ToDecl);
+ return Importer.getToContext().getTypeDeclType(*ToDeclOrErr);
}
-QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
- Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
- if (!ToExpr)
- return {};
+ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
+ ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr());
+ if (!ToExprOrErr)
+ return ToExprOrErr.takeError();
- return Importer.getToContext().getTypeOfExprType(ToExpr);
+ return Importer.getToContext().getTypeOfExprType(*ToExprOrErr);
}
-QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
- QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
- if (ToUnderlyingType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
+ ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+ if (!ToUnderlyingTypeOrErr)
+ return ToUnderlyingTypeOrErr.takeError();
- return Importer.getToContext().getTypeOfType(ToUnderlyingType);
+ return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr);
}
-QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
+ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
// FIXME: Make sure that the "to" context supports C++0x!
- Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
- if (!ToExpr)
- return {};
+ ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr());
+ if (!ToExprOrErr)
+ return ToExprOrErr.takeError();
- QualType UnderlyingType = Importer.Import(T->getUnderlyingType());
- if (UnderlyingType.isNull())
- return {};
+ ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+ if (!ToUnderlyingTypeOrErr)
+ return ToUnderlyingTypeOrErr.takeError();
- return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType);
+ return Importer.getToContext().getDecltypeType(
+ *ToExprOrErr, *ToUnderlyingTypeOrErr);
}
-QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
- QualType ToBaseType = Importer.Import(T->getBaseType());
- QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
- if (ToBaseType.isNull() || ToUnderlyingType.isNull())
- return {};
+ExpectedType
+ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
+ ExpectedType ToBaseTypeOrErr = import(T->getBaseType());
+ if (!ToBaseTypeOrErr)
+ return ToBaseTypeOrErr.takeError();
+
+ ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+ if (!ToUnderlyingTypeOrErr)
+ return ToUnderlyingTypeOrErr.takeError();
- return Importer.getToContext().getUnaryTransformType(ToBaseType,
- ToUnderlyingType,
- T->getUTTKind());
+ return Importer.getToContext().getUnaryTransformType(
+ *ToBaseTypeOrErr, *ToUnderlyingTypeOrErr, T->getUTTKind());
}
-QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
+ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) {
// FIXME: Make sure that the "to" context supports C++11!
- QualType FromDeduced = T->getDeducedType();
- QualType ToDeduced;
- if (!FromDeduced.isNull()) {
- ToDeduced = Importer.Import(FromDeduced);
- if (ToDeduced.isNull())
- return {};
- }
+ ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType());
+ if (!ToDeducedTypeOrErr)
+ return ToDeducedTypeOrErr.takeError();
- return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(),
+ return Importer.getToContext().getAutoType(*ToDeducedTypeOrErr,
+ T->getKeyword(),
/*IsDependent*/false);
}
-QualType ASTNodeImporter::VisitInjectedClassNameType(
+ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
const InjectedClassNameType *T) {
- auto *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl()));
- if (!D)
- return {};
+ Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl());
+ if (!ToDeclOrErr)
+ return ToDeclOrErr.takeError();
- QualType InjType = Importer.Import(T->getInjectedSpecializationType());
- if (InjType.isNull())
- return {};
+ ExpectedType ToInjTypeOrErr = import(T->getInjectedSpecializationType());
+ if (!ToInjTypeOrErr)
+ return ToInjTypeOrErr.takeError();
// FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading
// See comments in InjectedClassNameType definition for details
@@ -927,293 +1324,287 @@ QualType ASTNodeImporter::VisitInjectedClassNameType(
};
return QualType(new (Importer.getToContext(), TypeAlignment)
- InjectedClassNameType(D, InjType), 0);
+ InjectedClassNameType(*ToDeclOrErr, *ToInjTypeOrErr), 0);
}
-QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
- auto *ToDecl = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl()));
- if (!ToDecl)
- return {};
+ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) {
+ Expected<RecordDecl *> ToDeclOrErr = import(T->getDecl());
+ if (!ToDeclOrErr)
+ return ToDeclOrErr.takeError();
- return Importer.getToContext().getTagDeclType(ToDecl);
+ return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
}
-QualType ASTNodeImporter::VisitEnumType(const EnumType *T) {
- auto *ToDecl = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl()));
- if (!ToDecl)
- return {};
+ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) {
+ Expected<EnumDecl *> ToDeclOrErr = import(T->getDecl());
+ if (!ToDeclOrErr)
+ return ToDeclOrErr.takeError();
- return Importer.getToContext().getTagDeclType(ToDecl);
+ return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
}
-QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
- QualType FromModifiedType = T->getModifiedType();
- QualType FromEquivalentType = T->getEquivalentType();
- QualType ToModifiedType;
- QualType ToEquivalentType;
-
- if (!FromModifiedType.isNull()) {
- ToModifiedType = Importer.Import(FromModifiedType);
- if (ToModifiedType.isNull())
- return {};
- }
- if (!FromEquivalentType.isNull()) {
- ToEquivalentType = Importer.Import(FromEquivalentType);
- if (ToEquivalentType.isNull())
- return {};
- }
+ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
+ ExpectedType ToModifiedTypeOrErr = import(T->getModifiedType());
+ if (!ToModifiedTypeOrErr)
+ return ToModifiedTypeOrErr.takeError();
+ ExpectedType ToEquivalentTypeOrErr = import(T->getEquivalentType());
+ if (!ToEquivalentTypeOrErr)
+ return ToEquivalentTypeOrErr.takeError();
return Importer.getToContext().getAttributedType(T->getAttrKind(),
- ToModifiedType, ToEquivalentType);
+ *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr);
}
-QualType ASTNodeImporter::VisitTemplateTypeParmType(
+ExpectedType ASTNodeImporter::VisitTemplateTypeParmType(
const TemplateTypeParmType *T) {
- auto *ParmDecl =
- cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl()));
- if (!ParmDecl && T->getDecl())
- return {};
+ Expected<TemplateTypeParmDecl *> ToDeclOrErr = import(T->getDecl());
+ if (!ToDeclOrErr)
+ return ToDeclOrErr.takeError();
return Importer.getToContext().getTemplateTypeParmType(
- T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl);
+ T->getDepth(), T->getIndex(), T->isParameterPack(), *ToDeclOrErr);
}
-QualType ASTNodeImporter::VisitSubstTemplateTypeParmType(
+ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *T) {
- const auto *Replaced =
- cast_or_null<TemplateTypeParmType>(Importer.Import(
- QualType(T->getReplacedParameter(), 0)).getTypePtr());
- if (!Replaced)
- return {};
+ ExpectedType ReplacedOrErr = import(QualType(T->getReplacedParameter(), 0));
+ if (!ReplacedOrErr)
+ return ReplacedOrErr.takeError();
+ const TemplateTypeParmType *Replaced =
+ cast<TemplateTypeParmType>((*ReplacedOrErr).getTypePtr());
- QualType Replacement = Importer.Import(T->getReplacementType());
- if (Replacement.isNull())
- return {};
- Replacement = Replacement.getCanonicalType();
+ ExpectedType ToReplacementTypeOrErr = import(T->getReplacementType());
+ if (!ToReplacementTypeOrErr)
+ return ToReplacementTypeOrErr.takeError();
return Importer.getToContext().getSubstTemplateTypeParmType(
- Replaced, Replacement);
+ Replaced, (*ToReplacementTypeOrErr).getCanonicalType());
}
-QualType ASTNodeImporter::VisitTemplateSpecializationType(
+ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
- TemplateName ToTemplate = Importer.Import(T->getTemplateName());
- if (ToTemplate.isNull())
- return {};
+ auto ToTemplateOrErr = import(T->getTemplateName());
+ if (!ToTemplateOrErr)
+ return ToTemplateOrErr.takeError();
SmallVector<TemplateArgument, 2> ToTemplateArgs;
- if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToTemplateArgs))
- return {};
+ if (Error Err = ImportTemplateArguments(
+ T->getArgs(), T->getNumArgs(), ToTemplateArgs))
+ return std::move(Err);
QualType ToCanonType;
if (!QualType(T, 0).isCanonical()) {
QualType FromCanonType
= Importer.getFromContext().getCanonicalType(QualType(T, 0));
- ToCanonType =Importer.Import(FromCanonType);
- if (ToCanonType.isNull())
- return {};
+ if (ExpectedType TyOrErr = import(FromCanonType))
+ ToCanonType = *TyOrErr;
+ else
+ return TyOrErr.takeError();
}
- return Importer.getToContext().getTemplateSpecializationType(ToTemplate,
+ return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr,
ToTemplateArgs,
ToCanonType);
}
-QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
- NestedNameSpecifier *ToQualifier = nullptr;
+ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
// Note: the qualifier in an ElaboratedType is optional.
- if (T->getQualifier()) {
- ToQualifier = Importer.Import(T->getQualifier());
- if (!ToQualifier)
- return {};
- }
+ auto ToQualifierOrErr = import(T->getQualifier());
+ if (!ToQualifierOrErr)
+ return ToQualifierOrErr.takeError();
- QualType ToNamedType = Importer.Import(T->getNamedType());
- if (ToNamedType.isNull())
- return {};
+ ExpectedType ToNamedTypeOrErr = import(T->getNamedType());
+ if (!ToNamedTypeOrErr)
+ return ToNamedTypeOrErr.takeError();
- TagDecl *OwnedTagDecl =
- cast_or_null<TagDecl>(Importer.Import(T->getOwnedTagDecl()));
- if (!OwnedTagDecl && T->getOwnedTagDecl())
- return {};
+ Expected<TagDecl *> ToOwnedTagDeclOrErr = import(T->getOwnedTagDecl());
+ if (!ToOwnedTagDeclOrErr)
+ return ToOwnedTagDeclOrErr.takeError();
return Importer.getToContext().getElaboratedType(T->getKeyword(),
- ToQualifier, ToNamedType,
- OwnedTagDecl);
+ *ToQualifierOrErr,
+ *ToNamedTypeOrErr,
+ *ToOwnedTagDeclOrErr);
}
-QualType ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
- QualType Pattern = Importer.Import(T->getPattern());
- if (Pattern.isNull())
- return {};
+ExpectedType
+ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
+ ExpectedType ToPatternOrErr = import(T->getPattern());
+ if (!ToPatternOrErr)
+ return ToPatternOrErr.takeError();
- return Importer.getToContext().getPackExpansionType(Pattern,
+ return Importer.getToContext().getPackExpansionType(*ToPatternOrErr,
T->getNumExpansions());
}
-QualType ASTNodeImporter::VisitDependentTemplateSpecializationType(
+ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T) {
- NestedNameSpecifier *Qualifier = Importer.Import(T->getQualifier());
- if (!Qualifier && T->getQualifier())
- return {};
+ auto ToQualifierOrErr = import(T->getQualifier());
+ if (!ToQualifierOrErr)
+ return ToQualifierOrErr.takeError();
- IdentifierInfo *Name = Importer.Import(T->getIdentifier());
- if (!Name && T->getIdentifier())
- return {};
+ IdentifierInfo *ToName = Importer.Import(T->getIdentifier());
SmallVector<TemplateArgument, 2> ToPack;
ToPack.reserve(T->getNumArgs());
- if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToPack))
- return {};
+ if (Error Err = ImportTemplateArguments(
+ T->getArgs(), T->getNumArgs(), ToPack))
+ return std::move(Err);
return Importer.getToContext().getDependentTemplateSpecializationType(
- T->getKeyword(), Qualifier, Name, ToPack);
+ T->getKeyword(), *ToQualifierOrErr, ToName, ToPack);
}
-QualType ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
- NestedNameSpecifier *NNS = Importer.Import(T->getQualifier());
- if (!NNS && T->getQualifier())
- return QualType();
+ExpectedType
+ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
+ auto ToQualifierOrErr = import(T->getQualifier());
+ if (!ToQualifierOrErr)
+ return ToQualifierOrErr.takeError();
IdentifierInfo *Name = Importer.Import(T->getIdentifier());
- if (!Name && T->getIdentifier())
- return QualType();
- QualType Canon = (T == T->getCanonicalTypeInternal().getTypePtr())
- ? QualType()
- : Importer.Import(T->getCanonicalTypeInternal());
- if (!Canon.isNull())
- Canon = Canon.getCanonicalType();
+ QualType Canon;
+ if (T != T->getCanonicalTypeInternal().getTypePtr()) {
+ if (ExpectedType TyOrErr = import(T->getCanonicalTypeInternal()))
+ Canon = (*TyOrErr).getCanonicalType();
+ else
+ return TyOrErr.takeError();
+ }
- return Importer.getToContext().getDependentNameType(T->getKeyword(), NNS,
+ return Importer.getToContext().getDependentNameType(T->getKeyword(),
+ *ToQualifierOrErr,
Name, Canon);
}
-QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
- auto *Class =
- dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl()));
- if (!Class)
- return {};
+ExpectedType
+ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+ Expected<ObjCInterfaceDecl *> ToDeclOrErr = import(T->getDecl());
+ if (!ToDeclOrErr)
+ return ToDeclOrErr.takeError();
- return Importer.getToContext().getObjCInterfaceType(Class);
+ return Importer.getToContext().getObjCInterfaceType(*ToDeclOrErr);
}
-QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
- QualType ToBaseType = Importer.Import(T->getBaseType());
- if (ToBaseType.isNull())
- return {};
+ExpectedType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
+ ExpectedType ToBaseTypeOrErr = import(T->getBaseType());
+ if (!ToBaseTypeOrErr)
+ return ToBaseTypeOrErr.takeError();
SmallVector<QualType, 4> TypeArgs;
for (auto TypeArg : T->getTypeArgsAsWritten()) {
- QualType ImportedTypeArg = Importer.Import(TypeArg);
- if (ImportedTypeArg.isNull())
- return {};
-
- TypeArgs.push_back(ImportedTypeArg);
+ if (ExpectedType TyOrErr = import(TypeArg))
+ TypeArgs.push_back(*TyOrErr);
+ else
+ return TyOrErr.takeError();
}
SmallVector<ObjCProtocolDecl *, 4> Protocols;
for (auto *P : T->quals()) {
- auto *Protocol = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P));
- if (!Protocol)
- return {};
- Protocols.push_back(Protocol);
+ if (Expected<ObjCProtocolDecl *> ProtocolOrErr = import(P))
+ Protocols.push_back(*ProtocolOrErr);
+ else
+ return ProtocolOrErr.takeError();
+
}
- return Importer.getToContext().getObjCObjectType(ToBaseType, TypeArgs,
+ return Importer.getToContext().getObjCObjectType(*ToBaseTypeOrErr, TypeArgs,
Protocols,
T->isKindOfTypeAsWritten());
}
-QualType
+ExpectedType
ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
- QualType ToPointeeType = Importer.Import(T->getPointeeType());
- if (ToPointeeType.isNull())
- return {};
+ ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
+ if (!ToPointeeTypeOrErr)
+ return ToPointeeTypeOrErr.takeError();
- return Importer.getToContext().getObjCObjectPointerType(ToPointeeType);
+ return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
}
//----------------------------------------------------------------------------
// Import Declarations
//----------------------------------------------------------------------------
-bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
- DeclContext *&LexicalDC,
- DeclarationName &Name,
- NamedDecl *&ToD,
- SourceLocation &Loc) {
+Error ASTNodeImporter::ImportDeclParts(
+ NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC,
+ DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) {
// Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop.
// example: int struct_in_proto(struct data_t{int a;int b;} *d);
DeclContext *OrigDC = D->getDeclContext();
FunctionDecl *FunDecl;
if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) &&
FunDecl->hasBody()) {
- SourceRange RecR = D->getSourceRange();
- SourceRange BodyR = FunDecl->getBody()->getSourceRange();
- // If RecordDecl is not in Body (it is a param), we bail out.
- if (RecR.isValid() && BodyR.isValid() &&
- (RecR.getBegin() < BodyR.getBegin() ||
- BodyR.getEnd() < RecR.getEnd())) {
- Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
- << D->getDeclKindName();
- return true;
+ auto getLeafPointeeType = [](const Type *T) {
+ while (T->isPointerType() || T->isArrayType()) {
+ T = T->getPointeeOrArrayElementType();
+ }
+ return T;
+ };
+ for (const ParmVarDecl *P : FunDecl->parameters()) {
+ const Type *LeafT =
+ getLeafPointeeType(P->getType().getCanonicalType().getTypePtr());
+ auto *RT = dyn_cast<RecordType>(LeafT);
+ if (RT && RT->getDecl() == D) {
+ Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
+ << D->getDeclKindName();
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
+ }
}
}
// Import the context of this declaration.
- DC = Importer.ImportContext(OrigDC);
- if (!DC)
- return true;
-
- LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return true;
- }
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return Err;
// Import the name of this declaration.
- Name = Importer.Import(D->getDeclName());
- if (D->getDeclName() && !Name)
- return true;
+ if (Error Err = importInto(Name, D->getDeclName()))
+ return Err;
// Import the location of this declaration.
- Loc = Importer.Import(D->getLocation());
+ if (Error Err = importInto(Loc, D->getLocation()))
+ return Err;
+
ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
- return false;
+ if (ToD)
+ if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
+ return Err;
+
+ return Error::success();
}
-void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) {
+Error ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) {
if (!FromD)
- return;
+ return Error::success();
- if (!ToD) {
- ToD = Importer.Import(FromD);
- if (!ToD)
- return;
- }
-
- if (auto *FromRecord = dyn_cast<RecordDecl>(FromD)) {
- if (auto *ToRecord = cast_or_null<RecordDecl>(ToD)) {
- if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && !ToRecord->getDefinition()) {
- ImportDefinition(FromRecord, ToRecord);
+ if (!ToD)
+ if (Error Err = importInto(ToD, FromD))
+ return Err;
+
+ if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) {
+ if (RecordDecl *ToRecord = cast<RecordDecl>(ToD)) {
+ if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() &&
+ !ToRecord->getDefinition()) {
+ if (Error Err = ImportDefinition(FromRecord, ToRecord))
+ return Err;
}
}
- return;
+ return Error::success();
}
- if (auto *FromEnum = dyn_cast<EnumDecl>(FromD)) {
- if (auto *ToEnum = cast_or_null<EnumDecl>(ToD)) {
+ if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) {
+ if (EnumDecl *ToEnum = cast<EnumDecl>(ToD)) {
if (FromEnum->getDefinition() && !ToEnum->getDefinition()) {
- ImportDefinition(FromEnum, ToEnum);
+ if (Error Err = ImportDefinition(FromEnum, ToEnum))
+ return Err;
}
}
- return;
+ return Error::success();
}
+
+ return Error::success();
}
-void
-ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
- DeclarationNameInfo& To) {
+Error
+ASTNodeImporter::ImportDeclarationNameLoc(
+ const DeclarationNameInfo &From, DeclarationNameInfo& To) {
// NOTE: To.Name and To.Loc are already imported.
// We only have to import To.LocInfo.
switch (To.getName().getNameKind()) {
@@ -1223,76 +1614,121 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXUsingDirective:
case DeclarationName::CXXDeductionGuideName:
- return;
+ return Error::success();
case DeclarationName::CXXOperatorName: {
- SourceRange Range = From.getCXXOperatorNameRange();
- To.setCXXOperatorNameRange(Importer.Import(Range));
- return;
+ if (auto ToRangeOrErr = import(From.getCXXOperatorNameRange()))
+ To.setCXXOperatorNameRange(*ToRangeOrErr);
+ else
+ return ToRangeOrErr.takeError();
+ return Error::success();
}
case DeclarationName::CXXLiteralOperatorName: {
- SourceLocation Loc = From.getCXXLiteralOperatorNameLoc();
- To.setCXXLiteralOperatorNameLoc(Importer.Import(Loc));
- return;
+ if (ExpectedSLoc LocOrErr = import(From.getCXXLiteralOperatorNameLoc()))
+ To.setCXXLiteralOperatorNameLoc(*LocOrErr);
+ else
+ return LocOrErr.takeError();
+ return Error::success();
}
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName: {
- TypeSourceInfo *FromTInfo = From.getNamedTypeInfo();
- To.setNamedTypeInfo(Importer.Import(FromTInfo));
- return;
+ if (auto ToTInfoOrErr = import(From.getNamedTypeInfo()))
+ To.setNamedTypeInfo(*ToTInfoOrErr);
+ else
+ return ToTInfoOrErr.takeError();
+ return Error::success();
}
}
llvm_unreachable("Unknown name kind.");
}
-void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
+Error
+ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
if (Importer.isMinimalImport() && !ForceImport) {
- Importer.ImportContext(FromDC);
- return;
+ auto ToDCOrErr = Importer.ImportContext(FromDC);
+ return ToDCOrErr.takeError();
+ }
+ llvm::SmallVector<Decl *, 8> ImportedDecls;
+ for (auto *From : FromDC->decls()) {
+ ExpectedDecl ImportedOrErr = import(From);
+ if (!ImportedOrErr)
+ // Ignore the error, continue with next Decl.
+ // FIXME: Handle this case somehow better.
+ consumeError(ImportedOrErr.takeError());
}
- for (auto *From : FromDC->decls())
- Importer.Import(From);
+ return Error::success();
+}
+
+Error ASTNodeImporter::ImportDeclContext(
+ Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) {
+ auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext());
+ if (!ToDCOrErr)
+ return ToDCOrErr.takeError();
+ ToDC = *ToDCOrErr;
+
+ if (FromD->getDeclContext() != FromD->getLexicalDeclContext()) {
+ auto ToLexicalDCOrErr = Importer.ImportContext(
+ FromD->getLexicalDeclContext());
+ if (!ToLexicalDCOrErr)
+ return ToLexicalDCOrErr.takeError();
+ ToLexicalDC = *ToLexicalDCOrErr;
+ } else
+ ToLexicalDC = ToDC;
+
+ return Error::success();
}
-void ASTNodeImporter::ImportImplicitMethods(
+Error ASTNodeImporter::ImportImplicitMethods(
const CXXRecordDecl *From, CXXRecordDecl *To) {
assert(From->isCompleteDefinition() && To->getDefinition() == To &&
"Import implicit methods to or from non-definition");
for (CXXMethodDecl *FromM : From->methods())
- if (FromM->isImplicit())
- Importer.Import(FromM);
+ if (FromM->isImplicit()) {
+ Expected<CXXMethodDecl *> ToMOrErr = import(FromM);
+ if (!ToMOrErr)
+ return ToMOrErr.takeError();
+ }
+
+ return Error::success();
}
-static void setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To,
- ASTImporter &Importer) {
+static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To,
+ ASTImporter &Importer) {
if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) {
- auto *ToTypedef =
- cast_or_null<TypedefNameDecl>(Importer.Import(FromTypedef));
- assert (ToTypedef && "Failed to import typedef of an anonymous structure");
-
- To->setTypedefNameForAnonDecl(ToTypedef);
+ Decl *ToTypedef = Importer.Import(FromTypedef);
+ if (!ToTypedef)
+ return make_error<ImportError>();
+ To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(ToTypedef));
+ // FIXME: This should be the final code.
+ //if (Expected<Decl *> ToTypedefOrErr = Importer.Import(FromTypedef))
+ // To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(*ToTypedefOrErr));
+ //else
+ // return ToTypedefOrErr.takeError();
}
+ return Error::success();
}
-bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
- ImportDefinitionKind Kind) {
+Error ASTNodeImporter::ImportDefinition(
+ RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) {
if (To->getDefinition() || To->isBeingDefined()) {
if (Kind == IDK_Everything)
- ImportDeclContext(From, /*ForceImport=*/true);
+ return ImportDeclContext(From, /*ForceImport=*/true);
- return false;
+ return Error::success();
}
To->startDefinition();
- setTypedefNameForAnonDecl(From, To, Importer);
+ if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
+ return Err;
// Add base classes.
- if (auto *ToCXX = dyn_cast<CXXRecordDecl>(To)) {
- auto *FromCXX = cast<CXXRecordDecl>(From);
+ auto *ToCXX = dyn_cast<CXXRecordDecl>(To);
+ auto *FromCXX = dyn_cast<CXXRecordDecl>(From);
+ if (ToCXX && FromCXX && ToCXX->dataPtr() && FromCXX->dataPtr()) {
struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data();
struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data();
@@ -1364,228 +1800,172 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
SmallVector<CXXBaseSpecifier *, 4> Bases;
for (const auto &Base1 : FromCXX->bases()) {
- QualType T = Importer.Import(Base1.getType());
- if (T.isNull())
- return true;
+ ExpectedType TyOrErr = import(Base1.getType());
+ if (!TyOrErr)
+ return TyOrErr.takeError();
SourceLocation EllipsisLoc;
- if (Base1.isPackExpansion())
- EllipsisLoc = Importer.Import(Base1.getEllipsisLoc());
+ if (Base1.isPackExpansion()) {
+ if (ExpectedSLoc LocOrErr = import(Base1.getEllipsisLoc()))
+ EllipsisLoc = *LocOrErr;
+ else
+ return LocOrErr.takeError();
+ }
// Ensure that we have a definition for the base.
- ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl());
+ if (Error Err =
+ ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl()))
+ return Err;
+
+ auto RangeOrErr = import(Base1.getSourceRange());
+ if (!RangeOrErr)
+ return RangeOrErr.takeError();
+
+ auto TSIOrErr = import(Base1.getTypeSourceInfo());
+ if (!TSIOrErr)
+ return TSIOrErr.takeError();
Bases.push_back(
- new (Importer.getToContext())
- CXXBaseSpecifier(Importer.Import(Base1.getSourceRange()),
- Base1.isVirtual(),
- Base1.isBaseOfClass(),
- Base1.getAccessSpecifierAsWritten(),
- Importer.Import(Base1.getTypeSourceInfo()),
- EllipsisLoc));
+ new (Importer.getToContext()) CXXBaseSpecifier(
+ *RangeOrErr,
+ Base1.isVirtual(),
+ Base1.isBaseOfClass(),
+ Base1.getAccessSpecifierAsWritten(),
+ *TSIOrErr,
+ EllipsisLoc));
}
if (!Bases.empty())
ToCXX->setBases(Bases.data(), Bases.size());
}
if (shouldForceImportDeclContext(Kind))
- ImportDeclContext(From, /*ForceImport=*/true);
+ if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
+ return Err;
To->completeDefinition();
- return false;
+ return Error::success();
}
-bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To,
- ImportDefinitionKind Kind) {
+Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) {
if (To->getAnyInitializer())
- return false;
+ return Error::success();
- // FIXME: Can we really import any initializer? Alternatively, we could force
- // ourselves to import every declaration of a variable and then only use
- // getInit() here.
- To->setInit(Importer.Import(const_cast<Expr *>(From->getAnyInitializer())));
+ Expr *FromInit = From->getInit();
+ if (!FromInit)
+ return Error::success();
- // FIXME: Other bits to merge?
+ ExpectedExpr ToInitOrErr = import(FromInit);
+ if (!ToInitOrErr)
+ return ToInitOrErr.takeError();
+
+ To->setInit(*ToInitOrErr);
+ if (From->isInitKnownICE()) {
+ EvaluatedStmt *Eval = To->ensureEvaluatedStmt();
+ Eval->CheckedICE = true;
+ Eval->IsICE = From->isInitICE();
+ }
- return false;
+ // FIXME: Other bits to merge?
+ return Error::success();
}
-bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
- ImportDefinitionKind Kind) {
+Error ASTNodeImporter::ImportDefinition(
+ EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) {
if (To->getDefinition() || To->isBeingDefined()) {
if (Kind == IDK_Everything)
- ImportDeclContext(From, /*ForceImport=*/true);
- return false;
+ return ImportDeclContext(From, /*ForceImport=*/true);
+ return Error::success();
}
To->startDefinition();
- setTypedefNameForAnonDecl(From, To, Importer);
+ if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
+ return Err;
- QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(From));
- if (T.isNull())
- return true;
+ ExpectedType ToTypeOrErr =
+ import(Importer.getFromContext().getTypeDeclType(From));
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- QualType ToPromotionType = Importer.Import(From->getPromotionType());
- if (ToPromotionType.isNull())
- return true;
+ ExpectedType ToPromotionTypeOrErr = import(From->getPromotionType());
+ if (!ToPromotionTypeOrErr)
+ return ToPromotionTypeOrErr.takeError();
if (shouldForceImportDeclContext(Kind))
- ImportDeclContext(From, /*ForceImport=*/true);
+ if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
+ return Err;
// FIXME: we might need to merge the number of positive or negative bits
// if the enumerator lists don't match.
- To->completeDefinition(T, ToPromotionType,
+ To->completeDefinition(*ToTypeOrErr, *ToPromotionTypeOrErr,
From->getNumPositiveBits(),
From->getNumNegativeBits());
- return false;
+ return Error::success();
}
-TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
- TemplateParameterList *Params) {
+// FIXME: Remove this, use `import` instead.
+Expected<TemplateParameterList *> ASTNodeImporter::ImportTemplateParameterList(
+ TemplateParameterList *Params) {
SmallVector<NamedDecl *, 4> ToParams(Params->size());
- if (ImportContainerChecked(*Params, ToParams))
- return nullptr;
+ if (Error Err = ImportContainerChecked(*Params, ToParams))
+ return std::move(Err);
Expr *ToRequiresClause;
if (Expr *const R = Params->getRequiresClause()) {
- ToRequiresClause = Importer.Import(R);
- if (!ToRequiresClause)
- return nullptr;
+ if (Error Err = importInto(ToRequiresClause, R))
+ return std::move(Err);
} else {
ToRequiresClause = nullptr;
}
- return TemplateParameterList::Create(Importer.getToContext(),
- Importer.Import(Params->getTemplateLoc()),
- Importer.Import(Params->getLAngleLoc()),
- ToParams,
- Importer.Import(Params->getRAngleLoc()),
- ToRequiresClause);
-}
-
-TemplateArgument
-ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
- switch (From.getKind()) {
- case TemplateArgument::Null:
- return TemplateArgument();
-
- case TemplateArgument::Type: {
- QualType ToType = Importer.Import(From.getAsType());
- if (ToType.isNull())
- return {};
- return TemplateArgument(ToType);
- }
-
- case TemplateArgument::Integral: {
- QualType ToType = Importer.Import(From.getIntegralType());
- if (ToType.isNull())
- return {};
- return TemplateArgument(From, ToType);
- }
-
- case TemplateArgument::Declaration: {
- auto *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl()));
- QualType ToType = Importer.Import(From.getParamTypeForDecl());
- if (!To || ToType.isNull())
- return {};
- return TemplateArgument(To, ToType);
- }
-
- case TemplateArgument::NullPtr: {
- QualType ToType = Importer.Import(From.getNullPtrType());
- if (ToType.isNull())
- return {};
- return TemplateArgument(ToType, /*isNullPtr*/true);
- }
-
- case TemplateArgument::Template: {
- TemplateName ToTemplate = Importer.Import(From.getAsTemplate());
- if (ToTemplate.isNull())
- return {};
-
- return TemplateArgument(ToTemplate);
- }
-
- case TemplateArgument::TemplateExpansion: {
- TemplateName ToTemplate
- = Importer.Import(From.getAsTemplateOrTemplatePattern());
- if (ToTemplate.isNull())
- return {};
-
- return TemplateArgument(ToTemplate, From.getNumTemplateExpansions());
- }
-
- case TemplateArgument::Expression:
- if (Expr *ToExpr = Importer.Import(From.getAsExpr()))
- return TemplateArgument(ToExpr);
- return TemplateArgument();
-
- case TemplateArgument::Pack: {
- SmallVector<TemplateArgument, 2> ToPack;
- ToPack.reserve(From.pack_size());
- if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack))
- return {};
-
- return TemplateArgument(
- llvm::makeArrayRef(ToPack).copy(Importer.getToContext()));
- }
- }
-
- llvm_unreachable("Invalid template argument kind");
-}
-
-Optional<TemplateArgumentLoc>
-ASTNodeImporter::ImportTemplateArgumentLoc(const TemplateArgumentLoc &TALoc) {
- TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument());
- TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
- TemplateArgumentLocInfo ToInfo;
- if (Arg.getKind() == TemplateArgument::Expression) {
- Expr *E = Importer.Import(FromInfo.getAsExpr());
- ToInfo = TemplateArgumentLocInfo(E);
- if (!E)
- return None;
- } else if (Arg.getKind() == TemplateArgument::Type) {
- if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo()))
- ToInfo = TemplateArgumentLocInfo(TSI);
+ auto ToTemplateLocOrErr = import(Params->getTemplateLoc());
+ if (!ToTemplateLocOrErr)
+ return ToTemplateLocOrErr.takeError();
+ auto ToLAngleLocOrErr = import(Params->getLAngleLoc());
+ if (!ToLAngleLocOrErr)
+ return ToLAngleLocOrErr.takeError();
+ auto ToRAngleLocOrErr = import(Params->getRAngleLoc());
+ if (!ToRAngleLocOrErr)
+ return ToRAngleLocOrErr.takeError();
+
+ return TemplateParameterList::Create(
+ Importer.getToContext(),
+ *ToTemplateLocOrErr,
+ *ToLAngleLocOrErr,
+ ToParams,
+ *ToRAngleLocOrErr,
+ ToRequiresClause);
+}
+
+Error ASTNodeImporter::ImportTemplateArguments(
+ const TemplateArgument *FromArgs, unsigned NumFromArgs,
+ SmallVectorImpl<TemplateArgument> &ToArgs) {
+ for (unsigned I = 0; I != NumFromArgs; ++I) {
+ if (auto ToOrErr = import(FromArgs[I]))
+ ToArgs.push_back(*ToOrErr);
else
- return None;
- } else {
- ToInfo = TemplateArgumentLocInfo(
- Importer.Import(FromInfo.getTemplateQualifierLoc()),
- Importer.Import(FromInfo.getTemplateNameLoc()),
- Importer.Import(FromInfo.getTemplateEllipsisLoc()));
+ return ToOrErr.takeError();
}
- return TemplateArgumentLoc(Arg, ToInfo);
-}
-
-bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
- unsigned NumFromArgs,
- SmallVectorImpl<TemplateArgument> &ToArgs) {
- for (unsigned I = 0; I != NumFromArgs; ++I) {
- TemplateArgument To = ImportTemplateArgument(FromArgs[I]);
- if (To.isNull() && !FromArgs[I].isNull())
- return true;
- ToArgs.push_back(To);
- }
+ return Error::success();
+}
- return false;
+// FIXME: Do not forget to remove this and use only 'import'.
+Expected<TemplateArgument>
+ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
+ return import(From);
}
-// We cannot use Optional<> pattern here and below because
-// TemplateArgumentListInfo's operator new is declared as deleted so it cannot
-// be stored in Optional.
template <typename InContainerTy>
-bool ASTNodeImporter::ImportTemplateArgumentListInfo(
+Error ASTNodeImporter::ImportTemplateArgumentListInfo(
const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
for (const auto &FromLoc : Container) {
- if (auto ToLoc = ImportTemplateArgumentLoc(FromLoc))
- ToTAInfo.addArgument(*ToLoc);
+ if (auto ToLocOrErr = import(FromLoc))
+ ToTAInfo.addArgument(*ToLocOrErr);
else
- return true;
+ return ToLocOrErr.takeError();
}
- return false;
+ return Error::success();
}
static StructuralEquivalenceKind
@@ -1682,30 +2062,31 @@ bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From,
return Ctx.IsEquivalent(From, To);
}
-Decl *ASTNodeImporter::VisitDecl(Decl *D) {
+ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) {
Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
<< D->getDeclKindName();
- return nullptr;
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
-Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
- // Import the context of this declaration.
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- if (!DC)
- return nullptr;
+ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) {
+ Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
+ << D->getDeclKindName();
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
+}
- DeclContext *LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return nullptr;
- }
+ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
+ // Import the context of this declaration.
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
// Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
+ ExpectedSLoc LocOrErr = import(D->getLocation());
+ if (!LocOrErr)
+ return LocOrErr.takeError();
EmptyDecl *ToD;
- if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc))
+ if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *LocOrErr))
return ToD;
ToD->setLexicalDeclContext(LexicalDC);
@@ -1713,7 +2094,7 @@ Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
return ToD;
}
-Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
TranslationUnitDecl *ToD =
Importer.getToContext().getTranslationUnitDecl();
@@ -1722,18 +2103,23 @@ Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
return ToD;
}
-Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
- SourceLocation Loc = Importer.Import(D->getLocation());
- SourceLocation ColonLoc = Importer.Import(D->getColonLoc());
+ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
+ ExpectedSLoc LocOrErr = import(D->getLocation());
+ if (!LocOrErr)
+ return LocOrErr.takeError();
+ auto ColonLocOrErr = import(D->getColonLoc());
+ if (!ColonLocOrErr)
+ return ColonLocOrErr.takeError();
// Import the context of this declaration.
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- if (!DC)
- return nullptr;
+ auto DCOrErr = Importer.ImportContext(D->getDeclContext());
+ if (!DCOrErr)
+ return DCOrErr.takeError();
+ DeclContext *DC = *DCOrErr;
AccessSpecDecl *ToD;
if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(),
- DC, Loc, ColonLoc))
+ DC, *LocOrErr, *ColonLocOrErr))
return ToD;
// Lexical DeclContext and Semantic DeclContext
@@ -1744,29 +2130,26 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
return ToD;
}
-Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- if (!DC)
- return nullptr;
-
+ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ auto DCOrErr = Importer.ImportContext(D->getDeclContext());
+ if (!DCOrErr)
+ return DCOrErr.takeError();
+ DeclContext *DC = *DCOrErr;
DeclContext *LexicalDC = DC;
- // Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
-
- Expr *AssertExpr = Importer.Import(D->getAssertExpr());
- if (!AssertExpr)
- return nullptr;
-
- StringLiteral *FromMsg = D->getMessage();
- auto *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg));
- if (!ToMsg && FromMsg)
- return nullptr;
+ SourceLocation ToLocation, ToRParenLoc;
+ Expr *ToAssertExpr;
+ StringLiteral *ToMessage;
+ if (auto Imp = importSeq(
+ D->getLocation(), D->getAssertExpr(), D->getMessage(), D->getRParenLoc()))
+ std::tie(ToLocation, ToAssertExpr, ToMessage, ToRParenLoc) = *Imp;
+ else
+ return Imp.takeError();
StaticAssertDecl *ToD;
if (GetImportedOrCreateDecl(
- ToD, D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
- Importer.Import(D->getRParenLoc()), D->isFailed()))
+ ToD, D, Importer.getToContext(), DC, ToLocation, ToAssertExpr, ToMessage,
+ ToRParenLoc, D->isFailed()))
return ToD;
ToD->setLexicalDeclContext(LexicalDC);
@@ -1774,14 +2157,14 @@ Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
return ToD;
}
-Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
@@ -1796,8 +2179,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace();
} else {
SmallVector<NamedDecl *, 4> ConflictingDecls;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace))
continue;
@@ -1815,15 +2197,21 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Namespace,
ConflictingDecls.data(),
ConflictingDecls.size());
+ if (!Name)
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
+ ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
+ if (!BeginLocOrErr)
+ return BeginLocOrErr.takeError();
+
// Create the "to" namespace, if needed.
NamespaceDecl *ToNamespace = MergeWithNamespace;
if (!ToNamespace) {
if (GetImportedOrCreateDecl(
ToNamespace, D, Importer.getToContext(), DC, D->isInline(),
- Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(),
+ *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(),
/*PrevDecl=*/nullptr))
return ToNamespace;
ToNamespace->setLexicalDeclContext(LexicalDC);
@@ -1840,43 +2228,42 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
}
Importer.MapImported(D, ToNamespace);
- ImportDeclContext(D);
+ if (Error Err = ImportDeclContext(D))
+ return std::move(Err);
return ToNamespace;
}
-Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *LookupD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc))
+ return std::move(Err);
if (LookupD)
return LookupD;
// NOTE: No conflict resolution is done for namespace aliases now.
- auto *TargetDecl = cast_or_null<NamespaceDecl>(
- Importer.Import(D->getNamespace()));
- if (!TargetDecl)
- return nullptr;
-
- IdentifierInfo *ToII = Importer.Import(D->getIdentifier());
- if (!ToII)
- return nullptr;
-
- NestedNameSpecifierLoc ToQLoc = Importer.Import(D->getQualifierLoc());
- if (D->getQualifierLoc() && !ToQLoc)
- return nullptr;
+ SourceLocation ToNamespaceLoc, ToAliasLoc, ToTargetNameLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ NamespaceDecl *ToNamespace;
+ if (auto Imp = importSeq(
+ D->getNamespaceLoc(), D->getAliasLoc(), D->getQualifierLoc(),
+ D->getTargetNameLoc(), D->getNamespace()))
+ std::tie(
+ ToNamespaceLoc, ToAliasLoc, ToQualifierLoc, ToTargetNameLoc,
+ ToNamespace) = *Imp;
+ else
+ return Imp.takeError();
+ IdentifierInfo *ToIdentifier = Importer.Import(D->getIdentifier());
NamespaceAliasDecl *ToD;
- if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC,
- Importer.Import(D->getNamespaceLoc()),
- Importer.Import(D->getAliasLoc()), ToII, ToQLoc,
- Importer.Import(D->getTargetNameLoc()),
- TargetDecl))
+ if (GetImportedOrCreateDecl(
+ ToD, D, Importer.getToContext(), DC, ToNamespaceLoc, ToAliasLoc,
+ ToIdentifier, ToQualifierLoc, ToTargetNameLoc, ToNamespace))
return ToD;
ToD->setLexicalDeclContext(LexicalDC);
@@ -1885,14 +2272,15 @@ Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
return ToD;
}
-Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
+ExpectedDecl
+ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
// Import the major distinguishing characteristics of this typedef.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
@@ -1902,15 +2290,21 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
- if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(),
- FoundTypedef->getUnderlyingType()))
- return Importer.MapImported(D, FoundTypedef);
+ QualType FromUT = D->getUnderlyingType();
+ QualType FoundUT = FoundTypedef->getUnderlyingType();
+ if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) {
+ // If the "From" context has a complete underlying type but we
+ // already have a complete underlying type then return with that.
+ if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType())
+ return Importer.MapImported(D, FoundTypedef);
+ }
+ // FIXME Handle redecl chain.
+ break;
}
ConflictingDecls.push_back(FoundDecl);
@@ -1921,28 +2315,30 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return nullptr;
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
- // Import the underlying type of this typedef;
- QualType T = Importer.Import(D->getUnderlyingType());
- if (T.isNull())
- return nullptr;
+ QualType ToUnderlyingType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ SourceLocation ToBeginLoc;
+ if (auto Imp = importSeq(
+ D->getUnderlyingType(), D->getTypeSourceInfo(), D->getBeginLoc()))
+ std::tie(ToUnderlyingType, ToTypeSourceInfo, ToBeginLoc) = *Imp;
+ else
+ return Imp.takeError();
// Create the new typedef node.
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- SourceLocation StartL = Importer.Import(D->getLocStart());
-
+ // FIXME: ToUnderlyingType is not used.
TypedefNameDecl *ToTypedef;
if (IsAlias) {
if (GetImportedOrCreateDecl<TypeAliasDecl>(
- ToTypedef, D, Importer.getToContext(), DC, StartL, Loc,
- Name.getAsIdentifierInfo(), TInfo))
+ ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc,
+ Name.getAsIdentifierInfo(), ToTypeSourceInfo))
return ToTypedef;
} else if (GetImportedOrCreateDecl<TypedefDecl>(
- ToTypedef, D, Importer.getToContext(), DC, StartL, Loc,
- Name.getAsIdentifierInfo(), TInfo))
+ ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc,
+ Name.getAsIdentifierInfo(), ToTypeSourceInfo))
return ToTypedef;
ToTypedef->setAccess(D->getAccess());
@@ -1956,22 +2352,23 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
return ToTypedef;
}
-Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) {
return VisitTypedefNameDecl(D, /*IsAlias=*/false);
}
-Decl *ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) {
return VisitTypedefNameDecl(D, /*IsAlias=*/true);
}
-Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
+ExpectedDecl
+ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
// Import the major distinguishing characteristics of this typedef.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *FoundD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc))
+ return std::move(Err);
if (FoundD)
return FoundD;
@@ -1981,8 +2378,7 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
@@ -1996,26 +2392,23 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return nullptr;
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
- TemplateParameterList *Params = ImportTemplateParameterList(
- D->getTemplateParameters());
- if (!Params)
- return nullptr;
-
- auto *TemplDecl = cast_or_null<TypeAliasDecl>(
- Importer.Import(D->getTemplatedDecl()));
- if (!TemplDecl)
- return nullptr;
+ TemplateParameterList *ToTemplateParameters;
+ TypeAliasDecl *ToTemplatedDecl;
+ if (auto Imp = importSeq(D->getTemplateParameters(), D->getTemplatedDecl()))
+ std::tie(ToTemplateParameters, ToTemplatedDecl) = *Imp;
+ else
+ return Imp.takeError();
TypeAliasTemplateDecl *ToAlias;
if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc,
- Name, Params, TemplDecl))
+ Name, ToTemplateParameters, ToTemplatedDecl))
return ToAlias;
- TemplDecl->setDescribedAliasTemplate(ToAlias);
+ ToTemplatedDecl->setDescribedAliasTemplate(ToAlias);
ToAlias->setAccess(D->getAccess());
ToAlias->setLexicalDeclContext(LexicalDC);
@@ -2023,48 +2416,53 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
return ToAlias;
}
-Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
// Import the major distinguishing characteristics of this label.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
assert(LexicalDC->isFunctionOrMethod());
LabelDecl *ToLabel;
- if (D->isGnuLocal()
- ? GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC,
- Importer.Import(D->getLocation()),
- Name.getAsIdentifierInfo(),
- Importer.Import(D->getLocStart()))
- : GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC,
- Importer.Import(D->getLocation()),
- Name.getAsIdentifierInfo()))
- return ToLabel;
-
- auto *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt()));
- if (!Label)
- return nullptr;
+ if (D->isGnuLocal()) {
+ ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
+ if (!BeginLocOrErr)
+ return BeginLocOrErr.takeError();
+ if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo(), *BeginLocOrErr))
+ return ToLabel;
+
+ } else {
+ if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo()))
+ return ToLabel;
+
+ }
- ToLabel->setStmt(Label);
+ Expected<LabelStmt *> ToStmtOrErr = import(D->getStmt());
+ if (!ToStmtOrErr)
+ return ToStmtOrErr.takeError();
+
+ ToLabel->setStmt(*ToStmtOrErr);
ToLabel->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToLabel);
return ToLabel;
}
-Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
// Import the major distinguishing characteristics of this enum.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
@@ -2072,7 +2470,9 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
unsigned IDNS = Decl::IDNS_Tag;
DeclarationName SearchName = Name;
if (!SearchName && D->getTypedefNameForAnonDecl()) {
- SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName());
+ if (Error Err = importInto(
+ SearchName, D->getTypedefNameForAnonDecl()->getDeclName()))
+ return std::move(Err);
IDNS = Decl::IDNS_Ordinary;
} else if (Importer.getToContext().getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Ordinary;
@@ -2080,19 +2480,18 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
// We may already have an enum of the same name; try to find and match it.
if (!DC->isFunctionOrMethod() && SearchName) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls);
+ auto FoundDecls =
+ Importer.findDeclsInToCtx(DC, SearchName);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- Decl *Found = FoundDecl;
- if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
+ if (auto *Typedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
- Found = Tag->getDecl();
+ FoundDecl = Tag->getDecl();
}
- if (auto *FoundEnum = dyn_cast<EnumDecl>(Found)) {
+ if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) {
if (IsStructuralMatch(D, FoundEnum))
return Importer.MapImported(D, FoundEnum);
}
@@ -2104,53 +2503,69 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
ConflictingDecls.data(),
ConflictingDecls.size());
+ if (!Name)
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
+ SourceLocation ToBeginLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ QualType ToIntegerType;
+ if (auto Imp = importSeq(
+ D->getBeginLoc(), D->getQualifierLoc(), D->getIntegerType()))
+ std::tie(ToBeginLoc, ToQualifierLoc, ToIntegerType) = *Imp;
+ else
+ return Imp.takeError();
+
// Create the enum declaration.
EnumDecl *D2;
if (GetImportedOrCreateDecl(
- D2, D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()),
+ D2, D, Importer.getToContext(), DC, ToBeginLoc,
Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(),
D->isScopedUsingClassTag(), D->isFixed()))
return D2;
- // Import the qualifier, if any.
- D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ D2->setQualifierInfo(ToQualifierLoc);
+ D2->setIntegerType(ToIntegerType);
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(D2);
- // Import the integer type.
- QualType ToIntegerType = Importer.Import(D->getIntegerType());
- if (ToIntegerType.isNull())
- return nullptr;
- D2->setIntegerType(ToIntegerType);
-
// Import the definition
- if (D->isCompleteDefinition() && ImportDefinition(D, D2))
- return nullptr;
+ if (D->isCompleteDefinition())
+ if (Error Err = ImportDefinition(D, D2))
+ return std::move(Err);
return D2;
}
-Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
+ bool IsFriendTemplate = false;
+ if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
+ IsFriendTemplate =
+ DCXX->getDescribedClassTemplate() &&
+ DCXX->getDescribedClassTemplate()->getFriendObjectKind() !=
+ Decl::FOK_None;
+ }
+
// If this record has a definition in the translation unit we're coming from,
// but this particular declaration is not that definition, import the
// definition and map to that.
TagDecl *Definition = D->getDefinition();
if (Definition && Definition != D &&
+ // Friend template declaration must be imported on its own.
+ !IsFriendTemplate &&
// In contrast to a normal CXXRecordDecl, the implicit
// CXXRecordDecl of ClassTemplateSpecializationDecl is its redeclaration.
// The definition of the implicit CXXRecordDecl in this case is the
// ClassTemplateSpecializationDecl itself. Thus, we start with an extra
// condition in order to be able to import the implict Decl.
!D->isImplicit()) {
- Decl *ImportedDef = Importer.Import(Definition);
- if (!ImportedDef)
- return nullptr;
+ ExpectedDecl ImportedDefOrErr = import(Definition);
+ if (!ImportedDefOrErr)
+ return ImportedDefOrErr.takeError();
- return Importer.MapImported(D, ImportedDef);
+ return Importer.MapImported(D, *ImportedDefOrErr);
}
// Import the major distinguishing characteristics of this record.
@@ -2158,8 +2573,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
@@ -2167,19 +2582,19 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
unsigned IDNS = Decl::IDNS_Tag;
DeclarationName SearchName = Name;
if (!SearchName && D->getTypedefNameForAnonDecl()) {
- SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName());
+ if (Error Err = importInto(
+ SearchName, D->getTypedefNameForAnonDecl()->getDeclName()))
+ return std::move(Err);
IDNS = Decl::IDNS_Ordinary;
} else if (Importer.getToContext().getLangOpts().CPlusPlus)
- IDNS |= Decl::IDNS_Ordinary;
+ IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend;
// We may already have a record of the same name; try to find and match it.
- RecordDecl *AdoptDecl = nullptr;
RecordDecl *PrevDecl = nullptr;
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls);
-
+ auto FoundDecls =
+ Importer.findDeclsInToCtx(DC, SearchName);
if (!FoundDecls.empty()) {
// We're going to have to compare D against potentially conflicting Decls, so complete it.
if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition())
@@ -2196,30 +2611,23 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Found = Tag->getDecl();
}
- if (D->getDescribedTemplate()) {
- if (auto *Template = dyn_cast<ClassTemplateDecl>(Found))
- Found = Template->getTemplatedDecl();
- else
- continue;
- }
-
if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) {
- if (!SearchName) {
+ // Do not emit false positive diagnostic in case of unnamed
+ // struct/union and in case of anonymous structs. Would be false
+ // because there may be several anonymous/unnamed structs in a class.
+ // E.g. these are both valid:
+ // struct A { // unnamed structs
+ // struct { struct A *next; } entry0;
+ // struct { struct A *next; } entry1;
+ // };
+ // struct X { struct { int a; }; struct { int b; }; }; // anon structs
+ if (!SearchName)
if (!IsStructuralMatch(D, FoundRecord, false))
continue;
- }
- PrevDecl = FoundRecord;
-
- if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
- if ((SearchName && !D->isCompleteDefinition())
- || (D->isCompleteDefinition() &&
- D->isAnonymousStructOrUnion()
- == FoundDef->isAnonymousStructOrUnion() &&
- IsStructuralMatch(D, FoundDef))) {
- // The record types structurally match, or the "from" translation
- // unit only had a forward declaration anyway; call it the same
- // function.
+ if (IsStructuralMatch(D, FoundRecord)) {
+ RecordDecl *FoundDef = FoundRecord->getDefinition();
+ if (D->isThisDeclarationADefinition() && FoundDef) {
// FIXME: Structural equivalence check should check for same
// user-defined methods.
Importer.MapImported(D, FoundDef);
@@ -2227,178 +2635,178 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
auto *FoundCXX = dyn_cast<CXXRecordDecl>(FoundDef);
assert(FoundCXX && "Record type mismatch");
- if (D->isCompleteDefinition() && !Importer.isMinimalImport())
+ if (!Importer.isMinimalImport())
// FoundDef may not have every implicit method that D has
// because implicit methods are created only if they are used.
- ImportImplicitMethods(DCXX, FoundCXX);
+ if (Error Err = ImportImplicitMethods(DCXX, FoundCXX))
+ return std::move(Err);
}
- return FoundDef;
}
- } else if (!D->isCompleteDefinition()) {
- // We have a forward declaration of this type, so adopt that forward
- // declaration rather than building a new one.
-
- // If one or both can be completed from external storage then try one
- // last time to complete and compare them before doing this.
-
- if (FoundRecord->hasExternalLexicalStorage() &&
- !FoundRecord->isCompleteDefinition())
- FoundRecord->getASTContext().getExternalSource()->CompleteType(FoundRecord);
- if (D->hasExternalLexicalStorage())
- D->getASTContext().getExternalSource()->CompleteType(D);
-
- if (FoundRecord->isCompleteDefinition() &&
- D->isCompleteDefinition() &&
- !IsStructuralMatch(D, FoundRecord))
- continue;
-
- AdoptDecl = FoundRecord;
- continue;
- } else if (!SearchName) {
- continue;
+ PrevDecl = FoundRecord->getMostRecentDecl();
+ break;
}
}
ConflictingDecls.push_back(FoundDecl);
- }
+ } // for
if (!ConflictingDecls.empty() && SearchName) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
ConflictingDecls.data(),
ConflictingDecls.size());
+ if (!Name)
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
+ ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
+ if (!BeginLocOrErr)
+ return BeginLocOrErr.takeError();
+
// Create the record declaration.
- RecordDecl *D2 = AdoptDecl;
- SourceLocation StartLoc = Importer.Import(D->getLocStart());
- if (!D2) {
- CXXRecordDecl *D2CXX = nullptr;
- if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
- if (DCXX->isLambda()) {
- TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo());
- if (GetImportedOrCreateSpecialDecl(
- D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(),
- DC, TInfo, Loc, DCXX->isDependentLambda(),
- DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault()))
- return D2CXX;
- Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl());
- if (DCXX->getLambdaContextDecl() && !CDecl)
- return nullptr;
- D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), CDecl);
- } else if (DCXX->isInjectedClassName()) {
- // We have to be careful to do a similar dance to the one in
- // Sema::ActOnStartCXXMemberDeclarations
- CXXRecordDecl *const PrevDecl = nullptr;
- const bool DelayTypeCreation = true;
- if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(),
- D->getTagKind(), DC, StartLoc, Loc,
- Name.getAsIdentifierInfo(), PrevDecl,
- DelayTypeCreation))
- return D2CXX;
- Importer.getToContext().getTypeDeclType(
- D2CXX, dyn_cast<CXXRecordDecl>(DC));
- } else {
- if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(),
- D->getTagKind(), DC, StartLoc, Loc,
- Name.getAsIdentifierInfo(),
- cast_or_null<CXXRecordDecl>(PrevDecl)))
- return D2CXX;
- }
+ RecordDecl *D2 = nullptr;
+ CXXRecordDecl *D2CXX = nullptr;
+ if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
+ if (DCXX->isLambda()) {
+ auto TInfoOrErr = import(DCXX->getLambdaTypeInfo());
+ if (!TInfoOrErr)
+ return TInfoOrErr.takeError();
+ if (GetImportedOrCreateSpecialDecl(
+ D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(),
+ DC, *TInfoOrErr, Loc, DCXX->isDependentLambda(),
+ DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault()))
+ return D2CXX;
+ ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl());
+ if (!CDeclOrErr)
+ return CDeclOrErr.takeError();
+ D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr);
+ } else if (DCXX->isInjectedClassName()) {
+ // We have to be careful to do a similar dance to the one in
+ // Sema::ActOnStartCXXMemberDeclarations
+ const bool DelayTypeCreation = true;
+ if (GetImportedOrCreateDecl(
+ D2CXX, D, Importer.getToContext(), D->getTagKind(), DC,
+ *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(),
+ cast_or_null<CXXRecordDecl>(PrevDecl), DelayTypeCreation))
+ return D2CXX;
+ Importer.getToContext().getTypeDeclType(
+ D2CXX, dyn_cast<CXXRecordDecl>(DC));
+ } else {
+ if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(),
+ D->getTagKind(), DC, *BeginLocOrErr, Loc,
+ Name.getAsIdentifierInfo(),
+ cast_or_null<CXXRecordDecl>(PrevDecl)))
+ return D2CXX;
+ }
- D2 = D2CXX;
- D2->setAccess(D->getAccess());
- D2->setLexicalDeclContext(LexicalDC);
- if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit())
- LexicalDC->addDeclInternal(D2);
-
- if (ClassTemplateDecl *FromDescribed =
- DCXX->getDescribedClassTemplate()) {
- auto *ToDescribed = cast_or_null<ClassTemplateDecl>(
- Importer.Import(FromDescribed));
- if (!ToDescribed)
- return nullptr;
- D2CXX->setDescribedClassTemplate(ToDescribed);
- if (!DCXX->isInjectedClassName()) {
- // In a record describing a template the type should be an
- // InjectedClassNameType (see Sema::CheckClassTemplate). Update the
- // previously set type to the correct value here (ToDescribed is not
- // available at record create).
- // FIXME: The previous type is cleared but not removed from
- // ASTContext's internal storage.
- CXXRecordDecl *Injected = nullptr;
- for (NamedDecl *Found : D2CXX->noload_lookup(Name)) {
- auto *Record = dyn_cast<CXXRecordDecl>(Found);
- if (Record && Record->isInjectedClassName()) {
- Injected = Record;
- break;
- }
- }
- D2CXX->setTypeForDecl(nullptr);
- Importer.getToContext().getInjectedClassNameType(D2CXX,
- ToDescribed->getInjectedClassNameSpecialization());
- if (Injected) {
- Injected->setTypeForDecl(nullptr);
- Importer.getToContext().getTypeDeclType(Injected, D2CXX);
+ D2 = D2CXX;
+ D2->setAccess(D->getAccess());
+ D2->setLexicalDeclContext(LexicalDC);
+ if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit())
+ LexicalDC->addDeclInternal(D2);
+
+ if (LexicalDC != DC && D->isInIdentifierNamespace(Decl::IDNS_TagFriend))
+ DC->makeDeclVisibleInContext(D2);
+
+ if (ClassTemplateDecl *FromDescribed =
+ DCXX->getDescribedClassTemplate()) {
+ ClassTemplateDecl *ToDescribed;
+ if (Error Err = importInto(ToDescribed, FromDescribed))
+ return std::move(Err);
+ D2CXX->setDescribedClassTemplate(ToDescribed);
+ if (!DCXX->isInjectedClassName() && !IsFriendTemplate) {
+ // In a record describing a template the type should be an
+ // InjectedClassNameType (see Sema::CheckClassTemplate). Update the
+ // previously set type to the correct value here (ToDescribed is not
+ // available at record create).
+ // FIXME: The previous type is cleared but not removed from
+ // ASTContext's internal storage.
+ CXXRecordDecl *Injected = nullptr;
+ for (NamedDecl *Found : D2CXX->noload_lookup(Name)) {
+ auto *Record = dyn_cast<CXXRecordDecl>(Found);
+ if (Record && Record->isInjectedClassName()) {
+ Injected = Record;
+ break;
}
}
- } else if (MemberSpecializationInfo *MemberInfo =
+ // Create an injected type for the whole redecl chain.
+ SmallVector<Decl *, 2> Redecls =
+ getCanonicalForwardRedeclChain(D2CXX);
+ for (auto *R : Redecls) {
+ auto *RI = cast<CXXRecordDecl>(R);
+ RI->setTypeForDecl(nullptr);
+ // Below we create a new injected type and assign that to the
+ // canonical decl, subsequent declarations in the chain will reuse
+ // that type.
+ Importer.getToContext().getInjectedClassNameType(
+ RI, ToDescribed->getInjectedClassNameSpecialization());
+ }
+ // Set the new type for the previous injected decl too.
+ if (Injected) {
+ Injected->setTypeForDecl(nullptr);
+ Importer.getToContext().getTypeDeclType(Injected, D2CXX);
+ }
+ }
+ } else if (MemberSpecializationInfo *MemberInfo =
DCXX->getMemberSpecializationInfo()) {
TemplateSpecializationKind SK =
MemberInfo->getTemplateSpecializationKind();
CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass();
- auto *ToInst =
- cast_or_null<CXXRecordDecl>(Importer.Import(FromInst));
- if (FromInst && !ToInst)
- return nullptr;
- D2CXX->setInstantiationOfMemberClass(ToInst, SK);
- D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation(
- Importer.Import(MemberInfo->getPointOfInstantiation()));
- }
- } else {
- if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(),
- D->getTagKind(), DC, StartLoc, Loc,
- Name.getAsIdentifierInfo(), PrevDecl))
- return D2;
- D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
+
+ if (Expected<CXXRecordDecl *> ToInstOrErr = import(FromInst))
+ D2CXX->setInstantiationOfMemberClass(*ToInstOrErr, SK);
+ else
+ return ToInstOrErr.takeError();
+
+ if (ExpectedSLoc POIOrErr =
+ import(MemberInfo->getPointOfInstantiation()))
+ D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation(
+ *POIOrErr);
+ else
+ return POIOrErr.takeError();
}
- D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
- if (D->isAnonymousStructOrUnion())
- D2->setAnonymousStructOrUnion(true);
+ } else {
+ if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(),
+ D->getTagKind(), DC, *BeginLocOrErr, Loc,
+ Name.getAsIdentifierInfo(), PrevDecl))
+ return D2;
+ D2->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(D2);
}
- Importer.MapImported(D, D2);
+ if (auto QualifierLocOrErr = import(D->getQualifierLoc()))
+ D2->setQualifierInfo(*QualifierLocOrErr);
+ else
+ return QualifierLocOrErr.takeError();
- if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default))
- return nullptr;
+ if (D->isAnonymousStructOrUnion())
+ D2->setAnonymousStructOrUnion(true);
+
+ if (D->isCompleteDefinition())
+ if (Error Err = ImportDefinition(D, D2, IDK_Default))
+ return std::move(Err);
return D2;
}
-Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
// Import the major distinguishing characteristics of this enumerator.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
-
// Determine whether there are any other declarations with the same name and
// in the same context.
if (!LexicalDC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
@@ -2416,18 +2824,22 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return nullptr;
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
- Expr *Init = Importer.Import(D->getInitExpr());
- if (D->getInitExpr() && !Init)
- return nullptr;
+ ExpectedType TypeOrErr = import(D->getType());
+ if (!TypeOrErr)
+ return TypeOrErr.takeError();
+
+ ExpectedExpr InitOrErr = import(D->getInitExpr());
+ if (!InitOrErr)
+ return InitOrErr.takeError();
EnumConstantDecl *ToEnumerator;
if (GetImportedOrCreateDecl(
ToEnumerator, D, Importer.getToContext(), cast<EnumDecl>(DC), Loc,
- Name.getAsIdentifierInfo(), T, Init, D->getInitVal()))
+ Name.getAsIdentifierInfo(), *TypeOrErr, *InitOrErr, D->getInitVal()))
return ToEnumerator;
ToEnumerator->setAccess(D->getAccess());
@@ -2436,52 +2848,57 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
return ToEnumerator;
}
-bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD,
- FunctionDecl *ToFD) {
+Error ASTNodeImporter::ImportTemplateInformation(
+ FunctionDecl *FromFD, FunctionDecl *ToFD) {
switch (FromFD->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_FunctionTemplate:
- return false;
+ return Error::success();
case FunctionDecl::TK_MemberSpecialization: {
- auto *InstFD = cast_or_null<FunctionDecl>(
- Importer.Import(FromFD->getInstantiatedFromMemberFunction()));
- if (!InstFD)
- return true;
-
TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind();
- SourceLocation POI = Importer.Import(
- FromFD->getMemberSpecializationInfo()->getPointOfInstantiation());
- ToFD->setInstantiationOfMemberFunction(InstFD, TSK);
- ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
- return false;
+
+ if (Expected<FunctionDecl *> InstFDOrErr =
+ import(FromFD->getInstantiatedFromMemberFunction()))
+ ToFD->setInstantiationOfMemberFunction(*InstFDOrErr, TSK);
+ else
+ return InstFDOrErr.takeError();
+
+ if (ExpectedSLoc POIOrErr = import(
+ FromFD->getMemberSpecializationInfo()->getPointOfInstantiation()))
+ ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr);
+ else
+ return POIOrErr.takeError();
+
+ return Error::success();
}
case FunctionDecl::TK_FunctionTemplateSpecialization: {
- FunctionTemplateDecl* Template;
- OptionalTemplateArgsTy ToTemplArgs;
- std::tie(Template, ToTemplArgs) =
+ auto FunctionAndArgsOrErr =
ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
- if (!Template || !ToTemplArgs)
- return true;
+ if (!FunctionAndArgsOrErr)
+ return FunctionAndArgsOrErr.takeError();
TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy(
- Importer.getToContext(), *ToTemplArgs);
+ Importer.getToContext(), std::get<1>(*FunctionAndArgsOrErr));
auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
TemplateArgumentListInfo ToTAInfo;
const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten;
if (FromTAArgsAsWritten)
- if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo))
- return true;
+ if (Error Err = ImportTemplateArgumentListInfo(
+ *FromTAArgsAsWritten, ToTAInfo))
+ return Err;
- SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation());
+ ExpectedSLoc POIOrErr = import(FTSInfo->getPointOfInstantiation());
+ if (!POIOrErr)
+ return POIOrErr.takeError();
TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();
ToFD->setFunctionTemplateSpecialization(
- Template, ToTAList, /* InsertPos= */ nullptr,
- TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI);
- return false;
+ std::get<0>(*FunctionAndArgsOrErr), ToTAList, /* InsertPos= */ nullptr,
+ TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, *POIOrErr);
+ return Error::success();
}
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
@@ -2489,53 +2906,56 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD,
UnresolvedSet<8> TemplDecls;
unsigned NumTemplates = FromInfo->getNumTemplates();
for (unsigned I = 0; I < NumTemplates; I++) {
- if (auto *ToFTD = cast_or_null<FunctionTemplateDecl>(
- Importer.Import(FromInfo->getTemplate(I))))
- TemplDecls.addDecl(ToFTD);
+ if (Expected<FunctionTemplateDecl *> ToFTDOrErr =
+ import(FromInfo->getTemplate(I)))
+ TemplDecls.addDecl(*ToFTDOrErr);
else
- return true;
+ return ToFTDOrErr.takeError();
}
// Import TemplateArgumentListInfo.
TemplateArgumentListInfo ToTAInfo;
- if (ImportTemplateArgumentListInfo(
- FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(),
- llvm::makeArrayRef(FromInfo->getTemplateArgs(),
- FromInfo->getNumTemplateArgs()),
- ToTAInfo))
- return true;
+ if (Error Err = ImportTemplateArgumentListInfo(
+ FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(),
+ llvm::makeArrayRef(
+ FromInfo->getTemplateArgs(), FromInfo->getNumTemplateArgs()),
+ ToTAInfo))
+ return Err;
ToFD->setDependentTemplateSpecialization(Importer.getToContext(),
TemplDecls, ToTAInfo);
- return false;
+ return Error::success();
}
}
llvm_unreachable("All cases should be covered!");
}
-FunctionDecl *
+Expected<FunctionDecl *>
ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) {
- FunctionTemplateDecl* Template;
- OptionalTemplateArgsTy ToTemplArgs;
- std::tie(Template, ToTemplArgs) =
+ auto FunctionAndArgsOrErr =
ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
- if (!Template || !ToTemplArgs)
- return nullptr;
+ if (!FunctionAndArgsOrErr)
+ return FunctionAndArgsOrErr.takeError();
+ FunctionTemplateDecl *Template;
+ TemplateArgsTy ToTemplArgs;
+ std::tie(Template, ToTemplArgs) = *FunctionAndArgsOrErr;
void *InsertPos = nullptr;
- auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos);
+ auto *FoundSpec = Template->findSpecialization(ToTemplArgs, InsertPos);
return FoundSpec;
}
-Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
- SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D);
+ SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D);
auto RedeclIt = Redecls.begin();
// Import the first part of the decl chain. I.e. import all previous
// declarations starting from the canonical decl.
- for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt)
- if (!Importer.Import(*RedeclIt))
- return nullptr;
+ for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) {
+ ExpectedDecl ToRedeclOrErr = import(*RedeclIt);
+ if (!ToRedeclOrErr)
+ return ToRedeclOrErr.takeError();
+ }
assert(*RedeclIt == D);
// Import the major distinguishing characteristics of this function.
@@ -2543,8 +2963,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
@@ -2552,16 +2972,18 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
FunctionTemplateDecl *FromFT = D->getDescribedFunctionTemplate();
// If this is a function template specialization, then try to find the same
- // existing specialization in the "to" context. The localUncachedLookup
- // below will not find any specialization, but would find the primary
- // template; thus, we have to skip normal lookup in case of specializations.
+ // existing specialization in the "to" context. The lookup below will not
+ // find any specialization, but would find the primary template; thus, we
+ // have to skip normal lookup in case of specializations.
// FIXME handle member function templates (TK_MemberSpecialization) similarly?
if (D->getTemplatedKind() ==
FunctionDecl::TK_FunctionTemplateSpecialization) {
- if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) {
- if (D->doesThisDeclarationHaveABody() &&
- FoundFunction->hasBody())
- return Importer.Imported(D, FoundFunction);
+ auto FoundFunctionOrErr = FindFunctionTemplateSpecialization(D);
+ if (!FoundFunctionOrErr)
+ return FoundFunctionOrErr.takeError();
+ if (FunctionDecl *FoundFunction = *FoundFunctionOrErr) {
+ if (D->doesThisDeclarationHaveABody() && FoundFunction->hasBody())
+ return Importer.MapImported(D, FoundFunction);
FoundByLookup = FoundFunction;
}
}
@@ -2570,20 +2992,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
else if (!LexicalDC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- // If template was found, look at the templated function.
- if (FromFT) {
- if (auto *Template = dyn_cast<FunctionTemplateDecl>(FoundDecl))
- FoundDecl = Template->getTemplatedDecl();
- else
- continue;
- }
-
if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) {
if (FoundFunction->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
@@ -2622,13 +3035,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return nullptr;
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
DeclarationNameInfo NameInfo(Name, Loc);
// Import additional name location/type info.
- ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+ if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
+ return std::move(Err);
QualType FromTy = D->getType();
bool usedDifferentExceptionSpec = false;
@@ -2649,84 +3063,93 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
}
- // Import the type.
- QualType T = Importer.Import(FromTy);
- if (T.isNull())
- return nullptr;
+ QualType T;
+ TypeSourceInfo *TInfo;
+ SourceLocation ToInnerLocStart, ToEndLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ if (auto Imp = importSeq(
+ FromTy, D->getTypeSourceInfo(), D->getInnerLocStart(),
+ D->getQualifierLoc(), D->getEndLoc()))
+ std::tie(T, TInfo, ToInnerLocStart, ToQualifierLoc, ToEndLoc) = *Imp;
+ else
+ return Imp.takeError();
// Import the function parameters.
SmallVector<ParmVarDecl *, 8> Parameters;
for (auto P : D->parameters()) {
- auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P));
- if (!ToP)
- return nullptr;
-
- Parameters.push_back(ToP);
+ if (Expected<ParmVarDecl *> ToPOrErr = import(P))
+ Parameters.push_back(*ToPOrErr);
+ else
+ return ToPOrErr.takeError();
}
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- if (D->getTypeSourceInfo() && !TInfo)
- return nullptr;
-
// Create the imported function.
FunctionDecl *ToFunction = nullptr;
- SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart());
if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
if (GetImportedOrCreateDecl<CXXConstructorDecl>(
- ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
- InnerLocStart, NameInfo, T, TInfo, FromConstructor->isExplicit(),
- D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ ToInnerLocStart, NameInfo, T, TInfo,
+ FromConstructor->isExplicit(),
+ D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()))
return ToFunction;
- if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
- SmallVector<CXXCtorInitializer *, 4> CtorInitializers;
- for (auto *I : FromConstructor->inits()) {
- auto *ToI = cast_or_null<CXXCtorInitializer>(Importer.Import(I));
- if (!ToI && I)
- return nullptr;
- CtorInitializers.push_back(ToI);
- }
- auto **Memory =
- new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
- std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
- auto *ToCtor = cast<CXXConstructorDecl>(ToFunction);
- ToCtor->setCtorInitializers(Memory);
- ToCtor->setNumCtorInitializers(NumInitializers);
- }
} else if (isa<CXXDestructorDecl>(D)) {
if (GetImportedOrCreateDecl<CXXDestructorDecl>(
- ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
- InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
- D->isImplicit()))
+ ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
+ ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
+ D->isImplicit()))
return ToFunction;
} else if (CXXConversionDecl *FromConversion =
dyn_cast<CXXConversionDecl>(D)) {
if (GetImportedOrCreateDecl<CXXConversionDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
- InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
+ ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
FromConversion->isExplicit(), D->isConstexpr(), SourceLocation()))
return ToFunction;
} else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (GetImportedOrCreateDecl<CXXMethodDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
- InnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(),
+ ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(),
Method->isInlineSpecified(), D->isConstexpr(), SourceLocation()))
return ToFunction;
} else {
if (GetImportedOrCreateDecl(ToFunction, D, Importer.getToContext(), DC,
- InnerLocStart, NameInfo, T, TInfo,
+ ToInnerLocStart, NameInfo, T, TInfo,
D->getStorageClass(), D->isInlineSpecified(),
D->hasWrittenPrototype(), D->isConstexpr()))
return ToFunction;
}
- // Import the qualifier, if any.
- ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ // Connect the redecl chain.
+ if (FoundByLookup) {
+ auto *Recent = const_cast<FunctionDecl *>(
+ FoundByLookup->getMostRecentDecl());
+ ToFunction->setPreviousDecl(Recent);
+ }
+
+ // Import Ctor initializers.
+ if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
+ SmallVector<CXXCtorInitializer *, 4> CtorInitializers(NumInitializers);
+ // Import first, then allocate memory and copy if there was no error.
+ if (Error Err = ImportContainerChecked(
+ FromConstructor->inits(), CtorInitializers))
+ return std::move(Err);
+ auto **Memory =
+ new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
+ std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
+ auto *ToCtor = cast<CXXConstructorDecl>(ToFunction);
+ ToCtor->setCtorInitializers(Memory);
+ ToCtor->setNumCtorInitializers(NumInitializers);
+ }
+ }
+
+ ToFunction->setQualifierInfo(ToQualifierLoc);
ToFunction->setAccess(D->getAccess());
ToFunction->setLexicalDeclContext(LexicalDC);
ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
ToFunction->setTrivial(D->isTrivial());
ToFunction->setPure(D->isPure());
- ToFunction->setRangeEnd(Importer.Import(D->getLocEnd()));
+ ToFunction->setRangeEnd(ToEndLoc);
// Set the parameters.
for (auto *Param : Parameters) {
@@ -2735,12 +3158,6 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
ToFunction->setParams(Parameters);
- if (FoundByLookup) {
- auto *Recent = const_cast<FunctionDecl *>(
- FoundByLookup->getMostRecentDecl());
- ToFunction->setPreviousDecl(Recent);
- }
-
// We need to complete creation of FunctionProtoTypeLoc manually with setting
// params it refers to.
if (TInfo) {
@@ -2753,30 +3170,33 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
if (usedDifferentExceptionSpec) {
// Update FunctionProtoType::ExtProtoInfo.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
- ToFunction->setType(T);
+ if (ExpectedType TyOrErr = import(D->getType()))
+ ToFunction->setType(*TyOrErr);
+ else
+ return TyOrErr.takeError();
}
// Import the describing template function, if any.
- if (FromFT)
- if (!Importer.Import(FromFT))
- return nullptr;
+ if (FromFT) {
+ auto ToFTOrErr = import(FromFT);
+ if (!ToFTOrErr)
+ return ToFTOrErr.takeError();
+ }
if (D->doesThisDeclarationHaveABody()) {
if (Stmt *FromBody = D->getBody()) {
- if (Stmt *ToBody = Importer.Import(FromBody)) {
- ToFunction->setBody(ToBody);
- }
+ if (ExpectedStmt ToBodyOrErr = import(FromBody))
+ ToFunction->setBody(*ToBodyOrErr);
+ else
+ return ToBodyOrErr.takeError();
}
}
// FIXME: Other bits to merge?
// If it is a template, import all related things.
- if (ImportTemplateInformation(D, ToFunction))
- return nullptr;
+ if (Error Err = ImportTemplateInformation(D, ToFunction))
+ return std::move(Err);
bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend);
@@ -2796,133 +3216,139 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
DC->makeDeclVisibleInContext(ToFunction);
}
- // Import the rest of the chain. I.e. import all subsequent declarations.
- for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt)
- if (!Importer.Import(*RedeclIt))
- return nullptr;
-
if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod);
+ // Import the rest of the chain. I.e. import all subsequent declarations.
+ for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) {
+ ExpectedDecl ToRedeclOrErr = import(*RedeclIt);
+ if (!ToRedeclOrErr)
+ return ToRedeclOrErr.takeError();
+ }
+
return ToFunction;
}
-Decl *ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) {
return VisitFunctionDecl(D);
}
-Decl *ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
return VisitCXXMethodDecl(D);
}
-Decl *ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
return VisitCXXMethodDecl(D);
}
-Decl *ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
return VisitCXXMethodDecl(D);
}
-static unsigned getFieldIndex(Decl *F) {
- auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext());
- if (!Owner)
- return 0;
-
- unsigned Index = 1;
- for (const auto *D : Owner->noload_decls()) {
- if (D == F)
- return Index;
-
- if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D))
- ++Index;
- }
-
- return Index;
-}
-
-Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
// Import the major distinguishing characteristics of a variable.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
// Determine whether we've already imported this field.
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
- if (auto *FoundField = dyn_cast<FieldDecl>(FoundDecl)) {
+ if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecl)) {
// For anonymous fields, match up by index.
- if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
+ if (!Name &&
+ ASTImporter::getFieldIndex(D) !=
+ ASTImporter::getFieldIndex(FoundField))
continue;
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundField->getType())) {
Importer.MapImported(D, FoundField);
+ // In case of a FieldDecl of a ClassTemplateSpecializationDecl, the
+ // initializer of a FieldDecl might not had been instantiated in the
+ // "To" context. However, the "From" context might instantiated that,
+ // thus we have to merge that.
+ if (Expr *FromInitializer = D->getInClassInitializer()) {
+ // We don't have yet the initializer set.
+ if (FoundField->hasInClassInitializer() &&
+ !FoundField->getInClassInitializer()) {
+ if (ExpectedExpr ToInitializerOrErr = import(FromInitializer))
+ FoundField->setInClassInitializer(*ToInitializerOrErr);
+ else {
+ // We can't return error here,
+ // since we already mapped D as imported.
+ // FIXME: warning message?
+ consumeError(ToInitializerOrErr.takeError());
+ return FoundField;
+ }
+ }
+ }
return FoundField;
}
+ // FIXME: Why is this case not handled with calling HandleNameConflict?
Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent)
<< Name << D->getType() << FoundField->getType();
Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
<< FoundField->getType();
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
- // Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
-
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- Expr *BitWidth = Importer.Import(D->getBitWidth());
- if (!BitWidth && D->getBitWidth())
- return nullptr;
+ QualType ToType;
+ TypeSourceInfo *ToTInfo;
+ Expr *ToBitWidth;
+ SourceLocation ToInnerLocStart;
+ Expr *ToInitializer;
+ if (auto Imp = importSeq(
+ D->getType(), D->getTypeSourceInfo(), D->getBitWidth(),
+ D->getInnerLocStart(), D->getInClassInitializer()))
+ std::tie(
+ ToType, ToTInfo, ToBitWidth, ToInnerLocStart, ToInitializer) = *Imp;
+ else
+ return Imp.takeError();
FieldDecl *ToField;
if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC,
- Importer.Import(D->getInnerLocStart()), Loc,
- Name.getAsIdentifierInfo(), T, TInfo, BitWidth,
- D->isMutable(), D->getInClassInitStyle()))
+ ToInnerLocStart, Loc, Name.getAsIdentifierInfo(),
+ ToType, ToTInfo, ToBitWidth, D->isMutable(),
+ D->getInClassInitStyle()))
return ToField;
ToField->setAccess(D->getAccess());
ToField->setLexicalDeclContext(LexicalDC);
- if (Expr *FromInitializer = D->getInClassInitializer()) {
- Expr *ToInitializer = Importer.Import(FromInitializer);
- if (ToInitializer)
- ToField->setInClassInitializer(ToInitializer);
- else
- return nullptr;
- }
+ if (ToInitializer)
+ ToField->setInClassInitializer(ToInitializer);
ToField->setImplicit(D->isImplicit());
LexicalDC->addDeclInternal(ToField);
return ToField;
}
-Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
// Import the major distinguishing characteristics of a variable.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
// Determine whether we've already imported this field.
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
if (auto *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
// For anonymous indirect fields, match up by index.
- if (!Name && getFieldIndex(D) != getFieldIndex(FoundField))
+ if (!Name &&
+ ASTImporter::getFieldIndex(D) !=
+ ASTImporter::getFieldIndex(FoundField))
continue;
if (Importer.IsStructurallyEquivalent(D->getType(),
@@ -2936,39 +3362,40 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
if (!Name && I < N-1)
continue;
+ // FIXME: Why is this case not handled with calling HandleNameConflict?
Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent)
<< Name << D->getType() << FoundField->getType();
Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
<< FoundField->getType();
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
// Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
+ auto TypeOrErr = import(D->getType());
+ if (!TypeOrErr)
+ return TypeOrErr.takeError();
auto **NamedChain =
new (Importer.getToContext()) NamedDecl*[D->getChainingSize()];
unsigned i = 0;
- for (auto *PI : D->chain()) {
- Decl *D = Importer.Import(PI);
- if (!D)
- return nullptr;
- NamedChain[i++] = cast<NamedDecl>(D);
- }
+ for (auto *PI : D->chain())
+ if (Expected<NamedDecl *> ToD = import(PI))
+ NamedChain[i++] = *ToD;
+ else
+ return ToD.takeError();
llvm::MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()};
IndirectFieldDecl *ToIndirectField;
if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC,
- Loc, Name.getAsIdentifierInfo(), T, CH))
+ Loc, Name.getAsIdentifierInfo(), *TypeOrErr, CH))
// FIXME here we leak `NamedChain` which is allocated before
return ToIndirectField;
- for (const auto *A : D->attrs())
- ToIndirectField->addAttr(Importer.Import(A));
+ for (const auto *Attr : D->attrs())
+ ToIndirectField->addAttr(Importer.Import(Attr));
ToIndirectField->setAccess(D->getAccess());
ToIndirectField->setLexicalDeclContext(LexicalDC);
@@ -2976,16 +3403,14 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
return ToIndirectField;
}
-Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
// Import the major distinguishing characteristics of a declaration.
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext()
- ? DC : Importer.ImportContext(D->getLexicalDeclContext());
- if (!DC || !LexicalDC)
- return nullptr;
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
// Determine whether we've already imported this decl.
- // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup.
+ // FriendDecl is not a NamedDecl so we cannot use lookup.
auto *RD = cast<CXXRecordDecl>(DC);
FriendDecl *ImportedFriend = RD->getFirstFriend();
@@ -3007,30 +3432,42 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
// Not found. Create it.
FriendDecl::FriendUnion ToFU;
if (NamedDecl *FriendD = D->getFriendDecl()) {
- auto *ToFriendD = cast_or_null<NamedDecl>(Importer.Import(FriendD));
- if (ToFriendD && FriendD->getFriendObjectKind() != Decl::FOK_None &&
+ NamedDecl *ToFriendD;
+ if (Error Err = importInto(ToFriendD, FriendD))
+ return std::move(Err);
+
+ if (FriendD->getFriendObjectKind() != Decl::FOK_None &&
!(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator)))
ToFriendD->setObjectOfFriendDecl(false);
ToFU = ToFriendD;
- } else // The friend is a type, not a decl.
- ToFU = Importer.Import(D->getFriendType());
- if (!ToFU)
- return nullptr;
+ } else { // The friend is a type, not a decl.
+ if (auto TSIOrErr = import(D->getFriendType()))
+ ToFU = *TSIOrErr;
+ else
+ return TSIOrErr.takeError();
+ }
SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
auto **FromTPLists = D->getTrailingObjects<TemplateParameterList *>();
for (unsigned I = 0; I < D->NumTPLists; I++) {
- TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]);
- if (!List)
- return nullptr;
- ToTPLists[I] = List;
+ if (auto ListOrErr = ImportTemplateParameterList(FromTPLists[I]))
+ ToTPLists[I] = *ListOrErr;
+ else
+ return ListOrErr.takeError();
}
+ auto LocationOrErr = import(D->getLocation());
+ if (!LocationOrErr)
+ return LocationOrErr.takeError();
+ auto FriendLocOrErr = import(D->getFriendLoc());
+ if (!FriendLocOrErr)
+ return FriendLocOrErr.takeError();
+
FriendDecl *FrD;
if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC,
- Importer.Import(D->getLocation()), ToFU,
- Importer.Import(D->getFriendLoc()), ToTPLists))
+ *LocationOrErr, ToFU,
+ *FriendLocOrErr, ToTPLists))
return FrD;
FrD->setAccess(D->getAccess());
@@ -3039,22 +3476,21 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
return FrD;
}
-Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Import the major distinguishing characteristics of an ivar.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
// Determine whether we've already imported this ivar
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
- if (auto *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) {
+ if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundIvar->getType())) {
Importer.MapImported(D, FoundIvar);
@@ -3065,26 +3501,27 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
<< Name << D->getType() << FoundIvar->getType();
Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here)
<< FoundIvar->getType();
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
- // Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
-
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- Expr *BitWidth = Importer.Import(D->getBitWidth());
- if (!BitWidth && D->getBitWidth())
- return nullptr;
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ Expr *ToBitWidth;
+ SourceLocation ToInnerLocStart;
+ if (auto Imp = importSeq(
+ D->getType(), D->getTypeSourceInfo(), D->getBitWidth(), D->getInnerLocStart()))
+ std::tie(ToType, ToTypeSourceInfo, ToBitWidth, ToInnerLocStart) = *Imp;
+ else
+ return Imp.takeError();
ObjCIvarDecl *ToIvar;
if (GetImportedOrCreateDecl(
ToIvar, D, Importer.getToContext(), cast<ObjCContainerDecl>(DC),
- Importer.Import(D->getInnerLocStart()), Loc,
- Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth,
- D->getSynthesize()))
+ ToInnerLocStart, Loc, Name.getAsIdentifierInfo(),
+ ToType, ToTypeSourceInfo,
+ D->getAccessControl(),ToBitWidth, D->getSynthesize()))
return ToIvar;
ToIvar->setLexicalDeclContext(LexicalDC);
@@ -3092,25 +3529,36 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
return ToIvar;
}
-Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
+
+ SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D);
+ auto RedeclIt = Redecls.begin();
+ // Import the first part of the decl chain. I.e. import all previous
+ // declarations starting from the canonical decl.
+ for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) {
+ ExpectedDecl RedeclOrErr = import(*RedeclIt);
+ if (!RedeclOrErr)
+ return RedeclOrErr.takeError();
+ }
+ assert(*RedeclIt == D);
+
// Import the major distinguishing characteristics of a variable.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
// Try to find a variable in our own ("to") context with the same name and
// in the same context as the variable we're importing.
+ VarDecl *FoundByLookup = nullptr;
if (D->isFileVarDecl()) {
- VarDecl *MergeWithVar = nullptr;
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
@@ -3121,7 +3569,23 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
D->hasExternalFormalLinkage()) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundVar->getType())) {
- MergeWithVar = FoundVar;
+
+ // The VarDecl in the "From" context has a definition, but in the
+ // "To" context we already have a definition.
+ VarDecl *FoundDef = FoundVar->getDefinition();
+ if (D->isThisDeclarationADefinition() && FoundDef)
+ // FIXME Check for ODR error if the two definitions have
+ // different initializers?
+ return Importer.MapImported(D, FoundDef);
+
+ // The VarDecl in the "From" context has an initializer, but in the
+ // "To" context we already have an initializer.
+ const VarDecl *FoundDInit = nullptr;
+ if (D->getInit() && FoundVar->getAnyInitializer(FoundDInit))
+ // FIXME Diagnose ODR error if the two initializers are different?
+ return Importer.MapImported(D, const_cast<VarDecl*>(FoundDInit));
+
+ FoundByLookup = FoundVar;
break;
}
@@ -3133,16 +3597,16 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
if (isa<IncompleteArrayType>(FoundArray) &&
isa<ConstantArrayType>(TArray)) {
// Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
+ if (auto TyOrErr = import(D->getType()))
+ FoundVar->setType(*TyOrErr);
+ else
+ return TyOrErr.takeError();
- FoundVar->setType(T);
- MergeWithVar = FoundVar;
+ FoundByLookup = FoundVar;
break;
} else if (isa<IncompleteArrayType>(TArray) &&
isa<ConstantArrayType>(FoundArray)) {
- MergeWithVar = FoundVar;
+ FoundByLookup = FoundVar;
break;
}
}
@@ -3157,125 +3621,110 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
ConflictingDecls.push_back(FoundDecl);
}
- if (MergeWithVar) {
- // An equivalent variable with external linkage has been found. Link
- // the two declarations, then merge them.
- Importer.MapImported(D, MergeWithVar);
- updateFlags(D, MergeWithVar);
-
- if (VarDecl *DDef = D->getDefinition()) {
- if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) {
- Importer.ToDiag(ExistingDef->getLocation(),
- diag::err_odr_variable_multiple_def)
- << Name;
- Importer.FromDiag(DDef->getLocation(), diag::note_odr_defined_here);
- } else {
- Expr *Init = Importer.Import(DDef->getInit());
- MergeWithVar->setInit(Init);
- if (DDef->isInitKnownICE()) {
- EvaluatedStmt *Eval = MergeWithVar->ensureEvaluatedStmt();
- Eval->CheckedICE = true;
- Eval->IsICE = DDef->isInitICE();
- }
- }
- }
-
- return MergeWithVar;
- }
-
if (!ConflictingDecls.empty()) {
Name = Importer.HandleNameConflict(Name, DC, IDNS,
ConflictingDecls.data(),
ConflictingDecls.size());
if (!Name)
- return nullptr;
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
- // Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ SourceLocation ToInnerLocStart;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ if (auto Imp = importSeq(
+ D->getType(), D->getTypeSourceInfo(), D->getInnerLocStart(),
+ D->getQualifierLoc()))
+ std::tie(ToType, ToTypeSourceInfo, ToInnerLocStart, ToQualifierLoc) = *Imp;
+ else
+ return Imp.takeError();
// Create the imported variable.
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
VarDecl *ToVar;
if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC,
- Importer.Import(D->getInnerLocStart()), Loc,
- Name.getAsIdentifierInfo(), T, TInfo,
+ ToInnerLocStart, Loc,
+ Name.getAsIdentifierInfo(),
+ ToType, ToTypeSourceInfo,
D->getStorageClass()))
return ToVar;
- ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ ToVar->setQualifierInfo(ToQualifierLoc);
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
- // Templated declarations should never appear in the enclosing DeclContext.
- if (!D->getDescribedVarTemplate())
- LexicalDC->addDeclInternal(ToVar);
+ if (FoundByLookup) {
+ auto *Recent = const_cast<VarDecl *>(FoundByLookup->getMostRecentDecl());
+ ToVar->setPreviousDecl(Recent);
+ }
- // Merge the initializer.
- if (ImportDefinition(D, ToVar))
- return nullptr;
+ if (Error Err = ImportInitializer(D, ToVar))
+ return std::move(Err);
if (D->isConstexpr())
ToVar->setConstexpr(true);
+ if (D->getDeclContext()->containsDeclAndLoad(D))
+ DC->addDeclInternal(ToVar);
+ if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D))
+ LexicalDC->addDeclInternal(ToVar);
+
+ // Import the rest of the chain. I.e. import all subsequent declarations.
+ for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) {
+ ExpectedDecl RedeclOrErr = import(*RedeclIt);
+ if (!RedeclOrErr)
+ return RedeclOrErr.takeError();
+ }
+
return ToVar;
}
-Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
// Parameters are created in the translation unit's context, then moved
// into the function declaration's context afterward.
DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
- // Import the name of this declaration.
- DeclarationName Name = Importer.Import(D->getDeclName());
- if (D->getDeclName() && !Name)
- return nullptr;
-
- // Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
-
- // Import the parameter's type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
+ DeclarationName ToDeclName;
+ SourceLocation ToLocation;
+ QualType ToType;
+ if (auto Imp = importSeq(D->getDeclName(), D->getLocation(), D->getType()))
+ std::tie(ToDeclName, ToLocation, ToType) = *Imp;
+ else
+ return Imp.takeError();
// Create the imported parameter.
ImplicitParamDecl *ToParm = nullptr;
- if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, Loc,
- Name.getAsIdentifierInfo(), T,
- D->getParameterKind()))
+ if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
+ ToLocation, ToDeclName.getAsIdentifierInfo(),
+ ToType, D->getParameterKind()))
return ToParm;
return ToParm;
}
-Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
// Parameters are created in the translation unit's context, then moved
// into the function declaration's context afterward.
DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
- // Import the name of this declaration.
- DeclarationName Name = Importer.Import(D->getDeclName());
- if (D->getDeclName() && !Name)
- return nullptr;
-
- // Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
-
- // Import the parameter's type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
+ DeclarationName ToDeclName;
+ SourceLocation ToLocation, ToInnerLocStart;
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ if (auto Imp = importSeq(
+ D->getDeclName(), D->getLocation(), D->getType(), D->getInnerLocStart(),
+ D->getTypeSourceInfo()))
+ std::tie(
+ ToDeclName, ToLocation, ToType, ToInnerLocStart,
+ ToTypeSourceInfo) = *Imp;
+ else
+ return Imp.takeError();
- // Create the imported parameter.
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
ParmVarDecl *ToParm;
if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
- Importer.Import(D->getInnerLocStart()), Loc,
- Name.getAsIdentifierInfo(), T, TInfo,
- D->getStorageClass(),
+ ToInnerLocStart, ToLocation,
+ ToDeclName.getAsIdentifierInfo(), ToType,
+ ToTypeSourceInfo, D->getStorageClass(),
/*DefaultArg*/ nullptr))
return ToParm;
@@ -3283,21 +3732,19 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
ToParm->setKNRPromoted(D->isKNRPromoted());
- Expr *ToDefArg = nullptr;
- Expr *FromDefArg = nullptr;
if (D->hasUninstantiatedDefaultArg()) {
- FromDefArg = D->getUninstantiatedDefaultArg();
- ToDefArg = Importer.Import(FromDefArg);
- ToParm->setUninstantiatedDefaultArg(ToDefArg);
+ if (auto ToDefArgOrErr = import(D->getUninstantiatedDefaultArg()))
+ ToParm->setUninstantiatedDefaultArg(*ToDefArgOrErr);
+ else
+ return ToDefArgOrErr.takeError();
} else if (D->hasUnparsedDefaultArg()) {
ToParm->setUnparsedDefaultArg();
} else if (D->hasDefaultArg()) {
- FromDefArg = D->getDefaultArg();
- ToDefArg = Importer.Import(FromDefArg);
- ToParm->setDefaultArg(ToDefArg);
+ if (auto ToDefArgOrErr = import(D->getDefaultArg()))
+ ToParm->setDefaultArg(*ToDefArgOrErr);
+ else
+ return ToDefArgOrErr.takeError();
}
- if (FromDefArg && !ToDefArg)
- return nullptr;
if (D->isObjCMethodParameter()) {
ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex());
@@ -3310,19 +3757,18 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
return ToParm;
}
-Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
// Import the major distinguishing characteristics of a method.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (auto *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecl)) {
if (FoundMethod->isInstanceMethod() != D->isInstanceMethod())
@@ -3337,7 +3783,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
// Check the number of parameters.
@@ -3348,7 +3795,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
// Check parameter types.
@@ -3363,7 +3811,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
<< (*P)->getType() << (*FoundP)->getType();
Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here)
<< (*FoundP)->getType();
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
@@ -3375,7 +3824,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Importer.ToDiag(FoundMethod->getLocation(),
diag::note_odr_objc_method_here)
<< D->isInstanceMethod() << Name;
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
// FIXME: Any other bits we need to merge?
@@ -3383,18 +3833,20 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
}
}
- // Import the result type.
- QualType ResultTy = Importer.Import(D->getReturnType());
- if (ResultTy.isNull())
- return nullptr;
-
- TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo());
+ SourceLocation ToEndLoc;
+ QualType ToReturnType;
+ TypeSourceInfo *ToReturnTypeSourceInfo;
+ if (auto Imp = importSeq(
+ D->getEndLoc(), D->getReturnType(), D->getReturnTypeSourceInfo()))
+ std::tie(ToEndLoc, ToReturnType, ToReturnTypeSourceInfo) = *Imp;
+ else
+ return Imp.takeError();
ObjCMethodDecl *ToMethod;
if (GetImportedOrCreateDecl(
ToMethod, D, Importer.getToContext(), Loc,
- Importer.Import(D->getLocEnd()), Name.getObjCSelector(), ResultTy,
- ReturnTInfo, DC, D->isInstanceMethod(), D->isVariadic(),
+ ToEndLoc, Name.getObjCSelector(), ToReturnType,
+ ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(),
D->isPropertyAccessor(), D->isImplicit(), D->isDefined(),
D->getImplementationControl(), D->hasRelatedResultType()))
return ToMethod;
@@ -3405,11 +3857,10 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
// Import the parameters
SmallVector<ParmVarDecl *, 5> ToParams;
for (auto *FromP : D->parameters()) {
- auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP));
- if (!ToP)
- return nullptr;
-
- ToParams.push_back(ToP);
+ if (Expected<ParmVarDecl *> ToPOrErr = import(FromP))
+ ToParams.push_back(*ToPOrErr);
+ else
+ return ToPOrErr.takeError();
}
// Set the parameters.
@@ -3418,82 +3869,99 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
ToMethod->addDeclInternal(ToParam);
}
- SmallVector<SourceLocation, 12> SelLocs;
- D->getSelectorLocs(SelLocs);
- for (auto &Loc : SelLocs)
- Loc = Importer.Import(Loc);
+ SmallVector<SourceLocation, 12> FromSelLocs;
+ D->getSelectorLocs(FromSelLocs);
+ SmallVector<SourceLocation, 12> ToSelLocs(FromSelLocs.size());
+ if (Error Err = ImportContainerChecked(FromSelLocs, ToSelLocs))
+ return std::move(Err);
- ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs);
+ ToMethod->setMethodParams(Importer.getToContext(), ToParams, ToSelLocs);
ToMethod->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToMethod);
return ToMethod;
}
-Decl *ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
// Import the major distinguishing characteristics of a category.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- TypeSourceInfo *BoundInfo = Importer.Import(D->getTypeSourceInfo());
- if (!BoundInfo)
- return nullptr;
+ SourceLocation ToVarianceLoc, ToLocation, ToColonLoc;
+ TypeSourceInfo *ToTypeSourceInfo;
+ if (auto Imp = importSeq(
+ D->getVarianceLoc(), D->getLocation(), D->getColonLoc(),
+ D->getTypeSourceInfo()))
+ std::tie(ToVarianceLoc, ToLocation, ToColonLoc, ToTypeSourceInfo) = *Imp;
+ else
+ return Imp.takeError();
ObjCTypeParamDecl *Result;
if (GetImportedOrCreateDecl(
Result, D, Importer.getToContext(), DC, D->getVariance(),
- Importer.Import(D->getVarianceLoc()), D->getIndex(),
- Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(),
- Importer.Import(D->getColonLoc()), BoundInfo))
+ ToVarianceLoc, D->getIndex(),
+ ToLocation, Name.getAsIdentifierInfo(),
+ ToColonLoc, ToTypeSourceInfo))
return Result;
Result->setLexicalDeclContext(LexicalDC);
return Result;
}
-Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
// Import the major distinguishing characteristics of a category.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- auto *ToInterface =
- cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
- if (!ToInterface)
- return nullptr;
+ ObjCInterfaceDecl *ToInterface;
+ if (Error Err = importInto(ToInterface, D->getClassInterface()))
+ return std::move(Err);
// Determine if we've already encountered this category.
ObjCCategoryDecl *MergeWithCategory
= ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo());
ObjCCategoryDecl *ToCategory = MergeWithCategory;
if (!ToCategory) {
+ SourceLocation ToAtStartLoc, ToCategoryNameLoc;
+ SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc;
+ if (auto Imp = importSeq(
+ D->getAtStartLoc(), D->getCategoryNameLoc(),
+ D->getIvarLBraceLoc(), D->getIvarRBraceLoc()))
+ std::tie(
+ ToAtStartLoc, ToCategoryNameLoc,
+ ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp;
+ else
+ return Imp.takeError();
if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC,
- Importer.Import(D->getAtStartLoc()), Loc,
- Importer.Import(D->getCategoryNameLoc()),
+ ToAtStartLoc, Loc,
+ ToCategoryNameLoc,
Name.getAsIdentifierInfo(), ToInterface,
/*TypeParamList=*/nullptr,
- Importer.Import(D->getIvarLBraceLoc()),
- Importer.Import(D->getIvarRBraceLoc())))
+ ToIvarLBraceLoc,
+ ToIvarRBraceLoc))
return ToCategory;
ToCategory->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToCategory);
- // Import the type parameter list after calling Imported, to avoid
+ // Import the type parameter list after MapImported, to avoid
// loops when bringing in their DeclContext.
- ToCategory->setTypeParamList(ImportObjCTypeParamList(
- D->getTypeParamList()));
+ if (auto PListOrErr = ImportObjCTypeParamList(D->getTypeParamList()))
+ ToCategory->setTypeParamList(*PListOrErr);
+ else
+ return PListOrErr.takeError();
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
@@ -3504,45 +3972,48 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
FromProtoEnd = D->protocol_end();
FromProto != FromProtoEnd;
++FromProto, ++FromProtoLoc) {
- auto *ToProto =
- cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
- if (!ToProto)
- return nullptr;
- Protocols.push_back(ToProto);
- ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto))
+ Protocols.push_back(*ToProtoOrErr);
+ else
+ return ToProtoOrErr.takeError();
+
+ if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc))
+ ProtocolLocs.push_back(*ToProtoLocOrErr);
+ else
+ return ToProtoLocOrErr.takeError();
}
// FIXME: If we're merging, make sure that the protocol list is the same.
ToCategory->setProtocolList(Protocols.data(), Protocols.size(),
ProtocolLocs.data(), Importer.getToContext());
+
} else {
Importer.MapImported(D, ToCategory);
}
// Import all of the members of this category.
- ImportDeclContext(D);
+ if (Error Err = ImportDeclContext(D))
+ return std::move(Err);
// If we have an implementation, import it as well.
if (D->getImplementation()) {
- auto *Impl =
- cast_or_null<ObjCCategoryImplDecl>(
- Importer.Import(D->getImplementation()));
- if (!Impl)
- return nullptr;
-
- ToCategory->setImplementation(Impl);
+ if (Expected<ObjCCategoryImplDecl *> ToImplOrErr =
+ import(D->getImplementation()))
+ ToCategory->setImplementation(*ToImplOrErr);
+ else
+ return ToImplOrErr.takeError();
}
return ToCategory;
}
-bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
- ObjCProtocolDecl *To,
- ImportDefinitionKind Kind) {
+Error ASTNodeImporter::ImportDefinition(
+ ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind) {
if (To->getDefinition()) {
if (shouldForceImportDeclContext(Kind))
- ImportDeclContext(From);
- return false;
+ if (Error Err = ImportDeclContext(From))
+ return Err;
+ return Error::success();
}
// Start the protocol definition
@@ -3551,17 +4022,22 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
SmallVector<SourceLocation, 4> ProtocolLocs;
- ObjCProtocolDecl::protocol_loc_iterator
- FromProtoLoc = From->protocol_loc_begin();
+ ObjCProtocolDecl::protocol_loc_iterator FromProtoLoc =
+ From->protocol_loc_begin();
for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(),
FromProtoEnd = From->protocol_end();
FromProto != FromProtoEnd;
++FromProto, ++FromProtoLoc) {
- auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
- if (!ToProto)
- return true;
- Protocols.push_back(ToProto);
- ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto))
+ Protocols.push_back(*ToProtoOrErr);
+ else
+ return ToProtoOrErr.takeError();
+
+ if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc))
+ ProtocolLocs.push_back(*ToProtoLocOrErr);
+ else
+ return ToProtoLocOrErr.takeError();
+
}
// FIXME: If we're merging, make sure that the protocol list is the same.
@@ -3570,22 +4046,22 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
if (shouldForceImportDeclContext(Kind)) {
// Import all of the members of this protocol.
- ImportDeclContext(From, /*ForceImport=*/true);
+ if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
+ return Err;
}
- return false;
+ return Error::success();
}
-Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
// If this protocol has a definition in the translation unit we're coming
// from, but this particular declaration is not that definition, import the
// definition and map to that.
ObjCProtocolDecl *Definition = D->getDefinition();
if (Definition && Definition != D) {
- Decl *ImportedDef = Importer.Import(Definition);
- if (!ImportedDef)
- return nullptr;
-
- return Importer.MapImported(D, ImportedDef);
+ if (ExpectedDecl ImportedDefOrErr = import(Definition))
+ return Importer.MapImported(D, *ImportedDefOrErr);
+ else
+ return ImportedDefOrErr.takeError();
}
// Import the major distinguishing characteristics of a protocol.
@@ -3593,14 +4069,13 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
ObjCProtocolDecl *MergeWithProtocol = nullptr;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
continue;
@@ -3611,9 +4086,13 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
ObjCProtocolDecl *ToProto = MergeWithProtocol;
if (!ToProto) {
+ auto ToAtBeginLocOrErr = import(D->getAtStartLoc());
+ if (!ToAtBeginLocOrErr)
+ return ToAtBeginLocOrErr.takeError();
+
if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC,
Name.getAsIdentifierInfo(), Loc,
- Importer.Import(D->getAtStartLoc()),
+ *ToAtBeginLocOrErr,
/*PrevDecl=*/nullptr))
return ToProto;
ToProto->setLexicalDeclContext(LexicalDC);
@@ -3622,29 +4101,39 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
Importer.MapImported(D, ToProto);
- if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto))
- return nullptr;
+ if (D->isThisDeclarationADefinition())
+ if (Error Err = ImportDefinition(D, ToProto))
+ return std::move(Err);
return ToProto;
}
-Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+ExpectedDecl ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
+
+ ExpectedSLoc ExternLocOrErr = import(D->getExternLoc());
+ if (!ExternLocOrErr)
+ return ExternLocOrErr.takeError();
- SourceLocation ExternLoc = Importer.Import(D->getExternLoc());
- SourceLocation LangLoc = Importer.Import(D->getLocation());
+ ExpectedSLoc LangLocOrErr = import(D->getLocation());
+ if (!LangLocOrErr)
+ return LangLocOrErr.takeError();
bool HasBraces = D->hasBraces();
LinkageSpecDecl *ToLinkageSpec;
if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC,
- ExternLoc, LangLoc, D->getLanguage(), HasBraces))
+ *ExternLocOrErr, *LangLocOrErr,
+ D->getLanguage(), HasBraces))
return ToLinkageSpec;
if (HasBraces) {
- SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc());
- ToLinkageSpec->setRBraceLoc(RBraceLoc);
+ ExpectedSLoc RBraceLocOrErr = import(D->getRBraceLoc());
+ if (!RBraceLocOrErr)
+ return RBraceLocOrErr.takeError();
+ ToLinkageSpec->setRBraceLoc(*RBraceLocOrErr);
}
ToLinkageSpec->setLexicalDeclContext(LexicalDC);
@@ -3653,24 +4142,31 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
return ToLinkageSpec;
}
-Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD = nullptr;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- DeclarationNameInfo NameInfo(Name,
- Importer.Import(D->getNameInfo().getLoc()));
- ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+ SourceLocation ToLoc, ToUsingLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ if (auto Imp = importSeq(
+ D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc()))
+ std::tie(ToLoc, ToUsingLoc, ToQualifierLoc) = *Imp;
+ else
+ return Imp.takeError();
+
+ DeclarationNameInfo NameInfo(Name, ToLoc);
+ if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
+ return std::move(Err);
UsingDecl *ToUsing;
if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC,
- Importer.Import(D->getUsingLoc()),
- Importer.Import(D->getQualifierLoc()), NameInfo,
+ ToUsingLoc, ToQualifierLoc, NameInfo,
D->hasTypename()))
return ToUsing;
@@ -3679,48 +4175,45 @@ Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
if (NamedDecl *FromPattern =
Importer.getFromContext().getInstantiatedFromUsingDecl(D)) {
- if (auto *ToPattern =
- dyn_cast_or_null<NamedDecl>(Importer.Import(FromPattern)))
- Importer.getToContext().setInstantiatedFromUsingDecl(ToUsing, ToPattern);
+ if (Expected<NamedDecl *> ToPatternOrErr = import(FromPattern))
+ Importer.getToContext().setInstantiatedFromUsingDecl(
+ ToUsing, *ToPatternOrErr);
else
- return nullptr;
+ return ToPatternOrErr.takeError();
}
- for (auto *FromShadow : D->shadows()) {
- if (auto *ToShadow =
- dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromShadow)))
- ToUsing->addShadowDecl(ToShadow);
+ for (UsingShadowDecl *FromShadow : D->shadows()) {
+ if (Expected<UsingShadowDecl *> ToShadowOrErr = import(FromShadow))
+ ToUsing->addShadowDecl(*ToShadowOrErr);
else
- // FIXME: We return a nullptr here but the definition is already created
+ // FIXME: We return error here but the definition is already created
// and available with lookups. How to fix this?..
- return nullptr;
+ return ToShadowOrErr.takeError();
}
return ToUsing;
}
-Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD = nullptr;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- auto *ToUsing = dyn_cast_or_null<UsingDecl>(
- Importer.Import(D->getUsingDecl()));
- if (!ToUsing)
- return nullptr;
+ Expected<UsingDecl *> ToUsingOrErr = import(D->getUsingDecl());
+ if (!ToUsingOrErr)
+ return ToUsingOrErr.takeError();
- auto *ToTarget = dyn_cast_or_null<NamedDecl>(
- Importer.Import(D->getTargetDecl()));
- if (!ToTarget)
- return nullptr;
+ Expected<NamedDecl *> ToTargetOrErr = import(D->getTargetDecl());
+ if (!ToTargetOrErr)
+ return ToTargetOrErr.takeError();
UsingShadowDecl *ToShadow;
if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc,
- ToUsing, ToTarget))
+ *ToUsingOrErr, *ToTargetOrErr))
return ToShadow;
ToShadow->setLexicalDeclContext(LexicalDC);
@@ -3728,14 +4221,13 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
if (UsingShadowDecl *FromPattern =
Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) {
- if (auto *ToPattern =
- dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromPattern)))
- Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow,
- ToPattern);
+ if (Expected<UsingShadowDecl *> ToPatternOrErr = import(FromPattern))
+ Importer.getToContext().setInstantiatedFromUsingShadowDecl(
+ ToShadow, *ToPatternOrErr);
else
- // FIXME: We return a nullptr here but the definition is already created
+ // FIXME: We return error here but the definition is already created
// and available with lookups. How to fix this?..
- return nullptr;
+ return ToPatternOrErr.takeError();
}
LexicalDC->addDeclInternal(ToShadow);
@@ -3743,32 +4235,40 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
return ToShadow;
}
-Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD = nullptr;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- DeclContext *ToComAncestor = Importer.ImportContext(D->getCommonAncestor());
- if (!ToComAncestor)
- return nullptr;
-
- auto *ToNominated = cast_or_null<NamespaceDecl>(
- Importer.Import(D->getNominatedNamespace()));
- if (!ToNominated)
- return nullptr;
+ auto ToComAncestorOrErr = Importer.ImportContext(D->getCommonAncestor());
+ if (!ToComAncestorOrErr)
+ return ToComAncestorOrErr.takeError();
+
+ NamespaceDecl *ToNominatedNamespace;
+ SourceLocation ToUsingLoc, ToNamespaceKeyLocation, ToIdentLocation;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ if (auto Imp = importSeq(
+ D->getNominatedNamespace(), D->getUsingLoc(),
+ D->getNamespaceKeyLocation(), D->getQualifierLoc(),
+ D->getIdentLocation()))
+ std::tie(
+ ToNominatedNamespace, ToUsingLoc, ToNamespaceKeyLocation,
+ ToQualifierLoc, ToIdentLocation) = *Imp;
+ else
+ return Imp.takeError();
UsingDirectiveDecl *ToUsingDir;
if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC,
- Importer.Import(D->getUsingLoc()),
- Importer.Import(D->getNamespaceKeyLocation()),
- Importer.Import(D->getQualifierLoc()),
- Importer.Import(D->getIdentLocation()),
- ToNominated, ToComAncestor))
+ ToUsingLoc,
+ ToNamespaceKeyLocation,
+ ToQualifierLoc,
+ ToIdentLocation,
+ ToNominatedNamespace, *ToComAncestorOrErr))
return ToUsingDir;
ToUsingDir->setLexicalDeclContext(LexicalDC);
@@ -3777,25 +4277,34 @@ Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
return ToUsingDir;
}
-Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl(
+ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl(
UnresolvedUsingValueDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD = nullptr;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
- DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc()));
- ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+ SourceLocation ToLoc, ToUsingLoc, ToEllipsisLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ if (auto Imp = importSeq(
+ D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc(),
+ D->getEllipsisLoc()))
+ std::tie(ToLoc, ToUsingLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp;
+ else
+ return Imp.takeError();
+
+ DeclarationNameInfo NameInfo(Name, ToLoc);
+ if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
+ return std::move(Err);
UnresolvedUsingValueDecl *ToUsingValue;
if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC,
- Importer.Import(D->getUsingLoc()),
- Importer.Import(D->getQualifierLoc()), NameInfo,
- Importer.Import(D->getEllipsisLoc())))
+ ToUsingLoc, ToQualifierLoc, NameInfo,
+ ToEllipsisLoc))
return ToUsingValue;
ToUsingValue->setAccess(D->getAccess());
@@ -3805,23 +4314,30 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl(
return ToUsingValue;
}
-Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
+ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD = nullptr;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
+ SourceLocation ToUsingLoc, ToTypenameLoc, ToEllipsisLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ if (auto Imp = importSeq(
+ D->getUsingLoc(), D->getTypenameLoc(), D->getQualifierLoc(),
+ D->getEllipsisLoc()))
+ std::tie(ToUsingLoc, ToTypenameLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp;
+ else
+ return Imp.takeError();
+
UnresolvedUsingTypenameDecl *ToUsing;
if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC,
- Importer.Import(D->getUsingLoc()),
- Importer.Import(D->getTypenameLoc()),
- Importer.Import(D->getQualifierLoc()), Loc, Name,
- Importer.Import(D->getEllipsisLoc())))
+ ToUsingLoc, ToTypenameLoc,
+ ToQualifierLoc, Loc, Name, ToEllipsisLoc))
return ToUsing;
ToUsing->setAccess(D->getAccess());
@@ -3831,16 +4347,17 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
return ToUsing;
}
-bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
- ObjCInterfaceDecl *To,
- ImportDefinitionKind Kind) {
+
+Error ASTNodeImporter::ImportDefinition(
+ ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) {
if (To->getDefinition()) {
// Check consistency of superclass.
ObjCInterfaceDecl *FromSuper = From->getSuperClass();
if (FromSuper) {
- FromSuper = cast_or_null<ObjCInterfaceDecl>(Importer.Import(FromSuper));
- if (!FromSuper)
- return true;
+ if (auto FromSuperOrErr = import(FromSuper))
+ FromSuper = *FromSuperOrErr;
+ else
+ return FromSuperOrErr.takeError();
}
ObjCInterfaceDecl *ToSuper = To->getSuperClass();
@@ -3865,8 +4382,9 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
}
if (shouldForceImportDeclContext(Kind))
- ImportDeclContext(From);
- return false;
+ if (Error Err = ImportDeclContext(From))
+ return Err;
+ return Error::success();
}
// Start the definition.
@@ -3874,28 +4392,32 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
// If this class has a superclass, import it.
if (From->getSuperClass()) {
- TypeSourceInfo *SuperTInfo = Importer.Import(From->getSuperClassTInfo());
- if (!SuperTInfo)
- return true;
-
- To->setSuperClass(SuperTInfo);
+ if (auto SuperTInfoOrErr = import(From->getSuperClassTInfo()))
+ To->setSuperClass(*SuperTInfoOrErr);
+ else
+ return SuperTInfoOrErr.takeError();
}
// Import protocols
SmallVector<ObjCProtocolDecl *, 4> Protocols;
SmallVector<SourceLocation, 4> ProtocolLocs;
- ObjCInterfaceDecl::protocol_loc_iterator
- FromProtoLoc = From->protocol_loc_begin();
+ ObjCInterfaceDecl::protocol_loc_iterator FromProtoLoc =
+ From->protocol_loc_begin();
for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(),
FromProtoEnd = From->protocol_end();
FromProto != FromProtoEnd;
++FromProto, ++FromProtoLoc) {
- auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
- if (!ToProto)
- return true;
- Protocols.push_back(ToProto);
- ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto))
+ Protocols.push_back(*ToProtoOrErr);
+ else
+ return ToProtoOrErr.takeError();
+
+ if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc))
+ ProtocolLocs.push_back(*ToProtoLocOrErr);
+ else
+ return ToProtoLocOrErr.takeError();
+
}
// FIXME: If we're merging, make sure that the protocol list is the same.
@@ -3904,58 +4426,66 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
// Import categories. When the categories themselves are imported, they'll
// hook themselves into this interface.
- for (auto *Cat : From->known_categories())
- Importer.Import(Cat);
+ for (auto *Cat : From->known_categories()) {
+ auto ToCatOrErr = import(Cat);
+ if (!ToCatOrErr)
+ return ToCatOrErr.takeError();
+ }
// If we have an @implementation, import it as well.
if (From->getImplementation()) {
- auto *Impl = cast_or_null<ObjCImplementationDecl>(
- Importer.Import(From->getImplementation()));
- if (!Impl)
- return true;
-
- To->setImplementation(Impl);
+ if (Expected<ObjCImplementationDecl *> ToImplOrErr =
+ import(From->getImplementation()))
+ To->setImplementation(*ToImplOrErr);
+ else
+ return ToImplOrErr.takeError();
}
if (shouldForceImportDeclContext(Kind)) {
// Import all of the members of this class.
- ImportDeclContext(From, /*ForceImport=*/true);
+ if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
+ return Err;
}
- return false;
+ return Error::success();
}
-ObjCTypeParamList *
+Expected<ObjCTypeParamList *>
ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) {
if (!list)
return nullptr;
SmallVector<ObjCTypeParamDecl *, 4> toTypeParams;
- for (auto fromTypeParam : *list) {
- auto *toTypeParam = cast_or_null<ObjCTypeParamDecl>(
- Importer.Import(fromTypeParam));
- if (!toTypeParam)
- return nullptr;
-
- toTypeParams.push_back(toTypeParam);
+ for (auto *fromTypeParam : *list) {
+ if (auto toTypeParamOrErr = import(fromTypeParam))
+ toTypeParams.push_back(*toTypeParamOrErr);
+ else
+ return toTypeParamOrErr.takeError();
}
+ auto LAngleLocOrErr = import(list->getLAngleLoc());
+ if (!LAngleLocOrErr)
+ return LAngleLocOrErr.takeError();
+
+ auto RAngleLocOrErr = import(list->getRAngleLoc());
+ if (!RAngleLocOrErr)
+ return RAngleLocOrErr.takeError();
+
return ObjCTypeParamList::create(Importer.getToContext(),
- Importer.Import(list->getLAngleLoc()),
+ *LAngleLocOrErr,
toTypeParams,
- Importer.Import(list->getRAngleLoc()));
+ *RAngleLocOrErr);
}
-Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
// If this class has a definition in the translation unit we're coming from,
// but this particular declaration is not that definition, import the
// definition and map to that.
ObjCInterfaceDecl *Definition = D->getDefinition();
if (Definition && Definition != D) {
- Decl *ImportedDef = Importer.Import(Definition);
- if (!ImportedDef)
- return nullptr;
-
- return Importer.MapImported(D, ImportedDef);
+ if (ExpectedDecl ImportedDefOrErr = import(Definition))
+ return Importer.MapImported(D, *ImportedDefOrErr);
+ else
+ return ImportedDefOrErr.takeError();
}
// Import the major distinguishing characteristics of an @interface.
@@ -3963,15 +4493,14 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
// Look for an existing interface with the same name.
ObjCInterfaceDecl *MergeWithIface = nullptr;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
@@ -3983,9 +4512,13 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
// Create an interface declaration, if one does not already exist.
ObjCInterfaceDecl *ToIface = MergeWithIface;
if (!ToIface) {
+ ExpectedSLoc AtBeginLocOrErr = import(D->getAtStartLoc());
+ if (!AtBeginLocOrErr)
+ return AtBeginLocOrErr.takeError();
+
if (GetImportedOrCreateDecl(
ToIface, D, Importer.getToContext(), DC,
- Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(),
+ *AtBeginLocOrErr, Name.getAsIdentifierInfo(),
/*TypeParamList=*/nullptr,
/*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()))
return ToIface;
@@ -3993,91 +4526,99 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
LexicalDC->addDeclInternal(ToIface);
}
Importer.MapImported(D, ToIface);
- // Import the type parameter list after calling Imported, to avoid
+ // Import the type parameter list after MapImported, to avoid
// loops when bringing in their DeclContext.
- ToIface->setTypeParamList(ImportObjCTypeParamList(
- D->getTypeParamListAsWritten()));
+ if (auto ToPListOrErr =
+ ImportObjCTypeParamList(D->getTypeParamListAsWritten()))
+ ToIface->setTypeParamList(*ToPListOrErr);
+ else
+ return ToPListOrErr.takeError();
- if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
- return nullptr;
+ if (D->isThisDeclarationADefinition())
+ if (Error Err = ImportDefinition(D, ToIface))
+ return std::move(Err);
return ToIface;
}
-Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
- auto *Category = cast_or_null<ObjCCategoryDecl>(
- Importer.Import(D->getCategoryDecl()));
- if (!Category)
- return nullptr;
+ExpectedDecl
+ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ ObjCCategoryDecl *Category;
+ if (Error Err = importInto(Category, D->getCategoryDecl()))
+ return std::move(Err);
ObjCCategoryImplDecl *ToImpl = Category->getImplementation();
if (!ToImpl) {
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- if (!DC)
- return nullptr;
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
+
+ SourceLocation ToLocation, ToAtStartLoc, ToCategoryNameLoc;
+ if (auto Imp = importSeq(
+ D->getLocation(), D->getAtStartLoc(), D->getCategoryNameLoc()))
+ std::tie(ToLocation, ToAtStartLoc, ToCategoryNameLoc) = *Imp;
+ else
+ return Imp.takeError();
- SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc());
if (GetImportedOrCreateDecl(
ToImpl, D, Importer.getToContext(), DC,
Importer.Import(D->getIdentifier()), Category->getClassInterface(),
- Importer.Import(D->getLocation()),
- Importer.Import(D->getAtStartLoc()), CategoryNameLoc))
+ ToLocation, ToAtStartLoc, ToCategoryNameLoc))
return ToImpl;
- DeclContext *LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return nullptr;
-
- ToImpl->setLexicalDeclContext(LexicalDC);
- }
-
+ ToImpl->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToImpl);
Category->setImplementation(ToImpl);
}
Importer.MapImported(D, ToImpl);
- ImportDeclContext(D);
+ if (Error Err = ImportDeclContext(D))
+ return std::move(Err);
+
return ToImpl;
}
-Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+ExpectedDecl
+ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
// Find the corresponding interface.
- auto *Iface = cast_or_null<ObjCInterfaceDecl>(
- Importer.Import(D->getClassInterface()));
- if (!Iface)
- return nullptr;
+ ObjCInterfaceDecl *Iface;
+ if (Error Err = importInto(Iface, D->getClassInterface()))
+ return std::move(Err);
// Import the superclass, if any.
- ObjCInterfaceDecl *Super = nullptr;
- if (D->getSuperClass()) {
- Super = cast_or_null<ObjCInterfaceDecl>(
- Importer.Import(D->getSuperClass()));
- if (!Super)
- return nullptr;
- }
+ ObjCInterfaceDecl *Super;
+ if (Error Err = importInto(Super, D->getSuperClass()))
+ return std::move(Err);
ObjCImplementationDecl *Impl = Iface->getImplementation();
if (!Impl) {
// We haven't imported an implementation yet. Create a new @implementation
// now.
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
+
+ SourceLocation ToLocation, ToAtStartLoc, ToSuperClassLoc;
+ SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc;
+ if (auto Imp = importSeq(
+ D->getLocation(), D->getAtStartLoc(), D->getSuperClassLoc(),
+ D->getIvarLBraceLoc(), D->getIvarRBraceLoc()))
+ std::tie(
+ ToLocation, ToAtStartLoc, ToSuperClassLoc,
+ ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp;
+ else
+ return Imp.takeError();
+
if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(),
- Importer.ImportContext(D->getDeclContext()),
- Iface, Super, Importer.Import(D->getLocation()),
- Importer.Import(D->getAtStartLoc()),
- Importer.Import(D->getSuperClassLoc()),
- Importer.Import(D->getIvarLBraceLoc()),
- Importer.Import(D->getIvarRBraceLoc())))
+ DC, Iface, Super,
+ ToLocation,
+ ToAtStartLoc,
+ ToSuperClassLoc,
+ ToIvarLBraceLoc,
+ ToIvarRBraceLoc))
return Impl;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- DeclContext *LexicalDC
- = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return nullptr;
- Impl->setLexicalDeclContext(LexicalDC);
- }
+ Impl->setLexicalDeclContext(LexicalDC);
// Associate the implementation with the class it implements.
Iface->setImplementation(Impl);
@@ -4110,30 +4651,31 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
else
Importer.FromDiag(D->getLocation(),
diag::note_odr_objc_missing_superclass);
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
}
// Import all of the members of this @implementation.
- ImportDeclContext(D);
+ if (Error Err = ImportDeclContext(D))
+ return std::move(Err);
return Impl;
}
-Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
// Import the major distinguishing characteristics of an @property.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
// Check whether we have already imported this property.
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (auto *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecl)) {
// Check property types.
@@ -4143,7 +4685,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
<< Name << D->getType() << FoundProp->getType();
Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here)
<< FoundProp->getType();
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
// FIXME: Check property attributes, getters, setters, etc.?
@@ -4154,79 +4697,88 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
}
}
- // Import the type.
- TypeSourceInfo *TSI = Importer.Import(D->getTypeSourceInfo());
- if (!TSI)
- return nullptr;
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ SourceLocation ToAtLoc, ToLParenLoc;
+ if (auto Imp = importSeq(
+ D->getType(), D->getTypeSourceInfo(), D->getAtLoc(), D->getLParenLoc()))
+ std::tie(ToType, ToTypeSourceInfo, ToAtLoc, ToLParenLoc) = *Imp;
+ else
+ return Imp.takeError();
// Create the new property.
ObjCPropertyDecl *ToProperty;
if (GetImportedOrCreateDecl(
ToProperty, D, Importer.getToContext(), DC, Loc,
- Name.getAsIdentifierInfo(), Importer.Import(D->getAtLoc()),
- Importer.Import(D->getLParenLoc()), Importer.Import(D->getType()),
- TSI, D->getPropertyImplementation()))
+ Name.getAsIdentifierInfo(), ToAtLoc,
+ ToLParenLoc, ToType,
+ ToTypeSourceInfo, D->getPropertyImplementation()))
return ToProperty;
+ Selector ToGetterName, ToSetterName;
+ SourceLocation ToGetterNameLoc, ToSetterNameLoc;
+ ObjCMethodDecl *ToGetterMethodDecl, *ToSetterMethodDecl;
+ ObjCIvarDecl *ToPropertyIvarDecl;
+ if (auto Imp = importSeq(
+ D->getGetterName(), D->getSetterName(),
+ D->getGetterNameLoc(), D->getSetterNameLoc(),
+ D->getGetterMethodDecl(), D->getSetterMethodDecl(),
+ D->getPropertyIvarDecl()))
+ std::tie(
+ ToGetterName, ToSetterName,
+ ToGetterNameLoc, ToSetterNameLoc,
+ ToGetterMethodDecl, ToSetterMethodDecl,
+ ToPropertyIvarDecl) = *Imp;
+ else
+ return Imp.takeError();
+
ToProperty->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToProperty);
ToProperty->setPropertyAttributes(D->getPropertyAttributes());
ToProperty->setPropertyAttributesAsWritten(
D->getPropertyAttributesAsWritten());
- ToProperty->setGetterName(Importer.Import(D->getGetterName()),
- Importer.Import(D->getGetterNameLoc()));
- ToProperty->setSetterName(Importer.Import(D->getSetterName()),
- Importer.Import(D->getSetterNameLoc()));
- ToProperty->setGetterMethodDecl(
- cast_or_null<ObjCMethodDecl>(Importer.Import(D->getGetterMethodDecl())));
- ToProperty->setSetterMethodDecl(
- cast_or_null<ObjCMethodDecl>(Importer.Import(D->getSetterMethodDecl())));
- ToProperty->setPropertyIvarDecl(
- cast_or_null<ObjCIvarDecl>(Importer.Import(D->getPropertyIvarDecl())));
+ ToProperty->setGetterName(ToGetterName, ToGetterNameLoc);
+ ToProperty->setSetterName(ToSetterName, ToSetterNameLoc);
+ ToProperty->setGetterMethodDecl(ToGetterMethodDecl);
+ ToProperty->setSetterMethodDecl(ToSetterMethodDecl);
+ ToProperty->setPropertyIvarDecl(ToPropertyIvarDecl);
return ToProperty;
}
-Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
- auto *Property = cast_or_null<ObjCPropertyDecl>(
- Importer.Import(D->getPropertyDecl()));
- if (!Property)
- return nullptr;
-
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- if (!DC)
- return nullptr;
+ExpectedDecl
+ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+ ObjCPropertyDecl *Property;
+ if (Error Err = importInto(Property, D->getPropertyDecl()))
+ return std::move(Err);
- // Import the lexical declaration context.
- DeclContext *LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return nullptr;
- }
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
- auto *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC);
- if (!InImpl)
- return nullptr;
+ auto *InImpl = cast<ObjCImplDecl>(LexicalDC);
// Import the ivar (for an @synthesize).
ObjCIvarDecl *Ivar = nullptr;
- if (D->getPropertyIvarDecl()) {
- Ivar = cast_or_null<ObjCIvarDecl>(
- Importer.Import(D->getPropertyIvarDecl()));
- if (!Ivar)
- return nullptr;
- }
+ if (Error Err = importInto(Ivar, D->getPropertyIvarDecl()))
+ return std::move(Err);
ObjCPropertyImplDecl *ToImpl
= InImpl->FindPropertyImplDecl(Property->getIdentifier(),
Property->getQueryKind());
if (!ToImpl) {
+ SourceLocation ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc;
+ if (auto Imp = importSeq(
+ D->getBeginLoc(), D->getLocation(), D->getPropertyIvarDeclLoc()))
+ std::tie(ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc) = *Imp;
+ else
+ return Imp.takeError();
+
if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC,
- Importer.Import(D->getLocStart()),
- Importer.Import(D->getLocation()), Property,
+ ToBeginLoc,
+ ToLocation, Property,
D->getPropertyImplementation(), Ivar,
- Importer.Import(D->getPropertyIvarDeclLoc())))
+ ToPropertyIvarDeclLoc))
return ToImpl;
ToImpl->setLexicalDeclContext(LexicalDC);
@@ -4244,7 +4796,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
diag::note_odr_objc_property_impl_kind)
<< D->getPropertyDecl()->getDeclName()
<< (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
// For @synthesize, check that we have the same
@@ -4258,7 +4811,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
Importer.FromDiag(D->getPropertyIvarDeclLoc(),
diag::note_odr_objc_synthesize_ivar_here)
<< D->getPropertyIvarDecl()->getDeclName();
- return nullptr;
+
+ return make_error<ImportError>(ImportError::NameConflict);
}
// Merge the existing implementation with the new implementation.
@@ -4268,41 +4822,46 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
return ToImpl;
}
-Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ExpectedDecl
+ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
// For template arguments, we adopt the translation unit as our declaration
// context. This context will be fixed when the actual template declaration
// is created.
// FIXME: Import default argument.
+
+ ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
+ if (!BeginLocOrErr)
+ return BeginLocOrErr.takeError();
+
+ ExpectedSLoc LocationOrErr = import(D->getLocation());
+ if (!LocationOrErr)
+ return LocationOrErr.takeError();
+
TemplateTypeParmDecl *ToD = nullptr;
(void)GetImportedOrCreateDecl(
ToD, D, Importer.getToContext(),
Importer.getToContext().getTranslationUnitDecl(),
- Importer.Import(D->getLocStart()), Importer.Import(D->getLocation()),
+ *BeginLocOrErr, *LocationOrErr,
D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()),
D->wasDeclaredWithTypename(), D->isParameterPack());
return ToD;
}
-Decl *
+ExpectedDecl
ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
- // Import the name of this declaration.
- DeclarationName Name = Importer.Import(D->getDeclName());
- if (D->getDeclName() && !Name)
- return nullptr;
-
- // Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
-
- // Import the type of this declaration.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
-
- // Import type-source information.
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- if (D->getTypeSourceInfo() && !TInfo)
- return nullptr;
+ DeclarationName ToDeclName;
+ SourceLocation ToLocation, ToInnerLocStart;
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ if (auto Imp = importSeq(
+ D->getDeclName(), D->getLocation(), D->getType(), D->getTypeSourceInfo(),
+ D->getInnerLocStart()))
+ std::tie(
+ ToDeclName, ToLocation, ToType, ToTypeSourceInfo,
+ ToInnerLocStart) = *Imp;
+ else
+ return Imp.takeError();
// FIXME: Import default argument.
@@ -4310,36 +4869,39 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
(void)GetImportedOrCreateDecl(
ToD, D, Importer.getToContext(),
Importer.getToContext().getTranslationUnitDecl(),
- Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(),
- D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(),
- TInfo);
+ ToInnerLocStart, ToLocation, D->getDepth(),
+ D->getPosition(), ToDeclName.getAsIdentifierInfo(), ToType,
+ D->isParameterPack(), ToTypeSourceInfo);
return ToD;
}
-Decl *
+ExpectedDecl
ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
// Import the name of this declaration.
- DeclarationName Name = Importer.Import(D->getDeclName());
- if (D->getDeclName() && !Name)
- return nullptr;
+ auto NameOrErr = import(D->getDeclName());
+ if (!NameOrErr)
+ return NameOrErr.takeError();
// Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
+ ExpectedSLoc LocationOrErr = import(D->getLocation());
+ if (!LocationOrErr)
+ return LocationOrErr.takeError();
// Import template parameters.
- TemplateParameterList *TemplateParams
- = ImportTemplateParameterList(D->getTemplateParameters());
- if (!TemplateParams)
- return nullptr;
+ auto TemplateParamsOrErr = ImportTemplateParameterList(
+ D->getTemplateParameters());
+ if (!TemplateParamsOrErr)
+ return TemplateParamsOrErr.takeError();
// FIXME: Import default argument.
TemplateTemplateParmDecl *ToD = nullptr;
(void)GetImportedOrCreateDecl(
ToD, D, Importer.getToContext(),
- Importer.getToContext().getTranslationUnitDecl(), Loc, D->getDepth(),
- D->getPosition(), D->isParameterPack(), Name.getAsIdentifierInfo(),
- TemplateParams);
+ Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr,
+ D->getDepth(), D->getPosition(), D->isParameterPack(),
+ (*NameOrErr).getAsIdentifierInfo(),
+ *TemplateParamsOrErr);
return ToD;
}
@@ -4354,19 +4916,18 @@ static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) {
return TemplateWithDef;
}
-Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
- // If this record has a definition in the translation unit we're coming from,
- // but this particular declaration is not that definition, import the
- // definition and map to that.
- auto *Definition =
- cast_or_null<CXXRecordDecl>(D->getTemplatedDecl()->getDefinition());
- if (Definition && Definition != D->getTemplatedDecl()) {
- Decl *ImportedDef
- = Importer.Import(Definition->getDescribedClassTemplate());
- if (!ImportedDef)
- return nullptr;
+ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ bool IsFriend = D->getFriendObjectKind() != Decl::FOK_None;
- return Importer.MapImported(D, ImportedDef);
+ // If this template has a definition in the translation unit we're coming
+ // from, but this particular declaration is not that definition, import the
+ // definition and map to that.
+ ClassTemplateDecl *Definition = getDefinition(D);
+ if (Definition && Definition != D && !IsFriend) {
+ if (ExpectedDecl ImportedDefOrErr = import(Definition))
+ return Importer.MapImported(D, *ImportedDefOrErr);
+ else
+ return ImportedDefOrErr.takeError();
}
// Import the major distinguishing characteristics of this class template.
@@ -4374,40 +4935,33 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
+ ClassTemplateDecl *FoundByLookup = nullptr;
+
// We may already have a template of the same name; try to find and match it.
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
- if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary |
+ Decl::IDNS_TagFriend))
continue;
Decl *Found = FoundDecl;
- if (auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found)) {
-
- // The class to be imported is a definition.
- if (D->isThisDeclarationADefinition()) {
- // Lookup will find the fwd decl only if that is more recent than the
- // definition. So, try to get the definition if that is available in
- // the redecl chain.
- ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate);
- if (!TemplateWithDef)
- continue;
- FoundTemplate = TemplateWithDef; // Continue with the definition.
- }
+ auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found);
+ if (FoundTemplate) {
if (IsStructuralMatch(D, FoundTemplate)) {
- // The class templates structurally match; call it the same template.
-
- Importer.MapImported(D->getTemplatedDecl(),
- FoundTemplate->getTemplatedDecl());
- return Importer.MapImported(D, FoundTemplate);
+ ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate);
+ if (D->isThisDeclarationADefinition() && TemplateWithDef) {
+ return Importer.MapImported(D, TemplateWithDef);
+ }
+ FoundByLookup = FoundTemplate;
+ break;
}
}
@@ -4421,33 +4975,61 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
}
if (!Name)
- return nullptr;
+ return make_error<ImportError>(ImportError::NameConflict);
}
CXXRecordDecl *FromTemplated = D->getTemplatedDecl();
// Create the declaration that is being templated.
- auto *ToTemplated = cast_or_null<CXXRecordDecl>(
- Importer.Import(FromTemplated));
- if (!ToTemplated)
- return nullptr;
+ CXXRecordDecl *ToTemplated;
+ if (Error Err = importInto(ToTemplated, FromTemplated))
+ return std::move(Err);
// Create the class template declaration itself.
- TemplateParameterList *TemplateParams =
- ImportTemplateParameterList(D->getTemplateParameters());
- if (!TemplateParams)
- return nullptr;
+ auto TemplateParamsOrErr = ImportTemplateParameterList(
+ D->getTemplateParameters());
+ if (!TemplateParamsOrErr)
+ return TemplateParamsOrErr.takeError();
ClassTemplateDecl *D2;
if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name,
- TemplateParams, ToTemplated))
+ *TemplateParamsOrErr, ToTemplated))
return D2;
ToTemplated->setDescribedClassTemplate(D2);
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
+
+ if (D->getDeclContext()->containsDeclAndLoad(D))
+ DC->addDeclInternal(D2);
+ if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D))
+ LexicalDC->addDeclInternal(D2);
+
+ if (FoundByLookup) {
+ auto *Recent =
+ const_cast<ClassTemplateDecl *>(FoundByLookup->getMostRecentDecl());
+
+ // It is possible that during the import of the class template definition
+ // we start the import of a fwd friend decl of the very same class template
+ // and we add the fwd friend decl to the lookup table. But the ToTemplated
+ // had been created earlier and by that time the lookup could not find
+ // anything existing, so it has no previous decl. Later, (still during the
+ // import of the fwd friend decl) we start to import the definition again
+ // and this time the lookup finds the previous fwd friend class template.
+ // In this case we must set up the previous decl for the templated decl.
+ if (!ToTemplated->getPreviousDecl()) {
+ CXXRecordDecl *PrevTemplated =
+ FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
+ if (ToTemplated != PrevTemplated)
+ ToTemplated->setPreviousDecl(PrevTemplated);
+ }
+
+ D2->setPreviousDecl(Recent);
+ }
+
+ if (LexicalDC != DC && IsFriend)
+ DC->makeDeclVisibleInContext(D2);
if (FromTemplated->isCompleteDefinition() &&
!ToTemplated->isCompleteDefinition()) {
@@ -4457,124 +5039,173 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
return D2;
}
-Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
+ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D) {
// If this record has a definition in the translation unit we're coming from,
// but this particular declaration is not that definition, import the
// definition and map to that.
TagDecl *Definition = D->getDefinition();
if (Definition && Definition != D) {
- Decl *ImportedDef = Importer.Import(Definition);
- if (!ImportedDef)
- return nullptr;
-
- return Importer.MapImported(D, ImportedDef);
+ if (ExpectedDecl ImportedDefOrErr = import(Definition))
+ return Importer.MapImported(D, *ImportedDefOrErr);
+ else
+ return ImportedDefOrErr.takeError();
}
- auto *ClassTemplate =
- cast_or_null<ClassTemplateDecl>(Importer.Import(
- D->getSpecializedTemplate()));
- if (!ClassTemplate)
- return nullptr;
+ ClassTemplateDecl *ClassTemplate;
+ if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate()))
+ return std::move(Err);
// Import the context of this declaration.
- DeclContext *DC = ClassTemplate->getDeclContext();
- if (!DC)
- return nullptr;
-
- DeclContext *LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return nullptr;
- }
-
- // Import the location of this declaration.
- SourceLocation StartLoc = Importer.Import(D->getLocStart());
- SourceLocation IdLoc = Importer.Import(D->getLocation());
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
// Import template arguments.
SmallVector<TemplateArgument, 2> TemplateArgs;
- if (ImportTemplateArguments(D->getTemplateArgs().data(),
- D->getTemplateArgs().size(),
- TemplateArgs))
- return nullptr;
+ if (Error Err = ImportTemplateArguments(
+ D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs))
+ return std::move(Err);
// Try to find an existing specialization with these template arguments.
void *InsertPos = nullptr;
- ClassTemplateSpecializationDecl *D2
- = ClassTemplate->findSpecialization(TemplateArgs, InsertPos);
- if (D2) {
- // We already have a class template specialization with these template
- // arguments.
+ ClassTemplateSpecializationDecl *D2 = nullptr;
+ ClassTemplatePartialSpecializationDecl *PartialSpec =
+ dyn_cast<ClassTemplatePartialSpecializationDecl>(D);
+ if (PartialSpec)
+ D2 = ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos);
+ else
+ D2 = ClassTemplate->findSpecialization(TemplateArgs, InsertPos);
+ ClassTemplateSpecializationDecl * const PrevDecl = D2;
+ RecordDecl *FoundDef = D2 ? D2->getDefinition() : nullptr;
+ if (FoundDef) {
+ if (!D->isCompleteDefinition()) {
+ // The "From" translation unit only had a forward declaration; call it
+ // the same declaration.
+ // TODO Handle the redecl chain properly!
+ return Importer.MapImported(D, FoundDef);
+ }
- // FIXME: Check for specialization vs. instantiation errors.
+ if (IsStructuralMatch(D, FoundDef)) {
- if (RecordDecl *FoundDef = D2->getDefinition()) {
- if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
- // The record types structurally match, or the "from" translation
- // unit only had a forward declaration anyway; call it the same
- // function.
- return Importer.MapImported(D, FoundDef);
+ Importer.MapImported(D, FoundDef);
+
+ // Import those those default field initializers which have been
+ // instantiated in the "From" context, but not in the "To" context.
+ for (auto *FromField : D->fields()) {
+ auto ToOrErr = import(FromField);
+ if (!ToOrErr)
+ // FIXME: return the error?
+ consumeError(ToOrErr.takeError());
+ }
+
+ // Import those methods which have been instantiated in the
+ // "From" context, but not in the "To" context.
+ for (CXXMethodDecl *FromM : D->methods()) {
+ auto ToOrErr = import(FromM);
+ if (!ToOrErr)
+ // FIXME: return the error?
+ consumeError(ToOrErr.takeError());
}
+
+ // TODO Import instantiated default arguments.
+ // TODO Import instantiated exception specifications.
+ //
+ // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint what
+ // else could be fused during an AST merge.
+
+ return FoundDef;
}
- } else {
- // Create a new specialization.
- if (auto *PartialSpec =
- dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
- // Import TemplateArgumentListInfo
+ } else { // We either couldn't find any previous specialization in the "To"
+ // context, or we found one but without definition. Let's create a
+ // new specialization and register that at the class template.
+
+ // Import the location of this declaration.
+ ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
+ if (!BeginLocOrErr)
+ return BeginLocOrErr.takeError();
+ ExpectedSLoc IdLocOrErr = import(D->getLocation());
+ if (!IdLocOrErr)
+ return IdLocOrErr.takeError();
+
+ if (PartialSpec) {
+ // Import TemplateArgumentListInfo.
TemplateArgumentListInfo ToTAInfo;
const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
- if (ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo))
- return nullptr;
+ if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo))
+ return std::move(Err);
- QualType CanonInjType = Importer.Import(
- PartialSpec->getInjectedSpecializationType());
- if (CanonInjType.isNull())
- return nullptr;
+ QualType CanonInjType;
+ if (Error Err = importInto(
+ CanonInjType, PartialSpec->getInjectedSpecializationType()))
+ return std::move(Err);
CanonInjType = CanonInjType.getCanonicalType();
- TemplateParameterList *ToTPList = ImportTemplateParameterList(
- PartialSpec->getTemplateParameters());
- if (!ToTPList && PartialSpec->getTemplateParameters())
- return nullptr;
+ auto ToTPListOrErr = ImportTemplateParameterList(
+ PartialSpec->getTemplateParameters());
+ if (!ToTPListOrErr)
+ return ToTPListOrErr.takeError();
if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>(
- D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc,
- IdLoc, ToTPList, ClassTemplate,
+ D2, D, Importer.getToContext(), D->getTagKind(), DC,
+ *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, ClassTemplate,
llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()),
- ToTAInfo, CanonInjType, nullptr))
+ ToTAInfo, CanonInjType,
+ cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl)))
return D2;
- } else {
+ // Update InsertPos, because preceding import calls may have invalidated
+ // it by adding new specializations.
+ if (!ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos))
+ // Add this partial specialization to the class template.
+ ClassTemplate->AddPartialSpecialization(
+ cast<ClassTemplatePartialSpecializationDecl>(D2), InsertPos);
+
+ } else { // Not a partial specialization.
if (GetImportedOrCreateDecl(
- D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc,
- IdLoc, ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr))
+ D2, D, Importer.getToContext(), D->getTagKind(), DC,
+ *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs,
+ PrevDecl))
return D2;
+
+ // Update InsertPos, because preceding import calls may have invalidated
+ // it by adding new specializations.
+ if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos))
+ // Add this specialization to the class template.
+ ClassTemplate->AddSpecialization(D2, InsertPos);
}
D2->setSpecializationKind(D->getSpecializationKind());
- // Add this specialization to the class template.
- ClassTemplate->AddSpecialization(D2, InsertPos);
-
// Import the qualifier, if any.
- D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ if (auto LocOrErr = import(D->getQualifierLoc()))
+ D2->setQualifierInfo(*LocOrErr);
+ else
+ return LocOrErr.takeError();
if (auto *TSI = D->getTypeAsWritten()) {
- TypeSourceInfo *TInfo = Importer.Import(TSI);
- if (!TInfo)
- return nullptr;
- D2->setTypeAsWritten(TInfo);
- D2->setTemplateKeywordLoc(Importer.Import(D->getTemplateKeywordLoc()));
- D2->setExternLoc(Importer.Import(D->getExternLoc()));
+ if (auto TInfoOrErr = import(TSI))
+ D2->setTypeAsWritten(*TInfoOrErr);
+ else
+ return TInfoOrErr.takeError();
+
+ if (auto LocOrErr = import(D->getTemplateKeywordLoc()))
+ D2->setTemplateKeywordLoc(*LocOrErr);
+ else
+ return LocOrErr.takeError();
+
+ if (auto LocOrErr = import(D->getExternLoc()))
+ D2->setExternLoc(*LocOrErr);
+ else
+ return LocOrErr.takeError();
}
- SourceLocation POI = Importer.Import(D->getPointOfInstantiation());
- if (POI.isValid())
- D2->setPointOfInstantiation(POI);
- else if (D->getPointOfInstantiation().isValid())
- return nullptr;
+ if (D->getPointOfInstantiation().isValid()) {
+ if (auto POIOrErr = import(D->getPointOfInstantiation()))
+ D2->setPointOfInstantiation(*POIOrErr);
+ else
+ return POIOrErr.takeError();
+ }
D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind());
@@ -4586,13 +5217,14 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
LexicalDC->addDeclInternal(D2);
}
}
- if (D->isCompleteDefinition() && ImportDefinition(D, D2))
- return nullptr;
+ if (D->isCompleteDefinition())
+ if (Error Err = ImportDefinition(D, D2))
+ return std::move(Err);
return D2;
}
-Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
+ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
// If this variable has a definition in the translation unit we're coming
// from,
// but this particular declaration is not that definition, import the
@@ -4600,11 +5232,11 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
auto *Definition =
cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition());
if (Definition && Definition != D->getTemplatedDecl()) {
- Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate());
- if (!ImportedDef)
- return nullptr;
-
- return Importer.MapImported(D, ImportedDef);
+ if (ExpectedDecl ImportedDefOrErr = import(
+ Definition->getDescribedVarTemplate()))
+ return Importer.MapImported(D, *ImportedDefOrErr);
+ else
+ return ImportedDefOrErr.takeError();
}
// Import the major distinguishing characteristics of this variable template.
@@ -4612,8 +5244,8 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
@@ -4621,14 +5253,13 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
assert(!DC->isFunctionOrMethod() &&
"Variable templates cannot be declared at function scope");
SmallVector<NamedDecl *, 4> ConflictingDecls;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
continue;
Decl *Found = FoundDecl;
- if (auto *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
+ if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
if (IsStructuralMatch(D, FoundTemplate)) {
// The variable templates structurally match; call it the same template.
Importer.MapImported(D->getTemplatedDecl(),
@@ -4647,29 +5278,32 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
}
if (!Name)
- return nullptr;
+ // FIXME: Is it possible to get other error than name conflict?
+ // (Put this `if` into the previous `if`?)
+ return make_error<ImportError>(ImportError::NameConflict);
VarDecl *DTemplated = D->getTemplatedDecl();
// Import the type.
- QualType T = Importer.Import(DTemplated->getType());
- if (T.isNull())
- return nullptr;
+ // FIXME: Value not used?
+ ExpectedType TypeOrErr = import(DTemplated->getType());
+ if (!TypeOrErr)
+ return TypeOrErr.takeError();
// Create the declaration that is being templated.
- auto *ToTemplated = dyn_cast_or_null<VarDecl>(Importer.Import(DTemplated));
- if (!ToTemplated)
- return nullptr;
+ VarDecl *ToTemplated;
+ if (Error Err = importInto(ToTemplated, DTemplated))
+ return std::move(Err);
// Create the variable template declaration itself.
- TemplateParameterList *TemplateParams =
- ImportTemplateParameterList(D->getTemplateParameters());
- if (!TemplateParams)
- return nullptr;
+ auto TemplateParamsOrErr = ImportTemplateParameterList(
+ D->getTemplateParameters());
+ if (!TemplateParamsOrErr)
+ return TemplateParamsOrErr.takeError();
VarTemplateDecl *ToVarTD;
if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc,
- Name, TemplateParams, ToTemplated))
+ Name, *TemplateParamsOrErr, ToTemplated))
return ToVarTD;
ToTemplated->setDescribedVarTemplate(ToVarTD);
@@ -4686,46 +5320,42 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
return ToVarTD;
}
-Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
+ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *D) {
// If this record has a definition in the translation unit we're coming from,
// but this particular declaration is not that definition, import the
// definition and map to that.
VarDecl *Definition = D->getDefinition();
if (Definition && Definition != D) {
- Decl *ImportedDef = Importer.Import(Definition);
- if (!ImportedDef)
- return nullptr;
-
- return Importer.MapImported(D, ImportedDef);
+ if (ExpectedDecl ImportedDefOrErr = import(Definition))
+ return Importer.MapImported(D, *ImportedDefOrErr);
+ else
+ return ImportedDefOrErr.takeError();
}
- auto *VarTemplate = cast_or_null<VarTemplateDecl>(
- Importer.Import(D->getSpecializedTemplate()));
- if (!VarTemplate)
- return nullptr;
+ VarTemplateDecl *VarTemplate;
+ if (Error Err = importInto(VarTemplate, D->getSpecializedTemplate()))
+ return std::move(Err);
// Import the context of this declaration.
- DeclContext *DC = VarTemplate->getDeclContext();
- if (!DC)
- return nullptr;
-
- DeclContext *LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return nullptr;
- }
+ DeclContext *DC, *LexicalDC;
+ if (Error Err = ImportDeclContext(D, DC, LexicalDC))
+ return std::move(Err);
// Import the location of this declaration.
- SourceLocation StartLoc = Importer.Import(D->getLocStart());
- SourceLocation IdLoc = Importer.Import(D->getLocation());
+ ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
+ if (!BeginLocOrErr)
+ return BeginLocOrErr.takeError();
+
+ auto IdLocOrErr = import(D->getLocation());
+ if (!IdLocOrErr)
+ return IdLocOrErr.takeError();
// Import template arguments.
SmallVector<TemplateArgument, 2> TemplateArgs;
- if (ImportTemplateArguments(D->getTemplateArgs().data(),
- D->getTemplateArgs().size(), TemplateArgs))
- return nullptr;
+ if (Error Err = ImportTemplateArguments(
+ D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs))
+ return std::move(Err);
// Try to find an existing specialization with these template arguments.
void *InsertPos = nullptr;
@@ -4748,17 +5378,18 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
}
} else {
// Import the type.
- QualType T = Importer.Import(D->getType());
- if (T.isNull())
- return nullptr;
+ QualType T;
+ if (Error Err = importInto(T, D->getType()))
+ return std::move(Err);
- TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
- if (D->getTypeSourceInfo() && !TInfo)
- return nullptr;
+ auto TInfoOrErr = import(D->getTypeSourceInfo());
+ if (!TInfoOrErr)
+ return TInfoOrErr.takeError();
TemplateArgumentListInfo ToTAInfo;
- if (ImportTemplateArgumentListInfo(D->getTemplateArgsInfo(), ToTAInfo))
- return nullptr;
+ if (Error Err = ImportTemplateArgumentListInfo(
+ D->getTemplateArgsInfo(), ToTAInfo))
+ return std::move(Err);
using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
// Create a new specialization.
@@ -4767,41 +5398,47 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
TemplateArgumentListInfo ArgInfos;
const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten();
// NOTE: FromTAArgsAsWritten and template parameter list are non-null.
- if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos))
- return nullptr;
+ if (Error Err = ImportTemplateArgumentListInfo(
+ *FromTAArgsAsWritten, ArgInfos))
+ return std::move(Err);
- TemplateParameterList *ToTPList = ImportTemplateParameterList(
- FromPartial->getTemplateParameters());
- if (!ToTPList)
- return nullptr;
+ auto ToTPListOrErr = ImportTemplateParameterList(
+ FromPartial->getTemplateParameters());
+ if (!ToTPListOrErr)
+ return ToTPListOrErr.takeError();
PartVarSpecDecl *ToPartial;
if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC,
- StartLoc, IdLoc, ToTPList, VarTemplate, T,
- TInfo, D->getStorageClass(), TemplateArgs,
- ArgInfos))
+ *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
+ VarTemplate, T, *TInfoOrErr,
+ D->getStorageClass(), TemplateArgs, ArgInfos))
return ToPartial;
- auto *FromInst = FromPartial->getInstantiatedFromMember();
- auto *ToInst = cast_or_null<PartVarSpecDecl>(Importer.Import(FromInst));
- if (FromInst && !ToInst)
- return nullptr;
+ if (Expected<PartVarSpecDecl *> ToInstOrErr = import(
+ FromPartial->getInstantiatedFromMember()))
+ ToPartial->setInstantiatedFromMember(*ToInstOrErr);
+ else
+ return ToInstOrErr.takeError();
- ToPartial->setInstantiatedFromMember(ToInst);
if (FromPartial->isMemberSpecialization())
ToPartial->setMemberSpecialization();
D2 = ToPartial;
+
} else { // Full specialization
- if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, StartLoc,
- IdLoc, VarTemplate, T, TInfo,
+ if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC,
+ *BeginLocOrErr, *IdLocOrErr, VarTemplate,
+ T, *TInfoOrErr,
D->getStorageClass(), TemplateArgs))
return D2;
}
- SourceLocation POI = D->getPointOfInstantiation();
- if (POI.isValid())
- D2->setPointOfInstantiation(Importer.Import(POI));
+ if (D->getPointOfInstantiation().isValid()) {
+ if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation()))
+ D2->setPointOfInstantiation(*POIOrErr);
+ else
+ return POIOrErr.takeError();
+ }
D2->setSpecializationKind(D->getSpecializationKind());
D2->setTemplateArgsInfo(ToTAInfo);
@@ -4810,7 +5447,10 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
VarTemplate->AddSpecialization(D2, InsertPos);
// Import the qualifier, if any.
- D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ if (auto LocOrErr = import(D->getQualifierLoc()))
+ D2->setQualifierInfo(*LocOrErr);
+ else
+ return LocOrErr.takeError();
if (D->isConstexpr())
D2->setConstexpr(true);
@@ -4822,25 +5462,21 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
D2->setAccess(D->getAccess());
}
- // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if
- // declaration has initializer. Should this be fixed in the AST?.. Anyway,
- // we have to check the declaration for initializer - otherwise, it won't be
- // imported.
- if ((D->isThisDeclarationADefinition() || D->hasInit()) &&
- ImportDefinition(D, D2))
- return nullptr;
+ if (Error Err = ImportInitializer(D, D2))
+ return std::move(Err);
return D2;
}
-Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ExpectedDecl
+ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
- return nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
if (ToD)
return ToD;
@@ -4849,13 +5485,13 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// type, and in the same context as the function we're importing.
if (!LexicalDC->isFunctionOrMethod()) {
unsigned IDNS = Decl::IDNS_Ordinary;
- SmallVector<NamedDecl *, 2> FoundDecls;
- DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (auto *FoundFunction = dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
+ if (auto *FoundFunction =
+ dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
if (FoundFunction->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
if (IsStructuralMatch(D, FoundFunction)) {
@@ -4865,22 +5501,22 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
}
}
}
+ // TODO: handle conflicting names
}
}
- TemplateParameterList *Params =
- ImportTemplateParameterList(D->getTemplateParameters());
- if (!Params)
- return nullptr;
+ auto ParamsOrErr = ImportTemplateParameterList(
+ D->getTemplateParameters());
+ if (!ParamsOrErr)
+ return ParamsOrErr.takeError();
- auto *TemplatedFD =
- cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl()));
- if (!TemplatedFD)
- return nullptr;
+ FunctionDecl *TemplatedFD;
+ if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl()))
+ return std::move(Err);
FunctionTemplateDecl *ToFunc;
if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name,
- Params, TemplatedFD))
+ *ParamsOrErr, TemplatedFD))
return ToFunc;
TemplatedFD->setDescribedFunctionTemplate(ToFunc);
@@ -4895,2073 +5531,2189 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// Import Statements
//----------------------------------------------------------------------------
-DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) {
- if (DG.isNull())
- return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0);
- size_t NumDecls = DG.end() - DG.begin();
- SmallVector<Decl *, 1> ToDecls(NumDecls);
- auto &_Importer = this->Importer;
- std::transform(DG.begin(), DG.end(), ToDecls.begin(),
- [&_Importer](Decl *D) -> Decl * {
- return _Importer.Import(D);
- });
- return DeclGroupRef::Create(Importer.getToContext(),
- ToDecls.begin(),
- NumDecls);
+ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) {
+ Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node)
+ << S->getStmtClassName();
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
-Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
- Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
- << S->getStmtClassName();
- return nullptr;
-}
-Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
+ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
SmallVector<IdentifierInfo *, 4> Names;
for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I));
// ToII is nullptr when no symbolic name is given for output operand
// see ParseStmtAsm::ParseAsmOperandsOpt
- if (!ToII && S->getOutputIdentifier(I))
- return nullptr;
Names.push_back(ToII);
}
+
for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I));
// ToII is nullptr when no symbolic name is given for input operand
// see ParseStmtAsm::ParseAsmOperandsOpt
- if (!ToII && S->getInputIdentifier(I))
- return nullptr;
Names.push_back(ToII);
}
SmallVector<StringLiteral *, 4> Clobbers;
for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) {
- auto *Clobber = cast_or_null<StringLiteral>(
- Importer.Import(S->getClobberStringLiteral(I)));
- if (!Clobber)
- return nullptr;
- Clobbers.push_back(Clobber);
+ if (auto ClobberOrErr = import(S->getClobberStringLiteral(I)))
+ Clobbers.push_back(*ClobberOrErr);
+ else
+ return ClobberOrErr.takeError();
+
}
SmallVector<StringLiteral *, 4> Constraints;
for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
- auto *Output = cast_or_null<StringLiteral>(
- Importer.Import(S->getOutputConstraintLiteral(I)));
- if (!Output)
- return nullptr;
- Constraints.push_back(Output);
+ if (auto OutputOrErr = import(S->getOutputConstraintLiteral(I)))
+ Constraints.push_back(*OutputOrErr);
+ else
+ return OutputOrErr.takeError();
}
for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
- auto *Input = cast_or_null<StringLiteral>(
- Importer.Import(S->getInputConstraintLiteral(I)));
- if (!Input)
- return nullptr;
- Constraints.push_back(Input);
+ if (auto InputOrErr = import(S->getInputConstraintLiteral(I)))
+ Constraints.push_back(*InputOrErr);
+ else
+ return InputOrErr.takeError();
}
SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs());
- if (ImportContainerChecked(S->outputs(), Exprs))
- return nullptr;
-
- if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
- return nullptr;
-
- auto *AsmStr = cast_or_null<StringLiteral>(
- Importer.Import(S->getAsmString()));
- if (!AsmStr)
- return nullptr;
+ if (Error Err = ImportContainerChecked(S->outputs(), Exprs))
+ return std::move(Err);
+
+ if (Error Err = ImportArrayChecked(
+ S->inputs(), Exprs.begin() + S->getNumOutputs()))
+ return std::move(Err);
+
+ ExpectedSLoc AsmLocOrErr = import(S->getAsmLoc());
+ if (!AsmLocOrErr)
+ return AsmLocOrErr.takeError();
+ auto AsmStrOrErr = import(S->getAsmString());
+ if (!AsmStrOrErr)
+ return AsmStrOrErr.takeError();
+ ExpectedSLoc RParenLocOrErr = import(S->getRParenLoc());
+ if (!RParenLocOrErr)
+ return RParenLocOrErr.takeError();
return new (Importer.getToContext()) GCCAsmStmt(
- Importer.getToContext(),
- Importer.Import(S->getAsmLoc()),
- S->isSimple(),
- S->isVolatile(),
- S->getNumOutputs(),
- S->getNumInputs(),
- Names.data(),
- Constraints.data(),
- Exprs.data(),
- AsmStr,
- S->getNumClobbers(),
- Clobbers.data(),
- Importer.Import(S->getRParenLoc()));
-}
-
-Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
- DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup());
- for (auto *ToD : ToDG) {
- if (!ToD)
- return nullptr;
- }
- SourceLocation ToStartLoc = Importer.Import(S->getStartLoc());
- SourceLocation ToEndLoc = Importer.Import(S->getEndLoc());
- return new (Importer.getToContext()) DeclStmt(ToDG, ToStartLoc, ToEndLoc);
-}
+ Importer.getToContext(),
+ *AsmLocOrErr,
+ S->isSimple(),
+ S->isVolatile(),
+ S->getNumOutputs(),
+ S->getNumInputs(),
+ Names.data(),
+ Constraints.data(),
+ Exprs.data(),
+ *AsmStrOrErr,
+ S->getNumClobbers(),
+ Clobbers.data(),
+ *RParenLocOrErr);
+}
+
+ExpectedStmt ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
+ auto Imp = importSeq(S->getDeclGroup(), S->getBeginLoc(), S->getEndLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ DeclGroupRef ToDG;
+ SourceLocation ToBeginLoc, ToEndLoc;
+ std::tie(ToDG, ToBeginLoc, ToEndLoc) = *Imp;
+
+ return new (Importer.getToContext()) DeclStmt(ToDG, ToBeginLoc, ToEndLoc);
+}
+
+ExpectedStmt ASTNodeImporter::VisitNullStmt(NullStmt *S) {
+ ExpectedSLoc ToSemiLocOrErr = import(S->getSemiLoc());
+ if (!ToSemiLocOrErr)
+ return ToSemiLocOrErr.takeError();
+ return new (Importer.getToContext()) NullStmt(
+ *ToSemiLocOrErr, S->hasLeadingEmptyMacro());
+}
+
+ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
+ SmallVector<Stmt *, 8> ToStmts(S->size());
-Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
- SourceLocation ToSemiLoc = Importer.Import(S->getSemiLoc());
- return new (Importer.getToContext()) NullStmt(ToSemiLoc,
- S->hasLeadingEmptyMacro());
-}
+ if (Error Err = ImportContainerChecked(S->body(), ToStmts))
+ return std::move(Err);
-Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
- SmallVector<Stmt *, 8> ToStmts(S->size());
+ ExpectedSLoc ToLBracLocOrErr = import(S->getLBracLoc());
+ if (!ToLBracLocOrErr)
+ return ToLBracLocOrErr.takeError();
- if (ImportContainerChecked(S->body(), ToStmts))
- return nullptr;
+ ExpectedSLoc ToRBracLocOrErr = import(S->getRBracLoc());
+ if (!ToRBracLocOrErr)
+ return ToRBracLocOrErr.takeError();
- SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
- SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc());
- return CompoundStmt::Create(Importer.getToContext(), ToStmts, ToLBraceLoc,
- ToRBraceLoc);
+ return CompoundStmt::Create(
+ Importer.getToContext(), ToStmts,
+ *ToLBracLocOrErr, *ToRBracLocOrErr);
}
-Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
- Expr *ToLHS = Importer.Import(S->getLHS());
- if (!ToLHS)
- return nullptr;
- Expr *ToRHS = Importer.Import(S->getRHS());
- if (!ToRHS && S->getRHS())
- return nullptr;
- Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
- if (!ToSubStmt && S->getSubStmt())
- return nullptr;
- SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc());
- SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc());
- SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
- auto *ToStmt = new (Importer.getToContext())
- CaseStmt(ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc);
+ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {
+ auto Imp = importSeq(
+ S->getLHS(), S->getRHS(), S->getSubStmt(), S->getCaseLoc(),
+ S->getEllipsisLoc(), S->getColonLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ Expr *ToLHS, *ToRHS;
+ Stmt *ToSubStmt;
+ SourceLocation ToCaseLoc, ToEllipsisLoc, ToColonLoc;
+ std::tie(ToLHS, ToRHS, ToSubStmt, ToCaseLoc, ToEllipsisLoc, ToColonLoc) =
+ *Imp;
+
+ auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS,
+ ToCaseLoc, ToEllipsisLoc, ToColonLoc);
ToStmt->setSubStmt(ToSubStmt);
+
return ToStmt;
}
-Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
- SourceLocation ToDefaultLoc = Importer.Import(S->getDefaultLoc());
- SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
- Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
- if (!ToSubStmt && S->getSubStmt())
- return nullptr;
- return new (Importer.getToContext()) DefaultStmt(ToDefaultLoc, ToColonLoc,
- ToSubStmt);
-}
+ExpectedStmt ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {
+ auto Imp = importSeq(S->getDefaultLoc(), S->getColonLoc(), S->getSubStmt());
+ if (!Imp)
+ return Imp.takeError();
-Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {
- SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc());
- auto *ToLabelDecl = cast_or_null<LabelDecl>(Importer.Import(S->getDecl()));
- if (!ToLabelDecl && S->getDecl())
- return nullptr;
- Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
- if (!ToSubStmt && S->getSubStmt())
- return nullptr;
- return new (Importer.getToContext()) LabelStmt(ToIdentLoc, ToLabelDecl,
- ToSubStmt);
-}
+ SourceLocation ToDefaultLoc, ToColonLoc;
+ Stmt *ToSubStmt;
+ std::tie(ToDefaultLoc, ToColonLoc, ToSubStmt) = *Imp;
-Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
- SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc());
- ArrayRef<const Attr*> FromAttrs(S->getAttrs());
- SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size());
- if (ImportContainerChecked(FromAttrs, ToAttrs))
- return nullptr;
- Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
- if (!ToSubStmt && S->getSubStmt())
- return nullptr;
- return AttributedStmt::Create(Importer.getToContext(), ToAttrLoc,
- ToAttrs, ToSubStmt);
+ return new (Importer.getToContext()) DefaultStmt(
+ ToDefaultLoc, ToColonLoc, ToSubStmt);
}
-Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) {
- SourceLocation ToIfLoc = Importer.Import(S->getIfLoc());
- Stmt *ToInit = Importer.Import(S->getInit());
- if (!ToInit && S->getInit())
- return nullptr;
- VarDecl *ToConditionVariable = nullptr;
- if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
- ToConditionVariable =
- dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
- if (!ToConditionVariable)
- return nullptr;
- }
- Expr *ToCondition = Importer.Import(S->getCond());
- if (!ToCondition && S->getCond())
- return nullptr;
- Stmt *ToThenStmt = Importer.Import(S->getThen());
- if (!ToThenStmt && S->getThen())
- return nullptr;
- SourceLocation ToElseLoc = Importer.Import(S->getElseLoc());
- Stmt *ToElseStmt = Importer.Import(S->getElse());
- if (!ToElseStmt && S->getElse())
- return nullptr;
- return new (Importer.getToContext()) IfStmt(Importer.getToContext(),
- ToIfLoc, S->isConstexpr(),
- ToInit,
- ToConditionVariable,
- ToCondition, ToThenStmt,
- ToElseLoc, ToElseStmt);
+ExpectedStmt ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {
+ auto Imp = importSeq(S->getIdentLoc(), S->getDecl(), S->getSubStmt());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToIdentLoc;
+ LabelDecl *ToLabelDecl;
+ Stmt *ToSubStmt;
+ std::tie(ToIdentLoc, ToLabelDecl, ToSubStmt) = *Imp;
+
+ return new (Importer.getToContext()) LabelStmt(
+ ToIdentLoc, ToLabelDecl, ToSubStmt);
}
-Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
- Stmt *ToInit = Importer.Import(S->getInit());
- if (!ToInit && S->getInit())
- return nullptr;
- VarDecl *ToConditionVariable = nullptr;
- if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
- ToConditionVariable =
- dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
- if (!ToConditionVariable)
- return nullptr;
- }
- Expr *ToCondition = Importer.Import(S->getCond());
- if (!ToCondition && S->getCond())
- return nullptr;
- auto *ToStmt = new (Importer.getToContext()) SwitchStmt(
- Importer.getToContext(), ToInit,
- ToConditionVariable, ToCondition);
- Stmt *ToBody = Importer.Import(S->getBody());
- if (!ToBody && S->getBody())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
+ ExpectedSLoc ToAttrLocOrErr = import(S->getAttrLoc());
+ if (!ToAttrLocOrErr)
+ return ToAttrLocOrErr.takeError();
+ ArrayRef<const Attr*> FromAttrs(S->getAttrs());
+ SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size());
+ if (Error Err = ImportContainerChecked(FromAttrs, ToAttrs))
+ return std::move(Err);
+ ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt());
+ if (!ToSubStmtOrErr)
+ return ToSubStmtOrErr.takeError();
+
+ return AttributedStmt::Create(
+ Importer.getToContext(), *ToAttrLocOrErr, ToAttrs, *ToSubStmtOrErr);
+}
+
+ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) {
+ auto Imp = importSeq(
+ S->getIfLoc(), S->getInit(), S->getConditionVariable(), S->getCond(),
+ S->getThen(), S->getElseLoc(), S->getElse());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToIfLoc, ToElseLoc;
+ Stmt *ToInit, *ToThen, *ToElse;
+ VarDecl *ToConditionVariable;
+ Expr *ToCond;
+ std::tie(
+ ToIfLoc, ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc, ToElse) =
+ *Imp;
+
+ return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(),
+ ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc,
+ ToElse);
+}
+
+ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
+ auto Imp = importSeq(
+ S->getInit(), S->getConditionVariable(), S->getCond(),
+ S->getBody(), S->getSwitchLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ Stmt *ToInit, *ToBody;
+ VarDecl *ToConditionVariable;
+ Expr *ToCond;
+ SourceLocation ToSwitchLoc;
+ std::tie(ToInit, ToConditionVariable, ToCond, ToBody, ToSwitchLoc) = *Imp;
+
+ auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit,
+ ToConditionVariable, ToCond);
ToStmt->setBody(ToBody);
- ToStmt->setSwitchLoc(Importer.Import(S->getSwitchLoc()));
+ ToStmt->setSwitchLoc(ToSwitchLoc);
+
// Now we have to re-chain the cases.
SwitchCase *LastChainedSwitchCase = nullptr;
for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr;
SC = SC->getNextSwitchCase()) {
- auto *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC));
- if (!ToSC)
- return nullptr;
+ Expected<SwitchCase *> ToSCOrErr = import(SC);
+ if (!ToSCOrErr)
+ return ToSCOrErr.takeError();
if (LastChainedSwitchCase)
- LastChainedSwitchCase->setNextSwitchCase(ToSC);
+ LastChainedSwitchCase->setNextSwitchCase(*ToSCOrErr);
else
- ToStmt->setSwitchCaseList(ToSC);
- LastChainedSwitchCase = ToSC;
+ ToStmt->setSwitchCaseList(*ToSCOrErr);
+ LastChainedSwitchCase = *ToSCOrErr;
}
+
return ToStmt;
}
-Stmt *ASTNodeImporter::VisitWhileStmt(WhileStmt *S) {
- VarDecl *ToConditionVariable = nullptr;
- if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
- ToConditionVariable =
- dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
- if (!ToConditionVariable)
- return nullptr;
- }
- Expr *ToCondition = Importer.Import(S->getCond());
- if (!ToCondition && S->getCond())
- return nullptr;
- Stmt *ToBody = Importer.Import(S->getBody());
- if (!ToBody && S->getBody())
- return nullptr;
- SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
- return new (Importer.getToContext()) WhileStmt(Importer.getToContext(),
- ToConditionVariable,
- ToCondition, ToBody,
- ToWhileLoc);
+ExpectedStmt ASTNodeImporter::VisitWhileStmt(WhileStmt *S) {
+ auto Imp = importSeq(
+ S->getConditionVariable(), S->getCond(), S->getBody(), S->getWhileLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ VarDecl *ToConditionVariable;
+ Expr *ToCond;
+ Stmt *ToBody;
+ SourceLocation ToWhileLoc;
+ std::tie(ToConditionVariable, ToCond, ToBody, ToWhileLoc) = *Imp;
+
+ return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond,
+ ToBody, ToWhileLoc);
}
-Stmt *ASTNodeImporter::VisitDoStmt(DoStmt *S) {
- Stmt *ToBody = Importer.Import(S->getBody());
- if (!ToBody && S->getBody())
- return nullptr;
- Expr *ToCondition = Importer.Import(S->getCond());
- if (!ToCondition && S->getCond())
- return nullptr;
- SourceLocation ToDoLoc = Importer.Import(S->getDoLoc());
- SourceLocation ToWhileLoc = Importer.Import(S->getWhileLoc());
- SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
- return new (Importer.getToContext()) DoStmt(ToBody, ToCondition,
- ToDoLoc, ToWhileLoc,
- ToRParenLoc);
+ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) {
+ auto Imp = importSeq(
+ S->getBody(), S->getCond(), S->getDoLoc(), S->getWhileLoc(),
+ S->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ Stmt *ToBody;
+ Expr *ToCond;
+ SourceLocation ToDoLoc, ToWhileLoc, ToRParenLoc;
+ std::tie(ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc) = *Imp;
+
+ return new (Importer.getToContext()) DoStmt(
+ ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc);
}
-Stmt *ASTNodeImporter::VisitForStmt(ForStmt *S) {
- Stmt *ToInit = Importer.Import(S->getInit());
- if (!ToInit && S->getInit())
- return nullptr;
- Expr *ToCondition = Importer.Import(S->getCond());
- if (!ToCondition && S->getCond())
- return nullptr;
- VarDecl *ToConditionVariable = nullptr;
- if (VarDecl *FromConditionVariable = S->getConditionVariable()) {
- ToConditionVariable =
- dyn_cast_or_null<VarDecl>(Importer.Import(FromConditionVariable));
- if (!ToConditionVariable)
- return nullptr;
- }
- Expr *ToInc = Importer.Import(S->getInc());
- if (!ToInc && S->getInc())
- return nullptr;
- Stmt *ToBody = Importer.Import(S->getBody());
- if (!ToBody && S->getBody())
- return nullptr;
- SourceLocation ToForLoc = Importer.Import(S->getForLoc());
- SourceLocation ToLParenLoc = Importer.Import(S->getLParenLoc());
- SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
- return new (Importer.getToContext()) ForStmt(Importer.getToContext(),
- ToInit, ToCondition,
- ToConditionVariable,
- ToInc, ToBody,
- ToForLoc, ToLParenLoc,
- ToRParenLoc);
-}
-
-Stmt *ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {
- LabelDecl *ToLabel = nullptr;
- if (LabelDecl *FromLabel = S->getLabel()) {
- ToLabel = dyn_cast_or_null<LabelDecl>(Importer.Import(FromLabel));
- if (!ToLabel)
- return nullptr;
- }
- SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
- SourceLocation ToLabelLoc = Importer.Import(S->getLabelLoc());
- return new (Importer.getToContext()) GotoStmt(ToLabel,
- ToGotoLoc, ToLabelLoc);
+ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) {
+ auto Imp = importSeq(
+ S->getInit(), S->getCond(), S->getConditionVariable(), S->getInc(),
+ S->getBody(), S->getForLoc(), S->getLParenLoc(), S->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ Stmt *ToInit;
+ Expr *ToCond, *ToInc;
+ VarDecl *ToConditionVariable;
+ Stmt *ToBody;
+ SourceLocation ToForLoc, ToLParenLoc, ToRParenLoc;
+ std::tie(
+ ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc,
+ ToLParenLoc, ToRParenLoc) = *Imp;
+
+ return new (Importer.getToContext()) ForStmt(
+ Importer.getToContext(),
+ ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, ToLParenLoc,
+ ToRParenLoc);
}
-Stmt *ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
- SourceLocation ToGotoLoc = Importer.Import(S->getGotoLoc());
- SourceLocation ToStarLoc = Importer.Import(S->getStarLoc());
- Expr *ToTarget = Importer.Import(S->getTarget());
- if (!ToTarget && S->getTarget())
- return nullptr;
- return new (Importer.getToContext()) IndirectGotoStmt(ToGotoLoc, ToStarLoc,
- ToTarget);
+ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {
+ auto Imp = importSeq(S->getLabel(), S->getGotoLoc(), S->getLabelLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ LabelDecl *ToLabel;
+ SourceLocation ToGotoLoc, ToLabelLoc;
+ std::tie(ToLabel, ToGotoLoc, ToLabelLoc) = *Imp;
+
+ return new (Importer.getToContext()) GotoStmt(
+ ToLabel, ToGotoLoc, ToLabelLoc);
}
-Stmt *ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) {
- SourceLocation ToContinueLoc = Importer.Import(S->getContinueLoc());
- return new (Importer.getToContext()) ContinueStmt(ToContinueLoc);
+ExpectedStmt ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+ auto Imp = importSeq(S->getGotoLoc(), S->getStarLoc(), S->getTarget());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToGotoLoc, ToStarLoc;
+ Expr *ToTarget;
+ std::tie(ToGotoLoc, ToStarLoc, ToTarget) = *Imp;
+
+ return new (Importer.getToContext()) IndirectGotoStmt(
+ ToGotoLoc, ToStarLoc, ToTarget);
}
-Stmt *ASTNodeImporter::VisitBreakStmt(BreakStmt *S) {
- SourceLocation ToBreakLoc = Importer.Import(S->getBreakLoc());
- return new (Importer.getToContext()) BreakStmt(ToBreakLoc);
+ExpectedStmt ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) {
+ ExpectedSLoc ToContinueLocOrErr = import(S->getContinueLoc());
+ if (!ToContinueLocOrErr)
+ return ToContinueLocOrErr.takeError();
+ return new (Importer.getToContext()) ContinueStmt(*ToContinueLocOrErr);
}
-Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {
- SourceLocation ToRetLoc = Importer.Import(S->getReturnLoc());
- Expr *ToRetExpr = Importer.Import(S->getRetValue());
- if (!ToRetExpr && S->getRetValue())
- return nullptr;
- auto *NRVOCandidate = const_cast<VarDecl *>(S->getNRVOCandidate());
- auto *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate));
- if (!ToNRVOCandidate && NRVOCandidate)
- return nullptr;
- return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr,
- ToNRVOCandidate);
+ExpectedStmt ASTNodeImporter::VisitBreakStmt(BreakStmt *S) {
+ auto ToBreakLocOrErr = import(S->getBreakLoc());
+ if (!ToBreakLocOrErr)
+ return ToBreakLocOrErr.takeError();
+ return new (Importer.getToContext()) BreakStmt(*ToBreakLocOrErr);
}
-Stmt *ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) {
- SourceLocation ToCatchLoc = Importer.Import(S->getCatchLoc());
- VarDecl *ToExceptionDecl = nullptr;
- if (VarDecl *FromExceptionDecl = S->getExceptionDecl()) {
- ToExceptionDecl =
- dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
- if (!ToExceptionDecl)
- return nullptr;
- }
- Stmt *ToHandlerBlock = Importer.Import(S->getHandlerBlock());
- if (!ToHandlerBlock && S->getHandlerBlock())
- return nullptr;
- return new (Importer.getToContext()) CXXCatchStmt(ToCatchLoc,
- ToExceptionDecl,
- ToHandlerBlock);
+ExpectedStmt ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {
+ auto Imp = importSeq(
+ S->getReturnLoc(), S->getRetValue(), S->getNRVOCandidate());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToReturnLoc;
+ Expr *ToRetValue;
+ const VarDecl *ToNRVOCandidate;
+ std::tie(ToReturnLoc, ToRetValue, ToNRVOCandidate) = *Imp;
+
+ return ReturnStmt::Create(Importer.getToContext(), ToReturnLoc, ToRetValue,
+ ToNRVOCandidate);
}
-Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
- SourceLocation ToTryLoc = Importer.Import(S->getTryLoc());
- Stmt *ToTryBlock = Importer.Import(S->getTryBlock());
- if (!ToTryBlock && S->getTryBlock())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ auto Imp = importSeq(
+ S->getCatchLoc(), S->getExceptionDecl(), S->getHandlerBlock());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToCatchLoc;
+ VarDecl *ToExceptionDecl;
+ Stmt *ToHandlerBlock;
+ std::tie(ToCatchLoc, ToExceptionDecl, ToHandlerBlock) = *Imp;
+
+ return new (Importer.getToContext()) CXXCatchStmt (
+ ToCatchLoc, ToExceptionDecl, ToHandlerBlock);
+}
+
+ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
+ ExpectedSLoc ToTryLocOrErr = import(S->getTryLoc());
+ if (!ToTryLocOrErr)
+ return ToTryLocOrErr.takeError();
+
+ ExpectedStmt ToTryBlockOrErr = import(S->getTryBlock());
+ if (!ToTryBlockOrErr)
+ return ToTryBlockOrErr.takeError();
+
SmallVector<Stmt *, 1> ToHandlers(S->getNumHandlers());
for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) {
CXXCatchStmt *FromHandler = S->getHandler(HI);
- if (Stmt *ToHandler = Importer.Import(FromHandler))
- ToHandlers[HI] = ToHandler;
+ if (auto ToHandlerOrErr = import(FromHandler))
+ ToHandlers[HI] = *ToHandlerOrErr;
else
- return nullptr;
- }
- return CXXTryStmt::Create(Importer.getToContext(), ToTryLoc, ToTryBlock,
- ToHandlers);
-}
-
-Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
- auto *ToRange =
- dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt()));
- if (!ToRange && S->getRangeStmt())
- return nullptr;
- auto *ToBegin =
- dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginStmt()));
- if (!ToBegin && S->getBeginStmt())
- return nullptr;
- auto *ToEnd =
- dyn_cast_or_null<DeclStmt>(Importer.Import(S->getEndStmt()));
- if (!ToEnd && S->getEndStmt())
- return nullptr;
- Expr *ToCond = Importer.Import(S->getCond());
- if (!ToCond && S->getCond())
- return nullptr;
- Expr *ToInc = Importer.Import(S->getInc());
- if (!ToInc && S->getInc())
- return nullptr;
- auto *ToLoopVar =
- dyn_cast_or_null<DeclStmt>(Importer.Import(S->getLoopVarStmt()));
- if (!ToLoopVar && S->getLoopVarStmt())
- return nullptr;
- Stmt *ToBody = Importer.Import(S->getBody());
- if (!ToBody && S->getBody())
- return nullptr;
- SourceLocation ToForLoc = Importer.Import(S->getForLoc());
- SourceLocation ToCoawaitLoc = Importer.Import(S->getCoawaitLoc());
- SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
- SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
- return new (Importer.getToContext()) CXXForRangeStmt(ToRange, ToBegin, ToEnd,
- ToCond, ToInc,
- ToLoopVar, ToBody,
- ToForLoc, ToCoawaitLoc,
- ToColonLoc, ToRParenLoc);
-}
-
-Stmt *ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
- Stmt *ToElem = Importer.Import(S->getElement());
- if (!ToElem && S->getElement())
- return nullptr;
- Expr *ToCollect = Importer.Import(S->getCollection());
- if (!ToCollect && S->getCollection())
- return nullptr;
- Stmt *ToBody = Importer.Import(S->getBody());
- if (!ToBody && S->getBody())
- return nullptr;
- SourceLocation ToForLoc = Importer.Import(S->getForLoc());
- SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
- return new (Importer.getToContext()) ObjCForCollectionStmt(ToElem,
- ToCollect,
- ToBody, ToForLoc,
+ return ToHandlerOrErr.takeError();
+ }
+
+ return CXXTryStmt::Create(
+ Importer.getToContext(), *ToTryLocOrErr,*ToTryBlockOrErr, ToHandlers);
+}
+
+ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
+ auto Imp1 = importSeq(
+ S->getInit(), S->getRangeStmt(), S->getBeginStmt(), S->getEndStmt(),
+ S->getCond(), S->getInc(), S->getLoopVarStmt(), S->getBody());
+ if (!Imp1)
+ return Imp1.takeError();
+ auto Imp2 = importSeq(
+ S->getForLoc(), S->getCoawaitLoc(), S->getColonLoc(), S->getRParenLoc());
+ if (!Imp2)
+ return Imp2.takeError();
+
+ DeclStmt *ToRangeStmt, *ToBeginStmt, *ToEndStmt, *ToLoopVarStmt;
+ Expr *ToCond, *ToInc;
+ Stmt *ToInit, *ToBody;
+ std::tie(
+ ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt,
+ ToBody) = *Imp1;
+ SourceLocation ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc;
+ std::tie(ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc) = *Imp2;
+
+ return new (Importer.getToContext()) CXXForRangeStmt(
+ ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt,
+ ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc);
+}
+
+ExpectedStmt
+ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+ auto Imp = importSeq(
+ S->getElement(), S->getCollection(), S->getBody(),
+ S->getForLoc(), S->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ Stmt *ToElement, *ToBody;
+ Expr *ToCollection;
+ SourceLocation ToForLoc, ToRParenLoc;
+ std::tie(ToElement, ToCollection, ToBody, ToForLoc, ToRParenLoc) = *Imp;
+
+ return new (Importer.getToContext()) ObjCForCollectionStmt(ToElement,
+ ToCollection,
+ ToBody,
+ ToForLoc,
ToRParenLoc);
}
-Stmt *ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
- SourceLocation ToAtCatchLoc = Importer.Import(S->getAtCatchLoc());
- SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
- VarDecl *ToExceptionDecl = nullptr;
- if (VarDecl *FromExceptionDecl = S->getCatchParamDecl()) {
- ToExceptionDecl =
- dyn_cast_or_null<VarDecl>(Importer.Import(FromExceptionDecl));
- if (!ToExceptionDecl)
- return nullptr;
- }
- Stmt *ToBody = Importer.Import(S->getCatchBody());
- if (!ToBody && S->getCatchBody())
- return nullptr;
- return new (Importer.getToContext()) ObjCAtCatchStmt(ToAtCatchLoc,
- ToRParenLoc,
- ToExceptionDecl,
- ToBody);
+ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ auto Imp = importSeq(
+ S->getAtCatchLoc(), S->getRParenLoc(), S->getCatchParamDecl(),
+ S->getCatchBody());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToAtCatchLoc, ToRParenLoc;
+ VarDecl *ToCatchParamDecl;
+ Stmt *ToCatchBody;
+ std::tie(ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody) = *Imp;
+
+ return new (Importer.getToContext()) ObjCAtCatchStmt (
+ ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody);
}
-Stmt *ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
- SourceLocation ToAtFinallyLoc = Importer.Import(S->getAtFinallyLoc());
- Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyBody());
- if (!ToAtFinallyStmt && S->getFinallyBody())
- return nullptr;
- return new (Importer.getToContext()) ObjCAtFinallyStmt(ToAtFinallyLoc,
- ToAtFinallyStmt);
+ExpectedStmt ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ ExpectedSLoc ToAtFinallyLocOrErr = import(S->getAtFinallyLoc());
+ if (!ToAtFinallyLocOrErr)
+ return ToAtFinallyLocOrErr.takeError();
+ ExpectedStmt ToAtFinallyStmtOrErr = import(S->getFinallyBody());
+ if (!ToAtFinallyStmtOrErr)
+ return ToAtFinallyStmtOrErr.takeError();
+ return new (Importer.getToContext()) ObjCAtFinallyStmt(*ToAtFinallyLocOrErr,
+ *ToAtFinallyStmtOrErr);
}
-Stmt *ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
- SourceLocation ToAtTryLoc = Importer.Import(S->getAtTryLoc());
- Stmt *ToAtTryStmt = Importer.Import(S->getTryBody());
- if (!ToAtTryStmt && S->getTryBody())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+ auto Imp = importSeq(
+ S->getAtTryLoc(), S->getTryBody(), S->getFinallyStmt());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToAtTryLoc;
+ Stmt *ToTryBody, *ToFinallyStmt;
+ std::tie(ToAtTryLoc, ToTryBody, ToFinallyStmt) = *Imp;
+
SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts());
for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) {
ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI);
- if (Stmt *ToCatchStmt = Importer.Import(FromCatchStmt))
- ToCatchStmts[CI] = ToCatchStmt;
+ if (ExpectedStmt ToCatchStmtOrErr = import(FromCatchStmt))
+ ToCatchStmts[CI] = *ToCatchStmtOrErr;
else
- return nullptr;
+ return ToCatchStmtOrErr.takeError();
}
- Stmt *ToAtFinallyStmt = Importer.Import(S->getFinallyStmt());
- if (!ToAtFinallyStmt && S->getFinallyStmt())
- return nullptr;
+
return ObjCAtTryStmt::Create(Importer.getToContext(),
- ToAtTryLoc, ToAtTryStmt,
+ ToAtTryLoc, ToTryBody,
ToCatchStmts.begin(), ToCatchStmts.size(),
- ToAtFinallyStmt);
+ ToFinallyStmt);
}
-Stmt *ASTNodeImporter::VisitObjCAtSynchronizedStmt
+ExpectedStmt ASTNodeImporter::VisitObjCAtSynchronizedStmt
(ObjCAtSynchronizedStmt *S) {
- SourceLocation ToAtSynchronizedLoc =
- Importer.Import(S->getAtSynchronizedLoc());
- Expr *ToSynchExpr = Importer.Import(S->getSynchExpr());
- if (!ToSynchExpr && S->getSynchExpr())
- return nullptr;
- Stmt *ToSynchBody = Importer.Import(S->getSynchBody());
- if (!ToSynchBody && S->getSynchBody())
- return nullptr;
+ auto Imp = importSeq(
+ S->getAtSynchronizedLoc(), S->getSynchExpr(), S->getSynchBody());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToAtSynchronizedLoc;
+ Expr *ToSynchExpr;
+ Stmt *ToSynchBody;
+ std::tie(ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody) = *Imp;
+
return new (Importer.getToContext()) ObjCAtSynchronizedStmt(
ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody);
}
-Stmt *ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
- SourceLocation ToAtThrowLoc = Importer.Import(S->getThrowLoc());
- Expr *ToThrow = Importer.Import(S->getThrowExpr());
- if (!ToThrow && S->getThrowExpr())
- return nullptr;
- return new (Importer.getToContext()) ObjCAtThrowStmt(ToAtThrowLoc, ToThrow);
+ExpectedStmt ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ ExpectedSLoc ToThrowLocOrErr = import(S->getThrowLoc());
+ if (!ToThrowLocOrErr)
+ return ToThrowLocOrErr.takeError();
+ ExpectedExpr ToThrowExprOrErr = import(S->getThrowExpr());
+ if (!ToThrowExprOrErr)
+ return ToThrowExprOrErr.takeError();
+ return new (Importer.getToContext()) ObjCAtThrowStmt(
+ *ToThrowLocOrErr, *ToThrowExprOrErr);
}
-Stmt *ASTNodeImporter::VisitObjCAutoreleasePoolStmt
- (ObjCAutoreleasePoolStmt *S) {
- SourceLocation ToAtLoc = Importer.Import(S->getAtLoc());
- Stmt *ToSubStmt = Importer.Import(S->getSubStmt());
- if (!ToSubStmt && S->getSubStmt())
- return nullptr;
- return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(ToAtLoc,
- ToSubStmt);
+ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt(
+ ObjCAutoreleasePoolStmt *S) {
+ ExpectedSLoc ToAtLocOrErr = import(S->getAtLoc());
+ if (!ToAtLocOrErr)
+ return ToAtLocOrErr.takeError();
+ ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt());
+ if (!ToSubStmtOrErr)
+ return ToSubStmtOrErr.takeError();
+ return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(*ToAtLocOrErr,
+ *ToSubStmtOrErr);
}
//----------------------------------------------------------------------------
// Import Expressions
//----------------------------------------------------------------------------
-Expr *ASTNodeImporter::VisitExpr(Expr *E) {
- Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node)
- << E->getStmtClassName();
- return nullptr;
-}
-
-Expr *ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr && E->getSubExpr())
- return nullptr;
-
- TypeSourceInfo *TInfo = Importer.Import(E->getWrittenTypeInfo());
- if (!TInfo)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) {
+ Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node)
+ << E->getStmtClassName();
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
+}
+
+ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {
+ auto Imp = importSeq(
+ E->getBuiltinLoc(), E->getSubExpr(), E->getWrittenTypeInfo(),
+ E->getRParenLoc(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToBuiltinLoc, ToRParenLoc;
+ Expr *ToSubExpr;
+ TypeSourceInfo *ToWrittenTypeInfo;
+ QualType ToType;
+ std::tie(ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType) =
+ *Imp;
return new (Importer.getToContext()) VAArgExpr(
- Importer.Import(E->getBuiltinLoc()), SubExpr, TInfo,
- Importer.Import(E->getRParenLoc()), T, E->isMicrosoftABI());
+ ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType,
+ E->isMicrosoftABI());
}
-Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
- return new (Importer.getToContext()) GNUNullExpr(
- T, Importer.Import(E->getLocStart()));
+ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
+ ExpectedType TypeOrErr = import(E->getType());
+ if (!TypeOrErr)
+ return TypeOrErr.takeError();
+
+ ExpectedSLoc BeginLocOrErr = import(E->getBeginLoc());
+ if (!BeginLocOrErr)
+ return BeginLocOrErr.takeError();
+
+ return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr);
}
-Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
+ auto Imp = importSeq(
+ E->getBeginLoc(), E->getType(), E->getFunctionName());
+ if (!Imp)
+ return Imp.takeError();
- auto *SL = cast_or_null<StringLiteral>(Importer.Import(E->getFunctionName()));
- if (!SL && E->getFunctionName())
- return nullptr;
+ SourceLocation ToBeginLoc;
+ QualType ToType;
+ StringLiteral *ToFunctionName;
+ std::tie(ToBeginLoc, ToType, ToFunctionName) = *Imp;
- return new (Importer.getToContext()) PredefinedExpr(
- Importer.Import(E->getLocStart()), T, E->getIdentType(), SL);
+ return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType,
+ E->getIdentKind(), ToFunctionName);
}
-Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
- auto *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
- if (!ToD)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
+ auto Imp = importSeq(
+ E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDecl(),
+ E->getLocation(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
+
+ NestedNameSpecifierLoc ToQualifierLoc;
+ SourceLocation ToTemplateKeywordLoc, ToLocation;
+ ValueDecl *ToDecl;
+ QualType ToType;
+ std::tie(ToQualifierLoc, ToTemplateKeywordLoc, ToDecl, ToLocation, ToType) =
+ *Imp;
- NamedDecl *FoundD = nullptr;
+ NamedDecl *ToFoundD = nullptr;
if (E->getDecl() != E->getFoundDecl()) {
- FoundD = cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl()));
- if (!FoundD)
- return nullptr;
+ auto FoundDOrErr = import(E->getFoundDecl());
+ if (!FoundDOrErr)
+ return FoundDOrErr.takeError();
+ ToFoundD = *FoundDOrErr;
}
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
TemplateArgumentListInfo ToTAInfo;
- TemplateArgumentListInfo *ResInfo = nullptr;
+ TemplateArgumentListInfo *ToResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
- if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
- return nullptr;
- ResInfo = &ToTAInfo;
+ if (Error Err =
+ ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+ return std::move(Err);
+ ToResInfo = &ToTAInfo;
}
- DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
- Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()),
- ToD,
- E->refersToEnclosingVariableOrCapture(),
- Importer.Import(E->getLocation()),
- T, E->getValueKind(),
- FoundD, ResInfo);
+ auto *ToE = DeclRefExpr::Create(
+ Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl,
+ E->refersToEnclosingVariableOrCapture(), ToLocation, ToType,
+ E->getValueKind(), ToFoundD, ToResInfo);
if (E->hadMultipleCandidates())
- DRE->setHadMultipleCandidates(true);
- return DRE;
-}
-
-Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- return new (Importer.getToContext()) ImplicitValueInitExpr(T);
+ ToE->setHadMultipleCandidates(true);
+ return ToE;
}
-ASTNodeImporter::Designator
-ASTNodeImporter::ImportDesignator(const Designator &D) {
- if (D.isFieldDesignator()) {
- IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName());
- // Caller checks for import error
- return Designator(ToFieldName, Importer.Import(D.getDotLoc()),
- Importer.Import(D.getFieldLoc()));
- }
- if (D.isArrayDesignator())
- return Designator(D.getFirstExprIndex(),
- Importer.Import(D.getLBracketLoc()),
- Importer.Import(D.getRBracketLoc()));
+ExpectedStmt ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+ ExpectedType TypeOrErr = import(E->getType());
+ if (!TypeOrErr)
+ return TypeOrErr.takeError();
- assert(D.isArrayRangeDesignator());
- return Designator(D.getFirstExprIndex(),
- Importer.Import(D.getLBracketLoc()),
- Importer.Import(D.getEllipsisLoc()),
- Importer.Import(D.getRBracketLoc()));
+ return new (Importer.getToContext()) ImplicitValueInitExpr(*TypeOrErr);
}
+ExpectedStmt ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ ExpectedExpr ToInitOrErr = import(E->getInit());
+ if (!ToInitOrErr)
+ return ToInitOrErr.takeError();
-Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) {
- auto *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit()));
- if (!Init)
- return nullptr;
+ ExpectedSLoc ToEqualOrColonLocOrErr = import(E->getEqualOrColonLoc());
+ if (!ToEqualOrColonLocOrErr)
+ return ToEqualOrColonLocOrErr.takeError();
- SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1);
+ SmallVector<Expr *, 4> ToIndexExprs(E->getNumSubExprs() - 1);
// List elements from the second, the first is Init itself
- for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) {
- if (auto *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I))))
- IndexExprs[I - 1] = Arg;
+ for (unsigned I = 1, N = E->getNumSubExprs(); I < N; I++) {
+ if (ExpectedExpr ToArgOrErr = import(E->getSubExpr(I)))
+ ToIndexExprs[I - 1] = *ToArgOrErr;
else
- return nullptr;
+ return ToArgOrErr.takeError();
}
- SmallVector<Designator, 4> Designators(DIE->size());
- llvm::transform(DIE->designators(), Designators.begin(),
- [this](const Designator &D) -> Designator {
- return ImportDesignator(D);
- });
-
- for (const auto &D : DIE->designators())
- if (D.isFieldDesignator() && !D.getFieldName())
- return nullptr;
+ SmallVector<Designator, 4> ToDesignators(E->size());
+ if (Error Err = ImportContainerChecked(E->designators(), ToDesignators))
+ return std::move(Err);
return DesignatedInitExpr::Create(
- Importer.getToContext(), Designators,
- IndexExprs, Importer.Import(DIE->getEqualOrColonLoc()),
- DIE->usesGNUSyntax(), Init);
+ Importer.getToContext(), ToDesignators,
+ ToIndexExprs, *ToEqualOrColonLocOrErr,
+ E->usesGNUSyntax(), *ToInitOrErr);
}
-Expr *ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt
+ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- return new (Importer.getToContext())
- CXXNullPtrLiteralExpr(T, Importer.Import(E->getLocation()));
+ ExpectedSLoc ToLocationOrErr = import(E->getLocation());
+ if (!ToLocationOrErr)
+ return ToLocationOrErr.takeError();
+
+ return new (Importer.getToContext()) CXXNullPtrLiteralExpr(
+ *ToTypeOrErr, *ToLocationOrErr);
}
-Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- return IntegerLiteral::Create(Importer.getToContext(),
- E->getValue(), T,
- Importer.Import(E->getLocation()));
+ ExpectedSLoc ToLocationOrErr = import(E->getLocation());
+ if (!ToLocationOrErr)
+ return ToLocationOrErr.takeError();
+
+ return IntegerLiteral::Create(
+ Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr);
}
-Expr *ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
- return FloatingLiteral::Create(Importer.getToContext(),
- E->getValue(), E->isExact(), T,
- Importer.Import(E->getLocation()));
+ExpectedStmt ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+
+ ExpectedSLoc ToLocationOrErr = import(E->getLocation());
+ if (!ToLocationOrErr)
+ return ToLocationOrErr.takeError();
+
+ return FloatingLiteral::Create(
+ Importer.getToContext(), E->getValue(), E->isExact(),
+ *ToTypeOrErr, *ToLocationOrErr);
}
-Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+ auto ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+
+ ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
+ if (!ToSubExprOrErr)
+ return ToSubExprOrErr.takeError();
- return new (Importer.getToContext()) CharacterLiteral(E->getValue(),
- E->getKind(), T,
- Importer.Import(E->getLocation()));
+ return new (Importer.getToContext()) ImaginaryLiteral(
+ *ToSubExprOrErr, *ToTypeOrErr);
}
-Expr *ASTNodeImporter::VisitStringLiteral(StringLiteral *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- SmallVector<SourceLocation, 4> Locations(E->getNumConcatenated());
- ImportArray(E->tokloc_begin(), E->tokloc_end(), Locations.begin());
+ ExpectedSLoc ToLocationOrErr = import(E->getLocation());
+ if (!ToLocationOrErr)
+ return ToLocationOrErr.takeError();
- return StringLiteral::Create(Importer.getToContext(), E->getBytes(),
- E->getKind(), E->isPascal(), T,
- Locations.data(), Locations.size());
+ return new (Importer.getToContext()) CharacterLiteral(
+ E->getValue(), E->getKind(), *ToTypeOrErr, *ToLocationOrErr);
}
-Expr *ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitStringLiteral(StringLiteral *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- TypeSourceInfo *TInfo = Importer.Import(E->getTypeSourceInfo());
- if (!TInfo)
- return nullptr;
+ SmallVector<SourceLocation, 4> ToLocations(E->getNumConcatenated());
+ if (Error Err = ImportArrayChecked(
+ E->tokloc_begin(), E->tokloc_end(), ToLocations.begin()))
+ return std::move(Err);
- Expr *Init = Importer.Import(E->getInitializer());
- if (!Init)
- return nullptr;
+ return StringLiteral::Create(
+ Importer.getToContext(), E->getBytes(), E->getKind(), E->isPascal(),
+ *ToTypeOrErr, ToLocations.data(), ToLocations.size());
+}
+
+ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ auto Imp = importSeq(
+ E->getLParenLoc(), E->getTypeSourceInfo(), E->getType(),
+ E->getInitializer());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToLParenLoc;
+ TypeSourceInfo *ToTypeSourceInfo;
+ QualType ToType;
+ Expr *ToInitializer;
+ std::tie(ToLParenLoc, ToTypeSourceInfo, ToType, ToInitializer) = *Imp;
return new (Importer.getToContext()) CompoundLiteralExpr(
- Importer.Import(E->getLParenLoc()), TInfo, T, E->getValueKind(),
- Init, E->isFileScope());
+ ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(),
+ ToInitializer, E->isFileScope());
}
-Expr *ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {
+ auto Imp = importSeq(
+ E->getBuiltinLoc(), E->getType(), E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
- SmallVector<Expr *, 6> Exprs(E->getNumSubExprs());
- if (ImportArrayChecked(
- E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(),
- Exprs.begin()))
- return nullptr;
+ SourceLocation ToBuiltinLoc, ToRParenLoc;
+ QualType ToType;
+ std::tie(ToBuiltinLoc, ToType, ToRParenLoc) = *Imp;
+
+ SmallVector<Expr *, 6> ToExprs(E->getNumSubExprs());
+ if (Error Err = ImportArrayChecked(
+ E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(),
+ ToExprs.begin()))
+ return std::move(Err);
return new (Importer.getToContext()) AtomicExpr(
- Importer.Import(E->getBuiltinLoc()), Exprs, T, E->getOp(),
- Importer.Import(E->getRParenLoc()));
+ ToBuiltinLoc, ToExprs, ToType, E->getOp(), ToRParenLoc);
}
-Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) {
+ auto Imp = importSeq(
+ E->getAmpAmpLoc(), E->getLabelLoc(), E->getLabel(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
- auto *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel()));
- if (!ToLabel)
- return nullptr;
+ SourceLocation ToAmpAmpLoc, ToLabelLoc;
+ LabelDecl *ToLabel;
+ QualType ToType;
+ std::tie(ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType) = *Imp;
return new (Importer.getToContext()) AddrLabelExpr(
- Importer.Import(E->getAmpAmpLoc()), Importer.Import(E->getLabelLoc()),
- ToLabel, T);
+ ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType);
}
-Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) {
+ auto Imp = importSeq(E->getSubExpr());
+ if (!Imp)
+ return Imp.takeError();
+
+ Expr *ToSubExpr;
+ std::tie(ToSubExpr) = *Imp;
+
+ return ConstantExpr::Create(Importer.getToContext(), ToSubExpr);
+}
+
+ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
+ auto Imp = importSeq(E->getLParen(), E->getRParen(), E->getSubExpr());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToLParen, ToRParen;
+ Expr *ToSubExpr;
+ std::tie(ToLParen, ToRParen, ToSubExpr) = *Imp;
return new (Importer.getToContext())
- ParenExpr(Importer.Import(E->getLParen()),
- Importer.Import(E->getRParen()),
- SubExpr);
+ ParenExpr(ToLParen, ToRParen, ToSubExpr);
}
-Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
- SmallVector<Expr *, 4> Exprs(E->getNumExprs());
- if (ImportContainerChecked(E->exprs(), Exprs))
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
+ SmallVector<Expr *, 4> ToExprs(E->getNumExprs());
+ if (Error Err = ImportContainerChecked(E->exprs(), ToExprs))
+ return std::move(Err);
+
+ ExpectedSLoc ToLParenLocOrErr = import(E->getLParenLoc());
+ if (!ToLParenLocOrErr)
+ return ToLParenLocOrErr.takeError();
- return new (Importer.getToContext()) ParenListExpr(
- Importer.getToContext(), Importer.Import(E->getLParenLoc()),
- Exprs, Importer.Import(E->getLParenLoc()));
+ ExpectedSLoc ToRParenLocOrErr = import(E->getRParenLoc());
+ if (!ToRParenLocOrErr)
+ return ToRParenLocOrErr.takeError();
+
+ return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr,
+ ToExprs, *ToRParenLocOrErr);
}
-Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
+ auto Imp = importSeq(
+ E->getSubStmt(), E->getType(), E->getLParenLoc(), E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
- auto *ToSubStmt = cast_or_null<CompoundStmt>(
- Importer.Import(E->getSubStmt()));
- if (!ToSubStmt && E->getSubStmt())
- return nullptr;
+ CompoundStmt *ToSubStmt;
+ QualType ToType;
+ SourceLocation ToLParenLoc, ToRParenLoc;
+ std::tie(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc) = *Imp;
- return new (Importer.getToContext()) StmtExpr(ToSubStmt, T,
- Importer.Import(E->getLParenLoc()), Importer.Import(E->getRParenLoc()));
+ return new (Importer.getToContext()) StmtExpr(
+ ToSubStmt, ToType, ToLParenLoc, ToRParenLoc);
}
-Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
+ auto Imp = importSeq(
+ E->getSubExpr(), E->getType(), E->getOperatorLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
- return nullptr;
+ Expr *ToSubExpr;
+ QualType ToType;
+ SourceLocation ToOperatorLoc;
+ std::tie(ToSubExpr, ToType, ToOperatorLoc) = *Imp;
return new (Importer.getToContext()) UnaryOperator(
- SubExpr, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(),
- Importer.Import(E->getOperatorLoc()), E->canOverflow());
+ ToSubExpr, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(),
+ ToOperatorLoc, E->canOverflow());
}
-Expr *
+ExpectedStmt
ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
- QualType ResultType = Importer.Import(E->getType());
+ auto Imp = importSeq(E->getType(), E->getOperatorLoc(), E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ QualType ToType;
+ SourceLocation ToOperatorLoc, ToRParenLoc;
+ std::tie(ToType, ToOperatorLoc, ToRParenLoc) = *Imp;
if (E->isArgumentType()) {
- TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo());
- if (!TInfo)
- return nullptr;
+ Expected<TypeSourceInfo *> ToArgumentTypeInfoOrErr =
+ import(E->getArgumentTypeInfo());
+ if (!ToArgumentTypeInfoOrErr)
+ return ToArgumentTypeInfoOrErr.takeError();
- return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
- TInfo, ResultType,
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getRParenLoc()));
+ return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(
+ E->getKind(), *ToArgumentTypeInfoOrErr, ToType, ToOperatorLoc,
+ ToRParenLoc);
}
- Expr *SubExpr = Importer.Import(E->getArgumentExpr());
- if (!SubExpr)
- return nullptr;
+ ExpectedExpr ToArgumentExprOrErr = import(E->getArgumentExpr());
+ if (!ToArgumentExprOrErr)
+ return ToArgumentExprOrErr.takeError();
- return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(),
- SubExpr, ResultType,
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getRParenLoc()));
+ return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(
+ E->getKind(), *ToArgumentExprOrErr, ToType, ToOperatorLoc, ToRParenLoc);
}
-Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
+ auto Imp = importSeq(
+ E->getLHS(), E->getRHS(), E->getType(), E->getOperatorLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *LHS = Importer.Import(E->getLHS());
- if (!LHS)
- return nullptr;
+ Expr *ToLHS, *ToRHS;
+ QualType ToType;
+ SourceLocation ToOperatorLoc;
+ std::tie(ToLHS, ToRHS, ToType, ToOperatorLoc) = *Imp;
- Expr *RHS = Importer.Import(E->getRHS());
- if (!RHS)
- return nullptr;
-
- return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),
- T, E->getValueKind(),
- E->getObjectKind(),
- Importer.Import(E->getOperatorLoc()),
- E->getFPFeatures());
+ return new (Importer.getToContext()) BinaryOperator(
+ ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
+ E->getObjectKind(), ToOperatorLoc, E->getFPFeatures());
}
-Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- Expr *ToLHS = Importer.Import(E->getLHS());
- if (!ToLHS)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) {
+ auto Imp = importSeq(
+ E->getCond(), E->getQuestionLoc(), E->getLHS(), E->getColonLoc(),
+ E->getRHS(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
- Expr *ToRHS = Importer.Import(E->getRHS());
- if (!ToRHS)
- return nullptr;
-
- Expr *ToCond = Importer.Import(E->getCond());
- if (!ToCond)
- return nullptr;
+ Expr *ToCond, *ToLHS, *ToRHS;
+ SourceLocation ToQuestionLoc, ToColonLoc;
+ QualType ToType;
+ std::tie(ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType) = *Imp;
return new (Importer.getToContext()) ConditionalOperator(
- ToCond, Importer.Import(E->getQuestionLoc()),
- ToLHS, Importer.Import(E->getColonLoc()),
- ToRHS, T, E->getValueKind(), E->getObjectKind());
+ ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType,
+ E->getValueKind(), E->getObjectKind());
}
-Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
+ExpectedStmt ASTNodeImporter::VisitBinaryConditionalOperator(
BinaryConditionalOperator *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- Expr *Common = Importer.Import(E->getCommon());
- if (!Common)
- return nullptr;
-
- Expr *Cond = Importer.Import(E->getCond());
- if (!Cond)
- return nullptr;
-
- auto *OpaqueValue = cast_or_null<OpaqueValueExpr>(
- Importer.Import(E->getOpaqueValue()));
- if (!OpaqueValue)
- return nullptr;
-
- Expr *TrueExpr = Importer.Import(E->getTrueExpr());
- if (!TrueExpr)
- return nullptr;
-
- Expr *FalseExpr = Importer.Import(E->getFalseExpr());
- if (!FalseExpr)
- return nullptr;
+ auto Imp = importSeq(
+ E->getCommon(), E->getOpaqueValue(), E->getCond(), E->getTrueExpr(),
+ E->getFalseExpr(), E->getQuestionLoc(), E->getColonLoc(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
+
+ Expr *ToCommon, *ToCond, *ToTrueExpr, *ToFalseExpr;
+ OpaqueValueExpr *ToOpaqueValue;
+ SourceLocation ToQuestionLoc, ToColonLoc;
+ QualType ToType;
+ std::tie(
+ ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, ToQuestionLoc,
+ ToColonLoc, ToType) = *Imp;
return new (Importer.getToContext()) BinaryConditionalOperator(
- Common, OpaqueValue, Cond, TrueExpr, FalseExpr,
- Importer.Import(E->getQuestionLoc()), Importer.Import(E->getColonLoc()),
- T, E->getValueKind(), E->getObjectKind());
-}
-
-Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo());
- if (!ToQueried)
- return nullptr;
-
- Expr *Dim = Importer.Import(E->getDimensionExpression());
- if (!Dim && E->getDimensionExpression())
- return nullptr;
+ ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr,
+ ToQuestionLoc, ToColonLoc, ToType, E->getValueKind(),
+ E->getObjectKind());
+}
+
+ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+ auto Imp = importSeq(
+ E->getBeginLoc(), E->getQueriedTypeSourceInfo(),
+ E->getDimensionExpression(), E->getEndLoc(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToBeginLoc, ToEndLoc;
+ TypeSourceInfo *ToQueriedTypeSourceInfo;
+ Expr *ToDimensionExpression;
+ QualType ToType;
+ std::tie(
+ ToBeginLoc, ToQueriedTypeSourceInfo, ToDimensionExpression, ToEndLoc,
+ ToType) = *Imp;
return new (Importer.getToContext()) ArrayTypeTraitExpr(
- Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
- E->getValue(), Dim, Importer.Import(E->getLocEnd()), T);
+ ToBeginLoc, E->getTrait(), ToQueriedTypeSourceInfo, E->getValue(),
+ ToDimensionExpression, ToEndLoc, ToType);
}
-Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ auto Imp = importSeq(
+ E->getBeginLoc(), E->getQueriedExpression(), E->getEndLoc(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
- Expr *ToQueried = Importer.Import(E->getQueriedExpression());
- if (!ToQueried)
- return nullptr;
+ SourceLocation ToBeginLoc, ToEndLoc;
+ Expr *ToQueriedExpression;
+ QualType ToType;
+ std::tie(ToBeginLoc, ToQueriedExpression, ToEndLoc, ToType) = *Imp;
return new (Importer.getToContext()) ExpressionTraitExpr(
- Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
- E->getValue(), Importer.Import(E->getLocEnd()), T);
+ ToBeginLoc, E->getTrait(), ToQueriedExpression, E->getValue(),
+ ToEndLoc, ToType);
}
-Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ auto Imp = importSeq(
+ E->getLocation(), E->getType(), E->getSourceExpr());
+ if (!Imp)
+ return Imp.takeError();
- Expr *SourceExpr = Importer.Import(E->getSourceExpr());
- if (!SourceExpr && E->getSourceExpr())
- return nullptr;
+ SourceLocation ToLocation;
+ QualType ToType;
+ Expr *ToSourceExpr;
+ std::tie(ToLocation, ToType, ToSourceExpr) = *Imp;
return new (Importer.getToContext()) OpaqueValueExpr(
- Importer.Import(E->getLocation()), T, E->getValueKind(),
- E->getObjectKind(), SourceExpr);
+ ToLocation, ToType, E->getValueKind(), E->getObjectKind(), ToSourceExpr);
}
-Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- Expr *ToLHS = Importer.Import(E->getLHS());
- if (!ToLHS)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ auto Imp = importSeq(
+ E->getLHS(), E->getRHS(), E->getType(), E->getRBracketLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *ToRHS = Importer.Import(E->getRHS());
- if (!ToRHS)
- return nullptr;
+ Expr *ToLHS, *ToRHS;
+ SourceLocation ToRBracketLoc;
+ QualType ToType;
+ std::tie(ToLHS, ToRHS, ToType, ToRBracketLoc) = *Imp;
return new (Importer.getToContext()) ArraySubscriptExpr(
- ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(),
- Importer.Import(E->getRBracketLoc()));
+ ToLHS, ToRHS, ToType, E->getValueKind(), E->getObjectKind(),
+ ToRBracketLoc);
}
-Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- QualType CompLHSType = Importer.Import(E->getComputationLHSType());
- if (CompLHSType.isNull())
- return nullptr;
-
- QualType CompResultType = Importer.Import(E->getComputationResultType());
- if (CompResultType.isNull())
- return nullptr;
-
- Expr *LHS = Importer.Import(E->getLHS());
- if (!LHS)
- return nullptr;
+ExpectedStmt
+ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+ auto Imp = importSeq(
+ E->getLHS(), E->getRHS(), E->getType(), E->getComputationLHSType(),
+ E->getComputationResultType(), E->getOperatorLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *RHS = Importer.Import(E->getRHS());
- if (!RHS)
- return nullptr;
+ Expr *ToLHS, *ToRHS;
+ QualType ToType, ToComputationLHSType, ToComputationResultType;
+ SourceLocation ToOperatorLoc;
+ std::tie(ToLHS, ToRHS, ToType, ToComputationLHSType, ToComputationResultType,
+ ToOperatorLoc) = *Imp;
- return new (Importer.getToContext())
- CompoundAssignOperator(LHS, RHS, E->getOpcode(),
- T, E->getValueKind(),
- E->getObjectKind(),
- CompLHSType, CompResultType,
- Importer.Import(E->getOperatorLoc()),
- E->getFPFeatures());
+ return new (Importer.getToContext()) CompoundAssignOperator(
+ ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
+ E->getObjectKind(), ToComputationLHSType, ToComputationResultType,
+ ToOperatorLoc, E->getFPFeatures());
}
-bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) {
+Expected<CXXCastPath>
+ASTNodeImporter::ImportCastPath(CastExpr *CE) {
+ CXXCastPath Path;
for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) {
- if (CXXBaseSpecifier *Spec = Importer.Import(*I))
- Path.push_back(Spec);
+ if (auto SpecOrErr = import(*I))
+ Path.push_back(*SpecOrErr);
else
- return true;
+ return SpecOrErr.takeError();
}
- return false;
+ return Path;
}
-Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
- return nullptr;
+ ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
+ if (!ToSubExprOrErr)
+ return ToSubExprOrErr.takeError();
- CXXCastPath BasePath;
- if (ImportCastPath(E, BasePath))
- return nullptr;
+ Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E);
+ if (!ToBasePathOrErr)
+ return ToBasePathOrErr.takeError();
- return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
- SubExpr, &BasePath, E->getValueKind());
+ return ImplicitCastExpr::Create(
+ Importer.getToContext(), *ToTypeOrErr, E->getCastKind(), *ToSubExprOrErr,
+ &(*ToBasePathOrErr), E->getValueKind());
}
-Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+ auto Imp1 = importSeq(
+ E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten());
+ if (!Imp1)
+ return Imp1.takeError();
- TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten());
- if (!TInfo && E->getTypeInfoAsWritten())
- return nullptr;
+ QualType ToType;
+ Expr *ToSubExpr;
+ TypeSourceInfo *ToTypeInfoAsWritten;
+ std::tie(ToType, ToSubExpr, ToTypeInfoAsWritten) = *Imp1;
- CXXCastPath BasePath;
- if (ImportCastPath(E, BasePath))
- return nullptr;
+ Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E);
+ if (!ToBasePathOrErr)
+ return ToBasePathOrErr.takeError();
+ CXXCastPath *ToBasePath = &(*ToBasePathOrErr);
switch (E->getStmtClass()) {
case Stmt::CStyleCastExprClass: {
auto *CCE = cast<CStyleCastExpr>(E);
- return CStyleCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), E->getCastKind(),
- SubExpr, &BasePath, TInfo,
- Importer.Import(CCE->getLParenLoc()),
- Importer.Import(CCE->getRParenLoc()));
+ ExpectedSLoc ToLParenLocOrErr = import(CCE->getLParenLoc());
+ if (!ToLParenLocOrErr)
+ return ToLParenLocOrErr.takeError();
+ ExpectedSLoc ToRParenLocOrErr = import(CCE->getRParenLoc());
+ if (!ToRParenLocOrErr)
+ return ToRParenLocOrErr.takeError();
+ return CStyleCastExpr::Create(
+ Importer.getToContext(), ToType, E->getValueKind(), E->getCastKind(),
+ ToSubExpr, ToBasePath, ToTypeInfoAsWritten, *ToLParenLocOrErr,
+ *ToRParenLocOrErr);
}
case Stmt::CXXFunctionalCastExprClass: {
auto *FCE = cast<CXXFunctionalCastExpr>(E);
- return CXXFunctionalCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), TInfo,
- E->getCastKind(), SubExpr, &BasePath,
- Importer.Import(FCE->getLParenLoc()),
- Importer.Import(FCE->getRParenLoc()));
+ ExpectedSLoc ToLParenLocOrErr = import(FCE->getLParenLoc());
+ if (!ToLParenLocOrErr)
+ return ToLParenLocOrErr.takeError();
+ ExpectedSLoc ToRParenLocOrErr = import(FCE->getRParenLoc());
+ if (!ToRParenLocOrErr)
+ return ToRParenLocOrErr.takeError();
+ return CXXFunctionalCastExpr::Create(
+ Importer.getToContext(), ToType, E->getValueKind(), ToTypeInfoAsWritten,
+ E->getCastKind(), ToSubExpr, ToBasePath, *ToLParenLocOrErr,
+ *ToRParenLocOrErr);
}
case Stmt::ObjCBridgedCastExprClass: {
- auto *OCE = cast<ObjCBridgedCastExpr>(E);
- return new (Importer.getToContext()) ObjCBridgedCastExpr(
- Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(),
- E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()),
- TInfo, SubExpr);
+ auto *OCE = cast<ObjCBridgedCastExpr>(E);
+ ExpectedSLoc ToLParenLocOrErr = import(OCE->getLParenLoc());
+ if (!ToLParenLocOrErr)
+ return ToLParenLocOrErr.takeError();
+ ExpectedSLoc ToBridgeKeywordLocOrErr = import(OCE->getBridgeKeywordLoc());
+ if (!ToBridgeKeywordLocOrErr)
+ return ToBridgeKeywordLocOrErr.takeError();
+ return new (Importer.getToContext()) ObjCBridgedCastExpr(
+ *ToLParenLocOrErr, OCE->getBridgeKind(), E->getCastKind(),
+ *ToBridgeKeywordLocOrErr, ToTypeInfoAsWritten, ToSubExpr);
}
default:
- break; // just fall through
- }
-
- auto *Named = cast<CXXNamedCastExpr>(E);
- SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()),
- RParenLoc = Importer.Import(Named->getRParenLoc());
- SourceRange Brackets = Importer.Import(Named->getAngleBrackets());
-
- switch (E->getStmtClass()) {
- case Stmt::CXXStaticCastExprClass:
- return CXXStaticCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), E->getCastKind(),
- SubExpr, &BasePath, TInfo,
- ExprLoc, RParenLoc, Brackets);
-
- case Stmt::CXXDynamicCastExprClass:
- return CXXDynamicCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), E->getCastKind(),
- SubExpr, &BasePath, TInfo,
- ExprLoc, RParenLoc, Brackets);
-
- case Stmt::CXXReinterpretCastExprClass:
- return CXXReinterpretCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), E->getCastKind(),
- SubExpr, &BasePath, TInfo,
- ExprLoc, RParenLoc, Brackets);
-
- case Stmt::CXXConstCastExprClass:
- return CXXConstCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), SubExpr, TInfo, ExprLoc,
- RParenLoc, Brackets);
- default:
llvm_unreachable("Cast expression of unsupported type!");
- return nullptr;
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
}
-Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) {
- QualType T = Importer.Import(OE->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) {
+ SmallVector<OffsetOfNode, 4> ToNodes;
+ for (int I = 0, N = E->getNumComponents(); I < N; ++I) {
+ const OffsetOfNode &FromNode = E->getComponent(I);
- SmallVector<OffsetOfNode, 4> Nodes;
- for (int I = 0, E = OE->getNumComponents(); I < E; ++I) {
- const OffsetOfNode &Node = OE->getComponent(I);
+ SourceLocation ToBeginLoc, ToEndLoc;
+ if (FromNode.getKind() != OffsetOfNode::Base) {
+ auto Imp = importSeq(FromNode.getBeginLoc(), FromNode.getEndLoc());
+ if (!Imp)
+ return Imp.takeError();
+ std::tie(ToBeginLoc, ToEndLoc) = *Imp;
+ }
- switch (Node.getKind()) {
+ switch (FromNode.getKind()) {
case OffsetOfNode::Array:
- Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()),
- Node.getArrayExprIndex(),
- Importer.Import(Node.getLocEnd())));
+ ToNodes.push_back(
+ OffsetOfNode(ToBeginLoc, FromNode.getArrayExprIndex(), ToEndLoc));
break;
-
case OffsetOfNode::Base: {
- CXXBaseSpecifier *BS = Importer.Import(Node.getBase());
- if (!BS && Node.getBase())
- return nullptr;
- Nodes.push_back(OffsetOfNode(BS));
+ auto ToBSOrErr = import(FromNode.getBase());
+ if (!ToBSOrErr)
+ return ToBSOrErr.takeError();
+ ToNodes.push_back(OffsetOfNode(*ToBSOrErr));
break;
}
case OffsetOfNode::Field: {
- auto *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField()));
- if (!FD)
- return nullptr;
- Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD,
- Importer.Import(Node.getLocEnd())));
+ auto ToFieldOrErr = import(FromNode.getField());
+ if (!ToFieldOrErr)
+ return ToFieldOrErr.takeError();
+ ToNodes.push_back(OffsetOfNode(ToBeginLoc, *ToFieldOrErr, ToEndLoc));
break;
}
case OffsetOfNode::Identifier: {
- IdentifierInfo *ToII = Importer.Import(Node.getFieldName());
- if (!ToII)
- return nullptr;
- Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII,
- Importer.Import(Node.getLocEnd())));
+ IdentifierInfo *ToII = Importer.Import(FromNode.getFieldName());
+ ToNodes.push_back(OffsetOfNode(ToBeginLoc, ToII, ToEndLoc));
break;
}
}
}
- SmallVector<Expr *, 4> Exprs(OE->getNumExpressions());
- for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) {
- Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I));
- if (!ToIndexExpr)
- return nullptr;
- Exprs[I] = ToIndexExpr;
+ SmallVector<Expr *, 4> ToExprs(E->getNumExpressions());
+ for (int I = 0, N = E->getNumExpressions(); I < N; ++I) {
+ ExpectedExpr ToIndexExprOrErr = import(E->getIndexExpr(I));
+ if (!ToIndexExprOrErr)
+ return ToIndexExprOrErr.takeError();
+ ToExprs[I] = *ToIndexExprOrErr;
}
- TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo());
- if (!TInfo && OE->getTypeSourceInfo())
- return nullptr;
+ auto Imp = importSeq(
+ E->getType(), E->getTypeSourceInfo(), E->getOperatorLoc(),
+ E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ SourceLocation ToOperatorLoc, ToRParenLoc;
+ std::tie(ToType, ToTypeSourceInfo, ToOperatorLoc, ToRParenLoc) = *Imp;
- return OffsetOfExpr::Create(Importer.getToContext(), T,
- Importer.Import(OE->getOperatorLoc()),
- TInfo, Nodes, Exprs,
- Importer.Import(OE->getRParenLoc()));
+ return OffsetOfExpr::Create(
+ Importer.getToContext(), ToType, ToOperatorLoc, ToTypeSourceInfo, ToNodes,
+ ToExprs, ToRParenLoc);
}
-Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ auto Imp = importSeq(
+ E->getType(), E->getOperand(), E->getBeginLoc(), E->getEndLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *Operand = Importer.Import(E->getOperand());
- if (!Operand)
- return nullptr;
+ QualType ToType;
+ Expr *ToOperand;
+ SourceLocation ToBeginLoc, ToEndLoc;
+ std::tie(ToType, ToOperand, ToBeginLoc, ToEndLoc) = *Imp;
- CanThrowResult CanThrow;
+ CanThrowResult ToCanThrow;
if (E->isValueDependent())
- CanThrow = CT_Dependent;
+ ToCanThrow = CT_Dependent;
else
- CanThrow = E->getValue() ? CT_Can : CT_Cannot;
+ ToCanThrow = E->getValue() ? CT_Can : CT_Cannot;
return new (Importer.getToContext()) CXXNoexceptExpr(
- T, Operand, CanThrow,
- Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd()));
+ ToType, ToOperand, ToCanThrow, ToBeginLoc, ToEndLoc);
}
-Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
+ auto Imp = importSeq(E->getSubExpr(), E->getType(), E->getThrowLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr && E->getSubExpr())
- return nullptr;
+ Expr *ToSubExpr;
+ QualType ToType;
+ SourceLocation ToThrowLoc;
+ std::tie(ToSubExpr, ToType, ToThrowLoc) = *Imp;
return new (Importer.getToContext()) CXXThrowExpr(
- SubExpr, T, Importer.Import(E->getThrowLoc()),
- E->isThrownVariableInScope());
+ ToSubExpr, ToType, ToThrowLoc, E->isThrownVariableInScope());
}
-Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
- auto *Param = cast_or_null<ParmVarDecl>(Importer.Import(E->getParam()));
- if (!Param)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ ExpectedSLoc ToUsedLocOrErr = import(E->getUsedLocation());
+ if (!ToUsedLocOrErr)
+ return ToUsedLocOrErr.takeError();
+
+ auto ToParamOrErr = import(E->getParam());
+ if (!ToParamOrErr)
+ return ToParamOrErr.takeError();
return CXXDefaultArgExpr::Create(
- Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param);
+ Importer.getToContext(), *ToUsedLocOrErr, *ToParamOrErr);
}
-Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt
+ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ auto Imp = importSeq(
+ E->getType(), E->getTypeSourceInfo(), E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
- TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo());
- if (!TypeInfo)
- return nullptr;
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ SourceLocation ToRParenLoc;
+ std::tie(ToType, ToTypeSourceInfo, ToRParenLoc) = *Imp;
return new (Importer.getToContext()) CXXScalarValueInitExpr(
- T, TypeInfo, Importer.Import(E->getRParenLoc()));
+ ToType, ToTypeSourceInfo, ToRParenLoc);
}
-Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
- Expr *SubExpr = Importer.Import(E->getSubExpr());
- if (!SubExpr)
- return nullptr;
+ExpectedStmt
+ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
+ if (!ToSubExprOrErr)
+ return ToSubExprOrErr.takeError();
- auto *Dtor = cast_or_null<CXXDestructorDecl>(
- Importer.Import(const_cast<CXXDestructorDecl *>(
- E->getTemporary()->getDestructor())));
- if (!Dtor)
- return nullptr;
+ auto ToDtorOrErr = import(E->getTemporary()->getDestructor());
+ if (!ToDtorOrErr)
+ return ToDtorOrErr.takeError();
ASTContext &ToCtx = Importer.getToContext();
- CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor);
- return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr);
+ CXXTemporary *Temp = CXXTemporary::Create(ToCtx, *ToDtorOrErr);
+ return CXXBindTemporaryExpr::Create(ToCtx, Temp, *ToSubExprOrErr);
}
-Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
- QualType T = Importer.Import(CE->getType());
- if (T.isNull())
- return nullptr;
-
- TypeSourceInfo *TInfo = Importer.Import(CE->getTypeSourceInfo());
- if (!TInfo)
- return nullptr;
+ExpectedStmt
+ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
+ auto Imp = importSeq(
+ E->getConstructor(), E->getType(), E->getTypeSourceInfo(),
+ E->getParenOrBraceRange());
+ if (!Imp)
+ return Imp.takeError();
- SmallVector<Expr *, 8> Args(CE->getNumArgs());
- if (ImportContainerChecked(CE->arguments(), Args))
- return nullptr;
+ CXXConstructorDecl *ToConstructor;
+ QualType ToType;
+ TypeSourceInfo *ToTypeSourceInfo;
+ SourceRange ToParenOrBraceRange;
+ std::tie(ToConstructor, ToType, ToTypeSourceInfo, ToParenOrBraceRange) = *Imp;
- auto *Ctor = cast_or_null<CXXConstructorDecl>(
- Importer.Import(CE->getConstructor()));
- if (!Ctor)
- return nullptr;
+ SmallVector<Expr *, 8> ToArgs(E->getNumArgs());
+ if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
+ return std::move(Err);
- return new (Importer.getToContext()) CXXTemporaryObjectExpr(
- Importer.getToContext(), Ctor, T, TInfo, Args,
- Importer.Import(CE->getParenOrBraceRange()), CE->hadMultipleCandidates(),
- CE->isListInitialization(), CE->isStdInitListInitialization(),
- CE->requiresZeroInitialization());
+ return CXXTemporaryObjectExpr::Create(
+ Importer.getToContext(), ToConstructor, ToType, ToTypeSourceInfo, ToArgs,
+ ToParenOrBraceRange, E->hadMultipleCandidates(),
+ E->isListInitialization(), E->isStdInitListInitialization(),
+ E->requiresZeroInitialization());
}
-Expr *
+ExpectedStmt
ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ auto Imp = importSeq(
+ E->getType(), E->GetTemporaryExpr(), E->getExtendingDecl());
+ if (!Imp)
+ return Imp.takeError();
- Expr *TempE = Importer.Import(E->GetTemporaryExpr());
- if (!TempE)
- return nullptr;
-
- auto *ExtendedBy = cast_or_null<ValueDecl>(
- Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl())));
- if (!ExtendedBy && E->getExtendingDecl())
- return nullptr;
+ QualType ToType;
+ Expr *ToTemporaryExpr;
+ const ValueDecl *ToExtendingDecl;
+ std::tie(ToType, ToTemporaryExpr, ToExtendingDecl) = *Imp;
auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
- T, TempE, E->isBoundToLvalueReference());
+ ToType, ToTemporaryExpr, E->isBoundToLvalueReference());
// FIXME: Should ManglingNumber get numbers associated with 'to' context?
- ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber());
+ ToMTE->setExtendingDecl(ToExtendingDecl, E->getManglingNumber());
return ToMTE;
}
-Expr *ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) {
+ auto Imp = importSeq(
+ E->getType(), E->getPattern(), E->getEllipsisLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *Pattern = Importer.Import(E->getPattern());
- if (!Pattern)
- return nullptr;
+ QualType ToType;
+ Expr *ToPattern;
+ SourceLocation ToEllipsisLoc;
+ std::tie(ToType, ToPattern, ToEllipsisLoc) = *Imp;
return new (Importer.getToContext()) PackExpansionExpr(
- T, Pattern, Importer.Import(E->getEllipsisLoc()),
- E->getNumExpansions());
+ ToType, ToPattern, ToEllipsisLoc, E->getNumExpansions());
}
-Expr *ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
- auto *Pack = cast_or_null<NamedDecl>(Importer.Import(E->getPack()));
- if (!Pack)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
+ auto Imp = importSeq(
+ E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
- Optional<unsigned> Length;
+ SourceLocation ToOperatorLoc, ToPackLoc, ToRParenLoc;
+ NamedDecl *ToPack;
+ std::tie(ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc) = *Imp;
+ Optional<unsigned> Length;
if (!E->isValueDependent())
Length = E->getPackLength();
- SmallVector<TemplateArgument, 8> PartialArguments;
+ SmallVector<TemplateArgument, 8> ToPartialArguments;
if (E->isPartiallySubstituted()) {
- if (ImportTemplateArguments(E->getPartialArguments().data(),
- E->getPartialArguments().size(),
- PartialArguments))
- return nullptr;
+ if (Error Err = ImportTemplateArguments(
+ E->getPartialArguments().data(),
+ E->getPartialArguments().size(),
+ ToPartialArguments))
+ return std::move(Err);
}
return SizeOfPackExpr::Create(
- Importer.getToContext(), Importer.Import(E->getOperatorLoc()), Pack,
- Importer.Import(E->getPackLoc()), Importer.Import(E->getRParenLoc()),
- Length, PartialArguments);
-}
-
-Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
- QualType T = Importer.Import(CE->getType());
- if (T.isNull())
- return nullptr;
-
- SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs());
- if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs))
- return nullptr;
-
- auto *OperatorNewDecl = cast_or_null<FunctionDecl>(
- Importer.Import(CE->getOperatorNew()));
- if (!OperatorNewDecl && CE->getOperatorNew())
- return nullptr;
-
- auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
- Importer.Import(CE->getOperatorDelete()));
- if (!OperatorDeleteDecl && CE->getOperatorDelete())
- return nullptr;
-
- Expr *ToInit = Importer.Import(CE->getInitializer());
- if (!ToInit && CE->getInitializer())
- return nullptr;
-
- TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo());
- if (!TInfo)
- return nullptr;
-
- Expr *ToArrSize = Importer.Import(CE->getArraySize());
- if (!ToArrSize && CE->getArraySize())
- return nullptr;
-
- return new (Importer.getToContext()) CXXNewExpr(
- Importer.getToContext(),
- CE->isGlobalNew(),
- OperatorNewDecl, OperatorDeleteDecl,
- CE->passAlignment(),
- CE->doesUsualArrayDeleteWantSize(),
- PlacementArgs,
- Importer.Import(CE->getTypeIdParens()),
- ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo,
- Importer.Import(CE->getSourceRange()),
- Importer.Import(CE->getDirectInitRange()));
-}
-
-Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
-
- auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
- Importer.Import(E->getOperatorDelete()));
- if (!OperatorDeleteDecl && E->getOperatorDelete())
- return nullptr;
-
- Expr *ToArg = Importer.Import(E->getArgument());
- if (!ToArg && E->getArgument())
- return nullptr;
+ Importer.getToContext(), ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc,
+ Length, ToPartialArguments);
+}
+
+
+ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) {
+ auto Imp = importSeq(
+ E->getOperatorNew(), E->getOperatorDelete(), E->getTypeIdParens(),
+ E->getArraySize(), E->getInitializer(), E->getType(),
+ E->getAllocatedTypeSourceInfo(), E->getSourceRange(),
+ E->getDirectInitRange());
+ if (!Imp)
+ return Imp.takeError();
+
+ FunctionDecl *ToOperatorNew, *ToOperatorDelete;
+ SourceRange ToTypeIdParens, ToSourceRange, ToDirectInitRange;
+ Expr *ToArraySize, *ToInitializer;
+ QualType ToType;
+ TypeSourceInfo *ToAllocatedTypeSourceInfo;
+ std::tie(
+ ToOperatorNew, ToOperatorDelete, ToTypeIdParens, ToArraySize, ToInitializer,
+ ToType, ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange) = *Imp;
+
+ SmallVector<Expr *, 4> ToPlacementArgs(E->getNumPlacementArgs());
+ if (Error Err =
+ ImportContainerChecked(E->placement_arguments(), ToPlacementArgs))
+ return std::move(Err);
+
+ return CXXNewExpr::Create(
+ Importer.getToContext(), E->isGlobalNew(), ToOperatorNew,
+ ToOperatorDelete, E->passAlignment(), E->doesUsualArrayDeleteWantSize(),
+ ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(),
+ ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange,
+ ToDirectInitRange);
+}
+
+ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ auto Imp = importSeq(
+ E->getType(), E->getOperatorDelete(), E->getArgument(), E->getBeginLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ QualType ToType;
+ FunctionDecl *ToOperatorDelete;
+ Expr *ToArgument;
+ SourceLocation ToBeginLoc;
+ std::tie(ToType, ToOperatorDelete, ToArgument, ToBeginLoc) = *Imp;
return new (Importer.getToContext()) CXXDeleteExpr(
- T, E->isGlobalDelete(),
- E->isArrayForm(),
- E->isArrayFormAsWritten(),
- E->doesUsualArrayDeleteWantSize(),
- OperatorDeleteDecl,
- ToArg,
- Importer.Import(E->getLocStart()));
+ ToType, E->isGlobalDelete(), E->isArrayForm(), E->isArrayFormAsWritten(),
+ E->doesUsualArrayDeleteWantSize(), ToOperatorDelete, ToArgument,
+ ToBeginLoc);
}
-Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ auto Imp = importSeq(
+ E->getType(), E->getLocation(), E->getConstructor(),
+ E->getParenOrBraceRange());
+ if (!Imp)
+ return Imp.takeError();
- auto *ToCCD =
- dyn_cast_or_null<CXXConstructorDecl>(Importer.Import(E->getConstructor()));
- if (!ToCCD)
- return nullptr;
+ QualType ToType;
+ SourceLocation ToLocation;
+ CXXConstructorDecl *ToConstructor;
+ SourceRange ToParenOrBraceRange;
+ std::tie(ToType, ToLocation, ToConstructor, ToParenOrBraceRange) = *Imp;
SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
- if (ImportContainerChecked(E->arguments(), ToArgs))
- return nullptr;
+ if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
+ return std::move(Err);
- return CXXConstructExpr::Create(Importer.getToContext(), T,
- Importer.Import(E->getLocation()),
- ToCCD, E->isElidable(),
- ToArgs, E->hadMultipleCandidates(),
- E->isListInitialization(),
- E->isStdInitListInitialization(),
- E->requiresZeroInitialization(),
- E->getConstructionKind(),
- Importer.Import(E->getParenOrBraceRange()));
+ return CXXConstructExpr::Create(
+ Importer.getToContext(), ToType, ToLocation, ToConstructor,
+ E->isElidable(), ToArgs, E->hadMultipleCandidates(),
+ E->isListInitialization(), E->isStdInitListInitialization(),
+ E->requiresZeroInitialization(), E->getConstructionKind(),
+ ToParenOrBraceRange);
}
-Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) {
- Expr *SubExpr = Importer.Import(EWC->getSubExpr());
- if (!SubExpr && EWC->getSubExpr())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) {
+ ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
+ if (!ToSubExprOrErr)
+ return ToSubExprOrErr.takeError();
- SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects());
- for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++)
- if (ExprWithCleanups::CleanupObject Obj =
- cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I))))
- Objs[I] = Obj;
- else
- return nullptr;
+ SmallVector<ExprWithCleanups::CleanupObject, 8> ToObjects(E->getNumObjects());
+ if (Error Err = ImportContainerChecked(E->getObjects(), ToObjects))
+ return std::move(Err);
- return ExprWithCleanups::Create(Importer.getToContext(),
- SubExpr, EWC->cleanupsHaveSideEffects(),
- Objs);
+ return ExprWithCleanups::Create(
+ Importer.getToContext(), *ToSubExprOrErr, E->cleanupsHaveSideEffects(),
+ ToObjects);
}
-Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+ auto Imp = importSeq(
+ E->getCallee(), E->getType(), E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *ToFn = Importer.Import(E->getCallee());
- if (!ToFn)
- return nullptr;
+ Expr *ToCallee;
+ QualType ToType;
+ SourceLocation ToRParenLoc;
+ std::tie(ToCallee, ToType, ToRParenLoc) = *Imp;
SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
- if (ImportContainerChecked(E->arguments(), ToArgs))
- return nullptr;
+ if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
+ return std::move(Err);
- return new (Importer.getToContext()) CXXMemberCallExpr(
- Importer.getToContext(), ToFn, ToArgs, T, E->getValueKind(),
- Importer.Import(E->getRParenLoc()));
+ return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs,
+ ToType, E->getValueKind(), ToRParenLoc);
}
-Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- return new (Importer.getToContext())
- CXXThisExpr(Importer.Import(E->getLocation()), T, E->isImplicit());
-}
-
-Expr *ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ ExpectedSLoc ToLocationOrErr = import(E->getLocation());
+ if (!ToLocationOrErr)
+ return ToLocationOrErr.takeError();
- return new (Importer.getToContext())
- CXXBoolLiteralExpr(E->getValue(), T, Importer.Import(E->getLocation()));
+ return new (Importer.getToContext()) CXXThisExpr(
+ *ToLocationOrErr, *ToTypeOrErr, E->isImplicit());
}
+ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
-Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ ExpectedSLoc ToLocationOrErr = import(E->getLocation());
+ if (!ToLocationOrErr)
+ return ToLocationOrErr.takeError();
- Expr *ToBase = Importer.Import(E->getBase());
- if (!ToBase && E->getBase())
- return nullptr;
+ return new (Importer.getToContext()) CXXBoolLiteralExpr(
+ E->getValue(), *ToTypeOrErr, *ToLocationOrErr);
+}
- auto *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl()));
- if (!ToMember && E->getMemberDecl())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
+ auto Imp1 = importSeq(
+ E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(),
+ E->getTemplateKeywordLoc(), E->getMemberDecl(), E->getType());
+ if (!Imp1)
+ return Imp1.takeError();
- auto *ToDecl =
- dyn_cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl()));
- if (!ToDecl && E->getFoundDecl().getDecl())
- return nullptr;
+ Expr *ToBase;
+ SourceLocation ToOperatorLoc, ToTemplateKeywordLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ ValueDecl *ToMemberDecl;
+ QualType ToType;
+ std::tie(
+ ToBase, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl,
+ ToType) = *Imp1;
+
+ auto Imp2 = importSeq(
+ E->getFoundDecl().getDecl(), E->getMemberNameInfo().getName(),
+ E->getMemberNameInfo().getLoc(), E->getLAngleLoc(), E->getRAngleLoc());
+ if (!Imp2)
+ return Imp2.takeError();
+ NamedDecl *ToDecl;
+ DeclarationName ToName;
+ SourceLocation ToLoc, ToLAngleLoc, ToRAngleLoc;
+ std::tie(ToDecl, ToName, ToLoc, ToLAngleLoc, ToRAngleLoc) = *Imp2;
DeclAccessPair ToFoundDecl =
DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess());
- DeclarationNameInfo ToMemberNameInfo(
- Importer.Import(E->getMemberNameInfo().getName()),
- Importer.Import(E->getMemberNameInfo().getLoc()));
+ DeclarationNameInfo ToMemberNameInfo(ToName, ToLoc);
if (E->hasExplicitTemplateArgs()) {
- return nullptr; // FIXME: handle template arguments
+ // FIXME: handle template arguments
+ return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
- return MemberExpr::Create(Importer.getToContext(), ToBase,
- E->isArrow(),
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()),
- ToMember, ToFoundDecl, ToMemberNameInfo,
- nullptr, T, E->getValueKind(),
- E->getObjectKind());
+ return MemberExpr::Create(
+ Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc,
+ ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, ToFoundDecl,
+ ToMemberNameInfo, nullptr, ToType, E->getValueKind(), E->getObjectKind());
}
-Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr(
- CXXPseudoDestructorExpr *E) {
- Expr *BaseE = Importer.Import(E->getBase());
- if (!BaseE)
- return nullptr;
+ExpectedStmt
+ASTNodeImporter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+ auto Imp = importSeq(
+ E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(),
+ E->getScopeTypeInfo(), E->getColonColonLoc(), E->getTildeLoc());
+ if (!Imp)
+ return Imp.takeError();
- TypeSourceInfo *ScopeInfo = Importer.Import(E->getScopeTypeInfo());
- if (!ScopeInfo && E->getScopeTypeInfo())
- return nullptr;
+ Expr *ToBase;
+ SourceLocation ToOperatorLoc, ToColonColonLoc, ToTildeLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ TypeSourceInfo *ToScopeTypeInfo;
+ std::tie(
+ ToBase, ToOperatorLoc, ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc,
+ ToTildeLoc) = *Imp;
PseudoDestructorTypeStorage Storage;
if (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) {
IdentifierInfo *ToII = Importer.Import(FromII);
- if (!ToII)
- return nullptr;
- Storage = PseudoDestructorTypeStorage(
- ToII, Importer.Import(E->getDestroyedTypeLoc()));
+ ExpectedSLoc ToDestroyedTypeLocOrErr = import(E->getDestroyedTypeLoc());
+ if (!ToDestroyedTypeLocOrErr)
+ return ToDestroyedTypeLocOrErr.takeError();
+ Storage = PseudoDestructorTypeStorage(ToII, *ToDestroyedTypeLocOrErr);
} else {
- TypeSourceInfo *TI = Importer.Import(E->getDestroyedTypeInfo());
- if (!TI)
- return nullptr;
- Storage = PseudoDestructorTypeStorage(TI);
+ if (auto ToTIOrErr = import(E->getDestroyedTypeInfo()))
+ Storage = PseudoDestructorTypeStorage(*ToTIOrErr);
+ else
+ return ToTIOrErr.takeError();
}
return new (Importer.getToContext()) CXXPseudoDestructorExpr(
- Importer.getToContext(), BaseE, E->isArrow(),
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getQualifierLoc()),
- ScopeInfo, Importer.Import(E->getColonColonLoc()),
- Importer.Import(E->getTildeLoc()), Storage);
+ Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc,
+ ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc, ToTildeLoc, Storage);
}
-Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
+ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr *E) {
- Expr *Base = nullptr;
+ auto Imp = importSeq(
+ E->getType(), E->getOperatorLoc(), E->getQualifierLoc(),
+ E->getTemplateKeywordLoc(), E->getFirstQualifierFoundInScope());
+ if (!Imp)
+ return Imp.takeError();
+
+ QualType ToType;
+ SourceLocation ToOperatorLoc, ToTemplateKeywordLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ NamedDecl *ToFirstQualifierFoundInScope;
+ std::tie(
+ ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
+ ToFirstQualifierFoundInScope) = *Imp;
+
+ Expr *ToBase = nullptr;
if (!E->isImplicitAccess()) {
- Base = Importer.Import(E->getBase());
- if (!Base)
- return nullptr;
+ if (ExpectedExpr ToBaseOrErr = import(E->getBase()))
+ ToBase = *ToBaseOrErr;
+ else
+ return ToBaseOrErr.takeError();
}
- QualType BaseType = Importer.Import(E->getBaseType());
- if (BaseType.isNull())
- return nullptr;
-
TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
- if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
- E->template_arguments(), ToTAInfo))
- return nullptr;
+ if (Error Err = ImportTemplateArgumentListInfo(
+ E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(),
+ ToTAInfo))
+ return std::move(Err);
ResInfo = &ToTAInfo;
}
- DeclarationName Name = Importer.Import(E->getMember());
- if (!E->getMember().isEmpty() && Name.isEmpty())
- return nullptr;
-
- DeclarationNameInfo MemberNameInfo(Name, Importer.Import(E->getMemberLoc()));
+ auto ToMemberNameInfoOrErr = importSeq(E->getMember(), E->getMemberLoc());
+ if (!ToMemberNameInfoOrErr)
+ return ToMemberNameInfoOrErr.takeError();
+ DeclarationNameInfo ToMemberNameInfo(
+ std::get<0>(*ToMemberNameInfoOrErr), std::get<1>(*ToMemberNameInfoOrErr));
// Import additional name location/type info.
- ImportDeclarationNameLoc(E->getMemberNameInfo(), MemberNameInfo);
- auto ToFQ = Importer.Import(E->getFirstQualifierFoundInScope());
- if (!ToFQ && E->getFirstQualifierFoundInScope())
- return nullptr;
+ if (Error Err = ImportDeclarationNameLoc(
+ E->getMemberNameInfo(), ToMemberNameInfo))
+ return std::move(Err);
return CXXDependentScopeMemberExpr::Create(
- Importer.getToContext(), Base, BaseType, E->isArrow(),
- Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()),
- cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo);
+ Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc,
+ ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope,
+ ToMemberNameInfo, ResInfo);
}
-Expr *
+ExpectedStmt
ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
- DeclarationName Name = Importer.Import(E->getDeclName());
- if (!E->getDeclName().isEmpty() && Name.isEmpty())
- return nullptr;
-
- DeclarationNameInfo NameInfo(Name, Importer.Import(E->getExprLoc()));
- ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
-
- TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()),
- Importer.Import(E->getRAngleLoc()));
+ auto Imp = importSeq(
+ E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDeclName(),
+ E->getExprLoc(), E->getLAngleLoc(), E->getRAngleLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ NestedNameSpecifierLoc ToQualifierLoc;
+ SourceLocation ToTemplateKeywordLoc, ToExprLoc, ToLAngleLoc, ToRAngleLoc;
+ DeclarationName ToDeclName;
+ std::tie(
+ ToQualifierLoc, ToTemplateKeywordLoc, ToDeclName, ToExprLoc,
+ ToLAngleLoc, ToRAngleLoc) = *Imp;
+
+ DeclarationNameInfo ToNameInfo(ToDeclName, ToExprLoc);
+ if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
+ return std::move(Err);
+
+ TemplateArgumentListInfo ToTAInfo(ToLAngleLoc, ToRAngleLoc);
TemplateArgumentListInfo *ResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
- if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
- return nullptr;
+ if (Error Err =
+ ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+ return std::move(Err);
ResInfo = &ToTAInfo;
}
return DependentScopeDeclRefExpr::Create(
- Importer.getToContext(), Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo);
+ Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc,
+ ToNameInfo, ResInfo);
}
-Expr *ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
- CXXUnresolvedConstructExpr *CE) {
- unsigned NumArgs = CE->arg_size();
+ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
+ CXXUnresolvedConstructExpr *E) {
+ auto Imp = importSeq(
+ E->getLParenLoc(), E->getRParenLoc(), E->getTypeSourceInfo());
+ if (!Imp)
+ return Imp.takeError();
- SmallVector<Expr *, 8> ToArgs(NumArgs);
- if (ImportArrayChecked(CE->arg_begin(), CE->arg_end(), ToArgs.begin()))
- return nullptr;
+ SourceLocation ToLParenLoc, ToRParenLoc;
+ TypeSourceInfo *ToTypeSourceInfo;
+ std::tie(ToLParenLoc, ToRParenLoc, ToTypeSourceInfo) = *Imp;
+
+ SmallVector<Expr *, 8> ToArgs(E->arg_size());
+ if (Error Err =
+ ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
+ return std::move(Err);
return CXXUnresolvedConstructExpr::Create(
- Importer.getToContext(), Importer.Import(CE->getTypeSourceInfo()),
- Importer.Import(CE->getLParenLoc()), llvm::makeArrayRef(ToArgs),
- Importer.Import(CE->getRParenLoc()));
+ Importer.getToContext(), ToTypeSourceInfo, ToLParenLoc,
+ llvm::makeArrayRef(ToArgs), ToRParenLoc);
}
-Expr *ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
- auto *NamingClass =
- cast_or_null<CXXRecordDecl>(Importer.Import(E->getNamingClass()));
- if (E->getNamingClass() && !NamingClass)
- return nullptr;
+ExpectedStmt
+ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
+ Expected<CXXRecordDecl *> ToNamingClassOrErr = import(E->getNamingClass());
+ if (!ToNamingClassOrErr)
+ return ToNamingClassOrErr.takeError();
- DeclarationName Name = Importer.Import(E->getName());
- if (E->getName() && !Name)
- return nullptr;
+ auto ToQualifierLocOrErr = import(E->getQualifierLoc());
+ if (!ToQualifierLocOrErr)
+ return ToQualifierLocOrErr.takeError();
- DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc()));
+ auto ToNameInfoOrErr = importSeq(E->getName(), E->getNameLoc());
+ if (!ToNameInfoOrErr)
+ return ToNameInfoOrErr.takeError();
+ DeclarationNameInfo ToNameInfo(
+ std::get<0>(*ToNameInfoOrErr), std::get<1>(*ToNameInfoOrErr));
// Import additional name location/type info.
- ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+ if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
+ return std::move(Err);
UnresolvedSet<8> ToDecls;
- for (auto *D : E->decls()) {
- if (auto *To = cast_or_null<NamedDecl>(Importer.Import(D)))
- ToDecls.addDecl(To);
+ for (auto *D : E->decls())
+ if (auto ToDOrErr = import(D))
+ ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr));
else
- return nullptr;
- }
+ return ToDOrErr.takeError();
- TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr;
- if (E->hasExplicitTemplateArgs()) {
- if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
- E->template_arguments(), ToTAInfo))
- return nullptr;
- ResInfo = &ToTAInfo;
- }
+ if (E->hasExplicitTemplateArgs() && E->getTemplateKeywordLoc().isValid()) {
+ TemplateArgumentListInfo ToTAInfo;
+ if (Error Err = ImportTemplateArgumentListInfo(
+ E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(),
+ ToTAInfo))
+ return std::move(Err);
+
+ ExpectedSLoc ToTemplateKeywordLocOrErr = import(E->getTemplateKeywordLoc());
+ if (!ToTemplateKeywordLocOrErr)
+ return ToTemplateKeywordLocOrErr.takeError();
- if (ResInfo || E->getTemplateKeywordLoc().isValid())
return UnresolvedLookupExpr::Create(
- Importer.getToContext(), NamingClass,
- Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()), NameInfo, E->requiresADL(),
- ResInfo, ToDecls.begin(), ToDecls.end());
+ Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
+ *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo,
+ ToDecls.begin(), ToDecls.end());
+ }
return UnresolvedLookupExpr::Create(
- Importer.getToContext(), NamingClass,
- Importer.Import(E->getQualifierLoc()), NameInfo, E->requiresADL(),
- E->isOverloaded(), ToDecls.begin(), ToDecls.end());
-}
-
-Expr *ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
- DeclarationName Name = Importer.Import(E->getName());
- if (!E->getName().isEmpty() && Name.isEmpty())
- return nullptr;
- DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc()));
+ Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
+ ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(),
+ ToDecls.end());
+}
+
+ExpectedStmt
+ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+ auto Imp1 = importSeq(
+ E->getType(), E->getOperatorLoc(), E->getQualifierLoc(),
+ E->getTemplateKeywordLoc());
+ if (!Imp1)
+ return Imp1.takeError();
+
+ QualType ToType;
+ SourceLocation ToOperatorLoc, ToTemplateKeywordLoc;
+ NestedNameSpecifierLoc ToQualifierLoc;
+ std::tie(ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc) = *Imp1;
+
+ auto Imp2 = importSeq(E->getName(), E->getNameLoc());
+ if (!Imp2)
+ return Imp2.takeError();
+ DeclarationNameInfo ToNameInfo(std::get<0>(*Imp2), std::get<1>(*Imp2));
// Import additional name location/type info.
- ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
-
- QualType BaseType = Importer.Import(E->getType());
- if (!E->getType().isNull() && BaseType.isNull())
- return nullptr;
+ if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
+ return std::move(Err);
UnresolvedSet<8> ToDecls;
- for (Decl *D : E->decls()) {
- if (NamedDecl *To = cast_or_null<NamedDecl>(Importer.Import(D)))
- ToDecls.addDecl(To);
+ for (Decl *D : E->decls())
+ if (auto ToDOrErr = import(D))
+ ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr));
else
- return nullptr;
- }
+ return ToDOrErr.takeError();
TemplateArgumentListInfo ToTAInfo;
TemplateArgumentListInfo *ResInfo = nullptr;
if (E->hasExplicitTemplateArgs()) {
- if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
- return nullptr;
+ if (Error Err =
+ ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+ return std::move(Err);
ResInfo = &ToTAInfo;
}
- Expr *BaseE = E->isImplicitAccess() ? nullptr : Importer.Import(E->getBase());
- if (!BaseE && !E->isImplicitAccess() && E->getBase()) {
- return nullptr;
+ Expr *ToBase = nullptr;
+ if (!E->isImplicitAccess()) {
+ if (ExpectedExpr ToBaseOrErr = import(E->getBase()))
+ ToBase = *ToBaseOrErr;
+ else
+ return ToBaseOrErr.takeError();
}
return UnresolvedMemberExpr::Create(
- Importer.getToContext(), E->hasUnresolvedUsing(), BaseE, BaseType,
- E->isArrow(), Importer.Import(E->getOperatorLoc()),
- Importer.Import(E->getQualifierLoc()),
- Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo,
- ToDecls.begin(), ToDecls.end());
+ Importer.getToContext(), E->hasUnresolvedUsing(), ToBase, ToType,
+ E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
+ ToNameInfo, ResInfo, ToDecls.begin(), ToDecls.end());
}
-Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) {
+ auto Imp = importSeq(E->getCallee(), E->getType(), E->getRParenLoc());
+ if (!Imp)
+ return Imp.takeError();
- Expr *ToCallee = Importer.Import(E->getCallee());
- if (!ToCallee && E->getCallee())
- return nullptr;
+ Expr *ToCallee;
+ QualType ToType;
+ SourceLocation ToRParenLoc;
+ std::tie(ToCallee, ToType, ToRParenLoc) = *Imp;
unsigned NumArgs = E->getNumArgs();
- SmallVector<Expr *, 2> ToArgs(NumArgs);
- if (ImportContainerChecked(E->arguments(), ToArgs))
- return nullptr;
-
- auto **ToArgs_Copied = new (Importer.getToContext()) Expr*[NumArgs];
-
- for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai)
- ToArgs_Copied[ai] = ToArgs[ai];
+ llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
+ if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
+ return std::move(Err);
if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
- return new (Importer.getToContext()) CXXOperatorCallExpr(
- Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, T,
- OCE->getValueKind(), Importer.Import(OCE->getRParenLoc()),
- OCE->getFPFeatures());
+ return CXXOperatorCallExpr::Create(
+ Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, ToType,
+ OCE->getValueKind(), ToRParenLoc, OCE->getFPFeatures(),
+ OCE->getADLCallKind());
}
- return new (Importer.getToContext())
- CallExpr(Importer.getToContext(), ToCallee,
- llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(),
- Importer.Import(E->getRParenLoc()));
+ return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType,
+ E->getValueKind(), ToRParenLoc, /*MinNumArgs=*/0,
+ E->getADLCallKind());
}
-Optional<LambdaCapture>
-ASTNodeImporter::ImportLambdaCapture(const LambdaCapture &From) {
- VarDecl *Var = nullptr;
- if (From.capturesVariable()) {
- Var = cast_or_null<VarDecl>(Importer.Import(From.getCapturedVar()));
- if (!Var)
- return None;
- }
-
- return LambdaCapture(Importer.Import(From.getLocation()), From.isImplicit(),
- From.getCaptureKind(), Var,
- From.isPackExpansion()
- ? Importer.Import(From.getEllipsisLoc())
- : SourceLocation());
-}
-
-Expr *ASTNodeImporter::VisitLambdaExpr(LambdaExpr *LE) {
- CXXRecordDecl *FromClass = LE->getLambdaClass();
- auto *ToClass = dyn_cast_or_null<CXXRecordDecl>(Importer.Import(FromClass));
- if (!ToClass)
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) {
+ CXXRecordDecl *FromClass = E->getLambdaClass();
+ auto ToClassOrErr = import(FromClass);
+ if (!ToClassOrErr)
+ return ToClassOrErr.takeError();
+ CXXRecordDecl *ToClass = *ToClassOrErr;
// NOTE: lambda classes are created with BeingDefined flag set up.
// It means that ImportDefinition doesn't work for them and we should fill it
// manually.
if (ToClass->isBeingDefined()) {
for (auto FromField : FromClass->fields()) {
- auto *ToField = cast_or_null<FieldDecl>(Importer.Import(FromField));
- if (!ToField)
- return nullptr;
+ auto ToFieldOrErr = import(FromField);
+ if (!ToFieldOrErr)
+ return ToFieldOrErr.takeError();
}
}
- auto *ToCallOp = dyn_cast_or_null<CXXMethodDecl>(
- Importer.Import(LE->getCallOperator()));
- if (!ToCallOp)
- return nullptr;
+ auto ToCallOpOrErr = import(E->getCallOperator());
+ if (!ToCallOpOrErr)
+ return ToCallOpOrErr.takeError();
ToClass->completeDefinition();
- unsigned NumCaptures = LE->capture_size();
- SmallVector<LambdaCapture, 8> Captures;
- Captures.reserve(NumCaptures);
- for (const auto &FromCapture : LE->captures()) {
- if (auto ToCapture = ImportLambdaCapture(FromCapture))
- Captures.push_back(*ToCapture);
+ SmallVector<LambdaCapture, 8> ToCaptures;
+ ToCaptures.reserve(E->capture_size());
+ for (const auto &FromCapture : E->captures()) {
+ if (auto ToCaptureOrErr = import(FromCapture))
+ ToCaptures.push_back(*ToCaptureOrErr);
else
- return nullptr;
+ return ToCaptureOrErr.takeError();
}
- SmallVector<Expr *, 8> InitCaptures(NumCaptures);
- if (ImportContainerChecked(LE->capture_inits(), InitCaptures))
- return nullptr;
+ SmallVector<Expr *, 8> ToCaptureInits(E->capture_size());
+ if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits))
+ return std::move(Err);
- return LambdaExpr::Create(Importer.getToContext(), ToClass,
- Importer.Import(LE->getIntroducerRange()),
- LE->getCaptureDefault(),
- Importer.Import(LE->getCaptureDefaultLoc()),
- Captures,
- LE->hasExplicitParameters(),
- LE->hasExplicitResultType(),
- InitCaptures,
- Importer.Import(LE->getLocEnd()),
- LE->containsUnexpandedParameterPack());
+ auto Imp = importSeq(
+ E->getIntroducerRange(), E->getCaptureDefaultLoc(), E->getEndLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceRange ToIntroducerRange;
+ SourceLocation ToCaptureDefaultLoc, ToEndLoc;
+ std::tie(ToIntroducerRange, ToCaptureDefaultLoc, ToEndLoc) = *Imp;
+
+ return LambdaExpr::Create(
+ Importer.getToContext(), ToClass, ToIntroducerRange,
+ E->getCaptureDefault(), ToCaptureDefaultLoc, ToCaptures,
+ E->hasExplicitParameters(), E->hasExplicitResultType(), ToCaptureInits,
+ ToEndLoc, E->containsUnexpandedParameterPack());
}
-Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
- QualType T = Importer.Import(ILE->getType());
- if (T.isNull())
- return nullptr;
- SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
- if (ImportContainerChecked(ILE->inits(), Exprs))
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitInitListExpr(InitListExpr *E) {
+ auto Imp = importSeq(E->getLBraceLoc(), E->getRBraceLoc(), E->getType());
+ if (!Imp)
+ return Imp.takeError();
+
+ SourceLocation ToLBraceLoc, ToRBraceLoc;
+ QualType ToType;
+ std::tie(ToLBraceLoc, ToRBraceLoc, ToType) = *Imp;
+
+ SmallVector<Expr *, 4> ToExprs(E->getNumInits());
+ if (Error Err = ImportContainerChecked(E->inits(), ToExprs))
+ return std::move(Err);
ASTContext &ToCtx = Importer.getToContext();
InitListExpr *To = new (ToCtx) InitListExpr(
- ToCtx, Importer.Import(ILE->getLBraceLoc()),
- Exprs, Importer.Import(ILE->getLBraceLoc()));
- To->setType(T);
+ ToCtx, ToLBraceLoc, ToExprs, ToRBraceLoc);
+ To->setType(ToType);
- if (ILE->hasArrayFiller()) {
- Expr *Filler = Importer.Import(ILE->getArrayFiller());
- if (!Filler)
- return nullptr;
- To->setArrayFiller(Filler);
+ if (E->hasArrayFiller()) {
+ if (ExpectedExpr ToFillerOrErr = import(E->getArrayFiller()))
+ To->setArrayFiller(*ToFillerOrErr);
+ else
+ return ToFillerOrErr.takeError();
}
- if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) {
- auto *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD));
- if (!ToFD)
- return nullptr;
- To->setInitializedFieldInUnion(ToFD);
+ if (FieldDecl *FromFD = E->getInitializedFieldInUnion()) {
+ if (auto ToFDOrErr = import(FromFD))
+ To->setInitializedFieldInUnion(*ToFDOrErr);
+ else
+ return ToFDOrErr.takeError();
}
- if (InitListExpr *SyntForm = ILE->getSyntacticForm()) {
- auto *ToSyntForm = cast_or_null<InitListExpr>(Importer.Import(SyntForm));
- if (!ToSyntForm)
- return nullptr;
- To->setSyntacticForm(ToSyntForm);
+ if (InitListExpr *SyntForm = E->getSyntacticForm()) {
+ if (auto ToSyntFormOrErr = import(SyntForm))
+ To->setSyntacticForm(*ToSyntFormOrErr);
+ else
+ return ToSyntFormOrErr.takeError();
}
- To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator());
- To->setValueDependent(ILE->isValueDependent());
- To->setInstantiationDependent(ILE->isInstantiationDependent());
+ // Copy InitListExprBitfields, which are not handled in the ctor of
+ // InitListExpr.
+ To->sawArrayRangeDesignator(E->hadArrayRangeDesignator());
return To;
}
-Expr *ASTNodeImporter::VisitCXXStdInitializerListExpr(
+ExpectedStmt ASTNodeImporter::VisitCXXStdInitializerListExpr(
CXXStdInitializerListExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- Expr *SE = Importer.Import(E->getSubExpr());
- if (!SE)
- return nullptr;
+ ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
+ if (!ToSubExprOrErr)
+ return ToSubExprOrErr.takeError();
- return new (Importer.getToContext()) CXXStdInitializerListExpr(T, SE);
+ return new (Importer.getToContext()) CXXStdInitializerListExpr(
+ *ToTypeOrErr, *ToSubExprOrErr);
}
-Expr *ASTNodeImporter::VisitCXXInheritedCtorInitExpr(
+ExpectedStmt ASTNodeImporter::VisitCXXInheritedCtorInitExpr(
CXXInheritedCtorInitExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ auto Imp = importSeq(E->getLocation(), E->getType(), E->getConstructor());
+ if (!Imp)
+ return Imp.takeError();
- auto *Ctor = cast_or_null<CXXConstructorDecl>(Importer.Import(
- E->getConstructor()));
- if (!Ctor)
- return nullptr;
+ SourceLocation ToLocation;
+ QualType ToType;
+ CXXConstructorDecl *ToConstructor;
+ std::tie(ToLocation, ToType, ToConstructor) = *Imp;
return new (Importer.getToContext()) CXXInheritedCtorInitExpr(
- Importer.Import(E->getLocation()), T, Ctor,
- E->constructsVBase(), E->inheritedFromVBase());
+ ToLocation, ToType, ToConstructor, E->constructsVBase(),
+ E->inheritedFromVBase());
}
-Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
- QualType ToType = Importer.Import(E->getType());
- if (ToType.isNull())
- return nullptr;
-
- Expr *ToCommon = Importer.Import(E->getCommonExpr());
- if (!ToCommon && E->getCommonExpr())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
+ auto Imp = importSeq(E->getType(), E->getCommonExpr(), E->getSubExpr());
+ if (!Imp)
+ return Imp.takeError();
- Expr *ToSubExpr = Importer.Import(E->getSubExpr());
- if (!ToSubExpr && E->getSubExpr())
- return nullptr;
+ QualType ToType;
+ Expr *ToCommonExpr, *ToSubExpr;
+ std::tie(ToType, ToCommonExpr, ToSubExpr) = *Imp;
- return new (Importer.getToContext())
- ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr);
+ return new (Importer.getToContext()) ArrayInitLoopExpr(
+ ToType, ToCommonExpr, ToSubExpr);
}
-Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
- QualType ToType = Importer.Import(E->getType());
- if (ToType.isNull())
- return nullptr;
- return new (Importer.getToContext()) ArrayInitIndexExpr(ToType);
+ExpectedStmt ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
+ return new (Importer.getToContext()) ArrayInitIndexExpr(*ToTypeOrErr);
}
-Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
- auto *ToField = dyn_cast_or_null<FieldDecl>(Importer.Import(DIE->getField()));
- if (!ToField && DIE->getField())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
+ ExpectedSLoc ToBeginLocOrErr = import(E->getBeginLoc());
+ if (!ToBeginLocOrErr)
+ return ToBeginLocOrErr.takeError();
+
+ auto ToFieldOrErr = import(E->getField());
+ if (!ToFieldOrErr)
+ return ToFieldOrErr.takeError();
return CXXDefaultInitExpr::Create(
- Importer.getToContext(), Importer.Import(DIE->getLocStart()), ToField);
+ Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr);
}
-Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
- QualType ToType = Importer.Import(E->getType());
- if (ToType.isNull() && !E->getType().isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+ auto Imp = importSeq(
+ E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten(),
+ E->getOperatorLoc(), E->getRParenLoc(), E->getAngleBrackets());
+ if (!Imp)
+ return Imp.takeError();
+
+ QualType ToType;
+ Expr *ToSubExpr;
+ TypeSourceInfo *ToTypeInfoAsWritten;
+ SourceLocation ToOperatorLoc, ToRParenLoc;
+ SourceRange ToAngleBrackets;
+ std::tie(
+ ToType, ToSubExpr, ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc,
+ ToAngleBrackets) = *Imp;
+
ExprValueKind VK = E->getValueKind();
CastKind CK = E->getCastKind();
- Expr *ToOp = Importer.Import(E->getSubExpr());
- if (!ToOp && E->getSubExpr())
- return nullptr;
- CXXCastPath BasePath;
- if (ImportCastPath(E, BasePath))
- return nullptr;
- TypeSourceInfo *ToWritten = Importer.Import(E->getTypeInfoAsWritten());
- SourceLocation ToOperatorLoc = Importer.Import(E->getOperatorLoc());
- SourceLocation ToRParenLoc = Importer.Import(E->getRParenLoc());
- SourceRange ToAngleBrackets = Importer.Import(E->getAngleBrackets());
+ auto ToBasePathOrErr = ImportCastPath(E);
+ if (!ToBasePathOrErr)
+ return ToBasePathOrErr.takeError();
if (isa<CXXStaticCastExpr>(E)) {
return CXXStaticCastExpr::Create(
- Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
- ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
+ ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
} else if (isa<CXXDynamicCastExpr>(E)) {
return CXXDynamicCastExpr::Create(
- Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
- ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
+ ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
} else if (isa<CXXReinterpretCastExpr>(E)) {
return CXXReinterpretCastExpr::Create(
- Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath,
- ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
+ ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ } else if (isa<CXXConstCastExpr>(E)) {
+ return CXXConstCastExpr::Create(
+ Importer.getToContext(), ToType, VK, ToSubExpr, ToTypeInfoAsWritten,
+ ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
} else {
- return nullptr;
+ llvm_unreachable("Unknown cast type");
+ return make_error<ImportError>();
}
}
-Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
+ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
- QualType T = Importer.Import(E->getType());
- if (T.isNull())
- return nullptr;
+ auto Imp = importSeq(
+ E->getType(), E->getExprLoc(), E->getParameter(), E->getReplacement());
+ if (!Imp)
+ return Imp.takeError();
- auto *Param = cast_or_null<NonTypeTemplateParmDecl>(
- Importer.Import(E->getParameter()));
- if (!Param)
- return nullptr;
-
- Expr *Replacement = Importer.Import(E->getReplacement());
- if (!Replacement)
- return nullptr;
+ QualType ToType;
+ SourceLocation ToExprLoc;
+ NonTypeTemplateParmDecl *ToParameter;
+ Expr *ToReplacement;
+ std::tie(ToType, ToExprLoc, ToParameter, ToReplacement) = *Imp;
return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
- T, E->getValueKind(), Importer.Import(E->getExprLoc()), Param,
- Replacement);
+ ToType, E->getValueKind(), ToExprLoc, ToParameter, ToReplacement);
}
-Expr *ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
- QualType ToType = Importer.Import(E->getType());
- if (ToType.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
+ auto Imp = importSeq(
+ E->getType(), E->getBeginLoc(), E->getEndLoc());
+ if (!Imp)
+ return Imp.takeError();
+
+ QualType ToType;
+ SourceLocation ToBeginLoc, ToEndLoc;
+ std::tie(ToType, ToBeginLoc, ToEndLoc) = *Imp;
SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs());
- if (ImportContainerChecked(E->getArgs(), ToArgs))
- return nullptr;
+ if (Error Err = ImportContainerChecked(E->getArgs(), ToArgs))
+ return std::move(Err);
// According to Sema::BuildTypeTrait(), if E is value-dependent,
// Value is always false.
- bool ToValue = false;
- if (!E->isValueDependent())
- ToValue = E->getValue();
+ bool ToValue = (E->isValueDependent() ? false : E->getValue());
return TypeTraitExpr::Create(
- Importer.getToContext(), ToType, Importer.Import(E->getLocStart()),
- E->getTrait(), ToArgs, Importer.Import(E->getLocEnd()), ToValue);
+ Importer.getToContext(), ToType, ToBeginLoc, E->getTrait(), ToArgs,
+ ToEndLoc, ToValue);
}
-Expr *ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
- QualType ToType = Importer.Import(E->getType());
- if (ToType.isNull())
- return nullptr;
+ExpectedStmt ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ ExpectedType ToTypeOrErr = import(E->getType());
+ if (!ToTypeOrErr)
+ return ToTypeOrErr.takeError();
- if (E->isTypeOperand()) {
- TypeSourceInfo *TSI = Importer.Import(E->getTypeOperandSourceInfo());
- if (!TSI)
- return nullptr;
+ auto ToSourceRangeOrErr = import(E->getSourceRange());
+ if (!ToSourceRangeOrErr)
+ return ToSourceRangeOrErr.takeError();
- return new (Importer.getToContext())
- CXXTypeidExpr(ToType, TSI, Importer.Import(E->getSourceRange()));
+ if (E->isTypeOperand()) {
+ if (auto ToTSIOrErr = import(E->getTypeOperandSourceInfo()))
+ return new (Importer.getToContext()) CXXTypeidExpr(
+ *ToTypeOrErr, *ToTSIOrErr, *ToSourceRangeOrErr);
+ else
+ return ToTSIOrErr.takeError();
}
- Expr *Op = Importer.Import(E->getExprOperand());
- if (!Op)
- return nullptr;
+ ExpectedExpr ToExprOperandOrErr = import(E->getExprOperand());
+ if (!ToExprOperandOrErr)
+ return ToExprOperandOrErr.takeError();
- return new (Importer.getToContext())
- CXXTypeidExpr(ToType, Op, Importer.Import(E->getSourceRange()));
+ return new (Importer.getToContext()) CXXTypeidExpr(
+ *ToTypeOrErr, *ToExprOperandOrErr, *ToSourceRangeOrErr);
}
void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod) {
- for (auto *FromOverriddenMethod : FromMethod->overridden_methods())
- ToMethod->addOverriddenMethod(
- cast<CXXMethodDecl>(Importer.Import(const_cast<CXXMethodDecl*>(
- FromOverriddenMethod))));
+ for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) {
+ if (auto ImportedOrErr = import(FromOverriddenMethod))
+ ToMethod->getCanonicalDecl()->addOverriddenMethod(cast<CXXMethodDecl>(
+ (*ImportedOrErr)->getCanonicalDecl()));
+ else
+ consumeError(ImportedOrErr.takeError());
+ }
}
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
- bool MinimalImport)
- : ToContext(ToContext), FromContext(FromContext),
+ bool MinimalImport,
+ ASTImporterLookupTable *LookupTable)
+ : LookupTable(LookupTable), ToContext(ToContext), FromContext(FromContext),
ToFileManager(ToFileManager), FromFileManager(FromFileManager),
Minimal(MinimalImport) {
- ImportedDecls[FromContext.getTranslationUnitDecl()]
- = ToContext.getTranslationUnitDecl();
+
+ ImportedDecls[FromContext.getTranslationUnitDecl()] =
+ ToContext.getTranslationUnitDecl();
}
ASTImporter::~ASTImporter() = default;
+Expected<QualType> ASTImporter::Import_New(QualType FromT) {
+ QualType ToT = Import(FromT);
+ if (ToT.isNull() && !FromT.isNull())
+ return make_error<ImportError>();
+ return ToT;
+}
+
+Optional<unsigned> ASTImporter::getFieldIndex(Decl *F) {
+ assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) &&
+ "Try to get field index for non-field.");
+
+ auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext());
+ if (!Owner)
+ return None;
+
+ unsigned Index = 0;
+ for (const auto *D : Owner->decls()) {
+ if (D == F)
+ return Index;
+
+ if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D))
+ ++Index;
+ }
+
+ llvm_unreachable("Field was not found in its parent context.");
+
+ return None;
+}
+
+ASTImporter::FoundDeclsTy
+ASTImporter::findDeclsInToCtx(DeclContext *DC, DeclarationName Name) {
+ // We search in the redecl context because of transparent contexts.
+ // E.g. a simple C language enum is a transparent context:
+ // enum E { A, B };
+ // Now if we had a global variable in the TU
+ // int A;
+ // then the enum constant 'A' and the variable 'A' violates ODR.
+ // We can diagnose this only if we search in the redecl context.
+ DeclContext *ReDC = DC->getRedeclContext();
+ if (LookupTable) {
+ ASTImporterLookupTable::LookupResult LookupResult =
+ LookupTable->lookup(ReDC, Name);
+ return FoundDeclsTy(LookupResult.begin(), LookupResult.end());
+ } else {
+ // FIXME Can we remove this kind of lookup?
+ // Or lldb really needs this C/C++ lookup?
+ FoundDeclsTy Result;
+ ReDC->localUncachedLookup(Name, Result);
+ return Result;
+ }
+}
+
+void ASTImporter::AddToLookupTable(Decl *ToD) {
+ if (LookupTable)
+ if (auto *ToND = dyn_cast<NamedDecl>(ToD))
+ LookupTable->add(ToND);
+}
+
QualType ASTImporter::Import(QualType FromT) {
if (FromT.isNull())
return {};
- const Type *fromTy = FromT.getTypePtr();
+ const Type *FromTy = FromT.getTypePtr();
// Check whether we've already imported this type.
llvm::DenseMap<const Type *, const Type *>::iterator Pos
- = ImportedTypes.find(fromTy);
+ = ImportedTypes.find(FromTy);
if (Pos != ImportedTypes.end())
return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers());
// Import the type
ASTNodeImporter Importer(*this);
- QualType ToT = Importer.Visit(fromTy);
- if (ToT.isNull())
- return ToT;
+ ExpectedType ToTOrErr = Importer.Visit(FromTy);
+ if (!ToTOrErr) {
+ llvm::consumeError(ToTOrErr.takeError());
+ return {};
+ }
// Record the imported type.
- ImportedTypes[fromTy] = ToT.getTypePtr();
+ ImportedTypes[FromTy] = (*ToTOrErr).getTypePtr();
- return ToContext.getQualifiedType(ToT, FromT.getLocalQualifiers());
+ return ToContext.getQualifiedType(*ToTOrErr, FromT.getLocalQualifiers());
}
+Expected<TypeSourceInfo *> ASTImporter::Import_New(TypeSourceInfo *FromTSI) {
+ TypeSourceInfo *ToTSI = Import(FromTSI);
+ if (!ToTSI && FromTSI)
+ return llvm::make_error<ImportError>();
+ return ToTSI;
+}
TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
if (!FromTSI)
return FromTSI;
@@ -6972,28 +7724,34 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
if (T.isNull())
return nullptr;
- return ToContext.getTrivialTypeSourceInfo(T,
- Import(FromTSI->getTypeLoc().getLocStart()));
+ return ToContext.getTrivialTypeSourceInfo(
+ T, Import(FromTSI->getTypeLoc().getBeginLoc()));
}
+Expected<Attr *> ASTImporter::Import_New(const Attr *FromAttr) {
+ return Import(FromAttr);
+}
Attr *ASTImporter::Import(const Attr *FromAttr) {
Attr *ToAttr = FromAttr->clone(ToContext);
+ // NOTE: Import of SourceRange may fail.
ToAttr->setRange(Import(FromAttr->getRange()));
return ToAttr;
}
-Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) {
- llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
- if (Pos != ImportedDecls.end()) {
- Decl *ToD = Pos->second;
- // FIXME: move this call to ImportDeclParts().
- ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD);
- return ToD;
- } else {
+Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const {
+ auto Pos = ImportedDecls.find(FromD);
+ if (Pos != ImportedDecls.end())
+ return Pos->second;
+ else
return nullptr;
- }
}
+Expected<Decl *> ASTImporter::Import_New(Decl *FromD) {
+ Decl *ToD = Import(FromD);
+ if (!ToD && FromD)
+ return llvm::make_error<ImportError>();
+ return ToD;
+}
Decl *ASTImporter::Import(Decl *FromD) {
if (!FromD)
return nullptr;
@@ -7009,17 +7767,26 @@ Decl *ASTImporter::Import(Decl *FromD) {
}
// Import the type.
- ToD = Importer.Visit(FromD);
- if (!ToD)
+ ExpectedDecl ToDOrErr = Importer.Visit(FromD);
+ if (!ToDOrErr) {
+ llvm::consumeError(ToDOrErr.takeError());
return nullptr;
+ }
+ ToD = *ToDOrErr;
+
+ // Once the decl is connected to the existing declarations, i.e. when the
+ // redecl chain is properly set then we populate the lookup again.
+ // This way the primary context will be able to find all decls.
+ AddToLookupTable(ToD);
// Notify subclasses.
Imported(FromD, ToD);
+ updateFlags(FromD, ToD);
return ToD;
}
-DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
+Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) {
if (!FromDC)
return FromDC;
@@ -7034,8 +7801,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
if (ToRecord->isCompleteDefinition()) {
// Do nothing.
} else if (FromRecord->isCompleteDefinition()) {
- ASTNodeImporter(*this).ImportDefinition(FromRecord, ToRecord,
- ASTNodeImporter::IDK_Basic);
+ if (Error Err = ASTNodeImporter(*this).ImportDefinition(
+ FromRecord, ToRecord, ASTNodeImporter::IDK_Basic))
+ return std::move(Err);
} else {
CompleteDecl(ToRecord);
}
@@ -7044,8 +7812,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
if (ToEnum->isCompleteDefinition()) {
// Do nothing.
} else if (FromEnum->isCompleteDefinition()) {
- ASTNodeImporter(*this).ImportDefinition(FromEnum, ToEnum,
- ASTNodeImporter::IDK_Basic);
+ if (Error Err = ASTNodeImporter(*this).ImportDefinition(
+ FromEnum, ToEnum, ASTNodeImporter::IDK_Basic))
+ return std::move(Err);
} else {
CompleteDecl(ToEnum);
}
@@ -7054,8 +7823,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
if (ToClass->getDefinition()) {
// Do nothing.
} else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) {
- ASTNodeImporter(*this).ImportDefinition(FromDef, ToClass,
- ASTNodeImporter::IDK_Basic);
+ if (Error Err = ASTNodeImporter(*this).ImportDefinition(
+ FromDef, ToClass, ASTNodeImporter::IDK_Basic))
+ return std::move(Err);
} else {
CompleteDecl(ToClass);
}
@@ -7064,8 +7834,9 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
if (ToProto->getDefinition()) {
// Do nothing.
} else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) {
- ASTNodeImporter(*this).ImportDefinition(FromDef, ToProto,
- ASTNodeImporter::IDK_Basic);
+ if (Error Err = ASTNodeImporter(*this).ImportDefinition(
+ FromDef, ToProto, ASTNodeImporter::IDK_Basic))
+ return std::move(Err);
} else {
CompleteDecl(ToProto);
}
@@ -7074,6 +7845,12 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
return ToDC;
}
+Expected<Expr *> ASTImporter::Import_New(Expr *FromE) {
+ Expr *ToE = Import(FromE);
+ if (!ToE && FromE)
+ return llvm::make_error<ImportError>();
+ return ToE;
+}
Expr *ASTImporter::Import(Expr *FromE) {
if (!FromE)
return nullptr;
@@ -7081,6 +7858,12 @@ Expr *ASTImporter::Import(Expr *FromE) {
return cast_or_null<Expr>(Import(cast<Stmt>(FromE)));
}
+Expected<Stmt *> ASTImporter::Import_New(Stmt *FromS) {
+ Stmt *ToS = Import(FromS);
+ if (!ToS && FromS)
+ return llvm::make_error<ImportError>();
+ return ToS;
+}
Stmt *ASTImporter::Import(Stmt *FromS) {
if (!FromS)
return nullptr;
@@ -7090,17 +7873,39 @@ Stmt *ASTImporter::Import(Stmt *FromS) {
if (Pos != ImportedStmts.end())
return Pos->second;
- // Import the type
+ // Import the statement.
ASTNodeImporter Importer(*this);
- Stmt *ToS = Importer.Visit(FromS);
- if (!ToS)
+ ExpectedStmt ToSOrErr = Importer.Visit(FromS);
+ if (!ToSOrErr) {
+ llvm::consumeError(ToSOrErr.takeError());
return nullptr;
+ }
+
+ if (auto *ToE = dyn_cast<Expr>(*ToSOrErr)) {
+ auto *FromE = cast<Expr>(FromS);
+ // Copy ExprBitfields, which may not be handled in Expr subclasses
+ // constructors.
+ ToE->setValueKind(FromE->getValueKind());
+ ToE->setObjectKind(FromE->getObjectKind());
+ ToE->setTypeDependent(FromE->isTypeDependent());
+ ToE->setValueDependent(FromE->isValueDependent());
+ ToE->setInstantiationDependent(FromE->isInstantiationDependent());
+ ToE->setContainsUnexpandedParameterPack(
+ FromE->containsUnexpandedParameterPack());
+ }
// Record the imported declaration.
- ImportedStmts[FromS] = ToS;
- return ToS;
+ ImportedStmts[FromS] = *ToSOrErr;
+ return *ToSOrErr;
}
+Expected<NestedNameSpecifier *>
+ASTImporter::Import_New(NestedNameSpecifier *FromNNS) {
+ NestedNameSpecifier *ToNNS = Import(FromNNS);
+ if (!ToNNS && FromNNS)
+ return llvm::make_error<ImportError>();
+ return ToNNS;
+}
NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
if (!FromNNS)
return nullptr;
@@ -7154,6 +7959,11 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
llvm_unreachable("Invalid nested name specifier kind");
}
+Expected<NestedNameSpecifierLoc>
+ASTImporter::Import_New(NestedNameSpecifierLoc FromNNS) {
+ NestedNameSpecifierLoc ToNNS = Import(FromNNS);
+ return ToNNS;
+}
NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
// Copied from NestedNameSpecifier mostly.
SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
@@ -7225,6 +8035,12 @@ NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
return Builder.getWithLocInContext(getToContext());
}
+Expected<TemplateName> ASTImporter::Import_New(TemplateName From) {
+ TemplateName To = Import(From);
+ if (To.isNull() && !From.isNull())
+ return llvm::make_error<ImportError>();
+ return To;
+}
TemplateName ASTImporter::Import(TemplateName From) {
switch (From.getKind()) {
case TemplateName::Template:
@@ -7301,18 +8117,26 @@ TemplateName ASTImporter::Import(TemplateName From) {
return {};
ASTNodeImporter Importer(*this);
- TemplateArgument ArgPack
+ Expected<TemplateArgument> ArgPack
= Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
- if (ArgPack.isNull())
+ if (!ArgPack) {
+ llvm::consumeError(ArgPack.takeError());
return {};
+ }
- return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack);
+ return ToContext.getSubstTemplateTemplateParmPack(Param, *ArgPack);
}
}
llvm_unreachable("Invalid template name kind");
}
+Expected<SourceLocation> ASTImporter::Import_New(SourceLocation FromLoc) {
+ SourceLocation ToLoc = Import(FromLoc);
+ if (ToLoc.isInvalid() && !FromLoc.isInvalid())
+ return llvm::make_error<ImportError>();
+ return ToLoc;
+}
SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
if (FromLoc.isInvalid())
return {};
@@ -7327,10 +8151,20 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
return ToSM.getComposedLoc(ToFileID, Decomposed.second);
}
+Expected<SourceRange> ASTImporter::Import_New(SourceRange FromRange) {
+ SourceRange ToRange = Import(FromRange);
+ return ToRange;
+}
SourceRange ASTImporter::Import(SourceRange FromRange) {
return SourceRange(Import(FromRange.getBegin()), Import(FromRange.getEnd()));
}
+Expected<FileID> ASTImporter::Import_New(FileID FromID) {
+ FileID ToID = Import(FromID);
+ if (ToID.isInvalid() && FromID.isValid())
+ return llvm::make_error<ImportError>();
+ return ToID;
+}
FileID ASTImporter::Import(FileID FromID) {
llvm::DenseMap<FileID, FileID>::iterator Pos = ImportedFileIDs.find(FromID);
if (Pos != ImportedFileIDs.end())
@@ -7388,6 +8222,13 @@ FileID ASTImporter::Import(FileID FromID) {
return ToID;
}
+Expected<CXXCtorInitializer *>
+ASTImporter::Import_New(CXXCtorInitializer *From) {
+ CXXCtorInitializer *To = Import(From);
+ if (!To && From)
+ return llvm::make_error<ImportError>();
+ return To;
+}
CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
Expr *ToExpr = Import(From->getInit());
if (!ToExpr && From->getInit())
@@ -7433,6 +8274,13 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
}
}
+Expected<CXXBaseSpecifier *>
+ASTImporter::Import_New(const CXXBaseSpecifier *From) {
+ CXXBaseSpecifier *To = Import(From);
+ if (!To && From)
+ return llvm::make_error<ImportError>();
+ return To;
+}
CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
if (Pos != ImportedCXXBaseSpecifiers.end())
@@ -7448,50 +8296,62 @@ CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
return Imported;
}
-void ASTImporter::ImportDefinition(Decl *From) {
+Error ASTImporter::ImportDefinition_New(Decl *From) {
Decl *To = Import(From);
if (!To)
- return;
+ return llvm::make_error<ImportError>();
if (auto *FromDC = cast<DeclContext>(From)) {
ASTNodeImporter Importer(*this);
if (auto *ToRecord = dyn_cast<RecordDecl>(To)) {
if (!ToRecord->getDefinition()) {
- Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord,
- ASTNodeImporter::IDK_Everything);
- return;
+ return Importer.ImportDefinition(
+ cast<RecordDecl>(FromDC), ToRecord,
+ ASTNodeImporter::IDK_Everything);
}
}
if (auto *ToEnum = dyn_cast<EnumDecl>(To)) {
if (!ToEnum->getDefinition()) {
- Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum,
- ASTNodeImporter::IDK_Everything);
- return;
+ return Importer.ImportDefinition(
+ cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything);
}
}
if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
if (!ToIFace->getDefinition()) {
- Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace,
- ASTNodeImporter::IDK_Everything);
- return;
+ return Importer.ImportDefinition(
+ cast<ObjCInterfaceDecl>(FromDC), ToIFace,
+ ASTNodeImporter::IDK_Everything);
}
}
if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
if (!ToProto->getDefinition()) {
- Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto,
- ASTNodeImporter::IDK_Everything);
- return;
+ return Importer.ImportDefinition(
+ cast<ObjCProtocolDecl>(FromDC), ToProto,
+ ASTNodeImporter::IDK_Everything);
}
}
- Importer.ImportDeclContext(FromDC, true);
+ return Importer.ImportDeclContext(FromDC, true);
}
+
+ return Error::success();
}
+void ASTImporter::ImportDefinition(Decl *From) {
+ Error Err = ImportDefinition_New(From);
+ llvm::consumeError(std::move(Err));
+}
+
+Expected<DeclarationName> ASTImporter::Import_New(DeclarationName FromName) {
+ DeclarationName ToName = Import(FromName);
+ if (!ToName && FromName)
+ return llvm::make_error<ImportError>();
+ return ToName;
+}
DeclarationName ASTImporter::Import(DeclarationName FromName) {
if (!FromName)
return {};
@@ -7568,6 +8428,12 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
return ToId;
}
+Expected<Selector> ASTImporter::Import_New(Selector FromSel) {
+ Selector ToSel = Import(FromSel);
+ if (ToSel.isNull() && !FromSel.isNull())
+ return llvm::make_error<ImportError>();
+ return ToSel;
+}
Selector ASTImporter::Import(Selector FromSel) {
if (FromSel.isNull())
return {};
diff --git a/lib/AST/ASTImporterLookupTable.cpp b/lib/AST/ASTImporterLookupTable.cpp
new file mode 100644
index 000000000000..fbcd4f5cb341
--- /dev/null
+++ b/lib/AST/ASTImporterLookupTable.cpp
@@ -0,0 +1,129 @@
+//===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ASTImporterLookupTable class which implements a
+// lookup procedure for the import mechanism.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTImporterLookupTable.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+namespace clang {
+
+namespace {
+
+struct Builder : RecursiveASTVisitor<Builder> {
+ ASTImporterLookupTable &LT;
+ Builder(ASTImporterLookupTable &LT) : LT(LT) {}
+ bool VisitNamedDecl(NamedDecl *D) {
+ LT.add(D);
+ return true;
+ }
+ bool VisitFriendDecl(FriendDecl *D) {
+ if (D->getFriendType()) {
+ QualType Ty = D->getFriendType()->getType();
+ // FIXME Can this be other than elaborated?
+ QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
+ if (!NamedTy->isDependentType()) {
+ if (const auto *RTy = dyn_cast<RecordType>(NamedTy))
+ LT.add(RTy->getAsCXXRecordDecl());
+ else if (const auto *SpecTy =
+ dyn_cast<TemplateSpecializationType>(NamedTy)) {
+ LT.add(SpecTy->getAsCXXRecordDecl());
+ }
+ }
+ }
+ return true;
+ }
+
+ // Override default settings of base.
+ bool shouldVisitTemplateInstantiations() const { return true; }
+ bool shouldVisitImplicitCode() const { return true; }
+};
+
+} // anonymous namespace
+
+ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
+ Builder B(*this);
+ B.TraverseDecl(&TU);
+}
+
+void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
+ DeclList &Decls = LookupTable[DC][ND->getDeclName()];
+ // Inserts if and only if there is no element in the container equal to it.
+ Decls.insert(ND);
+}
+
+void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
+ DeclList &Decls = LookupTable[DC][ND->getDeclName()];
+ bool EraseResult = Decls.remove(ND);
+ (void)EraseResult;
+ assert(EraseResult == true && "Trying to remove not contained Decl");
+}
+
+void ASTImporterLookupTable::add(NamedDecl *ND) {
+ assert(ND);
+ DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
+ add(DC, ND);
+ DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
+ if (DC != ReDC)
+ add(ReDC, ND);
+}
+
+void ASTImporterLookupTable::remove(NamedDecl *ND) {
+ assert(ND);
+ DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
+ remove(DC, ND);
+ DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
+ if (DC != ReDC)
+ remove(ReDC, ND);
+}
+
+ASTImporterLookupTable::LookupResult
+ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
+ auto DCI = LookupTable.find(DC->getPrimaryContext());
+ if (DCI == LookupTable.end())
+ return {};
+
+ const auto &FoundNameMap = DCI->second;
+ auto NamesI = FoundNameMap.find(Name);
+ if (NamesI == FoundNameMap.end())
+ return {};
+
+ return NamesI->second;
+}
+
+void ASTImporterLookupTable::dump(DeclContext *DC) const {
+ auto DCI = LookupTable.find(DC->getPrimaryContext());
+ if (DCI == LookupTable.end())
+ llvm::errs() << "empty\n";
+ const auto &FoundNameMap = DCI->second;
+ for (const auto &Entry : FoundNameMap) {
+ DeclarationName Name = Entry.first;
+ llvm::errs() << "==== Name: ";
+ Name.dump();
+ const DeclList& List = Entry.second;
+ for (NamedDecl *ND : List) {
+ ND->dump();
+ }
+ }
+}
+
+void ASTImporterLookupTable::dump() const {
+ for (const auto &Entry : LookupTable) {
+ DeclContext *DC = Entry.first;
+ StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
+ llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
+ dump(DC);
+ }
+}
+
+} // namespace clang
diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp
index df3c2be9a2e2..d19b89bb95b4 100644
--- a/lib/AST/ASTStructuralEquivalence.cpp
+++ b/lib/AST/ASTStructuralEquivalence.cpp
@@ -911,7 +911,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return true;
}
-/// Determine structural equivalence of two methodss.
+/// Determine structural equivalence of two methods.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
CXXMethodDecl *Method1,
CXXMethodDecl *Method2) {
@@ -1016,14 +1016,15 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
// Compare the definitions of these two records. If either or both are
- // incomplete, we assume that they are equivalent.
+ // incomplete (i.e. it is a forward decl), we assume that they are
+ // equivalent.
D1 = D1->getDefinition();
D2 = D2->getDefinition();
if (!D1 || !D2)
return true;
// If any of the records has external storage and we do a minimal check (or
- // AST import) we assmue they are equivalent. (If we didn't have this
+ // AST import) we assume they are equivalent. (If we didn't have this
// assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger
// another AST import which in turn would call the structural equivalency
// check again and finally we'd have an improper result.)
@@ -1031,6 +1032,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage())
return true;
+ // If one definition is currently being defined, we do not compare for
+ // equality and we assume that the decls are equal.
+ if (D1->isBeingDefined() || D2->isBeingDefined())
+ return true;
+
if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
if (D1CXX->hasExternalLexicalStorage() &&
@@ -1061,9 +1067,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
- Context.Diag2(Base2->getLocStart(), diag::note_odr_base)
+ Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
<< Base2->getType() << Base2->getSourceRange();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
+ Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
<< Base1->getType() << Base1->getSourceRange();
}
return false;
@@ -1075,9 +1081,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(),
diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
- Context.Diag2(Base2->getLocStart(), diag::note_odr_virtual_base)
+ Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
<< Base2->isVirtual() << Base2->getSourceRange();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
+ Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
<< Base1->isVirtual() << Base1->getSourceRange();
}
return false;
@@ -1126,7 +1132,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
<< Context.ToCtx.getTypeDeclType(D2);
const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
- Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
+ Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
<< Base1->getType() << Base1->getSourceRange();
Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
}
@@ -1178,6 +1184,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
/// Determine structural equivalence of two enums.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
EnumDecl *D1, EnumDecl *D2) {
+
+ // Compare the definitions of these two enums. If either or both are
+ // incomplete (i.e. forward declared), we assume that they are equivalent.
+ D1 = D1->getDefinition();
+ D2 = D2->getDefinition();
+ if (!D1 || !D2)
+ return true;
+
EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(),
EC2End = D2->enumerator_end();
for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(),
@@ -1497,6 +1511,141 @@ bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) {
return !Finish();
}
+bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
+ // Check for equivalent described template.
+ TemplateDecl *Template1 = D1->getDescribedTemplate();
+ TemplateDecl *Template2 = D2->getDescribedTemplate();
+ if ((Template1 != nullptr) != (Template2 != nullptr))
+ return false;
+ if (Template1 && !IsStructurallyEquivalent(*this, Template1, Template2))
+ return false;
+
+ // FIXME: Move check for identifier names into this function.
+
+ return true;
+}
+
+bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
+ Decl *D1, Decl *D2) {
+ // FIXME: Switch on all declaration kinds. For now, we're just going to
+ // check the obvious ones.
+ if (auto *Record1 = dyn_cast<RecordDecl>(D1)) {
+ if (auto *Record2 = dyn_cast<RecordDecl>(D2)) {
+ // Check for equivalent structure names.
+ IdentifierInfo *Name1 = Record1->getIdentifier();
+ if (!Name1 && Record1->getTypedefNameForAnonDecl())
+ Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier();
+ IdentifierInfo *Name2 = Record2->getIdentifier();
+ if (!Name2 && Record2->getTypedefNameForAnonDecl())
+ Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier();
+ if (!::IsStructurallyEquivalent(Name1, Name2) ||
+ !::IsStructurallyEquivalent(*this, Record1, Record2))
+ return false;
+ } else {
+ // Record/non-record mismatch.
+ return false;
+ }
+ } else if (auto *Enum1 = dyn_cast<EnumDecl>(D1)) {
+ if (auto *Enum2 = dyn_cast<EnumDecl>(D2)) {
+ // Check for equivalent enum names.
+ IdentifierInfo *Name1 = Enum1->getIdentifier();
+ if (!Name1 && Enum1->getTypedefNameForAnonDecl())
+ Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier();
+ IdentifierInfo *Name2 = Enum2->getIdentifier();
+ if (!Name2 && Enum2->getTypedefNameForAnonDecl())
+ Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier();
+ if (!::IsStructurallyEquivalent(Name1, Name2) ||
+ !::IsStructurallyEquivalent(*this, Enum1, Enum2))
+ return false;
+ } else {
+ // Enum/non-enum mismatch
+ return false;
+ }
+ } else if (const auto *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) {
+ if (const auto *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(),
+ Typedef2->getIdentifier()) ||
+ !::IsStructurallyEquivalent(*this, Typedef1->getUnderlyingType(),
+ Typedef2->getUnderlyingType()))
+ return false;
+ } else {
+ // Typedef/non-typedef mismatch.
+ return false;
+ }
+ } else if (auto *ClassTemplate1 = dyn_cast<ClassTemplateDecl>(D1)) {
+ if (auto *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, ClassTemplate1,
+ ClassTemplate2))
+ return false;
+ } else {
+ // Class template/non-class-template mismatch.
+ return false;
+ }
+ } else if (auto *FunctionTemplate1 = dyn_cast<FunctionTemplateDecl>(D1)) {
+ if (auto *FunctionTemplate2 = dyn_cast<FunctionTemplateDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, FunctionTemplate1,
+ FunctionTemplate2))
+ return false;
+ } else {
+ // Class template/non-class-template mismatch.
+ return false;
+ }
+ } else if (auto *TTP1 = dyn_cast<TemplateTypeParmDecl>(D1)) {
+ if (auto *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
+ return false;
+ } else {
+ // Kind mismatch.
+ return false;
+ }
+ } else if (auto *NTTP1 = dyn_cast<NonTypeTemplateParmDecl>(D1)) {
+ if (auto *NTTP2 = dyn_cast<NonTypeTemplateParmDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2))
+ return false;
+ } else {
+ // Kind mismatch.
+ return false;
+ }
+ } else if (auto *TTP1 = dyn_cast<TemplateTemplateParmDecl>(D1)) {
+ if (auto *TTP2 = dyn_cast<TemplateTemplateParmDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
+ return false;
+ } else {
+ // Kind mismatch.
+ return false;
+ }
+ } else if (auto *MD1 = dyn_cast<CXXMethodDecl>(D1)) {
+ if (auto *MD2 = dyn_cast<CXXMethodDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, MD1, MD2))
+ return false;
+ } else {
+ // Kind mismatch.
+ return false;
+ }
+ } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) {
+ if (FunctionDecl *FD2 = dyn_cast<FunctionDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(FD1->getIdentifier(),
+ FD2->getIdentifier()))
+ return false;
+ if (!::IsStructurallyEquivalent(*this, FD1, FD2))
+ return false;
+ } else {
+ // Kind mismatch.
+ return false;
+ }
+ } else if (FriendDecl *FrD1 = dyn_cast<FriendDecl>(D1)) {
+ if (FriendDecl *FrD2 = dyn_cast<FriendDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, FrD1, FrD2))
+ return false;
+ } else {
+ // Kind mismatch.
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool StructuralEquivalenceContext::Finish() {
while (!DeclsToCheck.empty()) {
// Check the next declaration.
@@ -1506,123 +1655,8 @@ bool StructuralEquivalenceContext::Finish() {
Decl *D2 = TentativeEquivalences[D1];
assert(D2 && "Unrecorded tentative equivalence?");
- bool Equivalent = true;
-
- // FIXME: Switch on all declaration kinds. For now, we're just going to
- // check the obvious ones.
- if (auto *Record1 = dyn_cast<RecordDecl>(D1)) {
- if (auto *Record2 = dyn_cast<RecordDecl>(D2)) {
- // Check for equivalent structure names.
- IdentifierInfo *Name1 = Record1->getIdentifier();
- if (!Name1 && Record1->getTypedefNameForAnonDecl())
- Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier();
- IdentifierInfo *Name2 = Record2->getIdentifier();
- if (!Name2 && Record2->getTypedefNameForAnonDecl())
- Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier();
- if (!::IsStructurallyEquivalent(Name1, Name2) ||
- !::IsStructurallyEquivalent(*this, Record1, Record2))
- Equivalent = false;
- } else {
- // Record/non-record mismatch.
- Equivalent = false;
- }
- } else if (auto *Enum1 = dyn_cast<EnumDecl>(D1)) {
- if (auto *Enum2 = dyn_cast<EnumDecl>(D2)) {
- // Check for equivalent enum names.
- IdentifierInfo *Name1 = Enum1->getIdentifier();
- if (!Name1 && Enum1->getTypedefNameForAnonDecl())
- Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier();
- IdentifierInfo *Name2 = Enum2->getIdentifier();
- if (!Name2 && Enum2->getTypedefNameForAnonDecl())
- Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier();
- if (!::IsStructurallyEquivalent(Name1, Name2) ||
- !::IsStructurallyEquivalent(*this, Enum1, Enum2))
- Equivalent = false;
- } else {
- // Enum/non-enum mismatch
- Equivalent = false;
- }
- } else if (const auto *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) {
- if (const auto *Typedef2 = dyn_cast<TypedefNameDecl>(D2)) {
- if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(),
- Typedef2->getIdentifier()) ||
- !::IsStructurallyEquivalent(*this, Typedef1->getUnderlyingType(),
- Typedef2->getUnderlyingType()))
- Equivalent = false;
- } else {
- // Typedef/non-typedef mismatch.
- Equivalent = false;
- }
- } else if (auto *ClassTemplate1 = dyn_cast<ClassTemplateDecl>(D1)) {
- if (auto *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, ClassTemplate1,
- ClassTemplate2))
- Equivalent = false;
- } else {
- // Class template/non-class-template mismatch.
- Equivalent = false;
- }
- } else if (auto *FunctionTemplate1 = dyn_cast<FunctionTemplateDecl>(D1)) {
- if (auto *FunctionTemplate2 = dyn_cast<FunctionTemplateDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, FunctionTemplate1,
- FunctionTemplate2))
- Equivalent = false;
- } else {
- // Class template/non-class-template mismatch.
- Equivalent = false;
- }
- } else if (auto *TTP1 = dyn_cast<TemplateTypeParmDecl>(D1)) {
- if (auto *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- } else if (auto *NTTP1 = dyn_cast<NonTypeTemplateParmDecl>(D1)) {
- if (auto *NTTP2 = dyn_cast<NonTypeTemplateParmDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- } else if (auto *TTP1 = dyn_cast<TemplateTemplateParmDecl>(D1)) {
- if (auto *TTP2 = dyn_cast<TemplateTemplateParmDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- } else if (auto *MD1 = dyn_cast<CXXMethodDecl>(D1)) {
- if (auto *MD2 = dyn_cast<CXXMethodDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, MD1, MD2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) {
- if (FunctionDecl *FD2 = dyn_cast<FunctionDecl>(D2)) {
- if (!::IsStructurallyEquivalent(FD1->getIdentifier(),
- FD2->getIdentifier()))
- Equivalent = false;
- if (!::IsStructurallyEquivalent(*this, FD1, FD2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- } else if (FriendDecl *FrD1 = dyn_cast<FriendDecl>(D1)) {
- if (FriendDecl *FrD2 = dyn_cast<FriendDecl>(D2)) {
- if (!::IsStructurallyEquivalent(*this, FrD1, FrD2))
- Equivalent = false;
- } else {
- // Kind mismatch.
- Equivalent = false;
- }
- }
+ bool Equivalent =
+ CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
if (!Equivalent) {
// Note that these two declarations are not equivalent (and we already
@@ -1631,7 +1665,6 @@ bool StructuralEquivalenceContext::Finish() {
std::make_pair(D1->getCanonicalDecl(), D2->getCanonicalDecl()));
return true;
}
- // FIXME: Check other declaration kinds!
}
return false;
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 4f868a3af59e..570ca718acf5 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_library(clangAST
ASTDiagnostic.cpp
ASTDumper.cpp
ASTImporter.cpp
+ ASTImporterLookupTable.cpp
ASTStructuralEquivalence.cpp
ASTTypeTraits.cpp
AttrImpl.cpp
@@ -39,6 +40,7 @@ add_clang_library(clangAST
ExprObjC.cpp
ExternalASTMerger.cpp
ExternalASTSource.cpp
+ FormatString.cpp
InheritViz.cpp
ItaniumCXXABI.cpp
ItaniumMangle.cpp
@@ -48,12 +50,15 @@ add_clang_library(clangAST
NestedNameSpecifier.cpp
NSAPI.cpp
ODRHash.cpp
+ OSLog.cpp
OpenMPClause.cpp
ParentMap.cpp
+ PrintfFormatString.cpp
QualTypeNames.cpp
RawCommentList.cpp
RecordLayout.cpp
RecordLayoutBuilder.cpp
+ ScanfFormatString.cpp
SelectorLocationsKind.cpp
Stmt.cpp
StmtCXX.cpp
@@ -65,6 +70,7 @@ add_clang_library(clangAST
StmtViz.cpp
TemplateBase.cpp
TemplateName.cpp
+ TextNodeDumper.cpp
Type.cpp
TypeLoc.cpp
TypePrinter.cpp
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index a0b22b6a85e0..ddb350e72bbd 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -103,7 +103,6 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
- // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7.
return lookupInBases(
[BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
return FindBaseClass(Specifier, Path, BaseDecl);
@@ -124,7 +123,6 @@ bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
- // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7.
return lookupInBases(
[BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
return FindVirtualBaseClass(Specifier, Path, BaseDecl);
diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp
index 8d401ff5c7ea..c43275318dd7 100644
--- a/lib/AST/CommentLexer.cpp
+++ b/lib/AST/CommentLexer.cpp
@@ -21,7 +21,7 @@ namespace comments {
void Token::dump(const Lexer &L, const SourceManager &SM) const {
llvm::errs() << "comments::Token Kind=" << Kind << " ";
- Loc.dump(SM);
+ Loc.print(llvm::errs(), SM);
llvm::errs() << " " << Length << " \"" << L.getSpelling(*this, SM) << "\"\n";
}
diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp
index c1c04239f58e..7f70b95e9812 100644
--- a/lib/AST/CommentParser.cpp
+++ b/lib/AST/CommentParser.cpp
@@ -558,7 +558,6 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() {
case tok::verbatim_block_begin:
case tok::verbatim_line_name:
case tok::eof:
- assert(Content.size() != 0);
break; // Block content or EOF ahead, finish this parapgaph.
case tok::unknown_command:
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index 4bc98bf10765..88588a7a89e6 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -703,10 +703,9 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
SmallString<64> TextToInsert(" ");
TextToInsert += AttributeSpelling;
- Diag(FD->getLocEnd(),
- diag::note_add_deprecation_attr)
- << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1),
- TextToInsert);
+ Diag(FD->getEndLoc(), diag::note_add_deprecation_attr)
+ << FixItHint::CreateInsertion(FD->getEndLoc().getLocWithOffset(1),
+ TextToInsert);
}
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 8030dd0c2f41..5536358b1ecf 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/Decl.h"
#include "Linkage.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CanonicalType.h"
@@ -49,7 +50,6 @@
#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Visibility.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
@@ -725,7 +725,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method.
if (useInlineVisibilityHidden(D))
- LV.mergeVisibility(HiddenVisibility, true);
+ LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
}
}
@@ -915,7 +915,7 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
// Note that we do this before merging information about
// the class visibility.
if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
- LV.mergeVisibility(HiddenVisibility, true);
+ LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
}
// If this class member has an explicit visibility attribute, the only
@@ -1262,7 +1262,27 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
!isTemplateInstantiation(FD->getTemplateSpecializationKind()))
return LinkageInfo::none();
+ // If a function is hidden by -fvisibility-inlines-hidden option and
+ // is not explicitly attributed as a hidden function,
+ // we should not make static local variables in the function hidden.
LV = getLVForDecl(FD, computation);
+ if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
+ !LV.isVisibilityExplicit()) {
+ assert(cast<VarDecl>(D)->isStaticLocal());
+ // If this was an implicitly hidden inline method, check again for
+ // explicit visibility on the parent class, and use that for static locals
+ // if present.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
+ LV = getLVForDecl(MD->getParent(), computation);
+ if (!LV.isVisibilityExplicit()) {
+ Visibility globalVisibility =
+ computation.isValueVisibility()
+ ? Context.getLangOpts().getValueVisibilityMode()
+ : Context.getLangOpts().getTypeVisibilityMode();
+ return LinkageInfo(VisibleNoLinkage, globalVisibility,
+ /*visibilityExplicit=*/false);
+ }
+ }
}
if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo::none();
@@ -1937,7 +1957,7 @@ VarDecl::TLSKind VarDecl::getTLSKind() const {
SourceRange VarDecl::getSourceRange() const {
if (const Expr *Init = getInit()) {
- SourceLocation InitEnd = Init->getLocEnd();
+ SourceLocation InitEnd = Init->getEndLoc();
// If Init is implicit, ignore its source range and fallback on
// DeclaratorDecl::getSourceRange() to handle postfix elements.
if (InitEnd.isValid() && InitEnd != getLocation())
@@ -2351,6 +2371,14 @@ static DeclT *getDefinitionOrSelf(DeclT *D) {
return D;
}
+bool VarDecl::isEscapingByref() const {
+ return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref;
+}
+
+bool VarDecl::isNonEscapingByref() const {
+ return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref;
+}
+
VarDecl *VarDecl::getTemplateInstantiationPattern() const {
// If it's a variable template specialization, find the template or partial
// specialization from which it was instantiated.
@@ -2441,7 +2469,7 @@ bool VarDecl::isKnownToBeDefined() const {
//
// With CUDA relocatable device code enabled, these variables don't get
// special handling; they're treated like regular extern variables.
- if (LangOpts.CUDA && !LangOpts.CUDARelocatableDeviceCode &&
+ if (LangOpts.CUDA && !LangOpts.GPURelocatableDeviceCode &&
hasExternalStorage() && hasAttr<CUDASharedAttr>() &&
isa<IncompleteArrayType>(getType()))
return true;
@@ -2449,6 +2477,12 @@ bool VarDecl::isKnownToBeDefined() const {
return hasDefinition();
}
+bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
+ return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() ||
+ (!Ctx.getLangOpts().RegisterStaticDestructors &&
+ !hasAttr<AlwaysDestroyAttr>()));
+}
+
MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
if (isStaticDataMember())
// FIXME: Remove ?
@@ -2531,7 +2565,7 @@ SourceRange ParmVarDecl::getSourceRange() const {
// DeclaratorDecl considers the range of postfix types as overlapping with the
// declaration name, but this is not the case with parameters in ObjC methods.
if (isa<ObjCMethodDecl>(getDeclContext()))
- return SourceRange(DeclaratorDecl::getLocStart(), getLocation());
+ return SourceRange(DeclaratorDecl::getBeginLoc(), getLocation());
return DeclaratorDecl::getSourceRange();
}
@@ -2542,7 +2576,7 @@ Expr *ParmVarDecl::getDefaultArg() {
"Default argument is not yet instantiated!");
Expr *Arg = getInit();
- if (auto *E = dyn_cast_or_null<ExprWithCleanups>(Arg))
+ if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
return E->getSubExpr();
return Arg;
@@ -2609,6 +2643,41 @@ unsigned ParmVarDecl::getParameterIndexLarge() const {
// FunctionDecl Implementation
//===----------------------------------------------------------------------===//
+FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S,
+ bool isInlineSpecified, bool isConstexprSpecified)
+ : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
+ StartLoc),
+ DeclContext(DK), redeclarable_base(C), ODRHash(0),
+ EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {
+ assert(T.isNull() || T->isFunctionType());
+ FunctionDeclBits.SClass = S;
+ FunctionDeclBits.IsInline = isInlineSpecified;
+ FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
+ FunctionDeclBits.IsExplicitSpecified = false;
+ FunctionDeclBits.IsVirtualAsWritten = false;
+ FunctionDeclBits.IsPure = false;
+ FunctionDeclBits.HasInheritedPrototype = false;
+ FunctionDeclBits.HasWrittenPrototype = true;
+ FunctionDeclBits.IsDeleted = false;
+ FunctionDeclBits.IsTrivial = false;
+ FunctionDeclBits.IsTrivialForCall = false;
+ FunctionDeclBits.IsDefaulted = false;
+ FunctionDeclBits.IsExplicitlyDefaulted = false;
+ FunctionDeclBits.HasImplicitReturnZero = false;
+ FunctionDeclBits.IsLateTemplateParsed = false;
+ FunctionDeclBits.IsConstexpr = isConstexprSpecified;
+ FunctionDeclBits.InstantiationIsPending = false;
+ FunctionDeclBits.UsesSEHTry = false;
+ FunctionDeclBits.HasSkippedBody = false;
+ FunctionDeclBits.WillHaveBody = false;
+ FunctionDeclBits.IsMultiVersion = false;
+ FunctionDeclBits.IsCopyDeductionCandidate = false;
+ FunctionDeclBits.HasODRHash = false;
+}
+
void FunctionDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
@@ -2672,11 +2741,11 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
void FunctionDecl::setBody(Stmt *B) {
Body = B;
if (B)
- EndRangeLoc = B->getLocEnd();
+ EndRangeLoc = B->getEndLoc();
}
void FunctionDecl::setPure(bool P) {
- IsPure = P;
+ FunctionDeclBits.IsPure = P;
if (P)
if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
Parent->markedVirtualFunctionPure();
@@ -2873,6 +2942,17 @@ bool FunctionDecl::isNoReturn() const {
return false;
}
+
+MultiVersionKind FunctionDecl::getMultiVersionKind() const {
+ if (hasAttr<TargetAttr>())
+ return MultiVersionKind::Target;
+ if (hasAttr<CPUDispatchAttr>())
+ return MultiVersionKind::CPUDispatch;
+ if (hasAttr<CPUSpecificAttr>())
+ return MultiVersionKind::CPUSpecific;
+ return MultiVersionKind::None;
+}
+
bool FunctionDecl::isCPUDispatchMultiVersion() const {
return isMultiVersion() && hasAttr<CPUDispatchAttr>();
}
@@ -2881,6 +2961,10 @@ bool FunctionDecl::isCPUSpecificMultiVersion() const {
return isMultiVersion() && hasAttr<CPUSpecificAttr>();
}
+bool FunctionDecl::isTargetMultiVersion() const {
+ return isMultiVersion() && hasAttr<TargetAttr>();
+}
+
void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
redeclarable_base::setPreviousDecl(PrevDecl);
@@ -2892,8 +2976,8 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
FunTmpl->setPreviousDecl(PrevFunTmpl);
}
- if (PrevDecl && PrevDecl->IsInline)
- IsInline = true;
+ if (PrevDecl && PrevDecl->isInlined())
+ setImplicitlyInline(true);
}
FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
@@ -3127,7 +3211,7 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const {
// Skip self-referential return types.
const SourceManager &SM = getASTContext().getSourceManager();
SourceRange RTRange = FTL.getReturnLoc().getSourceRange();
- SourceLocation Boundary = getNameInfo().getLocStart();
+ SourceLocation Boundary = getNameInfo().getBeginLoc();
if (RTRange.isInvalid() || Boundary.isInvalid() ||
!SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary))
return SourceRange();
@@ -3147,20 +3231,6 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
return FTL.getExceptionSpecRange();
}
-const Attr *FunctionDecl::getUnusedResultAttr() const {
- QualType RetType = getReturnType();
- if (const auto *Ret = RetType->getAsRecordDecl()) {
- if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>())
- return R;
- } else if (const auto *ET = RetType->getAs<EnumType>()) {
- if (const EnumDecl *ED = ET->getDecl()) {
- if (const auto *R = ED->getAttr<WarnUnusedResultAttr>())
- return R;
- }
- }
- return getAttr<WarnUnusedResultAttr>();
-}
-
/// For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
@@ -3664,23 +3734,23 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
}
unsigned FunctionDecl::getODRHash() const {
- assert(HasODRHash);
+ assert(hasODRHash());
return ODRHash;
}
unsigned FunctionDecl::getODRHash() {
- if (HasODRHash)
+ if (hasODRHash())
return ODRHash;
if (auto *FT = getInstantiatedFromMemberFunction()) {
- HasODRHash = true;
+ setHasODRHash(true);
ODRHash = FT->getODRHash();
return ODRHash;
}
class ODRHash Hash;
Hash.AddFunctionDecl(this);
- HasODRHash = true;
+ setHasODRHash(true);
ODRHash = Hash.CalculateHash();
return ODRHash;
}
@@ -3749,7 +3819,7 @@ SourceRange FieldDecl::getSourceRange() const {
if (!FinalExpr)
FinalExpr = getBitWidth();
if (FinalExpr)
- return SourceRange(getInnerLocStart(), FinalExpr->getLocEnd());
+ return SourceRange(getInnerLocStart(), FinalExpr->getEndLoc());
return DeclaratorDecl::getSourceRange();
}
@@ -3767,6 +3837,22 @@ void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
// TagDecl Implementation
//===----------------------------------------------------------------------===//
+TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
+ SourceLocation StartL)
+ : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
+ TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
+ assert((DK != Enum || TK == TTK_Enum) &&
+ "EnumDecl not matched with TTK_Enum");
+ setPreviousDecl(PrevDecl);
+ setTagKind(TK);
+ setCompleteDefinition(false);
+ setBeingDefined(false);
+ setEmbeddedInDeclarator(false);
+ setFreeStanding(false);
+ setCompleteDefinitionRequired(false);
+}
+
SourceLocation TagDecl::getOuterLocStart() const {
return getTemplateOrInnerLocStart(this);
}
@@ -3789,7 +3875,7 @@ void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
}
void TagDecl::startDefinition() {
- IsBeingDefined = true;
+ setBeingDefined(true);
if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
struct CXXRecordDecl::DefinitionData *Data =
@@ -3804,8 +3890,8 @@ void TagDecl::completeDefinition() {
cast<CXXRecordDecl>(this)->hasDefinition()) &&
"definition completed but not started");
- IsCompleteDefinition = true;
- IsBeingDefined = false;
+ setCompleteDefinition(true);
+ setBeingDefined(false);
if (ASTMutationListener *L = getASTMutationListener())
L->CompletedTagDefinition(this);
@@ -3816,7 +3902,7 @@ TagDecl *TagDecl::getDefinition() const {
return const_cast<TagDecl *>(this);
// If it's possible for us to have an out-of-date definition, check now.
- if (MayHaveOutOfDateDef) {
+ if (mayHaveOutOfDateDef()) {
if (IdentifierInfo *II = getIdentifier()) {
if (II->isOutOfDate()) {
updateOutOfDate(*II);
@@ -3869,6 +3955,21 @@ void TagDecl::setTemplateParameterListsInfo(
// EnumDecl Implementation
//===----------------------------------------------------------------------===//
+EnumDecl::EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
+ bool Scoped, bool ScopedUsingClassTag, bool Fixed)
+ : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
+ assert(Scoped || !ScopedUsingClassTag);
+ IntegerType = nullptr;
+ setNumPositiveBits(0);
+ setNumNegativeBits(0);
+ setScoped(Scoped);
+ setScopedUsingClassTag(ScopedUsingClassTag);
+ setFixed(Fixed);
+ setHasODRHash(false);
+ ODRHash = 0;
+}
+
void EnumDecl::anchor() {}
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
@@ -3878,7 +3979,7 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
bool IsScopedUsingClassTag, bool IsFixed) {
auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
IsScoped, IsScopedUsingClassTag, IsFixed);
- Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+ Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
C.getTypeDeclType(Enum, PrevDecl);
return Enum;
}
@@ -3887,7 +3988,7 @@ EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
EnumDecl *Enum =
new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr, false, false, false);
- Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+ Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
return Enum;
}
@@ -3971,12 +4072,12 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
}
unsigned EnumDecl::getODRHash() {
- if (HasODRHash)
+ if (hasODRHash())
return ODRHash;
class ODRHash Hash;
Hash.AddEnumDecl(this);
- HasODRHash = true;
+ setHasODRHash(true);
ODRHash = Hash.CalculateHash();
return ODRHash;
}
@@ -3989,14 +4090,18 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
RecordDecl *PrevDecl)
- : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc),
- HasFlexibleArrayMember(false), AnonymousStructOrUnion(false),
- HasObjectMember(false), HasVolatileMember(false),
- LoadedFieldsFromExternalStorage(false),
- NonTrivialToPrimitiveDefaultInitialize(false),
- NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),
- ParamDestroyedInCallee(false), ArgPassingRestrictions(APK_CanPassInRegs) {
- assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
+ : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
+ assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!");
+ setHasFlexibleArrayMember(false);
+ setAnonymousStructOrUnion(false);
+ setHasObjectMember(false);
+ setHasVolatileMember(false);
+ setHasLoadedFieldsFromExternalStorage(false);
+ setNonTrivialToPrimitiveDefaultInitialize(false);
+ setNonTrivialToPrimitiveCopy(false);
+ setNonTrivialToPrimitiveDestroy(false);
+ setParamDestroyedInCallee(false);
+ setArgPassingRestrictions(APK_CanPassInRegs);
}
RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
@@ -4004,7 +4109,7 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
IdentifierInfo *Id, RecordDecl* PrevDecl) {
RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
StartLoc, IdLoc, Id, PrevDecl);
- R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+ R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
C.getTypeDeclType(R, PrevDecl);
return R;
@@ -4014,7 +4119,7 @@ RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
RecordDecl *R =
new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(),
SourceLocation(), nullptr, nullptr);
- R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+ R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
return R;
}
@@ -4038,7 +4143,7 @@ void RecordDecl::setCapturedRecord() {
}
RecordDecl::field_iterator RecordDecl::field_begin() const {
- if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage)
+ if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage())
LoadFieldsFromExternalStorage();
return field_iterator(decl_iterator(FirstDecl));
@@ -4066,7 +4171,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
ExternalASTSource::Deserializing TheFields(Source);
SmallVector<Decl*, 64> Decls;
- LoadedFieldsFromExternalStorage = true;
+ setHasLoadedFieldsFromExternalStorage(true);
Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
}, Decls);
@@ -4148,6 +4253,15 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
+BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
+ : Decl(Block, DC, CaretLoc), DeclContext(Block) {
+ setIsVariadic(false);
+ setCapturesCXXThis(false);
+ setBlockMissingReturnType(true);
+ setIsConversionFromLambda(false);
+ setDoesNotEscape(false);
+}
+
void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
assert(!ParamInfo && "Already has param info!");
@@ -4161,7 +4275,7 @@ void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
bool CapturesCXXThis) {
- this->CapturesCXXThis = CapturesCXXThis;
+ this->setCapturesCXXThis(CapturesCXXThis);
this->NumCaptures = Captures.size();
if (Captures.empty()) {
@@ -4182,7 +4296,7 @@ bool BlockDecl::capturesVariable(const VarDecl *variable) const {
}
SourceRange BlockDecl::getSourceRange() const {
- return SourceRange(getLocation(), Body? Body->getLocEnd() : getLocation());
+ return SourceRange(getLocation(), Body ? Body->getEndLoc() : getLocation());
}
//===----------------------------------------------------------------------===//
@@ -4315,7 +4429,7 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
FunctionDecl *New =
new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo,
SC, isInlineSpecified, isConstexprSpecified);
- New->HasWrittenPrototype = hasWrittenPrototype;
+ New->setHasWrittenPrototype(hasWrittenPrototype);
return New;
}
@@ -4398,7 +4512,7 @@ IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
SourceRange EnumConstantDecl::getSourceRange() const {
SourceLocation End = getLocation();
if (Init)
- End = Init->getLocEnd();
+ End = Init->getEndLoc();
return SourceRange(getLocation(), End);
}
@@ -4472,14 +4586,14 @@ SourceRange TypedefDecl::getSourceRange() const {
if (typeIsPostfix(TInfo->getType()))
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
}
- return SourceRange(getLocStart(), RangeEnd);
+ return SourceRange(getBeginLoc(), RangeEnd);
}
SourceRange TypeAliasDecl::getSourceRange() const {
- SourceLocation RangeEnd = getLocStart();
+ SourceLocation RangeEnd = getBeginLoc();
if (TypeSourceInfo *TInfo = getTypeSourceInfo())
RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
- return SourceRange(getLocStart(), RangeEnd);
+ return SourceRange(getBeginLoc(), RangeEnd);
}
void FileScopeAsmDecl::anchor() {}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 700ddd389ddd..b83082e9eb08 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -153,12 +153,12 @@ void Decl::setInvalidDecl(bool Invalid) {
}
const char *DeclContext::getDeclKindName() const {
- switch (DeclKind) {
- default: llvm_unreachable("Declaration context not in DeclNodes.inc!");
+ switch (getDeclKind()) {
#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
}
+ llvm_unreachable("Declaration context not in DeclNodes.inc!");
}
bool Decl::StatisticsEnabled = false;
@@ -810,6 +810,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCCategoryImpl:
case Import:
case OMPThreadPrivate:
+ case OMPRequires:
case OMPCapturedExpr:
case Empty:
// Never looked up by name.
@@ -836,6 +837,29 @@ void Decl::dropAttrs() {
getASTContext().eraseDeclAttrs(this);
}
+void Decl::addAttr(Attr *A) {
+ if (!hasAttrs()) {
+ setAttrs(AttrVec(1, A));
+ return;
+ }
+
+ AttrVec &Attrs = getAttrs();
+ if (!A->isInherited()) {
+ Attrs.push_back(A);
+ return;
+ }
+
+ // Attribute inheritance is processed after attribute parsing. To keep the
+ // order as in the source code, add inherited attributes before non-inherited
+ // ones.
+ auto I = Attrs.begin(), E = Attrs.end();
+ for (; I != E; ++I) {
+ if (!(*I)->isInherited())
+ break;
+ }
+ Attrs.insert(I, A);
+}
+
const AttrVec &Decl::getAttrs() const {
assert(HasAttrs && "No attrs to get!");
return getASTContext().getDeclAttrs(this);
@@ -930,6 +954,10 @@ bool Decl::AccessDeclContextSanity() const {
static Decl::Kind getKind(const Decl *D) { return D->getKind(); }
static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }
+int64_t Decl::getID() const {
+ return getASTContext().getAllocator().identifyKnownAlignedObject<Decl>(this);
+}
+
const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
QualType Ty;
if (const auto *D = dyn_cast<ValueDecl>(this))
@@ -980,6 +1008,16 @@ Decl *DeclContext::getNonClosureAncestor() {
// DeclContext Implementation
//===----------------------------------------------------------------------===//
+DeclContext::DeclContext(Decl::Kind K) {
+ DeclContextBits.DeclKind = K;
+ setHasExternalLexicalStorage(false);
+ setHasExternalVisibleStorage(false);
+ setNeedToReconcileExternalVisibleStorage(false);
+ setHasLazyLocalLexicalLookups(false);
+ setHasLazyExternalLexicalLookups(false);
+ setUseQualifiedLookup(false);
+}
+
bool DeclContext::classof(const Decl *D) {
switch (D->getKind()) {
#define DECL(NAME, BASE)
@@ -1007,7 +1045,7 @@ DeclContext::~DeclContext() = default;
/// a friend function the parent lookup context is the lexical context, which
/// is the class in which the friend is declared.
DeclContext *DeclContext::getLookupParent() {
- // FIXME: Find a better way to identify friends
+ // FIXME: Find a better way to identify friends.
if (isa<FunctionDecl>(this))
if (getParent()->getRedeclContext()->isFileContext() &&
getLexicalParent()->getRedeclContext()->isRecord())
@@ -1070,9 +1108,9 @@ bool DeclContext::isDependentContext() const {
}
bool DeclContext::isTransparentContext() const {
- if (DeclKind == Decl::Enum)
+ if (getDeclKind() == Decl::Enum)
return !cast<EnumDecl>(this)->isScoped();
- else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export)
+ else if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export)
return true;
return false;
@@ -1118,7 +1156,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
}
DeclContext *DeclContext::getPrimaryContext() {
- switch (DeclKind) {
+ switch (getDeclKind()) {
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::LinkageSpec:
@@ -1154,7 +1192,7 @@ DeclContext *DeclContext::getPrimaryContext() {
return this;
default:
- if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) {
+ if (getDeclKind() >= Decl::firstTag && getDeclKind() <= Decl::lastTag) {
// If this is a tag type that has a definition or is currently
// being defined, that definition is our primary context.
auto *Tag = cast<TagDecl>(this);
@@ -1174,7 +1212,8 @@ DeclContext *DeclContext::getPrimaryContext() {
return Tag;
}
- assert(DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction &&
+ assert(getDeclKind() >= Decl::firstFunction &&
+ getDeclKind() <= Decl::lastFunction &&
"Unknown DeclContext kind");
return this;
}
@@ -1184,7 +1223,7 @@ void
DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
Contexts.clear();
- if (DeclKind != Decl::Namespace) {
+ if (getDeclKind() != Decl::Namespace) {
Contexts.push_back(this);
return;
}
@@ -1222,8 +1261,8 @@ DeclContext::BuildDeclChain(ArrayRef<Decl *> Decls,
/// built a lookup map. For every name in the map, pull in the new names from
/// the external storage.
void DeclContext::reconcileExternalVisibleStorage() const {
- assert(NeedToReconcileExternalVisibleStorage && LookupPtr);
- NeedToReconcileExternalVisibleStorage = false;
+ assert(hasNeedToReconcileExternalVisibleStorage() && LookupPtr);
+ setNeedToReconcileExternalVisibleStorage(false);
for (auto &Lookup : *LookupPtr)
Lookup.second.setHasExternalDecls();
@@ -1242,7 +1281,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
// Load the external declarations, if any.
SmallVector<Decl*, 64> Decls;
- ExternalLexicalStorage = false;
+ setHasExternalLexicalStorage(false);
Source->FindExternalLexicalDecls(this, Decls);
if (Decls.empty())
@@ -1252,7 +1291,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
// we need to ignore them.
bool FieldsAlreadyLoaded = false;
if (const auto *RD = dyn_cast<RecordDecl>(this))
- FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage;
+ FieldsAlreadyLoaded = RD->hasLoadedFieldsFromExternalStorage();
// Splice the newly-read declarations into the beginning of the list
// of declarations.
@@ -1273,7 +1312,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
StoredDeclsMap *Map;
if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
- if (DC->NeedToReconcileExternalVisibleStorage)
+ if (DC->hasNeedToReconcileExternalVisibleStorage())
DC->reconcileExternalVisibleStorage();
(*Map)[Name].removeExternalDecls();
@@ -1289,7 +1328,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
StoredDeclsMap *Map;
if (!(Map = DC->LookupPtr))
Map = DC->CreateStoredDeclsMap(Context);
- if (DC->NeedToReconcileExternalVisibleStorage)
+ if (DC->hasNeedToReconcileExternalVisibleStorage())
DC->reconcileExternalVisibleStorage();
StoredDeclsList &List = (*Map)[Name];
@@ -1366,6 +1405,12 @@ static bool shouldBeHidden(NamedDecl *D) {
D->isTemplateParameter())
return true;
+ // Skip friends and local extern declarations unless they're the first
+ // declaration of the entity.
+ if ((D->isLocalExternDecl() || D->getFriendObjectKind()) &&
+ D != D->getCanonicalDecl())
+ return true;
+
// Skip template specializations.
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
@@ -1424,7 +1469,9 @@ void DeclContext::removeDecl(Decl *D) {
if (Map) {
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
assert(Pos != Map->end() && "no lookup entry for decl");
- if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND)
+ // Remove the decl only if it is contained.
+ StoredDeclsList::DeclsTy *Vec = Pos->second.getAsVector();
+ if ((Vec && is_contained(*Vec, ND)) || Pos->second.getAsDecl() == ND)
Pos->second.remove(ND);
}
} while (DC->isTransparentContext() && (DC = DC->getParent()));
@@ -1483,21 +1530,24 @@ void DeclContext::addDeclInternal(Decl *D) {
StoredDeclsMap *DeclContext::buildLookup() {
assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
- if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups)
+ if (!hasLazyLocalLexicalLookups() &&
+ !hasLazyExternalLexicalLookups())
return LookupPtr;
SmallVector<DeclContext *, 2> Contexts;
collectAllContexts(Contexts);
- if (HasLazyExternalLexicalLookups) {
- HasLazyExternalLexicalLookups = false;
+ if (hasLazyExternalLexicalLookups()) {
+ setHasLazyExternalLexicalLookups(false);
for (auto *DC : Contexts) {
- if (DC->hasExternalLexicalStorage())
- HasLazyLocalLexicalLookups |=
- DC->LoadLexicalDeclsFromExternalStorage();
+ if (DC->hasExternalLexicalStorage()) {
+ bool LoadedDecls = DC->LoadLexicalDeclsFromExternalStorage();
+ setHasLazyLocalLexicalLookups(
+ hasLazyLocalLexicalLookups() | LoadedDecls );
+ }
}
- if (!HasLazyLocalLexicalLookups)
+ if (!hasLazyLocalLexicalLookups())
return LookupPtr;
}
@@ -1505,7 +1555,7 @@ StoredDeclsMap *DeclContext::buildLookup() {
buildLookupImpl(DC, hasExternalVisibleStorage());
// We no longer have any lazy decls.
- HasLazyLocalLexicalLookups = false;
+ setHasLazyLocalLexicalLookups(false);
return LookupPtr;
}
@@ -1543,7 +1593,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr;
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) const {
- assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
+ assert(getDeclKind() != Decl::LinkageSpec &&
+ getDeclKind() != Decl::Export &&
"should not perform lookups into transparent contexts");
const DeclContext *PrimaryContext = getPrimaryContext();
@@ -1560,12 +1611,13 @@ DeclContext::lookup(DeclarationName Name) const {
if (hasExternalVisibleStorage()) {
assert(Source && "external visible storage but no external source?");
- if (NeedToReconcileExternalVisibleStorage)
+ if (hasNeedToReconcileExternalVisibleStorage())
reconcileExternalVisibleStorage();
StoredDeclsMap *Map = LookupPtr;
- if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
+ if (hasLazyLocalLexicalLookups() ||
+ hasLazyExternalLexicalLookups())
// FIXME: Make buildLookup const?
Map = const_cast<DeclContext*>(this)->buildLookup();
@@ -1590,7 +1642,8 @@ DeclContext::lookup(DeclarationName Name) const {
}
StoredDeclsMap *Map = LookupPtr;
- if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
+ if (hasLazyLocalLexicalLookups() ||
+ hasLazyExternalLexicalLookups())
Map = const_cast<DeclContext*>(this)->buildLookup();
if (!Map)
@@ -1605,7 +1658,8 @@ DeclContext::lookup(DeclarationName Name) const {
DeclContext::lookup_result
DeclContext::noload_lookup(DeclarationName Name) {
- assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
+ assert(getDeclKind() != Decl::LinkageSpec &&
+ getDeclKind() != Decl::Export &&
"should not perform lookups into transparent contexts");
DeclContext *PrimaryContext = getPrimaryContext();
@@ -1626,12 +1680,12 @@ DeclContext::noload_lookup(DeclarationName Name) {
// now. Don't import any external declarations, not even if we know we have
// some missing from the external visible lookups.
void DeclContext::loadLazyLocalLexicalLookups() {
- if (HasLazyLocalLexicalLookups) {
+ if (hasLazyLocalLexicalLookups()) {
SmallVector<DeclContext *, 2> Contexts;
collectAllContexts(Contexts);
for (auto *Context : Contexts)
buildLookupImpl(Context, hasExternalVisibleStorage());
- HasLazyLocalLexicalLookups = false;
+ setHasLazyLocalLexicalLookups(false);
}
}
@@ -1649,7 +1703,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
// If we have a lookup table, check there first. Maybe we'll get lucky.
// FIXME: Should we be checking these flags on the primary context?
- if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) {
+ if (Name && !hasLazyLocalLexicalLookups() &&
+ !hasLazyExternalLexicalLookups()) {
if (StoredDeclsMap *Map = LookupPtr) {
StoredDeclsMap::iterator Pos = Map->find(Name);
if (Pos != Map->end()) {
@@ -1674,8 +1729,18 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
DeclContext *DeclContext::getRedeclContext() {
DeclContext *Ctx = this;
- // Skip through transparent contexts.
- while (Ctx->isTransparentContext())
+
+ // In C, a record type is the redeclaration context for its fields only. If
+ // we arrive at a record context after skipping anything else, we should skip
+ // the record as well. Currently, this means skipping enumerations because
+ // they're the only transparent context that can exist within a struct or
+ // union.
+ bool SkipRecords = getDeclKind() == Decl::Kind::Enum &&
+ !getParentASTContext().getLangOpts().CPlusPlus;
+
+ // Skip through contexts to get to the redeclaration context. Transparent
+ // contexts are always skipped.
+ while ((SkipRecords && Ctx->isRecord()) || Ctx->isTransparentContext())
Ctx = Ctx->getParent();
return Ctx;
}
@@ -1758,7 +1823,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
buildLookup();
makeDeclVisibleInContextImpl(D, Internal);
} else {
- HasLazyLocalLexicalLookups = true;
+ setHasLazyLocalLexicalLookups(true);
}
// If we are a transparent context or inline namespace, insert into our
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 51e8e14f804a..31ffeb0dcd1e 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -128,7 +128,7 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
bool DelayTypeCreation) {
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
PrevDecl);
- R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+ R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
// FIXME: DelayTypeCreation seems like such a hack
if (!DelayTypeCreation)
@@ -143,11 +143,11 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
LambdaCaptureDefault CaptureDefault) {
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
nullptr, nullptr);
- R->IsBeingDefined = true;
+ R->setBeingDefined(true);
R->DefinitionData =
new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
CaptureDefault);
- R->MayHaveOutOfDateDef = false;
+ R->setMayHaveOutOfDateDef(false);
R->setImplicit(true);
C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
return R;
@@ -158,7 +158,7 @@ CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
auto *R = new (C, ID) CXXRecordDecl(
CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
- R->MayHaveOutOfDateDef = false;
+ R->setMayHaveOutOfDateDef(false);
return R;
}
@@ -628,6 +628,24 @@ bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType(
return false;
}
+bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const {
+ assert(isLambda() && "not a lambda");
+
+ // C++2a [expr.prim.lambda.capture]p11:
+ // The closure type associated with a lambda-expression has no default
+ // constructor if the lambda-expression has a lambda-capture and a
+ // defaulted default constructor otherwise. It has a deleted copy
+ // assignment operator if the lambda-expression has a lambda-capture and
+ // defaulted copy and move assignment operators otherwise.
+ //
+ // C++17 [expr.prim.lambda]p21:
+ // The closure type associated with a lambda-expression has no default
+ // constructor and a deleted copy assignment operator.
+ if (getLambdaCaptureDefault() != LCD_None)
+ return false;
+ return getASTContext().getLangOpts().CPlusPlus2a;
+}
+
void CXXRecordDecl::addedMember(Decl *D) {
if (!D->isImplicit() &&
!isa<FieldDecl>(D) &&
@@ -731,9 +749,14 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// C++11 [dcl.init.aggr]p1: DR1518
- // An aggregate is an array or a class with no user-provided, explicit, or
- // inherited constructors
- if (Constructor->isUserProvided() || Constructor->isExplicit())
+ // An aggregate is an array or a class with no user-provided [or]
+ // explicit [...] constructors
+ // C++20 [dcl.init.aggr]p1:
+ // An aggregate is an array or a class with no user-declared [...]
+ // constructors
+ if (getASTContext().getLangOpts().CPlusPlus2a
+ ? !Constructor->isImplicit()
+ : (Constructor->isUserProvided() || Constructor->isExplicit()))
data().Aggregate = false;
}
@@ -1327,6 +1350,15 @@ bool CXXRecordDecl::isGenericLambda() const {
return getLambdaData().IsGenericLambda;
}
+#ifndef NDEBUG
+static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) {
+ for (auto *D : R)
+ if (!declaresSameEntity(D, R.front()))
+ return false;
+ return true;
+}
+#endif
+
CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
if (!isLambda()) return nullptr;
DeclarationName Name =
@@ -1334,7 +1366,8 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
DeclContext::lookup_result Calls = lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");
- assert(Calls.size() == 1 && "More than one lambda call operator!");
+ assert(allLookupResultsAreTheSame(Calls) &&
+ "More than one lambda call operator!");
NamedDecl *CallOp = Calls.front();
if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
@@ -1349,7 +1382,8 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
&getASTContext().Idents.get(getLambdaStaticInvokerName());
DeclContext::lookup_result Invoker = lookup(Name);
if (Invoker.empty()) return nullptr;
- assert(Invoker.size() == 1 && "More than one static invoker operator!");
+ assert(allLookupResultsAreTheSame(Invoker) &&
+ "More than one static invoker operator!");
NamedDecl *InvokerFun = Invoker.front();
if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun))
return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl());
@@ -1994,7 +2028,9 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
return nullptr;
}
-bool CXXMethodDecl::isUsualDeallocationFunction() const {
+bool CXXMethodDecl::isUsualDeallocationFunction(
+ SmallVectorImpl<const FunctionDecl *> &PreventedBy) const {
+ assert(PreventedBy.empty() && "PreventedBy is expected to be empty");
if (getOverloadedOperator() != OO_Delete &&
getOverloadedOperator() != OO_Array_Delete)
return false;
@@ -2052,14 +2088,16 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
// This function is a usual deallocation function if there are no
// single-parameter deallocation functions of the same kind.
DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
- for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
- I != E; ++I) {
- if (const auto *FD = dyn_cast<FunctionDecl>(*I))
- if (FD->getNumParams() == 1)
- return false;
+ bool Result = true;
+ for (const auto *D : R) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getNumParams() == 1) {
+ PreventedBy.push_back(FD);
+ Result = false;
+ }
+ }
}
-
- return true;
+ return Result;
}
bool CXXMethodDecl::isCopyAssignmentOperator() const {
@@ -2135,19 +2173,24 @@ CXXMethodDecl::overridden_methods() const {
return getASTContext().overridden_methods(this);
}
-QualType CXXMethodDecl::getThisType(ASTContext &C) const {
+QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
+ const CXXRecordDecl *Decl) {
+ ASTContext &C = Decl->getASTContext();
+ QualType ClassTy = C.getTypeDeclType(Decl);
+ ClassTy = C.getQualifiedType(ClassTy, FPT->getTypeQuals());
+ return C.getPointerType(ClassTy);
+}
+
+QualType CXXMethodDecl::getThisType() const {
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
// If the member function is declared const, the type of this is const X*,
// if the member function is declared volatile, the type of this is
// volatile X*, and if the member function is declared const volatile,
// the type of this is const volatile X*.
-
assert(isInstance() && "No 'this' for static methods!");
- QualType ClassTy = C.getTypeDeclType(getParent());
- ClassTy = C.getQualifiedType(ClassTy,
- Qualifiers::fromCVRUMask(getTypeQualifiers()));
- return C.getPointerType(ClassTy);
+ return CXXMethodDecl::getThisType(getType()->getAs<FunctionProtoType>(),
+ getParent());
}
bool CXXMethodDecl::hasInlineBody() const {
@@ -2208,6 +2251,11 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
: Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R),
IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {}
+int64_t CXXCtorInitializer::getID(const ASTContext &Context) const {
+ return Context.getAllocator()
+ .identifyKnownAlignedObject<CXXCtorInitializer>(this);
+}
+
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
@@ -2246,6 +2294,21 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
return SourceRange(getSourceLocation(), getRParenLoc());
}
+CXXConstructorDecl::CXXConstructorDecl(
+ ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
+ bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared,
+ bool isConstexpr, InheritedConstructor Inherited)
+ : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
+ SC_None, isInline, isConstexpr, SourceLocation()) {
+ setNumCtorInitializers(0);
+ setInheritingConstructor(static_cast<bool>(Inherited));
+ setImplicit(isImplicitlyDeclared);
+ if (Inherited)
+ *getTrailingObjects<InheritedConstructor>() = Inherited;
+ setExplicitSpecified(isExplicitSpecified);
+}
+
void CXXConstructorDecl::anchor() {}
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
@@ -2255,7 +2318,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
false, false, false, false, InheritedConstructor());
- Result->IsInheritingConstructor = Inherited;
+ Result->setInheritingConstructor(Inherited);
return Result;
}
@@ -2451,6 +2514,15 @@ bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
getConversionType()->isBlockPointerType();
}
+LinkageSpecDecl::LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
+ SourceLocation LangLoc, LanguageIDs lang,
+ bool HasBraces)
+ : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
+ ExternLoc(ExternLoc), RBraceLoc(SourceLocation()) {
+ setLanguage(lang);
+ LinkageSpecDeclBits.HasBraces = HasBraces;
+}
+
void LinkageSpecDecl::anchor() {}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
@@ -2838,6 +2910,8 @@ void DecompositionDecl::printName(llvm::raw_ostream &os) const {
os << ']';
}
+void MSPropertyDecl::anchor() {}
+
MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N,
QualType T, TypeSourceInfo *TInfo,
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 01fd10429fc1..1ed7fc71b025 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -65,6 +65,13 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
+ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC,
+ IdentifierInfo *Id, SourceLocation nameLoc,
+ SourceLocation atStartLoc)
+ : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) {
+ setAtStartLoc(atStartLoc);
+}
+
void ObjCContainerDecl::anchor() {}
/// getIvarDecl - This method looks up an ivar in this ContextDecl.
@@ -350,7 +357,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const {
SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
if (TypeSourceInfo *superTInfo = getSuperClassTInfo())
- return superTInfo->getTypeLoc().getLocStart();
+ return superTInfo->getTypeLoc().getBeginLoc();
return SourceLocation();
}
@@ -769,6 +776,37 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
// ObjCMethodDecl
//===----------------------------------------------------------------------===//
+ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
+ Selector SelInfo, QualType T,
+ TypeSourceInfo *ReturnTInfo,
+ DeclContext *contextDecl, bool isInstance,
+ bool isVariadic, bool isPropertyAccessor,
+ bool isImplicitlyDeclared, bool isDefined,
+ ImplementationControl impControl,
+ bool HasRelatedResultType)
+ : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
+ DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
+ DeclEndLoc(endLoc) {
+
+ // Initialized the bits stored in DeclContext.
+ ObjCMethodDeclBits.Family =
+ static_cast<ObjCMethodFamily>(InvalidObjCMethodFamily);
+ setInstanceMethod(isInstance);
+ setVariadic(isVariadic);
+ setPropertyAccessor(isPropertyAccessor);
+ setDefined(isDefined);
+ setIsRedeclaration(false);
+ setHasRedeclaration(false);
+ setDeclImplementation(impControl);
+ setObjCDeclQualifier(OBJC_TQ_None);
+ setRelatedResultType(HasRelatedResultType);
+ setSelLocsKind(SelLoc_StandardNoSpace);
+ setOverriding(false);
+ setHasSkippedBody(false);
+
+ setImplicit(isImplicitlyDeclared);
+}
+
ObjCMethodDecl *ObjCMethodDecl::Create(
ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
@@ -791,6 +829,14 @@ bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
hasAttr<ObjCDesignatedInitializerAttr>();
}
+bool ObjCMethodDecl::definedInNSObject(const ASTContext &Ctx) const {
+ if (const auto *PD = dyn_cast<const ObjCProtocolDecl>(getDeclContext()))
+ return PD->getIdentifier() == Ctx.getNSObjectName();
+ if (const auto *ID = dyn_cast<const ObjCInterfaceDecl>(getDeclContext()))
+ return ID->getIdentifier() == Ctx.getNSObjectName();
+ return false;
+}
+
bool ObjCMethodDecl::isDesignatedInitializerForTheInterface(
const ObjCMethodDecl **InitMethod) const {
if (getMethodFamily() != OMF_init)
@@ -810,8 +856,8 @@ Stmt *ObjCMethodDecl::getBody() const {
void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
assert(PrevMethod);
getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
- IsRedeclaration = true;
- PrevMethod->HasRedeclaration = true;
+ setIsRedeclaration(true);
+ PrevMethod->setHasRedeclaration(true);
}
void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
@@ -846,9 +892,9 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C,
if (isImplicit())
return setParamsAndSelLocs(C, Params, llvm::None);
- SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params,
- DeclEndLoc);
- if (SelLocsKind != SelLoc_NonStandard)
+ setSelLocsKind(hasStandardSelectorLocs(getSelector(), SelLocs, Params,
+ DeclEndLoc));
+ if (getSelLocsKind() != SelLoc_NonStandard)
return setParamsAndSelLocs(C, Params, llvm::None);
setParamsAndSelLocs(C, Params, SelLocs);
@@ -860,7 +906,7 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C,
ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
ASTContext &Ctx = getASTContext();
ObjCMethodDecl *Redecl = nullptr;
- if (HasRedeclaration)
+ if (hasRedeclaration())
Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this));
if (Redecl)
return Redecl;
@@ -931,14 +977,14 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
return this;
}
-SourceLocation ObjCMethodDecl::getLocEnd() const {
+SourceLocation ObjCMethodDecl::getEndLoc() const {
if (Stmt *Body = getBody())
- return Body->getLocEnd();
+ return Body->getEndLoc();
return DeclEndLoc;
}
ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
- auto family = static_cast<ObjCMethodFamily>(Family);
+ auto family = static_cast<ObjCMethodFamily>(ObjCMethodDeclBits.Family);
if (family != static_cast<unsigned>(InvalidObjCMethodFamily))
return family;
@@ -954,7 +1000,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break;
case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break;
}
- Family = static_cast<unsigned>(family);
+ ObjCMethodDeclBits.Family = family;
return family;
}
@@ -1025,7 +1071,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
}
// Cache the result.
- Family = static_cast<unsigned>(family);
+ ObjCMethodDeclBits.Family = family;
return family;
}
diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp
index f5c3599ef6c6..b77a67cbf38d 100644
--- a/lib/AST/DeclOpenMP.cpp
+++ b/lib/AST/DeclOpenMP.cpp
@@ -54,9 +54,49 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
}
//===----------------------------------------------------------------------===//
+// OMPRequiresDecl Implementation.
+//===----------------------------------------------------------------------===//
+
+void OMPRequiresDecl::anchor() {}
+
+OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ArrayRef<OMPClause *> CL) {
+ OMPRequiresDecl *D =
+ new (C, DC, additionalSizeToAlloc<OMPClause *>(CL.size()))
+ OMPRequiresDecl(OMPRequires, DC, L);
+ D->NumClauses = CL.size();
+ D->setClauses(CL);
+ return D;
+}
+
+OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned N) {
+ OMPRequiresDecl *D = new (C, ID, additionalSizeToAlloc<OMPClause *>(N))
+ OMPRequiresDecl(OMPRequires, nullptr, SourceLocation());
+ D->NumClauses = N;
+ return D;
+}
+
+void OMPRequiresDecl::setClauses(ArrayRef<OMPClause *> CL) {
+ assert(CL.size() == NumClauses &&
+ "Number of clauses is not the same as the preallocated buffer");
+ std::uninitialized_copy(CL.begin(), CL.end(),
+ getTrailingObjects<OMPClause *>());
+}
+
+//===----------------------------------------------------------------------===//
// OMPDeclareReductionDecl Implementation.
//===----------------------------------------------------------------------===//
+OMPDeclareReductionDecl::OMPDeclareReductionDecl(
+ Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
+ QualType Ty, OMPDeclareReductionDecl *PrevDeclInScope)
+ : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr),
+ PrevDeclInScope(PrevDeclInScope) {
+ setInitializer(nullptr, CallInit);
+}
+
void OMPDeclareReductionDecl::anchor() {}
OMPDeclareReductionDecl *OMPDeclareReductionDecl::Create(
@@ -104,5 +144,5 @@ OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C,
SourceRange OMPCapturedExprDecl::getSourceRange() const {
assert(hasInit());
- return SourceRange(getInit()->getLocStart(), getInit()->getLocEnd());
+ return SourceRange(getInit()->getBeginLoc(), getInit()->getEndLoc());
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 09e22f19f87a..517851f9eeb1 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -100,6 +100,7 @@ namespace {
void VisitUsingDecl(UsingDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
+ void VisitOMPRequiresDecl(OMPRequiresDecl *D);
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
@@ -422,7 +423,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
// FIXME: Need to be able to tell the DeclPrinter when
const char *Terminator = nullptr;
- if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D))
+ if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) ||
+ isa<OMPRequiresDecl>(*D))
Terminator = nullptr;
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
Terminator = nullptr;
@@ -544,7 +546,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
prettyPrintAttributes(D);
if (Expr *Init = D->getInitExpr()) {
Out << " = ";
- Init->printPretty(Out, nullptr, Policy, Indentation, &Context);
+ Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
}
}
@@ -1091,6 +1093,10 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
printTemplateParameters(FD->getTemplateParameterList(I));
}
VisitRedeclarableTemplateDecl(D);
+ // Declare target attribute is special one, natural spelling for the pragma
+ // assumes "ending" construct so print it here.
+ if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
+ Out << "#pragma omp end declare target\n";
// Never print "instantiations" for deduction guides (they don't really
// have them).
@@ -1540,6 +1546,15 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
}
}
+void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
+ Out << "#pragma omp requires ";
+ if (!D->clauselist_empty()) {
+ OMPClausePrinter Printer(Out, Policy);
+ for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I)
+ Printer.Visit(*I);
+ }
+}
+
void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
if (!D->isInvalidDecl()) {
Out << "#pragma omp declare reduction (";
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 848427e7f9d9..76f29dac1647 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -149,6 +149,8 @@ void *allocateDefaultArgStorageChain(const ASTContext &C) {
// RedeclarableTemplateDecl Implementation
//===----------------------------------------------------------------------===//
+void RedeclarableTemplateDecl::anchor() {}
+
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
if (Common)
return Common;
@@ -300,6 +302,40 @@ ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size());
}
+void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
+ using Base = RedeclarableTemplateDecl;
+
+ // If we haven't created a common pointer yet, then it can just be created
+ // with the usual method.
+ if (!Base::Common)
+ return;
+
+ Common *ThisCommon = static_cast<Common *>(Base::Common);
+ Common *PrevCommon = nullptr;
+ SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
+ for (; Prev; Prev = Prev->getPreviousDecl()) {
+ if (Prev->Base::Common) {
+ PrevCommon = static_cast<Common *>(Prev->Base::Common);
+ break;
+ }
+ PreviousDecls.push_back(Prev);
+ }
+
+ // If the previous redecl chain hasn't created a common pointer yet, then just
+ // use this common pointer.
+ if (!PrevCommon) {
+ for (auto *D : PreviousDecls)
+ D->Base::Common = ThisCommon;
+ return;
+ }
+
+ // Ensure we don't leak any important state.
+ assert(ThisCommon->Specializations.size() == 0 &&
+ "Can't merge incompatible declarations!");
+
+ Base::Common = PrevCommon;
+}
+
//===----------------------------------------------------------------------===//
// ClassTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -473,7 +509,7 @@ SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
SourceRange TemplateTypeParmDecl::getSourceRange() const {
if (hasDefaultArgument() && !defaultArgumentWasInherited())
- return SourceRange(getLocStart(),
+ return SourceRange(getBeginLoc(),
getDefaultArgumentInfo()->getTypeLoc().getEndLoc());
else
return TypeDecl::getSourceRange();
@@ -712,7 +748,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
new (Context, DC) ClassTemplateSpecializationDecl(
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, PrevDecl);
- Result->MayHaveOutOfDateDef = false;
+ Result->setMayHaveOutOfDateDef(false);
Context.getTypeDeclType(Result, PrevDecl);
return Result;
@@ -723,7 +759,7 @@ ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
auto *Result =
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
- Result->MayHaveOutOfDateDef = false;
+ Result->setMayHaveOutOfDateDef(false);
return Result;
}
@@ -830,7 +866,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC,
Params, SpecializedTemplate, Args,
ASTArgInfos, PrevDecl);
Result->setSpecializationKind(TSK_ExplicitSpecialization);
- Result->MayHaveOutOfDateDef = false;
+ Result->setMayHaveOutOfDateDef(false);
Context.getInjectedClassNameType(Result, CanonInjectedType);
return Result;
@@ -840,7 +876,7 @@ ClassTemplatePartialSpecializationDecl *
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
- Result->MayHaveOutOfDateDef = false;
+ Result->setMayHaveOutOfDateDef(false);
return Result;
}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 9866d92f61eb..f2c152f918eb 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -39,74 +39,6 @@
using namespace clang;
-namespace clang {
-
-/// CXXSpecialName - Records the type associated with one of the
-/// "special" kinds of declaration names in C++, e.g., constructors,
-/// destructors, and conversion functions.
-class CXXSpecialName
- : public DeclarationNameExtra, public llvm::FoldingSetNode {
-public:
- /// Type - The type associated with this declaration name.
- QualType Type;
-
- /// FETokenInfo - Extra information associated with this declaration
- /// name that can be used by the front end.
- void *FETokenInfo;
-
- void Profile(llvm::FoldingSetNodeID &ID) {
- ID.AddInteger(ExtraKindOrNumArgs);
- ID.AddPointer(Type.getAsOpaquePtr());
- }
-};
-
-/// Contains extra information for the name of a C++ deduction guide.
-class CXXDeductionGuideNameExtra : public DeclarationNameExtra,
- public llvm::FoldingSetNode {
-public:
- /// The template named by the deduction guide.
- TemplateDecl *Template;
-
- /// FETokenInfo - Extra information associated with this operator
- /// name that can be used by the front end.
- void *FETokenInfo;
-
- void Profile(llvm::FoldingSetNodeID &ID) {
- ID.AddPointer(Template);
- }
-};
-
-/// CXXOperatorIdName - Contains extra information for the name of an
-/// overloaded operator in C++, such as "operator+.
-class CXXOperatorIdName : public DeclarationNameExtra {
-public:
- /// FETokenInfo - Extra information associated with this operator
- /// name that can be used by the front end.
- void *FETokenInfo;
-};
-
-/// CXXLiteralOperatorName - Contains the actual identifier that makes up the
-/// name.
-///
-/// This identifier is stored here rather than directly in DeclarationName so as
-/// to allow Objective-C selectors, which are about a million times more common,
-/// to consume minimal memory.
-class CXXLiteralOperatorIdName
- : public DeclarationNameExtra, public llvm::FoldingSetNode {
-public:
- IdentifierInfo *ID;
-
- /// FETokenInfo - Extra information associated with this operator
- /// name that can be used by the front end.
- void *FETokenInfo;
-
- void Profile(llvm::FoldingSetNodeID &FSID) {
- FSID.AddPointer(ID);
- }
-};
-
-} // namespace clang
-
static int compareInt(unsigned A, unsigned B) {
return (A < B ? -1 : (A > B ? 1 : 0));
}
@@ -117,10 +49,12 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
switch (LHS.getNameKind()) {
case DeclarationName::Identifier: {
- IdentifierInfo *LII = LHS.getAsIdentifierInfo();
- IdentifierInfo *RII = RHS.getAsIdentifierInfo();
- if (!LII) return RII ? -1 : 0;
- if (!RII) return 1;
+ IdentifierInfo *LII = LHS.castAsIdentifierInfo();
+ IdentifierInfo *RII = RHS.castAsIdentifierInfo();
+ if (!LII)
+ return RII ? -1 : 0;
+ if (!RII)
+ return 1;
return LII->getName().compare(RII->getName());
}
@@ -134,15 +68,18 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
return LHSSelector.getAsIdentifierInfo()->getName().compare(
- RHSSelector.getAsIdentifierInfo()->getName());
+ RHSSelector.getAsIdentifierInfo()->getName());
}
unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
switch (LHSSelector.getNameForSlot(I).compare(
- RHSSelector.getNameForSlot(I))) {
- case -1: return -1;
- case 1: return 1;
- default: break;
+ RHSSelector.getNameForSlot(I))) {
+ case -1:
+ return -1;
+ case 1:
+ return 1;
+ default:
+ break;
}
}
@@ -170,7 +107,7 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
case DeclarationName::CXXLiteralOperatorName:
return LHS.getCXXLiteralIdentifier()->getName().compare(
- RHS.getCXXLiteralIdentifier()->getName());
+ RHS.getCXXLiteralIdentifier()->getName());
case DeclarationName::CXXUsingDirective:
return 0;
@@ -199,25 +136,24 @@ static void printCXXConstructorDestructorName(QualType ClassType,
}
void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
- DeclarationName &N = *this;
- switch (N.getNameKind()) {
+ switch (getNameKind()) {
case DeclarationName::Identifier:
- if (const IdentifierInfo *II = N.getAsIdentifierInfo())
+ if (const IdentifierInfo *II = getAsIdentifierInfo())
OS << II->getName();
return;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- N.getObjCSelector().print(OS);
+ getObjCSelector().print(OS);
return;
case DeclarationName::CXXConstructorName:
- return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
+ return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
case DeclarationName::CXXDestructorName:
OS << '~';
- return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
+ return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
case DeclarationName::CXXDeductionGuideName:
OS << "<deduction guide for ";
@@ -226,13 +162,13 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
return;
case DeclarationName::CXXOperatorName: {
- static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
- nullptr,
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- Spelling,
+ static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
+ nullptr,
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
+ Spelling,
#include "clang/Basic/OperatorKinds.def"
};
- const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
+ const char *OpName = OperatorNames[getCXXOverloadedOperator()];
assert(OpName && "not an overloaded operator");
OS << "operator";
@@ -243,12 +179,12 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
}
case DeclarationName::CXXLiteralOperatorName:
- OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName();
+ OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
return;
case DeclarationName::CXXConversionFunctionName: {
OS << "operator ";
- QualType Type = N.getCXXNameType();
+ QualType Type = getCXXNameType();
if (const RecordType *Rec = Type->getAs<RecordType>()) {
OS << *Rec->getDecl();
return;
@@ -277,46 +213,6 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
} // namespace clang
-DeclarationName::NameKind DeclarationName::getNameKind() const {
- switch (getStoredNameKind()) {
- case StoredIdentifier: return Identifier;
- case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
- case StoredObjCOneArgSelector: return ObjCOneArgSelector;
-
- case StoredDeclarationNameExtra:
- switch (getExtra()->ExtraKindOrNumArgs) {
- case DeclarationNameExtra::CXXConstructor:
- return CXXConstructorName;
-
- case DeclarationNameExtra::CXXDestructor:
- return CXXDestructorName;
-
- case DeclarationNameExtra::CXXDeductionGuide:
- return CXXDeductionGuideName;
-
- case DeclarationNameExtra::CXXConversionFunction:
- return CXXConversionFunctionName;
-
- case DeclarationNameExtra::CXXLiteralOperator:
- return CXXLiteralOperatorName;
-
- case DeclarationNameExtra::CXXUsingDirective:
- return CXXUsingDirective;
-
- default:
- // Check if we have one of the CXXOperator* enumeration values.
- if (getExtra()->ExtraKindOrNumArgs <
- DeclarationNameExtra::CXXUsingDirective)
- return CXXOperatorName;
-
- return ObjCMultiArgSelector;
- }
- }
-
- // Can't actually get here.
- llvm_unreachable("This should be unreachable!");
-}
-
bool DeclarationName::isDependentName() const {
QualType T = getCXXNameType();
if (!T.isNull() && T->isDependentType())
@@ -337,241 +233,148 @@ std::string DeclarationName::getAsString() const {
return OS.str();
}
-QualType DeclarationName::getCXXNameType() const {
- if (CXXSpecialName *CXXName = getAsCXXSpecialName())
- return CXXName->Type;
- else
- return QualType();
-}
-
-TemplateDecl *DeclarationName::getCXXDeductionGuideTemplate() const {
- if (auto *Guide = getAsCXXDeductionGuideNameExtra())
- return Guide->Template;
- return nullptr;
-}
-
-OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
- if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
- unsigned value
- = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
- return static_cast<OverloadedOperatorKind>(value);
- } else {
- return OO_None;
- }
-}
-
-IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
- if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
- return CXXLit->ID;
- else
- return nullptr;
-}
-
-void *DeclarationName::getFETokenInfoAsVoidSlow() const {
+void *DeclarationName::getFETokenInfoSlow() const {
switch (getNameKind()) {
case Identifier:
- llvm_unreachable("Handled by getFETokenInfo()");
-
+ llvm_unreachable("case Identifier already handled by getFETokenInfo!");
case CXXConstructorName:
case CXXDestructorName:
case CXXConversionFunctionName:
- return getAsCXXSpecialName()->FETokenInfo;
-
- case CXXDeductionGuideName:
- return getAsCXXDeductionGuideNameExtra()->FETokenInfo;
-
+ return castAsCXXSpecialNameExtra()->FETokenInfo;
case CXXOperatorName:
- return getAsCXXOperatorIdName()->FETokenInfo;
-
+ return castAsCXXOperatorIdName()->FETokenInfo;
+ case CXXDeductionGuideName:
+ return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
case CXXLiteralOperatorName:
- return getAsCXXLiteralOperatorIdName()->FETokenInfo;
-
+ return castAsCXXLiteralOperatorIdName()->FETokenInfo;
default:
- llvm_unreachable("Declaration name has no FETokenInfo");
+ llvm_unreachable("DeclarationName has no FETokenInfo!");
}
}
-void DeclarationName::setFETokenInfo(void *T) {
+void DeclarationName::setFETokenInfoSlow(void *T) {
switch (getNameKind()) {
case Identifier:
- getAsIdentifierInfo()->setFETokenInfo(T);
- break;
-
+ llvm_unreachable("case Identifier already handled by setFETokenInfo!");
case CXXConstructorName:
case CXXDestructorName:
case CXXConversionFunctionName:
- getAsCXXSpecialName()->FETokenInfo = T;
+ castAsCXXSpecialNameExtra()->FETokenInfo = T;
break;
-
- case CXXDeductionGuideName:
- getAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
- break;
-
case CXXOperatorName:
- getAsCXXOperatorIdName()->FETokenInfo = T;
+ castAsCXXOperatorIdName()->FETokenInfo = T;
+ break;
+ case CXXDeductionGuideName:
+ castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
break;
-
case CXXLiteralOperatorName:
- getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
+ castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
break;
-
default:
- llvm_unreachable("Declaration name has no FETokenInfo");
+ llvm_unreachable("DeclarationName has no FETokenInfo!");
}
}
-DeclarationName DeclarationName::getUsingDirectiveName() {
- // Single instance of DeclarationNameExtra for using-directive
- static const DeclarationNameExtra UDirExtra =
- { DeclarationNameExtra::CXXUsingDirective };
-
- uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
- Ptr |= StoredDeclarationNameExtra;
-
- return DeclarationName(Ptr);
-}
-
LLVM_DUMP_METHOD void DeclarationName::dump() const {
llvm::errs() << *this << '\n';
}
DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
- CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
- CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
- CXXDeductionGuideNames = new llvm::FoldingSet<CXXDeductionGuideNameExtra>;
-
// Initialize the overloaded operator names.
- CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
- for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
- CXXOperatorNames[Op].ExtraKindOrNumArgs
- = Op + DeclarationNameExtra::CXXConversionFunction;
- CXXOperatorNames[Op].FETokenInfo = nullptr;
- }
-}
-
-DeclarationNameTable::~DeclarationNameTable() {
- auto *SpecialNames =
- static_cast<llvm::FoldingSet<CXXSpecialName> *>(CXXSpecialNamesImpl);
- auto *LiteralNames =
- static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName> *>(
- CXXLiteralOperatorNames);
- auto *DeductionGuideNames =
- static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>(
- CXXDeductionGuideNames);
-
- delete SpecialNames;
- delete LiteralNames;
- delete DeductionGuideNames;
-}
-
-DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
- return getCXXSpecialName(DeclarationName::CXXConstructorName,
- Ty.getUnqualifiedType());
-}
-
-DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
- return getCXXSpecialName(DeclarationName::CXXDestructorName,
- Ty.getUnqualifiedType());
+ for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
+ CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
}
DeclarationName
DeclarationNameTable::getCXXDeductionGuideName(TemplateDecl *Template) {
Template = cast<TemplateDecl>(Template->getCanonicalDecl());
- auto *DeductionGuideNames =
- static_cast<llvm::FoldingSet<CXXDeductionGuideNameExtra> *>(
- CXXDeductionGuideNames);
-
llvm::FoldingSetNodeID ID;
ID.AddPointer(Template);
void *InsertPos = nullptr;
- if (auto *Name = DeductionGuideNames->FindNodeOrInsertPos(ID, InsertPos))
+ if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
return DeclarationName(Name);
- auto *Name = new (Ctx) CXXDeductionGuideNameExtra;
- Name->ExtraKindOrNumArgs = DeclarationNameExtra::CXXDeductionGuide;
- Name->Template = Template;
- Name->FETokenInfo = nullptr;
-
- DeductionGuideNames->InsertNode(Name, InsertPos);
+ auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
+ CXXDeductionGuideNames.InsertNode(Name, InsertPos);
return DeclarationName(Name);
}
+DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
+ // The type of constructors is unqualified.
+ Ty = Ty.getUnqualifiedType();
+ // Do we already have this C++ constructor name ?
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(Ty.getAsOpaquePtr());
+ void *InsertPos = nullptr;
+ if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
+ return {Name, DeclarationName::StoredCXXConstructorName};
+
+ // We have to create it.
+ auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
+ CXXConstructorNames.InsertNode(SpecialName, InsertPos);
+ return {SpecialName, DeclarationName::StoredCXXConstructorName};
+}
+
+DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
+ // The type of destructors is unqualified.
+ Ty = Ty.getUnqualifiedType();
+ // Do we already have this C++ destructor name ?
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(Ty.getAsOpaquePtr());
+ void *InsertPos = nullptr;
+ if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
+ return {Name, DeclarationName::StoredCXXDestructorName};
+
+ // We have to create it.
+ auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
+ CXXDestructorNames.InsertNode(SpecialName, InsertPos);
+ return {SpecialName, DeclarationName::StoredCXXDestructorName};
+}
+
DeclarationName
DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
- return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
+ // Do we already have this C++ conversion function name ?
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(Ty.getAsOpaquePtr());
+ void *InsertPos = nullptr;
+ if (auto *Name =
+ CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
+ return {Name, DeclarationName::StoredCXXConversionFunctionName};
+
+ // We have to create it.
+ auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
+ CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
+ return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
}
DeclarationName
DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
CanQualType Ty) {
- assert(Kind >= DeclarationName::CXXConstructorName &&
- Kind <= DeclarationName::CXXConversionFunctionName &&
- "Kind must be a C++ special name kind");
- llvm::FoldingSet<CXXSpecialName> *SpecialNames
- = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
-
- DeclarationNameExtra::ExtraKind EKind;
switch (Kind) {
case DeclarationName::CXXConstructorName:
- EKind = DeclarationNameExtra::CXXConstructor;
- assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
- break;
+ return getCXXConstructorName(Ty);
case DeclarationName::CXXDestructorName:
- EKind = DeclarationNameExtra::CXXDestructor;
- assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
- break;
+ return getCXXDestructorName(Ty);
case DeclarationName::CXXConversionFunctionName:
- EKind = DeclarationNameExtra::CXXConversionFunction;
- break;
+ return getCXXConversionFunctionName(Ty);
default:
- return DeclarationName();
+ llvm_unreachable("Invalid kind in getCXXSpecialName!");
}
-
- // Unique selector, to guarantee there is one per name.
- llvm::FoldingSetNodeID ID;
- ID.AddInteger(EKind);
- ID.AddPointer(Ty.getAsOpaquePtr());
-
- void *InsertPos = nullptr;
- if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
- return DeclarationName(Name);
-
- CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
- SpecialName->ExtraKindOrNumArgs = EKind;
- SpecialName->Type = Ty;
- SpecialName->FETokenInfo = nullptr;
-
- SpecialNames->InsertNode(SpecialName, InsertPos);
- return DeclarationName(SpecialName);
-}
-
-DeclarationName
-DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
- return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
}
DeclarationName
DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
- llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
- = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
- (CXXLiteralOperatorNames);
-
llvm::FoldingSetNodeID ID;
ID.AddPointer(II);
void *InsertPos = nullptr;
- if (CXXLiteralOperatorIdName *Name =
- LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
- return DeclarationName (Name);
-
- CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
- LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
- LiteralName->ID = II;
- LiteralName->FETokenInfo = nullptr;
+ if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
+ return DeclarationName(Name);
- LiteralNames->InsertNode(LiteralName, InsertPos);
+ auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
+ CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
return DeclarationName(LiteralName);
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 7556c76c38bd..7cdd3b2c2a30 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -28,7 +28,6 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -192,7 +191,7 @@ bool Expr::isKnownToHaveBooleanValue() const {
// Amusing macro metaprogramming hack: check whether a class provides
// a more specific implementation of getExprLoc().
//
-// See also Stmt.cpp:{getLocStart(),getLocEnd()}.
+// See also Stmt.cpp:{getBeginLoc(),getEndLoc()}.
namespace {
/// This implementation is used when a class provides a custom
/// implementation of getExprLoc.
@@ -209,7 +208,7 @@ namespace {
template <class E>
SourceLocation getExprLocImpl(const Expr *expr,
SourceLocation (Expr::*v)() const) {
- return static_cast<const E*>(expr)->getLocStart();
+ return static_cast<const E *>(expr)->getBeginLoc();
}
}
@@ -342,16 +341,32 @@ void DeclRefExpr::computeDependence(const ASTContext &Ctx) {
ExprBits.ContainsUnexpandedParameterPack = true;
}
+DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
+ bool RefersToEnclosingVariableOrCapture, QualType T,
+ ExprValueKind VK, SourceLocation L,
+ const DeclarationNameLoc &LocInfo)
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
+ D(D), DNLoc(LocInfo) {
+ DeclRefExprBits.HasQualifier = false;
+ DeclRefExprBits.HasTemplateKWAndArgsInfo = false;
+ DeclRefExprBits.HasFoundDecl = false;
+ DeclRefExprBits.HadMultipleCandidates = false;
+ DeclRefExprBits.RefersToEnclosingVariableOrCapture =
+ RefersToEnclosingVariableOrCapture;
+ DeclRefExprBits.Loc = L;
+ computeDependence(Ctx);
+}
+
DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *D, bool RefersToEnclosingVariableOrCapture,
- const DeclarationNameInfo &NameInfo,
- NamedDecl *FoundD,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
+ bool RefersToEnclosingVariableOrCapture,
+ const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK)
- : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
- D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
+ D(D), DNLoc(NameInfo.getInfo()) {
+ DeclRefExprBits.Loc = NameInfo.getLoc();
DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0;
if (QualifierLoc) {
new (getTrailingObjects<NestedNameSpecifierLoc>())
@@ -447,31 +462,56 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
return new (Mem) DeclRefExpr(EmptyShell());
}
-SourceLocation DeclRefExpr::getLocStart() const {
+SourceLocation DeclRefExpr::getBeginLoc() const {
if (hasQualifier())
return getQualifierLoc().getBeginLoc();
- return getNameInfo().getLocStart();
+ return getNameInfo().getBeginLoc();
}
-SourceLocation DeclRefExpr::getLocEnd() const {
+SourceLocation DeclRefExpr::getEndLoc() const {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
- return getNameInfo().getLocEnd();
+ return getNameInfo().getEndLoc();
}
-PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
+PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
StringLiteral *SL)
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary,
FNTy->isDependentType(), FNTy->isDependentType(),
FNTy->isInstantiationDependentType(),
- /*ContainsUnexpandedParameterPack=*/false),
- Loc(L), Type(IT), FnName(SL) {}
+ /*ContainsUnexpandedParameterPack=*/false) {
+ PredefinedExprBits.Kind = IK;
+ assert((getIdentKind() == IK) &&
+ "IdentKind do not fit in PredefinedExprBitfields!");
+ bool HasFunctionName = SL != nullptr;
+ PredefinedExprBits.HasFunctionName = HasFunctionName;
+ PredefinedExprBits.Loc = L;
+ if (HasFunctionName)
+ setFunctionName(SL);
+}
+
+PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName)
+ : Expr(PredefinedExprClass, Empty) {
+ PredefinedExprBits.HasFunctionName = HasFunctionName;
+}
-StringLiteral *PredefinedExpr::getFunctionName() {
- return cast_or_null<StringLiteral>(FnName);
+PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
+ QualType FNTy, IdentKind IK,
+ StringLiteral *SL) {
+ bool HasFunctionName = SL != nullptr;
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
+ alignof(PredefinedExpr));
+ return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
}
-StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
- switch (IT) {
+PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx,
+ bool HasFunctionName) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
+ alignof(PredefinedExpr));
+ return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName);
+}
+
+StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
+ switch (IK) {
case Func:
return "__func__";
case Function:
@@ -489,15 +529,15 @@ StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
case PrettyFunctionNoVirtual:
break;
}
- llvm_unreachable("Unknown ident type for PredefinedExpr");
+ llvm_unreachable("Unknown ident kind for PredefinedExpr");
}
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
-std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
+std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
ASTContext &Context = CurrentDecl->getASTContext();
- if (IT == PredefinedExpr::FuncDName) {
+ if (IK == PredefinedExpr::FuncDName) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) {
std::unique_ptr<MangleContext> MC;
MC.reset(Context.createMangleContext());
@@ -532,21 +572,21 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
llvm::raw_svector_ostream Out(Buffer);
if (auto *DCBlock = dyn_cast<BlockDecl>(DC))
// For nested blocks, propagate up to the parent.
- Out << ComputeName(IT, DCBlock);
+ Out << ComputeName(IK, DCBlock);
else if (auto *DCDecl = dyn_cast<Decl>(DC))
- Out << ComputeName(IT, DCDecl) << "_block_invoke";
+ Out << ComputeName(IK, DCDecl) << "_block_invoke";
return Out.str();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
- if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual &&
- IT != FuncSig && IT != LFuncSig)
+ if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual &&
+ IK != FuncSig && IK != LFuncSig)
return FD->getNameAsString();
SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- if (MD->isVirtual() && IT != PrettyFunctionNoVirtual)
+ if (MD->isVirtual() && IK != PrettyFunctionNoVirtual)
Out << "virtual ";
if (MD->isStatic())
Out << "static ";
@@ -564,7 +604,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
- if (IT == FuncSig || IT == LFuncSig) {
+ if (IK == FuncSig || IK == LFuncSig) {
switch (AFT->getCallConv()) {
case CC_C: POut << "__cdecl "; break;
case CC_X86StdCall: POut << "__stdcall "; break;
@@ -589,7 +629,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
if (FT->isVariadic()) {
if (FD->getNumParams()) POut << ", ";
POut << "...";
- } else if ((IT == FuncSig || IT == LFuncSig ||
+ } else if ((IK == FuncSig || IK == LFuncSig ||
!Context.getLangOpts().CPlusPlus) &&
!Decl->getNumParams()) {
POut << "void";
@@ -688,7 +728,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
// CapturedDecl.
if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) {
const Decl *D = Decl::castFromDeclContext(DC);
- return ComputeName(IT, D);
+ return ComputeName(IK, D);
}
llvm_unreachable("CapturedDecl not inside a function or method");
}
@@ -713,7 +753,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
return Name.str().str();
}
- if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
+ if (isa<TranslationUnitDecl>(CurrentDecl) && IK == PrettyFunction) {
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
return "top level";
}
@@ -785,7 +825,7 @@ std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
// which is 43 characters.
SmallString<64> S;
FixedPointValueToString(
- S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale, Radix);
+ S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale);
return S.str();
}
@@ -861,66 +901,105 @@ double FloatingLiteral::getValueAsApproximateDouble() const {
return V.convertToDouble();
}
-int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) {
- int CharByteWidth = 0;
- switch(k) {
- case Ascii:
- case UTF8:
- CharByteWidth = target.getCharWidth();
- break;
- case Wide:
- CharByteWidth = target.getWCharWidth();
- break;
- case UTF16:
- CharByteWidth = target.getChar16Width();
- break;
- case UTF32:
- CharByteWidth = target.getChar32Width();
- break;
+unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target,
+ StringKind SK) {
+ unsigned CharByteWidth = 0;
+ switch (SK) {
+ case Ascii:
+ case UTF8:
+ CharByteWidth = Target.getCharWidth();
+ break;
+ case Wide:
+ CharByteWidth = Target.getWCharWidth();
+ break;
+ case UTF16:
+ CharByteWidth = Target.getChar16Width();
+ break;
+ case UTF32:
+ CharByteWidth = Target.getChar32Width();
+ break;
}
assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple");
CharByteWidth /= 8;
- assert((CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4)
- && "character byte widths supported are 1, 2, and 4 only");
+ assert((CharByteWidth == 1 || CharByteWidth == 2 || CharByteWidth == 4) &&
+ "The only supported character byte widths are 1,2 and 4!");
return CharByteWidth;
}
-StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str,
- StringKind Kind, bool Pascal, QualType Ty,
- const SourceLocation *Loc,
- unsigned NumStrs) {
- assert(C.getAsConstantArrayType(Ty) &&
+StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
+ const SourceLocation *Loc,
+ unsigned NumConcatenated)
+ : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
+ false) {
+ assert(Ctx.getAsConstantArrayType(Ty) &&
"StringLiteral must be of constant array type!");
+ unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind);
+ unsigned ByteLength = Str.size();
+ assert((ByteLength % CharByteWidth == 0) &&
+ "The size of the data must be a multiple of CharByteWidth!");
+
+ // Avoid the expensive division. The compiler should be able to figure it
+ // out by itself. However as of clang 7, even with the appropriate
+ // llvm_unreachable added just here, it is not able to do so.
+ unsigned Length;
+ switch (CharByteWidth) {
+ case 1:
+ Length = ByteLength;
+ break;
+ case 2:
+ Length = ByteLength / 2;
+ break;
+ case 4:
+ Length = ByteLength / 4;
+ break;
+ default:
+ llvm_unreachable("Unsupported character width!");
+ }
- // Allocate enough space for the StringLiteral plus an array of locations for
- // any concatenated string tokens.
- void *Mem =
- C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
- alignof(StringLiteral));
- StringLiteral *SL = new (Mem) StringLiteral(Ty);
+ StringLiteralBits.Kind = Kind;
+ StringLiteralBits.CharByteWidth = CharByteWidth;
+ StringLiteralBits.IsPascal = Pascal;
+ StringLiteralBits.NumConcatenated = NumConcatenated;
+ *getTrailingObjects<unsigned>() = Length;
- // OPTIMIZE: could allocate this appended to the StringLiteral.
- SL->setString(C,Str,Kind,Pascal);
+ // Initialize the trailing array of SourceLocation.
+ // This is safe since SourceLocation is POD-like.
+ std::memcpy(getTrailingObjects<SourceLocation>(), Loc,
+ NumConcatenated * sizeof(SourceLocation));
- SL->TokLocs[0] = Loc[0];
- SL->NumConcatenated = NumStrs;
+ // Initialize the trailing array of char holding the string data.
+ std::memcpy(getTrailingObjects<char>(), Str.data(), ByteLength);
+}
- if (NumStrs != 1)
- memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1));
- return SL;
+StringLiteral::StringLiteral(EmptyShell Empty, unsigned NumConcatenated,
+ unsigned Length, unsigned CharByteWidth)
+ : Expr(StringLiteralClass, Empty) {
+ StringLiteralBits.CharByteWidth = CharByteWidth;
+ StringLiteralBits.NumConcatenated = NumConcatenated;
+ *getTrailingObjects<unsigned>() = Length;
}
-StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C,
- unsigned NumStrs) {
- void *Mem =
- C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
- alignof(StringLiteral));
- StringLiteral *SL =
- new (Mem) StringLiteral(C.adjustStringLiteralBaseType(QualType()));
- SL->CharByteWidth = 0;
- SL->Length = 0;
- SL->NumConcatenated = NumStrs;
- return SL;
+StringLiteral *StringLiteral::Create(const ASTContext &Ctx, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
+ const SourceLocation *Loc,
+ unsigned NumConcatenated) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>(
+ 1, NumConcatenated, Str.size()),
+ alignof(StringLiteral));
+ return new (Mem)
+ StringLiteral(Ctx, Str, Kind, Pascal, Ty, Loc, NumConcatenated);
+}
+
+StringLiteral *StringLiteral::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumConcatenated,
+ unsigned Length,
+ unsigned CharByteWidth) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned, SourceLocation, char>(
+ 1, NumConcatenated, Length * CharByteWidth),
+ alignof(StringLiteral));
+ return new (Mem)
+ StringLiteral(EmptyShell(), NumConcatenated, Length, CharByteWidth);
}
void StringLiteral::outputString(raw_ostream &OS) const {
@@ -1019,42 +1098,6 @@ void StringLiteral::outputString(raw_ostream &OS) const {
OS << '"';
}
-void StringLiteral::setString(const ASTContext &C, StringRef Str,
- StringKind Kind, bool IsPascal) {
- //FIXME: we assume that the string data comes from a target that uses the same
- // code unit size and endianness for the type of string.
- this->Kind = Kind;
- this->IsPascal = IsPascal;
-
- CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind);
- assert((Str.size()%CharByteWidth == 0)
- && "size of data must be multiple of CharByteWidth");
- Length = Str.size()/CharByteWidth;
-
- switch(CharByteWidth) {
- case 1: {
- char *AStrData = new (C) char[Length];
- std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
- StrData.asChar = AStrData;
- break;
- }
- case 2: {
- uint16_t *AStrData = new (C) uint16_t[Length];
- std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
- StrData.asUInt16 = AStrData;
- break;
- }
- case 4: {
- uint32_t *AStrData = new (C) uint32_t[Length];
- std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
- StrData.asUInt32 = AStrData;
- break;
- }
- default:
- llvm_unreachable("unsupported CharByteWidth");
- }
-}
-
/// getLocationOfByte - Return a source location that points to the specified
/// byte of this string literal.
///
@@ -1076,7 +1119,8 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
const LangOptions &Features,
const TargetInfo &Target, unsigned *StartToken,
unsigned *StartTokenByteOffset) const {
- assert((Kind == StringLiteral::Ascii || Kind == StringLiteral::UTF8) &&
+ assert((getKind() == StringLiteral::Ascii ||
+ getKind() == StringLiteral::UTF8) &&
"Only narrow string literals are currently supported");
// Loop over all of the tokens in this string until we find the one that
@@ -1144,8 +1188,6 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
}
}
-
-
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++".
StringRef UnaryOperator::getOpcodeStr(Opcode Op) {
@@ -1192,49 +1234,98 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
// Postfix Operators.
//===----------------------------------------------------------------------===//
-CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
- ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t,
- ExprValueKind VK, SourceLocation rparenloc)
- : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(),
- fn->isValueDependent(), fn->isInstantiationDependent(),
- fn->containsUnexpandedParameterPack()),
- NumArgs(args.size()) {
+CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation RParenLoc, unsigned MinNumArgs,
+ ADLCallKind UsesADL)
+ : Expr(SC, Ty, VK, OK_Ordinary, Fn->isTypeDependent(),
+ Fn->isValueDependent(), Fn->isInstantiationDependent(),
+ Fn->containsUnexpandedParameterPack()),
+ RParenLoc(RParenLoc) {
+ NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ unsigned NumPreArgs = PreArgs.size();
+ CallExprBits.NumPreArgs = NumPreArgs;
+ assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
+
+ unsigned OffsetToTrailingObjects = offsetToTrailingObjects(SC);
+ CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects;
+ assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) &&
+ "OffsetToTrailingObjects overflow!");
- unsigned NumPreArgs = preargs.size();
- SubExprs = new (C) Stmt *[args.size()+PREARGS_START+NumPreArgs];
- SubExprs[FN] = fn;
- for (unsigned i = 0; i != NumPreArgs; ++i) {
- updateDependenciesFromArg(preargs[i]);
- SubExprs[i+PREARGS_START] = preargs[i];
+ CallExprBits.UsesADL = static_cast<bool>(UsesADL);
+
+ setCallee(Fn);
+ for (unsigned I = 0; I != NumPreArgs; ++I) {
+ updateDependenciesFromArg(PreArgs[I]);
+ setPreArg(I, PreArgs[I]);
+ }
+ for (unsigned I = 0; I != Args.size(); ++I) {
+ updateDependenciesFromArg(Args[I]);
+ setArg(I, Args[I]);
}
- for (unsigned i = 0; i != args.size(); ++i) {
- updateDependenciesFromArg(args[i]);
- SubExprs[i+PREARGS_START+NumPreArgs] = args[i];
+ for (unsigned I = Args.size(); I != NumArgs; ++I) {
+ setArg(I, nullptr);
}
+}
+CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
+ EmptyShell Empty)
+ : Expr(SC, Empty), NumArgs(NumArgs) {
CallExprBits.NumPreArgs = NumPreArgs;
- RParenLoc = rparenloc;
+ assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
+
+ unsigned OffsetToTrailingObjects = offsetToTrailingObjects(SC);
+ CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects;
+ assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) &&
+ "OffsetToTrailingObjects overflow!");
}
-CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
- ArrayRef<Expr *> args, QualType t, ExprValueKind VK,
- SourceLocation rparenloc)
- : CallExpr(C, SC, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) {}
+CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation RParenLoc, unsigned MinNumArgs,
+ ADLCallKind UsesADL) {
+ unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem =
+ Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr));
+ return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
+ RParenLoc, MinNumArgs, UsesADL);
+}
-CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args,
- QualType t, ExprValueKind VK, SourceLocation rparenloc)
- : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) {
+CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
+ ExprValueKind VK, SourceLocation RParenLoc,
+ ADLCallKind UsesADL) {
+ assert(!(reinterpret_cast<uintptr_t>(Mem) % alignof(CallExpr)) &&
+ "Misaligned memory in CallExpr::CreateTemporary!");
+ return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty,
+ VK, RParenLoc, /*MinNumArgs=*/0, UsesADL);
}
-CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty)
- : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {}
+CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
+ EmptyShell Empty) {
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem =
+ Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr));
+ return new (Mem) CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, Empty);
+}
-CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
- EmptyShell Empty)
- : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) {
- // FIXME: Why do we allocate this?
- SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs]();
- CallExprBits.NumPreArgs = NumPreArgs;
+unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) {
+ switch (SC) {
+ case CallExprClass:
+ return sizeof(CallExpr);
+ case CXXOperatorCallExprClass:
+ return sizeof(CXXOperatorCallExpr);
+ case CXXMemberCallExprClass:
+ return sizeof(CXXMemberCallExpr);
+ case UserDefinedLiteralClass:
+ return sizeof(UserDefinedLiteral);
+ case CUDAKernelCallExprClass:
+ return sizeof(CUDAKernelCallExpr);
+ default:
+ llvm_unreachable("unexpected class deriving from CallExpr!");
+ }
}
void CallExpr::updateDependenciesFromArg(Expr *Arg) {
@@ -1248,14 +1339,6 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) {
ExprBits.ContainsUnexpandedParameterPack = true;
}
-FunctionDecl *CallExpr::getDirectCallee() {
- return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
-}
-
-Decl *CallExpr::getCalleeDecl() {
- return getCallee()->getReferencedDeclOfCallee();
-}
-
Decl *Expr::getReferencedDeclOfCallee() {
Expr *CEE = IgnoreParenImpCasts();
@@ -1280,35 +1363,6 @@ Decl *Expr::getReferencedDeclOfCallee() {
return nullptr;
}
-/// setNumArgs - This changes the number of arguments present in this call.
-/// Any orphaned expressions are deleted by this, and any new operands are set
-/// to null.
-void CallExpr::setNumArgs(const ASTContext& C, unsigned NumArgs) {
- // No change, just return.
- if (NumArgs == getNumArgs()) return;
-
- // If shrinking # arguments, just delete the extras and forgot them.
- if (NumArgs < getNumArgs()) {
- this->NumArgs = NumArgs;
- return;
- }
-
- // Otherwise, we are growing the # arguments. New an bigger argument array.
- unsigned NumPreArgs = getNumPreArgs();
- Stmt **NewSubExprs = new (C) Stmt*[NumArgs+PREARGS_START+NumPreArgs];
- // Copy over args.
- for (unsigned i = 0; i != getNumArgs()+PREARGS_START+NumPreArgs; ++i)
- NewSubExprs[i] = SubExprs[i];
- // Null out new args.
- for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs;
- i != NumArgs+PREARGS_START+NumPreArgs; ++i)
- NewSubExprs[i] = nullptr;
-
- if (SubExprs) C.Deallocate(SubExprs);
- SubExprs = NewSubExprs;
- this->NumArgs = NumArgs;
-}
-
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If
/// not, return 0.
unsigned CallExpr::getBuiltinCallee() const {
@@ -1358,22 +1412,35 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
return FnType->getReturnType();
}
-SourceLocation CallExpr::getLocStart() const {
+const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
+ // If the return type is a struct, union, or enum that is marked nodiscard,
+ // then return the return type attribute.
+ if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl())
+ if (const auto *A = TD->getAttr<WarnUnusedResultAttr>())
+ return A;
+
+ // Otherwise, see if the callee is marked nodiscard and return that attribute
+ // instead.
+ const Decl *D = getCalleeDecl();
+ return D ? D->getAttr<WarnUnusedResultAttr>() : nullptr;
+}
+
+SourceLocation CallExpr::getBeginLoc() const {
if (isa<CXXOperatorCallExpr>(this))
- return cast<CXXOperatorCallExpr>(this)->getLocStart();
+ return cast<CXXOperatorCallExpr>(this)->getBeginLoc();
- SourceLocation begin = getCallee()->getLocStart();
+ SourceLocation begin = getCallee()->getBeginLoc();
if (begin.isInvalid() && getNumArgs() > 0 && getArg(0))
- begin = getArg(0)->getLocStart();
+ begin = getArg(0)->getBeginLoc();
return begin;
}
-SourceLocation CallExpr::getLocEnd() const {
+SourceLocation CallExpr::getEndLoc() const {
if (isa<CXXOperatorCallExpr>(this))
- return cast<CXXOperatorCallExpr>(this)->getLocEnd();
+ return cast<CXXOperatorCallExpr>(this)->getEndLoc();
SourceLocation end = getRParenLoc();
if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1))
- end = getArg(getNumArgs() - 1)->getLocEnd();
+ end = getArg(getNumArgs() - 1)->getEndLoc();
return end;
}
@@ -1446,7 +1513,7 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
// Check to see if we are in the situation where alignof(decl) should be
// dependent because decl's alignment is dependent.
- if (ExprKind == UETT_AlignOf) {
+ if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
if (!isValueDependent() || !isInstantiationDependent()) {
E = E->IgnoreParens();
@@ -1502,7 +1569,7 @@ MemberExpr *MemberExpr::Create(
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
E->setInstantiationDependent(true);
- E->HasQualifierOrFoundDecl = true;
+ E->MemberExprBits.HasQualifierOrFoundDecl = true;
MemberExprNameQualifier *NQ =
E->getTrailingObjects<MemberExprNameQualifier>();
@@ -1510,7 +1577,8 @@ MemberExpr *MemberExpr::Create(
NQ->FoundDecl = founddecl;
}
- E->HasTemplateKWAndArgsInfo = (targs || TemplateKWLoc.isValid());
+ E->MemberExprBits.HasTemplateKWAndArgsInfo =
+ (targs || TemplateKWLoc.isValid());
if (targs) {
bool Dependent = false;
@@ -1529,7 +1597,7 @@ MemberExpr *MemberExpr::Create(
return E;
}
-SourceLocation MemberExpr::getLocStart() const {
+SourceLocation MemberExpr::getBeginLoc() const {
if (isImplicitAccess()) {
if (hasQualifier())
return getQualifierLoc().getBeginLoc();
@@ -1538,17 +1606,17 @@ SourceLocation MemberExpr::getLocStart() const {
// FIXME: We don't want this to happen. Rather, we should be able to
// detect all kinds of implicit accesses more cleanly.
- SourceLocation BaseStartLoc = getBase()->getLocStart();
+ SourceLocation BaseStartLoc = getBase()->getBeginLoc();
if (BaseStartLoc.isValid())
return BaseStartLoc;
return MemberLoc;
}
-SourceLocation MemberExpr::getLocEnd() const {
+SourceLocation MemberExpr::getEndLoc() const {
SourceLocation EndLoc = getMemberNameInfo().getEndLoc();
if (hasExplicitTemplateArgs())
EndLoc = getRAngleLoc();
else if (EndLoc.isInvalid())
- EndLoc = getBase()->getLocEnd();
+ EndLoc = getBase()->getEndLoc();
return EndLoc;
}
@@ -1605,13 +1673,18 @@ bool CastExpr::CastConsistency() const {
assert(getSubExpr()->getType()->isFunctionType());
goto CheckNoBasePath;
- case CK_AddressSpaceConversion:
- assert(getType()->isPointerType() || getType()->isBlockPointerType());
- assert(getSubExpr()->getType()->isPointerType() ||
- getSubExpr()->getType()->isBlockPointerType());
- assert(getType()->getPointeeType().getAddressSpace() !=
- getSubExpr()->getType()->getPointeeType().getAddressSpace());
- LLVM_FALLTHROUGH;
+ case CK_AddressSpaceConversion: {
+ auto Ty = getType();
+ auto SETy = getSubExpr()->getType();
+ assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy));
+ if (isRValue()) {
+ Ty = Ty->getPointeeType();
+ SETy = SETy->getPointeeType();
+ }
+ assert(!Ty.isNull() && !SETy.isNull() &&
+ Ty.getAddressSpace() != SETy.getAddressSpace());
+ goto CheckNoBasePath;
+ }
// These should not have an inheritance path.
case CK_Dynamic:
case CK_ToUnion:
@@ -1641,9 +1714,9 @@ bool CastExpr::CastConsistency() const {
case CK_ARCConsumeObject:
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_ZeroToOCLOpaqueType:
case CK_IntToOCLSampler:
+ case CK_FixedPointCast:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
goto CheckNoBasePath;
@@ -1661,6 +1734,7 @@ bool CastExpr::CastConsistency() const {
case CK_LValueBitCast: // -> bool&
case CK_UserDefinedConversion: // operator bool()
case CK_BuiltinFnToFnPtr:
+ case CK_FixedPointToBoolean:
CheckNoBasePath:
assert(path_empty() && "Cast kind should not have a base path!");
break;
@@ -1734,21 +1808,6 @@ NamedDecl *CastExpr::getConversionFunction() const {
return nullptr;
}
-CastExpr::BasePathSizeTy *CastExpr::BasePathSize() {
- assert(!path_empty());
- switch (getStmtClass()) {
-#define ABSTRACT_STMT(x)
-#define CASTEXPR(Type, Base) \
- case Stmt::Type##Class: \
- return static_cast<Type *>(this) \
- ->getTrailingObjects<CastExpr::BasePathSizeTy>();
-#define STMT(Type, Base)
-#include "clang/AST/StmtNodes.inc"
- default:
- llvm_unreachable("non-cast expressions not possible here");
- }
-}
-
CXXBaseSpecifier **CastExpr::path_buffer() {
switch (getStmtClass()) {
#define ABSTRACT_STMT(x)
@@ -1787,9 +1846,7 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
const CXXCastPath *BasePath,
ExprValueKind VK) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
ImplicitCastExpr *E =
new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
if (PathSize)
@@ -1800,9 +1857,7 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
}
@@ -1813,9 +1868,7 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
TypeSourceInfo *WrittenTy,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
CStyleCastExpr *E =
new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R);
if (PathSize)
@@ -1826,9 +1879,7 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
}
@@ -2039,9 +2090,9 @@ bool InitListExpr::isIdiomaticZeroInitializer(const LangOptions &LangOpts) const
return Lit && Lit->getValue() == 0;
}
-SourceLocation InitListExpr::getLocStart() const {
+SourceLocation InitListExpr::getBeginLoc() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
- return SyntacticForm->getLocStart();
+ return SyntacticForm->getBeginLoc();
SourceLocation Beg = LBraceLoc;
if (Beg.isInvalid()) {
// Find the first non-null initializer.
@@ -2049,7 +2100,7 @@ SourceLocation InitListExpr::getLocStart() const {
E = InitExprs.end();
I != E; ++I) {
if (Stmt *S = *I) {
- Beg = S->getLocStart();
+ Beg = S->getBeginLoc();
break;
}
}
@@ -2057,9 +2108,9 @@ SourceLocation InitListExpr::getLocStart() const {
return Beg;
}
-SourceLocation InitListExpr::getLocEnd() const {
+SourceLocation InitListExpr::getEndLoc() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
- return SyntacticForm->getLocEnd();
+ return SyntacticForm->getEndLoc();
SourceLocation End = RBraceLoc;
if (End.isInvalid()) {
// Find the first non-null initializer from the end.
@@ -2067,7 +2118,7 @@ SourceLocation InitListExpr::getLocEnd() const {
E = InitExprs.rend();
I != E; ++I) {
if (Stmt *S = *I) {
- End = S->getLocEnd();
+ End = S->getEndLoc();
break;
}
}
@@ -2262,24 +2313,20 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
if (const Decl *FD = CE->getCalleeDecl()) {
- const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
- bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr()
- : FD->hasAttr<WarnUnusedResultAttr>();
-
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
//
// Note: If new cases are added here, DiagnoseUnusedExprResult should be
// updated to match for QoI.
- if (HasWarnUnusedResultAttr ||
+ if (CE->hasUnusedResultAttr(Ctx) ||
FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) {
WarnE = this;
- Loc = CE->getCallee()->getLocStart();
+ Loc = CE->getCallee()->getBeginLoc();
R1 = CE->getCallee()->getSourceRange();
if (unsigned NumArgs = CE->getNumArgs())
- R2 = SourceRange(CE->getArg(0)->getLocStart(),
- CE->getArg(NumArgs-1)->getLocEnd());
+ R2 = SourceRange(CE->getArg(0)->getBeginLoc(),
+ CE->getArg(NumArgs - 1)->getEndLoc());
return true;
}
}
@@ -2296,7 +2343,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) {
if (Type->hasAttr<WarnUnusedAttr>()) {
WarnE = this;
- Loc = getLocStart();
+ Loc = getBeginLoc();
R1 = getSourceRange();
return true;
}
@@ -2396,7 +2443,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
WarnE = this;
if (const CXXFunctionalCastExpr *CXXCE =
dyn_cast<CXXFunctionalCastExpr>(this)) {
- Loc = CXXCE->getLocStart();
+ Loc = CXXCE->getBeginLoc();
R1 = CXXCE->getSubExpr()->getSourceRange();
} else {
const CStyleCastExpr *CStyleCE = cast<CStyleCastExpr>(this);
@@ -2535,6 +2582,10 @@ Expr* Expr::IgnoreParens() {
continue;
}
}
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) {
+ E = CE->getSubExpr();
+ continue;
+ }
return E;
}
}
@@ -2559,6 +2610,10 @@ Expr *Expr::IgnoreParenCasts() {
E = NTTP->getReplacement();
continue;
}
+ if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
+ E = FE->getSubExpr();
+ continue;
+ }
return E;
}
}
@@ -2580,6 +2635,10 @@ Expr *Expr::IgnoreCasts() {
E = NTTP->getReplacement();
continue;
}
+ if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
+ E = FE->getSubExpr();
+ continue;
+ }
return E;
}
}
@@ -2605,6 +2664,9 @@ Expr *Expr::IgnoreParenLValueCasts() {
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
continue;
+ } else if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
+ E = FE->getSubExpr();
+ continue;
}
break;
}
@@ -2870,6 +2932,12 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
break;
}
+ case ConstantExprClass: {
+ // FIXME: We should be able to return "true" here, but it can lead to extra
+ // error messages. E.g. in Sema/array-init.c.
+ const Expr *Exp = cast<ConstantExpr>(this)->getSubExpr();
+ return Exp->isConstantInitializer(Ctx, false, Culprit);
+ }
case CompoundLiteralExprClass: {
// This handles gcc's extension that allows global initializers like
// "struct x {int x;} x = (struct x) {};".
@@ -2909,8 +2977,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
const Expr *Elt = ILE->getInit(ElementNo++);
if (Field->isBitField()) {
// Bitfields have to evaluate to an integer.
- llvm::APSInt ResultTmp;
- if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) {
+ EvalResult Result;
+ if (!Elt->EvaluateAsInt(Result, Ctx)) {
if (Culprit)
*Culprit = Elt;
return false;
@@ -3095,6 +3163,11 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
// These never have a side-effect.
return false;
+ case ConstantExprClass:
+ // FIXME: Move this into the "return false;" block above.
+ return cast<ConstantExpr>(this)->getSubExpr()->HasSideEffects(
+ Ctx, IncludePossibleEffects);
+
case CallExprClass:
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass:
@@ -3254,11 +3327,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case LambdaExprClass: {
const LambdaExpr *LE = cast<LambdaExpr>(this);
- for (LambdaExpr::capture_iterator I = LE->capture_begin(),
- E = LE->capture_end(); I != E; ++I)
- if (I->getCaptureKind() == LCK_ByCopy)
- // FIXME: Only has a side-effect if the variable is volatile or if
- // the copy would invoke a non-trivial copy constructor.
+ for (Expr *E : LE->capture_inits())
+ if (E->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
return false;
}
@@ -3389,20 +3459,20 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
// Check that it is a cast to void*.
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
+ Qualifiers Qs = Pointee.getQualifiers();
// Only (void*)0 or equivalent are treated as nullptr. If pointee type
// has non-default address space it is not treated as nullptr.
// (__generic void*)0 in OpenCL 2.0 should not be treated as nullptr
// since it cannot be assigned to a pointer to constant address space.
- bool PointeeHasDefaultAS =
- Pointee.getAddressSpace() == LangAS::Default ||
- (Ctx.getLangOpts().OpenCLVersion >= 200 &&
+ if ((Ctx.getLangOpts().OpenCLVersion >= 200 &&
Pointee.getAddressSpace() == LangAS::opencl_generic) ||
(Ctx.getLangOpts().OpenCL &&
Ctx.getLangOpts().OpenCLVersion < 200 &&
- Pointee.getAddressSpace() == LangAS::opencl_private);
+ Pointee.getAddressSpace() == LangAS::opencl_private))
+ Qs.removeAddressSpace();
- if (PointeeHasDefaultAS && Pointee->isVoidType() && // to void*
- CE->getSubExpr()->getType()->isIntegerType()) // from int.
+ if (Pointee->isVoidType() && Qs.empty() && // to void*
+ CE->getSubExpr()->getType()->isIntegerType()) // from int
return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
}
}
@@ -3866,11 +3936,11 @@ SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const {
DesignatedInitExpr *DIE = const_cast<DesignatedInitExpr*>(this);
if (size() == 1)
return DIE->getDesignator(0)->getSourceRange();
- return SourceRange(DIE->getDesignator(0)->getLocStart(),
- DIE->getDesignator(size()-1)->getLocEnd());
+ return SourceRange(DIE->getDesignator(0)->getBeginLoc(),
+ DIE->getDesignator(size() - 1)->getEndLoc());
}
-SourceLocation DesignatedInitExpr::getLocStart() const {
+SourceLocation DesignatedInitExpr::getBeginLoc() const {
SourceLocation StartLoc;
auto *DIE = const_cast<DesignatedInitExpr *>(this);
Designator &First = *DIE->getDesignator(0);
@@ -3885,8 +3955,8 @@ SourceLocation DesignatedInitExpr::getLocStart() const {
return StartLoc;
}
-SourceLocation DesignatedInitExpr::getLocEnd() const {
- return getInit()->getLocEnd();
+SourceLocation DesignatedInitExpr::getEndLoc() const {
+ return getInit()->getEndLoc();
}
Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const {
@@ -3944,35 +4014,56 @@ DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
BaseAndUpdaterExprs[1] = ILE;
}
-SourceLocation DesignatedInitUpdateExpr::getLocStart() const {
- return getBase()->getLocStart();
+SourceLocation DesignatedInitUpdateExpr::getBeginLoc() const {
+ return getBase()->getBeginLoc();
}
-SourceLocation DesignatedInitUpdateExpr::getLocEnd() const {
- return getBase()->getLocEnd();
+SourceLocation DesignatedInitUpdateExpr::getEndLoc() const {
+ return getBase()->getEndLoc();
}
-ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
- ArrayRef<Expr*> exprs,
- SourceLocation rparenloc)
- : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
- false, false, false, false),
- NumExprs(exprs.size()), LParenLoc(lparenloc), RParenLoc(rparenloc) {
- Exprs = new (C) Stmt*[exprs.size()];
- for (unsigned i = 0; i != exprs.size(); ++i) {
- if (exprs[i]->isTypeDependent())
+ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs,
+ SourceLocation RParenLoc)
+ : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
+ ParenListExprBits.NumExprs = Exprs.size();
+
+ for (unsigned I = 0, N = Exprs.size(); I != N; ++I) {
+ if (Exprs[I]->isTypeDependent())
ExprBits.TypeDependent = true;
- if (exprs[i]->isValueDependent())
+ if (Exprs[I]->isValueDependent())
ExprBits.ValueDependent = true;
- if (exprs[i]->isInstantiationDependent())
+ if (Exprs[I]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
- if (exprs[i]->containsUnexpandedParameterPack())
+ if (Exprs[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
- Exprs[i] = exprs[i];
+ getTrailingObjects<Stmt *>()[I] = Exprs[I];
}
}
+ParenListExpr::ParenListExpr(EmptyShell Empty, unsigned NumExprs)
+ : Expr(ParenListExprClass, Empty) {
+ ParenListExprBits.NumExprs = NumExprs;
+}
+
+ParenListExpr *ParenListExpr::Create(const ASTContext &Ctx,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> Exprs,
+ SourceLocation RParenLoc) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(Exprs.size()),
+ alignof(ParenListExpr));
+ return new (Mem) ParenListExpr(LParenLoc, Exprs, RParenLoc);
+}
+
+ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumExprs) {
+ void *Mem =
+ Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumExprs), alignof(ParenListExpr));
+ return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
+}
+
const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
e = ewc->getSubExpr();
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 93d68ec8e0b2..3891f45c7fc2 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -89,88 +89,132 @@ QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const {
}
// CXXScalarValueInitExpr
-SourceLocation CXXScalarValueInitExpr::getLocStart() const {
- return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc;
+SourceLocation CXXScalarValueInitExpr::getBeginLoc() const {
+ return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : getRParenLoc();
}
// CXXNewExpr
-CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
- FunctionDecl *operatorNew, FunctionDecl *operatorDelete,
- bool PassAlignment, bool usualArrayDeleteWantsSize,
- ArrayRef<Expr*> placementArgs,
- SourceRange typeIdParens, Expr *arraySize,
- InitializationStyle initializationStyle,
- Expr *initializer, QualType ty,
- TypeSourceInfo *allocatedTypeInfo,
- SourceRange Range, SourceRange directInitRange)
- : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(),
- ty->isDependentType(), ty->isInstantiationDependentType(),
- ty->containsUnexpandedParameterPack()),
- OperatorNew(operatorNew), OperatorDelete(operatorDelete),
- AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
- Range(Range), DirectInitRange(directInitRange), GlobalNew(globalNew),
- PassAlignment(PassAlignment),
- UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
- assert((initializer != nullptr || initializationStyle == NoInit) &&
- "Only NoInit can have no initializer.");
- StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
- AllocateArgsArray(C, arraySize != nullptr, placementArgs.size(),
- initializer != nullptr);
- unsigned i = 0;
- if (Array) {
- if (arraySize->isInstantiationDependent())
+CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
+ FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
+ bool UsualArrayDeleteWantsSize,
+ ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens,
+ Expr *ArraySize, InitializationStyle InitializationStyle,
+ Expr *Initializer, QualType Ty,
+ TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
+ SourceRange DirectInitRange)
+ : Expr(CXXNewExprClass, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(),
+ Ty->isDependentType(), Ty->isInstantiationDependentType(),
+ Ty->containsUnexpandedParameterPack()),
+ OperatorNew(OperatorNew), OperatorDelete(OperatorDelete),
+ AllocatedTypeInfo(AllocatedTypeInfo), Range(Range),
+ DirectInitRange(DirectInitRange) {
+
+ assert((Initializer != nullptr || InitializationStyle == NoInit) &&
+ "Only NoInit can have no initializer!");
+
+ CXXNewExprBits.IsGlobalNew = IsGlobalNew;
+ CXXNewExprBits.IsArray = ArraySize != nullptr;
+ CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment;
+ CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize;
+ CXXNewExprBits.StoredInitializationStyle =
+ Initializer ? InitializationStyle + 1 : 0;
+ bool IsParenTypeId = TypeIdParens.isValid();
+ CXXNewExprBits.IsParenTypeId = IsParenTypeId;
+ CXXNewExprBits.NumPlacementArgs = PlacementArgs.size();
+
+ if (ArraySize) {
+ if (ArraySize->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
-
- if (arraySize->containsUnexpandedParameterPack())
+ if (ArraySize->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
- SubExprs[i++] = arraySize;
+ getTrailingObjects<Stmt *>()[arraySizeOffset()] = ArraySize;
}
- if (initializer) {
- if (initializer->isInstantiationDependent())
+ if (Initializer) {
+ if (Initializer->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
-
- if (initializer->containsUnexpandedParameterPack())
+ if (Initializer->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
- SubExprs[i++] = initializer;
+ getTrailingObjects<Stmt *>()[initExprOffset()] = Initializer;
}
- for (unsigned j = 0; j != placementArgs.size(); ++j) {
- if (placementArgs[j]->isInstantiationDependent())
+ for (unsigned I = 0; I != PlacementArgs.size(); ++I) {
+ if (PlacementArgs[I]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
- if (placementArgs[j]->containsUnexpandedParameterPack())
+ if (PlacementArgs[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
- SubExprs[i++] = placementArgs[j];
+ getTrailingObjects<Stmt *>()[placementNewArgsOffset() + I] =
+ PlacementArgs[I];
}
+ if (IsParenTypeId)
+ getTrailingObjects<SourceRange>()[0] = TypeIdParens;
+
switch (getInitializationStyle()) {
case CallInit:
- this->Range.setEnd(DirectInitRange.getEnd()); break;
+ this->Range.setEnd(DirectInitRange.getEnd());
+ break;
case ListInit:
- this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); break;
+ this->Range.setEnd(getInitializer()->getSourceRange().getEnd());
+ break;
default:
- if (TypeIdParens.isValid())
+ if (IsParenTypeId)
this->Range.setEnd(TypeIdParens.getEnd());
break;
}
}
-void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray,
- unsigned numPlaceArgs, bool hasInitializer){
- assert(SubExprs == nullptr && "SubExprs already allocated");
- Array = isArray;
- NumPlacementArgs = numPlaceArgs;
-
- unsigned TotalSize = Array + hasInitializer + NumPlacementArgs;
- SubExprs = new (C) Stmt*[TotalSize];
+CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray,
+ unsigned NumPlacementArgs, bool IsParenTypeId)
+ : Expr(CXXNewExprClass, Empty) {
+ CXXNewExprBits.IsArray = IsArray;
+ CXXNewExprBits.NumPlacementArgs = NumPlacementArgs;
+ CXXNewExprBits.IsParenTypeId = IsParenTypeId;
+}
+
+CXXNewExpr *
+CXXNewExpr::Create(const ASTContext &Ctx, bool IsGlobalNew,
+ FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete,
+ bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize,
+ ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens,
+ Expr *ArraySize, InitializationStyle InitializationStyle,
+ Expr *Initializer, QualType Ty,
+ TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
+ SourceRange DirectInitRange) {
+ bool IsArray = ArraySize != nullptr;
+ bool HasInit = Initializer != nullptr;
+ unsigned NumPlacementArgs = PlacementArgs.size();
+ bool IsParenTypeId = TypeIdParens.isValid();
+ void *Mem =
+ Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>(
+ IsArray + HasInit + NumPlacementArgs, IsParenTypeId),
+ alignof(CXXNewExpr));
+ return new (Mem)
+ CXXNewExpr(IsGlobalNew, OperatorNew, OperatorDelete, ShouldPassAlignment,
+ UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens,
+ ArraySize, InitializationStyle, Initializer, Ty,
+ AllocatedTypeInfo, Range, DirectInitRange);
+}
+
+CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray,
+ bool HasInit, unsigned NumPlacementArgs,
+ bool IsParenTypeId) {
+ void *Mem =
+ Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>(
+ IsArray + HasInit + NumPlacementArgs, IsParenTypeId),
+ alignof(CXXNewExpr));
+ return new (Mem)
+ CXXNewExpr(EmptyShell(), IsArray, NumPlacementArgs, IsParenTypeId);
}
-bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const {
- return getOperatorNew()->getType()->castAs<FunctionProtoType>()
- ->isNothrow() &&
+bool CXXNewExpr::shouldNullCheckAllocation() const {
+ return getOperatorNew()
+ ->getType()
+ ->castAs<FunctionProtoType>()
+ ->isNothrow() &&
!getOperatorNew()->isReservedGlobalPlacementOperator();
}
@@ -250,7 +294,7 @@ QualType CXXPseudoDestructorExpr::getDestroyedType() const {
return QualType();
}
-SourceLocation CXXPseudoDestructorExpr::getLocEnd() const {
+SourceLocation CXXPseudoDestructorExpr::getEndLoc() const {
SourceLocation End = DestroyedType.getLocation();
if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
End = TInfo->getTypeLoc().getLocalSourceRange().getEnd();
@@ -258,68 +302,95 @@ SourceLocation CXXPseudoDestructorExpr::getLocEnd() const {
}
// UnresolvedLookupExpr
-UnresolvedLookupExpr *
-UnresolvedLookupExpr::Create(const ASTContext &C,
- CXXRecordDecl *NamingClass,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- bool ADL,
- const TemplateArgumentListInfo *Args,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End) {
- assert(Args || TemplateKWLoc.isValid());
- unsigned num_args = Args ? Args->size() : 0;
+UnresolvedLookupExpr::UnresolvedLookupExpr(
+ const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
+ const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End)
+ : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc,
+ TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, false,
+ false, false),
+ NamingClass(NamingClass) {
+ UnresolvedLookupExprBits.RequiresADL = RequiresADL;
+ UnresolvedLookupExprBits.Overloaded = Overloaded;
+}
+
+UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty,
+ unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo)
+ : OverloadExpr(UnresolvedLookupExprClass, Empty, NumResults,
+ HasTemplateKWAndArgsInfo) {}
+
+UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
+ const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ unsigned NumResults = End - Begin;
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(NumResults, 0, 0);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
+ return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
+ SourceLocation(), NameInfo, RequiresADL,
+ Overloaded, nullptr, Begin, End);
+}
- std::size_t Size =
- totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1,
- num_args);
- void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
- return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
- TemplateKWLoc, NameInfo,
- ADL, /*Overload*/ true, Args,
- Begin, End);
-}
-
-UnresolvedLookupExpr *
-UnresolvedLookupExpr::CreateEmpty(const ASTContext &C,
- bool HasTemplateKWAndArgsInfo,
- unsigned NumTemplateArgs) {
+UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
+ const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo, bool RequiresADL,
+ const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ assert(Args || TemplateKWLoc.isValid());
+ unsigned NumResults = End - Begin;
+ unsigned NumTemplateArgs = Args ? Args->size() : 0;
+ unsigned Size =
+ totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(NumResults, 1, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
+ return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
+ TemplateKWLoc, NameInfo, RequiresADL,
+ /*Overloaded*/ true, Args, Begin, End);
+}
+
+UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty(
+ const ASTContext &Context, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
- std::size_t Size =
- totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
- HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
- auto *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
- E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
- return E;
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
+ return new (Mem)
+ UnresolvedLookupExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo);
}
-OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
+OverloadExpr::OverloadExpr(StmtClass SC, const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin,
- UnresolvedSetIterator End,
- bool KnownDependent,
+ UnresolvedSetIterator End, bool KnownDependent,
bool KnownInstantiationDependent,
bool KnownContainsUnexpandedParameterPack)
- : Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
- KnownDependent,
- (KnownInstantiationDependent ||
- NameInfo.isInstantiationDependent() ||
- (QualifierLoc &&
+ : Expr(
+ SC, Context.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
+ KnownDependent,
+ (KnownInstantiationDependent || NameInfo.isInstantiationDependent() ||
+ (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
- (KnownContainsUnexpandedParameterPack ||
- NameInfo.containsUnexpandedParameterPack() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()))),
- NameInfo(NameInfo), QualifierLoc(QualifierLoc), NumResults(End - Begin),
- HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
- TemplateKWLoc.isValid()) {
- NumResults = End - Begin;
+ (KnownContainsUnexpandedParameterPack ||
+ NameInfo.containsUnexpandedParameterPack() ||
+ (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()))),
+ NameInfo(NameInfo), QualifierLoc(QualifierLoc) {
+ unsigned NumResults = End - Begin;
+ OverloadExprBits.NumResults = NumResults;
+ OverloadExprBits.HasTemplateKWAndArgsInfo =
+ (TemplateArgs != nullptr ) || TemplateKWLoc.isValid();
+
if (NumResults) {
// Determine whether this expression is type-dependent.
for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I) {
@@ -331,8 +402,9 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
}
}
- Results = static_cast<DeclAccessPair *>(C.Allocate(
- sizeof(DeclAccessPair) * NumResults, alignof(DeclAccessPair)));
+ // Copy the results to the trailing array past UnresolvedLookupExpr
+ // or UnresolvedMemberExpr.
+ DeclAccessPair *Results = getTrailingResults();
memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
@@ -360,48 +432,33 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
}
if (isTypeDependent())
- setType(C.DependentTy);
-}
-
-void OverloadExpr::initializeResults(const ASTContext &C,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End) {
- assert(!Results && "Results already initialized!");
- NumResults = End - Begin;
- if (NumResults) {
- Results = static_cast<DeclAccessPair *>(
- C.Allocate(sizeof(DeclAccessPair) * NumResults,
-
- alignof(DeclAccessPair)));
- memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
- }
+ setType(Context.DependentTy);
}
-CXXRecordDecl *OverloadExpr::getNamingClass() const {
- if (isa<UnresolvedLookupExpr>(this))
- return cast<UnresolvedLookupExpr>(this)->getNamingClass();
- else
- return cast<UnresolvedMemberExpr>(this)->getNamingClass();
+OverloadExpr::OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo)
+ : Expr(SC, Empty) {
+ OverloadExprBits.NumResults = NumResults;
+ OverloadExprBits.HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
}
// DependentScopeDeclRefExpr
-DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *Args)
- : Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary,
- true, true,
- (NameInfo.isInstantiationDependent() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
- (NameInfo.containsUnexpandedParameterPack() ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()))),
- QualifierLoc(QualifierLoc), NameInfo(NameInfo),
- HasTemplateKWAndArgsInfo(Args != nullptr || TemplateKWLoc.isValid())
-{
+DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(
+ QualType Ty, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *Args)
+ : Expr(
+ DependentScopeDeclRefExprClass, Ty, VK_LValue, OK_Ordinary, true,
+ true,
+ (NameInfo.isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
+ (NameInfo.containsUnexpandedParameterPack() ||
+ (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()))),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo) {
+ DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
+ (Args != nullptr) || TemplateKWLoc.isValid();
if (Args) {
bool Dependent = true;
bool InstantiationDependent = true;
@@ -417,57 +474,55 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
}
}
-DependentScopeDeclRefExpr *
-DependentScopeDeclRefExpr::Create(const ASTContext &C,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *Args) {
+DependentScopeDeclRefExpr *DependentScopeDeclRefExpr::Create(
+ const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *Args) {
assert(QualifierLoc && "should be created for dependent qualifiers");
bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, Args ? Args->size() : 0);
- void *Mem = C.Allocate(Size);
- return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
+ void *Mem = Context.Allocate(Size);
+ return new (Mem) DependentScopeDeclRefExpr(Context.DependentTy, QualifierLoc,
TemplateKWLoc, NameInfo, Args);
}
DependentScopeDeclRefExpr *
-DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C,
+DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &Context,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size);
- auto *E =
- new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
- SourceLocation(),
- DeclarationNameInfo(), nullptr);
- E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
+ void *Mem = Context.Allocate(Size);
+ auto *E = new (Mem) DependentScopeDeclRefExpr(
+ QualType(), NestedNameSpecifierLoc(), SourceLocation(),
+ DeclarationNameInfo(), nullptr);
+ E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
+ HasTemplateKWAndArgsInfo;
return E;
}
-SourceLocation CXXConstructExpr::getLocStart() const {
+SourceLocation CXXConstructExpr::getBeginLoc() const {
if (isa<CXXTemporaryObjectExpr>(this))
- return cast<CXXTemporaryObjectExpr>(this)->getLocStart();
- return Loc;
+ return cast<CXXTemporaryObjectExpr>(this)->getBeginLoc();
+ return getLocation();
}
-SourceLocation CXXConstructExpr::getLocEnd() const {
+SourceLocation CXXConstructExpr::getEndLoc() const {
if (isa<CXXTemporaryObjectExpr>(this))
- return cast<CXXTemporaryObjectExpr>(this)->getLocEnd();
+ return cast<CXXTemporaryObjectExpr>(this)->getEndLoc();
if (ParenOrBraceRange.isValid())
return ParenOrBraceRange.getEnd();
- SourceLocation End = Loc;
+ SourceLocation End = getLocation();
for (unsigned I = getNumArgs(); I > 0; --I) {
const Expr *Arg = getArg(I-1);
if (!Arg->isDefaultArgument()) {
- SourceLocation NewEnd = Arg->getLocEnd();
+ SourceLocation NewEnd = Arg->getEndLoc();
if (NewEnd.isValid()) {
End = NewEnd;
break;
@@ -478,30 +533,110 @@ SourceLocation CXXConstructExpr::getLocEnd() const {
return End;
}
+CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind,
+ Expr *Fn, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation OperatorLoc,
+ FPOptions FPFeatures,
+ ADLCallKind UsesADL)
+ : CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
+ OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
+ CXXOperatorCallExprBits.OperatorKind = OpKind;
+ CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt();
+ assert(
+ (CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) &&
+ "OperatorKind overflow!");
+ assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) &&
+ "FPFeatures overflow!");
+ Range = getSourceRangeImpl();
+}
+
+CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+
+CXXOperatorCallExpr *CXXOperatorCallExpr::Create(
+ const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = Args.size();
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXOperatorCallExpr));
+ return new (Mem) CXXOperatorCallExpr(OpKind, Fn, Args, Ty, VK, OperatorLoc,
+ FPFeatures, UsesADL);
+}
+
+CXXOperatorCallExpr *CXXOperatorCallExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXOperatorCallExpr));
+ return new (Mem) CXXOperatorCallExpr(NumArgs, Empty);
+}
+
SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
OverloadedOperatorKind Kind = getOperator();
if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
if (getNumArgs() == 1)
// Prefix operator
- return SourceRange(getOperatorLoc(), getArg(0)->getLocEnd());
+ return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc());
else
// Postfix operator
- return SourceRange(getArg(0)->getLocStart(), getOperatorLoc());
+ return SourceRange(getArg(0)->getBeginLoc(), getOperatorLoc());
} else if (Kind == OO_Arrow) {
return getArg(0)->getSourceRange();
} else if (Kind == OO_Call) {
- return SourceRange(getArg(0)->getLocStart(), getRParenLoc());
+ return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc());
} else if (Kind == OO_Subscript) {
- return SourceRange(getArg(0)->getLocStart(), getRParenLoc());
+ return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc());
} else if (getNumArgs() == 1) {
- return SourceRange(getOperatorLoc(), getArg(0)->getLocEnd());
+ return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc());
} else if (getNumArgs() == 2) {
- return SourceRange(getArg(0)->getLocStart(), getArg(1)->getLocEnd());
+ return SourceRange(getArg(0)->getBeginLoc(), getArg(1)->getEndLoc());
} else {
return getOperatorLoc();
}
}
+CXXMemberCallExpr::CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation RP, unsigned MinNumArgs)
+ : CallExpr(CXXMemberCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, RP,
+ MinNumArgs, NotADL) {}
+
+CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+
+CXXMemberCallExpr *CXXMemberCallExpr::Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK,
+ SourceLocation RP,
+ unsigned MinNumArgs) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXMemberCallExpr));
+ return new (Mem) CXXMemberCallExpr(Fn, Args, Ty, VK, RP, MinNumArgs);
+}
+
+CXXMemberCallExpr *CXXMemberCallExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXMemberCallExpr));
+ return new (Mem) CXXMemberCallExpr(NumArgs, Empty);
+}
+
Expr *CXXMemberCallExpr::getImplicitObjectArgument() const {
const Expr *Callee = getCallee()->IgnoreParens();
if (const auto *MemExpr = dyn_cast<MemberExpr>(Callee))
@@ -559,9 +694,7 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
auto *E =
new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
@@ -573,9 +706,7 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
}
@@ -588,9 +719,7 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
auto *E =
new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
@@ -602,9 +731,7 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
}
@@ -649,9 +776,7 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
auto *E =
new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
@@ -663,9 +788,7 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
CXXReinterpretCastExpr *
CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
}
@@ -688,9 +811,7 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
const CXXCastPath *BasePath,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
auto *E =
new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
if (PathSize)
@@ -701,18 +822,52 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
CXXFunctionalCastExpr *
CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer =
- C.Allocate(totalSizeToAlloc<CastExpr::BasePathSizeTy, CXXBaseSpecifier *>(
- PathSize ? 1 : 0, PathSize));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
}
-SourceLocation CXXFunctionalCastExpr::getLocStart() const {
- return getTypeInfoAsWritten()->getTypeLoc().getLocStart();
+SourceLocation CXXFunctionalCastExpr::getBeginLoc() const {
+ return getTypeInfoAsWritten()->getTypeLoc().getBeginLoc();
+}
+
+SourceLocation CXXFunctionalCastExpr::getEndLoc() const {
+ return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getEndLoc();
+}
+
+UserDefinedLiteral::UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation LitEndLoc,
+ SourceLocation SuffixLoc)
+ : CallExpr(UserDefinedLiteralClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
+ LitEndLoc, /*MinNumArgs=*/0, NotADL),
+ UDSuffixLoc(SuffixLoc) {}
+
+UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+
+UserDefinedLiteral *UserDefinedLiteral::Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation LitEndLoc,
+ SourceLocation SuffixLoc) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = Args.size();
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
+ alignof(UserDefinedLiteral));
+ return new (Mem) UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc);
}
-SourceLocation CXXFunctionalCastExpr::getLocEnd() const {
- return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getLocEnd();
+UserDefinedLiteral *UserDefinedLiteral::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
+ alignof(UserDefinedLiteral));
+ return new (Mem) UserDefinedLiteral(NumArgs, Empty);
}
UserDefinedLiteral::LiteralOperatorKind
@@ -749,14 +904,15 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const {
return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier();
}
-CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc,
- FieldDecl *Field, QualType T)
- : Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C),
- T->isLValueReferenceType() ? VK_LValue : T->isRValueReferenceType()
+CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
+ FieldDecl *Field, QualType Ty)
+ : Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx),
+ Ty->isLValueReferenceType() ? VK_LValue : Ty->isRValueReferenceType()
? VK_XValue
: VK_RValue,
/*FIXME*/ OK_Ordinary, false, false, false, false),
- Field(Field), Loc(Loc) {
+ Field(Field) {
+ CXXDefaultInitExprBits.Loc = Loc;
assert(Field->hasInClassInitializer());
}
@@ -775,92 +931,118 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C,
return new (C) CXXBindTemporaryExpr(Temp, SubExpr);
}
-CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C,
- CXXConstructorDecl *Cons,
- QualType Type,
- TypeSourceInfo *TSI,
- ArrayRef<Expr*> Args,
- SourceRange ParenOrBraceRange,
- bool HadMultipleCandidates,
- bool ListInitialization,
- bool StdInitListInitialization,
- bool ZeroInitialization)
- : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type,
- TSI->getTypeLoc().getBeginLoc(), Cons, false, Args,
- HadMultipleCandidates, ListInitialization,
- StdInitListInitialization, ZeroInitialization,
- CXXConstructExpr::CK_Complete, ParenOrBraceRange),
- Type(TSI) {}
-
-SourceLocation CXXTemporaryObjectExpr::getLocStart() const {
- return Type->getTypeLoc().getBeginLoc();
-}
-
-SourceLocation CXXTemporaryObjectExpr::getLocEnd() const {
+CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(
+ CXXConstructorDecl *Cons, QualType Ty, TypeSourceInfo *TSI,
+ ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange,
+ bool HadMultipleCandidates, bool ListInitialization,
+ bool StdInitListInitialization, bool ZeroInitialization)
+ : CXXConstructExpr(
+ CXXTemporaryObjectExprClass, Ty, TSI->getTypeLoc().getBeginLoc(),
+ Cons, /* Elidable=*/false, Args, HadMultipleCandidates,
+ ListInitialization, StdInitListInitialization, ZeroInitialization,
+ CXXConstructExpr::CK_Complete, ParenOrBraceRange),
+ TSI(TSI) {}
+
+CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(EmptyShell Empty,
+ unsigned NumArgs)
+ : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty, NumArgs) {}
+
+CXXTemporaryObjectExpr *CXXTemporaryObjectExpr::Create(
+ const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty,
+ TypeSourceInfo *TSI, ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange,
+ bool HadMultipleCandidates, bool ListInitialization,
+ bool StdInitListInitialization, bool ZeroInitialization) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(Args.size());
+ void *Mem =
+ Ctx.Allocate(sizeof(CXXTemporaryObjectExpr) + SizeOfTrailingObjects,
+ alignof(CXXTemporaryObjectExpr));
+ return new (Mem) CXXTemporaryObjectExpr(
+ Cons, Ty, TSI, Args, ParenOrBraceRange, HadMultipleCandidates,
+ ListInitialization, StdInitListInitialization, ZeroInitialization);
+}
+
+CXXTemporaryObjectExpr *
+CXXTemporaryObjectExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(NumArgs);
+ void *Mem =
+ Ctx.Allocate(sizeof(CXXTemporaryObjectExpr) + SizeOfTrailingObjects,
+ alignof(CXXTemporaryObjectExpr));
+ return new (Mem) CXXTemporaryObjectExpr(EmptyShell(), NumArgs);
+}
+
+SourceLocation CXXTemporaryObjectExpr::getBeginLoc() const {
+ return getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+}
+
+SourceLocation CXXTemporaryObjectExpr::getEndLoc() const {
SourceLocation Loc = getParenOrBraceRange().getEnd();
if (Loc.isInvalid() && getNumArgs())
- Loc = getArg(getNumArgs()-1)->getLocEnd();
+ Loc = getArg(getNumArgs() - 1)->getEndLoc();
return Loc;
}
-CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T,
- SourceLocation Loc,
- CXXConstructorDecl *Ctor,
- bool Elidable,
- ArrayRef<Expr*> Args,
- bool HadMultipleCandidates,
- bool ListInitialization,
- bool StdInitListInitialization,
- bool ZeroInitialization,
- ConstructionKind ConstructKind,
- SourceRange ParenOrBraceRange) {
- return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc,
- Ctor, Elidable, Args,
- HadMultipleCandidates, ListInitialization,
- StdInitListInitialization,
- ZeroInitialization, ConstructKind,
- ParenOrBraceRange);
-}
-
-CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
- QualType T, SourceLocation Loc,
- CXXConstructorDecl *Ctor,
- bool Elidable,
- ArrayRef<Expr*> Args,
- bool HadMultipleCandidates,
- bool ListInitialization,
- bool StdInitListInitialization,
- bool ZeroInitialization,
- ConstructionKind ConstructKind,
- SourceRange ParenOrBraceRange)
- : Expr(SC, T, VK_RValue, OK_Ordinary,
- T->isDependentType(), T->isDependentType(),
- T->isInstantiationDependentType(),
- T->containsUnexpandedParameterPack()),
- Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange),
- NumArgs(Args.size()), Elidable(Elidable),
- HadMultipleCandidates(HadMultipleCandidates),
- ListInitialization(ListInitialization),
- StdInitListInitialization(StdInitListInitialization),
- ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind) {
- if (NumArgs) {
- this->Args = new (C) Stmt*[Args.size()];
-
- for (unsigned i = 0; i != Args.size(); ++i) {
- assert(Args[i] && "NULL argument in CXXConstructExpr");
-
- if (Args[i]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Args[i]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Args[i]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
+CXXConstructExpr *CXXConstructExpr::Create(
+ const ASTContext &Ctx, QualType Ty, SourceLocation Loc,
+ CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args,
+ bool HadMultipleCandidates, bool ListInitialization,
+ bool StdInitListInitialization, bool ZeroInitialization,
+ ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(Args.size());
+ void *Mem = Ctx.Allocate(sizeof(CXXConstructExpr) + SizeOfTrailingObjects,
+ alignof(CXXConstructExpr));
+ return new (Mem) CXXConstructExpr(
+ CXXConstructExprClass, Ty, Loc, Ctor, Elidable, Args,
+ HadMultipleCandidates, ListInitialization, StdInitListInitialization,
+ ZeroInitialization, ConstructKind, ParenOrBraceRange);
+}
+
+CXXConstructExpr *CXXConstructExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXConstructExpr) + SizeOfTrailingObjects,
+ alignof(CXXConstructExpr));
+ return new (Mem)
+ CXXConstructExpr(CXXConstructExprClass, EmptyShell(), NumArgs);
+}
+
+CXXConstructExpr::CXXConstructExpr(
+ StmtClass SC, QualType Ty, SourceLocation Loc, CXXConstructorDecl *Ctor,
+ bool Elidable, ArrayRef<Expr *> Args, bool HadMultipleCandidates,
+ bool ListInitialization, bool StdInitListInitialization,
+ bool ZeroInitialization, ConstructionKind ConstructKind,
+ SourceRange ParenOrBraceRange)
+ : Expr(SC, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(),
+ Ty->isDependentType(), Ty->isInstantiationDependentType(),
+ Ty->containsUnexpandedParameterPack()),
+ Constructor(Ctor), ParenOrBraceRange(ParenOrBraceRange),
+ NumArgs(Args.size()) {
+ CXXConstructExprBits.Elidable = Elidable;
+ CXXConstructExprBits.HadMultipleCandidates = HadMultipleCandidates;
+ CXXConstructExprBits.ListInitialization = ListInitialization;
+ CXXConstructExprBits.StdInitListInitialization = StdInitListInitialization;
+ CXXConstructExprBits.ZeroInitialization = ZeroInitialization;
+ CXXConstructExprBits.ConstructionKind = ConstructKind;
+ CXXConstructExprBits.Loc = Loc;
+
+ Stmt **TrailingArgs = getTrailingArgs();
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ assert(Args[I] && "NULL argument in CXXConstructExpr!");
- this->Args[i] = Args[i];
- }
+ if (Args[I]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (Args[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (Args[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ TrailingArgs[I] = Args[I];
}
}
+CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty,
+ unsigned NumArgs)
+ : Expr(SC, Empty), NumArgs(NumArgs) {}
+
LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
LambdaCaptureKind Kind, VarDecl *Var,
SourceLocation EllipsisLoc)
@@ -1044,12 +1226,7 @@ bool LambdaExpr::isMutable() const {
ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> objects)
- : Expr(ExprWithCleanupsClass, subexpr->getType(),
- subexpr->getValueKind(), subexpr->getObjectKind(),
- subexpr->isTypeDependent(), subexpr->isValueDependent(),
- subexpr->isInstantiationDependent(),
- subexpr->containsUnexpandedParameterPack()),
- SubExpr(subexpr) {
+ : FullExpr(ExprWithCleanupsClass, subexpr) {
ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
ExprWithCleanupsBits.NumObjects = objects.size();
for (unsigned i = 0, e = objects.size(); i != e; ++i)
@@ -1066,7 +1243,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
}
ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
- : Expr(ExprWithCleanupsClass, empty) {
+ : FullExpr(ExprWithCleanupsClass, empty) {
ExprWithCleanupsBits.NumObjects = numObjects;
}
@@ -1078,22 +1255,22 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
return new (buffer) ExprWithCleanups(empty, numObjects);
}
-CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
- SourceLocation LParenLoc,
- ArrayRef<Expr*> Args,
- SourceLocation RParenLoc)
+CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *TSI,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc)
: Expr(CXXUnresolvedConstructExprClass,
- Type->getType().getNonReferenceType(),
- (Type->getType()->isLValueReferenceType()
+ TSI->getType().getNonReferenceType(),
+ (TSI->getType()->isLValueReferenceType()
? VK_LValue
- : Type->getType()->isRValueReferenceType() ? VK_XValue
- : VK_RValue),
+ : TSI->getType()->isRValueReferenceType() ? VK_XValue
+ : VK_RValue),
OK_Ordinary,
- Type->getType()->isDependentType() ||
- Type->getType()->getContainedDeducedType(),
- true, true, Type->getType()->containsUnexpandedParameterPack()),
- Type(Type), LParenLoc(LParenLoc), RParenLoc(RParenLoc),
- NumArgs(Args.size()) {
+ TSI->getType()->isDependentType() ||
+ TSI->getType()->getContainedDeducedType(),
+ true, true, TSI->getType()->containsUnexpandedParameterPack()),
+ TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
+ CXXUnresolvedConstructExprBits.NumArgs = Args.size();
auto **StoredArgs = getTrailingObjects<Expr *>();
for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->containsUnexpandedParameterPack())
@@ -1103,46 +1280,45 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
}
}
-CXXUnresolvedConstructExpr *
-CXXUnresolvedConstructExpr::Create(const ASTContext &C,
- TypeSourceInfo *Type,
- SourceLocation LParenLoc,
- ArrayRef<Expr*> Args,
- SourceLocation RParenLoc) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
- return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc, Args, RParenLoc);
+CXXUnresolvedConstructExpr *CXXUnresolvedConstructExpr::Create(
+ const ASTContext &Context, TypeSourceInfo *TSI, SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args, SourceLocation RParenLoc) {
+ void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
+ return new (Mem) CXXUnresolvedConstructExpr(TSI, LParenLoc, Args, RParenLoc);
}
CXXUnresolvedConstructExpr *
-CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &C, unsigned NumArgs) {
- Stmt::EmptyShell Empty;
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumArgs));
- return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs);
+CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumArgs) {
+ void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(NumArgs));
+ return new (Mem) CXXUnresolvedConstructExpr(EmptyShell(), NumArgs);
}
-SourceLocation CXXUnresolvedConstructExpr::getLocStart() const {
- return Type->getTypeLoc().getBeginLoc();
+SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
+ return TSI->getTypeLoc().getBeginLoc();
}
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
- const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow,
+ const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
- : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue,
+ : Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
OK_Ordinary, true, true, true,
((Base && Base->containsUnexpandedParameterPack()) ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()) ||
+ (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()) ||
MemberNameInfo.containsUnexpandedParameterPack())),
- Base(Base), BaseType(BaseType), IsArrow(IsArrow),
- HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
- TemplateKWLoc.isValid()),
- OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
- FirstQualifierFoundInScope(FirstQualifierFoundInScope),
+ Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
MemberNameInfo(MemberNameInfo) {
+ CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
+ CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
+ (TemplateArgs != nullptr) || TemplateKWLoc.isValid();
+ CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
+ FirstQualifierFoundInScope != nullptr;
+ CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
+
if (TemplateArgs) {
bool Dependent = true;
bool InstantiationDependent = true;
@@ -1156,56 +1332,54 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc);
}
+
+ if (hasFirstQualifierFoundInScope())
+ *getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
}
-CXXDependentScopeMemberExpr *
-CXXDependentScopeMemberExpr::Create(const ASTContext &C,
- Expr *Base, QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierFoundInScope,
- DeclarationNameInfo MemberNameInfo,
- const TemplateArgumentListInfo *TemplateArgs) {
- bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
+CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
+ EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
+ bool HasFirstQualifierFoundInScope)
+ : Expr(CXXDependentScopeMemberExprClass, Empty) {
+ CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
+ HasTemplateKWAndArgsInfo;
+ CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
+ HasFirstQualifierFoundInScope;
+}
+
+CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create(
+ const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ bool HasTemplateKWAndArgsInfo =
+ (TemplateArgs != nullptr) || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
- std::size_t Size =
- totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
- HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr;
- void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
- return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType,
- IsArrow, OperatorLoc,
- QualifierLoc,
- TemplateKWLoc,
- FirstQualifierFoundInScope,
- MemberNameInfo, TemplateArgs);
+ unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc, NamedDecl *>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
+
+ void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
+ return new (Mem) CXXDependentScopeMemberExpr(
+ Ctx, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc,
+ FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs);
}
-CXXDependentScopeMemberExpr *
-CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
- bool HasTemplateKWAndArgsInfo,
- unsigned NumTemplateArgs) {
+CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
+ const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
- std::size_t Size =
- totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
- HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
- auto *E =
- new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
- false, SourceLocation(),
- NestedNameSpecifierLoc(),
- SourceLocation(), nullptr,
- DeclarationNameInfo(), nullptr);
- E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
- return E;
-}
-bool CXXDependentScopeMemberExpr::isImplicitAccess() const {
- if (!Base)
- return true;
+ unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc, NamedDecl *>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
- return cast<Expr>(Base)->isImplicitCXXThis();
+ void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
+ return new (Mem) CXXDependentScopeMemberExpr(
+ EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
}
static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin,
@@ -1225,19 +1399,15 @@ static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin,
return true;
}
-UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C,
- bool HasUnresolvedUsing,
- Expr *Base, QualType BaseType,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &MemberNameInfo,
- const TemplateArgumentListInfo *TemplateArgs,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End)
+UnresolvedMemberExpr::UnresolvedMemberExpr(
+ const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base,
+ QualType BaseType, bool IsArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End)
: OverloadExpr(
- UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc,
+ UnresolvedMemberExprClass, Context, QualifierLoc, TemplateKWLoc,
MemberNameInfo, TemplateArgs, Begin, End,
// Dependent
((Base && Base->isTypeDependent()) || BaseType->isDependentType()),
@@ -1246,14 +1416,22 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C,
// Contains unexpanded parameter pack
((Base && Base->containsUnexpandedParameterPack()) ||
BaseType->containsUnexpandedParameterPack())),
- IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base),
- BaseType(BaseType), OperatorLoc(OperatorLoc) {
+ Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
+ UnresolvedMemberExprBits.IsArrow = IsArrow;
+ UnresolvedMemberExprBits.HasUnresolvedUsing = HasUnresolvedUsing;
+
// Check whether all of the members are non-static member functions,
// and if so, mark give this bound-member type instead of overload type.
if (hasOnlyNonStaticMemberFunctions(Begin, End))
- setType(C.BoundMemberTy);
+ setType(Context.BoundMemberTy);
}
+UnresolvedMemberExpr::UnresolvedMemberExpr(EmptyShell Empty,
+ unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo)
+ : OverloadExpr(UnresolvedMemberExprClass, Empty, NumResults,
+ HasTemplateKWAndArgsInfo) {}
+
bool UnresolvedMemberExpr::isImplicitAccess() const {
if (!Base)
return true;
@@ -1262,39 +1440,37 @@ bool UnresolvedMemberExpr::isImplicitAccess() const {
}
UnresolvedMemberExpr *UnresolvedMemberExpr::Create(
- const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType,
- bool IsArrow, SourceLocation OperatorLoc,
+ const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base,
+ QualType BaseType, bool IsArrow, SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
+ unsigned NumResults = End - Begin;
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
- std::size_t Size =
- totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
- HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0);
-
- void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
+ unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr));
return new (Mem) UnresolvedMemberExpr(
- C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc,
- TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
+ Context, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc,
+ QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
}
-UnresolvedMemberExpr *
-UnresolvedMemberExpr::CreateEmpty(const ASTContext &C,
- bool HasTemplateKWAndArgsInfo,
- unsigned NumTemplateArgs) {
+UnresolvedMemberExpr *UnresolvedMemberExpr::CreateEmpty(
+ const ASTContext &Context, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
- std::size_t Size =
- totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
- HasTemplateKWAndArgsInfo, NumTemplateArgs);
-
- void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
- auto *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
- E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
- return E;
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr));
+ return new (Mem)
+ UnresolvedMemberExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo);
}
-CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
+CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() {
// Unlike for UnresolvedLookupExpr, it is very easy to re-derive this.
// If there was a nested name specifier, it names the naming class.
@@ -1448,4 +1624,37 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
return new (Mem) TypeTraitExpr(EmptyShell());
}
-void ArrayTypeTraitExpr::anchor() {}
+CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config,
+ ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK, SourceLocation RP,
+ unsigned MinNumArgs)
+ : CallExpr(CUDAKernelCallExprClass, Fn, /*PreArgs=*/Config, Args, Ty, VK,
+ RP, MinNumArgs, NotADL) {}
+
+CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs,
+ Empty) {}
+
+CUDAKernelCallExpr *
+CUDAKernelCallExpr::Create(const ASTContext &Ctx, Expr *Fn, CallExpr *Config,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation RP, unsigned MinNumArgs) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
+ alignof(CUDAKernelCallExpr));
+ return new (Mem) CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, MinNumArgs);
+}
+
+CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
+ alignof(CUDAKernelCallExpr));
+ return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
+}
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index e50dd9c79d11..e1d6a1c9edcc 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -194,6 +194,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::DesignatedInitUpdateExprClass:
return Cl::CL_PRValue;
+ case Expr::ConstantExprClass:
+ return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr());
+
// Next come the complicated cases.
case Expr::SubstNonTypeTemplateParmExprClass:
return ClassifyInternal(Ctx,
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 44cf75dbd25b..da093ff22c12 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -39,11 +39,13 @@
#include "clang/AST/ASTLambda.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/OSLog.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
#include <functional>
@@ -143,8 +145,8 @@ namespace {
// If we're doing a variable assignment from e.g. malloc(N), there will
// probably be a cast of some kind. In exotic cases, we might also see a
// top-level ExprWithCleanups. Ignore them either way.
- if (const auto *EC = dyn_cast<ExprWithCleanups>(E))
- E = EC->getSubExpr()->IgnoreParens();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr()->IgnoreParens();
if (const auto *Cast = dyn_cast<CastExpr>(E))
E = Cast->getSubExpr()->IgnoreParens();
@@ -350,6 +352,7 @@ namespace {
/// Get the type of the designated object.
QualType getType(ASTContext &Ctx) const {
+ assert(!Invalid && "invalid designator has no subobject type");
return MostDerivedPathLength == Entries.size()
? MostDerivedType
: Ctx.getRecordType(getAsBaseClass(Entries.back()));
@@ -504,7 +507,7 @@ namespace {
}
// FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact
- // on the overall stack usage of deeply-recursing constexpr evaluataions.
+ // on the overall stack usage of deeply-recursing constexpr evaluations.
// (We should cache this map rather than recomputing it repeatedly.)
// But let's try this and see how it goes; we can look into caching the map
// as a later change.
@@ -719,6 +722,10 @@ namespace {
/// Whether or not we're currently speculatively evaluating.
bool IsSpeculativelyEvaluating;
+ /// Whether or not we're in a context where the front end requires a
+ /// constant value.
+ bool InConstantContext;
+
enum EvaluationMode {
/// Evaluate as a constant expression. Stop if we find that the expression
/// is not a constant expression.
@@ -758,18 +765,6 @@ namespace {
/// context we try to fold them immediately since the optimizer never
/// gets a chance to look at it.
EM_PotentialConstantExpressionUnevaluated,
-
- /// Evaluate as a constant expression. In certain scenarios, if:
- /// - we find a MemberExpr with a base that can't be evaluated, or
- /// - we find a variable initialized with a call to a function that has
- /// the alloc_size attribute on it
- /// then we may consider evaluation to have succeeded.
- ///
- /// In either case, the LValue returned shall have an invalid base; in the
- /// former, the base will be the invalid MemberExpr, in the latter, the
- /// base will be either the alloc_size CallExpr or a CastExpr wrapping
- /// said CallExpr.
- EM_OffsetFold,
} EvalMode;
/// Are we checking whether the expression is a potential constant
@@ -792,7 +787,7 @@ namespace {
EvaluatingDecl((const ValueDecl *)nullptr),
EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false),
- EvalMode(Mode) {}
+ InConstantContext(false), EvalMode(Mode) {}
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
@@ -831,7 +826,7 @@ namespace {
bool nextStep(const Stmt *S) {
if (!StepsLeft) {
- FFDiag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded);
+ FFDiag(S->getBeginLoc(), diag::note_constexpr_step_limit_exceeded);
return false;
}
--StepsLeft;
@@ -873,7 +868,6 @@ namespace {
case EM_PotentialConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_PotentialConstantExpressionUnevaluated:
- case EM_OffsetFold:
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -965,7 +959,6 @@ namespace {
case EM_ConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
- case EM_OffsetFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -984,7 +977,6 @@ namespace {
case EM_EvaluateForOverflow:
case EM_IgnoreSideEffects:
case EM_ConstantFold:
- case EM_OffsetFold:
return true;
case EM_PotentialConstantExpression:
@@ -1020,7 +1012,6 @@ namespace {
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
case EM_IgnoreSideEffects:
- case EM_OffsetFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -1092,18 +1083,18 @@ namespace {
}
};
- /// RAII object used to treat the current evaluation as the correct pointer
- /// offset fold for the current EvalMode
- struct FoldOffsetRAII {
+ /// RAII object used to set the current evaluation mode to ignore
+ /// side-effects.
+ struct IgnoreSideEffectsRAII {
EvalInfo &Info;
EvalInfo::EvaluationMode OldMode;
- explicit FoldOffsetRAII(EvalInfo &Info)
+ explicit IgnoreSideEffectsRAII(EvalInfo &Info)
: Info(Info), OldMode(Info.EvalMode) {
if (!Info.checkingPotentialConstantExpression())
- Info.EvalMode = EvalInfo::EM_OffsetFold;
+ Info.EvalMode = EvalInfo::EM_IgnoreSideEffects;
}
- ~FoldOffsetRAII() { Info.EvalMode = OldMode; }
+ ~IgnoreSideEffectsRAII() { Info.EvalMode = OldMode; }
};
/// RAII object used to optionally suppress diagnostics and side-effects from
@@ -1299,6 +1290,14 @@ void EvalInfo::addCallStack(unsigned Limit) {
}
}
+/// Kinds of access we can perform on an object, for diagnostics.
+enum AccessKinds {
+ AK_Read,
+ AK_Assign,
+ AK_Increment,
+ AK_Decrement
+};
+
namespace {
struct ComplexValue {
private:
@@ -1404,21 +1403,36 @@ namespace {
set(B, true);
}
+ private:
// Check that this LValue is not based on a null pointer. If it is, produce
// a diagnostic and mark the designator as invalid.
- bool checkNullPointer(EvalInfo &Info, const Expr *E,
- CheckSubobjectKind CSK) {
+ template <typename GenDiagType>
+ bool checkNullPointerDiagnosingWith(const GenDiagType &GenDiag) {
if (Designator.Invalid)
return false;
if (IsNullPtr) {
- Info.CCEDiag(E, diag::note_constexpr_null_subobject)
- << CSK;
+ GenDiag();
Designator.setInvalid();
return false;
}
return true;
}
+ public:
+ bool checkNullPointer(EvalInfo &Info, const Expr *E,
+ CheckSubobjectKind CSK) {
+ return checkNullPointerDiagnosingWith([&Info, E, CSK] {
+ Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK;
+ });
+ }
+
+ bool checkNullPointerForFoldAccess(EvalInfo &Info, const Expr *E,
+ AccessKinds AK) {
+ return checkNullPointerDiagnosingWith([&Info, E, AK] {
+ Info.FFDiag(E, diag::note_constexpr_access_null) << AK;
+ });
+ }
+
// Check this LValue refers to an object. If not, set the designator to be
// invalid and emit a diagnostic.
bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) {
@@ -2088,11 +2102,12 @@ static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E,
QualType DestType, QualType SrcType,
const APSInt &Value) {
unsigned DestWidth = Info.Ctx.getIntWidth(DestType);
- APSInt Result = Value;
// Figure out if this is a truncate, extend or noop cast.
// If the input is signed, do a sign extend, noop, or truncate.
- Result = Result.extOrTrunc(DestWidth);
+ APSInt Result = Value.extOrTrunc(DestWidth);
Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType());
+ if (DestType->isBooleanType())
+ Result = Value.getBoolValue();
return Result;
}
@@ -2553,8 +2568,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
if (Info.checkingPotentialConstantExpression())
return false;
// FIXME: implement capture evaluation during constant expr evaluation.
- Info.FFDiag(E->getLocStart(),
- diag::note_unimplemented_constexpr_lambda_feature_ast)
+ Info.FFDiag(E->getBeginLoc(),
+ diag::note_unimplemented_constexpr_lambda_feature_ast)
<< "captures not currently allowed";
return false;
}
@@ -2754,14 +2769,6 @@ static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E,
return false;
}
-/// Kinds of access we can perform on an object, for diagnostics.
-enum AccessKinds {
- AK_Read,
- AK_Assign,
- AK_Increment,
- AK_Decrement
-};
-
namespace {
/// A handle to a complete object (an object that is not a subobject of
/// another object).
@@ -3432,19 +3439,31 @@ struct CompoundAssignSubobjectHandler {
if (!checkConst(SubobjType))
return false;
- if (!SubobjType->isIntegerType() || !RHS.isInt()) {
+ if (!SubobjType->isIntegerType()) {
// We don't support compound assignment on integer-cast-to-pointer
// values.
Info.FFDiag(E);
return false;
}
- APSInt LHS = HandleIntToIntCast(Info, E, PromotedLHSType,
- SubobjType, Value);
- if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS))
- return false;
- Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS);
- return true;
+ if (RHS.isInt()) {
+ APSInt LHS =
+ HandleIntToIntCast(Info, E, PromotedLHSType, SubobjType, Value);
+ if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS))
+ return false;
+ Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS);
+ return true;
+ } else if (RHS.isFloat()) {
+ APFloat FValue(0.0);
+ return HandleIntToFloatCast(Info, E, SubobjType, Value, PromotedLHSType,
+ FValue) &&
+ handleFloatFloatBinOp(Info, E, FValue, Opcode, RHS.getFloat()) &&
+ HandleFloatToIntCast(Info, E, PromotedLHSType, FValue, SubobjType,
+ Value);
+ }
+
+ Info.FFDiag(E);
+ return false;
}
bool found(APFloat &Value, QualType SubobjType) {
return checkConst(SubobjType) &&
@@ -3844,8 +3863,8 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
const Expr *InitE = VD->getInit();
if (!InitE) {
- Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized)
- << false << VD->getType();
+ Info.FFDiag(VD->getBeginLoc(), diag::note_constexpr_uninitialized)
+ << false << VD->getType();
Val = APValue();
return false;
}
@@ -3990,7 +4009,8 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info,
case ESR_CaseNotFound:
// This can only happen if the switch case is nested within a statement
// expression. We have no intention of supporting that.
- Info.FFDiag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported);
+ Info.FFDiag(Found->getBeginLoc(),
+ diag::note_constexpr_stmt_expr_unsupported);
return ESR_Failed;
}
llvm_unreachable("Invalid EvalStmtResult!");
@@ -4081,7 +4101,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
return ESR_Succeeded;
}
- Info.FFDiag(S->getLocStart());
+ Info.FFDiag(S->getBeginLoc());
return ESR_Failed;
case Stmt::NullStmtClass:
@@ -4215,6 +4235,13 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
const CXXForRangeStmt *FS = cast<CXXForRangeStmt>(S);
BlockScopeRAII Scope(Info);
+ // Evaluate the init-statement if present.
+ if (FS->getInit()) {
+ EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit());
+ if (ESR != ESR_Succeeded)
+ return ESR;
+ }
+
// Initialize the __range variable.
EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getRangeStmt());
if (ESR != ESR_Succeeded)
@@ -4279,6 +4306,9 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
case Stmt::CaseStmtClass:
case Stmt::DefaultStmtClass:
return EvaluateStmt(Result, Info, cast<SwitchCase>(S)->getSubStmt(), Case);
+ case Stmt::CXXTryStmtClass:
+ // Evaluate try blocks by evaluating all sub statements.
+ return EvaluateStmt(Result, Info, cast<CXXTryStmt>(S)->getTryBlock(), Case);
}
}
@@ -4321,10 +4351,13 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
Declaration->isConstexpr())
return false;
- // Bail out with no diagnostic if the function declaration itself is invalid.
- // We will have produced a relevant diagnostic while parsing it.
- if (Declaration->isInvalidDecl())
+ // Bail out if the function declaration itself is invalid. We will
+ // have produced a relevant diagnostic while parsing it, so just
+ // note the problematic sub-expression.
+ if (Declaration->isInvalidDecl()) {
+ Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr);
return false;
+ }
// Can we evaluate this function call?
if (Definition && Definition->isConstexpr() &&
@@ -4429,7 +4462,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(),
RHS, RHSValue))
return false;
- if (!handleAssignment(Info, Args[0], *This, MD->getThisType(Info.Ctx),
+ if (!handleAssignment(Info, Args[0], *This, MD->getThisType(),
RHSValue))
return false;
This->moveInto(Result);
@@ -4451,7 +4484,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
if (ESR == ESR_Succeeded) {
if (Callee->getReturnType()->isVoidType())
return true;
- Info.FFDiag(Callee->getLocEnd(), diag::note_constexpr_no_return);
+ Info.FFDiag(Callee->getEndLoc(), diag::note_constexpr_no_return);
}
return ESR == ESR_Returned;
}
@@ -4722,6 +4755,8 @@ public:
return Error(E);
}
+ bool VisitConstantExpr(const ConstantExpr *E)
+ { return StmtVisitorTy::Visit(E->getSubExpr()); }
bool VisitParenExpr(const ParenExpr *E)
{ return StmtVisitorTy::Visit(E->getSubExpr()); }
bool VisitUnaryExtension(const UnaryOperator *E)
@@ -5076,8 +5111,8 @@ public:
if (BI + 1 == BE) {
const Expr *FinalExpr = dyn_cast<Expr>(*BI);
if (!FinalExpr) {
- Info.FFDiag((*BI)->getLocStart(),
- diag::note_constexpr_stmt_expr_unsupported);
+ Info.FFDiag((*BI)->getBeginLoc(),
+ diag::note_constexpr_stmt_expr_unsupported);
return false;
}
return this->Visit(FinalExpr);
@@ -5091,8 +5126,8 @@ public:
// 'break', or 'continue', it would be nice to propagate that to
// the outer statement evaluation rather than bailing out.
if (ESR != ESR_Failed)
- Info.FFDiag((*BI)->getLocStart(),
- diag::note_constexpr_stmt_expr_unsupported);
+ Info.FFDiag((*BI)->getBeginLoc(),
+ diag::note_constexpr_stmt_expr_unsupported);
return false;
}
}
@@ -5625,8 +5660,10 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
return false;
auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) {
- if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects))
+ Expr::EvalResult ExprResult;
+ if (!E->EvaluateAsInt(ExprResult, Ctx, Expr::SE_AllowSideEffects))
return false;
+ Into = ExprResult.Val.getInt();
if (Into.isNegative() || !Into.isIntN(BitsInSizeT))
return false;
Into = Into.zextOrSelf(BitsInSizeT);
@@ -5852,11 +5889,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
// permitted in constant expressions in C++11. Bitcasts from cv void* are
// also static_casts, but we disallow them as a resolution to DR1312.
if (!E->getType()->isVoidPointerType()) {
- // If we changed anything other than cvr-qualifiers, we can't use this
- // value for constant folding. FIXME: Qualification conversions should
- // always be CK_NoOp, but we get this wrong in C.
- if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType()))
- Result.Designator.setInvalid();
+ Result.Designator.setInvalid();
if (SubExpr->getType()->isVoidPointerType())
CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 3 << SubExpr->getType();
@@ -5954,21 +5987,35 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
return ExprEvaluatorBaseTy::VisitCastExpr(E);
}
-static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) {
+static CharUnits GetAlignOfType(EvalInfo &Info, QualType T,
+ UnaryExprOrTypeTrait ExprKind) {
// C++ [expr.alignof]p3:
// When alignof is applied to a reference type, the result is the
// alignment of the referenced type.
if (const ReferenceType *Ref = T->getAs<ReferenceType>())
T = Ref->getPointeeType();
- // __alignof is defined to return the preferred alignment.
if (T.getQualifiers().hasUnaligned())
return CharUnits::One();
- return Info.Ctx.toCharUnitsFromBits(
- Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
+
+ const bool AlignOfReturnsPreferred =
+ Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
+
+ // __alignof is defined to return the preferred alignment.
+ // Before 8, clang returned the preferred alignment for alignof and _Alignof
+ // as well.
+ if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
+ return Info.Ctx.toCharUnitsFromBits(
+ Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
+ // alignof and _Alignof are defined to return the ABI alignment.
+ else if (ExprKind == UETT_AlignOf)
+ return Info.Ctx.getTypeAlignInChars(T.getTypePtr());
+ else
+ llvm_unreachable("GetAlignOfType on a non-alignment ExprKind");
}
-static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) {
+static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E,
+ UnaryExprOrTypeTrait ExprKind) {
E = E->IgnoreParens();
// The kinds of expressions that we have special-case logic here for
@@ -5985,7 +6032,7 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) {
return Info.Ctx.getDeclAlign(ME->getMemberDecl(),
/*RefAsPointee*/true);
- return GetAlignOfType(Info, E->getType());
+ return GetAlignOfType(Info, E->getType(), ExprKind);
}
// To be clear: this happily visits unsupported builtins. Better name welcomed.
@@ -6046,8 +6093,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
OffsetResult.Base.dyn_cast<const ValueDecl*>()) {
BaseAlignment = Info.Ctx.getDeclAlign(VD);
} else {
- BaseAlignment =
- GetAlignOfExpr(Info, OffsetResult.Base.get<const Expr*>());
+ BaseAlignment = GetAlignOfExpr(
+ Info, OffsetResult.Base.get<const Expr *>(), UETT_AlignOf);
}
if (BaseAlignment < Align) {
@@ -6077,7 +6124,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return true;
}
-
+ case Builtin::BI__builtin_launder:
+ return evaluatePointer(E->getArg(0), Result);
case Builtin::BIstrchr:
case Builtin::BIwcschr:
case Builtin::BImemchr:
@@ -6109,9 +6157,27 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return false;
MaxLength = N.getExtValue();
}
-
- QualType CharTy = E->getArg(0)->getType()->getPointeeType();
-
+ // We cannot find the value if there are no candidates to match against.
+ if (MaxLength == 0u)
+ return ZeroInitialization(E);
+ if (!Result.checkNullPointerForFoldAccess(Info, E, AK_Read) ||
+ Result.Designator.Invalid)
+ return false;
+ QualType CharTy = Result.Designator.getType(Info.Ctx);
+ bool IsRawByte = BuiltinOp == Builtin::BImemchr ||
+ BuiltinOp == Builtin::BI__builtin_memchr;
+ assert(IsRawByte ||
+ Info.Ctx.hasSameUnqualifiedType(
+ CharTy, E->getArg(0)->getType()->getPointeeType()));
+ // Pointers to const void may point to objects of incomplete type.
+ if (IsRawByte && CharTy->isIncompleteType()) {
+ Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy;
+ return false;
+ }
+ // Give up on byte-oriented matching against multibyte elements.
+ // FIXME: We can compare the bytes in the correct order.
+ if (IsRawByte && Info.Ctx.getTypeSizeInChars(CharTy) != CharUnits::One())
+ return false;
// Figure out what value we're actually looking for (after converting to
// the corresponding unsigned type if necessary).
uint64_t DesiredVal;
@@ -6207,6 +6273,20 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
if (!N)
return true;
+ // Otherwise, if either of the operands is null, we can't proceed. Don't
+ // try to determine the type of the copied objects, because there aren't
+ // any.
+ if (!Src.Base || !Dest.Base) {
+ APValue Val;
+ (!Src.Base ? Src : Dest).moveInto(Val);
+ Info.FFDiag(E, diag::note_constexpr_memcpy_null)
+ << Move << WChar << !!Src.Base
+ << Val.getAsString(Info.Ctx, E->getArg(0)->getType());
+ return false;
+ }
+ if (Src.Designator.Invalid || Dest.Designator.Invalid)
+ return false;
+
// We require that Src and Dest are both pointers to arrays of
// trivially-copyable type. (For the wide version, the designator will be
// invalid if the designated object is not a wchar_t.)
@@ -6216,6 +6296,10 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
Info.FFDiag(E, diag::note_constexpr_memcpy_type_pun) << Move << SrcT << T;
return false;
}
+ if (T->isIncompleteType()) {
+ Info.FFDiag(E, diag::note_constexpr_memcpy_incomplete_type) << Move << T;
+ return false;
+ }
if (!T.isTriviallyCopyableType(Info.Ctx)) {
Info.FFDiag(E, diag::note_constexpr_memcpy_nontrivial) << Move << T;
return false;
@@ -7320,6 +7404,8 @@ public:
// Visitor Methods
//===--------------------------------------------------------------------===//
+ bool VisitConstantExpr(const ConstantExpr *E);
+
bool VisitIntegerLiteral(const IntegerLiteral *E) {
return Success(E->getValue(), E);
}
@@ -7619,6 +7705,9 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
@@ -8023,7 +8112,7 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
// If there are any, but we can determine the pointed-to object anyway, then
// ignore the side-effects.
SpeculativeEvaluationRAII SpeculativeEval(Info);
- FoldOffsetRAII Fold(Info);
+ IgnoreSideEffectsRAII Fold(Info);
if (E->isGLValue()) {
// It's possible for us to be given GLValues if we're called via
@@ -8057,6 +8146,11 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
return true;
}
+bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) {
+ llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
+ return ExprEvaluatorBaseTy::VisitConstantExpr(E);
+}
+
bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (unsigned BuiltinOp = E->getBuiltinCallee())
return VisitBuiltinCallExpr(E, BuiltinOp);
@@ -8091,7 +8185,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case EvalInfo::EM_ConstantFold:
case EvalInfo::EM_EvaluateForOverflow:
case EvalInfo::EM_IgnoreSideEffects:
- case EvalInfo::EM_OffsetFold:
// Leave it to IR generation.
return Error(E);
case EvalInfo::EM_ConstantExpressionUnevaluated:
@@ -8103,6 +8196,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
llvm_unreachable("unexpected EvalMode");
}
+ case Builtin::BI__builtin_os_log_format_buffer_size: {
+ analyze_os_log::OSLogBufferLayout Layout;
+ analyze_os_log::computeOSLogBufferLayout(Info.Ctx, E, Layout);
+ return Success(Layout.size().getQuantity(), E);
+ }
+
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64: {
@@ -8116,9 +8215,15 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case Builtin::BI__builtin_classify_type:
return Success((int)EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E);
- // FIXME: BI__builtin_clrsb
- // FIXME: BI__builtin_clrsbl
- // FIXME: BI__builtin_clrsbll
+ case Builtin::BI__builtin_clrsb:
+ case Builtin::BI__builtin_clrsbl:
+ case Builtin::BI__builtin_clrsbll: {
+ APSInt Val;
+ if (!EvaluateInteger(E->getArg(0), Val, Info))
+ return false;
+
+ return Success(Val.getBitWidth() - Val.getMinSignedBits(), E);
+ }
case Builtin::BI__builtin_clz:
case Builtin::BI__builtin_clzl:
@@ -8133,8 +8238,20 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Val.countLeadingZeros(), E);
}
- case Builtin::BI__builtin_constant_p:
- return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E);
+ case Builtin::BI__builtin_constant_p: {
+ auto Arg = E->getArg(0);
+ if (EvaluateBuiltinConstantP(Info.Ctx, Arg))
+ return Success(true, E);
+ auto ArgTy = Arg->IgnoreImplicit()->getType();
+ if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) &&
+ !ArgTy->isAggregateType() && !ArgTy->isPointerType()) {
+ // We can delay calculation of __builtin_constant_p until after
+ // inlining. Note: This diagnostic won't be shown to the user.
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ return false;
+ }
+ return Success(false, E);
+ }
case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl:
@@ -8314,8 +8431,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
!EvaluatePointer(E->getArg(1), String2, Info))
return false;
- QualType CharTy = E->getArg(0)->getType()->getPointeeType();
-
uint64_t MaxLength = uint64_t(-1);
if (BuiltinOp != Builtin::BIstrcmp &&
BuiltinOp != Builtin::BIwcscmp &&
@@ -8326,6 +8441,88 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return false;
MaxLength = N.getExtValue();
}
+
+ // Empty substrings compare equal by definition.
+ if (MaxLength == 0u)
+ return Success(0, E);
+
+ if (!String1.checkNullPointerForFoldAccess(Info, E, AK_Read) ||
+ !String2.checkNullPointerForFoldAccess(Info, E, AK_Read) ||
+ String1.Designator.Invalid || String2.Designator.Invalid)
+ return false;
+
+ QualType CharTy1 = String1.Designator.getType(Info.Ctx);
+ QualType CharTy2 = String2.Designator.getType(Info.Ctx);
+
+ bool IsRawByte = BuiltinOp == Builtin::BImemcmp ||
+ BuiltinOp == Builtin::BI__builtin_memcmp;
+
+ assert(IsRawByte ||
+ (Info.Ctx.hasSameUnqualifiedType(
+ CharTy1, E->getArg(0)->getType()->getPointeeType()) &&
+ Info.Ctx.hasSameUnqualifiedType(CharTy1, CharTy2)));
+
+ const auto &ReadCurElems = [&](APValue &Char1, APValue &Char2) {
+ return handleLValueToRValueConversion(Info, E, CharTy1, String1, Char1) &&
+ handleLValueToRValueConversion(Info, E, CharTy2, String2, Char2) &&
+ Char1.isInt() && Char2.isInt();
+ };
+ const auto &AdvanceElems = [&] {
+ return HandleLValueArrayAdjustment(Info, E, String1, CharTy1, 1) &&
+ HandleLValueArrayAdjustment(Info, E, String2, CharTy2, 1);
+ };
+
+ if (IsRawByte) {
+ uint64_t BytesRemaining = MaxLength;
+ // Pointers to const void may point to objects of incomplete type.
+ if (CharTy1->isIncompleteType()) {
+ Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy1;
+ return false;
+ }
+ if (CharTy2->isIncompleteType()) {
+ Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy2;
+ return false;
+ }
+ uint64_t CharTy1Width{Info.Ctx.getTypeSize(CharTy1)};
+ CharUnits CharTy1Size = Info.Ctx.toCharUnitsFromBits(CharTy1Width);
+ // Give up on comparing between elements with disparate widths.
+ if (CharTy1Size != Info.Ctx.getTypeSizeInChars(CharTy2))
+ return false;
+ uint64_t BytesPerElement = CharTy1Size.getQuantity();
+ assert(BytesRemaining && "BytesRemaining should not be zero: the "
+ "following loop considers at least one element");
+ while (true) {
+ APValue Char1, Char2;
+ if (!ReadCurElems(Char1, Char2))
+ return false;
+ // We have compatible in-memory widths, but a possible type and
+ // (for `bool`) internal representation mismatch.
+ // Assuming two's complement representation, including 0 for `false` and
+ // 1 for `true`, we can check an appropriate number of elements for
+ // equality even if they are not byte-sized.
+ APSInt Char1InMem = Char1.getInt().extOrTrunc(CharTy1Width);
+ APSInt Char2InMem = Char2.getInt().extOrTrunc(CharTy1Width);
+ if (Char1InMem.ne(Char2InMem)) {
+ // If the elements are byte-sized, then we can produce a three-way
+ // comparison result in a straightforward manner.
+ if (BytesPerElement == 1u) {
+ // memcmp always compares unsigned chars.
+ return Success(Char1InMem.ult(Char2InMem) ? -1 : 1, E);
+ }
+ // The result is byte-order sensitive, and we have multibyte elements.
+ // FIXME: We can compare the remaining bytes in the correct order.
+ return false;
+ }
+ if (!AdvanceElems())
+ return false;
+ if (BytesRemaining <= BytesPerElement)
+ break;
+ BytesRemaining -= BytesPerElement;
+ }
+ // Enough elements are equal to account for the memcmp limit.
+ return Success(0, E);
+ }
+
bool StopAtNull = (BuiltinOp != Builtin::BImemcmp &&
BuiltinOp != Builtin::BIwmemcmp &&
BuiltinOp != Builtin::BI__builtin_memcmp &&
@@ -8336,11 +8533,10 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
BuiltinOp == Builtin::BI__builtin_wcscmp ||
BuiltinOp == Builtin::BI__builtin_wcsncmp ||
BuiltinOp == Builtin::BI__builtin_wmemcmp;
+
for (; MaxLength; --MaxLength) {
APValue Char1, Char2;
- if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) ||
- !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) ||
- !Char1.isInt() || !Char2.isInt())
+ if (!ReadCurElems(Char1, Char2))
return false;
if (Char1.getInt() != Char2.getInt()) {
if (IsWide) // wmemcmp compares with wchar_t signedness.
@@ -8351,8 +8547,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
if (StopAtNull && !Char1.getInt())
return Success(0, E);
assert(!(StopAtNull && !Char2.getInt()));
- if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) ||
- !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1))
+ if (!AdvanceElems())
return false;
}
// We hit the strncmp / memcmp limit.
@@ -9343,11 +9538,14 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *E) {
switch(E->getKind()) {
+ case UETT_PreferredAlignOf:
case UETT_AlignOf: {
if (E->isArgumentType())
- return Success(GetAlignOfType(Info, E->getArgumentType()), E);
+ return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()),
+ E);
else
- return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E);
+ return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()),
+ E);
}
case UETT_VecStep: {
@@ -9536,11 +9734,11 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
case CK_BuiltinFnToFnPtr:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_ZeroToOCLOpaqueType:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
+ case CK_FixedPointCast:
llvm_unreachable("invalid cast kind for integral value");
case CK_BitCast:
@@ -9575,6 +9773,14 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
return Success(IntResult, E);
}
+ case CK_FixedPointToBoolean: {
+ // Unsigned padding does not affect this.
+ APValue Val;
+ if (!Evaluate(Val, Info, SubExpr))
+ return false;
+ return Success(Val.getInt().getBoolValue(), E);
+ }
+
case CK_IntegralCast: {
if (!Visit(SubExpr))
return false;
@@ -9697,8 +9903,7 @@ bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) {
SmallString<64> S;
FixedPointValueToString(S, Value,
- Info.Ctx.getTypeInfo(E->getType()).Width,
- /*Radix=*/10);
+ Info.Ctx.getTypeInfo(E->getType()).Width);
Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType();
if (Info.noteUndefinedBehavior()) return false;
}
@@ -10071,11 +10276,12 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_ZeroToOCLOpaqueType:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -10236,7 +10442,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
case BO_Mul:
if (Result.isComplexFloat()) {
// This is an implementation of complex multiplication according to the
- // constraints laid out in C11 Annex G. The implemention uses the
+ // constraints laid out in C11 Annex G. The implementation uses the
// following naming scheme:
// (a + ib) * (c + id)
ComplexValue LHS = Result;
@@ -10317,7 +10523,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
case BO_Div:
if (Result.isComplexFloat()) {
// This is an implementation of complex division according to the
- // constraints laid out in C11 Annex G. The implemention uses the
+ // constraints laid out in C11 Annex G. The implementation uses the
// following naming scheme:
// (a + ib) / (c + id)
ComplexValue LHS = Result;
@@ -10693,19 +10899,46 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
return false;
}
+static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result,
+ Expr::SideEffectsKind SEK) {
+ return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) ||
+ (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior);
+}
+
+static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result,
+ const ASTContext &Ctx, EvalInfo &Info) {
+ bool IsConst;
+ if (FastEvaluateAsRValue(E, Result, Ctx, IsConst))
+ return IsConst;
+
+ return EvaluateAsRValue(Info, E, Result.Val);
+}
+
+static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult,
+ const ASTContext &Ctx,
+ Expr::SideEffectsKind AllowSideEffects,
+ EvalInfo &Info) {
+ if (!E->getType()->isIntegralOrEnumerationType())
+ return false;
+
+ if (!::EvaluateAsRValue(E, ExprResult, Ctx, Info) ||
+ !ExprResult.Val.isInt() ||
+ hasUnacceptableSideEffect(ExprResult, AllowSideEffects))
+ return false;
+
+ return true;
+}
/// EvaluateAsRValue - Return true if this is a constant which we can fold using
/// any crazy technique (that has nothing to do with language standards) that
/// we want to. If this function returns true, it returns the folded constant
/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion
/// will be applied to the result.
-bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
- bool IsConst;
- if (FastEvaluateAsRValue(this, Result, Ctx, IsConst))
- return IsConst;
-
+bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
+ bool InConstantContext) const {
EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
- return ::EvaluateAsRValue(Info, this, Result.Val);
+ Info.InConstantContext = InConstantContext;
+ return ::EvaluateAsRValue(this, Result, Ctx, Info);
}
bool Expr::EvaluateAsBooleanCondition(bool &Result,
@@ -10715,24 +10948,10 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result,
HandleConversionToBool(Scratch.Val, Result);
}
-static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result,
- Expr::SideEffectsKind SEK) {
- return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) ||
- (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior);
-}
-
-bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx,
+bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects) const {
- if (!getType()->isIntegralOrEnumerationType())
- return false;
-
- EvalResult ExprResult;
- if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() ||
- hasUnacceptableSideEffect(ExprResult, AllowSideEffects))
- return false;
-
- Result = ExprResult.Val.getInt();
- return true;
+ EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
+ return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info);
}
bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx,
@@ -10790,6 +11009,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
? EvalInfo::EM_ConstantExpression
: EvalInfo::EM_ConstantFold);
InitInfo.setEvaluatingDecl(VD, Value);
+ InitInfo.InConstantContext = true;
LValue LVal;
LVal.set(VD);
@@ -10819,28 +11039,46 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
/// constant folded, but discard the result.
bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const {
EvalResult Result;
- return EvaluateAsRValue(Result, Ctx) &&
+ return EvaluateAsRValue(Result, Ctx, /* in constant context */ true) &&
!hasUnacceptableSideEffect(Result, SEK);
}
APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
- EvalResult EvalResult;
- EvalResult.Diag = Diag;
- bool Result = EvaluateAsRValue(EvalResult, Ctx);
+ EvalResult EVResult;
+ EVResult.Diag = Diag;
+ EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
+ Info.InConstantContext = true;
+
+ bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info);
(void)Result;
assert(Result && "Could not evaluate expression");
- assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer");
+ assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
- return EvalResult.Val.getInt();
+ return EVResult.Val.getInt();
+}
+
+APSInt Expr::EvaluateKnownConstIntCheckOverflow(
+ const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
+ EvalResult EVResult;
+ EVResult.Diag = Diag;
+ EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow);
+ Info.InConstantContext = true;
+
+ bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val);
+ (void)Result;
+ assert(Result && "Could not evaluate expression");
+ assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
+
+ return EVResult.Val.getInt();
}
void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
bool IsConst;
- EvalResult EvalResult;
- if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) {
- EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow);
- (void)::EvaluateAsRValue(Info, this, EvalResult.Val);
+ EvalResult EVResult;
+ if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) {
+ EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow);
+ (void)::EvaluateAsRValue(Info, this, EVResult.Val);
}
}
@@ -10893,9 +11131,13 @@ static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; }
static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) {
Expr::EvalResult EVResult;
- if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects ||
+ Expr::EvalStatus Status;
+ EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
+
+ Info.InConstantContext = true;
+ if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects ||
!EVResult.Val.isInt())
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
return NoDiag();
}
@@ -10903,7 +11145,7 @@ static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) {
static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
assert(!E->isValueDependent() && "Should not see value dependent exprs!");
if (!E->getType()->isIntegralOrEnumerationType())
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
switch (E->getStmtClass()) {
#define ABSTRACT_STMT(Node)
@@ -10987,7 +11229,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CoawaitExprClass:
case Expr::DependentCoawaitExprClass:
case Expr::CoyieldExprClass:
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
case Expr::InitListExprClass: {
// C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the
@@ -10997,7 +11239,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
if (E->isRValue())
if (cast<InitListExpr>(E)->getNumInits() == 1)
return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx);
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
}
case Expr::SizeOfPackExprClass:
@@ -11009,6 +11251,9 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
return
CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx);
+ case Expr::ConstantExprClass:
+ return CheckICE(cast<ConstantExpr>(E)->getSubExpr(), Ctx);
+
case Expr::ParenExprClass:
return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
case Expr::GenericSelectionExprClass:
@@ -11032,7 +11277,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
const CallExpr *CE = cast<CallExpr>(E);
if (CE->getBuiltinCallee())
return CheckEvalInICE(E, Ctx);
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
}
case Expr::DeclRefExprClass: {
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
@@ -11062,7 +11307,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
}
}
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
}
case Expr::UnaryOperatorClass: {
const UnaryOperator *Exp = cast<UnaryOperator>(E);
@@ -11077,7 +11322,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
// C99 6.6/3 allows increment and decrement within unevaluated
// subexpressions of constant expressions, but they can never be ICEs
// because an ICE cannot contain an lvalue operand.
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
case UO_Extension:
case UO_LNot:
case UO_Plus:
@@ -11087,9 +11332,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case UO_Imag:
return CheckICE(Exp->getSubExpr(), Ctx);
}
-
- // OffsetOf falls through here.
- LLVM_FALLTHROUGH;
+ llvm_unreachable("invalid unary operator class");
}
case Expr::OffsetOfExprClass: {
// Note that per C99, offsetof must be an ICE. And AFAIK, using
@@ -11104,7 +11347,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E);
if ((Exp->getKind() == UETT_SizeOf) &&
Exp->getTypeOfArgument()->isVariableArrayType())
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
return NoDiag();
}
case Expr::BinaryOperatorClass: {
@@ -11126,7 +11369,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
// C99 6.6/3 allows assignments within unevaluated subexpressions of
// constant expressions, but they can never be ICEs because an ICE cannot
// contain an lvalue operand.
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
case BO_Mul:
case BO_Div:
@@ -11155,11 +11398,11 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) {
llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx);
if (REval == 0)
- return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart());
+ return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
if (REval.isSigned() && REval.isAllOnesValue()) {
llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx);
if (LEval.isMinSignedValue())
- return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart());
+ return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
}
}
}
@@ -11168,10 +11411,10 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
// C99 6.6p3 introduces a strange edge case: comma can be in an ICE
// if it isn't evaluated.
if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE)
- return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart());
+ return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc());
} else {
// In both C89 and C++, commas in ICEs are illegal.
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
}
}
return Worst(LHSResult, RHSResult);
@@ -11193,7 +11436,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
return Worst(LHSResult, RHSResult);
}
}
- LLVM_FALLTHROUGH;
+ llvm_unreachable("invalid binary operator kind");
}
case Expr::ImplicitCastExprClass:
case Expr::CStyleCastExprClass:
@@ -11216,7 +11459,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
if (FL->getValue().convertToInteger(IgnoredVal,
llvm::APFloat::rmTowardZero,
&Ignored) & APFloat::opInvalidOp)
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
return NoDiag();
}
}
@@ -11229,7 +11472,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case CK_IntegralCast:
return CheckICE(SubExpr, Ctx);
default:
- return ICEDiag(IK_NotICE, E->getLocStart());
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
}
}
case Expr::BinaryConditionalOperatorClass: {
@@ -11330,12 +11573,20 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx,
if (!isIntegerConstantExpr(Ctx, Loc))
return false;
+
// The only possible side-effects here are due to UB discovered in the
// evaluation (for instance, INT_MAX + 1). In such a case, we are still
// required to treat the expression as an ICE, so we produce the folded
// value.
- if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects))
+ EvalResult ExprResult;
+ Expr::EvalStatus Status;
+ EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects);
+ Info.InConstantContext = true;
+
+ if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info))
llvm_unreachable("ICE cannot be evaluated!");
+
+ Value = ExprResult.Val.getInt();
return true;
}
@@ -11421,6 +11672,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
EvalInfo Info(FD->getASTContext(), Status,
EvalInfo::EM_PotentialConstantExpression);
+ Info.InConstantContext = true;
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr;
diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp
index ae28c588ca31..12e6bfc041a4 100644
--- a/lib/AST/ExternalASTMerger.cpp
+++ b/lib/AST/ExternalASTMerger.cpp
@@ -144,14 +144,14 @@ public:
}
if (auto *ToTag = dyn_cast<TagDecl>(To)) {
ToTag->setHasExternalLexicalStorage();
- ToTag->setMustBuildLookupTable();
+ ToTag->getPrimaryContext()->setMustBuildLookupTable();
assert(Parent.CanComplete(ToTag));
} else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
ToNamespace->setHasExternalVisibleStorage();
assert(Parent.CanComplete(ToNamespace));
} else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
ToContainer->setHasExternalLexicalStorage();
- ToContainer->setMustBuildLookupTable();
+ ToContainer->getPrimaryContext()->setMustBuildLookupTable();
assert(Parent.CanComplete(ToContainer));
}
return To;
@@ -230,7 +230,8 @@ void ExternalASTMerger::CompleteType(TagDecl *Tag) {
if (!SourceTag->getDefinition())
return false;
Forward.MapImported(SourceTag, Tag);
- Forward.ImportDefinition(SourceTag);
+ if (llvm::Error Err = Forward.ImportDefinition_New(SourceTag))
+ llvm::consumeError(std::move(Err));
Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
return true;
});
@@ -249,7 +250,8 @@ void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
if (!SourceInterface->getDefinition())
return false;
Forward.MapImported(SourceInterface, Interface);
- Forward.ImportDefinition(SourceInterface);
+ if (llvm::Error Err = Forward.ImportDefinition_New(SourceInterface))
+ llvm::consumeError(std::move(Err));
return true;
});
}
diff --git a/lib/Analysis/FormatString.cpp b/lib/AST/FormatString.cpp
index f37e4affae3f..04bd48f14a2a 100644
--- a/lib/Analysis/FormatString.cpp
+++ b/lib/AST/FormatString.cpp
@@ -179,6 +179,36 @@ clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
}
bool
+clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H,
+ FormatSpecifier &FS,
+ const char *&I,
+ const char *E,
+ const LangOptions &LO) {
+ if (!LO.OpenCL)
+ return false;
+
+ const char *Start = I;
+ if (*I == 'v') {
+ ++I;
+
+ if (I == E) {
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ OptionalAmount NumElts = ParseAmount(I, E);
+ if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ FS.setVectorNumElts(NumElts);
+ }
+
+ return false;
+}
+
+bool
clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
const char *&I,
const char *E,
@@ -406,12 +436,14 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
}
case WIntTy: {
+ QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
- QualType PromoArg =
- argTy->isPromotableIntegerType()
- ? C.getPromotedIntegerType(argTy) : argTy;
+ if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
+ return Match;
- QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
+ QualType PromoArg = argTy->isPromotableIntegerType()
+ ? C.getPromotedIntegerType(argTy)
+ : argTy;
PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
// If the promoted argument is the corresponding signed type of the
@@ -455,6 +487,14 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
llvm_unreachable("Invalid ArgType Kind!");
}
+ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
+ if (K != SpecificTy) // Won't be a valid vector element type.
+ return ArgType::Invalid();
+
+ QualType Vec = C.getExtVectorType(T, NumElts);
+ return ArgType(Vec, Name);
+}
+
QualType ArgType::getRepresentativeType(ASTContext &C) const {
QualType Res;
switch (K) {
@@ -687,7 +727,7 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
break;
}
}
- // Fall through.
+ LLVM_FALLTHROUGH;
case LengthModifier::AsChar:
case LengthModifier::AsLongLong:
case LengthModifier::AsQuad:
@@ -872,7 +912,7 @@ bool FormatSpecifier::hasStandardConversionSpecifier(
return true;
case ConversionSpecifier::CArg:
case ConversionSpecifier::SArg:
- return LangOpt.ObjC1 || LangOpt.ObjC2;
+ return LangOpt.ObjC;
case ConversionSpecifier::InvalidSpecifier:
case ConversionSpecifier::FreeBSDbArg:
case ConversionSpecifier::FreeBSDDArg:
diff --git a/lib/Analysis/FormatStringParsing.h b/lib/AST/FormatStringParsing.h
index a63140b366cd..9da829adcb49 100644
--- a/lib/Analysis/FormatStringParsing.h
+++ b/lib/AST/FormatStringParsing.h
@@ -3,7 +3,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
-#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/AST/FormatString.h"
namespace clang {
@@ -41,6 +41,10 @@ bool ParseArgPosition(FormatStringHandler &H,
FormatSpecifier &CS, const char *Start,
const char *&Beg, const char *E);
+bool ParseVectorModifier(FormatStringHandler &H,
+ FormatSpecifier &FS, const char *&Beg, const char *E,
+ const LangOptions &LO);
+
/// Returns true if a LengthModifier was parsed and installed in the
/// FormatSpecifier& argument, and false otherwise.
bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 2dc04f2f3d86..98c843db31d6 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -33,12 +33,6 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#define MANGLE_CHECKER 0
-
-#if MANGLE_CHECKER
-#include <cxxabi.h>
-#endif
-
using namespace clang;
namespace {
@@ -323,7 +317,7 @@ class CXXNameMangler {
AdditionalAbiTags->end());
}
- llvm::sort(TagList.begin(), TagList.end());
+ llvm::sort(TagList);
TagList.erase(std::unique(TagList.begin(), TagList.end()), TagList.end());
writeSortedUniqueAbiTags(Out, TagList);
@@ -339,7 +333,7 @@ class CXXNameMangler {
}
const AbiTagList &getSortedUniqueUsedAbiTags() {
- llvm::sort(UsedAbiTags.begin(), UsedAbiTags.end());
+ llvm::sort(UsedAbiTags);
UsedAbiTags.erase(std::unique(UsedAbiTags.begin(), UsedAbiTags.end()),
UsedAbiTags.end());
return UsedAbiTags;
@@ -415,17 +409,6 @@ public:
SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth),
AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {}
-#if MANGLE_CHECKER
- ~CXXNameMangler() {
- if (Out.str()[0] == '\01')
- return;
-
- int status = 0;
- char *result = abi::__cxa_demangle(Out.str().str().c_str(), 0, 0, &status);
- assert(status == 0 && "Could not demangle mangled name!");
- free(result);
- }
-#endif
raw_ostream &getStream() { return Out; }
void disableDerivedAbiTags() { DisableDerivedAbiTags = true; }
@@ -721,10 +704,8 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) {
if (FD->hasAttr<EnableIfAttr>()) {
FunctionTypeDepthState Saved = FunctionTypeDepth.push();
Out << "Ua9enable_ifI";
- // FIXME: specific_attr_iterator iterates in reverse order. Fix that and use
- // it here.
- for (AttrVec::const_reverse_iterator I = FD->getAttrs().rbegin(),
- E = FD->getAttrs().rend();
+ for (AttrVec::const_iterator I = FD->getAttrs().begin(),
+ E = FD->getAttrs().end();
I != E; ++I) {
EnableIfAttr *EIA = dyn_cast<EnableIfAttr>(*I);
if (!EIA)
@@ -1522,8 +1503,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
Out << 'N';
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
- Qualifiers MethodQuals =
- Qualifiers::fromCVRUMask(Method->getTypeQualifiers());
+ Qualifiers MethodQuals = Method->getTypeQualifiers();
// We do not consider restrict a distinguishing attribute for overloading
// purposes so we must not mangle it.
MethodQuals.removeRestrict();
@@ -2654,6 +2634,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
case BuiltinType::OCLReserveID:
Out << "13ocl_reserveid";
break;
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id: \
+ type_name = "ocl_" #ExtType; \
+ Out << type_name.size() << type_name; \
+ break;
+#include "clang/Basic/OpenCLExtensionTypes.def"
}
}
@@ -2662,16 +2648,12 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
case CC_C:
return "";
- case CC_X86StdCall:
- case CC_X86FastCall:
- case CC_X86ThisCall:
case CC_X86VectorCall:
case CC_X86Pascal:
- case CC_Win64:
- case CC_X86_64SysV:
case CC_X86RegCall:
case CC_AAPCS:
case CC_AAPCS_VFP:
+ case CC_AArch64VectorCall:
case CC_IntelOclBicc:
case CC_SpirFunction:
case CC_OpenCLKernel:
@@ -2680,6 +2662,22 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
// FIXME: we should be mangling all of the above.
return "";
+ case CC_X86ThisCall:
+ // FIXME: To match mingw GCC, thiscall should only be mangled in when it is
+ // used explicitly. At this point, we don't have that much information in
+ // the AST, since clang tends to bake the convention into the canonical
+ // function type. thiscall only rarely used explicitly, so don't mangle it
+ // for now.
+ return "";
+
+ case CC_X86StdCall:
+ return "stdcall";
+ case CC_X86FastCall:
+ return "fastcall";
+ case CC_X86_64SysV:
+ return "sysv_abi";
+ case CC_Win64:
+ return "ms_abi";
case CC_Swift:
return "swiftcall";
}
@@ -2737,7 +2735,7 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
// e.g. "const" in "int (A::*)() const".
- mangleQualifiers(Qualifiers::fromCVRUMask(T->getTypeQuals()));
+ mangleQualifiers(T->getTypeQuals());
// Mangle instantiation-dependent exception-specification, if present,
// per cxx-abi-dev proposal on 2016-10-11.
@@ -3526,6 +3524,10 @@ recurse:
case Expr::CXXInheritedCtorInitExprClass:
llvm_unreachable("unexpected statement kind");
+ case Expr::ConstantExprClass:
+ E = cast<ConstantExpr>(E)->getSubExpr();
+ goto recurse;
+
// FIXME: invent manglings for all these.
case Expr::BlockExprClass:
case Expr::ChooseExprClass:
@@ -3883,6 +3885,7 @@ recurse:
case UETT_SizeOf:
Out << 's';
break;
+ case UETT_PreferredAlignOf:
case UETT_AlignOf:
Out << 'a';
break;
diff --git a/lib/AST/Linkage.h b/lib/AST/Linkage.h
index e6489c7ef2b3..8ad748bcc4a2 100644
--- a/lib/AST/Linkage.h
+++ b/lib/AST/Linkage.h
@@ -20,6 +20,7 @@
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
namespace clang {
/// Kinds of LV computation. The linkage side of the computation is
@@ -36,6 +37,8 @@ struct LVComputationKind {
/// in computing linkage.
unsigned IgnoreAllVisibility : 1;
+ enum { NumLVComputationKindBits = 3 };
+
explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
: ExplicitKind(EK), IgnoreExplicitVisibility(false),
IgnoreAllVisibility(false) {}
@@ -78,12 +81,14 @@ class LinkageComputer {
// using C = Foo<B, B>;
// using D = Foo<C, C>;
//
- // The unsigned represents an LVComputationKind.
- using QueryType = std::pair<const NamedDecl *, unsigned>;
+ // The integer represents an LVComputationKind.
+ using QueryType =
+ llvm::PointerIntPair<const NamedDecl *,
+ LVComputationKind::NumLVComputationKindBits>;
llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
- return std::make_pair(ND, Kind.toBits());
+ return QueryType(ND, Kind.toBits());
}
llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND,
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index b0e5146e8194..bb29bffc1b8f 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -25,12 +25,6 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#define MANGLE_CHECKER 0
-
-#if MANGLE_CHECKER
-#include <cxxabi.h>
-#endif
-
using namespace clang;
// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 5db51b5cb384..92e9679e49aa 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -29,6 +29,7 @@
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/xxhash.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
@@ -127,10 +128,10 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
+ SmallString<16> AnonymousNamespaceHash;
public:
- MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
- : MicrosoftMangleContext(Context, Diags) {}
+ MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags);
bool shouldMangleCXXName(const NamedDecl *D) override;
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
@@ -238,6 +239,12 @@ public:
return Result.first->second;
}
+ /// Return a character sequence that is (somewhat) unique to the TU suitable
+ /// for mangling anonymous namespaces.
+ StringRef getAnonymousNamespaceHash() const {
+ return AnonymousNamespaceHash;
+ }
+
private:
void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out);
};
@@ -302,13 +309,15 @@ public:
const MethodVFTableLocation &ML);
void mangleNumber(int64_t Number);
void mangleTagTypeKind(TagTypeKind TK);
- void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName,
+ void mangleArtificialTagType(TagTypeKind TK, StringRef UnqualifiedName,
ArrayRef<StringRef> NestedNames = None);
+ void mangleAddressSpaceType(QualType T, Qualifiers Quals, SourceRange Range);
void mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM = QMM_Mangle);
void mangleFunctionType(const FunctionType *T,
const FunctionDecl *D = nullptr,
- bool ForceThisQuals = false);
+ bool ForceThisQuals = false,
+ bool MangleExceptionSpec = true);
void mangleNestedName(const NamedDecl *ND);
private:
@@ -368,9 +377,39 @@ private:
void mangleObjCProtocol(const ObjCProtocolDecl *PD);
void mangleObjCLifetime(const QualType T, Qualifiers Quals,
SourceRange Range);
+ void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals,
+ SourceRange Range);
};
}
+MicrosoftMangleContextImpl::MicrosoftMangleContextImpl(ASTContext &Context,
+ DiagnosticsEngine &Diags)
+ : MicrosoftMangleContext(Context, Diags) {
+ // To mangle anonymous namespaces, hash the path to the main source file. The
+ // path should be whatever (probably relative) path was passed on the command
+ // line. The goal is for the compiler to produce the same output regardless of
+ // working directory, so use the uncanonicalized relative path.
+ //
+ // It's important to make the mangled names unique because, when CodeView
+ // debug info is in use, the debugger uses mangled type names to distinguish
+ // between otherwise identically named types in anonymous namespaces.
+ //
+ // These symbols are always internal, so there is no need for the hash to
+ // match what MSVC produces. For the same reason, clang is free to change the
+ // hash at any time without breaking compatibility with old versions of clang.
+ // The generated names are intended to look similar to what MSVC generates,
+ // which are something like "?A0x01234567@".
+ SourceManager &SM = Context.getSourceManager();
+ if (const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID())) {
+ // Truncate the hash so we get 8 characters of hexadecimal.
+ uint32_t TruncatedHash = uint32_t(xxHash64(FE->getName()));
+ AnonymousNamespaceHash = llvm::utohexstr(TruncatedHash);
+ } else {
+ // If we don't have a path to the main file, we'll just use 0.
+ AnonymousNamespaceHash = "0";
+ }
+}
+
bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
LanguageLinkage L = FD->getLanguageLinkage();
@@ -475,7 +514,7 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD,
mangleFunctionClass(FD);
- mangleFunctionType(FT, FD);
+ mangleFunctionType(FT, FD, false, false);
} else {
Out << '9';
}
@@ -785,7 +824,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (NS->isAnonymousNamespace()) {
- Out << "?A@";
+ Out << "?A0x" << Context.getAnonymousNamespaceHash() << '@';
break;
}
}
@@ -905,8 +944,14 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- llvm_unreachable("Can't mangle Objective-C selector names here!");
+ case DeclarationName::ObjCMultiArgSelector: {
+ // This is reachable only when constructing an outlined SEH finally
+ // block. Nothing depends on this mangling and it's used only with
+ // functinos with internal linkage.
+ llvm::SmallString<64> Name;
+ mangleSourceName(Name.str());
+ break;
+ }
case DeclarationName::CXXConstructorName:
if (isStructorDecl(ND)) {
@@ -1027,7 +1072,7 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
if (PointersAre64Bit)
Out << 'E';
Out << 'A';
- mangleArtificalTagType(TTK_Struct,
+ mangleArtificialTagType(TTK_Struct,
Discriminate("__block_literal", Discriminator,
ParameterDiscriminator));
Out << "@Z";
@@ -1322,7 +1367,7 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
// It's a global variable.
Out << '3';
// It's a struct called __s_GUID.
- mangleArtificalTagType(TTK_Struct, "__s_GUID");
+ mangleArtificialTagType(TTK_Struct, "__s_GUID");
// It's const.
Out << 'B';
return;
@@ -1343,9 +1388,16 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
assert(TPL->size() == TemplateArgs.size() &&
"size mismatch between args and parms!");
- unsigned Idx = 0;
- for (const TemplateArgument &TA : TemplateArgs.asArray())
- mangleTemplateArg(TD, TA, TPL->getParam(Idx++));
+ for (size_t i = 0; i < TemplateArgs.size(); ++i) {
+ const TemplateArgument &TA = TemplateArgs[i];
+
+ // Separate consecutive packs by $$Z.
+ if (i > 0 && TA.getKind() == TemplateArgument::Pack &&
+ TemplateArgs[i - 1].getKind() == TemplateArgument::Pack)
+ Out << "$$Z";
+
+ mangleTemplateArg(TD, TA, TPL->getParam(i));
+ }
}
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
@@ -1471,9 +1523,9 @@ void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) {
Stream << "?$";
Extra.mangleSourceName("Protocol");
- Extra.mangleArtificalTagType(TTK_Struct, PD->getName());
+ Extra.mangleArtificialTagType(TTK_Struct, PD->getName());
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
}
void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type,
@@ -1502,7 +1554,24 @@ void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type,
Extra.manglePointerExtQualifiers(Quals, Type);
Extra.mangleType(Type, Range);
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
+}
+
+void MicrosoftCXXNameMangler::mangleObjCKindOfType(const ObjCObjectType *T,
+ Qualifiers Quals,
+ SourceRange Range) {
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+
+ Stream << "?$";
+ Extra.mangleSourceName("KindOf");
+ Extra.mangleType(QualType(T, 0)
+ .stripObjCKindOfType(getASTContext())
+ ->getAs<ObjCObjectType>(),
+ Quals, Range);
+
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
}
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
@@ -1698,7 +1767,7 @@ void MicrosoftCXXNameMangler::manglePassObjectSizeArg(
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
if (Found == TypeBackReferences.end()) {
- mangleArtificalTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type),
+ mangleArtificialTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type),
{"__clang"});
if (TypeBackReferences.size() < 10) {
@@ -1710,12 +1779,77 @@ void MicrosoftCXXNameMangler::manglePassObjectSizeArg(
}
}
+void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T,
+ Qualifiers Quals,
+ SourceRange Range) {
+ // Address space is mangled as an unqualified templated type in the __clang
+ // namespace. The demangled version of this is:
+ // In the case of a language specific address space:
+ // __clang::struct _AS[language_addr_space]<Type>
+ // where:
+ // <language_addr_space> ::= <OpenCL-addrspace> | <CUDA-addrspace>
+ // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" |
+ // "private"| "generic" ]
+ // <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
+ // Note that the above were chosen to match the Itanium mangling for this.
+ //
+ // In the case of a non-language specific address space:
+ // __clang::struct _AS<TargetAS, Type>
+ assert(Quals.hasAddressSpace() && "Not valid without address space");
+ llvm::SmallString<32> ASMangling;
+ llvm::raw_svector_ostream Stream(ASMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Stream << "?$";
+
+ LangAS AS = Quals.getAddressSpace();
+ if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
+ unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
+ Extra.mangleSourceName("_AS");
+ Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(TargetAS),
+ /*IsBoolean*/ false);
+ } else {
+ switch (AS) {
+ default:
+ llvm_unreachable("Not a language specific address space");
+ case LangAS::opencl_global:
+ Extra.mangleSourceName("_ASCLglobal");
+ break;
+ case LangAS::opencl_local:
+ Extra.mangleSourceName("_ASCLlocal");
+ break;
+ case LangAS::opencl_constant:
+ Extra.mangleSourceName("_ASCLconstant");
+ break;
+ case LangAS::opencl_private:
+ Extra.mangleSourceName("_ASCLprivate");
+ break;
+ case LangAS::opencl_generic:
+ Extra.mangleSourceName("_ASCLgeneric");
+ break;
+ case LangAS::cuda_device:
+ Extra.mangleSourceName("_ASCUdevice");
+ break;
+ case LangAS::cuda_constant:
+ Extra.mangleSourceName("_ASCUconstant");
+ break;
+ case LangAS::cuda_shared:
+ Extra.mangleSourceName("_ASCUshared");
+ break;
+ }
+ }
+
+ Extra.mangleType(T, Range, QMM_Escape);
+ mangleQualifiers(Qualifiers(), false);
+ mangleArtificialTagType(TTK_Struct, ASMangling, {"__clang"});
+}
+
void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM) {
// Don't use the canonical types. MSVC includes things like 'const' on
// pointer arguments to function pointers that canonicalization strips away.
T = T.getDesugaredType(getASTContext());
Qualifiers Quals = T.getLocalQualifiers();
+
if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
// If there were any Quals, getAsArrayType() pushed them onto the array
// element type.
@@ -1884,13 +2018,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
llvm_unreachable("placeholder types shouldn't get to name mangling");
case BuiltinType::ObjCId:
- mangleArtificalTagType(TTK_Struct, "objc_object");
+ mangleArtificialTagType(TTK_Struct, "objc_object");
break;
case BuiltinType::ObjCClass:
- mangleArtificalTagType(TTK_Struct, "objc_class");
+ mangleArtificialTagType(TTK_Struct, "objc_class");
break;
case BuiltinType::ObjCSel:
- mangleArtificalTagType(TTK_Struct, "objc_selector");
+ mangleArtificialTagType(TTK_Struct, "objc_selector");
break;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@@ -1900,35 +2034,40 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_sampler");
+ mangleArtificialTagType(TTK_Struct, "ocl_sampler");
break;
case BuiltinType::OCLEvent:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_event");
+ mangleArtificialTagType(TTK_Struct, "ocl_event");
break;
case BuiltinType::OCLClkEvent:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_clkevent");
+ mangleArtificialTagType(TTK_Struct, "ocl_clkevent");
break;
case BuiltinType::OCLQueue:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_queue");
+ mangleArtificialTagType(TTK_Struct, "ocl_queue");
break;
case BuiltinType::OCLReserveID:
Out << "PA";
- mangleArtificalTagType(TTK_Struct, "ocl_reserveid");
+ mangleArtificialTagType(TTK_Struct, "ocl_reserveid");
+ break;
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id: \
+ mangleArtificialTagType(TTK_Struct, "ocl_" #ExtType); \
break;
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::NullPtr:
Out << "$$T";
break;
case BuiltinType::Float16:
- mangleArtificalTagType(TTK_Struct, "_Float16", {"__clang"});
+ mangleArtificialTagType(TTK_Struct, "_Float16", {"__clang"});
break;
case BuiltinType::Half:
- mangleArtificalTagType(TTK_Struct, "_Half", {"__clang"});
+ mangleArtificialTagType(TTK_Struct, "_Half", {"__clang"});
break;
case BuiltinType::ShortAccum:
@@ -1989,7 +2128,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
const FunctionDecl *D,
- bool ForceThisQuals) {
+ bool ForceThisQuals,
+ bool MangleExceptionSpec) {
// <function-type> ::= <this-cvr-qualifiers> <calling-convention>
// <return-type> <argument-list> <throw-spec>
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T);
@@ -2021,7 +2161,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
if (HasThisQuals) {
- Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals());
+ Qualifiers Quals = Proto->getTypeQuals();
manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType());
mangleRefQualifier(Proto->getRefQualifier());
mangleQualifiers(Quals, /*IsMember=*/false);
@@ -2122,7 +2262,12 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
Out << '@';
}
- mangleThrowSpecification(Proto);
+ if (MangleExceptionSpec && getASTContext().getLangOpts().CPlusPlus17 &&
+ getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2017_5))
+ mangleThrowSpecification(Proto);
+ else
+ Out << 'Z';
}
void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
@@ -2227,15 +2372,15 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
mangleCallingConvention(T->getCallConv());
}
+
void MicrosoftCXXNameMangler::mangleThrowSpecification(
const FunctionProtoType *FT) {
- // <throw-spec> ::= Z # throw(...) (default)
- // ::= @ # throw() or __declspec/__attribute__((nothrow))
- // ::= <type>+
- // NOTE: Since the Microsoft compiler ignores throw specifications, they are
- // all actually mangled as 'Z'. (They're ignored because their associated
- // functionality isn't implemented, and probably never will be.)
- Out << 'Z';
+ // <throw-spec> ::= Z # (default)
+ // ::= _E # noexcept
+ if (FT->canThrow())
+ Out << 'Z';
+ else
+ Out << "_E";
}
void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
@@ -2285,7 +2430,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
}
// If you add a call to this, consider updating isArtificialTagType() too.
-void MicrosoftCXXNameMangler::mangleArtificalTagType(
+void MicrosoftCXXNameMangler::mangleArtificialTagType(
TagTypeKind TK, StringRef UnqualifiedName,
ArrayRef<StringRef> NestedNames) {
// <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
@@ -2416,7 +2561,11 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
QualType PointeeType = T->getPointeeType();
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
- mangleType(PointeeType, Range);
+
+ if (PointeeType.getQualifiers().hasAddressSpace())
+ mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range);
+ else
+ mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
@@ -2471,10 +2620,10 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers,
Extra.mangleSourceName("_Complex");
Extra.mangleType(ElementType, Range, QMM_Escape);
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
-// Returns true for types that mangleArtificalTagType() gets called for with
+// Returns true for types that mangleArtificialTagType() gets called for with
// TTK_Union, TTK_Struct, TTK_Class and where compatibility with MSVC's
// mangling matters.
// (It doesn't matter for Objective-C types and the like that cl.exe doesn't
@@ -2487,7 +2636,7 @@ bool MicrosoftCXXNameMangler::isArtificialTagType(QualType T) const {
case Type::Vector: {
// For ABI compatibility only __m64, __m128(id), and __m256(id) matter,
- // but since mangleType(VectorType*) always calls mangleArtificalTagType()
+ // but since mangleType(VectorType*) always calls mangleArtificialTagType()
// just always return true (the other vector types are clang-only).
return true;
}
@@ -2502,18 +2651,20 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
// Pattern match exactly the typedefs in our intrinsic headers. Anything that
// doesn't match the Intel types uses a custom mangling below.
size_t OutSizeBefore = Out.tell();
- llvm::Triple::ArchType AT =
- getASTContext().getTargetInfo().getTriple().getArch();
- if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) {
- if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
- mangleArtificalTagType(TTK_Union, "__m64");
- } else if (Width >= 128) {
- if (ET->getKind() == BuiltinType::Float)
- mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width));
- else if (ET->getKind() == BuiltinType::LongLong)
- mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i');
- else if (ET->getKind() == BuiltinType::Double)
- mangleArtificalTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd');
+ if (!isa<ExtVectorType>(T)) {
+ llvm::Triple::ArchType AT =
+ getASTContext().getTargetInfo().getTriple().getArch();
+ if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) {
+ if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
+ mangleArtificialTagType(TTK_Union, "__m64");
+ } else if (Width >= 128) {
+ if (ET->getKind() == BuiltinType::Float)
+ mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width));
+ else if (ET->getKind() == BuiltinType::LongLong)
+ mangleArtificialTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i');
+ else if (ET->getKind() == BuiltinType::Double)
+ mangleArtificialTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd');
+ }
}
}
@@ -2532,7 +2683,7 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements()),
/*IsBoolean=*/false);
- mangleArtificalTagType(TTK_Union, TemplateMangling, {"__clang"});
+ mangleArtificialTagType(TTK_Union, TemplateMangling, {"__clang"});
}
}
@@ -2575,9 +2726,12 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
mangleName(T->getDecl());
}
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
- SourceRange Range) {
- if (T->qual_empty())
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
+ Qualifiers Quals, SourceRange Range) {
+ if (T->isKindOfType())
+ return mangleObjCKindOfType(T, Quals, Range);
+
+ if (T->qual_empty() && !T->isSpecialized())
return mangleType(T->getBaseType(), Range, QMM_Drop);
ArgBackRefMap OuterArgsContext;
@@ -2598,6 +2752,11 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
for (const auto &Q : T->quals())
mangleObjCProtocol(Q);
+
+ if (T->isSpecialized())
+ for (const auto &TA : T->getTypeArgs())
+ mangleType(TA, Range, QMM_Drop);
+
Out << '@';
Out << '@';
@@ -2728,7 +2887,7 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
Extra.mangleSourceName("_Atomic");
Extra.mangleType(ValueType, Range, QMM_Escape);
- mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
+ mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
@@ -2780,14 +2939,14 @@ void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
// <vtordisp-shift> ::= <offset-to-vtordisp>
// <vtordispex-shift> ::= <offset-to-vbptr> <vbase-offset-offset>
// <offset-to-vtordisp>
-static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
+static void mangleThunkThisAdjustment(AccessSpecifier AS,
const ThisAdjustment &Adjustment,
MicrosoftCXXNameMangler &Mangler,
raw_ostream &Out) {
if (!Adjustment.Virtual.isEmpty()) {
Out << '$';
char AccessSpec;
- switch (MD->getAccess()) {
+ switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
@@ -2815,7 +2974,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual));
}
} else if (Adjustment.NonVirtual != 0) {
- switch (MD->getAccess()) {
+ switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
@@ -2829,7 +2988,7 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD,
}
Mangler.mangleNumber(-static_cast<uint32_t>(Adjustment.NonVirtual));
} else {
- switch (MD->getAccess()) {
+ switch (AS) {
case AS_none:
llvm_unreachable("Unsupported access specifier");
case AS_private:
@@ -2860,7 +3019,13 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << '?';
Mangler.mangleName(MD);
- mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO);
+
+ // Usually the thunk uses the access specifier of the new method, but if this
+ // is a covariant return thunk, then MSVC always uses the public access
+ // specifier, and we do the same.
+ AccessSpecifier AS = Thunk.Return.isEmpty() ? MD->getAccess() : AS_public;
+ mangleThunkThisAdjustment(AS, Thunk.This, Mangler, MHO);
+
if (!Thunk.Return.isEmpty())
assert(Thunk.Method != nullptr &&
"Thunk info should hold the overridee decl");
@@ -2881,7 +3046,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
Mangler.getStream() << "??_E";
Mangler.mangleName(DD->getParent());
- mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO);
+ mangleThunkThisAdjustment(DD->getAccess(), Adjustment, Mangler, MHO);
Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD);
}
@@ -3175,10 +3340,13 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D,
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
Mangler.getStream() << "??__" << CharCode;
- Mangler.mangleName(D);
if (D->isStaticDataMember()) {
+ Mangler.getStream() << '?';
+ Mangler.mangleName(D);
Mangler.mangleVariableEncoding(D);
- Mangler.getStream() << '@';
+ Mangler.getStream() << "@@";
+ } else {
+ Mangler.mangleName(D);
}
// This is the function class mangling. These stubs are global, non-variadic,
// cdecl functions that return void and take no args.
diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp
index 94ad87b6e337..5b8300893e2d 100644
--- a/lib/AST/NSAPI.cpp
+++ b/lib/AST/NSAPI.cpp
@@ -475,6 +475,9 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
@@ -509,7 +512,7 @@ bool NSAPI::isObjCNSUIntegerType(QualType T) const {
}
StringRef NSAPI::GetNSIntegralKind(QualType T) const {
- if (!Ctx.getLangOpts().ObjC1 || T.isNull())
+ if (!Ctx.getLangOpts().ObjC || T.isNull())
return StringRef();
while (const TypedefType *TDT = T->getAs<TypedefType>()) {
@@ -561,7 +564,7 @@ bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
bool NSAPI::isObjCTypedef(QualType T,
StringRef name, IdentifierInfo *&II) const {
- if (!Ctx.getLangOpts().ObjC1)
+ if (!Ctx.getLangOpts().ObjC)
return false;
if (T.isNull())
return false;
@@ -580,7 +583,7 @@ bool NSAPI::isObjCTypedef(QualType T,
bool NSAPI::isObjCEnumerator(const Expr *E,
StringRef name, IdentifierInfo *&II) const {
- if (!Ctx.getLangOpts().ObjC1)
+ if (!Ctx.getLangOpts().ObjC)
return false;
if (!E)
return false;
@@ -607,3 +610,11 @@ Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
}
return Sel;
}
+
+Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
+ if (Sel.isNull()) {
+ IdentifierInfo *Ident = &Ctx.Idents.get(Id);
+ Sel = Ctx.Selectors.getSelector(0, &Ident);
+ }
+ return Sel;
+}
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index a514d57b6b6b..42f6a133d717 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -270,9 +271,8 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
/// Print this nested name specifier to the given output
/// stream.
-void
-NestedNameSpecifier::print(raw_ostream &OS,
- const PrintingPolicy &Policy) const {
+void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool ResolveTemplateArguments) const {
if (getPrefix())
getPrefix()->print(OS, Policy);
@@ -305,6 +305,15 @@ NestedNameSpecifier::print(raw_ostream &OS,
LLVM_FALLTHROUGH;
case TypeSpec: {
+ const auto *Record =
+ dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
+ if (ResolveTemplateArguments && Record) {
+ // Print the type trait with resolved template parameters.
+ Record->printName(OS);
+ printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
+ Policy);
+ break;
+ }
const Type *T = getAsType();
PrintingPolicy InnerPolicy(Policy);
@@ -339,13 +348,20 @@ NestedNameSpecifier::print(raw_ostream &OS,
OS << "::";
}
-void NestedNameSpecifier::dump(const LangOptions &LO) const {
- print(llvm::errs(), PrintingPolicy(LO));
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
+ dump(llvm::errs(), LO);
}
-LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const {
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
+
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
LangOptions LO;
- print(llvm::errs(), PrintingPolicy(LO));
+ dump(OS, LO);
+}
+
+LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
+ const LangOptions &LO) const {
+ print(OS, PrintingPolicy(LO));
}
unsigned
@@ -446,9 +462,9 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
}
TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
- assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec ||
- Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) &&
- "Nested-name-specifier location is not a type");
+ if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
+ Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
+ return TypeLoc();
// The "void*" that points at the TypeLoc data.
unsigned Offset = getDataLength(Qualifier->getPrefix());
@@ -547,6 +563,7 @@ operator=(const NestedNameSpecifierLocBuilder &Other) {
}
// Deep copy.
+ BufferSize = 0;
Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
BufferCapacity);
return *this;
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
index e710d3780337..a4c344ce0a9b 100644
--- a/lib/AST/ODRHash.cpp
+++ b/lib/AST/ODRHash.cpp
@@ -32,12 +32,24 @@ void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
ID.AddString(II->getName());
}
-void ODRHash::AddDeclarationName(DeclarationName Name) {
+void ODRHash::AddDeclarationName(DeclarationName Name, bool TreatAsDecl) {
+ if (TreatAsDecl)
+ // Matches the NamedDecl check in AddDecl
+ AddBoolean(true);
+
+ AddDeclarationNameImpl(Name);
+
+ if (TreatAsDecl)
+ // Matches the ClassTemplateSpecializationDecl check in AddDecl
+ AddBoolean(false);
+}
+
+void ODRHash::AddDeclarationNameImpl(DeclarationName Name) {
// Index all DeclarationName and use index numbers to refer to them.
auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
ID.AddInteger(Result.first->second);
if (!Result.second) {
- // If found in map, the the DeclarationName has previously been processed.
+ // If found in map, the DeclarationName has previously been processed.
return;
}
@@ -405,6 +417,7 @@ public:
void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
AddDecl(D->getTemplatedDecl());
+ ID.AddInteger(D->getTemplatedDecl()->getODRHash());
Inherited::VisitFunctionTemplateDecl(D);
}
@@ -552,11 +565,27 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
!Function->isDefaulted() && !Function->isDeleted() &&
!Function->isLateTemplateParsed();
AddBoolean(HasBody);
- if (HasBody) {
- auto *Body = Function->getBody();
- AddBoolean(Body);
- if (Body)
- AddStmt(Body);
+ if (!HasBody) {
+ return;
+ }
+
+ auto *Body = Function->getBody();
+ AddBoolean(Body);
+ if (Body)
+ AddStmt(Body);
+
+ // Filter out sub-Decls which will not be processed in order to get an
+ // accurate count of Decl's.
+ llvm::SmallVector<const Decl *, 16> Decls;
+ for (Decl *SubDecl : Function->decls()) {
+ if (isWhitelistedDecl(SubDecl, Function)) {
+ Decls.push_back(SubDecl);
+ }
+ }
+
+ ID.AddInteger(Decls.size());
+ for (auto SubDecl : Decls) {
+ AddSubDecl(SubDecl);
}
}
@@ -592,13 +621,24 @@ void ODRHash::AddDecl(const Decl *D) {
assert(D && "Expecting non-null pointer.");
D = D->getCanonicalDecl();
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- AddDeclarationName(ND->getDeclName());
+ const NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ AddBoolean(ND);
+ if (!ND) {
+ ID.AddInteger(D->getKind());
return;
}
- ID.AddInteger(D->getKind());
- // TODO: Handle non-NamedDecl here.
+ AddDeclarationName(ND->getDeclName());
+
+ const auto *Specialization =
+ dyn_cast<ClassTemplateSpecializationDecl>(D);
+ AddBoolean(Specialization);
+ if (Specialization) {
+ const TemplateArgumentList &List = Specialization->getTemplateArgs();
+ ID.AddInteger(List.size());
+ for (const TemplateArgument &TA : List.asArray())
+ AddTemplateArgument(TA);
+ }
}
namespace {
@@ -700,11 +740,67 @@ public:
VisitArrayType(T);
}
+ void VisitAttributedType(const AttributedType *T) {
+ ID.AddInteger(T->getAttrKind());
+ AddQualType(T->getModifiedType());
+ AddQualType(T->getEquivalentType());
+
+ VisitType(T);
+ }
+
+ void VisitBlockPointerType(const BlockPointerType *T) {
+ AddQualType(T->getPointeeType());
+ VisitType(T);
+ }
+
void VisitBuiltinType(const BuiltinType *T) {
ID.AddInteger(T->getKind());
VisitType(T);
}
+ void VisitComplexType(const ComplexType *T) {
+ AddQualType(T->getElementType());
+ VisitType(T);
+ }
+
+ void VisitDecltypeType(const DecltypeType *T) {
+ AddStmt(T->getUnderlyingExpr());
+ AddQualType(T->getUnderlyingType());
+ VisitType(T);
+ }
+
+ void VisitDependentDecltypeType(const DependentDecltypeType *T) {
+ VisitDecltypeType(T);
+ }
+
+ void VisitDeducedType(const DeducedType *T) {
+ AddQualType(T->getDeducedType());
+ VisitType(T);
+ }
+
+ void VisitAutoType(const AutoType *T) {
+ ID.AddInteger((unsigned)T->getKeyword());
+ VisitDeducedType(T);
+ }
+
+ void VisitDeducedTemplateSpecializationType(
+ const DeducedTemplateSpecializationType *T) {
+ Hash.AddTemplateName(T->getTemplateName());
+ VisitDeducedType(T);
+ }
+
+ void VisitDependentAddressSpaceType(const DependentAddressSpaceType *T) {
+ AddQualType(T->getPointeeType());
+ AddStmt(T->getAddrSpaceExpr());
+ VisitType(T);
+ }
+
+ void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {
+ AddQualType(T->getElementType());
+ AddStmt(T->getSizeExpr());
+ VisitType(T);
+ }
+
void VisitFunctionType(const FunctionType *T) {
AddQualType(T->getReturnType());
T->getExtInfo().Profile(ID);
@@ -726,6 +822,74 @@ public:
VisitFunctionType(T);
}
+ void VisitInjectedClassNameType(const InjectedClassNameType *T) {
+ AddDecl(T->getDecl());
+ VisitType(T);
+ }
+
+ void VisitMemberPointerType(const MemberPointerType *T) {
+ AddQualType(T->getPointeeType());
+ AddType(T->getClass());
+ VisitType(T);
+ }
+
+ void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ AddQualType(T->getPointeeType());
+ VisitType(T);
+ }
+
+ void VisitObjCObjectType(const ObjCObjectType *T) {
+ AddDecl(T->getInterface());
+
+ auto TypeArgs = T->getTypeArgsAsWritten();
+ ID.AddInteger(TypeArgs.size());
+ for (auto Arg : TypeArgs) {
+ AddQualType(Arg);
+ }
+
+ auto Protocols = T->getProtocols();
+ ID.AddInteger(Protocols.size());
+ for (auto Protocol : Protocols) {
+ AddDecl(Protocol);
+ }
+
+ Hash.AddBoolean(T->isKindOfType());
+
+ VisitType(T);
+ }
+
+ void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+ // This type is handled by the parent type ObjCObjectType.
+ VisitObjCObjectType(T);
+ }
+
+ void VisitObjCTypeParamType(const ObjCTypeParamType *T) {
+ AddDecl(T->getDecl());
+ auto Protocols = T->getProtocols();
+ ID.AddInteger(Protocols.size());
+ for (auto Protocol : Protocols) {
+ AddDecl(Protocol);
+ }
+
+ VisitType(T);
+ }
+
+ void VisitPackExpansionType(const PackExpansionType *T) {
+ AddQualType(T->getPattern());
+ VisitType(T);
+ }
+
+ void VisitParenType(const ParenType *T) {
+ AddQualType(T->getInnerType());
+ VisitType(T);
+ }
+
+ void VisitPipeType(const PipeType *T) {
+ AddQualType(T->getElementType());
+ Hash.AddBoolean(T->isReadOnly());
+ VisitType(T);
+ }
+
void VisitPointerType(const PointerType *T) {
AddQualType(T->getPointeeType());
VisitType(T);
@@ -744,6 +908,43 @@ public:
VisitReferenceType(T);
}
+ void
+ VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
+ AddType(T->getReplacedParameter());
+ Hash.AddTemplateArgument(T->getArgumentPack());
+ VisitType(T);
+ }
+
+ void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+ AddType(T->getReplacedParameter());
+ AddQualType(T->getReplacementType());
+ VisitType(T);
+ }
+
+ void VisitTagType(const TagType *T) {
+ AddDecl(T->getDecl());
+ VisitType(T);
+ }
+
+ void VisitRecordType(const RecordType *T) { VisitTagType(T); }
+ void VisitEnumType(const EnumType *T) { VisitTagType(T); }
+
+ void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
+ ID.AddInteger(T->getNumArgs());
+ for (const auto &TA : T->template_arguments()) {
+ Hash.AddTemplateArgument(TA);
+ }
+ Hash.AddTemplateName(T->getTemplateName());
+ VisitType(T);
+ }
+
+ void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+ ID.AddInteger(T->getDepth());
+ ID.AddInteger(T->getIndex());
+ Hash.AddBoolean(T->isParameterPack());
+ AddDecl(T->getDecl());
+ }
+
void VisitTypedefType(const TypedefType *T) {
AddDecl(T->getDecl());
QualType UnderlyingType = T->getDecl()->getUnderlyingType();
@@ -766,13 +967,18 @@ public:
VisitType(T);
}
- void VisitTagType(const TagType *T) {
- AddDecl(T->getDecl());
+ void VisitTypeOfExprType(const TypeOfExprType *T) {
+ AddStmt(T->getUnderlyingExpr());
+ Hash.AddBoolean(T->isSugared());
+ if (T->isSugared())
+ AddQualType(T->desugar());
+
+ VisitType(T);
+ }
+ void VisitTypeOfType(const TypeOfType *T) {
+ AddQualType(T->getUnderlyingType());
VisitType(T);
}
-
- void VisitRecordType(const RecordType *T) { VisitTagType(T); }
- void VisitEnumType(const EnumType *T) { VisitTagType(T); }
void VisitTypeWithKeyword(const TypeWithKeyword *T) {
ID.AddInteger(T->getKeyword());
@@ -802,20 +1008,26 @@ public:
VisitTypeWithKeyword(T);
}
- void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
- ID.AddInteger(T->getNumArgs());
- for (const auto &TA : T->template_arguments()) {
- Hash.AddTemplateArgument(TA);
- }
- Hash.AddTemplateName(T->getTemplateName());
+ void VisitUnaryTransformType(const UnaryTransformType *T) {
+ AddQualType(T->getUnderlyingType());
+ AddQualType(T->getBaseType());
VisitType(T);
}
- void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
- ID.AddInteger(T->getDepth());
- ID.AddInteger(T->getIndex());
- Hash.AddBoolean(T->isParameterPack());
+ void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
AddDecl(T->getDecl());
+ VisitType(T);
+ }
+
+ void VisitVectorType(const VectorType *T) {
+ AddQualType(T->getElementType());
+ ID.AddInteger(T->getNumElements());
+ ID.AddInteger(T->getVectorKind());
+ VisitType(T);
+ }
+
+ void VisitExtVectorType(const ExtVectorType * T) {
+ VisitVectorType(T);
}
};
} // namespace
diff --git a/lib/Analysis/OSLog.cpp b/lib/AST/OSLog.cpp
index b2983932ea22..df2f808728cf 100644
--- a/lib/Analysis/OSLog.cpp
+++ b/lib/AST/OSLog.cpp
@@ -1,11 +1,11 @@
// TODO: header template
-#include "clang/Analysis/Analyses/OSLog.h"
+#include "clang/AST/OSLog.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/AST/FormatString.h"
#include "clang/Basic/Builtins.h"
#include "llvm/ADT/SmallBitVector.h"
@@ -26,6 +26,7 @@ private:
Optional<const Expr *> Precision;
Optional<const Expr *> FieldWidth;
unsigned char Flags = 0;
+ StringRef MaskType;
};
SmallVector<ArgData, 4> ArgsData;
ArrayRef<const Expr *> Args;
@@ -120,18 +121,26 @@ public:
ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
}
- if (FS.isPrivate()) {
+ if (FS.isSensitive())
+ ArgsData.back().Flags |= OSLogBufferItem::IsSensitive;
+ else if (FS.isPrivate())
ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
- }
- if (FS.isPublic()) {
+ else if (FS.isPublic())
ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
- }
+
+ ArgsData.back().MaskType = FS.getMaskType();
return true;
}
void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
Layout.Items.clear();
for (auto &Data : ArgsData) {
+ if (!Data.MaskType.empty()) {
+ CharUnits Size = CharUnits::fromQuantity(8);
+ Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr,
+ Size, 0, Data.MaskType);
+ }
+
if (Data.FieldWidth) {
CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp
index 50729264bfe1..76098f15bf36 100644
--- a/lib/AST/OpenMPClause.cpp
+++ b/lib/AST/OpenMPClause.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclOpenMP.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Casting.h"
@@ -106,6 +107,11 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
+ case OMPC_atomic_default_mem_order:
break;
}
@@ -175,12 +181,68 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
+ case OMPC_atomic_default_mem_order:
break;
}
return nullptr;
}
+OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num,
+ unsigned NumLoops,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
+ auto *Clause =
+ new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc);
+ for (unsigned I = 0; I < NumLoops; ++I) {
+ Clause->setLoopNumIterations(I, nullptr);
+ Clause->setLoopCounter(I, nullptr);
+ }
+ return Clause;
+}
+
+OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C,
+ unsigned NumLoops) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
+ auto *Clause = new (Mem) OMPOrderedClause(NumLoops);
+ for (unsigned I = 0; I < NumLoops; ++I) {
+ Clause->setLoopNumIterations(I, nullptr);
+ Clause->setLoopCounter(I, nullptr);
+ }
+ return Clause;
+}
+
+void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop,
+ Expr *NumIterations) {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ getTrailingObjects<Expr *>()[NumLoop] = NumIterations;
+}
+
+ArrayRef<Expr *> OMPOrderedClause::getLoopNumIterations() const {
+ return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumberOfLoops);
+}
+
+void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop] = Counter;
+}
+
+Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
+}
+
+const Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) const {
+ assert(NumLoop < NumberOfLoops && "out of loops number.");
+ return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
+}
+
void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
@@ -653,44 +715,58 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
return new (Mem) OMPFlushClause(N);
}
-OMPDependClause *OMPDependClause::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
- SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
- OMPDependClause *Clause =
- new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size());
+OMPDependClause *
+OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VL,
+ unsigned NumLoops) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops));
+ OMPDependClause *Clause = new (Mem)
+ OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
Clause->setVarRefs(VL);
Clause->setDependencyKind(DepKind);
Clause->setDependencyLoc(DepLoc);
Clause->setColonLoc(ColonLoc);
- Clause->setCounterValue(nullptr);
+ for (unsigned I = 0 ; I < NumLoops; ++I)
+ Clause->setLoopData(I, nullptr);
return Clause;
}
-OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1));
- return new (Mem) OMPDependClause(N);
+OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N,
+ unsigned NumLoops) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops));
+ return new (Mem) OMPDependClause(N, NumLoops);
}
-void OMPDependClause::setCounterValue(Expr *V) {
- assert(getDependencyKind() == OMPC_DEPEND_sink ||
- getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
- *getVarRefs().end() = V;
+void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
+ assert((getDependencyKind() == OMPC_DEPEND_sink ||
+ getDependencyKind() == OMPC_DEPEND_source) &&
+ NumLoop < NumLoops &&
+ "Expected sink or source depend + loop index must be less number of "
+ "loops.");
+ auto It = std::next(getVarRefs().end(), NumLoop);
+ *It = Cnt;
}
-const Expr *OMPDependClause::getCounterValue() const {
- auto *V = *getVarRefs().end();
- assert(getDependencyKind() == OMPC_DEPEND_sink ||
- getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
- return V;
+Expr *OMPDependClause::getLoopData(unsigned NumLoop) {
+ assert((getDependencyKind() == OMPC_DEPEND_sink ||
+ getDependencyKind() == OMPC_DEPEND_source) &&
+ NumLoop < NumLoops &&
+ "Expected sink or source depend + loop index must be less number of "
+ "loops.");
+ auto It = std::next(getVarRefs().end(), NumLoop);
+ return *It;
}
-Expr *OMPDependClause::getCounterValue() {
- auto *V = *getVarRefs().end();
- assert(getDependencyKind() == OMPC_DEPEND_sink ||
- getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
- return V;
+const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const {
+ assert((getDependencyKind() == OMPC_DEPEND_sink ||
+ getDependencyKind() == OMPC_DEPEND_source) &&
+ NumLoop < NumLoops &&
+ "Expected sink or source depend + loop index must be less number of "
+ "loops.");
+ auto It = std::next(getVarRefs().end(), NumLoop);
+ return *It;
}
unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
@@ -720,8 +796,10 @@ OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists,
- OpenMPMapClauseKind TypeModifier, OpenMPMapClauseKind Type,
- bool TypeIsImplicit, SourceLocation TypeLoc) {
+ ArrayRef<OpenMPMapModifierKind> MapModifiers,
+ ArrayRef<SourceLocation> MapModifiersLoc,
+ OpenMPMapClauseKind Type, bool TypeIsImplicit,
+ SourceLocation TypeLoc) {
unsigned NumVars = Vars.size();
unsigned NumUniqueDeclarations =
getUniqueDeclarationsTotalNumber(Declarations);
@@ -744,12 +822,12 @@ OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc,
NumVars, NumUniqueDeclarations,
NumUniqueDeclarations + NumComponentLists, NumComponents));
OMPMapClause *Clause = new (Mem) OMPMapClause(
- TypeModifier, Type, TypeIsImplicit, TypeLoc, StartLoc, LParenLoc, EndLoc,
- NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents);
+ MapModifiers, MapModifiersLoc, Type, TypeIsImplicit, TypeLoc, StartLoc,
+ LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, NumComponentLists,
+ NumComponents);
Clause->setVarRefs(Vars);
Clause->setClauseInfo(Declarations, ComponentLists);
- Clause->setMapTypeModifier(TypeModifier);
Clause->setMapType(Type);
Clause->setMapLoc(TypeLoc);
return Clause;
@@ -976,3 +1054,444 @@ OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(
return new (Mem) OMPIsDevicePtrClause(NumVars, NumUniqueDeclarations,
NumComponentLists, NumComponents);
}
+
+//===----------------------------------------------------------------------===//
+// OpenMP clauses printing methods
+//===----------------------------------------------------------------------===//
+
+void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
+ OS << "if(";
+ if (Node->getNameModifier() != OMPD_unknown)
+ OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": ";
+ Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) {
+ OS << "final(";
+ Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
+ OS << "num_threads(";
+ Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
+ OS << "safelen(";
+ Node->getSafelen()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) {
+ OS << "simdlen(";
+ Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
+ OS << "collapse(";
+ Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
+ OS << "default("
+ << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
+ << ")";
+}
+
+void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
+ OS << "proc_bind("
+ << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind())
+ << ")";
+}
+
+void OMPClausePrinter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {
+ OS << "unified_address";
+}
+
+void OMPClausePrinter::VisitOMPUnifiedSharedMemoryClause(
+ OMPUnifiedSharedMemoryClause *) {
+ OS << "unified_shared_memory";
+}
+
+void OMPClausePrinter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {
+ OS << "reverse_offload";
+}
+
+void OMPClausePrinter::VisitOMPDynamicAllocatorsClause(
+ OMPDynamicAllocatorsClause *) {
+ OS << "dynamic_allocators";
+}
+
+void OMPClausePrinter::VisitOMPAtomicDefaultMemOrderClause(
+ OMPAtomicDefaultMemOrderClause *Node) {
+ OS << "atomic_default_mem_order("
+ << getOpenMPSimpleClauseTypeName(OMPC_atomic_default_mem_order,
+ Node->getAtomicDefaultMemOrderKind())
+ << ")";
+}
+
+void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
+ OS << "schedule(";
+ if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
+ OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
+ Node->getFirstScheduleModifier());
+ if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
+ OS << ", ";
+ OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
+ Node->getSecondScheduleModifier());
+ }
+ OS << ": ";
+ }
+ OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
+ if (auto *E = Node->getChunkSize()) {
+ OS << ", ";
+ E->printPretty(OS, nullptr, Policy);
+ }
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) {
+ OS << "ordered";
+ if (auto *Num = Node->getNumForLoops()) {
+ OS << "(";
+ Num->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) {
+ OS << "nowait";
+}
+
+void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) {
+ OS << "untied";
+}
+
+void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) {
+ OS << "nogroup";
+}
+
+void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) {
+ OS << "mergeable";
+}
+
+void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; }
+
+void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; }
+
+void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) {
+ OS << "update";
+}
+
+void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) {
+ OS << "capture";
+}
+
+void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+ OS << "seq_cst";
+}
+
+void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
+ OS << "threads";
+}
+
+void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
+
+void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
+ OS << "device(";
+ Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
+ OS << "num_teams(";
+ Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) {
+ OS << "thread_limit(";
+ Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) {
+ OS << "priority(";
+ Node->getPriority()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) {
+ OS << "grainsize(";
+ Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) {
+ OS << "num_tasks(";
+ Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
+ OS << "hint(";
+ Node->getHint()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+template<typename T>
+void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
+ for (typename T::varlist_iterator I = Node->varlist_begin(),
+ E = Node->varlist_end();
+ I != E; ++I) {
+ assert(*I && "Expected non-null Stmt");
+ OS << (I == Node->varlist_begin() ? StartSym : ',');
+ if (auto *DRE = dyn_cast<DeclRefExpr>(*I)) {
+ if (isa<OMPCapturedExprDecl>(DRE->getDecl()))
+ DRE->printPretty(OS, nullptr, Policy, 0);
+ else
+ DRE->getDecl()->printQualifiedName(OS);
+ } else
+ (*I)->printPretty(OS, nullptr, Policy, 0);
+ }
+}
+
+void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "private";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "firstprivate";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "lastprivate";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "shared";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "reduction(";
+ NestedNameSpecifier *QualifierLoc =
+ Node->getQualifierLoc().getNestedNameSpecifier();
+ OverloadedOperatorKind OOK =
+ Node->getNameInfo().getName().getCXXOverloadedOperator();
+ if (QualifierLoc == nullptr && OOK != OO_None) {
+ // Print reduction identifier in C format
+ OS << getOperatorSpelling(OOK);
+ } else {
+ // Use C++ format
+ if (QualifierLoc != nullptr)
+ QualifierLoc->print(OS, Policy);
+ OS << Node->getNameInfo();
+ }
+ OS << ":";
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPTaskReductionClause(
+ OMPTaskReductionClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "task_reduction(";
+ NestedNameSpecifier *QualifierLoc =
+ Node->getQualifierLoc().getNestedNameSpecifier();
+ OverloadedOperatorKind OOK =
+ Node->getNameInfo().getName().getCXXOverloadedOperator();
+ if (QualifierLoc == nullptr && OOK != OO_None) {
+ // Print reduction identifier in C format
+ OS << getOperatorSpelling(OOK);
+ } else {
+ // Use C++ format
+ if (QualifierLoc != nullptr)
+ QualifierLoc->print(OS, Policy);
+ OS << Node->getNameInfo();
+ }
+ OS << ":";
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "in_reduction(";
+ NestedNameSpecifier *QualifierLoc =
+ Node->getQualifierLoc().getNestedNameSpecifier();
+ OverloadedOperatorKind OOK =
+ Node->getNameInfo().getName().getCXXOverloadedOperator();
+ if (QualifierLoc == nullptr && OOK != OO_None) {
+ // Print reduction identifier in C format
+ OS << getOperatorSpelling(OOK);
+ } else {
+ // Use C++ format
+ if (QualifierLoc != nullptr)
+ QualifierLoc->print(OS, Policy);
+ OS << Node->getNameInfo();
+ }
+ OS << ":";
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "linear";
+ if (Node->getModifierLoc().isValid()) {
+ OS << '('
+ << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier());
+ }
+ VisitOMPClauseList(Node, '(');
+ if (Node->getModifierLoc().isValid())
+ OS << ')';
+ if (Node->getStep() != nullptr) {
+ OS << ": ";
+ Node->getStep()->printPretty(OS, nullptr, Policy, 0);
+ }
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "aligned";
+ VisitOMPClauseList(Node, '(');
+ if (Node->getAlignment() != nullptr) {
+ OS << ": ";
+ Node->getAlignment()->printPretty(OS, nullptr, Policy, 0);
+ }
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "copyin";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "copyprivate";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
+ if (!Node->varlist_empty()) {
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
+ OS << "depend(";
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
+ Node->getDependencyKind());
+ if (!Node->varlist_empty()) {
+ OS << " :";
+ VisitOMPClauseList(Node, ' ');
+ }
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "map(";
+ if (Node->getMapType() != OMPC_MAP_unknown) {
+ for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) {
+ if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) {
+ OS << getOpenMPSimpleClauseTypeName(OMPC_map,
+ Node->getMapTypeModifier(I));
+ OS << ',';
+ }
+ }
+ OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType());
+ OS << ':';
+ }
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "to";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "from";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
+ OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
+ OMPC_dist_schedule, Node->getDistScheduleKind());
+ if (auto *E = Node->getChunkSize()) {
+ OS << ", ";
+ E->printPretty(OS, nullptr, Policy);
+ }
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) {
+ OS << "defaultmap(";
+ OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
+ Node->getDefaultmapModifier());
+ OS << ": ";
+ OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
+ Node->getDefaultmapKind());
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "use_device_ptr";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "is_device_ptr";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index af2a480dc23f..88c178aa372f 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -163,7 +163,7 @@ bool ParentMap::isConsumedExpr(Expr* E) const {
// Ignore parents that don't guarantee consumption.
while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
- isa<ExprWithCleanups>(P))) {
+ isa<FullExpr>(P))) {
DirectChild = P;
P = getParent(P);
}
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/AST/PrintfFormatString.cpp
index dcb15c5e3758..e0a0c5b7582a 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/AST/PrintfFormatString.cpp
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/Analyses/FormatString.h"
-#include "clang/Analysis/Analyses/OSLog.h"
+#include "clang/AST/FormatString.h"
+#include "clang/AST/OSLog.h"
#include "FormatStringParsing.h"
#include "clang/Basic/TargetInfo.h"
@@ -127,7 +127,9 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
do {
StringRef Str(I, E - I);
- std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})";
+ std::string Match = "^[[:space:]]*"
+ "(private|public|sensitive|mask\\.[^[:space:],}]*)"
+ "[[:space:]]*(,|})";
llvm::Regex R(Match);
SmallVector<StringRef, 2> Matches;
@@ -138,7 +140,17 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
// Set the privacy flag if the privacy annotation in the
// comma-delimited segment is at least as strict as the privacy
// annotations in previous comma-delimited segments.
- if (MatchedStr.equals("private"))
+ if (MatchedStr.startswith("mask")) {
+ StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
+ unsigned Size = MaskType.size();
+ if (Warn && (Size == 0 || Size > 8))
+ H.handleInvalidMaskType(MaskType);
+ FS.setMaskType(MaskType);
+ } else if (MatchedStr.equals("sensitive"))
+ PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive;
+ else if (PrivacyFlags !=
+ clang::analyze_os_log::OSLogBufferItem::IsSensitive &&
+ MatchedStr.equals("private"))
PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
@@ -168,6 +180,9 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
case clang::analyze_os_log::OSLogBufferItem::IsPublic:
FS.setIsPublic(MatchedStr.data());
break;
+ case clang::analyze_os_log::OSLogBufferItem::IsSensitive:
+ FS.setIsSensitive(MatchedStr.data());
+ break;
default:
llvm_unreachable("Unexpected privacy flag value");
}
@@ -232,6 +247,9 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
}
}
+ if (ParseVectorModifier(H, FS, I, E, LO))
+ return true;
+
// Look for the length modifier.
if (ParseLengthModifier(FS, I, E, LO) && I == E) {
// No more characters left?
@@ -347,6 +365,7 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
case 'Z':
if (Target.getTriple().isOSMSVCRT())
k = ConversionSpecifier::ZArg;
+ break;
}
// Check to see if we used the Objective-C modifier flags with
@@ -445,13 +464,8 @@ bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
// Methods on PrintfSpecifier.
//===----------------------------------------------------------------------===//
-ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
- bool IsObjCLiteral) const {
- const PrintfConversionSpecifier &CS = getConversionSpecifier();
-
- if (!CS.consumesDataArgument())
- return ArgType::Invalid();
-
+ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
+ bool IsObjCLiteral) const {
if (CS.getKind() == ConversionSpecifier::cArg)
switch (LM.getKind()) {
case LengthModifier::None:
@@ -611,6 +625,21 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
return ArgType();
}
+
+ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
+ bool IsObjCLiteral) const {
+ const PrintfConversionSpecifier &CS = getConversionSpecifier();
+
+ if (!CS.consumesDataArgument())
+ return ArgType::Invalid();
+
+ ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
+ if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
+ return ScalarTy;
+
+ return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
+}
+
bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
ASTContext &Ctx, bool IsObjCLiteral) {
// %n is different from other conversion specifiers; don't try to fix it.
@@ -660,8 +689,17 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
if (const EnumType *ETy = QT->getAs<EnumType>())
QT = ETy->getDecl()->getIntegerType();
- // We can only work with builtin types.
const BuiltinType *BT = QT->getAs<BuiltinType>();
+ if (!BT) {
+ const VectorType *VT = QT->getAs<VectorType>();
+ if (VT) {
+ QT = VT->getElementType();
+ BT = QT->getAs<BuiltinType>();
+ VectorNumElts = OptionalAmount(VT->getNumElements());
+ }
+ }
+
+ // We can only work with builtin types.
if (!BT)
return false;
@@ -708,6 +746,9 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
#define SIGNED_TYPE(Id, SingletonId)
#define UNSIGNED_TYPE(Id, SingletonId)
#define FLOATING_TYPE(Id, SingletonId)
@@ -830,6 +871,11 @@ void PrintfSpecifier::toString(raw_ostream &os) const {
FieldWidth.toString(os);
// Precision
Precision.toString(os);
+
+ // Vector modifier
+ if (!VectorNumElts.isInvalid())
+ os << 'v' << VectorNumElts.getConstantAmount();
+
// Length modifier
os << LM.toString();
// Conversion specifier
diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp
index 95da9ed6d238..ab873a396419 100644
--- a/lib/AST/RawCommentList.cpp
+++ b/lib/AST/RawCommentList.cpp
@@ -68,8 +68,8 @@ bool mergedCommentIsTrailingComment(StringRef Comment) {
/// column.
bool commentsStartOnSameColumn(const SourceManager &SM, const RawComment &R1,
const RawComment &R2) {
- SourceLocation L1 = R1.getLocStart();
- SourceLocation L2 = R2.getLocStart();
+ SourceLocation L1 = R1.getBeginLoc();
+ SourceLocation L2 = R2.getBeginLoc();
bool Invalid = false;
unsigned C1 = SM.getPresumedColumnNumber(L1, &Invalid);
if (!Invalid) {
@@ -278,8 +278,8 @@ void RawCommentList::addComment(const RawComment &RC,
// Check if the comments are not in source order.
while (!Comments.empty() &&
- !SourceMgr.isBeforeInTranslationUnit(Comments.back()->getLocStart(),
- RC.getLocStart())) {
+ !SourceMgr.isBeforeInTranslationUnit(Comments.back()->getBeginLoc(),
+ RC.getBeginLoc())) {
// If they are, just pop a few last comments that don't fit.
// This happens if an \#include directive contains comments.
Comments.pop_back();
@@ -316,9 +316,9 @@ void RawCommentList::addComment(const RawComment &RC,
(C1.isTrailingComment() && !C2.isTrailingComment() &&
isOrdinaryKind(C2.getKind()) &&
commentsStartOnSameColumn(SourceMgr, C1, C2))) &&
- onlyWhitespaceBetween(SourceMgr, C1.getLocEnd(), C2.getLocStart(),
+ onlyWhitespaceBetween(SourceMgr, C1.getEndLoc(), C2.getBeginLoc(),
/*MaxNewlinesAllowed=*/1)) {
- SourceRange MergedRange(C1.getLocStart(), C2.getLocEnd());
+ SourceRange MergedRange(C1.getBeginLoc(), C2.getEndLoc());
*Comments.back() = RawComment(SourceMgr, MergedRange, CommentOpts, true);
} else {
Comments.push_back(new (Allocator) RawComment(RC));
@@ -415,7 +415,7 @@ std::string RawComment::getFormattedText(const SourceManager &SourceMgr,
Str.pop_back();
};
- // Proces first line separately to remember indent for the following lines.
+ // Process first line separately to remember indent for the following lines.
if (!LexLine(/*IsFirstLine=*/true)) {
DropTrailingNewLines(Result);
return Result;
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 6f71d5b83e62..62dc22c81403 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -9,6 +9,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
@@ -16,7 +17,6 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
@@ -2829,15 +2829,14 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
CharUnits BaseOffset;
// Respect the external AST source base offset, if present.
- bool FoundBase = false;
if (UseExternalLayout) {
- FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
- if (FoundBase)
- assert(BaseOffset >= Size && "base offset already allocated");
- }
- if (!FoundBase)
+ if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset))
+ BaseOffset = Size;
+ } else
BaseOffset = Size.alignTo(Info.Alignment);
+ assert(BaseOffset >= Size && "base offset already allocated");
+
VBases.insert(std::make_pair(BaseDecl,
ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
Size = BaseOffset + BaseLayout.getNonVirtualSize();
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/AST/ScanfFormatString.cpp
index a9af0cdfdacd..08ba7a7a4f5c 100644
--- a/lib/Analysis/ScanfFormatString.cpp
+++ b/lib/AST/ScanfFormatString.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/AST/FormatString.h"
#include "FormatStringParsing.h"
#include "clang/Basic/TargetInfo.h"
@@ -264,6 +264,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsWide:
return ArgType::Invalid();
}
+ llvm_unreachable("Unsupported LenghtModifier Type");
// Unsigned int.
case ConversionSpecifier::oArg:
@@ -303,6 +304,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
case LengthModifier::AsWide:
return ArgType::Invalid();
}
+ llvm_unreachable("Unsupported LenghtModifier Type");
// Float.
case ConversionSpecifier::aArg:
diff --git a/lib/AST/SelectorLocationsKind.cpp b/lib/AST/SelectorLocationsKind.cpp
index 671207a7f2d9..8b72c85d7ef7 100644
--- a/lib/AST/SelectorLocationsKind.cpp
+++ b/lib/AST/SelectorLocationsKind.cpp
@@ -49,12 +49,12 @@ SourceLocation getArgLoc(T* Arg);
template <>
SourceLocation getArgLoc<Expr>(Expr *Arg) {
- return Arg->getLocStart();
+ return Arg->getBeginLoc();
}
template <>
SourceLocation getArgLoc<ParmVarDecl>(ParmVarDecl *Arg) {
- SourceLocation Loc = Arg->getLocStart();
+ SourceLocation Loc = Arg->getBeginLoc();
if (Loc.isInvalid())
return Loc;
// -1 to point to left paren of the method parameter's type.
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index a041006c905e..116291bfa1ef 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -76,6 +76,14 @@ const char *Stmt::getStmtClassName() const {
return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
}
+// Check that no statement / expression class is polymorphic. LLVM style RTTI
+// should be used instead. If absolutely needed an exception can still be added
+// here by defining the appropriate macro (but please don't do this).
+#define STMT(CLASS, PARENT) \
+ static_assert(!std::is_polymorphic<CLASS>::value, \
+ #CLASS " should not be polymorphic!");
+#include "clang/AST/StmtNodes.inc"
+
void Stmt::PrintStats() {
// Ensure the table is primed.
getStmtInfoTableEntry(Stmt::NullStmtClass);
@@ -113,17 +121,23 @@ void Stmt::EnableStatistics() {
Stmt *Stmt::IgnoreImplicit() {
Stmt *s = this;
- if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
- s = ewc->getSubExpr();
+ Stmt *lasts = nullptr;
- if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
- s = mte->GetTemporaryExpr();
+ while (s != lasts) {
+ lasts = s;
- if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s))
- s = bte->getSubExpr();
+ if (auto *fe = dyn_cast<FullExpr>(s))
+ s = fe->getSubExpr();
- while (auto *ice = dyn_cast<ImplicitCastExpr>(s))
- s = ice->getSubExpr();
+ if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
+ s = mte->GetTemporaryExpr();
+
+ if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s))
+ s = bte->getSubExpr();
+
+ if (auto *ice = dyn_cast<ImplicitCastExpr>(s))
+ s = ice->getSubExpr();
+ }
return s;
}
@@ -185,30 +199,26 @@ namespace {
return bad();
}
- typedef SourceLocation getLocStart_t() const;
- template <class T> good implements_getLocStart(getLocStart_t T::*) {
+ typedef SourceLocation getBeginLoc_t() const;
+ template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) {
return good();
}
LLVM_ATTRIBUTE_UNUSED
- static bad implements_getLocStart(getLocStart_t Stmt::*) {
- return bad();
- }
+ static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); }
typedef SourceLocation getLocEnd_t() const;
- template <class T> good implements_getLocEnd(getLocEnd_t T::*) {
+ template <class T> good implements_getEndLoc(getLocEnd_t T::*) {
return good();
}
LLVM_ATTRIBUTE_UNUSED
- static bad implements_getLocEnd(getLocEnd_t Stmt::*) {
- return bad();
- }
+ static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); }
#define ASSERT_IMPLEMENTS_children(type) \
(void) is_good(implements_children(&type::children))
-#define ASSERT_IMPLEMENTS_getLocStart(type) \
- (void) is_good(implements_getLocStart(&type::getLocStart))
-#define ASSERT_IMPLEMENTS_getLocEnd(type) \
- (void) is_good(implements_getLocEnd(&type::getLocEnd))
+#define ASSERT_IMPLEMENTS_getBeginLoc(type) \
+ (void)is_good(implements_getBeginLoc(&type::getBeginLoc))
+#define ASSERT_IMPLEMENTS_getEndLoc(type) \
+ (void)is_good(implements_getEndLoc(&type::getEndLoc))
} // namespace
@@ -217,10 +227,10 @@ namespace {
LLVM_ATTRIBUTE_UNUSED
static inline void check_implementations() {
#define ABSTRACT_STMT(type)
-#define STMT(type, base) \
- ASSERT_IMPLEMENTS_children(type); \
- ASSERT_IMPLEMENTS_getLocStart(type); \
- ASSERT_IMPLEMENTS_getLocEnd(type);
+#define STMT(type, base) \
+ ASSERT_IMPLEMENTS_children(type); \
+ ASSERT_IMPLEMENTS_getBeginLoc(type); \
+ ASSERT_IMPLEMENTS_getEndLoc(type);
#include "clang/AST/StmtNodes.inc"
}
@@ -257,8 +267,8 @@ namespace {
template <class S>
SourceRange getSourceRangeImpl(const Stmt *stmt,
SourceRange (Stmt::*v)() const) {
- return SourceRange(static_cast<const S*>(stmt)->getLocStart(),
- static_cast<const S*>(stmt)->getLocEnd());
+ return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(),
+ static_cast<const S *>(stmt)->getEndLoc());
}
} // namespace
@@ -275,36 +285,41 @@ SourceRange Stmt::getSourceRange() const {
llvm_unreachable("unknown statement kind!");
}
-SourceLocation Stmt::getLocStart() const {
-// llvm::errs() << "getLocStart() for " << getStmtClassName() << "\n";
+SourceLocation Stmt::getBeginLoc() const {
+ // llvm::errs() << "getBeginLoc() for " << getStmtClassName() << "\n";
switch (getStmtClass()) {
case Stmt::NoStmtClass: llvm_unreachable("statement without class");
#define ABSTRACT_STMT(type)
-#define STMT(type, base) \
- case Stmt::type##Class: \
- return static_cast<const type*>(this)->getLocStart();
+#define STMT(type, base) \
+ case Stmt::type##Class: \
+ return static_cast<const type *>(this)->getBeginLoc();
#include "clang/AST/StmtNodes.inc"
}
llvm_unreachable("unknown statement kind");
}
-SourceLocation Stmt::getLocEnd() const {
+SourceLocation Stmt::getEndLoc() const {
switch (getStmtClass()) {
case Stmt::NoStmtClass: llvm_unreachable("statement without class");
#define ABSTRACT_STMT(type)
-#define STMT(type, base) \
- case Stmt::type##Class: \
- return static_cast<const type*>(this)->getLocEnd();
+#define STMT(type, base) \
+ case Stmt::type##Class: \
+ return static_cast<const type *>(this)->getEndLoc();
#include "clang/AST/StmtNodes.inc"
}
llvm_unreachable("unknown statement kind");
}
+int64_t Stmt::getID(const ASTContext &Context) const {
+ return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this);
+}
+
CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB,
SourceLocation RB)
- : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) {
+ : Stmt(CompoundStmtClass), RBraceLoc(RB) {
CompoundStmtBits.NumStmts = Stmts.size();
setStmts(Stmts);
+ CompoundStmtBits.LBraceLoc = LB;
}
void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) {
@@ -789,51 +804,99 @@ void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
});
}
-IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, bool IsConstexpr,
- Stmt *init, VarDecl *var, Expr *cond, Stmt *then,
- SourceLocation EL, Stmt *elsev)
- : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) {
+IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr,
+ Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then,
+ SourceLocation EL, Stmt *Else)
+ : Stmt(IfStmtClass) {
+ bool HasElse = Else != nullptr;
+ bool HasVar = Var != nullptr;
+ bool HasInit = Init != nullptr;
+ IfStmtBits.HasElse = HasElse;
+ IfStmtBits.HasVar = HasVar;
+ IfStmtBits.HasInit = HasInit;
+
setConstexpr(IsConstexpr);
- setConditionVariable(C, var);
- SubExprs[INIT] = init;
- SubExprs[COND] = cond;
- SubExprs[THEN] = then;
- SubExprs[ELSE] = elsev;
-}
-VarDecl *IfStmt::getConditionVariable() const {
- if (!SubExprs[VAR])
+ setCond(Cond);
+ setThen(Then);
+ if (HasElse)
+ setElse(Else);
+ if (HasVar)
+ setConditionVariable(Ctx, Var);
+ if (HasInit)
+ setInit(Init);
+
+ setIfLoc(IL);
+ if (HasElse)
+ setElseLoc(EL);
+}
+
+IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit)
+ : Stmt(IfStmtClass, Empty) {
+ IfStmtBits.HasElse = HasElse;
+ IfStmtBits.HasVar = HasVar;
+ IfStmtBits.HasInit = HasInit;
+}
+
+IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL,
+ bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
+ Stmt *Then, SourceLocation EL, Stmt *Else) {
+ bool HasElse = Else != nullptr;
+ bool HasVar = Var != nullptr;
+ bool HasInit = Init != nullptr;
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *, SourceLocation>(
+ NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
+ alignof(IfStmt));
+ return new (Mem)
+ IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else);
+}
+
+IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
+ bool HasInit) {
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *, SourceLocation>(
+ NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
+ alignof(IfStmt));
+ return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit);
+}
+
+VarDecl *IfStmt::getConditionVariable() {
+ auto *DS = getConditionVariableDeclStmt();
+ if (!DS)
return nullptr;
-
- auto *DS = cast<DeclStmt>(SubExprs[VAR]);
return cast<VarDecl>(DS->getSingleDecl());
}
-void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
+void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
+ assert(hasVarStorage() &&
+ "This if statement has no storage for a condition variable!");
+
if (!V) {
- SubExprs[VAR] = nullptr;
+ getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
return;
}
SourceRange VarRange = V->getSourceRange();
- SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
- VarRange.getEnd());
+ getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
+ DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
}
bool IfStmt::isObjCAvailabilityCheck() const {
- return isa<ObjCAvailabilityCheckExpr>(SubExprs[COND]);
+ return isa<ObjCAvailabilityCheckExpr>(getCond());
}
ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
SourceLocation RP)
- : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
+ : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP)
{
SubExprs[INIT] = Init;
setConditionVariable(C, condVar);
SubExprs[COND] = Cond;
SubExprs[INC] = Inc;
SubExprs[BODY] = Body;
+ ForStmtBits.ForLoc = FL;
}
VarDecl *ForStmt::getConditionVariable() const {
@@ -855,66 +918,125 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
VarRange.getEnd());
}
-SwitchStmt::SwitchStmt(const ASTContext &C, Stmt *init, VarDecl *Var,
- Expr *cond)
- : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
- setConditionVariable(C, Var);
- SubExprs[INIT] = init;
- SubExprs[COND] = cond;
- SubExprs[BODY] = nullptr;
+SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
+ Expr *Cond)
+ : Stmt(SwitchStmtClass), FirstCase(nullptr) {
+ bool HasInit = Init != nullptr;
+ bool HasVar = Var != nullptr;
+ SwitchStmtBits.HasInit = HasInit;
+ SwitchStmtBits.HasVar = HasVar;
+ SwitchStmtBits.AllEnumCasesCovered = false;
+
+ setCond(Cond);
+ setBody(nullptr);
+ if (HasInit)
+ setInit(Init);
+ if (HasVar)
+ setConditionVariable(Ctx, Var);
+
+ setSwitchLoc(SourceLocation{});
}
-VarDecl *SwitchStmt::getConditionVariable() const {
- if (!SubExprs[VAR])
- return nullptr;
+SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar)
+ : Stmt(SwitchStmtClass, Empty) {
+ SwitchStmtBits.HasInit = HasInit;
+ SwitchStmtBits.HasVar = HasVar;
+ SwitchStmtBits.AllEnumCasesCovered = false;
+}
+
+SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
+ Expr *Cond) {
+ bool HasInit = Init != nullptr;
+ bool HasVar = Var != nullptr;
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
+ alignof(SwitchStmt));
+ return new (Mem) SwitchStmt(Ctx, Init, Var, Cond);
+}
- auto *DS = cast<DeclStmt>(SubExprs[VAR]);
+SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit,
+ bool HasVar) {
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
+ alignof(SwitchStmt));
+ return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar);
+}
+
+VarDecl *SwitchStmt::getConditionVariable() {
+ auto *DS = getConditionVariableDeclStmt();
+ if (!DS)
+ return nullptr;
return cast<VarDecl>(DS->getSingleDecl());
}
-void SwitchStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
+void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
+ assert(hasVarStorage() &&
+ "This switch statement has no storage for a condition variable!");
+
if (!V) {
- SubExprs[VAR] = nullptr;
+ getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
return;
}
SourceRange VarRange = V->getSourceRange();
- SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
- VarRange.getEnd());
+ getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
+ DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
}
-Stmt *SwitchCase::getSubStmt() {
- if (isa<CaseStmt>(this))
- return cast<CaseStmt>(this)->getSubStmt();
- return cast<DefaultStmt>(this)->getSubStmt();
+WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
+ Stmt *Body, SourceLocation WL)
+ : Stmt(WhileStmtClass) {
+ bool HasVar = Var != nullptr;
+ WhileStmtBits.HasVar = HasVar;
+
+ setCond(Cond);
+ setBody(Body);
+ if (HasVar)
+ setConditionVariable(Ctx, Var);
+
+ setWhileLoc(WL);
}
-WhileStmt::WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
- SourceLocation WL)
- : Stmt(WhileStmtClass) {
- setConditionVariable(C, Var);
- SubExprs[COND] = cond;
- SubExprs[BODY] = body;
- WhileLoc = WL;
+WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
+ : Stmt(WhileStmtClass, Empty) {
+ WhileStmtBits.HasVar = HasVar;
}
-VarDecl *WhileStmt::getConditionVariable() const {
- if (!SubExprs[VAR])
- return nullptr;
+WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
+ Stmt *Body, SourceLocation WL) {
+ bool HasVar = Var != nullptr;
+ void *Mem =
+ Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
+ alignof(WhileStmt));
+ return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL);
+}
+
+WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) {
+ void *Mem =
+ Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
+ alignof(WhileStmt));
+ return new (Mem) WhileStmt(EmptyShell(), HasVar);
+}
- auto *DS = cast<DeclStmt>(SubExprs[VAR]);
+VarDecl *WhileStmt::getConditionVariable() {
+ auto *DS = getConditionVariableDeclStmt();
+ if (!DS)
+ return nullptr;
return cast<VarDecl>(DS->getSingleDecl());
}
-void WhileStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
+void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
+ assert(hasVarStorage() &&
+ "This while statement has no storage for a condition variable!");
+
if (!V) {
- SubExprs[VAR] = nullptr;
+ getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
return;
}
SourceRange VarRange = V->getSourceRange();
- SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
- VarRange.getEnd());
+ getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
+ DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
}
// IndirectGotoStmt
@@ -925,11 +1047,54 @@ LabelDecl *IndirectGotoStmt::getConstantTarget() {
}
// ReturnStmt
-const Expr* ReturnStmt::getRetValue() const {
- return cast_or_null<Expr>(RetExpr);
-}
-Expr* ReturnStmt::getRetValue() {
- return cast_or_null<Expr>(RetExpr);
+ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
+ : Stmt(ReturnStmtClass), RetExpr(E) {
+ bool HasNRVOCandidate = NRVOCandidate != nullptr;
+ ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
+ if (HasNRVOCandidate)
+ setNRVOCandidate(NRVOCandidate);
+ setReturnLoc(RL);
+}
+
+ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate)
+ : Stmt(ReturnStmtClass, Empty) {
+ ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
+}
+
+ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL,
+ Expr *E, const VarDecl *NRVOCandidate) {
+ bool HasNRVOCandidate = NRVOCandidate != nullptr;
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
+ alignof(ReturnStmt));
+ return new (Mem) ReturnStmt(RL, E, NRVOCandidate);
+}
+
+ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx,
+ bool HasNRVOCandidate) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
+ alignof(ReturnStmt));
+ return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate);
+}
+
+// CaseStmt
+CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
+ SourceLocation caseLoc, SourceLocation ellipsisLoc,
+ SourceLocation colonLoc) {
+ bool CaseStmtIsGNURange = rhs != nullptr;
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *, SourceLocation>(
+ NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
+ alignof(CaseStmt));
+ return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc);
+}
+
+CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx,
+ bool CaseStmtIsGNURange) {
+ void *Mem = Ctx.Allocate(
+ totalSizeToAlloc<Stmt *, SourceLocation>(
+ NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
+ alignof(CaseStmt));
+ return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange);
}
SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp
index bf2d6a16fb5f..12367f8fd54b 100644
--- a/lib/AST/StmtCXX.cpp
+++ b/lib/AST/StmtCXX.cpp
@@ -45,7 +45,7 @@ CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
std::copy(handlers.begin(), handlers.end(), Stmts + 1);
}
-CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range,
+CXXForRangeStmt::CXXForRangeStmt(Stmt *Init, DeclStmt *Range,
DeclStmt *BeginStmt, DeclStmt *EndStmt,
Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
Stmt *Body, SourceLocation FL,
@@ -53,6 +53,7 @@ CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range,
SourceLocation RPL)
: Stmt(CXXForRangeStmtClass), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL),
RParenLoc(RPL) {
+ SubExprs[INIT] = Init;
SubExprs[RANGE] = Range;
SubExprs[BEGINSTMT] = BeginStmt;
SubExprs[ENDSTMT] = EndStmt;
diff --git a/lib/AST/StmtObjC.cpp b/lib/AST/StmtObjC.cpp
index eea03f64c2fe..ed21e2d0d2b6 100644
--- a/lib/AST/StmtObjC.cpp
+++ b/lib/AST/StmtObjC.cpp
@@ -64,10 +64,10 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context,
return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
}
-SourceLocation ObjCAtTryStmt::getLocEnd() const {
+SourceLocation ObjCAtTryStmt::getEndLoc() const {
if (HasFinally)
- return getFinallyStmt()->getLocEnd();
+ return getFinallyStmt()->getEndLoc();
if (NumCatchStmts)
- return getCatchStmt(NumCatchStmts - 1)->getLocEnd();
- return getTryBody()->getLocEnd();
+ return getCatchStmt(NumCatchStmts - 1)->getEndLoc();
+ return getTryBody()->getEndLoc();
}
diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp
index 1258af7a2d37..85a2daa0801a 100644
--- a/lib/AST/StmtOpenMP.cpp
+++ b/lib/AST/StmtOpenMP.cpp
@@ -1079,6 +1079,8 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
+ Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
Dir->HasCancel = HasCancel;
return Dir;
}
@@ -1145,6 +1147,8 @@ OMPDistributeParallelForSimdDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
+ Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
return Dir;
}
@@ -1457,6 +1461,8 @@ OMPTeamsDistributeParallelForSimdDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
+ Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
return Dir;
}
@@ -1524,6 +1530,8 @@ OMPTeamsDistributeParallelForDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
+ Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
Dir->HasCancel = HasCancel;
return Dir;
}
@@ -1670,6 +1678,8 @@ OMPTargetTeamsDistributeParallelForDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
+ Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
Dir->HasCancel = HasCancel;
return Dir;
}
@@ -1741,6 +1751,8 @@ OMPTargetTeamsDistributeParallelForSimdDirective::Create(
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
+ Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond);
+ Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond);
return Dir;
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index cbf26c036058..ae726e387107 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -69,14 +69,16 @@ namespace {
unsigned IndentLevel;
PrinterHelper* Helper;
PrintingPolicy Policy;
+ std::string NL;
const ASTContext *Context;
public:
StmtPrinter(raw_ostream &os, PrinterHelper *helper,
const PrintingPolicy &Policy, unsigned Indentation = 0,
+ StringRef NL = "\n",
const ASTContext *Context = nullptr)
: OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
- Context(Context) {}
+ NL(NL), Context(Context) {}
void PrintStmt(Stmt *S) {
PrintStmt(S, Policy.Indentation);
@@ -88,15 +90,37 @@ namespace {
// If this is an expr used in a stmt context, indent and newline it.
Indent();
Visit(S);
- OS << ";\n";
+ OS << ";" << NL;
} else if (S) {
Visit(S);
} else {
- Indent() << "<<<NULL STATEMENT>>>\n";
+ Indent() << "<<<NULL STATEMENT>>>" << NL;
}
IndentLevel -= SubIndent;
}
+ void PrintInitStmt(Stmt *S, unsigned PrefixWidth) {
+ // FIXME: Cope better with odd prefix widths.
+ IndentLevel += (PrefixWidth + 1) / 2;
+ if (auto *DS = dyn_cast<DeclStmt>(S))
+ PrintRawDeclStmt(DS);
+ else
+ PrintExpr(cast<Expr>(S));
+ OS << "; ";
+ IndentLevel -= (PrefixWidth + 1) / 2;
+ }
+
+ void PrintControlledStmt(Stmt *S) {
+ if (auto *CS = dyn_cast<CompoundStmt>(S)) {
+ OS << " ";
+ PrintRawCompoundStmt(CS);
+ OS << NL;
+ } else {
+ OS << NL;
+ PrintStmt(S);
+ }
+ }
+
void PrintRawCompoundStmt(CompoundStmt *S);
void PrintRawDecl(Decl *D);
void PrintRawDeclStmt(const DeclStmt *S);
@@ -128,7 +152,7 @@ namespace {
}
void VisitStmt(Stmt *Node) LLVM_ATTRIBUTE_UNUSED {
- Indent() << "<<unknown stmt type>>\n";
+ Indent() << "<<unknown stmt type>>" << NL;
}
void VisitExpr(Expr *Node) LLVM_ATTRIBUTE_UNUSED {
@@ -152,7 +176,7 @@ namespace {
/// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and
/// with no newline after the }.
void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
- OS << "{\n";
+ OS << "{" << NL;
for (auto *I : Node->body())
PrintStmt(I);
@@ -169,19 +193,19 @@ void StmtPrinter::PrintRawDeclStmt(const DeclStmt *S) {
}
void StmtPrinter::VisitNullStmt(NullStmt *Node) {
- Indent() << ";\n";
+ Indent() << ";" << NL;
}
void StmtPrinter::VisitDeclStmt(DeclStmt *Node) {
Indent();
PrintRawDeclStmt(Node);
- OS << ";\n";
+ OS << ";" << NL;
}
void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) {
Indent();
PrintRawCompoundStmt(Node);
- OS << "\n";
+ OS << "" << NL;
}
void StmtPrinter::VisitCaseStmt(CaseStmt *Node) {
@@ -191,18 +215,18 @@ void StmtPrinter::VisitCaseStmt(CaseStmt *Node) {
OS << " ... ";
PrintExpr(Node->getRHS());
}
- OS << ":\n";
+ OS << ":" << NL;
PrintStmt(Node->getSubStmt(), 0);
}
void StmtPrinter::VisitDefaultStmt(DefaultStmt *Node) {
- Indent(-1) << "default:\n";
+ Indent(-1) << "default:" << NL;
PrintStmt(Node->getSubStmt(), 0);
}
void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
- Indent(-1) << Node->getName() << ":\n";
+ Indent(-1) << Node->getName() << ":" << NL;
PrintStmt(Node->getSubStmt(), 0);
}
@@ -216,6 +240,8 @@ void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
OS << "if (";
+ if (If->getInit())
+ PrintInitStmt(If->getInit(), 4);
if (const DeclStmt *DS = If->getConditionVariableDeclStmt())
PrintRawDeclStmt(DS);
else
@@ -225,9 +251,9 @@ void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
if (auto *CS = dyn_cast<CompoundStmt>(If->getThen())) {
OS << ' ';
PrintRawCompoundStmt(CS);
- OS << (If->getElse() ? ' ' : '\n');
+ OS << (If->getElse() ? " " : NL);
} else {
- OS << '\n';
+ OS << NL;
PrintStmt(If->getThen());
if (If->getElse()) Indent();
}
@@ -238,12 +264,12 @@ void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
OS << ' ';
PrintRawCompoundStmt(CS);
- OS << '\n';
+ OS << NL;
} else if (auto *ElseIf = dyn_cast<IfStmt>(Else)) {
OS << ' ';
PrintRawIfStmt(ElseIf);
} else {
- OS << '\n';
+ OS << NL;
PrintStmt(If->getElse());
}
}
@@ -256,21 +282,14 @@ void StmtPrinter::VisitIfStmt(IfStmt *If) {
void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) {
Indent() << "switch (";
+ if (Node->getInit())
+ PrintInitStmt(Node->getInit(), 8);
if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
PrintRawDeclStmt(DS);
else
PrintExpr(Node->getCond());
OS << ")";
-
- // Pretty print compoundstmt bodies (very common).
- if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
- OS << " ";
- PrintRawCompoundStmt(CS);
- OS << "\n";
- } else {
- OS << "\n";
- PrintStmt(Node->getBody());
- }
+ PrintControlledStmt(Node->getBody());
}
void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
@@ -279,7 +298,7 @@ void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
PrintRawDeclStmt(DS);
else
PrintExpr(Node->getCond());
- OS << ")\n";
+ OS << ")" << NL;
PrintStmt(Node->getBody());
}
@@ -289,43 +308,31 @@ void StmtPrinter::VisitDoStmt(DoStmt *Node) {
PrintRawCompoundStmt(CS);
OS << " ";
} else {
- OS << "\n";
+ OS << NL;
PrintStmt(Node->getBody());
Indent();
}
OS << "while (";
PrintExpr(Node->getCond());
- OS << ");\n";
+ OS << ");" << NL;
}
void StmtPrinter::VisitForStmt(ForStmt *Node) {
Indent() << "for (";
- if (Node->getInit()) {
- if (auto *DS = dyn_cast<DeclStmt>(Node->getInit()))
- PrintRawDeclStmt(DS);
- else
- PrintExpr(cast<Expr>(Node->getInit()));
- }
- OS << ";";
- if (Node->getCond()) {
- OS << " ";
+ if (Node->getInit())
+ PrintInitStmt(Node->getInit(), 5);
+ else
+ OS << (Node->getCond() ? "; " : ";");
+ if (Node->getCond())
PrintExpr(Node->getCond());
- }
OS << ";";
if (Node->getInc()) {
OS << " ";
PrintExpr(Node->getInc());
}
- OS << ") ";
-
- if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
- PrintRawCompoundStmt(CS);
- OS << "\n";
- } else {
- OS << "\n";
- PrintStmt(Node->getBody());
- }
+ OS << ")";
+ PrintControlledStmt(Node->getBody());
}
void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) {
@@ -336,28 +343,21 @@ void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) {
PrintExpr(cast<Expr>(Node->getElement()));
OS << " in ";
PrintExpr(Node->getCollection());
- OS << ") ";
-
- if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
- PrintRawCompoundStmt(CS);
- OS << "\n";
- } else {
- OS << "\n";
- PrintStmt(Node->getBody());
- }
+ OS << ")";
+ PrintControlledStmt(Node->getBody());
}
void StmtPrinter::VisitCXXForRangeStmt(CXXForRangeStmt *Node) {
Indent() << "for (";
+ if (Node->getInit())
+ PrintInitStmt(Node->getInit(), 5);
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressInitializers = true;
Node->getLoopVariable()->print(OS, SubPolicy, IndentLevel);
OS << " : ";
PrintExpr(Node->getRangeInit());
- OS << ") {\n";
- PrintStmt(Node->getBody());
- Indent() << "}";
- if (Policy.IncludeNewlines) OS << "\n";
+ OS << ")";
+ PrintControlledStmt(Node->getBody());
}
void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
@@ -378,24 +378,24 @@ void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
void StmtPrinter::VisitGotoStmt(GotoStmt *Node) {
Indent() << "goto " << Node->getLabel()->getName() << ";";
- if (Policy.IncludeNewlines) OS << "\n";
+ if (Policy.IncludeNewlines) OS << NL;
}
void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) {
Indent() << "goto *";
PrintExpr(Node->getTarget());
OS << ";";
- if (Policy.IncludeNewlines) OS << "\n";
+ if (Policy.IncludeNewlines) OS << NL;
}
void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) {
Indent() << "continue;";
- if (Policy.IncludeNewlines) OS << "\n";
+ if (Policy.IncludeNewlines) OS << NL;
}
void StmtPrinter::VisitBreakStmt(BreakStmt *Node) {
Indent() << "break;";
- if (Policy.IncludeNewlines) OS << "\n";
+ if (Policy.IncludeNewlines) OS << NL;
}
void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
@@ -405,7 +405,7 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
PrintExpr(Node->getRetValue());
}
OS << ";";
- if (Policy.IncludeNewlines) OS << "\n";
+ if (Policy.IncludeNewlines) OS << NL;
}
void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
@@ -470,17 +470,17 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
}
OS << ");";
- if (Policy.IncludeNewlines) OS << "\n";
+ if (Policy.IncludeNewlines) OS << NL;
}
void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) {
// FIXME: Implement MS style inline asm statement printer.
Indent() << "__asm ";
if (Node->hasBraces())
- OS << "{\n";
- OS << Node->getAsmString() << "\n";
+ OS << "{" << NL;
+ OS << Node->getAsmString() << NL;
if (Node->hasBraces())
- Indent() << "}\n";
+ Indent() << "}" << NL;
}
void StmtPrinter::VisitCapturedStmt(CapturedStmt *Node) {
@@ -491,7 +491,7 @@ void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
Indent() << "@try";
if (auto *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {
PrintRawCompoundStmt(TS);
- OS << "\n";
+ OS << NL;
}
for (unsigned I = 0, N = Node->getNumCatchStmts(); I != N; ++I) {
@@ -504,14 +504,14 @@ void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
OS << ")";
if (auto *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) {
PrintRawCompoundStmt(CS);
- OS << "\n";
+ OS << NL;
}
}
if (auto *FS = static_cast<ObjCAtFinallyStmt *>(Node->getFinallyStmt())) {
Indent() << "@finally";
PrintRawCompoundStmt(dyn_cast<CompoundStmt>(FS->getFinallyBody()));
- OS << "\n";
+ OS << NL;
}
}
@@ -519,7 +519,7 @@ void StmtPrinter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Node) {
}
void StmtPrinter::VisitObjCAtCatchStmt (ObjCAtCatchStmt *Node) {
- Indent() << "@catch (...) { /* todo */ } \n";
+ Indent() << "@catch (...) { /* todo */ } " << NL;
}
void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) {
@@ -528,7 +528,7 @@ void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) {
OS << " ";
PrintExpr(Node->getThrowExpr());
}
- OS << ";\n";
+ OS << ";" << NL;
}
void StmtPrinter::VisitObjCAvailabilityCheckExpr(
@@ -541,13 +541,13 @@ void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) {
PrintExpr(Node->getSynchExpr());
OS << ")";
PrintRawCompoundStmt(Node->getSynchBody());
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *Node) {
Indent() << "@autoreleasepool";
PrintRawCompoundStmt(dyn_cast<CompoundStmt>(Node->getSubStmt()));
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
@@ -563,7 +563,7 @@ void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) {
Indent();
PrintRawCXXCatchStmt(Node);
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
@@ -573,7 +573,7 @@ void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
OS << " ";
PrintRawCXXCatchStmt(Node->getHandler(i));
}
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) {
@@ -587,471 +587,38 @@ void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) {
assert(F && "Must have a finally block...");
PrintRawSEHFinallyStmt(F);
}
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) {
OS << "__finally ";
PrintRawCompoundStmt(Node->getBlock());
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::PrintRawSEHExceptHandler(SEHExceptStmt *Node) {
OS << "__except (";
VisitExpr(Node->getFilterExpr());
- OS << ")\n";
+ OS << ")" << NL;
PrintRawCompoundStmt(Node->getBlock());
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::VisitSEHExceptStmt(SEHExceptStmt *Node) {
Indent();
PrintRawSEHExceptHandler(Node);
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) {
Indent();
PrintRawSEHFinallyStmt(Node);
- OS << "\n";
+ OS << NL;
}
void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) {
Indent() << "__leave;";
- if (Policy.IncludeNewlines) OS << "\n";
-}
-
-//===----------------------------------------------------------------------===//
-// OpenMP clauses printing methods
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class OMPClausePrinter : public OMPClauseVisitor<OMPClausePrinter> {
- raw_ostream &OS;
- const PrintingPolicy &Policy;
-
- /// Process clauses with list of variables.
- template <typename T>
- void VisitOMPClauseList(T *Node, char StartSym);
-
-public:
- OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
- : OS(OS), Policy(Policy) {}
-
-#define OPENMP_CLAUSE(Name, Class) \
- void Visit##Class(Class *S);
-#include "clang/Basic/OpenMPKinds.def"
-};
-
-} // namespace
-
-void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
- OS << "if(";
- if (Node->getNameModifier() != OMPD_unknown)
- OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": ";
- Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) {
- OS << "final(";
- Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
- OS << "num_threads(";
- Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
- OS << "safelen(";
- Node->getSafelen()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) {
- OS << "simdlen(";
- Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
- OS << "collapse(";
- Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
- OS << "default("
- << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
- << ")";
-}
-
-void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
- OS << "proc_bind("
- << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind())
- << ")";
-}
-
-void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
- OS << "schedule(";
- if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
- OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
- Node->getFirstScheduleModifier());
- if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
- OS << ", ";
- OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
- Node->getSecondScheduleModifier());
- }
- OS << ": ";
- }
- OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
- if (auto *E = Node->getChunkSize()) {
- OS << ", ";
- E->printPretty(OS, nullptr, Policy);
- }
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) {
- OS << "ordered";
- if (auto *Num = Node->getNumForLoops()) {
- OS << "(";
- Num->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) {
- OS << "nowait";
-}
-
-void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) {
- OS << "untied";
-}
-
-void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) {
- OS << "nogroup";
-}
-
-void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) {
- OS << "mergeable";
-}
-
-void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; }
-
-void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; }
-
-void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) {
- OS << "update";
-}
-
-void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) {
- OS << "capture";
-}
-
-void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
- OS << "seq_cst";
-}
-
-void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
- OS << "threads";
-}
-
-void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
-
-void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
- OS << "device(";
- Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
- OS << "num_teams(";
- Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) {
- OS << "thread_limit(";
- Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) {
- OS << "priority(";
- Node->getPriority()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) {
- OS << "grainsize(";
- Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) {
- OS << "num_tasks(";
- Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
- OS << "hint(";
- Node->getHint()->printPretty(OS, nullptr, Policy, 0);
- OS << ")";
-}
-
-template<typename T>
-void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
- for (typename T::varlist_iterator I = Node->varlist_begin(),
- E = Node->varlist_end();
- I != E; ++I) {
- assert(*I && "Expected non-null Stmt");
- OS << (I == Node->varlist_begin() ? StartSym : ',');
- if (auto *DRE = dyn_cast<DeclRefExpr>(*I)) {
- if (isa<OMPCapturedExprDecl>(DRE->getDecl()))
- DRE->printPretty(OS, nullptr, Policy, 0);
- else
- DRE->getDecl()->printQualifiedName(OS);
- } else
- (*I)->printPretty(OS, nullptr, Policy, 0);
- }
-}
-
-void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "private";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "firstprivate";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "lastprivate";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "shared";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "reduction(";
- NestedNameSpecifier *QualifierLoc =
- Node->getQualifierLoc().getNestedNameSpecifier();
- OverloadedOperatorKind OOK =
- Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
- // Print reduction identifier in C format
- OS << getOperatorSpelling(OOK);
- } else {
- // Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
- OS << Node->getNameInfo();
- }
- OS << ":";
- VisitOMPClauseList(Node, ' ');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPTaskReductionClause(
- OMPTaskReductionClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "task_reduction(";
- NestedNameSpecifier *QualifierLoc =
- Node->getQualifierLoc().getNestedNameSpecifier();
- OverloadedOperatorKind OOK =
- Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
- // Print reduction identifier in C format
- OS << getOperatorSpelling(OOK);
- } else {
- // Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
- OS << Node->getNameInfo();
- }
- OS << ":";
- VisitOMPClauseList(Node, ' ');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "in_reduction(";
- NestedNameSpecifier *QualifierLoc =
- Node->getQualifierLoc().getNestedNameSpecifier();
- OverloadedOperatorKind OOK =
- Node->getNameInfo().getName().getCXXOverloadedOperator();
- if (QualifierLoc == nullptr && OOK != OO_None) {
- // Print reduction identifier in C format
- OS << getOperatorSpelling(OOK);
- } else {
- // Use C++ format
- if (QualifierLoc != nullptr)
- QualifierLoc->print(OS, Policy);
- OS << Node->getNameInfo();
- }
- OS << ":";
- VisitOMPClauseList(Node, ' ');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "linear";
- if (Node->getModifierLoc().isValid()) {
- OS << '('
- << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier());
- }
- VisitOMPClauseList(Node, '(');
- if (Node->getModifierLoc().isValid())
- OS << ')';
- if (Node->getStep() != nullptr) {
- OS << ": ";
- Node->getStep()->printPretty(OS, nullptr, Policy, 0);
- }
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "aligned";
- VisitOMPClauseList(Node, '(');
- if (Node->getAlignment() != nullptr) {
- OS << ": ";
- Node->getAlignment()->printPretty(OS, nullptr, Policy, 0);
- }
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "copyin";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "copyprivate";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
- if (!Node->varlist_empty()) {
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
- OS << "depend(";
- OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
- Node->getDependencyKind());
- if (!Node->varlist_empty()) {
- OS << " :";
- VisitOMPClauseList(Node, ' ');
- }
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "map(";
- if (Node->getMapType() != OMPC_MAP_unknown) {
- if (Node->getMapTypeModifier() != OMPC_MAP_unknown) {
- OS << getOpenMPSimpleClauseTypeName(OMPC_map,
- Node->getMapTypeModifier());
- OS << ',';
- }
- OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType());
- OS << ':';
- }
- VisitOMPClauseList(Node, ' ');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "to";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "from";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
- OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
- OMPC_dist_schedule, Node->getDistScheduleKind());
- if (auto *E = Node->getChunkSize()) {
- OS << ", ";
- E->printPretty(OS, nullptr, Policy);
- }
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) {
- OS << "defaultmap(";
- OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
- Node->getDefaultmapModifier());
- OS << ": ";
- OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
- Node->getDefaultmapKind());
- OS << ")";
-}
-
-void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "use_device_ptr";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
-}
-
-void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) {
- if (!Node->varlist_empty()) {
- OS << "is_device_ptr";
- VisitOMPClauseList(Node, '(');
- OS << ")";
- }
+ if (Policy.IncludeNewlines) OS << NL;
}
//===----------------------------------------------------------------------===//
@@ -1067,7 +634,7 @@ void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
OS << ' ';
Printer.Visit(Clause);
}
- OS << "\n";
+ OS << NL;
if (!ForceNoStmt && S->hasAssociatedStmt())
PrintStmt(S->getInnermostCapturedStmt()->getCapturedStmt());
}
@@ -1339,6 +906,10 @@ void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
// Expr printing methods.
//===----------------------------------------------------------------------===//
+void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
+ PrintExpr(Node->getSubExpr());
+}
+
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);
@@ -1378,7 +949,7 @@ static bool isImplicitSelf(const Expr *E) {
if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
if (const auto *PD = dyn_cast<ImplicitParamDecl>(DRE->getDecl())) {
if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf &&
- DRE->getLocStart().isInvalid())
+ DRE->getBeginLoc().isInvalid())
return true;
}
}
@@ -1424,7 +995,7 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
}
void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
- OS << PredefinedExpr::getIdentTypeName(Node->getIdentType());
+ OS << PredefinedExpr::getIdentKindName(Node->getIdentKind());
}
void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
@@ -1668,6 +1239,9 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
else
OS << "__alignof";
break;
+ case UETT_PreferredAlignOf:
+ OS << "__alignof";
+ break;
case UETT_VecStep:
OS << "vec_step";
break;
@@ -2808,8 +2382,9 @@ void Stmt::dumpPretty(const ASTContext &Context) const {
void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy, unsigned Indentation,
+ StringRef NL,
const ASTContext *Context) const {
- StmtPrinter P(OS, Helper, Policy, Indentation, Context);
+ StmtPrinter P(OS, Helper, Policy, Indentation, NL, Context);
P.Visit(const_cast<Stmt*>(this));
}
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 15653c4fd838..ec4dac03d497 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -189,7 +189,7 @@ namespace {
// store its nullness. Add a boolean here to match.
ID.AddBoolean(true);
}
- Hash.AddDeclarationName(Name);
+ Hash.AddDeclarationName(Name, TreatAsDecl);
}
void VisitIdentifierInfo(IdentifierInfo *II) override {
ID.AddBoolean(II);
@@ -467,6 +467,21 @@ void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
+void OMPClauseProfiler::VisitOMPUnifiedAddressClause(
+ const OMPUnifiedAddressClause *C) {}
+
+void OMPClauseProfiler::VisitOMPUnifiedSharedMemoryClause(
+ const OMPUnifiedSharedMemoryClause *C) {}
+
+void OMPClauseProfiler::VisitOMPReverseOffloadClause(
+ const OMPReverseOffloadClause *C) {}
+
+void OMPClauseProfiler::VisitOMPDynamicAllocatorsClause(
+ const OMPDynamicAllocatorsClause *C) {}
+
+void OMPClauseProfiler::VisitOMPAtomicDefaultMemOrderClause(
+ const OMPAtomicDefaultMemOrderClause *C) {}
+
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
VistOMPClauseWithPreInit(C);
if (auto *S = C->getChunkSize())
@@ -984,6 +999,10 @@ void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
+void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
VisitExpr(S);
if (!Canonical)
@@ -998,7 +1017,7 @@ void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
VisitExpr(S);
- ID.AddInteger(S->getIdentType());
+ ID.AddInteger(S->getIdentKind());
}
void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
diff --git a/lib/AST/TextNodeDumper.cpp b/lib/AST/TextNodeDumper.cpp
new file mode 100644
index 000000000000..b51a9006226a
--- /dev/null
+++ b/lib/AST/TextNodeDumper.cpp
@@ -0,0 +1,1168 @@
+//===--- TextNodeDumper.cpp - Printing of AST nodes -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements AST dumping of components of individual AST nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/TextNodeDumper.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/LocInfoType.h"
+
+using namespace clang;
+
+static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
+
+template <typename T>
+static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) {
+ const T *First = D->getFirstDecl();
+ if (First != D)
+ OS << " first " << First;
+}
+
+template <typename T>
+static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) {
+ const T *Prev = D->getPreviousDecl();
+ if (Prev)
+ OS << " prev " << Prev;
+}
+
+/// Dump the previous declaration in the redeclaration chain for a declaration,
+/// if any.
+static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
+ switch (D->getKind()) {
+#define DECL(DERIVED, BASE) \
+ case Decl::DERIVED: \
+ return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D));
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ }
+ llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
+}
+
+TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors,
+ const SourceManager *SM,
+ const PrintingPolicy &PrintPolicy,
+ const comments::CommandTraits *Traits)
+ : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors), SM(SM),
+ PrintPolicy(PrintPolicy), Traits(Traits) {}
+
+void TextNodeDumper::Visit(const comments::Comment *C,
+ const comments::FullComment *FC) {
+ if (!C) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
+
+ {
+ ColorScope Color(OS, ShowColors, CommentColor);
+ OS << C->getCommentKindName();
+ }
+ dumpPointer(C);
+ dumpSourceRange(C->getSourceRange());
+
+ ConstCommentVisitor<TextNodeDumper, void,
+ const comments::FullComment *>::visit(C, FC);
+}
+
+void TextNodeDumper::Visit(const Attr *A) {
+ {
+ ColorScope Color(OS, ShowColors, AttrColor);
+
+ switch (A->getKind()) {
+#define ATTR(X) \
+ case attr::X: \
+ OS << #X; \
+ break;
+#include "clang/Basic/AttrList.inc"
+ }
+ OS << "Attr";
+ }
+ dumpPointer(A);
+ dumpSourceRange(A->getRange());
+ if (A->isInherited())
+ OS << " Inherited";
+ if (A->isImplicit())
+ OS << " Implicit";
+
+ ConstAttrVisitor<TextNodeDumper>::Visit(A);
+}
+
+void TextNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
+ const Decl *From, StringRef Label) {
+ OS << "TemplateArgument";
+ if (R.isValid())
+ dumpSourceRange(R);
+
+ if (From)
+ dumpDeclRef(From, Label);
+
+ ConstTemplateArgumentVisitor<TextNodeDumper>::Visit(TA);
+}
+
+void TextNodeDumper::Visit(const Stmt *Node) {
+ if (!Node) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
+ {
+ ColorScope Color(OS, ShowColors, StmtColor);
+ OS << Node->getStmtClassName();
+ }
+ dumpPointer(Node);
+ dumpSourceRange(Node->getSourceRange());
+
+ if (const auto *E = dyn_cast<Expr>(Node)) {
+ dumpType(E->getType());
+
+ {
+ ColorScope Color(OS, ShowColors, ValueKindColor);
+ switch (E->getValueKind()) {
+ case VK_RValue:
+ break;
+ case VK_LValue:
+ OS << " lvalue";
+ break;
+ case VK_XValue:
+ OS << " xvalue";
+ break;
+ }
+ }
+
+ {
+ ColorScope Color(OS, ShowColors, ObjectKindColor);
+ switch (E->getObjectKind()) {
+ case OK_Ordinary:
+ break;
+ case OK_BitField:
+ OS << " bitfield";
+ break;
+ case OK_ObjCProperty:
+ OS << " objcproperty";
+ break;
+ case OK_ObjCSubscript:
+ OS << " objcsubscript";
+ break;
+ case OK_VectorComponent:
+ OS << " vectorcomponent";
+ break;
+ }
+ }
+ }
+
+ ConstStmtVisitor<TextNodeDumper>::Visit(Node);
+}
+
+void TextNodeDumper::Visit(const Type *T) {
+ if (!T) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
+ if (isa<LocInfoType>(T)) {
+ {
+ ColorScope Color(OS, ShowColors, TypeColor);
+ OS << "LocInfo Type";
+ }
+ dumpPointer(T);
+ return;
+ }
+
+ {
+ ColorScope Color(OS, ShowColors, TypeColor);
+ OS << T->getTypeClassName() << "Type";
+ }
+ dumpPointer(T);
+ OS << " ";
+ dumpBareType(QualType(T, 0), false);
+
+ QualType SingleStepDesugar =
+ T->getLocallyUnqualifiedSingleStepDesugaredType();
+ if (SingleStepDesugar != QualType(T, 0))
+ OS << " sugar";
+
+ if (T->isDependentType())
+ OS << " dependent";
+ else if (T->isInstantiationDependentType())
+ OS << " instantiation_dependent";
+
+ if (T->isVariablyModifiedType())
+ OS << " variably_modified";
+ if (T->containsUnexpandedParameterPack())
+ OS << " contains_unexpanded_pack";
+ if (T->isFromAST())
+ OS << " imported";
+
+ TypeVisitor<TextNodeDumper>::Visit(T);
+}
+
+void TextNodeDumper::Visit(QualType T) {
+ OS << "QualType";
+ dumpPointer(T.getAsOpaquePtr());
+ OS << " ";
+ dumpBareType(T, false);
+ OS << " " << T.split().Quals.getAsString();
+}
+
+void TextNodeDumper::Visit(const Decl *D) {
+ if (!D) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
+
+ {
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
+ OS << D->getDeclKindName() << "Decl";
+ }
+ dumpPointer(D);
+ if (D->getLexicalDeclContext() != D->getDeclContext())
+ OS << " parent " << cast<Decl>(D->getDeclContext());
+ dumpPreviousDecl(OS, D);
+ dumpSourceRange(D->getSourceRange());
+ OS << ' ';
+ dumpLocation(D->getLocation());
+ if (D->isFromASTFile())
+ OS << " imported";
+ if (Module *M = D->getOwningModule())
+ OS << " in " << M->getFullModuleName();
+ if (auto *ND = dyn_cast<NamedDecl>(D))
+ for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
+ const_cast<NamedDecl *>(ND)))
+ AddChild([=] { OS << "also in " << M->getFullModuleName(); });
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (ND->isHidden())
+ OS << " hidden";
+ if (D->isImplicit())
+ OS << " implicit";
+
+ if (D->isUsed())
+ OS << " used";
+ else if (D->isThisDeclarationReferenced())
+ OS << " referenced";
+
+ if (D->isInvalidDecl())
+ OS << " invalid";
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isConstexpr())
+ OS << " constexpr";
+}
+
+void TextNodeDumper::Visit(const CXXCtorInitializer *Init) {
+ OS << "CXXCtorInitializer";
+ if (Init->isAnyMemberInitializer()) {
+ OS << ' ';
+ dumpBareDeclRef(Init->getAnyMember());
+ } else if (Init->isBaseInitializer()) {
+ dumpType(QualType(Init->getBaseClass(), 0));
+ } else if (Init->isDelegatingInitializer()) {
+ dumpType(Init->getTypeSourceInfo()->getType());
+ } else {
+ llvm_unreachable("Unknown initializer type");
+ }
+}
+
+void TextNodeDumper::Visit(const BlockDecl::Capture &C) {
+ OS << "capture";
+ if (C.isByRef())
+ OS << " byref";
+ if (C.isNested())
+ OS << " nested";
+ if (C.getVariable()) {
+ OS << ' ';
+ dumpBareDeclRef(C.getVariable());
+ }
+}
+
+void TextNodeDumper::Visit(const OMPClause *C) {
+ if (!C) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>> OMPClause";
+ return;
+ }
+ {
+ ColorScope Color(OS, ShowColors, AttrColor);
+ StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
+ OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
+ << ClauseName.drop_front() << "Clause";
+ }
+ dumpPointer(C);
+ dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
+ if (C->isImplicit())
+ OS << " <implicit>";
+}
+
+void TextNodeDumper::dumpPointer(const void *Ptr) {
+ ColorScope Color(OS, ShowColors, AddressColor);
+ OS << ' ' << Ptr;
+}
+
+void TextNodeDumper::dumpLocation(SourceLocation Loc) {
+ if (!SM)
+ return;
+
+ ColorScope Color(OS, ShowColors, LocationColor);
+ SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
+
+ // The general format we print out is filename:line:col, but we drop pieces
+ // that haven't changed since the last loc printed.
+ PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
+
+ if (PLoc.isInvalid()) {
+ OS << "<invalid sloc>";
+ return;
+ }
+
+ if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
+ OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
+ << PLoc.getColumn();
+ LastLocFilename = PLoc.getFilename();
+ LastLocLine = PLoc.getLine();
+ } else if (PLoc.getLine() != LastLocLine) {
+ OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
+ LastLocLine = PLoc.getLine();
+ } else {
+ OS << "col" << ':' << PLoc.getColumn();
+ }
+}
+
+void TextNodeDumper::dumpSourceRange(SourceRange R) {
+ // Can't translate locations if a SourceManager isn't available.
+ if (!SM)
+ return;
+
+ OS << " <";
+ dumpLocation(R.getBegin());
+ if (R.getBegin() != R.getEnd()) {
+ OS << ", ";
+ dumpLocation(R.getEnd());
+ }
+ OS << ">";
+
+ // <t2.c:123:421[blah], t2.c:412:321>
+}
+
+void TextNodeDumper::dumpBareType(QualType T, bool Desugar) {
+ ColorScope Color(OS, ShowColors, TypeColor);
+
+ SplitQualType T_split = T.split();
+ OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'";
+
+ if (Desugar && !T.isNull()) {
+ // If the type is sugared, also dump a (shallow) desugared type.
+ SplitQualType D_split = T.getSplitDesugaredType();
+ if (T_split != D_split)
+ OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
+ }
+}
+
+void TextNodeDumper::dumpType(QualType T) {
+ OS << ' ';
+ dumpBareType(T);
+}
+
+void TextNodeDumper::dumpBareDeclRef(const Decl *D) {
+ if (!D) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>>";
+ return;
+ }
+
+ {
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
+ OS << D->getDeclKindName();
+ }
+ dumpPointer(D);
+
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ ColorScope Color(OS, ShowColors, DeclNameColor);
+ OS << " '" << ND->getDeclName() << '\'';
+ }
+
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ dumpType(VD->getType());
+}
+
+void TextNodeDumper::dumpName(const NamedDecl *ND) {
+ if (ND->getDeclName()) {
+ ColorScope Color(OS, ShowColors, DeclNameColor);
+ OS << ' ' << ND->getNameAsString();
+ }
+}
+
+void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) {
+ switch (AS) {
+ case AS_none:
+ break;
+ case AS_public:
+ OS << "public";
+ break;
+ case AS_protected:
+ OS << "protected";
+ break;
+ case AS_private:
+ OS << "private";
+ break;
+ }
+}
+
+void TextNodeDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
+ OS << "(CXXTemporary";
+ dumpPointer(Temporary);
+ OS << ")";
+}
+
+void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) {
+ if (!D)
+ return;
+
+ AddChild([=] {
+ if (!Label.empty())
+ OS << Label << ' ';
+ dumpBareDeclRef(D);
+ });
+}
+
+const char *TextNodeDumper::getCommandName(unsigned CommandID) {
+ if (Traits)
+ return Traits->getCommandInfo(CommandID)->Name;
+ const comments::CommandInfo *Info =
+ comments::CommandTraits::getBuiltinCommandInfo(CommandID);
+ if (Info)
+ return Info->Name;
+ return "<not a builtin command>";
+}
+
+void TextNodeDumper::visitTextComment(const comments::TextComment *C,
+ const comments::FullComment *) {
+ OS << " Text=\"" << C->getText() << "\"";
+}
+
+void TextNodeDumper::visitInlineCommandComment(
+ const comments::InlineCommandComment *C, const comments::FullComment *) {
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
+ switch (C->getRenderKind()) {
+ case comments::InlineCommandComment::RenderNormal:
+ OS << " RenderNormal";
+ break;
+ case comments::InlineCommandComment::RenderBold:
+ OS << " RenderBold";
+ break;
+ case comments::InlineCommandComment::RenderMonospaced:
+ OS << " RenderMonospaced";
+ break;
+ case comments::InlineCommandComment::RenderEmphasized:
+ OS << " RenderEmphasized";
+ break;
+ }
+
+ for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
+ OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
+}
+
+void TextNodeDumper::visitHTMLStartTagComment(
+ const comments::HTMLStartTagComment *C, const comments::FullComment *) {
+ OS << " Name=\"" << C->getTagName() << "\"";
+ if (C->getNumAttrs() != 0) {
+ OS << " Attrs: ";
+ for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
+ const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
+ OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
+ }
+ }
+ if (C->isSelfClosing())
+ OS << " SelfClosing";
+}
+
+void TextNodeDumper::visitHTMLEndTagComment(
+ const comments::HTMLEndTagComment *C, const comments::FullComment *) {
+ OS << " Name=\"" << C->getTagName() << "\"";
+}
+
+void TextNodeDumper::visitBlockCommandComment(
+ const comments::BlockCommandComment *C, const comments::FullComment *) {
+ OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
+ for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
+ OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
+}
+
+void TextNodeDumper::visitParamCommandComment(
+ const comments::ParamCommandComment *C, const comments::FullComment *FC) {
+ OS << " "
+ << comments::ParamCommandComment::getDirectionAsString(C->getDirection());
+
+ if (C->isDirectionExplicit())
+ OS << " explicitly";
+ else
+ OS << " implicitly";
+
+ if (C->hasParamName()) {
+ if (C->isParamIndexValid())
+ OS << " Param=\"" << C->getParamName(FC) << "\"";
+ else
+ OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
+ }
+
+ if (C->isParamIndexValid() && !C->isVarArgParam())
+ OS << " ParamIndex=" << C->getParamIndex();
+}
+
+void TextNodeDumper::visitTParamCommandComment(
+ const comments::TParamCommandComment *C, const comments::FullComment *FC) {
+ if (C->hasParamName()) {
+ if (C->isPositionValid())
+ OS << " Param=\"" << C->getParamName(FC) << "\"";
+ else
+ OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
+ }
+
+ if (C->isPositionValid()) {
+ OS << " Position=<";
+ for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
+ OS << C->getIndex(i);
+ if (i != e - 1)
+ OS << ", ";
+ }
+ OS << ">";
+ }
+}
+
+void TextNodeDumper::visitVerbatimBlockComment(
+ const comments::VerbatimBlockComment *C, const comments::FullComment *) {
+ OS << " Name=\"" << getCommandName(C->getCommandID())
+ << "\""
+ " CloseName=\""
+ << C->getCloseName() << "\"";
+}
+
+void TextNodeDumper::visitVerbatimBlockLineComment(
+ const comments::VerbatimBlockLineComment *C,
+ const comments::FullComment *) {
+ OS << " Text=\"" << C->getText() << "\"";
+}
+
+void TextNodeDumper::visitVerbatimLineComment(
+ const comments::VerbatimLineComment *C, const comments::FullComment *) {
+ OS << " Text=\"" << C->getText() << "\"";
+}
+
+void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) {
+ OS << " null";
+}
+
+void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
+ OS << " type";
+ dumpType(TA.getAsType());
+}
+
+void TextNodeDumper::VisitDeclarationTemplateArgument(
+ const TemplateArgument &TA) {
+ OS << " decl";
+ dumpDeclRef(TA.getAsDecl());
+}
+
+void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &) {
+ OS << " nullptr";
+}
+
+void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
+ OS << " integral " << TA.getAsIntegral();
+}
+
+void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
+ OS << " template ";
+ TA.getAsTemplate().dump(OS);
+}
+
+void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
+ const TemplateArgument &TA) {
+ OS << " template expansion ";
+ TA.getAsTemplateOrTemplatePattern().dump(OS);
+}
+
+void TextNodeDumper::VisitExpressionTemplateArgument(const TemplateArgument &) {
+ OS << " expr";
+}
+
+void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &) {
+ OS << " pack";
+}
+
+static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
+ if (Node->path_empty())
+ return;
+
+ OS << " (";
+ bool First = true;
+ for (CastExpr::path_const_iterator I = Node->path_begin(),
+ E = Node->path_end();
+ I != E; ++I) {
+ const CXXBaseSpecifier *Base = *I;
+ if (!First)
+ OS << " -> ";
+
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ if (Base->isVirtual())
+ OS << "virtual ";
+ OS << RD->getName();
+ First = false;
+ }
+
+ OS << ')';
+}
+
+void TextNodeDumper::VisitIfStmt(const IfStmt *Node) {
+ if (Node->hasInitStorage())
+ OS << " has_init";
+ if (Node->hasVarStorage())
+ OS << " has_var";
+ if (Node->hasElseStorage())
+ OS << " has_else";
+}
+
+void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) {
+ if (Node->hasInitStorage())
+ OS << " has_init";
+ if (Node->hasVarStorage())
+ OS << " has_var";
+}
+
+void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {
+ if (Node->hasVarStorage())
+ OS << " has_var";
+}
+
+void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
+ OS << " '" << Node->getName() << "'";
+}
+
+void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {
+ OS << " '" << Node->getLabel()->getName() << "'";
+ dumpPointer(Node->getLabel());
+}
+
+void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
+ if (Node->caseStmtIsGNURange())
+ OS << " gnu_range";
+}
+
+void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
+ if (Node->usesADL())
+ OS << " adl";
+}
+
+void TextNodeDumper::VisitCastExpr(const CastExpr *Node) {
+ OS << " <";
+ {
+ ColorScope Color(OS, ShowColors, CastColor);
+ OS << Node->getCastKindName();
+ }
+ dumpBasePath(OS, Node);
+ OS << ">";
+}
+
+void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) {
+ VisitCastExpr(Node);
+ if (Node->isPartOfExplicitCast())
+ OS << " part_of_explicit_cast";
+}
+
+void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
+ OS << " ";
+ dumpBareDeclRef(Node->getDecl());
+ if (Node->getDecl() != Node->getFoundDecl()) {
+ OS << " (";
+ dumpBareDeclRef(Node->getFoundDecl());
+ OS << ")";
+ }
+}
+
+void TextNodeDumper::VisitUnresolvedLookupExpr(
+ const UnresolvedLookupExpr *Node) {
+ OS << " (";
+ if (!Node->requiresADL())
+ OS << "no ";
+ OS << "ADL) = '" << Node->getName() << '\'';
+
+ UnresolvedLookupExpr::decls_iterator I = Node->decls_begin(),
+ E = Node->decls_end();
+ if (I == E)
+ OS << " empty";
+ for (; I != E; ++I)
+ dumpPointer(*I);
+}
+
+void TextNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
+ {
+ ColorScope Color(OS, ShowColors, DeclKindNameColor);
+ OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
+ }
+ OS << "='" << *Node->getDecl() << "'";
+ dumpPointer(Node->getDecl());
+ if (Node->isFreeIvar())
+ OS << " isFreeIvar";
+}
+
+void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
+ OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind());
+}
+
+void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << " " << Node->getValue();
+}
+
+void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
+ bool isSigned = Node->getType()->isSignedIntegerType();
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << " " << Node->getValue().toString(10, isSigned);
+}
+
+void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << " " << Node->getValueAsString(/*Radix=*/10);
+}
+
+void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << " " << Node->getValueAsApproximateDouble();
+}
+
+void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) {
+ ColorScope Color(OS, ShowColors, ValueColor);
+ OS << " ";
+ Str->outputString(OS);
+}
+
+void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
+ if (auto *Field = ILE->getInitializedFieldInUnion()) {
+ OS << " field ";
+ dumpBareDeclRef(Field);
+ }
+}
+
+void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
+ OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '"
+ << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
+ if (!Node->canOverflow())
+ OS << " cannot overflow";
+}
+
+void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
+ const UnaryExprOrTypeTraitExpr *Node) {
+ switch (Node->getKind()) {
+ case UETT_SizeOf:
+ OS << " sizeof";
+ break;
+ case UETT_AlignOf:
+ OS << " alignof";
+ break;
+ case UETT_VecStep:
+ OS << " vec_step";
+ break;
+ case UETT_OpenMPRequiredSimdAlign:
+ OS << " __builtin_omp_required_simd_align";
+ break;
+ case UETT_PreferredAlignOf:
+ OS << " __alignof";
+ break;
+ }
+ if (Node->isArgumentType())
+ dumpType(Node->getArgumentType());
+}
+
+void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) {
+ OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
+ dumpPointer(Node->getMemberDecl());
+}
+
+void TextNodeDumper::VisitExtVectorElementExpr(
+ const ExtVectorElementExpr *Node) {
+ OS << " " << Node->getAccessor().getNameStart();
+}
+
+void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) {
+ OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
+}
+
+void TextNodeDumper::VisitCompoundAssignOperator(
+ const CompoundAssignOperator *Node) {
+ OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
+ << "' ComputeLHSTy=";
+ dumpBareType(Node->getComputationLHSType());
+ OS << " ComputeResultTy=";
+ dumpBareType(Node->getComputationResultType());
+}
+
+void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
+ OS << " " << Node->getLabel()->getName();
+ dumpPointer(Node->getLabel());
+}
+
+void TextNodeDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
+ OS << " " << Node->getCastName() << "<"
+ << Node->getTypeAsWritten().getAsString() << ">"
+ << " <" << Node->getCastKindName();
+ dumpBasePath(OS, Node);
+ OS << ">";
+}
+
+void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
+ OS << " " << (Node->getValue() ? "true" : "false");
+}
+
+void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
+ OS << " this";
+}
+
+void TextNodeDumper::VisitCXXFunctionalCastExpr(
+ const CXXFunctionalCastExpr *Node) {
+ OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <"
+ << Node->getCastKindName() << ">";
+}
+
+void TextNodeDumper::VisitCXXUnresolvedConstructExpr(
+ const CXXUnresolvedConstructExpr *Node) {
+ dumpType(Node->getTypeAsWritten());
+ if (Node->isListInitialization())
+ OS << " list";
+}
+
+void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
+ CXXConstructorDecl *Ctor = Node->getConstructor();
+ dumpType(Ctor->getType());
+ if (Node->isElidable())
+ OS << " elidable";
+ if (Node->isListInitialization())
+ OS << " list";
+ if (Node->isStdInitListInitialization())
+ OS << " std::initializer_list";
+ if (Node->requiresZeroInitialization())
+ OS << " zeroing";
+}
+
+void TextNodeDumper::VisitCXXBindTemporaryExpr(
+ const CXXBindTemporaryExpr *Node) {
+ OS << " ";
+ dumpCXXTemporary(Node->getTemporary());
+}
+
+void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
+ if (Node->isGlobalNew())
+ OS << " global";
+ if (Node->isArray())
+ OS << " array";
+ if (Node->getOperatorNew()) {
+ OS << ' ';
+ dumpBareDeclRef(Node->getOperatorNew());
+ }
+ // We could dump the deallocation function used in case of error, but it's
+ // usually not that interesting.
+}
+
+void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
+ if (Node->isGlobalDelete())
+ OS << " global";
+ if (Node->isArrayForm())
+ OS << " array";
+ if (Node->getOperatorDelete()) {
+ OS << ' ';
+ dumpBareDeclRef(Node->getOperatorDelete());
+ }
+}
+
+void TextNodeDumper::VisitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *Node) {
+ if (const ValueDecl *VD = Node->getExtendingDecl()) {
+ OS << " extended by ";
+ dumpBareDeclRef(VD);
+ }
+}
+
+void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
+ for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
+ dumpDeclRef(Node->getObject(i), "cleanup");
+}
+
+void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
+ dumpPointer(Node->getPack());
+ dumpName(Node->getPack());
+}
+
+void TextNodeDumper::VisitCXXDependentScopeMemberExpr(
+ const CXXDependentScopeMemberExpr *Node) {
+ OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
+}
+
+void TextNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
+ OS << " selector=";
+ Node->getSelector().print(OS);
+ switch (Node->getReceiverKind()) {
+ case ObjCMessageExpr::Instance:
+ break;
+
+ case ObjCMessageExpr::Class:
+ OS << " class=";
+ dumpBareType(Node->getClassReceiver());
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ OS << " super (instance)";
+ break;
+
+ case ObjCMessageExpr::SuperClass:
+ OS << " super (class)";
+ break;
+ }
+}
+
+void TextNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
+ if (auto *BoxingMethod = Node->getBoxingMethod()) {
+ OS << " selector=";
+ BoxingMethod->getSelector().print(OS);
+ }
+}
+
+void TextNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
+ if (!Node->getCatchParamDecl())
+ OS << " catch all";
+}
+
+void TextNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
+ dumpType(Node->getEncodedType());
+}
+
+void TextNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
+ OS << " ";
+ Node->getSelector().print(OS);
+}
+
+void TextNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
+ OS << ' ' << *Node->getProtocol();
+}
+
+void TextNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
+ if (Node->isImplicitProperty()) {
+ OS << " Kind=MethodRef Getter=\"";
+ if (Node->getImplicitPropertyGetter())
+ Node->getImplicitPropertyGetter()->getSelector().print(OS);
+ else
+ OS << "(null)";
+
+ OS << "\" Setter=\"";
+ if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
+ Setter->getSelector().print(OS);
+ else
+ OS << "(null)";
+ OS << "\"";
+ } else {
+ OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty()
+ << '"';
+ }
+
+ if (Node->isSuperReceiver())
+ OS << " super";
+
+ OS << " Messaging=";
+ if (Node->isMessagingGetter() && Node->isMessagingSetter())
+ OS << "Getter&Setter";
+ else if (Node->isMessagingGetter())
+ OS << "Getter";
+ else if (Node->isMessagingSetter())
+ OS << "Setter";
+}
+
+void TextNodeDumper::VisitObjCSubscriptRefExpr(
+ const ObjCSubscriptRefExpr *Node) {
+ if (Node->isArraySubscriptRefExpr())
+ OS << " Kind=ArraySubscript GetterForArray=\"";
+ else
+ OS << " Kind=DictionarySubscript GetterForDictionary=\"";
+ if (Node->getAtIndexMethodDecl())
+ Node->getAtIndexMethodDecl()->getSelector().print(OS);
+ else
+ OS << "(null)";
+
+ if (Node->isArraySubscriptRefExpr())
+ OS << "\" SetterForArray=\"";
+ else
+ OS << "\" SetterForDictionary=\"";
+ if (Node->setAtIndexMethodDecl())
+ Node->setAtIndexMethodDecl()->getSelector().print(OS);
+ else
+ OS << "(null)";
+}
+
+void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
+ OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
+}
+
+void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
+ if (T->isSpelledAsLValue())
+ OS << " written as lvalue reference";
+}
+
+void TextNodeDumper::VisitArrayType(const ArrayType *T) {
+ switch (T->getSizeModifier()) {
+ case ArrayType::Normal:
+ break;
+ case ArrayType::Static:
+ OS << " static";
+ break;
+ case ArrayType::Star:
+ OS << " *";
+ break;
+ }
+ OS << " " << T->getIndexTypeQualifiers().getAsString();
+}
+
+void TextNodeDumper::VisitConstantArrayType(const ConstantArrayType *T) {
+ OS << " " << T->getSize();
+ VisitArrayType(T);
+}
+
+void TextNodeDumper::VisitVariableArrayType(const VariableArrayType *T) {
+ OS << " ";
+ dumpSourceRange(T->getBracketsRange());
+ VisitArrayType(T);
+}
+
+void TextNodeDumper::VisitDependentSizedArrayType(
+ const DependentSizedArrayType *T) {
+ VisitArrayType(T);
+ OS << " ";
+ dumpSourceRange(T->getBracketsRange());
+}
+
+void TextNodeDumper::VisitDependentSizedExtVectorType(
+ const DependentSizedExtVectorType *T) {
+ OS << " ";
+ dumpLocation(T->getAttributeLoc());
+}
+
+void TextNodeDumper::VisitVectorType(const VectorType *T) {
+ switch (T->getVectorKind()) {
+ case VectorType::GenericVector:
+ break;
+ case VectorType::AltiVecVector:
+ OS << " altivec";
+ break;
+ case VectorType::AltiVecPixel:
+ OS << " altivec pixel";
+ break;
+ case VectorType::AltiVecBool:
+ OS << " altivec bool";
+ break;
+ case VectorType::NeonVector:
+ OS << " neon";
+ break;
+ case VectorType::NeonPolyVector:
+ OS << " neon poly";
+ break;
+ }
+ OS << " " << T->getNumElements();
+}
+
+void TextNodeDumper::VisitFunctionType(const FunctionType *T) {
+ auto EI = T->getExtInfo();
+ if (EI.getNoReturn())
+ OS << " noreturn";
+ if (EI.getProducesResult())
+ OS << " produces_result";
+ if (EI.getHasRegParm())
+ OS << " regparm " << EI.getRegParm();
+ OS << " " << FunctionType::getNameForCallConv(EI.getCC());
+}
+
+void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
+ auto EPI = T->getExtProtoInfo();
+ if (EPI.HasTrailingReturn)
+ OS << " trailing_return";
+ if (T->isConst())
+ OS << " const";
+ if (T->isVolatile())
+ OS << " volatile";
+ if (T->isRestrict())
+ OS << " restrict";
+ switch (EPI.RefQualifier) {
+ case RQ_None:
+ break;
+ case RQ_LValue:
+ OS << " &";
+ break;
+ case RQ_RValue:
+ OS << " &&";
+ break;
+ }
+ // FIXME: Exception specification.
+ // FIXME: Consumed parameters.
+ VisitFunctionType(T);
+}
+
+void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+ dumpDeclRef(T->getDecl());
+}
+
+void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
+ dumpDeclRef(T->getDecl());
+}
+
+void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
+ switch (T->getUTTKind()) {
+ case UnaryTransformType::EnumUnderlyingType:
+ OS << " underlying_type";
+ break;
+ }
+}
+
+void TextNodeDumper::VisitTagType(const TagType *T) {
+ dumpDeclRef(T->getDecl());
+}
+
+void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+ OS << " depth " << T->getDepth() << " index " << T->getIndex();
+ if (T->isParameterPack())
+ OS << " pack";
+ dumpDeclRef(T->getDecl());
+}
+
+void TextNodeDumper::VisitAutoType(const AutoType *T) {
+ if (T->isDecltypeAuto())
+ OS << " decltype(auto)";
+ if (!T->isDeduced())
+ OS << " undeduced";
+}
+
+void TextNodeDumper::VisitTemplateSpecializationType(
+ const TemplateSpecializationType *T) {
+ if (T->isTypeAlias())
+ OS << " alias";
+ OS << " ";
+ T->getTemplateName().dump(OS);
+}
+
+void TextNodeDumper::VisitInjectedClassNameType(
+ const InjectedClassNameType *T) {
+ dumpDeclRef(T->getDecl());
+}
+
+void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+ dumpDeclRef(T->getDecl());
+}
+
+void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) {
+ if (auto N = T->getNumExpansions())
+ OS << " expansions " << *N;
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index f79a59712a41..0dbc88c04521 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -291,6 +291,14 @@ QualType QualType::getSingleStepDesugaredTypeImpl(QualType type,
return Context.getQualifiedType(desugar, split.Quals);
}
+// Check that no type class is polymorphic. LLVM style RTTI should be used
+// instead. If absolutely needed an exception can still be added here by
+// defining the appropriate macro (but please don't do this).
+#define TYPE(CLASS, BASE) \
+ static_assert(!std::is_polymorphic<CLASS##Type>::value, \
+ #CLASS "Type should not be polymorphic!");
+#include "clang/AST/TypeNodes.def"
+
QualType Type::getLocallyUnqualifiedSingleStepDesugaredType() const {
switch (getTypeClass()) {
#define ABSTRACT_TYPE(Class, Parent)
@@ -592,28 +600,6 @@ bool Type::isObjCClassOrClassKindOfType() const {
return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType();
}
-/// Was this type written with the special inert-in-MRC __unsafe_unretained
-/// qualifier?
-///
-/// This approximates the answer to the following question: if this
-/// translation unit were compiled in ARC, would this type be qualified
-/// with __unsafe_unretained?
-bool Type::isObjCInertUnsafeUnretainedType() const {
- const Type *cur = this;
- while (true) {
- if (const auto attributed = dyn_cast<AttributedType>(cur)) {
- if (attributed->getAttrKind() ==
- AttributedType::attr_objc_inert_unsafe_unretained)
- return true;
- }
-
- // Single-step desugar until we run out of sugar.
- QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();
- if (next.getTypePtr() == cur) return false;
- cur = next.getTypePtr();
- }
-}
-
ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,
QualType can,
ArrayRef<ObjCProtocolDecl *> protocols)
@@ -1641,6 +1627,16 @@ TagDecl *Type::getAsTagDecl() const {
return nullptr;
}
+bool Type::hasAttr(attr::Kind AK) const {
+ const Type *Cur = this;
+ while (const auto *AT = Cur->getAs<AttributedType>()) {
+ if (AT->getAttrKind() == AK)
+ return true;
+ Cur = AT->getEquivalentType().getTypePtr();
+ }
+ return false;
+}
+
namespace {
class GetContainedDeducedTypeVisitor :
@@ -1977,6 +1973,7 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer;
if (BT->isInteger()) return STK_Integral;
if (BT->isFloatingPoint()) return STK_Floating;
+ if (BT->isFixedPointType()) return STK_FixedPoint;
llvm_unreachable("unknown scalar builtin type");
} else if (isa<PointerType>(T)) {
return STK_CPointer;
@@ -2604,7 +2601,8 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType(
: TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true,
/*VariablyModified=*/false,
NNS && NNS->containsUnexpandedParameterPack()),
- NNS(NNS), Name(Name), NumArgs(Args.size()) {
+ NNS(NNS), Name(Name) {
+ DependentTemplateSpecializationTypeBits.NumArgs = Args.size();
assert((!NNS || NNS->isDependent()) &&
"DependentTemplateSpecializatonType requires dependent qualifier");
TemplateArgument *ArgBuffer = getArgBuffer();
@@ -2796,6 +2794,10 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "reserve_id_t";
case OMPArraySection:
return "<OpenMP array section type>";
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case Id: \
+ return #ExtType;
+#include "clang/Basic/OpenCLExtensionTypes.def"
}
llvm_unreachable("Invalid builtin type.");
@@ -2830,6 +2832,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86RegCall : return "regcall";
case CC_AAPCS: return "aapcs";
case CC_AAPCS_VFP: return "aapcs-vfp";
+ case CC_AArch64VectorCall: return "aarch64_vector_pcs";
case CC_IntelOclBicc: return "intel_ocl_bicc";
case CC_SpirFunction: return "spir_function";
case CC_OpenCLKernel: return "opencl_kernel";
@@ -2844,24 +2847,28 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType canonical,
const ExtProtoInfo &epi)
- : FunctionType(FunctionProto, result, canonical,
- result->isDependentType(),
+ : FunctionType(FunctionProto, result, canonical, result->isDependentType(),
result->isInstantiationDependentType(),
result->isVariablyModifiedType(),
- result->containsUnexpandedParameterPack(), epi.ExtInfo),
- NumParams(params.size()),
- NumExceptions(epi.ExceptionSpec.Exceptions.size()),
- ExceptionSpecType(epi.ExceptionSpec.Type),
- HasExtParameterInfos(epi.ExtParameterInfos != nullptr),
- Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) {
- assert(NumParams == params.size() && "function has too many parameters");
-
- FunctionTypeBits.TypeQuals = epi.TypeQuals;
+ result->containsUnexpandedParameterPack(), epi.ExtInfo) {
+ FunctionTypeBits.FastTypeQuals = epi.TypeQuals.getFastQualifiers();
FunctionTypeBits.RefQualifier = epi.RefQualifier;
+ FunctionTypeBits.NumParams = params.size();
+ assert(getNumParams() == params.size() && "NumParams overflow!");
+ FunctionTypeBits.ExceptionSpecType = epi.ExceptionSpec.Type;
+ FunctionTypeBits.HasExtParameterInfos = !!epi.ExtParameterInfos;
+ FunctionTypeBits.Variadic = epi.Variadic;
+ FunctionTypeBits.HasTrailingReturn = epi.HasTrailingReturn;
+
+ // Fill in the extra trailing bitfields if present.
+ if (hasExtraBitfields(epi.ExceptionSpec.Type)) {
+ auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>();
+ ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size();
+ }
// Fill in the trailing argument array.
- auto *argSlot = reinterpret_cast<QualType *>(this+1);
- for (unsigned i = 0; i != NumParams; ++i) {
+ auto *argSlot = getTrailingObjects<QualType>();
+ for (unsigned i = 0; i != getNumParams(); ++i) {
if (params[i]->isDependentType())
setDependent();
else if (params[i]->isInstantiationDependentType())
@@ -2873,9 +2880,11 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
argSlot[i] = params[i];
}
+ // Fill in the exception type array if present.
if (getExceptionSpecType() == EST_Dynamic) {
- // Fill in the exception array.
- QualType *exnSlot = argSlot + NumParams;
+ assert(hasExtraBitfields() && "missing trailing extra bitfields!");
+ auto *exnSlot =
+ reinterpret_cast<QualType *>(getTrailingObjects<ExceptionType>());
unsigned I = 0;
for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {
// Note that, before C++17, a dependent exception specification does
@@ -2889,14 +2898,15 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
exnSlot[I++] = ExceptionType;
}
- } else if (isComputedNoexcept(getExceptionSpecType())) {
+ }
+ // Fill in the Expr * in the exception specification if present.
+ else if (isComputedNoexcept(getExceptionSpecType())) {
assert(epi.ExceptionSpec.NoexceptExpr && "computed noexcept with no expr");
assert((getExceptionSpecType() == EST_DependentNoexcept) ==
epi.ExceptionSpec.NoexceptExpr->isValueDependent());
// Store the noexcept expression and context.
- auto **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams);
- *noexSlot = epi.ExceptionSpec.NoexceptExpr;
+ *getTrailingObjects<Expr *>() = epi.ExceptionSpec.NoexceptExpr;
if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||
epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
@@ -2904,10 +2914,12 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
- } else if (getExceptionSpecType() == EST_Uninstantiated) {
+ }
+ // Fill in the FunctionDecl * in the exception specification if present.
+ else if (getExceptionSpecType() == EST_Uninstantiated) {
// Store the function decl from which we will resolve our
// exception specification.
- auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = getTrailingObjects<FunctionDecl *>();
slot[0] = epi.ExceptionSpec.SourceDecl;
slot[1] = epi.ExceptionSpec.SourceTemplate;
// This exception specification doesn't make the type dependent, because
@@ -2915,7 +2927,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
} else if (getExceptionSpecType() == EST_Unevaluated) {
// Store the function decl from which we will resolve our
// exception specification.
- auto **slot = reinterpret_cast<FunctionDecl **>(argSlot + NumParams);
+ auto **slot = getTrailingObjects<FunctionDecl *>();
slot[0] = epi.ExceptionSpec.SourceDecl;
}
@@ -2932,12 +2944,19 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
setDependent();
}
+ // Fill in the extra parameter info if present.
if (epi.ExtParameterInfos) {
- auto *extParamInfos =
- const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer());
- for (unsigned i = 0; i != NumParams; ++i)
+ auto *extParamInfos = getTrailingObjects<ExtParameterInfo>();
+ for (unsigned i = 0; i != getNumParams(); ++i)
extParamInfos[i] = epi.ExtParameterInfos[i];
}
+
+ if (epi.TypeQuals.hasNonFastQualifiers()) {
+ FunctionTypeBits.HasExtQuals = 1;
+ *getTrailingObjects<Qualifiers>() = epi.TypeQuals;
+ } else {
+ FunctionTypeBits.HasExtQuals = 0;
+ }
}
bool FunctionProtoType::hasDependentExceptionSpec() const {
@@ -2981,7 +3000,7 @@ CanThrowResult FunctionProtoType::canThrow() const {
case EST_Dynamic:
// A dynamic exception specification is throwing unless every exception
// type is an (unexpanded) pack expansion type.
- for (unsigned I = 0, N = NumExceptions; I != N; ++I)
+ for (unsigned I = 0; I != getNumExceptions(); ++I)
if (!getExceptionType(I)->getAs<PackExpansionType>())
return CT_Can;
return CT_Dependent;
@@ -3029,14 +3048,13 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
// shortcut, use one AddInteger call instead of four for the next four
// fields.
assert(!(unsigned(epi.Variadic) & ~1) &&
- !(unsigned(epi.TypeQuals) & ~255) &&
!(unsigned(epi.RefQualifier) & ~3) &&
!(unsigned(epi.ExceptionSpec.Type) & ~15) &&
"Values larger than expected.");
ID.AddInteger(unsigned(epi.Variadic) +
- (epi.TypeQuals << 1) +
- (epi.RefQualifier << 9) +
- (epi.ExceptionSpec.Type << 11));
+ (epi.RefQualifier << 1) +
+ (epi.ExceptionSpec.Type << 3));
+ ID.Add(epi.TypeQuals);
if (epi.ExceptionSpec.Type == EST_Dynamic) {
for (QualType Ex : epi.ExceptionSpec.Exceptions)
ID.AddPointer(Ex.getAsOpaquePtr());
@@ -3056,8 +3074,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) {
- Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(),
- Ctx, isCanonicalUnqualified());
+ Profile(ID, getReturnType(), param_type_begin(), getNumParams(),
+ getExtProtoInfo(), Ctx, isCanonicalUnqualified());
}
QualType TypedefType::desugar() const {
@@ -3154,118 +3172,81 @@ bool TagType::isBeingDefined() const {
}
bool RecordType::hasConstFields() const {
- for (FieldDecl *FD : getDecl()->fields()) {
- QualType FieldTy = FD->getType();
- if (FieldTy.isConstQualified())
- return true;
- FieldTy = FieldTy.getCanonicalType();
- if (const auto *FieldRecTy = FieldTy->getAs<RecordType>())
- if (FieldRecTy->hasConstFields())
+ std::vector<const RecordType*> RecordTypeList;
+ RecordTypeList.push_back(this);
+ unsigned NextToCheckIndex = 0;
+
+ while (RecordTypeList.size() > NextToCheckIndex) {
+ for (FieldDecl *FD :
+ RecordTypeList[NextToCheckIndex]->getDecl()->fields()) {
+ QualType FieldTy = FD->getType();
+ if (FieldTy.isConstQualified())
return true;
+ FieldTy = FieldTy.getCanonicalType();
+ if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) {
+ if (llvm::find(RecordTypeList, FieldRecTy) == RecordTypeList.end())
+ RecordTypeList.push_back(FieldRecTy);
+ }
+ }
+ ++NextToCheckIndex;
}
return false;
}
bool AttributedType::isQualifier() const {
+ // FIXME: Generate this with TableGen.
switch (getAttrKind()) {
// These are type qualifiers in the traditional C sense: they annotate
// something about a specific value/variable of a type. (They aren't
// always part of the canonical type, though.)
- case AttributedType::attr_address_space:
- case AttributedType::attr_objc_gc:
- case AttributedType::attr_objc_ownership:
- case AttributedType::attr_objc_inert_unsafe_unretained:
- case AttributedType::attr_nonnull:
- case AttributedType::attr_nullable:
- case AttributedType::attr_null_unspecified:
- case AttributedType::attr_lifetimebound:
+ case attr::ObjCGC:
+ case attr::ObjCOwnership:
+ case attr::ObjCInertUnsafeUnretained:
+ case attr::TypeNonNull:
+ case attr::TypeNullable:
+ case attr::TypeNullUnspecified:
+ case attr::LifetimeBound:
return true;
- // These aren't qualifiers; they rewrite the modified type to be a
- // semantically different type.
- case AttributedType::attr_regparm:
- case AttributedType::attr_vector_size:
- case AttributedType::attr_neon_vector_type:
- case AttributedType::attr_neon_polyvector_type:
- case AttributedType::attr_pcs:
- case AttributedType::attr_pcs_vfp:
- case AttributedType::attr_noreturn:
- case AttributedType::attr_cdecl:
- case AttributedType::attr_fastcall:
- case AttributedType::attr_stdcall:
- case AttributedType::attr_thiscall:
- case AttributedType::attr_regcall:
- case AttributedType::attr_pascal:
- case AttributedType::attr_swiftcall:
- case AttributedType::attr_vectorcall:
- case AttributedType::attr_inteloclbicc:
- case AttributedType::attr_preserve_most:
- case AttributedType::attr_preserve_all:
- case AttributedType::attr_ms_abi:
- case AttributedType::attr_sysv_abi:
- case AttributedType::attr_ptr32:
- case AttributedType::attr_ptr64:
- case AttributedType::attr_sptr:
- case AttributedType::attr_uptr:
- case AttributedType::attr_objc_kindof:
- case AttributedType::attr_ns_returns_retained:
- case AttributedType::attr_nocf_check:
+ // All other type attributes aren't qualifiers; they rewrite the modified
+ // type to be a semantically different type.
+ default:
return false;
}
- llvm_unreachable("bad attributed type kind");
}
bool AttributedType::isMSTypeSpec() const {
+ // FIXME: Generate this with TableGen?
switch (getAttrKind()) {
- default: return false;
- case attr_ptr32:
- case attr_ptr64:
- case attr_sptr:
- case attr_uptr:
+ default: return false;
+ case attr::Ptr32:
+ case attr::Ptr64:
+ case attr::SPtr:
+ case attr::UPtr:
return true;
}
llvm_unreachable("invalid attr kind");
}
bool AttributedType::isCallingConv() const {
+ // FIXME: Generate this with TableGen.
switch (getAttrKind()) {
- case attr_ptr32:
- case attr_ptr64:
- case attr_sptr:
- case attr_uptr:
- case attr_address_space:
- case attr_regparm:
- case attr_vector_size:
- case attr_neon_vector_type:
- case attr_neon_polyvector_type:
- case attr_objc_gc:
- case attr_objc_ownership:
- case attr_objc_inert_unsafe_unretained:
- case attr_noreturn:
- case attr_nonnull:
- case attr_ns_returns_retained:
- case attr_nullable:
- case attr_null_unspecified:
- case attr_objc_kindof:
- case attr_nocf_check:
- case attr_lifetimebound:
- return false;
-
- case attr_pcs:
- case attr_pcs_vfp:
- case attr_cdecl:
- case attr_fastcall:
- case attr_stdcall:
- case attr_thiscall:
- case attr_regcall:
- case attr_swiftcall:
- case attr_vectorcall:
- case attr_pascal:
- case attr_ms_abi:
- case attr_sysv_abi:
- case attr_inteloclbicc:
- case attr_preserve_most:
- case attr_preserve_all:
+ default: return false;
+ case attr::Pcs:
+ case attr::CDecl:
+ case attr::FastCall:
+ case attr::StdCall:
+ case attr::ThisCall:
+ case attr::RegCall:
+ case attr::SwiftCall:
+ case attr::VectorCall:
+ case attr::AArch64VectorPcs:
+ case attr::Pascal:
+ case attr::MSABI:
+ case attr::SysVABI:
+ case attr::IntelOclBicc:
+ case attr::PreserveMost:
+ case attr::PreserveAll:
return true;
}
llvm_unreachable("invalid attr kind");
@@ -3284,11 +3265,12 @@ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
QualType Canon,
const TemplateArgument &ArgPack)
: Type(SubstTemplateTypeParmPack, Canon, true, true, false, true),
- Replaced(Param),
- Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()) {}
+ Replaced(Param), Arguments(ArgPack.pack_begin()) {
+ SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size();
+}
TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
- return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
+ return TemplateArgument(llvm::makeArrayRef(Arguments, getNumArgs()));
}
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
@@ -3335,8 +3317,10 @@ TemplateSpecializationType(TemplateName T,
Canon.isNull()? true : Canon->isDependentType(),
Canon.isNull()? true : Canon->isInstantiationDependentType(),
false,
- T.containsUnexpandedParameterPack()),
- Template(T), NumArgs(Args.size()), TypeAlias(!AliasedType.isNull()) {
+ T.containsUnexpandedParameterPack()), Template(T) {
+ TemplateSpecializationTypeBits.NumArgs = Args.size();
+ TemplateSpecializationTypeBits.TypeAlias = !AliasedType.isNull();
+
assert(!T.getAsDependentTemplateName() &&
"Use DependentTemplateSpecializationType for dependent template-name");
assert((T.getKind() == TemplateName::Template ||
@@ -3365,7 +3349,7 @@ TemplateSpecializationType(TemplateName T,
}
// Store the aliased type if this is a type alias template specialization.
- if (TypeAlias) {
+ if (isTypeAlias()) {
auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
*reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType;
}
@@ -3708,23 +3692,18 @@ LinkageInfo Type::getLinkageAndVisibility() const {
return LinkageComputer{}.getTypeLinkageAndVisibility(this);
}
-Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const {
- QualType type(this, 0);
- do {
+Optional<NullabilityKind>
+Type::getNullability(const ASTContext &Context) const {
+ QualType Type(this, 0);
+ while (const auto *AT = Type->getAs<AttributedType>()) {
// Check whether this is an attributed type with nullability
// information.
- if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) {
- if (auto nullability = attributed->getImmediateNullability())
- return nullability;
- }
+ if (auto Nullability = AT->getImmediateNullability())
+ return Nullability;
- // Desugar the type. If desugaring does nothing, we're done.
- QualType desugared = type.getSingleStepDesugaredType(context);
- if (desugared.getTypePtr() == type.getTypePtr())
- return None;
-
- type = desugared;
- } while (true);
+ Type = AT->getEquivalentType();
+ }
+ return None;
}
bool Type::canHaveNullability(bool ResultIfUnknown) const {
@@ -3796,6 +3775,9 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
@@ -3837,12 +3819,13 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
llvm_unreachable("bad type kind!");
}
-llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const {
- if (getAttrKind() == AttributedType::attr_nonnull)
+llvm::Optional<NullabilityKind>
+AttributedType::getImmediateNullability() const {
+ if (getAttrKind() == attr::TypeNonNull)
return NullabilityKind::NonNull;
- if (getAttrKind() == AttributedType::attr_nullable)
+ if (getAttrKind() == attr::TypeNullable)
return NullabilityKind::Nullable;
- if (getAttrKind() == AttributedType::attr_null_unspecified)
+ if (getAttrKind() == attr::TypeNullUnspecified)
return NullabilityKind::Unspecified;
return None;
}
@@ -4032,17 +4015,26 @@ CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
}
void clang::FixedPointValueToString(SmallVectorImpl<char> &Str,
- const llvm::APSInt &Val, unsigned Scale,
- unsigned Radix) {
- llvm::APSInt ScaleVal = llvm::APSInt::getUnsigned(1ULL << Scale);
- llvm::APSInt IntPart = Val / ScaleVal;
- llvm::APSInt FractPart = Val % ScaleVal;
- llvm::APSInt RadixInt = llvm::APSInt::getUnsigned(Radix);
-
- IntPart.toString(Str, Radix);
+ llvm::APSInt Val, unsigned Scale) {
+ if (Val.isSigned() && Val.isNegative() && Val != -Val) {
+ Val = -Val;
+ Str.push_back('-');
+ }
+
+ llvm::APSInt IntPart = Val >> Scale;
+
+ // Add 4 digits to hold the value after multiplying 10 (the radix)
+ unsigned Width = Val.getBitWidth() + 4;
+ llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width);
+ llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width);
+ llvm::APInt RadixInt = llvm::APInt(Width, 10);
+
+ IntPart.toString(Str, /*radix=*/10);
Str.push_back('.');
do {
- (FractPart * RadixInt / ScaleVal).toString(Str, Radix);
- FractPart = (FractPart * RadixInt) % ScaleVal;
- } while (FractPart.getExtValue());
+ (FractPart * RadixInt)
+ .lshr(Scale)
+ .toString(Str, /*radix=*/10, Val.isSigned());
+ FractPart = (FractPart * RadixInt) & FractPartMask;
+ } while (FractPart != 0);
}
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index e4fd6f106e33..b7b2f188d716 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -384,6 +384,9 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
@@ -404,11 +407,11 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
}
SourceLocation TypeLoc::findNullabilityLoc() const {
- if (auto attributedLoc = getAs<AttributedTypeLoc>()) {
- if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||
- attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||
- attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified)
- return attributedLoc.getAttrNameLoc();
+ if (auto ATL = getAs<AttributedTypeLoc>()) {
+ const Attr *A = ATL.getAttr();
+ if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||
+ isa<TypeNullUnspecifiedAttr>(A)))
+ return A->getLocation();
}
return {};
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index e032c312aa12..32c75afb4381 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -117,9 +117,7 @@ namespace {
void spaceBeforePlaceHolder(raw_ostream &OS);
void printTypeSpec(NamedDecl *D, raw_ostream &OS);
- void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
void printBefore(QualType T, raw_ostream &OS);
- void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
void printAfter(QualType T, raw_ostream &OS);
void AppendScope(DeclContext *DC, raw_ostream &OS);
void printTag(TagDecl *T, raw_ostream &OS);
@@ -129,6 +127,10 @@ namespace {
void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \
void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
#include "clang/AST/TypeNodes.def"
+
+ private:
+ void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
+ void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
};
} // namespace
@@ -160,8 +162,15 @@ void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
OS << ' ';
}
+static SplitQualType splitAccordingToPolicy(QualType QT,
+ const PrintingPolicy &Policy) {
+ if (Policy.PrintCanonicalTypes)
+ QT = QT.getCanonicalType();
+ return QT.split();
+}
+
void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {
- SplitQualType split = t.split();
+ SplitQualType split = splitAccordingToPolicy(t, Policy);
print(split.Ty, split.Quals, OS, PlaceHolder);
}
@@ -260,7 +269,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
}
void TypePrinter::printBefore(QualType T, raw_ostream &OS) {
- SplitQualType Split = T.split();
+ SplitQualType Split = splitAccordingToPolicy(T, Policy);
// If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
// at this level.
@@ -320,7 +329,7 @@ void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {
}
void TypePrinter::printAfter(QualType t, raw_ostream &OS) {
- SplitQualType split = t.split();
+ SplitQualType split = splitAccordingToPolicy(t, Policy);
printAfter(split.Ty, split.Quals, OS);
}
@@ -801,10 +810,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
printFunctionAfter(Info, OS);
- if (unsigned quals = T->getTypeQuals()) {
- OS << ' ';
- AppendTypeQualList(OS, quals, Policy.Restrict);
- }
+ if (!T->getTypeQuals().empty())
+ OS << " " << T->getTypeQuals().getAsString();
switch (T->getRefQualifier()) {
case RQ_None:
@@ -861,6 +868,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
case CC_AAPCS_VFP:
OS << " __attribute__((pcs(\"aapcs-vfp\")))";
break;
+ case CC_AArch64VectorCall:
+ OS << "__attribute__((aarch64_vector_pcs))";
+ break;
case CC_IntelOclBicc:
OS << " __attribute__((intel_ocl_bicc))";
break;
@@ -1154,9 +1164,13 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
D->getLocation());
if (PLoc.isValid()) {
- OS << " at " << PLoc.getFilename()
- << ':' << PLoc.getLine()
- << ':' << PLoc.getColumn();
+ OS << " at ";
+ StringRef File = PLoc.getFilename();
+ if (Policy.RemapFilePaths)
+ OS << Policy.remapPath(File);
+ else
+ OS << File;
+ OS << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
}
}
@@ -1354,12 +1368,14 @@ void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
void TypePrinter::printAttributedBefore(const AttributedType *T,
raw_ostream &OS) {
+ // FIXME: Generate this with TableGen.
+
// Prefer the macro forms of the GC and ownership qualifiers.
- if (T->getAttrKind() == AttributedType::attr_objc_gc ||
- T->getAttrKind() == AttributedType::attr_objc_ownership)
+ if (T->getAttrKind() == attr::ObjCGC ||
+ T->getAttrKind() == attr::ObjCOwnership)
return printBefore(T->getEquivalentType(), OS);
- if (T->getAttrKind() == AttributedType::attr_objc_kindof)
+ if (T->getAttrKind() == attr::ObjCKindOf)
OS << "__kindof ";
printBefore(T->getModifiedType(), OS);
@@ -1367,23 +1383,21 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
if (T->isMSTypeSpec()) {
switch (T->getAttrKind()) {
default: return;
- case AttributedType::attr_ptr32: OS << " __ptr32"; break;
- case AttributedType::attr_ptr64: OS << " __ptr64"; break;
- case AttributedType::attr_sptr: OS << " __sptr"; break;
- case AttributedType::attr_uptr: OS << " __uptr"; break;
+ case attr::Ptr32: OS << " __ptr32"; break;
+ case attr::Ptr64: OS << " __ptr64"; break;
+ case attr::SPtr: OS << " __sptr"; break;
+ case attr::UPtr: OS << " __uptr"; break;
}
spaceBeforePlaceHolder(OS);
}
// Print nullability type specifiers.
- if (T->getAttrKind() == AttributedType::attr_nonnull ||
- T->getAttrKind() == AttributedType::attr_nullable ||
- T->getAttrKind() == AttributedType::attr_null_unspecified) {
- if (T->getAttrKind() == AttributedType::attr_nonnull)
+ if (T->getImmediateNullability()) {
+ if (T->getAttrKind() == attr::TypeNonNull)
OS << " _Nonnull";
- else if (T->getAttrKind() == AttributedType::attr_nullable)
+ else if (T->getAttrKind() == attr::TypeNullable)
OS << " _Nullable";
- else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
+ else if (T->getAttrKind() == attr::TypeNullUnspecified)
OS << " _Null_unspecified";
else
llvm_unreachable("unhandled nullability");
@@ -1393,140 +1407,96 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
void TypePrinter::printAttributedAfter(const AttributedType *T,
raw_ostream &OS) {
+ // FIXME: Generate this with TableGen.
+
// Prefer the macro forms of the GC and ownership qualifiers.
- if (T->getAttrKind() == AttributedType::attr_objc_gc ||
- T->getAttrKind() == AttributedType::attr_objc_ownership)
+ if (T->getAttrKind() == attr::ObjCGC ||
+ T->getAttrKind() == attr::ObjCOwnership)
return printAfter(T->getEquivalentType(), OS);
- if (T->getAttrKind() == AttributedType::attr_objc_kindof)
- return;
-
- // TODO: not all attributes are GCC-style attributes.
- if (T->isMSTypeSpec())
- return;
-
- // Nothing to print after.
- if (T->getAttrKind() == AttributedType::attr_nonnull ||
- T->getAttrKind() == AttributedType::attr_nullable ||
- T->getAttrKind() == AttributedType::attr_null_unspecified)
- return printAfter(T->getModifiedType(), OS);
-
// If this is a calling convention attribute, don't print the implicit CC from
// the modified type.
SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
printAfter(T->getModifiedType(), OS);
+ // Some attributes are printed as qualifiers before the type, so we have
+ // nothing left to do.
+ if (T->getAttrKind() == attr::ObjCKindOf ||
+ T->isMSTypeSpec() || T->getImmediateNullability())
+ return;
+
// Don't print the inert __unsafe_unretained attribute at all.
- if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained)
+ if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
return;
// Don't print ns_returns_retained unless it had an effect.
- if (T->getAttrKind() == AttributedType::attr_ns_returns_retained &&
+ if (T->getAttrKind() == attr::NSReturnsRetained &&
!T->getEquivalentType()->castAs<FunctionType>()
->getExtInfo().getProducesResult())
return;
- // Print nullability type specifiers that occur after
- if (T->getAttrKind() == AttributedType::attr_nonnull ||
- T->getAttrKind() == AttributedType::attr_nullable ||
- T->getAttrKind() == AttributedType::attr_null_unspecified) {
- if (T->getAttrKind() == AttributedType::attr_nonnull)
- OS << " _Nonnull";
- else if (T->getAttrKind() == AttributedType::attr_nullable)
- OS << " _Nullable";
- else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
- OS << " _Null_unspecified";
- else
- llvm_unreachable("unhandled nullability");
-
+ if (T->getAttrKind() == attr::LifetimeBound) {
+ OS << " [[clang::lifetimebound]]";
return;
}
- if (T->getAttrKind() == AttributedType::attr_lifetimebound) {
- OS << " [[clang::lifetimebound]]";
+ // The printing of the address_space attribute is handled by the qualifier
+ // since it is still stored in the qualifier. Return early to prevent printing
+ // this twice.
+ if (T->getAttrKind() == attr::AddressSpace)
return;
- }
OS << " __attribute__((";
switch (T->getAttrKind()) {
- case AttributedType::attr_lifetimebound:
- case AttributedType::attr_nonnull:
- case AttributedType::attr_nullable:
- case AttributedType::attr_null_unspecified:
- case AttributedType::attr_objc_gc:
- case AttributedType::attr_objc_inert_unsafe_unretained:
- case AttributedType::attr_objc_kindof:
- case AttributedType::attr_objc_ownership:
- case AttributedType::attr_ptr32:
- case AttributedType::attr_ptr64:
- case AttributedType::attr_sptr:
- case AttributedType::attr_uptr:
- llvm_unreachable("This attribute should have been handled already");
-
- case AttributedType::attr_address_space:
- OS << "address_space(";
- // FIXME: printing the raw LangAS value is wrong. This should probably
- // use the same code as Qualifiers::print()
- OS << (unsigned)T->getEquivalentType().getAddressSpace();
- OS << ')';
- break;
-
- case AttributedType::attr_vector_size:
- OS << "__vector_size__(";
- if (const auto *vector = T->getEquivalentType()->getAs<VectorType>()) {
- OS << vector->getNumElements();
- OS << " * sizeof(";
- print(vector->getElementType(), OS, StringRef());
- OS << ')';
- }
- OS << ')';
- break;
-
- case AttributedType::attr_neon_vector_type:
- case AttributedType::attr_neon_polyvector_type: {
- if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
- OS << "neon_vector_type(";
- else
- OS << "neon_polyvector_type(";
- const auto *vector = T->getEquivalentType()->getAs<VectorType>();
- OS << vector->getNumElements();
- OS << ')';
+#define TYPE_ATTR(NAME)
+#define DECL_OR_TYPE_ATTR(NAME)
+#define ATTR(NAME) case attr::NAME:
+#include "clang/Basic/AttrList.inc"
+ llvm_unreachable("non-type attribute attached to type");
+
+ case attr::OpenCLPrivateAddressSpace:
+ case attr::OpenCLGlobalAddressSpace:
+ case attr::OpenCLLocalAddressSpace:
+ case attr::OpenCLConstantAddressSpace:
+ case attr::OpenCLGenericAddressSpace:
+ // FIXME: Update printAttributedBefore to print these once we generate
+ // AttributedType nodes for them.
break;
- }
- case AttributedType::attr_regparm: {
- // FIXME: When Sema learns to form this AttributedType, avoid printing the
- // attribute again in printFunctionProtoAfter.
- OS << "regparm(";
- QualType t = T->getEquivalentType();
- while (!t->isFunctionType())
- t = t->getPointeeType();
- OS << t->getAs<FunctionType>()->getRegParmType();
- OS << ')';
- break;
- }
+ case attr::LifetimeBound:
+ case attr::TypeNonNull:
+ case attr::TypeNullable:
+ case attr::TypeNullUnspecified:
+ case attr::ObjCGC:
+ case attr::ObjCInertUnsafeUnretained:
+ case attr::ObjCKindOf:
+ case attr::ObjCOwnership:
+ case attr::Ptr32:
+ case attr::Ptr64:
+ case attr::SPtr:
+ case attr::UPtr:
+ case attr::AddressSpace:
+ llvm_unreachable("This attribute should have been handled already");
- case AttributedType::attr_ns_returns_retained:
+ case attr::NSReturnsRetained:
OS << "ns_returns_retained";
break;
// FIXME: When Sema learns to form this AttributedType, avoid printing the
// attribute again in printFunctionProtoAfter.
- case AttributedType::attr_noreturn: OS << "noreturn"; break;
- case AttributedType::attr_nocf_check: OS << "nocf_check"; break;
- case AttributedType::attr_cdecl: OS << "cdecl"; break;
- case AttributedType::attr_fastcall: OS << "fastcall"; break;
- case AttributedType::attr_stdcall: OS << "stdcall"; break;
- case AttributedType::attr_thiscall: OS << "thiscall"; break;
- case AttributedType::attr_swiftcall: OS << "swiftcall"; break;
- case AttributedType::attr_vectorcall: OS << "vectorcall"; break;
- case AttributedType::attr_pascal: OS << "pascal"; break;
- case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
- case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
- case AttributedType::attr_regcall: OS << "regcall"; break;
- case AttributedType::attr_pcs:
- case AttributedType::attr_pcs_vfp: {
+ case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
+ case attr::CDecl: OS << "cdecl"; break;
+ case attr::FastCall: OS << "fastcall"; break;
+ case attr::StdCall: OS << "stdcall"; break;
+ case attr::ThisCall: OS << "thiscall"; break;
+ case attr::SwiftCall: OS << "swiftcall"; break;
+ case attr::VectorCall: OS << "vectorcall"; break;
+ case attr::Pascal: OS << "pascal"; break;
+ case attr::MSABI: OS << "ms_abi"; break;
+ case attr::SysVABI: OS << "sysv_abi"; break;
+ case attr::RegCall: OS << "regcall"; break;
+ case attr::Pcs: {
OS << "pcs(";
QualType t = T->getEquivalentType();
while (!t->isFunctionType())
@@ -1536,15 +1506,18 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
OS << ')';
break;
}
-
- case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
- case AttributedType::attr_preserve_most:
+ case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break;
+ case attr::IntelOclBicc: OS << "inteloclbicc"; break;
+ case attr::PreserveMost:
OS << "preserve_most";
break;
- case AttributedType::attr_preserve_all:
+ case attr::PreserveAll:
OS << "preserve_all";
break;
+ case attr::NoDeref:
+ OS << "noderef";
+ break;
}
OS << "))";
}
@@ -1851,6 +1824,12 @@ std::string QualType::getAsString(const Type *ty, Qualifiers qs,
return buffer;
}
+void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,
+ const Twine &PlaceHolder, unsigned Indentation) const {
+ print(splitAccordingToPolicy(*this, Policy), OS, Policy, PlaceHolder,
+ Indentation);
+}
+
void QualType::print(const Type *ty, Qualifiers qs,
raw_ostream &OS, const PrintingPolicy &policy,
const Twine &PlaceHolder, unsigned Indentation) {
@@ -1860,6 +1839,12 @@ void QualType::print(const Type *ty, Qualifiers qs,
TypePrinter(policy, Indentation).print(ty, qs, OS, PH);
}
+void QualType::getAsStringInternal(std::string &Str,
+ const PrintingPolicy &Policy) const {
+ return getAsStringInternal(splitAccordingToPolicy(*this, Policy), Str,
+ Policy);
+}
+
void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
std::string &buffer,
const PrintingPolicy &policy) {
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index dfc5774ab498..846a6085743e 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -2105,8 +2105,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
const CXXMethodDecl *MD = I.second;
ThunkInfoVectorTy ThunksVector = Thunks[MD];
- llvm::sort(ThunksVector.begin(), ThunksVector.end(),
- [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ llvm::sort(ThunksVector, [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
assert(LHS.Method == nullptr && RHS.Method == nullptr);
return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
});
@@ -2206,13 +2205,12 @@ VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices,
else
this->VTableIndices = OwningArrayRef<size_t>(VTableIndices);
- llvm::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
- [](const VTableLayout::VTableThunkTy &LHS,
- const VTableLayout::VTableThunkTy &RHS) {
- assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
- "Different thunks should have unique indices!");
- return LHS.first < RHS.first;
- });
+ llvm::sort(this->VTableThunks, [](const VTableLayout::VTableThunkTy &LHS,
+ const VTableLayout::VTableThunkTy &RHS) {
+ assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
+ "Different thunks should have unique indices!");
+ return LHS.first < RHS.first;
+ });
}
VTableLayout::~VTableLayout() { }
@@ -3345,8 +3343,7 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
PathsSorted.reserve(Paths.size());
for (auto& P : Paths)
PathsSorted.push_back(*P);
- llvm::sort(PathsSorted.begin(), PathsSorted.end(),
- [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
+ llvm::sort(PathsSorted, [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
return LHS.MangledPath < RHS.MangledPath;
});
bool Changed = false;
@@ -3409,10 +3406,9 @@ static void removeRedundantPaths(std::list<FullPathTy> &FullPaths) {
for (const FullPathTy &OtherPath : FullPaths) {
if (&SpecificPath == &OtherPath)
continue;
- if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
- [&](const BaseSubobject &BSO) {
- return OtherPath.count(BSO) != 0;
- })) {
+ if (llvm::all_of(SpecificPath, [&](const BaseSubobject &BSO) {
+ return OtherPath.count(BSO) != 0;
+ })) {
return true;
}
}
@@ -3488,10 +3484,9 @@ static const FullPathTy *selectBestPath(ASTContext &Context,
// It's possible that the overrider isn't in this path. If so, skip it
// because this path didn't introduce it.
const CXXRecordDecl *OverridingParent = OverridingMethod->getParent();
- if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
- [&](const BaseSubobject &BSO) {
- return BSO.getBase() == OverridingParent;
- }))
+ if (llvm::none_of(SpecificPath, [&](const BaseSubobject &BSO) {
+ return BSO.getBase() == OverridingParent;
+ }))
continue;
CurrentOverrides.insert(OverridingMethod);
}
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index 63f8395b8277..dec2e2ad1f93 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -635,10 +635,6 @@ private:
bool memoizedMatchesAncestorOfRecursively(
const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) {
- if (Node.get<TranslationUnitDecl>() ==
- ActiveASTContext->getTranslationUnitDecl())
- return false;
-
// For AST-nodes that don't have an identity, we can't memoize.
if (!Builder->isComparable())
return matchesAncestorOfRecursively(Node, Matcher, Builder, MatchMode);
@@ -673,7 +669,26 @@ private:
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) {
const auto &Parents = ActiveASTContext->getParents(Node);
- assert(!Parents.empty() && "Found node that is not in the parent map.");
+ if (Parents.empty()) {
+ // Nodes may have no parents if:
+ // a) the node is the TranslationUnitDecl
+ // b) we have a limited traversal scope that excludes the parent edges
+ // c) there is a bug in the AST, and the node is not reachable
+ // Usually the traversal scope is the whole AST, which precludes b.
+ // Bugs are common enough that it's worthwhile asserting when we can.
+#ifndef NDEBUG
+ if (!Node.get<TranslationUnitDecl>() &&
+ /* Traversal scope is full AST if any of the bounds are the TU */
+ llvm::any_of(ActiveASTContext->getTraversalScope(), [](Decl *D) {
+ return D->getKind() == Decl::TranslationUnit;
+ })) {
+ llvm::errs() << "Tried to match orphan node:\n";
+ Node.dump(llvm::errs(), ActiveASTContext->getSourceManager());
+ llvm_unreachable("Parent map should be complete!");
+ }
+#endif
+ return false;
+ }
if (Parents.size() == 1) {
// Only one parent - do recursive memoization.
const ast_type_traits::DynTypedNode Parent = Parents[0];
@@ -1019,7 +1034,7 @@ void MatchFinder::matchAST(ASTContext &Context) {
internal::MatchASTVisitor Visitor(&Matchers, Options);
Visitor.set_active_ast_context(&Context);
Visitor.onStartOfTranslationUnit();
- Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+ Visitor.TraverseAST(Context);
Visitor.onEndOfTranslationUnit();
}
diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index 9cea2f5efc5b..e1aae172a8d6 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -144,10 +144,10 @@ DynTypedMatcher DynTypedMatcher::constructVariadic(
ast_type_traits::ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers) {
assert(!InnerMatchers.empty() && "Array must not be empty.");
- assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
- [SupportedKind](const DynTypedMatcher &M) {
- return M.canConvertTo(SupportedKind);
- }) &&
+ assert(llvm::all_of(InnerMatchers,
+ [SupportedKind](const DynTypedMatcher &M) {
+ return M.canConvertTo(SupportedKind);
+ }) &&
"InnerMatchers must be convertible to SupportedKind!");
// We must relax the restrict kind here.
@@ -449,7 +449,7 @@ bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
assert(UseUnqualifiedMatch);
llvm::SmallString<128> Scratch;
StringRef NodeName = getNodeName(Node, Scratch);
- return std::any_of(Names.begin(), Names.end(), [&](StringRef Name) {
+ return llvm::any_of(Names, [&](StringRef Name) {
return consumeNameSuffix(Name, NodeName) && Name.empty();
});
}
@@ -573,6 +573,9 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
const internal::VariadicDynCastAllOfMatcher<Decl,
ClassTemplateSpecializationDecl>
classTemplateSpecializationDecl;
+const internal::VariadicDynCastAllOfMatcher<
+ Decl, ClassTemplatePartialSpecializationDecl>
+ classTemplatePartialSpecializationDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
declaratorDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
@@ -603,6 +606,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
cxxConversionDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, IndirectFieldDecl>
+ indirectFieldDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
functionTemplateDecl;
@@ -610,6 +615,10 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
const internal::VariadicAllOfMatcher<Stmt> stmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedMemberExpr>
+ unresolvedMemberExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDependentScopeMemberExpr>
+ cxxDependentScopeMemberExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
@@ -659,6 +668,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingValueDecl>
unresolvedUsingValueDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingTypenameDecl>
unresolvedUsingTypenameDecl;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ConstantExpr> constantExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr>
cxxConstructExpr;
@@ -680,6 +690,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr> objcIvarRefExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, BlockExpr> blockExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt>
@@ -710,6 +721,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral>
const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
integerLiteral;
const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> floatLiteral;
+const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral> imaginaryLiteral;
const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
userDefinedLiteral;
const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr>
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index da8df907ba7f..5db10048fdf8 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -110,6 +110,10 @@ private:
}
switch (Code[0]) {
+ case '#':
+ Result.Kind = TokenInfo::TK_Eof;
+ Result.Text = "";
+ return Result;
case ',':
Result.Kind = TokenInfo::TK_Comma;
Result.Text = Code.substr(0, 1);
@@ -339,8 +343,27 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
if (const VariantValue NamedValue =
NamedValues ? NamedValues->lookup(NameToken.Text)
: VariantValue()) {
- *Value = NamedValue;
- return true;
+
+ if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) {
+ *Value = NamedValue;
+ return true;
+ }
+
+ std::string BindID;
+ if (!parseBindID(BindID))
+ return false;
+
+ assert(NamedValue.isMatcher());
+ llvm::Optional<DynTypedMatcher> Result =
+ NamedValue.getMatcher().getSingleMatcher();
+ if (Result.hasValue()) {
+ llvm::Optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
+ if (Bound.hasValue()) {
+ *Value = VariantMatcher::SingleMatcher(*Bound);
+ return true;
+ }
+ }
+ return false;
}
// If the syntax is correct and the name is not a matcher either, report
// unknown named value.
@@ -359,6 +382,43 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
return parseMatcherExpressionImpl(NameToken, Value);
}
+bool Parser::parseBindID(std::string &BindID) {
+ // Parse .bind("foo")
+ assert(Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period);
+ Tokenizer->consumeNextToken(); // consume the period.
+ const TokenInfo BindToken = Tokenizer->consumeNextToken();
+ if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
+ addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
+ return false;
+ }
+
+ const TokenInfo OpenToken = Tokenizer->consumeNextToken();
+ const TokenInfo IDToken = Tokenizer->consumeNextToken();
+ const TokenInfo CloseToken = Tokenizer->consumeNextToken();
+
+ // TODO: We could use different error codes for each/some to be more
+ // explicit about the syntax error.
+ if (BindToken.Kind != TokenInfo::TK_Ident ||
+ BindToken.Text != TokenInfo::ID_Bind) {
+ Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
+ Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
+ Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
+ Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
+ return false;
+ }
+ BindID = IDToken.Value.getString();
+ return true;
+}
+
/// Parse and validate a matcher expression.
/// \return \c true on success, in which case \c Value has the matcher parsed.
/// If the input is malformed, or some argument has an error, it
@@ -425,38 +485,8 @@ bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
std::string BindID;
if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
- // Parse .bind("foo")
- Tokenizer->consumeNextToken(); // consume the period.
- const TokenInfo BindToken = Tokenizer->consumeNextToken();
- if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
- addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
+ if (!parseBindID(BindID))
return false;
- }
-
- const TokenInfo OpenToken = Tokenizer->consumeNextToken();
- const TokenInfo IDToken = Tokenizer->consumeNextToken();
- const TokenInfo CloseToken = Tokenizer->consumeNextToken();
-
- // TODO: We could use different error codes for each/some to be more
- // explicit about the syntax error.
- if (BindToken.Kind != TokenInfo::TK_Ident ||
- BindToken.Text != TokenInfo::ID_Bind) {
- Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
- return false;
- }
- if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
- Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
- return false;
- }
- if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
- Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
- return false;
- }
- if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
- Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
- return false;
- }
- BindID = IDToken.Value.getString();
}
if (!Ctor)
@@ -619,12 +649,12 @@ Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
P.parseExpressionImpl(&Dummy);
// Sort by specificity, then by name.
- llvm::sort(P.Completions.begin(), P.Completions.end(),
+ llvm::sort(P.Completions,
[](const MatcherCompletion &A, const MatcherCompletion &B) {
- if (A.Specificity != B.Specificity)
- return A.Specificity > B.Specificity;
- return A.TypedText < B.TypedText;
- });
+ if (A.Specificity != B.Specificity)
+ return A.Specificity > B.Specificity;
+ return A.TypedText < B.TypedText;
+ });
return P.Completions;
}
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 4d2d76f6a75b..e6e48467967e 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -106,6 +106,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_OVERLOADED_2(callee);
REGISTER_OVERLOADED_2(hasPrefix);
REGISTER_OVERLOADED_2(hasType);
+ REGISTER_OVERLOADED_2(ignoringParens);
REGISTER_OVERLOADED_2(isDerivedFrom);
REGISTER_OVERLOADED_2(isSameOrDerivedFrom);
REGISTER_OVERLOADED_2(loc);
@@ -133,11 +134,12 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(asString);
REGISTER_MATCHER(atomicExpr);
REGISTER_MATCHER(atomicType);
- REGISTER_MATCHER(autoType);
REGISTER_MATCHER(autoreleasePoolStmt)
- REGISTER_MATCHER(binaryOperator);
+ REGISTER_MATCHER(autoType);
REGISTER_MATCHER(binaryConditionalOperator);
+ REGISTER_MATCHER(binaryOperator);
REGISTER_MATCHER(blockDecl);
+ REGISTER_MATCHER(blockExpr);
REGISTER_MATCHER(blockPointerType);
REGISTER_MATCHER(booleanType);
REGISTER_MATCHER(breakStmt);
@@ -153,6 +155,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(compoundStmt);
REGISTER_MATCHER(conditionalOperator);
REGISTER_MATCHER(constantArrayType);
+ REGISTER_MATCHER(constantExpr);
REGISTER_MATCHER(containsDeclaration);
REGISTER_MATCHER(continueStmt);
REGISTER_MATCHER(cStyleCastExpr);
@@ -167,6 +170,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(cxxCtorInitializer);
REGISTER_MATCHER(cxxDefaultArgExpr);
REGISTER_MATCHER(cxxDeleteExpr);
+ REGISTER_MATCHER(cxxDependentScopeMemberExpr);
REGISTER_MATCHER(cxxDestructorDecl);
REGISTER_MATCHER(cxxDynamicCastExpr);
REGISTER_MATCHER(cxxForRangeStmt);
@@ -188,10 +192,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(decayedType);
REGISTER_MATCHER(decl);
REGISTER_MATCHER(declaratorDecl);
- REGISTER_MATCHER(decltypeType);
REGISTER_MATCHER(declCountIs);
REGISTER_MATCHER(declRefExpr);
REGISTER_MATCHER(declStmt);
+ REGISTER_MATCHER(decltypeType);
REGISTER_MATCHER(defaultStmt);
REGISTER_MATCHER(dependentSizedArrayType);
REGISTER_MATCHER(designatedInitExpr);
@@ -208,6 +212,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(expr);
REGISTER_MATCHER(exprWithCleanups);
REGISTER_MATCHER(fieldDecl);
+ REGISTER_MATCHER(indirectFieldDecl);
REGISTER_MATCHER(floatLiteral);
REGISTER_MATCHER(forEach);
REGISTER_MATCHER(forEachArgumentWithParam);
@@ -232,6 +237,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasAnyDeclaration);
REGISTER_MATCHER(hasAnyName);
REGISTER_MATCHER(hasAnyParameter);
+ REGISTER_MATCHER(hasAnySelector);
REGISTER_MATCHER(hasAnySubstatement);
REGISTER_MATCHER(hasAnyTemplateArgument);
REGISTER_MATCHER(hasAnyUsingShadowDecl);
@@ -267,6 +273,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasInClassInitializer);
REGISTER_MATCHER(hasIncrement);
REGISTER_MATCHER(hasIndex);
+ REGISTER_MATCHER(hasInit);
REGISTER_MATCHER(hasInitializer);
REGISTER_MATCHER(hasKeywordSelector);
REGISTER_MATCHER(hasLHS);
@@ -290,11 +297,11 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasReturnValue);
REGISTER_MATCHER(hasRHS);
REGISTER_MATCHER(hasSelector);
- REGISTER_MATCHER(hasAnySelector);
REGISTER_MATCHER(hasSingleDecl);
REGISTER_MATCHER(hasSize);
REGISTER_MATCHER(hasSizeExpr);
REGISTER_MATCHER(hasSourceExpression);
+ REGISTER_MATCHER(hasSpecializedTemplate);
REGISTER_MATCHER(hasStaticStorageDuration);
REGISTER_MATCHER(hasSyntacticForm);
REGISTER_MATCHER(hasTargetDecl);
@@ -307,14 +314,15 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasUnaryOperand);
REGISTER_MATCHER(hasUnarySelector);
REGISTER_MATCHER(hasUnderlyingDecl);
+ REGISTER_MATCHER(hasUnderlyingType);
REGISTER_MATCHER(hasUnqualifiedDesugaredType);
REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
- REGISTER_MATCHER(ignoringImplicit);
REGISTER_MATCHER(ignoringImpCasts);
+ REGISTER_MATCHER(ignoringImplicit);
REGISTER_MATCHER(ignoringParenCasts);
REGISTER_MATCHER(ignoringParenImpCasts);
- REGISTER_MATCHER(ignoringParens);
+ REGISTER_MATCHER(imaginaryLiteral);
REGISTER_MATCHER(implicitCastExpr);
REGISTER_MATCHER(implicitValueInitExpr);
REGISTER_MATCHER(incompleteArrayType);
@@ -341,19 +349,21 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isDefaulted);
REGISTER_MATCHER(isDefinition);
REGISTER_MATCHER(isDeleted);
+ REGISTER_MATCHER(isDelegatingConstructor);
REGISTER_MATCHER(isExceptionVariable);
+ REGISTER_MATCHER(isExpansionInFileMatching);
+ REGISTER_MATCHER(isExpansionInMainFile);
+ REGISTER_MATCHER(isExpansionInSystemHeader);
REGISTER_MATCHER(isExplicit);
REGISTER_MATCHER(isExplicitTemplateSpecialization);
REGISTER_MATCHER(isExpr);
REGISTER_MATCHER(isExternC);
REGISTER_MATCHER(isFinal);
- REGISTER_MATCHER(isInline);
REGISTER_MATCHER(isImplicit);
- REGISTER_MATCHER(isExpansionInFileMatching);
- REGISTER_MATCHER(isExpansionInMainFile);
+ REGISTER_MATCHER(isInline);
REGISTER_MATCHER(isInstanceMessage);
REGISTER_MATCHER(isInstantiated);
- REGISTER_MATCHER(isExpansionInSystemHeader);
+ REGISTER_MATCHER(isInstantiationDependent);
REGISTER_MATCHER(isInteger);
REGISTER_MATCHER(isIntegral);
REGISTER_MATCHER(isInTemplateInstantiation);
@@ -372,11 +382,15 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isPure);
REGISTER_MATCHER(isScoped);
REGISTER_MATCHER(isSignedInteger);
+ REGISTER_MATCHER(isStaticLocal);
REGISTER_MATCHER(isStaticStorageClass);
REGISTER_MATCHER(isStruct);
REGISTER_MATCHER(isTemplateInstantiation);
+ REGISTER_MATCHER(isTypeDependent);
REGISTER_MATCHER(isUnion);
REGISTER_MATCHER(isUnsignedInteger);
+ REGISTER_MATCHER(isUserProvided);
+ REGISTER_MATCHER(isValueDependent);
REGISTER_MATCHER(isVariadic);
REGISTER_MATCHER(isVirtual);
REGISTER_MATCHER(isVirtualAsWritten);
@@ -399,10 +413,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(namesType);
REGISTER_MATCHER(nestedNameSpecifier);
REGISTER_MATCHER(nestedNameSpecifierLoc);
+ REGISTER_MATCHER(nonTypeTemplateParmDecl);
REGISTER_MATCHER(nullPointerConstant);
REGISTER_MATCHER(nullStmt);
REGISTER_MATCHER(numSelectorArgs);
- REGISTER_MATCHER(ofClass);
REGISTER_MATCHER(objcCatchStmt);
REGISTER_MATCHER(objcCategoryDecl);
REGISTER_MATCHER(objcCategoryImplDecl);
@@ -418,6 +432,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(objcProtocolDecl);
REGISTER_MATCHER(objcThrowStmt);
REGISTER_MATCHER(objcTryStmt);
+ REGISTER_MATCHER(ofClass);
REGISTER_MATCHER(on);
REGISTER_MATCHER(onImplicitObjectArgument);
REGISTER_MATCHER(opaqueValueExpr);
@@ -437,6 +452,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(refersToDeclaration);
REGISTER_MATCHER(refersToIntegralType);
REGISTER_MATCHER(refersToType);
+ REGISTER_MATCHER(refersToTemplate);
REGISTER_MATCHER(requiresZeroInitialization);
REGISTER_MATCHER(returns);
REGISTER_MATCHER(returnStmt);
@@ -454,9 +470,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(substTemplateTypeParmType);
REGISTER_MATCHER(switchCase);
REGISTER_MATCHER(switchStmt);
+ REGISTER_MATCHER(tagType);
REGISTER_MATCHER(templateArgument);
- REGISTER_MATCHER(templateName);
REGISTER_MATCHER(templateArgumentCountIs);
+ REGISTER_MATCHER(templateName);
REGISTER_MATCHER(templateSpecializationType);
REGISTER_MATCHER(templateTypeParmDecl);
REGISTER_MATCHER(templateTypeParmType);
@@ -464,20 +481,22 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(to);
REGISTER_MATCHER(translationUnitDecl);
REGISTER_MATCHER(type);
+ REGISTER_MATCHER(typeAliasDecl);
+ REGISTER_MATCHER(typeAliasTemplateDecl);
REGISTER_MATCHER(typedefDecl);
REGISTER_MATCHER(typedefNameDecl);
REGISTER_MATCHER(typedefType);
- REGISTER_MATCHER(typeAliasDecl);
- REGISTER_MATCHER(typeAliasTemplateDecl);
REGISTER_MATCHER(typeLoc);
REGISTER_MATCHER(unaryExprOrTypeTraitExpr);
REGISTER_MATCHER(unaryOperator);
REGISTER_MATCHER(unaryTransformType);
REGISTER_MATCHER(unless);
REGISTER_MATCHER(unresolvedLookupExpr);
+ REGISTER_MATCHER(unresolvedMemberExpr);
REGISTER_MATCHER(unresolvedUsingTypenameDecl);
REGISTER_MATCHER(unresolvedUsingValueDecl);
REGISTER_MATCHER(userDefinedLiteral);
+ REGISTER_MATCHER(usesADL);
REGISTER_MATCHER(usingDecl);
REGISTER_MATCHER(usingDirectiveDecl);
REGISTER_MATCHER(valueDecl);
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index 9557f68452ff..30160bc239ae 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/lib/Analysis/AnalysisDeclContext.cpp
@@ -27,7 +27,6 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
-#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
#include "clang/Analysis/BodyFarm.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
@@ -137,7 +136,7 @@ bool AnalysisDeclContext::isBodyAutosynthesized() const {
bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
bool Tmp;
Stmt *Body = getBody(Tmp);
- return Tmp && Body->getLocStart().isValid();
+ return Tmp && Body->getBeginLoc().isValid();
}
/// Returns true if \param VD is an Objective-C implicit 'self' parameter.
@@ -292,12 +291,6 @@ ParentMap &AnalysisDeclContext::getParentMap() {
return *PM;
}
-PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() {
- if (!PCA)
- PCA.reset(new PseudoConstantAnalysis(getBody()));
- return PCA.get();
-}
-
AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
@@ -392,7 +385,7 @@ LocationContextManager::getLocationContext(AnalysisDeclContext *ctx,
LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
- L = new LOC(ctx, parent, d);
+ L = new LOC(ctx, parent, d, ++NewID);
Contexts.InsertNode(L, InsertPos);
}
return L;
@@ -409,7 +402,7 @@ LocationContextManager::getStackFrame(AnalysisDeclContext *ctx,
auto *L =
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
- L = new StackFrameContext(ctx, parent, s, blk, idx);
+ L = new StackFrameContext(ctx, parent, s, blk, idx, ++NewID);
Contexts.InsertNode(L, InsertPos);
}
return L;
@@ -434,7 +427,7 @@ LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx,
cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
InsertPos));
if (!L) {
- L = new BlockInvocationContext(ctx, parent, BD, ContextData);
+ L = new BlockInvocationContext(ctx, parent, BD, ContextData, ++NewID);
Contexts.InsertNode(L, InsertPos);
}
return L;
@@ -500,7 +493,7 @@ void LocationContext::dumpStack(
OS << "Calling anonymous code";
if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
OS << " at ";
- printLocation(OS, SM, S->getLocStart());
+ printLocation(OS, SM, S->getBeginLoc());
}
break;
case Scope:
@@ -510,7 +503,7 @@ void LocationContext::dumpStack(
OS << "Invoking block";
if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
OS << " defined at ";
- printLocation(OS, SM, D->getLocStart());
+ printLocation(OS, SM, D->getBeginLoc());
}
break;
}
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index ac8fcdc912a0..35f046406763 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -201,10 +201,9 @@ ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
/*arrow=*/true, /*free=*/false);
}
-
ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
- return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal),
- nullptr);
+ return ReturnStmt::Create(C, SourceLocation(), const_cast<Expr *>(RetVal),
+ /* NRVOCandidate=*/nullptr);
}
IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) {
@@ -270,8 +269,8 @@ static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
llvm_unreachable("Unexpected state");
}
- return new (C)
- CallExpr(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, SourceLocation());
+ return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue,
+ SourceLocation());
}
static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
@@ -293,12 +292,12 @@ static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
/* T =*/ callOperatorDecl->getType(),
/* VK =*/ VK_LValue);
- return new (C)
- CXXOperatorCallExpr(/*AstContext=*/C, OO_Call, callOperatorDeclRef,
- /*args=*/CallArgs,
- /*QualType=*/C.VoidTy,
- /*ExprValueType=*/VK_RValue,
- /*SourceLocation=*/SourceLocation(), FPOptions());
+ return CXXOperatorCallExpr::Create(
+ /*AstContext=*/C, OO_Call, callOperatorDeclRef,
+ /*args=*/CallArgs,
+ /*QualType=*/C.VoidTy,
+ /*ExprValueType=*/VK_RValue,
+ /*SourceLocation=*/SourceLocation(), FPOptions());
}
/// Create a fake body for std::call_once.
@@ -464,13 +463,13 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
DerefType);
- IfStmt *Out = new (C)
- IfStmt(C, SourceLocation(),
- /* IsConstexpr=*/ false,
- /* init=*/ nullptr,
- /* var=*/ nullptr,
- /* cond=*/ FlagCheck,
- /* then=*/ M.makeCompound({CallbackCall, FlagAssignment}));
+ auto *Out =
+ IfStmt::Create(C, SourceLocation(),
+ /* IsConstexpr=*/false,
+ /* init=*/nullptr,
+ /* var=*/nullptr,
+ /* cond=*/FlagCheck,
+ /* then=*/M.makeCompound({CallbackCall, FlagAssignment}));
return Out;
}
@@ -510,7 +509,7 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
ASTMaker M(C);
// (1) Create the call.
- CallExpr *CE = new (C) CallExpr(
+ CallExpr *CE = CallExpr::Create(
/*ASTContext=*/C,
/*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
/*args=*/None,
@@ -549,12 +548,12 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
// (5) Create the 'if' statement.
- IfStmt *If = new (C) IfStmt(C, SourceLocation(),
- /* IsConstexpr=*/ false,
- /* init=*/ nullptr,
- /* var=*/ nullptr,
- /* cond=*/ GuardCondition,
- /* then=*/ CS);
+ auto *If = IfStmt::Create(C, SourceLocation(),
+ /* IsConstexpr=*/false,
+ /* init=*/nullptr,
+ /* var=*/nullptr,
+ /* cond=*/GuardCondition,
+ /* then=*/CS);
return If;
}
@@ -580,8 +579,8 @@ static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
ASTMaker M(C);
DeclRefExpr *DR = M.makeDeclRefExpr(PV);
ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
- CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
- SourceLocation());
+ CallExpr *CE =
+ CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue, SourceLocation());
return CE;
}
@@ -657,8 +656,11 @@ static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
Stmt *Else = M.makeReturn(RetVal);
/// Construct the If.
- Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
- Comparison, Body, SourceLocation(), Else);
+ auto *If = IfStmt::Create(C, SourceLocation(),
+ /* IsConstexpr=*/false,
+ /* init=*/nullptr,
+ /* var=*/nullptr, Comparison, Body,
+ SourceLocation(), Else);
return If;
}
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 97829de7ace3..96130c25be8a 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -551,6 +551,7 @@ private:
CFGBlock *VisitGotoStmt(GotoStmt *G);
CFGBlock *VisitIfStmt(IfStmt *I);
CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
+ CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);
CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
CFGBlock *VisitLabelStmt(LabelStmt *L);
CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);
@@ -571,7 +572,7 @@ private:
CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
- CFGBlock *VisitReturnStmt(ReturnStmt *R);
+ CFGBlock *VisitReturnStmt(Stmt *S);
CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
@@ -1038,12 +1039,14 @@ private:
if (!areExprTypesCompatible(Expr1, Expr2))
return {};
- llvm::APSInt L1, L2;
-
- if (!Expr1->EvaluateAsInt(L1, *Context) ||
- !Expr2->EvaluateAsInt(L2, *Context))
+ Expr::EvalResult L1Result, L2Result;
+ if (!Expr1->EvaluateAsInt(L1Result, *Context) ||
+ !Expr2->EvaluateAsInt(L2Result, *Context))
return {};
+ llvm::APSInt L1 = L1Result.Val.getInt();
+ llvm::APSInt L2 = L2Result.Val.getInt();
+
// Can't compare signed with unsigned or with different bit width.
if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
return {};
@@ -1133,13 +1136,16 @@ private:
case BO_And: {
// If either operand is zero, we know the value
// must be false.
- llvm::APSInt IntVal;
- if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) {
+ Expr::EvalResult LHSResult;
+ if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
+ llvm::APSInt IntVal = LHSResult.Val.getInt();
if (!IntVal.getBoolValue()) {
return TryResult(false);
}
}
- if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) {
+ Expr::EvalResult RHSResult;
+ if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
+ llvm::APSInt IntVal = RHSResult.Val.getInt();
if (!IntVal.getBoolValue()) {
return TryResult(false);
}
@@ -1334,6 +1340,7 @@ void CFGBuilder::findConstructionContexts(
case CK_NoOp:
case CK_ConstructorConversion:
findConstructionContexts(Layer, Cast->getSubExpr());
+ break;
default:
break;
}
@@ -2099,6 +2106,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::ImplicitCastExprClass:
return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
+ case Stmt::ConstantExprClass:
+ return VisitConstantExpr(cast<ConstantExpr>(S), asc);
+
case Stmt::IndirectGotoStmtClass:
return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
@@ -2146,7 +2156,8 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
case Stmt::ReturnStmtClass:
- return VisitReturnStmt(cast<ReturnStmt>(S));
+ case Stmt::CoreturnStmtClass:
+ return VisitReturnStmt(S);
case Stmt::SEHExceptStmtClass:
return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
@@ -2421,8 +2432,6 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
if (!boundType.isNull()) calleeType = boundType;
}
- findConstructionContextsForArguments(C);
-
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
@@ -2439,6 +2448,13 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
bool OmitArguments = false;
if (FunctionDecl *FD = C->getDirectCallee()) {
+ // TODO: Support construction contexts for variadic function arguments.
+ // These are a bit problematic and not very useful because passing
+ // C++ objects as C-style variadic arguments doesn't work in general
+ // (see [expr.call]).
+ if (!FD->isVariadic())
+ findConstructionContextsForArguments(C);
+
if (FD->isNoReturn() || C->isBuiltinAssumeFalse(*Context))
NoReturn = true;
if (FD->hasAttr<NoThrowAttr>())
@@ -2627,15 +2643,12 @@ CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(),
E = DS->decl_rend();
I != E; ++I) {
- // Get the alignment of the new DeclStmt, padding out to >=8 bytes.
- unsigned A = alignof(DeclStmt) < 8 ? 8 : alignof(DeclStmt);
// Allocate the DeclStmt using the BumpPtrAllocator. It will get
// automatically freed with the CFG.
DeclGroupRef DG(*I);
Decl *D = *I;
- void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A);
- DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
+ DeclStmt *DSNew = new (Context) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
cfg->addSyntheticDeclStmt(DSNew, DS);
// Append the fake DeclStmt to block.
@@ -2874,22 +2887,24 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
return LastBlock;
}
-CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) {
+CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
// If we were in the middle of a block we stop processing that block.
//
- // NOTE: If a "return" appears in the middle of a block, this means that the
- // code afterwards is DEAD (unreachable). We still keep a basic block
- // for that code; a simple "mark-and-sweep" from the entry block will be
- // able to report such dead blocks.
+ // NOTE: If a "return" or "co_return" appears in the middle of a block, this
+ // means that the code afterwards is DEAD (unreachable). We still keep
+ // a basic block for that code; a simple "mark-and-sweep" from the entry
+ // block will be able to report such dead blocks.
+ assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
// Create the new block.
Block = createBlock(false);
- addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), R);
+ addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
- findConstructionContexts(
- ConstructionContextLayer::create(cfg->getBumpVectorContext(), R),
- R->getRetValue());
+ if (auto *R = dyn_cast<ReturnStmt>(S))
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), R),
+ R->getRetValue());
// If the one of the destructors does not return, we already have the Exit
// block as a successor.
@@ -2898,7 +2913,7 @@ CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) {
// Add the return statement to the block. This may create new blocks if R
// contains control-flow (short-circuit operations).
- return VisitStmt(R, AddStmtChoice::AlwaysAdd);
+ return VisitStmt(S, AddStmtChoice::AlwaysAdd);
}
CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
@@ -4250,7 +4265,10 @@ CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
Block = createBlock();
addStmt(S->getBeginStmt());
addStmt(S->getEndStmt());
- return addStmt(S->getRangeStmt());
+ CFGBlock *Head = addStmt(S->getRangeStmt());
+ if (S->getInit())
+ Head = addStmt(S->getInit());
+ return Head;
}
CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
@@ -4352,6 +4370,11 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
AddStmtChoice asc) {
+ // If the constructor takes objects as arguments by value, we need to properly
+ // construct these objects. Construction contexts we find here aren't for the
+ // constructor C, they're for its arguments only.
+ findConstructionContextsForArguments(C);
+
autoCreateBlock();
appendConstructor(Block, C);
return VisitChildren(C);
@@ -4366,6 +4389,10 @@ CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
return Visit(E->getSubExpr(), AddStmtChoice());
}
+CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
+ return Visit(E->getSubExpr(), AddStmtChoice());
+}
+
CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
// Lazily create the indirect-goto dispatch block if there isn't one already.
CFGBlock *IBlock = cfg->getIndirectGotoBlock();
@@ -4422,6 +4449,10 @@ tryAgain:
E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
goto tryAgain;
+ case Stmt::ConstantExprClass:
+ E = cast<ConstantExpr>(E)->getSubExpr();
+ goto tryAgain;
+
case Stmt::ParenExprClass:
E = cast<ParenExpr>(E)->getSubExpr();
goto tryAgain;
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 432067d98157..5345a56f2002 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -15,16 +15,12 @@ add_clang_library(clangAnalysis
Consumed.cpp
CodeInjector.cpp
Dominators.cpp
- FormatString.cpp
+ ExprMutationAnalyzer.cpp
LiveVariables.cpp
- OSLog.cpp
ObjCNoReturn.cpp
PostOrderCFGView.cpp
- PrintfFormatString.cpp
ProgramPoint.cpp
- PseudoConstantAnalysis.cpp
ReachableCode.cpp
- ScanfFormatString.cpp
ThreadSafety.cpp
ThreadSafetyCommon.cpp
ThreadSafetyLogical.cpp
@@ -33,6 +29,7 @@ add_clang_library(clangAnalysis
LINK_LIBS
clangAST
+ clangASTMatchers
clangBasic
clangLex
)
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index bac00680ffda..66a6f1a9bcea 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -212,7 +212,7 @@ void CallGraph::viewGraph() const {
void CallGraphNode::print(raw_ostream &os) const {
if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
- return ND->printName(os);
+ return ND->printQualifiedName(os);
os << "< >";
}
diff --git a/lib/Analysis/CloneDetection.cpp b/lib/Analysis/CloneDetection.cpp
index 8912b3b76751..88402e2adaa7 100644
--- a/lib/Analysis/CloneDetection.cpp
+++ b/lib/Analysis/CloneDetection.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
///
-/// This file implements classes for searching and anlyzing source code clones.
+/// This file implements classes for searching and analyzing source code clones.
///
//===----------------------------------------------------------------------===//
@@ -45,8 +45,8 @@ bool StmtSequence::contains(const StmtSequence &Other) const {
// Otherwise check if the start and end locations of the current sequence
// surround the other sequence.
bool StartIsInBounds =
- SM.isBeforeInTranslationUnit(getStartLoc(), Other.getStartLoc()) ||
- getStartLoc() == Other.getStartLoc();
+ SM.isBeforeInTranslationUnit(getBeginLoc(), Other.getBeginLoc()) ||
+ getBeginLoc() == Other.getBeginLoc();
if (!StartIsInBounds)
return false;
@@ -77,14 +77,14 @@ ASTContext &StmtSequence::getASTContext() const {
return D->getASTContext();
}
-SourceLocation StmtSequence::getStartLoc() const {
- return front()->getLocStart();
+SourceLocation StmtSequence::getBeginLoc() const {
+ return front()->getBeginLoc();
}
-SourceLocation StmtSequence::getEndLoc() const { return back()->getLocEnd(); }
+SourceLocation StmtSequence::getEndLoc() const { return back()->getEndLoc(); }
SourceRange StmtSequence::getSourceRange() const {
- return SourceRange(getStartLoc(), getEndLoc());
+ return SourceRange(getBeginLoc(), getEndLoc());
}
void CloneDetector::analyzeCodeBody(const Decl *D) {
@@ -433,7 +433,7 @@ size_t MinComplexityConstraint::calculateStmtComplexity(
// Look up what macros expanded into the current statement.
std::string MacroStack =
- data_collection::getMacroStack(Seq.getStartLoc(), Context);
+ data_collection::getMacroStack(Seq.getBeginLoc(), Context);
// First, check if ParentMacroStack is not empty which means we are currently
// dealing with a parent statement which was expanded from a macro.
@@ -523,8 +523,7 @@ void CloneConstraint::splitCloneGroups(
Result.push_back(PotentialGroup);
}
- assert(std::all_of(Indexes.begin(), Indexes.end(),
- [](char c) { return c == 1; }));
+ assert(llvm::all_of(Indexes, [](char c) { return c == 1; }));
}
CloneGroups = Result;
}
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index bc81a71b3d91..16eeaba2f61b 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -64,7 +64,7 @@ static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {
// is not empty.
for (const auto &B : *Block)
if (Optional<CFGStmt> CS = B.getAs<CFGStmt>())
- return CS->getStmt()->getLocStart();
+ return CS->getStmt()->getBeginLoc();
// Block is empty.
// If we have one successor, return the first statement in that block
@@ -78,12 +78,12 @@ static SourceLocation getLastStmtLoc(const CFGBlock *Block) {
// Find the source location of the last statement in the block, if the block
// is not empty.
if (const Stmt *StmtNode = Block->getTerminator()) {
- return StmtNode->getLocStart();
+ return StmtNode->getBeginLoc();
} else {
for (CFGBlock::const_reverse_iterator BI = Block->rbegin(),
BE = Block->rend(); BI != BE; ++BI) {
if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>())
- return CS->getStmt()->getLocStart();
+ return CS->getStmt()->getBeginLoc();
}
}
@@ -463,7 +463,6 @@ class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
using InfoEntry = MapType::iterator;
using ConstInfoEntry = MapType::const_iterator;
- AnalysisDeclContext &AC;
ConsumedAnalyzer &Analyzer;
ConsumedStateMap *StateMap;
MapType PropagationMap;
@@ -515,9 +514,8 @@ public:
void VisitUnaryOperator(const UnaryOperator *UOp);
void VisitVarDecl(const VarDecl *Var);
- ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer,
- ConsumedStateMap *StateMap)
- : AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
+ ConsumedStmtVisitor(ConsumedAnalyzer &Analyzer, ConsumedStateMap *StateMap)
+ : Analyzer(Analyzer), StateMap(StateMap) {}
PropagationInfo getInfo(const Expr *StmtNode) const {
ConstInfoEntry Entry = findInfo(StmtNode);
@@ -774,8 +772,7 @@ void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
CXXConstructorDecl *Constructor = Call->getConstructor();
- ASTContext &CurrContext = AC.getASTContext();
- QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
+ QualType ThisType = Constructor->getThisType()->getPointeeType();
if (!isConsumableType(ThisType))
return;
@@ -793,7 +790,7 @@ void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
} else if (Constructor->isCopyConstructor()) {
// Copy state from arg. If setStateOnRead then set arg to CS_Unknown.
ConsumedState NS =
- isSetOnReadPtrType(Constructor->getThisType(CurrContext)) ?
+ isSetOnReadPtrType(Constructor->getThisType()) ?
CS_Unknown : CS_None;
copyInfo(Call->getArg(0), Call, NS);
} else {
@@ -893,7 +890,7 @@ void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {
}
}
- StateMap->checkParamsForReturnTypestate(Ret->getLocStart(),
+ StateMap->checkParamsForReturnTypestate(Ret->getBeginLoc(),
Analyzer.WarningsHandler);
}
@@ -1203,8 +1200,7 @@ void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
const FunctionDecl *D) {
QualType ReturnType;
if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
- ASTContext &CurrContext = AC.getASTContext();
- ReturnType = Constructor->getThisType(CurrContext)->getPointeeType();
+ ReturnType = Constructor->getThisType()->getPointeeType();
} else
ReturnType = D->getCallResultType();
@@ -1323,7 +1319,7 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
CurrStates = llvm::make_unique<ConsumedStateMap>();
- ConsumedStmtVisitor Visitor(AC, *this, CurrStates.get());
+ ConsumedStmtVisitor Visitor(*this, CurrStates.get());
// Add all trackable parameters to the state map.
for (const auto *PI : D->parameters())
@@ -1363,7 +1359,7 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
case CFGElement::AutomaticObjectDtor: {
const CFGAutomaticObjDtor &DTor = B.castAs<CFGAutomaticObjDtor>();
- SourceLocation Loc = DTor.getTriggerStmt()->getLocEnd();
+ SourceLocation Loc = DTor.getTriggerStmt()->getEndLoc();
const VarDecl *Var = DTor.getVarDecl();
Visitor.checkCallability(PropagationInfo(Var),
diff --git a/lib/Analysis/ExprMutationAnalyzer.cpp b/lib/Analysis/ExprMutationAnalyzer.cpp
new file mode 100644
index 000000000000..8414cb5c726a
--- /dev/null
+++ b/lib/Analysis/ExprMutationAnalyzer.cpp
@@ -0,0 +1,445 @@
+//===---------- ExprMutationAnalyzer.cpp ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+using namespace ast_matchers;
+
+namespace {
+
+AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) {
+ return llvm::is_contained(Node.capture_inits(), E);
+}
+
+AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt,
+ ast_matchers::internal::Matcher<DeclStmt>, InnerMatcher) {
+ const DeclStmt *const Range = Node.getRangeStmt();
+ return InnerMatcher.matches(*Range, Finder, Builder);
+}
+
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr>
+ cxxTypeidExpr;
+
+AST_MATCHER(CXXTypeidExpr, isPotentiallyEvaluated) {
+ return Node.isPotentiallyEvaluated();
+}
+
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
+ cxxNoexceptExpr;
+
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt,
+ GenericSelectionExpr>
+ genericSelectionExpr;
+
+AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr,
+ ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder);
+}
+
+const auto nonConstReferenceType = [] {
+ return hasUnqualifiedDesugaredType(
+ referenceType(pointee(unless(isConstQualified()))));
+};
+
+const auto nonConstPointerType = [] {
+ return hasUnqualifiedDesugaredType(
+ pointerType(pointee(unless(isConstQualified()))));
+};
+
+const auto isMoveOnly = [] {
+ return cxxRecordDecl(
+ hasMethod(cxxConstructorDecl(isMoveConstructor(), unless(isDeleted()))),
+ hasMethod(cxxMethodDecl(isMoveAssignmentOperator(), unless(isDeleted()))),
+ unless(anyOf(hasMethod(cxxConstructorDecl(isCopyConstructor(),
+ unless(isDeleted()))),
+ hasMethod(cxxMethodDecl(isCopyAssignmentOperator(),
+ unless(isDeleted()))))));
+};
+
+template <class T> struct NodeID;
+template <> struct NodeID<Expr> { static const std::string value; };
+template <> struct NodeID<Decl> { static const std::string value; };
+const std::string NodeID<Expr>::value = "expr";
+const std::string NodeID<Decl>::value = "decl";
+
+template <class T, class F = const Stmt *(ExprMutationAnalyzer::*)(const T *)>
+const Stmt *tryEachMatch(ArrayRef<ast_matchers::BoundNodes> Matches,
+ ExprMutationAnalyzer *Analyzer, F Finder) {
+ const StringRef ID = NodeID<T>::value;
+ for (const auto &Nodes : Matches) {
+ if (const Stmt *S = (Analyzer->*Finder)(Nodes.getNodeAs<T>(ID)))
+ return S;
+ }
+ return nullptr;
+}
+
+} // namespace
+
+const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) {
+ return findMutationMemoized(Exp,
+ {&ExprMutationAnalyzer::findDirectMutation,
+ &ExprMutationAnalyzer::findMemberMutation,
+ &ExprMutationAnalyzer::findArrayElementMutation,
+ &ExprMutationAnalyzer::findCastMutation,
+ &ExprMutationAnalyzer::findRangeLoopMutation,
+ &ExprMutationAnalyzer::findReferenceMutation,
+ &ExprMutationAnalyzer::findFunctionArgMutation},
+ Results);
+}
+
+const Stmt *ExprMutationAnalyzer::findMutation(const Decl *Dec) {
+ return tryEachDeclRef(Dec, &ExprMutationAnalyzer::findMutation);
+}
+
+const Stmt *ExprMutationAnalyzer::findPointeeMutation(const Expr *Exp) {
+ return findMutationMemoized(Exp, {/*TODO*/}, PointeeResults);
+}
+
+const Stmt *ExprMutationAnalyzer::findPointeeMutation(const Decl *Dec) {
+ return tryEachDeclRef(Dec, &ExprMutationAnalyzer::findPointeeMutation);
+}
+
+const Stmt *ExprMutationAnalyzer::findMutationMemoized(
+ const Expr *Exp, llvm::ArrayRef<MutationFinder> Finders,
+ ResultMap &MemoizedResults) {
+ const auto Memoized = MemoizedResults.find(Exp);
+ if (Memoized != MemoizedResults.end())
+ return Memoized->second;
+
+ if (isUnevaluated(Exp))
+ return MemoizedResults[Exp] = nullptr;
+
+ for (const auto &Finder : Finders) {
+ if (const Stmt *S = (this->*Finder)(Exp))
+ return MemoizedResults[Exp] = S;
+ }
+
+ return MemoizedResults[Exp] = nullptr;
+}
+
+const Stmt *ExprMutationAnalyzer::tryEachDeclRef(const Decl *Dec,
+ MutationFinder Finder) {
+ const auto Refs =
+ match(findAll(declRefExpr(to(equalsNode(Dec))).bind(NodeID<Expr>::value)),
+ Stm, Context);
+ for (const auto &RefNodes : Refs) {
+ const auto *E = RefNodes.getNodeAs<Expr>(NodeID<Expr>::value);
+ if ((this->*Finder)(E))
+ return E;
+ }
+ return nullptr;
+}
+
+bool ExprMutationAnalyzer::isUnevaluated(const Expr *Exp) {
+ return selectFirst<Expr>(
+ NodeID<Expr>::value,
+ match(
+ findAll(
+ expr(equalsNode(Exp),
+ anyOf(
+ // `Exp` is part of the underlying expression of
+ // decltype/typeof if it has an ancestor of
+ // typeLoc.
+ hasAncestor(typeLoc(unless(
+ hasAncestor(unaryExprOrTypeTraitExpr())))),
+ hasAncestor(expr(anyOf(
+ // `UnaryExprOrTypeTraitExpr` is unevaluated
+ // unless it's sizeof on VLA.
+ unaryExprOrTypeTraitExpr(unless(sizeOfExpr(
+ hasArgumentOfType(variableArrayType())))),
+ // `CXXTypeidExpr` is unevaluated unless it's
+ // applied to an expression of glvalue of
+ // polymorphic class type.
+ cxxTypeidExpr(
+ unless(isPotentiallyEvaluated())),
+ // The controlling expression of
+ // `GenericSelectionExpr` is unevaluated.
+ genericSelectionExpr(hasControllingExpr(
+ hasDescendant(equalsNode(Exp)))),
+ cxxNoexceptExpr())))))
+ .bind(NodeID<Expr>::value)),
+ Stm, Context)) != nullptr;
+}
+
+const Stmt *
+ExprMutationAnalyzer::findExprMutation(ArrayRef<BoundNodes> Matches) {
+ return tryEachMatch<Expr>(Matches, this, &ExprMutationAnalyzer::findMutation);
+}
+
+const Stmt *
+ExprMutationAnalyzer::findDeclMutation(ArrayRef<BoundNodes> Matches) {
+ return tryEachMatch<Decl>(Matches, this, &ExprMutationAnalyzer::findMutation);
+}
+
+const Stmt *ExprMutationAnalyzer::findExprPointeeMutation(
+ ArrayRef<ast_matchers::BoundNodes> Matches) {
+ return tryEachMatch<Expr>(Matches, this,
+ &ExprMutationAnalyzer::findPointeeMutation);
+}
+
+const Stmt *ExprMutationAnalyzer::findDeclPointeeMutation(
+ ArrayRef<ast_matchers::BoundNodes> Matches) {
+ return tryEachMatch<Decl>(Matches, this,
+ &ExprMutationAnalyzer::findPointeeMutation);
+}
+
+const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) {
+ // LHS of any assignment operators.
+ const auto AsAssignmentLhs =
+ binaryOperator(isAssignmentOperator(), hasLHS(equalsNode(Exp)));
+
+ // Operand of increment/decrement operators.
+ const auto AsIncDecOperand =
+ unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")),
+ hasUnaryOperand(equalsNode(Exp)));
+
+ // Invoking non-const member function.
+ // A member function is assumed to be non-const when it is unresolved.
+ const auto NonConstMethod = cxxMethodDecl(unless(isConst()));
+ const auto AsNonConstThis =
+ expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))),
+ cxxOperatorCallExpr(callee(NonConstMethod),
+ hasArgument(0, equalsNode(Exp))),
+ callExpr(callee(expr(anyOf(
+ unresolvedMemberExpr(hasObjectExpression(equalsNode(Exp))),
+ cxxDependentScopeMemberExpr(
+ hasObjectExpression(equalsNode(Exp)))))))));
+
+ // Taking address of 'Exp'.
+ // We're assuming 'Exp' is mutated as soon as its address is taken, though in
+ // theory we can follow the pointer and see whether it escaped `Stm` or is
+ // dereferenced and then mutated. This is left for future improvements.
+ const auto AsAmpersandOperand =
+ unaryOperator(hasOperatorName("&"),
+ // A NoOp implicit cast is adding const.
+ unless(hasParent(implicitCastExpr(hasCastKind(CK_NoOp)))),
+ hasUnaryOperand(equalsNode(Exp)));
+ const auto AsPointerFromArrayDecay =
+ castExpr(hasCastKind(CK_ArrayToPointerDecay),
+ unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp)));
+ // Treat calling `operator->()` of move-only classes as taking address.
+ // These are typically smart pointers with unique ownership so we treat
+ // mutation of pointee as mutation of the smart pointer itself.
+ const auto AsOperatorArrowThis =
+ cxxOperatorCallExpr(hasOverloadedOperatorName("->"),
+ callee(cxxMethodDecl(ofClass(isMoveOnly()),
+ returns(nonConstPointerType()))),
+ argumentCountIs(1), hasArgument(0, equalsNode(Exp)));
+
+ // Used as non-const-ref argument when calling a function.
+ // An argument is assumed to be non-const-ref when the function is unresolved.
+ // Instantiated template functions are not handled here but in
+ // findFunctionArgMutation which has additional smarts for handling forwarding
+ // references.
+ const auto NonConstRefParam = forEachArgumentWithParam(
+ equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType())));
+ const auto NotInstantiated = unless(hasDeclaration(isInstantiated()));
+ const auto AsNonConstRefArg = anyOf(
+ callExpr(NonConstRefParam, NotInstantiated),
+ cxxConstructExpr(NonConstRefParam, NotInstantiated),
+ callExpr(callee(expr(anyOf(unresolvedLookupExpr(), unresolvedMemberExpr(),
+ cxxDependentScopeMemberExpr(),
+ hasType(templateTypeParmType())))),
+ hasAnyArgument(equalsNode(Exp))),
+ cxxUnresolvedConstructExpr(hasAnyArgument(equalsNode(Exp))));
+
+ // Captured by a lambda by reference.
+ // If we're initializing a capture with 'Exp' directly then we're initializing
+ // a reference capture.
+ // For value captures there will be an ImplicitCastExpr <LValueToRValue>.
+ const auto AsLambdaRefCaptureInit = lambdaExpr(hasCaptureInit(Exp));
+
+ // Returned as non-const-ref.
+ // If we're returning 'Exp' directly then it's returned as non-const-ref.
+ // For returning by value there will be an ImplicitCastExpr <LValueToRValue>.
+ // For returning by const-ref there will be an ImplicitCastExpr <NoOp> (for
+ // adding const.)
+ const auto AsNonConstRefReturn = returnStmt(hasReturnValue(equalsNode(Exp)));
+
+ const auto Matches =
+ match(findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis,
+ AsAmpersandOperand, AsPointerFromArrayDecay,
+ AsOperatorArrowThis, AsNonConstRefArg,
+ AsLambdaRefCaptureInit, AsNonConstRefReturn))
+ .bind("stmt")),
+ Stm, Context);
+ return selectFirst<Stmt>("stmt", Matches);
+}
+
+const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) {
+ // Check whether any member of 'Exp' is mutated.
+ const auto MemberExprs =
+ match(findAll(expr(anyOf(memberExpr(hasObjectExpression(equalsNode(Exp))),
+ cxxDependentScopeMemberExpr(
+ hasObjectExpression(equalsNode(Exp)))))
+ .bind(NodeID<Expr>::value)),
+ Stm, Context);
+ return findExprMutation(MemberExprs);
+}
+
+const Stmt *ExprMutationAnalyzer::findArrayElementMutation(const Expr *Exp) {
+ // Check whether any element of an array is mutated.
+ const auto SubscriptExprs = match(
+ findAll(arraySubscriptExpr(hasBase(ignoringImpCasts(equalsNode(Exp))))
+ .bind(NodeID<Expr>::value)),
+ Stm, Context);
+ return findExprMutation(SubscriptExprs);
+}
+
+const Stmt *ExprMutationAnalyzer::findCastMutation(const Expr *Exp) {
+ // If 'Exp' is casted to any non-const reference type, check the castExpr.
+ const auto Casts =
+ match(findAll(castExpr(hasSourceExpression(equalsNode(Exp)),
+ anyOf(explicitCastExpr(hasDestinationType(
+ nonConstReferenceType())),
+ implicitCastExpr(hasImplicitDestinationType(
+ nonConstReferenceType()))))
+ .bind(NodeID<Expr>::value)),
+ Stm, Context);
+ if (const Stmt *S = findExprMutation(Casts))
+ return S;
+ // Treat std::{move,forward} as cast.
+ const auto Calls =
+ match(findAll(callExpr(callee(namedDecl(
+ hasAnyName("::std::move", "::std::forward"))),
+ hasArgument(0, equalsNode(Exp)))
+ .bind("expr")),
+ Stm, Context);
+ return findExprMutation(Calls);
+}
+
+const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) {
+ // If range for looping over 'Exp' with a non-const reference loop variable,
+ // check all declRefExpr of the loop variable.
+ const auto LoopVars =
+ match(findAll(cxxForRangeStmt(
+ hasLoopVariable(varDecl(hasType(nonConstReferenceType()))
+ .bind(NodeID<Decl>::value)),
+ hasRangeInit(equalsNode(Exp)))),
+ Stm, Context);
+ return findDeclMutation(LoopVars);
+}
+
+const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) {
+ // Follow non-const reference returned by `operator*()` of move-only classes.
+ // These are typically smart pointers with unique ownership so we treat
+ // mutation of pointee as mutation of the smart pointer itself.
+ const auto Ref =
+ match(findAll(cxxOperatorCallExpr(
+ hasOverloadedOperatorName("*"),
+ callee(cxxMethodDecl(ofClass(isMoveOnly()),
+ returns(nonConstReferenceType()))),
+ argumentCountIs(1), hasArgument(0, equalsNode(Exp)))
+ .bind(NodeID<Expr>::value)),
+ Stm, Context);
+ if (const Stmt *S = findExprMutation(Ref))
+ return S;
+
+ // If 'Exp' is bound to a non-const reference, check all declRefExpr to that.
+ const auto Refs = match(
+ stmt(forEachDescendant(
+ varDecl(
+ hasType(nonConstReferenceType()),
+ hasInitializer(anyOf(equalsNode(Exp),
+ conditionalOperator(anyOf(
+ hasTrueExpression(equalsNode(Exp)),
+ hasFalseExpression(equalsNode(Exp)))))),
+ hasParent(declStmt().bind("stmt")),
+ // Don't follow the reference in range statement, we've handled
+ // that separately.
+ unless(hasParent(declStmt(hasParent(
+ cxxForRangeStmt(hasRangeStmt(equalsBoundNode("stmt"))))))))
+ .bind(NodeID<Decl>::value))),
+ Stm, Context);
+ return findDeclMutation(Refs);
+}
+
+const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
+ const auto NonConstRefParam = forEachArgumentWithParam(
+ equalsNode(Exp),
+ parmVarDecl(hasType(nonConstReferenceType())).bind("parm"));
+ const auto IsInstantiated = hasDeclaration(isInstantiated());
+ const auto FuncDecl = hasDeclaration(functionDecl().bind("func"));
+ const auto Matches = match(
+ findAll(expr(anyOf(callExpr(NonConstRefParam, IsInstantiated, FuncDecl,
+ unless(callee(namedDecl(hasAnyName(
+ "::std::move", "::std::forward"))))),
+ cxxConstructExpr(NonConstRefParam, IsInstantiated,
+ FuncDecl)))
+ .bind(NodeID<Expr>::value)),
+ Stm, Context);
+ for (const auto &Nodes : Matches) {
+ const auto *Exp = Nodes.getNodeAs<Expr>(NodeID<Expr>::value);
+ const auto *Func = Nodes.getNodeAs<FunctionDecl>("func");
+ if (!Func->getBody() || !Func->getPrimaryTemplate())
+ return Exp;
+
+ const auto *Parm = Nodes.getNodeAs<ParmVarDecl>("parm");
+ const ArrayRef<ParmVarDecl *> AllParams =
+ Func->getPrimaryTemplate()->getTemplatedDecl()->parameters();
+ QualType ParmType =
+ AllParams[std::min<size_t>(Parm->getFunctionScopeIndex(),
+ AllParams.size() - 1)]
+ ->getType();
+ if (const auto *T = ParmType->getAs<PackExpansionType>())
+ ParmType = T->getPattern();
+
+ // If param type is forwarding reference, follow into the function
+ // definition and see whether the param is mutated inside.
+ if (const auto *RefType = ParmType->getAs<RValueReferenceType>()) {
+ if (!RefType->getPointeeType().getQualifiers() &&
+ RefType->getPointeeType()->getAs<TemplateTypeParmType>()) {
+ std::unique_ptr<FunctionParmMutationAnalyzer> &Analyzer =
+ FuncParmAnalyzer[Func];
+ if (!Analyzer)
+ Analyzer.reset(new FunctionParmMutationAnalyzer(*Func, Context));
+ if (Analyzer->findMutation(Parm))
+ return Exp;
+ continue;
+ }
+ }
+ // Not forwarding reference.
+ return Exp;
+ }
+ return nullptr;
+}
+
+FunctionParmMutationAnalyzer::FunctionParmMutationAnalyzer(
+ const FunctionDecl &Func, ASTContext &Context)
+ : BodyAnalyzer(*Func.getBody(), Context) {
+ if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(&Func)) {
+ // CXXCtorInitializer might also mutate Param but they're not part of
+ // function body, check them eagerly here since they're typically trivial.
+ for (const CXXCtorInitializer *Init : Ctor->inits()) {
+ ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context);
+ for (const ParmVarDecl *Parm : Ctor->parameters()) {
+ if (Results.find(Parm) != Results.end())
+ continue;
+ if (const Stmt *S = InitAnalyzer.findMutation(Parm))
+ Results[Parm] = S;
+ }
+ }
+ }
+}
+
+const Stmt *
+FunctionParmMutationAnalyzer::findMutation(const ParmVarDecl *Parm) {
+ const auto Memoized = Results.find(Parm);
+ if (Memoized != Results.end())
+ return Memoized->second;
+
+ if (const Stmt *S = BodyAnalyzer.findMutation(Parm))
+ return Results[Parm] = S;
+
+ return Results[Parm] = nullptr;
+}
+
+} // namespace clang
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 05bc1a5d102c..afe2d264907f 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -93,6 +93,7 @@ public:
LiveVariables::Observer *obs = nullptr);
void dumpBlockLiveness(const SourceManager& M);
+ void dumpStmtLiveness(const SourceManager& M);
LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign)
: analysisContext(ac),
@@ -237,8 +238,8 @@ static const Stmt *LookThroughStmt(const Stmt *S) {
while (S) {
if (const Expr *Ex = dyn_cast<Expr>(S))
S = Ex->IgnoreParens();
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) {
- S = EWC->getSubExpr();
+ if (const FullExpr *FE = dyn_cast<FullExpr>(S)) {
+ S = FE->getSubExpr();
continue;
}
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
@@ -327,6 +328,35 @@ void TransferFunctions::Visit(Stmt *S) {
// No need to unconditionally visit subexpressions.
return;
}
+ case Stmt::IfStmtClass: {
+ // If one of the branches is an expression rather than a compound
+ // statement, it will be bad if we mark it as live at the terminator
+ // of the if-statement (i.e., immediately after the condition expression).
+ AddLiveStmt(val.liveStmts, LV.SSetFact, cast<IfStmt>(S)->getCond());
+ return;
+ }
+ case Stmt::WhileStmtClass: {
+ // If the loop body is an expression rather than a compound statement,
+ // it will be bad if we mark it as live at the terminator of the loop
+ // (i.e., immediately after the condition expression).
+ AddLiveStmt(val.liveStmts, LV.SSetFact, cast<WhileStmt>(S)->getCond());
+ return;
+ }
+ case Stmt::DoStmtClass: {
+ // If the loop body is an expression rather than a compound statement,
+ // it will be bad if we mark it as live at the terminator of the loop
+ // (i.e., immediately after the condition expression).
+ AddLiveStmt(val.liveStmts, LV.SSetFact, cast<DoStmt>(S)->getCond());
+ return;
+ }
+ case Stmt::ForStmtClass: {
+ // If the loop body is an expression rather than a compound statement,
+ // it will be bad if we mark it as live at the terminator of the loop
+ // (i.e., immediately after the condition expression).
+ AddLiveStmt(val.liveStmts, LV.SSetFact, cast<ForStmt>(S)->getCond());
+ return;
+ }
+
}
for (Stmt *Child : S->children()) {
@@ -597,7 +627,7 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
it != ei; ++it) {
vec.push_back(it->first);
}
- llvm::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
+ llvm::sort(vec, [](const CFGBlock *A, const CFGBlock *B) {
return A->getBlockID() < B->getBlockID();
});
@@ -617,21 +647,38 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
declVec.push_back(*si);
}
- llvm::sort(declVec.begin(), declVec.end(),
- [](const Decl *A, const Decl *B) {
- return A->getLocStart() < B->getLocStart();
+ llvm::sort(declVec, [](const Decl *A, const Decl *B) {
+ return A->getBeginLoc() < B->getBeginLoc();
});
for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
de = declVec.end(); di != de; ++di) {
llvm::errs() << " " << (*di)->getDeclName().getAsString()
<< " <";
- (*di)->getLocation().dump(M);
+ (*di)->getLocation().print(llvm::errs(), M);
llvm::errs() << ">\n";
}
}
llvm::errs() << "\n";
}
+void LiveVariables::dumpStmtLiveness(const SourceManager &M) {
+ getImpl(impl).dumpStmtLiveness(M);
+}
+
+void LiveVariablesImpl::dumpStmtLiveness(const SourceManager &M) {
+ // Don't iterate over blockEndsToLiveness directly because it's not sorted.
+ for (auto I : *analysisContext.getCFG()) {
+
+ llvm::errs() << "\n[ B" << I->getBlockID()
+ << " (live statements at block exit) ]\n";
+ for (auto S : blocksEndToLiveness[I].liveStmts) {
+ llvm::errs() << "\n";
+ S->dump();
+ }
+ llvm::errs() << "\n";
+ }
+}
+
const void *LiveVariables::getTag() { static int x; return &x; }
const void *RelaxedLiveVariables::getTag() { static int x; return &x; }
diff --git a/lib/Analysis/ProgramPoint.cpp b/lib/Analysis/ProgramPoint.cpp
index d9833659d7b3..2d016cb13353 100644
--- a/lib/Analysis/ProgramPoint.cpp
+++ b/lib/Analysis/ProgramPoint.cpp
@@ -43,6 +43,181 @@ ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
}
}
+LLVM_DUMP_METHOD void ProgramPoint::dump() const {
+ return print(/*CR=*/"\n", llvm::errs());
+}
+
+static void printLocation(raw_ostream &Out, SourceLocation SLoc,
+ const SourceManager &SM,
+ StringRef CR,
+ StringRef Postfix) {
+ if (SLoc.isFileID()) {
+ Out << CR << "line=" << SM.getExpansionLineNumber(SLoc)
+ << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix;
+ }
+}
+
+void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const {
+ const ASTContext &Context =
+ getLocationContext()->getAnalysisDeclContext()->getASTContext();
+ const SourceManager &SM = Context.getSourceManager();
+ switch (getKind()) {
+ case ProgramPoint::BlockEntranceKind:
+ Out << "Block Entrance: B"
+ << castAs<BlockEntrance>().getBlock()->getBlockID();
+ break;
+
+ case ProgramPoint::FunctionExitKind: {
+ auto FEP = getAs<FunctionExitPoint>();
+ Out << "Function Exit: B" << FEP->getBlock()->getBlockID();
+ if (const ReturnStmt *RS = FEP->getStmt()) {
+ Out << CR << " Return: S" << RS->getID(Context) << CR;
+ RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
+ /*Indentation=*/2, /*NewlineSymbol=*/CR);
+ }
+ break;
+ }
+ case ProgramPoint::BlockExitKind:
+ assert(false);
+ break;
+
+ case ProgramPoint::CallEnterKind:
+ Out << "CallEnter";
+ break;
+
+ case ProgramPoint::CallExitBeginKind:
+ Out << "CallExitBegin";
+ break;
+
+ case ProgramPoint::CallExitEndKind:
+ Out << "CallExitEnd";
+ break;
+
+ case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
+ Out << "PostStmtPurgeDeadSymbols";
+ break;
+
+ case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
+ Out << "PreStmtPurgeDeadSymbols";
+ break;
+
+ case ProgramPoint::EpsilonKind:
+ Out << "Epsilon Point";
+ break;
+
+ case ProgramPoint::LoopExitKind: {
+ LoopExit LE = castAs<LoopExit>();
+ Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName();
+ break;
+ }
+
+ case ProgramPoint::PreImplicitCallKind: {
+ ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
+ Out << "PreCall: ";
+ PC.getDecl()->print(Out, Context.getLangOpts());
+ printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
+ break;
+ }
+
+ case ProgramPoint::PostImplicitCallKind: {
+ ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
+ Out << "PostCall: ";
+ PC.getDecl()->print(Out, Context.getLangOpts());
+ printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
+ break;
+ }
+
+ case ProgramPoint::PostInitializerKind: {
+ Out << "PostInitializer: ";
+ const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();
+ if (const FieldDecl *FD = Init->getAnyMember())
+ Out << *FD;
+ else {
+ QualType Ty = Init->getTypeSourceInfo()->getType();
+ Ty = Ty.getLocalUnqualifiedType();
+ Ty.print(Out, Context.getLangOpts());
+ }
+ break;
+ }
+
+ case ProgramPoint::BlockEdgeKind: {
+ const BlockEdge &E = castAs<BlockEdge>();
+ Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
+ << E.getDst()->getBlockID() << ')';
+
+ if (const Stmt *T = E.getSrc()->getTerminator()) {
+ SourceLocation SLoc = T->getBeginLoc();
+
+ Out << "\\|Terminator: ";
+ E.getSrc()->printTerminator(Out, Context.getLangOpts());
+ printLocation(Out, SLoc, SM, CR, /*Postfix=*/"");
+
+ if (isa<SwitchStmt>(T)) {
+ const Stmt *Label = E.getDst()->getLabel();
+
+ if (Label) {
+ if (const auto *C = dyn_cast<CaseStmt>(Label)) {
+ Out << CR << "case ";
+ if (C->getLHS())
+ C->getLHS()->printPretty(
+ Out, nullptr, Context.getPrintingPolicy(),
+ /*Indentation=*/0, /*NewlineSymbol=*/CR);
+
+ if (const Stmt *RHS = C->getRHS()) {
+ Out << " .. ";
+ RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(),
+ /*Indetation=*/0, /*NewlineSymbol=*/CR);
+ }
+
+ Out << ":";
+ } else {
+ assert(isa<DefaultStmt>(Label));
+ Out << CR << "default:";
+ }
+ } else
+ Out << CR << "(implicit) default:";
+ } else if (isa<IndirectGotoStmt>(T)) {
+ // FIXME
+ } else {
+ Out << CR << "Condition: ";
+ if (*E.getSrc()->succ_begin() == E.getDst())
+ Out << "true";
+ else
+ Out << "false";
+ }
+
+ Out << CR;
+ }
+
+ break;
+ }
+
+ default: {
+ const Stmt *S = castAs<StmtPoint>().getStmt();
+ assert(S != nullptr && "Expecting non-null Stmt");
+
+ Out << S->getStmtClassName() << " S" << S->getID(Context) << " <"
+ << (const void *)S << "> ";
+ S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
+ /*Indentation=*/2, /*NewlineSymbol=*/CR);
+ printLocation(Out, S->getBeginLoc(), SM, CR, /*Postfix=*/"");
+
+ if (getAs<PreStmt>())
+ Out << CR << "PreStmt" << CR;
+ else if (getAs<PostLoad>())
+ Out << CR << "PostLoad" << CR;
+ else if (getAs<PostStore>())
+ Out << CR << "PostStore" << CR;
+ else if (getAs<PostLValue>())
+ Out << CR << "PostLValue" << CR;
+ else if (getAs<PostAllocatorCall>())
+ Out << CR << "PostAllocatorCall" << CR;
+
+ break;
+ }
+ }
+}
+
SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
StringRef Msg)
: Desc((MsgProvider + " : " + Msg).str()) {}
diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp
deleted file mode 100644
index 83b545a7be83..000000000000
--- a/lib/Analysis/PseudoConstantAnalysis.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-//== PseudoConstantAnalysis.cpp - Find Pseudoconstants in the AST-*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file tracks the usage of variables in a Decl body to see if they are
-// never written to, implying that they constant. This is useful in static
-// analysis to see if a developer might have intended a variable to be const.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Stmt.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include <deque>
-
-using namespace clang;
-
-typedef llvm::SmallPtrSet<const VarDecl*, 32> VarDeclSet;
-
-PseudoConstantAnalysis::PseudoConstantAnalysis(const Stmt *DeclBody) :
- DeclBody(DeclBody), Analyzed(false) {
- NonConstantsImpl = new VarDeclSet;
- UsedVarsImpl = new VarDeclSet;
-}
-
-PseudoConstantAnalysis::~PseudoConstantAnalysis() {
- delete (VarDeclSet*)NonConstantsImpl;
- delete (VarDeclSet*)UsedVarsImpl;
-}
-
-// Returns true if the given ValueDecl is never written to in the given DeclBody
-bool PseudoConstantAnalysis::isPseudoConstant(const VarDecl *VD) {
- // Only local and static variables can be pseudoconstants
- if (!VD->hasLocalStorage() && !VD->isStaticLocal())
- return false;
-
- if (!Analyzed) {
- RunAnalysis();
- Analyzed = true;
- }
-
- VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
-
- return !NonConstants->count(VD);
-}
-
-// Returns true if the variable was used (self assignments don't count)
-bool PseudoConstantAnalysis::wasReferenced(const VarDecl *VD) {
- if (!Analyzed) {
- RunAnalysis();
- Analyzed = true;
- }
-
- VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
-
- return UsedVars->count(VD);
-}
-
-// Returns a Decl from a (Block)DeclRefExpr (if any)
-const Decl *PseudoConstantAnalysis::getDecl(const Expr *E) {
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
- return DR->getDecl();
- else
- return nullptr;
-}
-
-void PseudoConstantAnalysis::RunAnalysis() {
- std::deque<const Stmt *> WorkList;
- VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
- VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
-
- // Start with the top level statement of the function
- WorkList.push_back(DeclBody);
-
- while (!WorkList.empty()) {
- const Stmt *Head = WorkList.front();
- WorkList.pop_front();
-
- if (const Expr *Ex = dyn_cast<Expr>(Head))
- Head = Ex->IgnoreParenCasts();
-
- switch (Head->getStmtClass()) {
- // Case 1: Assignment operators modifying VarDecls
- case Stmt::BinaryOperatorClass: {
- const BinaryOperator *BO = cast<BinaryOperator>(Head);
- // Look for a Decl on the LHS
- const Decl *LHSDecl = getDecl(BO->getLHS()->IgnoreParenCasts());
- if (!LHSDecl)
- break;
-
- // We found a binary operator with a DeclRefExpr on the LHS. We now check
- // for any of the assignment operators, implying that this Decl is being
- // written to.
- switch (BO->getOpcode()) {
- // Self-assignments don't count as use of a variable
- case BO_Assign: {
- // Look for a DeclRef on the RHS
- const Decl *RHSDecl = getDecl(BO->getRHS()->IgnoreParenCasts());
-
- // If the Decls match, we have self-assignment
- if (LHSDecl == RHSDecl)
- // Do not visit the children
- continue;
-
- LLVM_FALLTHROUGH;
- }
- case BO_AddAssign:
- case BO_SubAssign:
- case BO_MulAssign:
- case BO_DivAssign:
- case BO_AndAssign:
- case BO_OrAssign:
- case BO_XorAssign:
- case BO_ShlAssign:
- case BO_ShrAssign: {
- const VarDecl *VD = dyn_cast<VarDecl>(LHSDecl);
- // The DeclRefExpr is being assigned to - mark it as non-constant
- if (VD)
- NonConstants->insert(VD);
- break;
- }
-
- default:
- break;
- }
- break;
- }
-
- // Case 2: Pre/post increment/decrement and address of
- case Stmt::UnaryOperatorClass: {
- const UnaryOperator *UO = cast<UnaryOperator>(Head);
-
- // Look for a DeclRef in the subexpression
- const Decl *D = getDecl(UO->getSubExpr()->IgnoreParenCasts());
- if (!D)
- break;
-
- // We found a unary operator with a DeclRef as a subexpression. We now
- // check for any of the increment/decrement operators, as well as
- // addressOf.
- switch (UO->getOpcode()) {
- case UO_PostDec:
- case UO_PostInc:
- case UO_PreDec:
- case UO_PreInc:
- // The DeclRef is being changed - mark it as non-constant
- case UO_AddrOf: {
- // If we are taking the address of the DeclRefExpr, assume it is
- // non-constant.
- const VarDecl *VD = dyn_cast<VarDecl>(D);
- if (VD)
- NonConstants->insert(VD);
- break;
- }
-
- default:
- break;
- }
- break;
- }
-
- // Case 3: Reference Declarations
- case Stmt::DeclStmtClass: {
- const DeclStmt *DS = cast<DeclStmt>(Head);
- // Iterate over each decl and see if any of them contain reference decls
- for (const auto *I : DS->decls()) {
- // We only care about VarDecls
- const VarDecl *VD = dyn_cast<VarDecl>(I);
- if (!VD)
- continue;
-
- // We found a VarDecl; make sure it is a reference type
- if (!VD->getType().getTypePtr()->isReferenceType())
- continue;
-
- // Try to find a Decl in the initializer
- const Decl *D = getDecl(VD->getInit()->IgnoreParenCasts());
- if (!D)
- break;
-
- // If the reference is to another var, add the var to the non-constant
- // list
- if (const VarDecl *RefVD = dyn_cast<VarDecl>(D)) {
- NonConstants->insert(RefVD);
- continue;
- }
- }
- break;
- }
-
- // Case 4: Variable references
- case Stmt::DeclRefExprClass: {
- const DeclRefExpr *DR = cast<DeclRefExpr>(Head);
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- // Add the Decl to the used list
- UsedVars->insert(VD);
- continue;
- }
- break;
- }
-
- // Case 5: Block expressions
- case Stmt::BlockExprClass: {
- const BlockExpr *B = cast<BlockExpr>(Head);
- // Add the body of the block to the list
- WorkList.push_back(B->getBody());
- continue;
- }
-
- default:
- break;
- } // switch (head->getStmtClass())
-
- // Add all substatements to the worklist
- for (const Stmt *SubStmt : Head->children())
- if (SubStmt)
- WorkList.push_back(SubStmt);
- } // while (!WorkList.empty())
-}
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index ed26a94f3d60..87f4f7010f98 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -153,7 +153,7 @@ static bool isExpandedFromConfigurationMacro(const Stmt *S,
// value comes from a macro, but we can do much better. This is likely
// to be over conservative. This logic is factored into a separate function
// so that we can refine it later.
- SourceLocation L = S->getLocStart();
+ SourceLocation L = S->getBeginLoc();
if (L.isMacroID()) {
SourceManager &SM = PP.getSourceManager();
if (IgnoreYES_NO) {
@@ -200,7 +200,7 @@ static bool isConfigurationValue(const Stmt *S,
// Special case looking for the sigil '()' around an integer literal.
if (const ParenExpr *PE = dyn_cast<ParenExpr>(S))
- if (!PE->getLocStart().isMacroID())
+ if (!PE->getBeginLoc().isMacroID())
return isConfigurationValue(PE->getSubExpr(), PP, SilenceableCondVal,
IncludeIntegers, true);
@@ -219,7 +219,7 @@ static bool isConfigurationValue(const Stmt *S,
return isConfigurationValue(cast<DeclRefExpr>(S)->getDecl(), PP);
case Stmt::ObjCBoolLiteralExprClass:
IgnoreYES_NO = true;
- // Fallthrough.
+ LLVM_FALLTHROUGH;
case Stmt::CXXBoolLiteralExprClass:
case Stmt::IntegerLiteralClass: {
const Expr *E = cast<Expr>(S);
@@ -446,7 +446,7 @@ bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
}
static bool isValidDeadStmt(const Stmt *S) {
- if (S->getLocStart().isInvalid())
+ if (S->getBeginLoc().isInvalid())
return false;
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))
return BO->getOpcode() != BO_Comma;
@@ -474,9 +474,9 @@ const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
static int SrcCmp(const std::pair<const CFGBlock *, const Stmt *> *p1,
const std::pair<const CFGBlock *, const Stmt *> *p2) {
- if (p1->second->getLocStart() < p2->second->getLocStart())
+ if (p1->second->getBeginLoc() < p2->second->getBeginLoc())
return -1;
- if (p2->second->getLocStart() < p1->second->getLocStart())
+ if (p2->second->getBeginLoc() < p1->second->getBeginLoc())
return 1;
return 0;
}
@@ -509,7 +509,7 @@ unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start,
}
// Specially handle macro-expanded code.
- if (S->getLocStart().isMacroID()) {
+ if (S->getBeginLoc().isMacroID()) {
count += scanMaybeReachableFromBlock(Block, PP, Reachable);
continue;
}
@@ -592,7 +592,7 @@ static SourceLocation GetUnreachableLoc(const Stmt *S,
case Expr::CXXFunctionalCastExprClass: {
const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
R1 = CE->getSubExpr()->getSourceRange();
- return CE->getLocStart();
+ return CE->getBeginLoc();
}
case Stmt::CXXTryStmtClass: {
return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
@@ -605,7 +605,7 @@ static SourceLocation GetUnreachableLoc(const Stmt *S,
default: ;
}
R1 = S->getSourceRange();
- return S->getLocStart();
+ return S->getBeginLoc();
}
void DeadCodeScan::reportDeadCode(const CFGBlock *B,
@@ -631,12 +631,12 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
// a for/for-range loop. This is the block that contains
// the increment code.
if (const Stmt *LoopTarget = B->getLoopTarget()) {
- SourceLocation Loc = LoopTarget->getLocStart();
+ SourceLocation Loc = LoopTarget->getBeginLoc();
SourceRange R1(Loc, Loc), R2;
if (const ForStmt *FS = dyn_cast<ForStmt>(LoopTarget)) {
const Expr *Inc = FS->getInc();
- Loc = Inc->getLocStart();
+ Loc = Inc->getBeginLoc();
R2 = Inc->getSourceRange();
}
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 03cc234dce5c..78e1b056e1d7 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -33,6 +33,7 @@
#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
@@ -41,6 +42,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -64,13 +66,6 @@ using namespace threadSafety;
// Key method definition
ThreadSafetyHandler::~ThreadSafetyHandler() = default;
-namespace {
-
-class TILPrinter :
- public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
-
-} // namespace
-
/// Issue a warning about an invalid lock expression
static void warnInvalidLock(ThreadSafetyHandler &Handler,
const Expr *MutexExp, const NamedDecl *D,
@@ -86,8 +81,8 @@ static void warnInvalidLock(ThreadSafetyHandler &Handler,
namespace {
-/// A set of CapabilityInfo objects, which are compiled from the
-/// requires attributes on a function.
+/// A set of CapabilityExpr objects, which are compiled from thread safety
+/// attributes on a function.
class CapExprSet : public SmallVector<CapabilityExpr, 4> {
public:
/// Push M onto list, but discard duplicates.
@@ -142,13 +137,16 @@ public:
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
SourceLocation JoinLoc, LockErrorKind LEK,
ThreadSafetyHandler &Handler) const = 0;
+ virtual void handleLock(FactSet &FSet, FactManager &FactMan,
+ const FactEntry &entry, ThreadSafetyHandler &Handler,
+ StringRef DiagKind) const = 0;
virtual void handleUnlock(FactSet &FSet, FactManager &FactMan,
const CapabilityExpr &Cp, SourceLocation UnlockLoc,
bool FullyRemove, ThreadSafetyHandler &Handler,
StringRef DiagKind) const = 0;
// Return true if LKind >= LK, where exclusive > shared
- bool isAtLeast(LockKind LK) {
+ bool isAtLeast(LockKind LK) const {
return (LKind == LK_Exclusive) || (LK == LK_Shared);
}
};
@@ -159,7 +157,7 @@ using FactID = unsigned short;
/// the analysis of a single routine.
class FactManager {
private:
- std::vector<std::unique_ptr<FactEntry>> Facts;
+ std::vector<std::unique_ptr<const FactEntry>> Facts;
public:
FactID newFact(std::unique_ptr<FactEntry> Entry) {
@@ -168,7 +166,6 @@ public:
}
const FactEntry &operator[](FactID F) const { return *Facts[F]; }
- FactEntry &operator[](FactID F) { return *Facts[F]; }
};
/// A FactSet is the set of facts that are known to be true at a
@@ -238,22 +235,23 @@ public:
});
}
- FactEntry *findLock(FactManager &FM, const CapabilityExpr &CapE) const {
+ const FactEntry *findLock(FactManager &FM, const CapabilityExpr &CapE) const {
auto I = std::find_if(begin(), end(), [&](FactID ID) {
return FM[ID].matches(CapE);
});
return I != end() ? &FM[*I] : nullptr;
}
- FactEntry *findLockUniv(FactManager &FM, const CapabilityExpr &CapE) const {
+ const FactEntry *findLockUniv(FactManager &FM,
+ const CapabilityExpr &CapE) const {
auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
return FM[ID].matchesUniv(CapE);
});
return I != end() ? &FM[*I] : nullptr;
}
- FactEntry *findPartialMatch(FactManager &FM,
- const CapabilityExpr &CapE) const {
+ const FactEntry *findPartialMatch(FactManager &FM,
+ const CapabilityExpr &CapE) const {
auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
return FM[ID].partiallyMatches(CapE);
});
@@ -419,7 +417,7 @@ private:
Context::Factory ContextFactory;
std::vector<VarDefinition> VarDefinitions;
std::vector<unsigned> CtxIndices;
- std::vector<std::pair<Stmt *, Context>> SavedContexts;
+ std::vector<std::pair<const Stmt *, Context>> SavedContexts;
public:
LocalVariableMap() {
@@ -460,7 +458,7 @@ public:
/// Return the next context after processing S. This function is used by
/// clients of the class to get the appropriate context when traversing the
/// CFG. It must be called for every assignment or DeclStmt.
- Context getNextContext(unsigned &CtxIndex, Stmt *S, Context C) {
+ Context getNextContext(unsigned &CtxIndex, const Stmt *S, Context C) {
if (SavedContexts[CtxIndex+1].first == S) {
CtxIndex++;
Context Result = SavedContexts[CtxIndex].second;
@@ -522,7 +520,7 @@ protected:
unsigned getContextIndex() { return SavedContexts.size()-1; }
// Save the current context for later replay
- void saveContext(Stmt *S, Context C) {
+ void saveContext(const Stmt *S, Context C) {
SavedContexts.push_back(std::make_pair(S, C));
}
@@ -592,7 +590,7 @@ CFGBlockInfo CFGBlockInfo::getEmptyBlockInfo(LocalVariableMap &M) {
namespace {
/// Visitor which builds a LocalVariableMap
-class VarMapBuilder : public StmtVisitor<VarMapBuilder> {
+class VarMapBuilder : public ConstStmtVisitor<VarMapBuilder> {
public:
LocalVariableMap* VMap;
LocalVariableMap::Context Ctx;
@@ -600,16 +598,16 @@ public:
VarMapBuilder(LocalVariableMap *VM, LocalVariableMap::Context C)
: VMap(VM), Ctx(C) {}
- void VisitDeclStmt(DeclStmt *S);
- void VisitBinaryOperator(BinaryOperator *BO);
+ void VisitDeclStmt(const DeclStmt *S);
+ void VisitBinaryOperator(const BinaryOperator *BO);
};
} // namespace
// Add new local variables to the variable map
-void VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
+void VarMapBuilder::VisitDeclStmt(const DeclStmt *S) {
bool modifiedCtx = false;
- DeclGroupRef DGrp = S->getDeclGroup();
+ const DeclGroupRef DGrp = S->getDeclGroup();
for (const auto *D : DGrp) {
if (const auto *VD = dyn_cast_or_null<VarDecl>(D)) {
const Expr *E = VD->getInit();
@@ -627,7 +625,7 @@ void VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
}
// Update local variable definitions in variable map
-void VarMapBuilder::VisitBinaryOperator(BinaryOperator *BO) {
+void VarMapBuilder::VisitBinaryOperator(const BinaryOperator *BO) {
if (!BO->isAssignmentOp())
return;
@@ -734,7 +732,7 @@ void LocalVariableMap::traverseCFG(CFG *CFGraph,
CtxIndices.resize(CFGraph->getNumBlockIDs());
for (const auto *CurrBlock : *SortedGraph) {
- int CurrBlockID = CurrBlock->getBlockID();
+ unsigned CurrBlockID = CurrBlock->getBlockID();
CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
VisitedBlocks.insert(CurrBlock);
@@ -750,7 +748,7 @@ void LocalVariableMap::traverseCFG(CFG *CFGraph,
continue;
}
- int PrevBlockID = (*PI)->getBlockID();
+ unsigned PrevBlockID = (*PI)->getBlockID();
CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
if (CtxInit) {
@@ -780,7 +778,7 @@ void LocalVariableMap::traverseCFG(CFG *CFGraph,
switch (BI.getKind()) {
case CFGElement::Statement: {
CFGStmt CS = BI.castAs<CFGStmt>();
- VMapBuilder.Visit(const_cast<Stmt *>(CS.getStmt()));
+ VMapBuilder.Visit(CS.getStmt());
break;
}
default:
@@ -819,13 +817,13 @@ static void findBlockLocations(CFG *CFGraph,
// Find the source location of the last statement in the block, if the
// block is not empty.
if (const Stmt *S = CurrBlock->getTerminator()) {
- CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getLocStart();
+ CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getBeginLoc();
} else {
for (CFGBlock::const_reverse_iterator BI = CurrBlock->rbegin(),
BE = CurrBlock->rend(); BI != BE; ++BI) {
// FIXME: Handle other CFGElement kinds.
if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>()) {
- CurrBlockInfo->ExitLoc = CS->getStmt()->getLocStart();
+ CurrBlockInfo->ExitLoc = CS->getStmt()->getBeginLoc();
break;
}
}
@@ -837,7 +835,7 @@ static void findBlockLocations(CFG *CFGraph,
for (const auto &BI : *CurrBlock) {
// FIXME: Handle other CFGElement kinds.
if (Optional<CFGStmt> CS = BI.getAs<CFGStmt>()) {
- CurrBlockInfo->EntryLoc = CS->getStmt()->getLocStart();
+ CurrBlockInfo->EntryLoc = CS->getStmt()->getBeginLoc();
break;
}
}
@@ -873,6 +871,12 @@ public:
}
}
+ void handleLock(FactSet &FSet, FactManager &FactMan, const FactEntry &entry,
+ ThreadSafetyHandler &Handler,
+ StringRef DiagKind) const override {
+ Handler.handleDoubleLock(DiagKind, entry.toString(), entry.loc());
+ }
+
void handleUnlock(FactSet &FSet, FactManager &FactMan,
const CapabilityExpr &Cp, SourceLocation UnlockLoc,
bool FullyRemove, ThreadSafetyHandler &Handler,
@@ -887,63 +891,117 @@ public:
class ScopedLockableFactEntry : public FactEntry {
private:
- SmallVector<const til::SExpr *, 4> UnderlyingMutexes;
+ enum UnderlyingCapabilityKind {
+ UCK_Acquired, ///< Any kind of acquired capability.
+ UCK_ReleasedShared, ///< Shared capability that was released.
+ UCK_ReleasedExclusive, ///< Exclusive capability that was released.
+ };
+
+ using UnderlyingCapability =
+ llvm::PointerIntPair<const til::SExpr *, 2, UnderlyingCapabilityKind>;
+
+ SmallVector<UnderlyingCapability, 4> UnderlyingMutexes;
public:
- ScopedLockableFactEntry(const CapabilityExpr &CE, SourceLocation Loc,
- const CapExprSet &Excl, const CapExprSet &Shrd)
- : FactEntry(CE, LK_Exclusive, Loc, false) {
- for (const auto &M : Excl)
- UnderlyingMutexes.push_back(M.sexpr());
- for (const auto &M : Shrd)
- UnderlyingMutexes.push_back(M.sexpr());
+ ScopedLockableFactEntry(const CapabilityExpr &CE, SourceLocation Loc)
+ : FactEntry(CE, LK_Exclusive, Loc, false) {}
+
+ void addExclusiveLock(const CapabilityExpr &M) {
+ UnderlyingMutexes.emplace_back(M.sexpr(), UCK_Acquired);
+ }
+
+ void addSharedLock(const CapabilityExpr &M) {
+ UnderlyingMutexes.emplace_back(M.sexpr(), UCK_Acquired);
+ }
+
+ void addExclusiveUnlock(const CapabilityExpr &M) {
+ UnderlyingMutexes.emplace_back(M.sexpr(), UCK_ReleasedExclusive);
+ }
+
+ void addSharedUnlock(const CapabilityExpr &M) {
+ UnderlyingMutexes.emplace_back(M.sexpr(), UCK_ReleasedShared);
}
void
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
SourceLocation JoinLoc, LockErrorKind LEK,
ThreadSafetyHandler &Handler) const override {
- for (const auto *UnderlyingMutex : UnderlyingMutexes) {
- if (FSet.findLock(FactMan, CapabilityExpr(UnderlyingMutex, false))) {
+ for (const auto &UnderlyingMutex : UnderlyingMutexes) {
+ const auto *Entry = FSet.findLock(
+ FactMan, CapabilityExpr(UnderlyingMutex.getPointer(), false));
+ if ((UnderlyingMutex.getInt() == UCK_Acquired && Entry) ||
+ (UnderlyingMutex.getInt() != UCK_Acquired && !Entry)) {
// If this scoped lock manages another mutex, and if the underlying
- // mutex is still held, then warn about the underlying mutex.
+ // mutex is still/not held, then warn about the underlying mutex.
Handler.handleMutexHeldEndOfScope(
- "mutex", sx::toString(UnderlyingMutex), loc(), JoinLoc, LEK);
+ "mutex", sx::toString(UnderlyingMutex.getPointer()), loc(), JoinLoc,
+ LEK);
}
}
}
+ void handleLock(FactSet &FSet, FactManager &FactMan, const FactEntry &entry,
+ ThreadSafetyHandler &Handler,
+ StringRef DiagKind) const override {
+ for (const auto &UnderlyingMutex : UnderlyingMutexes) {
+ CapabilityExpr UnderCp(UnderlyingMutex.getPointer(), false);
+
+ if (UnderlyingMutex.getInt() == UCK_Acquired)
+ lock(FSet, FactMan, UnderCp, entry.kind(), entry.loc(), &Handler,
+ DiagKind);
+ else
+ unlock(FSet, FactMan, UnderCp, entry.loc(), &Handler, DiagKind);
+ }
+ }
+
void handleUnlock(FactSet &FSet, FactManager &FactMan,
const CapabilityExpr &Cp, SourceLocation UnlockLoc,
bool FullyRemove, ThreadSafetyHandler &Handler,
StringRef DiagKind) const override {
assert(!Cp.negative() && "Managing object cannot be negative.");
- for (const auto *UnderlyingMutex : UnderlyingMutexes) {
- CapabilityExpr UnderCp(UnderlyingMutex, false);
- auto UnderEntry = llvm::make_unique<LockableFactEntry>(
- !UnderCp, LK_Exclusive, UnlockLoc);
-
- if (FullyRemove) {
- // We're destroying the managing object.
- // Remove the underlying mutex if it exists; but don't warn.
- if (FSet.findLock(FactMan, UnderCp)) {
- FSet.removeLock(FactMan, UnderCp);
- FSet.addLock(FactMan, std::move(UnderEntry));
- }
+ for (const auto &UnderlyingMutex : UnderlyingMutexes) {
+ CapabilityExpr UnderCp(UnderlyingMutex.getPointer(), false);
+
+ // Remove/lock the underlying mutex if it exists/is still unlocked; warn
+ // on double unlocking/locking if we're not destroying the scoped object.
+ ThreadSafetyHandler *TSHandler = FullyRemove ? nullptr : &Handler;
+ if (UnderlyingMutex.getInt() == UCK_Acquired) {
+ unlock(FSet, FactMan, UnderCp, UnlockLoc, TSHandler, DiagKind);
} else {
- // We're releasing the underlying mutex, but not destroying the
- // managing object. Warn on dual release.
- if (!FSet.findLock(FactMan, UnderCp)) {
- Handler.handleUnmatchedUnlock(DiagKind, UnderCp.toString(),
- UnlockLoc);
- }
- FSet.removeLock(FactMan, UnderCp);
- FSet.addLock(FactMan, std::move(UnderEntry));
+ LockKind kind = UnderlyingMutex.getInt() == UCK_ReleasedShared
+ ? LK_Shared
+ : LK_Exclusive;
+ lock(FSet, FactMan, UnderCp, kind, UnlockLoc, TSHandler, DiagKind);
}
}
if (FullyRemove)
FSet.removeLock(FactMan, Cp);
}
+
+private:
+ void lock(FactSet &FSet, FactManager &FactMan, const CapabilityExpr &Cp,
+ LockKind kind, SourceLocation loc, ThreadSafetyHandler *Handler,
+ StringRef DiagKind) const {
+ if (!FSet.findLock(FactMan, Cp)) {
+ FSet.removeLock(FactMan, !Cp);
+ FSet.addLock(FactMan,
+ llvm::make_unique<LockableFactEntry>(Cp, kind, loc));
+ } else if (Handler) {
+ Handler->handleDoubleLock(DiagKind, Cp.toString(), loc);
+ }
+ }
+
+ void unlock(FactSet &FSet, FactManager &FactMan, const CapabilityExpr &Cp,
+ SourceLocation loc, ThreadSafetyHandler *Handler,
+ StringRef DiagKind) const {
+ if (FSet.findLock(FactMan, Cp)) {
+ FSet.removeLock(FactMan, Cp);
+ FSet.addLock(FactMan, llvm::make_unique<LockableFactEntry>(
+ !Cp, LK_Exclusive, loc));
+ } else if (Handler) {
+ Handler->handleUnmatchedUnlock(DiagKind, Cp.toString(), loc);
+ }
+ }
};
/// Class which implements the core thread safety analysis routines.
@@ -976,11 +1034,11 @@ public:
StringRef DiagKind);
template <typename AttrType>
- void getMutexIDs(CapExprSet &Mtxs, AttrType *Attr, Expr *Exp,
+ void getMutexIDs(CapExprSet &Mtxs, AttrType *Attr, const Expr *Exp,
const NamedDecl *D, VarDecl *SelfDecl = nullptr);
template <class AttrType>
- void getMutexIDs(CapExprSet &Mtxs, AttrType *Attr, Expr *Exp,
+ void getMutexIDs(CapExprSet &Mtxs, AttrType *Attr, const Expr *Exp,
const NamedDecl *D,
const CFGBlock *PredBlock, const CFGBlock *CurrBlock,
Expr *BrE, bool Neg);
@@ -1232,7 +1290,7 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
if (!ReqAttr && !Entry->negative()) {
// look for the negative capability, and remove it from the fact set.
CapabilityExpr NegC = !*Entry;
- FactEntry *Nen = FSet.findLock(FactMan, NegC);
+ const FactEntry *Nen = FSet.findLock(FactMan, NegC);
if (Nen) {
FSet.removeLock(FactMan, NegC);
}
@@ -1251,9 +1309,9 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
}
// FIXME: Don't always warn when we have support for reentrant locks.
- if (FSet.findLock(FactMan, *Entry)) {
+ if (const FactEntry *Cp = FSet.findLock(FactMan, *Entry)) {
if (!Entry->asserted())
- Handler.handleDoubleLock(DiagKind, Entry->toString(), Entry->loc());
+ Cp->handleLock(FSet, FactMan, *Entry, Handler, DiagKind);
} else {
FSet.addLock(FactMan, std::move(Entry));
}
@@ -1289,7 +1347,7 @@ void ThreadSafetyAnalyzer::removeLock(FactSet &FSet, const CapabilityExpr &Cp,
/// and push them onto Mtxs, discarding any duplicates.
template <typename AttrType>
void ThreadSafetyAnalyzer::getMutexIDs(CapExprSet &Mtxs, AttrType *Attr,
- Expr *Exp, const NamedDecl *D,
+ const Expr *Exp, const NamedDecl *D,
VarDecl *SelfDecl) {
if (Attr->args_size() == 0) {
// The mutex held is the "this" object.
@@ -1321,7 +1379,7 @@ void ThreadSafetyAnalyzer::getMutexIDs(CapExprSet &Mtxs, AttrType *Attr,
/// any duplicates.
template <class AttrType>
void ThreadSafetyAnalyzer::getMutexIDs(CapExprSet &Mtxs, AttrType *Attr,
- Expr *Exp, const NamedDecl *D,
+ const Expr *Exp, const NamedDecl *D,
const CFGBlock *PredBlock,
const CFGBlock *CurrBlock,
Expr *BrE, bool Neg) {
@@ -1369,14 +1427,17 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
if (!Cond)
return nullptr;
- if (const auto *CallExp = dyn_cast<CallExpr>(Cond))
+ if (const auto *CallExp = dyn_cast<CallExpr>(Cond)) {
+ if (CallExp->getBuiltinCallee() == Builtin::BI__builtin_expect)
+ return getTrylockCallExpr(CallExp->getArg(0), C, Negate);
return CallExp;
+ }
else if (const auto *PE = dyn_cast<ParenExpr>(Cond))
return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
else if (const auto *CE = dyn_cast<ImplicitCastExpr>(Cond))
return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
- else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Cond))
- return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
+ else if (const auto *FE = dyn_cast<FullExpr>(Cond))
+ return getTrylockCallExpr(FE->getSubExpr(), C, Negate);
else if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
return getTrylockCallExpr(E, C, Negate);
@@ -1412,6 +1473,17 @@ const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
if (BOP->getOpcode() == BO_LOr)
return getTrylockCallExpr(BOP->getRHS(), C, Negate);
return nullptr;
+ } else if (const auto *COP = dyn_cast<ConditionalOperator>(Cond)) {
+ bool TCond, FCond;
+ if (getStaticBooleanValue(COP->getTrueExpr(), TCond) &&
+ getStaticBooleanValue(COP->getFalseExpr(), FCond)) {
+ if (TCond && !FCond)
+ return getTrylockCallExpr(COP->getCond(), C, Negate);
+ if (!TCond && FCond) {
+ Negate = !Negate;
+ return getTrylockCallExpr(COP->getCond(), C, Negate);
+ }
+ }
}
return nullptr;
}
@@ -1426,7 +1498,8 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
Result = ExitSet;
const Stmt *Cond = PredBlock->getTerminatorCondition();
- if (!Cond)
+ // We don't acquire try-locks on ?: branches, only when its result is used.
+ if (!Cond || isa<ConditionalOperator>(PredBlock->getTerminator()))
return;
bool Negate = false;
@@ -1434,7 +1507,7 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;
StringRef CapDiagKind = "mutex";
- auto *Exp = const_cast<CallExpr *>(getTrylockCallExpr(Cond, LVarCtx, Negate));
+ const auto *Exp = getTrylockCallExpr(Cond, LVarCtx, Negate);
if (!Exp)
return;
@@ -1494,7 +1567,7 @@ namespace {
/// An expression may cause us to add or remove locks from the lockset, or else
/// output error messages related to missing locks.
/// FIXME: In future, we may be able to not inherit from a visitor.
-class BuildLockset : public StmtVisitor<BuildLockset> {
+class BuildLockset : public ConstStmtVisitor<BuildLockset> {
friend class ThreadSafetyAnalyzer;
ThreadSafetyAnalyzer *Analyzer;
@@ -1514,19 +1587,23 @@ class BuildLockset : public StmtVisitor<BuildLockset> {
void checkPtAccess(const Expr *Exp, AccessKind AK,
ProtectedOperationKind POK = POK_VarAccess);
- void handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD = nullptr);
+ void handleCall(const Expr *Exp, const NamedDecl *D, VarDecl *VD = nullptr);
+ void examineArguments(const FunctionDecl *FD,
+ CallExpr::const_arg_iterator ArgBegin,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool SkipFirstParam = false);
public:
BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
- : StmtVisitor<BuildLockset>(), Analyzer(Anlzr), FSet(Info.EntrySet),
+ : ConstStmtVisitor<BuildLockset>(), Analyzer(Anlzr), FSet(Info.EntrySet),
LVarCtx(Info.EntryContext), CtxIndex(Info.EntryIndex) {}
- void VisitUnaryOperator(UnaryOperator *UO);
- void VisitBinaryOperator(BinaryOperator *BO);
- void VisitCastExpr(CastExpr *CE);
- void VisitCallExpr(CallExpr *Exp);
- void VisitCXXConstructExpr(CXXConstructExpr *Exp);
- void VisitDeclStmt(DeclStmt *S);
+ void VisitUnaryOperator(const UnaryOperator *UO);
+ void VisitBinaryOperator(const BinaryOperator *BO);
+ void VisitCastExpr(const CastExpr *CE);
+ void VisitCallExpr(const CallExpr *Exp);
+ void VisitCXXConstructExpr(const CXXConstructExpr *Exp);
+ void VisitDeclStmt(const DeclStmt *S);
};
} // namespace
@@ -1549,7 +1626,7 @@ void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp,
if (Cp.negative()) {
// Negative capabilities act like locks excluded
- FactEntry *LDat = FSet.findLock(Analyzer->FactMan, !Cp);
+ const FactEntry *LDat = FSet.findLock(Analyzer->FactMan, !Cp);
if (LDat) {
Analyzer->Handler.handleFunExcludesLock(
DiagKind, D->getNameAsString(), (!Cp).toString(), Loc);
@@ -1570,7 +1647,7 @@ void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp,
return;
}
- FactEntry* LDat = FSet.findLockUniv(Analyzer->FactMan, Cp);
+ const FactEntry *LDat = FSet.findLockUniv(Analyzer->FactMan, Cp);
bool NoError = true;
if (!LDat) {
// No exact match found. Look for a partial match.
@@ -1606,7 +1683,7 @@ void BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr *Exp,
return;
}
- FactEntry* LDat = FSet.findLock(Analyzer->FactMan, Cp);
+ const FactEntry *LDat = FSet.findLock(Analyzer->FactMan, Cp);
if (LDat) {
Analyzer->Handler.handleFunExcludesLock(
DiagKind, D->getNameAsString(), Cp.toString(), Exp->getExprLoc());
@@ -1630,6 +1707,9 @@ void BuildLockset::checkAccess(const Expr *Exp, AccessKind AK,
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()->getCanonicalDecl());
if (VD && VD->isLocalVarDecl() && VD->getType()->isReferenceType()) {
if (const auto *E = VD->getInit()) {
+ // Guard against self-initialization. e.g., int &i = i;
+ if (E == Exp)
+ break;
Exp = E;
continue;
}
@@ -1718,7 +1798,8 @@ void BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK,
/// and check that the appropriate locks are held. Non-const method calls with
/// the same signature as const method calls can be also treated as reads.
///
-void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
+void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
+ VarDecl *VD) {
SourceLocation Loc = Exp->getExprLoc();
CapExprSet ExclusiveLocksToAdd, SharedLocksToAdd;
CapExprSet ExclusiveLocksToRemove, SharedLocksToRemove, GenericLocksToRemove;
@@ -1858,25 +1939,32 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
if (isScopedVar) {
// Add the managing object as a dummy mutex, mapped to the underlying mutex.
SourceLocation MLoc = VD->getLocation();
- DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation());
+ DeclRefExpr DRE(VD->getASTContext(), VD, false, VD->getType(), VK_LValue,
+ VD->getLocation());
// FIXME: does this store a pointer to DRE?
CapabilityExpr Scp = Analyzer->SxBuilder.translateAttrExpr(&DRE, nullptr);
- std::copy(ScopedExclusiveReqs.begin(), ScopedExclusiveReqs.end(),
- std::back_inserter(ExclusiveLocksToAdd));
- std::copy(ScopedSharedReqs.begin(), ScopedSharedReqs.end(),
- std::back_inserter(SharedLocksToAdd));
- Analyzer->addLock(FSet,
- llvm::make_unique<ScopedLockableFactEntry>(
- Scp, MLoc, ExclusiveLocksToAdd, SharedLocksToAdd),
- CapDiagKind);
+ auto ScopedEntry = llvm::make_unique<ScopedLockableFactEntry>(Scp, MLoc);
+ for (const auto &M : ExclusiveLocksToAdd)
+ ScopedEntry->addExclusiveLock(M);
+ for (const auto &M : ScopedExclusiveReqs)
+ ScopedEntry->addExclusiveLock(M);
+ for (const auto &M : SharedLocksToAdd)
+ ScopedEntry->addSharedLock(M);
+ for (const auto &M : ScopedSharedReqs)
+ ScopedEntry->addSharedLock(M);
+ for (const auto &M : ExclusiveLocksToRemove)
+ ScopedEntry->addExclusiveUnlock(M);
+ for (const auto &M : SharedLocksToRemove)
+ ScopedEntry->addSharedUnlock(M);
+ Analyzer->addLock(FSet, std::move(ScopedEntry), CapDiagKind);
}
}
/// For unary operations which read and write a variable, we need to
/// check whether we hold any required mutexes. Reads are checked in
/// VisitCastExpr.
-void BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
+void BuildLockset::VisitUnaryOperator(const UnaryOperator *UO) {
switch (UO->getOpcode()) {
case UO_PostDec:
case UO_PostInc:
@@ -1892,7 +1980,7 @@ void BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
/// For binary operations which assign to a variable (writes), we need to check
/// whether we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
-void BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
+void BuildLockset::VisitBinaryOperator(const BinaryOperator *BO) {
if (!BO->isAssignmentOp())
return;
@@ -1905,16 +1993,43 @@ void BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
/// need to ensure we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
-void BuildLockset::VisitCastExpr(CastExpr *CE) {
+void BuildLockset::VisitCastExpr(const CastExpr *CE) {
if (CE->getCastKind() != CK_LValueToRValue)
return;
checkAccess(CE->getSubExpr(), AK_Read);
}
-void BuildLockset::VisitCallExpr(CallExpr *Exp) {
- bool ExamineArgs = true;
- bool OperatorFun = false;
+void BuildLockset::examineArguments(const FunctionDecl *FD,
+ CallExpr::const_arg_iterator ArgBegin,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool SkipFirstParam) {
+ // Currently we can't do anything if we don't know the function declaration.
+ if (!FD)
+ return;
+
+ // NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it
+ // only turns off checking within the body of a function, but we also
+ // use it to turn off checking in arguments to the function. This
+ // could result in some false negatives, but the alternative is to
+ // create yet another attribute.
+ if (FD->hasAttr<NoThreadSafetyAnalysisAttr>())
+ return;
+
+ const ArrayRef<ParmVarDecl *> Params = FD->parameters();
+ auto Param = Params.begin();
+ if (SkipFirstParam)
+ ++Param;
+ // There can be default arguments, so we stop when one iterator is at end().
+ for (auto Arg = ArgBegin; Param != Params.end() && Arg != ArgEnd;
+ ++Param, ++Arg) {
+ QualType Qt = (*Param)->getType();
+ if (Qt->isReferenceType())
+ checkAccess(*Arg, AK_Read, POK_PassByRef);
+ }
+}
+
+void BuildLockset::VisitCallExpr(const CallExpr *Exp) {
if (const auto *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
const auto *ME = dyn_cast<MemberExpr>(CE->getCallee());
// ME can be null when calling a method pointer
@@ -1933,13 +2048,12 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
checkAccess(CE->getImplicitObjectArgument(), AK_Read);
}
}
- } else if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
- OperatorFun = true;
+ examineArguments(CE->getDirectCallee(), CE->arg_begin(), CE->arg_end());
+ } else if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
auto OEop = OE->getOperator();
switch (OEop) {
case OO_Equal: {
- ExamineArgs = false;
const Expr *Target = OE->getArg(0);
const Expr *Source = OE->getArg(1);
checkAccess(Target, AK_Written);
@@ -1948,60 +2062,27 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
}
case OO_Star:
case OO_Arrow:
- case OO_Subscript: {
- const Expr *Obj = OE->getArg(0);
- checkAccess(Obj, AK_Read);
+ case OO_Subscript:
if (!(OEop == OO_Star && OE->getNumArgs() > 1)) {
// Grrr. operator* can be multiplication...
- checkPtAccess(Obj, AK_Read);
+ checkPtAccess(OE->getArg(0), AK_Read);
}
- break;
- }
+ LLVM_FALLTHROUGH;
default: {
// TODO: get rid of this, and rely on pass-by-ref instead.
const Expr *Obj = OE->getArg(0);
checkAccess(Obj, AK_Read);
+ // Check the remaining arguments. For method operators, the first
+ // argument is the implicit self argument, and doesn't appear in the
+ // FunctionDecl, but for non-methods it does.
+ const FunctionDecl *FD = OE->getDirectCallee();
+ examineArguments(FD, std::next(OE->arg_begin()), OE->arg_end(),
+ /*SkipFirstParam*/ !isa<CXXMethodDecl>(FD));
break;
}
}
- }
-
- if (ExamineArgs) {
- if (FunctionDecl *FD = Exp->getDirectCallee()) {
- // NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it
- // only turns off checking within the body of a function, but we also
- // use it to turn off checking in arguments to the function. This
- // could result in some false negatives, but the alternative is to
- // create yet another attribute.
- if (!FD->hasAttr<NoThreadSafetyAnalysisAttr>()) {
- unsigned Fn = FD->getNumParams();
- unsigned Cn = Exp->getNumArgs();
- unsigned Skip = 0;
-
- unsigned i = 0;
- if (OperatorFun) {
- if (isa<CXXMethodDecl>(FD)) {
- // First arg in operator call is implicit self argument,
- // and doesn't appear in the FunctionDecl.
- Skip = 1;
- Cn--;
- } else {
- // Ignore the first argument of operators; it's been checked above.
- i = 1;
- }
- }
- // Ignore default arguments
- unsigned n = (Fn < Cn) ? Fn : Cn;
-
- for (; i < n; ++i) {
- ParmVarDecl* Pvd = FD->getParamDecl(i);
- Expr* Arg = Exp->getArg(i+Skip);
- QualType Qt = Pvd->getType();
- if (Qt->isReferenceType())
- checkAccess(Arg, AK_Read, POK_PassByRef);
- }
- }
- }
+ } else {
+ examineArguments(Exp->getDirectCallee(), Exp->arg_begin(), Exp->arg_end());
}
auto *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
@@ -2010,13 +2091,14 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
handleCall(Exp, D);
}
-void BuildLockset::VisitCXXConstructExpr(CXXConstructExpr *Exp) {
+void BuildLockset::VisitCXXConstructExpr(const CXXConstructExpr *Exp) {
const CXXConstructorDecl *D = Exp->getConstructor();
if (D && D->isCopyConstructor()) {
const Expr* Source = Exp->getArg(0);
checkAccess(Source, AK_Read);
+ } else {
+ examineArguments(D, Exp->arg_begin(), Exp->arg_end());
}
- // FIXME -- only handles constructors in DeclStmt below.
}
static CXXConstructorDecl *
@@ -2046,7 +2128,7 @@ static Expr *buildFakeCtorCall(CXXConstructorDecl *CD, ArrayRef<Expr *> Args,
SourceRange(Loc, Loc));
}
-void BuildLockset::VisitDeclStmt(DeclStmt *S) {
+void BuildLockset::VisitDeclStmt(const DeclStmt *S) {
// adjust the context
LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
@@ -2080,7 +2162,7 @@ void BuildLockset::VisitDeclStmt(DeclStmt *S) {
CXXConstructorDecl *CtorD = findConstructorForByValueReturn(RD);
if (!CtorD || !CtorD->hasAttrs())
continue;
- handleCall(buildFakeCtorCall(CtorD, {E}, E->getLocStart()), CtorD, VD);
+ handleCall(buildFakeCtorCall(CtorD, {E}, E->getBeginLoc()), CtorD, VD);
}
}
}
@@ -2242,8 +2324,8 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
// We must ignore such methods.
if (A->args_size() == 0)
return;
- // FIXME -- deal with exclusive vs. shared unlock functions?
- getMutexIDs(ExclusiveLocksToAdd, A, nullptr, D);
+ getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
+ nullptr, D);
getMutexIDs(LocksReleased, A, nullptr, D);
CapDiagKind = ClassifyDiagnostic(A);
} else if (const auto *A = dyn_cast<AcquireCapabilityAttr>(Attr)) {
@@ -2279,7 +2361,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
}
for (const auto *CurrBlock : *SortedGraph) {
- int CurrBlockID = CurrBlock->getBlockID();
+ unsigned CurrBlockID = CurrBlock->getBlockID();
CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
// Use the default initial lockset in case there are no predecessors.
@@ -2306,7 +2388,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
if (*PI == nullptr || !VisitedBlocks.alreadySet(*PI))
continue;
- int PrevBlockID = (*PI)->getBlockID();
+ unsigned PrevBlockID = (*PI)->getBlockID();
CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
// Ignore edges from blocks that can't return.
@@ -2347,7 +2429,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
// Process continue and break blocks. Assume that the lockset for the
// resulting block is unaffected by any discrepancies in them.
for (const auto *PrevBlock : SpecialBlocks) {
- int PrevBlockID = PrevBlock->getBlockID();
+ unsigned PrevBlockID = PrevBlock->getBlockID();
CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
if (!LocksetInitialized) {
@@ -2382,21 +2464,21 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
switch (BI.getKind()) {
case CFGElement::Statement: {
CFGStmt CS = BI.castAs<CFGStmt>();
- LocksetBuilder.Visit(const_cast<Stmt *>(CS.getStmt()));
+ LocksetBuilder.Visit(CS.getStmt());
break;
}
// Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
case CFGElement::AutomaticObjectDtor: {
CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
- auto *DD = const_cast<CXXDestructorDecl *>(
- AD.getDestructorDecl(AC.getASTContext()));
+ const auto *DD = AD.getDestructorDecl(AC.getASTContext());
if (!DD->hasAttrs())
break;
// Create a dummy expression,
auto *VD = const_cast<VarDecl *>(AD.getVarDecl());
- DeclRefExpr DRE(VD, false, VD->getType().getNonReferenceType(),
- VK_LValue, AD.getTriggerStmt()->getLocEnd());
+ DeclRefExpr DRE(VD->getASTContext(), VD, false,
+ VD->getType().getNonReferenceType(), VK_LValue,
+ AD.getTriggerStmt()->getEndLoc());
LocksetBuilder.handleCall(&DRE, DD);
break;
}
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index fced17ff9197..14d1d9c7a8f7 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -128,7 +128,8 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
// Hack to handle constructors, where self cannot be recovered from
// the expression.
if (SelfDecl && !Ctx.SelfArg) {
- DeclRefExpr SelfDRE(SelfDecl, false, SelfDecl->getType(), VK_LValue,
+ DeclRefExpr SelfDRE(SelfDecl->getASTContext(), SelfDecl, false,
+ SelfDecl->getType(), VK_LValue,
SelfDecl->getLocation());
Ctx.SelfArg = &SelfDRE;
@@ -211,6 +212,8 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx);
case Stmt::MemberExprClass:
return translateMemberExpr(cast<MemberExpr>(S), Ctx);
+ case Stmt::ObjCIvarRefExprClass:
+ return translateObjCIVarRefExpr(cast<ObjCIvarRefExpr>(S), Ctx);
case Stmt::CallExprClass:
return translateCallExpr(cast<CallExpr>(S), Ctx);
case Stmt::CXXMemberCallExprClass:
@@ -233,6 +236,8 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
cast<BinaryConditionalOperator>(S), Ctx);
// We treat these as no-ops
+ case Stmt::ConstantExprClass:
+ return translate(cast<ConstantExpr>(S)->getSubExpr(), Ctx);
case Stmt::ParenExprClass:
return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
case Stmt::ExprWithCleanupsClass:
@@ -311,9 +316,9 @@ static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
return nullptr;
}
-static bool hasCppPointerType(const til::SExpr *E) {
+static bool hasAnyPointerType(const til::SExpr *E) {
auto *VD = getValueDeclFromSExpr(E);
- if (VD && VD->getType()->isPointerType())
+ if (VD && VD->getType()->isAnyPointerType())
return true;
if (const auto *C = dyn_cast<til::Cast>(E))
return C->castOpcode() == til::CAST_objToPtr;
@@ -344,7 +349,20 @@ til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
D = getFirstVirtualDecl(VD);
til::Project *P = new (Arena) til::Project(E, D);
- if (hasCppPointerType(BE))
+ if (hasAnyPointerType(BE))
+ P->setArrow(true);
+ return P;
+}
+
+til::SExpr *SExprBuilder::translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE,
+ CallingContext *Ctx) {
+ til::SExpr *BE = translate(IVRE->getBase(), Ctx);
+ til::SExpr *E = new (Arena) til::SApply(BE);
+
+ const auto *D = cast<ObjCIvarDecl>(IVRE->getDecl()->getCanonicalDecl());
+
+ til::Project *P = new (Arena) til::Project(E, D);
+ if (hasAnyPointerType(BE))
P->setArrow(true);
return P;
}
@@ -354,15 +372,17 @@ til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
const Expr *SelfE) {
if (CapabilityExprMode) {
// Handle LOCK_RETURNED
- const FunctionDecl *FD = CE->getDirectCallee()->getMostRecentDecl();
- if (LockReturnedAttr* At = FD->getAttr<LockReturnedAttr>()) {
- CallingContext LRCallCtx(Ctx);
- LRCallCtx.AttrDecl = CE->getDirectCallee();
- LRCallCtx.SelfArg = SelfE;
- LRCallCtx.NumArgs = CE->getNumArgs();
- LRCallCtx.FunArgs = CE->getArgs();
- return const_cast<til::SExpr *>(
- translateAttrExpr(At->getArg(), &LRCallCtx).sexpr());
+ if (const FunctionDecl *FD = CE->getDirectCallee()) {
+ FD = FD->getMostRecentDecl();
+ if (LockReturnedAttr *At = FD->getAttr<LockReturnedAttr>()) {
+ CallingContext LRCallCtx(Ctx);
+ LRCallCtx.AttrDecl = CE->getDirectCallee();
+ LRCallCtx.SelfArg = SelfE;
+ LRCallCtx.NumArgs = CE->getNumArgs();
+ LRCallCtx.FunArgs = CE->getArgs();
+ return const_cast<til::SExpr *>(
+ translateAttrExpr(At->getArg(), &LRCallCtx).sexpr());
+ }
}
}
@@ -927,6 +947,16 @@ void SExprBuilder::exitCFG(const CFGBlock *Last) {
}
/*
+namespace {
+
+class TILPrinter :
+ public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
+
+} // namespace
+
+namespace clang {
+namespace threadSafety {
+
void printSCFG(CFGWalker &Walker) {
llvm::BumpPtrAllocator Bpa;
til::MemRegionRef Arena(&Bpa);
@@ -934,4 +964,7 @@ void printSCFG(CFGWalker &Walker) {
til::SCFG *Scfg = SxBuilder.buildCFG(Walker);
TILPrinter::print(Scfg, llvm::errs());
}
+
+} // namespace threadSafety
+} // namespace clang
*/
diff --git a/lib/Analysis/ThreadSafetyTIL.cpp b/lib/Analysis/ThreadSafetyTIL.cpp
index 798bbfb29d7b..11f7afbd229c 100644
--- a/lib/Analysis/ThreadSafetyTIL.cpp
+++ b/lib/Analysis/ThreadSafetyTIL.cpp
@@ -150,7 +150,7 @@ void til::simplifyIncompleteArg(til::Phi *Ph) {
}
// Renumbers the arguments and instructions to have unique, sequential IDs.
-int BasicBlock::renumberInstrs(int ID) {
+unsigned BasicBlock::renumberInstrs(unsigned ID) {
for (auto *Arg : Args)
Arg->setID(this, ID++);
for (auto *Instr : Instrs)
@@ -163,7 +163,8 @@ int BasicBlock::renumberInstrs(int ID) {
// Each block will be written into the Blocks array in order, and its BlockID
// will be set to the index in the array. Sorting should start from the entry
// block, and ID should be the total number of blocks.
-int BasicBlock::topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID) {
+unsigned BasicBlock::topologicalSort(SimpleArray<BasicBlock *> &Blocks,
+ unsigned ID) {
if (Visited) return ID;
Visited = true;
for (auto *Block : successors())
@@ -186,7 +187,8 @@ int BasicBlock::topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID) {
// critical edges, and (3) the entry block is reachable from the exit block
// and no blocks are accessible via traversal of back-edges from the exit that
// weren't accessible via forward edges from the entry.
-int BasicBlock::topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID) {
+unsigned BasicBlock::topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks,
+ unsigned ID) {
// Visited is assumed to have been set by the topologicalSort. This pass
// assumes !Visited means that we've visited this node before.
if (!Visited) return ID;
@@ -257,7 +259,7 @@ void BasicBlock::computePostDominator() {
// Renumber instructions in all blocks
void SCFG::renumberInstrs() {
- int InstrID = 0;
+ unsigned InstrID = 0;
for (auto *Block : Blocks)
InstrID = Block->renumberInstrs(InstrID);
}
@@ -288,11 +290,11 @@ static inline void computeNodeID(BasicBlock *B,
// 3) Topologically sorting the blocks into the "Blocks" array.
void SCFG::computeNormalForm() {
// Topologically sort the blocks starting from the entry block.
- int NumUnreachableBlocks = Entry->topologicalSort(Blocks, Blocks.size());
+ unsigned NumUnreachableBlocks = Entry->topologicalSort(Blocks, Blocks.size());
if (NumUnreachableBlocks > 0) {
// If there were unreachable blocks shift everything down, and delete them.
- for (size_t I = NumUnreachableBlocks, E = Blocks.size(); I < E; ++I) {
- size_t NI = I - NumUnreachableBlocks;
+ for (unsigned I = NumUnreachableBlocks, E = Blocks.size(); I < E; ++I) {
+ unsigned NI = I - NumUnreachableBlocks;
Blocks[NI] = Blocks[I];
Blocks[NI]->BlockID = NI;
// FIXME: clean up predecessor pointers to unreachable blocks?
@@ -305,7 +307,7 @@ void SCFG::computeNormalForm() {
Block->computeDominator();
// Once dominators have been computed, the final sort may be performed.
- int NumBlocks = Exit->topologicalFinalSort(Blocks, 0);
+ unsigned NumBlocks = Exit->topologicalFinalSort(Blocks, 0);
assert(static_cast<size_t>(NumBlocks) == Blocks.size());
(void) NumBlocks;
diff --git a/lib/Basic/Attributes.cpp b/lib/Basic/Attributes.cpp
index b7570d03c85a..9a8eb3d932cc 100644
--- a/lib/Basic/Attributes.cpp
+++ b/lib/Basic/Attributes.cpp
@@ -12,9 +12,16 @@ int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
Name = Name.substr(2, Name.size() - 4);
+ // Normalize the scope name, but only for gnu and clang attributes.
+ StringRef ScopeName = Scope ? Scope->getName() : "";
+ if (ScopeName == "__gnu__")
+ ScopeName = "gnu";
+ else if (ScopeName == "_Clang")
+ ScopeName = "clang";
+
#include "clang/Basic/AttrHasAttributeImpl.inc"
- return 0;
+ return 0;
}
const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index a3210ba09068..7e7f67ca874e 100644
--- a/lib/Basic/Builtins.cpp
+++ b/lib/Basic/Builtins.cpp
@@ -68,7 +68,7 @@ bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
bool GnuModeUnsupported = !LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG);
bool MSModeUnsupported =
!LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
- bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;
+ bool ObjCUnsupported = !LangOpts.ObjC && BuiltinInfo.Langs == OBJC_LANG;
bool OclC1Unsupported = (LangOpts.OpenCLVersion / 100) != 1 &&
(BuiltinInfo.Langs & ALL_OCLC_LANGUAGES ) == OCLC1X_LANG;
bool OclC2Unsupported = LangOpts.OpenCLVersion != 200 &&
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index e82f451dea17..8b3aa0f1e972 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -48,12 +48,14 @@ add_clang_library(clangBasic
Attributes.cpp
Builtins.cpp
CharInfo.cpp
+ CodeGenOptions.cpp
Cuda.cpp
Diagnostic.cpp
DiagnosticIDs.cpp
DiagnosticOptions.cpp
FileManager.cpp
FileSystemStatCache.cpp
+ FixedPoint.cpp
IdentifierTable.cpp
LangOptions.cpp
MemoryBufferCache.cpp
@@ -70,6 +72,7 @@ add_clang_library(clangBasic
Targets.cpp
Targets/AArch64.cpp
Targets/AMDGPU.cpp
+ Targets/ARC.cpp
Targets/ARM.cpp
Targets/AVR.cpp
Targets/BPF.cpp
@@ -79,7 +82,6 @@ add_clang_library(clangBasic
Targets/MSP430.cpp
Targets/Mips.cpp
Targets/NVPTX.cpp
- Targets/Nios2.cpp
Targets/OSTargets.cpp
Targets/PNaCl.cpp
Targets/PPC.cpp
@@ -93,7 +95,6 @@ add_clang_library(clangBasic
Targets/XCore.cpp
TokenKinds.cpp
Version.cpp
- VirtualFileSystem.cpp
Warnings.cpp
XRayInstr.cpp
XRayLists.cpp
diff --git a/lib/Frontend/CodeGenOptions.cpp b/lib/Basic/CodeGenOptions.cpp
index 84a39f2d570d..aface1cd4bf9 100644
--- a/lib/Frontend/CodeGenOptions.cpp
+++ b/lib/Basic/CodeGenOptions.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Basic/CodeGenOptions.h"
#include <string.h>
namespace clang {
@@ -15,7 +15,7 @@ namespace clang {
CodeGenOptions::CodeGenOptions() {
#define CODEGENOPT(Name, Bits, Default) Name = Default;
#define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default);
-#include "clang/Frontend/CodeGenOptions.def"
+#include "clang/Basic/CodeGenOptions.def"
RelocationModel = llvm::Reloc::PIC_;
memcpy(CoverageVersion, "402*", 4);
diff --git a/lib/Basic/Cuda.cpp b/lib/Basic/Cuda.cpp
index dc7e61c02b24..6c34856dfdf7 100644
--- a/lib/Basic/Cuda.cpp
+++ b/lib/Basic/Cuda.cpp
@@ -22,6 +22,8 @@ const char *CudaVersionToString(CudaVersion V) {
return "9.1";
case CudaVersion::CUDA_92:
return "9.2";
+ case CudaVersion::CUDA_100:
+ return "10.0";
}
llvm_unreachable("invalid enum");
}
@@ -60,6 +62,8 @@ const char *CudaArchToString(CudaArch A) {
return "sm_70";
case CudaArch::SM_72:
return "sm_72";
+ case CudaArch::SM_75:
+ return "sm_75";
case CudaArch::GFX600: // tahiti
return "gfx600";
case CudaArch::GFX601: // pitcairn, verde, oland,hainan
@@ -86,6 +90,12 @@ const char *CudaArchToString(CudaArch A) {
return "gfx900";
case CudaArch::GFX902: // TBA
return "gfx902";
+ case CudaArch::GFX904: // TBA
+ return "gfx904";
+ case CudaArch::GFX906: // TBA
+ return "gfx906";
+ case CudaArch::GFX909: // TBA
+ return "gfx909";
}
llvm_unreachable("invalid enum");
}
@@ -106,6 +116,7 @@ CudaArch StringToCudaArch(llvm::StringRef S) {
.Case("sm_62", CudaArch::SM_62)
.Case("sm_70", CudaArch::SM_70)
.Case("sm_72", CudaArch::SM_72)
+ .Case("sm_75", CudaArch::SM_75)
.Case("gfx600", CudaArch::GFX600)
.Case("gfx601", CudaArch::GFX601)
.Case("gfx700", CudaArch::GFX700)
@@ -119,6 +130,9 @@ CudaArch StringToCudaArch(llvm::StringRef S) {
.Case("gfx810", CudaArch::GFX810)
.Case("gfx900", CudaArch::GFX900)
.Case("gfx902", CudaArch::GFX902)
+ .Case("gfx904", CudaArch::GFX904)
+ .Case("gfx906", CudaArch::GFX906)
+ .Case("gfx909", CudaArch::GFX909)
.Default(CudaArch::UNKNOWN);
}
@@ -152,6 +166,8 @@ const char *CudaVirtualArchToString(CudaVirtualArch A) {
return "compute_70";
case CudaVirtualArch::COMPUTE_72:
return "compute_72";
+ case CudaVirtualArch::COMPUTE_75:
+ return "compute_75";
case CudaVirtualArch::COMPUTE_AMDGCN:
return "compute_amdgcn";
}
@@ -173,6 +189,7 @@ CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
.Case("compute_62", CudaVirtualArch::COMPUTE_62)
.Case("compute_70", CudaVirtualArch::COMPUTE_70)
.Case("compute_72", CudaVirtualArch::COMPUTE_72)
+ .Case("compute_75", CudaVirtualArch::COMPUTE_75)
.Case("compute_amdgcn", CudaVirtualArch::COMPUTE_AMDGCN)
.Default(CudaVirtualArch::UNKNOWN);
}
@@ -210,6 +227,8 @@ CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
return CudaVirtualArch::COMPUTE_70;
case CudaArch::SM_72:
return CudaVirtualArch::COMPUTE_72;
+ case CudaArch::SM_75:
+ return CudaVirtualArch::COMPUTE_75;
case CudaArch::GFX600:
case CudaArch::GFX601:
case CudaArch::GFX700:
@@ -223,6 +242,9 @@ CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
case CudaArch::GFX810:
case CudaArch::GFX900:
case CudaArch::GFX902:
+ case CudaArch::GFX904:
+ case CudaArch::GFX906:
+ case CudaArch::GFX909:
return CudaVirtualArch::COMPUTE_AMDGCN;
}
llvm_unreachable("invalid enum");
@@ -252,6 +274,8 @@ CudaVersion MinVersionForCudaArch(CudaArch A) {
return CudaVersion::CUDA_90;
case CudaArch::SM_72:
return CudaVersion::CUDA_91;
+ case CudaArch::SM_75:
+ return CudaVersion::CUDA_100;
case CudaArch::GFX600:
case CudaArch::GFX601:
case CudaArch::GFX700:
@@ -265,6 +289,9 @@ CudaVersion MinVersionForCudaArch(CudaArch A) {
case CudaArch::GFX810:
case CudaArch::GFX900:
case CudaArch::GFX902:
+ case CudaArch::GFX904:
+ case CudaArch::GFX906:
+ case CudaArch::GFX909:
return CudaVersion::CUDA_70;
}
llvm_unreachable("invalid enum");
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index f1ebd9d38b9e..56c54cb9070c 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -89,6 +89,14 @@ DiagnosticsEngine::~DiagnosticsEngine() {
setClient(nullptr);
}
+void DiagnosticsEngine::dump() const {
+ DiagStatesByLoc.dump(*SourceMgr);
+}
+
+void DiagnosticsEngine::dump(StringRef DiagName) const {
+ DiagStatesByLoc.dump(*SourceMgr, DiagName);
+}
+
void DiagnosticsEngine::setClient(DiagnosticConsumer *client,
bool ShouldOwnClient) {
Owner.reset(ShouldOwnClient ? client : nullptr);
@@ -239,7 +247,7 @@ DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr,
void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
StringRef DiagName) const {
llvm::errs() << "diagnostic state at ";
- CurDiagStateLoc.dump(SrcMgr);
+ CurDiagStateLoc.print(llvm::errs(), SrcMgr);
llvm::errs() << ": " << CurDiagState << "\n";
for (auto &F : Files) {
@@ -261,7 +269,7 @@ void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
<< Decomp.first.getHashValue() << "> ";
SrcMgr.getLocForStartOfFile(Decomp.first)
.getLocWithOffset(Decomp.second)
- .dump(SrcMgr);
+ .print(llvm::errs(), SrcMgr);
}
if (File.HasLocalTransitions)
llvm::errs() << " has_local_transitions";
@@ -281,7 +289,7 @@ void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
llvm::errs() << " ";
SrcMgr.getLocForStartOfFile(ID)
.getLocWithOffset(Transition.Offset)
- .dump(SrcMgr);
+ .print(llvm::errs(), SrcMgr);
llvm::errs() << ": state " << Transition.State << ":\n";
};
@@ -975,6 +983,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
break;
}
+ case DiagnosticsEngine::ak_qual:
case DiagnosticsEngine::ak_qualtype:
case DiagnosticsEngine::ak_declarationname:
case DiagnosticsEngine::ak_nameddecl:
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index d339b972ae8e..f5a2d4894c13 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -49,7 +49,7 @@ using namespace clang;
//===----------------------------------------------------------------------===//
FileManager::FileManager(const FileSystemOptions &FSO,
- IntrusiveRefCntPtr<vfs::FileSystem> FS)
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
: FS(std::move(FS)), FileSystemOpts(FSO), SeenDirEntries(64),
SeenFileEntries(64), NextFileUID(0) {
NumDirLookups = NumFileLookups = 0;
@@ -58,49 +58,17 @@ FileManager::FileManager(const FileSystemOptions &FSO,
// If the caller doesn't provide a virtual file system, just grab the real
// file system.
if (!this->FS)
- this->FS = vfs::getRealFileSystem();
+ this->FS = llvm::vfs::getRealFileSystem();
}
FileManager::~FileManager() = default;
-void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
- bool AtBeginning) {
+void FileManager::setStatCache(std::unique_ptr<FileSystemStatCache> statCache) {
assert(statCache && "No stat cache provided?");
- if (AtBeginning || !StatCache.get()) {
- statCache->setNextStatCache(std::move(StatCache));
- StatCache = std::move(statCache);
- return;
- }
-
- FileSystemStatCache *LastCache = StatCache.get();
- while (LastCache->getNextStatCache())
- LastCache = LastCache->getNextStatCache();
-
- LastCache->setNextStatCache(std::move(statCache));
-}
-
-void FileManager::removeStatCache(FileSystemStatCache *statCache) {
- if (!statCache)
- return;
-
- if (StatCache.get() == statCache) {
- // This is the first stat cache.
- StatCache = StatCache->takeNextStatCache();
- return;
- }
-
- // Find the stat cache in the list.
- FileSystemStatCache *PrevCache = StatCache.get();
- while (PrevCache && PrevCache->getNextStatCache() != statCache)
- PrevCache = PrevCache->getNextStatCache();
-
- assert(PrevCache && "Stat cache not found for removal");
- PrevCache->setNextStatCache(statCache->takeNextStatCache());
+ StatCache = std::move(statCache);
}
-void FileManager::clearStatCaches() {
- StatCache.reset();
-}
+void FileManager::clearStatCache() { StatCache.reset(); }
/// Retrieve the directory that the given file name resides in.
/// Filename can point to either a real file or a virtual file.
@@ -221,15 +189,21 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
*SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first;
// See if there is already an entry in the map.
- if (NamedFileEnt.second)
- return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr
- : NamedFileEnt.second;
+ if (NamedFileEnt.second) {
+ if (NamedFileEnt.second == NON_EXISTENT_FILE)
+ return nullptr;
+ // Entry exists: return it *unless* it wasn't opened and open is requested.
+ if (!(NamedFileEnt.second->DeferredOpen && openFile))
+ return NamedFileEnt.second;
+ // We previously stat()ed the file, but didn't open it: do that below.
+ // FIXME: the below does other redundant work too (stats the dir and file).
+ } else {
+ // By default, initialize it to invalid.
+ NamedFileEnt.second = NON_EXISTENT_FILE;
+ }
++NumFileCacheMisses;
- // By default, initialize it to invalid.
- NamedFileEnt.second = NON_EXISTENT_FILE;
-
// Get the null-terminated file name as stored as the key of the
// SeenFileEntries map.
StringRef InterndFileName = NamedFileEnt.first();
@@ -252,7 +226,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// FIXME: This will reduce the # syscalls.
// Nope, there isn't. Check to see if the file exists.
- std::unique_ptr<vfs::File> F;
+ std::unique_ptr<llvm::vfs::File> F;
FileData Data;
if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) {
// There's no real file at the given path.
@@ -267,6 +241,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// It exists. See if we have already opened a file with the same inode.
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueRealFiles[Data.UniqueID];
+ UFE.DeferredOpen = !openFile;
NamedFileEnt.second = &UFE;
@@ -283,6 +258,15 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
InterndFileName = NamedFileEnt.first().data();
}
+ // If we opened the file for the first time, record the resulting info.
+ // Do this even if the cache entry was valid, maybe we didn't previously open.
+ if (F && !UFE.File) {
+ if (auto PathName = F->getName())
+ fillRealPathName(&UFE, *PathName);
+ UFE.File = std::move(F);
+ assert(!UFE.DeferredOpen && "we just opened it!");
+ }
+
if (UFE.isValid()) { // Already have an entry with this inode, return it.
// FIXME: this hack ensures that if we look up a file by a virtual path in
@@ -313,11 +297,9 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
UFE.UniqueID = Data.UniqueID;
UFE.IsNamedPipe = Data.IsNamedPipe;
UFE.InPCH = Data.InPCH;
- UFE.File = std::move(F);
UFE.IsValid = true;
- if (UFE.File)
- if (auto RealPathName = UFE.File->getName())
- UFE.RealPathName = *RealPathName;
+ // Note File and DeferredOpen were initialized above.
+
return &UFE;
}
@@ -373,6 +355,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
UFE->UniqueID = Data.UniqueID;
UFE->IsNamedPipe = Data.IsNamedPipe;
UFE->InPCH = Data.InPCH;
+ fillRealPathName(UFE, Data.Name);
}
if (!UFE) {
@@ -388,6 +371,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
UFE->UID = NextFileUID++;
UFE->IsValid = true;
UFE->File.reset();
+ UFE->DeferredOpen = false;
return UFE;
}
@@ -415,6 +399,17 @@ bool FileManager::makeAbsolutePath(SmallVectorImpl<char> &Path) const {
return Changed;
}
+void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) {
+ llvm::SmallString<128> AbsPath(FileName);
+ // This is not the same as `VFS::getRealPath()`, which resolves symlinks
+ // but can be very expensive on real file systems.
+ // FIXME: the semantic of RealPathName is unclear, and the name might be
+ // misleading. We need to clean up the interface here.
+ makeAbsolutePath(AbsPath);
+ llvm::sys::path::remove_dots(AbsPath, /*remove_dot_dot=*/true);
+ UFE->RealPathName = AbsPath.str();
+}
+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
bool ShouldCloseOpenFile) {
@@ -465,7 +460,7 @@ FileManager::getBufferForFile(StringRef Filename, bool isVolatile) {
/// false if it's an existent real file. If FileDescriptor is NULL,
/// do directory look-up instead of file look-up.
bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F) {
+ std::unique_ptr<llvm::vfs::File> *F) {
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
// absolute!
if (FileSystemOpts.WorkingDir.empty())
@@ -479,11 +474,11 @@ bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile,
}
bool FileManager::getNoncachedStatValue(StringRef Path,
- vfs::Status &Result) {
+ llvm::vfs::Status &Result) {
SmallString<128> FilePath(Path);
FixupRelativePath(FilePath);
- llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str());
+ llvm::ErrorOr<llvm::vfs::Status> S = FS->status(FilePath.c_str());
if (!S)
return true;
Result = *S;
diff --git a/lib/Basic/FileSystemStatCache.cpp b/lib/Basic/FileSystemStatCache.cpp
index f5856cb6542a..6f2eef4e2062 100644
--- a/lib/Basic/FileSystemStatCache.cpp
+++ b/lib/Basic/FileSystemStatCache.cpp
@@ -12,17 +12,17 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileSystemStatCache.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <utility>
using namespace clang;
void FileSystemStatCache::anchor() {}
-static void copyStatusToFileData(const vfs::Status &Status,
+static void copyStatusToFileData(const llvm::vfs::Status &Status,
FileData &Data) {
Data.Name = Status.getName();
Data.Size = Status.getSize();
@@ -44,8 +44,9 @@ static void copyStatusToFileData(const vfs::Status &Status,
/// implementation can optionally fill in FileDescriptor with a valid
/// descriptor and the client guarantees that it will close it.
bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F,
- FileSystemStatCache *Cache, vfs::FileSystem &FS) {
+ std::unique_ptr<llvm::vfs::File> *F,
+ FileSystemStatCache *Cache,
+ llvm::vfs::FileSystem &FS) {
LookupResult R;
bool isForDir = !isFile;
@@ -55,7 +56,7 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
else if (isForDir || !F) {
// If this is a directory or a file descriptor is not needed and we have
// no cache, just go to the file system.
- llvm::ErrorOr<vfs::Status> Status = FS.status(Path);
+ llvm::ErrorOr<llvm::vfs::Status> Status = FS.status(Path);
if (!Status) {
R = CacheMissing;
} else {
@@ -79,7 +80,7 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
// Otherwise, the open succeeded. Do an fstat to get the information
// about the file. We'll end up returning the open file descriptor to the
// client to do what they please with it.
- llvm::ErrorOr<vfs::Status> Status = (*OwnedFile)->status();
+ llvm::ErrorOr<llvm::vfs::Status> Status = (*OwnedFile)->status();
if (Status) {
R = CacheExists;
copyStatusToFileData(*Status, Data);
@@ -111,19 +112,19 @@ bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
MemorizeStatCalls::LookupResult
MemorizeStatCalls::getStat(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
- LookupResult Result = statChained(Path, Data, isFile, F, FS);
-
- // Do not cache failed stats, it is easy to construct common inconsistent
- // situations if we do, and they are not important for PCH performance (which
- // currently only needs the stats to construct the initial FileManager
- // entries).
- if (Result == CacheMissing)
- return Result;
+ std::unique_ptr<llvm::vfs::File> *F,
+ llvm::vfs::FileSystem &FS) {
+ if (get(Path, Data, isFile, F, nullptr, FS)) {
+ // Do not cache failed stats, it is easy to construct common inconsistent
+ // situations if we do, and they are not important for PCH performance
+ // (which currently only needs the stats to construct the initial
+ // FileManager entries).
+ return CacheMissing;
+ }
// Cache file 'stat' results and directories with absolutely paths.
if (!Data.IsDirectory || llvm::sys::path::is_absolute(Path))
StatCalls[Path] = Data;
- return Result;
+ return CacheExists;
}
diff --git a/lib/Basic/FixedPoint.cpp b/lib/Basic/FixedPoint.cpp
new file mode 100644
index 000000000000..bfff0fc212e0
--- /dev/null
+++ b/lib/Basic/FixedPoint.cpp
@@ -0,0 +1,115 @@
+//===- FixedPoint.cpp - Fixed point constant handling -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Defines the implementation for the fixed point number interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FixedPoint.h"
+
+namespace clang {
+
+APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema) const {
+ llvm::APSInt NewVal = Val;
+ unsigned DstWidth = DstSema.getWidth();
+ unsigned DstScale = DstSema.getScale();
+ bool Upscaling = DstScale > getScale();
+
+ if (Upscaling) {
+ NewVal = NewVal.extend(NewVal.getBitWidth() + DstScale - getScale());
+ NewVal <<= (DstScale - getScale());
+ } else {
+ NewVal >>= (getScale() - DstScale);
+ }
+
+ if (DstSema.isSaturated()) {
+ auto Mask = llvm::APInt::getBitsSetFrom(
+ NewVal.getBitWidth(),
+ std::min(DstScale + DstSema.getIntegralBits(), NewVal.getBitWidth()));
+ llvm::APInt Masked(NewVal & Mask);
+
+ // Change in the bits above the sign
+ if (!(Masked == Mask || Masked == 0))
+ NewVal = NewVal.isNegative() ? Mask : ~Mask;
+
+ if (!DstSema.isSigned() && NewVal.isNegative())
+ NewVal = 0;
+ }
+
+ NewVal = NewVal.extOrTrunc(DstWidth);
+ NewVal.setIsSigned(DstSema.isSigned());
+ return APFixedPoint(NewVal, DstSema);
+}
+
+int APFixedPoint::compare(const APFixedPoint &Other) const {
+ llvm::APSInt ThisVal = getValue();
+ llvm::APSInt OtherVal = Other.getValue();
+ bool ThisSigned = Val.isSigned();
+ bool OtherSigned = OtherVal.isSigned();
+ unsigned OtherScale = Other.getScale();
+ unsigned OtherWidth = OtherVal.getBitWidth();
+
+ unsigned CommonWidth = std::max(Val.getBitWidth(), OtherWidth);
+
+ // Prevent overflow in the event the widths are the same but the scales differ
+ CommonWidth += getScale() >= OtherScale ? getScale() - OtherScale
+ : OtherScale - getScale();
+
+ ThisVal = ThisVal.extOrTrunc(CommonWidth);
+ OtherVal = OtherVal.extOrTrunc(CommonWidth);
+
+ unsigned CommonScale = std::max(getScale(), OtherScale);
+ ThisVal = ThisVal.shl(CommonScale - getScale());
+ OtherVal = OtherVal.shl(CommonScale - OtherScale);
+
+ if (ThisSigned && OtherSigned) {
+ if (ThisVal.sgt(OtherVal))
+ return 1;
+ else if (ThisVal.slt(OtherVal))
+ return -1;
+ } else if (!ThisSigned && !OtherSigned) {
+ if (ThisVal.ugt(OtherVal))
+ return 1;
+ else if (ThisVal.ult(OtherVal))
+ return -1;
+ } else if (ThisSigned && !OtherSigned) {
+ if (ThisVal.isSignBitSet())
+ return -1;
+ else if (ThisVal.ugt(OtherVal))
+ return 1;
+ else if (ThisVal.ult(OtherVal))
+ return -1;
+ } else {
+ // !ThisSigned && OtherSigned
+ if (OtherVal.isSignBitSet())
+ return 1;
+ else if (ThisVal.ugt(OtherVal))
+ return 1;
+ else if (ThisVal.ult(OtherVal))
+ return -1;
+ }
+
+ return 0;
+}
+
+APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) {
+ bool IsUnsigned = !Sema.isSigned();
+ auto Val = llvm::APSInt::getMaxValue(Sema.getWidth(), IsUnsigned);
+ if (IsUnsigned && Sema.hasUnsignedPadding())
+ Val = Val.lshr(1);
+ return APFixedPoint(Val, Sema);
+}
+
+APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) {
+ auto Val = llvm::APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned());
+ return APFixedPoint(Val, Sema);
+}
+
+} // namespace clang
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 7ec3cb7dd65b..b961c8333bd7 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -34,28 +34,6 @@
using namespace clang;
//===----------------------------------------------------------------------===//
-// IdentifierInfo Implementation
-//===----------------------------------------------------------------------===//
-
-IdentifierInfo::IdentifierInfo() {
- TokenID = tok::identifier;
- ObjCOrBuiltinID = 0;
- HasMacro = false;
- HadMacro = false;
- IsExtension = false;
- IsFutureCompatKeyword = false;
- IsPoisoned = false;
- IsCPPOperatorKeyword = false;
- NeedsHandleIdentifier = false;
- IsFromAST = false;
- ChangedAfterLoad = false;
- FEChangedAfterLoad = false;
- RevertedTokenID = false;
- OutOfDate = false;
- IsModulesImport = false;
-}
-
-//===----------------------------------------------------------------------===//
// IdentifierTable Implementation
//===----------------------------------------------------------------------===//
@@ -99,30 +77,29 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
namespace {
enum {
- KEYC99 = 0x1,
- KEYCXX = 0x2,
- KEYCXX11 = 0x4,
- KEYGNU = 0x8,
- KEYMS = 0x10,
- BOOLSUPPORT = 0x20,
- KEYALTIVEC = 0x40,
- KEYNOCXX = 0x80,
- KEYBORLAND = 0x100,
- KEYOPENCLC = 0x200,
- KEYC11 = 0x400,
- KEYARC = 0x800,
- KEYNOMS18 = 0x01000,
- KEYNOOPENCL = 0x02000,
- WCHARSUPPORT = 0x04000,
- HALFSUPPORT = 0x08000,
- CHAR8SUPPORT = 0x10000,
- KEYCONCEPTS = 0x20000,
- KEYOBJC2 = 0x40000,
- KEYZVECTOR = 0x80000,
- KEYCOROUTINES = 0x100000,
- KEYMODULES = 0x200000,
- KEYCXX2A = 0x400000,
- KEYOPENCLCXX = 0x800000,
+ KEYC99 = 0x1,
+ KEYCXX = 0x2,
+ KEYCXX11 = 0x4,
+ KEYGNU = 0x8,
+ KEYMS = 0x10,
+ BOOLSUPPORT = 0x20,
+ KEYALTIVEC = 0x40,
+ KEYNOCXX = 0x80,
+ KEYBORLAND = 0x100,
+ KEYOPENCLC = 0x200,
+ KEYC11 = 0x400,
+ KEYNOMS18 = 0x800,
+ KEYNOOPENCL = 0x1000,
+ WCHARSUPPORT = 0x2000,
+ HALFSUPPORT = 0x4000,
+ CHAR8SUPPORT = 0x8000,
+ KEYCONCEPTS = 0x10000,
+ KEYOBJC = 0x20000,
+ KEYZVECTOR = 0x40000,
+ KEYCOROUTINES = 0x80000,
+ KEYMODULES = 0x100000,
+ KEYCXX2A = 0x200000,
+ KEYOPENCLCXX = 0x400000,
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A,
KEYALL = (0xffffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
@@ -155,6 +132,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled;
if (LangOpts.Char8 && (Flags & CHAR8SUPPORT)) return KS_Enabled;
if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) return KS_Enabled;
+ if (LangOpts.ZVector && (Flags & KEYZVECTOR)) return KS_Enabled;
if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLC))
return KS_Enabled;
if (LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLCXX)) return KS_Enabled;
@@ -162,8 +140,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (LangOpts.C11 && (Flags & KEYC11)) return KS_Enabled;
// We treat bridge casts as objective-C keywords so we can warn on them
// in non-arc mode.
- if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
- if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
+ if (LangOpts.ObjC && (Flags & KEYOBJC)) return KS_Enabled;
if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
if (LangOpts.CoroutinesTS && (Flags & KEYCOROUTINES)) return KS_Enabled;
if (LangOpts.ModulesTS && (Flags & KEYMODULES)) return KS_Enabled;
@@ -227,11 +204,8 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
if (LangOpts.CXXOperatorNames) \
AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
-#define OBJC1_AT_KEYWORD(NAME) \
- if (LangOpts.ObjC1) \
- AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
-#define OBJC2_AT_KEYWORD(NAME) \
- if (LangOpts.ObjC2) \
+#define OBJC_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC) \
AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
#define TESTING_KEYWORD(NAME, FLAGS)
#include "clang/Basic/TokenKinds.def"
@@ -382,24 +356,23 @@ unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
namespace clang {
-/// MultiKeywordSelector - One of these variable length records is kept for each
+/// One of these variable length records is kept for each
/// selector containing more than one keyword. We use a folding set
/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
/// this class is provided strictly through Selector.
-class MultiKeywordSelector
- : public DeclarationNameExtra, public llvm::FoldingSetNode {
- MultiKeywordSelector(unsigned nKeys) {
- ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
- }
+class alignas(IdentifierInfoAlignment) MultiKeywordSelector
+ : public detail::DeclarationNameExtra,
+ public llvm::FoldingSetNode {
+ MultiKeywordSelector(unsigned nKeys) : DeclarationNameExtra(nKeys) {}
public:
// Constructor for keyword selectors.
- MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
+ MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV)
+ : DeclarationNameExtra(nKeys) {
assert((nKeys > 1) && "not a multi-keyword selector");
- ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
// Fill in the trailing keyword array.
- IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
+ IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this + 1);
for (unsigned i = 0; i != nKeys; ++i)
KeyInfo[i] = IIV[i];
}
@@ -407,16 +380,16 @@ public:
// getName - Derive the full selector name and return it.
std::string getName() const;
- unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
+ using DeclarationNameExtra::getNumArgs;
using keyword_iterator = IdentifierInfo *const *;
keyword_iterator keyword_begin() const {
- return reinterpret_cast<keyword_iterator>(this+1);
+ return reinterpret_cast<keyword_iterator>(this + 1);
}
keyword_iterator keyword_end() const {
- return keyword_begin()+getNumArgs();
+ return keyword_begin() + getNumArgs();
}
IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
@@ -424,8 +397,8 @@ public:
return keyword_begin()[i];
}
- static void Profile(llvm::FoldingSetNodeID &ID,
- keyword_iterator ArgTys, unsigned NumArgs) {
+ static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys,
+ unsigned NumArgs) {
ID.AddInteger(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i]);
@@ -462,7 +435,7 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
StringRef Selector::getNameForSlot(unsigned int argIndex) const {
IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
- return II? II->getName() : StringRef();
+ return II ? II->getName() : StringRef();
}
std::string MultiKeywordSelector::getName() const {
@@ -584,6 +557,7 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
break;
case 'i':
if (startsWithWord(name, "init")) return OIT_Init;
+ break;
default:
break;
}
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 1a0c19059058..fd552f2baaca 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -71,6 +71,37 @@ Module::~Module() {
}
}
+static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
+ StringRef Platform = Target.getPlatformName();
+ StringRef Env = Target.getTriple().getEnvironmentName();
+
+ // Attempt to match platform and environment.
+ if (Platform == Feature || Target.getTriple().getOSName() == Feature ||
+ Env == Feature)
+ return true;
+
+ auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) {
+ auto Pos = LHS.find("-");
+ if (Pos == StringRef::npos)
+ return false;
+ SmallString<128> NewLHS = LHS.slice(0, Pos);
+ NewLHS += LHS.slice(Pos+1, LHS.size());
+ return NewLHS == RHS;
+ };
+
+ SmallString<128> PlatformEnv = Target.getTriple().getOSAndEnvironmentName();
+ // Darwin has different but equivalent variants for simulators, example:
+ // 1. x86_64-apple-ios-simulator
+ // 2. x86_64-apple-iossimulator
+ // where both are valid examples of the same platform+environment but in the
+ // variant (2) the simulator is hardcoded as part of the platform name. Both
+ // forms above should match for "iossimulator" requirement.
+ if (Target.getTriple().isOSDarwin() && PlatformEnv.endswith("simulator"))
+ return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature);
+
+ return PlatformEnv == Feature;
+}
+
/// Determine whether a translation unit built using the current
/// language options has the given feature.
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
@@ -88,12 +119,13 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
.Case("c17", LangOpts.C17)
.Case("freestanding", LangOpts.Freestanding)
.Case("gnuinlineasm", LangOpts.GNUAsm)
- .Case("objc", LangOpts.ObjC1)
+ .Case("objc", LangOpts.ObjC)
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
.Case("opencl", LangOpts.OpenCL)
.Case("tls", Target.isTLSSupported())
.Case("zvector", LangOpts.ZVector)
- .Default(Target.hasFeature(Feature));
+ .Default(Target.hasFeature(Feature) ||
+ isPlatformEnvironment(Target, Feature));
if (!HasFeature)
HasFeature = std::find(LangOpts.ModuleFeatures.begin(),
LangOpts.ModuleFeatures.end(),
@@ -577,10 +609,6 @@ void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
};
std::function<void(Visiting)> VisitModule = [&](Visiting V) {
- // Modules that aren't available cannot be made visible.
- if (!V.M->isAvailable())
- return;
-
// Nothing to do for a module that's already visible.
unsigned ID = V.M->getVisibilityID();
if (ImportLocs.size() <= ID)
@@ -594,8 +622,11 @@ void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
// Make any exported modules visible.
SmallVector<Module *, 16> Exports;
V.M->getExportedModules(Exports);
- for (Module *E : Exports)
- VisitModule({E, &V});
+ for (Module *E : Exports) {
+ // Don't recurse to unavailable submodules.
+ if (E->isAvailable())
+ VisitModule({E, &V});
+ }
for (auto &C : V.M->Conflicts) {
if (isVisible(C.Other)) {
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index 67b7d91e6292..a5bfac86e610 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -108,8 +108,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_LINEAR_unknown);
case OMPC_map:
- return llvm::StringSwitch<OpenMPMapClauseKind>(Str)
-#define OPENMP_MAP_KIND(Name) .Case(#Name, OMPC_MAP_##Name)
+ return llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_MAP_KIND(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_MAP_##Name))
+#define OPENMP_MAP_MODIFIER_KIND(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_MAP_MODIFIER_##Name))
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_MAP_unknown);
case OMPC_dist_schedule:
@@ -125,6 +128,12 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
.Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_MODIFIER_##Name))
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_DEFAULTMAP_unknown);
+ case OMPC_atomic_default_mem_order:
+ return llvm::StringSwitch<OpenMPAtomicDefaultMemOrderClauseKind>(Str)
+#define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name) \
+ .Case(#Name, OMPC_ATOMIC_DEFAULT_MEM_ORDER_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@@ -168,6 +177,10 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -233,10 +246,14 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_map:
switch (Type) {
case OMPC_MAP_unknown:
+ case OMPC_MAP_MODIFIER_last:
return "unknown";
#define OPENMP_MAP_KIND(Name) \
case OMPC_MAP_##Name: \
return #Name;
+#define OPENMP_MAP_MODIFIER_KIND(Name) \
+ case OMPC_MAP_MODIFIER_##Name: \
+ return #Name;
#include "clang/Basic/OpenMPKinds.def"
default:
break;
@@ -266,6 +283,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'schedule' clause type");
+ case OMPC_atomic_default_mem_order:
+ switch (Type) {
+ case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
+ return "unknown";
+#define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name) \
+ case OMPC_ATOMIC_DEFAULT_MEM_ORDER_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+}
+ llvm_unreachable("Invalid OpenMP 'atomic_default_mem_order' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@@ -309,6 +336,10 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -442,6 +473,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_requires:
+ switch (CKind) {
+#define OPENMP_REQUIRES_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
case OMPD_target_data:
switch (CKind) {
#define OPENMP_TARGET_DATA_CLAUSE(Name) \
@@ -961,6 +1002,7 @@ void clang::getOpenMPCaptureRegions(
case OMPD_declare_simd:
case OMPD_declare_target:
case OMPD_end_declare_target:
+ case OMPD_requires:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
diff --git a/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp
index eb916ec76fdc..aa844f2cd26c 100644
--- a/lib/Basic/SourceLocation.cpp
+++ b/lib/Basic/SourceLocation.cpp
@@ -77,6 +77,61 @@ SourceLocation::printToString(const SourceManager &SM) const {
LLVM_DUMP_METHOD void SourceLocation::dump(const SourceManager &SM) const {
print(llvm::errs(), SM);
+ llvm::errs() << '\n';
+}
+
+LLVM_DUMP_METHOD void SourceRange::dump(const SourceManager &SM) const {
+ print(llvm::errs(), SM);
+ llvm::errs() << '\n';
+}
+
+static PresumedLoc PrintDifference(raw_ostream &OS, const SourceManager &SM,
+ SourceLocation Loc, PresumedLoc Previous) {
+ if (Loc.isFileID()) {
+
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+
+ if (PLoc.isInvalid()) {
+ OS << "<invalid sloc>";
+ return Previous;
+ }
+
+ if (Previous.isInvalid() ||
+ strcmp(PLoc.getFilename(), Previous.getFilename()) != 0) {
+ OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
+ << PLoc.getColumn();
+ } else if (Previous.isInvalid() || PLoc.getLine() != Previous.getLine()) {
+ OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
+ } else {
+ OS << "col" << ':' << PLoc.getColumn();
+ }
+ return PLoc;
+ }
+ auto PrintedLoc = PrintDifference(OS, SM, SM.getExpansionLoc(Loc), Previous);
+
+ OS << " <Spelling=";
+ PrintedLoc = PrintDifference(OS, SM, SM.getSpellingLoc(Loc), PrintedLoc);
+ OS << '>';
+ return PrintedLoc;
+}
+
+void SourceRange::print(raw_ostream &OS, const SourceManager &SM) const {
+
+ OS << '<';
+ auto PrintedLoc = PrintDifference(OS, SM, B, {});
+ if (B != E) {
+ OS << ", ";
+ PrintDifference(OS, SM, E, PrintedLoc);
+ }
+ OS << '>';
+}
+
+LLVM_DUMP_METHOD std::string
+SourceRange::printToString(const SourceManager &SM) const {
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ print(OS, SM);
+ return OS.str();
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index efa6ad2493b2..ce8aa5d112b3 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -195,8 +195,7 @@ llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
}
unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
- auto IterBool =
- FilenameIDs.insert(std::make_pair(Name, FilenamesByID.size()));
+ auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
if (IterBool.second)
FilenamesByID.push_back(&*IterBool.first);
return IterBool.first->second;
@@ -1217,65 +1216,22 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
- unsigned Offs = 0;
+ unsigned I = 0;
while (true) {
// Skip over the contents of the line.
- const unsigned char *NextBuf = (const unsigned char *)Buf;
-
-#ifdef __SSE2__
- // Try to skip to the next newline using SSE instructions. This is very
- // performance sensitive for programs with lots of diagnostics and in -E
- // mode.
- __m128i CRs = _mm_set1_epi8('\r');
- __m128i LFs = _mm_set1_epi8('\n');
-
- // First fix up the alignment to 16 bytes.
- while (((uintptr_t)NextBuf & 0xF) != 0) {
- if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0')
- goto FoundSpecialChar;
- ++NextBuf;
- }
-
- // Scan 16 byte chunks for '\r' and '\n'. Ignore '\0'.
- while (NextBuf+16 <= End) {
- const __m128i Chunk = *(const __m128i*)NextBuf;
- __m128i Cmp = _mm_or_si128(_mm_cmpeq_epi8(Chunk, CRs),
- _mm_cmpeq_epi8(Chunk, LFs));
- unsigned Mask = _mm_movemask_epi8(Cmp);
-
- // If we found a newline, adjust the pointer and jump to the handling code.
- if (Mask != 0) {
- NextBuf += llvm::countTrailingZeros(Mask);
- goto FoundSpecialChar;
- }
- NextBuf += 16;
- }
-#endif
-
- while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
- ++NextBuf;
-
-#ifdef __SSE2__
-FoundSpecialChar:
-#endif
- Offs += NextBuf-Buf;
- Buf = NextBuf;
-
- if (Buf[0] == '\n' || Buf[0] == '\r') {
- // If this is \n\r or \r\n, skip both characters.
- if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1]) {
- ++Offs;
- ++Buf;
- }
- ++Offs;
- ++Buf;
- LineOffsets.push_back(Offs);
+ while (Buf[I] != '\n' && Buf[I] != '\r' && Buf[I] != '\0')
+ ++I;
+
+ if (Buf[I] == '\n' || Buf[I] == '\r') {
+ // If this is \r\n, skip both characters.
+ if (Buf[I] == '\r' && Buf[I+1] == '\n')
+ ++I;
+ ++I;
+ LineOffsets.push_back(I);
} else {
- // Otherwise, this is a null. If end of file, exit.
- if (Buf == End) break;
- // Otherwise, skip the null.
- ++Offs;
- ++Buf;
+ // Otherwise, this is a NUL. If end of file, exit.
+ if (Buf+I == End) break;
+ ++I;
}
}
@@ -1965,9 +1921,7 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
// Uses IncludedLocMap to retrieve/cache the decomposed loc.
using DecompTy = std::pair<FileID, unsigned>;
- using MapTy = llvm::DenseMap<FileID, DecompTy>;
- std::pair<MapTy::iterator, bool>
- InsertOp = IncludedLocMap.insert(std::make_pair(FID, DecompTy()));
+ auto InsertOp = IncludedLocMap.try_emplace(FID);
DecompTy &DecompLoc = InsertOp.first->second;
if (!InsertOp.second)
return DecompLoc; // already in map.
@@ -2263,8 +2217,8 @@ SourceManagerForFile::SourceManagerForFile(StringRef FileName,
StringRef Content) {
// This is referenced by `FileMgr` and will be released by `FileMgr` when it
// is deleted.
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
InMemoryFileSystem->addFile(
FileName, 0,
llvm::MemoryBuffer::getMemBuffer(Content, FileName,
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 3400c8721f7a..269fad38b8d5 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -63,8 +63,9 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
MinGlobalAlign = 0;
// From the glibc documentation, on GNU systems, malloc guarantees 16-byte
// alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
- // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html
- if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment())
+ // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html.
+ // This alignment guarantee also applies to Windows and Android.
+ if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid())
NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
else
NewAlign = 0; // Infer from basic type alignment.
@@ -684,7 +685,9 @@ bool TargetInfo::validateInputConstraint(
// FIXME: Fail if % is used with the last operand.
break;
case 'i': // immediate integer.
+ break;
case 'n': // immediate integer with a known value.
+ Info.setRequiresImmediate();
break;
case 'I': // Various constant constraints with target-specific meanings.
case 'J':
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 1ef2fe3b8141..cf87bc484621 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -16,6 +16,7 @@
#include "Targets/AArch64.h"
#include "Targets/AMDGPU.h"
+#include "Targets/ARC.h"
#include "Targets/ARM.h"
#include "Targets/AVR.h"
#include "Targets/BPF.h"
@@ -25,7 +26,6 @@
#include "Targets/MSP430.h"
#include "Targets/Mips.h"
#include "Targets/NVPTX.h"
-#include "Targets/Nios2.h"
#include "Targets/OSTargets.h"
#include "Targets/PNaCl.h"
#include "Targets/PPC.h"
@@ -124,6 +124,9 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
default:
return nullptr;
+ case llvm::Triple::arc:
+ return new ARCTargetInfo(Triple, Opts);
+
case llvm::Triple::xcore:
return new XCoreTargetInfo(Triple, Opts);
@@ -243,9 +246,6 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::msp430:
return new MSP430TargetInfo(Triple, Opts);
- case llvm::Triple::nios2:
- return new LinuxTargetInfo<Nios2TargetInfo>(Triple, Opts);
-
case llvm::Triple::mips:
switch (os) {
case llvm::Triple::Linux:
@@ -495,6 +495,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new NaClTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::ELFIAMCU:
return new MCUX86_32TargetInfo(Triple, Opts);
+ case llvm::Triple::Hurd:
+ return new HurdTargetInfo<X86_32TargetInfo>(Triple, Opts);
default:
return new X86_32TargetInfo(Triple, Opts);
}
@@ -566,17 +568,19 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::wasm32:
if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
Triple.getVendor() != llvm::Triple::UnknownVendor ||
- Triple.getOS() != llvm::Triple::UnknownOS ||
- Triple.getEnvironment() != llvm::Triple::UnknownEnvironment ||
- !(Triple.isOSBinFormatELF() || Triple.isOSBinFormatWasm()))
+ !Triple.isOSBinFormatWasm())
+ return nullptr;
+ if (Triple.getOS() != llvm::Triple::UnknownOS &&
+ Triple.getOS() != llvm::Triple::WASI)
return nullptr;
return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
case llvm::Triple::wasm64:
if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
Triple.getVendor() != llvm::Triple::UnknownVendor ||
- Triple.getOS() != llvm::Triple::UnknownOS ||
- Triple.getEnvironment() != llvm::Triple::UnknownEnvironment ||
- !(Triple.isOSBinFormatELF() || Triple.isOSBinFormatWasm()))
+ !Triple.isOSBinFormatWasm())
+ return nullptr;
+ if (Triple.getOS() != llvm::Triple::UnknownOS &&
+ Triple.getOS() != llvm::Triple::WASI)
return nullptr;
return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
@@ -640,7 +644,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
Opts->Features.push_back((F.getValue() ? "+" : "-") + F.getKey().str());
// Sort here, so we handle the features in a predictable order. (This matters
// when we're dealing with features that overlap.)
- llvm::sort(Opts->Features.begin(), Opts->Features.end());
+ llvm::sort(Opts->Features);
if (!Target->handleTargetFeatures(Opts->Features, Diags))
return nullptr;
diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index 3444591ac593..62919a02dcb9 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -37,11 +37,11 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), ABI("aapcs") {
- if (getTriple().getOS() == llvm::Triple::OpenBSD) {
+ if (getTriple().isOSOpenBSD()) {
Int64Type = SignedLongLong;
IntMaxType = SignedLongLong;
} else {
- if (!getTriple().isOSDarwin() && getTriple().getOS() != llvm::Triple::NetBSD)
+ if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
WCharType = UnsignedInt;
Int64Type = SignedLong;
@@ -122,10 +122,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Target identification.
Builder.defineMacro("__aarch64__");
- // For bare-metal none-eabi.
+ // For bare-metal.
if (getTriple().getOS() == llvm::Triple::UnknownOS &&
- (getTriple().getEnvironment() == llvm::Triple::EABI ||
- getTriple().getEnvironment() == llvm::Triple::EABIHF))
+ getTriple().isOSBinFormatELF())
Builder.defineMacro("__ELF__");
// Target properties.
@@ -195,6 +194,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasDotProd)
Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
+ if ((FPU & NeonMode) && HasFP16FML)
+ Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
+
switch (ArchKind) {
default:
break;
@@ -232,6 +234,7 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
Unaligned = 1;
HasFullFP16 = 0;
HasDotProd = 0;
+ HasFP16FML = 0;
ArchKind = llvm::AArch64::ArchKind::ARMV8A;
for (const auto &Feature : Features) {
@@ -253,6 +256,8 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasFullFP16 = 1;
if (Feature == "+dotprod")
HasDotProd = 1;
+ if (Feature == "+fp16fml")
+ HasFP16FML = 1;
}
setDataLayout();
@@ -268,6 +273,7 @@ AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_PreserveMost:
case CC_PreserveAll:
case CC_OpenCLKernel:
+ case CC_AArch64VectorCall:
case CC_Win64:
return CCCR_OK;
default:
@@ -508,6 +514,7 @@ WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_OpenCLKernel:
case CC_PreserveMost:
case CC_PreserveAll:
+ case CC_Swift:
case CC_Win64:
return CCCR_OK;
default:
diff --git a/lib/Basic/Targets/AArch64.h b/lib/Basic/Targets/AArch64.h
index a9df895e4dad..d7f767abd4d1 100644
--- a/lib/Basic/Targets/AArch64.h
+++ b/lib/Basic/Targets/AArch64.h
@@ -34,6 +34,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
unsigned Unaligned;
unsigned HasFullFP16;
unsigned HasDotProd;
+ unsigned HasFP16FML;
llvm::AArch64::ArchKind ArchKind;
static const Builtin::Info BuiltinInfo[];
diff --git a/lib/Basic/Targets/AMDGPU.cpp b/lib/Basic/Targets/AMDGPU.cpp
index b6b9aa2f1244..7313a692f46b 100644
--- a/lib/Basic/Targets/AMDGPU.cpp
+++ b/lib/Basic/Targets/AMDGPU.cpp
@@ -13,10 +13,10 @@
#include "AMDGPU.h"
#include "clang/Basic/Builtins.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -127,15 +127,19 @@ bool AMDGPUTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeatureVec) const {
+ using namespace llvm::AMDGPU;
+
// XXX - What does the member GPU mean if device name string passed here?
if (isAMDGCN(getTriple())) {
if (CPU.empty())
CPU = "gfx600";
- switch (parseAMDGCNName(CPU).Kind) {
+ switch (llvm::AMDGPU::parseArchAMDGCN(CPU)) {
case GK_GFX906:
Features["dl-insts"] = true;
+ Features["dot-insts"] = true;
LLVM_FALLTHROUGH;
+ case GK_GFX909:
case GK_GFX904:
case GK_GFX902:
case GK_GFX900:
@@ -145,15 +149,18 @@ bool AMDGPUTargetInfo::initFeatureMap(
case GK_GFX803:
case GK_GFX802:
case GK_GFX801:
+ Features["vi-insts"] = true;
Features["16-bit-insts"] = true;
Features["dpp"] = true;
Features["s-memrealtime"] = true;
- break;
+ LLVM_FALLTHROUGH;
case GK_GFX704:
case GK_GFX703:
case GK_GFX702:
case GK_GFX701:
case GK_GFX700:
+ Features["ci-insts"] = true;
+ LLVM_FALLTHROUGH;
case GK_GFX601:
case GK_GFX600:
break;
@@ -166,7 +173,7 @@ bool AMDGPUTargetInfo::initFeatureMap(
if (CPU.empty())
CPU = "r600";
- switch (parseR600Name(CPU).Kind) {
+ switch (llvm::AMDGPU::parseArchR600(CPU)) {
case GK_CAYMAN:
case GK_CYPRESS:
case GK_RV770:
@@ -198,7 +205,7 @@ void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts,
TargetOptions &TargetOpts) const {
bool hasFP32Denormals = false;
bool hasFP64Denormals = false;
- GPUInfo CGOptsGPU = parseGPUName(TargetOpts.CPU);
+
for (auto &I : TargetOpts.FeaturesAsWritten) {
if (I == "+fp32-denormals" || I == "-fp32-denormals")
hasFP32Denormals = true;
@@ -207,53 +214,20 @@ void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts,
}
if (!hasFP32Denormals)
TargetOpts.Features.push_back(
- (Twine(CGOptsGPU.HasFastFMAF && !CGOpts.FlushDenorm
- ? '+'
- : '-') +
- Twine("fp32-denormals"))
+ (Twine(hasFastFMAF() && hasFullRateDenormalsF32() && !CGOpts.FlushDenorm
+ ? '+' : '-') + Twine("fp32-denormals"))
.str());
// Always do not flush fp64 or fp16 denorms.
- if (!hasFP64Denormals && CGOptsGPU.HasFP64)
+ if (!hasFP64Denormals && hasFP64())
TargetOpts.Features.push_back("+fp64-fp16-denormals");
}
-constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::InvalidGPU;
-constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::R600GPUs[];
-constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::AMDGCNGPUs[];
-
-AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseR600Name(StringRef Name) {
- const auto *Result = llvm::find_if(
- R600GPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; });
-
- if (Result == std::end(R600GPUs))
- return InvalidGPU;
- return *Result;
-}
-
-AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseAMDGCNName(StringRef Name) {
- const auto *Result = llvm::find_if(
- AMDGCNGPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; });
-
- if (Result == std::end(AMDGCNGPUs))
- return InvalidGPU;
- return *Result;
-}
-
-AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseGPUName(StringRef Name) const {
- if (isAMDGCN(getTriple()))
- return parseAMDGCNName(Name);
- else
- return parseR600Name(Name);
-}
-
void AMDGPUTargetInfo::fillValidCPUList(
SmallVectorImpl<StringRef> &Values) const {
if (isAMDGCN(getTriple()))
- llvm::for_each(AMDGCNGPUs, [&Values](const GPUInfo &GPU) {
- Values.emplace_back(GPU.Name);});
+ llvm::AMDGPU::fillValidArchListAMDGCN(Values);
else
- llvm::for_each(R600GPUs, [&Values](const GPUInfo &GPU) {
- Values.emplace_back(GPU.Name);});
+ llvm::AMDGPU::fillValidArchListR600(Values);
}
void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) {
@@ -263,7 +237,12 @@ void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) {
AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple),
- GPU(isAMDGCN(Triple) ? AMDGCNGPUs[0] : parseR600Name(Opts.CPU)) {
+ GPUKind(isAMDGCN(Triple) ?
+ llvm::AMDGPU::parseArchAMDGCN(Opts.CPU) :
+ llvm::AMDGPU::parseArchR600(Opts.CPU)),
+ GPUFeatures(isAMDGCN(Triple) ?
+ llvm::AMDGPU::getArchAttrAMDGCN(GPUKind) :
+ llvm::AMDGPU::getArchAttrR600(GPUKind)) {
resetDataLayout(isAMDGCN(getTriple()) ? DataLayoutStringAMDGCN
: DataLayoutStringR600);
assert(DataLayout->getAllocaAddrSpace() == Private);
@@ -308,19 +287,22 @@ void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,
else
Builder.defineMacro("__R600__");
- if (GPU.Kind != GK_NONE)
- Builder.defineMacro(Twine("__") + Twine(GPU.CanonicalName) + Twine("__"));
+ if (GPUKind != llvm::AMDGPU::GK_NONE) {
+ StringRef CanonName = isAMDGCN(getTriple()) ?
+ getArchNameAMDGCN(GPUKind) : getArchNameR600(GPUKind);
+ Builder.defineMacro(Twine("__") + Twine(CanonName) + Twine("__"));
+ }
// TODO: __HAS_FMAF__, __HAS_LDEXPF__, __HAS_FP64__ are deprecated and will be
// removed in the near future.
- if (GPU.HasFMAF)
+ if (hasFMAF())
Builder.defineMacro("__HAS_FMAF__");
- if (GPU.HasFastFMAF)
+ if (hasFastFMAF())
Builder.defineMacro("FP_FAST_FMAF");
- if (GPU.HasLDEXPF)
+ if (hasLDEXPF())
Builder.defineMacro("__HAS_LDEXPF__");
- if (GPU.HasFP64)
+ if (hasFP64())
Builder.defineMacro("__HAS_FP64__");
- if (GPU.HasFastFMA)
+ if (hasFastFMA())
Builder.defineMacro("FP_FAST_FMA");
}
diff --git a/lib/Basic/Targets/AMDGPU.h b/lib/Basic/Targets/AMDGPU.h
index b0221031addf..926772809aa7 100644
--- a/lib/Basic/Targets/AMDGPU.h
+++ b/lib/Basic/Targets/AMDGPU.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TargetParser.h"
namespace clang {
namespace targets {
@@ -38,147 +39,47 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
static const LangASMap AMDGPUDefIsGenMap;
static const LangASMap AMDGPUDefIsPrivMap;
- /// GPU kinds supported by the AMDGPU target.
- enum GPUKind : uint32_t {
- // Not specified processor.
- GK_NONE = 0,
-
- // R600-based processors.
- GK_R600,
- GK_R630,
- GK_RS880,
- GK_RV670,
- GK_RV710,
- GK_RV730,
- GK_RV770,
- GK_CEDAR,
- GK_CYPRESS,
- GK_JUNIPER,
- GK_REDWOOD,
- GK_SUMO,
- GK_BARTS,
- GK_CAICOS,
- GK_CAYMAN,
- GK_TURKS,
-
- GK_R600_FIRST = GK_R600,
- GK_R600_LAST = GK_TURKS,
-
- // AMDGCN-based processors.
- GK_GFX600,
- GK_GFX601,
- GK_GFX700,
- GK_GFX701,
- GK_GFX702,
- GK_GFX703,
- GK_GFX704,
- GK_GFX801,
- GK_GFX802,
- GK_GFX803,
- GK_GFX810,
- GK_GFX900,
- GK_GFX902,
- GK_GFX904,
- GK_GFX906,
-
- GK_AMDGCN_FIRST = GK_GFX600,
- GK_AMDGCN_LAST = GK_GFX906,
- };
+ llvm::AMDGPU::GPUKind GPUKind;
+ unsigned GPUFeatures;
- struct GPUInfo {
- llvm::StringLiteral Name;
- llvm::StringLiteral CanonicalName;
- AMDGPUTargetInfo::GPUKind Kind;
- bool HasFMAF;
- bool HasFastFMAF;
- bool HasLDEXPF;
- bool HasFP64;
- bool HasFastFMA;
- };
- static constexpr GPUInfo InvalidGPU =
- {{""}, {""}, GK_NONE, false, false, false, false, false};
- static constexpr GPUInfo R600GPUs[26] = {
- // Name Canonical Kind Has Has Has Has Has
- // Name FMAF Fast LDEXPF FP64 Fast
- // FMAF FMA
- {{"r600"}, {"r600"}, GK_R600, false, false, false, false, false},
- {{"rv630"}, {"r600"}, GK_R600, false, false, false, false, false},
- {{"rv635"}, {"r600"}, GK_R600, false, false, false, false, false},
- {{"r630"}, {"r630"}, GK_R630, false, false, false, false, false},
- {{"rs780"}, {"rs880"}, GK_RS880, false, false, false, false, false},
- {{"rs880"}, {"rs880"}, GK_RS880, false, false, false, false, false},
- {{"rv610"}, {"rs880"}, GK_RS880, false, false, false, false, false},
- {{"rv620"}, {"rs880"}, GK_RS880, false, false, false, false, false},
- {{"rv670"}, {"rv670"}, GK_RV670, false, false, false, false, false},
- {{"rv710"}, {"rv710"}, GK_RV710, false, false, false, false, false},
- {{"rv730"}, {"rv730"}, GK_RV730, false, false, false, false, false},
- {{"rv740"}, {"rv770"}, GK_RV770, false, false, false, false, false},
- {{"rv770"}, {"rv770"}, GK_RV770, false, false, false, false, false},
- {{"cedar"}, {"cedar"}, GK_CEDAR, false, false, false, false, false},
- {{"palm"}, {"cedar"}, GK_CEDAR, false, false, false, false, false},
- {{"cypress"}, {"cypress"}, GK_CYPRESS, true, false, false, false, false},
- {{"hemlock"}, {"cypress"}, GK_CYPRESS, true, false, false, false, false},
- {{"juniper"}, {"juniper"}, GK_JUNIPER, false, false, false, false, false},
- {{"redwood"}, {"redwood"}, GK_REDWOOD, false, false, false, false, false},
- {{"sumo"}, {"sumo"}, GK_SUMO, false, false, false, false, false},
- {{"sumo2"}, {"sumo"}, GK_SUMO, false, false, false, false, false},
- {{"barts"}, {"barts"}, GK_BARTS, false, false, false, false, false},
- {{"caicos"}, {"caicos"}, GK_BARTS, false, false, false, false, false},
- {{"aruba"}, {"cayman"}, GK_CAYMAN, true, false, false, false, false},
- {{"cayman"}, {"cayman"}, GK_CAYMAN, true, false, false, false, false},
- {{"turks"}, {"turks"}, GK_TURKS, false, false, false, false, false},
- };
- static constexpr GPUInfo AMDGCNGPUs[32] = {
- // Name Canonical Kind Has Has Has Has Has
- // Name FMAF Fast LDEXPF FP64 Fast
- // FMAF FMA
- {{"gfx600"}, {"gfx600"}, GK_GFX600, true, true, true, true, true},
- {{"tahiti"}, {"gfx600"}, GK_GFX600, true, true, true, true, true},
- {{"gfx601"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
- {{"hainan"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
- {{"oland"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
- {{"pitcairn"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
- {{"verde"}, {"gfx601"}, GK_GFX601, true, false, true, true, true},
- {{"gfx700"}, {"gfx700"}, GK_GFX700, true, false, true, true, true},
- {{"kaveri"}, {"gfx700"}, GK_GFX700, true, false, true, true, true},
- {{"gfx701"}, {"gfx701"}, GK_GFX701, true, true, true, true, true},
- {{"hawaii"}, {"gfx701"}, GK_GFX701, true, true, true, true, true},
- {{"gfx702"}, {"gfx702"}, GK_GFX702, true, true, true, true, true},
- {{"gfx703"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
- {{"kabini"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
- {{"mullins"}, {"gfx703"}, GK_GFX703, true, false, true, true, true},
- {{"gfx704"}, {"gfx704"}, GK_GFX704, true, false, true, true, true},
- {{"bonaire"}, {"gfx704"}, GK_GFX704, true, false, true, true, true},
- {{"gfx801"}, {"gfx801"}, GK_GFX801, true, true, true, true, true},
- {{"carrizo"}, {"gfx801"}, GK_GFX801, true, true, true, true, true},
- {{"gfx802"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
- {{"iceland"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
- {{"tonga"}, {"gfx802"}, GK_GFX802, true, false, true, true, true},
- {{"gfx803"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
- {{"fiji"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
- {{"polaris10"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
- {{"polaris11"}, {"gfx803"}, GK_GFX803, true, false, true, true, true},
- {{"gfx810"}, {"gfx810"}, GK_GFX810, true, false, true, true, true},
- {{"stoney"}, {"gfx810"}, GK_GFX810, true, false, true, true, true},
- {{"gfx900"}, {"gfx900"}, GK_GFX900, true, true, true, true, true},
- {{"gfx902"}, {"gfx902"}, GK_GFX900, true, true, true, true, true},
- {{"gfx904"}, {"gfx904"}, GK_GFX904, true, true, true, true, true},
- {{"gfx906"}, {"gfx906"}, GK_GFX906, true, true, true, true, true},
- };
+ bool hasFP64() const {
+ return getTriple().getArch() == llvm::Triple::amdgcn ||
+ !!(GPUFeatures & llvm::AMDGPU::FEATURE_FP64);
+ }
- static GPUInfo parseR600Name(StringRef Name);
+ /// Has fast fma f32
+ bool hasFastFMAF() const {
+ return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32);
+ }
- static GPUInfo parseAMDGCNName(StringRef Name);
+ /// Has fast fma f64
+ bool hasFastFMA() const {
+ return getTriple().getArch() == llvm::Triple::amdgcn;
+ }
- GPUInfo parseGPUName(StringRef Name) const;
+ bool hasFMAF() const {
+ return getTriple().getArch() == llvm::Triple::amdgcn ||
+ !!(GPUFeatures & llvm::AMDGPU::FEATURE_FMA);
+ }
- GPUInfo GPU;
+ bool hasFullRateDenormalsF32() const {
+ return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
+ }
+
+ bool hasLDEXPF() const {
+ return getTriple().getArch() == llvm::Triple::amdgcn ||
+ !!(GPUFeatures & llvm::AMDGPU::FEATURE_LDEXP);
+ }
static bool isAMDGCN(const llvm::Triple &TT) {
return TT.getArch() == llvm::Triple::amdgcn;
}
+ static bool isR600(const llvm::Triple &TT) {
+ return TT.getArch() == llvm::Triple::r600;
+ }
+
public:
AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
@@ -187,10 +88,12 @@ public:
void adjust(LangOptions &Opts) override;
uint64_t getPointerWidthV(unsigned AddrSpace) const override {
- if (GPU.Kind <= GK_R600_LAST)
+ if (isR600(getTriple()))
return 32;
+
if (AddrSpace == Private || AddrSpace == Local)
return 32;
+
return 64;
}
@@ -321,20 +224,22 @@ public:
bool isValidCPUName(StringRef Name) const override {
if (getTriple().getArch() == llvm::Triple::amdgcn)
- return GK_NONE != parseAMDGCNName(Name).Kind;
- else
- return GK_NONE != parseR600Name(Name).Kind;
+ return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE;
+ return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE;
}
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool setCPU(const std::string &Name) override {
- if (getTriple().getArch() == llvm::Triple::amdgcn)
- GPU = parseAMDGCNName(Name);
- else
- GPU = parseR600Name(Name);
+ if (getTriple().getArch() == llvm::Triple::amdgcn) {
+ GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name);
+ GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind);
+ } else {
+ GPUKind = llvm::AMDGPU::parseArchR600(Name);
+ GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind);
+ }
- return GK_NONE != GPU.Kind;
+ return GPUKind != llvm::AMDGPU::GK_NONE;
}
void setSupportedOpenCLOpts() override {
@@ -342,16 +247,20 @@ public:
Opts.support("cl_clang_storage_class_specifiers");
Opts.support("cl_khr_icd");
- if (GPU.HasFP64)
+ bool IsAMDGCN = isAMDGCN(getTriple());
+
+ if (hasFP64())
Opts.support("cl_khr_fp64");
- if (GPU.Kind >= GK_CEDAR) {
+
+ if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
Opts.support("cl_khr_byte_addressable_store");
Opts.support("cl_khr_global_int32_base_atomics");
Opts.support("cl_khr_global_int32_extended_atomics");
Opts.support("cl_khr_local_int32_base_atomics");
Opts.support("cl_khr_local_int32_extended_atomics");
}
- if (GPU.Kind >= GK_AMDGCN_FIRST) {
+
+ if (IsAMDGCN) {
Opts.support("cl_khr_fp16");
Opts.support("cl_khr_int64_base_atomics");
Opts.support("cl_khr_int64_extended_atomics");
@@ -378,6 +287,27 @@ public:
}
}
+ LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
+ switch (AS) {
+ case 0:
+ return LangAS::opencl_generic;
+ case 1:
+ return LangAS::opencl_global;
+ case 3:
+ return LangAS::opencl_local;
+ case 4:
+ return LangAS::opencl_constant;
+ case 5:
+ return LangAS::opencl_private;
+ default:
+ return getLangASFromTargetAS(AS);
+ }
+ }
+
+ LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
+ return LangAS::Default;
+ }
+
llvm::Optional<LangAS> getConstantAddressSpace() const override {
return getLangASFromTargetAS(Constant);
}
diff --git a/lib/Basic/Targets/ARC.cpp b/lib/Basic/Targets/ARC.cpp
new file mode 100644
index 000000000000..2159ab8e2020
--- /dev/null
+++ b/lib/Basic/Targets/ARC.cpp
@@ -0,0 +1,25 @@
+//===--- ARC.cpp - Implement ARC target feature support -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements ARC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARC.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+void ARCTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__arc__");
+}
diff --git a/lib/Basic/Targets/ARC.h b/lib/Basic/Targets/ARC.h
new file mode 100644
index 000000000000..ee20568f3d5b
--- /dev/null
+++ b/lib/Basic/Targets/ARC.h
@@ -0,0 +1,74 @@
+//===--- ARC.h - Declare ARC target feature support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares ARC TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_ARC_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_ARC_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY ARCTargetInfo : public TargetInfo {
+public:
+ ARCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ NoAsmVariants = true;
+ LongLongAlign = 32;
+ SuitableAlign = 32;
+ DoubleAlign = LongDoubleAlign = 32;
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ UseZeroLengthBitfieldAlignment = true;
+ resetDataLayout("e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-"
+ "i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32");
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ const char *getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "gp", "sp", "fp", "ilink1", "r30", "blink"};
+ return llvm::makeArrayRef(GCCRegNames);
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARC_H
diff --git a/lib/Basic/Targets/ARM.cpp b/lib/Basic/Targets/ARM.cpp
index 19fcc5abea97..16644ace108b 100644
--- a/lib/Basic/Targets/ARM.cpp
+++ b/lib/Basic/Targets/ARM.cpp
@@ -28,8 +28,8 @@ void ARMTargetInfo::setABIAAPCS() {
DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
const llvm::Triple &T = getTriple();
- bool IsNetBSD = T.getOS() == llvm::Triple::NetBSD;
- bool IsOpenBSD = T.getOS() == llvm::Triple::OpenBSD;
+ bool IsNetBSD = T.isOSNetBSD();
+ bool IsOpenBSD = T.isOSOpenBSD();
if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
WCharType = UnsignedInt;
@@ -189,6 +189,8 @@ StringRef ARMTargetInfo::getCPUAttr() const {
return "8_3A";
case llvm::ARM::ArchKind::ARMV8_4A:
return "8_4A";
+ case llvm::ARM::ArchKind::ARMV8_5A:
+ return "8_5A";
case llvm::ARM::ArchKind::ARMV8MBaseline:
return "8M_BASE";
case llvm::ARM::ArchKind::ARMV8MMainline:
@@ -215,8 +217,8 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
HW_FP(0) {
- bool IsOpenBSD = Triple.getOS() == llvm::Triple::OpenBSD;
- bool IsNetBSD = Triple.getOS() == llvm::Triple::NetBSD;
+ bool IsOpenBSD = Triple.isOSOpenBSD();
+ bool IsNetBSD = Triple.isOSNetBSD();
// FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
// environment where size_t is `unsigned long` rather than `unsigned int`
@@ -280,9 +282,9 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
setABI("apcs-gnu");
break;
default:
- if (Triple.getOS() == llvm::Triple::NetBSD)
+ if (IsNetBSD)
setABI("apcs-gnu");
- else if (Triple.getOS() == llvm::Triple::OpenBSD)
+ else if (IsOpenBSD)
setABI("aapcs-linux");
else
setABI("aapcs");
@@ -661,7 +663,7 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
}
// ACLE 6.4.9 32-bit SIMD instructions
- if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM"))
+ if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))
Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
// ACLE 6.4.10 Hardware Integer Divide
@@ -994,6 +996,7 @@ WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
case CC_OpenCLKernel:
case CC_PreserveMost:
case CC_PreserveAll:
+ case CC_Swift:
return CCCR_OK;
default:
return CCCR_Warning;
diff --git a/lib/Basic/Targets/Hexagon.cpp b/lib/Basic/Targets/Hexagon.cpp
index 0ef1f6db281e..94e1388e381e 100644
--- a/lib/Basic/Targets/Hexagon.cpp
+++ b/lib/Basic/Targets/Hexagon.cpp
@@ -25,14 +25,7 @@ void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__qdsp6__", "1");
Builder.defineMacro("__hexagon__", "1");
- if (CPU == "hexagonv4") {
- Builder.defineMacro("__HEXAGON_V4__");
- Builder.defineMacro("__HEXAGON_ARCH__", "4");
- if (Opts.HexagonQdsp6Compat) {
- Builder.defineMacro("__QDSP6_V4__");
- Builder.defineMacro("__QDSP6_ARCH__", "4");
- }
- } else if (CPU == "hexagonv5") {
+ if (CPU == "hexagonv5") {
Builder.defineMacro("__HEXAGON_V5__");
Builder.defineMacro("__HEXAGON_ARCH__", "5");
if (Opts.HexagonQdsp6Compat) {
@@ -55,6 +48,9 @@ void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
} else if (CPU == "hexagonv65") {
Builder.defineMacro("__HEXAGON_V65__");
Builder.defineMacro("__HEXAGON_ARCH__", "65");
+ } else if (CPU == "hexagonv66") {
+ Builder.defineMacro("__HEXAGON_V66__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "66");
}
if (hasFeature("hvx-length64b")) {
@@ -150,9 +146,9 @@ struct CPUSuffix {
};
static constexpr CPUSuffix Suffixes[] = {
- {{"hexagonv4"}, {"4"}}, {{"hexagonv5"}, {"5"}},
- {{"hexagonv55"}, {"55"}}, {{"hexagonv60"}, {"60"}},
- {{"hexagonv62"}, {"62"}}, {{"hexagonv65"}, {"65"}},
+ {{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}},
+ {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}},
+ {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}},
};
const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
diff --git a/lib/Basic/Targets/Mips.cpp b/lib/Basic/Targets/Mips.cpp
index cbd5a01c3da8..d43edeae608f 100644
--- a/lib/Basic/Targets/Mips.cpp
+++ b/lib/Basic/Targets/Mips.cpp
@@ -59,6 +59,16 @@ void MipsTargetInfo::fillValidCPUList(
Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
}
+unsigned MipsTargetInfo::getISARev() const {
+ return llvm::StringSwitch<unsigned>(getCPU())
+ .Cases("mips32", "mips64", 1)
+ .Cases("mips32r2", "mips64r2", 2)
+ .Cases("mips32r3", "mips64r3", 3)
+ .Cases("mips32r5", "mips64r5", 5)
+ .Cases("mips32r6", "mips64r6", 6)
+ .Default(0);
+}
+
void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
if (BigEndian) {
@@ -84,13 +94,8 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");
}
- const std::string ISARev = llvm::StringSwitch<std::string>(getCPU())
- .Cases("mips32", "mips64", "1")
- .Cases("mips32r2", "mips64r2", "2")
- .Cases("mips32r3", "mips64r3", "3")
- .Cases("mips32r5", "mips64r5", "5")
- .Cases("mips32r6", "mips64r6", "6")
- .Default("");
+ const std::string ISARev = std::to_string(getISARev());
+
if (!ISARev.empty())
Builder.defineMacro("__mips_isa_rev", ISARev);
@@ -129,9 +134,22 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
if (IsSingleFloat)
Builder.defineMacro("__mips_single_float", Twine(1));
- Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32));
- Builder.defineMacro("_MIPS_FPSET",
- Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2)));
+ switch (FPMode) {
+ case FPXX:
+ Builder.defineMacro("__mips_fpr", Twine(0));
+ break;
+ case FP32:
+ Builder.defineMacro("__mips_fpr", Twine(32));
+ break;
+ case FP64:
+ Builder.defineMacro("__mips_fpr", Twine(64));
+ break;
+}
+
+ if (FPMode == FP64 || IsSingleFloat)
+ Builder.defineMacro("_MIPS_FPSET", Twine(32));
+ else
+ Builder.defineMacro("_MIPS_FPSET", Twine(16));
if (IsMips16)
Builder.defineMacro("__mips16", Twine(1));
@@ -189,7 +207,7 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
bool MipsTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("mips", true)
- .Case("fp64", HasFP64)
+ .Case("fp64", FPMode == FP64)
.Default(false);
}
@@ -235,5 +253,30 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
return false;
}
+ // -fpxx is valid only for the o32 ABI
+ if (FPMode == FPXX && (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx" << "o32";
+ return false;
+ }
+
+ // -mfp32 and n32/n64 ABIs are incompatible
+ if (FPMode != FP64 && FPMode != FPXX && !IsSingleFloat &&
+ (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" << CPU;
+ return false;
+ }
+ // Mips revision 6 and -mfp32 are incompatible
+ if (FPMode != FP64 && FPMode != FPXX && (CPU == "mips32r6" ||
+ CPU == "mips64r6")) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32" << CPU;
+ return false;
+ }
+ // Option -mfp64 permitted on Mips32 iff revision 2 or higher is present
+ if (FPMode == FP64 && (CPU == "mips1" || CPU == "mips2" ||
+ getISARev() < 2) && ABI == "o32") {
+ Diags.Report(diag::err_mips_fp64_req) << "-mfp64";
+ return false;
+ }
+
return true;
}
diff --git a/lib/Basic/Targets/Mips.h b/lib/Basic/Targets/Mips.h
index 11e9ac914430..d49f49888b0c 100644
--- a/lib/Basic/Targets/Mips.h
+++ b/lib/Basic/Targets/Mips.h
@@ -57,7 +57,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
bool UseIndirectJumpHazard;
protected:
- bool HasFP64;
+ enum FPModeEnum { FPXX, FP32, FP64 } FPMode;
std::string ABI;
public:
@@ -66,15 +66,20 @@ public:
IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),
IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),
DspRev(NoDSP), HasMSA(false), DisableMadd4(false),
- UseIndirectJumpHazard(false), HasFP64(false) {
+ UseIndirectJumpHazard(false), FPMode(FPXX) {
TheCXXABI.set(TargetCXXABI::GenericMIPS);
- setABI(getTriple().isMIPS32() ? "o32" : "n64");
+ if (Triple.isMIPS32())
+ setABI("o32");
+ else if (Triple.getEnvironment() == llvm::Triple::GNUABIN32)
+ setABI("n32");
+ else
+ setABI("n64");
CPU = ABI == "o32" ? "mips32r2" : "mips64r2";
- CanUseBSDABICalls = Triple.getOS() == llvm::Triple::FreeBSD ||
- Triple.getOS() == llvm::Triple::OpenBSD;
+ CanUseBSDABICalls = Triple.isOSFreeBSD() ||
+ Triple.isOSOpenBSD();
}
bool isIEEE754_2008Default() const {
@@ -127,7 +132,7 @@ public:
void setN32N64ABITypes() {
LongDoubleWidth = LongDoubleAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad();
- if (getTriple().getOS() == llvm::Triple::FreeBSD) {
+ if (getTriple().isOSFreeBSD()) {
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
@@ -137,7 +142,7 @@ public:
void setN64ABITypes() {
setN32N64ABITypes();
- if (getTriple().getOS() == llvm::Triple::OpenBSD) {
+ if (getTriple().isOSOpenBSD()) {
Int64Type = SignedLongLong;
} else {
Int64Type = SignedLong;
@@ -181,6 +186,8 @@ public:
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
+ unsigned getISARev() const;
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
@@ -305,7 +312,7 @@ public:
IsSingleFloat = false;
FloatABI = HardFloat;
DspRev = NoDSP;
- HasFP64 = isFP64Default();
+ FPMode = isFP64Default() ? FP64 : FPXX;
for (const auto &Feature : Features) {
if (Feature == "+single-float")
@@ -325,9 +332,11 @@ public:
else if (Feature == "+nomadd4")
DisableMadd4 = true;
else if (Feature == "+fp64")
- HasFP64 = true;
+ FPMode = FP64;
else if (Feature == "-fp64")
- HasFP64 = false;
+ FPMode = FP32;
+ else if (Feature == "+fpxx")
+ FPMode = FPXX;
else if (Feature == "+nan2008")
IsNan2008 = true;
else if (Feature == "-nan2008")
diff --git a/lib/Basic/Targets/NVPTX.cpp b/lib/Basic/Targets/NVPTX.cpp
index fd4ee1606061..ca41c4d14ca3 100644
--- a/lib/Basic/Targets/NVPTX.cpp
+++ b/lib/Basic/Targets/NVPTX.cpp
@@ -188,6 +188,9 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
case CudaArch::GFX810:
case CudaArch::GFX900:
case CudaArch::GFX902:
+ case CudaArch::GFX904:
+ case CudaArch::GFX906:
+ case CudaArch::GFX909:
case CudaArch::LAST:
break;
case CudaArch::UNKNOWN:
@@ -221,6 +224,8 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
return "700";
case CudaArch::SM_72:
return "720";
+ case CudaArch::SM_75:
+ return "750";
}
llvm_unreachable("unhandled CudaArch");
}();
diff --git a/lib/Basic/Targets/Nios2.cpp b/lib/Basic/Targets/Nios2.cpp
deleted file mode 100644
index 48f662dd98c1..000000000000
--- a/lib/Basic/Targets/Nios2.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//===--- Nios2.cpp - Implement Nios2 target feature support ---------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements Nios2 TargetInfo objects.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Nios2.h"
-#include "Targets.h"
-#include "clang/Basic/MacroBuilder.h"
-#include "clang/Basic/TargetBuiltins.h"
-#include "llvm/ADT/StringSwitch.h"
-
-using namespace clang;
-using namespace clang::targets;
-
-const Builtin::Info Nios2TargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
- {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
-#include "clang/Basic/BuiltinsNios2.def"
-};
-
-bool Nios2TargetInfo::isFeatureSupportedByCPU(StringRef Feature,
- StringRef CPU) const {
- const bool isR2 = CPU == "nios2r2";
- return llvm::StringSwitch<bool>(Feature)
- .Case("nios2r2mandatory", isR2)
- .Case("nios2r2bmx", isR2)
- .Case("nios2r2mpx", isR2)
- .Case("nios2r2cdx", isR2)
- .Default(false);
-}
-
-void Nios2TargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "nios2", Opts);
- DefineStd(Builder, "NIOS2", Opts);
-
- Builder.defineMacro("__nios2");
- Builder.defineMacro("__NIOS2");
- Builder.defineMacro("__nios2__");
- Builder.defineMacro("__NIOS2__");
-}
-
-ArrayRef<Builtin::Info> Nios2TargetInfo::getTargetBuiltins() const {
- return llvm::makeArrayRef(BuiltinInfo, clang::Nios2::LastTSBuiltin -
- Builtin::FirstTSBuiltin);
-}
diff --git a/lib/Basic/Targets/Nios2.h b/lib/Basic/Targets/Nios2.h
deleted file mode 100644
index ffeb414d4778..000000000000
--- a/lib/Basic/Targets/Nios2.h
+++ /dev/null
@@ -1,151 +0,0 @@
-//===--- Nios2.h - Declare Nios2 target feature support ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares Nios2 TargetInfo objects.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
-#define LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
-
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/TargetOptions.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Compiler.h"
-
-namespace clang {
-namespace targets {
-
-class LLVM_LIBRARY_VISIBILITY Nios2TargetInfo : public TargetInfo {
- void setDataLayout() {
- if (BigEndian)
- resetDataLayout("E-p:32:32:32-i8:8:32-i16:16:32-n32");
- else
- resetDataLayout("e-p:32:32:32-i8:8:32-i16:16:32-n32");
- }
-
- static const Builtin::Info BuiltinInfo[];
- std::string CPU;
- std::string ABI;
-
-public:
- Nios2TargetInfo(const llvm::Triple &triple, const TargetOptions &opts)
- : TargetInfo(triple), CPU(opts.CPU), ABI(opts.ABI) {
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
- setDataLayout();
- }
-
- StringRef getABI() const override { return ABI; }
- bool setABI(const std::string &Name) override {
- if (Name == "o32" || Name == "eabi") {
- ABI = Name;
- return true;
- }
- return false;
- }
-
- bool isValidCPUName(StringRef Name) const override {
- return Name == "nios2r1" || Name == "nios2r2";
- }
-
- void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
- Values.append({"nios2r1", "nios2r2"});
- }
-
- bool setCPU(const std::string &Name) override {
- if (isValidCPUName(Name)) {
- CPU = Name;
- return true;
- }
- return false;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override;
-
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;
-
- bool isFeatureSupportedByCPU(StringRef Feature, StringRef CPU) const;
-
- bool
- initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
- StringRef CPU,
- const std::vector<std::string> &FeatureVec) const override {
- static const char *allFeatures[] = {"nios2r2mandatory", "nios2r2bmx",
- "nios2r2mpx", "nios2r2cdx"
- };
- for (const char *feature : allFeatures) {
- Features[feature] = isFeatureSupportedByCPU(feature, CPU);
- }
- return true;
- }
-
- bool hasFeature(StringRef Feature) const override {
- return isFeatureSupportedByCPU(Feature, CPU);
- }
-
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
-
- ArrayRef<const char *> getGCCRegNames() const override {
- static const char *const GCCRegNames[] = {
- // CPU register names
- // Must match second column of GCCRegAliases
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
- "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20",
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30",
- "r31",
- // Floating point register names
- "ctl0", "ctl1", "ctl2", "ctl3", "ctl4", "ctl5", "ctl6", "ctl7", "ctl8",
- "ctl9", "ctl10", "ctl11", "ctl12", "ctl13", "ctl14", "ctl15"
- };
- return llvm::makeArrayRef(GCCRegNames);
- }
-
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default:
- return false;
-
- case 'r': // CPU registers.
- case 'd': // Equivalent to "r" unless generating MIPS16 code.
- case 'y': // Equivalent to "r", backwards compatibility only.
- case 'f': // floating-point registers.
- case 'c': // $25 for indirect jumps
- case 'l': // lo register
- case 'x': // hilo register pair
- Info.setAllowsRegister();
- return true;
- }
- }
-
- const char *getClobbers() const override { return ""; }
-
- ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
- static const TargetInfo::GCCRegAlias aliases[] = {
- {{"zero"}, "r0"}, {{"at"}, "r1"}, {{"et"}, "r24"},
- {{"bt"}, "r25"}, {{"gp"}, "r26"}, {{"sp"}, "r27"},
- {{"fp"}, "r28"}, {{"ea"}, "r29"}, {{"ba"}, "r30"},
- {{"ra"}, "r31"}, {{"status"}, "ctl0"}, {{"estatus"}, "ctl1"},
- {{"bstatus"}, "ctl2"}, {{"ienable"}, "ctl3"}, {{"ipending"}, "ctl4"},
- {{"cpuid"}, "ctl5"}, {{"exception"}, "ctl7"}, {{"pteaddr"}, "ctl8"},
- {{"tlbacc"}, "ctl9"}, {{"tlbmisc"}, "ctl10"}, {{"badaddr"}, "ctl12"},
- {{"config"}, "ctl13"}, {{"mpubase"}, "ctl14"}, {{"mpuacc"}, "ctl15"},
- };
- return llvm::makeArrayRef(aliases);
- }
-};
-
-} // namespace targets
-} // namespace clang
-#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NIOS2_H
diff --git a/lib/Basic/Targets/OSTargets.cpp b/lib/Basic/Targets/OSTargets.cpp
index 50abd4ce0c8c..6252a51ef710 100644
--- a/lib/Basic/Targets/OSTargets.cpp
+++ b/lib/Basic/Targets/OSTargets.cpp
@@ -33,7 +33,7 @@ void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
Builder.defineMacro("_FORTIFY_SOURCE", "0");
// Darwin defines __weak, __strong, and __unsafe_unretained even in C mode.
- if (!Opts.ObjC1) {
+ if (!Opts.ObjC) {
// __weak is always defined, for use in blocks and with objc pointers.
Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
Builder.defineMacro("__strong", "");
diff --git a/lib/Basic/Targets/OSTargets.h b/lib/Basic/Targets/OSTargets.h
index d0354784acf9..085efa02cc5f 100644
--- a/lib/Basic/Targets/OSTargets.h
+++ b/lib/Basic/Targets/OSTargets.h
@@ -133,6 +133,15 @@ public:
/// is very similar to ELF's "protected"; Darwin requires a "weak"
/// attribute on declarations that can be dynamically replaced.
bool hasProtectedVisibility() const override { return false; }
+
+ TargetInfo::IntType getLeastIntTypeByWidth(unsigned BitWidth,
+ bool IsSigned) const final {
+ // Darwin uses `long long` for `int_least64_t` and `int_fast64_t`.
+ return BitWidth == 64
+ ? (IsSigned ? TargetInfo::SignedLongLong
+ : TargetInfo::UnsignedLongLong)
+ : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
+ }
};
// DragonFlyBSD Target
@@ -257,6 +266,8 @@ protected:
Builder.defineMacro("__HAIKU__");
Builder.defineMacro("__ELF__");
DefineStd(Builder, "unix", Opts);
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
}
public:
@@ -267,7 +278,38 @@ public:
this->PtrDiffType = TargetInfo::SignedLong;
this->ProcessIDType = TargetInfo::SignedLong;
this->TLSSupported = false;
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->HasFloat128 = true;
+ break;
+ }
+ }
+};
+
+// Hurd target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY HurdTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ // Hurd defines; list based off of gcc output.
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__GNU__");
+ Builder.defineMacro("__gnu_hurd__");
+ Builder.defineMacro("__MACH__");
+ Builder.defineMacro("__GLIBC__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
}
+public:
+ HurdTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {}
};
// Minix Target
@@ -303,7 +345,6 @@ protected:
// Linux defines; list based off of gcc output
DefineStd(Builder, "unix", Opts);
DefineStd(Builder, "linux", Opts);
- Builder.defineMacro("__gnu_linux__");
Builder.defineMacro("__ELF__");
if (Triple.isAndroid()) {
Builder.defineMacro("__ANDROID__", "1");
@@ -313,6 +354,8 @@ protected:
this->PlatformMinVersion = VersionTuple(Maj, Min, Rev);
if (Maj)
Builder.defineMacro("__ANDROID_API__", Twine(Maj));
+ } else {
+ Builder.defineMacro("__gnu_linux__");
}
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
@@ -341,7 +384,6 @@ public:
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- case llvm::Triple::systemz:
this->HasFloat128 = true;
break;
}
@@ -397,7 +439,7 @@ public:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->HasFloat128 = true;
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
default:
this->MCountName = "__mcount";
break;
@@ -643,6 +685,7 @@ public:
WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedShort;
+ this->WIntType = TargetInfo::UnsignedShort;
}
};
diff --git a/lib/Basic/Targets/PPC.cpp b/lib/Basic/Targets/PPC.cpp
index b4eb3b1b97b7..6cfbed1713e1 100644
--- a/lib/Basic/Targets/PPC.cpp
+++ b/lib/Basic/Targets/PPC.cpp
@@ -83,8 +83,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
if (getTriple().getArch() == llvm::Triple::ppc64le) {
Builder.defineMacro("_LITTLE_ENDIAN");
} else {
- if (getTriple().getOS() != llvm::Triple::NetBSD &&
- getTriple().getOS() != llvm::Triple::OpenBSD)
+ if (!getTriple().isOSNetBSD() &&
+ !getTriple().isOSOpenBSD())
Builder.defineMacro("_BIG_ENDIAN");
}
@@ -412,6 +412,36 @@ ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}
+// PPC ELFABIv2 DWARF Definitoin "Table 2.26. Mappings of Common Registers".
+// vs0 ~ vs31 is mapping to 32 - 63,
+// vs32 ~ vs63 is mapping to 77 - 108.
+const TargetInfo::AddlRegName GCCAddlRegNames[] = {
+ // Table of additional register names to use in user input.
+ {{"vs0"}, 32}, {{"vs1"}, 33}, {{"vs2"}, 34}, {{"vs3"}, 35},
+ {{"vs4"}, 36}, {{"vs5"}, 37}, {{"vs6"}, 38}, {{"vs7"}, 39},
+ {{"vs8"}, 40}, {{"vs9"}, 41}, {{"vs10"}, 42}, {{"vs11"}, 43},
+ {{"vs12"}, 44}, {{"vs13"}, 45}, {{"vs14"}, 46}, {{"vs15"}, 47},
+ {{"vs16"}, 48}, {{"vs17"}, 49}, {{"vs18"}, 50}, {{"vs19"}, 51},
+ {{"vs20"}, 52}, {{"vs21"}, 53}, {{"vs22"}, 54}, {{"vs23"}, 55},
+ {{"vs24"}, 56}, {{"vs25"}, 57}, {{"vs26"}, 58}, {{"vs27"}, 59},
+ {{"vs28"}, 60}, {{"vs29"}, 61}, {{"vs30"}, 62}, {{"vs31"}, 63},
+ {{"vs32"}, 77}, {{"vs33"}, 78}, {{"vs34"}, 79}, {{"vs35"}, 80},
+ {{"vs36"}, 81}, {{"vs37"}, 82}, {{"vs38"}, 83}, {{"vs39"}, 84},
+ {{"vs40"}, 85}, {{"vs41"}, 86}, {{"vs42"}, 87}, {{"vs43"}, 88},
+ {{"vs44"}, 89}, {{"vs45"}, 90}, {{"vs46"}, 91}, {{"vs47"}, 92},
+ {{"vs48"}, 93}, {{"vs49"}, 94}, {{"vs50"}, 95}, {{"vs51"}, 96},
+ {{"vs52"}, 97}, {{"vs53"}, 98}, {{"vs54"}, 99}, {{"vs55"}, 100},
+ {{"vs56"}, 101}, {{"vs57"}, 102}, {{"vs58"}, 103}, {{"vs59"}, 104},
+ {{"vs60"}, 105}, {{"vs61"}, 106}, {{"vs62"}, 107}, {{"vs63"}, 108},
+};
+
+ArrayRef<TargetInfo::AddlRegName> PPCTargetInfo::getGCCAddlRegNames() const {
+ if (ABI == "elfv2")
+ return llvm::makeArrayRef(GCCAddlRegNames);
+ else
+ return TargetInfo::getGCCAddlRegNames();
+}
+
static constexpr llvm::StringLiteral ValidCPUNames[] = {
{"generic"}, {"440"}, {"450"}, {"601"}, {"602"},
{"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"},
diff --git a/lib/Basic/Targets/PPC.h b/lib/Basic/Targets/PPC.h
index 439c73a0e326..058970a0e098 100644
--- a/lib/Basic/Targets/PPC.h
+++ b/lib/Basic/Targets/PPC.h
@@ -176,6 +176,8 @@ public:
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
+
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
@@ -201,6 +203,7 @@ public:
case 's': // VSX vector register to hold scalar float data
case 'a': // Any VSX register
case 'c': // An individual CR bit
+ case 'i': // FP or VSX register to hold 64-bit integers data
break;
default:
return false;
@@ -328,7 +331,7 @@ public:
break;
}
- if (getTriple().getOS() == llvm::Triple::FreeBSD) {
+ if (getTriple().isOSFreeBSD()) {
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
diff --git a/lib/Basic/Targets/Sparc.h b/lib/Basic/Targets/Sparc.h
index af2189f21468..5ae305bffb43 100644
--- a/lib/Basic/Targets/Sparc.h
+++ b/lib/Basic/Targets/Sparc.h
@@ -199,7 +199,7 @@ public:
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
// OpenBSD uses long long for int64_t and intmax_t.
- if (getTriple().getOS() == llvm::Triple::OpenBSD)
+ if (getTriple().isOSOpenBSD())
IntMaxType = SignedLongLong;
else
IntMaxType = SignedLong;
diff --git a/lib/Basic/Targets/WebAssembly.cpp b/lib/Basic/Targets/WebAssembly.cpp
index b8a2a092aff4..2fdc84bb8cc8 100644
--- a/lib/Basic/Targets/WebAssembly.cpp
+++ b/lib/Basic/Targets/WebAssembly.cpp
@@ -24,6 +24,8 @@ using namespace clang::targets;
const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsWebAssembly.def"
@@ -35,6 +37,7 @@ static constexpr llvm::StringLiteral ValidCPUNames[] = {
bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("simd128", SIMDLevel >= SIMD128)
+ .Case("unimplemented-simd128", SIMDLevel >= UnimplementedSIMD128)
.Case("nontrapping-fptoint", HasNontrappingFPToInt)
.Case("sign-ext", HasSignExt)
.Case("exception-handling", HasExceptionHandling)
@@ -55,6 +58,44 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
if (SIMDLevel >= SIMD128)
Builder.defineMacro("__wasm_simd128__");
+ if (SIMDLevel >= UnimplementedSIMD128)
+ Builder.defineMacro("__wasm_unimplemented_simd128__");
+}
+
+void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
+ SIMDEnum Level) {
+ switch (Level) {
+ case UnimplementedSIMD128:
+ Features["unimplemented-simd128"] = true;
+ LLVM_FALLTHROUGH;
+ case SIMD128:
+ Features["simd128"] = true;
+ LLVM_FALLTHROUGH;
+ case NoSIMD:
+ break;
+ }
+}
+
+bool WebAssemblyTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ if (CPU == "bleeding-edge") {
+ Features["nontrapping-fptoint"] = true;
+ Features["sign-ext"] = true;
+ setSIMDLevel(Features, SIMD128);
+ }
+ // Other targets do not consider user-configured features here, but while we
+ // are actively developing new features it is useful to let user-configured
+ // features control availability of builtins
+ setSIMDLevel(Features, SIMDLevel);
+ if (HasNontrappingFPToInt)
+ Features["nontrapping-fptoint"] = true;
+ if (HasSignExt)
+ Features["sign-ext"] = true;
+ if (HasExceptionHandling)
+ Features["exception-handling"] = true;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
bool WebAssemblyTargetInfo::handleTargetFeatures(
@@ -68,6 +109,14 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
continue;
}
+ if (Feature == "+unimplemented-simd128") {
+ SIMDLevel = std::max(SIMDLevel, SIMDEnum(UnimplementedSIMD128));
+ continue;
+ }
+ if (Feature == "-unimplemented-simd128") {
+ SIMDLevel = std::min(SIMDLevel, SIMDEnum(UnimplementedSIMD128 - 1));
+ continue;
+ }
if (Feature == "+nontrapping-fptoint") {
HasNontrappingFPToInt = true;
continue;
diff --git a/lib/Basic/Targets/WebAssembly.h b/lib/Basic/Targets/WebAssembly.h
index c04c5cb6fb3a..3dea9a373cb4 100644
--- a/lib/Basic/Targets/WebAssembly.h
+++ b/lib/Basic/Targets/WebAssembly.h
@@ -28,7 +28,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
enum SIMDEnum {
NoSIMD,
SIMD128,
- } SIMDLevel;
+ UnimplementedSIMD128,
+ } SIMDLevel = NoSIMD;
bool HasNontrappingFPToInt;
bool HasSignExt;
@@ -59,18 +60,12 @@ protected:
MacroBuilder &Builder) const override;
private:
+ static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level);
+
bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const override {
- if (CPU == "bleeding-edge") {
- Features["simd128"] = true;
- Features["nontrapping-fptoint"] = true;
- Features["sign-ext"] = true;
- }
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
- }
-
+ const std::vector<std::string> &FeaturesVec) const override;
bool hasFeature(StringRef Feature) const final;
bool handleTargetFeatures(std::vector<std::string> &Features,
diff --git a/lib/Basic/Targets/X86.cpp b/lib/Basic/Targets/X86.cpp
index e295cff9d5d2..53b4c153e952 100644
--- a/lib/Basic/Targets/X86.cpp
+++ b/lib/Basic/Targets/X86.cpp
@@ -142,7 +142,6 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "gfni", true);
setFeatureEnabledImpl(Features, "vpclmulqdq", true);
setFeatureEnabledImpl(Features, "avx512bitalg", true);
- setFeatureEnabledImpl(Features, "avx512vnni", true);
setFeatureEnabledImpl(Features, "avx512vbmi2", true);
setFeatureEnabledImpl(Features, "avx512vpopcntdq", true);
setFeatureEnabledImpl(Features, "rdpid", true);
@@ -152,6 +151,12 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "avx512vbmi", true);
setFeatureEnabledImpl(Features, "sha", true);
LLVM_FALLTHROUGH;
+ case CK_Cascadelake:
+ //Cannonlake has no VNNI feature inside while Icelake has
+ if (Kind != CK_Cannonlake)
+ // CLK inherits all SKX features plus AVX512_VNNI
+ setFeatureEnabledImpl(Features, "avx512vnni", true);
+ LLVM_FALLTHROUGH;
case CK_SkylakeServer:
setFeatureEnabledImpl(Features, "avx512f", true);
setFeatureEnabledImpl(Features, "avx512cd", true);
@@ -166,10 +171,12 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "xsavec", true);
setFeatureEnabledImpl(Features, "xsaves", true);
setFeatureEnabledImpl(Features, "mpx", true);
- if (Kind != CK_SkylakeServer) // SKX inherits all SKL features, except SGX
+ if (Kind != CK_SkylakeServer
+ && Kind != CK_Cascadelake)
+ // SKX/CLX inherits all SKL features, except SGX
setFeatureEnabledImpl(Features, "sgx", true);
setFeatureEnabledImpl(Features, "clflushopt", true);
- setFeatureEnabledImpl(Features, "rtm", true);
+ setFeatureEnabledImpl(Features, "aes", true);
LLVM_FALLTHROUGH;
case CK_Broadwell:
setFeatureEnabledImpl(Features, "rdseed", true);
@@ -196,7 +203,6 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "xsaveopt", true);
LLVM_FALLTHROUGH;
case CK_Westmere:
- setFeatureEnabledImpl(Features, "aes", true);
setFeatureEnabledImpl(Features, "pclmul", true);
LLVM_FALLTHROUGH;
case CK_Nehalem:
@@ -248,10 +254,10 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "clflushopt", true);
setFeatureEnabledImpl(Features, "mpx", true);
setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "aes", true);
LLVM_FALLTHROUGH;
case CK_Silvermont:
setFeatureEnabledImpl(Features, "rdrnd", true);
- setFeatureEnabledImpl(Features, "aes", true);
setFeatureEnabledImpl(Features, "pclmul", true);
setFeatureEnabledImpl(Features, "sse4.2", true);
setFeatureEnabledImpl(Features, "prfchw", true);
@@ -281,7 +287,6 @@ bool X86TargetInfo::initFeatureMap(
setFeatureEnabledImpl(Features, "lzcnt", true);
setFeatureEnabledImpl(Features, "bmi", true);
setFeatureEnabledImpl(Features, "bmi2", true);
- setFeatureEnabledImpl(Features, "rtm", true);
setFeatureEnabledImpl(Features, "fma", true);
setFeatureEnabledImpl(Features, "rdrnd", true);
setFeatureEnabledImpl(Features, "f16c", true);
@@ -796,8 +801,6 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasCLDEMOTE = true;
} else if (Feature == "+rdpid") {
HasRDPID = true;
- } else if (Feature == "+retpoline") {
- HasRetpoline = true;
} else if (Feature == "+retpoline-external-thunk") {
HasRetpolineExternalThunk = true;
} else if (Feature == "+sahf") {
@@ -862,6 +865,11 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
/// definitions for this particular subtarget.
void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
+ std::string CodeModel = getTargetOpts().CodeModel;
+ if (CodeModel == "default")
+ CodeModel = "small";
+ Builder.defineMacro("__code_model_" + CodeModel + "_");
+
// Target identification.
if (getTriple().getArch() == llvm::Triple::x86_64) {
Builder.defineMacro("__amd64__");
@@ -948,6 +956,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
case CK_Broadwell:
case CK_SkylakeClient:
case CK_SkylakeServer:
+ case CK_Cascadelake:
case CK_Cannonlake:
case CK_IcelakeClient:
case CK_IcelakeServer:
@@ -1083,6 +1092,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasMWAITX)
Builder.defineMacro("__MWAITX__");
+ if (HasMOVBE)
+ Builder.defineMacro("__MOVBE__");
+
switch (XOPLevel) {
case XOP:
Builder.defineMacro("__XOP__");
@@ -1397,7 +1409,6 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("rdpid", HasRDPID)
.Case("rdrnd", HasRDRND)
.Case("rdseed", HasRDSEED)
- .Case("retpoline", HasRetpoline)
.Case("retpoline-external-thunk", HasRetpolineExternalThunk)
.Case("rtm", HasRTM)
.Case("sahf", HasLAHFSAHF)
@@ -1678,6 +1689,7 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
return false;
break;
}
+ LLVM_FALLTHROUGH;
case 'v':
case 'x':
if (SSELevel >= AVX512F)
diff --git a/lib/Basic/Targets/X86.h b/lib/Basic/Targets/X86.h
index 019bc8d51a63..05930ae9eec0 100644
--- a/lib/Basic/Targets/X86.h
+++ b/lib/Basic/Targets/X86.h
@@ -98,7 +98,6 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasMOVBE = false;
bool HasPREFETCHWT1 = false;
bool HasRDPID = false;
- bool HasRetpoline = false;
bool HasRetpolineExternalThunk = false;
bool HasLAHFSAHF = false;
bool HasWBNOINVD = false;
@@ -226,6 +225,7 @@ public:
case 'Y':
if ((++I != E) && ((*I == '0') || (*I == 'z')))
return "xmm0";
+ break;
default:
break;
}
@@ -291,9 +291,6 @@ public:
return checkCPUKind(CPU = getCPUKind(Name));
}
- bool supportsMultiVersioning() const override {
- return getTriple().isOSBinFormatELF();
- }
unsigned multiVersionSortPriority(StringRef Name) const override;
bool setFPMath(StringRef Name) override;
@@ -350,11 +347,9 @@ public:
(1 << TargetInfo::LongDouble));
// x86-32 has atomics up to 8 bytes
- CPUKind Kind = getCPUKind(Opts.CPU);
- if (Kind >= CK_i586 || Kind == CK_Generic)
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- else if (Kind >= CK_i486)
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ // FIXME: Check that we actually have cmpxchg8b before setting
+ // MaxAtomicInlineWidth. (cmpxchg8b is an i586 instruction.)
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
}
BuiltinVaListKind getBuiltinVaListKind() const override {
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
deleted file mode 100644
index bcfcbdbb9014..000000000000
--- a/lib/Basic/VirtualFileSystem.cpp
+++ /dev/null
@@ -1,2026 +0,0 @@
-//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the VirtualFileSystem interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Basic/VirtualFileSystem.h"
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Chrono.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <atomic>
-#include <cassert>
-#include <cstdint>
-#include <iterator>
-#include <limits>
-#include <map>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <vector>
-
-using namespace clang;
-using namespace vfs;
-using namespace llvm;
-
-using llvm::sys::fs::file_status;
-using llvm::sys::fs::file_type;
-using llvm::sys::fs::perms;
-using llvm::sys::fs::UniqueID;
-
-Status::Status(const file_status &Status)
- : UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
- User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
- Type(Status.type()), Perms(Status.permissions()) {}
-
-Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime,
- uint32_t User, uint32_t Group, uint64_t Size, file_type Type,
- perms Perms)
- : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
- Type(Type), Perms(Perms) {}
-
-Status Status::copyWithNewName(const Status &In, StringRef NewName) {
- return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
- In.getUser(), In.getGroup(), In.getSize(), In.getType(),
- In.getPermissions());
-}
-
-Status Status::copyWithNewName(const file_status &In, StringRef NewName) {
- return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
- In.getUser(), In.getGroup(), In.getSize(), In.type(),
- In.permissions());
-}
-
-bool Status::equivalent(const Status &Other) const {
- assert(isStatusKnown() && Other.isStatusKnown());
- return getUniqueID() == Other.getUniqueID();
-}
-
-bool Status::isDirectory() const {
- return Type == file_type::directory_file;
-}
-
-bool Status::isRegularFile() const {
- return Type == file_type::regular_file;
-}
-
-bool Status::isOther() const {
- return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
-}
-
-bool Status::isSymlink() const {
- return Type == file_type::symlink_file;
-}
-
-bool Status::isStatusKnown() const {
- return Type != file_type::status_error;
-}
-
-bool Status::exists() const {
- return isStatusKnown() && Type != file_type::file_not_found;
-}
-
-File::~File() = default;
-
-FileSystem::~FileSystem() = default;
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatile) {
- auto F = openFileForRead(Name);
- if (!F)
- return F.getError();
-
- return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
-}
-
-std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
- if (llvm::sys::path::is_absolute(Path))
- return {};
-
- auto WorkingDir = getCurrentWorkingDirectory();
- if (!WorkingDir)
- return WorkingDir.getError();
-
- return llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
-}
-
-std::error_code FileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- return errc::operation_not_permitted;
-}
-
-bool FileSystem::exists(const Twine &Path) {
- auto Status = status(Path);
- return Status && Status->exists();
-}
-
-#ifndef NDEBUG
-static bool isTraversalComponent(StringRef Component) {
- return Component.equals("..") || Component.equals(".");
-}
-
-static bool pathHasTraversal(StringRef Path) {
- using namespace llvm::sys;
-
- for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
- if (isTraversalComponent(Comp))
- return true;
- return false;
-}
-#endif
-
-//===-----------------------------------------------------------------------===/
-// RealFileSystem implementation
-//===-----------------------------------------------------------------------===/
-
-namespace {
-
-/// Wrapper around a raw file descriptor.
-class RealFile : public File {
- friend class RealFileSystem;
-
- int FD;
- Status S;
- std::string RealName;
-
- RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
- : FD(FD), S(NewName, {}, {}, {}, {}, {},
- llvm::sys::fs::file_type::status_error, {}),
- RealName(NewRealPathName.str()) {
- assert(FD >= 0 && "Invalid or inactive file descriptor");
- }
-
-public:
- ~RealFile() override;
-
- ErrorOr<Status> status() override;
- ErrorOr<std::string> getName() override;
- ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
- int64_t FileSize,
- bool RequiresNullTerminator,
- bool IsVolatile) override;
- std::error_code close() override;
-};
-
-} // namespace
-
-RealFile::~RealFile() { close(); }
-
-ErrorOr<Status> RealFile::status() {
- assert(FD != -1 && "cannot stat closed file");
- if (!S.isStatusKnown()) {
- file_status RealStatus;
- if (std::error_code EC = sys::fs::status(FD, RealStatus))
- return EC;
- S = Status::copyWithNewName(RealStatus, S.getName());
- }
- return S;
-}
-
-ErrorOr<std::string> RealFile::getName() {
- return RealName.empty() ? S.getName().str() : RealName;
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-RealFile::getBuffer(const Twine &Name, int64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatile) {
- assert(FD != -1 && "cannot get buffer for closed file");
- return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
- IsVolatile);
-}
-
-std::error_code RealFile::close() {
- std::error_code EC = sys::Process::SafelyCloseFileDescriptor(FD);
- FD = -1;
- return EC;
-}
-
-namespace {
-
-/// The file system according to your operating system.
-class RealFileSystem : public FileSystem {
-public:
- ErrorOr<Status> status(const Twine &Path) override;
- ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
- directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
-
- llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
- std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
- std::error_code getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const override;
-};
-
-} // namespace
-
-ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
- sys::fs::file_status RealStatus;
- if (std::error_code EC = sys::fs::status(Path, RealStatus))
- return EC;
- return Status::copyWithNewName(RealStatus, Path.str());
-}
-
-ErrorOr<std::unique_ptr<File>>
-RealFileSystem::openFileForRead(const Twine &Name) {
- int FD;
- SmallString<256> RealName;
- if (std::error_code EC =
- sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName))
- return EC;
- return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str()));
-}
-
-llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
- SmallString<256> Dir;
- if (std::error_code EC = llvm::sys::fs::current_path(Dir))
- return EC;
- return Dir.str().str();
-}
-
-std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
- // FIXME: chdir is thread hostile; on the other hand, creating the same
- // behavior as chdir is complex: chdir resolves the path once, thus
- // guaranteeing that all subsequent relative path operations work
- // on the same path the original chdir resulted in. This makes a
- // difference for example on network filesystems, where symlinks might be
- // switched during runtime of the tool. Fixing this depends on having a
- // file system abstraction that allows openat() style interactions.
- return llvm::sys::fs::set_current_path(Path);
-}
-
-std::error_code
-RealFileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- return llvm::sys::fs::real_path(Path, Output);
-}
-
-IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
- static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem();
- return FS;
-}
-
-namespace {
-
-class RealFSDirIter : public clang::vfs::detail::DirIterImpl {
- llvm::sys::fs::directory_iterator Iter;
-
-public:
- RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
- if (Iter != llvm::sys::fs::directory_iterator()) {
- llvm::sys::fs::file_status S;
- std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
- CurrentEntry = Status::copyWithNewName(S, Iter->path());
- if (!EC)
- EC = ErrorCode;
- }
- }
-
- std::error_code increment() override {
- std::error_code EC;
- Iter.increment(EC);
- if (Iter == llvm::sys::fs::directory_iterator()) {
- CurrentEntry = Status();
- } else {
- llvm::sys::fs::file_status S;
- std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
- CurrentEntry = Status::copyWithNewName(S, Iter->path());
- if (!EC)
- EC = ErrorCode;
- }
- return EC;
- }
-};
-
-} // namespace
-
-directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
- std::error_code &EC) {
- return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC));
-}
-
-//===-----------------------------------------------------------------------===/
-// OverlayFileSystem implementation
-//===-----------------------------------------------------------------------===/
-
-OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
- FSList.push_back(std::move(BaseFS));
-}
-
-void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
- FSList.push_back(FS);
- // Synchronize added file systems by duplicating the working directory from
- // the first one in the list.
- FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
-}
-
-ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) {
- // FIXME: handle symlinks that cross file systems
- for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
- ErrorOr<Status> Status = (*I)->status(Path);
- if (Status || Status.getError() != llvm::errc::no_such_file_or_directory)
- return Status;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-ErrorOr<std::unique_ptr<File>>
-OverlayFileSystem::openFileForRead(const llvm::Twine &Path) {
- // FIXME: handle symlinks that cross file systems
- for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
- auto Result = (*I)->openFileForRead(Path);
- if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
- return Result;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-llvm::ErrorOr<std::string>
-OverlayFileSystem::getCurrentWorkingDirectory() const {
- // All file systems are synchronized, just take the first working directory.
- return FSList.front()->getCurrentWorkingDirectory();
-}
-
-std::error_code
-OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
- for (auto &FS : FSList)
- if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
- return EC;
- return {};
-}
-
-std::error_code
-OverlayFileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- for (auto &FS : FSList)
- if (FS->exists(Path))
- return FS->getRealPath(Path, Output);
- return errc::no_such_file_or_directory;
-}
-
-clang::vfs::detail::DirIterImpl::~DirIterImpl() = default;
-
-namespace {
-
-class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
- OverlayFileSystem &Overlays;
- std::string Path;
- OverlayFileSystem::iterator CurrentFS;
- directory_iterator CurrentDirIter;
- llvm::StringSet<> SeenNames;
-
- std::error_code incrementFS() {
- assert(CurrentFS != Overlays.overlays_end() && "incrementing past end");
- ++CurrentFS;
- for (auto E = Overlays.overlays_end(); CurrentFS != E; ++CurrentFS) {
- std::error_code EC;
- CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
- if (EC && EC != errc::no_such_file_or_directory)
- return EC;
- if (CurrentDirIter != directory_iterator())
- break; // found
- }
- return {};
- }
-
- std::error_code incrementDirIter(bool IsFirstTime) {
- assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
- "incrementing past end");
- std::error_code EC;
- if (!IsFirstTime)
- CurrentDirIter.increment(EC);
- if (!EC && CurrentDirIter == directory_iterator())
- EC = incrementFS();
- return EC;
- }
-
- std::error_code incrementImpl(bool IsFirstTime) {
- while (true) {
- std::error_code EC = incrementDirIter(IsFirstTime);
- if (EC || CurrentDirIter == directory_iterator()) {
- CurrentEntry = Status();
- return EC;
- }
- CurrentEntry = *CurrentDirIter;
- StringRef Name = llvm::sys::path::filename(CurrentEntry.getName());
- if (SeenNames.insert(Name).second)
- return EC; // name not seen before
- }
- llvm_unreachable("returned above");
- }
-
-public:
- OverlayFSDirIterImpl(const Twine &Path, OverlayFileSystem &FS,
- std::error_code &EC)
- : Overlays(FS), Path(Path.str()), CurrentFS(Overlays.overlays_begin()) {
- CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
- EC = incrementImpl(true);
- }
-
- std::error_code increment() override { return incrementImpl(false); }
-};
-
-} // namespace
-
-directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
- std::error_code &EC) {
- return directory_iterator(
- std::make_shared<OverlayFSDirIterImpl>(Dir, *this, EC));
-}
-
-namespace clang {
-namespace vfs {
-
-namespace detail {
-
-enum InMemoryNodeKind { IME_File, IME_Directory };
-
-/// The in memory file system is a tree of Nodes. Every node can either be a
-/// file or a directory.
-class InMemoryNode {
- Status Stat;
- InMemoryNodeKind Kind;
-
-public:
- InMemoryNode(Status Stat, InMemoryNodeKind Kind)
- : Stat(std::move(Stat)), Kind(Kind) {}
- virtual ~InMemoryNode() = default;
-
- const Status &getStatus() const { return Stat; }
- InMemoryNodeKind getKind() const { return Kind; }
- virtual std::string toString(unsigned Indent) const = 0;
-};
-
-namespace {
-
-class InMemoryFile : public InMemoryNode {
- std::unique_ptr<llvm::MemoryBuffer> Buffer;
-
-public:
- InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
- : InMemoryNode(std::move(Stat), IME_File), Buffer(std::move(Buffer)) {}
-
- llvm::MemoryBuffer *getBuffer() { return Buffer.get(); }
-
- std::string toString(unsigned Indent) const override {
- return (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
- }
-
- static bool classof(const InMemoryNode *N) {
- return N->getKind() == IME_File;
- }
-};
-
-/// Adapt a InMemoryFile for VFS' File interface.
-class InMemoryFileAdaptor : public File {
- InMemoryFile &Node;
-
-public:
- explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
-
- llvm::ErrorOr<Status> status() override { return Node.getStatus(); }
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
- bool IsVolatile) override {
- llvm::MemoryBuffer *Buf = Node.getBuffer();
- return llvm::MemoryBuffer::getMemBuffer(
- Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
- }
-
- std::error_code close() override { return {}; }
-};
-
-} // namespace
-
-class InMemoryDirectory : public InMemoryNode {
- std::map<std::string, std::unique_ptr<InMemoryNode>> Entries;
-
-public:
- InMemoryDirectory(Status Stat)
- : InMemoryNode(std::move(Stat), IME_Directory) {}
-
- InMemoryNode *getChild(StringRef Name) {
- auto I = Entries.find(Name);
- if (I != Entries.end())
- return I->second.get();
- return nullptr;
- }
-
- InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
- return Entries.insert(make_pair(Name, std::move(Child)))
- .first->second.get();
- }
-
- using const_iterator = decltype(Entries)::const_iterator;
-
- const_iterator begin() const { return Entries.begin(); }
- const_iterator end() const { return Entries.end(); }
-
- std::string toString(unsigned Indent) const override {
- std::string Result =
- (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
- for (const auto &Entry : Entries)
- Result += Entry.second->toString(Indent + 2);
- return Result;
- }
-
- static bool classof(const InMemoryNode *N) {
- return N->getKind() == IME_Directory;
- }
-};
-
-} // namespace detail
-
-InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
- : Root(new detail::InMemoryDirectory(
- Status("", getNextVirtualUniqueID(), llvm::sys::TimePoint<>(), 0, 0,
- 0, llvm::sys::fs::file_type::directory_file,
- llvm::sys::fs::perms::all_all))),
- UseNormalizedPaths(UseNormalizedPaths) {}
-
-InMemoryFileSystem::~InMemoryFileSystem() = default;
-
-std::string InMemoryFileSystem::toString() const {
- return Root->toString(/*Indent=*/0);
-}
-
-bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- Optional<uint32_t> User,
- Optional<uint32_t> Group,
- Optional<llvm::sys::fs::file_type> Type,
- Optional<llvm::sys::fs::perms> Perms) {
- SmallString<128> Path;
- P.toVector(Path);
-
- // Fix up relative paths. This just prepends the current working directory.
- std::error_code EC = makeAbsolute(Path);
- assert(!EC);
- (void)EC;
-
- if (useNormalizedPaths())
- llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
-
- if (Path.empty())
- return false;
-
- detail::InMemoryDirectory *Dir = Root.get();
- auto I = llvm::sys::path::begin(Path), E = sys::path::end(Path);
- const auto ResolvedUser = User.getValueOr(0);
- const auto ResolvedGroup = Group.getValueOr(0);
- const auto ResolvedType = Type.getValueOr(sys::fs::file_type::regular_file);
- const auto ResolvedPerms = Perms.getValueOr(sys::fs::all_all);
- // Any intermediate directories we create should be accessible by
- // the owner, even if Perms says otherwise for the final path.
- const auto NewDirectoryPerms = ResolvedPerms | sys::fs::owner_all;
- while (true) {
- StringRef Name = *I;
- detail::InMemoryNode *Node = Dir->getChild(Name);
- ++I;
- if (!Node) {
- if (I == E) {
- // End of the path, create a new file or directory.
- Status Stat(P.str(), getNextVirtualUniqueID(),
- llvm::sys::toTimePoint(ModificationTime), ResolvedUser,
- ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
- ResolvedPerms);
- std::unique_ptr<detail::InMemoryNode> Child;
- if (ResolvedType == sys::fs::file_type::directory_file) {
- Child.reset(new detail::InMemoryDirectory(std::move(Stat)));
- } else {
- Child.reset(new detail::InMemoryFile(std::move(Stat),
- std::move(Buffer)));
- }
- Dir->addChild(Name, std::move(Child));
- return true;
- }
-
- // Create a new directory. Use the path up to here.
- Status Stat(
- StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
- getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime),
- ResolvedUser, ResolvedGroup, Buffer->getBufferSize(),
- sys::fs::file_type::directory_file, NewDirectoryPerms);
- Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
- Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
- continue;
- }
-
- if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
- Dir = NewDir;
- } else {
- assert(isa<detail::InMemoryFile>(Node) &&
- "Must be either file or directory!");
-
- // Trying to insert a directory in place of a file.
- if (I != E)
- return false;
-
- // Return false only if the new file is different from the existing one.
- return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
- Buffer->getBuffer();
- }
- }
-}
-
-bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
- llvm::MemoryBuffer *Buffer,
- Optional<uint32_t> User,
- Optional<uint32_t> Group,
- Optional<llvm::sys::fs::file_type> Type,
- Optional<llvm::sys::fs::perms> Perms) {
- return addFile(P, ModificationTime,
- llvm::MemoryBuffer::getMemBuffer(
- Buffer->getBuffer(), Buffer->getBufferIdentifier()),
- std::move(User), std::move(Group), std::move(Type),
- std::move(Perms));
-}
-
-static ErrorOr<detail::InMemoryNode *>
-lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
- const Twine &P) {
- SmallString<128> Path;
- P.toVector(Path);
-
- // Fix up relative paths. This just prepends the current working directory.
- std::error_code EC = FS.makeAbsolute(Path);
- assert(!EC);
- (void)EC;
-
- if (FS.useNormalizedPaths())
- llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
-
- if (Path.empty())
- return Dir;
-
- auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
- while (true) {
- detail::InMemoryNode *Node = Dir->getChild(*I);
- ++I;
- if (!Node)
- return errc::no_such_file_or_directory;
-
- // Return the file if it's at the end of the path.
- if (auto File = dyn_cast<detail::InMemoryFile>(Node)) {
- if (I == E)
- return File;
- return errc::no_such_file_or_directory;
- }
-
- // Traverse directories.
- Dir = cast<detail::InMemoryDirectory>(Node);
- if (I == E)
- return Dir;
- }
-}
-
-llvm::ErrorOr<Status> InMemoryFileSystem::status(const Twine &Path) {
- auto Node = lookupInMemoryNode(*this, Root.get(), Path);
- if (Node)
- return (*Node)->getStatus();
- return Node.getError();
-}
-
-llvm::ErrorOr<std::unique_ptr<File>>
-InMemoryFileSystem::openFileForRead(const Twine &Path) {
- auto Node = lookupInMemoryNode(*this, Root.get(), Path);
- if (!Node)
- return Node.getError();
-
- // When we have a file provide a heap-allocated wrapper for the memory buffer
- // to match the ownership semantics for File.
- if (auto *F = dyn_cast<detail::InMemoryFile>(*Node))
- return std::unique_ptr<File>(new detail::InMemoryFileAdaptor(*F));
-
- // FIXME: errc::not_a_file?
- return make_error_code(llvm::errc::invalid_argument);
-}
-
-namespace {
-
-/// Adaptor from InMemoryDir::iterator to directory_iterator.
-class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
- detail::InMemoryDirectory::const_iterator I;
- detail::InMemoryDirectory::const_iterator E;
-
-public:
- InMemoryDirIterator() = default;
-
- explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
- : I(Dir.begin()), E(Dir.end()) {
- if (I != E)
- CurrentEntry = I->second->getStatus();
- }
-
- std::error_code increment() override {
- ++I;
- // When we're at the end, make CurrentEntry invalid and DirIterImpl will do
- // the rest.
- CurrentEntry = I != E ? I->second->getStatus() : Status();
- return {};
- }
-};
-
-} // namespace
-
-directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
- std::error_code &EC) {
- auto Node = lookupInMemoryNode(*this, Root.get(), Dir);
- if (!Node) {
- EC = Node.getError();
- return directory_iterator(std::make_shared<InMemoryDirIterator>());
- }
-
- if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
- return directory_iterator(std::make_shared<InMemoryDirIterator>(*DirNode));
-
- EC = make_error_code(llvm::errc::not_a_directory);
- return directory_iterator(std::make_shared<InMemoryDirIterator>());
-}
-
-std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
- SmallString<128> Path;
- P.toVector(Path);
-
- // Fix up relative paths. This just prepends the current working directory.
- std::error_code EC = makeAbsolute(Path);
- assert(!EC);
- (void)EC;
-
- if (useNormalizedPaths())
- llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
-
- if (!Path.empty())
- WorkingDirectory = Path.str();
- return {};
-}
-
-std::error_code
-InMemoryFileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- auto CWD = getCurrentWorkingDirectory();
- if (!CWD || CWD->empty())
- return errc::operation_not_permitted;
- Path.toVector(Output);
- if (auto EC = makeAbsolute(Output))
- return EC;
- llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true);
- return {};
-}
-
-} // namespace vfs
-} // namespace clang
-
-//===-----------------------------------------------------------------------===/
-// RedirectingFileSystem implementation
-//===-----------------------------------------------------------------------===/
-
-namespace {
-
-enum EntryKind {
- EK_Directory,
- EK_File
-};
-
-/// A single file or directory in the VFS.
-class Entry {
- EntryKind Kind;
- std::string Name;
-
-public:
- Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
- virtual ~Entry() = default;
-
- StringRef getName() const { return Name; }
- EntryKind getKind() const { return Kind; }
-};
-
-class RedirectingDirectoryEntry : public Entry {
- std::vector<std::unique_ptr<Entry>> Contents;
- Status S;
-
-public:
- RedirectingDirectoryEntry(StringRef Name,
- std::vector<std::unique_ptr<Entry>> Contents,
- Status S)
- : Entry(EK_Directory, Name), Contents(std::move(Contents)),
- S(std::move(S)) {}
- RedirectingDirectoryEntry(StringRef Name, Status S)
- : Entry(EK_Directory, Name), S(std::move(S)) {}
-
- Status getStatus() { return S; }
-
- void addContent(std::unique_ptr<Entry> Content) {
- Contents.push_back(std::move(Content));
- }
-
- Entry *getLastContent() const { return Contents.back().get(); }
-
- using iterator = decltype(Contents)::iterator;
-
- iterator contents_begin() { return Contents.begin(); }
- iterator contents_end() { return Contents.end(); }
-
- static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
-};
-
-class RedirectingFileEntry : public Entry {
-public:
- enum NameKind {
- NK_NotSet,
- NK_External,
- NK_Virtual
- };
-
-private:
- std::string ExternalContentsPath;
- NameKind UseName;
-
-public:
- RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
- NameKind UseName)
- : Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
- UseName(UseName) {}
-
- StringRef getExternalContentsPath() const { return ExternalContentsPath; }
-
- /// whether to use the external path as the name for this file.
- bool useExternalName(bool GlobalUseExternalName) const {
- return UseName == NK_NotSet ? GlobalUseExternalName
- : (UseName == NK_External);
- }
-
- NameKind getUseName() const { return UseName; }
-
- static bool classof(const Entry *E) { return E->getKind() == EK_File; }
-};
-
-class RedirectingFileSystem;
-
-class VFSFromYamlDirIterImpl : public clang::vfs::detail::DirIterImpl {
- std::string Dir;
- RedirectingFileSystem &FS;
- RedirectingDirectoryEntry::iterator Current, End;
-
-public:
- VFSFromYamlDirIterImpl(const Twine &Path, RedirectingFileSystem &FS,
- RedirectingDirectoryEntry::iterator Begin,
- RedirectingDirectoryEntry::iterator End,
- std::error_code &EC);
-
- std::error_code increment() override;
-};
-
-/// A virtual file system parsed from a YAML file.
-///
-/// Currently, this class allows creating virtual directories and mapping
-/// virtual file paths to existing external files, available in \c ExternalFS.
-///
-/// The basic structure of the parsed file is:
-/// \verbatim
-/// {
-/// 'version': <version number>,
-/// <optional configuration>
-/// 'roots': [
-/// <directory entries>
-/// ]
-/// }
-/// \endverbatim
-///
-/// All configuration options are optional.
-/// 'case-sensitive': <boolean, default=true>
-/// 'use-external-names': <boolean, default=true>
-/// 'overlay-relative': <boolean, default=false>
-/// 'ignore-non-existent-contents': <boolean, default=true>
-///
-/// Virtual directories are represented as
-/// \verbatim
-/// {
-/// 'type': 'directory',
-/// 'name': <string>,
-/// 'contents': [ <file or directory entries> ]
-/// }
-/// \endverbatim
-///
-/// The default attributes for virtual directories are:
-/// \verbatim
-/// MTime = now() when created
-/// Perms = 0777
-/// User = Group = 0
-/// Size = 0
-/// UniqueID = unspecified unique value
-/// \endverbatim
-///
-/// Re-mapped files are represented as
-/// \verbatim
-/// {
-/// 'type': 'file',
-/// 'name': <string>,
-/// 'use-external-name': <boolean> # Optional
-/// 'external-contents': <path to external file>)
-/// }
-/// \endverbatim
-///
-/// and inherit their attributes from the external contents.
-///
-/// In both cases, the 'name' field may contain multiple path components (e.g.
-/// /path/to/file). However, any directory that contains more than one child
-/// must be uniquely represented by a directory entry.
-class RedirectingFileSystem : public vfs::FileSystem {
- friend class RedirectingFileSystemParser;
-
- /// The root(s) of the virtual file system.
- std::vector<std::unique_ptr<Entry>> Roots;
-
- /// The file system to use for external references.
- IntrusiveRefCntPtr<FileSystem> ExternalFS;
-
- /// If IsRelativeOverlay is set, this represents the directory
- /// path that should be prefixed to each 'external-contents' entry
- /// when reading from YAML files.
- std::string ExternalContentsPrefixDir;
-
- /// @name Configuration
- /// @{
-
- /// Whether to perform case-sensitive comparisons.
- ///
- /// Currently, case-insensitive matching only works correctly with ASCII.
- bool CaseSensitive = true;
-
- /// IsRelativeOverlay marks whether a IsExternalContentsPrefixDir path must
- /// be prefixed in every 'external-contents' when reading from YAML files.
- bool IsRelativeOverlay = false;
-
- /// Whether to use to use the value of 'external-contents' for the
- /// names of files. This global value is overridable on a per-file basis.
- bool UseExternalNames = true;
-
- /// Whether an invalid path obtained via 'external-contents' should
- /// cause iteration on the VFS to stop. If 'true', the VFS should ignore
- /// the entry and continue with the next. Allows YAML files to be shared
- /// across multiple compiler invocations regardless of prior existent
- /// paths in 'external-contents'. This global value is overridable on a
- /// per-file basis.
- bool IgnoreNonExistentContents = true;
- /// @}
-
- /// Virtual file paths and external files could be canonicalized without "..",
- /// "." and "./" in their paths. FIXME: some unittests currently fail on
- /// win32 when using remove_dots and remove_leading_dotslash on paths.
- bool UseCanonicalizedPaths =
-#ifdef _WIN32
- false;
-#else
- true;
-#endif
-
-private:
- RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
- : ExternalFS(std::move(ExternalFS)) {}
-
- /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
- /// recursing into the contents of \p From if it is a directory.
- ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start,
- sys::path::const_iterator End, Entry *From);
-
- /// Get the status of a given an \c Entry.
- ErrorOr<Status> status(const Twine &Path, Entry *E);
-
-public:
- /// Looks up \p Path in \c Roots.
- ErrorOr<Entry *> lookupPath(const Twine &Path);
-
- /// Parses \p Buffer, which is expected to be in YAML format and
- /// returns a virtual file system representing its contents.
- static RedirectingFileSystem *
- create(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
- void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
-
- ErrorOr<Status> status(const Twine &Path) override;
- ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
-
- llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
- return ExternalFS->getCurrentWorkingDirectory();
- }
-
- std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
- return ExternalFS->setCurrentWorkingDirectory(Path);
- }
-
- directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override{
- ErrorOr<Entry *> E = lookupPath(Dir);
- if (!E) {
- EC = E.getError();
- return {};
- }
- ErrorOr<Status> S = status(Dir, *E);
- if (!S) {
- EC = S.getError();
- return {};
- }
- if (!S->isDirectory()) {
- EC = std::error_code(static_cast<int>(errc::not_a_directory),
- std::system_category());
- return {};
- }
-
- auto *D = cast<RedirectingDirectoryEntry>(*E);
- return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir,
- *this, D->contents_begin(), D->contents_end(), EC));
- }
-
- void setExternalContentsPrefixDir(StringRef PrefixDir) {
- ExternalContentsPrefixDir = PrefixDir.str();
- }
-
- StringRef getExternalContentsPrefixDir() const {
- return ExternalContentsPrefixDir;
- }
-
- bool ignoreNonExistentContents() const {
- return IgnoreNonExistentContents;
- }
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void dump() const {
- for (const auto &Root : Roots)
- dumpEntry(Root.get());
- }
-
-LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const {
- StringRef Name = E->getName();
- for (int i = 0, e = NumSpaces; i < e; ++i)
- dbgs() << " ";
- dbgs() << "'" << Name.str().c_str() << "'" << "\n";
-
- if (E->getKind() == EK_Directory) {
- auto *DE = dyn_cast<RedirectingDirectoryEntry>(E);
- assert(DE && "Should be a directory");
-
- for (std::unique_ptr<Entry> &SubEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end()))
- dumpEntry(SubEntry.get(), NumSpaces+2);
- }
- }
-#endif
-};
-
-/// A helper class to hold the common YAML parsing state.
-class RedirectingFileSystemParser {
- yaml::Stream &Stream;
-
- void error(yaml::Node *N, const Twine &Msg) {
- Stream.printError(N, Msg);
- }
-
- // false on error
- bool parseScalarString(yaml::Node *N, StringRef &Result,
- SmallVectorImpl<char> &Storage) {
- const auto *S = dyn_cast<yaml::ScalarNode>(N);
-
- if (!S) {
- error(N, "expected string");
- return false;
- }
- Result = S->getValue(Storage);
- return true;
- }
-
- // false on error
- bool parseScalarBool(yaml::Node *N, bool &Result) {
- SmallString<5> Storage;
- StringRef Value;
- if (!parseScalarString(N, Value, Storage))
- return false;
-
- if (Value.equals_lower("true") || Value.equals_lower("on") ||
- Value.equals_lower("yes") || Value == "1") {
- Result = true;
- return true;
- } else if (Value.equals_lower("false") || Value.equals_lower("off") ||
- Value.equals_lower("no") || Value == "0") {
- Result = false;
- return true;
- }
-
- error(N, "expected boolean value");
- return false;
- }
-
- struct KeyStatus {
- bool Required;
- bool Seen = false;
-
- KeyStatus(bool Required = false) : Required(Required) {}
- };
-
- using KeyStatusPair = std::pair<StringRef, KeyStatus>;
-
- // false on error
- bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
- DenseMap<StringRef, KeyStatus> &Keys) {
- if (!Keys.count(Key)) {
- error(KeyNode, "unknown key");
- return false;
- }
- KeyStatus &S = Keys[Key];
- if (S.Seen) {
- error(KeyNode, Twine("duplicate key '") + Key + "'");
- return false;
- }
- S.Seen = true;
- return true;
- }
-
- // false on error
- bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
- for (const auto &I : Keys) {
- if (I.second.Required && !I.second.Seen) {
- error(Obj, Twine("missing key '") + I.first + "'");
- return false;
- }
- }
- return true;
- }
-
- Entry *lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
- Entry *ParentEntry = nullptr) {
- if (!ParentEntry) { // Look for a existent root
- for (const auto &Root : FS->Roots) {
- if (Name.equals(Root->getName())) {
- ParentEntry = Root.get();
- return ParentEntry;
- }
- }
- } else { // Advance to the next component
- auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
- for (std::unique_ptr<Entry> &Content :
- llvm::make_range(DE->contents_begin(), DE->contents_end())) {
- auto *DirContent = dyn_cast<RedirectingDirectoryEntry>(Content.get());
- if (DirContent && Name.equals(Content->getName()))
- return DirContent;
- }
- }
-
- // ... or create a new one
- std::unique_ptr<Entry> E = llvm::make_unique<RedirectingDirectoryEntry>(
- Name,
- Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
- 0, 0, 0, file_type::directory_file, sys::fs::all_all));
-
- if (!ParentEntry) { // Add a new root to the overlay
- FS->Roots.push_back(std::move(E));
- ParentEntry = FS->Roots.back().get();
- return ParentEntry;
- }
-
- auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
- DE->addContent(std::move(E));
- return DE->getLastContent();
- }
-
- void uniqueOverlayTree(RedirectingFileSystem *FS, Entry *SrcE,
- Entry *NewParentE = nullptr) {
- StringRef Name = SrcE->getName();
- switch (SrcE->getKind()) {
- case EK_Directory: {
- auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
- assert(DE && "Must be a directory");
- // Empty directories could be present in the YAML as a way to
- // describe a file for a current directory after some of its subdir
- // is parsed. This only leads to redundant walks, ignore it.
- if (!Name.empty())
- NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
- for (std::unique_ptr<Entry> &SubEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end()))
- uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
- break;
- }
- case EK_File: {
- auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
- assert(FE && "Must be a file");
- assert(NewParentE && "Parent entry must exist");
- auto *DE = dyn_cast<RedirectingDirectoryEntry>(NewParentE);
- DE->addContent(llvm::make_unique<RedirectingFileEntry>(
- Name, FE->getExternalContentsPath(), FE->getUseName()));
- break;
- }
- }
- }
-
- std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) {
- auto *M = dyn_cast<yaml::MappingNode>(N);
- if (!M) {
- error(N, "expected mapping node for file or directory entry");
- return nullptr;
- }
-
- KeyStatusPair Fields[] = {
- KeyStatusPair("name", true),
- KeyStatusPair("type", true),
- KeyStatusPair("contents", false),
- KeyStatusPair("external-contents", false),
- KeyStatusPair("use-external-name", false),
- };
-
- DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
-
- bool HasContents = false; // external or otherwise
- std::vector<std::unique_ptr<Entry>> EntryArrayContents;
- std::string ExternalContentsPath;
- std::string Name;
- auto UseExternalName = RedirectingFileEntry::NK_NotSet;
- EntryKind Kind;
-
- for (auto &I : *M) {
- StringRef Key;
- // Reuse the buffer for key and value, since we don't look at key after
- // parsing value.
- SmallString<256> Buffer;
- if (!parseScalarString(I.getKey(), Key, Buffer))
- return nullptr;
-
- if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
- return nullptr;
-
- StringRef Value;
- if (Key == "name") {
- if (!parseScalarString(I.getValue(), Value, Buffer))
- return nullptr;
-
- if (FS->UseCanonicalizedPaths) {
- SmallString<256> Path(Value);
- // Guarantee that old YAML files containing paths with ".." and "."
- // are properly canonicalized before read into the VFS.
- Path = sys::path::remove_leading_dotslash(Path);
- sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
- Name = Path.str();
- } else {
- Name = Value;
- }
- } else if (Key == "type") {
- if (!parseScalarString(I.getValue(), Value, Buffer))
- return nullptr;
- if (Value == "file")
- Kind = EK_File;
- else if (Value == "directory")
- Kind = EK_Directory;
- else {
- error(I.getValue(), "unknown value for 'type'");
- return nullptr;
- }
- } else if (Key == "contents") {
- if (HasContents) {
- error(I.getKey(),
- "entry already has 'contents' or 'external-contents'");
- return nullptr;
- }
- HasContents = true;
- auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
- if (!Contents) {
- // FIXME: this is only for directories, what about files?
- error(I.getValue(), "expected array");
- return nullptr;
- }
-
- for (auto &I : *Contents) {
- if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
- EntryArrayContents.push_back(std::move(E));
- else
- return nullptr;
- }
- } else if (Key == "external-contents") {
- if (HasContents) {
- error(I.getKey(),
- "entry already has 'contents' or 'external-contents'");
- return nullptr;
- }
- HasContents = true;
- if (!parseScalarString(I.getValue(), Value, Buffer))
- return nullptr;
-
- SmallString<256> FullPath;
- if (FS->IsRelativeOverlay) {
- FullPath = FS->getExternalContentsPrefixDir();
- assert(!FullPath.empty() &&
- "External contents prefix directory must exist");
- llvm::sys::path::append(FullPath, Value);
- } else {
- FullPath = Value;
- }
-
- if (FS->UseCanonicalizedPaths) {
- // Guarantee that old YAML files containing paths with ".." and "."
- // are properly canonicalized before read into the VFS.
- FullPath = sys::path::remove_leading_dotslash(FullPath);
- sys::path::remove_dots(FullPath, /*remove_dot_dot=*/true);
- }
- ExternalContentsPath = FullPath.str();
- } else if (Key == "use-external-name") {
- bool Val;
- if (!parseScalarBool(I.getValue(), Val))
- return nullptr;
- UseExternalName = Val ? RedirectingFileEntry::NK_External
- : RedirectingFileEntry::NK_Virtual;
- } else {
- llvm_unreachable("key missing from Keys");
- }
- }
-
- if (Stream.failed())
- return nullptr;
-
- // check for missing keys
- if (!HasContents) {
- error(N, "missing key 'contents' or 'external-contents'");
- return nullptr;
- }
- if (!checkMissingKeys(N, Keys))
- return nullptr;
-
- // check invalid configuration
- if (Kind == EK_Directory &&
- UseExternalName != RedirectingFileEntry::NK_NotSet) {
- error(N, "'use-external-name' is not supported for directories");
- return nullptr;
- }
-
- // Remove trailing slash(es), being careful not to remove the root path
- StringRef Trimmed(Name);
- size_t RootPathLen = sys::path::root_path(Trimmed).size();
- while (Trimmed.size() > RootPathLen &&
- sys::path::is_separator(Trimmed.back()))
- Trimmed = Trimmed.slice(0, Trimmed.size()-1);
- // Get the last component
- StringRef LastComponent = sys::path::filename(Trimmed);
-
- std::unique_ptr<Entry> Result;
- switch (Kind) {
- case EK_File:
- Result = llvm::make_unique<RedirectingFileEntry>(
- LastComponent, std::move(ExternalContentsPath), UseExternalName);
- break;
- case EK_Directory:
- Result = llvm::make_unique<RedirectingDirectoryEntry>(
- LastComponent, std::move(EntryArrayContents),
- Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
- 0, 0, 0, file_type::directory_file, sys::fs::all_all));
- break;
- }
-
- StringRef Parent = sys::path::parent_path(Trimmed);
- if (Parent.empty())
- return Result;
-
- // if 'name' contains multiple components, create implicit directory entries
- for (sys::path::reverse_iterator I = sys::path::rbegin(Parent),
- E = sys::path::rend(Parent);
- I != E; ++I) {
- std::vector<std::unique_ptr<Entry>> Entries;
- Entries.push_back(std::move(Result));
- Result = llvm::make_unique<RedirectingDirectoryEntry>(
- *I, std::move(Entries),
- Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
- 0, 0, 0, file_type::directory_file, sys::fs::all_all));
- }
- return Result;
- }
-
-public:
- RedirectingFileSystemParser(yaml::Stream &S) : Stream(S) {}
-
- // false on error
- bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
- auto *Top = dyn_cast<yaml::MappingNode>(Root);
- if (!Top) {
- error(Root, "expected mapping node");
- return false;
- }
-
- KeyStatusPair Fields[] = {
- KeyStatusPair("version", true),
- KeyStatusPair("case-sensitive", false),
- KeyStatusPair("use-external-names", false),
- KeyStatusPair("overlay-relative", false),
- KeyStatusPair("ignore-non-existent-contents", false),
- KeyStatusPair("roots", true),
- };
-
- DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
- std::vector<std::unique_ptr<Entry>> RootEntries;
-
- // Parse configuration and 'roots'
- for (auto &I : *Top) {
- SmallString<10> KeyBuffer;
- StringRef Key;
- if (!parseScalarString(I.getKey(), Key, KeyBuffer))
- return false;
-
- if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
- return false;
-
- if (Key == "roots") {
- auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
- if (!Roots) {
- error(I.getValue(), "expected array");
- return false;
- }
-
- for (auto &I : *Roots) {
- if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
- RootEntries.push_back(std::move(E));
- else
- return false;
- }
- } else if (Key == "version") {
- StringRef VersionString;
- SmallString<4> Storage;
- if (!parseScalarString(I.getValue(), VersionString, Storage))
- return false;
- int Version;
- if (VersionString.getAsInteger<int>(10, Version)) {
- error(I.getValue(), "expected integer");
- return false;
- }
- if (Version < 0) {
- error(I.getValue(), "invalid version number");
- return false;
- }
- if (Version != 0) {
- error(I.getValue(), "version mismatch, expected 0");
- return false;
- }
- } else if (Key == "case-sensitive") {
- if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
- return false;
- } else if (Key == "overlay-relative") {
- if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
- return false;
- } else if (Key == "use-external-names") {
- if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
- return false;
- } else if (Key == "ignore-non-existent-contents") {
- if (!parseScalarBool(I.getValue(), FS->IgnoreNonExistentContents))
- return false;
- } else {
- llvm_unreachable("key missing from Keys");
- }
- }
-
- if (Stream.failed())
- return false;
-
- if (!checkMissingKeys(Top, Keys))
- return false;
-
- // Now that we sucessefully parsed the YAML file, canonicalize the internal
- // representation to a proper directory tree so that we can search faster
- // inside the VFS.
- for (auto &E : RootEntries)
- uniqueOverlayTree(FS, E.get());
-
- return true;
- }
-};
-
-} // namespace
-
-RedirectingFileSystem *
-RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- StringRef YAMLFilePath, void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS) {
- SourceMgr SM;
- yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
-
- SM.setDiagHandler(DiagHandler, DiagContext);
- yaml::document_iterator DI = Stream.begin();
- yaml::Node *Root = DI->getRoot();
- if (DI == Stream.end() || !Root) {
- SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node");
- return nullptr;
- }
-
- RedirectingFileSystemParser P(Stream);
-
- std::unique_ptr<RedirectingFileSystem> FS(
- new RedirectingFileSystem(std::move(ExternalFS)));
-
- if (!YAMLFilePath.empty()) {
- // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
- // to each 'external-contents' path.
- //
- // Example:
- // -ivfsoverlay dummy.cache/vfs/vfs.yaml
- // yields:
- // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
- //
- SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
- std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
- assert(!EC && "Overlay dir final path must be absolute");
- (void)EC;
- FS->setExternalContentsPrefixDir(OverlayAbsDir);
- }
-
- if (!P.parse(Root, FS.get()))
- return nullptr;
-
- return FS.release();
-}
-
-ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
- SmallString<256> Path;
- Path_.toVector(Path);
-
- // Handle relative paths
- if (std::error_code EC = makeAbsolute(Path))
- return EC;
-
- // Canonicalize path by removing ".", "..", "./", etc components. This is
- // a VFS request, do bot bother about symlinks in the path components
- // but canonicalize in order to perform the correct entry search.
- if (UseCanonicalizedPaths) {
- Path = sys::path::remove_leading_dotslash(Path);
- sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
- }
-
- if (Path.empty())
- return make_error_code(llvm::errc::invalid_argument);
-
- sys::path::const_iterator Start = sys::path::begin(Path);
- sys::path::const_iterator End = sys::path::end(Path);
- for (const auto &Root : Roots) {
- ErrorOr<Entry *> Result = lookupPath(Start, End, Root.get());
- if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
- return Result;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-ErrorOr<Entry *>
-RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
- sys::path::const_iterator End, Entry *From) {
-#ifndef _WIN32
- assert(!isTraversalComponent(*Start) &&
- !isTraversalComponent(From->getName()) &&
- "Paths should not contain traversal components");
-#else
- // FIXME: this is here to support windows, remove it once canonicalized
- // paths become globally default.
- if (Start->equals("."))
- ++Start;
-#endif
-
- StringRef FromName = From->getName();
-
- // Forward the search to the next component in case this is an empty one.
- if (!FromName.empty()) {
- if (CaseSensitive ? !Start->equals(FromName)
- : !Start->equals_lower(FromName))
- // failure to match
- return make_error_code(llvm::errc::no_such_file_or_directory);
-
- ++Start;
-
- if (Start == End) {
- // Match!
- return From;
- }
- }
-
- auto *DE = dyn_cast<RedirectingDirectoryEntry>(From);
- if (!DE)
- return make_error_code(llvm::errc::not_a_directory);
-
- for (const std::unique_ptr<Entry> &DirEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end())) {
- ErrorOr<Entry *> Result = lookupPath(Start, End, DirEntry.get());
- if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
- return Result;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames,
- Status ExternalStatus) {
- Status S = ExternalStatus;
- if (!UseExternalNames)
- S = Status::copyWithNewName(S, Path.str());
- S.IsVFSMapped = true;
- return S;
-}
-
-ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path, Entry *E) {
- assert(E != nullptr);
- if (auto *F = dyn_cast<RedirectingFileEntry>(E)) {
- ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
- assert(!S || S->getName() == F->getExternalContentsPath());
- if (S)
- return getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
- *S);
- return S;
- } else { // directory
- auto *DE = cast<RedirectingDirectoryEntry>(E);
- return Status::copyWithNewName(DE->getStatus(), Path.str());
- }
-}
-
-ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
- ErrorOr<Entry *> Result = lookupPath(Path);
- if (!Result)
- return Result.getError();
- return status(Path, *Result);
-}
-
-namespace {
-
-/// Provide a file wrapper with an overriden status.
-class FileWithFixedStatus : public File {
- std::unique_ptr<File> InnerFile;
- Status S;
-
-public:
- FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
- : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
-
- ErrorOr<Status> status() override { return S; }
- ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
-
- getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
- bool IsVolatile) override {
- return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
- IsVolatile);
- }
-
- std::error_code close() override { return InnerFile->close(); }
-};
-
-} // namespace
-
-ErrorOr<std::unique_ptr<File>>
-RedirectingFileSystem::openFileForRead(const Twine &Path) {
- ErrorOr<Entry *> E = lookupPath(Path);
- if (!E)
- return E.getError();
-
- auto *F = dyn_cast<RedirectingFileEntry>(*E);
- if (!F) // FIXME: errc::not_a_file?
- return make_error_code(llvm::errc::invalid_argument);
-
- auto Result = ExternalFS->openFileForRead(F->getExternalContentsPath());
- if (!Result)
- return Result;
-
- auto ExternalStatus = (*Result)->status();
- if (!ExternalStatus)
- return ExternalStatus.getError();
-
- // FIXME: Update the status with the name and VFSMapped.
- Status S = getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
- *ExternalStatus);
- return std::unique_ptr<File>(
- llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
-}
-
-IntrusiveRefCntPtr<FileSystem>
-vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- StringRef YAMLFilePath,
- void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS) {
- return RedirectingFileSystem::create(std::move(Buffer), DiagHandler,
- YAMLFilePath, DiagContext,
- std::move(ExternalFS));
-}
-
-static void getVFSEntries(Entry *SrcE, SmallVectorImpl<StringRef> &Path,
- SmallVectorImpl<YAMLVFSEntry> &Entries) {
- auto Kind = SrcE->getKind();
- if (Kind == EK_Directory) {
- auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
- assert(DE && "Must be a directory");
- for (std::unique_ptr<Entry> &SubEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end())) {
- Path.push_back(SubEntry->getName());
- getVFSEntries(SubEntry.get(), Path, Entries);
- Path.pop_back();
- }
- return;
- }
-
- assert(Kind == EK_File && "Must be a EK_File");
- auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
- assert(FE && "Must be a file");
- SmallString<128> VPath;
- for (auto &Comp : Path)
- llvm::sys::path::append(VPath, Comp);
- Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
-}
-
-void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- StringRef YAMLFilePath,
- SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
- void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS) {
- RedirectingFileSystem *VFS = RedirectingFileSystem::create(
- std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
- std::move(ExternalFS));
- ErrorOr<Entry *> RootE = VFS->lookupPath("/");
- if (!RootE)
- return;
- SmallVector<StringRef, 8> Components;
- Components.push_back("/");
- getVFSEntries(*RootE, Components, CollectedEntries);
-}
-
-UniqueID vfs::getNextVirtualUniqueID() {
- static std::atomic<unsigned> UID;
- unsigned ID = ++UID;
- // The following assumes that uint64_t max will never collide with a real
- // dev_t value from the OS.
- return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
-}
-
-void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
- assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
- assert(sys::path::is_absolute(RealPath) && "real path not absolute");
- assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
- Mappings.emplace_back(VirtualPath, RealPath);
-}
-
-namespace {
-
-class JSONWriter {
- llvm::raw_ostream &OS;
- SmallVector<StringRef, 16> DirStack;
-
- unsigned getDirIndent() { return 4 * DirStack.size(); }
- unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
- bool containedIn(StringRef Parent, StringRef Path);
- StringRef containedPart(StringRef Parent, StringRef Path);
- void startDirectory(StringRef Path);
- void endDirectory();
- void writeEntry(StringRef VPath, StringRef RPath);
-
-public:
- JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
-
- void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
- Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
- Optional<bool> IgnoreNonExistentContents, StringRef OverlayDir);
-};
-
-} // namespace
-
-bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
- using namespace llvm::sys;
-
- // Compare each path component.
- auto IParent = path::begin(Parent), EParent = path::end(Parent);
- for (auto IChild = path::begin(Path), EChild = path::end(Path);
- IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
- if (*IParent != *IChild)
- return false;
- }
- // Have we exhausted the parent path?
- return IParent == EParent;
-}
-
-StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
- assert(!Parent.empty());
- assert(containedIn(Parent, Path));
- return Path.slice(Parent.size() + 1, StringRef::npos);
-}
-
-void JSONWriter::startDirectory(StringRef Path) {
- StringRef Name =
- DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
- DirStack.push_back(Path);
- unsigned Indent = getDirIndent();
- OS.indent(Indent) << "{\n";
- OS.indent(Indent + 2) << "'type': 'directory',\n";
- OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n";
- OS.indent(Indent + 2) << "'contents': [\n";
-}
-
-void JSONWriter::endDirectory() {
- unsigned Indent = getDirIndent();
- OS.indent(Indent + 2) << "]\n";
- OS.indent(Indent) << "}";
-
- DirStack.pop_back();
-}
-
-void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
- unsigned Indent = getFileIndent();
- OS.indent(Indent) << "{\n";
- OS.indent(Indent + 2) << "'type': 'file',\n";
- OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n";
- OS.indent(Indent + 2) << "'external-contents': \""
- << llvm::yaml::escape(RPath) << "\"\n";
- OS.indent(Indent) << "}";
-}
-
-void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
- Optional<bool> UseExternalNames,
- Optional<bool> IsCaseSensitive,
- Optional<bool> IsOverlayRelative,
- Optional<bool> IgnoreNonExistentContents,
- StringRef OverlayDir) {
- using namespace llvm::sys;
-
- OS << "{\n"
- " 'version': 0,\n";
- if (IsCaseSensitive.hasValue())
- OS << " 'case-sensitive': '"
- << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
- if (UseExternalNames.hasValue())
- OS << " 'use-external-names': '"
- << (UseExternalNames.getValue() ? "true" : "false") << "',\n";
- bool UseOverlayRelative = false;
- if (IsOverlayRelative.hasValue()) {
- UseOverlayRelative = IsOverlayRelative.getValue();
- OS << " 'overlay-relative': '"
- << (UseOverlayRelative ? "true" : "false") << "',\n";
- }
- if (IgnoreNonExistentContents.hasValue())
- OS << " 'ignore-non-existent-contents': '"
- << (IgnoreNonExistentContents.getValue() ? "true" : "false") << "',\n";
- OS << " 'roots': [\n";
-
- if (!Entries.empty()) {
- const YAMLVFSEntry &Entry = Entries.front();
- startDirectory(path::parent_path(Entry.VPath));
-
- StringRef RPath = Entry.RPath;
- if (UseOverlayRelative) {
- unsigned OverlayDirLen = OverlayDir.size();
- assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
- "Overlay dir must be contained in RPath");
- RPath = RPath.slice(OverlayDirLen, RPath.size());
- }
-
- writeEntry(path::filename(Entry.VPath), RPath);
-
- for (const auto &Entry : Entries.slice(1)) {
- StringRef Dir = path::parent_path(Entry.VPath);
- if (Dir == DirStack.back())
- OS << ",\n";
- else {
- while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
- OS << "\n";
- endDirectory();
- }
- OS << ",\n";
- startDirectory(Dir);
- }
- StringRef RPath = Entry.RPath;
- if (UseOverlayRelative) {
- unsigned OverlayDirLen = OverlayDir.size();
- assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
- "Overlay dir must be contained in RPath");
- RPath = RPath.slice(OverlayDirLen, RPath.size());
- }
- writeEntry(path::filename(Entry.VPath), RPath);
- }
-
- while (!DirStack.empty()) {
- OS << "\n";
- endDirectory();
- }
- OS << "\n";
- }
-
- OS << " ]\n"
- << "}\n";
-}
-
-void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
- llvm::sort(Mappings.begin(), Mappings.end(),
- [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
- return LHS.VPath < RHS.VPath;
- });
-
- JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
- IsOverlayRelative, IgnoreNonExistentContents,
- OverlayDir);
-}
-
-VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
- const Twine &_Path, RedirectingFileSystem &FS,
- RedirectingDirectoryEntry::iterator Begin,
- RedirectingDirectoryEntry::iterator End, std::error_code &EC)
- : Dir(_Path.str()), FS(FS), Current(Begin), End(End) {
- while (Current != End) {
- SmallString<128> PathStr(Dir);
- llvm::sys::path::append(PathStr, (*Current)->getName());
- llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
- if (S) {
- CurrentEntry = *S;
- return;
- }
- // Skip entries which do not map to a reliable external content.
- if (FS.ignoreNonExistentContents() &&
- S.getError() == llvm::errc::no_such_file_or_directory) {
- ++Current;
- continue;
- } else {
- EC = S.getError();
- break;
- }
- }
-}
-
-std::error_code VFSFromYamlDirIterImpl::increment() {
- assert(Current != End && "cannot iterate past end");
- while (++Current != End) {
- SmallString<128> PathStr(Dir);
- llvm::sys::path::append(PathStr, (*Current)->getName());
- llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
- if (!S) {
- // Skip entries which do not map to a reliable external content.
- if (FS.ignoreNonExistentContents() &&
- S.getError() == llvm::errc::no_such_file_or_directory) {
- continue;
- } else {
- return S.getError();
- }
- }
- CurrentEntry = *S;
- break;
- }
-
- if (Current == End)
- CurrentEntry = Status();
- return {};
-}
-
-vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_,
- const Twine &Path,
- std::error_code &EC)
- : FS(&FS_) {
- directory_iterator I = FS->dir_begin(Path, EC);
- if (I != directory_iterator()) {
- State = std::make_shared<IterState>();
- State->push(I);
- }
-}
-
-vfs::recursive_directory_iterator &
-recursive_directory_iterator::increment(std::error_code &EC) {
- assert(FS && State && !State->empty() && "incrementing past end");
- assert(State->top()->isStatusKnown() && "non-canonical end iterator");
- vfs::directory_iterator End;
- if (State->top()->isDirectory()) {
- vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC);
- if (I != End) {
- State->push(I);
- return *this;
- }
- }
-
- while (!State->empty() && State->top().increment(EC) == End)
- State->pop();
-
- if (State->empty())
- State.reset(); // end iterator
-
- return *this;
-}
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 415bd9626220..b927acabac59 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/BackendUtil.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
@@ -37,6 +37,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -54,10 +55,13 @@
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
+#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
+#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
#include "llvm/Transforms/Utils/SymbolRewriter.h"
#include <memory>
@@ -235,11 +239,12 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Address);
bool UseAfterScope = CGOpts.SanitizeAddressUseAfterScope;
+ bool UseOdrIndicator = CGOpts.SanitizeAddressUseOdrIndicator;
bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts);
PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover,
UseAfterScope));
PM.add(createAddressSanitizerModulePass(/*CompileKernel*/ false, Recover,
- UseGlobalsGC));
+ UseGlobalsGC, UseOdrIndicator));
}
static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
@@ -247,7 +252,8 @@ static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
PM.add(createAddressSanitizerFunctionPass(
/*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false));
PM.add(createAddressSanitizerModulePass(
- /*CompileKernel*/ true, /*Recover*/ true));
+ /*CompileKernel*/ true, /*Recover*/ true, /*UseGlobalsGC*/ true,
+ /*UseOdrIndicator*/ false));
}
static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
@@ -265,14 +271,15 @@ static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
/*CompileKernel*/ true, /*Recover*/ true));
}
-static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
- legacy::PassManagerBase &PM) {
+static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM,
+ bool CompileKernel) {
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins;
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory);
- PM.add(createMemorySanitizerPass(TrackOrigins, Recover));
+ PM.add(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover, CompileKernel));
// MemorySanitizer inserts complex instrumentation that mostly follows
// the logic of the original code, but operates on "shadow" values.
@@ -287,9 +294,19 @@ static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
}
}
+static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ false);
+}
+
+static void addKernelMemorySanitizerPass(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ true);
+}
+
static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
- PM.add(createThreadSanitizerPass());
+ PM.add(createThreadSanitizerLegacyPassPass());
}
static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder,
@@ -368,6 +385,7 @@ static CodeGenOpt::Level getCGOptLevel(const CodeGenOptions &CodeGenOpts) {
static Optional<llvm::CodeModel::Model>
getCodeModel(const CodeGenOptions &CodeGenOpts) {
unsigned CodeModel = llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)
+ .Case("tiny", llvm::CodeModel::Tiny)
.Case("small", llvm::CodeModel::Small)
.Case("kernel", llvm::CodeModel::Kernel)
.Case("medium", llvm::CodeModel::Medium)
@@ -416,7 +434,7 @@ static void initTargetOptions(llvm::TargetOptions &Options,
switch (LangOpts.getDefaultFPContractMode()) {
case LangOptions::FPC_Off:
// Preserve any contraction performed by the front-end. (Strict performs
- // splitting of the muladd instrinsic in the backend.)
+ // splitting of the muladd intrinsic in the backend.)
Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
break;
case LangOptions::FPC_On:
@@ -456,7 +474,7 @@ static void initTargetOptions(llvm::TargetOptions &Options,
Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
Options.EmitAddrsig = CodeGenOpts.Addrsig;
- if (CodeGenOpts.EnableSplitDwarf)
+ if (CodeGenOpts.getSplitDwarfMode() != CodeGenOptions::NoFission)
Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
@@ -491,6 +509,8 @@ static Optional<GCOVOptions> getGCOVOptions(const CodeGenOptions &CodeGenOpts) {
Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum;
Options.NoRedZone = CodeGenOpts.DisableRedZone;
Options.FunctionNamesInData = !CodeGenOpts.CoverageNoFunctionNamesInData;
+ Options.Filter = CodeGenOpts.ProfileFilterFiles;
+ Options.Exclude = CodeGenOpts.ProfileExcludeFiles;
Options.ExitBlockBeforeBody = CodeGenOpts.CoverageExitBlockBeforeBody;
return Options;
}
@@ -613,6 +633,13 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
addMemorySanitizerPass);
}
+ if (LangOpts.Sanitize.has(SanitizerKind::KernelMemory)) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addKernelMemorySanitizerPass);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addKernelMemorySanitizerPass);
+ }
+
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addThreadSanitizerPass);
@@ -653,6 +680,11 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
InstrProfOptions Options;
Options.NoRedZone = CodeGenOpts.DisableRedZone;
Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput;
+
+ // TODO: Surface the option to emit atomic profile counter increments at
+ // the driver level.
+ Options.Atomic = LangOpts.Sanitize.has(SanitizerKind::Thread);
+
MPM.add(createInstrProfilingLegacyPass(Options));
}
if (CodeGenOpts.hasProfileIRInstr()) {
@@ -777,12 +809,14 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
break;
case Backend_EmitBC:
- if (CodeGenOpts.PrepareForThinLTO) {
+ if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {
if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
if (!ThinLinkOS)
return;
}
+ TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
+ CodeGenOpts.EnableSplitLTOUnit);
PerModulePasses.add(createWriteThinLTOBitcodePass(
*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
} else {
@@ -790,14 +824,18 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
// targets
bool EmitLTOSummary =
(CodeGenOpts.PrepareForLTO &&
+ !CodeGenOpts.DisableLLVMPasses &&
llvm::Triple(TheModule->getTargetTriple()).getVendor() !=
llvm::Triple::Apple);
- if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO"))
- TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
+ if (EmitLTOSummary) {
+ if (!TheModule->getModuleFlag("ThinLTO"))
+ TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
+ TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
+ CodeGenOpts.EnableSplitLTOUnit);
+ }
- PerModulePasses.add(
- createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
- EmitLTOSummary));
+ PerModulePasses.add(createBitcodeWriterPass(
+ *OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary));
}
break;
@@ -807,7 +845,8 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
break;
default:
- if (!CodeGenOpts.SplitDwarfFile.empty()) {
+ if (!CodeGenOpts.SplitDwarfFile.empty() &&
+ (CodeGenOpts.getSplitDwarfMode() == CodeGenOptions::SplitFileFission)) {
DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile);
if (!DwoOS)
return;
@@ -905,18 +944,21 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
PGOOpt = PGOOptions(CodeGenOpts.InstrProfileOutput.empty()
? DefaultProfileGenName
: CodeGenOpts.InstrProfileOutput,
- "", "", true, CodeGenOpts.DebugInfoForProfiling);
+ "", "", "", true,
+ CodeGenOpts.DebugInfoForProfiling);
else if (CodeGenOpts.hasProfileIRUse())
// -fprofile-use.
- PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "", false,
+ PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "",
+ CodeGenOpts.ProfileRemappingFile, false,
CodeGenOpts.DebugInfoForProfiling);
else if (!CodeGenOpts.SampleProfileFile.empty())
// -fprofile-sample-use
- PGOOpt = PGOOptions("", "", CodeGenOpts.SampleProfileFile, false,
+ PGOOpt = PGOOptions("", "", CodeGenOpts.SampleProfileFile,
+ CodeGenOpts.ProfileRemappingFile, false,
CodeGenOpts.DebugInfoForProfiling);
else if (CodeGenOpts.DebugInfoForProfiling)
// -fdebug-info-for-profiling
- PGOOpt = PGOOptions("", "", "", false, true);
+ PGOOpt = PGOOptions("", "", "", "", false, true);
PassBuilder PB(TM.get(), PGOOpt);
@@ -961,9 +1003,11 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass()));
- // Lastly, add a semantically necessary pass for LTO.
- if (IsLTO || IsThinLTO)
+ // Lastly, add semantically necessary passes for LTO.
+ if (IsLTO || IsThinLTO) {
+ MPM.addPass(CanonicalizeAliasesPass());
MPM.addPass(NameAnonGlobalPass());
+ }
} else {
// Map our optimization levels into one of the distinct levels used to
// configure the pipeline.
@@ -984,10 +1028,12 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
if (IsThinLTO) {
MPM = PB.buildThinLTOPreLinkDefaultPipeline(
Level, CodeGenOpts.DebugPassManager);
+ MPM.addPass(CanonicalizeAliasesPass());
MPM.addPass(NameAnonGlobalPass());
} else if (IsLTO) {
MPM = PB.buildLTOPreLinkDefaultPipeline(Level,
CodeGenOpts.DebugPassManager);
+ MPM.addPass(CanonicalizeAliasesPass());
MPM.addPass(NameAnonGlobalPass());
} else {
MPM = PB.buildPerModuleDefaultPipeline(Level,
@@ -1008,12 +1054,14 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
break;
case Backend_EmitBC:
- if (CodeGenOpts.PrepareForThinLTO) {
+ if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {
if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
if (!ThinLinkOS)
return;
}
+ TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
+ CodeGenOpts.EnableSplitLTOUnit);
MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os()
: nullptr));
} else {
@@ -1021,13 +1069,17 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
// targets
bool EmitLTOSummary =
(CodeGenOpts.PrepareForLTO &&
+ !CodeGenOpts.DisableLLVMPasses &&
llvm::Triple(TheModule->getTargetTriple()).getVendor() !=
llvm::Triple::Apple);
- if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO"))
- TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
-
- MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
- EmitLTOSummary));
+ if (EmitLTOSummary) {
+ if (!TheModule->getModuleFlag("ThinLTO"))
+ TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
+ TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
+ CodeGenOpts.EnableSplitLTOUnit);
+ }
+ MPM.addPass(
+ BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary));
}
break;
@@ -1104,6 +1156,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
const LangOptions &LOpts,
std::unique_ptr<raw_pwrite_stream> OS,
std::string SampleProfile,
+ std::string ProfileRemapping,
BackendAction Action) {
StringMap<DenseMap<GlobalValue::GUID, GlobalValueSummary *>>
ModuleToDefinedGVSummaries;
@@ -1121,15 +1174,14 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
continue;
auto GUID = GlobalList.first;
- assert(GlobalList.second.SummaryList.size() == 1 &&
- "Expected individual combined index to have one summary per GUID");
- auto &Summary = GlobalList.second.SummaryList[0];
- // Skip the summaries for the importing module. These are included to
- // e.g. record required linkage changes.
- if (Summary->modulePath() == M->getModuleIdentifier())
- continue;
- // Add an entry to provoke importing by thinBackend.
- ImportList[Summary->modulePath()].insert(GUID);
+ for (auto &Summary : GlobalList.second.SummaryList) {
+ // Skip the summaries for the importing module. These are included to
+ // e.g. record required linkage changes.
+ if (Summary->modulePath() == M->getModuleIdentifier())
+ continue;
+ // Add an entry to provoke importing by thinBackend.
+ ImportList[Summary->modulePath()].insert(GUID);
+ }
}
std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedImports;
@@ -1176,6 +1228,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
Conf.CGOptLevel = getCGOptLevel(CGOpts);
initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts);
Conf.SampleProfile = std::move(SampleProfile);
+ Conf.ProfileRemapping = std::move(ProfileRemapping);
Conf.UseNewPM = CGOpts.ExperimentalNewPassManager;
Conf.DebugPassManager = CGOpts.DebugPassManager;
Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness;
@@ -1242,7 +1295,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
if (!CombinedIndex->skipModuleByDistributedBackend()) {
runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts,
LOpts, std::move(OS), CGOpts.SampleProfileFile,
- Action);
+ CGOpts.ProfileRemappingFile, Action);
return;
}
// Distributed indexing detected that nothing from the module is needed
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index b34bcdc1fc38..24056a449def 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -18,7 +18,7 @@
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
@@ -765,11 +765,15 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy);
uint64_t Size = sizeChars.getQuantity();
unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth();
- bool UseLibcall = ((Ptr.getAlignment() % sizeChars) != 0 ||
- getContext().toBits(sizeChars) > MaxInlineWidthInBits);
- if (UseLibcall)
- CGM.getDiags().Report(E->getLocStart(), diag::warn_atomic_op_misaligned);
+ bool Oversized = getContext().toBits(sizeChars) > MaxInlineWidthInBits;
+ bool Misaligned = (Ptr.getAlignment() % sizeChars) != 0;
+ bool UseLibcall = Misaligned | Oversized;
+
+ if (UseLibcall) {
+ CGM.getDiags().Report(E->getBeginLoc(), diag::warn_atomic_op_misaligned)
+ << !Oversized;
+ }
llvm::Value *Order = EmitScalarExpr(E->getOrder());
llvm::Value *Scope =
@@ -923,6 +927,15 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
UseOptimizedLibcall = true;
break;
+ case AtomicExpr::AO__atomic_load:
+ case AtomicExpr::AO__atomic_store:
+ case AtomicExpr::AO__atomic_exchange:
+ case AtomicExpr::AO__atomic_compare_exchange:
+ // Use the generic version if we don't know that the operand will be
+ // suitably aligned for the optimized version.
+ if (Misaligned)
+ break;
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__c11_atomic_exchange:
@@ -934,14 +947,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
case AtomicExpr::AO__atomic_load_n:
- case AtomicExpr::AO__atomic_load:
case AtomicExpr::AO__atomic_store_n:
- case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_exchange_n:
- case AtomicExpr::AO__atomic_exchange:
case AtomicExpr::AO__atomic_compare_exchange_n:
- case AtomicExpr::AO__atomic_compare_exchange:
// Only use optimized library calls for sizes for which they exist.
+ // FIXME: Size == 16 optimized library functions exist too.
if (Size == 1 || Size == 2 || Size == 4 || Size == 8)
UseOptimizedLibcall = true;
break;
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 8269b5b229a2..fa3c3ee8610c 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CGBlocks.h"
+#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
@@ -25,6 +26,7 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/ScopedPrinter.h"
#include <algorithm>
#include <cstdio>
@@ -34,8 +36,8 @@ using namespace CodeGen;
CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
: Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false),
- LocalAddress(Address::invalid()), StructureType(nullptr), Block(block),
- DominatingIP(nullptr) {
+ CapturesNonExternalType(false), LocalAddress(Address::invalid()),
+ StructureType(nullptr), Block(block), DominatingIP(nullptr) {
// Skip asm prefix, if any. 'name' is usually taken directly from
// the mangled name of the enclosing function.
@@ -63,6 +65,110 @@ static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo);
}
+namespace {
+
+/// Represents a type of copy/destroy operation that should be performed for an
+/// entity that's captured by a block.
+enum class BlockCaptureEntityKind {
+ CXXRecord, // Copy or destroy
+ ARCWeak,
+ ARCStrong,
+ NonTrivialCStruct,
+ BlockObject, // Assign or release
+ None
+};
+
+/// Represents a captured entity that requires extra operations in order for
+/// this entity to be copied or destroyed correctly.
+struct BlockCaptureManagedEntity {
+ BlockCaptureEntityKind CopyKind, DisposeKind;
+ BlockFieldFlags CopyFlags, DisposeFlags;
+ const BlockDecl::Capture *CI;
+ const CGBlockInfo::Capture *Capture;
+
+ BlockCaptureManagedEntity(BlockCaptureEntityKind CopyType,
+ BlockCaptureEntityKind DisposeType,
+ BlockFieldFlags CopyFlags,
+ BlockFieldFlags DisposeFlags,
+ const BlockDecl::Capture &CI,
+ const CGBlockInfo::Capture &Capture)
+ : CopyKind(CopyType), DisposeKind(DisposeType), CopyFlags(CopyFlags),
+ DisposeFlags(DisposeFlags), CI(&CI), Capture(&Capture) {}
+
+ bool operator<(const BlockCaptureManagedEntity &Other) const {
+ return Capture->getOffset() < Other.Capture->getOffset();
+ }
+};
+
+enum class CaptureStrKind {
+ // String for the copy helper.
+ CopyHelper,
+ // String for the dispose helper.
+ DisposeHelper,
+ // Merge the strings for the copy helper and dispose helper.
+ Merged
+};
+
+} // end anonymous namespace
+
+static void findBlockCapturedManagedEntities(
+ const CGBlockInfo &BlockInfo, const LangOptions &LangOpts,
+ SmallVectorImpl<BlockCaptureManagedEntity> &ManagedCaptures);
+
+static std::string getBlockCaptureStr(const BlockCaptureManagedEntity &E,
+ CaptureStrKind StrKind,
+ CharUnits BlockAlignment,
+ CodeGenModule &CGM);
+
+static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo,
+ CodeGenModule &CGM) {
+ std::string Name = "__block_descriptor_";
+ Name += llvm::to_string(BlockInfo.BlockSize.getQuantity()) + "_";
+
+ if (BlockInfo.needsCopyDisposeHelpers()) {
+ if (CGM.getLangOpts().Exceptions)
+ Name += "e";
+ if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
+ Name += "a";
+ Name += llvm::to_string(BlockInfo.BlockAlign.getQuantity()) + "_";
+
+ SmallVector<BlockCaptureManagedEntity, 4> ManagedCaptures;
+ findBlockCapturedManagedEntities(BlockInfo, CGM.getContext().getLangOpts(),
+ ManagedCaptures);
+
+ for (const BlockCaptureManagedEntity &E : ManagedCaptures) {
+ Name += llvm::to_string(E.Capture->getOffset().getQuantity());
+
+ if (E.CopyKind == E.DisposeKind) {
+ // If CopyKind and DisposeKind are the same, merge the capture
+ // information.
+ assert(E.CopyKind != BlockCaptureEntityKind::None &&
+ "shouldn't see BlockCaptureManagedEntity that is None");
+ Name += getBlockCaptureStr(E, CaptureStrKind::Merged,
+ BlockInfo.BlockAlign, CGM);
+ } else {
+ // If CopyKind and DisposeKind are not the same, which can happen when
+ // either Kind is None or the captured object is a __strong block,
+ // concatenate the copy and dispose strings.
+ Name += getBlockCaptureStr(E, CaptureStrKind::CopyHelper,
+ BlockInfo.BlockAlign, CGM);
+ Name += getBlockCaptureStr(E, CaptureStrKind::DisposeHelper,
+ BlockInfo.BlockAlign, CGM);
+ }
+ }
+ Name += "_";
+ }
+
+ std::string TypeAtEncoding =
+ CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr());
+ /// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms as
+ /// a separator between symbol name and symbol version.
+ std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');
+ Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding;
+ Name += "l" + CGM.getObjCRuntime().getRCBlockLayoutStr(CGM, BlockInfo);
+ return Name;
+}
+
/// buildBlockDescriptor - Build the block descriptor meta-data for a block.
/// buildBlockDescriptor is accessed from 5th field of the Block_literal
/// meta-data and contains stationary information about the block literal.
@@ -72,7 +178,7 @@ static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
/// unsigned long reserved;
/// unsigned long size; // size of Block_literal metadata in bytes.
/// void *copy_func_helper_decl; // optional copy helper.
-/// void *destroy_func_decl; // optioanl destructor helper.
+/// void *destroy_func_decl; // optional destructor helper.
/// void *block_method_encoding_address; // @encode for block literal signature.
/// void *block_layout_info; // encoding of captured block variables.
/// };
@@ -91,6 +197,19 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
else
i8p = CGM.VoidPtrTy;
+ std::string descName;
+
+ // If an equivalent block descriptor global variable exists, return it.
+ if (C.getLangOpts().ObjC &&
+ CGM.getLangOpts().getGC() == LangOptions::NonGC) {
+ descName = getBlockDescriptorName(blockInfo, CGM);
+ if (llvm::GlobalValue *desc = CGM.getModule().getNamedValue(descName))
+ return llvm::ConstantExpr::getBitCast(desc,
+ CGM.getBlockDescriptorType());
+ }
+
+ // If there isn't an equivalent block descriptor global variable, create a new
+ // one.
ConstantInitBuilder builder(CGM);
auto elements = builder.beginStruct();
@@ -104,12 +223,20 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
elements.addInt(ulong, blockInfo.BlockSize.getQuantity());
// Optional copy/dispose helpers.
+ bool hasInternalHelper = false;
if (blockInfo.needsCopyDisposeHelpers()) {
// copy_func_helper_decl
- elements.add(buildCopyHelper(CGM, blockInfo));
+ llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
+ elements.add(copyHelper);
// destroy_func_decl
- elements.add(buildDisposeHelper(CGM, blockInfo));
+ llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
+ elements.add(disposeHelper);
+
+ if (cast<llvm::Function>(copyHelper->getOperand(0))->hasInternalLinkage() ||
+ cast<llvm::Function>(disposeHelper->getOperand(0))
+ ->hasInternalLinkage())
+ hasInternalHelper = true;
}
// Signature. Mandatory ObjC-style method descriptor @encode sequence.
@@ -119,7 +246,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p));
// GC layout.
- if (C.getLangOpts().ObjC1) {
+ if (C.getLangOpts().ObjC) {
if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
elements.add(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
else
@@ -132,12 +259,26 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
if (C.getLangOpts().OpenCL)
AddrSpace = C.getTargetAddressSpace(LangAS::opencl_constant);
+ llvm::GlobalValue::LinkageTypes linkage;
+ if (descName.empty()) {
+ linkage = llvm::GlobalValue::InternalLinkage;
+ descName = "__block_descriptor_tmp";
+ } else if (hasInternalHelper) {
+ // If either the copy helper or the dispose helper has internal linkage,
+ // the block descriptor must have internal linkage too.
+ linkage = llvm::GlobalValue::InternalLinkage;
+ } else {
+ linkage = llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+
llvm::GlobalVariable *global =
- elements.finishAndCreateGlobal("__block_descriptor_tmp",
- CGM.getPointerAlign(),
- /*constant*/ true,
- llvm::GlobalValue::InternalLinkage,
- AddrSpace);
+ elements.finishAndCreateGlobal(descName, CGM.getPointerAlign(),
+ /*constant*/ true, linkage, AddrSpace);
+
+ if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) {
+ global->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ }
return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType());
}
@@ -308,12 +449,25 @@ static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
assert(elementTypes.empty());
if (CGM.getLangOpts().OpenCL) {
- // The header is basically 'struct { int; int;
+ // The header is basically 'struct { int; int; generic void *;
// custom_fields; }'. Assert that struct is packed.
+ auto GenericAS =
+ CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic);
+ auto GenPtrAlign =
+ CharUnits::fromQuantity(CGM.getTarget().getPointerAlign(GenericAS) / 8);
+ auto GenPtrSize =
+ CharUnits::fromQuantity(CGM.getTarget().getPointerWidth(GenericAS) / 8);
+ assert(CGM.getIntSize() <= GenPtrSize);
+ assert(CGM.getIntAlign() <= GenPtrAlign);
+ assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign));
elementTypes.push_back(CGM.IntTy); /* total size */
elementTypes.push_back(CGM.IntTy); /* align */
- unsigned Offset = 2 * CGM.getIntSize().getQuantity();
- unsigned BlockAlign = CGM.getIntAlign().getQuantity();
+ elementTypes.push_back(
+ CGM.getOpenCLRuntime()
+ .getGenericVoidPointerType()); /* invoke function */
+ unsigned Offset =
+ 2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity();
+ unsigned BlockAlign = GenPtrAlign.getQuantity();
if (auto *Helper =
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ {
@@ -355,7 +509,11 @@ static QualType getCaptureFieldType(const CodeGenFunction &CGF,
return CGF.BlockInfo->getCapture(VD).fieldType();
if (auto *FD = CGF.LambdaCaptureFields.lookup(VD))
return FD->getType();
- return VD->getType();
+ // If the captured variable is a non-escaping __block variable, the field
+ // type is the reference type. If the variable is a __block variable that
+ // already has a reference type, the field type is the variable's type.
+ return VD->isNonEscapingByref() ?
+ CGF.getContext().getLValueReferenceType(VD->getType()) : VD->getType();
}
/// Compute the layout of the given block. Attempts to lay the block
@@ -378,7 +536,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
info.CanBeGlobal = true;
return;
}
- else if (C.getLangOpts().ObjC1 &&
+ else if (C.getLangOpts().ObjC &&
CGM.getLangOpts().getGC() == LangOptions::NonGC)
info.HasCapturedVariableLayout = true;
@@ -393,7 +551,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
if (block->capturesCXXThis()) {
assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) &&
"Can't capture 'this' outside a method");
- QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType(C);
+ QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType();
// Theoretically, this could be in a different address space, so
// don't assume standard pointer size/align.
@@ -411,7 +569,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
for (const auto &CI : block->captures()) {
const VarDecl *variable = CI.getVariable();
- if (CI.isByRef()) {
+ if (CI.isEscapingByref()) {
// We have to copy/dispose of the __block reference.
info.NeedsCopyDispose = true;
@@ -419,6 +577,10 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
CharUnits align = CGM.getPointerAlign();
maxFieldAlign = std::max(maxFieldAlign, align);
+ // Since a __block variable cannot be captured by lambdas, its type and
+ // the capture field type should always match.
+ assert(getCaptureFieldType(*CGF, CI) == variable->getType() &&
+ "capture type differs from the variable type");
layout.push_back(BlockLayoutChunk(align, CGM.getPointerSize(),
Qualifiers::OCL_None, &CI,
CGM.VoidPtrTy, variable->getType()));
@@ -432,10 +594,11 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
continue;
}
+ QualType VT = getCaptureFieldType(*CGF, CI);
+
// If we have a lifetime qualifier, honor it for capture purposes.
// That includes *not* copying it if it's __unsafe_unretained.
- Qualifiers::ObjCLifetime lifetime =
- variable->getType().getObjCLifetime();
+ Qualifiers::ObjCLifetime lifetime = VT.getObjCLifetime();
if (lifetime) {
switch (lifetime) {
case Qualifiers::OCL_None: llvm_unreachable("impossible");
@@ -449,10 +612,10 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
}
// Block pointers require copy/dispose. So do Objective-C pointers.
- } else if (variable->getType()->isObjCRetainableType()) {
+ } else if (VT->isObjCRetainableType()) {
// But honor the inert __unsafe_unretained qualifier, which doesn't
// actually make it into the type system.
- if (variable->getType()->isObjCInertUnsafeUnretainedType()) {
+ if (VT->isObjCInertUnsafeUnretainedType()) {
lifetime = Qualifiers::OCL_ExplicitNone;
} else {
info.NeedsCopyDispose = true;
@@ -464,27 +627,27 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
} else if (CI.hasCopyExpr()) {
info.NeedsCopyDispose = true;
info.HasCXXObject = true;
+ if (!VT->getAsCXXRecordDecl()->isExternallyVisible())
+ info.CapturesNonExternalType = true;
// So do C structs that require non-trivial copy construction or
// destruction.
- } else if (variable->getType().isNonTrivialToPrimitiveCopy() ==
- QualType::PCK_Struct ||
- variable->getType().isDestructedType() ==
- QualType::DK_nontrivial_c_struct) {
+ } else if (VT.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct ||
+ VT.isDestructedType() == QualType::DK_nontrivial_c_struct) {
info.NeedsCopyDispose = true;
// And so do types with destructors.
} else if (CGM.getLangOpts().CPlusPlus) {
- if (const CXXRecordDecl *record =
- variable->getType()->getAsCXXRecordDecl()) {
+ if (const CXXRecordDecl *record = VT->getAsCXXRecordDecl()) {
if (!record->hasTrivialDestructor()) {
info.HasCXXObject = true;
info.NeedsCopyDispose = true;
+ if (!record->isExternallyVisible())
+ info.CapturesNonExternalType = true;
}
}
}
- QualType VT = getCaptureFieldType(*CGF, CI);
CharUnits size = C.getTypeSizeInChars(VT);
CharUnits align = C.getDeclAlign(variable);
@@ -699,10 +862,12 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
/// Enter a full-expression with a non-trivial number of objects to
/// clean up. This is in this file because, at the moment, the only
/// kind of cleanup object is a BlockDecl*.
-void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) {
- assert(E->getNumObjects() != 0);
- for (const ExprWithCleanups::CleanupObject &C : E->getObjects())
- enterBlockScope(*this, C);
+void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) {
+ if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) {
+ assert(EWC->getNumObjects() != 0);
+ for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects())
+ enterBlockScope(*this, C);
+ }
}
/// Find the layout for the given block in a linked list and remove it.
@@ -759,12 +924,20 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
+ auto GenVoidPtrTy =
+ IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
+ LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
+ auto GenVoidPtrSize = CharUnits::fromQuantity(
+ CGM.getTarget().getPointerWidth(
+ CGM.getContext().getTargetAddressSpace(GenVoidPtrAddr)) /
+ 8);
// Using the computed layout, generate the actual block function.
bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda();
CodeGenFunction BlockCGF{CGM, true};
BlockCGF.SanOpts = SanOpts;
auto *InvokeFn = BlockCGF.GenerateBlockFunction(
CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal);
+ auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
// If there is nothing to capture, we can emit this as a global block.
if (blockInfo.CanBeGlobal)
@@ -840,12 +1013,11 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
getIntSize(), "block.align");
}
- if (!IsOpenCL) {
- addHeaderField(llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy),
- getPointerSize(), "block.invoke");
+ addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
+ if (!IsOpenCL)
addHeaderField(descriptor, getPointerSize(), "block.descriptor");
- } else if (auto *Helper =
- CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ else if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
addHeaderField(
I.first,
@@ -889,7 +1061,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// The lambda capture in a lambda's conversion-to-block-pointer is
// special; we'll simply emit it directly.
src = Address::invalid();
- } else if (CI.isByRef()) {
+ } else if (CI.isEscapingByref()) {
if (BlockInfo && CI.isNested()) {
// We need to use the capture from the enclosing block.
const CGBlockInfo::Capture &enclosingCapture =
@@ -906,7 +1078,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
src = I->second;
}
} else {
- DeclRefExpr declRef(const_cast<VarDecl *>(variable),
+ DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),
/*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
type.getNonReferenceType(), VK_LValue,
SourceLocation());
@@ -917,7 +1089,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// the block field. There's no need to chase the forwarding
// pointer at this point, since we're building something that will
// live a shorter life than the stack byref anyway.
- if (CI.isByRef()) {
+ if (CI.isEscapingByref()) {
// Get a void* that points to the byref struct.
llvm::Value *byrefPointer;
if (CI.isNested())
@@ -980,7 +1152,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// We use one of these or the other depending on whether the
// reference is nested.
- DeclRefExpr declRef(const_cast<VarDecl *>(variable),
+ DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),
/*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
type, VK_LValue, SourceLocation());
@@ -1049,23 +1221,38 @@ llvm::Type *CodeGenModule::getBlockDescriptorType() {
}
llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
- assert(!getLangOpts().OpenCL && "OpenCL does not need this");
-
if (GenericBlockLiteralType)
return GenericBlockLiteralType;
llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
- // struct __block_literal_generic {
- // void *__isa;
- // int __flags;
- // int __reserved;
- // void (*__invoke)(void *);
- // struct __block_descriptor *__descriptor;
- // };
- GenericBlockLiteralType =
- llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
- IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
+ if (getLangOpts().OpenCL) {
+ // struct __opencl_block_literal_generic {
+ // int __size;
+ // int __align;
+ // __generic void *__invoke;
+ // /* custom fields */
+ // };
+ SmallVector<llvm::Type *, 8> StructFields(
+ {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()});
+ if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ for (auto I : Helper->getCustomFieldTypes())
+ StructFields.push_back(I);
+ }
+ GenericBlockLiteralType = llvm::StructType::create(
+ StructFields, "struct.__opencl_block_literal_generic");
+ } else {
+ // struct __block_literal_generic {
+ // void *__isa;
+ // int __flags;
+ // int __reserved;
+ // void (*__invoke)(void *);
+ // struct __block_descriptor *__descriptor;
+ // };
+ GenericBlockLiteralType =
+ llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
+ IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
+ }
return GenericBlockLiteralType;
}
@@ -1076,21 +1263,27 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
E->getCallee()->getType()->getAs<BlockPointerType>();
llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
- llvm::Value *FuncPtr;
- if (!CGM.getLangOpts().OpenCL) {
- // Get a pointer to the generic block literal.
- llvm::Type *BlockLiteralTy =
- llvm::PointerType::get(CGM.getGenericBlockLiteralType(), 0);
+ // Get a pointer to the generic block literal.
+ // For OpenCL we generate generic AS void ptr to be able to reuse the same
+ // block definition for blocks with captures generated as private AS local
+ // variables and without captures generated as global AS program scope
+ // variables.
+ unsigned AddrSpace = 0;
+ if (getLangOpts().OpenCL)
+ AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_generic);
- // Bitcast the callee to a block literal.
- BlockPtr =
- Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal");
+ llvm::Type *BlockLiteralTy =
+ llvm::PointerType::get(CGM.getGenericBlockLiteralType(), AddrSpace);
- // Get the function pointer from the literal.
- FuncPtr =
- Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3);
- }
+ // Bitcast the callee to a block literal.
+ BlockPtr =
+ Builder.CreatePointerCast(BlockPtr, BlockLiteralTy, "block.literal");
+
+ // Get the function pointer from the literal.
+ llvm::Value *FuncPtr =
+ Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr,
+ CGM.getLangOpts().OpenCL ? 2 : 3);
// Add the block literal.
CallArgList Args;
@@ -1113,11 +1306,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
// Load the function.
- llvm::Value *Func;
- if (CGM.getLangOpts().OpenCL)
- Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
- else
- Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
+ llvm::Value *Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
const FunctionType *FuncTy = FnType->castAs<FunctionType>();
const CGFunctionInfo &FnInfo =
@@ -1136,8 +1325,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
return EmitCall(FnInfo, Callee, ReturnValue, Args);
}
-Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
- bool isByRef) {
+Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable) {
assert(BlockInfo && "evaluating block ref without block information?");
const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable);
@@ -1148,7 +1336,7 @@ Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
capture.getOffset(), "block.capture.addr");
- if (isByRef) {
+ if (variable->isEscapingByref()) {
// addr should be a void** right now. Load, then cast the result
// to byref*.
@@ -1162,6 +1350,10 @@ Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
variable->getName());
}
+ assert((!variable->isNonEscapingByref() ||
+ capture.fieldType()->isReferenceType()) &&
+ "the capture field of a non-escaping variable should have a "
+ "reference type");
if (capture.fieldType()->isReferenceType())
addr = EmitLoadOfReference(MakeAddrLValue(addr, capture.fieldType()));
@@ -1213,9 +1405,13 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
auto fields = builder.beginStruct();
bool IsOpenCL = CGM.getLangOpts().OpenCL;
+ bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
if (!IsOpenCL) {
// isa
- fields.add(CGM.getNSConcreteGlobalBlock());
+ if (IsWindows)
+ fields.addNullPointer(CGM.Int8PtrPtrTy);
+ else
+ fields.add(CGM.getNSConcreteGlobalBlock());
// __flags
BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
@@ -1226,14 +1422,14 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
// Reserved
fields.addInt(CGM.IntTy, 0);
-
- // Function
- fields.add(blockFn);
} else {
fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity());
fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity());
}
+ // Function
+ fields.add(blockFn);
+
if (!IsOpenCL) {
// Descriptor
fields.add(buildBlockDescriptor(CGM, blockInfo));
@@ -1250,7 +1446,27 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
llvm::Constant *literal = fields.finishAndCreateGlobal(
"__block_literal_global", blockInfo.BlockAlign,
- /*constant*/ true, llvm::GlobalVariable::InternalLinkage, AddrSpace);
+ /*constant*/ !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);
+
+ // Windows does not allow globals to be initialised to point to globals in
+ // different DLLs. Any such variables must run code to initialise them.
+ if (IsWindows) {
+ auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,
+ {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init",
+ &CGM.getModule());
+ llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
+ Init));
+ b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(),
+ b.CreateStructGEP(literal, 0), CGM.getPointerAlign().getQuantity());
+ b.CreateRetVoid();
+ // We can't use the normal LLVM global initialisation array, because we
+ // need to specify that this runs early in library initialisation.
+ auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
+ /*isConstant*/true, llvm::GlobalValue::InternalLinkage,
+ Init, ".block_isa_init_ptr");
+ InitVar->setSection(".CRT$XCLa");
+ CGM.addUsedGlobal(InitVar);
+ }
// Return a constant of the appropriately-casted type.
llvm::Type *RequiredType =
@@ -1284,7 +1500,7 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
}
}
- SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getLocStart();
+ SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getBeginLoc();
ApplyDebugLocation Scope(*this, StartLoc);
// Instead of messing around with LocalDeclMap, just set the value
@@ -1314,7 +1530,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
CurGD = GD;
- CurEHLocation = blockInfo.getBlockExpr()->getLocEnd();
+ CurEHLocation = blockInfo.getBlockExpr()->getEndLoc();
BlockInfo = &blockInfo;
@@ -1379,7 +1595,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
// Begin generating the function.
StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args,
blockDecl->getLocation(),
- blockInfo.getBlockExpr()->getBody()->getLocStart());
+ blockInfo.getBlockExpr()->getBody()->getBeginLoc());
// Okay. Undo some of what StartFunction did.
@@ -1480,35 +1696,6 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
return fn;
}
-namespace {
-
-/// Represents a type of copy/destroy operation that should be performed for an
-/// entity that's captured by a block.
-enum class BlockCaptureEntityKind {
- CXXRecord, // Copy or destroy
- ARCWeak,
- ARCStrong,
- NonTrivialCStruct,
- BlockObject, // Assign or release
- None
-};
-
-/// Represents a captured entity that requires extra operations in order for
-/// this entity to be copied or destroyed correctly.
-struct BlockCaptureManagedEntity {
- BlockCaptureEntityKind Kind;
- BlockFieldFlags Flags;
- const BlockDecl::Capture &CI;
- const CGBlockInfo::Capture &Capture;
-
- BlockCaptureManagedEntity(BlockCaptureEntityKind Type, BlockFieldFlags Flags,
- const BlockDecl::Capture &CI,
- const CGBlockInfo::Capture &Capture)
- : Kind(Type), Flags(Flags), CI(CI), Capture(Capture) {}
-};
-
-} // end anonymous namespace
-
static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
const LangOptions &LangOpts) {
@@ -1518,7 +1705,7 @@ computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags());
}
BlockFieldFlags Flags;
- if (CI.isByRef()) {
+ if (CI.isEscapingByref()) {
Flags = BLOCK_FIELD_IS_BYREF;
if (T.isObjCGCWeak())
Flags |= BLOCK_FIELD_IS_WEAK;
@@ -1566,23 +1753,32 @@ computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
llvm_unreachable("after exhaustive PrimitiveCopyKind switch");
}
+static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
+computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
+ const LangOptions &LangOpts);
+
/// Find the set of block captures that need to be explicitly copied or destroy.
static void findBlockCapturedManagedEntities(
const CGBlockInfo &BlockInfo, const LangOptions &LangOpts,
- SmallVectorImpl<BlockCaptureManagedEntity> &ManagedCaptures,
- llvm::function_ref<std::pair<BlockCaptureEntityKind, BlockFieldFlags>(
- const BlockDecl::Capture &, QualType, const LangOptions &)>
- Predicate) {
+ SmallVectorImpl<BlockCaptureManagedEntity> &ManagedCaptures) {
for (const auto &CI : BlockInfo.getBlockDecl()->captures()) {
const VarDecl *Variable = CI.getVariable();
const CGBlockInfo::Capture &Capture = BlockInfo.getCapture(Variable);
if (Capture.isConstant())
continue;
- auto Info = Predicate(CI, Variable->getType(), LangOpts);
- if (Info.first != BlockCaptureEntityKind::None)
- ManagedCaptures.emplace_back(Info.first, Info.second, CI, Capture);
+ QualType VT = Capture.fieldType();
+ auto CopyInfo = computeCopyInfoForBlockCapture(CI, VT, LangOpts);
+ auto DisposeInfo = computeDestroyInfoForBlockCapture(CI, VT, LangOpts);
+ if (CopyInfo.first != BlockCaptureEntityKind::None ||
+ DisposeInfo.first != BlockCaptureEntityKind::None)
+ ManagedCaptures.emplace_back(CopyInfo.first, DisposeInfo.first,
+ CopyInfo.second, DisposeInfo.second, CI,
+ Capture);
}
+
+ // Sort the captures by offset.
+ llvm::sort(ManagedCaptures);
}
namespace {
@@ -1590,10 +1786,12 @@ namespace {
struct CallBlockRelease final : EHScopeStack::Cleanup {
Address Addr;
BlockFieldFlags FieldFlags;
- bool LoadBlockVarAddr;
+ bool LoadBlockVarAddr, CanThrow;
- CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue)
- : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue) {}
+ CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue,
+ bool CT)
+ : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue),
+ CanThrow(CT) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
llvm::Value *BlockVarAddr;
@@ -1604,15 +1802,145 @@ struct CallBlockRelease final : EHScopeStack::Cleanup {
BlockVarAddr = Addr.getPointer();
}
- CGF.BuildBlockRelease(BlockVarAddr, FieldFlags);
+ CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow);
}
};
} // end anonymous namespace
+/// Check if \p T is a C++ class that has a destructor that can throw.
+bool CodeGenFunction::cxxDestructorCanThrow(QualType T) {
+ if (const auto *RD = T->getAsCXXRecordDecl())
+ if (const CXXDestructorDecl *DD = RD->getDestructor())
+ return DD->getType()->getAs<FunctionProtoType>()->canThrow();
+ return false;
+}
+
+// Return a string that has the information about a capture.
+static std::string getBlockCaptureStr(const BlockCaptureManagedEntity &E,
+ CaptureStrKind StrKind,
+ CharUnits BlockAlignment,
+ CodeGenModule &CGM) {
+ std::string Str;
+ ASTContext &Ctx = CGM.getContext();
+ const BlockDecl::Capture &CI = *E.CI;
+ QualType CaptureTy = CI.getVariable()->getType();
+
+ BlockCaptureEntityKind Kind;
+ BlockFieldFlags Flags;
+
+ // CaptureStrKind::Merged should be passed only when the operations and the
+ // flags are the same for copy and dispose.
+ assert((StrKind != CaptureStrKind::Merged ||
+ (E.CopyKind == E.DisposeKind && E.CopyFlags == E.DisposeFlags)) &&
+ "different operations and flags");
+
+ if (StrKind == CaptureStrKind::DisposeHelper) {
+ Kind = E.DisposeKind;
+ Flags = E.DisposeFlags;
+ } else {
+ Kind = E.CopyKind;
+ Flags = E.CopyFlags;
+ }
+
+ switch (Kind) {
+ case BlockCaptureEntityKind::CXXRecord: {
+ Str += "c";
+ SmallString<256> TyStr;
+ llvm::raw_svector_ostream Out(TyStr);
+ CGM.getCXXABI().getMangleContext().mangleTypeName(CaptureTy, Out);
+ Str += llvm::to_string(TyStr.size()) + TyStr.c_str();
+ break;
+ }
+ case BlockCaptureEntityKind::ARCWeak:
+ Str += "w";
+ break;
+ case BlockCaptureEntityKind::ARCStrong:
+ Str += "s";
+ break;
+ case BlockCaptureEntityKind::BlockObject: {
+ const VarDecl *Var = CI.getVariable();
+ unsigned F = Flags.getBitMask();
+ if (F & BLOCK_FIELD_IS_BYREF) {
+ Str += "r";
+ if (F & BLOCK_FIELD_IS_WEAK)
+ Str += "w";
+ else {
+ // If CaptureStrKind::Merged is passed, check both the copy expression
+ // and the destructor.
+ if (StrKind != CaptureStrKind::DisposeHelper) {
+ if (Ctx.getBlockVarCopyInit(Var).canThrow())
+ Str += "c";
+ }
+ if (StrKind != CaptureStrKind::CopyHelper) {
+ if (CodeGenFunction::cxxDestructorCanThrow(CaptureTy))
+ Str += "d";
+ }
+ }
+ } else {
+ assert((F & BLOCK_FIELD_IS_OBJECT) && "unexpected flag value");
+ if (F == BLOCK_FIELD_IS_BLOCK)
+ Str += "b";
+ else
+ Str += "o";
+ }
+ break;
+ }
+ case BlockCaptureEntityKind::NonTrivialCStruct: {
+ bool IsVolatile = CaptureTy.isVolatileQualified();
+ CharUnits Alignment =
+ BlockAlignment.alignmentAtOffset(E.Capture->getOffset());
+
+ Str += "n";
+ std::string FuncStr;
+ if (StrKind == CaptureStrKind::DisposeHelper)
+ FuncStr = CodeGenFunction::getNonTrivialDestructorStr(
+ CaptureTy, Alignment, IsVolatile, Ctx);
+ else
+ // If CaptureStrKind::Merged is passed, use the copy constructor string.
+ // It has all the information that the destructor string has.
+ FuncStr = CodeGenFunction::getNonTrivialCopyConstructorStr(
+ CaptureTy, Alignment, IsVolatile, Ctx);
+ // The underscore is necessary here because non-trivial copy constructor
+ // and destructor strings can start with a number.
+ Str += llvm::to_string(FuncStr.size()) + "_" + FuncStr;
+ break;
+ }
+ case BlockCaptureEntityKind::None:
+ break;
+ }
+
+ return Str;
+}
+
+static std::string getCopyDestroyHelperFuncName(
+ const SmallVectorImpl<BlockCaptureManagedEntity> &Captures,
+ CharUnits BlockAlignment, CaptureStrKind StrKind, CodeGenModule &CGM) {
+ assert((StrKind == CaptureStrKind::CopyHelper ||
+ StrKind == CaptureStrKind::DisposeHelper) &&
+ "unexpected CaptureStrKind");
+ std::string Name = StrKind == CaptureStrKind::CopyHelper
+ ? "__copy_helper_block_"
+ : "__destroy_helper_block_";
+ if (CGM.getLangOpts().Exceptions)
+ Name += "e";
+ if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
+ Name += "a";
+ Name += llvm::to_string(BlockAlignment.getQuantity()) + "_";
+
+ for (const BlockCaptureManagedEntity &E : Captures) {
+ Name += llvm::to_string(E.Capture->getOffset().getQuantity());
+ Name += getBlockCaptureStr(E, StrKind, BlockAlignment, CGM);
+ }
+
+ return Name;
+}
+
static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
Address Field, QualType CaptureType,
- BlockFieldFlags Flags, bool EHOnly,
- CodeGenFunction &CGF) {
+ BlockFieldFlags Flags, bool ForCopyHelper,
+ VarDecl *Var, CodeGenFunction &CGF) {
+ bool EHOnly = ForCopyHelper;
+
switch (CaptureKind) {
case BlockCaptureEntityKind::CXXRecord:
case BlockCaptureEntityKind::ARCWeak:
@@ -1634,15 +1962,34 @@ static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
case BlockCaptureEntityKind::BlockObject: {
if (!EHOnly || CGF.getLangOpts().Exceptions) {
CleanupKind Kind = EHOnly ? EHCleanup : NormalAndEHCleanup;
- CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true);
+ // Calls to _Block_object_dispose along the EH path in the copy helper
+ // function don't throw as newly-copied __block variables always have a
+ // reference count of 2.
+ bool CanThrow =
+ !ForCopyHelper && CGF.cxxDestructorCanThrow(CaptureType);
+ CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true,
+ CanThrow);
}
break;
}
case BlockCaptureEntityKind::None:
- llvm_unreachable("unexpected BlockCaptureEntityKind");
+ break;
}
}
+static void setBlockHelperAttributesVisibility(bool CapturesNonExternalType,
+ llvm::Function *Fn,
+ const CGFunctionInfo &FI,
+ CodeGenModule &CGM) {
+ if (CapturesNonExternalType) {
+ CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
+ } else {
+ Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn);
+ CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
+ }
+}
/// Generate the copy-helper function for a block closure object:
/// static void block_copy_helper(block_t *dst, block_t *src);
/// The runtime will have previously initialized 'dst' by doing a
@@ -1653,42 +2000,51 @@ static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
/// the contents of an individual __block variable to the heap.
llvm::Constant *
CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
+ SmallVector<BlockCaptureManagedEntity, 4> CopiedCaptures;
+ findBlockCapturedManagedEntities(blockInfo, getLangOpts(), CopiedCaptures);
+ std::string FuncName =
+ getCopyDestroyHelperFuncName(CopiedCaptures, blockInfo.BlockAlign,
+ CaptureStrKind::CopyHelper, CGM);
+
+ if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))
+ return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy);
+
ASTContext &C = getContext();
+ QualType ReturnTy = C.VoidTy;
+
FunctionArgList args;
- ImplicitParamDecl DstDecl(getContext(), C.VoidPtrTy,
- ImplicitParamDecl::Other);
+ ImplicitParamDecl DstDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
args.push_back(&DstDecl);
- ImplicitParamDecl SrcDecl(getContext(), C.VoidPtrTy,
- ImplicitParamDecl::Other);
+ ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
args.push_back(&SrcDecl);
const CGFunctionInfo &FI =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
// FIXME: it would be nice if these were mergeable with things with
// identical semantics.
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
llvm::Function *Fn =
- llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- "__copy_helper_block_", &CGM.getModule());
+ llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
+ FuncName, &CGM.getModule());
- IdentifierInfo *II
- = &CGM.getContext().Idents.get("__copy_helper_block_");
+ IdentifierInfo *II = &C.Idents.get(FuncName);
- FunctionDecl *FD = FunctionDecl::Create(C,
- C.getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(), II, C.VoidTy,
- nullptr, SC_Static,
- false,
- false);
+ SmallVector<QualType, 2> ArgTys;
+ ArgTys.push_back(C.VoidPtrTy);
+ ArgTys.push_back(C.VoidPtrTy);
+ QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
- CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
+ FunctionDecl *FD = FunctionDecl::Create(
+ C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
+ FunctionTy, nullptr, SC_Static, false, false);
- StartFunction(FD, C.VoidTy, Fn, FI, args);
- ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getLocStart()};
+ setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
+ CGM);
+ StartFunction(FD, ReturnTy, Fn, FI, args);
+ ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getBeginLoc()};
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
Address src = GetAddrOfLocalVar(&SrcDecl);
@@ -1699,88 +2055,81 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
dst = Address(Builder.CreateLoad(dst), blockInfo.BlockAlign);
dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest");
- SmallVector<BlockCaptureManagedEntity, 4> CopiedCaptures;
- findBlockCapturedManagedEntities(blockInfo, getLangOpts(), CopiedCaptures,
- computeCopyInfoForBlockCapture);
-
for (const auto &CopiedCapture : CopiedCaptures) {
- const BlockDecl::Capture &CI = CopiedCapture.CI;
- const CGBlockInfo::Capture &capture = CopiedCapture.Capture;
+ const BlockDecl::Capture &CI = *CopiedCapture.CI;
+ const CGBlockInfo::Capture &capture = *CopiedCapture.Capture;
QualType captureType = CI.getVariable()->getType();
- BlockFieldFlags flags = CopiedCapture.Flags;
+ BlockFieldFlags flags = CopiedCapture.CopyFlags;
unsigned index = capture.getIndex();
Address srcField = Builder.CreateStructGEP(src, index, capture.getOffset());
Address dstField = Builder.CreateStructGEP(dst, index, capture.getOffset());
- // If there's an explicit copy expression, we do that.
- if (CI.getCopyExpr()) {
- assert(CopiedCapture.Kind == BlockCaptureEntityKind::CXXRecord);
+ switch (CopiedCapture.CopyKind) {
+ case BlockCaptureEntityKind::CXXRecord:
+ // If there's an explicit copy expression, we do that.
+ assert(CI.getCopyExpr() && "copy expression for variable is missing");
EmitSynthesizedCXXCopyCtor(dstField, srcField, CI.getCopyExpr());
- } else if (CopiedCapture.Kind == BlockCaptureEntityKind::ARCWeak) {
+ break;
+ case BlockCaptureEntityKind::ARCWeak:
EmitARCCopyWeak(dstField, srcField);
- // If this is a C struct that requires non-trivial copy construction, emit a
- // call to its copy constructor.
- } else if (CopiedCapture.Kind ==
- BlockCaptureEntityKind::NonTrivialCStruct) {
+ break;
+ case BlockCaptureEntityKind::NonTrivialCStruct: {
+ // If this is a C struct that requires non-trivial copy construction,
+ // emit a call to its copy constructor.
QualType varType = CI.getVariable()->getType();
callCStructCopyConstructor(MakeAddrLValue(dstField, varType),
MakeAddrLValue(srcField, varType));
- } else {
+ break;
+ }
+ case BlockCaptureEntityKind::ARCStrong: {
llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
- if (CopiedCapture.Kind == BlockCaptureEntityKind::ARCStrong) {
- // At -O0, store null into the destination field (so that the
- // storeStrong doesn't over-release) and then call storeStrong.
- // This is a workaround to not having an initStrong call.
- if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
- auto *ty = cast<llvm::PointerType>(srcValue->getType());
- llvm::Value *null = llvm::ConstantPointerNull::get(ty);
- Builder.CreateStore(null, dstField);
- EmitARCStoreStrongCall(dstField, srcValue, true);
-
- // With optimization enabled, take advantage of the fact that
- // the blocks runtime guarantees a memcpy of the block data, and
- // just emit a retain of the src field.
- } else {
- EmitARCRetainNonBlock(srcValue);
-
- // Unless EH cleanup is required, we don't need this anymore, so kill
- // it. It's not quite worth the annoyance to avoid creating it in the
- // first place.
- if (!needsEHCleanup(captureType.isDestructedType()))
- cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
- }
+ // At -O0, store null into the destination field (so that the
+ // storeStrong doesn't over-release) and then call storeStrong.
+ // This is a workaround to not having an initStrong call.
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
+ auto *ty = cast<llvm::PointerType>(srcValue->getType());
+ llvm::Value *null = llvm::ConstantPointerNull::get(ty);
+ Builder.CreateStore(null, dstField);
+ EmitARCStoreStrongCall(dstField, srcValue, true);
+
+ // With optimization enabled, take advantage of the fact that
+ // the blocks runtime guarantees a memcpy of the block data, and
+ // just emit a retain of the src field.
} else {
- assert(CopiedCapture.Kind == BlockCaptureEntityKind::BlockObject);
- srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
- llvm::Value *dstAddr =
- Builder.CreateBitCast(dstField.getPointer(), VoidPtrTy);
- llvm::Value *args[] = {
- dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
- };
-
- const VarDecl *variable = CI.getVariable();
- bool copyCanThrow = false;
- if (CI.isByRef() && variable->getType()->getAsCXXRecordDecl()) {
- const Expr *copyExpr =
- CGM.getContext().getBlockVarCopyInits(variable);
- if (copyExpr) {
- copyCanThrow = true; // FIXME: reuse the noexcept logic
- }
- }
+ EmitARCRetainNonBlock(srcValue);
- if (copyCanThrow) {
- EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args);
- } else {
- EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args);
- }
+ // Unless EH cleanup is required, we don't need this anymore, so kill
+ // it. It's not quite worth the annoyance to avoid creating it in the
+ // first place.
+ if (!needsEHCleanup(captureType.isDestructedType()))
+ cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
}
+ break;
+ }
+ case BlockCaptureEntityKind::BlockObject: {
+ llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
+ srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
+ llvm::Value *dstAddr =
+ Builder.CreateBitCast(dstField.getPointer(), VoidPtrTy);
+ llvm::Value *args[] = {
+ dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
+ };
+
+ if (CI.isByRef() && C.getBlockVarCopyInit(CI.getVariable()).canThrow())
+ EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args);
+ else
+ EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args);
+ break;
+ }
+ case BlockCaptureEntityKind::None:
+ continue;
}
// Ensure that we destroy the copied object if an exception is thrown later
// in the helper function.
- pushCaptureCleanup(CopiedCapture.Kind, dstField, captureType, flags, /*EHOnly*/ true,
- *this);
+ pushCaptureCleanup(CopiedCapture.CopyKind, dstField, captureType, flags,
+ /*ForCopyHelper*/ true, CI.getVariable(), *this);
}
FinishFunction();
@@ -1800,7 +2149,7 @@ getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI,
static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
const LangOptions &LangOpts) {
- if (CI.isByRef()) {
+ if (CI.isEscapingByref()) {
BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF;
if (T.isObjCGCWeak())
Flags |= BLOCK_FIELD_IS_WEAK;
@@ -1844,37 +2193,50 @@ computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
/// variable.
llvm::Constant *
CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
+ SmallVector<BlockCaptureManagedEntity, 4> DestroyedCaptures;
+ findBlockCapturedManagedEntities(blockInfo, getLangOpts(), DestroyedCaptures);
+ std::string FuncName =
+ getCopyDestroyHelperFuncName(DestroyedCaptures, blockInfo.BlockAlign,
+ CaptureStrKind::DisposeHelper, CGM);
+
+ if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))
+ return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy);
+
ASTContext &C = getContext();
+ QualType ReturnTy = C.VoidTy;
+
FunctionArgList args;
- ImplicitParamDecl SrcDecl(getContext(), C.VoidPtrTy,
- ImplicitParamDecl::Other);
+ ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
args.push_back(&SrcDecl);
const CGFunctionInfo &FI =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
llvm::Function *Fn =
- llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- "__destroy_helper_block_", &CGM.getModule());
+ llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
+ FuncName, &CGM.getModule());
- IdentifierInfo *II
- = &CGM.getContext().Idents.get("__destroy_helper_block_");
+ IdentifierInfo *II = &C.Idents.get(FuncName);
+
+ SmallVector<QualType, 1> ArgTys;
+ ArgTys.push_back(C.VoidPtrTy);
+ QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
- FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(), II, C.VoidTy,
- nullptr, SC_Static,
- false, false);
+ FunctionDecl *FD = FunctionDecl::Create(
+ C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
+ FunctionTy, nullptr, SC_Static, false, false);
- CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
+ setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
+ CGM);
+ StartFunction(FD, ReturnTy, Fn, FI, args);
+ markAsIgnoreThreadCheckingAtRuntime(Fn);
- StartFunction(FD, C.VoidTy, Fn, FI, args);
- ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getLocStart()};
+ ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getBeginLoc()};
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -1884,20 +2246,17 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
CodeGenFunction::RunCleanupsScope cleanups(*this);
- SmallVector<BlockCaptureManagedEntity, 4> DestroyedCaptures;
- findBlockCapturedManagedEntities(blockInfo, getLangOpts(), DestroyedCaptures,
- computeDestroyInfoForBlockCapture);
-
for (const auto &DestroyedCapture : DestroyedCaptures) {
- const BlockDecl::Capture &CI = DestroyedCapture.CI;
- const CGBlockInfo::Capture &capture = DestroyedCapture.Capture;
- BlockFieldFlags flags = DestroyedCapture.Flags;
+ const BlockDecl::Capture &CI = *DestroyedCapture.CI;
+ const CGBlockInfo::Capture &capture = *DestroyedCapture.Capture;
+ BlockFieldFlags flags = DestroyedCapture.DisposeFlags;
Address srcField =
Builder.CreateStructGEP(src, capture.getIndex(), capture.getOffset());
- pushCaptureCleanup(DestroyedCapture.Kind, srcField,
- CI.getVariable()->getType(), flags, /*EHOnly*/ false, *this);
+ pushCaptureCleanup(DestroyedCapture.DisposeKind, srcField,
+ CI.getVariable()->getType(), flags,
+ /*ForCopyHelper*/ false, CI.getVariable(), *this);
}
cleanups.ForceCleanup();
@@ -1937,7 +2296,7 @@ public:
field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0));
llvm::Value *value = CGF.Builder.CreateLoad(field);
- CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER);
+ CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER, false);
}
void profileImpl(llvm::FoldingSetNodeID &id) const override {
@@ -2093,19 +2452,17 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
BlockByrefHelpers &generator) {
ASTContext &Context = CGF.getContext();
- QualType R = Context.VoidTy;
+ QualType ReturnTy = Context.VoidTy;
FunctionArgList args;
- ImplicitParamDecl Dst(CGF.getContext(), Context.VoidPtrTy,
- ImplicitParamDecl::Other);
+ ImplicitParamDecl Dst(Context, Context.VoidPtrTy, ImplicitParamDecl::Other);
args.push_back(&Dst);
- ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy,
- ImplicitParamDecl::Other);
+ ImplicitParamDecl Src(Context, Context.VoidPtrTy, ImplicitParamDecl::Other);
args.push_back(&Src);
const CGFunctionInfo &FI =
- CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args);
+ CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI);
@@ -2118,16 +2475,18 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
IdentifierInfo *II
= &Context.Idents.get("__Block_byref_object_copy_");
- FunctionDecl *FD = FunctionDecl::Create(Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(), II, R, nullptr,
- SC_Static,
- false, false);
+ SmallVector<QualType, 2> ArgTys;
+ ArgTys.push_back(Context.VoidPtrTy);
+ ArgTys.push_back(Context.VoidPtrTy);
+ QualType FunctionTy = Context.getFunctionType(ReturnTy, ArgTys, {});
+
+ FunctionDecl *FD = FunctionDecl::Create(
+ Context, Context.getTranslationUnitDecl(), SourceLocation(),
+ SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false);
CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
- CGF.StartFunction(FD, R, Fn, FI, args);
+ CGF.StartFunction(FD, ReturnTy, Fn, FI, args);
if (generator.needsCopy()) {
llvm::Type *byrefPtrType = byrefInfo.Type->getPointerTo(0);
@@ -2192,12 +2551,13 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
IdentifierInfo *II
= &Context.Idents.get("__Block_byref_object_dispose_");
- FunctionDecl *FD = FunctionDecl::Create(Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(), II, R, nullptr,
- SC_Static,
- false, false);
+ SmallVector<QualType, 1> ArgTys;
+ ArgTys.push_back(Context.VoidPtrTy);
+ QualType FunctionTy = Context.getFunctionType(R, ArgTys, {});
+
+ FunctionDecl *FD = FunctionDecl::Create(
+ Context, Context.getTranslationUnitDecl(), SourceLocation(),
+ SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false);
CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
@@ -2254,6 +2614,9 @@ BlockByrefHelpers *
CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
const AutoVarEmission &emission) {
const VarDecl &var = *emission.Variable;
+ assert(var.isEscapingByref() &&
+ "only escaping __block variables need byref helpers");
+
QualType type = var.getType();
auto &byrefInfo = getBlockByrefInfo(&var);
@@ -2264,7 +2627,8 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset);
if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
- const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var);
+ const Expr *copyExpr =
+ CGM.getContext().getBlockVarCopyInit(&var).getCopyExpr();
if (!copyExpr && record->hasTrivialDestructor()) return nullptr;
return ::buildByrefHelpers(
@@ -2567,19 +2931,25 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
}
}
-void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) {
+void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags,
+ bool CanThrow) {
llvm::Value *F = CGM.getBlockObjectDispose();
llvm::Value *args[] = {
Builder.CreateBitCast(V, Int8PtrTy),
llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
};
- EmitNounwindRuntimeCall(F, args); // FIXME: throwing destructors?
+
+ if (CanThrow)
+ EmitRuntimeCallOrInvoke(F, args);
+ else
+ EmitNounwindRuntimeCall(F, args);
}
void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr,
BlockFieldFlags Flags,
- bool LoadBlockVarAddr) {
- EHStack.pushCleanup<CallBlockRelease>(Kind, Addr, Flags, LoadBlockVarAddr);
+ bool LoadBlockVarAddr, bool CanThrow) {
+ EHStack.pushCleanup<CallBlockRelease>(Kind, Addr, Flags, LoadBlockVarAddr,
+ CanThrow);
}
/// Adjust the declaration of something from the blocks API.
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 5abf82b3f6e1..3f9fc16d9b10 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -60,7 +60,7 @@ enum BlockLiteralFlags {
BLOCK_IS_GLOBAL = (1 << 28),
BLOCK_USE_STRET = (1 << 29),
BLOCK_HAS_SIGNATURE = (1 << 30),
- BLOCK_HAS_EXTENDED_LAYOUT = (1 << 31)
+ BLOCK_HAS_EXTENDED_LAYOUT = (1u << 31)
};
class BlockFlags {
uint32_t flags;
@@ -132,6 +132,9 @@ public:
friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) {
return (l.flags & r.flags);
}
+ bool operator==(BlockFieldFlags Other) const {
+ return flags == Other.flags;
+ }
};
inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) {
return BlockFieldFlags(l) | BlockFieldFlags(r);
@@ -231,6 +234,11 @@ public:
/// and their layout meta-data has been generated.
bool HasCapturedVariableLayout : 1;
+ /// Indicates whether an object of a non-external C++ class is captured. This
+ /// bit is used to determine the linkage of the block copy/destroy helper
+ /// functions.
+ bool CapturesNonExternalType : 1;
+
/// The mapping of allocated indexes within the block.
llvm::DenseMap<const VarDecl*, Capture> Captures;
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index e99121c46d9b..a718f2f19aa6 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -21,10 +21,11 @@
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
-#include "clang/Analysis/Analyses/OSLog.h"
+#include "clang/AST/OSLog.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
@@ -93,11 +94,11 @@ static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V,
return V;
}
-/// Utility to insert an atomic instruction based on Instrinsic::ID
+/// Utility to insert an atomic instruction based on Intrinsic::ID
/// and the expression node.
-static Value *MakeBinaryAtomicValue(CodeGenFunction &CGF,
- llvm::AtomicRMWInst::BinOp Kind,
- const CallExpr *E) {
+static Value *MakeBinaryAtomicValue(
+ CodeGenFunction &CGF, llvm::AtomicRMWInst::BinOp Kind, const CallExpr *E,
+ AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent) {
QualType T = E->getType();
assert(E->getArg(0)->getType()->isPointerType());
assert(CGF.getContext().hasSameUnqualifiedType(T,
@@ -119,7 +120,7 @@ static Value *MakeBinaryAtomicValue(CodeGenFunction &CGF,
Args[1] = EmitToInt(CGF, Args[1], T, IntType);
llvm::Value *Result = CGF.Builder.CreateAtomicRMW(
- Kind, Args[0], Args[1], llvm::AtomicOrdering::SequentiallyConsistent);
+ Kind, Args[0], Args[1], Ordering);
return EmitFromInt(CGF, Result, T, ValueType);
}
@@ -151,7 +152,7 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
return RValue::get(MakeBinaryAtomicValue(CGF, Kind, E));
}
-/// Utility to insert an atomic instruction based Instrinsic::ID and
+/// Utility to insert an atomic instruction based Intrinsic::ID and
/// the expression node, where the return value is the result of the
/// operation.
static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF,
@@ -200,6 +201,9 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF,
/// cmpxchg result or the old value.
///
/// @returns result of cmpxchg, according to ReturnBool
+///
+/// Note: In order to lower Microsoft's _InterlockedCompareExchange* intrinsics
+/// invoke the function EmitAtomicCmpXchgForMSIntrin.
static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E,
bool ReturnBool) {
QualType T = ReturnBool ? E->getArg(1)->getType() : E->getType();
@@ -230,6 +234,72 @@ static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E,
ValueType);
}
+/// This function should be invoked to emit atomic cmpxchg for Microsoft's
+/// _InterlockedCompareExchange* intrinsics which have the following signature:
+/// T _InterlockedCompareExchange(T volatile *Destination,
+/// T Exchange,
+/// T Comparand);
+///
+/// Whereas the llvm 'cmpxchg' instruction has the following syntax:
+/// cmpxchg *Destination, Comparand, Exchange.
+/// So we need to swap Comparand and Exchange when invoking
+/// CreateAtomicCmpXchg. That is the reason we could not use the above utility
+/// function MakeAtomicCmpXchgValue since it expects the arguments to be
+/// already swapped.
+
+static
+Value *EmitAtomicCmpXchgForMSIntrin(CodeGenFunction &CGF, const CallExpr *E,
+ AtomicOrdering SuccessOrdering = AtomicOrdering::SequentiallyConsistent) {
+ assert(E->getArg(0)->getType()->isPointerType());
+ assert(CGF.getContext().hasSameUnqualifiedType(
+ E->getType(), E->getArg(0)->getType()->getPointeeType()));
+ assert(CGF.getContext().hasSameUnqualifiedType(E->getType(),
+ E->getArg(1)->getType()));
+ assert(CGF.getContext().hasSameUnqualifiedType(E->getType(),
+ E->getArg(2)->getType()));
+
+ auto *Destination = CGF.EmitScalarExpr(E->getArg(0));
+ auto *Comparand = CGF.EmitScalarExpr(E->getArg(2));
+ auto *Exchange = CGF.EmitScalarExpr(E->getArg(1));
+
+ // For Release ordering, the failure ordering should be Monotonic.
+ auto FailureOrdering = SuccessOrdering == AtomicOrdering::Release ?
+ AtomicOrdering::Monotonic :
+ SuccessOrdering;
+
+ auto *Result = CGF.Builder.CreateAtomicCmpXchg(
+ Destination, Comparand, Exchange,
+ SuccessOrdering, FailureOrdering);
+ Result->setVolatile(true);
+ return CGF.Builder.CreateExtractValue(Result, 0);
+}
+
+static Value *EmitAtomicIncrementValue(CodeGenFunction &CGF, const CallExpr *E,
+ AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent) {
+ assert(E->getArg(0)->getType()->isPointerType());
+
+ auto *IntTy = CGF.ConvertType(E->getType());
+ auto *Result = CGF.Builder.CreateAtomicRMW(
+ AtomicRMWInst::Add,
+ CGF.EmitScalarExpr(E->getArg(0)),
+ ConstantInt::get(IntTy, 1),
+ Ordering);
+ return CGF.Builder.CreateAdd(Result, ConstantInt::get(IntTy, 1));
+}
+
+static Value *EmitAtomicDecrementValue(CodeGenFunction &CGF, const CallExpr *E,
+ AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent) {
+ assert(E->getArg(0)->getType()->isPointerType());
+
+ auto *IntTy = CGF.ConvertType(E->getType());
+ auto *Result = CGF.Builder.CreateAtomicRMW(
+ AtomicRMWInst::Sub,
+ CGF.EmitScalarExpr(E->getArg(0)),
+ ConstantInt::get(IntTy, 1),
+ Ordering);
+ return CGF.Builder.CreateSub(Result, ConstantInt::get(IntTy, 1));
+}
+
// Emit a simple mangled intrinsic that has 1 argument and a return type
// matching the argument type.
static Value *emitUnaryBuiltin(CodeGenFunction &CGF,
@@ -316,7 +386,7 @@ static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD,
const CallExpr *E, llvm::Constant *calleeValue) {
- CGCallee callee = CGCallee::forDirect(calleeValue, FD);
+ CGCallee callee = CGCallee::forDirect(calleeValue, GlobalDecl(FD));
return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
}
@@ -461,7 +531,7 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
assert(DIter != LocalDeclMap.end());
return EmitLoadOfScalar(DIter->second, /*volatile=*/false,
- getContext().getSizeType(), E->getLocStart());
+ getContext().getSizeType(), E->getBeginLoc());
}
}
@@ -485,7 +555,7 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
}
namespace {
-/// A struct to generically desribe a bit test intrinsic.
+/// A struct to generically describe a bit test intrinsic.
struct BitTest {
enum ActionKind : uint8_t { TestOnly, Complement, Reset, Set };
enum InterlockingKind : uint8_t {
@@ -711,8 +781,11 @@ static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind,
} else {
Name = SJKind == MSVCSetJmpKind::_setjmp ? "_setjmp" : "_setjmpex";
Arg1Ty = CGF.Int8PtrTy;
- Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::frameaddress),
- llvm::ConstantInt::get(CGF.Int32Ty, 0));
+ if (CGF.getTarget().getTriple().getArch() == llvm::Triple::aarch64) {
+ Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::sponentry));
+ } else
+ Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::frameaddress),
+ llvm::ConstantInt::get(CGF.Int32Ty, 0));
}
// Mark the call site and declaration with ReturnsTwice.
@@ -745,6 +818,30 @@ enum class CodeGenFunction::MSVCIntrin {
_InterlockedIncrement,
_InterlockedOr,
_InterlockedXor,
+ _InterlockedExchangeAdd_acq,
+ _InterlockedExchangeAdd_rel,
+ _InterlockedExchangeAdd_nf,
+ _InterlockedExchange_acq,
+ _InterlockedExchange_rel,
+ _InterlockedExchange_nf,
+ _InterlockedCompareExchange_acq,
+ _InterlockedCompareExchange_rel,
+ _InterlockedCompareExchange_nf,
+ _InterlockedOr_acq,
+ _InterlockedOr_rel,
+ _InterlockedOr_nf,
+ _InterlockedXor_acq,
+ _InterlockedXor_rel,
+ _InterlockedXor_nf,
+ _InterlockedAnd_acq,
+ _InterlockedAnd_rel,
+ _InterlockedAnd_nf,
+ _InterlockedIncrement_acq,
+ _InterlockedIncrement_rel,
+ _InterlockedIncrement_nf,
+ _InterlockedDecrement_acq,
+ _InterlockedDecrement_rel,
+ _InterlockedDecrement_nf,
__fastfail,
};
@@ -811,25 +908,74 @@ Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID,
return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E);
case MSVCIntrin::_InterlockedXor:
return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E);
-
- case MSVCIntrin::_InterlockedDecrement: {
- llvm::Type *IntTy = ConvertType(E->getType());
- AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
- AtomicRMWInst::Sub,
- EmitScalarExpr(E->getArg(0)),
- ConstantInt::get(IntTy, 1),
- llvm::AtomicOrdering::SequentiallyConsistent);
- return Builder.CreateSub(RMWI, ConstantInt::get(IntTy, 1));
- }
- case MSVCIntrin::_InterlockedIncrement: {
- llvm::Type *IntTy = ConvertType(E->getType());
- AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
- AtomicRMWInst::Add,
- EmitScalarExpr(E->getArg(0)),
- ConstantInt::get(IntTy, 1),
- llvm::AtomicOrdering::SequentiallyConsistent);
- return Builder.CreateAdd(RMWI, ConstantInt::get(IntTy, 1));
- }
+ case MSVCIntrin::_InterlockedExchangeAdd_acq:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E,
+ AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedExchangeAdd_rel:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E,
+ AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedExchangeAdd_nf:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E,
+ AtomicOrdering::Monotonic);
+ case MSVCIntrin::_InterlockedExchange_acq:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E,
+ AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedExchange_rel:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E,
+ AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedExchange_nf:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E,
+ AtomicOrdering::Monotonic);
+ case MSVCIntrin::_InterlockedCompareExchange_acq:
+ return EmitAtomicCmpXchgForMSIntrin(*this, E, AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedCompareExchange_rel:
+ return EmitAtomicCmpXchgForMSIntrin(*this, E, AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedCompareExchange_nf:
+ return EmitAtomicCmpXchgForMSIntrin(*this, E, AtomicOrdering::Monotonic);
+ case MSVCIntrin::_InterlockedOr_acq:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E,
+ AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedOr_rel:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E,
+ AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedOr_nf:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E,
+ AtomicOrdering::Monotonic);
+ case MSVCIntrin::_InterlockedXor_acq:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E,
+ AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedXor_rel:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E,
+ AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedXor_nf:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E,
+ AtomicOrdering::Monotonic);
+ case MSVCIntrin::_InterlockedAnd_acq:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E,
+ AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedAnd_rel:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E,
+ AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedAnd_nf:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E,
+ AtomicOrdering::Monotonic);
+ case MSVCIntrin::_InterlockedIncrement_acq:
+ return EmitAtomicIncrementValue(*this, E, AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedIncrement_rel:
+ return EmitAtomicIncrementValue(*this, E, AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedIncrement_nf:
+ return EmitAtomicIncrementValue(*this, E, AtomicOrdering::Monotonic);
+ case MSVCIntrin::_InterlockedDecrement_acq:
+ return EmitAtomicDecrementValue(*this, E, AtomicOrdering::Acquire);
+ case MSVCIntrin::_InterlockedDecrement_rel:
+ return EmitAtomicDecrementValue(*this, E, AtomicOrdering::Release);
+ case MSVCIntrin::_InterlockedDecrement_nf:
+ return EmitAtomicDecrementValue(*this, E, AtomicOrdering::Monotonic);
+
+ case MSVCIntrin::_InterlockedDecrement:
+ return EmitAtomicDecrementValue(*this, E);
+ case MSVCIntrin::_InterlockedIncrement:
+ return EmitAtomicIncrementValue(*this, E);
case MSVCIntrin::__fastfail: {
// Request immediate process termination from the kernel. The instruction
@@ -923,35 +1069,42 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction(
if (llvm::Function *F = CGM.getModule().getFunction(Name))
return F;
+ llvm::SmallVector<QualType, 4> ArgTys;
llvm::SmallVector<ImplicitParamDecl, 4> Params;
Params.emplace_back(Ctx, nullptr, SourceLocation(), &Ctx.Idents.get("buffer"),
Ctx.VoidPtrTy, ImplicitParamDecl::Other);
+ ArgTys.emplace_back(Ctx.VoidPtrTy);
for (unsigned int I = 0, E = Layout.Items.size(); I < E; ++I) {
char Size = Layout.Items[I].getSizeByte();
if (!Size)
continue;
+ QualType ArgTy = getOSLogArgType(Ctx, Size);
Params.emplace_back(
Ctx, nullptr, SourceLocation(),
- &Ctx.Idents.get(std::string("arg") + llvm::to_string(I)),
- getOSLogArgType(Ctx, Size), ImplicitParamDecl::Other);
+ &Ctx.Idents.get(std::string("arg") + llvm::to_string(I)), ArgTy,
+ ImplicitParamDecl::Other);
+ ArgTys.emplace_back(ArgTy);
}
FunctionArgList Args;
for (auto &P : Params)
Args.push_back(&P);
+ QualType ReturnTy = Ctx.VoidTy;
+ QualType FuncionTy = Ctx.getFunctionType(ReturnTy, ArgTys, {});
+
// The helper function has linkonce_odr linkage to enable the linker to merge
// identical functions. To ensure the merging always happens, 'noinline' is
// attached to the function when compiling with -Oz.
const CGFunctionInfo &FI =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Args);
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, Args);
llvm::FunctionType *FuncTy = CGM.getTypes().GetFunctionType(FI);
llvm::Function *Fn = llvm::Function::Create(
FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, Name, &CGM.getModule());
Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.SetLLVMFunctionAttributes(nullptr, FI, Fn);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn);
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
// Attach 'noinline' at -Oz.
@@ -962,9 +1115,9 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction(
IdentifierInfo *II = &Ctx.Idents.get(Name);
FunctionDecl *FD = FunctionDecl::Create(
Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
- Ctx.VoidTy, nullptr, SC_PrivateExtern, false, false);
+ FuncionTy, nullptr, SC_PrivateExtern, false, false);
- StartFunction(FD, Ctx.VoidTy, Fn, FI, Args);
+ StartFunction(FD, ReturnTy, Fn, FI, Args);
// Create a scope with an artificial location for the body of this function.
auto AL = ApplyDebugLocation::CreateArtificial(*this);
@@ -1024,7 +1177,12 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) {
llvm::Value *ArgVal;
- if (const Expr *TheExpr = Item.getExpr()) {
+ if (Item.getKind() == analyze_os_log::OSLogBufferItem::MaskKind) {
+ uint64_t Val = 0;
+ for (unsigned I = 0, E = Item.getMaskType().size(); I < E; ++I)
+ Val |= ((uint64_t)Item.getMaskType()[I]) << I * 8;
+ ArgVal = llvm::Constant::getIntegerValue(Int64Ty, llvm::APInt(64, Val));
+ } else if (const Expr *TheExpr = Item.getExpr()) {
ArgVal = EmitScalarExpr(TheExpr, /*Ignore*/ false);
// Check if this is a retainable type.
@@ -1077,7 +1235,7 @@ static bool isSpecialMixedSignMultiply(unsigned BuiltinID,
WidthAndSignedness Op2Info,
WidthAndSignedness ResultInfo) {
return BuiltinID == Builtin::BI__builtin_mul_overflow &&
- Op1Info.Width == Op2Info.Width && Op1Info.Width >= ResultInfo.Width &&
+ std::max(Op1Info.Width, Op2Info.Width) >= ResultInfo.Width &&
Op1Info.Signed != Op2Info.Signed;
}
@@ -1098,11 +1256,20 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
const clang::Expr *UnsignedOp = Op1Info.Signed ? Op2 : Op1;
llvm::Value *Signed = CGF.EmitScalarExpr(SignedOp);
llvm::Value *Unsigned = CGF.EmitScalarExpr(UnsignedOp);
+ unsigned SignedOpWidth = Op1Info.Signed ? Op1Info.Width : Op2Info.Width;
+ unsigned UnsignedOpWidth = Op1Info.Signed ? Op2Info.Width : Op1Info.Width;
+
+ // One of the operands may be smaller than the other. If so, [s|z]ext it.
+ if (SignedOpWidth < UnsignedOpWidth)
+ Signed = CGF.Builder.CreateSExt(Signed, Unsigned->getType(), "op.sext");
+ if (UnsignedOpWidth < SignedOpWidth)
+ Unsigned = CGF.Builder.CreateZExt(Unsigned, Signed->getType(), "op.zext");
llvm::Type *OpTy = Signed->getType();
llvm::Value *Zero = llvm::Constant::getNullValue(OpTy);
Address ResultPtr = CGF.EmitPointerWithAlignment(ResultArg);
llvm::Type *ResTy = ResultPtr.getElementType();
+ unsigned OpWidth = std::max(Op1Info.Width, Op2Info.Width);
// Take the absolute value of the signed operand.
llvm::Value *IsNegative = CGF.Builder.CreateICmpSLT(Signed, Zero);
@@ -1120,8 +1287,8 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
if (ResultInfo.Signed) {
// Signed overflow occurs if the result is greater than INT_MAX or lesser
// than INT_MIN, i.e when |Result| > (INT_MAX + IsNegative).
- auto IntMax = llvm::APInt::getSignedMaxValue(ResultInfo.Width)
- .zextOrSelf(Op1Info.Width);
+ auto IntMax =
+ llvm::APInt::getSignedMaxValue(ResultInfo.Width).zextOrSelf(OpWidth);
llvm::Value *MaxResult =
CGF.Builder.CreateAdd(llvm::ConstantInt::get(OpTy, IntMax),
CGF.Builder.CreateZExt(IsNegative, OpTy));
@@ -1139,9 +1306,9 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
llvm::Value *Underflow = CGF.Builder.CreateAnd(
IsNegative, CGF.Builder.CreateIsNotNull(UnsignedResult));
Overflow = CGF.Builder.CreateOr(UnsignedOverflow, Underflow);
- if (ResultInfo.Width < Op1Info.Width) {
+ if (ResultInfo.Width < OpWidth) {
auto IntMax =
- llvm::APInt::getMaxValue(ResultInfo.Width).zext(Op1Info.Width);
+ llvm::APInt::getMaxValue(ResultInfo.Width).zext(OpWidth);
llvm::Value *TruncOverflow = CGF.Builder.CreateICmpUGT(
UnsignedResult, llvm::ConstantInt::get(OpTy, IntMax));
Overflow = CGF.Builder.CreateOr(Overflow, TruncOverflow);
@@ -1252,9 +1419,61 @@ static llvm::Value *dumpRecord(CodeGenFunction &CGF, QualType RType,
return Res;
}
-RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
- unsigned BuiltinID, const CallExpr *E,
+static bool
+TypeRequiresBuiltinLaunderImp(const ASTContext &Ctx, QualType Ty,
+ llvm::SmallPtrSetImpl<const Decl *> &Seen) {
+ if (const auto *Arr = Ctx.getAsArrayType(Ty))
+ Ty = Ctx.getBaseElementType(Arr);
+
+ const auto *Record = Ty->getAsCXXRecordDecl();
+ if (!Record)
+ return false;
+
+ // We've already checked this type, or are in the process of checking it.
+ if (!Seen.insert(Record).second)
+ return false;
+
+ assert(Record->hasDefinition() &&
+ "Incomplete types should already be diagnosed");
+
+ if (Record->isDynamicClass())
+ return true;
+
+ for (FieldDecl *F : Record->fields()) {
+ if (TypeRequiresBuiltinLaunderImp(Ctx, F->getType(), Seen))
+ return true;
+ }
+ return false;
+}
+
+/// Determine if the specified type requires laundering by checking if it is a
+/// dynamic class type or contains a subobject which is a dynamic class type.
+static bool TypeRequiresBuiltinLaunder(CodeGenModule &CGM, QualType Ty) {
+ if (!CGM.getCodeGenOpts().StrictVTablePointers)
+ return false;
+ llvm::SmallPtrSet<const Decl *, 16> Seen;
+ return TypeRequiresBuiltinLaunderImp(CGM.getContext(), Ty, Seen);
+}
+
+RValue CodeGenFunction::emitRotate(const CallExpr *E, bool IsRotateRight) {
+ llvm::Value *Src = EmitScalarExpr(E->getArg(0));
+ llvm::Value *ShiftAmt = EmitScalarExpr(E->getArg(1));
+
+ // The builtin's shift arg may have a different type than the source arg and
+ // result, but the LLVM intrinsic uses the same type for all values.
+ llvm::Type *Ty = Src->getType();
+ ShiftAmt = Builder.CreateIntCast(ShiftAmt, Ty, false);
+
+ // Rotate is a special case of LLVM funnel shift - 1st 2 args are the same.
+ unsigned IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl;
+ Value *F = CGM.getIntrinsic(IID, Ty);
+ return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt }));
+}
+
+RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
+ const CallExpr *E,
ReturnValueSlot ReturnValue) {
+ const FunctionDecl *FD = GD.getDecl()->getAsFunction();
// See if we can constant fold this builtin. If so, don't emit it at all.
Expr::EvalResult Result;
if (E->EvaluateAsRValue(Result, CGM.getContext()) &&
@@ -1537,6 +1756,26 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(ComplexVal.second);
}
+ case Builtin::BI__builtin_clrsb:
+ case Builtin::BI__builtin_clrsbl:
+ case Builtin::BI__builtin_clrsbll: {
+ // clrsb(x) -> clz(x < 0 ? ~x : x) - 1 or
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Zero = llvm::Constant::getNullValue(ArgType);
+ Value *IsNeg = Builder.CreateICmpSLT(ArgValue, Zero, "isneg");
+ Value *Inverse = Builder.CreateNot(ArgValue, "not");
+ Value *Tmp = Builder.CreateSelect(IsNeg, Inverse, ArgValue);
+ Value *Ctlz = Builder.CreateCall(F, {Tmp, Builder.getFalse()});
+ Value *Result = Builder.CreateSub(Ctlz, llvm::ConstantInt::get(ArgType, 1));
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return RValue::get(Result);
+ }
case Builtin::BI__builtin_ctzs:
case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl:
@@ -1609,6 +1848,21 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
"cast");
return RValue::get(Result);
}
+ case Builtin::BI__lzcnt16:
+ case Builtin::BI__lzcnt:
+ case Builtin::BI__lzcnt64: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return RValue::get(Result);
+ }
case Builtin::BI__popcnt16:
case Builtin::BI__popcnt:
case Builtin::BI__popcnt64:
@@ -1627,46 +1881,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
"cast");
return RValue::get(Result);
}
- case Builtin::BI_rotr8:
- case Builtin::BI_rotr16:
- case Builtin::BI_rotr:
- case Builtin::BI_lrotr:
- case Builtin::BI_rotr64: {
- Value *Val = EmitScalarExpr(E->getArg(0));
- Value *Shift = EmitScalarExpr(E->getArg(1));
-
- llvm::Type *ArgType = Val->getType();
- Shift = Builder.CreateIntCast(Shift, ArgType, false);
- unsigned ArgWidth = ArgType->getIntegerBitWidth();
- Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1);
-
- Value *RightShiftAmt = Builder.CreateAnd(Shift, Mask);
- Value *RightShifted = Builder.CreateLShr(Val, RightShiftAmt);
- Value *LeftShiftAmt = Builder.CreateAnd(Builder.CreateNeg(Shift), Mask);
- Value *LeftShifted = Builder.CreateShl(Val, LeftShiftAmt);
- Value *Result = Builder.CreateOr(LeftShifted, RightShifted);
- return RValue::get(Result);
- }
- case Builtin::BI_rotl8:
- case Builtin::BI_rotl16:
- case Builtin::BI_rotl:
- case Builtin::BI_lrotl:
- case Builtin::BI_rotl64: {
- Value *Val = EmitScalarExpr(E->getArg(0));
- Value *Shift = EmitScalarExpr(E->getArg(1));
-
- llvm::Type *ArgType = Val->getType();
- Shift = Builder.CreateIntCast(Shift, ArgType, false);
- unsigned ArgWidth = ArgType->getIntegerBitWidth();
- Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1);
-
- Value *LeftShiftAmt = Builder.CreateAnd(Shift, Mask);
- Value *LeftShifted = Builder.CreateShl(Val, LeftShiftAmt);
- Value *RightShiftAmt = Builder.CreateAnd(Builder.CreateNeg(Shift), Mask);
- Value *RightShifted = Builder.CreateLShr(Val, RightShiftAmt);
- Value *Result = Builder.CreateOr(LeftShifted, RightShifted);
- return RValue::get(Result);
- }
case Builtin::BI__builtin_unpredictable: {
// Always return the argument of __builtin_unpredictable. LLVM does not
// handle this builtin. Metadata for this builtin should be added directly
@@ -1690,15 +1904,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Result);
}
case Builtin::BI__builtin_assume_aligned: {
- Value *PtrValue = EmitScalarExpr(E->getArg(0));
+ const Expr *Ptr = E->getArg(0);
+ Value *PtrValue = EmitScalarExpr(Ptr);
Value *OffsetValue =
(E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : nullptr;
Value *AlignmentValue = EmitScalarExpr(E->getArg(1));
ConstantInt *AlignmentCI = cast<ConstantInt>(AlignmentValue);
- unsigned Alignment = (unsigned) AlignmentCI->getZExtValue();
+ unsigned Alignment = (unsigned)AlignmentCI->getZExtValue();
- EmitAlignmentAssumption(PtrValue, Alignment, OffsetValue);
+ EmitAlignmentAssumption(PtrValue, Ptr, /*The expr loc is sufficient.*/ SourceLocation(),
+ Alignment, OffsetValue);
return RValue::get(PtrValue);
}
case Builtin::BI__assume:
@@ -1721,6 +1937,48 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_bitreverse64: {
return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::bitreverse));
}
+ case Builtin::BI__builtin_rotateleft8:
+ case Builtin::BI__builtin_rotateleft16:
+ case Builtin::BI__builtin_rotateleft32:
+ case Builtin::BI__builtin_rotateleft64:
+ case Builtin::BI_rotl8: // Microsoft variants of rotate left
+ case Builtin::BI_rotl16:
+ case Builtin::BI_rotl:
+ case Builtin::BI_lrotl:
+ case Builtin::BI_rotl64:
+ return emitRotate(E, false);
+
+ case Builtin::BI__builtin_rotateright8:
+ case Builtin::BI__builtin_rotateright16:
+ case Builtin::BI__builtin_rotateright32:
+ case Builtin::BI__builtin_rotateright64:
+ case Builtin::BI_rotr8: // Microsoft variants of rotate right
+ case Builtin::BI_rotr16:
+ case Builtin::BI_rotr:
+ case Builtin::BI_lrotr:
+ case Builtin::BI_rotr64:
+ return emitRotate(E, true);
+
+ case Builtin::BI__builtin_constant_p: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ // At -O0, we don't perform inlining, so we don't need to delay the
+ // processing.
+ return RValue::get(ConstantInt::get(ResultType, 0));
+
+ const Expr *Arg = E->getArg(0);
+ QualType ArgType = Arg->getType();
+ if (!hasScalarEvaluationKind(ArgType) || ArgType->isFunctionType())
+ // We can only reason about scalar types.
+ return RValue::get(ConstantInt::get(ResultType, 0));
+
+ Value *ArgValue = EmitScalarExpr(Arg);
+ Value *F = CGM.getIntrinsic(Intrinsic::is_constant, ConvertType(ArgType));
+ Value *Result = Builder.CreateCall(F, ArgValue);
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/false);
+ return RValue::get(Result);
+ }
case Builtin::BI__builtin_object_size: {
unsigned Type =
E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue();
@@ -1985,10 +2243,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin___memcpy_chk: {
// fold __builtin_memcpy_chk(x, y, cst1, cst2) to memcpy iff cst1<=cst2.
- llvm::APSInt Size, DstSize;
- if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) ||
- !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext()))
+ Expr::EvalResult SizeResult, DstSizeResult;
+ if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) ||
+ !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext()))
break;
+ llvm::APSInt Size = SizeResult.Val.getInt();
+ llvm::APSInt DstSize = DstSizeResult.Val.getInt();
if (Size.ugt(DstSize))
break;
Address Dest = EmitPointerWithAlignment(E->getArg(0));
@@ -2009,10 +2269,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin___memmove_chk: {
// fold __builtin_memmove_chk(x, y, cst1, cst2) to memmove iff cst1<=cst2.
- llvm::APSInt Size, DstSize;
- if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) ||
- !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext()))
+ Expr::EvalResult SizeResult, DstSizeResult;
+ if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) ||
+ !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext()))
break;
+ llvm::APSInt Size = SizeResult.Val.getInt();
+ llvm::APSInt DstSize = DstSizeResult.Val.getInt();
if (Size.ugt(DstSize))
break;
Address Dest = EmitPointerWithAlignment(E->getArg(0));
@@ -2047,10 +2309,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__builtin___memset_chk: {
// fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
- llvm::APSInt Size, DstSize;
- if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) ||
- !E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext()))
+ Expr::EvalResult SizeResult, DstSizeResult;
+ if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) ||
+ !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext()))
break;
+ llvm::APSInt Size = SizeResult.Val.getInt();
+ llvm::APSInt DstSize = DstSizeResult.Val.getInt();
if (Size.ugt(DstSize))
break;
Address Dest = EmitPointerWithAlignment(E->getArg(0));
@@ -2258,6 +2522,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(nullptr);
}
+ case Builtin::BI__builtin_launder: {
+ const Expr *Arg = E->getArg(0);
+ QualType ArgTy = Arg->getType()->getPointeeType();
+ Value *Ptr = EmitScalarExpr(Arg);
+ if (TypeRequiresBuiltinLaunder(CGM, ArgTy))
+ Ptr = Builder.CreateLaunderInvariantGroup(Ptr);
+
+ return RValue::get(Ptr);
+ }
case Builtin::BI__sync_fetch_and_add:
case Builtin::BI__sync_fetch_and_sub:
case Builtin::BI__sync_fetch_and_or:
@@ -2952,7 +3225,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI_InterlockedExchangePointer:
return RValue::get(
EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E));
- case Builtin::BI_InterlockedCompareExchangePointer: {
+ case Builtin::BI_InterlockedCompareExchangePointer:
+ case Builtin::BI_InterlockedCompareExchangePointer_nf: {
llvm::Type *RTy;
llvm::IntegerType *IntType =
IntegerType::get(getLLVMContext(),
@@ -2969,10 +3243,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Value *Comparand =
Builder.CreatePtrToInt(EmitScalarExpr(E->getArg(2)), IntType);
- auto Result =
- Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange,
- AtomicOrdering::SequentiallyConsistent,
- AtomicOrdering::SequentiallyConsistent);
+ auto Ordering =
+ BuiltinID == Builtin::BI_InterlockedCompareExchangePointer_nf ?
+ AtomicOrdering::Monotonic : AtomicOrdering::SequentiallyConsistent;
+
+ auto Result = Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange,
+ Ordering, Ordering);
Result->setVolatile(true);
return RValue::get(Builder.CreateIntToPtr(Builder.CreateExtractValue(Result,
@@ -2982,16 +3258,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI_InterlockedCompareExchange8:
case Builtin::BI_InterlockedCompareExchange16:
case Builtin::BI_InterlockedCompareExchange:
- case Builtin::BI_InterlockedCompareExchange64: {
- AtomicCmpXchgInst *CXI = Builder.CreateAtomicCmpXchg(
- EmitScalarExpr(E->getArg(0)),
- EmitScalarExpr(E->getArg(2)),
- EmitScalarExpr(E->getArg(1)),
- AtomicOrdering::SequentiallyConsistent,
- AtomicOrdering::SequentiallyConsistent);
- CXI->setVolatile(true);
- return RValue::get(Builder.CreateExtractValue(CXI, 0));
- }
+ case Builtin::BI_InterlockedCompareExchange64:
+ return RValue::get(EmitAtomicCmpXchgForMSIntrin(*this, E));
case Builtin::BI_InterlockedIncrement16:
case Builtin::BI_InterlockedIncrement:
return RValue::get(
@@ -3337,24 +3605,31 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Create a temporary array to hold the sizes of local pointer arguments
// for the block. \p First is the position of the first size argument.
- auto CreateArrayForSizeVar = [=](unsigned First) {
- auto *AT = llvm::ArrayType::get(SizeTy, NumArgs - First);
- auto *Arr = Builder.CreateAlloca(AT);
- llvm::Value *Ptr;
+ auto CreateArrayForSizeVar = [=](unsigned First)
+ -> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> {
+ llvm::APInt ArraySize(32, NumArgs - First);
+ QualType SizeArrayTy = getContext().getConstantArrayType(
+ getContext().getSizeType(), ArraySize, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ auto Tmp = CreateMemTemp(SizeArrayTy, "block_sizes");
+ llvm::Value *TmpPtr = Tmp.getPointer();
+ llvm::Value *TmpSize = EmitLifetimeStart(
+ CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), TmpPtr);
+ llvm::Value *ElemPtr;
// Each of the following arguments specifies the size of the corresponding
// argument passed to the enqueued block.
auto *Zero = llvm::ConstantInt::get(IntTy, 0);
for (unsigned I = First; I < NumArgs; ++I) {
auto *Index = llvm::ConstantInt::get(IntTy, I - First);
- auto *GEP = Builder.CreateGEP(Arr, {Zero, Index});
+ auto *GEP = Builder.CreateGEP(TmpPtr, {Zero, Index});
if (I == First)
- Ptr = GEP;
+ ElemPtr = GEP;
auto *V =
Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(I)), SizeTy);
Builder.CreateAlignedStore(
V, GEP, CGM.getDataLayout().getPrefTypeAlignment(SizeTy));
}
- return Ptr;
+ return std::tie(ElemPtr, TmpSize, TmpPtr);
};
// Could have events and/or varargs.
@@ -3366,24 +3641,27 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Value *Kernel =
Builder.CreatePointerCast(Info.Kernel, GenericVoidPtrTy);
auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
- auto *PtrToSizeArray = CreateArrayForSizeVar(4);
+ llvm::Value *ElemPtr, *TmpSize, *TmpPtr;
+ std::tie(ElemPtr, TmpSize, TmpPtr) = CreateArrayForSizeVar(4);
// Create a vector of the arguments, as well as a constant value to
// express to the runtime the number of variadic arguments.
std::vector<llvm::Value *> Args = {
Queue, Flags, Range,
Kernel, Block, ConstantInt::get(IntTy, NumArgs - 4),
- PtrToSizeArray};
+ ElemPtr};
std::vector<llvm::Type *> ArgTys = {
- QueueTy, IntTy, RangeTy,
- GenericVoidPtrTy, GenericVoidPtrTy, IntTy,
- PtrToSizeArray->getType()};
+ QueueTy, IntTy, RangeTy, GenericVoidPtrTy,
+ GenericVoidPtrTy, IntTy, ElemPtr->getType()};
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
- return RValue::get(
- Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
- llvm::ArrayRef<llvm::Value *>(Args)));
+ auto Call =
+ RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+ llvm::ArrayRef<llvm::Value *>(Args)));
+ if (TmpSize)
+ EmitLifetimeEnd(TmpSize, TmpPtr);
+ return Call;
}
// Any calls now have event arguments passed.
if (NumArgs >= 7) {
@@ -3400,7 +3678,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Value *ClkEvent = EmitScalarExpr(E->getArg(5));
// Convert to generic address space.
EventList = Builder.CreatePointerCast(EventList, EventPtrTy);
- ClkEvent = Builder.CreatePointerCast(ClkEvent, EventPtrTy);
+ ClkEvent = ClkEvent->getType()->isIntegerTy()
+ ? Builder.CreateBitOrPointerCast(ClkEvent, EventPtrTy)
+ : Builder.CreatePointerCast(ClkEvent, EventPtrTy);
auto Info =
CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(6));
llvm::Value *Kernel =
@@ -3430,15 +3710,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_varargs";
- auto *PtrToSizeArray = CreateArrayForSizeVar(7);
- Args.push_back(PtrToSizeArray);
- ArgTys.push_back(PtrToSizeArray->getType());
+ llvm::Value *ElemPtr, *TmpSize, *TmpPtr;
+ std::tie(ElemPtr, TmpSize, TmpPtr) = CreateArrayForSizeVar(7);
+ Args.push_back(ElemPtr);
+ ArgTys.push_back(ElemPtr->getType());
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
- return RValue::get(
- Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
- llvm::ArrayRef<llvm::Value *>(Args)));
+ auto Call =
+ RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+ llvm::ArrayRef<llvm::Value *>(Args)));
+ if (TmpSize)
+ EmitLifetimeEnd(TmpSize, TmpPtr);
+ return Call;
}
LLVM_FALLTHROUGH;
}
@@ -3530,13 +3814,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_os_log_format:
return emitBuiltinOSLogFormat(*E);
- case Builtin::BI__builtin_os_log_format_buffer_size: {
- analyze_os_log::OSLogBufferLayout Layout;
- analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);
- return RValue::get(ConstantInt::get(ConvertType(E->getType()),
- Layout.size().getQuantity()));
- }
-
case Builtin::BI__xray_customevent: {
if (!ShouldXRayInstrumentFunction())
return RValue::getIgnored();
@@ -3703,6 +3980,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// we need to do a bit cast.
llvm::Type *PTy = FTy->getParamType(i);
if (PTy != ArgValue->getType()) {
+ // XXX - vector of pointers?
+ if (auto *PtrTy = dyn_cast<llvm::PointerType>(PTy)) {
+ if (PtrTy->getAddressSpace() !=
+ ArgValue->getType()->getPointerAddressSpace()) {
+ ArgValue = Builder.CreateAddrSpaceCast(
+ ArgValue,
+ ArgValue->getType()->getPointerTo(PtrTy->getAddressSpace()));
+ }
+ }
+
assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
"Must be able to losslessly bit cast to param");
ArgValue = Builder.CreateBitCast(ArgValue, PTy);
@@ -3719,6 +4006,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
RetTy = ConvertType(BuiltinRetType);
if (RetTy != V->getType()) {
+ // XXX - vector of pointers?
+ if (auto *PtrTy = dyn_cast<llvm::PointerType>(RetTy)) {
+ if (PtrTy->getAddressSpace() != V->getType()->getPointerAddressSpace()) {
+ V = Builder.CreateAddrSpaceCast(
+ V, V->getType()->getPointerTo(PtrTy->getAddressSpace()));
+ }
+ }
+
assert(V->getType()->canLosslesslyBitCastTo(RetTy) &&
"Must be able to losslessly bit cast result type");
V = Builder.CreateBitCast(V, RetTy);
@@ -4286,6 +4581,14 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP0(vextq_v),
NEONMAP0(vfma_v),
NEONMAP0(vfmaq_v),
+ NEONMAP1(vfmlal_high_v, aarch64_neon_fmlal2, 0),
+ NEONMAP1(vfmlal_low_v, aarch64_neon_fmlal, 0),
+ NEONMAP1(vfmlalq_high_v, aarch64_neon_fmlal2, 0),
+ NEONMAP1(vfmlalq_low_v, aarch64_neon_fmlal, 0),
+ NEONMAP1(vfmlsl_high_v, aarch64_neon_fmlsl2, 0),
+ NEONMAP1(vfmlsl_low_v, aarch64_neon_fmlsl, 0),
+ NEONMAP1(vfmlslq_high_v, aarch64_neon_fmlsl2, 0),
+ NEONMAP1(vfmlslq_low_v, aarch64_neon_fmlsl, 0),
NEONMAP2(vhadd_v, aarch64_neon_uhadd, aarch64_neon_shadd, Add1ArgType | UnsignedAlts),
NEONMAP2(vhaddq_v, aarch64_neon_uhadd, aarch64_neon_shadd, Add1ArgType | UnsignedAlts),
NEONMAP2(vhsub_v, aarch64_neon_uhsub, aarch64_neon_shsub, Add1ArgType | UnsignedAlts),
@@ -5259,6 +5562,34 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Int = Usgn ? LLVMIntrinsic : AltLLVMIntrinsic;
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vdot");
}
+ case NEON::BI__builtin_neon_vfmlal_low_v:
+ case NEON::BI__builtin_neon_vfmlalq_low_v: {
+ llvm::Type *InputTy =
+ llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
+ llvm::Type *Tys[2] = { Ty, InputTy };
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlal_low");
+ }
+ case NEON::BI__builtin_neon_vfmlsl_low_v:
+ case NEON::BI__builtin_neon_vfmlslq_low_v: {
+ llvm::Type *InputTy =
+ llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
+ llvm::Type *Tys[2] = { Ty, InputTy };
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlsl_low");
+ }
+ case NEON::BI__builtin_neon_vfmlal_high_v:
+ case NEON::BI__builtin_neon_vfmlalq_high_v: {
+ llvm::Type *InputTy =
+ llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
+ llvm::Type *Tys[2] = { Ty, InputTy };
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlal_high");
+ }
+ case NEON::BI__builtin_neon_vfmlsl_high_v:
+ case NEON::BI__builtin_neon_vfmlslq_high_v: {
+ llvm::Type *InputTy =
+ llvm::VectorType::get(HalfTy, Ty->getPrimitiveSizeInBits() / 16);
+ llvm::Type *Tys[2] = { Ty, InputTy };
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vfmlsl_high");
+ }
}
assert(Int && "Expected valid intrinsic number");
@@ -5506,10 +5837,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
llvm::FunctionType *FTy =
llvm::FunctionType::get(VoidTy, /*Variadic=*/false);
- APSInt Value;
- if (!E->getArg(0)->EvaluateAsInt(Value, CGM.getContext()))
+ Expr::EvalResult Result;
+ if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
llvm_unreachable("Sema will ensure that the parameter is constant");
+ llvm::APSInt Value = Result.Val.getInt();
uint64_t ZExtValue = Value.zextOrTrunc(IsThumb ? 16 : 32).getZExtValue();
llvm::InlineAsm *Emit =
@@ -5991,6 +6323,120 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E);
case ARM::BI_InterlockedIncrement64:
return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E);
+ case ARM::BI_InterlockedExchangeAdd8_acq:
+ case ARM::BI_InterlockedExchangeAdd16_acq:
+ case ARM::BI_InterlockedExchangeAdd_acq:
+ case ARM::BI_InterlockedExchangeAdd64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_acq, E);
+ case ARM::BI_InterlockedExchangeAdd8_rel:
+ case ARM::BI_InterlockedExchangeAdd16_rel:
+ case ARM::BI_InterlockedExchangeAdd_rel:
+ case ARM::BI_InterlockedExchangeAdd64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_rel, E);
+ case ARM::BI_InterlockedExchangeAdd8_nf:
+ case ARM::BI_InterlockedExchangeAdd16_nf:
+ case ARM::BI_InterlockedExchangeAdd_nf:
+ case ARM::BI_InterlockedExchangeAdd64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_nf, E);
+ case ARM::BI_InterlockedExchange8_acq:
+ case ARM::BI_InterlockedExchange16_acq:
+ case ARM::BI_InterlockedExchange_acq:
+ case ARM::BI_InterlockedExchange64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_acq, E);
+ case ARM::BI_InterlockedExchange8_rel:
+ case ARM::BI_InterlockedExchange16_rel:
+ case ARM::BI_InterlockedExchange_rel:
+ case ARM::BI_InterlockedExchange64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_rel, E);
+ case ARM::BI_InterlockedExchange8_nf:
+ case ARM::BI_InterlockedExchange16_nf:
+ case ARM::BI_InterlockedExchange_nf:
+ case ARM::BI_InterlockedExchange64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_nf, E);
+ case ARM::BI_InterlockedCompareExchange8_acq:
+ case ARM::BI_InterlockedCompareExchange16_acq:
+ case ARM::BI_InterlockedCompareExchange_acq:
+ case ARM::BI_InterlockedCompareExchange64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_acq, E);
+ case ARM::BI_InterlockedCompareExchange8_rel:
+ case ARM::BI_InterlockedCompareExchange16_rel:
+ case ARM::BI_InterlockedCompareExchange_rel:
+ case ARM::BI_InterlockedCompareExchange64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_rel, E);
+ case ARM::BI_InterlockedCompareExchange8_nf:
+ case ARM::BI_InterlockedCompareExchange16_nf:
+ case ARM::BI_InterlockedCompareExchange_nf:
+ case ARM::BI_InterlockedCompareExchange64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_nf, E);
+ case ARM::BI_InterlockedOr8_acq:
+ case ARM::BI_InterlockedOr16_acq:
+ case ARM::BI_InterlockedOr_acq:
+ case ARM::BI_InterlockedOr64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_acq, E);
+ case ARM::BI_InterlockedOr8_rel:
+ case ARM::BI_InterlockedOr16_rel:
+ case ARM::BI_InterlockedOr_rel:
+ case ARM::BI_InterlockedOr64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_rel, E);
+ case ARM::BI_InterlockedOr8_nf:
+ case ARM::BI_InterlockedOr16_nf:
+ case ARM::BI_InterlockedOr_nf:
+ case ARM::BI_InterlockedOr64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_nf, E);
+ case ARM::BI_InterlockedXor8_acq:
+ case ARM::BI_InterlockedXor16_acq:
+ case ARM::BI_InterlockedXor_acq:
+ case ARM::BI_InterlockedXor64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_acq, E);
+ case ARM::BI_InterlockedXor8_rel:
+ case ARM::BI_InterlockedXor16_rel:
+ case ARM::BI_InterlockedXor_rel:
+ case ARM::BI_InterlockedXor64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_rel, E);
+ case ARM::BI_InterlockedXor8_nf:
+ case ARM::BI_InterlockedXor16_nf:
+ case ARM::BI_InterlockedXor_nf:
+ case ARM::BI_InterlockedXor64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_nf, E);
+ case ARM::BI_InterlockedAnd8_acq:
+ case ARM::BI_InterlockedAnd16_acq:
+ case ARM::BI_InterlockedAnd_acq:
+ case ARM::BI_InterlockedAnd64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_acq, E);
+ case ARM::BI_InterlockedAnd8_rel:
+ case ARM::BI_InterlockedAnd16_rel:
+ case ARM::BI_InterlockedAnd_rel:
+ case ARM::BI_InterlockedAnd64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_rel, E);
+ case ARM::BI_InterlockedAnd8_nf:
+ case ARM::BI_InterlockedAnd16_nf:
+ case ARM::BI_InterlockedAnd_nf:
+ case ARM::BI_InterlockedAnd64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_nf, E);
+ case ARM::BI_InterlockedIncrement16_acq:
+ case ARM::BI_InterlockedIncrement_acq:
+ case ARM::BI_InterlockedIncrement64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_acq, E);
+ case ARM::BI_InterlockedIncrement16_rel:
+ case ARM::BI_InterlockedIncrement_rel:
+ case ARM::BI_InterlockedIncrement64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_rel, E);
+ case ARM::BI_InterlockedIncrement16_nf:
+ case ARM::BI_InterlockedIncrement_nf:
+ case ARM::BI_InterlockedIncrement64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_nf, E);
+ case ARM::BI_InterlockedDecrement16_acq:
+ case ARM::BI_InterlockedDecrement_acq:
+ case ARM::BI_InterlockedDecrement64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_acq, E);
+ case ARM::BI_InterlockedDecrement16_rel:
+ case ARM::BI_InterlockedDecrement_rel:
+ case ARM::BI_InterlockedDecrement64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_rel, E);
+ case ARM::BI_InterlockedDecrement16_nf:
+ case ARM::BI_InterlockedDecrement_nf:
+ case ARM::BI_InterlockedDecrement64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_nf, E);
}
// Get the last argument, which specifies the vector type.
@@ -6497,11 +6943,33 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F, {StoreVal, StoreAddr}, "stxr");
}
+ if (BuiltinID == AArch64::BI__getReg) {
+ Expr::EvalResult Result;
+ if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
+ llvm_unreachable("Sema will ensure that the parameter is constant");
+
+ llvm::APSInt Value = Result.Val.getInt();
+ LLVMContext &Context = CGM.getLLVMContext();
+ std::string Reg = Value == 31 ? "sp" : "x" + Value.toString(10);
+
+ llvm::Metadata *Ops[] = {llvm::MDString::get(Context, Reg)};
+ llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
+ llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
+
+ llvm::Value *F =
+ CGM.getIntrinsic(llvm::Intrinsic::read_register, {Int64Ty});
+ return Builder.CreateCall(F, Metadata);
+ }
+
if (BuiltinID == AArch64::BI__builtin_arm_clrex) {
Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex);
return Builder.CreateCall(F);
}
+ if (BuiltinID == AArch64::BI_ReadWriteBarrier)
+ return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
+ llvm::SyncScope::SingleThread);
+
// CRC32
Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic;
switch (BuiltinID) {
@@ -6564,6 +7032,48 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return EmitSpecialRegisterBuiltin(*this, E, RegisterType, ValueType, IsRead);
}
+ if (BuiltinID == AArch64::BI_ReadStatusReg ||
+ BuiltinID == AArch64::BI_WriteStatusReg) {
+ LLVMContext &Context = CGM.getLLVMContext();
+
+ unsigned SysReg =
+ E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
+
+ std::string SysRegStr;
+ llvm::raw_string_ostream(SysRegStr) <<
+ ((1 << 1) | ((SysReg >> 14) & 1)) << ":" <<
+ ((SysReg >> 11) & 7) << ":" <<
+ ((SysReg >> 7) & 15) << ":" <<
+ ((SysReg >> 3) & 15) << ":" <<
+ ( SysReg & 7);
+
+ llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) };
+ llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
+ llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
+
+ llvm::Type *RegisterType = Int64Ty;
+ llvm::Type *ValueType = Int32Ty;
+ llvm::Type *Types[] = { RegisterType };
+
+ if (BuiltinID == AArch64::BI_ReadStatusReg) {
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
+ llvm::Value *Call = Builder.CreateCall(F, Metadata);
+
+ return Builder.CreateTrunc(Call, ValueType);
+ }
+
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
+ llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
+ ArgValue = Builder.CreateZExt(ArgValue, RegisterType);
+
+ return Builder.CreateCall(F, { Metadata, ArgValue });
+ }
+
+ if (BuiltinID == AArch64::BI_AddressOfReturnAddress) {
+ llvm::Value *F = CGM.getIntrinsic(Intrinsic::addressofreturnaddress);
+ return Builder.CreateCall(F);
+ }
+
// Find out if any arguments are required to be integer constant
// expressions.
unsigned ICEArguments = 0;
@@ -6659,7 +7169,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvth_f16_u32:
case NEON::BI__builtin_neon_vcvth_f16_u64:
usgn = true;
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vcvth_f16_s16:
case NEON::BI__builtin_neon_vcvth_f16_s32:
case NEON::BI__builtin_neon_vcvth_f16_s64: {
@@ -6679,7 +7189,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vcvth_u16_f16:
usgn = true;
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vcvth_s16_f16: {
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
@@ -6689,7 +7199,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vcvth_u32_f16:
usgn = true;
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vcvth_s32_f16: {
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
@@ -6699,7 +7209,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vcvth_u64_f16:
usgn = true;
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case NEON::BI__builtin_neon_vcvth_s64_f16: {
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = Builder.CreateBitCast(Ops[0], HalfTy);
@@ -8414,6 +8924,129 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E);
case AArch64::BI_InterlockedIncrement64:
return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E);
+ case AArch64::BI_InterlockedExchangeAdd8_acq:
+ case AArch64::BI_InterlockedExchangeAdd16_acq:
+ case AArch64::BI_InterlockedExchangeAdd_acq:
+ case AArch64::BI_InterlockedExchangeAdd64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_acq, E);
+ case AArch64::BI_InterlockedExchangeAdd8_rel:
+ case AArch64::BI_InterlockedExchangeAdd16_rel:
+ case AArch64::BI_InterlockedExchangeAdd_rel:
+ case AArch64::BI_InterlockedExchangeAdd64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_rel, E);
+ case AArch64::BI_InterlockedExchangeAdd8_nf:
+ case AArch64::BI_InterlockedExchangeAdd16_nf:
+ case AArch64::BI_InterlockedExchangeAdd_nf:
+ case AArch64::BI_InterlockedExchangeAdd64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_nf, E);
+ case AArch64::BI_InterlockedExchange8_acq:
+ case AArch64::BI_InterlockedExchange16_acq:
+ case AArch64::BI_InterlockedExchange_acq:
+ case AArch64::BI_InterlockedExchange64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_acq, E);
+ case AArch64::BI_InterlockedExchange8_rel:
+ case AArch64::BI_InterlockedExchange16_rel:
+ case AArch64::BI_InterlockedExchange_rel:
+ case AArch64::BI_InterlockedExchange64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_rel, E);
+ case AArch64::BI_InterlockedExchange8_nf:
+ case AArch64::BI_InterlockedExchange16_nf:
+ case AArch64::BI_InterlockedExchange_nf:
+ case AArch64::BI_InterlockedExchange64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_nf, E);
+ case AArch64::BI_InterlockedCompareExchange8_acq:
+ case AArch64::BI_InterlockedCompareExchange16_acq:
+ case AArch64::BI_InterlockedCompareExchange_acq:
+ case AArch64::BI_InterlockedCompareExchange64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_acq, E);
+ case AArch64::BI_InterlockedCompareExchange8_rel:
+ case AArch64::BI_InterlockedCompareExchange16_rel:
+ case AArch64::BI_InterlockedCompareExchange_rel:
+ case AArch64::BI_InterlockedCompareExchange64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_rel, E);
+ case AArch64::BI_InterlockedCompareExchange8_nf:
+ case AArch64::BI_InterlockedCompareExchange16_nf:
+ case AArch64::BI_InterlockedCompareExchange_nf:
+ case AArch64::BI_InterlockedCompareExchange64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_nf, E);
+ case AArch64::BI_InterlockedOr8_acq:
+ case AArch64::BI_InterlockedOr16_acq:
+ case AArch64::BI_InterlockedOr_acq:
+ case AArch64::BI_InterlockedOr64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_acq, E);
+ case AArch64::BI_InterlockedOr8_rel:
+ case AArch64::BI_InterlockedOr16_rel:
+ case AArch64::BI_InterlockedOr_rel:
+ case AArch64::BI_InterlockedOr64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_rel, E);
+ case AArch64::BI_InterlockedOr8_nf:
+ case AArch64::BI_InterlockedOr16_nf:
+ case AArch64::BI_InterlockedOr_nf:
+ case AArch64::BI_InterlockedOr64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_nf, E);
+ case AArch64::BI_InterlockedXor8_acq:
+ case AArch64::BI_InterlockedXor16_acq:
+ case AArch64::BI_InterlockedXor_acq:
+ case AArch64::BI_InterlockedXor64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_acq, E);
+ case AArch64::BI_InterlockedXor8_rel:
+ case AArch64::BI_InterlockedXor16_rel:
+ case AArch64::BI_InterlockedXor_rel:
+ case AArch64::BI_InterlockedXor64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_rel, E);
+ case AArch64::BI_InterlockedXor8_nf:
+ case AArch64::BI_InterlockedXor16_nf:
+ case AArch64::BI_InterlockedXor_nf:
+ case AArch64::BI_InterlockedXor64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_nf, E);
+ case AArch64::BI_InterlockedAnd8_acq:
+ case AArch64::BI_InterlockedAnd16_acq:
+ case AArch64::BI_InterlockedAnd_acq:
+ case AArch64::BI_InterlockedAnd64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_acq, E);
+ case AArch64::BI_InterlockedAnd8_rel:
+ case AArch64::BI_InterlockedAnd16_rel:
+ case AArch64::BI_InterlockedAnd_rel:
+ case AArch64::BI_InterlockedAnd64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_rel, E);
+ case AArch64::BI_InterlockedAnd8_nf:
+ case AArch64::BI_InterlockedAnd16_nf:
+ case AArch64::BI_InterlockedAnd_nf:
+ case AArch64::BI_InterlockedAnd64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_nf, E);
+ case AArch64::BI_InterlockedIncrement16_acq:
+ case AArch64::BI_InterlockedIncrement_acq:
+ case AArch64::BI_InterlockedIncrement64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_acq, E);
+ case AArch64::BI_InterlockedIncrement16_rel:
+ case AArch64::BI_InterlockedIncrement_rel:
+ case AArch64::BI_InterlockedIncrement64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_rel, E);
+ case AArch64::BI_InterlockedIncrement16_nf:
+ case AArch64::BI_InterlockedIncrement_nf:
+ case AArch64::BI_InterlockedIncrement64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_nf, E);
+ case AArch64::BI_InterlockedDecrement16_acq:
+ case AArch64::BI_InterlockedDecrement_acq:
+ case AArch64::BI_InterlockedDecrement64_acq:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_acq, E);
+ case AArch64::BI_InterlockedDecrement16_rel:
+ case AArch64::BI_InterlockedDecrement_rel:
+ case AArch64::BI_InterlockedDecrement64_rel:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_rel, E);
+ case AArch64::BI_InterlockedDecrement16_nf:
+ case AArch64::BI_InterlockedDecrement_nf:
+ case AArch64::BI_InterlockedDecrement64_nf:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_nf, E);
+
+ case AArch64::BI_InterlockedAdd: {
+ Value *Arg0 = EmitScalarExpr(E->getArg(0));
+ Value *Arg1 = EmitScalarExpr(E->getArg(1));
+ AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
+ AtomicRMWInst::Add, Arg0, Arg1,
+ llvm::AtomicOrdering::SequentiallyConsistent);
+ return Builder.CreateAdd(RMWI, Arg1);
+ }
}
}
@@ -8524,8 +9157,9 @@ static Value *EmitX86CompressStore(CodeGenFunction &CGF,
}
static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc,
- unsigned NumElts, ArrayRef<Value *> Ops,
+ ArrayRef<Value *> Ops,
bool InvertLHS = false) {
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
Value *LHS = getMaskVecValue(CGF, Ops[0], NumElts);
Value *RHS = getMaskVecValue(CGF, Ops[1], NumElts);
@@ -8533,7 +9167,25 @@ static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc,
LHS = CGF.Builder.CreateNot(LHS);
return CGF.Builder.CreateBitCast(CGF.Builder.CreateBinOp(Opc, LHS, RHS),
- CGF.Builder.getIntNTy(std::max(NumElts, 8U)));
+ Ops[0]->getType());
+}
+
+static Value *EmitX86FunnelShift(CodeGenFunction &CGF, Value *Op0, Value *Op1,
+ Value *Amt, bool IsRight) {
+ llvm::Type *Ty = Op0->getType();
+
+ // Amount may be scalar immediate, in which case create a splat vector.
+ // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
+ // we only care about the lowest log2 bits anyway.
+ if (Amt->getType() != Ty) {
+ unsigned NumElts = Ty->getVectorNumElements();
+ Amt = CGF.Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
+ Amt = CGF.Builder.CreateVectorSplat(NumElts, Amt);
+ }
+
+ unsigned IID = IsRight ? Intrinsic::fshr : Intrinsic::fshl;
+ Value *F = CGF.CGM.getIntrinsic(IID, Ty);
+ return CGF.Builder.CreateCall(F, {Op0, Op1, Amt});
}
static Value *EmitX86Select(CodeGenFunction &CGF,
@@ -8855,6 +9507,17 @@ static Value *EmitX86SExtMask(CodeGenFunction &CGF, Value *Op,
return CGF.Builder.CreateSExt(Mask, DstTy, "vpmovm2");
}
+// Emit addition or subtraction with signed/unsigned saturation.
+static Value *EmitX86AddSubSatExpr(CodeGenFunction &CGF,
+ ArrayRef<Value *> Ops, bool IsSigned,
+ bool IsAddition) {
+ Intrinsic::ID IID =
+ IsSigned ? (IsAddition ? Intrinsic::sadd_sat : Intrinsic::ssub_sat)
+ : (IsAddition ? Intrinsic::uadd_sat : Intrinsic::usub_sat);
+ llvm::Function *F = CGF.CGM.getIntrinsic(IID, Ops[0]->getType());
+ return CGF.Builder.CreateCall(F, {Ops[0], Ops[1]});
+}
+
Value *CodeGenFunction::EmitX86CpuIs(const CallExpr *E) {
const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
@@ -8876,6 +9539,7 @@ Value *CodeGenFunction::EmitX86CpuIs(StringRef CPUStr) {
// Grab the global __cpu_model.
llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
+ cast<llvm::GlobalValue>(CpuModel)->setDSOLocal(true);
// Calculate the index needed to access the correct field based on the
// range. Also adjust the expected value.
@@ -8911,17 +9575,17 @@ Value *CodeGenFunction::EmitX86CpuSupports(const CallExpr *E) {
return EmitX86CpuSupports(FeatureStr);
}
-uint32_t
+uint64_t
CodeGenFunction::GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
// Processor features and mapping to processor feature value.
- uint32_t FeaturesMask = 0;
+ uint64_t FeaturesMask = 0;
for (const StringRef &FeatureStr : FeatureStrs) {
unsigned Feature =
StringSwitch<unsigned>(FeatureStr)
#define X86_FEATURE_COMPAT(VAL, ENUM, STR) .Case(STR, VAL)
#include "llvm/Support/X86TargetParser.def"
;
- FeaturesMask |= (1U << Feature);
+ FeaturesMask |= (1ULL << Feature);
}
return FeaturesMask;
}
@@ -8930,37 +9594,66 @@ Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) {
return EmitX86CpuSupports(GetX86CpuSupportsMask(FeatureStrs));
}
-llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint32_t FeaturesMask) {
- // Matching the struct layout from the compiler-rt/libgcc structure that is
- // filled in:
- // unsigned int __cpu_vendor;
- // unsigned int __cpu_type;
- // unsigned int __cpu_subtype;
- // unsigned int __cpu_features[1];
- llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,
- llvm::ArrayType::get(Int32Ty, 1));
+llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint64_t FeaturesMask) {
+ uint32_t Features1 = Lo_32(FeaturesMask);
+ uint32_t Features2 = Hi_32(FeaturesMask);
- // Grab the global __cpu_model.
- llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
+ Value *Result = Builder.getTrue();
+
+ if (Features1 != 0) {
+ // Matching the struct layout from the compiler-rt/libgcc structure that is
+ // filled in:
+ // unsigned int __cpu_vendor;
+ // unsigned int __cpu_type;
+ // unsigned int __cpu_subtype;
+ // unsigned int __cpu_features[1];
+ llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, Int32Ty,
+ llvm::ArrayType::get(Int32Ty, 1));
+
+ // Grab the global __cpu_model.
+ llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model");
+ cast<llvm::GlobalValue>(CpuModel)->setDSOLocal(true);
+
+ // Grab the first (0th) element from the field __cpu_features off of the
+ // global in the struct STy.
+ Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(3),
+ Builder.getInt32(0)};
+ Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
+ Value *Features =
+ Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4));
+
+ // Check the value of the bit corresponding to the feature requested.
+ Value *Mask = Builder.getInt32(Features1);
+ Value *Bitset = Builder.CreateAnd(Features, Mask);
+ Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);
+ Result = Builder.CreateAnd(Result, Cmp);
+ }
- // Grab the first (0th) element from the field __cpu_features off of the
- // global in the struct STy.
- Value *Idxs[] = {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 3),
- ConstantInt::get(Int32Ty, 0)};
- Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
- Value *Features =
- Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4));
-
- // Check the value of the bit corresponding to the feature requested.
- Value *Bitset = Builder.CreateAnd(
- Features, llvm::ConstantInt::get(Int32Ty, FeaturesMask));
- return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0));
+ if (Features2 != 0) {
+ llvm::Constant *CpuFeatures2 = CGM.CreateRuntimeVariable(Int32Ty,
+ "__cpu_features2");
+ cast<llvm::GlobalValue>(CpuFeatures2)->setDSOLocal(true);
+
+ Value *Features =
+ Builder.CreateAlignedLoad(CpuFeatures2, CharUnits::fromQuantity(4));
+
+ // Check the value of the bit corresponding to the feature requested.
+ Value *Mask = Builder.getInt32(Features2);
+ Value *Bitset = Builder.CreateAnd(Features, Mask);
+ Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);
+ Result = Builder.CreateAnd(Result, Cmp);
+ }
+
+ return Result;
}
Value *CodeGenFunction::EmitX86CpuInit() {
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy,
/*Variadic*/ false);
llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, "__cpu_indicator_init");
+ cast<llvm::GlobalValue>(Func)->setDSOLocal(true);
+ cast<llvm::GlobalValue>(Func)->setDLLStorageClass(
+ llvm::GlobalValue::DefaultStorageClass);
return Builder.CreateCall(Func);
}
@@ -9051,6 +9744,24 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__rdtsc: {
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_rdtsc));
}
+ case X86::BI__builtin_ia32_rdtscp: {
+ Value *Call = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_rdtscp));
+ Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1),
+ Ops[0]);
+ return Builder.CreateExtractValue(Call, 0);
+ }
+ case X86::BI__builtin_ia32_lzcnt_u16:
+ case X86::BI__builtin_ia32_lzcnt_u32:
+ case X86::BI__builtin_ia32_lzcnt_u64: {
+ Value *F = CGM.getIntrinsic(Intrinsic::ctlz, Ops[0]->getType());
+ return Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)});
+ }
+ case X86::BI__builtin_ia32_tzcnt_u16:
+ case X86::BI__builtin_ia32_tzcnt_u32:
+ case X86::BI__builtin_ia32_tzcnt_u64: {
+ Value *F = CGM.getIntrinsic(Intrinsic::cttz, Ops[0]->getType());
+ return Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)});
+ }
case X86::BI__builtin_ia32_undef128:
case X86::BI__builtin_ia32_undef256:
case X86::BI__builtin_ia32_undef512:
@@ -9822,6 +10533,50 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
"psrldq");
return Builder.CreateBitCast(SV, ResultType, "cast");
}
+ case X86::BI__builtin_ia32_kshiftliqi:
+ case X86::BI__builtin_ia32_kshiftlihi:
+ case X86::BI__builtin_ia32_kshiftlisi:
+ case X86::BI__builtin_ia32_kshiftlidi: {
+ unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
+
+ if (ShiftVal >= NumElts)
+ return llvm::Constant::getNullValue(Ops[0]->getType());
+
+ Value *In = getMaskVecValue(*this, Ops[0], NumElts);
+
+ uint32_t Indices[64];
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = NumElts + i - ShiftVal;
+
+ Value *Zero = llvm::Constant::getNullValue(In->getType());
+ Value *SV = Builder.CreateShuffleVector(Zero, In,
+ makeArrayRef(Indices, NumElts),
+ "kshiftl");
+ return Builder.CreateBitCast(SV, Ops[0]->getType());
+ }
+ case X86::BI__builtin_ia32_kshiftriqi:
+ case X86::BI__builtin_ia32_kshiftrihi:
+ case X86::BI__builtin_ia32_kshiftrisi:
+ case X86::BI__builtin_ia32_kshiftridi: {
+ unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[1])->getZExtValue() & 0xff;
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
+
+ if (ShiftVal >= NumElts)
+ return llvm::Constant::getNullValue(Ops[0]->getType());
+
+ Value *In = getMaskVecValue(*this, Ops[0], NumElts);
+
+ uint32_t Indices[64];
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = i + ShiftVal;
+
+ Value *Zero = llvm::Constant::getNullValue(In->getType());
+ Value *SV = Builder.CreateShuffleVector(In, Zero,
+ makeArrayRef(Indices, NumElts),
+ "kshiftr");
+ return Builder.CreateBitCast(SV, Ops[0]->getType());
+ }
case X86::BI__builtin_ia32_movnti:
case X86::BI__builtin_ia32_movnti64:
case X86::BI__builtin_ia32_movntsd:
@@ -9847,7 +10602,41 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
SI->setAlignment(1);
return SI;
}
-
+ // Rotate is a special case of funnel shift - 1st 2 args are the same.
+ case X86::BI__builtin_ia32_vprotb:
+ case X86::BI__builtin_ia32_vprotw:
+ case X86::BI__builtin_ia32_vprotd:
+ case X86::BI__builtin_ia32_vprotq:
+ case X86::BI__builtin_ia32_vprotbi:
+ case X86::BI__builtin_ia32_vprotwi:
+ case X86::BI__builtin_ia32_vprotdi:
+ case X86::BI__builtin_ia32_vprotqi:
+ case X86::BI__builtin_ia32_prold128:
+ case X86::BI__builtin_ia32_prold256:
+ case X86::BI__builtin_ia32_prold512:
+ case X86::BI__builtin_ia32_prolq128:
+ case X86::BI__builtin_ia32_prolq256:
+ case X86::BI__builtin_ia32_prolq512:
+ case X86::BI__builtin_ia32_prolvd128:
+ case X86::BI__builtin_ia32_prolvd256:
+ case X86::BI__builtin_ia32_prolvd512:
+ case X86::BI__builtin_ia32_prolvq128:
+ case X86::BI__builtin_ia32_prolvq256:
+ case X86::BI__builtin_ia32_prolvq512:
+ return EmitX86FunnelShift(*this, Ops[0], Ops[0], Ops[1], false);
+ case X86::BI__builtin_ia32_prord128:
+ case X86::BI__builtin_ia32_prord256:
+ case X86::BI__builtin_ia32_prord512:
+ case X86::BI__builtin_ia32_prorq128:
+ case X86::BI__builtin_ia32_prorq256:
+ case X86::BI__builtin_ia32_prorq512:
+ case X86::BI__builtin_ia32_prorvd128:
+ case X86::BI__builtin_ia32_prorvd256:
+ case X86::BI__builtin_ia32_prorvd512:
+ case X86::BI__builtin_ia32_prorvq128:
+ case X86::BI__builtin_ia32_prorvq256:
+ case X86::BI__builtin_ia32_prorvq512:
+ return EmitX86FunnelShift(*this, Ops[0], Ops[0], Ops[1], true);
case X86::BI__builtin_ia32_selectb_128:
case X86::BI__builtin_ia32_selectb_256:
case X86::BI__builtin_ia32_selectb_512:
@@ -9905,38 +10694,147 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return EmitX86MaskedCompare(*this, CC, false, Ops);
}
+ case X86::BI__builtin_ia32_kortestcqi:
case X86::BI__builtin_ia32_kortestchi:
- case X86::BI__builtin_ia32_kortestzhi: {
- Value *Or = EmitX86MaskLogic(*this, Instruction::Or, 16, Ops);
- Value *C;
- if (BuiltinID == X86::BI__builtin_ia32_kortestchi)
- C = llvm::Constant::getAllOnesValue(Builder.getInt16Ty());
- else
- C = llvm::Constant::getNullValue(Builder.getInt16Ty());
+ case X86::BI__builtin_ia32_kortestcsi:
+ case X86::BI__builtin_ia32_kortestcdi: {
+ Value *Or = EmitX86MaskLogic(*this, Instruction::Or, Ops);
+ Value *C = llvm::Constant::getAllOnesValue(Ops[0]->getType());
Value *Cmp = Builder.CreateICmpEQ(Or, C);
return Builder.CreateZExt(Cmp, ConvertType(E->getType()));
}
+ case X86::BI__builtin_ia32_kortestzqi:
+ case X86::BI__builtin_ia32_kortestzhi:
+ case X86::BI__builtin_ia32_kortestzsi:
+ case X86::BI__builtin_ia32_kortestzdi: {
+ Value *Or = EmitX86MaskLogic(*this, Instruction::Or, Ops);
+ Value *C = llvm::Constant::getNullValue(Ops[0]->getType());
+ Value *Cmp = Builder.CreateICmpEQ(Or, C);
+ return Builder.CreateZExt(Cmp, ConvertType(E->getType()));
+ }
+
+ case X86::BI__builtin_ia32_ktestcqi:
+ case X86::BI__builtin_ia32_ktestzqi:
+ case X86::BI__builtin_ia32_ktestchi:
+ case X86::BI__builtin_ia32_ktestzhi:
+ case X86::BI__builtin_ia32_ktestcsi:
+ case X86::BI__builtin_ia32_ktestzsi:
+ case X86::BI__builtin_ia32_ktestcdi:
+ case X86::BI__builtin_ia32_ktestzdi: {
+ Intrinsic::ID IID;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ case X86::BI__builtin_ia32_ktestcqi:
+ IID = Intrinsic::x86_avx512_ktestc_b;
+ break;
+ case X86::BI__builtin_ia32_ktestzqi:
+ IID = Intrinsic::x86_avx512_ktestz_b;
+ break;
+ case X86::BI__builtin_ia32_ktestchi:
+ IID = Intrinsic::x86_avx512_ktestc_w;
+ break;
+ case X86::BI__builtin_ia32_ktestzhi:
+ IID = Intrinsic::x86_avx512_ktestz_w;
+ break;
+ case X86::BI__builtin_ia32_ktestcsi:
+ IID = Intrinsic::x86_avx512_ktestc_d;
+ break;
+ case X86::BI__builtin_ia32_ktestzsi:
+ IID = Intrinsic::x86_avx512_ktestz_d;
+ break;
+ case X86::BI__builtin_ia32_ktestcdi:
+ IID = Intrinsic::x86_avx512_ktestc_q;
+ break;
+ case X86::BI__builtin_ia32_ktestzdi:
+ IID = Intrinsic::x86_avx512_ktestz_q;
+ break;
+ }
+
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
+ Value *LHS = getMaskVecValue(*this, Ops[0], NumElts);
+ Value *RHS = getMaskVecValue(*this, Ops[1], NumElts);
+ Function *Intr = CGM.getIntrinsic(IID);
+ return Builder.CreateCall(Intr, {LHS, RHS});
+ }
+ case X86::BI__builtin_ia32_kaddqi:
+ case X86::BI__builtin_ia32_kaddhi:
+ case X86::BI__builtin_ia32_kaddsi:
+ case X86::BI__builtin_ia32_kadddi: {
+ Intrinsic::ID IID;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ case X86::BI__builtin_ia32_kaddqi:
+ IID = Intrinsic::x86_avx512_kadd_b;
+ break;
+ case X86::BI__builtin_ia32_kaddhi:
+ IID = Intrinsic::x86_avx512_kadd_w;
+ break;
+ case X86::BI__builtin_ia32_kaddsi:
+ IID = Intrinsic::x86_avx512_kadd_d;
+ break;
+ case X86::BI__builtin_ia32_kadddi:
+ IID = Intrinsic::x86_avx512_kadd_q;
+ break;
+ }
+
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
+ Value *LHS = getMaskVecValue(*this, Ops[0], NumElts);
+ Value *RHS = getMaskVecValue(*this, Ops[1], NumElts);
+ Function *Intr = CGM.getIntrinsic(IID);
+ Value *Res = Builder.CreateCall(Intr, {LHS, RHS});
+ return Builder.CreateBitCast(Res, Ops[0]->getType());
+ }
+ case X86::BI__builtin_ia32_kandqi:
case X86::BI__builtin_ia32_kandhi:
- return EmitX86MaskLogic(*this, Instruction::And, 16, Ops);
+ case X86::BI__builtin_ia32_kandsi:
+ case X86::BI__builtin_ia32_kanddi:
+ return EmitX86MaskLogic(*this, Instruction::And, Ops);
+ case X86::BI__builtin_ia32_kandnqi:
case X86::BI__builtin_ia32_kandnhi:
- return EmitX86MaskLogic(*this, Instruction::And, 16, Ops, true);
+ case X86::BI__builtin_ia32_kandnsi:
+ case X86::BI__builtin_ia32_kandndi:
+ return EmitX86MaskLogic(*this, Instruction::And, Ops, true);
+ case X86::BI__builtin_ia32_korqi:
case X86::BI__builtin_ia32_korhi:
- return EmitX86MaskLogic(*this, Instruction::Or, 16, Ops);
+ case X86::BI__builtin_ia32_korsi:
+ case X86::BI__builtin_ia32_kordi:
+ return EmitX86MaskLogic(*this, Instruction::Or, Ops);
+ case X86::BI__builtin_ia32_kxnorqi:
case X86::BI__builtin_ia32_kxnorhi:
- return EmitX86MaskLogic(*this, Instruction::Xor, 16, Ops, true);
+ case X86::BI__builtin_ia32_kxnorsi:
+ case X86::BI__builtin_ia32_kxnordi:
+ return EmitX86MaskLogic(*this, Instruction::Xor, Ops, true);
+ case X86::BI__builtin_ia32_kxorqi:
case X86::BI__builtin_ia32_kxorhi:
- return EmitX86MaskLogic(*this, Instruction::Xor, 16, Ops);
- case X86::BI__builtin_ia32_knothi: {
- Ops[0] = getMaskVecValue(*this, Ops[0], 16);
- return Builder.CreateBitCast(Builder.CreateNot(Ops[0]),
- Builder.getInt16Ty());
+ case X86::BI__builtin_ia32_kxorsi:
+ case X86::BI__builtin_ia32_kxordi:
+ return EmitX86MaskLogic(*this, Instruction::Xor, Ops);
+ case X86::BI__builtin_ia32_knotqi:
+ case X86::BI__builtin_ia32_knothi:
+ case X86::BI__builtin_ia32_knotsi:
+ case X86::BI__builtin_ia32_knotdi: {
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
+ Value *Res = getMaskVecValue(*this, Ops[0], NumElts);
+ return Builder.CreateBitCast(Builder.CreateNot(Res),
+ Ops[0]->getType());
+ }
+ case X86::BI__builtin_ia32_kmovb:
+ case X86::BI__builtin_ia32_kmovw:
+ case X86::BI__builtin_ia32_kmovd:
+ case X86::BI__builtin_ia32_kmovq: {
+ // Bitcast to vXi1 type and then back to integer. This gets the mask
+ // register type into the IR, but might be optimized out depending on
+ // what's around it.
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
+ Value *Res = getMaskVecValue(*this, Ops[0], NumElts);
+ return Builder.CreateBitCast(Res, Ops[0]->getType());
}
case X86::BI__builtin_ia32_kunpckdi:
case X86::BI__builtin_ia32_kunpcksi:
case X86::BI__builtin_ia32_kunpckhi: {
- unsigned NumElts = Ops[0]->getType()->getScalarSizeInBits();
+ unsigned NumElts = Ops[0]->getType()->getIntegerBitWidth();
Value *LHS = getMaskVecValue(*this, Ops[0], NumElts);
Value *RHS = getMaskVecValue(*this, Ops[1], NumElts);
uint32_t Indices[64];
@@ -10103,6 +11001,52 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_pternlogq256_maskz:
return EmitX86Ternlog(*this, /*ZeroMask*/true, Ops);
+ case X86::BI__builtin_ia32_vpshldd128:
+ case X86::BI__builtin_ia32_vpshldd256:
+ case X86::BI__builtin_ia32_vpshldd512:
+ case X86::BI__builtin_ia32_vpshldq128:
+ case X86::BI__builtin_ia32_vpshldq256:
+ case X86::BI__builtin_ia32_vpshldq512:
+ case X86::BI__builtin_ia32_vpshldw128:
+ case X86::BI__builtin_ia32_vpshldw256:
+ case X86::BI__builtin_ia32_vpshldw512:
+ return EmitX86FunnelShift(*this, Ops[0], Ops[1], Ops[2], false);
+
+ case X86::BI__builtin_ia32_vpshrdd128:
+ case X86::BI__builtin_ia32_vpshrdd256:
+ case X86::BI__builtin_ia32_vpshrdd512:
+ case X86::BI__builtin_ia32_vpshrdq128:
+ case X86::BI__builtin_ia32_vpshrdq256:
+ case X86::BI__builtin_ia32_vpshrdq512:
+ case X86::BI__builtin_ia32_vpshrdw128:
+ case X86::BI__builtin_ia32_vpshrdw256:
+ case X86::BI__builtin_ia32_vpshrdw512:
+ // Ops 0 and 1 are swapped.
+ return EmitX86FunnelShift(*this, Ops[1], Ops[0], Ops[2], true);
+
+ case X86::BI__builtin_ia32_vpshldvd128:
+ case X86::BI__builtin_ia32_vpshldvd256:
+ case X86::BI__builtin_ia32_vpshldvd512:
+ case X86::BI__builtin_ia32_vpshldvq128:
+ case X86::BI__builtin_ia32_vpshldvq256:
+ case X86::BI__builtin_ia32_vpshldvq512:
+ case X86::BI__builtin_ia32_vpshldvw128:
+ case X86::BI__builtin_ia32_vpshldvw256:
+ case X86::BI__builtin_ia32_vpshldvw512:
+ return EmitX86FunnelShift(*this, Ops[0], Ops[1], Ops[2], false);
+
+ case X86::BI__builtin_ia32_vpshrdvd128:
+ case X86::BI__builtin_ia32_vpshrdvd256:
+ case X86::BI__builtin_ia32_vpshrdvd512:
+ case X86::BI__builtin_ia32_vpshrdvq128:
+ case X86::BI__builtin_ia32_vpshrdvq256:
+ case X86::BI__builtin_ia32_vpshrdvq512:
+ case X86::BI__builtin_ia32_vpshrdvw128:
+ case X86::BI__builtin_ia32_vpshrdvw256:
+ case X86::BI__builtin_ia32_vpshrdvw512:
+ // Ops 0 and 1 are swapped.
+ return EmitX86FunnelShift(*this, Ops[1], Ops[0], Ops[2], true);
+
// 3DNow!
case X86::BI__builtin_ia32_pswapdsf:
case X86::BI__builtin_ia32_pswapdsi: {
@@ -10145,6 +11089,33 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Ops[0]);
return Builder.CreateExtractValue(Call, 1);
}
+ case X86::BI__builtin_ia32_addcarryx_u32:
+ case X86::BI__builtin_ia32_addcarryx_u64:
+ case X86::BI__builtin_ia32_subborrow_u32:
+ case X86::BI__builtin_ia32_subborrow_u64: {
+ Intrinsic::ID IID;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ case X86::BI__builtin_ia32_addcarryx_u32:
+ IID = Intrinsic::x86_addcarry_32;
+ break;
+ case X86::BI__builtin_ia32_addcarryx_u64:
+ IID = Intrinsic::x86_addcarry_64;
+ break;
+ case X86::BI__builtin_ia32_subborrow_u32:
+ IID = Intrinsic::x86_subborrow_32;
+ break;
+ case X86::BI__builtin_ia32_subborrow_u64:
+ IID = Intrinsic::x86_subborrow_64;
+ break;
+ }
+
+ Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID),
+ { Ops[0], Ops[1], Ops[2] });
+ Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1),
+ Ops[3]);
+ return Builder.CreateExtractValue(Call, 0);
+ }
case X86::BI__builtin_ia32_fpclassps128_mask:
case X86::BI__builtin_ia32_fpclassps256_mask:
@@ -10183,6 +11154,51 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return EmitX86MaskedCompareResult(*this, Fpclass, NumElts, MaskIn);
}
+ case X86::BI__builtin_ia32_vpmultishiftqb128:
+ case X86::BI__builtin_ia32_vpmultishiftqb256:
+ case X86::BI__builtin_ia32_vpmultishiftqb512: {
+ Intrinsic::ID ID;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ case X86::BI__builtin_ia32_vpmultishiftqb128:
+ ID = Intrinsic::x86_avx512_pmultishift_qb_128;
+ break;
+ case X86::BI__builtin_ia32_vpmultishiftqb256:
+ ID = Intrinsic::x86_avx512_pmultishift_qb_256;
+ break;
+ case X86::BI__builtin_ia32_vpmultishiftqb512:
+ ID = Intrinsic::x86_avx512_pmultishift_qb_512;
+ break;
+ }
+
+ return Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
+ }
+
+ case X86::BI__builtin_ia32_vpshufbitqmb128_mask:
+ case X86::BI__builtin_ia32_vpshufbitqmb256_mask:
+ case X86::BI__builtin_ia32_vpshufbitqmb512_mask: {
+ unsigned NumElts = Ops[0]->getType()->getVectorNumElements();
+ Value *MaskIn = Ops[2];
+ Ops.erase(&Ops[2]);
+
+ Intrinsic::ID ID;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ case X86::BI__builtin_ia32_vpshufbitqmb128_mask:
+ ID = Intrinsic::x86_avx512_vpshufbitqmb_128;
+ break;
+ case X86::BI__builtin_ia32_vpshufbitqmb256_mask:
+ ID = Intrinsic::x86_avx512_vpshufbitqmb_256;
+ break;
+ case X86::BI__builtin_ia32_vpshufbitqmb512_mask:
+ ID = Intrinsic::x86_avx512_vpshufbitqmb_512;
+ break;
+ }
+
+ Value *Shufbit = Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
+ return EmitX86MaskedCompareResult(*this, Shufbit, NumElts, MaskIn);
+ }
+
// packed comparison intrinsics
case X86::BI__builtin_ia32_cmpeqps:
case X86::BI__builtin_ia32_cmpeqpd:
@@ -10361,6 +11377,27 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
llvm::SyncScope::System);
}
+ case X86::BI__shiftleft128:
+ case X86::BI__shiftright128: {
+ // FIXME: Once fshl/fshr no longer add an unneeded and and cmov, do this:
+ // llvm::Function *F = CGM.getIntrinsic(
+ // BuiltinID == X86::BI__shiftleft128 ? Intrinsic::fshl : Intrinsic::fshr,
+ // Int64Ty);
+ // Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
+ // return Builder.CreateCall(F, Ops);
+ llvm::Type *Int128Ty = Builder.getInt128Ty();
+ Value *Val = Builder.CreateOr(
+ Builder.CreateShl(Builder.CreateZExt(Ops[1], Int128Ty), 64),
+ Builder.CreateZExt(Ops[0], Int128Ty));
+ Value *Amt = Builder.CreateAnd(Builder.CreateZExt(Ops[2], Int128Ty),
+ llvm::ConstantInt::get(Int128Ty, 0x3f));
+ Value *Res;
+ if (BuiltinID == X86::BI__shiftleft128)
+ Res = Builder.CreateLShr(Builder.CreateShl(Val, Amt), 64);
+ else
+ Res = Builder.CreateLShr(Val, Amt);
+ return Builder.CreateTrunc(Res, Int64Ty);
+ }
case X86::BI_ReadWriteBarrier:
case X86::BI_ReadBarrier:
case X86::BI_WriteBarrier: {
@@ -10401,14 +11438,11 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
llvm::Type *Int128PtrTy = Int128Ty->getPointerTo();
Value *Destination =
- Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int128PtrTy);
- Value *ExchangeHigh128 =
- Builder.CreateZExt(EmitScalarExpr(E->getArg(1)), Int128Ty);
- Value *ExchangeLow128 =
- Builder.CreateZExt(EmitScalarExpr(E->getArg(2)), Int128Ty);
- Address ComparandResult(
- Builder.CreateBitCast(EmitScalarExpr(E->getArg(3)), Int128PtrTy),
- getContext().toCharUnitsFromBits(128));
+ Builder.CreateBitCast(Ops[0], Int128PtrTy);
+ Value *ExchangeHigh128 = Builder.CreateZExt(Ops[1], Int128Ty);
+ Value *ExchangeLow128 = Builder.CreateZExt(Ops[2], Int128Ty);
+ Address ComparandResult(Builder.CreateBitCast(Ops[3], Int128PtrTy),
+ getContext().toCharUnitsFromBits(128));
Value *Exchange = Builder.CreateOr(
Builder.CreateShl(ExchangeHigh128, 64, "", false, false),
@@ -10459,8 +11493,8 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__readfsdword:
case X86::BI__readfsqword: {
llvm::Type *IntTy = ConvertType(E->getType());
- Value *Ptr = Builder.CreateIntToPtr(EmitScalarExpr(E->getArg(0)),
- llvm::PointerType::get(IntTy, 257));
+ Value *Ptr =
+ Builder.CreateIntToPtr(Ops[0], llvm::PointerType::get(IntTy, 257));
LoadInst *Load = Builder.CreateAlignedLoad(
IntTy, Ptr, getContext().getTypeAlignInChars(E->getType()));
Load->setVolatile(true);
@@ -10471,17 +11505,44 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__readgsdword:
case X86::BI__readgsqword: {
llvm::Type *IntTy = ConvertType(E->getType());
- Value *Ptr = Builder.CreateIntToPtr(EmitScalarExpr(E->getArg(0)),
- llvm::PointerType::get(IntTy, 256));
+ Value *Ptr =
+ Builder.CreateIntToPtr(Ops[0], llvm::PointerType::get(IntTy, 256));
LoadInst *Load = Builder.CreateAlignedLoad(
IntTy, Ptr, getContext().getTypeAlignInChars(E->getType()));
Load->setVolatile(true);
return Load;
}
+ case X86::BI__builtin_ia32_paddsb512:
+ case X86::BI__builtin_ia32_paddsw512:
+ case X86::BI__builtin_ia32_paddsb256:
+ case X86::BI__builtin_ia32_paddsw256:
+ case X86::BI__builtin_ia32_paddsb128:
+ case X86::BI__builtin_ia32_paddsw128:
+ return EmitX86AddSubSatExpr(*this, Ops, true, true);
+ case X86::BI__builtin_ia32_paddusb512:
+ case X86::BI__builtin_ia32_paddusw512:
+ case X86::BI__builtin_ia32_paddusb256:
+ case X86::BI__builtin_ia32_paddusw256:
+ case X86::BI__builtin_ia32_paddusb128:
+ case X86::BI__builtin_ia32_paddusw128:
+ return EmitX86AddSubSatExpr(*this, Ops, false, true);
+ case X86::BI__builtin_ia32_psubsb512:
+ case X86::BI__builtin_ia32_psubsw512:
+ case X86::BI__builtin_ia32_psubsb256:
+ case X86::BI__builtin_ia32_psubsw256:
+ case X86::BI__builtin_ia32_psubsb128:
+ case X86::BI__builtin_ia32_psubsw128:
+ return EmitX86AddSubSatExpr(*this, Ops, true, false);
+ case X86::BI__builtin_ia32_psubusb512:
+ case X86::BI__builtin_ia32_psubusw512:
+ case X86::BI__builtin_ia32_psubusb256:
+ case X86::BI__builtin_ia32_psubusw256:
+ case X86::BI__builtin_ia32_psubusb128:
+ case X86::BI__builtin_ia32_psubusw128:
+ return EmitX86AddSubSatExpr(*this, Ops, false, false);
}
}
-
Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
SmallVector<Value*, 4> Ops;
@@ -10901,6 +11962,28 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
auto RetTy = ConvertType(BIRetType);
return Builder.CreateBitCast(ShuffleCall, RetTy);
}
+
+ case PPC::BI__builtin_pack_vector_int128: {
+ bool isLittleEndian = getTarget().isLittleEndian();
+ Value *UndefValue =
+ llvm::UndefValue::get(llvm::VectorType::get(Ops[0]->getType(), 2));
+ Value *Res = Builder.CreateInsertElement(
+ UndefValue, Ops[0], (uint64_t)(isLittleEndian ? 1 : 0));
+ Res = Builder.CreateInsertElement(Res, Ops[1],
+ (uint64_t)(isLittleEndian ? 0 : 1));
+ return Builder.CreateBitCast(Res, ConvertType(E->getType()));
+ }
+
+ case PPC::BI__builtin_unpack_vector_int128: {
+ ConstantInt *Index = cast<ConstantInt>(Ops[1]);
+ Value *Unpacked = Builder.CreateBitCast(
+ Ops[0], llvm::VectorType::get(ConvertType(E->getType()), 2));
+
+ if (getTarget().isLittleEndian())
+ Index = ConstantInt::get(Index->getType(), 1 - Index->getZExtValue());
+
+ return Builder.CreateExtractElement(Unpacked, Index);
+ }
}
}
@@ -10948,12 +12031,16 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_ds_swizzle:
return emitBinaryBuiltin(*this, E, Intrinsic::amdgcn_ds_swizzle);
- case AMDGPU::BI__builtin_amdgcn_mov_dpp: {
- llvm::SmallVector<llvm::Value *, 5> Args;
- for (unsigned I = 0; I != 5; ++I)
+ case AMDGPU::BI__builtin_amdgcn_mov_dpp:
+ case AMDGPU::BI__builtin_amdgcn_update_dpp: {
+ llvm::SmallVector<llvm::Value *, 6> Args;
+ for (unsigned I = 0; I != E->getNumArgs(); ++I)
Args.push_back(EmitScalarExpr(E->getArg(I)));
- Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_mov_dpp,
- Args[0]->getType());
+ assert(Args.size() == 5 || Args.size() == 6);
+ if (Args.size() == 5)
+ Args.insert(Args.begin(), llvm::UndefValue::get(Args[0]->getType()));
+ Value *F =
+ CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, Args[0]->getType());
return Builder.CreateCall(F, Args);
}
case AMDGPU::BI__builtin_amdgcn_div_fixup:
@@ -11039,50 +12126,6 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
CI->setConvergent();
return CI;
}
- case AMDGPU::BI__builtin_amdgcn_ds_faddf:
- case AMDGPU::BI__builtin_amdgcn_ds_fminf:
- case AMDGPU::BI__builtin_amdgcn_ds_fmaxf: {
- llvm::SmallVector<llvm::Value *, 5> Args;
- for (unsigned I = 0; I != 5; ++I)
- Args.push_back(EmitScalarExpr(E->getArg(I)));
- const llvm::Type *PtrTy = Args[0]->getType();
- // check pointer parameter
- if (!PtrTy->isPointerTy() ||
- E->getArg(0)
- ->getType()
- ->getPointeeType()
- .getQualifiers()
- .getAddressSpace() != LangAS::opencl_local ||
- !PtrTy->getPointerElementType()->isFloatTy()) {
- CGM.Error(E->getArg(0)->getLocStart(),
- "parameter should have type \"local float*\"");
- return nullptr;
- }
- // check float parameter
- if (!Args[1]->getType()->isFloatTy()) {
- CGM.Error(E->getArg(1)->getLocStart(),
- "parameter should have type \"float\"");
- return nullptr;
- }
-
- Intrinsic::ID ID;
- switch (BuiltinID) {
- case AMDGPU::BI__builtin_amdgcn_ds_faddf:
- ID = Intrinsic::amdgcn_ds_fadd;
- break;
- case AMDGPU::BI__builtin_amdgcn_ds_fminf:
- ID = Intrinsic::amdgcn_ds_fmin;
- break;
- case AMDGPU::BI__builtin_amdgcn_ds_fmaxf:
- ID = Intrinsic::amdgcn_ds_fmax;
- break;
- default:
- llvm_unreachable("Unknown BuiltinID");
- }
- Value *F = CGM.getIntrinsic(ID);
- return Builder.CreateCall(F, Args);
- }
-
// amdgcn workitem
case AMDGPU::BI__builtin_amdgcn_workitem_id_x:
return emitRangedBuiltin(*this, Intrinsic::amdgcn_workitem_id_x, 0, 1024);
@@ -11363,7 +12406,7 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F, {X, Y, M4Value});
}
- // Vector intrisincs that output the post-instruction CC value.
+ // Vector intrinsics that output the post-instruction CC value.
#define INTRINSIC_WITH_CC(NAME) \
case SystemZ::BI__builtin_##NAME: \
@@ -11823,7 +12866,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
bool isColMajor = isColMajorArg.getSExtValue();
unsigned IID;
unsigned NumResults = 8;
- // PTX Instructions (and LLVM instrinsics) are defined for slice _d_, yet
+ // PTX Instructions (and LLVM intrinsics) are defined for slice _d_, yet
// for some reason nvcc builtins use _c_.
switch (BuiltinID) {
case NVPTX::BI__hmma_m16n16k16_st_c_f16:
@@ -12046,31 +13089,6 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_grow, ResultType);
return Builder.CreateCall(Callee, Args);
}
- case WebAssembly::BI__builtin_wasm_mem_size: {
- llvm::Type *ResultType = ConvertType(E->getType());
- Value *I = EmitScalarExpr(E->getArg(0));
- Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_mem_size, ResultType);
- return Builder.CreateCall(Callee, I);
- }
- case WebAssembly::BI__builtin_wasm_mem_grow: {
- llvm::Type *ResultType = ConvertType(E->getType());
- Value *Args[] = {
- EmitScalarExpr(E->getArg(0)),
- EmitScalarExpr(E->getArg(1))
- };
- Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_mem_grow, ResultType);
- return Builder.CreateCall(Callee, Args);
- }
- case WebAssembly::BI__builtin_wasm_current_memory: {
- llvm::Type *ResultType = ConvertType(E->getType());
- Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_current_memory, ResultType);
- return Builder.CreateCall(Callee);
- }
- case WebAssembly::BI__builtin_wasm_grow_memory: {
- Value *X = EmitScalarExpr(E->getArg(0));
- Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_grow_memory, X->getType());
- return Builder.CreateCall(Callee, X);
- }
case WebAssembly::BI__builtin_wasm_throw: {
Value *Tag = EmitScalarExpr(E->getArg(0));
Value *Obj = EmitScalarExpr(E->getArg(1));
@@ -12081,6 +13099,211 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_rethrow);
return Builder.CreateCall(Callee);
}
+ case WebAssembly::BI__builtin_wasm_atomic_wait_i32: {
+ Value *Addr = EmitScalarExpr(E->getArg(0));
+ Value *Expected = EmitScalarExpr(E->getArg(1));
+ Value *Timeout = EmitScalarExpr(E->getArg(2));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_atomic_wait_i32);
+ return Builder.CreateCall(Callee, {Addr, Expected, Timeout});
+ }
+ case WebAssembly::BI__builtin_wasm_atomic_wait_i64: {
+ Value *Addr = EmitScalarExpr(E->getArg(0));
+ Value *Expected = EmitScalarExpr(E->getArg(1));
+ Value *Timeout = EmitScalarExpr(E->getArg(2));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_atomic_wait_i64);
+ return Builder.CreateCall(Callee, {Addr, Expected, Timeout});
+ }
+ case WebAssembly::BI__builtin_wasm_atomic_notify: {
+ Value *Addr = EmitScalarExpr(E->getArg(0));
+ Value *Count = EmitScalarExpr(E->getArg(1));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_atomic_notify);
+ return Builder.CreateCall(Callee, {Addr, Count});
+ }
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f64:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64_f64:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32x4_f32x4:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64x2_f64x2: {
+ Value *Src = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ResT = ConvertType(E->getType());
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_signed,
+ {ResT, Src->getType()});
+ return Builder.CreateCall(Callee, {Src});
+ }
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f64:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64_f64:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32x4_f32x4:
+ case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i64x2_f64x2: {
+ Value *Src = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ResT = ConvertType(E->getType());
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_unsigned,
+ {ResT, Src->getType()});
+ return Builder.CreateCall(Callee, {Src});
+ }
+ case WebAssembly::BI__builtin_wasm_min_f32:
+ case WebAssembly::BI__builtin_wasm_min_f64:
+ case WebAssembly::BI__builtin_wasm_min_f32x4:
+ case WebAssembly::BI__builtin_wasm_min_f64x2: {
+ Value *LHS = EmitScalarExpr(E->getArg(0));
+ Value *RHS = EmitScalarExpr(E->getArg(1));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::minimum,
+ ConvertType(E->getType()));
+ return Builder.CreateCall(Callee, {LHS, RHS});
+ }
+ case WebAssembly::BI__builtin_wasm_max_f32:
+ case WebAssembly::BI__builtin_wasm_max_f64:
+ case WebAssembly::BI__builtin_wasm_max_f32x4:
+ case WebAssembly::BI__builtin_wasm_max_f64x2: {
+ Value *LHS = EmitScalarExpr(E->getArg(0));
+ Value *RHS = EmitScalarExpr(E->getArg(1));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::maximum,
+ ConvertType(E->getType()));
+ return Builder.CreateCall(Callee, {LHS, RHS});
+ }
+ case WebAssembly::BI__builtin_wasm_extract_lane_s_i8x16:
+ case WebAssembly::BI__builtin_wasm_extract_lane_u_i8x16:
+ case WebAssembly::BI__builtin_wasm_extract_lane_s_i16x8:
+ case WebAssembly::BI__builtin_wasm_extract_lane_u_i16x8:
+ case WebAssembly::BI__builtin_wasm_extract_lane_i32x4:
+ case WebAssembly::BI__builtin_wasm_extract_lane_i64x2:
+ case WebAssembly::BI__builtin_wasm_extract_lane_f32x4:
+ case WebAssembly::BI__builtin_wasm_extract_lane_f64x2: {
+ llvm::APSInt LaneConst;
+ if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext()))
+ llvm_unreachable("Constant arg isn't actually constant?");
+ Value *Vec = EmitScalarExpr(E->getArg(0));
+ Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst);
+ Value *Extract = Builder.CreateExtractElement(Vec, Lane);
+ switch (BuiltinID) {
+ case WebAssembly::BI__builtin_wasm_extract_lane_s_i8x16:
+ case WebAssembly::BI__builtin_wasm_extract_lane_s_i16x8:
+ return Builder.CreateSExt(Extract, ConvertType(E->getType()));
+ case WebAssembly::BI__builtin_wasm_extract_lane_u_i8x16:
+ case WebAssembly::BI__builtin_wasm_extract_lane_u_i16x8:
+ return Builder.CreateZExt(Extract, ConvertType(E->getType()));
+ case WebAssembly::BI__builtin_wasm_extract_lane_i32x4:
+ case WebAssembly::BI__builtin_wasm_extract_lane_i64x2:
+ case WebAssembly::BI__builtin_wasm_extract_lane_f32x4:
+ case WebAssembly::BI__builtin_wasm_extract_lane_f64x2:
+ return Extract;
+ default:
+ llvm_unreachable("unexpected builtin ID");
+ }
+ }
+ case WebAssembly::BI__builtin_wasm_replace_lane_i8x16:
+ case WebAssembly::BI__builtin_wasm_replace_lane_i16x8:
+ case WebAssembly::BI__builtin_wasm_replace_lane_i32x4:
+ case WebAssembly::BI__builtin_wasm_replace_lane_i64x2:
+ case WebAssembly::BI__builtin_wasm_replace_lane_f32x4:
+ case WebAssembly::BI__builtin_wasm_replace_lane_f64x2: {
+ llvm::APSInt LaneConst;
+ if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext()))
+ llvm_unreachable("Constant arg isn't actually constant?");
+ Value *Vec = EmitScalarExpr(E->getArg(0));
+ Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst);
+ Value *Val = EmitScalarExpr(E->getArg(2));
+ switch (BuiltinID) {
+ case WebAssembly::BI__builtin_wasm_replace_lane_i8x16:
+ case WebAssembly::BI__builtin_wasm_replace_lane_i16x8: {
+ llvm::Type *ElemType = ConvertType(E->getType())->getVectorElementType();
+ Value *Trunc = Builder.CreateTrunc(Val, ElemType);
+ return Builder.CreateInsertElement(Vec, Trunc, Lane);
+ }
+ case WebAssembly::BI__builtin_wasm_replace_lane_i32x4:
+ case WebAssembly::BI__builtin_wasm_replace_lane_i64x2:
+ case WebAssembly::BI__builtin_wasm_replace_lane_f32x4:
+ case WebAssembly::BI__builtin_wasm_replace_lane_f64x2:
+ return Builder.CreateInsertElement(Vec, Val, Lane);
+ default:
+ llvm_unreachable("unexpected builtin ID");
+ }
+ }
+ case WebAssembly::BI__builtin_wasm_add_saturate_s_i8x16:
+ case WebAssembly::BI__builtin_wasm_add_saturate_u_i8x16:
+ case WebAssembly::BI__builtin_wasm_add_saturate_s_i16x8:
+ case WebAssembly::BI__builtin_wasm_add_saturate_u_i16x8:
+ case WebAssembly::BI__builtin_wasm_sub_saturate_s_i8x16:
+ case WebAssembly::BI__builtin_wasm_sub_saturate_u_i8x16:
+ case WebAssembly::BI__builtin_wasm_sub_saturate_s_i16x8:
+ case WebAssembly::BI__builtin_wasm_sub_saturate_u_i16x8: {
+ unsigned IntNo;
+ switch (BuiltinID) {
+ case WebAssembly::BI__builtin_wasm_add_saturate_s_i8x16:
+ case WebAssembly::BI__builtin_wasm_add_saturate_s_i16x8:
+ IntNo = Intrinsic::sadd_sat;
+ break;
+ case WebAssembly::BI__builtin_wasm_add_saturate_u_i8x16:
+ case WebAssembly::BI__builtin_wasm_add_saturate_u_i16x8:
+ IntNo = Intrinsic::uadd_sat;
+ break;
+ case WebAssembly::BI__builtin_wasm_sub_saturate_s_i8x16:
+ case WebAssembly::BI__builtin_wasm_sub_saturate_s_i16x8:
+ IntNo = Intrinsic::wasm_sub_saturate_signed;
+ break;
+ case WebAssembly::BI__builtin_wasm_sub_saturate_u_i8x16:
+ case WebAssembly::BI__builtin_wasm_sub_saturate_u_i16x8:
+ IntNo = Intrinsic::wasm_sub_saturate_unsigned;
+ break;
+ default:
+ llvm_unreachable("unexpected builtin ID");
+ }
+ Value *LHS = EmitScalarExpr(E->getArg(0));
+ Value *RHS = EmitScalarExpr(E->getArg(1));
+ Value *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType()));
+ return Builder.CreateCall(Callee, {LHS, RHS});
+ }
+ case WebAssembly::BI__builtin_wasm_bitselect: {
+ Value *V1 = EmitScalarExpr(E->getArg(0));
+ Value *V2 = EmitScalarExpr(E->getArg(1));
+ Value *C = EmitScalarExpr(E->getArg(2));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_bitselect,
+ ConvertType(E->getType()));
+ return Builder.CreateCall(Callee, {V1, V2, C});
+ }
+ case WebAssembly::BI__builtin_wasm_any_true_i8x16:
+ case WebAssembly::BI__builtin_wasm_any_true_i16x8:
+ case WebAssembly::BI__builtin_wasm_any_true_i32x4:
+ case WebAssembly::BI__builtin_wasm_any_true_i64x2:
+ case WebAssembly::BI__builtin_wasm_all_true_i8x16:
+ case WebAssembly::BI__builtin_wasm_all_true_i16x8:
+ case WebAssembly::BI__builtin_wasm_all_true_i32x4:
+ case WebAssembly::BI__builtin_wasm_all_true_i64x2: {
+ unsigned IntNo;
+ switch (BuiltinID) {
+ case WebAssembly::BI__builtin_wasm_any_true_i8x16:
+ case WebAssembly::BI__builtin_wasm_any_true_i16x8:
+ case WebAssembly::BI__builtin_wasm_any_true_i32x4:
+ case WebAssembly::BI__builtin_wasm_any_true_i64x2:
+ IntNo = Intrinsic::wasm_anytrue;
+ break;
+ case WebAssembly::BI__builtin_wasm_all_true_i8x16:
+ case WebAssembly::BI__builtin_wasm_all_true_i16x8:
+ case WebAssembly::BI__builtin_wasm_all_true_i32x4:
+ case WebAssembly::BI__builtin_wasm_all_true_i64x2:
+ IntNo = Intrinsic::wasm_alltrue;
+ break;
+ default:
+ llvm_unreachable("unexpected builtin ID");
+ }
+ Value *Vec = EmitScalarExpr(E->getArg(0));
+ Value *Callee = CGM.getIntrinsic(IntNo, Vec->getType());
+ return Builder.CreateCall(Callee, {Vec});
+ }
+ case WebAssembly::BI__builtin_wasm_abs_f32x4:
+ case WebAssembly::BI__builtin_wasm_abs_f64x2: {
+ Value *Vec = EmitScalarExpr(E->getArg(0));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::fabs, Vec->getType());
+ return Builder.CreateCall(Callee, {Vec});
+ }
+ case WebAssembly::BI__builtin_wasm_sqrt_f32x4:
+ case WebAssembly::BI__builtin_wasm_sqrt_f64x2: {
+ Value *Vec = EmitScalarExpr(E->getArg(0));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::sqrt, Vec->getType());
+ return Builder.CreateCall(Callee, {Vec});
+ }
default:
return nullptr;
diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp
index 5fcc9e011bcb..1c578bd151bd 100644
--- a/lib/CodeGen/CGCUDANV.cpp
+++ b/lib/CodeGen/CGCUDANV.cpp
@@ -137,7 +137,7 @@ CGNVCUDARuntime::addUnderscoredPrefixToName(StringRef FuncName) const {
CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
: CGCUDARuntime(CGM), Context(CGM.getLLVMContext()),
TheModule(CGM.getModule()),
- RelocatableDeviceCode(CGM.getLangOpts().CUDARelocatableDeviceCode) {
+ RelocatableDeviceCode(CGM.getLangOpts().GPURelocatableDeviceCode) {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@@ -353,8 +353,8 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
// global variable and save a reference in GpuBinaryHandle to be cleaned up
// in destructor on exit. Then associate all known kernels with the GPU binary
// handle so CUDA runtime can figure out what to call on the GPU side.
- std::unique_ptr<llvm::MemoryBuffer> CudaGpuBinary;
- if (!IsHIP) {
+ std::unique_ptr<llvm::MemoryBuffer> CudaGpuBinary = nullptr;
+ if (!CudaGpuBinaryFileName.empty()) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CudaGpuBinaryOrErr =
llvm::MemoryBuffer::getFileOrSTDIN(CudaGpuBinaryFileName);
if (std::error_code EC = CudaGpuBinaryOrErr.getError()) {
@@ -388,15 +388,23 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
ModuleIDSectionName = "__hip_module_id";
ModuleIDPrefix = "__hip_";
- // For HIP, create an external symbol __hip_fatbin in section .hip_fatbin.
- // The external symbol is supposed to contain the fat binary but will be
- // populated somewhere else, e.g. by lld through link script.
- FatBinStr = new llvm::GlobalVariable(
+ if (CudaGpuBinary) {
+ // If fatbin is available from early finalization, create a string
+ // literal containing the fat binary loaded from the given file.
+ FatBinStr = makeConstantString(CudaGpuBinary->getBuffer(), "",
+ FatbinConstantName, 8);
+ } else {
+ // If fatbin is not available, create an external symbol
+ // __hip_fatbin in section .hip_fatbin. The external symbol is supposed
+ // to contain the fat binary but will be populated somewhere else,
+ // e.g. by lld through link script.
+ FatBinStr = new llvm::GlobalVariable(
CGM.getModule(), CGM.Int8Ty,
/*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr,
"__hip_fatbin", nullptr,
llvm::GlobalVariable::NotThreadLocal);
- cast<llvm::GlobalVariable>(FatBinStr)->setSection(FatbinConstantName);
+ cast<llvm::GlobalVariable>(FatBinStr)->setSection(FatbinConstantName);
+ }
FatMagic = HIPFatMagic;
} else {
@@ -447,6 +455,8 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
// thread safety of the loaded program. Therefore we can assume sequential
// execution of constructor functions here.
if (IsHIP) {
+ auto Linkage = CudaGpuBinary ? llvm::GlobalValue::InternalLinkage :
+ llvm::GlobalValue::LinkOnceAnyLinkage;
llvm::BasicBlock *IfBlock =
llvm::BasicBlock::Create(Context, "if", ModuleCtorFunc);
llvm::BasicBlock *ExitBlock =
@@ -455,10 +465,13 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
// of HIP ABI.
GpuBinaryHandle = new llvm::GlobalVariable(
TheModule, VoidPtrPtrTy, /*isConstant=*/false,
- llvm::GlobalValue::LinkOnceAnyLinkage,
+ Linkage,
/*Initializer=*/llvm::ConstantPointerNull::get(VoidPtrPtrTy),
"__hip_gpubin_handle");
GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity());
+ // Prevent the weak symbol in different shared libraries being merged.
+ if (Linkage != llvm::GlobalValue::InternalLinkage)
+ GpuBinaryHandle->setVisibility(llvm::GlobalValue::HiddenVisibility);
Address GpuBinaryAddr(
GpuBinaryHandle,
CharUnits::fromQuantity(GpuBinaryHandle->getAlignment()));
@@ -507,7 +520,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
// Generate a unique module ID.
SmallString<64> ModuleID;
llvm::raw_svector_ostream OS(ModuleID);
- OS << ModuleIDPrefix << llvm::format("%x", FatbinWrapper->getGUID());
+ OS << ModuleIDPrefix << llvm::format("%" PRIx64, FatbinWrapper->getGUID());
llvm::Constant *ModuleIDConstant =
makeConstantString(ModuleID.str(), "", ModuleIDSectionName, 32);
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index d5945be43458..8b0733fbec3e 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -23,7 +23,7 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace CodeGen;
@@ -276,7 +276,7 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
llvm::Value *VFunc =
CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes);
- CGCallee Callee(GD.getDecl()->getCanonicalDecl(), VFunc);
+ CGCallee Callee(GD, VFunc);
return Callee;
}
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index 3b1b47cdfe07..ed168b1ce72d 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -132,7 +132,7 @@ void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
// generation. Maybe we can come up with a better way?
auto *ThisDecl = ImplicitParamDecl::Create(
CGM.getContext(), nullptr, MD->getLocation(),
- &CGM.getContext().Idents.get("this"), MD->getThisType(CGM.getContext()),
+ &CGM.getContext().Idents.get("this"), MD->getThisType(),
ImplicitParamDecl::CXXThis);
params.push_back(ThisDecl);
CGF.CXXABIThisDecl = ThisDecl;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index fa51dc30c58b..7d494bb1f1c7 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -23,11 +23,11 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/CodeGen/SwiftCallingConv.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -59,6 +59,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
case CC_X86Pascal: return llvm::CallingConv::C;
// TODO: Add support for __vectorcall to LLVM.
case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall;
+ case CC_AArch64VectorCall: return llvm::CallingConv::AArch64_VectorCall;
case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC;
case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv();
case CC_PreserveMost: return llvm::CallingConv::PreserveMost;
@@ -67,11 +68,13 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
}
}
-/// Derives the 'this' type for codegen purposes, i.e. ignoring method
+/// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR
/// qualification.
-/// FIXME: address space qualification?
-static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD) {
+static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD,
+ const CXXMethodDecl *MD) {
QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
+ if (MD)
+ RecTy = Context.getAddrSpaceQualType(RecTy, MD->getTypeQualifiers().getAddressSpace());
return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
}
@@ -214,6 +217,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
if (PcsAttr *PCS = D->getAttr<PcsAttr>())
return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP);
+ if (D->hasAttr<AArch64VectorPcsAttr>())
+ return CC_AArch64VectorCall;
+
if (D->hasAttr<IntelOclBiccAttr>())
return CC_IntelOclBicc;
@@ -246,7 +252,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
// Add the 'this' pointer.
if (RD)
- argTypes.push_back(GetThisType(Context, RD));
+ argTypes.push_back(GetThisType(Context, RD, MD));
else
argTypes.push_back(Context.VoidPtrTy);
@@ -302,7 +308,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
SmallVector<CanQualType, 16> argTypes;
SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
- argTypes.push_back(GetThisType(Context, MD->getParent()));
+ argTypes.push_back(GetThisType(Context, MD->getParent(), MD));
bool PassParams = true;
@@ -529,7 +535,7 @@ const CGFunctionInfo &
CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
assert(MD->isVirtual() && "only methods have thunks");
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
- CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) };
+ CanQualType ArgTys[] = { GetThisType(Context, MD->getParent(), MD) };
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
/*chainCall=*/false, ArgTys,
FTP->getExtInfo(), {}, RequiredArgs(1));
@@ -543,7 +549,7 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
CanQual<FunctionProtoType> FTP = GetFormalType(CD);
SmallVector<CanQualType, 2> ArgTys;
const CXXRecordDecl *RD = CD->getParent();
- ArgTys.push_back(GetThisType(Context, RD));
+ ArgTys.push_back(GetThisType(Context, RD, CD));
if (CT == Ctor_CopyingClosure)
ArgTys.push_back(*FTP->param_type_begin());
if (RD->getNumVBases() > 0)
@@ -741,8 +747,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
FunctionType::ExtInfo info,
ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
RequiredArgs required) {
- assert(std::all_of(argTypes.begin(), argTypes.end(),
- [](CanQualType T) { return T.isCanonicalAsParam(); }));
+ assert(llvm::all_of(argTypes,
+ [](CanQualType T) { return T.isCanonicalAsParam(); }));
// Lookup or create unique function info.
llvm::FoldingSetNodeID ID;
@@ -1253,8 +1259,8 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
// Otherwise do coercion through memory. This is stupid, but simple.
Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment());
- Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
- Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.AllocaInt8PtrTy);
+ Address Casted = CGF.Builder.CreateElementBitCast(Tmp,CGF.Int8Ty);
+ Address SrcCasted = CGF.Builder.CreateElementBitCast(Src,CGF.Int8Ty);
CGF.Builder.CreateMemCpy(Casted, SrcCasted,
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
false);
@@ -1335,8 +1341,8 @@ static void CreateCoercedStore(llvm::Value *Src,
// to that information.
Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment());
CGF.Builder.CreateStore(Src, Tmp);
- Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
- Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.AllocaInt8PtrTy);
+ Address Casted = CGF.Builder.CreateElementBitCast(Tmp,CGF.Int8Ty);
+ Address DstCasted = CGF.Builder.CreateElementBitCast(Dst,CGF.Int8Ty);
CGF.Builder.CreateMemCpy(DstCasted, Casted,
llvm::ConstantInt::get(CGF.IntPtrTy, DstSize),
false);
@@ -1709,6 +1715,8 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
if (CodeGenOpts.DisableRedZone)
FuncAttrs.addAttribute(llvm::Attribute::NoRedZone);
+ if (CodeGenOpts.IndirectTlsSegRefs)
+ FuncAttrs.addAttribute("indirect-tls-seg-refs");
if (CodeGenOpts.NoImplicitFloat)
FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat);
@@ -1784,6 +1792,11 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
FuncAttrs.addAttribute("stackrealign");
if (CodeGenOpts.Backchain)
FuncAttrs.addAttribute("backchain");
+
+ // FIXME: The interaction of this attribute with the SLH command line flag
+ // has not been determined.
+ if (CodeGenOpts.SpeculativeLoadHardening)
+ FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening);
}
if (getLangOpts().assumeFunctionsAreConvergent()) {
@@ -1803,6 +1816,12 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
if (CodeGenOpts.FlushDenorm)
FuncAttrs.addAttribute("nvptx-f32ftz", "true");
}
+
+ for (StringRef Attr : CodeGenOpts.DefaultFunctionAttrs) {
+ StringRef Var, Value;
+ std::tie(Var, Value) = Attr.split('=');
+ FuncAttrs.addAttribute(Var, Value);
+ }
}
void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) {
@@ -1828,7 +1847,7 @@ void CodeGenModule::ConstructAttributeList(
AddAttributesFromFunctionProtoType(getContext(), FuncAttrs,
CalleeInfo.getCalleeFunctionProtoType());
- const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
+ const Decl *TargetDecl = CalleeInfo.getCalleeDecl().getDecl();
bool HasOptnone = false;
// FIXME: handle sseregparm someday...
@@ -1845,6 +1864,8 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
if (TargetDecl->hasAttr<ConvergentAttr>())
FuncAttrs.addAttribute(llvm::Attribute::Convergent);
+ if (TargetDecl->hasAttr<SpeculativeLoadHardeningAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening);
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
AddAttributesFromFunctionProtoType(
@@ -1936,7 +1957,7 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute("disable-tail-calls",
llvm::toStringRef(DisableTailCalls));
- GetCPUAndFeaturesAttributes(TargetDecl, FuncAttrs);
+ GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs);
}
ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI);
@@ -2327,7 +2348,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
} else {
// Load scalar value from indirect argument.
llvm::Value *V =
- EmitLoadOfScalar(ParamAddr, false, Ty, Arg->getLocStart());
+ EmitLoadOfScalar(ParamAddr, false, Ty, Arg->getBeginLoc());
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
@@ -2389,7 +2410,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (!AVAttr)
if (const auto *TOTy = dyn_cast<TypedefType>(OTy))
AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>();
- if (AVAttr) {
+ if (AVAttr && !SanOpts.has(SanitizerKind::Alignment)) {
+ // If alignment-assumption sanitizer is enabled, we do *not* add
+ // alignment attribute here, but emit normal alignment assumption,
+ // so the UBSAN check could function.
llvm::Value *AlignmentValue =
EmitScalarExpr(AVAttr->getAlignment());
llvm::ConstantInt *AlignmentCI =
@@ -2490,7 +2514,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// Match to what EmitParmDecl is expecting for this type.
if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
llvm::Value *V =
- EmitLoadOfScalar(Alloca, false, Ty, Arg->getLocStart());
+ EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc());
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
ArgVals.push_back(ParamValue::forDirect(V));
@@ -3063,8 +3087,9 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
QualType type = param->getType();
- assert(!isInAllocaArgument(CGM.getCXXABI(), type) &&
- "cannot emit delegate call arguments for inalloca arguments!");
+ if (isInAllocaArgument(CGM.getCXXABI(), type)) {
+ CGM.ErrorUnsupported(param, "forwarded non-trivially copyable parameter");
+ }
// GetAddrOfLocalVar returns a pointer-to-pointer for references,
// but the argument needs to be the original pointer.
@@ -3945,15 +3970,28 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
} else if (I->hasLValue()) {
auto LV = I->getKnownLValue();
auto AS = LV.getAddressSpace();
+
if ((!ArgInfo.getIndirectByVal() &&
(LV.getAlignment() >=
- getContext().getTypeAlignInChars(I->Ty))) ||
- (ArgInfo.getIndirectByVal() &&
- ((AS != LangAS::Default && AS != LangAS::opencl_private &&
- AS != CGM.getASTAllocaAddressSpace())))) {
+ getContext().getTypeAlignInChars(I->Ty)))) {
+ NeedCopy = true;
+ }
+ if (!getLangOpts().OpenCL) {
+ if ((ArgInfo.getIndirectByVal() &&
+ (AS != LangAS::Default &&
+ AS != CGM.getASTAllocaAddressSpace()))) {
+ NeedCopy = true;
+ }
+ }
+ // For OpenCL even if RV is located in default or alloca address space
+ // we don't want to perform address space cast for it.
+ else if ((ArgInfo.getIndirectByVal() &&
+ Addr.getType()->getAddressSpace() != IRFuncTy->
+ getParamType(FirstIRArg)->getPointerAddressSpace())) {
NeedCopy = true;
}
}
+
if (NeedCopy) {
// Create an aligned temporary, and copy to it.
Address AI = CreateMemTempWithoutCast(
@@ -4235,6 +4273,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
#endif
+ // Update the largest vector width if any arguments have vector types.
+ for (unsigned i = 0; i < IRCallArgs.size(); ++i) {
+ if (auto *VT = dyn_cast<llvm::VectorType>(IRCallArgs[i]->getType()))
+ LargestVectorWidth = std::max(LargestVectorWidth,
+ VT->getPrimitiveSizeInBits());
+ }
+
// Compute the calling convention and attributes.
unsigned CallingConv;
llvm::AttributeList Attrs;
@@ -4248,8 +4293,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// Apply always_inline to all calls within flatten functions.
// FIXME: should this really take priority over __try, below?
if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
- !(Callee.getAbstractInfo().getCalleeDecl() &&
- Callee.getAbstractInfo().getCalleeDecl()->hasAttr<NoInlineAttr>())) {
+ !(Callee.getAbstractInfo().getCalleeDecl().getDecl() &&
+ Callee.getAbstractInfo()
+ .getCalleeDecl()
+ .getDecl()
+ ->hasAttr<NoInlineAttr>())) {
Attrs =
Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
llvm::Attribute::AlwaysInline);
@@ -4315,6 +4363,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (!CI->getType()->isVoidTy())
CI->setName("call");
+ // Update largest vector width from the return type.
+ if (auto *VT = dyn_cast<llvm::VectorType>(CI->getType()))
+ LargestVectorWidth = std::max(LargestVectorWidth,
+ VT->getPrimitiveSizeInBits());
+
// Insert instrumentation or attach profile metadata at indirect call sites.
// For more details, see the comment before the definition of
// IPVK_IndirectCallTarget in InstrProfData.inc.
@@ -4329,7 +4382,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// Suppress tail calls if requested.
if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
- const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
+ const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl();
if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
}
@@ -4476,7 +4529,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
} ();
// Emit the assume_aligned check on the return value.
- const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
+ const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl();
if (Ret.isScalar() && TargetDecl) {
if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) {
llvm::Value *OffsetValue = nullptr;
@@ -4485,13 +4538,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::Value *Alignment = EmitScalarExpr(AA->getAlignment());
llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(Alignment);
- EmitAlignmentAssumption(Ret.getScalarVal(), AlignmentCI->getZExtValue(),
- OffsetValue);
+ EmitAlignmentAssumption(Ret.getScalarVal(), RetTy, Loc, AA->getLocation(),
+ AlignmentCI->getZExtValue(), OffsetValue);
} else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) {
- llvm::Value *ParamVal =
- CallArgs[AA->getParamIndex().getLLVMIndex()].getRValue(
- *this).getScalarVal();
- EmitAlignmentAssumption(Ret.getScalarVal(), ParamVal);
+ llvm::Value *AlignmentVal = CallArgs[AA->getParamIndex().getLLVMIndex()]
+ .getRValue(*this)
+ .getScalarVal();
+ EmitAlignmentAssumption(Ret.getScalarVal(), RetTy, Loc, AA->getLocation(),
+ AlignmentVal);
}
}
@@ -4502,8 +4556,8 @@ CGCallee CGCallee::prepareConcreteCallee(CodeGenFunction &CGF) const {
if (isVirtual()) {
const CallExpr *CE = getVirtualCallExpr();
return CGF.CGM.getCXXABI().getVirtualFunctionPointer(
- CGF, getVirtualMethodDecl(), getThisAddress(),
- getFunctionType(), CE ? CE->getLocStart() : SourceLocation());
+ CGF, getVirtualMethodDecl(), getThisAddress(), getFunctionType(),
+ CE ? CE->getBeginLoc() : SourceLocation());
}
return *this;
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 99a36e4e12f1..c300808bea28 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -46,21 +46,21 @@ class CGCalleeInfo {
/// The function prototype of the callee.
const FunctionProtoType *CalleeProtoTy;
/// The function declaration of the callee.
- const Decl *CalleeDecl;
+ GlobalDecl CalleeDecl;
public:
- explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
- CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
+ explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {}
+ CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)
: CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
- : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
- CGCalleeInfo(const Decl *calleeDecl)
+ : CalleeProtoTy(calleeProtoTy), CalleeDecl() {}
+ CGCalleeInfo(GlobalDecl calleeDecl)
: CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
const FunctionProtoType *getCalleeFunctionProtoType() const {
return CalleeProtoTy;
}
- const Decl *getCalleeDecl() const { return CalleeDecl; }
+ const GlobalDecl getCalleeDecl() const { return CalleeDecl; }
};
/// All available information about a concrete callee.
@@ -171,7 +171,7 @@ public:
}
CGCalleeInfo getAbstractInfo() const {
if (isVirtual())
- return VirtualInfo.MD.getDecl();
+ return VirtualInfo.MD;
assert(isOrdinary());
return AbstractInfo;
}
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index ec4eb000a3b9..ee150a792b76 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -16,14 +16,15 @@
#include "CGDebugInfo.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
+#include "TargetInfo.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Transforms/Utils/SanitizerStats.h"
@@ -829,7 +830,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
// delegation optimization.
if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) &&
CGM.getTarget().getCXXABI().hasConstructorVariants()) {
- EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getLocEnd());
+ EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getEndLoc());
return;
}
@@ -2012,8 +2013,19 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
bool NewPointerIsChecked) {
CallArgList Args;
+ LangAS SlotAS = E->getType().getAddressSpace();
+ QualType ThisType = D->getThisType();
+ LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace();
+ llvm::Value *ThisPtr = This.getPointer();
+ if (SlotAS != ThisAS) {
+ unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS);
+ llvm::Type *NewType =
+ ThisPtr->getType()->getPointerElementType()->getPointerTo(TargetThisAS);
+ ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(),
+ ThisAS, SlotAS, NewType);
+ }
// Push the this ptr.
- Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
+ Args.add(RValue::get(ThisPtr), D->getThisType());
// If this is a trivial constructor, emit a memcpy now before we lose
// the alignment information on the argument.
@@ -2122,7 +2134,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CGM.getAddrOfCXXStructor(D, getFromCtorType(Type));
const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(
Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs);
- CGCallee Callee = CGCallee::forDirect(CalleePtr, D);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type));
EmitCall(Info, Callee, ReturnValueSlot(), Args);
// Generate vtable assumptions if we're constructing a complete object
@@ -2147,7 +2159,7 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall(
const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {
CallArgList Args;
- CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType(getContext()));
+ CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType());
// Forward the parameters.
if (InheritedFromVBase &&
@@ -2196,6 +2208,7 @@ void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
GlobalDecl GD(Ctor, CtorType);
InlinedInheritingConstructorScope Scope(*this, GD);
ApplyInlineDebugLocation DebugScope(*this, GD);
+ RunCleanupsScope RunCleanups(*this);
// Save the arguments to be passed to the inherited constructor.
CXXInheritedCtorInitExprArgs = Args;
@@ -2271,7 +2284,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
CallArgList Args;
// Push the this ptr.
- Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
+ Args.add(RValue::get(This.getPointer()), D->getThisType());
// Push the src ptr.
QualType QT = *(FPT->param_type_begin());
@@ -2808,7 +2821,7 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// variadic arguments.
// Now emit our call.
- auto callee = CGCallee::forDirect(calleePtr, callOperator);
+ auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator));
RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs);
// If necessary, copy the returned value into the slot.
@@ -2839,12 +2852,12 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
CallArgList CallArgs;
QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda));
- Address ThisPtr = GetAddrOfBlockDecl(variable, false);
+ Address ThisPtr = GetAddrOfBlockDecl(variable);
CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType);
// Add the rest of the parameters.
for (auto param : BD->parameters())
- EmitDelegateCallArg(CallArgs, param, param->getLocStart());
+ EmitDelegateCallArg(CallArgs, param, param->getBeginLoc());
assert(!Lambda->isGenericLambda() &&
"generic lambda interconversion to block not implemented");
@@ -2863,7 +2876,7 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
// Add the rest of the parameters.
for (auto Param : MD->parameters())
- EmitDelegateCallArg(CallArgs, Param, Param->getLocStart());
+ EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc());
const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
// For a generic lambda, find the corresponding call operator specialization
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index 0a766d176200..3743d24f11fc 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -366,7 +366,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF,
llvm::BasicBlock *Block) {
// If it's a branch, turn it into a switch whose default
// destination is its original target.
- llvm::TerminatorInst *Term = Block->getTerminator();
+ llvm::Instruction *Term = Block->getTerminator();
assert(Term && "can't transition block without terminator");
if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
@@ -589,7 +589,7 @@ static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
llvm::BasicBlock *To) {
// Exit is the exit block of a cleanup, so it always terminates in
// an unconditional branch or a switch.
- llvm::TerminatorInst *Term = Exit->getTerminator();
+ llvm::Instruction *Term = Exit->getTerminator();
if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
assert(Br->isUnconditional() && Br->getSuccessor(0) == From);
diff --git a/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp
index 4f525c8aac85..80fa7c873631 100644
--- a/lib/CodeGen/CGCoroutine.cpp
+++ b/lib/CodeGen/CGCoroutine.cpp
@@ -93,10 +93,10 @@ static void createCoroData(CodeGenFunction &CGF,
CallExpr const *CoroIdExpr = nullptr) {
if (CurCoro.Data) {
if (CurCoro.Data->CoroIdExpr)
- CGF.CGM.Error(CoroIdExpr->getLocStart(),
+ CGF.CGM.Error(CoroIdExpr->getBeginLoc(),
"only one __builtin_coro_id can be used in a function");
else if (CoroIdExpr)
- CGF.CGM.Error(CoroIdExpr->getLocStart(),
+ CGF.CGM.Error(CoroIdExpr->getBeginLoc(),
"__builtin_coro_id shall not be used in a C++ coroutine");
else
llvm_unreachable("EmitCoroutineBodyStatement called twice?");
@@ -444,7 +444,7 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup {
// We should have captured coro.free from the emission of deallocate.
auto *CoroFree = CGF.CurCoro.Data->LastCoroFree;
if (!CoroFree) {
- CGF.CGM.Error(Deallocate->getLocStart(),
+ CGF.CGM.Error(Deallocate->getBeginLoc(),
"Deallocation expressoin does not refer to coro.free");
return;
}
@@ -654,7 +654,7 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
EmitBlock(BodyBB);
}
- auto Loc = S.getLocStart();
+ auto Loc = S.getBeginLoc();
CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr,
CurCoro.Data->ExceptionHandler);
auto *TryStmt =
@@ -707,8 +707,8 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
if (CurCoro.Data && CurCoro.Data->CoroBegin) {
return RValue::get(CurCoro.Data->CoroBegin);
}
- CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_begin "
- "has been used earlier in this function");
+ CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_begin "
+ "has been used earlier in this function");
auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
return RValue::get(NullPtr);
}
@@ -722,7 +722,7 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
Args.push_back(CurCoro.Data->CoroId);
break;
}
- CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has"
+ CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_id has"
" been used earlier in this function");
// Fallthrough to the next case to add TokenNone as the first argument.
LLVM_FALLTHROUGH;
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 5be6fb3e4245..41f8721468a3 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -25,10 +25,10 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
@@ -41,6 +41,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MD5.h"
@@ -180,8 +181,7 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
SourceManager &SM = CGM.getContext().getSourceManager();
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
-
- if (PCLoc.isInvalid() || Scope->getFilename() == PCLoc.getFilename())
+ if (PCLoc.isInvalid() || Scope->getFile() == getOrCreateFile(CurLoc))
return;
if (auto *LBF = dyn_cast<llvm::DILexicalBlockFile>(Scope)) {
@@ -220,7 +220,7 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,
if (const auto *RDecl = dyn_cast<RecordDecl>(Context))
if (!RDecl->isDependentType())
return getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
- getOrCreateMainFile());
+ TheCU->getFile());
return Default;
}
@@ -234,6 +234,9 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
if (CGM.getCodeGenOpts().EmitCodeView)
PP.MSVCFormatting = true;
+ // Apply -fdebug-prefix-map.
+ PP.RemapFilePaths = true;
+ PP.remapPath = [this](StringRef Path) { return remapDIPath(Path); };
return PP;
}
@@ -401,19 +404,18 @@ Optional<StringRef> CGDebugInfo::getSource(const SourceManager &SM,
llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return getOrCreateMainFile();
+ return TheCU->getFile();
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
- if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
+ StringRef FileName = PLoc.getFilename();
+ if (PLoc.isInvalid() || FileName.empty())
// If the location is not valid then use main input file.
- return getOrCreateMainFile();
+ return TheCU->getFile();
// Cache the results.
- const char *fname = PLoc.getFilename();
- auto It = DIFileCache.find(fname);
-
+ auto It = DIFileCache.find(FileName.data());
if (It != DIFileCache.end()) {
// Verify that the information still exists.
if (llvm::Metadata *V = It->second)
@@ -426,22 +428,48 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo;
if (CSKind)
CSInfo.emplace(*CSKind, Checksum);
-
- llvm::DIFile *F = DBuilder.createFile(
- remapDIPath(PLoc.getFilename()), remapDIPath(getCurrentDirname()), CSInfo,
- getSource(SM, SM.getFileID(Loc)));
-
- DIFileCache[fname].reset(F);
+ return createFile(FileName, CSInfo, getSource(SM, SM.getFileID(Loc)));
+}
+
+llvm::DIFile *
+CGDebugInfo::createFile(StringRef FileName,
+ Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo,
+ Optional<StringRef> Source) {
+ StringRef Dir;
+ StringRef File;
+ std::string RemappedFile = remapDIPath(FileName);
+ std::string CurDir = remapDIPath(getCurrentDirname());
+ SmallString<128> DirBuf;
+ SmallString<128> FileBuf;
+ if (llvm::sys::path::is_absolute(RemappedFile)) {
+ // Strip the common prefix (if it is more than just "/") from current
+ // directory and FileName for a more space-efficient encoding.
+ auto FileIt = llvm::sys::path::begin(RemappedFile);
+ auto FileE = llvm::sys::path::end(RemappedFile);
+ auto CurDirIt = llvm::sys::path::begin(CurDir);
+ auto CurDirE = llvm::sys::path::end(CurDir);
+ for (; CurDirIt != CurDirE && *CurDirIt == *FileIt; ++CurDirIt, ++FileIt)
+ llvm::sys::path::append(DirBuf, *CurDirIt);
+ if (std::distance(llvm::sys::path::begin(CurDir), CurDirIt) == 1) {
+ // The common prefix only the root; stripping it would cause
+ // LLVM diagnostic locations to be more confusing.
+ Dir = {};
+ File = RemappedFile;
+ } else {
+ for (; FileIt != FileE; ++FileIt)
+ llvm::sys::path::append(FileBuf, *FileIt);
+ Dir = DirBuf;
+ File = FileBuf;
+ }
+ } else {
+ Dir = CurDir;
+ File = RemappedFile;
+ }
+ llvm::DIFile *F = DBuilder.createFile(File, Dir, CSInfo, Source);
+ DIFileCache[FileName.data()].reset(F);
return F;
}
-llvm::DIFile *CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.createFile(
- remapDIPath(TheCU->getFilename()), remapDIPath(TheCU->getDirectory()),
- TheCU->getFile()->getChecksum(),
- CGM.getCodeGenOpts().EmbedSource ? TheCU->getSource() : None);
-}
-
std::string CGDebugInfo::remapDIPath(StringRef Path) const {
for (const auto &Entry : DebugPrefixMap)
if (Path.startswith(Entry.first))
@@ -527,11 +555,11 @@ void CGDebugInfo::CreateCompileUnit() {
llvm::dwarf::SourceLanguage LangTag;
const LangOptions &LO = CGM.getLangOpts();
if (LO.CPlusPlus) {
- if (LO.ObjC1)
+ if (LO.ObjC)
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
else
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
- } else if (LO.ObjC1) {
+ } else if (LO.ObjC) {
LangTag = llvm::dwarf::DW_LANG_ObjC;
} else if (LO.RenderScript) {
LangTag = llvm::dwarf::DW_LANG_GOOGLE_RenderScript;
@@ -545,7 +573,7 @@ void CGDebugInfo::CreateCompileUnit() {
// Figure out which version of the ObjC runtime we have.
unsigned RuntimeVers = 0;
- if (LO.ObjC1)
+ if (LO.ObjC)
RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1;
llvm::DICompileUnit::DebugEmissionKind EmissionKind;
@@ -557,29 +585,42 @@ void CGDebugInfo::CreateCompileUnit() {
case codegenoptions::DebugLineTablesOnly:
EmissionKind = llvm::DICompileUnit::LineTablesOnly;
break;
+ case codegenoptions::DebugDirectivesOnly:
+ EmissionKind = llvm::DICompileUnit::DebugDirectivesOnly;
+ break;
case codegenoptions::LimitedDebugInfo:
case codegenoptions::FullDebugInfo:
EmissionKind = llvm::DICompileUnit::FullDebug;
break;
}
+ uint64_t DwoId = 0;
+ auto &CGOpts = CGM.getCodeGenOpts();
+ // The DIFile used by the CU is distinct from the main source
+ // file. Its directory part specifies what becomes the
+ // DW_AT_comp_dir (the compilation directory), even if the source
+ // file was specified with an absolute path.
if (CSKind)
CSInfo.emplace(*CSKind, Checksum);
+ llvm::DIFile *CUFile = DBuilder.createFile(
+ remapDIPath(MainFileName), remapDIPath(getCurrentDirname()), CSInfo,
+ getSource(SM, SM.getMainFileID()));
// Create new compile unit.
- // FIXME - Eliminate TheCU.
- auto &CGOpts = CGM.getCodeGenOpts();
TheCU = DBuilder.createCompileUnit(
- LangTag,
- DBuilder.createFile(remapDIPath(MainFileName),
- remapDIPath(getCurrentDirname()), CSInfo,
- getSource(SM, SM.getMainFileID())),
- CGOpts.EmitVersionIdentMetadata ? Producer : "",
+ LangTag, CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "",
LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO,
CGOpts.DwarfDebugFlags, RuntimeVers,
- CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind,
- 0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,
- CGOpts.GnuPubnames);
+ (CGOpts.getSplitDwarfMode() != CodeGenOptions::NoFission)
+ ? ""
+ : CGOpts.SplitDwarfFile,
+ EmissionKind, DwoId, CGOpts.SplitDwarfInlining,
+ CGOpts.DebugInfoForProfiling,
+ CGM.getTarget().getTriple().isNVPTX()
+ ? llvm::DICompileUnit::DebugNameTableKind::None
+ : static_cast<llvm::DICompileUnit::DebugNameTableKind>(
+ CGOpts.DebugNameTable),
+ CGOpts.DebugRangesBaseAddress);
}
llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
@@ -597,9 +638,9 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return nullptr;
case BuiltinType::ObjCClass:
if (!ClassTy)
- ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- "objc_class", TheCU,
- getOrCreateMainFile(), 0);
+ ClassTy =
+ DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ "objc_class", TheCU, TheCU->getFile(), 0);
return ClassTy;
case BuiltinType::ObjCId: {
// typedef struct objc_class *Class;
@@ -611,21 +652,21 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return ObjTy;
if (!ClassTy)
- ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- "objc_class", TheCU,
- getOrCreateMainFile(), 0);
+ ClassTy =
+ DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ "objc_class", TheCU, TheCU->getFile(), 0);
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
auto *ISATy = DBuilder.createPointerType(ClassTy, Size);
- ObjTy = DBuilder.createStructType(
- TheCU, "objc_object", getOrCreateMainFile(), 0, 0, 0,
- llvm::DINode::FlagZero, nullptr, llvm::DINodeArray());
+ ObjTy = DBuilder.createStructType(TheCU, "objc_object", TheCU->getFile(), 0,
+ 0, 0, llvm::DINode::FlagZero, nullptr,
+ llvm::DINodeArray());
DBuilder.replaceArrays(
ObjTy, DBuilder.getOrCreateArray(&*DBuilder.createMemberType(
- ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0,
+ ObjTy, "isa", TheCU->getFile(), 0, Size, 0, 0,
llvm::DINode::FlagZero, ISATy)));
return ObjTy;
}
@@ -633,7 +674,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
if (!SelTy)
SelTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
"objc_selector", TheCU,
- getOrCreateMainFile(), 0);
+ TheCU->getFile(), 0);
return SelTy;
}
@@ -652,6 +693,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return getOrCreateStructPtrType("opencl_queue_t", OCLQueueDITy);
case BuiltinType::OCLReserveID:
return getOrCreateStructPtrType("opencl_reserve_id_t", OCLReserveIDDITy);
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id: \
+ return getOrCreateStructPtrType("opencl_" #ExtType, Id##Ty);
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::UChar:
case BuiltinType::Char_U:
@@ -825,31 +870,45 @@ static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) {
}
}
-// Determines if the tag declaration will require a type identifier.
+// Determines if the debug info for this tag declaration needs a type
+// identifier. The purpose of the unique identifier is to deduplicate type
+// information for identical types across TUs. Because of the C++ one definition
+// rule (ODR), it is valid to assume that the type is defined the same way in
+// every TU and its debug info is equivalent.
+//
+// C does not have the ODR, and it is common for codebases to contain multiple
+// different definitions of a struct with the same name in different TUs.
+// Therefore, if the type doesn't have a C++ mangling, don't give it an
+// identifer. Type information in C is smaller and simpler than C++ type
+// information, so the increase in debug info size is negligible.
+//
+// If the type is not externally visible, it should be unique to the current TU,
+// and should not need an identifier to participate in type deduplication.
+// However, when emitting CodeView, the format internally uses these
+// unique type name identifers for references between debug info. For example,
+// the method of a class in an anonymous namespace uses the identifer to refer
+// to its parent class. The Microsoft C++ ABI attempts to provide unique names
+// for such types, so when emitting CodeView, always use identifiers for C++
+// types. This may create problems when attempting to emit CodeView when the MS
+// C++ ABI is not in use.
static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM,
llvm::DICompileUnit *TheCU) {
// We only add a type identifier for types with C++ name mangling.
if (!hasCXXMangling(TD, TheCU))
return false;
- // CodeView types with C++ mangling need a type identifier.
- if (CGM.getCodeGenOpts().EmitCodeView)
- return true;
-
// Externally visible types with C++ mangling need a type identifier.
if (TD->isExternallyVisible())
return true;
+ // CodeView types with C++ mangling need a type identifier.
+ if (CGM.getCodeGenOpts().EmitCodeView)
+ return true;
+
return false;
}
-// When emitting CodeView debug information we need to produce a type
-// identifier for all types which have a C++ mangling. Until a GUID is added
-// to the identifier (not currently implemented) the result will not be unique
-// across compilation units.
-// When emitting DWARF debug information, we need to produce a type identifier
-// for all externally visible types with C++ name mangling. This identifier
-// should be unique across ODR-compliant compilation units.
+// Returns a unique type identifier string if one exists, or an empty string.
static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM,
llvm::DICompileUnit *TheCU) {
SmallString<256> Identifier;
@@ -936,18 +995,53 @@ llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
if (Cache)
return Cache;
Cache = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name,
- TheCU, getOrCreateMainFile(), 0);
+ TheCU, TheCU->getFile(), 0);
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
Cache = DBuilder.createPointerType(Cache, Size);
return Cache;
}
+uint64_t CGDebugInfo::collectDefaultElementTypesForBlockPointer(
+ const BlockPointerType *Ty, llvm::DIFile *Unit, llvm::DIDerivedType *DescTy,
+ unsigned LineNo, SmallVectorImpl<llvm::Metadata *> &EltTys) {
+ QualType FType;
+
+ // Advanced by calls to CreateMemberType in increments of FType, then
+ // returned as the overall size of the default elements.
+ uint64_t FieldOffset = 0;
+
+ // Blocks in OpenCL have unique constraints which make the standard fields
+ // redundant while requiring size and align fields for enqueue_kernel. See
+ // initializeForBlockHeader in CGBlocks.cpp
+ if (CGM.getLangOpts().OpenCL) {
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__align", &FieldOffset));
+ } else {
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
+ FType = CGM.getContext().getPointerType(Ty->getPointeeType());
+ EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ uint64_t FieldSize = CGM.getContext().getTypeSize(Ty);
+ uint32_t FieldAlign = CGM.getContext().getTypeAlign(Ty);
+ EltTys.push_back(DBuilder.createMemberType(
+ Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign,
+ FieldOffset, llvm::DINode::FlagZero, DescTy));
+ FieldOffset += FieldSize;
+ }
+
+ return FieldOffset;
+}
+
llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
llvm::DIFile *Unit) {
SmallVector<llvm::Metadata *, 8> EltTys;
QualType FType;
- uint64_t FieldSize, FieldOffset;
- uint32_t FieldAlign;
+ uint64_t FieldOffset;
llvm::DINodeArray Elements;
FieldOffset = 0;
@@ -959,10 +1053,9 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTys.clear();
llvm::DINode::DIFlags Flags = llvm::DINode::FlagAppleBlock;
- unsigned LineNo = 0;
auto *EltTy =
- DBuilder.createStructType(Unit, "__block_descriptor", nullptr, LineNo,
+ DBuilder.createStructType(Unit, "__block_descriptor", nullptr, 0,
FieldOffset, 0, Flags, nullptr, Elements);
// Bit size, align and offset of the type.
@@ -970,27 +1063,8 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
auto *DescTy = DBuilder.createPointerType(EltTy, Size);
- FieldOffset = 0;
- if (CGM.getLangOpts().OpenCL) {
- FType = CGM.getContext().IntTy;
- EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "__align", &FieldOffset));
- } else {
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
- FType = CGM.getContext().IntTy;
- EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
- FType = CGM.getContext().getPointerType(Ty->getPointeeType());
- EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- FieldSize = CGM.getContext().getTypeSize(Ty);
- FieldAlign = CGM.getContext().getTypeAlign(Ty);
- EltTys.push_back(DBuilder.createMemberType(
- Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, FieldOffset,
- llvm::DINode::FlagZero, DescTy));
- FieldOffset += FieldSize;
- }
+ FieldOffset = collectDefaultElementTypesForBlockPointer(Ty, Unit, DescTy,
+ 0, EltTys);
Elements = DBuilder.getOrCreateArray(EltTys);
@@ -998,7 +1072,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
// DW_AT_APPLE_BLOCK attribute and are an implementation detail only
// the debugger needs to know about. To allow type uniquing, emit
// them without a name or a location.
- EltTy = DBuilder.createStructType(Unit, "", nullptr, LineNo, FieldOffset, 0,
+ EltTy = DBuilder.createStructType(Unit, "", nullptr, 0, FieldOffset, 0,
Flags, nullptr, Elements);
return DBuilder.createPointerType(EltTy, Size);
@@ -1058,6 +1132,7 @@ static unsigned getDwarfCC(CallingConv CC) {
case CC_X86_64SysV:
return llvm::dwarf::DW_CC_LLVM_X86_64SysV;
case CC_AAPCS:
+ case CC_AArch64VectorCall:
return llvm::dwarf::DW_CC_LLVM_AAPCS;
case CC_AAPCS_VFP:
return llvm::dwarf::DW_CC_LLVM_AAPCS_VFP;
@@ -1353,8 +1428,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
if (Method->isStatic())
return cast_or_null<llvm::DISubroutineType>(
getOrCreateType(QualType(Func, 0), Unit));
- return getOrCreateInstanceMethodType(Method->getThisType(CGM.getContext()),
- Func, Unit);
+ return getOrCreateInstanceMethodType(Method->getThisType(), Func, Unit);
}
llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
@@ -1450,16 +1524,16 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
// Collect virtual method info.
llvm::DIType *ContainingType = nullptr;
- unsigned Virtuality = 0;
unsigned VIndex = 0;
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
+ llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
int ThisAdjustment = 0;
if (Method->isVirtual()) {
if (Method->isPure())
- Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
+ SPFlags |= llvm::DISubprogram::SPFlagPureVirtual;
else
- Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
+ SPFlags |= llvm::DISubprogram::SPFlagVirtual;
if (CGM.getTarget().getCXXABI().isItaniumFamily()) {
// It doesn't make sense to give a virtual destructor a vtable index,
@@ -1511,12 +1585,13 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
Flags |= llvm::DINode::FlagLValueReference;
if (Method->getRefQualifier() == RQ_RValue)
Flags |= llvm::DINode::FlagRValueReference;
+ if (CGM.getLangOpts().Optimize)
+ SPFlags |= llvm::DISubprogram::SPFlagOptimized;
llvm::DINodeArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
llvm::DISubprogram *SP = DBuilder.createMethod(
RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine,
- MethodTy, /*isLocalToUnit=*/false, /*isDefinition=*/false, Virtuality,
- VIndex, ThisAdjustment, ContainingType, Flags, CGM.getLangOpts().Optimize,
+ MethodTy, VIndex, ThisAdjustment, ContainingType, Flags, SPFlags,
TParamsArray.get());
SPCache[Method->getCanonicalDecl()].reset(SP);
@@ -1741,6 +1816,29 @@ CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,
return llvm::DINodeArray();
}
+llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL,
+ llvm::DIFile *Unit) {
+ if (auto *TS = dyn_cast<VarTemplateSpecializationDecl>(VL)) {
+ auto T = TS->getSpecializedTemplateOrPartial();
+ auto TA = TS->getTemplateArgs().asArray();
+ // Collect parameters for a partial specialization
+ if (T.is<VarTemplatePartialSpecializationDecl *>()) {
+ const TemplateParameterList *TList =
+ T.get<VarTemplatePartialSpecializationDecl *>()
+ ->getTemplateParameters();
+ return CollectTemplateParams(TList, TA, Unit);
+ }
+
+ // Collect parameters for an explicit specialization
+ if (T.is<VarTemplateDecl *>()) {
+ const TemplateParameterList *TList = T.get<VarTemplateDecl *>()
+ ->getTemplateParameters();
+ return CollectTemplateParams(TList, TA, Unit);
+ }
+ }
+ return llvm::DINodeArray();
+}
+
llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) {
// Always get the full list of parameters, not just the ones from
@@ -1896,8 +1994,17 @@ static bool isDefinedInClangModule(const RecordDecl *RD) {
if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
if (!CXXDecl->isCompleteDefinition())
return false;
+ // Check wether RD is a template.
auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
if (TemplateKind != TSK_Undeclared) {
+ // Unfortunately getOwningModule() isn't accurate enough to find the
+ // owning module of a ClassTemplateSpecializationDecl that is inside a
+ // namespace spanning multiple modules.
+ bool Explicit = false;
+ if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(CXXDecl))
+ Explicit = TD->isExplicitInstantiationOrSpecialization();
+ if (!Explicit && CXXDecl->getEnclosingNamespaceContext())
+ return false;
// This is a template, check the origin of the first member.
if (CXXDecl->field_begin() == CXXDecl->field_end())
return TemplateKind == TSK_ExplicitInstantiationDeclaration;
@@ -2445,9 +2552,9 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
Count = CAT->getSize().getZExtValue();
else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
if (Expr *Size = VAT->getSizeExpr()) {
- llvm::APSInt V;
- if (Size->EvaluateAsInt(V, CGM.getContext()))
- Count = V.getExtValue();
+ Expr::EvalResult Result;
+ if (Size->EvaluateAsInt(Result, CGM.getContext()))
+ Count = Result.Val.getInt().getExtValue();
}
}
@@ -2513,9 +2620,9 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
const FunctionProtoType *FPT =
Ty->getPointeeType()->getAs<FunctionProtoType>();
return DBuilder.createMemberPointerType(
- getOrCreateInstanceMethodType(CGM.getContext().getPointerType(QualType(
- Ty->getClass(), FPT->getTypeQuals())),
- FPT, U),
+ getOrCreateInstanceMethodType(
+ CXXMethodDecl::getThisType(FPT, Ty->getMostRecentCXXRecordDecl()),
+ FPT, U),
ClassType, Size, /*Align=*/0, Flags);
}
@@ -2603,7 +2710,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit);
return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit,
Line, Size, Align, EltArray, ClassTy,
- Identifier, ED->isFixed());
+ Identifier, ED->isScoped());
}
llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent,
@@ -3035,6 +3142,7 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
unsigned &LineNo, QualType &T,
StringRef &Name, StringRef &LinkageName,
+ llvm::MDTuple *&TemplateParameters,
llvm::DIScope *&VDContext) {
Unit = getOrCreateFile(VD->getLocation());
LineNo = getLineNumber(VD->getLocation());
@@ -3058,6 +3166,13 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
if (LinkageName == Name)
LinkageName = StringRef();
+ if (isa<VarTemplateSpecializationDecl>(VD)) {
+ llvm::DINodeArray parameterNodes = CollectVarTemplateParams(VD, &*Unit);
+ TemplateParameters = parameterNodes.get();
+ } else {
+ TemplateParameters = nullptr;
+ }
+
// Since we emit declarations (DW_AT_members) for static members, place the
// definition of those static members in the namespace they were declared in
// in the source code (the lexical decl context).
@@ -3084,6 +3199,7 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
llvm::DINodeArray TParamsArray;
StringRef Name, LinkageName;
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
+ llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
SourceLocation Loc = GD.getDecl()->getLocation();
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *DContext = Unit;
@@ -3100,20 +3216,23 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv();
QualType FnType = CGM.getContext().getFunctionType(
FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC));
+ if (!FD->isExternallyVisible())
+ SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
+ if (CGM.getLangOpts().Optimize)
+ SPFlags |= llvm::DISubprogram::SPFlagOptimized;
+
if (Stub) {
+ Flags |= getCallSiteRelatedAttrs();
+ SPFlags |= llvm::DISubprogram::SPFlagDefinition;
return DBuilder.createFunction(
DContext, Name, LinkageName, Unit, Line,
- getOrCreateFunctionType(GD.getDecl(), FnType, Unit),
- !FD->isExternallyVisible(),
- /* isDefinition = */ true, 0, Flags, CGM.getLangOpts().Optimize,
+ getOrCreateFunctionType(GD.getDecl(), FnType, Unit), 0, Flags, SPFlags,
TParamsArray.get(), getFunctionDeclaration(FD));
}
llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl(
DContext, Name, LinkageName, Unit, Line,
- getOrCreateFunctionType(GD.getDecl(), FnType, Unit),
- !FD->isExternallyVisible(),
- /* isDefinition = */ false, 0, Flags, CGM.getLangOpts().Optimize,
+ getOrCreateFunctionType(GD.getDecl(), FnType, Unit), 0, Flags, SPFlags,
TParamsArray.get(), getFunctionDeclaration(FD));
const FunctionDecl *CanonDecl = FD->getCanonicalDecl();
FwdDeclReplaceMap.emplace_back(std::piecewise_construct,
@@ -3138,12 +3257,14 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *DContext = Unit;
unsigned Line = getLineNumber(Loc);
+ llvm::MDTuple *TemplateParameters = nullptr;
- collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
+ collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, TemplateParameters,
+ DContext);
auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
auto *GV = DBuilder.createTempGlobalVariableFwdDecl(
DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit),
- !VD->isExternallyVisible(), nullptr, Align);
+ !VD->isExternallyVisible(), nullptr, TemplateParameters, Align);
FwdDeclReplaceMap.emplace_back(
std::piecewise_construct,
std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())),
@@ -3299,6 +3420,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
bool HasDecl = (D != nullptr);
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
+ llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *FDContext = Unit;
llvm::DINodeArray TParamsArray;
@@ -3338,6 +3460,15 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
if (CurFuncIsThunk)
Flags |= llvm::DINode::FlagThunk;
+ if (Fn->hasLocalLinkage())
+ SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
+ if (CGM.getLangOpts().Optimize)
+ SPFlags |= llvm::DISubprogram::SPFlagOptimized;
+
+ llvm::DINode::DIFlags FlagsForDef = Flags | getCallSiteRelatedAttrs();
+ llvm::DISubprogram::DISPFlags SPFlagsForDef =
+ SPFlags | llvm::DISubprogram::SPFlagDefinition;
+
unsigned LineNo = getLineNumber(Loc);
unsigned ScopeLine = getLineNumber(ScopeLoc);
@@ -3348,9 +3479,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
// are emitted as CU level entities by the backend.
llvm::DISubprogram *SP = DBuilder.createFunction(
FDContext, Name, LinkageName, Unit, LineNo,
- getOrCreateFunctionType(D, FnType, Unit), Fn->hasLocalLinkage(),
- true /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize,
- TParamsArray.get(), getFunctionDeclaration(D));
+ getOrCreateFunctionType(D, FnType, Unit), ScopeLine, FlagsForDef,
+ SPFlagsForDef, TParamsArray.get(), getFunctionDeclaration(D));
Fn->setSubprogram(SP);
// We might get here with a VarDecl in the case we're generating
// code for the initialization of globals. Do not record these decls
@@ -3370,8 +3500,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
cast<llvm::DICompositeType>(It->second);
llvm::DISubprogram *FD = DBuilder.createFunction(
InterfaceDecl, Name, LinkageName, Unit, LineNo,
- getOrCreateFunctionType(D, FnType, Unit), Fn->hasLocalLinkage(),
- false /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize,
+ getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags,
TParamsArray.get());
DBuilder.finalizeSubprogram(FD);
ObjCMethodCache[ID].push_back(FD);
@@ -3420,11 +3549,13 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
}
unsigned LineNo = getLineNumber(Loc);
unsigned ScopeLine = 0;
+ llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
+ if (CGM.getLangOpts().Optimize)
+ SPFlags |= llvm::DISubprogram::SPFlagOptimized;
DBuilder.retainType(DBuilder.createFunction(
FDContext, Name, LinkageName, Unit, LineNo,
- getOrCreateFunctionType(D, FnType, Unit), false /*internalLinkage*/,
- false /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize,
+ getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags,
TParamsArray.get(), getFunctionDeclaration(D)));
}
@@ -3453,7 +3584,7 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
// Update our current location
setLocation(Loc);
- if (CurLoc.isInvalid() || CurLoc.isMacroID())
+ if (CurLoc.isInvalid() || CurLoc.isMacroID() || LexicalBlockStack.empty())
return;
llvm::MDNode *Scope = LexicalBlockStack.back();
@@ -3530,9 +3661,9 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn) {
DBuilder.finalizeSubprogram(Fn->getSubprogram());
}
-llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
- uint64_t *XOffset) {
-
+CGDebugInfo::BlockByRefType
+CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
+ uint64_t *XOffset) {
SmallVector<llvm::Metadata *, 5> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
@@ -3584,23 +3715,21 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
}
FType = Type;
- llvm::DIType *FieldTy = getOrCreateType(FType, Unit);
+ llvm::DIType *WrappedTy = getOrCreateType(FType, Unit);
FieldSize = CGM.getContext().getTypeSize(FType);
FieldAlign = CGM.getContext().toBits(Align);
*XOffset = FieldOffset;
- FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit, 0, FieldSize,
- FieldAlign, FieldOffset,
- llvm::DINode::FlagZero, FieldTy);
+ llvm::DIType *FieldTy = DBuilder.createMemberType(
+ Unit, VD->getName(), Unit, 0, FieldSize, FieldAlign, FieldOffset,
+ llvm::DINode::FlagZero, WrappedTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
-
- llvm::DINode::DIFlags Flags = llvm::DINode::FlagBlockByrefStruct;
-
- return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
- nullptr, Elements);
+ return {DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0,
+ llvm::DINode::FlagZero, nullptr, Elements),
+ WrappedTy};
}
llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
@@ -3621,7 +3750,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
llvm::DIType *Ty;
uint64_t XOffset = 0;
if (VD->hasAttr<BlocksAttr>())
- Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
+ Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
else
Ty = getOrCreateType(VD->getType(), Unit);
@@ -3759,7 +3888,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
llvm::DIType *Ty;
if (isByRef)
- Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
+ Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
else
Ty = getOrCreateType(VD->getType(), Unit);
@@ -3830,6 +3959,44 @@ bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
}
} // namespace
+void CGDebugInfo::collectDefaultFieldsForBlockLiteralDeclare(
+ const CGBlockInfo &Block, const ASTContext &Context, SourceLocation Loc,
+ const llvm::StructLayout &BlockLayout, llvm::DIFile *Unit,
+ SmallVectorImpl<llvm::Metadata *> &Fields) {
+ // Blocks in OpenCL have unique constraints which make the standard fields
+ // redundant while requiring size and align fields for enqueue_kernel. See
+ // initializeForBlockHeader in CGBlocks.cpp
+ if (CGM.getLangOpts().OpenCL) {
+ Fields.push_back(createFieldType("__size", Context.IntTy, Loc, AS_public,
+ BlockLayout.getElementOffsetInBits(0),
+ Unit, Unit));
+ Fields.push_back(createFieldType("__align", Context.IntTy, Loc, AS_public,
+ BlockLayout.getElementOffsetInBits(1),
+ Unit, Unit));
+ } else {
+ Fields.push_back(createFieldType("__isa", Context.VoidPtrTy, Loc, AS_public,
+ BlockLayout.getElementOffsetInBits(0),
+ Unit, Unit));
+ Fields.push_back(createFieldType("__flags", Context.IntTy, Loc, AS_public,
+ BlockLayout.getElementOffsetInBits(1),
+ Unit, Unit));
+ Fields.push_back(
+ createFieldType("__reserved", Context.IntTy, Loc, AS_public,
+ BlockLayout.getElementOffsetInBits(2), Unit, Unit));
+ auto *FnTy = Block.getBlockExpr()->getFunctionType();
+ auto FnPtrType = CGM.getContext().getPointerType(FnTy->desugar());
+ Fields.push_back(createFieldType("__FuncPtr", FnPtrType, Loc, AS_public,
+ BlockLayout.getElementOffsetInBits(3),
+ Unit, Unit));
+ Fields.push_back(createFieldType(
+ "__descriptor",
+ Context.getPointerType(Block.NeedsCopyDispose
+ ? Context.getBlockDescriptorExtendedType()
+ : Context.getBlockDescriptorType()),
+ Loc, AS_public, BlockLayout.getElementOffsetInBits(4), Unit, Unit));
+ }
+}
+
void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
StringRef Name,
unsigned ArgNo,
@@ -3852,35 +4019,8 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
CGM.getDataLayout().getStructLayout(block.StructureType);
SmallVector<llvm::Metadata *, 16> fields;
- if (CGM.getLangOpts().OpenCL) {
- fields.push_back(createFieldType("__size", C.IntTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(0),
- tunit, tunit));
- fields.push_back(createFieldType("__align", C.IntTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(1),
- tunit, tunit));
- } else {
- fields.push_back(createFieldType("__isa", C.VoidPtrTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(0),
- tunit, tunit));
- fields.push_back(createFieldType("__flags", C.IntTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(1),
- tunit, tunit));
- fields.push_back(createFieldType("__reserved", C.IntTy, loc, AS_public,
- blockLayout->getElementOffsetInBits(2),
- tunit, tunit));
- auto *FnTy = block.getBlockExpr()->getFunctionType();
- auto FnPtrType = CGM.getContext().getPointerType(FnTy->desugar());
- fields.push_back(createFieldType("__FuncPtr", FnPtrType, loc, AS_public,
- blockLayout->getElementOffsetInBits(3),
- tunit, tunit));
- fields.push_back(createFieldType(
- "__descriptor",
- C.getPointerType(block.NeedsCopyDispose
- ? C.getBlockDescriptorExtendedType()
- : C.getBlockDescriptorType()),
- loc, AS_public, blockLayout->getElementOffsetInBits(4), tunit, tunit));
- }
+ collectDefaultFieldsForBlockLiteralDeclare(block, C, loc, *blockLayout, tunit,
+ fields);
// We want to sort the captures by offset, not because DWARF
// requires this, but because we're paranoid about debuggers.
@@ -3923,7 +4063,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
QualType type;
if (auto *Method =
cast_or_null<CXXMethodDecl>(blockDecl->getNonClosureContext()))
- type = Method->getThisType(C);
+ type = Method->getThisType();
else if (auto *RDecl = dyn_cast<CXXRecordDecl>(blockDecl->getParent()))
type = QualType(RDecl->getTypeForDecl(), 0);
else
@@ -3941,10 +4081,10 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
if (capture->isByRef()) {
TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy);
auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0;
-
- // FIXME: this creates a second copy of this type!
+ // FIXME: This recomputes the layout of the BlockByRefWrapper.
uint64_t xoffset;
- fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
+ fieldType =
+ EmitTypeForVarWithBlocksAttr(variable, &xoffset).BlockByRefWrapper;
fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width);
fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
PtrInfo.Width, Align, offsetInBits,
@@ -4045,7 +4185,9 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
unsigned LineNo;
StringRef DeclName, LinkageName;
QualType T;
- collectVarDeclProps(D, Unit, LineNo, T, DeclName, LinkageName, DContext);
+ llvm::MDTuple *TemplateParameters = nullptr;
+ collectVarDeclProps(D, Unit, LineNo, T, DeclName, LinkageName,
+ TemplateParameters, DContext);
// Attempt to store one global variable for the declaration - even if we
// emit a lot of fields.
@@ -4071,7 +4213,8 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
Var->hasLocalLinkage(),
Expr.empty() ? nullptr : DBuilder.createExpression(Expr),
- getOrCreateStaticDataMemberDeclarationOrNull(D), Align);
+ getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters,
+ Align);
Var->addDebugInfo(GVE);
}
DeclCache[D->getCanonicalDecl()].reset(GVE);
@@ -4128,10 +4271,19 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
InitExpr = DBuilder.createConstantValueExpression(
Init.getFloat().bitcastToAPInt().getZExtValue());
}
+
+ llvm::MDTuple *TemplateParameters = nullptr;
+
+ if (isa<VarTemplateSpecializationDecl>(VD))
+ if (VarD) {
+ llvm::DINodeArray parameterNodes = CollectVarTemplateParams(VarD, &*Unit);
+ TemplateParameters = parameterNodes.get();
+ }
+
GV.reset(DBuilder.createGlobalVariableExpression(
DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty,
true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD),
- Align));
+ TemplateParameters, Align));
}
llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
@@ -4320,7 +4472,7 @@ void CGDebugInfo::EmitExplicitCastType(QualType Ty) {
if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo)
return;
- if (auto *DieTy = getOrCreateType(Ty, getOrCreateMainFile()))
+ if (auto *DieTy = getOrCreateType(Ty, TheCU->getFile()))
// Don't ignore in case of explicit cast where it is referenced indirectly.
DBuilder.retainType(DieTy);
}
@@ -4332,3 +4484,22 @@ llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) {
llvm::MDNode *Scope = LexicalBlockStack.back();
return llvm::DebugLoc::get(getLineNumber(Loc), getColumnNumber(Loc), Scope);
}
+
+llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const {
+ // Call site-related attributes are only useful in optimized programs, and
+ // when there's a possibility of debugging backtraces.
+ if (!CGM.getLangOpts().Optimize || DebugKind == codegenoptions::NoDebugInfo ||
+ DebugKind == codegenoptions::LocTrackingOnly)
+ return llvm::DINode::FlagZero;
+
+ // Call site-related attributes are available in DWARF v5. Some debuggers,
+ // while not fully DWARF v5-compliant, may accept these attributes as if they
+ // were part of DWARF v4.
+ bool SupportsDWARFv4Ext =
+ CGM.getCodeGenOpts().DwarfVersion == 4 &&
+ CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB;
+ if (!SupportsDWARFv4Ext && CGM.getCodeGenOpts().DwarfVersion < 5)
+ return llvm::DINode::FlagZero;
+
+ return llvm::DINode::FlagAllCallsDescribed;
+}
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index e632806138f0..031e40b9dde9 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -20,8 +20,8 @@
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
@@ -76,6 +76,9 @@ class CGDebugInfo {
llvm::DIType *OCLQueueDITy = nullptr;
llvm::DIType *OCLNDRangeDITy = nullptr;
llvm::DIType *OCLReserveIDDITy = nullptr;
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ llvm::DIType *Id##Ty = nullptr;
+#include "clang/Basic/OpenCLExtensionTypes.def"
/// Cache of previously constructed Types.
llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache;
@@ -248,6 +251,11 @@ class CGDebugInfo {
llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD,
llvm::DIFile *Unit);
+ /// A helper function to collect debug info for function template
+ /// parameters.
+ llvm::DINodeArray CollectVarTemplateParams(const VarDecl *VD,
+ llvm::DIFile *Unit);
+
/// A helper function to collect debug info for template
/// parameters.
llvm::DINodeArray
@@ -311,12 +319,31 @@ class CGDebugInfo {
void AppendAddressSpaceXDeref(unsigned AddressSpace,
SmallVectorImpl<int64_t> &Expr) const;
+ /// A helper function to collect debug info for the default elements of a
+ /// block.
+ ///
+ /// \returns The next available field offset after the default elements.
+ uint64_t collectDefaultElementTypesForBlockPointer(
+ const BlockPointerType *Ty, llvm::DIFile *Unit,
+ llvm::DIDerivedType *DescTy, unsigned LineNo,
+ SmallVectorImpl<llvm::Metadata *> &EltTys);
+
+ /// A helper function to collect debug info for the default fields of a
+ /// block.
+ void collectDefaultFieldsForBlockLiteralDeclare(
+ const CGBlockInfo &Block, const ASTContext &Context, SourceLocation Loc,
+ const llvm::StructLayout &BlockLayout, llvm::DIFile *Unit,
+ SmallVectorImpl<llvm::Metadata *> &Fields);
+
public:
CGDebugInfo(CodeGenModule &CGM);
~CGDebugInfo();
void finalize();
+ /// Remap a given path with the current debug prefix map
+ std::string remapDIPath(StringRef) const;
+
/// Register VLA size expression debug node with the qualified type.
void registerVLASizeExpression(QualType Ty, llvm::Metadata *SizeExpr) {
SizeExprCache[Ty] = SizeExpr;
@@ -475,9 +502,16 @@ private:
llvm::Optional<unsigned> ArgNo,
CGBuilderTy &Builder);
+ struct BlockByRefType {
+ /// The wrapper struct used inside the __block_literal struct.
+ llvm::DIType *BlockByRefWrapper;
+ /// The type as it appears in the source code.
+ llvm::DIType *WrappedType;
+ };
+
/// Build up structure info for the byref. See \a BuildByRefType.
- llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
- uint64_t *OffSet);
+ BlockByRefType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
+ uint64_t *OffSet);
/// Get context info for the DeclContext of \p Decl.
llvm::DIScope *getDeclContextDescriptor(const Decl *D);
@@ -497,9 +531,6 @@ private:
/// Create new compile unit.
void CreateCompileUnit();
- /// Remap a given path with the current debug prefix map
- std::string remapDIPath(StringRef) const;
-
/// Compute the file checksum debug info for input file ID.
Optional<llvm::DIFile::ChecksumKind>
computeChecksum(FileID FID, SmallString<32> &Checksum) const;
@@ -507,11 +538,15 @@ private:
/// Get the source of the given file ID.
Optional<StringRef> getSource(const SourceManager &SM, FileID FID);
- /// Get the file debug info descriptor for the input location.
+ /// Convenience function to get the file debug info descriptor for the input
+ /// location.
llvm::DIFile *getOrCreateFile(SourceLocation Loc);
- /// Get the file info for main compile unit.
- llvm::DIFile *getOrCreateMainFile();
+ /// Create a file debug info descriptor for a source file.
+ llvm::DIFile *
+ createFile(StringRef FileName,
+ Optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo,
+ Optional<StringRef> Source);
/// Get the type from the cache or create a new type if necessary.
llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
@@ -580,6 +615,11 @@ private:
unsigned LineNo, StringRef LinkageName,
llvm::GlobalVariable *Var, llvm::DIScope *DContext);
+
+ /// Return flags which enable debug info emission for call sites, provided
+ /// that it is supported and enabled.
+ llvm::DINode::DIFlags getCallSiteRelatedAttrs() const;
+
/// Get the printing policy for producing names for debug info.
PrintingPolicy getPrintingPolicy() const;
@@ -622,7 +662,9 @@ private:
/// Collect various properties of a VarDecl.
void collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
unsigned &LineNo, QualType &T, StringRef &Name,
- StringRef &LinkageName, llvm::DIScope *&VDContext);
+ StringRef &LinkageName,
+ llvm::MDTuple *&TemplateParameters,
+ llvm::DIScope *&VDContext);
/// Allocate a copy of \p A using the DebugInfoNames allocator
/// and return a reference to it. If multiple arguments are given the strings
@@ -702,7 +744,7 @@ public:
/// function \p InlinedFn. The current debug location becomes the inlined call
/// site of the inlined function.
ApplyInlineDebugLocation(CodeGenFunction &CGF, GlobalDecl InlinedFn);
- /// Restore everything back to the orginial state.
+ /// Restore everything back to the original state.
~ApplyInlineDebugLocation();
};
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 57b2fbadbeec..5959d889b455 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -26,10 +26,11 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Intrinsics.h"
@@ -104,6 +105,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::OMPCapturedExpr:
+ case Decl::OMPRequires:
case Decl::Empty:
// None of these decls require codegen support.
return;
@@ -545,7 +547,7 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) override {
// Compute the address of the local variable, in case it's a
// byref or something.
- DeclRefExpr DRE(const_cast<VarDecl*>(&Var), false,
+ DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false,
Var.getType(), VK_LValue, SourceLocation());
llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE),
SourceLocation());
@@ -563,7 +565,7 @@ namespace {
: CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- DeclRefExpr DRE(const_cast<VarDecl*>(&Var), false,
+ DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(&Var), false,
Var.getType(), VK_LValue, SourceLocation());
// Compute the address of the local variable, in case it's a byref
// or something.
@@ -752,9 +754,9 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
// If we're emitting a value with lifetime, we have to do the
// initialization *before* we leave the cleanup scopes.
- if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init)) {
- enterFullExpression(ewc);
- init = ewc->getSubExpr();
+ if (const FullExpr *fe = dyn_cast<FullExpr>(init)) {
+ enterFullExpression(fe);
+ init = fe->getSubExpr();
}
CodeGenFunction::RunCleanupsScope Scope(*this);
@@ -795,15 +797,21 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
case Qualifiers::OCL_None:
llvm_unreachable("present but none");
+ case Qualifiers::OCL_Strong: {
+ if (!D || !isa<VarDecl>(D) || !cast<VarDecl>(D)->isARCPseudoStrong()) {
+ value = EmitARCRetainScalarExpr(init);
+ break;
+ }
+ // If D is pseudo-strong, treat it like __unsafe_unretained here. This means
+ // that we omit the retain, and causes non-autoreleased return values to be
+ // immediately released.
+ LLVM_FALLTHROUGH;
+ }
+
case Qualifiers::OCL_ExplicitNone:
value = EmitARCUnsafeUnretainedScalarExpr(init);
break;
- case Qualifiers::OCL_Strong: {
- value = EmitARCRetainScalarExpr(init);
- break;
- }
-
case Qualifiers::OCL_Weak: {
// If it's not accessed by the initializer, try to emit the
// initialization with a copy or move.
@@ -948,111 +956,242 @@ static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init,
canEmitInitWithFewStoresAfterBZero(Init, StoreBudget);
}
-/// A byte pattern.
-///
-/// Can be "any" pattern if the value was padding or known to be undef.
-/// Can be "none" pattern if a sequence doesn't exist.
-class BytePattern {
- uint8_t Val;
- enum class ValueType : uint8_t { Specific, Any, None } Type;
- BytePattern(ValueType Type) : Type(Type) {}
-
-public:
- BytePattern(uint8_t Value) : Val(Value), Type(ValueType::Specific) {}
- static BytePattern Any() { return BytePattern(ValueType::Any); }
- static BytePattern None() { return BytePattern(ValueType::None); }
- bool isAny() const { return Type == ValueType::Any; }
- bool isNone() const { return Type == ValueType::None; }
- bool isValued() const { return Type == ValueType::Specific; }
- uint8_t getValue() const {
- assert(isValued());
- return Val;
- }
- BytePattern merge(const BytePattern Other) const {
- if (isNone() || Other.isNone())
- return None();
- if (isAny())
- return Other;
- if (Other.isAny())
- return *this;
- if (getValue() == Other.getValue())
- return *this;
- return None();
- }
-};
-
-/// Figures out whether the constant can be initialized with memset.
-static BytePattern constantIsRepeatedBytePattern(llvm::Constant *C) {
- if (isa<llvm::ConstantAggregateZero>(C) || isa<llvm::ConstantPointerNull>(C))
- return BytePattern(0x00);
- if (isa<llvm::UndefValue>(C))
- return BytePattern::Any();
-
- if (isa<llvm::ConstantInt>(C)) {
- auto *Int = cast<llvm::ConstantInt>(C);
- if (Int->getBitWidth() % 8 != 0)
- return BytePattern::None();
- const llvm::APInt &Value = Int->getValue();
- if (Value.isSplat(8))
- return BytePattern(Value.getLoBits(8).getLimitedValue());
- return BytePattern::None();
- }
-
- if (isa<llvm::ConstantFP>(C)) {
- auto *FP = cast<llvm::ConstantFP>(C);
- llvm::APInt Bits = FP->getValueAPF().bitcastToAPInt();
- if (Bits.getBitWidth() % 8 != 0)
- return BytePattern::None();
- if (!Bits.isSplat(8))
- return BytePattern::None();
- return BytePattern(Bits.getLimitedValue() & 0xFF);
- }
-
- if (isa<llvm::ConstantVector>(C)) {
- llvm::Constant *Splat = cast<llvm::ConstantVector>(C)->getSplatValue();
- if (Splat)
- return constantIsRepeatedBytePattern(Splat);
- return BytePattern::None();
- }
-
- if (isa<llvm::ConstantArray>(C) || isa<llvm::ConstantStruct>(C)) {
- BytePattern Pattern(BytePattern::Any());
- for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) {
- llvm::Constant *Elt = cast<llvm::Constant>(C->getOperand(I));
- Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt));
- if (Pattern.isNone())
- return Pattern;
+/// Decide whether we should use memset to initialize a local variable instead
+/// of using a memcpy from a constant global. Assumes we've already decided to
+/// not user bzero.
+/// FIXME We could be more clever, as we are for bzero above, and generate
+/// memset followed by stores. It's unclear that's worth the effort.
+static llvm::Value *shouldUseMemSetToInitialize(llvm::Constant *Init,
+ uint64_t GlobalSize) {
+ uint64_t SizeLimit = 32;
+ if (GlobalSize <= SizeLimit)
+ return nullptr;
+ return llvm::isBytewiseValue(Init);
+}
+
+static llvm::Constant *patternFor(CodeGenModule &CGM, llvm::Type *Ty) {
+ // The following value is a guaranteed unmappable pointer value and has a
+ // repeated byte-pattern which makes it easier to synthesize. We use it for
+ // pointers as well as integers so that aggregates are likely to be
+ // initialized with this repeated value.
+ constexpr uint64_t LargeValue = 0xAAAAAAAAAAAAAAAAull;
+ // For 32-bit platforms it's a bit trickier because, across systems, only the
+ // zero page can reasonably be expected to be unmapped, and even then we need
+ // a very low address. We use a smaller value, and that value sadly doesn't
+ // have a repeated byte-pattern. We don't use it for integers.
+ constexpr uint32_t SmallValue = 0x000000AA;
+ // Floating-point values are initialized as NaNs because they propagate. Using
+ // a repeated byte pattern means that it will be easier to initialize
+ // all-floating-point aggregates and arrays with memset. Further, aggregates
+ // which mix integral and a few floats might also initialize with memset
+ // followed by a handful of stores for the floats. Using fairly unique NaNs
+ // also means they'll be easier to distinguish in a crash.
+ constexpr bool NegativeNaN = true;
+ constexpr uint64_t NaNPayload = 0xFFFFFFFFFFFFFFFFull;
+ if (Ty->isIntOrIntVectorTy()) {
+ unsigned BitWidth = cast<llvm::IntegerType>(
+ Ty->isVectorTy() ? Ty->getVectorElementType() : Ty)
+ ->getBitWidth();
+ if (BitWidth <= 64)
+ return llvm::ConstantInt::get(Ty, LargeValue);
+ return llvm::ConstantInt::get(
+ Ty, llvm::APInt::getSplat(BitWidth, llvm::APInt(64, LargeValue)));
+ }
+ if (Ty->isPtrOrPtrVectorTy()) {
+ auto *PtrTy = cast<llvm::PointerType>(
+ Ty->isVectorTy() ? Ty->getVectorElementType() : Ty);
+ unsigned PtrWidth = CGM.getContext().getTargetInfo().getPointerWidth(
+ PtrTy->getAddressSpace());
+ llvm::Type *IntTy = llvm::IntegerType::get(CGM.getLLVMContext(), PtrWidth);
+ uint64_t IntValue;
+ switch (PtrWidth) {
+ default:
+ llvm_unreachable("pattern initialization of unsupported pointer width");
+ case 64:
+ IntValue = LargeValue;
+ break;
+ case 32:
+ IntValue = SmallValue;
+ break;
}
- return Pattern;
+ auto *Int = llvm::ConstantInt::get(IntTy, IntValue);
+ return llvm::ConstantExpr::getIntToPtr(Int, PtrTy);
+ }
+ if (Ty->isFPOrFPVectorTy()) {
+ unsigned BitWidth = llvm::APFloat::semanticsSizeInBits(
+ (Ty->isVectorTy() ? Ty->getVectorElementType() : Ty)
+ ->getFltSemantics());
+ llvm::APInt Payload(64, NaNPayload);
+ if (BitWidth >= 64)
+ Payload = llvm::APInt::getSplat(BitWidth, Payload);
+ return llvm::ConstantFP::getQNaN(Ty, NegativeNaN, &Payload);
+ }
+ if (Ty->isArrayTy()) {
+ // Note: this doesn't touch tail padding (at the end of an object, before
+ // the next array object). It is instead handled by replaceUndef.
+ auto *ArrTy = cast<llvm::ArrayType>(Ty);
+ llvm::SmallVector<llvm::Constant *, 8> Element(
+ ArrTy->getNumElements(), patternFor(CGM, ArrTy->getElementType()));
+ return llvm::ConstantArray::get(ArrTy, Element);
+ }
+
+ // Note: this doesn't touch struct padding. It will initialize as much union
+ // padding as is required for the largest type in the union. Padding is
+ // instead handled by replaceUndef. Stores to structs with volatile members
+ // don't have a volatile qualifier when initialized according to C++. This is
+ // fine because stack-based volatiles don't really have volatile semantics
+ // anyways, and the initialization shouldn't be observable.
+ auto *StructTy = cast<llvm::StructType>(Ty);
+ llvm::SmallVector<llvm::Constant *, 8> Struct(StructTy->getNumElements());
+ for (unsigned El = 0; El != Struct.size(); ++El)
+ Struct[El] = patternFor(CGM, StructTy->getElementType(El));
+ return llvm::ConstantStruct::get(StructTy, Struct);
+}
+
+static Address createUnnamedGlobalFrom(CodeGenModule &CGM, const VarDecl &D,
+ CGBuilderTy &Builder,
+ llvm::Constant *Constant,
+ CharUnits Align) {
+ auto FunctionName = [&](const DeclContext *DC) -> std::string {
+ if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
+ if (const auto *CC = dyn_cast<CXXConstructorDecl>(FD))
+ return CC->getNameAsString();
+ if (const auto *CD = dyn_cast<CXXDestructorDecl>(FD))
+ return CD->getNameAsString();
+ return CGM.getMangledName(FD);
+ } else if (const auto *OM = dyn_cast<ObjCMethodDecl>(DC)) {
+ return OM->getNameAsString();
+ } else if (isa<BlockDecl>(DC)) {
+ return "<block>";
+ } else if (isa<CapturedDecl>(DC)) {
+ return "<captured>";
+ } else {
+ llvm::llvm_unreachable_internal("expected a function or method");
+ }
+ };
+
+ auto *Ty = Constant->getType();
+ bool isConstant = true;
+ llvm::GlobalVariable *InsertBefore = nullptr;
+ unsigned AS = CGM.getContext().getTargetAddressSpace(
+ CGM.getStringLiteralAddressSpace());
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ CGM.getModule(), Ty, isConstant, llvm::GlobalValue::PrivateLinkage,
+ Constant,
+ "__const." + FunctionName(D.getParentFunctionOrMethod()) + "." +
+ D.getName(),
+ InsertBefore, llvm::GlobalValue::NotThreadLocal, AS);
+ GV->setAlignment(Align.getQuantity());
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
+ Address SrcPtr = Address(GV, Align);
+ llvm::Type *BP = llvm::PointerType::getInt8PtrTy(CGM.getLLVMContext(), AS);
+ if (SrcPtr.getType() != BP)
+ SrcPtr = Builder.CreateBitCast(SrcPtr, BP);
+ return SrcPtr;
+}
+
+static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
+ Address Loc, bool isVolatile,
+ CGBuilderTy &Builder,
+ llvm::Constant *constant) {
+ auto *Ty = constant->getType();
+ bool isScalar = Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy() ||
+ Ty->isFPOrFPVectorTy();
+ if (isScalar) {
+ Builder.CreateStore(constant, Loc, isVolatile);
+ return;
}
- if (llvm::ConstantDataSequential *CDS =
- dyn_cast<llvm::ConstantDataSequential>(C)) {
- BytePattern Pattern(BytePattern::Any());
- for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) {
- llvm::Constant *Elt = CDS->getElementAsConstant(I);
- Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt));
- if (Pattern.isNone())
- return Pattern;
+ auto *Int8Ty = llvm::IntegerType::getInt8Ty(CGM.getLLVMContext());
+ auto *IntPtrTy = CGM.getDataLayout().getIntPtrType(CGM.getLLVMContext());
+
+ // If the initializer is all or mostly the same, codegen with bzero / memset
+ // then do a few stores afterward.
+ uint64_t ConstantSize = CGM.getDataLayout().getTypeAllocSize(Ty);
+ auto *SizeVal = llvm::ConstantInt::get(IntPtrTy, ConstantSize);
+ if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) {
+ Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
+ isVolatile);
+
+ bool valueAlreadyCorrect =
+ constant->isNullValue() || isa<llvm::UndefValue>(constant);
+ if (!valueAlreadyCorrect) {
+ Loc = Builder.CreateBitCast(Loc, Ty->getPointerTo(Loc.getAddressSpace()));
+ emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder);
+ }
+ return;
+ }
+
+ llvm::Value *Pattern = shouldUseMemSetToInitialize(constant, ConstantSize);
+ if (Pattern) {
+ uint64_t Value = 0x00;
+ if (!isa<llvm::UndefValue>(Pattern)) {
+ const llvm::APInt &AP = cast<llvm::ConstantInt>(Pattern)->getValue();
+ assert(AP.getBitWidth() <= 8);
+ Value = AP.getLimitedValue();
}
- return Pattern;
+ Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, Value), SizeVal,
+ isVolatile);
+ return;
}
- // BlockAddress, ConstantExpr, and everything else is scary.
- return BytePattern::None();
+ Builder.CreateMemCpy(
+ Loc,
+ createUnnamedGlobalFrom(CGM, D, Builder, constant, Loc.getAlignment()),
+ SizeVal, isVolatile);
}
-/// Decide whether we should use memset to initialize a local variable instead
-/// of using a memcpy from a constant global. Assumes we've already decided to
-/// not user bzero.
-/// FIXME We could be more clever, as we are for bzero above, and generate
-/// memset followed by stores. It's unclear that's worth the effort.
-static BytePattern shouldUseMemSetToInitialize(llvm::Constant *Init,
- uint64_t GlobalSize) {
- uint64_t SizeLimit = 32;
- if (GlobalSize <= SizeLimit)
- return BytePattern::None();
- return constantIsRepeatedBytePattern(Init);
+static void emitStoresForZeroInit(CodeGenModule &CGM, const VarDecl &D,
+ Address Loc, bool isVolatile,
+ CGBuilderTy &Builder) {
+ llvm::Type *ElTy = Loc.getElementType();
+ llvm::Constant *constant = llvm::Constant::getNullValue(ElTy);
+ emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
+}
+
+static void emitStoresForPatternInit(CodeGenModule &CGM, const VarDecl &D,
+ Address Loc, bool isVolatile,
+ CGBuilderTy &Builder) {
+ llvm::Type *ElTy = Loc.getElementType();
+ llvm::Constant *constant = patternFor(CGM, ElTy);
+ assert(!isa<llvm::UndefValue>(constant));
+ emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
+}
+
+static bool containsUndef(llvm::Constant *constant) {
+ auto *Ty = constant->getType();
+ if (isa<llvm::UndefValue>(constant))
+ return true;
+ if (Ty->isStructTy() || Ty->isArrayTy() || Ty->isVectorTy())
+ for (llvm::Use &Op : constant->operands())
+ if (containsUndef(cast<llvm::Constant>(Op)))
+ return true;
+ return false;
+}
+
+static llvm::Constant *replaceUndef(llvm::Constant *constant) {
+ // FIXME: when doing pattern initialization, replace undef with 0xAA instead.
+ // FIXME: also replace padding between values by creating a new struct type
+ // which has no padding.
+ auto *Ty = constant->getType();
+ if (isa<llvm::UndefValue>(constant))
+ return llvm::Constant::getNullValue(Ty);
+ if (!(Ty->isStructTy() || Ty->isArrayTy() || Ty->isVectorTy()))
+ return constant;
+ if (!containsUndef(constant))
+ return constant;
+ llvm::SmallVector<llvm::Constant *, 8> Values(constant->getNumOperands());
+ for (unsigned Op = 0, NumOp = constant->getNumOperands(); Op != NumOp; ++Op) {
+ auto *OpValue = cast<llvm::Constant>(constant->getOperand(Op));
+ Values[Op] = replaceUndef(OpValue);
+ }
+ if (Ty->isStructTy())
+ return llvm::ConstantStruct::get(cast<llvm::StructType>(Ty), Values);
+ if (Ty->isArrayTy())
+ return llvm::ConstantArray::get(cast<llvm::ArrayType>(Ty), Values);
+ assert(Ty->isVectorTy());
+ return llvm::ConstantVector::get(Values);
}
/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
@@ -1098,6 +1237,7 @@ void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
// For each dimension stores its QualType and corresponding
// size-expression Value.
SmallVector<CodeGenFunction::VlaSizePair, 4> Dimensions;
+ SmallVector<IdentifierInfo *, 4> VLAExprNames;
// Break down the array into individual dimensions.
QualType Type1D = D.getType();
@@ -1106,8 +1246,14 @@ void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts))
Dimensions.emplace_back(C, Type1D.getUnqualifiedType());
else {
- auto SizeExprAddr = CreateDefaultAlignTempAlloca(
- VlaSize.NumElts->getType(), "__vla_expr");
+ // Generate a locally unique name for the size expression.
+ Twine Name = Twine("__vla_expr") + Twine(VLAExprCounter++);
+ SmallString<12> Buffer;
+ StringRef NameRef = Name.toStringRef(Buffer);
+ auto &Ident = getContext().Idents.getOwn(NameRef);
+ VLAExprNames.push_back(&Ident);
+ auto SizeExprAddr =
+ CreateDefaultAlignTempAlloca(VlaSize.NumElts->getType(), NameRef);
Builder.CreateStore(VlaSize.NumElts, SizeExprAddr);
Dimensions.emplace_back(SizeExprAddr.getPointer(),
Type1D.getUnqualifiedType());
@@ -1121,20 +1267,20 @@ void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
// Register each dimension's size-expression with a DILocalVariable,
// so that it can be used by CGDebugInfo when instantiating a DISubrange
// to describe this array.
+ unsigned NameIdx = 0;
for (auto &VlaSize : Dimensions) {
llvm::Metadata *MD;
if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts))
MD = llvm::ConstantAsMetadata::get(C);
else {
// Create an artificial VarDecl to generate debug info for.
- IdentifierInfo &NameIdent = getContext().Idents.getOwn(
- cast<llvm::AllocaInst>(VlaSize.NumElts)->getName());
+ IdentifierInfo *NameIdent = VLAExprNames[NameIdx++];
auto VlaExprTy = VlaSize.NumElts->getType()->getPointerElementType();
auto QT = getContext().getIntTypeForBitwidth(
VlaExprTy->getScalarSizeInBits(), false);
auto *ArtificialDecl = VarDecl::Create(
getContext(), const_cast<DeclContext *>(D.getDeclContext()),
- D.getLocation(), D.getLocation(), &NameIdent, QT,
+ D.getLocation(), D.getLocation(), NameIdent, QT,
getContext().CreateTypeSourceInfo(QT), SC_Auto);
ArtificialDecl->setImplicit();
@@ -1157,8 +1303,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
AutoVarEmission emission(D);
- bool isByRef = D.hasAttr<BlocksAttr>();
- emission.IsByRef = isByRef;
+ bool isEscapingByRef = D.isEscapingByref();
+ emission.IsEscapingByRef = isEscapingByRef;
CharUnits alignment = getContext().getDeclAlign(&D);
@@ -1197,8 +1343,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// in OpenCL.
if ((!getLangOpts().OpenCL ||
Ty.getAddressSpace() == LangAS::opencl_constant) &&
- (CGM.getCodeGenOpts().MergeAllConstants && !NRVO && !isByRef &&
- CGM.isTypeConstant(Ty, true))) {
+ (CGM.getCodeGenOpts().MergeAllConstants && !NRVO &&
+ !isEscapingByRef && CGM.isTypeConstant(Ty, true))) {
EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
// Signal this condition to later callbacks.
@@ -1250,7 +1396,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
} else {
CharUnits allocaAlignment;
llvm::Type *allocaTy;
- if (isByRef) {
+ if (isEscapingByRef) {
auto &byrefInfo = getBlockByrefInfo(&D);
allocaTy = byrefInfo.Type;
allocaAlignment = byrefInfo.ByrefAlignment;
@@ -1439,6 +1585,8 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, D.getLocation());
QualType type = D.getType();
+ bool isVolatile = type.isVolatileQualified();
+
// If this local has an initializer, emit it now.
const Expr *Init = D.getInit();
@@ -1450,7 +1598,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
}
// Initialize the structure of a __block variable.
- if (emission.IsByRef)
+ if (emission.IsEscapingByRef)
emitByrefStructureInit(emission);
// Initialize the variable here if it doesn't have a initializer and it is a
@@ -1460,30 +1608,126 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
type.isNonTrivialToPrimitiveDefaultInitialize() ==
QualType::PDIK_Struct) {
LValue Dst = MakeAddrLValue(emission.getAllocatedAddress(), type);
- if (emission.IsByRef)
+ if (emission.IsEscapingByRef)
drillIntoBlockVariable(*this, Dst, &D);
defaultInitNonTrivialCStructVar(Dst);
return;
}
- if (isTrivialInitializer(Init))
- return;
-
// Check whether this is a byref variable that's potentially
// captured and moved by its own initializer. If so, we'll need to
// emit the initializer first, then copy into the variable.
- bool capturedByInit = emission.IsByRef && isCapturedBy(D, Init);
+ bool capturedByInit =
+ Init && emission.IsEscapingByRef && isCapturedBy(D, Init);
Address Loc =
- capturedByInit ? emission.Addr : emission.getObjectAddress(*this);
+ capturedByInit ? emission.Addr : emission.getObjectAddress(*this);
+
+ // Note: constexpr already initializes everything correctly.
+ LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
+ (D.isConstexpr()
+ ? LangOptions::TrivialAutoVarInitKind::Uninitialized
+ : (D.getAttr<UninitializedAttr>()
+ ? LangOptions::TrivialAutoVarInitKind::Uninitialized
+ : getContext().getLangOpts().getTrivialAutoVarInit()));
+
+ auto initializeWhatIsTechnicallyUninitialized = [&]() {
+ if (trivialAutoVarInit ==
+ LangOptions::TrivialAutoVarInitKind::Uninitialized)
+ return;
+
+ CharUnits Size = getContext().getTypeSizeInChars(type);
+ if (!Size.isZero()) {
+ switch (trivialAutoVarInit) {
+ case LangOptions::TrivialAutoVarInitKind::Uninitialized:
+ llvm_unreachable("Uninitialized handled above");
+ case LangOptions::TrivialAutoVarInitKind::Zero:
+ emitStoresForZeroInit(CGM, D, Loc, isVolatile, Builder);
+ break;
+ case LangOptions::TrivialAutoVarInitKind::Pattern:
+ emitStoresForPatternInit(CGM, D, Loc, isVolatile, Builder);
+ break;
+ }
+ return;
+ }
+
+ // VLAs look zero-sized to getTypeInfo. We can't emit constant stores to
+ // them, so emit a memcpy with the VLA size to initialize each element.
+ // Technically zero-sized or negative-sized VLAs are undefined, and UBSan
+ // will catch that code, but there exists code which generates zero-sized
+ // VLAs. Be nice and initialize whatever they requested.
+ const VariableArrayType *VlaType =
+ dyn_cast_or_null<VariableArrayType>(getContext().getAsArrayType(type));
+ if (!VlaType)
+ return;
+ auto VlaSize = getVLASize(VlaType);
+ auto SizeVal = VlaSize.NumElts;
+ CharUnits EltSize = getContext().getTypeSizeInChars(VlaSize.Type);
+ switch (trivialAutoVarInit) {
+ case LangOptions::TrivialAutoVarInitKind::Uninitialized:
+ llvm_unreachable("Uninitialized handled above");
+
+ case LangOptions::TrivialAutoVarInitKind::Zero:
+ if (!EltSize.isOne())
+ SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize));
+ Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
+ isVolatile);
+ break;
+
+ case LangOptions::TrivialAutoVarInitKind::Pattern: {
+ llvm::Type *ElTy = Loc.getElementType();
+ llvm::Constant *Constant = patternFor(CGM, ElTy);
+ CharUnits ConstantAlign = getContext().getTypeAlignInChars(VlaSize.Type);
+ llvm::BasicBlock *SetupBB = createBasicBlock("vla-setup.loop");
+ llvm::BasicBlock *LoopBB = createBasicBlock("vla-init.loop");
+ llvm::BasicBlock *ContBB = createBasicBlock("vla-init.cont");
+ llvm::Value *IsZeroSizedVLA = Builder.CreateICmpEQ(
+ SizeVal, llvm::ConstantInt::get(SizeVal->getType(), 0),
+ "vla.iszerosized");
+ Builder.CreateCondBr(IsZeroSizedVLA, ContBB, SetupBB);
+ EmitBlock(SetupBB);
+ if (!EltSize.isOne())
+ SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize));
+ llvm::Value *BaseSizeInChars =
+ llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity());
+ Address Begin = Builder.CreateElementBitCast(Loc, Int8Ty, "vla.begin");
+ llvm::Value *End =
+ Builder.CreateInBoundsGEP(Begin.getPointer(), SizeVal, "vla.end");
+ llvm::BasicBlock *OriginBB = Builder.GetInsertBlock();
+ EmitBlock(LoopBB);
+ llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur");
+ Cur->addIncoming(Begin.getPointer(), OriginBB);
+ CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize);
+ Builder.CreateMemCpy(
+ Address(Cur, CurAlign),
+ createUnnamedGlobalFrom(CGM, D, Builder, Constant, ConstantAlign),
+ BaseSizeInChars, isVolatile);
+ llvm::Value *Next =
+ Builder.CreateInBoundsGEP(Int8Ty, Cur, BaseSizeInChars, "vla.next");
+ llvm::Value *Done = Builder.CreateICmpEQ(Next, End, "vla-init.isdone");
+ Builder.CreateCondBr(Done, ContBB, LoopBB);
+ Cur->addIncoming(Next, LoopBB);
+ EmitBlock(ContBB);
+ } break;
+ }
+ };
+
+ if (isTrivialInitializer(Init)) {
+ initializeWhatIsTechnicallyUninitialized();
+ return;
+ }
llvm::Constant *constant = nullptr;
if (emission.IsConstantAggregate || D.isConstexpr()) {
assert(!capturedByInit && "constant init contains a capturing block?");
constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
+ if (constant && trivialAutoVarInit !=
+ LangOptions::TrivialAutoVarInitKind::Uninitialized)
+ constant = replaceUndef(constant);
}
if (!constant) {
+ initializeWhatIsTechnicallyUninitialized();
LValue lv = MakeAddrLValue(Loc, type);
lv.setNonGC(true);
return EmitExprAsInit(Init, &D, lv, capturedByInit);
@@ -1496,61 +1740,11 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
return EmitStoreThroughLValue(RValue::get(constant), lv, true);
}
- // If this is a simple aggregate initialization, we can optimize it
- // in various ways.
- bool isVolatile = type.isVolatileQualified();
-
- llvm::Value *SizeVal =
- llvm::ConstantInt::get(IntPtrTy,
- getContext().getTypeSizeInChars(type).getQuantity());
-
llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace());
if (Loc.getType() != BP)
Loc = Builder.CreateBitCast(Loc, BP);
- // If the initializer is all or mostly the same, codegen with bzero / memset
- // then do a few stores afterward.
- uint64_t ConstantSize =
- CGM.getDataLayout().getTypeAllocSize(constant->getType());
- if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) {
- Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
- isVolatile);
- // Zero and undef don't require a stores.
- if (!constant->isNullValue() && !isa<llvm::UndefValue>(constant)) {
- Loc = Builder.CreateBitCast(Loc,
- constant->getType()->getPointerTo(Loc.getAddressSpace()));
- emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder);
- }
- return;
- }
-
- BytePattern Pattern = shouldUseMemSetToInitialize(constant, ConstantSize);
- if (!Pattern.isNone()) {
- uint8_t Value = Pattern.isAny() ? 0x00 : Pattern.getValue();
- Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, Value), SizeVal,
- isVolatile);
- return;
- }
-
- // Otherwise, create a temporary global with the initializer then
- // memcpy from the global to the alloca.
- std::string Name = getStaticDeclName(CGM, D);
- unsigned AS = CGM.getContext().getTargetAddressSpace(
- CGM.getStringLiteralAddressSpace());
- BP = llvm::PointerType::getInt8PtrTy(getLLVMContext(), AS);
-
- llvm::GlobalVariable *GV = new llvm::GlobalVariable(
- CGM.getModule(), constant->getType(), true,
- llvm::GlobalValue::PrivateLinkage, constant, Name, nullptr,
- llvm::GlobalValue::NotThreadLocal, AS);
- GV->setAlignment(Loc.getAlignment().getQuantity());
- GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
-
- Address SrcPtr = Address(GV, Loc.getAlignment());
- if (SrcPtr.getType() != BP)
- SrcPtr = Builder.CreateBitCast(SrcPtr, BP);
-
- Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, isVolatile);
+ emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
}
/// Emit an expression as an initializer for an object (variable, field, etc.)
@@ -1712,12 +1906,14 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
// If this is a block variable, call _Block_object_destroy
// (on the unforwarded address). Don't enter this cleanup if we're in pure-GC
// mode.
- if (emission.IsByRef && CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
+ if (emission.IsEscapingByRef &&
+ CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF;
if (emission.Variable->getType().isObjCGCWeak())
Flags |= BLOCK_FIELD_IS_WEAK;
enterByrefCleanup(NormalAndEHCleanup, emission.Addr, Flags,
- /*LoadBlockVarAddr*/ false);
+ /*LoadBlockVarAddr*/ false,
+ cxxDestructorCanThrow(emission.Variable->getType()));
}
}
@@ -2134,15 +2330,11 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
// cleanup to do the release at the end of the function.
bool isConsumed = D.hasAttr<NSConsumedAttr>();
- // 'self' is always formally __strong, but if this is not an
- // init method then we don't want to retain it.
+ // If a parameter is pseudo-strong then we can omit the implicit retain.
if (D.isARCPseudoStrong()) {
- const ObjCMethodDecl *method = cast<ObjCMethodDecl>(CurCodeDecl);
- assert(&D == method->getSelfDecl());
- assert(lt == Qualifiers::OCL_Strong);
- assert(qs.hasConst());
- assert(method->getMethodFamily() != OMF_init);
- (void) method;
+ assert(lt == Qualifiers::OCL_Strong &&
+ "pseudo-strong variable isn't strong?");
+ assert(qs.hasConst() && "pseudo-strong variable should be const!");
lt = Qualifiers::OCL_ExplicitNone;
}
@@ -2224,3 +2416,7 @@ void CodeGenModule::EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
return;
getOpenMPRuntime().emitUserDefinedReduction(CGF, D);
}
+
+void CodeGenModule::EmitOMPRequiresDecl(const OMPRequiresDecl *D) {
+ getOpenMPRuntime().checkArchForUnifiedAddressing(*this, D);
+}
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 510863f68eff..9aa31f181e99 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -15,7 +15,7 @@
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGOpenMPRuntime.h"
-#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
@@ -26,7 +26,10 @@ using namespace CodeGen;
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
ConstantAddress DeclPtr) {
- assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
+ assert(
+ (D.hasGlobalStorage() ||
+ (D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) &&
+ "VarDecl must have global or local (in the case of OpenCL) storage!");
assert(!D.getType()->isReferenceType() &&
"Should not call EmitDeclInit on a reference!");
@@ -63,15 +66,24 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
- ConstantAddress addr) {
+ ConstantAddress Addr) {
+ // Honor __attribute__((no_destroy)) and bail instead of attempting
+ // to emit a reference to a possibly nonexistent destructor, which
+ // in turn can cause a crash. This will result in a global constructor
+ // that isn't balanced out by a destructor call as intended by the
+ // attribute. This also checks for -fno-c++-static-destructors and
+ // bails even if the attribute is not present.
+ if (D.isNoDestroy(CGF.getContext()))
+ return;
+
CodeGenModule &CGM = CGF.CGM;
// FIXME: __attribute__((cleanup)) ?
- QualType type = D.getType();
- QualType::DestructionKind dtorKind = type.isDestructedType();
+ QualType Type = D.getType();
+ QualType::DestructionKind DtorKind = Type.isDestructedType();
- switch (dtorKind) {
+ switch (DtorKind) {
case QualType::DK_none:
return;
@@ -86,13 +98,14 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
return;
}
- llvm::Constant *function;
- llvm::Constant *argument;
+ llvm::Constant *Func;
+ llvm::Constant *Argument;
// Special-case non-array C++ destructors, if they have the right signature.
// Under some ABIs, destructors return this instead of void, and cannot be
- // passed directly to __cxa_atexit if the target does not allow this mismatch.
- const CXXRecordDecl *Record = type->getAsCXXRecordDecl();
+ // passed directly to __cxa_atexit if the target does not allow this
+ // mismatch.
+ const CXXRecordDecl *Record = Type->getAsCXXRecordDecl();
bool CanRegisterDestructor =
Record && (!CGM.getCXXABI().HasThisReturn(
GlobalDecl(Record->getDestructor(), Dtor_Complete)) ||
@@ -103,43 +116,47 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit;
if (Record && (CanRegisterDestructor || UsingExternalHelper)) {
assert(!Record->hasTrivialDestructor());
- CXXDestructorDecl *dtor = Record->getDestructor();
+ CXXDestructorDecl *Dtor = Record->getDestructor();
- function = CGM.getAddrOfCXXStructor(dtor, StructorType::Complete);
- argument = llvm::ConstantExpr::getBitCast(
- addr.getPointer(), CGF.getTypes().ConvertType(type)->getPointerTo());
+ Func = CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete);
+ Argument = llvm::ConstantExpr::getBitCast(
+ Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo());
// Otherwise, the standard logic requires a helper function.
} else {
- function = CodeGenFunction(CGM)
- .generateDestroyHelper(addr, type, CGF.getDestroyer(dtorKind),
- CGF.needsEHCleanup(dtorKind), &D);
- argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
+ Func = CodeGenFunction(CGM)
+ .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind),
+ CGF.needsEHCleanup(DtorKind), &D);
+ Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
}
- CGM.getCXXABI().registerGlobalDtor(CGF, D, function, argument);
+ CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument);
}
/// Emit code to cause the variable at the given address to be considered as
/// constant from this point onwards.
static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *Addr) {
+ return CGF.EmitInvariantStart(
+ Addr, CGF.getContext().getTypeSizeInChars(D.getType()));
+}
+
+void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) {
// Do not emit the intrinsic if we're not optimizing.
- if (!CGF.CGM.getCodeGenOpts().OptimizationLevel)
+ if (!CGM.getCodeGenOpts().OptimizationLevel)
return;
// Grab the llvm.invariant.start intrinsic.
llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
// Overloaded address space type.
- llvm::Type *ObjectPtr[1] = {CGF.Int8PtrTy};
- llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID, ObjectPtr);
+ llvm::Type *ObjectPtr[1] = {Int8PtrTy};
+ llvm::Constant *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr);
// Emit a call with the size in bytes of the object.
- CharUnits WidthChars = CGF.getContext().getTypeSizeInChars(D.getType());
- uint64_t Width = WidthChars.getQuantity();
- llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, Width),
- llvm::ConstantExpr::getBitCast(Addr, CGF.Int8PtrTy)};
- CGF.Builder.CreateCall(InvariantStart, Args);
+ uint64_t Width = Size.getQuantity();
+ llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(Int64Ty, Width),
+ llvm::ConstantExpr::getBitCast(Addr, Int8PtrTy)};
+ Builder.CreateCall(InvariantStart, Args);
}
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
@@ -347,6 +364,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
!isInSanitizerBlacklist(SanitizerKind::Memory, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+ if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) &&
+ !isInSanitizerBlacklist(SanitizerKind::KernelMemory, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+
if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) &&
!isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SafeStack);
@@ -355,6 +376,22 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
!isInSanitizerBlacklist(SanitizerKind::ShadowCallStack, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
+ auto RASignKind = getCodeGenOpts().getSignReturnAddress();
+ if (RASignKind != CodeGenOptions::SignReturnAddressScope::None) {
+ Fn->addFnAttr("sign-return-address",
+ RASignKind == CodeGenOptions::SignReturnAddressScope::All
+ ? "all"
+ : "non-leaf");
+ auto RASignKey = getCodeGenOpts().getSignReturnAddressKey();
+ Fn->addFnAttr("sign-return-address-key",
+ RASignKey == CodeGenOptions::SignReturnAddressKeyValue::AKey
+ ? "a_key"
+ : "b_key");
+ }
+
+ if (getCodeGenOpts().BranchTargetEnforcement)
+ Fn->addFnAttr("branch-target-enforcement");
+
return Fn;
}
@@ -565,7 +602,7 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
if (D->hasAttr<NoDebugAttr>())
DebugInfo = nullptr; // disable debug info indefinitely for this function
- CurEHLocation = D->getLocStart();
+ CurEHLocation = D->getBeginLoc();
StartFunction(GlobalDecl(D), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(),
@@ -587,7 +624,7 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
void
CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Function *> Decls,
- Address Guard) {
+ ConstantAddress Guard) {
{
auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
@@ -611,6 +648,12 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
// initializers use previously-initialized thread_local vars, that's
// probably supposed to be OK, but the standard doesn't say.
Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
+
+ // The guard variable can't ever change again.
+ EmitInvariantStart(
+ Guard.getPointer(),
+ CharUnits::fromQuantity(
+ CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())));
}
RunCleanupsScope Scope(*this);
@@ -679,7 +722,7 @@ llvm::Function *CodeGenFunction::generateDestroyHelper(
llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(
FTy, "__cxx_global_array_dtor", FI, VD->getLocation());
- CurEHLocation = VD->getLocStart();
+ CurEHLocation = VD->getBeginLoc();
StartFunction(VD, getContext().VoidTy, fn, FI, args);
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index a2ff102e1ab4..5756e13d2623 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -66,7 +66,7 @@ llvm::Constant *CodeGenModule::getTerminateFn() {
name = "__std_terminate";
else
name = "?terminate@@YAXXZ";
- } else if (getLangOpts().ObjC1 &&
+ } else if (getLangOpts().ObjC &&
getLangOpts().ObjCRuntime.hasTerminate())
name = "objc_terminate";
else
@@ -224,7 +224,7 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
if (FD && FD->usesSEHTry())
return getSEHPersonalityMSVC(T);
- if (L.ObjC1)
+ if (L.ObjC)
return L.CPlusPlus ? getObjCXXPersonality(Target, L)
: getObjCPersonality(Target, L);
return L.CPlusPlus ? getCXXPersonality(Target, L)
@@ -250,7 +250,11 @@ static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,
static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
const EHPersonality &Personality) {
llvm::Constant *Fn = getPersonalityFn(CGM, Personality);
- return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
+ llvm::PointerType* Int8PtrTy = llvm::PointerType::get(
+ llvm::Type::getInt8Ty(CGM.getLLVMContext()),
+ CGM.getDataLayout().getProgramAddressSpace());
+
+ return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy);
}
/// Check whether a landingpad instruction only uses C++ features.
@@ -315,7 +319,7 @@ static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
/// when it really needs it.
void CodeGenModule::SimplifyPersonality() {
// If we're not in ObjC++ -fexceptions, there's nothing to do.
- if (!LangOpts.CPlusPlus || !LangOpts.ObjC1 || !LangOpts.Exceptions)
+ if (!LangOpts.CPlusPlus || !LangOpts.ObjC || !LangOpts.Exceptions)
return;
// Both the problem this endeavors to fix and the way the logic
@@ -1248,7 +1252,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
// we follow the false destination for each of the cond branches to reach
// the rethrow block.
llvm::BasicBlock *RethrowBlock = WasmCatchStartBlock;
- while (llvm::TerminatorInst *TI = RethrowBlock->getTerminator()) {
+ while (llvm::Instruction *TI = RethrowBlock->getTerminator()) {
auto *BI = cast<llvm::BranchInst>(TI);
assert(BI->isConditional());
RethrowBlock = BI->getSuccessor(1);
@@ -1623,8 +1627,16 @@ struct PerformSEHFinally final : EHScopeStack::Cleanup {
// Compute the two argument values.
QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
- llvm::Value *LocalAddrFn = CGM.getIntrinsic(llvm::Intrinsic::localaddress);
- llvm::Value *FP = CGF.Builder.CreateCall(LocalAddrFn);
+ llvm::Value *FP = nullptr;
+ // If CFG.IsOutlinedSEHHelper is true, then we are within a finally block.
+ if (CGF.IsOutlinedSEHHelper) {
+ FP = &CGF.CurFn->arg_begin()[1];
+ } else {
+ llvm::Value *LocalAddrFn =
+ CGM.getIntrinsic(llvm::Intrinsic::localaddress);
+ FP = CGF.Builder.CreateCall(LocalAddrFn);
+ }
+
llvm::Value *IsForEH =
llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
Args.add(RValue::get(IsForEH), ArgTys[0]);
@@ -1777,7 +1789,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
// frame pointer of the parent function. We only need to do this in filters,
// since finally funclets recover the parent FP for us.
llvm::Function *RecoverFPIntrin =
- CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
+ CGM.getIntrinsic(llvm::Intrinsic::eh_recoverfp);
llvm::Constant *ParentI8Fn =
llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryFP});
@@ -1823,13 +1835,13 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
bool IsFilter,
const Stmt *OutlinedStmt) {
- SourceLocation StartLoc = OutlinedStmt->getLocStart();
+ SourceLocation StartLoc = OutlinedStmt->getBeginLoc();
// Get the mangled function name.
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
- const FunctionDecl *ParentSEHFn = ParentCGF.CurSEHParent;
+ const NamedDecl *ParentSEHFn = ParentCGF.CurSEHParent;
assert(ParentSEHFn && "No CurSEHParent!");
MangleContext &Mangler = CGM.getCXXABI().getMangleContext();
if (IsFilter)
@@ -1871,10 +1883,10 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
IsOutlinedSEHHelper = true;
StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
- OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
+ OutlinedStmt->getBeginLoc(), OutlinedStmt->getBeginLoc());
CurSEHParent = ParentCGF.CurSEHParent;
- CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FnInfo, CurFn);
EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter);
}
@@ -1893,7 +1905,7 @@ CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
FilterExpr->getType()->isSignedIntegerType());
Builder.CreateStore(R, ReturnValue);
- FinishFunction(FilterExpr->getLocEnd());
+ FinishFunction(FilterExpr->getEndLoc());
return CurFn;
}
@@ -1907,7 +1919,7 @@ CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
// Emit the original filter expression, convert to i32, and return.
EmitStmt(FinallyBlock);
- FinishFunction(FinallyBlock->getLocEnd());
+ FinishFunction(FinallyBlock->getEndLoc());
return CurFn;
}
@@ -1972,6 +1984,11 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
return Builder.CreateZExt(&*AI, Int32Ty);
}
+void CodeGenFunction::pushSEHCleanup(CleanupKind Kind,
+ llvm::Function *FinallyFunc) {
+ EHStack.pushCleanup<PerformSEHFinally>(Kind, FinallyFunc);
+}
+
void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index f168dd02ead1..34a921e2dc00 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -26,7 +26,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/NSAPI.h"
-#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/DataLayout.h"
@@ -419,8 +419,12 @@ LValue CodeGenFunction::
EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
const Expr *E = M->GetTemporaryExpr();
- // FIXME: ideally this would use EmitAnyExprToMem, however, we cannot do so
- // as that will cause the lifetime adjustment to be lost for ARC
+ assert((!M->getExtendingDecl() || !isa<VarDecl>(M->getExtendingDecl()) ||
+ !cast<VarDecl>(M->getExtendingDecl())->isARCPseudoStrong()) &&
+ "Reference should never be pseudo-strong!");
+
+ // FIXME: ideally this would use EmitAnyExprToMem, however, we cannot do so
+ // as that will cause the lifetime adjustment to be lost for ARC
auto ownership = M->getType().getObjCLifetime();
if (ownership != Qualifiers::OCL_None &&
ownership != Qualifiers::OCL_ExplicitNone) {
@@ -498,18 +502,51 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
- case SD_FullExpression:
if (auto *Size = EmitLifetimeStart(
CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
Alloca.getPointer())) {
- if (M->getStorageDuration() == SD_Automatic)
- pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Alloca, Size);
- else
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
- Size);
+ pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
+ Alloca, Size);
+ }
+ break;
+
+ case SD_FullExpression: {
+ if (!ShouldEmitLifetimeMarkers)
+ break;
+
+ // Avoid creating a conditional cleanup just to hold an llvm.lifetime.end
+ // marker. Instead, start the lifetime of a conditional temporary earlier
+ // so that it's unconditional. Don't do this in ASan's use-after-scope
+ // mode so that it gets the more precise lifetime marks. If the type has
+ // a non-trivial destructor, we'll have a cleanup block for it anyway,
+ // so this typically doesn't help; skip it in that case.
+ ConditionalEvaluation *OldConditional = nullptr;
+ CGBuilderTy::InsertPoint OldIP;
+ if (isInConditionalBranch() && !E->getType().isDestructedType() &&
+ !CGM.getCodeGenOpts().SanitizeAddressUseAfterScope) {
+ OldConditional = OutermostConditional;
+ OutermostConditional = nullptr;
+
+ OldIP = Builder.saveIP();
+ llvm::BasicBlock *Block = OldConditional->getStartingBlock();
+ Builder.restoreIP(CGBuilderTy::InsertPoint(
+ Block, llvm::BasicBlock::iterator(Block->back())));
+ }
+
+ if (auto *Size = EmitLifetimeStart(
+ CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
+ Alloca.getPointer())) {
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
+ Size);
+ }
+
+ if (OldConditional) {
+ OutermostConditional = OldConditional;
+ Builder.restoreIP(OldIP);
}
break;
+ }
+
default:
break;
}
@@ -1043,7 +1080,7 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
EmitVTablePtrCheckForCast(PT->getPointeeType(), Addr.getPointer(),
/*MayBeNull=*/true,
CodeGenFunction::CFITCK_UnrelatedCast,
- CE->getLocStart());
+ CE->getBeginLoc());
}
return CE->getCastKind() != CK_AddressSpaceConversion
? Builder.CreateBitCast(Addr, ConvertType(E->getType()))
@@ -1227,6 +1264,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitVAArgExprLValue(cast<VAArgExpr>(E));
case Expr::DeclRefExprClass:
return EmitDeclRefLValue(cast<DeclRefExpr>(E));
+ case Expr::ConstantExprClass:
+ return EmitLValue(cast<ConstantExpr>(E)->getSubExpr());
case Expr::ParenExprClass:
return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
case Expr::GenericSelectionExprClass:
@@ -1458,6 +1497,16 @@ CodeGenFunction::tryEmitAsConstant(const MemberExpr *ME) {
return ConstantEmission();
}
+llvm::Value *CodeGenFunction::emitScalarConstant(
+ const CodeGenFunction::ConstantEmission &Constant, Expr *E) {
+ assert(Constant && "not a constant");
+ if (Constant.isReference())
+ return EmitLoadOfLValue(Constant.getReferenceLValue(*this, E),
+ E->getExprLoc())
+ .getScalarVal();
+ return Constant.getValue();
+}
+
llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue,
SourceLocation Loc) {
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
@@ -2237,18 +2286,14 @@ static LValue EmitThreadPrivateVarDeclLValue(
static Address emitDeclTargetLinkVarDeclLValue(CodeGenFunction &CGF,
const VarDecl *VD, QualType T) {
- for (const auto *D : VD->redecls()) {
- if (!VD->hasAttrs())
- continue;
- if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
- if (Attr->getMapType() == OMPDeclareTargetDeclAttr::MT_Link) {
- QualType PtrTy = CGF.getContext().getPointerType(VD->getType());
- Address Addr =
- CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
- return CGF.EmitLoadOfPointer(Addr, PtrTy->castAs<PointerType>());
- }
- }
- return Address::invalid();
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_To)
+ return Address::invalid();
+ assert(*Res == OMPDeclareTargetDeclAttr::MT_Link && "Expected link clause");
+ QualType PtrTy = CGF.getContext().getPointerType(VD->getType());
+ Address Addr = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
+ return CGF.EmitLoadOfPointer(Addr, PtrTy->castAs<PointerType>());
}
Address
@@ -2408,6 +2453,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// A DeclRefExpr for a reference initialized by a constant expression can
// appear without being odr-used. Directly emit the constant initializer.
const Expr *Init = VD->getAnyInitializer(VD);
+ const auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl);
if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() &&
VD->isUsableInConstantExpressions(getContext()) &&
VD->checkInitIsICE() &&
@@ -2417,7 +2463,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
(LocalDeclMap.count(VD->getCanonicalDecl()) ||
CapturedStmtInfo->lookup(VD->getCanonicalDecl()))) ||
LambdaCaptureFields.lookup(VD->getCanonicalDecl()) ||
- isa<BlockDecl>(CurCodeDecl)))) {
+ (BD && BD->capturesVariable(VD))))) {
llvm::Constant *Val =
ConstantEmitter(*this).emitAbstract(E->getLocation(),
*VD->evaluateValue(),
@@ -2456,7 +2502,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
assert(isa<BlockDecl>(CurCodeDecl));
- Address addr = GetAddrOfBlockDecl(VD, VD->hasAttr<BlocksAttr>());
+ Address addr = GetAddrOfBlockDecl(VD);
return MakeAddrLValue(addr, T, AlignmentSource::Decl);
}
}
@@ -2508,7 +2554,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
// Drill into block byref variables.
- bool isBlockByref = VD->hasAttr<BlocksAttr>();
+ bool isBlockByref = VD->isEscapingByref();
if (isBlockByref) {
addr = emitBlockByrefAddress(addr, VD);
}
@@ -2571,7 +2617,7 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
// of a pointer to object; as in void foo (__weak id *param); *param = 0;
// But, we continue to generate __strong write barrier on indirect write
// into a pointer to object.
- if (getLangOpts().ObjC1 &&
+ if (getLangOpts().ObjC &&
getLangOpts().getGC() != LangOptions::NonGC &&
LV.isObjCWeak())
LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
@@ -2632,7 +2678,7 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
if (FnName.startswith("\01"))
FnName = FnName.substr(1);
StringRef NameItems[] = {
- PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName};
+ PredefinedExpr::getIdentKindName(E->getIdentKind()), FnName};
std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
if (auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl)) {
std::string Name = SL->getString();
@@ -2837,6 +2883,11 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
CheckRecoverableKind RecoverKind, bool IsFatal,
llvm::BasicBlock *ContBB) {
assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable);
+ Optional<ApplyDebugLocation> DL;
+ if (!CGF.Builder.getCurrentDebugLocation()) {
+ // Ensure that the call has at least an artificial debug location.
+ DL.emplace(CGF, SourceLocation());
+ }
bool NeedsAbortSuffix =
IsFatal && RecoverKind != CheckRecoverableKind::Unrecoverable;
bool MinimalRuntime = CGF.CGM.getCodeGenOpts().SanitizeMinimalRuntime;
@@ -3448,7 +3499,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
- if (getLangOpts().ObjC1 &&
+ if (getLangOpts().ObjC &&
getLangOpts().getGC() != LangOptions::NonGC) {
LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
setObjCGCLValueClass(getContext(), E, LV);
@@ -3901,7 +3952,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo,
FieldTBAAInfo);
if (RecordCVR & Qualifiers::Volatile)
- RefLVal.getQuals().setVolatile(true);
+ RefLVal.getQuals().addVolatile();
addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo);
// Qualifiers on the struct don't apply to the referencee.
@@ -4121,8 +4172,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
- case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
case CK_Dependent:
@@ -4193,8 +4245,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
if (SanOpts.has(SanitizerKind::CFIDerivedCast))
EmitVTablePtrCheckForCast(E->getType(), Derived.getPointer(),
- /*MayBeNull=*/false,
- CFITCK_DerivedCast, E->getLocStart());
+ /*MayBeNull=*/false, CFITCK_DerivedCast,
+ E->getBeginLoc());
return MakeAddrLValue(Derived, E->getType(), LV.getBaseInfo(),
CGM.getTBAAInfoForSubobject(LV, E->getType()));
@@ -4210,12 +4262,21 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
if (SanOpts.has(SanitizerKind::CFIUnrelatedCast))
EmitVTablePtrCheckForCast(E->getType(), V.getPointer(),
- /*MayBeNull=*/false,
- CFITCK_UnrelatedCast, E->getLocStart());
+ /*MayBeNull=*/false, CFITCK_UnrelatedCast,
+ E->getBeginLoc());
return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(),
CGM.getTBAAInfoForSubobject(LV, E->getType()));
}
+ case CK_AddressSpaceConversion: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ QualType DestTy = getContext().getPointerType(E->getType());
+ llvm::Value *V = getTargetHooks().performAddrSpaceCast(
+ *this, LV.getPointer(), E->getSubExpr()->getType().getAddressSpace(),
+ E->getType().getAddressSpace(), ConvertType(DestTy));
+ return MakeAddrLValue(Address(V, LV.getAddress().getAlignment()),
+ E->getType(), LV.getBaseInfo(), LV.getTBAAInfo());
+ }
case CK_ObjCObjectLValueCast: {
LValue LV = EmitLValue(E->getSubExpr());
Address V = Builder.CreateElementBitCast(LV.getAddress(),
@@ -4223,10 +4284,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(),
CGM.getTBAAInfoForSubobject(LV, E->getType()));
}
- case CK_ZeroToOCLQueue:
- llvm_unreachable("NULL to OpenCL queue lvalue cast is not valid");
- case CK_ZeroToOCLEvent:
- llvm_unreachable("NULL to OpenCL event lvalue cast is not valid");
+ case CK_ZeroToOCLOpaqueType:
+ llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid");
}
llvm_unreachable("Unhandled lvalue cast kind?");
@@ -4333,7 +4392,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, const FunctionDecl *FD) {
}
llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, FD);
- return CGCallee::forDirect(calleePtr, FD);
+ return CGCallee::forDirect(calleePtr, GlobalDecl(FD));
}
CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
@@ -4377,8 +4436,13 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
calleePtr = EmitLValue(E).getPointer();
}
assert(functionType->isFunctionType());
- CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(),
- E->getReferencedDeclOfCallee());
+
+ GlobalDecl GD;
+ if (const auto *VD =
+ dyn_cast_or_null<VarDecl>(E->getReferencedDeclOfCallee()))
+ GD = GlobalDecl(VD);
+
+ CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), GD);
CGCallee callee(calleeInfo, calleePtr);
return callee;
}
@@ -4563,7 +4627,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
assert(CalleeType->isFunctionPointerType() &&
"Call must have function pointer type!");
- const Decl *TargetDecl = OrigCallee.getAbstractInfo().getCalleeDecl();
+ const Decl *TargetDecl =
+ OrigCallee.getAbstractInfo().getCalleeDecl().getDecl();
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
// We can only guarantee that a function is called from the correct
@@ -4620,10 +4685,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded);
llvm::Value *CalleeRTTIMatch =
Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
- llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(E->getLocStart()),
- EmitCheckTypeDescriptor(CalleeType)
- };
+ llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getBeginLoc()),
+ EmitCheckTypeDescriptor(CalleeType)};
EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function),
SanitizerHandler::FunctionTypeMismatch, StaticData, CalleePtr);
@@ -4657,7 +4720,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(Int8Ty, CFITCK_ICall),
- EmitCheckSourceLocation(E->getLocStart()),
+ EmitCheckSourceLocation(E->getBeginLoc()),
EmitCheckTypeDescriptor(QualType(FnType, 0)),
};
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 62641102861c..db49b3f28a59 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -125,6 +125,10 @@ public:
return Visit(E->getReplacement());
}
+ void VisitConstantExpr(ConstantExpr *E) {
+ return Visit(E->getSubExpr());
+ }
+
// l-values.
void VisitDeclRefExpr(DeclRefExpr *E) { EmitAggLoadOfLValue(E); }
void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); }
@@ -847,10 +851,11 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_ZeroToOCLOpaqueType:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
llvm_unreachable("cast kind invalid for aggregate types");
}
}
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index f29ef754c03f..884ce96859c5 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -17,8 +17,8 @@
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "ConstantEmitter.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Intrinsics.h"
@@ -177,7 +177,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
if (MD->isStatic()) {
// The method is static, emit it as we would a regular call.
- CGCallee callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD), MD);
+ CGCallee callee =
+ CGCallee::forDirect(CGM.GetAddrOfFunction(MD), GlobalDecl(MD));
return EmitCall(getContext().getPointerType(MD->getType()), callee, CE,
ReturnValue);
}
@@ -353,13 +354,13 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
else if (!DevirtualizedMethod)
Callee = CGCallee::forDirect(
CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty),
- Dtor);
+ GlobalDecl(Dtor, Dtor_Complete));
else {
const CXXDestructorDecl *DDtor =
cast<CXXDestructorDecl>(DevirtualizedMethod);
Callee = CGCallee::forDirect(
- CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty),
- DDtor);
+ CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty),
+ GlobalDecl(DDtor, Dtor_Complete));
}
EmitCXXMemberOrOperatorCall(
CalleeDecl, Callee, ReturnValue, This.getPointer(),
@@ -371,8 +372,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
CGCallee Callee;
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGCallee::forDirect(
- CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty),
- Ctor);
+ CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty),
+ GlobalDecl(Ctor, Ctor_Complete));
} else if (UseVirtualCall) {
Callee = CGCallee::forVirtual(CE, MD, This.getAddress(), Ty);
} else {
@@ -383,17 +384,18 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
std::tie(VTable, RD) =
CGM.getCXXABI().LoadVTablePtr(*this, This.getAddress(),
MD->getParent());
- EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getLocStart());
+ EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getBeginLoc());
}
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
else if (!DevirtualizedMethod)
- Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), MD);
+ Callee =
+ CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), GlobalDecl(MD));
else {
- Callee = CGCallee::forDirect(
- CGM.GetAddrOfFunction(DevirtualizedMethod, Ty),
- DevirtualizedMethod);
+ Callee =
+ CGCallee::forDirect(CGM.GetAddrOfFunction(DevirtualizedMethod, Ty),
+ GlobalDecl(DevirtualizedMethod));
}
}
@@ -1293,7 +1295,7 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
const CallArgList &Args) {
llvm::Instruction *CallOrInvoke;
llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl);
- CGCallee Callee = CGCallee::forDirect(CalleePtr, CalleeDecl);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl));
RValue RV =
CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
Args, CalleeType, /*chainCall=*/false),
@@ -1654,9 +1656,10 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// Emit a null check on the allocation result if the allocation
// function is allowed to return null (because it has a non-throwing
// exception spec or is the reserved placement new) and we have an
- // interesting initializer.
- bool nullCheck = E->shouldNullCheckAllocation(getContext()) &&
- (!allocType.isPODType(getContext()) || E->hasInitializer());
+ // interesting initializer will be running sanitizers on the initialization.
+ bool nullCheck = E->shouldNullCheckAllocation() &&
+ (!allocType.isPODType(getContext()) || E->hasInitializer() ||
+ sanitizePerformTypeCheck());
llvm::BasicBlock *nullCheckBB = nullptr;
llvm::BasicBlock *contBB = nullptr;
@@ -2252,7 +2255,6 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
}
void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
- RunCleanupsScope Scope(*this);
LValue SlotLV = MakeAddrLValue(Slot.getAddress(), E->getType());
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index fb176093a741..2db693b44c90 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -101,6 +101,9 @@ public:
llvm_unreachable("Stmt can't have complex result type!");
}
ComplexPairTy VisitExpr(Expr *S);
+ ComplexPairTy VisitConstantExpr(ConstantExpr *E) {
+ return Visit(E->getSubExpr());
+ }
ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
return Visit(GE->getResultExpr());
@@ -505,10 +508,11 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_ZeroToOCLOpaqueType:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 68766479a539..c9475840aeeb 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -47,7 +47,7 @@ class ConstStructBuilder {
public:
static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
ConstExprEmitter *ExprEmitter,
- llvm::ConstantStruct *Base,
+ llvm::Constant *Base,
InitListExpr *Updater,
QualType ValTy);
static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
@@ -76,7 +76,7 @@ private:
void ConvertStructToPacked();
bool Build(InitListExpr *ILE);
- bool Build(ConstExprEmitter *Emitter, llvm::ConstantStruct *Base,
+ bool Build(ConstExprEmitter *Emitter, llvm::Constant *Base,
InitListExpr *Updater);
bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
@@ -566,7 +566,7 @@ llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) {
llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
ConstExprEmitter *ExprEmitter,
- llvm::ConstantStruct *Base,
+ llvm::Constant *Base,
InitListExpr *Updater,
QualType ValTy) {
ConstStructBuilder Builder(Emitter);
@@ -723,6 +723,10 @@ public:
return nullptr;
}
+ llvm::Constant *VisitConstantExpr(ConstantExpr *CE, QualType T) {
+ return Visit(CE->getSubExpr(), T);
+ }
+
llvm::Constant *VisitParenExpr(ParenExpr *PE, QualType T) {
return Visit(PE->getSubExpr(), T);
}
@@ -869,8 +873,9 @@ public:
case CK_FloatingToIntegral:
case CK_FloatingToBoolean:
case CK_FloatingCast:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
+ case CK_ZeroToOCLOpaqueType:
return nullptr;
}
llvm_unreachable("Invalid CastKind");
@@ -1026,8 +1031,8 @@ public:
}
if (destType->isRecordType())
- return ConstStructBuilder::BuildStruct(Emitter, this,
- dyn_cast<llvm::ConstantStruct>(Base), Updater, destType);
+ return ConstStructBuilder::BuildStruct(Emitter, this, Base, Updater,
+ destType);
return nullptr;
}
@@ -1102,7 +1107,7 @@ public:
} // end anonymous namespace.
bool ConstStructBuilder::Build(ConstExprEmitter *ExprEmitter,
- llvm::ConstantStruct *Base,
+ llvm::Constant *Base,
InitListExpr *Updater) {
assert(Base && "base expression should not be empty");
@@ -1110,7 +1115,7 @@ bool ConstStructBuilder::Build(ConstExprEmitter *ExprEmitter,
RecordDecl *RD = ExprType->getAs<RecordType>()->getDecl();
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
const llvm::StructLayout *BaseLayout = CGM.getDataLayout().getStructLayout(
- Base->getType());
+ cast<llvm::StructType>(Base->getType()));
unsigned FieldNo = -1;
unsigned ElementNo = 0;
@@ -1131,7 +1136,7 @@ bool ConstStructBuilder::Build(ConstExprEmitter *ExprEmitter,
if (Field->isUnnamedBitfield())
continue;
- llvm::Constant *EltInit = Base->getOperand(ElementNo);
+ llvm::Constant *EltInit = Base->getAggregateElement(ElementNo);
// Bail out if the type of the ConstantStruct does not have the same layout
// as the type of the InitListExpr.
@@ -1450,6 +1455,7 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) {
if (CD->isTrivial() && CD->isDefaultConstructor())
return CGM.EmitNullConstant(D.getType());
}
+ InConstantContext = true;
}
QualType destType = D.getType();
@@ -1547,7 +1553,7 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E,
if (destType->isReferenceType())
Success = E->EvaluateAsLValue(Result, CGM.getContext());
else
- Success = E->EvaluateAsRValue(Result, CGM.getContext());
+ Success = E->EvaluateAsRValue(Result, CGM.getContext(), InConstantContext);
llvm::Constant *C;
if (Success && !Result.HasSideEffects)
@@ -1600,6 +1606,7 @@ private:
ConstantLValue tryEmitBase(const APValue::LValueBase &base);
ConstantLValue VisitStmt(const Stmt *S) { return nullptr; }
+ ConstantLValue VisitConstantExpr(const ConstantExpr *E);
ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
ConstantLValue VisitStringLiteral(const StringLiteral *E);
ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
@@ -1755,6 +1762,11 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
}
ConstantLValue
+ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) {
+ return Visit(E->getSubExpr());
+}
+
+ConstantLValue
ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
return tryEmitGlobalCompoundLiteral(CGM, Emitter.CGF, E);
}
@@ -1782,7 +1794,7 @@ ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *E) {
return cast<ConstantAddress>(Res.getAddress());
}
- auto kind = E->getIdentType();
+ auto kind = E->getIdentKind();
if (kind == PredefinedExpr::PrettyFunction) {
return CGM.GetAddrOfConstantCString("top level", ".tmp");
}
@@ -1968,6 +1980,16 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
Elts.push_back(C);
}
+ // This means that the array type is probably "IncompleteType" or some
+ // type that is not ConstantArray.
+ if (CAT == nullptr && CommonElementType == nullptr && !NumInitElts) {
+ const ArrayType *AT = CGM.getContext().getAsArrayType(DestType);
+ CommonElementType = CGM.getTypes().ConvertType(AT->getElementType());
+ llvm::ArrayType *AType = llvm::ArrayType::get(CommonElementType,
+ NumElements);
+ return llvm::ConstantAggregateZero::get(AType);
+ }
+
return EmitArrayConstant(CGM, CAT, CommonElementType, NumElements, Elts,
Filler);
}
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index c62588c68272..1c14d4c99a23 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -11,11 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#include "CodeGenFunction.h"
-#include "CGCleanup.h"
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
@@ -23,8 +23,9 @@
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
@@ -257,8 +258,11 @@ public:
AVAttr = TTy->getDecl()->getAttr<AlignValueAttr>();
} else {
// Assumptions for function parameters are emitted at the start of the
- // function, so there is no need to repeat that here.
- if (isa<ParmVarDecl>(VD))
+ // function, so there is no need to repeat that here,
+ // unless the alignment-assumption sanitizer is enabled,
+ // then we prefer the assumption over alignment attribute
+ // on IR function param.
+ if (isa<ParmVarDecl>(VD) && !CGF.SanOpts.has(SanitizerKind::Alignment))
return;
AVAttr = VD->getAttr<AlignValueAttr>();
@@ -275,7 +279,8 @@ public:
Value *AlignmentValue = CGF.EmitScalarExpr(AVAttr->getAlignment());
llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(AlignmentValue);
- CGF.EmitAlignmentAssumption(V, AlignmentCI->getZExtValue());
+ CGF.EmitAlignmentAssumption(V, E, AVAttr->getLocation(),
+ AlignmentCI->getZExtValue());
}
/// EmitLoadOfLValue - Given an expression with complex type that represents a
@@ -302,7 +307,11 @@ public:
/// Known implicit conversion check kinds.
/// Keep in sync with the enum of the same name in ubsan_handlers.h
enum ImplicitConversionCheckKind : unsigned char {
- ICCK_IntegerTruncation = 0,
+ ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7.
+ ICCK_UnsignedIntegerTruncation = 1,
+ ICCK_SignedIntegerTruncation = 2,
+ ICCK_IntegerSignChange = 3,
+ ICCK_SignedIntegerTruncationOrSignChange = 4,
};
/// Emit a check that an [implicit] truncation of an integer does not
@@ -310,21 +319,39 @@ public:
void EmitIntegerTruncationCheck(Value *Src, QualType SrcType, Value *Dst,
QualType DstType, SourceLocation Loc);
+ /// Emit a check that an [implicit] conversion of an integer does not change
+ /// the sign of the value. It is not UB, so we use the value after conversion.
+ /// NOTE: Src and Dst may be the exact same value! (point to the same thing)
+ void EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, Value *Dst,
+ QualType DstType, SourceLocation Loc);
+
/// Emit a conversion from the specified type to the specified destination
/// type, both of which are LLVM scalar types.
struct ScalarConversionOpts {
bool TreatBooleanAsSigned;
bool EmitImplicitIntegerTruncationChecks;
+ bool EmitImplicitIntegerSignChangeChecks;
ScalarConversionOpts()
: TreatBooleanAsSigned(false),
- EmitImplicitIntegerTruncationChecks(false) {}
+ EmitImplicitIntegerTruncationChecks(false),
+ EmitImplicitIntegerSignChangeChecks(false) {}
+
+ ScalarConversionOpts(clang::SanitizerSet SanOpts)
+ : TreatBooleanAsSigned(false),
+ EmitImplicitIntegerTruncationChecks(
+ SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
+ EmitImplicitIntegerSignChangeChecks(
+ SanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
};
Value *
EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
SourceLocation Loc,
ScalarConversionOpts Opts = ScalarConversionOpts());
+ Value *EmitFixedPointConversion(Value *Src, QualType SrcTy, QualType DstTy,
+ SourceLocation Loc);
+
/// Emit a conversion from the specified complex type to the specified
/// destination type, where the destination type is an LLVM scalar type.
Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
@@ -382,6 +409,9 @@ public:
}
Value *VisitExpr(Expr *S);
+ Value *VisitConstantExpr(ConstantExpr *E) {
+ return Visit(E->getSubExpr());
+ }
Value *VisitParenExpr(ParenExpr *PE) {
return Visit(PE->getSubExpr());
}
@@ -450,19 +480,10 @@ public:
return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal();
}
- Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,
- Expr *E) {
- assert(Constant && "not a constant");
- if (Constant.isReference())
- return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
- E->getExprLoc());
- return Constant.getValue();
- }
-
// l-values.
Value *VisitDeclRefExpr(DeclRefExpr *E) {
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
- return emitConstant(Constant, E);
+ return CGF.emitScalarConstant(Constant, E);
return EmitLoadOfLValue(E);
}
@@ -664,7 +685,7 @@ public:
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
- // Fall through.
+ LLVM_FALLTHROUGH;
case LangOptions::SOB_Trapping:
if (CanElideOverflowCheck(CGF.getContext(), Ops))
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
@@ -941,48 +962,233 @@ void ScalarExprEmitter::EmitFloatConversionCheck(
SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
}
+// Should be called within CodeGenFunction::SanitizerScope RAII scope.
+// Returns 'i1 false' when the truncation Src -> Dst was lossy.
+static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
+ std::pair<llvm::Value *, SanitizerMask>>
+EmitIntegerTruncationCheckHelper(Value *Src, QualType SrcType, Value *Dst,
+ QualType DstType, CGBuilderTy &Builder) {
+ llvm::Type *SrcTy = Src->getType();
+ llvm::Type *DstTy = Dst->getType();
+ (void)DstTy; // Only used in assert()
+
+ // This should be truncation of integral types.
+ assert(Src != Dst);
+ assert(SrcTy->getScalarSizeInBits() > Dst->getType()->getScalarSizeInBits());
+ assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) &&
+ "non-integer llvm type");
+
+ bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
+ bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
+
+ // If both (src and dst) types are unsigned, then it's an unsigned truncation.
+ // Else, it is a signed truncation.
+ ScalarExprEmitter::ImplicitConversionCheckKind Kind;
+ SanitizerMask Mask;
+ if (!SrcSigned && !DstSigned) {
+ Kind = ScalarExprEmitter::ICCK_UnsignedIntegerTruncation;
+ Mask = SanitizerKind::ImplicitUnsignedIntegerTruncation;
+ } else {
+ Kind = ScalarExprEmitter::ICCK_SignedIntegerTruncation;
+ Mask = SanitizerKind::ImplicitSignedIntegerTruncation;
+ }
+
+ llvm::Value *Check = nullptr;
+ // 1. Extend the truncated value back to the same width as the Src.
+ Check = Builder.CreateIntCast(Dst, SrcTy, DstSigned, "anyext");
+ // 2. Equality-compare with the original source value
+ Check = Builder.CreateICmpEQ(Check, Src, "truncheck");
+ // If the comparison result is 'i1 false', then the truncation was lossy.
+ return std::make_pair(Kind, std::make_pair(Check, Mask));
+}
+
void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
Value *Dst, QualType DstType,
SourceLocation Loc) {
- if (!CGF.SanOpts.has(SanitizerKind::ImplicitIntegerTruncation))
+ if (!CGF.SanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation))
return;
- llvm::Type *SrcTy = Src->getType();
- llvm::Type *DstTy = Dst->getType();
-
// We only care about int->int conversions here.
// We ignore conversions to/from pointer and/or bool.
if (!(SrcType->isIntegerType() && DstType->isIntegerType()))
return;
- assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) &&
- "clang integer type lowered to non-integer llvm type");
-
- unsigned SrcBits = SrcTy->getScalarSizeInBits();
- unsigned DstBits = DstTy->getScalarSizeInBits();
+ unsigned SrcBits = Src->getType()->getScalarSizeInBits();
+ unsigned DstBits = Dst->getType()->getScalarSizeInBits();
// This must be truncation. Else we do not care.
if (SrcBits <= DstBits)
return;
assert(!DstType->isBooleanType() && "we should not get here with booleans.");
+ // If the integer sign change sanitizer is enabled,
+ // and we are truncating from larger unsigned type to smaller signed type,
+ // let that next sanitizer deal with it.
+ bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
+ bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
+ if (CGF.SanOpts.has(SanitizerKind::ImplicitIntegerSignChange) &&
+ (!SrcSigned && DstSigned))
+ return;
+
CodeGenFunction::SanitizerScope SanScope(&CGF);
+ std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
+ std::pair<llvm::Value *, SanitizerMask>>
+ Check =
+ EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
+ // If the comparison result is 'i1 false', then the truncation was lossy.
+
+ // Do we care about this type of truncation?
+ if (!CGF.SanOpts.has(Check.second.second))
+ return;
+
+ llvm::Constant *StaticArgs[] = {
+ CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
+ CGF.EmitCheckTypeDescriptor(DstType),
+ llvm::ConstantInt::get(Builder.getInt8Ty(), Check.first)};
+ CGF.EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs,
+ {Src, Dst});
+}
+
+// Should be called within CodeGenFunction::SanitizerScope RAII scope.
+// Returns 'i1 false' when the conversion Src -> Dst changed the sign.
+static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
+ std::pair<llvm::Value *, SanitizerMask>>
+EmitIntegerSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst,
+ QualType DstType, CGBuilderTy &Builder) {
+ llvm::Type *SrcTy = Src->getType();
+ llvm::Type *DstTy = Dst->getType();
+
+ assert(isa<llvm::IntegerType>(SrcTy) && isa<llvm::IntegerType>(DstTy) &&
+ "non-integer llvm type");
+
+ bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
+ bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
+ (void)SrcSigned; // Only used in assert()
+ (void)DstSigned; // Only used in assert()
+ unsigned SrcBits = SrcTy->getScalarSizeInBits();
+ unsigned DstBits = DstTy->getScalarSizeInBits();
+ (void)SrcBits; // Only used in assert()
+ (void)DstBits; // Only used in assert()
+
+ assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) &&
+ "either the widths should be different, or the signednesses.");
+
+ // NOTE: zero value is considered to be non-negative.
+ auto EmitIsNegativeTest = [&Builder](Value *V, QualType VType,
+ const char *Name) -> Value * {
+ // Is this value a signed type?
+ bool VSigned = VType->isSignedIntegerOrEnumerationType();
+ llvm::Type *VTy = V->getType();
+ if (!VSigned) {
+ // If the value is unsigned, then it is never negative.
+ // FIXME: can we encounter non-scalar VTy here?
+ return llvm::ConstantInt::getFalse(VTy->getContext());
+ }
+ // Get the zero of the same type with which we will be comparing.
+ llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
+ // %V.isnegative = icmp slt %V, 0
+ // I.e is %V *strictly* less than zero, does it have negative value?
+ return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
+ llvm::Twine(Name) + "." + V->getName() +
+ ".negativitycheck");
+ };
+
+ // 1. Was the old Value negative?
+ llvm::Value *SrcIsNegative = EmitIsNegativeTest(Src, SrcType, "src");
+ // 2. Is the new Value negative?
+ llvm::Value *DstIsNegative = EmitIsNegativeTest(Dst, DstType, "dst");
+ // 3. Now, was the 'negativity status' preserved during the conversion?
+ // NOTE: conversion from negative to zero is considered to change the sign.
+ // (We want to get 'false' when the conversion changed the sign)
+ // So we should just equality-compare the negativity statuses.
llvm::Value *Check = nullptr;
+ Check = Builder.CreateICmpEQ(SrcIsNegative, DstIsNegative, "signchangecheck");
+ // If the comparison result is 'false', then the conversion changed the sign.
+ return std::make_pair(
+ ScalarExprEmitter::ICCK_IntegerSignChange,
+ std::make_pair(Check, SanitizerKind::ImplicitIntegerSignChange));
+}
- // 1. Extend the truncated value back to the same width as the Src.
- bool InputSigned = DstType->isSignedIntegerOrEnumerationType();
- Check = Builder.CreateIntCast(Dst, SrcTy, InputSigned, "anyext");
- // 2. Equality-compare with the original source value
- Check = Builder.CreateICmpEQ(Check, Src, "truncheck");
- // If the comparison result is 'i1 false', then the truncation was lossy.
+void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
+ Value *Dst, QualType DstType,
+ SourceLocation Loc) {
+ if (!CGF.SanOpts.has(SanitizerKind::ImplicitIntegerSignChange))
+ return;
+
+ llvm::Type *SrcTy = Src->getType();
+ llvm::Type *DstTy = Dst->getType();
+
+ // We only care about int->int conversions here.
+ // We ignore conversions to/from pointer and/or bool.
+ if (!(SrcType->isIntegerType() && DstType->isIntegerType()))
+ return;
+
+ bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
+ bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
+ unsigned SrcBits = SrcTy->getScalarSizeInBits();
+ unsigned DstBits = DstTy->getScalarSizeInBits();
+
+ // Now, we do not need to emit the check in *all* of the cases.
+ // We can avoid emitting it in some obvious cases where it would have been
+ // dropped by the opt passes (instcombine) always anyways.
+ // If it's a cast between effectively the same type, no check.
+ // NOTE: this is *not* equivalent to checking the canonical types.
+ if (SrcSigned == DstSigned && SrcBits == DstBits)
+ return;
+ // At least one of the values needs to have signed type.
+ // If both are unsigned, then obviously, neither of them can be negative.
+ if (!SrcSigned && !DstSigned)
+ return;
+ // If the conversion is to *larger* *signed* type, then no check is needed.
+ // Because either sign-extension happens (so the sign will remain),
+ // or zero-extension will happen (the sign bit will be zero.)
+ if ((DstBits > SrcBits) && DstSigned)
+ return;
+ if (CGF.SanOpts.has(SanitizerKind::ImplicitSignedIntegerTruncation) &&
+ (SrcBits > DstBits) && SrcSigned) {
+ // If the signed integer truncation sanitizer is enabled,
+ // and this is a truncation from signed type, then no check is needed.
+ // Because here sign change check is interchangeable with truncation check.
+ return;
+ }
+ // That's it. We can't rule out any more cases with the data we have.
+
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+
+ std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
+ std::pair<llvm::Value *, SanitizerMask>>
+ Check;
+
+ // Each of these checks needs to return 'false' when an issue was detected.
+ ImplicitConversionCheckKind CheckKind;
+ llvm::SmallVector<std::pair<llvm::Value *, SanitizerMask>, 2> Checks;
+ // So we can 'and' all the checks together, and still get 'false',
+ // if at least one of the checks detected an issue.
+
+ Check = EmitIntegerSignChangeCheckHelper(Src, SrcType, Dst, DstType, Builder);
+ CheckKind = Check.first;
+ Checks.emplace_back(Check.second);
+
+ if (CGF.SanOpts.has(SanitizerKind::ImplicitSignedIntegerTruncation) &&
+ (SrcBits > DstBits) && !SrcSigned && DstSigned) {
+ // If the signed integer truncation sanitizer was enabled,
+ // and we are truncating from larger unsigned type to smaller signed type,
+ // let's handle the case we skipped in that check.
+ Check =
+ EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
+ CheckKind = ICCK_SignedIntegerTruncationOrSignChange;
+ Checks.emplace_back(Check.second);
+ // If the comparison result is 'i1 false', then the truncation was lossy.
+ }
llvm::Constant *StaticArgs[] = {
CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
CGF.EmitCheckTypeDescriptor(DstType),
- llvm::ConstantInt::get(Builder.getInt8Ty(), ICCK_IntegerTruncation)};
- CGF.EmitCheck(std::make_pair(Check, SanitizerKind::ImplicitIntegerTruncation),
- SanitizerHandler::ImplicitConversion, StaticArgs, {Src, Dst});
+ llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind)};
+ // EmitCheck() will 'and' all the checks together.
+ CGF.EmitCheck(Checks, SanitizerHandler::ImplicitConversion, StaticArgs,
+ {Src, Dst});
}
/// Emit a conversion from the specified type to the specified destination type,
@@ -991,6 +1197,27 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
QualType DstType,
SourceLocation Loc,
ScalarConversionOpts Opts) {
+ // All conversions involving fixed point types should be handled by the
+ // EmitFixedPoint family functions. This is done to prevent bloating up this
+ // function more, and although fixed point numbers are represented by
+ // integers, we do not want to follow any logic that assumes they should be
+ // treated as integers.
+ // TODO(leonardchan): When necessary, add another if statement checking for
+ // conversions to fixed point types from other types.
+ if (SrcType->isFixedPointType()) {
+ if (DstType->isFixedPointType()) {
+ return EmitFixedPointConversion(Src, SrcType, DstType, Loc);
+ } else if (DstType->isBooleanType()) {
+ // We do not need to check the padding bit on unsigned types if unsigned
+ // padding is enabled because overflow into this bit is undefined
+ // behavior.
+ return Builder.CreateIsNotNull(Src, "tobool");
+ }
+
+ llvm_unreachable(
+ "Unhandled scalar conversion involving a fixed point type.");
+ }
+
QualType NoncanonicalSrcType = SrcType;
QualType NoncanonicalDstType = DstType;
@@ -1036,8 +1263,13 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
}
// Ignore conversions like int -> uint.
- if (SrcTy == DstTy)
+ if (SrcTy == DstTy) {
+ if (Opts.EmitImplicitIntegerSignChangeChecks)
+ EmitIntegerSignChangeCheck(Src, NoncanonicalSrcType, Src,
+ NoncanonicalDstType, Loc);
+
return Src;
+ }
// Handle pointer conversions next: pointers can only be converted to/from
// other pointers and integers. Check for pointer types in terms of LLVM, as
@@ -1181,9 +1413,91 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res,
NoncanonicalDstType, Loc);
+ if (Opts.EmitImplicitIntegerSignChangeChecks)
+ EmitIntegerSignChangeCheck(Src, NoncanonicalSrcType, Res,
+ NoncanonicalDstType, Loc);
+
return Res;
}
+Value *ScalarExprEmitter::EmitFixedPointConversion(Value *Src, QualType SrcTy,
+ QualType DstTy,
+ SourceLocation Loc) {
+ using llvm::APInt;
+ using llvm::ConstantInt;
+ using llvm::Value;
+
+ assert(SrcTy->isFixedPointType());
+ assert(DstTy->isFixedPointType());
+
+ FixedPointSemantics SrcFPSema =
+ CGF.getContext().getFixedPointSemantics(SrcTy);
+ FixedPointSemantics DstFPSema =
+ CGF.getContext().getFixedPointSemantics(DstTy);
+ unsigned SrcWidth = SrcFPSema.getWidth();
+ unsigned DstWidth = DstFPSema.getWidth();
+ unsigned SrcScale = SrcFPSema.getScale();
+ unsigned DstScale = DstFPSema.getScale();
+ bool SrcIsSigned = SrcFPSema.isSigned();
+ bool DstIsSigned = DstFPSema.isSigned();
+
+ llvm::Type *DstIntTy = Builder.getIntNTy(DstWidth);
+
+ Value *Result = Src;
+ unsigned ResultWidth = SrcWidth;
+
+ if (!DstFPSema.isSaturated()) {
+ // Downscale.
+ if (DstScale < SrcScale)
+ Result = SrcIsSigned ?
+ Builder.CreateAShr(Result, SrcScale - DstScale, "downscale") :
+ Builder.CreateLShr(Result, SrcScale - DstScale, "downscale");
+
+ // Resize.
+ Result = Builder.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize");
+
+ // Upscale.
+ if (DstScale > SrcScale)
+ Result = Builder.CreateShl(Result, DstScale - SrcScale, "upscale");
+ } else {
+ // Adjust the number of fractional bits.
+ if (DstScale > SrcScale) {
+ ResultWidth = SrcWidth + DstScale - SrcScale;
+ llvm::Type *UpscaledTy = Builder.getIntNTy(ResultWidth);
+ Result = Builder.CreateIntCast(Result, UpscaledTy, SrcIsSigned, "resize");
+ Result = Builder.CreateShl(Result, DstScale - SrcScale, "upscale");
+ } else if (DstScale < SrcScale) {
+ Result = SrcIsSigned ?
+ Builder.CreateAShr(Result, SrcScale - DstScale, "downscale") :
+ Builder.CreateLShr(Result, SrcScale - DstScale, "downscale");
+ }
+
+ // Handle saturation.
+ bool LessIntBits = DstFPSema.getIntegralBits() < SrcFPSema.getIntegralBits();
+ if (LessIntBits) {
+ Value *Max = ConstantInt::get(
+ CGF.getLLVMContext(),
+ APFixedPoint::getMax(DstFPSema).getValue().extOrTrunc(ResultWidth));
+ Value *TooHigh = SrcIsSigned ? Builder.CreateICmpSGT(Result, Max)
+ : Builder.CreateICmpUGT(Result, Max);
+ Result = Builder.CreateSelect(TooHigh, Max, Result, "satmax");
+ }
+ // Cannot overflow min to dest type if src is unsigned since all fixed
+ // point types can cover the unsigned min of 0.
+ if (SrcIsSigned && (LessIntBits || !DstIsSigned)) {
+ Value *Min = ConstantInt::get(
+ CGF.getLLVMContext(),
+ APFixedPoint::getMin(DstFPSema).getValue().extOrTrunc(ResultWidth));
+ Value *TooLow = Builder.CreateICmpSLT(Result, Min);
+ Result = Builder.CreateSelect(TooLow, Min, Result, "satmin");
+ }
+
+ // Resize the integer part to get the final destination size.
+ Result = Builder.CreateIntCast(Result, DstIntTy, SrcIsSigned, "resize");
+ }
+ return Result;
+}
+
/// Emit a conversion from the specified complex type to the specified
/// destination type, where the destination type is an LLVM scalar type.
Value *ScalarExprEmitter::EmitComplexToScalarConversion(
@@ -1405,10 +1719,11 @@ Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) {
CGF.EmitIgnoredExpr(E->getBase());
- return emitConstant(Constant, E);
+ return CGF.emitScalarConstant(Constant, E);
} else {
- llvm::APSInt Value;
- if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
+ Expr::EvalResult Result;
+ if (E->EvaluateAsInt(Result, CGF.getContext(), Expr::SE_AllowSideEffects)) {
+ llvm::APSInt Value = Result.Val.getInt();
CGF.EmitIgnoredExpr(E->getBase());
return Builder.getInt(Value);
}
@@ -1681,7 +1996,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
CGF.EmitVTablePtrCheckForCast(PT->getPointeeType(), Src,
/*MayBeNull=*/true,
CodeGenFunction::CFITCK_UnrelatedCast,
- CE->getLocStart());
+ CE->getBeginLoc());
}
if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
@@ -1745,11 +2060,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
Derived.getPointer(), DestTy->getPointeeType());
if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast))
- CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(),
- Derived.getPointer(),
- /*MayBeNull=*/true,
- CodeGenFunction::CFITCK_DerivedCast,
- CE->getLocStart());
+ CGF.EmitVTablePtrCheckForCast(
+ DestTy->getPointeeType(), Derived.getPointer(),
+ /*MayBeNull=*/true, CodeGenFunction::CFITCK_DerivedCast,
+ CE->getBeginLoc());
return Derived.getPointer();
}
@@ -1875,11 +2189,22 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
}
+ case CK_FixedPointCast:
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+ CE->getExprLoc());
+
+ case CK_FixedPointToBoolean:
+ assert(E->getType()->isFixedPointType() &&
+ "Expected src type to be fixed point type");
+ assert(DestTy->isBooleanType() && "Expected dest type to be boolean type");
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+ CE->getExprLoc());
+
case CK_IntegralCast: {
ScalarConversionOpts Opts;
- if (CGF.SanOpts.has(SanitizerKind::ImplicitIntegerTruncation)) {
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE))
- Opts.EmitImplicitIntegerTruncationChecks = !ICE->isPartOfExplicitCast();
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
+ if (!ICE->isPartOfExplicitCast())
+ Opts = ScalarConversionOpts(CGF.SanOpts);
}
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
CE->getExprLoc(), Opts);
@@ -1920,13 +2245,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
CE->getExprLoc());
}
- case CK_ZeroToOCLEvent: {
- assert(DestTy->isEventT() && "CK_ZeroToOCLEvent cast on non-event type");
- return llvm::Constant::getNullValue(ConvertType(DestTy));
- }
-
- case CK_ZeroToOCLQueue: {
- assert(DestTy->isQueueT() && "CK_ZeroToOCLQueue cast on non queue_t type");
+ case CK_ZeroToOCLOpaqueType: {
+ assert((DestTy->isEventT() || DestTy->isQueueT() ||
+ DestTy->isOCLIntelSubgroupAVCType()) &&
+ "CK_ZeroToOCLEvent cast on non-event type");
return llvm::Constant::getNullValue(ConvertType(DestTy));
}
@@ -1985,7 +2307,7 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
return Builder.CreateNSWAdd(InVal, Amount, Name);
- // Fall through.
+ LLVM_FALLTHROUGH;
case LangOptions::SOB_Trapping:
if (!E->canOverflow())
return Builder.CreateNSWAdd(InVal, Amount, Name);
@@ -2280,9 +2602,11 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
// Try folding the offsetof to a constant.
- llvm::APSInt Value;
- if (E->EvaluateAsInt(Value, CGF.getContext()))
+ Expr::EvalResult EVResult;
+ if (E->EvaluateAsInt(EVResult, CGF.getContext())) {
+ llvm::APSInt Value = EVResult.Val.getInt();
return Builder.getInt(Value);
+ }
// Loop over the components of the offsetof to compute the value.
unsigned n = E->getNumComponents();
@@ -2551,9 +2875,10 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
// Expand the binary operator.
Result = (this->*Func)(OpInfo);
- // Convert the result back to the LHS type.
- Result =
- EmitScalarConversion(Result, E->getComputationResultType(), LHSTy, Loc);
+ // Convert the result back to the LHS type,
+ // potentially with Implicit Conversion sanitizer check.
+ Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy,
+ Loc, ScalarConversionOpts(CGF.SanOpts));
if (atomicPHI) {
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
@@ -2991,7 +3316,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");
- // Fall through.
+ LLVM_FALLTHROUGH;
case LangOptions::SOB_Trapping:
if (CanElideOverflowCheck(CGF.getContext(), op))
return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");
@@ -3026,7 +3351,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
return Builder.CreateNSWSub(op.LHS, op.RHS, "sub");
- // Fall through.
+ LLVM_FALLTHROUGH;
case LangOptions::SOB_Trapping:
if (CanElideOverflowCheck(CGF.getContext(), op))
return Builder.CreateNSWSub(op.LHS, op.RHS, "sub");
diff --git a/lib/CodeGen/CGLoopInfo.cpp b/lib/CodeGen/CGLoopInfo.cpp
index 21e2b8dd8c31..fd0a9c773a2e 100644
--- a/lib/CodeGen/CGLoopInfo.cpp
+++ b/lib/CodeGen/CGLoopInfo.cpp
@@ -10,8 +10,8 @@
#include "CGLoopInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
-#include "clang/Sema/LoopHint.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
@@ -21,14 +21,17 @@ using namespace llvm;
static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
const llvm::DebugLoc &StartLoc,
- const llvm::DebugLoc &EndLoc) {
+ const llvm::DebugLoc &EndLoc, MDNode *&AccGroup) {
if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
+ Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
+ Attrs.PipelineInitiationInterval == 0 &&
Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
Attrs.UnrollEnable == LoopAttributes::Unspecified &&
- Attrs.DistributeEnable == LoopAttributes::Unspecified &&
- !StartLoc && !EndLoc)
+ Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
+ Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
+ !EndLoc)
return nullptr;
SmallVector<Metadata *, 4> Args;
@@ -61,7 +64,7 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
Args.push_back(MDNode::get(Ctx, Vals));
}
- // Setting interleave.count
+ // Setting unroll.count
if (Attrs.UnrollCount > 0) {
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
ConstantAsMetadata::get(ConstantInt::get(
@@ -69,6 +72,14 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
Args.push_back(MDNode::get(Ctx, Vals));
}
+ // Setting unroll_and_jam.count
+ if (Attrs.UnrollAndJamCount > 0) {
+ Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
+ ConstantAsMetadata::get(ConstantInt::get(
+ Type::getInt32Ty(Ctx), Attrs.UnrollAndJamCount))};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
// Setting vectorize.enable
if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
@@ -91,6 +102,19 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
Args.push_back(MDNode::get(Ctx, Vals));
}
+ // Setting unroll_and_jam.full or unroll_and_jam.disable
+ if (Attrs.UnrollAndJamEnable != LoopAttributes::Unspecified) {
+ std::string Name;
+ if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable)
+ Name = "llvm.loop.unroll_and_jam.enable";
+ else if (Attrs.UnrollAndJamEnable == LoopAttributes::Full)
+ Name = "llvm.loop.unroll_and_jam.full";
+ else
+ Name = "llvm.loop.unroll_and_jam.disable";
+ Metadata *Vals[] = {MDString::get(Ctx, Name)};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
if (Attrs.DistributeEnable != LoopAttributes::Unspecified) {
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
ConstantAsMetadata::get(ConstantInt::get(
@@ -99,6 +123,28 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
Args.push_back(MDNode::get(Ctx, Vals));
}
+ if (Attrs.IsParallel) {
+ AccGroup = MDNode::getDistinct(Ctx, {});
+ Args.push_back(MDNode::get(
+ Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
+ }
+
+ if (Attrs.PipelineDisabled) {
+ Metadata *Vals[] = {
+ MDString::get(Ctx, "llvm.loop.pipeline.disable"),
+ ConstantAsMetadata::get(ConstantInt::get(
+ Type::getInt1Ty(Ctx), (Attrs.PipelineDisabled == true)))};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
+ if (Attrs.PipelineInitiationInterval > 0) {
+ Metadata *Vals[] = {
+ MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
+ ConstantAsMetadata::get(ConstantInt::get(
+ Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
// Set the first operand to itself.
MDNode *LoopID = MDNode::get(Ctx, Args);
LoopID->replaceOperandWith(0, LoopID);
@@ -107,24 +153,31 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
LoopAttributes::LoopAttributes(bool IsParallel)
: IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
- UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
- InterleaveCount(0), UnrollCount(0),
- DistributeEnable(LoopAttributes::Unspecified) {}
+ UnrollEnable(LoopAttributes::Unspecified),
+ UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
+ InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
+ DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
+ PipelineInitiationInterval(0) {}
void LoopAttributes::clear() {
IsParallel = false;
VectorizeWidth = 0;
InterleaveCount = 0;
UnrollCount = 0;
+ UnrollAndJamCount = 0;
VectorizeEnable = LoopAttributes::Unspecified;
UnrollEnable = LoopAttributes::Unspecified;
+ UnrollAndJamEnable = LoopAttributes::Unspecified;
DistributeEnable = LoopAttributes::Unspecified;
+ PipelineDisabled = false;
+ PipelineInitiationInterval = 0;
}
LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
: LoopID(nullptr), Header(Header), Attrs(Attrs) {
- LoopID = createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc);
+ LoopID =
+ createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc, AccGroup);
}
void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
@@ -191,12 +244,20 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
case LoopHintAttr::Unroll:
setUnrollState(LoopAttributes::Disable);
break;
+ case LoopHintAttr::UnrollAndJam:
+ setUnrollAndJamState(LoopAttributes::Disable);
+ break;
case LoopHintAttr::Distribute:
setDistributeState(false);
break;
+ case LoopHintAttr::PipelineDisabled:
+ setPipelineDisabled(true);
+ break;
case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::UnrollAndJamCount:
case LoopHintAttr::VectorizeWidth:
case LoopHintAttr::InterleaveCount:
+ case LoopHintAttr::PipelineInitiationInterval:
llvm_unreachable("Options cannot be disabled.");
break;
}
@@ -210,12 +271,18 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
case LoopHintAttr::Unroll:
setUnrollState(LoopAttributes::Enable);
break;
+ case LoopHintAttr::UnrollAndJam:
+ setUnrollAndJamState(LoopAttributes::Enable);
+ break;
case LoopHintAttr::Distribute:
setDistributeState(true);
break;
case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::UnrollAndJamCount:
case LoopHintAttr::VectorizeWidth:
case LoopHintAttr::InterleaveCount:
+ case LoopHintAttr::PipelineDisabled:
+ case LoopHintAttr::PipelineInitiationInterval:
llvm_unreachable("Options cannot enabled.");
break;
}
@@ -229,10 +296,14 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
setVectorizeEnable(true);
break;
case LoopHintAttr::Unroll:
+ case LoopHintAttr::UnrollAndJam:
case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::UnrollAndJamCount:
case LoopHintAttr::VectorizeWidth:
case LoopHintAttr::InterleaveCount:
case LoopHintAttr::Distribute:
+ case LoopHintAttr::PipelineDisabled:
+ case LoopHintAttr::PipelineInitiationInterval:
llvm_unreachable("Options cannot be used to assume mem safety.");
break;
}
@@ -242,12 +313,18 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
case LoopHintAttr::Unroll:
setUnrollState(LoopAttributes::Full);
break;
+ case LoopHintAttr::UnrollAndJam:
+ setUnrollAndJamState(LoopAttributes::Full);
+ break;
case LoopHintAttr::Vectorize:
case LoopHintAttr::Interleave:
case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::UnrollAndJamCount:
case LoopHintAttr::VectorizeWidth:
case LoopHintAttr::InterleaveCount:
case LoopHintAttr::Distribute:
+ case LoopHintAttr::PipelineDisabled:
+ case LoopHintAttr::PipelineInitiationInterval:
llvm_unreachable("Options cannot be used with 'full' hint.");
break;
}
@@ -263,10 +340,18 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
case LoopHintAttr::UnrollCount:
setUnrollCount(ValueInt);
break;
+ case LoopHintAttr::UnrollAndJamCount:
+ setUnrollAndJamCount(ValueInt);
+ break;
+ case LoopHintAttr::PipelineInitiationInterval:
+ setPipelineInitiationInterval(ValueInt);
+ break;
case LoopHintAttr::Unroll:
+ case LoopHintAttr::UnrollAndJam:
case LoopHintAttr::Vectorize:
case LoopHintAttr::Interleave:
case LoopHintAttr::Distribute:
+ case LoopHintAttr::PipelineDisabled:
llvm_unreachable("Options cannot be assigned a value.");
break;
}
@@ -284,6 +369,21 @@ void LoopInfoStack::pop() {
}
void LoopInfoStack::InsertHelper(Instruction *I) const {
+ if (I->mayReadOrWriteMemory()) {
+ SmallVector<Metadata *, 4> AccessGroups;
+ for (const LoopInfo &AL : Active) {
+ // Here we assume that every loop that has an access group is parallel.
+ if (MDNode *Group = AL.getAccessGroup())
+ AccessGroups.push_back(Group);
+ }
+ MDNode *UnionMD = nullptr;
+ if (AccessGroups.size() == 1)
+ UnionMD = cast<MDNode>(AccessGroups[0]);
+ else if (AccessGroups.size() >= 2)
+ UnionMD = MDNode::get(I->getContext(), AccessGroups);
+ I->setMetadata("llvm.access.group", UnionMD);
+ }
+
if (!hasInfo())
return;
@@ -291,15 +391,12 @@ void LoopInfoStack::InsertHelper(Instruction *I) const {
if (!L.getLoopID())
return;
- if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
- for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
- if (TI->getSuccessor(i) == L.getHeader()) {
- TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
+ if (I->isTerminator()) {
+ for (BasicBlock *Succ : successors(I))
+ if (Succ == L.getHeader()) {
+ I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
break;
}
return;
}
-
- if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
- I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
}
diff --git a/lib/CodeGen/CGLoopInfo.h b/lib/CodeGen/CGLoopInfo.h
index 9d5f23ff9a2a..84ba03bfb00b 100644
--- a/lib/CodeGen/CGLoopInfo.h
+++ b/lib/CodeGen/CGLoopInfo.h
@@ -49,6 +49,9 @@ struct LoopAttributes {
/// Value for llvm.loop.unroll.* metadata (enable, disable, or full).
LVEnableState UnrollEnable;
+ /// Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
+ LVEnableState UnrollAndJamEnable;
+
/// Value for llvm.loop.vectorize.width metadata.
unsigned VectorizeWidth;
@@ -58,8 +61,17 @@ struct LoopAttributes {
/// llvm.unroll.
unsigned UnrollCount;
+ /// llvm.unroll.
+ unsigned UnrollAndJamCount;
+
/// Value for llvm.loop.distribute.enable metadata.
LVEnableState DistributeEnable;
+
+ /// Value for llvm.loop.pipeline.disable metadata.
+ bool PipelineDisabled;
+
+ /// Value for llvm.loop.pipeline.iicount metadata.
+ unsigned PipelineInitiationInterval;
};
/// Information used when generating a structured loop.
@@ -78,6 +90,9 @@ public:
/// Get the set of attributes active for this loop.
const LoopAttributes &getAttributes() const { return Attrs; }
+ /// Return this loop's access group or nullptr if it does not have one.
+ llvm::MDNode *getAccessGroup() const { return AccGroup; }
+
private:
/// Loop ID metadata.
llvm::MDNode *LoopID;
@@ -85,6 +100,8 @@ private:
llvm::BasicBlock *Header;
/// The attributes for this loop.
LoopAttributes Attrs;
+ /// The access group for memory accesses parallel to this loop.
+ llvm::MDNode *AccGroup = nullptr;
};
/// A stack of loop information corresponding to loop nesting levels.
@@ -143,6 +160,11 @@ public:
StagedAttrs.UnrollEnable = State;
}
+ /// Set the next pushed loop unroll_and_jam state.
+ void setUnrollAndJamState(const LoopAttributes::LVEnableState &State) {
+ StagedAttrs.UnrollAndJamEnable = State;
+ }
+
/// Set the vectorize width for the next loop pushed.
void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; }
@@ -152,6 +174,17 @@ public:
/// Set the unroll count for the next loop pushed.
void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; }
+ /// \brief Set the unroll count for the next loop pushed.
+ void setUnrollAndJamCount(unsigned C) { StagedAttrs.UnrollAndJamCount = C; }
+
+ /// Set the pipeline disabled state.
+ void setPipelineDisabled(bool S) { StagedAttrs.PipelineDisabled = S; }
+
+ /// Set the pipeline initiation interval.
+ void setPipelineInitiationInterval(unsigned C) {
+ StagedAttrs.PipelineInitiationInterval = C;
+ }
+
private:
/// Returns true if there is LoopInfo on the stack.
bool hasInfo() const { return !Active.empty(); }
diff --git a/lib/CodeGen/CGNonTrivialStruct.cpp b/lib/CodeGen/CGNonTrivialStruct.cpp
index 922e0934b866..c6a96a912622 100644
--- a/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -187,6 +187,7 @@ template <class Derived> struct GenFuncNameBase {
if (!FK)
return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
+ asDerived().flushTrivialFields();
CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
ASTContext &Ctx = asDerived().getContext();
const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
@@ -283,8 +284,9 @@ struct GenDefaultInitializeFuncName
struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
DestructedTypeVisitor<GenDestructorFuncName> {
using Super = DestructedTypeVisitor<GenDestructorFuncName>;
- GenDestructorFuncName(CharUnits DstAlignment, ASTContext &Ctx)
- : GenUnaryFuncName<GenDestructorFuncName>("__destructor_", DstAlignment,
+ GenDestructorFuncName(const char *Prefix, CharUnits DstAlignment,
+ ASTContext &Ctx)
+ : GenUnaryFuncName<GenDestructorFuncName>(Prefix, DstAlignment,
Ctx) {}
void visitWithKind(QualType::DestructionKind DK, QualType FT,
const FieldDecl *FD, CharUnits CurStructOffset) {
@@ -335,6 +337,7 @@ template <class Derived> struct GenFuncBase {
return asDerived().visitTrivial(QualType(AT, 0), FD, CurStackOffset,
Addrs);
+ asDerived().flushTrivialFields(Addrs);
CodeGenFunction &CGF = *this->CGF;
ASTContext &Ctx = CGF.getContext();
@@ -455,12 +458,13 @@ template <class Derived> struct GenFuncBase {
llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
FuncName, &CGM.getModule());
F->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.SetLLVMFunctionAttributes(nullptr, FI, F);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F);
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
IdentifierInfo *II = &Ctx.Idents.get(FuncName);
FunctionDecl *FD = FunctionDecl::Create(
Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
- II, Ctx.VoidTy, nullptr, SC_PrivateExtern, false, false);
+ II, Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {}), nullptr,
+ SC_PrivateExtern, false, false);
CodeGenFunction NewCGF(CGM);
setCGF(&NewCGF);
CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args);
@@ -824,11 +828,28 @@ void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) {
IsVolatile, *this, std::array<Address, 1>({{DstPtr}}));
}
+std::string
+CodeGenFunction::getNonTrivialCopyConstructorStr(QualType QT,
+ CharUnits Alignment,
+ bool IsVolatile,
+ ASTContext &Ctx) {
+ GenBinaryFuncName<false> GenName("", Alignment, Alignment, Ctx);
+ return GenName.getName(QT, IsVolatile);
+}
+
+std::string
+CodeGenFunction::getNonTrivialDestructorStr(QualType QT, CharUnits Alignment,
+ bool IsVolatile, ASTContext &Ctx) {
+ GenDestructorFuncName GenName("", Alignment, Ctx);
+ return GenName.getName(QT, IsVolatile);
+}
+
void CodeGenFunction::callCStructDestructor(LValue Dst) {
bool IsVolatile = Dst.isVolatile();
Address DstPtr = Dst.getAddress();
QualType QT = Dst.getType();
- GenDestructorFuncName GenName(DstPtr.getAlignment(), getContext());
+ GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(),
+ getContext());
std::string FuncName = GenName.getName(QT, IsVolatile);
callSpecialFunction(GenDestructor(getContext()), FuncName, QT, IsVolatile,
*this, std::array<Address, 1>({{DstPtr}}));
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index b94bbf2a384f..9c66ff0e8fb2 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -127,7 +127,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
llvm::Constant *Constant =
CGM.CreateRuntimeVariable(ConvertType(IdTy), ConstantName);
LValue LV = MakeNaturalAlignAddrLValue(Constant, IdTy);
- llvm::Value *Ptr = EmitLoadOfScalar(LV, E->getLocStart());
+ llvm::Value *Ptr = EmitLoadOfScalar(LV, E->getBeginLoc());
cast<llvm::LoadInst>(Ptr)->setMetadata(
CGM.getModule().getMDKindID("invariant.load"),
llvm::MDNode::get(getLLVMContext(), None));
@@ -352,6 +352,81 @@ static const Expr *findWeakLValue(const Expr *E) {
return nullptr;
}
+/// The ObjC runtime may provide entrypoints that are likely to be faster
+/// than an ordinary message send of the appropriate selector.
+///
+/// The entrypoints are guaranteed to be equivalent to just sending the
+/// corresponding message. If the entrypoint is implemented naively as just a
+/// message send, using it is a trade-off: it sacrifices a few cycles of
+/// overhead to save a small amount of code. However, it's possible for
+/// runtimes to detect and special-case classes that use "standard"
+/// behavior; if that's dynamically a large proportion of all objects, using
+/// the entrypoint will also be faster than using a message send.
+///
+/// If the runtime does support a required entrypoint, then this method will
+/// generate a call and return the resulting value. Otherwise it will return
+/// None and the caller can generate a msgSend instead.
+static Optional<llvm::Value *>
+tryGenerateSpecializedMessageSend(CodeGenFunction &CGF, QualType ResultType,
+ llvm::Value *Receiver,
+ const CallArgList& Args, Selector Sel,
+ const ObjCMethodDecl *method,
+ bool isClassMessage) {
+ auto &CGM = CGF.CGM;
+ if (!CGM.getCodeGenOpts().ObjCConvertMessagesToRuntimeCalls)
+ return None;
+
+ auto &Runtime = CGM.getLangOpts().ObjCRuntime;
+ switch (Sel.getMethodFamily()) {
+ case OMF_alloc:
+ if (isClassMessage &&
+ Runtime.shouldUseRuntimeFunctionsForAlloc() &&
+ ResultType->isObjCObjectPointerType()) {
+ // [Foo alloc] -> objc_alloc(Foo)
+ if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "alloc")
+ return CGF.EmitObjCAlloc(Receiver, CGF.ConvertType(ResultType));
+ // [Foo allocWithZone:nil] -> objc_allocWithZone(Foo)
+ if (Sel.isKeywordSelector() && Sel.getNumArgs() == 1 &&
+ Args.size() == 1 && Args.front().getType()->isPointerType() &&
+ Sel.getNameForSlot(0) == "allocWithZone") {
+ const llvm::Value* arg = Args.front().getKnownRValue().getScalarVal();
+ if (isa<llvm::ConstantPointerNull>(arg))
+ return CGF.EmitObjCAllocWithZone(Receiver,
+ CGF.ConvertType(ResultType));
+ return None;
+ }
+ }
+ break;
+
+ case OMF_autorelease:
+ if (ResultType->isObjCObjectPointerType() &&
+ CGM.getLangOpts().getGC() == LangOptions::NonGC &&
+ Runtime.shouldUseARCFunctionsForRetainRelease())
+ return CGF.EmitObjCAutorelease(Receiver, CGF.ConvertType(ResultType));
+ break;
+
+ case OMF_retain:
+ if (ResultType->isObjCObjectPointerType() &&
+ CGM.getLangOpts().getGC() == LangOptions::NonGC &&
+ Runtime.shouldUseARCFunctionsForRetainRelease())
+ return CGF.EmitObjCRetainNonBlock(Receiver, CGF.ConvertType(ResultType));
+ break;
+
+ case OMF_release:
+ if (ResultType->isVoidType() &&
+ CGM.getLangOpts().getGC() == LangOptions::NonGC &&
+ Runtime.shouldUseARCFunctionsForRetainRelease()) {
+ CGF.EmitObjCRelease(Receiver, ARCPreciseLifetime);
+ return nullptr;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return None;
+}
+
RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
ReturnValueSlot Return) {
// Only the lookup mechanism and first two arguments of the method
@@ -474,10 +549,17 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
Args,
method);
} else {
- result = Runtime.GenerateMessageSend(*this, Return, ResultType,
- E->getSelector(),
- Receiver, Args, OID,
- method);
+ // Call runtime methods directly if we can.
+ if (Optional<llvm::Value *> SpecializedResult =
+ tryGenerateSpecializedMessageSend(*this, ResultType, Receiver, Args,
+ E->getSelector(), method,
+ isClassMessage)) {
+ result = RValue::get(SpecializedResult.getValue());
+ } else {
+ result = Runtime.GenerateMessageSend(*this, Return, ResultType,
+ E->getSelector(), Receiver, Args,
+ OID, method);
+ }
}
// For delegate init calls in ARC, implicitly store the result of
@@ -531,7 +613,7 @@ struct FinishARCDealloc final : EHScopeStack::Cleanup {
/// CodeGenFunction.
void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) {
- SourceLocation StartLoc = OMD->getLocStart();
+ SourceLocation StartLoc = OMD->getBeginLoc();
FunctionArgList args;
// Check if we should generate debug info for this method.
if (OMD->hasAttr<NoDebugAttr>())
@@ -548,7 +630,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
args.append(OMD->param_begin(), OMD->param_end());
CurGD = OMD;
- CurEHLocation = OMD->getLocEnd();
+ CurEHLocation = OMD->getEndLoc();
StartFunction(OMD, OMD->getReturnType(), Fn, FI, args,
OMD->getLocation(), StartLoc);
@@ -568,7 +650,7 @@ static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF,
LValue lvalue, QualType type);
/// Generate an Objective-C method. An Objective-C method is a C function with
-/// its pointer, name, and types registered in the class struture.
+/// its pointer, name, and types registered in the class structure.
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
StartObjCMethod(OMD, OMD->getClassInterface());
PGO.assignRegionCounters(GlobalDecl(OMD), CurFn);
@@ -883,9 +965,10 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
// If there's a non-trivial 'get' expression, we just have to emit that.
if (!hasTrivialGetExpr(propImpl)) {
if (!AtomicHelperFn) {
- ReturnStmt ret(SourceLocation(), propImpl->getGetterCXXConstructor(),
- /*nrvo*/ nullptr);
- EmitReturnStmt(ret);
+ auto *ret = ReturnStmt::Create(getContext(), SourceLocation(),
+ propImpl->getGetterCXXConstructor(),
+ /* NRVOCandidate=*/nullptr);
+ EmitReturnStmt(*ret);
}
else {
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
@@ -1068,8 +1151,9 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
// The second argument is the address of the parameter variable.
ParmVarDecl *argVar = *OMD->param_begin();
- DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
- VK_LValue, SourceLocation());
+ DeclRefExpr argRef(CGF.getContext(), argVar, false,
+ argVar->getType().getNonReferenceType(), VK_LValue,
+ SourceLocation());
llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer();
argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
@@ -1113,8 +1197,9 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
// The second argument is the address of the parameter variable.
ParmVarDecl *argVar = *OMD->param_begin();
- DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
- VK_LValue, SourceLocation());
+ DeclRefExpr argRef(CGF.getContext(), argVar, false,
+ argVar->getType().getNonReferenceType(), VK_LValue,
+ SourceLocation());
llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer();
argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
@@ -1286,7 +1371,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
// Otherwise, fake up some ASTs and emit a normal assignment.
ValueDecl *selfDecl = setterMethod->getSelfDecl();
- DeclRefExpr self(selfDecl, false, selfDecl->getType(),
+ DeclRefExpr self(getContext(), selfDecl, false, selfDecl->getType(),
VK_LValue, SourceLocation());
ImplicitCastExpr selfLoad(ImplicitCastExpr::OnStack,
selfDecl->getType(), CK_LValueToRValue, &self,
@@ -1297,7 +1382,8 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
ParmVarDecl *argDecl = *setterMethod->param_begin();
QualType argType = argDecl->getType().getNonReferenceType();
- DeclRefExpr arg(argDecl, false, argType, VK_LValue, SourceLocation());
+ DeclRefExpr arg(getContext(), argDecl, false, argType, VK_LValue,
+ SourceLocation());
ImplicitCastExpr argLoad(ImplicitCastExpr::OnStack,
argType.getUnqualifiedType(), CK_LValueToRValue,
&arg, VK_RValue);
@@ -1459,7 +1545,8 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
llvm::Value *CodeGenFunction::LoadObjCSelf() {
VarDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl();
- DeclRefExpr DRE(Self, /*is enclosing local*/ (CurFuncDecl != CurCodeDecl),
+ DeclRefExpr DRE(getContext(), Self,
+ /*is enclosing local*/ (CurFuncDecl != CurCodeDecl),
Self->getType(), VK_LValue, SourceLocation());
return EmitLoadOfScalar(EmitDeclRefLValue(&DRE), SourceLocation());
}
@@ -1645,9 +1732,9 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Initialize the variable, in case it's a __block variable or something.
EmitAutoVarInit(variable);
- const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
- DeclRefExpr tempDRE(const_cast<VarDecl*>(D), false, D->getType(),
- VK_LValue, SourceLocation());
+ const VarDecl *D = cast<VarDecl>(SD->getSingleDecl());
+ DeclRefExpr tempDRE(getContext(), const_cast<VarDecl *>(D), false,
+ D->getType(), VK_LValue, SourceLocation());
elementLValue = EmitLValue(&tempDRE);
elementType = D->getType();
elementIsVariable = true;
@@ -1805,23 +1892,16 @@ llvm::Value *CodeGenFunction::EmitObjCExtendObjectLifetime(QualType type,
/// being intrinsically used up until this point in the program.
void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) {
llvm::Constant *&fn = CGM.getObjCEntrypoints().clang_arc_use;
- if (!fn) {
- llvm::FunctionType *fnType =
- llvm::FunctionType::get(CGM.VoidTy, None, true);
- fn = CGM.CreateRuntimeFunction(fnType, "clang.arc.use");
- }
+ if (!fn)
+ fn = CGM.getIntrinsic(llvm::Intrinsic::objc_clang_arc_use);
// This isn't really a "runtime" function, but as an intrinsic it
// doesn't really matter as long as we align things up.
EmitNounwindRuntimeCall(fn, values);
}
-
-static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
- llvm::FunctionType *FTy,
- StringRef Name) {
- llvm::Constant *RTF = CGM.CreateRuntimeFunction(FTy, Name);
-
+static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM,
+ llvm::Constant *RTF) {
if (auto *F = dyn_cast<llvm::Function>(RTF)) {
// If the target runtime doesn't naturally support ARC, emit weak
// references to the runtime support library. We don't really
@@ -1829,14 +1909,8 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC() &&
!CGM.getTriple().isOSBinFormatCOFF()) {
F->setLinkage(llvm::Function::ExternalWeakLinkage);
- } else if (Name == "objc_retain" || Name == "objc_release") {
- // If we have Native ARC, set nonlazybind attribute for these APIs for
- // performance.
- F->addFnAttr(llvm::Attribute::NonLazyBind);
}
}
-
- return RTF;
}
/// Perform an operation having the signature
@@ -1844,20 +1918,20 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
/// where a null input causes a no-op and returns null.
static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
llvm::Value *value,
+ llvm::Type *returnType,
llvm::Constant *&fn,
- StringRef fnName,
+ llvm::Intrinsic::ID IntID,
bool isTailCall = false) {
if (isa<llvm::ConstantPointerNull>(value))
return value;
if (!fn) {
- llvm::FunctionType *fnType =
- llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false);
- fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+ fn = CGF.CGM.getIntrinsic(IntID);
+ setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
// Cast the argument to 'id'.
- llvm::Type *origType = value->getType();
+ llvm::Type *origType = returnType ? returnType : value->getType();
value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy);
// Call the function.
@@ -1874,11 +1948,10 @@ static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF,
Address addr,
llvm::Constant *&fn,
- StringRef fnName) {
+ llvm::Intrinsic::ID IntID) {
if (!fn) {
- llvm::FunctionType *fnType =
- llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrPtrTy, false);
- fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+ fn = CGF.CGM.getIntrinsic(IntID);
+ setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
// Cast the argument to 'id*'.
@@ -1901,16 +1974,13 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF,
Address addr,
llvm::Value *value,
llvm::Constant *&fn,
- StringRef fnName,
+ llvm::Intrinsic::ID IntID,
bool ignored) {
assert(addr.getElementType() == value->getType());
if (!fn) {
- llvm::Type *argTypes[] = { CGF.Int8PtrPtrTy, CGF.Int8PtrTy };
-
- llvm::FunctionType *fnType
- = llvm::FunctionType::get(CGF.Int8PtrTy, argTypes, false);
- fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+ fn = CGF.CGM.getIntrinsic(IntID);
+ setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
llvm::Type *origType = value->getType();
@@ -1932,15 +2002,12 @@ static void emitARCCopyOperation(CodeGenFunction &CGF,
Address dst,
Address src,
llvm::Constant *&fn,
- StringRef fnName) {
+ llvm::Intrinsic::ID IntID) {
assert(dst.getType() == src.getType());
if (!fn) {
- llvm::Type *argTypes[] = { CGF.Int8PtrPtrTy, CGF.Int8PtrPtrTy };
-
- llvm::FunctionType *fnType
- = llvm::FunctionType::get(CGF.Builder.getVoidTy(), argTypes, false);
- fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+ fn = CGF.CGM.getIntrinsic(IntID);
+ setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
llvm::Value *args[] = {
@@ -1950,6 +2017,39 @@ static void emitARCCopyOperation(CodeGenFunction &CGF,
CGF.EmitNounwindRuntimeCall(fn, args);
}
+/// Perform an operation having the signature
+/// i8* (i8*)
+/// where a null input causes a no-op and returns null.
+static llvm::Value *emitObjCValueOperation(CodeGenFunction &CGF,
+ llvm::Value *value,
+ llvm::Type *returnType,
+ llvm::Constant *&fn,
+ StringRef fnName) {
+ if (isa<llvm::ConstantPointerNull>(value))
+ return value;
+
+ if (!fn) {
+ llvm::FunctionType *fnType =
+ llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false);
+ fn = CGF.CGM.CreateRuntimeFunction(fnType, fnName);
+
+ // We have Native ARC, so set nonlazybind attribute for performance
+ if (llvm::Function *f = dyn_cast<llvm::Function>(fn))
+ if (fnName == "objc_retain")
+ f->addFnAttr(llvm::Attribute::NonLazyBind);
+ }
+
+ // Cast the argument to 'id'.
+ llvm::Type *origType = returnType ? returnType : value->getType();
+ value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy);
+
+ // Call the function.
+ llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value);
+
+ // Cast the result back to the original type.
+ return CGF.Builder.CreateBitCast(call, origType);
+}
+
/// Produce the code to do a retain. Based on the type, calls one of:
/// call i8* \@objc_retain(i8* %value)
/// call i8* \@objc_retainBlock(i8* %value)
@@ -1963,9 +2063,9 @@ llvm::Value *CodeGenFunction::EmitARCRetain(QualType type, llvm::Value *value) {
/// Retain the given object, with normal retain semantics.
/// call i8* \@objc_retain(i8* %value)
llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) {
- return emitARCValueOperation(*this, value,
+ return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retain,
- "objc_retain");
+ llvm::Intrinsic::objc_retain);
}
/// Retain the given block, with _Block_copy semantics.
@@ -1977,9 +2077,9 @@ llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) {
llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value,
bool mandatory) {
llvm::Value *result
- = emitARCValueOperation(*this, value,
+ = emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retainBlock,
- "objc_retainBlock");
+ llvm::Intrinsic::objc_retainBlock);
// If the copy isn't mandatory, add !clang.arc.copy_on_escape to
// tell the optimizer that it doesn't need to do this copy if the
@@ -2047,9 +2147,9 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {
llvm::Value *
CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
emitAutoreleasedReturnValueMarker(*this);
- return emitARCValueOperation(*this, value,
+ return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
- "objc_retainAutoreleasedReturnValue");
+ llvm::Intrinsic::objc_retainAutoreleasedReturnValue);
}
/// Claim a possibly-autoreleased return value at +0. This is only
@@ -2062,9 +2162,9 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
llvm::Value *
CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) {
emitAutoreleasedReturnValueMarker(*this);
- return emitARCValueOperation(*this, value,
+ return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue,
- "objc_unsafeClaimAutoreleasedReturnValue");
+ llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue);
}
/// Release the given object.
@@ -2075,9 +2175,8 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value,
llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_release;
if (!fn) {
- llvm::FunctionType *fnType =
- llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
- fn = createARCRuntimeFunction(CGM, fnType, "objc_release");
+ fn = CGM.getIntrinsic(llvm::Intrinsic::objc_release);
+ setARCRuntimeFunctionLinkage(CGM, fn);
}
// Cast the argument to 'id'.
@@ -2122,10 +2221,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr,
llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_storeStrong;
if (!fn) {
- llvm::Type *argTypes[] = { Int8PtrPtrTy, Int8PtrTy };
- llvm::FunctionType *fnType
- = llvm::FunctionType::get(Builder.getVoidTy(), argTypes, false);
- fn = createARCRuntimeFunction(CGM, fnType, "objc_storeStrong");
+ fn = CGM.getIntrinsic(llvm::Intrinsic::objc_storeStrong);
+ setARCRuntimeFunctionLinkage(CGM, fn);
}
llvm::Value *args[] = {
@@ -2177,18 +2274,18 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst,
/// Autorelease the given object.
/// call i8* \@objc_autorelease(i8* %value)
llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) {
- return emitARCValueOperation(*this, value,
+ return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_autorelease,
- "objc_autorelease");
+ llvm::Intrinsic::objc_autorelease);
}
/// Autorelease the given object.
/// call i8* \@objc_autoreleaseReturnValue(i8* %value)
llvm::Value *
CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
- return emitARCValueOperation(*this, value,
+ return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_autoreleaseReturnValue,
- "objc_autoreleaseReturnValue",
+ llvm::Intrinsic::objc_autoreleaseReturnValue,
/*isTailCall*/ true);
}
@@ -2196,9 +2293,9 @@ CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
/// call i8* \@objc_retainAutoreleaseReturnValue(i8* %value)
llvm::Value *
CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) {
- return emitARCValueOperation(*this, value,
+ return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retainAutoreleaseReturnValue,
- "objc_retainAutoreleaseReturnValue",
+ llvm::Intrinsic::objc_retainAutoreleaseReturnValue,
/*isTailCall*/ true);
}
@@ -2225,9 +2322,9 @@ llvm::Value *CodeGenFunction::EmitARCRetainAutorelease(QualType type,
/// call i8* \@objc_retainAutorelease(i8* %value)
llvm::Value *
CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) {
- return emitARCValueOperation(*this, value,
+ return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retainAutorelease,
- "objc_retainAutorelease");
+ llvm::Intrinsic::objc_retainAutorelease);
}
/// i8* \@objc_loadWeak(i8** %addr)
@@ -2235,14 +2332,14 @@ CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) {
llvm::Value *CodeGenFunction::EmitARCLoadWeak(Address addr) {
return emitARCLoadOperation(*this, addr,
CGM.getObjCEntrypoints().objc_loadWeak,
- "objc_loadWeak");
+ llvm::Intrinsic::objc_loadWeak);
}
/// i8* \@objc_loadWeakRetained(i8** %addr)
llvm::Value *CodeGenFunction::EmitARCLoadWeakRetained(Address addr) {
return emitARCLoadOperation(*this, addr,
CGM.getObjCEntrypoints().objc_loadWeakRetained,
- "objc_loadWeakRetained");
+ llvm::Intrinsic::objc_loadWeakRetained);
}
/// i8* \@objc_storeWeak(i8** %addr, i8* %value)
@@ -2252,7 +2349,7 @@ llvm::Value *CodeGenFunction::EmitARCStoreWeak(Address addr,
bool ignored) {
return emitARCStoreOperation(*this, addr, value,
CGM.getObjCEntrypoints().objc_storeWeak,
- "objc_storeWeak", ignored);
+ llvm::Intrinsic::objc_storeWeak, ignored);
}
/// i8* \@objc_initWeak(i8** %addr, i8* %value)
@@ -2272,7 +2369,7 @@ void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) {
emitARCStoreOperation(*this, addr, value,
CGM.getObjCEntrypoints().objc_initWeak,
- "objc_initWeak", /*ignored*/ true);
+ llvm::Intrinsic::objc_initWeak, /*ignored*/ true);
}
/// void \@objc_destroyWeak(i8** %addr)
@@ -2280,9 +2377,8 @@ void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) {
void CodeGenFunction::EmitARCDestroyWeak(Address addr) {
llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_destroyWeak;
if (!fn) {
- llvm::FunctionType *fnType =
- llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrPtrTy, false);
- fn = createARCRuntimeFunction(CGM, fnType, "objc_destroyWeak");
+ fn = CGM.getIntrinsic(llvm::Intrinsic::objc_destroyWeak);
+ setARCRuntimeFunctionLinkage(CGM, fn);
}
// Cast the argument to 'id*'.
@@ -2297,7 +2393,7 @@ void CodeGenFunction::EmitARCDestroyWeak(Address addr) {
void CodeGenFunction::EmitARCMoveWeak(Address dst, Address src) {
emitARCCopyOperation(*this, dst, src,
CGM.getObjCEntrypoints().objc_moveWeak,
- "objc_moveWeak");
+ llvm::Intrinsic::objc_moveWeak);
}
/// void \@objc_copyWeak(i8** %dest, i8** %src)
@@ -2306,7 +2402,7 @@ void CodeGenFunction::EmitARCMoveWeak(Address dst, Address src) {
void CodeGenFunction::EmitARCCopyWeak(Address dst, Address src) {
emitARCCopyOperation(*this, dst, src,
CGM.getObjCEntrypoints().objc_copyWeak,
- "objc_copyWeak");
+ llvm::Intrinsic::objc_copyWeak);
}
void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr,
@@ -2329,9 +2425,8 @@ void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr,
llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush;
if (!fn) {
- llvm::FunctionType *fnType =
- llvm::FunctionType::get(Int8PtrTy, false);
- fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPush");
+ fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush);
+ setARCRuntimeFunctionLinkage(CGM, fn);
}
return EmitNounwindRuntimeCall(fn);
@@ -2342,18 +2437,28 @@ llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) {
assert(value->getType() == Int8PtrTy);
- llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
- if (!fn) {
- llvm::FunctionType *fnType =
- llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
+ if (getInvokeDest()) {
+ // Call the runtime method not the intrinsic if we are handling exceptions
+ llvm::Constant *&fn =
+ CGM.getObjCEntrypoints().objc_autoreleasePoolPopInvoke;
+ if (!fn) {
+ llvm::FunctionType *fnType =
+ llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
+ fn = CGM.CreateRuntimeFunction(fnType, "objc_autoreleasePoolPop");
+ setARCRuntimeFunctionLinkage(CGM, fn);
+ }
- // We don't want to use a weak import here; instead we should not
- // fall into this path.
- fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPop");
- }
+ // objc_autoreleasePoolPop can throw.
+ EmitRuntimeCallOrInvoke(fn, value);
+ } else {
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
+ if (!fn) {
+ fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop);
+ setARCRuntimeFunctionLinkage(CGM, fn);
+ }
- // objc_autoreleasePoolPop can throw.
- EmitRuntimeCallOrInvoke(fn, value);
+ EmitRuntimeCall(fn, value);
+ }
}
/// Produce the code to do an MRR version objc_autoreleasepool_push.
@@ -2384,6 +2489,24 @@ llvm::Value *CodeGenFunction::EmitObjCMRRAutoreleasePoolPush() {
return InitRV.getScalarVal();
}
+/// Allocate the given objc object.
+/// call i8* \@objc_alloc(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCAlloc(llvm::Value *value,
+ llvm::Type *resultType) {
+ return emitObjCValueOperation(*this, value, resultType,
+ CGM.getObjCEntrypoints().objc_alloc,
+ "objc_alloc");
+}
+
+/// Allocate the given objc object.
+/// call i8* \@objc_allocWithZone(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCAllocWithZone(llvm::Value *value,
+ llvm::Type *resultType) {
+ return emitObjCValueOperation(*this, value, resultType,
+ CGM.getObjCEntrypoints().objc_allocWithZone,
+ "objc_allocWithZone");
+}
+
/// Produce the code to do a primitive release.
/// [tmp drain];
void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) {
@@ -2418,6 +2541,55 @@ void CodeGenFunction::emitARCIntrinsicUse(CodeGenFunction &CGF, Address addr,
CGF.EmitARCIntrinsicUse(value);
}
+/// Autorelease the given object.
+/// call i8* \@objc_autorelease(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCAutorelease(llvm::Value *value,
+ llvm::Type *returnType) {
+ return emitObjCValueOperation(*this, value, returnType,
+ CGM.getObjCEntrypoints().objc_autoreleaseRuntimeFunction,
+ "objc_autorelease");
+}
+
+/// Retain the given object, with normal retain semantics.
+/// call i8* \@objc_retain(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCRetainNonBlock(llvm::Value *value,
+ llvm::Type *returnType) {
+ return emitObjCValueOperation(*this, value, returnType,
+ CGM.getObjCEntrypoints().objc_retainRuntimeFunction,
+ "objc_retain");
+}
+
+/// Release the given object.
+/// call void \@objc_release(i8* %value)
+void CodeGenFunction::EmitObjCRelease(llvm::Value *value,
+ ARCPreciseLifetime_t precise) {
+ if (isa<llvm::ConstantPointerNull>(value)) return;
+
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_release;
+ if (!fn) {
+ if (!fn) {
+ llvm::FunctionType *fnType =
+ llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
+ fn = CGM.CreateRuntimeFunction(fnType, "objc_release");
+ setARCRuntimeFunctionLinkage(CGM, fn);
+ // We have Native ARC, so set nonlazybind attribute for performance
+ if (llvm::Function *f = dyn_cast<llvm::Function>(fn))
+ f->addFnAttr(llvm::Attribute::NonLazyBind);
+ }
+ }
+
+ // Cast the argument to 'id'.
+ value = Builder.CreateBitCast(value, Int8PtrTy);
+
+ // Call objc_release.
+ llvm::CallInst *call = EmitNounwindRuntimeCall(fn, value);
+
+ if (precise == ARCImpreciseLifetime) {
+ call->setMetadata("clang.imprecise_release",
+ llvm::MDNode::get(Builder.getContext(), None));
+ }
+}
+
namespace {
struct CallObjCAutoreleasePoolObject final : EHScopeStack::Cleanup {
llvm::Value *Token;
@@ -2446,27 +2618,36 @@ void CodeGenFunction::EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr) {
EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, Ptr);
}
-static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
- LValue lvalue,
- QualType type) {
- switch (type.getObjCLifetime()) {
+static bool shouldRetainObjCLifetime(Qualifiers::ObjCLifetime lifetime) {
+ switch (lifetime) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Strong:
case Qualifiers::OCL_Autoreleasing:
- return TryEmitResult(CGF.EmitLoadOfLValue(lvalue,
- SourceLocation()).getScalarVal(),
- false);
+ return true;
case Qualifiers::OCL_Weak:
- return TryEmitResult(CGF.EmitARCLoadWeakRetained(lvalue.getAddress()),
- true);
+ return false;
}
llvm_unreachable("impossible lifetime!");
}
static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
+ LValue lvalue,
+ QualType type) {
+ llvm::Value *result;
+ bool shouldRetain = shouldRetainObjCLifetime(type.getObjCLifetime());
+ if (shouldRetain) {
+ result = CGF.EmitLoadOfLValue(lvalue, SourceLocation()).getScalarVal();
+ } else {
+ assert(type.getObjCLifetime() == Qualifiers::OCL_Weak);
+ result = CGF.EmitARCLoadWeakRetained(lvalue.getAddress());
+ }
+ return TryEmitResult(result, !shouldRetain);
+}
+
+static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
const Expr *e) {
e = e->IgnoreParens();
QualType type = e->getType();
@@ -2500,6 +2681,16 @@ static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
cast<BinaryOperator>(e)->getOpcode() == BO_Assign)
return TryEmitResult(CGF.EmitScalarExpr(e), false);
+ // Try to emit code for scalar constant instead of emitting LValue and
+ // loading it because we are not guaranteed to have an l-value. One of such
+ // cases is DeclRefExpr referencing non-odr-used constant-evaluated variable.
+ if (const auto *decl_expr = dyn_cast<DeclRefExpr>(e)) {
+ auto *DRE = const_cast<DeclRefExpr *>(decl_expr);
+ if (CodeGenFunction::ConstantEmission constant = CGF.tryEmitAsConstant(DRE))
+ return TryEmitResult(CGF.emitScalarConstant(constant, DRE),
+ !shouldRetainObjCLifetime(type.getObjCLifetime()));
+ }
+
return tryEmitARCRetainLoadOfScalar(CGF, CGF.EmitLValue(e), type);
}
@@ -3229,29 +3420,32 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
ASTContext &C = getContext();
IdentifierInfo *II
= &CGM.getContext().Idents.get("__assign_helper_atomic_property_");
- FunctionDecl *FD = FunctionDecl::Create(C,
- C.getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(), II, C.VoidTy,
- nullptr, SC_Static,
- false,
- false);
+ QualType ReturnTy = C.VoidTy;
QualType DestTy = C.getPointerType(Ty);
QualType SrcTy = Ty;
SrcTy.addConst();
SrcTy = C.getPointerType(SrcTy);
+ SmallVector<QualType, 2> ArgTys;
+ ArgTys.push_back(DestTy);
+ ArgTys.push_back(SrcTy);
+ QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
+
+ FunctionDecl *FD = FunctionDecl::Create(
+ C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
+ FunctionTy, nullptr, SC_Static, false, false);
+
FunctionArgList args;
- ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
- DestTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy,
+ ImplicitParamDecl::Other);
args.push_back(&DstDecl);
- ImplicitParamDecl SrcDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
- SrcTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy,
+ ImplicitParamDecl::Other);
args.push_back(&SrcDecl);
const CGFunctionInfo &FI =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
@@ -3262,25 +3456,25 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
- StartFunction(FD, C.VoidTy, Fn, FI, args);
+ StartFunction(FD, ReturnTy, Fn, FI, args);
- DeclRefExpr DstExpr(&DstDecl, false, DestTy,
- VK_RValue, SourceLocation());
+ DeclRefExpr DstExpr(getContext(), &DstDecl, false, DestTy, VK_RValue,
+ SourceLocation());
UnaryOperator DST(&DstExpr, UO_Deref, DestTy->getPointeeType(),
VK_LValue, OK_Ordinary, SourceLocation(), false);
- DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy,
- VK_RValue, SourceLocation());
+ DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue,
+ SourceLocation());
UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
VK_LValue, OK_Ordinary, SourceLocation(), false);
Expr *Args[2] = { &DST, &SRC };
CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
- CXXOperatorCallExpr TheCall(C, OO_Equal, CalleeExp->getCallee(),
- Args, DestTy->getPointeeType(),
- VK_LValue, SourceLocation(), FPOptions());
+ CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
+ C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(),
+ VK_LValue, SourceLocation(), FPOptions());
- EmitStmt(&TheCall);
+ EmitStmt(TheCall);
FinishFunction();
HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
@@ -3301,53 +3495,54 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic)))
return nullptr;
llvm::Constant *HelperFn = nullptr;
-
if (hasTrivialGetExpr(PID))
return nullptr;
assert(PID->getGetterCXXConstructor() && "getGetterCXXConstructor - null");
if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty)))
return HelperFn;
-
ASTContext &C = getContext();
- IdentifierInfo *II
- = &CGM.getContext().Idents.get("__copy_helper_atomic_property_");
- FunctionDecl *FD = FunctionDecl::Create(C,
- C.getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(), II, C.VoidTy,
- nullptr, SC_Static,
- false,
- false);
+ IdentifierInfo *II =
+ &CGM.getContext().Idents.get("__copy_helper_atomic_property_");
+ QualType ReturnTy = C.VoidTy;
QualType DestTy = C.getPointerType(Ty);
QualType SrcTy = Ty;
SrcTy.addConst();
SrcTy = C.getPointerType(SrcTy);
+ SmallVector<QualType, 2> ArgTys;
+ ArgTys.push_back(DestTy);
+ ArgTys.push_back(SrcTy);
+ QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
+
+ FunctionDecl *FD = FunctionDecl::Create(
+ C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
+ FunctionTy, nullptr, SC_Static, false, false);
+
FunctionArgList args;
- ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
- DestTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy,
+ ImplicitParamDecl::Other);
args.push_back(&DstDecl);
- ImplicitParamDecl SrcDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
- SrcTy, ImplicitParamDecl::Other);
+ ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy,
+ ImplicitParamDecl::Other);
args.push_back(&SrcDecl);
const CGFunctionInfo &FI =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
- llvm::Function *Fn =
- llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
- "__copy_helper_atomic_property_", &CGM.getModule());
+ llvm::Function *Fn = llvm::Function::Create(
+ LTy, llvm::GlobalValue::InternalLinkage, "__copy_helper_atomic_property_",
+ &CGM.getModule());
CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
- StartFunction(FD, C.VoidTy, Fn, FI, args);
+ StartFunction(FD, ReturnTy, Fn, FI, args);
- DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy,
- VK_RValue, SourceLocation());
+ DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue,
+ SourceLocation());
UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
VK_LValue, OK_Ordinary, SourceLocation(), false);
@@ -3372,8 +3567,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
CXXConstExpr->getConstructionKind(),
SourceRange());
- DeclRefExpr DstExpr(&DstDecl, false, DestTy,
- VK_RValue, SourceLocation());
+ DeclRefExpr DstExpr(getContext(), &DstDecl, false, DestTy, VK_RValue,
+ SourceLocation());
RValue DV = EmitAnyExpr(&DstExpr);
CharUnits Alignment
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 3e994edc976b..548bd6b3fd72 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -18,6 +18,7 @@
#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "CGCXXABI.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -178,6 +179,9 @@ protected:
/// runtime provides some LLVM passes that can use this to do things like
/// automatic IMP caching and speculative inlining.
unsigned msgSendMDKind;
+ /// Does the current target use SEH-based exceptions? False implies
+ /// Itanium-style DWARF unwinding.
+ bool usesSEHExceptions;
/// Helper to check if we are targeting a specific runtime version or later.
bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) {
@@ -217,6 +221,7 @@ protected:
llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true,
llvm::GlobalValue::LinkOnceODRLinkage, value, name);
+ GV->setComdat(TheModule.getOrInsertComdat(name));
if (Private)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
ConstStr = GV;
@@ -272,6 +277,8 @@ protected:
Fields.addInt(Int8Ty, 0);
}
+ virtual llvm::Constant *GenerateCategoryProtocolList(const
+ ObjCCategoryDecl *OCD);
virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
int count) {
// int count;
@@ -510,8 +517,8 @@ protected:
/// Returns a selector with the specified type encoding. An empty string is
/// used to return an untyped selector (with the types field set to NULL).
- virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding);
+ virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding);
/// Returns the name of ivar offset variables. In the GNUstep v1 ABI, this
/// contains the class and ivar names, in the v2 ABI this contains the type
@@ -810,8 +817,12 @@ class CGObjCGNUstep : public CGObjCGNU {
// Slot_t objc_slot_lookup_super(struct objc_super*, SEL);
SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
PtrToObjCSuperTy, SelectorTy);
- // If we're in ObjC++ mode, then we want to make
- if (CGM.getLangOpts().CPlusPlus) {
+ // If we're in ObjC++ mode, then we want to make
+ if (usesSEHExceptions) {
+ llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
+ // void objc_exception_rethrow(void)
+ ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
+ } else if (CGM.getLangOpts().CPlusPlus) {
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
// void *__cxa_begin_catch(void *e)
EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
@@ -888,22 +899,25 @@ class CGObjCGNUstep : public CGObjCGNU {
/// This is the ABI that provides a clean break with the legacy GCC ABI and
/// cleans up a number of things that were added to work around 1980s linkers.
class CGObjCGNUstep2 : public CGObjCGNUstep {
- /// The section for selectors.
- static constexpr const char *const SelSection = "__objc_selectors";
- /// The section for classes.
- static constexpr const char *const ClsSection = "__objc_classes";
- /// The section for references to classes.
- static constexpr const char *const ClsRefSection = "__objc_class_refs";
- /// The section for categories.
- static constexpr const char *const CatSection = "__objc_cats";
- /// The section for protocols.
- static constexpr const char *const ProtocolSection = "__objc_protocols";
- /// The section for protocol references.
- static constexpr const char *const ProtocolRefSection = "__objc_protocol_refs";
- /// The section for class aliases
- static constexpr const char *const ClassAliasSection = "__objc_class_aliases";
- /// The section for constexpr constant strings
- static constexpr const char *const ConstantStringSection = "__objc_constant_string";
+ enum SectionKind
+ {
+ SelectorSection = 0,
+ ClassSection,
+ ClassReferenceSection,
+ CategorySection,
+ ProtocolSection,
+ ProtocolReferenceSection,
+ ClassAliasSection,
+ ConstantStringSection
+ };
+ static const char *const SectionsBaseNames[8];
+ template<SectionKind K>
+ std::string sectionName() {
+ std::string name(SectionsBaseNames[K]);
+ if (CGM.getTriple().isOSBinFormatCOFF())
+ name += "$m";
+ return name;
+ }
/// The GCC ABI superclass message lookup function. Takes a pointer to a
/// structure describing the receiver and the class, and a selector as
/// arguments. Returns the IMP for the corresponding method.
@@ -1069,7 +1083,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
isNamed ? StringRef(StringName) : ".objc_string",
Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
: llvm::GlobalValue::PrivateLinkage);
- ObjCStrGV->setSection(ConstantStringSection);
+ ObjCStrGV->setSection(sectionName<ConstantStringSection>());
if (isNamed) {
ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
@@ -1152,6 +1166,15 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
return MethodList.finishAndCreateGlobal(".objc_protocol_method_list",
CGM.getPointerAlign());
}
+ llvm::Constant *GenerateCategoryProtocolList(const ObjCCategoryDecl *OCD)
+ override {
+ SmallVector<llvm::Constant*, 16> Protocols;
+ for (const auto *PI : OCD->getReferencedProtocols())
+ Protocols.push_back(
+ llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
+ ProtocolPtrTy));
+ return GenerateProtocolList(Protocols);
+ }
llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
llvm::Value *cmd, MessageSendInfo &MSI) override {
@@ -1247,9 +1270,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
assert(!TheModule.getGlobalVariable(RefName));
// Emit a reference symbol.
auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
- false, llvm::GlobalValue::ExternalLinkage,
+ false, llvm::GlobalValue::LinkOnceODRLinkage,
llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName);
- GV->setSection(ProtocolRefSection);
+ GV->setComdat(TheModule.getOrInsertComdat(RefName));
+ GV->setSection(sectionName<ProtocolReferenceSection>());
GV->setAlignment(CGM.getPointerAlign().getQuantity());
Ref = GV;
}
@@ -1282,9 +1306,22 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
EmittedProtocol = true;
+ auto SymName = SymbolForProtocol(ProtocolName);
+ auto *OldGV = TheModule.getGlobalVariable(SymName);
+
// Use the protocol definition, if there is one.
if (const ObjCProtocolDecl *Def = PD->getDefinition())
PD = Def;
+ else {
+ // If there is no definition, then create an external linkage symbol and
+ // hope that someone else fills it in for us (and fail to link if they
+ // don't).
+ assert(!OldGV);
+ Protocol = new llvm::GlobalVariable(TheModule, ProtocolTy,
+ /*isConstant*/false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, SymName);
+ return Protocol;
+ }
SmallVector<llvm::Constant*, 16> Protocols;
for (const auto *PI : PD->protocols())
@@ -1301,8 +1338,6 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
EmitProtocolMethodList(PD->class_methods(), ClassMethodList,
OptionalClassMethodList);
- auto SymName = SymbolForProtocol(ProtocolName);
- auto *OldGV = TheModule.getGlobalVariable(SymName);
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
ConstantInitBuilder builder(CGM);
@@ -1326,7 +1361,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
- GV->setSection(ProtocolSection);
+ GV->setSection(sectionName<ProtocolSection>());
GV->setComdat(TheModule.getOrInsertComdat(SymName));
if (OldGV) {
OldGV->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GV,
@@ -1342,8 +1377,8 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
return Val;
return llvm::ConstantExpr::getBitCast(Val, Ty);
}
- llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding) override {
+ llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding) override {
return GetConstantSelector(Sel, TypeEncoding);
}
llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
@@ -1359,6 +1394,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
TypeEncoding);
auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(),
true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName);
+ GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
TypesGlobal = GV;
}
@@ -1387,12 +1423,41 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- GV->setSection(SelSection);
+ GV->setSection(sectionName<SelectorSection>());
auto *SelVal = EnforceType(GV, SelectorTy);
return SelVal;
}
+ llvm::StructType *emptyStruct = nullptr;
+
+ /// Return pointers to the start and end of a section. On ELF platforms, we
+ /// use the __start_ and __stop_ symbols that GNU-compatible linkers will set
+ /// to the start and end of section names, as long as those section names are
+ /// valid identifiers and the symbols are referenced but not defined. On
+ /// Windows, we use the fact that MSVC-compatible linkers will lexically sort
+ /// by subsections and place everything that we want to reference in a middle
+ /// subsection and then insert zero-sized symbols in subsections a and z.
std::pair<llvm::Constant*,llvm::Constant*>
GetSectionBounds(StringRef Section) {
+ if (CGM.getTriple().isOSBinFormatCOFF()) {
+ if (emptyStruct == nullptr) {
+ emptyStruct = llvm::StructType::create(VMContext, ".objc_section_sentinel");
+ emptyStruct->setBody({}, /*isPacked*/true);
+ }
+ auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
+ auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
+ auto *Sym = new llvm::GlobalVariable(TheModule, emptyStruct,
+ /*isConstant*/false,
+ llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
+ Section);
+ Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ Sym->setSection((Section + SecSuffix).str());
+ Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
+ Section).str()));
+ Sym->setAlignment(1);
+ return Sym;
+ };
+ return { Sym("__start_", "$a"), Sym("__stop", "$z") };
+ }
auto *Start = new llvm::GlobalVariable(TheModule, PtrTy,
/*isConstant*/false,
llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") +
@@ -1405,6 +1470,9 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
return { Start, Stop };
}
+ CatchTypeInfo getCatchAllTypeInfo() override {
+ return CGM.getCXXABI().getCatchAllTypeInfo();
+ }
llvm::Function *ModuleInitFunction() override {
llvm::Function *LoadFunction = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
@@ -1420,19 +1488,11 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
ConstantInitBuilder builder(CGM);
auto InitStructBuilder = builder.beginStruct();
InitStructBuilder.addInt(Int64Ty, 0);
- auto addSection = [&](const char *section) {
- auto bounds = GetSectionBounds(section);
+ for (auto *s : SectionsBaseNames) {
+ auto bounds = GetSectionBounds(s);
InitStructBuilder.add(bounds.first);
InitStructBuilder.add(bounds.second);
};
- addSection(SelSection);
- addSection(ClsSection);
- addSection(ClsRefSection);
- addSection(CatSection);
- addSection(ProtocolSection);
- addSection(ProtocolRefSection);
- addSection(ClassAliasSection);
- addSection(ConstantStringSection);
auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init",
CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
@@ -1451,18 +1511,23 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
// Check that this hasn't been renamed. This shouldn't happen, because
// this function should be called precisely once.
assert(InitVar->getName() == ".objc_ctor");
- InitVar->setSection(".ctors");
+ // In Windows, initialisers are sorted by the suffix. XCL is for library
+ // initialisers, which run before user initialisers. We are running
+ // Objective-C loads at the end of library load. This means +load methods
+ // will run before any other static constructors, but that static
+ // constructors can see a fully initialised Objective-C state.
+ if (CGM.getTriple().isOSBinFormatCOFF())
+ InitVar->setSection(".CRT$XCLz");
+ else
+ InitVar->setSection(".ctors");
InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor"));
- CGM.addCompilerUsedGlobal(InitVar);
+ CGM.addUsedGlobal(InitVar);
for (auto *C : Categories) {
auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts());
- Cat->setSection(CatSection);
+ Cat->setSection(sectionName<CategorySection>());
CGM.addUsedGlobal(Cat);
}
- // Add a null value fore each special section so that we can always
- // guarantee that the _start and _stop symbols will exist and be
- // meaningful.
auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init,
StringRef Section) {
auto nullBuilder = builder.beginStruct();
@@ -1476,38 +1541,48 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
CGM.addUsedGlobal(GV);
return GV;
};
- createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr}, SelSection);
- if (Categories.empty())
- createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
- NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr}, CatSection);
- if (!EmittedClass) {
- createNullGlobal(".objc_null_cls_init_ref", NULLPtr, ClsSection);
- createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
- ClsRefSection);
- }
- if (!EmittedProtocol)
- createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
- NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
- NULLPtr}, ProtocolSection);
- if (!EmittedProtocolRef)
- createNullGlobal(".objc_null_protocol_ref", {NULLPtr}, ProtocolRefSection);
- if (!ClassAliases.empty())
- for (auto clsAlias : ClassAliases)
- createNullGlobal(std::string(".objc_class_alias") +
- clsAlias.second, { MakeConstantString(clsAlias.second),
- GetClassVar(clsAlias.first) }, ClassAliasSection);
- else
- createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
- ClassAliasSection);
- if (ConstantStrings.empty()) {
- auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
- createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
- i32Zero, i32Zero, i32Zero, NULLPtr }, ConstantStringSection);
+ for (auto clsAlias : ClassAliases)
+ createNullGlobal(std::string(".objc_class_alias") +
+ clsAlias.second, { MakeConstantString(clsAlias.second),
+ GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
+ // On ELF platforms, add a null value for each special section so that we
+ // can always guarantee that the _start and _stop symbols will exist and be
+ // meaningful. This is not required on COFF platforms, where our start and
+ // stop symbols will create the section.
+ if (!CGM.getTriple().isOSBinFormatCOFF()) {
+ createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr},
+ sectionName<SelectorSection>());
+ if (Categories.empty())
+ createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
+ sectionName<CategorySection>());
+ if (!EmittedClass) {
+ createNullGlobal(".objc_null_cls_init_ref", NULLPtr,
+ sectionName<ClassSection>());
+ createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
+ sectionName<ClassReferenceSection>());
+ }
+ if (!EmittedProtocol)
+ createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr}, sectionName<ProtocolSection>());
+ if (!EmittedProtocolRef)
+ createNullGlobal(".objc_null_protocol_ref", {NULLPtr},
+ sectionName<ProtocolReferenceSection>());
+ if (ClassAliases.empty())
+ createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
+ sectionName<ClassAliasSection>());
+ if (ConstantStrings.empty()) {
+ auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
+ createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
+ i32Zero, i32Zero, i32Zero, NULLPtr },
+ sectionName<ConstantStringSection>());
+ }
}
ConstantStrings.clear();
Categories.clear();
Classes.clear();
- return nullptr;//CGObjCGNU::ModuleInitFunction();
+ return nullptr;
}
/// In the v2 ABI, ivar offset variables use the type encoding in their name
/// to trigger linker failures if the types don't match.
@@ -1774,7 +1849,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
}
auto *classRefSymbol = GetClassVar(className);
- classRefSymbol->setSection(ClsRefSection);
+ classRefSymbol->setSection(sectionName<ClassReferenceSection>());
classRefSymbol->setInitializer(llvm::ConstantExpr::getBitCast(classStruct, IdTy));
@@ -1805,7 +1880,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
auto classInitRef = new llvm::GlobalVariable(TheModule,
classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage,
classStruct, "._OBJC_INIT_CLASS_" + className);
- classInitRef->setSection(ClsSection);
+ classInitRef->setSection(sectionName<ClassSection>());
CGM.addUsedGlobal(classInitRef);
EmittedClass = true;
@@ -1829,6 +1904,18 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
};
+const char *const CGObjCGNUstep2::SectionsBaseNames[8] =
+{
+"__objc_selectors",
+"__objc_classes",
+"__objc_class_refs",
+"__objc_cats",
+"__objc_protocols",
+"__objc_protocol_refs",
+"__objc_class_aliases",
+"__objc_constant_string"
+};
+
/// Support for the ObjFW runtime.
class CGObjCObjFW: public CGObjCGNU {
protected:
@@ -1931,6 +2018,8 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
+ usesSEHExceptions =
+ cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
CodeGenTypes &Types = CGM.getTypes();
IntTy = cast<llvm::IntegerType>(
@@ -2121,8 +2210,8 @@ llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
return Value;
}
-llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding) {
+llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding) {
SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
llvm::GlobalAlias *SelValue = nullptr;
@@ -2155,13 +2244,13 @@ Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
- return GetSelector(CGF, Sel, std::string());
+ return GetTypedSelector(CGF, Sel, std::string());
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) {
std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method);
- return GetSelector(CGF, Method->getSelector(), SelTypes);
+ return GetTypedSelector(CGF, Method->getSelector(), SelTypes);
}
llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
@@ -2186,6 +2275,9 @@ llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
}
llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
+ if (usesSEHExceptions)
+ return CGM.getCXXABI().getAddrOfRTTIDescriptor(T);
+
if (!CGM.getLangOpts().CPlusPlus)
return CGObjCGNU::GetEHType(T);
@@ -3018,18 +3110,21 @@ llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
return ptr;
}
+llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(const
+ ObjCCategoryDecl *OCD) {
+ SmallVector<std::string, 16> Protocols;
+ for (const auto *PD : OCD->getReferencedProtocols())
+ Protocols.push_back(PD->getNameAsString());
+ return GenerateProtocolList(Protocols);
+}
+
void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
const ObjCInterfaceDecl *Class = OCD->getClassInterface();
std::string ClassName = Class->getNameAsString();
std::string CategoryName = OCD->getNameAsString();
// Collect the names of referenced protocols
- SmallVector<std::string, 16> Protocols;
const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl();
- const ObjCList<ObjCProtocolDecl> &Protos = CatDecl->getReferencedProtocols();
- for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
- E = Protos.end(); I != E; ++I)
- Protocols.push_back((*I)->getNameAsString());
ConstantInitBuilder Builder(CGM);
auto Elements = Builder.beginStruct();
@@ -3051,7 +3146,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
GenerateMethodList(ClassName, CategoryName, ClassMethods, true),
PtrTy);
// Protocol list
- Elements.addBitCast(GenerateProtocolList(Protocols), PtrTy);
+ Elements.addBitCast(GenerateCategoryProtocolList(CatDecl), PtrTy);
if (isRuntime(ObjCRuntime::GNUstep, 2)) {
const ObjCCategoryDecl *Category =
Class->FindCategoryDeclaration(OCD->getIdentifier());
@@ -3460,12 +3555,16 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
ConstantInitBuilder builder(CGM);
auto selectors = builder.beginArray(selStructTy);
auto &table = SelectorTable; // MSVC workaround
- for (auto &entry : table) {
+ std::vector<Selector> allSelectors;
+ for (auto &entry : table)
+ allSelectors.push_back(entry.first);
+ llvm::sort(allSelectors);
- std::string selNameStr = entry.first.getAsString();
+ for (auto &untypedSel : allSelectors) {
+ std::string selNameStr = untypedSel.getAsString();
llvm::Constant *selName = ExportUniqueString(selNameStr, ".objc_sel_name");
- for (TypedSelector &sel : entry.second) {
+ for (TypedSelector &sel : table[untypedSel]) {
llvm::Constant *selectorTypeEncoding = NULLPtr;
if (!sel.first.empty())
selectorTypeEncoding =
@@ -3726,6 +3825,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
const ObjCAtThrowStmt &S,
bool ClearInsertionPoint) {
llvm::Value *ExceptionAsObject;
+ bool isRethrow = false;
if (const Expr *ThrowExpr = S.getThrowExpr()) {
llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
@@ -3734,11 +3834,24 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
"Unexpected rethrow outside @catch block.");
ExceptionAsObject = CGF.ObjCEHValueStack.back();
+ isRethrow = true;
+ }
+ if (isRethrow && usesSEHExceptions) {
+ // For SEH, ExceptionAsObject may be undef, because the catch handler is
+ // not passed it for catchalls and so it is not visible to the catch
+ // funclet. The real thrown object will still be live on the stack at this
+ // point and will be rethrown. If we are explicitly rethrowing the object
+ // that was passed into the `@catch` block, then this code path is not
+ // reached and we will instead call `objc_exception_throw` with an explicit
+ // argument.
+ CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn).setDoesNotReturn();
+ }
+ else {
+ ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
+ llvm::CallSite Throw =
+ CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
+ Throw.setDoesNotReturn();
}
- ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
- llvm::CallSite Throw =
- CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
- Throw.setDoesNotReturn();
CGF.Builder.CreateUnreachable();
if (ClearInsertionPoint)
CGF.Builder.ClearInsertionPoint();
@@ -3812,40 +3925,10 @@ llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
// is. This allows code compiled with non-fragile ivars to work correctly
// when linked against code which isn't (most of the time).
llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
- if (!IvarOffsetPointer) {
- // This will cause a run-time crash if we accidentally use it. A value of
- // 0 would seem more sensible, but will silently overwrite the isa pointer
- // causing a great deal of confusion.
- uint64_t Offset = -1;
- // We can't call ComputeIvarBaseOffset() here if we have the
- // implementation, because it will create an invalid ASTRecordLayout object
- // that we are then stuck with forever, so we only initialize the ivar
- // offset variable with a guess if we only have the interface. The
- // initializer will be reset later anyway, when we are generating the class
- // description.
- if (!CGM.getContext().getObjCImplementation(
- const_cast<ObjCInterfaceDecl *>(ID)))
- Offset = ComputeIvarBaseOffset(CGM, ID, Ivar);
-
- llvm::ConstantInt *OffsetGuess = llvm::ConstantInt::get(Int32Ty, Offset,
- /*isSigned*/true);
- // Don't emit the guess in non-PIC code because the linker will not be able
- // to replace it with the real version for a library. In non-PIC code you
- // must compile with the fragile ABI if you want to use ivars from a
- // GCC-compiled class.
- if (CGM.getLangOpts().PICLevel) {
- llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
- Int32Ty, false,
- llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
- IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
- IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
- IvarOffsetGV, Name);
- } else {
- IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
- llvm::Type::getInt32PtrTy(VMContext), false,
- llvm::GlobalValue::ExternalLinkage, nullptr, Name);
- }
- }
+ if (!IvarOffsetPointer)
+ IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
+ llvm::Type::getInt32PtrTy(VMContext), false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, Name);
return IvarOffsetPointer;
}
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 2b54e7bd67af..d91eb43ca322 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -23,9 +23,9 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
@@ -37,6 +37,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
@@ -1085,9 +1086,14 @@ public:
const CGBlockInfo &blockInfo) override;
llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
const CGBlockInfo &blockInfo) override;
+ std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) override;
llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
QualType T) override;
+
+private:
+ void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo);
};
namespace {
@@ -2795,8 +2801,44 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
return getConstantGEP(VMContext, Entry, 0, 0);
}
-llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
- const CGBlockInfo &blockInfo) {
+static std::string getBlockLayoutInfoString(
+ const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars,
+ bool HasCopyDisposeHelpers) {
+ std::string Str;
+ for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
+ if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
+ // Copy/dispose helpers don't have any information about
+ // __unsafe_unretained captures, so unconditionally concatenate a string.
+ Str += "u";
+ } else if (HasCopyDisposeHelpers) {
+ // Information about __strong, __weak, or byref captures has already been
+ // encoded into the names of the copy/dispose helpers. We have to add a
+ // string here only when the copy/dispose helpers aren't generated (which
+ // happens when the block is non-escaping).
+ continue;
+ } else {
+ switch (R.opcode) {
+ case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
+ Str += "s";
+ break;
+ case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
+ Str += "r";
+ break;
+ case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
+ Str += "w";
+ break;
+ default:
+ continue;
+ }
+ }
+ Str += llvm::to_string(R.block_var_bytepos.getQuantity());
+ Str += "l" + llvm::to_string(R.block_var_size.getQuantity());
+ }
+ return Str;
+}
+
+void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
RunSkipBlockVars.clear();
@@ -2845,9 +2887,22 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
fieldOffset, fieldSize);
}
+}
+
+llvm::Constant *
+CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ fillRunSkipBlockVars(CGM, blockInfo);
return getBitmapBlockLayout(false);
}
+std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ fillRunSkipBlockVars(CGM, blockInfo);
+ return getBlockLayoutInfoString(RunSkipBlockVars,
+ blockInfo.needsCopyDisposeHelpers());
+}
+
llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
QualType T) {
assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
@@ -6783,8 +6838,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
return Entry;
// Use the protocol definition, if there is one.
- if (const ObjCProtocolDecl *Def = PD->getDefinition())
- PD = Def;
+ assert(PD->hasDefinition() &&
+ "emitting protocol metadata without definition");
+ PD = PD->getDefinition();
auto methodLists = ProtocolMethodLists::get(PD);
@@ -7132,15 +7188,21 @@ CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
Weak ? llvm::GlobalValue::ExternalWeakLinkage
: llvm::GlobalValue::ExternalLinkage;
-
-
llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
- if (!GV) {
- GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
- false, L, nullptr, Name);
+ if (!GV || GV->getType() != ObjCTypes.ClassnfABITy->getPointerTo()) {
+ auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
+ nullptr, Name);
if (DLLImport)
- GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+
+ if (GV) {
+ GV->replaceAllUsesWith(
+ llvm::ConstantExpr::getBitCast(NewGV, GV->getType()));
+ GV->eraseFromParent();
+ }
+ GV = NewGV;
+ CGM.getModule().getGlobalList().push_back(GV);
}
assert(GV->getLinkage() == L);
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index a43885c0f9a2..4b6f24a03f27 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -15,6 +15,7 @@
#include "CGObjCRuntime.h"
#include "CGCleanup.h"
+#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@@ -22,6 +23,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -120,6 +122,8 @@ namespace {
const Stmt *Body;
llvm::BasicBlock *Block;
llvm::Constant *TypeInfo;
+ /// Flags used to differentiate cleanups and catchalls in Windows SEH
+ unsigned Flags;
};
struct CallObjCEndCatch final : EHScopeStack::Cleanup {
@@ -148,13 +152,17 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
if (S.getNumCatchStmts())
Cont = CGF.getJumpDestInCurrentScope("eh.cont");
+ bool useFunclets = EHPersonality::get(CGF).usesFuncletPads();
+
CodeGenFunction::FinallyInfo FinallyInfo;
- if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
- FinallyInfo.enter(CGF, Finally->getFinallyBody(),
- beginCatchFn, endCatchFn, exceptionRethrowFn);
+ if (!useFunclets)
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
+ FinallyInfo.enter(CGF, Finally->getFinallyBody(),
+ beginCatchFn, endCatchFn, exceptionRethrowFn);
SmallVector<CatchHandler, 8> Handlers;
+
// Enter the catch, if there is one.
if (S.getNumCatchStmts()) {
for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
@@ -166,10 +174,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
Handler.Variable = CatchDecl;
Handler.Body = CatchStmt->getCatchBody();
Handler.Block = CGF.createBasicBlock("catch");
+ Handler.Flags = 0;
// @catch(...) always matches.
if (!CatchDecl) {
- Handler.TypeInfo = nullptr; // catch-all
+ auto catchAll = getCatchAllTypeInfo();
+ Handler.TypeInfo = catchAll.RTTI;
+ Handler.Flags = catchAll.Flags;
// Don't consider any other catches.
break;
}
@@ -179,9 +190,31 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
- Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
+ Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block);
}
+ if (useFunclets)
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) {
+ CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+ if (!CGF.CurSEHParent)
+ CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl);
+ // Outline the finally block.
+ const Stmt *FinallyBlock = Finally->getFinallyBody();
+ HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock);
+
+ // Emit the original filter expression, convert to i32, and return.
+ HelperCGF.EmitStmt(FinallyBlock);
+
+ HelperCGF.FinishFunction(FinallyBlock->getEndLoc());
+
+ llvm::Function *FinallyFunc = HelperCGF.CurFn;
+
+
+ // Push a cleanup for __finally blocks.
+ CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc);
+ }
+
+
// Emit the try body.
CGF.EmitStmt(S.getTryBody());
@@ -197,6 +230,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CatchHandler &Handler = Handlers[I];
CGF.EmitBlock(Handler.Block);
+ llvm::CatchPadInst *CPI = nullptr;
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad);
+ if (useFunclets)
+ if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) {
+ CGF.CurrentFuncletPad = CPI;
+ CPI->setOperand(2, CGF.getExceptionSlot().getPointer());
+ }
llvm::Value *RawExn = CGF.getExceptionFromSlot();
// Enter the catch.
@@ -223,6 +263,8 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CGF.EmitAutoVarDecl(*CatchParam);
EmitInitOfCatchParam(CGF, CastExn, CatchParam);
}
+ if (CPI)
+ CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
CGF.ObjCEHValueStack.push_back(Exn);
CGF.EmitStmt(Handler.Body);
@@ -232,13 +274,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
cleanups.ForceCleanup();
CGF.EmitBranchThroughCleanup(Cont);
- }
+ }
// Go back to the try-statement fallthrough.
CGF.Builder.restoreIP(SavedIP);
// Pop out of the finally.
- if (S.getFinallyStmt())
+ if (!useFunclets && S.getFinallyStmt())
FinallyInfo.exit(CGF);
if (Cont.isValid())
@@ -254,7 +296,7 @@ void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF,
switch (paramDecl->getType().getQualifiers().getObjCLifetime()) {
case Qualifiers::OCL_Strong:
exn = CGF.EmitARCRetainNonBlock(exn);
- // fallthrough
+ LLVM_FALLTHROUGH;
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
@@ -277,7 +319,7 @@ namespace {
: SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
+ CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg);
}
};
}
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index ce082a61eb5e..fa16c198adbc 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -17,6 +17,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H
#include "CGBuilder.h"
#include "CGCall.h"
+#include "CGCleanup.h"
#include "CGValue.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h" // Selector
@@ -141,6 +142,8 @@ public:
/// error to Sema.
virtual llvm::Constant *GetEHType(QualType T) = 0;
+ virtual CatchTypeInfo getCatchAllTypeInfo() { return { nullptr, 0 }; }
+
/// Generate a constant string object.
virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0;
@@ -275,6 +278,10 @@ public:
const CodeGen::CGBlockInfo &blockInfo) = 0;
virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
const CodeGen::CGBlockInfo &blockInfo) = 0;
+ virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ return {};
+ }
/// Returns an i8* which points to the byref layout information.
virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
diff --git a/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp
index 1da19a90c387..7f6f595dd5d1 100644
--- a/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -62,6 +62,11 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
case BuiltinType::OCLReserveID:
return llvm::PointerType::get(
llvm::StructType::create(Ctx, "opencl.reserve_id_t"), AddrSpc);
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id: \
+ return llvm::PointerType::get( \
+ llvm::StructType::create(Ctx, "opencl." #ExtType), AddrSpc);
+#include "clang/Basic/OpenCLExtensionTypes.def"
}
}
@@ -118,25 +123,6 @@ llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
}
-// Get the block literal from an expression derived from the block expression.
-// OpenCL v2.0 s6.12.5:
-// Block variable declarations are implicitly qualified with const. Therefore
-// all block variables must be initialized at declaration time and may not be
-// reassigned.
-static const BlockExpr *getBlockExpr(const Expr *E) {
- if (auto Cast = dyn_cast<CastExpr>(E)) {
- E = Cast->getSubExpr();
- }
- if (auto DR = dyn_cast<DeclRefExpr>(E)) {
- E = cast<VarDecl>(DR->getDecl())->getInit();
- }
- E = E->IgnoreImplicit();
- if (auto Cast = dyn_cast<CastExpr>(E)) {
- E = Cast->getSubExpr();
- }
- return cast<BlockExpr>(E);
-}
-
/// Record emitted llvm invoke function and llvm block literal for the
/// corresponding block expression.
void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,
@@ -151,15 +137,21 @@ void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E,
EnqueuedBlockMap[E].Kernel = nullptr;
}
-llvm::Function *CGOpenCLRuntime::getInvokeFunction(const Expr *E) {
- return EnqueuedBlockMap[getBlockExpr(E)].InvokeFunc;
-}
-
CGOpenCLRuntime::EnqueuedBlockInfo
CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
CGF.EmitScalarExpr(E);
- const BlockExpr *Block = getBlockExpr(E);
+ // The block literal may be assigned to a const variable. Chasing down
+ // to get the block literal.
+ if (auto DR = dyn_cast<DeclRefExpr>(E)) {
+ E = cast<VarDecl>(DR->getDecl())->getInit();
+ }
+ E = E->IgnoreImplicit();
+ if (auto Cast = dyn_cast<CastExpr>(E)) {
+ E = Cast->getSubExpr();
+ }
+ auto *Block = cast<BlockExpr>(E);
+
assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() &&
"Block expression not emitted");
diff --git a/lib/CodeGen/CGOpenCLRuntime.h b/lib/CodeGen/CGOpenCLRuntime.h
index a513340827a8..750721f1b80f 100644
--- a/lib/CodeGen/CGOpenCLRuntime.h
+++ b/lib/CodeGen/CGOpenCLRuntime.h
@@ -16,6 +16,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENCLRUNTIME_H
#define LLVM_CLANG_LIB_CODEGEN_CGOPENCLRUNTIME_H
+#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Type.h"
@@ -91,10 +92,6 @@ public:
/// \param Block block literal emitted for the block expression.
void recordBlockInfo(const BlockExpr *E, llvm::Function *InvokeF,
llvm::Value *Block);
-
- /// \return LLVM block invoke function emitted for an expression derived from
- /// the block expression.
- llvm::Function *getInvokeFunction(const Expr *E);
};
}
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index fa850155df4f..20eb0b29f427 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -353,7 +353,7 @@ public:
if (VD->isLocalVarDeclOrParm())
continue;
- DeclRefExpr DRE(const_cast<VarDecl *>(VD),
+ DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
/*RefersToEnclosingVariableOrCapture=*/false,
VD->getType().getNonReferenceType(), VK_LValue,
C.getLocation());
@@ -673,6 +673,9 @@ enum OpenMPRTLFunction {
//
// Offloading related calls
//
+ // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
+ // size);
+ OMPRTL__kmpc_push_target_tripcount,
// Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
// arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
// *arg_types);
@@ -897,25 +900,6 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
}
-static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
-isDeclareTargetDeclaration(const ValueDecl *VD) {
- for (const Decl *D : VD->redecls()) {
- if (!D->hasAttrs())
- continue;
- if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
- return Attr->getMapType();
- }
- if (const auto *V = dyn_cast<VarDecl>(VD)) {
- if (const VarDecl *TD = V->getTemplateInstantiationPattern())
- return isDeclareTargetDeclaration(TD);
- } else if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
- if (const auto *TD = FD->getTemplateInstantiationPattern())
- return isDeclareTargetDeclaration(TD);
- }
-
- return llvm::None;
-}
-
LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
return CGF.EmitOMPSharedLValue(E);
}
@@ -1242,6 +1226,17 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
void CGOpenMPRuntime::clear() {
InternalVars.clear();
+ // Clean non-target variable declarations possibly used only in debug info.
+ for (const auto &Data : EmittedNonTargetVariables) {
+ if (!Data.getValue().pointsToAliveValue())
+ continue;
+ auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
+ if (!GV)
+ continue;
+ if (!GV->isDeclaration() || GV->getNumUses() > 0)
+ continue;
+ GV->eraseFromParent();
+ }
}
std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
@@ -1314,27 +1309,19 @@ void CGOpenMPRuntime::emitUserDefinedReduction(
CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
if (UDRMap.count(D) > 0)
return;
- ASTContext &C = CGM.getContext();
- if (!In || !Out) {
- In = &C.Idents.get("omp_in");
- Out = &C.Idents.get("omp_out");
- }
llvm::Function *Combiner = emitCombinerOrInitializer(
- CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()),
- cast<VarDecl>(D->lookup(Out).front()),
+ CGM, D->getType(), D->getCombiner(),
+ cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
+ cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
/*IsCombiner=*/true);
llvm::Function *Initializer = nullptr;
if (const Expr *Init = D->getInitializer()) {
- if (!Priv || !Orig) {
- Priv = &C.Idents.get("omp_priv");
- Orig = &C.Idents.get("omp_orig");
- }
Initializer = emitCombinerOrInitializer(
CGM, D->getType(),
D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
: nullptr,
- cast<VarDecl>(D->lookup(Orig).front()),
- cast<VarDecl>(D->lookup(Priv).front()),
+ cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
+ cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
/*IsCombiner=*/false);
}
UDRMap.try_emplace(D, Combiner, Initializer);
@@ -1406,8 +1393,8 @@ llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
bool Tied, unsigned &NumberOfParts) {
auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
PrePostActionTy &) {
- llvm::Value *ThreadID = getThreadID(CGF, D.getLocStart());
- llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getLocStart());
+ llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
+ llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
llvm::Value *TaskArgs[] = {
UpLoc, ThreadID,
CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
@@ -1456,17 +1443,17 @@ static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
template <class... As>
static llvm::GlobalVariable *
-createConstantGlobalStruct(CodeGenModule &CGM, QualType Ty,
- ArrayRef<llvm::Constant *> Data, const Twine &Name,
- As &&... Args) {
+createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
+ ArrayRef<llvm::Constant *> Data, const Twine &Name,
+ As &&... Args) {
const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
ConstantInitBuilder CIBuilder(CGM);
ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
buildStructValue(Fields, CGM, RD, RL, Data);
return Fields.finishAndCreateGlobal(
- Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty),
- /*isConstant=*/true, std::forward<As>(Args)...);
+ Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
+ std::forward<As>(Args)...);
}
template <typename T>
@@ -1483,7 +1470,9 @@ createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
- llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
+ unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
+ FlagsTy FlagsKey(Flags, Reserved2Flags);
+ llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
if (!Entry) {
if (!DefaultOpenMPPSource) {
// Initialize default location for psource field of ident_t structure of
@@ -1496,21 +1485,47 @@ Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
}
- llvm::Constant *Data[] = {llvm::ConstantInt::getNullValue(CGM.Int32Ty),
- llvm::ConstantInt::get(CGM.Int32Ty, Flags),
- llvm::ConstantInt::getNullValue(CGM.Int32Ty),
- llvm::ConstantInt::getNullValue(CGM.Int32Ty),
- DefaultOpenMPPSource};
- llvm::GlobalValue *DefaultOpenMPLocation = createConstantGlobalStruct(
- CGM, IdentQTy, Data, "", llvm::GlobalValue::PrivateLinkage);
+ llvm::Constant *Data[] = {
+ llvm::ConstantInt::getNullValue(CGM.Int32Ty),
+ llvm::ConstantInt::get(CGM.Int32Ty, Flags),
+ llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
+ llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
+ llvm::GlobalValue *DefaultOpenMPLocation =
+ createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
+ llvm::GlobalValue::PrivateLinkage);
DefaultOpenMPLocation->setUnnamedAddr(
llvm::GlobalValue::UnnamedAddr::Global);
- OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
+ OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
}
return Address(Entry, Align);
}
+void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
+ bool AtCurrentPoint) {
+ auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
+ assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
+
+ llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
+ if (AtCurrentPoint) {
+ Elem.second.ServiceInsertPt = new llvm::BitCastInst(
+ Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
+ } else {
+ Elem.second.ServiceInsertPt =
+ new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
+ Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
+ }
+}
+
+void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
+ auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
+ if (Elem.second.ServiceInsertPt) {
+ llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
+ Elem.second.ServiceInsertPt = nullptr;
+ Ptr->eraseFromParent();
+ }
+}
+
llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
SourceLocation Loc,
unsigned Flags) {
@@ -1537,8 +1552,10 @@ llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
Elem.second.DebugLoc = AI.getPointer();
LocValue = AI;
+ if (!Elem.second.ServiceInsertPt)
+ setLocThreadIdInsertPt(CGF);
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
- CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
+ CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
CGF.getTypeSize(IdentQTy));
}
@@ -1608,21 +1625,25 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
// kmpc_global_thread_num(ident_t *loc).
// Generate thread id value and cache this value for use across the
// function.
+ auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
+ if (!Elem.second.ServiceInsertPt)
+ setLocThreadIdInsertPt(CGF);
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
- CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
+ CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
llvm::CallInst *Call = CGF.Builder.CreateCall(
createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
emitUpdateLocation(CGF, Loc));
Call->setCallingConv(CGF.getRuntimeCC());
- auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
Elem.second.ThreadID = Call;
return Call;
}
void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
assert(CGF.CurFn && "No function in current CodeGenFunction.");
- if (OpenMPLocThreadIDMap.count(CGF.CurFn))
+ if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
+ clearLocThreadIdInsertPt(CGF);
OpenMPLocThreadIDMap.erase(CGF.CurFn);
+ }
if (FunctionUDRMap.count(CGF.CurFn) > 0) {
for(auto *D : FunctionUDRMap[CGF.CurFn])
UDRMap.erase(D);
@@ -2145,6 +2166,15 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
break;
}
+ case OMPRTL__kmpc_push_target_tripcount: {
+ // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
+ // size);
+ llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
+ break;
+ }
case OMPRTL__tgt_target: {
// Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
// arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
@@ -2417,7 +2447,7 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) {
if (CGM.getLangOpts().OpenMPSimd)
return Address::invalid();
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD);
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
SmallString<64> PtrName;
{
@@ -2496,8 +2526,7 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
return nullptr;
VD = VD->getDefinition(CGM.getContext());
- if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
- ThreadPrivateWithDefinition.insert(VD);
+ if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
QualType ASTTy = VD->getType();
llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
@@ -2639,16 +2668,16 @@ bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
llvm::GlobalVariable *Addr,
bool PerformInit) {
Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD);
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link)
- return false;
+ return CGM.getLangOpts().OpenMPIsDevice;
VD = VD->getDefinition(CGM.getContext());
- if (VD && !DeclareTargetWithDefinition.insert(VD).second)
+ if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
return CGM.getLangOpts().OpenMPIsDevice;
QualType ASTTy = VD->getType();
- SourceLocation Loc = VD->getCanonicalDecl()->getLocStart();
+ SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
// Produce the unique prefix to identify the new target regions. We use
// the source location of the variable declaration which we know to not
// conflict with any target region.
@@ -3197,13 +3226,7 @@ void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
}
-void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPDirectiveKind Kind, bool EmitChecks,
- bool ForceSimpleCall) {
- if (!CGF.HaveInsertPoint())
- return;
- // Build call __kmpc_cancel_barrier(loc, thread_id);
- // Build call __kmpc_barrier(loc, thread_id);
+unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
unsigned Flags;
if (Kind == OMPD_for)
Flags = OMP_IDENT_BARRIER_IMPL_FOR;
@@ -3215,6 +3238,17 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Flags = OMP_IDENT_BARRIER_EXPL;
else
Flags = OMP_IDENT_BARRIER_IMPL;
+ return Flags;
+}
+
+void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind Kind, bool EmitChecks,
+ bool ForceSimpleCall) {
+ if (!CGF.HaveInsertPoint())
+ return;
+ // Build call __kmpc_cancel_barrier(loc, thread_id);
+ // Build call __kmpc_barrier(loc, thread_id);
+ unsigned Flags = getDefaultFlagsForBarriers(Kind);
// Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
// thread_id);
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
@@ -3287,6 +3321,18 @@ bool CGOpenMPRuntime::isStaticNonchunked(
return Schedule == OMP_dist_sch_static;
}
+bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
+ bool Chunked) const {
+ OpenMPSchedType Schedule =
+ getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
+ return Schedule == OMP_sch_static_chunked;
+}
+
+bool CGOpenMPRuntime::isStaticChunked(
+ OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
+ OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
+ return Schedule == OMP_dist_sch_static_chunked;
+}
bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
OpenMPSchedType Schedule =
@@ -3784,8 +3830,8 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
DeviceImages, Index),
HostEntriesBegin, HostEntriesEnd};
std::string Descriptor = getName({"omp_offloading", "descriptor"});
- llvm::GlobalVariable *Desc = createConstantGlobalStruct(
- CGM, getTgtBinaryDescriptorQTy(), Data, Descriptor);
+ llvm::GlobalVariable *Desc = createGlobalStruct(
+ CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor);
// Emit code to register or unregister the descriptor at execution
// startup or closing, respectively.
@@ -3818,7 +3864,19 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
CGF.disableDebugInfo();
const auto &FI = CGM.getTypes().arrangeNullaryFunction();
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
- std::string Descriptor = getName({"omp_offloading", "descriptor_reg"});
+
+ // Encode offload target triples into the registration function name. It
+ // will serve as a comdat key for the registration/unregistration code for
+ // this particular combination of offloading targets.
+ SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U);
+ RegFnNameParts[0] = "omp_offloading";
+ RegFnNameParts[1] = "descriptor_reg";
+ llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2),
+ [](const llvm::Triple &T) -> const std::string& {
+ return T.getTriple();
+ });
+ llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end());
+ std::string Descriptor = getName(RegFnNameParts);
RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI);
CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
@@ -3868,9 +3926,9 @@ void CGOpenMPRuntime::createOffloadEntry(
llvm::ConstantInt::get(CGM.Int32Ty, Flags),
llvm::ConstantInt::get(CGM.Int32Ty, 0)};
std::string EntryName = getName({"omp_offloading", "entry", ""});
- llvm::GlobalVariable *Entry = createConstantGlobalStruct(
- CGM, getTgtOffloadEntryQTy(), Data, Twine(EntryName).concat(Name),
- llvm::GlobalValue::WeakAnyLinkage);
+ llvm::GlobalVariable *Entry = createGlobalStruct(
+ CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
+ Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
// The entry has to be created in the section the linker expects it to be.
std::string Section = getName({"omp_offloading", "entries"});
@@ -3895,6 +3953,8 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
llvm::LLVMContext &C = M.getContext();
SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
OrderedEntries(OffloadEntriesInfoManager.size());
+ llvm::SmallVector<StringRef, 16> ParentFunctions(
+ OffloadEntriesInfoManager.size());
// Auxiliary methods to create metadata values and strings.
auto &&GetMDInt = [this](unsigned V) {
@@ -3909,7 +3969,7 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
// Create function that emits metadata for each target region entry;
auto &&TargetRegionMetadataEmitter =
- [&C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
+ [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString](
unsigned DeviceID, unsigned FileID, StringRef ParentName,
unsigned Line,
const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
@@ -3929,6 +3989,7 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
// Save this entry in the right position of the ordered entries array.
OrderedEntries[E.getOrder()] = &E;
+ ParentFunctions[E.getOrder()] = ParentName;
// Add metadata to the named metadata node.
MD->addOperand(llvm::MDNode::get(C, Ops));
@@ -3970,6 +4031,10 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
E)) {
if (!CE->getID() || !CE->getAddress()) {
+ // Do not blame the entry if the parent funtion is not emitted.
+ StringRef FnName = ParentFunctions[CE->getOrder()];
+ if (!CGM.GetGlobalValue(FnName))
+ continue;
unsigned DiagID = CGM.getDiags().getCustomDiagID(
DiagnosticsEngine::Error,
"Offloading entry for target region is incorrect: either the "
@@ -3995,6 +4060,9 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
CGM.getDiags().Report(DiagID);
continue;
}
+ // The vaiable has no definition - no need to add the entry.
+ if (CE->getVarSize().isZero())
+ continue;
break;
}
case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
@@ -5226,8 +5294,8 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
LBLVal.getPointer(),
UBLVal.getPointer(),
CGF.EmitLoadOfScalar(StLVal, Loc),
- llvm::ConstantInt::getNullValue(
- CGF.IntTy), // Always 0 because taskgroup emitted by the compiler
+ llvm::ConstantInt::getSigned(
+ CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
llvm::ConstantInt::getSigned(
CGF.IntTy, Data.Schedule.getPointer()
? Data.Schedule.getInt() ? NumTasks : Grainsize
@@ -5776,7 +5844,7 @@ static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
std::string Name = CGM.getOpenMPRuntime().getName(
{D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
Out << Prefix << Name << "_"
- << D->getCanonicalDecl()->getLocStart().getRawEncoding();
+ << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
return Out.str();
}
@@ -6274,7 +6342,7 @@ void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
unsigned DeviceID;
unsigned FileID;
unsigned Line;
- getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
+ getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Line);
SmallString<64> EntryFnName;
{
@@ -6589,17 +6657,17 @@ private:
struct MapInfo {
OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
- OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
bool ReturnDevicePointer = false;
bool IsImplicit = false;
MapInfo() = default;
MapInfo(
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
- OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType,
+ ArrayRef<OpenMPMapModifierKind> MapModifiers,
bool ReturnDevicePointer, bool IsImplicit)
- : Components(Components), MapType(MapType),
- MapTypeModifier(MapTypeModifier),
+ : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
};
@@ -6676,10 +6744,9 @@ private:
/// a flag marking the map as a pointer if requested. Add a flag marking the
/// map as the first one of a series of maps that relate to the same map
/// expression.
- OpenMPOffloadMappingFlags getMapTypeBits(OpenMPMapClauseKind MapType,
- OpenMPMapClauseKind MapTypeModifier,
- bool IsImplicit, bool AddPtrFlag,
- bool AddIsTargetParamFlag) const {
+ OpenMPOffloadMappingFlags getMapTypeBits(
+ OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
+ bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
OpenMPOffloadMappingFlags Bits =
IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
switch (MapType) {
@@ -6702,7 +6769,6 @@ private:
case OMPC_MAP_delete:
Bits |= OMP_MAP_DELETE;
break;
- case OMPC_MAP_always:
case OMPC_MAP_unknown:
llvm_unreachable("Unexpected map type!");
}
@@ -6710,7 +6776,8 @@ private:
Bits |= OMP_MAP_PTR_AND_OBJ;
if (AddIsTargetParamFlag)
Bits |= OMP_MAP_TARGET_PARAM;
- if (MapTypeModifier == OMPC_MAP_always)
+ if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
+ != MapModifiers.end())
Bits |= OMP_MAP_ALWAYS;
return Bits;
}
@@ -6746,10 +6813,11 @@ private:
}
// Check if the length evaluates to 1.
- llvm::APSInt ConstLength;
- if (!Length->EvaluateAsInt(ConstLength, CGF.getContext()))
+ Expr::EvalResult Result;
+ if (!Length->EvaluateAsInt(Result, CGF.getContext()))
return true; // Can have more that size 1.
+ llvm::APSInt ConstLength = Result.Val.getInt();
return ConstLength.getSExtValue() != 1;
}
@@ -6758,12 +6826,15 @@ private:
/// \a IsFirstComponent should be set to true if the provided set of
/// components is the first associated with a capture.
void generateInfoForComponentList(
- OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType,
+ ArrayRef<OpenMPMapModifierKind> MapModifiers,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
- bool IsImplicit) const {
+ bool IsImplicit,
+ ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
+ OverlappedElements = llvm::None) const {
// The following summarizes what has to be generated for each map and the
// types below. The generated information is expressed in this order:
// base pointer, section pointer, size, flags
@@ -6933,19 +7004,26 @@ private:
// components.
bool IsExpressionFirstInfo = true;
Address BP = Address::invalid();
+ const Expr *AssocExpr = I->getAssociatedExpression();
+ const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
- if (isa<MemberExpr>(I->getAssociatedExpression())) {
+ if (isa<MemberExpr>(AssocExpr)) {
// The base is the 'this' pointer. The content of the pointer is going
// to be the base of the field being mapped.
BP = CGF.LoadCXXThisAddress();
+ } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
+ (OASE &&
+ isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
+ BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
} else {
// The base is the reference to the variable.
// BP = &Var.
- BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
+ BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
if (const auto *VD =
dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD))
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
if (*Res == OMPDeclareTargetDeclAttr::MT_Link) {
IsLink = true;
BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
@@ -7034,7 +7112,6 @@ private:
Address LB =
CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
- llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
// If this component is a pointer inside the base struct then we don't
// need to create any entry for it - it will be combined with the object
@@ -7043,6 +7120,70 @@ private:
IsPointer && EncounteredME &&
(dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
EncounteredME);
+ if (!OverlappedElements.empty()) {
+ // Handle base element with the info for overlapped elements.
+ assert(!PartialStruct.Base.isValid() && "The base element is set.");
+ assert(Next == CE &&
+ "Expected last element for the overlapped elements.");
+ assert(!IsPointer &&
+ "Unexpected base element with the pointer type.");
+ // Mark the whole struct as the struct that requires allocation on the
+ // device.
+ PartialStruct.LowestElem = {0, LB};
+ CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
+ I->getAssociatedExpression()->getType());
+ Address HB = CGF.Builder.CreateConstGEP(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
+ CGF.VoidPtrTy),
+ TypeSize.getQuantity() - 1, CharUnits::One());
+ PartialStruct.HighestElem = {
+ std::numeric_limits<decltype(
+ PartialStruct.HighestElem.first)>::max(),
+ HB};
+ PartialStruct.Base = BP;
+ // Emit data for non-overlapped data.
+ OpenMPOffloadMappingFlags Flags =
+ OMP_MAP_MEMBER_OF |
+ getMapTypeBits(MapType, MapModifiers, IsImplicit,
+ /*AddPtrFlag=*/false,
+ /*AddIsTargetParamFlag=*/false);
+ LB = BP;
+ llvm::Value *Size = nullptr;
+ // Do bitcopy of all non-overlapped structure elements.
+ for (OMPClauseMappableExprCommon::MappableExprComponentListRef
+ Component : OverlappedElements) {
+ Address ComponentLB = Address::invalid();
+ for (const OMPClauseMappableExprCommon::MappableComponent &MC :
+ Component) {
+ if (MC.getAssociatedDeclaration()) {
+ ComponentLB =
+ CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
+ .getAddress();
+ Size = CGF.Builder.CreatePtrDiff(
+ CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
+ CGF.EmitCastToVoidPtr(LB.getPointer()));
+ break;
+ }
+ }
+ BasePointers.push_back(BP.getPointer());
+ Pointers.push_back(LB.getPointer());
+ Sizes.push_back(Size);
+ Types.push_back(Flags);
+ LB = CGF.Builder.CreateConstGEP(ComponentLB, 1,
+ CGF.getPointerSize());
+ }
+ BasePointers.push_back(BP.getPointer());
+ Pointers.push_back(LB.getPointer());
+ Size = CGF.Builder.CreatePtrDiff(
+ CGF.EmitCastToVoidPtr(
+ CGF.Builder.CreateConstGEP(HB, 1, CharUnits::One())
+ .getPointer()),
+ CGF.EmitCastToVoidPtr(LB.getPointer()));
+ Sizes.push_back(Size);
+ Types.push_back(Flags);
+ break;
+ }
+ llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
if (!IsMemberPointer) {
BasePointers.push_back(BP.getPointer());
Pointers.push_back(LB.getPointer());
@@ -7053,7 +7194,7 @@ private:
// this map is the first one that relates with the current capture
// (there is a set of entries for each capture).
OpenMPOffloadMappingFlags Flags = getMapTypeBits(
- MapType, MapTypeModifier, IsImplicit,
+ MapType, MapModifiers, IsImplicit,
!IsExpressionFirstInfo || IsLink, IsCaptureFirstInfo && !IsLink);
if (!IsExpressionFirstInfo) {
@@ -7147,6 +7288,66 @@ private:
Flags |= MemberOfFlag;
}
+ void getPlainLayout(const CXXRecordDecl *RD,
+ llvm::SmallVectorImpl<const FieldDecl *> &Layout,
+ bool AsBase) const {
+ const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
+
+ llvm::StructType *St =
+ AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
+
+ unsigned NumElements = St->getNumElements();
+ llvm::SmallVector<
+ llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
+ RecordLayout(NumElements);
+
+ // Fill bases.
+ for (const auto &I : RD->bases()) {
+ if (I.isVirtual())
+ continue;
+ const auto *Base = I.getType()->getAsCXXRecordDecl();
+ // Ignore empty bases.
+ if (Base->isEmpty() || CGF.getContext()
+ .getASTRecordLayout(Base)
+ .getNonVirtualSize()
+ .isZero())
+ continue;
+
+ unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
+ RecordLayout[FieldIndex] = Base;
+ }
+ // Fill in virtual bases.
+ for (const auto &I : RD->vbases()) {
+ const auto *Base = I.getType()->getAsCXXRecordDecl();
+ // Ignore empty bases.
+ if (Base->isEmpty())
+ continue;
+ unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
+ if (RecordLayout[FieldIndex])
+ continue;
+ RecordLayout[FieldIndex] = Base;
+ }
+ // Fill in all the fields.
+ assert(!RD->isUnion() && "Unexpected union.");
+ for (const auto *Field : RD->fields()) {
+ // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
+ // will fill in later.)
+ if (!Field->isBitField()) {
+ unsigned FieldIndex = RL.getLLVMFieldNo(Field);
+ RecordLayout[FieldIndex] = Field;
+ }
+ }
+ for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
+ &Data : RecordLayout) {
+ if (Data.isNull())
+ continue;
+ if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
+ getPlainLayout(Base, Layout, /*AsBase=*/true);
+ else
+ Layout.push_back(Data.get<const FieldDecl *>());
+ }
+ }
+
public:
MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
: CurDir(Dir), CGF(CGF) {
@@ -7213,28 +7414,29 @@ public:
auto &&InfoGen = [&Info](
const ValueDecl *D,
OMPClauseMappableExprCommon::MappableExprComponentListRef L,
- OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier,
+ OpenMPMapClauseKind MapType,
+ ArrayRef<OpenMPMapModifierKind> MapModifiers,
bool ReturnDevicePointer, bool IsImplicit) {
const ValueDecl *VD =
D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- Info[VD].emplace_back(L, MapType, MapModifier, ReturnDevicePointer,
+ Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
IsImplicit);
};
// FIXME: MSVC 2013 seems to require this-> to find member CurDir.
for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
for (const auto &L : C->component_lists()) {
- InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(),
+ InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
/*ReturnDevicePointer=*/false, C->isImplicit());
}
for (const auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
for (const auto &L : C->component_lists()) {
- InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown,
+ InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
/*ReturnDevicePointer=*/false, C->isImplicit());
}
for (const auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
for (const auto &L : C->component_lists()) {
- InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown,
+ InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
/*ReturnDevicePointer=*/false, C->isImplicit());
}
@@ -7287,7 +7489,7 @@ public:
// Nonetheless, generateInfoForComponentList must be called to take
// the pointer into account for the calculation of the range of the
// partial struct.
- InfoGen(nullptr, L.second, OMPC_MAP_unknown, OMPC_MAP_unknown,
+ InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
/*ReturnDevicePointer=*/false, C->isImplicit());
DeferredInfo[nullptr].emplace_back(IE, VD);
} else {
@@ -7321,7 +7523,7 @@ public:
unsigned CurrentBasePointersIdx = CurBasePointers.size();
// FIXME: MSVC 2013 seems to require this-> to find the member method.
this->generateInfoForComponentList(
- L.MapType, L.MapTypeModifier, L.Components, CurBasePointers,
+ L.MapType, L.MapModifiers, L.Components, CurBasePointers,
CurPointers, CurSizes, CurTypes, PartialStruct,
IsFirstComponentList, L.IsImplicit);
@@ -7375,6 +7577,82 @@ public:
}
}
+ /// Emit capture info for lambdas for variables captured by reference.
+ void generateInfoForLambdaCaptures(
+ const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
+ MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
+ MapFlagsArrayTy &Types,
+ llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
+ const auto *RD = VD->getType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ ->getAsCXXRecordDecl();
+ if (!RD || !RD->isLambda())
+ return;
+ Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
+ LValue VDLVal = CGF.MakeAddrLValue(
+ VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
+ llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
+ FieldDecl *ThisCapture = nullptr;
+ RD->getCaptureFields(Captures, ThisCapture);
+ if (ThisCapture) {
+ LValue ThisLVal =
+ CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
+ LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
+ LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
+ BasePointers.push_back(ThisLVal.getPointer());
+ Pointers.push_back(ThisLValVal.getPointer());
+ Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
+ Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
+ OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
+ }
+ for (const LambdaCapture &LC : RD->captures()) {
+ if (LC.getCaptureKind() != LCK_ByRef)
+ continue;
+ const VarDecl *VD = LC.getCapturedVar();
+ auto It = Captures.find(VD);
+ assert(It != Captures.end() && "Found lambda capture without field.");
+ LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
+ LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
+ LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
+ BasePointers.push_back(VarLVal.getPointer());
+ Pointers.push_back(VarLValVal.getPointer());
+ Sizes.push_back(CGF.getTypeSize(
+ VD->getType().getCanonicalType().getNonReferenceType()));
+ Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
+ OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
+ }
+ }
+
+ /// Set correct indices for lambdas captures.
+ void adjustMemberOfForLambdaCaptures(
+ const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
+ MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
+ MapFlagsArrayTy &Types) const {
+ for (unsigned I = 0, E = Types.size(); I < E; ++I) {
+ // Set correct member_of idx for all implicit lambda captures.
+ if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
+ OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
+ continue;
+ llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
+ assert(BasePtr && "Unable to find base lambda address.");
+ int TgtIdx = -1;
+ for (unsigned J = I; J > 0; --J) {
+ unsigned Idx = J - 1;
+ if (Pointers[Idx] != BasePtr)
+ continue;
+ TgtIdx = Idx;
+ break;
+ }
+ assert(TgtIdx != -1 && "Unable to find parent lambda.");
+ // All other current entries will be MEMBER_OF the combined entry
+ // (except for PTR_AND_OBJ entries which do not have a placeholder value
+ // 0xFFFF in the MEMBER_OF field).
+ OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
+ setCorrectMemberOfFlag(Types[I], MemberOfFlag);
+ }
+ }
+
/// Generate the base pointers, section pointers, sizes and map types
/// associated to a given capture.
void generateInfoForCapture(const CapturedStmt::Capture *Cap,
@@ -7387,9 +7665,6 @@ public:
"Not expecting to generate map info for a variable array type!");
// We need to know when we generating information for the first component
- // associated with a capture, because the mapping flags depend on it.
- bool IsFirstComponentList = true;
-
const ValueDecl *VD = Cap->capturesThis()
? nullptr
: Cap->getCapturedVar()->getCanonicalDecl();
@@ -7405,19 +7680,151 @@ public:
return;
}
+ using MapData =
+ std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
+ SmallVector<MapData, 4> DeclComponentLists;
// FIXME: MSVC 2013 seems to require this-> to find member CurDir.
- for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
+ for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
for (const auto &L : C->decl_component_lists(VD)) {
assert(L.first == VD &&
"We got information for the wrong declaration??");
assert(!L.second.empty() &&
"Not expecting declaration with no component lists.");
- generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(),
- L.second, BasePointers, Pointers, Sizes,
- Types, PartialStruct, IsFirstComponentList,
- C->isImplicit());
- IsFirstComponentList = false;
+ DeclComponentLists.emplace_back(L.second, C->getMapType(),
+ C->getMapTypeModifiers(),
+ C->isImplicit());
+ }
+ }
+
+ // Find overlapping elements (including the offset from the base element).
+ llvm::SmallDenseMap<
+ const MapData *,
+ llvm::SmallVector<
+ OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
+ 4>
+ OverlappedData;
+ size_t Count = 0;
+ for (const MapData &L : DeclComponentLists) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
+ bool IsImplicit;
+ std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
+ ++Count;
+ for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
+ std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
+ auto CI = Components.rbegin();
+ auto CE = Components.rend();
+ auto SI = Components1.rbegin();
+ auto SE = Components1.rend();
+ for (; CI != CE && SI != SE; ++CI, ++SI) {
+ if (CI->getAssociatedExpression()->getStmtClass() !=
+ SI->getAssociatedExpression()->getStmtClass())
+ break;
+ // Are we dealing with different variables/fields?
+ if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
+ break;
+ }
+ // Found overlapping if, at least for one component, reached the head of
+ // the components list.
+ if (CI == CE || SI == SE) {
+ assert((CI != CE || SI != SE) &&
+ "Unexpected full match of the mapping components.");
+ const MapData &BaseData = CI == CE ? L : L1;
+ OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
+ SI == SE ? Components : Components1;
+ auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
+ OverlappedElements.getSecond().push_back(SubData);
+ }
}
+ }
+ // Sort the overlapped elements for each item.
+ llvm::SmallVector<const FieldDecl *, 4> Layout;
+ if (!OverlappedData.empty()) {
+ if (const auto *CRD =
+ VD->getType().getCanonicalType()->getAsCXXRecordDecl())
+ getPlainLayout(CRD, Layout, /*AsBase=*/false);
+ else {
+ const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
+ Layout.append(RD->field_begin(), RD->field_end());
+ }
+ }
+ for (auto &Pair : OverlappedData) {
+ llvm::sort(
+ Pair.getSecond(),
+ [&Layout](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef First,
+ OMPClauseMappableExprCommon::MappableExprComponentListRef
+ Second) {
+ auto CI = First.rbegin();
+ auto CE = First.rend();
+ auto SI = Second.rbegin();
+ auto SE = Second.rend();
+ for (; CI != CE && SI != SE; ++CI, ++SI) {
+ if (CI->getAssociatedExpression()->getStmtClass() !=
+ SI->getAssociatedExpression()->getStmtClass())
+ break;
+ // Are we dealing with different variables/fields?
+ if (CI->getAssociatedDeclaration() !=
+ SI->getAssociatedDeclaration())
+ break;
+ }
+
+ // Lists contain the same elements.
+ if (CI == CE && SI == SE)
+ return false;
+
+ // List with less elements is less than list with more elements.
+ if (CI == CE || SI == SE)
+ return CI == CE;
+
+ const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
+ const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
+ if (FD1->getParent() == FD2->getParent())
+ return FD1->getFieldIndex() < FD2->getFieldIndex();
+ const auto It =
+ llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
+ return FD == FD1 || FD == FD2;
+ });
+ return *It == FD1;
+ });
+ }
+
+ // Associated with a capture, because the mapping flags depend on it.
+ // Go through all of the elements with the overlapped elements.
+ for (const auto &Pair : OverlappedData) {
+ const MapData &L = *Pair.getFirst();
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
+ bool IsImplicit;
+ std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
+ ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
+ OverlappedComponents = Pair.getSecond();
+ bool IsFirstComponentList = true;
+ generateInfoForComponentList(MapType, MapModifiers, Components,
+ BasePointers, Pointers, Sizes, Types,
+ PartialStruct, IsFirstComponentList,
+ IsImplicit, OverlappedComponents);
+ }
+ // Go through other elements without overlapped elements.
+ bool IsFirstComponentList = OverlappedData.empty();
+ for (const MapData &L : DeclComponentLists) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
+ bool IsImplicit;
+ std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
+ auto It = OverlappedData.find(&L);
+ if (It == OverlappedData.end())
+ generateInfoForComponentList(MapType, MapModifiers, Components,
+ BasePointers, Pointers, Sizes, Types,
+ PartialStruct, IsFirstComponentList,
+ IsImplicit);
+ IsFirstComponentList = false;
+ }
}
/// Generate the base pointers, section pointers, sizes and map types
@@ -7436,12 +7843,12 @@ public:
if (!VD)
continue;
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD);
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
continue;
StructRangeInfoTy PartialStruct;
generateInfoForComponentList(
- C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers,
+ C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Pointers, Sizes, Types, PartialStruct,
/*IsFirstComponentList=*/true, C->isImplicit());
assert(!PartialStruct.Base.isValid() &&
@@ -7658,6 +8065,183 @@ static void emitOffloadingArraysArgument(
}
}
+/// Checks if the expression is constant or does not have non-trivial function
+/// calls.
+static bool isTrivial(ASTContext &Ctx, const Expr * E) {
+ // We can skip constant expressions.
+ // We can skip expressions with trivial calls or simple expressions.
+ return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
+ !E->hasNonTrivialCall(Ctx)) &&
+ !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
+}
+
+/// Checks if the \p Body is the \a CompoundStmt and returns its child statement
+/// iff there is only one that is not evaluatable at the compile time.
+static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body) {
+ if (const auto *C = dyn_cast<CompoundStmt>(Body)) {
+ const Stmt *Child = nullptr;
+ for (const Stmt *S : C->body()) {
+ if (const auto *E = dyn_cast<Expr>(S)) {
+ if (isTrivial(Ctx, E))
+ continue;
+ }
+ // Some of the statements can be ignored.
+ if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
+ isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
+ continue;
+ // Analyze declarations.
+ if (const auto *DS = dyn_cast<DeclStmt>(S)) {
+ if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
+ if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
+ isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
+ isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
+ isa<UsingDirectiveDecl>(D) ||
+ isa<OMPDeclareReductionDecl>(D) ||
+ isa<OMPThreadPrivateDecl>(D))
+ return true;
+ const auto *VD = dyn_cast<VarDecl>(D);
+ if (!VD)
+ return false;
+ return VD->isConstexpr() ||
+ ((VD->getType().isTrivialType(Ctx) ||
+ VD->getType()->isReferenceType()) &&
+ (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
+ }))
+ continue;
+ }
+ // Found multiple children - cannot get the one child only.
+ if (Child)
+ return Body;
+ Child = S;
+ }
+ if (Child)
+ return Child;
+ }
+ return Body;
+}
+
+/// Check for inner distribute directive.
+static const OMPExecutableDirective *
+getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
+ const auto *CS = D.getInnermostCapturedStmt();
+ const auto *Body =
+ CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
+ const Stmt *ChildStmt = getSingleCompoundChild(Ctx, Body);
+
+ if (const auto *NestedDir = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
+ switch (D.getDirectiveKind()) {
+ case OMPD_target:
+ if (isOpenMPDistributeDirective(DKind))
+ return NestedDir;
+ if (DKind == OMPD_teams) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
+ /*IgnoreCaptured=*/true);
+ if (!Body)
+ return nullptr;
+ ChildStmt = getSingleCompoundChild(Ctx, Body);
+ if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ DKind = NND->getDirectiveKind();
+ if (isOpenMPDistributeDirective(DKind))
+ return NND;
+ }
+ }
+ return nullptr;
+ case OMPD_target_teams:
+ if (isOpenMPDistributeDirective(DKind))
+ return NestedDir;
+ return nullptr;
+ case OMPD_target_parallel:
+ case OMPD_target_simd:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ return nullptr;
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_enter_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_update:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_requires:
+ case OMPD_unknown:
+ llvm_unreachable("Unexpected directive.");
+ }
+ }
+
+ return nullptr;
+}
+
+void CGOpenMPRuntime::emitTargetNumIterationsCall(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device,
+ const llvm::function_ref<llvm::Value *(
+ CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter) {
+ OpenMPDirectiveKind Kind = D.getDirectiveKind();
+ const OMPExecutableDirective *TD = &D;
+ // Get nested teams distribute kind directive, if any.
+ if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
+ TD = getNestedDistributeDirective(CGM.getContext(), D);
+ if (!TD)
+ return;
+ const auto *LD = cast<OMPLoopDirective>(TD);
+ auto &&CodeGen = [LD, &Device, &SizeEmitter, this](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ llvm::Value *NumIterations = SizeEmitter(CGF, *LD);
+
+ // Emit device ID if any.
+ llvm::Value *DeviceID;
+ if (Device)
+ DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
+ CGF.Int64Ty, /*isSigned=*/true);
+ else
+ DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
+
+ llvm::Value *Args[] = {DeviceID, NumIterations};
+ CGF.EmitRuntimeCall(
+ createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
+ };
+ emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
+}
+
void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
const OMPExecutableDirective &D,
llvm::Value *OutlinedFn,
@@ -7790,7 +8374,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
CapturedVars.clear();
CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
}
- emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn, CapturedVars);
+ emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
CGF.EmitBranch(OffloadContBlock);
CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
@@ -7804,7 +8388,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
CapturedVars.clear();
CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
}
- emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedFn, CapturedVars);
+ emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
};
auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
@@ -7818,6 +8402,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
// Get mappable expression information.
MappableExprsHandler MEHandler(D, CGF);
+ llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
auto RI = CS.getCapturedRecordDecl()->field_begin();
auto CV = CapturedVars.begin();
@@ -7847,6 +8432,12 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
if (CurBasePointers.empty())
MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
CurPointers, CurSizes, CurMapTypes);
+ // Generate correct mapping for variables captured by reference in
+ // lambdas.
+ if (CI->capturesVariable())
+ MEHandler.generateInfoForLambdaCaptures(
+ CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
+ CurMapTypes, LambdaPointers);
}
// We expect to have at least an element of information for this capture.
assert(!CurBasePointers.empty() &&
@@ -7868,6 +8459,9 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
Sizes.append(CurSizes.begin(), CurSizes.end());
MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
}
+ // Adjust MEMBER_OF flags for the lambdas captures.
+ MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
+ Pointers, MapTypes);
// Map other list items in the map clause which are not captured variables
// but "declare target link" global variables.
MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
@@ -7935,7 +8529,7 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
unsigned DeviceID;
unsigned FileID;
unsigned Line;
- getTargetEntryUniqueInfo(CGM.getContext(), E.getLocStart(), DeviceID,
+ getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
FileID, Line);
// Is this a target region that should not be emitted as an entry point? If
@@ -8030,6 +8624,7 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
case OMPD_declare_reduction:
case OMPD_taskloop:
case OMPD_taskloop_simd:
+ case OMPD_requires:
case OMPD_unknown:
llvm_unreachable("Unknown target directive for OpenMP device codegen.");
}
@@ -8055,19 +8650,20 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
}
bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
- const auto *FD = cast<FunctionDecl>(GD.getDecl());
-
// If emitting code for the host, we do not process FD here. Instead we do
// the normal code generation.
if (!CGM.getLangOpts().OpenMPIsDevice)
return false;
+ const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
+ StringRef Name = CGM.getMangledName(GD);
// Try to detect target regions in the function.
- scanForTargetRegionsFunctions(FD->getBody(), CGM.getMangledName(GD));
+ if (const auto *FD = dyn_cast<FunctionDecl>(VD))
+ scanForTargetRegionsFunctions(FD->getBody(), Name);
// Do not to emit function if it is not marked as declare target.
- return !isDeclareTargetDeclaration(FD) &&
- AlreadyEmittedTargetFunctions.count(FD->getCanonicalDecl()) == 0;
+ return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
+ AlreadyEmittedTargetFunctions.count(Name) == 0;
}
bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
@@ -8093,64 +8689,105 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
// Do not to emit variable if it is not marked as declare target.
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(cast<VarDecl>(GD.getDecl()));
- return !Res || *Res == OMPDeclareTargetDeclAttr::MT_Link;
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
+ cast<VarDecl>(GD.getDecl()));
+ if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) {
+ DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
+ return true;
+ }
+ return false;
}
void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
llvm::Constant *Addr) {
- if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD)) {
- OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
- StringRef VarName;
- CharUnits VarSize;
- llvm::GlobalValue::LinkageTypes Linkage;
- switch (*Res) {
- case OMPDeclareTargetDeclAttr::MT_To:
- Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
- VarName = CGM.getMangledName(VD);
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (!Res) {
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ // Register non-target variables being emitted in device code (debug info
+ // may cause this).
+ StringRef VarName = CGM.getMangledName(VD);
+ EmittedNonTargetVariables.try_emplace(VarName, Addr);
+ }
+ return;
+ }
+ // Register declare target variables.
+ OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
+ StringRef VarName;
+ CharUnits VarSize;
+ llvm::GlobalValue::LinkageTypes Linkage;
+ switch (*Res) {
+ case OMPDeclareTargetDeclAttr::MT_To:
+ Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
+ VarName = CGM.getMangledName(VD);
+ if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
- Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
- // Temp solution to prevent optimizations of the internal variables.
- if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
- std::string RefName = getName({VarName, "ref"});
- if (!CGM.GetGlobalValue(RefName)) {
- llvm::Constant *AddrRef =
- getOrCreateInternalVariable(Addr->getType(), RefName);
- auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
- GVAddrRef->setConstant(/*Val=*/true);
- GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
- GVAddrRef->setInitializer(Addr);
- CGM.addCompilerUsedGlobal(GVAddrRef);
- }
- }
- break;
- case OMPDeclareTargetDeclAttr::MT_Link:
- Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
- if (CGM.getLangOpts().OpenMPIsDevice) {
- VarName = Addr->getName();
- Addr = nullptr;
- } else {
- VarName = getAddrOfDeclareTargetLink(VD).getName();
- Addr =
- cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer());
+ assert(!VarSize.isZero() && "Expected non-zero size of the variable");
+ } else {
+ VarSize = CharUnits::Zero();
+ }
+ Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
+ // Temp solution to prevent optimizations of the internal variables.
+ if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
+ std::string RefName = getName({VarName, "ref"});
+ if (!CGM.GetGlobalValue(RefName)) {
+ llvm::Constant *AddrRef =
+ getOrCreateInternalVariable(Addr->getType(), RefName);
+ auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
+ GVAddrRef->setConstant(/*Val=*/true);
+ GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
+ GVAddrRef->setInitializer(Addr);
+ CGM.addCompilerUsedGlobal(GVAddrRef);
}
- VarSize = CGM.getPointerSize();
- Linkage = llvm::GlobalValue::WeakAnyLinkage;
- break;
}
- OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
- VarName, Addr, VarSize, Flags, Linkage);
+ break;
+ case OMPDeclareTargetDeclAttr::MT_Link:
+ Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ VarName = Addr->getName();
+ Addr = nullptr;
+ } else {
+ VarName = getAddrOfDeclareTargetLink(VD).getName();
+ Addr = cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer());
+ }
+ VarSize = CGM.getPointerSize();
+ Linkage = llvm::GlobalValue::WeakAnyLinkage;
+ break;
}
+ OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
+ VarName, Addr, VarSize, Flags, Linkage);
}
bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
- if (isa<FunctionDecl>(GD.getDecl()))
+ if (isa<FunctionDecl>(GD.getDecl()) ||
+ isa<OMPDeclareReductionDecl>(GD.getDecl()))
return emitTargetFunctions(GD);
return emitTargetGlobalVariable(GD);
}
+void CGOpenMPRuntime::emitDeferredTargetDecls() const {
+ for (const VarDecl *VD : DeferredGlobalVariables) {
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
+ if (!Res)
+ continue;
+ if (*Res == OMPDeclareTargetDeclAttr::MT_To) {
+ CGM.EmitGlobal(VD);
+ } else {
+ assert(*Res == OMPDeclareTargetDeclAttr::MT_Link &&
+ "Expected to or link clauses.");
+ (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
+ }
+ }
+}
+
+void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
+ assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
+ " Expected target-based directive.");
+}
+
CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
CodeGenModule &CGM)
: CGM(CGM) {
@@ -8169,21 +8806,20 @@ bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
return true;
+ StringRef Name = CGM.getMangledName(GD);
const auto *D = cast<FunctionDecl>(GD.getDecl());
- const FunctionDecl *FD = D->getCanonicalDecl();
// Do not to emit function if it is marked as declare target as it was already
// emitted.
- if (isDeclareTargetDeclaration(D)) {
- if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) {
- if (auto *F = dyn_cast_or_null<llvm::Function>(
- CGM.GetGlobalValue(CGM.getMangledName(GD))))
+ if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
+ if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
+ if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
return !F->isDeclaration();
return false;
}
return true;
}
- return !AlreadyEmittedTargetFunctions.insert(FD).second;
+ return !AlreadyEmittedTargetFunctions.insert(Name).second;
}
llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
@@ -8478,6 +9114,7 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
case OMPD_target_parallel:
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
+ case OMPD_requires:
case OMPD_unknown:
llvm_unreachable("Unexpected standalone target data directive.");
break;
@@ -8730,8 +9367,8 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
ParamAttrTy &ParamAttr = ParamAttrs[Pos];
ParamAttr.Kind = Linear;
if (*SI) {
- if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C,
- Expr::SE_AllowSideEffects)) {
+ Expr::EvalResult Result;
+ if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
if (const auto *DRE =
cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
@@ -8740,6 +9377,8 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
ParamPositions[StridePVD->getCanonicalDecl()]);
}
}
+ } else {
+ ParamAttr.StrideOrArg = Result.Val.getInt();
}
}
++SI;
@@ -8782,7 +9421,8 @@ public:
} // namespace
void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) {
+ const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) {
if (!CGF.HaveInsertPoint())
return;
@@ -8805,37 +9445,50 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
} else {
RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
}
+ llvm::APInt Size(/*numBits=*/32, NumIterations.size());
+ QualType ArrayTy =
+ C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
- Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims");
- CGF.EmitNullInitialization(DimsAddr, KmpDimTy);
+ Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
+ CGF.EmitNullInitialization(DimsAddr, ArrayTy);
enum { LowerFD = 0, UpperFD, StrideFD };
// Fill dims with data.
- LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy);
- // dims.upper = num_iterations;
- LValue UpperLVal =
- CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD));
- llvm::Value *NumIterVal = CGF.EmitScalarConversion(
- CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(),
- Int64Ty, D.getNumIterations()->getExprLoc());
- CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
- // dims.stride = 1;
- LValue StrideLVal =
- CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD));
- CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
- StrideLVal);
+ for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
+ LValue DimsLVal =
+ CGF.MakeAddrLValue(CGF.Builder.CreateConstArrayGEP(
+ DimsAddr, I, C.getTypeSizeInChars(KmpDimTy)),
+ KmpDimTy);
+ // dims.upper = num_iterations;
+ LValue UpperLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), UpperFD));
+ llvm::Value *NumIterVal =
+ CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
+ D.getNumIterations()->getType(), Int64Ty,
+ D.getNumIterations()->getExprLoc());
+ CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
+ // dims.stride = 1;
+ LValue StrideLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), StrideFD));
+ CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
+ StrideLVal);
+ }
// Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
// kmp_int32 num_dims, struct kmp_dim * dims);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()),
- getThreadID(CGF, D.getLocStart()),
- llvm::ConstantInt::getSigned(CGM.Int32Ty, 1),
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- DimsAddr.getPointer(), CGM.VoidPtrTy)};
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, D.getBeginLoc()),
+ getThreadID(CGF, D.getBeginLoc()),
+ llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder
+ .CreateConstArrayGEP(DimsAddr, 0, C.getTypeSizeInChars(KmpDimTy))
+ .getPointer(),
+ CGM.VoidPtrTy)};
llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init);
CGF.EmitRuntimeCall(RTLFn, Args);
llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
- emitUpdateLocation(CGF, D.getLocEnd()), getThreadID(CGF, D.getLocEnd())};
+ emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
llvm::Value *FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
llvm::makeArrayRef(FiniArgs));
@@ -8845,16 +9498,29 @@ void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
const OMPDependClause *C) {
QualType Int64Ty =
CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
- const Expr *CounterVal = C->getCounterValue();
- assert(CounterVal);
- llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal),
- CounterVal->getType(), Int64Ty,
- CounterVal->getExprLoc());
- Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr");
- CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()),
- getThreadID(CGF, C->getLocStart()),
- CntAddr.getPointer()};
+ llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
+ QualType ArrayTy = CGM.getContext().getConstantArrayType(
+ Int64Ty, Size, ArrayType::Normal, 0);
+ Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
+ const Expr *CounterVal = C->getLoopData(I);
+ assert(CounterVal);
+ llvm::Value *CntVal = CGF.EmitScalarConversion(
+ CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
+ CounterVal->getExprLoc());
+ CGF.EmitStoreOfScalar(
+ CntVal,
+ CGF.Builder.CreateConstArrayGEP(
+ CntAddr, I, CGM.getContext().getTypeSizeInChars(Int64Ty)),
+ /*Volatile=*/false, Int64Ty);
+ }
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, C->getBeginLoc()),
+ getThreadID(CGF, C->getBeginLoc()),
+ CGF.Builder
+ .CreateConstArrayGEP(CntAddr, 0,
+ CGM.getContext().getTypeSizeInChars(Int64Ty))
+ .getPointer()};
llvm::Value *RTLFn;
if (C->getDependencyKind() == OMPC_DEPEND_source) {
RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
@@ -9169,7 +9835,8 @@ void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
}
void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) {
+ const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) {
llvm_unreachable("Not supported in SIMD-only mode");
}
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 01ff0c20fd66..1822a6fd1974 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -15,12 +15,13 @@
#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
#include "CGValue.h"
+#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/Type.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/ValueHandle.h"
@@ -278,12 +279,39 @@ protected:
/// stored.
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
+ void setLocThreadIdInsertPt(CodeGenFunction &CGF,
+ bool AtCurrentPoint = false);
+ void clearLocThreadIdInsertPt(CodeGenFunction &CGF);
+
+ /// Check if the default location must be constant.
+ /// Default is false to support OMPT/OMPD.
+ virtual bool isDefaultLocationConstant() const { return false; }
+
+ /// Returns additional flags that can be stored in reserved_2 field of the
+ /// default location.
+ virtual unsigned getDefaultLocationReserved2Flags() const { return 0; }
+
+ /// Returns default flags for the barriers depending on the directive, for
+ /// which this barier is going to be emitted.
+ static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind);
+
+ /// Get the LLVM type for the critical name.
+ llvm::ArrayType *getKmpCriticalNameTy() const {return KmpCriticalNameTy;}
+
+ /// Returns corresponding lock object for the specified critical region
+ /// name. If the lock object does not exist it is created, otherwise the
+ /// reference to the existing copy is returned.
+ /// \param CriticalName Name of the critical region.
+ ///
+ llvm::Value *getCriticalRegionLock(StringRef CriticalName);
+
private:
/// Default const ident_t object used for initialization of all other
/// ident_t objects.
llvm::Constant *DefaultOpenMPPSource = nullptr;
+ using FlagsTy = std::pair<unsigned, unsigned>;
/// Map of flags and corresponding default locations.
- typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
+ using OpenMPDefaultLocMapTy = llvm::DenseMap<FlagsTy, llvm::Value *>;
OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
Address getOrCreateDefaultLocation(unsigned Flags);
@@ -300,6 +328,8 @@ private:
struct DebugLocThreadIdTy {
llvm::Value *DebugLoc;
llvm::Value *ThreadID;
+ /// Insert point for the service instructions.
+ llvm::AssertingVH<llvm::Instruction> ServiceInsertPt = nullptr;
};
/// Map of local debug location, ThreadId and functions.
typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy>
@@ -315,10 +345,6 @@ private:
SmallVector<const OMPDeclareReductionDecl *, 4>>
FunctionUDRMapTy;
FunctionUDRMapTy FunctionUDRMap;
- IdentifierInfo *In = nullptr;
- IdentifierInfo *Out = nullptr;
- IdentifierInfo *Priv = nullptr;
- IdentifierInfo *Orig = nullptr;
/// Type kmp_critical_name, originally defined as typedef kmp_int32
/// kmp_critical_name[8];
llvm::ArrayType *KmpCriticalNameTy;
@@ -600,7 +626,15 @@ private:
OffloadEntriesInfoManagerTy OffloadEntriesInfoManager;
bool ShouldMarkAsGlobal = true;
- llvm::SmallDenseSet<const FunctionDecl *> AlreadyEmittedTargetFunctions;
+ /// List of the emitted functions.
+ llvm::StringSet<> AlreadyEmittedTargetFunctions;
+ /// List of the global variables with their addresses that should not be
+ /// emitted for the target.
+ llvm::StringMap<llvm::WeakTrackingVH> EmittedNonTargetVariables;
+
+ /// List of variables that can become declare target implicitly and, thus,
+ /// must be emitted.
+ llvm::SmallDenseSet<const VarDecl *> DeferredGlobalVariables;
/// Creates and registers offloading binary descriptor for the current
/// compilation unit. The function that does the registration is returned.
@@ -673,10 +707,10 @@ private:
const llvm::Twine &Name);
/// Set of threadprivate variables with the generated initializer.
- llvm::SmallPtrSet<const VarDecl *, 4> ThreadPrivateWithDefinition;
+ llvm::StringSet<> ThreadPrivateWithDefinition;
/// Set of declare target variables with the generated initializer.
- llvm::SmallPtrSet<const VarDecl *, 4> DeclareTargetWithDefinition;
+ llvm::StringSet<> DeclareTargetWithDefinition;
/// Emits initialization code for the threadprivate variables.
/// \param VDAddr Address of the global variable \a VD.
@@ -688,13 +722,6 @@ private:
llvm::Value *Ctor, llvm::Value *CopyCtor,
llvm::Value *Dtor, SourceLocation Loc);
- /// Returns corresponding lock object for the specified critical region
- /// name. If the lock object does not exist it is created, otherwise the
- /// reference to the existing copy is returned.
- /// \param CriticalName Name of the critical region.
- ///
- llvm::Value *getCriticalRegionLock(StringRef CriticalName);
-
struct TaskResultTy {
llvm::Value *NewTask = nullptr;
llvm::Value *TaskEntry = nullptr;
@@ -884,6 +911,20 @@ public:
virtual bool isStaticNonchunked(OpenMPDistScheduleClauseKind ScheduleKind,
bool Chunked) const;
+ /// Check if the specified \a ScheduleKind is static chunked.
+ /// \param ScheduleKind Schedule kind specified in the 'schedule' clause.
+ /// \param Chunked True if chunk is specified in the clause.
+ ///
+ virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
+ bool Chunked) const;
+
+ /// Check if the specified \a ScheduleKind is static non-chunked.
+ /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause.
+ /// \param Chunked True if chunk is specified in the clause.
+ ///
+ virtual bool isStaticChunked(OpenMPDistScheduleClauseKind ScheduleKind,
+ bool Chunked) const;
+
/// Check if the specified \a ScheduleKind is dynamic.
/// This kind of worksharing directive is emitted without outer loop.
/// \param ScheduleKind Schedule Kind specified in the 'schedule' clause.
@@ -1327,6 +1368,15 @@ public:
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen);
+ /// Emit code that pushes the trip count of loops associated with constructs
+ /// 'target teams distribute' and 'teams distribute parallel for'.
+ /// \param SizeEmitter Emits the int64 value for the number of iterations of
+ /// the associated loop.
+ virtual void emitTargetNumIterationsCall(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device,
+ const llvm::function_ref<llvm::Value *(
+ CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter);
+
/// Emit the target offloading code associated with \a D. The emitted
/// code attempts offloading the execution to the device, an the event of
/// a failure it executes the host version outlined in \a OutlinedFn.
@@ -1465,8 +1515,8 @@ public:
/// Emit initialization for doacross loop nesting support.
/// \param D Loop-based construct used in doacross nesting construct.
- virtual void emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D);
+ virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations);
/// Emit code for doacross ordered directive with 'depend' clause.
/// \param C 'depend' clause with 'sink|source' dependency kind.
@@ -1490,6 +1540,18 @@ public:
const VarDecl *NativeParam,
const VarDecl *TargetParam) const;
+ /// Choose default schedule type and chunk value for the
+ /// dist_schedule clause.
+ virtual void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF,
+ const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind,
+ llvm::Value *&Chunk) const {}
+
+ /// Choose default schedule type and chunk value for the
+ /// schedule clause.
+ virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF,
+ const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind,
+ const Expr *&ChunkExpr) const {}
+
/// Emits call of the outlined function with the provided arguments,
/// translating these arguments to correct target-specific arguments.
virtual void
@@ -1505,10 +1567,23 @@ public:
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF,
const VarDecl *VD);
- /// Marks the declaration as alread emitted for the device code and returns
+ /// Marks the declaration as already emitted for the device code and returns
/// true, if it was marked already, and false, otherwise.
bool markAsGlobalTarget(GlobalDecl GD);
+ /// Emit deferred declare target variables marked for deferred emission.
+ void emitDeferredTargetDecls() const;
+
+ /// Adjust some parameters for the target-based directives, like addresses of
+ /// the variables captured by reference in lambdas.
+ virtual void
+ adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D) const;
+
+ /// Perform check on requires decl to ensure that target architecture
+ /// supports unified addressing
+ virtual void checkArchForUnifiedAddressing(CodeGenModule &CGM,
+ const OMPRequiresDecl *D) const {}
};
/// Class supports emissionof SIMD-only code.
@@ -2051,8 +2126,8 @@ public:
/// Emit initialization for doacross loop nesting support.
/// \param D Loop-based construct used in doacross nesting construct.
- void emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) override;
+ void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) override;
/// Emit code for doacross ordered directive with 'depend' clause.
/// \param C 'depend' clause with 'sink|source' dependency kind.
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 036b5371fe0b..7046ab3aa35c 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/Cuda.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace clang;
@@ -32,8 +33,8 @@ enum OpenMPRTLFunctionNVPTX {
/// Call to void __kmpc_spmd_kernel_init(kmp_int32 thread_limit,
/// int16_t RequiresOMPRuntime, int16_t RequiresDataSharing);
OMPRTL_NVPTX__kmpc_spmd_kernel_init,
- /// Call to void __kmpc_spmd_kernel_deinit();
- OMPRTL_NVPTX__kmpc_spmd_kernel_deinit,
+ /// Call to void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime);
+ OMPRTL_NVPTX__kmpc_spmd_kernel_deinit_v2,
/// Call to void __kmpc_kernel_prepare_parallel(void
/// *outlined_function, int16_t
/// IsOMPRuntimeInitialized);
@@ -55,37 +56,27 @@ enum OpenMPRTLFunctionNVPTX {
/// Call to int64_t __kmpc_shuffle_int64(int64_t element,
/// int16_t lane_offset, int16_t warp_size);
OMPRTL_NVPTX__kmpc_shuffle_int64,
- /// Call to __kmpc_nvptx_parallel_reduce_nowait(kmp_int32
+ /// Call to __kmpc_nvptx_parallel_reduce_nowait_v2(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_vars, size_t reduce_size, void* reduce_data,
/// void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
/// lane_offset, int16_t shortCircuit),
/// void (*kmp_InterWarpCopyFctPtr)(void* src, int32_t warp_num));
- OMPRTL_NVPTX__kmpc_parallel_reduce_nowait,
- /// Call to __kmpc_nvptx_simd_reduce_nowait(kmp_int32
- /// global_tid, kmp_int32 num_vars, size_t reduce_size, void* reduce_data,
- /// void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
- /// lane_offset, int16_t shortCircuit),
- /// void (*kmp_InterWarpCopyFctPtr)(void* src, int32_t warp_num));
- OMPRTL_NVPTX__kmpc_simd_reduce_nowait,
- /// Call to __kmpc_nvptx_teams_reduce_nowait(int32_t global_tid,
- /// int32_t num_vars, size_t reduce_size, void *reduce_data,
- /// void (*kmp_ShuffleReductFctPtr)(void *rhs, int16_t lane_id, int16_t
- /// lane_offset, int16_t shortCircuit),
- /// void (*kmp_InterWarpCopyFctPtr)(void* src, int32_t warp_num),
- /// void (*kmp_CopyToScratchpadFctPtr)(void *reduce_data, void * scratchpad,
- /// int32_t index, int32_t width),
- /// void (*kmp_LoadReduceFctPtr)(void *reduce_data, void * scratchpad, int32_t
- /// index, int32_t width, int32_t reduce))
- OMPRTL_NVPTX__kmpc_teams_reduce_nowait,
+ OMPRTL_NVPTX__kmpc_parallel_reduce_nowait_v2,
+ /// Call to __kmpc_nvptx_teams_reduce_nowait_simple(ident_t *loc, kmp_int32
+ /// global_tid, kmp_critical_name *lck)
+ OMPRTL_NVPTX__kmpc_nvptx_teams_reduce_nowait_simple,
+ /// Call to __kmpc_nvptx_teams_end_reduce_nowait_simple(ident_t *loc,
+ /// kmp_int32 global_tid, kmp_critical_name *lck)
+ OMPRTL_NVPTX__kmpc_nvptx_teams_end_reduce_nowait_simple,
/// Call to __kmpc_nvptx_end_reduce_nowait(int32_t global_tid);
OMPRTL_NVPTX__kmpc_end_reduce_nowait,
/// Call to void __kmpc_data_sharing_init_stack();
OMPRTL_NVPTX__kmpc_data_sharing_init_stack,
/// Call to void __kmpc_data_sharing_init_stack_spmd();
OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd,
- /// Call to void* __kmpc_data_sharing_push_stack(size_t size,
+ /// Call to void* __kmpc_data_sharing_coalesced_push_stack(size_t size,
/// int16_t UseSharedMemory);
- OMPRTL_NVPTX__kmpc_data_sharing_push_stack,
+ OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack,
/// Call to void __kmpc_data_sharing_pop_stack(void *a);
OMPRTL_NVPTX__kmpc_data_sharing_pop_stack,
/// Call to void __kmpc_begin_sharing_variables(void ***args,
@@ -100,6 +91,17 @@ enum OpenMPRTLFunctionNVPTX {
OMPRTL_NVPTX__kmpc_parallel_level,
/// Call to int8_t __kmpc_is_spmd_exec_mode();
OMPRTL_NVPTX__kmpc_is_spmd_exec_mode,
+ /// Call to void __kmpc_get_team_static_memory(int16_t isSPMDExecutionMode,
+ /// const void *buf, size_t size, int16_t is_shared, const void **res);
+ OMPRTL_NVPTX__kmpc_get_team_static_memory,
+ /// Call to void __kmpc_restore_team_static_memory(int16_t
+ /// isSPMDExecutionMode, int16_t is_shared);
+ OMPRTL_NVPTX__kmpc_restore_team_static_memory,
+ /// Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
+ OMPRTL__kmpc_barrier,
+ /// Call to void __kmpc_barrier_simple_spmd(ident_t *loc, kmp_int32
+ /// global_tid);
+ OMPRTL__kmpc_barrier_simple_spmd,
};
/// Pre(post)-action for different OpenMP constructs specialized for NVPTX.
@@ -142,19 +144,35 @@ public:
/// a target region. The appropriate mode (SPMD|NON-SPMD) is set on entry
/// to the target region and used by containing directives such as 'parallel'
/// to emit optimized code.
-class ExecutionModeRAII {
+class ExecutionRuntimeModesRAII {
private:
- CGOpenMPRuntimeNVPTX::ExecutionMode SavedMode;
- CGOpenMPRuntimeNVPTX::ExecutionMode &Mode;
+ CGOpenMPRuntimeNVPTX::ExecutionMode SavedExecMode =
+ CGOpenMPRuntimeNVPTX::EM_Unknown;
+ CGOpenMPRuntimeNVPTX::ExecutionMode &ExecMode;
+ bool SavedRuntimeMode = false;
+ bool *RuntimeMode = nullptr;
public:
- ExecutionModeRAII(CGOpenMPRuntimeNVPTX::ExecutionMode &Mode, bool IsSPMD)
- : Mode(Mode) {
- SavedMode = Mode;
- Mode = IsSPMD ? CGOpenMPRuntimeNVPTX::EM_SPMD
- : CGOpenMPRuntimeNVPTX::EM_NonSPMD;
+ /// Constructor for Non-SPMD mode.
+ ExecutionRuntimeModesRAII(CGOpenMPRuntimeNVPTX::ExecutionMode &ExecMode)
+ : ExecMode(ExecMode) {
+ SavedExecMode = ExecMode;
+ ExecMode = CGOpenMPRuntimeNVPTX::EM_NonSPMD;
+ }
+ /// Constructor for SPMD mode.
+ ExecutionRuntimeModesRAII(CGOpenMPRuntimeNVPTX::ExecutionMode &ExecMode,
+ bool &RuntimeMode, bool FullRuntimeMode)
+ : ExecMode(ExecMode), RuntimeMode(&RuntimeMode) {
+ SavedExecMode = ExecMode;
+ SavedRuntimeMode = RuntimeMode;
+ ExecMode = CGOpenMPRuntimeNVPTX::EM_SPMD;
+ RuntimeMode = FullRuntimeMode;
+ }
+ ~ExecutionRuntimeModesRAII() {
+ ExecMode = SavedExecMode;
+ if (RuntimeMode)
+ *RuntimeMode = SavedRuntimeMode;
}
- ~ExecutionModeRAII() { Mode = SavedMode; }
};
/// GPU Configuration: This information can be derived from cuda registers,
@@ -169,16 +187,113 @@ enum MachineConfiguration : unsigned {
LaneIDMask = WarpSize - 1,
/// Global memory alignment for performance.
- GlobalMemoryAlignment = 256,
-};
+ GlobalMemoryAlignment = 128,
-enum NamedBarrier : unsigned {
- /// Synchronize on this barrier #ID using a named barrier primitive.
- /// Only the subset of active threads in a parallel region arrive at the
- /// barrier.
- NB_Parallel = 1,
+ /// Maximal size of the shared memory buffer.
+ SharedMemorySize = 128,
};
+static const ValueDecl *getPrivateItem(const Expr *RefExpr) {
+ RefExpr = RefExpr->IgnoreParens();
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr)) {
+ const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
+ while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ RefExpr = Base;
+ } else if (auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr)) {
+ const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
+ while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
+ Base = TempOASE->getBase()->IgnoreParenImpCasts();
+ while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ RefExpr = Base;
+ }
+ RefExpr = RefExpr->IgnoreParenImpCasts();
+ if (const auto *DE = dyn_cast<DeclRefExpr>(RefExpr))
+ return cast<ValueDecl>(DE->getDecl()->getCanonicalDecl());
+ const auto *ME = cast<MemberExpr>(RefExpr);
+ return cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl());
+}
+
+typedef std::pair<CharUnits /*Align*/, const ValueDecl *> VarsDataTy;
+static bool stable_sort_comparator(const VarsDataTy P1, const VarsDataTy P2) {
+ return P1.first > P2.first;
+}
+
+static RecordDecl *buildRecordForGlobalizedVars(
+ ASTContext &C, ArrayRef<const ValueDecl *> EscapedDecls,
+ ArrayRef<const ValueDecl *> EscapedDeclsForTeams,
+ llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
+ &MappedDeclsFields) {
+ if (EscapedDecls.empty() && EscapedDeclsForTeams.empty())
+ return nullptr;
+ SmallVector<VarsDataTy, 4> GlobalizedVars;
+ for (const ValueDecl *D : EscapedDecls)
+ GlobalizedVars.emplace_back(
+ CharUnits::fromQuantity(std::max(
+ C.getDeclAlign(D).getQuantity(),
+ static_cast<CharUnits::QuantityType>(GlobalMemoryAlignment))),
+ D);
+ for (const ValueDecl *D : EscapedDeclsForTeams)
+ GlobalizedVars.emplace_back(C.getDeclAlign(D), D);
+ std::stable_sort(GlobalizedVars.begin(), GlobalizedVars.end(),
+ stable_sort_comparator);
+ // Build struct _globalized_locals_ty {
+ // /* globalized vars */[WarSize] align (max(decl_align,
+ // GlobalMemoryAlignment))
+ // /* globalized vars */ for EscapedDeclsForTeams
+ // };
+ RecordDecl *GlobalizedRD = C.buildImplicitRecord("_globalized_locals_ty");
+ GlobalizedRD->startDefinition();
+ llvm::SmallPtrSet<const ValueDecl *, 16> SingleEscaped(
+ EscapedDeclsForTeams.begin(), EscapedDeclsForTeams.end());
+ for (const auto &Pair : GlobalizedVars) {
+ const ValueDecl *VD = Pair.second;
+ QualType Type = VD->getType();
+ if (Type->isLValueReferenceType())
+ Type = C.getPointerType(Type.getNonReferenceType());
+ else
+ Type = Type.getNonReferenceType();
+ SourceLocation Loc = VD->getLocation();
+ FieldDecl *Field;
+ if (SingleEscaped.count(VD)) {
+ Field = FieldDecl::Create(
+ C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type,
+ C.getTrivialTypeSourceInfo(Type, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ if (VD->hasAttrs()) {
+ for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
+ E(VD->getAttrs().end());
+ I != E; ++I)
+ Field->addAttr(*I);
+ }
+ } else {
+ llvm::APInt ArraySize(32, WarpSize);
+ Type = C.getConstantArrayType(Type, ArraySize, ArrayType::Normal, 0);
+ Field = FieldDecl::Create(
+ C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type,
+ C.getTrivialTypeSourceInfo(Type, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ llvm::APInt Align(32, std::max(C.getDeclAlign(VD).getQuantity(),
+ static_cast<CharUnits::QuantityType>(
+ GlobalMemoryAlignment)));
+ Field->addAttr(AlignedAttr::CreateImplicit(
+ C, AlignedAttr::GNU_aligned, /*IsAlignmentExpr=*/true,
+ IntegerLiteral::Create(C, Align,
+ C.getIntTypeForBitwidth(32, /*Signed=*/0),
+ SourceLocation())));
+ }
+ GlobalizedRD->addDecl(Field);
+ MappedDeclsFields.try_emplace(VD, Field);
+ }
+ GlobalizedRD->completeDefinition();
+ return GlobalizedRD;
+}
+
/// Get the list of variables that can escape their declaration context.
class CheckVarsEscapingDeclContext final
: public ConstStmtVisitor<CheckVarsEscapingDeclContext> {
@@ -191,20 +306,10 @@ class CheckVarsEscapingDeclContext final
bool AllEscaped = false;
bool IsForCombinedParallelRegion = false;
- static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
- isDeclareTargetDeclaration(const ValueDecl *VD) {
- for (const Decl *D : VD->redecls()) {
- if (!D->hasAttrs())
- continue;
- if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
- return Attr->getMapType();
- }
- return llvm::None;
- }
-
void markAsEscaped(const ValueDecl *VD) {
// Do not globalize declare target variables.
- if (!isa<VarDecl>(VD) || isDeclareTargetDeclaration(VD))
+ if (!isa<VarDecl>(VD) ||
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
return;
VD = cast<ValueDecl>(VD->getCanonicalDecl());
// Variables captured by value must be globalized.
@@ -218,9 +323,11 @@ class CheckVarsEscapingDeclContext final
const auto *Attr = FD->getAttr<OMPCaptureKindAttr>();
if (!Attr)
return;
- if (!isOpenMPPrivate(
- static_cast<OpenMPClauseKind>(Attr->getCaptureKind())) ||
- Attr->getCaptureKind() == OMPC_map)
+ if (((Attr->getCaptureKind() != OMPC_map) &&
+ !isOpenMPPrivate(
+ static_cast<OpenMPClauseKind>(Attr->getCaptureKind()))) ||
+ ((Attr->getCaptureKind() == OMPC_map) &&
+ !FD->getType()->isAnyPointerType()))
return;
}
if (!FD->getType()->isReferenceType()) {
@@ -302,55 +409,24 @@ class CheckVarsEscapingDeclContext final
}
}
- typedef std::pair<CharUnits /*Align*/, const ValueDecl *> VarsDataTy;
- static bool stable_sort_comparator(const VarsDataTy P1, const VarsDataTy P2) {
- return P1.first > P2.first;
- }
-
- void buildRecordForGlobalizedVars() {
+ void buildRecordForGlobalizedVars(bool IsInTTDRegion) {
assert(!GlobalizedRD &&
"Record for globalized variables is built already.");
- if (EscapedDecls.empty())
- return;
- ASTContext &C = CGF.getContext();
- SmallVector<VarsDataTy, 4> GlobalizedVars;
- for (const ValueDecl *D : EscapedDecls)
- GlobalizedVars.emplace_back(C.getDeclAlign(D), D);
- std::stable_sort(GlobalizedVars.begin(), GlobalizedVars.end(),
- stable_sort_comparator);
- // Build struct _globalized_locals_ty {
- // /* globalized vars */
- // };
- GlobalizedRD = C.buildImplicitRecord("_globalized_locals_ty");
- GlobalizedRD->startDefinition();
- for (const auto &Pair : GlobalizedVars) {
- const ValueDecl *VD = Pair.second;
- QualType Type = VD->getType();
- if (Type->isLValueReferenceType())
- Type = C.getPointerType(Type.getNonReferenceType());
- else
- Type = Type.getNonReferenceType();
- SourceLocation Loc = VD->getLocation();
- auto *Field = FieldDecl::Create(
- C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type,
- C.getTrivialTypeSourceInfo(Type, SourceLocation()),
- /*BW=*/nullptr, /*Mutable=*/false,
- /*InitStyle=*/ICIS_NoInit);
- Field->setAccess(AS_public);
- GlobalizedRD->addDecl(Field);
- if (VD->hasAttrs()) {
- for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
- E(VD->getAttrs().end());
- I != E; ++I)
- Field->addAttr(*I);
- }
- MappedDeclsFields.try_emplace(VD, Field);
- }
- GlobalizedRD->completeDefinition();
+ ArrayRef<const ValueDecl *> EscapedDeclsForParallel, EscapedDeclsForTeams;
+ if (IsInTTDRegion)
+ EscapedDeclsForTeams = EscapedDecls.getArrayRef();
+ else
+ EscapedDeclsForParallel = EscapedDecls.getArrayRef();
+ GlobalizedRD = ::buildRecordForGlobalizedVars(
+ CGF.getContext(), EscapedDeclsForParallel, EscapedDeclsForTeams,
+ MappedDeclsFields);
}
public:
- CheckVarsEscapingDeclContext(CodeGenFunction &CGF) : CGF(CGF) {}
+ CheckVarsEscapingDeclContext(CodeGenFunction &CGF,
+ ArrayRef<const ValueDecl *> TeamsReductions)
+ : CGF(CGF), EscapedDecls(TeamsReductions.begin(), TeamsReductions.end()) {
+ }
virtual ~CheckVarsEscapingDeclContext() = default;
void VisitDeclStmt(const DeclStmt *S) {
if (!S)
@@ -492,9 +568,9 @@ public:
/// Returns the record that handles all the escaped local variables and used
/// instead of their original storage.
- const RecordDecl *getGlobalizedRecord() {
+ const RecordDecl *getGlobalizedRecord(bool IsInTTDRegion) {
if (!GlobalizedRD)
- buildRecordForGlobalizedVars();
+ buildRecordForGlobalizedVars(IsInTTDRegion);
return GlobalizedRD;
}
@@ -568,31 +644,6 @@ static llvm::Value *getNVPTXNumThreads(CodeGenFunction &CGF) {
"nvptx_num_threads");
}
-/// Get barrier to synchronize all threads in a block.
-static void getNVPTXCTABarrier(CodeGenFunction &CGF) {
- CGF.EmitRuntimeCall(llvm::Intrinsic::getDeclaration(
- &CGF.CGM.getModule(), llvm::Intrinsic::nvvm_barrier0));
-}
-
-/// Get barrier #ID to synchronize selected (multiple of warp size) threads in
-/// a CTA.
-static void getNVPTXBarrier(CodeGenFunction &CGF, int ID,
- llvm::Value *NumThreads) {
- CGBuilderTy &Bld = CGF.Builder;
- llvm::Value *Args[] = {Bld.getInt32(ID), NumThreads};
- CGF.EmitRuntimeCall(llvm::Intrinsic::getDeclaration(
- &CGF.CGM.getModule(), llvm::Intrinsic::nvvm_barrier),
- Args);
-}
-
-/// Synchronize all GPU threads in a block.
-static void syncCTAThreads(CodeGenFunction &CGF) { getNVPTXCTABarrier(CGF); }
-
-/// Synchronize worker threads in a parallel region.
-static void syncParallelThreads(CodeGenFunction &CGF, llvm::Value *NumThreads) {
- return getNVPTXBarrier(CGF, NB_Parallel, NumThreads);
-}
-
/// Get the value of the thread_limit clause in the teams directive.
/// For the 'generic' execution mode, the runtime encodes thread_limit in
/// the launch parameters, always starting thread_limit+warpSize threads per
@@ -654,12 +705,58 @@ getDataSharingMode(CodeGenModule &CGM) {
: CGOpenMPRuntimeNVPTX::Generic;
}
+/// Checks if the expression is constant or does not have non-trivial function
+/// calls.
+static bool isTrivial(ASTContext &Ctx, const Expr * E) {
+ // We can skip constant expressions.
+ // We can skip expressions with trivial calls or simple expressions.
+ return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
+ !E->hasNonTrivialCall(Ctx)) &&
+ !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
+}
+
/// Checks if the \p Body is the \a CompoundStmt and returns its child statement
-/// iff there is only one.
-static const Stmt *getSingleCompoundChild(const Stmt *Body) {
- if (const auto *C = dyn_cast<CompoundStmt>(Body))
- if (C->size() == 1)
- return C->body_front();
+/// iff there is only one that is not evaluatable at the compile time.
+static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body) {
+ if (const auto *C = dyn_cast<CompoundStmt>(Body)) {
+ const Stmt *Child = nullptr;
+ for (const Stmt *S : C->body()) {
+ if (const auto *E = dyn_cast<Expr>(S)) {
+ if (isTrivial(Ctx, E))
+ continue;
+ }
+ // Some of the statements can be ignored.
+ if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
+ isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
+ continue;
+ // Analyze declarations.
+ if (const auto *DS = dyn_cast<DeclStmt>(S)) {
+ if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
+ if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
+ isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
+ isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
+ isa<UsingDirectiveDecl>(D) ||
+ isa<OMPDeclareReductionDecl>(D) ||
+ isa<OMPThreadPrivateDecl>(D))
+ return true;
+ const auto *VD = dyn_cast<VarDecl>(D);
+ if (!VD)
+ return false;
+ return VD->isConstexpr() ||
+ ((VD->getType().isTrivialType(Ctx) ||
+ VD->getType()->isReferenceType()) &&
+ (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
+ }))
+ continue;
+ }
+ // Found multiple children - cannot get the one child only.
+ if (Child)
+ return Body;
+ Child = S;
+ }
+ if (Child)
+ return Child;
+ }
return Body;
}
@@ -686,8 +783,9 @@ static bool hasParallelIfNumThreadsClause(ASTContext &Ctx,
static bool hasNestedSPMDDirective(ASTContext &Ctx,
const OMPExecutableDirective &D) {
const auto *CS = D.getInnermostCapturedStmt();
- const auto *Body = CS->getCapturedStmt()->IgnoreContainers();
- const Stmt *ChildStmt = getSingleCompoundChild(Body);
+ const auto *Body =
+ CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
+ const Stmt *ChildStmt = getSingleCompoundChild(Ctx, Body);
if (const auto *NestedDir = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
@@ -696,27 +794,215 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
if (isOpenMPParallelDirective(DKind) &&
!hasParallelIfNumThreadsClause(Ctx, *NestedDir))
return true;
- if (DKind == OMPD_teams || DKind == OMPD_teams_distribute) {
- Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers();
+ if (DKind == OMPD_teams) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
+ /*IgnoreCaptured=*/true);
if (!Body)
return false;
- ChildStmt = getSingleCompoundChild(Body);
+ ChildStmt = getSingleCompoundChild(Ctx, Body);
if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
DKind = NND->getDirectiveKind();
if (isOpenMPParallelDirective(DKind) &&
!hasParallelIfNumThreadsClause(Ctx, *NND))
return true;
- if (DKind == OMPD_distribute) {
- Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers();
+ }
+ }
+ return false;
+ case OMPD_target_teams:
+ return isOpenMPParallelDirective(DKind) &&
+ !hasParallelIfNumThreadsClause(Ctx, *NestedDir);
+ case OMPD_target_simd:
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_enter_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_update:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_requires:
+ case OMPD_unknown:
+ llvm_unreachable("Unexpected directive.");
+ }
+ }
+
+ return false;
+}
+
+static bool supportsSPMDExecutionMode(ASTContext &Ctx,
+ const OMPExecutableDirective &D) {
+ OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
+ switch (DirectiveKind) {
+ case OMPD_target:
+ case OMPD_target_teams:
+ return hasNestedSPMDDirective(Ctx, D);
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ return !hasParallelIfNumThreadsClause(Ctx, D);
+ case OMPD_target_simd:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ return false;
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_enter_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_update:
+ case OMPD_declare_simd:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_requires:
+ case OMPD_unknown:
+ break;
+ }
+ llvm_unreachable(
+ "Unknown programming model for OpenMP directive on NVPTX target.");
+}
+
+/// Check if the directive is loops based and has schedule clause at all or has
+/// static scheduling.
+static bool hasStaticScheduling(const OMPExecutableDirective &D) {
+ assert(isOpenMPWorksharingDirective(D.getDirectiveKind()) &&
+ isOpenMPLoopDirective(D.getDirectiveKind()) &&
+ "Expected loop-based directive.");
+ return !D.hasClausesOfKind<OMPOrderedClause>() &&
+ (!D.hasClausesOfKind<OMPScheduleClause>() ||
+ llvm::any_of(D.getClausesOfKind<OMPScheduleClause>(),
+ [](const OMPScheduleClause *C) {
+ return C->getScheduleKind() == OMPC_SCHEDULE_static;
+ }));
+}
+
+/// Check for inner (nested) lightweight runtime construct, if any
+static bool hasNestedLightweightDirective(ASTContext &Ctx,
+ const OMPExecutableDirective &D) {
+ assert(supportsSPMDExecutionMode(Ctx, D) && "Expected SPMD mode directive.");
+ const auto *CS = D.getInnermostCapturedStmt();
+ const auto *Body =
+ CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
+ const Stmt *ChildStmt = getSingleCompoundChild(Ctx, Body);
+
+ if (const auto *NestedDir = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
+ switch (D.getDirectiveKind()) {
+ case OMPD_target:
+ if (isOpenMPParallelDirective(DKind) &&
+ isOpenMPWorksharingDirective(DKind) && isOpenMPLoopDirective(DKind) &&
+ hasStaticScheduling(*NestedDir))
+ return true;
+ if (DKind == OMPD_parallel) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
+ /*IgnoreCaptured=*/true);
+ if (!Body)
+ return false;
+ ChildStmt = getSingleCompoundChild(Ctx, Body);
+ if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ DKind = NND->getDirectiveKind();
+ if (isOpenMPWorksharingDirective(DKind) &&
+ isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND))
+ return true;
+ }
+ } else if (DKind == OMPD_teams) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
+ /*IgnoreCaptured=*/true);
+ if (!Body)
+ return false;
+ ChildStmt = getSingleCompoundChild(Ctx, Body);
+ if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
+ DKind = NND->getDirectiveKind();
+ if (isOpenMPParallelDirective(DKind) &&
+ isOpenMPWorksharingDirective(DKind) &&
+ isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND))
+ return true;
+ if (DKind == OMPD_parallel) {
+ Body = NND->getInnermostCapturedStmt()->IgnoreContainers(
+ /*IgnoreCaptured=*/true);
if (!Body)
return false;
- ChildStmt = getSingleCompoundChild(Body);
- if (!ChildStmt)
- return false;
+ ChildStmt = getSingleCompoundChild(Ctx, Body);
if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
DKind = NND->getDirectiveKind();
- return isOpenMPParallelDirective(DKind) &&
- !hasParallelIfNumThreadsClause(Ctx, *NND);
+ if (isOpenMPWorksharingDirective(DKind) &&
+ isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND))
+ return true;
}
}
}
@@ -724,25 +1010,28 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
return false;
case OMPD_target_teams:
if (isOpenMPParallelDirective(DKind) &&
- !hasParallelIfNumThreadsClause(Ctx, *NestedDir))
+ isOpenMPWorksharingDirective(DKind) && isOpenMPLoopDirective(DKind) &&
+ hasStaticScheduling(*NestedDir))
return true;
- if (DKind == OMPD_distribute) {
- Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers();
+ if (DKind == OMPD_parallel) {
+ Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
+ /*IgnoreCaptured=*/true);
if (!Body)
return false;
- ChildStmt = getSingleCompoundChild(Body);
+ ChildStmt = getSingleCompoundChild(Ctx, Body);
if (const auto *NND = dyn_cast<OMPExecutableDirective>(ChildStmt)) {
DKind = NND->getDirectiveKind();
- return isOpenMPParallelDirective(DKind) &&
- !hasParallelIfNumThreadsClause(Ctx, *NND);
+ if (isOpenMPWorksharingDirective(DKind) &&
+ isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NND))
+ return true;
}
}
return false;
+ case OMPD_target_parallel:
+ return isOpenMPWorksharingDirective(DKind) &&
+ isOpenMPLoopDirective(DKind) && hasStaticScheduling(*NestedDir);
case OMPD_target_teams_distribute:
- return isOpenMPParallelDirective(DKind) &&
- !hasParallelIfNumThreadsClause(Ctx, *NestedDir);
case OMPD_target_simd:
- case OMPD_target_parallel:
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
case OMPD_target_teams_distribute_simd:
@@ -790,6 +1079,7 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
case OMPD_declare_reduction:
case OMPD_taskloop:
case OMPD_taskloop_simd:
+ case OMPD_requires:
case OMPD_unknown:
llvm_unreachable("Unexpected directive.");
}
@@ -798,21 +1088,26 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
return false;
}
-static bool supportsSPMDExecutionMode(ASTContext &Ctx,
- const OMPExecutableDirective &D) {
+/// Checks if the construct supports lightweight runtime. It must be SPMD
+/// construct + inner loop-based construct with static scheduling.
+static bool supportsLightweightRuntime(ASTContext &Ctx,
+ const OMPExecutableDirective &D) {
+ if (!supportsSPMDExecutionMode(Ctx, D))
+ return false;
OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
switch (DirectiveKind) {
case OMPD_target:
case OMPD_target_teams:
- case OMPD_target_teams_distribute:
- return hasNestedSPMDDirective(Ctx, D);
case OMPD_target_parallel:
+ return hasNestedLightweightDirective(Ctx, D);
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
- return !hasParallelIfNumThreadsClause(Ctx, D);
+ // (Last|First)-privates must be shared in parallel region.
+ return hasStaticScheduling(D);
case OMPD_target_simd:
+ case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_simd:
return false;
case OMPD_parallel:
@@ -857,6 +1152,7 @@ static bool supportsSPMDExecutionMode(ASTContext &Ctx,
case OMPD_declare_reduction:
case OMPD_taskloop:
case OMPD_taskloop_simd:
+ case OMPD_requires:
case OMPD_unknown:
break;
}
@@ -870,9 +1166,9 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDKernel(const OMPExecutableDirective &D,
llvm::Constant *&OutlinedFnID,
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen) {
- ExecutionModeRAII ModeRAII(CurrentExecutionMode, /*IsSPMD=*/false);
+ ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode);
EntryFunctionState EST;
- WorkerFunctionState WST(CGM, D.getLocStart());
+ WorkerFunctionState WST(CGM, D.getBeginLoc());
Work.clear();
WrapperFunctionsMap.clear();
@@ -886,17 +1182,35 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDKernel(const OMPExecutableDirective &D,
CGOpenMPRuntimeNVPTX::WorkerFunctionState &WST)
: EST(EST), WST(WST) {}
void Enter(CodeGenFunction &CGF) override {
- static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
- .emitNonSPMDEntryHeader(CGF, EST, WST);
+ auto &RT =
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime());
+ RT.emitNonSPMDEntryHeader(CGF, EST, WST);
+ // Skip target region initialization.
+ RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true);
}
void Exit(CodeGenFunction &CGF) override {
- static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
- .emitNonSPMDEntryFooter(CGF, EST);
+ auto &RT =
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime());
+ RT.clearLocThreadIdInsertPt(CGF);
+ RT.emitNonSPMDEntryFooter(CGF, EST);
}
} Action(EST, WST);
CodeGen.setAction(Action);
+ IsInTTDRegion = true;
+ // Reserve place for the globalized memory.
+ GlobalizedRecords.emplace_back();
+ if (!KernelStaticGlobalized) {
+ KernelStaticGlobalized = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.VoidPtrTy, /*isConstant=*/false,
+ llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
+ "_openmp_kernel_static_glob_rd$ptr", /*InsertBefore=*/nullptr,
+ llvm::GlobalValue::NotThreadLocal,
+ CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared));
+ }
emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
IsOffloadEntry, CodeGen);
+ IsInTTDRegion = false;
// Now change the name of the worker function to correspond to this target
// region's entry function.
@@ -984,7 +1298,10 @@ void CGOpenMPRuntimeNVPTX::emitSPMDKernel(const OMPExecutableDirective &D,
llvm::Constant *&OutlinedFnID,
bool IsOffloadEntry,
const RegionCodeGenTy &CodeGen) {
- ExecutionModeRAII ModeRAII(CurrentExecutionMode, /*IsSPMD=*/true);
+ ExecutionRuntimeModesRAII ModeRAII(
+ CurrentExecutionMode, RequiresFullRuntime,
+ CGM.getLangOpts().OpenMPCUDAForceFullRuntime ||
+ !supportsLightweightRuntime(CGM.getContext(), D));
EntryFunctionState EST;
// Emit target region as a standalone region.
@@ -1000,14 +1317,30 @@ void CGOpenMPRuntimeNVPTX::emitSPMDKernel(const OMPExecutableDirective &D,
: RT(RT), EST(EST), D(D) {}
void Enter(CodeGenFunction &CGF) override {
RT.emitSPMDEntryHeader(CGF, EST, D);
+ // Skip target region initialization.
+ RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true);
}
void Exit(CodeGenFunction &CGF) override {
+ RT.clearLocThreadIdInsertPt(CGF);
RT.emitSPMDEntryFooter(CGF, EST);
}
} Action(*this, EST, D);
CodeGen.setAction(Action);
+ IsInTTDRegion = true;
+ // Reserve place for the globalized memory.
+ GlobalizedRecords.emplace_back();
+ if (!KernelStaticGlobalized) {
+ KernelStaticGlobalized = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.VoidPtrTy, /*isConstant=*/false,
+ llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
+ "_openmp_kernel_static_glob_rd$ptr", /*InsertBefore=*/nullptr,
+ llvm::GlobalValue::NotThreadLocal,
+ CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared));
+ }
emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
IsOffloadEntry, CodeGen);
+ IsInTTDRegion = false;
}
void CGOpenMPRuntimeNVPTX::emitSPMDEntryHeader(
@@ -1019,19 +1352,18 @@ void CGOpenMPRuntimeNVPTX::emitSPMDEntryHeader(
llvm::BasicBlock *ExecuteBB = CGF.createBasicBlock(".execute");
EST.ExitBB = CGF.createBasicBlock(".exit");
- // Initialize the OMP state in the runtime; called by all active threads.
- // TODO: Set RequiresOMPRuntime and RequiresDataSharing parameters
- // based on code analysis of the target region.
llvm::Value *Args[] = {getThreadLimit(CGF, /*IsInSPMDExecutionMode=*/true),
- /*RequiresOMPRuntime=*/Bld.getInt16(1),
- /*RequiresDataSharing=*/Bld.getInt16(1)};
+ /*RequiresOMPRuntime=*/
+ Bld.getInt16(RequiresFullRuntime ? 1 : 0),
+ /*RequiresDataSharing=*/Bld.getInt16(0)};
CGF.EmitRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_spmd_kernel_init), Args);
- // For data sharing, we need to initialize the stack.
- CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(
- OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd));
+ if (RequiresFullRuntime) {
+ // For data sharing, we need to initialize the stack.
+ CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd));
+ }
CGF.EmitBranch(ExecuteBB);
@@ -1054,8 +1386,11 @@ void CGOpenMPRuntimeNVPTX::emitSPMDEntryFooter(CodeGenFunction &CGF,
CGF.EmitBlock(OMPDeInitBB);
// DeInitialize the OMP state in the runtime; called by all active threads.
+ llvm::Value *Args[] = {/*RequiresOMPRuntime=*/
+ CGF.Builder.getInt16(RequiresFullRuntime ? 1 : 0)};
CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_spmd_kernel_deinit), None);
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_spmd_kernel_deinit_v2), Args);
CGF.EmitBranch(EST.ExitBB);
CGF.EmitBlock(EST.ExitBB);
@@ -1142,6 +1477,8 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
// Signal start of parallel region.
CGF.EmitBlock(ExecuteBB);
+ // Skip initialization.
+ setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true);
// Process work items: outlined parallel functions.
for (llvm::Function *W : Work) {
@@ -1202,6 +1539,8 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF,
// Exit target region.
CGF.EmitBlock(ExitBB);
+ // Skip initialization.
+ clearLocThreadIdInsertPt(CGF);
}
/// Returns specified OpenMP runtime function for the current OpenMP
@@ -1238,11 +1577,12 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_spmd_kernel_init");
break;
}
- case OMPRTL_NVPTX__kmpc_spmd_kernel_deinit: {
- // Build void __kmpc_spmd_kernel_deinit();
+ case OMPRTL_NVPTX__kmpc_spmd_kernel_deinit_v2: {
+ // Build void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime);
+ llvm::Type *TypeParams[] = {CGM.Int16Ty};
auto *FnTy =
- llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
- RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_spmd_kernel_deinit");
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_spmd_kernel_deinit_v2");
break;
}
case OMPRTL_NVPTX__kmpc_kernel_prepare_parallel: {
@@ -1307,12 +1647,12 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_shuffle_int64");
break;
}
- case OMPRTL_NVPTX__kmpc_parallel_reduce_nowait: {
- // Build int32_t kmpc_nvptx_parallel_reduce_nowait(kmp_int32 global_tid,
- // kmp_int32 num_vars, size_t reduce_size, void* reduce_data,
- // void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
- // lane_offset, int16_t Algorithm Version),
- // void (*kmp_InterWarpCopyFctPtr)(void* src, int warp_num));
+ case OMPRTL_NVPTX__kmpc_parallel_reduce_nowait_v2: {
+ // Build int32_t kmpc_nvptx_parallel_reduce_nowait_v2(ident_t *loc,
+ // kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size, void*
+ // reduce_data, void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t
+ // lane_id, int16_t lane_offset, int16_t Algorithm Version), void
+ // (*kmp_InterWarpCopyFctPtr)(void* src, int warp_num));
llvm::Type *ShuffleReduceTypeParams[] = {CGM.VoidPtrTy, CGM.Int16Ty,
CGM.Int16Ty, CGM.Int16Ty};
auto *ShuffleReduceFnTy =
@@ -1322,7 +1662,8 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
auto *InterWarpCopyFnTy =
llvm::FunctionType::get(CGM.VoidTy, InterWarpCopyTypeParams,
/*isVarArg=*/false);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
+ CGM.Int32Ty,
CGM.Int32Ty,
CGM.SizeTy,
CGM.VoidPtrTy,
@@ -1331,86 +1672,40 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
- FnTy, /*Name=*/"__kmpc_nvptx_parallel_reduce_nowait");
+ FnTy, /*Name=*/"__kmpc_nvptx_parallel_reduce_nowait_v2");
break;
}
- case OMPRTL_NVPTX__kmpc_simd_reduce_nowait: {
- // Build int32_t kmpc_nvptx_simd_reduce_nowait(kmp_int32 global_tid,
- // kmp_int32 num_vars, size_t reduce_size, void* reduce_data,
- // void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
- // lane_offset, int16_t Algorithm Version),
- // void (*kmp_InterWarpCopyFctPtr)(void* src, int warp_num));
- llvm::Type *ShuffleReduceTypeParams[] = {CGM.VoidPtrTy, CGM.Int16Ty,
- CGM.Int16Ty, CGM.Int16Ty};
- auto *ShuffleReduceFnTy =
- llvm::FunctionType::get(CGM.VoidTy, ShuffleReduceTypeParams,
- /*isVarArg=*/false);
- llvm::Type *InterWarpCopyTypeParams[] = {CGM.VoidPtrTy, CGM.Int32Ty};
- auto *InterWarpCopyFnTy =
- llvm::FunctionType::get(CGM.VoidTy, InterWarpCopyTypeParams,
- /*isVarArg=*/false);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
- CGM.Int32Ty,
- CGM.SizeTy,
- CGM.VoidPtrTy,
- ShuffleReduceFnTy->getPointerTo(),
- InterWarpCopyFnTy->getPointerTo()};
+ case OMPRTL_NVPTX__kmpc_end_reduce_nowait: {
+ // Build __kmpc_end_reduce_nowait(kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {CGM.Int32Ty};
auto *FnTy =
- llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
- FnTy, /*Name=*/"__kmpc_nvptx_simd_reduce_nowait");
+ FnTy, /*Name=*/"__kmpc_nvptx_end_reduce_nowait");
break;
}
- case OMPRTL_NVPTX__kmpc_teams_reduce_nowait: {
- // Build int32_t __kmpc_nvptx_teams_reduce_nowait(int32_t global_tid,
- // int32_t num_vars, size_t reduce_size, void *reduce_data,
- // void (*kmp_ShuffleReductFctPtr)(void *rhsData, int16_t lane_id, int16_t
- // lane_offset, int16_t shortCircuit),
- // void (*kmp_InterWarpCopyFctPtr)(void* src, int32_t warp_num),
- // void (*kmp_CopyToScratchpadFctPtr)(void *reduce_data, void * scratchpad,
- // int32_t index, int32_t width),
- // void (*kmp_LoadReduceFctPtr)(void *reduce_data, void * scratchpad,
- // int32_t index, int32_t width, int32_t reduce))
- llvm::Type *ShuffleReduceTypeParams[] = {CGM.VoidPtrTy, CGM.Int16Ty,
- CGM.Int16Ty, CGM.Int16Ty};
- auto *ShuffleReduceFnTy =
- llvm::FunctionType::get(CGM.VoidTy, ShuffleReduceTypeParams,
- /*isVarArg=*/false);
- llvm::Type *InterWarpCopyTypeParams[] = {CGM.VoidPtrTy, CGM.Int32Ty};
- auto *InterWarpCopyFnTy =
- llvm::FunctionType::get(CGM.VoidTy, InterWarpCopyTypeParams,
- /*isVarArg=*/false);
- llvm::Type *CopyToScratchpadTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy,
- CGM.Int32Ty, CGM.Int32Ty};
- auto *CopyToScratchpadFnTy =
- llvm::FunctionType::get(CGM.VoidTy, CopyToScratchpadTypeParams,
- /*isVarArg=*/false);
- llvm::Type *LoadReduceTypeParams[] = {
- CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.Int32Ty, CGM.Int32Ty, CGM.Int32Ty};
- auto *LoadReduceFnTy =
- llvm::FunctionType::get(CGM.VoidTy, LoadReduceTypeParams,
- /*isVarArg=*/false);
- llvm::Type *TypeParams[] = {CGM.Int32Ty,
- CGM.Int32Ty,
- CGM.SizeTy,
- CGM.VoidPtrTy,
- ShuffleReduceFnTy->getPointerTo(),
- InterWarpCopyFnTy->getPointerTo(),
- CopyToScratchpadFnTy->getPointerTo(),
- LoadReduceFnTy->getPointerTo()};
+ case OMPRTL_NVPTX__kmpc_nvptx_teams_reduce_nowait_simple: {
+ // Build __kmpc_nvptx_teams_reduce_nowait_simple(ident_t *loc, kmp_int32
+ // global_tid, kmp_critical_name *lck)
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty,
+ llvm::PointerType::getUnqual(getKmpCriticalNameTy())};
auto *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
- FnTy, /*Name=*/"__kmpc_nvptx_teams_reduce_nowait");
+ FnTy, /*Name=*/"__kmpc_nvptx_teams_reduce_nowait_simple");
break;
}
- case OMPRTL_NVPTX__kmpc_end_reduce_nowait: {
- // Build __kmpc_end_reduce_nowait(kmp_int32 global_tid);
- llvm::Type *TypeParams[] = {CGM.Int32Ty};
+ case OMPRTL_NVPTX__kmpc_nvptx_teams_end_reduce_nowait_simple: {
+ // Build __kmpc_nvptx_teams_end_reduce_nowait_simple(ident_t *loc, kmp_int32
+ // global_tid, kmp_critical_name *lck)
+ llvm::Type *TypeParams[] = {
+ getIdentTyPointerTy(), CGM.Int32Ty,
+ llvm::PointerType::getUnqual(getKmpCriticalNameTy())};
auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
- FnTy, /*Name=*/"__kmpc_nvptx_end_reduce_nowait");
+ FnTy, /*Name=*/"__kmpc_nvptx_teams_end_reduce_nowait_simple");
break;
}
case OMPRTL_NVPTX__kmpc_data_sharing_init_stack: {
@@ -1424,17 +1719,18 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
/// Build void __kmpc_data_sharing_init_stack_spmd();
auto *FnTy =
llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false);
- RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack_spmd");
+ RTLFn =
+ CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack_spmd");
break;
}
- case OMPRTL_NVPTX__kmpc_data_sharing_push_stack: {
- // Build void *__kmpc_data_sharing_push_stack(size_t size,
+ case OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack: {
+ // Build void *__kmpc_data_sharing_coalesced_push_stack(size_t size,
// int16_t UseSharedMemory);
llvm::Type *TypeParams[] = {CGM.SizeTy, CGM.Int16Ty};
auto *FnTy =
llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
RTLFn = CGM.CreateRuntimeFunction(
- FnTy, /*Name=*/"__kmpc_data_sharing_push_stack");
+ FnTy, /*Name=*/"__kmpc_data_sharing_coalesced_push_stack");
break;
}
case OMPRTL_NVPTX__kmpc_data_sharing_pop_stack: {
@@ -1484,6 +1780,46 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_is_spmd_exec_mode");
break;
}
+ case OMPRTL_NVPTX__kmpc_get_team_static_memory: {
+ // Build void __kmpc_get_team_static_memory(int16_t isSPMDExecutionMode,
+ // const void *buf, size_t size, int16_t is_shared, const void **res);
+ llvm::Type *TypeParams[] = {CGM.Int16Ty, CGM.VoidPtrTy, CGM.SizeTy,
+ CGM.Int16Ty, CGM.VoidPtrPtrTy};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_get_team_static_memory");
+ break;
+ }
+ case OMPRTL_NVPTX__kmpc_restore_team_static_memory: {
+ // Build void __kmpc_restore_team_static_memory(int16_t isSPMDExecutionMode,
+ // int16_t is_shared);
+ llvm::Type *TypeParams[] = {CGM.Int16Ty, CGM.Int16Ty};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
+ RTLFn =
+ CGM.CreateRuntimeFunction(FnTy, "__kmpc_restore_team_static_memory");
+ break;
+ }
+ case OMPRTL__kmpc_barrier: {
+ // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
+ cast<llvm::Function>(RTLFn)->addFnAttr(llvm::Attribute::Convergent);
+ break;
+ }
+ case OMPRTL__kmpc_barrier_simple_spmd: {
+ // Build void __kmpc_barrier_simple_spmd(ident_t *loc, kmp_int32
+ // global_tid);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
+ auto *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn =
+ CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier_simple_spmd");
+ cast<llvm::Function>(RTLFn)->addFnAttr(llvm::Attribute::Convergent);
+ break;
+ }
}
return RTLFn;
}
@@ -1530,6 +1866,37 @@ void CGOpenMPRuntimeNVPTX::emitTargetOutlinedFunction(
setPropertyExecutionMode(CGM, OutlinedFn->getName(), Mode);
}
+namespace {
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+/// Enum for accesseing the reserved_2 field of the ident_t struct.
+enum ModeFlagsTy : unsigned {
+ /// Bit set to 1 when in SPMD mode.
+ KMP_IDENT_SPMD_MODE = 0x01,
+ /// Bit set to 1 when a simplified runtime is used.
+ KMP_IDENT_SIMPLE_RT_MODE = 0x02,
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/KMP_IDENT_SIMPLE_RT_MODE)
+};
+
+/// Special mode Undefined. Is the combination of Non-SPMD mode + SimpleRuntime.
+static const ModeFlagsTy UndefinedMode =
+ (~KMP_IDENT_SPMD_MODE) & KMP_IDENT_SIMPLE_RT_MODE;
+} // anonymous namespace
+
+unsigned CGOpenMPRuntimeNVPTX::getDefaultLocationReserved2Flags() const {
+ switch (getExecutionMode()) {
+ case EM_SPMD:
+ if (requiresFullRuntime())
+ return KMP_IDENT_SPMD_MODE & (~KMP_IDENT_SIMPLE_RT_MODE);
+ return KMP_IDENT_SPMD_MODE | KMP_IDENT_SIMPLE_RT_MODE;
+ case EM_NonSPMD:
+ assert(requiresFullRuntime() && "Expected full runtime.");
+ return (~KMP_IDENT_SPMD_MODE) & (~KMP_IDENT_SIMPLE_RT_MODE);
+ case EM_Unknown:
+ return UndefinedMode;
+ }
+ llvm_unreachable("Unknown flags are requested.");
+}
+
CGOpenMPRuntimeNVPTX::CGOpenMPRuntimeNVPTX(CodeGenModule &CGM)
: CGOpenMPRuntime(CGM, "_", "$") {
if (!CGM.getLangOpts().OpenMPIsDevice)
@@ -1581,12 +1948,15 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction(
}
} Action(IsInParallelRegion);
CodeGen.setAction(Action);
+ bool PrevIsInTTDRegion = IsInTTDRegion;
+ IsInTTDRegion = false;
bool PrevIsInTargetMasterThreadRegion = IsInTargetMasterThreadRegion;
IsInTargetMasterThreadRegion = false;
auto *OutlinedFun =
cast<llvm::Function>(CGOpenMPRuntime::emitParallelOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen));
IsInTargetMasterThreadRegion = PrevIsInTargetMasterThreadRegion;
+ IsInTTDRegion = PrevIsInTTDRegion;
if (getExecutionMode() != CGOpenMPRuntimeNVPTX::EM_SPMD &&
!IsInParallelRegion) {
llvm::Function *WrapperFun =
@@ -1597,26 +1967,106 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction(
return OutlinedFun;
}
+/// Get list of lastprivate variables from the teams distribute ... or
+/// teams {distribute ...} directives.
+static void
+getDistributeLastprivateVars(ASTContext &Ctx, const OMPExecutableDirective &D,
+ llvm::SmallVectorImpl<const ValueDecl *> &Vars) {
+ assert(isOpenMPTeamsDirective(D.getDirectiveKind()) &&
+ "expected teams directive.");
+ const OMPExecutableDirective *Dir = &D;
+ if (!isOpenMPDistributeDirective(D.getDirectiveKind())) {
+ if (const Stmt *S = getSingleCompoundChild(
+ Ctx,
+ D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(
+ /*IgnoreCaptured=*/true))) {
+ Dir = dyn_cast<OMPExecutableDirective>(S);
+ if (Dir && !isOpenMPDistributeDirective(Dir->getDirectiveKind()))
+ Dir = nullptr;
+ }
+ }
+ if (!Dir)
+ return;
+ for (const auto *C : Dir->getClausesOfKind<OMPLastprivateClause>()) {
+ for (const Expr *E : C->getVarRefs())
+ Vars.push_back(getPrivateItem(E));
+ }
+}
+
+/// Get list of reduction variables from the teams ... directives.
+static void
+getTeamsReductionVars(ASTContext &Ctx, const OMPExecutableDirective &D,
+ llvm::SmallVectorImpl<const ValueDecl *> &Vars) {
+ assert(isOpenMPTeamsDirective(D.getDirectiveKind()) &&
+ "expected teams directive.");
+ for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
+ for (const Expr *E : C->privates())
+ Vars.push_back(getPrivateItem(E));
+ }
+}
+
llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
- SourceLocation Loc = D.getLocStart();
+ SourceLocation Loc = D.getBeginLoc();
+
+ const RecordDecl *GlobalizedRD = nullptr;
+ llvm::SmallVector<const ValueDecl *, 4> LastPrivatesReductions;
+ llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
+ // Globalize team reductions variable unconditionally in all modes.
+ getTeamsReductionVars(CGM.getContext(), D, LastPrivatesReductions);
+ if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) {
+ getDistributeLastprivateVars(CGM.getContext(), D, LastPrivatesReductions);
+ if (!LastPrivatesReductions.empty()) {
+ GlobalizedRD = ::buildRecordForGlobalizedVars(
+ CGM.getContext(), llvm::None, LastPrivatesReductions,
+ MappedDeclsFields);
+ }
+ } else if (!LastPrivatesReductions.empty()) {
+ assert(!TeamAndReductions.first &&
+ "Previous team declaration is not expected.");
+ TeamAndReductions.first = D.getCapturedStmt(OMPD_teams)->getCapturedDecl();
+ std::swap(TeamAndReductions.second, LastPrivatesReductions);
+ }
// Emit target region as a standalone region.
class NVPTXPrePostActionTy : public PrePostActionTy {
SourceLocation &Loc;
+ const RecordDecl *GlobalizedRD;
+ llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
+ &MappedDeclsFields;
public:
- NVPTXPrePostActionTy(SourceLocation &Loc) : Loc(Loc) {}
+ NVPTXPrePostActionTy(
+ SourceLocation &Loc, const RecordDecl *GlobalizedRD,
+ llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
+ &MappedDeclsFields)
+ : Loc(Loc), GlobalizedRD(GlobalizedRD),
+ MappedDeclsFields(MappedDeclsFields) {}
void Enter(CodeGenFunction &CGF) override {
- static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
- .emitGenericVarsProlog(CGF, Loc);
+ auto &Rt =
+ static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime());
+ if (GlobalizedRD) {
+ auto I = Rt.FunctionGlobalizedDecls.try_emplace(CGF.CurFn).first;
+ I->getSecond().GlobalRecord = GlobalizedRD;
+ I->getSecond().MappedParams =
+ llvm::make_unique<CodeGenFunction::OMPMapVars>();
+ DeclToAddrMapTy &Data = I->getSecond().LocalVarData;
+ for (const auto &Pair : MappedDeclsFields) {
+ assert(Pair.getFirst()->isCanonicalDecl() &&
+ "Expected canonical declaration");
+ Data.insert(std::make_pair(Pair.getFirst(),
+ MappedVarData(Pair.getSecond(),
+ /*IsOnePerTeam=*/true)));
+ }
+ }
+ Rt.emitGenericVarsProlog(CGF, Loc);
}
void Exit(CodeGenFunction &CGF) override {
static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
.emitGenericVarsEpilog(CGF);
}
- } Action(Loc);
+ } Action(Loc, GlobalizedRD, MappedDeclsFields);
CodeGen.setAction(Action);
llvm::Value *OutlinedFunVal = CGOpenMPRuntime::emitTeamsOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen);
@@ -1629,8 +2079,10 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
}
void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF,
- SourceLocation Loc) {
- if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic)
+ SourceLocation Loc,
+ bool WithSPMDCheck) {
+ if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic &&
+ getExecutionMode() != CGOpenMPRuntimeNVPTX::EM_SPMD)
return;
CGBuilderTy &Bld = CGF.Builder;
@@ -1639,33 +2091,187 @@ void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF,
if (I == FunctionGlobalizedDecls.end())
return;
if (const RecordDecl *GlobalizedVarsRecord = I->getSecond().GlobalRecord) {
- QualType RecTy = CGM.getContext().getRecordType(GlobalizedVarsRecord);
+ QualType GlobalRecTy = CGM.getContext().getRecordType(GlobalizedVarsRecord);
+ QualType SecGlobalRecTy;
// Recover pointer to this function's global record. The runtime will
// handle the specifics of the allocation of the memory.
// Use actual memory size of the record including the padding
// for alignment purposes.
unsigned Alignment =
- CGM.getContext().getTypeAlignInChars(RecTy).getQuantity();
+ CGM.getContext().getTypeAlignInChars(GlobalRecTy).getQuantity();
unsigned GlobalRecordSize =
- CGM.getContext().getTypeSizeInChars(RecTy).getQuantity();
+ CGM.getContext().getTypeSizeInChars(GlobalRecTy).getQuantity();
GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment);
- // TODO: allow the usage of shared memory to be controlled by
- // the user, for now, default to global.
- llvm::Value *GlobalRecordSizeArg[] = {
- llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize),
- CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
- llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_push_stack),
- GlobalRecordSizeArg);
- llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- GlobalRecValue, CGF.ConvertTypeForMem(RecTy)->getPointerTo());
+
+ llvm::PointerType *GlobalRecPtrTy =
+ CGF.ConvertTypeForMem(GlobalRecTy)->getPointerTo();
+ llvm::Value *GlobalRecCastAddr;
+ llvm::Value *IsTTD = nullptr;
+ if (!IsInTTDRegion &&
+ (WithSPMDCheck ||
+ getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_Unknown)) {
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
+ llvm::BasicBlock *SPMDBB = CGF.createBasicBlock(".spmd");
+ llvm::BasicBlock *NonSPMDBB = CGF.createBasicBlock(".non-spmd");
+ if (I->getSecond().SecondaryGlobalRecord.hasValue()) {
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
+ llvm::Value *ThreadID = getThreadID(CGF, Loc);
+ llvm::Value *PL = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_parallel_level),
+ {RTLoc, ThreadID});
+ IsTTD = Bld.CreateIsNull(PL);
+ }
+ llvm::Value *IsSPMD = Bld.CreateIsNotNull(CGF.EmitNounwindRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_is_spmd_exec_mode)));
+ Bld.CreateCondBr(IsSPMD, SPMDBB, NonSPMDBB);
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(SPMDBB);
+ Address RecPtr = Address(llvm::ConstantPointerNull::get(GlobalRecPtrTy),
+ CharUnits::fromQuantity(Alignment));
+ CGF.EmitBranch(ExitBB);
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(NonSPMDBB);
+ llvm::Value *Size = llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize);
+ if (const RecordDecl *SecGlobalizedVarsRecord =
+ I->getSecond().SecondaryGlobalRecord.getValueOr(nullptr)) {
+ SecGlobalRecTy =
+ CGM.getContext().getRecordType(SecGlobalizedVarsRecord);
+
+ // Recover pointer to this function's global record. The runtime will
+ // handle the specifics of the allocation of the memory.
+ // Use actual memory size of the record including the padding
+ // for alignment purposes.
+ unsigned Alignment =
+ CGM.getContext().getTypeAlignInChars(SecGlobalRecTy).getQuantity();
+ unsigned GlobalRecordSize =
+ CGM.getContext().getTypeSizeInChars(SecGlobalRecTy).getQuantity();
+ GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment);
+ Size = Bld.CreateSelect(
+ IsTTD, llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize), Size);
+ }
+ // TODO: allow the usage of shared memory to be controlled by
+ // the user, for now, default to global.
+ llvm::Value *GlobalRecordSizeArg[] = {
+ Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
+ llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack),
+ GlobalRecordSizeArg);
+ GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ GlobalRecValue, GlobalRecPtrTy);
+ CGF.EmitBlock(ExitBB);
+ auto *Phi = Bld.CreatePHI(GlobalRecPtrTy,
+ /*NumReservedValues=*/2, "_select_stack");
+ Phi->addIncoming(RecPtr.getPointer(), SPMDBB);
+ Phi->addIncoming(GlobalRecCastAddr, NonSPMDBB);
+ GlobalRecCastAddr = Phi;
+ I->getSecond().GlobalRecordAddr = Phi;
+ I->getSecond().IsInSPMDModeFlag = IsSPMD;
+ } else if (IsInTTDRegion) {
+ assert(GlobalizedRecords.back().Records.size() < 2 &&
+ "Expected less than 2 globalized records: one for target and one "
+ "for teams.");
+ unsigned Offset = 0;
+ for (const RecordDecl *RD : GlobalizedRecords.back().Records) {
+ QualType RDTy = CGM.getContext().getRecordType(RD);
+ unsigned Alignment =
+ CGM.getContext().getTypeAlignInChars(RDTy).getQuantity();
+ unsigned Size = CGM.getContext().getTypeSizeInChars(RDTy).getQuantity();
+ Offset =
+ llvm::alignTo(llvm::alignTo(Offset, Alignment) + Size, Alignment);
+ }
+ unsigned Alignment =
+ CGM.getContext().getTypeAlignInChars(GlobalRecTy).getQuantity();
+ Offset = llvm::alignTo(Offset, Alignment);
+ GlobalizedRecords.back().Records.push_back(GlobalizedVarsRecord);
+ ++GlobalizedRecords.back().RegionCounter;
+ if (GlobalizedRecords.back().Records.size() == 1) {
+ assert(KernelStaticGlobalized &&
+ "Kernel static pointer must be initialized already.");
+ auto *UseSharedMemory = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int16Ty, /*isConstant=*/true,
+ llvm::GlobalValue::InternalLinkage, nullptr,
+ "_openmp_static_kernel$is_shared");
+ UseSharedMemory->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ QualType Int16Ty = CGM.getContext().getIntTypeForBitwidth(
+ /*DestWidth=*/16, /*Signed=*/0);
+ llvm::Value *IsInSharedMemory = CGF.EmitLoadOfScalar(
+ Address(UseSharedMemory,
+ CGM.getContext().getTypeAlignInChars(Int16Ty)),
+ /*Volatile=*/false, Int16Ty, Loc);
+ auto *StaticGlobalized = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false,
+ llvm::GlobalValue::CommonLinkage, nullptr);
+ auto *RecSize = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.SizeTy, /*isConstant=*/true,
+ llvm::GlobalValue::InternalLinkage, nullptr,
+ "_openmp_static_kernel$size");
+ RecSize->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ llvm::Value *Ld = CGF.EmitLoadOfScalar(
+ Address(RecSize, CGM.getSizeAlign()), /*Volatile=*/false,
+ CGM.getContext().getSizeType(), Loc);
+ llvm::Value *ResAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ KernelStaticGlobalized, CGM.VoidPtrPtrTy);
+ llvm::Value *GlobalRecordSizeArg[] = {
+ llvm::ConstantInt::get(
+ CGM.Int16Ty,
+ getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD ? 1 : 0),
+ StaticGlobalized, Ld, IsInSharedMemory, ResAddr};
+ CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_get_team_static_memory),
+ GlobalRecordSizeArg);
+ GlobalizedRecords.back().Buffer = StaticGlobalized;
+ GlobalizedRecords.back().RecSize = RecSize;
+ GlobalizedRecords.back().UseSharedMemory = UseSharedMemory;
+ GlobalizedRecords.back().Loc = Loc;
+ }
+ assert(KernelStaticGlobalized && "Global address must be set already.");
+ Address FrameAddr = CGF.EmitLoadOfPointer(
+ Address(KernelStaticGlobalized, CGM.getPointerAlign()),
+ CGM.getContext()
+ .getPointerType(CGM.getContext().VoidPtrTy)
+ .castAs<PointerType>());
+ llvm::Value *GlobalRecValue =
+ Bld.CreateConstInBoundsGEP(FrameAddr, Offset, CharUnits::One())
+ .getPointer();
+ I->getSecond().GlobalRecordAddr = GlobalRecValue;
+ I->getSecond().IsInSPMDModeFlag = nullptr;
+ GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ GlobalRecValue, CGF.ConvertTypeForMem(GlobalRecTy)->getPointerTo());
+ } else {
+ // TODO: allow the usage of shared memory to be controlled by
+ // the user, for now, default to global.
+ llvm::Value *GlobalRecordSizeArg[] = {
+ llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize),
+ CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
+ llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack),
+ GlobalRecordSizeArg);
+ GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ GlobalRecValue, GlobalRecPtrTy);
+ I->getSecond().GlobalRecordAddr = GlobalRecValue;
+ I->getSecond().IsInSPMDModeFlag = nullptr;
+ }
LValue Base =
- CGF.MakeNaturalAlignPointeeAddrLValue(GlobalRecCastAddr, RecTy);
- I->getSecond().GlobalRecordAddr = GlobalRecValue;
+ CGF.MakeNaturalAlignPointeeAddrLValue(GlobalRecCastAddr, GlobalRecTy);
// Emit the "global alloca" which is a GEP from the global declaration
// record using the pointer returned by the runtime.
+ LValue SecBase;
+ decltype(I->getSecond().LocalVarData)::const_iterator SecIt;
+ if (IsTTD) {
+ SecIt = I->getSecond().SecondaryLocalVarData->begin();
+ llvm::PointerType *SecGlobalRecPtrTy =
+ CGF.ConvertTypeForMem(SecGlobalRecTy)->getPointerTo();
+ SecBase = CGF.MakeNaturalAlignPointeeAddrLValue(
+ Bld.CreatePointerBitCastOrAddrSpaceCast(
+ I->getSecond().GlobalRecordAddr, SecGlobalRecPtrTy),
+ SecGlobalRecTy);
+ }
for (auto &Rec : I->getSecond().LocalVarData) {
bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
llvm::Value *ParValue;
@@ -1675,14 +2281,51 @@ void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF,
CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
ParValue = CGF.EmitLoadOfScalar(ParLVal, Loc);
}
- const FieldDecl *FD = Rec.second.first;
- LValue VarAddr = CGF.EmitLValueForField(Base, FD);
- Rec.second.second = VarAddr.getAddress();
+ LValue VarAddr = CGF.EmitLValueForField(Base, Rec.second.FD);
+ // Emit VarAddr basing on lane-id if required.
+ QualType VarTy;
+ if (Rec.second.IsOnePerTeam) {
+ VarTy = Rec.second.FD->getType();
+ } else {
+ llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(
+ VarAddr.getAddress().getPointer(),
+ {Bld.getInt32(0), getNVPTXLaneID(CGF)});
+ VarTy =
+ Rec.second.FD->getType()->castAsArrayTypeUnsafe()->getElementType();
+ VarAddr = CGF.MakeAddrLValue(
+ Address(Ptr, CGM.getContext().getDeclAlign(Rec.first)), VarTy,
+ AlignmentSource::Decl);
+ }
+ Rec.second.PrivateAddr = VarAddr.getAddress();
+ if (!IsInTTDRegion &&
+ (WithSPMDCheck ||
+ getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_Unknown)) {
+ assert(I->getSecond().IsInSPMDModeFlag &&
+ "Expected unknown execution mode or required SPMD check.");
+ if (IsTTD) {
+ assert(SecIt->second.IsOnePerTeam &&
+ "Secondary glob data must be one per team.");
+ LValue SecVarAddr = CGF.EmitLValueForField(SecBase, SecIt->second.FD);
+ VarAddr.setAddress(
+ Address(Bld.CreateSelect(IsTTD, SecVarAddr.getPointer(),
+ VarAddr.getPointer()),
+ VarAddr.getAlignment()));
+ Rec.second.PrivateAddr = VarAddr.getAddress();
+ }
+ Address GlobalPtr = Rec.second.PrivateAddr;
+ Address LocalAddr = CGF.CreateMemTemp(VarTy, Rec.second.FD->getName());
+ Rec.second.PrivateAddr = Address(
+ Bld.CreateSelect(I->getSecond().IsInSPMDModeFlag,
+ LocalAddr.getPointer(), GlobalPtr.getPointer()),
+ LocalAddr.getAlignment());
+ }
if (EscapedParam) {
const auto *VD = cast<VarDecl>(Rec.first);
CGF.EmitStoreOfScalar(ParValue, VarAddr);
I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress());
}
+ if (IsTTD)
+ ++SecIt;
}
}
for (const ValueDecl *VD : I->getSecond().EscapedVariableLengthDecls) {
@@ -1704,7 +2347,8 @@ void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF,
llvm::Value *GlobalRecordSizeArg[] = {
Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_push_stack),
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_coalesced_push_stack),
GlobalRecordSizeArg);
llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
GlobalRecValue, CGF.ConvertTypeForMem(VD->getType())->getPointerTo());
@@ -1718,8 +2362,10 @@ void CGOpenMPRuntimeNVPTX::emitGenericVarsProlog(CodeGenFunction &CGF,
I->getSecond().MappedParams->apply(CGF);
}
-void CGOpenMPRuntimeNVPTX::emitGenericVarsEpilog(CodeGenFunction &CGF) {
- if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic)
+void CGOpenMPRuntimeNVPTX::emitGenericVarsEpilog(CodeGenFunction &CGF,
+ bool WithSPMDCheck) {
+ if (getDataSharingMode(CGM) != CGOpenMPRuntimeNVPTX::Generic &&
+ getExecutionMode() != CGOpenMPRuntimeNVPTX::EM_SPMD)
return;
const auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
@@ -1734,9 +2380,48 @@ void CGOpenMPRuntimeNVPTX::emitGenericVarsEpilog(CodeGenFunction &CGF) {
Addr);
}
if (I->getSecond().GlobalRecordAddr) {
- CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_data_sharing_pop_stack),
- I->getSecond().GlobalRecordAddr);
+ if (!IsInTTDRegion &&
+ (WithSPMDCheck ||
+ getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_Unknown)) {
+ CGBuilderTy &Bld = CGF.Builder;
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
+ llvm::BasicBlock *NonSPMDBB = CGF.createBasicBlock(".non-spmd");
+ Bld.CreateCondBr(I->getSecond().IsInSPMDModeFlag, ExitBB, NonSPMDBB);
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(NonSPMDBB);
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_pop_stack),
+ CGF.EmitCastToVoidPtr(I->getSecond().GlobalRecordAddr));
+ CGF.EmitBlock(ExitBB);
+ } else if (IsInTTDRegion) {
+ assert(GlobalizedRecords.back().RegionCounter > 0 &&
+ "region counter must be > 0.");
+ --GlobalizedRecords.back().RegionCounter;
+ // Emit the restore function only in the target region.
+ if (GlobalizedRecords.back().RegionCounter == 0) {
+ QualType Int16Ty = CGM.getContext().getIntTypeForBitwidth(
+ /*DestWidth=*/16, /*Signed=*/0);
+ llvm::Value *IsInSharedMemory = CGF.EmitLoadOfScalar(
+ Address(GlobalizedRecords.back().UseSharedMemory,
+ CGM.getContext().getTypeAlignInChars(Int16Ty)),
+ /*Volatile=*/false, Int16Ty, GlobalizedRecords.back().Loc);
+ llvm::Value *Args[] = {
+ llvm::ConstantInt::get(
+ CGM.Int16Ty,
+ getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD ? 1 : 0),
+ IsInSharedMemory};
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_restore_team_static_memory),
+ Args);
+ }
+ } else {
+ CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_data_sharing_pop_stack),
+ I->getSecond().GlobalRecordAddr);
+ }
}
}
}
@@ -1830,7 +2515,7 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
// passed from the outside of the target region.
CodeGenFunction::OMPPrivateScope PrivateArgScope(CGF);
- // There's somehting to share.
+ // There's something to share.
if (!CapturedVars.empty()) {
// Prepare for parallel region. Indicate the outlined function.
Address SharedArgs =
@@ -1884,30 +2569,24 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
Work.emplace_back(WFn);
};
- auto &&LNParallelGen = [this, Loc, &SeqGen, &L0ParallelGen, &CodeGen,
- &ThreadIDAddr](CodeGenFunction &CGF,
- PrePostActionTy &Action) {
- RegionCodeGenTy RCG(CodeGen);
+ auto &&LNParallelGen = [this, Loc, &SeqGen, &L0ParallelGen](
+ CodeGenFunction &CGF, PrePostActionTy &Action) {
if (IsInParallelRegion) {
SeqGen(CGF, Action);
} else if (IsInTargetMasterThreadRegion) {
L0ParallelGen(CGF, Action);
- } else if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_NonSPMD) {
- RCG(CGF);
} else {
// Check for master and then parallelism:
// if (__kmpc_is_spmd_exec_mode() || __kmpc_parallel_level(loc, gtid)) {
- // Serialized execution.
- // } else if (master) {
- // Worker call.
+ // Serialized execution.
// } else {
- // Outlined function call.
+ // Worker call.
// }
CGBuilderTy &Bld = CGF.Builder;
llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
llvm::BasicBlock *SeqBB = CGF.createBasicBlock(".sequential");
llvm::BasicBlock *ParallelCheckBB = CGF.createBasicBlock(".parcheck");
- llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck");
+ llvm::BasicBlock *MasterBB = CGF.createBasicBlock(".master");
llvm::Value *IsSPMD = Bld.CreateIsNotNull(CGF.EmitNounwindRuntimeCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_is_spmd_exec_mode)));
Bld.CreateCondBr(IsSPMD, SeqBB, ParallelCheckBB);
@@ -1920,29 +2599,17 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_parallel_level),
{RTLoc, ThreadID});
llvm::Value *Res = Bld.CreateIsNotNull(PL);
- Bld.CreateCondBr(Res, SeqBB, MasterCheckBB);
+ Bld.CreateCondBr(Res, SeqBB, MasterBB);
CGF.EmitBlock(SeqBB);
SeqGen(CGF, Action);
CGF.EmitBranch(ExitBB);
// There is no need to emit line number for unconditional branch.
(void)ApplyDebugLocation::CreateEmpty(CGF);
- CGF.EmitBlock(MasterCheckBB);
- llvm::BasicBlock *MasterThenBB = CGF.createBasicBlock("master.then");
- llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
- llvm::Value *IsMaster =
- Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF));
- Bld.CreateCondBr(IsMaster, MasterThenBB, ElseBlock);
- CGF.EmitBlock(MasterThenBB);
+ CGF.EmitBlock(MasterBB);
L0ParallelGen(CGF, Action);
CGF.EmitBranch(ExitBB);
// There is no need to emit line number for unconditional branch.
(void)ApplyDebugLocation::CreateEmpty(CGF);
- CGF.EmitBlock(ElseBlock);
- // In the worker need to use the real thread id.
- ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
- RCG(CGF);
- // There is no need to emit line number for unconditional branch.
- (void)ApplyDebugLocation::CreateEmpty(CGF);
// Emit the continuation block for code after the if.
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
}
@@ -2013,6 +2680,34 @@ void CGOpenMPRuntimeNVPTX::emitSPMDParallelCall(
}
}
+void CGOpenMPRuntimeNVPTX::syncCTAThreads(CodeGenFunction &CGF) {
+ // Always emit simple barriers!
+ if (!CGF.HaveInsertPoint())
+ return;
+ // Build call __kmpc_barrier_simple_spmd(nullptr, 0);
+ // This function does not use parameters, so we can emit just default values.
+ llvm::Value *Args[] = {
+ llvm::ConstantPointerNull::get(
+ cast<llvm::PointerType>(getIdentTyPointerTy())),
+ llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/0, /*isSigned=*/true)};
+ CGF.EmitRuntimeCall(
+ createNVPTXRuntimeFunction(OMPRTL__kmpc_barrier_simple_spmd), Args);
+}
+
+void CGOpenMPRuntimeNVPTX::emitBarrierCall(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPDirectiveKind Kind, bool,
+ bool) {
+ // Always emit simple barriers!
+ if (!CGF.HaveInsertPoint())
+ return;
+ // Build call __kmpc_cancel_barrier(loc, thread_id);
+ unsigned Flags = getDefaultFlagsForBarriers(Kind);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
+ getThreadID(CGF, Loc)};
+ CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(OMPRTL__kmpc_barrier), Args);
+}
+
void CGOpenMPRuntimeNVPTX::emitCriticalRegion(
CodeGenFunction &CGF, StringRef CriticalName,
const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
@@ -2055,14 +2750,16 @@ void CGOpenMPRuntimeNVPTX::emitCriticalRegion(
CGF.EmitBlock(BodyBB);
// Output the critical statement.
- CriticalOpGen(CGF);
+ CGOpenMPRuntime::emitCriticalRegion(CGF, CriticalName, CriticalOpGen, Loc,
+ Hint);
// After the body surrounded by the critical region, the single executing
// thread will jump to the synchronisation point.
// Block waits for all threads in current team to finish then increments the
// counter variable and returns to the loop.
CGF.EmitBlock(SyncBB);
- getNVPTXCTABarrier(CGF);
+ emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
llvm::Value *IncCounterVal =
CGF.Builder.CreateNSWAdd(CounterVal, CGF.Builder.getInt32(1));
@@ -2184,11 +2881,12 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr,
CGF, CGF.EmitLoadOfScalar(Ptr, /*Volatile=*/false, IntType, Loc),
IntType, Offset, Loc);
CGF.EmitStoreOfScalar(Res, ElemPtr, /*Volatile=*/false, IntType);
- Ptr = Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize));
- ElemPtr =
+ Address LocalPtr =
+ Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize));
+ Address LocalElemPtr =
Bld.CreateConstGEP(ElemPtr, 1, CharUnits::fromQuantity(IntSize));
- PhiSrc->addIncoming(Ptr.getPointer(), ThenBB);
- PhiDest->addIncoming(ElemPtr.getPointer(), ThenBB);
+ PhiSrc->addIncoming(LocalPtr.getPointer(), ThenBB);
+ PhiDest->addIncoming(LocalElemPtr.getPointer(), ThenBB);
CGF.EmitBranch(PreCondBB);
CGF.EmitBlock(ExitBB);
} else {
@@ -2414,235 +3112,18 @@ static void emitReductionListCopy(
}
}
-/// This function emits a helper that loads data from the scratchpad array
-/// and (optionally) reduces it with the input operand.
-///
-/// load_and_reduce(local, scratchpad, index, width, should_reduce)
-/// reduce_data remote;
-/// for elem in remote:
-/// remote.elem = Scratchpad[elem_id][index]
-/// if (should_reduce)
-/// local = local @ remote
-/// else
-/// local = remote
-static llvm::Value *emitReduceScratchpadFunction(
- CodeGenModule &CGM, ArrayRef<const Expr *> Privates,
- QualType ReductionArrayTy, llvm::Value *ReduceFn, SourceLocation Loc) {
- ASTContext &C = CGM.getContext();
- QualType Int32Ty = C.getIntTypeForBitwidth(32, /*Signed=*/1);
-
- // Destination of the copy.
- ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
- C.VoidPtrTy, ImplicitParamDecl::Other);
- // Base address of the scratchpad array, with each element storing a
- // Reduce list per team.
- ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
- C.VoidPtrTy, ImplicitParamDecl::Other);
- // A source index into the scratchpad array.
- ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
- ImplicitParamDecl::Other);
- // Row width of an element in the scratchpad array, typically
- // the number of teams.
- ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
- ImplicitParamDecl::Other);
- // If should_reduce == 1, then it's load AND reduce,
- // If should_reduce == 0 (or otherwise), then it only loads (+ copy).
- // The latter case is used for initialization.
- ImplicitParamDecl ShouldReduceArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
- Int32Ty, ImplicitParamDecl::Other);
-
- FunctionArgList Args;
- Args.push_back(&ReduceListArg);
- Args.push_back(&ScratchPadArg);
- Args.push_back(&IndexArg);
- Args.push_back(&WidthArg);
- Args.push_back(&ShouldReduceArg);
-
- const CGFunctionInfo &CGFI =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *Fn = llvm::Function::Create(
- CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
- "_omp_reduction_load_and_reduce", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
- Fn->setDoesNotRecurse();
- CodeGenFunction CGF(CGM);
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
-
- CGBuilderTy &Bld = CGF.Builder;
-
- // Get local Reduce list pointer.
- Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg);
- Address ReduceListAddr(
- Bld.CreatePointerBitCastOrAddrSpaceCast(
- CGF.EmitLoadOfScalar(AddrReduceListArg, /*Volatile=*/false,
- C.VoidPtrTy, Loc),
- CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo()),
- CGF.getPointerAlign());
-
- Address AddrScratchPadArg = CGF.GetAddrOfLocalVar(&ScratchPadArg);
- llvm::Value *ScratchPadBase = CGF.EmitLoadOfScalar(
- AddrScratchPadArg, /*Volatile=*/false, C.VoidPtrTy, Loc);
-
- Address AddrIndexArg = CGF.GetAddrOfLocalVar(&IndexArg);
- llvm::Value *IndexVal = Bld.CreateIntCast(
- CGF.EmitLoadOfScalar(AddrIndexArg, /*Volatile=*/false, Int32Ty, Loc),
- CGM.SizeTy, /*isSigned=*/true);
-
- Address AddrWidthArg = CGF.GetAddrOfLocalVar(&WidthArg);
- llvm::Value *WidthVal = Bld.CreateIntCast(
- CGF.EmitLoadOfScalar(AddrWidthArg, /*Volatile=*/false, Int32Ty, Loc),
- CGM.SizeTy, /*isSigned=*/true);
-
- Address AddrShouldReduceArg = CGF.GetAddrOfLocalVar(&ShouldReduceArg);
- llvm::Value *ShouldReduceVal = CGF.EmitLoadOfScalar(
- AddrShouldReduceArg, /*Volatile=*/false, Int32Ty, Loc);
-
- // The absolute ptr address to the base addr of the next element to copy.
- llvm::Value *CumulativeElemBasePtr =
- Bld.CreatePtrToInt(ScratchPadBase, CGM.SizeTy);
- Address SrcDataAddr(CumulativeElemBasePtr, CGF.getPointerAlign());
-
- // Create a Remote Reduce list to store the elements read from the
- // scratchpad array.
- Address RemoteReduceList =
- CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.remote_red_list");
-
- // Assemble remote Reduce list from scratchpad array.
- emitReductionListCopy(ScratchpadToThread, CGF, ReductionArrayTy, Privates,
- SrcDataAddr, RemoteReduceList,
- {/*RemoteLaneOffset=*/nullptr,
- /*ScratchpadIndex=*/IndexVal,
- /*ScratchpadWidth=*/WidthVal});
-
- llvm::BasicBlock *ThenBB = CGF.createBasicBlock("then");
- llvm::BasicBlock *ElseBB = CGF.createBasicBlock("else");
- llvm::BasicBlock *MergeBB = CGF.createBasicBlock("ifcont");
-
- llvm::Value *CondReduce = Bld.CreateIsNotNull(ShouldReduceVal);
- Bld.CreateCondBr(CondReduce, ThenBB, ElseBB);
-
- CGF.EmitBlock(ThenBB);
- // We should reduce with the local Reduce list.
- // reduce_function(LocalReduceList, RemoteReduceList)
- llvm::Value *LocalDataPtr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- ReduceListAddr.getPointer(), CGF.VoidPtrTy);
- llvm::Value *RemoteDataPtr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- RemoteReduceList.getPointer(), CGF.VoidPtrTy);
- CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
- CGF, Loc, ReduceFn, {LocalDataPtr, RemoteDataPtr});
- Bld.CreateBr(MergeBB);
-
- CGF.EmitBlock(ElseBB);
- // No reduction; just copy:
- // Local Reduce list = Remote Reduce list.
- emitReductionListCopy(ThreadCopy, CGF, ReductionArrayTy, Privates,
- RemoteReduceList, ReduceListAddr);
- Bld.CreateBr(MergeBB);
-
- CGF.EmitBlock(MergeBB);
-
- CGF.FinishFunction();
- return Fn;
-}
-
-/// This function emits a helper that stores reduced data from the team
-/// master to a scratchpad array in global memory.
-///
-/// for elem in Reduce List:
-/// scratchpad[elem_id][index] = elem
-///
-static llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM,
- ArrayRef<const Expr *> Privates,
- QualType ReductionArrayTy,
- SourceLocation Loc) {
-
- ASTContext &C = CGM.getContext();
- QualType Int32Ty = C.getIntTypeForBitwidth(32, /*Signed=*/1);
-
- // Source of the copy.
- ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
- C.VoidPtrTy, ImplicitParamDecl::Other);
- // Base address of the scratchpad array, with each element storing a
- // Reduce list per team.
- ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
- C.VoidPtrTy, ImplicitParamDecl::Other);
- // A destination index into the scratchpad array, typically the team
- // identifier.
- ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
- ImplicitParamDecl::Other);
- // Row width of an element in the scratchpad array, typically
- // the number of teams.
- ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int32Ty,
- ImplicitParamDecl::Other);
-
- FunctionArgList Args;
- Args.push_back(&ReduceListArg);
- Args.push_back(&ScratchPadArg);
- Args.push_back(&IndexArg);
- Args.push_back(&WidthArg);
-
- const CGFunctionInfo &CGFI =
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
- auto *Fn = llvm::Function::Create(
- CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
- "_omp_reduction_copy_to_scratchpad", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
- Fn->setDoesNotRecurse();
- CodeGenFunction CGF(CGM);
- CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
-
- CGBuilderTy &Bld = CGF.Builder;
-
- Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg);
- Address SrcDataAddr(
- Bld.CreatePointerBitCastOrAddrSpaceCast(
- CGF.EmitLoadOfScalar(AddrReduceListArg, /*Volatile=*/false,
- C.VoidPtrTy, Loc),
- CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo()),
- CGF.getPointerAlign());
-
- Address AddrScratchPadArg = CGF.GetAddrOfLocalVar(&ScratchPadArg);
- llvm::Value *ScratchPadBase = CGF.EmitLoadOfScalar(
- AddrScratchPadArg, /*Volatile=*/false, C.VoidPtrTy, Loc);
-
- Address AddrIndexArg = CGF.GetAddrOfLocalVar(&IndexArg);
- llvm::Value *IndexVal = Bld.CreateIntCast(
- CGF.EmitLoadOfScalar(AddrIndexArg, /*Volatile=*/false, Int32Ty, Loc),
- CGF.SizeTy, /*isSigned=*/true);
-
- Address AddrWidthArg = CGF.GetAddrOfLocalVar(&WidthArg);
- llvm::Value *WidthVal =
- Bld.CreateIntCast(CGF.EmitLoadOfScalar(AddrWidthArg, /*Volatile=*/false,
- Int32Ty, SourceLocation()),
- CGF.SizeTy, /*isSigned=*/true);
-
- // The absolute ptr address to the base addr of the next element to copy.
- llvm::Value *CumulativeElemBasePtr =
- Bld.CreatePtrToInt(ScratchPadBase, CGM.SizeTy);
- Address DestDataAddr(CumulativeElemBasePtr, CGF.getPointerAlign());
-
- emitReductionListCopy(ThreadToScratchpad, CGF, ReductionArrayTy, Privates,
- SrcDataAddr, DestDataAddr,
- {/*RemoteLaneOffset=*/nullptr,
- /*ScratchpadIndex=*/IndexVal,
- /*ScratchpadWidth=*/WidthVal});
-
- CGF.FinishFunction();
- return Fn;
-}
-
/// This function emits a helper that gathers Reduce lists from the first
/// lane of every active warp to lanes in the first warp.
///
/// void inter_warp_copy_func(void* reduce_data, num_warps)
/// shared smem[warp_size];
/// For all data entries D in reduce_data:
+/// sync
/// If (I am the first lane in each warp)
/// Copy my local D to smem[warp_id]
/// sync
/// if (I am the first warp)
/// Copy smem[thread_id] to my local D
-/// sync
static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
ArrayRef<const Expr *> Privates,
QualType ReductionArrayTy,
@@ -2688,11 +3169,10 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
llvm::GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
if (!TransferMedium) {
- auto *Ty = llvm::ArrayType::get(CGM.Int64Ty, WarpSize);
+ auto *Ty = llvm::ArrayType::get(CGM.Int32Ty, WarpSize);
unsigned SharedAddressSpace = C.getTargetAddressSpace(LangAS::cuda_shared);
TransferMedium = new llvm::GlobalVariable(
- M, Ty,
- /*isConstant=*/false, llvm::GlobalVariable::CommonLinkage,
+ M, Ty, /*isConstant=*/false, llvm::GlobalVariable::CommonLinkage,
llvm::Constant::getNullValue(Ty), TransferMediumName,
/*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal,
SharedAddressSpace);
@@ -2710,7 +3190,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
Address LocalReduceList(
Bld.CreatePointerBitCastOrAddrSpaceCast(
CGF.EmitLoadOfScalar(AddrReduceListArg, /*Volatile=*/false,
- C.VoidPtrTy, SourceLocation()),
+ C.VoidPtrTy, Loc),
CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo()),
CGF.getPointerAlign());
@@ -2720,121 +3200,151 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
// Warp master copies reduce element to transfer medium in __shared__
// memory.
//
- llvm::BasicBlock *ThenBB = CGF.createBasicBlock("then");
- llvm::BasicBlock *ElseBB = CGF.createBasicBlock("else");
- llvm::BasicBlock *MergeBB = CGF.createBasicBlock("ifcont");
-
- // if (lane_id == 0)
- llvm::Value *IsWarpMaster = Bld.CreateIsNull(LaneID, "warp_master");
- Bld.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
- CGF.EmitBlock(ThenBB);
-
- // Reduce element = LocalReduceList[i]
- Address ElemPtrPtrAddr =
- Bld.CreateConstArrayGEP(LocalReduceList, Idx, CGF.getPointerSize());
- llvm::Value *ElemPtrPtr = CGF.EmitLoadOfScalar(
- ElemPtrPtrAddr, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
- // elemptr = (type[i]*)(elemptrptr)
- Address ElemPtr =
- Address(ElemPtrPtr, C.getTypeAlignInChars(Private->getType()));
- ElemPtr = Bld.CreateElementBitCast(
- ElemPtr, CGF.ConvertTypeForMem(Private->getType()));
-
- // Get pointer to location in transfer medium.
- // MediumPtr = &medium[warp_id]
- llvm::Value *MediumPtrVal = Bld.CreateInBoundsGEP(
- TransferMedium, {llvm::Constant::getNullValue(CGM.Int64Ty), WarpID});
- Address MediumPtr(MediumPtrVal, C.getTypeAlignInChars(Private->getType()));
- // Casting to actual data type.
- // MediumPtr = (type[i]*)MediumPtrAddr;
- MediumPtr = Bld.CreateElementBitCast(
- MediumPtr, CGF.ConvertTypeForMem(Private->getType()));
-
- // elem = *elemptr
- //*MediumPtr = elem
- if (Private->getType()->isScalarType()) {
- llvm::Value *Elem = CGF.EmitLoadOfScalar(ElemPtr, /*Volatile=*/false,
- Private->getType(), Loc);
- // Store the source element value to the dest element address.
- CGF.EmitStoreOfScalar(Elem, MediumPtr, /*Volatile=*/false,
- Private->getType());
- } else {
- CGF.EmitAggregateCopy(CGF.MakeAddrLValue(ElemPtr, Private->getType()),
- CGF.MakeAddrLValue(MediumPtr, Private->getType()),
- Private->getType(), AggValueSlot::DoesNotOverlap);
- }
-
- Bld.CreateBr(MergeBB);
-
- CGF.EmitBlock(ElseBB);
- Bld.CreateBr(MergeBB);
-
- CGF.EmitBlock(MergeBB);
+ unsigned RealTySize =
+ C.getTypeSizeInChars(Private->getType())
+ .alignTo(C.getTypeAlignInChars(Private->getType()))
+ .getQuantity();
+ for (unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /=2) {
+ unsigned NumIters = RealTySize / TySize;
+ if (NumIters == 0)
+ continue;
+ QualType CType = C.getIntTypeForBitwidth(
+ C.toBits(CharUnits::fromQuantity(TySize)), /*Signed=*/1);
+ llvm::Type *CopyType = CGF.ConvertTypeForMem(CType);
+ CharUnits Align = CharUnits::fromQuantity(TySize);
+ llvm::Value *Cnt = nullptr;
+ Address CntAddr = Address::invalid();
+ llvm::BasicBlock *PrecondBB = nullptr;
+ llvm::BasicBlock *ExitBB = nullptr;
+ if (NumIters > 1) {
+ CntAddr = CGF.CreateMemTemp(C.IntTy, ".cnt.addr");
+ CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.IntTy), CntAddr,
+ /*Volatile=*/false, C.IntTy);
+ PrecondBB = CGF.createBasicBlock("precond");
+ ExitBB = CGF.createBasicBlock("exit");
+ llvm::BasicBlock *BodyBB = CGF.createBasicBlock("body");
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(PrecondBB);
+ Cnt = CGF.EmitLoadOfScalar(CntAddr, /*Volatile=*/false, C.IntTy, Loc);
+ llvm::Value *Cmp =
+ Bld.CreateICmpULT(Cnt, llvm::ConstantInt::get(CGM.IntTy, NumIters));
+ Bld.CreateCondBr(Cmp, BodyBB, ExitBB);
+ CGF.EmitBlock(BodyBB);
+ }
+ // kmpc_barrier.
+ CGM.getOpenMPRuntime().emitBarrierCall(CGF, Loc, OMPD_unknown,
+ /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
+ llvm::BasicBlock *ThenBB = CGF.createBasicBlock("then");
+ llvm::BasicBlock *ElseBB = CGF.createBasicBlock("else");
+ llvm::BasicBlock *MergeBB = CGF.createBasicBlock("ifcont");
+
+ // if (lane_id == 0)
+ llvm::Value *IsWarpMaster = Bld.CreateIsNull(LaneID, "warp_master");
+ Bld.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
+ CGF.EmitBlock(ThenBB);
- Address AddrNumWarpsArg = CGF.GetAddrOfLocalVar(&NumWarpsArg);
- llvm::Value *NumWarpsVal = CGF.EmitLoadOfScalar(
- AddrNumWarpsArg, /*Volatile=*/false, C.IntTy, SourceLocation());
+ // Reduce element = LocalReduceList[i]
+ Address ElemPtrPtrAddr =
+ Bld.CreateConstArrayGEP(LocalReduceList, Idx, CGF.getPointerSize());
+ llvm::Value *ElemPtrPtr = CGF.EmitLoadOfScalar(
+ ElemPtrPtrAddr, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
+ // elemptr = ((CopyType*)(elemptrptr)) + I
+ Address ElemPtr = Address(ElemPtrPtr, Align);
+ ElemPtr = Bld.CreateElementBitCast(ElemPtr, CopyType);
+ if (NumIters > 1) {
+ ElemPtr = Address(Bld.CreateGEP(ElemPtr.getPointer(), Cnt),
+ ElemPtr.getAlignment());
+ }
- llvm::Value *NumActiveThreads = Bld.CreateNSWMul(
- NumWarpsVal, getNVPTXWarpSize(CGF), "num_active_threads");
- // named_barrier_sync(ParallelBarrierID, num_active_threads)
- syncParallelThreads(CGF, NumActiveThreads);
+ // Get pointer to location in transfer medium.
+ // MediumPtr = &medium[warp_id]
+ llvm::Value *MediumPtrVal = Bld.CreateInBoundsGEP(
+ TransferMedium, {llvm::Constant::getNullValue(CGM.Int64Ty), WarpID});
+ Address MediumPtr(MediumPtrVal, Align);
+ // Casting to actual data type.
+ // MediumPtr = (CopyType*)MediumPtrAddr;
+ MediumPtr = Bld.CreateElementBitCast(MediumPtr, CopyType);
+
+ // elem = *elemptr
+ //*MediumPtr = elem
+ llvm::Value *Elem =
+ CGF.EmitLoadOfScalar(ElemPtr, /*Volatile=*/false, CType, Loc);
+ // Store the source element value to the dest element address.
+ CGF.EmitStoreOfScalar(Elem, MediumPtr, /*Volatile=*/true, CType);
+
+ Bld.CreateBr(MergeBB);
+
+ CGF.EmitBlock(ElseBB);
+ Bld.CreateBr(MergeBB);
+
+ CGF.EmitBlock(MergeBB);
+
+ // kmpc_barrier.
+ CGM.getOpenMPRuntime().emitBarrierCall(CGF, Loc, OMPD_unknown,
+ /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
+
+ //
+ // Warp 0 copies reduce element from transfer medium.
+ //
+ llvm::BasicBlock *W0ThenBB = CGF.createBasicBlock("then");
+ llvm::BasicBlock *W0ElseBB = CGF.createBasicBlock("else");
+ llvm::BasicBlock *W0MergeBB = CGF.createBasicBlock("ifcont");
+
+ Address AddrNumWarpsArg = CGF.GetAddrOfLocalVar(&NumWarpsArg);
+ llvm::Value *NumWarpsVal = CGF.EmitLoadOfScalar(
+ AddrNumWarpsArg, /*Volatile=*/false, C.IntTy, Loc);
+
+ // Up to 32 threads in warp 0 are active.
+ llvm::Value *IsActiveThread =
+ Bld.CreateICmpULT(ThreadID, NumWarpsVal, "is_active_thread");
+ Bld.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
+
+ CGF.EmitBlock(W0ThenBB);
+
+ // SrcMediumPtr = &medium[tid]
+ llvm::Value *SrcMediumPtrVal = Bld.CreateInBoundsGEP(
+ TransferMedium,
+ {llvm::Constant::getNullValue(CGM.Int64Ty), ThreadID});
+ Address SrcMediumPtr(SrcMediumPtrVal, Align);
+ // SrcMediumVal = *SrcMediumPtr;
+ SrcMediumPtr = Bld.CreateElementBitCast(SrcMediumPtr, CopyType);
+
+ // TargetElemPtr = (CopyType*)(SrcDataAddr[i]) + I
+ Address TargetElemPtrPtr =
+ Bld.CreateConstArrayGEP(LocalReduceList, Idx, CGF.getPointerSize());
+ llvm::Value *TargetElemPtrVal = CGF.EmitLoadOfScalar(
+ TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, Loc);
+ Address TargetElemPtr = Address(TargetElemPtrVal, Align);
+ TargetElemPtr = Bld.CreateElementBitCast(TargetElemPtr, CopyType);
+ if (NumIters > 1) {
+ TargetElemPtr = Address(Bld.CreateGEP(TargetElemPtr.getPointer(), Cnt),
+ TargetElemPtr.getAlignment());
+ }
- //
- // Warp 0 copies reduce element from transfer medium.
- //
- llvm::BasicBlock *W0ThenBB = CGF.createBasicBlock("then");
- llvm::BasicBlock *W0ElseBB = CGF.createBasicBlock("else");
- llvm::BasicBlock *W0MergeBB = CGF.createBasicBlock("ifcont");
-
- // Up to 32 threads in warp 0 are active.
- llvm::Value *IsActiveThread =
- Bld.CreateICmpULT(ThreadID, NumWarpsVal, "is_active_thread");
- Bld.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
-
- CGF.EmitBlock(W0ThenBB);
-
- // SrcMediumPtr = &medium[tid]
- llvm::Value *SrcMediumPtrVal = Bld.CreateInBoundsGEP(
- TransferMedium, {llvm::Constant::getNullValue(CGM.Int64Ty), ThreadID});
- Address SrcMediumPtr(SrcMediumPtrVal,
- C.getTypeAlignInChars(Private->getType()));
- // SrcMediumVal = *SrcMediumPtr;
- SrcMediumPtr = Bld.CreateElementBitCast(
- SrcMediumPtr, CGF.ConvertTypeForMem(Private->getType()));
-
- // TargetElemPtr = (type[i]*)(SrcDataAddr[i])
- Address TargetElemPtrPtr =
- Bld.CreateConstArrayGEP(LocalReduceList, Idx, CGF.getPointerSize());
- llvm::Value *TargetElemPtrVal = CGF.EmitLoadOfScalar(
- TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, SourceLocation());
- Address TargetElemPtr =
- Address(TargetElemPtrVal, C.getTypeAlignInChars(Private->getType()));
- TargetElemPtr = Bld.CreateElementBitCast(
- TargetElemPtr, CGF.ConvertTypeForMem(Private->getType()));
-
- // *TargetElemPtr = SrcMediumVal;
- if (Private->getType()->isScalarType()) {
- llvm::Value *SrcMediumValue = CGF.EmitLoadOfScalar(
- SrcMediumPtr, /*Volatile=*/false, Private->getType(), Loc);
+ // *TargetElemPtr = SrcMediumVal;
+ llvm::Value *SrcMediumValue =
+ CGF.EmitLoadOfScalar(SrcMediumPtr, /*Volatile=*/true, CType, Loc);
CGF.EmitStoreOfScalar(SrcMediumValue, TargetElemPtr, /*Volatile=*/false,
- Private->getType());
- } else {
- CGF.EmitAggregateCopy(
- CGF.MakeAddrLValue(SrcMediumPtr, Private->getType()),
- CGF.MakeAddrLValue(TargetElemPtr, Private->getType()),
- Private->getType(), AggValueSlot::DoesNotOverlap);
- }
- Bld.CreateBr(W0MergeBB);
+ CType);
+ Bld.CreateBr(W0MergeBB);
- CGF.EmitBlock(W0ElseBB);
- Bld.CreateBr(W0MergeBB);
+ CGF.EmitBlock(W0ElseBB);
+ Bld.CreateBr(W0MergeBB);
- CGF.EmitBlock(W0MergeBB);
+ CGF.EmitBlock(W0MergeBB);
- // While warp 0 copies values from transfer medium, all other warps must
- // wait.
- syncParallelThreads(CGF, NumActiveThreads);
+ if (NumIters > 1) {
+ Cnt = Bld.CreateNSWAdd(Cnt, llvm::ConstantInt::get(CGM.IntTy, /*V=*/1));
+ CGF.EmitStoreOfScalar(Cnt, CntAddr, /*Volatile=*/false, C.IntTy);
+ CGF.EmitBranch(PrecondBB);
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(ExitBB);
+ }
+ RealTySize %= TySize;
+ }
++Idx;
}
@@ -3103,7 +3613,7 @@ static llvm::Value *emitShuffleAndReduceFunction(
/// 3. Call the OpenMP runtime on the GPU to reduce within a team
/// and store the result on the team master:
///
-/// __kmpc_nvptx_parallel_reduce_nowait(...,
+/// __kmpc_nvptx_parallel_reduce_nowait_v2(...,
/// reduceData, shuffleReduceFn, interWarpCpyFn)
///
/// where:
@@ -3274,7 +3784,7 @@ static llvm::Value *emitShuffleAndReduceFunction(
/// Intra-Team Reduction
///
/// This function, as implemented in the runtime call
-/// '__kmpc_nvptx_parallel_reduce_nowait', aggregates data across OpenMP
+/// '__kmpc_nvptx_parallel_reduce_nowait_v2', aggregates data across OpenMP
/// threads in a team. It first reduces within a warp using the
/// aforementioned algorithms. We then proceed to gather all such
/// reduced values at the first warp.
@@ -3297,7 +3807,7 @@ static llvm::Value *emitShuffleAndReduceFunction(
/// 'loadAndReduceDataFn' to load and reduce values from the array, i.e.,
/// the k'th worker reduces every k'th element.
///
-/// Finally, a call is made to '__kmpc_nvptx_parallel_reduce_nowait' to
+/// Finally, a call is made to '__kmpc_nvptx_parallel_reduce_nowait_v2' to
/// reduce across workers and compute a globally reduced value.
///
void CGOpenMPRuntimeNVPTX::emitReduction(
@@ -3308,125 +3818,116 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
return;
bool ParallelReduction = isOpenMPParallelDirective(Options.ReductionKind);
+#ifndef NDEBUG
bool TeamsReduction = isOpenMPTeamsDirective(Options.ReductionKind);
- bool SimdReduction = isOpenMPSimdDirective(Options.ReductionKind);
- assert((TeamsReduction || ParallelReduction || SimdReduction) &&
- "Invalid reduction selection in emitReduction.");
+#endif
if (Options.SimpleReduction) {
+ assert(!TeamsReduction && !ParallelReduction &&
+ "Invalid reduction selection in emitReduction.");
CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
ReductionOps, Options);
return;
}
- ASTContext &C = CGM.getContext();
-
- // 1. Build a list of reduction variables.
- // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
- auto Size = RHSExprs.size();
- for (const Expr *E : Privates) {
- if (E->getType()->isVariablyModifiedType())
- // Reserve place for array size.
- ++Size;
- }
- llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
- QualType ReductionArrayTy =
- C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
- /*IndexTypeQuals=*/0);
- Address ReductionList =
- CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
- auto IPriv = Privates.begin();
- unsigned Idx = 0;
- for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
- Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
- CGF.getPointerSize());
- CGF.Builder.CreateStore(
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
- Elem);
- if ((*IPriv)->getType()->isVariablyModifiedType()) {
- // Store array size.
- ++Idx;
- Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
- CGF.getPointerSize());
- llvm::Value *Size = CGF.Builder.CreateIntCast(
- CGF.getVLASize(
- CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
- .NumElts,
- CGF.SizeTy, /*isSigned=*/false);
- CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
- Elem);
- }
- }
-
- // 2. Emit reduce_func().
- llvm::Value *ReductionFn = emitReductionFunction(
- CGM, Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(),
- Privates, LHSExprs, RHSExprs, ReductionOps);
+ assert((TeamsReduction || ParallelReduction) &&
+ "Invalid reduction selection in emitReduction.");
- // 4. Build res = __kmpc_reduce{_nowait}(<gtid>, <n>, sizeof(RedList),
+ // Build res = __kmpc_reduce{_nowait}(<gtid>, <n>, sizeof(RedList),
// RedList, shuffle_reduce_func, interwarp_copy_func);
+ // or
+ // Build res = __kmpc_reduce_teams_nowait_simple(<loc>, <gtid>, <lck>);
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
llvm::Value *ThreadId = getThreadID(CGF, Loc);
- llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
- llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- ReductionList.getPointer(), CGF.VoidPtrTy);
-
- llvm::Value *ShuffleAndReduceFn = emitShuffleAndReduceFunction(
- CGM, Privates, ReductionArrayTy, ReductionFn, Loc);
- llvm::Value *InterWarpCopyFn =
- emitInterWarpCopyFunction(CGM, Privates, ReductionArrayTy, Loc);
-
- llvm::Value *Args[] = {ThreadId,
- CGF.Builder.getInt32(RHSExprs.size()),
- ReductionArrayTySize,
- RL,
- ShuffleAndReduceFn,
- InterWarpCopyFn};
-
- llvm::Value *Res = nullptr;
- if (ParallelReduction)
- Res = CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_parallel_reduce_nowait),
- Args);
- else if (SimdReduction)
- Res = CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_simd_reduce_nowait),
- Args);
- if (TeamsReduction) {
- llvm::Value *ScratchPadCopyFn =
- emitCopyToScratchpad(CGM, Privates, ReductionArrayTy, Loc);
- llvm::Value *LoadAndReduceFn = emitReduceScratchpadFunction(
+ llvm::Value *Res;
+ if (ParallelReduction) {
+ ASTContext &C = CGM.getContext();
+ // 1. Build a list of reduction variables.
+ // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
+ auto Size = RHSExprs.size();
+ for (const Expr *E : Privates) {
+ if (E->getType()->isVariablyModifiedType())
+ // Reserve place for array size.
+ ++Size;
+ }
+ llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
+ QualType ReductionArrayTy =
+ C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ Address ReductionList =
+ CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
+ auto IPriv = Privates.begin();
+ unsigned Idx = 0;
+ for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
+ Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
+ CGF.getPointerSize());
+ CGF.Builder.CreateStore(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
+ Elem);
+ if ((*IPriv)->getType()->isVariablyModifiedType()) {
+ // Store array size.
+ ++Idx;
+ Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
+ CGF.getPointerSize());
+ llvm::Value *Size = CGF.Builder.CreateIntCast(
+ CGF.getVLASize(
+ CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
+ .NumElts,
+ CGF.SizeTy, /*isSigned=*/false);
+ CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
+ Elem);
+ }
+ }
+
+ llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
+ llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ ReductionList.getPointer(), CGF.VoidPtrTy);
+ llvm::Value *ReductionFn = emitReductionFunction(
+ CGM, Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(),
+ Privates, LHSExprs, RHSExprs, ReductionOps);
+ llvm::Value *ShuffleAndReduceFn = emitShuffleAndReduceFunction(
CGM, Privates, ReductionArrayTy, ReductionFn, Loc);
+ llvm::Value *InterWarpCopyFn =
+ emitInterWarpCopyFunction(CGM, Privates, ReductionArrayTy, Loc);
- llvm::Value *Args[] = {ThreadId,
+ llvm::Value *Args[] = {RTLoc,
+ ThreadId,
CGF.Builder.getInt32(RHSExprs.size()),
ReductionArrayTySize,
RL,
ShuffleAndReduceFn,
- InterWarpCopyFn,
- ScratchPadCopyFn,
- LoadAndReduceFn};
+ InterWarpCopyFn};
+
+ Res = CGF.EmitRuntimeCall(createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_parallel_reduce_nowait_v2),
+ Args);
+ } else {
+ assert(TeamsReduction && "expected teams reduction.");
+ std::string Name = getName({"reduction"});
+ llvm::Value *Lock = getCriticalRegionLock(Name);
+ llvm::Value *Args[] = {RTLoc, ThreadId, Lock};
Res = CGF.EmitRuntimeCall(
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_teams_reduce_nowait),
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_nvptx_teams_reduce_nowait_simple),
Args);
}
- // 5. Build switch(res)
- llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
- llvm::SwitchInst *SwInst =
- CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/1);
+ // 5. Build if (res == 1)
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.reduction.done");
+ llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.then");
+ llvm::Value *Cond = CGF.Builder.CreateICmpEQ(
+ Res, llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1));
+ CGF.Builder.CreateCondBr(Cond, ThenBB, ExitBB);
- // 6. Build case 1: where we have reduced values in the master
+ // 6. Build then branch: where we have reduced values in the master
// thread in each team.
// __kmpc_end_reduce{_nowait}(<gtid>);
// break;
- llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
- SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
- CGF.EmitBlock(Case1BB);
+ CGF.EmitBlock(ThenBB);
// Add emission of __kmpc_end_reduce{_nowait}(<gtid>);
- llvm::Value *EndArgs[] = {ThreadId};
auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps,
this](CodeGenFunction &CGF, PrePostActionTy &Action) {
auto IPriv = Privates.begin();
@@ -3440,15 +3941,33 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
++IRHS;
}
};
- RegionCodeGenTy RCG(CodeGen);
- NVPTXActionTy Action(
- nullptr, llvm::None,
- createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_reduce_nowait),
- EndArgs);
- RCG.setAction(Action);
- RCG(CGF);
- CGF.EmitBranch(DefaultBB);
- CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
+ if (ParallelReduction) {
+ llvm::Value *EndArgs[] = {ThreadId};
+ RegionCodeGenTy RCG(CodeGen);
+ NVPTXActionTy Action(
+ nullptr, llvm::None,
+ createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_end_reduce_nowait),
+ EndArgs);
+ RCG.setAction(Action);
+ RCG(CGF);
+ } else {
+ assert(TeamsReduction && "expected teams reduction.");
+ llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
+ std::string Name = getName({"reduction"});
+ llvm::Value *Lock = getCriticalRegionLock(Name);
+ llvm::Value *EndArgs[] = {RTLoc, ThreadId, Lock};
+ RegionCodeGenTy RCG(CodeGen);
+ NVPTXActionTy Action(
+ nullptr, llvm::None,
+ createNVPTXRuntimeFunction(
+ OMPRTL_NVPTX__kmpc_nvptx_teams_end_reduce_nowait_simple),
+ EndArgs);
+ RCG.setAction(Action);
+ RCG(CGF);
+ }
+ // There is no need to emit line number for unconditional branch.
+ (void)ApplyDebugLocation::CreateEmpty(CGF);
+ CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
}
const VarDecl *
@@ -3478,7 +3997,7 @@ CGOpenMPRuntimeNVPTX::translateParameter(const FieldDecl *FD,
return ParmVarDecl::Create(
CGM.getContext(),
const_cast<DeclContext *>(NativeParam->getDeclContext()),
- NativeParam->getLocStart(), NativeParam->getLocation(),
+ NativeParam->getBeginLoc(), NativeParam->getLocation(),
NativeParam->getIdentifier(), ArgType,
/*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr);
}
@@ -3556,10 +4075,10 @@ llvm::Function *CGOpenMPRuntimeNVPTX::createParallelDataSharingWrapper(
Ctx.getIntTypeForBitwidth(/*DestWidth=*/16, /*Signed=*/false);
QualType Int32QTy =
Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false);
- ImplicitParamDecl ParallelLevelArg(Ctx, /*DC=*/nullptr, D.getLocStart(),
+ ImplicitParamDecl ParallelLevelArg(Ctx, /*DC=*/nullptr, D.getBeginLoc(),
/*Id=*/nullptr, Int16QTy,
ImplicitParamDecl::Other);
- ImplicitParamDecl WrapperArg(Ctx, /*DC=*/nullptr, D.getLocStart(),
+ ImplicitParamDecl WrapperArg(Ctx, /*DC=*/nullptr, D.getBeginLoc(),
/*Id=*/nullptr, Int32QTy,
ImplicitParamDecl::Other);
WrapperArgs.emplace_back(&ParallelLevelArg);
@@ -3577,7 +4096,7 @@ llvm::Function *CGOpenMPRuntimeNVPTX::createParallelDataSharingWrapper(
CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, Fn, CGFI, WrapperArgs,
- D.getLocStart(), D.getLocStart());
+ D.getBeginLoc(), D.getBeginLoc());
const auto *RD = CS.getCapturedRecordDecl();
auto CurField = RD->field_begin();
@@ -3662,7 +4181,7 @@ llvm::Function *CGOpenMPRuntimeNVPTX::createParallelDataSharingWrapper(
}
}
- emitOutlinedFunctionCall(CGF, D.getLocStart(), OutlinedParallelFn, Args);
+ emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedParallelFn, Args);
CGF.FinishFunction();
return Fn;
}
@@ -3675,6 +4194,8 @@ void CGOpenMPRuntimeNVPTX::emitFunctionProlog(CodeGenFunction &CGF,
assert(D && "Expected function or captured|block decl.");
assert(FunctionGlobalizedDecls.count(CGF.CurFn) == 0 &&
"Function is registered already.");
+ assert((!TeamAndReductions.first || TeamAndReductions.first == D) &&
+ "Team is set but not processed.");
const Stmt *Body = nullptr;
bool NeedToDelayGlobalization = false;
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
@@ -3684,12 +4205,18 @@ void CGOpenMPRuntimeNVPTX::emitFunctionProlog(CodeGenFunction &CGF,
} else if (const auto *CD = dyn_cast<CapturedDecl>(D)) {
Body = CD->getBody();
NeedToDelayGlobalization = CGF.CapturedStmtInfo->getKind() == CR_OpenMP;
+ if (NeedToDelayGlobalization &&
+ getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD)
+ return;
}
if (!Body)
return;
- CheckVarsEscapingDeclContext VarChecker(CGF);
+ CheckVarsEscapingDeclContext VarChecker(CGF, TeamAndReductions.second);
VarChecker.Visit(Body);
- const RecordDecl *GlobalizedVarsRecord = VarChecker.getGlobalizedRecord();
+ const RecordDecl *GlobalizedVarsRecord =
+ VarChecker.getGlobalizedRecord(IsInTTDRegion);
+ TeamAndReductions.first = nullptr;
+ TeamAndReductions.second.clear();
ArrayRef<const ValueDecl *> EscapedVariableLengthDecls =
VarChecker.getEscapedVariableLengthDecls();
if (!GlobalizedVarsRecord && EscapedVariableLengthDecls.empty())
@@ -3707,16 +4234,30 @@ void CGOpenMPRuntimeNVPTX::emitFunctionProlog(CodeGenFunction &CGF,
for (const ValueDecl *VD : VarChecker.getEscapedDecls()) {
assert(VD->isCanonicalDecl() && "Expected canonical declaration");
const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD);
- Data.insert(std::make_pair(VD, std::make_pair(FD, Address::invalid())));
+ Data.insert(std::make_pair(VD, MappedVarData(FD, IsInTTDRegion)));
+ }
+ if (!IsInTTDRegion && !NeedToDelayGlobalization && !IsInParallelRegion) {
+ CheckVarsEscapingDeclContext VarChecker(CGF, llvm::None);
+ VarChecker.Visit(Body);
+ I->getSecond().SecondaryGlobalRecord =
+ VarChecker.getGlobalizedRecord(/*IsInTTDRegion=*/true);
+ I->getSecond().SecondaryLocalVarData.emplace();
+ DeclToAddrMapTy &Data = I->getSecond().SecondaryLocalVarData.getValue();
+ for (const ValueDecl *VD : VarChecker.getEscapedDecls()) {
+ assert(VD->isCanonicalDecl() && "Expected canonical declaration");
+ const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD);
+ Data.insert(
+ std::make_pair(VD, MappedVarData(FD, /*IsInTTDRegion=*/true)));
+ }
}
if (!NeedToDelayGlobalization) {
- emitGenericVarsProlog(CGF, D->getLocStart());
+ emitGenericVarsProlog(CGF, D->getBeginLoc(), /*WithSPMDCheck=*/true);
struct GlobalizationScope final : EHScopeStack::Cleanup {
GlobalizationScope() = default;
void Emit(CodeGenFunction &CGF, Flags flags) override {
static_cast<CGOpenMPRuntimeNVPTX &>(CGF.CGM.getOpenMPRuntime())
- .emitGenericVarsEpilog(CGF);
+ .emitGenericVarsEpilog(CGF, /*WithSPMDCheck=*/true);
}
};
CGF.EHStack.pushCleanup<GlobalizationScope>(NormalAndEHCleanup);
@@ -3734,7 +4275,7 @@ Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF,
return Address::invalid();
auto VDI = I->getSecond().LocalVarData.find(VD);
if (VDI != I->getSecond().LocalVarData.end())
- return VDI->second.second;
+ return VDI->second.PrivateAddr;
if (VD->hasAttrs()) {
for (specific_attr_iterator<OMPReferencedVarAttr> IT(VD->attr_begin()),
E(VD->attr_end());
@@ -3743,7 +4284,7 @@ Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF,
cast<VarDecl>(cast<DeclRefExpr>(IT->getRef())->getDecl())
->getCanonicalDecl());
if (VDI != I->getSecond().LocalVarData.end())
- return VDI->second.second;
+ return VDI->second.PrivateAddr;
}
}
return Address::invalid();
@@ -3753,3 +4294,311 @@ void CGOpenMPRuntimeNVPTX::functionFinished(CodeGenFunction &CGF) {
FunctionGlobalizedDecls.erase(CGF.CurFn);
CGOpenMPRuntime::functionFinished(CGF);
}
+
+void CGOpenMPRuntimeNVPTX::getDefaultDistScheduleAndChunk(
+ CodeGenFunction &CGF, const OMPLoopDirective &S,
+ OpenMPDistScheduleClauseKind &ScheduleKind,
+ llvm::Value *&Chunk) const {
+ if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) {
+ ScheduleKind = OMPC_DIST_SCHEDULE_static;
+ Chunk = CGF.EmitScalarConversion(getNVPTXNumThreads(CGF),
+ CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
+ S.getIterationVariable()->getType(), S.getBeginLoc());
+ return;
+ }
+ CGOpenMPRuntime::getDefaultDistScheduleAndChunk(
+ CGF, S, ScheduleKind, Chunk);
+}
+
+void CGOpenMPRuntimeNVPTX::getDefaultScheduleAndChunk(
+ CodeGenFunction &CGF, const OMPLoopDirective &S,
+ OpenMPScheduleClauseKind &ScheduleKind,
+ const Expr *&ChunkExpr) const {
+ ScheduleKind = OMPC_SCHEDULE_static;
+ // Chunk size is 1 in this case.
+ llvm::APInt ChunkSize(32, 1);
+ ChunkExpr = IntegerLiteral::Create(CGF.getContext(), ChunkSize,
+ CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
+ SourceLocation());
+}
+
+void CGOpenMPRuntimeNVPTX::adjustTargetSpecificDataForLambdas(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
+ assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
+ " Expected target-based directive.");
+ const CapturedStmt *CS = D.getCapturedStmt(OMPD_target);
+ for (const CapturedStmt::Capture &C : CS->captures()) {
+ // Capture variables captured by reference in lambdas for target-based
+ // directives.
+ if (!C.capturesVariable())
+ continue;
+ const VarDecl *VD = C.getCapturedVar();
+ const auto *RD = VD->getType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ ->getAsCXXRecordDecl();
+ if (!RD || !RD->isLambda())
+ continue;
+ Address VDAddr = CGF.GetAddrOfLocalVar(VD);
+ LValue VDLVal;
+ if (VD->getType().getCanonicalType()->isReferenceType())
+ VDLVal = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType());
+ else
+ VDLVal = CGF.MakeAddrLValue(
+ VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
+ llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
+ FieldDecl *ThisCapture = nullptr;
+ RD->getCaptureFields(Captures, ThisCapture);
+ if (ThisCapture && CGF.CapturedStmtInfo->isCXXThisExprCaptured()) {
+ LValue ThisLVal =
+ CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
+ llvm::Value *CXXThis = CGF.LoadCXXThis();
+ CGF.EmitStoreOfScalar(CXXThis, ThisLVal);
+ }
+ for (const LambdaCapture &LC : RD->captures()) {
+ if (LC.getCaptureKind() != LCK_ByRef)
+ continue;
+ const VarDecl *VD = LC.getCapturedVar();
+ if (!CS->capturesVariable(VD))
+ continue;
+ auto It = Captures.find(VD);
+ assert(It != Captures.end() && "Found lambda capture without field.");
+ LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
+ Address VDAddr = CGF.GetAddrOfLocalVar(VD);
+ if (VD->getType().getCanonicalType()->isReferenceType())
+ VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr,
+ VD->getType().getCanonicalType())
+ .getAddress();
+ CGF.EmitStoreOfScalar(VDAddr.getPointer(), VarLVal);
+ }
+ }
+}
+
+// Get current CudaArch and ignore any unknown values
+static CudaArch getCudaArch(CodeGenModule &CGM) {
+ if (!CGM.getTarget().hasFeature("ptx"))
+ return CudaArch::UNKNOWN;
+ llvm::StringMap<bool> Features;
+ CGM.getTarget().initFeatureMap(Features, CGM.getDiags(),
+ CGM.getTarget().getTargetOpts().CPU,
+ CGM.getTarget().getTargetOpts().Features);
+ for (const auto &Feature : Features) {
+ if (Feature.getValue()) {
+ CudaArch Arch = StringToCudaArch(Feature.getKey());
+ if (Arch != CudaArch::UNKNOWN)
+ return Arch;
+ }
+ }
+ return CudaArch::UNKNOWN;
+}
+
+/// Check to see if target architecture supports unified addressing which is
+/// a restriction for OpenMP requires clause "unified_shared_memory".
+void CGOpenMPRuntimeNVPTX::checkArchForUnifiedAddressing(
+ CodeGenModule &CGM, const OMPRequiresDecl *D) const {
+ for (const OMPClause *Clause : D->clauselists()) {
+ if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
+ switch (getCudaArch(CGM)) {
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ case CudaArch::SM_30:
+ case CudaArch::SM_32:
+ case CudaArch::SM_35:
+ case CudaArch::SM_37:
+ case CudaArch::SM_50:
+ case CudaArch::SM_52:
+ case CudaArch::SM_53:
+ case CudaArch::SM_60:
+ case CudaArch::SM_61:
+ case CudaArch::SM_62:
+ CGM.Error(Clause->getBeginLoc(),
+ "Target architecture does not support unified addressing");
+ return;
+ case CudaArch::SM_70:
+ case CudaArch::SM_72:
+ case CudaArch::SM_75:
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ case CudaArch::GFX904:
+ case CudaArch::GFX906:
+ case CudaArch::GFX909:
+ case CudaArch::UNKNOWN:
+ break;
+ case CudaArch::LAST:
+ llvm_unreachable("Unexpected Cuda arch.");
+ }
+ }
+ }
+}
+
+/// Get number of SMs and number of blocks per SM.
+static std::pair<unsigned, unsigned> getSMsBlocksPerSM(CodeGenModule &CGM) {
+ std::pair<unsigned, unsigned> Data;
+ if (CGM.getLangOpts().OpenMPCUDANumSMs)
+ Data.first = CGM.getLangOpts().OpenMPCUDANumSMs;
+ if (CGM.getLangOpts().OpenMPCUDABlocksPerSM)
+ Data.second = CGM.getLangOpts().OpenMPCUDABlocksPerSM;
+ if (Data.first && Data.second)
+ return Data;
+ switch (getCudaArch(CGM)) {
+ case CudaArch::SM_20:
+ case CudaArch::SM_21:
+ case CudaArch::SM_30:
+ case CudaArch::SM_32:
+ case CudaArch::SM_35:
+ case CudaArch::SM_37:
+ case CudaArch::SM_50:
+ case CudaArch::SM_52:
+ case CudaArch::SM_53:
+ return {16, 16};
+ case CudaArch::SM_60:
+ case CudaArch::SM_61:
+ case CudaArch::SM_62:
+ return {56, 32};
+ case CudaArch::SM_70:
+ case CudaArch::SM_72:
+ case CudaArch::SM_75:
+ return {84, 32};
+ case CudaArch::GFX600:
+ case CudaArch::GFX601:
+ case CudaArch::GFX700:
+ case CudaArch::GFX701:
+ case CudaArch::GFX702:
+ case CudaArch::GFX703:
+ case CudaArch::GFX704:
+ case CudaArch::GFX801:
+ case CudaArch::GFX802:
+ case CudaArch::GFX803:
+ case CudaArch::GFX810:
+ case CudaArch::GFX900:
+ case CudaArch::GFX902:
+ case CudaArch::GFX904:
+ case CudaArch::GFX906:
+ case CudaArch::GFX909:
+ case CudaArch::UNKNOWN:
+ break;
+ case CudaArch::LAST:
+ llvm_unreachable("Unexpected Cuda arch.");
+ }
+ llvm_unreachable("Unexpected NVPTX target without ptx feature.");
+}
+
+void CGOpenMPRuntimeNVPTX::clear() {
+ if (!GlobalizedRecords.empty()) {
+ ASTContext &C = CGM.getContext();
+ llvm::SmallVector<const GlobalPtrSizeRecsTy *, 4> GlobalRecs;
+ llvm::SmallVector<const GlobalPtrSizeRecsTy *, 4> SharedRecs;
+ RecordDecl *StaticRD = C.buildImplicitRecord(
+ "_openmp_static_memory_type_$_", RecordDecl::TagKind::TTK_Union);
+ StaticRD->startDefinition();
+ RecordDecl *SharedStaticRD = C.buildImplicitRecord(
+ "_shared_openmp_static_memory_type_$_", RecordDecl::TagKind::TTK_Union);
+ SharedStaticRD->startDefinition();
+ for (const GlobalPtrSizeRecsTy &Records : GlobalizedRecords) {
+ if (Records.Records.empty())
+ continue;
+ unsigned Size = 0;
+ unsigned RecAlignment = 0;
+ for (const RecordDecl *RD : Records.Records) {
+ QualType RDTy = C.getRecordType(RD);
+ unsigned Alignment = C.getTypeAlignInChars(RDTy).getQuantity();
+ RecAlignment = std::max(RecAlignment, Alignment);
+ unsigned RecSize = C.getTypeSizeInChars(RDTy).getQuantity();
+ Size =
+ llvm::alignTo(llvm::alignTo(Size, Alignment) + RecSize, Alignment);
+ }
+ Size = llvm::alignTo(Size, RecAlignment);
+ llvm::APInt ArySize(/*numBits=*/64, Size);
+ QualType SubTy = C.getConstantArrayType(
+ C.CharTy, ArySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
+ const bool UseSharedMemory = Size <= SharedMemorySize;
+ auto *Field =
+ FieldDecl::Create(C, UseSharedMemory ? SharedStaticRD : StaticRD,
+ SourceLocation(), SourceLocation(), nullptr, SubTy,
+ C.getTrivialTypeSourceInfo(SubTy, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ if (UseSharedMemory) {
+ SharedStaticRD->addDecl(Field);
+ SharedRecs.push_back(&Records);
+ } else {
+ StaticRD->addDecl(Field);
+ GlobalRecs.push_back(&Records);
+ }
+ Records.RecSize->setInitializer(llvm::ConstantInt::get(CGM.SizeTy, Size));
+ Records.UseSharedMemory->setInitializer(
+ llvm::ConstantInt::get(CGM.Int16Ty, UseSharedMemory ? 1 : 0));
+ }
+ // Allocate SharedMemorySize buffer for the shared memory.
+ // FIXME: nvlink does not handle weak linkage correctly (object with the
+ // different size are reported as erroneous).
+ // Restore this code as sson as nvlink is fixed.
+ if (!SharedStaticRD->field_empty()) {
+ llvm::APInt ArySize(/*numBits=*/64, SharedMemorySize);
+ QualType SubTy = C.getConstantArrayType(
+ C.CharTy, ArySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
+ auto *Field = FieldDecl::Create(
+ C, SharedStaticRD, SourceLocation(), SourceLocation(), nullptr, SubTy,
+ C.getTrivialTypeSourceInfo(SubTy, SourceLocation()),
+ /*BW=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
+ Field->setAccess(AS_public);
+ SharedStaticRD->addDecl(Field);
+ }
+ SharedStaticRD->completeDefinition();
+ if (!SharedStaticRD->field_empty()) {
+ QualType StaticTy = C.getRecordType(SharedStaticRD);
+ llvm::Type *LLVMStaticTy = CGM.getTypes().ConvertTypeForMem(StaticTy);
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), LLVMStaticTy,
+ /*isConstant=*/false, llvm::GlobalValue::CommonLinkage,
+ llvm::Constant::getNullValue(LLVMStaticTy),
+ "_openmp_shared_static_glob_rd_$_", /*InsertBefore=*/nullptr,
+ llvm::GlobalValue::NotThreadLocal,
+ C.getTargetAddressSpace(LangAS::cuda_shared));
+ auto *Replacement = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+ GV, CGM.VoidPtrTy);
+ for (const GlobalPtrSizeRecsTy *Rec : SharedRecs) {
+ Rec->Buffer->replaceAllUsesWith(Replacement);
+ Rec->Buffer->eraseFromParent();
+ }
+ }
+ StaticRD->completeDefinition();
+ if (!StaticRD->field_empty()) {
+ QualType StaticTy = C.getRecordType(StaticRD);
+ std::pair<unsigned, unsigned> SMsBlockPerSM = getSMsBlocksPerSM(CGM);
+ llvm::APInt Size1(32, SMsBlockPerSM.second);
+ QualType Arr1Ty =
+ C.getConstantArrayType(StaticTy, Size1, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ llvm::APInt Size2(32, SMsBlockPerSM.first);
+ QualType Arr2Ty = C.getConstantArrayType(Arr1Ty, Size2, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ llvm::Type *LLVMArr2Ty = CGM.getTypes().ConvertTypeForMem(Arr2Ty);
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), LLVMArr2Ty,
+ /*isConstant=*/false, llvm::GlobalValue::CommonLinkage,
+ llvm::Constant::getNullValue(LLVMArr2Ty),
+ "_openmp_static_glob_rd_$_");
+ auto *Replacement = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+ GV, CGM.VoidPtrTy);
+ for (const GlobalPtrSizeRecsTy *Rec : GlobalRecs) {
+ Rec->Buffer->replaceAllUsesWith(Replacement);
+ Rec->Buffer->eraseFromParent();
+ }
+ }
+ }
+ CGOpenMPRuntime::clear();
+}
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
index f83e99f8a3b7..6091610c37e3 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
+++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
@@ -56,6 +56,11 @@ private:
ExecutionMode getExecutionMode() const;
+ bool requiresFullRuntime() const { return RequiresFullRuntime; }
+
+ /// Get barrier to synchronize all threads in a block.
+ void syncCTAThreads(CodeGenFunction &CGF);
+
/// Emit the worker function for the current target region.
void emitWorkerFunction(WorkerFunctionState &WST);
@@ -72,10 +77,11 @@ private:
void emitNonSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
/// Helper for generic variables globalization prolog.
- void emitGenericVarsProlog(CodeGenFunction &CGF, SourceLocation Loc);
+ void emitGenericVarsProlog(CodeGenFunction &CGF, SourceLocation Loc,
+ bool WithSPMDCheck = false);
/// Helper for generic variables globalization epilog.
- void emitGenericVarsEpilog(CodeGenFunction &CGF);
+ void emitGenericVarsEpilog(CodeGenFunction &CGF, bool WithSPMDCheck = false);
/// Helper for SPMD mode target directive's entry function.
void emitSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
@@ -179,8 +185,19 @@ protected:
return "__omp_outlined__";
}
+ /// Check if the default location must be constant.
+ /// Constant for NVPTX for better optimization.
+ bool isDefaultLocationConstant() const override { return true; }
+
+ /// Returns additional flags that can be stored in reserved_2 field of the
+ /// default location.
+ /// For NVPTX target contains data about SPMD/Non-SPMD execution mode +
+ /// Full/Lightweight runtime mode. Used for better optimization.
+ unsigned getDefaultLocationReserved2Flags() const override;
+
public:
explicit CGOpenMPRuntimeNVPTX(CodeGenModule &CGM);
+ void clear() override;
/// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
/// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
@@ -260,6 +277,18 @@ public:
ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond) override;
+ /// Emit an implicit/explicit barrier for OpenMP threads.
+ /// \param Kind Directive for which this implicit barrier call must be
+ /// generated. Must be OMPD_barrier for explicit barrier generation.
+ /// \param EmitChecks true if need to emit checks for cancellation barriers.
+ /// \param ForceSimpleCall true simple barrier call must be emitted, false if
+ /// runtime class decides which one to emit (simple or with cancellation
+ /// checks).
+ ///
+ void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPDirectiveKind Kind, bool EmitChecks = true,
+ bool ForceSimpleCall = false) override;
+
/// Emits a critical region.
/// \param CriticalName Name of the critical region.
/// \param CriticalOpGen Generator for the statement associated with the given
@@ -339,6 +368,26 @@ public:
///
void functionFinished(CodeGenFunction &CGF) override;
+ /// Choose a default value for the dist_schedule clause.
+ void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF,
+ const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind,
+ llvm::Value *&Chunk) const override;
+
+ /// Choose a default value for the schedule clause.
+ void getDefaultScheduleAndChunk(CodeGenFunction &CGF,
+ const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind,
+ const Expr *&ChunkExpr) const override;
+
+ /// Adjust some parameters for the target-based directives, like addresses of
+ /// the variables captured by reference in lambdas.
+ void adjustTargetSpecificDataForLambdas(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D) const override;
+
+ /// Perform check on requires decl to ensure that target architecture
+ /// supports unified addressing
+ void checkArchForUnifiedAddressing(CodeGenModule &CGM,
+ const OMPRequiresDecl *D) const override;
+
private:
/// Track the execution mode when codegening directives within a target
/// region. The appropriate mode (SPMD/NON-SPMD) is set on entry to the
@@ -346,9 +395,15 @@ private:
/// to emit optimized code.
ExecutionMode CurrentExecutionMode = EM_Unknown;
+ /// Check if the full runtime is required (default - yes).
+ bool RequiresFullRuntime = true;
+
/// true if we're emitting the code for the target region and next parallel
/// region is L0 for sure.
bool IsInTargetMasterThreadRegion = false;
+ /// true if currently emitting code for target/teams/distribute region, false
+ /// - otherwise.
+ bool IsInTTDRegion = false;
/// true if we're definitely in the parallel region.
bool IsInParallelRegion = false;
@@ -362,23 +417,59 @@ private:
llvm::Function *createParallelDataSharingWrapper(
llvm::Function *OutlinedParallelFn, const OMPExecutableDirective &D);
+ /// The data for the single globalized variable.
+ struct MappedVarData {
+ /// Corresponding field in the global record.
+ const FieldDecl *FD = nullptr;
+ /// Corresponding address.
+ Address PrivateAddr = Address::invalid();
+ /// true, if only one element is required (for latprivates in SPMD mode),
+ /// false, if need to create based on the warp-size.
+ bool IsOnePerTeam = false;
+ MappedVarData() = delete;
+ MappedVarData(const FieldDecl *FD, bool IsOnePerTeam = false)
+ : FD(FD), IsOnePerTeam(IsOnePerTeam) {}
+ };
/// The map of local variables to their addresses in the global memory.
- using DeclToAddrMapTy = llvm::MapVector<const Decl *,
- std::pair<const FieldDecl *, Address>>;
+ using DeclToAddrMapTy = llvm::MapVector<const Decl *, MappedVarData>;
/// Set of the parameters passed by value escaping OpenMP context.
using EscapedParamsTy = llvm::SmallPtrSet<const Decl *, 4>;
struct FunctionData {
DeclToAddrMapTy LocalVarData;
+ llvm::Optional<DeclToAddrMapTy> SecondaryLocalVarData = llvm::None;
EscapedParamsTy EscapedParameters;
llvm::SmallVector<const ValueDecl*, 4> EscapedVariableLengthDecls;
llvm::SmallVector<llvm::Value *, 4> EscapedVariableLengthDeclsAddrs;
const RecordDecl *GlobalRecord = nullptr;
+ llvm::Optional<const RecordDecl *> SecondaryGlobalRecord = llvm::None;
llvm::Value *GlobalRecordAddr = nullptr;
+ llvm::Value *IsInSPMDModeFlag = nullptr;
std::unique_ptr<CodeGenFunction::OMPMapVars> MappedParams;
};
/// Maps the function to the list of the globalized variables with their
/// addresses.
llvm::SmallDenseMap<llvm::Function *, FunctionData> FunctionGlobalizedDecls;
+ /// List of records for the globalized variables in target/teams/distribute
+ /// contexts. Inner records are going to be joined into the single record,
+ /// while those resulting records are going to be joined into the single
+ /// union. This resulting union (one per CU) is the entry point for the static
+ /// memory management runtime functions.
+ struct GlobalPtrSizeRecsTy {
+ llvm::GlobalVariable *UseSharedMemory = nullptr;
+ llvm::GlobalVariable *RecSize = nullptr;
+ llvm::GlobalVariable *Buffer = nullptr;
+ SourceLocation Loc;
+ llvm::SmallVector<const RecordDecl *, 2> Records;
+ unsigned RegionCounter = 0;
+ };
+ llvm::SmallVector<GlobalPtrSizeRecsTy, 8> GlobalizedRecords;
+ /// Shared pointer for the global memory in the global memory buffer used for
+ /// the given kernel.
+ llvm::GlobalVariable *KernelStaticGlobalized = nullptr;
+ /// Pair of the Non-SPMD team and all reductions variables in this team
+ /// region.
+ std::pair<const Decl *, llvm::SmallVector<const ValueDecl *, 4>>
+ TeamAndReductions;
};
} // CodeGen namespace.
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 58aaae692552..c754541ac121 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -20,7 +20,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
-#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 79662ec0099f..0242b48659d1 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -19,8 +19,6 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Sema/LoopHint.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
@@ -38,7 +36,7 @@ using namespace CodeGen;
void CodeGenFunction::EmitStopPoint(const Stmt *S) {
if (CGDebugInfo *DI = getDebugInfo()) {
SourceLocation Loc;
- Loc = S->getLocStart();
+ Loc = S->getBeginLoc();
DI->EmitLocation(Builder, Loc);
LastStopPoint = Loc;
@@ -932,6 +930,8 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
LexicalScope ForScope(*this, S.getSourceRange());
// Evaluate the first pieces before the loop.
+ if (S.getInit())
+ EmitStmt(S.getInit());
EmitStmt(S.getRangeStmt());
EmitStmt(S.getBeginStmt());
EmitStmt(S.getEndStmt());
@@ -1020,7 +1020,7 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
if (requiresReturnValueCheck()) {
- llvm::Constant *SLoc = EmitCheckSourceLocation(S.getLocStart());
+ llvm::Constant *SLoc = EmitCheckSourceLocation(S.getBeginLoc());
auto *SLocPtr =
new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false,
llvm::GlobalVariable::PrivateLinkage, SLoc);
@@ -1045,10 +1045,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
// exception to our over-conservative rules about not jumping to
// statements following block literals with non-trivial cleanups.
RunCleanupsScope cleanupScope(*this);
- if (const ExprWithCleanups *cleanups =
- dyn_cast_or_null<ExprWithCleanups>(RV)) {
- enterFullExpression(cleanups);
- RV = cleanups->getSubExpr();
+ if (const FullExpr *fe = dyn_cast_or_null<FullExpr>(RV)) {
+ enterFullExpression(fe);
+ RV = fe->getSubExpr();
}
// FIXME: Clean this up by using an LValue for ReturnTemp,
@@ -1821,11 +1820,14 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
// If this can't be a register or memory, i.e., has to be a constant
// (immediate or symbolic), try to emit it as such.
if (!Info.allowsRegister() && !Info.allowsMemory()) {
- llvm::APSInt Result;
+ if (Info.requiresImmediateConstant()) {
+ llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext());
+ return llvm::ConstantInt::get(getLLVMContext(), AsmConst);
+ }
+
+ Expr::EvalResult Result;
if (InputExpr->EvaluateAsInt(Result, getContext()))
- return llvm::ConstantInt::get(getLLVMContext(), Result);
- assert(!Info.requiresImmediateConstant() &&
- "Required-immediate inlineasm arg isn't constant?");
+ return llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt());
}
if (Info.allowsRegister() || !Info.allowsMemory())
@@ -1848,7 +1850,7 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str,
SmallVector<llvm::Metadata *, 8> Locs;
// Add the location of the first line to the MDNode.
Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
- CGF.Int32Ty, Str->getLocStart().getRawEncoding())));
+ CGF.Int32Ty, Str->getBeginLoc().getRawEncoding())));
StringRef StrVal = Str->getString();
if (!StrVal.empty()) {
const SourceManager &SM = CGF.CGM.getContext().getSourceManager();
@@ -1979,6 +1981,11 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
diag::err_asm_invalid_type_in_input)
<< OutExpr->getType() << OutputConstraint;
}
+
+ // Update largest vector width for any vector types.
+ if (auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back()))
+ LargestVectorWidth = std::max(LargestVectorWidth,
+ VT->getPrimitiveSizeInBits());
} else {
ArgTypes.push_back(Dest.getAddress().getType());
Args.push_back(Dest.getPointer());
@@ -2000,6 +2007,10 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Arg->getType()))
Arg = Builder.CreateBitCast(Arg, AdjTy);
+ // Update largest vector width for any vector types.
+ if (auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
+ LargestVectorWidth = std::max(LargestVectorWidth,
+ VT->getPrimitiveSizeInBits());
if (Info.allowsRegister())
InOutConstraints += llvm::utostr(i);
else
@@ -2080,6 +2091,11 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
<< InputExpr->getType() << InputConstraint;
+ // Update largest vector width for any vector types.
+ if (auto *VT = dyn_cast<llvm::VectorType>(Arg->getType()))
+ LargestVectorWidth = std::max(LargestVectorWidth,
+ VT->getPrimitiveSizeInBits());
+
ArgTypes.push_back(Arg->getType());
Args.push_back(Arg);
Constraints += InputConstraint;
@@ -2272,7 +2288,7 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
"CapturedStmtInfo should be set when generating the captured function");
const CapturedDecl *CD = S.getCapturedDecl();
const RecordDecl *RD = S.getCapturedRecordDecl();
- SourceLocation Loc = S.getLocStart();
+ SourceLocation Loc = S.getBeginLoc();
assert(CD->hasBody() && "missing CapturedDecl body");
// Build the argument list.
@@ -2293,9 +2309,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
F->addFnAttr(llvm::Attribute::NoUnwind);
// Generate the function.
- StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args,
- CD->getLocation(),
- CD->getBody()->getLocStart());
+ StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(),
+ CD->getBody()->getBeginLoc());
// Set the context parameter in CapturedStmtInfo.
Address DeclPtr = GetAddrOfLocalVar(CD->getContextParam());
CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr));
@@ -2305,8 +2320,9 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
Ctx.getTagDeclType(RD));
for (auto *FD : RD->fields()) {
if (FD->hasCapturedVLAType()) {
- auto *ExprArg = EmitLoadOfLValue(EmitLValueForField(Base, FD),
- S.getLocStart()).getScalarVal();
+ auto *ExprArg =
+ EmitLoadOfLValue(EmitLValueForField(Base, FD), S.getBeginLoc())
+ .getScalarVal();
auto VAT = FD->getCapturedVLAType();
VLASizeMap[VAT->getSizeExpr()] = ExprArg;
}
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 0d343f84c71f..eb1304d89345 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -73,7 +73,7 @@ public:
assert(VD == VD->getCanonicalDecl() &&
"Canonical decl must be captured.");
DeclRefExpr DRE(
- const_cast<VarDecl *>(VD),
+ CGF.getContext(), const_cast<VarDecl *>(VD),
isCapturedVar(CGF, VD) || (CGF.CapturedStmtInfo &&
InlinedShareds.isGlobalVarCaptured(VD)),
VD->getType().getNonReferenceType(), VK_LValue, C.getLocation());
@@ -191,7 +191,7 @@ public:
auto *VD = C.getCapturedVar();
assert(VD == VD->getCanonicalDecl() &&
"Canonical decl must be captured.");
- DeclRefExpr DRE(const_cast<VarDecl *>(VD),
+ DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
isCapturedVar(CGF, VD) ||
(CGF.CapturedStmtInfo &&
InlinedShareds.isGlobalVarCaptured(VD)),
@@ -222,7 +222,7 @@ LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
LambdaCaptureFields.lookup(OrigVD) ||
(CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) ||
(CurCodeDecl && isa<BlockDecl>(CurCodeDecl));
- DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), IsCaptured,
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured,
OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc());
return EmitLValue(&DRE);
}
@@ -385,12 +385,12 @@ static llvm::Function *emitOutlinedFunctionPrologue(
FunctionDecl *DebugFunctionDecl = nullptr;
if (!FO.UIntPtrCastRequired) {
FunctionProtoType::ExtProtoInfo EPI;
+ QualType FunctionTy = Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI);
DebugFunctionDecl = FunctionDecl::Create(
- Ctx, Ctx.getTranslationUnitDecl(), FO.S->getLocStart(),
- SourceLocation(), DeclarationName(), Ctx.VoidTy,
- Ctx.getTrivialTypeSourceInfo(
- Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI)),
- SC_Static, /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false);
+ Ctx, Ctx.getTranslationUnitDecl(), FO.S->getBeginLoc(),
+ SourceLocation(), DeclarationName(), FunctionTy,
+ Ctx.getTrivialTypeSourceInfo(FunctionTy), SC_Static,
+ /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false);
}
for (const FieldDecl *FD : RD->fields()) {
QualType ArgType = FD->getType();
@@ -422,7 +422,7 @@ static llvm::Function *emitOutlinedFunctionPrologue(
if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
Arg = ParmVarDecl::Create(
Ctx, DebugFunctionDecl,
- CapVar ? CapVar->getLocStart() : FD->getLocStart(),
+ CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(),
CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType,
/*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr);
} else {
@@ -459,7 +459,7 @@ static llvm::Function *emitOutlinedFunctionPrologue(
// Generate the function.
CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs,
- FO.S->getLocStart(), CD->getBody()->getLocStart());
+ FO.S->getBeginLoc(), CD->getBody()->getBeginLoc());
unsigned Cnt = CD->getContextParamPosition();
I = FO.S->captures().begin();
for (const FieldDecl *FD : RD->fields()) {
@@ -602,7 +602,7 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
I->second.second,
I->second.first ? I->second.first->getType() : Arg->getType(),
AlignmentSource::Decl);
- CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getLocStart());
+ CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
} else {
auto EI = VLASizes.find(Arg);
if (EI != VLASizes.end()) {
@@ -611,12 +611,12 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
Arg->getType(),
AlignmentSource::Decl);
- CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getLocStart());
+ CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
}
}
CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
}
- CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, S.getLocStart(),
+ CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, S.getBeginLoc(),
F, CallArgs);
WrapperCGF.FinishFunction();
return WrapperF;
@@ -763,7 +763,7 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
const auto *VDInit =
cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
bool IsRegistered;
- DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
/*RefersToEnclosingVariableOrCapture=*/FD != nullptr,
(*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
LValue OriginalLVal = EmitLValue(&DRE);
@@ -878,8 +878,8 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
getContext().getTargetInfo().isTLSSupported()) {
assert(CapturedStmtInfo->lookup(VD) &&
"Copyin threadprivates should have been captured!");
- DeclRefExpr DRE(const_cast<VarDecl *>(VD), true, (*IRef)->getType(),
- VK_LValue, (*IRef)->getExprLoc());
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), true,
+ (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
MasterAddr = EmitLValue(&DRE).getAddress();
LocalDeclMap.erase(VD);
} else {
@@ -953,11 +953,10 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
const auto *DestVD =
cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() {
- DeclRefExpr DRE(
- const_cast<VarDecl *>(OrigVD),
- /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
- OrigVD) != nullptr,
- (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
+ /*RefersToEnclosingVariableOrCapture=*/
+ CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
return EmitLValue(&DRE).getAddress();
});
// Check if the variable is also a firstprivate: in this case IInit is
@@ -1183,7 +1182,7 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
// Emit nowait reduction if nowait clause is present or directive is a
// parallel directive (it always has implicit barrier).
CGM.getOpenMPRuntime().emitReduction(
- *this, D.getLocEnd(), Privates, LHSExprs, RHSExprs, ReductionOps,
+ *this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps,
{WithNowait, SimpleReduction, ReductionKind});
}
}
@@ -1237,12 +1236,12 @@ static void emitCommonOMPParallelDirective(
CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
/*IgnoreResultAssign=*/true);
CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(
- CGF, NumThreads, NumThreadsClause->getLocStart());
+ CGF, NumThreads, NumThreadsClause->getBeginLoc());
}
if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
CodeGenFunction::RunCleanupsScope ProcBindScope(CGF);
CGF.CGM.getOpenMPRuntime().emitProcBindClause(
- CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getLocStart());
+ CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
}
const Expr *IfCond = nullptr;
for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
@@ -1261,7 +1260,7 @@ static void emitCommonOMPParallelDirective(
// parameters when necessary
CodeGenBoundParameters(CGF, S, CapturedVars);
CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
- CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getLocStart(), OutlinedFn,
+ CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getBeginLoc(), OutlinedFn,
CapturedVars, IfCond);
}
@@ -1281,7 +1280,7 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
// propagation master's thread values of threadprivate variables to local
// instances of that variables of all other implicit threads.
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
- CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
/*ForceSimpleCall=*/true);
}
CGF.EmitOMPPrivateClause(S, PrivateScope);
@@ -1384,7 +1383,7 @@ bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
- DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
CapturedStmtInfo->lookup(OrigVD) != nullptr,
VD->getInit()->getType(), VK_LValue,
VD->getInit()->getExprLoc());
@@ -1429,7 +1428,7 @@ void CodeGenFunction::EmitOMPLinearClauseFinal(
}
}
const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
- DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
CapturedStmtInfo->lookup(OrigVD) != nullptr,
(*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
Address OrigAddr = EmitLValue(&DRE).getAddress();
@@ -1473,7 +1472,8 @@ static void emitAlignedClause(CodeGenFunction &CGF,
"alignment is not power of 2");
if (Alignment != 0) {
llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
- CGF.EmitAlignmentAssumption(PtrValue, Alignment);
+ CGF.EmitAlignmentAssumption(
+ PtrValue, E, /*No second loc needed*/ SourceLocation(), Alignment);
}
}
}
@@ -1497,7 +1497,7 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters(
if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
VD->hasGlobalStorage()) {
(void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() {
- DeclRefExpr DRE(const_cast<VarDecl *>(VD),
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
E->getType(), VK_LValue, E->getExprLoc());
return EmitLValue(&DRE).getAddress();
@@ -1509,6 +1509,23 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters(
}
++I;
}
+ // Privatize extra loop counters used in loops for ordered(n) clauses.
+ for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
+ if (!C->getNumForLoops())
+ continue;
+ for (unsigned I = S.getCollapsedNumber(),
+ E = C->getLoopNumIterations().size();
+ I < E; ++I) {
+ const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
+ const auto *VD = cast<VarDecl>(DRE->getDecl());
+ // Override only those variables that are really emitted already.
+ if (LocalDeclMap.count(VD)) {
+ (void)LoopScope.addPrivate(VD, [this, DRE, VD]() {
+ return CreateMemTemp(DRE->getType(), VD->getName());
+ });
+ }
+ }
+ }
}
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
@@ -1627,7 +1644,7 @@ void CodeGenFunction::EmitOMPSimdFinal(
if (CED) {
OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress();
} else {
- DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD),
+ DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD),
/*RefersToEnclosingVariableOrCapture=*/false,
(*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
OrigAddr = EmitLValue(&DRE).getAddress();
@@ -1721,6 +1738,8 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
CGF.EmitOMPReductionClauseInit(S, LoopScope);
bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
(void)LoopScope.Privatize();
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
+ CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
S.getInc(),
[&S](CodeGenFunction &CGF) {
@@ -1785,7 +1804,7 @@ void CodeGenFunction::EmitOMPOuterLoop(
BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond);
} else {
BoolCondVal =
- RT.emitForNext(*this, S.getLocStart(), IVSize, IVSigned, LoopArgs.IL,
+ RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
}
@@ -1819,7 +1838,7 @@ void CodeGenFunction::EmitOMPOuterLoop(
else
EmitOMPSimdInit(S, IsMonotonic);
- SourceLocation Loc = S.getLocStart();
+ SourceLocation Loc = S.getBeginLoc();
// when 'distribute' is not combined with a 'for':
// while (idx <= UB) { BODY; ++idx; }
@@ -1851,7 +1870,7 @@ void CodeGenFunction::EmitOMPOuterLoop(
// Tell the runtime we are done.
auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) {
if (!DynamicOrOrdered)
- CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd(),
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
S.getDirectiveKind());
};
OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
@@ -1934,13 +1953,13 @@ void CodeGenFunction::EmitOMPForOuterLoop(
llvm::Value *UBVal = DispatchBounds.second;
CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
LoopArgs.Chunk};
- RT.emitForDispatchInit(*this, S.getLocStart(), ScheduleKind, IVSize,
+ RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize,
IVSigned, Ordered, DipatchRTInputValues);
} else {
CGOpenMPRuntime::StaticRTInput StaticInit(
IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
LoopArgs.ST, LoopArgs.Chunk);
- RT.emitForStaticInit(*this, S.getLocStart(), S.getDirectiveKind(),
+ RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(),
ScheduleKind, StaticInit);
}
@@ -1986,10 +2005,10 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
CGOpenMPRuntime::StaticRTInput StaticInit(
IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB,
LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
- RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind, StaticInit);
+ RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit);
// for combined 'distribute' and 'for' the increment expression of distribute
- // is store in DistInc. For 'distribute' alone, it is in Inc.
+ // is stored in DistInc. For 'distribute' alone, it is in Inc.
Expr *IncExpr;
if (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()))
IncExpr = S.getDistInc();
@@ -2082,9 +2101,9 @@ emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF,
// distribute chunk
QualType IteratorTy = IVExpr->getType();
llvm::Value *LBVal =
- CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getLocStart());
+ CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
llvm::Value *UBVal =
- CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getLocStart());
+ CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
return {LBVal, UBVal};
}
@@ -2244,7 +2263,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
bool Ordered = false;
if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
if (OrderedClause->getNumForLoops())
- RT.emitDoacrossInit(*this, S);
+ RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
else
Ordered = true;
}
@@ -2270,7 +2289,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
// initialization of firstprivate variables and post-update of
// lastprivate variables.
CGM.getOpenMPRuntime().emitBarrierCall(
- *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
/*ForceSimpleCall=*/true);
}
EmitOMPPrivateClause(S, LoopScope);
@@ -2279,19 +2298,33 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
EmitOMPPrivateLoopCounters(S, LoopScope);
EmitOMPLinearClause(S, LoopScope);
(void)LoopScope.Privatize();
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
+ CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
// Detect the loop schedule kind and chunk.
- llvm::Value *Chunk = nullptr;
+ const Expr *ChunkExpr = nullptr;
OpenMPScheduleTy ScheduleKind;
if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
ScheduleKind.Schedule = C->getScheduleKind();
ScheduleKind.M1 = C->getFirstScheduleModifier();
ScheduleKind.M2 = C->getSecondScheduleModifier();
- if (const Expr *Ch = C->getChunkSize()) {
- Chunk = EmitScalarExpr(Ch);
- Chunk = EmitScalarConversion(Chunk, Ch->getType(),
- S.getIterationVariable()->getType(),
- S.getLocStart());
+ ChunkExpr = C->getChunkSize();
+ } else {
+ // Default behaviour for schedule clause.
+ CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
+ *this, S, ScheduleKind.Schedule, ChunkExpr);
+ }
+ bool HasChunkSizeOne = false;
+ llvm::Value *Chunk = nullptr;
+ if (ChunkExpr) {
+ Chunk = EmitScalarExpr(ChunkExpr);
+ Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(),
+ S.getIterationVariable()->getType(),
+ S.getBeginLoc());
+ Expr::EvalResult Result;
+ if (ChunkExpr->EvaluateAsInt(Result, getContext())) {
+ llvm::APSInt EvaluatedChunk = Result.Val.getInt();
+ HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
}
}
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
@@ -2300,8 +2333,12 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
// If the static schedule kind is specified or if the ordered clause is
// specified, and if no monotonic modifier is specified, the effect will
// be as if the monotonic modifier was specified.
- if (RT.isStaticNonchunked(ScheduleKind.Schedule,
- /* Chunked */ Chunk != nullptr) &&
+ bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.Schedule,
+ /* Chunked */ Chunk != nullptr) && HasChunkSizeOne &&
+ isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
+ if ((RT.isStaticNonchunked(ScheduleKind.Schedule,
+ /* Chunked */ Chunk != nullptr) ||
+ StaticChunkedOne) &&
!Ordered) {
if (isOpenMPSimdDirective(S.getDirectiveKind()))
EmitOMPSimdInit(S, /*IsMonotonic=*/true);
@@ -2312,27 +2349,42 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
// unspecified in this case.
CGOpenMPRuntime::StaticRTInput StaticInit(
IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
- UB.getAddress(), ST.getAddress());
- RT.emitForStaticInit(*this, S.getLocStart(), S.getDirectiveKind(),
+ UB.getAddress(), ST.getAddress(),
+ StaticChunkedOne ? Chunk : nullptr);
+ RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(),
ScheduleKind, StaticInit);
JumpDest LoopExit =
getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
- EmitIgnoredExpr(S.getEnsureUpperBound());
+ if (!StaticChunkedOne)
+ EmitIgnoredExpr(S.getEnsureUpperBound());
// IV = LB;
EmitIgnoredExpr(S.getInit());
- // while (idx <= UB) { BODY; ++idx; }
- EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(),
- S.getInc(),
- [&S, LoopExit](CodeGenFunction &CGF) {
- CGF.EmitOMPLoopBody(S, LoopExit);
- CGF.EmitStopPoint(&S);
- },
- [](CodeGenFunction &) {});
+ // For unchunked static schedule generate:
+ //
+ // while (idx <= UB) {
+ // BODY;
+ // ++idx;
+ // }
+ //
+ // For static schedule with chunk one:
+ //
+ // while (IV <= PrevUB) {
+ // BODY;
+ // IV += ST;
+ // }
+ EmitOMPInnerLoop(S, LoopScope.requiresCleanups(),
+ StaticChunkedOne ? S.getCombinedParForInDistCond() : S.getCond(),
+ StaticChunkedOne ? S.getDistInc() : S.getInc(),
+ [&S, LoopExit](CodeGenFunction &CGF) {
+ CGF.EmitOMPLoopBody(S, LoopExit);
+ CGF.EmitStopPoint(&S);
+ },
+ [](CodeGenFunction &) {});
EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd(),
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
S.getDirectiveKind());
};
OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
@@ -2351,11 +2403,10 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
LoopArguments, CGDispatchBounds);
}
if (isOpenMPSimdDirective(S.getDirectiveKind())) {
- EmitOMPSimdFinal(S,
- [IL, &S](CodeGenFunction &CGF) {
- return CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart()));
- });
+ EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
+ return CGF.Builder.CreateIsNotNull(
+ CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
+ });
}
EmitOMPReductionClauseFinal(
S, /*ReductionKind=*/isOpenMPSimdDirective(S.getDirectiveKind())
@@ -2365,17 +2416,17 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
emitPostUpdateForReductionClause(
*this, S, [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
});
// Emit final copy of the lastprivate variables if IsLastIter != 0.
if (HasLastprivateClause)
EmitOMPLastprivateClauseFinal(
S, isOpenMPSimdDirective(S.getDirectiveKind()),
- Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart())));
+ Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
}
EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
});
DoacrossCleanupScope.ForceCleanup();
// We're now done with the loop, so jump to the continuation block.
@@ -2432,7 +2483,7 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
}
void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
@@ -2450,7 +2501,7 @@ void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
}
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
@@ -2485,16 +2536,16 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.Builder.getInt32(0));
// Loop counter.
LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
- OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
+ OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
- OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue);
+ OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
// Generate condition for loop.
BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
- OK_Ordinary, S.getLocStart(), FPOptions());
+ OK_Ordinary, S.getBeginLoc(), FPOptions());
// Increment for loop counter.
UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
- S.getLocStart(), true);
+ S.getBeginLoc(), true);
auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
// Iterate through all sections and emit a switch construct:
// switch (IV) {
@@ -2509,7 +2560,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// .omp.sections.exit:
llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
llvm::SwitchInst *SwitchStmt =
- CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getLocStart()),
+ CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
ExitBB, CS == nullptr ? 1 : CS->size());
if (CS) {
unsigned CaseNumber = 0;
@@ -2537,13 +2588,15 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// initialization of firstprivate variables and post-update of lastprivate
// variables.
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
- CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
/*ForceSimpleCall=*/true);
}
CGF.EmitOMPPrivateClause(S, LoopScope);
HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
CGF.EmitOMPReductionClauseInit(S, LoopScope);
(void)LoopScope.Privatize();
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
+ CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
// Emit static non-chunked loop.
OpenMPScheduleTy ScheduleKind;
@@ -2552,20 +2605,20 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
/*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
LB.getAddress(), UB.getAddress(), ST.getAddress());
CGF.CGM.getOpenMPRuntime().emitForStaticInit(
- CGF, S.getLocStart(), S.getDirectiveKind(), ScheduleKind, StaticInit);
+ CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit);
// UB = min(UB, GlobalUB);
- llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
+ llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
// IV = LB;
- CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV);
+ CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
// while (idx <= UB) { BODY; ++idx; }
CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
[](CodeGenFunction &) {});
// Tell the runtime we are done.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd(),
+ CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
S.getDirectiveKind());
};
CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
@@ -2573,7 +2626,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// Emit post-update of the reduction variables if IsLastIter != 0.
emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
});
// Emit final copy of the lastprivate variables if IsLastIter != 0.
@@ -2581,7 +2634,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.EmitOMPLastprivateClauseFinal(
S, /*NoFinals=*/false,
CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart())));
+ CGF.EmitLoadOfScalar(IL, S.getBeginLoc())));
};
bool HasCancel = false;
@@ -2598,7 +2651,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
OMPD_unknown);
}
}
@@ -2610,7 +2663,7 @@ void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
}
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>()) {
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
OMPD_sections);
}
}
@@ -2652,7 +2705,7 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
};
{
OMPLexicalScope Scope(*this, S, OMPD_unknown);
- CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
+ CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(),
CopyprivateVars, DestExprs,
SrcExprs, AssignmentOps);
}
@@ -2660,7 +2713,7 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
// init or if no 'nowait' clause was specified and no 'copyprivate' clause).
if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
CGM.getOpenMPRuntime().emitBarrierCall(
- *this, S.getLocStart(),
+ *this, S.getBeginLoc(),
S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
}
}
@@ -2671,7 +2724,7 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
OMPLexicalScope Scope(*this, S, OMPD_unknown);
- CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart());
+ CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
}
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
@@ -2685,7 +2738,7 @@ void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitCriticalRegion(*this,
S.getDirectiveName().getAsString(),
- CodeGen, S.getLocStart(), Hint);
+ CodeGen, S.getBeginLoc(), Hint);
}
void CodeGenFunction::EmitOMPParallelForDirective(
@@ -2828,7 +2881,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
}
}
Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit(
- *this, S.getLocStart(), LHSs, RHSs, Data);
+ *this, S.getBeginLoc(), LHSs, RHSs, Data);
// Build list of dependences.
for (const auto *C : S.getClausesOfKind<OMPDependClause>())
for (const Expr *IRef : C->varlists())
@@ -2872,15 +2925,15 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
}
- CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
+ CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
CopyFn, CallArgs);
for (const auto &Pair : LastprivateDstsOrigs) {
const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
- DeclRefExpr DRE(
- const_cast<VarDecl *>(OrigVD),
- /*RefersToEnclosingVariableOrCapture=*/CGF.CapturedStmtInfo->lookup(
- OrigVD) != nullptr,
- Pair.second->getType(), VK_LValue, Pair.second->getExprLoc());
+ DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD),
+ /*RefersToEnclosingVariableOrCapture=*/
+ CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ Pair.second->getType(), VK_LValue,
+ Pair.second->getExprLoc());
Scope.addPrivate(Pair.first, [&CGF, &DRE]() {
return CGF.EmitLValue(&DRE).getAddress();
});
@@ -2902,11 +2955,11 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
RedCG.emitAggregateType(CGF, Cnt);
// FIXME: This must removed once the runtime library is fixed.
// Emit required threadprivate variables for
- // initilizer/combiner/finalizer.
- CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(),
+ // initializer/combiner/finalizer.
+ CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
RedCG, Cnt);
Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
- CGF, S.getLocStart(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
+ CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Replacement =
Address(CGF.EmitScalarConversion(
Replacement.getPointer(), CGF.getContext().VoidPtrTy,
@@ -2948,17 +3001,17 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
RedCG.emitSharedLValue(CGF, Cnt);
RedCG.emitAggregateType(CGF, Cnt);
// The taskgroup descriptor variable is always implicit firstprivate and
- // privatized already during procoessing of the firstprivates.
+ // privatized already during processing of the firstprivates.
// FIXME: This must removed once the runtime library is fixed.
// Emit required threadprivate variables for
- // initilizer/combiner/finalizer.
- CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(),
+ // initializer/combiner/finalizer.
+ CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
RedCG, Cnt);
llvm::Value *ReductionsPtr =
CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]),
TaskgroupDescriptors[Cnt]->getExprLoc());
Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
- CGF, S.getLocStart(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
+ CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Replacement = Address(
CGF.EmitScalarConversion(
Replacement.getPointer(), CGF.getContext().VoidPtrTy,
@@ -3049,14 +3102,14 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
getContext().VoidPtrTy, ArrSize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
BPVD = createImplicitFirstprivateForType(
- getContext(), Data, BaseAndPointersType, CD, S.getLocStart());
+ getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
PVD = createImplicitFirstprivateForType(
- getContext(), Data, BaseAndPointersType, CD, S.getLocStart());
+ getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
QualType SizesType = getContext().getConstantArrayType(
getContext().getSizeType(), ArrSize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
- S.getLocStart());
+ S.getBeginLoc());
TargetScope.addPrivate(
BPVD, [&InputInfo]() { return InputInfo.BasePointersArray; });
TargetScope.addPrivate(PVD,
@@ -3091,7 +3144,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
}
- CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
+ CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
CopyFn, CallArgs);
for (const auto &Pair : PrivatePtrs) {
Address Replacement(CGF.Builder.CreateLoad(Pair.second),
@@ -3122,7 +3175,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
SourceLocation());
- CGM.getOpenMPRuntime().emitTaskCall(*this, S.getLocStart(), S, OutlinedFn,
+ CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn,
SharedsTy, CapturedStruct, &IfCond, Data);
}
@@ -3149,7 +3202,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn,
const OMPTaskDataTy &Data) {
- CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getLocStart(), S, OutlinedFn,
+ CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
SharedsTy, CapturedStruct, IfCond,
Data);
};
@@ -3158,15 +3211,15 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
void CodeGenFunction::EmitOMPTaskyieldDirective(
const OMPTaskyieldDirective &S) {
- CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getLocStart());
+ CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc());
}
void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_barrier);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier);
}
void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
- CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getLocStart());
+ CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc());
}
void CodeGenFunction::EmitOMPTaskgroupDirective(
@@ -3195,7 +3248,7 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
}
}
llvm::Value *ReductionDesc =
- CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getLocStart(),
+ CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(),
LHSs, RHSs, Data);
const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
CGF.EmitVarDecl(*VD);
@@ -3205,7 +3258,7 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
OMPLexicalScope Scope(*this, S, OMPD_unknown);
- CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart());
+ CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
}
void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
@@ -3217,7 +3270,7 @@ void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
FlushClause->varlist_end());
return llvm::None;
}(),
- S.getLocStart());
+ S.getBeginLoc());
}
void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
@@ -3286,7 +3339,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
// on initialization of firstprivate variables and post-update of
// lastprivate variables.
CGM.getOpenMPRuntime().emitBarrierCall(
- *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
/*ForceSimpleCall=*/true);
}
EmitOMPPrivateClause(S, LoopScope);
@@ -3297,6 +3350,8 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
EmitOMPPrivateLoopCounters(S, LoopScope);
(void)LoopScope.Privatize();
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
+ CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
// Detect the distribute schedule kind and chunk.
llvm::Value *Chunk = nullptr;
@@ -3307,8 +3362,12 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
Chunk = EmitScalarExpr(Ch);
Chunk = EmitScalarConversion(Chunk, Ch->getType(),
S.getIterationVariable()->getType(),
- S.getLocStart());
+ S.getBeginLoc());
}
+ } else {
+ // Default behaviour for dist_schedule clause.
+ CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
+ *this, S, ScheduleKind, Chunk);
}
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
@@ -3321,14 +3380,19 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
// iteration space is divided into chunks that are approximately equal
// in size, and at most one chunk is distributed to each team of the
// league. The size of the chunks is unspecified in this case.
+ bool StaticChunked = RT.isStaticChunked(
+ ScheduleKind, /* Chunked */ Chunk != nullptr) &&
+ isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
if (RT.isStaticNonchunked(ScheduleKind,
- /* Chunked */ Chunk != nullptr)) {
+ /* Chunked */ Chunk != nullptr) ||
+ StaticChunked) {
if (isOpenMPSimdDirective(S.getDirectiveKind()))
EmitOMPSimdInit(S, /*IsMonotonic=*/true);
CGOpenMPRuntime::StaticRTInput StaticInit(
IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(),
- LB.getAddress(), UB.getAddress(), ST.getAddress());
- RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind,
+ LB.getAddress(), UB.getAddress(), ST.getAddress(),
+ StaticChunked ? Chunk : nullptr);
+ RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind,
StaticInit);
JumpDest LoopExit =
getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
@@ -3346,18 +3410,48 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
? S.getCombinedCond()
: S.getCond();
- // for distribute alone, codegen
- // while (idx <= UB) { BODY; ++idx; }
- // when combined with 'for' (e.g. as in 'distribute parallel for')
- // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; }
+ if (StaticChunked)
+ Cond = S.getCombinedDistCond();
+
+ // For static unchunked schedules generate:
+ //
+ // 1. For distribute alone, codegen
+ // while (idx <= UB) {
+ // BODY;
+ // ++idx;
+ // }
+ //
+ // 2. When combined with 'for' (e.g. as in 'distribute parallel for')
+ // while (idx <= UB) {
+ // <CodeGen rest of pragma>(LB, UB);
+ // idx += ST;
+ // }
+ //
+ // For static chunk one schedule generate:
+ //
+ // while (IV <= GlobalUB) {
+ // <CodeGen rest of pragma>(LB, UB);
+ // LB += ST;
+ // UB += ST;
+ // UB = min(UB, GlobalUB);
+ // IV = LB;
+ // }
+ //
EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), Cond, IncExpr,
[&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
CodeGenLoop(CGF, S, LoopExit);
},
- [](CodeGenFunction &) {});
+ [&S, StaticChunked](CodeGenFunction &CGF) {
+ if (StaticChunked) {
+ CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
+ CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
+ CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
+ CGF.EmitIgnoredExpr(S.getCombinedInit());
+ }
+ });
EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
- RT.emitForStaticFinish(*this, S.getLocStart(), S.getDirectiveKind());
+ RT.emitForStaticFinish(*this, S.getBeginLoc(), S.getDirectiveKind());
} else {
// Emit the outer loop, which requests its work chunk [LB..UB] from
// runtime and runs the inner loop to process it.
@@ -3370,38 +3464,25 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
if (isOpenMPSimdDirective(S.getDirectiveKind())) {
EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
});
}
if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
!isOpenMPParallelDirective(S.getDirectiveKind()) &&
!isOpenMPTeamsDirective(S.getDirectiveKind())) {
- OpenMPDirectiveKind ReductionKind = OMPD_unknown;
- if (isOpenMPParallelDirective(S.getDirectiveKind()) &&
- isOpenMPSimdDirective(S.getDirectiveKind())) {
- ReductionKind = OMPD_parallel_for_simd;
- } else if (isOpenMPParallelDirective(S.getDirectiveKind())) {
- ReductionKind = OMPD_parallel_for;
- } else if (isOpenMPSimdDirective(S.getDirectiveKind())) {
- ReductionKind = OMPD_simd;
- } else if (!isOpenMPTeamsDirective(S.getDirectiveKind()) &&
- S.hasClausesOfKind<OMPReductionClause>()) {
- llvm_unreachable(
- "No reduction clauses is allowed in distribute directive.");
- }
- EmitOMPReductionClauseFinal(S, ReductionKind);
+ EmitOMPReductionClauseFinal(S, OMPD_simd);
// Emit post-update of the reduction variables if IsLastIter != 0.
emitPostUpdateForReductionClause(
*this, S, [IL, &S](CodeGenFunction &CGF) {
return CGF.Builder.CreateIsNotNull(
- CGF.EmitLoadOfScalar(IL, S.getLocStart()));
+ CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
});
}
// Emit final copy of the lastprivate variables if IsLastIter != 0.
if (HasLastprivateClause) {
EmitOMPLastprivateClauseFinal(
S, /*NoFinals=*/false,
- Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart())));
+ Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
}
}
@@ -3448,7 +3529,7 @@ void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
llvm::SmallVector<llvm::Value *, 16> CapturedVars;
CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
llvm::Function *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS);
- CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getLocStart(),
+ CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
OutlinedFn, CapturedVars);
} else {
Action.Enter(CGF);
@@ -3456,7 +3537,7 @@ void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
}
};
OMPLexicalScope Scope(*this, S, OMPD_unknown);
- CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart(), !C);
+ CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C);
}
static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
@@ -3887,6 +3968,11 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
+ case OMPC_atomic_default_mem_order:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
@@ -3903,13 +3989,13 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
}
const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS))
- enterFullExpression(EWC);
+ if (const auto *FE = dyn_cast<FullExpr>(CS))
+ enterFullExpression(FE);
// Processing for statements under 'atomic capture'.
if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
for (const Stmt *C : Compound->body()) {
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(C))
- enterFullExpression(EWC);
+ if (const auto *FE = dyn_cast<FullExpr>(C))
+ enterFullExpression(FE);
}
}
@@ -3918,7 +4004,7 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
CGF.EmitStopPoint(CS);
emitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
S.getV(), S.getExpr(), S.getUpdateExpr(),
- S.isXLHSInRHSPart(), S.getLocStart());
+ S.isXLHSInRHSPart(), S.getBeginLoc());
};
OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
@@ -3986,6 +4072,16 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
IsOffloadEntry, CodeGen);
OMPLexicalScope Scope(CGF, S, OMPD_task);
+ auto &&SizeEmitter = [](CodeGenFunction &CGF, const OMPLoopDirective &D) {
+ OMPLoopScope(CGF, D);
+ // Emit calculation of the iterations count.
+ llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations());
+ NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty,
+ /*IsSigned=*/false);
+ return NumIterations;
+ };
+ CGM.getOpenMPRuntime().emitTargetNumIterationsCall(CGF, S, Device,
+ SizeEmitter);
CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device);
}
@@ -3996,6 +4092,8 @@ static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S,
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
CGF.EmitOMPPrivateClause(S, PrivateScope);
(void)PrivateScope.Privatize();
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
+ CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
}
@@ -4037,13 +4135,13 @@ static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
const Expr *ThreadLimit = TL ? TL->getThreadLimit() : nullptr;
CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
- S.getLocStart());
+ S.getBeginLoc());
}
OMPTeamsScope Scope(CGF, S);
llvm::SmallVector<llvm::Value *, 16> CapturedVars;
CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
- CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getLocStart(), OutlinedFn,
+ CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn,
CapturedVars);
}
@@ -4076,6 +4174,8 @@ static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
CGF.EmitOMPPrivateClause(S, PrivateScope);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
+ CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
CGF.EmitStmt(CS->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
};
@@ -4394,7 +4494,7 @@ void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
void CodeGenFunction::EmitOMPCancellationPointDirective(
const OMPCancellationPointDirective &S) {
- CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(),
+ CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(),
S.getCancelRegion());
}
@@ -4407,7 +4507,7 @@ void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
break;
}
}
- CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(), IfCond,
+ CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond,
S.getCancelRegion());
}
@@ -4634,6 +4734,8 @@ static void emitTargetParallelRegion(CodeGenFunction &CGF,
CGF.EmitOMPPrivateClause(S, PrivateScope);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
+ CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
// TODO: Add support for clauses.
CGF.EmitStmt(CS->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
@@ -4864,7 +4966,7 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
S, isOpenMPSimdDirective(S.getDirectiveKind()),
CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
- (*LIP)->getType(), S.getLocStart())));
+ (*LIP)->getType(), S.getBeginLoc())));
}
};
auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
@@ -4873,7 +4975,7 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
&Data](CodeGenFunction &CGF, PrePostActionTy &) {
OMPLoopScope PreInitScope(CGF, S);
- CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getLocStart(), S,
+ CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
OutlinedFn, SharedsTy,
CapturedStruct, IfCond, Data);
};
@@ -4891,7 +4993,7 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen,
Data);
},
- S.getLocStart());
+ S.getBeginLoc());
}
}
@@ -4934,16 +5036,37 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
if (isOpenMPSimdDirective(D.getDirectiveKind())) {
emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
} else {
+ OMPPrivateScope LoopGlobals(CGF);
if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
for (const Expr *E : LD->counters()) {
- if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
- cast<DeclRefExpr>(E)->getDecl())) {
+ const auto *VD = dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) {
+ LValue GlobLVal = CGF.EmitLValue(E);
+ LoopGlobals.addPrivate(
+ VD, [&GlobLVal]() { return GlobLVal.getAddress(); });
+ }
+ if (isa<OMPCapturedExprDecl>(VD)) {
// Emit only those that were not explicitly referenced in clauses.
if (!CGF.LocalDeclMap.count(VD))
CGF.EmitVarDecl(*VD);
}
}
+ for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
+ if (!C->getNumForLoops())
+ continue;
+ for (unsigned I = LD->getCollapsedNumber(),
+ E = C->getLoopNumIterations().size();
+ I < E; ++I) {
+ if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
+ cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) {
+ // Emit only those that were not explicitly referenced in clauses.
+ if (!CGF.LocalDeclMap.count(VD))
+ CGF.EmitVarDecl(*VD);
+ }
+ }
+ }
}
+ LoopGlobals.Privatize();
CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
}
};
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index b0a3a0bffa2e..fbd8146702a9 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -119,10 +119,10 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
llvm::ArrayType *ArrayType =
llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
+ unsigned Align = CGM.getDataLayout().getABITypeAlignment(CGM.Int8PtrTy);
- llvm::GlobalVariable *GV =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
- llvm::GlobalValue::ExternalLinkage);
+ llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
+ Name, ArrayType, llvm::GlobalValue::ExternalLinkage, Align);
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
return GV;
}
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index cc334637a831..bfb089ff908e 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -16,9 +16,9 @@
#include "CodeGenModule.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/Format.h"
#include "llvm/Transforms/Utils/Cloning.h"
@@ -128,7 +128,7 @@ static void resolveTopLevelMetadata(llvm::Function *Fn,
// they are referencing.
for (auto &BB : Fn->getBasicBlockList()) {
for (auto &I : BB) {
- if (auto *DII = dyn_cast<llvm::DbgInfoIntrinsic>(&I)) {
+ if (auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) {
auto *DILocal = DII->getVariable();
if (!DILocal->isResolved())
DILocal->resolve();
@@ -231,7 +231,7 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
// Build FunctionArgs.
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- QualType ThisType = MD->getThisType(getContext());
+ QualType ThisType = MD->getThisType();
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
QualType ResultType;
if (IsUnprototyped)
@@ -304,13 +304,13 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
CGM.ErrorUnsupported(
MD, "non-trivial argument copy for return-adjusting thunk");
}
- EmitMustTailThunk(MD, AdjustedThisPtr, CalleePtr);
+ EmitMustTailThunk(CurGD, AdjustedThisPtr, CalleePtr);
return;
}
// Start building CallArgs.
CallArgList CallArgs;
- QualType ThisType = MD->getThisType(getContext());
+ QualType ThisType = MD->getThisType();
CallArgs.add(RValue::get(AdjustedThisPtr), ThisType);
if (isa<CXXDestructorDecl>(MD))
@@ -350,13 +350,12 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
: FPT->getReturnType();
ReturnValueSlot Slot;
if (!ResultType->isVoidType() &&
- CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- !hasScalarEvaluationKind(CurFnInfo->getReturnType()))
+ CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect)
Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
// Now emit our call.
llvm::Instruction *CallOrInvoke;
- CGCallee Callee = CGCallee::forDirect(CalleePtr, MD);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, CurGD);
RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke);
// Consider return adjustment if we have ThunkInfo.
@@ -375,7 +374,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
FinishThunk();
}
-void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
+void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD,
llvm::Value *AdjustedThisPtr,
llvm::Value *CalleePtr) {
// Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery
@@ -412,7 +411,7 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
// Apply the standard set of call attributes.
unsigned CallingConv;
llvm::AttributeList Attrs;
- CGM.ConstructAttributeList(CalleePtr->getName(), *CurFnInfo, MD, Attrs,
+ CGM.ConstructAttributeList(CalleePtr->getName(), *CurFnInfo, GD, Attrs,
CallingConv, /*AttrOnCallSite=*/true);
Call->setAttributes(Attrs);
Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
@@ -756,9 +755,11 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
Linkage = llvm::GlobalVariable::InternalLinkage;
+ unsigned Align = CGM.getDataLayout().getABITypeAlignment(VTType);
+
// Create the variable that will hold the construction vtable.
llvm::GlobalVariable *VTable =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage);
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage, Align);
CGM.setGVProperties(VTable, RD);
// V-tables are always unnamed_addr.
@@ -1020,8 +1021,8 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
AP.second.AddressPointIndex));
// Sort the address points for determinism.
- llvm::sort(AddressPoints.begin(), AddressPoints.end(),
- [this](const AddressPoint &AP1, const AddressPoint &AP2) {
+ llvm::sort(AddressPoints, [this](const AddressPoint &AP1,
+ const AddressPoint &AP2) {
if (&AP1 == &AP2)
return false;
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 0dcbea423ad7..da8a8efb840b 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -562,7 +562,10 @@ public:
}
void setVolatile(bool flag) {
- Quals.setVolatile(flag);
+ if (flag)
+ Quals.addVolatile();
+ else
+ Quals.removeVolatile();
}
Qualifiers::ObjCLifetime getObjCLifetime() const {
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 2a0f4f0e83ec..29c6793c601e 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -102,4 +102,5 @@ add_clang_library(clangCodeGen
clangBasic
clangFrontend
clangLex
+ clangSerialization
)
diff --git a/lib/CodeGen/CodeGenABITypes.cpp b/lib/CodeGen/CodeGenABITypes.cpp
index c152291b15b9..27f5d53ffe11 100644
--- a/lib/CodeGen/CodeGenABITypes.cpp
+++ b/lib/CodeGen/CodeGenABITypes.cpp
@@ -20,7 +20,6 @@
#include "CGRecordLayout.h"
#include "CodeGenModule.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index d499364002f0..fd4506f2d197 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -127,6 +127,7 @@ namespace clang {
CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)) {
FrontendTimesIsEnabled = TimePasses;
+ llvm::TimePassesIsEnabled = TimePasses;
}
llvm::Module *getModule() const { return Gen->GetModule(); }
std::unique_ptr<llvm::Module> takeModule() {
@@ -548,12 +549,16 @@ const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc(
SourceLocation DILoc;
if (D.isLocationAvailable()) {
- D.getLocation(&Filename, &Line, &Column);
- const FileEntry *FE = FileMgr.getFile(Filename);
- if (FE && Line > 0) {
- // If -gcolumn-info was not used, Column will be 0. This upsets the
- // source manager, so pass 1 if Column is not set.
- DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
+ D.getLocation(Filename, Line, Column);
+ if (Line > 0) {
+ const FileEntry *FE = FileMgr.getFile(Filename);
+ if (!FE)
+ FE = FileMgr.getFile(D.getAbsolutePath());
+ if (FE) {
+ // If -gcolumn-info was not used, Column will be 0. This upsets the
+ // source manager, so pass 1 if Column is not set.
+ DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
+ }
}
BadDebugInfo = DILoc.isInvalid();
}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 3c582688e91e..1713e40c312b 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -28,10 +28,10 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
-#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Intrinsics.h"
@@ -430,10 +430,25 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
NormalCleanupDest = Address::invalid();
}
- // Add the required-vector-width attribute.
- if (LargestVectorWidth != 0)
- CurFn->addFnAttr("min-legal-vector-width",
- llvm::utostr(LargestVectorWidth));
+ // Scan function arguments for vector width.
+ for (llvm::Argument &A : CurFn->args())
+ if (auto *VT = dyn_cast<llvm::VectorType>(A.getType()))
+ LargestVectorWidth = std::max(LargestVectorWidth,
+ VT->getPrimitiveSizeInBits());
+
+ // Update vector width based on return type.
+ if (auto *VT = dyn_cast<llvm::VectorType>(CurFn->getReturnType()))
+ LargestVectorWidth = std::max(LargestVectorWidth,
+ VT->getPrimitiveSizeInBits());
+
+ // Add the required-vector-width attribute. This contains the max width from:
+ // 1. min-vector-width attribute used in the source program.
+ // 2. Any builtins used that have a vector width specified.
+ // 3. Values passed in and out of inline assembly.
+ // 4. Width of vector arguments and return types for this function.
+ // 5. Width of vector aguments and return types for functions called by this
+ // function.
+ CurFn->addFnAttr("min-legal-vector-width", llvm::utostr(LargestVectorWidth));
}
/// ShouldInstrumentFunction - Return true if the current function should be
@@ -772,9 +787,11 @@ static bool endsWithReturn(const Decl* F) {
return false;
}
-static void markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn) {
- Fn->addFnAttr("sanitize_thread_no_checking_at_run_time");
- Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
+void CodeGenFunction::markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn) {
+ if (SanOpts.has(SanitizerKind::Thread)) {
+ Fn->addFnAttr("sanitize_thread_no_checking_at_run_time");
+ Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
+ }
}
static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) {
@@ -866,7 +883,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
if (SanOpts.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
- if (SanOpts.has(SanitizerKind::Memory))
+ if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
if (SanOpts.has(SanitizerKind::SafeStack))
Fn->addFnAttr(llvm::Attribute::SafeStack);
@@ -887,10 +904,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
(OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) {
markAsIgnoreThreadCheckingAtRuntime(Fn);
}
- } else if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- IdentifierInfo *II = FD->getIdentifier();
- if (II && II->isStr("__destroy_helper_block_"))
- markAsIgnoreThreadCheckingAtRuntime(Fn);
}
}
@@ -903,21 +916,21 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
}
// Apply xray attributes to the function (as a string, for now)
- bool InstrumentXray = ShouldXRayInstrumentFunction() &&
- CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
- XRayInstrKind::Function);
- if (D && InstrumentXray) {
+ if (D) {
if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
- if (XRayAttr->alwaysXRayInstrument())
- Fn->addFnAttr("function-instrument", "xray-always");
- if (XRayAttr->neverXRayInstrument())
- Fn->addFnAttr("function-instrument", "xray-never");
- if (const auto *LogArgs = D->getAttr<XRayLogArgsAttr>()) {
- Fn->addFnAttr("xray-log-args",
- llvm::utostr(LogArgs->getArgumentCount()));
+ if (CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
+ XRayInstrKind::Function)) {
+ if (XRayAttr->alwaysXRayInstrument() && ShouldXRayInstrumentFunction())
+ Fn->addFnAttr("function-instrument", "xray-always");
+ if (XRayAttr->neverXRayInstrument())
+ Fn->addFnAttr("function-instrument", "xray-never");
+ if (const auto *LogArgs = D->getAttr<XRayLogArgsAttr>())
+ if (ShouldXRayInstrumentFunction())
+ Fn->addFnAttr("xray-log-args",
+ llvm::utostr(LogArgs->getArgumentCount()));
}
} else {
- if (!CGM.imbueXRayAttrs(Fn, Loc))
+ if (ShouldXRayInstrumentFunction() && !CGM.imbueXRayAttrs(Fn, Loc))
Fn->addFnAttr(
"xray-instruction-threshold",
llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold));
@@ -981,6 +994,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (FD->isMain())
Fn->addFnAttr(llvm::Attribute::NoRecurse);
+ // If a custom alignment is used, force realigning to this alignment on
+ // any main function which certainly will need it.
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ if ((FD->isMain() || FD->isMSVCRTEntryPoint()) &&
+ CGM.getCodeGenOpts().StackAlignment)
+ Fn->addFnAttr("stackrealign");
+
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
// Create a marker to make it easy to insert allocas into the entryblock
@@ -1053,9 +1073,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
// Count the implicit return.
if (!endsWithReturn(D))
++NumReturnExprs;
- } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- !hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
- // Indirect aggregate return; emit returned value directly into sret slot.
+ } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) {
+ // Indirect return; emit returned value directly into sret slot.
// This reduces code size, and affects correctness in C++.
auto AI = CurFn->arg_begin();
if (CurFnInfo->getReturnInfo().isSRetAfterThis())
@@ -1137,7 +1156,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (CXXABIThisValue) {
SanitizerSet SkippedChecks;
SkippedChecks.set(SanitizerKind::ObjectSize, true);
- QualType ThisTy = MD->getThisType(getContext());
+ QualType ThisTy = MD->getThisType();
// If this is the call operator of a lambda with no capture-default, it
// may have a static invoker function, which may call this operator with
@@ -1183,8 +1202,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
LargestVectorWidth = VecWidth->getVectorWidth();
}
-void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args,
- const Stmt *Body) {
+void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
incrementProfileCounter(Body);
if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
@@ -1238,7 +1256,7 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD,
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
if (MD && MD->isInstance()) {
if (CGM.getCXXABI().HasThisReturn(GD))
- ResTy = MD->getThisType(getContext());
+ ResTy = MD->getThisType();
else if (CGM.getCXXABI().hasMostDerivedReturn(GD))
ResTy = CGM.getContext().VoidPtrTy;
CGM.getCXXABI().buildThisParam(*this, Args);
@@ -1352,7 +1370,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// copy-constructors.
emitImplicitAssignmentOperatorBody(Args);
} else if (Body) {
- EmitFunctionBody(Args, Body);
+ EmitFunctionBody(Body);
} else
llvm_unreachable("no definition for emitted function");
@@ -1493,10 +1511,11 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
bool AllowLabels) {
// FIXME: Rename and handle conversion of other evaluatable things
// to bool.
- llvm::APSInt Int;
- if (!Cond->EvaluateAsInt(Int, getContext()))
+ Expr::EvalResult Result;
+ if (!Cond->EvaluateAsInt(Result, getContext()))
return false; // Not foldable, not integer or not fully evaluatable.
+ llvm::APSInt Int = Result.Val.getInt();
if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
return false; // Contains a label.
@@ -1681,7 +1700,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
// create metadata that specifies that the branch is unpredictable.
// Don't bother if not optimizing because that metadata would not be used.
llvm::MDNode *Unpredictable = nullptr;
- auto *Call = dyn_cast<CallExpr>(Cond);
+ auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts());
if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
@@ -2089,9 +2108,8 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
SanitizerScope SanScope(this);
llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType());
llvm::Constant *StaticArgs[] = {
- EmitCheckSourceLocation(size->getLocStart()),
- EmitCheckTypeDescriptor(size->getType())
- };
+ EmitCheckSourceLocation(size->getBeginLoc()),
+ EmitCheckTypeDescriptor(size->getType())};
EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero),
SanitizerKind::VLABound),
SanitizerHandler::VLABoundNotPositive, StaticArgs, Size);
@@ -2189,6 +2207,49 @@ void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
protection.Inst->eraseFromParent();
}
+void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue,
+ QualType Ty, SourceLocation Loc,
+ SourceLocation AssumptionLoc,
+ llvm::Value *Alignment,
+ llvm::Value *OffsetValue) {
+ llvm::Value *TheCheck;
+ llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption(
+ CGM.getDataLayout(), PtrValue, Alignment, OffsetValue, &TheCheck);
+ if (SanOpts.has(SanitizerKind::Alignment)) {
+ EmitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
+ OffsetValue, TheCheck, Assumption);
+ }
+}
+
+void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue,
+ QualType Ty, SourceLocation Loc,
+ SourceLocation AssumptionLoc,
+ unsigned Alignment,
+ llvm::Value *OffsetValue) {
+ llvm::Value *TheCheck;
+ llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption(
+ CGM.getDataLayout(), PtrValue, Alignment, OffsetValue, &TheCheck);
+ if (SanOpts.has(SanitizerKind::Alignment)) {
+ llvm::Value *AlignmentVal = llvm::ConstantInt::get(IntPtrTy, Alignment);
+ EmitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, AlignmentVal,
+ OffsetValue, TheCheck, Assumption);
+ }
+}
+
+void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue,
+ const Expr *E,
+ SourceLocation AssumptionLoc,
+ unsigned Alignment,
+ llvm::Value *OffsetValue) {
+ if (auto *CE = dyn_cast<CastExpr>(E))
+ E = CE->getSubExprAsWritten();
+ QualType Ty = E->getType();
+ SourceLocation Loc = E->getExprLoc();
+
+ EmitAlignmentAssumption(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
+ OffsetValue);
+}
+
llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Value *AnnotationFn,
llvm::Value *AnnotatedVal,
StringRef AnnotationStr,
@@ -2225,7 +2286,7 @@ Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
// annotation on the first field of a struct and annotation on the struct
// itself.
if (VTy != CGM.Int8PtrTy)
- V = Builder.Insert(new llvm::BitCastInst(V, CGM.Int8PtrTy));
+ V = Builder.CreateBitCast(V, CGM.Int8PtrTy);
V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation());
V = Builder.CreateBitCast(V, VTy);
}
@@ -2272,7 +2333,7 @@ static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures,
// Now build up the set of caller features and verify that all the required
// features are there.
llvm::StringMap<bool> CallerFeatureMap;
- CGM.getFunctionFeatureMap(CallerFeatureMap, FD);
+ CGM.getFunctionFeatureMap(CallerFeatureMap, GlobalDecl().getWithDecl(FD));
// If we have at least one of the features in the feature list return
// true, otherwise return false.
@@ -2280,14 +2341,13 @@ static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures,
ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef Feature) {
SmallVector<StringRef, 1> OrFeatures;
Feature.split(OrFeatures, '|');
- return std::any_of(OrFeatures.begin(), OrFeatures.end(),
- [&](StringRef Feature) {
- if (!CallerFeatureMap.lookup(Feature)) {
- FirstMissing = Feature.str();
- return false;
- }
- return true;
- });
+ return llvm::any_of(OrFeatures, [&](StringRef Feature) {
+ if (!CallerFeatureMap.lookup(Feature)) {
+ FirstMissing = Feature.str();
+ return false;
+ }
+ return true;
+ });
});
}
@@ -2319,7 +2379,7 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
return;
StringRef(FeatureList).split(ReqFeatures, ',');
if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
- CGM.getDiags().Report(E->getLocStart(), diag::err_builtin_needs_feature)
+ CGM.getDiags().Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
<< TargetDecl->getDeclName()
<< CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
@@ -2345,7 +2405,7 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
ReqFeatures.push_back(F.getKey());
}
if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
- CGM.getDiags().Report(E->getLocStart(), diag::err_function_needs_feature)
+ CGM.getDiags().Report(E->getBeginLoc(), diag::err_function_needs_feature)
<< FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
}
}
@@ -2359,91 +2419,81 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
CGM.getSanStats().create(IRB, SSK);
}
-llvm::Value *CodeGenFunction::FormResolverCondition(
- const TargetMultiVersionResolverOption &RO) {
- llvm::Value *TrueCondition = nullptr;
- if (!RO.ParsedAttribute.Architecture.empty())
- TrueCondition = EmitX86CpuIs(RO.ParsedAttribute.Architecture);
+llvm::Value *
+CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) {
+ llvm::Value *Condition = nullptr;
+
+ if (!RO.Conditions.Architecture.empty())
+ Condition = EmitX86CpuIs(RO.Conditions.Architecture);
- if (!RO.ParsedAttribute.Features.empty()) {
- SmallVector<StringRef, 8> FeatureList;
- llvm::for_each(RO.ParsedAttribute.Features,
- [&FeatureList](const std::string &Feature) {
- FeatureList.push_back(StringRef{Feature}.substr(1));
- });
- llvm::Value *FeatureCmp = EmitX86CpuSupports(FeatureList);
- TrueCondition = TrueCondition ? Builder.CreateAnd(TrueCondition, FeatureCmp)
- : FeatureCmp;
+ if (!RO.Conditions.Features.empty()) {
+ llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Conditions.Features);
+ Condition =
+ Condition ? Builder.CreateAnd(Condition, FeatureCond) : FeatureCond;
}
- return TrueCondition;
+ return Condition;
}
-void CodeGenFunction::EmitTargetMultiVersionResolver(
- llvm::Function *Resolver,
- ArrayRef<TargetMultiVersionResolverOption> Options) {
- assert((getContext().getTargetInfo().getTriple().getArch() ==
- llvm::Triple::x86 ||
- getContext().getTargetInfo().getTriple().getArch() ==
- llvm::Triple::x86_64) &&
- "Only implemented for x86 targets");
-
- // Main function's basic block.
- llvm::BasicBlock *CurBlock = createBasicBlock("entry", Resolver);
- Builder.SetInsertPoint(CurBlock);
- EmitX86CpuInit();
+static void CreateMultiVersionResolverReturn(CodeGenModule &CGM,
+ llvm::Function *Resolver,
+ CGBuilderTy &Builder,
+ llvm::Function *FuncToReturn,
+ bool SupportsIFunc) {
+ if (SupportsIFunc) {
+ Builder.CreateRet(FuncToReturn);
+ return;
+ }
- llvm::Function *DefaultFunc = nullptr;
- for (const TargetMultiVersionResolverOption &RO : Options) {
- Builder.SetInsertPoint(CurBlock);
- llvm::Value *TrueCondition = FormResolverCondition(RO);
+ llvm::SmallVector<llvm::Value *, 10> Args;
+ llvm::for_each(Resolver->args(),
+ [&](llvm::Argument &Arg) { Args.push_back(&Arg); });
- if (!TrueCondition) {
- DefaultFunc = RO.Function;
- } else {
- llvm::BasicBlock *RetBlock = createBasicBlock("ro_ret", Resolver);
- llvm::IRBuilder<> RetBuilder(RetBlock);
- RetBuilder.CreateRet(RO.Function);
- CurBlock = createBasicBlock("ro_else", Resolver);
- Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
- }
- }
+ llvm::CallInst *Result = Builder.CreateCall(FuncToReturn, Args);
+ Result->setTailCallKind(llvm::CallInst::TCK_MustTail);
- assert(DefaultFunc && "No default version?");
- // Emit return from the 'else-ist' block.
- Builder.SetInsertPoint(CurBlock);
- Builder.CreateRet(DefaultFunc);
+ if (Resolver->getReturnType()->isVoidTy())
+ Builder.CreateRetVoid();
+ else
+ Builder.CreateRet(Result);
}
-void CodeGenFunction::EmitCPUDispatchMultiVersionResolver(
- llvm::Function *Resolver,
- ArrayRef<CPUDispatchMultiVersionResolverOption> Options) {
+void CodeGenFunction::EmitMultiVersionResolver(
+ llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
assert((getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86 ||
getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86_64) &&
"Only implemented for x86 targets");
+ bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
+
// Main function's basic block.
llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
Builder.SetInsertPoint(CurBlock);
EmitX86CpuInit();
- for (const CPUDispatchMultiVersionResolverOption &RO : Options) {
+ for (const MultiVersionResolverOption &RO : Options) {
Builder.SetInsertPoint(CurBlock);
-
- // "generic" case should catch-all.
- if (RO.FeatureMask == 0) {
- Builder.CreateRet(RO.Function);
+ llvm::Value *Condition = FormResolverCondition(RO);
+
+ // The 'default' or 'generic' case.
+ if (!Condition) {
+ assert(&RO == Options.end() - 1 &&
+ "Default or Generic case must be last");
+ CreateMultiVersionResolverReturn(CGM, Resolver, Builder, RO.Function,
+ SupportsIFunc);
return;
}
+
llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
- llvm::IRBuilder<> RetBuilder(RetBlock);
- RetBuilder.CreateRet(RO.Function);
+ CGBuilderTy RetBuilder(*this, RetBlock);
+ CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, RO.Function,
+ SupportsIFunc);
CurBlock = createBasicBlock("resolver_else", Resolver);
- llvm::Value *TrueCondition = EmitX86CpuSupports(RO.FeatureMask);
- Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
+ Builder.CreateCondBr(Condition, RetBlock, CurBlock);
}
+ // If no generic/default, emit an unreachable.
Builder.SetInsertPoint(CurBlock);
llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
TrapCall->setDoesNotReturn();
@@ -2452,6 +2502,61 @@ void CodeGenFunction::EmitCPUDispatchMultiVersionResolver(
Builder.ClearInsertionPoint();
}
+// Loc - where the diagnostic will point, where in the source code this
+// alignment has failed.
+// SecondaryLoc - if present (will be present if sufficiently different from
+// Loc), the diagnostic will additionally point a "Note:" to this location.
+// It should be the location where the __attribute__((assume_aligned))
+// was written e.g.
+void CodeGenFunction::EmitAlignmentAssumptionCheck(
+ llvm::Value *Ptr, QualType Ty, SourceLocation Loc,
+ SourceLocation SecondaryLoc, llvm::Value *Alignment,
+ llvm::Value *OffsetValue, llvm::Value *TheCheck,
+ llvm::Instruction *Assumption) {
+ assert(Assumption && isa<llvm::CallInst>(Assumption) &&
+ cast<llvm::CallInst>(Assumption)->getCalledValue() ==
+ llvm::Intrinsic::getDeclaration(
+ Builder.GetInsertBlock()->getParent()->getParent(),
+ llvm::Intrinsic::assume) &&
+ "Assumption should be a call to llvm.assume().");
+ assert(&(Builder.GetInsertBlock()->back()) == Assumption &&
+ "Assumption should be the last instruction of the basic block, "
+ "since the basic block is still being generated.");
+
+ if (!SanOpts.has(SanitizerKind::Alignment))
+ return;
+
+ // Don't check pointers to volatile data. The behavior here is implementation-
+ // defined.
+ if (Ty->getPointeeType().isVolatileQualified())
+ return;
+
+ // We need to temorairly remove the assumption so we can insert the
+ // sanitizer check before it, else the check will be dropped by optimizations.
+ Assumption->removeFromParent();
+
+ {
+ SanitizerScope SanScope(this);
+
+ if (!OffsetValue)
+ OffsetValue = Builder.getInt1(0); // no offset.
+
+ llvm::Constant *StaticData[] = {EmitCheckSourceLocation(Loc),
+ EmitCheckSourceLocation(SecondaryLoc),
+ EmitCheckTypeDescriptor(Ty)};
+ llvm::Value *DynamicData[] = {EmitCheckValue(Ptr),
+ EmitCheckValue(Alignment),
+ EmitCheckValue(OffsetValue)};
+ EmitCheck({std::make_pair(TheCheck, SanitizerKind::Alignment)},
+ SanitizerHandler::AlignmentAssumption, StaticData, DynamicData);
+ }
+
+ // We are now in the (new, empty) "cont" basic block.
+ // Reintroduce the assumption.
+ Builder.Insert(Assumption);
+ // FIXME: Assumption still has it's original basic block as it's Parent.
+}
+
llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
if (CGDebugInfo *DI = getDebugInfo())
return DI->SourceLocToDebugLoc(Location);
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index f9e284232972..89cb850ab1b1 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -29,9 +29,9 @@
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
@@ -131,6 +131,7 @@ enum TypeEvaluationKind {
SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \
SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \
SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \
+ SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0) \
SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0)
enum SanitizerHandler {
@@ -470,7 +471,7 @@ public:
/// potentially set the return value.
bool SawAsmBlock = false;
- const FunctionDecl *CurSEHParent = nullptr;
+ const NamedDecl *CurSEHParent = nullptr;
/// True if the current function is an outlined SEH helper. This can be a
/// finally block or filter expression.
@@ -1197,6 +1198,8 @@ public:
private:
CGDebugInfo *DebugInfo;
+ /// Used to create unique names for artificial VLA size debug info variables.
+ unsigned VLAExprCounter = 0;
bool DisableDebugInfo = false;
/// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid
@@ -1746,6 +1749,9 @@ public:
bool IsLambdaConversionToBlock,
bool BuildGlobalBlock);
+ /// Check if \p T is a C++ class that has a destructor that can throw.
+ static bool cxxDestructorCanThrow(QualType T);
+
llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo);
llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo);
llvm::Constant *GenerateObjCAtomicSetterCopyHelperFunction(
@@ -1754,7 +1760,8 @@ public:
const ObjCPropertyImplDecl *PID);
llvm::Value *EmitBlockCopyAndAutorelease(llvm::Value *Block, QualType Ty);
- void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags);
+ void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags,
+ bool CanThrow);
class AutoVarEmission;
@@ -1777,13 +1784,13 @@ public:
/// \param LoadBlockVarAddr Indicates whether we need to emit a load from
/// \p Addr to get the address of the __block structure.
void enterByrefCleanup(CleanupKind Kind, Address Addr, BlockFieldFlags Flags,
- bool LoadBlockVarAddr);
+ bool LoadBlockVarAddr, bool CanThrow);
void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum,
llvm::Value *ptr);
Address LoadBlockStruct();
- Address GetAddrOfBlockDecl(const VarDecl *var, bool ByRef);
+ Address GetAddrOfBlockDecl(const VarDecl *var);
/// BuildBlockByrefAddress - Computes the location of the
/// data in a variable which is declared as __block.
@@ -1800,6 +1807,11 @@ public:
void GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo);
+
+ /// Annotate the function with an attribute that disables TSan checking at
+ /// runtime.
+ void markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn);
+
/// Emit code for the start of a function.
/// \param Loc The location to be associated with the function.
/// \param StartLoc The location of the function body.
@@ -1816,7 +1828,7 @@ public:
void EmitConstructorBody(FunctionArgList &Args);
void EmitDestructorBody(FunctionArgList &Args);
void emitImplicitAssignmentOperatorBody(FunctionArgList &Args);
- void EmitFunctionBody(FunctionArgList &Args, const Stmt *Body);
+ void EmitFunctionBody(const Stmt *Body);
void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S);
void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator,
@@ -1845,7 +1857,7 @@ public:
void FinishThunk();
/// Emit a musttail call for a thunk with a potentially adjusted this pointer.
- void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr,
+ void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr,
llvm::Value *Callee);
/// Generate a thunk for the given method.
@@ -2622,12 +2634,6 @@ public:
ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre);
- void EmitAlignmentAssumption(llvm::Value *PtrValue, unsigned Alignment,
- llvm::Value *OffsetValue = nullptr) {
- Builder.CreateAlignmentAssumption(CGM.getDataLayout(), PtrValue, Alignment,
- OffsetValue);
- }
-
/// Converts Location to a DebugLoc, if debug information is enabled.
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location);
@@ -2674,8 +2680,9 @@ public:
llvm::Value *NRVOFlag;
- /// True if the variable is a __block variable.
- bool IsByRef;
+ /// True if the variable is a __block variable that is captured by an
+ /// escaping block.
+ bool IsEscapingByRef;
/// True if the variable is of aggregate type and has a constant
/// initializer.
@@ -2695,7 +2702,7 @@ public:
AutoVarEmission(const VarDecl &variable)
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
- IsByRef(false), IsConstantAggregate(false),
+ IsEscapingByRef(false), IsConstantAggregate(false),
SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {}
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
@@ -2725,7 +2732,7 @@ public:
/// Note that this does not chase the forwarding pointer for
/// __block decls.
Address getObjectAddress(CodeGenFunction &CGF) const {
- if (!IsByRef) return Addr;
+ if (!IsEscapingByRef) return Addr;
return CGF.emitBlockByrefAddress(Addr, Variable, /*forward*/ false);
}
@@ -2790,11 +2797,27 @@ public:
PeepholeProtection protectFromPeepholes(RValue rvalue);
void unprotectFromPeepholes(PeepholeProtection protection);
- void EmitAlignmentAssumption(llvm::Value *PtrValue, llvm::Value *Alignment,
- llvm::Value *OffsetValue = nullptr) {
- Builder.CreateAlignmentAssumption(CGM.getDataLayout(), PtrValue, Alignment,
- OffsetValue);
- }
+ void EmitAlignmentAssumptionCheck(llvm::Value *Ptr, QualType Ty,
+ SourceLocation Loc,
+ SourceLocation AssumptionLoc,
+ llvm::Value *Alignment,
+ llvm::Value *OffsetValue,
+ llvm::Value *TheCheck,
+ llvm::Instruction *Assumption);
+
+ void EmitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty,
+ SourceLocation Loc, SourceLocation AssumptionLoc,
+ llvm::Value *Alignment,
+ llvm::Value *OffsetValue = nullptr);
+
+ void EmitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty,
+ SourceLocation Loc, SourceLocation AssumptionLoc,
+ unsigned Alignment,
+ llvm::Value *OffsetValue = nullptr);
+
+ void EmitAlignmentAssumption(llvm::Value *PtrValue, const Expr *E,
+ SourceLocation AssumptionLoc, unsigned Alignment,
+ llvm::Value *OffsetValue = nullptr);
//===--------------------------------------------------------------------===//
// Statement Emission
@@ -2878,6 +2901,8 @@ public:
void EnterSEHTryStmt(const SEHTryStmt &S);
void ExitSEHTryStmt(const SEHTryStmt &S);
+ void pushSEHCleanup(CleanupKind kind,
+ llvm::Function *FinallyFunc);
void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter,
const Stmt *OutlinedStmt);
@@ -3512,6 +3537,7 @@ public:
ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
ConstantEmission tryEmitAsConstant(const MemberExpr *ME);
+ llvm::Value *emitScalarConstant(const ConstantEmission &Constant, Expr *E);
RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
AggValueSlot slot = AggValueSlot::ignored());
@@ -3603,6 +3629,19 @@ public:
CXXDtorType Type,
const CXXRecordDecl *RD);
+ // Return the copy constructor name with the prefix "__copy_constructor_"
+ // removed.
+ static std::string getNonTrivialCopyConstructorStr(QualType QT,
+ CharUnits Alignment,
+ bool IsVolatile,
+ ASTContext &Ctx);
+
+ // Return the destructor name with the prefix "__destructor_" removed.
+ static std::string getNonTrivialDestructorStr(QualType QT,
+ CharUnits Alignment,
+ bool IsVolatile,
+ ASTContext &Ctx);
+
// These functions emit calls to the special functions of non-trivial C
// structs.
void defaultInitNonTrivialCStructVar(LValue Dst);
@@ -3653,9 +3692,10 @@ public:
RValue EmitNVPTXDevicePrintfCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue);
- RValue EmitBuiltinExpr(const FunctionDecl *FD,
- unsigned BuiltinID, const CallExpr *E,
- ReturnValueSlot ReturnValue);
+ RValue EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
+ const CallExpr *E, ReturnValueSlot ReturnValue);
+
+ RValue emitRotate(const CallExpr *E, bool IsRotateRight);
/// Emit IR for __builtin_os_log_format.
RValue emitBuiltinOSLogFormat(const CallExpr &E);
@@ -3769,6 +3809,11 @@ public:
llvm::Value *EmitARCRetainAutoreleasedReturnValue(llvm::Value *value);
llvm::Value *EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value);
+ llvm::Value *EmitObjCAutorelease(llvm::Value *value, llvm::Type *returnType);
+ llvm::Value *EmitObjCRetainNonBlock(llvm::Value *value,
+ llvm::Type *returnType);
+ void EmitObjCRelease(llvm::Value *value, ARCPreciseLifetime_t precise);
+
std::pair<LValue,llvm::Value*>
EmitARCStoreAutoreleasing(const BinaryOperator *e);
std::pair<LValue,llvm::Value*>
@@ -3776,6 +3821,10 @@ public:
std::pair<LValue,llvm::Value*>
EmitARCStoreUnsafeUnretained(const BinaryOperator *e, bool ignored);
+ llvm::Value *EmitObjCAlloc(llvm::Value *value,
+ llvm::Type *returnType);
+ llvm::Value *EmitObjCAllocWithZone(llvm::Value *value,
+ llvm::Type *returnType);
llvm::Value *EmitObjCThrowOperand(const Expr *expr);
llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr);
llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr);
@@ -3865,6 +3914,8 @@ public:
AddInitializerToStaticVarDecl(const VarDecl &D,
llvm::GlobalVariable *GV);
+ // Emit an @llvm.invariant.start call for the given memory region.
+ void EmitInvariantStart(llvm::Constant *Addr, CharUnits Size);
/// EmitCXXGlobalVarDeclInit - Create the initializer for a C++
/// variable with global storage.
@@ -3900,9 +3951,10 @@ public:
/// GenerateCXXGlobalInitFunc - Generates code for initializing global
/// variables.
- void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
- ArrayRef<llvm::Function *> CXXThreadLocals,
- Address Guard = Address::invalid());
+ void
+ GenerateCXXGlobalInitFunc(llvm::Function *Fn,
+ ArrayRef<llvm::Function *> CXXThreadLocals,
+ ConstantAddress Guard = ConstantAddress::invalid());
/// GenerateCXXGlobalDtorsFunc - Generates code for destroying global
/// variables.
@@ -3920,11 +3972,13 @@ public:
void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
- void enterFullExpression(const ExprWithCleanups *E) {
- if (E->getNumObjects() == 0) return;
+ void enterFullExpression(const FullExpr *E) {
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
+ if (EWC->getNumObjects() == 0)
+ return;
enterNonTrivialFullExpression(E);
}
- void enterNonTrivialFullExpression(const ExprWithCleanups *E);
+ void enterNonTrivialFullExpression(const FullExpr *E);
void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true);
@@ -4245,47 +4299,29 @@ public:
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK);
- struct TargetMultiVersionResolverOption {
+ struct MultiVersionResolverOption {
llvm::Function *Function;
- TargetAttr::ParsedTargetAttr ParsedAttribute;
- unsigned Priority;
- TargetMultiVersionResolverOption(
- const TargetInfo &TargInfo, llvm::Function *F,
- const clang::TargetAttr::ParsedTargetAttr &PT)
- : Function(F), ParsedAttribute(PT), Priority(0u) {
- for (StringRef Feat : PT.Features)
- Priority = std::max(Priority,
- TargInfo.multiVersionSortPriority(Feat.substr(1)));
-
- if (!PT.Architecture.empty())
- Priority = std::max(Priority,
- TargInfo.multiVersionSortPriority(PT.Architecture));
- }
-
- bool operator>(const TargetMultiVersionResolverOption &Other) const {
- return Priority > Other.Priority;
- }
+ FunctionDecl *FD;
+ struct Conds {
+ StringRef Architecture;
+ llvm::SmallVector<StringRef, 8> Features;
+
+ Conds(StringRef Arch, ArrayRef<StringRef> Feats)
+ : Architecture(Arch), Features(Feats.begin(), Feats.end()) {}
+ } Conditions;
+
+ MultiVersionResolverOption(llvm::Function *F, StringRef Arch,
+ ArrayRef<StringRef> Feats)
+ : Function(F), Conditions(Arch, Feats) {}
};
- void EmitTargetMultiVersionResolver(
- llvm::Function *Resolver,
- ArrayRef<TargetMultiVersionResolverOption> Options);
- struct CPUDispatchMultiVersionResolverOption {
- llvm::Function *Function;
- // Note: EmitX86CPUSupports only has 32 bits available, so we store the mask
- // as 32 bits here. When 64-bit support is added to __builtin_cpu_supports,
- // this can be extended to 64 bits.
- uint32_t FeatureMask;
- CPUDispatchMultiVersionResolverOption(llvm::Function *F, uint64_t Mask)
- : Function(F), FeatureMask(static_cast<uint32_t>(Mask)) {}
- bool operator>(const CPUDispatchMultiVersionResolverOption &Other) const {
- return FeatureMask > Other.FeatureMask;
- }
- };
- void EmitCPUDispatchMultiVersionResolver(
- llvm::Function *Resolver,
- ArrayRef<CPUDispatchMultiVersionResolverOption> Options);
- static uint32_t GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
+ // Emits the body of a multiversion function's resolver. Assumes that the
+ // options are already sorted in the proper order, with the 'default' option
+ // last (if it exists).
+ void EmitMultiVersionResolver(llvm::Function *Resolver,
+ ArrayRef<MultiVersionResolverOption> Options);
+
+ static uint64_t GetX86CpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
private:
QualType getVarArgType(const Expr *Arg);
@@ -4302,10 +4338,9 @@ private:
llvm::Value *EmitX86CpuIs(StringRef CPUStr);
llvm::Value *EmitX86CpuSupports(const CallExpr *E);
llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs);
- llvm::Value *EmitX86CpuSupports(uint32_t Mask);
+ llvm::Value *EmitX86CpuSupports(uint64_t Mask);
llvm::Value *EmitX86CpuInit();
- llvm::Value *
- FormResolverCondition(const TargetMultiVersionResolverOption &RO);
+ llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO);
};
inline DominatingLLVMValue::saved_type
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 8c5e0df0969b..244738042cef 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -36,14 +36,15 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
-#include "clang/Frontend/CodeGenOptions.h"
-#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/CallSite.h"
@@ -53,6 +54,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MD5.h"
@@ -124,7 +126,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
- if (LangOpts.ObjC1)
+ if (LangOpts.ObjC)
createObjCRuntime();
if (LangOpts.OpenCL)
createOpenCLRuntime();
@@ -147,12 +149,12 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
Block.GlobalUniqueCount = 0;
- if (C.getLangOpts().ObjC1)
+ if (C.getLangOpts().ObjC)
ObjCData.reset(new ObjCEntrypoints());
if (CodeGenOpts.hasProfileClangUse()) {
auto ReaderOrErr = llvm::IndexedInstrProfReader::create(
- CodeGenOpts.ProfileInstrumentUsePath);
+ CodeGenOpts.ProfileInstrumentUsePath, CodeGenOpts.ProfileRemappingFile);
if (auto E = ReaderOrErr.takeError()) {
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Could not read profile %0: %1");
@@ -320,8 +322,6 @@ void CodeGenModule::checkAliases() {
assert(FTy);
if (!FTy->getReturnType()->isPointerTy())
Diags.Report(Location, diag::err_ifunc_resolver_return);
- if (FTy->getNumParams())
- Diags.Report(Location, diag::err_ifunc_resolver_params);
}
llvm::Constant *Aliasee = Alias->getIndirectSymbol();
@@ -458,9 +458,12 @@ void CodeGenModule::Release() {
// Indicate that we want CodeView in the metadata.
getModule().addModuleFlag(llvm::Module::Warning, "CodeView", 1);
}
+ if (CodeGenOpts.CodeViewGHash) {
+ getModule().addModuleFlag(llvm::Module::Warning, "CodeViewGHash", 1);
+ }
if (CodeGenOpts.ControlFlowGuard) {
// We want function ID tables for Control Flow Guard.
- getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1);
+ getModule().addModuleFlag(llvm::Module::Warning, "cfguardtable", 1);
}
if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) {
// We don't support LTO with 2 with different StrictVTablePointers
@@ -556,6 +559,20 @@ void CodeGenModule::Release() {
getModule().setPIELevel(static_cast<llvm::PIELevel::Level>(PLevel));
}
+ if (getCodeGenOpts().CodeModel.size() > 0) {
+ unsigned CM = llvm::StringSwitch<unsigned>(getCodeGenOpts().CodeModel)
+ .Case("tiny", llvm::CodeModel::Tiny)
+ .Case("small", llvm::CodeModel::Small)
+ .Case("kernel", llvm::CodeModel::Kernel)
+ .Case("medium", llvm::CodeModel::Medium)
+ .Case("large", llvm::CodeModel::Large)
+ .Default(~0u);
+ if (CM != ~0u) {
+ llvm::CodeModel::Model codeModel = static_cast<llvm::CodeModel::Model>(CM);
+ getModule().setCodeModel(codeModel);
+ }
+ }
+
if (CodeGenOpts.NoPLT)
getModule().setRtLibUseGOT();
@@ -573,6 +590,9 @@ void CodeGenModule::Release() {
if (getCodeGenOpts().EmitVersionIdentMetadata)
EmitVersionIdentMetadata();
+ if (!getCodeGenOpts().RecordCommandLine.empty())
+ EmitCommandLineMetadata();
+
EmitTargetMetadata();
}
@@ -683,8 +703,8 @@ void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type) {
unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"cannot compile this %0 yet");
std::string Msg = Type;
- getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID)
- << Msg << S->getSourceRange();
+ getDiags().Report(Context.getFullLoc(S->getBeginLoc()), DiagID)
+ << Msg << S->getSourceRange();
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
@@ -730,6 +750,14 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
return false;
const llvm::Triple &TT = CGM.getTriple();
+ if (TT.isWindowsGNUEnvironment()) {
+ // In MinGW, variables without DLLImport can still be automatically
+ // imported from a DLL by the linker; don't mark variables that
+ // potentially could come from another DLL as DSO local.
+ if (GV->isDeclarationForLinker() && isa<llvm::GlobalVariable>(GV) &&
+ !GV->isThreadLocal())
+ return false;
+ }
// Every other GV is local on COFF.
// Make an exception for windows OS in the triple: Some firmware builds use
// *-win32-macho triples. This (accidentally?) produced windows relocations
@@ -869,11 +897,13 @@ static std::string getCPUSpecificMangling(const CodeGenModule &CGM,
static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
const CPUSpecificAttr *Attr,
+ unsigned CPUIndex,
raw_ostream &Out) {
- // cpu_specific gets the current name, dispatch gets the resolver.
+ // cpu_specific gets the current name, dispatch gets the resolver if IFunc is
+ // supported.
if (Attr)
- Out << getCPUSpecificMangling(CGM, Attr->getCurCPUName()->getName());
- else
+ Out << getCPUSpecificMangling(CGM, Attr->getCPUName(CPUIndex)->getName());
+ else if (CGM.getTarget().supportsIFunc())
Out << ".resolver";
}
@@ -939,11 +969,19 @@ static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD,
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
if (FD->isMultiVersion() && !OmitMultiVersionMangling) {
- if (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())
- AppendCPUSpecificCPUDispatchMangling(
- CGM, FD->getAttr<CPUSpecificAttr>(), Out);
- else
+ switch (FD->getMultiVersionKind()) {
+ case MultiVersionKind::CPUDispatch:
+ case MultiVersionKind::CPUSpecific:
+ AppendCPUSpecificCPUDispatchMangling(CGM,
+ FD->getAttr<CPUSpecificAttr>(),
+ GD.getMultiVersionIndex(), Out);
+ break;
+ case MultiVersionKind::Target:
AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
+ break;
+ case MultiVersionKind::None:
+ llvm_unreachable("None multiversion type isn't valid here");
+ }
}
return Out.str();
@@ -968,8 +1006,10 @@ void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
"Other GD should now be a multiversioned function");
// OtherFD is the version of this function that was mangled BEFORE
// becoming a MultiVersion function. It potentially needs to be updated.
- const FunctionDecl *OtherFD =
- OtherGD.getCanonicalDecl().getDecl()->getAsFunction();
+ const FunctionDecl *OtherFD = OtherGD.getCanonicalDecl()
+ .getDecl()
+ ->getAsFunction()
+ ->getMostRecentDecl();
std::string OtherName = getMangledNameImpl(*this, OtherGD, OtherFD);
// This is so that if the initial version was already the 'default'
// version, we don't try to update it.
@@ -1001,26 +1041,6 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
}
}
- const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl());
- // Since CPUSpecific can require multiple emits per decl, store the manglings
- // separately.
- if (FD &&
- (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())) {
- const auto *SD = FD->getAttr<CPUSpecificAttr>();
-
- std::pair<GlobalDecl, unsigned> SpecCanonicalGD{
- CanonicalGD,
- SD ? SD->ActiveArgIndex : std::numeric_limits<unsigned>::max()};
-
- auto FoundName = CPUSpecificMangledDeclNames.find(SpecCanonicalGD);
- if (FoundName != CPUSpecificMangledDeclNames.end())
- return FoundName->second;
-
- auto Result = CPUSpecificManglings.insert(
- std::make_pair(getMangledNameImpl(*this, GD, FD), SpecCanonicalGD));
- return CPUSpecificMangledDeclNames[SpecCanonicalGD] = Result.first->first();
- }
-
auto FoundName = MangledDeclNames.find(CanonicalGD);
if (FoundName != MangledDeclNames.end())
return FoundName->second;
@@ -1082,11 +1102,12 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
// Ctor function type is void()*.
llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false);
- llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
+ llvm::Type *CtorPFTy = llvm::PointerType::get(CtorFTy,
+ TheModule.getDataLayout().getProgramAddressSpace());
// Get the type of a ctor entry, { i32, void ()*, i8* }.
llvm::StructType *CtorStructTy = llvm::StructType::get(
- Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy);
+ Int32Ty, CtorPFTy, VoidPtrTy);
// Construct the constructor and destructor arrays.
ConstantInitBuilder builder(*this);
@@ -1142,12 +1163,12 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
}
-void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
+void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl GD,
const CGFunctionInfo &Info,
llvm::Function *F) {
unsigned CallingConv;
llvm::AttributeList PAL;
- ConstructAttributeList(F->getName(), Info, D, PAL, CallingConv, false);
+ ConstructAttributeList(F->getName(), Info, GD, PAL, CallingConv, false);
F->setAttributes(PAL);
F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
}
@@ -1277,9 +1298,19 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
// Otherwise, propagate the inline hint attribute and potentially use its
// absence to mark things as noinline.
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (any_of(FD->redecls(), [&](const FunctionDecl *Redecl) {
- return Redecl->isInlineSpecified();
- })) {
+ // Search function and template pattern redeclarations for inline.
+ auto CheckForInline = [](const FunctionDecl *FD) {
+ auto CheckRedeclForInline = [](const FunctionDecl *Redecl) {
+ return Redecl->isInlineSpecified();
+ };
+ if (any_of(FD->redecls(), CheckRedeclForInline))
+ return true;
+ const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
+ if (!Pattern)
+ return false;
+ return any_of(Pattern->redecls(), CheckRedeclForInline);
+ };
+ if (CheckForInline(FD)) {
B.addAttribute(llvm::Attribute::InlineHint);
} else if (CodeGenOpts.getInlining() ==
CodeGenOptions::OnlyHintInlining &&
@@ -1350,23 +1381,30 @@ void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
if (D && D->hasAttr<UsedAttr>())
addUsedGlobal(GV);
+
+ if (CodeGenOpts.KeepStaticConsts && D && isa<VarDecl>(D)) {
+ const auto *VD = cast<VarDecl>(D);
+ if (VD->getType().isConstQualified() &&
+ VD->getStorageDuration() == SD_Static)
+ addUsedGlobal(GV);
+ }
}
-bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D,
+bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
llvm::AttrBuilder &Attrs) {
// Add target-cpu and target-features attributes to functions. If
// we have a decl for the function and it has a target attribute then
// parse that and add it to the feature set.
StringRef TargetCPU = getTarget().getTargetOpts().CPU;
std::vector<std::string> Features;
- const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
+ const auto *FD = dyn_cast_or_null<FunctionDecl>(GD.getDecl());
FD = FD ? FD->getMostRecentDecl() : FD;
const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr;
const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr;
bool AddedAttr = false;
if (TD || SD) {
llvm::StringMap<bool> FeatureMap;
- getFunctionFeatureMap(FeatureMap, FD);
+ getFunctionFeatureMap(FeatureMap, GD);
// Produce the canonical string for this set of features.
for (const llvm::StringMap<bool>::value_type &Entry : FeatureMap)
@@ -1393,7 +1431,7 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D,
AddedAttr = true;
}
if (!Features.empty()) {
- llvm::sort(Features.begin(), Features.end());
+ llvm::sort(Features);
Attrs.addAttribute("target-features", llvm::join(Features, ","));
AddedAttr = true;
}
@@ -1422,7 +1460,7 @@ void CodeGenModule::setNonAliasAttributes(GlobalDecl GD,
F->addFnAttr("implicit-section-name", SA->getName());
llvm::AttrBuilder Attrs;
- if (GetCPUAndFeaturesAttributes(D, Attrs)) {
+ if (GetCPUAndFeaturesAttributes(GD, Attrs)) {
// We know that GetCPUAndFeaturesAttributes will always have the
// newest set, since it has the newest possible FunctionDecl, so the
// new ones should replace the old.
@@ -1445,7 +1483,7 @@ void CodeGenModule::SetInternalFunctionAttributes(GlobalDecl GD,
llvm::Function *F,
const CGFunctionInfo &FI) {
const Decl *D = GD.getDecl();
- SetLLVMFunctionAttributes(D, FI, F);
+ SetLLVMFunctionAttributes(GD, FI, F);
SetLLVMFunctionAttributesForDefinition(D, F);
F->setLinkage(llvm::Function::InternalLinkage);
@@ -1507,7 +1545,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
const auto *FD = cast<FunctionDecl>(GD.getDecl());
if (!IsIncompleteFunction) {
- SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
+ SetLLVMFunctionAttributes(GD, getTypes().arrangeGlobalDeclaration(GD), F);
// Setup target-specific attributes.
if (F->isDeclaration())
getTargetCodeGenInfo().setTargetAttributes(FD, F, *this);
@@ -1654,6 +1692,8 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
// Add linker options to link against the libraries/frameworks
// described by this module.
llvm::LLVMContext &Context = CGM.getLLVMContext();
+ bool IsELF = CGM.getTarget().getTriple().isOSBinFormatELF();
+ bool IsPS4 = CGM.getTarget().getTriple().isPS4();
// For modules that use export_as for linking, use that module
// name instead.
@@ -1673,11 +1713,19 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
}
// Link against a library.
- llvm::SmallString<24> Opt;
- CGM.getTargetCodeGenInfo().getDependentLibraryOption(
- Mod->LinkLibraries[I-1].Library, Opt);
- auto *OptString = llvm::MDString::get(Context, Opt);
- Metadata.push_back(llvm::MDNode::get(Context, OptString));
+ if (IsELF && !IsPS4) {
+ llvm::Metadata *Args[2] = {
+ llvm::MDString::get(Context, "lib"),
+ llvm::MDString::get(Context, Mod->LinkLibraries[I - 1].Library),
+ };
+ Metadata.push_back(llvm::MDNode::get(Context, Args));
+ } else {
+ llvm::SmallString<24> Opt;
+ CGM.getTargetCodeGenInfo().getDependentLibraryOption(
+ Mod->LinkLibraries[I - 1].Library, Opt);
+ auto *OptString = llvm::MDString::get(Context, Opt);
+ Metadata.push_back(llvm::MDNode::get(Context, OptString));
+ }
}
}
@@ -1708,16 +1756,14 @@ void CodeGenModule::EmitModuleLinkOptions() {
bool AnyChildren = false;
// Visit the submodules of this module.
- for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(),
- SubEnd = Mod->submodule_end();
- Sub != SubEnd; ++Sub) {
+ for (const auto &SM : Mod->submodules()) {
// Skip explicit children; they need to be explicitly imported to be
// linked against.
- if ((*Sub)->IsExplicit)
+ if (SM->IsExplicit)
continue;
- if (Visited.insert(*Sub).second) {
- Stack.push_back(*Sub);
+ if (Visited.insert(SM).second) {
+ Stack.push_back(SM);
AnyChildren = true;
}
}
@@ -1747,6 +1793,10 @@ void CodeGenModule::EmitModuleLinkOptions() {
}
void CodeGenModule::EmitDeferred() {
+ // Emit deferred declare target declarations.
+ if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd)
+ getOpenMPRuntime().emitDeferredTargetDecls();
+
// Emit code for any potentially referenced deferred decls. Since a
// previously unused static decl may become used during the generation of code
// for a static function, iterate until no changes are made.
@@ -1949,9 +1999,6 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
StringRef Category) const {
- if (!LangOpts.XRayInstrument)
- return false;
-
const auto &XRayFilter = getContext().getXRayFilter();
using ImbueAttr = XRayFunctionFilter::ImbueAttribute;
auto Attr = ImbueAttr::NONE;
@@ -1981,6 +2028,13 @@ bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
if (LangOpts.EmitAllDecls)
return true;
+ if (CodeGenOpts.KeepStaticConsts) {
+ const auto *VD = dyn_cast<VarDecl>(Global);
+ if (VD && VD->getType().isConstQualified() &&
+ VD->getStorageDuration() == SD_Static)
+ return true;
+ }
+
return getContext().DeclMustBeEmitted(Global);
}
@@ -2000,7 +2054,8 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
// codegen for global variables, because they may be marked as threadprivate.
if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS &&
getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global) &&
- !isTypeConstant(Global->getType(), false))
+ !isTypeConstant(Global->getType(), false) &&
+ !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Global))
return false;
return true;
@@ -2141,16 +2196,22 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
} else {
const auto *VD = cast<VarDecl>(Global);
assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
- // We need to emit device-side global CUDA variables even if a
- // variable does not have a definition -- we still need to define
- // host-side shadow for it.
- bool MustEmitForCuda = LangOpts.CUDA && !LangOpts.CUDAIsDevice &&
- !VD->hasDefinition() &&
- (VD->hasAttr<CUDAConstantAttr>() ||
- VD->hasAttr<CUDADeviceAttr>());
- if (!MustEmitForCuda &&
- VD->isThisDeclarationADefinition() != VarDecl::Definition &&
+ if (VD->isThisDeclarationADefinition() != VarDecl::Definition &&
!Context.isMSStaticDataMemberInlineDefinition(VD)) {
+ if (LangOpts.OpenMP) {
+ // Emit declaration of the must-be-emitted declare target variable.
+ if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
+ if (*Res == OMPDeclareTargetDeclAttr::MT_To) {
+ (void)GetAddrOfGlobalVar(VD);
+ } else {
+ assert(*Res == OMPDeclareTargetDeclAttr::MT_Link &&
+ "link claue expected.");
+ (void)getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
+ }
+ return;
+ }
+ }
// If this declaration may have caused an inline variable definition to
// change linkage, make sure that it's emitted.
if (Context.getInlineVariableDefinitionKind(VD) ==
@@ -2360,6 +2421,19 @@ bool CodeGenModule::shouldOpportunisticallyEmitVTables() {
return CodeGenOpts.OptimizationLevel > 0;
}
+void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
+ llvm::GlobalValue *GV) {
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
+
+ if (FD->isCPUSpecificMultiVersion()) {
+ auto *Spec = FD->getAttr<CPUSpecificAttr>();
+ for (unsigned I = 0; I < Spec->cpus_size(); ++I)
+ EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
+ // Requires multiple emits.
+ } else
+ EmitGlobalFunctionDefinition(GD, GV);
+}
+
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
const auto *D = cast<ValueDecl>(GD.getDecl());
@@ -2367,7 +2441,7 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
Context.getSourceManager(),
"Generating code for declaration");
- if (isa<FunctionDecl>(D)) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// At -O0, don't generate IR for functions with available_externally
// linkage.
if (!shouldEmitFunction(GD))
@@ -2380,6 +2454,8 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
ABI->emitCXXStructor(CD, getFromCtorType(GD.getCtorType()));
else if (const auto *DD = dyn_cast<CXXDestructorDecl>(Method))
ABI->emitCXXStructor(DD, getFromDtorType(GD.getDtorType()));
+ else if (FD->isMultiVersion())
+ EmitMultiVersionFunctionDefinition(GD, GV);
else
EmitGlobalFunctionDefinition(GD, GV);
@@ -2389,6 +2465,8 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
return;
}
+ if (FD->isMultiVersion())
+ return EmitMultiVersionFunctionDefinition(GD, GV);
return EmitGlobalFunctionDefinition(GD, GV);
}
@@ -2401,9 +2479,22 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
llvm::Function *NewFn);
+static unsigned
+TargetMVPriority(const TargetInfo &TI,
+ const CodeGenFunction::MultiVersionResolverOption &RO) {
+ unsigned Priority = 0;
+ for (StringRef Feat : RO.Conditions.Features)
+ Priority = std::max(Priority, TI.multiVersionSortPriority(Feat));
+
+ if (!RO.Conditions.Architecture.empty())
+ Priority = std::max(
+ Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture));
+ return Priority;
+}
+
void CodeGenModule::emitMultiVersionFunctions() {
for (GlobalDecl GD : MultiVersionFuncs) {
- SmallVector<CodeGenFunction::TargetMultiVersionResolverOption, 10> Options;
+ SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
getContext().forEachMultiversionedFunctionVersion(
FD, [this, &GD, &Options](const FunctionDecl *CurFD) {
@@ -2424,20 +2515,36 @@ void CodeGenModule::emitMultiVersionFunctions() {
}
assert(Func && "This should have just been created");
}
- Options.emplace_back(getTarget(), cast<llvm::Function>(Func),
- CurFD->getAttr<TargetAttr>()->parse());
+
+ const auto *TA = CurFD->getAttr<TargetAttr>();
+ llvm::SmallVector<StringRef, 8> Feats;
+ TA->getAddedFeatures(Feats);
+
+ Options.emplace_back(cast<llvm::Function>(Func),
+ TA->getArchitecture(), Feats);
});
- llvm::Function *ResolverFunc = cast<llvm::Function>(
- GetGlobalValue((getMangledName(GD) + ".resolver").str()));
+ llvm::Function *ResolverFunc;
+ const TargetInfo &TI = getTarget();
+
+ if (TI.supportsIFunc() || FD->isTargetMultiVersion())
+ ResolverFunc = cast<llvm::Function>(
+ GetGlobalValue((getMangledName(GD) + ".resolver").str()));
+ else
+ ResolverFunc = cast<llvm::Function>(GetGlobalValue(getMangledName(GD)));
+
if (supportsCOMDAT())
ResolverFunc->setComdat(
getModule().getOrInsertComdat(ResolverFunc->getName()));
+
std::stable_sort(
Options.begin(), Options.end(),
- std::greater<CodeGenFunction::TargetMultiVersionResolverOption>());
+ [&TI](const CodeGenFunction::MultiVersionResolverOption &LHS,
+ const CodeGenFunction::MultiVersionResolverOption &RHS) {
+ return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS);
+ });
CodeGenFunction CGF(*this);
- CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options);
+ CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
}
@@ -2446,27 +2553,58 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
assert(FD && "Not a FunctionDecl?");
const auto *DD = FD->getAttr<CPUDispatchAttr>();
assert(DD && "Not a cpu_dispatch Function?");
- llvm::Type *DeclTy = getTypes().ConvertTypeForMem(FD->getType());
+ QualType CanonTy = Context.getCanonicalType(FD->getType());
+ llvm::Type *DeclTy = getTypes().ConvertFunctionType(CanonTy, FD);
+
+ if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD);
+ DeclTy = getTypes().GetFunctionType(FInfo);
+ }
StringRef ResolverName = getMangledName(GD);
- llvm::Type *ResolverType = llvm::FunctionType::get(
- llvm::PointerType::get(DeclTy,
- Context.getTargetAddressSpace(FD->getType())),
- false);
- auto *ResolverFunc = cast<llvm::Function>(
- GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{},
- /*ForVTable=*/false));
-
- SmallVector<CodeGenFunction::CPUDispatchMultiVersionResolverOption, 10>
- Options;
+
+ llvm::Type *ResolverType;
+ GlobalDecl ResolverGD;
+ if (getTarget().supportsIFunc())
+ ResolverType = llvm::FunctionType::get(
+ llvm::PointerType::get(DeclTy,
+ Context.getTargetAddressSpace(FD->getType())),
+ false);
+ else {
+ ResolverType = DeclTy;
+ ResolverGD = GD;
+ }
+
+ auto *ResolverFunc = cast<llvm::Function>(GetOrCreateLLVMFunction(
+ ResolverName, ResolverType, ResolverGD, /*ForVTable=*/false));
+
+ SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
const TargetInfo &Target = getTarget();
+ unsigned Index = 0;
for (const IdentifierInfo *II : DD->cpus()) {
// Get the name of the target function so we can look it up/create it.
std::string MangledName = getMangledNameImpl(*this, GD, FD, true) +
getCPUSpecificMangling(*this, II->getName());
- llvm::Constant *Func = GetOrCreateLLVMFunction(
- MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/false,
- /*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
+
+ llvm::Constant *Func = GetGlobalValue(MangledName);
+
+ if (!Func) {
+ GlobalDecl ExistingDecl = Manglings.lookup(MangledName);
+ if (ExistingDecl.getDecl() &&
+ ExistingDecl.getDecl()->getAsFunction()->isDefined()) {
+ EmitGlobalFunctionDefinition(ExistingDecl, nullptr);
+ Func = GetGlobalValue(MangledName);
+ } else {
+ if (!ExistingDecl.getDecl())
+ ExistingDecl = GD.getWithMultiVersionIndex(Index);
+
+ Func = GetOrCreateLLVMFunction(
+ MangledName, DeclTy, ExistingDecl,
+ /*ForVTable=*/false, /*DontDefer=*/true,
+ /*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
+ }
+ }
+
llvm::SmallVector<StringRef, 32> Features;
Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features);
llvm::transform(Features, Features.begin(),
@@ -2475,27 +2613,54 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
Features.begin(), Features.end(), [&Target](StringRef Feat) {
return !Target.validateCpuSupports(Feat);
}), Features.end());
- Options.emplace_back(cast<llvm::Function>(Func),
- CodeGenFunction::GetX86CpuSupportsMask(Features));
+ Options.emplace_back(cast<llvm::Function>(Func), StringRef{}, Features);
+ ++Index;
}
llvm::sort(
- Options.begin(), Options.end(),
- std::greater<CodeGenFunction::CPUDispatchMultiVersionResolverOption>());
+ Options, [](const CodeGenFunction::MultiVersionResolverOption &LHS,
+ const CodeGenFunction::MultiVersionResolverOption &RHS) {
+ return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) >
+ CodeGenFunction::GetX86CpuSupportsMask(RHS.Conditions.Features);
+ });
+
+ // If the list contains multiple 'default' versions, such as when it contains
+ // 'pentium' and 'generic', don't emit the call to the generic one (since we
+ // always run on at least a 'pentium'). We do this by deleting the 'least
+ // advanced' (read, lowest mangling letter).
+ while (Options.size() > 1 &&
+ CodeGenFunction::GetX86CpuSupportsMask(
+ (Options.end() - 2)->Conditions.Features) == 0) {
+ StringRef LHSName = (Options.end() - 2)->Function->getName();
+ StringRef RHSName = (Options.end() - 1)->Function->getName();
+ if (LHSName.compare(RHSName) < 0)
+ Options.erase(Options.end() - 2);
+ else
+ Options.erase(Options.end() - 1);
+ }
+
CodeGenFunction CGF(*this);
- CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options);
+ CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
-/// If an ifunc for the specified mangled name is not in the module, create and
-/// return an llvm IFunc Function with the specified type.
-llvm::Constant *
-CodeGenModule::GetOrCreateMultiVersionIFunc(GlobalDecl GD, llvm::Type *DeclTy,
- const FunctionDecl *FD) {
+/// If a dispatcher for the specified mangled name is not in the module, create
+/// and return an llvm Function with the specified type.
+llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(
+ GlobalDecl GD, llvm::Type *DeclTy, const FunctionDecl *FD) {
std::string MangledName =
getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
- std::string IFuncName = MangledName + ".ifunc";
- if (llvm::GlobalValue *IFuncGV = GetGlobalValue(IFuncName))
- return IFuncGV;
+
+ // Holds the name of the resolver, in ifunc mode this is the ifunc (which has
+ // a separate resolver).
+ std::string ResolverName = MangledName;
+ if (getTarget().supportsIFunc())
+ ResolverName += ".ifunc";
+ else if (FD->isTargetMultiVersion())
+ ResolverName += ".resolver";
+
+ // If this already exists, just return that one.
+ if (llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName))
+ return ResolverGV;
// Since this is the first time we've created this IFunc, make sure
// that we put this multiversioned function into the list to be
@@ -2503,20 +2668,28 @@ CodeGenModule::GetOrCreateMultiVersionIFunc(GlobalDecl GD, llvm::Type *DeclTy,
if (!FD->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion())
MultiVersionFuncs.push_back(GD);
- std::string ResolverName = MangledName + ".resolver";
- llvm::Type *ResolverType = llvm::FunctionType::get(
- llvm::PointerType::get(DeclTy,
- Context.getTargetAddressSpace(FD->getType())),
- false);
- llvm::Constant *Resolver =
- GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{},
- /*ForVTable=*/false);
- llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
- DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule());
- GIF->setName(IFuncName);
- SetCommonAttributes(FD, GIF);
+ if (getTarget().supportsIFunc()) {
+ llvm::Type *ResolverType = llvm::FunctionType::get(
+ llvm::PointerType::get(
+ DeclTy, getContext().getTargetAddressSpace(FD->getType())),
+ false);
+ llvm::Constant *Resolver = GetOrCreateLLVMFunction(
+ MangledName + ".resolver", ResolverType, GlobalDecl{},
+ /*ForVTable=*/false);
+ llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
+ DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule());
+ GIF->setName(ResolverName);
+ SetCommonAttributes(FD, GIF);
- return GIF;
+ return GIF;
+ }
+
+ llvm::Constant *Resolver = GetOrCreateLLVMFunction(
+ ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false);
+ assert(isa<llvm::GlobalValue>(Resolver) &&
+ "Resolver should be created for the first time");
+ SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver));
+ return Resolver;
}
/// GetOrCreateLLVMFunction - If the specified mangled name is not in the
@@ -2539,15 +2712,16 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
if (getLangOpts().OpenMPIsDevice && OpenMPRuntime &&
!OpenMPRuntime->markAsGlobalTarget(GD) && FD->isDefined() &&
!DontDefer && !IsForDefinition) {
- const FunctionDecl *FDDef = FD->getDefinition();
- GlobalDecl GDDef;
- if (const auto *CD = dyn_cast<CXXConstructorDecl>(FDDef))
- GDDef = GlobalDecl(CD, GD.getCtorType());
- else if (const auto *DD = dyn_cast<CXXDestructorDecl>(FDDef))
- GDDef = GlobalDecl(DD, GD.getDtorType());
- else
- GDDef = GlobalDecl(FDDef);
- addDeferredDeclToEmit(GDDef);
+ if (const FunctionDecl *FDDef = FD->getDefinition()) {
+ GlobalDecl GDDef;
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(FDDef))
+ GDDef = GlobalDecl(CD, GD.getCtorType());
+ else if (const auto *DD = dyn_cast<CXXDestructorDecl>(FDDef))
+ GDDef = GlobalDecl(DD, GD.getDtorType());
+ else
+ GDDef = GlobalDecl(FDDef);
+ EmitGlobal(GDDef);
+ }
}
if (FD->isMultiVersion()) {
@@ -2555,7 +2729,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
if (TA && TA->isDefaultVersion())
UpdateMultiVersionNames(GD, FD);
if (!IsForDefinition)
- return GetOrCreateMultiVersionIFunc(GD, Ty, FD);
+ return GetOrCreateMultiVersionResolver(GD, Ty, FD);
}
}
@@ -3058,10 +3232,9 @@ CodeGenModule::GetAddrOfGlobal(GlobalDecl GD,
IsForDefinition);
}
-llvm::GlobalVariable *
-CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
- llvm::Type *Ty,
- llvm::GlobalValue::LinkageTypes Linkage) {
+llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable(
+ StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage,
+ unsigned Alignment) {
llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name);
llvm::GlobalVariable *OldGV = nullptr;
@@ -3097,6 +3270,8 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
!GV->hasAvailableExternallyLinkage())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
+ GV->setAlignment(Alignment);
+
return GV;
}
@@ -3313,8 +3488,15 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
// CUDA E.2.4.1 "__shared__ variables cannot have an initialization
// as part of their declaration." Sema has already checked for
// error cases, so we just need to set Init to UndefValue.
- if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
- D->hasAttr<CUDASharedAttr>())
+ bool IsCUDASharedVar =
+ getLangOpts().CUDAIsDevice && D->hasAttr<CUDASharedAttr>();
+ // Shadows of initialized device-side global variables are also left
+ // undefined.
+ bool IsCUDAShadowVar =
+ !getLangOpts().CUDAIsDevice &&
+ (D->hasAttr<CUDAConstantAttr>() || D->hasAttr<CUDADeviceAttr>() ||
+ D->hasAttr<CUDASharedAttr>());
+ if (getLangOpts().CUDA && (IsCUDASharedVar || IsCUDAShadowVar))
Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
else if (!InitExpr) {
// This is a tentative definition; tentative definitions are
@@ -3434,7 +3616,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
Flags |= CGCUDARuntime::ExternDeviceVar;
if (D->hasAttr<CUDAConstantAttr>())
Flags |= CGCUDARuntime::ConstantDeviceVar;
- getCUDARuntime().registerDeviceVar(*GV, Flags);
+ // Extern global variables will be registered in the TU where they are
+ // defined.
+ if (!D->hasExternalStorage())
+ getCUDARuntime().registerDeviceVar(*GV, Flags);
} else if (D->hasAttr<CUDASharedAttr>())
// __shared__ variables are odd. Shadows do get created, but
// they are not registered with the CUDA runtime, so they
@@ -3577,6 +3762,15 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
}
}
+ // Microsoft's link.exe doesn't support alignments greater than 32 for common
+ // symbols, so symbols with greater alignment requirements cannot be common.
+ // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
+ // alignments for common symbols via the aligncomm directive, so this
+ // restriction only applies to MSVC environments.
+ if (Context.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
+ Context.getTypeAlignIfKnown(D->getType()) > 32)
+ return true;
+
return false;
}
@@ -3592,6 +3786,10 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(
return llvm::GlobalVariable::WeakAnyLinkage;
}
+ if (const auto *FD = D->getAsFunction())
+ if (FD->isMultiVersion() && Linkage == GVA_AvailableExternally)
+ return llvm::GlobalVariable::LinkOnceAnyLinkage;
+
// We are guaranteed to have a strong definition somewhere else,
// so we can use available_externally linkage.
if (Linkage == GVA_AvailableExternally)
@@ -3828,15 +4026,6 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
AddGlobalDtor(Fn, DA->getPriority());
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, Fn);
-
- if (D->isCPUSpecificMultiVersion()) {
- auto *Spec = D->getAttr<CPUSpecificAttr>();
- // If there is another specific version we need to emit, do so here.
- if (Spec->ActiveArgIndex + 1 < Spec->cpus_size()) {
- ++Spec->ActiveArgIndex;
- EmitGlobalFunctionDefinition(GD, nullptr);
- }
- }
}
void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
@@ -4030,39 +4219,81 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };
+ const ASTContext &Context = getContext();
+ const llvm::Triple &Triple = getTriple();
+
+ const auto CFRuntime = getLangOpts().CFRuntime;
+ const bool IsSwiftABI =
+ static_cast<unsigned>(CFRuntime) >=
+ static_cast<unsigned>(LangOptions::CoreFoundationABI::Swift);
+ const bool IsSwift4_1 = CFRuntime == LangOptions::CoreFoundationABI::Swift4_1;
+
// If we don't already have it, get __CFConstantStringClassReference.
if (!CFConstantStringClassRef) {
+ const char *CFConstantStringClassName = "__CFConstantStringClassReference";
llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
Ty = llvm::ArrayType::get(Ty, 0);
- llvm::GlobalValue *GV = cast<llvm::GlobalValue>(
- CreateRuntimeVariable(Ty, "__CFConstantStringClassReference"));
-
- if (getTriple().isOSBinFormatCOFF()) {
- IdentifierInfo &II = getContext().Idents.get(GV->getName());
- TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl();
- DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
-
- const VarDecl *VD = nullptr;
- for (const auto &Result : DC->lookup(&II))
- if ((VD = dyn_cast<VarDecl>(Result)))
- break;
-
- if (!VD || !VD->hasAttr<DLLExportAttr>()) {
- GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- } else {
- GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+
+ switch (CFRuntime) {
+ default: break;
+ case LangOptions::CoreFoundationABI::Swift: LLVM_FALLTHROUGH;
+ case LangOptions::CoreFoundationABI::Swift5_0:
+ CFConstantStringClassName =
+ Triple.isOSDarwin() ? "$s15SwiftFoundation19_NSCFConstantStringCN"
+ : "$s10Foundation19_NSCFConstantStringCN";
+ Ty = IntPtrTy;
+ break;
+ case LangOptions::CoreFoundationABI::Swift4_2:
+ CFConstantStringClassName =
+ Triple.isOSDarwin() ? "$S15SwiftFoundation19_NSCFConstantStringCN"
+ : "$S10Foundation19_NSCFConstantStringCN";
+ Ty = IntPtrTy;
+ break;
+ case LangOptions::CoreFoundationABI::Swift4_1:
+ CFConstantStringClassName =
+ Triple.isOSDarwin() ? "__T015SwiftFoundation19_NSCFConstantStringCN"
+ : "__T010Foundation19_NSCFConstantStringCN";
+ Ty = IntPtrTy;
+ break;
+ }
+
+ llvm::Constant *C = CreateRuntimeVariable(Ty, CFConstantStringClassName);
+
+ if (Triple.isOSBinFormatELF() || Triple.isOSBinFormatCOFF()) {
+ llvm::GlobalValue *GV = nullptr;
+
+ if ((GV = dyn_cast<llvm::GlobalValue>(C))) {
+ IdentifierInfo &II = Context.Idents.get(GV->getName());
+ TranslationUnitDecl *TUDecl = Context.getTranslationUnitDecl();
+ DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
+
+ const VarDecl *VD = nullptr;
+ for (const auto &Result : DC->lookup(&II))
+ if ((VD = dyn_cast<VarDecl>(Result)))
+ break;
+
+ if (Triple.isOSBinFormatELF()) {
+ if (!VD)
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ } else {
+ GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ if (!VD || !VD->hasAttr<DLLExportAttr>())
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ else
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ }
+
+ setDSOLocal(GV);
}
}
- setDSOLocal(GV);
// Decay array -> ptr
CFConstantStringClassRef =
- llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros);
+ IsSwiftABI ? llvm::ConstantExpr::getPtrToInt(C, Ty)
+ : llvm::ConstantExpr::getGetElementPtr(Ty, C, Zeros);
}
- QualType CFTy = getContext().getCFConstantStringType();
+ QualType CFTy = Context.getCFConstantStringType();
auto *STy = cast<llvm::StructType>(getTypes().ConvertType(CFTy));
@@ -4073,7 +4304,12 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
Fields.add(cast<llvm::ConstantExpr>(CFConstantStringClassRef));
// Flags.
- Fields.addInt(IntTy, isUTF16 ? 0x07d0 : 0x07C8);
+ if (IsSwiftABI) {
+ Fields.addInt(IntPtrTy, IsSwift4_1 ? 0x05 : 0x01);
+ Fields.addInt(Int64Ty, isUTF16 ? 0x07d0 : 0x07c8);
+ } else {
+ Fields.addInt(IntTy, isUTF16 ? 0x07d0 : 0x07C8);
+ }
// String pointer.
llvm::Constant *C = nullptr;
@@ -4094,17 +4330,20 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
// Don't enforce the target's minimum global alignment, since the only use
// of the string is via this class initializer.
- CharUnits Align = isUTF16
- ? getContext().getTypeAlignInChars(getContext().ShortTy)
- : getContext().getTypeAlignInChars(getContext().CharTy);
+ CharUnits Align = isUTF16 ? Context.getTypeAlignInChars(Context.ShortTy)
+ : Context.getTypeAlignInChars(Context.CharTy);
GV->setAlignment(Align.getQuantity());
// FIXME: We set the section explicitly to avoid a bug in ld64 224.1.
// Without it LLVM can merge the string with a non unnamed_addr one during
// LTO. Doing that changes the section it ends in, which surprises ld64.
- if (getTriple().isOSBinFormatMachO())
+ if (Triple.isOSBinFormatMachO())
GV->setSection(isUTF16 ? "__TEXT,__ustring"
: "__TEXT,__cstring,cstring_literals");
+ // Make sure the literal ends up in .rodata to allow for safe ICF and for
+ // the static linker to adjust permissions to read-only later on.
+ else if (Triple.isOSBinFormatELF())
+ GV->setSection(".rodata");
// String.
llvm::Constant *Str =
@@ -4116,8 +4355,17 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
Fields.add(Str);
// String length.
- auto Ty = getTypes().ConvertType(getContext().LongTy);
- Fields.addInt(cast<llvm::IntegerType>(Ty), StringLength);
+ llvm::IntegerType *LengthTy =
+ llvm::IntegerType::get(getModule().getContext(),
+ Context.getTargetInfo().getLongWidth());
+ if (IsSwiftABI) {
+ if (CFRuntime == LangOptions::CoreFoundationABI::Swift4_1 ||
+ CFRuntime == LangOptions::CoreFoundationABI::Swift4_2)
+ LengthTy = Int32Ty;
+ else
+ LengthTy = IntPtrTy;
+ }
+ Fields.addInt(LengthTy, StringLength);
CharUnits Alignment = getPointerAlign();
@@ -4125,7 +4373,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
GV = Fields.finishAndCreateGlobal("_unnamed_cfstring_", Alignment,
/*isConstant=*/false,
llvm::GlobalVariable::PrivateLinkage);
- switch (getTriple().getObjectFormat()) {
+ switch (Triple.getObjectFormat()) {
case llvm::Triple::UnknownObjectFormat:
llvm_unreachable("unknown file format");
case llvm::Triple::COFF:
@@ -4264,15 +4512,13 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
StringRef GlobalVariableName;
llvm::GlobalValue::LinkageTypes LT;
- // Mangle the string literal if the ABI allows for it. However, we cannot
- // do this if we are compiling with ASan or -fwritable-strings because they
- // rely on strings having normal linkage.
- if (!LangOpts.WritableStrings &&
- !LangOpts.Sanitize.has(SanitizerKind::Address) &&
- getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) {
+ // Mangle the string literal if that's how the ABI merges duplicate strings.
+ // Don't do it if they are writable, since we don't want writes in one TU to
+ // affect strings in another.
+ if (getCXXABI().getMangleContext().shouldMangleStringLiteral(S) &&
+ !LangOpts.WritableStrings) {
llvm::raw_svector_ostream Out(MangledNameBuffer);
getCXXABI().getMangleContext().mangleStringLiteral(S, Out);
-
LT = llvm::GlobalValue::LinkOnceODRLinkage;
GlobalVariableName = MangledNameBuffer;
} else {
@@ -4620,6 +4866,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::TypeAliasTemplate:
case Decl::Block:
case Decl::Empty:
+ case Decl::Binding:
break;
case Decl::Using: // using X; [C++]
if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -4787,6 +5034,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(D));
break;
+ case Decl::OMPRequires:
+ EmitOMPRequiresDecl(cast<OMPRequiresDecl>(D));
+ break;
+
default:
// Make sure we handled everything we should, every other kind is a
// non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind
@@ -4810,7 +5061,7 @@ void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
if (!cast<FunctionDecl>(D)->doesThisDeclarationHaveABody())
return;
SourceManager &SM = getContext().getSourceManager();
- if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getLocStart()))
+ if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getBeginLoc()))
return;
auto I = DeferredEmptyCoverageMappingDecls.find(D);
if (I == DeferredEmptyCoverageMappingDecls.end())
@@ -4981,6 +5232,16 @@ void CodeGenModule::EmitVersionIdentMetadata() {
IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode));
}
+void CodeGenModule::EmitCommandLineMetadata() {
+ llvm::NamedMDNode *CommandLineMetadata =
+ TheModule.getOrInsertNamedMetadata("llvm.commandline");
+ std::string CommandLine = getCodeGenOpts().RecordCommandLine;
+ llvm::LLVMContext &Ctx = TheModule.getContext();
+
+ llvm::Metadata *CommandLineNode[] = {llvm::MDString::get(Ctx, CommandLine)};
+ CommandLineMetadata->addOperand(llvm::MDNode::get(Ctx, CommandLineNode));
+}
+
void CodeGenModule::EmitTargetMetadata() {
// Warning, new MangledDeclNames may be appended within this loop.
// We rely on MapVector insertions adding new elements to the end
@@ -5073,7 +5334,7 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
Address Addr(GetAddrOfGlobalVar(VD), getContext().getDeclAlign(VD));
if (auto InitFunction = getOpenMPRuntime().emitThreadPrivateVarDefinition(
- VD, Addr, RefExpr->getLocStart(), PerformInit))
+ VD, Addr, RefExpr->getBeginLoc(), PerformInit))
CXXGlobalInits.push_back(InitFunction);
}
}
@@ -5196,8 +5457,9 @@ TargetAttr::ParsedTargetAttr CodeGenModule::filterFunctionTargetAttrs(const Targ
// Fills in the supplied string map with the set of target features for the
// passed in function.
void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
- const FunctionDecl *FD) {
+ GlobalDecl GD) {
StringRef TargetCPU = Target.getTargetOpts().CPU;
+ const FunctionDecl *FD = GD.getDecl()->getAsFunction();
if (const auto *TD = FD->getAttr<TargetAttr>()) {
TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD);
@@ -5219,8 +5481,8 @@ void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
ParsedAttr.Features);
} else if (const auto *SD = FD->getAttr<CPUSpecificAttr>()) {
llvm::SmallVector<StringRef, 32> FeaturesTmp;
- Target.getCPUSpecificCPUDispatchFeatures(SD->getCurCPUName()->getName(),
- FeaturesTmp);
+ Target.getCPUSpecificCPUDispatchFeatures(
+ SD->getCPUName(GD.getMultiVersionIndex())->getName(), FeaturesTmp);
std::vector<std::string> Features(FeaturesTmp.begin(), FeaturesTmp.end());
Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Features);
} else {
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 91f3d94330f1..75679d11c13c 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -119,15 +119,29 @@ struct OrderGlobalInits {
struct ObjCEntrypoints {
ObjCEntrypoints() { memset(this, 0, sizeof(*this)); }
- /// void objc_autoreleasePoolPop(void*);
+ /// void objc_alloc(id);
+ llvm::Constant *objc_alloc;
+
+ /// void objc_allocWithZone(id);
+ llvm::Constant *objc_allocWithZone;
+
+ /// void objc_autoreleasePoolPop(void*);
llvm::Constant *objc_autoreleasePoolPop;
+ /// void objc_autoreleasePoolPop(void*);
+ /// Note this method is used when we are using exception handling
+ llvm::Constant *objc_autoreleasePoolPopInvoke;
+
/// void *objc_autoreleasePoolPush(void);
llvm::Constant *objc_autoreleasePoolPush;
/// id objc_autorelease(id);
llvm::Constant *objc_autorelease;
+ /// id objc_autorelease(id);
+ /// Note this is the runtime method not the intrinsic.
+ llvm::Constant *objc_autoreleaseRuntimeFunction;
+
/// id objc_autoreleaseReturnValue(id);
llvm::Constant *objc_autoreleaseReturnValue;
@@ -152,6 +166,10 @@ struct ObjCEntrypoints {
/// id objc_retain(id);
llvm::Constant *objc_retain;
+ /// id objc_retain(id);
+ /// Note this is the runtime method not the intrinsic.
+ llvm::Constant *objc_retainRuntimeFunction;
+
/// id objc_retainAutorelease(id);
llvm::Constant *objc_retainAutorelease;
@@ -167,6 +185,10 @@ struct ObjCEntrypoints {
/// void objc_release(id);
llvm::Constant *objc_release;
+ /// void objc_release(id);
+ /// Note this is the runtime method not the intrinsic.
+ llvm::Constant *objc_releaseRuntimeFunction;
+
/// void objc_storeStrong(id*, id);
llvm::Constant *objc_storeStrong;
@@ -764,7 +786,8 @@ public:
/// bitcast to the new variable.
llvm::GlobalVariable *
CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty,
- llvm::GlobalValue::LinkageTypes Linkage);
+ llvm::GlobalValue::LinkageTypes Linkage,
+ unsigned Alignment);
llvm::Function *
CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name,
@@ -1042,8 +1065,7 @@ public:
const CGFunctionInfo &FI);
/// Set the LLVM function attributes (sext, zext, etc).
- void SetLLVMFunctionAttributes(const Decl *D,
- const CGFunctionInfo &Info,
+ void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info,
llvm::Function *F);
/// Set the LLVM function attributes which only apply to a function
@@ -1103,8 +1125,7 @@ public:
// Fills in the supplied string map with the set of target features for the
// passed in function.
- void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
- const FunctionDecl *FD);
+ void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, GlobalDecl GD);
StringRef getMangledName(GlobalDecl GD);
StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD);
@@ -1223,6 +1244,10 @@ public:
void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
CodeGenFunction *CGF = nullptr);
+ /// Emit a code for requires directive.
+ /// \param D Requires declaration
+ void EmitOMPRequiresDecl(const OMPRequiresDecl *D);
+
/// Returns whether the given record has hidden LTO visibility and therefore
/// may participate in (single-module) CFI and whole-program vtable
/// optimization.
@@ -1288,9 +1313,9 @@ private:
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
ForDefinition_t IsForDefinition = NotForDefinition);
- llvm::Constant *GetOrCreateMultiVersionIFunc(GlobalDecl GD,
- llvm::Type *DeclTy,
- const FunctionDecl *FD);
+ llvm::Constant *GetOrCreateMultiVersionResolver(GlobalDecl GD,
+ llvm::Type *DeclTy,
+ const FunctionDecl *FD);
void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD);
llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
@@ -1299,7 +1324,7 @@ private:
ForDefinition_t IsForDefinition
= NotForDefinition);
- bool GetCPUAndFeaturesAttributes(const Decl *D,
+ bool GetCPUAndFeaturesAttributes(GlobalDecl GD,
llvm::AttrBuilder &AttrBuilder);
void setNonAliasAttributes(GlobalDecl GD, llvm::GlobalObject *GO);
@@ -1310,6 +1335,8 @@ private:
void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr);
void EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV);
+ void EmitMultiVersionFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV);
+
void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false);
void EmitAliasDefinition(GlobalDecl GD);
void emitIFuncDefinition(GlobalDecl GD);
@@ -1397,6 +1424,9 @@ private:
/// Emit the Clang version as llvm.ident metadata.
void EmitVersionIdentMetadata();
+ /// Emit the Clang commandline as llvm.commandline metadata.
+ void EmitCommandLineMetadata();
+
/// Emits target specific Metadata for global declarations.
void EmitTargetMetadata();
diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index c8c2a1b956b8..776060743a63 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/lib/CodeGen/CodeGenPGO.cpp
@@ -165,7 +165,12 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
// Blocks and lambdas are handled as separate functions, so we need not
// traverse them in the parent context.
bool TraverseBlockExpr(BlockExpr *BE) { return true; }
- bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
+ bool TraverseLambdaExpr(LambdaExpr *LE) {
+ // Traverse the captures, but not the body.
+ for (const auto &C : zip(LE->captures(), LE->capture_inits()))
+ TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
+ return true;
+ }
bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
bool VisitDecl(const Decl *D) {
@@ -544,6 +549,8 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
RecordStmtCount(S);
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getLoopVarStmt());
Visit(S->getRangeStmt());
Visit(S->getBeginStmt());
@@ -815,7 +822,7 @@ bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
// Don't map the functions in system headers.
const auto &SM = CGM.getContext().getSourceManager();
- auto Loc = D->getBody()->getLocStart();
+ auto Loc = D->getBody()->getBeginLoc();
return SM.isInSystemHeader(Loc);
}
diff --git a/lib/CodeGen/CodeGenPGO.h b/lib/CodeGen/CodeGenPGO.h
index 0759e65388b8..120ab651a4a8 100644
--- a/lib/CodeGen/CodeGenPGO.h
+++ b/lib/CodeGen/CodeGenPGO.h
@@ -17,7 +17,6 @@
#include "CGBuilder.h"
#include "CodeGenModule.h"
#include "CodeGenTypes.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include <array>
#include <memory>
diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index ec48231e5247..27d39716d22f 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/lib/CodeGen/CodeGenTBAA.cpp
@@ -20,7 +20,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
-#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 1a1395e6ae74..2acf1ac16180 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -503,6 +503,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 626869f00021..8e344e91b8cd 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -17,7 +17,6 @@
#include "CGCall.h"
#include "clang/Basic/ABI.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/Sema/Sema.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Module.h"
diff --git a/lib/CodeGen/ConstantEmitter.h b/lib/CodeGen/ConstantEmitter.h
index b4d1b65743c7..7ad8e5d37cd1 100644
--- a/lib/CodeGen/ConstantEmitter.h
+++ b/lib/CodeGen/ConstantEmitter.h
@@ -38,6 +38,9 @@ private:
/// Whether the constant-emission failed.
bool Failed = false;
+ /// Whether we're in a constant context.
+ bool InConstantContext = false;
+
/// The AST address space where this (non-abstract) initializer is going.
/// Used for generating appropriate placeholders.
LangAS DestAddressSpace;
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 2d8446463594..35962c73d9a8 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -67,7 +67,7 @@ public:
void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
- SourceLocation getStartLoc() const {
+ SourceLocation getBeginLoc() const {
assert(LocStart && "Region has no start location");
return *LocStart;
}
@@ -116,7 +116,7 @@ struct SpellingRegion {
}
SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
- : SpellingRegion(SM, R.getStartLoc(), R.getEndLoc()) {}
+ : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
/// Check if the start and end locations appear in source order, i.e
/// top->bottom, left->right.
@@ -204,7 +204,7 @@ public:
/// Get the start of \c S ignoring macro arguments and builtin macros.
SourceLocation getStart(const Stmt *S) {
- SourceLocation Loc = S->getLocStart();
+ SourceLocation Loc = S->getBeginLoc();
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
return Loc;
@@ -212,7 +212,7 @@ public:
/// Get the end of \c S ignoring macro arguments and builtin macros.
SourceLocation getEnd(const Stmt *S) {
- SourceLocation Loc = S->getLocEnd();
+ SourceLocation Loc = S->getEndLoc();
while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
return getPreciseTokenLocEnd(Loc);
@@ -229,7 +229,7 @@ public:
llvm::SmallSet<FileID, 8> Visited;
SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
for (const auto &Region : SourceRegions) {
- SourceLocation Loc = Region.getStartLoc();
+ SourceLocation Loc = Region.getBeginLoc();
FileID File = SM.getFileID(Loc);
if (!Visited.insert(File).second)
continue;
@@ -311,7 +311,7 @@ public:
for (const auto &Region : SourceRegions) {
assert(Region.hasEndLoc() && "incomplete region");
- SourceLocation LocStart = Region.getStartLoc();
+ SourceLocation LocStart = Region.getBeginLoc();
assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
// Ignore regions from system headers.
@@ -502,7 +502,7 @@ struct CounterCoverageMappingBuilder
DeferredRegion = None;
// If the region ends in an expansion, find the expansion site.
- FileID StartFile = SM.getFileID(DR.getStartLoc());
+ FileID StartFile = SM.getFileID(DR.getBeginLoc());
if (SM.getFileID(DeferredEndLoc) != StartFile) {
if (isNestedIn(DeferredEndLoc, StartFile)) {
do {
@@ -515,12 +515,12 @@ struct CounterCoverageMappingBuilder
// The parent of this deferred region ends where the containing decl ends,
// so the region isn't useful.
- if (DR.getStartLoc() == DeferredEndLoc)
+ if (DR.getBeginLoc() == DeferredEndLoc)
return Index;
// If we're visiting statements in non-source order (e.g switch cases or
// a loop condition) we can't construct a sensible deferred region.
- if (!SpellingRegion(SM, DR.getStartLoc(), DeferredEndLoc).isInSourceOrder())
+ if (!SpellingRegion(SM, DR.getBeginLoc(), DeferredEndLoc).isInSourceOrder())
return Index;
DR.setGap(true);
@@ -552,6 +552,15 @@ struct CounterCoverageMappingBuilder
completeDeferred(Count, DeferredEndLoc);
}
+ size_t locationDepth(SourceLocation Loc) {
+ size_t Depth = 0;
+ while (Loc.isValid()) {
+ Loc = getIncludeOrExpansionLoc(Loc);
+ Depth++;
+ }
+ return Depth;
+ }
+
/// Pop regions from the stack into the function's list of regions.
///
/// Adds all regions from \c ParentIndex to the top of the stack to the
@@ -562,23 +571,45 @@ struct CounterCoverageMappingBuilder
while (RegionStack.size() > ParentIndex) {
SourceMappingRegion &Region = RegionStack.back();
if (Region.hasStartLoc()) {
- SourceLocation StartLoc = Region.getStartLoc();
+ SourceLocation StartLoc = Region.getBeginLoc();
SourceLocation EndLoc = Region.hasEndLoc()
? Region.getEndLoc()
: RegionStack[ParentIndex].getEndLoc();
+ size_t StartDepth = locationDepth(StartLoc);
+ size_t EndDepth = locationDepth(EndLoc);
while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
- // The region ends in a nested file or macro expansion. Create a
- // separate region for each expansion.
- SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
- assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
-
- if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
- SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
-
- EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
- if (EndLoc.isInvalid())
- llvm::report_fatal_error("File exit not handled before popRegions");
+ bool UnnestStart = StartDepth >= EndDepth;
+ bool UnnestEnd = EndDepth >= StartDepth;
+ if (UnnestEnd) {
+ // The region ends in a nested file or macro expansion. Create a
+ // separate region for each expansion.
+ SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
+ assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
+
+ if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
+ SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
+
+ EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
+ if (EndLoc.isInvalid())
+ llvm::report_fatal_error("File exit not handled before popRegions");
+ EndDepth--;
+ }
+ if (UnnestStart) {
+ // The region begins in a nested file or macro expansion. Create a
+ // separate region for each expansion.
+ SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
+ assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
+
+ if (!isRegionAlreadyAdded(StartLoc, NestedLoc))
+ SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc);
+
+ StartLoc = getIncludeOrExpansionLoc(StartLoc);
+ if (StartLoc.isInvalid())
+ llvm::report_fatal_error("File exit not handled before popRegions");
+ StartDepth--;
+ }
}
+ Region.setStartLoc(StartLoc);
Region.setEndLoc(EndLoc);
MostRecentLocation = EndLoc;
@@ -588,7 +619,7 @@ struct CounterCoverageMappingBuilder
EndLoc == getEndOfFileOrMacro(EndLoc))
MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
- assert(SM.isWrittenInSameFile(Region.getStartLoc(), EndLoc));
+ assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
assert(SpellingRegion(SM, Region).isInSourceOrder());
SourceRegions.push_back(Region);
@@ -625,18 +656,21 @@ struct CounterCoverageMappingBuilder
return RegionStack.back();
}
- /// Propagate counts through the children of \c S.
- Counter propagateCounts(Counter TopCount, const Stmt *S) {
+ /// Propagate counts through the children of \p S if \p VisitChildren is true.
+ /// Otherwise, only emit a count for \p S itself.
+ Counter propagateCounts(Counter TopCount, const Stmt *S,
+ bool VisitChildren = true) {
SourceLocation StartLoc = getStart(S);
SourceLocation EndLoc = getEnd(S);
size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
- Visit(S);
+ if (VisitChildren)
+ Visit(S);
Counter ExitCount = getRegion().getCounter();
popRegions(Index);
// The statement may be spanned by an expansion. Make sure we handle a file
// exit out of this expansion before moving to the next statement.
- if (SM.isBeforeInTranslationUnit(StartLoc, S->getLocStart()))
+ if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
MostRecentLocation = EndLoc;
return ExitCount;
@@ -648,7 +682,7 @@ struct CounterCoverageMappingBuilder
return SourceRegions.rend() !=
std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
[&](const SourceMappingRegion &Region) {
- return Region.getStartLoc() == StartLoc &&
+ return Region.getBeginLoc() == StartLoc &&
Region.getEndLoc() == EndLoc;
});
}
@@ -700,7 +734,7 @@ struct CounterCoverageMappingBuilder
for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
if (!I.hasStartLoc())
continue;
- SourceLocation Loc = I.getStartLoc();
+ SourceLocation Loc = I.getBeginLoc();
if (!isNestedIn(Loc, ParentFile)) {
ParentCounter = I.getCounter();
break;
@@ -826,7 +860,7 @@ struct CounterCoverageMappingBuilder
}
void VisitStmt(const Stmt *S) {
- if (S->getLocStart().isValid())
+ if (S->getBeginLoc().isValid())
extendRegion(S);
for (const Stmt *Child : S->children())
if (Child)
@@ -843,7 +877,16 @@ struct CounterCoverageMappingBuilder
if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
return;
- propagateCounts(getRegionCounter(Body), Body);
+ // Do not visit the artificial children nodes of defaulted methods. The
+ // lexer may not be able to report back precise token end locations for
+ // these children nodes (llvm.org/PR39822), and moreover users will not be
+ // able to see coverage for them.
+ bool Defaulted = false;
+ if (auto *Method = dyn_cast<CXXMethodDecl>(D))
+ Defaulted = Method->isDefaulted();
+
+ propagateCounts(getRegionCounter(Body), Body,
+ /*VisitChildren=*/!Defaulted);
assert(RegionStack.empty() && "Regions entered but never exited");
// Discard the last uncompleted deferred region in a decl, if one exists.
@@ -1004,6 +1047,8 @@ struct CounterCoverageMappingBuilder
void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
extendRegion(S);
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getLoopVarStmt());
Visit(S->getRangeStmt());
@@ -1109,7 +1154,7 @@ struct CounterCoverageMappingBuilder
Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
// Reuse the existing region if it starts at our label. This is typical of
// the first case in a switch.
- if (Parent.hasStartLoc() && Parent.getStartLoc() == getStart(S))
+ if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
Parent.setCounter(Count);
else
pushRegion(Count, getStart(S));
diff --git a/lib/CodeGen/CoverageMappingGen.h b/lib/CodeGen/CoverageMappingGen.h
index b08ad896d7a5..c62db096952a 100644
--- a/lib/CodeGen/CoverageMappingGen.h
+++ b/lib/CodeGen/CoverageMappingGen.h
@@ -16,7 +16,6 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Lex/PPCallbacks.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/GlobalValue.h"
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 00fff144b597..b53304528c3d 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -287,6 +287,7 @@ public:
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
+ bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
bool ReturnAdjustment) override {
@@ -634,7 +635,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
if (ShouldEmitCFICheck) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
- CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getLocStart());
+ CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc());
CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0));
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),
@@ -1562,9 +1563,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
Type != Dtor_Base && DD->isVirtual())
Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
else
- Callee =
- CGCallee::forDirect(CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
- DD);
+ Callee = CGCallee::forDirect(
+ CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), GD);
CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(),
This.getPointer(), VTT, VTTTy,
@@ -1598,12 +1598,6 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
// Set the right visibility.
CGM.setGVProperties(VTable, RD);
- // Use pointer alignment for the vtable. Otherwise we would align them based
- // on the size of the initializer which doesn't make sense as only single
- // values are read.
- unsigned PAlign = CGM.getTarget().getPointerAlign(0);
- VTable->setAlignment(getContext().toCharUnitsFromBits(PAlign).getQuantity());
-
// If this is the magic class __cxxabiv1::__fundamental_type_info,
// we will emit the typeinfo for the fundamental types. This is the
// same behaviour as GCC.
@@ -1703,8 +1697,14 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
CGM.getItaniumVTableContext().getVTableLayout(RD);
llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
+ // Use pointer alignment for the vtable. Otherwise we would align them based
+ // on the size of the initializer which doesn't make sense as only single
+ // values are read.
+ unsigned PAlign = CGM.getTarget().getPointerAlign(0);
+
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
- Name, VTableType, llvm::GlobalValue::ExternalLinkage);
+ Name, VTableType, llvm::GlobalValue::ExternalLinkage,
+ getContext().toCharUnitsFromBits(PAlign).getQuantity());
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
CGM.setGVProperties(VTable, RD);
@@ -1750,7 +1750,7 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
VFunc = VFuncLoad;
}
- CGCallee Callee(MethodDecl->getCanonicalDecl(), VFunc);
+ CGCallee Callee(GD, VFunc);
return Callee;
}
@@ -1778,7 +1778,8 @@ void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
}
-bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
+bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
+ const CXXRecordDecl *RD) const {
// We don't emit available_externally vtables if we are in -fapple-kext mode
// because kext mode does not permit devirtualization.
if (CGM.getLangOpts().AppleKext)
@@ -1796,7 +1797,43 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
// to emit an available_externally copy of vtable.
// FIXME we can still emit a copy of the vtable if we
// can emit definition of the inline functions.
- return !hasAnyUnusedVirtualInlineFunction(RD);
+ if (hasAnyUnusedVirtualInlineFunction(RD))
+ return false;
+
+ // For a class with virtual bases, we must also be able to speculatively
+ // emit the VTT, because CodeGen doesn't have separate notions of "can emit
+ // the vtable" and "can emit the VTT". For a base subobject, this means we
+ // need to be able to emit non-virtual base vtables.
+ if (RD->getNumVBases()) {
+ for (const auto &B : RD->bases()) {
+ auto *BRD = B.getType()->getAsCXXRecordDecl();
+ assert(BRD && "no class for base specifier");
+ if (B.isVirtual() || !BRD->isDynamicClass())
+ continue;
+ if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
+ if (!canSpeculativelyEmitVTableAsBaseClass(RD))
+ return false;
+
+ // For a complete-object vtable (or more specifically, for the VTT), we need
+ // to be able to speculatively emit the vtables of all dynamic virtual bases.
+ for (const auto &B : RD->vbases()) {
+ auto *BRD = B.getType()->getAsCXXRecordDecl();
+ assert(BRD && "no class for base specifier");
+ if (!BRD->isDynamicClass())
+ continue;
+ if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
+ return false;
+ }
+
+ return true;
}
static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
Address InitialPtr,
@@ -1916,7 +1953,7 @@ Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
// Handle the array cookie specially in ASan.
if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
(expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
- CGM.getCodeGenOpts().SanitizeAddressPoisonClassMemberArrayNewCookie)) {
+ CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
// The store to the CookiePtr does not need to be instrumented.
CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI);
llvm::FunctionType *FTy =
@@ -2315,11 +2352,13 @@ void CodeGenModule::registerGlobalDtorsWithAtExit() {
FTy, GlobalInitFnName, getTypes().arrangeNullaryFunction(),
SourceLocation());
ASTContext &Ctx = getContext();
+ QualType ReturnTy = Ctx.VoidTy;
+ QualType FunctionTy = Ctx.getFunctionType(ReturnTy, llvm::None, {});
FunctionDecl *FD = FunctionDecl::Create(
Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
- &Ctx.Idents.get(GlobalInitFnName), Ctx.VoidTy, nullptr, SC_Static,
+ &Ctx.Idents.get(GlobalInitFnName), FunctionTy, nullptr, SC_Static,
false, false);
- CGF.StartFunction(GlobalDecl(FD), getContext().VoidTy, GlobalInitFn,
+ CGF.StartFunction(GlobalDecl(FD), ReturnTy, GlobalInitFn,
getTypes().arrangeNullaryFunction(), FunctionArgList(),
SourceLocation(), SourceLocation());
@@ -2342,6 +2381,9 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
llvm::Constant *dtor,
llvm::Constant *addr) {
+ if (D.isNoDestroy(CGM.getContext()))
+ return;
+
// Use __cxa_atexit if available.
if (CGM.getCodeGenOpts().CXAAtExit)
return emitGlobalDtorWithCXAAtExit(CGF, dtor, addr, D.getTLSKind());
@@ -2415,7 +2457,7 @@ ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM),
WrapperName.str(), &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(nullptr, FI, Wrapper);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper);
if (VD->hasDefinition())
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper);
@@ -2469,8 +2511,8 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
CharUnits GuardAlign = CharUnits::One();
Guard->setAlignment(GuardAlign.getQuantity());
- CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, OrderedInits,
- Address(Guard, GuardAlign));
+ CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(
+ InitFunc, OrderedInits, ConstantAddress(Guard, GuardAlign));
// On Darwin platforms, use CXX_FAST_TLS calling convention.
if (CGM.getTarget().getTriple().isOSDarwin()) {
InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
@@ -2522,7 +2564,8 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
llvm::GlobalVariable::ExternalWeakLinkage,
InitFnName.str(), &CGM.getModule());
const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
- CGM.SetLLVMFunctionAttributes(nullptr, FI, cast<llvm::Function>(Init));
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI,
+ cast<llvm::Function>(Init));
}
if (Init) {
@@ -2722,9 +2765,10 @@ llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
// get the mangled name of the type.
llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
Name.substr(4));
+ auto Align = CGM.getContext().getTypeAlignInChars(CGM.getContext().CharTy);
- llvm::GlobalVariable *GV =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);
+ llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
+ Name, Init->getType(), Linkage, Align.getQuantity());
GV->setInitializer(Init);
@@ -2808,6 +2852,9 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
@@ -3084,7 +3131,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
}
assert(isa<ObjCInterfaceType>(Ty));
- // Fall through.
+ LLVM_FALLTHROUGH;
case Type::ObjCInterface:
if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
@@ -3363,6 +3410,10 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
if (CGM.supportsCOMDAT() && GV->isWeakForLinker())
GV->setComdat(M.getOrInsertComdat(GV->getName()));
+ CharUnits Align =
+ CGM.getContext().toCharUnitsFromBits(CGM.getTarget().getPointerAlign(0));
+ GV->setAlignment(Align.getQuantity());
+
// The Itanium ABI specifies that type_info objects must be globally
// unique, with one exception: if the type is an incomplete class
// type or a (possibly indirect) pointer to one. That exception
@@ -4017,7 +4068,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
switch (CatchType.getQualifiers().getObjCLifetime()) {
case Qualifiers::OCL_Strong:
CastExn = CGF.EmitARCRetainNonBlock(CastExn);
- // fallthrough
+ LLVM_FALLTHROUGH;
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
@@ -4146,7 +4197,7 @@ void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
// Emit the local.
CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
- InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart());
+ InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());
CGF.EmitAutoVarCleanups(var);
}
diff --git a/lib/CodeGen/MacroPPCallbacks.cpp b/lib/CodeGen/MacroPPCallbacks.cpp
index 48dea7d54b1e..013ca15e2391 100644
--- a/lib/CodeGen/MacroPPCallbacks.cpp
+++ b/lib/CodeGen/MacroPPCallbacks.cpp
@@ -14,7 +14,8 @@
#include "MacroPPCallbacks.h"
#include "CGDebugInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Parse/Parser.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
using namespace clang;
@@ -88,16 +89,6 @@ SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {
return SourceLocation();
}
-static bool isBuiltinFile(SourceManager &SM, SourceLocation Loc) {
- StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
- return Filename.equals("<built-in>");
-}
-
-static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) {
- StringRef Filename(SM.getPresumedLoc(Loc).getFilename());
- return Filename.equals("<command line>");
-}
-
void MacroPPCallbacks::updateStatusToNextScope() {
switch (Status) {
case NoScope:
@@ -127,7 +118,7 @@ void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
updateStatusToNextScope();
return;
case BuiltinScope:
- if (isCommandLineFile(PP.getSourceManager(), Loc))
+ if (PP.getSourceManager().isWrittenInCommandLineFile(Loc))
return;
updateStatusToNextScope();
LLVM_FALLTHROUGH;
@@ -147,7 +138,7 @@ void MacroPPCallbacks::FileExited(SourceLocation Loc) {
default:
llvm_unreachable("Do not expect to exit a file from current scope");
case BuiltinScope:
- if (!isBuiltinFile(PP.getSourceManager(), Loc))
+ if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc))
// Skip next scope and change status to MainFileScope.
Status = MainFileScope;
return;
diff --git a/lib/CodeGen/MacroPPCallbacks.h b/lib/CodeGen/MacroPPCallbacks.h
index 48c67e2d36ad..b87a4005d481 100644
--- a/lib/CodeGen/MacroPPCallbacks.h
+++ b/lib/CodeGen/MacroPPCallbacks.h
@@ -11,6 +11,9 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LIB_CODEGEN_MACROPPCALLBACKS_H
+#define LLVM_CLANG_LIB_CODEGEN_MACROPPCALLBACKS_H
+
#include "clang/Lex/PPCallbacks.h"
namespace llvm {
@@ -116,3 +119,5 @@ public:
};
} // end namespace clang
+
+#endif
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 059adb78ca30..5545bc6647e6 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1552,9 +1552,9 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
if (Type == Dtor_Complete && DD->getParent()->getNumVBases() == 0)
Type = Dtor_Base;
- CGCallee Callee = CGCallee::forDirect(
- CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
- DD);
+ CGCallee Callee =
+ CGCallee::forDirect(CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
+ GlobalDecl(DD, Type));
if (DD->isVirtual()) {
assert(Type != CXXDtorType::Dtor_Deleting &&
@@ -1872,7 +1872,7 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
}
- CGCallee Callee(MethodDecl->getCanonicalDecl(), VFunc);
+ CGCallee Callee(GD, VFunc);
return Callee;
}
@@ -2024,8 +2024,10 @@ MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
assert(!CGM.getModule().getNamedGlobal(Name) &&
"vbtable with this name already exists: mangling bug?");
- llvm::GlobalVariable *GV =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, VBTableType, Linkage);
+ CharUnits Alignment =
+ CGM.getContext().getTypeAlignInChars(CGM.getContext().IntTy);
+ llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
+ Name, VBTableType, Linkage, Alignment.getQuantity());
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
if (RD->hasAttr<DLLImportAttr>())
@@ -2240,6 +2242,9 @@ static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD,
void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *Dtor,
llvm::Constant *Addr) {
+ if (D.isNoDestroy(CGM.getContext()))
+ return;
+
if (D.getTLSKind())
return emitGlobalDtorWithTLRegDtor(CGF, D, Dtor, Addr);
@@ -3924,7 +3929,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
CallArgList Args;
// Push the this ptr.
- Args.add(RValue::get(This), CD->getThisType(getContext()));
+ Args.add(RValue::get(This), CD->getThisType());
// Push the src ptr.
if (SrcVal)
@@ -3951,7 +3956,8 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
// Call the destructor with our arguments.
llvm::Constant *CalleePtr =
CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
- CGCallee Callee = CGCallee::forDirect(CalleePtr, CD);
+ CGCallee Callee =
+ CGCallee::forDirect(CalleePtr, GlobalDecl(CD, Ctor_Complete));
const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall(
Args, CD, Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix);
CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args);
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 8aa9bfb421b4..c0a37698e762 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -17,9 +17,9 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LLVMContext.h"
@@ -64,7 +64,7 @@ namespace {
std::unique_ptr<CodeGen::CodeGenModule> Builder;
private:
- SmallVector<CXXMethodDecl *, 8> DeferredInlineMethodDefinitions;
+ SmallVector<FunctionDecl *, 8> DeferredInlineMemberFuncDefs;
public:
CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName,
@@ -80,7 +80,7 @@ namespace {
~CodeGeneratorImpl() override {
// There should normally not be any leftover inline method definitions.
- assert(DeferredInlineMethodDefinitions.empty() ||
+ assert(DeferredInlineMemberFuncDefs.empty() ||
Diags.hasErrorOccurred());
}
@@ -132,6 +132,9 @@ namespace {
M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple());
M->setDataLayout(Ctx->getTargetInfo().getDataLayout());
+ const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion();
+ if (!SDKVersion.empty())
+ M->setSDKVersion(SDKVersion);
Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts,
PreprocessorOpts, CodeGenOpts,
*M, Diags, CoverageInfo));
@@ -163,16 +166,16 @@ namespace {
}
void EmitDeferredDecls() {
- if (DeferredInlineMethodDefinitions.empty())
+ if (DeferredInlineMemberFuncDefs.empty())
return;
// Emit any deferred inline method definitions. Note that more deferred
// methods may be added during this loop, since ASTConsumer callbacks
// can be invoked if AST inspection results in declarations being added.
HandlingTopLevelDeclRAII HandlingDecl(*this);
- for (unsigned I = 0; I != DeferredInlineMethodDefinitions.size(); ++I)
- Builder->EmitTopLevelDecl(DeferredInlineMethodDefinitions[I]);
- DeferredInlineMethodDefinitions.clear();
+ for (unsigned I = 0; I != DeferredInlineMemberFuncDefs.size(); ++I)
+ Builder->EmitTopLevelDecl(DeferredInlineMemberFuncDefs[I]);
+ DeferredInlineMemberFuncDefs.clear();
}
void HandleInlineFunctionDefinition(FunctionDecl *D) override {
@@ -181,17 +184,6 @@ namespace {
assert(D->doesThisDeclarationHaveABody());
- // Handle friend functions.
- if (D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)) {
- if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()
- && !D->getLexicalDeclContext()->isDependentContext())
- Builder->EmitTopLevelDecl(D);
- return;
- }
-
- // Otherwise, must be a method.
- auto MD = cast<CXXMethodDecl>(D);
-
// We may want to emit this definition. However, that decision might be
// based on computing the linkage, and we have to defer that in case we
// are inside of something that will change the method's final linkage,
@@ -200,13 +192,13 @@ namespace {
// void bar();
// void foo() { bar(); }
// } A;
- DeferredInlineMethodDefinitions.push_back(MD);
+ DeferredInlineMemberFuncDefs.push_back(D);
// Provide some coverage mapping even for methods that aren't emitted.
// Don't do this for templated classes though, as they may not be
// instantiable.
- if (!MD->getParent()->isDependentContext())
- Builder->AddDeferredUnusedCoverageMapping(MD);
+ if (!D->getLexicalDeclContext()->isDependentContext())
+ Builder->AddDeferredUnusedCoverageMapping(D);
}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
diff --git a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
index c164cec5d942..6f00c836f93d 100644
--- a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
+++ b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
@@ -14,14 +14,13 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/BackendUtil.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Serialization/ASTWriter.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -156,6 +155,8 @@ public:
LangOpts.CurrentModule.empty() ? MainFileName : LangOpts.CurrentModule;
CodeGenOpts.setDebugInfo(codegenoptions::FullDebugInfo);
CodeGenOpts.setDebuggerTuning(CI.getCodeGenOpts().getDebuggerTuning());
+ CodeGenOpts.DebugPrefixMap =
+ CI.getInvocation().getCodeGenOpts().DebugPrefixMap;
}
~PCHContainerGenerator() override = default;
diff --git a/lib/CodeGen/SwiftCallingConv.cpp b/lib/CodeGen/SwiftCallingConv.cpp
index b411a501ea81..75a0fa5ce189 100644
--- a/lib/CodeGen/SwiftCallingConv.cpp
+++ b/lib/CodeGen/SwiftCallingConv.cpp
@@ -415,6 +415,40 @@ static bool areBytesInSameUnit(CharUnits first, CharUnits second,
== getOffsetAtStartOfUnit(second, chunkSize);
}
+static bool isMergeableEntryType(llvm::Type *type) {
+ // Opaquely-typed memory is always mergeable.
+ if (type == nullptr) return true;
+
+ // Pointers and integers are always mergeable. In theory we should not
+ // merge pointers, but (1) it doesn't currently matter in practice because
+ // the chunk size is never greater than the size of a pointer and (2)
+ // Swift IRGen uses integer types for a lot of things that are "really"
+ // just storing pointers (like Optional<SomePointer>). If we ever have a
+ // target that would otherwise combine pointers, we should put some effort
+ // into fixing those cases in Swift IRGen and then call out pointer types
+ // here.
+
+ // Floating-point and vector types should never be merged.
+ // Most such types are too large and highly-aligned to ever trigger merging
+ // in practice, but it's important for the rule to cover at least 'half'
+ // and 'float', as well as things like small vectors of 'i1' or 'i8'.
+ return (!type->isFloatingPointTy() && !type->isVectorTy());
+}
+
+bool SwiftAggLowering::shouldMergeEntries(const StorageEntry &first,
+ const StorageEntry &second,
+ CharUnits chunkSize) {
+ // Only merge entries that overlap the same chunk. We test this first
+ // despite being a bit more expensive because this is the condition that
+ // tends to prevent merging.
+ if (!areBytesInSameUnit(first.End - CharUnits::One(), second.Begin,
+ chunkSize))
+ return false;
+
+ return (isMergeableEntryType(first.Type) &&
+ isMergeableEntryType(second.Type));
+}
+
void SwiftAggLowering::finish() {
if (Entries.empty()) {
Finished = true;
@@ -425,12 +459,12 @@ void SwiftAggLowering::finish() {
// which is generally the size of a pointer.
const CharUnits chunkSize = getMaximumVoluntaryIntegerSize(CGM);
- // First pass: if two entries share a chunk, make them both opaque
+ // First pass: if two entries should be merged, make them both opaque
// and stretch one to meet the next.
+ // Also, remember if there are any opaque entries.
bool hasOpaqueEntries = (Entries[0].Type == nullptr);
for (size_t i = 1, e = Entries.size(); i != e; ++i) {
- if (areBytesInSameUnit(Entries[i - 1].End - CharUnits::One(),
- Entries[i].Begin, chunkSize)) {
+ if (shouldMergeEntries(Entries[i - 1], Entries[i], chunkSize)) {
Entries[i - 1].Type = nullptr;
Entries[i].Type = nullptr;
Entries[i - 1].End = Entries[i].Begin;
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 6f6c5f50c2e7..89ec73670a73 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -19,9 +19,9 @@
#include "CGValue.h"
#include "CodeGenFunction.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/CodeGen/SwiftCallingConv.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
@@ -720,10 +720,12 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
// This is a very simple ABI that relies a lot on DefaultABIInfo.
//===----------------------------------------------------------------------===//
-class WebAssemblyABIInfo final : public DefaultABIInfo {
+class WebAssemblyABIInfo final : public SwiftABIInfo {
+ DefaultABIInfo defaultInfo;
+
public:
explicit WebAssemblyABIInfo(CodeGen::CodeGenTypes &CGT)
- : DefaultABIInfo(CGT) {}
+ : SwiftABIInfo(CGT), defaultInfo(CGT) {}
private:
ABIArgInfo classifyReturnType(QualType RetTy) const;
@@ -741,6 +743,15 @@ private:
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
+
+ bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
+ bool asReturnValue) const override {
+ return occupiesMoreThan(CGT, scalars, /*total*/ 4);
+ }
+
+ bool isSwiftErrorInRegister() const override {
+ return false;
+ }
};
class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
@@ -778,7 +789,7 @@ ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const {
}
// Otherwise just do the default thing.
- return DefaultABIInfo::classifyArgumentType(Ty);
+ return defaultInfo.classifyArgumentType(Ty);
}
ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const {
@@ -798,7 +809,7 @@ ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const {
}
// Otherwise just do the default thing.
- return DefaultABIInfo::classifyReturnType(RetTy);
+ return defaultInfo.classifyReturnType(RetTy);
}
Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
@@ -2337,7 +2348,7 @@ static std::string qualifyWindowsLibrary(llvm::StringRef Lib) {
bool Quote = (Lib.find(" ") != StringRef::npos);
std::string ArgStr = Quote ? "\"" : "";
ArgStr += Lib;
- if (!Lib.endswith_lower(".lib"))
+ if (!Lib.endswith_lower(".lib") && !Lib.endswith_lower(".a"))
ArgStr += ".lib";
ArgStr += Quote ? "\"" : "";
return ArgStr;
@@ -3944,18 +3955,39 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Width));
}
- // Bool type is always extended to the ABI, other builtin types are not
- // extended.
- const BuiltinType *BT = Ty->getAs<BuiltinType>();
- if (BT && BT->getKind() == BuiltinType::Bool)
- return ABIArgInfo::getExtend(Ty);
+ if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
+ switch (BT->getKind()) {
+ case BuiltinType::Bool:
+ // Bool type is always extended to the ABI, other builtin types are not
+ // extended.
+ return ABIArgInfo::getExtend(Ty);
- // Mingw64 GCC uses the old 80 bit extended precision floating point unit. It
- // passes them indirectly through memory.
- if (IsMingw64 && BT && BT->getKind() == BuiltinType::LongDouble) {
- const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
- if (LDF == &llvm::APFloat::x87DoubleExtended())
- return ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+ case BuiltinType::LongDouble:
+ // Mingw64 GCC uses the old 80 bit extended precision floating point
+ // unit. It passes them indirectly through memory.
+ if (IsMingw64) {
+ const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
+ if (LDF == &llvm::APFloat::x87DoubleExtended())
+ return ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+ }
+ break;
+
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ // If it's a parameter type, the normal ABI rule is that arguments larger
+ // than 8 bytes are passed indirectly. GCC follows it. We follow it too,
+ // even though it isn't particularly efficient.
+ if (!IsReturnType)
+ return ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+
+ // Mingw64 GCC returns i128 in XMM0. Coerce to v2i64 to handle that.
+ // Clang matches them for compatibility.
+ return ABIArgInfo::getDirect(
+ llvm::VectorType::get(llvm::Type::getInt64Ty(getVMContext()), 2));
+
+ default:
+ break;
+ }
}
return ABIArgInfo::getDirect();
@@ -4969,6 +5001,31 @@ public:
}
bool doesReturnSlotInterfereWithArgs() const override { return false; }
+
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override {
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (!FD)
+ return;
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+
+ auto Kind = CGM.getCodeGenOpts().getSignReturnAddress();
+ if (Kind != CodeGenOptions::SignReturnAddressScope::None) {
+ Fn->addFnAttr("sign-return-address",
+ Kind == CodeGenOptions::SignReturnAddressScope::All
+ ? "all"
+ : "non-leaf");
+
+ auto Key = CGM.getCodeGenOpts().getSignReturnAddressKey();
+ Fn->addFnAttr("sign-return-address-key",
+ Key == CodeGenOptions::SignReturnAddressKeyValue::AKey
+ ? "a_key"
+ : "b_key");
+ }
+
+ if (CGM.getCodeGenOpts().BranchTargetEnforcement)
+ Fn->addFnAttr("branch-target-enforcement");
+ }
};
class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
@@ -4976,6 +5033,9 @@ public:
WindowsAArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind K)
: AArch64TargetCodeGenInfo(CGT, K) {}
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override;
+
void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const override {
Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
@@ -4986,6 +5046,14 @@ public:
Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
}
};
+
+void WindowsAArch64TargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
+ AArch64TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+ if (GV->isDeclaration())
+ return;
+ addStackProbeTargetAttributes(D, GV, CGM);
+}
}
ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
@@ -5532,6 +5600,9 @@ public:
private:
ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic) const;
ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic) const;
+ ABIArgInfo classifyHomogeneousAggregate(QualType Ty, const Type *Base,
+ uint64_t Members) const;
+ ABIArgInfo coerceIllegalVector(QualType Ty) const;
bool isIllegalVectorType(QualType Ty) const;
bool isHomogeneousAggregateBaseType(QualType Ty) const override;
@@ -5706,6 +5777,41 @@ void ARMABIInfo::setCCs() {
RuntimeCC = abiCC;
}
+ABIArgInfo ARMABIInfo::coerceIllegalVector(QualType Ty) const {
+ uint64_t Size = getContext().getTypeSize(Ty);
+ if (Size <= 32) {
+ llvm::Type *ResType =
+ llvm::Type::getInt32Ty(getVMContext());
+ return ABIArgInfo::getDirect(ResType);
+ }
+ if (Size == 64 || Size == 128) {
+ llvm::Type *ResType = llvm::VectorType::get(
+ llvm::Type::getInt32Ty(getVMContext()), Size / 32);
+ return ABIArgInfo::getDirect(ResType);
+ }
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+}
+
+ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty,
+ const Type *Base,
+ uint64_t Members) const {
+ assert(Base && "Base class should be set for homogeneous aggregate");
+ // Base can be a floating-point or a vector.
+ if (const VectorType *VT = Base->getAs<VectorType>()) {
+ // FP16 vectors should be converted to integer vectors
+ if (!getTarget().hasLegalHalfType() &&
+ (VT->getElementType()->isFloat16Type() ||
+ VT->getElementType()->isHalfType())) {
+ uint64_t Size = getContext().getTypeSize(VT);
+ llvm::Type *NewVecTy = llvm::VectorType::get(
+ llvm::Type::getInt32Ty(getVMContext()), Size / 32);
+ llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members);
+ return ABIArgInfo::getDirect(Ty, 0, nullptr, false);
+ }
+ }
+ return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
+}
+
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
bool isVariadic) const {
// 6.1.2.1 The following argument types are VFP CPRCs:
@@ -5720,25 +5826,8 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
Ty = useFirstFieldIfTransparentUnion(Ty);
// Handle illegal vector types here.
- if (isIllegalVectorType(Ty)) {
- uint64_t Size = getContext().getTypeSize(Ty);
- if (Size <= 32) {
- llvm::Type *ResType =
- llvm::Type::getInt32Ty(getVMContext());
- return ABIArgInfo::getDirect(ResType);
- }
- if (Size == 64) {
- llvm::Type *ResType = llvm::VectorType::get(
- llvm::Type::getInt32Ty(getVMContext()), 2);
- return ABIArgInfo::getDirect(ResType);
- }
- if (Size == 128) {
- llvm::Type *ResType = llvm::VectorType::get(
- llvm::Type::getInt32Ty(getVMContext()), 4);
- return ABIArgInfo::getDirect(ResType);
- }
- return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
- }
+ if (isIllegalVectorType(Ty))
+ return coerceIllegalVector(Ty);
// _Float16 and __fp16 get passed as if it were an int or float, but with
// the top 16 bits unspecified. This is not done for OpenCL as it handles the
@@ -5774,11 +5863,8 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
// into VFP registers.
const Type *Base = nullptr;
uint64_t Members = 0;
- if (isHomogeneousAggregate(Ty, Base, Members)) {
- assert(Base && "Base class should be set for homogeneous aggregate");
- // Base can be a floating-point or a vector.
- return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
- }
+ if (isHomogeneousAggregate(Ty, Base, Members))
+ return classifyHomogeneousAggregate(Ty, Base, Members);
} else if (getABIKind() == ARMABIInfo::AAPCS16_VFP) {
// WatchOS does have homogeneous aggregates. Note that we intentionally use
// this convention even for a variadic function: the backend will use GPRs
@@ -5937,9 +6023,15 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
- // Large vector types should be returned via memory.
- if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) {
- return getNaturalAlignIndirect(RetTy);
+ if (const VectorType *VT = RetTy->getAs<VectorType>()) {
+ // Large vector types should be returned via memory.
+ if (getContext().getTypeSize(RetTy) > 128)
+ return getNaturalAlignIndirect(RetTy);
+ // FP16 vectors should be converted to integer vectors
+ if (!getTarget().hasLegalHalfType() &&
+ (VT->getElementType()->isFloat16Type() ||
+ VT->getElementType()->isHalfType()))
+ return coerceIllegalVector(RetTy);
}
// _Float16 and __fp16 get returned as if it were an int or float, but with
@@ -5999,11 +6091,8 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
if (IsEffectivelyAAPCS_VFP) {
const Type *Base = nullptr;
uint64_t Members = 0;
- if (isHomogeneousAggregate(RetTy, Base, Members)) {
- assert(Base && "Base class should be set for homogeneous aggregate");
- // Homogeneous Aggregates are returned directly.
- return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
- }
+ if (isHomogeneousAggregate(RetTy, Base, Members))
+ return classifyHomogeneousAggregate(RetTy, Base, Members);
}
// Aggregates <= 4 bytes are returned in r0; other aggregates
@@ -6038,6 +6127,13 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
/// isIllegalVector - check whether Ty is an illegal vector type.
bool ARMABIInfo::isIllegalVectorType(QualType Ty) const {
if (const VectorType *VT = Ty->getAs<VectorType> ()) {
+ // On targets that don't support FP16, FP16 is expanded into float, and we
+ // don't want the ABI to depend on whether or not FP16 is supported in
+ // hardware. Thus return false to coerce FP16 vectors into integer vectors.
+ if (!getTarget().hasLegalHalfType() &&
+ (VT->getElementType()->isFloat16Type() ||
+ VT->getElementType()->isHalfType()))
+ return true;
if (isAndroid()) {
// Android shipped using Clang 3.1, which supported a slightly different
// vector ABI. The primary differences were that 3-element vector types
@@ -8164,6 +8260,137 @@ SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
return false;
}
+// ARC ABI implementation.
+namespace {
+
+class ARCABIInfo : public DefaultABIInfo {
+public:
+ using DefaultABIInfo::DefaultABIInfo;
+
+private:
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
+
+ void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
+ if (!State.FreeRegs)
+ return;
+ if (Info.isIndirect() && Info.getInReg())
+ State.FreeRegs--;
+ else if (Info.isDirect() && Info.getInReg()) {
+ unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
+ if (sz < State.FreeRegs)
+ State.FreeRegs -= sz;
+ else
+ State.FreeRegs = 0;
+ }
+ }
+
+ void computeInfo(CGFunctionInfo &FI) const override {
+ CCState State(FI.getCallingConvention());
+ // ARC uses 8 registers to pass arguments.
+ State.FreeRegs = 8;
+
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ updateState(FI.getReturnInfo(), FI.getReturnType(), State);
+ for (auto &I : FI.arguments()) {
+ I.info = classifyArgumentType(I.type, State.FreeRegs);
+ updateState(I.info, I.type, State);
+ }
+ }
+
+ ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
+ ABIArgInfo getIndirectByValue(QualType Ty) const;
+ ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+};
+
+class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ ARCTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new ARCABIInfo(CGT)) {}
+};
+
+
+ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
+ return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) :
+ getNaturalAlignIndirect(Ty, false);
+}
+
+ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
+ // Compute the byval alignment.
+ const unsigned MinABIStackAlignInBytes = 4;
+ unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
+ TypeAlign > MinABIStackAlignInBytes);
+}
+
+Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ getContext().getTypeInfoInChars(Ty),
+ CharUnits::fromQuantity(4), true);
+}
+
+ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
+ uint8_t FreeRegs) const {
+ // Handle the generic C++ ABI.
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (RT) {
+ CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
+ if (RAA == CGCXXABI::RAA_Indirect)
+ return getIndirectByRef(Ty, FreeRegs > 0);
+
+ if (RAA == CGCXXABI::RAA_DirectInMemory)
+ return getIndirectByValue(Ty);
+ }
+
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
+
+ if (isAggregateTypeForABI(Ty)) {
+ // Structures with flexible arrays are always indirect.
+ if (RT && RT->getDecl()->hasFlexibleArrayMember())
+ return getIndirectByValue(Ty);
+
+ // Ignore empty structs/unions.
+ if (isEmptyRecord(getContext(), Ty, true))
+ return ABIArgInfo::getIgnore();
+
+ llvm::LLVMContext &LLVMContext = getVMContext();
+
+ llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
+ SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
+ llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
+
+ return FreeRegs >= SizeInRegs ?
+ ABIArgInfo::getDirectInReg(Result) :
+ ABIArgInfo::getDirect(Result, 0, nullptr, false);
+ }
+
+ return Ty->isPromotableIntegerType() ?
+ (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) :
+ ABIArgInfo::getExtend(Ty)) :
+ (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() :
+ ABIArgInfo::getDirect());
+}
+
+ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isAnyComplexType())
+ return ABIArgInfo::getDirectInReg();
+
+ // Arguments of size > 4 registers are indirect.
+ auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
+ if (RetSize > 4)
+ return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
+
+ return DefaultABIInfo::classifyReturnType(RetTy);
+}
+
+} // End anonymous namespace.
//===----------------------------------------------------------------------===//
// XCore ABI Implementation
@@ -8553,7 +8780,7 @@ static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT,
// The ABI requires unions to be sorted but not structures.
// See FieldEncoding::operator< for sort algorithm.
if (RT->isUnionType())
- llvm::sort(FE.begin(), FE.end());
+ llvm::sort(FE);
// We can now complete the TypeString.
unsigned E = FE.size();
for (unsigned I = 0; I != E; ++I) {
@@ -8597,7 +8824,7 @@ static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET,
EnumEnc += '}';
FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc));
}
- llvm::sort(FE.begin(), FE.end());
+ llvm::sort(FE);
unsigned E = FE.size();
for (unsigned I = 0; I != E; ++I) {
if (I)
@@ -9185,6 +9412,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
return SetCGInfo(new SparcV9TargetCodeGenInfo(Types));
case llvm::Triple::xcore:
return SetCGInfo(new XCoreTargetCodeGenInfo(Types));
+ case llvm::Triple::arc:
+ return SetCGInfo(new ARCTargetCodeGenInfo(Types));
case llvm::Triple::spir:
case llvm::Triple::spir64:
return SetCGInfo(new SPIRTargetCodeGenInfo(Types));
diff --git a/lib/CodeGen/VarBypassDetector.cpp b/lib/CodeGen/VarBypassDetector.cpp
index 2f8a591a3e7f..859cdd4282cc 100644
--- a/lib/CodeGen/VarBypassDetector.cpp
+++ b/lib/CodeGen/VarBypassDetector.cpp
@@ -78,7 +78,7 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
return false;
++StmtsToSkip;
}
- // Fall through
+ LLVM_FALLTHROUGH;
case Stmt::GotoStmtClass:
FromScopes.push_back({S, ParentScope});
diff --git a/lib/CodeGen/VarBypassDetector.h b/lib/CodeGen/VarBypassDetector.h
index f50baf4bab9f..47fe13cfacd6 100644
--- a/lib/CodeGen/VarBypassDetector.h
+++ b/lib/CodeGen/VarBypassDetector.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
#define LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
+#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/lib/CrossTU/CrossTranslationUnit.cpp b/lib/CrossTU/CrossTranslationUnit.cpp
index e20ea7702237..7c97beb498a5 100644
--- a/lib/CrossTU/CrossTranslationUnit.cpp
+++ b/lib/CrossTU/CrossTranslationUnit.cpp
@@ -17,10 +17,10 @@
#include "clang/CrossTU/CrossTUDiagnostic.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
@@ -32,6 +32,47 @@ namespace clang {
namespace cross_tu {
namespace {
+
+#define DEBUG_TYPE "CrossTranslationUnit"
+STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
+STATISTIC(
+ NumNotInOtherTU,
+ "The # of getCTUDefinition called but the function is not in any other TU");
+STATISTIC(NumGetCTUSuccess,
+ "The # of getCTUDefinition successfully returned the "
+ "requested function's body");
+STATISTIC(NumTripleMismatch, "The # of triple mismatches");
+STATISTIC(NumLangMismatch, "The # of language mismatches");
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple &Lhs, const llvm::Triple &Rhs) {
+ using llvm::Triple;
+ if (Lhs.getArch() != Triple::UnknownArch &&
+ Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+ return false;
+ if (Lhs.getSubArch() != Triple::NoSubArch &&
+ Rhs.getSubArch() != Triple::NoSubArch &&
+ Lhs.getSubArch() != Rhs.getSubArch())
+ return false;
+ if (Lhs.getVendor() != Triple::UnknownVendor &&
+ Rhs.getVendor() != Triple::UnknownVendor &&
+ Lhs.getVendor() != Rhs.getVendor())
+ return false;
+ if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+ Lhs.getOS() != Rhs.getOS())
+ return false;
+ if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+ Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+ Lhs.getEnvironment() != Rhs.getEnvironment())
+ return false;
+ if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+ Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+ Lhs.getObjectFormat() != Rhs.getObjectFormat())
+ return false;
+ return true;
+}
+
// FIXME: This class is will be removed after the transition to llvm::Error.
class IndexErrorCategory : public std::error_category {
public:
@@ -55,6 +96,10 @@ public:
return "Failed to load external AST source.";
case index_error_code::failed_to_generate_usr:
return "Failed to generate USR.";
+ case index_error_code::triple_mismatch:
+ return "Triple mismatch";
+ case index_error_code::lang_mismatch:
+ return "Language mismatch";
}
llvm_unreachable("Unrecognized index_error_code.");
}
@@ -75,26 +120,26 @@ std::error_code IndexError::convertToErrorCode() const {
llvm::Expected<llvm::StringMap<std::string>>
parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir) {
- std::ifstream ExternalFnMapFile(IndexPath);
- if (!ExternalFnMapFile)
+ std::ifstream ExternalMapFile(IndexPath);
+ if (!ExternalMapFile)
return llvm::make_error<IndexError>(index_error_code::missing_index_file,
IndexPath.str());
llvm::StringMap<std::string> Result;
std::string Line;
unsigned LineNo = 1;
- while (std::getline(ExternalFnMapFile, Line)) {
+ while (std::getline(ExternalMapFile, Line)) {
const size_t Pos = Line.find(" ");
if (Pos > 0 && Pos != std::string::npos) {
StringRef LineRef{Line};
- StringRef FunctionLookupName = LineRef.substr(0, Pos);
- if (Result.count(FunctionLookupName))
+ StringRef LookupName = LineRef.substr(0, Pos);
+ if (Result.count(LookupName))
return llvm::make_error<IndexError>(
index_error_code::multiple_definitions, IndexPath.str(), LineNo);
StringRef FileName = LineRef.substr(Pos + 1);
SmallString<256> FilePath = CrossTUDir;
llvm::sys::path::append(FilePath, FileName);
- Result[FunctionLookupName] = FilePath.str().str();
+ Result[LookupName] = FilePath.str().str();
} else
return llvm::make_error<IndexError>(
index_error_code::invalid_index_format, IndexPath.str(), LineNo);
@@ -149,23 +194,48 @@ CrossTranslationUnitContext::findFunctionInDeclContext(const DeclContext *DC,
llvm::Expected<const FunctionDecl *>
CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
StringRef CrossTUDir,
- StringRef IndexName) {
+ StringRef IndexName,
+ bool DisplayCTUProgress) {
+ assert(FD && "FD is missing, bad call to this function!");
assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+ ++NumGetCTUCalled;
const std::string LookupFnName = getLookupName(FD);
if (LookupFnName.empty())
return llvm::make_error<IndexError>(
index_error_code::failed_to_generate_usr);
llvm::Expected<ASTUnit *> ASTUnitOrError =
- loadExternalAST(LookupFnName, CrossTUDir, IndexName);
+ loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
if (!ASTUnitOrError)
return ASTUnitOrError.takeError();
ASTUnit *Unit = *ASTUnitOrError;
- if (!Unit)
- return llvm::make_error<IndexError>(
- index_error_code::failed_to_get_external_ast);
assert(&Unit->getFileManager() ==
&Unit->getASTContext().getSourceManager().getFileManager());
+ const llvm::Triple &TripleTo = Context.getTargetInfo().getTriple();
+ const llvm::Triple &TripleFrom =
+ Unit->getASTContext().getTargetInfo().getTriple();
+ // The imported AST had been generated for a different target.
+ // Some parts of the triple in the loaded ASTContext can be unknown while the
+ // very same parts in the target ASTContext are known. Thus we check for the
+ // known parts only.
+ if (!hasEqualKnownFields(TripleTo, TripleFrom)) {
+ // TODO: Pass the SourceLocation of the CallExpression for more precise
+ // diagnostics.
+ ++NumTripleMismatch;
+ return llvm::make_error<IndexError>(index_error_code::triple_mismatch,
+ Unit->getMainFileName(), TripleTo.str(),
+ TripleFrom.str());
+ }
+
+ const auto &LangTo = Context.getLangOpts();
+ const auto &LangFrom = Unit->getASTContext().getLangOpts();
+ // FIXME: Currenty we do not support CTU across C++ and C and across
+ // different dialects of C++.
+ if (LangTo.CPlusPlus != LangFrom.CPlusPlus) {
+ ++NumLangMismatch;
+ return llvm::make_error<IndexError>(index_error_code::lang_mismatch);
+ }
+
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
if (const FunctionDecl *ResultDecl =
findFunctionInDeclContext(TU, LookupFnName))
@@ -176,24 +246,29 @@ CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
void CrossTranslationUnitContext::emitCrossTUDiagnostics(const IndexError &IE) {
switch (IE.getCode()) {
case index_error_code::missing_index_file:
- Context.getDiagnostics().Report(diag::err_fe_error_opening)
- << IE.getFileName() << "required by the CrossTU functionality";
+ Context.getDiagnostics().Report(diag::err_ctu_error_opening)
+ << IE.getFileName();
break;
case index_error_code::invalid_index_format:
- Context.getDiagnostics().Report(diag::err_fnmap_parsing)
+ Context.getDiagnostics().Report(diag::err_extdefmap_parsing)
<< IE.getFileName() << IE.getLineNum();
break;
case index_error_code::multiple_definitions:
Context.getDiagnostics().Report(diag::err_multiple_def_index)
<< IE.getLineNum();
break;
+ case index_error_code::triple_mismatch:
+ Context.getDiagnostics().Report(diag::warn_ctu_incompat_triple)
+ << IE.getFileName() << IE.getTripleToName() << IE.getTripleFromName();
+ break;
default:
break;
}
}
llvm::Expected<ASTUnit *> CrossTranslationUnitContext::loadExternalAST(
- StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
+ StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
+ bool DisplayCTUProgress) {
// FIXME: The current implementation only supports loading functions with
// a lookup name from a single translation unit. If multiple
// translation units contains functions with the same lookup name an
@@ -216,8 +291,10 @@ llvm::Expected<ASTUnit *> CrossTranslationUnitContext::loadExternalAST(
}
auto It = FunctionFileMap.find(LookupName);
- if (It == FunctionFileMap.end())
+ if (It == FunctionFileMap.end()) {
+ ++NumNotInOtherTU;
return llvm::make_error<IndexError>(index_error_code::missing_definition);
+ }
StringRef ASTFileName = It->second;
auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
if (ASTCacheEntry == FileASTUnitMap.end()) {
@@ -233,6 +310,10 @@ llvm::Expected<ASTUnit *> CrossTranslationUnitContext::loadExternalAST(
ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts()));
Unit = LoadedUnit.get();
FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
+ if (DisplayCTUProgress) {
+ llvm::errs() << "CTU loaded AST file: "
+ << ASTFileName << "\n";
+ }
} else {
Unit = ASTCacheEntry->second.get();
}
@@ -240,27 +321,42 @@ llvm::Expected<ASTUnit *> CrossTranslationUnitContext::loadExternalAST(
} else {
Unit = FnUnitCacheEntry->second;
}
+ if (!Unit)
+ return llvm::make_error<IndexError>(
+ index_error_code::failed_to_get_external_ast);
return Unit;
}
llvm::Expected<const FunctionDecl *>
CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
+ assert(FD->hasBody() && "Functions to be imported should have body.");
+
ASTImporter &Importer = getOrCreateASTImporter(FD->getASTContext());
auto *ToDecl =
- cast<FunctionDecl>(Importer.Import(const_cast<FunctionDecl *>(FD)));
+ cast_or_null<FunctionDecl>(Importer.Import(const_cast<FunctionDecl *>(FD)));
+ if (!ToDecl)
+ return llvm::make_error<IndexError>(index_error_code::failed_import);
assert(ToDecl->hasBody());
assert(FD->hasBody() && "Functions already imported should have body.");
+ ++NumGetCTUSuccess;
return ToDecl;
}
+void CrossTranslationUnitContext::lazyInitLookupTable(
+ TranslationUnitDecl *ToTU) {
+ if (!LookupTable)
+ LookupTable = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
+}
+
ASTImporter &
CrossTranslationUnitContext::getOrCreateASTImporter(ASTContext &From) {
auto I = ASTUnitImporterMap.find(From.getTranslationUnitDecl());
if (I != ASTUnitImporterMap.end())
return *I->second;
- ASTImporter *NewImporter =
- new ASTImporter(Context, Context.getSourceManager().getFileManager(),
- From, From.getSourceManager().getFileManager(), false);
+ lazyInitLookupTable(Context.getTranslationUnitDecl());
+ ASTImporter *NewImporter = new ASTImporter(
+ Context, Context.getSourceManager().getFileManager(), From,
+ From.getSourceManager().getFileManager(), false, LookupTable.get());
ASTUnitImporterMap[From.getTranslationUnitDecl()].reset(NewImporter);
return *NewImporter;
}
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index 99d588d9c009..d4c7040a233c 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -26,6 +26,7 @@ const char *Action::getClassName(ActionClass AC) {
return "offload";
case PreprocessJobClass: return "preprocessor";
case PrecompileJobClass: return "precompiler";
+ case HeaderModulePrecompileJobClass: return "header-module-precompiler";
case AnalyzeJobClass: return "analyzer";
case MigrateJobClass: return "migrator";
case CompileJobClass: return "compiler";
@@ -319,6 +320,19 @@ void PrecompileJobAction::anchor() {}
PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
: JobAction(PrecompileJobClass, Input, OutputType) {}
+PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
+ types::ID OutputType)
+ : JobAction(Kind, Input, OutputType) {
+ assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
+}
+
+void HeaderModulePrecompileJobAction::anchor() {}
+
+HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
+ Action *Input, types::ID OutputType, const char *ModuleName)
+ : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
+ ModuleName(ModuleName) {}
+
void AnalyzeJobAction::anchor() {}
AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
@@ -382,7 +396,7 @@ VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
void OffloadBundlingJobAction::anchor() {}
OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
- : JobAction(OffloadBundlingJobClass, Inputs, Inputs.front()->getType()) {}
+ : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
void OffloadUnbundlingJobAction::anchor() {}
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 2b03c9f7001f..4793a1f90b2f 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -12,6 +12,7 @@ endif()
add_clang_library(clangDriver
Action.cpp
Compilation.cpp
+ DarwinSDKInfo.cpp
Distro.cpp
Driver.cpp
DriverOptions.cpp
@@ -47,17 +48,19 @@ add_clang_library(clangDriver
ToolChains/Haiku.cpp
ToolChains/HIP.cpp
ToolChains/Hexagon.cpp
+ ToolChains/Hurd.cpp
ToolChains/Linux.cpp
ToolChains/MipsLinux.cpp
ToolChains/MinGW.cpp
ToolChains/Minix.cpp
+ ToolChains/MSP430.cpp
ToolChains/MSVC.cpp
ToolChains/Myriad.cpp
ToolChains/NaCl.cpp
ToolChains/NetBSD.cpp
ToolChains/OpenBSD.cpp
ToolChains/PS4CPU.cpp
- ToolChains/RISCV.cpp
+ ToolChains/RISCVToolchain.cpp
ToolChains/Solaris.cpp
ToolChains/TCE.cpp
ToolChains/WebAssembly.cpp
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index ca2525dd07fb..982d7ecad962 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -127,7 +127,7 @@ bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
return true;
}
-bool Compilation::CleanupFileList(const ArgStringList &Files,
+bool Compilation::CleanupFileList(const llvm::opt::ArgStringList &Files,
bool IssueErrors) const {
bool Success = true;
for (const auto &File: Files)
diff --git a/lib/Driver/DarwinSDKInfo.cpp b/lib/Driver/DarwinSDKInfo.cpp
new file mode 100644
index 000000000000..547978b2f973
--- /dev/null
+++ b/lib/Driver/DarwinSDKInfo.cpp
@@ -0,0 +1,44 @@
+//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/DarwinSDKInfo.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang;
+
+Expected<Optional<DarwinSDKInfo>>
+driver::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {
+ llvm::SmallString<256> Filepath = SDKRootPath;
+ llvm::sys::path::append(Filepath, "SDKSettings.json");
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ VFS.getBufferForFile(Filepath);
+ if (!File) {
+ // If the file couldn't be read, assume it just doesn't exist.
+ return None;
+ }
+ Expected<llvm::json::Value> Result =
+ llvm::json::parse(File.get()->getBuffer());
+ if (!Result)
+ return Result.takeError();
+
+ if (const auto *Obj = Result->getAsObject()) {
+ auto VersionString = Obj->getString("Version");
+ if (VersionString) {
+ VersionTuple Version;
+ if (!Version.tryParse(*VersionString))
+ return DarwinSDKInfo(Version);
+ }
+ }
+ return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",
+ llvm::inconvertibleErrorCode());
+}
diff --git a/lib/Driver/Distro.cpp b/lib/Driver/Distro.cpp
index 2c4d44faf8d0..396d0bee5603 100644
--- a/lib/Driver/Distro.cpp
+++ b/lib/Driver/Distro.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Distro.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
@@ -17,7 +18,7 @@
using namespace clang::driver;
using namespace clang;
-static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
+static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
VFS.getBufferForFile("/etc/lsb-release");
if (File) {
@@ -50,6 +51,7 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
.Case("artful", Distro::UbuntuArtful)
.Case("bionic", Distro::UbuntuBionic)
.Case("cosmic", Distro::UbuntuCosmic)
+ .Case("disco", Distro::UbuntuDisco)
.Default(Distro::UnknownDistro);
if (Version != Distro::UnknownDistro)
return Version;
@@ -136,7 +138,10 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
if (VFS.exists("/etc/arch-release"))
return Distro::ArchLinux;
+ if (VFS.exists("/etc/gentoo-release"))
+ return Distro::Gentoo;
+
return Distro::UnknownDistro;
}
-Distro::Distro(vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}
+Distro::Distro(llvm::vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 952a716cb6e6..a784e218f139 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -26,8 +26,10 @@
#include "ToolChains/HIP.h"
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
+#include "ToolChains/Hurd.h"
#include "ToolChains/Lanai.h"
#include "ToolChains/Linux.h"
+#include "ToolChains/MSP430.h"
#include "ToolChains/MSVC.h"
#include "ToolChains/MinGW.h"
#include "ToolChains/Minix.h"
@@ -37,13 +39,12 @@
#include "ToolChains/NetBSD.h"
#include "ToolChains/OpenBSD.h"
#include "ToolChains/PS4CPU.h"
-#include "ToolChains/RISCV.h"
+#include "ToolChains/RISCVToolchain.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "clang/Basic/Version.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
@@ -68,18 +69,21 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <memory>
#include <utility>
#if LLVM_ON_UNIX
#include <unistd.h> // getpid
+#include <sysexits.h> // EX_IOERR
#endif
using namespace clang::driver;
@@ -88,7 +92,7 @@ using namespace llvm::opt;
Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
: Opts(createDriverOptTable()), Diags(Diags), VFS(std::move(VFS)),
Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
@@ -98,12 +102,11 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
CCGenDiagnostics(false), TargetTriple(TargetTriple),
CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
- CCCUsePCH(true), GenReproducer(false),
- SuppressMissingInputWarning(false) {
+ GenReproducer(false), SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
- this->VFS = vfs::getRealFileSystem();
+ this->VFS = llvm::vfs::getRealFileSystem();
Name = llvm::sys::path::filename(ClangExecutable);
Dir = llvm::sys::path::parent_path(ClangExecutable);
@@ -164,6 +167,7 @@ void Driver::setDriverModeFromOption(StringRef Opt) {
}
InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
+ bool IsClCompatMode,
bool &ContainsError) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
ContainsError = false;
@@ -171,7 +175,7 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
- getIncludeExcludeOptionFlagMasks();
+ getIncludeExcludeOptionFlagMasks(IsClCompatMode);
unsigned MissingArgIndex, MissingArgCount;
InputArgList Args =
@@ -300,6 +304,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DerivedArgList *DAL = new DerivedArgList(Args);
bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
+ bool HasNostdlibxx = Args.hasArg(options::OPT_nostdlibxx);
bool HasNodefaultlib = Args.hasArg(options::OPT_nodefaultlibs);
for (Arg *A : Args) {
// Unfortunately, we have to parse some forwarding options (-Xassembler,
@@ -344,7 +349,8 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
StringRef Value = A->getValue();
// Rewrite unless -nostdlib is present.
- if (!HasNostdlib && !HasNodefaultlib && Value == "stdc++") {
+ if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx &&
+ Value == "stdc++") {
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_stdcxx));
continue;
}
@@ -399,6 +405,13 @@ static llvm::Triple computeTargetTriple(const Driver &D,
llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
+ // GNU/Hurd's triples should have been -hurd-gnu*, but were historically made
+ // -gnu* only, and we can not change this, so we have to detect that case as
+ // being the Hurd OS.
+ if (TargetTriple.find("-unknown-gnu") != StringRef::npos ||
+ TargetTriple.find("-pc-gnu") != StringRef::npos)
+ Target.setOSName("hurd");
+
// Handle Apple-specific options available here.
if (Target.isOSBinFormatMachO()) {
// If an explicit Darwin arch name is given, that trumps all.
@@ -481,6 +494,29 @@ static llvm::Triple computeTargetTriple(const Driver &D,
Target.setVendorName("intel");
}
+ // If target is MIPS adjust the target triple
+ // accordingly to provided ABI name.
+ A = Args.getLastArg(options::OPT_mabi_EQ);
+ if (A && Target.isMIPS()) {
+ StringRef ABIName = A->getValue();
+ if (ABIName == "32") {
+ Target = Target.get32BitArchVariant();
+ if (Target.getEnvironment() == llvm::Triple::GNUABI64 ||
+ Target.getEnvironment() == llvm::Triple::GNUABIN32)
+ Target.setEnvironment(llvm::Triple::GNU);
+ } else if (ABIName == "n32") {
+ Target = Target.get64BitArchVariant();
+ if (Target.getEnvironment() == llvm::Triple::GNU ||
+ Target.getEnvironment() == llvm::Triple::GNUABI64)
+ Target.setEnvironment(llvm::Triple::GNUABIN32);
+ } else if (ABIName == "64") {
+ Target = Target.get64BitArchVariant();
+ if (Target.getEnvironment() == llvm::Triple::GNU ||
+ Target.getEnvironment() == llvm::Triple::GNUABIN32)
+ Target.setEnvironment(llvm::Triple::GNUABI64);
+ }
+ }
+
return Target;
}
@@ -705,7 +741,7 @@ bool Driver::readConfigFile(StringRef FileName) {
ConfigFile = CfgFileName.str();
bool ContainErrors;
CfgOptions = llvm::make_unique<InputArgList>(
- ParseArgStrings(NewCfgArgs, ContainErrors));
+ ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors));
if (ContainErrors) {
CfgOptions.reset();
return true;
@@ -899,7 +935,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// Arguments specified in command line.
bool ContainsError;
CLOptions = llvm::make_unique<InputArgList>(
- ParseArgStrings(ArgList.slice(1), ContainsError));
+ ParseArgStrings(ArgList.slice(1), IsCLMode(), ContainsError));
// Try parsing configuration file.
if (!ContainsError)
@@ -909,22 +945,48 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// All arguments, from both config file and command line.
InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
: std::move(*CLOptions));
- if (HasConfigFile)
- for (auto *Opt : *CLOptions) {
- if (Opt->getOption().matches(options::OPT_config))
- continue;
+
+ auto appendOneArg = [&Args](const Arg *Opt, const Arg *BaseArg) {
unsigned Index = Args.MakeIndex(Opt->getSpelling());
- const Arg *BaseArg = &Opt->getBaseArg();
- if (BaseArg == Opt)
- BaseArg = nullptr;
Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Opt->getSpelling(),
Index, BaseArg);
Copy->getValues() = Opt->getValues();
if (Opt->isClaimed())
Copy->claim();
Args.append(Copy);
+ };
+
+ if (HasConfigFile)
+ for (auto *Opt : *CLOptions) {
+ if (Opt->getOption().matches(options::OPT_config))
+ continue;
+ const Arg *BaseArg = &Opt->getBaseArg();
+ if (BaseArg == Opt)
+ BaseArg = nullptr;
+ appendOneArg(Opt, BaseArg);
}
+ // In CL mode, look for any pass-through arguments
+ if (IsCLMode() && !ContainsError) {
+ SmallVector<const char *, 16> CLModePassThroughArgList;
+ for (const auto *A : Args.filtered(options::OPT__SLASH_clang)) {
+ A->claim();
+ CLModePassThroughArgList.push_back(A->getValue());
+ }
+
+ if (!CLModePassThroughArgList.empty()) {
+ // Parse any pass through args using default clang processing rather
+ // than clang-cl processing.
+ auto CLModePassThroughOptions = llvm::make_unique<InputArgList>(
+ ParseArgStrings(CLModePassThroughArgList, false, ContainsError));
+
+ if (!ContainsError)
+ for (auto *Opt : *CLModePassThroughOptions) {
+ appendOneArg(Opt, nullptr);
+ }
+ }
+ }
+
// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;
@@ -947,8 +1009,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
CCCGenericGCCName = A->getValue();
- CCCUsePCH =
- Args.hasFlag(options::OPT_ccc_pch_is_pch, options::OPT_ccc_pch_is_pth);
GenReproducer = Args.hasFlag(options::OPT_gen_reproducer,
options::OPT_fno_crash_diagnostics,
!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"));
@@ -1377,8 +1437,9 @@ int Driver::ExecuteCompilation(
// Otherwise, remove result files and print extra information about abnormal
// failures.
+ int Res = 0;
for (const auto &CmdPair : FailingCommands) {
- int Res = CmdPair.first;
+ int CommandRes = CmdPair.first;
const Command *FailingCommand = CmdPair.second;
// Remove result files if we're not saving temps.
@@ -1387,10 +1448,19 @@ int Driver::ExecuteCompilation(
C.CleanupFileMap(C.getResultFiles(), JA, true);
// Failure result files are valid unless we crashed.
- if (Res < 0)
+ if (CommandRes < 0)
C.CleanupFileMap(C.getFailureResultFiles(), JA, true);
}
+#if LLVM_ON_UNIX
+ // llvm/lib/Support/Unix/Signals.inc will exit with a special return code
+ // for SIGPIPE. Do not print diagnostics for this case.
+ if (CommandRes == EX_IOERR) {
+ Res = CommandRes;
+ continue;
+ }
+#endif
+
// Print extra information about abnormal failures, if possible.
//
// This is ad-hoc, but we don't want to be excessively noisy. If the result
@@ -1400,30 +1470,31 @@ int Driver::ExecuteCompilation(
// diagnostics, so always print the diagnostic there.
const Tool &FailingTool = FailingCommand->getCreator();
- if (!FailingCommand->getCreator().hasGoodDiagnostics() || Res != 1) {
+ if (!FailingCommand->getCreator().hasGoodDiagnostics() || CommandRes != 1) {
// FIXME: See FIXME above regarding result code interpretation.
- if (Res < 0)
+ if (CommandRes < 0)
Diag(clang::diag::err_drv_command_signalled)
<< FailingTool.getShortName();
else
- Diag(clang::diag::err_drv_command_failed) << FailingTool.getShortName()
- << Res;
+ Diag(clang::diag::err_drv_command_failed)
+ << FailingTool.getShortName() << CommandRes;
}
}
- return 0;
+ return Res;
}
void Driver::PrintHelp(bool ShowHidden) const {
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
- getIncludeExcludeOptionFlagMasks();
+ getIncludeExcludeOptionFlagMasks(IsCLMode());
ExcludedFlagsBitmask |= options::NoDriverOption;
if (!ShowHidden)
ExcludedFlagsBitmask |= HelpHidden;
- getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(),
+ std::string Usage = llvm::formatv("{0} [options] file...", Name).str();
+ getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
IncludedFlagsBitmask, ExcludedFlagsBitmask,
/*ShowAllAliases=*/false);
}
@@ -1472,6 +1543,11 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
unsigned short DisableFlags =
options::NoDriverOption | options::Unsupported | options::Ignored;
+ // Distinguish "--autocomplete=-someflag" and "--autocomplete=-someflag,"
+ // because the latter indicates that the user put space before pushing tab
+ // which should end up in a file completion.
+ const bool HasSpace = PassedFlags.endswith(",");
+
// Parse PassedFlags by "," as all the command-line flags are passed to this
// function separated by ","
StringRef TargetFlags = PassedFlags;
@@ -1498,7 +1574,19 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
if (SuggestedCompletions.empty())
SuggestedCompletions = Opts->suggestValueCompletions(Cur, "");
- if (SuggestedCompletions.empty()) {
+ // If Flags were empty, it means the user typed `clang [tab]` where we should
+ // list all possible flags. If there was no value completion and the user
+ // pressed tab after a space, we should fall back to a file completion.
+ // We're printing a newline to be consistent with what we print at the end of
+ // this function.
+ if (SuggestedCompletions.empty() && HasSpace && !Flags.empty()) {
+ llvm::outs() << '\n';
+ return;
+ }
+
+ // When flag ends with '=' and there was no value completion, return empty
+ // string and fall back to the file autocompletion.
+ if (SuggestedCompletions.empty() && !Cur.endswith("=")) {
// If the flag is in the form of "--autocomplete=-foo",
// we were requested to print out all option names that start with "-foo".
// For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
@@ -1516,12 +1604,11 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
// deterministic order. We could sort in any way, but we chose
// case-insensitive sorting for consistency with the -help option
// which prints out options in the case-insensitive alphabetical order.
- llvm::sort(SuggestedCompletions.begin(), SuggestedCompletions.end(),
- [](StringRef A, StringRef B) {
- if (int X = A.compare_lower(B))
- return X < 0;
- return A.compare(B) > 0;
- });
+ llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) {
+ if (int X = A.compare_lower(B))
+ return X < 0;
+ return A.compare(B) > 0;
+ });
llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';
}
@@ -1661,17 +1748,28 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
- for (const Multilib &Multilib : TC.getMultilibs()) {
- if (Multilib.gccSuffix().empty())
- llvm::outs() << ".\n";
- else {
- StringRef Suffix(Multilib.gccSuffix());
- assert(Suffix.front() == '/');
- llvm::outs() << Suffix.substr(1) << "\n";
- }
+ const Multilib &Multilib = TC.getMultilib();
+ if (Multilib.gccSuffix().empty())
+ llvm::outs() << ".\n";
+ else {
+ StringRef Suffix(Multilib.gccSuffix());
+ assert(Suffix.front() == '/');
+ llvm::outs() << Suffix.substr(1) << "\n";
}
return false;
}
+
+ if (C.getArgs().hasArg(options::OPT_print_target_triple)) {
+ llvm::outs() << TC.getTripleString() << "\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_effective_triple)) {
+ const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));
+ llvm::outs() << Triple.getTriple() << "\n";
+ return false;
+ }
+
return true;
}
@@ -1882,7 +1980,7 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,
}
}
- if (llvm::sys::fs::exists(Twine(Path)))
+ if (D.getVFS().exists(Path))
return true;
if (D.IsCLMode()) {
@@ -1960,7 +2058,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
Ty = types::TY_C;
} else {
// Otherwise lookup by extension.
- // Fallback is C if invoked as C preprocessor or Object otherwise.
+ // Fallback is C if invoked as C preprocessor, C++ if invoked with
+ // clang-cl /E, or Object otherwise.
// We use a host hook here because Darwin at least has its own
// idea of what .s is.
if (const char *Ext = strrchr(Value, '.'))
@@ -1969,6 +2068,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
if (Ty == types::TY_INVALID) {
if (CCCIsCPP())
Ty = types::TY_C;
+ else if (IsCLMode() && Args.hasArgNoClaim(options::OPT_E))
+ Ty = types::TY_CXX;
else
Ty = types::TY_Object;
}
@@ -2223,6 +2324,18 @@ class OffloadingActionBuilder final {
// If this is an unbundling action use it as is for each CUDA toolchain.
if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
CudaDeviceActions.clear();
+ auto *IA = cast<InputAction>(UA->getInputs().back());
+ std::string FileName = IA->getInputArg().getAsString(Args);
+ // Check if the type of the file is the same as the action. Do not
+ // unbundle it if it is not. Do not unbundle .so files, for example,
+ // which are not object files.
+ if (IA->getType() == types::TY_Object &&
+ (!llvm::sys::path::has_extension(FileName) ||
+ types::lookupTypeForExtension(
+ llvm::sys::path::extension(FileName).drop_front()) !=
+ types::TY_Object))
+ return ABRT_Inactive;
+
for (auto Arch : GpuArchList) {
CudaDeviceActions.push_back(UA);
UA->registerDependentActionInfo(ToolChains[0], CudaArchToString(Arch),
@@ -2466,11 +2579,13 @@ class OffloadingActionBuilder final {
class HIPActionBuilder final : public CudaActionBuilderBase {
/// The linker inputs obtained for each device arch.
SmallVector<ActionList, 8> DeviceLinkerInputs;
+ bool Relocatable;
public:
HIPActionBuilder(Compilation &C, DerivedArgList &Args,
const Driver::InputList &Inputs)
- : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {}
+ : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP),
+ Relocatable(false) {}
bool canUseBundlerUnbundler() const override { return true; }
@@ -2479,23 +2594,70 @@ class OffloadingActionBuilder final {
phases::ID CurPhase, phases::ID FinalPhase,
PhasesTy &Phases) override {
// amdgcn does not support linking of object files, therefore we skip
- // backend and assemble phases to output LLVM IR.
- if (CudaDeviceActions.empty() || CurPhase == phases::Backend ||
+ // backend and assemble phases to output LLVM IR. Except for generating
+ // non-relocatable device coee, where we generate fat binary for device
+ // code and pass to host in Backend phase.
+ if (CudaDeviceActions.empty() ||
+ (CurPhase == phases::Backend && Relocatable) ||
CurPhase == phases::Assemble)
return ABRT_Success;
- assert((CurPhase == phases::Link ||
+ assert(((CurPhase == phases::Link && Relocatable) ||
CudaDeviceActions.size() == GpuArchList.size()) &&
"Expecting one action per GPU architecture.");
assert(!CompileHostOnly &&
"Not expecting CUDA actions in host-only compilation.");
- // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
- // This happens to each device action originated from each input file.
- // Later on, device actions in DeviceLinkerInputs are used to create
- // device link actions in appendLinkDependences and the created device
- // link actions are passed to the offload action as device dependence.
- if (CurPhase == phases::Link) {
+ if (!Relocatable && CurPhase == phases::Backend) {
+ // If we are in backend phase, we attempt to generate the fat binary.
+ // We compile each arch to IR and use a link action to generate code
+ // object containing ISA. Then we use a special "link" action to create
+ // a fat binary containing all the code objects for different GPU's.
+ // The fat binary is then an input to the host action.
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
+ // Create a link action to link device IR with device library
+ // and generate ISA.
+ ActionList AL;
+ AL.push_back(CudaDeviceActions[I]);
+ CudaDeviceActions[I] =
+ C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+
+ // OffloadingActionBuilder propagates device arch until an offload
+ // action. Since the next action for creating fatbin does
+ // not have device arch, whereas the above link action and its input
+ // have device arch, an offload action is needed to stop the null
+ // device arch of the next action being propagated to the above link
+ // action.
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*CudaDeviceActions[I], *ToolChains.front(),
+ CudaArchToString(GpuArchList[I]), AssociatedOffloadKind);
+ CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
+ DDep, CudaDeviceActions[I]->getType());
+ }
+ // Create HIP fat binary with a special "link" action.
+ CudaFatBinary =
+ C.MakeAction<LinkJobAction>(CudaDeviceActions,
+ types::TY_HIP_FATBIN);
+
+ if (!CompileDeviceOnly) {
+ DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
+ AssociatedOffloadKind);
+ // Clear the fat binary, it is already a dependence to an host
+ // action.
+ CudaFatBinary = nullptr;
+ }
+
+ // Remove the CUDA actions as they are already connected to an host
+ // action or fat binary.
+ CudaDeviceActions.clear();
+
+ return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
+ } else if (CurPhase == phases::Link) {
+ // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
+ // This happens to each device action originated from each input file.
+ // Later on, device actions in DeviceLinkerInputs are used to create
+ // device link actions in appendLinkDependences and the created device
+ // link actions are passed to the offload action as device dependence.
DeviceLinkerInputs.resize(CudaDeviceActions.size());
auto LI = DeviceLinkerInputs.begin();
for (auto *A : CudaDeviceActions) {
@@ -2528,6 +2690,13 @@ class OffloadingActionBuilder final {
++I;
}
}
+
+ bool initialize() override {
+ Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
+ options::OPT_fno_gpu_rdc, /*Default=*/false);
+
+ return CudaActionBuilderBase::initialize();
+ }
};
/// OpenMP action builder. The host bitcode is passed to the device frontend
@@ -2548,6 +2717,8 @@ class OffloadingActionBuilder final {
getDeviceDependences(OffloadAction::DeviceDependences &DA,
phases::ID CurPhase, phases::ID FinalPhase,
PhasesTy &Phases) override {
+ if (OpenMPDeviceActions.empty())
+ return ABRT_Inactive;
// We should always have an action for each input.
assert(OpenMPDeviceActions.size() == ToolChains.size() &&
@@ -2591,6 +2762,17 @@ class OffloadingActionBuilder final {
// If this is an unbundling action use it as is for each OpenMP toolchain.
if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
OpenMPDeviceActions.clear();
+ auto *IA = cast<InputAction>(UA->getInputs().back());
+ std::string FileName = IA->getInputArg().getAsString(Args);
+ // Check if the type of the file is the same as the action. Do not
+ // unbundle it if it is not. Do not unbundle .so files, for example,
+ // which are not object files.
+ if (IA->getType() == types::TY_Object &&
+ (!llvm::sys::path::has_extension(FileName) ||
+ types::lookupTypeForExtension(
+ llvm::sys::path::extension(FileName).drop_front()) !=
+ types::TY_Object))
+ return ABRT_Inactive;
for (unsigned I = 0; I < ToolChains.size(); ++I) {
OpenMPDeviceActions.push_back(UA);
UA->registerDependentActionInfo(
@@ -2835,6 +3017,11 @@ public:
OffloadKind |= SB->getAssociatedOffloadKind();
}
+ // Do not use unbundler if the Host does not depend on device action.
+ if (OffloadKind == Action::OFK_None && CanUseBundler)
+ if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction))
+ HostAction = UA->getInputs().back();
+
return false;
}
@@ -2852,8 +3039,10 @@ public:
}
// If we can use the bundler, replace the host action by the bundling one in
- // the resulting list. Otherwise, just append the device actions.
- if (CanUseBundler && !OffloadAL.empty()) {
+ // the resulting list. Otherwise, just append the device actions. For
+ // device only compilation, HostAction is a null pointer, therefore only do
+ // this when HostAction is not a null pointer.
+ if (CanUseBundler && HostAction && !OffloadAL.empty()) {
// Add the host action to the list in order to create the bundling action.
OffloadAL.push_back(HostAction);
@@ -2971,22 +3160,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
}
}
- // Diagnose unsupported forms of /Yc /Yu. Ignore /Yc/Yu for now if:
- // * no filename after it
- // * both /Yc and /Yu passed but with different filenames
- // * corresponding file not also passed as /FI
+ // Ignore /Yc/Yu if both /Yc and /Yu passed but with different filenames.
Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
- if (YcArg && YcArg->getValue()[0] == '\0') {
- Diag(clang::diag::warn_drv_ycyu_no_arg_clang_cl) << YcArg->getSpelling();
- Args.eraseArg(options::OPT__SLASH_Yc);
- YcArg = nullptr;
- }
- if (YuArg && YuArg->getValue()[0] == '\0') {
- Diag(clang::diag::warn_drv_ycyu_no_arg_clang_cl) << YuArg->getSpelling();
- Args.eraseArg(options::OPT__SLASH_Yu);
- YuArg = nullptr;
- }
if (YcArg && YuArg && strcmp(YcArg->getValue(), YuArg->getValue()) != 0) {
Diag(clang::diag::warn_drv_ycyu_different_arg_clang_cl);
Args.eraseArg(options::OPT__SLASH_Yc);
@@ -2998,9 +3174,10 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Args.eraseArg(options::OPT__SLASH_Yc);
YcArg = nullptr;
}
- if (Args.hasArg(options::OPT__SLASH_Y_)) {
- // /Y- disables all pch handling. Rather than check for it everywhere,
- // just remove clang-cl pch-related flags here.
+ if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) {
+ // If only preprocessing or /Y- is used, all pch handling is disabled.
+ // Rather than check for it everywhere, just remove clang-cl pch-related
+ // flags here.
Args.eraseArg(options::OPT__SLASH_Fp);
Args.eraseArg(options::OPT__SLASH_Yc);
Args.eraseArg(options::OPT__SLASH_Yu);
@@ -3011,6 +3188,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
OffloadingActionBuilder OffloadBuilder(C, Args, Inputs);
// Construct the actions to perform.
+ HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
ActionList LinkerInputs;
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
@@ -3107,13 +3285,29 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
break;
}
+ // Each precompiled header file after a module file action is a module
+ // header of that same module file, rather than being compiled to a
+ // separate PCH.
+ if (Phase == phases::Precompile && HeaderModuleAction &&
+ getPrecompiledType(InputType) == types::TY_PCH) {
+ HeaderModuleAction->addModuleHeaderInput(Current);
+ Current = nullptr;
+ break;
+ }
+
+ // FIXME: Should we include any prior module file outputs as inputs of
+ // later actions in the same command line?
+
// Otherwise construct the appropriate action.
- auto *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);
+ Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);
// We didn't create a new action, so we will just move to the next phase.
if (NewCurrent == Current)
continue;
+ if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent))
+ HeaderModuleAction = HMA;
+
Current = NewCurrent;
// Use the current host action in any of the offloading actions, if
@@ -3193,10 +3387,25 @@ Action *Driver::ConstructPhaseAction(
types::ID OutputTy = getPrecompiledType(Input->getType());
assert(OutputTy != types::TY_INVALID &&
"Cannot precompile this input type!");
+
+ // If we're given a module name, precompile header file inputs as a
+ // module, not as a precompiled header.
+ const char *ModName = nullptr;
+ if (OutputTy == types::TY_PCH) {
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_name_EQ))
+ ModName = A->getValue();
+ if (ModName)
+ OutputTy = types::TY_ModuleFile;
+ }
+
if (Args.hasArg(options::OPT_fsyntax_only)) {
// Syntax checks should not emit a PCH file
OutputTy = types::TY_Nothing;
}
+
+ if (ModName)
+ return C.MakeAction<HeaderModulePrecompileJobAction>(Input, OutputTy,
+ ModName);
return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
}
case phases::Compile: {
@@ -3449,7 +3658,7 @@ class ToolSelector final {
/// - Backend + Compile.
const Tool *
combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
- const ActionList *&Inputs,
+ ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (ActionInfo.size() < 3 || !canCollapseAssembleAction())
return nullptr;
@@ -3475,13 +3684,13 @@ class ToolSelector final {
if (!T->hasIntegratedAssembler())
return nullptr;
- Inputs = &CJ->getInputs();
+ Inputs = CJ->getInputs();
AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
/*NumElements=*/3);
return T;
}
const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo,
- const ActionList *&Inputs,
+ ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (ActionInfo.size() < 2 || !canCollapseAssembleAction())
return nullptr;
@@ -3508,13 +3717,13 @@ class ToolSelector final {
if (!T->hasIntegratedAssembler())
return nullptr;
- Inputs = &BJ->getInputs();
+ Inputs = BJ->getInputs();
AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
/*NumElements=*/2);
return T;
}
const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
- const ActionList *&Inputs,
+ ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (ActionInfo.size() < 2)
return nullptr;
@@ -3546,7 +3755,7 @@ class ToolSelector final {
if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode))
return nullptr;
- Inputs = &CJ->getInputs();
+ Inputs = CJ->getInputs();
AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
/*NumElements=*/2);
return T;
@@ -3556,22 +3765,28 @@ class ToolSelector final {
/// preprocessor action, and the current input is indeed a preprocessor
/// action. If combining results in the collapse of offloading actions, those
/// are appended to \a CollapsedOffloadAction.
- void combineWithPreprocessor(const Tool *T, const ActionList *&Inputs,
+ void combineWithPreprocessor(const Tool *T, ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP())
return;
// Attempt to get a preprocessor action dependence.
ActionList PreprocessJobOffloadActions;
- auto *PJ = getPrevDependentAction(*Inputs, PreprocessJobOffloadActions);
- if (!PJ || !isa<PreprocessJobAction>(PJ))
- return;
+ ActionList NewInputs;
+ for (Action *A : Inputs) {
+ auto *PJ = getPrevDependentAction({A}, PreprocessJobOffloadActions);
+ if (!PJ || !isa<PreprocessJobAction>(PJ)) {
+ NewInputs.push_back(A);
+ continue;
+ }
- // This is legal to combine. Append any offload action we found and set the
- // current inputs to preprocessor inputs.
- CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),
- PreprocessJobOffloadActions.end());
- Inputs = &PJ->getInputs();
+ // This is legal to combine. Append any offload action we found and add the
+ // current input to preprocessor inputs.
+ CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),
+ PreprocessJobOffloadActions.end());
+ NewInputs.append(PJ->input_begin(), PJ->input_end());
+ }
+ Inputs = NewInputs;
}
public:
@@ -3589,7 +3804,7 @@ public:
/// connected to collapsed actions are updated accordingly. The latter enables
/// the caller of the selector to process them afterwards instead of just
/// dropping them. If no suitable tool is found, null will be returned.
- const Tool *getTool(const ActionList *&Inputs,
+ const Tool *getTool(ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
//
// Get the largest chain of actions that we could combine.
@@ -3625,7 +3840,7 @@ public:
if (!T)
T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction);
if (!T) {
- Inputs = &BaseAction->getInputs();
+ Inputs = BaseAction->getInputs();
T = TC.SelectTool(*BaseAction);
}
@@ -3770,7 +3985,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
}
- const ActionList *Inputs = &A->getInputs();
+ ActionList Inputs = A->getInputs();
const JobAction *JA = cast<JobAction>(A);
ActionList CollapsedOffloadActions;
@@ -3796,7 +4011,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
// Only use pipes when there is exactly one input.
InputInfoList InputInfos;
- for (const Action *Input : *Inputs) {
+ for (const Action *Input : Inputs) {
// Treat dsymutil and verify sub-jobs as being at the top-level too, they
// shouldn't get temporary output names.
// FIXME: Clean this up.
@@ -3815,6 +4030,10 @@ InputInfo Driver::BuildJobsForActionNoCache(
if (JA->getType() == types::TY_dSYM)
BaseInput = InputInfos[0].getFilename();
+ // ... and in header module compilations, which use the module name.
+ if (auto *ModuleJA = dyn_cast<HeaderModulePrecompileJobAction>(JA))
+ BaseInput = ModuleJA->getModuleName();
+
// Append outputs of offload device jobs to the input list
if (!OffloadDependencesInputInfo.empty())
InputInfos.append(OffloadDependencesInputInfo.begin(),
@@ -4153,16 +4372,24 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
}
std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
- // Respect a limited subset of the '-Bprefix' functionality in GCC by
- // attempting to use this prefix when looking for file paths.
- for (const std::string &Dir : PrefixDirs) {
- if (Dir.empty())
- continue;
- SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
- llvm::sys::path::append(P, Name);
- if (llvm::sys::fs::exists(Twine(P)))
- return P.str();
- }
+ // Search for Name in a list of paths.
+ auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P)
+ -> llvm::Optional<std::string> {
+ // Respect a limited subset of the '-Bprefix' functionality in GCC by
+ // attempting to use this prefix when looking for file paths.
+ for (const auto &Dir : P) {
+ if (Dir.empty())
+ continue;
+ SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::exists(Twine(P)))
+ return P.str().str();
+ }
+ return None;
+ };
+
+ if (auto P = SearchPaths(PrefixDirs))
+ return *P;
SmallString<128> R(ResourceDir);
llvm::sys::path::append(R, Name);
@@ -4174,14 +4401,11 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
if (llvm::sys::fs::exists(Twine(P)))
return P.str();
- for (const std::string &Dir : TC.getFilePaths()) {
- if (Dir.empty())
- continue;
- SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
- llvm::sys::path::append(P, Name);
- if (llvm::sys::fs::exists(Twine(P)))
- return P.str();
- }
+ if (auto P = SearchPaths(TC.getLibraryPaths()))
+ return *P;
+
+ if (auto P = SearchPaths(TC.getFilePaths()))
+ return *P;
return Name;
}
@@ -4255,6 +4479,17 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
return Path.str();
}
+std::string Driver::GetTemporaryDirectory(StringRef Prefix) const {
+ SmallString<128> Path;
+ std::error_code EC = llvm::sys::fs::createUniqueDirectory(Prefix, Path);
+ if (EC) {
+ Diag(clang::diag::err_unable_to_make_temp) << EC.message();
+ return "";
+ }
+
+ return Path.str();
+}
+
std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
SmallString<128> Output;
if (Arg *FpArg = C.getArgs().getLastArg(options::OPT__SLASH_Fp)) {
@@ -4267,11 +4502,11 @@ std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
// extension of .pch is assumed. "
if (!llvm::sys::path::has_extension(Output))
Output += ".pch";
- } else if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc)) {
- Output = YcArg->getValue();
- llvm::sys::path::replace_extension(Output, ".pch");
} else {
- Output = BaseName;
+ if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc))
+ Output = YcArg->getValue();
+ if (Output.empty())
+ Output = BaseName;
llvm::sys::path::replace_extension(Output, ".pch");
}
return Output.str();
@@ -4373,6 +4608,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Contiki:
TC = llvm::make_unique<toolchains::Contiki>(*this, Target, Args);
break;
+ case llvm::Triple::Hurd:
+ TC = llvm::make_unique<toolchains::Hurd>(*this, Target, Args);
+ break;
default:
// Of these targets, Hexagon is the only one that might have
// an OS of Linux, in which case it got handled above already.
@@ -4400,6 +4638,10 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::avr:
TC = llvm::make_unique<toolchains::AVRToolChain>(*this, Target, Args);
break;
+ case llvm::Triple::msp430:
+ TC =
+ llvm::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args);
+ break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
TC = llvm::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
@@ -4508,11 +4750,11 @@ bool Driver::GetReleaseVersion(StringRef Str,
return false;
}
-std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks() const {
+std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
unsigned IncludedFlagsBitmask = 0;
unsigned ExcludedFlagsBitmask = options::NoDriverOption;
- if (Mode == CLMode) {
+ if (IsClCompatMode) {
// Include CL and Core options.
IncludedFlagsBitmask |= options::CLOption;
IncludedFlagsBitmask |= options::CoreOption;
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index bd1a9bd8e3eb..8d1dfbe12d73 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -35,7 +35,8 @@ using namespace clang;
using namespace driver;
Command::Command(const Action &Source, const Tool &Creator,
- const char *Executable, const ArgStringList &Arguments,
+ const char *Executable,
+ const llvm::opt::ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs)
: Source(Source), Creator(Creator), Executable(Executable),
Arguments(Arguments) {
@@ -315,6 +316,12 @@ void Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
std::string *ErrMsg, bool *ExecutionFailed) const {
+ if (PrintInputFilenames) {
+ for (const char *Arg : InputFilenames)
+ llvm::outs() << llvm::sys::path::filename(Arg) << "\n";
+ llvm::outs().flush();
+ }
+
SmallVector<const char*, 128> Argv;
Optional<ArrayRef<StringRef>> Env;
@@ -366,7 +373,7 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
const char *Executable_,
- const ArgStringList &Arguments_,
+ const llvm::opt::ArgStringList &Arguments_,
ArrayRef<InputInfo> Inputs,
std::unique_ptr<Command> Fallback_)
: Command(Source_, Creator_, Executable_, Arguments_, Inputs),
@@ -405,11 +412,9 @@ int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
return SecondaryStatus;
}
-ForceSuccessCommand::ForceSuccessCommand(const Action &Source_,
- const Tool &Creator_,
- const char *Executable_,
- const ArgStringList &Arguments_,
- ArrayRef<InputInfo> Inputs)
+ForceSuccessCommand::ForceSuccessCommand(
+ const Action &Source_, const Tool &Creator_, const char *Executable_,
+ const llvm::opt::ArgStringList &Arguments_, ArrayRef<InputInfo> Inputs)
: Command(Source_, Creator_, Executable_, Arguments_, Inputs) {}
void ForceSuccessCommand::Print(raw_ostream &OS, const char *Terminator,
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 5d3e31567ce6..1a46073aaa37 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -34,8 +34,9 @@ enum : SanitizerMask {
RequiresPIE = DataFlow | HWAddress | Scudo,
NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress |
- Memory | Leak | Undefined | Integer | ImplicitConversion |
- Nullability | DataFlow | Fuzzer | FuzzerNoLink,
+ Memory | KernelMemory | Leak | Undefined | Integer |
+ ImplicitConversion | Nullability | DataFlow | Fuzzer |
+ FuzzerNoLink,
RecoverableByDefault = Undefined | Integer | ImplicitConversion | Nullability,
Unrecoverable = Unreachable | Return,
AlwaysRecoverable = KernelAddress | KernelHWAddress,
@@ -46,7 +47,7 @@ enum : SanitizerMask {
TrappingDefault = CFI,
CFIClasses =
CFIVCall | CFINVCall | CFIMFCall | CFIDerivedCast | CFIUnrelatedCast,
- CompatibleWithMinimalRuntime = TrappingSupported | Scudo,
+ CompatibleWithMinimalRuntime = TrappingSupported | Scudo | ShadowCallStack,
};
enum CoverageFeature {
@@ -206,6 +207,8 @@ bool SanitizerArgs::needsUnwindTables() const {
return Sanitizers.Mask & NeedsUnwindTables;
}
+bool SanitizerArgs::needsLTO() const { return Sanitizers.Mask & NeedsLTO; }
+
SanitizerArgs::SanitizerArgs(const ToolChain &TC,
const llvm::opt::ArgList &Args) {
SanitizerMask AllRemove = 0; // During the loop below, the accumulated set of
@@ -375,13 +378,12 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
KernelAddress | Efficiency),
std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
KernelAddress | Efficiency),
- std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread |
- Memory | KernelAddress | Efficiency |
- SafeStack),
std::make_pair(KernelHWAddress, Address | HWAddress | Leak | Thread |
Memory | KernelAddress | Efficiency |
- SafeStack | ShadowCallStack)};
-
+ SafeStack),
+ std::make_pair(KernelMemory, Address | HWAddress | Leak | Thread |
+ Memory | KernelAddress | Efficiency |
+ Scudo | SafeStack)};
// Enable toolchain specific default sanitizers if not explicitly disabled.
SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
@@ -721,16 +723,38 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
options::OPT_fsanitize_address_use_after_scope,
options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
+ AsanPoisonCustomArrayCookie = Args.hasFlag(
+ options::OPT_fsanitize_address_poison_custom_array_cookie,
+ options::OPT_fno_sanitize_address_poison_custom_array_cookie,
+ AsanPoisonCustomArrayCookie);
+
// As a workaround for a bug in gold 2.26 and earlier, dead stripping of
// globals in ASan is disabled by default on ELF targets.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
AsanGlobalsDeadStripping =
!TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
+
+ AsanUseOdrIndicator =
+ Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
+ options::OPT_fno_sanitize_address_use_odr_indicator,
+ AsanUseOdrIndicator);
} else {
AsanUseAfterScope = false;
}
+ if (AllAddedKinds & HWAddress) {
+ if (Arg *HwasanAbiArg =
+ Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
+ HwasanAbi = HwasanAbiArg->getValue();
+ if (HwasanAbi != "platform" && HwasanAbi != "interceptor")
+ D.Diag(clang::diag::err_drv_invalid_value)
+ << HwasanAbiArg->getAsString(Args) << HwasanAbi;
+ } else {
+ HwasanAbi = "interceptor";
+ }
+ }
+
if (AllAddedKinds & SafeStack) {
// SafeStack runtime is built into the system on Fuchsia.
SafeStackRuntime = !TC.getTriple().isOSFuchsia();
@@ -894,9 +918,20 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
if (AsanUseAfterScope)
CmdArgs.push_back("-fsanitize-address-use-after-scope");
+ if (AsanPoisonCustomArrayCookie)
+ CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
+
if (AsanGlobalsDeadStripping)
CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
+ if (AsanUseOdrIndicator)
+ CmdArgs.push_back("-fsanitize-address-use-odr-indicator");
+
+ if (!HwasanAbi.empty()) {
+ CmdArgs.push_back("-default-function-attr");
+ CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
+ }
+
// MSan: Workaround for PR16386.
// ASan: This is mainly to help LSan with cases such as
// https://github.com/google/sanitizers/issues/373
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index cf3db34688df..88a627eab6de 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -13,7 +13,6 @@
#include "ToolChains/Clang.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Sanitizers.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
@@ -39,6 +38,7 @@
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <cassert>
#include <cstddef>
#include <cstring>
@@ -74,10 +74,17 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
- SmallString<128> P(D.ResourceDir);
+ SmallString<128> P;
+
+ P.assign(D.ResourceDir);
llvm::sys::path::append(P, D.getTargetTriple(), "lib");
if (getVFS().exists(P))
- getFilePaths().push_back(P.str());
+ getLibraryPaths().push_back(P.str());
+
+ P.assign(D.ResourceDir);
+ llvm::sys::path::append(P, Triple.str(), "lib");
+ if (getVFS().exists(P))
+ getLibraryPaths().push_back(P.str());
std::string CandidateLibPath = getArchSpecificLibPath();
if (getVFS().exists(CandidateLibPath))
@@ -92,7 +99,9 @@ void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
ToolChain::~ToolChain() = default;
-vfs::FileSystem &ToolChain::getVFS() const { return getDriver().getVFS(); }
+llvm::vfs::FileSystem &ToolChain::getVFS() const {
+ return getDriver().getVFS();
+}
bool ToolChain::useIntegratedAs() const {
return Args.hasFlag(options::OPT_fintegrated_as,
@@ -295,6 +304,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::CompileJobClass:
case Action::PrecompileJobClass:
+ case Action::HeaderModulePrecompileJobClass:
case Action::PreprocessJobClass:
case Action::AnalyzeJobClass:
case Action::MigrateJobClass:
@@ -359,15 +369,16 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
const char *Prefix = IsITANMSVCWindows ? "" : "lib";
- const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so")
+ const char *Suffix = Shared ? (Triple.isOSWindows() ? ".lib" : ".so")
: (IsITANMSVCWindows ? ".lib" : ".a");
+ if (Shared && Triple.isWindowsGNUEnvironment())
+ Suffix = ".dll.a";
- const Driver &D = getDriver();
- SmallString<128> P(D.ResourceDir);
- llvm::sys::path::append(P, D.getTargetTriple(), "lib");
- if (getVFS().exists(P)) {
+ for (const auto &LibPath : getLibraryPaths()) {
+ SmallString<128> P(LibPath);
llvm::sys::path::append(P, Prefix + Twine("clang_rt.") + Component + Suffix);
- return P.str();
+ if (getVFS().exists(P))
+ return P.str();
}
StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
@@ -392,19 +403,23 @@ std::string ToolChain::getArchSpecificLibPath() const {
}
bool ToolChain::needsProfileRT(const ArgList &Args) {
- if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
- false) ||
+ if (needsGCovInstrumentation(Args) ||
Args.hasArg(options::OPT_fprofile_generate) ||
Args.hasArg(options::OPT_fprofile_generate_EQ) ||
Args.hasArg(options::OPT_fprofile_instr_generate) ||
Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
- Args.hasArg(options::OPT_fcreate_profile) ||
- Args.hasArg(options::OPT_coverage))
+ Args.hasArg(options::OPT_fcreate_profile))
return true;
return false;
}
+bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
+ return Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false) ||
+ Args.hasArg(options::OPT_coverage);
+}
+
Tool *ToolChain::SelectTool(const JobAction &JA) const {
if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
Action::ActionClass AC = JA.getKind();
@@ -589,7 +604,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
// Check to see if an explicit choice to use thumb has been made via
// -mthumb. For assembler files we must check for -mthumb in the options
- // passed to the assember via -Wa or -Xassembler.
+ // passed to the assembler via -Wa or -Xassembler.
bool IsThumb = false;
if (InputType != types::TY_PP_Asm)
IsThumb = Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb,
@@ -762,6 +777,10 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
void ToolChain::AddFilePathLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
+ for (const auto &LibPath : getLibraryPaths())
+ if(LibPath.length() > 0)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
+
for (const auto &LibPath : getFilePaths())
if(LibPath.length() > 0)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
diff --git a/lib/Driver/ToolChains/AMDGPU.cpp b/lib/Driver/ToolChains/AMDGPU.cpp
index 6b673feeadfc..a421a09891cd 100644
--- a/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/lib/Driver/ToolChains/AMDGPU.cpp
@@ -98,3 +98,16 @@ AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
return DAL;
}
+
+void AMDGPUToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ // Default to "hidden" visibility, as object level linking will not be
+ // supported for the foreseeable future.
+ if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat)) {
+ CC1Args.push_back("-fvisibility");
+ CC1Args.push_back("hidden");
+ }
+}
diff --git a/lib/Driver/ToolChains/AMDGPU.h b/lib/Driver/ToolChains/AMDGPU.h
index 36114d0dabc4..9d38eeedf59d 100644
--- a/lib/Driver/ToolChains/AMDGPU.h
+++ b/lib/Driver/ToolChains/AMDGPU.h
@@ -61,6 +61,10 @@ public:
llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
};
} // end namespace toolchains
diff --git a/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp
index 5114279b4b45..71e55fe79e27 100644
--- a/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -19,10 +19,17 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+/// \returns true if the given triple can determine the default CPU type even
+/// if -arch is not specified.
+static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
+ return Triple.isOSDarwin();
+}
+
/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
/// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
/// provided, or to nullptr otherwise.
-std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
+std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple, Arg *&A) {
std::string CPU;
// If we have -mcpu, use that.
if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
@@ -36,9 +43,9 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
else if (CPU.size())
return CPU;
- // Make sure we pick "cyclone" if -arch is used.
- // FIXME: Should this be picked by checking the target triple instead?
- if (Args.getLastArg(options::OPT_arch))
+ // Make sure we pick "cyclone" if -arch is used or when targetting a Darwin
+ // OS.
+ if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
return "cyclone";
return "generic";
@@ -152,7 +159,9 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
}
-void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
+void aarch64::getAArch64TargetFeatures(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<StringRef> &Features) {
Arg *A;
bool success = true;
@@ -162,9 +171,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (Args.hasArg(options::OPT_arch))
- success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
- Args, Features);
+ else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
+ success = getAArch64ArchFeaturesFromMcpu(
+ D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
success =
@@ -172,9 +181,10 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
success =
getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (success && Args.hasArg(options::OPT_arch))
+ else if (success &&
+ (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)))
success = getAArch64MicroArchFeaturesFromMcpu(
- D, getAArch64TargetCPU(Args, A), Args, Features);
+ D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
if (!success)
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
@@ -193,17 +203,172 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("-crc");
}
+ // Handle (arch-dependent) fp16fml/fullfp16 relationship.
+ // FIXME: this fp16fml option handling will be reimplemented after the
+ // TargetParser rewrite.
+ const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
+ const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
+ if (std::find(Features.begin(), Features.end(), "+v8.4a") != Features.end()) {
+ const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
+ if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
+ // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
+ // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
+ if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
+ Features.push_back("+fp16fml");
+ }
+ else
+ goto fp16_fml_fallthrough;
+ }
+ else {
+fp16_fml_fallthrough:
+ // In both of these cases, putting the 'other' feature on the end of the vector will
+ // result in the same effect as placing it immediately after the current feature.
+ if (ItRNoFullFP16 < ItRFP16FML)
+ Features.push_back("-fp16fml");
+ else if (ItRNoFullFP16 > ItRFP16FML)
+ Features.push_back("+fullfp16");
+ }
+
+ // FIXME: this needs reimplementation too after the TargetParser rewrite
+ //
+ // Context sensitive meaning of Crypto:
+ // 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes
+ // 2) For Arch <= ARMv8.3a: crypto = sha2 + aes
+ const auto ItBegin = Features.begin();
+ const auto ItEnd = Features.end();
+ const auto ItRBegin = Features.rbegin();
+ const auto ItREnd = Features.rend();
+ const auto ItRCrypto = std::find(ItRBegin, ItREnd, "+crypto");
+ const auto ItRNoCrypto = std::find(ItRBegin, ItREnd, "-crypto");
+ const auto HasCrypto = ItRCrypto != ItREnd;
+ const auto HasNoCrypto = ItRNoCrypto != ItREnd;
+ const ptrdiff_t PosCrypto = ItRCrypto - ItRBegin;
+ const ptrdiff_t PosNoCrypto = ItRNoCrypto - ItRBegin;
+
+ bool NoCrypto = false;
+ if (HasCrypto && HasNoCrypto) {
+ if (PosNoCrypto < PosCrypto)
+ NoCrypto = true;
+ }
+
+ if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd) {
+ if (HasCrypto && !NoCrypto) {
+ // Check if we have NOT disabled an algorithm with something like:
+ // +crypto, -algorithm
+ // And if "-algorithm" does not occur, we enable that crypto algorithm.
+ const bool HasSM4 = (std::find(ItBegin, ItEnd, "-sm4") == ItEnd);
+ const bool HasSHA3 = (std::find(ItBegin, ItEnd, "-sha3") == ItEnd);
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
+ if (HasSM4)
+ Features.push_back("+sm4");
+ if (HasSHA3)
+ Features.push_back("+sha3");
+ if (HasSHA2)
+ Features.push_back("+sha2");
+ if (HasAES)
+ Features.push_back("+aes");
+ } else if (HasNoCrypto) {
+ // Check if we have NOT enabled a crypto algorithm with something like:
+ // -crypto, +algorithm
+ // And if "+algorithm" does not occur, we disable that crypto algorithm.
+ const bool HasSM4 = (std::find(ItBegin, ItEnd, "+sm4") != ItEnd);
+ const bool HasSHA3 = (std::find(ItBegin, ItEnd, "+sha3") != ItEnd);
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
+ if (!HasSM4)
+ Features.push_back("-sm4");
+ if (!HasSHA3)
+ Features.push_back("-sha3");
+ if (!HasSHA2)
+ Features.push_back("-sha2");
+ if (!HasAES)
+ Features.push_back("-aes");
+ }
+ } else {
+ if (HasCrypto && !NoCrypto) {
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
+ if (HasSHA2)
+ Features.push_back("+sha2");
+ if (HasAES)
+ Features.push_back("+aes");
+ } else if (HasNoCrypto) {
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
+ const bool HasV82a = (std::find(ItBegin, ItEnd, "+v8.2a") != ItEnd);
+ const bool HasV83a = (std::find(ItBegin, ItEnd, "+v8.3a") != ItEnd);
+ const bool HasV84a = (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd);
+ if (!HasSHA2)
+ Features.push_back("-sha2");
+ if (!HasAES)
+ Features.push_back("-aes");
+ if (HasV82a || HasV83a || HasV84a) {
+ Features.push_back("-sm4");
+ Features.push_back("-sha3");
+ }
+ }
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access))
if (A->getOption().matches(options::OPT_mno_unaligned_access))
Features.push_back("+strict-align");
+ if (Args.hasArg(options::OPT_ffixed_x1))
+ Features.push_back("+reserve-x1");
+
+ if (Args.hasArg(options::OPT_ffixed_x2))
+ Features.push_back("+reserve-x2");
+
+ if (Args.hasArg(options::OPT_ffixed_x3))
+ Features.push_back("+reserve-x3");
+
+ if (Args.hasArg(options::OPT_ffixed_x4))
+ Features.push_back("+reserve-x4");
+
+ if (Args.hasArg(options::OPT_ffixed_x5))
+ Features.push_back("+reserve-x5");
+
+ if (Args.hasArg(options::OPT_ffixed_x6))
+ Features.push_back("+reserve-x6");
+
+ if (Args.hasArg(options::OPT_ffixed_x7))
+ Features.push_back("+reserve-x7");
+
if (Args.hasArg(options::OPT_ffixed_x18))
Features.push_back("+reserve-x18");
if (Args.hasArg(options::OPT_ffixed_x20))
Features.push_back("+reserve-x20");
+ if (Args.hasArg(options::OPT_fcall_saved_x8))
+ Features.push_back("+call-saved-x8");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x9))
+ Features.push_back("+call-saved-x9");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x10))
+ Features.push_back("+call-saved-x10");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x11))
+ Features.push_back("+call-saved-x11");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x12))
+ Features.push_back("+call-saved-x12");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x13))
+ Features.push_back("+call-saved-x13");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x14))
+ Features.push_back("+call-saved-x14");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x15))
+ Features.push_back("+call-saved-x15");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x18))
+ Features.push_back("+call-saved-x18");
+
if (Args.hasArg(options::OPT_mno_neg_immediates))
Features.push_back("+no-neg-immediates");
}
diff --git a/lib/Driver/ToolChains/Arch/AArch64.h b/lib/Driver/ToolChains/Arch/AArch64.h
index 62e419cc19f7..5f6148ebd6c4 100644
--- a/lib/Driver/ToolChains/Arch/AArch64.h
+++ b/lib/Driver/ToolChains/Arch/AArch64.h
@@ -21,11 +21,12 @@ namespace driver {
namespace tools {
namespace aarch64 {
-void getAArch64TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
- llvm::opt::Arg *&A);
+ const llvm::Triple &Triple, llvm::opt::Arg *&A);
} // end namespace aarch64
} // end namespace target
diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp
index 886d947c586b..f55efc1a22e3 100644
--- a/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -378,6 +378,13 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
Features);
} else if (FPUArg) {
getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+ } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
+ // Android mandates minimum FPU requirements based on OS version.
+ const char *AndroidFPU =
+ Triple.isAndroidVersionLT(23) ? "vfpv3-d16" : "neon";
+ if (!llvm::ARM::getFPUFeatures(llvm::ARM::parseFPU(AndroidFPU), Features))
+ D.Diag(clang::diag::err_drv_clang_unsupported)
+ << std::string("-mfpu=") + AndroidFPU;
}
// Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
@@ -391,6 +398,33 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
} else if (HDivArg)
getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
+ // Handle (arch-dependent) fp16fml/fullfp16 relationship.
+ // Must happen before any features are disabled due to soft-float.
+ // FIXME: this fp16fml option handling will be reimplemented after the
+ // TargetParser rewrite.
+ const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
+ const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
+ if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) {
+ const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
+ if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
+ // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
+ // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
+ if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
+ Features.push_back("+fp16fml");
+ }
+ else
+ goto fp16_fml_fallthrough;
+ }
+ else {
+fp16_fml_fallthrough:
+ // In both of these cases, putting the 'other' feature on the end of the vector will
+ // result in the same effect as placing it immediately after the current feature.
+ if (ItRNoFullFP16 < ItRFP16FML)
+ Features.push_back("-fp16fml");
+ else if (ItRNoFullFP16 > ItRFP16FML)
+ Features.push_back("+fullfp16");
+ }
+
// Setting -msoft-float/-mfloat-abi=soft effectively disables the FPU (GCC
// ignores the -mfpu options in this case).
// Note that the ABI can also be set implicitly by the target selected.
@@ -404,7 +438,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
// now just be explicit and disable all known dependent features
// as well.
for (std::string Feature : {"vfp2", "vfp3", "vfp4", "fp-armv8", "fullfp16",
- "neon", "crypto", "dotprod"})
+ "neon", "crypto", "dotprod", "fp16fml"})
if (std::find(std::begin(Features), std::end(Features), "+" + Feature) != std::end(Features))
Features.push_back(Args.MakeArgString("-" + Feature));
}
@@ -417,6 +451,26 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
Features.push_back("-crc");
}
+ // For Arch >= ARMv8.0: crypto = sha2 + aes
+ // FIXME: this needs reimplementation after the TargetParser rewrite
+ if (ArchName.find_lower("armv8a") != StringRef::npos ||
+ ArchName.find_lower("armv8.1a") != StringRef::npos ||
+ ArchName.find_lower("armv8.2a") != StringRef::npos ||
+ ArchName.find_lower("armv8.3a") != StringRef::npos ||
+ ArchName.find_lower("armv8.4a") != StringRef::npos) {
+ if (ArchName.find_lower("+crypto") != StringRef::npos) {
+ if (ArchName.find_lower("+nosha2") == StringRef::npos)
+ Features.push_back("+sha2");
+ if (ArchName.find_lower("+noaes") == StringRef::npos)
+ Features.push_back("+aes");
+ } else if (ArchName.find_lower("-crypto") != StringRef::npos) {
+ if (ArchName.find_lower("+sha2") == StringRef::npos)
+ Features.push_back("-sha2");
+ if (ArchName.find_lower("+aes") == StringRef::npos)
+ Features.push_back("-aes");
+ }
+ }
+
// Look for the last occurrence of -mlong-calls or -mno-long-calls. If
// neither options are specified, see if we are compiling for kernel/kext and
// decide whether to pass "+long-calls" based on the OS and its version.
@@ -589,7 +643,7 @@ StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
return llvm::ARM::getSubArch(ArchKind);
}
-void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs,
+void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs,
const llvm::Triple &Triple) {
if (Args.hasArg(options::OPT_r))
return;
diff --git a/lib/Driver/ToolChains/Arch/ARM.h b/lib/Driver/ToolChains/Arch/ARM.h
index c1dc16884033..9f0dc4ea2e25 100644
--- a/lib/Driver/ToolChains/Arch/ARM.h
+++ b/lib/Driver/ToolChains/Arch/ARM.h
@@ -29,7 +29,7 @@ StringRef getARMCPUForMArch(llvm::StringRef Arch, const llvm::Triple &Triple);
StringRef getLLVMArchSuffixForARM(llvm::StringRef CPU, llvm::StringRef Arch,
const llvm::Triple &Triple);
-void appendEBLinkFlags(const llvm::opt::ArgList &Args,
+void appendBE8LinkFlag(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
const llvm::Triple &Triple);
enum class ReadTPMode {
diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp
index 6d814631d05f..e10a5e1c773f 100644
--- a/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -35,6 +35,11 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
DefMips64CPU = "mips64r6";
}
+ if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) {
+ DefMips32CPU = "mips32r6";
+ DefMips64CPU = "mips64r6";
+ }
+
// MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android).
if (Triple.isAndroid()) {
DefMips32CPU = "mips32";
@@ -42,12 +47,12 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
}
// MIPS3 is the default for mips64*-unknown-openbsd.
- if (Triple.getOS() == llvm::Triple::OpenBSD)
+ if (Triple.isOSOpenBSD())
DefMips64CPU = "mips3";
// MIPS2 is the default for mips(el)?-unknown-freebsd.
// MIPS3 is the default for mips64(el)?-unknown-freebsd.
- if (Triple.getOS() == llvm::Triple::FreeBSD) {
+ if (Triple.isOSFreeBSD()) {
DefMips32CPU = "mips2";
DefMips64CPU = "mips3";
}
@@ -82,6 +87,9 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
}
}
+ if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32))
+ ABIName = "n32";
+
if (ABIName.empty() &&
(Triple.getVendor() == llvm::Triple::MipsTechnologies ||
Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
diff --git a/lib/Driver/ToolChains/Arch/PPC.cpp b/lib/Driver/ToolChains/Arch/PPC.cpp
index f6a95962ace3..791f1206cf25 100644
--- a/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -107,15 +107,19 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (FloatABI == ppc::FloatABI::Soft)
Features.push_back("-hard-float");
- ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Args);
+ ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args);
if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt)
Features.push_back("+secure-plt");
}
-ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const ArgList &Args) {
+ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) {
if (Args.getLastArg(options::OPT_msecure_plt))
return ppc::ReadGOTPtrMode::SecurePlt;
- return ppc::ReadGOTPtrMode::Bss;
+ if (Triple.isOSOpenBSD())
+ return ppc::ReadGOTPtrMode::SecurePlt;
+ else
+ return ppc::ReadGOTPtrMode::Bss;
}
ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
diff --git a/lib/Driver/ToolChains/Arch/PPC.h b/lib/Driver/ToolChains/Arch/PPC.h
index 3acee91a2ac3..4f3cd688ca39 100644
--- a/lib/Driver/ToolChains/Arch/PPC.h
+++ b/lib/Driver/ToolChains/Arch/PPC.h
@@ -38,7 +38,7 @@ FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getPPCTargetCPU(const llvm::opt::ArgList &Args);
const char *getPPCAsmModeForCPU(StringRef Name);
-ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D,
+ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
diff --git a/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp
index 7a4f836d2e1a..45648945d5ef 100644
--- a/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/lib/Driver/ToolChains/Arch/X86.cpp
@@ -23,12 +23,8 @@ using namespace llvm::opt;
const char *x86::getX86TargetCPU(const ArgList &Args,
const llvm::Triple &Triple) {
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
- if (StringRef(A->getValue()) != "native") {
- if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
- return "core-avx2";
-
+ if (StringRef(A->getValue()) != "native")
return A->getValue();
- }
// FIXME: Reject attempts to use -march=native unless the target matches
// the host.
@@ -144,6 +140,34 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+ssse3");
}
+ // Translate the high level `-mretpoline` flag to the specific target feature
+ // flags. We also detect if the user asked for retpoline external thunks but
+ // failed to ask for retpolines themselves (through any of the different
+ // flags). This is a bit hacky but keeps existing usages working. We should
+ // consider deprecating this and instead warn if the user requests external
+ // retpoline thunks and *doesn't* request some form of retpolines.
+ if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline,
+ options::OPT_mspeculative_load_hardening,
+ options::OPT_mno_speculative_load_hardening)) {
+ if (Args.hasFlag(options::OPT_mretpoline, options::OPT_mno_retpoline,
+ false)) {
+ Features.push_back("+retpoline-indirect-calls");
+ Features.push_back("+retpoline-indirect-branches");
+ } else if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
+ options::OPT_mno_speculative_load_hardening,
+ false)) {
+ // On x86, speculative load hardening relies on at least using retpolines
+ // for indirect calls.
+ Features.push_back("+retpoline-indirect-calls");
+ }
+ } else if (Args.hasFlag(options::OPT_mretpoline_external_thunk,
+ options::OPT_mno_retpoline_external_thunk, false)) {
+ // FIXME: Add a warning about failing to specify `-mretpoline` and
+ // eventually switch to an error here.
+ Features.push_back("+retpoline-indirect-calls");
+ Features.push_back("+retpoline-indirect-branches");
+ }
+
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
diff --git a/lib/Driver/ToolChains/BareMetal.cpp b/lib/Driver/ToolChains/BareMetal.cpp
index c302d647b973..31d16922cc43 100644
--- a/lib/Driver/ToolChains/BareMetal.cpp
+++ b/lib/Driver/ToolChains/BareMetal.cpp
@@ -13,13 +13,13 @@
#include "InputInfo.h"
#include "Gnu.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm::opt;
@@ -119,10 +119,11 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(
std::error_code EC;
Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
// Walk the subdirs, and find the one with the newest gcc version:
- for (vfs::directory_iterator LI =
- getDriver().getVFS().dir_begin(Dir.str(), EC), LE;
+ for (llvm::vfs::directory_iterator
+ LI = getDriver().getVFS().dir_begin(Dir.str(), EC),
+ LE;
!EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
if (CandidateVersion.Major == -1)
continue;
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 8e9c4c6aecb8..75f16898dfaf 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -19,12 +19,14 @@
#include "AMDGPU.h"
#include "CommonArgs.h"
#include "Hexagon.h"
+#include "MSP430.h"
#include "InputInfo.h"
#include "PS4CPU.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
+#include "clang/Driver/Distro.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
@@ -341,7 +343,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- aarch64::getAArch64TargetFeatures(D, Args, Features);
+ aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
@@ -363,6 +365,8 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
case llvm::Triple::amdgcn:
amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
break;
+ case llvm::Triple::msp430:
+ msp430::getMSP430TargetFeatures(D, Args, Features);
}
// Find the last of each feature.
@@ -493,6 +497,8 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
if (A.getOption().matches(options::OPT_gline_tables_only) ||
A.getOption().matches(options::OPT_ggdb1))
return codegenoptions::DebugLineTablesOnly;
+ if (A.getOption().matches(options::OPT_gline_directives_only))
+ return codegenoptions::DebugDirectivesOnly;
return codegenoptions::LimitedDebugInfo;
}
@@ -524,11 +530,12 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
break;
}
- if (Triple.getOS() == llvm::Triple::NetBSD) {
+ if (Triple.isOSNetBSD()) {
return !areOptimizationsEnabled(Args);
}
- if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
+ if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI ||
+ Triple.isOSHurd()) {
switch (Triple.getArch()) {
// Don't use a frame pointer on linux if optimizing for certain targets.
case llvm::Triple::mips64:
@@ -800,6 +807,29 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
CmdArgs.push_back("-fcoverage-mapping");
}
+ if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) {
+ auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ);
+ if (!Args.hasArg(options::OPT_coverage))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fprofile-exclude-files="
+ << "--coverage";
+
+ StringRef v = Arg->getValue();
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fprofile-exclude-files=" + v)));
+ }
+
+ if (Args.hasArg(options::OPT_fprofile_filter_files_EQ)) {
+ auto *Arg = Args.getLastArg(options::OPT_fprofile_filter_files_EQ);
+ if (!Args.hasArg(options::OPT_coverage))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fprofile-filter-files="
+ << "--coverage";
+
+ StringRef v = Arg->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-filter-files=" + v)));
+ }
+
if (C.getArgs().hasArg(options::OPT_c) ||
C.getArgs().hasArg(options::OPT_S)) {
if (Output.isFilename()) {
@@ -889,6 +919,9 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
unsigned DwarfVersion,
llvm::DebuggerKind DebuggerTuning) {
switch (DebugInfoKind) {
+ case codegenoptions::DebugDirectivesOnly:
+ CmdArgs.push_back("-debug-info-kind=line-directives-only");
+ break;
case codegenoptions::DebugLineTablesOnly:
CmdArgs.push_back("-debug-info-kind=line-tables-only");
break;
@@ -1100,10 +1133,19 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue();
if (!isa<PrecompileJobAction>(JA)) {
CmdArgs.push_back("-include-pch");
- CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(C, ThroughHeader)));
+ CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(
+ C, !ThroughHeader.empty()
+ ? ThroughHeader
+ : llvm::sys::path::filename(Inputs[0].getBaseInput()))));
+ }
+
+ if (ThroughHeader.empty()) {
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-pch-through-hdrstop-") + (YcArg ? "create" : "use")));
+ } else {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader));
}
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader));
}
}
@@ -1114,42 +1156,26 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;
- // Use PCH if the user requested it.
- bool UsePCH = D.CCCUsePCH;
-
- bool FoundPTH = false;
bool FoundPCH = false;
SmallString<128> P(A->getValue());
// We want the files to have a name like foo.h.pch. Add a dummy extension
// so that replace_extension does the right thing.
P += ".dummy";
- if (UsePCH) {
- llvm::sys::path::replace_extension(P, "pch");
- if (llvm::sys::fs::exists(P))
- FoundPCH = true;
- }
+ llvm::sys::path::replace_extension(P, "pch");
+ if (llvm::sys::fs::exists(P))
+ FoundPCH = true;
if (!FoundPCH) {
- llvm::sys::path::replace_extension(P, "pth");
- if (llvm::sys::fs::exists(P))
- FoundPTH = true;
- }
-
- if (!FoundPCH && !FoundPTH) {
llvm::sys::path::replace_extension(P, "gch");
if (llvm::sys::fs::exists(P)) {
- FoundPCH = UsePCH;
- FoundPTH = !UsePCH;
+ FoundPCH = true;
}
}
- if (FoundPCH || FoundPTH) {
+ if (FoundPCH) {
if (IsFirstImplicitInclude) {
A->claim();
- if (UsePCH)
- CmdArgs.push_back("-include-pch");
- else
- CmdArgs.push_back("-include-pth");
+ CmdArgs.push_back("-include-pch");
CmdArgs.push_back(Args.MakeArgString(P));
continue;
} else {
@@ -1283,21 +1309,28 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) {
}
}
-void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
- ArgStringList &CmdArgs, bool KernelOrKext) const {
+namespace {
+void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
+ ArgStringList &CmdArgs) {
// Select the ABI to use.
// FIXME: Support -meabi.
// FIXME: Parts of this are duplicated in the backend, unify this somehow.
const char *ABIName = nullptr;
- if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
- else {
+ } else {
std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data();
}
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
+}
+}
+
+void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
+ ArgStringList &CmdArgs, bool KernelOrKext) const {
+ RenderARMABI(Triple, Args, CmdArgs);
// Determine floating point ABI from the options & target defaults.
arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
@@ -1409,19 +1442,59 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
}
}
-void Clang::AddAArch64TargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+// Parse -mbranch-protection=<protection>[+<protection>]* where
+// <protection> ::= standard | none | [bti,pac-ret[+b-key,+leaf]*]
+// Returns a triple of (return address signing Scope, signing key, require
+// landing pads)
+static std::tuple<StringRef, StringRef, bool>
+ParseAArch64BranchProtection(const Driver &D, const ArgList &Args,
+ const Arg *A) {
+ StringRef Scope = "none";
+ StringRef Key = "a_key";
+ bool IndirectBranches = false;
- if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
- Args.hasArg(options::OPT_mkernel) ||
- Args.hasArg(options::OPT_fapple_kext))
- CmdArgs.push_back("-disable-red-zone");
+ StringRef Value = A->getValue();
+ // This maps onto -mbranch-protection=<scope>+<key>
+
+ if (Value.equals("standard")) {
+ Scope = "non-leaf";
+ Key = "a_key";
+ IndirectBranches = true;
+
+ } else if (!Value.equals("none")) {
+ SmallVector<StringRef, 4> BranchProtection;
+ StringRef(A->getValue()).split(BranchProtection, '+');
+
+ auto Protection = BranchProtection.begin();
+ while (Protection != BranchProtection.end()) {
+ if (Protection->equals("bti"))
+ IndirectBranches = true;
+ else if (Protection->equals("pac-ret")) {
+ Scope = "non-leaf";
+ while (++Protection != BranchProtection.end()) {
+ // Inner loop as "leaf" and "b-key" options must only appear attached
+ // to pac-ret.
+ if (Protection->equals("leaf"))
+ Scope = "all";
+ else if (Protection->equals("b-key"))
+ Key = "b_key";
+ else
+ break;
+ }
+ Protection--;
+ } else
+ D.Diag(diag::err_invalid_branch_protection)
+ << *Protection << A->getAsString(Args);
+ Protection++;
+ }
+ }
- if (!Args.hasFlag(options::OPT_mimplicit_float,
- options::OPT_mno_implicit_float, true))
- CmdArgs.push_back("-no-implicit-float");
+ return std::make_tuple(Scope, Key, IndirectBranches);
+}
+namespace {
+void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args,
+ ArgStringList &CmdArgs) {
const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
ABIName = A->getValue();
@@ -1432,6 +1505,23 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
+}
+}
+
+void Clang::AddAArch64TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+
+ if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
+ Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-disable-red-zone");
+
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float, true))
+ CmdArgs.push_back("-no-implicit-float");
+
+ RenderAArch64ABI(Triple, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
options::OPT_mno_fix_cortex_a53_835769)) {
@@ -1455,6 +1545,35 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
else
CmdArgs.push_back("-aarch64-enable-global-merge=true");
}
+
+ // Enable/disable return address signing and indirect branch targets.
+ if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ,
+ options::OPT_mbranch_protection_EQ)) {
+
+ const Driver &D = getToolChain().getDriver();
+
+ StringRef Scope, Key;
+ bool IndirectBranches;
+
+ if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
+ Scope = A->getValue();
+ if (!Scope.equals("none") && !Scope.equals("non-leaf") &&
+ !Scope.equals("all"))
+ D.Diag(diag::err_invalid_branch_protection)
+ << Scope << A->getAsString(Args);
+ Key = "a_key";
+ IndirectBranches = false;
+ } else
+ std::tie(Scope, Key, IndirectBranches) =
+ ParseAArch64BranchProtection(D, Args, A);
+
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-msign-return-address=") + Scope));
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-msign-return-address-key=") + Key));
+ if (IndirectBranches)
+ CmdArgs.push_back("-mbranch-target-enforce");
+ }
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
@@ -1706,6 +1825,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
Args.hasArg(options::OPT_fapple_kext))
CmdArgs.push_back("-disable-red-zone");
+ if (!Args.hasFlag(options::OPT_mtls_direct_seg_refs,
+ options::OPT_mno_tls_direct_seg_refs, true))
+ CmdArgs.push_back("-mno-tls-direct-seg-refs");
+
// Default to avoid implicit floating-point for kernel/kext code, but allow
// that to be overridden with -mno-soft-float.
bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
@@ -2033,6 +2156,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
}
CmdArgs.push_back(Value.data());
TakeNextArg = true;
+ } else if (Value == "-fdebug-compilation-dir") {
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ TakeNextArg = true;
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
@@ -2045,6 +2171,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back("-target-feature");
CmdArgs.push_back(MipsTargetFeature);
}
+
+ // forward -fembed-bitcode to assmebler
+ if (C.getDriver().embedBitcodeEnabled() ||
+ C.getDriver().embedBitcodeMarkerOnly())
+ Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
}
static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
@@ -2066,6 +2197,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
StringRef DenormalFPMath = "";
StringRef FPContract = "";
+ if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
+ CmdArgs.push_back("-mlimit-float-precision");
+ CmdArgs.push_back(A->getValue());
+ }
+
for (const Arg *A : Args) {
switch (A->getOption().getID()) {
// If this isn't an FP option skip the claim below
@@ -2228,8 +2364,6 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
// Treat blocks as analysis entry points.
CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
- CmdArgs.push_back("-analyzer-eagerly-assume");
-
// Add default argument set.
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-analyzer-checker=core");
@@ -2339,6 +2473,50 @@ static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args,
}
}
+static void RenderTrivialAutoVarInitOptions(const Driver &D,
+ const ToolChain &TC,
+ const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ auto DefaultTrivialAutoVarInit = TC.GetDefaultTrivialAutoVarInit();
+ StringRef TrivialAutoVarInit = "";
+
+ for (const Arg *A : Args) {
+ switch (A->getOption().getID()) {
+ default:
+ continue;
+ case options::OPT_ftrivial_auto_var_init: {
+ A->claim();
+ StringRef Val = A->getValue();
+ if (Val == "uninitialized" || Val == "zero" || Val == "pattern")
+ TrivialAutoVarInit = Val;
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+ }
+ }
+
+ if (TrivialAutoVarInit.empty())
+ switch (DefaultTrivialAutoVarInit) {
+ case LangOptions::TrivialAutoVarInitKind::Uninitialized:
+ break;
+ case LangOptions::TrivialAutoVarInitKind::Pattern:
+ TrivialAutoVarInit = "pattern";
+ break;
+ case LangOptions::TrivialAutoVarInitKind::Zero:
+ TrivialAutoVarInit = "zero";
+ break;
+ }
+
+ if (!TrivialAutoVarInit.empty()) {
+ if (TrivialAutoVarInit == "zero" && !Args.hasArg(options::OPT_enable_trivial_var_init_zero))
+ D.Diag(diag::err_drv_trivial_auto_var_init_zero_disabled);
+ CmdArgs.push_back(
+ Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit));
+ }
+}
+
static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
const unsigned ForwardedArguments[] = {
options::OPT_cl_opt_disable,
@@ -2658,8 +2836,10 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
CmdArgs.push_back("-fno-signed-char");
}
- if (Args.hasFlag(options::OPT_fchar8__t, options::OPT_fno_char8__t, false))
- CmdArgs.push_back("-fchar8_t");
+ // The default depends on the language standard.
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fchar8__t, options::OPT_fno_char8__t))
+ A->render(Args, CmdArgs);
if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
options::OPT_fno_short_wchar)) {
@@ -2669,8 +2849,8 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
} else {
bool IsARM = T.isARM() || T.isThumb() || T.isAArch64();
CmdArgs.push_back("-fwchar-type=int");
- if (IsARM && !(T.isOSWindows() || T.getOS() == llvm::Triple::NetBSD ||
- T.getOS() == llvm::Triple::OpenBSD))
+ if (IsARM && !(T.isOSWindows() || T.isOSNetBSD() ||
+ T.isOSOpenBSD()))
CmdArgs.push_back("-fno-signed-wchar");
else
CmdArgs.push_back("-fsigned-wchar");
@@ -2701,7 +2881,6 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
// When ObjectiveC legacy runtime is in effect on MacOSX, turn on the option
// to do Array/Dictionary subscripting by default.
if (Arch == llvm::Triple::x86 && T.isMacOSX() &&
- !T.isMacOSXVersionLT(10, 7) &&
Runtime.getKind() == ObjCRuntime::FragileMacOSX && Runtime.isNeXTFamily())
CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
@@ -2737,6 +2916,18 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
}
+ // Allow the user to control whether messages can be converted to runtime
+ // functions.
+ if (types::isObjC(Input.getType())) {
+ auto *Arg = Args.getLastArg(
+ options::OPT_fobjc_convert_messages_to_runtime_calls,
+ options::OPT_fno_objc_convert_messages_to_runtime_calls);
+ if (Arg &&
+ Arg->getOption().matches(
+ options::OPT_fno_objc_convert_messages_to_runtime_calls))
+ CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls");
+ }
+
// -fobjc-infer-related-result-type is the default, except in the Objective-C
// rewriter.
if (InferCovariantReturns)
@@ -2872,12 +3063,35 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back("-fno-spell-checking");
}
+enum class DwarfFissionKind { None, Split, Single };
+
+static DwarfFissionKind getDebugFissionKind(const Driver &D,
+ const ArgList &Args, Arg *&Arg) {
+ Arg =
+ Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ);
+ if (!Arg)
+ return DwarfFissionKind::None;
+
+ if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
+ return DwarfFissionKind::Split;
+
+ StringRef Value = Arg->getValue();
+ if (Value == "split")
+ return DwarfFissionKind::Split;
+ if (Value == "single")
+ return DwarfFissionKind::Single;
+
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << Arg->getValue();
+ return DwarfFissionKind::None;
+}
+
static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
bool EmitCodeView, bool IsWindowsMSVC,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind &DebugInfoKind,
- const Arg *&SplitDWARFArg) {
+ DwarfFissionKind &DwarfFission) {
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
options::OPT_fno_debug_info_for_profiling, false) &&
checkDebugInfoOption(
@@ -2902,10 +3116,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
Args.ClaimAllArgs(options::OPT_g_Group);
- SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf);
+ Arg* SplitDWARFArg;
+ DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);
- if (SplitDWARFArg && !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
- SplitDWARFArg = nullptr;
+ if (DwarfFission != DwarfFissionKind::None &&
+ !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
+ DwarfFission = DwarfFissionKind::None;
SplitDWARFInlining = false;
}
@@ -2922,12 +3138,13 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// composing split-dwarf and line-tables-only, so let those compose
// naturally in that case. And if you just turned off debug info,
// (-gsplit-dwarf -g0) - do that.
- if (SplitDWARFArg) {
+ if (DwarfFission != DwarfFissionKind::None) {
if (A->getIndex() > SplitDWARFArg->getIndex()) {
if (DebugInfoKind == codegenoptions::NoDebugInfo ||
+ DebugInfoKind == codegenoptions::DebugDirectivesOnly ||
(DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
SplitDWARFInlining))
- SplitDWARFArg = nullptr;
+ DwarfFission = DwarfFissionKind::None;
} else if (SplitDWARFInlining)
DebugInfoKind = codegenoptions::NoDebugInfo;
}
@@ -2960,21 +3177,28 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
if (checkDebugInfoOption(A, Args, D, TC))
DWARFVersion = DwarfVersionNum(A->getSpelling());
- // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
- // argument parsing.
- if (EmitCodeView) {
- if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
- EmitCodeView = checkDebugInfoOption(A, Args, D, TC);
- if (EmitCodeView) {
- // DWARFVersion remains at 0 if no explicit choice was made.
- CmdArgs.push_back("-gcodeview");
- }
- }
+ if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
+ if (checkDebugInfoOption(A, Args, D, TC))
+ EmitCodeView = true;
}
+ // If the user asked for debug info but did not explicitly specify -gcodeview
+ // or -gdwarf, ask the toolchain for the default format.
if (!EmitCodeView && DWARFVersion == 0 &&
- DebugInfoKind != codegenoptions::NoDebugInfo)
- DWARFVersion = TC.GetDefaultDwarfVersion();
+ DebugInfoKind != codegenoptions::NoDebugInfo) {
+ switch (TC.getDefaultDebugFormat()) {
+ case codegenoptions::DIF_CodeView:
+ EmitCodeView = true;
+ break;
+ case codegenoptions::DIF_DWARF:
+ DWARFVersion = TC.GetDefaultDwarfVersion();
+ break;
+ }
+ }
+
+ // -gline-directives-only supported only for the DWARF debug info.
+ if (DWARFVersion == 0 && DebugInfoKind == codegenoptions::DebugDirectivesOnly)
+ DebugInfoKind = codegenoptions::NoDebugInfo;
// We ignore flag -gstrict-dwarf for now.
// And we handle flag -grecord-gcc-switches later with DWARFDebugFlags.
@@ -2993,10 +3217,11 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-dwarf-column-info");
// FIXME: Move backend command line options to the module.
- // If -gline-tables-only is the last option it wins.
+ // If -gline-tables-only or -gline-directives-only is the last option it wins.
if (const Arg *A = Args.getLastArg(options::OPT_gmodules))
if (checkDebugInfoOption(A, Args, D, TC)) {
- if (DebugInfoKind != codegenoptions::DebugLineTablesOnly) {
+ if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
+ DebugInfoKind != codegenoptions::DebugDirectivesOnly) {
DebugInfoKind = codegenoptions::LimitedDebugInfo;
CmdArgs.push_back("-dwarf-ext-refs");
CmdArgs.push_back("-fmodule-format=obj");
@@ -3005,15 +3230,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// -gsplit-dwarf should turn on -g and enable the backend dwarf
// splitting and extraction.
- // FIXME: Currently only works on Linux.
- if (T.isOSLinux()) {
+ // FIXME: Currently only works on Linux and Fuchsia.
+ if (T.isOSLinux() || T.isOSFuchsia()) {
if (!SplitDWARFInlining)
CmdArgs.push_back("-fno-split-dwarf-inlining");
- if (SplitDWARFArg) {
+ if (DwarfFission != DwarfFissionKind::None) {
if (DebugInfoKind == codegenoptions::NoDebugInfo)
DebugInfoKind = codegenoptions::LimitedDebugInfo;
- CmdArgs.push_back("-enable-split-dwarf");
+
+ if (DwarfFission == DwarfFissionKind::Single)
+ CmdArgs.push_back("-enable-split-dwarf=single");
+ else
+ CmdArgs.push_back("-enable-split-dwarf");
}
}
@@ -3044,6 +3273,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-gembed-source");
}
+ if (EmitCodeView) {
+ CmdArgs.push_back("-gcodeview");
+
+ // Emit codeview type hashes if requested.
+ if (Args.hasFlag(options::OPT_gcodeview_ghash,
+ options::OPT_gno_codeview_ghash, false)) {
+ CmdArgs.push_back("-gcodeview-ghash");
+ }
+ }
+
+ // Adjust the debug info kind for the given toolchain.
+ TC.adjustDebugInfoKind(DebugInfoKind, Args);
+
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion,
DebuggerTuning);
@@ -3055,11 +3297,24 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-debug-info-macro");
// -ggnu-pubnames turns on gnu style pubnames in the backend.
- if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
- false))
- if (checkDebugInfoOption(Args.getLastArg(options::OPT_ggnu_pubnames), Args,
- D, TC))
- CmdArgs.push_back("-ggnu-pubnames");
+ const auto *PubnamesArg =
+ Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
+ options::OPT_gpubnames, options::OPT_gno_pubnames);
+ if (DwarfFission != DwarfFissionKind::None ||
+ DebuggerTuning == llvm::DebuggerKind::LLDB ||
+ (PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC)))
+ if (!PubnamesArg ||
+ (!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) &&
+ !PubnamesArg->getOption().matches(options::OPT_gno_pubnames)))
+ CmdArgs.push_back(PubnamesArg && PubnamesArg->getOption().matches(
+ options::OPT_gpubnames)
+ ? "-gpubnames"
+ : "-ggnu-pubnames");
+
+ if (Args.hasFlag(options::OPT_fdebug_ranges_base_address,
+ options::OPT_fno_debug_ranges_base_address, false)) {
+ CmdArgs.push_back("-fdebug-ranges-base-address");
+ }
// -gdwarf-aranges turns on the emission of the aranges section in the
// backend.
@@ -3103,32 +3358,64 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
- const llvm::Triple &RawTriple = getToolChain().getTriple();
- const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+ const auto &TC = getToolChain();
+ const llvm::Triple &RawTriple = TC.getTriple();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
- const Driver &D = getToolChain().getDriver();
+ const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
// Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
- const InputInfo &Input = Inputs[0];
// CUDA/HIP compilation may have multiple inputs (source file + results of
// device-side compilations). OpenMP device jobs also take the host IR as a
- // second input. All other jobs are expected to have exactly one
- // input.
+ // second input. Module precompilation accepts a list of header files to
+ // include as part of the module. All other jobs are expected to have exactly
+ // one input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
- assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) ||
- Inputs.size() == 1) &&
- "Unable to handle multiple inputs.");
-
- const llvm::Triple *AuxTriple =
- IsCuda ? getToolChain().getAuxTriple() : nullptr;
+ bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
+
+ // A header module compilation doesn't have a main input file, so invent a
+ // fake one as a placeholder.
+ const char *ModuleName = [&]{
+ auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ);
+ return ModuleNameArg ? ModuleNameArg->getValue() : "";
+ }();
+ InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName);
+
+ const InputInfo &Input =
+ IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0];
+
+ InputInfoList ModuleHeaderInputs;
+ const InputInfo *CudaDeviceInput = nullptr;
+ const InputInfo *OpenMPDeviceInput = nullptr;
+ for (const InputInfo &I : Inputs) {
+ if (&I == &Input) {
+ // This is the primary input.
+ } else if (IsHeaderModulePrecompile &&
+ types::getPrecompiledType(I.getType()) == types::TY_PCH) {
+ types::ID Expected = HeaderModuleInput.getType();
+ if (I.getType() != Expected) {
+ D.Diag(diag::err_drv_module_header_wrong_kind)
+ << I.getFilename() << types::getTypeName(I.getType())
+ << types::getTypeName(Expected);
+ }
+ ModuleHeaderInputs.push_back(I);
+ } else if ((IsCuda || IsHIP) && !CudaDeviceInput) {
+ CudaDeviceInput = &I;
+ } else if (IsOpenMPDevice && !OpenMPDeviceInput) {
+ OpenMPDeviceInput = &I;
+ } else {
+ llvm_unreachable("unexpectedly given multiple inputs");
+ }
+ }
+ const llvm::Triple *AuxTriple = IsCuda ? TC.getAuxTriple() : nullptr;
bool IsWindowsGNU = RawTriple.isWindowsGNUEnvironment();
bool IsWindowsCygnus = RawTriple.isWindowsCygwinEnvironment();
bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
@@ -3204,7 +3491,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Push all default warning arguments that are specific to
// the given target. These come before user provided warning options
// are provided.
- getToolChain().addClangWarningOptions(CmdArgs);
+ TC.addClangWarningOptions(CmdArgs);
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
@@ -3231,17 +3518,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Also ignore explicit -force_cpusubtype_ALL option.
(void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
} else if (isa<PrecompileJobAction>(JA)) {
- // Use PCH if the user requested it.
- bool UsePCH = D.CCCUsePCH;
-
if (JA.getType() == types::TY_Nothing)
CmdArgs.push_back("-fsyntax-only");
else if (JA.getType() == types::TY_ModuleFile)
- CmdArgs.push_back("-emit-module-interface");
- else if (UsePCH)
- CmdArgs.push_back("-emit-pch");
+ CmdArgs.push_back(IsHeaderModulePrecompile
+ ? "-emit-header-module"
+ : "-emit-module-interface");
else
- CmdArgs.push_back("-emit-pth");
+ CmdArgs.push_back("-emit-pch");
} else if (isa<VerifyPCHJobAction>(JA)) {
CmdArgs.push_back("-verify-pch");
} else {
@@ -3305,13 +3589,116 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
// Embed-bitcode option.
+ // Only white-listed flags below are allowed to be embedded.
if (C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO() &&
(isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
// Add flags implied by -fembed-bitcode.
Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
// Disable all llvm IR level optimizations.
CmdArgs.push_back("-disable-llvm-passes");
+
+ // reject options that shouldn't be supported in bitcode
+ // also reject kernel/kext
+ static const constexpr unsigned kBitcodeOptionBlacklist[] = {
+ options::OPT_mkernel,
+ options::OPT_fapple_kext,
+ options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections,
+ options::OPT_fdata_sections,
+ options::OPT_fno_data_sections,
+ options::OPT_funique_section_names,
+ options::OPT_fno_unique_section_names,
+ options::OPT_mrestrict_it,
+ options::OPT_mno_restrict_it,
+ options::OPT_mstackrealign,
+ options::OPT_mno_stackrealign,
+ options::OPT_mstack_alignment,
+ options::OPT_mcmodel_EQ,
+ options::OPT_mlong_calls,
+ options::OPT_mno_long_calls,
+ options::OPT_ggnu_pubnames,
+ options::OPT_gdwarf_aranges,
+ options::OPT_fdebug_types_section,
+ options::OPT_fno_debug_types_section,
+ options::OPT_fdwarf_directory_asm,
+ options::OPT_fno_dwarf_directory_asm,
+ options::OPT_mrelax_all,
+ options::OPT_mno_relax_all,
+ options::OPT_ftrap_function_EQ,
+ options::OPT_ffixed_r9,
+ options::OPT_mfix_cortex_a53_835769,
+ options::OPT_mno_fix_cortex_a53_835769,
+ options::OPT_ffixed_x18,
+ options::OPT_mglobal_merge,
+ options::OPT_mno_global_merge,
+ options::OPT_mred_zone,
+ options::OPT_mno_red_zone,
+ options::OPT_Wa_COMMA,
+ options::OPT_Xassembler,
+ options::OPT_mllvm,
+ };
+ for (const auto &A : Args)
+ if (std::find(std::begin(kBitcodeOptionBlacklist),
+ std::end(kBitcodeOptionBlacklist),
+ A->getOption().getID()) !=
+ std::end(kBitcodeOptionBlacklist))
+ D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling();
+
+ // Render the CodeGen options that need to be passed.
+ if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls))
+ CmdArgs.push_back("-mdisable-tail-calls");
+
+ RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args,
+ CmdArgs);
+
+ // Render ABI arguments
+ switch (TC.getArch()) {
+ default: break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ RenderARMABI(Triple, Args, CmdArgs);
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ RenderAArch64ABI(Triple, Args, CmdArgs);
+ break;
+ }
+
+ // Optimization level for CodeGen.
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4)) {
+ CmdArgs.push_back("-O3");
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ // Input/Output file.
+ if (Output.getType() == types::TY_Dependencies) {
+ // Handled with other dependency code.
+ } else if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Input output.");
+ }
+
+ for (const auto &II : Inputs) {
+ addDashXForInput(Args, II, CmdArgs);
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+
+ C.addCommand(llvm::make_unique<Command>(JA, *this, D.getClangProgramPath(),
+ CmdArgs, Inputs));
+ return;
}
+
if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO())
CmdArgs.push_back("-fembed-bitcode=marker");
@@ -3346,12 +3733,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-static-define");
+ if (Args.hasArg(options::OPT_municode))
+ CmdArgs.push_back("-DUNICODE");
+
if (isa<AnalyzeJobAction>(JA))
RenderAnalyzerOptions(Args, CmdArgs, Triple, Input);
+ // Enable compatilibily mode to avoid analyzer-config related errors.
+ // Since we can't access frontend flags through hasArg, let's manually iterate
+ // through them.
+ bool FoundAnalyzerConfig = false;
+ for (auto Arg : Args.filtered(options::OPT_Xclang))
+ if (StringRef(Arg->getValue()) == "-analyzer-config") {
+ FoundAnalyzerConfig = true;
+ break;
+ }
+ if (!FoundAnalyzerConfig)
+ for (auto Arg : Args.filtered(options::OPT_Xanalyzer))
+ if (StringRef(Arg->getValue()) == "-analyzer-config") {
+ FoundAnalyzerConfig = true;
+ break;
+ }
+ if (FoundAnalyzerConfig)
+ CmdArgs.push_back("-analyzer-config-compatibility-mode=true");
+
CheckCodeGenerationOptions(D, Args);
- unsigned FunctionAlignment = ParseFunctionAlignment(getToolChain(), Args);
+ unsigned FunctionAlignment = ParseFunctionAlignment(TC, Args);
assert(FunctionAlignment <= 31 && "function alignment will be truncated!");
if (FunctionAlignment) {
CmdArgs.push_back("-function-alignment");
@@ -3361,8 +3769,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
- std::tie(RelocationModel, PICLevel, IsPIE) =
- ParsePICArgs(getToolChain(), Args);
+ std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args);
const char *RMName = RelocationModelName(RelocationModel);
@@ -3390,13 +3797,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mthread-model");
if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) {
- if (!getToolChain().isThreadModelSupported(A->getValue()))
+ if (!TC.isThreadModelSupported(A->getValue()))
D.Diag(diag::err_drv_invalid_thread_model_for_target)
<< A->getValue() << A->getAsString(Args);
CmdArgs.push_back(A->getValue());
}
else
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel()));
+ CmdArgs.push_back(Args.MakeArgString(TC.getThreadModel()));
Args.AddLastArg(CmdArgs, options::OPT_fveclib);
@@ -3451,7 +3858,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
options::OPT_freg_struct_return)) {
- if (getToolChain().getArch() != llvm::Triple::x86) {
+ if (TC.getArch() != llvm::Triple::x86) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getSpelling() << RawTriple.str();
} else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
@@ -3516,18 +3923,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fsplit_stack))
CmdArgs.push_back("-split-stacks");
- RenderFloatingPointOptions(getToolChain(), D, OFastEnabled, Args, CmdArgs);
+ RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs);
// Decide whether to use verbose asm. Verbose assembly is the default on
// toolchains which have the integrated assembler on by default.
- bool IsIntegratedAssemblerDefault =
- getToolChain().IsIntegratedAssemblerDefault();
+ bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault();
if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
IsIntegratedAssemblerDefault) ||
Args.hasArg(options::OPT_dA))
CmdArgs.push_back("-masm-verbose");
- if (!getToolChain().useIntegratedAs())
+ if (!TC.useIntegratedAs())
CmdArgs.push_back("-no-integrated-as");
if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
@@ -3580,20 +3986,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool AsynchronousUnwindTables =
Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
options::OPT_fno_asynchronous_unwind_tables,
- (getToolChain().IsUnwindTablesDefault(Args) ||
- getToolChain().getSanitizerArgs().needsUnwindTables()) &&
+ (TC.IsUnwindTablesDefault(Args) ||
+ TC.getSanitizerArgs().needsUnwindTables()) &&
!Freestanding);
if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
AsynchronousUnwindTables))
CmdArgs.push_back("-munwind-tables");
- getToolChain().addClangTargetOptions(Args, CmdArgs,
- JA.getOffloadingDeviceKind());
-
- if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
- CmdArgs.push_back("-mlimit-float-precision");
- CmdArgs.push_back(A->getValue());
- }
+ TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind());
// FIXME: Handle -mtune=.
(void)Args.hasArg(options::OPT_mtune_EQ);
@@ -3620,22 +4020,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
types::ID InputType = Input.getType();
if (D.IsCLMode())
AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
- else
- EmitCodeView = Args.hasArg(options::OPT_gcodeview);
- const Arg *SplitDWARFArg = nullptr;
- RenderDebugOptions(getToolChain(), D, RawTriple, Args, EmitCodeView,
- IsWindowsMSVC, CmdArgs, DebugInfoKind, SplitDWARFArg);
+ DwarfFissionKind DwarfFission;
+ RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, IsWindowsMSVC,
+ CmdArgs, DebugInfoKind, DwarfFission);
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
- bool SplitDWARF = SplitDWARFArg && RawTriple.isOSLinux() &&
+ bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) &&
+ (RawTriple.isOSLinux() || RawTriple.isOSFuchsia()) &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
isa<BackendJobAction>(JA));
const char *SplitDWARFOut;
if (SplitDWARF) {
CmdArgs.push_back("-split-dwarf-file");
- SplitDWARFOut = SplitDebugName(Args, Input);
+ SplitDWARFOut = SplitDebugName(Args, Output);
CmdArgs.push_back(SplitDWARFOut);
}
@@ -3653,7 +4052,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_fallow_unsupported)) {
Arg *Unsupported;
if (types::isCXX(InputType) && RawTriple.isOSDarwin() &&
- getToolChain().getArch() == llvm::Triple::x86) {
+ TC.getArch() == llvm::Triple::x86) {
if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
(Unsupported = Args.getLastArg(options::OPT_mkernel)))
D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
@@ -3717,9 +4116,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ABICompatArg->render(Args, CmdArgs);
// Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled.
- if (RawTriple.isPS4CPU()) {
- PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs);
- PS4cpu::addSanitizerArgs(getToolChain(), CmdArgs);
+ if (RawTriple.isPS4CPU() &&
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ PS4cpu::addProfileRTArgs(TC, Args, CmdArgs);
+ PS4cpu::addSanitizerArgs(TC, CmdArgs);
}
// Pass options for controlling the default header search paths.
@@ -3867,10 +4267,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-gnu-keywords");
}
- if (ShouldDisableDwarfDirectory(Args, getToolChain()))
+ if (ShouldDisableDwarfDirectory(Args, TC))
CmdArgs.push_back("-fno-dwarf-directory-asm");
- if (ShouldDisableAutolink(Args, getToolChain()))
+ if (ShouldDisableAutolink(Args, TC))
CmdArgs.push_back("-fno-autolink");
// Add in -fdebug-compilation-dir if necessary.
@@ -3916,6 +4316,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_relocatable_pch))
CmdArgs.push_back("-relocatable-pch");
+ if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) {
+ static const char *kCFABIs[] = {
+ "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
+ };
+
+ if (find(kCFABIs, StringRef(A->getValue())) == std::end(kCFABIs))
+ D.Diag(diag::err_drv_invalid_cf_runtime_abi) << A->getValue();
+ else
+ A->render(Args, CmdArgs);
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
CmdArgs.push_back("-fconstant-string-class");
CmdArgs.push_back(A->getValue());
@@ -3983,6 +4394,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
+ Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden);
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
@@ -3993,6 +4405,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
options::OPT_fno_emulated_tls);
+ Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts);
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
@@ -4022,11 +4435,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
+ Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ);
+ Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ);
+ if (Args.hasFlag(options::OPT_fopenmp_optimistic_collapse,
+ options::OPT_fno_openmp_optimistic_collapse,
+ /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-optimistic-collapse");
// When in OpenMP offloading mode with NVPTX target, forward
// cuda-mode flag
- Args.AddLastArg(CmdArgs, options::OPT_fopenmp_cuda_mode,
- options::OPT_fno_openmp_cuda_mode);
+ if (Args.hasFlag(options::OPT_fopenmp_cuda_mode,
+ options::OPT_fno_openmp_cuda_mode, /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-cuda-mode");
+
+ // When in OpenMP offloading mode with NVPTX target, check if full runtime
+ // is required.
+ if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime,
+ options::OPT_fno_openmp_cuda_force_full_runtime,
+ /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-cuda-force-full-runtime");
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
@@ -4043,16 +4470,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
}
- const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
- Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType);
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+ Sanitize.addArgs(TC, Args, CmdArgs, InputType);
- const XRayArgs &XRay = getToolChain().getXRayArgs();
- XRay.addArgs(getToolChain(), Args, CmdArgs, InputType);
+ const XRayArgs &XRay = TC.getXRayArgs();
+ XRay.addArgs(TC, Args, CmdArgs, InputType);
- if (getToolChain().SupportsProfiling())
+ if (TC.SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_pg);
- if (getToolChain().SupportsProfiling())
+ if (TC.SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_mfentry);
// -flax-vector-conversions is default.
@@ -4099,7 +4526,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_pthread);
- RenderSSPOptions(getToolChain(), Args, CmdArgs, KernelOrKext);
+ if (Args.hasFlag(options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening,
+ false))
+ CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening"));
+
+ RenderSSPOptions(TC, Args, CmdArgs, KernelOrKext);
+ RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
@@ -4158,8 +4590,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else
A->render(Args, CmdArgs);
}
+ Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ);
- RenderBuiltinOptions(getToolChain(), RawTriple, Args, CmdArgs);
+ RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
options::OPT_fno_assume_sane_operator_new))
@@ -4167,19 +4600,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
- getToolChain().IsBlocksDefault()) ||
+ TC.IsBlocksDefault()) ||
(Args.hasArg(options::OPT_fgnu_runtime) &&
Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
!Args.hasArg(options::OPT_fno_blocks))) {
CmdArgs.push_back("-fblocks");
- if (!Args.hasArg(options::OPT_fgnu_runtime) &&
- !getToolChain().hasBlocksRuntime())
+ if (!Args.hasArg(options::OPT_fgnu_runtime) && !TC.hasBlocksRuntime())
CmdArgs.push_back("-fblocks-runtime-optional");
}
// -fencode-extended-block-signature=1 is default.
- if (getToolChain().IsEncodeExtendedBlockSignatureDefault())
+ if (TC.IsEncodeExtendedBlockSignatureDefault())
CmdArgs.push_back("-fencode-extended-block-signature");
if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
@@ -4204,7 +4636,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_felide_constructors, false))
CmdArgs.push_back("-fno-elide-constructors");
- ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
if (KernelOrKext || (types::isCXX(InputType) &&
(RTTIMode == ToolChain::RM_Disabled)))
@@ -4212,7 +4644,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fshort-enums=0 is default for all architectures except Hexagon.
if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums,
- getToolChain().getArch() == llvm::Triple::hexagon))
+ TC.getArch() == llvm::Triple::hexagon))
CmdArgs.push_back("-fshort-enums");
RenderCharacterOptions(Args, AuxTriple ? *AuxTriple : RawTriple, CmdArgs);
@@ -4222,8 +4654,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
!RawTriple.isOSWindows() &&
RawTriple.getOS() != llvm::Triple::Solaris &&
- getToolChain().getArch() != llvm::Triple::hexagon &&
- getToolChain().getArch() != llvm::Triple::xcore &&
+ TC.getArch() != llvm::Triple::xcore &&
((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) ||
RawTriple.hasEnvironment())) ||
KernelOrKext)
@@ -4252,7 +4683,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_ms_extensions, true))))
CmdArgs.push_back("-fms-compatibility");
- VersionTuple MSVT = getToolChain().computeMSVCVersion(&D, Args);
+ VersionTuple MSVT = TC.computeMSVCVersion(&D, Args);
if (!MSVT.empty())
CmdArgs.push_back(
Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
@@ -4330,8 +4761,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_experimental_new_pass_manager);
ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
- RenderObjCOptions(getToolChain(), D, RawTriple, Args, Runtime,
- rewriteKind != RK_None, Input, CmdArgs);
+ RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
+ Input, CmdArgs);
if (Args.hasFlag(options::OPT_fapplication_extension,
options::OPT_fno_application_extension, false))
@@ -4339,8 +4770,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Handle GCC-style exception args.
if (!C.getDriver().IsCLMode())
- addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, Runtime,
- CmdArgs);
+ addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs);
// Handle exception personalities
Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
@@ -4355,7 +4785,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Opt.matches(options::OPT_fdwarf_exceptions))
CmdArgs.push_back("-fdwarf-exceptions");
} else {
- switch (getToolChain().GetExceptionModel(Args)) {
+ switch (TC.GetExceptionModel(Args)) {
default:
break;
case llvm::ExceptionHandling::DwarfCFI:
@@ -4592,7 +5022,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// nice to enable this when doing a crashdump for modules as well.
if (Args.hasFlag(options::OPT_frewrite_includes,
options::OPT_fno_rewrite_includes, false) ||
- (C.isForDiagnostics() && (RewriteImports || !HaveModules)))
+ (C.isForDiagnostics() && !HaveModules))
CmdArgs.push_back("-frewrite-includes");
// Only allow -traditional or -traditional-cpp outside in preprocessing modes.
@@ -4685,23 +5115,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
addDashXForInput(Args, Input, CmdArgs);
- if (Input.isFilename())
- CmdArgs.push_back(Input.getFilename());
- else
- Input.getInputArg().renderAsInput(Args, CmdArgs);
+ ArrayRef<InputInfo> FrontendInputs = Input;
+ if (IsHeaderModulePrecompile)
+ FrontendInputs = ModuleHeaderInputs;
+ else if (Input.isNothing())
+ FrontendInputs = {};
+
+ for (const InputInfo &Input : FrontendInputs) {
+ if (Input.isFilename())
+ CmdArgs.push_back(Input.getFilename());
+ else
+ Input.getInputArg().renderAsInput(Args, CmdArgs);
+ }
Args.AddAllArgs(CmdArgs, options::OPT_undef);
const char *Exec = D.getClangProgramPath();
- // Optionally embed the -cc1 level arguments into the debug info, for build
- // analysis.
+ // Optionally embed the -cc1 level arguments into the debug info or a
+ // section, for build analysis.
// Also record command line arguments into the debug info if
// -grecord-gcc-switches options is set on.
// By default, -gno-record-gcc-switches is set on and no recording.
- if (getToolChain().UseDwarfDebugFlags() ||
- Args.hasFlag(options::OPT_grecord_gcc_switches,
- options::OPT_gno_record_gcc_switches, false)) {
+ auto GRecordSwitches =
+ Args.hasFlag(options::OPT_grecord_command_line,
+ options::OPT_gno_record_command_line, false);
+ auto FRecordSwitches =
+ Args.hasFlag(options::OPT_frecord_command_line,
+ options::OPT_fno_record_command_line, false);
+ if (FRecordSwitches && !Triple.isOSBinFormatELF())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
+ << TripleStr;
+ if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) {
ArgStringList OriginalArgs;
for (const auto &Arg : Args)
Arg->render(Args, OriginalArgs);
@@ -4714,21 +5160,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Flags += " ";
Flags += EscapedArg;
}
- CmdArgs.push_back("-dwarf-debug-flags");
- CmdArgs.push_back(Args.MakeArgString(Flags));
+ auto FlagsArgString = Args.MakeArgString(Flags);
+ if (TC.UseDwarfDebugFlags() || GRecordSwitches) {
+ CmdArgs.push_back("-dwarf-debug-flags");
+ CmdArgs.push_back(FlagsArgString);
+ }
+ if (FRecordSwitches) {
+ CmdArgs.push_back("-record-command-line");
+ CmdArgs.push_back(FlagsArgString);
+ }
}
- if (IsCuda) {
- // Host-side cuda compilation receives all device-side outputs in a single
- // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
- if (Inputs.size() > 1) {
- assert(Inputs.size() == 2 && "More than one GPU binary!");
+ // Host-side cuda compilation receives all device-side outputs in a single
+ // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
+ if ((IsCuda || IsHIP) && CudaDeviceInput) {
CmdArgs.push_back("-fcuda-include-gpubinary");
- CmdArgs.push_back(Inputs[1].getFilename());
- }
+ CmdArgs.push_back(CudaDeviceInput->getFilename());
+ if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
+ CmdArgs.push_back("-fgpu-rdc");
+ }
- if (Args.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, false))
- CmdArgs.push_back("-fcuda-rdc");
+ if (IsCuda) {
if (Args.hasFlag(options::OPT_fcuda_short_ptr,
options::OPT_fno_cuda_short_ptr, false))
CmdArgs.push_back("-fcuda-short-ptr");
@@ -4741,9 +5193,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// only the relevant declarations are emitted.
if (IsOpenMPDevice) {
CmdArgs.push_back("-fopenmp-is-device");
- if (Inputs.size() == 2) {
+ if (OpenMPDeviceInput) {
CmdArgs.push_back("-fopenmp-host-ir-file-path");
- CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
+ CmdArgs.push_back(Args.MakeArgString(OpenMPDeviceInput->getFilename()));
}
}
@@ -4777,6 +5229,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fwhole-program-vtables");
}
+ bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO();
+ bool SplitLTOUnit =
+ Args.hasFlag(options::OPT_fsplit_lto_unit,
+ options::OPT_fno_split_lto_unit, RequiresSplitLTOUnit);
+ if (RequiresSplitLTOUnit && !SplitLTOUnit)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fno-split-lto-unit"
+ << (WholeProgramVTables ? "-fwhole-program-vtables" : "-fsanitize=cfi");
+ if (SplitLTOUnit)
+ CmdArgs.push_back("-fsplit-lto-unit");
+
if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel,
options::OPT_fno_experimental_isel)) {
CmdArgs.push_back("-mllvm");
@@ -4818,6 +5281,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_complete_member_pointers, false))
CmdArgs.push_back("-fcomplete-member-pointers");
+ if (!Args.hasFlag(options::OPT_fcxx_static_destructors,
+ options::OPT_fno_cxx_static_destructors, true))
+ CmdArgs.push_back("-fno-c++-static-destructors");
+
if (Arg *A = Args.getLastArg(options::OPT_moutline,
options::OPT_mno_outline)) {
if (A->getOption().matches(options::OPT_moutline)) {
@@ -4838,8 +5305,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
- getToolChain().getTriple().isOSBinFormatELF() &&
- getToolChain().useIntegratedAs()))
+ (TC.getTriple().isOSBinFormatELF() ||
+ TC.getTriple().isOSBinFormatCOFF()) &&
+ !TC.getTriple().isPS4() &&
+ !TC.getTriple().isOSNetBSD() &&
+ !Distro(D.getVFS()).IsGentoo() &&
+ !TC.getTriple().isAndroid() &&
+ TC.useIntegratedAs()))
CmdArgs.push_back("-faddrsig");
// Finally add the compile command to the compilation.
@@ -4860,16 +5332,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
+ // Make the compile command echo its inputs for /showFilenames.
+ if (Output.getType() == types::TY_Object &&
+ Args.hasFlag(options::OPT__SLASH_showFilenames,
+ options::OPT__SLASH_showFilenames_, false)) {
+ C.getJobs().getJobs().back()->setPrintInputFilenames(true);
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_pg))
- if (Args.hasArg(options::OPT_fomit_frame_pointer))
+ if (!shouldUseFramePointer(Args, Triple))
D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer"
<< A->getAsString(Args);
// Claim some arguments which clang supports automatically.
// -fpch-preprocess is used with gcc to add a special marker in the output to
- // include the PCH file. Clang's PTH solution is completely transparent, so we
- // do not need to deal with it at all.
+ // include the PCH file.
Args.ClaimAllArgs(options::OPT_fpch_preprocess);
// Claim some arguments which clang doesn't support, but we don't
@@ -4912,7 +5390,8 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
}
if ((runtime.getKind() == ObjCRuntime::GNUstep) &&
(runtime.getVersion() >= VersionTuple(2, 0)))
- if (!getToolChain().getTriple().isOSBinFormatELF()) {
+ if (!getToolChain().getTriple().isOSBinFormatELF() &&
+ !getToolChain().getTriple().isOSBinFormatCOFF()) {
getToolChain().getDriver().Diag(
diag::err_drv_gnustep_objc_runtime_incompatible_binary)
<< runtime.getVersion().getMajor();
@@ -5163,7 +5642,6 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
*DebugInfoKind = codegenoptions::LimitedDebugInfo;
else
*DebugInfoKind = codegenoptions::DebugLineTablesOnly;
- CmdArgs.push_back("-gcodeview");
} else {
*EmitCodeView = false;
}
@@ -5197,6 +5675,16 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
if (VolatileOptionID == options::OPT__SLASH_volatile_ms)
CmdArgs.push_back("-fms-volatile");
+ if (Args.hasFlag(options::OPT__SLASH_Zc_dllexportInlines_,
+ options::OPT__SLASH_Zc_dllexportInlines,
+ false)) {
+ if (Args.hasArg(options::OPT__SLASH_fallback)) {
+ D.Diag(clang::diag::err_drv_dllexport_inlines_and_fallback);
+ } else {
+ CmdArgs.push_back("-fno-dllexport-inlines");
+ }
+ }
+
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
@@ -5270,9 +5758,28 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("msvc");
}
- if (Args.hasArg(options::OPT__SLASH_Guard) &&
- Args.getLastArgValue(options::OPT__SLASH_Guard).equals_lower("cf"))
- CmdArgs.push_back("-cfguard");
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
+ SmallVector<StringRef, 1> SplitArgs;
+ StringRef(A->getValue()).split(SplitArgs, ",");
+ bool Instrument = false;
+ bool NoChecks = false;
+ for (StringRef Arg : SplitArgs) {
+ if (Arg.equals_lower("cf"))
+ Instrument = true;
+ else if (Arg.equals_lower("cf-"))
+ Instrument = false;
+ else if (Arg.equals_lower("nochecks"))
+ NoChecks = true;
+ else if (Arg.equals_lower("nochecks-"))
+ NoChecks = false;
+ else
+ D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << Arg;
+ }
+ // Currently there's no support emitting CFG instrumentation; the flag only
+ // emits the table of address-taken functions.
+ if (Instrument || NoChecks)
+ CmdArgs.push_back("-cfguard");
+ }
}
visualstudio::Compiler *Clang::getCLFallback() const {
@@ -5525,10 +6032,12 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (Args.hasArg(options::OPT_gsplit_dwarf) &&
- getToolChain().getTriple().isOSLinux()) {
+ const llvm::Triple &T = getToolChain().getTriple();
+ Arg *A;
+ if ((getDebugFissionKind(D, Args, A) == DwarfFissionKind::Split) &&
+ (T.isOSLinux() || T.isOSFuchsia())) {
CmdArgs.push_back("-split-dwarf-file");
- CmdArgs.push_back(SplitDebugName(Args, Input));
+ CmdArgs.push_back(SplitDebugName(Args, Output));
}
assert(Input.isFilename() && "Invalid input.");
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
index 1e093b25b909..d7e316befa61 100644
--- a/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
@@ -14,13 +14,13 @@
#include "Arch/PPC.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
+#include "HIP.h"
#include "Hexagon.h"
#include "InputInfo.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
@@ -51,6 +51,7 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/YAMLParser.h"
using namespace clang::driver;
@@ -219,21 +220,6 @@ static std::string getR600TargetGPU(const ArgList &Args) {
return "";
}
-static std::string getNios2TargetCPU(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_mcpu_EQ);
- if (!A)
- A = Args.getLastArg(options::OPT_march_EQ);
-
- if (!A)
- return "";
-
- const char *name = A->getValue();
- return llvm::StringSwitch<const char *>(name)
- .Case("r1", "nios2r1")
- .Case("r2", "nios2r2")
- .Default(name);
-}
-
static std::string getLanaiTargetCPU(const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
return A->getValue();
@@ -270,7 +256,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return aarch64::getAArch64TargetCPU(Args, A);
+ return aarch64::getAArch64TargetCPU(Args, T, A);
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -286,10 +272,6 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
return A->getValue();
return "";
- case llvm::Triple::nios2: {
- return getNios2TargetCPU(Args);
- }
-
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -559,6 +541,40 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
return false;
}
+static void addSanitizerLibPath(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, StringRef Name) {
+ for (const auto &LibPath : TC.getLibraryPaths()) {
+ if (!LibPath.empty()) {
+ SmallString<128> P(LibPath);
+ llvm::sys::path::append(P, Name);
+ if (TC.getVFS().exists(P))
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P));
+ }
+ }
+}
+
+void tools::addSanitizerPathLibArgs(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ if (SanArgs.needsAsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "asan");
+ }
+ if (SanArgs.needsHwasanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "hwasan");
+ }
+ if (SanArgs.needsLsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "lsan");
+ }
+ if (SanArgs.needsMsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "msan");
+ }
+ if (SanArgs.needsTsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "tsan");
+ }
+}
+
+
+
void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
ArgStringList &CmdArgs) {
// Force linking against the system libraries sanitizers depends on
@@ -568,19 +584,19 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
!TC.getTriple().isAndroid()) {
CmdArgs.push_back("-lpthread");
- if (TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ if (!TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lrt");
}
CmdArgs.push_back("-lm");
// There's no libdl on all OSes.
- if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
- TC.getTriple().getOS() != llvm::Triple::NetBSD &&
- TC.getTriple().getOS() != llvm::Triple::OpenBSD &&
- TC.getTriple().getOS() != llvm::Triple::RTEMS)
+ if (!TC.getTriple().isOSFreeBSD() &&
+ !TC.getTriple().isOSNetBSD() &&
+ !TC.getTriple().isOSOpenBSD() &&
+ TC.getTriple().getOS() != llvm::Triple::RTEMS)
CmdArgs.push_back("-ldl");
// Required for backtrace on some OSes
- if (TC.getTriple().getOS() == llvm::Triple::NetBSD ||
- TC.getTriple().getOS() == llvm::Triple::FreeBSD)
+ if (TC.getTriple().isOSFreeBSD() ||
+ TC.getTriple().isOSNetBSD())
CmdArgs.push_back("-lexecinfo");
}
@@ -755,13 +771,13 @@ bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringLis
void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) {
CmdArgs.push_back("--no-as-needed");
CmdArgs.push_back("-lpthread");
- if (TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ if (!TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lrt");
CmdArgs.push_back("-lm");
- if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
- TC.getTriple().getOS() != llvm::Triple::NetBSD &&
- TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ if (!TC.getTriple().isOSFreeBSD() &&
+ !TC.getTriple().isOSNetBSD() &&
+ !TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-ldl");
}
@@ -773,21 +789,18 @@ bool tools::areOptimizationsEnabled(const ArgList &Args) {
return false;
}
-const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input) {
- Arg *FinalOutput = Args.getLastArg(options::OPT_o);
- if (FinalOutput && Args.hasArg(options::OPT_c)) {
- SmallString<128> T(FinalOutput->getValue());
- llvm::sys::path::replace_extension(T, "dwo");
- return Args.MakeArgString(T);
- } else {
- // Use the compilation dir.
- SmallString<128> T(
- Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
- SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
- llvm::sys::path::replace_extension(F, "dwo");
- T += F;
- return Args.MakeArgString(F);
- }
+const char *tools::SplitDebugName(const ArgList &Args,
+ const InputInfo &Output) {
+ SmallString<128> F(Output.isFilename()
+ ? Output.getFilename()
+ : llvm::sys::path::stem(Output.getBaseInput()));
+
+ if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ))
+ if (StringRef(A->getValue()) == "single")
+ return Args.MakeArgString(F);
+
+ llvm::sys::path::replace_extension(F, "dwo");
+ return Args.MakeArgString(F);
}
void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
@@ -901,7 +914,7 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
}
// OpenBSD-specific defaults for PIE
- if (Triple.getOS() == llvm::Triple::OpenBSD) {
+ if (Triple.isOSOpenBSD()) {
switch (ToolChain.getArch()) {
case llvm::Triple::arm:
case llvm::Triple::aarch64:
@@ -1126,23 +1139,39 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
bool IsIAMCU = Triple.isOSIAMCU();
bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
Args.hasArg(options::OPT_static);
- if (!D.CCCIsCXX())
+
+ bool SharedLibgcc = Args.hasArg(options::OPT_shared_libgcc);
+ bool UnspecifiedLibgcc = !StaticLibgcc && !SharedLibgcc;
+
+ // Gcc adds libgcc arguments in various ways:
+ //
+ // gcc <none>: -lgcc --as-needed -lgcc_s --no-as-needed
+ // g++ <none>: -lgcc_s -lgcc
+ // gcc shared: -lgcc_s -lgcc
+ // g++ shared: -lgcc_s -lgcc
+ // gcc static: -lgcc -lgcc_eh
+ // g++ static: -lgcc -lgcc_eh
+ //
+ // Also, certain targets need additional adjustments.
+
+ bool LibGccFirst = (D.CCCIsCC() && UnspecifiedLibgcc) || StaticLibgcc;
+ if (LibGccFirst)
CmdArgs.push_back("-lgcc");
- if (StaticLibgcc || isAndroid) {
- if (D.CCCIsCXX())
- CmdArgs.push_back("-lgcc");
- } else {
- if (!D.CCCIsCXX() && !isCygMing)
- CmdArgs.push_back("--as-needed");
+ bool AsNeeded = D.CCCIsCC() && UnspecifiedLibgcc && !isAndroid && !isCygMing;
+ if (AsNeeded)
+ CmdArgs.push_back("--as-needed");
+
+ if ((UnspecifiedLibgcc || SharedLibgcc) && !isAndroid)
CmdArgs.push_back("-lgcc_s");
- if (!D.CCCIsCXX() && !isCygMing)
- CmdArgs.push_back("--no-as-needed");
- }
- if (StaticLibgcc && !isAndroid && !IsIAMCU)
+ else if (StaticLibgcc && !isAndroid && !IsIAMCU)
CmdArgs.push_back("-lgcc_eh");
- else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
+
+ if (AsNeeded)
+ CmdArgs.push_back("--no-as-needed");
+
+ if (!LibGccFirst)
CmdArgs.push_back("-lgcc");
// According to Android ABI, we have to link with libdl if we are
@@ -1318,6 +1347,18 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
if (!JA.isHostOffloading(Action::OFK_HIP))
return;
+ InputInfoList DeviceInputs;
+ for (const auto &II : Inputs) {
+ const Action *A = II.getAction();
+ // Is this a device linking action?
+ if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) {
+ DeviceInputs.push_back(II);
+ }
+ }
+
+ if (DeviceInputs.empty())
+ return;
+
// Create temporary linker script. Keep it if save-temps is enabled.
const char *LKS;
SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
@@ -1345,39 +1386,12 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
"Wrong platform");
(void)HIPTC;
- // Construct clang-offload-bundler command to bundle object files for
- // for different GPU archs.
- ArgStringList BundlerArgs;
- BundlerArgs.push_back(Args.MakeArgString("-type=o"));
-
- // ToDo: Remove the dummy host binary entry which is required by
- // clang-offload-bundler.
- std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
- std::string BundlerInputArg = "-inputs=/dev/null";
-
- for (const auto &II : Inputs) {
- const Action *A = II.getAction();
- // Is this a device linking action?
- if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) {
- BundlerTargetArg = BundlerTargetArg + ",hip-amdgcn-amd-amdhsa-" +
- StringRef(A->getOffloadingArch()).str();
- BundlerInputArg = BundlerInputArg + "," + II.getFilename();
- }
- }
- BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
- BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
-
- std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "o");
+ // The output file name needs to persist through the compilation, therefore
+ // it needs to be created through MakeArgString.
+ std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "hipfb");
const char *BundleFile =
C.addTempFile(C.getArgs().MakeArgString(BundleFileName.c_str()));
- auto BundlerOutputArg =
- Args.MakeArgString(std::string("-outputs=").append(BundleFile));
- BundlerArgs.push_back(BundlerOutputArg);
-
- SmallString<128> BundlerPath(C.getDriver().Dir);
- llvm::sys::path::append(BundlerPath, "clang-offload-bundler");
- const char *Bundler = Args.MakeArgString(BundlerPath);
- C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
+ AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T);
// Add commands to embed target binaries. We ensure that each section and
// image is 16-byte aligned. This is not mandatory, but increases the
@@ -1397,6 +1411,10 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n";
LksStream << " " << BundleFileName << "\n";
LksStream << " }\n";
+ LksStream << " /DISCARD/ :\n";
+ LksStream << " {\n";
+ LksStream << " * ( __CLANG_OFFLOAD_BUNDLE__* )\n";
+ LksStream << " }\n";
LksStream << "}\n";
LksStream << "INSERT BEFORE .data\n";
LksStream.flush();
diff --git a/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h
index e8ebe2225e1c..3704b2e01b54 100644
--- a/lib/Driver/ToolChains/CommonArgs.h
+++ b/lib/Driver/ToolChains/CommonArgs.h
@@ -32,6 +32,10 @@ void claimNoWarnArgs(const llvm::opt::ArgList &Args);
bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
+void addSanitizerPathLibArgs(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
void linkSanitizerRuntimeDeps(const ToolChain &TC,
llvm::opt::ArgStringList &CmdArgs);
@@ -59,7 +63,7 @@ void AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
const Tool &T);
const char *SplitDebugName(const llvm::opt::ArgList &Args,
- const InputInfo &Input);
+ const InputInfo &Output);
void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
const JobAction &JA, const llvm::opt::ArgList &Args,
diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp
index 6ca04a8a3abb..795356026fbe 100644
--- a/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/lib/Driver/ToolChains/CrossWindows.cpp
@@ -20,6 +20,7 @@ using namespace clang::driver;
using namespace clang::driver::toolchains;
using llvm::opt::ArgList;
+using llvm::opt::ArgStringList;
void tools::CrossWindows::Assembler::ConstructJob(
Compilation &C, const JobAction &JA, const InputInfo &Output,
diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp
index 7fb4ae4ea9cf..57b8d4340e3b 100644
--- a/lib/Driver/ToolChains/Cuda.cpp
+++ b/lib/Driver/ToolChains/Cuda.cpp
@@ -11,7 +11,6 @@
#include "CommonArgs.h"
#include "InputInfo.h"
#include "clang/Basic/Cuda.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Distro.h"
@@ -23,6 +22,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
using namespace clang::driver;
@@ -59,6 +59,8 @@ static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
return CudaVersion::CUDA_91;
if (Major == 9 && Minor == 2)
return CudaVersion::CUDA_92;
+ if (Major == 10 && Minor == 0)
+ return CudaVersion::CUDA_100;
return CudaVersion::UNKNOWN;
}
@@ -112,7 +114,7 @@ CudaInstallationDetector::CudaInstallationDetector(
for (const char *Ver : Versions)
Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver);
- if (Distro(D.getVFS()).IsDebian())
+ if (Distro(D.getVFS()).IsDebian() || Distro(D.getVFS()).IsUbuntu())
// Special case for Debian to have nvidia-cuda-toolkit work
// out of the box. More info on http://bugs.debian.org/882505
Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda");
@@ -165,7 +167,7 @@ CudaInstallationDetector::CudaInstallationDetector(
if (FS.exists(FilePath)) {
for (const char *GpuArchName :
{"sm_30", "sm_32", "sm_35", "sm_37", "sm_50", "sm_52", "sm_53",
- "sm_60", "sm_61", "sm_62", "sm_70", "sm_72"}) {
+ "sm_60", "sm_61", "sm_62", "sm_70", "sm_72", "sm_75"}) {
const CudaArch GpuArch = StringToCudaArch(GpuArchName);
if (Version >= MinVersionForCudaArch(GpuArch) &&
Version <= MaxVersionForCudaArch(GpuArch))
@@ -276,32 +278,44 @@ void CudaInstallationDetector::print(raw_ostream &OS) const {
}
namespace {
- /// Debug info kind.
-enum DebugInfoKind {
- NoDebug, /// No debug info.
- LineTableOnly, /// Line tables only.
- FullDebug /// Full debug info.
+/// Debug info level for the NVPTX devices. We may need to emit different debug
+/// info level for the host and for the device itselfi. This type controls
+/// emission of the debug info for the devices. It either prohibits disable info
+/// emission completely, or emits debug directives only, or emits same debug
+/// info as for the host.
+enum DeviceDebugInfoLevel {
+ DisableDebugInfo, /// Do not emit debug info for the devices.
+ DebugDirectivesOnly, /// Emit only debug directives.
+ EmitSameDebugInfoAsHost, /// Use the same debug info level just like for the
+ /// host.
};
} // anonymous namespace
-static DebugInfoKind mustEmitDebugInfo(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_O_Group);
- if (Args.hasFlag(options::OPT_cuda_noopt_device_debug,
- options::OPT_no_cuda_noopt_device_debug,
- !A || A->getOption().matches(options::OPT_O0))) {
- if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
- const Option &Opt = A->getOption();
- if (Opt.matches(options::OPT_gN_Group)) {
- if (Opt.matches(options::OPT_g0) || Opt.matches(options::OPT_ggdb0))
- return NoDebug;
- if (Opt.matches(options::OPT_gline_tables_only) ||
- Opt.matches(options::OPT_ggdb1))
- return LineTableOnly;
- }
- return FullDebug;
+/// Define debug info level for the NVPTX devices. If the debug info for both
+/// the host and device are disabled (-g0/-ggdb0 or no debug options at all). If
+/// only debug directives are requested for the both host and device
+/// (-gline-directvies-only), or the debug info only for the device is disabled
+/// (optimization is on and --cuda-noopt-device-debug was not specified), the
+/// debug directves only must be emitted for the device. Otherwise, use the same
+/// debug info level just like for the host (with the limitations of only
+/// supported DWARF2 standard).
+static DeviceDebugInfoLevel mustEmitDebugInfo(const ArgList &Args) {
+ const Arg *A = Args.getLastArg(options::OPT_O_Group);
+ bool IsDebugEnabled = !A || A->getOption().matches(options::OPT_O0) ||
+ Args.hasFlag(options::OPT_cuda_noopt_device_debug,
+ options::OPT_no_cuda_noopt_device_debug,
+ /*Default=*/false);
+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ const Option &Opt = A->getOption();
+ if (Opt.matches(options::OPT_gN_Group)) {
+ if (Opt.matches(options::OPT_g0) || Opt.matches(options::OPT_ggdb0))
+ return DisableDebugInfo;
+ if (Opt.matches(options::OPT_gline_directives_only))
+ return DebugDirectivesOnly;
}
+ return IsDebugEnabled ? EmitSameDebugInfoAsHost : DebugDirectivesOnly;
}
- return NoDebug;
+ return DisableDebugInfo;
}
void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -335,8 +349,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32");
- DebugInfoKind DIKind = mustEmitDebugInfo(Args);
- if (DIKind == FullDebug) {
+ DeviceDebugInfoLevel DIKind = mustEmitDebugInfo(Args);
+ if (DIKind == EmitSameDebugInfoAsHost) {
// ptxas does not accept -g option if optimization is enabled, so
// we ignore the compiler's -O* options if we want debug info.
CmdArgs.push_back("-g");
@@ -372,7 +386,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// to no optimizations, but ptxas's default is -O3.
CmdArgs.push_back("-O0");
}
- if (DIKind == LineTableOnly)
+ if (DIKind == DebugDirectivesOnly)
CmdArgs.push_back("-lineinfo");
// Pass -v to ptxas if it was passed to the driver.
@@ -396,8 +410,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fnoopenmp_relocatable_target,
/*Default=*/true);
else if (JA.isOffloading(Action::OFK_Cuda))
- Relocatable = Args.hasFlag(options::OPT_fcuda_rdc,
- options::OPT_fno_cuda_rdc, /*Default=*/false);
+ Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
+ options::OPT_fno_gpu_rdc, /*Default=*/false);
if (Relocatable)
CmdArgs.push_back("-c");
@@ -443,7 +457,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-64" : "-32");
CmdArgs.push_back(Args.MakeArgString("--create"));
CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));
- if (mustEmitDebugInfo(Args) == FullDebug)
+ if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost)
CmdArgs.push_back("-g");
for (const auto& II : Inputs) {
@@ -496,7 +510,7 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Output.getFilename());
} else
assert(Output.isNothing() && "Invalid output.");
- if (mustEmitDebugInfo(Args) == FullDebug)
+ if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost)
CmdArgs.push_back("-g");
if (Args.hasArg(options::OPT_v))
@@ -509,6 +523,11 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-arch");
CmdArgs.push_back(Args.MakeArgString(GPUArch));
+ // Assume that the directory specified with --libomptarget_nvptx_path
+ // contains the static library libomptarget-nvptx.a.
+ if (const Arg *A = Args.getLastArg(options::OPT_libomptarget_nvptx_path_EQ))
+ CmdArgs.push_back(Args.MakeArgString(Twine("-L") + A->getValue()));
+
// Add paths specified in LIBRARY_PATH environment variable as -L options.
addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
@@ -602,9 +621,9 @@ void CudaToolChain::addClangTargetOptions(
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
- if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
+ if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false))
- CC1Args.push_back("-fcuda-rdc");
+ CC1Args.push_back("-fgpu-rdc");
}
if (DriverArgs.hasArg(options::OPT_nocudalib))
@@ -621,13 +640,16 @@ void CudaToolChain::addClangTargetOptions(
return;
}
- CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
// Libdevice in CUDA-7.0 requires PTX version that's more recent than LLVM
// defaults to. Use PTX4.2 by default, which is the PTX version that came with
// CUDA-7.0.
const char *PtxFeature = "+ptx42";
+ // TODO(tra): CUDA-10+ needs PTX 6.3 to support new features. However that
+ // requires fair amount of work on LLVM side. We'll keep using PTX 6.1 until
+ // all prerequisites are in place.
if (CudaInstallation.version() >= CudaVersion::CUDA_91) {
// CUDA-9.1 uses new instructions that are only available in PTX6.1+
PtxFeature = "+ptx61";
@@ -642,12 +664,9 @@ void CudaToolChain::addClangTargetOptions(
if (DeviceOffloadingKind == Action::OFK_OpenMP) {
SmallVector<StringRef, 8> LibraryPaths;
- // Add path to lib and/or lib64 folders.
- SmallString<256> DefaultLibPath =
- llvm::sys::path::parent_path(getDriver().Dir);
- llvm::sys::path::append(DefaultLibPath,
- Twine("lib") + CLANG_LIBDIR_SUFFIX);
- LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
+ if (const Arg *A = DriverArgs.getLastArg(options::OPT_libomptarget_nvptx_path_EQ))
+ LibraryPaths.push_back(A->getValue());
// Add user defined library paths from LIBRARY_PATH.
llvm::Optional<std::string> LibPath =
@@ -660,6 +679,12 @@ void CudaToolChain::addClangTargetOptions(
LibraryPaths.emplace_back(Path.trim());
}
+ // Add path to lib / lib64 folder.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
std::string LibOmpTargetName =
"libomptarget-nvptx-" + GpuArch.str() + ".bc";
bool FoundBCLibrary = false;
@@ -667,7 +692,7 @@ void CudaToolChain::addClangTargetOptions(
SmallString<128> LibOmpTargetFile(LibraryPath);
llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
if (llvm::sys::fs::exists(LibOmpTargetFile)) {
- CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
FoundBCLibrary = true;
break;
@@ -691,6 +716,21 @@ bool CudaToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const {
O.matches(options::OPT_gcolumn_info);
}
+void CudaToolChain::adjustDebugInfoKind(
+ codegenoptions::DebugInfoKind &DebugInfoKind, const ArgList &Args) const {
+ switch (mustEmitDebugInfo(Args)) {
+ case DisableDebugInfo:
+ DebugInfoKind = codegenoptions::NoDebugInfo;
+ break;
+ case DebugDirectivesOnly:
+ DebugInfoKind = codegenoptions::DebugDirectivesOnly;
+ break;
+ case EmitSameDebugInfoAsHost:
+ // Use same debug info level as the host.
+ break;
+ }
+}
+
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Check our CUDA version if we're going to include the CUDA headers.
diff --git a/lib/Driver/ToolChains/Cuda.h b/lib/Driver/ToolChains/Cuda.h
index 01580cb66920..1d63ede41155 100644
--- a/lib/Driver/ToolChains/Cuda.h
+++ b/lib/Driver/ToolChains/Cuda.h
@@ -159,6 +159,8 @@ public:
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override;
+ void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind,
+ const llvm::opt::ArgList &Args) const override;
bool IsMathErrnoDefault() const override { return false; }
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp
index 9205dd52de0b..c395c9a4430e 100644
--- a/lib/Driver/ToolChains/Darwin.cpp
+++ b/lib/Driver/ToolChains/Darwin.cpp
@@ -12,7 +12,6 @@
#include "CommonArgs.h"
#include "clang/Basic/AlignedAllocation.h"
#include "clang/Basic/ObjCRuntime.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -23,6 +22,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <cstdlib> // ::getenv
using namespace clang::driver;
@@ -98,7 +98,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
SourceAction = SourceAction->getInputs()[0];
}
- // If -fno-integrated-as is used add -Q to the darwin assember driver to make
+ // If -fno-integrated-as is used add -Q to the darwin assembler driver to make
// sure it runs its system assembler not clang's integrated assembler.
// Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.
// FIXME: at run-time detect assembler capabilities or rely on version
@@ -224,13 +224,20 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-application_extension");
- if (D.isUsingLTO()) {
- // If we are using LTO, then automatically create a temporary file path for
- // the linker to use, so that it's lifetime will extend past a possible
- // dsymutil step.
- if (Version[0] >= 116 && NeedsTempPath(Inputs)) {
- const char *TmpPath = C.getArgs().MakeArgString(
- D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
+ if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs)) {
+ std::string TmpPathName;
+ if (D.getLTOMode() == LTOK_Full) {
+ // If we are using full LTO, then automatically create a temporary file
+ // path for the linker to use, so that it's lifetime will extend past a
+ // possible dsymutil step.
+ TmpPathName =
+ D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
+ } else if (D.getLTOMode() == LTOK_Thin)
+ // If we are using thin LTO, then create a directory instead.
+ TmpPathName = D.GetTemporaryDirectory("thinlto");
+
+ if (!TmpPathName.empty()) {
+ auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
C.addTempFile(TmpPath);
CmdArgs.push_back("-object_path_lto");
CmdArgs.push_back(TmpPath);
@@ -509,15 +516,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
- // SafeStack requires its own runtime libraries
- // These libraries should be linked first, to make sure the
- // __safestack_init constructor executes before everything else
- if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
- getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
- "libclang_rt.safestack_osx.a",
- toolchains::Darwin::RLO_AlwaysLink);
- }
-
Args.AddAllArgs(CmdArgs, options::OPT_L);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
@@ -917,8 +915,19 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {
}
void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
- StringRef DarwinLibName,
- RuntimeLinkOptions Opts) const {
+ StringRef Component, RuntimeLinkOptions Opts,
+ bool IsShared) const {
+ SmallString<64> DarwinLibName = StringRef("libclang_rt.");
+ // an Darwin the builtins compomnent is not in the library name
+ if (Component != "builtins") {
+ DarwinLibName += Component;
+ if (!(Opts & RLO_IsEmbedded))
+ DarwinLibName += "_";
+ DarwinLibName += getOSLibraryNameSuffix();
+ } else
+ DarwinLibName += getOSLibraryNameSuffix(true);
+
+ DarwinLibName += IsShared ? "_dynamic.dylib" : ".a";
SmallString<128> Dir(getDriver().ResourceDir);
llvm::sys::path::append(
Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
@@ -983,16 +992,19 @@ StringRef Darwin::getSDKName(StringRef isysroot) {
return "";
}
-StringRef Darwin::getOSLibraryNameSuffix() const {
- switch(TargetPlatform) {
+StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
+ switch (TargetPlatform) {
case DarwinPlatformKind::MacOS:
return "osx";
case DarwinPlatformKind::IPhoneOS:
- return TargetEnvironment == NativeEnvironment ? "ios" : "iossim";
+ return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
+ : "iossim";
case DarwinPlatformKind::TvOS:
- return TargetEnvironment == NativeEnvironment ? "tvos" : "tvossim";
+ return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
+ : "tvossim";
case DarwinPlatformKind::WatchOS:
- return TargetEnvironment == NativeEnvironment ? "watchos" : "watchossim";
+ return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
+ : "watchossim";
}
llvm_unreachable("Unsupported platform");
}
@@ -1022,18 +1034,24 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (!needsProfileRT(Args)) return;
- AddLinkRuntimeLib(
- Args, CmdArgs,
- (Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(),
- RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
+ AddLinkRuntimeLib(Args, CmdArgs, "profile",
+ RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
// If we have a symbol export directive and we're linking in the profile
// runtime, automatically export symbols necessary to implement some of the
// runtime's functionality.
if (hasExportSymbolDirective(Args)) {
- addExportedSymbol(CmdArgs, "___llvm_profile_filename");
- addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
- addExportedSymbol(CmdArgs, "_lprofCurFilename");
+ if (needsGCovInstrumentation(Args)) {
+ addExportedSymbol(CmdArgs, "___gcov_flush");
+ addExportedSymbol(CmdArgs, "_flush_fn_list");
+ addExportedSymbol(CmdArgs, "_writeout_fn_list");
+ } else {
+ addExportedSymbol(CmdArgs, "___llvm_profile_filename");
+ addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
+ addExportedSymbol(CmdArgs, "_lprofCurFilename");
+ addExportedSymbol(CmdArgs, "_lprofMergeValueProfData");
+ }
+ addExportedSymbol(CmdArgs, "_lprofDirMode");
}
}
@@ -1042,12 +1060,7 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
StringRef Sanitizer,
bool Shared) const {
auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
- AddLinkRuntimeLib(Args, CmdArgs,
- (Twine("libclang_rt.") + Sanitizer + "_" +
- getOSLibraryNameSuffix() +
- (Shared ? "_dynamic.dylib" : ".a"))
- .str(),
- RLO);
+ AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
}
ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
@@ -1101,66 +1114,33 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
AddCXXStdlibLibArgs(Args, CmdArgs);
}
if (Sanitize.needsStatsRt()) {
- StringRef OS = isTargetMacOS() ? "osx" : "iossim";
- AddLinkRuntimeLib(Args, CmdArgs,
- (Twine("libclang_rt.stats_client_") + OS + ".a").str(),
- RLO_AlwaysLink);
+ AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
}
if (Sanitize.needsEsanRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "esan");
+ const XRayArgs &XRay = getXRayArgs();
+ if (XRay.needsXRayRt()) {
+ AddLinkRuntimeLib(Args, CmdArgs, "xray");
+ AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
+ AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
+ }
+
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
CmdArgs.push_back("-lSystem");
// Select the dynamic runtime library and the target specific static library.
- if (isTargetWatchOSBased()) {
- // We currently always need a static runtime library for watchOS.
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.watchos.a");
- } else if (isTargetTvOSBased()) {
- // We currently always need a static runtime library for tvOS.
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.tvos.a");
- } else if (isTargetIOSBased()) {
+ if (isTargetIOSBased()) {
// If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
// it never went into the SDK.
// Linking against libgcc_s.1 isn't needed for iOS 5.0+
if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
getTriple().getArch() != llvm::Triple::aarch64)
CmdArgs.push_back("-lgcc_s.1");
-
- // We currently always need a static runtime library for iOS.
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ios.a");
- } else {
- assert(isTargetMacOS() && "unexpected non MacOS platform");
- // The dynamic runtime library was merged with libSystem for 10.6 and
- // beyond; only 10.4 and 10.5 need an additional runtime library.
- if (isMacosxVersionLT(10, 5))
- CmdArgs.push_back("-lgcc_s.10.4");
- else if (isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-lgcc_s.10.5");
-
- // Originally for OS X, we thought we would only need a static runtime
- // library when targeting 10.4, to provide versions of the static functions
- // which were omitted from 10.4.dylib. This led to the creation of the 10.4
- // builtins library.
- //
- // Unfortunately, that turned out to not be true, because Darwin system
- // headers can still use eprintf on i386, and it is not exported from
- // libSystem. Therefore, we still must provide a runtime library just for
- // the tiny tiny handful of projects that *might* use that symbol.
- //
- // Then over time, we figured out it was useful to add more things to the
- // runtime so we created libclang_rt.osx.a to provide new functions when
- // deploying to old OS builds, and for a long time we had both eprintf and
- // osx builtin libraries. Which just seems excessive. So with PR 28855, we
- // are removing the eprintf library and expecting eprintf to be provided by
- // the OS X builtins library.
- if (isMacosxVersionLT(10, 5))
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.10.4.a");
- else
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.osx.a");
}
+ AddLinkRuntimeLib(Args, CmdArgs, "builtins");
}
/// Returns the most appropriate macOS target version for the current process.
@@ -1314,6 +1294,18 @@ struct DarwinPlatform {
return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
}
+ /// Constructs an inferred SDKInfo value based on the version inferred from
+ /// the SDK path itself. Only works for values that were created by inferring
+ /// the platform from the SDKPath.
+ DarwinSDKInfo inferSDKInfo() {
+ assert(Kind == InferredFromSDK && "can infer SDK info only");
+ llvm::VersionTuple Version;
+ bool IsValid = !Version.tryParse(OSVersion);
+ (void)IsValid;
+ assert(IsValid && "invalid SDK version");
+ return DarwinSDKInfo(Version);
+ }
+
private:
DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
: Kind(Kind), Platform(Platform), Argument(Argument) {}
@@ -1447,8 +1439,11 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
}
/// Tries to infer the deployment target from the SDK specified by -isysroot
-/// (or SDKROOT).
-Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
+/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
+/// it's available.
+Optional<DarwinPlatform>
+inferDeploymentTargetFromSDK(DerivedArgList &Args,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
const Arg *A = Args.getLastArg(options::OPT_isysroot);
if (!A)
return None;
@@ -1456,28 +1451,37 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
StringRef SDK = Darwin::getSDKName(isysroot);
if (!SDK.size())
return None;
- // Slice the version number out.
- // Version number is between the first and the last number.
- size_t StartVer = SDK.find_first_of("0123456789");
- size_t EndVer = SDK.find_last_of("0123456789");
- if (StartVer != StringRef::npos && EndVer > StartVer) {
- StringRef Version = SDK.slice(StartVer, EndVer + 1);
- if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::IPhoneOS, Version,
- /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
- else if (SDK.startswith("MacOSX"))
- return DarwinPlatform::createFromSDK(Darwin::MacOS,
- getSystemOrSDKMacOSVersion(Version));
- else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::WatchOS, Version,
- /*IsSimulator=*/SDK.startswith("WatchSimulator"));
- else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::TvOS, Version,
- /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
- }
+
+ std::string Version;
+ if (SDKInfo) {
+ // Get the version from the SDKSettings.json if it's available.
+ Version = SDKInfo->getVersion().getAsString();
+ } else {
+ // Slice the version number out.
+ // Version number is between the first and the last number.
+ size_t StartVer = SDK.find_first_of("0123456789");
+ size_t EndVer = SDK.find_last_of("0123456789");
+ if (StartVer != StringRef::npos && EndVer > StartVer)
+ Version = SDK.slice(StartVer, EndVer + 1);
+ }
+ if (Version.empty())
+ return None;
+
+ if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::IPhoneOS, Version,
+ /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
+ else if (SDK.startswith("MacOSX"))
+ return DarwinPlatform::createFromSDK(Darwin::MacOS,
+ getSystemOrSDKMacOSVersion(Version));
+ else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::WatchOS, Version,
+ /*IsSimulator=*/SDK.startswith("WatchSimulator"));
+ else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::TvOS, Version,
+ /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
return None;
}
@@ -1552,6 +1556,22 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
Args.getLastArg(options::OPT_target));
}
+Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
+ const ArgList &Args,
+ const Driver &TheDriver) {
+ const Arg *A = Args.getLastArg(options::OPT_isysroot);
+ if (!A)
+ return None;
+ StringRef isysroot = A->getValue();
+ auto SDKInfoOrErr = driver::parseDarwinSDKInfo(VFS, isysroot);
+ if (!SDKInfoOrErr) {
+ llvm::consumeError(SDKInfoOrErr.takeError());
+ TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
+ return None;
+ }
+ return *SDKInfoOrErr;
+}
+
} // namespace
void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
@@ -1576,6 +1596,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
+ // Read the SDKSettings.json file for more information, like the SDK version
+ // that we can pass down to the compiler.
+ SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
+
// The OS and the version can be specified using the -target argument.
Optional<DarwinPlatform> OSTarget =
getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver());
@@ -1621,16 +1645,22 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
if (OSTarget) {
// Don't infer simulator from the arch when the SDK is also specified.
- Optional<DarwinPlatform> SDKTarget = inferDeploymentTargetFromSDK(Args);
+ Optional<DarwinPlatform> SDKTarget =
+ inferDeploymentTargetFromSDK(Args, SDKInfo);
if (SDKTarget)
OSTarget->setEnvironment(SDKTarget->getEnvironment());
}
}
// If there is no command-line argument to specify the Target version and
// no environment variable defined, see if we can set the default based
- // on -isysroot.
- if (!OSTarget)
- OSTarget = inferDeploymentTargetFromSDK(Args);
+ // on -isysroot using SDKSettings.json if it exists.
+ if (!OSTarget) {
+ OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
+ /// If the target was successfully constructed from the SDK path, try to
+ /// infer the SDK info if the SDK doesn't have it.
+ if (OSTarget && !SDKInfo)
+ SDKInfo = OSTarget->inferSDKInfo();
+ }
// If no OS targets have been specified, try to guess platform from -target
// or arch name and compute the version from the triple.
if (!OSTarget)
@@ -1709,6 +1739,39 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
+void DarwinClang::AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // The implementation from a base class will pass through the -stdlib to
+ // CC1Args.
+ // FIXME: this should not be necessary, remove usages in the frontend
+ // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
+ ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx: {
+ llvm::StringRef InstallDir = getDriver().getInstalledDir();
+ if (InstallDir.empty())
+ break;
+ // On Darwin, libc++ may be installed alongside the compiler in
+ // include/c++/v1.
+ // Get from 'foo/bin' to 'foo/include/c++/v1'.
+ SmallString<128> P = InstallDir;
+ // Note that InstallDir can be relative, so we have to '..' and not
+ // parent_path.
+ llvm::sys::path::append(P, "..", "include", "c++", "v1");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ break;
+ }
+ case ToolChain::CST_Libstdcxx:
+ // FIXME: should we do something about it?
+ break;
+ }
+}
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
@@ -1962,12 +2025,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
else if (Name == "pentIIm3")
DAL->AddJoinedArg(nullptr, MArch, "pentium2");
- else if (Name == "x86_64")
- DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
- else if (Name == "x86_64h") {
+ else if (Name == "x86_64" || Name == "x86_64h")
DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
- DAL->AddJoinedArg(nullptr, MArch, "x86_64h");
- }
else if (Name == "arm")
DAL->AddJoinedArg(nullptr, MArch, "armv4t");
@@ -2001,12 +2060,12 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
// Embedded targets are simple at the moment, not supporting sanitizers and
// with different libraries for each member of the product { static, PIC } x
// { hard-float, soft-float }
- llvm::SmallString<32> CompilerRT = StringRef("libclang_rt.");
+ llvm::SmallString<32> CompilerRT = StringRef("");
CompilerRT +=
(tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
? "hard"
: "soft";
- CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
+ CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
}
@@ -2035,8 +2094,21 @@ bool Darwin::isAlignedAllocationUnavailable() const {
void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {
- if (isAlignedAllocationUnavailable())
+ // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
+ // enabled or disabled aligned allocations.
+ if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
+ options::OPT_fno_aligned_allocation) &&
+ isAlignedAllocationUnavailable())
CC1Args.push_back("-faligned-alloc-unavailable");
+
+ if (SDKInfo) {
+ /// Pass the SDK version to the compiler when the SDK information is
+ /// available.
+ std::string Arg;
+ llvm::raw_string_ostream OS(Arg);
+ OS << "-target-sdk-version=" << SDKInfo->getVersion();
+ CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
+ }
}
DerivedArgList *
@@ -2131,7 +2203,7 @@ llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
// Only watchOS uses the new DWARF/Compact unwinding method.
llvm::Triple Triple(ComputeLLVMTriple(Args));
- if(Triple.isWatchABI())
+ if (Triple.isWatchABI())
return llvm::ExceptionHandling::DwarfCFI;
return llvm::ExceptionHandling::SjLj;
@@ -2268,8 +2340,7 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
}
if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) &&
- !isTargetWatchOS() &&
- isMacosxVersionLT(10, 5)) {
+ !isTargetWatchOS() && isMacosxVersionLT(10, 5)) {
const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
CmdArgs.push_back(Str);
}
@@ -2290,10 +2361,15 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::Function;
+
+ // Prior to 10.9, macOS shipped a version of the C++ standard library without
+ // C++11 support. The same is true of iOS prior to version 5. These OS'es are
+ // incompatible with -fsanitize=vptr.
+ if (!(isTargetMacOS() && isMacosxVersionLT(10, 9))
+ && !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
+ Res |= SanitizerKind::Vptr;
+
if (isTargetMacOS()) {
- if (!isMacosxVersionLT(10, 9))
- Res |= SanitizerKind::Vptr;
- Res |= SanitizerKind::SafeStack;
if (IsX86_64)
Res |= SanitizerKind::Thread;
} else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
diff --git a/lib/Driver/ToolChains/Darwin.h b/lib/Driver/ToolChains/Darwin.h
index 87d553bd7e0b..d753f8967a61 100644
--- a/lib/Driver/ToolChains/Darwin.h
+++ b/lib/Driver/ToolChains/Darwin.h
@@ -11,8 +11,10 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
#include "Cuda.h"
+#include "clang/Driver/DarwinSDKInfo.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/XRayArgs.h"
namespace clang {
namespace driver {
@@ -189,9 +191,9 @@ public:
/// Add a runtime library to the list of items to link.
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
- StringRef DarwinLibName,
- RuntimeLinkOptions Opts = RuntimeLinkOptions()) const;
+ llvm::opt::ArgStringList &CmdArgs, StringRef Component,
+ RuntimeLinkOptions Opts = RuntimeLinkOptions(),
+ bool IsShared = false) const;
/// Add any profiling runtime libraries that are needed. This is essentially a
/// MachO specific version of addProfileRT in Tools.cpp.
@@ -252,6 +254,10 @@ public:
return llvm::ExceptionHandling::None;
}
+ virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const {
+ return "";
+ }
+
/// }
};
@@ -283,6 +289,9 @@ public:
/// The OS version we are targeting.
mutable VersionTuple TargetVersion;
+ /// The information about the darwin SDK that was used.
+ mutable Optional<DarwinSDKInfo> SDKInfo;
+
CudaInstallationDetector CudaInstallation;
private:
@@ -418,7 +427,7 @@ protected:
Action::OffloadKind DeviceOffloadKind) const override;
StringRef getPlatformFamily() const;
- StringRef getOSLibraryNameSuffix() const;
+ StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
public:
static StringRef getSDKName(StringRef isysroot);
@@ -489,6 +498,10 @@ public:
void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp
index c16eabf06961..7a176d260aee 100644
--- a/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/lib/Driver/ToolChains/FreeBSD.cpp
@@ -12,11 +12,11 @@
#include "Arch/Mips.h"
#include "Arch/Sparc.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp
index 54c34ff159b1..de2c7411c5e4 100644
--- a/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/lib/Driver/ToolChains/Fuchsia.cpp
@@ -76,10 +76,11 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");
+ const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs();
+
if (!Args.hasArg(options::OPT_shared)) {
std::string Dyld = D.DyldPrefix;
- if (ToolChain.getSanitizerArgs().needsAsanRt() &&
- ToolChain.getSanitizerArgs().needsSharedRt())
+ if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())
Dyld += "asan/";
Dyld += "ld.so.1";
CmdArgs.push_back("-dynamic-linker");
@@ -98,6 +99,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_u);
+ addSanitizerPathLibArgs(ToolChain, Args, CmdArgs);
+
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
if (D.isUsingLTO()) {
@@ -106,8 +109,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
D.getLTOMode() == LTOK_Thin);
}
- addSanitizerRuntimes(ToolChain, Args, CmdArgs);
-
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
ToolChain.addProfileRTLibs(Args, CmdArgs);
@@ -119,15 +122,24 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (ToolChain.ShouldLinkCXXStdlib(Args)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
+ CmdArgs.push_back("--push-state");
+ CmdArgs.push_back("--as-needed");
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bstatic");
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back("-lm");
+ CmdArgs.push_back("--pop-state");
}
- CmdArgs.push_back("-lm");
}
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+
+ if (NeedsXRayDeps)
+ linkXRayRuntimeDeps(ToolChain, CmdArgs);
+
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
if (Args.hasArg(options::OPT_pthread) ||
diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp
index 3755673250b2..2ad45097dce8 100644
--- a/lib/Driver/ToolChains/Gnu.cpp
+++ b/lib/Driver/ToolChains/Gnu.cpp
@@ -16,7 +16,6 @@
#include "Arch/SystemZ.h"
#include "CommonArgs.h"
#include "Linux.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -27,6 +26,7 @@
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
using namespace clang::driver;
@@ -228,6 +228,30 @@ void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
// The types are (hopefully) good enough.
}
+// On Arm the endianness of the output file is determined by the target and
+// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and
+// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a
+// normalized triple so we must handle the flag here.
+static bool isArmBigEndian(const llvm::Triple &Triple,
+ const ArgList &Args) {
+ bool IsBigEndian = false;
+ switch (Triple.getArch()) {
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ IsBigEndian = true;
+ LLVM_FALLTHROUGH;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian))
+ IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
+ break;
+ default:
+ break;
+ }
+ return IsBigEndian;
+}
+
static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
switch (T.getArch()) {
case llvm::Triple::x86:
@@ -237,13 +261,12 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::aarch64:
return "aarch64linux";
case llvm::Triple::aarch64_be:
- return "aarch64_be_linux";
+ return "aarch64linuxb";
case llvm::Triple::arm:
case llvm::Triple::thumb:
- return "armelf_linux_eabi";
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- return "armelfb_linux_eabi";
+ return isArmBigEndian(T, Args) ? "armelfb_linux_eabi" : "armelf_linux_eabi";
case llvm::Triple::ppc:
return "elf32ppclinux";
case llvm::Triple::ppc64:
@@ -264,11 +287,13 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::mipsel:
return "elf32ltsmip";
case llvm::Triple::mips64:
- if (tools::mips::hasMipsAbiArg(Args, "n32"))
+ if (tools::mips::hasMipsAbiArg(Args, "n32") ||
+ T.getEnvironment() == llvm::Triple::GNUABIN32)
return "elf32btsmipn32";
return "elf64btsmip";
case llvm::Triple::mips64el:
- if (tools::mips::hasMipsAbiArg(Args, "n32"))
+ if (tools::mips::hasMipsAbiArg(Args, "n32") ||
+ T.getEnvironment() == llvm::Triple::GNUABIN32)
return "elf32ltsmipn32";
return "elf64ltsmip";
case llvm::Triple::systemz:
@@ -323,14 +348,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
- const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- if (llvm::sys::path::stem(Exec) == "lld") {
- CmdArgs.push_back("-flavor");
- CmdArgs.push_back("old-gnu");
- CmdArgs.push_back("-target");
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
- }
-
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
@@ -343,8 +360,13 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
- if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb)
- arm::appendEBLinkFlags(Args, CmdArgs, Triple);
+ if (Triple.isARM() || Triple.isThumb() || Triple.isAArch64()) {
+ bool IsBigEndian = isArmBigEndian(Triple, Args);
+ if (IsBigEndian)
+ arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
+ IsBigEndian = IsBigEndian || Arch == llvm::Triple::aarch64_be;
+ CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
+ }
// Most Android ARM64 targets should enable the linker fix for erratum
// 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
@@ -539,6 +561,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddHIPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA,
*this);
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -645,6 +668,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
const llvm::Triple &Triple2 = getToolChain().getTriple();
+ CmdArgs.push_back(isArmBigEndian(Triple2, Args) ? "-EB" : "-EL");
switch (Triple2.getSubArch()) {
case llvm::Triple::ARMSubArch_v7:
CmdArgs.push_back("-mfpu=neon");
@@ -677,6 +701,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
}
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be: {
+ CmdArgs.push_back(
+ getToolChain().getArch() == llvm::Triple::aarch64_be ? "-EB" : "-EL");
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
normalizeCPUNamesForAssembler(Args, CmdArgs);
@@ -791,17 +817,17 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
getToolChain().getTriple().isOSLinux())
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
- SplitDebugName(Args, Inputs[0]));
+ SplitDebugName(Args, Output));
}
namespace {
// Filter to remove Multilibs that don't exist as a suffix to Path
class FilterNonExistent {
StringRef Base, File;
- vfs::FileSystem &VFS;
+ llvm::vfs::FileSystem &VFS;
public:
- FilterNonExistent(StringRef Base, StringRef File, vfs::FileSystem &VFS)
+ FilterNonExistent(StringRef Base, StringRef File, llvm::vfs::FileSystem &VFS)
: Base(Base), File(File), VFS(VFS) {}
bool operator()(const Multilib &M) {
return !VFS.exists(Base + M.gccSuffix() + File);
@@ -852,6 +878,10 @@ static bool isRISCV(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64;
}
+static bool isMSP430(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::msp430;
+}
+
static Multilib makeMultilib(StringRef commonSuffix) {
return Multilib(commonSuffix, commonSuffix, commonSuffix);
}
@@ -947,7 +977,7 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
return false;
}
-static bool findMipsAndroidMultilibs(vfs::FileSystem &VFS, StringRef Path,
+static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,
const Multilib::flags_list &Flags,
FilterNonExistent &NonExistent,
DetectedMultilibs &Result) {
@@ -1397,6 +1427,26 @@ static void findAndroidArmMultilibs(const Driver &D,
Result.Multilibs = AndroidArmMultilibs;
}
+static bool findMSP430Multilibs(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ DetectedMultilibs &Result) {
+ FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+ Multilib MSP430Multilib = makeMultilib("/430");
+ // FIXME: when clang starts to support msp430x ISA additional logic
+ // to select between multilib must be implemented
+ // Multilib MSP430xMultilib = makeMultilib("/large");
+
+ Result.Multilibs.push_back(MSP430Multilib);
+ Result.Multilibs.FilterOut(NonExistent);
+
+ Multilib::flags_list Flags;
+ if (Result.Multilibs.select(Flags, Result.SelectedMultilib))
+ return true;
+
+ return false;
+}
+
static void findRISCVMultilibs(const Driver &D,
const llvm::Triple &TargetTriple, StringRef Path,
const ArgList &Args, DetectedMultilibs &Result) {
@@ -1625,10 +1675,18 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
return GoodVersion;
}
-static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
+static llvm::StringRef getGCCToolchainDir(const ArgList &Args,
+ llvm::StringRef SysRoot) {
const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain);
if (A)
return A->getValue();
+
+ // If we have a SysRoot, ignore GCC_INSTALL_PREFIX.
+ // GCC_INSTALL_PREFIX specifies the gcc installation for the default
+ // sysroot and is likely not valid with a different sysroot.
+ if (!SysRoot.empty())
+ return "";
+
return GCC_INSTALL_PREFIX;
}
@@ -1660,7 +1718,7 @@ void Generic_GCC::GCCInstallationDetector::init(
SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
D.PrefixDirs.end());
- StringRef GCCToolchainDir = getGCCToolchainDir(Args);
+ StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot);
if (GCCToolchainDir != "") {
if (GCCToolchainDir.back() == '/')
GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /
@@ -1769,9 +1827,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
std::string PrefixDir = SysRoot.str() + "/usr/gcc";
std::error_code EC;
- for (vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), LE;
+ for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),
+ LE;
!EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
// Filter out obviously bad entries.
@@ -1812,19 +1871,21 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
static const char *const AArch64Triples[] = {
"aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux",
- "aarch64-suse-linux"};
+ "aarch64-suse-linux", "aarch64-linux-android"};
static const char *const AArch64beLibDirs[] = {"/lib"};
static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu",
"aarch64_be-linux-gnu"};
static const char *const ARMLibDirs[] = {"/lib"};
- static const char *const ARMTriples[] = {"arm-linux-gnueabi"};
+ static const char *const ARMTriples[] = {"arm-linux-gnueabi",
+ "arm-linux-androideabi"};
static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",
"armv7hl-redhat-linux-gnueabi",
"armv6hl-suse-linux-gnueabi",
"armv7hl-suse-linux-gnueabi"};
static const char *const ARMebLibDirs[] = {"/lib"};
- static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"};
+ static const char *const ARMebTriples[] = {"armeb-linux-gnueabi",
+ "armeb-linux-androideabi"};
static const char *const ARMebHFTriples[] = {
"armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
@@ -1835,32 +1896,47 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"x86_64-redhat-linux", "x86_64-suse-linux",
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
"x86_64-slackware-linux", "x86_64-unknown-linux",
- "x86_64-amazon-linux"};
+ "x86_64-amazon-linux", "x86_64-linux-android"};
static const char *const X32LibDirs[] = {"/libx32"};
static const char *const X86LibDirs[] = {"/lib32", "/lib"};
static const char *const X86Triples[] = {
"i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu",
"i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux",
"i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux",
- "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu"};
+ "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu",
+ "i686-linux-android", "i386-gnu", "i486-gnu",
+ "i586-gnu", "i686-gnu"};
static const char *const MIPSLibDirs[] = {"/lib"};
- static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux",
- "mips-mti-linux-gnu",
- "mips-img-linux-gnu"};
+ static const char *const MIPSTriples[] = {
+ "mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu",
+ "mips-img-linux-gnu", "mipsisa32r6-linux-gnu"};
static const char *const MIPSELLibDirs[] = {"/lib"};
- static const char *const MIPSELTriples[] = {"mipsel-linux-gnu",
- "mips-img-linux-gnu"};
+ static const char *const MIPSELTriples[] = {
+ "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu",
+ "mipsel-linux-android"};
static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64Triples[] = {
- "mips64-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
- "mips64-linux-gnuabi64"};
+ "mips64-linux-gnu", "mips-mti-linux-gnu",
+ "mips-img-linux-gnu", "mips64-linux-gnuabi64",
+ "mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"};
static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64ELTriples[] = {
- "mips64el-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
- "mips64el-linux-gnuabi64"};
+ "mips64el-linux-gnu", "mips-mti-linux-gnu",
+ "mips-img-linux-gnu", "mips64el-linux-gnuabi64",
+ "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64",
+ "mips64el-linux-android"};
+
+ static const char *const MIPSN32LibDirs[] = {"/lib32"};
+ static const char *const MIPSN32Triples[] = {"mips64-linux-gnuabin32",
+ "mipsisa64r6-linux-gnuabin32"};
+ static const char *const MIPSN32ELLibDirs[] = {"/lib32"};
+ static const char *const MIPSN32ELTriples[] = {
+ "mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32"};
+ static const char *const MSP430LibDirs[] = {"/lib"};
+ static const char *const MSP430Triples[] = {"msp430-elf"};
static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
static const char *const PPCTriples[] = {
@@ -2057,6 +2133,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
BiarchLibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
+ BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
break;
case llvm::Triple::mipsel:
LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
@@ -2064,20 +2142,30 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
+ BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
break;
case llvm::Triple::mips64:
LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
TripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
BiarchLibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));
BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
+ BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
break;
case llvm::Triple::mips64el:
LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
+ BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
break;
+ case llvm::Triple::msp430:
+ LibDirs.append(begin(MSP430LibDirs), end(MSP430LibDirs));
+ TripleAliases.append(begin(MSP430Triples), end(MSP430Triples));
+ break;
case llvm::Triple::ppc:
LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
TripleAliases.append(begin(PPCTriples), end(PPCTriples));
@@ -2149,6 +2237,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
return false;
} else if (isRISCV(TargetArch)) {
findRISCVMultilibs(D, TargetTriple, Path, Args, Detected);
+ } else if (isMSP430(TargetArch)) {
+ findMSP430Multilibs(D, TargetTriple, Path, Args, Detected);
} else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
NeedsBiarchSuffix, Detected)) {
return false;
@@ -2204,6 +2294,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// triple.
{"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..",
(TargetArch == llvm::Triple::x86 &&
+ TargetTriple.getOS() != llvm::Triple::Solaris)},
+ {"i386-gnu/gcc/" + CandidateTriple.str(), "../../..",
+ (TargetArch == llvm::Triple::x86 &&
TargetTriple.getOS() != llvm::Triple::Solaris)}};
for (auto &Suffix : Suffixes) {
@@ -2212,21 +2305,21 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
StringRef LibSuffix = Suffix.LibSuffix;
std::error_code EC;
- for (vfs::directory_iterator
+ for (llvm::vfs::directory_iterator
LI = D.getVFS().dir_begin(LibDir + "/" + LibSuffix, EC),
LE;
!EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
if (CandidateVersion.Major != -1) // Filter obviously bad entries.
- if (!CandidateGCCInstallPaths.insert(LI->getName()).second)
+ if (!CandidateGCCInstallPaths.insert(LI->path()).second)
continue; // Saw this path before; no need to look at it again.
if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
if (CandidateVersion <= Version)
continue;
- if (!ScanGCCForMultilibs(TargetTriple, Args, LI->getName(),
+ if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
NeedsBiarchSuffix))
continue;
@@ -2375,7 +2468,7 @@ bool Generic_GCC::isPICDefault() const {
case llvm::Triple::x86_64:
return getTriple().isOSWindows();
case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
+ // Big endian PPC is PIC by default
return !getTriple().isOSBinFormatMachO() && !getTriple().isMacOSX();
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
@@ -2412,16 +2505,14 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::systemz:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
- return true;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
- // Enabled for Debian, Android, FreeBSD and OpenBSD mips64/mipsel, as they
- // can precisely identify the ABI in use (Debian) or only use N64 for MIPS64
- // (Android). Other targets are unable to distinguish N32 from N64.
- if (getTriple().getEnvironment() == llvm::Triple::GNUABI64 ||
- getTriple().isAndroid() ||
- getTriple().isOSFreeBSD() ||
- getTriple().isOSOpenBSD())
+ case llvm::Triple::msp430:
+ return true;
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ if (getTriple().isOSSolaris() || getTriple().isOSOpenBSD())
return true;
return false;
default:
@@ -2546,7 +2637,7 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
bool UseInitArrayDefault =
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
- (getTriple().getOS() == llvm::Triple::FreeBSD &&
+ (getTriple().isOSFreeBSD() &&
getTriple().getOSMajorVersion() >= 12) ||
(getTriple().getOS() == llvm::Triple::Linux &&
((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) ||
@@ -2554,7 +2645,9 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
getTriple().getOS() == llvm::Triple::NaCl ||
(getTriple().getVendor() == llvm::Triple::MipsTechnologies &&
!getTriple().hasEnvironment()) ||
- getTriple().getOS() == llvm::Triple::Solaris;
+ getTriple().getOS() == llvm::Triple::Solaris ||
+ getTriple().getArch() == llvm::Triple::riscv32 ||
+ getTriple().getArch() == llvm::Triple::riscv64;
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array, UseInitArrayDefault))
diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp
index 03acf45a9b31..868765cf88e5 100644
--- a/lib/Driver/ToolChains/HIP.cpp
+++ b/lib/Driver/ToolChains/HIP.cpp
@@ -24,6 +24,12 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+#if _WIN32 || _WIN64
+#define NULL_FILE "nul"
+#else
+#define NULL_FILE "/dev/null"
+#endif
+
namespace {
static void addBCLib(Compilation &C, const ArgList &Args,
@@ -81,8 +87,8 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand(
else
FlushDenormalControlBC = "oclc_daz_opt_off.amdgcn.bc";
- BCLibs.append({"opencl.amdgcn.bc",
- "ocml.amdgcn.bc", "ockl.amdgcn.bc", "irif.amdgcn.bc",
+ BCLibs.append({"hip.amdgcn.bc", "opencl.amdgcn.bc",
+ "ocml.amdgcn.bc", "ockl.amdgcn.bc",
"oclc_finite_only_off.amdgcn.bc",
FlushDenormalControlBC,
"oclc_correctly_rounded_sqrt_on.amdgcn.bc",
@@ -154,7 +160,7 @@ const char *AMDGCN::Linker::constructLlcCommand(
llvm::StringRef OutputFilePrefix, const char *InputFileName) const {
// Construct llc command.
ArgStringList LlcArgs{InputFileName, "-mtriple=amdgcn-amd-amdhsa",
- "-filetype=obj",
+ "-filetype=obj", "-mattr=-code-object-v3",
Args.MakeArgString("-mcpu=" + SubArchName), "-o"};
std::string LlcOutputFileName =
C.getDriver().GetTemporaryPath(OutputFilePrefix, "o");
@@ -184,6 +190,40 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs));
}
+// Construct a clang-offload-bundler command to bundle code objects for
+// different GPU's into a HIP fat binary.
+void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
+ StringRef OutputFileName, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args, const Tool& T) {
+ // Construct clang-offload-bundler command to bundle object files for
+ // for different GPU archs.
+ ArgStringList BundlerArgs;
+ BundlerArgs.push_back(Args.MakeArgString("-type=o"));
+
+ // ToDo: Remove the dummy host binary entry which is required by
+ // clang-offload-bundler.
+ std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
+ std::string BundlerInputArg = "-inputs=" NULL_FILE;
+
+ for (const auto &II : Inputs) {
+ const auto* A = II.getAction();
+ BundlerTargetArg = BundlerTargetArg + ",hip-amdgcn-amd-amdhsa-" +
+ StringRef(A->getOffloadingArch()).str();
+ BundlerInputArg = BundlerInputArg + "," + II.getFilename();
+ }
+ BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
+ BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
+
+ auto BundlerOutputArg =
+ Args.MakeArgString(std::string("-outputs=").append(OutputFileName));
+ BundlerArgs.push_back(BundlerOutputArg);
+
+ SmallString<128> BundlerPath(C.getDriver().Dir);
+ llvm::sys::path::append(BundlerPath, "clang-offload-bundler");
+ const char *Bundler = Args.MakeArgString(BundlerPath);
+ C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
+}
+
// For amdgcn the inputs of the linker job are device bitcode and output is
// object file. It calls llvm-link, opt, llc, then lld steps.
void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -192,6 +232,9 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
+ if (JA.getType() == types::TY_HIP_FATBIN)
+ return constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs, Args, *this);
+
assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
"Unsupported target");
@@ -244,9 +287,15 @@ void HIPToolChain::addClangTargetOptions(
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
- if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
+ if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false))
- CC1Args.push_back("-fcuda-rdc");
+ CC1Args.push_back("-fgpu-rdc");
+
+ // Default to "hidden" visibility, as object level linking will not be
+ // supported for the foreseeable future.
+ if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat))
+ CC1Args.append({"-fvisibility", "hidden"});
}
llvm::opt::DerivedArgList *
diff --git a/lib/Driver/ToolChains/HIP.h b/lib/Driver/ToolChains/HIP.h
index 40c9128e2f59..3af19d44dae0 100644
--- a/lib/Driver/ToolChains/HIP.h
+++ b/lib/Driver/ToolChains/HIP.h
@@ -19,6 +19,11 @@ namespace driver {
namespace tools {
namespace AMDGCN {
+ // Construct command for creating HIP fatbin.
+ void constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
+ StringRef OutputFileName, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs, const Tool& T);
+
// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
// device library, then compiles it to ISA in a shared object.
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
diff --git a/lib/Driver/ToolChains/Hexagon.cpp b/lib/Driver/ToolChains/Hexagon.cpp
index c2b27b6d9ac6..d302a3e24d8b 100644
--- a/lib/Driver/ToolChains/Hexagon.cpp
+++ b/lib/Driver/ToolChains/Hexagon.cpp
@@ -8,9 +8,8 @@
//===----------------------------------------------------------------------===//
#include "Hexagon.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
+#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -19,6 +18,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -32,6 +32,7 @@ static StringRef getDefaultHvxLength(StringRef Cpu) {
.Case("v60", "64b")
.Case("v62", "64b")
.Case("v65", "64b")
+ .Case("v66", "128b")
.Default("128b");
}
@@ -75,7 +76,7 @@ static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
// Handle -mhvx-length=.
if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
- // These falgs are valid only if HVX in enabled.
+ // These flags are valid only if HVX in enabled.
if (!HasHVX)
D.Diag(diag::err_drv_invalid_hvx_length);
else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
@@ -369,9 +370,8 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
LinkingOutput);
- std::string Linker = HTC.GetProgramPath("hexagon-link");
- C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
- CmdArgs, Inputs));
+ const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// Hexagon tools end.
@@ -513,11 +513,6 @@ unsigned HexagonToolChain::getOptimizationLevel(
void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- if (!DriverArgs.hasArg(options::OPT_ffp_contract)) {
- unsigned OptLevel = getOptimizationLevel(DriverArgs);
- if (OptLevel >= 3)
- CC1Args.push_back("-ffp-contract=fast");
- }
if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
CC1Args.push_back("-target-feature");
CC1Args.push_back("+reserved-r19");
diff --git a/lib/Driver/ToolChains/Hexagon.h b/lib/Driver/ToolChains/Hexagon.h
index e43b8a5b8800..a9e599de7ae5 100644
--- a/lib/Driver/ToolChains/Hexagon.h
+++ b/lib/Driver/ToolChains/Hexagon.h
@@ -81,6 +81,9 @@ public:
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+
+ const char *getDefaultLinker() const override { return "hexagon-link"; }
+
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
diff --git a/lib/Driver/ToolChains/Hurd.cpp b/lib/Driver/ToolChains/Hurd.cpp
new file mode 100644
index 000000000000..ff7b685dae3f
--- /dev/null
+++ b/lib/Driver/ToolChains/Hurd.cpp
@@ -0,0 +1,169 @@
+//===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Hurd.h"
+#include "CommonArgs.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+using tools::addPathIfExists;
+
+/// Get our best guess at the multiarch triple for a target.
+///
+/// Debian-based systems are starting to use a multiarch setup where they use
+/// a target-triple directory in the library and header search paths.
+/// Unfortunately, this triple does not align with the vanilla target triple,
+/// so we provide a rough mapping here.
+static std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) {
+ if (TargetTriple.getArch() == llvm::Triple::x86) {
+ // We use the existence of '/lib/<triple>' as a directory to detect some
+ // common hurd triples that don't quite match the Clang triple for both
+ // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
+ // regardless of what the actual target triple is.
+ if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))
+ return "i386-gnu";
+ }
+
+ // For most architectures, just use whatever we have rather than trying to be
+ // clever.
+ return TargetTriple.str();
+}
+
+static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
+ // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and
+ // using that variant while targeting other architectures causes problems
+ // because the libraries are laid out in shared system roots that can't cope
+ // with a 'lib32' library search path being considered. So we only enable
+ // them when we know we may need it.
+ //
+ // FIXME: This is a bit of a hack. We should really unify this code for
+ // reasoning about oslibdir spellings with the lib dir spellings in the
+ // GCCInstallationDetector, but that is a more significant refactoring.
+
+ if (Triple.getArch() == llvm::Triple::x86)
+ return "lib32";
+
+ return Triple.isArch32Bit() ? "lib" : "lib64";
+}
+
+Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ std::string SysRoot = computeSysRoot();
+ path_list &Paths = getFilePaths();
+
+ const std::string OSLibDir = getOSLibDir(Triple, Args);
+ const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
+
+ // If we are currently running Clang inside of the requested system root, add
+ // its parent library paths to those searched.
+ // FIXME: It's not clear whether we should use the driver's installed
+ // directory ('Dir' below) or the ResourceDir.
+ if (StringRef(D.Dir).startswith(SysRoot)) {
+ addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
+ }
+
+ addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+
+ addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+
+ // If we are currently running Clang inside of the requested system root, add
+ // its parent library path to those searched.
+ // FIXME: It's not clear whether we should use the driver's installed
+ // directory ('Dir' below) or the ResourceDir.
+ if (StringRef(D.Dir).startswith(SysRoot))
+ addPathIfExists(D, D.Dir + "/../lib", Paths);
+
+ addPathIfExists(D, SysRoot + "/lib", Paths);
+ addPathIfExists(D, SysRoot + "/usr/lib", Paths);
+}
+
+bool Hurd::HasNativeLLVMSupport() const { return true; }
+
+Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }
+
+Tool *Hurd::buildAssembler() const {
+ return new tools::gnutools::Assembler(*this);
+}
+
+std::string Hurd::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ return std::string();
+}
+
+std::string Hurd::getDynamicLinker(const ArgList &Args) const {
+ if (getArch() == llvm::Triple::x86)
+ return "/lib/ld.so";
+
+ llvm_unreachable("unsupported architecture");
+}
+
+void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
+ addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Check for configure-time C include directories.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ SmallVector<StringRef, 5> Dirs;
+ CIncludeDirs.split(Dirs, ":");
+ for (StringRef Dir : Dirs) {
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(Dir) ? StringRef(SysRoot) : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir);
+ }
+ return;
+ }
+
+ // Lacking those, try to detect the correct set of system includes for the
+ // target triple.
+ if (getTriple().getArch() == llvm::Triple::x86) {
+ std::string Path = SysRoot + "/usr/include/i386-gnu";
+ if (D.getVFS().exists(Path))
+ addExternCSystemInclude(DriverArgs, CC1Args, Path);
+ }
+
+ // Add an include of '/include' directly. This isn't provided by default by
+ // system GCCs, but is often used with cross-compiling GCCs, and harmless to
+ // add even when Clang is acting as-if it were a system compiler.
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
+
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
+}
diff --git a/lib/Driver/ToolChains/Hurd.h b/lib/Driver/ToolChains/Hurd.h
new file mode 100644
index 000000000000..d14619f0e2ce
--- /dev/null
+++ b/lib/Driver/ToolChains/Hurd.h
@@ -0,0 +1,46 @@
+//===--- Hurd.h - Hurd ToolChain Implementations ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
+
+#include "Gnu.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY Hurd : public Generic_ELF {
+public:
+ Hurd(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool HasNativeLLVMSupport() const override;
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ virtual std::string computeSysRoot() const;
+
+ virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const;
+
+ std::vector<std::string> ExtraOpts;
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp
index f8f36239180c..65ab9b2daf54 100644
--- a/lib/Driver/ToolChains/Linux.cpp
+++ b/lib/Driver/ToolChains/Linux.cpp
@@ -13,7 +13,6 @@
#include "Arch/PPC.h"
#include "Arch/RISCV.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/Driver.h"
@@ -23,6 +22,7 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
using namespace clang::driver;
@@ -44,6 +44,7 @@ static std::string getMultiarchTriple(const Driver &D,
llvm::Triple::EnvironmentType TargetEnvironment =
TargetTriple.getEnvironment();
bool IsAndroid = TargetTriple.isAndroid();
+ bool IsMipsR6 = TargetTriple.getSubArch() == llvm::Triple::MipsSubArch_r6;
// For most architectures, just use whatever we have rather than trying to be
// clever.
@@ -101,30 +102,36 @@ static std::string getMultiarchTriple(const Driver &D,
if (D.getVFS().exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
return "aarch64_be-linux-gnu";
break;
- case llvm::Triple::mips:
- if (D.getVFS().exists(SysRoot + "/lib/mips-linux-gnu"))
- return "mips-linux-gnu";
+ case llvm::Triple::mips: {
+ std::string Arch = IsMipsR6 ? "mipsisa32r6" : "mips";
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu"))
+ return Arch + "-linux-gnu";
break;
- case llvm::Triple::mipsel:
+ }
+ case llvm::Triple::mipsel: {
if (IsAndroid)
return "mipsel-linux-android";
- if (D.getVFS().exists(SysRoot + "/lib/mipsel-linux-gnu"))
- return "mipsel-linux-gnu";
+ std::string Arch = IsMipsR6 ? "mipsisa32r6el" : "mipsel";
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu"))
+ return Arch + "-linux-gnu";
break;
- case llvm::Triple::mips64:
- if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu"))
- return "mips64-linux-gnu";
- if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnuabi64"))
- return "mips64-linux-gnuabi64";
+ }
+ case llvm::Triple::mips64: {
+ std::string Arch = IsMipsR6 ? "mipsisa64r6" : "mips64";
+ std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment);
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI))
+ return Arch + "-linux-" + ABI;
break;
- case llvm::Triple::mips64el:
+ }
+ case llvm::Triple::mips64el: {
if (IsAndroid)
return "mips64el-linux-android";
- if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu"))
- return "mips64el-linux-gnu";
- if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnuabi64"))
- return "mips64el-linux-gnuabi64";
+ std::string Arch = IsMipsR6 ? "mipsisa64r6el" : "mips64el";
+ std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment);
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI))
+ return Arch + "-linux-" + ABI;
break;
+ }
case llvm::Triple::ppc:
if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
return "powerpc-linux-gnuspe";
@@ -210,6 +217,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
+ SelectedMultilib = GCCInstallation.getMultilib();
llvm::Triple::ArchType Arch = Triple.getArch();
std::string SysRoot = computeSysRoot();
@@ -228,16 +236,25 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
Distro Distro(D.getVFS());
- if (Distro.IsAlpineLinux()) {
+ if (Distro.IsAlpineLinux() || Triple.isAndroid()) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("now");
}
- if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux()) {
+ if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux() ||
+ Triple.isAndroid()) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("relro");
}
+ // The lld default page size is too large for Aarch64, which produces much
+ // larger .so files and images for arm64 device targets. Use 4KB page size
+ // for Android arm64 targets instead.
+ if (Triple.isAArch64() && Triple.isAndroid()) {
+ ExtraOpts.push_back("-z");
+ ExtraOpts.push_back("max-page-size=4096");
+ }
+
if (GCCInstallation.getParentLibPath().find("opt/rh/devtoolset") !=
StringRef::npos)
// With devtoolset on RHEL, we want to add a bin directory that is relative
@@ -263,15 +280,18 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// and the MIPS ABI require .dynsym to be sorted in different ways.
// .gnu.hash needs symbols to be grouped by hash code whereas the MIPS
// ABI requires a mapping between the GOT and the symbol table.
- // Android loader does not support .gnu.hash.
+ // Android loader does not support .gnu.hash until API 23.
// Hexagon linker/loader does not support .gnu.hash
- if (!IsMips && !IsAndroid && !IsHexagon) {
+ if (!IsMips && !IsHexagon) {
if (Distro.IsRedhat() || Distro.IsOpenSUSE() || Distro.IsAlpineLinux() ||
- (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick))
+ (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick) ||
+ (IsAndroid && !Triple.isAndroidVersionLT(23)))
ExtraOpts.push_back("--hash-style=gnu");
- if (Distro.IsDebian() || Distro.IsOpenSUSE() || Distro == Distro::UbuntuLucid ||
- Distro == Distro::UbuntuJaunty || Distro == Distro::UbuntuKarmic)
+ if (Distro.IsDebian() || Distro.IsOpenSUSE() ||
+ Distro == Distro::UbuntuLucid || Distro == Distro::UbuntuJaunty ||
+ Distro == Distro::UbuntuKarmic ||
+ (IsAndroid && Triple.isAndroidVersionLT(23)))
ExtraOpts.push_back("--hash-style=both");
}
@@ -299,16 +319,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
if (GCCInstallation.isValid()) {
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const std::string &LibPath = GCCInstallation.getParentLibPath();
- const Multilib &Multilib = GCCInstallation.getMultilib();
- const MultilibSet &Multilibs = GCCInstallation.getMultilibs();
// Add toolchain / multilib specific file paths.
- addMultilibsFilePaths(D, Multilibs, Multilib,
+ addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
GCCInstallation.getInstallPath(), Paths);
// Sourcery CodeBench MIPS toolchain holds some libraries under
// a biarch-like suffix of the GCC installation.
- addPathIfExists(D, GCCInstallation.getInstallPath() + Multilib.gccSuffix(),
+ addPathIfExists(D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
Paths);
// GCC cross compiling toolchains will install target libraries which ship
@@ -330,7 +348,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// Note that this matches the GCC behavior. See the below comment for where
// Clang diverges from GCC's behavior.
addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" +
- OSLibDir + Multilib.osSuffix(),
+ OSLibDir + SelectedMultilib.osSuffix(),
Paths);
// If the GCC installation we found is inside of the sysroot, we want to
@@ -433,6 +451,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
}
+ToolChain::CXXStdlibType Linux::GetDefaultCXXStdlibType() const {
+ if (getTriple().isAndroid())
+ return ToolChain::CST_Libcxx;
+ return ToolChain::CST_Libstdcxx;
+}
+
bool Linux::HasNativeLLVMSupport() const { return true; }
Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); }
@@ -695,12 +719,28 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
const StringRef MIPSELMultiarchIncludeDirs[] = {
"/usr/include/mipsel-linux-gnu"};
const StringRef MIPS64MultiarchIncludeDirs[] = {
- "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"};
+ "/usr/include/mips64-linux-gnuabi64"};
const StringRef MIPS64ELMultiarchIncludeDirs[] = {
- "/usr/include/mips64el-linux-gnu",
"/usr/include/mips64el-linux-gnuabi64"};
+ const StringRef MIPSN32MultiarchIncludeDirs[] = {
+ "/usr/include/mips64-linux-gnuabin32"};
+ const StringRef MIPSN32ELMultiarchIncludeDirs[] = {
+ "/usr/include/mips64el-linux-gnuabin32"};
+ const StringRef MIPSR6MultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa32-linux-gnu"};
+ const StringRef MIPSR6ELMultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa32r6el-linux-gnu"};
+ const StringRef MIPS64R6MultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6-linux-gnuabi64"};
+ const StringRef MIPS64R6ELMultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6el-linux-gnuabi64"};
+ const StringRef MIPSN32R6MultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6-linux-gnuabin32"};
+ const StringRef MIPSN32R6ELMultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6el-linux-gnuabin32"};
const StringRef PPCMultiarchIncludeDirs[] = {
- "/usr/include/powerpc-linux-gnu"};
+ "/usr/include/powerpc-linux-gnu",
+ "/usr/include/powerpc-linux-gnuspe"};
const StringRef PPC64MultiarchIncludeDirs[] = {
"/usr/include/powerpc64-linux-gnu"};
const StringRef PPC64LEMultiarchIncludeDirs[] = {
@@ -738,16 +778,38 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
MultiarchIncludeDirs = ARMEBMultiarchIncludeDirs;
break;
case llvm::Triple::mips:
- MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ MultiarchIncludeDirs = MIPSR6MultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
break;
case llvm::Triple::mipsel:
- MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ MultiarchIncludeDirs = MIPSR6ELMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
break;
case llvm::Triple::mips64:
- MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32R6MultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64R6MultiarchIncludeDirs;
+ else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32MultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
break;
case llvm::Triple::mips64el:
- MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32R6ELMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64R6ELMultiarchIncludeDirs;
+ else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32ELMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
break;
case llvm::Triple::ppc:
MultiarchIncludeDirs = PPCMultiarchIncludeDirs;
@@ -876,6 +938,9 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
// Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
// without a subdirectory corresponding to the gcc version.
LibDir.str() + "/../include/c++",
+ // Cray's gcc installation puts headers under "g++" without a
+ // version suffix.
+ LibDir.str() + "/../include/g++",
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
@@ -907,6 +972,12 @@ bool Linux::isPIEDefault() const {
getTriple().isMusl() || getSanitizerArgs().requiresPIE();
}
+bool Linux::IsMathErrnoDefault() const {
+ if (getTriple().isAndroid())
+ return false;
+ return Generic_ELF::IsMathErrnoDefault();
+}
+
SanitizerMask Linux::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
@@ -934,6 +1005,8 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
Res |= SanitizerKind::Thread;
+ if (IsX86_64)
+ Res |= SanitizerKind::KernelMemory;
if (IsX86_64 || IsMIPS64)
Res |= SanitizerKind::Efficiency;
if (IsX86 || IsX86_64)
@@ -954,7 +1027,7 @@ void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args,
// Add linker option -u__llvm_runtime_variable to cause runtime
// initialization module to be linked in.
- if (!Args.hasArg(options::OPT_coverage))
+ if ((!Args.hasArg(options::OPT_coverage)) && (!Args.hasArg(options::OPT_ftest_coverage)))
CmdArgs.push_back(Args.MakeArgString(
Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
ToolChain::addProfileRTLibs(Args, CmdArgs);
diff --git a/lib/Driver/ToolChains/Linux.h b/lib/Driver/ToolChains/Linux.h
index 22dbbecf6b96..4a662cb4b427 100644
--- a/lib/Driver/ToolChains/Linux.h
+++ b/lib/Driver/ToolChains/Linux.h
@@ -37,7 +37,9 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ CXXStdlibType GetDefaultCXXStdlibType() const override;
bool isPIEDefault() const override;
+ bool IsMathErrnoDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
void addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/lib/Driver/ToolChains/MSP430.cpp b/lib/Driver/ToolChains/MSP430.cpp
new file mode 100644
index 000000000000..b2ff88dbd021
--- /dev/null
+++ b/lib/Driver/ToolChains/MSP430.cpp
@@ -0,0 +1,233 @@
+//===--- MSP430.cpp - MSP430 Helpers for Tools ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSP430.h"
+#include "CommonArgs.h"
+#include "Gnu.h"
+#include "InputInfo.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Multilib.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static bool isSupportedMCU(const StringRef MCU) {
+ return llvm::StringSwitch<bool>(MCU)
+#define MSP430_MCU(NAME) .Case(NAME, true)
+#include "clang/Basic/MSP430Target.def"
+ .Default(false);
+}
+
+static StringRef getSupportedHWMult(const Arg *MCU) {
+ if (!MCU)
+ return "none";
+
+ return llvm::StringSwitch<StringRef>(MCU->getValue())
+#define MSP430_MCU_FEAT(NAME, HWMULT) .Case(NAME, HWMULT)
+#include "clang/Basic/MSP430Target.def"
+ .Default("none");
+}
+
+static StringRef getHWMultLib(const ArgList &Args) {
+ StringRef HWMult = Args.getLastArgValue(options::OPT_mhwmult_EQ, "auto");
+ if (HWMult == "auto") {
+ HWMult = getSupportedHWMult(Args.getLastArg(options::OPT_mmcu_EQ));
+ }
+
+ return llvm::StringSwitch<StringRef>(HWMult)
+ .Case("16bit", "-lmul_16")
+ .Case("32bit", "-lmul_32")
+ .Case("f5series", "-lmul_f5")
+ .Default("-lmul_none");
+}
+
+void msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ const Arg *MCU = Args.getLastArg(options::OPT_mmcu_EQ);
+ if (MCU && !isSupportedMCU(MCU->getValue())) {
+ D.Diag(diag::err_drv_clang_unsupported) << MCU->getValue();
+ return;
+ }
+
+ const Arg *HWMultArg = Args.getLastArg(options::OPT_mhwmult_EQ);
+ if (!MCU && !HWMultArg)
+ return;
+
+ StringRef HWMult = HWMultArg ? HWMultArg->getValue() : "auto";
+ StringRef SupportedHWMult = getSupportedHWMult(MCU);
+
+ if (HWMult == "auto") {
+ // 'auto' - deduce hw multiplier support based on mcu name provided.
+ // If no mcu name is provided, assume no hw multiplier is supported.
+ if (!MCU)
+ D.Diag(clang::diag::warn_drv_msp430_hwmult_no_device);
+ HWMult = SupportedHWMult;
+ }
+
+ if (HWMult == "none") {
+ // 'none' - disable hw multiplier.
+ Features.push_back("-hwmult16");
+ Features.push_back("-hwmult32");
+ Features.push_back("-hwmultf5");
+ return;
+ }
+
+ if (MCU && SupportedHWMult == "none")
+ D.Diag(clang::diag::warn_drv_msp430_hwmult_unsupported) << HWMult;
+ if (MCU && HWMult != SupportedHWMult)
+ D.Diag(clang::diag::warn_drv_msp430_hwmult_mismatch)
+ << SupportedHWMult << HWMult;
+
+ if (HWMult == "16bit") {
+ // '16bit' - for 16-bit only hw multiplier.
+ Features.push_back("+hwmult16");
+ } else if (HWMult == "32bit") {
+ // '32bit' - for 16/32-bit hw multiplier.
+ Features.push_back("+hwmult32");
+ } else if (HWMult == "f5series") {
+ // 'f5series' - for 16/32-bit hw multiplier supported by F5 series mcus.
+ Features.push_back("+hwmultf5");
+ } else {
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << HWMultArg->getAsString(Args) << HWMult;
+ }
+}
+
+/// MSP430 Toolchain
+MSP430ToolChain::MSP430ToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ StringRef MultilibSuf = "";
+
+ GCCInstallation.init(Triple, Args);
+ if (GCCInstallation.isValid()) {
+ MultilibSuf = GCCInstallation.getMultilib().gccSuffix();
+
+ SmallString<128> GCCBinPath;
+ llvm::sys::path::append(GCCBinPath,
+ GCCInstallation.getParentLibPath(), "..", "bin");
+ addPathIfExists(D, GCCBinPath, getProgramPaths());
+
+ SmallString<128> GCCRtPath;
+ llvm::sys::path::append(GCCRtPath,
+ GCCInstallation.getInstallPath(), MultilibSuf);
+ addPathIfExists(D, GCCRtPath, getFilePaths());
+ }
+
+ SmallString<128> SysRootDir(computeSysRoot());
+ llvm::sys::path::append(SysRootDir, "lib", MultilibSuf);
+ addPathIfExists(D, SysRootDir, getFilePaths());
+}
+
+std::string MSP430ToolChain::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ SmallString<128> Dir;
+ if (GCCInstallation.isValid())
+ llvm::sys::path::append(Dir, GCCInstallation.getParentLibPath(), "..",
+ GCCInstallation.getTriple().str());
+ else
+ llvm::sys::path::append(Dir, getDriver().Dir, "..", getTriple().str());
+
+ return Dir.str();
+}
+
+void MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ SmallString<128> Dir(computeSysRoot());
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+}
+
+void MSP430ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ CC1Args.push_back("-nostdsysteminc");
+
+ const auto *MCUArg = DriverArgs.getLastArg(options::OPT_mmcu_EQ);
+ if (!MCUArg)
+ return;
+
+ const StringRef MCU = MCUArg->getValue();
+ if (MCU.startswith("msp430i")) {
+ // 'i' should be in lower case as it's defined in TI MSP430-GCC headers
+ CC1Args.push_back(DriverArgs.MakeArgString(
+ "-D__MSP430i" + MCU.drop_front(7).upper() + "__"));
+ } else {
+ CC1Args.push_back(DriverArgs.MakeArgString("-D__" + MCU.upper() + "__"));
+ }
+}
+
+Tool *MSP430ToolChain::buildLinker() const {
+ return new tools::msp430::Linker(*this);
+}
+
+void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &ToolChain = getToolChain();
+ const Driver &D = ToolChain.getDriver();
+ std::string Linker = ToolChain.GetProgramPath(getShortName());
+ ArgStringList CmdArgs;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_T)) {
+ if (const Arg *MCUArg = Args.getLastArg(options::OPT_mmcu_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString("-T" + StringRef(MCUArg->getValue()) + ".ld"));
+ } else {
+ Args.AddAllArgs(CmdArgs, options::OPT_T);
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+ }
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back(Args.MakeArgString(getHWMultLib(Args)));
+ CmdArgs.push_back("-lgcc");
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lcrt");
+ CmdArgs.push_back("-lnosys");
+ }
+ CmdArgs.push_back("--end-group");
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
+ CmdArgs, Inputs));
+}
diff --git a/lib/Driver/ToolChains/MSP430.h b/lib/Driver/ToolChains/MSP430.h
new file mode 100644
index 000000000000..0fdceb75b963
--- /dev/null
+++ b/lib/Driver/ToolChains/MSP430.h
@@ -0,0 +1,71 @@
+//===--- MSP430.h - MSP430-specific Tool Helpers ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H
+
+#include "Gnu.h"
+#include "InputInfo.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY MSP430ToolChain : public Generic_ELF {
+public:
+ MSP430ToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const override;
+
+protected:
+ Tool *buildLinker() const override;
+
+private:
+ std::string computeSysRoot() const;
+};
+
+} // end namespace toolchains
+
+namespace tools {
+namespace msp430 {
+
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC)
+ : GnuTool("MSP430::Linker", "msp430-elf-ld", TC) {}
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+void getMSP430TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features);
+} // end namespace msp430
+} // end namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H
diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp
index d062c6abc955..7e34b0df5c8c 100644
--- a/lib/Driver/ToolChains/MSVC.cpp
+++ b/lib/Driver/ToolChains/MSVC.cpp
@@ -355,6 +355,15 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT__SLASH_Zd))
CmdArgs.push_back("-debug");
+ // Pass on /Brepro if it was passed to the compiler.
+ // Note that /Brepro maps to -mno-incremental-linker-compatible.
+ bool DefaultIncrementalLinkerCompatible =
+ C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
+ if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
+ options::OPT_mno_incremental_linker_compatible,
+ DefaultIncrementalLinkerCompatible))
+ CmdArgs.push_back("-Brepro");
+
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
options::OPT_shared);
if (DLL) {
@@ -365,6 +374,17 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
}
+ if (TC.getSanitizerArgs().needsFuzzer()) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-wholearchive:") +
+ TC.getCompilerRTArgString(Args, "fuzzer", false)));
+ CmdArgs.push_back(Args.MakeArgString("-debug"));
+ // Prevent the linker from padding sections we use for instrumentation
+ // arrays.
+ CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
+ }
+
if (TC.getSanitizerArgs().needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
@@ -702,15 +722,15 @@ bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
}
bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
- // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
- // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
- // how to generate them yet.
-
// Don't emit unwind tables by default for MachO targets.
if (getTriple().isOSBinFormatMachO())
return false;
- return getArch() == llvm::Triple::x86_64;
+ // All non-x86_32 Windows targets require unwind tables. However, LLVM
+ // doesn't know how to generate them for all targets, so only enable
+ // the ones that are actually implemented.
+ return getArch() == llvm::Triple::x86_64 ||
+ getArch() == llvm::Triple::aarch64;
}
bool MSVCToolChain::isPICDefault() const {
@@ -1266,7 +1286,7 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
if (MSVT.empty() &&
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
- // -fms-compatibility-version=19.11 is default, aka 2017
+ // -fms-compatibility-version=19.11 is default, aka 2017, 15.3
MSVT = VersionTuple(19, 11);
}
return MSVT;
@@ -1298,6 +1318,8 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
Res &= ~SanitizerKind::CFIMFCall;
return Res;
}
@@ -1356,6 +1378,7 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
}
break;
case 'g':
+ A->claim();
break;
case 'i':
if (I + 1 != E && OptStr[I + 1] == '-') {
diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h
index 1db589ec9706..ebca0018bb85 100644
--- a/lib/Driver/ToolChains/MSVC.h
+++ b/lib/Driver/ToolChains/MSVC.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H
#include "Cuda.h"
+#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -78,6 +79,18 @@ public:
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
+ /// Set CodeView as the default debug info format. Users can use -gcodeview
+ /// and -gdwarf to override the default.
+ codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override {
+ return codegenoptions::DIF_CodeView;
+ }
+
+ /// Set the debugger tuning to "default", since we're definitely not tuning
+ /// for GDB.
+ llvm::DebuggerKind getDefaultDebuggerTuning() const override {
+ return llvm::DebuggerKind::Default;
+ }
+
enum class SubDirectoryType {
Bin,
Include,
diff --git a/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp
index a88e00f0c8e8..2d5217d03d3a 100644
--- a/lib/Driver/ToolChains/MinGW.cpp
+++ b/lib/Driver/ToolChains/MinGW.cpp
@@ -10,10 +10,12 @@
#include "MinGW.h"
#include "InputInfo.h"
#include "CommonArgs.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -52,7 +54,7 @@ void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_gsplit_dwarf))
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
- SplitDebugName(Args, Inputs[0]));
+ SplitDebugName(Args, Output));
}
void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
@@ -95,7 +97,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
const ToolChain &TC = getToolChain();
const Driver &D = TC.getDriver();
- // const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
ArgStringList CmdArgs;
@@ -187,8 +189,6 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
TC.AddFilePathLibArgs(Args, CmdArgs);
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
- // TODO: Add ASan stuff here
-
// TODO: Add profile stuff here
if (TC.ShouldLinkCXXStdlib(Args)) {
@@ -220,8 +220,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lssp_nonshared");
CmdArgs.push_back("-lssp");
}
- if (Args.hasArg(options::OPT_fopenmp))
- CmdArgs.push_back("-lgomp");
+
+ if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false)) {
+ switch (TC.getDriver().getOpenMPRuntime(Args)) {
+ case Driver::OMPRT_OMP:
+ CmdArgs.push_back("-lomp");
+ break;
+ case Driver::OMPRT_IOMP5:
+ CmdArgs.push_back("-liomp5md");
+ break;
+ case Driver::OMPRT_GOMP:
+ CmdArgs.push_back("-lgomp");
+ break;
+ case Driver::OMPRT_Unknown:
+ // Already diagnosed.
+ break;
+ }
+ }
AddLibGCC(Args, CmdArgs);
@@ -231,6 +247,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
+ if (Sanitize.needsAsanRt()) {
+ // MinGW always links against a shared MSVCRT.
+ CmdArgs.push_back(
+ TC.getCompilerRTArgString(Args, "asan_dynamic", true));
+ CmdArgs.push_back(
+ TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
+ CmdArgs.push_back(Args.MakeArgString("--require-defined"));
+ CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
+ ? "___asan_seh_interceptor"
+ : "__asan_seh_interceptor"));
+ // Make sure the linker consider all object files from the dynamic
+ // runtime thunk.
+ CmdArgs.push_back(Args.MakeArgString("--whole-archive"));
+ CmdArgs.push_back(Args.MakeArgString(
+ TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
+ CmdArgs.push_back(Args.MakeArgString("--no-whole-archive"));
+ }
+
if (!HasWindowsApp) {
// Add system libraries. If linking to libwindowsapp.a, that import
// library replaces all these and we shouldn't accidentally try to
@@ -359,6 +393,10 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(Base + "lib");
// openSUSE
getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib");
+
+ NativeLLVMSupport =
+ Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
+ .equals_lower("lld");
}
bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
@@ -386,7 +424,17 @@ Tool *toolchains::MinGW::buildLinker() const {
return new tools::MinGW::Linker(*this);
}
+bool toolchains::MinGW::HasNativeLLVMSupport() const {
+ return NativeLLVMSupport;
+}
+
bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
+ Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions,
+ options::OPT_fseh_exceptions,
+ options::OPT_fdwarf_exceptions);
+ if (ExceptionArg &&
+ ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
+ return true;
return getArch() == llvm::Triple::x86_64;
}
@@ -407,6 +455,12 @@ toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
return llvm::ExceptionHandling::DwarfCFI;
}
+SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ return Res;
+}
+
void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
diff --git a/lib/Driver/ToolChains/MinGW.h b/lib/Driver/ToolChains/MinGW.h
index 0c3919d29f77..04d23006ee75 100644
--- a/lib/Driver/ToolChains/MinGW.h
+++ b/lib/Driver/ToolChains/MinGW.h
@@ -59,12 +59,16 @@ public:
MinGW(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+ bool HasNativeLLVMSupport() const override;
+
bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
+ SanitizerMask getSupportedSanitizers() const override;
+
llvm::ExceptionHandling GetExceptionModel(
const llvm::opt::ArgList &Args) const override;
@@ -97,6 +101,8 @@ private:
void findGccLibDir();
llvm::ErrorOr<std::string> findGcc();
llvm::ErrorOr<std::string> findClangRelativeSysroot();
+
+ bool NativeLLVMSupport;
};
} // end namespace toolchains
diff --git a/lib/Driver/ToolChains/Minix.cpp b/lib/Driver/ToolChains/Minix.cpp
index 39e6f90b6ef0..7fadcb129d46 100644
--- a/lib/Driver/ToolChains/Minix.cpp
+++ b/lib/Driver/ToolChains/Minix.cpp
@@ -8,13 +8,13 @@
//===----------------------------------------------------------------------===//
#include "Minix.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
+#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang;
diff --git a/lib/Driver/ToolChains/MipsLinux.h b/lib/Driver/ToolChains/MipsLinux.h
index d4b476d883e6..edf58a62b95c 100644
--- a/lib/Driver/ToolChains/MipsLinux.h
+++ b/lib/Driver/ToolChains/MipsLinux.h
@@ -49,7 +49,7 @@ public:
}
const char *getDefaultLinker() const override {
- return "lld";
+ return "ld.lld";
}
private:
diff --git a/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp
index 02caafda1657..b1321cacaf7a 100644
--- a/lib/Driver/ToolChains/NetBSD.cpp
+++ b/lib/Driver/ToolChains/NetBSD.cpp
@@ -164,7 +164,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- arm::appendEBLinkFlags(Args, CmdArgs, ToolChain.getEffectiveTriple());
+ arm::appendBE8LinkFlag(Args, CmdArgs, ToolChain.getEffectiveTriple());
CmdArgs.push_back("-m");
switch (ToolChain.getTriple().getEnvironment()) {
case llvm::Triple::EABI:
@@ -448,12 +448,24 @@ SanitizerMask NetBSD::getSupportedSanitizers() const {
Res |= SanitizerKind::Vptr;
}
if (IsX86_64) {
+ Res |= SanitizerKind::DataFlow;
Res |= SanitizerKind::Efficiency;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::HWAddress;
Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::KernelHWAddress;
+ Res |= SanitizerKind::KernelMemory;
Res |= SanitizerKind::Memory;
Res |= SanitizerKind::Thread;
}
return Res;
}
+
+void NetBSD::addClangTargetOptions(const ArgList &,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ const SanitizerArgs &SanArgs = getSanitizerArgs();
+ if (SanArgs.hasAnySanitizer())
+ CC1Args.push_back("-D_REENTRANT");
+}
diff --git a/lib/Driver/ToolChains/NetBSD.h b/lib/Driver/ToolChains/NetBSD.h
index 49e3a58d02c3..ae0865fd6573 100644
--- a/lib/Driver/ToolChains/NetBSD.h
+++ b/lib/Driver/ToolChains/NetBSD.h
@@ -76,6 +76,10 @@ public:
SanitizerMask getSupportedSanitizers() const override;
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp
index 7b98cd62bbfc..3d35d37b7db3 100644
--- a/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/lib/Driver/ToolChains/OpenBSD.cpp
@@ -111,9 +111,9 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
- if (getToolChain().getArch() == llvm::Triple::mips64)
+ if (ToolChain.getArch() == llvm::Triple::mips64)
CmdArgs.push_back("-EB");
- else if (getToolChain().getArch() == llvm::Triple::mips64el)
+ else if (ToolChain.getArch() == llvm::Triple::mips64el)
CmdArgs.push_back("-EL");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
@@ -138,7 +138,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pie))
CmdArgs.push_back("-pie");
- if (Args.hasArg(options::OPT_nopie))
+ if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-nopie");
if (Output.isFilename()) {
@@ -149,44 +149,40 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ const char *crt0 = nullptr;
+ const char *crtbegin = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o")));
+ crt0 = "gcrt0.o";
else if (Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_nopie))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("rcrt0.o")));
+ crt0 = "rcrt0.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
+ crt0 = "crt0.o";
+ crtbegin = "crtbegin.o";
} else {
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
+ crtbegin = "crtbeginS.o";
}
- }
- std::string Triple = getToolChain().getTripleString();
- if (Triple.substr(0, 6) == "x86_64")
- Triple.replace(0, 6, "amd64");
- CmdArgs.push_back(
- Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1"));
- CmdArgs.push_back(Args.MakeArgString("-L/usr/lib"));
+ if (crt0)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt0)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
- Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
- options::OPT_e, options::OPT_s, options::OPT_t,
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e,
+ options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_r});
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
- if (getToolChain().ShouldLinkCXXStdlib(Args))
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
@@ -202,7 +198,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
// FIXME: For some reason GCC passes -lgcc before adding
// the default system libraries. Just mimic this for now.
- CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lcompiler_rt");
if (Args.hasArg(options::OPT_pthread)) {
if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
@@ -218,21 +214,22 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lcompiler_rt");
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ const char *crtend = nullptr;
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
+ crtend = "crtend.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
+ crtend = "crtendS.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
}
const char *Exec = Args.MakeArgString(
- !NeedsSanitizerDeps ? getToolChain().GetLinkerPath()
- : getToolChain().GetProgramPath("ld.lld"));
+ !NeedsSanitizerDeps ? ToolChain.GetLinkerPath()
+ : ToolChain.GetProgramPath("ld.lld"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -257,8 +254,7 @@ SanitizerMask OpenBSD::getSupportedSanitizers() const {
OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
- getFilePaths().push_back(getDriver().Dir + "/../lib");
- getFilePaths().push_back("/usr/lib");
+ getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
diff --git a/lib/Driver/ToolChains/OpenBSD.h b/lib/Driver/ToolChains/OpenBSD.h
index bf8dfa4653cb..1912abdb95bc 100644
--- a/lib/Driver/ToolChains/OpenBSD.h
+++ b/lib/Driver/ToolChains/OpenBSD.h
@@ -58,6 +58,14 @@ public:
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
bool isPIEDefault() const override { return true; }
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_CompilerRT;
+ }
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Libcxx;
+ }
+
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/lib/Driver/ToolChains/PS4CPU.cpp b/lib/Driver/ToolChains/PS4CPU.cpp
index a4b74d492331..0708d25fe45c 100644
--- a/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/lib/Driver/ToolChains/PS4CPU.cpp
@@ -121,7 +121,8 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
assert(Output.isNothing() && "Invalid output.");
}
- AddPS4SanitizerArgs(ToolChain, CmdArgs);
+ if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -190,7 +191,8 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
assert(Output.isNothing() && "Invalid output.");
}
- AddPS4SanitizerArgs(ToolChain, CmdArgs);
+ if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
const char *crt1 = nullptr;
diff --git a/lib/Driver/ToolChains/RISCV.cpp b/lib/Driver/ToolChains/RISCVToolchain.cpp
index 31996fc588f1..e787c82b28a8 100644
--- a/lib/Driver/ToolChains/RISCV.cpp
+++ b/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -1,4 +1,4 @@
-//===--- RISCV.cpp - RISCV ToolChain Implementations ------------*- C++ -*-===//
+//===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "RISCV.h"
+#include "RISCVToolchain.h"
#include "CommonArgs.h"
#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -27,7 +28,7 @@ RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
- getFilePaths().push_back(D.SysRoot + "/lib");
+ getFilePaths().push_back(computeSysRoot() + "/lib");
if (GCCInstallation.isValid()) {
getFilePaths().push_back(GCCInstallation.getInstallPath().str());
getProgramPaths().push_back(
@@ -39,13 +40,21 @@ Tool *RISCVToolChain::buildLinker() const {
return new tools::RISCV::Linker(*this);
}
+void RISCVToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ CC1Args.push_back("-nostdsysteminc");
+ CC1Args.push_back("-fuse-init-array");
+}
+
void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
- SmallString<128> Dir(getDriver().SysRoot);
+ SmallString<128> Dir(computeSysRoot());
llvm::sys::path::append(Dir, "include");
addSystemInclude(DriverArgs, CC1Args, Dir.str());
}
@@ -54,15 +63,30 @@ void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
void RISCVToolChain::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- StringRef LibDir = GCCInstallation.getParentLibPath();
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
- addLibStdCXXIncludePaths(
- LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
+ addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
"", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
}
+std::string RISCVToolChain::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ if (!GCCInstallation.isValid())
+ return std::string();
+
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ std::string SysRootDir = LibDir.str() + "/../" + TripleStr.str();
+
+ if (!llvm::sys::fs::exists(SysRootDir))
+ return std::string();
+
+ return SysRootDir;
+}
+
void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
diff --git a/lib/Driver/ToolChains/RISCV.h b/lib/Driver/ToolChains/RISCVToolchain.h
index 6f59d84020d8..4b38690b1b61 100644
--- a/lib/Driver/ToolChains/RISCV.h
+++ b/lib/Driver/ToolChains/RISCVToolchain.h
@@ -1,4 +1,4 @@
-//===--- RISCV.h - RISCV ToolChain Implementations --------------*- C++ -*-===//
+//===--- RISCVToolchain.h - RISCV ToolChain Implementations -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H
#include "Gnu.h"
#include "clang/Driver/ToolChain.h"
@@ -23,6 +23,9 @@ public:
const llvm::opt::ArgList &Args);
bool IsIntegratedAssemblerDefault() const override { return true; }
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -32,6 +35,9 @@ public:
protected:
Tool *buildLinker() const override;
+
+private:
+ std::string computeSysRoot() const;
};
} // end namespace toolchains
@@ -54,4 +60,4 @@ public:
} // end namespace driver
} // end namespace clang
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H
diff --git a/lib/Driver/ToolChains/Solaris.h b/lib/Driver/ToolChains/Solaris.h
index 9e14269b393e..4d9c828b5c6b 100644
--- a/lib/Driver/ToolChains/Solaris.h
+++ b/lib/Driver/ToolChains/Solaris.h
@@ -55,8 +55,6 @@ public:
Solaris(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- bool IsIntegratedAssemblerDefault() const override { return true; }
-
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/lib/Driver/ToolChains/WebAssembly.cpp b/lib/Driver/ToolChains/WebAssembly.cpp
index 94f7279bbdba..6310d5fabaec 100644
--- a/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/lib/Driver/ToolChains/WebAssembly.cpp
@@ -22,15 +22,20 @@ using namespace clang;
using namespace llvm::opt;
wasm::Linker::Linker(const ToolChain &TC)
- : GnuTool("wasm::Linker", "lld", TC) {}
-
-bool wasm::Linker::isLinkJob() const {
- return true;
+ : GnuTool("wasm::Linker", "lld", TC) {}
+
+/// Following the conventions in https://wiki.debian.org/Multiarch/Tuples,
+/// we remove the vendor field to form the multiarch triple.
+static std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) {
+ return (TargetTriple.getArchName() + "-" +
+ TargetTriple.getOSAndEnvironmentName()).str();
}
-bool wasm::Linker::hasIntegratedCPP() const {
- return false;
-}
+bool wasm::Linker::isLinkJob() const { return true; }
+
+bool wasm::Linker::hasIntegratedCPP() const { return false; }
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
@@ -41,8 +46,6 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const ToolChain &ToolChain = getToolChain();
const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
ArgStringList CmdArgs;
- CmdArgs.push_back("-flavor");
- CmdArgs.push_back("wasm");
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
@@ -75,13 +78,23 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
- : ToolChain(D, Triple, Args) {
+ : ToolChain(D, Triple, Args) {
assert(Triple.isArch32Bit() != Triple.isArch64Bit());
getProgramPaths().push_back(getDriver().getInstalledDir());
- getFilePaths().push_back(getDriver().SysRoot + "/lib");
+ if (getTriple().getOS() == llvm::Triple::UnknownOS) {
+ // Theoretically an "unknown" OS should mean no standard libraries, however
+ // it could also mean that a custom set of libraries is in use, so just add
+ // /lib to the search path. Disable multiarch in this case, to discourage
+ // paths containing "unknown" from acquiring meanings.
+ getFilePaths().push_back(getDriver().SysRoot + "/lib");
+ } else {
+ const std::string MultiarchTriple =
+ getMultiarchTriple(getDriver(), Triple, getDriver().SysRoot);
+ getFilePaths().push_back(getDriver().SysRoot + "/lib/" + MultiarchTriple);
+ }
}
bool WebAssembly::IsMathErrnoDefault() const { return false; }
@@ -117,7 +130,8 @@ ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const {
return ToolChain::RLT_CompilerRT;
}
-ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
+ToolChain::CXXStdlibType
+WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value != "libc++")
@@ -129,16 +143,29 @@ ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) cons
void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (!DriverArgs.hasArg(options::OPT_nostdinc))
+ if (!DriverArgs.hasArg(options::OPT_nostdinc)) {
+ if (getTriple().getOS() != llvm::Triple::UnknownOS) {
+ const std::string MultiarchTriple =
+ getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
+ addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include/" + MultiarchTriple);
+ }
addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
+ }
}
void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (!DriverArgs.hasArg(options::OPT_nostdlibinc) &&
- !DriverArgs.hasArg(options::OPT_nostdincxx))
+ !DriverArgs.hasArg(options::OPT_nostdincxx)) {
+ if (getTriple().getOS() != llvm::Triple::UnknownOS) {
+ const std::string MultiarchTriple =
+ getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/include/" + MultiarchTriple + "/c++/v1");
+ }
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/include/c++/v1");
+ }
}
void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
diff --git a/lib/Driver/ToolChains/WebAssembly.h b/lib/Driver/ToolChains/WebAssembly.h
index cdbb34ff919f..d795bad90020 100644
--- a/lib/Driver/ToolChains/WebAssembly.h
+++ b/lib/Driver/ToolChains/WebAssembly.h
@@ -51,14 +51,15 @@ private:
bool hasBlocksRuntime() const override;
bool SupportsProfiling() const override;
bool HasNativeLLVMSupport() const override;
- void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
- void AddClangSystemIncludeArgs(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -66,9 +67,7 @@ private:
llvm::opt::ArgStringList &CmdArgs) const override;
std::string getThreadModel() const override;
- const char *getDefaultLinker() const override {
- return "lld";
- }
+ const char *getDefaultLinker() const override { return "wasm-ld"; }
Tool *buildLinker() const override;
};
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 45bb699cfb88..9d2737bbc719 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -312,9 +312,11 @@ ID types::lookupHeaderTypeForSourceType(ID Id) {
default:
return Id;
+ // FIXME: Handle preprocessed input types.
case types::TY_C:
return types::TY_CHeader;
case types::TY_CXX:
+ case types::TY_CXXModule:
return types::TY_CXXHeader;
case types::TY_ObjC:
return types::TY_ObjCHeader;
diff --git a/lib/Driver/XRayArgs.cpp b/lib/Driver/XRayArgs.cpp
index 30b0e72760c9..1a48493d7dc7 100644
--- a/lib/Driver/XRayArgs.cpp
+++ b/lib/Driver/XRayArgs.cpp
@@ -50,13 +50,23 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
- } else if (Triple.getOS() == llvm::Triple::FreeBSD ||
- Triple.getOS() == llvm::Triple::OpenBSD ||
- Triple.getOS() == llvm::Triple::NetBSD) {
+ } else if (Triple.isOSFreeBSD() ||
+ Triple.isOSOpenBSD() ||
+ Triple.isOSNetBSD() ||
+ Triple.getOS() == llvm::Triple::Darwin) {
if (Triple.getArch() != llvm::Triple::x86_64) {
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
+ } else if (Triple.getOS() == llvm::Triple::Fuchsia) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::aarch64:
+ break;
+ default:
+ D.Diag(diag::err_drv_clang_unsupported)
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+ }
} else {
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
@@ -164,7 +174,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
}
// Then we want to sort and unique the modes we've collected.
- llvm::sort(Modes.begin(), Modes.end());
+ llvm::sort(Modes);
Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
}
}
@@ -214,4 +224,19 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
ModeOpt += Mode;
CmdArgs.push_back(Args.MakeArgString(ModeOpt));
}
+
+ SmallString<64> Bundle("-fxray-instrumentation-bundle=");
+ if (InstrumentationBundle.full()) {
+ Bundle += "all";
+ } else if (InstrumentationBundle.empty()) {
+ Bundle += "none";
+ } else {
+ if (InstrumentationBundle.has(XRayInstrKind::Function))
+ Bundle += "function";
+ if (InstrumentationBundle.has(XRayInstrKind::Custom))
+ Bundle += "custom";
+ if (InstrumentationBundle.has(XRayInstrKind::Typed))
+ Bundle += "typed";
+ }
+ CmdArgs.push_back(Args.MakeArgString(Bundle));
}
diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp
index b53a70d87582..7c9ab170093f 100644
--- a/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -420,8 +420,8 @@ static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg,
commit.replace(MsgRange, "@[]");
return true;
}
- SourceRange ArgRange(Msg->getArg(0)->getLocStart(),
- Msg->getArg(Msg->getNumArgs()-2)->getLocEnd());
+ SourceRange ArgRange(Msg->getArg(0)->getBeginLoc(),
+ Msg->getArg(Msg->getNumArgs() - 2)->getEndLoc());
commit.replaceWithInner(MsgRange, ArgRange);
commit.insertWrap("@[", ArgRange, "]");
return true;
@@ -550,8 +550,8 @@ static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg,
// Range of arguments up until and including the last key.
// The sentinel and first value are cut off, the value will move after the
// key.
- SourceRange ArgRange(Msg->getArg(1)->getLocStart(),
- Msg->getArg(SentinelIdx-1)->getLocEnd());
+ SourceRange ArgRange(Msg->getArg(1)->getBeginLoc(),
+ Msg->getArg(SentinelIdx - 1)->getEndLoc());
commit.insertWrap("@{", ArgRange, "}");
commit.replaceWithInner(MsgRange, ArgRange);
return true;
@@ -591,8 +591,7 @@ static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg,
}
// Range of arguments up until and including the last key.
// The first value is cut off, the value will move after the key.
- SourceRange ArgRange(Keys.front()->getLocStart(),
- Keys.back()->getLocEnd());
+ SourceRange ArgRange(Keys.front()->getBeginLoc(), Keys.back()->getEndLoc());
commit.insertWrap("@{", ArgRange, "}");
commit.replaceWithInner(MsgRange, ArgRange);
return true;
@@ -1079,13 +1078,16 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
case CK_NonAtomicToAtomic:
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_ZeroToOCLOpaqueType:
case CK_IntToOCLSampler:
return false;
case CK_BooleanToSignedIntegral:
llvm_unreachable("OpenCL-specific cast in Objective-C?");
+
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
+ llvm_unreachable("Fixed point types are disabled for Objective-C");
}
}
@@ -1131,7 +1133,7 @@ static bool doRewriteToUTF8StringBoxedExpressionHelper(
if (const StringLiteral *
StrE = dyn_cast<StringLiteral>(OrigArg->IgnoreParens())) {
commit.replaceWithInner(Msg->getSourceRange(), StrE->getSourceRange());
- commit.insert(StrE->getLocStart(), "@");
+ commit.insert(StrE->getBeginLoc(), "@");
return true;
}
diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index fc2f891e0857..e6ce01b520b5 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/lib/Format/BreakableToken.cpp
@@ -67,10 +67,11 @@ static BreakableToken::Split getCommentSplit(StringRef Text,
unsigned ContentStartColumn,
unsigned ColumnLimit,
unsigned TabWidth,
- encoding::Encoding Encoding) {
- LLVM_DEBUG(llvm::dbgs() << "Comment split: \"" << Text << ", " << ColumnLimit
- << "\", Content start: " << ContentStartColumn
- << "\n");
+ encoding::Encoding Encoding,
+ const FormatStyle &Style) {
+ LLVM_DEBUG(llvm::dbgs() << "Comment split: \"" << Text
+ << "\", Column limit: " << ColumnLimit
+ << ", Content start: " << ContentStartColumn << "\n");
if (ColumnLimit <= ContentStartColumn + 1)
return BreakableToken::Split(StringRef::npos, 0);
@@ -89,12 +90,21 @@ static BreakableToken::Split getCommentSplit(StringRef Text,
StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
- // Do not split before a number followed by a dot: this would be interpreted
- // as a numbered list, which would prevent re-flowing in subsequent passes.
static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\.");
- if (SpaceOffset != StringRef::npos &&
- kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
- SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+ while (SpaceOffset != StringRef::npos) {
+ // Do not split before a number followed by a dot: this would be interpreted
+ // as a numbered list, which would prevent re-flowing in subsequent passes.
+ if (kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
+ SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+ // In JavaScript, some @tags can be followed by {, and machinery that parses
+ // these comments will fail to understand the comment if followed by a line
+ // break. So avoid ever breaking before a {.
+ else if (Style.Language == FormatStyle::LK_JavaScript &&
+ SpaceOffset + 1 < Text.size() && Text[SpaceOffset + 1] == '{')
+ SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+ else
+ break;
+ }
if (SpaceOffset == StringRef::npos ||
// Don't break at leading whitespace.
@@ -109,6 +119,12 @@ static BreakableToken::Split getCommentSplit(StringRef Text,
Blanks, std::max<unsigned>(MaxSplitBytes, FirstNonWhitespace));
}
if (SpaceOffset != StringRef::npos && SpaceOffset != 0) {
+ // adaptStartOfLine will break after lines starting with /** if the comment
+ // is broken anywhere. Avoid emitting this break twice here.
+ // Example: in /** longtextcomesherethatbreaks */ (with ColumnLimit 20) will
+ // insert a break after /**, so this code must not insert the same break.
+ if (SpaceOffset == 1 && Text[SpaceOffset - 1] == '*')
+ return BreakableToken::Split(StringRef::npos, 0);
StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(Blanks);
StringRef AfterCut = Text.substr(SpaceOffset).ltrim(Blanks);
return BreakableToken::Split(BeforeCut.size(),
@@ -260,7 +276,7 @@ BreakableComment::getSplit(unsigned LineIndex, unsigned TailOffset,
return Split(StringRef::npos, 0);
return getCommentSplit(Content[LineIndex].substr(TailOffset),
ContentStartColumn, ColumnLimit, Style.TabWidth,
- Encoding);
+ Encoding, Style);
}
void BreakableComment::compressWhitespace(
@@ -620,6 +636,8 @@ void BreakableBlockComment::adaptStartOfLine(
if (DelimitersOnNewline) {
// Since we're breaking at index 1 below, the break position and the
// break length are the same.
+ // Note: this works because getCommentSplit is careful never to split at
+ // the beginning of a line.
size_t BreakLength = Lines[0].substr(1).find_first_not_of(Blanks);
if (BreakLength != StringRef::npos)
insertBreak(LineIndex, 0, Split(1, BreakLength), /*ContentIndent=*/0,
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 7ca588a675b5..c369b94b9987 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -403,7 +403,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// }.bind(...));
// FIXME: We should find a more generic solution to this problem.
!(State.Column <= NewLineColumn &&
- Style.Language == FormatStyle::LK_JavaScript))
+ Style.Language == FormatStyle::LK_JavaScript) &&
+ !(Previous.closesScopeAfterBlock() &&
+ State.Column <= NewLineColumn))
return true;
// If the template declaration spans multiple lines, force wrap before the
@@ -700,7 +702,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
// Indent relative to the RHS of the expression unless this is a simple
// assignment without binary expression on the RHS. Also indent relative to
// unary operators and the colons of constructor initializers.
- State.Stack.back().LastSpace = State.Column;
+ if (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None)
+ State.Stack.back().LastSpace = State.Column;
} else if (Previous.is(TT_InheritanceColon)) {
State.Stack.back().Indent = State.Column;
State.Stack.back().LastSpace = State.Column;
@@ -1132,7 +1135,8 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
// }, a, b, c);
if (Current.isNot(tok::comment) && Previous &&
Previous->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) &&
- !Previous->is(TT_DictLiteral) && State.Stack.size() > 1) {
+ !Previous->is(TT_DictLiteral) && State.Stack.size() > 1 &&
+ !State.Stack.back().HasMultipleNestedBlocks) {
if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i)
State.Stack[i].NoLineBreak = true;
@@ -1499,10 +1503,25 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
// violate the rectangle rule and visually flows within the surrounding
// source.
bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] == '\n';
- unsigned NextStartColumn =
- ContentStartsOnNewline
- ? State.Stack.back().NestedBlockIndent + Style.IndentWidth
- : FirstStartColumn;
+ // If this token is the last parameter (checked by looking if it's followed by
+ // `)`, the base the indent off the line's nested block indent. Otherwise,
+ // base the indent off the arguments indent, so we can achieve:
+ // fffffffffff(1, 2, 3, R"pb(
+ // key1: 1 #
+ // key2: 2)pb");
+ //
+ // fffffffffff(1, 2, 3,
+ // R"pb(
+ // key1: 1 #
+ // key2: 2
+ // )pb",
+ // 5);
+ unsigned CurrentIndent = (Current.Next && Current.Next->is(tok::r_paren))
+ ? State.Stack.back().NestedBlockIndent
+ : State.Stack.back().Indent;
+ unsigned NextStartColumn = ContentStartsOnNewline
+ ? CurrentIndent + Style.IndentWidth
+ : FirstStartColumn;
// The last start column is the column the raw string suffix starts if it is
// put on a newline.
@@ -1514,7 +1533,7 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
// indent.
unsigned LastStartColumn = Current.NewlinesBefore
? FirstStartColumn - NewPrefixSize
- : State.Stack.back().NestedBlockIndent;
+ : CurrentIndent;
std::pair<tooling::Replacements, unsigned> Fixes = internal::reformat(
RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
@@ -1524,8 +1543,7 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
auto NewCode = applyAllReplacements(RawText, Fixes.first);
tooling::Replacements NoFixes;
if (!NewCode) {
- State.Column += Current.ColumnWidth;
- return 0;
+ return addMultilineToken(Current, State);
}
if (!DryRun) {
if (NewDelimiter != OldDelimiter) {
@@ -1574,6 +1592,13 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
unsigned PrefixExcessCharacters =
StartColumn + NewPrefixSize > Style.ColumnLimit ?
StartColumn + NewPrefixSize - Style.ColumnLimit : 0;
+ bool IsMultiline =
+ ContentStartsOnNewline || (NewCode->find('\n') != std::string::npos);
+ if (IsMultiline) {
+ // Break before further function parameters on all levels.
+ for (unsigned i = 0, e = State.Stack.size(); i != e; ++i)
+ State.Stack[i].BreakBeforeParameter = true;
+ }
return Fixes.second + PrefixExcessCharacters * Style.PenaltyExcessCharacter;
}
@@ -1840,7 +1865,8 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
// No break opportunity - update the penalty and continue with the next
// logical line.
if (LineIndex < EndIndex - 1)
- // The last line's penalty is handled in addNextStateToQueue().
+ // The last line's penalty is handled in addNextStateToQueue() or when
+ // calling replaceWhitespaceAfterLastLine below.
Penalty += Style.PenaltyExcessCharacter *
(ContentStartColumn + RemainingTokenColumns - ColumnLimit);
LLVM_DEBUG(llvm::dbgs() << " No break opportunity.\n");
@@ -2095,6 +2121,12 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
Token->getSplitAfterLastLine(TailOffset);
if (SplitAfterLastLine.first != StringRef::npos) {
LLVM_DEBUG(llvm::dbgs() << "Replacing whitespace after last line.\n");
+
+ // We add the last line's penalty here, since that line is going to be split
+ // now.
+ Penalty += Style.PenaltyExcessCharacter *
+ (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
+
if (!DryRun)
Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
Whitespaces);
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 9a2da69e89b1..2c4f8760540a 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -29,7 +29,6 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
#include "llvm/ADT/STLExtras.h"
@@ -38,6 +37,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/YAMLTraits.h"
#include <algorithm>
#include <memory>
@@ -414,6 +414,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("IndentWidth", Style.IndentWidth);
IO.mapOptional("IndentWrappedFunctionNames",
Style.IndentWrappedFunctionNames);
+ IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
@@ -469,6 +470,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
IO.mapOptional("Standard", Style.Standard);
+ IO.mapOptional("StatementMacros", Style.StatementMacros);
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("UseTab", Style.UseTab);
}
@@ -714,6 +716,8 @@ FormatStyle getLLVMStyle() {
LLVMStyle.DisableFormat = false;
LLVMStyle.SortIncludes = true;
LLVMStyle.SortUsingDeclarations = true;
+ LLVMStyle.StatementMacros.push_back("Q_UNUSED");
+ LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
return LLVMStyle;
}
@@ -819,7 +823,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
GoogleStyle.JavaScriptWrapImports = false;
} else if (Language == FormatStyle::LK_Proto) {
- GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+ GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.SpacesInContainerLiterals = false;
GoogleStyle.Cpp11BracedListStyle = false;
@@ -844,6 +848,20 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
ChromiumStyle.ContinuationIndentWidth = 8;
ChromiumStyle.IndentWidth = 4;
+ // See styleguide for import groups:
+ // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order
+ ChromiumStyle.JavaImportGroups = {
+ "android",
+ "com",
+ "dalvik",
+ "junit",
+ "org",
+ "com.google.android.apps.chrome",
+ "org.chromium",
+ "java",
+ "javax",
+ };
+ ChromiumStyle.SortIncludes = true;
} else if (Language == FormatStyle::LK_JavaScript) {
ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
ChromiumStyle.AllowShortLoopsOnASingleLine = false;
@@ -1309,8 +1327,7 @@ private:
std::set<unsigned> DeletedLines;
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
auto &Line = *AnnotatedLines[i];
- if (Line.startsWith(tok::kw_namespace) ||
- Line.startsWith(tok::kw_inline, tok::kw_namespace)) {
+ if (Line.startsWithNamespace()) {
checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
}
}
@@ -1347,9 +1364,7 @@ private:
if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
break;
- if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
- AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
- tok::kw_namespace)) {
+ if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
DeletedLines))
return false;
@@ -1489,7 +1504,8 @@ public:
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) override {
assert(Style.Language == FormatStyle::LK_Cpp);
- IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords());
+ IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
+ Tokens.getKeywords());
tooling::Replacements Result;
return {Result, 0};
}
@@ -1497,8 +1513,10 @@ public:
bool isObjC() { return IsObjC; }
private:
- static bool guessIsObjC(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- const AdditionalKeywords &Keywords) {
+ static bool
+ guessIsObjC(const SourceManager &SourceManager,
+ const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
+ const AdditionalKeywords &Keywords) {
// Keep this array sorted, since we are binary searching over it.
static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
"CGFloat",
@@ -1589,9 +1607,15 @@ private:
TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "Detected ObjC at location "
+ << FormatTok->Tok.getLocation().printToString(
+ SourceManager)
+ << " token: " << FormatTok->TokenText << " token type: "
+ << getTokenTypeName(FormatTok->Type) << "\n");
return true;
}
- if (guessIsObjC(Line->Children, Keywords))
+ if (guessIsObjC(SourceManager, Line->Children, Keywords))
return true;
}
}
@@ -1608,6 +1632,14 @@ struct IncludeDirective {
int Category;
};
+struct JavaImportDirective {
+ StringRef Identifier;
+ StringRef Text;
+ unsigned Offset;
+ std::vector<StringRef> AssociatedCommentLines;
+ bool IsStatic;
+};
+
} // end anonymous namespace
// Determines whether 'Ranges' intersects with ('Start', 'End').
@@ -1726,7 +1758,7 @@ static void sortCppIncludes(const FormatStyle &Style,
namespace {
-const char IncludeRegexPattern[] =
+const char CppIncludeRegexPattern[] =
R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
} // anonymous namespace
@@ -1738,7 +1770,7 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
unsigned *Cursor) {
unsigned Prev = 0;
unsigned SearchFrom = 0;
- llvm::Regex IncludeRegex(IncludeRegexPattern);
+ llvm::Regex IncludeRegex(CppIncludeRegexPattern);
SmallVector<StringRef, 4> Matches;
SmallVector<IncludeDirective, 16> IncludesInBlock;
@@ -1797,6 +1829,149 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
return Replaces;
}
+// Returns group number to use as a first order sort on imports. Gives UINT_MAX
+// if the import does not match any given groups.
+static unsigned findJavaImportGroup(const FormatStyle &Style,
+ StringRef ImportIdentifier) {
+ unsigned LongestMatchIndex = UINT_MAX;
+ unsigned LongestMatchLength = 0;
+ for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
+ std::string GroupPrefix = Style.JavaImportGroups[I];
+ if (ImportIdentifier.startswith(GroupPrefix) &&
+ GroupPrefix.length() > LongestMatchLength) {
+ LongestMatchIndex = I;
+ LongestMatchLength = GroupPrefix.length();
+ }
+ }
+ return LongestMatchIndex;
+}
+
+// Sorts and deduplicates a block of includes given by 'Imports' based on
+// JavaImportGroups, then adding the necessary replacement to 'Replaces'.
+// Import declarations with the same text will be deduplicated. Between each
+// import group, a newline is inserted, and within each import group, a
+// lexicographic sort based on ASCII value is performed.
+static void sortJavaImports(const FormatStyle &Style,
+ const SmallVectorImpl<JavaImportDirective> &Imports,
+ ArrayRef<tooling::Range> Ranges, StringRef FileName,
+ tooling::Replacements &Replaces) {
+ unsigned ImportsBeginOffset = Imports.front().Offset;
+ unsigned ImportsEndOffset =
+ Imports.back().Offset + Imports.back().Text.size();
+ unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
+ if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
+ return;
+ SmallVector<unsigned, 16> Indices;
+ SmallVector<unsigned, 16> JavaImportGroups;
+ for (unsigned i = 0, e = Imports.size(); i != e; ++i) {
+ Indices.push_back(i);
+ JavaImportGroups.push_back(
+ findJavaImportGroup(Style, Imports[i].Identifier));
+ }
+ llvm::sort(Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) {
+ // Negating IsStatic to push static imports above non-static imports.
+ return std::make_tuple(!Imports[LHSI].IsStatic, JavaImportGroups[LHSI],
+ Imports[LHSI].Identifier) <
+ std::make_tuple(!Imports[RHSI].IsStatic, JavaImportGroups[RHSI],
+ Imports[RHSI].Identifier);
+ });
+
+ // Deduplicate imports.
+ Indices.erase(std::unique(Indices.begin(), Indices.end(),
+ [&](unsigned LHSI, unsigned RHSI) {
+ return Imports[LHSI].Text == Imports[RHSI].Text;
+ }),
+ Indices.end());
+
+ bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
+ unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
+
+ std::string result;
+ for (unsigned Index : Indices) {
+ if (!result.empty()) {
+ result += "\n";
+ if (CurrentIsStatic != Imports[Index].IsStatic ||
+ CurrentImportGroup != JavaImportGroups[Index])
+ result += "\n";
+ }
+ for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
+ result += CommentLine;
+ result += "\n";
+ }
+ result += Imports[Index].Text;
+ CurrentIsStatic = Imports[Index].IsStatic;
+ CurrentImportGroup = JavaImportGroups[Index];
+ }
+
+ auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
+ ImportsBlockSize, result));
+ // FIXME: better error handling. For now, just skip the replacement for the
+ // release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
+}
+
+namespace {
+
+const char JavaImportRegexPattern[] =
+ "^[\t ]*import[\t ]*(static[\t ]*)?([^\t ]*)[\t ]*;";
+
+} // anonymous namespace
+
+tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName,
+ tooling::Replacements &Replaces) {
+ unsigned Prev = 0;
+ unsigned SearchFrom = 0;
+ llvm::Regex ImportRegex(JavaImportRegexPattern);
+ SmallVector<StringRef, 4> Matches;
+ SmallVector<JavaImportDirective, 16> ImportsInBlock;
+ std::vector<StringRef> AssociatedCommentLines;
+
+ bool FormattingOff = false;
+
+ for (;;) {
+ auto Pos = Code.find('\n', SearchFrom);
+ StringRef Line =
+ Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
+
+ StringRef Trimmed = Line.trim();
+ if (Trimmed == "// clang-format off")
+ FormattingOff = true;
+ else if (Trimmed == "// clang-format on")
+ FormattingOff = false;
+
+ if (ImportRegex.match(Line, &Matches)) {
+ if (FormattingOff) {
+ // If at least one import line has formatting turned off, turn off
+ // formatting entirely.
+ return Replaces;
+ }
+ StringRef Static = Matches[1];
+ StringRef Identifier = Matches[2];
+ bool IsStatic = false;
+ if (Static.contains("static")) {
+ IsStatic = true;
+ }
+ ImportsInBlock.push_back({Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
+ AssociatedCommentLines.clear();
+ } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
+ // Associating comments within the imports with the nearest import below
+ AssociatedCommentLines.push_back(Line);
+ }
+ Prev = Pos + 1;
+ if (Pos == StringRef::npos || Pos + 1 == Code.size())
+ break;
+ SearchFrom = Pos + 1;
+ }
+ if (!ImportsInBlock.empty())
+ sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Replaces);
+ return Replaces;
+}
+
bool isMpegTS(StringRef Code) {
// MPEG transport streams use the ".ts" file extension. clang-format should
// not attempt to format those. MPEG TS' frame format starts with 0x47 every
@@ -1819,6 +1994,8 @@ tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
return Replaces;
if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
return sortJavaScriptImports(Style, Code, Ranges, FileName);
+ if (Style.Language == FormatStyle::LanguageKind::LK_Java)
+ return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
return Replaces;
}
@@ -1872,7 +2049,8 @@ namespace {
inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
- llvm::Regex(IncludeRegexPattern).match(Replace.getReplacementText());
+ llvm::Regex(CppIncludeRegexPattern)
+ .match(Replace.getReplacementText());
}
inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
@@ -1925,7 +2103,7 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
}
}
- llvm::Regex IncludeRegex = llvm::Regex(IncludeRegexPattern);
+ llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern);
llvm::SmallVector<StringRef, 4> Matches;
for (const auto &R : HeaderInsertions) {
auto IncludeDirective = R.getReplacementText();
@@ -2095,8 +2273,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
bool AlternativeOperators = Style.isCpp();
LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
LangOpts.Bool = 1;
- LangOpts.ObjC1 = 1;
- LangOpts.ObjC2 = 1;
+ LangOpts.ObjC = 1;
LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
LangOpts.DeclSpecKeyword = 1; // To get __declspec.
return LangOpts;
@@ -2157,9 +2334,10 @@ const char *DefaultFallbackStyle = "LLVM";
llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
StringRef FallbackStyleName,
- StringRef Code, vfs::FileSystem *FS) {
+ StringRef Code,
+ llvm::vfs::FileSystem *FS) {
if (!FS) {
- FS = vfs::getRealFileSystem().get();
+ FS = llvm::vfs::getRealFileSystem().get();
}
FormatStyle Style = getLLVMStyle();
Style.Language = guessLanguage(FileName, Code);
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index 9094e7689e1d..10390c42911b 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -86,6 +86,7 @@ namespace format {
TYPE(RegexLiteral) \
TYPE(SelectorName) \
TYPE(StartOfName) \
+ TYPE(StatementMacro) \
TYPE(StructuredBindingLSquare) \
TYPE(TemplateCloser) \
TYPE(TemplateOpener) \
@@ -188,10 +189,6 @@ struct FormatToken {
bool ClosesTemplateDeclaration = false;
/// Number of parameters, if this is "(", "[" or "<".
- ///
- /// This is initialized to 1 as we don't need to distinguish functions with
- /// 0 parameters from functions with 1 parameter. Thus, we can simply count
- /// the number of commas.
unsigned ParameterCount = 0;
/// Number of parameters that are nested blocks,
@@ -268,7 +265,7 @@ struct FormatToken {
/// \c true if this token ends a binary expression.
bool EndsBinaryExpression = false;
- /// Is this is an operator (or "."/"->") in a sequence of operators
+ /// If this is an operator (or "."/"->") in a sequence of operators
/// with the same precedence, contains the 0-based operator index.
unsigned OperatorIndex = 0;
@@ -325,6 +322,14 @@ struct FormatToken {
}
template <typename T> bool isNot(T Kind) const { return !is(Kind); }
+ bool closesScopeAfterBlock() const {
+ if (BlockKind == BK_Block)
+ return true;
+ if (closesScope())
+ return Previous->closesScopeAfterBlock();
+ return false;
+ }
+
/// \c true if this token starts a sequence with the given tokens in order,
/// following the ``Next`` pointers, ignoring comments.
template <typename A, typename... Ts>
@@ -520,8 +525,8 @@ struct FormatToken {
const FormatToken *NamespaceTok = this;
if (is(tok::comment))
NamespaceTok = NamespaceTok->getNextNonComment();
- // Detect "(inline)? namespace" in the beginning of a line.
- if (NamespaceTok && NamespaceTok->is(tok::kw_inline))
+ // Detect "(inline|export)? namespace" in the beginning of a line.
+ if (NamespaceTok && NamespaceTok->isOneOf(tok::kw_inline, tok::kw_export))
NamespaceTok = NamespaceTok->getNextNonComment();
return NamespaceTok && NamespaceTok->is(tok::kw_namespace) ? NamespaceTok
: nullptr;
@@ -594,6 +599,8 @@ public:
/// Notifies the \c Role that a comma was found.
virtual void CommaFound(const FormatToken *Token) {}
+ virtual const FormatToken *lastComma() { return nullptr; }
+
protected:
const FormatStyle &Style;
};
@@ -616,6 +623,12 @@ public:
Commas.push_back(Token);
}
+ const FormatToken *lastComma() override {
+ if (Commas.empty())
+ return nullptr;
+ return Commas.back();
+ }
+
private:
/// A struct that holds information on how to format a given list with
/// a specific number of columns.
@@ -672,6 +685,7 @@ struct AdditionalKeywords {
kw_function = &IdentTable.get("function");
kw_get = &IdentTable.get("get");
kw_import = &IdentTable.get("import");
+ kw_infer = &IdentTable.get("infer");
kw_is = &IdentTable.get("is");
kw_let = &IdentTable.get("let");
kw_module = &IdentTable.get("module");
@@ -743,6 +757,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_function;
IdentifierInfo *kw_get;
IdentifierInfo *kw_import;
+ IdentifierInfo *kw_infer;
IdentifierInfo *kw_is;
IdentifierInfo *kw_let;
IdentifierInfo *kw_module;
diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index c7f720a443d3..146f5d68b559 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/lib/Format/FormatTokenLexer.cpp
@@ -37,8 +37,9 @@ FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
Lex->SetKeepWhitespaceMode(true);
for (const std::string &ForEachMacro : Style.ForEachMacros)
- ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
- llvm::sort(ForEachMacros.begin(), ForEachMacros.end());
+ Macros.insert({&IdentTable.get(ForEachMacro), TT_ForEachMacro});
+ for (const std::string &StatementMacro : Style.StatementMacros)
+ Macros.insert({&IdentTable.get(StatementMacro), TT_StatementMacro});
}
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
@@ -657,12 +658,12 @@ FormatToken *FormatTokenLexer::getNextToken() {
}
if (Style.isCpp()) {
+ auto it = Macros.find(FormatTok->Tok.getIdentifierInfo());
if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() &&
Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() ==
tok::pp_define) &&
- std::find(ForEachMacros.begin(), ForEachMacros.end(),
- FormatTok->Tok.getIdentifierInfo()) != ForEachMacros.end()) {
- FormatTok->Type = TT_ForEachMacro;
+ it != Macros.end()) {
+ FormatTok->Type = it->second;
} else if (FormatTok->is(tok::identifier)) {
if (MacroBlockBeginRegex.match(Text)) {
FormatTok->Type = TT_MacroBlockBegin;
diff --git a/lib/Format/FormatTokenLexer.h b/lib/Format/FormatTokenLexer.h
index 3b79d27480e3..0cf357c85f3b 100644
--- a/lib/Format/FormatTokenLexer.h
+++ b/lib/Format/FormatTokenLexer.h
@@ -22,6 +22,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "llvm/Support/Regex.h"
+#include "llvm/ADT/MapVector.h"
#include <stack>
@@ -99,7 +100,8 @@ private:
// Index (in 'Tokens') of the last token that starts a new line.
unsigned FirstInLineIndex;
SmallVector<FormatToken *, 16> Tokens;
- SmallVector<IdentifierInfo *, 8> ForEachMacros;
+
+ llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros;
bool FormattingDisabled;
diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp
index 995b3219a1f4..dd364866d1ce 100644
--- a/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -125,12 +125,7 @@ getNamespaceToken(const AnnotatedLine *Line,
if (StartLineIndex > 0)
NamespaceTok = AnnotatedLines[StartLineIndex - 1]->First;
}
- // Detect "(inline)? namespace" in the beginning of a line.
- if (NamespaceTok->is(tok::kw_inline))
- NamespaceTok = NamespaceTok->getNextNonComment();
- if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace))
- return nullptr;
- return NamespaceTok;
+ return NamespaceTok->getNamespaceToken();
}
NamespaceEndCommentsFixer::NamespaceEndCommentsFixer(const Environment &Env,
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 3a19215e1803..24c2f998c388 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -366,7 +366,8 @@ private:
// specifier parameter, although this is technically valid:
// [[foo(:)]]
if (AttrTok->is(tok::colon) ||
- AttrTok->startsSequence(tok::identifier, tok::identifier))
+ AttrTok->startsSequence(tok::identifier, tok::identifier) ||
+ AttrTok->startsSequence(tok::r_paren, tok::identifier))
return false;
if (AttrTok->is(tok::ellipsis))
return true;
@@ -398,9 +399,11 @@ private:
bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) ||
Contexts.back().InCpp11AttributeSpecifier;
+ bool InsideInlineASM = Line.startsWith(tok::kw_asm);
bool StartsObjCMethodExpr =
- !CppArrayTemplates && Style.isCpp() && !IsCpp11AttributeSpecifier &&
- Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
+ !InsideInlineASM && !CppArrayTemplates && Style.isCpp() &&
+ !IsCpp11AttributeSpecifier && Contexts.back().CanBeExpression &&
+ Left->isNot(TT_LambdaLSquare) &&
!CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&
(!Parent ||
Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
@@ -1120,6 +1123,7 @@ private:
(Tok.Next->Next->TokenText == "module" ||
Tok.Next->Next->TokenText == "provide" ||
Tok.Next->Next->TokenText == "require" ||
+ Tok.Next->Next->TokenText == "requireType" ||
Tok.Next->Next->TokenText == "forwardDeclare") &&
Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
}
@@ -2517,7 +2521,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Right.MatchingParen->BlockKind != BK_Block))
return !Style.Cpp11BracedListStyle;
if (Left.is(TT_BlockComment))
- return !Left.TokenText.endswith("=*/");
+ // No whitespace in x(/*foo=*/1), except for JavaScript.
+ return Style.Language == FormatStyle::LK_JavaScript ||
+ !Left.TokenText.endswith("=*/");
if (Right.is(tok::l_paren)) {
if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
(Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
@@ -2553,8 +2559,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&
Left.MatchingParen->Previous &&
- Left.MatchingParen->Previous->is(tok::period))
+ (Left.MatchingParen->Previous->is(tok::period) ||
+ Left.MatchingParen->Previous->is(tok::coloncolon)))
+ // Java call to generic function with explicit type:
// A.<B<C<...>>>DoSomething();
+ // A::<B<C<...>>>DoSomething(); // With a Java 8 method reference.
return false;
if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))
return false;
@@ -2774,6 +2783,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (!Style.SpaceBeforeAssignmentOperators &&
Right.getPrecedence() == prec::Assignment)
return false;
+ if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) &&
+ (Left.is(tok::identifier) || Left.is(tok::kw_this)))
+ return false;
if (Right.is(tok::coloncolon) && Left.is(tok::identifier))
// Generally don't remove existing spaces between an identifier and "::".
// The identifier might actually be a macro name such as ALWAYS_INLINE. If
@@ -2866,6 +2878,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
} else if (Style.Language == FormatStyle::LK_Cpp ||
Style.Language == FormatStyle::LK_ObjC ||
Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TableGen ||
Style.Language == FormatStyle::LK_TextProto) {
if (Left.isStringLiteral() && Right.isStringLiteral())
return true;
@@ -3041,6 +3054,30 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return true;
}
+ // Deal with lambda arguments in C++ - we want consistent line breaks whether
+ // they happen to be at arg0, arg1 or argN. The selection is a bit nuanced
+ // as aggressive line breaks are placed when the lambda is not the last arg.
+ if ((Style.Language == FormatStyle::LK_Cpp ||
+ Style.Language == FormatStyle::LK_ObjC) &&
+ Left.is(tok::l_paren) && Left.BlockParameterCount > 0 &&
+ !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) {
+ // Multiple lambdas in the same function call force line breaks.
+ if (Left.BlockParameterCount > 1)
+ return true;
+
+ // A lambda followed by another arg forces a line break.
+ if (!Left.Role)
+ return false;
+ auto Comma = Left.Role->lastComma();
+ if (!Comma)
+ return false;
+ auto Next = Comma->getNextNonComment();
+ if (!Next)
+ return false;
+ if (!Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret))
+ return true;
+ }
+
return false;
}
@@ -3078,14 +3115,33 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// Don't wrap between ":" and "!" of a strict prop init ("field!: type;").
if (Left.is(tok::exclaim) && Right.is(tok::colon))
return false;
- if (Right.is(Keywords.kw_is))
- return false;
+ // Look for is type annotations like:
+ // function f(): a is B { ... }
+ // Do not break before is in these cases.
+ if (Right.is(Keywords.kw_is)) {
+ const FormatToken* Next = Right.getNextNonComment();
+ // If `is` is followed by a colon, it's likely that it's a dict key, so
+ // ignore it for this check.
+ // For example this is common in Polymer:
+ // Polymer({
+ // is: 'name',
+ // ...
+ // });
+ if (!Next || !Next->is(tok::colon))
+ return false;
+ }
if (Left.is(Keywords.kw_in))
return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;
if (Right.is(Keywords.kw_in))
return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
if (Right.is(Keywords.kw_as))
return false; // must not break before as in 'x as type' casts
+ if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {
+ // extends and infer can appear as keywords in conditional types:
+ // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types
+ // do not break before them, as the expressions are subject to ASI.
+ return false;
+ }
if (Left.is(Keywords.kw_as))
return true;
if (Left.is(TT_JsNonNullAssertion))
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index a3124fcb3d65..e2f2c469d267 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -105,6 +105,13 @@ public:
return !Last->isOneOf(tok::semi, tok::comment);
}
+ /// \c true if this line starts a namespace definition.
+ bool startsWithNamespace() const {
+ return startsWith(tok::kw_namespace) ||
+ startsWith(tok::kw_inline, tok::kw_namespace) ||
+ startsWith(tok::kw_export, tok::kw_namespace);
+ }
+
FormatToken *First;
FormatToken *Last;
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 906dae40cbee..6b6a9aff461a 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -323,6 +323,10 @@ private:
kwId == clang::tok::objc_synchronized)
return 0;
}
+ // Don't merge block with left brace wrapped after case labels
+ if (TheLine->First->is(tok::l_brace) && I != AnnotatedLines.begin() &&
+ I[-1]->First->isOneOf(tok::kw_case, tok::kw_default))
+ return 0;
// Try to merge a block with left brace wrapped that wasn't yet covered
if (TheLine->Last->is(tok::l_brace)) {
return !Style.BraceWrapping.AfterFunction ||
@@ -424,6 +428,8 @@ private:
if (Limit == 0 || I + 1 == E ||
I[1]->First->isOneOf(tok::kw_case, tok::kw_default))
return 0;
+ if (I[0]->Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
+ return 0;
unsigned NumStmts = 0;
unsigned Length = 0;
bool EndsWithComment = false;
@@ -483,6 +489,12 @@ private:
if (Line.First->isOneOf(tok::kw_else, tok::kw_case) ||
(Line.First->Next && Line.First->Next->is(tok::kw_else)))
return 0;
+ // default: in switch statement
+ if (Line.First->is(tok::kw_default)) {
+ const FormatToken *Tok = Line.First->getNextNonComment();
+ if (Tok && Tok->is(tok::colon))
+ return 0;
+ }
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
tok::kw___try, tok::kw_catch, tok::kw___finally,
tok::kw_for, tok::r_brace, Keywords.kw___except)) {
@@ -529,7 +541,7 @@ private:
Tok->SpacesRequiredBefore = 0;
Tok->CanBreakBefore = true;
return 1;
- } else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
+ } else if (Limit != 0 && !Line.startsWithNamespace() &&
!startsExternCBlock(Line)) {
// We don't merge short records.
FormatToken *RecordTok = Line.First;
@@ -976,8 +988,7 @@ private:
Path.push_front(Best);
Best = Best->Previous;
}
- for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();
- I != E; ++I) {
+ for (auto I = Path.begin(), E = Path.end(); I != E; ++I) {
unsigned Penalty = 0;
formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);
@@ -986,8 +997,8 @@ private:
printLineState((*I)->Previous->State);
if ((*I)->NewLine) {
llvm::dbgs() << "Penalty for placing "
- << (*I)->Previous->State.NextToken->Tok.getName() << ": "
- << Penalty << "\n";
+ << (*I)->Previous->State.NextToken->Tok.getName()
+ << " on a new line: " << Penalty << "\n";
}
});
}
@@ -1154,7 +1165,7 @@ void UnwrappedLineFormatter::formatFirstToken(
// Remove empty lines after "{".
if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
PreviousLine->Last->is(tok::l_brace) &&
- PreviousLine->First->isNot(tok::kw_namespace) &&
+ !PreviousLine->startsWithNamespace() &&
!startsExternCBlock(*PreviousLine))
Newlines = 1;
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index e5afa1264abb..3cd3c8f9cdf6 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -350,7 +350,10 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
break;
case tok::kw_default: {
unsigned StoredPosition = Tokens->getPosition();
- FormatToken *Next = Tokens->getNextToken();
+ FormatToken *Next;
+ do {
+ Next = Tokens->getNextToken();
+ } while (Next && Next->is(tok::comment));
FormatTok = Tokens->setPosition(StoredPosition);
if (Next && Next->isNot(tok::colon)) {
// default not followed by ':' is not a case label; treat it like
@@ -477,6 +480,10 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
}
LBraceStack.pop_back();
break;
+ case tok::identifier:
+ if (!Tok->is(TT_StatementMacro))
+ break;
+ LLVM_FALLTHROUGH;
case tok::at:
case tok::semi:
case tok::kw_if:
@@ -989,13 +996,6 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_namespace:
parseNamespace();
return;
- case tok::kw_inline:
- nextToken();
- if (FormatTok->Tok.is(tok::kw_namespace)) {
- parseNamespace();
- return;
- }
- break;
case tok::kw_public:
case tok::kw_protected:
case tok::kw_private:
@@ -1063,6 +1063,16 @@ void UnwrappedLineParser::parseStructuralElement() {
parseJavaScriptEs6ImportExport();
return;
}
+ if (!Style.isCpp())
+ break;
+ // Handle C++ "(inline|export) namespace".
+ LLVM_FALLTHROUGH;
+ case tok::kw_inline:
+ nextToken();
+ if (FormatTok->Tok.is(tok::kw_namespace)) {
+ parseNamespace();
+ return;
+ }
break;
case tok::identifier:
if (FormatTok->is(TT_ForEachMacro)) {
@@ -1102,6 +1112,10 @@ void UnwrappedLineParser::parseStructuralElement() {
return;
}
}
+ if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
+ parseStatementMacro();
+ return;
+ }
// In all other cases, parse the declaration.
break;
default:
@@ -1116,6 +1130,10 @@ void UnwrappedLineParser::parseStructuralElement() {
nextToken();
parseBracedList();
break;
+ } else if (Style.Language == FormatStyle::LK_Java &&
+ FormatTok->is(Keywords.kw_interface)) {
+ nextToken();
+ break;
}
switch (FormatTok->Tok.getObjCKeywordID()) {
case tok::objc_public:
@@ -1260,6 +1278,8 @@ void UnwrappedLineParser::parseStructuralElement() {
break;
case tok::kw_try:
// We arrive here when parsing function-try blocks.
+ if (Style.BraceWrapping.AfterFunction)
+ addUnwrappedLine();
parseTryCatch();
return;
case tok::identifier: {
@@ -1301,6 +1321,11 @@ void UnwrappedLineParser::parseStructuralElement() {
return;
}
+ if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
+ parseStatementMacro();
+ return;
+ }
+
// See if the following token should start a new unwrapped line.
StringRef Text = FormatTok->TokenText;
nextToken();
@@ -2143,6 +2168,8 @@ void UnwrappedLineParser::parseObjCMethod() {
addUnwrappedLine();
return;
} else if (FormatTok->Tok.is(tok::l_brace)) {
+ if (Style.BraceWrapping.AfterFunction)
+ addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false);
addUnwrappedLine();
return;
@@ -2320,6 +2347,16 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
}
}
+void UnwrappedLineParser::parseStatementMacro()
+{
+ nextToken();
+ if (FormatTok->is(tok::l_paren))
+ parseParens();
+ if (FormatTok->is(tok::semi))
+ nextToken();
+ addUnwrappedLine();
+}
+
LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
StringRef Prefix = "") {
llvm::dbgs() << Prefix << "Line(" << Line.Level
diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h
index 87254832c635..55d60dff9152 100644
--- a/lib/Format/UnwrappedLineParser.h
+++ b/lib/Format/UnwrappedLineParser.h
@@ -126,6 +126,7 @@ private:
void parseObjCInterfaceOrImplementation();
bool parseObjCProtocol();
void parseJavaScriptEs6ImportExport();
+ void parseStatementMacro();
bool tryToParseLambda();
bool tryToParseLambdaIntroducer();
void tryToParseJSFunction();
diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index 7070ce03c864..032b1333322d 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/lib/Format/WhitespaceManager.cpp
@@ -90,7 +90,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
if (Changes.empty())
return Replaces;
- llvm::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
+ llvm::sort(Changes, Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
alignConsecutiveDeclarations();
alignConsecutiveAssignments();
@@ -255,8 +255,14 @@ AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches,
Changes[ScopeStack.back()].indentAndNestingLevel())
ScopeStack.pop_back();
+ // Compare current token to previous non-comment token to ensure whether
+ // it is in a deeper scope or not.
+ unsigned PreviousNonComment = i - 1;
+ while (PreviousNonComment > Start &&
+ Changes[PreviousNonComment].Tok->is(tok::comment))
+ PreviousNonComment--;
if (i != Start && Changes[i].indentAndNestingLevel() >
- Changes[i - 1].indentAndNestingLevel())
+ Changes[PreviousNonComment].indentAndNestingLevel())
ScopeStack.push_back(i);
bool InsideNestedScope = ScopeStack.size() != 0;
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 2a8bfef68eb9..28834a2de8a2 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -193,365 +193,3 @@ void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
return llvm::make_unique<ASTViewer>();
}
-
-//===----------------------------------------------------------------------===//
-/// DeclContextPrinter - Decl and DeclContext Visualization
-
-namespace {
-
-class DeclContextPrinter : public ASTConsumer {
- raw_ostream& Out;
-public:
- DeclContextPrinter() : Out(llvm::errs()) {}
-
- void HandleTranslationUnit(ASTContext &C) override {
- PrintDeclContext(C.getTranslationUnitDecl(), 4);
- }
-
- void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
-};
-} // end anonymous namespace
-
-void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
- unsigned Indentation) {
- // Print DeclContext name.
- switch (DC->getDeclKind()) {
- case Decl::TranslationUnit:
- Out << "[translation unit] " << DC;
- break;
- case Decl::Namespace: {
- Out << "[namespace] ";
- const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
- Out << *ND;
- break;
- }
- case Decl::Enum: {
- const EnumDecl* ED = cast<EnumDecl>(DC);
- if (ED->isCompleteDefinition())
- Out << "[enum] ";
- else
- Out << "<enum> ";
- Out << *ED;
- break;
- }
- case Decl::Record: {
- const RecordDecl* RD = cast<RecordDecl>(DC);
- if (RD->isCompleteDefinition())
- Out << "[struct] ";
- else
- Out << "<struct> ";
- Out << *RD;
- break;
- }
- case Decl::CXXRecord: {
- const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
- if (RD->isCompleteDefinition())
- Out << "[class] ";
- else
- Out << "<class> ";
- Out << *RD << ' ' << DC;
- break;
- }
- case Decl::ObjCMethod:
- Out << "[objc method]";
- break;
- case Decl::ObjCInterface:
- Out << "[objc interface]";
- break;
- case Decl::ObjCCategory:
- Out << "[objc category]";
- break;
- case Decl::ObjCProtocol:
- Out << "[objc protocol]";
- break;
- case Decl::ObjCImplementation:
- Out << "[objc implementation]";
- break;
- case Decl::ObjCCategoryImpl:
- Out << "[objc categoryimpl]";
- break;
- case Decl::LinkageSpec:
- Out << "[linkage spec]";
- break;
- case Decl::Block:
- Out << "[block]";
- break;
- case Decl::Function: {
- const FunctionDecl* FD = cast<FunctionDecl>(DC);
- if (FD->doesThisDeclarationHaveABody())
- Out << "[function] ";
- else
- Out << "<function> ";
- Out << *FD;
- // Print the parameters.
- Out << "(";
- bool PrintComma = false;
- for (auto I : FD->parameters()) {
- if (PrintComma)
- Out << ", ";
- else
- PrintComma = true;
- Out << *I;
- }
- Out << ")";
- break;
- }
- case Decl::CXXMethod: {
- const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
- if (D->isOutOfLine())
- Out << "[c++ method] ";
- else if (D->isImplicit())
- Out << "(c++ method) ";
- else
- Out << "<c++ method> ";
- Out << *D;
- // Print the parameters.
- Out << "(";
- bool PrintComma = false;
- for (ParmVarDecl *Parameter : D->parameters()) {
- if (PrintComma)
- Out << ", ";
- else
- PrintComma = true;
- Out << *Parameter;
- }
- Out << ")";
-
- // Check the semantic DeclContext.
- const DeclContext* SemaDC = D->getDeclContext();
- const DeclContext* LexicalDC = D->getLexicalDeclContext();
- if (SemaDC != LexicalDC)
- Out << " [[" << SemaDC << "]]";
-
- break;
- }
- case Decl::CXXConstructor: {
- const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
- if (D->isOutOfLine())
- Out << "[c++ ctor] ";
- else if (D->isImplicit())
- Out << "(c++ ctor) ";
- else
- Out << "<c++ ctor> ";
- Out << *D;
- // Print the parameters.
- Out << "(";
- bool PrintComma = false;
- for (ParmVarDecl *Parameter : D->parameters()) {
- if (PrintComma)
- Out << ", ";
- else
- PrintComma = true;
- Out << *Parameter;
- }
- Out << ")";
-
- // Check the semantic DC.
- const DeclContext* SemaDC = D->getDeclContext();
- const DeclContext* LexicalDC = D->getLexicalDeclContext();
- if (SemaDC != LexicalDC)
- Out << " [[" << SemaDC << "]]";
- break;
- }
- case Decl::CXXDestructor: {
- const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
- if (D->isOutOfLine())
- Out << "[c++ dtor] ";
- else if (D->isImplicit())
- Out << "(c++ dtor) ";
- else
- Out << "<c++ dtor> ";
- Out << *D;
- // Check the semantic DC.
- const DeclContext* SemaDC = D->getDeclContext();
- const DeclContext* LexicalDC = D->getLexicalDeclContext();
- if (SemaDC != LexicalDC)
- Out << " [[" << SemaDC << "]]";
- break;
- }
- case Decl::CXXConversion: {
- const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
- if (D->isOutOfLine())
- Out << "[c++ conversion] ";
- else if (D->isImplicit())
- Out << "(c++ conversion) ";
- else
- Out << "<c++ conversion> ";
- Out << *D;
- // Check the semantic DC.
- const DeclContext* SemaDC = D->getDeclContext();
- const DeclContext* LexicalDC = D->getLexicalDeclContext();
- if (SemaDC != LexicalDC)
- Out << " [[" << SemaDC << "]]";
- break;
- }
-
- case Decl::ClassTemplateSpecialization: {
- const auto *CTSD = cast<ClassTemplateSpecializationDecl>(DC);
- if (CTSD->isCompleteDefinition())
- Out << "[class template specialization] ";
- else
- Out << "<class template specialization> ";
- Out << *CTSD;
- break;
- }
-
- case Decl::ClassTemplatePartialSpecialization: {
- const auto *CTPSD = cast<ClassTemplatePartialSpecializationDecl>(DC);
- if (CTPSD->isCompleteDefinition())
- Out << "[class template partial specialization] ";
- else
- Out << "<class template partial specialization> ";
- Out << *CTPSD;
- break;
- }
-
- default:
- llvm_unreachable("a decl that inherits DeclContext isn't handled");
- }
-
- Out << "\n";
-
- // Print decls in the DeclContext.
- for (auto *I : DC->decls()) {
- for (unsigned i = 0; i < Indentation; ++i)
- Out << " ";
-
- Decl::Kind DK = I->getKind();
- switch (DK) {
- case Decl::Namespace:
- case Decl::Enum:
- case Decl::Record:
- case Decl::CXXRecord:
- case Decl::ObjCMethod:
- case Decl::ObjCInterface:
- case Decl::ObjCCategory:
- case Decl::ObjCProtocol:
- case Decl::ObjCImplementation:
- case Decl::ObjCCategoryImpl:
- case Decl::LinkageSpec:
- case Decl::Block:
- case Decl::Function:
- case Decl::CXXMethod:
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- case Decl::CXXConversion:
- case Decl::ClassTemplateSpecialization:
- case Decl::ClassTemplatePartialSpecialization: {
- DeclContext* DC = cast<DeclContext>(I);
- PrintDeclContext(DC, Indentation+2);
- break;
- }
- case Decl::IndirectField: {
- IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I);
- Out << "<IndirectField> " << *IFD << '\n';
- break;
- }
- case Decl::Label: {
- LabelDecl *LD = cast<LabelDecl>(I);
- Out << "<Label> " << *LD << '\n';
- break;
- }
- case Decl::Field: {
- FieldDecl *FD = cast<FieldDecl>(I);
- Out << "<field> " << *FD << '\n';
- break;
- }
- case Decl::Typedef:
- case Decl::TypeAlias: {
- TypedefNameDecl* TD = cast<TypedefNameDecl>(I);
- Out << "<typedef> " << *TD << '\n';
- break;
- }
- case Decl::EnumConstant: {
- EnumConstantDecl* ECD = cast<EnumConstantDecl>(I);
- Out << "<enum constant> " << *ECD << '\n';
- break;
- }
- case Decl::Var: {
- VarDecl* VD = cast<VarDecl>(I);
- Out << "<var> " << *VD << '\n';
- break;
- }
- case Decl::ImplicitParam: {
- ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I);
- Out << "<implicit parameter> " << *IPD << '\n';
- break;
- }
- case Decl::ParmVar: {
- ParmVarDecl* PVD = cast<ParmVarDecl>(I);
- Out << "<parameter> " << *PVD << '\n';
- break;
- }
- case Decl::ObjCProperty: {
- ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I);
- Out << "<objc property> " << *OPD << '\n';
- break;
- }
- case Decl::FunctionTemplate: {
- FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I);
- Out << "<function template> " << *FTD << '\n';
- break;
- }
- case Decl::FileScopeAsm: {
- Out << "<file-scope asm>\n";
- break;
- }
- case Decl::UsingDirective: {
- Out << "<using directive>\n";
- break;
- }
- case Decl::NamespaceAlias: {
- NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I);
- Out << "<namespace alias> " << *NAD << '\n';
- break;
- }
- case Decl::ClassTemplate: {
- ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I);
- Out << "<class template> " << *CTD << '\n';
- break;
- }
- case Decl::OMPThreadPrivate: {
- Out << "<omp threadprivate> " << '"' << I << "\"\n";
- break;
- }
- case Decl::Friend: {
- Out << "<friend>";
- if (const NamedDecl *ND = cast<FriendDecl>(I)->getFriendDecl())
- Out << ' ' << *ND;
- Out << "\n";
- break;
- }
- case Decl::Using: {
- Out << "<using> " << *cast<UsingDecl>(I) << "\n";
- break;
- }
- case Decl::UsingShadow: {
- Out << "<using shadow> " << *cast<UsingShadowDecl>(I) << "\n";
- break;
- }
- case Decl::Empty: {
- Out << "<empty>\n";
- break;
- }
- case Decl::AccessSpec: {
- Out << "<access specifier>\n";
- break;
- }
- case Decl::VarTemplate: {
- Out << "<var template> " << *cast<VarTemplateDecl>(I) << "\n";
- break;
- }
- case Decl::StaticAssert: {
- Out << "<static assert>\n";
- break;
- }
- default:
- Out << "DeclKind: " << DK << '"' << I << "\"\n";
- llvm_unreachable("decl unhandled");
- }
- }
-}
-std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() {
- return llvm::make_unique<DeclContextPrinter>();
-}
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index 2434113ab0db..4f622da118c5 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -10,6 +10,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
@@ -38,6 +39,8 @@ void ASTMergeAction::ExecuteAction() {
&CI.getASTContext());
IntrusiveRefCntPtr<DiagnosticIDs>
DiagIDs(CI.getDiagnostics().getDiagnosticIDs());
+ ASTImporterLookupTable LookupTable(
+ *CI.getASTContext().getTranslationUnitDecl());
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
IntrusiveRefCntPtr<DiagnosticsEngine>
Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(),
@@ -51,11 +54,9 @@ void ASTMergeAction::ExecuteAction() {
if (!Unit)
continue;
- ASTImporter Importer(CI.getASTContext(),
- CI.getFileManager(),
- Unit->getASTContext(),
- Unit->getFileManager(),
- /*MinimalImport=*/false);
+ ASTImporter Importer(CI.getASTContext(), CI.getFileManager(),
+ Unit->getASTContext(), Unit->getFileManager(),
+ /*MinimalImport=*/false, &LookupTable);
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
for (auto *D : TU->decls()) {
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index e4c313fed30f..c7b2551cb8d7 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -37,7 +37,6 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendAction.h"
@@ -45,7 +44,6 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
@@ -64,6 +62,7 @@
#include "clang/Serialization/ASTWriter.h"
#include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/Module.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -88,6 +87,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Timer.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <atomic>
@@ -155,9 +155,8 @@ static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
/// and file-to-buffer remappings inside \p Invocation.
static std::unique_ptr<llvm::MemoryBuffer>
getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
- vfs::FileSystem *VFS,
- StringRef FilePath,
- bool isVolatile) {
+ llvm::vfs::FileSystem *VFS,
+ StringRef FilePath, bool isVolatile) {
const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();
// Try to determine if the main file has been remapped, either from the
@@ -283,7 +282,7 @@ void ASTUnit::enableSourceFileDiagnostics() {
/// Determine the set of code-completion contexts in which this
/// declaration should be shown.
-static unsigned getDeclShowContexts(const NamedDecl *ND,
+static uint64_t getDeclShowContexts(const NamedDecl *ND,
const LangOptions &LangOpts,
bool &IsNestedNameSpecifier) {
IsNestedNameSpecifier = false;
@@ -437,14 +436,15 @@ void ASTUnit::CacheCodeCompletionResults() {
| (1LL << CodeCompletionContext::CCC_UnionTag)
| (1LL << CodeCompletionContext::CCC_ClassOrStructTag)
| (1LL << CodeCompletionContext::CCC_Type)
- | (1LL << CodeCompletionContext::CCC_PotentiallyQualifiedName)
+ | (1LL << CodeCompletionContext::CCC_Symbol)
+ | (1LL << CodeCompletionContext::CCC_SymbolOrNewName)
| (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
if (isa<NamespaceDecl>(R.Declaration) ||
isa<NamespaceAliasDecl>(R.Declaration))
NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
- if (unsigned RemainingContexts
+ if (uint64_t RemainingContexts
= NNSContexts & ~CachedResult.ShowInContexts) {
// If there any contexts where this completion can be a
// nested-name-specifier but isn't already an option, create a
@@ -752,7 +752,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->Diagnostics = Diags;
- IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
+ llvm::vfs::getRealFileSystem();
AST->FileMgr = new FileManager(FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
@@ -1074,7 +1075,7 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
/// contain any translation-unit information, false otherwise.
bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
if (!Invocation)
return true;
@@ -1082,7 +1083,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
if (OverrideMainBuffer) {
assert(Preamble &&
"No preamble was built, but OverrideMainBuffer is not null");
- IntrusiveRefCntPtr<vfs::FileSystem> OldVFS = VFS;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> OldVFS = VFS;
Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get());
if (OldVFS != VFS && FileMgr) {
assert(OldVFS == FileMgr->getVirtualFileSystem() &&
@@ -1279,7 +1280,7 @@ std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
CompilerInvocation &PreambleInvocationIn,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild,
unsigned MaxLines) {
auto MainFilePath =
PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();
@@ -1363,7 +1364,6 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
} else {
switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) {
case BuildPreambleError::CouldntCreateTempFile:
- case BuildPreambleError::PreambleIsEmpty:
// Try again next time.
PreambleRebuildCounter = 1;
return nullptr;
@@ -1469,7 +1469,7 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
bool CaptureDiagnostics, bool UserFilesAreVolatile) {
std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
- IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(*CI, *Diags);
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
@@ -1631,7 +1631,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
bool ASTUnit::LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
unsigned PrecompilePreambleAfterNParses,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
if (!Invocation)
return true;
@@ -1710,7 +1710,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,
bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
@@ -1755,7 +1755,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
if (!VFS)
- VFS = vfs::getRealFileSystem();
+ VFS = llvm::vfs::getRealFileSystem();
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->PCMCache = new MemoryBufferCache;
@@ -1795,7 +1795,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> RemappedFiles,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
if (!Invocation)
return true;
@@ -1912,8 +1912,10 @@ namespace {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
- unsigned NumCandidates) override {
- Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc) override {
+ Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
+ OpenParLoc);
}
CodeCompletionAllocator &getAllocator() override {
@@ -1950,8 +1952,8 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
case CodeCompletionContext::CCC_ObjCPropertyAccess:
case CodeCompletionContext::CCC_Namespace:
case CodeCompletionContext::CCC_Type:
- case CodeCompletionContext::CCC_Name:
- case CodeCompletionContext::CCC_PotentiallyQualifiedName:
+ case CodeCompletionContext::CCC_Symbol:
+ case CodeCompletionContext::CCC_SymbolOrNewName:
case CodeCompletionContext::CCC_ParenthesizedExpression:
case CodeCompletionContext::CCC_ObjCInterfaceName:
break;
@@ -1975,6 +1977,8 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
case CodeCompletionContext::CCC_ObjCInstanceMessage:
case CodeCompletionContext::CCC_ObjCClassMessage:
case CodeCompletionContext::CCC_ObjCCategoryName:
+ case CodeCompletionContext::CCC_IncludedFile:
+ case CodeCompletionContext::CCC_NewName:
// We're looking for nothing, or we're looking for names that cannot
// be hidden.
return;
@@ -2644,9 +2648,9 @@ InputKind ASTUnit::getInputKind() const {
else if (LangOpts.RenderScript)
Lang = InputKind::RenderScript;
else if (LangOpts.CPlusPlus)
- Lang = LangOpts.ObjC1 ? InputKind::ObjCXX : InputKind::CXX;
+ Lang = LangOpts.ObjC ? InputKind::ObjCXX : InputKind::CXX;
else
- Lang = LangOpts.ObjC1 ? InputKind::ObjC : InputKind::C;
+ Lang = LangOpts.ObjC ? InputKind::ObjC : InputKind::C;
InputKind::Format Fmt = InputKind::Source;
if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap)
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 6161b46a9dc5..3bd159537b6a 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -16,10 +16,8 @@ add_clang_library(clangFrontend
ASTConsumers.cpp
ASTMerge.cpp
ASTUnit.cpp
- CacheTokens.cpp
ChainedDiagnosticConsumer.cpp
ChainedIncludesSource.cpp
- CodeGenOptions.cpp
CompilerInstance.cpp
CompilerInvocation.cpp
CreateInvocationFromCommandLine.cpp
@@ -38,7 +36,6 @@ add_clang_library(clangFrontend
LogDiagnosticPrinter.cpp
ModuleDependencyCollector.cpp
MultiplexConsumer.cpp
- PCHContainerOperations.cpp
PrecompiledPreamble.cpp
PrintPreprocessedOutput.cpp
SerializedDiagnosticPrinter.cpp
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
deleted file mode 100644
index c4504a14456d..000000000000
--- a/lib/Frontend/CacheTokens.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-//===--- CacheTokens.cpp - Caching of lexer tokens for PTH support --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This provides a possible implementation of PTH support for Clang that is
-// based on caching lexed tokens and identifiers.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemStatCache.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Frontend/Utils.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Lex/PTHManager.h"
-#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/DJB.h"
-#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/OnDiskHashTable.h"
-#include "llvm/Support/Path.h"
-
-// FIXME: put this somewhere else?
-#ifndef S_ISDIR
-#define S_ISDIR(x) (((x)&_S_IFDIR)!=0)
-#endif
-
-using namespace clang;
-
-//===----------------------------------------------------------------------===//
-// PTH-specific stuff.
-//===----------------------------------------------------------------------===//
-
-typedef uint32_t Offset;
-
-namespace {
-class PTHEntry {
- Offset TokenData, PPCondData;
-
-public:
- PTHEntry() {}
-
- PTHEntry(Offset td, Offset ppcd)
- : TokenData(td), PPCondData(ppcd) {}
-
- Offset getTokenOffset() const { return TokenData; }
- Offset getPPCondTableOffset() const { return PPCondData; }
-};
-
-
-class PTHEntryKeyVariant {
- union {
- const FileEntry *FE;
- // FIXME: Use "StringRef Path;" when MSVC 2013 is dropped.
- const char *PathPtr;
- };
- size_t PathSize;
- enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind;
- FileData *Data;
-
-public:
- PTHEntryKeyVariant(const FileEntry *fe) : FE(fe), Kind(IsFE), Data(nullptr) {}
-
- PTHEntryKeyVariant(FileData *Data, StringRef Path)
- : PathPtr(Path.data()), PathSize(Path.size()), Kind(IsDE),
- Data(new FileData(*Data)) {}
-
- explicit PTHEntryKeyVariant(StringRef Path)
- : PathPtr(Path.data()), PathSize(Path.size()), Kind(IsNoExist),
- Data(nullptr) {}
-
- bool isFile() const { return Kind == IsFE; }
-
- StringRef getString() const {
- return Kind == IsFE ? FE->getName() : StringRef(PathPtr, PathSize);
- }
-
- unsigned getKind() const { return (unsigned) Kind; }
-
- void EmitData(raw_ostream& Out) {
- using namespace llvm::support;
- endian::Writer LE(Out, little);
- switch (Kind) {
- case IsFE: {
- // Emit stat information.
- llvm::sys::fs::UniqueID UID = FE->getUniqueID();
- LE.write<uint64_t>(UID.getFile());
- LE.write<uint64_t>(UID.getDevice());
- LE.write<uint64_t>(FE->getModificationTime());
- LE.write<uint64_t>(FE->getSize());
- } break;
- case IsDE:
- // Emit stat information.
- LE.write<uint64_t>(Data->UniqueID.getFile());
- LE.write<uint64_t>(Data->UniqueID.getDevice());
- LE.write<uint64_t>(Data->ModTime);
- LE.write<uint64_t>(Data->Size);
- delete Data;
- break;
- default:
- break;
- }
- }
-
- unsigned getRepresentationLength() const {
- return Kind == IsNoExist ? 0 : 4 * 8;
- }
-};
-
-class FileEntryPTHEntryInfo {
-public:
- typedef PTHEntryKeyVariant key_type;
- typedef key_type key_type_ref;
-
- typedef PTHEntry data_type;
- typedef const PTHEntry& data_type_ref;
-
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
-
- static hash_value_type ComputeHash(PTHEntryKeyVariant V) {
- return llvm::djbHash(V.getString());
- }
-
- static std::pair<unsigned,unsigned>
- EmitKeyDataLength(raw_ostream& Out, PTHEntryKeyVariant V,
- const PTHEntry& E) {
- using namespace llvm::support;
- endian::Writer LE(Out, little);
-
- unsigned n = V.getString().size() + 1 + 1;
- LE.write<uint16_t>(n);
-
- unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0);
- LE.write<uint8_t>(m);
-
- return std::make_pair(n, m);
- }
-
- static void EmitKey(raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){
- using namespace llvm::support;
- // Emit the entry kind.
- Out << char(V.getKind());
- // Emit the string.
- Out.write(V.getString().data(), n - 1);
- }
-
- static void EmitData(raw_ostream& Out, PTHEntryKeyVariant V,
- const PTHEntry& E, unsigned) {
- using namespace llvm::support;
- endian::Writer LE(Out, little);
-
- // For file entries emit the offsets into the PTH file for token data
- // and the preprocessor blocks table.
- if (V.isFile()) {
- LE.write<uint32_t>(E.getTokenOffset());
- LE.write<uint32_t>(E.getPPCondTableOffset());
- }
-
- // Emit any other data associated with the key (i.e., stat information).
- V.EmitData(Out);
- }
-};
-
-class OffsetOpt {
- bool valid;
- Offset off;
-public:
- OffsetOpt() : valid(false) {}
- bool hasOffset() const { return valid; }
- Offset getOffset() const { assert(valid); return off; }
- void setOffset(Offset o) { off = o; valid = true; }
-};
-} // end anonymous namespace
-
-typedef llvm::OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap;
-
-namespace {
-class PTHWriter {
- typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;
- typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
-
- raw_pwrite_stream &Out;
- Preprocessor& PP;
- IDMap IM;
- std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries;
- PTHMap PM;
- CachedStrsTy CachedStrs;
- uint32_t idcount;
- Offset CurStrOffset;
-
- //// Get the persistent id for the given IdentifierInfo*.
- uint32_t ResolveID(const IdentifierInfo* II);
-
- /// Emit a token to the PTH file.
- void EmitToken(const Token& T);
-
- void Emit8(uint32_t V) {
- Out << char(V);
- }
-
- void Emit16(uint32_t V) {
- using namespace llvm::support;
- endian::write<uint16_t>(Out, V, little);
- }
-
- void Emit32(uint32_t V) {
- using namespace llvm::support;
- endian::write<uint32_t>(Out, V, little);
- }
-
- void EmitBuf(const char *Ptr, unsigned NumBytes) {
- Out.write(Ptr, NumBytes);
- }
-
- void EmitString(StringRef V) {
- using namespace llvm::support;
- endian::write<uint16_t>(Out, V.size(), little);
- EmitBuf(V.data(), V.size());
- }
-
- /// EmitIdentifierTable - Emits two tables to the PTH file. The first is
- /// a hashtable mapping from identifier strings to persistent IDs.
- /// The second is a straight table mapping from persistent IDs to string data
- /// (the keys of the first table).
- std::pair<Offset, Offset> EmitIdentifierTable();
-
- /// EmitFileTable - Emit a table mapping from file name strings to PTH
- /// token data.
- Offset EmitFileTable() { return PM.Emit(Out); }
-
- PTHEntry LexTokens(Lexer& L);
- Offset EmitCachedSpellings();
-
-public:
- PTHWriter(raw_pwrite_stream &out, Preprocessor &pp)
- : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
-
- PTHMap &getPM() { return PM; }
- void GeneratePTH(StringRef MainFile);
-};
-} // end anonymous namespace
-
-uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) {
- // Null IdentifierInfo's map to the persistent ID 0.
- if (!II)
- return 0;
-
- IDMap::iterator I = IM.find(II);
- if (I != IM.end())
- return I->second; // We've already added 1.
-
- IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL.
- return idcount;
-}
-
-void PTHWriter::EmitToken(const Token& T) {
- // Emit the token kind, flags, and length.
- Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)|
- (((uint32_t) T.getLength()) << 16));
-
- if (!T.isLiteral()) {
- Emit32(ResolveID(T.getIdentifierInfo()));
- } else {
- // We cache *un-cleaned* spellings. This gives us 100% fidelity with the
- // source code.
- StringRef s(T.getLiteralData(), T.getLength());
-
- // Get the string entry.
- auto &E = *CachedStrs.insert(std::make_pair(s, OffsetOpt())).first;
-
- // If this is a new string entry, bump the PTH offset.
- if (!E.second.hasOffset()) {
- E.second.setOffset(CurStrOffset);
- StrEntries.push_back(&E);
- CurStrOffset += s.size() + 1;
- }
-
- // Emit the relative offset into the PTH file for the spelling string.
- Emit32(E.second.getOffset());
- }
-
- // Emit the offset into the original source file of this token so that we
- // can reconstruct its SourceLocation.
- Emit32(PP.getSourceManager().getFileOffset(T.getLocation()));
-}
-
-PTHEntry PTHWriter::LexTokens(Lexer& L) {
- // Pad 0's so that we emit tokens to a 4-byte alignment.
- // This speed up reading them back in.
- using namespace llvm::support;
- endian::Writer LE(Out, little);
- uint32_t TokenOff = Out.tell();
- for (uint64_t N = llvm::OffsetToAlignment(TokenOff, 4); N; --N, ++TokenOff)
- LE.write<uint8_t>(0);
-
- // Keep track of matching '#if' ... '#endif'.
- typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
- PPCondTable PPCond;
- std::vector<unsigned> PPStartCond;
- bool ParsingPreprocessorDirective = false;
- Token Tok;
-
- do {
- L.LexFromRawLexer(Tok);
- NextToken:
-
- if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
- ParsingPreprocessorDirective) {
- // Insert an eod token into the token cache. It has the same
- // position as the next token that is not on the same line as the
- // preprocessor directive. Observe that we continue processing
- // 'Tok' when we exit this branch.
- Token Tmp = Tok;
- Tmp.setKind(tok::eod);
- Tmp.clearFlag(Token::StartOfLine);
- Tmp.setIdentifierInfo(nullptr);
- EmitToken(Tmp);
- ParsingPreprocessorDirective = false;
- }
-
- if (Tok.is(tok::raw_identifier)) {
- PP.LookUpIdentifierInfo(Tok);
- EmitToken(Tok);
- continue;
- }
-
- if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
- // Special processing for #include. Store the '#' token and lex
- // the next token.
- assert(!ParsingPreprocessorDirective);
- Offset HashOff = (Offset) Out.tell();
-
- // Get the next token.
- Token NextTok;
- L.LexFromRawLexer(NextTok);
-
- // If we see the start of line, then we had a null directive "#". In
- // this case, discard both tokens.
- if (NextTok.isAtStartOfLine())
- goto NextToken;
-
- // The token is the start of a directive. Emit it.
- EmitToken(Tok);
- Tok = NextTok;
-
- // Did we see 'include'/'import'/'include_next'?
- if (Tok.isNot(tok::raw_identifier)) {
- EmitToken(Tok);
- continue;
- }
-
- IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
- tok::PPKeywordKind K = II->getPPKeywordID();
-
- ParsingPreprocessorDirective = true;
-
- switch (K) {
- case tok::pp_not_keyword:
- // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass
- // them through.
- default:
- break;
-
- case tok::pp_include:
- case tok::pp_import:
- case tok::pp_include_next: {
- // Save the 'include' token.
- EmitToken(Tok);
- // Lex the next token as an include string.
- L.setParsingPreprocessorDirective(true);
- L.LexIncludeFilename(Tok);
- L.setParsingPreprocessorDirective(false);
- assert(!Tok.isAtStartOfLine());
- if (Tok.is(tok::raw_identifier))
- PP.LookUpIdentifierInfo(Tok);
-
- break;
- }
- case tok::pp_if:
- case tok::pp_ifdef:
- case tok::pp_ifndef: {
- // Add an entry for '#if' and friends. We initially set the target
- // index to 0. This will get backpatched when we hit #endif.
- PPStartCond.push_back(PPCond.size());
- PPCond.push_back(std::make_pair(HashOff, 0U));
- break;
- }
- case tok::pp_endif: {
- // Add an entry for '#endif'. We set the target table index to itself.
- // This will later be set to zero when emitting to the PTH file. We
- // use 0 for uninitialized indices because that is easier to debug.
- unsigned index = PPCond.size();
- // Backpatch the opening '#if' entry.
- assert(!PPStartCond.empty());
- assert(PPCond.size() > PPStartCond.back());
- assert(PPCond[PPStartCond.back()].second == 0);
- PPCond[PPStartCond.back()].second = index;
- PPStartCond.pop_back();
- // Add the new entry to PPCond.
- PPCond.push_back(std::make_pair(HashOff, index));
- EmitToken(Tok);
-
- // Some files have gibberish on the same line as '#endif'.
- // Discard these tokens.
- do
- L.LexFromRawLexer(Tok);
- while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine());
- // We have the next token in hand.
- // Don't immediately lex the next one.
- goto NextToken;
- }
- case tok::pp_elif:
- case tok::pp_else: {
- // Add an entry for #elif or #else.
- // This serves as both a closing and opening of a conditional block.
- // This means that its entry will get backpatched later.
- unsigned index = PPCond.size();
- // Backpatch the previous '#if' entry.
- assert(!PPStartCond.empty());
- assert(PPCond.size() > PPStartCond.back());
- assert(PPCond[PPStartCond.back()].second == 0);
- PPCond[PPStartCond.back()].second = index;
- PPStartCond.pop_back();
- // Now add '#elif' as a new block opening.
- PPCond.push_back(std::make_pair(HashOff, 0U));
- PPStartCond.push_back(index);
- break;
- }
- }
- }
-
- EmitToken(Tok);
- }
- while (Tok.isNot(tok::eof));
-
- assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");
-
- // Next write out PPCond.
- Offset PPCondOff = (Offset) Out.tell();
-
- // Write out the size of PPCond so that clients can identifer empty tables.
- Emit32(PPCond.size());
-
- for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
- Emit32(PPCond[i].first - TokenOff);
- uint32_t x = PPCond[i].second;
- assert(x != 0 && "PPCond entry not backpatched.");
- // Emit zero for #endifs. This allows us to do checking when
- // we read the PTH file back in.
- Emit32(x == i ? 0 : x);
- }
-
- return PTHEntry(TokenOff, PPCondOff);
-}
-
-Offset PTHWriter::EmitCachedSpellings() {
- // Write each cached strings to the PTH file.
- Offset SpellingsOff = Out.tell();
-
- for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator
- I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I)
- EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/);
-
- return SpellingsOff;
-}
-
-static uint32_t swap32le(uint32_t X) {
- return llvm::support::endian::byte_swap<uint32_t, llvm::support::little>(X);
-}
-
-static void pwrite32le(raw_pwrite_stream &OS, uint32_t Val, uint64_t &Off) {
- uint32_t LEVal = swap32le(Val);
- OS.pwrite(reinterpret_cast<const char *>(&LEVal), 4, Off);
- Off += 4;
-}
-
-void PTHWriter::GeneratePTH(StringRef MainFile) {
- // Generate the prologue.
- Out << "cfe-pth" << '\0';
- Emit32(PTHManager::Version);
-
- // Leave 4 words for the prologue.
- Offset PrologueOffset = Out.tell();
- for (unsigned i = 0; i < 4; ++i)
- Emit32(0);
-
- // Write the name of the MainFile.
- if (!MainFile.empty()) {
- EmitString(MainFile);
- } else {
- // String with 0 bytes.
- Emit16(0);
- }
- Emit8(0);
-
- // Iterate over all the files in SourceManager. Create a lexer
- // for each file and cache the tokens.
- SourceManager &SM = PP.getSourceManager();
- const LangOptions &LOpts = PP.getLangOpts();
-
- for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(),
- E = SM.fileinfo_end(); I != E; ++I) {
- const SrcMgr::ContentCache &C = *I->second;
- const FileEntry *FE = C.OrigEntry;
-
- // FIXME: Handle files with non-absolute paths.
- if (llvm::sys::path::is_relative(FE->getName()))
- continue;
-
- const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics(), SM);
- if (!B) continue;
-
- FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
- const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
- Lexer L(FID, FromFile, SM, LOpts);
- PM.insert(FE, LexTokens(L));
- }
-
- // Write out the identifier table.
- const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable();
-
- // Write out the cached strings table.
- Offset SpellingOff = EmitCachedSpellings();
-
- // Write out the file table.
- Offset FileTableOff = EmitFileTable();
-
- // Finally, write the prologue.
- uint64_t Off = PrologueOffset;
- pwrite32le(Out, IdTableOff.first, Off);
- pwrite32le(Out, IdTableOff.second, Off);
- pwrite32le(Out, FileTableOff, Off);
- pwrite32le(Out, SpellingOff, Off);
-}
-
-namespace {
-/// StatListener - A simple "interpose" object used to monitor stat calls
-/// invoked by FileManager while processing the original sources used
-/// as input to PTH generation. StatListener populates the PTHWriter's
-/// file map with stat information for directories as well as negative stats.
-/// Stat information for files are populated elsewhere.
-class StatListener : public FileSystemStatCache {
- PTHMap &PM;
-public:
- StatListener(PTHMap &pm) : PM(pm) {}
- ~StatListener() override {}
-
- LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F,
- vfs::FileSystem &FS) override {
- LookupResult Result = statChained(Path, Data, isFile, F, FS);
-
- if (Result == CacheMissing) // Failed 'stat'.
- PM.insert(PTHEntryKeyVariant(Path), PTHEntry());
- else if (Data.IsDirectory) {
- // Only cache directories with absolute paths.
- if (llvm::sys::path::is_relative(Path))
- return Result;
-
- PM.insert(PTHEntryKeyVariant(&Data, Path), PTHEntry());
- }
-
- return Result;
- }
-};
-} // end anonymous namespace
-
-void clang::CacheTokens(Preprocessor &PP, raw_pwrite_stream *OS) {
- // Get the name of the main file.
- const SourceManager &SrcMgr = PP.getSourceManager();
- const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
- SmallString<128> MainFilePath(MainFile->getName());
-
- llvm::sys::fs::make_absolute(MainFilePath);
-
- // Create the PTHWriter.
- PTHWriter PW(*OS, PP);
-
- // Install the 'stat' system call listener in the FileManager.
- auto StatCacheOwner = llvm::make_unique<StatListener>(PW.getPM());
- StatListener *StatCache = StatCacheOwner.get();
- PP.getFileManager().addStatCache(std::move(StatCacheOwner),
- /*AtBeginning=*/true);
-
- // Lex through the entire file. This will populate SourceManager with
- // all of the header information.
- Token Tok;
- PP.EnterMainSourceFile();
- do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
-
- // Generate the PTH file.
- PP.getFileManager().removeStatCache(StatCache);
- PW.GeneratePTH(MainFilePath.str());
-}
-
-//===----------------------------------------------------------------------===//
-
-namespace {
-class PTHIdKey {
-public:
- const IdentifierInfo* II;
- uint32_t FileOffset;
-};
-
-class PTHIdentifierTableTrait {
-public:
- typedef PTHIdKey* key_type;
- typedef key_type key_type_ref;
-
- typedef uint32_t data_type;
- typedef data_type data_type_ref;
-
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
-
- static hash_value_type ComputeHash(PTHIdKey* key) {
- return llvm::djbHash(key->II->getName());
- }
-
- static std::pair<unsigned,unsigned>
- EmitKeyDataLength(raw_ostream& Out, const PTHIdKey* key, uint32_t) {
- using namespace llvm::support;
- unsigned n = key->II->getLength() + 1;
- endian::write<uint16_t>(Out, n, little);
- return std::make_pair(n, sizeof(uint32_t));
- }
-
- static void EmitKey(raw_ostream& Out, PTHIdKey* key, unsigned n) {
- // Record the location of the key data. This is used when generating
- // the mapping from persistent IDs to strings.
- key->FileOffset = Out.tell();
- Out.write(key->II->getNameStart(), n);
- }
-
- static void EmitData(raw_ostream& Out, PTHIdKey*, uint32_t pID,
- unsigned) {
- using namespace llvm::support;
- endian::write<uint32_t>(Out, pID, little);
- }
-};
-} // end anonymous namespace
-
-/// EmitIdentifierTable - Emits two tables to the PTH file. The first is
-/// a hashtable mapping from identifier strings to persistent IDs. The second
-/// is a straight table mapping from persistent IDs to string data (the
-/// keys of the first table).
-///
-std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
- // Build two maps:
- // (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset)
- // (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs
-
- // Note that we use 'calloc', so all the bytes are 0.
- PTHIdKey *IIDMap = static_cast<PTHIdKey*>(
- llvm::safe_calloc(idcount, sizeof(PTHIdKey)));
-
- // Create the hashtable.
- llvm::OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;
-
- // Generate mapping from persistent IDs -> IdentifierInfo*.
- for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) {
- // Decrement by 1 because we are using a vector for the lookup and
- // 0 is reserved for NULL.
- assert(I->second > 0);
- assert(I->second-1 < idcount);
- unsigned idx = I->second-1;
-
- // Store the mapping from persistent ID to IdentifierInfo*
- IIDMap[idx].II = I->first;
-
- // Store the reverse mapping in a hashtable.
- IIOffMap.insert(&IIDMap[idx], I->second);
- }
-
- // Write out the inverse map first. This causes the PCIDKey entries to
- // record PTH file offsets for the string data. This is used to write
- // the second table.
- Offset StringTableOffset = IIOffMap.Emit(Out);
-
- // Now emit the table mapping from persistent IDs to PTH file offsets.
- Offset IDOff = Out.tell();
- Emit32(idcount); // Emit the number of identifiers.
- for (unsigned i = 0 ; i < idcount; ++i)
- Emit32(IIDMap[i].FileOffset);
-
- // Finally, release the inverse map.
- free(IIDMap);
-
- return std::make_pair(IDOff, StringTableOffset);
-}
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index 4e8eb32121dc..1bfc25c4c778 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -129,7 +129,6 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
CInvok->getPreprocessorOpts().ChainedIncludes.clear();
CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
- CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
CInvok->getPreprocessorOpts().DisablePCHValidation = true;
CInvok->getPreprocessorOpts().Includes.clear();
CInvok->getPreprocessorOpts().MacroIncludes.clear();
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index ecb09da3c1ef..f66674535423 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -30,7 +30,6 @@
#include "clang/Frontend/Utils.h"
#include "clang/Frontend/VerifyDiagnosticConsumer.h"
#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/CodeCompleteConsumer.h"
@@ -38,6 +37,7 @@
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
@@ -177,18 +177,18 @@ static void collectIncludePCH(CompilerInstance &CI,
std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(PCHDir->getName(), DirNative);
- vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
SimpleASTReaderListener Validator(CI.getPreprocessor());
- for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
+ for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
// Check whether this is an AST file. ASTReader::isAcceptableASTFile is not
// used here since we're not interested in validating the PCH at this time,
// but only to check whether this is a file containing an AST.
if (!ASTReader::readASTFileControlBlock(
- Dir->getName(), FileMgr, CI.getPCHContainerReader(),
+ Dir->path(), FileMgr, CI.getPCHContainerReader(),
/*FindModuleFileExtensions=*/false, Validator,
/*ValidateDiagnosticOptions=*/false))
- MDC->addFile(Dir->getName());
+ MDC->addFile(Dir->path());
}
}
@@ -198,14 +198,14 @@ static void collectVFSEntries(CompilerInstance &CI,
return;
// Collect all VFS found.
- SmallVector<vfs::YAMLVFSEntry, 16> VFSEntries;
+ SmallVector<llvm::vfs::YAMLVFSEntry, 16> VFSEntries;
for (const std::string &VFSFile : CI.getHeaderSearchOpts().VFSOverlayFiles) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
llvm::MemoryBuffer::getFile(VFSFile);
if (!Buffer)
return;
- vfs::collectVFSFromYAML(std::move(Buffer.get()), /*DiagHandler*/ nullptr,
- VFSFile, VFSEntries);
+ llvm::vfs::collectVFSFromYAML(std::move(Buffer.get()),
+ /*DiagHandler*/ nullptr, VFSFile, VFSEntries);
}
for (auto &E : VFSEntries)
@@ -303,7 +303,7 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
FileManager *CompilerInstance::createFileManager() {
if (!hasVirtualFileSystem()) {
- IntrusiveRefCntPtr<vfs::FileSystem> VFS =
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(getInvocation(), getDiagnostics());
setVirtualFileSystem(VFS);
}
@@ -372,10 +372,8 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags,
void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
- // Create a PTH manager if we are using some form of a token cache.
- PTHManager *PTHMgr = nullptr;
- if (!PPOpts.TokenCache.empty())
- PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
+ // The module manager holds a reference to the old preprocessor (if any).
+ ModuleManager.reset();
// Create the Preprocessor.
HeaderSearch *HeaderInfo =
@@ -383,19 +381,12 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
getDiagnostics(), getLangOpts(), &getTarget());
PP = std::make_shared<Preprocessor>(
Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(),
- getSourceManager(), getPCMCache(), *HeaderInfo, *this, PTHMgr,
+ getSourceManager(), getPCMCache(), *HeaderInfo, *this,
+ /*IdentifierInfoLookup=*/nullptr,
/*OwnsHeaderSearch=*/true, TUKind);
getTarget().adjust(getLangOpts());
PP->Initialize(getTarget(), getAuxTarget());
- // Note that this is different then passing PTHMgr to Preprocessor's ctor.
- // That argument is used as the IdentifierInfoLookup argument to
- // IdentifierTable's ctor.
- if (PTHMgr) {
- PTHMgr->setPreprocessor(&*PP);
- PP->setPTHManager(PTHMgr);
- }
-
if (PPOpts.DetailedRecord)
PP->createPreprocessingRecord();
@@ -911,6 +902,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
// taking it as an input instead of hard-coding llvm::errs.
raw_ostream &OS = llvm::errs();
+ if (!Act.PrepareToExecute(*this))
+ return false;
+
// Create the target instance.
setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
getInvocation().TargetOpts));
@@ -921,7 +915,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) &&
!getFrontendOpts().AuxTriple.empty()) {
auto TO = std::make_shared<TargetOptions>();
- TO->Triple = getFrontendOpts().AuxTriple;
+ TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
TO->HostTriple = getTarget().getTriple().str();
setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
}
@@ -1021,7 +1015,7 @@ static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) {
return InputKind::OpenCL;
if (LangOpts.CUDA)
return InputKind::CUDA;
- if (LangOpts.ObjC1)
+ if (LangOpts.ObjC)
return LangOpts.CPlusPlus ? InputKind::ObjCXX : InputKind::ObjC;
return LangOpts.CPlusPlus ? InputKind::CXX : InputKind::C;
}
@@ -1266,7 +1260,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
<< Module->Name << Locked.getErrorMessage();
// Clear out any potential leftover.
Locked.unsafeRemoveLockFile();
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case llvm::LockFileManager::LFS_Owned:
// We're responsible for building the module ourselves.
if (!compileModuleImpl(ImportingInstance, ModuleNameLoc, Module,
@@ -1615,22 +1609,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Module::NameVisibilityKind Visibility,
bool IsInclusionDirective) {
// Determine what file we're searching from.
- // FIXME: Should we be deciding whether this is a submodule (here and
- // below) based on -fmodules-ts or should we pass a flag and make the
- // caller decide?
- std::string ModuleName;
- if (getLangOpts().ModulesTS) {
- // FIXME: Same code as Sema::ActOnModuleDecl() so there is probably a
- // better place/way to do this.
- for (auto &Piece : Path) {
- if (!ModuleName.empty())
- ModuleName += ".";
- ModuleName += Piece.first->getName();
- }
- }
- else
- ModuleName = Path[0].first->getName();
-
+ StringRef ModuleName = Path[0].first->getName();
SourceLocation ModuleNameLoc = Path[0].second;
// If we've already handled this import, just return the cached result.
@@ -1736,7 +1715,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// module cache, we don't know how to rebuild modules.
unsigned ARRFlags = Source == ModuleCache ?
ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing :
- ASTReader::ARR_ConfigurationMismatch;
+ Source == PrebuiltModulePath ?
+ 0 :
+ ASTReader::ARR_ConfigurationMismatch;
switch (ModuleManager->ReadAST(ModuleFileName,
Source == PrebuiltModulePath
? serialization::MK_PrebuiltModule
@@ -1859,7 +1840,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Verify that the rest of the module path actually corresponds to
// a submodule.
bool MapPrivateSubModToTopLevel = false;
- if (!getLangOpts().ModulesTS && Path.size() > 1) {
+ if (Path.size() > 1) {
for (unsigned I = 1, N = Path.size(); I != N; ++I) {
StringRef Name = Path[I].first->getName();
clang::Module *Sub = Module->findSubmodule(Name);
@@ -2139,7 +2120,7 @@ CompilerInstance::lookupMissingImports(StringRef Name,
return false;
}
-void CompilerInstance::resetAndLeakSema() { BuryPointer(takeSema()); }
+void CompilerInstance::resetAndLeakSema() { llvm::BuryPointer(takeSema()); }
void CompilerInstance::setExternalSemaSource(
IntrusiveRefCntPtr<ExternalSemaSource> ESS) {
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 78e6babd0251..3e6528c25982 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -11,6 +11,7 @@
#include "TestModuleFileExtension.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Basic/Diagnostic.h"
@@ -23,17 +24,16 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Basic/Visibility.h"
#include "clang/Basic/XRayInstr.h"
#include "clang/Config/config.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/CommandLineSourceLoc.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Frontend/MigratorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
@@ -55,6 +55,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Linker/Linker.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Option/Arg.h"
@@ -76,6 +77,7 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
@@ -119,25 +121,25 @@ CompilerInvocationBase::~CompilerInvocationBase() = default;
static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
- unsigned DefaultOpt = 0;
+ unsigned DefaultOpt = llvm::CodeGenOpt::None;
if (IK.getLanguage() == InputKind::OpenCL && !Args.hasArg(OPT_cl_opt_disable))
- DefaultOpt = 2;
+ DefaultOpt = llvm::CodeGenOpt::Default;
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O0))
- return 0;
+ return llvm::CodeGenOpt::None;
if (A->getOption().matches(options::OPT_Ofast))
- return 3;
+ return llvm::CodeGenOpt::Aggressive;
assert(A->getOption().matches(options::OPT_O));
StringRef S(A->getValue());
if (S == "s" || S == "z" || S.empty())
- return 2;
+ return llvm::CodeGenOpt::Default;
if (S == "g")
- return 1;
+ return llvm::CodeGenOpt::Less;
return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
}
@@ -180,6 +182,11 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
}
}
+// Parse the Static Analyzer configuration. If \p Diags is set to nullptr,
+// it won't verify the input.
+static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
+ DiagnosticsEngine *Diags);
+
static void getAllNoBuiltinFuncValues(ArgList &Args,
std::vector<std::string> &Funcs) {
SmallVector<const char *, 8> Values;
@@ -278,19 +285,24 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
+ Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help);
Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers);
+ Opts.ShouldEmitErrorsOnInvalidConfigValue =
+ /* negated */!llvm::StringSwitch<bool>(
+ Args.getLastArgValue(OPT_analyzer_config_compatibility_mode))
+ .Case("true", true)
+ .Case("false", false)
+ .Default(false);
Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks);
Opts.visualizeExplodedGraphWithGraphViz =
Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
- Opts.visualizeExplodedGraphWithUbiGraph =
- Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
+ Opts.DumpExplodedGraphTo = Args.getLastArgValue(OPT_analyzer_dump_egraph);
Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
Opts.AnalyzeNestedBlocks =
Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
- Opts.eagerlyAssumeBinOpBifurcation = Args.hasArg(OPT_analyzer_eagerly_assume);
Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG);
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
@@ -317,7 +329,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
// Go through the analyzer configuration options.
for (const auto *A : Args.filtered(OPT_analyzer_config)) {
- A->claim();
+
// We can have a list of comma separated config names, e.g:
// '-analyzer-config key1=val1,key2=val2'
StringRef configList = A->getValue();
@@ -339,10 +351,25 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Success = false;
break;
}
+
+ // TODO: Check checker options too, possibly in CheckerRegistry.
+ // Leave unknown non-checker configs unclaimed.
+ if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {
+ if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
+ Diags.Report(diag::err_analyzer_config_unknown) << key;
+ continue;
+ }
+
+ A->claim();
Opts.Config[key] = val;
}
}
+ if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
+ parseAnalyzerConfigs(Opts, &Diags);
+ else
+ parseAnalyzerConfigs(Opts, nullptr);
+
llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
if (i != 0)
@@ -354,6 +381,91 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
return Success;
}
+static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
+ StringRef OptionName, StringRef DefaultVal) {
+ return Config.insert({OptionName, DefaultVal}).first->second;
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+ DiagnosticsEngine *Diags,
+ StringRef &OptionField, StringRef Name,
+ StringRef DefaultVal) {
+ // String options may be known to invalid (e.g. if the expected string is a
+ // file name, but the file does not exist), those will have to be checked in
+ // parseConfigs.
+ OptionField = getStringOption(Config, Name, DefaultVal);
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+ DiagnosticsEngine *Diags,
+ bool &OptionField, StringRef Name, bool DefaultVal) {
+ auto PossiblyInvalidVal = llvm::StringSwitch<Optional<bool>>(
+ getStringOption(Config, Name, (DefaultVal ? "true" : "false")))
+ .Case("true", true)
+ .Case("false", false)
+ .Default(None);
+
+ if (!PossiblyInvalidVal) {
+ if (Diags)
+ Diags->Report(diag::err_analyzer_config_invalid_input)
+ << Name << "a boolean";
+ else
+ OptionField = DefaultVal;
+ } else
+ OptionField = PossiblyInvalidVal.getValue();
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+ DiagnosticsEngine *Diags,
+ unsigned &OptionField, StringRef Name,
+ unsigned DefaultVal) {
+
+ OptionField = DefaultVal;
+ bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
+ .getAsInteger(10, OptionField);
+ if (Diags && HasFailed)
+ Diags->Report(diag::err_analyzer_config_invalid_input)
+ << Name << "an unsigned";
+}
+
+static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
+ DiagnosticsEngine *Diags) {
+ // TODO: There's no need to store the entire configtable, it'd be plenty
+ // enough tostore checker options.
+
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
+ initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);
+
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL) \
+ switch (AnOpts.getUserMode()) { \
+ case UMK_Shallow: \
+ initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, SHALLOW_VAL); \
+ break; \
+ case UMK_Deep: \
+ initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEEP_VAL); \
+ break; \
+ } \
+
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+
+ // At this point, AnalyzerOptions is configured. Let's validate some options.
+
+ if (!Diags)
+ return;
+
+ if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir))
+ Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir"
+ << "a filename";
+
+ if (!AnOpts.ModelPath.empty() &&
+ !llvm::sys::fs::is_directory(AnOpts.ModelPath))
+ Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"
+ << "a filename";
+}
+
static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error);
Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal);
@@ -369,7 +481,7 @@ static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) {
if (Arg *A = Args.getLastArg(OPT_mcode_model)) {
StringRef Value = A->getValue();
if (Value == "small" || Value == "kernel" || Value == "medium" ||
- Value == "large")
+ Value == "large" || Value == "tiny")
return Value;
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
}
@@ -568,6 +680,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
unsigned Val =
llvm::StringSwitch<unsigned>(A->getValue())
.Case("line-tables-only", codegenoptions::DebugLineTablesOnly)
+ .Case("line-directives-only", codegenoptions::DebugDirectivesOnly)
.Case("limited", codegenoptions::LimitedDebugInfo)
.Case("standalone", codegenoptions::FullDebugInfo)
.Default(~0U);
@@ -592,12 +705,29 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
Opts.EmitCodeView = Args.hasArg(OPT_gcodeview);
+ Opts.CodeViewGHash = Args.hasArg(OPT_gcodeview_ghash);
Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro);
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
- Opts.EnableSplitDwarf = Args.hasArg(OPT_enable_split_dwarf);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining);
+
+ if (Arg *A =
+ Args.getLastArg(OPT_enable_split_dwarf, OPT_enable_split_dwarf_EQ)) {
+ if (A->getOption().matches(options::OPT_enable_split_dwarf)) {
+ Opts.setSplitDwarfMode(CodeGenOptions::SplitFileFission);
+ } else {
+ StringRef Name = A->getValue();
+ if (Name == "single")
+ Opts.setSplitDwarfMode(CodeGenOptions::SingleFileFission);
+ else if (Name == "split")
+ Opts.setSplitDwarfMode(CodeGenOptions::SplitFileFission);
+ else
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << Name;
+ }
+ }
+
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import);
Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params);
@@ -614,6 +744,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers);
Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
+ Opts.IndirectTlsSegRefs = Args.hasArg(OPT_mno_tls_direct_seg_refs);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
OPT_fuse_register_sized_bitfield_access);
@@ -625,6 +756,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasFlag(OPT_ffine_grained_bitfield_accesses,
OPT_fno_fine_grained_bitfield_accesses, false);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
+ Opts.RecordCommandLine = Args.getLastArgValue(OPT_record_command_line);
Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
@@ -643,7 +775,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
Opts.DebugInfoForProfiling = Args.hasFlag(
OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false);
- Opts.GnuPubnames = Args.hasArg(OPT_ggnu_pubnames);
+ Opts.DebugNameTable = static_cast<unsigned>(
+ Args.hasArg(OPT_ggnu_pubnames)
+ ? llvm::DICompileUnit::DebugNameTableKind::GNU
+ : Args.hasArg(OPT_gpubnames)
+ ? llvm::DICompileUnit::DebugNameTableKind::Default
+ : llvm::DICompileUnit::DebugNameTableKind::None);
+ Opts.DebugRangesBaseAddress = Args.hasArg(OPT_fdebug_ranges_base_address);
setPGOInstrumentor(Opts, Args, Diags);
Opts.InstrProfileOutput =
@@ -652,6 +790,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.getLastArgValue(OPT_fprofile_instrument_use_path_EQ);
if (!Opts.ProfileInstrumentUsePath.empty())
setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath);
+ Opts.ProfileRemappingFile =
+ Args.getLastArgValue(OPT_fprofile_remapping_file_EQ);
+ if (!Opts.ProfileRemappingFile.empty() && !Opts.ExperimentalNewPassManager) {
+ Diags.Report(diag::err_drv_argument_only_allowed_with)
+ << Args.getLastArg(OPT_fprofile_remapping_file_EQ)->getAsString(Args)
+ << "-fexperimental-new-pass-manager";
+ }
Opts.CoverageMapping =
Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false);
@@ -664,7 +809,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.RegisterGlobalDtorsWithAtExit =
Args.hasArg(OPT_fregister_global_dtors_with_atexit);
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
- Opts.CodeModel = getCodeModel(Args, Diags);
+ Opts.CodeModel = TargetOpts.CodeModel;
Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
Opts.DisableFPElim =
(Args.hasArg(OPT_mdisable_fp_elim) || Args.hasArg(OPT_pg));
@@ -762,6 +907,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
}
Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false);
+ Opts.EnableSplitLTOUnit = Args.hasArg(OPT_fsplit_lto_unit);
if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
if (IK.getLanguage() != InputKind::LLVM_IR)
Diags.Report(diag::err_drv_argument_only_allowed_with)
@@ -797,6 +943,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum);
Opts.CoverageNoFunctionNamesInData =
Args.hasArg(OPT_coverage_no_function_names_in_data);
+ Opts.ProfileFilterFiles =
+ Args.getLastArgValue(OPT_fprofile_filter_files_EQ);
+ Opts.ProfileExcludeFiles =
+ Args.getLastArgValue(OPT_fprofile_exclude_files_EQ);
Opts.CoverageExitBlockBeforeBody =
Args.hasArg(OPT_coverage_exit_block_before_body);
if (Args.hasArg(OPT_coverage_version_EQ)) {
@@ -844,7 +994,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
for (const auto &arg : ASL) {
StringRef ArgStr(arg);
Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end());
- // using \00 to seperate each commandline options.
+ // using \00 to separate each commandline options.
Opts.CmdArgs.push_back('\0');
}
}
@@ -912,10 +1062,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
for (auto *A :
- Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) {
+ Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {
CodeGenOptions::BitcodeFileToLink F;
F.Filename = A->getValue();
- if (A->getOption().matches(OPT_mlink_cuda_bitcode)) {
+ if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {
F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
// When linking CUDA bitcode, propagate function attributes so that
// e.g. libdevice gets fast-math attrs if we're building with fast-math.
@@ -955,11 +1105,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_fsanitize_cfi_icall_generalize_pointers);
Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats);
if (Arg *A = Args.getLastArg(
- OPT_fsanitize_address_poison_class_member_array_new_cookie,
- OPT_fno_sanitize_address_poison_class_member_array_new_cookie)) {
- Opts.SanitizeAddressPoisonClassMemberArrayNewCookie =
+ OPT_fsanitize_address_poison_custom_array_cookie,
+ OPT_fno_sanitize_address_poison_custom_array_cookie)) {
+ Opts.SanitizeAddressPoisonCustomArrayCookie =
A->getOption().getID() ==
- OPT_fsanitize_address_poison_class_member_array_new_cookie;
+ OPT_fsanitize_address_poison_custom_array_cookie;
}
if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope,
OPT_fno_sanitize_address_use_after_scope)) {
@@ -968,6 +1118,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
Opts.SanitizeAddressGlobalsDeadStripping =
Args.hasArg(OPT_fsanitize_address_globals_dead_stripping);
+ if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_odr_indicator,
+ OPT_fno_sanitize_address_use_odr_indicator)) {
+ Opts.SanitizeAddressUseOdrIndicator =
+ A->getOption().getID() == OPT_fsanitize_address_use_odr_indicator;
+ }
Opts.SSPBufferSize =
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
@@ -1003,6 +1158,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
+
+ if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
+ Opts.ObjCConvertMessagesToRuntimeCalls = 0;
+
if (Args.getLastArg(OPT_femulated_tls) ||
Args.getLastArg(OPT_fno_emulated_tls)) {
Opts.ExplicitEmulatedTLS = true;
@@ -1125,6 +1284,44 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.Addrsig = Args.hasArg(OPT_faddrsig);
+ if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
+ StringRef SignScope = A->getValue();
+
+ if (SignScope.equals_lower("none"))
+ Opts.setSignReturnAddress(CodeGenOptions::SignReturnAddressScope::None);
+ else if (SignScope.equals_lower("all"))
+ Opts.setSignReturnAddress(CodeGenOptions::SignReturnAddressScope::All);
+ else if (SignScope.equals_lower("non-leaf"))
+ Opts.setSignReturnAddress(
+ CodeGenOptions::SignReturnAddressScope::NonLeaf);
+ else
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << SignScope;
+
+ if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
+ StringRef SignKey = A->getValue();
+ if (!SignScope.empty() && !SignKey.empty()) {
+ if (SignKey.equals_lower("a_key"))
+ Opts.setSignReturnAddressKey(
+ CodeGenOptions::SignReturnAddressKeyValue::AKey);
+ else if (SignKey.equals_lower("b_key"))
+ Opts.setSignReturnAddressKey(
+ CodeGenOptions::SignReturnAddressKeyValue::BKey);
+ else
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << SignKey;
+ }
+ }
+ }
+
+ Opts.BranchTargetEnforcement = Args.hasArg(OPT_mbranch_target_enforce);
+
+ Opts.KeepStaticConsts = Args.hasArg(OPT_fkeep_static_consts);
+
+ Opts.SpeculativeLoadHardening = Args.hasArg(OPT_mspeculative_load_hardening);
+
+ Opts.DefaultFunctionAttrs = Args.getAllArgValues(OPT_default_function_attr);
+
return Success;
}
@@ -1316,7 +1513,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Success = false;
}
else
- llvm::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end());
+ llvm::sort(Opts.VerifyPrefixes);
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
@@ -1425,17 +1622,17 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::EmitObj; break;
case OPT_fixit_EQ:
Opts.FixItSuffix = A->getValue();
- // fall-through!
+ LLVM_FALLTHROUGH;
case OPT_fixit:
Opts.ProgramAction = frontend::FixIt; break;
case OPT_emit_module:
Opts.ProgramAction = frontend::GenerateModule; break;
case OPT_emit_module_interface:
Opts.ProgramAction = frontend::GenerateModuleInterface; break;
+ case OPT_emit_header_module:
+ Opts.ProgramAction = frontend::GenerateHeaderModule; break;
case OPT_emit_pch:
Opts.ProgramAction = frontend::GeneratePCH; break;
- case OPT_emit_pth:
- Opts.ProgramAction = frontend::GeneratePTH; break;
case OPT_init_only:
Opts.ProgramAction = frontend::InitOnly; break;
case OPT_fsyntax_only:
@@ -1444,8 +1641,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::ModuleFileInfo; break;
case OPT_verify_pch:
Opts.ProgramAction = frontend::VerifyPCH; break;
- case OPT_print_decl_contexts:
- Opts.ProgramAction = frontend::PrintDeclContext; break;
case OPT_print_preamble:
Opts.ProgramAction = frontend::PrintPreamble; break;
case OPT_E:
@@ -1550,8 +1745,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.OverrideRecordLayoutsFile
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
- Opts.AuxTriple =
- llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple));
+ Opts.AuxTriple = Args.getLastArgValue(OPT_aux_triple);
Opts.StatsFile = Args.getLastArgValue(OPT_stats_file);
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
@@ -1867,7 +2061,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
if (IK.getLanguage() == InputKind::Asm) {
Opts.AsmPreprocessor = 1;
} else if (IK.isObjectiveC()) {
- Opts.ObjC1 = Opts.ObjC2 = 1;
+ Opts.ObjC = 1;
}
if (LangStd == LangStandard::lang_unspecified) {
@@ -2130,6 +2324,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
}
+ if (Args.hasArg(OPT_fno_dllexport_inlines))
+ Opts.DllExportInlines = false;
+
if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
StringRef Name = A->getValue();
if (Name == "full" || Name == "branch") {
@@ -2196,9 +2393,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals))
Opts.CUDADeviceApproxTranscendentals = 1;
- Opts.CUDARelocatableDeviceCode = Args.hasArg(OPT_fcuda_rdc);
+ Opts.GPURelocatableDeviceCode = Args.hasArg(OPT_fgpu_rdc);
- if (Opts.ObjC1) {
+ if (Opts.ObjC) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
StringRef value = arg->getValue();
if (Opts.ObjCRuntime.tryParse(value))
@@ -2265,8 +2462,19 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_print_ivar_layout))
Opts.ObjCGCBitmapPrint = 1;
+
if (Args.hasArg(OPT_fno_constant_cfstrings))
Opts.NoConstantCFStrings = 1;
+ if (const auto *A = Args.getLastArg(OPT_fcf_runtime_abi_EQ))
+ Opts.CFRuntime =
+ llvm::StringSwitch<LangOptions::CoreFoundationABI>(A->getValue())
+ .Cases("unspecified", "standalone", "objc",
+ LangOptions::CoreFoundationABI::ObjectiveC)
+ .Cases("swift", "swift-5.0",
+ LangOptions::CoreFoundationABI::Swift5_0)
+ .Case("swift-4.2", LangOptions::CoreFoundationABI::Swift4_2)
+ .Case("swift-4.1", LangOptions::CoreFoundationABI::Swift4_1)
+ .Default(LangOptions::CoreFoundationABI::ObjectiveC);
if (Args.hasArg(OPT_fzvector))
Opts.ZVector = 1;
@@ -2291,6 +2499,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fvisibility_inlines_hidden))
Opts.InlineVisibilityHidden = 1;
+ if (Args.hasArg(OPT_fvisibility_global_new_delete_hidden))
+ Opts.GlobalAllocationFunctionVisibilityHidden = 1;
+
if (Args.hasArg(OPT_ftrapv)) {
Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
// Set the handler, if one is specified.
@@ -2314,7 +2525,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
VT.getSubminor().getValueOr(0);
}
- // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+ // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs
// is specified, or -std is set to a conforming mode.
// Trigraphs are disabled by default in c++1z onwards.
Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17;
@@ -2395,7 +2606,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules);
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
- Opts.Char8 = Args.hasArg(OPT_fchar8__t);
+ Opts.Char8 = Args.hasFlag(OPT_fchar8__t, OPT_fno_char8__t, Opts.CPlusPlus2a);
if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) {
Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue())
.Case("char", 1)
@@ -2478,7 +2689,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.CurrentModule = Opts.ModuleName;
Opts.AppExt = Args.hasArg(OPT_fapplication_extension);
Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature);
- llvm::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end());
+ llvm::sort(Opts.ModuleFeatures);
Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type);
Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns);
// Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns
@@ -2627,6 +2838,19 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.Exceptions = 0;
Opts.CXXExceptions = 0;
}
+ if (Opts.OpenMPIsDevice && T.isNVPTX()) {
+ Opts.OpenMPCUDANumSMs =
+ getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,
+ Opts.OpenMPCUDANumSMs, Diags);
+ Opts.OpenMPCUDABlocksPerSM =
+ getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,
+ Opts.OpenMPCUDABlocksPerSM, Diags);
+ }
+
+ // Prevent auto-widening the representation of loop counters during an
+ // OpenMP collapse clause.
+ Opts.OpenMPOptimisticCollapse =
+ Args.hasArg(options::OPT_fopenmp_optimistic_collapse) ? 1 : 0;
// Get the OpenMP target triples if any.
if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {
@@ -2657,10 +2881,15 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
<< Opts.OMPHostIRFile;
}
- // set CUDA mode for OpenMP target NVPTX if specified in options
+ // Set CUDA mode for OpenMP target NVPTX if specified in options
Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && T.isNVPTX() &&
Args.hasArg(options::OPT_fopenmp_cuda_mode);
+ // Set CUDA mode for OpenMP target NVPTX if specified in options
+ Opts.OpenMPCUDAForceFullRuntime =
+ Opts.OpenMPIsDevice && T.isNVPTX() &&
+ Args.hasArg(options::OPT_fopenmp_cuda_force_full_runtime);
+
// Record whether the __DEPRECATED define was requested.
Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro,
OPT_fno_deprecated_macro,
@@ -2718,6 +2947,19 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
case 3: Opts.setStackProtector(LangOptions::SSPReq); break;
}
+ if (Arg *A = Args.getLastArg(OPT_ftrivial_auto_var_init)) {
+ StringRef Val = A->getValue();
+ if (Val == "uninitialized")
+ Opts.setTrivialAutoVarInit(
+ LangOptions::TrivialAutoVarInitKind::Uninitialized);
+ else if (Val == "zero")
+ Opts.setTrivialAutoVarInit(LangOptions::TrivialAutoVarInitKind::Zero);
+ else if (Val == "pattern")
+ Opts.setTrivialAutoVarInit(LangOptions::TrivialAutoVarInitKind::Pattern);
+ else
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+ }
+
// Parse -fsanitize= arguments.
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
Diags, Opts.Sanitize);
@@ -2753,6 +2995,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// -fallow-editor-placeholders
Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders);
+ Opts.RegisterStaticDestructors = !Args.hasArg(OPT_fno_cxx_static_destructors);
+
if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
Opts.setClangABICompat(LangOptions::ClangABI::Latest);
@@ -2776,6 +3020,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
else if (Major <= 6)
Opts.setClangABICompat(LangOptions::ClangABI::Ver6);
+ else if (Major <= 7)
+ Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
} else if (Ver != "latest") {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
@@ -2802,13 +3048,12 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::FixIt:
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
+ case frontend::GenerateHeaderModule:
case frontend::GeneratePCH:
- case frontend::GeneratePTH:
case frontend::ParseSyntaxOnly:
case frontend::ModuleFileInfo:
case frontend::VerifyPCH:
case frontend::PluginAction:
- case frontend::PrintDeclContext:
case frontend::RewriteObjC:
case frontend::RewriteTest:
case frontend::RunAnalysis:
@@ -2833,12 +3078,10 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags,
frontend::ActionKind Action) {
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
- Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
+ Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
+ Args.hasArg(OPT_pch_through_hdrstop_use);
+ Opts.PCHWithHdrStopCreate = Args.hasArg(OPT_pch_through_hdrstop_create);
Opts.PCHThroughHeader = Args.getLastArgValue(OPT_pch_through_header_EQ);
- if (const Arg *A = Args.getLastArg(OPT_token_cache))
- Opts.TokenCache = A->getValue();
- else
- Opts.TokenCache = Opts.ImplicitPTHInclude;
Opts.UsePredefines = !Args.hasArg(OPT_undef);
Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
@@ -2943,6 +3186,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
+ Opts.CodeModel = getCodeModel(Args, Diags);
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
if (Arg *A = Args.getLastArg(OPT_meabi)) {
StringRef Value = A->getValue();
@@ -2971,6 +3215,14 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
Opts.ForceEnableInt128 = Args.hasArg(OPT_fforce_enable_int128);
Opts.NVPTXUseShortPointers = Args.hasFlag(
options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false);
+ if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
+ llvm::VersionTuple Version;
+ if (Version.tryParse(A->getValue()))
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ else
+ Opts.SDKVersion = Version;
+ }
}
bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
@@ -3023,6 +3275,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Res.getTargetOpts(), Res.getFrontendOpts());
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args,
Res.getFileSystemOpts().WorkingDir);
+ llvm::Triple T(Res.getTargetOpts().Triple);
if (DashX.getFormat() == InputKind::Precompiled ||
DashX.getLanguage() == InputKind::LLVM_IR) {
// ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
@@ -3037,12 +3290,18 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
Diags, LangOpts.Sanitize);
} else {
- // Other LangOpts are only initialzed when the input is not AST or LLVM IR.
+ // Other LangOpts are only initialized when the input is not AST or LLVM IR.
// FIXME: Should we really be calling this for an InputKind::Asm input?
ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
Res.getPreprocessorOpts(), Diags);
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
LangOpts.ObjCExceptions = 1;
+ if (T.isOSDarwin() && DashX.isPreprocessed()) {
+ // Supress the darwin-specific 'stdlibcxx-not-found' diagnostic for
+ // preprocessed input as we don't expect it to be used with -std=libc++
+ // anyway.
+ Res.getDiagnosticOpts().Warnings.push_back("no-stdlibcxx-not-found");
+ }
}
LangOpts.FunctionAlignment =
@@ -3064,7 +3323,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
// names.
Res.getCodeGenOpts().DiscardValueNames &=
!LangOpts.Sanitize.has(SanitizerKind::Address) &&
- !LangOpts.Sanitize.has(SanitizerKind::Memory);
+ !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
+ !LangOpts.Sanitize.has(SanitizerKind::Memory) &&
+ !LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
Res.getFrontendOpts().ProgramAction);
@@ -3072,7 +3333,6 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Res.getFrontendOpts().ProgramAction);
// Turn on -Wspir-compat for SPIR target.
- llvm::Triple T(Res.getTargetOpts().Triple);
auto Arch = T.getArch();
if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) {
Res.getDiagnosticOpts().Warnings.push_back("spir-compat");
@@ -3156,6 +3416,12 @@ std::string CompilerInvocation::getModuleHash() const {
code = ext->hashExtension(code);
}
+ // When compiling with -gmodules, also hash -fdebug-prefix-map as it
+ // affects the debug info in the PCM.
+ if (getCodeGenOpts().DebugTypeExtRefs)
+ for (const auto &KeyValue : getCodeGenOpts().DebugPrefixMap)
+ code = hash_combine(code, KeyValue.first, KeyValue.second);
+
// Extend the signature with the enabled sanitizers, if at least one is
// enabled. Sanitizers which cannot affect AST generation aren't hashed.
SanitizerSet SanHash = LangOpts->Sanitize;
@@ -3195,53 +3461,40 @@ uint64_t getLastArgUInt64Value(const ArgList &Args, OptSpecifier Id,
return getLastArgIntValueImpl<uint64_t>(Args, Id, Default, Diags);
}
-void BuryPointer(const void *Ptr) {
- // This function may be called only a small fixed amount of times per each
- // invocation, otherwise we do actually have a leak which we want to report.
- // If this function is called more than kGraveYardMaxSize times, the pointers
- // will not be properly buried and a leak detector will report a leak, which
- // is what we want in such case.
- static const size_t kGraveYardMaxSize = 16;
- LLVM_ATTRIBUTE_UNUSED static const void *GraveYard[kGraveYardMaxSize];
- static std::atomic<unsigned> GraveYardSize;
- unsigned Idx = GraveYardSize++;
- if (Idx >= kGraveYardMaxSize)
- return;
- GraveYard[Idx] = Ptr;
-}
-
-IntrusiveRefCntPtr<vfs::FileSystem>
+IntrusiveRefCntPtr<llvm::vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags) {
- return createVFSFromCompilerInvocation(CI, Diags, vfs::getRealFileSystem());
+ return createVFSFromCompilerInvocation(CI, Diags,
+ llvm::vfs::getRealFileSystem());
}
-IntrusiveRefCntPtr<vfs::FileSystem>
-createVFSFromCompilerInvocation(const CompilerInvocation &CI,
- DiagnosticsEngine &Diags,
- IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
+IntrusiveRefCntPtr<llvm::vfs::FileSystem> createVFSFromCompilerInvocation(
+ const CompilerInvocation &CI, DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
return BaseFS;
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
- new vfs::OverlayFileSystem(BaseFS));
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS;
// earlier vfs files are on the bottom
for (const auto &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
- BaseFS->getBufferForFile(File);
+ Result->getBufferForFile(File);
if (!Buffer) {
Diags.Report(diag::err_missing_vfs_overlay_file) << File;
continue;
}
- IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML(
- std::move(Buffer.get()), /*DiagHandler*/ nullptr, File);
- if (FS)
- Overlay->pushOverlay(FS);
- else
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
+ std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
+ /*DiagContext*/ nullptr, Result);
+ if (!FS) {
Diags.Report(diag::err_invalid_vfs_overlay) << File;
+ continue;
+ }
+
+ Result = FS;
}
- return Overlay;
+ return Result;
}
} // namespace clang
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index c3ce7ce2b742..2d4c40f8b9f1 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -32,7 +32,7 @@ using namespace llvm::opt;
/// argument vector.
std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine(
ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
if (!Diags.get()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index e6e07190e1ff..a03d4b79c8b9 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -17,7 +17,6 @@
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/DirectoryLookup.h"
-#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
@@ -200,6 +199,10 @@ public:
const Module *Imported,
SrcMgr::CharacteristicKind FileType) override;
+ void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled,
+ const FileEntry *File,
+ SrcMgr::CharacteristicKind FileType) override;
+
void EndOfMainFile() override {
OutputDependencyFile();
}
@@ -328,6 +331,17 @@ void DFGImpl::InclusionDirective(SourceLocation HashLoc,
}
}
+void DFGImpl::HasInclude(SourceLocation Loc, StringRef SpelledFilename,
+ bool IsAngled, const FileEntry *File,
+ SrcMgr::CharacteristicKind FileType) {
+ if (!File)
+ return;
+ StringRef Filename = File->getName();
+ if (!FileMatchesDepCriteria(Filename.data(), FileType))
+ return;
+ AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
+}
+
bool DFGImpl::AddFilename(StringRef Filename) {
if (FilesSet.insert(Filename).second) {
Files.push_back(Filename);
@@ -386,28 +400,32 @@ bool DFGImpl::AddFilename(StringRef Filename) {
/// for Windows file-naming info.
static void PrintFilename(raw_ostream &OS, StringRef Filename,
DependencyOutputFormat OutputFormat) {
+ // Convert filename to platform native path
+ llvm::SmallString<256> NativePath;
+ llvm::sys::path::native(Filename.str(), NativePath);
+
if (OutputFormat == DependencyOutputFormat::NMake) {
// Add quotes if needed. These are the characters listed as "special" to
// NMake, that are legal in a Windows filespec, and that could cause
// misinterpretation of the dependency string.
- if (Filename.find_first_of(" #${}^!") != StringRef::npos)
- OS << '\"' << Filename << '\"';
+ if (NativePath.find_first_of(" #${}^!") != StringRef::npos)
+ OS << '\"' << NativePath << '\"';
else
- OS << Filename;
+ OS << NativePath;
return;
}
assert(OutputFormat == DependencyOutputFormat::Make);
- for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
- if (Filename[i] == '#') // Handle '#' the broken gcc way.
+ for (unsigned i = 0, e = NativePath.size(); i != e; ++i) {
+ if (NativePath[i] == '#') // Handle '#' the broken gcc way.
OS << '\\';
- else if (Filename[i] == ' ') { // Handle space correctly.
+ else if (NativePath[i] == ' ') { // Handle space correctly.
OS << '\\';
unsigned j = i;
- while (j > 0 && Filename[--j] == '\\')
+ while (j > 0 && NativePath[--j] == '\\')
OS << '\\';
- } else if (Filename[i] == '$') // $ is escaped by $$.
+ } else if (NativePath[i] == '$') // $ is escaped by $$.
OS << '$';
- OS << Filename[i];
+ OS << NativePath[i];
}
}
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index 757ceec7ec9d..3bd86dc5beaa 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -337,8 +337,8 @@ static void computeCommonMacroArgExpansionFileIDs(
SmallVector<FileID, 4> EndArgExpansions;
getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM);
getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM);
- llvm::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
- llvm::sort(EndArgExpansions.begin(), EndArgExpansions.end());
+ llvm::sort(BeginArgExpansions);
+ llvm::sort(EndArgExpansions);
std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
EndArgExpansions.begin(), EndArgExpansions.end(),
std::back_inserter(CommonArgExpansions));
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 74550c410396..f5226380b4dd 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -26,6 +26,7 @@
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
+#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -151,6 +152,24 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
if (!Consumer)
return nullptr;
+ // Validate -add-plugin args.
+ bool FoundAllPlugins = true;
+ for (const std::string &Arg : CI.getFrontendOpts().AddPluginActions) {
+ bool Found = false;
+ for (FrontendPluginRegistry::iterator it = FrontendPluginRegistry::begin(),
+ ie = FrontendPluginRegistry::end();
+ it != ie; ++it) {
+ if (it->getName() == Arg)
+ Found = true;
+ }
+ if (!Found) {
+ CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << Arg;
+ FoundAllPlugins = false;
+ }
+ }
+ if (!FoundAllPlugins)
+ return nullptr;
+
// If there are no registered plugins we don't need to wrap the consumer
if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end())
return Consumer;
@@ -276,7 +295,7 @@ static void addHeaderInclude(StringRef HeaderName,
bool IsExternC) {
if (IsExternC && LangOpts.CPlusPlus)
Includes += "extern \"C\" {\n";
- if (LangOpts.ObjC1)
+ if (LangOpts.ObjC)
Includes += "#import \"";
else
Includes += "#include \"";
@@ -342,17 +361,17 @@ static std::error_code collectModuleHeaderIncludes(
SmallString<128> DirNative;
llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative);
- vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
- for (vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;
+ llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End;
Dir != End && !EC; Dir.increment(EC)) {
// Check whether this entry has an extension typically associated with
// headers.
- if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName()))
- .Cases(".h", ".H", ".hh", ".hpp", true)
- .Default(false))
+ if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
+ .Cases(".h", ".H", ".hh", ".hpp", true)
+ .Default(false))
continue;
- const FileEntry *Header = FileMgr.getFile(Dir->getName());
+ const FileEntry *Header = FileMgr.getFile(Dir->path());
// FIXME: This shouldn't happen unless there is a file system race. Is
// that worth diagnosing?
if (!Header)
@@ -365,7 +384,7 @@ static std::error_code collectModuleHeaderIncludes(
// Compute the relative path from the directory to this file.
SmallVector<StringRef, 16> Components;
- auto PathIt = llvm::sys::path::rbegin(Dir->getName());
+ auto PathIt = llvm::sys::path::rbegin(Dir->path());
for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
Components.push_back(*PathIt);
SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten);
@@ -523,7 +542,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
setCurrentInput(Input);
setCompilerInstance(&CI);
- StringRef InputFile = Input.getFile();
bool HasBegunSourceFile = false;
bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&
usesPreprocessorOnly();
@@ -541,6 +559,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
&Diags->getDiagnosticOptions()));
ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
+ // FIXME: What if the input is a memory buffer?
+ StringRef InputFile = Input.getFile();
+
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
InputFile, CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly,
ASTDiags, CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs);
@@ -566,7 +587,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
auto &MM = ASTReader->getModuleManager();
auto &PrimaryModule = MM.getPrimaryModule();
- for (ModuleFile &MF : MM)
+ for (serialization::ModuleFile &MF : MM)
if (&MF != &PrimaryModule)
CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);
@@ -585,12 +606,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
assert(ASTModule && "module file does not define its own module");
Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);
} else {
- auto &SM = CI.getSourceManager();
- FileID ID = SM.getMainFileID();
- if (auto *File = SM.getFileEntryForID(ID))
+ auto &OldSM = AST->getSourceManager();
+ FileID ID = OldSM.getMainFileID();
+ if (auto *File = OldSM.getFileEntryForID(ID))
Input = FrontendInputFile(File->getName(), Kind);
else
- Input = FrontendInputFile(SM.getBuffer(ID), Kind);
+ Input = FrontendInputFile(OldSM.getBuffer(ID), Kind);
}
setCurrentInput(Input, std::move(AST));
}
@@ -604,6 +625,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
+ // FIXME: What if the input is a memory buffer?
+ StringRef InputFile = Input.getFile();
+
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags,
CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs);
@@ -691,15 +715,16 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
SmallString<128> DirNative;
llvm::sys::path::native(PCHDir->getName(), DirNative);
bool Found = false;
- vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
- for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
+ llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
+ DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
// Check whether this is an acceptable AST file.
if (ASTReader::isAcceptableASTFile(
- Dir->getName(), FileMgr, CI.getPCHContainerReader(),
+ Dir->path(), FileMgr, CI.getPCHContainerReader(),
CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(),
SpecificModuleCachePath)) {
- PPOpts.ImplicitPCHInclude = Dir->getName();
+ PPOpts.ImplicitPCHInclude = Dir->path();
Found = true;
break;
}
@@ -791,7 +816,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// For preprocessed files, check if the first line specifies the original
// source file name with a linemarker.
- std::string PresumedInputFile = InputFile;
+ std::string PresumedInputFile = getCurrentFileOrBufferName();
if (Input.isPreprocessed())
ReadOriginalFileName(CI, PresumedInputFile);
@@ -943,7 +968,7 @@ void FrontendAction::EndSourceFile() {
if (DisableFree) {
CI.resetAndLeakSema();
CI.resetAndLeakASTContext();
- BuryPointer(CI.takeASTConsumer().get());
+ llvm::BuryPointer(CI.takeASTConsumer().get());
} else {
CI.setSema(nullptr);
CI.setASTContext(nullptr);
@@ -968,7 +993,7 @@ void FrontendAction::EndSourceFile() {
CI.resetAndLeakPreprocessor();
CI.resetAndLeakSourceManager();
CI.resetAndLeakFileManager();
- BuryPointer(CurrentASTUnit.release());
+ llvm::BuryPointer(std::move(CurrentASTUnit));
} else {
CI.setPreprocessor(nullptr);
CI.setSourceManager(nullptr);
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 8a8354c7d4c9..a407dfc162bb 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -92,12 +92,6 @@ ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
}
std::unique_ptr<ASTConsumer>
-DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- return CreateDeclContextPrinter();
-}
-
-std::unique_ptr<ASTConsumer>
GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::string Sysroot;
if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot))
@@ -242,6 +236,76 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
}
+bool GenerateHeaderModuleAction::PrepareToExecuteAction(
+ CompilerInstance &CI) {
+ if (!CI.getLangOpts().Modules && !CI.getLangOpts().ModulesTS) {
+ CI.getDiagnostics().Report(diag::err_header_module_requires_modules);
+ return false;
+ }
+
+ auto &Inputs = CI.getFrontendOpts().Inputs;
+ if (Inputs.empty())
+ return GenerateModuleAction::BeginInvocation(CI);
+
+ auto Kind = Inputs[0].getKind();
+
+ // Convert the header file inputs into a single module input buffer.
+ SmallString<256> HeaderContents;
+ ModuleHeaders.reserve(Inputs.size());
+ for (const FrontendInputFile &FIF : Inputs) {
+ // FIXME: We should support re-compiling from an AST file.
+ if (FIF.getKind().getFormat() != InputKind::Source || !FIF.isFile()) {
+ CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
+ << (FIF.isFile() ? FIF.getFile()
+ : FIF.getBuffer()->getBufferIdentifier());
+ return true;
+ }
+
+ HeaderContents += "#include \"";
+ HeaderContents += FIF.getFile();
+ HeaderContents += "\"\n";
+ ModuleHeaders.push_back(FIF.getFile());
+ }
+ Buffer = llvm::MemoryBuffer::getMemBufferCopy(
+ HeaderContents, Module::getModuleInputBufferName());
+
+ // Set that buffer up as our "real" input.
+ Inputs.clear();
+ Inputs.push_back(FrontendInputFile(Buffer.get(), Kind, /*IsSystem*/false));
+
+ return GenerateModuleAction::PrepareToExecuteAction(CI);
+}
+
+bool GenerateHeaderModuleAction::BeginSourceFileAction(
+ CompilerInstance &CI) {
+ CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderModule);
+
+ // Synthesize a Module object for the given headers.
+ auto &HS = CI.getPreprocessor().getHeaderSearchInfo();
+ SmallVector<Module::Header, 16> Headers;
+ for (StringRef Name : ModuleHeaders) {
+ const DirectoryLookup *CurDir = nullptr;
+ const FileEntry *FE = HS.LookupFile(
+ Name, SourceLocation(), /*Angled*/ false, nullptr, CurDir,
+ None, nullptr, nullptr, nullptr, nullptr, nullptr);
+ if (!FE) {
+ CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
+ << Name;
+ continue;
+ }
+ Headers.push_back({Name, FE});
+ }
+ HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
+
+ return GenerateModuleAction::BeginSourceFileAction(CI);
+}
+
+std::unique_ptr<raw_pwrite_stream>
+GenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI,
+ StringRef InFile) {
+ return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
+}
+
SyntaxOnlyAction::~SyntaxOnlyAction() {
}
@@ -341,6 +405,8 @@ private:
return "PriorTemplateArgumentSubstitution";
case CodeSynthesisContext::DefaultTemplateArgumentChecking:
return "DefaultTemplateArgumentChecking";
+ case CodeSynthesisContext::ExceptionSpecEvaluation:
+ return "ExceptionSpecEvaluation";
case CodeSynthesisContext::ExceptionSpecInstantiation:
return "ExceptionSpecInstantiation";
case CodeSynthesisContext::DeclaringSpecialMember:
@@ -599,6 +665,17 @@ namespace {
return true;
}
+
+ /// Returns true if this \c ASTReaderListener wants to receive the
+ /// imports of the AST file via \c visitImport, false otherwise.
+ bool needsImportVisitation() const override { return true; }
+
+ /// If needsImportVisitation returns \c true, this is called for each
+ /// AST file imported by this AST file.
+ void visitImport(StringRef ModuleName, StringRef Filename) override {
+ Out.indent(2) << "Imports module '" << ModuleName
+ << "': " << Filename.str() << "\n";
+ }
#undef DUMP_BOOLEAN
};
}
@@ -673,16 +750,6 @@ void DumpTokensAction::ExecuteAction() {
} while (Tok.isNot(tok::eof));
}
-void GeneratePTHAction::ExecuteAction() {
- CompilerInstance &CI = getCompilerInstance();
- std::unique_ptr<raw_pwrite_stream> OS =
- CI.createDefaultOutputFile(true, getCurrentFile());
- if (!OS)
- return;
-
- CacheTokens(CI.getPreprocessor(), OS.get());
-}
-
void PreprocessOnlyAction::ExecuteAction() {
Preprocessor &PP = getCompilerInstance().getPreprocessor();
@@ -742,7 +809,7 @@ void PrintPreprocessedAction::ExecuteAction() {
}
std::unique_ptr<raw_ostream> OS =
- CI.createDefaultOutputFile(BinaryMode, getCurrentFile());
+ CI.createDefaultOutputFile(BinaryMode, getCurrentFileOrBufferName());
if (!OS) return;
// If we're preprocessing a module map, start by dumping the contents of the
@@ -754,8 +821,6 @@ void PrintPreprocessedAction::ExecuteAction() {
OS->write_escaped(Input.getFile());
(*OS) << "\"\n";
}
- // FIXME: Include additional information here so that we don't need the
- // original source files to exist on disk.
getCurrentModule()->print(*OS);
(*OS) << "#pragma clang module contents\n";
}
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 8a70404629d3..ac3bb713ddcc 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -260,6 +260,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
switch (os) {
case llvm::Triple::Linux:
+ case llvm::Triple::Hurd:
case llvm::Triple::Solaris:
llvm_unreachable("Include management is handled in the driver.");
@@ -412,6 +413,7 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(
switch (os) {
case llvm::Triple::Linux:
+ case llvm::Triple::Hurd:
case llvm::Triple::Solaris:
llvm_unreachable("Include management is handled in the driver.");
break;
@@ -460,6 +462,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
break; // Everything else continues to use this routine's logic.
case llvm::Triple::Linux:
+ case llvm::Triple::Hurd:
case llvm::Triple::Solaris:
return;
@@ -473,22 +476,6 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
if (HSOpts.UseLibcxx) {
- if (triple.isOSDarwin()) {
- // On Darwin, libc++ may be installed alongside the compiler in
- // include/c++/v1.
- if (!HSOpts.ResourceDir.empty()) {
- // Remove version from foo/lib/clang/version
- StringRef NoVer = llvm::sys::path::parent_path(HSOpts.ResourceDir);
- // Remove clang from foo/lib/clang
- StringRef Lib = llvm::sys::path::parent_path(NoVer);
- // Remove lib from foo/lib
- SmallString<128> P = llvm::sys::path::parent_path(Lib);
-
- // Get foo/include/c++/v1
- llvm::sys::path::append(P, "include", "c++", "v1");
- AddUnmappedPath(P, CXXSystem, false);
- }
- }
AddPath("/usr/include/c++/v1", CXXSystem, false);
} else {
AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts);
@@ -616,11 +603,11 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
for (auto &Include : IncludePath)
if (Include.first == System || Include.first == ExternCSystem ||
- (!Lang.ObjC1 && !Lang.CPlusPlus && Include.first == CSystem) ||
- (/*FIXME !Lang.ObjC1 && */ Lang.CPlusPlus &&
+ (!Lang.ObjC && !Lang.CPlusPlus && Include.first == CSystem) ||
+ (/*FIXME !Lang.ObjC && */ Lang.CPlusPlus &&
Include.first == CXXSystem) ||
- (Lang.ObjC1 && !Lang.CPlusPlus && Include.first == ObjCSystem) ||
- (Lang.ObjC1 && Lang.CPlusPlus && Include.first == ObjCXXSystem))
+ (Lang.ObjC && !Lang.CPlusPlus && Include.first == ObjCSystem) ||
+ (Lang.ObjC && Lang.CPlusPlus && Include.first == ObjCXXSystem))
SearchList.push_back(Include.second);
for (auto &Include : IncludePath)
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index e3f4f92b9d1e..66807b097d40 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -21,7 +21,6 @@
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTReader.h"
@@ -76,23 +75,6 @@ static void AddImplicitIncludeMacros(MacroBuilder &Builder, StringRef File) {
Builder.append("##"); // ##?
}
-/// AddImplicitIncludePTH - Add an implicit \#include using the original file
-/// used to generate a PTH cache.
-static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
- StringRef ImplicitIncludePTH) {
- PTHManager *P = PP.getPTHManager();
- // Null check 'P' in the corner case where it couldn't be created.
- const char *OriginalFile = P ? P->getOriginalSourceFile() : nullptr;
-
- if (!OriginalFile) {
- PP.getDiagnostics().Report(diag::err_fe_pth_file_has_no_source_header)
- << ImplicitIncludePTH;
- return;
- }
-
- AddImplicitInclude(Builder, OriginalFile);
-}
-
/// Add an implicit \#include using the original file used to generate
/// a PCH file.
static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP,
@@ -421,7 +403,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__STDC_UTF_16__", "1");
Builder.defineMacro("__STDC_UTF_32__", "1");
- if (LangOpts.ObjC1)
+ if (LangOpts.ObjC)
Builder.defineMacro("__OBJC__");
// OpenCL v1.0/1.1 s6.9, v1.2/2.0 s6.10: Preprocessor Directives and Macros.
@@ -553,20 +535,21 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L");
Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L");
}
- if (LangOpts.AlignedAllocation)
+ if (LangOpts.AlignedAllocation && !LangOpts.AlignedAllocationUnavailable)
Builder.defineMacro("__cpp_aligned_new", "201606L");
if (LangOpts.RelaxedTemplateTemplateArgs)
Builder.defineMacro("__cpp_template_template_args", "201611L");
+ // C++20 features.
+ if (LangOpts.Char8)
+ Builder.defineMacro("__cpp_char8_t", "201811L");
+ Builder.defineMacro("__cpp_impl_destroying_delete", "201806L");
+
// TS features.
if (LangOpts.ConceptsTS)
Builder.defineMacro("__cpp_experimental_concepts", "1L");
if (LangOpts.CoroutinesTS)
Builder.defineMacro("__cpp_coroutines", "201703L");
-
- // Potential future breaking changes.
- if (LangOpts.Char8)
- Builder.defineMacro("__cpp_char8_t", "201803L");
}
static void InitializePredefinedMacros(const TargetInfo &TI,
@@ -635,7 +618,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (!LangOpts.MSVCCompat && LangOpts.CPlusPlus11)
Builder.defineMacro("__GXX_EXPERIMENTAL_CXX0X__");
- if (LangOpts.ObjC1) {
+ if (LangOpts.ObjC) {
if (LangOpts.ObjCRuntime.isNonFragile()) {
Builder.defineMacro("__OBJC2__");
@@ -699,7 +682,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (!LangOpts.NoConstantCFStrings)
Builder.defineMacro("__CONSTANT_CFSTRINGS__");
- if (LangOpts.ObjC2)
+ if (LangOpts.ObjC)
Builder.defineMacro("OBJC_NEW_PROPERTIES");
if (LangOpts.PascalStrings)
@@ -1016,7 +999,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
Builder.defineMacro("__autoreleasing", "");
Builder.defineMacro("__unsafe_unretained", "");
- } else if (LangOpts.ObjC1) {
+ } else if (LangOpts.ObjC) {
Builder.defineMacro("__weak", "__attribute__((objc_ownership(weak)))");
Builder.defineMacro("__strong", "__attribute__((objc_ownership(strong)))");
Builder.defineMacro("__autoreleasing",
@@ -1130,7 +1113,7 @@ void clang::InitializePreprocessor(
// Install definitions to make Objective-C++ ARC work well with various
// C++ Standard Library implementations.
- if (LangOpts.ObjC1 && LangOpts.CPlusPlus &&
+ if (LangOpts.ObjC && LangOpts.CPlusPlus &&
(LangOpts.ObjCAutoRefCount || LangOpts.ObjCWeak)) {
switch (InitOpts.ObjCXXARCStandardLibrary) {
case ARCXX_nolib:
@@ -1177,8 +1160,6 @@ void clang::InitializePreprocessor(
if (!InitOpts.ImplicitPCHInclude.empty())
AddImplicitIncludePCH(Builder, PP, PCHContainerRdr,
InitOpts.ImplicitPCHInclude);
- if (!InitOpts.ImplicitPTHInclude.empty())
- AddImplicitIncludePTH(Builder, PP, InitOpts.ImplicitPTHInclude);
// Process -include directives.
for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp
index 25cad8be6d00..fa8efcc3b53c 100644
--- a/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/lib/Frontend/ModuleDependencyCollector.cpp
@@ -156,10 +156,6 @@ void ModuleDependencyCollector::writeFileMap() {
// allows crash reproducer scripts to work across machines.
VFSWriter.setOverlayDir(VFSDir);
- // Do not ignore non existent contents otherwise we might skip something
- // that should have been collected here.
- VFSWriter.setIgnoreNonExistentContents(false);
-
// Explicitly set case sensitivity for the YAML writer. For that, find out
// the sensitivity at the path where the headers all collected to.
VFSWriter.setCaseSensitivity(isCaseSensitivePath(VFSDir));
diff --git a/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp
index 30ae2db26d86..1930af187e7a 100644
--- a/lib/Frontend/PrecompiledPreamble.cpp
+++ b/lib/Frontend/PrecompiledPreamble.cpp
@@ -14,7 +14,6 @@
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
@@ -30,6 +29,7 @@
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <limits>
#include <utility>
@@ -48,17 +48,17 @@ StringRef getInMemoryPreamblePath() {
#endif
}
-IntrusiveRefCntPtr<vfs::FileSystem>
+IntrusiveRefCntPtr<llvm::vfs::FileSystem>
createVFSOverlayForPreamblePCH(StringRef PCHFilename,
std::unique_ptr<llvm::MemoryBuffer> PCHBuffer,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
// We want only the PCH file from the real filesystem to be available,
// so we create an in-memory VFS with just that and overlay it on top.
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> PCHFS(
- new vfs::InMemoryFileSystem());
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> PCHFS(
+ new llvm::vfs::InMemoryFileSystem());
PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer));
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
- new vfs::OverlayFileSystem(VFS));
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> Overlay(
+ new llvm::vfs::OverlayFileSystem(VFS));
Overlay->pushOverlay(PCHFS);
return Overlay;
}
@@ -232,14 +232,12 @@ PreambleBounds clang::ComputePreambleBounds(const LangOptions &LangOpts,
llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
- DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ DiagnosticsEngine &Diagnostics,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps, bool StoreInMemory,
PreambleCallbacks &Callbacks) {
assert(VFS && "VFS is null");
- if (!Bounds.Size)
- return BuildPreambleError::PreambleIsEmpty;
-
auto PreambleInvocation = std::make_shared<CompilerInvocation>(Invocation);
FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
PreprocessorOptions &PreprocessorOpts =
@@ -413,7 +411,7 @@ std::size_t PrecompiledPreamble::getSize() const {
bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer,
PreambleBounds Bounds,
- vfs::FileSystem *VFS) const {
+ llvm::vfs::FileSystem *VFS) const {
assert(
Bounds.Size <= MainFileBuffer->getBufferSize() &&
@@ -423,17 +421,14 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
PreprocessorOptions &PreprocessorOpts =
PreambleInvocation->getPreprocessorOpts();
- if (!Bounds.Size)
- return false;
-
// We've previously computed a preamble. Check whether we have the same
// preamble now that we did before, and that there's enough space in
// the main-file buffer within the precompiled preamble to fit the
// new main file.
if (PreambleBytes.size() != Bounds.Size ||
PreambleEndsAtStartOfLine != Bounds.PreambleEndsAtStartOfLine ||
- memcmp(PreambleBytes.data(), MainFileBuffer->getBufferStart(),
- Bounds.Size) != 0)
+ !std::equal(PreambleBytes.begin(), PreambleBytes.end(),
+ MainFileBuffer->getBuffer().begin()))
return false;
// The preamble has not changed. We may be able to re-use the precompiled
// preamble.
@@ -443,7 +438,7 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
// remapping or unsaved_files.
std::map<llvm::sys::fs::UniqueID, PreambleFileHash> OverriddenFiles;
for (const auto &R : PreprocessorOpts.RemappedFiles) {
- vfs::Status Status;
+ llvm::vfs::Status Status;
if (!moveOnNoError(VFS->status(R.second), Status)) {
// If we can't stat the file we're remapping to, assume that something
// horrible happened.
@@ -455,7 +450,7 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
}
for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
- vfs::Status Status;
+ llvm::vfs::Status Status;
if (!moveOnNoError(VFS->status(RB.first), Status))
return false;
@@ -465,7 +460,7 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
// Check whether anything has changed.
for (const auto &F : FilesInPreamble) {
- vfs::Status Status;
+ llvm::vfs::Status Status;
if (!moveOnNoError(VFS->status(F.first()), Status)) {
// If we can't stat the file, assume that something horrible happened.
return false;
@@ -491,14 +486,14 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation,
}
void PrecompiledPreamble::AddImplicitPreamble(
- CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ CompilerInvocation &CI, IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
llvm::MemoryBuffer *MainFileBuffer) const {
PreambleBounds Bounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
configurePreamble(Bounds, CI, VFS, MainFileBuffer);
}
void PrecompiledPreamble::OverridePreamble(
- CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ CompilerInvocation &CI, IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
llvm::MemoryBuffer *MainFileBuffer) const {
auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), MainFileBuffer, 0);
configurePreamble(Bounds, CI, VFS, MainFileBuffer);
@@ -686,7 +681,7 @@ PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
void PrecompiledPreamble::configurePreamble(
PreambleBounds Bounds, CompilerInvocation &CI,
- IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
llvm::MemoryBuffer *MainFileBuffer) const {
assert(VFS);
@@ -707,13 +702,14 @@ void PrecompiledPreamble::configurePreamble(
void PrecompiledPreamble::setupPreambleStorage(
const PCHStorage &Storage, PreprocessorOptions &PreprocessorOpts,
- IntrusiveRefCntPtr<vfs::FileSystem> &VFS) {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS) {
if (Storage.getKind() == PCHStorage::Kind::TempFile) {
const TempPCHFile &PCHFile = Storage.asFile();
PreprocessorOpts.ImplicitPCHInclude = PCHFile.getFilePath();
// Make sure we can access the PCH file even if we're using a VFS
- IntrusiveRefCntPtr<vfs::FileSystem> RealFS = vfs::getRealFileSystem();
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> RealFS =
+ llvm::vfs::getRealFileSystem();
auto PCHPath = PCHFile.getFilePath();
if (VFS == RealFS || VFS->exists(PCHPath))
return;
@@ -748,8 +744,10 @@ std::unique_ptr<PPCallbacks> PreambleCallbacks::createPPCallbacks() {
return nullptr;
}
+static llvm::ManagedStatic<BuildPreambleErrorCategory> BuildPreambleErrCategory;
+
std::error_code clang::make_error_code(BuildPreambleError Error) {
- return std::error_code(static_cast<int>(Error), BuildPreambleErrorCategory());
+ return std::error_code(static_cast<int>(Error), *BuildPreambleErrCategory);
}
const char *BuildPreambleErrorCategory::name() const noexcept {
@@ -758,8 +756,6 @@ const char *BuildPreambleErrorCategory::name() const noexcept {
std::string BuildPreambleErrorCategory::message(int condition) const {
switch (static_cast<BuildPreambleError>(condition)) {
- case BuildPreambleError::PreambleIsEmpty:
- return "Preamble is empty";
case BuildPreambleError::CouldntCreateTempFile:
return "Could not create temporary file for PCH";
case BuildPreambleError::CouldntCreateTargetInfo:
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 69cd072ea57f..3b835985a54c 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -750,6 +750,11 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
reinterpret_cast<Module *>(Tok.getAnnotationValue()));
PP.Lex(Tok);
continue;
+ } else if (Tok.isAnnotation()) {
+ // Ignore annotation tokens created by pragmas - the pragmas themselves
+ // will be reproduced in the preprocessed output.
+ PP.Lex(Tok);
+ continue;
} else if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
OS << II->getName();
} else if (Tok.isLiteral() && !Tok.needsCleaning() &&
diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp
index fa17b3e7cb3f..bcf6d215c998 100644
--- a/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -181,7 +181,7 @@ RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
void RewriteMacrosAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
std::unique_ptr<raw_ostream> OS =
- CI.createDefaultOutputFile(true, getCurrentFile());
+ CI.createDefaultOutputFile(true, getCurrentFileOrBufferName());
if (!OS) return;
RewriteMacrosInInput(CI.getPreprocessor(), OS.get());
@@ -190,7 +190,7 @@ void RewriteMacrosAction::ExecuteAction() {
void RewriteTestAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
std::unique_ptr<raw_ostream> OS =
- CI.createDefaultOutputFile(false, getCurrentFile());
+ CI.createDefaultOutputFile(false, getCurrentFileOrBufferName());
if (!OS) return;
DoRewriteTest(CI.getPreprocessor(), OS.get());
@@ -265,7 +265,8 @@ public:
bool RewriteIncludesAction::BeginSourceFileAction(CompilerInstance &CI) {
if (!OutputStream) {
- OutputStream = CI.createDefaultOutputFile(true, getCurrentFile());
+ OutputStream =
+ CI.createDefaultOutputFile(true, getCurrentFileOrBufferName());
if (!OutputStream)
return false;
}
diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp
index 1631eccd7013..2e7baa3d9581 100644
--- a/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -586,6 +586,7 @@ void InclusionRewriter::Process(FileID FileId,
LocalEOL, Line, /*EnsureNewline=*/ true);
WriteLineInfo(FileName, Line, FileType);
RawLex.SetKeepWhitespaceMode(false);
+ break;
}
default:
break;
diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 36382e1438d5..10ca9a785699 100644
--- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -265,8 +265,8 @@ namespace {
// Measure the old text.
int Size = Rewrite.getRangeSize(SrcRange);
if (Size == -1) {
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
+ Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
+ << Old->getSourceRange();
return;
}
// Get the new text.
@@ -282,8 +282,8 @@ namespace {
}
if (SilenceRewriteMacroWarning)
return;
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
+ Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
+ << Old->getSourceRange();
}
void InsertText(SourceLocation Loc, StringRef Str,
@@ -541,7 +541,7 @@ namespace {
// FIXME: This predicate seems like it would be useful to add to ASTContext.
bool isObjCType(QualType T) {
- if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
+ if (!LangOpts.ObjC)
return false;
QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
@@ -748,11 +748,11 @@ void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
if (!IFace->isThisDeclarationADefinition()) {
SmallVector<Decl *, 8> DG;
- SourceLocation StartLoc = IFace->getLocStart();
+ SourceLocation StartLoc = IFace->getBeginLoc();
do {
if (isa<ObjCInterfaceDecl>(*DI) &&
!cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
- StartLoc == (*DI)->getLocStart())
+ StartLoc == (*DI)->getBeginLoc())
DG.push_back(*DI);
else
break;
@@ -773,11 +773,11 @@ void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
if (!Proto->isThisDeclarationADefinition()) {
SmallVector<Decl *, 8> DG;
- SourceLocation StartLoc = Proto->getLocStart();
+ SourceLocation StartLoc = Proto->getBeginLoc();
do {
if (isa<ObjCProtocolDecl>(*DI) &&
!cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
- StartLoc == (*DI)->getLocStart())
+ StartLoc == (*DI)->getBeginLoc())
DG.push_back(*DI);
else
break;
@@ -923,17 +923,16 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
static bool objcSetPropertyDefined = false;
SourceLocation startGetterSetterLoc;
- if (PID->getLocStart().isValid()) {
- SourceLocation startLoc = PID->getLocStart();
+ if (PID->getBeginLoc().isValid()) {
+ SourceLocation startLoc = PID->getBeginLoc();
InsertText(startLoc, "// ");
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @synthesize location");
const char *semiBuf = strchr(startBuf, ';');
assert((*semiBuf == ';') && "@synthesize: can't find ';'");
startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
- }
- else
- startGetterSetterLoc = IMD ? IMD->getLocEnd() : CID->getLocEnd();
+ } else
+ startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc();
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
return; // FIXME: is this correct?
@@ -1061,7 +1060,7 @@ static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
const std::string &typedefString) {
- SourceLocation startLoc = ClassDecl->getLocStart();
+ SourceLocation startLoc = ClassDecl->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
const char *semiPtr = strchr(startBuf, ';');
// Replace the @class with typedefs corresponding to the classes.
@@ -1109,8 +1108,8 @@ void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
// nothing to rewrite.
if (Method->isImplicit())
return;
- SourceLocation LocStart = Method->getLocStart();
- SourceLocation LocEnd = Method->getLocEnd();
+ SourceLocation LocStart = Method->getBeginLoc();
+ SourceLocation LocEnd = Method->getEndLoc();
if (SM->getExpansionLineNumber(LocEnd) >
SM->getExpansionLineNumber(LocStart)) {
@@ -1129,7 +1128,7 @@ void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {
}
void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
- SourceLocation LocStart = CatDecl->getLocStart();
+ SourceLocation LocStart = CatDecl->getBeginLoc();
// FIXME: handle category headers that are declared across multiple lines.
if (CatDecl->getIvarRBraceLoc().isValid()) {
@@ -1154,7 +1153,7 @@ void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
}
void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
- SourceLocation LocStart = PDecl->getLocStart();
+ SourceLocation LocStart = PDecl->getBeginLoc();
assert(PDecl->isThisDeclarationADefinition());
// FIXME: handle protocol headers that are declared across multiple lines.
@@ -1189,7 +1188,7 @@ void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
}
void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
- SourceLocation LocStart = (*D.begin())->getLocStart();
+ SourceLocation LocStart = (*D.begin())->getBeginLoc();
if (LocStart.isInvalid())
llvm_unreachable("Invalid SourceLocation");
// FIXME: handle forward protocol that are declared across multiple lines.
@@ -1198,7 +1197,7 @@ void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
void
RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
- SourceLocation LocStart = DG[0]->getLocStart();
+ SourceLocation LocStart = DG[0]->getBeginLoc();
if (LocStart.isInvalid())
llvm_unreachable("Invalid SourceLocation");
// FIXME: handle forward protocol that are declared across multiple lines.
@@ -1338,21 +1337,21 @@ void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
if (IMD) {
if (IMD->getIvarRBraceLoc().isValid()) {
- ReplaceText(IMD->getLocStart(), 1, "/** ");
+ ReplaceText(IMD->getBeginLoc(), 1, "/** ");
ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ ");
}
else {
- InsertText(IMD->getLocStart(), "// ");
+ InsertText(IMD->getBeginLoc(), "// ");
}
}
else
- InsertText(CID->getLocStart(), "// ");
+ InsertText(CID->getBeginLoc(), "// ");
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
- SourceLocation LocStart = OMD->getLocStart();
- SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+ SourceLocation LocStart = OMD->getBeginLoc();
+ SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
@@ -1362,8 +1361,8 @@ void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
- SourceLocation LocStart = OMD->getLocStart();
- SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+ SourceLocation LocStart = OMD->getBeginLoc();
+ SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
@@ -1372,7 +1371,7 @@ void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())
RewritePropertyImplDecl(I, IMD, CID);
- InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// ");
+ InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");
}
void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
@@ -1608,7 +1607,7 @@ Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {
// replace break with goto __break_label
std::string buf;
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
buf = "goto __break_label_";
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("break"), buf);
@@ -1638,7 +1637,7 @@ Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {
// replace continue with goto __continue_label
std::string buf;
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
buf = "goto __continue_label_";
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("continue"), buf);
@@ -1686,7 +1685,7 @@ Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
assert(!ObjCBcLabelNo.empty() &&
"ObjCForCollectionStmt - Label No stack empty");
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
StringRef elementName;
std::string elementTypeAsString;
@@ -1860,7 +1859,7 @@ static void Write_RethrowObject(std::string &buf) {
///
Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
// Get the start location and compute the semi location.
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @synchronized location");
@@ -1880,20 +1879,20 @@ Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S)
buf += "\n\tid sync_exit;";
buf += "\n\t} _sync_exit(_sync_obj);\n";
- // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
+ // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since
// the sync expression is typically a message expression that's already
// been rewritten! (which implies the SourceLocation's are invalid).
- SourceLocation RParenExprLoc = S->getSynchBody()->getLocStart();
+ SourceLocation RParenExprLoc = S->getSynchBody()->getBeginLoc();
const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);
while (*RParenExprLocBuf != ')') RParenExprLocBuf--;
RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);
- SourceLocation LBranceLoc = S->getSynchBody()->getLocStart();
+ SourceLocation LBranceLoc = S->getSynchBody()->getBeginLoc();
const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);
assert (*LBraceLocBuf == '{');
ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);
- SourceLocation startRBraceLoc = S->getSynchBody()->getLocEnd();
+ SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc();
assert((*SM->getCharacterData(startRBraceLoc) == '}') &&
"bogus @synchronized block");
@@ -1915,7 +1914,7 @@ void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
WarnAboutReturnGotoStmts(SubStmt);
if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
- Diags.Report(Context->getFullLoc(S->getLocStart()),
+ Diags.Report(Context->getFullLoc(S->getBeginLoc()),
TryFinallyContainsReturnDiag);
}
}
@@ -1923,7 +1922,7 @@ void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
SourceLocation startLoc = S->getAtLoc();
ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");
- ReplaceText(S->getSubStmt()->getLocStart(), 1,
+ ReplaceText(S->getSubStmt()->getBeginLoc(), 1,
"{ __AtAutoreleasePool __autoreleasepool; ");
return nullptr;
@@ -1944,7 +1943,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
}
}
// Get the start location and compute the semi location.
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @try location");
@@ -1958,7 +1957,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
VarDecl *catchDecl = Catch->getCatchParamDecl();
- startLoc = Catch->getLocStart();
+ startLoc = Catch->getBeginLoc();
bool AtRemoved = false;
if (catchDecl) {
QualType t = catchDecl->getType();
@@ -1967,7 +1966,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
if (IDecl) {
std::string Result;
- ConvertSourceLocationToLineDirective(Catch->getLocStart(), Result);
+ ConvertSourceLocationToLineDirective(Catch->getBeginLoc(), Result);
startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @catch location");
@@ -1988,7 +1987,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
Result += "_"; Result += catchDecl->getNameAsString();
Result += "; ";
- SourceLocation lBraceLoc = Catch->getCatchBody()->getLocStart();
+ SourceLocation lBraceLoc = Catch->getCatchBody()->getBeginLoc();
ReplaceText(lBraceLoc, 1, Result);
AtRemoved = true;
}
@@ -2001,7 +2000,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
}
if (finalStmt) {
buf.clear();
- SourceLocation FinallyLoc = finalStmt->getLocStart();
+ SourceLocation FinallyLoc = finalStmt->getBeginLoc();
if (noCatch) {
ConvertSourceLocationToLineDirective(FinallyLoc, buf);
@@ -2013,15 +2012,15 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
buf += "catch (id e) {_rethrow = e;}\n";
}
- SourceLocation startFinalLoc = finalStmt->getLocStart();
+ SourceLocation startFinalLoc = finalStmt->getBeginLoc();
ReplaceText(startFinalLoc, 8, buf);
Stmt *body = finalStmt->getFinallyBody();
- SourceLocation startFinalBodyLoc = body->getLocStart();
+ SourceLocation startFinalBodyLoc = body->getBeginLoc();
buf.clear();
Write_RethrowObject(buf);
ReplaceText(startFinalBodyLoc, 1, buf);
- SourceLocation endFinalBodyLoc = body->getLocEnd();
+ SourceLocation endFinalBodyLoc = body->getEndLoc();
ReplaceText(endFinalBodyLoc, 1, "}\n}");
// Now check for any return/continue/go statements within the @try.
WarnAboutReturnGotoStmts(S->getTryBody());
@@ -2035,7 +2034,7 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
// been rewritten! (which implies the SourceLocation's are invalid).
Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
// Get the start location and compute the semi location.
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @throw location");
@@ -2052,7 +2051,7 @@ Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
assert((*wBuf == 'w') && "@throw: can't find 'w'");
ReplaceText(startLoc, wBuf-startBuf+1, buf);
- SourceLocation endLoc = S->getLocEnd();
+ SourceLocation endLoc = S->getEndLoc();
const char *endBuf = SM->getCharacterData(endLoc);
const char *semiBuf = strchr(endBuf, ';');
assert((*semiBuf == ';') && "@throw: can't find ';'");
@@ -2097,8 +2096,8 @@ RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
QualType msgSendType = FD->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE =
- new (Context) DeclRefExpr(FD, false, msgSendType, VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,
+ VK_LValue, SourceLocation());
// Now, we cast the reference to a pointer to the objc_msgSend type.
QualType pToFunc = Context->getPointerType(msgSendType);
@@ -2108,9 +2107,8 @@ RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *Exp = new (Context) CallExpr(*Context, ICE, Args,
- FT->getCallResultType(*Context),
- VK_RValue, EndLoc);
+ CallExpr *Exp = CallExpr::Create(
+ *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc);
return Exp;
}
@@ -2170,8 +2168,8 @@ void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
Loc = ECE->getLParenLoc();
EndLoc = ECE->getRParenLoc();
} else {
- Loc = E->getLocStart();
- EndLoc = E->getLocEnd();
+ Loc = E->getBeginLoc();
+ EndLoc = E->getEndLoc();
}
// This will defend against trying to rewrite synthesized expressions.
if (Loc.isInvalid() || EndLoc.isInvalid())
@@ -2296,13 +2294,13 @@ void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
startLoc = ECE->getLParenLoc();
else
- startLoc = E->getLocStart();
+ startLoc = E->getBeginLoc();
startLoc = SM->getExpansionLoc(startLoc);
const char *endBuf = SM->getCharacterData(startLoc);
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
}
else {
- SourceLocation X = ND->getLocEnd();
+ SourceLocation X = ND->getEndLoc();
X = SM->getExpansionLoc(X);
const char *endBuf = SM->getCharacterData(X);
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
@@ -2585,12 +2583,11 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(S),
strType, nullptr, SC_Static);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
- SourceLocation());
- Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
- Context->getPointerType(DRE->getType()),
- VK_RValue, OK_Ordinary,
- SourceLocation(), false);
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
+ Expr *Unop = new (Context)
+ UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()),
+ VK_RValue, OK_Ordinary, SourceLocation(), false);
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_CPointerToObjCPointerCast, Unop);
@@ -2625,8 +2622,8 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
SynthGetClassFunctionDecl();
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
- SourceLocation StartLoc = Exp->getLocStart();
- SourceLocation EndLoc = Exp->getLocEnd();
+ SourceLocation StartLoc = Exp->getBeginLoc();
+ SourceLocation EndLoc = Exp->getEndLoc();
// Synthesize a call to objc_msgSend().
SmallVector<Expr*, 4> MsgExprs;
@@ -2674,12 +2671,11 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
QualType msgSendType = MsgSendFlavor->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
- VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(
+ *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
- CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
- Context->getPointerType(Context->VoidTy),
- CK_BitCast, DRE);
+ CastExpr *cast = NoTypeInfoCStyleCastExpr(
+ Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
// Now do the "normal" pointer to function cast.
QualType castType =
@@ -2692,8 +2688,8 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *CE = new (Context)
- CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
+ CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
+ VK_RValue, EndLoc);
ReplaceStmt(Exp, CE);
return CE;
}
@@ -2709,8 +2705,8 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
SynthGetClassFunctionDecl();
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
- SourceLocation StartLoc = Exp->getLocStart();
- SourceLocation EndLoc = Exp->getLocEnd();
+ SourceLocation StartLoc = Exp->getBeginLoc();
+ SourceLocation EndLoc = Exp->getEndLoc();
// Build the expression: __NSContainer_literal(int, ...).arr
QualType IntQT = Context->IntTy;
@@ -2718,9 +2714,8 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
getSimpleFunctionType(Context->VoidTy, IntQT, true);
std::string NSArrayFName("__NSContainer_literal");
FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);
- DeclRefExpr *NSArrayDRE =
- new (Context) DeclRefExpr(NSArrayFD, false, NSArrayFType, VK_RValue,
- SourceLocation());
+ DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr(
+ *Context, NSArrayFD, false, NSArrayFType, VK_RValue, SourceLocation());
SmallVector<Expr*, 16> InitExprs;
unsigned NumElements = Exp->getNumElements();
@@ -2733,8 +2728,8 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
for (unsigned i = 0; i < NumElements; i++)
InitExprs.push_back(Exp->getElement(i));
Expr *NSArrayCallExpr =
- new (Context) CallExpr(*Context, NSArrayDRE, InitExprs,
- NSArrayFType, VK_LValue, SourceLocation());
+ CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue,
+ SourceLocation());
FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -2797,12 +2792,11 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
QualType msgSendType = MsgSendFlavor->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
- VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(
+ *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
- CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
- Context->getPointerType(Context->VoidTy),
- CK_BitCast, DRE);
+ CastExpr *cast = NoTypeInfoCStyleCastExpr(
+ Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
// Now do the "normal" pointer to function cast.
QualType castType =
@@ -2815,8 +2809,8 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *CE = new (Context)
- CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
+ CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
+ VK_RValue, EndLoc);
ReplaceStmt(Exp, CE);
return CE;
}
@@ -2832,8 +2826,8 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
SynthGetClassFunctionDecl();
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
- SourceLocation StartLoc = Exp->getLocStart();
- SourceLocation EndLoc = Exp->getLocEnd();
+ SourceLocation StartLoc = Exp->getBeginLoc();
+ SourceLocation EndLoc = Exp->getEndLoc();
// Build the expression: __NSContainer_literal(int, ...).arr
QualType IntQT = Context->IntTy;
@@ -2841,9 +2835,8 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
getSimpleFunctionType(Context->VoidTy, IntQT, true);
std::string NSDictFName("__NSContainer_literal");
FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);
- DeclRefExpr *NSDictDRE =
- new (Context) DeclRefExpr(NSDictFD, false, NSDictFType, VK_RValue,
- SourceLocation());
+ DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr(
+ *Context, NSDictFD, false, NSDictFType, VK_RValue, SourceLocation());
SmallVector<Expr*, 16> KeyExprs;
SmallVector<Expr*, 16> ValueExprs;
@@ -2864,8 +2857,8 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
// (const id [])objects
Expr *NSValueCallExpr =
- new (Context) CallExpr(*Context, NSDictDRE, ValueExprs,
- NSDictFType, VK_LValue, SourceLocation());
+ CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue,
+ SourceLocation());
FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -2883,9 +2876,8 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
CK_BitCast,
DictLiteralValueME);
// (const id <NSCopying> [])keys
- Expr *NSKeyCallExpr =
- new (Context) CallExpr(*Context, NSDictDRE, KeyExprs,
- NSDictFType, VK_LValue, SourceLocation());
+ Expr *NSKeyCallExpr = CallExpr::Create(
+ *Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation());
MemberExpr *DictLiteralKeyME = new (Context)
MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
@@ -2951,12 +2943,11 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
QualType msgSendType = MsgSendFlavor->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
- VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(
+ *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
- CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
- Context->getPointerType(Context->VoidTy),
- CK_BitCast, DRE);
+ CastExpr *cast = NoTypeInfoCStyleCastExpr(
+ Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
// Now do the "normal" pointer to function cast.
QualType castType =
@@ -2969,8 +2960,8 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *CE = new (Context)
- CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
+ CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
+ VK_RValue, EndLoc);
ReplaceStmt(Exp, CE);
return CE;
}
@@ -3070,7 +3061,7 @@ void RewriteModernObjC::RewriteLineDirective(const Decl *D) {
LineString += "\"";
else LineString += "\"\n";
- Location = D->getLocStart();
+ Location = D->getBeginLoc();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isExternC() && !FD->isMain()) {
const DeclContext *DC = FD->getDeclContext();
@@ -3100,10 +3091,9 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
SmallVectorImpl<Expr*> &MsgExprs,
ObjCMethodDecl *Method) {
// Now do the "normal" pointer to function cast.
- QualType castType = getSimpleFunctionType(returnType, ArgTypes,
- Method ? Method->isVariadic()
- : false);
- castType = Context->getPointerType(castType);
+ QualType FuncType = getSimpleFunctionType(
+ returnType, ArgTypes, Method ? Method->isVariadic() : false);
+ QualType castType = Context->getPointerType(FuncType);
// build type for containing the objc_msgSend_stret object.
static unsigned stretCount=0;
@@ -3169,7 +3159,7 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
else {
assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null");
- FunLocStart = CurMethodDef->getLocStart();
+ FunLocStart = CurMethodDef->getBeginLoc();
}
InsertText(FunLocStart, str);
@@ -3177,13 +3167,13 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
// AST for __Stretn(receiver, args).s;
IdentifierInfo *ID = &Context->Idents.get(name);
- FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
- SourceLocation(), ID, castType,
- nullptr, SC_Extern, false, false);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue,
- SourceLocation());
- CallExpr *STCE = new (Context) CallExpr(*Context, DRE, MsgExprs,
- castType, VK_LValue, SourceLocation());
+ FunctionDecl *FD =
+ FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(),
+ ID, FuncType, nullptr, SC_Extern, false, false);
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, FD, false, castType, VK_RValue, SourceLocation());
+ CallExpr *STCE = CallExpr::Create(*Context, DRE, MsgExprs, castType,
+ VK_LValue, SourceLocation());
FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -3249,7 +3239,8 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
InitExprs.push_back(
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
CK_BitCast,
- new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+ new (Context) DeclRefExpr(*Context,
+ CurMethodDef->getSelfDecl(),
false,
Context->getObjCIdType(),
VK_RValue,
@@ -3280,12 +3271,11 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
if (LangOpts.MicrosoftExt) {
SynthSuperConstructorFunctionDecl();
// Simulate a constructor call...
- DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl,
- false, superType, VK_LValue,
- SourceLocation());
- SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs,
- superType, VK_LValue,
- SourceLocation());
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
+ VK_LValue, SourceLocation());
+ SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
+ VK_LValue, SourceLocation());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -3345,7 +3335,8 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
InitExprs.push_back(
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
CK_BitCast,
- new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+ new (Context) DeclRefExpr(*Context,
+ CurMethodDef->getSelfDecl(),
false,
Context->getObjCIdType(),
VK_RValue, SourceLocation()))
@@ -3375,11 +3366,11 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
if (LangOpts.MicrosoftExt) {
SynthSuperConstructorFunctionDecl();
// Simulate a constructor call...
- DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl,
- false, superType, VK_LValue,
- SourceLocation());
- SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs,
- superType, VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
+ VK_LValue, SourceLocation());
+ SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
+ VK_LValue, SourceLocation());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -3519,8 +3510,8 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
QualType msgSendType = MsgSendFlavor->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
- VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(
+ *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
// Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
// If we don't do this cast, we get the following bizarre warning/note:
@@ -3543,8 +3534,8 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *CE = new (Context)
- CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
+ CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
+ VK_RValue, EndLoc);
Stmt *ReplacingStmt = CE;
if (MsgSendStretFlavor) {
// We have the method which returns a struct/union. Must also generate
@@ -3563,8 +3554,8 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
}
Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
- Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(),
- Exp->getLocEnd());
+ Stmt *ReplacingStmt =
+ SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());
// Now do the actual rewrite.
ReplaceStmt(Exp, ReplacingStmt);
@@ -3597,10 +3588,9 @@ Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), ID, getProtocolType(),
nullptr, SC_Extern);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
- VK_LValue, SourceLocation());
- CastExpr *castExpr =
- NoTypeInfoCStyleCastExpr(
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(
+ *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(
Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE);
ReplaceStmt(Exp, castExpr);
ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
@@ -3896,7 +3886,7 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
IVD; IVD = IVD->getNextIvar())
IVars.push_back(IVD);
- SourceLocation LocStart = CDecl->getLocStart();
+ SourceLocation LocStart = CDecl->getBeginLoc();
SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
const char *startBuf = SM->getCharacterData(LocStart);
@@ -4461,9 +4451,9 @@ static void BuildUniqueMethodName(std::string &Name,
}
void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
- //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
- //SourceLocation FunLocStart = MD->getLocStart();
- SourceLocation FunLocStart = MD->getLocStart();
+ // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
+ // SourceLocation FunLocStart = MD->getBeginLoc();
+ SourceLocation FunLocStart = MD->getBeginLoc();
std::string FuncName;
BuildUniqueMethodName(FuncName, MD);
SynthesizeBlockLiterals(FunLocStart, FuncName);
@@ -4656,9 +4646,8 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp
E = Exp->arg_end(); I != E; ++I) {
BlkExprs.push_back(*I);
}
- CallExpr *CE = new (Context) CallExpr(*Context, PE, BlkExprs,
- Exp->getType(), VK_RValue,
- SourceLocation());
+ CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(),
+ VK_RValue, SourceLocation());
return CE;
}
@@ -4778,7 +4767,7 @@ void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
std::string Str = "(";
Str += TypeString;
Str += ")";
- InsertText(IC->getSubExpr()->getLocStart(), Str);
+ InsertText(IC->getSubExpr()->getBeginLoc(), Str);
}
void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
@@ -5036,7 +5025,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
// Use variable's location which is good for this case.
DeclLoc = ND->getLocation();
const char *startBuf = SM->getCharacterData(DeclLoc);
- SourceLocation X = ND->getLocEnd();
+ SourceLocation X = ND->getEndLoc();
X = SM->getExpansionLoc(X);
const char *endBuf = SM->getCharacterData(X);
std::string Name(ND->getNameAsString());
@@ -5069,7 +5058,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
else {
assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
- FunLocStart = CurMethodDef->getLocStart();
+ FunLocStart = CurMethodDef->getBeginLoc();
}
InsertText(FunLocStart, ByrefType);
@@ -5156,7 +5145,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
startLoc = ECE->getLParenLoc();
else
- startLoc = E->getLocStart();
+ startLoc = E->getBeginLoc();
startLoc = SM->getExpansionLoc(startLoc);
endBuf = SM->getCharacterData(startLoc);
ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
@@ -5287,15 +5276,15 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
Tag += FuncName + "_block_impl_" + BlockNumber;
FD = SynthBlockInitFunctionDecl(Tag);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue,
- SourceLocation());
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, FD, false, FType, VK_RValue, SourceLocation());
SmallVector<Expr*, 4> InitExprs;
// Initialize the block function.
FD = SynthBlockInitFunctionDecl(Func);
- DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(),
- VK_LValue, SourceLocation());
+ DeclRefExpr *Arg = new (Context) DeclRefExpr(
+ *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
CK_BitCast, Arg);
InitExprs.push_back(castExpr);
@@ -5306,15 +5295,11 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
VarDecl *NewVD = VarDecl::Create(
*Context, TUDecl, SourceLocation(), SourceLocation(),
&Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
- UnaryOperator *DescRefExpr =
- new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
- Context->VoidPtrTy,
- VK_LValue,
- SourceLocation()),
- UO_AddrOf,
- Context->getPointerType(Context->VoidPtrTy),
- VK_RValue, OK_Ordinary,
- SourceLocation(), false);
+ UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
+ new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
+ VK_LValue, SourceLocation()),
+ UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
+ OK_Ordinary, SourceLocation(), false);
InitExprs.push_back(DescRefExpr);
// Add initializers for any closure decl refs.
@@ -5326,7 +5311,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
if (isObjCType((*I)->getType())) {
// FIXME: Conform to ABI ([[obj retain] autorelease]).
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Exp = new (Context) DeclRefExpr(FD, false, FD->getType(),
+ Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
VK_LValue, SourceLocation());
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
@@ -5337,13 +5322,13 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Arg = new (Context) DeclRefExpr(FD, false, FD->getType(),
+ Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
VK_LValue, SourceLocation());
Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
CK_BitCast, Arg);
} else {
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Exp = new (Context) DeclRefExpr(FD, false, FD->getType(),
+ Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
VK_LValue, SourceLocation());
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
@@ -5372,8 +5357,8 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
- SourceLocation());
+ Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
+ VK_LValue, SourceLocation());
bool isNestedCapturedVar = false;
if (block)
for (const auto &CI : block->captures()) {
@@ -5405,8 +5390,8 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
Context->IntTy, SourceLocation());
InitExprs.push_back(FlagExp);
}
- NewRep = new (Context) CallExpr(*Context, DRE, InitExprs,
- FType, VK_LValue, SourceLocation());
+ NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
+ SourceLocation());
if (GlobalBlockExpr) {
assert (!GlobalConstructionExp &&
@@ -5537,8 +5522,8 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
#if 0
// Before we rewrite it, put the original message expression in a comment.
- SourceLocation startLoc = MessExpr->getLocStart();
- SourceLocation endLoc = MessExpr->getLocEnd();
+ SourceLocation startLoc = MessExpr->getBeginLoc();
+ SourceLocation endLoc = MessExpr->getEndLoc();
const char *startBuf = SM->getCharacterData(startLoc);
const char *endBuf = SM->getCharacterData(endLoc);
@@ -5676,7 +5661,7 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
const std::string &Str = Buf.str();
printf("CAST = %s\n", &Str[0]);
- InsertText(ICE->getSubExpr()->getLocStart(), Str);
+ InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
delete S;
return Replacement;
}
@@ -7499,9 +7484,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
SourceLocation(), &Context->Idents.get(IvarOffsetName),
Context->UnsignedLongTy, nullptr,
SC_Extern);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false,
- Context->UnsignedLongTy, VK_LValue,
- SourceLocation());
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,
+ VK_LValue, SourceLocation());
BinaryOperator *addExpr =
new (Context) BinaryOperator(castExpr, DRE, BO_Add,
Context->getPointerType(Context->CharTy),
diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp
index 6229351e8f54..3e018800b909 100644
--- a/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -216,8 +216,8 @@ namespace {
// Measure the old text.
int Size = Rewrite.getRangeSize(SrcRange);
if (Size == -1) {
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
+ Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
+ << Old->getSourceRange();
return;
}
// Get the new text.
@@ -233,8 +233,8 @@ namespace {
}
if (SilenceRewriteMacroWarning)
return;
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
+ Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
+ << Old->getSourceRange();
}
void InsertText(SourceLocation Loc, StringRef Str,
@@ -448,7 +448,7 @@ namespace {
// FIXME: This predicate seems like it would be useful to add to ASTContext.
bool isObjCType(QualType T) {
- if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
+ if (!LangOpts.ObjC)
return false;
QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
@@ -680,11 +680,11 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
if (!IFace->isThisDeclarationADefinition()) {
SmallVector<Decl *, 8> DG;
- SourceLocation StartLoc = IFace->getLocStart();
+ SourceLocation StartLoc = IFace->getBeginLoc();
do {
if (isa<ObjCInterfaceDecl>(*DI) &&
!cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
- StartLoc == (*DI)->getLocStart())
+ StartLoc == (*DI)->getBeginLoc())
DG.push_back(*DI);
else
break;
@@ -699,11 +699,11 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
if (!Proto->isThisDeclarationADefinition()) {
SmallVector<Decl *, 8> DG;
- SourceLocation StartLoc = Proto->getLocStart();
+ SourceLocation StartLoc = Proto->getBeginLoc();
do {
if (isa<ObjCProtocolDecl>(*DI) &&
!cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
- StartLoc == (*DI)->getLocStart())
+ StartLoc == (*DI)->getBeginLoc())
DG.push_back(*DI);
else
break;
@@ -769,7 +769,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
ObjCCategoryImplDecl *CID) {
static bool objcGetPropertyDefined = false;
static bool objcSetPropertyDefined = false;
- SourceLocation startLoc = PID->getLocStart();
+ SourceLocation startLoc = PID->getBeginLoc();
InsertText(startLoc, "// ");
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @synthesize location");
@@ -901,11 +901,11 @@ static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
const std::string &typedefString) {
- SourceLocation startLoc = ClassDecl->getLocStart();
- const char *startBuf = SM->getCharacterData(startLoc);
- const char *semiPtr = strchr(startBuf, ';');
- // Replace the @class with typedefs corresponding to the classes.
- ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
+ SourceLocation startLoc = ClassDecl->getBeginLoc();
+ const char *startBuf = SM->getCharacterData(startLoc);
+ const char *semiPtr = strchr(startBuf, ';');
+ // Replace the @class with typedefs corresponding to the classes.
+ ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);
}
void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {
@@ -945,8 +945,8 @@ void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
// nothing to rewrite.
if (Method->isImplicit())
return;
- SourceLocation LocStart = Method->getLocStart();
- SourceLocation LocEnd = Method->getLocEnd();
+ SourceLocation LocStart = Method->getBeginLoc();
+ SourceLocation LocEnd = Method->getEndLoc();
if (SM->getExpansionLineNumber(LocEnd) >
SM->getExpansionLineNumber(LocStart)) {
@@ -965,7 +965,7 @@ void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
}
void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
- SourceLocation LocStart = CatDecl->getLocStart();
+ SourceLocation LocStart = CatDecl->getBeginLoc();
// FIXME: handle category headers that are declared across multiple lines.
ReplaceText(LocStart, 0, "// ");
@@ -983,7 +983,7 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
}
void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
- SourceLocation LocStart = PDecl->getLocStart();
+ SourceLocation LocStart = PDecl->getBeginLoc();
assert(PDecl->isThisDeclarationADefinition());
// FIXME: handle protocol headers that are declared across multiple lines.
@@ -1018,7 +1018,7 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
}
void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
- SourceLocation LocStart = (*D.begin())->getLocStart();
+ SourceLocation LocStart = (*D.begin())->getBeginLoc();
if (LocStart.isInvalid())
llvm_unreachable("Invalid SourceLocation");
// FIXME: handle forward protocol that are declared across multiple lines.
@@ -1027,7 +1027,7 @@ void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
void
RewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
- SourceLocation LocStart = DG[0]->getLocStart();
+ SourceLocation LocStart = DG[0]->getBeginLoc();
if (LocStart.isInvalid())
llvm_unreachable("Invalid SourceLocation");
// FIXME: handle forward protocol that are declared across multiple lines.
@@ -1165,13 +1165,13 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
- InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// ");
+ InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
- SourceLocation LocStart = OMD->getLocStart();
- SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+ SourceLocation LocStart = OMD->getBeginLoc();
+ SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
@@ -1181,8 +1181,8 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
- SourceLocation LocStart = OMD->getLocStart();
- SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+ SourceLocation LocStart = OMD->getBeginLoc();
+ SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
@@ -1191,7 +1191,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())
RewritePropertyImplDecl(I, IMD, CID);
- InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// ");
+ InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");
}
void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
@@ -1412,7 +1412,7 @@ Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
// replace break with goto __break_label
std::string buf;
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
buf = "goto __break_label_";
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("break"), buf);
@@ -1429,7 +1429,7 @@ Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
// replace continue with goto __continue_label
std::string buf;
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
buf = "goto __continue_label_";
buf += utostr(ObjCBcLabelNo.back());
ReplaceText(startLoc, strlen("continue"), buf);
@@ -1477,7 +1477,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
assert(!ObjCBcLabelNo.empty() &&
"ObjCForCollectionStmt - Label No stack empty");
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
StringRef elementName;
std::string elementTypeAsString;
@@ -1641,7 +1641,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
///
Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
// Get the start location and compute the semi location.
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @synchronized location");
@@ -1651,10 +1651,10 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
const char *lparenBuf = startBuf;
while (*lparenBuf != '(') lparenBuf++;
ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
- // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
+ // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since
// the sync expression is typically a message expression that's already
// been rewritten! (which implies the SourceLocation's are invalid).
- SourceLocation endLoc = S->getSynchBody()->getLocStart();
+ SourceLocation endLoc = S->getSynchBody()->getBeginLoc();
const char *endBuf = SM->getCharacterData(endLoc);
while (*endBuf != ')') endBuf--;
SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf);
@@ -1667,7 +1667,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
buf += "objc_exception_try_enter(&_stack);\n";
buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
ReplaceText(rparenLoc, 1, buf);
- startLoc = S->getSynchBody()->getLocEnd();
+ startLoc = S->getSynchBody()->getEndLoc();
startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '}') && "bogus @synchronized block");
@@ -1719,7 +1719,7 @@ void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
WarnAboutReturnGotoStmts(SubStmt);
if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
- Diags.Report(Context->getFullLoc(S->getLocStart()),
+ Diags.Report(Context->getFullLoc(S->getBeginLoc()),
TryFinallyContainsReturnDiag);
}
}
@@ -1742,7 +1742,7 @@ void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
RewriteTryReturnStmts(SubStmt);
}
if (isa<ReturnStmt>(S)) {
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
const char *semiBuf = strchr(startBuf, ';');
assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
@@ -1763,7 +1763,7 @@ void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
RewriteSyncReturnStmts(SubStmt, syncExitBuf);
}
if (isa<ReturnStmt>(S)) {
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
const char *semiBuf = strchr(startBuf, ';');
@@ -1782,7 +1782,7 @@ void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
// Get the start location and compute the semi location.
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @try location");
@@ -1798,7 +1798,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
ReplaceText(startLoc, 4, buf);
- startLoc = S->getTryBody()->getLocEnd();
+ startLoc = S->getTryBody()->getEndLoc();
startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '}') && "bogus @try block");
@@ -1829,7 +1829,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
buf = "if ("; // we are generating code for the first catch clause
else
buf = "else if (";
- startLoc = Catch->getLocStart();
+ startLoc = Catch->getBeginLoc();
startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @catch location");
@@ -1839,7 +1839,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
if (Catch->hasEllipsis()) {
// Now rewrite the body...
lastCatchBody = Catch->getCatchBody();
- SourceLocation bodyLoc = lastCatchBody->getLocStart();
+ SourceLocation bodyLoc = lastCatchBody->getBeginLoc();
const char *bodyBuf = SM->getCharacterData(bodyLoc);
assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' &&
"bogus @catch paren location");
@@ -1866,7 +1866,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
// Now rewrite the body...
lastCatchBody = Catch->getCatchBody();
SourceLocation rParenLoc = Catch->getRParenLoc();
- SourceLocation bodyLoc = lastCatchBody->getLocStart();
+ SourceLocation bodyLoc = lastCatchBody->getBeginLoc();
const char *bodyBuf = SM->getCharacterData(bodyLoc);
const char *rParenBuf = SM->getCharacterData(rParenLoc);
assert((*rParenBuf == ')') && "bogus @catch paren location");
@@ -1881,7 +1881,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
}
// Complete the catch list...
if (lastCatchBody) {
- SourceLocation bodyLoc = lastCatchBody->getLocEnd();
+ SourceLocation bodyLoc = lastCatchBody->getEndLoc();
assert(*SM->getCharacterData(bodyLoc) == '}' &&
"bogus @catch body location");
@@ -1897,18 +1897,18 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
InsertText(bodyLoc, buf);
// Set lastCurlyLoc
- lastCurlyLoc = lastCatchBody->getLocEnd();
+ lastCurlyLoc = lastCatchBody->getEndLoc();
}
if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
- startLoc = finalStmt->getLocStart();
+ startLoc = finalStmt->getBeginLoc();
startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @finally start");
ReplaceText(startLoc, 8, "/* @finally */");
Stmt *body = finalStmt->getFinallyBody();
- SourceLocation startLoc = body->getLocStart();
- SourceLocation endLoc = body->getLocEnd();
+ SourceLocation startLoc = body->getBeginLoc();
+ SourceLocation endLoc = body->getEndLoc();
assert(*SM->getCharacterData(startLoc) == '{' &&
"bogus @finally body location");
assert(*SM->getCharacterData(endLoc) == '}' &&
@@ -1920,7 +1920,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n");
// Set lastCurlyLoc
- lastCurlyLoc = body->getLocEnd();
+ lastCurlyLoc = body->getEndLoc();
// Now check for any return/continue/go statements within the @try.
WarnAboutReturnGotoStmts(S->getTryBody());
@@ -1950,7 +1950,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
// been rewritten! (which implies the SourceLocation's are invalid).
Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
// Get the start location and compute the semi location.
- SourceLocation startLoc = S->getLocStart();
+ SourceLocation startLoc = S->getBeginLoc();
const char *startBuf = SM->getCharacterData(startLoc);
assert((*startBuf == '@') && "bogus @throw location");
@@ -2009,7 +2009,7 @@ RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
QualType msgSendType = FD->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, msgSendType,
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,
VK_LValue, SourceLocation());
// Now, we cast the reference to a pointer to the objc_msgSend type.
@@ -2020,9 +2020,8 @@ RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *Exp = new (Context) CallExpr(*Context, ICE, Args,
- FT->getCallResultType(*Context),
- VK_RValue, EndLoc);
+ CallExpr *Exp = CallExpr::Create(
+ *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc);
return Exp;
}
@@ -2082,8 +2081,8 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
Loc = ECE->getLParenLoc();
EndLoc = ECE->getRParenLoc();
} else {
- Loc = E->getLocStart();
- EndLoc = E->getLocEnd();
+ Loc = E->getBeginLoc();
+ EndLoc = E->getEndLoc();
}
// This will defend against trying to rewrite synthesized expressions.
if (Loc.isInvalid() || EndLoc.isInvalid())
@@ -2204,13 +2203,13 @@ void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) {
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
startLoc = ECE->getLParenLoc();
else
- startLoc = E->getLocStart();
+ startLoc = E->getBeginLoc();
startLoc = SM->getExpansionLoc(startLoc);
const char *endBuf = SM->getCharacterData(startLoc);
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
}
else {
- SourceLocation X = ND->getLocEnd();
+ SourceLocation X = ND->getEndLoc();
X = SM->getExpansionLoc(X);
const char *endBuf = SM->getCharacterData(X);
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
@@ -2506,12 +2505,11 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), &Context->Idents.get(S),
strType, nullptr, SC_Static);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue,
- SourceLocation());
- Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
- Context->getPointerType(DRE->getType()),
- VK_RValue, OK_Ordinary,
- SourceLocation(), false);
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
+ Expr *Unop = new (Context)
+ UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()),
+ VK_RValue, OK_Ordinary, SourceLocation(), false);
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_CPointerToObjCPointerCast, Unop);
@@ -2589,9 +2587,9 @@ CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavo
SmallVectorImpl<Expr*> &MsgExprs,
ObjCMethodDecl *Method) {
// Create a reference to the objc_msgSend_stret() declaration.
- DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor,
- false, msgSendType,
- VK_LValue, SourceLocation());
+ DeclRefExpr *STDRE =
+ new (Context) DeclRefExpr(*Context, MsgSendStretFlavor, false,
+ msgSendType, VK_LValue, SourceLocation());
// Need to cast objc_msgSend_stret to "void *" (see above comment).
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->VoidTy),
@@ -2608,8 +2606,8 @@ CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavo
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *STCE = new (Context) CallExpr(
- *Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, SourceLocation());
+ CallExpr *STCE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
+ VK_RValue, SourceLocation());
return STCE;
}
@@ -2664,7 +2662,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
InitExprs.push_back(
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
CK_BitCast,
- new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+ new (Context) DeclRefExpr(*Context,
+ CurMethodDef->getSelfDecl(),
false,
Context->getObjCIdType(),
VK_RValue,
@@ -2697,12 +2696,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
if (LangOpts.MicrosoftExt) {
SynthSuperConstructorFunctionDecl();
// Simulate a constructor call...
- DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl,
- false, superType, VK_LValue,
- SourceLocation());
- SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs,
- superType, VK_LValue,
- SourceLocation());
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
+ VK_LValue, SourceLocation());
+ SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
+ VK_LValue, SourceLocation());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -2759,7 +2757,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
InitExprs.push_back(
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
CK_BitCast,
- new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+ new (Context) DeclRefExpr(*Context,
+ CurMethodDef->getSelfDecl(),
false,
Context->getObjCIdType(),
VK_RValue, SourceLocation()))
@@ -2792,11 +2791,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
if (LangOpts.MicrosoftExt) {
SynthSuperConstructorFunctionDecl();
// Simulate a constructor call...
- DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl,
- false, superType, VK_LValue,
- SourceLocation());
- SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs,
- superType, VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
+ VK_LValue, SourceLocation());
+ SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
+ VK_LValue, SourceLocation());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -2936,8 +2935,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
QualType msgSendType = MsgSendFlavor->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType,
- VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(
+ *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
// Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
// If we don't do this cast, we get the following bizarre warning/note:
@@ -2960,8 +2959,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *CE = new (Context)
- CallExpr(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, EndLoc);
+ CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
+ VK_RValue, EndLoc);
Stmt *ReplacingStmt = CE;
if (MsgSendStretFlavor) {
// We have the method which returns a struct/union. Must also generate
@@ -3008,8 +3007,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
}
Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
- Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(),
- Exp->getLocEnd());
+ Stmt *ReplacingStmt =
+ SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());
// Now do the actual rewrite.
ReplaceStmt(Exp, ReplacingStmt);
@@ -3041,8 +3040,8 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
SourceLocation(), ID, getProtocolType(),
nullptr, SC_Extern);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(),
- VK_LValue, SourceLocation());
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(
+ *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()),
VK_RValue, OK_Ordinary, SourceLocation(), false);
@@ -3093,7 +3092,7 @@ void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
return;
ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
int NumIvars = CDecl->ivar_size();
- SourceLocation LocStart = CDecl->getLocStart();
+ SourceLocation LocStart = CDecl->getBeginLoc();
SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
const char *startBuf = SM->getCharacterData(LocStart);
@@ -3635,9 +3634,9 @@ static void BuildUniqueMethodName(std::string &Name,
}
void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
- //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
- //SourceLocation FunLocStart = MD->getLocStart();
- SourceLocation FunLocStart = MD->getLocStart();
+ // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
+ // SourceLocation FunLocStart = MD->getBeginLoc();
+ SourceLocation FunLocStart = MD->getBeginLoc();
std::string FuncName;
BuildUniqueMethodName(FuncName, MD);
SynthesizeBlockLiterals(FunLocStart, FuncName);
@@ -3811,9 +3810,8 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
E = Exp->arg_end(); I != E; ++I) {
BlkExprs.push_back(*I);
}
- CallExpr *CE = new (Context) CallExpr(*Context, PE, BlkExprs,
- Exp->getType(), VK_RValue,
- SourceLocation());
+ CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(),
+ VK_RValue, SourceLocation());
return CE;
}
@@ -4179,7 +4177,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
// Use variable's location which is good for this case.
DeclLoc = ND->getLocation();
const char *startBuf = SM->getCharacterData(DeclLoc);
- SourceLocation X = ND->getLocEnd();
+ SourceLocation X = ND->getEndLoc();
X = SM->getExpansionLoc(X);
const char *endBuf = SM->getCharacterData(X);
std::string Name(ND->getNameAsString());
@@ -4212,7 +4210,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
else {
assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
- FunLocStart = CurMethodDef->getLocStart();
+ FunLocStart = CurMethodDef->getBeginLoc();
}
InsertText(FunLocStart, ByrefType);
if (Ty.isObjCGCWeak()) {
@@ -4274,7 +4272,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
startLoc = ECE->getLParenLoc();
else
- startLoc = E->getLocStart();
+ startLoc = E->getBeginLoc();
startLoc = SM->getExpansionLoc(startLoc);
endBuf = SM->getCharacterData(startLoc);
ByrefType += " " + Name;
@@ -4411,17 +4409,17 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
// Simulate a constructor call...
FD = SynthBlockInitFunctionDecl(Tag);
- DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue,
- SourceLocation());
+ DeclRefExpr *DRE = new (Context)
+ DeclRefExpr(*Context, FD, false, FType, VK_RValue, SourceLocation());
SmallVector<Expr*, 4> InitExprs;
// Initialize the block function.
FD = SynthBlockInitFunctionDecl(Func);
- DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(),
- VK_LValue, SourceLocation());
- CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
- CK_BitCast, Arg);
+ DeclRefExpr *Arg = new (Context) DeclRefExpr(
+ *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());
+ CastExpr *castExpr =
+ NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg);
InitExprs.push_back(castExpr);
// Initialize the block descriptor.
@@ -4430,15 +4428,11 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
VarDecl *NewVD = VarDecl::Create(
*Context, TUDecl, SourceLocation(), SourceLocation(),
&Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
- UnaryOperator *DescRefExpr =
- new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
- Context->VoidPtrTy,
- VK_LValue,
- SourceLocation()),
- UO_AddrOf,
- Context->getPointerType(Context->VoidPtrTy),
- VK_RValue, OK_Ordinary,
- SourceLocation(), false);
+ UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
+ new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
+ VK_LValue, SourceLocation()),
+ UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
+ OK_Ordinary, SourceLocation(), false);
InitExprs.push_back(DescRefExpr);
// Add initializers for any closure decl refs.
@@ -4450,8 +4444,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
if (isObjCType((*I)->getType())) {
// FIXME: Conform to ABI ([[obj retain] autorelease]).
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
- SourceLocation());
+ Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
+ VK_LValue, SourceLocation());
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
@@ -4461,14 +4455,14 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
- SourceLocation());
- Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
- CK_BitCast, Arg);
+ Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
+ VK_LValue, SourceLocation());
+ Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast,
+ Arg);
} else {
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
- SourceLocation());
+ Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
+ VK_LValue, SourceLocation());
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
@@ -4495,8 +4489,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
FD = SynthBlockInitFunctionDecl((*I)->getName());
- Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue,
- SourceLocation());
+ Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
+ VK_LValue, SourceLocation());
bool isNestedCapturedVar = false;
if (block)
for (const auto &CI : block->captures()) {
@@ -4527,11 +4521,11 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
Context->IntTy, SourceLocation());
InitExprs.push_back(FlagExp);
}
- NewRep = new (Context) CallExpr(*Context, DRE, InitExprs,
- FType, VK_LValue, SourceLocation());
- NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
- Context->getPointerType(NewRep->getType()),
- VK_RValue, OK_Ordinary, SourceLocation(), false);
+ NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
+ SourceLocation());
+ NewRep = new (Context) UnaryOperator(
+ NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), VK_RValue,
+ OK_Ordinary, SourceLocation(), false);
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
BlockDeclRefs.clear();
@@ -4632,8 +4626,8 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
#if 0
// Before we rewrite it, put the original message expression in a comment.
- SourceLocation startLoc = MessExpr->getLocStart();
- SourceLocation endLoc = MessExpr->getLocEnd();
+ SourceLocation startLoc = MessExpr->getBeginLoc();
+ SourceLocation endLoc = MessExpr->getEndLoc();
const char *startBuf = SM->getCharacterData(startLoc);
const char *endBuf = SM->getCharacterData(endLoc);
@@ -4760,7 +4754,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
const std::string &Str = Buf.str();
printf("CAST = %s\n", &Str[0]);
- InsertText(ICE->getSubExpr()->getLocStart(), Str);
+ InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
delete S;
return Replacement;
}
@@ -5873,8 +5867,8 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
CK_BitCast,
IV->getBase());
// Don't forget the parens to enforce the proper binding.
- ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
- IV->getBase()->getLocEnd(), castExpr);
+ ParenExpr *PE = new (Context) ParenExpr(
+ IV->getBase()->getBeginLoc(), IV->getBase()->getEndLoc(), castExpr);
// Cannot delete IV->getBase(), since PE points to it.
// Replace the old base with the cast. This is important when doing
// embedded rewrites. For example, [newInv->_container addObject:0].
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 747fdd241640..7015772fa168 100644
--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -12,7 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/FrontendTool/Utils.h"
#include "clang/ARCMigrate/ARCMTActions.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Config/config.h"
@@ -23,10 +22,12 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/Utils.h"
+#include "clang/FrontendTool/Utils.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -61,8 +62,9 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
return llvm::make_unique<GenerateModuleFromModuleMapAction>();
case GenerateModuleInterface:
return llvm::make_unique<GenerateModuleInterfaceAction>();
+ case GenerateHeaderModule:
+ return llvm::make_unique<GenerateHeaderModuleAction>();
case GeneratePCH: return llvm::make_unique<GeneratePCHAction>();
- case GeneratePTH: return llvm::make_unique<GeneratePTHAction>();
case InitOnly: return llvm::make_unique<InitOnlyAction>();
case ParseSyntaxOnly: return llvm::make_unique<SyntaxOnlyAction>();
case ModuleFileInfo: return llvm::make_unique<DumpModuleInfoAction>();
@@ -88,7 +90,6 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
return nullptr;
}
- case PrintDeclContext: return llvm::make_unique<DeclContextPrintAction>();
case PrintPreamble: return llvm::make_unique<PrintPreambleAction>();
case PrintPreprocessedInput: {
if (CI.getPreprocessorOutputOpts().RewriteIncludes ||
@@ -182,7 +183,7 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
// Honor -help.
if (Clang->getFrontendOpts().ShowHelp) {
std::unique_ptr<OptTable> Opts = driver::createDriverOptTable();
- Opts->PrintHelp(llvm::outs(), "clang -cc1",
+ Opts->PrintHelp(llvm::outs(), "clang -cc1 [options] file...",
"LLVM 'Clang' Compiler: http://clang.llvm.org",
/*Include=*/driver::options::CC1Option,
/*Exclude=*/0, /*ShowAllAliases=*/false);
@@ -237,13 +238,23 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
// Honor -analyzer-checker-help.
// This should happen AFTER plugins have been loaded!
if (Clang->getAnalyzerOpts()->ShowCheckerHelp) {
- ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins);
+ ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins,
+ Clang->getDiagnostics());
return true;
}
+
+ // Honor -analyzer-list-enabled-checkers.
if (Clang->getAnalyzerOpts()->ShowEnabledCheckerList) {
ento::printEnabledCheckerList(llvm::outs(),
Clang->getFrontendOpts().Plugins,
- *Clang->getAnalyzerOpts());
+ *Clang->getAnalyzerOpts(),
+ Clang->getDiagnostics());
+ }
+
+ // Honor -analyzer-config-help.
+ if (Clang->getAnalyzerOpts()->ShowConfigOptionsList) {
+ ento::printAnalyzerConfigList(llvm::outs());
+ return true;
}
#endif
@@ -256,7 +267,7 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
return false;
bool Success = Clang->ExecuteAction(*Act);
if (Clang->getFrontendOpts().DisableFree)
- BuryPointer(std::move(Act));
+ llvm::BuryPointer(std::move(Act));
return Success;
}
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index 1930d8e225c7..e444c9c8706f 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -144,7 +144,7 @@ foreach( f ${files} ${cuda_wrapper_files} )
list(APPEND out_files ${dst})
endforeach( f )
-add_custom_command(OUTPUT ${output_dir}/arm_neon.h
+add_custom_command(OUTPUT ${output_dir}/arm_neon.h
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/arm_neon.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/arm_neon.h ${output_dir}/arm_neon.h
COMMENT "Copying clang's arm_neon.h...")
@@ -156,7 +156,9 @@ add_custom_command(OUTPUT ${output_dir}/arm_fp16.h
list(APPEND out_files ${output_dir}/arm_fp16.h)
add_custom_target(clang-headers ALL DEPENDS ${out_files})
-set_target_properties(clang-headers PROPERTIES FOLDER "Misc")
+set_target_properties(clang-headers PROPERTIES
+ FOLDER "Misc"
+ RUNTIME_OUTPUT_DIRECTORY "${output_dir}")
install(
FILES ${files} ${CMAKE_CURRENT_BINARY_DIR}/arm_neon.h
diff --git a/lib/Headers/__clang_cuda_runtime_wrapper.h b/lib/Headers/__clang_cuda_runtime_wrapper.h
index 09705a273a47..f05c0454a883 100644
--- a/lib/Headers/__clang_cuda_runtime_wrapper.h
+++ b/lib/Headers/__clang_cuda_runtime_wrapper.h
@@ -62,10 +62,15 @@
#include "cuda.h"
#if !defined(CUDA_VERSION)
#error "cuda.h did not define CUDA_VERSION"
-#elif CUDA_VERSION < 7000 || CUDA_VERSION > 9020
+#elif CUDA_VERSION < 7000 || CUDA_VERSION > 10000
#error "Unsupported CUDA version!"
#endif
+#pragma push_macro("__CUDA_INCLUDE_COMPILER_INTERNAL_HEADERS__")
+#if CUDA_VERSION >= 10000
+#define __CUDA_INCLUDE_COMPILER_INTERNAL_HEADERS__
+#endif
+
// Make largest subset of device functions available during host
// compilation -- SM_35 for the time being.
#ifndef __CUDA_ARCH__
@@ -419,6 +424,7 @@ __device__ inline __cuda_builtin_gridDim_t::operator dim3() const {
#pragma pop_macro("dim3")
#pragma pop_macro("uint3")
#pragma pop_macro("__USE_FAST_MATH__")
+#pragma pop_macro("__CUDA_INCLUDE_COMPILER_INTERNAL_HEADERS__")
#endif // __CUDA__
#endif // __CLANG_CUDA_RUNTIME_WRAPPER_H__
diff --git a/lib/Headers/adxintrin.h b/lib/Headers/adxintrin.h
index ee347284178e..d6c454db8512 100644
--- a/lib/Headers/adxintrin.h
+++ b/lib/Headers/adxintrin.h
@@ -53,7 +53,7 @@ static __inline unsigned char __DEFAULT_FN_ATTRS
_addcarry_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
unsigned int *__p)
{
- return __builtin_ia32_addcarry_u32(__cf, __x, __y, __p);
+ return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p);
}
#ifdef __x86_64__
@@ -61,7 +61,7 @@ static __inline unsigned char __DEFAULT_FN_ATTRS
_addcarry_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y, unsigned long long *__p)
{
- return __builtin_ia32_addcarry_u64(__cf, __x, __y, __p);
+ return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p);
}
#endif
diff --git a/lib/Headers/altivec.h b/lib/Headers/altivec.h
index 90fd477d9b98..2dc6adb9009f 100644
--- a/lib/Headers/altivec.h
+++ b/lib/Headers/altivec.h
@@ -9492,49 +9492,51 @@ vec_splat_u32(signed char __a) {
/* vec_sr */
-static __inline__ vector signed char __ATTRS_o_ai
-vec_sr(vector signed char __a, vector unsigned char __b) {
- vector unsigned char __res = (vector unsigned char)__a >> __b;
- return (vector signed char)__res;
-}
-
+// vec_sr does modulo arithmetic on __b first, so __b is allowed to be more
+// than the length of __a.
static __inline__ vector unsigned char __ATTRS_o_ai
vec_sr(vector unsigned char __a, vector unsigned char __b) {
- return __a >> __b;
+ return __a >>
+ (__b % (vector unsigned char)(sizeof(unsigned char) * __CHAR_BIT__));
}
-static __inline__ vector signed short __ATTRS_o_ai
-vec_sr(vector signed short __a, vector unsigned short __b) {
- vector unsigned short __res = (vector unsigned short)__a >> __b;
- return (vector signed short)__res;
+static __inline__ vector signed char __ATTRS_o_ai
+vec_sr(vector signed char __a, vector unsigned char __b) {
+ return (vector signed char)vec_sr((vector unsigned char)__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
vec_sr(vector unsigned short __a, vector unsigned short __b) {
- return __a >> __b;
+ return __a >>
+ (__b % (vector unsigned short)(sizeof(unsigned short) * __CHAR_BIT__));
}
-static __inline__ vector signed int __ATTRS_o_ai
-vec_sr(vector signed int __a, vector unsigned int __b) {
- vector unsigned int __res = (vector unsigned int)__a >> __b;
- return (vector signed int)__res;
+static __inline__ vector short __ATTRS_o_ai vec_sr(vector short __a,
+ vector unsigned short __b) {
+ return (vector short)vec_sr((vector unsigned short)__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
vec_sr(vector unsigned int __a, vector unsigned int __b) {
- return __a >> __b;
+ return __a >>
+ (__b % (vector unsigned int)(sizeof(unsigned int) * __CHAR_BIT__));
}
-#ifdef __POWER8_VECTOR__
-static __inline__ vector signed long long __ATTRS_o_ai
-vec_sr(vector signed long long __a, vector unsigned long long __b) {
- vector unsigned long long __res = (vector unsigned long long)__a >> __b;
- return (vector signed long long)__res;
+static __inline__ vector int __ATTRS_o_ai vec_sr(vector int __a,
+ vector unsigned int __b) {
+ return (vector int)vec_sr((vector unsigned int)__a, __b);
}
+#ifdef __POWER8_VECTOR__
static __inline__ vector unsigned long long __ATTRS_o_ai
vec_sr(vector unsigned long long __a, vector unsigned long long __b) {
- return __a >> __b;
+ return __a >> (__b % (vector unsigned long long)(sizeof(unsigned long long) *
+ __CHAR_BIT__));
+}
+
+static __inline__ vector long long __ATTRS_o_ai
+vec_sr(vector long long __a, vector unsigned long long __b) {
+ return (vector long long)vec_sr((vector unsigned long long)__a, __b);
}
#endif
@@ -9544,12 +9546,12 @@ vec_sr(vector unsigned long long __a, vector unsigned long long __b) {
static __inline__ vector signed char __ATTRS_o_ai
vec_vsrb(vector signed char __a, vector unsigned char __b) {
- return __a >> (vector signed char)__b;
+ return vec_sr(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
vec_vsrb(vector unsigned char __a, vector unsigned char __b) {
- return __a >> __b;
+ return vec_sr(__a, __b);
}
/* vec_vsrh */
@@ -9558,12 +9560,12 @@ vec_vsrb(vector unsigned char __a, vector unsigned char __b) {
static __inline__ vector short __ATTRS_o_ai
vec_vsrh(vector short __a, vector unsigned short __b) {
- return __a >> (vector short)__b;
+ return vec_sr(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
vec_vsrh(vector unsigned short __a, vector unsigned short __b) {
- return __a >> __b;
+ return vec_sr(__a, __b);
}
/* vec_vsrw */
@@ -9572,12 +9574,12 @@ vec_vsrh(vector unsigned short __a, vector unsigned short __b) {
static __inline__ vector int __ATTRS_o_ai vec_vsrw(vector int __a,
vector unsigned int __b) {
- return __a >> (vector int)__b;
+ return vec_sr(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
vec_vsrw(vector unsigned int __a, vector unsigned int __b) {
- return __a >> __b;
+ return vec_sr(__a, __b);
}
/* vec_sra */
@@ -16353,67 +16355,82 @@ vec_revb(vector unsigned __int128 __a) {
/* vec_xl */
+typedef vector signed char unaligned_vec_schar __attribute__((aligned(1)));
+typedef vector unsigned char unaligned_vec_uchar __attribute__((aligned(1)));
+typedef vector signed short unaligned_vec_sshort __attribute__((aligned(1)));
+typedef vector unsigned short unaligned_vec_ushort __attribute__((aligned(1)));
+typedef vector signed int unaligned_vec_sint __attribute__((aligned(1)));
+typedef vector unsigned int unaligned_vec_uint __attribute__((aligned(1)));
+typedef vector float unaligned_vec_float __attribute__((aligned(1)));
+
static inline __ATTRS_o_ai vector signed char vec_xl(signed long long __offset,
signed char *__ptr) {
- return *(vector signed char *)(__ptr + __offset);
+ return *(unaligned_vec_schar *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector unsigned char
vec_xl(signed long long __offset, unsigned char *__ptr) {
- return *(vector unsigned char *)(__ptr + __offset);
+ return *(unaligned_vec_uchar*)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector signed short vec_xl(signed long long __offset,
signed short *__ptr) {
- return *(vector signed short *)(__ptr + __offset);
+ return *(unaligned_vec_sshort *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector unsigned short
vec_xl(signed long long __offset, unsigned short *__ptr) {
- return *(vector unsigned short *)(__ptr + __offset);
+ return *(unaligned_vec_ushort *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector signed int vec_xl(signed long long __offset,
signed int *__ptr) {
- return *(vector signed int *)(__ptr + __offset);
+ return *(unaligned_vec_sint *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector unsigned int vec_xl(signed long long __offset,
unsigned int *__ptr) {
- return *(vector unsigned int *)(__ptr + __offset);
+ return *(unaligned_vec_uint *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector float vec_xl(signed long long __offset,
float *__ptr) {
- return *(vector float *)(__ptr + __offset);
+ return *(unaligned_vec_float *)(__ptr + __offset);
}
#ifdef __VSX__
+typedef vector signed long long unaligned_vec_sll __attribute__((aligned(1)));
+typedef vector unsigned long long unaligned_vec_ull __attribute__((aligned(1)));
+typedef vector double unaligned_vec_double __attribute__((aligned(1)));
+
static inline __ATTRS_o_ai vector signed long long
vec_xl(signed long long __offset, signed long long *__ptr) {
- return *(vector signed long long *)(__ptr + __offset);
+ return *(unaligned_vec_sll *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector unsigned long long
vec_xl(signed long long __offset, unsigned long long *__ptr) {
- return *(vector unsigned long long *)(__ptr + __offset);
+ return *(unaligned_vec_ull *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector double vec_xl(signed long long __offset,
double *__ptr) {
- return *(vector double *)(__ptr + __offset);
+ return *(unaligned_vec_double *)(__ptr + __offset);
}
#endif
#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+typedef vector signed __int128 unaligned_vec_si128 __attribute__((aligned(1)));
+typedef vector unsigned __int128 unaligned_vec_ui128
+ __attribute__((aligned(1)));
static inline __ATTRS_o_ai vector signed __int128
vec_xl(signed long long __offset, signed __int128 *__ptr) {
- return *(vector signed __int128 *)(__ptr + __offset);
+ return *(unaligned_vec_si128 *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector unsigned __int128
vec_xl(signed long long __offset, unsigned __int128 *__ptr) {
- return *(vector unsigned __int128 *)(__ptr + __offset);
+ return *(unaligned_vec_ui128 *)(__ptr + __offset);
}
#endif
@@ -16498,62 +16515,62 @@ vec_xl_be(signed long long __offset, unsigned __int128 *__ptr) {
static inline __ATTRS_o_ai void vec_xst(vector signed char __vec,
signed long long __offset,
signed char *__ptr) {
- *(vector signed char *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_schar *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned char __vec,
signed long long __offset,
unsigned char *__ptr) {
- *(vector unsigned char *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_uchar *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector signed short __vec,
signed long long __offset,
signed short *__ptr) {
- *(vector signed short *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_sshort *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned short __vec,
signed long long __offset,
unsigned short *__ptr) {
- *(vector unsigned short *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_ushort *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector signed int __vec,
signed long long __offset,
signed int *__ptr) {
- *(vector signed int *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_sint *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned int __vec,
signed long long __offset,
unsigned int *__ptr) {
- *(vector unsigned int *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_uint *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector float __vec,
signed long long __offset,
float *__ptr) {
- *(vector float *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_float *)(__ptr + __offset) = __vec;
}
#ifdef __VSX__
static inline __ATTRS_o_ai void vec_xst(vector signed long long __vec,
signed long long __offset,
signed long long *__ptr) {
- *(vector signed long long *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_sll *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned long long __vec,
signed long long __offset,
unsigned long long *__ptr) {
- *(vector unsigned long long *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_ull *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector double __vec,
signed long long __offset,
double *__ptr) {
- *(vector double *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_double *)(__ptr + __offset) = __vec;
}
#endif
@@ -16561,13 +16578,13 @@ static inline __ATTRS_o_ai void vec_xst(vector double __vec,
static inline __ATTRS_o_ai void vec_xst(vector signed __int128 __vec,
signed long long __offset,
signed __int128 *__ptr) {
- *(vector signed __int128 *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_si128 *)(__ptr + __offset) = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned __int128 __vec,
signed long long __offset,
unsigned __int128 *__ptr) {
- *(vector unsigned __int128 *)(__ptr + __offset) = __vec;
+ *(unaligned_vec_ui128 *)(__ptr + __offset) = __vec;
}
#endif
diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h
index fc4632374977..a90a255376c0 100644
--- a/lib/Headers/avx512bwintrin.h
+++ b/lib/Headers/avx512bwintrin.h
@@ -32,7 +32,216 @@ typedef unsigned int __mmask32;
typedef unsigned long long __mmask64;
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bw"), __min_vector_width__(512)))
+#define __DEFAULT_FN_ATTRS512 __attribute__((__always_inline__, __nodebug__, __target__("avx512bw"), __min_vector_width__(512)))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bw")))
+
+static __inline __mmask32 __DEFAULT_FN_ATTRS
+_knot_mask32(__mmask32 __M)
+{
+ return __builtin_ia32_knotsi(__M);
+}
+
+static __inline __mmask64 __DEFAULT_FN_ATTRS
+_knot_mask64(__mmask64 __M)
+{
+ return __builtin_ia32_knotdi(__M);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_kand_mask32(__mmask32 __A, __mmask32 __B)
+{
+ return (__mmask32)__builtin_ia32_kandsi((__mmask32)__A, (__mmask32)__B);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_kand_mask64(__mmask64 __A, __mmask64 __B)
+{
+ return (__mmask64)__builtin_ia32_kanddi((__mmask64)__A, (__mmask64)__B);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_kandn_mask32(__mmask32 __A, __mmask32 __B)
+{
+ return (__mmask32)__builtin_ia32_kandnsi((__mmask32)__A, (__mmask32)__B);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_kandn_mask64(__mmask64 __A, __mmask64 __B)
+{
+ return (__mmask64)__builtin_ia32_kandndi((__mmask64)__A, (__mmask64)__B);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_kor_mask32(__mmask32 __A, __mmask32 __B)
+{
+ return (__mmask32)__builtin_ia32_korsi((__mmask32)__A, (__mmask32)__B);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_kor_mask64(__mmask64 __A, __mmask64 __B)
+{
+ return (__mmask64)__builtin_ia32_kordi((__mmask64)__A, (__mmask64)__B);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_kxnor_mask32(__mmask32 __A, __mmask32 __B)
+{
+ return (__mmask32)__builtin_ia32_kxnorsi((__mmask32)__A, (__mmask32)__B);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_kxnor_mask64(__mmask64 __A, __mmask64 __B)
+{
+ return (__mmask64)__builtin_ia32_kxnordi((__mmask64)__A, (__mmask64)__B);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_kxor_mask32(__mmask32 __A, __mmask32 __B)
+{
+ return (__mmask32)__builtin_ia32_kxorsi((__mmask32)__A, (__mmask32)__B);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_kxor_mask64(__mmask64 __A, __mmask64 __B)
+{
+ return (__mmask64)__builtin_ia32_kxordi((__mmask64)__A, (__mmask64)__B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestc_mask32_u8(__mmask32 __A, __mmask32 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestcsi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestz_mask32_u8(__mmask32 __A, __mmask32 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestzsi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortest_mask32_u8(__mmask32 __A, __mmask32 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_kortestcsi(__A, __B);
+ return (unsigned char)__builtin_ia32_kortestzsi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestc_mask64_u8(__mmask64 __A, __mmask64 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestcdi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestz_mask64_u8(__mmask64 __A, __mmask64 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestzdi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortest_mask64_u8(__mmask64 __A, __mmask64 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_kortestcdi(__A, __B);
+ return (unsigned char)__builtin_ia32_kortestzdi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestc_mask32_u8(__mmask32 __A, __mmask32 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestcsi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestz_mask32_u8(__mmask32 __A, __mmask32 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestzsi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktest_mask32_u8(__mmask32 __A, __mmask32 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_ktestcsi(__A, __B);
+ return (unsigned char)__builtin_ia32_ktestzsi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestc_mask64_u8(__mmask64 __A, __mmask64 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestcdi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestz_mask64_u8(__mmask64 __A, __mmask64 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestzdi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktest_mask64_u8(__mmask64 __A, __mmask64 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_ktestcdi(__A, __B);
+ return (unsigned char)__builtin_ia32_ktestzdi(__A, __B);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_kadd_mask32(__mmask32 __A, __mmask32 __B)
+{
+ return (__mmask32)__builtin_ia32_kaddsi((__mmask32)__A, (__mmask32)__B);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_kadd_mask64(__mmask64 __A, __mmask64 __B)
+{
+ return (__mmask64)__builtin_ia32_kadddi((__mmask64)__A, (__mmask64)__B);
+}
+
+#define _kshiftli_mask32(A, I) \
+ (__mmask32)__builtin_ia32_kshiftlisi((__mmask32)(A), (unsigned int)(I))
+
+#define _kshiftri_mask32(A, I) \
+ (__mmask32)__builtin_ia32_kshiftrisi((__mmask32)(A), (unsigned int)(I))
+
+#define _kshiftli_mask64(A, I) \
+ (__mmask64)__builtin_ia32_kshiftlidi((__mmask64)(A), (unsigned int)(I))
+
+#define _kshiftri_mask64(A, I) \
+ (__mmask64)__builtin_ia32_kshiftridi((__mmask64)(A), (unsigned int)(I))
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
+_cvtmask32_u32(__mmask32 __A) {
+ return (unsigned int)__builtin_ia32_kmovd((__mmask32)__A);
+}
+
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+_cvtmask64_u64(__mmask64 __A) {
+ return (unsigned long long)__builtin_ia32_kmovq((__mmask64)__A);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_cvtu32_mask32(unsigned int __A) {
+ return (__mmask32)__builtin_ia32_kmovd((__mmask32)__A);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_cvtu64_mask64(unsigned long long __A) {
+ return (__mmask64)__builtin_ia32_kmovq((__mmask64)__A);
+}
+
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+_load_mask32(__mmask32 *__A) {
+ return (__mmask32)__builtin_ia32_kmovd(*(__mmask32 *)__A);
+}
+
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+_load_mask64(__mmask64 *__A) {
+ return (__mmask64)__builtin_ia32_kmovq(*(__mmask64 *)__A);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_store_mask32(__mmask32 *__A, __mmask32 __B) {
+ *(__mmask32 *)__A = __builtin_ia32_kmovd((__mmask32)__B);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_store_mask64(__mmask64 *__A, __mmask64 __B) {
+ *(__mmask64 *)__A = __builtin_ia32_kmovq((__mmask64)__B);
+}
/* Integer compare */
@@ -176,102 +385,102 @@ typedef unsigned long long __mmask64;
#define _mm512_mask_cmpneq_epu16_mask(k, A, B) \
_mm512_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_NE)
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_add_epi8 (__m512i __A, __m512i __B) {
return (__m512i) ((__v64qu) __A + (__v64qu) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_add_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_add_epi8(__A, __B),
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_add_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_add_epi8(__A, __B),
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sub_epi8 (__m512i __A, __m512i __B) {
return (__m512i) ((__v64qu) __A - (__v64qu) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sub_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_sub_epi8(__A, __B),
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sub_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_sub_epi8(__A, __B),
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_add_epi16 (__m512i __A, __m512i __B) {
return (__m512i) ((__v32hu) __A + (__v32hu) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_add_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_add_epi16(__A, __B),
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_add_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_add_epi16(__A, __B),
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sub_epi16 (__m512i __A, __m512i __B) {
return (__m512i) ((__v32hu) __A - (__v32hu) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sub_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_sub_epi16(__A, __B),
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sub_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_sub_epi16(__A, __B),
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mullo_epi16 (__m512i __A, __m512i __B) {
return (__m512i) ((__v32hu) __A * (__v32hu) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mullo_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_mullo_epi16(__A, __B),
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mullo_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_mullo_epi16(__A, __B),
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_blend_epi8 (__mmask64 __U, __m512i __A, __m512i __W)
{
return (__m512i) __builtin_ia32_selectb_512 ((__mmask64) __U,
@@ -279,7 +488,7 @@ _mm512_mask_blend_epi8 (__mmask64 __U, __m512i __A, __m512i __W)
(__v64qi) __A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_blend_epi16 (__mmask32 __U, __m512i __A, __m512i __W)
{
return (__m512i) __builtin_ia32_selectw_512 ((__mmask32) __U,
@@ -287,13 +496,13 @@ _mm512_mask_blend_epi16 (__mmask32 __U, __m512i __A, __m512i __W)
(__v32hi) __A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_abs_epi8 (__m512i __A)
{
return (__m512i)__builtin_ia32_pabsb512((__v64qi)__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_abs_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
@@ -301,7 +510,7 @@ _mm512_mask_abs_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_abs_epi8 (__mmask64 __U, __m512i __A)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
@@ -309,13 +518,13 @@ _mm512_maskz_abs_epi8 (__mmask64 __U, __m512i __A)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_abs_epi16 (__m512i __A)
{
return (__m512i)__builtin_ia32_pabsw512((__v32hi)__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_abs_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -323,7 +532,7 @@ _mm512_mask_abs_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_abs_epi16 (__mmask32 __U, __m512i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -331,13 +540,13 @@ _mm512_maskz_abs_epi16 (__mmask32 __U, __m512i __A)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_packs_epi32(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_packssdw512((__v16si)__A, (__v16si)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_packs_epi32(__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -345,7 +554,7 @@ _mm512_maskz_packs_epi32(__mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_packs_epi32(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -353,13 +562,13 @@ _mm512_mask_packs_epi32(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_packs_epi16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_packsswb512((__v32hi)__A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_packs_epi16(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -367,7 +576,7 @@ _mm512_mask_packs_epi16(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_packs_epi16(__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -375,13 +584,13 @@ _mm512_maskz_packs_epi16(__mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_packus_epi32(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_packusdw512((__v16si) __A, (__v16si) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_packus_epi32(__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -389,7 +598,7 @@ _mm512_maskz_packus_epi32(__mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_packus_epi32(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -397,13 +606,13 @@ _mm512_mask_packus_epi32(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_packus_epi16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_packuswb512((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_packus_epi16(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -411,7 +620,7 @@ _mm512_mask_packus_epi16(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_packus_epi16(__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -419,119 +628,95 @@ _mm512_maskz_packus_epi16(__mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_adds_epi8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_paddsb512((__v64qi)__A, (__v64qi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_adds_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_adds_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_adds_epi8(__A, __B),
+ (__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_adds_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_adds_epi8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_adds_epi16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_paddsw512((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_adds_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_adds_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_adds_epi16(__A, __B),
+ (__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_adds_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_adds_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_adds_epu8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_paddusb512((__v64qi) __A, (__v64qi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_adds_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_adds_epu8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_adds_epu8(__A, __B),
+ (__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_adds_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_adds_epu8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_adds_epu16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_paddusw512((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_adds_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_adds_epu16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_adds_epu16(__A, __B),
+ (__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_adds_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_adds_epu16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_avg_epu8 (__m512i __A, __m512i __B)
{
typedef unsigned short __v64hu __attribute__((__vector_size__(128)));
@@ -541,7 +726,7 @@ _mm512_avg_epu8 (__m512i __A, __m512i __B)
>> 1, __v64qu);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_avg_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
__m512i __B)
{
@@ -550,7 +735,7 @@ _mm512_mask_avg_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_avg_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
@@ -558,7 +743,7 @@ _mm512_maskz_avg_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_avg_epu16 (__m512i __A, __m512i __B)
{
typedef unsigned int __v32su __attribute__((__vector_size__(128)));
@@ -568,7 +753,7 @@ _mm512_avg_epu16 (__m512i __A, __m512i __B)
>> 1, __v32hu);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_avg_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
__m512i __B)
{
@@ -577,7 +762,7 @@ _mm512_mask_avg_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_avg_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -585,13 +770,13 @@ _mm512_maskz_avg_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
(__v32hi) _mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_max_epi8 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pmaxsb512((__v64qi) __A, (__v64qi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -599,7 +784,7 @@ _mm512_maskz_max_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epi8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -607,13 +792,13 @@ _mm512_mask_max_epi8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_max_epi16 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pmaxsw512((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -621,7 +806,7 @@ _mm512_maskz_max_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
__m512i __B)
{
@@ -630,13 +815,13 @@ _mm512_mask_max_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_max_epu8 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pmaxub512((__v64qi)__A, (__v64qi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -644,7 +829,7 @@ _mm512_maskz_max_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epu8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -652,13 +837,13 @@ _mm512_mask_max_epu8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_max_epu16 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pmaxuw512((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_max_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -666,7 +851,7 @@ _mm512_maskz_max_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_max_epu16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -674,13 +859,13 @@ _mm512_mask_max_epu16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_min_epi8 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pminsb512((__v64qi) __A, (__v64qi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -688,7 +873,7 @@ _mm512_maskz_min_epi8 (__mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epi8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -696,13 +881,13 @@ _mm512_mask_min_epi8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_min_epi16 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pminsw512((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -710,7 +895,7 @@ _mm512_maskz_min_epi16 (__mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epi16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -718,13 +903,13 @@ _mm512_mask_min_epi16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_min_epu8 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pminub512((__v64qi)__A, (__v64qi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -732,7 +917,7 @@ _mm512_maskz_min_epu8 (__mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epu8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
@@ -740,13 +925,13 @@ _mm512_mask_min_epu8 (__m512i __W, __mmask64 __M, __m512i __A, __m512i __B)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_min_epu16 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pminuw512((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_min_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -754,7 +939,7 @@ _mm512_maskz_min_epu16 (__mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_min_epu16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__M,
@@ -762,13 +947,13 @@ _mm512_mask_min_epu16 (__m512i __W, __mmask32 __M, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_shuffle_epi8(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pshufb512((__v64qi)__A,(__v64qi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_shuffle_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
@@ -776,7 +961,7 @@ _mm512_mask_shuffle_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B)
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_shuffle_epi8(__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
@@ -784,126 +969,102 @@ _mm512_maskz_shuffle_epi8(__mmask64 __U, __m512i __A, __m512i __B)
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_subs_epi8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_psubsb512((__v64qi)__A, (__v64qi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_subs_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_subs_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_subs_epi8(__A, __B),
+ (__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_subs_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_subs_epi8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_subs_epi16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psubsw512((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_subs_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_subs_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_subs_epi16(__A, __B),
+ (__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_subs_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_subs_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_subs_epu8 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_psubusb512((__v64qi) __A, (__v64qi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_subs_epu8 (__m512i __W, __mmask64 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_subs_epu8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_subs_epu8(__A, __B),
+ (__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_subs_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_si512(),
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_subs_epu8(__A, __B),
+ (__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_subs_epu16 (__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psubusw512((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_subs_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
+_mm512_mask_subs_epu16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_subs_epu16(__A, __B),
+ (__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_subs_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_si512(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_subs_epu16(__A, __B),
+ (__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_permutex2var_epi16(__m512i __A, __m512i __I, __m512i __B)
{
return (__m512i)__builtin_ia32_vpermi2varhi512((__v32hi)__A, (__v32hi)__I,
(__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_permutex2var_epi16(__m512i __A, __mmask32 __U, __m512i __I,
__m512i __B)
{
@@ -912,7 +1073,7 @@ _mm512_mask_permutex2var_epi16(__m512i __A, __mmask32 __U, __m512i __I,
(__v32hi)__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask2_permutex2var_epi16(__m512i __A, __m512i __I, __mmask32 __U,
__m512i __B)
{
@@ -921,7 +1082,7 @@ _mm512_mask2_permutex2var_epi16(__m512i __A, __m512i __I, __mmask32 __U,
(__v32hi)__I);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_permutex2var_epi16(__mmask32 __U, __m512i __A, __m512i __I,
__m512i __B)
{
@@ -930,13 +1091,13 @@ _mm512_maskz_permutex2var_epi16(__mmask32 __U, __m512i __A, __m512i __I,
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mulhrs_epi16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pmulhrsw512((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mulhrs_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -944,7 +1105,7 @@ _mm512_mask_mulhrs_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mulhrs_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -952,13 +1113,13 @@ _mm512_maskz_mulhrs_epi16(__mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mulhi_epi16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pmulhw512((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mulhi_epi16(__m512i __W, __mmask32 __U, __m512i __A,
__m512i __B)
{
@@ -967,7 +1128,7 @@ _mm512_mask_mulhi_epi16(__m512i __W, __mmask32 __U, __m512i __A,
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mulhi_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -975,13 +1136,13 @@ _mm512_maskz_mulhi_epi16(__mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mulhi_epu16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_pmulhuw512((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mulhi_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -989,7 +1150,7 @@ _mm512_mask_mulhi_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mulhi_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -997,12 +1158,12 @@ _mm512_maskz_mulhi_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maddubs_epi16(__m512i __X, __m512i __Y) {
return (__m512i)__builtin_ia32_pmaddubsw512((__v64qi)__X, (__v64qi)__Y);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_maddubs_epi16(__m512i __W, __mmask32 __U, __m512i __X,
__m512i __Y) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32) __U,
@@ -1010,114 +1171,114 @@ _mm512_mask_maddubs_epi16(__m512i __W, __mmask32 __U, __m512i __X,
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_maddubs_epi16(__mmask32 __U, __m512i __X, __m512i __Y) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32) __U,
(__v32hi)_mm512_maddubs_epi16(__X, __Y),
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_madd_epi16(__m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_pmaddwd512((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_madd_epi16(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
(__v16si)_mm512_madd_epi16(__A, __B),
(__v16si)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_madd_epi16(__mmask16 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
(__v16si)_mm512_madd_epi16(__A, __B),
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtsepi16_epi8 (__m512i __A) {
return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A,
(__v32qi)_mm256_setzero_si256(),
(__mmask32) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) {
return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A,
(__v32qi)__O,
__M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtsepi16_epi8 (__mmask32 __M, __m512i __A) {
return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A,
(__v32qi) _mm256_setzero_si256(),
__M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtusepi16_epi8 (__m512i __A) {
return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A,
(__v32qi) _mm256_setzero_si256(),
(__mmask32) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) {
return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A,
(__v32qi) __O,
__M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtusepi16_epi8 (__mmask32 __M, __m512i __A) {
return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A,
(__v32qi) _mm256_setzero_si256(),
__M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_cvtepi16_epi8 (__m512i __A) {
return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A,
(__v32qi) _mm256_undefined_si256(),
(__mmask32) -1);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) {
return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A,
(__v32qi) __O,
__M);
}
-static __inline__ __m256i __DEFAULT_FN_ATTRS
+static __inline__ __m256i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi16_epi8 (__mmask32 __M, __m512i __A) {
return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A,
(__v32qi) _mm256_setzero_si256(),
__M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi16_storeu_epi8 (void * __P, __mmask32 __M, __m512i __A)
{
__builtin_ia32_pmovwb512mem_mask ((__v32qi *) __P, (__v32hi) __A, __M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask32 __M, __m512i __A)
{
__builtin_ia32_pmovswb512mem_mask ((__v32qi *) __P, (__v32hi) __A, __M);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask32 __M, __m512i __A)
{
__builtin_ia32_pmovuswb512mem_mask ((__v32qi *) __P, (__v32hi) __A, __M);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpackhi_epi8(__m512i __A, __m512i __B) {
return (__m512i)__builtin_shufflevector((__v64qi)__A, (__v64qi)__B,
8, 64+8, 9, 64+9,
@@ -1138,21 +1299,21 @@ _mm512_unpackhi_epi8(__m512i __A, __m512i __B) {
62, 64+62, 63, 64+63);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpackhi_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_unpackhi_epi8(__A, __B),
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpackhi_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_unpackhi_epi8(__A, __B),
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpackhi_epi16(__m512i __A, __m512i __B) {
return (__m512i)__builtin_shufflevector((__v32hi)__A, (__v32hi)__B,
4, 32+4, 5, 32+5,
@@ -1165,21 +1326,21 @@ _mm512_unpackhi_epi16(__m512i __A, __m512i __B) {
30, 32+30, 31, 32+31);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpackhi_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_unpackhi_epi16(__A, __B),
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpackhi_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_unpackhi_epi16(__A, __B),
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpacklo_epi8(__m512i __A, __m512i __B) {
return (__m512i)__builtin_shufflevector((__v64qi)__A, (__v64qi)__B,
0, 64+0, 1, 64+1,
@@ -1200,21 +1361,21 @@ _mm512_unpacklo_epi8(__m512i __A, __m512i __B) {
54, 64+54, 55, 64+55);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpacklo_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_unpacklo_epi8(__A, __B),
(__v64qi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpacklo_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
(__v64qi)_mm512_unpacklo_epi8(__A, __B),
(__v64qi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_unpacklo_epi16(__m512i __A, __m512i __B) {
return (__m512i)__builtin_shufflevector((__v32hi)__A, (__v32hi)__B,
0, 32+0, 1, 32+1,
@@ -1227,21 +1388,21 @@ _mm512_unpacklo_epi16(__m512i __A, __m512i __B) {
26, 32+26, 27, 32+27);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_unpacklo_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_unpacklo_epi16(__A, __B),
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_unpacklo_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
(__v32hi)_mm512_unpacklo_epi16(__A, __B),
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepi8_epi16(__m256i __A)
{
/* This function always performs a signed extension, but __v32qi is a char
@@ -1249,7 +1410,7 @@ _mm512_cvtepi8_epi16(__m256i __A)
return (__m512i)__builtin_convertvector((__v32qs)__A, __v32hi);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi8_epi16(__m512i __W, __mmask32 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1257,7 +1418,7 @@ _mm512_mask_cvtepi8_epi16(__m512i __W, __mmask32 __U, __m256i __A)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi8_epi16(__mmask32 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1265,13 +1426,13 @@ _mm512_maskz_cvtepi8_epi16(__mmask32 __U, __m256i __A)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtepu8_epi16(__m256i __A)
{
return (__m512i)__builtin_convertvector((__v32qu)__A, __v32hi);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu8_epi16(__m512i __W, __mmask32 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1279,7 +1440,7 @@ _mm512_mask_cvtepu8_epi16(__m512i __W, __mmask32 __U, __m256i __A)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1320,13 +1481,13 @@ _mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A)
(imm)), \
(__v32hi)_mm512_setzero_si512())
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sllv_epi16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_psllv32hi((__v32hi) __A, (__v32hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sllv_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1334,7 +1495,7 @@ _mm512_mask_sllv_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sllv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1342,13 +1503,13 @@ _mm512_maskz_sllv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sll_epi16(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psllw512((__v32hi) __A, (__v8hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sll_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1356,7 +1517,7 @@ _mm512_mask_sll_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sll_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1364,13 +1525,13 @@ _mm512_maskz_sll_epi16(__mmask32 __U, __m512i __A, __m128i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_slli_epi16(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psllwi512((__v32hi)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_slli_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1378,7 +1539,7 @@ _mm512_mask_slli_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1389,13 +1550,13 @@ _mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A, int __B)
#define _mm512_bslli_epi128(a, imm) \
(__m512i)__builtin_ia32_pslldqi512_byteshift((__v8di)(__m512i)(a), (int)(imm))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srlv_epi16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_psrlv32hi((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srlv_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1403,7 +1564,7 @@ _mm512_mask_srlv_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srlv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1411,13 +1572,13 @@ _mm512_maskz_srlv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srav_epi16(__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_psrav32hi((__v32hi)__A, (__v32hi)__B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srav_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1425,7 +1586,7 @@ _mm512_mask_srav_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srav_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1433,13 +1594,13 @@ _mm512_maskz_srav_epi16(__mmask32 __U, __m512i __A, __m512i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sra_epi16(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psraw512((__v32hi) __A, (__v8hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_sra_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1447,7 +1608,7 @@ _mm512_mask_sra_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_sra_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1455,13 +1616,13 @@ _mm512_maskz_sra_epi16(__mmask32 __U, __m512i __A, __m128i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srai_epi16(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psrawi512((__v32hi)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srai_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1469,7 +1630,7 @@ _mm512_mask_srai_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srai_epi16(__mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1477,13 +1638,13 @@ _mm512_maskz_srai_epi16(__mmask32 __U, __m512i __A, int __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srl_epi16(__m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_psrlw512((__v32hi) __A, (__v8hi) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srl_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1491,7 +1652,7 @@ _mm512_mask_srl_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srl_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1499,13 +1660,13 @@ _mm512_maskz_srl_epi16(__mmask32 __U, __m512i __A, __m128i __B)
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_srli_epi16(__m512i __A, int __B)
{
return (__m512i)__builtin_ia32_psrlwi512((__v32hi)__A, __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_srli_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1513,7 +1674,7 @@ _mm512_mask_srli_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
(__v32hi)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A, int __B)
{
return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
@@ -1524,7 +1685,7 @@ _mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A, int __B)
#define _mm512_bsrli_epi128(a, imm) \
(__m512i)__builtin_ia32_psrldqi512_byteshift((__v8di)(__m512i)(a), (int)(imm))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mov_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectw_512 ((__mmask32) __U,
@@ -1532,7 +1693,7 @@ _mm512_mask_mov_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
(__v32hi) __W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_epi16 (__mmask32 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectw_512 ((__mmask32) __U,
@@ -1540,7 +1701,7 @@ _mm512_maskz_mov_epi16 (__mmask32 __U, __m512i __A)
(__v32hi) _mm512_setzero_si512 ());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mov_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectb_512 ((__mmask64) __U,
@@ -1548,7 +1709,7 @@ _mm512_mask_mov_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
(__v64qi) __W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_epi8 (__mmask64 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_selectb_512 ((__mmask64) __U,
@@ -1556,7 +1717,7 @@ _mm512_maskz_mov_epi8 (__mmask64 __U, __m512i __A)
(__v64qi) _mm512_setzero_si512 ());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_set1_epi8 (__m512i __O, __mmask64 __M, char __A)
{
return (__m512i) __builtin_ia32_selectb_512(__M,
@@ -1564,7 +1725,7 @@ _mm512_mask_set1_epi8 (__m512i __O, __mmask64 __M, char __A)
(__v64qi) __O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_set1_epi8 (__mmask64 __M, char __A)
{
return (__m512i) __builtin_ia32_selectb_512(__M,
@@ -1572,21 +1733,30 @@ _mm512_maskz_set1_epi8 (__mmask64 __M, char __A)
(__v64qi) _mm512_setzero_si512());
}
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS512
_mm512_kunpackd (__mmask64 __A, __mmask64 __B)
{
return (__mmask64) __builtin_ia32_kunpckdi ((__mmask64) __A,
(__mmask64) __B);
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS512
_mm512_kunpackw (__mmask32 __A, __mmask32 __B)
{
return (__mmask32) __builtin_ia32_kunpcksi ((__mmask32) __A,
(__mmask32) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
+_mm512_loadu_epi16 (void const *__P)
+{
+ struct __loadu_epi16 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi16*)__P)->__v;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_epi16 (__m512i __W, __mmask32 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddquhi512_mask ((__v32hi *) __P,
@@ -1594,7 +1764,7 @@ _mm512_mask_loadu_epi16 (__m512i __W, __mmask32 __U, void const *__P)
(__mmask32) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_loadu_epi16 (__mmask32 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddquhi512_mask ((__v32hi *) __P,
@@ -1603,7 +1773,16 @@ _mm512_maskz_loadu_epi16 (__mmask32 __U, void const *__P)
(__mmask32) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline __m512i __DEFAULT_FN_ATTRS512
+_mm512_loadu_epi8 (void const *__P)
+{
+ struct __loadu_epi8 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi8*)__P)->__v;
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_epi8 (__m512i __W, __mmask64 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddquqi512_mask ((__v64qi *) __P,
@@ -1611,7 +1790,7 @@ _mm512_mask_loadu_epi8 (__m512i __W, __mmask64 __U, void const *__P)
(__mmask64) __U);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_loadu_epi8 (__mmask64 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddquqi512_mask ((__v64qi *) __P,
@@ -1619,7 +1798,17 @@ _mm512_maskz_loadu_epi8 (__mmask64 __U, void const *__P)
_mm512_setzero_si512 (),
(__mmask64) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+
+static __inline void __DEFAULT_FN_ATTRS512
+_mm512_storeu_epi16 (void *__P, __m512i __A)
+{
+ struct __storeu_epi16 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi16*)__P)->__v = __A;
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_epi16 (void *__P, __mmask32 __U, __m512i __A)
{
__builtin_ia32_storedquhi512_mask ((__v32hi *) __P,
@@ -1627,7 +1816,16 @@ _mm512_mask_storeu_epi16 (void *__P, __mmask32 __U, __m512i __A)
(__mmask32) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS
+static __inline void __DEFAULT_FN_ATTRS512
+_mm512_storeu_epi8 (void *__P, __m512i __A)
+{
+ struct __storeu_epi8 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi8*)__P)->__v = __A;
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_epi8 (void *__P, __mmask64 __U, __m512i __A)
{
__builtin_ia32_storedquqi512_mask ((__v64qi *) __P,
@@ -1635,86 +1833,86 @@ _mm512_mask_storeu_epi8 (void *__P, __mmask64 __U, __m512i __A)
(__mmask64) __U);
}
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS512
_mm512_test_epi8_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpneq_epi8_mask (_mm512_and_epi32 (__A, __B),
_mm512_setzero_si512());
}
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS512
_mm512_mask_test_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpneq_epi8_mask (__U, _mm512_and_epi32 (__A, __B),
_mm512_setzero_si512());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS512
_mm512_test_epi16_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpneq_epi16_mask (_mm512_and_epi32 (__A, __B),
_mm512_setzero_si512());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS512
_mm512_mask_test_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpneq_epi16_mask (__U, _mm512_and_epi32 (__A, __B),
_mm512_setzero_si512());
}
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS512
_mm512_testn_epi8_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpeq_epi8_mask (_mm512_and_epi32 (__A, __B), _mm512_setzero_si512());
}
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS512
_mm512_mask_testn_epi8_mask (__mmask64 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpeq_epi8_mask (__U, _mm512_and_epi32 (__A, __B),
_mm512_setzero_si512());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS512
_mm512_testn_epi16_mask (__m512i __A, __m512i __B)
{
return _mm512_cmpeq_epi16_mask (_mm512_and_epi32 (__A, __B),
_mm512_setzero_si512());
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS512
_mm512_mask_testn_epi16_mask (__mmask32 __U, __m512i __A, __m512i __B)
{
return _mm512_mask_cmpeq_epi16_mask (__U, _mm512_and_epi32 (__A, __B),
_mm512_setzero_si512());
}
-static __inline__ __mmask64 __DEFAULT_FN_ATTRS
+static __inline__ __mmask64 __DEFAULT_FN_ATTRS512
_mm512_movepi8_mask (__m512i __A)
{
return (__mmask64) __builtin_ia32_cvtb2mask512 ((__v64qi) __A);
}
-static __inline__ __mmask32 __DEFAULT_FN_ATTRS
+static __inline__ __mmask32 __DEFAULT_FN_ATTRS512
_mm512_movepi16_mask (__m512i __A)
{
return (__mmask32) __builtin_ia32_cvtw2mask512 ((__v32hi) __A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_movm_epi8 (__mmask64 __A)
{
return (__m512i) __builtin_ia32_cvtmask2b512 (__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_movm_epi16 (__mmask32 __A)
{
return (__m512i) __builtin_ia32_cvtmask2w512 (__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcastb_epi8 (__m128i __A)
{
return (__m512i)__builtin_shufflevector((__v16qi) __A, (__v16qi) __A,
@@ -1724,7 +1922,7 @@ _mm512_broadcastb_epi8 (__m128i __A)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcastb_epi8 (__m512i __O, __mmask64 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectb_512(__M,
@@ -1732,7 +1930,7 @@ _mm512_mask_broadcastb_epi8 (__m512i __O, __mmask64 __M, __m128i __A)
(__v64qi) __O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcastb_epi8 (__mmask64 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectb_512(__M,
@@ -1740,7 +1938,7 @@ _mm512_maskz_broadcastb_epi8 (__mmask64 __M, __m128i __A)
(__v64qi) _mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_set1_epi16 (__m512i __O, __mmask32 __M, short __A)
{
return (__m512i) __builtin_ia32_selectw_512(__M,
@@ -1748,7 +1946,7 @@ _mm512_mask_set1_epi16 (__m512i __O, __mmask32 __M, short __A)
(__v32hi) __O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_set1_epi16 (__mmask32 __M, short __A)
{
return (__m512i) __builtin_ia32_selectw_512(__M,
@@ -1756,7 +1954,7 @@ _mm512_maskz_set1_epi16 (__mmask32 __M, short __A)
(__v32hi) _mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcastw_epi16 (__m128i __A)
{
return (__m512i)__builtin_shufflevector((__v8hi) __A, (__v8hi) __A,
@@ -1764,7 +1962,7 @@ _mm512_broadcastw_epi16 (__m128i __A)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcastw_epi16 (__m512i __O, __mmask32 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectw_512(__M,
@@ -1772,7 +1970,7 @@ _mm512_mask_broadcastw_epi16 (__m512i __O, __mmask32 __M, __m128i __A)
(__v32hi) __O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcastw_epi16 (__mmask32 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectw_512(__M,
@@ -1780,13 +1978,13 @@ _mm512_maskz_broadcastw_epi16 (__mmask32 __M, __m128i __A)
(__v32hi) _mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_permutexvar_epi16 (__m512i __A, __m512i __B)
{
return (__m512i)__builtin_ia32_permvarhi512((__v32hi)__B, (__v32hi)__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_permutexvar_epi16 (__mmask32 __M, __m512i __A,
__m512i __B)
{
@@ -1795,7 +1993,7 @@ _mm512_maskz_permutexvar_epi16 (__mmask32 __M, __m512i __A,
(__v32hi)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_permutexvar_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
__m512i __B)
{
@@ -1832,15 +2030,14 @@ _mm512_mask_permutexvar_epi16 (__m512i __W, __mmask32 __M, __m512i __A,
(__v32hi)_mm512_dbsad_epu8((A), (B), (imm)), \
(__v32hi)_mm512_setzero_si512())
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_sad_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psadbw512 ((__v64qi) __A,
(__v64qi) __B);
}
-
-
+#undef __DEFAULT_FN_ATTRS512
#undef __DEFAULT_FN_ATTRS
#endif
diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h
index 8a00b3afa9d5..6e6c293af22e 100644
--- a/lib/Headers/avx512dqintrin.h
+++ b/lib/Headers/avx512dqintrin.h
@@ -29,180 +29,309 @@
#define __AVX512DQINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512dq"), __min_vector_width__(512)))
+#define __DEFAULT_FN_ATTRS512 __attribute__((__always_inline__, __nodebug__, __target__("avx512dq"), __min_vector_width__(512)))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512dq")))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline __mmask8 __DEFAULT_FN_ATTRS
+_knot_mask8(__mmask8 __M)
+{
+ return __builtin_ia32_knotqi(__M);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_kand_mask8(__mmask8 __A, __mmask8 __B)
+{
+ return (__mmask8)__builtin_ia32_kandqi((__mmask8)__A, (__mmask8)__B);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_kandn_mask8(__mmask8 __A, __mmask8 __B)
+{
+ return (__mmask8)__builtin_ia32_kandnqi((__mmask8)__A, (__mmask8)__B);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_kor_mask8(__mmask8 __A, __mmask8 __B)
+{
+ return (__mmask8)__builtin_ia32_korqi((__mmask8)__A, (__mmask8)__B);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_kxnor_mask8(__mmask8 __A, __mmask8 __B)
+{
+ return (__mmask8)__builtin_ia32_kxnorqi((__mmask8)__A, (__mmask8)__B);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_kxor_mask8(__mmask8 __A, __mmask8 __B)
+{
+ return (__mmask8)__builtin_ia32_kxorqi((__mmask8)__A, (__mmask8)__B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestc_mask8_u8(__mmask8 __A, __mmask8 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestcqi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestz_mask8_u8(__mmask8 __A, __mmask8 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestzqi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortest_mask8_u8(__mmask8 __A, __mmask8 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_kortestcqi(__A, __B);
+ return (unsigned char)__builtin_ia32_kortestzqi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestc_mask8_u8(__mmask8 __A, __mmask8 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestcqi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestz_mask8_u8(__mmask8 __A, __mmask8 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestzqi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktest_mask8_u8(__mmask8 __A, __mmask8 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_ktestcqi(__A, __B);
+ return (unsigned char)__builtin_ia32_ktestzqi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestc_mask16_u8(__mmask16 __A, __mmask16 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestchi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktestz_mask16_u8(__mmask16 __A, __mmask16 __B)
+{
+ return (unsigned char)__builtin_ia32_ktestzhi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_ktest_mask16_u8(__mmask16 __A, __mmask16 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_ktestchi(__A, __B);
+ return (unsigned char)__builtin_ia32_ktestzhi(__A, __B);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_kadd_mask8(__mmask8 __A, __mmask8 __B)
+{
+ return (__mmask8)__builtin_ia32_kaddqi((__mmask8)__A, (__mmask8)__B);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_kadd_mask16(__mmask16 __A, __mmask16 __B)
+{
+ return (__mmask16)__builtin_ia32_kaddhi((__mmask16)__A, (__mmask16)__B);
+}
+
+#define _kshiftli_mask8(A, I) \
+ (__mmask8)__builtin_ia32_kshiftliqi((__mmask8)(A), (unsigned int)(I))
+
+#define _kshiftri_mask8(A, I) \
+ (__mmask8)__builtin_ia32_kshiftriqi((__mmask8)(A), (unsigned int)(I))
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
+_cvtmask8_u32(__mmask8 __A) {
+ return (unsigned int)__builtin_ia32_kmovb((__mmask8)__A);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_cvtu32_mask8(unsigned int __A) {
+ return (__mmask8)__builtin_ia32_kmovb((__mmask8)__A);
+}
+
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+_load_mask8(__mmask8 *__A) {
+ return (__mmask8)__builtin_ia32_kmovb(*(__mmask8 *)__A);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_store_mask8(__mmask8 *__A, __mmask8 __B) {
+ *(__mmask8 *)__A = __builtin_ia32_kmovb((__mmask8)__B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mullo_epi64 (__m512i __A, __m512i __B) {
return (__m512i) ((__v8du) __A * (__v8du) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_mullo_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
(__v8di)_mm512_mullo_epi64(__A, __B),
(__v8di)__W);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_mullo_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
(__v8di)_mm512_mullo_epi64(__A, __B),
(__v8di)_mm512_setzero_si512());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_xor_pd(__m512d __A, __m512d __B) {
return (__m512d)((__v8du)__A ^ (__v8du)__B);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_xor_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_xor_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_xor_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_xor_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_xor_ps (__m512 __A, __m512 __B) {
return (__m512)((__v16su)__A ^ (__v16su)__B);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_xor_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_xor_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_xor_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_xor_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_or_pd(__m512d __A, __m512d __B) {
return (__m512d)((__v8du)__A | (__v8du)__B);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_or_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_or_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_or_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_or_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_or_ps(__m512 __A, __m512 __B) {
return (__m512)((__v16su)__A | (__v16su)__B);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_or_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_or_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_or_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_or_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_and_pd(__m512d __A, __m512d __B) {
return (__m512d)((__v8du)__A & (__v8du)__B);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_and_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_and_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_and_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_and_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_and_ps(__m512 __A, __m512 __B) {
return (__m512)((__v16su)__A & (__v16su)__B);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_and_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_and_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_and_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_and_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_andnot_pd(__m512d __A, __m512d __B) {
return (__m512d)(~(__v8du)__A & (__v8du)__B);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_andnot_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_andnot_pd(__A, __B),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_andnot_pd(__mmask8 __U, __m512d __A, __m512d __B) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_andnot_pd(__A, __B),
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_andnot_ps(__m512 __A, __m512 __B) {
return (__m512)(~(__v16su)__A & (__v16su)__B);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_andnot_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_andnot_ps(__A, __B),
(__v16sf)__W);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_andnot_ps(__mmask16 __U, __m512 __A, __m512 __B) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
(__v16sf)_mm512_andnot_ps(__A, __B),
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtpd_epi64 (__m512d __A) {
return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -210,7 +339,7 @@ _mm512_cvtpd_epi64 (__m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A,
(__v8di) __W,
@@ -218,7 +347,7 @@ _mm512_mask_cvtpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtpd_epi64 (__mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -241,7 +370,7 @@ _mm512_maskz_cvtpd_epi64 (__mmask8 __U, __m512d __A) {
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtpd_epu64 (__m512d __A) {
return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -249,7 +378,7 @@ _mm512_cvtpd_epu64 (__m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A,
(__v8di) __W,
@@ -257,7 +386,7 @@ _mm512_mask_cvtpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtpd_epu64 (__mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -280,7 +409,7 @@ _mm512_maskz_cvtpd_epu64 (__mmask8 __U, __m512d __A) {
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtps_epi64 (__m256 __A) {
return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -288,7 +417,7 @@ _mm512_cvtps_epi64 (__m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A,
(__v8di) __W,
@@ -296,7 +425,7 @@ _mm512_mask_cvtps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtps_epi64 (__mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -319,7 +448,7 @@ _mm512_maskz_cvtps_epi64 (__mmask8 __U, __m256 __A) {
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvtps_epu64 (__m256 __A) {
return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -327,7 +456,7 @@ _mm512_cvtps_epu64 (__m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvtps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A,
(__v8di) __W,
@@ -335,7 +464,7 @@ _mm512_mask_cvtps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtps_epu64 (__mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -359,19 +488,19 @@ _mm512_maskz_cvtps_epu64 (__mmask8 __U, __m256 __A) {
(__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtepi64_pd (__m512i __A) {
return (__m512d)__builtin_convertvector((__v8di)__A, __v8df);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_pd (__m512d __W, __mmask8 __U, __m512i __A) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_cvtepi64_pd(__A),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi64_pd (__mmask8 __U, __m512i __A) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_cvtepi64_pd(__A),
@@ -393,7 +522,7 @@ _mm512_maskz_cvtepi64_pd (__mmask8 __U, __m512i __A) {
(__v8df)_mm512_setzero_pd(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_cvtepi64_ps (__m512i __A) {
return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A,
(__v8sf) _mm256_setzero_ps(),
@@ -401,7 +530,7 @@ _mm512_cvtepi64_ps (__m512i __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepi64_ps (__m256 __W, __mmask8 __U, __m512i __A) {
return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A,
(__v8sf) __W,
@@ -409,7 +538,7 @@ _mm512_mask_cvtepi64_ps (__m256 __W, __mmask8 __U, __m512i __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepi64_ps (__mmask8 __U, __m512i __A) {
return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A,
(__v8sf) _mm256_setzero_ps(),
@@ -433,7 +562,7 @@ _mm512_maskz_cvtepi64_ps (__mmask8 __U, __m512i __A) {
(__mmask8)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvttpd_epi64 (__m512d __A) {
return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -441,7 +570,7 @@ _mm512_cvttpd_epi64 (__m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A,
(__v8di) __W,
@@ -449,7 +578,7 @@ _mm512_mask_cvttpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttpd_epi64 (__mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -472,7 +601,7 @@ _mm512_maskz_cvttpd_epi64 (__mmask8 __U, __m512d __A) {
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvttpd_epu64 (__m512d __A) {
return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -480,7 +609,7 @@ _mm512_cvttpd_epu64 (__m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A,
(__v8di) __W,
@@ -488,7 +617,7 @@ _mm512_mask_cvttpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttpd_epu64 (__mmask8 __U, __m512d __A) {
return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A,
(__v8di) _mm512_setzero_si512(),
@@ -511,7 +640,7 @@ _mm512_maskz_cvttpd_epu64 (__mmask8 __U, __m512d __A) {
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvttps_epi64 (__m256 __A) {
return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -519,7 +648,7 @@ _mm512_cvttps_epi64 (__m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A,
(__v8di) __W,
@@ -527,7 +656,7 @@ _mm512_mask_cvttps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttps_epi64 (__mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -550,7 +679,7 @@ _mm512_maskz_cvttps_epi64 (__mmask8 __U, __m256 __A) {
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_cvttps_epu64 (__m256 __A) {
return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -558,7 +687,7 @@ _mm512_cvttps_epu64 (__m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_cvttps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A,
(__v8di) __W,
@@ -566,7 +695,7 @@ _mm512_mask_cvttps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_cvttps_epu64 (__mmask8 __U, __m256 __A) {
return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A,
(__v8di) _mm512_setzero_si512(),
@@ -589,19 +718,19 @@ _mm512_maskz_cvttps_epu64 (__mmask8 __U, __m256 __A) {
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U), (int)(R))
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_cvtepu64_pd (__m512i __A) {
return (__m512d)__builtin_convertvector((__v8du)__A, __v8df);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu64_pd (__m512d __W, __mmask8 __U, __m512i __A) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_cvtepu64_pd(__A),
(__v8df)__W);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu64_pd (__mmask8 __U, __m512i __A) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
(__v8df)_mm512_cvtepu64_pd(__A),
@@ -625,7 +754,7 @@ _mm512_maskz_cvtepu64_pd (__mmask8 __U, __m512i __A) {
(__mmask8)(U), (int)(R))
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_cvtepu64_ps (__m512i __A) {
return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A,
(__v8sf) _mm256_setzero_ps(),
@@ -633,7 +762,7 @@ _mm512_cvtepu64_ps (__m512i __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_mask_cvtepu64_ps (__m256 __W, __mmask8 __U, __m512i __A) {
return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A,
(__v8sf) __W,
@@ -641,7 +770,7 @@ _mm512_mask_cvtepu64_ps (__m256 __W, __mmask8 __U, __m512i __A) {
_MM_FROUND_CUR_DIRECTION);
}
-static __inline__ __m256 __DEFAULT_FN_ATTRS
+static __inline__ __m256 __DEFAULT_FN_ATTRS512
_mm512_maskz_cvtepu64_ps (__mmask8 __U, __m512i __A) {
return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A,
(__v8sf) _mm256_setzero_ps(),
@@ -935,32 +1064,32 @@ _mm512_maskz_cvtepu64_ps (__mmask8 __U, __m512i __A) {
(__v2df)_mm_setzero_pd(), \
(__mmask8)(U), (int)(C), (int)(R))
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
_mm512_movepi32_mask (__m512i __A)
{
return (__mmask16) __builtin_ia32_cvtd2mask512 ((__v16si) __A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_movm_epi32 (__mmask16 __A)
{
return (__m512i) __builtin_ia32_cvtmask2d512 (__A);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_movm_epi64 (__mmask8 __A)
{
return (__m512i) __builtin_ia32_cvtmask2q512 (__A);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS512
_mm512_movepi64_mask (__m512i __A)
{
return (__mmask8) __builtin_ia32_cvtq2mask512 ((__v8di) __A);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_broadcast_f32x2 (__m128 __A)
{
return (__m512)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A,
@@ -968,7 +1097,7 @@ _mm512_broadcast_f32x2 (__m128 __A)
0, 1, 0, 1, 0, 1, 0, 1);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_f32x2 (__m512 __O, __mmask16 __M, __m128 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
@@ -976,7 +1105,7 @@ _mm512_mask_broadcast_f32x2 (__m512 __O, __mmask16 __M, __m128 __A)
(__v16sf)__O);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_f32x2 (__mmask16 __M, __m128 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
@@ -984,7 +1113,7 @@ _mm512_maskz_broadcast_f32x2 (__mmask16 __M, __m128 __A)
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_broadcast_f32x8(__m256 __A)
{
return (__m512)__builtin_shufflevector((__v8sf)__A, (__v8sf)__A,
@@ -992,7 +1121,7 @@ _mm512_broadcast_f32x8(__m256 __A)
0, 1, 2, 3, 4, 5, 6, 7);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_f32x8(__m512 __O, __mmask16 __M, __m256 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
@@ -1000,7 +1129,7 @@ _mm512_mask_broadcast_f32x8(__m512 __O, __mmask16 __M, __m256 __A)
(__v16sf)__O);
}
-static __inline__ __m512 __DEFAULT_FN_ATTRS
+static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_f32x8(__mmask16 __M, __m256 __A)
{
return (__m512)__builtin_ia32_selectps_512((__mmask16)__M,
@@ -1008,14 +1137,14 @@ _mm512_maskz_broadcast_f32x8(__mmask16 __M, __m256 __A)
(__v16sf)_mm512_setzero_ps());
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_broadcast_f64x2(__m128d __A)
{
return (__m512d)__builtin_shufflevector((__v2df)__A, (__v2df)__A,
0, 1, 0, 1, 0, 1, 0, 1);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_f64x2(__m512d __O, __mmask8 __M, __m128d __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__M,
@@ -1023,7 +1152,7 @@ _mm512_mask_broadcast_f64x2(__m512d __O, __mmask8 __M, __m128d __A)
(__v8df)__O);
}
-static __inline__ __m512d __DEFAULT_FN_ATTRS
+static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_f64x2(__mmask8 __M, __m128d __A)
{
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__M,
@@ -1031,7 +1160,7 @@ _mm512_maskz_broadcast_f64x2(__mmask8 __M, __m128d __A)
(__v8df)_mm512_setzero_pd());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcast_i32x2 (__m128i __A)
{
return (__m512i)__builtin_shufflevector((__v4si)__A, (__v4si)__A,
@@ -1039,7 +1168,7 @@ _mm512_broadcast_i32x2 (__m128i __A)
0, 1, 0, 1, 0, 1, 0, 1);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_i32x2 (__m512i __O, __mmask16 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -1047,7 +1176,7 @@ _mm512_mask_broadcast_i32x2 (__m512i __O, __mmask16 __M, __m128i __A)
(__v16si)__O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_i32x2 (__mmask16 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -1055,7 +1184,7 @@ _mm512_maskz_broadcast_i32x2 (__mmask16 __M, __m128i __A)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcast_i32x8(__m256i __A)
{
return (__m512i)__builtin_shufflevector((__v8si)__A, (__v8si)__A,
@@ -1063,7 +1192,7 @@ _mm512_broadcast_i32x8(__m256i __A)
0, 1, 2, 3, 4, 5, 6, 7);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_i32x8(__m512i __O, __mmask16 __M, __m256i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -1071,7 +1200,7 @@ _mm512_mask_broadcast_i32x8(__m512i __O, __mmask16 __M, __m256i __A)
(__v16si)__O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_i32x8(__mmask16 __M, __m256i __A)
{
return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
@@ -1079,14 +1208,14 @@ _mm512_maskz_broadcast_i32x8(__mmask16 __M, __m256i __A)
(__v16si)_mm512_setzero_si512());
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_broadcast_i64x2(__m128i __A)
{
return (__m512i)__builtin_shufflevector((__v2di)__A, (__v2di)__A,
0, 1, 0, 1, 0, 1, 0, 1);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_broadcast_i64x2(__m512i __O, __mmask8 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -1094,7 +1223,7 @@ _mm512_mask_broadcast_i64x2(__m512i __O, __mmask8 __M, __m128i __A)
(__v8di)__O);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS
+static __inline__ __m512i __DEFAULT_FN_ATTRS512
_mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A)
{
return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
@@ -1256,6 +1385,7 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A)
(__mmask8)__builtin_ia32_fpclassss_mask((__v4sf)(__m128)(A), (int)(imm), \
(__mmask8)(U))
+#undef __DEFAULT_FN_ATTRS512
#undef __DEFAULT_FN_ATTRS
#endif
diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h
index 8dd4a0a40eea..1c19993ff1bb 100644
--- a/lib/Headers/avx512fintrin.h
+++ b/lib/Headers/avx512fintrin.h
@@ -175,6 +175,7 @@ typedef enum
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS512 __attribute__((__always_inline__, __nodebug__, __target__("avx512f"), __min_vector_width__(512)))
#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512f"), __min_vector_width__(128)))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512f")))
/* Create vectors with repeated elements */
@@ -508,13 +509,13 @@ _mm512_castsi512_si256 (__m512i __A)
return (__m256i)__builtin_shufflevector(__A, __A , 0, 1, 2, 3);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_int2mask(int __a)
{
return (__mmask16)__a;
}
-static __inline__ int __DEFAULT_FN_ATTRS512
+static __inline__ int __DEFAULT_FN_ATTRS
_mm512_mask2int(__mmask16 __a)
{
return (int)__a;
@@ -4329,6 +4330,15 @@ _mm512_loadu_si512 (void const *__P)
}
static __inline __m512i __DEFAULT_FN_ATTRS512
+_mm512_loadu_epi32 (void const *__P)
+{
+ struct __loadu_epi32 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi32*)__P)->__v;
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *) __P,
@@ -4347,6 +4357,15 @@ _mm512_maskz_loadu_epi32(__mmask16 __U, void const *__P)
}
static __inline __m512i __DEFAULT_FN_ATTRS512
+_mm512_loadu_epi64 (void const *__P)
+{
+ struct __loadu_epi64 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi64*)__P)->__v;
+}
+
+static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void const *__P)
{
return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *) __P,
@@ -4482,6 +4501,15 @@ _mm512_load_epi64 (void const *__P)
/* SIMD store ops */
static __inline void __DEFAULT_FN_ATTRS512
+_mm512_storeu_epi64 (void *__P, __m512i __A)
+{
+ struct __storeu_epi64 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi64*)__P)->__v = __A;
+}
+
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_epi64(void *__P, __mmask8 __U, __m512i __A)
{
__builtin_ia32_storedqudi512_mask ((long long *)__P, (__v8di) __A,
@@ -4498,6 +4526,15 @@ _mm512_storeu_si512 (void *__P, __m512i __A)
}
static __inline void __DEFAULT_FN_ATTRS512
+_mm512_storeu_epi32 (void *__P, __m512i __A)
+{
+ struct __storeu_epi32 {
+ __m512i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi32*)__P)->__v = __A;
+}
+
+static __inline void __DEFAULT_FN_ATTRS512
_mm512_mask_storeu_epi32(void *__P, __mmask16 __U, __m512i __A)
{
__builtin_ia32_storedqusi512_mask ((int *)__P, (__v16si) __A,
@@ -4580,7 +4617,7 @@ _mm512_store_epi64 (void *__P, __m512i __A)
/* Mask ops */
-static __inline __mmask16 __DEFAULT_FN_ATTRS512
+static __inline __mmask16 __DEFAULT_FN_ATTRS
_mm512_knot(__mmask16 __M)
{
return __builtin_ia32_knothi(__M);
@@ -5622,7 +5659,7 @@ _mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B)
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(U), (int)(R))
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kmov (__mmask16 __A)
{
return __A;
@@ -7593,177 +7630,177 @@ _mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A)
#define _mm512_i64gather_ps(index, addr, scale) \
(__m256)__builtin_ia32_gatherdiv16sf((__v8sf)_mm256_undefined_ps(), \
- (float const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), (__mmask8)-1, \
(int)(scale))
#define _mm512_mask_i64gather_ps(v1_old, mask, index, addr, scale) \
(__m256)__builtin_ia32_gatherdiv16sf((__v8sf)(__m256)(v1_old),\
- (float const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm512_i64gather_epi32(index, addr, scale) \
(__m256i)__builtin_ia32_gatherdiv16si((__v8si)_mm256_undefined_si256(), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), \
(__mmask8)-1, (int)(scale))
#define _mm512_mask_i64gather_epi32(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gatherdiv16si((__v8si)(__m256i)(v1_old), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm512_i64gather_pd(index, addr, scale) \
(__m512d)__builtin_ia32_gatherdiv8df((__v8df)_mm512_undefined_pd(), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), (__mmask8)-1, \
(int)(scale))
#define _mm512_mask_i64gather_pd(v1_old, mask, index, addr, scale) \
(__m512d)__builtin_ia32_gatherdiv8df((__v8df)(__m512d)(v1_old), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm512_i64gather_epi64(index, addr, scale) \
(__m512i)__builtin_ia32_gatherdiv8di((__v8di)_mm512_undefined_epi32(), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), (__mmask8)-1, \
(int)(scale))
#define _mm512_mask_i64gather_epi64(v1_old, mask, index, addr, scale) \
(__m512i)__builtin_ia32_gatherdiv8di((__v8di)(__m512i)(v1_old), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v8di)(__m512i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm512_i32gather_ps(index, addr, scale) \
(__m512)__builtin_ia32_gathersiv16sf((__v16sf)_mm512_undefined_ps(), \
- (float const *)(addr), \
+ (void const *)(addr), \
(__v16sf)(__m512)(index), \
(__mmask16)-1, (int)(scale))
#define _mm512_mask_i32gather_ps(v1_old, mask, index, addr, scale) \
(__m512)__builtin_ia32_gathersiv16sf((__v16sf)(__m512)(v1_old), \
- (float const *)(addr), \
+ (void const *)(addr), \
(__v16sf)(__m512)(index), \
(__mmask16)(mask), (int)(scale))
#define _mm512_i32gather_epi32(index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv16si((__v16si)_mm512_undefined_epi32(), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v16si)(__m512i)(index), \
(__mmask16)-1, (int)(scale))
#define _mm512_mask_i32gather_epi32(v1_old, mask, index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv16si((__v16si)(__m512i)(v1_old), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v16si)(__m512i)(index), \
(__mmask16)(mask), (int)(scale))
#define _mm512_i32gather_pd(index, addr, scale) \
(__m512d)__builtin_ia32_gathersiv8df((__v8df)_mm512_undefined_pd(), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v8si)(__m256i)(index), (__mmask8)-1, \
(int)(scale))
#define _mm512_mask_i32gather_pd(v1_old, mask, index, addr, scale) \
(__m512d)__builtin_ia32_gathersiv8df((__v8df)(__m512d)(v1_old), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v8si)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm512_i32gather_epi64(index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv8di((__v8di)_mm512_undefined_epi32(), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v8si)(__m256i)(index), (__mmask8)-1, \
(int)(scale))
#define _mm512_mask_i32gather_epi64(v1_old, mask, index, addr, scale) \
(__m512i)__builtin_ia32_gathersiv8di((__v8di)(__m512i)(v1_old), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v8si)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm512_i64scatter_ps(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv16sf((float *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv16sf((void *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
(__v8sf)(__m256)(v1), (int)(scale))
#define _mm512_mask_i64scatter_ps(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv16sf((float *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv16sf((void *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
(__v8sf)(__m256)(v1), (int)(scale))
#define _mm512_i64scatter_epi32(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv16si((int *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv16si((void *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
(__v8si)(__m256i)(v1), (int)(scale))
#define _mm512_mask_i64scatter_epi32(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv16si((int *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv16si((void *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
(__v8si)(__m256i)(v1), (int)(scale))
#define _mm512_i64scatter_pd(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv8df((double *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv8df((void *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
(__v8df)(__m512d)(v1), (int)(scale))
#define _mm512_mask_i64scatter_pd(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv8df((double *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv8df((void *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
(__v8df)(__m512d)(v1), (int)(scale))
#define _mm512_i64scatter_epi64(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv8di((long long *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv8di((void *)(addr), (__mmask8)-1, \
(__v8di)(__m512i)(index), \
(__v8di)(__m512i)(v1), (int)(scale))
#define _mm512_mask_i64scatter_epi64(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv8di((long long *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv8di((void *)(addr), (__mmask8)(mask), \
(__v8di)(__m512i)(index), \
(__v8di)(__m512i)(v1), (int)(scale))
#define _mm512_i32scatter_ps(addr, index, v1, scale) \
- __builtin_ia32_scattersiv16sf((float *)(addr), (__mmask16)-1, \
+ __builtin_ia32_scattersiv16sf((void *)(addr), (__mmask16)-1, \
(__v16si)(__m512i)(index), \
(__v16sf)(__m512)(v1), (int)(scale))
#define _mm512_mask_i32scatter_ps(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv16sf((float *)(addr), (__mmask16)(mask), \
+ __builtin_ia32_scattersiv16sf((void *)(addr), (__mmask16)(mask), \
(__v16si)(__m512i)(index), \
(__v16sf)(__m512)(v1), (int)(scale))
#define _mm512_i32scatter_epi32(addr, index, v1, scale) \
- __builtin_ia32_scattersiv16si((int *)(addr), (__mmask16)-1, \
+ __builtin_ia32_scattersiv16si((void *)(addr), (__mmask16)-1, \
(__v16si)(__m512i)(index), \
(__v16si)(__m512i)(v1), (int)(scale))
#define _mm512_mask_i32scatter_epi32(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv16si((int *)(addr), (__mmask16)(mask), \
+ __builtin_ia32_scattersiv16si((void *)(addr), (__mmask16)(mask), \
(__v16si)(__m512i)(index), \
(__v16si)(__m512i)(v1), (int)(scale))
#define _mm512_i32scatter_pd(addr, index, v1, scale) \
- __builtin_ia32_scattersiv8df((double *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv8df((void *)(addr), (__mmask8)-1, \
(__v8si)(__m256i)(index), \
(__v8df)(__m512d)(v1), (int)(scale))
#define _mm512_mask_i32scatter_pd(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv8df((double *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv8df((void *)(addr), (__mmask8)(mask), \
(__v8si)(__m256i)(index), \
(__v8df)(__m512d)(v1), (int)(scale))
#define _mm512_i32scatter_epi64(addr, index, v1, scale) \
- __builtin_ia32_scattersiv8di((long long *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv8di((void *)(addr), (__mmask8)-1, \
(__v8si)(__m256i)(index), \
(__v8di)(__m512i)(v1), (int)(scale))
#define _mm512_mask_i32scatter_epi64(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv8di((long long *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv8di((void *)(addr), (__mmask8)(mask), \
(__v8si)(__m256i)(index), \
(__v8di)(__m512i)(v1), (int)(scale))
@@ -8320,54 +8357,105 @@ _mm512_mask_permutexvar_epi32 (__m512i __W, __mmask16 __M, __m512i __X,
#define _mm512_mask_permutevar_epi32 _mm512_mask_permutexvar_epi32
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kand (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kandhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kandn (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kandnhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kor (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_korhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ int __DEFAULT_FN_ATTRS512
+static __inline__ int __DEFAULT_FN_ATTRS
_mm512_kortestc (__mmask16 __A, __mmask16 __B)
{
return __builtin_ia32_kortestchi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ int __DEFAULT_FN_ATTRS512
+static __inline__ int __DEFAULT_FN_ATTRS
_mm512_kortestz (__mmask16 __A, __mmask16 __B)
{
return __builtin_ia32_kortestzhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestc_mask16_u8(__mmask16 __A, __mmask16 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestchi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortestz_mask16_u8(__mmask16 __A, __mmask16 __B)
+{
+ return (unsigned char)__builtin_ia32_kortestzhi(__A, __B);
+}
+
+static __inline__ unsigned char __DEFAULT_FN_ATTRS
+_kortest_mask16_u8(__mmask16 __A, __mmask16 __B, unsigned char *__C) {
+ *__C = (unsigned char)__builtin_ia32_kortestchi(__A, __B);
+ return (unsigned char)__builtin_ia32_kortestzhi(__A, __B);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kunpackb (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kunpckhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kxnor (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kxnorhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ __mmask16 __DEFAULT_FN_ATTRS512
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
_mm512_kxor (__mmask16 __A, __mmask16 __B)
{
return (__mmask16) __builtin_ia32_kxorhi ((__mmask16) __A, (__mmask16) __B);
}
+#define _kand_mask16 _mm512_kand
+#define _kandn_mask16 _mm512_kandn
+#define _knot_mask16 _mm512_knot
+#define _kor_mask16 _mm512_kor
+#define _kxnor_mask16 _mm512_kxnor
+#define _kxor_mask16 _mm512_kxor
+
+#define _kshiftli_mask16(A, I) \
+ (__mmask16)__builtin_ia32_kshiftlihi((__mmask16)(A), (unsigned int)(I))
+
+#define _kshiftri_mask16(A, I) \
+ (__mmask16)__builtin_ia32_kshiftrihi((__mmask16)(A), (unsigned int)(I))
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
+_cvtmask16_u32(__mmask16 __A) {
+ return (unsigned int)__builtin_ia32_kmovw((__mmask16)__A);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_cvtu32_mask16(unsigned int __A) {
+ return (__mmask16)__builtin_ia32_kmovw((__mmask16)__A);
+}
+
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_load_mask16(__mmask16 *__A) {
+ return (__mmask16)__builtin_ia32_kmovw(*(__mmask16 *)__A);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_store_mask16(__mmask16 *__A, __mmask16 __B) {
+ *(__mmask16 *)__A = __builtin_ia32_kmovw((__mmask16)__B);
+}
+
static __inline__ void __DEFAULT_FN_ATTRS512
_mm512_stream_si512 (__m512i * __P, __m512i __A)
{
@@ -9594,5 +9682,6 @@ _mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __V) {
#undef __DEFAULT_FN_ATTRS512
#undef __DEFAULT_FN_ATTRS128
+#undef __DEFAULT_FN_ATTRS
#endif /* __AVX512FINTRIN_H */
diff --git a/lib/Headers/avx512pfintrin.h b/lib/Headers/avx512pfintrin.h
index 5b8260b77c63..73b2234fb410 100644
--- a/lib/Headers/avx512pfintrin.h
+++ b/lib/Headers/avx512pfintrin.h
@@ -33,78 +33,78 @@
#define _mm512_mask_prefetch_i32gather_pd(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfdpd((__mmask8)(mask), (__v8si)(__m256i)(index), \
- (long long const *)(addr), (int)(scale), \
+ (void const *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_prefetch_i32gather_pd(index, addr, scale, hint) \
__builtin_ia32_gatherpfdpd((__mmask8) -1, (__v8si)(__m256i)(index), \
- (long long const *)(addr), (int)(scale), \
+ (void const *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_mask_prefetch_i32gather_ps(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfdps((__mmask16)(mask), \
- (__v16si)(__m512i)(index), (int const *)(addr), \
+ (__v16si)(__m512i)(index), (void const *)(addr), \
(int)(scale), (int)(hint))
#define _mm512_prefetch_i32gather_ps(index, addr, scale, hint) \
__builtin_ia32_gatherpfdps((__mmask16) -1, \
- (__v16si)(__m512i)(index), (int const *)(addr), \
+ (__v16si)(__m512i)(index), (void const *)(addr), \
(int)(scale), (int)(hint))
#define _mm512_mask_prefetch_i64gather_pd(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfqpd((__mmask8)(mask), (__v8di)(__m512i)(index), \
- (long long const *)(addr), (int)(scale), \
+ (void const *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_prefetch_i64gather_pd(index, addr, scale, hint) \
__builtin_ia32_gatherpfqpd((__mmask8) -1, (__v8di)(__m512i)(index), \
- (long long const *)(addr), (int)(scale), \
+ (void const *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_mask_prefetch_i64gather_ps(index, mask, addr, scale, hint) \
__builtin_ia32_gatherpfqps((__mmask8)(mask), (__v8di)(__m512i)(index), \
- (int const *)(addr), (int)(scale), (int)(hint))
+ (void const *)(addr), (int)(scale), (int)(hint))
#define _mm512_prefetch_i64gather_ps(index, addr, scale, hint) \
__builtin_ia32_gatherpfqps((__mmask8) -1, (__v8di)(__m512i)(index), \
- (int const *)(addr), (int)(scale), (int)(hint))
+ (void const *)(addr), (int)(scale), (int)(hint))
#define _mm512_prefetch_i32scatter_pd(addr, index, scale, hint) \
__builtin_ia32_scatterpfdpd((__mmask8)-1, (__v8si)(__m256i)(index), \
- (long long *)(addr), (int)(scale), \
+ (void *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_mask_prefetch_i32scatter_pd(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfdpd((__mmask8)(mask), (__v8si)(__m256i)(index), \
- (long long *)(addr), (int)(scale), \
+ (void *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_prefetch_i32scatter_ps(addr, index, scale, hint) \
__builtin_ia32_scatterpfdps((__mmask16)-1, (__v16si)(__m512i)(index), \
- (int *)(addr), (int)(scale), (int)(hint))
+ (void *)(addr), (int)(scale), (int)(hint))
#define _mm512_mask_prefetch_i32scatter_ps(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfdps((__mmask16)(mask), \
- (__v16si)(__m512i)(index), (int *)(addr), \
+ (__v16si)(__m512i)(index), (void *)(addr), \
(int)(scale), (int)(hint))
#define _mm512_prefetch_i64scatter_pd(addr, index, scale, hint) \
__builtin_ia32_scatterpfqpd((__mmask8)-1, (__v8di)(__m512i)(index), \
- (long long *)(addr), (int)(scale), \
+ (void *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_mask_prefetch_i64scatter_pd(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfqpd((__mmask8)(mask), (__v8di)(__m512i)(index), \
- (long long *)(addr), (int)(scale), \
+ (void *)(addr), (int)(scale), \
(int)(hint))
#define _mm512_prefetch_i64scatter_ps(addr, index, scale, hint) \
__builtin_ia32_scatterpfqps((__mmask8)-1, (__v8di)(__m512i)(index), \
- (int *)(addr), (int)(scale), (int)(hint))
+ (void *)(addr), (int)(scale), (int)(hint))
#define _mm512_mask_prefetch_i64scatter_ps(addr, mask, index, scale, hint) \
__builtin_ia32_scatterpfqps((__mmask8)(mask), (__v8di)(__m512i)(index), \
- (int *)(addr), (int)(scale), (int)(hint))
+ (void *)(addr), (int)(scale), (int)(hint))
#undef __DEFAULT_FN_ATTRS
diff --git a/lib/Headers/avx512vbmi2intrin.h b/lib/Headers/avx512vbmi2intrin.h
index d2a58094fd07..53242524293f 100644
--- a/lib/Headers/avx512vbmi2intrin.h
+++ b/lib/Headers/avx512vbmi2intrin.h
@@ -227,167 +227,141 @@ _mm512_maskz_expandloadu_epi8(__mmask64 __U, void const *__P)
(__v32hi)_mm512_setzero_si512())
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_shldv_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B)
+_mm512_shldv_epi64(__m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvq512_mask ((__v8di) __S,
- (__v8di) __A,
- (__v8di) __B,
- __U);
+ return (__m512i)__builtin_ia32_vpshldvq512((__v8di)__A, (__v8di)__B,
+ (__v8di)__C);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_shldv_epi64(__mmask8 __U, __m512i __S, __m512i __A, __m512i __B)
+_mm512_mask_shldv_epi64(__m512i __A, __mmask8 __U, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvq512_maskz ((__v8di) __S,
- (__v8di) __A,
- (__v8di) __B,
- __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_shldv_epi64(__A, __B, __C),
+ (__v8di)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_shldv_epi64(__m512i __S, __m512i __A, __m512i __B)
+_mm512_maskz_shldv_epi64(__mmask8 __U, __m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvq512_mask ((__v8di) __S,
- (__v8di) __A,
- (__v8di) __B,
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_shldv_epi64(__A, __B, __C),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_shldv_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B)
+_mm512_shldv_epi32(__m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- __U);
+ return (__m512i)__builtin_ia32_vpshldvd512((__v16si)__A, (__v16si)__B,
+ (__v16si)__C);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_shldv_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B)
+_mm512_mask_shldv_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvd512_maskz ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- __U);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_shldv_epi32(__A, __B, __C),
+ (__v16si)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_shldv_epi32(__m512i __S, __m512i __A, __m512i __B)
+_mm512_maskz_shldv_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_shldv_epi32(__A, __B, __C),
+ (__v16si)_mm512_setzero_si512());
}
-
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_shldv_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B)
+_mm512_shldv_epi16(__m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvw512_mask ((__v32hi) __S,
- (__v32hi) __A,
- (__v32hi) __B,
- __U);
+ return (__m512i)__builtin_ia32_vpshldvw512((__v32hi)__A, (__v32hi)__B,
+ (__v32hi)__C);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_shldv_epi16(__mmask32 __U, __m512i __S, __m512i __A, __m512i __B)
+_mm512_mask_shldv_epi16(__m512i __A, __mmask32 __U, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvw512_maskz ((__v32hi) __S,
- (__v32hi) __A,
- (__v32hi) __B,
- __U);
+ return (__m512i)__builtin_ia32_selectw_512(__U,
+ (__v32hi)_mm512_shldv_epi16(__A, __B, __C),
+ (__v32hi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_shldv_epi16(__m512i __S, __m512i __A, __m512i __B)
+_mm512_maskz_shldv_epi16(__mmask32 __U, __m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshldvw512_mask ((__v32hi) __S,
- (__v32hi) __A,
- (__v32hi) __B,
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_selectw_512(__U,
+ (__v32hi)_mm512_shldv_epi16(__A, __B, __C),
+ (__v32hi)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_shrdv_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B)
+_mm512_shrdv_epi64(__m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvq512_mask ((__v8di) __S,
- (__v8di) __A,
- (__v8di) __B,
- __U);
+ return (__m512i)__builtin_ia32_vpshrdvq512((__v8di)__A, (__v8di)__B,
+ (__v8di)__C);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_shrdv_epi64(__mmask8 __U, __m512i __S, __m512i __A, __m512i __B)
+_mm512_mask_shrdv_epi64(__m512i __A, __mmask8 __U, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvq512_maskz ((__v8di) __S,
- (__v8di) __A,
- (__v8di) __B,
- __U);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_shrdv_epi64(__A, __B, __C),
+ (__v8di)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_shrdv_epi64(__m512i __S, __m512i __A, __m512i __B)
+_mm512_maskz_shrdv_epi64(__mmask8 __U, __m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvq512_mask ((__v8di) __S,
- (__v8di) __A,
- (__v8di) __B,
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_selectq_512(__U,
+ (__v8di)_mm512_shrdv_epi64(__A, __B, __C),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_shrdv_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B)
+_mm512_shrdv_epi32(__m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- __U);
+ return (__m512i)__builtin_ia32_vpshrdvd512((__v16si)__A, (__v16si)__B,
+ (__v16si)__C);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_shrdv_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B)
+_mm512_mask_shrdv_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvd512_maskz ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- __U);
+ return (__m512i) __builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_shrdv_epi32(__A, __B, __C),
+ (__v16si)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_shrdv_epi32(__m512i __S, __m512i __A, __m512i __B)
+_mm512_maskz_shrdv_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvd512_mask ((__v16si) __S,
- (__v16si) __A,
- (__v16si) __B,
- (__mmask16) -1);
+ return (__m512i) __builtin_ia32_selectd_512(__U,
+ (__v16si)_mm512_shrdv_epi32(__A, __B, __C),
+ (__v16si)_mm512_setzero_si512());
}
-
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_shrdv_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B)
+_mm512_shrdv_epi16(__m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvw512_mask ((__v32hi) __S,
- (__v32hi) __A,
- (__v32hi) __B,
- __U);
+ return (__m512i)__builtin_ia32_vpshrdvw512((__v32hi)__A, (__v32hi)__B,
+ (__v32hi)__C);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_shrdv_epi16(__mmask32 __U, __m512i __S, __m512i __A, __m512i __B)
+_mm512_mask_shrdv_epi16(__m512i __A, __mmask32 __U, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvw512_maskz ((__v32hi) __S,
- (__v32hi) __A,
- (__v32hi) __B,
- __U);
+ return (__m512i)__builtin_ia32_selectw_512(__U,
+ (__v32hi)_mm512_shrdv_epi16(__A, __B, __C),
+ (__v32hi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_shrdv_epi16(__m512i __S, __m512i __A, __m512i __B)
+_mm512_maskz_shrdv_epi16(__mmask32 __U, __m512i __A, __m512i __B, __m512i __C)
{
- return (__m512i) __builtin_ia32_vpshrdvw512_mask ((__v32hi) __S,
- (__v32hi) __A,
- (__v32hi) __B,
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_selectw_512(__U,
+ (__v32hi)_mm512_shrdv_epi16(__A, __B, __C),
+ (__v32hi)_mm512_setzero_si512());
}
diff --git a/lib/Headers/avx512vbmiintrin.h b/lib/Headers/avx512vbmiintrin.h
index b6e93c285871..5463d9015504 100644
--- a/lib/Headers/avx512vbmiintrin.h
+++ b/lib/Headers/avx512vbmiintrin.h
@@ -91,30 +91,26 @@ _mm512_mask_permutexvar_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_multishift_epi64_epi8 (__m512i __W, __mmask64 __M, __m512i __X, __m512i __Y)
+_mm512_multishift_epi64_epi8(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
- (__v64qi) __Y,
- (__v64qi) __W,
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_vpmultishiftqb512((__v64qi)__X, (__v64qi) __Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_multishift_epi64_epi8 (__mmask64 __M, __m512i __X, __m512i __Y)
+_mm512_mask_multishift_epi64_epi8(__m512i __W, __mmask64 __M, __m512i __X,
+ __m512i __Y)
{
- return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
- (__v64qi) __Y,
- (__v64qi) _mm512_setzero_si512 (),
- (__mmask64) __M);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_multishift_epi64_epi8(__X, __Y),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_multishift_epi64_epi8 (__m512i __X, __m512i __Y)
+_mm512_maskz_multishift_epi64_epi8(__mmask64 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
- (__v64qi) __Y,
- (__v64qi) _mm512_undefined_epi32 (),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__M,
+ (__v64qi)_mm512_multishift_epi64_epi8(__X, __Y),
+ (__v64qi)_mm512_setzero_si512());
}
diff --git a/lib/Headers/avx512vbmivlintrin.h b/lib/Headers/avx512vbmivlintrin.h
index 9a0400b2b5d5..b5d5aa9af523 100644
--- a/lib/Headers/avx512vbmivlintrin.h
+++ b/lib/Headers/avx512vbmivlintrin.h
@@ -150,61 +150,49 @@ _mm256_mask_permutexvar_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i __Y)
+_mm_multishift_epi64_epi8(__m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
- (__v16qi) __Y,
- (__v16qi) __W,
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_vpmultishiftqb128((__v16qi)__X, (__v16qi)__Y);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y)
+_mm_mask_multishift_epi64_epi8(__m128i __W, __mmask16 __M, __m128i __X,
+ __m128i __Y)
{
- return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
- (__v16qi) __Y,
- (__v16qi)
- _mm_setzero_si128 (),
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_multishift_epi64_epi8(__X, __Y),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y)
+_mm_maskz_multishift_epi64_epi8(__mmask16 __M, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
- (__v16qi) __Y,
- (__v16qi)
- _mm_undefined_si128 (),
- (__mmask16) -1);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_multishift_epi64_epi8(__X, __Y),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m256i __Y)
+_mm256_multishift_epi64_epi8(__m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
- (__v32qi) __Y,
- (__v32qi) __W,
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_vpmultishiftqb256((__v32qi)__X, (__v32qi)__Y);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y)
+_mm256_mask_multishift_epi64_epi8(__m256i __W, __mmask32 __M, __m256i __X,
+ __m256i __Y)
{
- return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
- (__v32qi) __Y,
- (__v32qi)
- _mm256_setzero_si256 (),
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_multishift_epi64_epi8(__X, __Y),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y)
+_mm256_maskz_multishift_epi64_epi8(__mmask32 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
- (__v32qi) __Y,
- (__v32qi)
- _mm256_undefined_si256 (),
- (__mmask32) -1);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_multishift_epi64_epi8(__X, __Y),
+ (__v32qi)_mm256_setzero_si256());
}
diff --git a/lib/Headers/avx512vlbwintrin.h b/lib/Headers/avx512vlbwintrin.h
index 1b038dd04df6..87e0023e8b74 100644
--- a/lib/Headers/avx512vlbwintrin.h
+++ b/lib/Headers/avx512vlbwintrin.h
@@ -2297,6 +2297,15 @@ _mm256_maskz_set1_epi8 (__mmask32 __M, char __A)
(__v32qi) _mm256_setzero_si256());
}
+static __inline __m128i __DEFAULT_FN_ATTRS128
+_mm_loadu_epi16 (void const *__P)
+{
+ struct __loadu_epi16 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi16*)__P)->__v;
+}
+
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi16 (__m128i __W, __mmask8 __U, void const *__P)
{
@@ -2314,6 +2323,15 @@ _mm_maskz_loadu_epi16 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
+static __inline __m256i __DEFAULT_FN_ATTRS256
+_mm256_loadu_epi16 (void const *__P)
+{
+ struct __loadu_epi16 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi16*)__P)->__v;
+}
+
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi16 (__m256i __W, __mmask16 __U, void const *__P)
{
@@ -2331,6 +2349,15 @@ _mm256_maskz_loadu_epi16 (__mmask16 __U, void const *__P)
(__mmask16) __U);
}
+static __inline __m128i __DEFAULT_FN_ATTRS128
+_mm_loadu_epi8 (void const *__P)
+{
+ struct __loadu_epi8 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi8*)__P)->__v;
+}
+
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi8 (__m128i __W, __mmask16 __U, void const *__P)
{
@@ -2348,6 +2375,15 @@ _mm_maskz_loadu_epi8 (__mmask16 __U, void const *__P)
(__mmask16) __U);
}
+static __inline __m256i __DEFAULT_FN_ATTRS256
+_mm256_loadu_epi8 (void const *__P)
+{
+ struct __loadu_epi8 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi8*)__P)->__v;
+}
+
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi8 (__m256i __W, __mmask32 __U, void const *__P)
{
@@ -2364,7 +2400,17 @@ _mm256_maskz_loadu_epi8 (__mmask32 __U, void const *__P)
_mm256_setzero_si256 (),
(__mmask32) __U);
}
-static __inline__ void __DEFAULT_FN_ATTRS256
+
+static __inline void __DEFAULT_FN_ATTRS128
+_mm_storeu_epi16 (void *__P, __m128i __A)
+{
+ struct __storeu_epi16 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi16*)__P)->__v = __A;
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_epi16 (void *__P, __mmask8 __U, __m128i __A)
{
__builtin_ia32_storedquhi128_mask ((__v8hi *) __P,
@@ -2372,6 +2418,15 @@ _mm_mask_storeu_epi16 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
+static __inline void __DEFAULT_FN_ATTRS256
+_mm256_storeu_epi16 (void *__P, __m256i __A)
+{
+ struct __storeu_epi16 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi16*)__P)->__v = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi16 (void *__P, __mmask16 __U, __m256i __A)
{
@@ -2380,6 +2435,15 @@ _mm256_mask_storeu_epi16 (void *__P, __mmask16 __U, __m256i __A)
(__mmask16) __U);
}
+static __inline void __DEFAULT_FN_ATTRS128
+_mm_storeu_epi8 (void *__P, __m128i __A)
+{
+ struct __storeu_epi8 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi8*)__P)->__v = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_epi8 (void *__P, __mmask16 __U, __m128i __A)
{
@@ -2388,6 +2452,15 @@ _mm_mask_storeu_epi8 (void *__P, __mmask16 __U, __m128i __A)
(__mmask16) __U);
}
+static __inline void __DEFAULT_FN_ATTRS256
+_mm256_storeu_epi8 (void *__P, __m256i __A)
+{
+ struct __storeu_epi8 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi8*)__P)->__v = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi8 (void *__P, __mmask32 __U, __m256i __A)
{
diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h
index 0ee1d00ef4d2..a2cdc0a96e59 100644
--- a/lib/Headers/avx512vlintrin.h
+++ b/lib/Headers/avx512vlintrin.h
@@ -462,10 +462,16 @@ _mm_mask_mullo_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_and_epi32(__m256i __a, __m256i __b)
+{
+ return (__m256i)((__v8su)__a & (__v8su)__b);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_and_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_and_si256(__A, __B),
+ (__v8si)_mm256_and_epi32(__A, __B),
(__v8si)__W);
}
@@ -476,10 +482,16 @@ _mm256_maskz_and_epi32(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_and_epi32(__m128i __a, __m128i __b)
+{
+ return (__m128i)((__v4su)__a & (__v4su)__b);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_and_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_and_si128(__A, __B),
+ (__v4si)_mm_and_epi32(__A, __B),
(__v4si)__W);
}
@@ -490,10 +502,16 @@ _mm_maskz_and_epi32(__mmask8 __U, __m128i __A, __m128i __B)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_andnot_epi32(__m256i __A, __m256i __B)
+{
+ return (__m256i)(~(__v8su)__A & (__v8su)__B);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_andnot_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_andnot_si256(__A, __B),
+ (__v8si)_mm256_andnot_epi32(__A, __B),
(__v8si)__W);
}
@@ -505,24 +523,36 @@ _mm256_maskz_andnot_epi32(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_andnot_epi32(__m128i __A, __m128i __B)
+{
+ return (__m128i)(~(__v4su)__A & (__v4su)__B);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_andnot_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_andnot_si128(__A, __B),
+ (__v4si)_mm_andnot_epi32(__A, __B),
(__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_andnot_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_andnot_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)_mm_mask_andnot_epi32(_mm_setzero_si128(), __U, __A, __B);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_or_epi32(__m256i __a, __m256i __b)
+{
+ return (__m256i)((__v8su)__a | (__v8su)__b);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_or_si256(__A, __B),
+ (__v8si)_mm256_or_epi32(__A, __B),
(__v8si)__W);
}
@@ -533,10 +563,16 @@ _mm256_maskz_or_epi32(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_or_epi32(__m128i __a, __m128i __b)
+{
+ return (__m128i)((__v4su)__a | (__v4su)__b);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_or_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_or_si128(__A, __B),
+ (__v4si)_mm_or_epi32(__A, __B),
(__v4si)__W);
}
@@ -547,10 +583,16 @@ _mm_maskz_or_epi32(__mmask8 __U, __m128i __A, __m128i __B)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_xor_epi32(__m256i __a, __m256i __b)
+{
+ return (__m256i)((__v8su)__a ^ (__v8su)__b);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_xor_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
- (__v8si)_mm256_xor_si256(__A, __B),
+ (__v8si)_mm256_xor_epi32(__A, __B),
(__v8si)__W);
}
@@ -561,11 +603,16 @@ _mm256_maskz_xor_epi32(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_xor_epi32(__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_xor_epi32(__m128i __a, __m128i __b)
+{
+ return (__m128i)((__v4su)__a ^ (__v4su)__b);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_mask_xor_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
- (__v4si)_mm_xor_si128(__A, __B),
+ (__v4si)_mm_xor_epi32(__A, __B),
(__v4si)__W);
}
@@ -576,10 +623,16 @@ _mm_maskz_xor_epi32(__mmask8 __U, __m128i __A, __m128i __B)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_and_epi64(__m256i __a, __m256i __b)
+{
+ return (__m256i)((__v4du)__a & (__v4du)__b);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_and_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_and_si256(__A, __B),
+ (__v4di)_mm256_and_epi64(__A, __B),
(__v4di)__W);
}
@@ -590,10 +643,16 @@ _mm256_maskz_and_epi64(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_and_epi64(__m128i __a, __m128i __b)
+{
+ return (__m128i)((__v2du)__a & (__v2du)__b);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_and_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_and_si128(__A, __B),
+ (__v2di)_mm_and_epi64(__A, __B),
(__v2di)__W);
}
@@ -604,10 +663,16 @@ _mm_maskz_and_epi64(__mmask8 __U, __m128i __A, __m128i __B)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_andnot_epi64(__m256i __A, __m256i __B)
+{
+ return (__m256i)(~(__v4du)__A & (__v4du)__B);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_andnot_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_andnot_si256(__A, __B),
+ (__v4di)_mm256_andnot_epi64(__A, __B),
(__v4di)__W);
}
@@ -619,10 +684,16 @@ _mm256_maskz_andnot_epi64(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_andnot_epi64(__m128i __A, __m128i __B)
+{
+ return (__m128i)(~(__v2du)__A & (__v2du)__B);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_andnot_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_andnot_si128(__A, __B),
+ (__v2di)_mm_andnot_epi64(__A, __B),
(__v2di)__W);
}
@@ -633,10 +704,16 @@ _mm_maskz_andnot_epi64(__mmask8 __U, __m128i __A, __m128i __B)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_or_epi64(__m256i __a, __m256i __b)
+{
+ return (__m256i)((__v4du)__a | (__v4du)__b);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_or_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_or_si256(__A, __B),
+ (__v4di)_mm256_or_epi64(__A, __B),
(__v4di)__W);
}
@@ -647,10 +724,16 @@ _mm256_maskz_or_epi64(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_or_epi64(__m128i __a, __m128i __b)
+{
+ return (__m128i)((__v2du)__a | (__v2du)__b);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_or_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_or_si128(__A, __B),
+ (__v2di)_mm_or_epi64(__A, __B),
(__v2di)__W);
}
@@ -661,10 +744,16 @@ _mm_maskz_or_epi64(__mmask8 __U, __m128i __A, __m128i __B)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
+_mm256_xor_epi64(__m256i __a, __m256i __b)
+{
+ return (__m256i)((__v4du)__a ^ (__v4du)__b);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_xor_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
- (__v4di)_mm256_xor_si256(__A, __B),
+ (__v4di)_mm256_xor_epi64(__A, __B),
(__v4di)__W);
}
@@ -675,11 +764,17 @@ _mm256_maskz_xor_epi64(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
+_mm_xor_epi64(__m128i __a, __m128i __b)
+{
+ return (__m128i)((__v2du)__a ^ (__v2du)__b);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_xor_epi64(__m128i __W, __mmask8 __U, __m128i __A,
__m128i __B)
{
return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
- (__v2di)_mm_xor_si128(__A, __B),
+ (__v2di)_mm_xor_epi64(__A, __B),
(__v2di)__W);
}
@@ -3389,162 +3484,162 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) {
}
#define _mm_i64scatter_pd(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv2df((double *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv2df((void *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), \
(__v2df)(__m128d)(v1), (int)(scale))
#define _mm_mask_i64scatter_pd(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv2df((double *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv2df((void *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), \
(__v2df)(__m128d)(v1), (int)(scale))
#define _mm_i64scatter_epi64(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv2di((long long *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv2di((void *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), \
(__v2di)(__m128i)(v1), (int)(scale))
#define _mm_mask_i64scatter_epi64(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv2di((long long *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv2di((void *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), \
(__v2di)(__m128i)(v1), (int)(scale))
#define _mm256_i64scatter_pd(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv4df((double *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv4df((void *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), \
(__v4df)(__m256d)(v1), (int)(scale))
#define _mm256_mask_i64scatter_pd(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv4df((double *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv4df((void *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), \
(__v4df)(__m256d)(v1), (int)(scale))
#define _mm256_i64scatter_epi64(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv4di((long long *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv4di((void *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), \
(__v4di)(__m256i)(v1), (int)(scale))
#define _mm256_mask_i64scatter_epi64(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv4di((long long *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv4di((void *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), \
(__v4di)(__m256i)(v1), (int)(scale))
#define _mm_i64scatter_ps(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv4sf((float *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv4sf((void *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), (__v4sf)(__m128)(v1), \
(int)(scale))
#define _mm_mask_i64scatter_ps(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv4sf((float *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv4sf((void *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), (__v4sf)(__m128)(v1), \
(int)(scale))
#define _mm_i64scatter_epi32(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv4si((int *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv4si((void *)(addr), (__mmask8)-1, \
(__v2di)(__m128i)(index), \
(__v4si)(__m128i)(v1), (int)(scale))
#define _mm_mask_i64scatter_epi32(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv4si((int *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv4si((void *)(addr), (__mmask8)(mask), \
(__v2di)(__m128i)(index), \
(__v4si)(__m128i)(v1), (int)(scale))
#define _mm256_i64scatter_ps(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv8sf((float *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv8sf((void *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), (__v4sf)(__m128)(v1), \
(int)(scale))
#define _mm256_mask_i64scatter_ps(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv8sf((float *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv8sf((void *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), (__v4sf)(__m128)(v1), \
(int)(scale))
#define _mm256_i64scatter_epi32(addr, index, v1, scale) \
- __builtin_ia32_scatterdiv8si((int *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scatterdiv8si((void *)(addr), (__mmask8)-1, \
(__v4di)(__m256i)(index), \
(__v4si)(__m128i)(v1), (int)(scale))
#define _mm256_mask_i64scatter_epi32(addr, mask, index, v1, scale) \
- __builtin_ia32_scatterdiv8si((int *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scatterdiv8si((void *)(addr), (__mmask8)(mask), \
(__v4di)(__m256i)(index), \
(__v4si)(__m128i)(v1), (int)(scale))
#define _mm_i32scatter_pd(addr, index, v1, scale) \
- __builtin_ia32_scattersiv2df((double *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv2df((void *)(addr), (__mmask8)-1, \
(__v4si)(__m128i)(index), \
(__v2df)(__m128d)(v1), (int)(scale))
#define _mm_mask_i32scatter_pd(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv2df((double *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv2df((void *)(addr), (__mmask8)(mask), \
(__v4si)(__m128i)(index), \
(__v2df)(__m128d)(v1), (int)(scale))
#define _mm_i32scatter_epi64(addr, index, v1, scale) \
- __builtin_ia32_scattersiv2di((long long *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv2di((void *)(addr), (__mmask8)-1, \
(__v4si)(__m128i)(index), \
(__v2di)(__m128i)(v1), (int)(scale))
#define _mm_mask_i32scatter_epi64(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv2di((long long *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv2di((void *)(addr), (__mmask8)(mask), \
(__v4si)(__m128i)(index), \
(__v2di)(__m128i)(v1), (int)(scale))
#define _mm256_i32scatter_pd(addr, index, v1, scale) \
- __builtin_ia32_scattersiv4df((double *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv4df((void *)(addr), (__mmask8)-1, \
(__v4si)(__m128i)(index), \
(__v4df)(__m256d)(v1), (int)(scale))
#define _mm256_mask_i32scatter_pd(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv4df((double *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv4df((void *)(addr), (__mmask8)(mask), \
(__v4si)(__m128i)(index), \
(__v4df)(__m256d)(v1), (int)(scale))
#define _mm256_i32scatter_epi64(addr, index, v1, scale) \
- __builtin_ia32_scattersiv4di((long long *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv4di((void *)(addr), (__mmask8)-1, \
(__v4si)(__m128i)(index), \
(__v4di)(__m256i)(v1), (int)(scale))
#define _mm256_mask_i32scatter_epi64(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv4di((long long *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv4di((void *)(addr), (__mmask8)(mask), \
(__v4si)(__m128i)(index), \
(__v4di)(__m256i)(v1), (int)(scale))
#define _mm_i32scatter_ps(addr, index, v1, scale) \
- __builtin_ia32_scattersiv4sf((float *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv4sf((void *)(addr), (__mmask8)-1, \
(__v4si)(__m128i)(index), (__v4sf)(__m128)(v1), \
(int)(scale))
#define _mm_mask_i32scatter_ps(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv4sf((float *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv4sf((void *)(addr), (__mmask8)(mask), \
(__v4si)(__m128i)(index), (__v4sf)(__m128)(v1), \
(int)(scale))
#define _mm_i32scatter_epi32(addr, index, v1, scale) \
- __builtin_ia32_scattersiv4si((int *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv4si((void *)(addr), (__mmask8)-1, \
(__v4si)(__m128i)(index), \
(__v4si)(__m128i)(v1), (int)(scale))
#define _mm_mask_i32scatter_epi32(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv4si((int *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv4si((void *)(addr), (__mmask8)(mask), \
(__v4si)(__m128i)(index), \
(__v4si)(__m128i)(v1), (int)(scale))
#define _mm256_i32scatter_ps(addr, index, v1, scale) \
- __builtin_ia32_scattersiv8sf((float *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv8sf((void *)(addr), (__mmask8)-1, \
(__v8si)(__m256i)(index), (__v8sf)(__m256)(v1), \
(int)(scale))
#define _mm256_mask_i32scatter_ps(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv8sf((float *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv8sf((void *)(addr), (__mmask8)(mask), \
(__v8si)(__m256i)(index), (__v8sf)(__m256)(v1), \
(int)(scale))
#define _mm256_i32scatter_epi32(addr, index, v1, scale) \
- __builtin_ia32_scattersiv8si((int *)(addr), (__mmask8)-1, \
+ __builtin_ia32_scattersiv8si((void *)(addr), (__mmask8)-1, \
(__v8si)(__m256i)(index), \
(__v8si)(__m256i)(v1), (int)(scale))
#define _mm256_mask_i32scatter_epi32(addr, mask, index, v1, scale) \
- __builtin_ia32_scattersiv8si((int *)(addr), (__mmask8)(mask), \
+ __builtin_ia32_scattersiv8si((void *)(addr), (__mmask8)(mask), \
(__v8si)(__m256i)(index), \
(__v8si)(__m256i)(v1), (int)(scale))
@@ -4989,6 +5084,12 @@ _mm256_maskz_mov_epi32 (__mmask8 __U, __m256i __A)
(__v8si) _mm256_setzero_si256 ());
}
+static __inline __m128i __DEFAULT_FN_ATTRS128
+_mm_load_epi32 (void const *__P)
+{
+ return *(__m128i *) __P;
+}
+
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_load_epi32 (__m128i __W, __mmask8 __U, void const *__P)
{
@@ -5008,6 +5109,12 @@ _mm_maskz_load_epi32 (__mmask8 __U, void const *__P)
__U);
}
+static __inline __m256i __DEFAULT_FN_ATTRS256
+_mm256_load_epi32 (void const *__P)
+{
+ return *(__m256i *) __P;
+}
+
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_load_epi32 (__m256i __W, __mmask8 __U, void const *__P)
{
@@ -5027,6 +5134,12 @@ _mm256_maskz_load_epi32 (__mmask8 __U, void const *__P)
__U);
}
+static __inline void __DEFAULT_FN_ATTRS128
+_mm_store_epi32 (void *__P, __m128i __A)
+{
+ *(__m128i *) __P = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_epi32 (void *__P, __mmask8 __U, __m128i __A)
{
@@ -5035,6 +5148,12 @@ _mm_mask_store_epi32 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
+static __inline void __DEFAULT_FN_ATTRS256
+_mm256_store_epi32 (void *__P, __m256i __A)
+{
+ *(__m256i *) __P = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_store_epi32 (void *__P, __mmask8 __U, __m256i __A)
{
@@ -5075,6 +5194,12 @@ _mm256_maskz_mov_epi64 (__mmask8 __U, __m256i __A)
(__v4di) _mm256_setzero_si256 ());
}
+static __inline __m128i __DEFAULT_FN_ATTRS128
+_mm_load_epi64 (void const *__P)
+{
+ return *(__m128i *) __P;
+}
+
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_load_epi64 (__m128i __W, __mmask8 __U, void const *__P)
{
@@ -5094,6 +5219,12 @@ _mm_maskz_load_epi64 (__mmask8 __U, void const *__P)
__U);
}
+static __inline __m256i __DEFAULT_FN_ATTRS256
+_mm256_load_epi64 (void const *__P)
+{
+ return *(__m256i *) __P;
+}
+
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_load_epi64 (__m256i __W, __mmask8 __U, void const *__P)
{
@@ -5113,6 +5244,12 @@ _mm256_maskz_load_epi64 (__mmask8 __U, void const *__P)
__U);
}
+static __inline void __DEFAULT_FN_ATTRS128
+_mm_store_epi64 (void *__P, __m128i __A)
+{
+ *(__m128i *) __P = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_store_epi64 (void *__P, __mmask8 __U, __m128i __A)
{
@@ -5121,6 +5258,12 @@ _mm_mask_store_epi64 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
+static __inline void __DEFAULT_FN_ATTRS256
+_mm256_store_epi64 (void *__P, __m256i __A)
+{
+ *(__m256i *) __P = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_store_epi64 (void *__P, __mmask8 __U, __m256i __A)
{
@@ -5366,6 +5509,15 @@ _mm256_maskz_load_ps (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
+static __inline __m128i __DEFAULT_FN_ATTRS128
+_mm_loadu_epi64 (void const *__P)
+{
+ struct __loadu_epi64 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi64*)__P)->__v;
+}
+
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi64 (__m128i __W, __mmask8 __U, void const *__P)
{
@@ -5383,6 +5535,15 @@ _mm_maskz_loadu_epi64 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
+static __inline __m256i __DEFAULT_FN_ATTRS256
+_mm256_loadu_epi64 (void const *__P)
+{
+ struct __loadu_epi64 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi64*)__P)->__v;
+}
+
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi64 (__m256i __W, __mmask8 __U, void const *__P)
{
@@ -5400,6 +5561,15 @@ _mm256_maskz_loadu_epi64 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
+static __inline __m128i __DEFAULT_FN_ATTRS128
+_mm_loadu_epi32 (void const *__P)
+{
+ struct __loadu_epi32 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi32*)__P)->__v;
+}
+
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_loadu_epi32 (__m128i __W, __mmask8 __U, void const *__P)
{
@@ -5417,6 +5587,15 @@ _mm_maskz_loadu_epi32 (__mmask8 __U, void const *__P)
(__mmask8) __U);
}
+static __inline __m256i __DEFAULT_FN_ATTRS256
+_mm256_loadu_epi32 (void const *__P)
+{
+ struct __loadu_epi32 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ return ((struct __loadu_epi32*)__P)->__v;
+}
+
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_loadu_epi32 (__m256i __W, __mmask8 __U, void const *__P)
{
@@ -5534,6 +5713,15 @@ _mm256_mask_store_ps (void *__P, __mmask8 __U, __m256 __A)
(__mmask8) __U);
}
+static __inline void __DEFAULT_FN_ATTRS128
+_mm_storeu_epi64 (void *__P, __m128i __A)
+{
+ struct __storeu_epi64 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi64*)__P)->__v = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A)
{
@@ -5542,6 +5730,15 @@ _mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
+static __inline void __DEFAULT_FN_ATTRS256
+_mm256_storeu_epi64 (void *__P, __m256i __A)
+{
+ struct __storeu_epi64 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi64*)__P)->__v = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A)
{
@@ -5550,6 +5747,15 @@ _mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A)
(__mmask8) __U);
}
+static __inline void __DEFAULT_FN_ATTRS128
+_mm_storeu_epi32 (void *__P, __m128i __A)
+{
+ struct __storeu_epi32 {
+ __m128i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi32*)__P)->__v = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS128
_mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A)
{
@@ -5558,6 +5764,15 @@ _mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A)
(__mmask8) __U);
}
+static __inline void __DEFAULT_FN_ATTRS256
+_mm256_storeu_epi32 (void *__P, __m256i __A)
+{
+ struct __storeu_epi32 {
+ __m256i __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_epi32*)__P)->__v = __A;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS256
_mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A)
{
@@ -7769,97 +7984,97 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
#define _mm_mmask_i64gather_pd(v1_old, mask, index, addr, scale) \
(__m128d)__builtin_ia32_gather3div2df((__v2df)(__m128d)(v1_old), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v2di)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm_mmask_i64gather_epi64(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3div2di((__v2di)(__m128i)(v1_old), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v2di)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i64gather_pd(v1_old, mask, index, addr, scale) \
(__m256d)__builtin_ia32_gather3div4df((__v4df)(__m256d)(v1_old), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v4di)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i64gather_epi64(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gather3div4di((__v4di)(__m256i)(v1_old), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v4di)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm_mmask_i64gather_ps(v1_old, mask, index, addr, scale) \
(__m128)__builtin_ia32_gather3div4sf((__v4sf)(__m128)(v1_old), \
- (float const *)(addr), \
+ (void const *)(addr), \
(__v2di)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm_mmask_i64gather_epi32(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3div4si((__v4si)(__m128i)(v1_old), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v2di)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i64gather_ps(v1_old, mask, index, addr, scale) \
(__m128)__builtin_ia32_gather3div8sf((__v4sf)(__m128)(v1_old), \
- (float const *)(addr), \
+ (void const *)(addr), \
(__v4di)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i64gather_epi32(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3div8si((__v4si)(__m128i)(v1_old), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v4di)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm_mmask_i32gather_pd(v1_old, mask, index, addr, scale) \
(__m128d)__builtin_ia32_gather3siv2df((__v2df)(__m128d)(v1_old), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v4si)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm_mmask_i32gather_epi64(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3siv2di((__v2di)(__m128i)(v1_old), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v4si)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i32gather_pd(v1_old, mask, index, addr, scale) \
(__m256d)__builtin_ia32_gather3siv4df((__v4df)(__m256d)(v1_old), \
- (double const *)(addr), \
+ (void const *)(addr), \
(__v4si)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i32gather_epi64(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gather3siv4di((__v4di)(__m256i)(v1_old), \
- (long long const *)(addr), \
+ (void const *)(addr), \
(__v4si)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm_mmask_i32gather_ps(v1_old, mask, index, addr, scale) \
(__m128)__builtin_ia32_gather3siv4sf((__v4sf)(__m128)(v1_old), \
- (float const *)(addr), \
+ (void const *)(addr), \
(__v4si)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm_mmask_i32gather_epi32(v1_old, mask, index, addr, scale) \
(__m128i)__builtin_ia32_gather3siv4si((__v4si)(__m128i)(v1_old), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v4si)(__m128i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i32gather_ps(v1_old, mask, index, addr, scale) \
(__m256)__builtin_ia32_gather3siv8sf((__v8sf)(__m256)(v1_old), \
- (float const *)(addr), \
+ (void const *)(addr), \
(__v8si)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
#define _mm256_mmask_i32gather_epi32(v1_old, mask, index, addr, scale) \
(__m256i)__builtin_ia32_gather3siv8si((__v8si)(__m256i)(v1_old), \
- (int const *)(addr), \
+ (void const *)(addr), \
(__v8si)(__m256i)(index), \
(__mmask8)(mask), (int)(scale))
diff --git a/lib/Headers/avx512vlvbmi2intrin.h b/lib/Headers/avx512vlvbmi2intrin.h
index baaf5654631c..632d14fb55aa 100644
--- a/lib/Headers/avx512vlvbmi2intrin.h
+++ b/lib/Headers/avx512vlvbmi2intrin.h
@@ -421,327 +421,279 @@ _mm256_maskz_expandloadu_epi8(__mmask32 __U, void const *__P)
(__v8hi)_mm_setzero_si128())
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
+_mm256_shldv_epi64(__m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvq256_mask ((__v4di) __S,
- (__v4di) __A,
- (__v4di) __B,
- __U);
+ return (__m256i)__builtin_ia32_vpshldvq256((__v4di)__A, (__v4di)__B,
+ (__v4di)__C);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_maskz_shldv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
+_mm256_mask_shldv_epi64(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvq256_maskz ((__v4di) __S,
- (__v4di) __A,
- (__v4di) __B,
- __U);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_shldv_epi64(__A, __B, __C),
+ (__v4di)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B)
+_mm256_maskz_shldv_epi64(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvq256_mask ((__v4di) __S,
- (__v4di) __A,
- (__v4di) __B,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_shldv_epi64(__A, __B, __C),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+_mm_shldv_epi64(__m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvq128_mask ((__v2di) __S,
- (__v2di) __A,
- (__v2di) __B,
- __U);
+ return (__m128i)__builtin_ia32_vpshldvq128((__v2di)__A, (__v2di)__B,
+ (__v2di)__C);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+_mm_mask_shldv_epi64(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvq128_maskz ((__v2di) __S,
- (__v2di) __A,
- (__v2di) __B,
- __U);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_shldv_epi64(__A, __B, __C),
+ (__v2di)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B)
+_mm_maskz_shldv_epi64(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvq128_mask ((__v2di) __S,
- (__v2di) __A,
- (__v2di) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_shldv_epi64(__A, __B, __C),
+ (__v2di)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_mask_shldv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
+_mm256_shldv_epi32(__m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- __U);
+ return (__m256i)__builtin_ia32_vpshldvd256((__v8si)__A, (__v8si)__B,
+ (__v8si)__C);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_maskz_shldv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
+_mm256_mask_shldv_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvd256_maskz ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_shldv_epi32(__A, __B, __C),
+ (__v8si)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B)
+_mm256_maskz_shldv_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_shldv_epi32(__A, __B, __C),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+_mm_shldv_epi32(__m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- __U);
+ return (__m128i)__builtin_ia32_vpshldvd128((__v4si)__A, (__v4si)__B,
+ (__v4si)__C);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+_mm_mask_shldv_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvd128_maskz ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_shldv_epi32(__A, __B, __C),
+ (__v4si)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B)
+_mm_maskz_shldv_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_shldv_epi32(__A, __B, __C),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_mask_shldv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B)
+_mm256_shldv_epi16(__m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvw256_mask ((__v16hi) __S,
- (__v16hi) __A,
- (__v16hi) __B,
- __U);
+ return (__m256i)__builtin_ia32_vpshldvw256((__v16hi)__A, (__v16hi)__B,
+ (__v16hi)__C);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_maskz_shldv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B)
+_mm256_mask_shldv_epi16(__m256i __A, __mmask16 __U, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvw256_maskz ((__v16hi) __S,
- (__v16hi) __A,
- (__v16hi) __B,
- __U);
+ return (__m256i)__builtin_ia32_selectw_256(__U,
+ (__v16hi)_mm256_shldv_epi16(__A, __B, __C),
+ (__v16hi)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B)
+_mm256_maskz_shldv_epi16(__mmask16 __U, __m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshldvw256_mask ((__v16hi) __S,
- (__v16hi) __A,
- (__v16hi) __B,
- (__mmask16) -1);
+ return (__m256i)__builtin_ia32_selectw_256(__U,
+ (__v16hi)_mm256_shldv_epi16(__A, __B, __C),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+_mm_shldv_epi16(__m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvw128_mask ((__v8hi) __S,
- (__v8hi) __A,
- (__v8hi) __B,
- __U);
+ return (__m128i)__builtin_ia32_vpshldvw128((__v8hi)__A, (__v8hi)__B,
+ (__v8hi)__C);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+_mm_mask_shldv_epi16(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvw128_maskz ((__v8hi) __S,
- (__v8hi) __A,
- (__v8hi) __B,
- __U);
+ return (__m128i)__builtin_ia32_selectw_128(__U,
+ (__v8hi)_mm_shldv_epi16(__A, __B, __C),
+ (__v8hi)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B)
+_mm_maskz_shldv_epi16(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshldvw128_mask ((__v8hi) __S,
- (__v8hi) __A,
- (__v8hi) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_selectw_128(__U,
+ (__v8hi)_mm_shldv_epi16(__A, __B, __C),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_mask_shrdv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
+_mm256_shrdv_epi64(__m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvq256_mask ((__v4di) __S,
- (__v4di) __A,
- (__v4di) __B,
- __U);
+ return (__m256i)__builtin_ia32_vpshrdvq256((__v4di)__A, (__v4di)__B,
+ (__v4di)__C);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_maskz_shrdv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
+_mm256_mask_shrdv_epi64(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvq256_maskz ((__v4di) __S,
- (__v4di) __A,
- (__v4di) __B,
- __U);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_shrdv_epi64(__A, __B, __C),
+ (__v4di)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B)
+_mm256_maskz_shrdv_epi64(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvq256_mask ((__v4di) __S,
- (__v4di) __A,
- (__v4di) __B,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_selectq_256(__U,
+ (__v4di)_mm256_shrdv_epi64(__A, __B, __C),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+_mm_shrdv_epi64(__m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvq128_mask ((__v2di) __S,
- (__v2di) __A,
- (__v2di) __B,
- __U);
+ return (__m128i)__builtin_ia32_vpshrdvq128((__v2di)__A, (__v2di)__B,
+ (__v2di)__C);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+_mm_mask_shrdv_epi64(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvq128_maskz ((__v2di) __S,
- (__v2di) __A,
- (__v2di) __B,
- __U);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_shrdv_epi64(__A, __B, __C),
+ (__v2di)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B)
+_mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvq128_mask ((__v2di) __S,
- (__v2di) __A,
- (__v2di) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_selectq_128(__U,
+ (__v2di)_mm_shrdv_epi64(__A, __B, __C),
+ (__v2di)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_mask_shrdv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B)
+_mm256_shrdv_epi32(__m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- __U);
+ return (__m256i)__builtin_ia32_vpshrdvd256((__v8si)__A, (__v8si)__B,
+ (__v8si)__C);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_maskz_shrdv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B)
+_mm256_mask_shrdv_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvd256_maskz ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- __U);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_shrdv_epi32(__A, __B, __C),
+ (__v8si)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B)
+_mm256_maskz_shrdv_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvd256_mask ((__v8si) __S,
- (__v8si) __A,
- (__v8si) __B,
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_selectd_256(__U,
+ (__v8si)_mm256_shrdv_epi32(__A, __B, __C),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+_mm_shrdv_epi32(__m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- __U);
+ return (__m128i)__builtin_ia32_vpshrdvd128((__v4si)__A, (__v4si)__B,
+ (__v4si)__C);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+_mm_mask_shrdv_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvd128_maskz ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- __U);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_shrdv_epi32(__A, __B, __C),
+ (__v4si)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B)
+_mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvd128_mask ((__v4si) __S,
- (__v4si) __A,
- (__v4si) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_selectd_128(__U,
+ (__v4si)_mm_shrdv_epi32(__A, __B, __C),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_mask_shrdv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B)
+_mm256_shrdv_epi16(__m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvw256_mask ((__v16hi) __S,
- (__v16hi) __A,
- (__v16hi) __B,
- __U);
+ return (__m256i)__builtin_ia32_vpshrdvw256((__v16hi)__A, (__v16hi)__B,
+ (__v16hi)__C);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_maskz_shrdv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B)
+_mm256_mask_shrdv_epi16(__m256i __A, __mmask16 __U, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvw256_maskz ((__v16hi) __S,
- (__v16hi) __A,
- (__v16hi) __B,
- __U);
+ return (__m256i)__builtin_ia32_selectw_256(__U,
+ (__v16hi)_mm256_shrdv_epi16(__A, __B, __C),
+ (__v16hi)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
-_mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B)
+_mm256_maskz_shrdv_epi16(__mmask16 __U, __m256i __A, __m256i __B, __m256i __C)
{
- return (__m256i) __builtin_ia32_vpshrdvw256_mask ((__v16hi) __S,
- (__v16hi) __A,
- (__v16hi) __B,
- (__mmask16) -1);
+ return (__m256i)__builtin_ia32_selectw_256(__U,
+ (__v16hi)_mm256_shrdv_epi16(__A, __B, __C),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B)
+_mm_shrdv_epi16(__m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvw128_mask ((__v8hi) __S,
- (__v8hi) __A,
- (__v8hi) __B,
- __U);
+ return (__m128i)__builtin_ia32_vpshrdvw128((__v8hi)__A, (__v8hi)__B,
+ (__v8hi)__C);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B)
+_mm_mask_shrdv_epi16(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvw128_maskz ((__v8hi) __S,
- (__v8hi) __A,
- (__v8hi) __B,
- __U);
+ return (__m128i)__builtin_ia32_selectw_128(__U,
+ (__v8hi)_mm_shrdv_epi16(__A, __B, __C),
+ (__v8hi)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
-_mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B)
+_mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C)
{
- return (__m128i) __builtin_ia32_vpshrdvw128_mask ((__v8hi) __S,
- (__v8hi) __A,
- (__v8hi) __B,
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_selectw_128(__U,
+ (__v8hi)_mm_shrdv_epi16(__A, __B, __C),
+ (__v8hi)_mm_setzero_si128());
}
diff --git a/lib/Headers/bmiintrin.h b/lib/Headers/bmiintrin.h
index d03bef442a28..56c20b78d340 100644
--- a/lib/Headers/bmiintrin.h
+++ b/lib/Headers/bmiintrin.h
@@ -62,7 +62,7 @@
static __inline__ unsigned short __RELAXED_FN_ATTRS
__tzcnt_u16(unsigned short __X)
{
- return __X ? __builtin_ctzs(__X) : 16;
+ return __builtin_ia32_tzcnt_u16(__X);
}
/// Performs a bitwise AND of the second operand with the one's
@@ -196,7 +196,7 @@ __blsr_u32(unsigned int __X)
static __inline__ unsigned int __RELAXED_FN_ATTRS
__tzcnt_u32(unsigned int __X)
{
- return __X ? __builtin_ctz(__X) : 32;
+ return __builtin_ia32_tzcnt_u32(__X);
}
/// Counts the number of trailing zero bits in the operand.
@@ -212,7 +212,7 @@ __tzcnt_u32(unsigned int __X)
static __inline__ int __RELAXED_FN_ATTRS
_mm_tzcnt_32(unsigned int __X)
{
- return __X ? __builtin_ctz(__X) : 32;
+ return __builtin_ia32_tzcnt_u32(__X);
}
#ifdef __x86_64__
@@ -359,7 +359,7 @@ __blsr_u64(unsigned long long __X)
static __inline__ unsigned long long __RELAXED_FN_ATTRS
__tzcnt_u64(unsigned long long __X)
{
- return __X ? __builtin_ctzll(__X) : 64;
+ return __builtin_ia32_tzcnt_u64(__X);
}
/// Counts the number of trailing zero bits in the operand.
@@ -375,7 +375,7 @@ __tzcnt_u64(unsigned long long __X)
static __inline__ long long __RELAXED_FN_ATTRS
_mm_tzcnt_64(unsigned long long __X)
{
- return __X ? __builtin_ctzll(__X) : 64;
+ return __builtin_ia32_tzcnt_u64(__X);
}
#endif /* __x86_64__ */
diff --git a/lib/Headers/cuda_wrappers/new b/lib/Headers/cuda_wrappers/new
index 71b7a52363ce..f49811c5a57c 100644
--- a/lib/Headers/cuda_wrappers/new
+++ b/lib/Headers/cuda_wrappers/new
@@ -73,10 +73,12 @@ __device__ inline void operator delete[](void *ptr,
// Sized delete, C++14 only.
#if __cplusplus >= 201402L
-__device__ void operator delete(void *ptr, __SIZE_TYPE__ size) CUDA_NOEXCEPT {
+__device__ inline void operator delete(void *ptr,
+ __SIZE_TYPE__ size) CUDA_NOEXCEPT {
::operator delete(ptr);
}
-__device__ void operator delete[](void *ptr, __SIZE_TYPE__ size) CUDA_NOEXCEPT {
+__device__ inline void operator delete[](void *ptr,
+ __SIZE_TYPE__ size) CUDA_NOEXCEPT {
::operator delete(ptr);
}
#endif
diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h
index f0ea7cd05c63..6d61f9719944 100644
--- a/lib/Headers/emmintrin.h
+++ b/lib/Headers/emmintrin.h
@@ -1675,7 +1675,49 @@ _mm_loadu_si64(void const *__a)
long long __v;
} __attribute__((__packed__, __may_alias__));
long long __u = ((struct __loadu_si64*)__a)->__v;
- return __extension__ (__m128i)(__v2di){__u, 0L};
+ return __extension__ (__m128i)(__v2di){__u, 0LL};
+}
+
+/// Loads a 32-bit integer value to the low element of a 128-bit integer
+/// vector and clears the upper element.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
+///
+/// \param __a
+/// A pointer to a 32-bit memory location. The address of the memory
+/// location does not have to be aligned.
+/// \returns A 128-bit vector of [4 x i32] containing the loaded value.
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_loadu_si32(void const *__a)
+{
+ struct __loadu_si32 {
+ int __v;
+ } __attribute__((__packed__, __may_alias__));
+ int __u = ((struct __loadu_si32*)__a)->__v;
+ return __extension__ (__m128i)(__v4si){__u, 0, 0, 0};
+}
+
+/// Loads a 16-bit integer value to the low element of a 128-bit integer
+/// vector and clears the upper element.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic does not correspond to a specific instruction.
+///
+/// \param __a
+/// A pointer to a 16-bit memory location. The address of the memory
+/// location does not have to be aligned.
+/// \returns A 128-bit vector of [8 x i16] containing the loaded value.
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_loadu_si16(void const *__a)
+{
+ struct __loadu_si16 {
+ short __v;
+ } __attribute__((__packed__, __may_alias__));
+ short __u = ((struct __loadu_si16*)__a)->__v;
+ return __extension__ (__m128i)(__v8hi){__u, 0, 0, 0, 0, 0, 0, 0};
}
/// Loads a 64-bit double-precision value to the low element of a
@@ -3993,6 +4035,69 @@ _mm_storeu_si128(__m128i *__p, __m128i __b)
((struct __storeu_si128*)__p)->__v = __b;
}
+/// Stores a 64-bit integer value from the low element of a 128-bit integer
+/// vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction.
+///
+/// \param __p
+/// A pointer to a 64-bit memory location. The address of the memory
+/// location does not have to be algned.
+/// \param __b
+/// A 128-bit integer vector containing the value to be stored.
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_storeu_si64(void const *__p, __m128i __b)
+{
+ struct __storeu_si64 {
+ long long __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_si64*)__p)->__v = ((__v2di)__b)[0];
+}
+
+/// Stores a 32-bit integer value from the low element of a 128-bit integer
+/// vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
+///
+/// \param __p
+/// A pointer to a 32-bit memory location. The address of the memory
+/// location does not have to be aligned.
+/// \param __b
+/// A 128-bit integer vector containing the value to be stored.
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_storeu_si32(void const *__p, __m128i __b)
+{
+ struct __storeu_si32 {
+ int __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_si32*)__p)->__v = ((__v4si)__b)[0];
+}
+
+/// Stores a 16-bit integer value from the low element of a 128-bit integer
+/// vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic does not correspond to a specific instruction.
+///
+/// \param __p
+/// A pointer to a 16-bit memory location. The address of the memory
+/// location does not have to be aligned.
+/// \param __b
+/// A 128-bit integer vector containing the value to be stored.
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_storeu_si16(void const *__p, __m128i __b)
+{
+ struct __storeu_si16 {
+ short __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_si16*)__p)->__v = ((__v8hi)__b)[0];
+}
+
/// Moves bytes selected by the mask from the first operand to the
/// specified unaligned memory location. When a mask bit is 1, the
/// corresponding byte is written, otherwise it is not written.
diff --git a/lib/Headers/float.h b/lib/Headers/float.h
index 44d4d05494f5..56215cd624d7 100644
--- a/lib/Headers/float.h
+++ b/lib/Headers/float.h
@@ -21,8 +21,8 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef __FLOAT_H
-#define __FLOAT_H
+#ifndef __CLANG_FLOAT_H
+#define __CLANG_FLOAT_H
/* If we're on MinGW, fall back to the system's float.h, which might have
* additional definitions provided for Windows.
@@ -85,6 +85,9 @@
# undef FLT_DECIMAL_DIG
# undef DBL_DECIMAL_DIG
# undef LDBL_DECIMAL_DIG
+# undef FLT_HAS_SUBNORM
+# undef DBL_HAS_SUBNORM
+# undef LDBL_HAS_SUBNORM
# endif
#endif
@@ -141,6 +144,9 @@
# define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__
# define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__
# define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
+# define FLT_HAS_SUBNORM __FLT_HAS_DENORM__
+# define DBL_HAS_SUBNORM __DBL_HAS_DENORM__
+# define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__
#endif
#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
@@ -157,4 +163,4 @@
# define FLT16_TRUE_MIN __FLT16_TRUE_MIN__
#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__ */
-#endif /* __FLOAT_H */
+#endif /* __CLANG_FLOAT_H */
diff --git a/lib/Headers/immintrin.h b/lib/Headers/immintrin.h
index e7bfbf964d56..7d0722ec7652 100644
--- a/lib/Headers/immintrin.h
+++ b/lib/Headers/immintrin.h
@@ -306,6 +306,65 @@ _writegsbase_u64(unsigned long long __V)
#endif
#endif /* __FSGSBASE__ */
+#if !defined(_MSC_VER) || __has_feature(modules) || defined(__MOVBE__)
+
+/* The structs used below are to force the load/store to be unaligned. This
+ * is accomplished with the __packed__ attribute. The __may_alias__ prevents
+ * tbaa metadata from being generated based on the struct and the type of the
+ * field inside of it.
+ */
+
+static __inline__ short __attribute__((__always_inline__, __nodebug__, __target__("movbe")))
+_loadbe_i16(void const * __P) {
+ struct __loadu_i16 {
+ short __v;
+ } __attribute__((__packed__, __may_alias__));
+ return __builtin_bswap16(((struct __loadu_i16*)__P)->__v);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("movbe")))
+_storebe_i16(void * __P, short __D) {
+ struct __storeu_i16 {
+ short __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_i16*)__P)->__v = __builtin_bswap16(__D);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__, __target__("movbe")))
+_loadbe_i32(void const * __P) {
+ struct __loadu_i32 {
+ int __v;
+ } __attribute__((__packed__, __may_alias__));
+ return __builtin_bswap32(((struct __loadu_i32*)__P)->__v);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("movbe")))
+_storebe_i32(void * __P, int __D) {
+ struct __storeu_i32 {
+ int __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_i32*)__P)->__v = __builtin_bswap32(__D);
+}
+
+#ifdef __x86_64__
+static __inline__ long long __attribute__((__always_inline__, __nodebug__, __target__("movbe")))
+_loadbe_i64(void const * __P) {
+ struct __loadu_i64 {
+ long long __v;
+ } __attribute__((__packed__, __may_alias__));
+ return __builtin_bswap64(((struct __loadu_i64*)__P)->__v);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("movbe")))
+_storebe_i64(void * __P, long long __D) {
+ struct __storeu_i64 {
+ long long __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __storeu_i64*)__P)->__v = __builtin_bswap64(__D);
+}
+#endif
+#endif /* __MOVBE */
+
#if !defined(_MSC_VER) || __has_feature(modules) || defined(__RTM__)
#include <rtmintrin.h>
#include <xtestintrin.h>
diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h
index 91914214e299..c86f41faeb88 100644
--- a/lib/Headers/intrin.h
+++ b/lib/Headers/intrin.h
@@ -90,8 +90,6 @@ void __inwordstring(unsigned short, unsigned short *, unsigned long);
void __lidt(void *);
unsigned __int64 __ll_lshift(unsigned __int64, int);
__int64 __ll_rshift(__int64, int);
-unsigned int __lzcnt(unsigned int);
-unsigned short __lzcnt16(unsigned short);
static __inline__
void __movsb(unsigned char *, unsigned char const *, size_t);
static __inline__
@@ -219,7 +217,6 @@ void __incgsbyte(unsigned long);
void __incgsdword(unsigned long);
void __incgsqword(unsigned long);
void __incgsword(unsigned long);
-unsigned __int64 __lzcnt64(unsigned __int64);
static __inline__
void __movsq(unsigned long long *, unsigned long long const *, size_t);
static __inline__
@@ -329,189 +326,63 @@ __int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask);
|* Interlocked Exchange Add
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd8_acq(char volatile *_Addend, char _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd8_nf(char volatile *_Addend, char _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd8_rel(char volatile *_Addend, char _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd16_acq(short volatile *_Addend, short _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd16_nf(short volatile *_Addend, short _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd16_rel(short volatile *_Addend, short _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELEASE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd_acq(long volatile *_Addend, long _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd_nf(long volatile *_Addend, long _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd_rel(long volatile *_Addend, long _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELEASE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd64_acq(__int64 volatile *_Addend, __int64 _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd64_nf(__int64 volatile *_Addend, __int64 _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd64_rel(__int64 volatile *_Addend, __int64 _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELEASE);
-}
+char _InterlockedExchangeAdd8_acq(char volatile *_Addend, char _Value);
+char _InterlockedExchangeAdd8_nf(char volatile *_Addend, char _Value);
+char _InterlockedExchangeAdd8_rel(char volatile *_Addend, char _Value);
+short _InterlockedExchangeAdd16_acq(short volatile *_Addend, short _Value);
+short _InterlockedExchangeAdd16_nf(short volatile *_Addend, short _Value);
+short _InterlockedExchangeAdd16_rel(short volatile *_Addend, short _Value);
+long _InterlockedExchangeAdd_acq(long volatile *_Addend, long _Value);
+long _InterlockedExchangeAdd_nf(long volatile *_Addend, long _Value);
+long _InterlockedExchangeAdd_rel(long volatile *_Addend, long _Value);
+__int64 _InterlockedExchangeAdd64_acq(__int64 volatile *_Addend, __int64 _Value);
+__int64 _InterlockedExchangeAdd64_nf(__int64 volatile *_Addend, __int64 _Value);
+__int64 _InterlockedExchangeAdd64_rel(__int64 volatile *_Addend, __int64 _Value);
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Increment
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedIncrement16_acq(short volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_ACQUIRE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedIncrement16_nf(short volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_RELAXED);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedIncrement16_rel(short volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_RELEASE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedIncrement_acq(long volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_ACQUIRE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedIncrement_nf(long volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_RELAXED);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedIncrement_rel(long volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_RELEASE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedIncrement64_acq(__int64 volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_ACQUIRE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedIncrement64_nf(__int64 volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_RELAXED);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedIncrement64_rel(__int64 volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_RELEASE);
-}
+short _InterlockedIncrement16_acq(short volatile *_Value);
+short _InterlockedIncrement16_nf(short volatile *_Value);
+short _InterlockedIncrement16_rel(short volatile *_Value);
+long _InterlockedIncrement_acq(long volatile *_Value);
+long _InterlockedIncrement_nf(long volatile *_Value);
+long _InterlockedIncrement_rel(long volatile *_Value);
+__int64 _InterlockedIncrement64_acq(__int64 volatile *_Value);
+__int64 _InterlockedIncrement64_nf(__int64 volatile *_Value);
+__int64 _InterlockedIncrement64_rel(__int64 volatile *_Value);
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Decrement
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedDecrement16_acq(short volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_ACQUIRE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedDecrement16_nf(short volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELAXED);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedDecrement16_rel(short volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELEASE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedDecrement_acq(long volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_ACQUIRE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedDecrement_nf(long volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELAXED);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedDecrement_rel(long volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELEASE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedDecrement64_acq(__int64 volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_ACQUIRE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedDecrement64_nf(__int64 volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELAXED);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedDecrement64_rel(__int64 volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELEASE);
-}
+short _InterlockedDecrement16_acq(short volatile *_Value);
+short _InterlockedDecrement16_nf(short volatile *_Value);
+short _InterlockedDecrement16_rel(short volatile *_Value);
+long _InterlockedDecrement_acq(long volatile *_Value);
+long _InterlockedDecrement_nf(long volatile *_Value);
+long _InterlockedDecrement_rel(long volatile *_Value);
+__int64 _InterlockedDecrement64_acq(__int64 volatile *_Value);
+__int64 _InterlockedDecrement64_nf(__int64 volatile *_Value);
+__int64 _InterlockedDecrement64_rel(__int64 volatile *_Value);
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked And
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedAnd8_acq(char volatile *_Value, char _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedAnd8_nf(char volatile *_Value, char _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedAnd8_rel(char volatile *_Value, char _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedAnd16_acq(short volatile *_Value, short _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedAnd16_nf(short volatile *_Value, short _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedAnd16_rel(short volatile *_Value, short _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedAnd_acq(long volatile *_Value, long _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedAnd_nf(long volatile *_Value, long _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedAnd_rel(long volatile *_Value, long _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedAnd64_acq(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedAnd64_nf(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedAnd64_rel(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
-}
+char _InterlockedAnd8_acq(char volatile *_Value, char _Mask);
+char _InterlockedAnd8_nf(char volatile *_Value, char _Mask);
+char _InterlockedAnd8_rel(char volatile *_Value, char _Mask);
+short _InterlockedAnd16_acq(short volatile *_Value, short _Mask);
+short _InterlockedAnd16_nf(short volatile *_Value, short _Mask);
+short _InterlockedAnd16_rel(short volatile *_Value, short _Mask);
+long _InterlockedAnd_acq(long volatile *_Value, long _Mask);
+long _InterlockedAnd_nf(long volatile *_Value, long _Mask);
+long _InterlockedAnd_rel(long volatile *_Value, long _Mask);
+__int64 _InterlockedAnd64_acq(__int64 volatile *_Value, __int64 _Mask);
+__int64 _InterlockedAnd64_nf(__int64 volatile *_Value, __int64 _Mask);
+__int64 _InterlockedAnd64_rel(__int64 volatile *_Value, __int64 _Mask);
#endif
/*----------------------------------------------------------------------------*\
|* Bit Counting and Testing
@@ -534,261 +405,81 @@ unsigned char _interlockedbittestandreset_rel(long volatile *_BitBase,
|* Interlocked Or
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedOr8_acq(char volatile *_Value, char _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedOr8_nf(char volatile *_Value, char _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedOr8_rel(char volatile *_Value, char _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedOr16_acq(short volatile *_Value, short _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedOr16_nf(short volatile *_Value, short _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedOr16_rel(short volatile *_Value, short _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedOr_acq(long volatile *_Value, long _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedOr_nf(long volatile *_Value, long _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedOr_rel(long volatile *_Value, long _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedOr64_acq(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedOr64_nf(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedOr64_rel(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
-}
+char _InterlockedOr8_acq(char volatile *_Value, char _Mask);
+char _InterlockedOr8_nf(char volatile *_Value, char _Mask);
+char _InterlockedOr8_rel(char volatile *_Value, char _Mask);
+short _InterlockedOr16_acq(short volatile *_Value, short _Mask);
+short _InterlockedOr16_nf(short volatile *_Value, short _Mask);
+short _InterlockedOr16_rel(short volatile *_Value, short _Mask);
+long _InterlockedOr_acq(long volatile *_Value, long _Mask);
+long _InterlockedOr_nf(long volatile *_Value, long _Mask);
+long _InterlockedOr_rel(long volatile *_Value, long _Mask);
+__int64 _InterlockedOr64_acq(__int64 volatile *_Value, __int64 _Mask);
+__int64 _InterlockedOr64_nf(__int64 volatile *_Value, __int64 _Mask);
+__int64 _InterlockedOr64_rel(__int64 volatile *_Value, __int64 _Mask);
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Xor
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedXor8_acq(char volatile *_Value, char _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedXor8_nf(char volatile *_Value, char _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedXor8_rel(char volatile *_Value, char _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedXor16_acq(short volatile *_Value, short _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedXor16_nf(short volatile *_Value, short _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedXor16_rel(short volatile *_Value, short _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedXor_acq(long volatile *_Value, long _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedXor_nf(long volatile *_Value, long _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedXor_rel(long volatile *_Value, long _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedXor64_acq(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedXor64_nf(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedXor64_rel(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
-}
+char _InterlockedXor8_acq(char volatile *_Value, char _Mask);
+char _InterlockedXor8_nf(char volatile *_Value, char _Mask);
+char _InterlockedXor8_rel(char volatile *_Value, char _Mask);
+short _InterlockedXor16_acq(short volatile *_Value, short _Mask);
+short _InterlockedXor16_nf(short volatile *_Value, short _Mask);
+short _InterlockedXor16_rel(short volatile *_Value, short _Mask);
+long _InterlockedXor_acq(long volatile *_Value, long _Mask);
+long _InterlockedXor_nf(long volatile *_Value, long _Mask);
+long _InterlockedXor_rel(long volatile *_Value, long _Mask);
+__int64 _InterlockedXor64_acq(__int64 volatile *_Value, __int64 _Mask);
+__int64 _InterlockedXor64_nf(__int64 volatile *_Value, __int64 _Mask);
+__int64 _InterlockedXor64_rel(__int64 volatile *_Value, __int64 _Mask);
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Exchange
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchange8_acq(char volatile *_Target, char _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
- return _Value;
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchange8_nf(char volatile *_Target, char _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
- return _Value;
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchange8_rel(char volatile *_Target, char _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
- return _Value;
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchange16_acq(short volatile *_Target, short _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
- return _Value;
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchange16_nf(short volatile *_Target, short _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
- return _Value;
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchange16_rel(short volatile *_Target, short _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
- return _Value;
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedExchange_acq(long volatile *_Target, long _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
- return _Value;
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedExchange_nf(long volatile *_Target, long _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
- return _Value;
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedExchange_rel(long volatile *_Target, long _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
- return _Value;
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchange64_acq(__int64 volatile *_Target, __int64 _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
- return _Value;
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchange64_nf(__int64 volatile *_Target, __int64 _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
- return _Value;
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchange64_rel(__int64 volatile *_Target, __int64 _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
- return _Value;
-}
+char _InterlockedExchange8_acq(char volatile *_Target, char _Value);
+char _InterlockedExchange8_nf(char volatile *_Target, char _Value);
+char _InterlockedExchange8_rel(char volatile *_Target, char _Value);
+short _InterlockedExchange16_acq(short volatile *_Target, short _Value);
+short _InterlockedExchange16_nf(short volatile *_Target, short _Value);
+short _InterlockedExchange16_rel(short volatile *_Target, short _Value);
+long _InterlockedExchange_acq(long volatile *_Target, long _Value);
+long _InterlockedExchange_nf(long volatile *_Target, long _Value);
+long _InterlockedExchange_rel(long volatile *_Target, long _Value);
+__int64 _InterlockedExchange64_acq(__int64 volatile *_Target, __int64 _Value);
+__int64 _InterlockedExchange64_nf(__int64 volatile *_Target, __int64 _Value);
+__int64 _InterlockedExchange64_rel(__int64 volatile *_Target, __int64 _Value);
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Compare Exchange
\*----------------------------------------------------------------------------*/
#if defined(__arm__) || defined(__aarch64__)
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange8_acq(char volatile *_Destination,
- char _Exchange, char _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
- return _Comparand;
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange8_nf(char volatile *_Destination,
- char _Exchange, char _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
- return _Comparand;
-}
-static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange8_rel(char volatile *_Destination,
- char _Exchange, char _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
- return _Comparand;
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange16_acq(short volatile *_Destination,
- short _Exchange, short _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
- return _Comparand;
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange16_nf(short volatile *_Destination,
- short _Exchange, short _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
- return _Comparand;
-}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange16_rel(short volatile *_Destination,
- short _Exchange, short _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
- return _Comparand;
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange_acq(long volatile *_Destination,
- long _Exchange, long _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
- return _Comparand;
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange_nf(long volatile *_Destination,
- long _Exchange, long _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
- return _Comparand;
-}
-static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange_rel(long volatile *_Destination,
- long _Exchange, long _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
- return _Comparand;
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange64_acq(__int64 volatile *_Destination,
- __int64 _Exchange, __int64 _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
- return _Comparand;
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange64_nf(__int64 volatile *_Destination,
- __int64 _Exchange, __int64 _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
- return _Comparand;
-}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange64_rel(__int64 volatile *_Destination,
- __int64 _Exchange, __int64 _Comparand) {
- __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
- return _Comparand;
-}
+char _InterlockedCompareExchange8_acq(char volatile *_Destination,
+ char _Exchange, char _Comparand);
+char _InterlockedCompareExchange8_nf(char volatile *_Destination,
+ char _Exchange, char _Comparand);
+char _InterlockedCompareExchange8_rel(char volatile *_Destination,
+ char _Exchange, char _Comparand);
+short _InterlockedCompareExchange16_acq(short volatile *_Destination,
+ short _Exchange, short _Comparand);
+short _InterlockedCompareExchange16_nf(short volatile *_Destination,
+ short _Exchange, short _Comparand);
+short _InterlockedCompareExchange16_rel(short volatile *_Destination,
+ short _Exchange, short _Comparand);
+long _InterlockedCompareExchange_acq(long volatile *_Destination,
+ long _Exchange, long _Comparand);
+long _InterlockedCompareExchange_nf(long volatile *_Destination,
+ long _Exchange, long _Comparand);
+long _InterlockedCompareExchange_rel(long volatile *_Destination,
+ long _Exchange, long _Comparand);
+__int64 _InterlockedCompareExchange64_acq(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand);
+__int64 _InterlockedCompareExchange64_nf(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand);
+__int64 _InterlockedCompareExchange64_rel(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand);
#endif
/*----------------------------------------------------------------------------*\
@@ -841,7 +532,7 @@ __stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) {
static __inline__ void __DEFAULT_FN_ATTRS
__cpuid(int __info[4], int __level) {
__asm__ ("cpuid" : "=a"(__info[0]), "=b" (__info[1]), "=c"(__info[2]), "=d"(__info[3])
- : "a"(__level));
+ : "a"(__level), "c"(0));
}
static __inline__ void __DEFAULT_FN_ATTRS
__cpuidex(int __info[4], int __level, int __ecx) {
@@ -858,23 +549,32 @@ static __inline__ void __DEFAULT_FN_ATTRS
__halt(void) {
__asm__ volatile ("hlt");
}
+#endif
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
static __inline__ void __DEFAULT_FN_ATTRS
__nop(void) {
__asm__ volatile ("nop");
}
#endif
-#if defined(__x86_64__)
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-__shiftleft128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) {
- unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l;
- unsigned __int128 __res = __val << (__d & 63);
- return (unsigned __int64)(__res >> 64);
+
+/*----------------------------------------------------------------------------*\
+|* MS AArch64 specific
+\*----------------------------------------------------------------------------*/
+#if defined(__aarch64__)
+unsigned __int64 __getReg(int);
+long _InterlockedAdd(long volatile *Addend, long Value);
+int _ReadStatusReg(int);
+void _WriteStatusReg(int, int);
+
+static inline unsigned short _byteswap_ushort (unsigned short val) {
+ return __builtin_bswap16(val);
}
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-__shiftright128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) {
- unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l;
- unsigned __int128 __res = __val >> (__d & 63);
- return (unsigned __int64)__res;
+static inline unsigned long _byteswap_ulong (unsigned long val) {
+ return __builtin_bswap32(val);
+}
+static inline unsigned __int64 _byteswap_uint64 (unsigned __int64 val) {
+ return __builtin_bswap64(val);
}
#endif
diff --git a/lib/Headers/lzcntintrin.h b/lib/Headers/lzcntintrin.h
index 558f1828f0e7..35c1651cc4a8 100644
--- a/lib/Headers/lzcntintrin.h
+++ b/lib/Headers/lzcntintrin.h
@@ -31,6 +31,7 @@
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lzcnt")))
+#ifndef _MSC_VER
/// Counts the number of leading zero bits in the operand.
///
/// \headerfile <x86intrin.h>
@@ -41,11 +42,8 @@
/// An unsigned 16-bit integer whose leading zeros are to be counted.
/// \returns An unsigned 16-bit integer containing the number of leading zero
/// bits in the operand.
-static __inline__ unsigned short __DEFAULT_FN_ATTRS
-__lzcnt16(unsigned short __X)
-{
- return __X ? __builtin_clzs(__X) : 16;
-}
+#define __lzcnt16(X) __builtin_ia32_lzcnt_u16((unsigned short)(X))
+#endif // _MSC_VER
/// Counts the number of leading zero bits in the operand.
///
@@ -61,7 +59,7 @@ __lzcnt16(unsigned short __X)
static __inline__ unsigned int __DEFAULT_FN_ATTRS
__lzcnt32(unsigned int __X)
{
- return __X ? __builtin_clz(__X) : 32;
+ return __builtin_ia32_lzcnt_u32(__X);
}
/// Counts the number of leading zero bits in the operand.
@@ -78,10 +76,11 @@ __lzcnt32(unsigned int __X)
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_lzcnt_u32(unsigned int __X)
{
- return __X ? __builtin_clz(__X) : 32;
+ return __builtin_ia32_lzcnt_u32(__X);
}
#ifdef __x86_64__
+#ifndef _MSC_VER
/// Counts the number of leading zero bits in the operand.
///
/// \headerfile <x86intrin.h>
@@ -93,11 +92,8 @@ _lzcnt_u32(unsigned int __X)
/// \returns An unsigned 64-bit integer containing the number of leading zero
/// bits in the operand.
/// \see _lzcnt_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
-__lzcnt64(unsigned long long __X)
-{
- return __X ? __builtin_clzll(__X) : 64;
-}
+#define __lzcnt64(X) __builtin_ia32_lzcnt_u64((unsigned long long)(X))
+#endif // _MSC_VER
/// Counts the number of leading zero bits in the operand.
///
@@ -113,7 +109,7 @@ __lzcnt64(unsigned long long __X)
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_lzcnt_u64(unsigned long long __X)
{
- return __X ? __builtin_clzll(__X) : 64;
+ return __builtin_ia32_lzcnt_u64(__X);
}
#endif
diff --git a/lib/Headers/opencl-c.h b/lib/Headers/opencl-c.h
index e481c792df71..160bae807174 100644
--- a/lib/Headers/opencl-c.h
+++ b/lib/Headers/opencl-c.h
@@ -22,6 +22,14 @@
#endif //cl_khr_3d_image_writes
#endif //__OPENCL_C_VERSION__ < CL_VERSION_2_0
+#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
+#ifndef cl_intel_planar_yuv
+#define cl_intel_planar_yuv
+#endif // cl_intel_planar_yuv
+#pragma OPENCL EXTENSION cl_intel_planar_yuv : begin
+#pragma OPENCL EXTENSION cl_intel_planar_yuv : end
+#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
+
#define __ovld __attribute__((overloadable))
#define __conv __attribute__((convergent))
@@ -14462,7 +14470,7 @@ half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask);
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
-int printf(__constant const char* st, ...);
+int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
#endif
// OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions
@@ -14602,6 +14610,7 @@ int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, f
uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, int4 coord);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord);
+#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, int4 coord);
float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, float4 coord);
@@ -14609,6 +14618,7 @@ int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_
int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_t sampler, float4 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, int4 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, float4 coord);
+#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, int coord);
float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord);
@@ -14618,6 +14628,7 @@ int4 __purefn __ovld read_imagei(read_only image1d_t image, sampler_t sampler, f
uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, int coord);
uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, float coord);
+#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, int2 coord);
float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, float2 coord);
@@ -14625,6 +14636,7 @@ int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_
int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_t sampler, float2 coord);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, int2 coord);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, float2 coord);
+#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
#ifdef cl_khr_depth_images
float __purefn __ovld read_imagef(read_only image2d_depth_t image, sampler_t sampler, float2 coord);
@@ -14727,6 +14739,8 @@ uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler,
#endif //cl_khr_mipmap_image
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
+#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
+
/**
* Sampler-less Image Access
*/
@@ -14760,24 +14774,31 @@ float4 __purefn __ovld read_imagef(read_only image3d_t image, int4 coord);
int4 __purefn __ovld read_imagei(read_only image3d_t image, int4 coord);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, int4 coord);
+#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
+
// Image read functions returning half4 type
#ifdef cl_khr_fp16
half4 __purefn __ovld read_imageh(read_only image1d_t image, sampler_t sampler, int coord);
half4 __purefn __ovld read_imageh(read_only image1d_t image, sampler_t sampler, float coord);
-half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, int2 coord);
-half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, float2 coord);
half4 __purefn __ovld read_imageh(read_only image2d_t image, sampler_t sampler, int2 coord);
half4 __purefn __ovld read_imageh(read_only image2d_t image, sampler_t sampler, float2 coord);
half4 __purefn __ovld read_imageh(read_only image3d_t image, sampler_t sampler, int4 coord);
half4 __purefn __ovld read_imageh(read_only image3d_t image, sampler_t sampler, float4 coord);
+#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
+half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, int2 coord);
+half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, float2 coord);
half4 __purefn __ovld read_imageh(read_only image2d_array_t image, sampler_t sampler, int4 coord);
half4 __purefn __ovld read_imageh(read_only image2d_array_t image, sampler_t sampler, float4 coord);
+/**
+ * Sampler-less Image Access
+ */
half4 __purefn __ovld read_imageh(read_only image1d_t image, int coord);
half4 __purefn __ovld read_imageh(read_only image2d_t image, int2 coord);
half4 __purefn __ovld read_imageh(read_only image3d_t image, int4 coord);
half4 __purefn __ovld read_imageh(read_only image1d_array_t image, int2 coord);
half4 __purefn __ovld read_imageh(read_only image2d_array_t image, int4 coord);
half4 __purefn __ovld read_imageh(read_only image1d_buffer_t image, int coord);
+#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
#endif //cl_khr_fp16
// Image read functions for read_write images
@@ -15707,7 +15728,6 @@ double __ovld __conv work_group_scan_inclusive_max(double x);
// OpenCL v2.0 s6.13.16 - Pipe Functions
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
-#define PIPE_RESERVE_ID_VALID_BIT (1U << 30)
#define CLK_NULL_RESERVE_ID (__builtin_astype(((void*)(__SIZE_MAX__)), reserve_id_t))
bool __ovld is_valid_reserve_id(reserve_id_t reserve_id);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
@@ -16193,6 +16213,637 @@ void __ovld __conv intel_sub_group_block_write_us4( __global ushort* p, u
void __ovld __conv intel_sub_group_block_write_us8( __global ushort* p, ushort8 data );
#endif // cl_intel_subgroups_short
+#ifdef cl_intel_device_side_avc_motion_estimation
+#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : begin
+
+#define CLK_AVC_ME_MAJOR_16x16_INTEL 0x0
+#define CLK_AVC_ME_MAJOR_16x8_INTEL 0x1
+#define CLK_AVC_ME_MAJOR_8x16_INTEL 0x2
+#define CLK_AVC_ME_MAJOR_8x8_INTEL 0x3
+
+#define CLK_AVC_ME_MINOR_8x8_INTEL 0x0
+#define CLK_AVC_ME_MINOR_8x4_INTEL 0x1
+#define CLK_AVC_ME_MINOR_4x8_INTEL 0x2
+#define CLK_AVC_ME_MINOR_4x4_INTEL 0x3
+
+#define CLK_AVC_ME_MAJOR_FORWARD_INTEL 0x0
+#define CLK_AVC_ME_MAJOR_BACKWARD_INTEL 0x1
+#define CLK_AVC_ME_MAJOR_BIDIRECTIONAL_INTEL 0x2
+
+#define CLK_AVC_ME_PARTITION_MASK_ALL_INTEL 0x0
+#define CLK_AVC_ME_PARTITION_MASK_16x16_INTEL 0x7E
+#define CLK_AVC_ME_PARTITION_MASK_16x8_INTEL 0x7D
+#define CLK_AVC_ME_PARTITION_MASK_8x16_INTEL 0x7B
+#define CLK_AVC_ME_PARTITION_MASK_8x8_INTEL 0x77
+#define CLK_AVC_ME_PARTITION_MASK_8x4_INTEL 0x6F
+#define CLK_AVC_ME_PARTITION_MASK_4x8_INTEL 0x5F
+#define CLK_AVC_ME_PARTITION_MASK_4x4_INTEL 0x3F
+
+#define CLK_AVC_ME_SLICE_TYPE_PRED_INTEL 0x0
+#define CLK_AVC_ME_SLICE_TYPE_BPRED_INTEL 0x1
+#define CLK_AVC_ME_SLICE_TYPE_INTRA_INTEL 0x2
+
+#define CLK_AVC_ME_SEARCH_WINDOW_EXHAUSTIVE_INTEL 0x0
+#define CLK_AVC_ME_SEARCH_WINDOW_SMALL_INTEL 0x1
+#define CLK_AVC_ME_SEARCH_WINDOW_TINY_INTEL 0x2
+#define CLK_AVC_ME_SEARCH_WINDOW_EXTRA_TINY_INTEL 0x3
+#define CLK_AVC_ME_SEARCH_WINDOW_DIAMOND_INTEL 0x4
+#define CLK_AVC_ME_SEARCH_WINDOW_LARGE_DIAMOND_INTEL 0x5
+#define CLK_AVC_ME_SEARCH_WINDOW_RESERVED0_INTEL 0x6
+#define CLK_AVC_ME_SEARCH_WINDOW_RESERVED1_INTEL 0x7
+#define CLK_AVC_ME_SEARCH_WINDOW_CUSTOM_INTEL 0x8
+
+#define CLK_AVC_ME_SAD_ADJUST_MODE_NONE_INTEL 0x0
+#define CLK_AVC_ME_SAD_ADJUST_MODE_HAAR_INTEL 0x2
+
+#define CLK_AVC_ME_SUBPIXEL_MODE_INTEGER_INTEL 0x0
+#define CLK_AVC_ME_SUBPIXEL_MODE_HPEL_INTEL 0x1
+#define CLK_AVC_ME_SUBPIXEL_MODE_QPEL_INTEL 0x3
+
+#define CLK_AVC_ME_COST_PRECISION_QPEL_INTEL 0x0
+#define CLK_AVC_ME_COST_PRECISION_HPEL_INTEL 0x1
+#define CLK_AVC_ME_COST_PRECISION_PEL_INTEL 0x2
+#define CLK_AVC_ME_COST_PRECISION_DPEL_INTEL 0x3
+
+#define CLK_AVC_ME_BIDIR_WEIGHT_QUARTER_INTEL 0x10
+#define CLK_AVC_ME_BIDIR_WEIGHT_THIRD_INTEL 0x15
+#define CLK_AVC_ME_BIDIR_WEIGHT_HALF_INTEL 0x20
+#define CLK_AVC_ME_BIDIR_WEIGHT_TWO_THIRD_INTEL 0x2B
+#define CLK_AVC_ME_BIDIR_WEIGHT_THREE_QUARTER_INTEL 0x30
+
+#define CLK_AVC_ME_BORDER_REACHED_LEFT_INTEL 0x0
+#define CLK_AVC_ME_BORDER_REACHED_RIGHT_INTEL 0x2
+#define CLK_AVC_ME_BORDER_REACHED_TOP_INTEL 0x4
+#define CLK_AVC_ME_BORDER_REACHED_BOTTOM_INTEL 0x8
+
+#define CLK_AVC_ME_INTRA_16x16_INTEL 0x0
+#define CLK_AVC_ME_INTRA_8x8_INTEL 0x1
+#define CLK_AVC_ME_INTRA_4x4_INTEL 0x2
+
+#define CLK_AVC_ME_SKIP_BLOCK_PARTITION_16x16_INTEL 0x0
+#define CLK_AVC_ME_SKIP_BLOCK_PARTITION_8x8_INTEL 0x4000
+
+#define CLK_AVC_ME_SKIP_BLOCK_16x16_FORWARD_ENABLE_INTEL (0x1 << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_16x16_BACKWARD_ENABLE_INTEL (0x2 << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_16x16_DUAL_ENABLE_INTEL (0x3 << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_FORWARD_ENABLE_INTEL (0x55 << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_BACKWARD_ENABLE_INTEL (0xAA << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_DUAL_ENABLE_INTEL (0xFF << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_0_FORWARD_ENABLE_INTEL (0x1 << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_0_BACKWARD_ENABLE_INTEL (0x2 << 24)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_1_FORWARD_ENABLE_INTEL (0x1 << 26)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_1_BACKWARD_ENABLE_INTEL (0x2 << 26)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_2_FORWARD_ENABLE_INTEL (0x1 << 28)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_2_BACKWARD_ENABLE_INTEL (0x2 << 28)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_3_FORWARD_ENABLE_INTEL (0x1 << 30)
+#define CLK_AVC_ME_SKIP_BLOCK_8x8_3_BACKWARD_ENABLE_INTEL (0x2 << 30)
+
+#define CLK_AVC_ME_BLOCK_BASED_SKIP_4x4_INTEL 0x00
+#define CLK_AVC_ME_BLOCK_BASED_SKIP_8x8_INTEL 0x80
+
+#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_ALL_INTEL 0x0
+#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_16x16_INTEL 0x6
+#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_8x8_INTEL 0x5
+#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_4x4_INTEL 0x3
+
+#define CLK_AVC_ME_INTRA_NEIGHBOR_LEFT_MASK_ENABLE_INTEL 0x60
+#define CLK_AVC_ME_INTRA_NEIGHBOR_UPPER_MASK_ENABLE_INTEL 0x10
+#define CLK_AVC_ME_INTRA_NEIGHBOR_UPPER_RIGHT_MASK_ENABLE_INTEL 0x8
+#define CLK_AVC_ME_INTRA_NEIGHBOR_UPPER_LEFT_MASK_ENABLE_INTEL 0x4
+
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_VERTICAL_INTEL 0x0
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_HORIZONTAL_INTEL 0x1
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_DC_INTEL 0x2
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_DIAGONAL_DOWN_LEFT_INTEL 0x3
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_DIAGONAL_DOWN_RIGHT_INTEL 0x4
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_PLANE_INTEL 0x4
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_VERTICAL_RIGHT_INTEL 0x5
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_HORIZONTAL_DOWN_INTEL 0x6
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_VERTICAL_LEFT_INTEL 0x7
+#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_HORIZONTAL_UP_INTEL 0x8
+#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_DC_INTEL 0x0
+#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_HORIZONTAL_INTEL 0x1
+#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_VERTICAL_INTEL 0x2
+#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_PLANE_INTEL 0x3
+
+#define CLK_AVC_ME_FRAME_FORWARD_INTEL 0x1
+#define CLK_AVC_ME_FRAME_BACKWARD_INTEL 0x2
+#define CLK_AVC_ME_FRAME_DUAL_INTEL 0x3
+
+#define CLK_AVC_ME_INTERLACED_SCAN_TOP_FIELD_INTEL 0x0
+#define CLK_AVC_ME_INTERLACED_SCAN_BOTTOM_FIELD_INTEL 0x1
+
+#define CLK_AVC_ME_INITIALIZE_INTEL 0x0
+
+#define CLK_AVC_IME_PAYLOAD_INITIALIZE_INTEL 0x0
+#define CLK_AVC_REF_PAYLOAD_INITIALIZE_INTEL 0x0
+#define CLK_AVC_SIC_PAYLOAD_INITIALIZE_INTEL 0x0
+
+#define CLK_AVC_IME_RESULT_INITIALIZE_INTEL 0x0
+#define CLK_AVC_REF_RESULT_INITIALIZE_INTEL 0x0
+#define CLK_AVC_SIC_RESULT_INITIALIZE_INTEL 0x0
+
+#define CLK_AVC_IME_RESULT_SINGLE_REFERENCE_STREAMOUT_INITIALIZE_INTEL 0x0
+#define CLK_AVC_IME_RESULT_SINGLE_REFERENCE_STREAMIN_INITIALIZE_INTEL 0x0
+#define CLK_AVC_IME_RESULT_DUAL_REFERENCE_STREAMOUT_INITIALIZE_INTEL 0x0
+#define CLK_AVC_IME_RESULT_DUAL_REFERENCE_STREAMIN_INITIALIZE_INTEL 0x0
+
+// MCE built-in functions
+uchar __ovld
+intel_sub_group_avc_mce_get_default_inter_base_multi_reference_penalty(
+ uchar slice_type, uchar qp);
+ulong __ovld intel_sub_group_avc_mce_get_default_inter_shape_penalty(
+ uchar slice_type, uchar qp);
+uchar __ovld intel_sub_group_avc_mce_get_default_inter_direction_penalty(
+ uchar slice_type, uchar qp);
+uint __ovld intel_sub_group_avc_mce_get_default_intra_luma_shape_penalty(
+ uchar slice_type, uchar qp);
+uint2 __ovld
+intel_sub_group_avc_mce_get_default_inter_motion_vector_cost_table(
+ uchar slice_type, uchar qp);
+uchar __ovld intel_sub_group_avc_mce_get_default_intra_luma_mode_penalty(
+ uchar slice_type, uchar qp);
+
+uint2 __ovld intel_sub_group_avc_mce_get_default_high_penalty_cost_table();
+uint2 __ovld intel_sub_group_avc_mce_get_default_medium_penalty_cost_table();
+uint2 __ovld intel_sub_group_avc_mce_get_default_low_penalty_cost_table();
+uint __ovld intel_sub_group_avc_mce_get_default_non_dc_luma_intra_penalty();
+uchar __ovld
+intel_sub_group_avc_mce_get_default_intra_chroma_mode_base_penalty();
+
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_inter_base_multi_reference_penalty(
+ uchar reference_base_penalty, intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_inter_shape_penalty(
+ ulong packed_shape_penalty, intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_inter_direction_penalty(
+ uchar direction_cost, intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_motion_vector_cost_function(
+ ulong packed_cost_center_delta, uint2 packed_cost_table,
+ uchar cost_precision, intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_ac_only_haar(
+ intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_source_interlaced_field_polarity(
+ uchar src_field_polarity, intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_single_reference_interlaced_field_polarity(
+ uchar ref_field_polarity, intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_mce_set_dual_reference_interlaced_field_polarities(
+ uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
+ intel_sub_group_avc_mce_payload_t payload);
+
+ulong __ovld intel_sub_group_avc_mce_get_motion_vectors(
+ intel_sub_group_avc_mce_result_t result);
+ushort __ovld intel_sub_group_avc_mce_get_inter_distortions(
+ intel_sub_group_avc_mce_result_t result);
+ushort __ovld intel_sub_group_avc_mce_get_best_inter_distortion(
+ intel_sub_group_avc_mce_result_t result);
+uchar __ovld intel_sub_group_avc_mce_get_inter_major_shape(
+ intel_sub_group_avc_mce_result_t result);
+uchar __ovld intel_sub_group_avc_mce_get_inter_minor_shapes(
+ intel_sub_group_avc_mce_result_t result);
+uchar __ovld intel_sub_group_avc_mce_get_inter_directions(
+ intel_sub_group_avc_mce_result_t result);
+uchar __ovld intel_sub_group_avc_mce_get_inter_motion_vector_count(
+ intel_sub_group_avc_mce_result_t result);
+uint __ovld intel_sub_group_avc_mce_get_inter_reference_ids(
+ intel_sub_group_avc_mce_result_t result);
+uchar __ovld
+intel_sub_group_avc_mce_get_inter_reference_interlaced_field_polarities(
+ uint packed_reference_ids, uint packed_reference_parameter_field_polarities,
+ intel_sub_group_avc_mce_result_t result);
+
+// IME built-in functions
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_initialize(
+ ushort2 src_coord, uchar partition_mask, uchar sad_adjustment);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_single_reference(
+ short2 ref_offset, uchar search_window_config,
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_dual_reference(
+ short2 fwd_ref_offset, short2 bwd_ref_offset, uchar search_window_config,
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_max_motion_vector_count(
+ uchar max_motion_vector_count, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_unidirectional_mix_disable(
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_early_search_termination_threshold(
+ uchar threshold, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_weighted_sad(
+ uint packed_sad_weights, intel_sub_group_avc_ime_payload_t payload);
+
+__attribute__((deprecated("If you use the latest Intel driver, please use "
+ "intel_sub_group_avc_ime_ref_window_size instead",
+ "intel_sub_group_avc_ime_ref_window_size")))
+ushort2 __ovld
+intel_sub_group_ime_ref_window_size(uchar search_window_config, char dual_ref);
+ushort2 __ovld intel_sub_group_avc_ime_ref_window_size(
+ uchar search_window_config, char dual_ref);
+short2 __ovld intel_sub_group_avc_ime_adjust_ref_offset(
+ short2 ref_offset, ushort2 src_coord, ushort2 ref_window_size,
+ ushort2 image_size);
+
+intel_sub_group_avc_ime_result_t __ovld
+intel_sub_group_avc_ime_evaluate_with_single_reference(
+ read_only image2d_t src_image, read_only image2d_t ref_image,
+ sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_result_t __ovld
+intel_sub_group_avc_ime_evaluate_with_dual_reference(
+ read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
+ read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_result_single_reference_streamout_t __ovld
+intel_sub_group_avc_ime_evaluate_with_single_reference_streamout(
+ read_only image2d_t src_image, read_only image2d_t ref_image,
+ sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_result_dual_reference_streamout_t __ovld
+intel_sub_group_avc_ime_evaluate_with_dual_reference_streamout(
+ read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
+ read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_result_t __ovld
+intel_sub_group_avc_ime_evaluate_with_single_reference_streamin(
+ read_only image2d_t src_image, read_only image2d_t ref_image,
+ sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload,
+ intel_sub_group_avc_ime_single_reference_streamin_t streamin_components);
+intel_sub_group_avc_ime_result_t __ovld
+intel_sub_group_avc_ime_evaluate_with_dual_reference_streamin(
+ read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
+ read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
+ intel_sub_group_avc_ime_payload_t payload,
+ intel_sub_group_avc_ime_dual_reference_streamin_t streamin_components);
+intel_sub_group_avc_ime_result_single_reference_streamout_t __ovld
+intel_sub_group_avc_ime_evaluate_with_single_reference_streaminout(
+ read_only image2d_t src_image, read_only image2d_t ref_image,
+ sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload,
+ intel_sub_group_avc_ime_single_reference_streamin_t streamin_components);
+intel_sub_group_avc_ime_result_dual_reference_streamout_t __ovld
+intel_sub_group_avc_ime_evaluate_with_dual_reference_streaminout(
+ read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
+ read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
+ intel_sub_group_avc_ime_payload_t payload,
+ intel_sub_group_avc_ime_dual_reference_streamin_t streamin_components);
+
+intel_sub_group_avc_ime_single_reference_streamin_t __ovld
+intel_sub_group_avc_ime_get_single_reference_streamin(
+ intel_sub_group_avc_ime_result_single_reference_streamout_t result);
+intel_sub_group_avc_ime_dual_reference_streamin_t __ovld
+intel_sub_group_avc_ime_get_dual_reference_streamin(
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t result);
+intel_sub_group_avc_ime_result_t __ovld
+intel_sub_group_avc_ime_strip_single_reference_streamout(
+ intel_sub_group_avc_ime_result_single_reference_streamout_t result);
+intel_sub_group_avc_ime_result_t __ovld
+intel_sub_group_avc_ime_strip_dual_reference_streamout(
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t result);
+
+uint __ovld intel_sub_group_avc_ime_get_streamout_major_shape_motion_vectors(
+ intel_sub_group_avc_ime_result_single_reference_streamout_t result,
+ uchar major_shape);
+ushort __ovld intel_sub_group_avc_ime_get_streamout_major_shape_distortions(
+ intel_sub_group_avc_ime_result_single_reference_streamout_t result,
+ uchar major_shape);
+uchar __ovld intel_sub_group_avc_ime_get_streamout_major_shape_reference_ids(
+ intel_sub_group_avc_ime_result_single_reference_streamout_t result,
+ uchar major_shape);
+uint __ovld intel_sub_group_avc_ime_get_streamout_major_shape_motion_vectors(
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t result,
+ uchar major_shape, uchar direction);
+ushort __ovld intel_sub_group_avc_ime_get_streamout_major_shape_distortions(
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t result,
+ uchar major_shape, uchar direction);
+uchar __ovld intel_sub_group_avc_ime_get_streamout_major_shape_reference_ids(
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t result,
+ uchar major_shape, uchar direction);
+
+uchar __ovld intel_sub_group_avc_ime_get_border_reached(
+ uchar image_select, intel_sub_group_avc_ime_result_t result);
+uchar __ovld intel_sub_group_avc_ime_get_truncated_search_indication(
+ intel_sub_group_avc_ime_result_t result);
+uchar __ovld
+intel_sub_group_avc_ime_get_unidirectional_early_search_termination(
+ intel_sub_group_avc_ime_result_t result);
+uint __ovld intel_sub_group_avc_ime_get_weighting_pattern_minimum_motion_vector(
+ intel_sub_group_avc_ime_result_t result);
+ushort __ovld intel_sub_group_avc_ime_get_weighting_pattern_minimum_distortion(
+ intel_sub_group_avc_ime_result_t result);
+
+// REF built-in functions
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_fme_initialize(
+ ushort2 src_coord, ulong motion_vectors, uchar major_shapes,
+ uchar minor_shapes, uchar directions, uchar pixel_resolution,
+ uchar sad_adjustment);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_bme_initialize(
+ ushort2 src_coord, ulong motion_vectors, uchar major_shapes,
+ uchar minor_shapes, uchar directions, uchar pixel_resolution,
+ uchar bidirectional_weight, uchar sad_adjustment);
+
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_bidirectional_mix_disable(
+ intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_bilinear_filter_enable(
+ intel_sub_group_avc_ref_payload_t payload);
+
+intel_sub_group_avc_ref_result_t __ovld
+intel_sub_group_avc_ref_evaluate_with_single_reference(
+ read_only image2d_t src_image, read_only image2d_t ref_image,
+ sampler_t vme_media_sampler, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_ref_result_t __ovld
+intel_sub_group_avc_ref_evaluate_with_dual_reference(
+ read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
+ read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
+ intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_ref_result_t __ovld
+intel_sub_group_avc_ref_evaluate_with_multi_reference(
+ read_only image2d_t src_image, uint packed_reference_ids,
+ sampler_t vme_media_sampler, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_ref_result_t __ovld
+intel_sub_group_avc_ref_evaluate_with_multi_reference(
+ read_only image2d_t src_image, uint packed_reference_ids,
+ uchar packed_reference_field_polarities, sampler_t vme_media_sampler,
+ intel_sub_group_avc_ref_payload_t payload);
+
+// SIC built-in functions
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_initialize(
+ ushort2 src_coord);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_configure_skc(
+ uint skip_block_partition_type, uint skip_motion_vector_mask,
+ ulong motion_vectors, uchar bidirectional_weight, uchar skip_sad_adjustment,
+ intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_configure_ipe(
+ uchar luma_intra_partition_mask, uchar intra_neighbour_availabilty,
+ uchar left_edge_luma_pixels, uchar upper_left_corner_luma_pixel,
+ uchar upper_edge_luma_pixels, uchar upper_right_edge_luma_pixels,
+ uchar intra_sad_adjustment, intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_configure_ipe(
+ uchar luma_intra_partition_mask, uchar intra_neighbour_availabilty,
+ uchar left_edge_luma_pixels, uchar upper_left_corner_luma_pixel,
+ uchar upper_edge_luma_pixels, uchar upper_right_edge_luma_pixels,
+ ushort left_edge_chroma_pixels, ushort upper_left_corner_chroma_pixel,
+ ushort upper_edge_chroma_pixels, uchar intra_sad_adjustment,
+ intel_sub_group_avc_sic_payload_t payload);
+uint __ovld
+intel_sub_group_avc_sic_get_motion_vector_mask(
+ uint skip_block_partition_type, uchar direction);
+
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_intra_luma_shape_penalty(
+ uint packed_shape_cost, intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_intra_luma_mode_cost_function(
+ uchar luma_mode_penalty, uint luma_packed_neighbor_modes,
+ uint luma_packed_non_dc_penalty, intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_intra_chroma_mode_cost_function(
+ uchar chroma_mode_penalty, intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_skc_bilinear_filter_enable(
+ intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_skc_forward_transform_enable(
+ ulong packed_sad_coefficients, intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_block_based_raw_skip_sad(
+ uchar block_based_skip_type,
+ intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_sic_result_t __ovld
+intel_sub_group_avc_sic_evaluate_ipe(
+ read_only image2d_t src_image, sampler_t vme_media_sampler,
+ intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_result_t __ovld
+intel_sub_group_avc_sic_evaluate_with_single_reference(
+ read_only image2d_t src_image, read_only image2d_t ref_image,
+ sampler_t vme_media_sampler, intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_result_t __ovld
+intel_sub_group_avc_sic_evaluate_with_dual_reference(
+ read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
+ read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
+ intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_result_t __ovld
+intel_sub_group_avc_sic_evaluate_with_multi_reference(
+ read_only image2d_t src_image, uint packed_reference_ids,
+ sampler_t vme_media_sampler, intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_result_t __ovld
+intel_sub_group_avc_sic_evaluate_with_multi_reference(
+ read_only image2d_t src_image, uint packed_reference_ids,
+ uchar packed_reference_field_polarities, sampler_t vme_media_sampler,
+ intel_sub_group_avc_sic_payload_t payload);
+
+uchar __ovld intel_sub_group_avc_sic_get_ipe_luma_shape(
+ intel_sub_group_avc_sic_result_t result);
+ushort __ovld intel_sub_group_avc_sic_get_best_ipe_luma_distortion(
+ intel_sub_group_avc_sic_result_t result);
+ushort __ovld intel_sub_group_avc_sic_get_best_ipe_chroma_distortion(
+ intel_sub_group_avc_sic_result_t result);
+ulong __ovld intel_sub_group_avc_sic_get_packed_ipe_luma_modes(
+ intel_sub_group_avc_sic_result_t result);
+uchar __ovld intel_sub_group_avc_sic_get_ipe_chroma_mode(
+ intel_sub_group_avc_sic_result_t result);
+uint __ovld intel_sub_group_avc_sic_get_packed_skc_luma_count_threshold(
+ intel_sub_group_avc_sic_result_t result);
+ulong __ovld intel_sub_group_avc_sic_get_packed_skc_luma_sum_threshold(
+ intel_sub_group_avc_sic_result_t result);
+ushort __ovld intel_sub_group_avc_sic_get_inter_raw_sads(
+ intel_sub_group_avc_sic_result_t result);
+
+// Wrappers
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_inter_base_multi_reference_penalty(
+ uchar reference_base_penalty, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_inter_base_multi_reference_penalty(
+ uchar reference_base_penalty, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_inter_base_multi_reference_penalty(
+ uchar reference_base_penalty, intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_inter_shape_penalty(
+ ulong packed_shape_cost, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_inter_shape_penalty(
+ ulong packed_shape_cost, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_inter_shape_penalty(
+ ulong packed_shape_cost, intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_inter_direction_penalty(
+ uchar direction_cost, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_inter_direction_penalty(
+ uchar direction_cost, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_inter_direction_penalty(
+ uchar direction_cost, intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_motion_vector_cost_function(
+ ulong packed_cost_center_delta, uint2 packed_cost_table,
+ uchar cost_precision, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_motion_vector_cost_function(
+ ulong packed_cost_center_delta, uint2 packed_cost_table,
+ uchar cost_precision, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_motion_vector_cost_function(
+ ulong packed_cost_center_delta, uint2 packed_cost_table,
+ uchar cost_precision, intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_source_interlaced_field_polarity(
+ uchar src_field_polarity, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_source_interlaced_field_polarity(
+ uchar src_field_polarity, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_source_interlaced_field_polarity(
+ uchar src_field_polarity, intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_single_reference_interlaced_field_polarity(
+ uchar ref_field_polarity, intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_single_reference_interlaced_field_polarity(
+ uchar ref_field_polarity, intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_single_reference_interlaced_field_polarity(
+ uchar ref_field_polarity, intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_dual_reference_interlaced_field_polarities(
+ uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_dual_reference_interlaced_field_polarities(
+ uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
+ intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_dual_reference_interlaced_field_polarities(
+ uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
+ intel_sub_group_avc_sic_payload_t payload);
+
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_ime_set_ac_only_haar(
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_ref_set_ac_only_haar(
+ intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_sic_set_ac_only_haar(
+ intel_sub_group_avc_sic_payload_t payload);
+
+ulong __ovld intel_sub_group_avc_ime_get_motion_vectors(
+ intel_sub_group_avc_ime_result_t result);
+ulong __ovld intel_sub_group_avc_ref_get_motion_vectors(
+ intel_sub_group_avc_ref_result_t result);
+
+ushort __ovld intel_sub_group_avc_ime_get_inter_distortions(
+ intel_sub_group_avc_ime_result_t result);
+ushort __ovld intel_sub_group_avc_ref_get_inter_distortions(
+ intel_sub_group_avc_ref_result_t result);
+ushort __ovld intel_sub_group_avc_sic_get_inter_distortions(
+ intel_sub_group_avc_sic_result_t result);
+
+ushort __ovld intel_sub_group_avc_ime_get_best_inter_distortion(
+ intel_sub_group_avc_ime_result_t result);
+ushort __ovld intel_sub_group_avc_ref_get_best_inter_distortion(
+ intel_sub_group_avc_ref_result_t result);
+
+uchar __ovld intel_sub_group_avc_ime_get_inter_major_shape(
+ intel_sub_group_avc_ime_result_t result);
+uchar __ovld intel_sub_group_avc_ref_get_inter_major_shape(
+ intel_sub_group_avc_ref_result_t result);
+uchar __ovld intel_sub_group_avc_ime_get_inter_minor_shapes(
+ intel_sub_group_avc_ime_result_t result);
+uchar __ovld intel_sub_group_avc_ref_get_inter_minor_shapes(
+ intel_sub_group_avc_ref_result_t result);
+
+uchar __ovld intel_sub_group_avc_ime_get_inter_directions(
+ intel_sub_group_avc_ime_result_t result);
+uchar __ovld intel_sub_group_avc_ref_get_inter_directions(
+ intel_sub_group_avc_ref_result_t result);
+
+uchar __ovld intel_sub_group_avc_ime_get_inter_motion_vector_count(
+ intel_sub_group_avc_ime_result_t result);
+uchar __ovld intel_sub_group_avc_ref_get_inter_motion_vector_count(
+ intel_sub_group_avc_ref_result_t result);
+
+uint __ovld intel_sub_group_avc_ime_get_inter_reference_ids(
+ intel_sub_group_avc_ime_result_t result);
+uint __ovld intel_sub_group_avc_ref_get_inter_reference_ids(
+ intel_sub_group_avc_ref_result_t result);
+
+uchar __ovld
+intel_sub_group_avc_ime_get_inter_reference_interlaced_field_polarities(
+ uint packed_reference_ids, uint packed_reference_parameter_field_polarities,
+ intel_sub_group_avc_ime_result_t result);
+uchar __ovld
+intel_sub_group_avc_ref_get_inter_reference_interlaced_field_polarities(
+ uint packed_reference_ids, uint packed_reference_parameter_field_polarities,
+ intel_sub_group_avc_ref_result_t result);
+
+// Type conversion functions
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_ime_convert_to_mce_payload(
+ intel_sub_group_avc_ime_payload_t payload);
+intel_sub_group_avc_ime_payload_t __ovld
+intel_sub_group_avc_mce_convert_to_ime_payload(
+ intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_ref_convert_to_mce_payload(
+ intel_sub_group_avc_ref_payload_t payload);
+intel_sub_group_avc_ref_payload_t __ovld
+intel_sub_group_avc_mce_convert_to_ref_payload(
+ intel_sub_group_avc_mce_payload_t payload);
+intel_sub_group_avc_mce_payload_t __ovld
+intel_sub_group_avc_sic_convert_to_mce_payload(
+ intel_sub_group_avc_sic_payload_t payload);
+intel_sub_group_avc_sic_payload_t __ovld
+intel_sub_group_avc_mce_convert_to_sic_payload(
+ intel_sub_group_avc_mce_payload_t payload);
+
+intel_sub_group_avc_mce_result_t __ovld
+intel_sub_group_avc_ime_convert_to_mce_result(
+ intel_sub_group_avc_ime_result_t result);
+intel_sub_group_avc_ime_result_t __ovld
+intel_sub_group_avc_mce_convert_to_ime_result(
+ intel_sub_group_avc_mce_result_t result);
+intel_sub_group_avc_mce_result_t __ovld
+intel_sub_group_avc_ref_convert_to_mce_result(
+ intel_sub_group_avc_ref_result_t result);
+intel_sub_group_avc_ref_result_t __ovld
+intel_sub_group_avc_mce_convert_to_ref_result(
+ intel_sub_group_avc_mce_result_t result);
+intel_sub_group_avc_mce_result_t __ovld
+intel_sub_group_avc_sic_convert_to_mce_result(
+ intel_sub_group_avc_sic_result_t result);
+intel_sub_group_avc_sic_result_t __ovld
+intel_sub_group_avc_mce_convert_to_sic_result(
+ intel_sub_group_avc_mce_result_t result);
+#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : end
+#endif // cl_intel_device_side_avc_motion_estimation
+
#ifdef cl_amd_media_ops
uint __ovld amd_bitalign(uint a, uint b, uint c);
uint2 __ovld amd_bitalign(uint2 a, uint2 b, uint2 c);
diff --git a/lib/Headers/unwind.h b/lib/Headers/unwind.h
index 345fa4d0c193..0e8317e5b9d9 100644
--- a/lib/Headers/unwind.h
+++ b/lib/Headers/unwind.h
@@ -154,8 +154,12 @@ struct _Unwind_Control_Block {
struct _Unwind_Exception {
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
+#if !defined (__USING_SJLJ_EXCEPTIONS__) && defined (__SEH__)
+ _Unwind_Word private_[6];
+#else
_Unwind_Word private_1;
_Unwind_Word private_2;
+#endif
/* The Itanium ABI requires that _Unwind_Exception objects are "double-word
* aligned". GCC has interpreted this to mean "use the maximum useful
* alignment for the target"; so do we. */
diff --git a/lib/Headers/vecintrin.h b/lib/Headers/vecintrin.h
index f7061e88949f..e627389838df 100644
--- a/lib/Headers/vecintrin.h
+++ b/lib/Headers/vecintrin.h
@@ -381,7 +381,7 @@ vec_insert_and_zero(const unsigned long long *__ptr) {
static inline __ATTRS_o_ai vector float
vec_insert_and_zero(const float *__ptr) {
vector float __vec = (vector float)0;
- __vec[0] = *__ptr;
+ __vec[1] = *__ptr;
return __vec;
}
#endif
@@ -5942,13 +5942,13 @@ vec_orc(vector unsigned long long __a, vector unsigned long long __b) {
static inline __ATTRS_o_ai vector float
vec_orc(vector float __a, vector float __b) {
- return (vector float)((vector unsigned int)__a &
+ return (vector float)((vector unsigned int)__a |
~(vector unsigned int)__b);
}
static inline __ATTRS_o_ai vector double
vec_orc(vector double __a, vector double __b) {
- return (vector double)((vector unsigned long long)__a &
+ return (vector double)((vector unsigned long long)__a |
~(vector unsigned long long)__b);
}
#endif
diff --git a/lib/Index/CommentToXML.cpp b/lib/Index/CommentToXML.cpp
index 918068a2405f..a2659119a2ff 100644
--- a/lib/Index/CommentToXML.cpp
+++ b/lib/Index/CommentToXML.cpp
@@ -720,6 +720,7 @@ void CommentASTToXMLConverter::visitBlockCommandComment(
case CommandTraits::KCI_version:
case CommandTraits::KCI_warning:
ParagraphKind = C->getCommandName(Traits);
+ break;
default:
break;
}
diff --git a/lib/Index/IndexBody.cpp b/lib/Index/IndexBody.cpp
index 786563a44a4d..54a6df2496a9 100644
--- a/lib/Index/IndexBody.cpp
+++ b/lib/Index/IndexBody.cpp
@@ -9,6 +9,7 @@
#include "IndexingContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/ASTLambda.h"
using namespace clang;
using namespace clang::index;
@@ -143,7 +144,7 @@ public:
bool VisitMemberExpr(MemberExpr *E) {
SourceLocation Loc = E->getMemberLoc();
if (Loc.isInvalid())
- Loc = E->getLocStart();
+ Loc = E->getBeginLoc();
SmallVector<SymbolRelation, 4> Relations;
SymbolRoleSet Roles = getRolesForRef(E, Relations);
return IndexCtx.handleReference(E->getMemberDecl(), Loc,
@@ -175,7 +176,7 @@ public:
return true;
SourceLocation Loc = NameInfo.getLoc();
if (Loc.isInvalid())
- Loc = E->getLocStart();
+ Loc = E->getBeginLoc();
SmallVector<SymbolRelation, 4> Relations;
SymbolRoleSet Roles = getRolesForRef(E, Relations);
return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles,
@@ -259,8 +260,24 @@ public:
if (isDynamic(E)) {
Roles |= (unsigned)SymbolRole::Dynamic;
- if (auto *RecD = E->getReceiverInterface())
- Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
+
+ auto addReceivers = [&](const ObjCObjectType *Ty) {
+ if (!Ty)
+ return;
+ if (const auto *clsD = Ty->getInterface()) {
+ Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
+ clsD);
+ }
+ for (const auto *protD : Ty->quals()) {
+ Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
+ protD);
+ }
+ };
+ QualType recT = E->getReceiverType();
+ if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>())
+ addReceivers(Ptr->getObjectType());
+ else
+ addReceivers(recT->getAs<ObjCObjectType>());
}
return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
@@ -312,8 +329,8 @@ public:
SmallVector<SymbolRelation, 2> Relations;
addCallRole(Roles, Relations);
Roles |= (unsigned)SymbolRole::Implicit;
- return IndexCtx.handleReference(MD, E->getLocStart(),
- Parent, ParentDC, Roles, Relations, E);
+ return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC,
+ Roles, Relations, E);
}
bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
@@ -432,12 +449,22 @@ public:
for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
const OffsetOfNode &Component = S->getComponent(I);
if (Component.getKind() == OffsetOfNode::Field)
- IndexCtx.handleReference(Component.getField(), Component.getLocEnd(),
+ IndexCtx.handleReference(Component.getField(), Component.getEndLoc(),
Parent, ParentDC, SymbolRoleSet(), {});
// FIXME: Try to resolve dependent field references.
}
return true;
}
+
+ bool VisitParmVarDecl(ParmVarDecl* D) {
+ // Index the parameters of lambda expression.
+ if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
+ const auto *DC = D->getDeclContext();
+ if (DC && isLambdaCallOperator(DC))
+ IndexCtx.handleDecl(D);
+ }
+ return true;
+ }
};
} // anonymous namespace
diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp
index 01ad3a277216..a7725f9dd97f 100644
--- a/lib/Index/IndexDecl.cpp
+++ b/lib/Index/IndexDecl.cpp
@@ -263,7 +263,7 @@ public:
} else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
IndexCtx.handleReference(Dtor->getParent(),
- TypeNameInfo->getTypeLoc().getLocStart(),
+ TypeNameInfo->getTypeLoc().getBeginLoc(),
Dtor->getParent(), Dtor->getDeclContext());
}
} else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 03b55ffe8a4e..1cdc0984f780 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -96,6 +96,9 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
if (isFunctionLocalSymbol(D)) {
Info.Properties |= (SymbolPropertySet)SymbolProperty::Local;
}
+ if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
+ Info.Properties |= (SymbolPropertySet)SymbolProperty::ProtocolInterface;
+ }
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
switch (TD->getTagKind()) {
@@ -519,6 +522,7 @@ void index::applyForEachSymbolProperty(SymbolPropertySet Props,
APPLY_FOR_PROPERTY(IBOutletCollection);
APPLY_FOR_PROPERTY(GKInspectable);
APPLY_FOR_PROPERTY(Local);
+ APPLY_FOR_PROPERTY(ProtocolInterface);
#undef APPLY_FOR_PROPERTY
}
@@ -539,6 +543,7 @@ void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) {
case SymbolProperty::IBOutletCollection: OS << "IBColl"; break;
case SymbolProperty::GKInspectable: OS << "GKI"; break;
case SymbolProperty::Local: OS << "local"; break;
+ case SymbolProperty::ProtocolInterface: OS << "protocol"; break;
}
});
}
diff --git a/lib/Index/IndexTypeSourceInfo.cpp b/lib/Index/IndexTypeSourceInfo.cpp
index 4b6bfbc67eff..85afc6345053 100644
--- a/lib/Index/IndexTypeSourceInfo.cpp
+++ b/lib/Index/IndexTypeSourceInfo.cpp
@@ -100,7 +100,8 @@ public:
bool VisitTagTypeLoc(TagTypeLoc TL) {
TagDecl *D = TL.getDecl();
- if (D->getParentFunctionOrMethod())
+ if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
+ D->getParentFunctionOrMethod())
return true;
if (TL.isDefinition()) {
@@ -130,14 +131,15 @@ public:
bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) {
if (const auto *T = TL.getTypePtr()) {
if (IndexCtx.shouldIndexImplicitInstantiation()) {
- if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
Parent, ParentDC, SymbolRoleSet(), Relations);
- } else {
- if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
- IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
- Parent, ParentDC, SymbolRoleSet(), Relations);
+ return true;
+ }
}
+ if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
+ IndexCtx.handleReference(D, TL.getTemplateNameLoc(), Parent, ParentDC,
+ SymbolRoleSet(), Relations);
}
return true;
}
diff --git a/lib/Index/IndexingAction.cpp b/lib/Index/IndexingAction.cpp
index 16f6c21745ef..5cdec4b4528e 100644
--- a/lib/Index/IndexingAction.cpp
+++ b/lib/Index/IndexingAction.cpp
@@ -37,6 +37,7 @@ bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
}
bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
+ const Module *Mod,
SymbolRoleSet Roles,
SourceLocation Loc) {
return true;
@@ -215,23 +216,41 @@ static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
}
+static void indexPreprocessorMacros(const Preprocessor &PP,
+ IndexDataConsumer &DataConsumer) {
+ for (const auto &M : PP.macros())
+ if (MacroDirective *MD = M.second.getLatest())
+ DataConsumer.handleMacroOccurence(
+ M.first, MD->getMacroInfo(),
+ static_cast<unsigned>(index::SymbolRole::Definition),
+ MD->getLocation());
+}
+
void index::indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
IndexingOptions Opts) {
IndexingContext IndexCtx(Opts, DataConsumer);
IndexCtx.setASTContext(Unit.getASTContext());
DataConsumer.initialize(Unit.getASTContext());
DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());
+
+ if (Opts.IndexMacrosInPreprocessor)
+ indexPreprocessorMacros(Unit.getPreprocessor(), DataConsumer);
indexTranslationUnit(Unit, IndexCtx);
DataConsumer.finish();
}
-void index::indexTopLevelDecls(ASTContext &Ctx, ArrayRef<const Decl *> Decls,
+void index::indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP,
+ ArrayRef<const Decl *> Decls,
IndexDataConsumer &DataConsumer,
IndexingOptions Opts) {
IndexingContext IndexCtx(Opts, DataConsumer);
IndexCtx.setASTContext(Ctx);
DataConsumer.initialize(Ctx);
+
+ if (Opts.IndexMacrosInPreprocessor)
+ indexPreprocessorMacros(PP, DataConsumer);
+
for (const Decl *D : Decls)
IndexCtx.indexTopLevelDecl(D);
DataConsumer.finish();
@@ -251,6 +270,9 @@ void index::indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,
IndexCtx.setASTContext(Ctx);
DataConsumer.initialize(Ctx);
+ if (Opts.IndexMacrosInPreprocessor)
+ indexPreprocessorMacros(Reader.getPreprocessor(), DataConsumer);
+
for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
IndexCtx.indexTopLevelDecl(D);
}
diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp
index 333f9dc3091b..bba6c8390b56 100644
--- a/lib/Index/IndexingContext.cpp
+++ b/lib/Index/IndexingContext.cpp
@@ -80,11 +80,27 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
RefE, RefD, DC);
}
+static void reportModuleReferences(const Module *Mod,
+ ArrayRef<SourceLocation> IdLocs,
+ const ImportDecl *ImportD,
+ IndexDataConsumer &DataConsumer) {
+ if (!Mod)
+ return;
+ reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
+ DataConsumer);
+ DataConsumer.handleModuleOccurence(ImportD, Mod,
+ (SymbolRoleSet)SymbolRole::Reference,
+ IdLocs.back());
+}
+
bool IndexingContext::importedModule(const ImportDecl *ImportD) {
+ if (ImportD->isInvalidDecl())
+ return true;
+
SourceLocation Loc;
auto IdLocs = ImportD->getIdentifierLocs();
if (!IdLocs.empty())
- Loc = IdLocs.front();
+ Loc = IdLocs.back();
else
Loc = ImportD->getLocation();
@@ -108,11 +124,17 @@ bool IndexingContext::importedModule(const ImportDecl *ImportD) {
}
}
+ const Module *Mod = ImportD->getImportedModule();
+ if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
+ reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
+ DataConsumer);
+ }
+
SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
if (ImportD->isImplicit())
Roles |= (unsigned)SymbolRole::Implicit;
- return DataConsumer.handleModuleOccurence(ImportD, Roles, Loc);
+ return DataConsumer.handleModuleOccurence(ImportD, Mod, Roles, Loc);
}
bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
diff --git a/lib/Index/SimpleFormatContext.h b/lib/Index/SimpleFormatContext.h
index 9c6d29bec329..24adcac60201 100644
--- a/lib/Index/SimpleFormatContext.h
+++ b/lib/Index/SimpleFormatContext.h
@@ -36,12 +36,10 @@ class SimpleFormatContext {
public:
SimpleFormatContext(LangOptions Options)
: DiagOpts(new DiagnosticOptions()),
- Diagnostics(new DiagnosticsEngine(new DiagnosticIDs,
- DiagOpts.get())),
- InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ Diagnostics(new DiagnosticsEngine(new DiagnosticIDs, DiagOpts.get())),
+ InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
Files(FileSystemOptions(), InMemoryFileSystem),
- Sources(*Diagnostics, Files),
- Rewrite(Sources, Options) {
+ Sources(*Diagnostics, Files), Rewrite(Sources, Options) {
Diagnostics->setClient(new IgnoringDiagConsumer, true);
}
@@ -63,7 +61,7 @@ public:
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
FileManager Files;
SourceManager Sources;
Rewriter Rewrite;
diff --git a/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp
index b128b69931a3..84ca753bf840 100644
--- a/lib/Index/USRGeneration.cpp
+++ b/lib/Index/USRGeneration.cpp
@@ -97,6 +97,7 @@ public:
void VisitTypedefDecl(const TypedefDecl *D);
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
void VisitVarDecl(const VarDecl *D);
+ void VisitBindingDecl(const BindingDecl *D);
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
@@ -269,7 +270,8 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->isStatic())
Out << 'S';
- if (unsigned quals = MD->getTypeQualifiers())
+ // FIXME: OpenCL: Need to consider address spaces
+ if (unsigned quals = MD->getTypeQualifiers().getCVRUQualifiers())
Out << (char)('0' + quals);
switch (MD->getRefQualifier()) {
case RQ_None: break;
@@ -334,6 +336,12 @@ void USRGenerator::VisitVarDecl(const VarDecl *D) {
}
}
+void USRGenerator::VisitBindingDecl(const BindingDecl *D) {
+ if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))
+ return;
+ VisitNamedDecl(D);
+}
+
void USRGenerator::VisitNonTypeTemplateParmDecl(
const NonTypeTemplateParmDecl *D) {
GenLoc(D, /*IncludeOffset=*/true);
@@ -599,7 +607,7 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
D = D->getCanonicalDecl();
IgnoreResults =
- IgnoreResults || printLoc(Out, D->getLocStart(),
+ IgnoreResults || printLoc(Out, D->getBeginLoc(),
Context->getSourceManager(), IncludeOffset);
return IgnoreResults;
@@ -704,6 +712,9 @@ void USRGenerator::VisitType(QualType T) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
@@ -935,7 +946,7 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
case TemplateArgument::TemplateExpansion:
Out << 'P'; // pack expansion of...
- // Fall through
+ LLVM_FALLTHROUGH;
case TemplateArgument::Template:
VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
@@ -1094,3 +1105,40 @@ bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
Out << MacroName;
return false;
}
+
+bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
+ SmallVectorImpl<char> &Buf) {
+ if (T.isNull())
+ return true;
+ T = T.getCanonicalType();
+
+ USRGenerator UG(&Ctx, Buf);
+ UG.VisitType(T);
+ return UG.ignoreResults();
+}
+
+bool clang::index::generateFullUSRForModule(const Module *Mod,
+ raw_ostream &OS) {
+ if (!Mod->Parent)
+ return generateFullUSRForTopLevelModuleName(Mod->Name, OS);
+ if (generateFullUSRForModule(Mod->Parent, OS))
+ return true;
+ return generateUSRFragmentForModule(Mod, OS);
+}
+
+bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,
+ raw_ostream &OS) {
+ OS << getUSRSpacePrefix();
+ return generateUSRFragmentForModuleName(ModName, OS);
+}
+
+bool clang::index::generateUSRFragmentForModule(const Module *Mod,
+ raw_ostream &OS) {
+ return generateUSRFragmentForModuleName(Mod->Name, OS);
+}
+
+bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,
+ raw_ostream &OS) {
+ OS << "@M@" << ModName;
+ return false;
+}
diff --git a/lib/Lex/CMakeLists.txt b/lib/Lex/CMakeLists.txt
index 38df144adf9a..7888b15cb66e 100644
--- a/lib/Lex/CMakeLists.txt
+++ b/lib/Lex/CMakeLists.txt
@@ -17,7 +17,6 @@ add_clang_library(clangLex
PPExpressions.cpp
PPLexerChange.cpp
PPMacroExpansion.cpp
- PTHLexer.cpp
Pragma.cpp
PreprocessingRecord.cpp
Preprocessor.cpp
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index 24a14b6cdb57..23cb053c2d71 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -48,7 +48,8 @@ static inline unsigned HashHMapKey(StringRef Str) {
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
/// If it looks like a HeaderMap but is obviously corrupted, it puts a reason
/// into the string error argument and returns null.
-const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) {
+std::unique_ptr<HeaderMap> HeaderMap::Create(const FileEntry *FE,
+ FileManager &FM) {
// If the file is too small to be a header map, ignore it.
unsigned FileSize = FE->getSize();
if (FileSize <= sizeof(HMapHeader)) return nullptr;
@@ -59,7 +60,7 @@ const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) {
bool NeedsByteSwap;
if (!checkHeader(**FileBuffer, NeedsByteSwap))
return nullptr;
- return new HeaderMap(std::move(*FileBuffer), NeedsByteSwap);
+ return std::unique_ptr<HeaderMap>(new HeaderMap(std::move(*FileBuffer), NeedsByteSwap));
}
bool HeaderMapImpl::checkHeader(const llvm::MemoryBuffer &File,
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index fbfa54b2fffd..c65fb47c0fe5 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -17,7 +17,6 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderMap.h"
@@ -35,6 +34,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -75,12 +75,6 @@ HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}
-HeaderSearch::~HeaderSearch() {
- // Delete headermaps.
- for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
- delete HeaderMaps[i].second;
-}
-
void HeaderSearch::PrintStats() {
fprintf(stderr, "\n*** HeaderSearch Stats:\n");
fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size());
@@ -113,12 +107,12 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
// Pointer equality comparison of FileEntries works because they are
// already uniqued by inode.
if (HeaderMaps[i].first == FE)
- return HeaderMaps[i].second;
+ return HeaderMaps[i].second.get();
}
- if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) {
- HeaderMaps.push_back(std::make_pair(FE, HM));
- return HM;
+ if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) {
+ HeaderMaps.emplace_back(FE, std::move(HM));
+ return HeaderMaps.back().second.get();
}
return nullptr;
@@ -654,7 +648,7 @@ static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,
++I;
}
- return FoundComp >= 2;
+ return !FrameworkName.empty() && FoundComp >= 2;
}
static void
@@ -1577,20 +1571,21 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
DirNative);
// Search each of the ".framework" directories to load them as modules.
- vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
- for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
+ llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
+ DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
- if (llvm::sys::path::extension(Dir->getName()) != ".framework")
+ if (llvm::sys::path::extension(Dir->path()) != ".framework")
continue;
const DirectoryEntry *FrameworkDir =
- FileMgr.getDirectory(Dir->getName());
+ FileMgr.getDirectory(Dir->path());
if (!FrameworkDir)
continue;
// Load this framework module.
- loadFrameworkModule(llvm::sys::path::stem(Dir->getName()),
- FrameworkDir, IsSystem);
+ loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir,
+ IsSystem);
}
continue;
}
@@ -1643,15 +1638,16 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
return;
std::error_code EC;
+ SmallString<128> Dir = SearchDir.getDir()->getName();
+ FileMgr.makeAbsolutePath(Dir);
SmallString<128> DirNative;
- llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative);
- vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
- for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
+ llvm::sys::path::native(Dir, DirNative);
+ llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
- bool IsFramework =
- llvm::sys::path::extension(Dir->getName()) == ".framework";
+ bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
if (IsFramework == SearchDir.isFramework())
- loadModuleMapFile(Dir->getName(), SearchDir.isSystemHeaderDirectory(),
+ loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),
SearchDir.isFramework());
}
@@ -1682,9 +1678,8 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(
StringRef Dir = SearchDirs[I].getDir()->getName();
llvm::SmallString<32> DirPath(Dir.begin(), Dir.end());
if (!WorkingDir.empty() && !path::is_absolute(Dir)) {
- auto err = fs::make_absolute(WorkingDir, DirPath);
- if (!err)
- path::remove_dots(DirPath, /*remove_dot_dot=*/true);
+ fs::make_absolute(WorkingDir, DirPath);
+ path::remove_dots(DirPath, /*remove_dot_dot=*/true);
Dir = DirPath;
}
for (auto NI = path::begin(File), NE = path::end(File),
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index e8588a771a43..d4723091114a 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -1015,7 +1015,7 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
StringRef Lexer::getImmediateMacroNameForDiagnostics(
SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) {
assert(Loc.isMacroID() && "Only reasonable to call this on macros");
- // Walk past macro argument expanions.
+ // Walk past macro argument expansions.
while (SM.isMacroArgExpansion(Loc))
Loc = SM.getImmediateExpansionRange(Loc).getBegin();
@@ -1510,8 +1510,17 @@ static void maybeDiagnoseUTF8Homoglyph(DiagnosticsEngine &Diags, uint32_t C,
bool operator<(HomoglyphPair R) const { return Character < R.Character; }
};
static constexpr HomoglyphPair SortedHomoglyphs[] = {
+ {U'\u00ad', 0}, // SOFT HYPHEN
{U'\u01c3', '!'}, // LATIN LETTER RETROFLEX CLICK
{U'\u037e', ';'}, // GREEK QUESTION MARK
+ {U'\u200b', 0}, // ZERO WIDTH SPACE
+ {U'\u200c', 0}, // ZERO WIDTH NON-JOINER
+ {U'\u200d', 0}, // ZERO WIDTH JOINER
+ {U'\u2060', 0}, // WORD JOINER
+ {U'\u2061', 0}, // FUNCTION APPLICATION
+ {U'\u2062', 0}, // INVISIBLE TIMES
+ {U'\u2063', 0}, // INVISIBLE SEPARATOR
+ {U'\u2064', 0}, // INVISIBLE PLUS
{U'\u2212', '-'}, // MINUS SIGN
{U'\u2215', '/'}, // DIVISION SLASH
{U'\u2216', '\\'}, // SET MINUS
@@ -1521,6 +1530,7 @@ static void maybeDiagnoseUTF8Homoglyph(DiagnosticsEngine &Diags, uint32_t C,
{U'\u2236', ':'}, // RATIO
{U'\u223c', '~'}, // TILDE OPERATOR
{U'\ua789', ':'}, // MODIFIER LETTER COLON
+ {U'\ufeff', 0}, // ZERO WIDTH NO-BREAK SPACE
{U'\uff01', '!'}, // FULLWIDTH EXCLAMATION MARK
{U'\uff03', '#'}, // FULLWIDTH NUMBER SIGN
{U'\uff04', '$'}, // FULLWIDTH DOLLAR SIGN
@@ -1560,9 +1570,14 @@ static void maybeDiagnoseUTF8Homoglyph(DiagnosticsEngine &Diags, uint32_t C,
llvm::raw_svector_ostream CharOS(CharBuf);
llvm::write_hex(CharOS, C, llvm::HexPrintStyle::Upper, 4);
}
- const char LooksLikeStr[] = {Homoglyph->LooksLike, 0};
- Diags.Report(Range.getBegin(), diag::warn_utf8_symbol_homoglyph)
- << Range << CharBuf << LooksLikeStr;
+ if (Homoglyph->LooksLike) {
+ const char LooksLikeStr[] = {Homoglyph->LooksLike, 0};
+ Diags.Report(Range.getBegin(), diag::warn_utf8_symbol_homoglyph)
+ << Range << CharBuf << LooksLikeStr;
+ } else {
+ Diags.Report(Range.getBegin(), diag::warn_utf8_symbol_zero_width)
+ << Range << CharBuf;
+ }
}
}
@@ -1881,6 +1896,7 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
/// either " or L" or u8" or u" or U".
bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
tok::TokenKind Kind) {
+ const char *AfterQuote = CurPtr;
// Does this string contain the \0 character?
const char *NulCharacter = nullptr;
@@ -1909,8 +1925,11 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
if (C == 0) {
if (isCodeCompletionPoint(CurPtr-1)) {
- PP->CodeCompleteNaturalLanguage();
- FormTokenWithChars(Result, CurPtr-1, tok::unknown);
+ if (ParsingFilename)
+ codeCompleteIncludedFile(AfterQuote, CurPtr - 1, /*IsAngled=*/false);
+ else
+ PP->CodeCompleteNaturalLanguage();
+ FormTokenWithChars(Result, CurPtr - 1, tok::unknown);
cutOffLexing();
return true;
}
@@ -2028,9 +2047,8 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
if (C == '\\')
C = getAndAdvanceChar(CurPtr, Result);
- if (C == '\n' || C == '\r' || // Newline.
- (C == 0 && (CurPtr-1 == BufferEnd || // End of file.
- isCodeCompletionPoint(CurPtr-1)))) {
+ if (C == '\n' || C == '\r' || // Newline.
+ (C == 0 && (CurPtr - 1 == BufferEnd))) { // End of file.
// If the filename is unterminated, then it must just be a lone <
// character. Return this as such.
FormTokenWithChars(Result, AfterLessPos, tok::less);
@@ -2038,6 +2056,12 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
}
if (C == 0) {
+ if (isCodeCompletionPoint(CurPtr - 1)) {
+ codeCompleteIncludedFile(AfterLessPos, CurPtr - 1, /*IsAngled=*/true);
+ cutOffLexing();
+ FormTokenWithChars(Result, CurPtr - 1, tok::unknown);
+ return true;
+ }
NulCharacter = CurPtr-1;
}
C = getAndAdvanceChar(CurPtr, Result);
@@ -2054,6 +2078,34 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
return true;
}
+void Lexer::codeCompleteIncludedFile(const char *PathStart,
+ const char *CompletionPoint,
+ bool IsAngled) {
+ // Completion only applies to the filename, after the last slash.
+ StringRef PartialPath(PathStart, CompletionPoint - PathStart);
+ auto Slash = PartialPath.find_last_of(LangOpts.MSVCCompat ? "/\\" : "/");
+ StringRef Dir =
+ (Slash == StringRef::npos) ? "" : PartialPath.take_front(Slash);
+ const char *StartOfFilename =
+ (Slash == StringRef::npos) ? PathStart : PathStart + Slash + 1;
+ // Code completion filter range is the filename only, up to completion point.
+ PP->setCodeCompletionIdentifierInfo(&PP->getIdentifierTable().get(
+ StringRef(StartOfFilename, CompletionPoint - StartOfFilename)));
+ // We should replace the characters up to the closing quote, if any.
+ while (CompletionPoint < BufferEnd) {
+ char Next = *(CompletionPoint + 1);
+ if (Next == 0 || Next == '\r' || Next == '\n')
+ break;
+ ++CompletionPoint;
+ if (Next == (IsAngled ? '>' : '"'))
+ break;
+ }
+ PP->setCodeCompletionTokenRange(
+ FileLoc.getLocWithOffset(StartOfFilename - BufferStart),
+ FileLoc.getLocWithOffset(CompletionPoint - BufferStart));
+ PP->CodeCompleteIncludedFile(Dir, IsAngled);
+}
+
/// LexCharConstant - Lex the remainder of a character constant, after having
/// lexed either ' or L' or u8' or u' or U'.
bool Lexer::LexCharConstant(Token &Result, const char *CurPtr,
@@ -3033,6 +3085,8 @@ bool Lexer::LexUnicode(Token &Result, uint32_t C, const char *CurPtr) {
maybeDiagnoseIDCharCompat(PP->getDiagnostics(), C,
makeCharRange(*this, BufferPtr, CurPtr),
/*IsFirst=*/true);
+ maybeDiagnoseUTF8Homoglyph(PP->getDiagnostics(), C,
+ makeCharRange(*this, BufferPtr, CurPtr));
}
MIOpt.ReadToken();
@@ -3790,7 +3844,7 @@ LexNextToken:
case '@':
// Objective C support.
- if (CurPtr[-1] == '@' && LangOpts.ObjC1)
+ if (CurPtr[-1] == '@' && LangOpts.ObjC)
Kind = tok::at;
else
Kind = tok::unknown;
@@ -3827,7 +3881,6 @@ LexNextToken:
// We can't just reset CurPtr to BufferPtr because BufferPtr may point to
// an escaped newline.
--CurPtr;
- const char *UTF8StartPtr = CurPtr;
llvm::ConversionResult Status =
llvm::convertUTF8Sequence((const llvm::UTF8 **)&CurPtr,
(const llvm::UTF8 *)BufferEnd,
@@ -3842,9 +3895,6 @@ LexNextToken:
// (We manually eliminate the tail call to avoid recursion.)
goto LexNextToken;
}
- if (!isLexingRawMode())
- maybeDiagnoseUTF8Homoglyph(PP->getDiagnostics(), CodePoint,
- makeCharRange(*this, UTF8StartPtr, CurPtr));
return LexUnicode(Result, CodePoint, CurPtr);
}
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index 3f2af1a74e5a..fa0815eb9c6c 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -693,7 +693,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
break;
}
}
- // fall through.
+ LLVM_FALLTHROUGH;
case 'j':
case 'J':
if (isImaginary) break; // Cannot be repeated.
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index 4ed69ecc465d..434c12007596 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -200,7 +200,8 @@ MacroDirective::DefInfo MacroDirective::getDefinition() {
}
const MacroDirective::DefInfo
-MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const {
+MacroDirective::findDirectiveAtLoc(SourceLocation L,
+ const SourceManager &SM) const {
assert(L.isValid() && "SourceLocation is invalid.");
for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {
if (Def.getLocation().isInvalid() || // For macros defined on the command line.
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 87749f74734c..cff950b703a6 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -22,7 +22,6 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
@@ -43,6 +42,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -54,6 +54,8 @@
using namespace clang;
+void ModuleMapCallbacks::anchor() {}
+
void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
if (PendingLinkAs != PendingLinkAsModule.end()) {
@@ -523,7 +525,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
// At this point, only non-modular includes remain.
- if (LangOpts.ModulesStrictDeclUse) {
+ if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
<< RequestingModule->getTopLevelModule()->Name << Filename;
} else if (RequestingModule && RequestingModuleIsModuleInterface &&
@@ -806,12 +808,11 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
}
Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
- assert(!PendingGlobalModule && "created multiple global modules");
- PendingGlobalModule.reset(
+ PendingSubmodules.emplace_back(
new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
/*IsExplicit*/ true, NumCreatedModules++));
- PendingGlobalModule->Kind = Module::GlobalModuleFragment;
- return PendingGlobalModule.get();
+ PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
+ return PendingSubmodules.back().get();
}
Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
@@ -827,10 +828,11 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
Modules[Name] = SourceModule = Result;
// Reparent the current global module fragment as a submodule of this module.
- assert(GlobalModule == PendingGlobalModule.get() &&
- "unexpected global module");
- GlobalModule->setParent(Result);
- PendingGlobalModule.release(); // now owned by parent
+ for (auto &Submodule : PendingSubmodules) {
+ Submodule->setParent(Result);
+ Submodule.release(); // now owned by parent
+ }
+ PendingSubmodules.clear();
// Mark the main source file as being within the newly-created module so that
// declarations and macros are properly visibility-restricted to it.
@@ -841,6 +843,29 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
return Result;
}
+Module *ModuleMap::createHeaderModule(StringRef Name,
+ ArrayRef<Module::Header> Headers) {
+ assert(LangOpts.CurrentModule == Name && "module name mismatch");
+ assert(!Modules[Name] && "redefining existing module");
+
+ auto *Result =
+ new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
+ /*IsExplicit*/ false, NumCreatedModules++);
+ Result->Kind = Module::ModuleInterfaceUnit;
+ Modules[Name] = SourceModule = Result;
+
+ for (const Module::Header &H : Headers) {
+ auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
+ /*IsFramework*/ false,
+ /*IsExplicit*/ true, NumCreatedModules++);
+ // Header modules are implicitly 'export *'.
+ M->Exports.push_back(Module::ExportDecl(nullptr, true));
+ addHeader(M, H, NormalHeader);
+ }
+
+ return Result;
+}
+
/// For a framework module, infer the framework against which we
/// should link.
static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
@@ -997,15 +1022,16 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
= StringRef(FrameworkDir->getName());
llvm::sys::path::append(SubframeworksDirName, "Frameworks");
llvm::sys::path::native(SubframeworksDirName);
- vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
- for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC),
- DirEnd;
+ llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ for (llvm::vfs::directory_iterator
+ Dir = FS.dir_begin(SubframeworksDirName, EC),
+ DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
- if (!StringRef(Dir->getName()).endswith(".framework"))
+ if (!StringRef(Dir->path()).endswith(".framework"))
continue;
if (const DirectoryEntry *SubframeworkDir =
- FileMgr.getDirectory(Dir->getName())) {
+ FileMgr.getDirectory(Dir->path())) {
// Note: as an egregious but useful hack, we use the real path here and
// check whether it is actually a subdirectory of the parent directory.
// This will not be the case if the 'subframework' is actually a symlink
@@ -2371,13 +2397,13 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
// uncommonly used Tcl module on Darwin platforms.
std::error_code EC;
SmallVector<Module::Header, 6> Headers;
- vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem();
- for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
+ llvm::vfs::FileSystem &FS =
+ *SourceMgr.getFileManager().getVirtualFileSystem();
+ for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
I != E && !EC; I.increment(EC)) {
- if (const FileEntry *FE =
- SourceMgr.getFileManager().getFile(I->getName())) {
+ if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) {
- Module::Header Header = {I->getName(), FE};
+ Module::Header Header = {I->path(), FE};
Headers.push_back(std::move(Header));
}
}
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 66a9faa6e60a..d62a3513c777 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -31,7 +31,6 @@
#include "clang/Lex/Pragma.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/VariadicMacroSupport.h"
#include "llvm/ADT/ArrayRef.h"
@@ -119,7 +118,7 @@ static bool isReservedId(StringRef Text, const LangOptions &Lang) {
// the specified module, meaning clang won't build the specified module. This is
// useful in a number of situations, for instance, when building a library that
// vends a module map, one might want to avoid hitting intermediate build
-// products containig the the module map or avoid finding the system installed
+// products containimg the the module map or avoid finding the system installed
// modulemap for that library.
static bool isForModuleBuilding(Module *M, StringRef CurrentModule,
StringRef ModuleName) {
@@ -383,11 +382,6 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/ false,
FoundNonSkipPortion, FoundElse);
- if (CurPTHLexer) {
- PTHSkipExcludedConditionalBlock();
- return;
- }
-
// Enter raw mode to disable identifier lookup (and thus macro expansion),
// disabling warnings, etc.
CurPPLexer->LexingRawMode = true;
@@ -405,7 +399,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
// If this is the end of the buffer, we have an error.
if (Tok.is(tok::eof)) {
// We don't emit errors for unterminated conditionals here,
- // Lexer::LexEndOfFile can do that propertly.
+ // Lexer::LexEndOfFile can do that properly.
// Just return and let the caller lex after this #include.
if (PreambleConditionalStack.isRecording())
PreambleConditionalStack.SkipInfo.emplace(
@@ -585,83 +579,6 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
Tok.getLocation());
}
-void Preprocessor::PTHSkipExcludedConditionalBlock() {
- while (true) {
- assert(CurPTHLexer);
- assert(CurPTHLexer->LexingRawMode == false);
-
- // Skip to the next '#else', '#elif', or #endif.
- if (CurPTHLexer->SkipBlock()) {
- // We have reached an #endif. Both the '#' and 'endif' tokens
- // have been consumed by the PTHLexer. Just pop off the condition level.
- PPConditionalInfo CondInfo;
- bool InCond = CurPTHLexer->popConditionalLevel(CondInfo);
- (void)InCond; // Silence warning in no-asserts mode.
- assert(!InCond && "Can't be skipping if not in a conditional!");
- break;
- }
-
- // We have reached a '#else' or '#elif'. Lex the next token to get
- // the directive flavor.
- Token Tok;
- LexUnexpandedToken(Tok);
-
- // We can actually look up the IdentifierInfo here since we aren't in
- // raw mode.
- tok::PPKeywordKind K = Tok.getIdentifierInfo()->getPPKeywordID();
-
- if (K == tok::pp_else) {
- // #else: Enter the else condition. We aren't in a nested condition
- // since we skip those. We're always in the one matching the last
- // blocked we skipped.
- PPConditionalInfo &CondInfo = CurPTHLexer->peekConditionalLevel();
- // Note that we've seen a #else in this conditional.
- CondInfo.FoundElse = true;
-
- // If the #if block wasn't entered then enter the #else block now.
- if (!CondInfo.FoundNonSkip) {
- CondInfo.FoundNonSkip = true;
-
- // Scan until the eod token.
- CurPTHLexer->ParsingPreprocessorDirective = true;
- DiscardUntilEndOfDirective();
- CurPTHLexer->ParsingPreprocessorDirective = false;
-
- break;
- }
-
- // Otherwise skip this block.
- continue;
- }
-
- assert(K == tok::pp_elif);
- PPConditionalInfo &CondInfo = CurPTHLexer->peekConditionalLevel();
-
- // If this is a #elif with a #else before it, report the error.
- if (CondInfo.FoundElse)
- Diag(Tok, diag::pp_err_elif_after_else);
-
- // If this is in a skipping block or if we're already handled this #if
- // block, don't bother parsing the condition. We just skip this block.
- if (CondInfo.FoundNonSkip)
- continue;
-
- // Evaluate the condition of the #elif.
- IdentifierInfo *IfNDefMacro = nullptr;
- CurPTHLexer->ParsingPreprocessorDirective = true;
- bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro).Conditional;
- CurPTHLexer->ParsingPreprocessorDirective = false;
-
- // If this condition is true, enter it!
- if (ShouldEnter) {
- CondInfo.FoundNonSkip = true;
- break;
- }
-
- // Otherwise, skip this block and go to the next one.
- }
-}
-
Module *Preprocessor::getModuleForLocation(SourceLocation Loc) {
if (!SourceMgr.isInMainFile(Loc)) {
// Try to determine the module of the include directive.
@@ -690,7 +607,7 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
// If we have a module import syntax, we shouldn't include a header to
// make a particular module visible.
- if (getLangOpts().ObjC2)
+ if (getLangOpts().ObjC)
return nullptr;
Module *TopM = M->getTopLevelModule();
@@ -887,18 +804,29 @@ private:
bool save;
};
-/// Process a directive while looking for the through header.
-/// Only #include (to check if it is the through header) and #define (to warn
-/// about macros that don't match the PCH) are handled. All other directives
-/// are completely discarded.
-void Preprocessor::HandleSkippedThroughHeaderDirective(Token &Result,
+/// Process a directive while looking for the through header or a #pragma
+/// hdrstop. The following directives are handled:
+/// #include (to check if it is the through header)
+/// #define (to warn about macros that don't match the PCH)
+/// #pragma (to check for pragma hdrstop).
+/// All other directives are completely discarded.
+void Preprocessor::HandleSkippedDirectiveWhileUsingPCH(Token &Result,
SourceLocation HashLoc) {
if (const IdentifierInfo *II = Result.getIdentifierInfo()) {
- if (II->getPPKeywordID() == tok::pp_include)
- return HandleIncludeDirective(HashLoc, Result);
- if (II->getPPKeywordID() == tok::pp_define)
+ if (II->getPPKeywordID() == tok::pp_define) {
return HandleDefineDirective(Result,
/*ImmediatelyAfterHeaderGuard=*/false);
+ }
+ if (SkippingUntilPCHThroughHeader &&
+ II->getPPKeywordID() == tok::pp_include) {
+ return HandleIncludeDirective(HashLoc, Result);
+ }
+ if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
+ Token P = LookAhead(0);
+ auto *II = P.getIdentifierInfo();
+ if (II && II->getName() == "hdrstop")
+ return HandlePragmaDirective(HashLoc, PIK_HashPragma);
+ }
}
DiscardUntilEndOfDirective();
}
@@ -964,8 +892,8 @@ void Preprocessor::HandleDirective(Token &Result) {
// and reset to previous state when returning from this function.
ResetMacroExpansionHelper helper(this);
- if (SkippingUntilPCHThroughHeader)
- return HandleSkippedThroughHeaderDirective(Result, SavedHash.getLocation());
+ if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
+ return HandleSkippedDirectiveWhileUsingPCH(Result, SavedHash.getLocation());
switch (Result.getKind()) {
case tok::eod:
@@ -1376,10 +1304,6 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
///
void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,
bool isWarning) {
- // PTH doesn't emit #warning or #error directives.
- if (CurPTHLexer)
- return CurPTHLexer->DiscardToEndOfLine();
-
// Read the rest of the line raw. We do this because we don't want macros
// to be expanded and we don't require that the tokens be valid preprocessing
// tokens. For example, this is allowed: "#warning ` 'foo". GCC does
@@ -1618,7 +1542,7 @@ static void diagnoseAutoModuleImport(
Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok,
ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,
SourceLocation PathEnd) {
- assert(PP.getLangOpts().ObjC2 && "no import syntax available");
+ assert(PP.getLangOpts().ObjC && "no import syntax available");
SmallString<128> PathString;
for (size_t I = 0, N = Path.size(); I != N; ++I) {
@@ -1783,6 +1707,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Check that we don't have infinite #include recursion.
if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
Diag(FilenameTok, diag::err_pp_include_too_deep);
+ HasReachedMaxIncludeDepth = true;
return;
}
@@ -1868,15 +1793,58 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped);
if (File) {
SourceRange Range(FilenameTok.getLocation(), CharEnd);
- Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) <<
+ Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal) <<
Filename <<
FixItHint::CreateReplacement(Range, "\"" + Filename.str() + "\"");
}
}
+ // Check for likely typos due to leading or trailing non-isAlphanumeric
+ // characters
+ StringRef OriginalFilename = Filename;
+ if (LangOpts.SpellChecking && !File) {
+ // A heuristic to correct a typo file name by removing leading and
+ // trailing non-isAlphanumeric characters.
+ auto CorrectTypoFilename = [](llvm::StringRef Filename) {
+ Filename = Filename.drop_until(isAlphanumeric);
+ while (!Filename.empty() && !isAlphanumeric(Filename.back())) {
+ Filename = Filename.drop_back();
+ }
+ return Filename;
+ };
+ StringRef TypoCorrectionName = CorrectTypoFilename(Filename);
+ SmallString<128> NormalizedTypoCorrectionPath;
+ if (LangOpts.MSVCCompat) {
+ NormalizedTypoCorrectionPath = TypoCorrectionName.str();
+#ifndef _WIN32
+ llvm::sys::path::native(NormalizedTypoCorrectionPath);
+#endif
+ }
+ File = LookupFile(
+ FilenameLoc,
+ LangOpts.MSVCCompat ? NormalizedTypoCorrectionPath.c_str()
+ : TypoCorrectionName,
+ isAngled, LookupFrom, LookupFromFile, CurDir,
+ Callbacks ? &SearchPath : nullptr,
+ Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped);
+ if (File) {
+ SourceRange Range(FilenameTok.getLocation(), CharEnd);
+ auto Hint = isAngled
+ ? FixItHint::CreateReplacement(
+ Range, "<" + TypoCorrectionName.str() + ">")
+ : FixItHint::CreateReplacement(
+ Range, "\"" + TypoCorrectionName.str() + "\"");
+ Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
+ << OriginalFilename << TypoCorrectionName << Hint;
+ // We found the file, so set the Filename to the name after typo
+ // correction.
+ Filename = TypoCorrectionName;
+ }
+ }
+
// If the file is still not found, just go with the vanilla diagnostic
if (!File)
- Diag(FilenameTok, diag::err_pp_file_not_found) << Filename
+ Diag(FilenameTok, diag::err_pp_file_not_found) << OriginalFilename
<< FilenameRange;
}
}
@@ -1896,10 +1864,11 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (PPOpts->SingleFileParseMode)
ShouldEnter = false;
- // Any diagnostics after the fatal error will not be visible. As the
- // compilation failed already and errors in subsequently included files won't
- // be visible, avoid preprocessing those files.
- if (ShouldEnter && Diags->hasFatalErrorOccurred())
+ // If we've reached the max allowed include depth, it is usually due to an
+ // include cycle. Don't enter already processed files again as it can lead to
+ // reaching the max allowed include depth again.
+ if (ShouldEnter && HasReachedMaxIncludeDepth && File &&
+ HeaderInfo.getFileInfo(File).NumIncludes)
ShouldEnter = false;
// Determine whether we should try to import the module for this #include, if
@@ -1932,7 +1901,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Warn that we're replacing the include/import with a module import.
// We only do this in Objective-C, where we have a module-import syntax.
- if (getLangOpts().ObjC2)
+ if (getLangOpts().ObjC)
diagnoseAutoModuleImport(*this, HashLoc, IncludeTok, Path, CharEnd);
// Load the module to import its macros. We'll make the declarations
@@ -1961,14 +1930,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (hadModuleLoaderFatalFailure()) {
// With a fatal failure in the module loader, we abort parsing.
Token &Result = IncludeTok;
- if (CurLexer) {
- Result.startToken();
- CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
- CurLexer->cutOffLexing();
- } else {
- assert(CurPTHLexer && "#include but no current lexer set!");
- CurPTHLexer->getEOF(Result);
- }
+ assert(CurLexer && "#include but no current lexer set!");
+ Result.startToken();
+ CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
+ CurLexer->cutOffLexing();
}
return;
}
@@ -2169,7 +2134,7 @@ void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) {
///
void Preprocessor::HandleImportDirective(SourceLocation HashLoc,
Token &ImportTok) {
- if (!LangOpts.ObjC1) { // #import is standard for ObjC.
+ if (!LangOpts.ObjC) { // #import is standard for ObjC.
if (LangOpts.MSVCCompat)
return HandleMicrosoftImportDirective(ImportTok);
Diag(ImportTok, diag::ext_pp_import_directive);
@@ -2640,7 +2605,7 @@ void Preprocessor::HandleDefineDirective(
II->isStr("__unsafe_unretained") ||
II->isStr("__autoreleasing");
};
- if (getLangOpts().ObjC1 &&
+ if (getLangOpts().ObjC &&
SourceMgr.getFileID(OtherMI->getDefinitionLoc())
== getPredefinesFileID() &&
isObjCProtectedMacro(MacroNameTok.getIdentifierInfo())) {
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index 6631b13b1583..e321dd38fed6 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -19,7 +19,6 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/MacroInfo.h"
-#include "clang/Lex/PTHManager.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -76,13 +75,6 @@ bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
if (MaxIncludeStackDepth < IncludeMacroStack.size())
MaxIncludeStackDepth = IncludeMacroStack.size();
- if (PTH) {
- if (PTHLexer *PL = PTH->CreateLexer(FID)) {
- EnterSourceFileWithPTH(PL, CurDir);
- return false;
- }
- }
-
// Get the MemoryBuffer for this FID, if it fails, we fail.
bool Invalid = false;
const llvm::MemoryBuffer *InputFile =
@@ -131,31 +123,6 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
}
}
-/// EnterSourceFileWithPTH - Add a source file to the top of the include stack
-/// and start getting tokens from it using the PTH cache.
-void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
- const DirectoryLookup *CurDir) {
-
- if (CurPPLexer || CurTokenLexer)
- PushIncludeMacroStack();
-
- CurDirLookup = CurDir;
- CurPTHLexer.reset(PL);
- CurPPLexer = CurPTHLexer.get();
- CurLexerSubmodule = nullptr;
- if (CurLexerKind != CLK_LexAfterModuleImport)
- CurLexerKind = CLK_PTHLexer;
-
- // Notify the client, if desired, that we are in a new source file.
- if (Callbacks) {
- FileID FID = CurPPLexer->getFileID();
- SourceLocation EnterLoc = SourceMgr.getLocForStartOfFile(FID);
- SrcMgr::CharacteristicKind FileType =
- SourceMgr.getFileCharacteristic(EnterLoc);
- Callbacks->FileChanged(EnterLoc, PPCallbacks::EnterFile, FileType);
- }
-}
-
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer.
void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
@@ -304,20 +271,21 @@ void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
const DirectoryEntry *Dir = Mod.getUmbrellaDir().Entry;
- vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
std::error_code EC;
- for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End;
+ for (llvm::vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC),
+ End;
Entry != End && !EC; Entry.increment(EC)) {
using llvm::StringSwitch;
// Check whether this entry has an extension typically associated with
// headers.
- if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->getName()))
+ if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
.Cases(".h", ".H", ".hh", ".hpp", true)
.Default(false))
continue;
- if (const FileEntry *Header = getFileManager().getFile(Entry->getName()))
+ if (const FileEntry *Header = getFileManager().getFile(Entry->path()))
if (!getSourceManager().hasFileInfo(Header)) {
if (!ModMap.isHeaderInUnavailableModule(Header)) {
// Find the relative path that would access this header.
@@ -339,7 +307,6 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
// If we have an unclosed module region from a pragma at the end of a
// module, complain and close it now.
- // FIXME: This is not correct if we are building a module from PTH.
const bool LeavingSubmodule = CurLexer && CurLexerSubmodule;
if ((LeavingSubmodule || IncludeMacroStack.empty()) &&
!BuildingSubmoduleStack.empty() &&
@@ -436,15 +403,10 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
if (isCodeCompletionEnabled() && CurPPLexer &&
SourceMgr.getLocForStartOfFile(CurPPLexer->getFileID()) ==
CodeCompletionFileLoc) {
- if (CurLexer) {
- Result.startToken();
- CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
- CurLexer.reset();
- } else {
- assert(CurPTHLexer && "Got EOF but no current lexer set!");
- CurPTHLexer->getEOF(Result);
- CurPTHLexer.reset();
- }
+ assert(CurLexer && "Got EOF but no current lexer set!");
+ Result.startToken();
+ CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
+ CurLexer.reset();
CurPPLexer = nullptr;
recomputeCurLexerKind();
@@ -522,39 +484,34 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
}
// If this is the end of the main file, form an EOF token.
- if (CurLexer) {
- const char *EndPos = getCurLexerEndPos();
- Result.startToken();
- CurLexer->BufferPtr = EndPos;
- CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
-
- if (isCodeCompletionEnabled()) {
- // Inserting the code-completion point increases the source buffer by 1,
- // but the main FileID was created before inserting the point.
- // Compensate by reducing the EOF location by 1, otherwise the location
- // will point to the next FileID.
- // FIXME: This is hacky, the code-completion point should probably be
- // inserted before the main FileID is created.
- if (CurLexer->getFileLoc() == CodeCompletionFileLoc)
- Result.setLocation(Result.getLocation().getLocWithOffset(-1));
- }
-
- if (creatingPCHWithThroughHeader() && !LeavingPCHThroughHeader) {
- // Reached the end of the compilation without finding the through header.
- Diag(CurLexer->getFileLoc(), diag::err_pp_through_header_not_seen)
- << PPOpts->PCHThroughHeader << 0;
- }
+ assert(CurLexer && "Got EOF but no current lexer set!");
+ const char *EndPos = getCurLexerEndPos();
+ Result.startToken();
+ CurLexer->BufferPtr = EndPos;
+ CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
+
+ if (isCodeCompletionEnabled()) {
+ // Inserting the code-completion point increases the source buffer by 1,
+ // but the main FileID was created before inserting the point.
+ // Compensate by reducing the EOF location by 1, otherwise the location
+ // will point to the next FileID.
+ // FIXME: This is hacky, the code-completion point should probably be
+ // inserted before the main FileID is created.
+ if (CurLexer->getFileLoc() == CodeCompletionFileLoc)
+ Result.setLocation(Result.getLocation().getLocWithOffset(-1));
+ }
- if (!isIncrementalProcessingEnabled())
- // We're done with lexing.
- CurLexer.reset();
- } else {
- assert(CurPTHLexer && "Got EOF but no current lexer set!");
- CurPTHLexer->getEOF(Result);
- CurPTHLexer.reset();
+ if (creatingPCHWithThroughHeader() && !LeavingPCHThroughHeader) {
+ // Reached the end of the compilation without finding the through header.
+ Diag(CurLexer->getFileLoc(), diag::err_pp_through_header_not_seen)
+ << PPOpts->PCHThroughHeader << 0;
}
if (!isIncrementalProcessingEnabled())
+ // We're done with lexing.
+ CurLexer.reset();
+
+ if (!isIncrementalProcessingEnabled())
CurPPLexer = nullptr;
if (TUKind == TU_Complete) {
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 346dd947c028..c70ff46ec904 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -23,12 +23,12 @@
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorLexer.h"
-#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -428,8 +428,6 @@ bool Preprocessor::isNextPPTokenLParen() {
unsigned Val;
if (CurLexer)
Val = CurLexer->isNextPPTokenLParen();
- else if (CurPTHLexer)
- Val = CurPTHLexer->isNextPPTokenLParen();
else
Val = CurTokenLexer->isNextTokenLParen();
@@ -442,8 +440,6 @@ bool Preprocessor::isNextPPTokenLParen() {
for (const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {
if (Entry.TheLexer)
Val = Entry.TheLexer->isNextPPTokenLParen();
- else if (Entry.ThePTHLexer)
- Val = Entry.ThePTHLexer->isNextPPTokenLParen();
else
Val = Entry.TheTokenLexer->isNextTokenLParen();
@@ -1242,6 +1238,13 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile,
CurDir, nullptr, nullptr, nullptr, nullptr);
+ if (PPCallbacks *Callbacks = PP.getPPCallbacks()) {
+ SrcMgr::CharacteristicKind FileType = SrcMgr::C_User;
+ if (File)
+ FileType = PP.getHeaderSearchInfo().getFileDirFlavor(File);
+ Callbacks->HasInclude(FilenameLoc, Filename, isAngled, File, FileType);
+ }
+
// Get the result value. A result of true means the file exists.
return File != nullptr;
}
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
deleted file mode 100644
index 45cff56dcaa1..000000000000
--- a/lib/Lex/PTHLexer.cpp
+++ /dev/null
@@ -1,748 +0,0 @@
-//===- PTHLexer.cpp - Lex from a token stream -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the PTHLexer interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Lex/PTHLexer.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemStatCache.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TokenKinds.h"
-#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Lex/PTHManager.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/Token.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/DJB.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/OnDiskHashTable.h"
-#include <cassert>
-#include <cstdint>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <memory>
-#include <utility>
-
-using namespace clang;
-
-static const unsigned StoredTokenSize = 1 + 1 + 2 + 4 + 4;
-
-//===----------------------------------------------------------------------===//
-// PTHLexer methods.
-//===----------------------------------------------------------------------===//
-
-PTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const unsigned char *D,
- const unsigned char *ppcond, PTHManager &PM)
- : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), PPCond(ppcond),
- CurPPCondPtr(ppcond), PTHMgr(PM) {
- FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID);
-}
-
-bool PTHLexer::Lex(Token& Tok) {
- //===--------------------------------------==//
- // Read the raw token data.
- //===--------------------------------------==//
- using namespace llvm::support;
-
- // Shadow CurPtr into an automatic variable.
- const unsigned char *CurPtrShadow = CurPtr;
-
- // Read in the data for the token.
- unsigned Word0 = endian::readNext<uint32_t, little, aligned>(CurPtrShadow);
- uint32_t IdentifierID =
- endian::readNext<uint32_t, little, aligned>(CurPtrShadow);
- uint32_t FileOffset =
- endian::readNext<uint32_t, little, aligned>(CurPtrShadow);
-
- tok::TokenKind TKind = (tok::TokenKind) (Word0 & 0xFF);
- Token::TokenFlags TFlags = (Token::TokenFlags) ((Word0 >> 8) & 0xFF);
- uint32_t Len = Word0 >> 16;
-
- CurPtr = CurPtrShadow;
-
- //===--------------------------------------==//
- // Construct the token itself.
- //===--------------------------------------==//
-
- Tok.startToken();
- Tok.setKind(TKind);
- Tok.setFlag(TFlags);
- assert(!LexingRawMode);
- Tok.setLocation(FileStartLoc.getLocWithOffset(FileOffset));
- Tok.setLength(Len);
-
- // Handle identifiers.
- if (Tok.isLiteral()) {
- Tok.setLiteralData((const char*) (PTHMgr.SpellingBase + IdentifierID));
- }
- else if (IdentifierID) {
- MIOpt.ReadToken();
- IdentifierInfo *II = PTHMgr.GetIdentifierInfo(IdentifierID-1);
-
- Tok.setIdentifierInfo(II);
-
- // Change the kind of this identifier to the appropriate token kind, e.g.
- // turning "for" into a keyword.
- Tok.setKind(II->getTokenID());
-
- if (II->isHandleIdentifierCase())
- return PP->HandleIdentifier(Tok);
-
- return true;
- }
-
- //===--------------------------------------==//
- // Process the token.
- //===--------------------------------------==//
- if (TKind == tok::eof) {
- // Save the end-of-file token.
- EofToken = Tok;
-
- assert(!ParsingPreprocessorDirective);
- assert(!LexingRawMode);
-
- return LexEndOfFile(Tok);
- }
-
- if (TKind == tok::hash && Tok.isAtStartOfLine()) {
- LastHashTokPtr = CurPtr - StoredTokenSize;
- assert(!LexingRawMode);
- PP->HandleDirective(Tok);
-
- return false;
- }
-
- if (TKind == tok::eod) {
- assert(ParsingPreprocessorDirective);
- ParsingPreprocessorDirective = false;
- return true;
- }
-
- MIOpt.ReadToken();
- return true;
-}
-
-bool PTHLexer::LexEndOfFile(Token &Result) {
- // If we hit the end of the file while parsing a preprocessor directive,
- // end the preprocessor directive first. The next token returned will
- // then be the end of file.
- if (ParsingPreprocessorDirective) {
- ParsingPreprocessorDirective = false; // Done parsing the "line".
- return true; // Have a token.
- }
-
- assert(!LexingRawMode);
-
- // If we are in a #if directive, emit an error.
- while (!ConditionalStack.empty()) {
- if (PP->getCodeCompletionFileLoc() != FileStartLoc)
- PP->Diag(ConditionalStack.back().IfLoc,
- diag::err_pp_unterminated_conditional);
- ConditionalStack.pop_back();
- }
-
- // Finally, let the preprocessor handle this.
- return PP->HandleEndOfFile(Result);
-}
-
-// FIXME: We can just grab the last token instead of storing a copy
-// into EofToken.
-void PTHLexer::getEOF(Token& Tok) {
- assert(EofToken.is(tok::eof));
- Tok = EofToken;
-}
-
-void PTHLexer::DiscardToEndOfLine() {
- assert(ParsingPreprocessorDirective && ParsingFilename == false &&
- "Must be in a preprocessing directive!");
-
- // We assume that if the preprocessor wishes to discard to the end of
- // the line that it also means to end the current preprocessor directive.
- ParsingPreprocessorDirective = false;
-
- // Skip tokens by only peeking at their token kind and the flags.
- // We don't need to actually reconstruct full tokens from the token buffer.
- // This saves some copies and it also reduces IdentifierInfo* lookup.
- const unsigned char* p = CurPtr;
- while (true) {
- // Read the token kind. Are we at the end of the file?
- tok::TokenKind x = (tok::TokenKind) (uint8_t) *p;
- if (x == tok::eof) break;
-
- // Read the token flags. Are we at the start of the next line?
- Token::TokenFlags y = (Token::TokenFlags) (uint8_t) p[1];
- if (y & Token::StartOfLine) break;
-
- // Skip to the next token.
- p += StoredTokenSize;
- }
-
- CurPtr = p;
-}
-
-/// SkipBlock - Used by Preprocessor to skip the current conditional block.
-bool PTHLexer::SkipBlock() {
- using namespace llvm::support;
-
- assert(CurPPCondPtr && "No cached PP conditional information.");
- assert(LastHashTokPtr && "No known '#' token.");
-
- const unsigned char *HashEntryI = nullptr;
- uint32_t TableIdx;
-
- do {
- // Read the token offset from the side-table.
- uint32_t Offset = endian::readNext<uint32_t, little, aligned>(CurPPCondPtr);
-
- // Read the target table index from the side-table.
- TableIdx = endian::readNext<uint32_t, little, aligned>(CurPPCondPtr);
-
- // Compute the actual memory address of the '#' token data for this entry.
- HashEntryI = TokBuf + Offset;
-
- // Optimization: "Sibling jumping". #if...#else...#endif blocks can
- // contain nested blocks. In the side-table we can jump over these
- // nested blocks instead of doing a linear search if the next "sibling"
- // entry is not at a location greater than LastHashTokPtr.
- if (HashEntryI < LastHashTokPtr && TableIdx) {
- // In the side-table we are still at an entry for a '#' token that
- // is earlier than the last one we saw. Check if the location we would
- // stride gets us closer.
- const unsigned char* NextPPCondPtr =
- PPCond + TableIdx*(sizeof(uint32_t)*2);
- assert(NextPPCondPtr >= CurPPCondPtr);
- // Read where we should jump to.
- const unsigned char *HashEntryJ =
- TokBuf + endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
-
- if (HashEntryJ <= LastHashTokPtr) {
- // Jump directly to the next entry in the side table.
- HashEntryI = HashEntryJ;
- TableIdx = endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
- CurPPCondPtr = NextPPCondPtr;
- }
- }
- }
- while (HashEntryI < LastHashTokPtr);
- assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'");
- assert(TableIdx && "No jumping from #endifs.");
-
- // Update our side-table iterator.
- const unsigned char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2);
- assert(NextPPCondPtr >= CurPPCondPtr);
- CurPPCondPtr = NextPPCondPtr;
-
- // Read where we should jump to.
- HashEntryI =
- TokBuf + endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
- uint32_t NextIdx = endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
-
- // By construction NextIdx will be zero if this is a #endif. This is useful
- // to know to obviate lexing another token.
- bool isEndif = NextIdx == 0;
-
- // This case can occur when we see something like this:
- //
- // #if ...
- // /* a comment or nothing */
- // #elif
- //
- // If we are skipping the first #if block it will be the case that CurPtr
- // already points 'elif'. Just return.
-
- if (CurPtr > HashEntryI) {
- assert(CurPtr == HashEntryI + StoredTokenSize);
- // Did we reach a #endif? If so, go ahead and consume that token as well.
- if (isEndif)
- CurPtr += StoredTokenSize * 2;
- else
- LastHashTokPtr = HashEntryI;
-
- return isEndif;
- }
-
- // Otherwise, we need to advance. Update CurPtr to point to the '#' token.
- CurPtr = HashEntryI;
-
- // Update the location of the last observed '#'. This is useful if we
- // are skipping multiple blocks.
- LastHashTokPtr = CurPtr;
-
- // Skip the '#' token.
- assert(((tok::TokenKind)*CurPtr) == tok::hash);
- CurPtr += StoredTokenSize;
-
- // Did we reach a #endif? If so, go ahead and consume that token as well.
- if (isEndif) {
- CurPtr += StoredTokenSize * 2;
- }
-
- return isEndif;
-}
-
-SourceLocation PTHLexer::getSourceLocation() {
- // getSourceLocation is not on the hot path. It is used to get the location
- // of the next token when transitioning back to this lexer when done
- // handling a #included file. Just read the necessary data from the token
- // data buffer to construct the SourceLocation object.
- // NOTE: This is a virtual function; hence it is defined out-of-line.
- using namespace llvm::support;
-
- const unsigned char *OffsetPtr = CurPtr + (StoredTokenSize - 4);
- uint32_t Offset = endian::readNext<uint32_t, little, aligned>(OffsetPtr);
- return FileStartLoc.getLocWithOffset(Offset);
-}
-
-//===----------------------------------------------------------------------===//
-// PTH file lookup: map from strings to file data.
-//===----------------------------------------------------------------------===//
-
-/// PTHFileLookup - This internal data structure is used by the PTHManager
-/// to map from FileEntry objects managed by FileManager to offsets within
-/// the PTH file.
-namespace {
-
-class PTHFileData {
- const uint32_t TokenOff;
- const uint32_t PPCondOff;
-
-public:
- PTHFileData(uint32_t tokenOff, uint32_t ppCondOff)
- : TokenOff(tokenOff), PPCondOff(ppCondOff) {}
-
- uint32_t getTokenOffset() const { return TokenOff; }
- uint32_t getPPCondOffset() const { return PPCondOff; }
-};
-
-class PTHFileLookupCommonTrait {
-public:
- using internal_key_type = std::pair<unsigned char, StringRef>;
- using hash_value_type = unsigned;
- using offset_type = unsigned;
-
- static hash_value_type ComputeHash(internal_key_type x) {
- return llvm::djbHash(x.second);
- }
-
- static std::pair<unsigned, unsigned>
- ReadKeyDataLength(const unsigned char*& d) {
- using namespace llvm::support;
-
- unsigned keyLen =
- (unsigned)endian::readNext<uint16_t, little, unaligned>(d);
- unsigned dataLen = (unsigned) *(d++);
- return std::make_pair(keyLen, dataLen);
- }
-
- static internal_key_type ReadKey(const unsigned char* d, unsigned) {
- unsigned char k = *(d++); // Read the entry kind.
- return std::make_pair(k, (const char*) d);
- }
-};
-
-} // namespace
-
-class PTHManager::PTHFileLookupTrait : public PTHFileLookupCommonTrait {
-public:
- using external_key_type = const FileEntry *;
- using data_type = PTHFileData;
-
- static internal_key_type GetInternalKey(const FileEntry* FE) {
- return std::make_pair((unsigned char) 0x1, FE->getName());
- }
-
- static bool EqualKey(internal_key_type a, internal_key_type b) {
- return a.first == b.first && a.second == b.second;
- }
-
- static PTHFileData ReadData(const internal_key_type& k,
- const unsigned char* d, unsigned) {
- using namespace llvm::support;
-
- assert(k.first == 0x1 && "Only file lookups can match!");
- uint32_t x = endian::readNext<uint32_t, little, unaligned>(d);
- uint32_t y = endian::readNext<uint32_t, little, unaligned>(d);
- return PTHFileData(x, y);
- }
-};
-
-class PTHManager::PTHStringLookupTrait {
-public:
- using data_type = uint32_t;
- using external_key_type = const std::pair<const char *, unsigned>;
- using internal_key_type = external_key_type;
- using hash_value_type = uint32_t;
- using offset_type = unsigned;
-
- static bool EqualKey(const internal_key_type& a,
- const internal_key_type& b) {
- return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
- : false;
- }
-
- static hash_value_type ComputeHash(const internal_key_type& a) {
- return llvm::djbHash(StringRef(a.first, a.second));
- }
-
- // This hopefully will just get inlined and removed by the optimizer.
- static const internal_key_type&
- GetInternalKey(const external_key_type& x) { return x; }
-
- static std::pair<unsigned, unsigned>
- ReadKeyDataLength(const unsigned char*& d) {
- using namespace llvm::support;
-
- return std::make_pair(
- (unsigned)endian::readNext<uint16_t, little, unaligned>(d),
- sizeof(uint32_t));
- }
-
- static std::pair<const char*, unsigned>
- ReadKey(const unsigned char* d, unsigned n) {
- assert(n >= 2 && d[n-1] == '\0');
- return std::make_pair((const char*) d, n-1);
- }
-
- static uint32_t ReadData(const internal_key_type& k, const unsigned char* d,
- unsigned) {
- using namespace llvm::support;
-
- return endian::readNext<uint32_t, little, unaligned>(d);
- }
-};
-
-//===----------------------------------------------------------------------===//
-// PTHManager methods.
-//===----------------------------------------------------------------------===//
-
-PTHManager::PTHManager(
- std::unique_ptr<const llvm::MemoryBuffer> buf,
- std::unique_ptr<PTHFileLookup> fileLookup, const unsigned char *idDataTable,
- std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> perIDCache,
- std::unique_ptr<PTHStringIdLookup> stringIdLookup, unsigned numIds,
- const unsigned char *spellingBase, const char *originalSourceFile)
- : Buf(std::move(buf)), PerIDCache(std::move(perIDCache)),
- FileLookup(std::move(fileLookup)), IdDataTable(idDataTable),
- StringIdLookup(std::move(stringIdLookup)), NumIds(numIds),
- SpellingBase(spellingBase), OriginalSourceFile(originalSourceFile) {}
-
-PTHManager::~PTHManager() = default;
-
-static void InvalidPTH(DiagnosticsEngine &Diags, const char *Msg) {
- Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) << Msg;
-}
-
-PTHManager *PTHManager::Create(StringRef file, DiagnosticsEngine &Diags) {
- // Memory map the PTH file.
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
- llvm::MemoryBuffer::getFile(file);
-
- if (!FileOrErr) {
- // FIXME: Add ec.message() to this diag.
- Diags.Report(diag::err_invalid_pth_file) << file;
- return nullptr;
- }
- std::unique_ptr<llvm::MemoryBuffer> File = std::move(FileOrErr.get());
-
- using namespace llvm::support;
-
- // Get the buffer ranges and check if there are at least three 32-bit
- // words at the end of the file.
- const unsigned char *BufBeg = (const unsigned char*)File->getBufferStart();
- const unsigned char *BufEnd = (const unsigned char*)File->getBufferEnd();
-
- // Check the prologue of the file.
- if ((BufEnd - BufBeg) < (signed)(sizeof("cfe-pth") + 4 + 4) ||
- memcmp(BufBeg, "cfe-pth", sizeof("cfe-pth")) != 0) {
- Diags.Report(diag::err_invalid_pth_file) << file;
- return nullptr;
- }
-
- // Read the PTH version.
- const unsigned char *p = BufBeg + (sizeof("cfe-pth"));
- unsigned Version = endian::readNext<uint32_t, little, aligned>(p);
-
- if (Version < PTHManager::Version) {
- InvalidPTH(Diags,
- Version < PTHManager::Version
- ? "PTH file uses an older PTH format that is no longer supported"
- : "PTH file uses a newer PTH format that cannot be read");
- return nullptr;
- }
-
- // Compute the address of the index table at the end of the PTH file.
- const unsigned char *PrologueOffset = p;
-
- if (PrologueOffset >= BufEnd) {
- Diags.Report(diag::err_invalid_pth_file) << file;
- return nullptr;
- }
-
- // Construct the file lookup table. This will be used for mapping from
- // FileEntry*'s to cached tokens.
- const unsigned char* FileTableOffset = PrologueOffset + sizeof(uint32_t)*2;
- const unsigned char *FileTable =
- BufBeg + endian::readNext<uint32_t, little, aligned>(FileTableOffset);
-
- if (!(FileTable > BufBeg && FileTable < BufEnd)) {
- Diags.Report(diag::err_invalid_pth_file) << file;
- return nullptr; // FIXME: Proper error diagnostic?
- }
-
- std::unique_ptr<PTHFileLookup> FL(PTHFileLookup::Create(FileTable, BufBeg));
-
- // Warn if the PTH file is empty. We still want to create a PTHManager
- // as the PTH could be used with -include-pth.
- if (FL->isEmpty())
- InvalidPTH(Diags, "PTH file contains no cached source data");
-
- // Get the location of the table mapping from persistent ids to the
- // data needed to reconstruct identifiers.
- const unsigned char* IDTableOffset = PrologueOffset + sizeof(uint32_t)*0;
- const unsigned char *IData =
- BufBeg + endian::readNext<uint32_t, little, aligned>(IDTableOffset);
-
- if (!(IData >= BufBeg && IData < BufEnd)) {
- Diags.Report(diag::err_invalid_pth_file) << file;
- return nullptr;
- }
-
- // Get the location of the hashtable mapping between strings and
- // persistent IDs.
- const unsigned char* StringIdTableOffset = PrologueOffset + sizeof(uint32_t)*1;
- const unsigned char *StringIdTable =
- BufBeg + endian::readNext<uint32_t, little, aligned>(StringIdTableOffset);
- if (!(StringIdTable >= BufBeg && StringIdTable < BufEnd)) {
- Diags.Report(diag::err_invalid_pth_file) << file;
- return nullptr;
- }
-
- std::unique_ptr<PTHStringIdLookup> SL(
- PTHStringIdLookup::Create(StringIdTable, BufBeg));
-
- // Get the location of the spelling cache.
- const unsigned char* spellingBaseOffset = PrologueOffset + sizeof(uint32_t)*3;
- const unsigned char *spellingBase =
- BufBeg + endian::readNext<uint32_t, little, aligned>(spellingBaseOffset);
- if (!(spellingBase >= BufBeg && spellingBase < BufEnd)) {
- Diags.Report(diag::err_invalid_pth_file) << file;
- return nullptr;
- }
-
- // Get the number of IdentifierInfos and pre-allocate the identifier cache.
- uint32_t NumIds = endian::readNext<uint32_t, little, aligned>(IData);
-
- // Pre-allocate the persistent ID -> IdentifierInfo* cache. We use calloc()
- // so that we in the best case only zero out memory once when the OS returns
- // us new pages.
- std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> PerIDCache;
-
- if (NumIds) {
- PerIDCache.reset((IdentifierInfo **)calloc(NumIds, sizeof(PerIDCache[0])));
- if (!PerIDCache) {
- InvalidPTH(Diags, "Could not allocate memory for processing PTH file");
- return nullptr;
- }
- }
-
- // Compute the address of the original source file.
- const unsigned char* originalSourceBase = PrologueOffset + sizeof(uint32_t)*4;
- unsigned len =
- endian::readNext<uint16_t, little, unaligned>(originalSourceBase);
- if (!len) originalSourceBase = nullptr;
-
- // Create the new PTHManager.
- return new PTHManager(std::move(File), std::move(FL), IData,
- std::move(PerIDCache), std::move(SL), NumIds,
- spellingBase, (const char *)originalSourceBase);
-}
-
-IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
- using namespace llvm::support;
-
- // Look in the PTH file for the string data for the IdentifierInfo object.
- const unsigned char* TableEntry = IdDataTable + sizeof(uint32_t)*PersistentID;
- const unsigned char *IDData =
- (const unsigned char *)Buf->getBufferStart() +
- endian::readNext<uint32_t, little, aligned>(TableEntry);
- assert(IDData < (const unsigned char*)Buf->getBufferEnd());
-
- // Allocate the object.
- std::pair<IdentifierInfo,const unsigned char*> *Mem =
- Alloc.Allocate<std::pair<IdentifierInfo, const unsigned char *>>();
-
- Mem->second = IDData;
- assert(IDData[0] != '\0');
- IdentifierInfo *II = new ((void*) Mem) IdentifierInfo();
-
- // Store the new IdentifierInfo in the cache.
- PerIDCache[PersistentID] = II;
- assert(II->getNameStart() && II->getNameStart()[0] != '\0');
- return II;
-}
-
-IdentifierInfo* PTHManager::get(StringRef Name) {
- // Double check our assumption that the last character isn't '\0'.
- assert(Name.empty() || Name.back() != '\0');
- PTHStringIdLookup::iterator I =
- StringIdLookup->find(std::make_pair(Name.data(), Name.size()));
- if (I == StringIdLookup->end()) // No identifier found?
- return nullptr;
-
- // Match found. Return the identifier!
- assert(*I > 0);
- return GetIdentifierInfo(*I-1);
-}
-
-PTHLexer *PTHManager::CreateLexer(FileID FID) {
- const FileEntry *FE = PP->getSourceManager().getFileEntryForID(FID);
- if (!FE)
- return nullptr;
-
- using namespace llvm::support;
-
- // Lookup the FileEntry object in our file lookup data structure. It will
- // return a variant that indicates whether or not there is an offset within
- // the PTH file that contains cached tokens.
- PTHFileLookup::iterator I = FileLookup->find(FE);
-
- if (I == FileLookup->end()) // No tokens available?
- return nullptr;
-
- const PTHFileData& FileData = *I;
-
- const unsigned char *BufStart = (const unsigned char *)Buf->getBufferStart();
- // Compute the offset of the token data within the buffer.
- const unsigned char* data = BufStart + FileData.getTokenOffset();
-
- // Get the location of pp-conditional table.
- const unsigned char* ppcond = BufStart + FileData.getPPCondOffset();
- uint32_t Len = endian::readNext<uint32_t, little, aligned>(ppcond);
- if (Len == 0) ppcond = nullptr;
-
- assert(PP && "No preprocessor set yet!");
- return new PTHLexer(*PP, FID, data, ppcond, *this);
-}
-
-//===----------------------------------------------------------------------===//
-// 'stat' caching.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class PTHStatData {
-public:
- uint64_t Size;
- time_t ModTime;
- llvm::sys::fs::UniqueID UniqueID;
- const bool HasData = false;
- bool IsDirectory;
-
- PTHStatData() = default;
- PTHStatData(uint64_t Size, time_t ModTime, llvm::sys::fs::UniqueID UniqueID,
- bool IsDirectory)
- : Size(Size), ModTime(ModTime), UniqueID(UniqueID), HasData(true),
- IsDirectory(IsDirectory) {}
-};
-
-class PTHStatLookupTrait : public PTHFileLookupCommonTrait {
-public:
- using external_key_type = StringRef; // const char*
- using data_type = PTHStatData;
-
- static internal_key_type GetInternalKey(StringRef path) {
- // The key 'kind' doesn't matter here because it is ignored in EqualKey.
- return std::make_pair((unsigned char) 0x0, path);
- }
-
- static bool EqualKey(internal_key_type a, internal_key_type b) {
- // When doing 'stat' lookups we don't care about the kind of 'a' and 'b',
- // just the paths.
- return a.second == b.second;
- }
-
- static data_type ReadData(const internal_key_type& k, const unsigned char* d,
- unsigned) {
- if (k.first /* File or Directory */) {
- bool IsDirectory = true;
- if (k.first == 0x1 /* File */) {
- IsDirectory = false;
- d += 4 * 2; // Skip the first 2 words.
- }
-
- using namespace llvm::support;
-
- uint64_t File = endian::readNext<uint64_t, little, unaligned>(d);
- uint64_t Device = endian::readNext<uint64_t, little, unaligned>(d);
- llvm::sys::fs::UniqueID UniqueID(Device, File);
- time_t ModTime = endian::readNext<uint64_t, little, unaligned>(d);
- uint64_t Size = endian::readNext<uint64_t, little, unaligned>(d);
- return data_type(Size, ModTime, UniqueID, IsDirectory);
- }
-
- // Negative stat. Don't read anything.
- return data_type();
- }
-};
-
-} // namespace
-
-namespace clang {
-
-class PTHStatCache : public FileSystemStatCache {
- using CacheTy = llvm::OnDiskChainedHashTable<PTHStatLookupTrait>;
-
- CacheTy Cache;
-
-public:
- PTHStatCache(PTHManager::PTHFileLookup &FL)
- : Cache(FL.getNumBuckets(), FL.getNumEntries(), FL.getBuckets(),
- FL.getBase()) {}
-
- LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F,
- vfs::FileSystem &FS) override {
- // Do the lookup for the file's data in the PTH file.
- CacheTy::iterator I = Cache.find(Path);
-
- // If we don't get a hit in the PTH file just forward to 'stat'.
- if (I == Cache.end())
- return statChained(Path, Data, isFile, F, FS);
-
- const PTHStatData &D = *I;
-
- if (!D.HasData)
- return CacheMissing;
-
- Data.Name = Path;
- Data.Size = D.Size;
- Data.ModTime = D.ModTime;
- Data.UniqueID = D.UniqueID;
- Data.IsDirectory = D.IsDirectory;
- Data.IsNamedPipe = false;
- Data.InPCH = true;
-
- return CacheExists;
- }
-};
-
-} // namespace clang
-
-std::unique_ptr<FileSystemStatCache> PTHManager::createStatCache() {
- return llvm::make_unique<PTHStatCache>(*FileLookup);
-}
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 37c0a23646c5..575935119f6f 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -31,7 +31,6 @@
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorLexer.h"
-#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
@@ -404,10 +403,7 @@ void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
void Preprocessor::HandlePragmaMark() {
assert(CurPPLexer && "No current lexer?");
- if (CurLexer)
- CurLexer->ReadToEndOfLine();
- else
- CurPTHLexer->DiscardToEndOfLine();
+ CurLexer->ReadToEndOfLine();
}
/// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'.
@@ -810,12 +806,6 @@ void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
DiscardUntilEndOfDirective();
}
- if (CurPTHLexer) {
- // FIXME: Support this somehow?
- Diag(Loc, diag::err_pp_module_build_pth);
- return;
- }
-
CurLexer->LexingRawMode = true;
auto TryConsumeIdentifier = [&](StringRef Ident) -> bool {
@@ -876,6 +866,37 @@ void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
StringRef(Start, End - Start));
}
+void Preprocessor::HandlePragmaHdrstop(Token &Tok) {
+ Lex(Tok);
+ if (Tok.is(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::warn_pp_hdrstop_filename_ignored);
+
+ std::string FileName;
+ if (!LexStringLiteral(Tok, FileName, "pragma hdrstop", false))
+ return;
+
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected) << tok::r_paren;
+ return;
+ }
+ Lex(Tok);
+ }
+ if (Tok.isNot(tok::eod))
+ Diag(Tok.getLocation(), diag::ext_pp_extra_tokens_at_eol)
+ << "pragma hdrstop";
+
+ if (creatingPCHWithPragmaHdrStop() &&
+ SourceMgr.isInMainFile(Tok.getLocation())) {
+ assert(CurLexer && "no lexer for #pragma hdrstop processing");
+ Token &Result = Tok;
+ Result.startToken();
+ CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
+ CurLexer->cutOffLexing();
+ }
+ if (usingPCHWithPragmaHdrStop())
+ SkippingUntilPragmaHdrStop = false;
+}
+
/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
/// If 'Namespace' is non-null, then it is a token required to exist on the
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
@@ -1099,10 +1120,6 @@ struct PragmaDebugHandler : public PragmaHandler {
}
void HandleCaptured(Preprocessor &PP) {
- // Skip if emitting preprocessed output.
- if (PP.isPreprocessedOutput())
- return;
-
Token Tok;
PP.LexUnexpandedToken(Tok);
@@ -1220,6 +1237,15 @@ public:
}
};
+/// "\#pragma hdrstop [<header-name-string>]"
+struct PragmaHdrstopHandler : public PragmaHandler {
+ PragmaHdrstopHandler() : PragmaHandler("hdrstop") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &DepToken) override {
+ PP.HandlePragmaHdrstop(DepToken);
+ }
+};
+
/// "\#pragma warning(...)". MSVC's diagnostics do not map cleanly to clang's
/// diagnostics, so we don't really implement this pragma. We parse it and
/// ignore it to avoid -Wunknown-pragma warnings.
@@ -1799,6 +1825,7 @@ void Preprocessor::RegisterBuiltinPragmas() {
if (LangOpts.MicrosoftExt) {
AddPragmaHandler(new PragmaWarningHandler());
AddPragmaHandler(new PragmaIncludeAliasHandler());
+ AddPragmaHandler(new PragmaHdrstopHandler());
}
// Pragmas added by plugins
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index def47b2f1095..047a4caaca73 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -44,8 +44,6 @@
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h"
-#include "clang/Lex/PTHLexer.h"
-#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Pragma.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/PreprocessorLexer.h"
@@ -149,6 +147,10 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
Ident_AbnormalTermination = nullptr;
}
+ // If using a PCH where a #pragma hdrstop is expected, start skipping tokens.
+ if (usingPCHWithPragmaHdrStop())
+ SkippingUntilPragmaHdrStop = true;
+
// If using a PCH with a through header, start skipping tokens.
if (!this->PPOpts->PCHThroughHeader.empty() &&
!this->PPOpts->ImplicitPCHInclude.empty())
@@ -220,11 +222,6 @@ void Preprocessor::FinalizeForModelFile() {
PragmaHandlers = std::move(PragmaHandlersBackup);
}
-void Preprocessor::setPTHManager(PTHManager* pm) {
- PTH.reset(pm);
- FileMgr.addStatCache(PTH->createStatCache());
-}
-
void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
llvm::errs() << tok::getTokenName(Tok.getKind()) << " '"
<< getSpelling(Tok) << "'";
@@ -250,7 +247,7 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
}
void Preprocessor::DumpLocation(SourceLocation Loc) const {
- Loc.dump(SourceMgr);
+ Loc.print(llvm::errs(), SourceMgr);
}
void Preprocessor::DumpMacro(const MacroInfo &MI) const {
@@ -375,8 +372,6 @@ StringRef Preprocessor::getLastMacroWithSpelling(
void Preprocessor::recomputeCurLexerKind() {
if (CurLexer)
CurLexerKind = CLK_Lexer;
- else if (CurPTHLexer)
- CurLexerKind = CLK_PTHLexer;
else if (CurTokenLexer)
CurLexerKind = CLK_TokenLexer;
else
@@ -441,6 +436,13 @@ bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
return false;
}
+void Preprocessor::CodeCompleteIncludedFile(llvm::StringRef Dir,
+ bool IsAngled) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteIncludedFile(Dir, IsAngled);
+ setCodeCompletionReached();
+}
+
void Preprocessor::CodeCompleteNaturalLanguage() {
if (CodeComplete)
CodeComplete->CodeCompleteNaturalLanguage();
@@ -576,8 +578,9 @@ void Preprocessor::EnterMainSourceFile() {
}
// Skip tokens from the Predefines and if needed the main file.
- if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader)
- SkipTokensUntilPCHThroughHeader();
+ if ((usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) ||
+ (usingPCHWithPragmaHdrStop() && SkippingUntilPragmaHdrStop))
+ SkipTokensWhileUsingPCH();
}
void Preprocessor::setPCHThroughHeaderFileID(FileID FID) {
@@ -602,12 +605,23 @@ bool Preprocessor::usingPCHWithThroughHeader() {
PCHThroughHeaderFileID.isValid();
}
-/// Skip tokens until after the #include of the through header.
-/// Tokens in the predefines file and the main file may be skipped. If the end
-/// of the predefines file is reached, skipping continues into the main file.
-/// If the end of the main file is reached, it's a fatal error.
-void Preprocessor::SkipTokensUntilPCHThroughHeader() {
+bool Preprocessor::creatingPCHWithPragmaHdrStop() {
+ return TUKind == TU_Prefix && PPOpts->PCHWithHdrStop;
+}
+
+bool Preprocessor::usingPCHWithPragmaHdrStop() {
+ return TUKind != TU_Prefix && PPOpts->PCHWithHdrStop;
+}
+
+/// Skip tokens until after the #include of the through header or
+/// until after a #pragma hdrstop is seen. Tokens in the predefines file
+/// and the main file may be skipped. If the end of the predefines file
+/// is reached, skipping continues into the main file. If the end of the
+/// main file is reached, it's a fatal error.
+void Preprocessor::SkipTokensWhileUsingPCH() {
bool ReachedMainFileEOF = false;
+ bool UsingPCHThroughHeader = SkippingUntilPCHThroughHeader;
+ bool UsingPragmaHdrStop = SkippingUntilPragmaHdrStop;
Token Tok;
while (true) {
bool InPredefines = (CurLexer->getFileID() == getPredefinesFileID());
@@ -616,12 +630,18 @@ void Preprocessor::SkipTokensUntilPCHThroughHeader() {
ReachedMainFileEOF = true;
break;
}
- if (!SkippingUntilPCHThroughHeader)
+ if (UsingPCHThroughHeader && !SkippingUntilPCHThroughHeader)
break;
+ if (UsingPragmaHdrStop && !SkippingUntilPragmaHdrStop)
+ break;
+ }
+ if (ReachedMainFileEOF) {
+ if (UsingPCHThroughHeader)
+ Diag(SourceLocation(), diag::err_pp_through_header_not_seen)
+ << PPOpts->PCHThroughHeader << 1;
+ else if (!PPOpts->PCHWithHdrStopCreate)
+ Diag(SourceLocation(), diag::err_pp_pragma_hdrstop_not_seen);
}
- if (ReachedMainFileEOF)
- Diag(SourceLocation(), diag::err_pp_through_header_not_seen)
- << PPOpts->PCHThroughHeader << 1;
}
void Preprocessor::replayPreambleConditionalStack() {
@@ -848,9 +868,6 @@ void Preprocessor::Lex(Token &Result) {
case CLK_Lexer:
ReturnedToken = CurLexer->Lex(Result);
break;
- case CLK_PTHLexer:
- ReturnedToken = CurPTHLexer->Lex(Result);
- break;
case CLK_TokenLexer:
ReturnedToken = CurTokenLexer->Lex(Result);
break;
@@ -868,6 +885,7 @@ void Preprocessor::Lex(Token &Result) {
if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
// Remember the identifier before code completion token.
setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+ setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
// Set IdenfitierInfo to null to avoid confusing code that handles both
// identifiers and completion tokens.
Result.setIdentifierInfo(nullptr);
@@ -913,7 +931,7 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
// If we have a non-empty module path, load the named module.
if (!ModuleImportPath.empty()) {
// Under the Modules TS, the dot is just part of the module name, and not
- // a real hierarachy separator. Flatten such module names now.
+ // a real hierarchy separator. Flatten such module names now.
//
// FIXME: Is this the right level to be performing this transformation?
std::string FlatModuleName;
diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp
index ec73479cb54f..f810c28ccdf1 100644
--- a/lib/Lex/TokenConcatenation.cpp
+++ b/lib/Lex/TokenConcatenation.cpp
@@ -67,7 +67,7 @@ bool TokenConcatenation::IsIdentifierStringPrefix(const Token &Tok) const {
return IsStringPrefix(StringRef(PP.getSpelling(Tok)), LangOpts.CPlusPlus11);
}
-TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {
+TokenConcatenation::TokenConcatenation(const Preprocessor &pp) : PP(pp) {
memset(TokenInfo, 0, sizeof(TokenInfo));
// These tokens have custom code in AvoidConcat.
@@ -126,7 +126,7 @@ TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {
/// GetFirstChar - Get the first character of the token \arg Tok,
/// avoiding calls to getSpelling where possible.
-static char GetFirstChar(Preprocessor &PP, const Token &Tok) {
+static char GetFirstChar(const Preprocessor &PP, const Token &Tok) {
if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
// Avoid spelling identifiers, the most common form of token.
return II->getNameStart()[0];
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp
index e71b5a9d1e6d..f7703b1bfd8a 100644
--- a/lib/Parse/ParseAST.cpp
+++ b/lib/Parse/ParseAST.cpp
@@ -141,26 +141,26 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
CleanupParser(ParseOP.get());
S.getPreprocessor().EnterMainSourceFile();
- if (!S.getPreprocessor().getCurrentLexer()) {
- // If a PCH through header is specified that does not have an include in
- // the source, there won't be any tokens or a Lexer.
- return;
- }
-
- P.Initialize();
-
- Parser::DeclGroupPtrTy ADecl;
ExternalASTSource *External = S.getASTContext().getExternalSource();
if (External)
External->StartTranslationUnit(Consumer);
- for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF;
- AtEOF = P.ParseTopLevelDecl(ADecl)) {
- // If we got a null return and something *was* parsed, ignore it. This
- // is due to a top-level semicolon, an action override, or a parse error
- // skipping something.
- if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
- return;
+ // If a PCH through header is specified that does not have an include in
+ // the source, or a PCH is being created with #pragma hdrstop with nothing
+ // after the pragma, there won't be any tokens or a Lexer.
+ bool HaveLexer = S.getPreprocessor().getCurrentLexer();
+
+ if (HaveLexer) {
+ P.Initialize();
+ Parser::DeclGroupPtrTy ADecl;
+ for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF;
+ AtEOF = P.ParseTopLevelDecl(ADecl)) {
+ // If we got a null return and something *was* parsed, ignore it. This
+ // is due to a top-level semicolon, an action override, or a parse error
+ // skipping something.
+ if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
+ return;
+ }
}
// Process any TopLevelDecls generated by #pragma weak.
@@ -179,7 +179,7 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
std::swap(OldCollectStats, S.CollectStats);
if (PrintStats) {
llvm::errs() << "\nSTATISTICS:\n";
- P.getActions().PrintStats();
+ if (HaveLexer) P.getActions().PrintStats();
S.getASTContext().PrintStats();
Decl::PrintStats();
Stmt::PrintStats();
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 5898120cab46..fde3ce00f830 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -595,7 +595,7 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
// to X" within the optional brace-or-equal-initializer. It shall not
// appear elsewhere in the member-declarator.
Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
- /*TypeQuals=*/(unsigned)0);
+ Qualifiers());
for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
@@ -728,7 +728,7 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
case tok::semi:
if (StopAtSemi)
return false;
- // FALL THROUGH.
+ LLVM_FALLTHROUGH;
default:
// consume this token.
Toks.push_back(Tok);
@@ -1108,13 +1108,13 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
goto consume_token;
if (AngleCount) --AngleCount;
if (KnownTemplateCount) --KnownTemplateCount;
- // Fall through.
+ LLVM_FALLTHROUGH;
case tok::greatergreater:
if (!getLangOpts().CPlusPlus11)
goto consume_token;
if (AngleCount) --AngleCount;
if (KnownTemplateCount) --KnownTemplateCount;
- // Fall through.
+ LLVM_FALLTHROUGH;
case tok::greater:
if (AngleCount) --AngleCount;
if (KnownTemplateCount) --KnownTemplateCount;
@@ -1219,7 +1219,7 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
case tok::semi:
if (CIK == CIK_DefaultInitializer)
return true; // End of the default initializer.
- // FALL THROUGH.
+ LLVM_FALLTHROUGH;
default:
consume_token:
Toks.push_back(Tok);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 6e57c7bbba91..298a2bad56c6 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -24,7 +24,6 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
@@ -754,7 +753,7 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
case tok::kw__Null_unspecified: {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- if (!getLangOpts().ObjC1)
+ if (!getLangOpts().ObjC)
Diag(AttrNameLoc, diag::ext_nullability)
<< AttrName;
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
@@ -1001,6 +1000,21 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
continue;
}
+ if (Keyword == Ident_deprecated && Platform->Ident &&
+ Platform->Ident->isStr("swift")) {
+ // For swift, we deprecate for all versions.
+ if (Changes[Deprecated].KeywordLoc.isValid()) {
+ Diag(KeywordLoc, diag::err_availability_redundant)
+ << Keyword
+ << SourceRange(Changes[Deprecated].KeywordLoc);
+ }
+
+ Changes[Deprecated].KeywordLoc = KeywordLoc;
+ // Use a fake version here.
+ Changes[Deprecated].Version = VersionTuple(1);
+ continue;
+ }
+
if (Tok.isNot(tok::equal)) {
Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
SkipUntil(tok::r_paren, StopAtSemi);
@@ -1412,7 +1426,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
// Allow 'this' within late-parsed attributes.
- Sema::CXXThisScopeRAII ThisScope(Actions, RD, /*TypeQuals=*/0,
+ Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(),
ND && ND->isCXXInstanceMember());
if (LA.Decls.size() == 1) {
@@ -1940,7 +1954,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
Diag(Loc, diag::err_c11_noreturn_misplaced)
<< (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint())
- << (Fixit ? FixItHint::CreateInsertion(D.getLocStart(), "_Noreturn ")
+ << (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ")
: FixItHint());
}
}
@@ -2302,20 +2316,28 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
llvm::function_ref<void()> ExprListCompleter;
auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
auto ConstructorCompleter = [&, ThisVarDecl] {
- Actions.CodeCompleteConstructor(
+ QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
- ThisDecl->getLocation(), Exprs);
+ ThisDecl->getLocation(), Exprs, T.getOpenLocation());
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
};
if (ThisVarDecl) {
// ParseExpressionList can sometimes succeed even when ThisDecl is not
// VarDecl. This is an error and it is reported in a call to
// Actions.ActOnInitializerError(). However, we call
- // CodeCompleteConstructor only on VarDecls, falling back to default
- // completer in other cases.
+ // ProduceConstructorSignatureHelp only on VarDecls, falling back to
+ // default completer in other cases.
ExprListCompleter = ConstructorCompleter;
}
if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) {
+ if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
+ ThisDecl->getLocation(), Exprs, T.getOpenLocation());
+ CalledSignatureHelp = true;
+ }
Actions.ActOnInitializerError(ThisDecl);
SkipUntil(tok::r_paren, StopAtSemi);
} else {
@@ -2841,7 +2863,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
return false;
const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
- Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()),
+ Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getEndLoc()),
diag::err_expected_after)
<< DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi;
@@ -3282,7 +3304,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Objective-C supports type arguments and protocol references
// following an Objective-C object or object pointer
// type. Handle either one of them.
- if (Tok.is(tok::less) && getLangOpts().ObjC1) {
+ if (Tok.is(tok::less) && getLangOpts().ObjC) {
SourceLocation NewEndLoc;
TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers(
Loc, TypeRep, /*consumeLastToken=*/true,
@@ -3804,7 +3826,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// GCC ObjC supports types like "<SomeProtocol>" as a synonym for
// "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
// but we support it.
- if (DS.hasTypeSpecifier() || !getLangOpts().ObjC1)
+ if (DS.hasTypeSpecifier() || !getLangOpts().ObjC)
goto DoneWithDeclSpec;
SourceLocation StartLoc = Tok.getLocation();
@@ -3830,7 +3852,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
assert(PrevSpec && "Method did not return previous specifier!");
assert(DiagID);
- if (DiagID == diag::ext_duplicate_declspec)
+ if (DiagID == diag::ext_duplicate_declspec ||
+ DiagID == diag::ext_warn_duplicate_declspec)
Diag(Tok, DiagID)
<< PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());
else if (DiagID == diag::err_opencl_unknown_type_specifier) {
@@ -4145,15 +4168,11 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// Enum definitions should not be parsed in a trailing-return-type.
bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing;
- bool AllowFixedUnderlyingType = AllowDeclaration &&
- (getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt ||
- getLangOpts().ObjC2);
-
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
// "enum foo : bar;" is not a potential typo for "enum foo::bar;"
// if a fixed underlying type is allowed.
- ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType);
+ ColonProtectionRAIIObject X(*this, AllowDeclaration);
CXXScopeSpec Spec;
if (ParseOptionalCXXScopeSpecifier(Spec, nullptr,
@@ -4175,7 +4194,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// Must have either 'enum name' or 'enum {...}'.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
- !(AllowFixedUnderlyingType && Tok.is(tok::colon))) {
+ !(AllowDeclaration && Tok.is(tok::colon))) {
Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
// Skip the rest of this declarator, up until the comma or semicolon.
@@ -4208,7 +4227,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// Parse the fixed underlying type.
bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
- if (AllowFixedUnderlyingType && Tok.is(tok::colon)) {
+ if (AllowDeclaration && Tok.is(tok::colon)) {
bool PossibleBitfield = false;
if (CanBeBitfield) {
// If we're in class scope, this can either be an enum declaration with
@@ -4268,13 +4287,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
SourceRange Range;
BaseType = ParseTypeName(&Range);
- if (getLangOpts().CPlusPlus11) {
- Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type);
- } else if (!getLangOpts().ObjC2) {
- if (getLangOpts().CPlusPlus)
- Diag(StartLoc, diag::ext_cxx11_enum_fixed_underlying_type) << Range;
+ if (!getLangOpts().ObjC) {
+ if (getLangOpts().CPlusPlus11)
+ Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type);
+ else if (getLangOpts().CPlusPlus)
+ Diag(StartLoc, diag::ext_cxx11_enum_fixed_underlying_type);
+ else if (getLangOpts().MicrosoftExt)
+ Diag(StartLoc, diag::ext_ms_c_enum_fixed_underlying_type);
else
- Diag(StartLoc, diag::ext_c_enum_fixed_underlying_type) << Range;
+ Diag(StartLoc, diag::ext_clang_c_enum_fixed_underlying_type);
}
}
}
@@ -4654,7 +4675,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::identifier: // foo::bar
if (TryAltiVecVectorToken())
return true;
- // Fall through.
+ LLVM_FALLTHROUGH;
case tok::kw_typename: // typename T::type
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
@@ -4733,7 +4754,7 @@ bool Parser::isTypeSpecifierQualifier() {
// GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
case tok::less:
- return getLangOpts().ObjC1;
+ return getLangOpts().ObjC;
case tok::kw___cdecl:
case tok::kw___stdcall:
@@ -4784,11 +4805,11 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
- if (getLangOpts().ObjC1 && NextToken().is(tok::period))
+ if (getLangOpts().ObjC && NextToken().is(tok::period))
return false;
if (TryAltiVecVectorToken())
return true;
- // Fall through.
+ LLVM_FALLTHROUGH;
case tok::kw_decltype: // decltype(T())::type
case tok::kw_typename: // typename T::type
// Annotate typenames and C++ scope specifiers. If we get one, just
@@ -4914,7 +4935,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
// GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
case tok::less:
- return getLangOpts().ObjC1;
+ return getLangOpts().ObjC;
// typedef-name
case tok::annot_typename:
@@ -5363,7 +5384,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Sema will have to catch (syntactically invalid) pointers into global
// scope. It has to catch pointers into namespace scope anyway.
D.AddTypeInfo(DeclaratorChunk::getMemberPointer(
- SS, DS.getTypeQualifiers(), DS.getLocEnd()),
+ SS, DS.getTypeQualifiers(), DS.getEndLoc()),
std::move(DS.getAttributes()),
/* Don't replace range end. */ SourceLocation());
return;
@@ -5755,7 +5776,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (D.getContext() == DeclaratorContext::MemberContext) {
// Objective-C++: Detect C++ keywords and try to prevent further errors by
// treating these keyword as valid member names.
- if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus &&
+ if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&
Tok.getIdentifierInfo() &&
Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) {
Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
@@ -6051,9 +6072,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
DeclSpec DS(AttrFactory);
bool RefQualifierIsLValueRef = true;
SourceLocation RefQualifierLoc;
- SourceLocation ConstQualifierLoc;
- SourceLocation VolatileQualifierLoc;
- SourceLocation RestrictQualifierLoc;
ExceptionSpecificationType ESpecType = EST_None;
SourceRange ESpecRange;
SmallVector<ParsedType, 2> DynamicExceptions;
@@ -6116,9 +6134,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
}));
if (!DS.getSourceRange().getEnd().isInvalid()) {
EndLoc = DS.getSourceRange().getEnd();
- ConstQualifierLoc = DS.getConstSpecLoc();
- VolatileQualifierLoc = DS.getVolatileSpecLoc();
- RestrictQualifierLoc = DS.getRestrictSpecLoc();
}
// Parse ref-qualifier[opt].
@@ -6140,13 +6155,14 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
: D.getContext() == DeclaratorContext::FileContext &&
D.getCXXScopeSpec().isValid() &&
Actions.CurContext->isRecord());
- Sema::CXXThisScopeRAII ThisScope(Actions,
- dyn_cast<CXXRecordDecl>(Actions.CurContext),
- DS.getTypeQualifiers() |
- (D.getDeclSpec().isConstexprSpecified() &&
- !getLangOpts().CPlusPlus14
- ? Qualifiers::Const : 0),
- IsCXX11MemberFunction);
+
+ Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
+ if (D.getDeclSpec().isConstexprSpecified() && !getLangOpts().CPlusPlus14)
+ Q.addConst();
+
+ Sema::CXXThisScopeRAII ThisScope(
+ Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,
+ IsCXX11MemberFunction);
// Parse exception-specification[opt].
bool Delayed = D.isFirstDeclarationOfMember() &&
@@ -6217,15 +6233,13 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
D.AddTypeInfo(DeclaratorChunk::getFunction(
HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(),
ParamInfo.size(), EllipsisLoc, RParenLoc,
- DS.getTypeQualifiers(), RefQualifierIsLValueRef,
- RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc,
- RestrictQualifierLoc,
- /*MutableLoc=*/SourceLocation(), ESpecType, ESpecRange,
- DynamicExceptions.data(), DynamicExceptionRanges.data(),
- DynamicExceptions.size(),
+ RefQualifierIsLValueRef, RefQualifierLoc,
+ /*MutableLoc=*/SourceLocation(),
+ ESpecType, ESpecRange, DynamicExceptions.data(),
+ DynamicExceptionRanges.data(), DynamicExceptions.size(),
NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
ExceptionSpecTokens, DeclsInPrototype, StartLoc,
- LocalEndLoc, D, TrailingReturnType),
+ LocalEndLoc, D, TrailingReturnType, &DS),
std::move(FnAttrs), EndLoc);
}
@@ -6693,7 +6707,7 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
if (NeedParens) {
// Create a DeclaratorChunk for the inserted parens.
- SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd());
+ SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc),
SourceLocation());
}
@@ -6709,11 +6723,11 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
if (!D.getIdentifier() && !NeedParens)
return;
- SourceLocation EndBracketLoc = TempDeclarator.getLocEnd();
+ SourceLocation EndBracketLoc = TempDeclarator.getEndLoc();
// Generate the move bracket error message.
SourceRange BracketRange(StartBracketLoc, EndBracketLoc);
- SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd());
+ SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
if (NeedParens) {
Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 9ba44d07aba8..f8359f1e87d8 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -24,7 +24,6 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -33,24 +32,25 @@ using namespace clang;
/// may either be a top level namespace or a block-level namespace alias. If
/// there was an inline keyword, it has already been parsed.
///
-/// namespace-definition: [C++ 7.3: basic.namespace]
+/// namespace-definition: [C++: namespace.def]
/// named-namespace-definition
/// unnamed-namespace-definition
+/// nested-namespace-definition
+///
+/// named-namespace-definition:
+/// 'inline'[opt] 'namespace' attributes[opt] identifier '{'
+/// namespace-body '}'
///
/// unnamed-namespace-definition:
/// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'
///
-/// named-namespace-definition:
-/// original-namespace-definition
-/// extension-namespace-definition
-///
-/// original-namespace-definition:
-/// 'inline'[opt] 'namespace' identifier attributes[opt]
-/// '{' namespace-body '}'
+/// nested-namespace-definition:
+/// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt]
+/// identifier '{' namespace-body '}'
///
-/// extension-namespace-definition:
-/// 'inline'[opt] 'namespace' original-namespace-name
-/// '{' namespace-body '}'
+/// enclosing-namespace-specifier:
+/// identifier
+/// enclosing-namespace-specifier '::' 'inline'[opt] identifier
///
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
@@ -70,9 +70,8 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
SourceLocation IdentLoc;
IdentifierInfo *Ident = nullptr;
- std::vector<SourceLocation> ExtraIdentLoc;
- std::vector<IdentifierInfo*> ExtraIdent;
- std::vector<SourceLocation> ExtraNamespaceLoc;
+ InnerNamespaceInfoList ExtraNSs;
+ SourceLocation FirstNestedInlineLoc;
ParsedAttributesWithRange attrs(AttrFactory);
SourceLocation attrLoc;
@@ -88,15 +87,29 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
IdentLoc = ConsumeToken(); // eat the identifier.
- while (Tok.is(tok::coloncolon) && NextToken().is(tok::identifier)) {
- ExtraNamespaceLoc.push_back(ConsumeToken());
- ExtraIdent.push_back(Tok.getIdentifierInfo());
- ExtraIdentLoc.push_back(ConsumeToken());
+ while (Tok.is(tok::coloncolon) &&
+ (NextToken().is(tok::identifier) ||
+ (NextToken().is(tok::kw_inline) &&
+ GetLookAheadToken(2).is(tok::identifier)))) {
+
+ InnerNamespaceInfo Info;
+ Info.NamespaceLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_inline)) {
+ Info.InlineLoc = ConsumeToken();
+ if (FirstNestedInlineLoc.isInvalid())
+ FirstNestedInlineLoc = Info.InlineLoc;
+ }
+
+ Info.Ident = Tok.getIdentifierInfo();
+ Info.IdentLoc = ConsumeToken();
+
+ ExtraNSs.push_back(Info);
}
}
// A nested namespace definition cannot have attributes.
- if (!ExtraNamespaceLoc.empty() && attrLoc.isValid())
+ if (!ExtraNSs.empty() && attrLoc.isValid())
Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute);
// Read label attributes, if present.
@@ -138,13 +151,21 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
return nullptr;
}
- if (ExtraIdent.empty()) {
+ if (ExtraNSs.empty()) {
// Normal namespace definition, not a nested-namespace-definition.
} else if (InlineLoc.isValid()) {
Diag(InlineLoc, diag::err_inline_nested_namespace_definition);
+ } else if (getLangOpts().CPlusPlus2a) {
+ Diag(ExtraNSs[0].NamespaceLoc,
+ diag::warn_cxx14_compat_nested_namespace_definition);
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc,
+ diag::warn_cxx17_compat_inline_nested_namespace_definition);
} else if (getLangOpts().CPlusPlus17) {
- Diag(ExtraNamespaceLoc[0],
+ Diag(ExtraNSs[0].NamespaceLoc,
diag::warn_cxx14_compat_nested_namespace_definition);
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);
} else {
TentativeParsingAction TPA(*this);
SkipUntil(tok::r_brace, StopBeforeMatch);
@@ -152,26 +173,34 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
TPA.Revert();
if (!rBraceToken.is(tok::r_brace)) {
- Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition)
- << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
+ Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)
+ << SourceRange(ExtraNSs.front().NamespaceLoc,
+ ExtraNSs.back().IdentLoc);
} else {
std::string NamespaceFix;
- for (std::vector<IdentifierInfo*>::iterator I = ExtraIdent.begin(),
- E = ExtraIdent.end(); I != E; ++I) {
- NamespaceFix += " { namespace ";
- NamespaceFix += (*I)->getName();
+ for (const auto &ExtraNS : ExtraNSs) {
+ NamespaceFix += " { ";
+ if (ExtraNS.InlineLoc.isValid())
+ NamespaceFix += "inline ";
+ NamespaceFix += "namespace ";
+ NamespaceFix += ExtraNS.Ident->getName();
}
std::string RBraces;
- for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i)
+ for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i)
RBraces += "} ";
- Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition)
- << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(),
- ExtraIdentLoc.back()),
- NamespaceFix)
+ Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)
+ << FixItHint::CreateReplacement(
+ SourceRange(ExtraNSs.front().NamespaceLoc,
+ ExtraNSs.back().IdentLoc),
+ NamespaceFix)
<< FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces);
}
+
+ // Warn about nested inline namespaces.
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);
}
// If we're still good, complain about inline namespaces in non-C++0x now.
@@ -192,8 +221,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
// Parse the contents of the namespace. This includes parsing recovery on
// any improperly nested namespaces.
- ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0,
- InlineLoc, attrs, T);
+ ParseInnerNamespace(ExtraNSs, 0, InlineLoc, attrs, T);
// Leave the namespace scope.
NamespaceScope.Exit();
@@ -206,13 +234,11 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
}
/// ParseInnerNamespace - Parse the contents of a namespace.
-void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
- std::vector<IdentifierInfo *> &Ident,
- std::vector<SourceLocation> &NamespaceLoc,
+void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
unsigned int index, SourceLocation &InlineLoc,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker) {
- if (index == Ident.size()) {
+ if (index == InnerNSs.size()) {
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -233,14 +259,13 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
ParseScope NamespaceScope(this, Scope::DeclScope);
UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
- getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index],
- Ident[index], Tracker.getOpenLocation(), attrs,
- ImplicitUsingDirectiveDecl);
+ getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc,
+ InnerNSs[index].IdentLoc, InnerNSs[index].Ident,
+ Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl);
assert(!ImplicitUsingDirectiveDecl &&
"nested namespace definition cannot define anonymous namespace");
- ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
- attrs, Tracker);
+ ParseInnerNamespace(InnerNSs, ++index, InlineLoc, attrs, Tracker);
NamespaceScope.Exit();
Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());
@@ -365,7 +390,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
case tok::r_brace:
if (!NestedModules)
break;
- // Fall through.
+ LLVM_FALLTHROUGH;
default:
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
@@ -2321,32 +2346,22 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
if (D.isFunctionDeclarator()) {
auto &Function = D.getFunctionTypeInfo();
if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
- auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
- const char *FixItName,
- SourceLocation SpecLoc,
- unsigned* QualifierLoc) {
+ auto DeclSpecCheck = [&](DeclSpec::TQ TypeQual, StringRef FixItName,
+ SourceLocation SpecLoc) {
FixItHint Insertion;
- if (DS.getTypeQualifiers() & TypeQual) {
- if (!(Function.TypeQuals & TypeQual)) {
- std::string Name(FixItName);
- Name += " ";
- Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
- Function.TypeQuals |= TypeQual;
- *QualifierLoc = SpecLoc.getRawEncoding();
- }
- Diag(SpecLoc, diag::err_declspec_after_virtspec)
+ auto &MQ = Function.getOrCreateMethodQualifiers();
+ if (!(MQ.getTypeQualifiers() & TypeQual)) {
+ std::string Name(FixItName.data());
+ Name += " ";
+ Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
+ MQ.SetTypeQual(TypeQual, SpecLoc);
+ }
+ Diag(SpecLoc, diag::err_declspec_after_virtspec)
<< FixItName
<< VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
- << FixItHint::CreateRemoval(SpecLoc)
- << Insertion;
- }
+ << FixItHint::CreateRemoval(SpecLoc) << Insertion;
};
- DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
- &Function.ConstQualifierLoc);
- DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
- &Function.VolatileQualifierLoc);
- DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(),
- &Function.RestrictQualifierLoc);
+ DS.forEachQualifier(DeclSpecCheck);
}
// Parse ref-qualifiers.
@@ -2410,7 +2425,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject *TemplateDiags) {
if (Tok.is(tok::at)) {
- if (getLangOpts().ObjC1 && NextToken().isObjCAtKeyword(tok::objc_defs))
+ if (getLangOpts().ObjC && NextToken().isObjCAtKeyword(tok::objc_defs))
Diag(Tok, diag::err_at_defs_cxx);
else
Diag(Tok, diag::err_at_in_class);
@@ -3449,6 +3464,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
+ // FIXME: Add support for signature help inside initializer lists.
ExprResult InitList = ParseBraceInitializer();
if (InitList.isInvalid())
return true;
@@ -3466,7 +3482,20 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// Parse the optional expression-list.
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
- if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
+ if (Tok.isNot(tok::r_paren) &&
+ ParseExpressionList(ArgExprs, CommaLocs, [&] {
+ QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ T.getOpenLocation());
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ })) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ Actions.ProduceCtorInitMemberSignatureHelp(
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ T.getOpenLocation());
+ CalledSignatureHelp = true;
+ }
SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
@@ -3776,6 +3805,28 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
}
return nullptr;
+ case tok::numeric_constant: {
+ // If we got a numeric constant, check to see if it comes from a macro that
+ // corresponds to the predefined __clang__ macro. If it does, warn the user
+ // and recover by pretending they said _Clang instead.
+ if (Tok.getLocation().isMacroID()) {
+ SmallString<8> ExpansionBuf;
+ SourceLocation ExpansionLoc =
+ PP.getSourceManager().getExpansionLoc(Tok.getLocation());
+ StringRef Spelling = PP.getSpelling(ExpansionLoc, ExpansionBuf);
+ if (Spelling == "__clang__") {
+ SourceRange TokRange(
+ ExpansionLoc,
+ PP.getSourceManager().getExpansionLoc(Tok.getEndLoc()));
+ Diag(Tok, diag::warn_wrong_clang_attr_namespace)
+ << FixItHint::CreateReplacement(TokRange, "_Clang");
+ Loc = ConsumeToken();
+ return &PP.getIdentifierTable().get("_Clang");
+ }
+ }
+ return nullptr;
+ }
+
case tok::ampamp: // 'and'
case tok::pipe: // 'bitor'
case tok::pipepipe: // 'or'
@@ -3854,7 +3905,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
return false;
}
- if (ScopeName && ScopeName->getName() == "gnu") {
+ if (ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"))) {
// GNU-scoped attributes have some special cases to handle GNU-specific
// behaviors.
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
@@ -3864,10 +3915,9 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
unsigned NumArgs;
// Some Clang-scoped attributes have some special parsing behavior.
- if (ScopeName && ScopeName->getName() == "clang")
- NumArgs =
- ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
- ScopeLoc, Syntax);
+ if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")))
+ NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
else
NumArgs =
ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
@@ -3875,7 +3925,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
if (!Attrs.empty() &&
IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
- ParsedAttr &Attr = *Attrs.begin();
+ ParsedAttr &Attr = Attrs.back();
// If the attribute is a standard or built-in attribute and we are
// parsing an argument list, we need to determine whether this attribute
// was allowed to have an argument list (such as [[deprecated]]), and how
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 2a65eec8a0f6..4bcbebcbb48e 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -315,6 +315,19 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
return LHS;
}
+ // In Objective-C++, alternative operator tokens can be used as keyword args
+ // in message expressions. Unconsume the token so that it can reinterpreted
+ // as an identifier in ParseObjCMessageExpressionBody. i.e., we support:
+ // [foo meth:0 and:0];
+ // [foo not_eq];
+ if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&
+ Tok.isOneOf(tok::colon, tok::r_square) &&
+ OpToken.getIdentifierInfo() != nullptr) {
+ PP.EnterToken(Tok);
+ Tok = OpToken;
+ return LHS;
+ }
+
// Special case handling for the ternary operator.
ExprResult TernaryMiddle(true);
if (NextTokPrec == prec::Conditional) {
@@ -380,10 +393,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
}
}
- // Code completion for the right-hand side of an assignment expression
- // goes through a special hook that takes the left-hand side into account.
- if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) {
- Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get());
+ // Code completion for the right-hand side of a binary expression goes
+ // through a special hook that takes the left-hand side into account.
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteBinaryRHS(getCurScope(), LHS.get(),
+ OpToken.getKind());
cutOffParsing();
return ExprError();
}
@@ -944,7 +958,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation ILoc = ConsumeToken();
// Support 'Class.property' and 'super.property' notation.
- if (getLangOpts().ObjC1 && Tok.is(tok::period) &&
+ if (getLangOpts().ObjC && Tok.is(tok::period) &&
(Actions.getTypeName(II, ILoc, getCurScope()) ||
// Allow the base to be 'super' if in an objc-method.
(&II == Ident_super && getCurScope()->isInObjcMethodScope()))) {
@@ -974,7 +988,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// the token sequence is ill-formed. However, if there's a ':' or ']' after
// that identifier, this is probably a message send with a missing open
// bracket. Treat it as such.
- if (getLangOpts().ObjC1 && &II == Ident_super && !InMessageExpression &&
+ if (getLangOpts().ObjC && &II == Ident_super && !InMessageExpression &&
getCurScope()->isInObjcMethodScope() &&
((Tok.is(tok::identifier) &&
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
@@ -989,7 +1003,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// send that's missing the opening '['. Recovery
// appropriately. Also take this path if we're performing code
// completion after an Objective-C class name.
- if (getLangOpts().ObjC1 &&
+ if (getLangOpts().ObjC &&
((Tok.is(tok::identifier) && !InMessageExpression) ||
Tok.is(tok::code_completion))) {
const Token& Next = NextToken();
@@ -1162,7 +1176,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')'
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_alignment) << Tok.getName();
- // fallthrough
+ LLVM_FALLTHROUGH;
case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')'
case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
// unary-expression: '__alignof' '(' type-name ')'
@@ -1228,7 +1242,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Ty.get(), nullptr);
break;
}
- // Fall through
+ LLVM_FALLTHROUGH;
case tok::annot_decltype:
case tok::kw_char:
@@ -1416,7 +1430,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
}
case tok::l_square:
if (getLangOpts().CPlusPlus11) {
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
// C++11 lambda expressions and Objective-C message sends both start with a
// square bracket. There are three possibilities here:
// we have a valid lambda expression, we have an invalid lambda
@@ -1430,11 +1444,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Res = ParseLambdaExpression();
break;
}
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
Res = ParseObjCMessageExpression();
break;
}
- // FALL THROUGH.
+ LLVM_FALLTHROUGH;
default:
NotCastExpr = true;
return ExprError();
@@ -1498,7 +1512,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// If we see identifier: after an expression, and we're not already in a
// message send, then this is probably a message send with a missing
// opening bracket '['.
- if (getLangOpts().ObjC1 && !InMessageExpression &&
+ if (getLangOpts().ObjC && !InMessageExpression &&
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
nullptr, LHS.get());
@@ -1516,7 +1530,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// actually another message send. In this case, do some look-ahead to see
// if the contents of the square brackets are obviously not a valid
// expression and recover by pretending there is no suffix.
- if (getLangOpts().ObjC1 && Tok.isAtStartOfLine() &&
+ if (getLangOpts().ObjC && Tok.isAtStartOfLine() &&
isSimpleObjCMessageExpression())
return LHS;
@@ -1637,7 +1651,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
CommaLocsTy CommaLocs;
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteCall(getCurScope(), LHS.get(), None);
+ QualType PreferredType = Actions.ProduceCallSignatureHelp(
+ getCurScope(), LHS.get(), None, PT.getOpenLocation());
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
cutOffParsing();
return ExprError();
}
@@ -1645,9 +1662,21 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (OpKind == tok::l_paren || !LHS.isInvalid()) {
if (Tok.isNot(tok::r_paren)) {
if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
- Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
- })) {
+ QualType PreferredType = Actions.ProduceCallSignatureHelp(
+ getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation());
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ })) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
+ // If we got an error when parsing expression list, we don't call
+ // the CodeCompleteCall handler inside the parser. So call it here
+ // to make sure we get overload suggestions even when we are in the
+ // middle of a parameter.
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ Actions.ProduceCallSignatureHelp(getCurScope(), LHS.get(),
+ ArgExprs, PT.getOpenLocation());
+ CalledSignatureHelp = true;
+ }
LHS = ExprError();
} else if (LHS.isInvalid()) {
for (auto &E : ArgExprs)
@@ -1738,11 +1767,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
Expr *Base = LHS.get();
Expr *CorrectedBase = CorrectedLHS.get();
+ if (!CorrectedBase && !getLangOpts().CPlusPlus)
+ CorrectedBase = Base;
// Code completion for a member access expression.
Actions.CodeCompleteMemberReferenceExpr(
getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow,
- Base && ExprStatementTokLoc == Base->getLocStart());
+ Base && ExprStatementTokLoc == Base->getBeginLoc());
cutOffParsing();
return ExprError();
@@ -1763,7 +1794,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// FIXME: Add support for explicit call of template constructor.
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
- if (getLangOpts().ObjC2 && OpKind == tok::period &&
+ if (getLangOpts().ObjC && OpKind == tok::period &&
Tok.is(tok::kw_class)) {
// Objective-C++:
// After a '.' in a member access expression, treat the keyword
@@ -1779,7 +1810,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/*EnteringContext=*/false,
/*AllowDestructorName=*/true,
/*AllowConstructorName=*/
- getLangOpts().MicrosoftExt,
+ getLangOpts().MicrosoftExt &&
+ SS.isNotEmpty(),
/*AllowDeductionGuide=*/false,
ObjectType, &TemplateKWLoc, Name)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
@@ -1992,8 +2024,10 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
CastRange);
UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
- if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof))
+ if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
ExprKind = UETT_AlignOf;
+ else if (OpTok.is(tok::kw___alignof))
+ ExprKind = UETT_PreferredAlignOf;
else if (OpTok.is(tok::kw_vec_step))
ExprKind = UETT_VecStep;
else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))
@@ -2306,7 +2340,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
}
// Diagnose use of bridge casts in non-arc mode.
- bool BridgeCast = (getLangOpts().ObjC2 &&
+ bool BridgeCast = (getLangOpts().ObjC &&
Tok.isOneOf(tok::kw___bridge,
tok::kw___bridge_transfer,
tok::kw___bridge_retained,
@@ -2416,7 +2450,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// this is probably an Objective-C message send where the leading '[' is
// missing. Recover as if that were the case.
if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) &&
- !InMessageExpression && getLangOpts().ObjC1 &&
+ !InMessageExpression && getLangOpts().ObjC &&
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
TypeResult Ty;
{
@@ -2502,7 +2536,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
}
// Reject the cast of super idiom in ObjC.
- if (Tok.is(tok::identifier) && getLangOpts().ObjC1 &&
+ if (Tok.is(tok::identifier) && getLangOpts().ObjC &&
Tok.getIdentifierInfo() == Ident_super &&
getCurScope()->isInObjcMethodScope() &&
GetLookAheadToken(1).isNot(tok::period)) {
@@ -2978,12 +3012,8 @@ ExprResult Parser::ParseBlockLiteralExpression() {
/*NumArgs=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
/*RefQualifierIsLvalueRef=*/true,
/*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc, EST_None,
/*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 663c397ee049..3caec6b4def6 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -235,22 +235,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
while (true) {
if (HasScopeSpecifier) {
- // C++ [basic.lookup.classref]p5:
- // If the qualified-id has the form
- //
- // ::class-name-or-namespace-name::...
- //
- // the class-name-or-namespace-name is looked up in global scope as a
- // class-name or namespace-name.
- //
- // To implement this, we clear out the object type as soon as we've
- // seen a leading '::' or part of a nested-name-specifier.
- ObjectType = nullptr;
-
if (Tok.is(tok::code_completion)) {
// Code completion for a nested-name-specifier, where the code
// completion token follows the '::'.
- Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext);
+ Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext,
+ ObjectType.get());
// Include code completion token into the range of the scope otherwise
// when we try to annotate the scope tokens the dangling code completion
// token will cause assertion in
@@ -259,6 +248,18 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
cutOffParsing();
return true;
}
+
+ // C++ [basic.lookup.classref]p5:
+ // If the qualified-id has the form
+ //
+ // ::class-name-or-namespace-name::...
+ //
+ // the class-name-or-namespace-name is looked up in global scope as a
+ // class-name or namespace-name.
+ //
+ // To implement this, we clear out the object type as soon as we've
+ // seen a leading '::' or part of a nested-name-specifier.
+ ObjectType = nullptr;
}
// nested-name-specifier:
@@ -774,7 +775,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// send. In that case, fail here and let the ObjC message
// expression parser perform the completion.
if (Tok.is(tok::code_completion) &&
- !(getLangOpts().ObjC1 && Intro.Default == LCD_None &&
+ !(getLangOpts().ObjC && Intro.Default == LCD_None &&
!Intro.Captures.empty())) {
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
@@ -790,7 +791,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
if (Tok.is(tok::code_completion)) {
// If we're in Objective-C++ and we have a bare '[', then this is more
// likely to be a message receiver.
- if (getLangOpts().ObjC1 && first)
+ if (getLangOpts().ObjC && first)
Actions.CodeCompleteObjCMessageReceiver(getCurScope());
else
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
@@ -1205,12 +1206,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
/*hasProto=*/true,
/*isAmbiguous=*/false, LParenLoc, ParamInfo.data(),
ParamInfo.size(), EllipsisLoc, RParenLoc,
- DS.getTypeQualifiers(),
/*RefQualifierIsLValueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType,
+ /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType,
ESpecRange, DynamicExceptions.data(),
DynamicExceptionRanges.data(), DynamicExceptions.size(),
NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
@@ -1272,12 +1269,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
/*NumParams=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
/*RefQualifierIsLValueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None,
+ /*RefQualifierLoc=*/NoLoc, MutableLoc, EST_None,
/*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
@@ -1674,8 +1667,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
return Init;
Expr *InitList = Init.get();
return Actions.ActOnCXXTypeConstructExpr(
- TypeRep, InitList->getLocStart(), MultiExprArg(&InitList, 1),
- InitList->getLocEnd(), /*ListInitialization=*/true);
+ TypeRep, InitList->getBeginLoc(), MultiExprArg(&InitList, 1),
+ InitList->getEndLoc(), /*ListInitialization=*/true);
} else {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -1685,10 +1678,18 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
if (Tok.isNot(tok::r_paren)) {
if (ParseExpressionList(Exprs, CommaLocs, [&] {
- Actions.CodeCompleteConstructor(getCurScope(),
- TypeRep.get()->getCanonicalTypeInternal(),
- DS.getLocEnd(), Exprs);
- })) {
+ QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+ DS.getEndLoc(), Exprs, T.getOpenLocation());
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ })) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+ DS.getEndLoc(), Exprs, T.getOpenLocation());
+ CalledSignatureHelp = true;
+ }
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -1730,10 +1731,14 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
/// \param Loc The location of the start of the statement that requires this
/// condition, e.g., the "for" in a for loop.
///
+/// \param FRI If non-null, a for range declaration is permitted, and if
+/// present will be parsed and stored here, and a null result will be returned.
+///
/// \returns The parsed condition.
Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
SourceLocation Loc,
- Sema::ConditionKind CK) {
+ Sema::ConditionKind CK,
+ ForRangeInfo *FRI) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
if (Tok.is(tok::code_completion)) {
@@ -1753,7 +1758,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
};
// Determine what kind of thing we have.
- switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) {
+ switch (isCXXConditionDeclarationOrInitStatement(InitStmt, FRI)) {
case ConditionOrInitStatement::Expression: {
ProhibitAttributes(attrs);
@@ -1761,7 +1766,13 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
// if (; true);
if (InitStmt && Tok.is(tok::semi)) {
WarnOnInit();
- SourceLocation SemiLoc = ConsumeToken();
+ SourceLocation SemiLoc = Tok.getLocation();
+ if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID()) {
+ Diag(SemiLoc, diag::warn_empty_init_statement)
+ << (CK == Sema::ConditionKind::Switch)
+ << FixItHint::CreateRemoval(SemiLoc);
+ }
+ ConsumeToken();
*InitStmt = Actions.ActOnNullStmt(SemiLoc);
return ParseCXXCondition(nullptr, Loc, CK);
}
@@ -1791,6 +1802,15 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
return ParseCXXCondition(nullptr, Loc, CK);
}
+ case ConditionOrInitStatement::ForRangeDecl: {
+ assert(FRI && "should not parse a for range declaration here");
+ SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(
+ DeclaratorContext::ForContext, DeclEnd, attrs, false, FRI);
+ FRI->LoopVar = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
+ return Sema::ConditionResult();
+ }
+
case ConditionOrInitStatement::ConditionDecl:
case ConditionOrInitStatement::Error:
break;
@@ -2817,13 +2837,22 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
if (Tok.isNot(tok::r_paren)) {
CommaLocsTy CommaLocs;
if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] {
- ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(),
- DeclaratorInfo).get();
- Actions.CodeCompleteConstructor(getCurScope(),
- TypeRep.get()->getCanonicalTypeInternal(),
- DeclaratorInfo.getLocEnd(),
- ConstructorArgs);
- })) {
+ ParsedType TypeRep =
+ Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
+ QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+ DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ })) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ ParsedType TypeRep =
+ Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
+ Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+ DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
+ CalledSignatureHelp = true;
+ }
SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
return ExprError();
}
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 0cd550bc6a47..7742a5087cf0 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -209,7 +209,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
// send) or send to 'super', parse this as a message send
// expression. We handle C++ and C separately, since C++ requires
// much more complicated parsing.
- if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus) {
+ if (getLangOpts().ObjC && getLangOpts().CPlusPlus) {
// Send to 'super'.
if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
NextToken().isNot(tok::period) &&
@@ -242,7 +242,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
// adopt the expression for further analysis below.
// FIXME: potentially-potentially evaluated expression above?
Idx = ExprResult(static_cast<Expr*>(TypeOrExpr));
- } else if (getLangOpts().ObjC1 && Tok.is(tok::identifier)) {
+ } else if (getLangOpts().ObjC && Tok.is(tok::identifier)) {
IdentifierInfo *II = Tok.getIdentifierInfo();
SourceLocation IILoc = Tok.getLocation();
ParsedType ReceiverType;
@@ -312,7 +312,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() {
// tokens are '...' or ']' or an objc message send. If this is an objc
// message send, handle it now. An objc-message send is the start of
// an assignment-expression production.
- if (getLangOpts().ObjC1 && Tok.isNot(tok::ellipsis) &&
+ if (getLangOpts().ObjC && Tok.isNot(tok::ellipsis) &&
Tok.isNot(tok::r_square)) {
CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig);
return ParseAssignmentExprWithObjCMessageExprStart(
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 99e5edb9d4a3..bd55f7179399 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -178,8 +178,7 @@ void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
Diag(AtLoc, diag::err_objc_missing_end)
<< FixItHint::CreateInsertion(AtLoc, "@end\n");
if (Decl)
- Diag(Decl->getLocStart(), diag::note_objc_container_start)
- << (int) ock;
+ Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock;
}
///
@@ -264,7 +263,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
}
- else if (!getLangOpts().ObjC2) {
+ else if (!getLangOpts().ObjC) {
Diag(Tok, diag::err_expected)
<< tok::identifier; // missing category name.
return nullptr;
@@ -384,12 +383,12 @@ static void addContextSensitiveTypeNullability(Parser &P,
if (D.getNumTypeObjects() > 0) {
// Add the attribute to the declarator chunk nearest the declarator.
- D.getTypeObject(0).getAttrs().addAtStart(
+ D.getTypeObject(0).getAttrs().addAtEnd(
getNullabilityAttr(D.getAttributePool()));
} else if (!addedToDeclSpec) {
// Otherwise, just put it on the declaration specifiers (if one
// isn't there already).
- D.getMutableDeclSpec().getAttributes().addAtStart(
+ D.getMutableDeclSpec().getAttributes().addAtEnd(
getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool()));
addedToDeclSpec = true;
}
@@ -690,8 +689,8 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
case tok::objc_interface:
Diag(AtLoc, diag::err_objc_missing_end)
<< FixItHint::CreateInsertion(AtLoc, "@end\n");
- Diag(CDecl->getLocStart(), diag::note_objc_container_start)
- << (int) Actions.getObjCContainerKind();
+ Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)
+ << (int)Actions.getObjCContainerKind();
ConsumeToken();
break;
@@ -706,7 +705,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
break;
case tok::objc_property:
- if (!getLangOpts().ObjC2)
+ if (!getLangOpts().ObjC)
Diag(AtLoc, diag::err_objc_properties_require_objc2);
ObjCDeclSpec OCDS;
@@ -776,8 +775,8 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
} else {
Diag(Tok, diag::err_objc_missing_end)
<< FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
- Diag(CDecl->getLocStart(), diag::note_objc_container_start)
- << (int) Actions.getObjCContainerKind();
+ Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)
+ << (int)Actions.getObjCContainerKind();
AtEnd.setBegin(Tok.getLocation());
AtEnd.setEnd(Tok.getLocation());
}
@@ -1104,7 +1103,7 @@ bool Parser::isTokIdentifier_in() const {
// FIXME: May have to do additional look-ahead to only allow for
// valid tokens following an 'in'; such as an identifier, unary operators,
// '[' etc.
- return (getLangOpts().ObjC2 && Tok.is(tok::identifier) &&
+ return (getLangOpts().ObjC && Tok.is(tok::identifier) &&
Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
}
@@ -1198,7 +1197,7 @@ static void takeDeclAttributes(ParsedAttributesView &attrs,
for (auto &AL : llvm::reverse(from)) {
if (!AL.isUsedAsTypeAttr()) {
from.remove(&AL);
- attrs.addAtStart(&AL);
+ attrs.addAtEnd(&AL);
}
}
}
@@ -1338,7 +1337,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// If attributes exist before the method, parse them.
ParsedAttributes methodAttrs(AttrFactory);
- if (getLangOpts().ObjC2)
+ if (getLangOpts().ObjC)
MaybeParseGNUAttributes(methodAttrs);
MaybeParseCXX11Attributes(methodAttrs);
@@ -1365,7 +1364,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
if (Tok.isNot(tok::colon)) {
// If attributes exist after the method, parse them.
- if (getLangOpts().ObjC2)
+ if (getLangOpts().ObjC)
MaybeParseGNUAttributes(methodAttrs);
MaybeParseCXX11Attributes(methodAttrs);
@@ -1401,7 +1400,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// If attributes exist before the argument name, parse them.
// Regardless, collect all the attributes we've parsed so far.
- if (getLangOpts().ObjC2)
+ if (getLangOpts().ObjC)
MaybeParseGNUAttributes(paramAttrs);
MaybeParseCXX11Attributes(paramAttrs);
ArgInfo.ArgAttrs = paramAttrs;
@@ -1485,7 +1484,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// FIXME: Add support for optional parameter list...
// If attributes exist after the method, parse them.
- if (getLangOpts().ObjC2)
+ if (getLangOpts().ObjC)
MaybeParseGNUAttributes(methodAttrs);
MaybeParseCXX11Attributes(methodAttrs);
@@ -1551,7 +1550,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) {
assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
- assert(getLangOpts().ObjC1 && "Protocol qualifiers only exist in Objective-C");
+ assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C");
SourceLocation lAngleLoc;
SmallVector<Decl *, 8> protocols;
@@ -2223,7 +2222,7 @@ Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
if (P.isEofOrEom()) {
P.Diag(P.Tok, diag::err_objc_missing_end)
<< FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
- P.Diag(Dcl->getLocStart(), diag::note_objc_container_start)
+ P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start)
<< Sema::OCK_Implementation;
}
}
@@ -2742,7 +2741,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
// Otherwise, eat the semicolon.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
- return Actions.ActOnExprStmt(Res);
+ return Actions.ActOnExprStmt(Res, isExprValueDiscarded());
}
ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
@@ -2946,14 +2945,14 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
/// This routine will only return true for a subset of valid message-send
/// expressions.
bool Parser::isSimpleObjCMessageExpression() {
- assert(Tok.is(tok::l_square) && getLangOpts().ObjC1 &&
+ assert(Tok.is(tok::l_square) && getLangOpts().ObjC &&
"Incorrect start for isSimpleObjCMessageExpression");
return GetLookAheadToken(1).is(tok::identifier) &&
GetLookAheadToken(2).is(tok::identifier);
}
bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
- if (!getLangOpts().ObjC1 || !NextToken().is(tok::identifier) ||
+ if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) ||
InMessageExpression)
return false;
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index a413e96a91e7..dd2a8aae9f2f 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -314,7 +314,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
ExprResult CombinerResult =
Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
- D->getLocation(), /*DiscardedValue=*/true);
+ D->getLocation(), /*DiscardedValue*/ false);
Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
@@ -353,12 +353,18 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
// Check if initializer is omp_priv <init_expr> or something else.
if (Tok.is(tok::identifier) &&
Tok.getIdentifierInfo()->isStr("omp_priv")) {
- ConsumeToken();
- ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
+ if (Actions.getLangOpts().CPlusPlus) {
+ InitializerResult = Actions.ActOnFinishFullExpr(
+ ParseAssignmentExpression().get(), D->getLocation(),
+ /*DiscardedValue*/ false);
+ } else {
+ ConsumeToken();
+ ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
+ }
} else {
InitializerResult = Actions.ActOnFinishFullExpr(
ParseAssignmentExpression().get(), D->getLocation(),
- /*DiscardedValue=*/true);
+ /*DiscardedValue*/ false);
}
Actions.ActOnOpenMPDeclareReductionInitializerEnd(
D, InitializerResult.get(), OmpPrivParm);
@@ -415,11 +421,22 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
ExprVector Exprs;
CommaLocsTy CommaLocs;
- if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
- Actions.CodeCompleteConstructor(
- getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
- OmpPrivParm->getLocation(), Exprs);
- })) {
+ SourceLocation LParLoc = T.getOpenLocation();
+ if (ParseExpressionList(
+ Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] {
+ QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(),
+ OmpPrivParm->getType()->getCanonicalTypeInternal(),
+ OmpPrivParm->getLocation(), Exprs, LParLoc);
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ })) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
+ OmpPrivParm->getLocation(), Exprs, LParLoc);
+ CalledSignatureHelp = true;
+ }
Actions.ActOnInitializerError(OmpPrivParm);
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
} else {
@@ -478,7 +495,7 @@ public:
Sema &Actions = P.getActions();
// Allow 'this' within late-parsed attributes.
- ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
+ ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
ND && ND->isCXXInstanceMember());
// If the Decl is templatized, add template parameters to scope.
@@ -627,6 +644,60 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
LinModifiers, Steps, SourceRange(Loc, EndLoc));
}
+Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
+ // OpenMP 4.5 syntax with list of entities.
+ Sema::NamedDeclSetType SameDirectiveDecls;
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ StringRef ClauseName = II->getName();
+ // Parse 'to|link' clauses.
+ if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName;
+ break;
+ }
+ ConsumeToken();
+ }
+ auto &&Callback = [this, MT, &SameDirectiveDecls](
+ CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
+ Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
+ SameDirectiveDecls);
+ };
+ if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
+ /*AllowScopeSpecifier=*/true))
+ break;
+
+ // Consume optional ','.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
+ SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
+ ConsumeAnyToken();
+ SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
+ SameDirectiveDecls.end());
+ if (Decls.empty())
+ return DeclGroupPtrTy();
+ return Actions.BuildDeclaratorGroup(Decls);
+}
+
+void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
+ SourceLocation DTLoc) {
+ if (DKind != OMPD_end_declare_target) {
+ Diag(Tok, diag::err_expected_end_declare_target);
+ Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
+ return;
+ }
+ ConsumeAnyToken();
+ if (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
+ << getOpenMPDirectiveName(OMPD_end_declare_target);
+ SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
+ }
+ // Skip the last annot_pragma_openmp_end.
+ ConsumeAnyToken();
+}
+
/// Parsing of declarative OpenMP directives.
///
/// threadprivate-directive:
@@ -642,6 +713,10 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
/// annot_pragma_openmp_end
/// <function declaration/definition>
///
+/// requires directive:
+/// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
+/// annot_pragma_openmp_end
+///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
DeclSpec::TST TagType, Decl *Tag) {
@@ -670,6 +745,46 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
break;
}
+ case OMPD_requires: {
+ SourceLocation StartLoc = ConsumeToken();
+ SmallVector<OMPClause *, 5> Clauses;
+ SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
+ FirstClauses(OMPC_unknown + 1);
+ if (Tok.is(tok::annot_pragma_openmp_end)) {
+ Diag(Tok, diag::err_omp_expected_clause)
+ << getOpenMPDirectiveName(OMPD_requires);
+ break;
+ }
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ Actions.StartOpenMPClause(CKind);
+ OMPClause *Clause =
+ ParseOpenMPClause(OMPD_requires, CKind, !FirstClauses[CKind].getInt());
+ SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, StopBeforeMatch);
+ FirstClauses[CKind].setInt(true);
+ if (Clause != nullptr)
+ Clauses.push_back(Clause);
+ if (Tok.is(tok::annot_pragma_openmp_end)) {
+ Actions.EndOpenMPClause();
+ break;
+ }
+ // Skip ',' if any.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ Actions.EndOpenMPClause();
+ }
+ // Consume final annot_pragma_openmp_end
+ if (Clauses.size() == 0) {
+ Diag(Tok, diag::err_omp_expected_clause)
+ << getOpenMPDirectiveName(OMPD_requires);
+ ConsumeAnnotationToken();
+ return nullptr;
+ }
+ ConsumeAnnotationToken();
+ return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
+ }
case OMPD_declare_reduction:
ConsumeToken();
if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
@@ -724,43 +839,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- // OpenMP 4.5 syntax with list of entities.
- Sema::NamedDeclSetType SameDirectiveDecls;
- while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OMPDeclareTargetDeclAttr::MapTypeTy MT =
- OMPDeclareTargetDeclAttr::MT_To;
- if (Tok.is(tok::identifier)) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- StringRef ClauseName = II->getName();
- // Parse 'to|link' clauses.
- if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
- MT)) {
- Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName;
- break;
- }
- ConsumeToken();
- }
- auto &&Callback = [this, MT, &SameDirectiveDecls](
- CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
- Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
- SameDirectiveDecls);
- };
- if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
- /*AllowScopeSpecifier=*/true))
- break;
-
- // Consume optional ','.
- if (Tok.is(tok::comma))
- ConsumeToken();
- }
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- ConsumeAnyToken();
- SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
- SameDirectiveDecls.end());
- if (Decls.empty())
- return DeclGroupPtrTy();
- return Actions.BuildDeclaratorGroup(Decls);
+ return ParseOMPDeclareTargetClauses();
}
// Skip the last annot_pragma_openmp_end.
@@ -771,8 +850,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
llvm::SmallVector<Decl *, 4> Decls;
DKind = parseOpenMPDirectiveKind(*this);
- while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
- Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
+ while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
+ Tok.isNot(tok::r_brace)) {
DeclGroupPtrTy Ptr;
// Here we expect to see some function declaration.
if (AS == AS_none) {
@@ -799,19 +878,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
}
- if (DKind == OMPD_end_declare_target) {
- ConsumeAnyToken();
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_end_declare_target);
- SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- }
- // Skip the last annot_pragma_openmp_end.
- ConsumeAnyToken();
- } else {
- Diag(Tok, diag::err_expected_end_declare_target);
- Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
- }
+ ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
Actions.ActOnFinishOpenMPDeclareTargetDirective();
return Actions.BuildDeclaratorGroup(Decls);
}
@@ -1124,6 +1191,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
case OMPD_declare_simd:
case OMPD_declare_target:
case OMPD_end_declare_target:
+ case OMPD_requires:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end);
@@ -1275,11 +1343,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
break;
case OMPC_default:
case OMPC_proc_bind:
+ case OMPC_atomic_default_mem_order:
// OpenMP [2.14.3.1, Restrictions]
// Only a single default clause may be specified on a parallel, task or
// teams directive.
// OpenMP [2.5, parallel Construct, Restrictions]
// At most one proc_bind clause can appear on the directive.
+ // OpenMP [5.0, Requires directive, Restrictions]
+ // At most one atomic_default_mem_order clause can appear
+ // on the directive
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
@@ -1316,10 +1388,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_threads:
case OMPC_simd:
case OMPC_nogroup:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
// OpenMP [2.7.1, Restrictions, p. 9]
// Only one ordered clause can appear on a loop directive.
// OpenMP [2.7.1, Restrictions, C/C++, p. 4]
// Only one nowait clause can appear on a for directive.
+ // OpenMP [5.0, Requires directive, Restrictions]
+ // Each of the requires clauses can appear at most once on the directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
@@ -1377,7 +1455,7 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
ExprResult LHS(ParseCastExpression(
/*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
- Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
+ Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
// Parse ')'.
RLoc = Tok.getLocation();
@@ -1633,7 +1711,8 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
- Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
+ Val =
+ Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
}
// Parse ')'.
@@ -1696,6 +1775,79 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
nullptr, nullptr, ReductionId);
}
+/// Checks if the token is a valid map-type-modifier.
+static OpenMPMapModifierKind isMapModifier(Parser &P) {
+ Token Tok = P.getCurToken();
+ if (!Tok.is(tok::identifier))
+ return OMPC_MAP_MODIFIER_unknown;
+
+ Preprocessor &PP = P.getPreprocessor();
+ OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
+ getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
+ return TypeModifier;
+}
+
+/// Parse map-type-modifiers in map clause.
+/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
+/// where, map-type-modifier ::= always | close
+static void parseMapTypeModifiers(Parser &P,
+ Parser::OpenMPVarListDataTy &Data) {
+ Preprocessor &PP = P.getPreprocessor();
+ while (P.getCurToken().isNot(tok::colon)) {
+ Token Tok = P.getCurToken();
+ OpenMPMapModifierKind TypeModifier = isMapModifier(P);
+ if (TypeModifier == OMPC_MAP_MODIFIER_always ||
+ TypeModifier == OMPC_MAP_MODIFIER_close) {
+ Data.MapTypeModifiers.push_back(TypeModifier);
+ Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
+ P.ConsumeToken();
+ } else {
+ // For the case of unknown map-type-modifier or a map-type.
+ // Map-type is followed by a colon; the function returns when it
+ // encounters a token followed by a colon.
+ if (Tok.is(tok::comma)) {
+ P.Diag(Tok, diag::err_omp_map_type_modifier_missing);
+ P.ConsumeToken();
+ continue;
+ }
+ // Potential map-type token as it is followed by a colon.
+ if (PP.LookAhead(0).is(tok::colon))
+ return;
+ P.Diag(Tok, diag::err_omp_unknown_map_type_modifier);
+ P.ConsumeToken();
+ }
+ if (P.getCurToken().is(tok::comma))
+ P.ConsumeToken();
+ }
+}
+
+/// Checks if the token is a valid map-type.
+static OpenMPMapClauseKind isMapType(Parser &P) {
+ Token Tok = P.getCurToken();
+ // The map-type token can be either an identifier or the C++ delete keyword.
+ if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
+ return OMPC_MAP_unknown;
+ Preprocessor &PP = P.getPreprocessor();
+ OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
+ getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
+ return MapType;
+}
+
+/// Parse map-type in map clause.
+/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
+/// where, map-type ::= to | from | tofrom | alloc | release | delete
+static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
+ Token Tok = P.getCurToken();
+ if (Tok.is(tok::colon)) {
+ P.Diag(Tok, diag::err_omp_map_type_missing);
+ return;
+ }
+ Data.MapType = isMapType(P);
+ if (Data.MapType == OMPC_MAP_unknown)
+ P.Diag(Tok, diag::err_omp_unknown_map_type);
+ P.ConsumeToken();
+}
+
/// Parses clauses with list.
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
OpenMPClauseKind Kind,
@@ -1703,7 +1855,6 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
OpenMPVarListDataTy &Data) {
UnqualifiedId UnqualifiedReductionId;
bool InvalidReductionId = false;
- bool MapTypeModifierSpecified = false;
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
@@ -1775,104 +1926,40 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
// Handle map type for map clause.
ColonProtectionRAIIObject ColonRAII(*this);
- /// The map clause modifier token can be either a identifier or the C++
- /// delete keyword.
- auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
- return Tok.isOneOf(tok::identifier, tok::kw_delete);
- };
-
// The first identifier may be a list item, a map-type or a
- // map-type-modifier. The map modifier can also be delete which has the same
+ // map-type-modifier. The map-type can also be delete which has the same
// spelling of the C++ delete keyword.
- Data.MapType =
- IsMapClauseModifierToken(Tok)
- ? static_cast<OpenMPMapClauseKind>(
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
- : OMPC_MAP_unknown;
Data.DepLinMapLoc = Tok.getLocation();
- bool ColonExpected = false;
-
- if (IsMapClauseModifierToken(Tok)) {
- if (PP.LookAhead(0).is(tok::colon)) {
- if (Data.MapType == OMPC_MAP_unknown)
- Diag(Tok, diag::err_omp_unknown_map_type);
- else if (Data.MapType == OMPC_MAP_always)
- Diag(Tok, diag::err_omp_map_type_missing);
- ConsumeToken();
- } else if (PP.LookAhead(0).is(tok::comma)) {
- if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
- PP.LookAhead(2).is(tok::colon)) {
- Data.MapTypeModifier = Data.MapType;
- if (Data.MapTypeModifier != OMPC_MAP_always) {
- Diag(Tok, diag::err_omp_unknown_map_type_modifier);
- Data.MapTypeModifier = OMPC_MAP_unknown;
- } else {
- MapTypeModifierSpecified = true;
- }
-
- ConsumeToken();
- ConsumeToken();
-
- Data.MapType =
- IsMapClauseModifierToken(Tok)
- ? static_cast<OpenMPMapClauseKind>(
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
- : OMPC_MAP_unknown;
- if (Data.MapType == OMPC_MAP_unknown ||
- Data.MapType == OMPC_MAP_always)
- Diag(Tok, diag::err_omp_unknown_map_type);
- ConsumeToken();
- } else {
- Data.MapType = OMPC_MAP_tofrom;
- Data.IsMapTypeImplicit = true;
- }
- } else if (IsMapClauseModifierToken(PP.LookAhead(0))) {
- if (PP.LookAhead(1).is(tok::colon)) {
- Data.MapTypeModifier = Data.MapType;
- if (Data.MapTypeModifier != OMPC_MAP_always) {
- Diag(Tok, diag::err_omp_unknown_map_type_modifier);
- Data.MapTypeModifier = OMPC_MAP_unknown;
- } else {
- MapTypeModifierSpecified = true;
- }
- ConsumeToken();
-
- Data.MapType =
- IsMapClauseModifierToken(Tok)
- ? static_cast<OpenMPMapClauseKind>(
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
- : OMPC_MAP_unknown;
- if (Data.MapType == OMPC_MAP_unknown ||
- Data.MapType == OMPC_MAP_always)
- Diag(Tok, diag::err_omp_unknown_map_type);
- ConsumeToken();
- } else {
- Data.MapType = OMPC_MAP_tofrom;
- Data.IsMapTypeImplicit = true;
- }
- } else {
- Data.MapType = OMPC_MAP_tofrom;
- Data.IsMapTypeImplicit = true;
- }
- } else {
+ // Check for presence of a colon in the map clause.
+ TentativeParsingAction TPA(*this);
+ bool ColonPresent = false;
+ if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch)) {
+ if (Tok.is(tok::colon))
+ ColonPresent = true;
+ }
+ TPA.Revert();
+ // Only parse map-type-modifier[s] and map-type if a colon is present in
+ // the map clause.
+ if (ColonPresent) {
+ parseMapTypeModifiers(*this, Data);
+ parseMapType(*this, Data);
+ }
+ if (Data.MapType == OMPC_MAP_unknown) {
Data.MapType = OMPC_MAP_tofrom;
Data.IsMapTypeImplicit = true;
}
if (Tok.is(tok::colon))
Data.ColonLoc = ConsumeToken();
- else if (ColonExpected)
- Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
}
bool IsComma =
(Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
(Kind == OMPC_reduction && !InvalidReductionId) ||
- (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
- (!MapTypeModifierSpecified ||
- Data.MapTypeModifier == OMPC_MAP_always)) ||
+ (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
(Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
@@ -1910,7 +1997,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.ColonLoc = Tok.getLocation();
SourceLocation ELoc = ConsumeToken();
ExprResult Tail = ParseAssignmentExpression();
- Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
+ Tail =
+ Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
if (Tail.isUsable())
Data.TailExpr = Tail.get();
else
@@ -1957,7 +2045,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/// depend-clause:
/// 'depend' '(' in | out | inout : list | source ')'
/// map-clause:
-/// 'map' '(' [ [ always , ]
+/// 'map' '(' [ [ always [,] ] [ close [,] ]
/// to | from | tofrom | alloc | release | delete ':' ] list ')';
/// to-clause:
/// 'to' '(' list ')'
@@ -1988,7 +2076,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
return Actions.ActOnOpenMPVarListClause(
Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc,
Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
- Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
- Data.DepLinMapLoc);
+ Data.MapTypeModifiers, Data.MapTypeModifiersLoc, Data.MapType,
+ Data.IsMapTypeImplicit, Data.DepLinMapLoc);
}
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 07f48e0779dc..380eb64997a7 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -15,10 +15,10 @@
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/LoopHint.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
-#include "clang/Sema/LoopHint.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -106,8 +106,19 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
tok::OnOffSwitch OOS;
if (PP.LexOnOffSwitch(OOS))
return;
- if (OOS == tok::OOS_ON)
+ if (OOS == tok::OOS_ON) {
PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
+ }
+
+ MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
+ 1);
+ Toks[0].startToken();
+ Toks[0].setKind(tok::annot_pragma_fenv_access);
+ Toks[0].setLocation(Tok.getLocation());
+ Toks[0].setAnnotationEndLoc(Tok.getLocation());
+ Toks[0].setAnnotationValue(reinterpret_cast<void*>(
+ static_cast<uintptr_t>(OOS)));
+ PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
}
};
@@ -250,112 +261,122 @@ struct PragmaAttributeHandler : public PragmaHandler {
} // end namespace
void Parser::initializePragmaHandlers() {
- AlignHandler.reset(new PragmaAlignHandler());
+ AlignHandler = llvm::make_unique<PragmaAlignHandler>();
PP.AddPragmaHandler(AlignHandler.get());
- GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
+ GCCVisibilityHandler = llvm::make_unique<PragmaGCCVisibilityHandler>();
PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
- OptionsHandler.reset(new PragmaOptionsHandler());
+ OptionsHandler = llvm::make_unique<PragmaOptionsHandler>();
PP.AddPragmaHandler(OptionsHandler.get());
- PackHandler.reset(new PragmaPackHandler());
+ PackHandler = llvm::make_unique<PragmaPackHandler>();
PP.AddPragmaHandler(PackHandler.get());
- MSStructHandler.reset(new PragmaMSStructHandler());
+ MSStructHandler = llvm::make_unique<PragmaMSStructHandler>();
PP.AddPragmaHandler(MSStructHandler.get());
- UnusedHandler.reset(new PragmaUnusedHandler());
+ UnusedHandler = llvm::make_unique<PragmaUnusedHandler>();
PP.AddPragmaHandler(UnusedHandler.get());
- WeakHandler.reset(new PragmaWeakHandler());
+ WeakHandler = llvm::make_unique<PragmaWeakHandler>();
PP.AddPragmaHandler(WeakHandler.get());
- RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
+ RedefineExtnameHandler = llvm::make_unique<PragmaRedefineExtnameHandler>();
PP.AddPragmaHandler(RedefineExtnameHandler.get());
- FPContractHandler.reset(new PragmaFPContractHandler());
+ FPContractHandler = llvm::make_unique<PragmaFPContractHandler>();
PP.AddPragmaHandler("STDC", FPContractHandler.get());
- STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler());
+ STDCFENVHandler = llvm::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
- STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler());
+ STDCCXLIMITHandler = llvm::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
- STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler());
+ STDCUnknownHandler = llvm::make_unique<PragmaSTDC_UnknownHandler>();
PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
- PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
+ PCSectionHandler = llvm::make_unique<PragmaClangSectionHandler>(Actions);
PP.AddPragmaHandler("clang", PCSectionHandler.get());
if (getLangOpts().OpenCL) {
- OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
+ OpenCLExtensionHandler = llvm::make_unique<PragmaOpenCLExtensionHandler>();
PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
}
if (getLangOpts().OpenMP)
- OpenMPHandler.reset(new PragmaOpenMPHandler());
+ OpenMPHandler = llvm::make_unique<PragmaOpenMPHandler>();
else
- OpenMPHandler.reset(new PragmaNoOpenMPHandler());
+ OpenMPHandler = llvm::make_unique<PragmaNoOpenMPHandler>();
PP.AddPragmaHandler(OpenMPHandler.get());
if (getLangOpts().MicrosoftExt ||
getTargetInfo().getTriple().isOSBinFormatELF()) {
- MSCommentHandler.reset(new PragmaCommentHandler(Actions));
+ MSCommentHandler = llvm::make_unique<PragmaCommentHandler>(Actions);
PP.AddPragmaHandler(MSCommentHandler.get());
}
if (getLangOpts().MicrosoftExt) {
- MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
+ MSDetectMismatchHandler =
+ llvm::make_unique<PragmaDetectMismatchHandler>(Actions);
PP.AddPragmaHandler(MSDetectMismatchHandler.get());
- MSPointersToMembers.reset(new PragmaMSPointersToMembers());
+ MSPointersToMembers = llvm::make_unique<PragmaMSPointersToMembers>();
PP.AddPragmaHandler(MSPointersToMembers.get());
- MSVtorDisp.reset(new PragmaMSVtorDisp());
+ MSVtorDisp = llvm::make_unique<PragmaMSVtorDisp>();
PP.AddPragmaHandler(MSVtorDisp.get());
- MSInitSeg.reset(new PragmaMSPragma("init_seg"));
+ MSInitSeg = llvm::make_unique<PragmaMSPragma>("init_seg");
PP.AddPragmaHandler(MSInitSeg.get());
- MSDataSeg.reset(new PragmaMSPragma("data_seg"));
+ MSDataSeg = llvm::make_unique<PragmaMSPragma>("data_seg");
PP.AddPragmaHandler(MSDataSeg.get());
- MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
+ MSBSSSeg = llvm::make_unique<PragmaMSPragma>("bss_seg");
PP.AddPragmaHandler(MSBSSSeg.get());
- MSConstSeg.reset(new PragmaMSPragma("const_seg"));
+ MSConstSeg = llvm::make_unique<PragmaMSPragma>("const_seg");
PP.AddPragmaHandler(MSConstSeg.get());
- MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
+ MSCodeSeg = llvm::make_unique<PragmaMSPragma>("code_seg");
PP.AddPragmaHandler(MSCodeSeg.get());
- MSSection.reset(new PragmaMSPragma("section"));
+ MSSection = llvm::make_unique<PragmaMSPragma>("section");
PP.AddPragmaHandler(MSSection.get());
- MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
+ MSRuntimeChecks = llvm::make_unique<PragmaMSRuntimeChecksHandler>();
PP.AddPragmaHandler(MSRuntimeChecks.get());
- MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
+ MSIntrinsic = llvm::make_unique<PragmaMSIntrinsicHandler>();
PP.AddPragmaHandler(MSIntrinsic.get());
- MSOptimize.reset(new PragmaMSOptimizeHandler());
+ MSOptimize = llvm::make_unique<PragmaMSOptimizeHandler>();
PP.AddPragmaHandler(MSOptimize.get());
}
if (getLangOpts().CUDA) {
- CUDAForceHostDeviceHandler.reset(
- new PragmaForceCUDAHostDeviceHandler(Actions));
+ CUDAForceHostDeviceHandler =
+ llvm::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
}
- OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
+ OptimizeHandler = llvm::make_unique<PragmaOptimizeHandler>(Actions);
PP.AddPragmaHandler("clang", OptimizeHandler.get());
- LoopHintHandler.reset(new PragmaLoopHintHandler());
+ LoopHintHandler = llvm::make_unique<PragmaLoopHintHandler>();
PP.AddPragmaHandler("clang", LoopHintHandler.get());
- UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
+ UnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("unroll");
PP.AddPragmaHandler(UnrollHintHandler.get());
- NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
+ NoUnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("nounroll");
PP.AddPragmaHandler(NoUnrollHintHandler.get());
- FPHandler.reset(new PragmaFPHandler());
+ UnrollAndJamHintHandler =
+ llvm::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
+ PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
+
+ NoUnrollAndJamHintHandler =
+ llvm::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
+ PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
+
+ FPHandler = llvm::make_unique<PragmaFPHandler>();
PP.AddPragmaHandler("clang", FPHandler.get());
- AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory));
+ AttributePragmaHandler =
+ llvm::make_unique<PragmaAttributeHandler>(AttrFactory);
PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
}
@@ -451,6 +472,12 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler(NoUnrollHintHandler.get());
NoUnrollHintHandler.reset();
+ PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
+ UnrollAndJamHintHandler.reset();
+
+ PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
+ NoUnrollAndJamHintHandler.reset();
+
PP.RemovePragmaHandler("clang", FPHandler.get());
FPHandler.reset();
@@ -591,6 +618,30 @@ void Parser::HandlePragmaFPContract() {
ConsumeAnnotationToken();
}
+void Parser::HandlePragmaFEnvAccess() {
+ assert(Tok.is(tok::annot_pragma_fenv_access));
+ tok::OnOffSwitch OOS =
+ static_cast<tok::OnOffSwitch>(
+ reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
+
+ LangOptions::FEnvAccessModeKind FPC;
+ switch (OOS) {
+ case tok::OOS_ON:
+ FPC = LangOptions::FEA_On;
+ break;
+ case tok::OOS_OFF:
+ FPC = LangOptions::FEA_Off;
+ break;
+ case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
+ FPC = LangOptions::FEA_Off;
+ break;
+ }
+
+ Actions.ActOnPragmaFEnvAccess(FPC);
+ ConsumeAnnotationToken();
+}
+
+
StmtResult Parser::HandlePragmaCaptured()
{
assert(Tok.is(tok::annot_pragma_captured));
@@ -955,6 +1006,8 @@ static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
if (PragmaName.getIdentifierInfo()->getName() == "loop") {
PragmaString = "clang loop ";
PragmaString += Option.getIdentifierInfo()->getName();
+ } else if (PragmaName.getIdentifierInfo()->getName() == "unroll_and_jam") {
+ PragmaString = "unroll_and_jam";
} else {
assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
"Unexpected pragma name");
@@ -986,7 +1039,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
// without an argument.
bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
- if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
+ bool PragmaUnrollAndJam = PragmaNameInfo->getName() == "unroll_and_jam";
+ bool PragmaNoUnrollAndJam = PragmaNameInfo->getName() == "nounroll_and_jam";
+ if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll || PragmaUnrollAndJam ||
+ PragmaNoUnrollAndJam)) {
ConsumeAnnotationToken();
Hint.Range = Info->PragmaName.getLocation();
return true;
@@ -999,24 +1055,31 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
// If no option is specified the argument is assumed to be a constant expr.
bool OptionUnroll = false;
+ bool OptionUnrollAndJam = false;
bool OptionDistribute = false;
+ bool OptionPipelineDisabled = false;
bool StateOption = false;
if (OptionInfo) { // Pragma Unroll does not specify an option.
OptionUnroll = OptionInfo->isStr("unroll");
+ OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
OptionDistribute = OptionInfo->isStr("distribute");
+ OptionPipelineDisabled = OptionInfo->isStr("pipeline");
StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
.Case("vectorize", true)
.Case("interleave", true)
.Default(false) ||
- OptionUnroll || OptionDistribute;
+ OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
+ OptionPipelineDisabled;
}
- bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
+ bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
+ !OptionDistribute && !OptionPipelineDisabled;
// Verify loop hint has an argument.
if (Toks[0].is(tok::eof)) {
ConsumeAnnotationToken();
Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
- << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
+ << /*StateArgument=*/StateOption
+ << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
<< /*AssumeSafetyKeyword=*/AssumeSafetyArg;
return false;
}
@@ -1029,14 +1092,19 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
bool Valid = StateInfo &&
llvm::StringSwitch<bool>(StateInfo->getName())
- .Cases("enable", "disable", true)
- .Case("full", OptionUnroll)
+ .Case("disable", true)
+ .Case("enable", !OptionPipelineDisabled)
+ .Case("full", OptionUnroll || OptionUnrollAndJam)
.Case("assume_safety", AssumeSafetyArg)
.Default(false);
if (!Valid) {
- Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
- << /*FullKeyword=*/OptionUnroll
- << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
+ if (OptionPipelineDisabled) {
+ Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
+ } else {
+ Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
+ << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
+ << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
+ }
return false;
}
if (Toks.size() > 2)
@@ -1076,9 +1144,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
namespace {
struct PragmaAttributeInfo {
- enum ActionType { Push, Pop };
+ enum ActionType { Push, Pop, Attribute };
ParsedAttributes &Attributes;
ActionType Action;
+ const IdentifierInfo *Namespace = nullptr;
ArrayRef<Token> Tokens;
PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
@@ -1333,12 +1402,20 @@ void Parser::HandlePragmaAttribute() {
auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
if (Info->Action == PragmaAttributeInfo::Pop) {
ConsumeAnnotationToken();
- Actions.ActOnPragmaAttributePop(PragmaLoc);
+ Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
return;
}
// Parse the actual attribute with its arguments.
- assert(Info->Action == PragmaAttributeInfo::Push &&
+ assert((Info->Action == PragmaAttributeInfo::Push ||
+ Info->Action == PragmaAttributeInfo::Attribute) &&
"Unexpected #pragma attribute command");
+
+ if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
+ ConsumeAnnotationToken();
+ Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
+ return;
+ }
+
PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
ConsumeAnnotationToken();
@@ -1485,8 +1562,12 @@ void Parser::HandlePragmaAttribute() {
// Consume the eof terminator token.
ConsumeToken();
- Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
- std::move(SubjectMatchRules));
+ // Handle a mixed push/attribute by desurging to a push, then an attribute.
+ if (Info->Action == PragmaAttributeInfo::Push)
+ Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
+
+ Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
+ std::move(SubjectMatchRules));
}
// #pragma GCC visibility comes in two variants:
@@ -2737,6 +2818,8 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
/// 'vectorize_width' '(' loop-hint-value ')'
/// 'interleave_count' '(' loop-hint-value ')'
/// 'unroll_count' '(' loop-hint-value ')'
+/// 'pipeline' '(' disable ')'
+/// 'pipeline_initiation_interval' '(' loop-hint-value ')'
///
/// loop-hint-keyword:
/// 'enable'
@@ -2796,6 +2879,8 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
.Case("vectorize_width", true)
.Case("interleave_count", true)
.Case("unroll_count", true)
+ .Case("pipeline", true)
+ .Case("pipeline_initiation_interval", true)
.Default(false);
if (!OptionValid) {
PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
@@ -2844,6 +2929,10 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
/// #pragma unroll unroll-hint-value
/// #pragma unroll '(' unroll-hint-value ')'
/// #pragma nounroll
+/// #pragma unroll_and_jam
+/// #pragma unroll_and_jam unroll-hint-value
+/// #pragma unroll_and_jam '(' unroll-hint-value ')'
+/// #pragma nounroll_and_jam
///
/// unroll-hint-value:
/// constant-expression
@@ -2868,9 +2957,10 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
// nounroll or unroll pragma without an argument.
Info->PragmaName = PragmaName;
Info->Option.startToken();
- } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
+ } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
+ PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "nounroll";
+ << PragmaName.getIdentifierInfo()->getName();
return;
} else {
// Unroll pragma with an argument: "#pragma unroll N" or
@@ -3041,10 +3131,22 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma(
///
/// The syntax is:
/// \code
-/// #pragma clang attribute push(attribute, subject-set)
+/// #pragma clang attribute push (attribute, subject-set)
+/// #pragma clang attribute push
+/// #pragma clang attribute (attribute, subject-set)
/// #pragma clang attribute pop
/// \endcode
///
+/// There are also 'namespace' variants of push and pop directives. The bare
+/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
+/// namespace, since it always applies attributes to the most recently pushed
+/// group, regardless of namespace.
+/// \code
+/// #pragma clang attribute namespace.push (attribute, subject-set)
+/// #pragma clang attribute namespace.push
+/// #pragma clang attribute namespace.pop
+/// \endcode
+///
/// The subject-set clause defines the set of declarations which receive the
/// attribute. Its exact syntax is described in the LanguageExtensions document
/// in Clang's documentation.
@@ -3060,25 +3162,56 @@ void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
auto *Info = new (PP.getPreprocessorAllocator())
PragmaAttributeInfo(AttributesForPragmaAttribute);
- // Parse the 'push' or 'pop'.
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
- return;
+ // Parse the optional namespace followed by a period.
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (!II->isStr("push") && !II->isStr("pop")) {
+ Info->Namespace = II;
+ PP.Lex(Tok);
+
+ if (!Tok.is(tok::period)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
+ << II;
+ return;
+ }
+ PP.Lex(Tok);
+ }
}
- const auto *II = Tok.getIdentifierInfo();
- if (II->isStr("push"))
- Info->Action = PragmaAttributeInfo::Push;
- else if (II->isStr("pop"))
- Info->Action = PragmaAttributeInfo::Pop;
- else {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
- << PP.getSpelling(Tok);
+
+ if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_attribute_expected_push_pop_paren);
return;
}
- PP.Lex(Tok);
+
+ // Determine what action this pragma clang attribute represents.
+ if (Tok.is(tok::l_paren)) {
+ if (Info->Namespace) {
+ PP.Diag(Tok.getLocation(),
+ diag::err_pragma_attribute_namespace_on_attribute);
+ PP.Diag(Tok.getLocation(),
+ diag::note_pragma_attribute_namespace_on_attribute);
+ return;
+ }
+ Info->Action = PragmaAttributeInfo::Attribute;
+ } else {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II->isStr("push"))
+ Info->Action = PragmaAttributeInfo::Push;
+ else if (II->isStr("pop"))
+ Info->Action = PragmaAttributeInfo::Pop;
+ else {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
+ << PP.getSpelling(Tok);
+ return;
+ }
+
+ PP.Lex(Tok);
+ }
// Parse the actual attribute.
- if (Info->Action == PragmaAttributeInfo::Push) {
+ if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
+ Info->Action == PragmaAttributeInfo::Attribute) {
if (Tok.isNot(tok::l_paren)) {
PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
return;
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index deb10af4b17b..2974e6a245b0 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -15,10 +15,10 @@
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Parse/LoopHint.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/LoopHint.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
using namespace clang;
@@ -348,6 +348,11 @@ Retry:
ConsumeAnnotationToken();
return StmtError();
+ case tok::annot_pragma_fenv_access:
+ ProhibitAttributes(Attrs);
+ HandlePragmaFEnvAccess();
+ return StmtEmpty();
+
case tok::annot_pragma_opencl_extension:
ProhibitAttributes(Attrs);
HandlePragmaOpenCLExtension();
@@ -434,7 +439,7 @@ StmtResult Parser::ParseExprStatement() {
// Otherwise, eat the semicolon.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
- return Actions.ActOnExprStmt(Expr);
+ return Actions.ActOnExprStmt(Expr, isExprValueDiscarded());
}
/// ParseSEHTryBlockCommon
@@ -902,6 +907,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
case tok::annot_pragma_fp:
HandlePragmaFP();
break;
+ case tok::annot_pragma_fenv_access:
+ HandlePragmaFEnvAccess();
+ break;
case tok::annot_pragma_ms_pointers_to_members:
HandlePragmaMSPointersToMembers();
break;
@@ -922,6 +930,44 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
}
+/// Consume any extra semi-colons resulting in null statements,
+/// returning true if any tok::semi were consumed.
+bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
+ if (!Tok.is(tok::semi))
+ return false;
+
+ SourceLocation StartLoc = Tok.getLocation();
+ SourceLocation EndLoc;
+
+ while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() &&
+ Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {
+ EndLoc = Tok.getLocation();
+
+ // Don't just ConsumeToken() this tok::semi, do store it in AST.
+ StmtResult R = ParseStatementOrDeclaration(Stmts, ACK_Any);
+ if (R.isUsable())
+ Stmts.push_back(R.get());
+ }
+
+ // Did not consume any extra semi.
+ if (EndLoc.isInvalid())
+ return false;
+
+ Diag(StartLoc, diag::warn_null_statement)
+ << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
+ return true;
+}
+
+bool Parser::isExprValueDiscarded() {
+ if (Actions.isCurCompoundStmtAStmtExpr()) {
+ // Look to see if the next two tokens close the statement expression;
+ // if so, this expression statement is the last statement in a
+ // statment expression.
+ return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren);
+ }
+ return true;
+}
+
/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
/// ActOnCompoundStmt action. This expects the '{' to be the current token, and
/// consume the '}' at the end of the block. It does not manipulate the scope
@@ -984,6 +1030,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
continue;
}
+ if (ConsumeNullStmt(Stmts))
+ continue;
+
StmtResult R;
if (Tok.isNot(tok::kw___extension__)) {
R = ParseStatementOrDeclaration(Stmts, ACK_Any);
@@ -1023,7 +1072,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
// Eat the semicolon at the end of stmt and convert the expr into a
// statement.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
- R = Actions.ActOnExprStmt(Res);
+ R = Actions.ActOnExprStmt(Res, isExprValueDiscarded());
}
}
@@ -1534,7 +1583,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
}
bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus ||
- getLangOpts().ObjC1;
+ getLangOpts().ObjC;
// C99 6.8.5p5 - In C99, the for statement is a block. This is not
// the case for C90. Start the loop scope.
@@ -1562,11 +1611,11 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ExprResult Value;
- bool ForEach = false, ForRange = false;
+ bool ForEach = false;
StmtResult FirstPart;
Sema::ConditionResult SecondPart;
ExprResult Collection;
- ForRangeInit ForRangeInit;
+ ForRangeInfo ForRangeInfo;
FullExprArg ThirdPart(Actions);
if (Tok.is(tok::code_completion)) {
@@ -1580,10 +1629,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
+ SourceLocation EmptyInitStmtSemiLoc;
+
// Parse the first part of the for specifier.
if (Tok.is(tok::semi)) { // for (;
ProhibitAttributes(attrs);
// no first part, eat the ';'.
+ SourceLocation SemiLoc = Tok.getLocation();
+ if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID())
+ EmptyInitStmtSemiLoc = SemiLoc;
ConsumeToken();
} else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
isForRangeIdentifier()) {
@@ -1592,20 +1646,19 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
SourceLocation Loc = ConsumeToken();
MaybeParseCXX11Attributes(attrs);
- ForRangeInit.ColonLoc = ConsumeToken();
+ ForRangeInfo.ColonLoc = ConsumeToken();
if (Tok.is(tok::l_brace))
- ForRangeInit.RangeExpr = ParseBraceInitializer();
+ ForRangeInfo.RangeExpr = ParseBraceInitializer();
else
- ForRangeInit.RangeExpr = ParseExpression();
+ ForRangeInfo.RangeExpr = ParseExpression();
Diag(Loc, diag::err_for_range_identifier)
<< ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17)
? FixItHint::CreateInsertion(Loc, "auto &&")
: FixItHint());
- FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name,
- attrs, attrs.Range.getEnd());
- ForRange = true;
+ ForRangeInfo.LoopVar = Actions.ActOnCXXForRangeIdentifier(
+ getCurScope(), Loc, Name, attrs, attrs.Range.getEnd());
} else if (isForInitDeclaration()) { // for (int X = 4;
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -1622,13 +1675,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy DG = ParseSimpleDeclaration(
DeclaratorContext::ForContext, DeclEnd, attrs, false,
- MightBeForRangeStmt ? &ForRangeInit : nullptr);
+ MightBeForRangeStmt ? &ForRangeInfo : nullptr);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
- if (ForRangeInit.ParsedForRangeDecl()) {
- Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ?
+ if (ForRangeInfo.ParsedForRangeDecl()) {
+ Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_for_range : diag::ext_for_range);
-
- ForRange = true;
+ ForRangeInfo.LoopVar = FirstPart;
+ FirstPart = StmtResult();
} else if (Tok.is(tok::semi)) { // for (int x = 4;
ConsumeToken();
} else if ((ForEach = isTokIdentifier_in())) {
@@ -1655,8 +1708,16 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
if (!Value.isInvalid()) {
if (ForEach)
FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
- else
- FirstPart = Actions.ActOnExprStmt(Value);
+ else {
+ // We already know this is not an init-statement within a for loop, so
+ // if we are parsing a C++11 range-based for loop, we should treat this
+ // expression statement as being a discarded value expression because
+ // we will err below. This way we do not warn on an unused expression
+ // that was an error in the first place, like with: for (expr : expr);
+ bool IsRangeBasedFor =
+ getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
+ FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor);
+ }
}
if (Tok.is(tok::semi)) {
@@ -1691,17 +1752,38 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// Parse the second part of the for specifier.
getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
- if (!ForEach && !ForRange && !SecondPart.isInvalid()) {
+ if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
+ !SecondPart.isInvalid()) {
// Parse the second part of the for specifier.
if (Tok.is(tok::semi)) { // for (...;;
// no second part.
} else if (Tok.is(tok::r_paren)) {
// missing both semicolons.
} else {
- if (getLangOpts().CPlusPlus)
+ if (getLangOpts().CPlusPlus) {
+ // C++2a: We've parsed an init-statement; we might have a
+ // for-range-declaration next.
+ bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl();
+ ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
SecondPart =
- ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean);
- else {
+ ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean,
+ MightBeForRangeStmt ? &ForRangeInfo : nullptr);
+
+ if (ForRangeInfo.ParsedForRangeDecl()) {
+ Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc()
+ : ForRangeInfo.ColonLoc,
+ getLangOpts().CPlusPlus2a
+ ? diag::warn_cxx17_compat_for_range_init_stmt
+ : diag::ext_for_range_init_stmt)
+ << (FirstPart.get() ? FirstPart.get()->getSourceRange()
+ : SourceRange());
+ if (EmptyInitStmtSemiLoc.isValid()) {
+ Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)
+ << /*for-loop*/ 2
+ << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc);
+ }
+ }
+ } else {
ExprResult SecondExpr = ParseExpression();
if (SecondExpr.isInvalid())
SecondPart = Sema::ConditionError();
@@ -1711,7 +1793,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
Sema::ConditionKind::Boolean);
}
}
+ }
+ // Parse the third part of the for statement.
+ if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
if (Tok.isNot(tok::semi)) {
if (!SecondPart.isInvalid())
Diag(Tok, diag::err_expected_semi_for);
@@ -1724,7 +1809,6 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
ConsumeToken();
}
- // Parse the third part of the for specifier.
if (Tok.isNot(tok::r_paren)) { // for (...;...;)
ExprResult Third = ParseExpression();
// FIXME: The C++11 standard doesn't actually say that this is a
@@ -1737,7 +1821,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// C++ Coroutines [stmt.iter]:
// 'co_await' can only be used for a range-based for statement.
- if (CoawaitLoc.isValid() && !ForRange) {
+ if (CoawaitLoc.isValid() && !ForRangeInfo.ParsedForRangeDecl()) {
Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
CoawaitLoc = SourceLocation();
}
@@ -1748,12 +1832,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
StmtResult ForRangeStmt;
StmtResult ForEachStmt;
- if (ForRange) {
+ if (ForRangeInfo.ParsedForRangeDecl()) {
ExprResult CorrectedRange =
- Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get());
+ Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get());
ForRangeStmt = Actions.ActOnCXXForRangeStmt(
getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
- ForRangeInit.ColonLoc, CorrectedRange.get(),
+ ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(),
T.getCloseLocation(), Sema::BFRK_Build);
// Similarly, we need to do the semantic analysis for a for-range
@@ -1808,7 +1892,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(),
Body.get());
- if (ForRange)
+ if (ForRangeInfo.ParsedForRangeDecl())
return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
@@ -1897,10 +1981,11 @@ StmtResult Parser::ParseReturnStatement() {
if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) {
R = ParseInitializer();
if (R.isUsable())
- Diag(R.get()->getLocStart(), getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_generalized_initializer_lists :
- diag::ext_generalized_initializer_lists)
- << R.get()->getSourceRange();
+ Diag(R.get()->getBeginLoc(),
+ getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_generalized_initializer_lists
+ : diag::ext_generalized_initializer_lists)
+ << R.get()->getSourceRange();
} else
R = ParseExpression();
if (R.isInvalid()) {
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 063f7ccea320..e0a7cc6e856d 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -425,7 +425,9 @@ bool Parser::isStartOfTemplateTypeParameter() {
}
}
- if (Tok.isNot(tok::kw_typename))
+ // 'typedef' is a reasonably-common typo/thinko for 'typename', and is
+ // ill-formed otherwise.
+ if (Tok.isNot(tok::kw_typename) && Tok.isNot(tok::kw_typedef))
return false;
// C++ [temp.param]p2:
@@ -448,6 +450,13 @@ bool Parser::isStartOfTemplateTypeParameter() {
case tok::ellipsis:
return true;
+ case tok::kw_typename:
+ case tok::kw_typedef:
+ case tok::kw_class:
+ // These indicate that a comma was missed after a type parameter, not that
+ // we have found a non-type parameter.
+ return true;
+
default:
return false;
}
@@ -469,26 +478,25 @@ bool Parser::isStartOfTemplateTypeParameter() {
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
/// = id-expression
NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
- if (isStartOfTemplateTypeParameter())
- return ParseTypeParameter(Depth, Position);
-
- if (Tok.is(tok::kw_template))
- return ParseTemplateTemplateParameter(Depth, Position);
+ if (isStartOfTemplateTypeParameter()) {
+ // Is there just a typo in the input code? ('typedef' instead of 'typename')
+ if (Tok.is(tok::kw_typedef)) {
+ Diag(Tok.getLocation(), diag::err_expected_template_parameter);
- // Is there just a typo in the input code? ('typedef' instead of 'typename')
- if (Tok.is(tok::kw_typedef)) {
- Diag(Tok.getLocation(), diag::err_expected_template_parameter);
-
- Diag(Tok.getLocation(), diag::note_meant_to_use_typename)
- << FixItHint::CreateReplacement(CharSourceRange::getCharRange(
- Tok.getLocation(), Tok.getEndLoc()),
- "typename");
+ Diag(Tok.getLocation(), diag::note_meant_to_use_typename)
+ << FixItHint::CreateReplacement(CharSourceRange::getCharRange(
+ Tok.getLocation(), Tok.getEndLoc()),
+ "typename");
- Tok.setKind(tok::kw_typename);
+ Tok.setKind(tok::kw_typename);
+ }
return ParseTypeParameter(Depth, Position);
}
+ if (Tok.is(tok::kw_template))
+ return ParseTemplateTemplateParameter(Depth, Position);
+
// If it's none of the above, then it must be a parameter declaration.
// NOTE: This will pick up errors in the closure of the template parameter
// list (e.g., template < ; Check here to implement >> style closures.
@@ -938,7 +946,9 @@ Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,
bool Invalid = false;
{
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
- if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater))
+ if (!Tok.isOneOf(tok::greater, tok::greatergreater,
+ tok::greatergreatergreater, tok::greaterequal,
+ tok::greatergreaterequal))
Invalid = ParseTemplateArgumentList(TemplateArgs);
if (Invalid) {
@@ -1371,26 +1381,37 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
- // Get the list of DeclContexts to reenter.
- SmallVector<DeclContext*, 4> DeclContextsToReenter;
+ // Get the list of DeclContexts to reenter. For inline methods, we only want
+ // to push the DeclContext of the outermost class. This matches the way the
+ // parser normally parses bodies of inline methods when the outermost class is
+ // complete.
+ struct ContainingDC {
+ ContainingDC(DeclContext *DC, bool ShouldPush) : Pair(DC, ShouldPush) {}
+ llvm::PointerIntPair<DeclContext *, 1, bool> Pair;
+ DeclContext *getDC() { return Pair.getPointer(); }
+ bool shouldPushDC() { return Pair.getInt(); }
+ };
+ SmallVector<ContainingDC, 4> DeclContextsToReenter;
DeclContext *DD = FunD;
+ DeclContext *NextContaining = Actions.getContainingDC(DD);
while (DD && !DD->isTranslationUnit()) {
- DeclContextsToReenter.push_back(DD);
+ bool ShouldPush = DD == NextContaining;
+ DeclContextsToReenter.push_back({DD, ShouldPush});
+ if (ShouldPush)
+ NextContaining = Actions.getContainingDC(DD);
DD = DD->getLexicalParent();
}
// Reenter template scopes from outermost to innermost.
- SmallVectorImpl<DeclContext *>::reverse_iterator II =
- DeclContextsToReenter.rbegin();
- for (; II != DeclContextsToReenter.rend(); ++II) {
- TemplateParamScopeStack.push_back(new ParseScope(this,
- Scope::TemplateParamScope));
- unsigned NumParamLists =
- Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II));
+ for (ContainingDC CDC : reverse(DeclContextsToReenter)) {
+ TemplateParamScopeStack.push_back(
+ new ParseScope(this, Scope::TemplateParamScope));
+ unsigned NumParamLists = Actions.ActOnReenterTemplateScope(
+ getCurScope(), cast<Decl>(CDC.getDC()));
CurTemplateDepthTracker.addDepth(NumParamLists);
- if (*II != FunD) {
+ if (CDC.shouldPushDC()) {
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
- Actions.PushDeclContext(Actions.getCurScope(), *II);
+ Actions.PushDeclContext(Actions.getCurScope(), CDC.getDC());
}
}
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index dfd1f8c3b2e6..de39e0675fdb 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -159,7 +159,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
ConsumeToken();
break;
}
- // Fall through.
+ LLVM_FALLTHROUGH;
case tok::kw_typeof:
case tok::kw___attribute:
case tok::kw___underlying_type: {
@@ -219,11 +219,11 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
case tok::annot_cxxscope:
ConsumeAnnotationToken();
- // Fall through.
+ LLVM_FALLTHROUGH;
default:
ConsumeAnyToken();
- if (getLangOpts().ObjC1 && Tok.is(tok::less))
+ if (getLangOpts().ObjC && Tok.is(tok::less))
return TryParseProtocolQualifiers();
break;
}
@@ -345,22 +345,55 @@ struct Parser::ConditionDeclarationOrInitStatementState {
bool CanBeExpression = true;
bool CanBeCondition = true;
bool CanBeInitStatement;
+ bool CanBeForRangeDecl;
+
+ ConditionDeclarationOrInitStatementState(Parser &P, bool CanBeInitStatement,
+ bool CanBeForRangeDecl)
+ : P(P), CanBeInitStatement(CanBeInitStatement),
+ CanBeForRangeDecl(CanBeForRangeDecl) {}
- ConditionDeclarationOrInitStatementState(Parser &P, bool CanBeInitStatement)
- : P(P), CanBeInitStatement(CanBeInitStatement) {}
+ bool resolved() {
+ return CanBeExpression + CanBeCondition + CanBeInitStatement +
+ CanBeForRangeDecl < 2;
+ }
void markNotExpression() {
CanBeExpression = false;
- if (CanBeCondition && CanBeInitStatement) {
+ if (!resolved()) {
// FIXME: Unify the parsing codepaths for condition variables and
// simple-declarations so that we don't need to eagerly figure out which
// kind we have here. (Just parse init-declarators until we reach a
// semicolon or right paren.)
RevertingTentativeParsingAction PA(P);
- P.SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch);
+ if (CanBeForRangeDecl) {
+ // Skip until we hit a ')', ';', or a ':' with no matching '?'.
+ // The final case is a for range declaration, the rest are not.
+ while (true) {
+ unsigned QuestionColonDepth = 0;
+ P.SkipUntil({tok::r_paren, tok::semi, tok::question, tok::colon},
+ StopBeforeMatch);
+ if (P.Tok.is(tok::question))
+ ++QuestionColonDepth;
+ else if (P.Tok.is(tok::colon)) {
+ if (QuestionColonDepth)
+ --QuestionColonDepth;
+ else {
+ CanBeCondition = CanBeInitStatement = false;
+ return;
+ }
+ } else {
+ CanBeForRangeDecl = false;
+ break;
+ }
+ P.ConsumeToken();
+ }
+ } else {
+ // Just skip until we hit a ')' or ';'.
+ P.SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch);
+ }
if (P.Tok.isNot(tok::r_paren))
- CanBeCondition = false;
+ CanBeCondition = CanBeForRangeDecl = false;
if (P.Tok.isNot(tok::semi))
CanBeInitStatement = false;
}
@@ -368,28 +401,36 @@ struct Parser::ConditionDeclarationOrInitStatementState {
bool markNotCondition() {
CanBeCondition = false;
- return !CanBeInitStatement || !CanBeExpression;
+ return resolved();
+ }
+
+ bool markNotForRangeDecl() {
+ CanBeForRangeDecl = false;
+ return resolved();
}
bool update(TPResult IsDecl) {
switch (IsDecl) {
case TPResult::True:
markNotExpression();
- return true;
+ assert(resolved() && "can't continue after tentative parsing bails out");
+ break;
case TPResult::False:
- CanBeCondition = CanBeInitStatement = false;
- return true;
+ CanBeCondition = CanBeInitStatement = CanBeForRangeDecl = false;
+ break;
case TPResult::Ambiguous:
- return false;
+ break;
case TPResult::Error:
- CanBeExpression = CanBeCondition = CanBeInitStatement = false;
- return true;
+ CanBeExpression = CanBeCondition = CanBeInitStatement =
+ CanBeForRangeDecl = false;
+ break;
}
- llvm_unreachable("unknown tentative parse result");
+ return resolved();
}
ConditionOrInitStatement result() const {
- assert(CanBeExpression + CanBeCondition + CanBeInitStatement < 2 &&
+ assert(CanBeExpression + CanBeCondition + CanBeInitStatement +
+ CanBeForRangeDecl < 2 &&
"result called but not yet resolved");
if (CanBeExpression)
return ConditionOrInitStatement::Expression;
@@ -397,6 +438,8 @@ struct Parser::ConditionDeclarationOrInitStatementState {
return ConditionOrInitStatement::ConditionDecl;
if (CanBeInitStatement)
return ConditionOrInitStatement::InitStmtDecl;
+ if (CanBeForRangeDecl)
+ return ConditionOrInitStatement::ForRangeDecl;
return ConditionOrInitStatement::Error;
}
};
@@ -419,8 +462,10 @@ struct Parser::ConditionDeclarationOrInitStatementState {
/// to the ';' to disambiguate cases like 'int(x))' (an expression) from
/// 'int(x);' (a simple-declaration in an init-statement).
Parser::ConditionOrInitStatement
-Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) {
- ConditionDeclarationOrInitStatementState State(*this, CanBeInitStatement);
+Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,
+ bool CanBeForRangeDecl) {
+ ConditionDeclarationOrInitStatementState State(*this, CanBeInitStatement,
+ CanBeForRangeDecl);
if (State.update(isCXXDeclarationSpecifier()))
return State.result();
@@ -447,11 +492,19 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) {
return State.result();
}
+ // A colon here identifies a for-range declaration.
+ if (State.CanBeForRangeDecl && Tok.is(tok::colon))
+ return ConditionOrInitStatement::ForRangeDecl;
+
// At this point, it can't be a condition any more, because a condition
// must have a brace-or-equal-initializer.
if (State.markNotCondition())
return State.result();
+ // Likewise, it can't be a for-range declaration any more.
+ if (State.markNotForRangeDecl())
+ return State.result();
+
// A parenthesized initializer could be part of an expression or a
// simple-declaration.
if (Tok.is(tok::l_paren)) {
@@ -596,7 +649,7 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate,
return CAK_NotAttributeSpecifier;
// No tentative parsing if we don't need to look for ']]' or a lambda.
- if (!Disambiguate && !getLangOpts().ObjC1)
+ if (!Disambiguate && !getLangOpts().ObjC)
return CAK_AttributeSpecifier;
RevertingTentativeParsingAction PA(*this);
@@ -605,7 +658,7 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate,
ConsumeBracket();
// Outside Obj-C++11, treat anything with a matching ']]' as an attribute.
- if (!getLangOpts().ObjC1) {
+ if (!getLangOpts().ObjC) {
ConsumeBracket();
bool IsAttribute = SkipUntil(tok::r_square);
@@ -1107,8 +1160,8 @@ public:
// Reject any candidate that only resolves to instance members since they
// aren't viable as standalone identifiers instead of member references.
if (Candidate.isResolved() && !Candidate.isKeyword() &&
- std::all_of(Candidate.begin(), Candidate.end(),
- [](NamedDecl *ND) { return ND->isCXXInstanceMember(); }))
+ llvm::all_of(Candidate,
+ [](NamedDecl *ND) { return ND->isCXXInstanceMember(); }))
return false;
return CorrectionCandidateCallback::ValidateCandidate(Candidate);
@@ -1233,7 +1286,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
const Token &Next = NextToken();
// In 'foo bar', 'foo' is always a type name outside of Objective-C.
- if (!getLangOpts().ObjC1 && Next.is(tok::identifier))
+ if (!getLangOpts().ObjC && Next.is(tok::identifier))
return TPResult::True;
if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
@@ -1299,8 +1352,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
if (Next.isOneOf(tok::kw_new, // ::new
tok::kw_delete)) // ::delete
return TPResult::False;
+ LLVM_FALLTHROUGH;
}
- // Fall through.
case tok::kw___super:
case tok::kw_decltype:
// Annotate typenames and C++ scope specifiers. If we get one, just
@@ -1506,7 +1559,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::annot_typename:
case_typename:
// In Objective-C, we might have a protocol-qualified type.
- if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {
+ if (getLangOpts().ObjC && NextToken().is(tok::less)) {
// Tentatively parse the protocol qualifiers.
RevertingTentativeParsingAction PA(*this);
ConsumeAnyToken(); // The type token
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index c3085654f529..a93db799f8fe 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -341,7 +341,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
case tok::semi:
if (HasFlagsSet(Flags, StopAtSemi))
return false;
- // FALL THROUGH.
+ LLVM_FALLTHROUGH;
default:
// Skip this token.
ConsumeAnyToken();
@@ -443,7 +443,7 @@ void Parser::Initialize() {
// Initialization for Objective-C context sensitive keywords recognition.
// Referenced in Parser::ParseObjCTypeQualifierList.
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
ObjCTypeQuals[objc_in] = &PP.getIdentifierTable().get("in");
ObjCTypeQuals[objc_out] = &PP.getIdentifierTable().get("out");
ObjCTypeQuals[objc_inout] = &PP.getIdentifierTable().get("inout");
@@ -674,6 +674,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_fp_contract:
HandlePragmaFPContract();
return nullptr;
+ case tok::annot_pragma_fenv_access:
+ HandlePragmaFEnvAccess();
+ return nullptr;
case tok::annot_pragma_fp:
HandlePragmaFP();
break;
@@ -744,7 +747,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
return ParseObjCAtDirectives(attrs);
case tok::minus:
case tok::plus:
- if (!getLangOpts().ObjC1) {
+ if (!getLangOpts().ObjC) {
Diag(Tok, diag::err_expected_external_declaration);
ConsumeToken();
return nullptr;
@@ -975,7 +978,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
// ObjC2 allows prefix attributes on class interfaces and protocols.
// FIXME: This still needs better diagnostics. We should only accept
// attributes here, no types, etc.
- if (getLangOpts().ObjC2 && Tok.is(tok::at)) {
+ if (getLangOpts().ObjC && Tok.is(tok::at)) {
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (!Tok.isObjCAtKeyword(tok::objc_interface) &&
!Tok.isObjCAtKeyword(tok::objc_protocol)) {
@@ -1519,7 +1522,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
// Look up and classify the identifier. We don't perform any typo-correction
// after a scope specifier, because in general we can't recover from typos
- // there (eg, after correcting 'A::tempalte B<X>::C' [sic], we would need to
+ // there (eg, after correcting 'A::template B<X>::C' [sic], we would need to
// jump back into scope specifier parsing).
Sema::NameClassification Classification = Actions.ClassifyName(
getCurScope(), SS, Name, NameLoc, Next, IsAddressOfOperand,
@@ -1551,7 +1554,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
/// An Objective-C object type followed by '<' is a specialization of
/// a parameterized class type or a protocol-qualified type.
ParsedType Ty = Classification.getType();
- if (getLangOpts().ObjC1 && NextToken().is(tok::less) &&
+ if (getLangOpts().ObjC && NextToken().is(tok::less) &&
(Ty.get()->isObjCObjectType() ||
Ty.get()->isObjCObjectPointerType())) {
// Consume the name.
@@ -1591,7 +1594,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
AnnotateScopeToken(SS, !WasScopeAnnotation);
return ANK_TemplateName;
}
- // Fall through.
+ LLVM_FALLTHROUGH;
case Sema::NC_VarTemplate:
case Sema::NC_FunctionTemplate: {
// We have a type, variable or function template followed by '<'.
@@ -1778,7 +1781,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS,
/// An Objective-C object type followed by '<' is a specialization of
/// a parameterized class type or a protocol-qualified type.
- if (getLangOpts().ObjC1 && NextToken().is(tok::less) &&
+ if (getLangOpts().ObjC && NextToken().is(tok::less) &&
(Ty.get()->isObjCObjectType() ||
Ty.get()->isObjCObjectPointerType())) {
// Consume the name.
@@ -1964,6 +1967,10 @@ void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro,
ArgumentIndex);
}
+void Parser::CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) {
+ Actions.CodeCompleteIncludedFile(Dir, IsAngled);
+}
+
void Parser::CodeCompleteNaturalLanguage() {
Actions.CodeCompleteNaturalLanguage();
}
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 12d7a16a2fc8..2088d4571aad 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -477,7 +477,7 @@ void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) {
// Chop off the L, u, U or 8 prefix
++TokOffs;
--TokLen;
- // FALL THROUGH.
+ LLVM_FALLTHROUGH;
case tok::string_literal:
// FIXME: Exclude the optional ud-suffix from the highlighted range.
HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
diff --git a/lib/Rewrite/RewriteRope.cpp b/lib/Rewrite/RewriteRope.cpp
index 5bc79f3eddc9..e3b47a1c52f8 100644
--- a/lib/Rewrite/RewriteRope.cpp
+++ b/lib/Rewrite/RewriteRope.cpp
@@ -59,7 +59,7 @@ using namespace clang;
///
/// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
/// nodes. This directly represents a chunk of the string with those
-/// RopePieces contatenated.
+/// RopePieces concatenated.
/// RopePieceBTreeInterior - An interior node in the B+ Tree, which manages
/// up to '2*WidthFactor' other nodes in the tree.
@@ -128,7 +128,7 @@ namespace {
/// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
/// nodes. This directly represents a chunk of the string with those
- /// RopePieces contatenated. Since this is a B+Tree, all values (in this case
+ /// RopePieces concatenated. Since this is a B+Tree, all values (in this case
/// instances of RopePiece) are stored in leaves like this. To make iteration
/// over the leaves efficient, they maintain a singly linked list through the
/// NextLeaf field. This allows the B+Tree forward iterator to be constant
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index ed240f4ed292..c818d40c7771 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -114,7 +114,7 @@ static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
//
// Note that this is also a performance optimization. Analyzing
// headers many times can be expensive.
- if (!S.getSourceManager().isInMainFile(AC.getDecl()->getLocStart()))
+ if (!S.getSourceManager().isInMainFile(AC.getDecl()->getBeginLoc()))
return;
UnreachableCodeHandler UC(S);
@@ -252,7 +252,7 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
// Emit diagnostic if a recursive function call is detected for all paths.
if (checkForRecursiveFunctionCall(FD, cfg))
- S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
+ S.Diag(Body->getBeginLoc(), diag::warn_infinite_recursive_function);
}
//===----------------------------------------------------------------------===//
@@ -651,7 +651,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
// Short circuit for compilation speed.
if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
return;
- SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd();
+ SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc();
auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
if (IsCoroutine)
S.Diag(Loc, DiagID) << FSI->CoroutinePromise->getType();
@@ -748,10 +748,10 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
return false;
// Don't suggest a fixit inside macros.
- if (VD->getLocEnd().isMacroID())
+ if (VD->getEndLoc().isMacroID())
return false;
- SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getEndLoc());
// Suggest possible initialization (if any).
std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
@@ -771,19 +771,17 @@ static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,
if (CondVal) {
// If condition is always true, remove all but the 'then'.
Fixit1 = FixItHint::CreateRemoval(
- CharSourceRange::getCharRange(If->getLocStart(),
- Then->getLocStart()));
+ CharSourceRange::getCharRange(If->getBeginLoc(), Then->getBeginLoc()));
if (Else) {
- SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getLocEnd());
- Fixit2 = FixItHint::CreateRemoval(
- SourceRange(ElseKwLoc, Else->getLocEnd()));
+ SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getEndLoc());
+ Fixit2 =
+ FixItHint::CreateRemoval(SourceRange(ElseKwLoc, Else->getEndLoc()));
}
} else {
// If condition is always false, remove all but the 'else'.
if (Else)
- Fixit1 = FixItHint::CreateRemoval(
- CharSourceRange::getCharRange(If->getLocStart(),
- Else->getLocStart()));
+ Fixit1 = FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ If->getBeginLoc(), Else->getBeginLoc()));
else
Fixit1 = FixItHint::CreateRemoval(If->getSourceRange());
}
@@ -797,7 +795,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
switch (Use.getKind()) {
case UninitUse::Always:
- S.Diag(Use.getUser()->getLocStart(), diag::warn_uninit_var)
+ S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var)
<< VD->getDeclName() << IsCapturedByBlock
<< Use.getUser()->getSourceRange();
return;
@@ -809,8 +807,8 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
<< (Use.getKind() == UninitUse::AfterDecl ? 4 : 5)
<< const_cast<DeclContext*>(VD->getLexicalDeclContext())
<< VD->getSourceRange();
- S.Diag(Use.getUser()->getLocStart(), diag::note_uninit_var_use)
- << IsCapturedByBlock << Use.getUser()->getSourceRange();
+ S.Diag(Use.getUser()->getBeginLoc(), diag::note_uninit_var_use)
+ << IsCapturedByBlock << Use.getUser()->getSourceRange();
return;
case UninitUse::Maybe:
@@ -880,8 +878,8 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
if ((BO->getOpcode() == BO_LAnd && I->Output) ||
(BO->getOpcode() == BO_LOr && !I->Output))
// true && y -> y, false || y -> y.
- Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(),
- BO->getOperatorLoc()));
+ Fixit1 = FixItHint::CreateRemoval(
+ SourceRange(BO->getBeginLoc(), BO->getOperatorLoc()));
else
// false && y -> false, true || y -> true.
Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr);
@@ -943,8 +941,8 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)
<< VD->getDeclName() << IsCapturedByBlock << DiagKind
<< Str << I->Output << Range;
- S.Diag(User->getLocStart(), diag::note_uninit_var_use)
- << IsCapturedByBlock << User->getSourceRange();
+ S.Diag(User->getBeginLoc(), diag::note_uninit_var_use)
+ << IsCapturedByBlock << User->getSourceRange();
if (RemoveDiagKind != -1)
S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond)
<< RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
@@ -953,7 +951,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
}
if (!Diagnosed)
- S.Diag(Use.getUser()->getLocStart(), diag::warn_maybe_uninit_var)
+ S.Diag(Use.getUser()->getBeginLoc(), diag::warn_maybe_uninit_var)
<< VD->getDeclName() << IsCapturedByBlock
<< Use.getUser()->getSourceRange();
}
@@ -985,9 +983,8 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
ContainsReference CR(S.Context, DRE);
CR.Visit(Initializer);
if (CR.doesContainReference()) {
- S.Diag(DRE->getLocStart(),
- diag::warn_uninit_self_reference_in_init)
- << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
+ S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
+ << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
return true;
}
}
@@ -996,9 +993,9 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
} else {
const BlockExpr *BE = cast<BlockExpr>(Use.getUser());
if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
- S.Diag(BE->getLocStart(),
+ S.Diag(BE->getBeginLoc(),
diag::warn_uninit_byref_blockvar_captured_by_block)
- << VD->getDeclName();
+ << VD->getDeclName();
else
DiagUninitUse(S, VD, Use, true);
}
@@ -1007,8 +1004,8 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
// the initializer of that declaration & we didn't already suggest
// an initialization fixit.
if (!SuggestInitializationFixit(S, VD))
- S.Diag(VD->getLocStart(), diag::note_var_declared_here)
- << VD->getDeclName();
+ S.Diag(VD->getBeginLoc(), diag::note_var_declared_here)
+ << VD->getDeclName();
return true;
}
@@ -1098,7 +1095,7 @@ namespace {
// attribute in template instantiations as it may not be
// unreachable in all instantiations of the template.
if (!IsTemplateInstantiation)
- S.Diag(AS->getLocStart(),
+ S.Diag(AS->getBeginLoc(),
diag::warn_fallthrough_attr_unreachable);
markFallthroughVisited(AS);
++AnnotatedCnt;
@@ -1156,7 +1153,12 @@ namespace {
bool TraverseDecl(Decl *D) { return true; }
// We analyze lambda bodies separately. Skip them here.
- bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
+ bool TraverseLambdaExpr(LambdaExpr *LE) {
+ // Traverse the captures, but not the body.
+ for (const auto &C : zip(LE->captures(), LE->capture_inits()))
+ TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
+ return true;
+ }
private:
@@ -1266,12 +1268,12 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
IsTemplateInstantiation))
continue;
- S.Diag(Label->getLocStart(),
- PerFunction ? diag::warn_unannotated_fallthrough_per_function
- : diag::warn_unannotated_fallthrough);
+ S.Diag(Label->getBeginLoc(),
+ PerFunction ? diag::warn_unannotated_fallthrough_per_function
+ : diag::warn_unannotated_fallthrough);
if (!AnnotatedCnt) {
- SourceLocation L = Label->getLocStart();
+ SourceLocation L = Label->getBeginLoc();
if (L.isMacroID())
continue;
if (S.getLangOpts().CPlusPlus11) {
@@ -1297,7 +1299,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
}
for (const auto *F : FM.getFallthroughStmts())
- S.Diag(F->getLocStart(), diag::err_fallthrough_attr_invalid_placement);
+ S.Diag(F->getBeginLoc(), diag::err_fallthrough_attr_invalid_placement);
}
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
@@ -1312,11 +1314,10 @@ static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
case Stmt::ObjCForCollectionStmtClass:
return true;
case Stmt::DoStmtClass: {
- const Expr *Cond = cast<DoStmt>(S)->getCond();
- llvm::APSInt Val;
- if (!Cond->EvaluateAsInt(Val, Ctx))
+ Expr::EvalResult Result;
+ if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
return true;
- return Val.getBoolValue();
+ return Result.Val.getInt().getBoolValue();
}
default:
break;
@@ -1394,11 +1395,11 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
// Sort by first use so that we emit the warnings in a deterministic order.
SourceManager &SM = S.getSourceManager();
- llvm::sort(UsesByStmt.begin(), UsesByStmt.end(),
+ llvm::sort(UsesByStmt,
[&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
- return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
- RHS.first->getLocStart());
- });
+ return SM.isBeforeInTranslationUnit(LHS.first->getBeginLoc(),
+ RHS.first->getBeginLoc());
+ });
// Classify the current code body for better warning text.
// This enum should stay in sync with the cases in
@@ -1467,15 +1468,15 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
continue;
// Show the first time the object was read.
- S.Diag(FirstRead->getLocStart(), DiagKind)
- << int(ObjectKind) << KeyProp << int(FunctionKind)
- << FirstRead->getSourceRange();
+ S.Diag(FirstRead->getBeginLoc(), DiagKind)
+ << int(ObjectKind) << KeyProp << int(FunctionKind)
+ << FirstRead->getSourceRange();
// Print all the other accesses as notes.
for (const auto &Use : Uses) {
if (Use.getUseExpr() == FirstRead)
continue;
- S.Diag(Use.getUseExpr()->getLocStart(),
+ S.Diag(Use.getUseExpr()->getBeginLoc(),
diag::note_arc_weak_also_accessed_here)
<< Use.getUseExpr()->getSourceRange();
}
@@ -1538,7 +1539,7 @@ public:
// Prefer a more confident report over a less confident one.
if (a.getKind() != b.getKind())
return a.getKind() > b.getKind();
- return a.getUser()->getLocStart() < b.getUser()->getLocStart();
+ return a.getUser()->getBeginLoc() < b.getUser()->getBeginLoc();
});
for (const auto &U : *vec) {
@@ -1605,7 +1606,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
OptionalNotes getNotes() const {
if (Verbose && CurrentFunction) {
- PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
+ PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
S.PDiag(diag::note_thread_warning_in_fun)
<< CurrentFunction);
return OptionalNotes(1, FNote);
@@ -1616,7 +1617,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
OptionalNotes getNotes(const PartialDiagnosticAt &Note) const {
OptionalNotes ONS(1, Note);
if (Verbose && CurrentFunction) {
- PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
+ PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
S.PDiag(diag::note_thread_warning_in_fun)
<< CurrentFunction);
ONS.push_back(std::move(FNote));
@@ -1630,7 +1631,7 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
ONS.push_back(Note1);
ONS.push_back(Note2);
if (Verbose && CurrentFunction) {
- PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
+ PartialDiagnosticAt FNote(CurrentFunction->getBody()->getBeginLoc(),
S.PDiag(diag::note_thread_warning_in_fun)
<< CurrentFunction);
ONS.push_back(std::move(FNote));
@@ -2068,11 +2069,11 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
}
// Install the logical handler for -Wtautological-overlap-compare
- std::unique_ptr<LogicalErrorHandler> LEH;
+ llvm::Optional<LogicalErrorHandler> LEH;
if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison,
- D->getLocStart())) {
- LEH.reset(new LogicalErrorHandler(S));
- AC.getCFGBuildOptions().Observer = LEH.get();
+ D->getBeginLoc())) {
+ LEH.emplace(S);
+ AC.getCFGBuildOptions().Observer = &*LEH;
}
// Emit delayed diagnostics.
@@ -2145,11 +2146,11 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// Check for thread safety violations
if (P.enableThreadSafetyAnalysis) {
SourceLocation FL = AC.getDecl()->getLocation();
- SourceLocation FEL = AC.getDecl()->getLocEnd();
+ SourceLocation FEL = AC.getDecl()->getEndLoc();
threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
- if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getLocStart()))
+ if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getBeginLoc()))
Reporter.setIssueBetaWarnings(true);
- if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getLocStart()))
+ if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getBeginLoc()))
Reporter.setVerbose(true);
threadSafety::runThreadSafetyAnalysis(AC, Reporter,
@@ -2164,9 +2165,9 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
Analyzer.run(AC);
}
- if (!Diags.isIgnored(diag::warn_uninit_var, D->getLocStart()) ||
- !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getLocStart()) ||
- !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getLocStart())) {
+ if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
+ !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
+ !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc())) {
if (CFG *cfg = AC.getCFG()) {
UninitValsDiagReporter reporter(S);
UninitVariablesAnalysisStats stats;
@@ -2189,29 +2190,29 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
}
bool FallThroughDiagFull =
- !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getLocStart());
+ !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());
bool FallThroughDiagPerFunction = !Diags.isIgnored(
- diag::warn_unannotated_fallthrough_per_function, D->getLocStart());
+ diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc());
if (FallThroughDiagFull || FallThroughDiagPerFunction ||
fscope->HasFallthroughStmt) {
DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
}
if (S.getLangOpts().ObjCWeak &&
- !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart()))
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getBeginLoc()))
diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
// Check for infinite self-recursion in functions
if (!Diags.isIgnored(diag::warn_infinite_recursive_function,
- D->getLocStart())) {
+ D->getBeginLoc())) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
checkRecursiveFunction(S, FD, Body, AC);
}
}
// Check for throw out of non-throwing function.
- if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getLocStart()))
+ if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc()))
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
if (S.getLangOpts().CPlusPlus && isNoexcept(FD))
checkThrowInNonThrowingFunc(S, FD, AC);
@@ -2219,7 +2220,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// If none of the previous checks caused a CFG build, trigger one here
// for -Wtautological-overlap-compare
if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison,
- D->getLocStart())) {
+ D->getBeginLoc())) {
AC.getCFG();
}
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 3d21d79f2b85..5f20af01fb7b 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
if (MSVC)
set_source_files_properties(SemaDeclAttr.cpp PROPERTIES COMPILE_FLAGS /bigobj)
set_source_files_properties(SemaExpr.cpp PROPERTIES COMPILE_FLAGS /bigobj)
+ set_source_files_properties(SemaExprCXX.cpp PROPERTIES COMPILE_FLAGS /bigobj)
set_source_files_properties(SemaTemplate.cpp PROPERTIES COMPILE_FLAGS /bigobj)
endif()
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 8af54b993932..92e65c4b819b 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -20,8 +20,8 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Sema/Sema.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Sema.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -29,6 +29,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -48,6 +49,8 @@ bool CodeCompletionContext::wantConstructorResults() const {
case CCC_Expression:
case CCC_ObjCMessageReceiver:
case CCC_ParenthesizedExpression:
+ case CCC_Symbol:
+ case CCC_SymbolOrNewName:
return true;
case CCC_TopLevel:
@@ -64,8 +67,7 @@ bool CodeCompletionContext::wantConstructorResults() const {
case CCC_ObjCProtocolName:
case CCC_Namespace:
case CCC_Type:
- case CCC_Name:
- case CCC_PotentiallyQualifiedName:
+ case CCC_NewName:
case CCC_MacroName:
case CCC_MacroNameUse:
case CCC_PreprocessorExpression:
@@ -79,6 +81,7 @@ bool CodeCompletionContext::wantConstructorResults() const {
case CCC_ObjCClassMessage:
case CCC_ObjCInterfaceName:
case CCC_ObjCCategoryName:
+ case CCC_IncludedFile:
return false;
}
@@ -126,10 +129,12 @@ StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) {
return "Namespace";
case CCKind::CCC_Type:
return "Type";
- case CCKind::CCC_Name:
- return "Name";
- case CCKind::CCC_PotentiallyQualifiedName:
- return "PotentiallyQualifiedName";
+ case CCKind::CCC_NewName:
+ return "NewName";
+ case CCKind::CCC_Symbol:
+ return "Symbol";
+ case CCKind::CCC_SymbolOrNewName:
+ return "SymbolOrNewName";
case CCKind::CCC_MacroName:
return "MacroName";
case CCKind::CCC_MacroNameUse:
@@ -154,6 +159,8 @@ StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) {
return "ObjCInterfaceName";
case CCKind::CCC_ObjCCategoryName:
return "ObjCCategoryName";
+ case CCKind::CCC_IncludedFile:
+ return "IncludedFile";
case CCKind::CCC_Recovery:
return "Recovery";
}
@@ -265,23 +272,18 @@ CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
return Chunk(CK_ResultType, ResultType);
}
-CodeCompletionString::Chunk
-CodeCompletionString::Chunk::CreateCurrentParameter(
- const char *CurrentParameter) {
+CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter(
+ const char *CurrentParameter) {
return Chunk(CK_CurrentParameter, CurrentParameter);
}
-CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
- unsigned NumChunks,
- unsigned Priority,
- CXAvailabilityKind Availability,
- const char **Annotations,
- unsigned NumAnnotations,
- StringRef ParentName,
- const char *BriefComment)
- : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
- Priority(Priority), Availability(Availability),
- ParentName(ParentName), BriefComment(BriefComment) {
+CodeCompletionString::CodeCompletionString(
+ const Chunk *Chunks, unsigned NumChunks, unsigned Priority,
+ CXAvailabilityKind Availability, const char **Annotations,
+ unsigned NumAnnotations, StringRef ParentName, const char *BriefComment)
+ : NumChunks(NumChunks), NumAnnotations(NumAnnotations), Priority(Priority),
+ Availability(Availability), ParentName(ParentName),
+ BriefComment(BriefComment) {
assert(NumChunks <= 0xffff);
assert(NumAnnotations <= 0xffff);
@@ -289,7 +291,8 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
for (unsigned I = 0; I != NumChunks; ++I)
StoredChunks[I] = Chunks[I];
- const char **StoredAnnotations = reinterpret_cast<const char **>(StoredChunks + NumChunks);
+ const char **StoredAnnotations =
+ reinterpret_cast<const char **>(StoredChunks + NumChunks);
for (unsigned I = 0; I != NumAnnotations; ++I)
StoredAnnotations[I] = Annotations[I];
}
@@ -300,7 +303,7 @@ unsigned CodeCompletionString::getAnnotationCount() const {
const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
if (AnnotationNr < NumAnnotations)
- return reinterpret_cast<const char * const*>(end())[AnnotationNr];
+ return reinterpret_cast<const char *const *>(end())[AnnotationNr];
else
return nullptr;
}
@@ -309,27 +312,33 @@ std::string CodeCompletionString::getAsString() const {
std::string Result;
llvm::raw_string_ostream OS(Result);
- for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
- switch (C->Kind) {
- case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
- case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
-
+ for (const Chunk &C : *this) {
+ switch (C.Kind) {
+ case CK_Optional:
+ OS << "{#" << C.Optional->getAsString() << "#}";
+ break;
+ case CK_Placeholder:
+ OS << "<#" << C.Text << "#>";
+ break;
case CK_Informative:
case CK_ResultType:
- OS << "[#" << C->Text << "#]";
+ OS << "[#" << C.Text << "#]";
+ break;
+ case CK_CurrentParameter:
+ OS << "<#" << C.Text << "#>";
+ break;
+ default:
+ OS << C.Text;
break;
-
- case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
- default: OS << C->Text; break;
}
}
return OS.str();
}
const char *CodeCompletionString::getTypedText() const {
- for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
- if (C->Kind == CK_TypedText)
- return C->Text;
+ for (const Chunk &C : *this)
+ if (C.Kind == CK_TypedText)
+ return C.Text;
return nullptr;
}
@@ -364,7 +373,7 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
// Find the interesting names.
SmallVector<const DeclContext *, 2> Contexts;
while (DC && !DC->isFunctionOrMethod()) {
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
+ if (const auto *ND = dyn_cast<NamedDecl>(DC)) {
if (ND->getIdentifier())
Contexts.push_back(DC);
}
@@ -383,11 +392,11 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
OS << "::";
}
- const DeclContext *CurDC = Contexts[I-1];
- if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
+ const DeclContext *CurDC = Contexts[I - 1];
+ if (const auto *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
CurDC = CatImpl->getCategoryDecl();
- if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
+ if (const auto *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
const ObjCInterfaceDecl *Interface = Cat->getClassInterface();
if (!Interface) {
// Assign an empty StringRef but with non-null data to distinguish
@@ -413,11 +422,9 @@ CodeCompletionString *CodeCompletionBuilder::TakeString() {
sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() +
sizeof(const char *) * Annotations.size(),
alignof(CodeCompletionString));
- CodeCompletionString *Result
- = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
- Priority, Availability,
- Annotations.data(), Annotations.size(),
- ParentName, BriefComment);
+ CodeCompletionString *Result = new (Mem) CodeCompletionString(
+ Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(),
+ Annotations.size(), ParentName, BriefComment);
Chunks.clear();
return Result;
}
@@ -446,8 +453,8 @@ void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) {
Chunks.push_back(Chunk::CreateResultType(ResultType));
}
-void
-CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) {
+void CodeCompletionBuilder::AddCurrentParameterChunk(
+ const char *CurrentParameter) {
Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
}
@@ -477,8 +484,7 @@ void CodeCompletionBuilder::addBriefComment(StringRef Comment) {
//===----------------------------------------------------------------------===//
// Code completion overload candidate implementation
//===----------------------------------------------------------------------===//
-FunctionDecl *
-CodeCompleteConsumer::OverloadCandidate::getFunction() const {
+FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const {
if (getKind() == CK_Function)
return Function;
else if (getKind() == CK_FunctionTemplate)
@@ -494,8 +500,9 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
return Function->getType()->getAs<FunctionType>();
case CK_FunctionTemplate:
- return FunctionTemplate->getTemplatedDecl()->getType()
- ->getAs<FunctionType>();
+ return FunctionTemplate->getTemplatedDecl()
+ ->getType()
+ ->getAs<FunctionType>();
case CK_FunctionType:
return Type;
@@ -510,46 +517,56 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
CodeCompleteConsumer::~CodeCompleteConsumer() = default;
-bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter,
- CodeCompletionResult Result) {
+bool PrintingCodeCompleteConsumer::isResultFilteredOut(
+ StringRef Filter, CodeCompletionResult Result) {
switch (Result.Kind) {
case CodeCompletionResult::RK_Declaration:
return !(Result.Declaration->getIdentifier() &&
- Result.Declaration->getIdentifier()->getName().startswith(Filter));
+ Result.Declaration->getIdentifier()->getName().startswith(Filter));
case CodeCompletionResult::RK_Keyword:
return !StringRef(Result.Keyword).startswith(Filter);
case CodeCompletionResult::RK_Macro:
return !Result.Macro->getName().startswith(Filter);
case CodeCompletionResult::RK_Pattern:
- return !StringRef(Result.Pattern->getAsString()).startswith(Filter);
+ return !(Result.Pattern->getTypedText() &&
+ StringRef(Result.Pattern->getTypedText()).startswith(Filter));
}
llvm_unreachable("Unknown code completion result Kind.");
}
-void
-PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
- CodeCompletionContext Context,
- CodeCompletionResult *Results,
- unsigned NumResults) {
+void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(
+ Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results,
+ unsigned NumResults) {
std::stable_sort(Results, Results + NumResults);
- StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
+ if (!Context.getPreferredType().isNull())
+ OS << "PREFERRED-TYPE: " << Context.getPreferredType().getAsString()
+ << "\n";
- // Print the results.
+ StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
+ // Print the completions.
for (unsigned I = 0; I != NumResults; ++I) {
- if(!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
+ if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
continue;
OS << "COMPLETION: ";
switch (Results[I].Kind) {
case CodeCompletionResult::RK_Declaration:
OS << *Results[I].Declaration;
- if (Results[I].Hidden)
- OS << " (Hidden)";
- if (CodeCompletionString *CCS
- = Results[I].CreateCodeCompletionString(SemaRef, Context,
- getAllocator(),
- CCTUInfo,
- includeBriefComments())) {
+ {
+ std::vector<std::string> Tags;
+ if (Results[I].Hidden)
+ Tags.push_back("Hidden");
+ if (Results[I].InBaseClass)
+ Tags.push_back("InBase");
+ if (Results[I].Availability ==
+ CXAvailabilityKind::CXAvailability_NotAccessible)
+ Tags.push_back("Inaccessible");
+ if (!Tags.empty())
+ OS << " (" << llvm::join(Tags, ",") << ")";
+ }
+ if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(
+ SemaRef, Context, getAllocator(), CCTUInfo,
+ includeBriefComments())) {
OS << " : " << CCS->getAsString();
if (const char *BriefComment = CCS->getBriefComment())
OS << " : " << BriefComment;
@@ -581,19 +598,16 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
case CodeCompletionResult::RK_Macro:
OS << Results[I].Macro->getName();
- if (CodeCompletionString *CCS
- = Results[I].CreateCodeCompletionString(SemaRef, Context,
- getAllocator(),
- CCTUInfo,
- includeBriefComments())) {
+ if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(
+ SemaRef, Context, getAllocator(), CCTUInfo,
+ includeBriefComments())) {
OS << " : " << CCS->getAsString();
}
OS << '\n';
break;
case CodeCompletionResult::RK_Pattern:
- OS << "Pattern : "
- << Results[I].Pattern->getAsString() << '\n';
+ OS << "Pattern : " << Results[I].Pattern->getAsString() << '\n';
break;
}
}
@@ -618,22 +632,29 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) {
OS << "<#" << C.Text << "#>";
break;
- default: OS << C.Text; break;
+ // FIXME: We can also print optional parameters of an overload.
+ case CodeCompletionString::CK_Optional:
+ break;
+
+ default:
+ OS << C.Text;
+ break;
}
}
return OS.str();
}
-void
-PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
- unsigned CurrentArg,
- OverloadCandidate *Candidates,
- unsigned NumCandidates) {
+void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
+ Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
+ unsigned NumCandidates, SourceLocation OpenParLoc) {
+ OS << "OPENING_PAREN_LOC: ";
+ OpenParLoc.print(OS, SemaRef.getSourceManager());
+ OS << "\n";
+
for (unsigned I = 0; I != NumCandidates; ++I) {
- if (CodeCompletionString *CCS
- = Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
- getAllocator(), CCTUInfo,
- includeBriefComments())) {
+ if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
+ CurrentArg, SemaRef, getAllocator(), CCTUInfo,
+ includeBriefComments())) {
OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
}
}
@@ -673,7 +694,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
break;
}
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
+ if (const auto *Function = dyn_cast<FunctionDecl>(Declaration))
if (Function->isDeleted())
Availability = CXAvailability_NotAvailable;
@@ -707,15 +728,15 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
/// saved into Saved and the returned StringRef will refer to it.
StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
switch (Kind) {
- case RK_Keyword:
- return Keyword;
- case RK_Pattern:
- return Pattern->getTypedText();
- case RK_Macro:
- return Macro->getName();
- case RK_Declaration:
- // Handle declarations below.
- break;
+ case RK_Keyword:
+ return Keyword;
+ case RK_Pattern:
+ return Pattern->getTypedText();
+ case RK_Macro:
+ return Macro->getName();
+ case RK_Declaration:
+ // Handle declarations below.
+ break;
}
DeclarationName Name = Declaration->getDeclName();
@@ -725,8 +746,7 @@ StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
return Id->getName();
if (Name.isObjCZeroArgSelector())
- if (IdentifierInfo *Id
- = Name.getObjCSelector().getIdentifierInfoForSlot(0))
+ if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0))
return Id->getName();
Saved = Name.getAsString();
@@ -743,9 +763,5 @@ bool clang::operator<(const CodeCompletionResult &X,
return cmp < 0;
// If case-insensitive comparison fails, try case-sensitive comparison.
- cmp = XStr.compare(YStr);
- if (cmp)
- return cmp < 0;
-
- return false;
+ return XStr.compare(YStr) < 0;
}
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index b22eea2b3642..8b002dac1343 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -156,14 +156,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
unsigned NumParams,
SourceLocation EllipsisLoc,
SourceLocation RParenLoc,
- unsigned TypeQuals,
bool RefQualifierIsLvalueRef,
SourceLocation RefQualifierLoc,
- SourceLocation ConstQualifierLoc,
- SourceLocation
- VolatileQualifierLoc,
- SourceLocation
- RestrictQualifierLoc,
SourceLocation MutableLoc,
ExceptionSpecificationType
ESpecType,
@@ -178,8 +172,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
- TypeResult TrailingReturnType) {
- assert(!(TypeQuals & DeclSpec::TQ_atomic) &&
+ TypeResult TrailingReturnType,
+ DeclSpec *MethodQualifiers) {
+ assert(!(MethodQualifiers && MethodQualifiers->getTypeQualifiers() & DeclSpec::TQ_atomic) &&
"function cannot have _Atomic qualifier");
DeclaratorChunk I;
@@ -193,14 +188,10 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
I.Fun.RParenLoc = RParenLoc.getRawEncoding();
I.Fun.DeleteParams = false;
- I.Fun.TypeQuals = TypeQuals;
I.Fun.NumParams = NumParams;
I.Fun.Params = nullptr;
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
- I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding();
- I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding();
- I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding();
I.Fun.MutableLoc = MutableLoc.getRawEncoding();
I.Fun.ExceptionSpecType = ESpecType;
I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
@@ -211,8 +202,21 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
TrailingReturnType.isInvalid();
I.Fun.TrailingReturnType = TrailingReturnType.get();
+ I.Fun.MethodQualifiers = nullptr;
+ I.Fun.QualAttrFactory = nullptr;
+
+ if (MethodQualifiers && (MethodQualifiers->getTypeQualifiers() ||
+ MethodQualifiers->getAttributes().size())) {
+ auto &attrs = MethodQualifiers->getAttributes();
+ I.Fun.MethodQualifiers = new DeclSpec(attrs.getPool().getFactory());
+ MethodQualifiers->forEachCVRUQualifier(
+ [&](DeclSpec::TQ TypeQual, StringRef PrintName, SourceLocation SL) {
+ I.Fun.MethodQualifiers->SetTypeQual(TypeQual, SL);
+ });
+ I.Fun.MethodQualifiers->getAttributes().takeAllFrom(attrs);
+ I.Fun.MethodQualifiers->getAttributePool().takeAllFrom(attrs.getPool());
+ }
- assert(I.Fun.TypeQuals == TypeQuals && "bitfield overflow");
assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow");
// new[] a parameter array if needed.
@@ -403,6 +407,24 @@ bool Declarator::isCtorOrDtor() {
(getName().getKind() == UnqualifiedIdKind::IK_DestructorName);
}
+void DeclSpec::forEachCVRUQualifier(
+ llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) {
+ if (TypeQualifiers & TQ_const)
+ Handle(TQ_const, "const", TQ_constLoc);
+ if (TypeQualifiers & TQ_volatile)
+ Handle(TQ_volatile, "volatile", TQ_volatileLoc);
+ if (TypeQualifiers & TQ_restrict)
+ Handle(TQ_restrict, "restrict", TQ_restrictLoc);
+ if (TypeQualifiers & TQ_unaligned)
+ Handle(TQ_unaligned, "unaligned", TQ_unalignedLoc);
+}
+
+void DeclSpec::forEachQualifier(
+ llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) {
+ forEachCVRUQualifier(Handle);
+ // FIXME: Add code below to iterate through the attributes and call Handle.
+}
+
bool DeclSpec::hasTagDefinition() const {
if (!TypeSpecOwned)
return false;
@@ -438,7 +460,7 @@ template <class T> static bool BadSpecifier(T TNew, T TPrev,
if (TNew != TPrev)
DiagID = diag::err_invalid_decl_spec_combination;
else
- DiagID = IsExtension ? diag::ext_duplicate_declspec :
+ DiagID = IsExtension ? diag::ext_warn_duplicate_declspec :
diag::warn_duplicate_declspec;
return true;
}
@@ -566,14 +588,16 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
// these storage-class specifiers.
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
// specifiers are not supported."
+ // OpenCL C++ v1.0 s2.9 restricts register.
if (S.getLangOpts().OpenCL &&
!S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
switch (SC) {
case SCS_extern:
case SCS_private_extern:
case SCS_static:
- if (S.getLangOpts().OpenCLVersion < 120) {
- DiagID = diag::err_opencl_unknown_type_specifier;
+ if (S.getLangOpts().OpenCLVersion < 120 &&
+ !S.getLangOpts().OpenCLCPlusPlus) {
+ DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = getSpecifierName(SC);
return true;
}
@@ -860,6 +884,11 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
IsExtension = false;
return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension);
}
+
+ return SetTypeQual(T, Loc);
+}
+
+bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc) {
TypeQualifiers |= T;
switch (T) {
@@ -967,7 +996,7 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID) {
if (isModulePrivateSpecified()) {
PrevSpec = "__module_private__";
- DiagID = diag::ext_duplicate_declspec;
+ DiagID = diag::ext_warn_duplicate_declspec;
return true;
}
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index dba56931d49c..b439f7255728 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -147,7 +147,7 @@ void IdentifierResolver::AddDecl(NamedDecl *D) {
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
- void *Ptr = Name.getFETokenInfo<void>();
+ void *Ptr = Name.getFETokenInfo();
if (!Ptr) {
Name.setFETokenInfo(D);
@@ -172,7 +172,7 @@ void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
- void *Ptr = Name.getFETokenInfo<void>();
+ void *Ptr = Name.getFETokenInfo();
if (!Ptr) {
AddDecl(D);
@@ -213,7 +213,7 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) {
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
- void *Ptr = Name.getFETokenInfo<void>();
+ void *Ptr = Name.getFETokenInfo();
assert(Ptr && "Didn't find this decl on its identifier's chain!");
@@ -232,7 +232,7 @@ IdentifierResolver::begin(DeclarationName Name) {
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
readingIdentifier(*II);
- void *Ptr = Name.getFETokenInfo<void>();
+ void *Ptr = Name.getFETokenInfo();
if (!Ptr) return end();
if (isDeclPtr(Ptr))
@@ -304,7 +304,7 @@ bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
readingIdentifier(*II);
- void *Ptr = Name.getFETokenInfo<void>();
+ void *Ptr = Name.getFETokenInfo();
if (!Ptr) {
Name.setFETokenInfo(D);
@@ -397,7 +397,7 @@ void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {
/// It creates a new IdDeclInfo if one was not created before for this id.
IdentifierResolver::IdDeclInfo &
IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
- void *Ptr = Name.getFETokenInfo<void>();
+ void *Ptr = Name.getFETokenInfo();
if (Ptr) return *toIdDeclInfo(Ptr);
@@ -415,7 +415,7 @@ IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
void IdentifierResolver::iterator::incrementSlowCase() {
NamedDecl *D = **this;
- void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
+ void *InfoPtr = D->getDeclName().getFETokenInfo();
assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 58a7862370cc..a7495e8e0482 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -299,7 +299,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
auto *CS = cast<ObjCForCollectionStmt>(S);
unsigned Diag = diag::note_protected_by_objc_fast_enumeration;
unsigned NewParentScope = Scopes.size();
- Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getLocStart()));
+ Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getBeginLoc()));
BuildScopeInformation(CS->getBody(), NewParentScope);
return;
}
@@ -353,16 +353,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
// Cannot jump into the middle of the condition.
unsigned NewParentScope = Scopes.size();
- Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
+ Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc()));
BuildScopeInformation(IS->getCond(), NewParentScope);
// Jumps into either arm of an 'if constexpr' are not allowed.
NewParentScope = Scopes.size();
- Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
+ Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc()));
BuildScopeInformation(IS->getThen(), NewParentScope);
if (Stmt *Else = IS->getElse()) {
NewParentScope = Scopes.size();
- Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
+ Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getBeginLoc()));
BuildScopeInformation(Else, NewParentScope);
}
return;
@@ -619,11 +619,11 @@ void JumpScopeChecker::VerifyJumps() {
continue;
SourceLocation Loc;
if (CaseStmt *CS = dyn_cast<CaseStmt>(SC))
- Loc = CS->getLocStart();
+ Loc = CS->getBeginLoc();
else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC))
- Loc = DS->getLocStart();
+ Loc = DS->getBeginLoc();
else
- Loc = SC->getLocStart();
+ Loc = SC->getBeginLoc();
CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0,
diag::warn_cxx98_compat_switch_into_protected_scope);
}
@@ -863,7 +863,7 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
// less nested scope. Check if it crosses a __finally along the way.
for (unsigned I = FromScope; I > ToScope; I = Scopes[I].ParentScope) {
if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) {
- S.Diag(From->getLocStart(), diag::warn_jump_out_of_seh_finally);
+ S.Diag(From->getBeginLoc(), diag::warn_jump_out_of_seh_finally);
break;
}
}
diff --git a/lib/Sema/ParsedAttr.cpp b/lib/Sema/ParsedAttr.cpp
index 6509df9985ef..59e5aab677a9 100644
--- a/lib/Sema/ParsedAttr.cpp
+++ b/lib/Sema/ParsedAttr.cpp
@@ -41,8 +41,12 @@ size_t ParsedAttr::allocated_size() const {
else if (IsProperty)
return AttributeFactory::PropertyAllocSize;
else if (HasParsedType)
- return sizeof(ParsedAttr) + sizeof(void *);
- return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion));
+ return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(0, 0, 0, 1, 0);
+ return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(NumArgs, 0, 0, 0, 0);
}
AttributeFactory::AttributeFactory() {
@@ -78,7 +82,7 @@ void AttributeFactory::deallocate(ParsedAttr *Attr) {
if (freeListIndex >= FreeLists.size())
FreeLists.resize(freeListIndex + 1);
-#if !NDEBUG
+#ifndef NDEBUG
// In debug mode, zero out the attribute to help find memory overwriting.
memset(Attr, 0, size);
#endif
@@ -99,15 +103,31 @@ void AttributePool::takePool(AttributePool &pool) {
#include "clang/Sema/AttrParsedAttrKinds.inc"
-static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
+static StringRef normalizeAttrScopeName(StringRef ScopeName,
+ ParsedAttr::Syntax SyntaxUsed) {
+ // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
+ // to be "clang".
+ if (SyntaxUsed == ParsedAttr::AS_CXX11 ||
+ SyntaxUsed == ParsedAttr::AS_C2x) {
+ if (ScopeName == "__gnu__")
+ ScopeName = "gnu";
+ else if (ScopeName == "_Clang")
+ ScopeName = "clang";
+ }
+ return ScopeName;
+}
+
+static StringRef normalizeAttrName(StringRef AttrName,
+ StringRef NormalizedScopeName,
ParsedAttr::Syntax SyntaxUsed) {
// Normalize the attribute name, __foo__ becomes foo. This is only allowable
- // for GNU attributes.
- bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU ||
- ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
- SyntaxUsed == ParsedAttr::AS_C2x) &&
- ScopeName == "gnu");
- if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
+ // for GNU attributes, and attributes using the double square bracket syntax.
+ bool ShouldNormalize =
+ SyntaxUsed == ParsedAttr::AS_GNU ||
+ ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
+ SyntaxUsed == ParsedAttr::AS_C2x) &&
+ (NormalizedScopeName == "gnu" || NormalizedScopeName == "clang"));
+ if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
AttrName.endswith("__"))
AttrName = AttrName.slice(2, AttrName.size() - 2);
@@ -121,7 +141,7 @@ ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
SmallString<64> FullName;
if (ScopeName)
- FullName += ScopeName->getName();
+ FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
@@ -137,9 +157,10 @@ ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
unsigned ParsedAttr::getAttributeSpellingListIndex() const {
// Both variables will be used in tablegen generated
// attribute spell list index matching code.
- StringRef Scope = ScopeName ? ScopeName->getName() : "";
- StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
- (ParsedAttr::Syntax)SyntaxUsed);
+ auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
+ StringRef Scope =
+ ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : "";
+ StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
#include "clang/Sema/AttrSpellingListIndex.inc"
diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp
index 62a83ccb70aa..bd8db6f4ed91 100644
--- a/lib/Sema/ScopeInfo.cpp
+++ b/lib/Sema/ScopeInfo.cpp
@@ -54,6 +54,8 @@ void FunctionScopeInfo::Clear() {
PossiblyUnreachableDiags.clear();
WeakObjectUses.clear();
ModifiedNonNullParams.clear();
+ Blocks.clear();
+ ByrefBlockVars.clear();
}
static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 49f3decc1151..9fa39968625a 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -152,7 +152,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
NSNumberLiteralMethods[I] = nullptr;
- if (getLangOpts().ObjC1)
+ if (getLangOpts().ObjC)
NSAPIObj.reset(new NSAPI(Context));
if (getLangOpts().CPlusPlus)
@@ -167,7 +167,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags));
- // Initilization of data sharing attributes stack for OpenMP
+ // Initialization of data sharing attributes stack for OpenMP
InitDataSharingAttributesStack();
std::unique_ptr<sema::SemaPPCallbacks> Callbacks =
@@ -214,7 +214,7 @@ void Sema::Initialize() {
// Initialize predefined Objective-C types:
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
// If 'SEL' does not yet refer to any declarations, make it refer to the
// predefined 'SEL'.
DeclarationName SEL = &Context.Idents.get("SEL");
@@ -320,6 +320,10 @@ void Sema::Initialize() {
#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \
setOpenCLExtensionForType(Context.Id, Ext);
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ addImplicitTypedef(#ExtType, Context.Id##Ty); \
+ setOpenCLExtensionForType(Context.Id##Ty, #Ext);
+#include "clang/Basic/OpenCLExtensionTypes.def"
};
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
@@ -441,7 +445,7 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) {
if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant,
- E->getLocStart()))
+ E->getBeginLoc()))
return;
// nullptr only exists from C++11 on, so don't warn on its absence earlier.
if (!getLangOpts().CPlusPlus11)
@@ -454,13 +458,13 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) {
// If it is a macro from system header, and if the macro name is not "NULL",
// do not warn.
- SourceLocation MaybeMacroLoc = E->getLocStart();
+ SourceLocation MaybeMacroLoc = E->getBeginLoc();
if (Diags.getSuppressSystemWarnings() &&
SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
!findMacroSpelling(MaybeMacroLoc, "NULL"))
return;
- Diag(E->getLocStart(), diag::warn_zero_as_null_pointer_constant)
+ Diag(E->getBeginLoc(), diag::warn_zero_as_null_pointer_constant)
<< FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
}
@@ -488,7 +492,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue");
#endif
- diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart());
+ diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc());
diagnoseZeroToNullptrConversion(Kind, E);
QualType ExprTy = Context.getCanonicalType(E->getType());
@@ -533,6 +537,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
case Type::STK_Floating: return CK_FloatingToBoolean;
case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
+ case Type::STK_FixedPoint: return CK_FixedPointToBoolean;
}
llvm_unreachable("unknown scalar type kind");
}
@@ -644,7 +649,8 @@ void Sema::getUndefinedButUsed(
continue;
if (FD->isExternallyVisible() &&
!isExternalWithNoLinkageType(FD) &&
- !FD->getMostRecentDecl()->isInlined())
+ !FD->getMostRecentDecl()->isInlined() &&
+ !FD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
if (FD->getBuiltinID())
continue;
@@ -654,7 +660,8 @@ void Sema::getUndefinedButUsed(
continue;
if (VD->isExternallyVisible() &&
!isExternalWithNoLinkageType(VD) &&
- !VD->getMostRecentDecl()->isInline())
+ !VD->getMostRecentDecl()->isInline() &&
+ !VD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
// Skip VarDecls that lack formal definitions but which we know are in
@@ -827,7 +834,9 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() {
/// is parsed. Note that the ASTContext may have already injected some
/// declarations.
void Sema::ActOnStartOfTranslationUnit() {
- if (getLangOpts().ModulesTS) {
+ if (getLangOpts().ModulesTS &&
+ (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface ||
+ getLangOpts().getCompilingModule() == LangOptions::CMK_None)) {
SourceLocation StartOfTU =
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
@@ -922,10 +931,9 @@ void Sema::ActOnEndOfTranslationUnit() {
// All delayed member exception specs should be checked or we end up accepting
// incompatible declarations.
- // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to
- // write out the lists to the AST file (if any).
+ assert(DelayedOverridingExceptionSpecChecks.empty());
+ assert(DelayedEquivalentExceptionSpecChecks.empty());
assert(DelayedDefaultedMemberExceptionSpecs.empty());
- assert(DelayedExceptionSpecChecks.empty());
// All dllexport classes should have been processed already.
assert(DelayedDllExportClasses.empty());
@@ -978,7 +986,8 @@ void Sema::ActOnEndOfTranslationUnit() {
// module declaration by now.
if (getLangOpts().getCompilingModule() ==
LangOptions::CMK_ModuleInterface &&
- ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) {
+ (ModuleScopes.empty() ||
+ ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)) {
// FIXME: Make a better guess as to where to put the module declaration.
Diag(getSourceManager().getLocForStartOfFile(
getSourceManager().getMainFileID()),
@@ -1399,9 +1408,69 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
"Remove assertion if intentionally called in a non-lambda context.");
}
+// Check that the type of the VarDecl has an accessible copy constructor and
+// resolve its destructor's exception spefication.
+static void checkEscapingByref(VarDecl *VD, Sema &S) {
+ QualType T = VD->getType();
+ EnterExpressionEvaluationContext scope(
+ S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+ SourceLocation Loc = VD->getLocation();
+ Expr *VarRef =
+ new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
+ ExprResult Result = S.PerformMoveOrCopyInitialization(
+ InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(),
+ VarRef, /*AllowNRVO=*/true);
+ if (!Result.isInvalid()) {
+ Result = S.MaybeCreateExprWithCleanups(Result);
+ Expr *Init = Result.getAs<Expr>();
+ S.Context.setBlockVarCopyInit(VD, Init, S.canThrow(Init));
+ }
+
+ // The destructor's exception spefication is needed when IRGen generates
+ // block copy/destroy functions. Resolve it here.
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ if (CXXDestructorDecl *DD = RD->getDestructor()) {
+ auto *FPT = DD->getType()->getAs<FunctionProtoType>();
+ S.ResolveExceptionSpec(Loc, FPT);
+ }
+}
+
+static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) {
+ // Set the EscapingByref flag of __block variables captured by
+ // escaping blocks.
+ for (const BlockDecl *BD : FSI.Blocks) {
+ if (BD->doesNotEscape())
+ continue;
+ for (const BlockDecl::Capture &BC : BD->captures()) {
+ VarDecl *VD = BC.getVariable();
+ if (VD->hasAttr<BlocksAttr>())
+ VD->setEscapingByref();
+ }
+ }
+
+ for (VarDecl *VD : FSI.ByrefBlockVars) {
+ // __block variables might require us to capture a copy-initializer.
+ if (!VD->isEscapingByref())
+ continue;
+ // It's currently invalid to ever have a __block variable with an
+ // array type; should we diagnose that here?
+ // Regardless, we don't want to ignore array nesting when
+ // constructing this copy.
+ if (VD->getType()->isStructureOrClassType())
+ checkEscapingByref(VD, S);
+ }
+}
+
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
assert(!FunctionScopes.empty() && "mismatched push/pop!");
+
+ // This function shouldn't be called after popping the current function scope.
+ // markEscapingByrefs calls PerformMoveOrCopyInitialization, which can call
+ // PushFunctionScope, which can cause clearing out PreallocatedFunctionScope
+ // when FunctionScopes is empty.
+ markEscapingByrefs(*FunctionScopes.back(), *this);
+
FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
if (LangOpts.OpenMP)
@@ -1851,6 +1920,34 @@ void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
}
+std::string Sema::getOpenCLExtensionsFromDeclExtMap(FunctionDecl *FD) {
+ if (!OpenCLDeclExtMap.empty())
+ return getOpenCLExtensionsFromExtMap(FD, OpenCLDeclExtMap);
+
+ return "";
+}
+
+std::string Sema::getOpenCLExtensionsFromTypeExtMap(FunctionType *FT) {
+ if (!OpenCLTypeExtMap.empty())
+ return getOpenCLExtensionsFromExtMap(FT, OpenCLTypeExtMap);
+
+ return "";
+}
+
+template <typename T, typename MapT>
+std::string Sema::getOpenCLExtensionsFromExtMap(T *FDT, MapT &Map) {
+ std::string ExtensionNames = "";
+ auto Loc = Map.find(FDT);
+
+ for (auto const& I : Loc->second) {
+ ExtensionNames += I;
+ ExtensionNames += " ";
+ }
+ ExtensionNames.pop_back();
+
+ return ExtensionNames;
+}
+
bool Sema::isOpenCLDisabledDecl(Decl *FD) {
auto Loc = OpenCLDeclExtMap.find(FD);
if (Loc == OpenCLDeclExtMap.end())
@@ -1889,6 +1986,14 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
Decl = TagT->getDecl();
auto Loc = DS.getTypeSpecTypeLoc();
+
+ // Check extensions for vector types.
+ // e.g. double4 is not allowed when cl_khr_fp64 is absent.
+ if (QT->isExtVectorType()) {
+ auto TypePtr = QT->castAs<ExtVectorType>()->getElementType().getTypePtr();
+ return checkOpenCLDisabledTypeOrDecl(TypePtr, Loc, QT, OpenCLTypeExtMap);
+ }
+
if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
return true;
@@ -1899,6 +2004,6 @@ bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) {
IdentifierInfo *FnName = D.getIdentifier();
- return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), FnName,
+ return checkOpenCLDisabledTypeOrDecl(&D, E.getBeginLoc(), FnName,
OpenCLDeclExtMap, 1, D.getSourceRange());
}
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index e06792cae78b..69084589efea 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -1728,6 +1728,22 @@ Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,
return CheckAccess(*this, UseLoc, Entity);
}
+/// Checks implicit access to a member in a structured binding.
+Sema::AccessResult
+Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc,
+ CXXRecordDecl *DecomposedClass,
+ DeclAccessPair Field) {
+ if (!getLangOpts().AccessControl ||
+ Field.getAccess() == AS_public)
+ return AR_accessible;
+
+ AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field,
+ Context.getRecordType(DecomposedClass));
+ Entity.setDiag(diag::err_decomp_decl_inaccessible_field);
+
+ return CheckAccess(*this, UseLoc, Entity);
+}
+
/// Checks access to an overloaded member operator, including
/// conversion operators.
Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
@@ -1861,22 +1877,31 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
/// specifiers into account, but no member access expressions and such.
///
/// \param Target the declaration to check if it can be accessed
-/// \param Ctx the class/context from which to start the search
+/// \param NamingClass the class in which the lookup was started.
+/// \param BaseType type of the left side of member access expression.
+/// \p BaseType and \p NamingClass are used for C++ access control.
+/// Depending on the lookup case, they should be set to the following:
+/// - lhs.target (member access without a qualifier):
+/// \p BaseType and \p NamingClass are both the type of 'lhs'.
+/// - lhs.X::target (member access with a qualifier):
+/// BaseType is the type of 'lhs', NamingClass is 'X'
+/// - X::target (qualified lookup without member access):
+/// BaseType is null, NamingClass is 'X'.
+/// - target (unqualified lookup).
+/// BaseType is null, NamingClass is the parent class of 'target'.
/// \return true if the Target is accessible from the Class, false otherwise.
-bool Sema::IsSimplyAccessible(NamedDecl *Target, DeclContext *Ctx) {
- if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) {
- if (!Target->isCXXClassMember())
- return true;
-
- if (Target->getAccess() == AS_public)
- return true;
- QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
+bool Sema::IsSimplyAccessible(NamedDecl *Target, CXXRecordDecl *NamingClass,
+ QualType BaseType) {
+ // Perform the C++ accessibility checks first.
+ if (Target->isCXXClassMember() && NamingClass) {
+ if (!getLangOpts().CPlusPlus)
+ return false;
// The unprivileged access is AS_none as we don't know how the member was
// accessed, which is described by the access in DeclAccessPair.
// `IsAccessible` will examine the actual access of Target (i.e.
// Decl->getAccess()) when calculating the access.
- AccessTarget Entity(Context, AccessedEntity::Member, Class,
- DeclAccessPair::make(Target, AS_none), qType);
+ AccessTarget Entity(Context, AccessedEntity::Member, NamingClass,
+ DeclAccessPair::make(Target, AS_none), BaseType);
EffectiveContext EC(CurContext);
return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
}
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 1a8a00075306..2bc1b769f77a 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -405,7 +405,7 @@ void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
<< "stack empty";
if (SegmentName &&
- !checkSectionName(SegmentName->getLocStart(), SegmentName->getString()))
+ !checkSectionName(SegmentName->getBeginLoc(), SegmentName->getString()))
return;
Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
}
@@ -520,9 +520,9 @@ attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {
} // end anonymous namespace
-void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute,
- SourceLocation PragmaLoc,
- attr::ParsedSubjectMatchRuleSet Rules) {
+void Sema::ActOnPragmaAttributeAttribute(
+ ParsedAttr &Attribute, SourceLocation PragmaLoc,
+ attr::ParsedSubjectMatchRuleSet Rules) {
SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
// Gather the subject match rules that are supported by the attribute.
SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4>
@@ -622,54 +622,88 @@ void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute,
Diagnostic << attrMatcherRuleListToString(ExtraRules);
}
- PragmaAttributeStack.push_back(
+ if (PragmaAttributeStack.empty()) {
+ Diag(PragmaLoc, diag::err_pragma_attr_attr_no_push);
+ return;
+ }
+
+ PragmaAttributeStack.back().Entries.push_back(
{PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false});
}
-void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) {
+void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace) {
+ PragmaAttributeStack.emplace_back();
+ PragmaAttributeStack.back().Loc = PragmaLoc;
+ PragmaAttributeStack.back().Namespace = Namespace;
+}
+
+void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace) {
if (PragmaAttributeStack.empty()) {
- Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch);
+ Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1;
return;
}
- const PragmaAttributeEntry &Entry = PragmaAttributeStack.back();
- if (!Entry.IsUsed) {
- assert(Entry.Attribute && "Expected an attribute");
- Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
- << Entry.Attribute->getName();
- Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);
+
+ // Dig back through the stack trying to find the most recently pushed group
+ // that in Namespace. Note that this works fine if no namespace is present,
+ // think of push/pops without namespaces as having an implicit "nullptr"
+ // namespace.
+ for (size_t Index = PragmaAttributeStack.size(); Index;) {
+ --Index;
+ if (PragmaAttributeStack[Index].Namespace == Namespace) {
+ for (const PragmaAttributeEntry &Entry :
+ PragmaAttributeStack[Index].Entries) {
+ if (!Entry.IsUsed) {
+ assert(Entry.Attribute && "Expected an attribute");
+ Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
+ << *Entry.Attribute;
+ Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);
+ }
+ }
+ PragmaAttributeStack.erase(PragmaAttributeStack.begin() + Index);
+ return;
+ }
}
- PragmaAttributeStack.pop_back();
+
+ if (Namespace)
+ Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch)
+ << 0 << Namespace->getName();
+ else
+ Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1;
}
void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
if (PragmaAttributeStack.empty())
return;
- for (auto &Entry : PragmaAttributeStack) {
- ParsedAttr *Attribute = Entry.Attribute;
- assert(Attribute && "Expected an attribute");
-
- // Ensure that the attribute can be applied to the given declaration.
- bool Applies = false;
- for (const auto &Rule : Entry.MatchRules) {
- if (Attribute->appliesToDecl(D, Rule)) {
- Applies = true;
- break;
+ for (auto &Group : PragmaAttributeStack) {
+ for (auto &Entry : Group.Entries) {
+ ParsedAttr *Attribute = Entry.Attribute;
+ assert(Attribute && "Expected an attribute");
+
+ // Ensure that the attribute can be applied to the given declaration.
+ bool Applies = false;
+ for (const auto &Rule : Entry.MatchRules) {
+ if (Attribute->appliesToDecl(D, Rule)) {
+ Applies = true;
+ break;
+ }
}
+ if (!Applies)
+ continue;
+ Entry.IsUsed = true;
+ PragmaAttributeCurrentTargetDecl = D;
+ ParsedAttributesView Attrs;
+ Attrs.addAtEnd(Attribute);
+ ProcessDeclAttributeList(S, D, Attrs);
+ PragmaAttributeCurrentTargetDecl = nullptr;
}
- if (!Applies)
- continue;
- Entry.IsUsed = true;
- PragmaAttributeCurrentTargetDecl = D;
- ParsedAttributesView Attrs;
- Attrs.addAtStart(Attribute);
- ProcessDeclAttributeList(S, D, Attrs);
- PragmaAttributeCurrentTargetDecl = nullptr;
}
}
void Sema::PrintPragmaAttributeInstantiationPoint() {
assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");
- Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(),
+ Diags.Report(PragmaAttributeCurrentTargetDecl->getBeginLoc(),
diag::note_pragma_attribute_applied_decl_here);
}
@@ -773,6 +807,18 @@ void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) {
}
}
+void Sema::ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC) {
+ switch (FPC) {
+ case LangOptions::FEA_On:
+ FPFeatures.setAllowFEnvAccess();
+ break;
+ case LangOptions::FEA_Off:
+ FPFeatures.setDisallowFEnvAccess();
+ break;
+ }
+}
+
+
void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
SourceLocation Loc) {
// Visibility calculations will consider the namespace's visibility.
diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp
index 13dd8d936fd2..ffc728898584 100644
--- a/lib/Sema/SemaCUDA.cpp
+++ b/lib/Sema/SemaCUDA.cpp
@@ -48,7 +48,7 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
QualType ConfigQTy = ConfigDecl->getType();
DeclRefExpr *ConfigDR = new (Context)
- DeclRefExpr(ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
+ DeclRefExpr(Context, ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
MarkFunctionReferenced(LLLLoc, ConfigDecl);
return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 4e39d0675471..2354ffe7fbcc 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -209,11 +209,13 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
if (!tag || tag->isDependentContext())
return false;
+ // Grab the tag definition, if there is one.
+ QualType type = Context.getTypeDeclType(tag);
+ tag = type->getAsTagDecl();
+
// If we're currently defining this type, then lookup into the
// type is okay: don't complain that it isn't complete yet.
- QualType type = Context.getTypeDeclType(tag);
- const TagType *tagType = type->getAs<TagType>();
- if (tagType && tagType->isBeingDefined())
+ if (tag->isBeingDefined())
return false;
SourceLocation loc = SS.getLastQualifierNameLoc();
@@ -229,13 +231,13 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
// Fixed enum types are complete, but they aren't valid as scopes
// until we see a definition, so awkwardly pull out this special
// case.
- const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType);
- if (!enumType)
+ auto *EnumD = dyn_cast<EnumDecl>(tag);
+ if (!EnumD)
return false;
- if (enumType->getDecl()->isCompleteDefinition()) {
+ if (EnumD->isCompleteDefinition()) {
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
- if (!hasVisibleDefinition(enumType->getDecl(), &SuggestedDef,
+ if (!hasVisibleDefinition(EnumD, &SuggestedDef,
/*OnlyNeedComplete*/false)) {
// If the user is going to see an error here, recover by making the
// definition visible.
@@ -249,11 +251,11 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
// Try to instantiate the definition, if this is a specialization of an
// enumeration temploid.
- EnumDecl *ED = enumType->getDecl();
- if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
- MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo();
+ if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) {
+ MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo();
if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
- if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED),
+ if (InstantiateEnum(loc, EnumD, Pattern,
+ getTemplateInstantiationArgs(EnumD),
TSK_ImplicitInstantiation)) {
SS.SetInvalid(SS.getRange());
return true;
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index 57aac80f5ad2..0b4645e11c34 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -131,6 +131,9 @@ namespace {
return PlaceholderKind == K;
}
+ // Language specific cast restrictions for address spaces.
+ void checkAddressSpaceCast(QualType SrcType, QualType DestType);
+
void checkCastAlign() {
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
}
@@ -561,7 +564,7 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
Qualifiers *CastAwayQualifiers = nullptr) {
// If the only checking we care about is for Objective-C lifetime qualifiers,
// and we're not in ObjC mode, there's nothing to check.
- if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC1)
+ if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC)
return CastAwayConstnessKind::CACK_None;
if (!DestType->isReferenceType()) {
@@ -1044,6 +1047,17 @@ void CastOperation::CheckStaticCast() {
}
}
+static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) {
+ auto *SrcPtrType = SrcType->getAs<PointerType>();
+ if (!SrcPtrType)
+ return false;
+ auto *DestPtrType = DestType->getAs<PointerType>();
+ if (!DestPtrType)
+ return false;
+ return SrcPtrType->getPointeeType().getAddressSpace() !=
+ DestPtrType->getPointeeType().getAddressSpace();
+}
+
/// TryStaticCast - Check if a static cast can be performed, and do so if
/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
/// and casting away constness.
@@ -1185,7 +1199,9 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
return TC_Failed;
}
}
- Kind = CK_BitCast;
+ Kind = IsAddressSpaceConversion(SrcType, DestType)
+ ? CK_AddressSpaceConversion
+ : CK_BitCast;
return TC_Success;
}
@@ -1264,7 +1280,7 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
}
Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship(
- SrcExpr->getLocStart(), ToType, FromType, DerivedToBase, ObjCConversion,
+ SrcExpr->getBeginLoc(), ToType, FromType, DerivedToBase, ObjCConversion,
ObjCLifetimeConversion);
if (RefResult != Sema::Ref_Compatible) {
if (CStyle || RefResult == Sema::Ref_Incompatible)
@@ -1281,7 +1297,7 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
Kind = CK_DerivedToBase;
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (!Self.IsDerivedFrom(SrcExpr->getLocStart(), SrcExpr->getType(),
+ if (!Self.IsDerivedFrom(SrcExpr->getBeginLoc(), SrcExpr->getType(),
R->getPointeeType(), Paths))
return TC_NotApplicable;
@@ -1964,12 +1980,6 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType,
return Result.isUsable();
}
-static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) {
- return SrcType->isPointerType() && DestType->isPointerType() &&
- SrcType->getAs<PointerType>()->getPointeeType().getAddressSpace() !=
- DestType->getAs<PointerType>()->getPointeeType().getAddressSpace();
-}
-
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
SourceRange OpRange,
@@ -2269,6 +2279,27 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return SuccessResult;
}
+void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) {
+ // In OpenCL only conversions between pointers to objects in overlapping
+ // addr spaces are allowed. v2.0 s6.5.5 - Generic addr space overlaps
+ // with any named one, except for constant.
+ if (Self.getLangOpts().OpenCL) {
+ auto SrcPtrType = SrcType->getAs<PointerType>();
+ if (!SrcPtrType)
+ return;
+ auto DestPtrType = DestType->getAs<PointerType>();
+ if (!DestPtrType)
+ return;
+ if (!DestPtrType->isAddressSpaceOverlapping(*SrcPtrType)) {
+ Self.Diag(OpRange.getBegin(),
+ diag::err_typecheck_incompatible_address_space)
+ << SrcType << DestType << Sema::AA_Casting
+ << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
+ }
+ }
+}
+
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
bool ListInitialization) {
assert(Self.getLangOpts().CPlusPlus);
@@ -2396,6 +2427,8 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
}
}
+ checkAddressSpaceCast(SrcExpr.get()->getType(), DestType);
+
if (isValidCast(tcr)) {
if (Kind == CK_BitCast)
checkCastAlign();
@@ -2482,20 +2515,9 @@ void CastOperation::CheckCStyleCast() {
assert(!SrcType->isPlaceholderType());
- // OpenCL v1 s6.5: Casting a pointer to address space A to a pointer to
- // address space B is illegal.
- if (Self.getLangOpts().OpenCL && DestType->isPointerType() &&
- SrcType->isPointerType()) {
- const PointerType *DestPtr = DestType->getAs<PointerType>();
- if (!DestPtr->isAddressSpaceOverlapping(*SrcType->getAs<PointerType>())) {
- Self.Diag(OpRange.getBegin(),
- diag::err_typecheck_incompatible_address_space)
- << SrcType << DestType << Sema::AA_Casting
- << SrcExpr.get()->getSourceRange();
- SrcExpr = ExprError();
- return;
- }
- }
+ checkAddressSpaceCast(SrcType, DestType);
+ if (SrcExpr.isInvalid())
+ return;
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
diag::err_typecheck_cast_to_incomplete)) {
@@ -2532,10 +2554,11 @@ void CastOperation::CheckCStyleCast() {
// OpenCL v2.0 s6.13.10 - Allow casts from '0' to event_t type.
if (Self.getLangOpts().OpenCL && DestType->isEventT()) {
- llvm::APSInt CastInt;
- if (SrcExpr.get()->EvaluateAsInt(CastInt, Self.Context)) {
+ Expr::EvalResult Result;
+ if (SrcExpr.get()->EvaluateAsInt(Result, Self.Context)) {
+ llvm::APSInt CastInt = Result.Val.getInt();
if (0 == CastInt) {
- Kind = CK_ZeroToOCLEvent;
+ Kind = CK_ZeroToOCLOpaqueType;
return;
}
Self.Diag(OpRange.getBegin(),
@@ -2612,9 +2635,9 @@ void CastOperation::CheckCStyleCast() {
} else if (!SrcType->isArithmeticType()) {
if (!DestType->isIntegralType(Self.Context) &&
DestType->isArithmeticType()) {
- Self.Diag(SrcExpr.get()->getLocStart(),
- diag::err_cast_pointer_to_non_pointer_int)
- << DestType << SrcExpr.get()->getSourceRange();
+ Self.Diag(SrcExpr.get()->getBeginLoc(),
+ diag::err_cast_pointer_to_non_pointer_int)
+ << DestType << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
}
@@ -2623,8 +2646,8 @@ void CastOperation::CheckCStyleCast() {
if (Self.getLangOpts().OpenCL &&
!Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
if (DestType->isHalfType()) {
- Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
- << DestType << SrcExpr.get()->getSourceRange();
+ Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_opencl_cast_to_half)
+ << DestType << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
}
@@ -2644,18 +2667,18 @@ void CastOperation::CheckCStyleCast() {
if (CastPtr->getPointeeType()->isObjCLifetimeType() &&
ExprPtr->getPointeeType()->isObjCLifetimeType() &&
!CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) {
- Self.Diag(SrcExpr.get()->getLocStart(),
+ Self.Diag(SrcExpr.get()->getBeginLoc(),
diag::err_typecheck_incompatible_ownership)
- << SrcType << DestType << Sema::AA_Casting
- << SrcExpr.get()->getSourceRange();
+ << SrcType << DestType << Sema::AA_Casting
+ << SrcExpr.get()->getSourceRange();
return;
}
}
}
else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) {
- Self.Diag(SrcExpr.get()->getLocStart(),
+ Self.Diag(SrcExpr.get()->getBeginLoc(),
diag::err_arc_convesion_of_weak_unavailable)
- << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange();
+ << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
}
@@ -2703,10 +2726,10 @@ static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr,
}
// This is a variant of int **x; const int **y = (const int **)x;
if (qualifiers == -1)
- Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual2)
+ Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual2)
<< SrcType << DestType;
else
- Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual)
+ Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual)
<< TheOffendingSrcType << TheOffendingDestType << qualifiers;
}
@@ -2716,7 +2739,7 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
Expr *CastExpr) {
CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
- Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
+ Op.OpRange = SourceRange(LPLoc, CastExpr->getEndLoc());
if (getLangOpts().CPlusPlus) {
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false,
@@ -2744,7 +2767,7 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
assert(LPLoc.isValid() && "List-initialization shouldn't get here.");
CastOperation Op(*this, Type, CastExpr);
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
- Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
+ Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getEndLoc());
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false);
if (Op.SrcExpr.isInvalid())
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 93dbeab5b034..8dc1fdb76988 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -27,6 +27,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/FormatString.h"
#include "clang/AST/NSAPI.h"
#include "clang/AST/NonTrivialTypeVisitor.h"
#include "clang/AST/OperationKinds.h"
@@ -35,7 +36,6 @@
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/UnresolvedSet.h"
-#include "clang/Analysis/Analyses/FormatString.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
@@ -112,13 +112,13 @@ static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
if (argCount == desiredArgCount) return false;
if (argCount < desiredArgCount)
- return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 /*function call*/ << desiredArgCount << argCount
- << call->getSourceRange();
+ return S.Diag(call->getEndLoc(), diag::err_typecheck_call_too_few_args)
+ << 0 /*function call*/ << desiredArgCount << argCount
+ << call->getSourceRange();
// Highlight all the excess arguments.
- SourceRange range(call->getArg(desiredArgCount)->getLocStart(),
- call->getArg(argCount - 1)->getLocEnd());
+ SourceRange range(call->getArg(desiredArgCount)->getBeginLoc(),
+ call->getArg(argCount - 1)->getEndLoc());
return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args)
<< 0 /*function call*/ << desiredArgCount << argCount
@@ -135,8 +135,8 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
Expr *ValArg = TheCall->getArg(0);
QualType Ty = ValArg->getType();
if (!Ty->isIntegerType()) {
- S.Diag(ValArg->getLocStart(), diag::err_builtin_annotation_first_arg)
- << ValArg->getSourceRange();
+ S.Diag(ValArg->getBeginLoc(), diag::err_builtin_annotation_first_arg)
+ << ValArg->getSourceRange();
return true;
}
@@ -144,8 +144,8 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
Expr *StrArg = TheCall->getArg(1)->IgnoreParenCasts();
StringLiteral *Literal = dyn_cast<StringLiteral>(StrArg);
if (!Literal || !Literal->isAscii()) {
- S.Diag(StrArg->getLocStart(), diag::err_builtin_annotation_second_arg)
- << StrArg->getSourceRange();
+ S.Diag(StrArg->getBeginLoc(), diag::err_builtin_annotation_second_arg)
+ << StrArg->getSourceRange();
return true;
}
@@ -156,7 +156,7 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) {
// We need at least one argument.
if (TheCall->getNumArgs() < 1) {
- S.Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ S.Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
<< 0 << 1 << TheCall->getNumArgs()
<< TheCall->getCallee()->getSourceRange();
return true;
@@ -166,7 +166,7 @@ static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) {
for (Expr *Arg : TheCall->arguments()) {
auto *Literal = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts());
if (!Literal || !Literal->isWide()) {
- S.Diag(Arg->getLocStart(), diag::err_msvc_annotation_wide_str)
+ S.Diag(Arg->getBeginLoc(), diag::err_msvc_annotation_wide_str)
<< Arg->getSourceRange();
return true;
}
@@ -182,7 +182,7 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
return true;
ExprResult Arg(TheCall->getArg(0));
- QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart());
+ QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getBeginLoc());
if (ResultType.isNull())
return true;
@@ -200,7 +200,7 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
ExprResult Arg = TheCall->getArg(I);
QualType Ty = Arg.get()->getType();
if (!Ty->isIntegerType()) {
- S.Diag(Arg.get()->getLocStart(), diag::err_overflow_builtin_must_be_int)
+ S.Diag(Arg.get()->getBeginLoc(), diag::err_overflow_builtin_must_be_int)
<< Ty << Arg.get()->getSourceRange();
return true;
}
@@ -221,7 +221,7 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
const auto *PtrTy = Ty->getAs<PointerType>();
if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() &&
!PtrTy->getPointeeType().isConstQualified())) {
- S.Diag(Arg.get()->getLocStart(),
+ S.Diag(Arg.get()->getBeginLoc(),
diag::err_overflow_builtin_must_be_ptr_int)
<< Ty << Arg.get()->getSourceRange();
return true;
@@ -238,7 +238,8 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
CallExpr *TheCall, unsigned SizeIdx,
- unsigned DstSizeIdx) {
+ unsigned DstSizeIdx,
+ StringRef LikelyMacroName) {
if (TheCall->getNumArgs() <= SizeIdx ||
TheCall->getNumArgs() <= DstSizeIdx)
return;
@@ -246,29 +247,41 @@ static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
const Expr *SizeArg = TheCall->getArg(SizeIdx);
const Expr *DstSizeArg = TheCall->getArg(DstSizeIdx);
- llvm::APSInt Size, DstSize;
+ Expr::EvalResult SizeResult, DstSizeResult;
// find out if both sizes are known at compile time
- if (!SizeArg->EvaluateAsInt(Size, S.Context) ||
- !DstSizeArg->EvaluateAsInt(DstSize, S.Context))
+ if (!SizeArg->EvaluateAsInt(SizeResult, S.Context) ||
+ !DstSizeArg->EvaluateAsInt(DstSizeResult, S.Context))
return;
+ llvm::APSInt Size = SizeResult.Val.getInt();
+ llvm::APSInt DstSize = DstSizeResult.Val.getInt();
+
if (Size.ule(DstSize))
return;
- // confirmed overflow so generate the diagnostic.
- IdentifierInfo *FnName = FDecl->getIdentifier();
- SourceLocation SL = TheCall->getLocStart();
- SourceRange SR = TheCall->getSourceRange();
+ // Confirmed overflow, so generate the diagnostic.
+ StringRef FunctionName = FDecl->getName();
+ SourceLocation SL = TheCall->getBeginLoc();
+ SourceManager &SM = S.getSourceManager();
+ // If we're in an expansion of a macro whose name corresponds to this builtin,
+ // use the simple macro name and location.
+ if (SL.isMacroID() && Lexer::getImmediateMacroName(SL, SM, S.getLangOpts()) ==
+ LikelyMacroName) {
+ FunctionName = LikelyMacroName;
+ SL = SM.getImmediateMacroCallerLoc(SL);
+ }
- S.Diag(SL, diag::warn_memcpy_chk_overflow) << SR << FnName;
+ S.Diag(SL, diag::warn_memcpy_chk_overflow)
+ << FunctionName << DstSize.toString(/*Radix=*/10)
+ << Size.toString(/*Radix=*/10);
}
static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) {
if (checkArgCount(S, BuiltinCall, 2))
return true;
- SourceLocation BuiltinLoc = BuiltinCall->getLocStart();
+ SourceLocation BuiltinLoc = BuiltinCall->getBeginLoc();
Expr *Builtin = BuiltinCall->getCallee()->IgnoreImpCasts();
Expr *Call = BuiltinCall->getArg(0);
Expr *Chain = BuiltinCall->getArg(1);
@@ -375,9 +388,9 @@ static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) {
SourceLocation ErrorLoc;
if (isa<BlockExpr>(BlockArg)) {
BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl();
- ErrorLoc = BD->getParamDecl(ArgCounter)->getLocStart();
+ ErrorLoc = BD->getParamDecl(ArgCounter)->getBeginLoc();
} else if (isa<DeclRefExpr>(BlockArg)) {
- ErrorLoc = cast<DeclRefExpr>(BlockArg)->getLocStart();
+ ErrorLoc = cast<DeclRefExpr>(BlockArg)->getBeginLoc();
}
S.Diag(ErrorLoc,
diag::err_opencl_enqueue_kernel_blocks_non_local_void_args);
@@ -390,8 +403,8 @@ static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) {
static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) {
if (!S.getOpenCLOptions().isEnabled("cl_khr_subgroups")) {
- S.Diag(Call->getLocStart(), diag::err_opencl_requires_extension)
- << 1 << Call->getDirectCallee() << "cl_khr_subgroups";
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
+ << 1 << Call->getDirectCallee() << "cl_khr_subgroups";
return true;
}
return false;
@@ -407,16 +420,14 @@ static bool SemaOpenCLBuiltinNDRangeAndBlock(Sema &S, CallExpr *TheCall) {
// First argument is an ndrange_t type.
Expr *NDRangeArg = TheCall->getArg(0);
if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
- S.Diag(NDRangeArg->getLocStart(),
- diag::err_opencl_builtin_expected_type)
+ S.Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "'ndrange_t'";
return true;
}
Expr *BlockArg = TheCall->getArg(1);
if (!isBlockPointer(BlockArg)) {
- S.Diag(BlockArg->getLocStart(),
- diag::err_opencl_builtin_expected_type)
+ S.Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "block";
return true;
}
@@ -432,8 +443,7 @@ static bool SemaOpenCLBuiltinKernelWorkGroupSize(Sema &S, CallExpr *TheCall) {
Expr *BlockArg = TheCall->getArg(0);
if (!isBlockPointer(BlockArg)) {
- S.Diag(BlockArg->getLocStart(),
- diag::err_opencl_builtin_expected_type)
+ S.Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "block";
return true;
}
@@ -467,7 +477,7 @@ static bool checkOpenCLEnqueueVariadicArgs(Sema &S, CallExpr *TheCall,
// For each argument passed to the block, a corresponding uint needs to
// be passed to describe the size of the local memory.
if (TotalNumArgs != NumBlockParams + NumNonVarArgs) {
- S.Diag(TheCall->getLocStart(),
+ S.Diag(TheCall->getBeginLoc(),
diag::err_opencl_enqueue_kernel_local_size_args);
return true;
}
@@ -507,7 +517,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
unsigned NumArgs = TheCall->getNumArgs();
if (NumArgs < 4) {
- S.Diag(TheCall->getLocStart(), diag::err_typecheck_call_too_few_args);
+ S.Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args);
return true;
}
@@ -518,7 +528,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
// First argument always needs to be a queue_t type.
if (!Arg0->getType()->isQueueT()) {
- S.Diag(TheCall->getArg(0)->getLocStart(),
+ S.Diag(TheCall->getArg(0)->getBeginLoc(),
diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << S.Context.OCLQueueTy;
return true;
@@ -526,7 +536,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
// Second argument always needs to be a kernel_enqueue_flags_t enum value.
if (!Arg1->getType()->isIntegerType()) {
- S.Diag(TheCall->getArg(1)->getLocStart(),
+ S.Diag(TheCall->getArg(1)->getBeginLoc(),
diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)";
return true;
@@ -534,7 +544,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
// Third argument is always an ndrange_t type.
if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
- S.Diag(TheCall->getArg(2)->getLocStart(),
+ S.Diag(TheCall->getArg(2)->getBeginLoc(),
diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "'ndrange_t'";
return true;
@@ -545,7 +555,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
if (NumArgs == 4) {
// check that the last argument is the right block type.
if (!isBlockPointer(Arg3)) {
- S.Diag(Arg3->getLocStart(), diag::err_opencl_builtin_expected_type)
+ S.Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "block";
return true;
}
@@ -553,7 +563,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
const BlockPointerType *BPT =
cast<BlockPointerType>(Arg3->getType().getCanonicalType());
if (BPT->getPointeeType()->getAs<FunctionProtoType>()->getNumParams() > 0) {
- S.Diag(Arg3->getLocStart(),
+ S.Diag(Arg3->getBeginLoc(),
diag::err_opencl_enqueue_kernel_blocks_no_args);
return true;
}
@@ -568,7 +578,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
// check common block argument.
Expr *Arg6 = TheCall->getArg(6);
if (!isBlockPointer(Arg6)) {
- S.Diag(Arg6->getLocStart(), diag::err_opencl_builtin_expected_type)
+ S.Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "block";
return true;
}
@@ -577,7 +587,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
// Forth argument has to be any integer type.
if (!Arg3->getType()->isIntegerType()) {
- S.Diag(TheCall->getArg(3)->getLocStart(),
+ S.Diag(TheCall->getArg(3)->getBeginLoc(),
diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee() << "integer";
return true;
@@ -590,7 +600,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
if (!Arg4->isNullPointerConstant(S.Context,
Expr::NPC_ValueDependentIsNotNull) &&
!Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) {
- S.Diag(TheCall->getArg(4)->getLocStart(),
+ S.Diag(TheCall->getArg(4)->getBeginLoc(),
diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee()
<< S.Context.getPointerType(S.Context.OCLClkEventTy);
@@ -602,7 +612,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
Expr::NPC_ValueDependentIsNotNull) &&
!(Arg5->getType()->isPointerType() &&
Arg5->getType()->getPointeeType()->isClkEventT())) {
- S.Diag(TheCall->getArg(5)->getLocStart(),
+ S.Diag(TheCall->getArg(5)->getBeginLoc(),
diag::err_opencl_builtin_expected_type)
<< TheCall->getDirectCallee()
<< S.Context.getPointerType(S.Context.OCLClkEventTy);
@@ -616,7 +626,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
}
// None of the specific case has been detected, give generic error
- S.Diag(TheCall->getLocStart(),
+ S.Diag(TheCall->getBeginLoc(),
diag::err_opencl_enqueue_kernel_incorrect_args);
return true;
}
@@ -631,7 +641,7 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {
const Expr *Arg0 = Call->getArg(0);
// First argument type should always be pipe.
if (!Arg0->getType()->isPipeType()) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
<< Call->getDirectCallee() << Arg0->getSourceRange();
return true;
}
@@ -650,7 +660,7 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {
case Builtin::BIwork_group_commit_read_pipe:
case Builtin::BIsub_group_commit_read_pipe:
if (!(!AccessQual || AccessQual->isReadOnly())) {
- S.Diag(Arg0->getLocStart(),
+ S.Diag(Arg0->getBeginLoc(),
diag::err_opencl_builtin_pipe_invalid_access_modifier)
<< "read_only" << Arg0->getSourceRange();
return true;
@@ -664,7 +674,7 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {
case Builtin::BIwork_group_commit_write_pipe:
case Builtin::BIsub_group_commit_write_pipe:
if (!(AccessQual && AccessQual->isWriteOnly())) {
- S.Diag(Arg0->getLocStart(),
+ S.Diag(Arg0->getBeginLoc(),
diag::err_opencl_builtin_pipe_invalid_access_modifier)
<< "write_only" << Arg0->getSourceRange();
return true;
@@ -688,7 +698,7 @@ static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
if (!ArgTy ||
!S.Context.hasSameType(
EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
<< Call->getDirectCallee() << S.Context.getPointerType(EltTy)
<< ArgIdx->getType() << ArgIdx->getSourceRange();
return true;
@@ -721,7 +731,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
// read/write_pipe(pipe T, reserve_id_t, uint, T*).
// Check reserve_id_t.
if (!Call->getArg(1)->getType()->isReserveIDT()) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
<< Call->getDirectCallee() << S.Context.OCLReserveIDTy
<< Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
return true;
@@ -731,7 +741,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
const Expr *Arg2 = Call->getArg(2);
if (!Arg2->getType()->isIntegerType() &&
!Arg2->getType()->isUnsignedIntegerType()) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
<< Call->getDirectCallee() << S.Context.UnsignedIntTy
<< Arg2->getType() << Arg2->getSourceRange();
return true;
@@ -742,7 +752,7 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
return true;
} break;
default:
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_arg_num)
<< Call->getDirectCallee() << Call->getSourceRange();
return true;
}
@@ -765,7 +775,7 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) {
// Check the reserve size.
if (!Call->getArg(1)->getType()->isIntegerType() &&
!Call->getArg(1)->getType()->isUnsignedIntegerType()) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
<< Call->getDirectCallee() << S.Context.UnsignedIntTy
<< Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
return true;
@@ -793,7 +803,7 @@ static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) {
// Check reserve_id_t.
if (!Call->getArg(1)->getType()->isReserveIDT()) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
<< Call->getDirectCallee() << S.Context.OCLReserveIDTy
<< Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
return true;
@@ -812,7 +822,7 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
return true;
if (!Call->getArg(0)->getType()->isPipeType()) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
<< Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
return true;
}
@@ -829,7 +839,7 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
CallExpr *Call) {
if (Call->getNumArgs() != 1) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_arg_num)
<< Call->getDirectCallee() << Call->getSourceRange();
return true;
}
@@ -837,11 +847,18 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
auto RT = Call->getArg(0)->getType();
if (!RT->isPointerType() || RT->getPointeeType()
.getAddressSpace() == LangAS::opencl_constant) {
- S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg)
+ S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_invalid_arg)
<< Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
return true;
}
+ if (RT->getPointeeType().getAddressSpace() != LangAS::opencl_generic) {
+ S.Diag(Call->getArg(0)->getBeginLoc(),
+ diag::warn_opencl_generic_address_space_arg)
+ << Call->getDirectCallee()->getNameInfo().getAsString()
+ << Call->getArg(0)->getSourceRange();
+ }
+
RT = RT->getPointeeType();
auto Qual = RT.getQualifiers();
switch (BuiltinID) {
@@ -863,6 +880,66 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
return false;
}
+static ExprResult SemaBuiltinLaunder(Sema &S, CallExpr *TheCall) {
+ if (checkArgCount(S, TheCall, 1))
+ return ExprError();
+
+ // Compute __builtin_launder's parameter type from the argument.
+ // The parameter type is:
+ // * The type of the argument if it's not an array or function type,
+ // Otherwise,
+ // * The decayed argument type.
+ QualType ParamTy = [&]() {
+ QualType ArgTy = TheCall->getArg(0)->getType();
+ if (const ArrayType *Ty = ArgTy->getAsArrayTypeUnsafe())
+ return S.Context.getPointerType(Ty->getElementType());
+ if (ArgTy->isFunctionType()) {
+ return S.Context.getPointerType(ArgTy);
+ }
+ return ArgTy;
+ }();
+
+ TheCall->setType(ParamTy);
+
+ auto DiagSelect = [&]() -> llvm::Optional<unsigned> {
+ if (!ParamTy->isPointerType())
+ return 0;
+ if (ParamTy->isFunctionPointerType())
+ return 1;
+ if (ParamTy->isVoidPointerType())
+ return 2;
+ return llvm::Optional<unsigned>{};
+ }();
+ if (DiagSelect.hasValue()) {
+ S.Diag(TheCall->getBeginLoc(), diag::err_builtin_launder_invalid_arg)
+ << DiagSelect.getValue() << TheCall->getSourceRange();
+ return ExprError();
+ }
+
+ // We either have an incomplete class type, or we have a class template
+ // whose instantiation has not been forced. Example:
+ //
+ // template <class T> struct Foo { T value; };
+ // Foo<int> *p = nullptr;
+ // auto *d = __builtin_launder(p);
+ if (S.RequireCompleteType(TheCall->getBeginLoc(), ParamTy->getPointeeType(),
+ diag::err_incomplete_type))
+ return ExprError();
+
+ assert(ParamTy->getPointeeType()->isObjectType() &&
+ "Unhandled non-object pointer case");
+
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(S.Context, ParamTy, false);
+ ExprResult Arg =
+ S.PerformCopyInitialization(Entity, SourceLocation(), TheCall->getArg(0));
+ if (Arg.isInvalid())
+ return ExprError();
+ TheCall->setArg(0, Arg.get());
+
+ return TheCall;
+}
+
// Emit an error and return true if the current architecture is not in the list
// of supported architectures.
static bool
@@ -872,7 +949,7 @@ CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall,
S.getASTContext().getTargetInfo().getTriple().getArch();
if (llvm::is_contained(SupportedArchs, CurArch))
return false;
- S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported)
+ S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
<< TheCall->getSourceRange();
return true;
}
@@ -915,6 +992,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
break;
case Builtin::BI__va_start: {
switch (Context.getTargetInfo().getTriple().getArch()) {
+ case llvm::Triple::aarch64:
case llvm::Triple::arm:
case llvm::Triple::thumb:
if (SemaBuiltinVAStartARMMicrosoft(TheCall))
@@ -1024,6 +1102,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (checkArgCount(*this, TheCall, 1)) return true;
TheCall->setType(Context.IntTy);
break;
+ case Builtin::BI__builtin_launder:
+ return SemaBuiltinLaunder(*this, TheCall);
case Builtin::BI__sync_fetch_and_add:
case Builtin::BI__sync_fetch_and_add_1:
case Builtin::BI__sync_fetch_and_add_2:
@@ -1127,6 +1207,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__sync_swap_8:
case Builtin::BI__sync_swap_16:
return SemaBuiltinAtomicOverloaded(TheCallResult);
+ case Builtin::BI__sync_synchronize:
+ Diag(TheCall->getBeginLoc(), diag::warn_atomic_implicit_seq_cst)
+ << TheCall->getCallee()->getSourceRange();
+ break;
case Builtin::BI__builtin_nontemporal_load:
case Builtin::BI__builtin_nontemporal_store:
return SemaBuiltinNontemporalOverloaded(TheCallResult);
@@ -1171,7 +1255,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
const QualType PtrArgType = PtrArg->getType();
if (!PtrArgType->isPointerType() ||
!PtrArgType->getPointeeType()->isRecordType()) {
- Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ Diag(PtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
<< PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType
<< "structure pointer";
return ExprError();
@@ -1181,9 +1265,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
const Expr *FnPtrArg = TheCall->getArg(1)->IgnoreImpCasts();
const QualType FnPtrArgType = FnPtrArg->getType();
if (!FnPtrArgType->isPointerType()) {
- Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
- << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
- << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
+ Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 << 2
+ << FnPtrArgType << "'int (*)(const char *, ...)'";
return ExprError();
}
@@ -1191,15 +1275,15 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
FnPtrArgType->getPointeeType()->getAs<FunctionType>();
if (!FuncType) {
- Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
- << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
- << 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
+ Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
+ << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 << 2
+ << FnPtrArgType << "'int (*)(const char *, ...)'";
return ExprError();
}
if (const auto *FT = dyn_cast<FunctionProtoType>(FuncType)) {
if (!FT->getNumParams()) {
- Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
<< FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
<< 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
return ExprError();
@@ -1208,7 +1292,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (!FT->isVariadic() || FT->getReturnType() != Context.IntTy ||
!PT->isPointerType() || !PT->getPointeeType()->isCharType() ||
!PT->getPointeeType().isConstQualified()) {
- Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ Diag(FnPtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
<< FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3
<< 2 << FnPtrArgType << "'int (*)(const char *, ...)'";
return ExprError();
@@ -1222,21 +1306,37 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// check secure string manipulation functions where overflows
// are detectable at compile time
case Builtin::BI__builtin___memcpy_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "memcpy");
+ break;
case Builtin::BI__builtin___memmove_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "memmove");
+ break;
case Builtin::BI__builtin___memset_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "memset");
+ break;
case Builtin::BI__builtin___strlcat_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strlcat");
+ break;
case Builtin::BI__builtin___strlcpy_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strlcpy");
+ break;
case Builtin::BI__builtin___strncat_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strncat");
+ break;
case Builtin::BI__builtin___strncpy_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "strncpy");
+ break;
case Builtin::BI__builtin___stpncpy_chk:
- SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3);
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3, "stpncpy");
break;
case Builtin::BI__builtin___memccpy_chk:
- SemaBuiltinMemChkCall(*this, FDecl, TheCall, 3, 4);
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 3, 4, "memccpy");
break;
case Builtin::BI__builtin___snprintf_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3, "snprintf");
+ break;
case Builtin::BI__builtin___vsnprintf_chk:
- SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3);
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3, "vsnprintf");
break;
case Builtin::BI__builtin_call_with_static_chain:
if (SemaBuiltinCallWithStaticChain(*this, TheCall))
@@ -1259,7 +1359,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
return ExprError();
if (CheckCXXThrowOperand(
- TheCall->getLocStart(),
+ TheCall->getBeginLoc(),
Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()),
TheCall))
return ExprError();
@@ -1273,7 +1373,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// check for the argument.
if (SemaBuiltinRWPipe(*this, TheCall))
return ExprError();
- TheCall->setType(Context.IntTy);
break;
case Builtin::BIreserve_read_pipe:
case Builtin::BIreserve_write_pipe:
@@ -1305,7 +1404,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BIget_pipe_max_packets:
if (SemaBuiltinPipePackets(*this, TheCall))
return ExprError();
- TheCall->setType(Context.UnsignedIntTy);
break;
case Builtin::BIto_global:
case Builtin::BIto_local:
@@ -1477,8 +1575,8 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
TV = Result.getLimitedValue(64);
if ((TV > 63) || (mask & (1ULL << TV)) == 0)
- return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
- << TheCall->getArg(ImmArg)->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
+ << TheCall->getArg(ImmArg)->getSourceRange();
}
if (PtrArgNum >= 0) {
@@ -1503,7 +1601,7 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
if (RHS.isInvalid())
return true;
- if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy,
+ if (DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy, RHSTy,
RHS.get(), AA_Assigning))
return true;
}
@@ -1557,8 +1655,8 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
if (!pointerType) {
- Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
- << PointerArg->getType() << PointerArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
+ << PointerArg->getType() << PointerArg->getSourceRange();
return true;
}
@@ -1574,10 +1672,9 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
CastKind CastNeeded = CK_NoOp;
if (!AddrType.isAtLeastAsQualifiedAs(ValType)) {
CastNeeded = CK_BitCast;
- Diag(DRE->getLocStart(), diag::ext_typecheck_convert_discards_qualifiers)
- << PointerArg->getType()
- << Context.getPointerType(AddrType)
- << AA_Passing << PointerArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
+ << PointerArg->getType() << Context.getPointerType(AddrType)
+ << AA_Passing << PointerArg->getSourceRange();
}
// Finally, do the cast and replace the argument with the corrected version.
@@ -1592,16 +1689,16 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
// In general, we allow ints, floats and pointers to be loaded and stored.
if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
!ValType->isBlockPointerType() && !ValType->isFloatingType()) {
- Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
- << PointerArg->getType() << PointerArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
+ << PointerArg->getType() << PointerArg->getSourceRange();
return true;
}
// But ARM doesn't have instructions to deal with 128-bit versions.
if (Context.getTypeSize(ValType) > MaxWidth) {
assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
- Diag(DRE->getLocStart(), diag::err_atomic_exclusive_builtin_pointer_size)
- << PointerArg->getType() << PointerArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size)
+ << PointerArg->getType() << PointerArg->getSourceRange();
return true;
}
@@ -1614,8 +1711,8 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
case Qualifiers::OCL_Weak:
case Qualifiers::OCL_Strong:
case Qualifiers::OCL_Autoreleasing:
- Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership)
- << ValType << PointerArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
+ << ValType << PointerArg->getSourceRange();
return true;
}
@@ -1715,6 +1812,16 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
BuiltinID == AArch64::BI__builtin_arm_wsrp)
return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
+ // Only check the valid encoding range. Any constant in this range would be
+ // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
+ // an exception for incorrect registers. This matches MSVC behavior.
+ if (BuiltinID == AArch64::BI_ReadStatusReg ||
+ BuiltinID == AArch64::BI_WriteStatusReg)
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
+
+ if (BuiltinID == AArch64::BI__getReg)
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31);
+
if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
@@ -1732,783 +1839,820 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
}
bool Sema::CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall) {
- static const std::map<unsigned, std::vector<StringRef>> ValidCPU = {
- { Hexagon::BI__builtin_HEXAGON_A6_vcmpbeq_notany, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_A6_vminub_RdP, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffb, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffub, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_vsplatrbp, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_vtrunehb_ppp, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_S6_vtrunohb_ppp, {"v62", "v65"} },
+ struct BuiltinAndString {
+ unsigned BuiltinID;
+ const char *Str;
};
- static const std::map<unsigned, std::vector<StringRef>> ValidHVX = {
- { Hexagon::BI__builtin_HEXAGON_V6_extractw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_extractw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_hi, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_hi_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lo, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lo_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lvsplath, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lvsplath_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_not, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_not_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_pred_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsb, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsb_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_valignb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_valignb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vand, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vand_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandqrt, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvqv, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvqv_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvrt, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslhv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslhv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslwv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vaslwv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrhv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vasrwv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vassign, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vassign_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vassignp, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vassignp_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgb, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgb_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguw, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguw_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vcl0h, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vcl0h_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vcl0w, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vcl0w_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vcombine, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vcombine_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vd0, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vd0_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdd0, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdd0_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdelta, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdelta_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlalignb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlalignb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrb, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrb_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlut4, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlut4_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxb, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxb_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmaxw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminb, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminb_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vminw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabus, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpahb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybus, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyih, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmux, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vmux_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgb, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgb_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnavgw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnormamth, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnormamth_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnot, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vnot_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackeb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackeb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackeh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackeh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackob, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackob_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackoh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackoh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrdelta, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrdelta_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B, {"v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vror, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vror_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundhb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundhb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundhub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundhub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundwh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundwh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsathub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsathub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsatwh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsatwh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufeh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufeh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffob, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffob_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufoh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vshufoh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubhw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubhw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsububh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsububh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsububsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv_128B, {"v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubw, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubw_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vswap, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vswap_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackob, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackob_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackub, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackub_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vxor, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vxor_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vzb, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vzb_128B, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vzh, {"v60", "v62", "v65"} },
- { Hexagon::BI__builtin_HEXAGON_V6_vzh_128B, {"v60", "v62", "v65"} },
+ static BuiltinAndString ValidCPU[] = {
+ { Hexagon::BI__builtin_HEXAGON_A6_vcmpbeq_notany, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_A6_vminub_RdP, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfadd, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_F2_dfsub, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_M2_mnaci, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffb, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffub, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S2_mask, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_vsplatrbp, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_vtrunehb_ppp, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_S6_vtrunohb_ppp, "v62,v65,v66" },
+ };
+
+ static BuiltinAndString ValidHVX[] = {
+ { Hexagon::BI__builtin_HEXAGON_V6_hi, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_hi_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lo, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lo_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_extractw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_extractw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplath, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplath_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_not, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_not_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_pred_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddcarrysat, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddcarrysat_128B, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vand, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vand_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvqv, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvqv_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslhv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslhv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslwv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vaslwv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrhv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasr_into, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasr_into_128B, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vasrwv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassign, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassign_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassignp, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vassignp_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgb, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgb_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguw, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguw_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0h, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0h_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0w, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcl0w_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcombine, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vcombine_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vd0, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vd0_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdd0, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdd0_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdelta, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdelta_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrb, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrb_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlut4, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlut4_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxb, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxb_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmaxw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminb, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminb_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vminw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmux, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vmux_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgb, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgb_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnavgw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamth, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamth_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnot, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vnot_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackeh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackob, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackob_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackoh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackoh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw_128B, "v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrdelta, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrdelta_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_128B, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_128B, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B, "v65" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vror, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vror_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrotr, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrotr_128B, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundhub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatdw, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatdw_128B, "v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsathub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsathub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatwh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsatwh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufeh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufeh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffob, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffob_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vshufoh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubhw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv_128B, "v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vswap, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vswap_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackob, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackob_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackub, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackub_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vxor, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vxor_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzb, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzb_128B, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzh, "v60,v62,v65,v66" },
+ { Hexagon::BI__builtin_HEXAGON_V6_vzh_128B, "v60,v62,v65,v66" },
+ };
+
+ // Sort the tables on first execution so we can binary search them.
+ auto SortCmp = [](const BuiltinAndString &LHS, const BuiltinAndString &RHS) {
+ return LHS.BuiltinID < RHS.BuiltinID;
+ };
+ static const bool SortOnce =
+ (llvm::sort(ValidCPU, SortCmp),
+ llvm::sort(ValidHVX, SortCmp), true);
+ (void)SortOnce;
+ auto LowerBoundCmp = [](const BuiltinAndString &BI, unsigned BuiltinID) {
+ return BI.BuiltinID < BuiltinID;
};
const TargetInfo &TI = Context.getTargetInfo();
- auto FC = ValidCPU.find(BuiltinID);
- if (FC != ValidCPU.end()) {
+ const BuiltinAndString *FC =
+ std::lower_bound(std::begin(ValidCPU), std::end(ValidCPU), BuiltinID,
+ LowerBoundCmp);
+ if (FC != std::end(ValidCPU) && FC->BuiltinID == BuiltinID) {
const TargetOptions &Opts = TI.getTargetOpts();
StringRef CPU = Opts.CPU;
if (!CPU.empty()) {
assert(CPU.startswith("hexagon") && "Unexpected CPU name");
CPU.consume_front("hexagon");
- if (llvm::none_of(FC->second, [CPU](StringRef S) { return S == CPU; }))
- return Diag(TheCall->getLocStart(),
+ SmallVector<StringRef, 3> CPUs;
+ StringRef(FC->Str).split(CPUs, ',');
+ if (llvm::none_of(CPUs, [CPU](StringRef S) { return S == CPU; }))
+ return Diag(TheCall->getBeginLoc(),
diag::err_hexagon_builtin_unsupported_cpu);
}
}
- auto FH = ValidHVX.find(BuiltinID);
- if (FH != ValidHVX.end()) {
+ const BuiltinAndString *FH =
+ std::lower_bound(std::begin(ValidHVX), std::end(ValidHVX), BuiltinID,
+ LowerBoundCmp);
+ if (FH != std::end(ValidHVX) && FH->BuiltinID == BuiltinID) {
if (!TI.hasFeature("hvx"))
- return Diag(TheCall->getLocStart(),
+ return Diag(TheCall->getBeginLoc(),
diag::err_hexagon_builtin_requires_hvx);
- bool IsValid = llvm::any_of(FH->second,
+ SmallVector<StringRef, 3> HVXs;
+ StringRef(FH->Str).split(HVXs, ',');
+ bool IsValid = llvm::any_of(HVXs,
[&TI] (StringRef V) {
std::string F = "hvx" + V.str();
return TI.hasFeature(F);
});
if (!IsValid)
- return Diag(TheCall->getLocStart(),
+ return Diag(TheCall->getBeginLoc(),
diag::err_hexagon_builtin_unsupported_hvx);
}
@@ -2517,15 +2661,17 @@ bool Sema::CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall) {
bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
struct ArgInfo {
- ArgInfo(unsigned O, bool S, unsigned W, unsigned A)
- : OpNum(O), IsSigned(S), BitWidth(W), Align(A) {}
- unsigned OpNum = 0;
- bool IsSigned = false;
- unsigned BitWidth = 0;
- unsigned Align = 0;
+ uint8_t OpNum;
+ bool IsSigned;
+ uint8_t BitWidth;
+ uint8_t Align;
+ };
+ struct BuiltinInfo {
+ unsigned BuiltinID;
+ ArgInfo Infos[2];
};
- static const std::map<unsigned, std::vector<ArgInfo>> Infos = {
+ static BuiltinInfo Infos[] = {
{ Hexagon::BI__builtin_circ_ldd, {{ 3, true, 4, 3 }} },
{ Hexagon::BI__builtin_circ_ldw, {{ 3, true, 4, 2 }} },
{ Hexagon::BI__builtin_circ_ldh, {{ 3, true, 4, 1 }} },
@@ -2711,15 +2857,33 @@ bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
{{ 3, false, 1, 0 }} },
};
- auto F = Infos.find(BuiltinID);
- if (F == Infos.end())
+ // Use a dynamically initialized static to sort the table exactly once on
+ // first run.
+ static const bool SortOnce =
+ (llvm::sort(Infos,
+ [](const BuiltinInfo &LHS, const BuiltinInfo &RHS) {
+ return LHS.BuiltinID < RHS.BuiltinID;
+ }),
+ true);
+ (void)SortOnce;
+
+ const BuiltinInfo *F =
+ std::lower_bound(std::begin(Infos), std::end(Infos), BuiltinID,
+ [](const BuiltinInfo &BI, unsigned BuiltinID) {
+ return BI.BuiltinID < BuiltinID;
+ });
+ if (F == std::end(Infos) || F->BuiltinID != BuiltinID)
return false;
bool Error = false;
- for (const ArgInfo &A : F->second) {
- int32_t Min = A.IsSigned ? -(1 << (A.BitWidth-1)) : 0;
- int32_t Max = (1 << (A.IsSigned ? A.BitWidth-1 : A.BitWidth)) - 1;
+ for (const ArgInfo &A : F->Infos) {
+ // Ignore empty ArgInfo elements.
+ if (A.BitWidth == 0)
+ continue;
+
+ int32_t Min = A.IsSigned ? -(1 << (A.BitWidth - 1)) : 0;
+ int32_t Max = (1 << (A.IsSigned ? A.BitWidth - 1 : A.BitWidth)) - 1;
if (!A.Align) {
Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max);
} else {
@@ -2760,7 +2924,7 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break;
case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break;
case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break;
- // MSA instrinsics. Instructions (which the intrinsics maps to) which use the
+ // MSA intrinsics. Instructions (which the intrinsics maps to) which use the
// df/m field.
// These intrinsics take an unsigned 3 bit immediate.
case Mips::BI__builtin_msa_bclri_b:
@@ -2903,14 +3067,14 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Mips::BI__builtin_msa_ldi_h:
case Mips::BI__builtin_msa_ldi_w:
case Mips::BI__builtin_msa_ldi_d: i = 0; l = -512; u = 511; break;
- case Mips::BI__builtin_msa_ld_b: i = 1; l = -512; u = 511; m = 16; break;
- case Mips::BI__builtin_msa_ld_h: i = 1; l = -1024; u = 1022; m = 16; break;
- case Mips::BI__builtin_msa_ld_w: i = 1; l = -2048; u = 2044; m = 16; break;
- case Mips::BI__builtin_msa_ld_d: i = 1; l = -4096; u = 4088; m = 16; break;
- case Mips::BI__builtin_msa_st_b: i = 2; l = -512; u = 511; m = 16; break;
- case Mips::BI__builtin_msa_st_h: i = 2; l = -1024; u = 1022; m = 16; break;
- case Mips::BI__builtin_msa_st_w: i = 2; l = -2048; u = 2044; m = 16; break;
- case Mips::BI__builtin_msa_st_d: i = 2; l = -4096; u = 4088; m = 16; break;
+ case Mips::BI__builtin_msa_ld_b: i = 1; l = -512; u = 511; m = 1; break;
+ case Mips::BI__builtin_msa_ld_h: i = 1; l = -1024; u = 1022; m = 2; break;
+ case Mips::BI__builtin_msa_ld_w: i = 1; l = -2048; u = 2044; m = 4; break;
+ case Mips::BI__builtin_msa_ld_d: i = 1; l = -4096; u = 4088; m = 8; break;
+ case Mips::BI__builtin_msa_st_b: i = 2; l = -512; u = 511; m = 1; break;
+ case Mips::BI__builtin_msa_st_h: i = 2; l = -1024; u = 1022; m = 2; break;
+ case Mips::BI__builtin_msa_st_w: i = 2; l = -2048; u = 2044; m = 4; break;
+ case Mips::BI__builtin_msa_st_d: i = 2; l = -4096; u = 4088; m = 8; break;
}
if (!m)
@@ -2935,15 +3099,22 @@ bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
BuiltinID == PPC::BI__builtin_divdeu;
if (Is64BitBltin && !IsTarget64Bit)
- return Diag(TheCall->getLocStart(), diag::err_64_bit_builtin_32_bit_tgt)
- << TheCall->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
+ << TheCall->getSourceRange();
if ((IsBltinExtDiv && !Context.getTargetInfo().hasFeature("extdiv")) ||
(BuiltinID == PPC::BI__builtin_bpermd &&
!Context.getTargetInfo().hasFeature("bpermd")))
- return Diag(TheCall->getLocStart(), diag::err_ppc_builtin_only_on_pwr7)
+ return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7)
<< TheCall->getSourceRange();
+ auto SemaVSXCheck = [&](CallExpr *TheCall) -> bool {
+ if (!Context.getTargetInfo().hasFeature("vsx"))
+ return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7)
+ << TheCall->getSourceRange();
+ return false;
+ };
+
switch (BuiltinID) {
default: return false;
case PPC::BI__builtin_altivec_crypto_vshasigmaw:
@@ -2962,6 +3133,11 @@ bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case PPC::BI__builtin_vsx_xxpermdi:
case PPC::BI__builtin_vsx_xxsldwi:
return SemaBuiltinVSX(TheCall);
+ case PPC::BI__builtin_unpack_vector_int128:
+ return SemaVSXCheck(TheCall) ||
+ SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
+ case PPC::BI__builtin_pack_vector_int128:
+ return SemaVSXCheck(TheCall);
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
@@ -2973,7 +3149,7 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
llvm::APSInt AbortCode(32);
if (Arg->isIntegerConstantExpr(AbortCode, Context) &&
AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256)
- return Diag(Arg->getLocStart(), diag::err_systemz_invalid_tabort_code)
+ return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code)
<< Arg->getSourceRange();
}
@@ -3037,14 +3213,14 @@ static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) {
// Check if the argument is a string literal.
if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
- return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
<< Arg->getSourceRange();
// Check the contents of the string.
StringRef Feature =
cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
if (!S.Context.getTargetInfo().validateCpuSupports(Feature))
- return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports)
+ return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports)
<< Arg->getSourceRange();
return false;
}
@@ -3057,14 +3233,14 @@ static bool SemaBuiltinCpuIs(Sema &S, CallExpr *TheCall) {
// Check if the argument is a string literal.
if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
- return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
<< Arg->getSourceRange();
// Check the contents of the string.
StringRef Feature =
cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
if (!S.Context.getTargetInfo().validateCpuIs(Feature))
- return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_is)
+ return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is)
<< Arg->getSourceRange();
return false;
}
@@ -3267,8 +3443,8 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
(HasRC && Result.getZExtValue() >= 8 && Result.getZExtValue() <= 11))
return false;
- return Diag(TheCall->getLocStart(), diag::err_x86_builtin_invalid_rounding)
- << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_x86_builtin_invalid_rounding)
+ << Arg->getSourceRange();
}
// Check if the gather/scatter scale is legal.
@@ -3370,8 +3546,8 @@ bool Sema::CheckX86BuiltinGatherScatterScale(unsigned BuiltinID,
if (Result == 1 || Result == 2 || Result == 4 || Result == 8)
return false;
- return Diag(TheCall->getLocStart(), diag::err_x86_builtin_invalid_scale)
- << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_x86_builtin_invalid_scale)
+ << Arg->getSourceRange();
}
static bool isX86_32Builtin(unsigned BuiltinID) {
@@ -3395,7 +3571,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
// Check for 32-bit only builtins on a 64-bit target.
const llvm::Triple &TT = Context.getTargetInfo().getTriple();
if (TT.getArch() != llvm::Triple::x86 && isX86_32Builtin(BuiltinID))
- return Diag(TheCall->getCallee()->getLocStart(),
+ return Diag(TheCall->getCallee()->getBeginLoc(),
diag::err_32_bit_builtin_64_bit_tgt);
// If the intrinsic has rounding or SAE make sure its valid.
@@ -3630,6 +3806,14 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_psrldqi128_byteshift:
case X86::BI__builtin_ia32_psrldqi256_byteshift:
case X86::BI__builtin_ia32_psrldqi512_byteshift:
+ case X86::BI__builtin_ia32_kshiftliqi:
+ case X86::BI__builtin_ia32_kshiftlihi:
+ case X86::BI__builtin_ia32_kshiftlisi:
+ case X86::BI__builtin_ia32_kshiftlidi:
+ case X86::BI__builtin_ia32_kshiftriqi:
+ case X86::BI__builtin_ia32_kshiftrihi:
+ case X86::BI__builtin_ia32_kshiftrisi:
+ case X86::BI__builtin_ia32_kshiftridi:
i = 1; l = 0; u = 255;
break;
case X86::BI__builtin_ia32_vperm2f128_pd256:
@@ -4056,7 +4240,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
CheckAbsoluteValueFunction(TheCall, FDecl);
CheckMaxUnsignedZero(TheCall, FDecl);
- if (getLangOpts().ObjC1)
+ if (getLangOpts().ObjC)
DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs);
unsigned CMId = FDecl->getMemoryFunctionKind();
@@ -4312,15 +4496,15 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
++AdjustedNumArgs;
// Check we have the right number of arguments.
if (TheCall->getNumArgs() < AdjustedNumArgs) {
- Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 << AdjustedNumArgs << TheCall->getNumArgs()
- << TheCall->getCallee()->getSourceRange();
+ Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args)
+ << 0 << AdjustedNumArgs << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
return ExprError();
} else if (TheCall->getNumArgs() > AdjustedNumArgs) {
- Diag(TheCall->getArg(AdjustedNumArgs)->getLocStart(),
+ Diag(TheCall->getArg(AdjustedNumArgs)->getBeginLoc(),
diag::err_typecheck_call_too_many_args)
- << 0 << AdjustedNumArgs << TheCall->getNumArgs()
- << TheCall->getCallee()->getSourceRange();
+ << 0 << AdjustedNumArgs << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
return ExprError();
}
@@ -4333,8 +4517,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Ptr = ConvertedPtr.get();
const PointerType *pointerType = Ptr->getType()->getAs<PointerType>();
if (!pointerType) {
- Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
- << Ptr->getType() << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
+ << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
@@ -4343,13 +4527,13 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
QualType ValType = AtomTy; // 'C'
if (IsC11) {
if (!AtomTy->isAtomicType()) {
- Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic)
- << Ptr->getType() << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_atomic)
+ << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
- if (AtomTy.isConstQualified() ||
+ if ((Form != Load && Form != LoadCopy && AtomTy.isConstQualified()) ||
AtomTy.getAddressSpace() == LangAS::opencl_constant) {
- Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_atomic)
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_non_const_atomic)
<< (AtomTy.isConstQualified() ? 0 : 1) << Ptr->getType()
<< Ptr->getSourceRange();
return ExprError();
@@ -4357,8 +4541,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
ValType = AtomTy->getAs<AtomicType>()->getValueType();
} else if (Form != Load && Form != LoadCopy) {
if (ValType.isConstQualified()) {
- Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer)
- << Ptr->getType() << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_non_const_pointer)
+ << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
}
@@ -4368,33 +4552,33 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// gcc does not enforce these rules for GNU atomics, but we do so for sanity.
if (IsAddSub && !ValType->isIntegerType()
&& !ValType->isPointerType()) {
- Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr)
- << IsC11 << Ptr->getType() << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_atomic_int_or_ptr)
+ << IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
if (IsMinMax) {
const BuiltinType *BT = ValType->getAs<BuiltinType>();
if (!BT || (BT->getKind() != BuiltinType::Int &&
BT->getKind() != BuiltinType::UInt)) {
- Diag(DRE->getLocStart(), diag::err_atomic_op_needs_int32_or_ptr);
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_int32_or_ptr);
return ExprError();
}
}
if (!IsAddSub && !IsMinMax && !ValType->isIntegerType()) {
- Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int)
- << IsC11 << Ptr->getType() << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_bitwise_needs_atomic_int)
+ << IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
if (IsC11 && ValType->isPointerType() &&
- RequireCompleteType(Ptr->getLocStart(), ValType->getPointeeType(),
+ RequireCompleteType(Ptr->getBeginLoc(), ValType->getPointeeType(),
diag::err_incomplete_type)) {
return ExprError();
}
} else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType()) {
// For __atomic_*_n operations, the value type must be a scalar integral or
// pointer type which is 1, 2, 4, 8 or 16 bytes in length.
- Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr)
- << IsC11 << Ptr->getType() << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_atomic_int_or_ptr)
+ << IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
@@ -4402,8 +4586,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
!AtomTy->isScalarType()) {
// For GNU atomics, require a trivially-copyable type. This is not part of
// the GNU atomics specification, but we enforce it for sanity.
- Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy)
- << Ptr->getType() << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_op_needs_trivial_copy)
+ << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
@@ -4418,8 +4602,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
case Qualifiers::OCL_Autoreleasing:
// FIXME: Can this happen? By this point, ValType should be known
// to be trivially copyable.
- Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership)
- << ValType << Ptr->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
+ << ValType << Ptr->getSourceRange();
return ExprError();
}
@@ -4457,7 +4641,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
case 0:
// The first argument is always a pointer. It has a fixed type.
// It is always dereferenced, a nullptr is undefined.
- CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart());
+ CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getBeginLoc());
// Nothing else to do: we already know all we want about this pointer.
continue;
case 1:
@@ -4471,14 +4655,14 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
else if (Form == Copy || Form == Xchg) {
if (IsPassedByAddress)
// The value pointer is always dereferenced, a nullptr is undefined.
- CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart());
+ CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getBeginLoc());
Ty = ByValType;
} else if (Form == Arithmetic)
Ty = Context.getPointerDiffType();
else {
Expr *ValArg = TheCall->getArg(i);
// The value pointer is always dereferenced, a nullptr is undefined.
- CheckNonNullArgument(*this, ValArg, DRE->getLocStart());
+ CheckNonNullArgument(*this, ValArg, DRE->getBeginLoc());
LangAS AS = LangAS::Default;
// Keep address space of non-atomic pointer type.
if (const PointerType *PtrTy =
@@ -4493,7 +4677,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
// The third argument to compare_exchange / GNU exchange is the desired
// value, either by-value (for the C11 and *_n variant) or as a pointer.
if (IsPassedByAddress)
- CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getLocStart());
+ CheckNonNullArgument(*this, TheCall->getArg(i), DRE->getBeginLoc());
Ty = ByValType;
break;
case 3:
@@ -4558,7 +4742,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
llvm::APSInt Result(32);
if (SubExprs[1]->isIntegerConstantExpr(Result, Context) &&
!isValidOrderingForOp(Result.getSExtValue(), Op))
- Diag(SubExprs[1]->getLocStart(),
+ Diag(SubExprs[1]->getBeginLoc(),
diag::warn_atomic_op_has_invalid_memory_order)
<< SubExprs[1]->getSourceRange();
}
@@ -4568,25 +4752,26 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
llvm::APSInt Result(32);
if (Scope->isIntegerConstantExpr(Result, Context) &&
!ScopeModel->isValid(Result.getZExtValue())) {
- Diag(Scope->getLocStart(), diag::err_atomic_op_has_invalid_synch_scope)
+ Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope)
<< Scope->getSourceRange();
}
SubExprs.push_back(Scope);
}
- AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),
- SubExprs, ResultType, Op,
- TheCall->getRParenLoc());
+ AtomicExpr *AE =
+ new (Context) AtomicExpr(TheCall->getCallee()->getBeginLoc(), SubExprs,
+ ResultType, Op, TheCall->getRParenLoc());
if ((Op == AtomicExpr::AO__c11_atomic_load ||
Op == AtomicExpr::AO__c11_atomic_store ||
Op == AtomicExpr::AO__opencl_atomic_load ||
Op == AtomicExpr::AO__opencl_atomic_store ) &&
Context.AtomicUsesUnsupportedLibcall(AE))
- Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib)
+ Diag(AE->getBeginLoc(), diag::err_atomic_load_store_uses_lib)
<< ((Op == AtomicExpr::AO__c11_atomic_load ||
- Op == AtomicExpr::AO__opencl_atomic_load)
- ? 0 : 1);
+ Op == AtomicExpr::AO__opencl_atomic_load)
+ ? 0
+ : 1);
return AE;
}
@@ -4615,25 +4800,24 @@ static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) {
return false;
}
-/// SemaBuiltinAtomicOverloaded - We have a call to a function like
-/// __sync_fetch_and_add, which is an overloaded function based on the pointer
-/// type of its first argument. The main ActOnCallExpr routines have already
-/// promoted the types of arguments because all of these calls are prototyped as
-/// void(...).
+/// We have a call to a function like __sync_fetch_and_add, which is an
+/// overloaded function based on the pointer type of its first argument.
+/// The main ActOnCallExpr routines have already promoted the types of
+/// arguments because all of these calls are prototyped as void(...).
///
/// This function goes through and does final semantic checking for these
-/// builtins,
+/// builtins, as well as generating any warnings.
ExprResult
Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
- CallExpr *TheCall = (CallExpr *)TheCallResult.get();
- DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+ CallExpr *TheCall = static_cast<CallExpr *>(TheCallResult.get());
+ Expr *Callee = TheCall->getCallee();
+ DeclRefExpr *DRE = cast<DeclRefExpr>(Callee->IgnoreParenCasts());
FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
// Ensure that we have at least one argument to do type inference from.
if (TheCall->getNumArgs() < 1) {
- Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
- << 0 << 1 << TheCall->getNumArgs()
- << TheCall->getCallee()->getSourceRange();
+ Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1 << TheCall->getNumArgs() << Callee->getSourceRange();
return ExprError();
}
@@ -4651,21 +4835,21 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>();
if (!pointerType) {
- Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
- << FirstArg->getType() << FirstArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
+ << FirstArg->getType() << FirstArg->getSourceRange();
return ExprError();
}
QualType ValType = pointerType->getPointeeType();
if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
!ValType->isBlockPointerType()) {
- Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr)
- << FirstArg->getType() << FirstArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr)
+ << FirstArg->getType() << FirstArg->getSourceRange();
return ExprError();
}
if (ValType.isConstQualified()) {
- Diag(DRE->getLocStart(), diag::err_atomic_builtin_cannot_be_const)
+ Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_cannot_be_const)
<< FirstArg->getType() << FirstArg->getSourceRange();
return ExprError();
}
@@ -4679,8 +4863,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Qualifiers::OCL_Weak:
case Qualifiers::OCL_Strong:
case Qualifiers::OCL_Autoreleasing:
- Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership)
- << ValType << FirstArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
+ << ValType << FirstArg->getSourceRange();
return ExprError();
}
@@ -4730,8 +4914,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case 8: SizeIndex = 3; break;
case 16: SizeIndex = 4; break;
default:
- Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size)
- << FirstArg->getType() << FirstArg->getSourceRange();
+ Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_pointer_size)
+ << FirstArg->getType() << FirstArg->getSourceRange();
return ExprError();
}
@@ -4908,15 +5092,18 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// Now that we know how many fixed arguments we expect, first check that we
// have at least that many.
if (TheCall->getNumArgs() < 1+NumFixed) {
- Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
- << 0 << 1+NumFixed << TheCall->getNumArgs()
- << TheCall->getCallee()->getSourceRange();
+ Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1 + NumFixed << TheCall->getNumArgs()
+ << Callee->getSourceRange();
return ExprError();
}
+ Diag(TheCall->getEndLoc(), diag::warn_atomic_implicit_seq_cst)
+ << Callee->getSourceRange();
+
if (WarnAboutSemanticsChange) {
- Diag(TheCall->getLocEnd(), diag::warn_sync_fetch_and_nand_semantics_change)
- << TheCall->getCallee()->getSourceRange();
+ Diag(TheCall->getEndLoc(), diag::warn_sync_fetch_and_nand_semantics_change)
+ << Callee->getSourceRange();
}
// Get the decl for the concrete builtin from this, we can tell what the
@@ -4929,7 +5116,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
else {
// Perform builtin lookup to avoid redeclaring it.
DeclarationName DN(&Context.Idents.get(NewBuiltinName));
- LookupResult Res(*this, DN, DRE->getLocStart(), LookupOrdinaryName);
+ LookupResult Res(*this, DN, DRE->getBeginLoc(), LookupOrdinaryName);
LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true);
assert(Res.getFoundDecl());
NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl());
@@ -4961,8 +5148,6 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
TheCall->setArg(i+1, Arg.get());
}
- ASTContext& Context = this->getASTContext();
-
// Create a new DeclRefExpr to refer to the new decl.
DeclRefExpr* NewDRE = DeclRefExpr::Create(
Context,
@@ -5026,7 +5211,7 @@ ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) {
const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
if (!pointerType) {
- Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_must_be_pointer)
+ Diag(DRE->getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer)
<< PointerArg->getType() << PointerArg->getSourceRange();
return ExprError();
}
@@ -5038,7 +5223,7 @@ ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) {
if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
!ValType->isBlockPointerType() && !ValType->isFloatingType() &&
!ValType->isVectorType()) {
- Diag(DRE->getLocStart(),
+ Diag(DRE->getBeginLoc(),
diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector)
<< PointerArg->getType() << PointerArg->getSourceRange();
return ExprError();
@@ -5070,8 +5255,8 @@ bool Sema::CheckObjCString(Expr *Arg) {
StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
if (!Literal || !Literal->isAscii()) {
- Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant)
- << Arg->getSourceRange();
+ Diag(Arg->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)
+ << Arg->getSourceRange();
return true;
}
@@ -5087,8 +5272,8 @@ bool Sema::CheckObjCString(Expr *Arg) {
ToPtr + NumBytes, llvm::strictConversion);
// Check for conversion failure.
if (Result != llvm::conversionOK)
- Diag(Arg->getLocStart(),
- diag::warn_cfstring_truncated) << Arg->getSourceRange();
+ Diag(Arg->getBeginLoc(), diag::warn_cfstring_truncated)
+ << Arg->getSourceRange();
}
return false;
}
@@ -5106,7 +5291,7 @@ ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) {
if (!Literal || (!Literal->isAscii() && !Literal->isUTF8())) {
return ExprError(
- Diag(Arg->getLocStart(), diag::err_os_log_format_not_string_constant)
+ Diag(Arg->getBeginLoc(), diag::err_os_log_format_not_string_constant)
<< Arg->getSourceRange());
}
@@ -5133,7 +5318,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) {
if (IsMSVAStart) {
// Don't allow this in System V ABI functions.
if (CC == CC_X86_64SysV || (!IsWindows && CC != CC_Win64))
- return S.Diag(Fn->getLocStart(),
+ return S.Diag(Fn->getBeginLoc(),
diag::err_ms_va_start_used_in_sysv_function);
} else {
// On x86-64/AArch64 Unix, don't allow this in Win64 ABI functions.
@@ -5142,7 +5327,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) {
// System V ABI functions on Windows.)
if ((IsWindows && CC == CC_X86_64SysV) ||
(!IsWindows && CC == CC_Win64))
- return S.Diag(Fn->getLocStart(),
+ return S.Diag(Fn->getBeginLoc(),
diag::err_va_start_used_in_wrong_abi_function)
<< !IsWindows;
}
@@ -5150,7 +5335,7 @@ static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) {
}
if (IsMSVAStart)
- return S.Diag(Fn->getLocStart(), diag::err_builtin_x64_aarch64_only);
+ return S.Diag(Fn->getBeginLoc(), diag::err_builtin_x64_aarch64_only);
return false;
}
@@ -5173,16 +5358,16 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn,
Params = MD->parameters();
} else if (isa<CapturedDecl>(Caller)) {
// We don't support va_start in a CapturedDecl.
- S.Diag(Fn->getLocStart(), diag::err_va_start_captured_stmt);
+ S.Diag(Fn->getBeginLoc(), diag::err_va_start_captured_stmt);
return true;
} else {
// This must be some other declcontext that parses exprs.
- S.Diag(Fn->getLocStart(), diag::err_va_start_outside_function);
+ S.Diag(Fn->getBeginLoc(), diag::err_va_start_outside_function);
return true;
}
if (!IsVariadic) {
- S.Diag(Fn->getLocStart(), diag::err_va_start_fixed_function);
+ S.Diag(Fn->getBeginLoc(), diag::err_va_start_fixed_function);
return true;
}
@@ -5202,19 +5387,19 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
return true;
if (TheCall->getNumArgs() > 2) {
- Diag(TheCall->getArg(2)->getLocStart(),
+ Diag(TheCall->getArg(2)->getBeginLoc(),
diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << 2 << TheCall->getNumArgs()
- << Fn->getSourceRange()
- << SourceRange(TheCall->getArg(2)->getLocStart(),
- (*(TheCall->arg_end()-1))->getLocEnd());
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << Fn->getSourceRange()
+ << SourceRange(TheCall->getArg(2)->getBeginLoc(),
+ (*(TheCall->arg_end() - 1))->getEndLoc());
return true;
}
if (TheCall->getNumArgs() < 2) {
- return Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_few_args_at_least)
- << 0 /*function call*/ << 2 << TheCall->getNumArgs();
+ return Diag(TheCall->getEndLoc(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs();
}
// Type-check the first argument normally.
@@ -5249,7 +5434,7 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
}
if (!SecondArgIsLastNamedArgument)
- Diag(TheCall->getArg(1)->getLocStart(),
+ Diag(TheCall->getArg(1)->getBeginLoc(),
diag::warn_second_arg_of_va_start_not_last_named_param);
else if (IsCRegister || Type->isReferenceType() ||
Type->isSpecificBuiltinType(BuiltinType::Float) || [=] {
@@ -5266,7 +5451,7 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
unsigned Reason = 0;
if (Type->isReferenceType()) Reason = 1;
else if (IsCRegister) Reason = 2;
- Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason;
+ Diag(Arg->getBeginLoc(), diag::warn_va_start_type_is_undefined) << Reason;
Diag(ParamLoc, diag::note_parameter_type) << Type;
}
@@ -5281,7 +5466,7 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
Expr *Func = Call->getCallee();
if (Call->getNumArgs() < 3)
- return Diag(Call->getLocEnd(),
+ return Diag(Call->getEndLoc(),
diag::err_typecheck_call_too_few_args_at_least)
<< 0 /*function call*/ << 3 << Call->getNumArgs();
@@ -5305,20 +5490,18 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
Context.getPointerType(Context.CharTy.withConst());
if (!Arg1Ty->isPointerType() ||
Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy)
- Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible)
- << Arg1->getType() << ConstCharPtrTy
- << 1 /* different class */
- << 0 /* qualifier difference */
- << 3 /* parameter mismatch */
+ Diag(Arg1->getBeginLoc(), diag::err_typecheck_convert_incompatible)
+ << Arg1->getType() << ConstCharPtrTy << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
<< 2 << Arg1->getType() << ConstCharPtrTy;
const QualType SizeTy = Context.getSizeType();
if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy)
- Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible)
- << Arg2->getType() << SizeTy
- << 1 /* different class */
- << 0 /* qualifier difference */
- << 3 /* parameter mismatch */
+ Diag(Arg2->getBeginLoc(), diag::err_typecheck_convert_incompatible)
+ << Arg2->getType() << SizeTy << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
<< 3 << Arg2->getType() << SizeTy;
return false;
@@ -5328,14 +5511,14 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
/// friends. This is declared to take (...), so we have to check everything.
bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
if (TheCall->getNumArgs() < 2)
- return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 << 2 << TheCall->getNumArgs()/*function call*/;
+ return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args)
+ << 0 << 2 << TheCall->getNumArgs() /*function call*/;
if (TheCall->getNumArgs() > 2)
- return Diag(TheCall->getArg(2)->getLocStart(),
+ return Diag(TheCall->getArg(2)->getBeginLoc(),
diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << 2 << TheCall->getNumArgs()
- << SourceRange(TheCall->getArg(2)->getLocStart(),
- (*(TheCall->arg_end()-1))->getLocEnd());
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << SourceRange(TheCall->getArg(2)->getBeginLoc(),
+ (*(TheCall->arg_end() - 1))->getEndLoc());
ExprResult OrigArg0 = TheCall->getArg(0);
ExprResult OrigArg1 = TheCall->getArg(1);
@@ -5358,10 +5541,11 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
// If the common type isn't a real floating type, then the arguments were
// invalid for this operation.
if (Res.isNull() || !Res->isRealFloatingType())
- return Diag(OrigArg0.get()->getLocStart(),
+ return Diag(OrigArg0.get()->getBeginLoc(),
diag::err_typecheck_call_invalid_ordered_compare)
- << OrigArg0.get()->getType() << OrigArg1.get()->getType()
- << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd());
+ << OrigArg0.get()->getType() << OrigArg1.get()->getType()
+ << SourceRange(OrigArg0.get()->getBeginLoc(),
+ OrigArg1.get()->getEndLoc());
return false;
}
@@ -5372,14 +5556,14 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
/// value.
bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
if (TheCall->getNumArgs() < NumArgs)
- return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 << NumArgs << TheCall->getNumArgs()/*function call*/;
+ return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args)
+ << 0 << NumArgs << TheCall->getNumArgs() /*function call*/;
if (TheCall->getNumArgs() > NumArgs)
- return Diag(TheCall->getArg(NumArgs)->getLocStart(),
+ return Diag(TheCall->getArg(NumArgs)->getBeginLoc(),
diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << NumArgs << TheCall->getNumArgs()
- << SourceRange(TheCall->getArg(NumArgs)->getLocStart(),
- (*(TheCall->arg_end()-1))->getLocEnd());
+ << 0 /*function call*/ << NumArgs << TheCall->getNumArgs()
+ << SourceRange(TheCall->getArg(NumArgs)->getBeginLoc(),
+ (*(TheCall->arg_end() - 1))->getEndLoc());
Expr *OrigArg = TheCall->getArg(NumArgs-1);
@@ -5388,9 +5572,9 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
// This operation requires a non-_Complex floating-point number.
if (!OrigArg->getType()->isRealFloatingType())
- return Diag(OrigArg->getLocStart(),
+ return Diag(OrigArg->getBeginLoc(),
diag::err_typecheck_call_invalid_unary_fp)
- << OrigArg->getType() << OrigArg->getSourceRange();
+ << OrigArg->getType() << OrigArg->getSourceRange();
// If this is an implicit conversion from float -> float, double, or
// long double, remove it.
@@ -5424,13 +5608,13 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
unsigned ExpectedNumArgs = 3;
if (TheCall->getNumArgs() < ExpectedNumArgs)
- return Diag(TheCall->getLocEnd(),
+ return Diag(TheCall->getEndLoc(),
diag::err_typecheck_call_too_few_args_at_least)
- << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
+ << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
<< TheCall->getSourceRange();
if (TheCall->getNumArgs() > ExpectedNumArgs)
- return Diag(TheCall->getLocEnd(),
+ return Diag(TheCall->getEndLoc(),
diag::err_typecheck_call_too_many_args_at_most)
<< 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
<< TheCall->getSourceRange();
@@ -5438,31 +5622,31 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
// Check the third argument is a compile time constant
llvm::APSInt Value;
if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context))
- return Diag(TheCall->getLocStart(),
+ return Diag(TheCall->getBeginLoc(),
diag::err_vsx_builtin_nonconstant_argument)
<< 3 /* argument index */ << TheCall->getDirectCallee()
- << SourceRange(TheCall->getArg(2)->getLocStart(),
- TheCall->getArg(2)->getLocEnd());
+ << SourceRange(TheCall->getArg(2)->getBeginLoc(),
+ TheCall->getArg(2)->getEndLoc());
QualType Arg1Ty = TheCall->getArg(0)->getType();
QualType Arg2Ty = TheCall->getArg(1)->getType();
// Check the type of argument 1 and argument 2 are vectors.
- SourceLocation BuiltinLoc = TheCall->getLocStart();
+ SourceLocation BuiltinLoc = TheCall->getBeginLoc();
if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
(!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee()
- << SourceRange(TheCall->getArg(0)->getLocStart(),
- TheCall->getArg(1)->getLocEnd());
+ << SourceRange(TheCall->getArg(0)->getBeginLoc(),
+ TheCall->getArg(1)->getEndLoc());
}
// Check the first two arguments are the same type.
if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
- << SourceRange(TheCall->getArg(0)->getLocStart(),
- TheCall->getArg(1)->getLocEnd());
+ << SourceRange(TheCall->getArg(0)->getBeginLoc(),
+ TheCall->getArg(1)->getEndLoc());
}
// When default clang type checking is turned off and the customized type
@@ -5477,7 +5661,7 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
// This is declared to take (...), so we have to check everything.
ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (TheCall->getNumArgs() < 2)
- return ExprError(Diag(TheCall->getLocEnd(),
+ return ExprError(Diag(TheCall->getEndLoc(),
diag::err_typecheck_call_too_few_args_at_least)
<< 0 /*function call*/ << 2 << TheCall->getNumArgs()
<< TheCall->getSourceRange());
@@ -5494,11 +5678,11 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
QualType RHSType = TheCall->getArg(1)->getType();
if (!LHSType->isVectorType() || !RHSType->isVectorType())
- return ExprError(Diag(TheCall->getLocStart(),
- diag::err_vec_builtin_non_vector)
- << TheCall->getDirectCallee()
- << SourceRange(TheCall->getArg(0)->getLocStart(),
- TheCall->getArg(1)->getLocEnd()));
+ return ExprError(
+ Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector)
+ << TheCall->getDirectCallee()
+ << SourceRange(TheCall->getArg(0)->getBeginLoc(),
+ TheCall->getArg(1)->getEndLoc()));
numElements = LHSType->getAs<VectorType>()->getNumElements();
unsigned numResElements = TheCall->getNumArgs() - 2;
@@ -5509,17 +5693,17 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (TheCall->getNumArgs() == 2) {
if (!RHSType->hasIntegerRepresentation() ||
RHSType->getAs<VectorType>()->getNumElements() != numElements)
- return ExprError(Diag(TheCall->getLocStart(),
+ return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
- << SourceRange(TheCall->getArg(1)->getLocStart(),
- TheCall->getArg(1)->getLocEnd()));
+ << SourceRange(TheCall->getArg(1)->getBeginLoc(),
+ TheCall->getArg(1)->getEndLoc()));
} else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
- return ExprError(Diag(TheCall->getLocStart(),
+ return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
- << SourceRange(TheCall->getArg(0)->getLocStart(),
- TheCall->getArg(1)->getLocEnd()));
+ << SourceRange(TheCall->getArg(0)->getBeginLoc(),
+ TheCall->getArg(1)->getEndLoc()));
} else if (numElements != numResElements) {
QualType eltType = LHSType->getAs<VectorType>()->getElementType();
resType = Context.getVectorType(eltType, numResElements,
@@ -5534,7 +5718,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
llvm::APSInt Result(32);
if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
- return ExprError(Diag(TheCall->getLocStart(),
+ return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_shufflevector_nonconstant_argument)
<< TheCall->getArg(i)->getSourceRange());
@@ -5543,7 +5727,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
continue;
if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
- return ExprError(Diag(TheCall->getLocStart(),
+ return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_shufflevector_argument_too_large)
<< TheCall->getArg(i)->getSourceRange());
}
@@ -5556,7 +5740,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
}
return new (Context) ShuffleVectorExpr(Context, exprs, resType,
- TheCall->getCallee()->getLocStart(),
+ TheCall->getCallee()->getBeginLoc(),
TheCall->getRParenLoc());
}
@@ -5597,10 +5781,9 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
unsigned NumArgs = TheCall->getNumArgs();
if (NumArgs > 3)
- return Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_many_args_at_most)
- << 0 /*function call*/ << 3 << NumArgs
- << TheCall->getSourceRange();
+ return Diag(TheCall->getEndLoc(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /*function call*/ << 3 << NumArgs << TheCall->getSourceRange();
// Argument 0 is checked for us and the remaining arguments must be
// constant integers.
@@ -5619,9 +5802,9 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) {
if (Arg->isInstantiationDependent()) return false;
if (Arg->HasSideEffects(Context))
- Diag(Arg->getLocStart(), diag::warn_assume_side_effects)
- << Arg->getSourceRange()
- << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier();
+ Diag(Arg->getBeginLoc(), diag::warn_assume_side_effects)
+ << Arg->getSourceRange()
+ << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier();
return false;
}
@@ -5637,26 +5820,24 @@ bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) {
if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
if (const auto *UE =
dyn_cast<UnaryExprOrTypeTraitExpr>(Arg->IgnoreParenImpCasts()))
- if (UE->getKind() == UETT_AlignOf)
- Diag(TheCall->getLocStart(), diag::warn_alloca_align_alignof)
- << Arg->getSourceRange();
+ if (UE->getKind() == UETT_AlignOf ||
+ UE->getKind() == UETT_PreferredAlignOf)
+ Diag(TheCall->getBeginLoc(), diag::warn_alloca_align_alignof)
+ << Arg->getSourceRange();
llvm::APSInt Result = Arg->EvaluateKnownConstInt(Context);
if (!Result.isPowerOf2())
- return Diag(TheCall->getLocStart(),
- diag::err_alignment_not_power_of_two)
- << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two)
+ << Arg->getSourceRange();
if (Result < Context.getCharWidth())
- return Diag(TheCall->getLocStart(), diag::err_alignment_too_small)
- << (unsigned)Context.getCharWidth()
- << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_alignment_too_small)
+ << (unsigned)Context.getCharWidth() << Arg->getSourceRange();
if (Result > std::numeric_limits<int32_t>::max())
- return Diag(TheCall->getLocStart(), diag::err_alignment_too_big)
- << std::numeric_limits<int32_t>::max()
- << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_alignment_too_big)
+ << std::numeric_limits<int32_t>::max() << Arg->getSourceRange();
}
return false;
@@ -5668,10 +5849,9 @@ bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
unsigned NumArgs = TheCall->getNumArgs();
if (NumArgs > 3)
- return Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_many_args_at_most)
- << 0 /*function call*/ << 3 << NumArgs
- << TheCall->getSourceRange();
+ return Diag(TheCall->getEndLoc(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /*function call*/ << 3 << NumArgs << TheCall->getSourceRange();
// The alignment must be a constant integer.
Expr *Arg = TheCall->getArg(1);
@@ -5683,9 +5863,8 @@ bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
return true;
if (!Result.isPowerOf2())
- return Diag(TheCall->getLocStart(),
- diag::err_alignment_not_power_of_two)
- << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two)
+ << Arg->getSourceRange();
}
if (NumArgs > 2) {
@@ -5708,12 +5887,12 @@ bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) {
unsigned NumArgs = TheCall->getNumArgs();
unsigned NumRequiredArgs = IsSizeCall ? 1 : 2;
if (NumArgs < NumRequiredArgs) {
- return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args)
<< 0 /* function call */ << NumRequiredArgs << NumArgs
<< TheCall->getSourceRange();
}
if (NumArgs >= NumRequiredArgs + 0x100) {
- return Diag(TheCall->getLocEnd(),
+ return Diag(TheCall->getEndLoc(),
diag::err_typecheck_call_too_many_args_at_most)
<< 0 /* function call */ << (NumRequiredArgs + 0xff) << NumArgs
<< TheCall->getSourceRange();
@@ -5751,7 +5930,7 @@ bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) {
return true;
CharUnits ArgSize = Context.getTypeSizeInChars(Arg.get()->getType());
if (ArgSize.getQuantity() >= 0x100) {
- return Diag(Arg.get()->getLocEnd(), diag::err_os_log_argument_too_big)
+ return Diag(Arg.get()->getEndLoc(), diag::err_os_log_argument_too_big)
<< i << (int)ArgSize.getQuantity() << 0xff
<< TheCall->getSourceRange();
}
@@ -5766,7 +5945,7 @@ bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) {
ArrayRef<const Expr *> Args(TheCall->getArgs(), TheCall->getNumArgs());
bool Success = CheckFormatArguments(
Args, /*HasVAListArg*/ false, FormatIdx, FirstDataArg, FST_OSLog,
- VariadicFunction, TheCall->getLocStart(), SourceRange(),
+ VariadicFunction, TheCall->getBeginLoc(), SourceRange(),
CheckedVarArgs);
if (!Success)
return true;
@@ -5791,8 +5970,8 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
if (Arg->isTypeDependent() || Arg->isValueDependent()) return false;
if (!Arg->isIntegerConstantExpr(Result, Context))
- return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type)
- << FDecl->getDeclName() << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_constant_integer_arg_type)
+ << FDecl->getDeclName() << Arg->getSourceRange();
return false;
}
@@ -5814,15 +5993,15 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
if (Result.getSExtValue() < Low || Result.getSExtValue() > High) {
if (RangeIsError)
- return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ return Diag(TheCall->getBeginLoc(), diag::err_argument_invalid_range)
<< Result.toString(10) << Low << High << Arg->getSourceRange();
else
// Defer the warning until we know if the code will be emitted so that
// dead code can ignore this.
- DiagRuntimeBehavior(TheCall->getLocStart(), TheCall,
- PDiag(diag::warn_argument_invalid_range)
- << Result.toString(10) << Low << High
- << Arg->getSourceRange());
+ DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
+ PDiag(diag::warn_argument_invalid_range)
+ << Result.toString(10) << Low << High
+ << Arg->getSourceRange());
}
return false;
@@ -5844,8 +6023,8 @@ bool Sema::SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum,
return true;
if (Result.getSExtValue() % Num != 0)
- return Diag(TheCall->getLocStart(), diag::err_argument_not_multiple)
- << Num << Arg->getSourceRange();
+ return Diag(TheCall->getBeginLoc(), diag::err_argument_not_multiple)
+ << Num << Arg->getSourceRange();
return false;
}
@@ -5876,7 +6055,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
// Check if the argument is a string literal.
if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
- return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
<< Arg->getSourceRange();
// Check the type of special register given.
@@ -5885,7 +6064,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
Reg.split(Fields, ":");
if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
- return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg)
+ return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
<< Arg->getSourceRange();
// If the string is the name of a register then we cannot check that it is
@@ -5927,7 +6106,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
}
if (!ValidString)
- return Diag(TheCall->getLocStart(), diag::err_arm_invalid_specialreg)
+ return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
<< Arg->getSourceRange();
} else if (IsAArch64Builtin && Fields.size() == 1) {
// If the register name is one of those that appear in the condition below
@@ -5955,8 +6134,8 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
/// that val is a constant 1.
bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
if (!Context.getTargetInfo().hasSjLjLowering())
- return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_unsupported)
- << SourceRange(TheCall->getLocStart(), TheCall->getLocEnd());
+ return Diag(TheCall->getBeginLoc(), diag::err_builtin_longjmp_unsupported)
+ << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
Expr *Arg = TheCall->getArg(1);
llvm::APSInt Result;
@@ -5966,8 +6145,8 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
return true;
if (Result != 1)
- return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val)
- << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+ return Diag(TheCall->getBeginLoc(), diag::err_builtin_longjmp_invalid_val)
+ << SourceRange(Arg->getBeginLoc(), Arg->getEndLoc());
return false;
}
@@ -5976,8 +6155,8 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
/// This checks that the target supports __builtin_setjmp.
bool Sema::SemaBuiltinSetjmp(CallExpr *TheCall) {
if (!Context.getTargetInfo().hasSjLjLowering())
- return Diag(TheCall->getLocStart(), diag::err_builtin_setjmp_unsupported)
- << SourceRange(TheCall->getLocStart(), TheCall->getLocEnd());
+ return Diag(TheCall->getBeginLoc(), diag::err_builtin_setjmp_unsupported)
+ << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
return false;
}
@@ -6121,11 +6300,11 @@ class FormatStringLiteral {
StartToken, StartTokenByteOffset);
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return FExpr->getLocStart().getLocWithOffset(Offset);
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return FExpr->getBeginLoc().getLocWithOffset(Offset);
}
- SourceLocation getLocEnd() const LLVM_READONLY { return FExpr->getLocEnd(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return FExpr->getEndLoc(); }
};
} // namespace
@@ -6377,13 +6556,12 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
return SLCT_NotALiteral;
}
case Stmt::BinaryOperatorClass: {
- llvm::APSInt LResult;
- llvm::APSInt RResult;
-
const BinaryOperator *BinOp = cast<BinaryOperator>(E);
// A string literal + an int offset is still a string literal.
if (BinOp->isAdditiveOp()) {
+ Expr::EvalResult LResult, RResult;
+
bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context);
bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context);
@@ -6392,12 +6570,12 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
if (LIsInt) {
if (BinOpKind == BO_Add) {
- sumOffsets(Offset, LResult, BinOpKind, RIsInt);
+ sumOffsets(Offset, LResult.Val.getInt(), BinOpKind, RIsInt);
E = BinOp->getRHS();
goto tryAgain;
}
} else {
- sumOffsets(Offset, RResult, BinOpKind, RIsInt);
+ sumOffsets(Offset, RResult.Val.getInt(), BinOpKind, RIsInt);
E = BinOp->getLHS();
goto tryAgain;
}
@@ -6410,9 +6588,10 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
const UnaryOperator *UnaOp = cast<UnaryOperator>(E);
auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr());
if (UnaOp->getOpcode() == UO_AddrOf && ASE) {
- llvm::APSInt IndexResult;
+ Expr::EvalResult IndexResult;
if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) {
- sumOffsets(Offset, IndexResult, BO_Add, /*RHS is int*/ true);
+ sumOffsets(Offset, IndexResult.Val.getInt(), BO_Add,
+ /*RHS is int*/ true);
E = ASE->getBase();
goto tryAgain;
}
@@ -6511,7 +6690,7 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
// format is either NSString or CFString. This is a hack to prevent
// diag when using the NSLocalizedString and CFCopyLocalizedString macros
// which are usually used in place of NS and CF string literals.
- SourceLocation FormatLoc = Args[format_idx]->getLocStart();
+ SourceLocation FormatLoc = Args[format_idx]->getBeginLoc();
if (Type == FST_NSString && SourceMgr.isInSystemMacro(FormatLoc))
return false;
@@ -6831,7 +7010,7 @@ void UncoveredArgHandler::Diagnose(Sema &S, bool IsFunctionCall,
if (!ArgExpr)
return;
- SourceLocation Loc = ArgExpr->getLocStart();
+ SourceLocation Loc = ArgExpr->getBeginLoc();
if (S.getSourceManager().isInSystemMacro(Loc))
return;
@@ -7029,6 +7208,8 @@ public:
const char *startSpecifier,
unsigned specifierLen) override;
+ void handleInvalidMaskType(StringRef MaskType) override;
+
bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) override;
@@ -7080,6 +7261,10 @@ bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
CS.getStart(), CS.getLength());
}
+void CheckPrintfHandler::handleInvalidMaskType(StringRef MaskType) {
+ S.Diag(getLocationOfByte(MaskType.data()), diag::err_invalid_mask_type_size);
+}
+
bool CheckPrintfHandler::HandleAmount(
const analyze_format_string::OptionalAmount &Amt,
unsigned k, const char *startSpecifier,
@@ -7276,10 +7461,9 @@ bool CheckPrintfHandler::checkForCStrMembers(
if (Method->getMinRequiredArguments() == 0 &&
AT.matchesType(S.Context, Method->getReturnType())) {
// FIXME: Suggest parens if the expression needs them.
- SourceLocation EndLoc = S.getLocForEndOfToken(E->getLocEnd());
- S.Diag(E->getLocStart(), diag::note_printf_c_str)
- << "c_str()"
- << FixItHint::CreateInsertion(EndLoc, ".c_str()");
+ SourceLocation EndLoc = S.getLocForEndOfToken(E->getEndLoc());
+ S.Diag(E->getBeginLoc(), diag::note_printf_c_str)
+ << "c_str()" << FixItHint::CreateInsertion(EndLoc, ".c_str()");
return true;
}
}
@@ -7353,22 +7537,22 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
ArgType(S.Context.IntTy) : ArgType::CPointerTy;
if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
EmitFormatDiagnostic(
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << Ex->getType()
- << false << Ex->getSourceRange(),
- Ex->getLocStart(), /*IsStringLocation*/false,
- getSpecifierRange(startSpecifier, specifierLen));
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << Ex->getType()
+ << false << Ex->getSourceRange(),
+ Ex->getBeginLoc(), /*IsStringLocation*/ false,
+ getSpecifierRange(startSpecifier, specifierLen));
// Type check the second argument (char * for both %b and %D)
Ex = getDataArg(argIndex + 1);
const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
EmitFormatDiagnostic(
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
- << AT2.getRepresentativeTypeName(S.Context) << Ex->getType()
- << false << Ex->getSourceRange(),
- Ex->getLocStart(), /*IsStringLocation*/false,
- getSpecifierRange(startSpecifier, specifierLen));
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT2.getRepresentativeTypeName(S.Context) << Ex->getType()
+ << false << Ex->getSourceRange(),
+ Ex->getBeginLoc(), /*IsStringLocation*/ false,
+ getSpecifierRange(startSpecifier, specifierLen));
return true;
}
@@ -7585,6 +7769,30 @@ shouldNotPrintDirectly(const ASTContext &Context,
return std::make_pair(QualType(), StringRef());
}
+/// Return true if \p ICE is an implicit argument promotion of an arithmetic
+/// type. Bit-field 'promotions' from a higher ranked type to a lower ranked
+/// type do not count.
+static bool
+isArithmeticArgumentPromotion(Sema &S, const ImplicitCastExpr *ICE) {
+ QualType From = ICE->getSubExpr()->getType();
+ QualType To = ICE->getType();
+ // It's an integer promotion if the destination type is the promoted
+ // source type.
+ if (ICE->getCastKind() == CK_IntegralCast &&
+ From->isPromotableIntegerType() &&
+ S.Context.getPromotedIntegerType(From) == To)
+ return true;
+ // Look through vector types, since we do default argument promotion for
+ // those in OpenCL.
+ if (const auto *VecTy = From->getAs<ExtVectorType>())
+ From = VecTy->getElementType();
+ if (const auto *VecTy = To->getAs<ExtVectorType>())
+ To = VecTy->getElementType();
+ // It's a floating promotion if the source type is a lower rank.
+ return ICE->getCastKind() == CK_FloatingCast &&
+ S.Context.getFloatingTypeOrder(From, To) < 0;
+}
+
bool
CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
const char *StartSpecifier,
@@ -7612,11 +7820,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// Look through argument promotions for our error message's reported type.
// This includes the integral and floating promotions, but excludes array
- // and function pointer decay; seeing that an argument intended to be a
- // string has type 'char [6]' is probably more confusing than 'char *'.
+ // and function pointer decay (seeing that an argument intended to be a
+ // string has type 'char [6]' is probably more confusing than 'char *') and
+ // certain bitfield promotions (bitfields can be 'demoted' to a lesser type).
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->getCastKind() == CK_IntegralCast ||
- ICE->getCastKind() == CK_FloatingCast) {
+ if (isArithmeticArgumentPromotion(S, ICE)) {
E = ICE->getSubExpr();
ExprTy = E->getType();
@@ -7666,7 +7874,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
return true;
}
- LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getLocStart(),
+ LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getBeginLoc(),
Sema::LookupOrdinaryName);
if (S.LookupName(Result, S.getCurScope())) {
NamedDecl *ND = Result.getFoundDecl();
@@ -7718,7 +7926,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
EmitFormatDiagnostic(S.PDiag(Diag)
<< AT.getRepresentativeTypeName(S.Context)
<< IntendedTy << IsEnum << E->getSourceRange(),
- E->getLocStart(),
+ E->getBeginLoc(),
/*IsStringLocation*/ false, SpecRange,
FixItHint::CreateReplacement(SpecRange, os.str()));
} else {
@@ -7747,15 +7955,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
} else if (!requiresParensToAddCast(E)) {
// If the expression has high enough precedence,
// just write the C-style cast.
- Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(),
- CastFix.str()));
+ Hints.push_back(
+ FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str()));
} else {
// Otherwise, add parens around the expression as well as the cast.
CastFix << "(";
- Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(),
- CastFix.str()));
+ Hints.push_back(
+ FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str()));
- SourceLocation After = S.getLocForEndOfToken(E->getLocEnd());
+ SourceLocation After = S.getLocForEndOfToken(E->getEndLoc());
Hints.push_back(FixItHint::CreateInsertion(After, ")"));
}
@@ -7773,18 +7981,17 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
: diag::warn_format_argument_needs_cast;
EmitFormatDiagnostic(S.PDiag(Diag) << Name << IntendedTy << IsEnum
<< E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation=*/false,
+ E->getBeginLoc(), /*IsStringLocation=*/false,
SpecRange, Hints);
} else {
// In this case, the expression could be printed using a different
// specifier, but we've decided that the specifier is probably correct
// and we should cast instead. Just use the normal warning message.
EmitFormatDiagnostic(
- S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/false,
- SpecRange, Hints);
+ S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum
+ << E->getSourceRange(),
+ E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, Hints);
}
}
} else {
@@ -7804,41 +8011,34 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
EmitFormatDiagnostic(
S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
<< IsEnum << CSR << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/ false, CSR);
+ E->getBeginLoc(), /*IsStringLocation*/ false, CSR);
break;
}
case Sema::VAK_Undefined:
case Sema::VAK_MSVCUndefined:
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_non_pod_vararg_with_format_string)
- << S.getLangOpts().CPlusPlus11
- << ExprTy
- << CallType
- << AT.getRepresentativeTypeName(S.Context)
- << CSR
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/false, CSR);
+ EmitFormatDiagnostic(S.PDiag(diag::warn_non_pod_vararg_with_format_string)
+ << S.getLangOpts().CPlusPlus11 << ExprTy
+ << CallType
+ << AT.getRepresentativeTypeName(S.Context) << CSR
+ << E->getSourceRange(),
+ E->getBeginLoc(), /*IsStringLocation*/ false, CSR);
checkForCStrMembers(AT, E);
break;
case Sema::VAK_Invalid:
if (ExprTy->isObjCObjectType())
EmitFormatDiagnostic(
- S.PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format)
- << S.getLangOpts().CPlusPlus11
- << ExprTy
- << CallType
- << AT.getRepresentativeTypeName(S.Context)
- << CSR
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/false, CSR);
+ S.PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format)
+ << S.getLangOpts().CPlusPlus11 << ExprTy << CallType
+ << AT.getRepresentativeTypeName(S.Context) << CSR
+ << E->getSourceRange(),
+ E->getBeginLoc(), /*IsStringLocation*/ false, CSR);
else
// FIXME: If this is an initializer list, suggest removing the braces
// or inserting a cast to the target type.
- S.Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg_format)
- << isa<InitListExpr>(E) << ExprTy << CallType
- << AT.getRepresentativeTypeName(S.Context)
- << E->getSourceRange();
+ S.Diag(E->getBeginLoc(), diag::err_cannot_pass_to_vararg_format)
+ << isa<InitListExpr>(E) << ExprTy << CallType
+ << AT.getRepresentativeTypeName(S.Context) << E->getSourceRange();
break;
}
@@ -8008,7 +8208,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
EmitFormatDiagnostic(
S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context)
<< Ex->getType() << false << Ex->getSourceRange(),
- Ex->getLocStart(),
+ Ex->getBeginLoc(),
/*IsStringLocation*/ false,
getSpecifierRange(startSpecifier, specifierLen),
FixItHint::CreateReplacement(
@@ -8017,7 +8217,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
EmitFormatDiagnostic(S.PDiag(Diag)
<< AT.getRepresentativeTypeName(S.Context)
<< Ex->getType() << false << Ex->getSourceRange(),
- Ex->getLocStart(),
+ Ex->getBeginLoc(),
/*IsStringLocation*/ false,
getSpecifierRange(startSpecifier, specifierLen));
}
@@ -8038,9 +8238,9 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
// CHECK: is the format string a wide literal?
if (!FExpr->isAscii() && !FExpr->isUTF8()) {
CheckFormatHandler::EmitFormatDiagnostic(
- S, inFunctionCall, Args[format_idx],
- S.PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(),
- /*IsStringLocation*/true, OrigFormatExpr->getSourceRange());
+ S, inFunctionCall, Args[format_idx],
+ S.PDiag(diag::warn_format_string_is_wide_literal), FExpr->getBeginLoc(),
+ /*IsStringLocation*/ true, OrigFormatExpr->getSourceRange());
return;
}
@@ -8062,7 +8262,7 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
CheckFormatHandler::EmitFormatDiagnostic(
S, inFunctionCall, Args[format_idx],
S.PDiag(diag::warn_printf_format_string_not_null_terminated),
- FExpr->getLocStart(),
+ FExpr->getBeginLoc(),
/*IsStringLocation=*/true, OrigFormatExpr->getSourceRange());
return;
}
@@ -8070,9 +8270,9 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
// CHECK: empty format string?
if (StrLen == 0 && numDataArgs > 0) {
CheckFormatHandler::EmitFormatDiagnostic(
- S, inFunctionCall, Args[format_idx],
- S.PDiag(diag::warn_empty_format_string), FExpr->getLocStart(),
- /*IsStringLocation*/true, OrigFormatExpr->getSourceRange());
+ S, inFunctionCall, Args[format_idx],
+ S.PDiag(diag::warn_empty_format_string), FExpr->getBeginLoc(),
+ /*IsStringLocation*/ true, OrigFormatExpr->getSourceRange());
return;
}
@@ -8587,8 +8787,9 @@ static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E,
S.Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison)
<< SizeRange << FnName;
S.Diag(FnLoc, diag::note_memsize_comparison_paren)
- << FnName << FixItHint::CreateInsertion(
- S.getLocForEndOfToken(Size->getLHS()->getLocEnd()), ")")
+ << FnName
+ << FixItHint::CreateInsertion(
+ S.getLocForEndOfToken(Size->getLHS()->getEndLoc()), ")")
<< FixItHint::CreateRemoval(RParenLoc);
S.Diag(SizeRange.getBegin(), diag::note_memsize_comparison_cast_silence)
<< FixItHint::CreateInsertion(SizeRange.getBegin(), "(size_t)(")
@@ -8853,7 +9054,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
if (CheckMemorySizeofForComparison(*this, LenExpr, FnName,
- Call->getLocStart(), Call->getRParenLoc()))
+ Call->getBeginLoc(), Call->getRParenLoc()))
return;
// Catch cases like 'memset(buf, sizeof(buf), 0)'.
@@ -9075,7 +9276,7 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
const Expr *CompareWithSrc = nullptr;
if (CheckMemorySizeofForComparison(*this, SizeArg, FnName,
- Call->getLocStart(), Call->getRParenLoc()))
+ Call->getBeginLoc(), Call->getRParenLoc()))
return;
// Look for 'strlcpy(dst, x, sizeof(x))'
@@ -9107,8 +9308,8 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
return;
const Expr *OriginalSizeArg = Call->getArg(2);
- Diag(CompareWithSrcDRE->getLocStart(), diag::warn_strlcpycat_wrong_size)
- << OriginalSizeArg->getSourceRange() << FnName;
+ Diag(CompareWithSrcDRE->getBeginLoc(), diag::warn_strlcpycat_wrong_size)
+ << OriginalSizeArg->getSourceRange() << FnName;
// Output a FIXIT hint if the destination is an array (rather than a
// pointer to an array). This could be enhanced to handle some
@@ -9124,9 +9325,9 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
DstArg->printPretty(OS, nullptr, getPrintingPolicy());
OS << ")";
- Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size)
- << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(),
- OS.str());
+ Diag(OriginalSizeArg->getBeginLoc(), diag::note_strlcpycat_wrong_size)
+ << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(),
+ OS.str());
}
/// Check if two expressions refer to the same declaration.
@@ -9159,7 +9360,7 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts();
const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts();
- if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getLocStart(),
+ if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getBeginLoc(),
CE->getRParenLoc()))
return;
@@ -9191,7 +9392,7 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
return;
// Generate the diagnostic.
- SourceLocation SL = LenArg->getLocStart();
+ SourceLocation SL = LenArg->getBeginLoc();
SourceRange SR = LenArg->getSourceRange();
SourceManager &SM = getSourceManager();
@@ -9738,7 +9939,7 @@ static bool IsEnumConstOrFromMacro(Sema &S, Expr *E) {
return true;
// Suppress cases where the '0' value is expanded from a macro.
- if (E->getLocStart().isMacroID())
+ if (E->getBeginLoc().isMacroID())
return true;
return false;
@@ -10159,8 +10360,8 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
Expr *OriginalInit = Init->IgnoreParenImpCasts();
unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context);
- llvm::APSInt Value;
- if (!OriginalInit->EvaluateAsInt(Value, S.Context,
+ Expr::EvalResult Result;
+ if (!OriginalInit->EvaluateAsInt(Result, S.Context,
Expr::SE_AllowSideEffects)) {
// The RHS is not constant. If the RHS has an enum type, make sure the
// bitfield is wide enough to hold all the values of the enum without
@@ -10216,6 +10417,8 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
return false;
}
+ llvm::APSInt Value = Result.Val.getInt();
+
unsigned OriginalWidth = Value.getBitWidth();
if (!Value.isSigned() || Value.isNegative())
@@ -10268,6 +10471,10 @@ static void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
}
AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+
+ // Diagnose implicitly sequentially-consistent atomic assignment.
+ if (E->getLHS()->getType()->isAtomicType())
+ S.Diag(E->getRHS()->getBeginLoc(), diag::warn_atomic_implicit_seq_cst);
}
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
@@ -10292,33 +10499,6 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType T,
DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow);
}
-/// Analyze the given compound assignment for the possible losing of
-/// floating-point precision.
-static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) {
- assert(isa<CompoundAssignOperator>(E) &&
- "Must be compound assignment operation");
- // Recurse on the LHS and RHS in here
- AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
- AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
-
- // Now check the outermost expression
- const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>();
- const auto *RBT = cast<CompoundAssignOperator>(E)
- ->getComputationResultType()
- ->getAs<BuiltinType>();
-
- // If both source and target are floating points.
- if (ResultBT && ResultBT->isFloatingPoint() && RBT && RBT->isFloatingPoint())
- // Builtin FP kinds are ordered by increasing FP rank.
- if (ResultBT->getKind() < RBT->getKind())
- // We don't want to warn for system macro.
- if (!S.SourceMgr.isInSystemMacro(E->getOperatorLoc()))
- // warn about dropping FP rank.
- DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(),
- E->getOperatorLoc(),
- diag::warn_impcast_float_result_precision);
-}
-
/// Diagnose an implicit cast from a floating point value to an integer value.
static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
SourceLocation CContext) {
@@ -10421,6 +10601,42 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T,
}
}
+/// Analyze the given compound assignment for the possible losing of
+/// floating-point precision.
+static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) {
+ assert(isa<CompoundAssignOperator>(E) &&
+ "Must be compound assignment operation");
+ // Recurse on the LHS and RHS in here
+ AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
+ AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+
+ if (E->getLHS()->getType()->isAtomicType())
+ S.Diag(E->getOperatorLoc(), diag::warn_atomic_implicit_seq_cst);
+
+ // Now check the outermost expression
+ const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>();
+ const auto *RBT = cast<CompoundAssignOperator>(E)
+ ->getComputationResultType()
+ ->getAs<BuiltinType>();
+
+ // The below checks assume source is floating point.
+ if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return;
+
+ // If source is floating point but target is not.
+ if (!ResultBT->isFloatingPoint())
+ return DiagnoseFloatingImpCast(S, E, E->getRHS()->getType(),
+ E->getExprLoc());
+
+ // If both source and target are floating points.
+ // Builtin FP kinds are ordered by increasing FP rank.
+ if (ResultBT->getKind() < RBT->getKind() &&
+ // We don't want to warn for system macro.
+ !S.SourceMgr.isInSystemMacro(E->getOperatorLoc()))
+ // warn about dropping FP rank.
+ DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(),
+ diag::warn_impcast_float_result_precision);
+}
+
static std::string PrettyPrintInRange(const llvm::APSInt &Value,
IntRange Range) {
if (!Range.Width) return "0";
@@ -10545,10 +10761,9 @@ static void checkObjCCollectionLiteralElement(Sema &S,
ElementResult,
false, false)
!= Sema::Compatible) {
- S.Diag(Element->getLocStart(),
- diag::warn_objc_collection_literal_element)
- << ElementType << ElementKind << TargetElementType
- << Element->getSourceRange();
+ S.Diag(Element->getBeginLoc(), diag::warn_objc_collection_literal_element)
+ << ElementType << ElementKind << TargetElementType
+ << Element->getSourceRange();
}
if (auto ArrayLiteral = dyn_cast<ObjCArrayLiteral>(Element))
@@ -10624,7 +10839,7 @@ static bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T,
// to fill all the bits, even if there is a sign change.
if (auto *IntLit = dyn_cast<IntegerLiteral>(E->IgnoreParenImpCasts())) {
const char FirstLiteralCharacter =
- S.getSourceManager().getCharacterData(IntLit->getLocStart())[0];
+ S.getSourceManager().getCharacterData(IntLit->getBeginLoc())[0];
if (FirstLiteralCharacter == '0')
return false;
}
@@ -10659,6 +10874,9 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
if (CC.isInvalid())
return;
+ if (Source->isAtomicType())
+ S.Diag(E->getExprLoc(), diag::warn_atomic_implicit_seq_cst);
+
// Diagnose implicit casts to bool.
if (Target->isSpecificBuiltinType(BuiltinType::Bool)) {
if (isa<StringLiteral>(E))
@@ -10813,8 +11031,11 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
if (SourceRange.Width > TargetRange.Width) {
// If the source is a constant, use a default-on diagnostic.
// TODO: this should happen for bitfield stores, too.
- llvm::APSInt Value(32);
- if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) {
+ Expr::EvalResult Result;
+ if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) {
+ llvm::APSInt Value(32);
+ Value = Result.Val.getInt();
+
if (S.SourceMgr.isInSystemMacro(CC))
return;
@@ -10839,15 +11060,29 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
}
+ if (TargetRange.Width > SourceRange.Width) {
+ if (auto *UO = dyn_cast<UnaryOperator>(E))
+ if (UO->getOpcode() == UO_Minus)
+ if (Source->isUnsignedIntegerType()) {
+ if (Target->isUnsignedIntegerType())
+ return DiagnoseImpCast(S, E, T, CC,
+ diag::warn_impcast_high_order_zero_bits);
+ if (Target->isSignedIntegerType())
+ return DiagnoseImpCast(S, E, T, CC,
+ diag::warn_impcast_nonnegative_result);
+ }
+ }
+
if (TargetRange.Width == SourceRange.Width && !TargetRange.NonNegative &&
SourceRange.NonNegative && Source->isSignedIntegerType()) {
// Warn when doing a signed to signed conversion, warn if the positive
// source value is exactly the width of the target type, which will
// cause a negative value to be stored.
- llvm::APSInt Value;
- if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects) &&
+ Expr::EvalResult Result;
+ if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects) &&
!S.SourceMgr.isInSystemMacro(CC)) {
+ llvm::APSInt Value = Result.Val.getInt();
if (isSameWidthConstantConversion(S, E, T, CC)) {
std::string PrettySourceValue = Value.toString(10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
@@ -10954,11 +11189,13 @@ static void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
E->getType(), CC, &Suspicious);
}
-/// CheckBoolLikeConversion - Check conversion of given expression to boolean.
+/// Check conversion of given expression to boolean.
/// Input argument E is a logical expression.
static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) {
if (S.getLangOpts().Bool)
return;
+ if (E->IgnoreParenImpCasts()->getType()->isAtomicType())
+ return;
CheckImplicitConversion(S, E->IgnoreParenImpCasts(), S.Context.BoolTy, CC);
}
@@ -11003,8 +11240,10 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
}
// Skip past explicit casts.
- if (isa<ExplicitCastExpr>(E)) {
- E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
+ if (auto *CE = dyn_cast<ExplicitCastExpr>(E)) {
+ E = CE->getSubExpr()->IgnoreParenImpCasts();
+ if (!CE->getType()->isVoidType() && E->getType()->isAtomicType())
+ S.Diag(E->getBeginLoc(), diag::warn_atomic_implicit_seq_cst);
return AnalyzeImplicitConversions(S, E, CC);
}
@@ -11057,9 +11296,15 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE,
::CheckBoolLikeConversion(S, SubExpr, BO->getExprLoc());
}
- if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E))
- if (U->getOpcode() == UO_LNot)
+ if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
+ if (U->getOpcode() == UO_LNot) {
::CheckBoolLikeConversion(S, U->getSubExpr(), CC);
+ } else if (U->getOpcode() != UO_AddrOf) {
+ if (U->getSubExpr()->getType()->isAtomicType())
+ S.Diag(U->getSubExpr()->getBeginLoc(),
+ diag::warn_atomic_implicit_seq_cst);
+ }
+ }
}
/// Diagnose integer type and any valid implicit conversion to it.
@@ -11067,13 +11312,13 @@ static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
// Taking into account implicit conversions,
// allow any integer.
if (!E->getType()->isIntegerType()) {
- S.Diag(E->getLocStart(),
+ S.Diag(E->getBeginLoc(),
diag::err_opencl_enqueue_kernel_invalid_local_size_type);
return true;
}
// Potentially emit standard warnings for implicit conversions if enabled
// using -Wconversion.
- CheckImplicitConversion(S, E, IntT, E->getLocStart());
+ CheckImplicitConversion(S, E, IntT, E->getBeginLoc());
return false;
}
@@ -11281,7 +11526,7 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
// Suggest '&' to silence the function warning.
Diag(E->getExprLoc(), diag::note_function_warning_silence)
- << FixItHint::CreateInsertion(E->getLocStart(), "&");
+ << FixItHint::CreateInsertion(E->getBeginLoc(), "&");
// Check to see if '()' fixit should be emitted.
QualType ReturnType;
@@ -11310,7 +11555,7 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
return;
}
Diag(E->getExprLoc(), diag::note_function_to_function_call)
- << FixItHint::CreateInsertion(getLocForEndOfToken(E->getLocEnd()), "()");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(E->getEndLoc()), "()");
}
/// Diagnoses "dangerous" implicit conversions within the given
@@ -11663,30 +11908,42 @@ public:
notePostUse(O, E);
}
- void VisitBinComma(BinaryOperator *BO) {
- // C++11 [expr.comma]p1:
- // Every value computation and side effect associated with the left
- // expression is sequenced before every value computation and side
- // effect associated with the right expression.
- SequenceTree::Seq LHS = Tree.allocate(Region);
- SequenceTree::Seq RHS = Tree.allocate(Region);
+ void VisitSequencedExpressions(Expr *SequencedBefore, Expr *SequencedAfter) {
+ SequenceTree::Seq BeforeRegion = Tree.allocate(Region);
+ SequenceTree::Seq AfterRegion = Tree.allocate(Region);
SequenceTree::Seq OldRegion = Region;
{
- SequencedSubexpression SeqLHS(*this);
- Region = LHS;
- Visit(BO->getLHS());
+ SequencedSubexpression SeqBefore(*this);
+ Region = BeforeRegion;
+ Visit(SequencedBefore);
}
- Region = RHS;
- Visit(BO->getRHS());
+ Region = AfterRegion;
+ Visit(SequencedAfter);
Region = OldRegion;
- // Forget that LHS and RHS are sequenced. They are both unsequenced
- // with respect to other stuff.
- Tree.merge(LHS);
- Tree.merge(RHS);
+ Tree.merge(BeforeRegion);
+ Tree.merge(AfterRegion);
+ }
+
+ void VisitArraySubscriptExpr(ArraySubscriptExpr *ASE) {
+ // C++17 [expr.sub]p1:
+ // The expression E1[E2] is identical (by definition) to *((E1)+(E2)). The
+ // expression E1 is sequenced before the expression E2.
+ if (SemaRef.getLangOpts().CPlusPlus17)
+ VisitSequencedExpressions(ASE->getLHS(), ASE->getRHS());
+ else
+ Base::VisitStmt(ASE);
+ }
+
+ void VisitBinComma(BinaryOperator *BO) {
+ // C++11 [expr.comma]p1:
+ // Every value computation and side effect associated with the left
+ // expression is sequenced before every value computation and side
+ // effect associated with the right expression.
+ VisitSequencedExpressions(BO->getLHS(), BO->getRHS());
}
void VisitBinAssign(BinaryOperator *BO) {
@@ -11992,6 +12249,18 @@ bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
if (!Param->getType().isConstQualified())
Diag(Param->getLocation(), diag::err_attribute_pointers_only)
<< Attr->getSpelling() << 1;
+
+ // Check for parameter names shadowing fields from the class.
+ if (LangOpts.CPlusPlus && !Param->isInvalidDecl()) {
+ // The owning context for the parameter should be the function, but we
+ // want to see if this function's declaration context is a record.
+ DeclContext *DC = Param->getDeclContext();
+ if (DC && DC->isFunctionOrMethod()) {
+ if (auto *RD = dyn_cast<CXXRecordDecl>(DC->getParent()))
+ CheckShadowInheritedFields(Param->getLocation(), Param->getDeclName(),
+ RD, /*DeclIsField*/ false);
+ }
+ }
}
return HasInvalidParm;
@@ -12120,13 +12389,18 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
BaseExpr->getType()->getPointeeOrArrayElementType();
BaseExpr = BaseExpr->IgnoreParenCasts();
const ConstantArrayType *ArrayTy =
- Context.getAsConstantArrayType(BaseExpr->getType());
+ Context.getAsConstantArrayType(BaseExpr->getType());
+
if (!ArrayTy)
return;
- llvm::APSInt index;
- if (!IndexExpr->EvaluateAsInt(index, Context, Expr::SE_AllowSideEffects))
+ const Type *BaseType = ArrayTy->getElementType().getTypePtr();
+
+ Expr::EvalResult Result;
+ if (!IndexExpr->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects))
return;
+
+ llvm::APSInt index = Result.Val.getInt();
if (IndexNegated)
index = -index;
@@ -12137,11 +12411,19 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
ND = ME->getMemberDecl();
if (index.isUnsigned() || !index.isNegative()) {
+ // It is possible that the type of the base expression after
+ // IgnoreParenCasts is incomplete, even though the type of the base
+ // expression before IgnoreParenCasts is complete (see PR39746 for an
+ // example). In this case we have no information about whether the array
+ // access exceeds the array bounds. However we can still diagnose an array
+ // access which precedes the array bounds.
+ if (BaseType->isIncompleteType())
+ return;
+
llvm::APInt size = ArrayTy->getSize();
if (!size.isStrictlyPositive())
return;
- const Type *BaseType = BaseExpr->getType()->getPointeeOrArrayElementType();
if (BaseType != EffectiveType) {
// Make sure we're comparing apples to apples when comparing index to size
uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType);
@@ -12183,8 +12465,8 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
SourceLocation RBracketLoc = SourceMgr.getSpellingLoc(
ASE->getRBracketLoc());
if (SourceMgr.isInSystemHeader(RBracketLoc)) {
- SourceLocation IndexLoc = SourceMgr.getSpellingLoc(
- IndexExpr->getLocStart());
+ SourceLocation IndexLoc =
+ SourceMgr.getSpellingLoc(IndexExpr->getBeginLoc());
if (SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc))
return;
}
@@ -12194,11 +12476,11 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (ASE)
DiagID = diag::warn_array_index_exceeds_bounds;
- DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr,
+ DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
PDiag(DiagID) << index.toString(10, true)
- << size.toString(10, true)
- << (unsigned)size.getLimitedValue(~0U)
- << IndexExpr->getSourceRange());
+ << size.toString(10, true)
+ << (unsigned)size.getLimitedValue(~0U)
+ << IndexExpr->getSourceRange());
} else {
unsigned DiagID = diag::warn_array_index_precedes_bounds;
if (!ASE) {
@@ -12206,9 +12488,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (index.isNegative()) index = -index;
}
- DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr,
+ DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
PDiag(DiagID) << index.toString(10, true)
- << IndexExpr->getSourceRange());
+ << IndexExpr->getSourceRange());
}
if (!ND) {
@@ -12223,9 +12505,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
}
if (ND)
- DiagRuntimeBehavior(ND->getLocStart(), BaseExpr,
+ DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr,
PDiag(diag::note_array_index_out_of_bounds)
- << ND->getDeclName());
+ << ND->getDeclName());
}
void Sema::CheckArrayAccess(const Expr *expr) {
@@ -12965,15 +13247,13 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S,
if (!ProbableTypo) {
bool BodyColInvalid;
unsigned BodyCol = SourceMgr.getPresumedColumnNumber(
- PossibleBody->getLocStart(),
- &BodyColInvalid);
+ PossibleBody->getBeginLoc(), &BodyColInvalid);
if (BodyColInvalid)
return;
bool StmtColInvalid;
- unsigned StmtCol = SourceMgr.getPresumedColumnNumber(
- S->getLocStart(),
- &StmtColInvalid);
+ unsigned StmtCol =
+ SourceMgr.getPresumedColumnNumber(S->getBeginLoc(), &StmtColInvalid);
if (StmtColInvalid)
return;
@@ -13493,7 +13773,7 @@ void Sema::DiagnoseMisalignedMembers() {
if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl())
ND = TD;
}
- Diag(m.E->getLocStart(), diag::warn_taking_address_of_packed_member)
+ Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
<< m.MD << ND << m.E->getSourceRange();
}
MisalignedMembers.clear();
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 30af826ef6cc..d9f007a46da5 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -10,6 +10,8 @@
// This file defines the code-completion semantic actions.
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
@@ -32,6 +34,8 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Path.h"
#include <list>
#include <map>
#include <vector>
@@ -40,315 +44,309 @@ using namespace clang;
using namespace sema;
namespace {
- /// A container of code-completion results.
- class ResultBuilder {
- public:
- /// The type of a name-lookup filter, which can be provided to the
- /// name-lookup routines to specify which declarations should be included in
- /// the result set (when it returns true) and which declarations should be
- /// filtered out (returns false).
- typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
-
- typedef CodeCompletionResult Result;
+/// A container of code-completion results.
+class ResultBuilder {
+public:
+ /// The type of a name-lookup filter, which can be provided to the
+ /// name-lookup routines to specify which declarations should be included in
+ /// the result set (when it returns true) and which declarations should be
+ /// filtered out (returns false).
+ typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
- private:
- /// The actual results we have found.
- std::vector<Result> Results;
+ typedef CodeCompletionResult Result;
- /// A record of all of the declarations we have found and placed
- /// into the result set, used to ensure that no declaration ever gets into
- /// the result set twice.
- llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
+private:
+ /// The actual results we have found.
+ std::vector<Result> Results;
- typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
+ /// A record of all of the declarations we have found and placed
+ /// into the result set, used to ensure that no declaration ever gets into
+ /// the result set twice.
+ llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
- /// An entry in the shadow map, which is optimized to store
- /// a single (declaration, index) mapping (the common case) but
- /// can also store a list of (declaration, index) mappings.
- class ShadowMapEntry {
- typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
+ typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
- /// Contains either the solitary NamedDecl * or a vector
- /// of (declaration, index) pairs.
- llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
+ /// An entry in the shadow map, which is optimized to store
+ /// a single (declaration, index) mapping (the common case) but
+ /// can also store a list of (declaration, index) mappings.
+ class ShadowMapEntry {
+ typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
- /// When the entry contains a single declaration, this is
- /// the index associated with that entry.
- unsigned SingleDeclIndex;
+ /// Contains either the solitary NamedDecl * or a vector
+ /// of (declaration, index) pairs.
+ llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
- public:
- ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
+ /// When the entry contains a single declaration, this is
+ /// the index associated with that entry.
+ unsigned SingleDeclIndex;
- void Add(const NamedDecl *ND, unsigned Index) {
- if (DeclOrVector.isNull()) {
- // 0 - > 1 elements: just set the single element information.
- DeclOrVector = ND;
- SingleDeclIndex = Index;
- return;
- }
+ public:
+ ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
- if (const NamedDecl *PrevND =
- DeclOrVector.dyn_cast<const NamedDecl *>()) {
- // 1 -> 2 elements: create the vector of results and push in the
- // existing declaration.
- DeclIndexPairVector *Vec = new DeclIndexPairVector;
- Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
- DeclOrVector = Vec;
- }
+ void Add(const NamedDecl *ND, unsigned Index) {
+ if (DeclOrVector.isNull()) {
+ // 0 - > 1 elements: just set the single element information.
+ DeclOrVector = ND;
+ SingleDeclIndex = Index;
+ return;
+ }
- // Add the new element to the end of the vector.
- DeclOrVector.get<DeclIndexPairVector*>()->push_back(
- DeclIndexPair(ND, Index));
+ if (const NamedDecl *PrevND =
+ DeclOrVector.dyn_cast<const NamedDecl *>()) {
+ // 1 -> 2 elements: create the vector of results and push in the
+ // existing declaration.
+ DeclIndexPairVector *Vec = new DeclIndexPairVector;
+ Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
+ DeclOrVector = Vec;
}
- void Destroy() {
- if (DeclIndexPairVector *Vec
- = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
- delete Vec;
- DeclOrVector = ((NamedDecl *)nullptr);
- }
+ // Add the new element to the end of the vector.
+ DeclOrVector.get<DeclIndexPairVector *>()->push_back(
+ DeclIndexPair(ND, Index));
+ }
+
+ void Destroy() {
+ if (DeclIndexPairVector *Vec =
+ DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
+ delete Vec;
+ DeclOrVector = ((NamedDecl *)nullptr);
}
+ }
- // Iteration.
- class iterator;
- iterator begin() const;
- iterator end() const;
- };
+ // Iteration.
+ class iterator;
+ iterator begin() const;
+ iterator end() const;
+ };
- /// A mapping from declaration names to the declarations that have
- /// this name within a particular scope and their index within the list of
- /// results.
- typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+ /// A mapping from declaration names to the declarations that have
+ /// this name within a particular scope and their index within the list of
+ /// results.
+ typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
- /// The semantic analysis object for which results are being
- /// produced.
- Sema &SemaRef;
+ /// The semantic analysis object for which results are being
+ /// produced.
+ Sema &SemaRef;
- /// The allocator used to allocate new code-completion strings.
- CodeCompletionAllocator &Allocator;
+ /// The allocator used to allocate new code-completion strings.
+ CodeCompletionAllocator &Allocator;
- CodeCompletionTUInfo &CCTUInfo;
+ CodeCompletionTUInfo &CCTUInfo;
- /// If non-NULL, a filter function used to remove any code-completion
- /// results that are not desirable.
- LookupFilter Filter;
+ /// If non-NULL, a filter function used to remove any code-completion
+ /// results that are not desirable.
+ LookupFilter Filter;
- /// Whether we should allow declarations as
- /// nested-name-specifiers that would otherwise be filtered out.
- bool AllowNestedNameSpecifiers;
+ /// Whether we should allow declarations as
+ /// nested-name-specifiers that would otherwise be filtered out.
+ bool AllowNestedNameSpecifiers;
- /// If set, the type that we would prefer our resulting value
- /// declarations to have.
- ///
- /// Closely matching the preferred type gives a boost to a result's
- /// priority.
- CanQualType PreferredType;
+ /// If set, the type that we would prefer our resulting value
+ /// declarations to have.
+ ///
+ /// Closely matching the preferred type gives a boost to a result's
+ /// priority.
+ CanQualType PreferredType;
- /// A list of shadow maps, which is used to model name hiding at
- /// different levels of, e.g., the inheritance hierarchy.
- std::list<ShadowMap> ShadowMaps;
+ /// A list of shadow maps, which is used to model name hiding at
+ /// different levels of, e.g., the inheritance hierarchy.
+ std::list<ShadowMap> ShadowMaps;
- /// If we're potentially referring to a C++ member function, the set
- /// of qualifiers applied to the object type.
- Qualifiers ObjectTypeQualifiers;
+ /// If we're potentially referring to a C++ member function, the set
+ /// of qualifiers applied to the object type.
+ Qualifiers ObjectTypeQualifiers;
- /// Whether the \p ObjectTypeQualifiers field is active.
- bool HasObjectTypeQualifiers;
+ /// Whether the \p ObjectTypeQualifiers field is active.
+ bool HasObjectTypeQualifiers;
- /// The selector that we prefer.
- Selector PreferredSelector;
+ /// The selector that we prefer.
+ Selector PreferredSelector;
- /// The completion context in which we are gathering results.
- CodeCompletionContext CompletionContext;
+ /// The completion context in which we are gathering results.
+ CodeCompletionContext CompletionContext;
- /// If we are in an instance method definition, the \@implementation
- /// object.
- ObjCImplementationDecl *ObjCImplementation;
+ /// If we are in an instance method definition, the \@implementation
+ /// object.
+ ObjCImplementationDecl *ObjCImplementation;
- void AdjustResultPriorityForDecl(Result &R);
+ void AdjustResultPriorityForDecl(Result &R);
- void MaybeAddConstructorResults(Result R);
+ void MaybeAddConstructorResults(Result R);
- public:
- explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo,
- const CodeCompletionContext &CompletionContext,
- LookupFilter Filter = nullptr)
+public:
+ explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ const CodeCompletionContext &CompletionContext,
+ LookupFilter Filter = nullptr)
: SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
- Filter(Filter),
- AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
- CompletionContext(CompletionContext),
- ObjCImplementation(nullptr)
- {
- // If this is an Objective-C instance method definition, dig out the
- // corresponding implementation.
- switch (CompletionContext.getKind()) {
- case CodeCompletionContext::CCC_Expression:
- case CodeCompletionContext::CCC_ObjCMessageReceiver:
- case CodeCompletionContext::CCC_ParenthesizedExpression:
- case CodeCompletionContext::CCC_Statement:
- case CodeCompletionContext::CCC_Recovery:
- if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
- if (Method->isInstanceMethod())
- if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
- ObjCImplementation = Interface->getImplementation();
- break;
+ Filter(Filter), AllowNestedNameSpecifiers(false),
+ HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
+ ObjCImplementation(nullptr) {
+ // If this is an Objective-C instance method definition, dig out the
+ // corresponding implementation.
+ switch (CompletionContext.getKind()) {
+ case CodeCompletionContext::CCC_Expression:
+ case CodeCompletionContext::CCC_ObjCMessageReceiver:
+ case CodeCompletionContext::CCC_ParenthesizedExpression:
+ case CodeCompletionContext::CCC_Statement:
+ case CodeCompletionContext::CCC_Recovery:
+ if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
+ if (Method->isInstanceMethod())
+ if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
+ ObjCImplementation = Interface->getImplementation();
+ break;
- default:
- break;
- }
- }
-
- /// Determine the priority for a reference to the given declaration.
- unsigned getBasePriority(const NamedDecl *D);
-
- /// Whether we should include code patterns in the completion
- /// results.
- bool includeCodePatterns() const {
- return SemaRef.CodeCompleter &&
- SemaRef.CodeCompleter->includeCodePatterns();
- }
-
- /// Set the filter used for code-completion results.
- void setFilter(LookupFilter Filter) {
- this->Filter = Filter;
- }
-
- Result *data() { return Results.empty()? nullptr : &Results.front(); }
- unsigned size() const { return Results.size(); }
- bool empty() const { return Results.empty(); }
-
- /// Specify the preferred type.
- void setPreferredType(QualType T) {
- PreferredType = SemaRef.Context.getCanonicalType(T);
+ default:
+ break;
}
+ }
- /// Set the cv-qualifiers on the object type, for us in filtering
- /// calls to member functions.
- ///
- /// When there are qualifiers in this set, they will be used to filter
- /// out member functions that aren't available (because there will be a
- /// cv-qualifier mismatch) or prefer functions with an exact qualifier
- /// match.
- void setObjectTypeQualifiers(Qualifiers Quals) {
- ObjectTypeQualifiers = Quals;
- HasObjectTypeQualifiers = true;
- }
-
- /// Set the preferred selector.
- ///
- /// When an Objective-C method declaration result is added, and that
- /// method's selector matches this preferred selector, we give that method
- /// a slight priority boost.
- void setPreferredSelector(Selector Sel) {
- PreferredSelector = Sel;
- }
-
- /// Retrieve the code-completion context for which results are
- /// being collected.
- const CodeCompletionContext &getCompletionContext() const {
- return CompletionContext;
- }
-
- /// Specify whether nested-name-specifiers are allowed.
- void allowNestedNameSpecifiers(bool Allow = true) {
- AllowNestedNameSpecifiers = Allow;
- }
-
- /// Return the semantic analysis object for which we are collecting
- /// code completion results.
- Sema &getSema() const { return SemaRef; }
-
- /// Retrieve the allocator used to allocate code completion strings.
- CodeCompletionAllocator &getAllocator() const { return Allocator; }
-
- CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
-
- /// Determine whether the given declaration is at all interesting
- /// as a code-completion result.
- ///
- /// \param ND the declaration that we are inspecting.
- ///
- /// \param AsNestedNameSpecifier will be set true if this declaration is
- /// only interesting when it is a nested-name-specifier.
- bool isInterestingDecl(const NamedDecl *ND,
- bool &AsNestedNameSpecifier) const;
-
- /// Check whether the result is hidden by the Hiding declaration.
- ///
- /// \returns true if the result is hidden and cannot be found, false if
- /// the hidden result could still be found. When false, \p R may be
- /// modified to describe how the result can be found (e.g., via extra
- /// qualification).
- bool CheckHiddenResult(Result &R, DeclContext *CurContext,
- const NamedDecl *Hiding);
-
- /// Add a new result to this result set (if it isn't already in one
- /// of the shadow maps), or replace an existing result (for, e.g., a
- /// redeclaration).
- ///
- /// \param R the result to add (if it is unique).
- ///
- /// \param CurContext the context in which this result will be named.
- void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
-
- /// Add a new result to this result set, where we already know
- /// the hiding declaration (if any).
- ///
- /// \param R the result to add (if it is unique).
- ///
- /// \param CurContext the context in which this result will be named.
- ///
- /// \param Hiding the declaration that hides the result.
- ///
- /// \param InBaseClass whether the result was found in a base
- /// class of the searched context.
- void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
- bool InBaseClass);
-
- /// Add a new non-declaration result to this result set.
- void AddResult(Result R);
-
- /// Enter into a new scope.
- void EnterNewScope();
-
- /// Exit from the current scope.
- void ExitScope();
-
- /// Ignore this declaration, if it is seen again.
- void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
-
- /// Add a visited context.
- void addVisitedContext(DeclContext *Ctx) {
- CompletionContext.addVisitedContext(Ctx);
- }
-
- /// \name Name lookup predicates
- ///
- /// These predicates can be passed to the name lookup functions to filter the
- /// results of name lookup. All of the predicates have the same type, so that
- ///
- //@{
- bool IsOrdinaryName(const NamedDecl *ND) const;
- bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
- bool IsIntegralConstantValue(const NamedDecl *ND) const;
- bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
- bool IsNestedNameSpecifier(const NamedDecl *ND) const;
- bool IsEnum(const NamedDecl *ND) const;
- bool IsClassOrStruct(const NamedDecl *ND) const;
- bool IsUnion(const NamedDecl *ND) const;
- bool IsNamespace(const NamedDecl *ND) const;
- bool IsNamespaceOrAlias(const NamedDecl *ND) const;
- bool IsType(const NamedDecl *ND) const;
- bool IsMember(const NamedDecl *ND) const;
- bool IsObjCIvar(const NamedDecl *ND) const;
- bool IsObjCMessageReceiver(const NamedDecl *ND) const;
- bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
- bool IsObjCCollection(const NamedDecl *ND) const;
- bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
- //@}
- };
-}
+ /// Determine the priority for a reference to the given declaration.
+ unsigned getBasePriority(const NamedDecl *D);
+
+ /// Whether we should include code patterns in the completion
+ /// results.
+ bool includeCodePatterns() const {
+ return SemaRef.CodeCompleter &&
+ SemaRef.CodeCompleter->includeCodePatterns();
+ }
+
+ /// Set the filter used for code-completion results.
+ void setFilter(LookupFilter Filter) { this->Filter = Filter; }
+
+ Result *data() { return Results.empty() ? nullptr : &Results.front(); }
+ unsigned size() const { return Results.size(); }
+ bool empty() const { return Results.empty(); }
+
+ /// Specify the preferred type.
+ void setPreferredType(QualType T) {
+ PreferredType = SemaRef.Context.getCanonicalType(T);
+ }
+
+ /// Set the cv-qualifiers on the object type, for us in filtering
+ /// calls to member functions.
+ ///
+ /// When there are qualifiers in this set, they will be used to filter
+ /// out member functions that aren't available (because there will be a
+ /// cv-qualifier mismatch) or prefer functions with an exact qualifier
+ /// match.
+ void setObjectTypeQualifiers(Qualifiers Quals) {
+ ObjectTypeQualifiers = Quals;
+ HasObjectTypeQualifiers = true;
+ }
+
+ /// Set the preferred selector.
+ ///
+ /// When an Objective-C method declaration result is added, and that
+ /// method's selector matches this preferred selector, we give that method
+ /// a slight priority boost.
+ void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
+
+ /// Retrieve the code-completion context for which results are
+ /// being collected.
+ const CodeCompletionContext &getCompletionContext() const {
+ return CompletionContext;
+ }
+
+ /// Specify whether nested-name-specifiers are allowed.
+ void allowNestedNameSpecifiers(bool Allow = true) {
+ AllowNestedNameSpecifiers = Allow;
+ }
+
+ /// Return the semantic analysis object for which we are collecting
+ /// code completion results.
+ Sema &getSema() const { return SemaRef; }
+
+ /// Retrieve the allocator used to allocate code completion strings.
+ CodeCompletionAllocator &getAllocator() const { return Allocator; }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
+
+ /// Determine whether the given declaration is at all interesting
+ /// as a code-completion result.
+ ///
+ /// \param ND the declaration that we are inspecting.
+ ///
+ /// \param AsNestedNameSpecifier will be set true if this declaration is
+ /// only interesting when it is a nested-name-specifier.
+ bool isInterestingDecl(const NamedDecl *ND,
+ bool &AsNestedNameSpecifier) const;
+
+ /// Check whether the result is hidden by the Hiding declaration.
+ ///
+ /// \returns true if the result is hidden and cannot be found, false if
+ /// the hidden result could still be found. When false, \p R may be
+ /// modified to describe how the result can be found (e.g., via extra
+ /// qualification).
+ bool CheckHiddenResult(Result &R, DeclContext *CurContext,
+ const NamedDecl *Hiding);
+
+ /// Add a new result to this result set (if it isn't already in one
+ /// of the shadow maps), or replace an existing result (for, e.g., a
+ /// redeclaration).
+ ///
+ /// \param R the result to add (if it is unique).
+ ///
+ /// \param CurContext the context in which this result will be named.
+ void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
+
+ /// Add a new result to this result set, where we already know
+ /// the hiding declaration (if any).
+ ///
+ /// \param R the result to add (if it is unique).
+ ///
+ /// \param CurContext the context in which this result will be named.
+ ///
+ /// \param Hiding the declaration that hides the result.
+ ///
+ /// \param InBaseClass whether the result was found in a base
+ /// class of the searched context.
+ void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
+ bool InBaseClass);
+
+ /// Add a new non-declaration result to this result set.
+ void AddResult(Result R);
+
+ /// Enter into a new scope.
+ void EnterNewScope();
+
+ /// Exit from the current scope.
+ void ExitScope();
+
+ /// Ignore this declaration, if it is seen again.
+ void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
+
+ /// Add a visited context.
+ void addVisitedContext(DeclContext *Ctx) {
+ CompletionContext.addVisitedContext(Ctx);
+ }
+
+ /// \name Name lookup predicates
+ ///
+ /// These predicates can be passed to the name lookup functions to filter the
+ /// results of name lookup. All of the predicates have the same type, so that
+ ///
+ //@{
+ bool IsOrdinaryName(const NamedDecl *ND) const;
+ bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
+ bool IsIntegralConstantValue(const NamedDecl *ND) const;
+ bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
+ bool IsNestedNameSpecifier(const NamedDecl *ND) const;
+ bool IsEnum(const NamedDecl *ND) const;
+ bool IsClassOrStruct(const NamedDecl *ND) const;
+ bool IsUnion(const NamedDecl *ND) const;
+ bool IsNamespace(const NamedDecl *ND) const;
+ bool IsNamespaceOrAlias(const NamedDecl *ND) const;
+ bool IsType(const NamedDecl *ND) const;
+ bool IsMember(const NamedDecl *ND) const;
+ bool IsObjCIvar(const NamedDecl *ND) const;
+ bool IsObjCMessageReceiver(const NamedDecl *ND) const;
+ bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
+ bool IsObjCCollection(const NamedDecl *ND) const;
+ bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
+ //@}
+};
+} // namespace
class ResultBuilder::ShadowMapEntry::iterator {
llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
@@ -364,20 +362,18 @@ public:
DeclIndexPair Value;
public:
- pointer(const DeclIndexPair &Value) : Value(Value) { }
+ pointer(const DeclIndexPair &Value) : Value(Value) {}
- const DeclIndexPair *operator->() const {
- return &Value;
- }
+ const DeclIndexPair *operator->() const { return &Value; }
};
iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
iterator(const NamedDecl *SingleDecl, unsigned Index)
- : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
+ : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
iterator(const DeclIndexPair *Iterator)
- : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
+ : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
iterator &operator++() {
if (DeclOrIterator.is<const NamedDecl *>()) {
@@ -386,7 +382,7 @@ public:
return *this;
}
- const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
+ const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
++I;
DeclOrIterator = I;
return *this;
@@ -402,17 +398,15 @@ public:
if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
return reference(ND, SingleDeclIndex);
- return *DeclOrIterator.get<const DeclIndexPair*>();
+ return *DeclOrIterator.get<const DeclIndexPair *>();
}
- pointer operator->() const {
- return pointer(**this);
- }
+ pointer operator->() const { return pointer(**this); }
friend bool operator==(const iterator &X, const iterator &Y) {
- return X.DeclOrIterator.getOpaqueValue()
- == Y.DeclOrIterator.getOpaqueValue() &&
- X.SingleDeclIndex == Y.SingleDeclIndex;
+ return X.DeclOrIterator.getOpaqueValue() ==
+ Y.DeclOrIterator.getOpaqueValue() &&
+ X.SingleDeclIndex == Y.SingleDeclIndex;
}
friend bool operator!=(const iterator &X, const iterator &Y) {
@@ -453,8 +447,7 @@ ResultBuilder::ShadowMapEntry::end() const {
/// \returns a nested name specifier that refers into the target context, or
/// NULL if no qualification is needed.
static NestedNameSpecifier *
-getRequiredQualification(ASTContext &Context,
- const DeclContext *CurContext,
+getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
const DeclContext *TargetContext) {
SmallVector<const DeclContext *, 4> TargetParents;
@@ -472,16 +465,14 @@ getRequiredQualification(ASTContext &Context,
while (!TargetParents.empty()) {
const DeclContext *Parent = TargetParents.pop_back_val();
- if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
+ if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
if (!Namespace->getIdentifier())
continue;
Result = NestedNameSpecifier::Create(Context, Result, Namespace);
- }
- else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
- Result = NestedNameSpecifier::Create(Context, Result,
- false,
- Context.getTypeDeclType(TD).getTypePtr());
+ } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
+ Result = NestedNameSpecifier::Create(
+ Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
}
return Result;
}
@@ -494,8 +485,8 @@ static bool isReservedName(const IdentifierInfo *Id,
return false;
const char *Name = Id->getNameStart();
return Name[0] == '_' &&
- (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
- !doubleUnderscoreOnly));
+ (Name[1] == '_' ||
+ (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
}
// Some declarations have reserved names that we don't want to ever show.
@@ -514,9 +505,9 @@ static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
// This allows for system headers providing private symbols with a single
// underscore.
if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
- SemaRef.SourceMgr.isInSystemHeader(
- SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
- return true;
+ SemaRef.SourceMgr.isInSystemHeader(
+ SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
+ return true;
return false;
}
@@ -550,10 +541,8 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
return false;
if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
- (isa<NamespaceDecl>(ND) &&
- Filter != &ResultBuilder::IsNamespace &&
- Filter != &ResultBuilder::IsNamespaceOrAlias &&
- Filter != nullptr))
+ (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
+ Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
AsNestedNameSpecifier = true;
// Filter out any unwanted results.
@@ -597,8 +586,7 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
R.QualifierIsInformative = false;
if (!R.Qualifier)
- R.Qualifier = getRequiredQualification(SemaRef.Context,
- CurContext,
+ R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
R.Declaration->getDeclContext());
return false;
}
@@ -609,23 +597,23 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (T->getTypeClass()) {
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
- case BuiltinType::Void:
- return STC_Void;
+ case BuiltinType::Void:
+ return STC_Void;
- case BuiltinType::NullPtr:
- return STC_Pointer;
+ case BuiltinType::NullPtr:
+ return STC_Pointer;
- case BuiltinType::Overload:
- case BuiltinType::Dependent:
- return STC_Other;
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ return STC_Other;
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- return STC_ObjectiveC;
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return STC_ObjectiveC;
- default:
- return STC_Arithmetic;
+ default:
+ return STC_Arithmetic;
}
case Type::Complex:
@@ -677,21 +665,21 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
ND = ND->getUnderlyingDecl();
- if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ if (const auto *Type = dyn_cast<TypeDecl>(ND))
return C.getTypeDeclType(Type);
- if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
+ if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
return C.getObjCInterfaceType(Iface);
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getCallResultType();
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
T = Method->getSendResultType();
- else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
- else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
T = Property->getType();
- else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+ else if (const auto *Value = dyn_cast<ValueDecl>(ND))
T = Value->getType();
else
return QualType();
@@ -700,12 +688,12 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
// get down to the likely type of an expression when the entity is
// used.
do {
- if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
+ if (const auto *Ref = T->getAs<ReferenceType>()) {
T = Ref->getPointeeType();
continue;
}
- if (const PointerType *Pointer = T->getAs<PointerType>()) {
+ if (const auto *Pointer = T->getAs<PointerType>()) {
if (Pointer->getPointeeType()->isFunctionType()) {
T = Pointer->getPointeeType();
continue;
@@ -714,12 +702,12 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
break;
}
- if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
+ if (const auto *Block = T->getAs<BlockPointerType>()) {
T = Block->getPointeeType();
continue;
}
- if (const FunctionType *Function = T->getAs<FunctionType>()) {
+ if (const auto *Function = T->getAs<FunctionType>()) {
T = Function->getReturnType();
continue;
}
@@ -738,8 +726,7 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
const DeclContext *LexicalDC = ND->getLexicalDeclContext();
if (LexicalDC->isFunctionOrMethod()) {
// _cmd is relatively rare
- if (const ImplicitParamDecl *ImplicitParam =
- dyn_cast<ImplicitParamDecl>(ND))
+ if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
if (ImplicitParam->getIdentifier() &&
ImplicitParam->getIdentifier()->isStr("_cmd"))
return CCP_ObjC_cmd;
@@ -770,10 +757,10 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
// likely that the user will want to write a type as other declarations.
if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
!(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
- CompletionContext.getKind()
- == CodeCompletionContext::CCC_ObjCMessageReceiver ||
- CompletionContext.getKind()
- == CodeCompletionContext::CCC_ParenthesizedExpression))
+ CompletionContext.getKind() ==
+ CodeCompletionContext::CCC_ObjCMessageReceiver ||
+ CompletionContext.getKind() ==
+ CodeCompletionContext::CCC_ParenthesizedExpression))
return CCP_Type;
return CCP_Declaration;
@@ -783,7 +770,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
// If this is an Objective-C method declaration whose selector matches our
// preferred selector, give it a priority boost.
if (!PreferredSelector.isNull())
- if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
+ if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
if (PreferredSelector == Method->getSelector())
R.Priority += CCD_SelectorMatch;
@@ -797,20 +784,28 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
R.Priority /= CCF_ExactTypeMatch;
// Check for nearly-matching types, based on classification of each.
- else if ((getSimplifiedTypeClass(PreferredType)
- == getSimplifiedTypeClass(TC)) &&
+ else if ((getSimplifiedTypeClass(PreferredType) ==
+ getSimplifiedTypeClass(TC)) &&
!(PreferredType->isEnumeralType() && TC->isEnumeralType()))
R.Priority /= CCF_SimilarTypeMatch;
}
}
}
+DeclContext::lookup_result getConstructors(ASTContext &Context,
+ const CXXRecordDecl *Record) {
+ QualType RecordTy = Context.getTypeDeclType(Record);
+ DeclarationName ConstructorName =
+ Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(RecordTy));
+ return Record->lookup(ConstructorName);
+}
+
void ResultBuilder::MaybeAddConstructorResults(Result R) {
if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
!CompletionContext.wantConstructorResults())
return;
- ASTContext &Context = SemaRef.Context;
const NamedDecl *D = R.Declaration;
const CXXRecordDecl *Record = nullptr;
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
@@ -828,16 +823,8 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) {
if (!Record)
return;
-
- QualType RecordTy = Context.getTypeDeclType(Record);
- DeclarationName ConstructorName
- = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(RecordTy));
- DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
- for (DeclContext::lookup_iterator I = Ctors.begin(),
- E = Ctors.end();
- I != E; ++I) {
- R.Declaration = *I;
+ for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
+ R.Declaration = Ctor;
R.CursorKind = getCursorKindForDecl(R.Declaration);
Results.push_back(R);
}
@@ -919,8 +906,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
continue;
// Protocols are in distinct namespaces from everything else.
- if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
- || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+ if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
+ (IDNS & Decl::IDNS_ObjCProtocol)) &&
I->first->getIdentifierNamespace() != IDNS)
continue;
@@ -942,18 +929,19 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
} else
- AdjustResultPriorityForDecl(R);
+ AdjustResultPriorityForDecl(R);
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
- Namespace);
+ R.Qualifier =
+ NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
- false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ R.Qualifier = NestedNameSpecifier::Create(
+ SemaRef.Context, nullptr, false,
+ SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -967,6 +955,11 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
MaybeAddConstructorResults(R);
}
+static void setInBaseClass(ResultBuilder::Result &R) {
+ R.Priority += CCD_InBaseClass;
+ R.InBaseClass = true;
+}
+
void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
NamedDecl *Hiding, bool InBaseClass = false) {
if (R.Kind != Result::RK_Declaration) {
@@ -976,7 +969,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
}
// Look through using declarations.
- if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+ if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
CodeCompletionResult Result(Using->getTargetDecl(),
getBasePriority(Using->getTargetDecl()),
R.Qualifier);
@@ -1015,27 +1008,27 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
- if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
- Namespace);
- else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
- R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+ R.Qualifier =
+ NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
+ else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
+ R.Qualifier = NestedNameSpecifier::Create(
+ SemaRef.Context, nullptr, false,
+ SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
}
// Adjust the priority if this result comes from a base class.
if (InBaseClass)
- R.Priority += CCD_InBaseClass;
+ setInBaseClass(R);
AdjustResultPriorityForDecl(R);
if (HasObjectTypeQualifiers)
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
if (Method->isInstance()) {
- Qualifiers MethodQuals
- = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
+ Qualifiers MethodQuals = Method->getTypeQualifiers();
if (ObjectTypeQualifiers == MethodQuals)
R.Priority += CCD_ObjectQualifierMatch;
else if (ObjectTypeQualifiers - MethodQuals) {
@@ -1054,7 +1047,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
void ResultBuilder::AddResult(Result R) {
assert(R.Kind != Result::RK_Declaration &&
- "Declaration results need more context");
+ "Declaration results need more context");
Results.push_back(R);
}
@@ -1064,9 +1057,8 @@ void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
/// Exit from the current scope.
void ResultBuilder::ExitScope() {
for (ShadowMap::iterator E = ShadowMaps.back().begin(),
- EEnd = ShadowMaps.back().end();
- E != EEnd;
- ++E)
+ EEnd = ShadowMaps.back().end();
+ E != EEnd; ++E)
E->second.Destroy();
ShadowMaps.pop_back();
@@ -1082,7 +1074,7 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
- else if (SemaRef.getLangOpts().ObjC1) {
+ else if (SemaRef.getLangOpts().ObjC) {
if (isa<ObjCIvarDecl>(ND))
return true;
}
@@ -1107,7 +1099,7 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
- else if (SemaRef.getLangOpts().ObjC1) {
+ else if (SemaRef.getLangOpts().ObjC) {
if (isa<ObjCIvarDecl>(ND))
return true;
}
@@ -1119,7 +1111,7 @@ bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
if (!IsOrdinaryNonTypeName(ND))
return 0;
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
+ if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
if (VD->getType()->isIntegralOrEnumerationType())
return true;
@@ -1135,16 +1127,15 @@ bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
- return (ND->getIdentifierNamespace() & IDNS) &&
- !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
- !isa<ObjCPropertyDecl>(ND);
+ return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
+ !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
}
/// Determines whether the given declaration is suitable as the
/// start of a C++ nested-name-specifier, e.g., a class or namespace.
bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
// Allow us to find class templates, too.
- if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
return SemaRef.isAcceptableNestedNameSpecifier(ND);
@@ -1158,14 +1149,13 @@ bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
/// Determines whether the given declaration is a class or struct.
bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
// Allow us to find class templates, too.
- if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
// For purposes of this check, interfaces match too.
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
- return RD->getTagKind() == TTK_Class ||
- RD->getTagKind() == TTK_Struct ||
- RD->getTagKind() == TTK_Interface;
+ if (const auto *RD = dyn_cast<RecordDecl>(ND))
+ return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
+ RD->getTagKind() == TTK_Interface;
return false;
}
@@ -1173,10 +1163,10 @@ bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
/// Determines whether the given declaration is a union.
bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
// Allow us to find class templates, too.
- if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+ if (const auto *RD = dyn_cast<RecordDecl>(ND))
return RD->getTagKind() == TTK_Union;
return false;
@@ -1250,11 +1240,12 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
return isObjCReceiverType(SemaRef.Context, T);
}
-bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
+bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
+ const NamedDecl *ND) const {
if (IsObjCMessageReceiver(ND))
return true;
- const VarDecl *Var = dyn_cast<VarDecl>(ND);
+ const auto *Var = dyn_cast<VarDecl>(ND);
if (!Var)
return false;
@@ -1287,34 +1278,80 @@ bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
}
namespace {
- /// Visible declaration consumer that adds a code-completion result
- /// for each visible declaration.
- class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
- ResultBuilder &Results;
- DeclContext *CurContext;
- std::vector<FixItHint> FixIts;
- public:
- CodeCompletionDeclConsumer(
- ResultBuilder &Results, DeclContext *CurContext,
- std::vector<FixItHint> FixIts = std::vector<FixItHint>())
- : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {}
+/// Visible declaration consumer that adds a code-completion result
+/// for each visible declaration.
+class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
+ ResultBuilder &Results;
+ DeclContext *InitialLookupCtx;
+ // NamingClass and BaseType are used for access-checking. See
+ // Sema::IsSimplyAccessible for details.
+ CXXRecordDecl *NamingClass;
+ QualType BaseType;
+ std::vector<FixItHint> FixIts;
- void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
- bool InBaseClass) override {
- bool Accessible = true;
- if (Ctx)
- Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
- ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
- false, Accessible, FixIts);
- Results.AddResult(Result, CurContext, Hiding, InBaseClass);
+public:
+ CodeCompletionDeclConsumer(
+ ResultBuilder &Results, DeclContext *InitialLookupCtx,
+ QualType BaseType = QualType(),
+ std::vector<FixItHint> FixIts = std::vector<FixItHint>())
+ : Results(Results), InitialLookupCtx(InitialLookupCtx),
+ FixIts(std::move(FixIts)) {
+ NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
+ // If BaseType was not provided explicitly, emulate implicit 'this->'.
+ if (BaseType.isNull()) {
+ auto ThisType = Results.getSema().getCurrentThisType();
+ if (!ThisType.isNull()) {
+ assert(ThisType->isPointerType());
+ BaseType = ThisType->getPointeeType();
+ if (!NamingClass)
+ NamingClass = BaseType->getAsCXXRecordDecl();
+ }
}
-
- void EnteredContext(DeclContext* Ctx) override {
- Results.addVisitedContext(Ctx);
+ this->BaseType = BaseType;
+ }
+
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override {
+ ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
+ false, IsAccessible(ND, Ctx), FixIts);
+ Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
+ }
+
+ void EnteredContext(DeclContext *Ctx) override {
+ Results.addVisitedContext(Ctx);
+ }
+
+private:
+ bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
+ // Naming class to use for access check. In most cases it was provided
+ // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
+ // for unqualified lookup we fallback to the \p Ctx in which we found the
+ // member.
+ auto *NamingClass = this->NamingClass;
+ QualType BaseType = this->BaseType;
+ if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
+ if (!NamingClass)
+ NamingClass = Cls;
+ // When we emulate implicit 'this->' in an unqualified lookup, we might
+ // end up with an invalid naming class. In that case, we avoid emulating
+ // 'this->' qualifier to satisfy preconditions of the access checking.
+ if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
+ !NamingClass->isDerivedFrom(Cls)) {
+ NamingClass = Cls;
+ BaseType = QualType();
+ }
+ } else {
+ // The decl was found outside the C++ class, so only ObjC access checks
+ // apply. Those do not rely on NamingClass and BaseType, so we clear them
+ // out.
+ NamingClass = nullptr;
+ BaseType = QualType();
}
- };
-}
+ return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
+ }
+};
+} // namespace
/// Add type specifiers for the current language as keyword results.
static void AddTypeSpecifierResults(const LangOptions &LangOpts,
@@ -1347,8 +1384,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Results.getCodeCompletionTUInfo());
if (LangOpts.CPlusPlus) {
// C++-specific
- Results.AddResult(Result("bool", CCP_Type +
- (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
+ Results.AddResult(
+ Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Results.AddResult(Result("class", CCP_Type));
Results.AddResult(Result("wchar_t", CCP_Type));
@@ -1464,14 +1501,11 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
- ResultBuilder &Results,
- bool NeedAt);
+ ResultBuilder &Results, bool NeedAt);
static void AddObjCImplementationResults(const LangOptions &LangOpts,
- ResultBuilder &Results,
- bool NeedAt);
+ ResultBuilder &Results, bool NeedAt);
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
- ResultBuilder &Results,
- bool NeedAt);
+ ResultBuilder &Results, bool NeedAt);
static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
static void AddTypedefResult(ResultBuilder &Results) {
@@ -1509,7 +1543,7 @@ static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
return false;
case Sema::PCC_ForInit:
- return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
+ return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
}
llvm_unreachable("Invalid ParserCompletionContext!");
@@ -1535,8 +1569,7 @@ static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
///
/// This routine provides a fast path where we provide constant strings for
/// common type names.
-static const char *GetCompletionTypeString(QualType T,
- ASTContext &Context,
+static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
const PrintingPolicy &Policy,
CodeCompletionAllocator &Allocator) {
if (!T.getLocalQualifiers()) {
@@ -1549,11 +1582,16 @@ static const char *GetCompletionTypeString(QualType T,
if (TagDecl *Tag = TagT->getDecl())
if (!Tag->hasNameForLinkage()) {
switch (Tag->getTagKind()) {
- case TTK_Struct: return "struct <anonymous>";
- case TTK_Interface: return "__interface <anonymous>";
- case TTK_Class: return "class <anonymous>";
- case TTK_Union: return "union <anonymous>";
- case TTK_Enum: return "enum <anonymous>";
+ case TTK_Struct:
+ return "struct <anonymous>";
+ case TTK_Interface:
+ return "__interface <anonymous>";
+ case TTK_Class:
+ return "class <anonymous>";
+ case TTK_Union:
+ return "union <anonymous>";
+ case TTK_Enum:
+ return "enum <anonymous>";
}
}
}
@@ -1573,10 +1611,8 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) {
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
- Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
- S.Context,
- Policy,
- Allocator));
+ Builder.AddResultTypeChunk(
+ GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Builder.AddTypedTextChunk("this");
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
@@ -1596,11 +1632,76 @@ static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
+static void printOverrideString(llvm::raw_ostream &OS,
+ CodeCompletionString *CCS) {
+ for (const auto &C : *CCS) {
+ if (C.Kind == CodeCompletionString::CK_Optional)
+ printOverrideString(OS, C.Optional);
+ else
+ OS << C.Text;
+ // Add a space after return type.
+ if (C.Kind == CodeCompletionString::CK_ResultType)
+ OS << ' ';
+ }
+}
+
+static void AddOverrideResults(ResultBuilder &Results,
+ const CodeCompletionContext &CCContext,
+ CodeCompletionBuilder &Builder) {
+ Sema &S = Results.getSema();
+ const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
+ // If not inside a class/struct/union return empty.
+ if (!CR)
+ return;
+ // First store overrides within current class.
+ // These are stored by name to make querying fast in the later step.
+ llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
+ for (auto *Method : CR->methods()) {
+ if (!Method->isVirtual() || !Method->getIdentifier())
+ continue;
+ Overrides[Method->getName()].push_back(Method);
+ }
+
+ for (const auto &Base : CR->bases()) {
+ const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+ if (!BR)
+ continue;
+ for (auto *Method : BR->methods()) {
+ if (!Method->isVirtual() || !Method->getIdentifier())
+ continue;
+ const auto it = Overrides.find(Method->getName());
+ bool IsOverriden = false;
+ if (it != Overrides.end()) {
+ for (auto *MD : it->second) {
+ // If the method in current body is not an overload of this virtual
+ // function, then it overrides this one.
+ if (!S.IsOverload(MD, Method, false)) {
+ IsOverriden = true;
+ break;
+ }
+ }
+ }
+ if (!IsOverriden) {
+ // Generates a new CodeCompletionResult by taking this function and
+ // converting it into an override declaration with only one chunk in the
+ // final CodeCompletionString as a TypedTextChunk.
+ std::string OverrideSignature;
+ llvm::raw_string_ostream OS(OverrideSignature);
+ CodeCompletionResult CCR(Method, 0);
+ PrintingPolicy Policy =
+ getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
+ auto *CCS = CCR.createCodeCompletionStringForOverride(
+ S.getPreprocessor(), S.getASTContext(), Builder,
+ /*IncludeBriefComments=*/false, CCContext, Policy);
+ Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
+ }
+ }
+ }
+}
+
/// Add language constructs that show up for "ordinary" names.
-static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
- Scope *S,
- Sema &SemaRef,
- ResultBuilder &Results) {
+static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
+ Sema &SemaRef, ResultBuilder &Results) {
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
@@ -1649,10 +1750,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("declaration");
Results.AddResult(Result(Builder.TakeString()));
+ } else {
+ Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
}
}
- if (SemaRef.getLangOpts().ObjC1)
+ if (SemaRef.getLangOpts().ObjC)
AddObjCTopLevelResults(Results, true);
AddTypedefResult(Results);
@@ -1704,6 +1807,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
if (IsNotInheritanceScope && Results.includeCodePatterns())
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
+
+ // FIXME: This adds override results only if we are at the first word of
+ // the declaration/definition. Also call this from other sides to have
+ // more use-cases.
+ AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
+ Builder);
}
}
LLVM_FALLTHROUGH;
@@ -1717,6 +1826,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("parameters");
Builder.AddChunk(CodeCompletionString::CK_RightAngle);
Results.AddResult(Result(Builder.TakeString()));
+ } else {
+ Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
}
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
@@ -1760,7 +1871,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
- if (SemaRef.getLangOpts().ObjC1)
+ if (SemaRef.getLangOpts().ObjC)
AddObjCStatementResults(Results, true);
if (Results.includeCodePatterns()) {
@@ -1793,7 +1904,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
}
// Switch-specific statements.
- if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
+ if (SemaRef.getCurFunction() &&
+ !SemaRef.getCurFunction()->SwitchStack.empty()) {
// case expression:
Builder.AddTypedTextChunk("case");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1869,10 +1981,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
// "return expression ;" or "return ;", depending on whether we
// know the function is void or not.
bool isVoid = false;
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
+ if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
isVoid = Function->getReturnType()->isVoidType();
- else if (ObjCMethodDecl *Method
- = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
+ else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
isVoid = Method->getReturnType()->isVoidType();
else if (SemaRef.getCurBlock() &&
!SemaRef.getCurBlock()->ReturnType.isNull())
@@ -1900,7 +2011,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
}
- LLVM_FALLTHROUGH;
+ LLVM_FALLTHROUGH;
// Fall through (for statement expressions).
case Sema::PCC_ForInit:
@@ -2087,7 +2198,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
}
}
- if (SemaRef.getLangOpts().ObjC1) {
+ if (SemaRef.getLangOpts().ObjC) {
// Add "super", if we're in an Objective-C class with a superclass.
if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
// The interface can be NULL.
@@ -2146,8 +2257,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
/// type chunk.
static void AddResultTypeChunk(ASTContext &Context,
const PrintingPolicy &Policy,
- const NamedDecl *ND,
- QualType BaseType,
+ const NamedDecl *ND, QualType BaseType,
CodeCompletionBuilder &Result) {
if (!ND)
return;
@@ -2161,24 +2271,24 @@ static void AddResultTypeChunk(ASTContext &Context,
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getReturnType();
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+ else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
if (!BaseType.isNull())
T = Method->getSendResultType(BaseType);
else
T = Method->getReturnType();
- } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
+ } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
T = clang::TypeName::getFullyQualifiedType(T, Context);
} else if (isa<UnresolvedUsingValueDecl>(ND)) {
/* Do nothing: ignore unresolved using declarations*/
- } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
+ } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
if (!BaseType.isNull())
T = Ivar->getUsageType(BaseType);
else
T = Ivar->getType();
- } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
+ } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
T = Value->getType();
- } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
+ } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
if (!BaseType.isNull())
T = Property->getUsageType(BaseType);
else
@@ -2188,8 +2298,8 @@ static void AddResultTypeChunk(ASTContext &Context,
if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
return;
- Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
- Result.getAllocator()));
+ Result.AddResultTypeChunk(
+ GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
}
static void MaybeAddSentinel(Preprocessor &PP,
@@ -2197,7 +2307,7 @@ static void MaybeAddSentinel(Preprocessor &PP,
CodeCompletionBuilder &Result) {
if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
if (Sentinel->getSentinel() == 0) {
- if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
+ if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Result.AddTextChunk(", nil");
else if (PP.isMacroDefined("NULL"))
Result.AddTextChunk(", NULL");
@@ -2295,11 +2405,10 @@ formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
bool SuppressBlock = false,
Optional<ArrayRef<QualType>> ObjCSubsts = None);
-static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
- const ParmVarDecl *Param,
- bool SuppressName = false,
- bool SuppressBlock = false,
- Optional<ArrayRef<QualType>> ObjCSubsts = None) {
+static std::string
+FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
+ bool SuppressName = false, bool SuppressBlock = false,
+ Optional<ArrayRef<QualType>> ObjCSubsts = None) {
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
if (Param->getType()->isDependentType() ||
!Param->getType()->isBlockPointerType()) {
@@ -2315,8 +2424,8 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
ObjCSubstitutionContext::Parameter);
if (ObjCMethodParam) {
- Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
- Type);
+ Result =
+ "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Result += Type.getAsString(Policy) + ")";
if (Param->getIdentifier() && !SuppressName)
Result += Param->getIdentifier()->getName();
@@ -2447,13 +2556,15 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param,
bool Invalid = CharSrcRange.isInvalid();
if (Invalid)
return "";
- StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
+ StringRef srcText =
+ Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
if (Invalid)
return "";
if (srcText.empty() || srcText == "=") {
// Lexer can't determine the value.
- // This happens if the code is incorrect (for example class is forward declared).
+ // This happens if the code is incorrect (for example class is forward
+ // declared).
return "";
}
std::string DefValue(srcText.str());
@@ -2461,7 +2572,8 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param,
// this value always has (or always does not have) '=' in front of it
if (DefValue.at(0) != '=') {
// If we don't have '=' in front of value.
- // Lexer returns built-in types values without '=' and user-defined types values with it.
+ // Lexer returns built-in types values without '=' and user-defined types
+ // values with it.
return " = " + DefValue;
}
return " " + DefValue;
@@ -2501,18 +2613,18 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
// Format the placeholder string.
std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
- PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
+ PlaceholderStr +=
+ GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
if (Function->isVariadic() && P == N - 1)
PlaceholderStr += ", ...";
// Add the placeholder string.
Result.AddPlaceholderChunk(
- Result.getAllocator().CopyString(PlaceholderStr));
+ Result.getAllocator().CopyString(PlaceholderStr));
}
- if (const FunctionProtoType *Proto
- = Function->getType()->getAs<FunctionProtoType>())
+ if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
if (Proto->isVariadic()) {
if (Proto->getNumParams() == 0)
Result.AddPlaceholderChunk("...");
@@ -2522,13 +2634,10 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
}
/// Add template parameter chunks to the given code completion string.
-static void AddTemplateParameterChunks(ASTContext &Context,
- const PrintingPolicy &Policy,
- const TemplateDecl *Template,
- CodeCompletionBuilder &Result,
- unsigned MaxParameters = 0,
- unsigned Start = 0,
- bool InDefaultArg = false) {
+static void AddTemplateParameterChunks(
+ ASTContext &Context, const PrintingPolicy &Policy,
+ const TemplateDecl *Template, CodeCompletionBuilder &Result,
+ unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
bool FirstParameter = true;
// Prefer to take the template parameter names from the first declaration of
@@ -2539,8 +2648,8 @@ static void AddTemplateParameterChunks(ASTContext &Context,
TemplateParameterList::iterator PEnd = Params->end();
if (MaxParameters)
PEnd = Params->begin() + MaxParameters;
- for (TemplateParameterList::iterator P = Params->begin() + Start;
- P != PEnd; ++P) {
+ for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
+ ++P) {
bool HasDefaultArg = false;
std::string PlaceholderStr;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
@@ -2555,8 +2664,8 @@ static void AddTemplateParameterChunks(ASTContext &Context,
}
HasDefaultArg = TTP->hasDefaultArgument();
- } else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ } else if (NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(*P)) {
if (NTTP->getIdentifier())
PlaceholderStr = NTTP->getIdentifier()->getName();
NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
@@ -2598,18 +2707,17 @@ static void AddTemplateParameterChunks(ASTContext &Context,
// Add the placeholder string.
Result.AddPlaceholderChunk(
- Result.getAllocator().CopyString(PlaceholderStr));
+ Result.getAllocator().CopyString(PlaceholderStr));
}
}
/// Add a qualifier to the given code-completion string, if the
/// provided nested-name-specifier is non-NULL.
-static void
-AddQualifierToCompletionString(CodeCompletionBuilder &Result,
- NestedNameSpecifier *Qualifier,
- bool QualifierIsInformative,
- ASTContext &Context,
- const PrintingPolicy &Policy) {
+static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
+ NestedNameSpecifier *Qualifier,
+ bool QualifierIsInformative,
+ ASTContext &Context,
+ const PrintingPolicy &Policy) {
if (!Qualifier)
return;
@@ -2627,25 +2735,24 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result,
static void
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
const FunctionDecl *Function) {
- const FunctionProtoType *Proto
- = Function->getType()->getAs<FunctionProtoType>();
+ const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
if (!Proto || !Proto->getTypeQuals())
return;
// FIXME: Add ref-qualifier!
// Handle single qualifiers without copying
- if (Proto->getTypeQuals() == Qualifiers::Const) {
+ if (Proto->getTypeQuals().hasOnlyConst()) {
Result.AddInformativeChunk(" const");
return;
}
- if (Proto->getTypeQuals() == Qualifiers::Volatile) {
+ if (Proto->getTypeQuals().hasOnlyVolatile()) {
Result.AddInformativeChunk(" volatile");
return;
}
- if (Proto->getTypeQuals() == Qualifiers::Restrict) {
+ if (Proto->getTypeQuals().hasOnlyRestrict()) {
Result.AddInformativeChunk(" restrict");
return;
}
@@ -2670,37 +2777,51 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
return;
switch (Name.getNameKind()) {
- case DeclarationName::CXXOperatorName: {
- const char *OperatorName = nullptr;
- switch (Name.getCXXOverloadedOperator()) {
- case OO_None:
- case OO_Conditional:
- case NUM_OVERLOADED_OPERATORS:
- OperatorName = "operator";
- break;
+ case DeclarationName::CXXOperatorName: {
+ const char *OperatorName = nullptr;
+ switch (Name.getCXXOverloadedOperator()) {
+ case OO_None:
+ case OO_Conditional:
+ case NUM_OVERLOADED_OPERATORS:
+ OperatorName = "operator";
+ break;
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- case OO_##Name: OperatorName = "operator" Spelling; break;
-#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
+ case OO_##Name: \
+ OperatorName = "operator" Spelling; \
+ break;
+#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
#include "clang/Basic/OperatorKinds.def"
- case OO_New: OperatorName = "operator new"; break;
- case OO_Delete: OperatorName = "operator delete"; break;
- case OO_Array_New: OperatorName = "operator new[]"; break;
- case OO_Array_Delete: OperatorName = "operator delete[]"; break;
- case OO_Call: OperatorName = "operator()"; break;
- case OO_Subscript: OperatorName = "operator[]"; break;
- }
- Result.AddTypedTextChunk(OperatorName);
+ case OO_New:
+ OperatorName = "operator new";
+ break;
+ case OO_Delete:
+ OperatorName = "operator delete";
+ break;
+ case OO_Array_New:
+ OperatorName = "operator new[]";
+ break;
+ case OO_Array_Delete:
+ OperatorName = "operator delete[]";
+ break;
+ case OO_Call:
+ OperatorName = "operator()";
+ break;
+ case OO_Subscript:
+ OperatorName = "operator[]";
break;
}
+ Result.AddTypedTextChunk(OperatorName);
+ break;
+ }
case DeclarationName::Identifier:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXLiteralOperatorName:
Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(ND->getNameAsString()));
+ Result.getAllocator().CopyString(ND->getNameAsString()));
break;
case DeclarationName::CXXDeductionGuideName:
@@ -2713,19 +2834,18 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
case DeclarationName::CXXConstructorName: {
CXXRecordDecl *Record = nullptr;
QualType Ty = Name.getCXXNameType();
- if (const RecordType *RecordTy = Ty->getAs<RecordType>())
+ if (const auto *RecordTy = Ty->getAs<RecordType>())
Record = cast<CXXRecordDecl>(RecordTy->getDecl());
- else if (const InjectedClassNameType *InjectedTy
- = Ty->getAs<InjectedClassNameType>())
+ else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Record = InjectedTy->getDecl();
else {
Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(ND->getNameAsString()));
+ Result.getAllocator().CopyString(ND->getNameAsString()));
break;
}
Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(Record->getNameAsString()));
+ Result.getAllocator().CopyString(Record->getNameAsString()));
if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Result.AddChunk(CodeCompletionString::CK_LeftAngle);
AddTemplateParameterChunks(Context, Policy, Template, Result);
@@ -2736,11 +2856,10 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
}
}
-CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
- const CodeCompletionContext &CCContext,
- CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo,
- bool IncludeBriefComments) {
+CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
+ Sema &S, const CodeCompletionContext &CCContext,
+ CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments) {
return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
CCTUInfo, IncludeBriefComments);
}
@@ -2797,13 +2916,10 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
/// \returns Either a new, heap-allocated code completion string describing
/// how to use this result, or NULL to indicate that the string or name of the
/// result is all that is needed.
-CodeCompletionString *
-CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
- Preprocessor &PP,
- const CodeCompletionContext &CCContext,
- CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo,
- bool IncludeBriefComments) {
+CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
+ ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
+ CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments) {
if (Kind == RK_Macro)
return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
@@ -2832,6 +2948,30 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
assert(Kind == RK_Declaration && "Missed a result kind?");
+ return createCodeCompletionStringForDecl(
+ PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
+}
+
+CodeCompletionString *
+CodeCompletionResult::createCodeCompletionStringForOverride(
+ Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
+ bool IncludeBriefComments, const CodeCompletionContext &CCContext,
+ PrintingPolicy &Policy) {
+ std::string OverrideSignature;
+ llvm::raw_string_ostream OS(OverrideSignature);
+ auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
+ /*IncludeBriefComments=*/false,
+ CCContext, Policy);
+ printOverrideString(OS, CCS);
+ OS << " override";
+ Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
+ return Result.TakeString();
+}
+
+CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
+ Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
+ bool IncludeBriefComments, const CodeCompletionContext &CCContext,
+ PrintingPolicy &Policy) {
const NamedDecl *ND = Declaration;
Result.addParentContext(ND->getDeclContext());
@@ -2844,7 +2984,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
if (StartsNestedNameSpecifier) {
Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(ND->getNameAsString()));
+ Result.getAllocator().CopyString(ND->getNameAsString()));
Result.AddTextChunk("::");
return Result.TakeString();
}
@@ -2854,7 +2994,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
+ if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
@@ -2865,7 +3005,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
- if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
+ if (const FunctionTemplateDecl *FunTmpl =
+ dyn_cast<FunctionTemplateDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
@@ -2884,16 +3025,16 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
// FIXME: We need to abstract template parameters better!
bool HasDefaultArg = false;
NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
- LastDeducibleArgument - 1);
+ LastDeducibleArgument - 1);
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
HasDefaultArg = TTP->hasDefaultArgument();
- else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ else if (NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(Param))
HasDefaultArg = NTTP->hasDefaultArgument();
else {
assert(isa<TemplateTemplateParmDecl>(Param));
- HasDefaultArg
- = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
+ HasDefaultArg =
+ cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
}
if (!HasDefaultArg)
@@ -2919,22 +3060,21 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
return Result.TakeString();
}
- if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
+ if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(Template->getNameAsString()));
+ Result.getAllocator().CopyString(Template->getNameAsString()));
Result.AddChunk(CodeCompletionString::CK_LeftAngle);
AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Result.AddChunk(CodeCompletionString::CK_RightAngle);
return Result.TakeString();
}
-
- if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+ if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Selector Sel = Method->getSelector();
if (Sel.isUnarySelector()) {
- Result.AddTypedTextChunk(Result.getAllocator().CopyString(
- Sel.getNameForSlot(0)));
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
return Result.TakeString();
}
@@ -2952,7 +3092,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
}
unsigned Idx = 0;
for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
+ PEnd = Method->param_end();
P != PEnd; (void)++P, ++Idx) {
if (Idx > 0) {
std::string Keyword;
@@ -2979,12 +3119,11 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
if (ParamType->isBlockPointerType() && !DeclaringEntity)
Arg = FormatFunctionParameter(Policy, *P, true,
- /*SuppressBlock=*/false,
- ObjCSubsts);
+ /*SuppressBlock=*/false, ObjCSubsts);
else {
if (ObjCSubsts)
- ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
- ObjCSubstitutionContext::Parameter);
+ ParamType = ParamType.substObjCTypeArgs(
+ Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
ParamType);
Arg += ParamType.getAsString(Policy) + ")";
@@ -3025,7 +3164,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
Ctx, Policy);
Result.AddTypedTextChunk(
- Result.getAllocator().CopyString(ND->getNameAsString()));
+ Result.getAllocator().CopyString(ND->getNameAsString()));
return Result.TakeString();
}
@@ -3037,7 +3176,7 @@ const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
return RC;
// Try to find comment from a property for ObjC methods.
- const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
+ const auto *M = dyn_cast<ObjCMethodDecl>(ND);
if (!M)
return nullptr;
const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
@@ -3049,7 +3188,7 @@ const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
const NamedDecl *ND) {
- const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
+ const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
if (!M || !M->isPropertyAccessor())
return nullptr;
@@ -3072,8 +3211,7 @@ const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
const RawComment *clang::getParameterComment(
const ASTContext &Ctx,
- const CodeCompleteConsumer::OverloadCandidate &Result,
- unsigned ArgIndex) {
+ const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
auto FDecl = Result.getFunction();
if (!FDecl)
return nullptr;
@@ -3089,12 +3227,11 @@ static void AddOverloadParameterChunks(ASTContext &Context,
const FunctionDecl *Function,
const FunctionProtoType *Prototype,
CodeCompletionBuilder &Result,
- unsigned CurrentArg,
- unsigned Start = 0,
+ unsigned CurrentArg, unsigned Start = 0,
bool InOptional = false) {
bool FirstParameter = true;
- unsigned NumParams = Function ? Function->getNumParams()
- : Prototype->getNumParams();
+ unsigned NumParams =
+ Function ? Function->getNumParams() : Prototype->getNumParams();
for (unsigned P = Start; P != NumParams; ++P) {
if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
@@ -3124,14 +3261,15 @@ static void AddOverloadParameterChunks(ASTContext &Context,
const ParmVarDecl *Param = Function->getParamDecl(P);
Placeholder = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
- Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
+ Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
+ Context.getLangOpts());
} else {
Placeholder = Prototype->getParamType(P).getAsString(Policy);
}
if (P == CurrentArg)
Result.AddCurrentParameterChunk(
- Result.getAllocator().CopyString(Placeholder));
+ Result.getAllocator().CopyString(Placeholder));
else
Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
}
@@ -3153,23 +3291,22 @@ static void AddOverloadParameterChunks(ASTContext &Context,
CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
- unsigned CurrentArg, Sema &S,
- CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo,
- bool IncludeBriefComments) const {
+ unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
// FIXME: Set priority, availability appropriately.
- CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
+ CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
+ CXAvailability_Available);
FunctionDecl *FDecl = getFunction();
- const FunctionProtoType *Proto
- = dyn_cast<FunctionProtoType>(getFunctionType());
+ const FunctionProtoType *Proto =
+ dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
// Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
- FT->getReturnType().getAsString(Policy)));
+ FT->getReturnType().getAsString(Policy)));
Result.AddChunk(CodeCompletionString::CK_LeftParen);
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Result.AddChunk(CodeCompletionString::CK_RightParen);
@@ -3183,10 +3320,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
}
AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Result.AddTextChunk(
- Result.getAllocator().CopyString(FDecl->getNameAsString()));
+ Result.getAllocator().CopyString(FDecl->getNameAsString()));
} else {
- Result.AddResultTypeChunk(
- Result.getAllocator().CopyString(
+ Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Proto->getReturnType().getAsString(Policy)));
}
@@ -3216,8 +3352,7 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName,
Priority = CCP_Constant;
// Treat "bool" as a type.
else if (MacroName.equals("bool"))
- Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
-
+ Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
return Priority;
}
@@ -3227,105 +3362,142 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
return CXCursor_UnexposedDecl;
switch (D->getKind()) {
- case Decl::Enum: return CXCursor_EnumDecl;
- case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
- case Decl::Field: return CXCursor_FieldDecl;
- case Decl::Function:
- return CXCursor_FunctionDecl;
- case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
- case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
- case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
-
- case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
- case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
- case Decl::ObjCMethod:
- return cast<ObjCMethodDecl>(D)->isInstanceMethod()
- ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
- case Decl::CXXMethod: return CXCursor_CXXMethod;
- case Decl::CXXConstructor: return CXCursor_Constructor;
- case Decl::CXXDestructor: return CXCursor_Destructor;
- case Decl::CXXConversion: return CXCursor_ConversionFunction;
- case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
- case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
- case Decl::ParmVar: return CXCursor_ParmDecl;
- case Decl::Typedef: return CXCursor_TypedefDecl;
- case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
- case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
- case Decl::Var: return CXCursor_VarDecl;
- case Decl::Namespace: return CXCursor_Namespace;
- case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
- case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
- case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
- case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
- case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
- case Decl::ClassTemplate: return CXCursor_ClassTemplate;
- case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
- case Decl::ClassTemplatePartialSpecialization:
- return CXCursor_ClassTemplatePartialSpecialization;
- case Decl::UsingDirective: return CXCursor_UsingDirective;
- case Decl::StaticAssert: return CXCursor_StaticAssert;
- case Decl::Friend: return CXCursor_FriendDecl;
- case Decl::TranslationUnit: return CXCursor_TranslationUnit;
-
- case Decl::Using:
- case Decl::UnresolvedUsingValue:
- case Decl::UnresolvedUsingTypename:
- return CXCursor_UsingDeclaration;
-
- case Decl::ObjCPropertyImpl:
- switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
- case ObjCPropertyImplDecl::Dynamic:
- return CXCursor_ObjCDynamicDecl;
-
- case ObjCPropertyImplDecl::Synthesize:
- return CXCursor_ObjCSynthesizeDecl;
- }
+ case Decl::Enum:
+ return CXCursor_EnumDecl;
+ case Decl::EnumConstant:
+ return CXCursor_EnumConstantDecl;
+ case Decl::Field:
+ return CXCursor_FieldDecl;
+ case Decl::Function:
+ return CXCursor_FunctionDecl;
+ case Decl::ObjCCategory:
+ return CXCursor_ObjCCategoryDecl;
+ case Decl::ObjCCategoryImpl:
+ return CXCursor_ObjCCategoryImplDecl;
+ case Decl::ObjCImplementation:
+ return CXCursor_ObjCImplementationDecl;
+
+ case Decl::ObjCInterface:
+ return CXCursor_ObjCInterfaceDecl;
+ case Decl::ObjCIvar:
+ return CXCursor_ObjCIvarDecl;
+ case Decl::ObjCMethod:
+ return cast<ObjCMethodDecl>(D)->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl
+ : CXCursor_ObjCClassMethodDecl;
+ case Decl::CXXMethod:
+ return CXCursor_CXXMethod;
+ case Decl::CXXConstructor:
+ return CXCursor_Constructor;
+ case Decl::CXXDestructor:
+ return CXCursor_Destructor;
+ case Decl::CXXConversion:
+ return CXCursor_ConversionFunction;
+ case Decl::ObjCProperty:
+ return CXCursor_ObjCPropertyDecl;
+ case Decl::ObjCProtocol:
+ return CXCursor_ObjCProtocolDecl;
+ case Decl::ParmVar:
+ return CXCursor_ParmDecl;
+ case Decl::Typedef:
+ return CXCursor_TypedefDecl;
+ case Decl::TypeAlias:
+ return CXCursor_TypeAliasDecl;
+ case Decl::TypeAliasTemplate:
+ return CXCursor_TypeAliasTemplateDecl;
+ case Decl::Var:
+ return CXCursor_VarDecl;
+ case Decl::Namespace:
+ return CXCursor_Namespace;
+ case Decl::NamespaceAlias:
+ return CXCursor_NamespaceAlias;
+ case Decl::TemplateTypeParm:
+ return CXCursor_TemplateTypeParameter;
+ case Decl::NonTypeTemplateParm:
+ return CXCursor_NonTypeTemplateParameter;
+ case Decl::TemplateTemplateParm:
+ return CXCursor_TemplateTemplateParameter;
+ case Decl::FunctionTemplate:
+ return CXCursor_FunctionTemplate;
+ case Decl::ClassTemplate:
+ return CXCursor_ClassTemplate;
+ case Decl::AccessSpec:
+ return CXCursor_CXXAccessSpecifier;
+ case Decl::ClassTemplatePartialSpecialization:
+ return CXCursor_ClassTemplatePartialSpecialization;
+ case Decl::UsingDirective:
+ return CXCursor_UsingDirective;
+ case Decl::StaticAssert:
+ return CXCursor_StaticAssert;
+ case Decl::Friend:
+ return CXCursor_FriendDecl;
+ case Decl::TranslationUnit:
+ return CXCursor_TranslationUnit;
+
+ case Decl::Using:
+ case Decl::UnresolvedUsingValue:
+ case Decl::UnresolvedUsingTypename:
+ return CXCursor_UsingDeclaration;
+
+ case Decl::ObjCPropertyImpl:
+ switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
+ case ObjCPropertyImplDecl::Dynamic:
+ return CXCursor_ObjCDynamicDecl;
+
+ case ObjCPropertyImplDecl::Synthesize:
+ return CXCursor_ObjCSynthesizeDecl;
+ }
+ llvm_unreachable("Unexpected Kind!");
+
+ case Decl::Import:
+ return CXCursor_ModuleImportDecl;
+
+ case Decl::ObjCTypeParam:
+ return CXCursor_TemplateTypeParameter;
- case Decl::Import:
- return CXCursor_ModuleImportDecl;
-
- case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
-
- default:
- if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
- switch (TD->getTagKind()) {
- case TTK_Interface: // fall through
- case TTK_Struct: return CXCursor_StructDecl;
- case TTK_Class: return CXCursor_ClassDecl;
- case TTK_Union: return CXCursor_UnionDecl;
- case TTK_Enum: return CXCursor_EnumDecl;
- }
+ default:
+ if (const auto *TD = dyn_cast<TagDecl>(D)) {
+ switch (TD->getTagKind()) {
+ case TTK_Interface: // fall through
+ case TTK_Struct:
+ return CXCursor_StructDecl;
+ case TTK_Class:
+ return CXCursor_ClassDecl;
+ case TTK_Union:
+ return CXCursor_UnionDecl;
+ case TTK_Enum:
+ return CXCursor_EnumDecl;
}
+ }
}
return CXCursor_UnexposedDecl;
}
static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
- bool IncludeUndefined,
+ bool LoadExternal, bool IncludeUndefined,
bool TargetTypeIsPointer = false) {
typedef CodeCompletionResult Result;
Results.EnterNewScope();
- for (Preprocessor::macro_iterator M = PP.macro_begin(),
- MEnd = PP.macro_end();
+ for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
+ MEnd = PP.macro_end(LoadExternal);
M != MEnd; ++M) {
auto MD = PP.getMacroDefinition(M->first);
if (IncludeUndefined || MD) {
- if (MacroInfo *MI = MD.getMacroInfo())
- if (MI->isUsedForHeaderGuard())
- continue;
+ MacroInfo *MI = MD.getMacroInfo();
+ if (MI && MI->isUsedForHeaderGuard())
+ continue;
- Results.AddResult(Result(M->first,
- getMacroUsagePriority(M->first->getName(),
- PP.getLangOpts(),
- TargetTypeIsPointer)));
+ Results.AddResult(
+ Result(M->first, MI,
+ getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
+ TargetTypeIsPointer)));
}
}
Results.ExitScope();
-
}
static void AddPrettyFunctionResults(const LangOptions &LangOpts,
@@ -3350,8 +3522,8 @@ static void HandleCodeCompleteResults(Sema *S,
CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
}
-static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
- Sema::ParserCompletionContext PCC) {
+static CodeCompletionContext
+mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
switch (PCC) {
case Sema::PCC_Namespace:
return CodeCompletionContext::CCC_TopLevel;
@@ -3381,14 +3553,16 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
case Sema::PCC_ForInit:
if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
- S.getLangOpts().ObjC1)
+ S.getLangOpts().ObjC)
return CodeCompletionContext::CCC_ParenthesizedExpression;
else
return CodeCompletionContext::CCC_Expression;
case Sema::PCC_Expression:
- case Sema::PCC_Condition:
return CodeCompletionContext::CCC_Expression;
+ case Sema::PCC_Condition:
+ return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
+ S.getASTContext().BoolTy);
case Sema::PCC_Statement:
return CodeCompletionContext::CCC_Statement;
@@ -3421,7 +3595,6 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
while (isa<BlockDecl>(CurContext))
CurContext = CurContext->getParent();
-
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
if (!Method || !Method->isVirtual())
return;
@@ -3441,9 +3614,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
// If we need a nested-name-specifier, add one now.
if (!InContext) {
- NestedNameSpecifier *NNS
- = getRequiredQualification(S.Context, CurContext,
- Overridden->getDeclContext());
+ NestedNameSpecifier *NNS = getRequiredQualification(
+ S.Context, CurContext, Overridden->getDeclContext());
if (NNS) {
std::string Str;
llvm::raw_string_ostream OS(Str);
@@ -3453,8 +3625,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
} else if (!InContext->Equals(Overridden->getDeclContext()))
continue;
- Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
- Overridden->getNameAsString()));
+ Builder.AddTypedTextChunk(
+ Results.getAllocator().CopyString(Overridden->getNameAsString()));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
bool FirstParam = true;
for (auto P : Method->parameters()) {
@@ -3467,11 +3639,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
Results.getAllocator().CopyString(P->getIdentifier()->getName()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
- CCP_SuperCompletion,
- CXCursor_CXXMethod,
- CXAvailability_Available,
- Overridden));
+ Results.AddResult(CodeCompletionResult(
+ Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
+ CXAvailability_Available, Overridden));
Results.Ignore(Overridden);
}
}
@@ -3493,39 +3663,35 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
PP.getHeaderSearchInfo().collectAllModules(Modules);
for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
Builder.AddTypedTextChunk(
- Builder.getAllocator().CopyString(Modules[I]->Name));
- Results.AddResult(Result(Builder.TakeString(),
- CCP_Declaration,
- CXCursor_ModuleImportDecl,
- Modules[I]->isAvailable()
- ? CXAvailability_Available
- : CXAvailability_NotAvailable));
+ Builder.getAllocator().CopyString(Modules[I]->Name));
+ Results.AddResult(Result(
+ Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
+ Modules[I]->isAvailable() ? CXAvailability_Available
+ : CXAvailability_NotAvailable));
}
} else if (getLangOpts().Modules) {
// Load the named module.
- Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
- Module::AllVisible,
- /*IsInclusionDirective=*/false);
+ Module *Mod =
+ PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
+ /*IsInclusionDirective=*/false);
// Enumerate submodules.
if (Mod) {
for (Module::submodule_iterator Sub = Mod->submodule_begin(),
- SubEnd = Mod->submodule_end();
+ SubEnd = Mod->submodule_end();
Sub != SubEnd; ++Sub) {
Builder.AddTypedTextChunk(
- Builder.getAllocator().CopyString((*Sub)->Name));
- Results.AddResult(Result(Builder.TakeString(),
- CCP_Declaration,
- CXCursor_ModuleImportDecl,
- (*Sub)->isAvailable()
- ? CXAvailability_Available
- : CXAvailability_NotAvailable));
+ Builder.getAllocator().CopyString((*Sub)->Name));
+ Results.AddResult(Result(
+ Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
+ (*Sub)->isAvailable() ? CXAvailability_Available
+ : CXAvailability_NotAvailable));
}
}
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
- Results.data(),Results.size());
+ Results.data(), Results.size());
}
void Sema::CodeCompleteOrdinaryName(Scope *S,
@@ -3572,10 +3738,9 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
// If we are in a C++ non-static member function, check the qualifiers on
// the member function to filter/prioritize the results list.
- if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
- if (CurMethod->isInstance())
- Results.setObjectTypeQualifiers(
- Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
+ auto ThisType = getCurrentThisType();
+ if (!ThisType.isNull())
+ Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
@@ -3609,28 +3774,30 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
}
if (CodeCompleter->includeMacros())
- AddMacroResults(PP, Results, false);
+ AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
- Results.data(),Results.size());
+ Results.data(), Results.size());
}
static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
- bool AtArgumentExpression,
- bool IsSuper,
+ bool AtArgumentExpression, bool IsSuper,
ResultBuilder &Results);
void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
bool AllowNonIdentifiers,
bool AllowNestedNameSpecifiers) {
typedef CodeCompletionResult Result;
- ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- AllowNestedNameSpecifiers
- ? CodeCompletionContext::CCC_PotentiallyQualifiedName
- : CodeCompletionContext::CCC_Name);
+ ResultBuilder Results(
+ *this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ AllowNestedNameSpecifiers
+ // FIXME: Try to separate codepath leading here to deduce whether we
+ // need an existing symbol or a new one.
+ ? CodeCompletionContext::CCC_SymbolOrNewName
+ : CodeCompletionContext::CCC_NewName);
Results.EnterNewScope();
// Type qualifiers can come after names.
@@ -3671,12 +3838,11 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
DS.getTypeSpecType() == DeclSpec::TST_typename &&
DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- !DS.isTypeAltiVecVector() &&
- S &&
+ !DS.isTypeAltiVecVector() && S &&
(S->getFlags() & Scope::DeclScope) != 0 &&
(S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
- Scope::FunctionPrototypeScope |
- Scope::AtCatchScope)) == 0) {
+ Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
+ 0) {
ParsedType T = DS.getRepAsType();
if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
AddClassMessageCompletions(*this, S, T, None, false, false, Results);
@@ -3685,15 +3851,14 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
// Note that we intentionally suppress macro results here, since we do not
// encourage using macros to produce the names of entities.
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
struct Sema::CodeCompleteExpressionData {
CodeCompleteExpressionData(QualType PreferredType = QualType())
- : PreferredType(PreferredType), IntegralConstantExpression(false),
- ObjCCollection(false) { }
+ : PreferredType(PreferredType), IntegralConstantExpression(false),
+ ObjCCollection(false) {}
QualType PreferredType;
bool IntegralConstantExpression;
@@ -3737,31 +3902,35 @@ void Sema::CodeCompleteExpression(Scope *S,
bool PreferredTypeIsPointer = false;
if (!Data.PreferredType.isNull())
- PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
- || Data.PreferredType->isMemberPointerType()
- || Data.PreferredType->isBlockPointerType();
+ PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
+ Data.PreferredType->isMemberPointerType() ||
+ Data.PreferredType->isBlockPointerType();
- if (S->getFnParent() &&
- !Data.ObjCCollection &&
+ if (S->getFnParent() && !Data.ObjCCollection &&
!Data.IntegralConstantExpression)
AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
- AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
+ AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
+ PreferredTypeIsPointer);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
+void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
+ return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
+}
+
void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
if (E.isInvalid())
CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
- else if (getLangOpts().ObjC1)
+ else if (getLangOpts().ObjC)
CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
}
/// The set of properties that have already been added, referenced by
/// property name.
-typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
+typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
/// Retrieve the container definition, if any?
static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
@@ -3819,11 +3988,13 @@ static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
-static void AddObjCProperties(
- const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
- bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
- AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
- bool IsBaseExprStatement = false, bool IsClassProperty = false) {
+static void
+AddObjCProperties(const CodeCompletionContext &CCContext,
+ ObjCContainerDecl *Container, bool AllowCategories,
+ bool AllowNullaryMethods, DeclContext *CurContext,
+ AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
+ bool IsBaseExprStatement = false,
+ bool IsClassProperty = false, bool InOriginalClass = true) {
typedef CodeCompletionResult Result;
// Retrieve the definition.
@@ -3838,8 +4009,10 @@ static void AddObjCProperties(
// expressions.
if (!P->getType().getTypePtr()->isBlockPointerType() ||
!IsBaseExprStatement) {
- Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
- CurContext);
+ Result R = Result(P, Results.getBasePriority(P), nullptr);
+ if (!InOriginalClass)
+ setInBaseClass(R);
+ Results.MaybeAddResult(R, CurContext);
return;
}
@@ -3850,8 +4023,10 @@ static void AddObjCProperties(
findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
BlockProtoLoc);
if (!BlockLoc) {
- Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
- CurContext);
+ Result R = Result(P, Results.getBasePriority(P), nullptr);
+ if (!InOriginalClass)
+ setInBaseClass(R);
+ Results.MaybeAddResult(R, CurContext);
return;
}
@@ -3862,9 +4037,10 @@ static void AddObjCProperties(
AddObjCBlockCall(Container->getASTContext(),
getCompletionPrintingPolicy(Results.getSema()), Builder, P,
BlockLoc, BlockProtoLoc);
- Results.MaybeAddResult(
- Result(Builder.TakeString(), P, Results.getBasePriority(P)),
- CurContext);
+ Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
+ if (!InOriginalClass)
+ setInBaseClass(R);
+ Results.MaybeAddResult(R, CurContext);
// Provide additional block setter completion iff the base expression is a
// statement and the block property is mutable.
@@ -3890,13 +4066,15 @@ static void AddObjCProperties(
// otherwise the setter completion should show up before the default
// property completion, as we normally want to use the result of the
// call.
- Results.MaybeAddResult(
+ Result R =
Result(Builder.TakeString(), P,
Results.getBasePriority(P) +
(BlockLoc.getTypePtr()->getReturnType()->isVoidType()
? CCD_BlockPropertySetter
- : -CCD_BlockPropertySetter)),
- CurContext);
+ : -CCD_BlockPropertySetter));
+ if (!InOriginalClass)
+ setInBaseClass(R);
+ Results.MaybeAddResult(R, CurContext);
}
};
@@ -3924,10 +4102,11 @@ static void AddObjCProperties(
AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(Name->getName()));
- Results.MaybeAddResult(
- Result(Builder.TakeString(), M,
- CCP_MemberDeclaration + CCD_MethodAsProperty),
- CurContext);
+ Result R = Result(Builder.TakeString(), M,
+ CCP_MemberDeclaration + CCD_MethodAsProperty);
+ if (!InOriginalClass)
+ setInBaseClass(R);
+ Results.MaybeAddResult(R, CurContext);
};
if (IsClassProperty) {
@@ -3953,42 +4132,47 @@ static void AddObjCProperties(
for (auto *P : Protocol->protocols())
AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
- IsBaseExprStatement, IsClassProperty);
- } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
+ IsBaseExprStatement, IsClassProperty,
+ /*InOriginalClass*/ false);
+ } else if (ObjCInterfaceDecl *IFace =
+ dyn_cast<ObjCInterfaceDecl>(Container)) {
if (AllowCategories) {
// Look through categories.
for (auto *Cat : IFace->known_categories())
AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
- IsBaseExprStatement, IsClassProperty);
+ IsBaseExprStatement, IsClassProperty,
+ InOriginalClass);
}
// Look through protocols.
for (auto *I : IFace->all_referenced_protocols())
AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
- IsBaseExprStatement, IsClassProperty);
+ IsBaseExprStatement, IsClassProperty,
+ /*InOriginalClass*/ false);
// Look in the superclass.
if (IFace->getSuperClass())
AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
AllowNullaryMethods, CurContext, AddedProperties,
- Results, IsBaseExprStatement, IsClassProperty);
- } else if (const ObjCCategoryDecl *Category
- = dyn_cast<ObjCCategoryDecl>(Container)) {
+ Results, IsBaseExprStatement, IsClassProperty,
+ /*InOriginalClass*/ false);
+ } else if (const auto *Category =
+ dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
for (auto *P : Category->protocols())
AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
- IsBaseExprStatement, IsClassProperty);
+ IsBaseExprStatement, IsClassProperty,
+ /*InOriginalClass*/ false);
}
}
-static void AddRecordMembersCompletionResults(Sema &SemaRef,
- ResultBuilder &Results, Scope *S,
- QualType BaseType,
- RecordDecl *RD,
- Optional<FixItHint> AccessOpFixIt) {
+static void
+AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
+ Scope *S, QualType BaseType, RecordDecl *RD,
+ Optional<FixItHint> AccessOpFixIt) {
// Indicate that we are performing a member access, and the cv-qualifiers
// for the base object type.
Results.setObjectTypeQualifiers(BaseType.getQualifiers());
@@ -3997,8 +4181,8 @@ static void AddRecordMembersCompletionResults(Sema &SemaRef,
Results.allowNestedNameSpecifiers();
std::vector<FixItHint> FixIts;
if (AccessOpFixIt)
- FixIts.emplace_back(AccessOpFixIt.getValue());
- CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts));
+ FixIts.emplace_back(AccessOpFixIt.getValue());
+ CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
SemaRef.CodeCompleter->includeGlobals(),
/*IncludeDependentBases=*/true,
@@ -4039,7 +4223,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
enum CodeCompletionContext::Kind contextKind;
if (IsArrow) {
- if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
+ if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
ConvertedBaseType = Ptr->getPointeeType();
}
@@ -4059,7 +4243,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
CodeCompleter->getCodeCompletionTUInfo(), CCContext,
&ResultBuilder::IsMember);
- auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
+ auto DoCompletion = [&](Expr *Base, bool IsArrow,
+ Optional<FixItHint> AccessOpFixIt) -> bool {
if (!Base)
return false;
@@ -4113,7 +4298,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
CurContext, AddedProperties, Results,
- IsBaseExprStatement);
+ IsBaseExprStatement, /*IsClassProperty*/ false,
+ /*InOriginalClass*/ false);
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
// Objective-C instance variable access.
@@ -4126,7 +4312,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
// Add all ivars from this class and its superclasses.
if (Class) {
- CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Results.setFilter(&ResultBuilder::IsObjCIvar);
LookupVisibleDecls(
Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
@@ -4188,8 +4374,8 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
return;
ResultBuilder::LookupFilter Filter = nullptr;
- enum CodeCompletionContext::Kind ContextKind
- = CodeCompletionContext::CCC_Other;
+ enum CodeCompletionContext::Kind ContextKind =
+ CodeCompletionContext::CCC_Other;
switch ((DeclSpec::TST)TagSpec) {
case DeclSpec::TST_enum:
Filter = &ResultBuilder::IsEnum;
@@ -4231,7 +4417,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
- Results.data(),Results.size());
+ Results.data(), Results.size());
}
static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
@@ -4255,8 +4441,7 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Results.EnterNewScope();
AddTypeQualifierResults(DS, Results, LangOpts);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -4291,6 +4476,9 @@ void Sema::CodeCompleteCase(Scope *S) {
return;
SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
+ // Condition expression might be invalid, do not continue in this case.
+ if (!Switch->getCond())
+ return;
QualType type = Switch->getCond()->IgnoreImplicit()->getType();
if (!type->isEnumeralType()) {
CodeCompleteExpressionData Data(type);
@@ -4318,9 +4506,9 @@ void Sema::CodeCompleteCase(Scope *S) {
continue;
Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
- if (EnumConstantDecl *Enumerator
- = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
+ if (auto *Enumerator =
+ dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
// We look into the AST of the case statement to determine which
// enumerator was named. Alternatively, we could compute the value of
// the integral constant expression, then compare it against the
@@ -4366,7 +4554,7 @@ void Sema::CodeCompleteCase(Scope *S) {
Results.ExitScope();
if (CodeCompleter->includeMacros()) {
- AddMacroResults(PP, Results, false);
+ AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
@@ -4385,10 +4573,9 @@ static bool anyNullArguments(ArrayRef<Expr *> Args) {
typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
-static void mergeCandidatesWithResults(Sema &SemaRef,
- SmallVectorImpl<ResultCandidate> &Results,
- OverloadCandidateSet &CandidateSet,
- SourceLocation Loc) {
+static void mergeCandidatesWithResults(
+ Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
+ OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
if (!CandidateSet.empty()) {
// Sort the overload candidate set by placing the best overloads first.
std::stable_sort(
@@ -4399,7 +4586,7 @@ static void mergeCandidatesWithResults(Sema &SemaRef,
});
// Add the remaining viable overload candidates as code-completion results.
- for (auto &Candidate : CandidateSet) {
+ for (OverloadCandidate &Candidate : CandidateSet) {
if (Candidate.Function && Candidate.Function->isDeleted())
continue;
if (Candidate.Viable)
@@ -4411,22 +4598,21 @@ static void mergeCandidatesWithResults(Sema &SemaRef,
/// Get the type of the Nth parameter from a given set of overload
/// candidates.
static QualType getParamType(Sema &SemaRef,
- ArrayRef<ResultCandidate> Candidates,
- unsigned N) {
+ ArrayRef<ResultCandidate> Candidates, unsigned N) {
// Given the overloads 'Candidates' for a function call matching all arguments
// up to N, return the type of the Nth parameter if it is the same for all
// overload candidates.
QualType ParamType;
for (auto &Candidate : Candidates) {
- if (auto FType = Candidate.getFunctionType())
- if (auto Proto = dyn_cast<FunctionProtoType>(FType))
+ if (const auto *FType = Candidate.getFunctionType())
+ if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
if (N < Proto->getNumParams()) {
if (ParamType.isNull())
ParamType = Proto->getParamType(N);
else if (!SemaRef.Context.hasSameUnqualifiedType(
- ParamType.getNonReferenceType(),
- Proto->getParamType(N).getNonReferenceType()))
+ ParamType.getNonReferenceType(),
+ Proto->getParamType(N).getNonReferenceType()))
// Otherwise return a default-constructed QualType.
return QualType();
}
@@ -4435,41 +4621,28 @@ static QualType getParamType(Sema &SemaRef,
return ParamType;
}
-static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
- MutableArrayRef<ResultCandidate> Candidates,
- unsigned CurrentArg,
- bool CompleteExpressionWithCurrentArg = true) {
- QualType ParamType;
- if (CompleteExpressionWithCurrentArg)
- ParamType = getParamType(SemaRef, Candidates, CurrentArg);
-
- if (ParamType.isNull())
- SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
- else
- SemaRef.CodeCompleteExpression(S, ParamType);
-
- if (!Candidates.empty())
- SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
- Candidates.data(),
- Candidates.size());
+static QualType
+ProduceSignatureHelp(Sema &SemaRef, Scope *S,
+ MutableArrayRef<ResultCandidate> Candidates,
+ unsigned CurrentArg, SourceLocation OpenParLoc) {
+ if (Candidates.empty())
+ return QualType();
+ SemaRef.CodeCompleter->ProcessOverloadCandidates(
+ SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
+ return getParamType(SemaRef, Candidates, CurrentArg);
}
-void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
+QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
+ ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc) {
if (!CodeCompleter)
- return;
-
- // When we're code-completing for a call, we fall back to ordinary
- // name code-completion whenever we can't produce specific
- // results. We may want to revisit this strategy in the future,
- // e.g., by merging the two kinds of results.
+ return QualType();
// FIXME: Provide support for variadic template functions.
-
// Ignore type-dependent call expressions entirely.
if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
Expr::hasAnyTypeDependentArguments(Args)) {
- CodeCompleteOrdinaryName(S, PCC_Expression);
- return;
+ return QualType();
}
// Build an overload candidate set based on the functions we find.
@@ -4498,13 +4671,12 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
/*SuppressUsedConversions=*/false,
- /*PartialOverloading=*/true,
- FirstArgumentIsBase);
+ /*PartialOverloading=*/true, FirstArgumentIsBase);
} else {
FunctionDecl *FD = nullptr;
- if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
+ if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
- else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
+ else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
FD = dyn_cast<FunctionDecl>(DRE->getDecl());
if (FD) { // We check whether it's a resolved function declaration.
if (!getLangOpts().CPlusPlus ||
@@ -4521,8 +4693,8 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
// call operator, so we check if it does and add them as candidates.
// A complete type is needed to lookup for member function call operators.
if (isCompleteType(Loc, NakedFn->getType())) {
- DeclarationName OpName = Context.DeclarationNames
- .getCXXOperatorName(OO_Call);
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Call);
LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
LookupQualifiedName(R, DC);
R.suppressDiagnostics();
@@ -4542,7 +4714,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
if (auto FP = T->getAs<FunctionProtoType>()) {
if (!TooManyArguments(FP->getNumParams(), Args.size(),
- /*PartialOverloading=*/true) ||
+ /*PartialOverloading=*/true) ||
FP->isVariadic())
Results.push_back(ResultCandidate(FP));
} else if (auto FT = T->getAs<FunctionType>())
@@ -4550,49 +4722,67 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Results.push_back(ResultCandidate(FT));
}
}
-
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
- CodeCompleteOverloadResults(*this, S, Results, Args.size(),
- !CandidateSet.empty());
+ QualType ParamType =
+ ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
+ return !CandidateSet.empty() ? ParamType : QualType();
}
-void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
- ArrayRef<Expr *> Args) {
+QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
+ SourceLocation Loc,
+ ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc) {
if (!CodeCompleter)
- return;
+ return QualType();
// A complete type is needed to lookup for constructors.
CXXRecordDecl *RD =
isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
- if (!RD) {
- CodeCompleteExpression(S, Type);
- return;
- }
+ if (!RD)
+ return Type;
// FIXME: Provide support for member initializers.
// FIXME: Provide support for variadic template constructors.
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- for (auto C : LookupConstructors(RD)) {
- if (auto FD = dyn_cast<FunctionDecl>(C)) {
- AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
- Args, CandidateSet,
+ for (NamedDecl *C : LookupConstructors(RD)) {
+ if (auto *FD = dyn_cast<FunctionDecl>(C)) {
+ AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
+ CandidateSet,
/*SuppressUsedConversions=*/false,
/*PartialOverloading=*/true);
- } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
- AddTemplateOverloadCandidate(FTD,
- DeclAccessPair::make(FTD, C->getAccess()),
- /*ExplicitTemplateArgs=*/nullptr,
- Args, CandidateSet,
- /*SuppressUsedConversions=*/false,
- /*PartialOverloading=*/true);
+ } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
+ AddTemplateOverloadCandidate(
+ FTD, DeclAccessPair::make(FTD, C->getAccess()),
+ /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
+ /*SuppressUsedConversions=*/false,
+ /*PartialOverloading=*/true);
}
}
SmallVector<ResultCandidate, 8> Results;
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
- CodeCompleteOverloadResults(*this, S, Results, Args.size());
+ return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
+}
+
+QualType Sema::ProduceCtorInitMemberSignatureHelp(
+ Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
+ ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
+ if (!CodeCompleter)
+ return QualType();
+
+ CXXConstructorDecl *Constructor =
+ dyn_cast<CXXConstructorDecl>(ConstructorDecl);
+ if (!Constructor)
+ return QualType();
+ // FIXME: Add support for Base class constructors as well.
+ if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
+ Constructor->getParent(), SS, TemplateTypeTy, II))
+ return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
+ MemberDecl->getLocation(), ArgExprs,
+ OpenParLoc);
+ return QualType();
}
void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
@@ -4602,7 +4792,12 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
return;
}
- CodeCompleteExpression(S, VD->getType());
+ CodeCompleteExpressionData Data;
+ Data.PreferredType = VD->getType();
+ // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
+ Data.IgnoreDecls.push_back(VD);
+
+ CodeCompleteExpression(S, Data);
}
void Sema::CodeCompleteReturn(Scope *S) {
@@ -4610,9 +4805,9 @@ void Sema::CodeCompleteReturn(Scope *S) {
if (isa<BlockDecl>(CurContext)) {
if (BlockScopeInfo *BSI = getCurBlock())
ResultType = BSI->ReturnType;
- } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
+ } else if (const auto *Function = dyn_cast<FunctionDecl>(CurContext))
ResultType = Function->getReturnType();
- else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
+ else if (const auto *Method = dyn_cast<ObjCMethodDecl>(CurContext))
ResultType = Method->getReturnType();
if (ResultType.isNull())
@@ -4676,21 +4871,99 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
- AddMacroResults(PP, Results, false);
+ AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
- Results.data(),Results.size());
+ Results.data(), Results.size());
+}
+
+static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
+ tok::TokenKind Op) {
+ if (!LHS)
+ return QualType();
+
+ QualType LHSType = LHS->getType();
+ if (LHSType->isPointerType()) {
+ if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
+ return S.getASTContext().getPointerDiffType();
+ // Pointer difference is more common than subtracting an int from a pointer.
+ if (Op == tok::minus)
+ return LHSType;
+ }
+
+ switch (Op) {
+ // No way to infer the type of RHS from LHS.
+ case tok::comma:
+ return QualType();
+ // Prefer the type of the left operand for all of these.
+ // Arithmetic operations.
+ case tok::plus:
+ case tok::plusequal:
+ case tok::minus:
+ case tok::minusequal:
+ case tok::percent:
+ case tok::percentequal:
+ case tok::slash:
+ case tok::slashequal:
+ case tok::star:
+ case tok::starequal:
+ // Assignment.
+ case tok::equal:
+ // Comparison operators.
+ case tok::equalequal:
+ case tok::exclaimequal:
+ case tok::less:
+ case tok::lessequal:
+ case tok::greater:
+ case tok::greaterequal:
+ case tok::spaceship:
+ return LHS->getType();
+ // Binary shifts are often overloaded, so don't try to guess those.
+ case tok::greatergreater:
+ case tok::greatergreaterequal:
+ case tok::lessless:
+ case tok::lesslessequal:
+ if (LHSType->isIntegralOrEnumerationType())
+ return S.getASTContext().IntTy;
+ return QualType();
+ // Logical operators, assume we want bool.
+ case tok::ampamp:
+ case tok::pipepipe:
+ case tok::caretcaret:
+ return S.getASTContext().BoolTy;
+ // Operators often used for bit manipulation are typically used with the type
+ // of the left argument.
+ case tok::pipe:
+ case tok::pipeequal:
+ case tok::caret:
+ case tok::caretequal:
+ case tok::amp:
+ case tok::ampequal:
+ if (LHSType->isIntegralOrEnumerationType())
+ return LHSType;
+ return QualType();
+ // RHS should be a pointer to a member of the 'LHS' type, but we can't give
+ // any particular type here.
+ case tok::periodstar:
+ case tok::arrowstar:
+ return QualType();
+ default:
+ // FIXME(ibiryukov): handle the missing op, re-add the assertion.
+ // assert(false && "unhandled binary op");
+ return QualType();
+ }
}
-void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
- if (LHS)
- CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
+void Sema::CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op) {
+ auto PreferredType = getPreferredTypeOfBinaryRHS(*this, LHS, Op);
+ if (!PreferredType.isNull())
+ CodeCompleteExpression(S, PreferredType);
else
CodeCompleteOrdinaryName(S, PCC_Expression);
}
void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
- bool EnteringContext) {
+ bool EnteringContext, QualType BaseType) {
if (SS.isEmpty() || !CodeCompleter)
return;
@@ -4699,7 +4972,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// it can be useful for global code completion which have information about
// contexts/symbols that are not in the AST.
if (SS.isInvalid()) {
- CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
+ CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
CC.setCXXScopeSpecifier(SS);
HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
return;
@@ -4717,7 +4990,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_Name);
+ CodeCompletionContext::CCC_Symbol);
Results.EnterNewScope();
// The "template" keyword can follow "::" in the grammar, but only
@@ -4737,7 +5010,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
if (CodeCompleter->includeNamespaceLevelDecls() ||
(!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
- CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
/*IncludeGlobalScope=*/true,
/*IncludeDependentBases=*/true,
@@ -4757,7 +5030,10 @@ void Sema::CodeCompleteUsing(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_PotentiallyQualifiedName,
+ // This can be both a using alias or using
+ // declaration, in the former we expect a new name and a
+ // symbol in the latter case.
+ CodeCompletionContext::CCC_SymbolOrNewName,
&ResultBuilder::IsNestedNameSpecifier);
Results.EnterNewScope();
@@ -4797,7 +5073,7 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
Results.data(), Results.size());
}
-void Sema::CodeCompleteNamespaceDecl(Scope *S) {
+void Sema::CodeCompleteNamespaceDecl(Scope *S) {
if (!CodeCompleter)
return;
@@ -4805,14 +5081,14 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
if (!S->getParent())
Ctx = Context.getTranslationUnitDecl();
- bool SuppressedGlobalResults
- = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
+ bool SuppressedGlobalResults =
+ Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
SuppressedGlobalResults
- ? CodeCompletionContext::CCC_Namespace
- : CodeCompletionContext::CCC_Other,
+ ? CodeCompletionContext::CCC_Namespace
+ : CodeCompletionContext::CCC_Other,
&ResultBuilder::IsNamespace);
if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
@@ -4822,7 +5098,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
// definition of each namespace.
std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
for (DeclContext::specific_decl_iterator<NamespaceDecl>
- NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
+ NS(Ctx->decls_begin()),
+ NSEnd(Ctx->decls_end());
NS != NSEnd; ++NS)
OrigToLatest[NS->getOriginalNamespace()] = *NS;
@@ -4830,22 +5107,21 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
// namespace to the list of results.
Results.EnterNewScope();
for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
- NS = OrigToLatest.begin(),
- NSEnd = OrigToLatest.end();
+ NS = OrigToLatest.begin(),
+ NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
- Results.AddResult(CodeCompletionResult(
- NS->second, Results.getBasePriority(NS->second),
- nullptr),
- CurContext, nullptr, false);
+ Results.AddResult(
+ CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
+ nullptr),
+ CurContext, nullptr, false);
Results.ExitScope();
}
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
-void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
+void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
if (!CodeCompleter)
return;
@@ -4858,9 +5134,8 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteOperatorName(Scope *S) {
@@ -4875,8 +5150,8 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
Results.EnterNewScope();
// Add the names of overloadable operators.
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- if (std::strcmp(Spelling, "?")) \
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
+ if (std::strcmp(Spelling, "?")) \
Results.AddResult(Result(Spelling));
#include "clang/Basic/OperatorKinds.def"
@@ -4896,20 +5171,19 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
}
void Sema::CodeCompleteConstructorInitializer(
- Decl *ConstructorD,
- ArrayRef <CXXCtorInitializer *> Initializers) {
+ Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
if (!ConstructorD)
return;
AdjustDeclIfTemplate(ConstructorD);
- CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
+ auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor)
return;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_PotentiallyQualifiedName);
+ CodeCompletionContext::CCC_Symbol);
Results.EnterNewScope();
// Fill in any already-initialized fields or base classes.
@@ -4917,39 +5191,96 @@ void Sema::CodeCompleteConstructorInitializer(
llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
if (Initializers[I]->isBaseInitializer())
- InitializedBases.insert(
- Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
+ InitializedBases.insert(Context.getCanonicalType(
+ QualType(Initializers[I]->getBaseClass(), 0)));
else
- InitializedFields.insert(cast<FieldDecl>(
- Initializers[I]->getAnyMember()));
+ InitializedFields.insert(
+ cast<FieldDecl>(Initializers[I]->getAnyMember()));
}
// Add completions for base classes.
- CodeCompletionBuilder Builder(Results.getAllocator(),
- Results.getCodeCompletionTUInfo());
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
bool SawLastInitializer = Initializers.empty();
CXXRecordDecl *ClassDecl = Constructor->getParent();
+
+ auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
+ CodeCompletionBuilder Builder(Results.getAllocator(),
+ Results.getCodeCompletionTUInfo());
+ Builder.AddTypedTextChunk(Name);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ if (const auto *Function = dyn_cast<FunctionDecl>(ND))
+ AddFunctionParameterChunks(PP, Policy, Function, Builder);
+ else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
+ AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
+ Builder);
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ return Builder.TakeString();
+ };
+ auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
+ const NamedDecl *ND) {
+ CodeCompletionBuilder Builder(Results.getAllocator(),
+ Results.getCodeCompletionTUInfo());
+ Builder.AddTypedTextChunk(Name);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk(Type);
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ if (ND) {
+ auto CCR = CodeCompletionResult(
+ Builder.TakeString(), ND,
+ SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
+ if (isa<FieldDecl>(ND))
+ CCR.CursorKind = CXCursor_MemberRef;
+ return Results.AddResult(CCR);
+ }
+ return Results.AddResult(CodeCompletionResult(
+ Builder.TakeString(),
+ SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
+ };
+ auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
+ const char *Name, const FieldDecl *FD) {
+ if (!RD)
+ return AddDefaultCtorInit(Name,
+ FD ? Results.getAllocator().CopyString(
+ FD->getType().getAsString(Policy))
+ : Name,
+ FD);
+ auto Ctors = getConstructors(Context, RD);
+ if (Ctors.begin() == Ctors.end())
+ return AddDefaultCtorInit(Name, Name, RD);
+ for (const NamedDecl *Ctor : Ctors) {
+ auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
+ CCR.CursorKind = getCursorKindForDecl(Ctor);
+ Results.AddResult(CCR);
+ }
+ };
+ auto AddBase = [&](const CXXBaseSpecifier &Base) {
+ const char *BaseName =
+ Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
+ const auto *RD = Base.getType()->getAsCXXRecordDecl();
+ AddCtorsWithName(
+ RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
+ BaseName, nullptr);
+ };
+ auto AddField = [&](const FieldDecl *FD) {
+ const char *FieldName =
+ Results.getAllocator().CopyString(FD->getIdentifier()->getName());
+ const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
+ AddCtorsWithName(
+ RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
+ FieldName, FD);
+ };
+
for (const auto &Base : ClassDecl->bases()) {
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
- SawLastInitializer
- = !Initializers.empty() &&
- Initializers.back()->isBaseInitializer() &&
- Context.hasSameUnqualifiedType(Base.getType(),
- QualType(Initializers.back()->getBaseClass(), 0));
+ SawLastInitializer =
+ !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
+ Context.hasSameUnqualifiedType(
+ Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
- Builder.AddTypedTextChunk(
- Results.getAllocator().CopyString(
- Base.getType().getAsString(Policy)));
- Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- Builder.AddPlaceholderChunk("args");
- Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
- SawLastInitializer? CCP_NextInitializer
- : CCP_MemberDeclaration));
+ AddBase(Base);
SawLastInitializer = false;
}
@@ -4957,23 +5288,14 @@ void Sema::CodeCompleteConstructorInitializer(
for (const auto &Base : ClassDecl->vbases()) {
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
- SawLastInitializer
- = !Initializers.empty() &&
- Initializers.back()->isBaseInitializer() &&
- Context.hasSameUnqualifiedType(Base.getType(),
- QualType(Initializers.back()->getBaseClass(), 0));
+ SawLastInitializer =
+ !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
+ Context.hasSameUnqualifiedType(
+ Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
- Builder.AddTypedTextChunk(
- Builder.getAllocator().CopyString(
- Base.getType().getAsString(Policy)));
- Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- Builder.AddPlaceholderChunk("args");
- Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
- SawLastInitializer? CCP_NextInitializer
- : CCP_MemberDeclaration));
+ AddBase(Base);
SawLastInitializer = false;
}
@@ -4981,27 +5303,16 @@ void Sema::CodeCompleteConstructorInitializer(
for (auto *Field : ClassDecl->fields()) {
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
.second) {
- SawLastInitializer
- = !Initializers.empty() &&
- Initializers.back()->isAnyMemberInitializer() &&
- Initializers.back()->getAnyMember() == Field;
+ SawLastInitializer = !Initializers.empty() &&
+ Initializers.back()->isAnyMemberInitializer() &&
+ Initializers.back()->getAnyMember() == Field;
continue;
}
if (!Field->getDeclName())
continue;
- Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
- Field->getIdentifier()->getName()));
- Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- Builder.AddPlaceholderChunk("args");
- Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
- SawLastInitializer? CCP_NextInitializer
- : CCP_MemberDeclaration,
- CXCursor_MemberRef,
- CXAvailability_Available,
- Field));
+ AddField(Field);
SawLastInitializer = false;
}
Results.ExitScope();
@@ -5042,9 +5353,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
for (; S && !isNamespaceScope(S); S = S->getParent()) {
for (const auto *D : S->decls()) {
const auto *Var = dyn_cast<VarDecl>(D);
- if (!Var ||
- !Var->hasLocalStorage() ||
- Var->hasAttr<BlocksAttr>())
+ if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
continue;
if (Known.insert(Var->getIdentifier()).second)
@@ -5065,26 +5374,25 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
/// Macro that optionally prepends an "@" to the string literal passed in via
/// Keyword, depending on whether NeedAt is true or false.
-#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
+#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
static void AddObjCImplementationResults(const LangOptions &LangOpts,
- ResultBuilder &Results,
- bool NeedAt) {
+ ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
// Since we have an implementation, we can end it.
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- if (LangOpts.ObjC2) {
+ if (LangOpts.ObjC) {
// @dynamic
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
// @synthesize
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
@@ -5092,22 +5400,21 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts,
}
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
- ResultBuilder &Results,
- bool NeedAt) {
+ ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
// Since we have an interface or protocol, we can end it.
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
- if (LangOpts.ObjC2) {
+ if (LangOpts.ObjC) {
// @property
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
// @required
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
// @optional
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
}
}
@@ -5117,7 +5424,7 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
Results.getCodeCompletionTUInfo());
// @class name ;
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
@@ -5126,26 +5433,27 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
// @interface name
// FIXME: Could introduce the whole pattern, including superclasses and
// such.
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
// @protocol name
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("protocol");
Results.AddResult(Result(Builder.TakeString()));
// @implementation name
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
}
// @compatibility_alias name
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
+ Builder.AddTypedTextChunk(
+ OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("alias");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -5188,7 +5496,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
Results.getSema().getLangOpts().ConstStrings)
EncodeType = "const char[]";
Builder.AddResultTypeChunk(EncodeType);
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("type-name");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
@@ -5196,7 +5504,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
// @protocol ( protocol-name )
Builder.AddResultTypeChunk("Protocol *");
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("protocol-name");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
@@ -5204,7 +5512,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
// @selector ( selector )
Builder.AddResultTypeChunk("SEL");
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("selector");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
@@ -5212,21 +5520,21 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
// @"string"
Builder.AddResultTypeChunk("NSString *");
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Builder.AddPlaceholderChunk("string");
Builder.AddTextChunk("\"");
Results.AddResult(Result(Builder.TakeString()));
// @[objects, ...]
Builder.AddResultTypeChunk("NSArray *");
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Builder.AddPlaceholderChunk("objects, ...");
Builder.AddChunk(CodeCompletionString::CK_RightBracket);
Results.AddResult(Result(Builder.TakeString()));
// @{key : object, ...}
Builder.AddResultTypeChunk("NSDictionary *");
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Builder.AddPlaceholderChunk("key");
Builder.AddChunk(CodeCompletionString::CK_Colon);
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -5250,7 +5558,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
if (Results.includeCodePatterns()) {
// @try { statements } @catch ( declaration ) { statements } @finally
// { statements }
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
@@ -5269,14 +5577,14 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
}
// @throw
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
if (Results.includeCodePatterns()) {
// @synchronized ( expression ) { statements }
- Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
@@ -5289,14 +5597,13 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
}
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
- ResultBuilder &Results,
- bool NeedAt) {
+ ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
- if (LangOpts.ObjC2)
- Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
+ if (LangOpts.ObjC)
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
}
void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
@@ -5348,14 +5655,12 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
return true;
// Check for more than one of { assign, copy, retain, strong, weak }.
- unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_retain |
- ObjCDeclSpec::DQ_PR_strong |
- ObjCDeclSpec::DQ_PR_weak);
- if (AssignCopyRetMask &&
- AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
+ unsigned AssignCopyRetMask =
+ Attributes &
+ (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
+ ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
+ ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
+ if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
@@ -5433,11 +5738,10 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
enum ObjCMethodKind {
MK_Any, ///< Any kind of method, provided it means other specified criteria.
MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
- MK_OneArgSelector ///< One-argument selector.
+ MK_OneArgSelector ///< One-argument selector.
};
-static bool isAcceptableObjCSelector(Selector Sel,
- ObjCMethodKind WantKind,
+static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
ArrayRef<IdentifierInfo *> SelIdents,
bool AllowSameLength = true) {
unsigned NumSelIdents = SelIdents.size();
@@ -5445,9 +5749,12 @@ static bool isAcceptableObjCSelector(Selector Sel,
return false;
switch (WantKind) {
- case MK_Any: break;
- case MK_ZeroArgSelector: return Sel.isUnarySelector();
- case MK_OneArgSelector: return Sel.getNumArgs() == 1;
+ case MK_Any:
+ break;
+ case MK_ZeroArgSelector:
+ return Sel.isUnarySelector();
+ case MK_OneArgSelector:
+ return Sel.getNumArgs() == 1;
}
if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
@@ -5468,11 +5775,9 @@ static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
AllowSameLength);
}
-namespace {
- /// A set of selectors, which is used to avoid introducing multiple
- /// completions with the same selector into the result set.
- typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
-}
+/// A set of selectors, which is used to avoid introducing multiple
+/// completions with the same selector into the result set.
+typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
/// Add all of the Objective-C methods in the given Objective-C
/// container to the set of results.
@@ -5505,7 +5810,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
Container = getContainerDef(Container);
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
- for (auto *M : Container->methods()) {
+ for (ObjCMethodDecl *M : Container->methods()) {
// The instance methods on the root class can be messaged via the
// metaclass.
if (M->isInstanceMethod() == WantInstanceMethods ||
@@ -5522,16 +5827,16 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
- R.Priority += CCD_InBaseClass;
+ setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
}
}
// Visit the protocols of protocols.
- if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+ if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition()) {
- const ObjCList<ObjCProtocolDecl> &Protocols
- = Protocol->getReferencedProtocols();
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
@@ -5544,19 +5849,19 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
return;
// Add methods in protocols.
- for (auto *I : IFace->protocols())
+ for (ObjCProtocolDecl *I : IFace->protocols())
AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, false, IsRootClass);
// Add methods in categories.
- for (auto *CatDecl : IFace->known_categories()) {
+ for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
CurContext, Selectors, AllowSameLength, Results,
InOriginalClass, IsRootClass);
// Add a categories protocol methods.
- const ObjCList<ObjCProtocolDecl> &Protocols
- = CatDecl->getReferencedProtocols();
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ CatDecl->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
@@ -5584,13 +5889,12 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
IsRootClass);
}
-
void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
// Try to find the interface where getters might live.
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
if (!Class) {
- if (ObjCCategoryDecl *Category
- = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
+ if (ObjCCategoryDecl *Category =
+ dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Class = Category->getClassInterface();
if (!Class)
@@ -5613,11 +5917,10 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
// Try to find the interface where setters might live.
- ObjCInterfaceDecl *Class
- = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
+ ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
if (!Class) {
- if (ObjCCategoryDecl *Category
- = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
+ if (ObjCCategoryDecl *Category =
+ dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Class = Category->getClassInterface();
if (!Class)
@@ -5631,8 +5934,8 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Results.EnterNewScope();
VisitedSelectorSet Selectors;
- AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
- Selectors, /*AllowSameLength=*/true, Results);
+ AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
+ /*AllowSameLength=*/true, Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
@@ -5663,9 +5966,9 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
ObjCDeclSpec::DQ_Oneway)) == 0) {
- Results.AddResult("bycopy");
- Results.AddResult("byref");
- Results.AddResult("oneway");
+ Results.AddResult("bycopy");
+ Results.AddResult("byref");
+ Results.AddResult("oneway");
}
if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
Results.AddResult("nonnull");
@@ -5710,7 +6013,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
CodeCompleter->loadExternal());
if (CodeCompleter->includeMacros())
- AddMacroResults(PP, Results, false);
+ AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
@@ -5721,7 +6024,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
/// common uses of Objective-C. This routine returns that class type,
/// or NULL if no better result could be determined.
static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
- ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
+ auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
if (!Msg)
return nullptr;
@@ -5741,8 +6044,8 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
ObjCInterfaceDecl *IFace = nullptr;
switch (Msg->getReceiverKind()) {
case ObjCMessageExpr::Class:
- if (const ObjCObjectType *ObjType
- = Msg->getClassReceiver()->getAs<ObjCObjectType>())
+ if (const ObjCObjectType *ObjType =
+ Msg->getClassReceiver()->getAs<ObjCObjectType>())
IFace = ObjType->getInterface();
break;
@@ -5764,27 +6067,27 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
ObjCInterfaceDecl *Super = IFace->getSuperClass();
if (Method->isInstanceMethod())
return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
- .Case("retain", IFace)
- .Case("strong", IFace)
- .Case("autorelease", IFace)
- .Case("copy", IFace)
- .Case("copyWithZone", IFace)
- .Case("mutableCopy", IFace)
- .Case("mutableCopyWithZone", IFace)
- .Case("awakeFromCoder", IFace)
- .Case("replacementObjectFromCoder", IFace)
+ .Case("retain", IFace)
+ .Case("strong", IFace)
+ .Case("autorelease", IFace)
+ .Case("copy", IFace)
+ .Case("copyWithZone", IFace)
+ .Case("mutableCopy", IFace)
+ .Case("mutableCopyWithZone", IFace)
+ .Case("awakeFromCoder", IFace)
+ .Case("replacementObjectFromCoder", IFace)
+ .Case("class", IFace)
+ .Case("classForCoder", IFace)
+ .Case("superclass", Super)
+ .Default(nullptr);
+
+ return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
+ .Case("new", IFace)
+ .Case("alloc", IFace)
+ .Case("allocWithZone", IFace)
.Case("class", IFace)
- .Case("classForCoder", IFace)
.Case("superclass", Super)
.Default(nullptr);
-
- return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
- .Case("new", IFace)
- .Case("alloc", IFace)
- .Case("allocWithZone", IFace)
- .Case("class", IFace)
- .Case("superclass", Super)
- .Default(nullptr);
}
// Add a special completion for a message send to "super", which fills in the
@@ -5803,10 +6106,10 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
///
/// \returns the Objective-C method declaration that would be invoked by
/// this "super" completion. If NULL, no completion was added.
-static ObjCMethodDecl *AddSuperSendCompletion(
- Sema &S, bool NeedSuperKeyword,
- ArrayRef<IdentifierInfo *> SelIdents,
- ResultBuilder &Results) {
+static ObjCMethodDecl *
+AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
+ ArrayRef<IdentifierInfo *> SelIdents,
+ ResultBuilder &Results) {
ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
if (!CurMethod)
return nullptr;
@@ -5826,7 +6129,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
if (!SuperMethod) {
for (const auto *Cat : Class->known_categories()) {
if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
- CurMethod->isInstanceMethod())))
+ CurMethod->isInstanceMethod())))
break;
}
}
@@ -5841,8 +6144,8 @@ static ObjCMethodDecl *AddSuperSendCompletion(
return nullptr;
for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
- CurPEnd = CurMethod->param_end(),
- SuperP = SuperMethod->param_begin();
+ CurPEnd = CurMethod->param_end(),
+ SuperP = SuperMethod->param_begin();
CurP != CurPEnd; ++CurP, ++SuperP) {
// Make sure the parameter types are compatible.
if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
@@ -5860,8 +6163,7 @@ static ObjCMethodDecl *AddSuperSendCompletion(
// Give this completion a return type.
AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
- Results.getCompletionContext().getBaseType(),
- Builder);
+ Results.getCompletionContext().getBaseType(), Builder);
// If we need the "super" keyword, add it (plus some spacing).
if (NeedSuperKeyword) {
@@ -5872,11 +6174,11 @@ static ObjCMethodDecl *AddSuperSendCompletion(
Selector Sel = CurMethod->getSelector();
if (Sel.isUnarySelector()) {
if (NeedSuperKeyword)
- Builder.AddTextChunk(Builder.getAllocator().CopyString(
- Sel.getNameForSlot(0)));
+ Builder.AddTextChunk(
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
else
- Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
- Sel.getNameForSlot(0)));
+ Builder.AddTypedTextChunk(
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
} else {
ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
@@ -5885,20 +6187,17 @@ static ObjCMethodDecl *AddSuperSendCompletion(
if (I < SelIdents.size())
Builder.AddInformativeChunk(
- Builder.getAllocator().CopyString(
- Sel.getNameForSlot(I) + ":"));
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
else if (NeedSuperKeyword || I > SelIdents.size()) {
Builder.AddTextChunk(
- Builder.getAllocator().CopyString(
- Sel.getNameForSlot(I) + ":"));
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
- (*CurP)->getIdentifier()->getName()));
+ (*CurP)->getIdentifier()->getName()));
} else {
Builder.AddTypedTextChunk(
- Builder.getAllocator().CopyString(
- Sel.getNameForSlot(I) + ":"));
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
- (*CurP)->getIdentifier()->getName()));
+ (*CurP)->getIdentifier()->getName()));
}
}
}
@@ -5910,12 +6209,13 @@ static ObjCMethodDecl *AddSuperSendCompletion(
void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
typedef CodeCompletionResult Result;
- ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_ObjCMessageReceiver,
- getLangOpts().CPlusPlus11
- ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
- : &ResultBuilder::IsObjCMessageReceiver);
+ ResultBuilder Results(
+ *this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext::CCC_ObjCMessageReceiver,
+ getLangOpts().CPlusPlus11
+ ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
+ : &ResultBuilder::IsObjCMessageReceiver);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
Results.EnterNewScope();
@@ -5939,10 +6239,9 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
Results.ExitScope();
if (CodeCompleter->includeMacros())
- AddMacroResults(PP, Results, false);
+ AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
-
}
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
@@ -5965,8 +6264,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
// send [super ...] is actually calling an instance method on the
// current object.
return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
- AtArgumentExpression,
- CDecl);
+ AtArgumentExpression, CDecl);
}
// Fall through to send to the superclass in CDecl.
@@ -5974,13 +6272,12 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
// "super" may be the name of a type or variable. Figure out which
// it is.
IdentifierInfo *Super = getSuperIdentifier();
- NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
- LookupOrdinaryName);
+ NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
// "super" names an interface. Use it.
} else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
- if (const ObjCObjectType *Iface
- = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
+ if (const ObjCObjectType *Iface =
+ Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
CDecl = Iface->getInterface();
} else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
// "super" names an unresolved type; we can't be more specific.
@@ -5990,11 +6287,10 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
SourceLocation TemplateKWLoc;
UnqualifiedId id;
id.setIdentifier(Super, SuperLoc);
- ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
- false, false);
+ ExprResult SuperExpr =
+ ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false);
return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
- SelIdents,
- AtArgumentExpression);
+ SelIdents, AtArgumentExpression);
}
// Fall through
@@ -6025,8 +6321,8 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
if (R.Priority <= BestPriority) {
const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
if (NumSelIdents <= Method->param_size()) {
- QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
- ->getType();
+ QualType MyPreferredType =
+ Method->parameters()[NumSelIdents - 1]->getType();
if (R.Priority < BestPriority || PreferredType.isNull()) {
BestPriority = R.Priority;
PreferredType = MyPreferredType;
@@ -6045,8 +6341,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
- bool AtArgumentExpression,
- bool IsSuper,
+ bool AtArgumentExpression, bool IsSuper,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
ObjCInterfaceDecl *CDecl = nullptr;
@@ -6067,8 +6362,8 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
// If this is a send-to-super, try to add the special "super" send
// completion.
if (IsSuper) {
- if (ObjCMethodDecl *SuperMethod
- = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
+ if (ObjCMethodDecl *SuperMethod =
+ AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
@@ -6079,9 +6374,8 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
VisitedSelectorSet Selectors;
if (CDecl)
- AddObjCMethods(CDecl, false, MK_Any, SelIdents,
- SemaRef.CurContext, Selectors, AtArgumentExpression,
- Results);
+ AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
+ Selectors, AtArgumentExpression, Results);
else {
// We're messaging "id" as a type; provide all class/factory methods.
@@ -6100,11 +6394,10 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
}
for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
- MEnd = SemaRef.MethodPool.end();
+ MEnd = SemaRef.MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.second;
- MethList && MethList->getMethod();
- MethList = MethList->getNext()) {
+ MethList && MethList->getMethod(); MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
@@ -6127,10 +6420,11 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
QualType T = this->GetTypeFromParser(Receiver);
- ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
- T, SelIdents));
+ ResultBuilder Results(
+ *this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
+ SelIdents));
AddClassMessageCompletions(*this, S, Receiver, SelIdents,
AtArgumentExpression, IsSuper, Results);
@@ -6141,8 +6435,8 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
// code-complete the expression using the corresponding parameter type as
// our preferred type, improving completion results.
if (AtArgumentExpression) {
- QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
- SelIdents.size());
+ QualType PreferredType =
+ getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
@@ -6150,8 +6444,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
return;
}
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
@@ -6171,10 +6464,11 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
return;
RecExpr = Conv.get();
}
- QualType ReceiverType = RecExpr? RecExpr->getType()
- : Super? Context.getObjCObjectPointerType(
+ QualType ReceiverType = RecExpr
+ ? RecExpr->getType()
+ : Super ? Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(Super))
- : Context.getObjCIdType();
+ : Context.getObjCIdType();
// If we're messaging an expression with type "id" or "Class", check
// whether we know something special about the receiver that allows
@@ -6182,13 +6476,12 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
if (ReceiverType->isObjCClassType())
- return CodeCompleteObjCClassMessage(S,
- ParsedType::make(Context.getObjCInterfaceType(IFace)),
- SelIdents,
- AtArgumentExpression, Super);
+ return CodeCompleteObjCClassMessage(
+ S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
+ AtArgumentExpression, Super);
- ReceiverType = Context.getObjCObjectPointerType(
- Context.getObjCInterfaceType(IFace));
+ ReceiverType =
+ Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
}
} else if (RecExpr && getLangOpts().CPlusPlus) {
ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
@@ -6199,18 +6492,19 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
}
// Build the set of methods we can see.
- ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
- ReceiverType, SelIdents));
+ ResultBuilder Results(
+ *this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
+ ReceiverType, SelIdents));
Results.EnterNewScope();
// If this is a send-to-super, try to add the special "super" send
// completion.
if (Super) {
- if (ObjCMethodDecl *SuperMethod
- = AddSuperSendCompletion(*this, false, SelIdents, Results))
+ if (ObjCMethodDecl *SuperMethod =
+ AddSuperSendCompletion(*this, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
@@ -6229,30 +6523,29 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
ReceiverType->isObjCQualifiedClassType()) {
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
- AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
- CurContext, Selectors, AtArgumentExpression, Results);
+ AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
+ Selectors, AtArgumentExpression, Results);
}
}
// Handle messages to a qualified ID ("id<foo>").
- else if (const ObjCObjectPointerType *QualID
- = ReceiverType->getAsObjCQualifiedIdType()) {
+ else if (const ObjCObjectPointerType *QualID =
+ ReceiverType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
for (auto *I : QualID->quals())
- AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
- Selectors, AtArgumentExpression, Results);
+ AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
+ AtArgumentExpression, Results);
}
// Handle messages to a pointer to interface type.
- else if (const ObjCObjectPointerType *IFacePtr
- = ReceiverType->getAsObjCInterfacePointerType()) {
+ else if (const ObjCObjectPointerType *IFacePtr =
+ ReceiverType->getAsObjCInterfacePointerType()) {
// Search the class, its superclasses, etc., for instance methods.
AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
- CurContext, Selectors, AtArgumentExpression,
- Results);
+ CurContext, Selectors, AtArgumentExpression, Results);
// Search protocols for instance methods.
for (auto *I : IFacePtr->quals())
- AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
- Selectors, AtArgumentExpression, Results);
+ AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
+ AtArgumentExpression, Results);
}
// Handle messages to "id".
else if (ReceiverType->isObjCIdType()) {
@@ -6276,8 +6569,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
MEnd = MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.first;
- MethList && MethList->getMethod();
- MethList = MethList->getNext()) {
+ MethList && MethList->getMethod(); MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
@@ -6294,15 +6586,14 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
}
Results.ExitScope();
-
// If we're actually at the argument expression (rather than prior to the
// selector), we're actually performing code completion for an expression.
// Determine whether we have a single, best method. If so, we can
// code-complete the expression using the corresponding parameter type as
// our preferred type, improving completion results.
if (AtArgumentExpression) {
- QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
- SelIdents.size());
+ QualType PreferredType =
+ getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
@@ -6310,9 +6601,8 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
return;
}
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
- Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCForCollection(Scope *S,
@@ -6336,8 +6626,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
// If we have an external source, load the entire class method
// pool from the AST file.
if (ExternalSource) {
- for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
- I != N; ++I) {
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
+ ++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || MethodPool.count(Sel))
continue;
@@ -6351,7 +6641,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
CodeCompletionContext::CCC_SelectorName);
Results.EnterNewScope();
for (GlobalMethodPool::iterator M = MethodPool.begin(),
- MEnd = MethodPool.end();
+ MEnd = MethodPool.end();
M != MEnd; ++M) {
Selector Sel = M->first;
@@ -6361,8 +6651,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (Sel.isUnarySelector()) {
- Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
- Sel.getNameForSlot(0)));
+ Builder.AddTypedTextChunk(
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Results.AddResult(Builder.TakeString());
continue;
}
@@ -6371,8 +6661,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
if (I == SelIdents.size()) {
if (!Accumulator.empty()) {
- Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
- Accumulator));
+ Builder.AddInformativeChunk(
+ Builder.getAllocator().CopyString(Accumulator));
Accumulator.clear();
}
}
@@ -6380,7 +6670,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S,
Accumulator += Sel.getNameForSlot(I);
Accumulator += ':';
}
- Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Results.AddResult(Builder.TakeString());
}
Results.ExitScope();
@@ -6400,13 +6690,14 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
// Record any protocols we find.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
if (!OnlyForwardDeclarations || !Proto->hasDefinition())
- Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
- CurContext, nullptr, false);
+ Results.AddResult(
+ Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
+ nullptr, false);
}
}
void Sema::CodeCompleteObjCProtocolReferences(
- ArrayRef<IdentifierLocPair> Protocols) {
+ ArrayRef<IdentifierLocPair> Protocols) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
@@ -6418,8 +6709,7 @@ void Sema::CodeCompleteObjCProtocolReferences(
// already seen.
// FIXME: This doesn't work when caching code-completion results.
for (const IdentifierLocPair &Pair : Protocols)
- if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
- Pair.second))
+ if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Results.Ignore(Protocol);
// Add all protocols.
@@ -6465,8 +6755,9 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
(!OnlyUnimplemented || !Class->getImplementation()))
- Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
- CurContext, nullptr, false);
+ Results.AddResult(
+ Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
+ nullptr, false);
}
}
@@ -6496,8 +6787,8 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Results.EnterNewScope();
// Make sure that we ignore the class we're currently defining.
- NamedDecl *CurClass
- = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+ NamedDecl *CurClass =
+ LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Results.Ignore(CurClass);
@@ -6543,9 +6834,10 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
// Ignore any categories we find that have already been implemented by this
// interface.
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
- NamedDecl *CurClass
- = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
- if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
+ NamedDecl *CurClass =
+ LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+ if (ObjCInterfaceDecl *Class =
+ dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
for (const auto *Cat : Class->visible_categories())
CategoryNames.insert(Cat->getIdentifier());
}
@@ -6556,9 +6848,9 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
for (const auto *D : TU->decls())
if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
if (CategoryNames.insert(Category->getIdentifier()).second)
- Results.AddResult(Result(Category, Results.getBasePriority(Category),
- nullptr),
- CurContext, nullptr, false);
+ Results.AddResult(
+ Result(Category, Results.getBasePriority(Category), nullptr),
+ CurContext, nullptr, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
@@ -6573,8 +6865,8 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
// Find the corresponding interface. If we couldn't find the interface, the
// program itself is ill-formed. However, we'll try to be helpful still by
// providing the list of all of the categories we know about.
- NamedDecl *CurClass
- = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+ NamedDecl *CurClass =
+ LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
if (!Class)
return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
@@ -6609,15 +6901,13 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CCContext);
+ CodeCompleter->getCodeCompletionTUInfo(), CCContext);
// Figure out where this @synthesize lives.
- ObjCContainerDecl *Container
- = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
- if (!Container ||
- (!isa<ObjCImplementationDecl>(Container) &&
- !isa<ObjCCategoryImplDecl>(Container)))
+ ObjCContainerDecl *Container =
+ dyn_cast_or_null<ObjCContainerDecl>(CurContext);
+ if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
return;
// Ignore any properties that have already been implemented.
@@ -6629,8 +6919,8 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
// Add any properties that we find.
AddedPropertiesSet AddedProperties;
Results.EnterNewScope();
- if (ObjCImplementationDecl *ClassImpl
- = dyn_cast<ObjCImplementationDecl>(Container))
+ if (ObjCImplementationDecl *ClassImpl =
+ dyn_cast<ObjCImplementationDecl>(Container))
AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
/*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
@@ -6645,37 +6935,37 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
- IdentifierInfo *PropertyName) {
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(
+ Scope *S, IdentifierInfo *PropertyName) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
// Figure out where this @synthesize lives.
- ObjCContainerDecl *Container
- = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
- if (!Container ||
- (!isa<ObjCImplementationDecl>(Container) &&
- !isa<ObjCCategoryImplDecl>(Container)))
+ ObjCContainerDecl *Container =
+ dyn_cast_or_null<ObjCContainerDecl>(CurContext);
+ if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
return;
// Figure out which interface we're looking into.
ObjCInterfaceDecl *Class = nullptr;
- if (ObjCImplementationDecl *ClassImpl
- = dyn_cast<ObjCImplementationDecl>(Container))
+ if (ObjCImplementationDecl *ClassImpl =
+ dyn_cast<ObjCImplementationDecl>(Container))
Class = ClassImpl->getClassInterface();
else
- Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
- ->getClassInterface();
+ Class = cast<ObjCCategoryImplDecl>(Container)
+ ->getCategoryDecl()
+ ->getClassInterface();
// Determine the type of the property we're synthesizing.
QualType PropertyType = Context.getObjCIdType();
if (Class) {
if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
- PropertyType
- = Property->getType().getNonReferenceType().getUnqualifiedType();
+ PropertyType =
+ Property->getType().getNonReferenceType().getUnqualifiedType();
// Give preference to ivars
Results.setPreferredType(PropertyType);
@@ -6690,7 +6980,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
NameWithPrefix += PropertyName->getName();
std::string NameWithSuffix = PropertyName->getName().str();
NameWithSuffix += '_';
- for(; Class; Class = Class->getSuperClass()) {
+ for (; Class; Class = Class->getSuperClass()) {
for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
@@ -6706,8 +6996,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
// Reduce the priority of this result by one, to give it a slight
// advantage over other results whose names don't match so closely.
if (Results.size() &&
- Results.data()[Results.size() - 1].Kind
- == CodeCompletionResult::RK_Declaration &&
+ Results.data()[Results.size() - 1].Kind ==
+ CodeCompletionResult::RK_Declaration &&
Results.data()[Results.size() - 1].Declaration == Ivar)
Results.data()[Results.size() - 1].Priority--;
}
@@ -6721,14 +7011,14 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
typedef CodeCompletionResult Result;
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
- Priority,CXAvailability_Available);
+ Priority, CXAvailability_Available);
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
- Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
- Policy, Allocator));
+ Builder.AddResultTypeChunk(
+ GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
- Results.AddResult(Result(Builder.TakeString(), Priority,
- CXCursor_ObjCIvarDecl));
+ Results.AddResult(
+ Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
}
Results.ExitScope();
@@ -6739,8 +7029,9 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
// Mapping from selectors to the methods that implement that selector, along
// with the "in original class" flag.
-typedef llvm::DenseMap<
- Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
+typedef llvm::DenseMap<Selector,
+ llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
+ KnownMethodsMap;
/// Find all of the methods that reside in the given container
/// (and its superclasses, protocols, etc.) that meet the given
@@ -6760,8 +7051,8 @@ static void FindImplementableMethods(ASTContext &Context,
IFace = IFace->getDefinition();
Container = IFace;
- const ObjCList<ObjCProtocolDecl> &Protocols
- = IFace->getReferencedProtocols();
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ IFace->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
@@ -6777,14 +7068,14 @@ static void FindImplementableMethods(ASTContext &Context,
// Visit the superclass.
if (IFace->getSuperClass())
FindImplementableMethods(Context, IFace->getSuperClass(),
- WantInstanceMethods, ReturnType,
- KnownMethods, false);
+ WantInstanceMethods, ReturnType, KnownMethods,
+ false);
}
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
// Recurse into protocols.
- const ObjCList<ObjCProtocolDecl> &Protocols
- = Category->getReferencedProtocols();
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ Category->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
@@ -6806,10 +7097,10 @@ static void FindImplementableMethods(ASTContext &Context,
Container = Protocol;
// Recurse into protocols.
- const ObjCList<ObjCProtocolDecl> &Protocols
- = Protocol->getReferencedProtocols();
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end();
+ E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, false);
@@ -6832,8 +7123,7 @@ static void FindImplementableMethods(ASTContext &Context,
/// Add the parenthesized return or parameter type chunk to a code
/// completion string.
-static void AddObjCPassingTypeChunk(QualType Type,
- unsigned ObjCDeclQuals,
+static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
ASTContext &Context,
const PrintingPolicy &Policy,
CodeCompletionBuilder &Builder) {
@@ -6841,15 +7131,14 @@ static void AddObjCPassingTypeChunk(QualType Type,
std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
if (!Quals.empty())
Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
- Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
- Builder.getAllocator()));
+ Builder.AddTextChunk(
+ GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
/// Determine whether the given class is or inherits from a class by
/// the given name.
-static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
- StringRef Name) {
+static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
if (!Class)
return false;
@@ -6863,8 +7152,7 @@ static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
/// Key-Value Observing (KVO).
static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
bool IsInstanceMethod,
- QualType ReturnType,
- ASTContext &Context,
+ QualType ReturnType, ASTContext &Context,
VisitedSelectorSet &KnownSelectors,
ResultBuilder &Results) {
IdentifierInfo *PropName = Property->getIdentifier();
@@ -6889,7 +7177,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
const char *CopiedKey;
KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
- : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
+ : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
operator const char *() {
if (CopiedKey)
@@ -6904,19 +7192,19 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
if (!UpperKey.empty())
UpperKey[0] = toUppercase(UpperKey[0]);
- bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
- Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
- Property->getType());
- bool ReturnTypeMatchesVoid
- = ReturnType.isNull() || ReturnType->isVoidType();
+ bool ReturnTypeMatchesProperty =
+ ReturnType.isNull() ||
+ Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
+ Property->getType());
+ bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
// Add the normal accessor -(type)key.
if (IsInstanceMethod &&
KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
if (ReturnType.isNull())
- AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
- Context, Policy, Builder);
+ AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
+ Builder);
Builder.AddTypedTextChunk(Key);
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
@@ -6928,9 +7216,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
if (IsInstanceMethod &&
((!ReturnType.isNull() &&
(ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
- (ReturnType.isNull() &&
- (Property->getType()->isIntegerType() ||
- Property->getType()->isBooleanType())))) {
+ (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
+ Property->getType()->isBooleanType())))) {
std::string SelectorName = (Twine("is") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
@@ -6941,8 +7228,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
- Builder.AddTypedTextChunk(
- Allocator.CopyString(SelectorId->getName()));
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
@@ -6960,11 +7246,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
- Builder.AddTypedTextChunk(
- Allocator.CopyString(SelectorId->getName()));
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Builder.AddTypedTextChunk(":");
- AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
- Context, Policy, Builder);
+ AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
+ Builder);
Builder.AddTextChunk(Key);
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
@@ -6976,8 +7261,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
unsigned IndexedSetterPriority = CCP_CodePattern;
unsigned UnorderedGetterPriority = CCP_CodePattern;
unsigned UnorderedSetterPriority = CCP_CodePattern;
- if (const ObjCObjectPointerType *ObjCPointer
- = Property->getType()->getAs<ObjCObjectPointerType>()) {
+ if (const auto *ObjCPointer =
+ Property->getType()->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
// If this interface type is not provably derived from a known
// collection, penalize the corresponding completions.
@@ -7013,12 +7298,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
- Builder.AddTypedTextChunk(
- Allocator.CopyString(SelectorId->getName()));
- Results.AddResult(Result(Builder.TakeString(),
- std::min(IndexedGetterPriority,
- UnorderedGetterPriority),
- CXCursor_ObjCInstanceMethodDecl));
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
+ Results.AddResult(
+ Result(Builder.TakeString(),
+ std::min(IndexedGetterPriority, UnorderedGetterPriority),
+ CXCursor_ObjCInstanceMethodDecl));
}
}
@@ -7026,8 +7310,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// Add -(id)objectInKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
- std::string SelectorName
- = (Twine("objectIn") + UpperKey + "AtIndex").str();
+ std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
@@ -7051,10 +7334,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
(ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
- ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
- ->getName() == "NSArray"))) {
- std::string SelectorName
- = (Twine(Property->getName()) + "AtIndexes").str();
+ ReturnType->getAs<ObjCObjectPointerType>()
+ ->getInterfaceDecl()
+ ->getName() == "NSArray"))) {
+ std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
@@ -7076,10 +7359,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// Add -(void)getKey:(type **)buffer range:(NSRange)inRange
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("get") + UpperKey).str();
- IdentifierInfo *SelectorIds[2] = {
- &Context.Idents.get(SelectorName),
- &Context.Idents.get("range")
- };
+ IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
+ &Context.Idents.get("range")};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
@@ -7110,10 +7391,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
- IdentifierInfo *SelectorIds[2] = {
- &Context.Idents.get("insertObject"),
- &Context.Idents.get(SelectorName)
- };
+ IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
+ &Context.Idents.get(SelectorName)};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
@@ -7142,10 +7421,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("insert") + UpperKey).str();
- IdentifierInfo *SelectorIds[2] = {
- &Context.Idents.get(SelectorName),
- &Context.Idents.get("atIndexes")
- };
+ IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
+ &Context.Idents.get("atIndexes")};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
@@ -7172,8 +7449,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName
- = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
+ std::string SelectorName =
+ (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
@@ -7194,8 +7471,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName
- = (Twine("remove") + UpperKey + "AtIndexes").str();
+ std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
@@ -7216,12 +7492,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName
- = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
- IdentifierInfo *SelectorIds[2] = {
- &Context.Idents.get(SelectorName),
- &Context.Idents.get("withObject")
- };
+ std::string SelectorName =
+ (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
+ IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
+ &Context.Idents.get("withObject")};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
@@ -7248,13 +7522,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName1
- = (Twine("replace") + UpperKey + "AtIndexes").str();
+ std::string SelectorName1 =
+ (Twine("replace") + UpperKey + "AtIndexes").str();
std::string SelectorName2 = (Twine("with") + UpperKey).str();
- IdentifierInfo *SelectorIds[2] = {
- &Context.Idents.get(SelectorName1),
- &Context.Idents.get(SelectorName2)
- };
+ IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
+ &Context.Idents.get(SelectorName2)};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
@@ -7285,8 +7557,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
(ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
- ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
- ->getName() == "NSEnumerator"))) {
+ ReturnType->getAs<ObjCObjectPointerType>()
+ ->getInterfaceDecl()
+ ->getName() == "NSEnumerator"))) {
std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
@@ -7299,7 +7572,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
- CXCursor_ObjCInstanceMethodDecl));
+ CXCursor_ObjCInstanceMethodDecl));
}
}
@@ -7322,9 +7595,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
} else {
- Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
- Policy,
- Builder.getAllocator()));
+ Builder.AddTextChunk(GetCompletionTypeString(
+ ReturnType, Context, Policy, Builder.getAllocator()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
@@ -7336,8 +7608,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// Mutable unordered accessors
// - (void)addKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName
- = (Twine("add") + UpperKey + Twine("Object")).str();
+ std::string SelectorName =
+ (Twine("add") + UpperKey + Twine("Object")).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
@@ -7380,8 +7652,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// - (void)removeKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
- std::string SelectorName
- = (Twine("remove") + UpperKey + Twine("Object")).str();
+ std::string SelectorName =
+ (Twine("remove") + UpperKey + Twine("Object")).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
@@ -7449,10 +7721,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
(ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
- ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
- ->getName() == "NSSet"))) {
- std::string SelectorName
- = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
+ ReturnType->getAs<ObjCObjectPointerType>()
+ ->getInterfaceDecl()
+ ->getName() == "NSSet"))) {
+ std::string SelectorName =
+ (Twine("keyPathsForValuesAffecting") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
.second) {
@@ -7464,17 +7737,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
- CXCursor_ObjCClassMethodDecl));
+ CXCursor_ObjCClassMethodDecl));
}
}
// + (BOOL)automaticallyNotifiesObserversForKey
if (!IsInstanceMethod &&
- (ReturnType.isNull() ||
- ReturnType->isIntegerType() ||
+ (ReturnType.isNull() || ReturnType->isIntegerType() ||
ReturnType->isBooleanType())) {
- std::string SelectorName
- = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
+ std::string SelectorName =
+ (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
.second) {
@@ -7486,7 +7758,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
- CXCursor_ObjCClassMethodDecl));
+ CXCursor_ObjCClassMethodDecl));
}
}
}
@@ -7498,8 +7770,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
QualType ReturnType = GetTypeFromParser(ReturnTy);
Decl *IDecl = nullptr;
if (CurContext->isObjCContainer()) {
- ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
- IDecl = OCD;
+ ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
+ IDecl = OCD;
}
// Determine where we should start searching for methods.
ObjCContainerDecl *SearchDecl = nullptr;
@@ -7508,8 +7780,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
SearchDecl = Impl->getClassInterface();
IsInImplementation = true;
- } else if (ObjCCategoryImplDecl *CatImpl
- = dyn_cast<ObjCCategoryImplDecl>(D)) {
+ } else if (ObjCCategoryImplDecl *CatImpl =
+ dyn_cast<ObjCCategoryImplDecl>(D)) {
SearchDecl = CatImpl->getCategoryDecl();
IsInImplementation = true;
} else
@@ -7523,15 +7795,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
if (!SearchDecl) {
HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
- nullptr, 0);
+ CodeCompletionContext::CCC_Other, nullptr, 0);
return;
}
// Find all of the methods that we could declare/implement here.
KnownMethodsMap KnownMethods;
- FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
- ReturnType, KnownMethods);
+ FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
+ KnownMethods);
// Add declarations or definitions for each of the known methods.
typedef CodeCompletionResult Result;
@@ -7541,7 +7812,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Results.EnterNewScope();
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
for (KnownMethodsMap::iterator M = KnownMethods.begin(),
- MEnd = KnownMethods.end();
+ MEnd = KnownMethods.end();
M != MEnd; ++M) {
ObjCMethodDecl *Method = M->second.getPointer();
CodeCompletionBuilder Builder(Results.getAllocator(),
@@ -7558,21 +7829,20 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
if (ReturnType.isNull()) {
QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
AttributedType::stripOuterNullability(ResTy);
- AddObjCPassingTypeChunk(ResTy,
- Method->getObjCDeclQualifier(), Context, Policy,
- Builder);
+ AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
+ Policy, Builder);
}
Selector Sel = Method->getSelector();
// Add the first part of the selector to the pattern.
- Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
- Sel.getNameForSlot(0)));
+ Builder.AddTypedTextChunk(
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
// Add parameters to the pattern.
unsigned I = 0;
for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
+ PEnd = Method->param_end();
P != PEnd; (void)++P, ++I) {
// Add the part of the selector name.
if (I == 0)
@@ -7580,7 +7850,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
else if (I < Sel.getNumArgs()) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTypedTextChunk(
- Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
} else
break;
@@ -7590,16 +7860,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
ParamType = (*P)->getType();
else
ParamType = (*P)->getOriginalType();
- ParamType = ParamType.substObjCTypeArgs(Context, {},
- ObjCSubstitutionContext::Parameter);
+ ParamType = ParamType.substObjCTypeArgs(
+ Context, {}, ObjCSubstitutionContext::Parameter);
AttributedType::stripOuterNullability(ParamType);
- AddObjCPassingTypeChunk(ParamType,
- (*P)->getObjCDeclQualifier(),
- Context, Policy,
- Builder);
+ AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
+ Policy, Builder);
if (IdentifierInfo *Id = (*P)->getIdentifier())
- Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
+ Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
}
if (Method->isVariadic()) {
@@ -7627,25 +7895,24 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
}
unsigned Priority = CCP_CodePattern;
+ auto R = Result(Builder.TakeString(), Method, Priority);
if (!M->second.getInt())
- Priority += CCD_InBaseClass;
-
- Results.AddResult(Result(Builder.TakeString(), Method, Priority));
+ setInBaseClass(R);
+ Results.AddResult(std::move(R));
}
// Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
// the properties in this class and its categories.
- if (Context.getLangOpts().ObjC2) {
+ if (Context.getLangOpts().ObjC) {
SmallVector<ObjCContainerDecl *, 4> Containers;
Containers.push_back(SearchDecl);
VisitedSelectorSet KnownSelectors;
for (KnownMethodsMap::iterator M = KnownMethods.begin(),
- MEnd = KnownMethods.end();
+ MEnd = KnownMethods.end();
M != MEnd; ++M)
KnownSelectors.insert(M->first);
-
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
if (!IFace)
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
@@ -7669,16 +7936,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Results.data(), Results.size());
}
-void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
- bool IsInstanceMethod,
- bool AtParameterName,
- ParsedType ReturnTy,
- ArrayRef<IdentifierInfo *> SelIdents) {
+void Sema::CodeCompleteObjCMethodDeclSelector(
+ Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
+ ArrayRef<IdentifierInfo *> SelIdents) {
// If we have an external source, load the entire class method
// pool from the AST file.
if (ExternalSource) {
- for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
- I != N; ++I) {
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
+ ++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || MethodPool.count(Sel))
continue;
@@ -7700,10 +7965,9 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
for (GlobalMethodPool::iterator M = MethodPool.begin(),
MEnd = MethodPool.end();
M != MEnd; ++M) {
- for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
- &M->second.second;
- MethList && MethList->getMethod();
- MethList = MethList->getNext()) {
+ for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
+ : &M->second.second;
+ MethList && MethList->getMethod(); MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
@@ -7718,7 +7982,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
- Param->getIdentifier()->getName()));
+ Param->getIdentifier()->getName()));
Results.AddResult(Builder.TakeString());
}
}
@@ -7864,7 +8128,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Builder.AddPlaceholderChunk("arguments");
Results.AddResult(Builder.TakeString());
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
// #import "header"
Builder.AddTypedTextChunk("import");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7916,29 +8180,27 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
}
void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
- CodeCompleteOrdinaryName(S,
- S->getFnParent()? Sema::PCC_RecoveryInFunction
- : Sema::PCC_Namespace);
+ CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
+ : Sema::PCC_Namespace);
}
void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
- IsDefinition? CodeCompletionContext::CCC_MacroName
- : CodeCompletionContext::CCC_MacroNameUse);
+ IsDefinition ? CodeCompletionContext::CCC_MacroName
+ : CodeCompletionContext::CCC_MacroNameUse);
if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
// Add just the names of macros, not their arguments.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Results.EnterNewScope();
for (Preprocessor::macro_iterator M = PP.macro_begin(),
- MEnd = PP.macro_end();
+ MEnd = PP.macro_end();
M != MEnd; ++M) {
- Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
- M->first->getName()));
- Results.AddResult(CodeCompletionResult(Builder.TakeString(),
- CCP_CodePattern,
- CXCursor_MacroDefinition));
+ Builder.AddTypedTextChunk(
+ Builder.getAllocator().CopyString(M->first->getName()));
+ Results.AddResult(CodeCompletionResult(
+ Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
}
Results.ExitScope();
} else if (IsDefinition) {
@@ -7955,9 +8217,11 @@ void Sema::CodeCompletePreprocessorExpression() {
CodeCompletionContext::CCC_PreprocessorExpression);
if (!CodeCompleter || CodeCompleter->includeMacros())
- AddMacroResults(PP, Results, true);
+ AddMacroResults(PP, Results,
+ CodeCompleter ? CodeCompleter->loadExternal() : false,
+ true);
- // defined (<macro>)
+ // defined (<macro>)
Results.EnterNewScope();
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -7984,10 +8248,118 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
// for the expanded tokens.
}
+// This handles completion inside an #include filename, e.g. #include <foo/ba
+// We look for the directory "foo" under each directory on the include path,
+// list its files, and reassemble the appropriate #include.
+void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
+ // RelDir should use /, but unescaped \ is possible on windows!
+ // Our completions will normalize to / for simplicity, this case is rare.
+ std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
+ // We need the native slashes for the actual file system interactions.
+ SmallString<128> NativeRelDir = StringRef(RelDir);
+ llvm::sys::path::native(NativeRelDir);
+ auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext::CCC_IncludedFile);
+ llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
+
+ // Helper: adds one file or directory completion result.
+ auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
+ SmallString<64> TypedChunk = Filename;
+ // Directory completion is up to the slash, e.g. <sys/
+ TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
+ auto R = SeenResults.insert(TypedChunk);
+ if (R.second) { // New completion
+ const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
+ *R.first = InternedTyped; // Avoid dangling StringRef.
+ CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo());
+ Builder.AddTypedTextChunk(InternedTyped);
+ // The result is a "Pattern", which is pretty opaque.
+ // We may want to include the real filename to allow smart ranking.
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+ }
+ };
+
+ // Helper: scans IncludeDir for nice files, and adds results for each.
+ auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
+ llvm::SmallString<128> Dir = IncludeDir;
+ if (!NativeRelDir.empty())
+ llvm::sys::path::append(Dir, NativeRelDir);
+
+ std::error_code EC;
+ unsigned Count = 0;
+ for (auto It = FS->dir_begin(Dir, EC);
+ !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
+ if (++Count == 2500) // If we happen to hit a huge directory,
+ break; // bail out early so we're not too slow.
+ StringRef Filename = llvm::sys::path::filename(It->path());
+ switch (It->type()) {
+ case llvm::sys::fs::file_type::directory_file:
+ AddCompletion(Filename, /*IsDirectory=*/true);
+ break;
+ case llvm::sys::fs::file_type::regular_file:
+ // Only files that really look like headers. (Except in system dirs).
+ if (!IsSystem) {
+ // Header extensions from Types.def, which we can't depend on here.
+ if (!(Filename.endswith_lower(".h") ||
+ Filename.endswith_lower(".hh") ||
+ Filename.endswith_lower(".hpp") ||
+ Filename.endswith_lower(".inc")))
+ break;
+ }
+ AddCompletion(Filename, /*IsDirectory=*/false);
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ // Helper: adds results relative to IncludeDir, if possible.
+ auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
+ bool IsSystem) {
+ switch (IncludeDir.getLookupType()) {
+ case DirectoryLookup::LT_HeaderMap:
+ // header maps are not (currently) enumerable.
+ break;
+ case DirectoryLookup::LT_NormalDir:
+ AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
+ break;
+ case DirectoryLookup::LT_Framework:
+ AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
+ break;
+ }
+ };
+
+ // Finally with all our helpers, we can scan the include path.
+ // Do this in standard order so deduplication keeps the right file.
+ // (In case we decide to add more details to the results later).
+ const auto &S = PP.getHeaderSearchInfo();
+ using llvm::make_range;
+ if (!Angled) {
+ // The current directory is on the include path for "quoted" includes.
+ auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
+ if (CurFile && CurFile->getDir())
+ AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
+ for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
+ AddFilesFromDirLookup(D, false);
+ }
+ for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
+ AddFilesFromDirLookup(D, false);
+ for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
+ AddFilesFromDirLookup(D, true);
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
void Sema::CodeCompleteNaturalLanguage() {
HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_NaturalLanguage,
- nullptr, 0);
+ CodeCompletionContext::CCC_NaturalLanguage, nullptr,
+ 0);
}
void Sema::CodeCompleteAvailabilityPlatformName() {
@@ -8006,9 +8378,9 @@ void Sema::CodeCompleteAvailabilityPlatformName() {
Results.data(), Results.size());
}
-void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
- CodeCompletionTUInfo &CCTUInfo,
- SmallVectorImpl<CodeCompletionResult> &Results) {
+void Sema::GatherGlobalCodeCompletions(
+ CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
+ SmallVectorImpl<CodeCompletionResult> &Results) {
ResultBuilder Builder(*this, Allocator, CCTUInfo,
CodeCompletionContext::CCC_Recovery);
if (!CodeCompleter || CodeCompleter->includeGlobals()) {
@@ -8020,9 +8392,11 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
}
if (!CodeCompleter || CodeCompleter->includeMacros())
- AddMacroResults(PP, Builder, true);
+ AddMacroResults(PP, Builder,
+ CodeCompleter ? CodeCompleter->loadExternal() : false,
+ true);
Results.clear();
- Results.insert(Results.end(),
- Builder.data(), Builder.data() + Builder.size());
+ Results.insert(Results.end(), Builder.data(),
+ Builder.data() + Builder.size());
}
diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
index 1d5454ca778b..181efa6d3dd0 100644
--- a/lib/Sema/SemaCoroutine.cpp
+++ b/lib/Sema/SemaCoroutine.cpp
@@ -84,8 +84,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
// ref-qualifier or with the & ref-qualifier
// -- "rvalue reference to cv X" for functions declared with the &&
// ref-qualifier
- QualType T =
- MD->getThisType(S.Context)->getAs<PointerType>()->getPointeeType();
+ QualType T = MD->getThisType()->getAs<PointerType>()->getPointeeType();
T = FnType->getRefQualifier() == RQ_RValue
? S.Context.getRValueReferenceType(T)
: S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true);
@@ -453,7 +452,7 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
// to bool.
ExprResult Conv = S.PerformContextuallyConvertToBool(AwaitReady);
if (Conv.isInvalid()) {
- S.Diag(AwaitReady->getDirectCallee()->getLocStart(),
+ S.Diag(AwaitReady->getDirectCallee()->getBeginLoc(),
diag::note_await_ready_no_bool_conversion);
S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
<< AwaitReady->getDirectCallee() << E->getSourceRange();
@@ -506,7 +505,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
auto *FD = cast<FunctionDecl>(CurContext);
bool IsThisDependentType = [&] {
if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD))
- return MD->isInstance() && MD->getThisType(Context)->isDependentType();
+ return MD->isInstance() && MD->getThisType()->isDependentType();
else
return false;
}();
@@ -565,8 +564,8 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
// Create an initialization sequence for the promise type using the
// constructor arguments, wrapped in a parenthesized list expression.
- Expr *PLE = new (Context) ParenListExpr(Context, FD->getLocation(),
- CtorArgExprs, FD->getLocation());
+ Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(),
+ CtorArgExprs, FD->getLocation());
InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
InitializationKind Kind = InitializationKind::CreateForInit(
VD->getLocation(), /*DirectInit=*/true, PLE);
@@ -647,7 +646,7 @@ bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
return StmtError();
Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(),
/*IsImplicit*/ true);
- Suspend = ActOnFinishFullExpr(Suspend.get());
+ Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false);
if (Suspend.isInvalid()) {
Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
<< ((Name == "initial_suspend") ? 0 : 1);
@@ -841,6 +840,19 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
E = R.get();
}
+ // Move the return value if we can
+ if (E) {
+ auto NRVOCandidate = this->getCopyElisionCandidate(E->getType(), E, CES_AsIfByStdMove);
+ if (NRVOCandidate) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate);
+ ExprResult MoveResult = this->PerformMoveOrCopyInitialization(
+ Entity, NRVOCandidate, E->getType(), E);
+ if (MoveResult.get())
+ E = MoveResult.get();
+ }
+ }
+
// FIXME: If the operand is a reference to a variable that's about to go out
// of scope, we should treat the operand as an xvalue for this overload
// resolution.
@@ -855,7 +867,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
if (PC.isInvalid())
return StmtError();
- Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
+ Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get();
Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
return Res;
@@ -1224,7 +1236,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
ExprResult NewExpr =
S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
- NewExpr = S.ActOnFinishFullExpr(NewExpr.get());
+ NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false);
if (NewExpr.isInvalid())
return false;
@@ -1250,7 +1262,8 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
ExprResult DeleteExpr =
S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
- DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get());
+ DeleteExpr =
+ S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
if (DeleteExpr.isInvalid())
return false;
@@ -1335,7 +1348,8 @@ bool CoroutineStmtBuilder::makeOnException() {
ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
"unhandled_exception", None);
- UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc);
+ UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,
+ /*DiscardedValue*/ false);
if (UnhandledException.isInvalid())
return false;
@@ -1388,7 +1402,8 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
"get_return_object type must no longer be dependent");
if (FnRetType->isVoidType()) {
- ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc);
+ ExprResult Res =
+ S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
if (Res.isInvalid())
return false;
@@ -1420,7 +1435,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
if (Res.isInvalid())
return false;
- Res = S.ActOnFinishFullExpr(Res.get());
+ Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false);
if (Res.isInvalid())
return false;
@@ -1460,7 +1475,7 @@ static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) {
T = E->getType();
QualType TargetType = S.BuildReferenceType(
T, /*SpelledAsLValue*/ false, SourceLocation(), DeclarationName());
- SourceLocation ExprLoc = E->getLocStart();
+ SourceLocation ExprLoc = E->getBeginLoc();
TypeSourceInfo *TargetLoc =
S.Context.getTrivialTypeSourceInfo(TargetType, ExprLoc);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b92d76ad4204..23c99d45a78d 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1735,12 +1735,13 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx,
FixItHint &Hint) {
if (isa<LabelDecl>(D)) {
- SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(),
- tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true);
+ SourceLocation AfterColon = Lexer::findLocationAfterToken(
+ D->getEndLoc(), tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(),
+ true);
if (AfterColon.isInvalid())
return;
- Hint = FixItHint::CreateRemoval(CharSourceRange::
- getCharRange(D->getLocStart(), AfterColon));
+ Hint = FixItHint::CreateRemoval(
+ CharSourceRange::getCharRange(D->getBeginLoc(), AfterColon));
}
}
@@ -2110,7 +2111,7 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
// Allow multiple definitions for ObjC built-in typedefs.
// FIXME: Verify the underlying types are equivalent!
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
const IdentifierInfo *TypeID = New->getIdentifier();
switch (TypeID->getLength()) {
default: break;
@@ -2474,14 +2475,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
- NewAttr = S.mergeInternalLinkageAttr(
- D, InternalLinkageA->getRange(),
- &S.Context.Idents.get(InternalLinkageA->getSpelling()),
- AttrSpellingListIndex);
+ NewAttr = S.mergeInternalLinkageAttr(D, *InternalLinkageA);
else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr))
- NewAttr = S.mergeCommonAttr(D, CommonA->getRange(),
- &S.Context.Idents.get(CommonA->getSpelling()),
- AttrSpellingListIndex);
+ NewAttr = S.mergeCommonAttr(D, *CommonA);
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
@@ -3249,20 +3245,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// Redeclarations or specializations of a function or function template
// with a declared return type that uses a placeholder type shall also
// use that placeholder, not a deduced type.
- QualType OldDeclaredReturnType =
- (Old->getTypeSourceInfo()
- ? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>()
- : OldType)->getReturnType();
- QualType NewDeclaredReturnType =
- (New->getTypeSourceInfo()
- ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
- : NewType)->getReturnType();
+ QualType OldDeclaredReturnType = Old->getDeclaredReturnType();
+ QualType NewDeclaredReturnType = New->getDeclaredReturnType();
if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) &&
- !((NewQType->isDependentType() || OldQType->isDependentType()) &&
- New->isLocalExternDecl())) {
+ canFullyTypeCheckRedeclaration(New, Old, NewDeclaredReturnType,
+ OldDeclaredReturnType)) {
QualType ResQT;
if (NewDeclaredReturnType->isObjCObjectPointerType() &&
OldDeclaredReturnType->isObjCObjectPointerType())
+ // FIXME: This does the wrong thing for a deduced return type.
ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
if (ResQT.isNull()) {
if (New->isCXXClassMember() && New->isOutOfLine())
@@ -3427,13 +3418,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
if (OldQTypeForComparison == NewQType)
return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
- if ((NewQType->isDependentType() || OldQType->isDependentType()) &&
- New->isLocalExternDecl()) {
- // It's OK if we couldn't merge types for a local function declaraton
- // if either the old or new type is dependent. We'll merge the types
- // when we instantiate the function.
+ // If the types are imprecise (due to dependent constructs in friends or
+ // local extern declarations), it's OK if they differ. We'll check again
+ // during instantiation.
+ if (!canFullyTypeCheckRedeclaration(New, Old, NewQType, OldQType))
return false;
- }
// Fall through for conflicting redeclarations and redefinitions.
}
@@ -4356,8 +4345,8 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
Record = UT->getDecl();
if (Record && getLangOpts().MicrosoftExt) {
- Diag(DS.getLocStart(), diag::ext_ms_anonymous_record)
- << Record->isUnion() << DS.getSourceRange();
+ Diag(DS.getBeginLoc(), diag::ext_ms_anonymous_record)
+ << Record->isUnion() << DS.getSourceRange();
return BuildMicrosoftCAnonymousStruct(S, DS, Record);
}
@@ -4380,8 +4369,8 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
if (!DS.isMissingDeclaratorOk()) {
// Customize diagnostic for a typedef missing a name.
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
- Diag(DS.getLocStart(), diag::ext_typedef_without_a_name)
- << DS.getSourceRange();
+ Diag(DS.getBeginLoc(), diag::ext_typedef_without_a_name)
+ << DS.getSourceRange();
else
DeclaresAnything = false;
}
@@ -4405,7 +4394,7 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
if (!DeclaresAnything) {
// In C, we allow this as a (popular) extension / bug. Don't bother
// producing further diagnostics for redundant qualifiers after this.
- Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange();
+ Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange();
return TagD;
}
@@ -4815,14 +4804,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Create a declaration for this anonymous struct/union.
NamedDecl *Anon = nullptr;
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
- Anon = FieldDecl::Create(Context, OwningClass,
- DS.getLocStart(),
- Record->getLocation(),
- /*IdentifierInfo=*/nullptr,
- Context.getTypeDeclType(Record),
- TInfo,
- /*BitWidth=*/nullptr, /*Mutable=*/false,
- /*InitStyle=*/ICIS_NoInit);
+ Anon = FieldDecl::Create(
+ Context, OwningClass, DS.getBeginLoc(), Record->getLocation(),
+ /*IdentifierInfo=*/nullptr, Context.getTypeDeclType(Record), TInfo,
+ /*BitWidth=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
Anon->setAccess(AS);
if (getLangOpts().CPlusPlus)
FieldCollector->Add(cast<FieldDecl>(Anon));
@@ -4837,11 +4823,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
SC = SC_None;
}
- Anon = VarDecl::Create(Context, Owner,
- DS.getLocStart(),
+ Anon = VarDecl::Create(Context, Owner, DS.getBeginLoc(),
Record->getLocation(), /*IdentifierInfo=*/nullptr,
- Context.getTypeDeclType(Record),
- TInfo, SC);
+ Context.getTypeDeclType(Record), TInfo, SC);
// Default-initialize the implicit variable. This initialization will be
// trivial in almost all cases, except if a union member has an in-class
@@ -4913,15 +4897,11 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
QualType RecTy = Context.getTypeDeclType(Record);
// Create a declaration for this anonymous struct.
- NamedDecl *Anon = FieldDecl::Create(Context,
- ParentDecl,
- DS.getLocStart(),
- DS.getLocStart(),
- /*IdentifierInfo=*/nullptr,
- RecTy,
- TInfo,
- /*BitWidth=*/nullptr, /*Mutable=*/false,
- /*InitStyle=*/ICIS_NoInit);
+ NamedDecl *Anon =
+ FieldDecl::Create(Context, ParentDecl, DS.getBeginLoc(), DS.getBeginLoc(),
+ /*IdentifierInfo=*/nullptr, RecTy, TInfo,
+ /*BitWidth=*/nullptr, /*Mutable=*/false,
+ /*InitStyle=*/ICIS_NoInit);
Anon->setImplicit();
// Add the anonymous struct object to the current context.
@@ -4962,7 +4942,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
case UnqualifiedIdKind::IK_ImplicitSelfParam:
case UnqualifiedIdKind::IK_Identifier:
NameInfo.setName(Name.Identifier);
- NameInfo.setLoc(Name.StartLocation);
return NameInfo;
case UnqualifiedIdKind::IK_DeductionGuideName: {
@@ -4989,14 +4968,12 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
NameInfo.setName(
Context.DeclarationNames.getCXXDeductionGuideName(Template));
- NameInfo.setLoc(Name.StartLocation);
return NameInfo;
}
case UnqualifiedIdKind::IK_OperatorFunctionId:
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator));
- NameInfo.setLoc(Name.StartLocation);
NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc
= Name.OperatorFunctionId.SymbolLocations[0];
NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
@@ -5006,7 +4983,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
case UnqualifiedIdKind::IK_LiteralOperatorId:
NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
Name.Identifier));
- NameInfo.setLoc(Name.StartLocation);
NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
return NameInfo;
@@ -5017,7 +4993,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return DeclarationNameInfo();
NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName(
Context.getCanonicalType(Ty)));
- NameInfo.setLoc(Name.StartLocation);
NameInfo.setNamedTypeInfo(TInfo);
return NameInfo;
}
@@ -5029,7 +5004,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return DeclarationNameInfo();
NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Ty)));
- NameInfo.setLoc(Name.StartLocation);
NameInfo.setNamedTypeInfo(TInfo);
return NameInfo;
}
@@ -5051,7 +5025,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(CurClassType)));
- NameInfo.setLoc(Name.StartLocation);
// FIXME: should we retrieve TypeSourceInfo?
NameInfo.setNamedTypeInfo(nullptr);
return NameInfo;
@@ -5064,7 +5037,6 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
return DeclarationNameInfo();
NameInfo.setName(Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(Ty)));
- NameInfo.setLoc(Name.StartLocation);
NameInfo.setNamedTypeInfo(TInfo);
return NameInfo;
}
@@ -5349,9 +5321,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
return ActOnDecompositionDeclarator(S, D, TemplateParamLists);
} else if (!Name) {
if (!D.isInvalidType()) // Reject this if we think it is valid.
- Diag(D.getDeclSpec().getLocStart(),
- diag::err_declarator_need_ident)
- << D.getDeclSpec().getSourceRange() << D.getSourceRange();
+ Diag(D.getDeclSpec().getBeginLoc(), diag::err_declarator_need_ident)
+ << D.getDeclSpec().getSourceRange() << D.getSourceRange();
return nullptr;
} else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
return nullptr;
@@ -5542,15 +5513,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
// If this has an identifier and is not a function template specialization,
// add it to the scope stack.
- if (New->getDeclName() && AddToScope) {
- // Only make a locally-scoped extern declaration visible if it is the first
- // declaration of this entity. Qualified lookup for such an entity should
- // only find this declaration if there is no visible declaration of it.
- bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl();
- PushOnScopeChains(New, S, AddToContext);
- if (!AddToContext)
- CurContext->addHiddenDecl(New);
- }
+ if (New->getDeclName() && AddToScope)
+ PushOnScopeChains(New, S);
if (isInOpenMPDeclareTargetContext())
checkDeclIsAllowedInOpenMPTarget(nullptr, New);
@@ -5604,11 +5568,13 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
if (VLATy->getElementType()->isVariablyModifiedType())
return QualType();
- llvm::APSInt Res;
+ Expr::EvalResult Result;
if (!VLATy->getSizeExpr() ||
- !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context))
+ !VLATy->getSizeExpr()->EvaluateAsInt(Result, Context))
return QualType();
+ llvm::APSInt Res = Result.Val.getInt();
+
// Check whether the array size is negative.
if (Res.isSigned() && Res.isNegative()) {
SizeIsNegative = true;
@@ -5897,10 +5863,10 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
return true;
}
-static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) {
+static void SetNestedNameSpecifier(Sema &S, DeclaratorDecl *DD, Declarator &D) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
if (!SS.isSet()) return;
- DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext()));
+ DD->setQualifierInfo(SS.getWithLocInContext(S.Context));
}
bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
@@ -6021,14 +5987,14 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
// The [[lifetimebound]] attribute can be applied to the implicit object
// parameter of a non-static member function (other than a ctor or dtor)
// by applying it to the function type.
- if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) {
+ if (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) {
const auto *MD = dyn_cast<CXXMethodDecl>(FD);
if (!MD || MD->isStatic()) {
- S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param)
- << !MD << ATL.getLocalSourceRange();
+ S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param)
+ << !MD << A->getRange();
} else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
- S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor)
- << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange();
+ S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
+ << isa<CXXDestructorDecl>(MD) << A->getRange();
}
}
}
@@ -6383,7 +6349,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// address space qualifiers.
if (R->isEventT()) {
if (R.getAddressSpace() != LangAS::opencl_private) {
- Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
+ Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual);
D.setInvalidType();
}
}
@@ -6457,9 +6423,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
VarTemplateDecl *NewTemplate = nullptr;
TemplateParameterList *TemplateParams = nullptr;
if (!getLangOpts().CPlusPlus) {
- NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
- D.getIdentifierLoc(), II,
- R, TInfo, SC);
+ NewVD = VarDecl::Create(Context, DC, D.getBeginLoc(), D.getIdentifierLoc(),
+ II, R, TInfo, SC);
if (R->getContainedDeducedType())
ParsingInitForAutoVars.insert(NewVD);
@@ -6521,7 +6486,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
TemplateParams = MatchTemplateParametersToScopeSpecifier(
- D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
+ D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
D.getCXXScopeSpec(),
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
@@ -6580,11 +6545,11 @@ NamedDecl *Sema::ActOnVariableDeclarator(
NewVD = cast<VarDecl>(Res.get());
AddToScope = false;
} else if (D.isDecompositionDeclarator()) {
- NewVD = DecompositionDecl::Create(Context, DC, D.getLocStart(),
+ NewVD = DecompositionDecl::Create(Context, DC, D.getBeginLoc(),
D.getIdentifierLoc(), R, TInfo, SC,
Bindings);
} else
- NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
+ NewVD = VarDecl::Create(Context, DC, D.getBeginLoc(),
D.getIdentifierLoc(), II, R, TInfo, SC);
// If this is supposed to be a variable template, create it as such.
@@ -6606,7 +6571,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
NewTemplate->setInvalidDecl();
}
- SetNestedNameSpecifier(NewVD, D);
+ SetNestedNameSpecifier(*this, NewVD, D);
// If we have any template parameter lists that don't directly belong to
// the variable (matching the scope specifier), store them.
@@ -6801,7 +6766,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
if (!R->isIntegralType(Context) && !R->isPointerType()) {
- Diag(D.getLocStart(), diag::err_asm_bad_register_type);
+ Diag(D.getBeginLoc(), diag::err_asm_bad_register_type);
NewVD->setInvalidDecl(true);
}
}
@@ -6931,12 +6896,12 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// C++ [basic.start.main]p3
// A program that declares a variable main at global scope is ill-formed.
if (getLangOpts().CPlusPlus)
- Diag(D.getLocStart(), diag::err_main_global_variable);
+ Diag(D.getBeginLoc(), diag::err_main_global_variable);
// In C, and external-linkage variable named main results in undefined
// behavior.
else if (NewVD->hasExternalFormalLinkage())
- Diag(D.getLocStart(), diag::warn_main_redefined);
+ Diag(D.getBeginLoc(), diag::warn_main_redefined);
}
if (D.isRedeclaration() && !Previous.empty()) {
@@ -7382,19 +7347,23 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
return;
}
}
- // OpenCL v1.2 s6.5 - All program scope variables must be declared in the
+ // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the
// __constant address space.
- // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
+ // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static
// variables inside a function can also be declared in the global
// address space.
+ // OpenCL C++ v1.0 s2.5 inherits rule from OpenCL C v2.0 and allows local
+ // address space additionally.
+ // FIXME: Add local AS for OpenCL C++.
if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
NewVD->hasExternalStorage()) {
if (!T->isSamplerT() &&
!(T.getAddressSpace() == LangAS::opencl_constant ||
(T.getAddressSpace() == LangAS::opencl_global &&
- getLangOpts().OpenCLVersion == 200))) {
+ (getLangOpts().OpenCLVersion == 200 ||
+ getLangOpts().OpenCLCPlusPlus)))) {
int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1;
- if (getLangOpts().OpenCLVersion == 200)
+ if (getLangOpts().OpenCLVersion == 200 || getLangOpts().OpenCLCPlusPlus)
Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
<< Scope << "global or constant";
else
@@ -7747,8 +7716,10 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches;
TypoCorrection Correction;
bool IsDefinition = ExtraArgs.D.isFunctionDefinition();
- unsigned DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend
- : diag::err_member_decl_does_not_match;
+ unsigned DiagMsg =
+ IsLocalFriend ? diag::err_no_matching_local_friend :
+ NewFD->getFriendObjectKind() ? diag::err_qualified_friend_no_match :
+ diag::err_member_decl_does_not_match;
LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
IsLocalFriend ? Sema::LookupLocalFriendName
: Sema::LookupOrdinaryName,
@@ -7938,10 +7909,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
(D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
(!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType());
- NewFD = FunctionDecl::Create(SemaRef.Context, DC,
- D.getLocStart(), NameInfo, R,
- TInfo, SC, isInline,
- HasPrototype, false);
+ NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
+ R, TInfo, SC, isInline, HasPrototype, false);
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -7966,31 +7935,26 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
"Constructors can only be declared in a member context");
R = SemaRef.CheckConstructorDeclarator(D, R, SC);
- return CXXConstructorDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
- D.getLocStart(), NameInfo,
- R, TInfo, isExplicit, isInline,
- /*isImplicitlyDeclared=*/false,
- isConstexpr);
+ return CXXConstructorDecl::Create(
+ SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
+ TInfo, isExplicit, isInline,
+ /*isImplicitlyDeclared=*/false, isConstexpr);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
R = SemaRef.CheckDestructorDeclarator(D, R, SC);
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
- CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(
- SemaRef.Context, Record,
- D.getLocStart(),
- NameInfo, R, TInfo, isInline,
- /*isImplicitlyDeclared=*/false);
-
- // If the class is complete, then we now create the implicit exception
- // specification. If the class is incomplete or dependent, we can't do
- // it yet.
- if (SemaRef.getLangOpts().CPlusPlus11 && !Record->isDependentType() &&
- Record->getDefinition() && !Record->isBeingDefined() &&
- R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) {
- SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
- }
+ CXXDestructorDecl *NewDD =
+ CXXDestructorDecl::Create(SemaRef.Context, Record, D.getBeginLoc(),
+ NameInfo, R, TInfo, isInline,
+ /*isImplicitlyDeclared=*/false);
+
+ // If the destructor needs an implicit exception specification, set it
+ // now. FIXME: It'd be nice to be able to create the right type to start
+ // with, but the type needs to reference the destructor declaration.
+ if (SemaRef.getLangOpts().CPlusPlus11)
+ SemaRef.AdjustDestructorExceptionSpec(NewDD);
IsVirtualOkay = true;
return NewDD;
@@ -8001,10 +7965,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// Create a FunctionDecl to satisfy the function definition parsing
// code path.
- return FunctionDecl::Create(SemaRef.Context, DC,
- D.getLocStart(),
- D.getIdentifierLoc(), Name, R, TInfo,
- SC, isInline,
+ return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(),
+ D.getIdentifierLoc(), Name, R, TInfo, SC,
+ isInline,
/*hasPrototype=*/true, isConstexpr);
}
@@ -8017,17 +7980,16 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.CheckConversionDeclarator(D, R, SC);
IsVirtualOkay = true;
- return CXXConversionDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
- D.getLocStart(), NameInfo,
- R, TInfo, isInline, isExplicit,
- isConstexpr, SourceLocation());
+ return CXXConversionDecl::Create(
+ SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
+ TInfo, isInline, isExplicit, isConstexpr, SourceLocation());
} else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
SemaRef.CheckDeductionGuideDeclarator(D, R, SC);
- return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getLocStart(),
+ return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getBeginLoc(),
isExplicit, NameInfo, R, TInfo,
- D.getLocEnd());
+ D.getEndLoc());
} else if (DC->isRecord()) {
// If the name of the function is the same as the name of the record,
// then this must be an invalid constructor that has a return type.
@@ -8042,11 +8004,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
}
// This is a C++ method declaration.
- CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context,
- cast<CXXRecordDecl>(DC),
- D.getLocStart(), NameInfo, R,
- TInfo, SC, isInline,
- isConstexpr, SourceLocation());
+ CXXMethodDecl *Ret = CXXMethodDecl::Create(
+ SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R,
+ TInfo, SC, isInline, isConstexpr, SourceLocation());
IsVirtualOkay = !Ret->isStatic();
return Ret;
} else {
@@ -8058,10 +8018,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// Determine whether the function was written with a
// prototype. This true when:
// - we're in C++ (where every function has a prototype),
- return FunctionDecl::Create(SemaRef.Context, DC,
- D.getLocStart(),
- NameInfo, R, TInfo, SC, isInline,
- true/*HasPrototype*/, isConstexpr);
+ return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo,
+ R, TInfo, SC, isInline, true /*HasPrototype*/,
+ isConstexpr);
}
}
@@ -8137,7 +8096,7 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
// Call ourself to check an underlying type of an array. Since the
// getPointeeOrArrayElementType returns an innermost type which is not an
- // array, this recusive call only happens once.
+ // array, this recursive call only happens once.
return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
}
@@ -8415,7 +8374,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union);
}
- SetNestedNameSpecifier(NewFD, D);
+ SetNestedNameSpecifier(*this, NewFD, D);
isMemberSpecialization = false;
isFunctionTemplateSpecialization = false;
if (D.isInvalidType())
@@ -8426,7 +8385,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool Invalid = false;
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
- D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
+ D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
D.getCXXScopeSpec(),
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
@@ -8496,8 +8455,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< FixItHint::CreateInsertion(InsertLoc, "<>");
}
}
- }
- else {
+ } else {
// All template param lists were matched against the scope specifier:
// this is NOT (an explicit specialization of) a template.
if (TemplateParamLists.size() > 0)
@@ -9067,10 +9025,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// selecting a friend based on a dependent factor. But there
// are situations where these conditions don't apply and we
// can actually do this check immediately.
+ //
+ // Unless the scope is dependent, it's always an error if qualified
+ // redeclaration lookup found nothing at all. Diagnose that now;
+ // nothing will diagnose that error later.
if (isFriend &&
- (TemplateParamLists.size() ||
- D.getCXXScopeSpec().getScopeRep()->isDependent() ||
- CurContext->isDependentContext())) {
+ (D.getCXXScopeSpec().getScopeRep()->isDependent() ||
+ (!Previous.empty() && (TemplateParamLists.size() ||
+ CurContext->isDependentContext())))) {
// ignore these
} else {
// The user tried to provide an out-of-line definition for a
@@ -9336,6 +9298,39 @@ Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD,
}
return nullptr;
}
+
+/// Determines if we can perform a correct type check for \p D as a
+/// redeclaration of \p PrevDecl. If not, we can generally still perform a
+/// best-effort check.
+///
+/// \param NewD The new declaration.
+/// \param OldD The old declaration.
+/// \param NewT The portion of the type of the new declaration to check.
+/// \param OldT The portion of the type of the old declaration to check.
+bool Sema::canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD,
+ QualType NewT, QualType OldT) {
+ if (!NewD->getLexicalDeclContext()->isDependentContext())
+ return true;
+
+ // For dependently-typed local extern declarations and friends, we can't
+ // perform a correct type check in general until instantiation:
+ //
+ // int f();
+ // template<typename T> void g() { T f(); }
+ //
+ // (valid if g() is only instantiated with T = int).
+ if (NewT->isDependentType() &&
+ (NewD->isLocalExternDecl() || NewD->getFriendObjectKind()))
+ return false;
+
+ // Similarly, if the previous declaration was a dependent local extern
+ // declaration, we don't really know its type yet.
+ if (OldT->isDependentType() && OldD->isLocalExternDecl())
+ return false;
+
+ return true;
+}
+
/// Checks if the new declaration declared in dependent context must be
/// put in the same redeclaration chain as the specified declaration.
///
@@ -9346,36 +9341,32 @@ Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD,
/// belongs to.
///
bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) {
- // Any declarations should be put into redeclaration chains except for
- // friend declaration in a dependent context that names a function in
- // namespace scope.
+ if (!D->getLexicalDeclContext()->isDependentContext())
+ return true;
+
+ // Don't chain dependent friend function definitions until instantiation, to
+ // permit cases like
//
- // This allows to compile code like:
+ // void func();
+ // template<typename T> class C1 { friend void func() {} };
+ // template<typename T> class C2 { friend void func() {} };
//
- // void func();
- // template<typename T> class C1 { friend void func() { } };
- // template<typename T> class C2 { friend void func() { } };
+ // ... which is valid if only one of C1 and C2 is ever instantiated.
//
- // This code snippet is a valid code unless both templates are instantiated.
- return !(D->getLexicalDeclContext()->isDependentContext() &&
- D->getDeclContext()->isFileContext() &&
- D->getFriendObjectKind() != Decl::FOK_None);
-}
+ // FIXME: This need only apply to function definitions. For now, we proxy
+ // this by checking for a file-scope function. We do not want this to apply
+ // to friend declarations nominating member functions, because that gets in
+ // the way of access checks.
+ if (D->getFriendObjectKind() && D->getDeclContext()->isFileContext())
+ return false;
-namespace MultiVersioning {
-enum Type { None, Target, CPUSpecific, CPUDispatch};
-} // MultiVersionType
-
-static MultiVersioning::Type
-getMultiVersionType(const FunctionDecl *FD) {
- if (FD->hasAttr<TargetAttr>())
- return MultiVersioning::Target;
- if (FD->hasAttr<CPUDispatchAttr>())
- return MultiVersioning::CPUDispatch;
- if (FD->hasAttr<CPUSpecificAttr>())
- return MultiVersioning::CPUSpecific;
- return MultiVersioning::None;
+ auto *VD = dyn_cast<ValueDecl>(D);
+ auto *PrevVD = dyn_cast<ValueDecl>(PrevDecl);
+ return !VD || !PrevVD ||
+ canFullyTypeCheckRedeclaration(VD, PrevVD, VD->getType(),
+ PrevVD->getType());
}
+
/// Check the target attribute of the function for MultiVersion
/// validity.
///
@@ -9412,10 +9403,31 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
return false;
}
+static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
+ MultiVersionKind MVType) {
+ for (const Attr *A : FD->attrs()) {
+ switch (A->getKind()) {
+ case attr::CPUDispatch:
+ case attr::CPUSpecific:
+ if (MVType != MultiVersionKind::CPUDispatch &&
+ MVType != MultiVersionKind::CPUSpecific)
+ return true;
+ break;
+ case attr::Target:
+ if (MVType != MultiVersionKind::Target)
+ return true;
+ break;
+ default:
+ return true;
+ }
+ }
+ return false;
+}
+
static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
const FunctionDecl *NewFD,
bool CausesMV,
- MultiVersioning::Type MVType) {
+ MultiVersionKind MVType) {
enum DoesntSupport {
FuncTemplates = 0,
VirtFuncs = 1,
@@ -9436,8 +9448,8 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
};
bool IsCPUSpecificCPUDispatchMVType =
- MVType == MultiVersioning::CPUDispatch ||
- MVType == MultiVersioning::CPUSpecific;
+ MVType == MultiVersionKind::CPUDispatch ||
+ MVType == MultiVersionKind::CPUSpecific;
if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) {
S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto);
@@ -9457,15 +9469,14 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
// For now, disallow all other attributes. These should be opt-in, but
// an analysis of all of them is a future FIXME.
- if (CausesMV && OldFD &&
- std::distance(OldFD->attr_begin(), OldFD->attr_end()) != 1) {
+ if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) {
S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
<< IsCPUSpecificCPUDispatchMVType;
S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
return true;
}
- if (std::distance(NewFD->attr_begin(), NewFD->attr_end()) != 1)
+ if (HasNonMultiVersionAttributes(NewFD, MVType))
return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
<< IsCPUSpecificCPUDispatchMVType;
@@ -9498,8 +9509,8 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
<< IsCPUSpecificCPUDispatchMVType << DefaultedFuncs;
- if (NewFD->isConstexpr() && (MVType == MultiVersioning::CPUDispatch ||
- MVType == MultiVersioning::CPUSpecific))
+ if (NewFD->isConstexpr() && (MVType == MultiVersionKind::CPUDispatch ||
+ MVType == MultiVersionKind::CPUSpecific))
return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
<< IsCPUSpecificCPUDispatchMVType << ConstexprFuncs;
@@ -9563,19 +9574,19 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
///
/// Returns true if there was an error, false otherwise.
static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD,
- MultiVersioning::Type MVType,
+ MultiVersionKind MVType,
const TargetAttr *TA,
const CPUDispatchAttr *CPUDisp,
const CPUSpecificAttr *CPUSpec) {
- assert(MVType != MultiVersioning::None &&
+ assert(MVType != MultiVersionKind::None &&
"Function lacks multiversion attribute");
// Target only causes MV if it is default, otherwise this is a normal
// function.
- if (MVType == MultiVersioning::Target && !TA->isDefaultVersion())
+ if (MVType == MultiVersionKind::Target && !TA->isDefaultVersion())
return false;
- if (MVType == MultiVersioning::Target && CheckMultiVersionValue(S, FD)) {
+ if (MVType == MultiVersionKind::Target && CheckMultiVersionValue(S, FD)) {
FD->setInvalidDecl();
return true;
}
@@ -9589,6 +9600,15 @@ static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD,
return false;
}
+static bool PreviousDeclsHaveMultiVersionAttribute(const FunctionDecl *FD) {
+ for (const Decl *D = FD->getPreviousDecl(); D; D = D->getPreviousDecl()) {
+ if (D->getAsFunction()->getMultiVersionKind() != MultiVersionKind::None)
+ return true;
+ }
+
+ return false;
+}
+
static bool CheckTargetCausesMultiVersioning(
Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, const TargetAttr *NewTA,
bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious,
@@ -9596,11 +9616,12 @@ static bool CheckTargetCausesMultiVersioning(
const auto *OldTA = OldFD->getAttr<TargetAttr>();
TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse();
// Sort order doesn't matter, it just needs to be consistent.
- llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end());
+ llvm::sort(NewParsed.Features);
// If the old decl is NOT MultiVersioned yet, and we don't cause that
// to change, this is a simple redeclaration.
- if (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr())
+ if (!NewTA->isDefaultVersion() &&
+ (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr()))
return false;
// Otherwise, this decl causes MultiVersioning.
@@ -9612,7 +9633,7 @@ static bool CheckTargetCausesMultiVersioning(
}
if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true,
- MultiVersioning::Target)) {
+ MultiVersionKind::Target)) {
NewFD->setInvalidDecl();
return true;
}
@@ -9622,6 +9643,15 @@ static bool CheckTargetCausesMultiVersioning(
return true;
}
+ // If this is 'default', permit the forward declaration.
+ if (!OldFD->isMultiVersion() && !OldTA && NewTA->isDefaultVersion()) {
+ Redeclaration = true;
+ OldDecl = OldFD;
+ OldFD->setIsMultiVersion();
+ NewFD->setIsMultiVersion();
+ return false;
+ }
+
if (CheckMultiVersionValue(S, OldFD)) {
S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
NewFD->setInvalidDecl();
@@ -9640,7 +9670,10 @@ static bool CheckTargetCausesMultiVersioning(
for (const auto *FD : OldFD->redecls()) {
const auto *CurTA = FD->getAttr<TargetAttr>();
- if (!CurTA || CurTA->isInherited()) {
+ // We allow forward declarations before ANY multiversioning attributes, but
+ // nothing after the fact.
+ if (PreviousDeclsHaveMultiVersionAttribute(FD) &&
+ (!CurTA || CurTA->isInherited())) {
S.Diag(FD->getLocation(), diag::err_multiversion_required_in_redecl)
<< 0;
S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
@@ -9662,17 +9695,17 @@ static bool CheckTargetCausesMultiVersioning(
/// multiversioned declaration collection.
static bool CheckMultiVersionAdditionalDecl(
Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD,
- MultiVersioning::Type NewMVType, const TargetAttr *NewTA,
+ MultiVersionKind NewMVType, const TargetAttr *NewTA,
const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec,
bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious,
LookupResult &Previous) {
- MultiVersioning::Type OldMVType = getMultiVersionType(OldFD);
+ MultiVersionKind OldMVType = OldFD->getMultiVersionKind();
// Disallow mixing of multiversioning types.
- if ((OldMVType == MultiVersioning::Target &&
- NewMVType != MultiVersioning::Target) ||
- (NewMVType == MultiVersioning::Target &&
- OldMVType != MultiVersioning::Target)) {
+ if ((OldMVType == MultiVersionKind::Target &&
+ NewMVType != MultiVersionKind::Target) ||
+ (NewMVType == MultiVersionKind::Target &&
+ OldMVType != MultiVersionKind::Target)) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
NewFD->setInvalidDecl();
@@ -9682,7 +9715,7 @@ static bool CheckMultiVersionAdditionalDecl(
TargetAttr::ParsedTargetAttr NewParsed;
if (NewTA) {
NewParsed = NewTA->parse();
- llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end());
+ llvm::sort(NewParsed.Features);
}
bool UseMemberUsingDeclRules =
@@ -9697,7 +9730,7 @@ static bool CheckMultiVersionAdditionalDecl(
if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules))
continue;
- if (NewMVType == MultiVersioning::Target) {
+ if (NewMVType == MultiVersionKind::Target) {
const auto *CurTA = CurFD->getAttr<TargetAttr>();
if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) {
NewFD->setIsMultiVersion();
@@ -9720,7 +9753,7 @@ static bool CheckMultiVersionAdditionalDecl(
// Handle CPUDispatch/CPUSpecific versions.
// Only 1 CPUDispatch function is allowed, this will make it go through
// the redeclaration errors.
- if (NewMVType == MultiVersioning::CPUDispatch &&
+ if (NewMVType == MultiVersionKind::CPUDispatch &&
CurFD->hasAttr<CPUDispatchAttr>()) {
if (CurCPUDisp->cpus_size() == NewCPUDisp->cpus_size() &&
std::equal(
@@ -9741,7 +9774,7 @@ static bool CheckMultiVersionAdditionalDecl(
NewFD->setInvalidDecl();
return true;
}
- if (NewMVType == MultiVersioning::CPUSpecific && CurCPUSpec) {
+ if (NewMVType == MultiVersionKind::CPUSpecific && CurCPUSpec) {
if (CurCPUSpec->cpus_size() == NewCPUSpec->cpus_size() &&
std::equal(
@@ -9777,17 +9810,27 @@ static bool CheckMultiVersionAdditionalDecl(
// Else, this is simply a non-redecl case. Checking the 'value' is only
// necessary in the Target case, since The CPUSpecific/Dispatch cases are
// handled in the attribute adding step.
- if (NewMVType == MultiVersioning::Target &&
+ if (NewMVType == MultiVersionKind::Target &&
CheckMultiVersionValue(S, NewFD)) {
NewFD->setInvalidDecl();
return true;
}
- if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, false, NewMVType)) {
+ if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD,
+ !OldFD->isMultiVersion(), NewMVType)) {
NewFD->setInvalidDecl();
return true;
}
+ // Permit forward declarations in the case where these two are compatible.
+ if (!OldFD->isMultiVersion()) {
+ OldFD->setIsMultiVersion();
+ NewFD->setIsMultiVersion();
+ Redeclaration = true;
+ OldDecl = OldFD;
+ return false;
+ }
+
NewFD->setIsMultiVersion();
Redeclaration = false;
MergeTypeWithPrevious = false;
@@ -9819,14 +9862,14 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
return true;
}
- MultiVersioning::Type MVType = getMultiVersionType(NewFD);
+ MultiVersionKind MVType = NewFD->getMultiVersionKind();
// Main isn't allowed to become a multiversion function, however it IS
// permitted to have 'main' be marked with the 'target' optimization hint.
if (NewFD->isMain()) {
- if ((MVType == MultiVersioning::Target && NewTA->isDefaultVersion()) ||
- MVType == MultiVersioning::CPUDispatch ||
- MVType == MultiVersioning::CPUSpecific) {
+ if ((MVType == MultiVersionKind::Target && NewTA->isDefaultVersion()) ||
+ MVType == MultiVersionKind::CPUDispatch ||
+ MVType == MultiVersionKind::CPUSpecific) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main);
NewFD->setInvalidDecl();
return true;
@@ -9839,7 +9882,7 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
NewFD->getDeclContext()->getRedeclContext()) {
// If there's no previous declaration, AND this isn't attempting to cause
// multiversioning, this isn't an error condition.
- if (MVType == MultiVersioning::None)
+ if (MVType == MultiVersionKind::None)
return false;
return CheckMultiVersionFirstFunction(S, NewFD, MVType, NewTA, NewCPUDisp,
NewCPUSpec);
@@ -9847,29 +9890,21 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
FunctionDecl *OldFD = OldDecl->getAsFunction();
- if (!OldFD->isMultiVersion() && MVType == MultiVersioning::None)
+ if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::None)
return false;
- if (OldFD->isMultiVersion() && MVType == MultiVersioning::None) {
+ if (OldFD->isMultiVersion() && MVType == MultiVersionKind::None) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl)
- << (getMultiVersionType(OldFD) != MultiVersioning::Target);
+ << (OldFD->getMultiVersionKind() != MultiVersionKind::Target);
NewFD->setInvalidDecl();
return true;
}
// Handle the target potentially causes multiversioning case.
- if (!OldFD->isMultiVersion() && MVType == MultiVersioning::Target)
+ if (!OldFD->isMultiVersion() && MVType == MultiVersionKind::Target)
return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA,
Redeclaration, OldDecl,
MergeTypeWithPrevious, Previous);
- // Previous declarations lack CPUDispatch/CPUSpecific.
- if (!OldFD->isMultiVersion()) {
- S.Diag(OldFD->getLocation(), diag::err_multiversion_required_in_redecl)
- << 1;
- S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
- NewFD->setInvalidDecl();
- return true;
- }
// At this point, we have a multiversion function decl (in OldFD) AND an
// appropriate attribute in the current function decl. Resolve that these are
@@ -9982,7 +10017,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
if (!getLangOpts().CPlusPlus14 && MD && MD->isConstexpr() &&
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
- (MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
+ !MD->getTypeQualifiers().hasConst()) {
CXXMethodDecl *OldMD = nullptr;
if (OldDecl)
OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl->getAsFunction());
@@ -9990,7 +10025,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
const FunctionProtoType *FPT =
MD->getType()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- EPI.TypeQuals |= Qualifiers::Const;
+ EPI.TypeQuals.addConst();
MD->setType(Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI));
@@ -10022,11 +10057,17 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (FunctionTemplateDecl *OldTemplateDecl =
dyn_cast<FunctionTemplateDecl>(OldDecl)) {
auto *OldFD = OldTemplateDecl->getTemplatedDecl();
- NewFD->setPreviousDeclaration(OldFD);
- adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
FunctionTemplateDecl *NewTemplateDecl
= NewFD->getDescribedFunctionTemplate();
assert(NewTemplateDecl && "Template/non-template mismatch");
+
+ // The call to MergeFunctionDecl above may have created some state in
+ // NewTemplateDecl that needs to be merged with OldTemplateDecl before we
+ // can add it as a redeclaration.
+ NewTemplateDecl->mergePrevDecl(OldTemplateDecl);
+
+ NewFD->setPreviousDeclaration(OldFD);
+ adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
if (NewFD->isCXXClassMember()) {
NewFD->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
@@ -10116,7 +10157,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// A deduction guide is not on the list of entities that can be
// explicitly specialized.
if (Guide->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
- Diag(Guide->getLocStart(), diag::err_deduction_guide_specialized)
+ Diag(Guide->getBeginLoc(), diag::err_deduction_guide_specialized)
<< /*explicit specialization*/ 1;
}
@@ -10479,7 +10520,7 @@ namespace {
Expr *Base = E;
bool ReferenceField = false;
- // Get the field memebers used.
+ // Get the field members used.
while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
if (!FD)
@@ -10719,11 +10760,10 @@ namespace {
return;
}
- S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
+ S.DiagRuntimeBehavior(DRE->getBeginLoc(), DRE,
S.PDiag(diag)
- << DRE->getDecl()
- << OrigDecl->getLocation()
- << DRE->getSourceRange());
+ << DRE->getDecl() << OrigDecl->getLocation()
+ << DRE->getSourceRange());
}
};
@@ -10768,7 +10808,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
DeclarationName Name, QualType Type,
TypeSourceInfo *TSI,
SourceRange Range, bool DirectInit,
- Expr *Init) {
+ Expr *&Init) {
bool IsInitCapture = !VDecl;
assert((!VDecl || !VDecl->isInitCapture()) &&
"init captures are expected to be deduced prior to initialization");
@@ -10822,7 +10862,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
if (DeduceInits.empty()) {
// It isn't possible to write this directly, but it is possible to
// end up in this situation with "auto x(some_pack...);"
- Diag(Init->getLocStart(), IsInitCapture
+ Diag(Init->getBeginLoc(), IsInitCapture
? diag::err_init_capture_no_expression
: diag::err_auto_var_init_no_expression)
<< VN << Type << Range;
@@ -10830,7 +10870,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
}
if (DeduceInits.size() > 1) {
- Diag(DeduceInits[1]->getLocStart(),
+ Diag(DeduceInits[1]->getBeginLoc(),
IsInitCapture ? diag::err_init_capture_multiple_expressions
: diag::err_auto_var_init_multiple_expressions)
<< VN << Type << Range;
@@ -10839,7 +10879,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
Expr *DeduceInit = DeduceInits[0];
if (DirectInit && isa<InitListExpr>(DeduceInit)) {
- Diag(Init->getLocStart(), IsInitCapture
+ Diag(Init->getBeginLoc(), IsInitCapture
? diag::err_init_capture_paren_braces
: diag::err_auto_var_init_paren_braces)
<< isa<InitListExpr>(Init) << VN << Type << Range;
@@ -10884,7 +10924,8 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
<< (DeduceInit->getType().isNull() ? TSI->getType()
: DeduceInit->getType())
<< DeduceInit->getSourceRange();
- }
+ } else
+ Init = DeduceInit;
// Warn if we deduced 'id'. 'auto' usually implies type-safety, but using
// 'id' instead of a specific object type prevents most of our usual
@@ -10901,7 +10942,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
}
bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
- Expr *Init) {
+ Expr *&Init) {
QualType DeducedType = deduceVarTypeFromInitializer(
VDecl, VDecl->getDeclName(), VDecl->getType(), VDecl->getTypeSourceInfo(),
VDecl->getSourceRange(), DirectInit, Init);
@@ -11144,7 +11185,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
- Init->getLocStart()))
+ Init->getBeginLoc()))
FSI->markSafeWeakUse(Init);
}
@@ -11159,9 +11200,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// struct T { S a, b; } t = { Temp(), Temp() }
//
// we should destroy the first Temp before constructing the second.
- ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(),
- false,
- VDecl->isConstexpr());
+ ExprResult Result =
+ ActOnFinishFullExpr(Init, VDecl->getLocation(),
+ /*DiscardedValue*/ false, VDecl->isConstexpr());
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
@@ -11276,9 +11317,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
Diag(VDecl->getLocation(),
diag::ext_in_class_initializer_float_type_cxx11)
<< DclT << Init->getSourceRange();
- Diag(VDecl->getLocStart(),
+ Diag(VDecl->getBeginLoc(),
diag::note_in_class_initializer_float_type_cxx11)
- << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+ << FixItHint::CreateInsertion(VDecl->getBeginLoc(), "constexpr ");
} else {
Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
<< DclT << Init->getSourceRange();
@@ -11293,8 +11334,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// Suggest adding 'constexpr' in C++11 for literal types.
} else if (getLangOpts().CPlusPlus11 && DclT->isLiteralType(Context)) {
Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type)
- << DclT << Init->getSourceRange()
- << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+ << DclT << Init->getSourceRange()
+ << FixItHint::CreateInsertion(VDecl->getBeginLoc(), "constexpr ");
VDecl->setConstexpr(true);
} else {
@@ -11407,8 +11448,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
return;
}
+ Expr *TmpInit = nullptr;
if (Type->isUndeducedType() &&
- DeduceVariableDeclarationType(Var, false, nullptr))
+ DeduceVariableDeclarationType(Var, false, TmpInit))
return;
// C++11 [class.static.data]p3: A static data member can be declared with
@@ -11708,7 +11750,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
// In Objective-C, don't allow jumps past the implicit initialization of a
// local retaining variable.
- if (getLangOpts().ObjC1 &&
+ if (getLangOpts().ObjC &&
var->hasLocalStorage()) {
switch (var->getType().getObjCLifetime()) {
case Qualifiers::OCL_None:
@@ -11827,29 +11869,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
QualType type = var->getType();
if (type->isDependentType()) return;
- // __block variables might require us to capture a copy-initializer.
- if (var->hasAttr<BlocksAttr>()) {
- // It's currently invalid to ever have a __block variable with an
- // array type; should we diagnose that here?
-
- // Regardless, we don't want to ignore array nesting when
- // constructing this copy.
- if (type->isStructureOrClassType()) {
- EnterExpressionEvaluationContext scope(
- *this, ExpressionEvaluationContext::PotentiallyEvaluated);
- SourceLocation poi = var->getLocation();
- Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi);
- ExprResult result
- = PerformMoveOrCopyInitialization(
- InitializedEntity::InitializeBlock(poi, type, false),
- var, var->getType(), varRef, /*AllowNRVO=*/true);
- if (!result.isInvalid()) {
- result = MaybeCreateExprWithCleanups(result);
- Expr *init = result.getAs<Expr>();
- Context.setBlockVarCopyInits(var, init);
- }
- }
- }
+ if (var->hasAttr<BlocksAttr>())
+ getCurFunction()->addByrefBlockVar(var);
Expr *Init = var->getInit();
bool IsGlobal = GlobalStorage && !var->isStaticLocal();
@@ -11940,6 +11961,49 @@ static bool hasDependentAlignment(VarDecl *VD) {
return false;
}
+/// Check if VD needs to be dllexport/dllimport due to being in a
+/// dllexport/import function.
+void Sema::CheckStaticLocalForDllExport(VarDecl *VD) {
+ assert(VD->isStaticLocal());
+
+ auto *FD = dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod());
+
+ // Find outermost function when VD is in lambda function.
+ while (FD && !getDLLAttr(FD) &&
+ !FD->hasAttr<DLLExportStaticLocalAttr>() &&
+ !FD->hasAttr<DLLImportStaticLocalAttr>()) {
+ FD = dyn_cast_or_null<FunctionDecl>(FD->getParentFunctionOrMethod());
+ }
+
+ if (!FD)
+ return;
+
+ // Static locals inherit dll attributes from their function.
+ if (Attr *A = getDLLAttr(FD)) {
+ auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext()));
+ NewAttr->setInherited(true);
+ VD->addAttr(NewAttr);
+ } else if (Attr *A = FD->getAttr<DLLExportStaticLocalAttr>()) {
+ auto *NewAttr = ::new (getASTContext()) DLLExportAttr(A->getRange(),
+ getASTContext(),
+ A->getSpellingListIndex());
+ NewAttr->setInherited(true);
+ VD->addAttr(NewAttr);
+
+ // Export this function to enforce exporting this static variable even
+ // if it is not used in this compilation unit.
+ if (!FD->hasAttr<DLLExportAttr>())
+ FD->addAttr(NewAttr);
+
+ } else if (Attr *A = FD->getAttr<DLLImportStaticLocalAttr>()) {
+ auto *NewAttr = ::new (getASTContext()) DLLImportAttr(A->getRange(),
+ getASTContext(),
+ A->getSpellingListIndex());
+ NewAttr->setInherited(true);
+ VD->addAttr(NewAttr);
+ }
+}
+
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
/// any semantic actions necessary after any initializer has been attached.
void Sema::FinalizeDeclaration(Decl *ThisDecl) {
@@ -11993,14 +12057,9 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
if (VD->isStaticLocal()) {
- if (FunctionDecl *FD =
- dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) {
- // Static locals inherit dll attributes from their function.
- if (Attr *A = getDLLAttr(FD)) {
- auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext()));
- NewAttr->setInherited(true);
- VD->addAttr(NewAttr);
- }
+ CheckStaticLocalForDllExport(VD);
+
+ if (dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) {
// CUDA 8.0 E.3.9.4: Within the body of a __device__ or __global__
// function, only __shared__ variables or variables without any device
// memory qualifiers may be declared with static storage class.
@@ -12375,11 +12434,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Temporarily put parameter variables in the translation unit, not
// the enclosing context. This prevents them from accidentally
// looking like class members in C++.
- ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(),
- D.getLocStart(),
- D.getIdentifierLoc(), II,
- parmDeclType, TInfo,
- SC);
+ ParmVarDecl *New =
+ CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(),
+ D.getIdentifierLoc(), II, parmDeclType, TInfo, SC);
if (D.isInvalidType())
New->setInvalidDecl();
@@ -12508,7 +12565,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
// passed by reference.
if (T->isObjCObjectType()) {
SourceLocation TypeEndLoc =
- getLocForEndOfToken(TSInfo->getTypeLoc().getLocEnd());
+ getLocForEndOfToken(TSInfo->getTypeLoc().getEndLoc());
Diag(NameLoc,
diag::err_object_cannot_be_passed_returned_by_value) << 1 << T
<< FixItHint::CreateInsertion(TypeEndLoc, "*");
@@ -12682,6 +12739,29 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
}
}
}
+
+ if (!Definition)
+ // Similar to friend functions a friend function template may be a
+ // definition and do not have a body if it is instantiated in a class
+ // template.
+ if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) {
+ for (auto I : FTD->redecls()) {
+ auto D = cast<FunctionTemplateDecl>(I);
+ if (D != FTD) {
+ assert(!D->isThisDeclarationADefinition() &&
+ "More than one definition in redeclaration chain");
+ if (D->getFriendObjectKind() != Decl::FOK_None)
+ if (FunctionTemplateDecl *FT =
+ D->getInstantiatedFromMemberTemplate()) {
+ if (FT->isThisDeclarationADefinition()) {
+ Definition = D->getTemplatedDecl();
+ break;
+ }
+ }
+ }
+ }
+ }
+
if (!Definition)
return;
@@ -12701,6 +12781,7 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
Definition->getDescribedFunctionTemplate() ||
Definition->getNumTemplateParameterLists())) {
SkipBody->ShouldSkip = true;
+ SkipBody->Previous = const_cast<FunctionDecl*>(Definition);
if (auto *TD = Definition->getDescribedFunctionTemplate())
makeMergedDefinitionVisible(TD);
makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition));
@@ -12772,6 +12853,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
// Parsing the function declaration failed in some way. Push on a fake scope
// anyway so we can try to parse the function body.
PushFunctionScope();
+ PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
return D;
}
@@ -12782,6 +12864,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
else
FD = cast<FunctionDecl>(D);
+ // Do not push if it is a lambda because one is already pushed when building
+ // the lambda in ActOnStartOfLambdaDefinition().
+ if (!isLambdaCallOperator(FD))
+ PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
+
// Check for defining attributes before the check for redefinition.
if (const auto *Attr = FD->getAttr<AliasAttr>()) {
Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 0;
@@ -12990,6 +13077,21 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
return ActOnFinishFunctionBody(D, BodyArg, false);
}
+/// RAII object that pops an ExpressionEvaluationContext when exiting a function
+/// body.
+class ExitFunctionBodyRAII {
+public:
+ ExitFunctionBodyRAII(Sema &S, bool IsLambda) : S(S), IsLambda(IsLambda) {}
+ ~ExitFunctionBodyRAII() {
+ if (!IsLambda)
+ S.PopExpressionEvaluationContext();
+ }
+
+private:
+ Sema &S;
+ bool IsLambda = false;
+};
+
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr;
@@ -13000,6 +13102,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (getLangOpts().CoroutinesTS && getCurFunction()->isCoroutine())
CheckCompletedCoroutineBody(FD, Body);
+ // Do not call PopExpressionEvaluationContext() if it is a lambda because one
+ // is already popped when finishing the lambda in BuildLambdaExpr(). This is
+ // meant to pop the context added in ActOnStartOfFunctionDef().
+ ExitFunctionBodyRAII ExitRAII(*this, isLambdaCallOperator(FD));
+
if (FD) {
FD->setBody(Body);
FD->setWillHaveBody(false);
@@ -13054,7 +13161,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (!FD->isInvalidDecl()) {
// Don't diagnose unused parameters of defaulted or deleted functions.
- if (!FD->isDeleted() && !FD->isDefaulted())
+ if (!FD->isDeleted() && !FD->isDefaulted() && !FD->hasSkippedBody())
DiagnoseUnusedParameters(FD->parameters());
DiagnoseSizeOfParametersAndReturnValue(FD->parameters(),
FD->getReturnType(), FD);
@@ -13116,7 +13223,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD->isMultiVersion() && FD->hasAttr<CPUDispatchAttr>() && Body)
if (const auto *CmpndBody = dyn_cast<CompoundStmt>(Body))
if (!CmpndBody->body_empty())
- Diag(CmpndBody->body_front()->getLocStart(),
+ Diag(CmpndBody->body_front()->getBeginLoc(),
diag::warn_dispatch_body_ignored);
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
@@ -13149,7 +13256,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
assert(MD == getCurMethodDecl() && "Method parsing confused");
MD->setBody(Body);
if (!MD->isInvalidDecl()) {
- DiagnoseUnusedParameters(MD->parameters());
+ if (!MD->hasSkippedBody())
+ DiagnoseUnusedParameters(MD->parameters());
DiagnoseSizeOfParametersAndReturnValue(MD->parameters(),
MD->getReturnType(), MD);
@@ -13157,8 +13265,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
computeNRVO(Body, getCurFunction());
}
if (getCurFunction()->ObjCShouldCallSuper) {
- Diag(MD->getLocEnd(), diag::warn_objc_missing_super_call)
- << MD->getSelector().getAsString();
+ Diag(MD->getEndLoc(), diag::warn_objc_missing_super_call)
+ << MD->getSelector().getAsString();
getCurFunction()->ObjCShouldCallSuper = false;
}
if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
@@ -13267,7 +13375,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (RegisterVariables)
continue;
if (!isa<AsmStmt>(S) && !isa<NullStmt>(S)) {
- Diag(S->getLocStart(), diag::err_non_asm_stmt_in_naked_function);
+ Diag(S->getBeginLoc(), diag::err_non_asm_stmt_in_naked_function);
Diag(FD->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
FD->setInvalidDecl();
break;
@@ -13354,15 +13462,17 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
}
// Extension in C99. Legal in C90, but warn about it.
- // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported.
unsigned diag_id;
if (II.getName().startswith("__builtin_"))
diag_id = diag::warn_builtin_unknown;
- else if (getLangOpts().C99 || getLangOpts().OpenCL)
+ // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported.
+ else if (getLangOpts().OpenCL)
+ diag_id = diag::err_opencl_implicit_function_decl;
+ else if (getLangOpts().C99)
diag_id = diag::ext_implicit_function_decl;
else
diag_id = diag::warn_implicit_function_decl;
- Diag(Loc, diag_id) << &II << getLangOpts().OpenCL;
+ Diag(Loc, diag_id) << &II;
// If we found a prior declaration of this function, don't bother building
// another one. We've already pushed that one into scope, so there's nothing
@@ -13400,12 +13510,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*NumParams=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
/*RefQualifierIsLvalueRef=*/true,
/*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc, EST_None,
/*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
@@ -13573,11 +13679,9 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
}
// Scope manipulation handled by caller.
- TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
- D.getLocStart(),
- D.getIdentifierLoc(),
- D.getIdentifier(),
- TInfo);
+ TypedefDecl *NewTD =
+ TypedefDecl::Create(Context, CurContext, D.getBeginLoc(),
+ D.getIdentifierLoc(), D.getIdentifier(), TInfo);
// Bail out immediately if we have an invalid declaration.
if (D.isInvalidType()) {
@@ -13739,76 +13843,106 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
// struct class-key shall be used to refer to a class (clause 9)
// declared using the class or struct class-key.
TagTypeKind OldTag = Previous->getTagKind();
- if (!isDefinition || !isClassCompatTagKind(NewTag))
- if (OldTag == NewTag)
+ if (OldTag != NewTag &&
+ !(isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)))
+ return false;
+
+ // Tags are compatible, but we might still want to warn on mismatched tags.
+ // Non-class tags can't be mismatched at this point.
+ if (!isClassCompatTagKind(NewTag))
+ return true;
+
+ // Declarations for which -Wmismatched-tags is disabled are entirely ignored
+ // by our warning analysis. We don't want to warn about mismatches with (eg)
+ // declarations in system headers that are designed to be specialized, but if
+ // a user asks us to warn, we should warn if their code contains mismatched
+ // declarations.
+ auto IsIgnoredLoc = [&](SourceLocation Loc) {
+ return getDiagnostics().isIgnored(diag::warn_struct_class_tag_mismatch,
+ Loc);
+ };
+ if (IsIgnoredLoc(NewTagLoc))
+ return true;
+
+ auto IsIgnored = [&](const TagDecl *Tag) {
+ return IsIgnoredLoc(Tag->getLocation());
+ };
+ while (IsIgnored(Previous)) {
+ Previous = Previous->getPreviousDecl();
+ if (!Previous)
return true;
+ OldTag = Previous->getTagKind();
+ }
- if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) {
- // Warn about the struct/class tag mismatch.
- bool isTemplate = false;
- if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
- isTemplate = Record->getDescribedClassTemplate();
+ bool isTemplate = false;
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
+ isTemplate = Record->getDescribedClassTemplate();
- if (inTemplateInstantiation()) {
+ if (inTemplateInstantiation()) {
+ if (OldTag != NewTag) {
// In a template instantiation, do not offer fix-its for tag mismatches
// since they usually mess up the template instead of fixing the problem.
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
<< getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(OldTag);
+ // FIXME: Note previous location?
+ }
+ return true;
+ }
+
+ if (isDefinition) {
+ // On definitions, check all previous tags and issue a fix-it for each
+ // one that doesn't match the current tag.
+ if (Previous->getDefinition()) {
+ // Don't suggest fix-its for redefinitions.
return true;
}
- if (isDefinition) {
- // On definitions, check previous tags and issue a fix-it for each
- // one that doesn't match the current tag.
- if (Previous->getDefinition()) {
- // Don't suggest fix-its for redefinitions.
- return true;
- }
+ bool previousMismatch = false;
+ for (const TagDecl *I : Previous->redecls()) {
+ if (I->getTagKind() != NewTag) {
+ // Ignore previous declarations for which the warning was disabled.
+ if (IsIgnored(I))
+ continue;
- bool previousMismatch = false;
- for (auto I : Previous->redecls()) {
- if (I->getTagKind() != NewTag) {
- if (!previousMismatch) {
- previousMismatch = true;
- Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
- << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
- << getRedeclDiagFromTagKind(I->getTagKind());
- }
- Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
- << getRedeclDiagFromTagKind(NewTag)
- << FixItHint::CreateReplacement(I->getInnerLocStart(),
- TypeWithKeyword::getTagTypeKindName(NewTag));
+ if (!previousMismatch) {
+ previousMismatch = true;
+ Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
+ << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
+ << getRedeclDiagFromTagKind(I->getTagKind());
}
+ Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
+ << getRedeclDiagFromTagKind(NewTag)
+ << FixItHint::CreateReplacement(I->getInnerLocStart(),
+ TypeWithKeyword::getTagTypeKindName(NewTag));
}
- return true;
- }
-
- // Check for a previous definition. If current tag and definition
- // are same type, do nothing. If no definition, but disagree with
- // with previous tag type, give a warning, but no fix-it.
- const TagDecl *Redecl = Previous->getDefinition() ?
- Previous->getDefinition() : Previous;
- if (Redecl->getTagKind() == NewTag) {
- return true;
}
+ return true;
+ }
+ // Identify the prevailing tag kind: this is the kind of the definition (if
+ // there is a non-ignored definition), or otherwise the kind of the prior
+ // (non-ignored) declaration.
+ const TagDecl *PrevDef = Previous->getDefinition();
+ if (PrevDef && IsIgnored(PrevDef))
+ PrevDef = nullptr;
+ const TagDecl *Redecl = PrevDef ? PrevDef : Previous;
+ if (Redecl->getTagKind() != NewTag) {
Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
<< getRedeclDiagFromTagKind(NewTag) << isTemplate << Name
<< getRedeclDiagFromTagKind(OldTag);
Diag(Redecl->getLocation(), diag::note_previous_use);
// If there is a previous definition, suggest a fix-it.
- if (Previous->getDefinition()) {
- Diag(NewTagLoc, diag::note_struct_class_suggestion)
- << getRedeclDiagFromTagKind(Redecl->getTagKind())
- << FixItHint::CreateReplacement(SourceRange(NewTagLoc),
- TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind()));
+ if (PrevDef) {
+ Diag(NewTagLoc, diag::note_struct_class_suggestion)
+ << getRedeclDiagFromTagKind(Redecl->getTagKind())
+ << FixItHint::CreateReplacement(SourceRange(NewTagLoc),
+ TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind()));
}
-
- return true;
}
- return false;
+
+ return true;
}
/// Add a minimal nested name specifier fixit hint to allow lookup of a tag name
@@ -14031,7 +14165,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// many points during the parsing of a struct declaration (because
// the #pragma tokens are effectively skipped over during the
// parsing of the struct).
- if (TUK == TUK_Definition) {
+ if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
AddAlignmentAttributesForRecord(RD);
AddMsStructLayoutForRecord(RD);
}
@@ -14462,12 +14596,15 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// comparison.
SkipBody->CheckSameAsPrevious = true;
SkipBody->New = createTagFromNewDecl();
- SkipBody->Previous = Hidden;
+ SkipBody->Previous = Def;
+ return Def;
} else {
SkipBody->ShouldSkip = true;
+ SkipBody->Previous = Def;
makeMergedDefinitionVisible(Hidden);
+ // Carry on and handle it like a normal definition. We'll
+ // skip starting the definitiion later.
}
- return Def;
} else if (!IsExplicitSpecializationAfterInstantiation) {
// A redeclaration in function prototype scope in C isn't
// visible elsewhere, so merely issue a warning.
@@ -14606,7 +14743,7 @@ CreateNewDecl:
// If this is an undefined enum, warn.
if (TUK != TUK_Definition && !Invalid) {
TagDecl *Def;
- if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
+ if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC) &&
cast<EnumDecl>(New)->isFixed()) {
// C++0x: 7.2p2: opaque-enum-declaration.
// Conflicts are diagnosed above. Do nothing.
@@ -14696,7 +14833,7 @@ CreateNewDecl:
// many points during the parsing of a struct declaration (because
// the #pragma tokens are effectively skipped over during the
// parsing of the struct).
- if (TUK == TUK_Definition) {
+ if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
AddAlignmentAttributesForRecord(RD);
AddMsStructLayoutForRecord(RD);
}
@@ -14758,7 +14895,7 @@ CreateNewDecl:
if (PrevDecl)
CheckRedeclarationModuleOwnership(New, PrevDecl);
- if (TUK == TUK_Definition)
+ if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip))
New->startDefinition();
ProcessDeclAttributeList(S, New, Attrs);
@@ -14808,6 +14945,8 @@ CreateNewDecl:
if (auto RD = dyn_cast<RecordDecl>(New))
RD->completeDefinition();
return nullptr;
+ } else if (SkipBody && SkipBody->ShouldSkip) {
+ return SkipBody->Previous;
} else {
return New;
}
@@ -14868,12 +15007,11 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
// class itself; this is known as the injected-class-name. For
// purposes of access checking, the injected-class-name is treated
// as if it were a public member name.
- CXXRecordDecl *InjectedClassName
- = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext,
- Record->getLocStart(), Record->getLocation(),
- Record->getIdentifier(),
- /*PrevDecl=*/nullptr,
- /*DelayTypeCreation=*/true);
+ CXXRecordDecl *InjectedClassName = CXXRecordDecl::Create(
+ Context, Record->getTagKind(), CurContext, Record->getBeginLoc(),
+ Record->getLocation(), Record->getIdentifier(),
+ /*PrevDecl=*/nullptr,
+ /*DelayTypeCreation=*/true);
Context.getTypeDeclType(InjectedClassName, Record);
InjectedClassName->setImplicit();
InjectedClassName->setAccess(AS_public);
@@ -15080,22 +15218,6 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
}
}
- // TR 18037 does not allow fields to be declared with address spaces.
- if (T.getQualifiers().hasAddressSpace() ||
- T->isDependentAddressSpaceType() ||
- T->getBaseElementTypeUnsafe()->isDependentAddressSpaceType()) {
- Diag(Loc, diag::err_field_with_address_space);
- D.setInvalidType();
- }
-
- // OpenCL v1.2 s6.9b,r & OpenCL v2.0 s6.12.5 - The following types cannot be
- // used as structure or union field: image, sampler, event or block types.
- if (LangOpts.OpenCL && (T->isEventT() || T->isImageType() ||
- T->isSamplerT() || T->isBlockPointerType())) {
- Diag(Loc, diag::err_opencl_type_struct_or_union_field) << T;
- D.setInvalidType();
- }
-
DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (D.getDeclSpec().isInlineSpecified())
@@ -15140,7 +15262,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
bool Mutable
= (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
- SourceLocation TSSL = D.getLocStart();
+ SourceLocation TSSL = D.getBeginLoc();
FieldDecl *NewFD
= CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, InitStyle,
TSSL, AS, PrevDecl, &D);
@@ -15207,12 +15329,30 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
}
}
- // OpenCL v1.2 s6.9.c: bitfields are not supported.
- if (BitWidth && getLangOpts().OpenCL) {
- Diag(Loc, diag::err_opencl_bitfields);
+ // TR 18037 does not allow fields to be declared with address space
+ if (T.getQualifiers().hasAddressSpace() || T->isDependentAddressSpaceType() ||
+ T->getBaseElementTypeUnsafe()->isDependentAddressSpaceType()) {
+ Diag(Loc, diag::err_field_with_address_space);
+ Record->setInvalidDecl();
InvalidDecl = true;
}
+ if (LangOpts.OpenCL) {
+ // OpenCL v1.2 s6.9b,r & OpenCL v2.0 s6.12.5 - The following types cannot be
+ // used as structure or union field: image, sampler, event or block types.
+ if (T->isEventT() || T->isImageType() || T->isSamplerT() ||
+ T->isBlockPointerType()) {
+ Diag(Loc, diag::err_opencl_type_struct_or_union_field) << T;
+ Record->setInvalidDecl();
+ InvalidDecl = true;
+ }
+ // OpenCL v1.2 s6.9.c: bitfields are not supported.
+ if (BitWidth) {
+ Diag(Loc, diag::err_opencl_bitfields);
+ InvalidDecl = true;
+ }
+ }
+
// Anonymous bit-fields cannot be cv-qualified (CWG 2229).
if (!InvalidDecl && getLangOpts().CPlusPlus && !II && BitWidth &&
T.hasQualifiers()) {
@@ -15602,6 +15742,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
}
RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
+ CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(EnclosingDecl);
// Start counting up the number of named members; make sure to include
// members of anonymous structs and unions in the total.
@@ -15691,9 +15832,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// virtual bases after the derived members. This would make a flexible
// array member declared at the end of an object not adjacent to the end
// of the type.
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
- if (RD->getNumVBases() != 0)
- Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
+ if (CXXRecord && CXXRecord->getNumVBases() != 0)
+ Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
<< FD->getDeclName() << Record->getTagKind();
if (!getLangOpts().C99)
Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
@@ -15784,7 +15924,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
}
ObjCFieldLifetimeErrReported = true;
}
- } else if (getLangOpts().ObjC1 &&
+ } else if (getLangOpts().ObjC &&
getLangOpts().getGC() != LangOptions::NonGC &&
Record && !Record->hasObjectMember()) {
if (FD->getType()->isObjCObjectPointerType() ||
@@ -15831,7 +15971,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// Okay, we successfully defined 'Record'.
if (Record) {
bool Completed = false;
- if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
+ if (CXXRecord) {
if (!CXXRecord->isInvalidDecl()) {
// Set access bits correctly on the directly-declared conversions.
for (CXXRecordDecl::conversion_iterator
@@ -15841,13 +15981,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
}
if (!CXXRecord->isDependentType()) {
- if (CXXRecord->hasUserDeclaredDestructor()) {
- // Adjust user-defined destructor exception spec.
- if (getLangOpts().CPlusPlus11)
- AdjustDestructorExceptionSpec(CXXRecord,
- CXXRecord->getDestructor());
- }
-
// Add any implicitly-declared members to this class.
AddImplicitlyDeclaredMembersToClass(CXXRecord);
@@ -15902,7 +16035,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
ProcessDeclAttributeList(S, Record, Attrs);
// We may have deferred checking for a deleted destructor. Check now.
- if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
+ if (CXXRecord) {
auto *Dtor = CXXRecord->getDestructor();
if (Dtor && Dtor->isImplicit() &&
ShouldDeleteSpecialMember(Dtor, CXXDestructor)) {
@@ -16289,8 +16422,10 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// Verify that there isn't already something declared with this name in this
// scope.
- NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName,
- ForVisibleRedeclaration);
+ LookupResult R(*this, Id, IdLoc, LookupOrdinaryName, ForVisibleRedeclaration);
+ LookupName(R, S);
+ NamedDecl *PrevDecl = R.getAsSingle<NamedDecl>();
+
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
@@ -16313,6 +16448,11 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
return nullptr;
if (PrevDecl) {
+ if (!TheEnumDecl->isScoped() && isa<ValueDecl>(PrevDecl)) {
+ // Check for other kinds of shadowing not already handled.
+ CheckShadow(New, PrevDecl, R);
+ }
+
// When in C++, we may get a TagDecl with the same name; in this case the
// enum constant will 'hide' the tag.
assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
@@ -16399,7 +16539,7 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
typedef SmallVector<std::unique_ptr<ECDVector>, 3> DuplicatesVector;
typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
- typedef llvm::DenseMap<int64_t, DeclOrVector> ValueToVectorMap;
+ typedef std::unordered_map<int64_t, DeclOrVector> ValueToVectorMap;
// Use int64_t as a key to avoid needing special handling for DenseMap keys.
auto EnumConstantToKey = [](const EnumConstantDecl *D) {
@@ -16570,7 +16710,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
NumNegativeBits = std::max(NumNegativeBits,
(unsigned)InitVal.getMinSignedBits());
- // Keep track of whether every enum element has type int (very commmon).
+ // Keep track of whether every enum element has type int (very common).
if (AllElementsInt)
AllElementsInt = ECD->getType() == Context.IntTy;
}
@@ -16776,7 +16916,7 @@ static void checkModuleImportContext(Sema &S, Module *M,
switch (LSD->getLanguage()) {
case LinkageSpecDecl::lang_c:
if (ExternCLoc.isInvalid())
- ExternCLoc = LSD->getLocStart();
+ ExternCLoc = LSD->getBeginLoc();
break;
case LinkageSpecDecl::lang_cxx:
break;
@@ -16792,8 +16932,9 @@ static void checkModuleImportContext(Sema &S, Module *M,
? diag::ext_module_import_not_at_top_level_noop
: diag::err_module_import_not_at_top_level_fatal)
<< M->getFullModuleName() << DC;
- S.Diag(cast<Decl>(DC)->getLocStart(),
- diag::note_module_import_not_at_top_level) << DC;
+ S.Diag(cast<Decl>(DC)->getBeginLoc(),
+ diag::note_module_import_not_at_top_level)
+ << DC;
} else if (!M->IsExternC && ExternCLoc.isValid()) {
S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
<< M->getFullModuleName();
@@ -16830,6 +16971,10 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
case LangOptions::CMK_ModuleMap:
Diag(ModuleLoc, diag::err_module_decl_in_module_map_module);
return nullptr;
+
+ case LangOptions::CMK_HeaderModule:
+ Diag(ModuleLoc, diag::err_module_decl_in_header_module);
+ return nullptr;
}
assert(ModuleScopes.size() == 1 && "expected to be at global module scope");
@@ -16898,7 +17043,8 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
case ModuleDeclKind::Implementation:
std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc(
PP.getIdentifierInfo(ModuleName), Path[0].second);
- Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible,
+ Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
+ Module::AllVisible,
/*IsIncludeDirective=*/false);
if (!Mod) {
Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
@@ -16928,6 +17074,19 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
+ // Flatten the module path for a Modules TS module name.
+ std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc;
+ if (getLangOpts().ModulesTS) {
+ std::string ModuleName;
+ for (auto &Piece : Path) {
+ if (!ModuleName.empty())
+ ModuleName += ".";
+ ModuleName += Piece.first->getName();
+ }
+ ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Path[0].second};
+ Path = ModuleIdPath(ModuleNameLoc);
+ }
+
Module *Mod =
getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
/*IsIncludeDirective=*/false);
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 77deed6047f4..0e10804a2ec7 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -93,6 +93,17 @@ static unsigned getFunctionOrMethodNumParams(const Decl *D) {
return cast<ObjCMethodDecl>(D)->param_size();
}
+static const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
+ unsigned Idx) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return FD->getParamDecl(Idx);
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->getParamDecl(Idx);
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
+ return BD->getParamDecl(Idx);
+ return nullptr;
+}
+
static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
@@ -103,12 +114,8 @@ static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
}
static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- return FD->getParamDecl(Idx)->getSourceRange();
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
- return MD->parameters()[Idx]->getSourceRange();
- if (const auto *BD = dyn_cast<BlockDecl>(D))
- return BD->getParamDecl(Idx)->getSourceRange();
+ if (auto *PVD = getFunctionOrMethodParam(D, Idx))
+ return PVD->getSourceRange();
return SourceRange();
}
@@ -182,7 +189,7 @@ static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
unsigned Num, unsigned Diag,
Compare Comp) {
if (Comp(getNumAttributeArgs(AL), Num)) {
- S.Diag(AL.getLoc(), Diag) << AL.getName() << Num;
+ S.Diag(AL.getLoc(), Diag) << AL << Num;
return false;
}
@@ -225,34 +232,25 @@ getAttrLoc(const AttrInfo &AL) {
}
static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
-/// A helper function to provide Attribute Name for the Attr types
-/// AND the ParsedAttr.
-template <typename AttrInfo>
-static typename std::enable_if<std::is_base_of<Attr, AttrInfo>::value,
- const AttrInfo *>::type
-getAttrName(const AttrInfo &AL) {
- return &AL;
-}
-static const IdentifierInfo *getAttrName(const ParsedAttr &AL) {
- return AL.getName();
-}
-
/// If Expr is a valid integer constant, get the value of the integer
/// expression and return success or failure. May output an error.
+///
+/// Negative argument is implicitly converted to unsigned, unless
+/// \p StrictlyUnsigned is true.
template <typename AttrInfo>
static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
- uint32_t &Val, unsigned Idx = UINT_MAX) {
+ uint32_t &Val, unsigned Idx = UINT_MAX,
+ bool StrictlyUnsigned = false) {
llvm::APSInt I(32);
if (Expr->isTypeDependent() || Expr->isValueDependent() ||
!Expr->isIntegerConstantExpr(I, S.Context)) {
if (Idx != UINT_MAX)
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
- << getAttrName(AI) << Idx << AANT_ArgumentIntegerConstant
- << Expr->getSourceRange();
+ << AI << Idx << AANT_ArgumentIntegerConstant
+ << Expr->getSourceRange();
else
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
- << getAttrName(AI) << AANT_ArgumentIntegerConstant
- << Expr->getSourceRange();
+ << AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange();
return false;
}
@@ -262,6 +260,12 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
return false;
}
+ if (StrictlyUnsigned && I.isSigned() && I.isNegative()) {
+ S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer)
+ << AI << /*non-negative*/ 1;
+ return false;
+ }
+
Val = (uint32_t)I.getZExtValue();
return true;
}
@@ -291,10 +295,19 @@ static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Ex
/// Diagnose mutually exclusive attributes when present on a given
/// declaration. Returns true if diagnosed.
template <typename AttrTy>
-static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
- IdentifierInfo *Ident) {
+static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) {
if (const auto *A = D->getAttr<AttrTy>()) {
- S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A;
+ S.Diag(A->getLocation(), diag::note_conflicting_attribute);
+ return true;
+ }
+ return false;
+}
+
+template <typename AttrTy>
+static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) {
+ if (const auto *A = D->getAttr<AttrTy>()) {
+ S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL
<< A;
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
return true;
@@ -324,22 +337,21 @@ static bool checkFunctionOrMethodParameterIndex(
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
!IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
- << getAttrName(AI) << AttrArgNum << AANT_ArgumentIntegerConstant
- << IdxExpr->getSourceRange();
+ << &AI << AttrArgNum << AANT_ArgumentIntegerConstant
+ << IdxExpr->getSourceRange();
return false;
}
unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX);
if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
- << getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange();
+ << &AI << AttrArgNum << IdxExpr->getSourceRange();
return false;
}
if (HasImplicitThisParam && !CanIndexImplicitThis) {
if (IdxSource == 1) {
- S.Diag(getAttrLoc(AI),
- diag::err_attribute_invalid_implicit_this_argument)
- << getAttrName(AI) << IdxExpr->getSourceRange();
+ S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
+ << &AI << IdxExpr->getSourceRange();
return false;
}
}
@@ -359,7 +371,7 @@ bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
if (AL.isArgIdent(ArgNum)) {
IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum);
Diag(Loc->Loc, diag::err_attribute_argument_type)
- << AL.getName() << AANT_ArgumentString
+ << AL << AANT_ArgumentString
<< FixItHint::CreateInsertion(Loc->Loc, "\"")
<< FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
Str = Loc->Ident->getName();
@@ -372,11 +384,11 @@ bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
Expr *ArgExpr = AL.getArgAsExpr(ArgNum);
const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
if (ArgLocation)
- *ArgLocation = ArgExpr->getLocStart();
+ *ArgLocation = ArgExpr->getBeginLoc();
if (!Literal || !Literal->isAscii()) {
- Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type)
- << AL.getName() << AANT_ArgumentString;
+ Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentString;
return false;
}
@@ -387,9 +399,59 @@ bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
/// Applies the given attribute to the Decl without performing any
/// additional semantic checking.
template <typename AttrType>
+static void handleSimpleAttribute(Sema &S, Decl *D, SourceRange SR,
+ unsigned SpellingIndex) {
+ D->addAttr(::new (S.Context) AttrType(SR, S.Context, SpellingIndex));
+}
+
+template <typename AttrType>
static void handleSimpleAttribute(Sema &S, Decl *D, const ParsedAttr &AL) {
- D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
+ handleSimpleAttribute<AttrType>(S, D, AL.getRange(),
+ AL.getAttributeSpellingListIndex());
+}
+
+
+template <typename... DiagnosticArgs>
+static const Sema::SemaDiagnosticBuilder&
+appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
+ return Bldr;
+}
+
+template <typename T, typename... DiagnosticArgs>
+static const Sema::SemaDiagnosticBuilder&
+appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
+ DiagnosticArgs &&... ExtraArgs) {
+ return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
+ std::forward<DiagnosticArgs>(ExtraArgs)...);
+}
+
+/// Add an attribute {@code AttrType} to declaration {@code D}, provided that
+/// {@code PassesCheck} is true.
+/// Otherwise, emit diagnostic {@code DiagID}, passing in all parameters
+/// specified in {@code ExtraArgs}.
+template <typename AttrType, typename... DiagnosticArgs>
+static void
+handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, SourceRange SR,
+ unsigned SpellingIndex,
+ bool PassesCheck,
+ unsigned DiagID, DiagnosticArgs&&... ExtraArgs) {
+ if (!PassesCheck) {
+ Sema::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID);
+ appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
+ return;
+ }
+ handleSimpleAttribute<AttrType>(S, D, SR, SpellingIndex);
+}
+
+template <typename AttrType, typename... DiagnosticArgs>
+static void
+handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, const ParsedAttr &AL,
+ bool PassesCheck,
+ unsigned DiagID,
+ DiagnosticArgs&&... ExtraArgs) {
+ return handleSimpleAttributeOrDiagnose<AttrType>(
+ S, D, AL.getRange(), AL.getAttributeSpellingListIndex(), PassesCheck,
+ DiagID, std::forward<DiagnosticArgs>(ExtraArgs)...);
}
template <typename AttrType>
@@ -404,8 +466,7 @@ template <typename AttrType, typename IncompatibleAttrType,
typename... IncompatibleAttrTypes>
static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL.getRange(),
- AL.getName()))
+ if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL))
return;
handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D,
AL);
@@ -421,17 +482,36 @@ static bool isIntOrBool(Expr *Exp) {
// Check to see if the type is a smart pointer of some kind. We assume
// it's a smart pointer if it defines both operator-> and operator*.
static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
- DeclContextLookupResult Res1 = RT->getDecl()->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Star));
- if (Res1.empty())
- return false;
+ auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record,
+ OverloadedOperatorKind Op) {
+ DeclContextLookupResult Result =
+ Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op));
+ return !Result.empty();
+ };
+
+ const RecordDecl *Record = RT->getDecl();
+ bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
+ bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
+ if (foundStarOperator && foundArrowOperator)
+ return true;
- DeclContextLookupResult Res2 = RT->getDecl()->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow));
- if (Res2.empty())
+ const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record);
+ if (!CXXRecord)
return false;
- return true;
+ for (auto BaseSpecifier : CXXRecord->bases()) {
+ if (!foundStarOperator)
+ foundStarOperator = IsOverloadedOperatorPresent(
+ BaseSpecifier.getType()->getAsRecordDecl(), OO_Star);
+ if (!foundArrowOperator)
+ foundArrowOperator = IsOverloadedOperatorPresent(
+ BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow);
+ }
+
+ if (foundStarOperator && foundArrowOperator)
+ return true;
+
+ return false;
}
/// Check if passed in Decl is a pointer type.
@@ -455,8 +535,7 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
return true;
}
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
- << AL.getName() << QT;
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT;
return false;
}
@@ -473,6 +552,29 @@ static const RecordType *getRecordType(QualType QT) {
return nullptr;
}
+template <typename AttrType>
+static bool checkRecordDeclForAttr(const RecordDecl *RD) {
+ // Check if the record itself has the attribute.
+ if (RD->hasAttr<AttrType>())
+ return true;
+
+ // Else check if any base classes have the attribute.
+ if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+ CXXBasePaths BPaths(false, false);
+ if (CRD->lookupInBases(
+ [](const CXXBaseSpecifier *BS, CXXBasePath &) {
+ const auto &Ty = *BS->getType();
+ // If it's type-dependent, we assume it could have the attribute.
+ if (Ty.isDependentType())
+ return true;
+ return Ty.getAs<RecordType>()->getDecl()->hasAttr<AttrType>();
+ },
+ BPaths, true))
+ return true;
+ }
+ return false;
+}
+
static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
const RecordType *RT = getRecordType(Ty);
@@ -488,21 +590,7 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
if (threadSafetyCheckIsSmartPointer(S, RT))
return true;
- // Check if the record itself has a capability.
- RecordDecl *RD = RT->getDecl();
- if (RD->hasAttr<CapabilityAttr>())
- return true;
-
- // Else check if any base classes have a capability.
- if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) {
- const auto *Type = BS->getType()->getAs<RecordType>();
- return Type->getDecl()->hasAttr<CapabilityAttr>();
- }, BPaths))
- return true;
- }
- return false;
+ return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl());
}
static bool checkTypedefTypeForCapability(QualType Ty) {
@@ -560,8 +648,27 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args,
- int Sidx = 0,
+ unsigned Sidx = 0,
bool ParamIdxOk = false) {
+ if (Sidx == AL.getNumArgs()) {
+ // If we don't have any capability arguments, the attribute implicitly
+ // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're
+ // a non-static method, and that the class is a (scoped) capability.
+ const auto *MD = dyn_cast<const CXXMethodDecl>(D);
+ if (MD && !MD->isStatic()) {
+ const CXXRecordDecl *RD = MD->getParent();
+ // FIXME -- need to check this again on template instantiation
+ if (!checkRecordDeclForAttr<CapabilityAttr>(RD) &&
+ !checkRecordDeclForAttr<ScopedLockableAttr>(RD))
+ S.Diag(AL.getLoc(),
+ diag::warn_thread_attribute_not_on_capability_member)
+ << AL << MD->getParent();
+ } else {
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member)
+ << AL;
+ }
+ }
+
for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) {
Expr *ArgExp = AL.getArgAsExpr(Idx);
@@ -582,7 +689,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// We allow constant strings to be used as a placeholder for expressions
// that are not valid C++ syntax, but warn that they are ignored.
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL;
Args.push_back(ArgExp);
continue;
}
@@ -611,7 +718,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
- << AL.getName() << Idx + 1 << NumParams;
+ << AL << Idx + 1 << NumParams;
continue;
}
ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
@@ -624,7 +731,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// boolean logic expression. Eg) requires_capability(A || B && !C)
if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
- << AL.getName() << ArgTy;
+ << AL << ArgTy;
Args.push_back(ArgExp);
}
@@ -686,8 +793,7 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
// Check that this attribute only applies to lockable types.
QualType QT = cast<ValueDecl>(D)->getType();
if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
- << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL;
return false;
}
@@ -772,9 +878,9 @@ static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex());
if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) {
- SourceLocation SrcLoc = AttrArg->getLocStart();
+ SourceLocation SrcLoc = AttrArg->getBeginLoc();
S.Diag(SrcLoc, diag::err_attribute_integers_only)
- << getAttrName(AI) << Param->getSourceRange();
+ << AI << Param->getSourceRange();
return false;
}
return true;
@@ -787,8 +893,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
const auto *FD = cast<FunctionDecl>(D);
if (!FD->getReturnType()->isPointerType()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
- << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL;
return;
}
@@ -825,7 +930,7 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
if (!isIntOrBool(AL.getArgAsExpr(0))) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 1 << AANT_ArgumentIntOrBool;
+ << AL << 1 << AANT_ArgumentIntOrBool;
return false;
}
@@ -907,8 +1012,7 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL,
if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
!Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
Diags)) {
- S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr)
- << AL.getName();
+ S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL;
for (const PartialDiagnosticAt &PDiag : Diags)
S.Diag(PDiag.first, PDiag.second);
return false;
@@ -987,7 +1091,7 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
DiagnoseIfAttr::DiagnosticType DiagType;
if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) {
- S.Diag(AL.getArgAsExpr(2)->getLocStart(),
+ S.Diag(AL.getArgAsExpr(2)->getBeginLoc(),
diag::err_diagnose_if_invalid_diagnostic_type);
return;
}
@@ -1002,8 +1106,7 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->hasAttr<PassObjectSizeAttr>()) {
- S.Diag(D->getLocStart(), diag::err_attribute_only_once_per_parameter)
- << AL.getName();
+ S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL;
return;
}
@@ -1016,8 +1119,8 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// __builtin_object_size. So, it has the same constraints as that second
// argument; namely, it must be in the range [0, 3].
if (Type > 3) {
- S.Diag(E->getLocStart(), diag::err_attribute_argument_outof_range)
- << AL.getName() << 0 << 3 << E->getSourceRange();
+ S.Diag(E->getBeginLoc(), diag::err_attribute_argument_outof_range)
+ << AL << 0 << 3 << E->getSourceRange();
return;
}
@@ -1026,8 +1129,7 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// At this point, we have no clue if `D` belongs to a function declaration or
// definition, so we defer the constness check until later.
if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
- S.Diag(D->getLocStart(), diag::err_attribute_pointers_only)
- << AL.getName() << 1;
+ S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1;
return;
}
@@ -1042,13 +1144,13 @@ static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
IdentifierLoc *IL = AL.getArgAsIdent(0);
if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
DefaultState)) {
- S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
- << AL.getName() << IL->Ident;
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
+ << IL->Ident;
return;
}
} else {
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL.getName() << AANT_ArgumentIdentifier;
+ << AL << AANT_ArgumentIdentifier;
return;
}
@@ -1059,8 +1161,7 @@ static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
const ParsedAttr &AL) {
- ASTContext &CurrContext = S.getASTContext();
- QualType ThisType = MD->getThisType(CurrContext)->getPointeeType();
+ QualType ThisType = MD->getThisType()->getPointeeType();
if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
if (!RD->hasAttr<ConsumableAttr>()) {
@@ -1098,8 +1199,7 @@ static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
CallableState)) {
- S.Diag(Loc, diag::warn_attribute_type_not_supported)
- << AL.getName() << StateString;
+ S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString;
return;
}
@@ -1121,12 +1221,12 @@ static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
ParamState)) {
S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << AL.getName() << StateString;
+ << AL << StateString;
return;
}
} else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
- AL.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIdentifier;
return;
}
@@ -1154,13 +1254,13 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
IdentifierLoc *IL = AL.getArgAsIdent(0);
if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
ReturnState)) {
- S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
- << AL.getName() << IL->Ident;
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
+ << IL->Ident;
return;
}
} else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
- AL.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIdentifier;
return;
}
@@ -1174,7 +1274,7 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
//
//} else if (const CXXConstructorDecl *Constructor =
// dyn_cast<CXXConstructorDecl>(D)) {
- // ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType();
+ // ReturnType = Constructor->getThisType()->getPointeeType();
//
//} else {
//
@@ -1203,13 +1303,13 @@ static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
IdentifierLoc *Ident = AL.getArgAsIdent(0);
StringRef Param = Ident->Ident->getName();
if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
- S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << AL.getName() << Param;
+ S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
+ << Param;
return;
}
} else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
- AL.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIdentifier;
return;
}
@@ -1227,13 +1327,13 @@ static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
IdentifierLoc *Ident = AL.getArgAsIdent(0);
StringRef Param = Ident->Ident->getName();
if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
- S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << AL.getName() << Param;
+ S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
+ << Param;
return;
}
} else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type) <<
- AL.getName() << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIdentifier;
return;
}
@@ -1261,7 +1361,7 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (BitfieldByteAligned)
// The PS4 target needs to maintain ABI backwards compatibility.
S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
- << AL.getName() << FD->getType();
+ << AL << FD->getType();
else
FD->addAttr(::new (S.Context) PackedAttr(
AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
@@ -1275,7 +1375,7 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
} else
- S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
}
static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -1285,19 +1385,19 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
- << AL.getName() << VD->getType() << 0;
+ << AL << VD->getType() << 0;
return false;
}
}
else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
- << AL.getName() << PD->getType() << 1;
+ << AL << PD->getType() << 1;
return false;
}
}
else {
- S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;
return false;
}
@@ -1317,8 +1417,7 @@ static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) {
// The iboutletcollection attribute can have zero or one arguments.
if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
return;
}
@@ -1390,10 +1489,10 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL,
if (!S.isValidPointerAttrType(T)) {
if (isReturnValue)
S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
- << AL.getName() << AttrParmRange << TypeRange;
+ << AL << AttrParmRange << TypeRange;
else
S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
- << AL.getName() << AttrParmRange << TypeRange << 0;
+ << AL << AttrParmRange << TypeRange << 0;
return false;
}
return true;
@@ -1486,7 +1585,7 @@ static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
QualType T = cast<ParmVarDecl>(D)->getType();
if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) {
S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
- << AL.getName() << AL.getRange() << 0;
+ << AL << AL.getRange() << 0;
return;
}
@@ -1579,7 +1678,7 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
if (!Ty->isDependentType() && !Ty->isIntegralType(Context)) {
- Diag(ParamExpr->getLocStart(), diag::err_attribute_integers_only)
+ Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only)
<< &TmpAttr
<< FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
return;
@@ -1611,7 +1710,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 1 << AANT_ArgumentIdentifier;
+ << AL << 1 << AANT_ArgumentIdentifier;
return;
}
@@ -1625,15 +1724,13 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
case OwnershipAttr::Takes:
case OwnershipAttr::Holds:
if (AL.getNumArgs() < 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments)
- << AL.getName() << 2;
+ S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2;
return;
}
break;
case OwnershipAttr::Returns:
if (AL.getNumArgs() > 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
return;
}
break;
@@ -1668,8 +1765,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
break;
}
if (-1 != Err) {
- S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err
- << Ex->getSourceRange();
+ S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err
+ << Ex->getSourceRange();
return;
}
@@ -1679,8 +1776,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// index.
if (I->getOwnKind() != K && I->args_end() !=
std::find(I->args_begin(), I->args_end(), Idx)) {
- S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
- << AL.getName() << I;
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I;
return;
} else if (K == OwnershipAttr::Returns &&
I->getOwnKind() == OwnershipAttr::Returns) {
@@ -1710,8 +1806,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check the attribute arguments.
if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
return;
}
@@ -1812,7 +1907,16 @@ static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
}
- // FIXME: check if target symbol exists in current file
+ // Mark target used to prevent unneeded-internal-declaration warnings.
+ if (!S.LangOpts.CPlusPlus) {
+ // FIXME: demangle Str for C++, as the attribute refers to the mangled
+ // linkage name, not the pre-mangled identifier.
+ const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc());
+ LookupResult LR(S, target, Sema::LookupOrdinaryName);
+ if (S.LookupQualifiedName(LR, S.getCurLexicalContext()))
+ for (NamedDecl *ND : LR)
+ ND->markUsed(S.Context);
+ }
D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
AL.getAttributeSpellingListIndex()));
@@ -1846,11 +1950,19 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
- << AL.getName() << getFunctionOrMethodResultSourceRange(D);
+ << AL << getFunctionOrMethodResultSourceRange(D);
}
static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
FunctionDecl *FD = cast<FunctionDecl>(D);
+
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->getParent()->isLambda()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL;
+ return;
+ }
+ }
+
if (!checkAttributeAtLeastNumArgs(S, AL, 1))
return;
@@ -1858,7 +1970,7 @@ static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) {
if (!AL.isArgIdent(ArgNo)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL.getName() << AANT_ArgumentIdentifier;
+ << AL << AANT_ArgumentIdentifier;
return;
}
@@ -1896,18 +2008,16 @@ static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (S.LangOpts.CPlusPlus) {
S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
- << AL.getName() << AttributeLangSupport::Cpp;
+ << AL << AttributeLangSupport::Cpp;
return;
}
- if (CommonAttr *CA = S.mergeCommonAttr(D, AL.getRange(), AL.getName(),
- AL.getAttributeSpellingListIndex()))
+ if (CommonAttr *CA = S.mergeCommonAttr(D, AL))
D->addAttr(CA);
}
static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL.getRange(),
- AL.getName()))
+ if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL))
return;
if (AL.isDeclspecAttribute()) {
@@ -1916,7 +2026,7 @@ static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (Arch != llvm::Triple::x86 &&
(Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) {
S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch)
- << AL.getName() << Triple.getArchName();
+ << AL << Triple.getArchName();
return;
}
}
@@ -1930,7 +2040,7 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attrs.getName() << ExpectedFunctionOrMethod;
+ << Attrs << ExpectedFunctionOrMethod;
return;
}
@@ -1957,7 +2067,7 @@ bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
// Check whether the attribute is valid on the current target.
if (!AL.existsInTarget(Context.getTargetInfo())) {
- Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName();
+ Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL;
AL.setInvalid();
return true;
}
@@ -1973,10 +2083,10 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD || (!VD->getType()->isBlockPointerType() &&
!VD->getType()->isFunctionPointerType())) {
- S.Diag(AL.getLoc(),
- AL.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
- : diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunctionMethodOrBlock;
+ S.Diag(AL.getLoc(), AL.isCXX11Attribute()
+ ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
+ << AL << ExpectedFunctionMethodOrBlock;
return;
}
}
@@ -2065,7 +2175,7 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// If this is spelled as the standard C++17 attribute, but not in C++17, warn
// about using it as an extension.
if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr)
- S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName();
+ S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
D->addAttr(::new (S.Context) UnusedAttr(
AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
@@ -2108,7 +2218,7 @@ static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
- << AL.getName() << AL.getRange();
+ << AL << AL.getRange();
return;
}
@@ -2365,6 +2475,15 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr()))
Replacement = SE->getString();
+ if (II->isStr("swift")) {
+ if (Introduced.isValid() || Obsoleted.isValid() ||
+ (!IsUnavailable && !Deprecated.isValid())) {
+ S.Diag(AL.getLoc(),
+ diag::warn_availability_swift_unavailable_deprecated_only);
+ return;
+ }
+ }
+
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, AL.getRange(), II,
false/*Implicit*/,
Introduced.Version,
@@ -2506,8 +2625,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
bool isTypeVisibility) {
// Visibility attributes don't mean anything on a typedef.
if (isa<TypedefNameDecl>(D)) {
- S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored)
- << AL.getName();
+ S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL;
return;
}
@@ -2517,7 +2635,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
isa<ObjCInterfaceDecl>(D) ||
isa<NamespaceDecl>(D))) {
S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
- << AL.getName() << ExpectedTypeOrNamespace;
+ << AL << ExpectedTypeOrNamespace;
return;
}
@@ -2529,8 +2647,8 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
VisibilityAttr::VisibilityType type;
if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
- S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
- << AL.getName() << TypeStr;
+ S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL
+ << TypeStr;
return;
}
@@ -2559,15 +2677,14 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
const auto *M = cast<ObjCMethodDecl>(D);
if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 1 << AANT_ArgumentIdentifier;
+ << AL << 1 << AANT_ArgumentIdentifier;
return;
}
IdentifierLoc *IL = AL.getArgAsIdent(0);
ObjCMethodFamilyAttr::FamilyKind F;
if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
- S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
- << AL.getName() << IL->Ident;
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident;
return;
}
@@ -2631,15 +2748,14 @@ static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 1 << AANT_ArgumentIdentifier;
+ << AL << 1 << AANT_ArgumentIdentifier;
return;
}
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
BlocksAttr::BlockType type;
if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL.getName() << II;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
return;
}
@@ -2656,8 +2772,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 1 << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
+ << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange();
return;
}
@@ -2677,8 +2792,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 2 << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
+ << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange();
return;
}
nullPos = Idx.getZExtValue();
@@ -2726,12 +2840,12 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
} else {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunctionMethodOrBlock;
+ << AL << ExpectedFunctionMethodOrBlock;
return;
}
} else {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunctionMethodOrBlock;
+ << AL << ExpectedFunctionMethodOrBlock;
return;
}
D->addAttr(::new (S.Context)
@@ -2742,14 +2856,12 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->getFunctionType() &&
D->getFunctionType()->getReturnType()->isVoidType()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method)
- << AL.getName() << 0;
+ S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0;
return;
}
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
if (MD->getReturnType()->isVoidType()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1;
return;
}
@@ -2757,7 +2869,7 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
// about using it as an extension.
if (!S.getLangOpts().CPlusPlus17 && AL.isCXX11Attribute() &&
!AL.getScopeName())
- S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL.getName();
+ S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
D->addAttr(::new (S.Context)
WarnUnusedResultAttr(AL.getRange(), S.Context,
@@ -2777,7 +2889,7 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Nothing to warn about here.
} else
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedVariableOrFunction;
+ << AL << ExpectedVariableOrFunction;
return;
}
@@ -2793,11 +2905,12 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
uint32_t WGSize[3];
for (unsigned i = 0; i < 3; ++i) {
const Expr *E = AL.getArgAsExpr(i);
- if (!checkUInt32Argument(S, AL, E, WGSize[i], i))
+ if (!checkUInt32Argument(S, AL, E, WGSize[i], i,
+ /*StrictlyUnsigned=*/true))
return;
if (WGSize[i] == 0) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
- << AL.getName() << E->getSourceRange();
+ << AL << E->getSourceRange();
return;
}
}
@@ -2806,7 +2919,7 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
if (Existing && !(Existing->getXDim() == WGSize[0] &&
Existing->getYDim() == WGSize[1] &&
Existing->getZDim() == WGSize[2]))
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
D->addAttr(::new (S.Context) WorkGroupAttr(AL.getRange(), S.Context,
WGSize[0], WGSize[1], WGSize[2],
@@ -2821,14 +2934,14 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
if (SGSize == 0) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
- << AL.getName() << E->getSourceRange();
+ << AL << E->getSourceRange();
return;
}
OpenCLIntelReqdSubGroupSizeAttr *Existing =
D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
if (Existing && Existing->getSubGroupSize() != SGSize)
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
D->addAttr(::new (S.Context) OpenCLIntelReqdSubGroupSizeAttr(
AL.getRange(), S.Context, SGSize,
@@ -2837,8 +2950,7 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!AL.hasParsedType()) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
return;
}
@@ -2856,7 +2968,7 @@ static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
return;
}
}
@@ -3030,7 +3142,7 @@ static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>();
if (Existing && Existing->getVectorWidth() != VecWidth) {
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
return;
}
@@ -3100,7 +3212,7 @@ static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 0 << AANT_ArgumentIdentifier;
+ << AL << 0 << AANT_ArgumentIdentifier;
return;
}
@@ -3108,8 +3220,7 @@ static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(),
ExtensibilityKind)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL.getName() << II;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
return;
}
@@ -3188,7 +3299,7 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) {
/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.getLangOpts().CPlusPlus) {
- S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName();
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
return;
}
@@ -3215,7 +3326,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (prioritynum < 101 || prioritynum > 65535) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_outof_range)
- << E->getSourceRange() << AL.getName() << 101 << 65535;
+ << E->getSourceRange() << AL << 101 << 65535;
AL.setInvalid();
return;
}
@@ -3250,7 +3361,7 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 1 << AANT_ArgumentIdentifier;
+ << AL << 1 << AANT_ArgumentIdentifier;
return;
}
@@ -3275,7 +3386,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (Kind == InvalidFormat) {
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL.getName() << II->getName();
+ << AL << II->getName();
return;
}
@@ -3287,7 +3398,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (Idx < 1 || Idx > NumArgs) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL.getName() << 2 << IdxExpr->getSourceRange();
+ << AL << 2 << IdxExpr->getSourceRange();
return;
}
@@ -3358,7 +3469,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// if 0 it disables parameter checking (to use with e.g. va_list)
} else if (FirstArg != 0 && FirstArg != NumArgs) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL.getName() << 3 << FirstArgExpr->getSourceRange();
+ << AL << 3 << FirstArgExpr->getSourceRange();
return;
}
@@ -3379,8 +3490,8 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
RD = dyn_cast<RecordDecl>(D);
if (!RD || !RD->isUnion()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedUnion;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL
+ << ExpectedUnion;
return;
}
@@ -3513,8 +3624,7 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// check the attribute arguments.
if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
return;
}
@@ -3794,8 +3904,8 @@ static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// This attribute isn't documented, but glibc uses it. It changes
// the width of an int or unsigned int to the specified size.
if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName()
- << AANT_ArgumentIdentifier;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIdentifier;
return;
}
@@ -3968,26 +4078,55 @@ AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
-CommonAttr *Sema::mergeCommonAttr(Decl *D, SourceRange Range,
- IdentifierInfo *Ident,
- unsigned AttrSpellingListIndex) {
- if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, Range, Ident))
+CommonAttr *Sema::mergeCommonAttr(Decl *D, const ParsedAttr &AL) {
+ if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL))
+ return nullptr;
+
+ return ::new (Context)
+ CommonAttr(AL.getRange(), Context, AL.getAttributeSpellingListIndex());
+}
+
+CommonAttr *Sema::mergeCommonAttr(Decl *D, const CommonAttr &AL) {
+ if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL))
return nullptr;
- return ::new (Context) CommonAttr(Range, Context, AttrSpellingListIndex);
+ return ::new (Context)
+ CommonAttr(AL.getRange(), Context, AL.getSpellingListIndex());
}
+InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D,
+ const ParsedAttr &AL) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ // Attribute applies to Var but not any subclass of it (like ParmVar,
+ // ImplicitParm or VarTemplateSpecialization).
+ if (VD->getKind() != Decl::Var) {
+ Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+ : ExpectedVariableOrFunction);
+ return nullptr;
+ }
+ // Attribute does not apply to non-static local variables.
+ if (VD->hasLocalStorage()) {
+ Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
+ return nullptr;
+ }
+ }
+
+ if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL))
+ return nullptr;
+
+ return ::new (Context) InternalLinkageAttr(
+ AL.getRange(), Context, AL.getAttributeSpellingListIndex());
+}
InternalLinkageAttr *
-Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range,
- IdentifierInfo *Ident,
- unsigned AttrSpellingListIndex) {
+Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) {
if (const auto *VD = dyn_cast<VarDecl>(D)) {
// Attribute applies to Var but not any subclass of it (like ParmVar,
// ImplicitParm or VarTemplateSpecialization).
if (VD->getKind() != Decl::Var) {
- Diag(Range.getBegin(), diag::warn_attribute_wrong_decl_type)
- << Ident << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
- : ExpectedVariableOrFunction);
+ Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type)
+ << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+ : ExpectedVariableOrFunction);
return nullptr;
}
// Attribute does not apply to non-static local variables.
@@ -3997,11 +4136,11 @@ Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range,
}
}
- if (checkAttrMutualExclusion<CommonAttr>(*this, D, Range, Ident))
+ if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL))
return nullptr;
return ::new (Context)
- InternalLinkageAttr(Range, Context, AttrSpellingListIndex);
+ InternalLinkageAttr(AL.getRange(), Context, AL.getSpellingListIndex());
}
MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range,
@@ -4039,8 +4178,7 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
}
static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL.getRange(),
- AL.getName()))
+ if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL))
return;
if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
@@ -4062,8 +4200,7 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL.getRange(),
- AL.getName()))
+ if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL))
return;
const auto *VD = cast<VarDecl>(D);
if (!VD->hasGlobalStorage()) {
@@ -4075,13 +4212,12 @@ static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL.getRange(),
- AL.getName()))
+ if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL))
return;
const auto *VD = cast<VarDecl>(D);
// extern __shared__ is only allowed on arrays with no length (e.g.
// "int x[]").
- if (!S.getLangOpts().CUDARelocatableDeviceCode && VD->hasExternalStorage() &&
+ if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() &&
!isa<IncompleteArrayType>(VD->getType())) {
S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD;
return;
@@ -4095,10 +4231,8 @@ static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL.getRange(),
- AL.getName()) ||
- checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL.getRange(),
- AL.getName())) {
+ if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL) ||
+ checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL)) {
return;
}
const auto *FD = cast<FunctionDecl>(D);
@@ -4112,15 +4246,15 @@ static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
if (Method->isInstance()) {
- S.Diag(Method->getLocStart(), diag::err_kern_is_nonstatic_method)
+ S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method)
<< Method;
return;
}
- S.Diag(Method->getLocStart(), diag::warn_kern_is_method) << Method;
+ S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method;
}
// Only warn for "inline" when compiling for host, to cut down on noise.
if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice)
- S.Diag(FD->getLocStart(), diag::warn_kern_is_inline) << FD;
+ S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD;
D->addAttr(::new (S.Context)
CUDAGlobalAttr(AL.getRange(), S.Context,
@@ -4150,7 +4284,7 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunctionOrMethod;
+ << AL << ExpectedFunctionOrMethod;
return;
}
@@ -4222,6 +4356,11 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
AL.getAttributeSpellingListIndex()));
return;
}
+ case ParsedAttr::AT_AArch64VectorPcs:
+ D->addAttr(::new(S.Context)
+ AArch64VectorPcsAttr(AL.getRange(), S.Context,
+ AL.getAttributeSpellingListIndex()));
+ return;
case ParsedAttr::AT_IntelOclBicc:
D->addAttr(::new (S.Context)
IntelOclBiccAttr(AL.getRange(), S.Context,
@@ -4299,6 +4438,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
case ParsedAttr::AT_VectorCall:
CC = CC_X86VectorCall;
break;
+ case ParsedAttr::AT_AArch64VectorPcs:
+ CC = CC_AArch64VectorCall;
+ break;
case ParsedAttr::AT_RegCall:
CC = CC_X86RegCall;
break;
@@ -4344,7 +4486,7 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
if (A != TargetInfo::CCCR_OK) {
if (A == TargetInfo::CCCR_Warning)
- Diag(Attrs.getLoc(), diag::warn_cconv_ignored) << Attrs.getName();
+ Diag(Attrs.getLoc(), diag::warn_cconv_ignored) << Attrs;
// This convention is not valid for the target. Use the default function or
// method calling convention.
@@ -4559,7 +4701,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
+ << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier;
return;
}
@@ -4579,8 +4721,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex();
if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) ||
!getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType())
- S.Diag(AL.getLoc(), diag::err_attribute_pointers_only)
- << AL.getName() << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0;
}
D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(
@@ -4592,7 +4733,7 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
if (!AL.isArgIdent(0)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL.getName() << 1 << AANT_ArgumentIdentifier;
+ << AL << 1 << AANT_ArgumentIdentifier;
return;
}
@@ -4601,7 +4742,7 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
if (!isa<VarDecl>(D)) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
- << AL.getName() << ExpectedVariable;
+ << AL << ExpectedVariable;
return;
}
@@ -4635,58 +4776,84 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
-
static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
return QT->isDependentType() || QT->isObjCRetainableType();
}
-static bool isValidSubjectOfNSAttribute(Sema &S, QualType QT) {
+static bool isValidSubjectOfNSAttribute(QualType QT) {
return QT->isDependentType() || QT->isObjCObjectPointerType() ||
- S.Context.isObjCNSObjectType(QT);
+ QT->isObjCNSObjectType();
}
-static bool isValidSubjectOfCFAttribute(Sema &S, QualType QT) {
+static bool isValidSubjectOfCFAttribute(QualType QT) {
return QT->isDependentType() || QT->isPointerType() ||
- isValidSubjectOfNSAttribute(S, QT);
+ isValidSubjectOfNSAttribute(QT);
}
-static void handleNSConsumedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- S.AddNSConsumedAttr(AL.getRange(), D, AL.getAttributeSpellingListIndex(),
- AL.getKind() == ParsedAttr::AT_NSConsumed,
- /*template instantiation*/ false);
+static bool isValidSubjectOfOSAttribute(QualType QT) {
+ if (QT->isDependentType())
+ return true;
+ QualType PT = QT->getPointeeType();
+ return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr;
}
-void Sema::AddNSConsumedAttr(SourceRange AttrRange, Decl *D,
- unsigned SpellingIndex, bool IsNSConsumed,
- bool IsTemplateInstantiation) {
- const auto *Param = cast<ParmVarDecl>(D);
- bool TypeOK;
-
- if (IsNSConsumed)
- TypeOK = isValidSubjectOfNSAttribute(*this, Param->getType());
- else
- TypeOK = isValidSubjectOfCFAttribute(*this, Param->getType());
+void Sema::AddXConsumedAttr(Decl *D, SourceRange SR, unsigned SpellingIndex,
+ RetainOwnershipKind K,
+ bool IsTemplateInstantiation) {
+ ValueDecl *VD = cast<ValueDecl>(D);
+ switch (K) {
+ case RetainOwnershipKind::OS:
+ handleSimpleAttributeOrDiagnose<OSConsumedAttr>(
+ *this, VD, SR, SpellingIndex, isValidSubjectOfOSAttribute(VD->getType()),
+ diag::warn_ns_attribute_wrong_parameter_type,
+ /*ExtraArgs=*/SR, "os_consumed", /*pointers*/ 1);
+ return;
+ case RetainOwnershipKind::NS:
+ handleSimpleAttributeOrDiagnose<NSConsumedAttr>(
+ *this, VD, SR, SpellingIndex, isValidSubjectOfNSAttribute(VD->getType()),
- if (!TypeOK) {
- // These attributes are normally just advisory, but in ARC, ns_consumed
- // is significant. Allow non-dependent code to contain inappropriate
- // attributes even in ARC, but require template instantiations to be
- // set up correctly.
- Diag(D->getLocStart(), (IsTemplateInstantiation && IsNSConsumed &&
- getLangOpts().ObjCAutoRefCount
- ? diag::err_ns_attribute_wrong_parameter_type
- : diag::warn_ns_attribute_wrong_parameter_type))
- << AttrRange << (IsNSConsumed ? "ns_consumed" : "cf_consumed")
- << (IsNSConsumed ? /*objc pointers*/ 0 : /*cf pointers*/ 1);
+ // These attributes are normally just advisory, but in ARC, ns_consumed
+ // is significant. Allow non-dependent code to contain inappropriate
+ // attributes even in ARC, but require template instantiations to be
+ // set up correctly.
+ ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount)
+ ? diag::err_ns_attribute_wrong_parameter_type
+ : diag::warn_ns_attribute_wrong_parameter_type),
+ /*ExtraArgs=*/SR, "ns_consumed", /*objc pointers*/ 0);
+ return;
+ case RetainOwnershipKind::CF:
+ handleSimpleAttributeOrDiagnose<CFConsumedAttr>(
+ *this, VD, SR, SpellingIndex,
+ isValidSubjectOfCFAttribute(VD->getType()),
+ diag::warn_ns_attribute_wrong_parameter_type,
+ /*ExtraArgs=*/SR, "cf_consumed", /*pointers*/1);
return;
}
+}
- if (IsNSConsumed)
- D->addAttr(::new (Context)
- NSConsumedAttr(AttrRange, Context, SpellingIndex));
- else
- D->addAttr(::new (Context)
- CFConsumedAttr(AttrRange, Context, SpellingIndex));
+static Sema::RetainOwnershipKind
+parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {
+ switch (AL.getKind()) {
+ case ParsedAttr::AT_CFConsumed:
+ case ParsedAttr::AT_CFReturnsRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
+ return Sema::RetainOwnershipKind::CF;
+ case ParsedAttr::AT_OSConsumesThis:
+ case ParsedAttr::AT_OSConsumed:
+ case ParsedAttr::AT_OSReturnsRetained:
+ case ParsedAttr::AT_OSReturnsNotRetained:
+ case ParsedAttr::AT_OSReturnsRetainedOnZero:
+ case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
+ return Sema::RetainOwnershipKind::OS;
+ case ParsedAttr::AT_NSConsumesSelf:
+ case ParsedAttr::AT_NSConsumed:
+ case ParsedAttr::AT_NSReturnsRetained:
+ case ParsedAttr::AT_NSReturnsNotRetained:
+ case ParsedAttr::AT_NSReturnsAutoreleased:
+ return Sema::RetainOwnershipKind::NS;
+ default:
+ llvm_unreachable("Wrong argument supplied");
+ }
}
bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) {
@@ -4698,25 +4865,40 @@ bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) {
return true;
}
-static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
+/// \return whether the parameter is a pointer to OSObject pointer.
+static bool isValidOSObjectOutParameter(const Decl *D) {
+ const auto *PVD = dyn_cast<ParmVarDecl>(D);
+ if (!PVD)
+ return false;
+ QualType QT = PVD->getType();
+ QualType PT = QT->getPointeeType();
+ return !PT.isNull() && isValidSubjectOfOSAttribute(PT);
+}
+
+static void handleXReturnsXRetainedAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
QualType ReturnType;
+ Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
ReturnType = MD->getReturnType();
- else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
- (AL.getKind() == ParsedAttr::AT_NSReturnsRetained))
+ } else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
+ (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) {
return; // ignore: was handled as a type attribute
- else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D))
+ } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
ReturnType = PD->getType();
- else if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
ReturnType = FD->getReturnType();
- else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
+ } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
+ // Attributes on parameters are used for out-parameters,
+ // passed as pointers-to-pointers.
+ unsigned DiagID = K == Sema::RetainOwnershipKind::CF
+ ? /*pointer-to-CF-pointer*/2
+ : /*pointer-to-OSObject-pointer*/3;
ReturnType = Param->getType()->getPointeeType();
if (ReturnType.isNull()) {
- S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
- << AL.getName() << /*pointer-to-CF*/2
- << AL.getRange();
+ S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
+ << AL << DiagID << AL.getRange();
return;
}
} else if (AL.isUsedAsTypeAttr()) {
@@ -4731,18 +4913,21 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
ExpectedDeclKind = ExpectedFunctionOrMethod;
break;
+ case ParsedAttr::AT_OSReturnsRetained:
+ case ParsedAttr::AT_OSReturnsNotRetained:
case ParsedAttr::AT_CFReturnsRetained:
case ParsedAttr::AT_CFReturnsNotRetained:
ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
break;
}
- S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << AL.getRange() << AL.getName() << ExpectedDeclKind;
+ S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getRange() << AL << ExpectedDeclKind;
return;
}
bool TypeOK;
bool Cf;
+ unsigned ParmDiagID = 2; // Pointer-to-CF-pointer
switch (AL.getKind()) {
default: llvm_unreachable("invalid ownership attribute");
case ParsedAttr::AT_NSReturnsRetained:
@@ -4752,14 +4937,21 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
case ParsedAttr::AT_NSReturnsAutoreleased:
case ParsedAttr::AT_NSReturnsNotRetained:
- TypeOK = isValidSubjectOfNSAttribute(S, ReturnType);
+ TypeOK = isValidSubjectOfNSAttribute(ReturnType);
Cf = false;
break;
case ParsedAttr::AT_CFReturnsRetained:
case ParsedAttr::AT_CFReturnsNotRetained:
- TypeOK = isValidSubjectOfCFAttribute(S, ReturnType);
+ TypeOK = isValidSubjectOfCFAttribute(ReturnType);
+ Cf = true;
+ break;
+
+ case ParsedAttr::AT_OSReturnsRetained:
+ case ParsedAttr::AT_OSReturnsNotRetained:
+ TypeOK = isValidSubjectOfOSAttribute(ReturnType);
Cf = true;
+ ParmDiagID = 3; // Pointer-to-OSObject-pointer
break;
}
@@ -4768,9 +4960,8 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
return;
if (isa<ParmVarDecl>(D)) {
- S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
- << AL.getName() << /*pointer-to-CF*/2
- << AL.getRange();
+ S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
+ << AL << ParmDiagID << AL.getRange();
} else {
// Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
enum : unsigned {
@@ -4782,9 +4973,8 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
SubjectKind = Method;
else if (isa<ObjCPropertyDecl>(D))
SubjectKind = Property;
- S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
- << AL.getName() << SubjectKind << Cf
- << AL.getRange();
+ S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
+ << AL << SubjectKind << Cf << AL.getRange();
}
return;
}
@@ -4793,24 +4983,25 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
default:
llvm_unreachable("invalid ownership attribute");
case ParsedAttr::AT_NSReturnsAutoreleased:
- D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
+ handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL);
return;
case ParsedAttr::AT_CFReturnsNotRetained:
- D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
+ handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL);
return;
case ParsedAttr::AT_NSReturnsNotRetained:
- D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
+ handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL);
return;
case ParsedAttr::AT_CFReturnsRetained:
- D->addAttr(::new (S.Context) CFReturnsRetainedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
+ handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL);
return;
case ParsedAttr::AT_NSReturnsRetained:
- D->addAttr(::new (S.Context) NSReturnsRetainedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
+ handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL);
+ return;
+ case ParsedAttr::AT_OSReturnsRetained:
+ handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL);
+ return;
+ case ParsedAttr::AT_OSReturnsNotRetained:
+ handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL);
return;
};
}
@@ -4829,11 +5020,10 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
if (!resultType->isReferenceType() &&
(!resultType->isPointerType() || resultType->isObjCRetainableType())) {
- S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
- << SourceRange(loc)
- << Attrs.getName()
- << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
- << /*non-retainable pointer*/ 2;
+ S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
+ << SourceRange(loc) << Attrs
+ << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
+ << /*non-retainable pointer*/ 2;
// Drop the attribute.
return;
@@ -4849,14 +5039,14 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
const DeclContext *DC = Method->getDeclContext();
if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
- S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
- << Attrs.getName() << 0;
+ S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
+ << 0;
S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
return;
}
if (Method->getMethodFamily() == OMF_dealloc) {
- S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
- << Attrs.getName() << 1;
+ S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
+ << 1;
return;
}
@@ -4868,15 +5058,14 @@ static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
if (!Parm) {
- S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
+ S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
return;
}
// Typedefs only allow objc_bridge(id) and have some additional checking.
if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
if (!Parm->Ident->isStr("id")) {
- S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id)
- << AL.getName();
+ S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL;
return;
}
@@ -4898,7 +5087,7 @@ static void handleObjCBridgeMutableAttr(Sema &S, Decl *D,
IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
if (!Parm) {
- S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
+ S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
return;
}
@@ -4912,7 +5101,7 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
IdentifierInfo *RelatedClass =
AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
if (!RelatedClass) {
- S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << AL.getName() << 0;
+ S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
return;
}
IdentifierInfo *ClassMethod =
@@ -4982,8 +5171,8 @@ static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (hasDeclarator(D)) return;
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << AL.getRange() << AL.getName() << ExpectedVariable;
+ S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
+ << AL.getRange() << AL << ExpectedVariable;
}
static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
@@ -5047,7 +5236,7 @@ UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range,
static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.LangOpts.CPlusPlus) {
S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
- << AL.getName() << AttributeLangSupport::C;
+ << AL << AttributeLangSupport::C;
return;
}
@@ -5097,7 +5286,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.LangOpts.CPlusPlus) {
S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
- << AL.getName() << AttributeLangSupport::C;
+ << AL << AttributeLangSupport::C;
return;
}
MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
@@ -5152,7 +5341,7 @@ static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
// Store tags sorted and without duplicates.
- llvm::sort(Tags.begin(), Tags.end());
+ llvm::sort(Tags);
Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
D->addAttr(::new (S.Context)
@@ -5163,8 +5352,7 @@ static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check the attribute arguments.
if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
return;
}
@@ -5178,8 +5366,8 @@ static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ARMInterruptAttr::InterruptType Kind;
if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL.getName() << Str << ArgLoc;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
+ << ArgLoc;
return;
}
@@ -5193,8 +5381,8 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
if (!AL.isArgExpr(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL.getName()
- << AANT_ArgumentIntegerConstant;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIntegerConstant;
return;
}
@@ -5204,16 +5392,16 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
llvm::APSInt NumParams(32);
if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL.getName() << AANT_ArgumentIntegerConstant
- << NumParamsExpr->getSourceRange();
+ << AL << AANT_ArgumentIntegerConstant
+ << NumParamsExpr->getSourceRange();
return;
}
unsigned Num = NumParams.getLimitedValue(255);
if ((Num & 1) || Num > 30) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL.getName() << (int)NumParams.getSExtValue()
- << NumParamsExpr->getSourceRange();
+ << AL << (int)NumParams.getSExtValue()
+ << NumParamsExpr->getSourceRange();
return;
}
@@ -5226,8 +5414,7 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Only one optional argument permitted.
if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
return;
}
@@ -5266,14 +5453,13 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
}
- if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL.getRange(),
- AL.getName()))
+ if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL))
return;
MipsInterruptAttr::InterruptType Kind;
if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL.getName() << "'" + std::string(Str) + "'";
+ << AL << "'" + std::string(Str) + "'";
return;
}
@@ -5292,7 +5478,7 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
CXXMethodDecl::isStaticOverloadedOperator(
cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunctionWithProtoType;
+ << AL << ExpectedFunctionWithProtoType;
return;
}
// Interrupt handler must have void return type.
@@ -5308,7 +5494,7 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Interrupt handler must have 1 or 2 parameters.
unsigned NumParams = getFunctionOrMethodNumParams(D);
if (NumParams < 1 || NumParams > 2) {
- S.Diag(D->getLocStart(), diag::err_anyx86_interrupt_attribute)
+ S.Diag(D->getBeginLoc(), diag::err_anyx86_interrupt_attribute)
<< (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
? 0
: 1)
@@ -5421,8 +5607,8 @@ static void handleRISCVInterruptAttr(Sema &S, Decl *D,
RISCVInterruptAttr::InterruptType Kind;
if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL.getName() << Str << ArgLoc;
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
+ << ArgLoc;
return;
}
@@ -5470,13 +5656,11 @@ static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
return;
if (Min == 0 && Max != 0) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
- << AL.getName() << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 0;
return;
}
if (Min > Max) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
return;
}
@@ -5499,13 +5683,11 @@ static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
if (Min == 0 && Max != 0) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
- << AL.getName() << 0;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 0;
return;
}
if (Max != 0 && Min > Max) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid)
- << AL.getName() << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;
return;
}
@@ -5552,7 +5734,7 @@ static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
// Attribute can only be applied to function types.
if (!isa<FunctionDecl>(D)) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunction;
+ << AL << ExpectedFunction;
return;
}
@@ -5568,12 +5750,17 @@ static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
// TODO: Investigate what happens with the next major version of MSVC.
- if (Version != LangOptions::MSVC2015) {
+ if (Version != LangOptions::MSVC2015 / 100) {
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL.getName() << Version << VersionExpr->getSourceRange();
+ << AL << Version << VersionExpr->getSourceRange();
return;
}
+ // The attribute expects a "major" version number like 19, but new versions of
+ // MSVC have moved to updating the "minor", or less significant numbers, so we
+ // have to multiply by 100 now.
+ Version *= 100;
+
D->addAttr(::new (S.Context)
LayoutVersionAttr(AL.getRange(), S.Context, Version,
AL.getAttributeSpellingListIndex()));
@@ -5608,8 +5795,7 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored)
- << A.getName();
+ S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A;
return;
}
@@ -5618,7 +5804,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// MinGW doesn't allow dllimport on inline functions.
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
- << A.getName();
+ << A;
return;
}
}
@@ -5626,7 +5812,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
MD->getParent()->isLambda()) {
- S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A.getName();
+ S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A;
return;
}
}
@@ -5788,10 +5974,8 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
!S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
return;
- if (!S.getLangOpts().CPlusPlus14)
- if (AL.isCXX11Attribute() &&
- !(AL.hasScope() && AL.getScopeName()->isStr("gnu")))
- S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL.getName();
+ if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope())
+ S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;
D->addAttr(::new (S.Context)
DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,
@@ -5821,7 +6005,7 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
else if (isGlobalVar(D) && SanitizerName != "address")
S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunctionOrMethod;
+ << AL << ExpectedFunctionOrMethod;
Sanitizers.push_back(SanitizerName);
}
@@ -5841,26 +6025,24 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
.Case("no_sanitize_memory", "memory");
if (isGlobalVar(D) && SanitizerName != "address")
S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunction;
+ << AL << ExpectedFunction;
D->addAttr(::new (S.Context)
NoSanitizeAttr(AL.getRange(), S.Context, &SanitizerName, 1,
AL.getAttributeSpellingListIndex()));
}
static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (InternalLinkageAttr *Internal =
- S.mergeInternalLinkageAttr(D, AL.getRange(), AL.getName(),
- AL.getAttributeSpellingListIndex()))
+ if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL))
D->addAttr(Internal);
}
static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (S.LangOpts.OpenCLVersion != 200)
S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
- << AL.getName() << "2.0" << 0;
+ << AL << "2.0" << 0;
else
- S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
- << AL.getName() << "2.0";
+ S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) << AL
+ << "2.0";
}
/// Handles semantic checking for features that are common to all attributes,
@@ -5912,10 +6094,16 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Check if there is only one access qualifier.
if (D->hasAttr<OpenCLAccessAttr>()) {
- S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
- << D->getSourceRange();
- D->setInvalidDecl(true);
- return;
+ if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
+ AL.getSemanticSpelling()) {
+ S.Diag(AL.getLoc(), diag::warn_duplicate_declspec)
+ << AL.getName()->getName() << AL.getRange();
+ } else {
+ S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
+ << D->getSourceRange();
+ D->setInvalidDecl(true);
+ return;
+ }
}
// OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an
@@ -5928,7 +6116,7 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (AL.getName()->getName().find("read_write") != StringRef::npos) {
if (S.getLangOpts().OpenCLVersion < 200 || DeclTy->isPipeType()) {
S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
- << AL.getName() << PDecl->getType() << DeclTy->isImageType();
+ << AL << PDecl->getType() << DeclTy->isImageType();
D->setInvalidDecl(true);
return;
}
@@ -5939,6 +6127,100 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
}
+static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) {
+ if (!cast<VarDecl>(D)->hasGlobalStorage()) {
+ S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var)
+ << (A.getKind() == ParsedAttr::AT_AlwaysDestroy);
+ return;
+ }
+
+ if (A.getKind() == ParsedAttr::AT_AlwaysDestroy)
+ handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D, A);
+ else
+ handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D, A);
+}
+
+static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic &&
+ "uninitialized is only valid on automatic duration variables");
+ unsigned Index = AL.getAttributeSpellingListIndex();
+ D->addAttr(::new (S.Context)
+ UninitializedAttr(AL.getLoc(), S.Context, Index));
+}
+
+static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,
+ bool DiagnoseFailure) {
+ QualType Ty = VD->getType();
+ if (!Ty->isObjCRetainableType()) {
+ if (DiagnoseFailure) {
+ S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
+ << 0;
+ }
+ return false;
+ }
+
+ Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime();
+
+ // Sema::inferObjCARCLifetime must run after processing decl attributes
+ // (because __block lowers to an attribute), so if the lifetime hasn't been
+ // explicitly specified, infer it locally now.
+ if (LifetimeQual == Qualifiers::OCL_None)
+ LifetimeQual = Ty->getObjCARCImplicitLifetime();
+
+ // The attributes only really makes sense for __strong variables; ignore any
+ // attempts to annotate a parameter with any other lifetime qualifier.
+ if (LifetimeQual != Qualifiers::OCL_Strong) {
+ if (DiagnoseFailure) {
+ S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
+ << 1;
+ }
+ return false;
+ }
+
+ // Tampering with the type of a VarDecl here is a bit of a hack, but we need
+ // to ensure that the variable is 'const' so that we can error on
+ // modification, which can otherwise over-release.
+ VD->setType(Ty.withConst());
+ VD->setARCPseudoStrong(true);
+ return true;
+}
+
+static void handleObjCExternallyRetainedAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically");
+ if (!VD->hasLocalStorage()) {
+ S.Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
+ << 0;
+ return;
+ }
+
+ if (!tryMakeVariablePseudoStrong(S, VD, /*DiagnoseFailure=*/true))
+ return;
+
+ handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
+ return;
+ }
+
+ // If D is a function-like declaration (method, block, or function), then we
+ // make every parameter psuedo-strong.
+ for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
+ auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I));
+ QualType Ty = PVD->getType();
+
+ // If a user wrote a parameter with __strong explicitly, then assume they
+ // want "real" strong semantics for that parameter. This works because if
+ // the parameter was written with __strong, then the strong qualifier will
+ // be non-local.
+ if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==
+ Qualifiers::OCL_Strong)
+ continue;
+
+ tryMakeVariablePseudoStrong(S, PVD, /*DiagnoseFailure=*/false);
+ }
+ handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
+}
+
//===----------------------------------------------------------------------===//
// Top Level Sema Entry Points
//===----------------------------------------------------------------------===//
@@ -5962,10 +6244,11 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
// though they were unknown attributes.
if (AL.getKind() == ParsedAttr::UnknownAttribute ||
!AL.existsInTarget(S.Context.getTargetInfo())) {
- S.Diag(AL.getLoc(), AL.isDeclspecAttribute()
- ? diag::warn_unhandled_ms_attribute_ignored
- : diag::warn_unknown_attribute_ignored)
- << AL.getName();
+ S.Diag(AL.getLoc(),
+ AL.isDeclspecAttribute()
+ ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
+ : (unsigned)diag::warn_unknown_attribute_ignored)
+ << AL;
return;
}
@@ -5980,7 +6263,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
break;
}
S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
- << AL.getName() << D->getLocation();
+ << AL << D->getLocation();
break;
case ParsedAttr::AT_Interrupt:
handleInterruptAttr(S, D, AL);
@@ -6259,17 +6542,37 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
break;
case ParsedAttr::AT_CFConsumed:
case ParsedAttr::AT_NSConsumed:
- handleNSConsumedAttr(S, D, AL);
+ case ParsedAttr::AT_OSConsumed:
+ S.AddXConsumedAttr(D, AL.getRange(), AL.getAttributeSpellingListIndex(),
+ parsedAttrToRetainOwnershipKind(AL),
+ /*IsTemplateInstantiation=*/false);
break;
case ParsedAttr::AT_NSConsumesSelf:
handleSimpleAttribute<NSConsumesSelfAttr>(S, D, AL);
break;
+ case ParsedAttr::AT_OSConsumesThis:
+ handleSimpleAttribute<OSConsumesThisAttr>(S, D, AL);
+ break;
+ case ParsedAttr::AT_OSReturnsRetainedOnZero:
+ handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>(
+ S, D, AL, isValidOSObjectOutParameter(D),
+ diag::warn_ns_attribute_wrong_parameter_type,
+ /*Extra Args=*/AL, /*pointer-to-OSObject-pointer*/ 3, AL.getRange());
+ break;
+ case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
+ handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnNonZeroAttr>(
+ S, D, AL, isValidOSObjectOutParameter(D),
+ diag::warn_ns_attribute_wrong_parameter_type,
+ /*Extra Args=*/AL, /*pointer-to-OSObject-poointer*/ 3, AL.getRange());
+ break;
case ParsedAttr::AT_NSReturnsAutoreleased:
case ParsedAttr::AT_NSReturnsNotRetained:
- case ParsedAttr::AT_CFReturnsNotRetained:
case ParsedAttr::AT_NSReturnsRetained:
+ case ParsedAttr::AT_CFReturnsNotRetained:
case ParsedAttr::AT_CFReturnsRetained:
- handleNSReturnsRetainedAttr(S, D, AL);
+ case ParsedAttr::AT_OSReturnsNotRetained:
+ case ParsedAttr::AT_OSReturnsRetained:
+ handleXReturnsXRetainedAttr(S, D, AL);
break;
case ParsedAttr::AT_WorkGroupSizeHint:
handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL);
@@ -6295,6 +6598,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Section:
handleSectionAttr(S, D, AL);
break;
+ case ParsedAttr::AT_SpeculativeLoadHardening:
+ handleSimpleAttribute<SpeculativeLoadHardeningAttr>(S, D, AL);
+ break;
case ParsedAttr::AT_CodeSeg:
handleCodeSegAttr(S, D, AL);
break;
@@ -6423,6 +6729,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_IntelOclBicc:
case ParsedAttr::AT_PreserveMost:
case ParsedAttr::AT_PreserveAll:
+ case ParsedAttr::AT_AArch64VectorPcs:
handleCallConvAttr(S, D, AL);
break;
case ParsedAttr::AT_Suppress:
@@ -6449,6 +6756,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_InternalLinkage:
handleInternalLinkageAttr(S, D, AL);
break;
+ case ParsedAttr::AT_ExcludeFromExplicitInstantiation:
+ handleSimpleAttribute<ExcludeFromExplicitInstantiationAttr>(S, D, AL);
+ break;
case ParsedAttr::AT_LTOVisibilityPublic:
handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL);
break;
@@ -6604,6 +6914,24 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_XRayLogArgs:
handleXRayLogArgsAttr(S, D, AL);
break;
+
+ // Move semantics attribute.
+ case ParsedAttr::AT_Reinitializes:
+ handleSimpleAttribute<ReinitializesAttr>(S, D, AL);
+ break;
+
+ case ParsedAttr::AT_AlwaysDestroy:
+ case ParsedAttr::AT_NoDestroy:
+ handleDestroyAttr(S, D, AL);
+ break;
+
+ case ParsedAttr::AT_Uninitialized:
+ handleUninitializedAttr(S, D, AL);
+ break;
+
+ case ParsedAttr::AT_ObjCExternallyRetained:
+ handleObjCExternallyRetainedAttr(S, D, AL);
+ break;
}
}
@@ -6708,10 +7036,10 @@ static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) {
if (AL.getKind() == ParsedAttr::UnknownAttribute) {
S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
- << AL.getName() << AL.getRange();
+ << AL << AL.getRange();
} else {
- S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl)
- << AL.getName() << AL.getRange();
+ S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL
+ << AL.getRange();
}
}
}
@@ -6942,8 +7270,12 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
/// \param D The declaration to check.
/// \param Message If non-null, this will be populated with the message from
/// the availability attribute that is selected.
+/// \param ClassReceiver If we're checking the the method of a class message
+/// send, the class. Otherwise nullptr.
static std::pair<AvailabilityResult, const NamedDecl *>
-ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
+ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D,
+ std::string *Message,
+ ObjCInterfaceDecl *ClassReceiver) {
AvailabilityResult Result = D->getAvailability(Message);
// For typedefs, if the typedef declaration appears available look
@@ -6976,6 +7308,20 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
}
}
+ // For +new, infer availability from -init.
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (S.NSAPIObj && ClassReceiver) {
+ ObjCMethodDecl *Init = ClassReceiver->lookupInstanceMethod(
+ S.NSAPIObj->getInitSelector());
+ if (Init && Result == AR_Available && MD->isClassMethod() &&
+ MD->getSelector() == S.NSAPIObj->getNewSelector() &&
+ MD->definedInNSObject(S.getASTContext())) {
+ Result = Init->getAvailability(Message);
+ D = Init;
+ }
+ }
+ }
+
return {Result, D};
}
@@ -6983,9 +7329,10 @@ ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) {
/// whether we should emit a diagnostic for \c K and \c DeclVersion in
/// the context of \c Ctx. For example, we should emit an unavailable diagnostic
/// in a deprecated context, but not the other way around.
-static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
- VersionTuple DeclVersion,
- Decl *Ctx) {
+static bool
+ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
+ VersionTuple DeclVersion, Decl *Ctx,
+ const NamedDecl *OffendingDecl) {
assert(K != AR_Available && "Expected an unavailable declaration here!");
// Checks if we should emit the availability diagnostic in the context of C.
@@ -6994,9 +7341,22 @@ static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C))
if (AA->getIntroduced() >= DeclVersion)
return true;
- } else if (K == AR_Deprecated)
+ } else if (K == AR_Deprecated) {
if (C->isDeprecated())
return true;
+ } else if (K == AR_Unavailable) {
+ // It is perfectly fine to refer to an 'unavailable' Objective-C method
+ // when it's actually defined and is referenced from within the
+ // @implementation itself. In this context, we interpret unavailable as a
+ // form of access control.
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(OffendingDecl)) {
+ if (const auto *Impl = dyn_cast<ObjCImplDecl>(C)) {
+ if (MD->getClassInterface() == Impl->getClassInterface() &&
+ MD->isDefined())
+ return true;
+ }
+ }
+ }
if (C->isUnavailable())
return true;
@@ -7078,13 +7438,13 @@ struct AttributeInsertion {
StringRef Suffix;
static AttributeInsertion createInsertionAfter(const NamedDecl *D) {
- return {" ", D->getLocEnd(), ""};
+ return {" ", D->getEndLoc(), ""};
}
static AttributeInsertion createInsertionAfter(SourceLocation Loc) {
return {" ", Loc, ""};
}
static AttributeInsertion createInsertionBefore(const NamedDecl *D) {
- return {"", D->getLocStart(), "\n"};
+ return {"", D->getBeginLoc(), "\n"};
}
};
@@ -7185,7 +7545,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl))
DeclVersion = AA->getIntroduced();
- if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
+ if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx,
+ OffendingDecl))
return;
SourceLocation Loc = Locs.front();
@@ -7223,14 +7584,16 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new
: diag::warn_unguarded_availability;
- S.Diag(Loc, Warning)
- << OffendingDecl
- << AvailabilityAttr::getPrettyPlatformName(
- S.getASTContext().getTargetInfo().getPlatformName())
- << Introduced.getAsString();
+ std::string PlatformName = AvailabilityAttr::getPrettyPlatformName(
+ S.getASTContext().getTargetInfo().getPlatformName());
- S.Diag(OffendingDecl->getLocation(), diag::note_availability_specified_here)
- << OffendingDecl << /* partial */ 3;
+ S.Diag(Loc, Warning) << OffendingDecl << PlatformName
+ << Introduced.getAsString();
+
+ S.Diag(OffendingDecl->getLocation(),
+ diag::note_partial_availability_specified_here)
+ << OffendingDecl << PlatformName << Introduced.getAsString()
+ << S.Context.getTargetInfo().getPlatformMinVersion().getAsString();
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
@@ -7423,6 +7786,7 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
// for each of the different declarations.
const DelayedDiagnosticPool *pool = &poppedPool;
do {
+ bool AnyAccessFailures = false;
for (DelayedDiagnosticPool::pool_iterator
i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
// This const_cast is a bit lame. Really, Triggered should be mutable.
@@ -7439,7 +7803,14 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
break;
case DelayedDiagnostic::Access:
+ // Only produce one access control diagnostic for a structured binding
+ // declaration: we don't need to tell the user that all the fields are
+ // inaccessible one at a time.
+ if (AnyAccessFailures && isa<DecompositionDecl>(decl))
+ continue;
HandleDelayedAccessCheck(diag, decl);
+ if (diag.Triggered)
+ AnyAccessFailures = true;
break;
case DelayedDiagnostic::ForbiddenType:
@@ -7564,7 +7935,8 @@ class DiagnoseUnguardedAvailability
SmallVector<VersionTuple, 8> AvailabilityStack;
SmallVector<const Stmt *, 16> StmtStack;
- void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range);
+ void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range,
+ ObjCInterfaceDecl *ClassReceiver = nullptr);
public:
DiagnoseUnguardedAvailability(Sema &SemaRef, Decl *Ctx)
@@ -7606,27 +7978,33 @@ public:
}
bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {
- if (ObjCMethodDecl *D = Msg->getMethodDecl())
+ if (ObjCMethodDecl *D = Msg->getMethodDecl()) {
+ ObjCInterfaceDecl *ID = nullptr;
+ QualType ReceiverTy = Msg->getClassReceiver();
+ if (!ReceiverTy.isNull() && ReceiverTy->getAsObjCInterfaceType())
+ ID = ReceiverTy->getAsObjCInterfaceType()->getInterface();
+
DiagnoseDeclAvailability(
- D, SourceRange(Msg->getSelectorStartLoc(), Msg->getLocEnd()));
+ D, SourceRange(Msg->getSelectorStartLoc(), Msg->getEndLoc()), ID);
+ }
return true;
}
bool VisitDeclRefExpr(DeclRefExpr *DRE) {
DiagnoseDeclAvailability(DRE->getDecl(),
- SourceRange(DRE->getLocStart(), DRE->getLocEnd()));
+ SourceRange(DRE->getBeginLoc(), DRE->getEndLoc()));
return true;
}
bool VisitMemberExpr(MemberExpr *ME) {
DiagnoseDeclAvailability(ME->getMemberDecl(),
- SourceRange(ME->getLocStart(), ME->getLocEnd()));
+ SourceRange(ME->getBeginLoc(), ME->getEndLoc()));
return true;
}
bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) {
- SemaRef.Diag(E->getLocStart(), diag::warn_at_available_unchecked_use)
- << (!SemaRef.getLangOpts().ObjC1);
+ SemaRef.Diag(E->getBeginLoc(), diag::warn_at_available_unchecked_use)
+ << (!SemaRef.getLangOpts().ObjC);
return true;
}
@@ -7634,11 +8012,11 @@ public:
};
void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
- NamedDecl *D, SourceRange Range) {
+ NamedDecl *D, SourceRange Range, ObjCInterfaceDecl *ReceiverClass) {
AvailabilityResult Result;
const NamedDecl *OffendingDecl;
std::tie(Result, OffendingDecl) =
- ShouldDiagnoseAvailabilityOfDecl(D, nullptr);
+ ShouldDiagnoseAvailabilityOfDecl(SemaRef, D, nullptr, ReceiverClass);
if (Result != AR_Available) {
// All other diagnostic kinds have already been handled in
// DiagnoseAvailabilityOfDecl.
@@ -7654,7 +8032,8 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
// If the context of this function is less available than D, we should not
// emit a diagnostic.
- if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx))
+ if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx,
+ OffendingDecl))
return;
// We would like to emit the diagnostic even if -Wunguarded-availability is
@@ -7668,21 +8047,24 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
? diag::warn_unguarded_availability_new
: diag::warn_unguarded_availability;
+ std::string PlatformName = AvailabilityAttr::getPrettyPlatformName(
+ SemaRef.getASTContext().getTargetInfo().getPlatformName());
+
SemaRef.Diag(Range.getBegin(), DiagKind)
- << Range << D
- << AvailabilityAttr::getPrettyPlatformName(
- SemaRef.getASTContext().getTargetInfo().getPlatformName())
- << Introduced.getAsString();
+ << Range << D << PlatformName << Introduced.getAsString();
SemaRef.Diag(OffendingDecl->getLocation(),
- diag::note_availability_specified_here)
- << OffendingDecl << /* partial */ 3;
+ diag::note_partial_availability_specified_here)
+ << OffendingDecl << PlatformName << Introduced.getAsString()
+ << SemaRef.Context.getTargetInfo()
+ .getPlatformMinVersion()
+ .getAsString();
auto FixitDiag =
SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
<< Range << D
- << (SemaRef.getLangOpts().ObjC1 ? /*@available*/ 0
- : /*__builtin_available*/ 1);
+ << (SemaRef.getLangOpts().ObjC ? /*@available*/ 0
+ : /*__builtin_available*/ 1);
// Find the statement which should be enclosed in the if @available check.
if (StmtStack.empty())
@@ -7714,10 +8096,10 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
const SourceManager &SM = SemaRef.getSourceManager();
SourceLocation IfInsertionLoc =
- SM.getExpansionLoc(StmtOfUse->getLocStart());
+ SM.getExpansionLoc(StmtOfUse->getBeginLoc());
SourceLocation StmtEndLoc =
SM.getExpansionRange(
- (LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getLocEnd())
+ (LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getEndLoc())
.getEnd();
if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc))
return;
@@ -7726,8 +8108,8 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
const char *ExtraIndentation = " ";
std::string FixItString;
llvm::raw_string_ostream FixItOS(FixItString);
- FixItOS << "if (" << (SemaRef.getLangOpts().ObjC1 ? "@available"
- : "__builtin_available")
+ FixItOS << "if (" << (SemaRef.getLangOpts().ObjC ? "@available"
+ : "__builtin_available")
<< "("
<< AvailabilityAttr::getPlatformNameSourceSpelling(
SemaRef.getASTContext().getTargetInfo().getPlatformName())
@@ -7820,12 +8202,14 @@ void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D,
ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
- bool AvoidPartialAvailabilityChecks) {
+ bool AvoidPartialAvailabilityChecks,
+ ObjCInterfaceDecl *ClassReceiver) {
std::string Message;
AvailabilityResult Result;
const NamedDecl* OffendingDecl;
// See if this declaration is unavailable, deprecated, or partial.
- std::tie(Result, OffendingDecl) = ShouldDiagnoseAvailabilityOfDecl(D, &Message);
+ std::tie(Result, OffendingDecl) =
+ ShouldDiagnoseAvailabilityOfDecl(*this, D, &Message, ClassReceiver);
if (Result == AR_Available)
return;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 4cf3abdf5745..43b289d8d0de 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -94,17 +94,17 @@ namespace {
// evaluated. Parameters of a function declared before a default
// argument expression are in scope and can hide namespace and
// class member names.
- return S->Diag(DRE->getLocStart(),
+ return S->Diag(DRE->getBeginLoc(),
diag::err_param_default_argument_references_param)
- << Param->getDeclName() << DefaultArg->getSourceRange();
+ << Param->getDeclName() << DefaultArg->getSourceRange();
} else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
// C++ [dcl.fct.default]p7
// Local variables shall not be used in default argument
// expressions.
if (VDecl->isLocalVarDecl())
- return S->Diag(DRE->getLocStart(),
+ return S->Diag(DRE->getBeginLoc(),
diag::err_param_default_argument_references_local)
- << VDecl->getDeclName() << DefaultArg->getSourceRange();
+ << VDecl->getDeclName() << DefaultArg->getSourceRange();
}
return false;
@@ -115,9 +115,9 @@ namespace {
// C++ [dcl.fct.default]p8:
// The keyword this shall not be used in a default argument of a
// member function.
- return S->Diag(ThisE->getLocStart(),
+ return S->Diag(ThisE->getBeginLoc(),
diag::err_param_default_argument_references_this)
- << ThisE->getSourceRange();
+ << ThisE->getSourceRange();
}
bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
@@ -144,8 +144,7 @@ namespace {
if (Lambda->capture_begin() == Lambda->capture_end())
return false;
- return S->Diag(Lambda->getLocStart(),
- diag::err_lambda_capture_default_arg);
+ return S->Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg);
}
}
@@ -1108,7 +1107,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
// [dcl.decomp]p3:
// The unqualified-id get is looked up in the scope of E by class member
- // access lookup
+ // access lookup ...
LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName);
bool UseMemberGet = false;
if (S.isCompleteType(Src->getLocation(), DecompType)) {
@@ -1116,7 +1115,20 @@ static bool checkTupleLikeDecomposition(Sema &S,
S.LookupQualifiedName(MemberGet, RD);
if (MemberGet.isAmbiguous())
return true;
- UseMemberGet = !MemberGet.empty();
+ // ... and if that finds at least one declaration that is a function
+ // template whose first template parameter is a non-type parameter ...
+ for (NamedDecl *D : MemberGet) {
+ if (FunctionTemplateDecl *FTD =
+ dyn_cast<FunctionTemplateDecl>(D->getUnderlyingDecl())) {
+ TemplateParameterList *TPL = FTD->getTemplateParameters();
+ if (TPL->size() != 0 &&
+ isa<NonTypeTemplateParmDecl>(TPL->getParam(0))) {
+ // ... the initializer is e.get<i>().
+ UseMemberGet = true;
+ break;
+ }
+ }
+ }
S.FilterAcceptableTemplateNames(MemberGet);
}
@@ -1193,7 +1205,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
E = Seq.Perform(S, Entity, Kind, Init);
if (E.isInvalid())
return true;
- E = S.ActOnFinishFullExpr(E.get(), Loc);
+ E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false);
if (E.isInvalid())
return true;
RefVD->setInit(E.get());
@@ -1215,16 +1227,16 @@ static bool checkTupleLikeDecomposition(Sema &S,
/// Find the base class to decompose in a built-in decomposition of a class type.
/// This base class search is, unfortunately, not quite like any other that we
/// perform anywhere else in C++.
-static const CXXRecordDecl *findDecomposableBaseClass(Sema &S,
- SourceLocation Loc,
- const CXXRecordDecl *RD,
- CXXCastPath &BasePath) {
+static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc,
+ const CXXRecordDecl *RD,
+ CXXCastPath &BasePath) {
auto BaseHasFields = [](const CXXBaseSpecifier *Specifier,
CXXBasePath &Path) {
return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields();
};
const CXXRecordDecl *ClassWithFields = nullptr;
+ AccessSpecifier AS = AS_public;
if (RD->hasDirectFields())
// [dcl.decomp]p4:
// Otherwise, all of E's non-static data members shall be public direct
@@ -1237,7 +1249,7 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S,
if (!RD->lookupInBases(BaseHasFields, Paths)) {
// If no classes have fields, just decompose RD itself. (This will work
// if and only if zero bindings were provided.)
- return RD;
+ return DeclAccessPair::make(const_cast<CXXRecordDecl*>(RD), AS_public);
}
CXXBasePath *BestPath = nullptr;
@@ -1250,7 +1262,7 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S,
S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
<< false << RD << BestPath->back().Base->getType()
<< P.back().Base->getType();
- return nullptr;
+ return DeclAccessPair();
} else if (P.Access < BestPath->Access) {
BestPath = &P;
}
@@ -1261,23 +1273,13 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S,
if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) {
S.Diag(Loc, diag::err_decomp_decl_ambiguous_base)
<< RD << BaseType << S.getAmbiguousPathsDisplayString(Paths);
- return nullptr;
+ return DeclAccessPair();
}
- // ... public base class of E.
- if (BestPath->Access != AS_public) {
- S.Diag(Loc, diag::err_decomp_decl_non_public_base)
- << RD << BaseType;
- for (auto &BS : *BestPath) {
- if (BS.Base->getAccessSpecifier() != AS_public) {
- S.Diag(BS.Base->getLocStart(), diag::note_access_constrained_by_path)
- << (BS.Base->getAccessSpecifier() == AS_protected)
- << (BS.Base->getAccessSpecifierAsWritten() == AS_none);
- break;
- }
- }
- return nullptr;
- }
+ // ... [accessible, implied by other rules] base class of E.
+ S.CheckBaseClassAccess(Loc, BaseType, S.Context.getRecordType(RD),
+ *BestPath, diag::err_decomp_decl_inaccessible_base);
+ AS = BestPath->Access;
ClassWithFields = BaseType->getAsCXXRecordDecl();
S.BuildBasePathArray(Paths, BasePath);
@@ -1290,17 +1292,19 @@ static const CXXRecordDecl *findDecomposableBaseClass(Sema &S,
S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
<< (ClassWithFields == RD) << RD << ClassWithFields
<< Paths.front().back().Base->getType();
- return nullptr;
+ return DeclAccessPair();
}
- return ClassWithFields;
+ return DeclAccessPair::make(const_cast<CXXRecordDecl*>(ClassWithFields), AS);
}
static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
ValueDecl *Src, QualType DecompType,
- const CXXRecordDecl *RD) {
+ const CXXRecordDecl *OrigRD) {
CXXCastPath BasePath;
- RD = findDecomposableBaseClass(S, Src->getLocation(), RD, BasePath);
+ DeclAccessPair BasePair =
+ findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);
+ const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
if (!RD)
return true;
QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD),
@@ -1317,7 +1321,8 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
return true;
};
- // all of E's non-static data members shall be public [...] members,
+ // all of E's non-static data members shall be [...] well-formed
+ // when named as e.name in the context of the structured binding,
// E shall not have an anonymous union member, ...
unsigned I = 0;
for (auto *FD : RD->fields()) {
@@ -1335,26 +1340,16 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
if (I >= Bindings.size())
return DiagnoseBadNumberOfBindings();
auto *B = Bindings[I++];
-
SourceLocation Loc = B->getLocation();
- if (FD->getAccess() != AS_public) {
- S.Diag(Loc, diag::err_decomp_decl_non_public_member) << FD << DecompType;
- // Determine whether the access specifier was explicit.
- bool Implicit = true;
- for (const auto *D : RD->decls()) {
- if (declaresSameEntity(D, FD))
- break;
- if (isa<AccessSpecDecl>(D)) {
- Implicit = false;
- break;
- }
- }
-
- S.Diag(FD->getLocation(), diag::note_access_natural)
- << (FD->getAccess() == AS_protected) << Implicit;
- return true;
- }
+ // The field must be accessible in the context of the structured binding.
+ // We already checked that the base class is accessible.
+ // FIXME: Add 'const' to AccessedEntity's classes so we can remove the
+ // const_cast here.
+ S.CheckStructuredBindingMemberAccess(
+ Loc, const_cast<CXXRecordDecl *>(OrigRD),
+ DeclAccessPair::make(FD, CXXRecordDecl::MergeAccess(
+ BasePair.getAccess(), FD->getAccess())));
// Initialize the binding to Src.FD.
ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
@@ -1606,8 +1601,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
<< isa<CXXConstructorDecl>(NewFD)
<< getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
for (const auto &I : RD->vbases())
- Diag(I.getLocStart(),
- diag::note_constexpr_virtual_base_here) << I.getSourceRange();
+ Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here)
+ << I.getSourceRange();
return false;
}
}
@@ -1691,11 +1686,11 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
case Decl::CXXRecord:
// C++1y allows types to be defined, not just declared.
if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition())
- SemaRef.Diag(DS->getLocStart(),
+ SemaRef.Diag(DS->getBeginLoc(),
SemaRef.getLangOpts().CPlusPlus14
- ? diag::warn_cxx11_compat_constexpr_type_definition
- : diag::ext_constexpr_type_definition)
- << isa<CXXConstructorDecl>(Dcl);
+ ? diag::warn_cxx11_compat_constexpr_type_definition
+ : diag::ext_constexpr_type_definition)
+ << isa<CXXConstructorDecl>(Dcl);
continue;
case Decl::EnumConstant:
@@ -1746,12 +1741,12 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
// These are disallowed in C++11 and permitted in C++1y. Allow them
// everywhere as an extension.
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = DS->getLocStart();
+ Cxx1yLoc = DS->getBeginLoc();
continue;
default:
- SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_body_invalid_stmt)
- << isa<CXXConstructorDecl>(Dcl);
+ SemaRef.Diag(DS->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
+ << isa<CXXConstructorDecl>(Dcl);
return false;
}
}
@@ -1808,7 +1803,7 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
static bool
CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
SmallVectorImpl<SourceLocation> &ReturnStmts,
- SourceLocation &Cxx1yLoc) {
+ SourceLocation &Cxx1yLoc, SourceLocation &Cxx2aLoc) {
// - its function-body shall be [...] a compound-statement that contains only
switch (S->getStmtClass()) {
case Stmt::NullStmtClass:
@@ -1830,22 +1825,22 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
if (isa<CXXConstructorDecl>(Dcl)) {
// C++1y allows return statements in constexpr constructors.
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = S->getLocStart();
+ Cxx1yLoc = S->getBeginLoc();
return true;
}
- ReturnStmts.push_back(S->getLocStart());
+ ReturnStmts.push_back(S->getBeginLoc());
return true;
case Stmt::CompoundStmtClass: {
// C++1y allows compound-statements.
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = S->getLocStart();
+ Cxx1yLoc = S->getBeginLoc();
CompoundStmt *CompStmt = cast<CompoundStmt>(S);
for (auto *BodyIt : CompStmt->body()) {
if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts,
- Cxx1yLoc))
+ Cxx1yLoc, Cxx2aLoc))
return false;
}
return true;
@@ -1853,21 +1848,21 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
case Stmt::AttributedStmtClass:
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = S->getLocStart();
+ Cxx1yLoc = S->getBeginLoc();
return true;
case Stmt::IfStmtClass: {
// C++1y allows if-statements.
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = S->getLocStart();
+ Cxx1yLoc = S->getBeginLoc();
IfStmt *If = cast<IfStmt>(S);
if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts,
- Cxx1yLoc))
+ Cxx1yLoc, Cxx2aLoc))
return false;
if (If->getElse() &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts,
- Cxx1yLoc))
+ Cxx1yLoc, Cxx2aLoc))
return false;
return true;
}
@@ -1882,11 +1877,11 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
if (!SemaRef.getLangOpts().CPlusPlus14)
break;
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = S->getLocStart();
+ Cxx1yLoc = S->getBeginLoc();
for (Stmt *SubStmt : S->children())
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
- Cxx1yLoc))
+ Cxx1yLoc, Cxx2aLoc))
return false;
return true;
@@ -1897,12 +1892,32 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
// C++1y allows switch-statements, and since they don't need variable
// mutation, we can reasonably allow them in C++11 as an extension.
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = S->getLocStart();
+ Cxx1yLoc = S->getBeginLoc();
for (Stmt *SubStmt : S->children())
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
- Cxx1yLoc))
+ Cxx1yLoc, Cxx2aLoc))
+ return false;
+ return true;
+
+ case Stmt::CXXTryStmtClass:
+ if (Cxx2aLoc.isInvalid())
+ Cxx2aLoc = S->getBeginLoc();
+ for (Stmt *SubStmt : S->children()) {
+ if (SubStmt &&
+ !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
+ Cxx1yLoc, Cxx2aLoc))
return false;
+ }
+ return true;
+
+ case Stmt::CXXCatchStmtClass:
+ // Do not bother checking the language mode (already covered by the
+ // try block check).
+ if (!CheckConstexprFunctionStmt(SemaRef, Dcl,
+ cast<CXXCatchStmt>(S)->getHandlerBlock(),
+ ReturnStmts, Cxx1yLoc, Cxx2aLoc))
+ return false;
return true;
default:
@@ -1911,12 +1926,12 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
// C++1y allows expression-statements.
if (!Cxx1yLoc.isValid())
- Cxx1yLoc = S->getLocStart();
+ Cxx1yLoc = S->getBeginLoc();
return true;
}
- SemaRef.Diag(S->getLocStart(), diag::err_constexpr_body_invalid_stmt)
- << isa<CXXConstructorDecl>(Dcl);
+ SemaRef.Diag(S->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
+ << isa<CXXConstructorDecl>(Dcl);
return false;
}
@@ -1925,6 +1940,8 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
///
/// \return true if the body is OK, false if we have diagnosed a problem.
bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
+ SmallVector<SourceLocation, 4> ReturnStmts;
+
if (isa<CXXTryStmt>(Body)) {
// C++11 [dcl.constexpr]p3:
// The definition of a constexpr function shall satisfy the following
@@ -1935,22 +1952,35 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
// C++11 [dcl.constexpr]p4:
// In the definition of a constexpr constructor, [...]
// - its function-body shall not be a function-try-block;
- Diag(Body->getLocStart(), diag::err_constexpr_function_try_block)
- << isa<CXXConstructorDecl>(Dcl);
- return false;
+ //
+ // This restriction is lifted in C++2a, as long as inner statements also
+ // apply the general constexpr rules.
+ Diag(Body->getBeginLoc(),
+ !getLangOpts().CPlusPlus2a
+ ? diag::ext_constexpr_function_try_block_cxx2a
+ : diag::warn_cxx17_compat_constexpr_function_try_block)
+ << isa<CXXConstructorDecl>(Dcl);
}
- SmallVector<SourceLocation, 4> ReturnStmts;
-
// - its function-body shall be [...] a compound-statement that contains only
// [... list of cases ...]
- CompoundStmt *CompBody = cast<CompoundStmt>(Body);
- SourceLocation Cxx1yLoc;
- for (auto *BodyIt : CompBody->body()) {
- if (!CheckConstexprFunctionStmt(*this, Dcl, BodyIt, ReturnStmts, Cxx1yLoc))
+ //
+ // Note that walking the children here is enough to properly check for
+ // CompoundStmt and CXXTryStmt body.
+ SourceLocation Cxx1yLoc, Cxx2aLoc;
+ for (Stmt *SubStmt : Body->children()) {
+ if (SubStmt &&
+ !CheckConstexprFunctionStmt(*this, Dcl, SubStmt, ReturnStmts,
+ Cxx1yLoc, Cxx2aLoc))
return false;
}
+ if (Cxx2aLoc.isValid())
+ Diag(Cxx2aLoc,
+ getLangOpts().CPlusPlus2a
+ ? diag::warn_cxx17_compat_constexpr_body_invalid_stmt
+ : diag::ext_constexpr_body_invalid_stmt_cxx2a)
+ << isa<CXXConstructorDecl>(Dcl);
if (Cxx1yLoc.isValid())
Diag(Cxx1yLoc,
getLangOpts().CPlusPlus14
@@ -2317,8 +2347,8 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
continue;
Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
- ? diag::warn_unknown_attribute_ignored
- : diag::err_base_specifier_attribute)
+ ? (unsigned)diag::warn_unknown_attribute_ignored
+ : (unsigned)diag::err_base_specifier_attribute)
<< AL.getName();
}
@@ -2395,10 +2425,8 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
// C++ [class.mi]p3:
// A class shall not be specified as a direct base class of a
// derived class more than once.
- Diag(Bases[idx]->getLocStart(),
- diag::err_duplicate_base_class)
- << KnownBase->getType()
- << Bases[idx]->getSourceRange();
+ Diag(Bases[idx]->getBeginLoc(), diag::err_duplicate_base_class)
+ << KnownBase->getType() << Bases[idx]->getSourceRange();
// Delete the duplicate base class specifier; we're going to
// overwrite its pointer later.
@@ -2421,9 +2449,9 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
KnownBase->getAccessSpecifier() != AS_public)) {
// The Microsoft extension __interface does not permit bases that
// are not themselves public interfaces.
- Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface)
- << getRecordDiagFromTagKind(RD->getTagKind()) << RD
- << RD->getSourceRange();
+ Diag(KnownBase->getBeginLoc(), diag::err_invalid_base_in_interface)
+ << getRecordDiagFromTagKind(RD->getTagKind()) << RD
+ << RD->getSourceRange();
Invalid = true;
}
if (RD->hasAttr<WeakAttr>())
@@ -2457,9 +2485,9 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
(void)found;
if (Paths.isAmbiguous(CanonicalBase))
- Diag(Bases[idx]->getLocStart (), diag::warn_inaccessible_base_class)
- << BaseType << getAmbiguousPathsDisplayString(Paths)
- << Bases[idx]->getSourceRange();
+ Diag(Bases[idx]->getBeginLoc(), diag::warn_inaccessible_base_class)
+ << BaseType << getAmbiguousPathsDisplayString(Paths)
+ << Bases[idx]->getSourceRange();
else
assert(Bases[idx]->isVirtual());
}
@@ -2842,7 +2870,8 @@ static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) {
// Check if there is a field shadowing.
void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
DeclarationName FieldName,
- const CXXRecordDecl *RD) {
+ const CXXRecordDecl *RD,
+ bool DeclIsField) {
if (Diags.isIgnored(diag::warn_shadow_field, Loc))
return;
@@ -2882,7 +2911,7 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
if (AS_none !=
CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) {
Diag(Loc, diag::warn_shadow_field)
- << FieldName << RD << Base;
+ << FieldName << RD << Base << DeclIsField;
Diag(BaseField->getLocation(), diag::note_shadow_field);
Bases.erase(It);
}
@@ -2906,7 +2935,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
// For anonymous bitfields, the location should point to the type.
if (Loc.isInvalid())
- Loc = D.getLocStart();
+ Loc = D.getBeginLoc();
Expr *BitWidth = static_cast<Expr*>(BW);
@@ -3144,17 +3173,17 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) {
auto *TD = DG->getDeducedTemplate();
if (AS != TD->getAccess()) {
- Diag(DG->getLocStart(), diag::err_deduction_guide_wrong_access);
- Diag(TD->getLocStart(), diag::note_deduction_guide_template_access)
- << TD->getAccess();
+ Diag(DG->getBeginLoc(), diag::err_deduction_guide_wrong_access);
+ Diag(TD->getBeginLoc(), diag::note_deduction_guide_template_access)
+ << TD->getAccess();
const AccessSpecDecl *LastAccessSpec = nullptr;
for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) {
if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D))
LastAccessSpec = AccessSpec;
}
assert(LastAccessSpec && "differing access with no access specifier");
- Diag(LastAccessSpec->getLocStart(), diag::note_deduction_guide_access)
- << AS;
+ Diag(LastAccessSpec->getBeginLoc(), diag::note_deduction_guide_access)
+ << AS;
}
}
}
@@ -3239,7 +3268,7 @@ namespace {
ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParenImpCasts());
}
- // Binding a reference to an unintialized field is not an
+ // Binding a reference to an uninitialized field is not an
// uninitialized use.
if (CheckReferenceOnly && !ReferenceField)
return true;
@@ -3638,10 +3667,10 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
InitializationKind Kind =
FD->getInClassInitStyle() == ICIS_ListInit
- ? InitializationKind::CreateDirectList(InitExpr->getLocStart(),
- InitExpr->getLocStart(),
- InitExpr->getLocEnd())
- : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc);
+ ? InitializationKind::CreateDirectList(InitExpr->getBeginLoc(),
+ InitExpr->getBeginLoc(),
+ InitExpr->getEndLoc())
+ : InitializationKind::CreateCopy(InitExpr->getBeginLoc(), InitLoc);
InitializationSequence Seq(*this, Entity, Kind, InitExpr);
Init = Seq.Perform(*this, Entity, Kind, InitExpr);
if (Init.isInvalid()) {
@@ -3653,7 +3682,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- Init = ActOnFinishFullExpr(Init.get(), InitLoc);
+ Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false);
if (Init.isInvalid()) {
FD->setInvalidDecl();
return;
@@ -3737,8 +3766,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
- Expr *List = new (Context) ParenListExpr(Context, LParenLoc,
- Args, RParenLoc);
+ Expr *List = ParenListExpr::Create(Context, LParenLoc, Args, RParenLoc);
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
DS, IdLoc, List, EllipsisLoc);
}
@@ -3767,6 +3795,22 @@ private:
}
+ValueDecl *Sema::tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+ CXXScopeSpec &SS,
+ ParsedType TemplateTypeTy,
+ IdentifierInfo *MemberOrBase) {
+ if (SS.getScopeRep() || TemplateTypeTy)
+ return nullptr;
+ DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
+ if (Result.empty())
+ return nullptr;
+ ValueDecl *Member;
+ if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
+ (Member = dyn_cast<IndirectFieldDecl>(Result.front())))
+ return Member;
+ return nullptr;
+}
+
/// Handle a C++ member initializer.
MemInitResult
Sema::BuildMemInitializer(Decl *ConstructorD,
@@ -3810,21 +3854,16 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
// of a single identifier refers to the class member. A
// mem-initializer-id for the hidden base class may be specified
// using a qualified name. ]
- if (!SS.getScopeRep() && !TemplateTypeTy) {
- // Look for a member, first.
- DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
- if (!Result.empty()) {
- ValueDecl *Member;
- if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
- (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) {
- if (EllipsisLoc.isValid())
- Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
- << MemberOrBase
- << SourceRange(IdLoc, Init->getSourceRange().getEnd());
- return BuildMemberInitializer(Member, Init, IdLoc);
- }
- }
+ // Look for a member, first.
+ if (ValueDecl *Member = tryLookupCtorInitMemberDecl(
+ ClassDecl, SS, TemplateTypeTy, MemberOrBase)) {
+ if (EllipsisLoc.isValid())
+ Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
+ << MemberOrBase
+ << SourceRange(IdLoc, Init->getSourceRange().getEnd());
+
+ return BuildMemberInitializer(Member, Init, IdLoc);
}
// It didn't name a member, so see if it names a class.
QualType BaseType;
@@ -3908,10 +3947,8 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec
: VirtualBaseSpec;
- Diag(BaseSpec->getLocStart(),
- diag::note_base_class_specified_here)
- << BaseSpec->getType()
- << BaseSpec->getSourceRange();
+ Diag(BaseSpec->getBeginLoc(), diag::note_base_class_specified_here)
+ << BaseSpec->getType() << BaseSpec->getSourceRange();
TyD = Type;
}
@@ -3990,7 +4027,7 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
nullptr);
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(
- IdLoc, Init->getLocStart(), Init->getLocEnd())
+ IdLoc, Init->getBeginLoc(), Init->getEndLoc())
: InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
InitRange.getEnd());
@@ -4003,7 +4040,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin());
+ MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(),
+ /*DiscardedValue*/ false);
if (MemberInit.isInvalid())
return true;
@@ -4043,7 +4081,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(
- NameLoc, Init->getLocStart(), Init->getLocEnd())
+ NameLoc, Init->getBeginLoc(), Init->getEndLoc())
: InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
@@ -4058,8 +4096,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- DelegationInit = ActOnFinishFullExpr(DelegationInit.get(),
- InitRange.getBegin());
+ DelegationInit = ActOnFinishFullExpr(
+ DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false);
if (DelegationInit.isInvalid())
return true;
@@ -4188,7 +4226,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin());
+ BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(),
+ /*DiscardedValue*/ false);
if (BaseInit.isInvalid())
return true;
@@ -4214,7 +4253,7 @@ static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) {
if (T.isNull()) T = E->getType();
QualType TargetType = SemaRef.BuildReferenceType(
T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName());
- SourceLocation ExprLoc = E->getLocStart();
+ SourceLocation ExprLoc = E->getBeginLoc();
TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo(
TargetType, ExprLoc);
@@ -5171,10 +5210,9 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
assert(Dtor && "No dtor found for BaseClassDecl!");
// FIXME: caret should be on the start of the class name
- CheckDestructorAccess(Base.getLocStart(), Dtor,
+ CheckDestructorAccess(Base.getBeginLoc(), Dtor,
PDiag(diag::err_access_dtor_base)
- << Base.getType()
- << Base.getSourceRange(),
+ << Base.getType() << Base.getSourceRange(),
Context.getTypeDeclType(ClassDecl));
MarkFunctionReferenced(Location, Dtor);
@@ -5492,6 +5530,9 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
// declaration.
return;
+ if (S.Context.getTargetInfo().getTriple().isWindowsGNUEnvironment())
+ S.MarkVTableUsed(Class->getLocation(), Class, true);
+
for (Decl *Member : Class->decls()) {
// Defined static variables that are members of an exported base
// class must be marked export too.
@@ -5705,8 +5746,28 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
continue;
if (!getDLLAttr(Member)) {
- auto *NewAttr =
- cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+ InheritableAttr *NewAttr = nullptr;
+
+ // Do not export/import inline function when -fno-dllexport-inlines is
+ // passed. But add attribute for later local static var check.
+ if (!getLangOpts().DllExportInlines && MD && MD->isInlined() &&
+ TSK != TSK_ExplicitInstantiationDeclaration &&
+ TSK != TSK_ExplicitInstantiationDefinition) {
+ if (ClassExported) {
+ NewAttr = ::new (getASTContext())
+ DLLExportStaticLocalAttr(ClassAttr->getRange(),
+ getASTContext(),
+ ClassAttr->getSpellingListIndex());
+ } else {
+ NewAttr = ::new (getASTContext())
+ DLLImportStaticLocalAttr(ClassAttr->getRange(),
+ getASTContext(),
+ ClassAttr->getSpellingListIndex());
+ }
+ } else {
+ NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+ }
+
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
@@ -5825,6 +5886,9 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
if (D->isDependentType() || D->isInvalidDecl())
return false;
+ if (D->hasAttr<TrivialABIAttr>())
+ return true;
+
// Clang <= 4 used the pre-C++11 rule, which ignores move operations.
// The PS4 platform ABI follows the behavior of Clang 3.2.
if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
@@ -6450,20 +6514,29 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// copy operation can take a non-const reference) as an implicit
// declaration, and
// -- not have default arguments.
+ // C++2a changes the second bullet to instead delete the function if it's
+ // defaulted on its first declaration, unless it's "an assignment operator,
+ // and its return type differs or its parameter type is not a reference".
+ bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus2a && First;
+ bool ShouldDeleteForTypeMismatch = false;
unsigned ExpectedParams = 1;
if (CSM == CXXDefaultConstructor || CSM == CXXDestructor)
ExpectedParams = 0;
if (MD->getNumParams() != ExpectedParams) {
- // This also checks for default arguments: a copy or move constructor with a
+ // This checks for default arguments: a copy or move constructor with a
// default argument is classified as a default constructor, and assignment
// operations and destructors can't have default arguments.
Diag(MD->getLocation(), diag::err_defaulted_special_member_params)
<< CSM << MD->getSourceRange();
HadError = true;
} else if (MD->isVariadic()) {
- Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic)
- << CSM << MD->getSourceRange();
- HadError = true;
+ if (DeleteOnTypeMismatch)
+ ShouldDeleteForTypeMismatch = true;
+ else {
+ Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic)
+ << CSM << MD->getSourceRange();
+ HadError = true;
+ }
}
const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>();
@@ -6478,8 +6551,11 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) {
// Check for return type matching.
ReturnType = Type->getReturnType();
- QualType ExpectedReturnType =
- Context.getLValueReferenceType(Context.getTypeDeclType(RD));
+
+ QualType DeclType = Context.getTypeDeclType(RD);
+ DeclType = Context.getAddrSpaceQualType(DeclType, MD->getTypeQualifiers().getAddressSpace());
+ QualType ExpectedReturnType = Context.getLValueReferenceType(DeclType);
+
if (!Context.hasSameType(ReturnType, ExpectedReturnType)) {
Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type)
<< (CSM == CXXMoveAssignment) << ExpectedReturnType;
@@ -6487,10 +6563,14 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
}
// A defaulted special member cannot have cv-qualifiers.
- if (Type->getTypeQuals()) {
- Diag(MD->getLocation(), diag::err_defaulted_special_member_quals)
- << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14;
- HadError = true;
+ if (Type->getTypeQuals().hasConst() || Type->getTypeQuals().hasVolatile()) {
+ if (DeleteOnTypeMismatch)
+ ShouldDeleteForTypeMismatch = true;
+ else {
+ Diag(MD->getLocation(), diag::err_defaulted_special_member_quals)
+ << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14;
+ HadError = true;
+ }
}
}
@@ -6503,23 +6583,30 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
HasConstParam = ReferentType.isConstQualified();
if (ReferentType.isVolatileQualified()) {
- Diag(MD->getLocation(),
- diag::err_defaulted_special_member_volatile_param) << CSM;
- HadError = true;
+ if (DeleteOnTypeMismatch)
+ ShouldDeleteForTypeMismatch = true;
+ else {
+ Diag(MD->getLocation(),
+ diag::err_defaulted_special_member_volatile_param) << CSM;
+ HadError = true;
+ }
}
if (HasConstParam && !CanHaveConstParam) {
- if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) {
+ if (DeleteOnTypeMismatch)
+ ShouldDeleteForTypeMismatch = true;
+ else if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) {
Diag(MD->getLocation(),
diag::err_defaulted_special_member_copy_const_param)
<< (CSM == CXXCopyAssignment);
// FIXME: Explain why this special member can't be const.
+ HadError = true;
} else {
Diag(MD->getLocation(),
diag::err_defaulted_special_member_move_const_param)
<< (CSM == CXXMoveAssignment);
+ HadError = true;
}
- HadError = true;
}
} else if (ExpectedParams) {
// A copy assignment operator can take its argument by value, but a
@@ -6542,7 +6629,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
: isa<CXXConstructorDecl>(MD)) &&
MD->isConstexpr() && !Constexpr &&
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
- Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM;
+ Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM;
// FIXME: Explain why the special member can't be constexpr.
HadError = true;
}
@@ -6556,7 +6643,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// If the exception specification needs to be instantiated, do so now,
// before we clobber it with an EST_Unevaluated specification below.
if (Type->getExceptionSpecType() == EST_Uninstantiated) {
- InstantiateExceptionSpec(MD->getLocStart(), MD);
+ InstantiateExceptionSpec(MD->getBeginLoc(), MD);
Type = MD->getType()->getAs<FunctionProtoType>();
}
DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type));
@@ -6581,14 +6668,27 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
EPI));
}
- if (ShouldDeleteSpecialMember(MD, CSM)) {
+ if (ShouldDeleteForTypeMismatch || ShouldDeleteSpecialMember(MD, CSM)) {
if (First) {
SetDeclDeleted(MD, MD->getLocation());
+ if (!inTemplateInstantiation() && !HadError) {
+ Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) << CSM;
+ if (ShouldDeleteForTypeMismatch) {
+ Diag(MD->getLocation(), diag::note_deleted_type_mismatch) << CSM;
+ } else {
+ ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
+ }
+ }
+ if (ShouldDeleteForTypeMismatch && !HadError) {
+ Diag(MD->getLocation(),
+ diag::warn_cxx17_compat_defaulted_method_type_mismatch) << CSM;
+ }
} else {
// C++11 [dcl.fct.def.default]p4:
// [For a] user-provided explicitly-defaulted function [...] if such a
// function is implicitly defined as deleted, the program is ill-formed.
Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
+ assert(!ShouldDeleteForTypeMismatch && "deleted non-first decl");
ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
HadError = true;
}
@@ -6628,20 +6728,27 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
}
void Sema::CheckDelayedMemberExceptionSpecs() {
- decltype(DelayedExceptionSpecChecks) Checks;
- decltype(DelayedDefaultedMemberExceptionSpecs) Specs;
+ decltype(DelayedOverridingExceptionSpecChecks) Overriding;
+ decltype(DelayedEquivalentExceptionSpecChecks) Equivalent;
+ decltype(DelayedDefaultedMemberExceptionSpecs) Defaulted;
- std::swap(Checks, DelayedExceptionSpecChecks);
- std::swap(Specs, DelayedDefaultedMemberExceptionSpecs);
+ std::swap(Overriding, DelayedOverridingExceptionSpecChecks);
+ std::swap(Equivalent, DelayedEquivalentExceptionSpecChecks);
+ std::swap(Defaulted, DelayedDefaultedMemberExceptionSpecs);
// Perform any deferred checking of exception specifications for virtual
// destructors.
- for (auto &Check : Checks)
+ for (auto &Check : Overriding)
CheckOverridingFunctionExceptionSpec(Check.first, Check.second);
+ // Perform any deferred checking of exception specifications for befriended
+ // special members.
+ for (auto &Check : Equivalent)
+ CheckEquivalentExceptionSpec(Check.second, Check.first);
+
// Check that any explicitly-defaulted methods have exception specifications
// compatible with their implicit exception specifications.
- for (auto &Spec : Specs)
+ for (auto &Spec : Defaulted)
CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second);
}
@@ -6858,10 +6965,10 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
<< Field << DiagKind << IsDtorCallInCtor;
} else {
CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
- S.Diag(Base->getLocStart(),
+ S.Diag(Base->getBeginLoc(),
diag::note_deleted_special_member_class_subobject)
- << getEffectiveCSM() << MD->getParent() << /*IsField*/false
- << Base->getType() << DiagKind << IsDtorCallInCtor;
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/ false
+ << Base->getType() << DiagKind << IsDtorCallInCtor;
}
if (DiagKind == 1)
@@ -6930,10 +7037,10 @@ bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
// FIXME: Check that the base has a usable destructor! Sink this into
// shouldDeleteForClassSubobject.
if (BaseCtor->isDeleted() && Diagnose) {
- S.Diag(Base->getLocStart(),
+ S.Diag(Base->getBeginLoc(),
diag::note_deleted_special_member_class_subobject)
- << getEffectiveCSM() << MD->getParent() << /*IsField*/false
- << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/false;
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/ false
+ << Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false;
S.NoteDeletedFunction(BaseCtor);
}
return BaseCtor->isDeleted();
@@ -7080,7 +7187,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
// The closure type associated with a lambda-expression has a
// deleted (8.4.3) default constructor and a deleted copy
// assignment operator.
- if (RD->isLambda() &&
+ // C++2a adds back these operators if the lambda has no capture-default.
+ if (RD->isLambda() && !RD->lambdaIsDefaultConstructibleAndAssignable() &&
(CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) {
if (Diagnose)
Diag(RD->getLocation(), diag::note_lambda_decl);
@@ -7180,8 +7288,17 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
if (getLangOpts().CUDA) {
// We should delete the special member in CUDA mode if target inference
// failed.
- return inferCUDATargetForImplicitSpecialMember(RD, CSM, MD, SMI.ConstArg,
- Diagnose);
+ // For inherited constructors (non-null ICI), CSM may be passed so that MD
+ // is treated as certain special member, which may not reflect what special
+ // member MD really is. However inferCUDATargetForImplicitSpecialMember
+ // expects CSM to match MD, therefore recalculate CSM.
+ assert(ICI || CSM == getSpecialMember(MD));
+ auto RealCSM = CSM;
+ if (ICI)
+ RealCSM = getSpecialMember(MD);
+
+ return inferCUDATargetForImplicitSpecialMember(RD, RealCSM, MD,
+ SMI.ConstArg, Diagnose);
}
return false;
@@ -7544,7 +7661,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// -- all the direct base classes have trivial [default constructors or
// destructors]
for (const auto &BI : RD->bases())
- if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(),
+ if (!checkTrivialSubobjectCall(*this, BI.getBeginLoc(), BI.getType(),
ConstArg, CSM, TSK_BaseClass, TAH, Diagnose))
return false;
@@ -7584,14 +7701,14 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// member in all bases is trivial, so vbases must all be direct.
CXXBaseSpecifier &BS = *RD->vbases_begin();
assert(BS.isVirtual());
- Diag(BS.getLocStart(), diag::note_nontrivial_has_virtual) << RD << 1;
+ Diag(BS.getBeginLoc(), diag::note_nontrivial_has_virtual) << RD << 1;
return false;
}
// Must have a virtual method.
for (const auto *MI : RD->methods()) {
if (MI->isVirtual()) {
- SourceLocation MLoc = MI->getLocStart();
+ SourceLocation MLoc = MI->getBeginLoc();
Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0;
return false;
}
@@ -7612,7 +7729,7 @@ struct FindHiddenVirtualMethod {
SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
private:
- /// Check whether any most overriden method from MD in Methods
+ /// Check whether any most overridden method from MD in Methods
static bool CheckMostOverridenMethods(
const CXXMethodDecl *MD,
const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
@@ -7696,7 +7813,7 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
FHVM.Method = MD;
FHVM.S = this;
- // Keep the base methods that were overriden or introduced in the subclass
+ // Keep the base methods that were overridden or introduced in the subclass
// by 'using' in a set. A base method not in this set is hidden.
CXXRecordDecl *DC = MD->getParent();
DeclContext::lookup_result R = DC->lookup(MD->getDeclName());
@@ -8063,16 +8180,12 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
}
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
- if (FTI.TypeQuals != 0) {
- if (FTI.TypeQuals & Qualifiers::Const)
- Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
- << "const" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & Qualifiers::Volatile)
- Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
- << "volatile" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & Qualifiers::Restrict)
- Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
- << "restrict" << SourceRange(D.getIdentifierLoc());
+ if (FTI.hasMethodTypeQualifiers()) {
+ FTI.MethodQualifiers->forEachQualifier(
+ [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
+ Diag(SL, diag::err_invalid_qualified_constructor)
+ << QualName << SourceRange(SL);
+ });
D.setInvalidType();
}
@@ -8093,7 +8206,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
return R;
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
- EPI.TypeQuals = 0;
+ EPI.TypeQuals = Qualifiers();
EPI.RefQualifier = RQ_None;
return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
@@ -8179,6 +8292,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
}
}
+ DiagnoseUseOfDecl(OperatorDelete, Loc);
MarkFunctionReferenced(Loc, OperatorDelete);
Destructor->setOperatorDelete(OperatorDelete, ThisArg);
}
@@ -8252,16 +8366,12 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
}
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
- if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
- if (FTI.TypeQuals & Qualifiers::Const)
- Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
- << "const" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & Qualifiers::Volatile)
- Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
- << "volatile" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & Qualifiers::Restrict)
- Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
- << "restrict" << SourceRange(D.getIdentifierLoc());
+ if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) {
+ FTI.MethodQualifiers->forEachQualifier(
+ [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
+ Diag(SL, diag::err_invalid_qualified_destructor)
+ << QualName << SourceRange(SL);
+ });
D.setInvalidType();
}
@@ -8299,7 +8409,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.Variadic = false;
- EPI.TypeQuals = 0;
+ EPI.TypeQuals = Qualifiers();
EPI.RefQualifier = RQ_None;
return Context.getFunctionType(Context.VoidTy, None, EPI);
}
@@ -8437,7 +8547,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// If we can provide a correct fix-it hint, do so.
if (After.isInvalid() && ConvTSI) {
SourceLocation InsertLoc =
- getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd());
+ getLocForEndOfToken(ConvTSI->getTypeLoc().getEndLoc());
DB << FixItHint::CreateInsertion(InsertLoc, " ")
<< FixItHint::CreateInsertionFromRange(
InsertLoc, CharSourceRange::getTokenRange(Before))
@@ -8627,13 +8737,13 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
if (Chunk.Kind == DeclaratorChunk::Paren)
continue;
if (Chunk.Kind != DeclaratorChunk::Function || FoundFunction) {
- Diag(D.getDeclSpec().getLocStart(),
- diag::err_deduction_guide_with_complex_decl)
- << D.getSourceRange();
+ Diag(D.getDeclSpec().getBeginLoc(),
+ diag::err_deduction_guide_with_complex_decl)
+ << D.getSourceRange();
break;
}
if (!Chunk.Fun.hasTrailingReturnType()) {
- Diag(D.getName().getLocStart(),
+ Diag(D.getName().getBeginLoc(),
diag::err_deduction_guide_no_trailing_return_type);
break;
}
@@ -8665,10 +8775,11 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
}
if (!AcceptableReturnType) {
- Diag(TSI->getTypeLoc().getLocStart(),
+ Diag(TSI->getTypeLoc().getBeginLoc(),
diag::err_deduction_guide_bad_trailing_return_type)
- << GuidedTemplate << TSI->getType() << MightInstantiateToSpecialization
- << TSI->getTypeLoc().getSourceRange();
+ << GuidedTemplate << TSI->getType()
+ << MightInstantiateToSpecialization
+ << TSI->getTypeLoc().getSourceRange();
}
// Keep going to check that we don't have any inner declarator pieces (we
@@ -9349,7 +9460,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
if (SS.isEmpty()) {
- Diag(Name.getLocStart(), diag::err_using_requires_qualname);
+ Diag(Name.getBeginLoc(), diag::err_using_requires_qualname);
return nullptr;
}
@@ -9364,24 +9475,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
case UnqualifiedIdKind::IK_ConstructorName:
case UnqualifiedIdKind::IK_ConstructorTemplateId:
// C++11 inheriting constructors.
- Diag(Name.getLocStart(),
- getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_using_decl_constructor :
- diag::err_using_decl_constructor)
- << SS.getRange();
+ Diag(Name.getBeginLoc(),
+ getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_using_decl_constructor
+ : diag::err_using_decl_constructor)
+ << SS.getRange();
if (getLangOpts().CPlusPlus11) break;
return nullptr;
case UnqualifiedIdKind::IK_DestructorName:
- Diag(Name.getLocStart(), diag::err_using_decl_destructor)
- << SS.getRange();
+ Diag(Name.getBeginLoc(), diag::err_using_decl_destructor) << SS.getRange();
return nullptr;
case UnqualifiedIdKind::IK_TemplateId:
- Diag(Name.getLocStart(), diag::err_using_decl_template_id)
- << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
+ Diag(Name.getBeginLoc(), diag::err_using_decl_template_id)
+ << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
return nullptr;
case UnqualifiedIdKind::IK_DeductionGuideName:
@@ -9395,10 +9505,10 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
// Warn about access declarations.
if (UsingLoc.isInvalid()) {
- Diag(Name.getLocStart(),
- getLangOpts().CPlusPlus11 ? diag::err_access_decl
- : diag::warn_access_decl_deprecated)
- << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
+ Diag(Name.getBeginLoc(), getLangOpts().CPlusPlus11
+ ? diag::err_access_decl
+ : diag::warn_access_decl_deprecated)
+ << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
}
if (EllipsisLoc.isInvalid()) {
@@ -10230,8 +10340,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
" = ");
} else {
// Convert 'using X::Y;' to 'typedef X::Y Y;'.
- SourceLocation InsertLoc =
- getLocForEndOfToken(NameInfo.getLocEnd());
+ SourceLocation InsertLoc = getLocForEndOfToken(NameInfo.getEndLoc());
Diag(InsertLoc, diag::note_using_decl_class_member_workaround)
<< 1 // typedef declaration
<< FixItHint::CreateReplacement(UsingLoc, "typedef")
@@ -10472,7 +10581,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
OldDecl->getTemplateParameters(),
/*Complain=*/true,
TPL_TemplateMatch))
- OldTemplateParams = OldDecl->getTemplateParameters();
+ OldTemplateParams =
+ OldDecl->getMostRecentDecl()->getTemplateParameters();
else
Invalid = true;
@@ -10679,19 +10789,48 @@ void SpecialMemberExceptionSpecInfo::visitSubobjectCall(
ExceptSpec.CalledDecl(getSubobjectLoc(Subobj), MD);
}
+namespace {
+/// RAII object to register a special member as being currently declared.
+struct ComputingExceptionSpec {
+ Sema &S;
+
+ ComputingExceptionSpec(Sema &S, CXXMethodDecl *MD, SourceLocation Loc)
+ : S(S) {
+ Sema::CodeSynthesisContext Ctx;
+ Ctx.Kind = Sema::CodeSynthesisContext::ExceptionSpecEvaluation;
+ Ctx.PointOfInstantiation = Loc;
+ Ctx.Entity = MD;
+ S.pushCodeSynthesisContext(Ctx);
+ }
+ ~ComputingExceptionSpec() {
+ S.popCodeSynthesisContext();
+ }
+};
+}
+
static Sema::ImplicitExceptionSpecification
ComputeDefaultedSpecialMemberExceptionSpec(
Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
Sema::InheritedConstructorInfo *ICI) {
+ ComputingExceptionSpec CES(S, MD, Loc);
+
CXXRecordDecl *ClassDecl = MD->getParent();
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, Loc);
+ SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, MD->getLocation());
if (ClassDecl->isInvalidDecl())
return Info.ExceptSpec;
+ // FIXME: If this diagnostic fires, we're probably missing a check for
+ // attempting to resolve an exception specification before it's known
+ // at a higher level.
+ if (S.RequireCompleteType(MD->getLocation(),
+ S.Context.getRecordType(ClassDecl),
+ diag::err_exception_spec_incomplete_type))
+ return Info.ExceptSpec;
+
// C++1z [except.spec]p7:
// [Look for exceptions thrown by] a constructor selected [...] to
// initialize a potentially constructed subobject,
@@ -10774,6 +10913,22 @@ void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) {
CheckFunctionDeclaration(S, FD, R, /*IsMemberSpecialization*/false);
}
+void Sema::setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
+ QualType ResultTy,
+ ArrayRef<QualType> Args) {
+ // Build an exception specification pointing back at this constructor.
+ FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, SpecialMem);
+
+ if (getLangOpts().OpenCLCPlusPlus) {
+ // OpenCL: Implicitly defaulted special member are of the generic address
+ // space.
+ EPI.TypeQuals.addAddressSpace(LangAS::opencl_generic);
+ }
+
+ auto QT = Context.getFunctionType(ResultTy, Args, EPI);
+ SpecialMem->setType(QT);
+}
+
CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
CXXRecordDecl *ClassDecl) {
// C++ [class.ctor]p5:
@@ -10814,9 +10969,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
/* Diagnose */ false);
}
- // Build an exception specification pointing back at this constructor.
- FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon);
- DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
+ setupImplicitSpecialMemberType(DefaultCon, Context.VoidTy, None);
// We don't need to use SpecialMemberIsTrivial here; triviality for default
// constructors is easy to compute.
@@ -10866,8 +11019,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
return;
}
- SourceLocation Loc = Constructor->getLocEnd().isValid()
- ? Constructor->getLocEnd()
+ SourceLocation Loc = Constructor->getEndLoc().isValid()
+ ? Constructor->getEndLoc()
: Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
Constructor->markUsed(Context);
@@ -11087,9 +11240,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
/* Diagnose */ false);
}
- // Build an exception specification pointing back at this destructor.
- FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor);
- Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
+ setupImplicitSpecialMemberType(Destructor, Context.VoidTy, None);
// We don't need to use SpecialMemberIsTrivial here; triviality for
// destructors is easy to compute.
@@ -11149,8 +11300,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
return;
}
- SourceLocation Loc = Destructor->getLocEnd().isValid()
- ? Destructor->getLocEnd()
+ SourceLocation Loc = Destructor->getEndLoc().isValid()
+ ? Destructor->getEndLoc()
: Destructor->getLocation();
Destructor->setBody(new (Context) CompoundStmt(Loc));
Destructor->markUsed(Context);
@@ -11166,8 +11317,9 @@ void Sema::ActOnFinishCXXMemberDecls() {
// If the context is an invalid C++ class, just suppress these checks.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
if (Record->isInvalidDecl()) {
+ DelayedOverridingExceptionSpecChecks.clear();
+ DelayedEquivalentExceptionSpecChecks.clear();
DelayedDefaultedMemberExceptionSpecs.clear();
- DelayedExceptionSpecChecks.clear();
return;
}
checkForMultipleExportedDefaultConstructors(*this, Record);
@@ -11189,11 +11341,13 @@ void Sema::referenceDLLExportedClassMethods() {
}
}
-void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
- CXXDestructorDecl *Destructor) {
+void Sema::AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor) {
assert(getLangOpts().CPlusPlus11 &&
"adjusting dtor exception specs was introduced in c++11");
+ if (Destructor->isDependentContext())
+ return;
+
// C++11 [class.dtor]p3:
// A declaration of a destructor that does not have an exception-
// specification is implicitly considered to have the same exception-
@@ -11660,6 +11814,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
bool Const = ClassDecl->implicitCopyAssignmentHasConstParam();
if (Const)
ArgType = ArgType.withConst();
+
+ if (Context.getLangOpts().OpenCLCPlusPlus)
+ ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
+
ArgType = Context.getLValueReferenceType(ArgType);
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
@@ -11686,10 +11844,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
/* Diagnose */ false);
}
- // Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI =
- getImplicitMethodEPI(*this, CopyAssignment);
- CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+ setupImplicitSpecialMemberType(CopyAssignment, RetType, ArgType);
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
@@ -11821,8 +11976,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Our location for everything implicitly-generated.
- SourceLocation Loc = CopyAssignOperator->getLocEnd().isValid()
- ? CopyAssignOperator->getLocEnd()
+ SourceLocation Loc = CopyAssignOperator->getEndLoc().isValid()
+ ? CopyAssignOperator->getEndLoc()
: CopyAssignOperator->getLocation();
// Builds a DeclRefExpr for the "other" object.
@@ -11853,7 +12008,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Dereference "this".
DerefBuilder DerefThis(This);
CastBuilder To(DerefThis,
- Context.getCVRQualifiedType(
+ Context.getQualifiedType(
BaseType, CopyAssignOperator->getTypeQualifiers()),
VK_LValue, BasePath);
@@ -12100,14 +12255,14 @@ static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
if (Existing && Existing != &BI) {
S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times)
<< Class << Base;
- S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here)
- << (Base->getCanonicalDecl() ==
- Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
- << Base << Existing->getType() << Existing->getSourceRange();
- S.Diag(BI.getLocStart(), diag::note_vbase_moved_here)
- << (Base->getCanonicalDecl() ==
- BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl())
- << Base << BI.getType() << BaseSpec->getSourceRange();
+ S.Diag(Existing->getBeginLoc(), diag::note_vbase_moved_here)
+ << (Base->getCanonicalDecl() ==
+ Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << Existing->getType() << Existing->getSourceRange();
+ S.Diag(BI.getBeginLoc(), diag::note_vbase_moved_here)
+ << (Base->getCanonicalDecl() ==
+ BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << BI.getType() << BaseSpec->getSourceRange();
// Only diagnose each vbase once.
Existing = nullptr;
@@ -12173,12 +12328,10 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0);
QualType OtherRefType = Other->getType()->
getAs<RValueReferenceType>()->getPointeeType();
- assert(!OtherRefType.getQualifiers() &&
- "Bad argument type of defaulted move assignment");
// Our location for everything implicitly-generated.
- SourceLocation Loc = MoveAssignOperator->getLocEnd().isValid()
- ? MoveAssignOperator->getLocEnd()
+ SourceLocation Loc = MoveAssignOperator->getEndLoc().isValid()
+ ? MoveAssignOperator->getEndLoc()
: MoveAssignOperator->getLocation();
// Builds a reference to the "other" object.
@@ -12220,7 +12373,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Implicitly cast "this" to the appropriately-qualified base type.
CastBuilder To(DerefThis,
- Context.getCVRQualifiedType(
+ Context.getQualifiedType(
BaseType, MoveAssignOperator->getTypeQualifiers()),
VK_LValue, BasePath);
@@ -12356,6 +12509,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
bool Const = ClassDecl->implicitCopyConstructorHasConstParam();
if (Const)
ArgType = ArgType.withConst();
+
+ if (Context.getLangOpts().OpenCLCPlusPlus)
+ ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
+
ArgType = Context.getLValueReferenceType(ArgType);
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
@@ -12384,11 +12541,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
/* Diagnose */ false);
}
- // Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI =
- getImplicitMethodEPI(*this, CopyConstructor);
- CopyConstructor->setType(
- Context.getFunctionType(Context.VoidTy, ArgType, EPI));
+ setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType);
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
@@ -12462,8 +12615,8 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false)) {
CopyConstructor->setInvalidDecl();
} else {
- SourceLocation Loc = CopyConstructor->getLocEnd().isValid()
- ? CopyConstructor->getLocEnd()
+ SourceLocation Loc = CopyConstructor->getEndLoc().isValid()
+ ? CopyConstructor->getEndLoc()
: CopyConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
CopyConstructor->setBody(
@@ -12485,7 +12638,11 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
return nullptr;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
- QualType ArgType = Context.getRValueReferenceType(ClassType);
+
+ QualType ArgType = ClassType;
+ if (Context.getLangOpts().OpenCLCPlusPlus)
+ ArgType = Context.getAddrSpaceQualType(ClassType, LangAS::opencl_generic);
+ ArgType = Context.getRValueReferenceType(ArgType);
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXMoveConstructor,
@@ -12514,11 +12671,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
/* Diagnose */ false);
}
- // Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI =
- getImplicitMethodEPI(*this, MoveConstructor);
- MoveConstructor->setType(
- Context.getFunctionType(Context.VoidTy, ArgType, EPI));
+ setupImplicitSpecialMemberType(MoveConstructor, Context.VoidTy, ArgType);
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
@@ -12585,8 +12738,8 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false)) {
MoveConstructor->setInvalidDecl();
} else {
- SourceLocation Loc = MoveConstructor->getLocEnd().isValid()
- ? MoveConstructor->getLocEnd()
+ SourceLocation Loc = MoveConstructor->getEndLoc().isValid()
+ ? MoveConstructor->getEndLoc()
: MoveConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
MoveConstructor->setBody(ActOnCompoundStmt(
@@ -12889,7 +13042,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext();
Diag(Loc, diag::err_in_class_initializer_not_yet_parsed)
<< OutermostClass << Field;
- Diag(Field->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed);
+ Diag(Field->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
// Recover by marking the field invalid, unless we're in a SFINAE context.
if (!isSFINAEContext())
Field->setInvalidDecl();
@@ -12904,6 +13057,9 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
if (ClassDecl->hasIrrelevantDestructor()) return;
if (ClassDecl->isDependentContext()) return;
+ if (VD->isNoDestroy(getASTContext()))
+ return;
+
CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
MarkFunctionReferenced(VD->getLocation(), Destructor);
CheckDestructorAccess(VD->getLocation(), Destructor,
@@ -13123,7 +13279,8 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
// C++ P0722:
// A destroying operator delete shall be a usual deallocation function.
if (MD && !MD->getParent()->isDependentContext() &&
- MD->isDestroyingOperatorDelete() && !MD->isUsualDeallocationFunction()) {
+ MD->isDestroyingOperatorDelete() &&
+ !SemaRef.isUsualDeallocationFunction(MD)) {
SemaRef.Diag(MD->getLocation(),
diag::err_destroying_operator_delete_not_usual);
return true;
@@ -13601,7 +13758,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
// Only the non-fragile NeXT runtime currently supports C++ catches
// of ObjC types, and no runtime supports catching ObjC types by value.
- if (!Invalid && getLangOpts().ObjC1) {
+ if (!Invalid && getLangOpts().ObjC) {
QualType T = ExDeclType;
if (const ReferenceType *RT = T->getAs<ReferenceType>())
T = RT->getPointeeType();
@@ -13711,10 +13868,8 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
Invalid = true;
}
- VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo,
- D.getLocStart(),
- D.getIdentifierLoc(),
- D.getIdentifier());
+ VarDecl *ExDecl = BuildExceptionDeclaration(
+ S, TInfo, D.getBeginLoc(), D.getIdentifierLoc(), D.getIdentifier());
if (Invalid)
ExDecl->setInvalidDecl();
@@ -13755,6 +13910,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
if (Converted.isInvalid())
Failed = true;
+ else
+ Converted = ConstantExpr::Create(Context, Converted.get());
llvm::APSInt Cond;
if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond,
@@ -13771,9 +13928,9 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *InnerCond = nullptr;
std::string InnerCondDescription;
std::tie(InnerCond, InnerCondDescription) =
- findFailedBooleanCondition(Converted.get(),
- /*AllowTopLevelCond=*/false);
- if (InnerCond) {
+ findFailedBooleanCondition(Converted.get());
+ if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
+ && !isa<IntegerLiteral>(InnerCond)) {
Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
<< InnerCondDescription << !AssertMessage
<< Msg.str() << InnerCond->getSourceRange();
@@ -13870,7 +14027,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
// cv-qualified) class type, that class is declared as a friend; otherwise,
// the friend declaration is ignored.
return FriendDecl::Create(Context, CurContext,
- TSInfo->getTypeLoc().getLocStart(), TSInfo,
+ TSInfo->getTypeLoc().getBeginLoc(), TSInfo,
FriendLoc);
}
@@ -14012,11 +14169,34 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
/// template <> template \<class T> friend class A<int>::B;
Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TempParams) {
- SourceLocation Loc = DS.getLocStart();
+ SourceLocation Loc = DS.getBeginLoc();
assert(DS.isFriendSpecified());
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+ // C++ [class.friend]p3:
+ // A friend declaration that does not declare a function shall have one of
+ // the following forms:
+ // friend elaborated-type-specifier ;
+ // friend simple-type-specifier ;
+ // friend typename-specifier ;
+ //
+ // Any declaration with a type qualifier does not have that form. (It's
+ // legal to specify a qualified type as a friend, you just can't write the
+ // keywords.)
+ if (DS.getTypeQualifiers()) {
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+ Diag(DS.getConstSpecLoc(), diag::err_friend_decl_spec) << "const";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
+ Diag(DS.getVolatileSpecLoc(), diag::err_friend_decl_spec) << "volatile";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
+ Diag(DS.getRestrictSpecLoc(), diag::err_friend_decl_spec) << "restrict";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
+ Diag(DS.getAtomicSpecLoc(), diag::err_friend_decl_spec) << "_Atomic";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)
+ Diag(DS.getUnalignedSpecLoc(), diag::err_friend_decl_spec) << "__unaligned";
+ }
+
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
@@ -14123,8 +14303,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
CXXScopeSpec &SS = D.getCXXScopeSpec();
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
- DeclarationName Name = NameInfo.getName();
- assert(Name);
+ assert(NameInfo.getName());
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) ||
@@ -14243,25 +14422,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
LookupQualifiedName(Previous, DC);
- // Ignore things found implicitly in the wrong scope.
- // TODO: better diagnostics for this case. Suggesting the right
- // qualified scope would be nice...
- LookupResult::Filter F = Previous.makeFilter();
- while (F.hasNext()) {
- NamedDecl *D = F.next();
- if (!DC->InEnclosingNamespaceSetOf(
- D->getDeclContext()->getRedeclContext()))
- F.erase();
- }
- F.done();
-
- if (Previous.empty()) {
- D.setInvalidType();
- Diag(Loc, diag::err_qualified_friend_not_found)
- << Name << TInfo->getType();
- return nullptr;
- }
-
// C++ [class.friend]p1: A friend of a class is a function or
// class that is not a member of the class . . .
if (DC->Equals(CurContext))
@@ -14275,6 +14435,10 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// A function can be defined in a friend declaration of a class if and
// only if the class is a non-local class (9.8), the function name is
// unqualified, and the function has namespace scope.
+ //
+ // FIXME: We should only do this if the scope specifier names the
+ // innermost enclosing namespace; otherwise the fixit changes the
+ // meaning of the code.
SemaDiagnosticBuilder DB
= Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def);
@@ -14532,8 +14696,8 @@ static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
if (!SubStmt)
continue;
if (isa<ReturnStmt>(SubStmt))
- Self.Diag(SubStmt->getLocStart(),
- diag::err_return_in_constructor_handler);
+ Self.Diag(SubStmt->getBeginLoc(),
+ diag::err_return_in_constructor_handler);
if (!isa<Expr>(SubStmt))
SearchForReturnInStmt(Self, SubStmt);
}
@@ -14834,6 +14998,15 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
if (!Class->isDynamicClass() || Class->isDependentContext() ||
CurContext->isDependentContext() || isUnevaluatedContext())
return;
+ // Do not mark as used if compiling for the device outside of the target
+ // region.
+ if (LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
+ !isInOpenMPDeclareTargetContext() &&
+ !isInOpenMPTargetExecutionDirective()) {
+ if (!DefinitionRequired)
+ MarkVirtualMembersReferenced(Loc, Class);
+ return;
+ }
// Try to insert this class into the map.
LoadExternalVTableUses();
@@ -15439,10 +15612,11 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
PrevDecl = nullptr;
- SourceLocation TSSL = D.getLocStart();
- const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData();
- MSPropertyDecl *NewPD = MSPropertyDecl::Create(
- Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId);
+ SourceLocation TSSL = D.getBeginLoc();
+ MSPropertyDecl *NewPD =
+ MSPropertyDecl::Create(Context, Record, Loc, II, T, TInfo, TSSL,
+ MSPropertyAttr.getPropertyDataGetter(),
+ MSPropertyAttr.getPropertyDataSetter());
ProcessDeclAttributes(TUScope, NewPD, D);
NewPD->setAccess(AS);
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 595cc76cd4a3..3746bdad0358 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -363,6 +363,8 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
assert((getCurMethodDecl() == nullptr) && "Methodparsing confused");
ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
+ PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
+
// If we don't have a valid method decl, simply return.
if (!MDecl)
return;
@@ -653,7 +655,7 @@ ActOnSuperClassOfClassInterface(Scope *S,
}
IDecl->setSuperClass(SuperClassTInfo);
- IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getLocEnd());
+ IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getEndLoc());
}
}
@@ -717,21 +719,22 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S,
if (auto attr = qual.getAs<AttributedTypeLoc>()) {
rangeToRemove = attr.getLocalSourceRange();
if (attr.getTypePtr()->getImmediateNullability()) {
- Diag(attr.getLocStart(),
+ Diag(attr.getBeginLoc(),
diag::err_objc_type_param_bound_explicit_nullability)
- << paramName << typeBound
- << FixItHint::CreateRemoval(rangeToRemove);
+ << paramName << typeBound
+ << FixItHint::CreateRemoval(rangeToRemove);
diagnosed = true;
}
}
}
if (!diagnosed) {
- Diag(qual ? qual.getLocStart()
- : typeBoundInfo->getTypeLoc().getLocStart(),
- diag::err_objc_type_param_bound_qualified)
- << paramName << typeBound << typeBound.getQualifiers().getAsString()
- << FixItHint::CreateRemoval(rangeToRemove);
+ Diag(qual ? qual.getBeginLoc()
+ : typeBoundInfo->getTypeLoc().getBeginLoc(),
+ diag::err_objc_type_param_bound_qualified)
+ << paramName << typeBound
+ << typeBound.getQualifiers().getAsString()
+ << FixItHint::CreateRemoval(rangeToRemove);
}
// If the type bound has qualifiers other than CVR, we need to strip
@@ -828,7 +831,7 @@ static bool checkTypeParamListConsistency(Sema &S,
if (newTypeParams->size() > prevTypeParams->size()) {
diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();
} else {
- diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getLocEnd());
+ diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getEndLoc());
}
S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)
@@ -865,7 +868,7 @@ static bool checkTypeParamListConsistency(Sema &S,
// Diagnose the conflict and update the second declaration.
SourceLocation diagLoc = newTypeParam->getVarianceLoc();
if (diagLoc.isInvalid())
- diagLoc = newTypeParam->getLocStart();
+ diagLoc = newTypeParam->getBeginLoc();
auto diag = S.Diag(diagLoc,
diag::err_objc_type_param_variance_conflict)
@@ -886,7 +889,7 @@ static bool checkTypeParamListConsistency(Sema &S,
: "__contravariant";
if (newTypeParam->getVariance()
== ObjCTypeParamVariance::Invariant) {
- diag << FixItHint::CreateInsertion(newTypeParam->getLocStart(),
+ diag << FixItHint::CreateInsertion(newTypeParam->getBeginLoc(),
(newVarianceStr + " ").str());
} else {
diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(),
@@ -2164,9 +2167,10 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
} else if (ImplIvar->isBitField() && ClsIvar->isBitField() &&
ImplIvar->getBitWidthValue(Context) !=
ClsIvar->getBitWidthValue(Context)) {
- Diag(ImplIvar->getBitWidth()->getLocStart(),
- diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier();
- Diag(ClsIvar->getBitWidth()->getLocStart(),
+ Diag(ImplIvar->getBitWidth()->getBeginLoc(),
+ diag::err_conflicting_ivar_bitwidth)
+ << ImplIvar->getIdentifier();
+ Diag(ClsIvar->getBitWidth()->getBeginLoc(),
diag::note_previous_definition);
}
// Make sure the names are identical.
@@ -2206,7 +2210,7 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
}
// Issue a note to the original declaration.
- SourceLocation MethodLoc = method->getLocStart();
+ SourceLocation MethodLoc = method->getBeginLoc();
if (MethodLoc.isValid())
S.Diag(MethodLoc, diag::note_method_declared_at) << method;
}
@@ -2880,7 +2884,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
IMPDecl, PI, IncompleteImpl, false,
WarnCategoryMethodImpl);
- // FIXME. For now, we are not checking for extact match of methods
+ // FIXME. For now, we are not checking for exact match of methods
// in category implementation and its primary class's super class.
if (!WarnCategoryMethodImpl && I->getSuperClass())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
@@ -3580,12 +3584,12 @@ void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &
else
Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
- Diag(Methods[0]->getLocStart(),
+ Diag(Methods[0]->getBeginLoc(),
issueError ? diag::note_possibility : diag::note_using)
- << Methods[0]->getSourceRange();
+ << Methods[0]->getSourceRange();
for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
- Diag(Methods[I]->getLocStart(), diag::note_also_found)
- << Methods[I]->getSourceRange();
+ Diag(Methods[I]->getBeginLoc(), diag::note_also_found)
+ << Methods[I]->getSourceRange();
}
}
}
@@ -4351,7 +4355,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
// Propagate down the 'related result type' bit from overridden methods.
if (RTC != Sema::RTC_Incompatible && overridden->hasRelatedResultType())
- ObjCMethod->SetRelatedResultType();
+ ObjCMethod->setRelatedResultType();
// Then merge the declarations.
mergeObjCMethodDecls(ObjCMethod, overridden);
@@ -4485,7 +4489,7 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef,
QualType T;
for (const ParmVarDecl *P : Method->parameters()) {
if (P->getType()->isVectorType()) {
- Loc = P->getLocStart();
+ Loc = P->getBeginLoc();
T = P->getType();
break;
}
@@ -4746,7 +4750,7 @@ Decl *Sema::ActOnMethodDeclaration(
if (InferRelatedResultType &&
!ObjCMethod->getReturnType()->isObjCIndependentClassType())
- ObjCMethod->SetRelatedResultType();
+ ObjCMethod->setRelatedResultType();
}
if (MethodDefinition &&
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 134c76ef28c6..e0850feaffc6 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -64,7 +64,7 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
}
// Only apply this hack within a system header.
- if (!Context.getSourceManager().isInSystemHeader(D.getLocStart()))
+ if (!Context.getSourceManager().isInSystemHeader(D.getBeginLoc()))
return false;
return llvm::StringSwitch<bool>(RD->getIdentifier()->getName())
@@ -230,6 +230,16 @@ Sema::UpdateExceptionSpec(FunctionDecl *FD,
Context.adjustExceptionSpec(Redecl, ESI);
}
+static bool exceptionSpecNotKnownYet(const FunctionDecl *FD) {
+ auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (!MD)
+ return false;
+
+ auto EST = MD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType();
+ return EST == EST_Unparsed ||
+ (EST == EST_Unevaluated && MD->getParent()->isBeingDefined());
+}
+
static bool CheckEquivalentExceptionSpecImpl(
Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
const FunctionProtoType *Old, SourceLocation OldLoc,
@@ -278,6 +288,14 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
ReturnValueOnError = false;
}
+ // If we're befriending a member function of a class that's currently being
+ // defined, we might not be able to work out its exception specification yet.
+ // If not, defer the check until later.
+ if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) {
+ DelayedEquivalentExceptionSpecChecks.push_back({New, Old});
+ return false;
+ }
+
// Check the types as written: they must match before any exception
// specification adjustment is applied.
if (!CheckEquivalentExceptionSpecImpl(
@@ -904,26 +922,21 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
EST_Unparsed)
return false;
- if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) {
- // Don't check uninstantiated template destructors at all. We can only
- // synthesize correct specs after the template is instantiated.
- if (New->getParent()->isDependentType())
- return false;
- if (New->getParent()->isBeingDefined()) {
- // The destructor might be updated once the definition is finished. So
- // remember it and check later.
- DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old));
- return false;
- }
- }
- // If the old exception specification hasn't been parsed yet, remember that
- // we need to perform this check when we get to the end of the outermost
+
+ // Don't check uninstantiated template destructors at all. We can only
+ // synthesize correct specs after the template is instantiated.
+ if (isa<CXXDestructorDecl>(New) && New->getParent()->isDependentType())
+ return false;
+
+ // If the old exception specification hasn't been parsed yet, or the new
+ // exception specification can't be computed yet, remember that we need to
+ // perform this check when we get to the end of the outermost
// lexically-surrounding class.
- if (Old->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
- EST_Unparsed) {
- DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old));
+ if (exceptionSpecNotKnownYet(Old) || exceptionSpecNotKnownYet(New)) {
+ DelayedOverridingExceptionSpecChecks.push_back({New, Old});
return false;
}
+
unsigned DiagID = diag::err_override_exception_spec;
if (getLangOpts().MicrosoftExt)
DiagID = diag::ext_override_exception_spec;
@@ -992,7 +1005,7 @@ static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) {
if (!FT)
return CT_Can;
- FT = S.ResolveExceptionSpec(E->getLocStart(), FT);
+ FT = S.ResolveExceptionSpec(E->getBeginLoc(), FT);
if (!FT)
return CT_Can;
@@ -1038,6 +1051,9 @@ CanThrowResult Sema::canThrow(const Expr *E) {
// [Can throw] if in a potentially-evaluated context the expression would
// contain:
switch (E->getStmtClass()) {
+ case Expr::ConstantExprClass:
+ return canThrow(cast<ConstantExpr>(E)->getSubExpr());
+
case Expr::CXXThrowExprClass:
// - a potentially evaluated throw-expression
return CT_Can;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 3dc6fb151cb7..d5416d4d057c 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -26,6 +26,7 @@
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -65,6 +66,12 @@ bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) {
if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false))
return false;
+
+ // See if this is an aligned allocation/deallocation function that is
+ // unavailable.
+ if (TreatUnavailableAsInvalid &&
+ isUnavailableAlignedAllocationFunction(*FD))
+ return false;
}
// See if this function is unavailable.
@@ -114,7 +121,7 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
return NoteDeletedInheritingConstructor(Ctor);
Diag(Decl->getLocation(), diag::note_availability_specified_here)
- << Decl << true;
+ << Decl << 1;
}
/// Determine whether a FunctionDecl was ever declared with an
@@ -205,7 +212,8 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
- bool AvoidPartialAvailabilityChecks) {
+ bool AvoidPartialAvailabilityChecks,
+ ObjCInterfaceDecl *ClassReceiver) {
SourceLocation Loc = Locs.front();
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
@@ -226,6 +234,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
// The function 'main' shall not be used within a program.
if (cast<FunctionDecl>(D)->isMain())
Diag(Loc, diag::ext_main_used);
+
+ diagnoseUnavailableAlignedAllocation(*cast<FunctionDecl>(D), Loc);
}
// See if this is an auto-typed variable whose initializer we are parsing.
@@ -264,6 +274,17 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
return true;
}
+ if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+ // Lambdas are only default-constructible or assignable in C++2a onwards.
+ if (MD->getParent()->isLambda() &&
+ ((isa<CXXConstructorDecl>(MD) &&
+ cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) ||
+ MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())) {
+ Diag(Loc, diag::warn_cxx17_compat_lambda_def_ctor_assign)
+ << !isa<CXXConstructorDecl>(MD);
+ }
+ }
+
auto getReferencedObjCProp = [](const NamedDecl *D) ->
const ObjCPropertyDecl * {
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
@@ -291,7 +312,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
}
DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess,
- AvoidPartialAvailabilityChecks);
+ AvoidPartialAvailabilityChecks, ClassReceiver);
DiagnoseUnusedOfDecl(*this, D, Loc);
@@ -386,8 +407,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
// or 'NULL' if those are actually defined in the context. Only use
// 'nil' for ObjC methods, where it's much more likely that the
// variadic arguments form a list of object pointers.
- SourceLocation MissingNilLoc
- = getLocForEndOfToken(sentinelExpr->getLocEnd());
+ SourceLocation MissingNilLoc = getLocForEndOfToken(sentinelExpr->getEndLoc());
std::string NullValue;
if (calleeType == CT_Method && PP.isMacroDefined("nil"))
NullValue = "nil";
@@ -501,12 +521,13 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
&S.Context.Idents.get("object_setClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectSetClass) {
- SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getLocEnd());
- S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) <<
- FixItHint::CreateInsertion(OIRE->getLocStart(), "object_setClass(") <<
- FixItHint::CreateReplacement(SourceRange(OIRE->getOpLoc(),
- AssignLoc), ",") <<
- FixItHint::CreateInsertion(RHSLocEnd, ")");
+ SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getEndLoc());
+ S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign)
+ << FixItHint::CreateInsertion(OIRE->getBeginLoc(),
+ "object_setClass(")
+ << FixItHint::CreateReplacement(
+ SourceRange(OIRE->getOpLoc(), AssignLoc), ",")
+ << FixItHint::CreateInsertion(RHSLocEnd, ")");
}
else
S.Diag(OIRE->getLocation(), diag::warn_objc_isa_assign);
@@ -516,11 +537,11 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
&S.Context.Idents.get("object_getClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectGetClass)
- S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use) <<
- FixItHint::CreateInsertion(OIRE->getLocStart(), "object_getClass(") <<
- FixItHint::CreateReplacement(
- SourceRange(OIRE->getOpLoc(),
- OIRE->getLocEnd()), ")");
+ S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use)
+ << FixItHint::CreateInsertion(OIRE->getBeginLoc(),
+ "object_getClass(")
+ << FixItHint::CreateReplacement(
+ SourceRange(OIRE->getOpLoc(), OIRE->getEndLoc()), ")");
else
S.Diag(OIRE->getLocation(), diag::warn_objc_isa_use);
}
@@ -575,10 +596,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
&Context.Idents.get("object_getClass"),
SourceLocation(), LookupOrdinaryName);
if (ObjectGetClass)
- Diag(E->getExprLoc(), diag::warn_objc_isa_use) <<
- FixItHint::CreateInsertion(OISA->getLocStart(), "object_getClass(") <<
- FixItHint::CreateReplacement(
- SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")");
+ Diag(E->getExprLoc(), diag::warn_objc_isa_use)
+ << FixItHint::CreateInsertion(OISA->getBeginLoc(), "object_getClass(")
+ << FixItHint::CreateReplacement(
+ SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")");
else
Diag(E->getExprLoc(), diag::warn_objc_isa_use);
}
@@ -717,20 +738,33 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
return ExprError();
E = Res.get();
+ QualType ScalarTy = Ty;
+ unsigned NumElts = 0;
+ if (const ExtVectorType *VecTy = Ty->getAs<ExtVectorType>()) {
+ NumElts = VecTy->getNumElements();
+ ScalarTy = VecTy->getElementType();
+ }
+
// If this is a 'float' or '__fp16' (CVR qualified or typedef)
// promote to double.
// Note that default argument promotion applies only to float (and
// half/fp16); it does not apply to _Float16.
- const BuiltinType *BTy = Ty->getAs<BuiltinType>();
+ const BuiltinType *BTy = ScalarTy->getAs<BuiltinType>();
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float)) {
if (getLangOpts().OpenCL &&
!getOpenCLOptions().isEnabled("cl_khr_fp64")) {
- if (BTy->getKind() == BuiltinType::Half) {
- E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
- }
+ if (BTy->getKind() == BuiltinType::Half) {
+ QualType Ty = Context.FloatTy;
+ if (NumElts != 0)
+ Ty = Context.getExtVectorType(Ty, NumElts);
+ E = ImpCastExprToType(E, Ty, CK_FloatingCast).get();
+ }
} else {
- E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
+ QualType Ty = Context.DoubleTy;
+ if (NumElts != 0)
+ Ty = Context.getExtVectorType(Ty, NumElts);
+ E = ImpCastExprToType(E, Ty, CK_FloatingCast).get();
}
}
@@ -819,40 +853,38 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
switch (VAK) {
case VAK_ValidInCXX11:
DiagRuntimeBehavior(
- E->getLocStart(), nullptr,
- PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
- << Ty << CT);
+ E->getBeginLoc(), nullptr,
+ PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) << Ty << CT);
LLVM_FALLTHROUGH;
case VAK_Valid:
if (Ty->isRecordType()) {
// This is unlikely to be what the user intended. If the class has a
// 'c_str' member function, the user probably meant to call that.
- DiagRuntimeBehavior(E->getLocStart(), nullptr,
+ DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
PDiag(diag::warn_pass_class_arg_to_vararg)
- << Ty << CT << hasCStrMethod(E) << ".c_str()");
+ << Ty << CT << hasCStrMethod(E) << ".c_str()");
}
break;
case VAK_Undefined:
case VAK_MSVCUndefined:
- DiagRuntimeBehavior(
- E->getLocStart(), nullptr,
- PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << getLangOpts().CPlusPlus11 << Ty << CT);
+ DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
+ PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+ << getLangOpts().CPlusPlus11 << Ty << CT);
break;
case VAK_Invalid:
if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
- Diag(E->getLocStart(),
- diag::err_cannot_pass_non_trivial_c_struct_to_vararg) << Ty << CT;
+ Diag(E->getBeginLoc(),
+ diag::err_cannot_pass_non_trivial_c_struct_to_vararg)
+ << Ty << CT;
else if (Ty->isObjCObjectType())
- DiagRuntimeBehavior(
- E->getLocStart(), nullptr,
- PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
- << Ty << CT);
+ DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
+ PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+ << Ty << CT);
else
- Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg)
- << isa<InitListExpr>(E) << Ty << CT;
+ Diag(E->getBeginLoc(), diag::err_cannot_pass_to_vararg)
+ << isa<InitListExpr>(E) << Ty << CT;
break;
}
}
@@ -890,20 +922,19 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
- E->getLocStart());
+ E->getBeginLoc());
ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc,
Name, true, false);
if (TrapFn.isInvalid())
return ExprError();
- ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(),
- E->getLocStart(), None,
- E->getLocEnd());
+ ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getBeginLoc(),
+ None, E->getEndLoc());
if (Call.isInvalid())
return ExprError();
- ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma,
- Call.get(), E);
+ ExprResult Comma =
+ ActOnBinOp(TUScope, E->getBeginLoc(), tok::comma, Call.get(), E);
if (Comma.isInvalid())
return ExprError();
return Comma.get();
@@ -1436,9 +1467,9 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
// We strip parens here because the controlling expression is typically
// parenthesized in macro definitions.
ControllingExpr = ControllingExpr->IgnoreParens();
- Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
- << ControllingExpr->getSourceRange() << ControllingExpr->getType()
- << (unsigned) CompatIndices.size();
+ Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_multi_match)
+ << ControllingExpr->getSourceRange() << ControllingExpr->getType()
+ << (unsigned)CompatIndices.size();
for (unsigned I : CompatIndices) {
Diag(Types[I]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
@@ -1455,8 +1486,8 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
// We strip parens here because the controlling expression is typically
// parenthesized in macro definitions.
ControllingExpr = ControllingExpr->IgnoreParens();
- Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match)
- << ControllingExpr->getSourceRange() << ControllingExpr->getType();
+ Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_no_match)
+ << ControllingExpr->getSourceRange() << ControllingExpr->getType();
return ExprError();
}
@@ -1549,6 +1580,32 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
CharTy = Context.UnsignedCharTy;
}
+ // Warn on initializing an array of char from a u8 string literal; this
+ // becomes ill-formed in C++2a.
+ if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus2a &&
+ !getLangOpts().Char8 && Kind == StringLiteral::UTF8) {
+ Diag(StringTokLocs.front(), diag::warn_cxx2a_compat_utf8_string);
+
+ // Create removals for all 'u8' prefixes in the string literal(s). This
+ // ensures C++2a compatibility (but may change the program behavior when
+ // built by non-Clang compilers for which the execution character set is
+ // not always UTF-8).
+ auto RemovalDiag = PDiag(diag::note_cxx2a_compat_utf8_string_remove_u8);
+ SourceLocation RemovalDiagLoc;
+ for (const Token &Tok : StringToks) {
+ if (Tok.getKind() == tok::utf8_string_literal) {
+ if (RemovalDiagLoc.isInvalid())
+ RemovalDiagLoc = Tok.getLocation();
+ RemovalDiag << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ Tok.getLocation(),
+ Lexer::AdvanceToTokenCharacter(Tok.getLocation(), 2,
+ getSourceManager(), getLangOpts())));
+ }
+ }
+ Diag(RemovalDiagLoc, RemovalDiag);
+ }
+
+
QualType CharTyConst = CharTy;
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
@@ -1681,7 +1738,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() &&
- !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getBeginLoc()))
getCurFunction()->recordUseOfWeak(E);
FieldDecl *FD = dyn_cast<FieldDecl>(D);
@@ -2528,7 +2585,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
if (Method->isStatic())
return From;
- DestType = Method->getThisType(Context);
+ DestType = Method->getThisType();
DestRecordType = DestType->getPointeeType();
if (FromType->getAs<PointerType>()) {
@@ -3026,7 +3083,7 @@ static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
}
ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
- PredefinedExpr::IdentType IT) {
+ PredefinedExpr::IdentKind IK) {
// Pick the current block, lambda, captured statement or function.
Decl *currentDecl = nullptr;
if (const BlockScopeInfo *BSI = getCurBlock())
@@ -3050,11 +3107,11 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
else {
// Pre-defined identifiers are of type char[x], where x is the length of
// the string.
- auto Str = PredefinedExpr::ComputeName(IT, currentDecl);
+ auto Str = PredefinedExpr::ComputeName(IK, currentDecl);
unsigned Length = Str.length();
llvm::APInt LengthI(32, Length + 1);
- if (IT == PredefinedExpr::LFunction || IT == PredefinedExpr::LFuncSig) {
+ if (IK == PredefinedExpr::LFunction || IK == PredefinedExpr::LFuncSig) {
ResTy =
Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst());
SmallString<32> RawChars;
@@ -3073,24 +3130,24 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
}
}
- return new (Context) PredefinedExpr(Loc, ResTy, IT, SL);
+ return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL);
}
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
- PredefinedExpr::IdentType IT;
+ PredefinedExpr::IdentKind IK;
switch (Kind) {
default: llvm_unreachable("Unknown simple primary expr!");
- case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
- case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
- case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
- case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS]
- case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; // [MS]
- case tok::kw_L__FUNCSIG__: IT = PredefinedExpr::LFuncSig; break; // [MS]
- case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
+ case tok::kw___func__: IK = PredefinedExpr::Func; break; // [C99 6.4.2.2]
+ case tok::kw___FUNCTION__: IK = PredefinedExpr::Function; break;
+ case tok::kw___FUNCDNAME__: IK = PredefinedExpr::FuncDName; break; // [MS]
+ case tok::kw___FUNCSIG__: IK = PredefinedExpr::FuncSig; break; // [MS]
+ case tok::kw_L__FUNCTION__: IK = PredefinedExpr::LFunction; break; // [MS]
+ case tok::kw_L__FUNCSIG__: IK = PredefinedExpr::LFuncSig; break; // [MS]
+ case tok::kw___PRETTY_FUNCTION__: IK = PredefinedExpr::PrettyFunction; break;
}
- return BuildPredefinedExpr(Loc, IT);
+ return BuildPredefinedExpr(Loc, IK);
}
ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
@@ -3363,16 +3420,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
bool isSigned = !Literal.isUnsigned;
unsigned scale = Context.getFixedPointScale(Ty);
- unsigned ibits = Context.getFixedPointIBits(Ty);
unsigned bit_width = Context.getTypeInfo(Ty).Width;
llvm::APInt Val(bit_width, 0, isSigned);
bool Overflowed = Literal.GetFixedPointValue(Val, scale);
+ bool ValIsZero = Val.isNullValue() && !Overflowed;
- // Do not use bit_width since some types may have padding like _Fract or
- // unsigned _Accums if PaddingOnUnsignedFixedPoint is set.
- auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width);
- if (Literal.isFract && Val == MaxVal + 1)
+ auto MaxVal = Context.getFixedPointMax(Ty).getValue();
+ if (Literal.isFract && Val == MaxVal + 1 && !ValIsZero)
// Clause 6.4.4 - The value of a constant shall be in the range of
// representable values for its type, with exception for constants of a
// fract type with a value of exactly 1; such a constant shall denote
@@ -3588,7 +3643,8 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
// C99 6.5.3.4p1:
if (T->isFunctionType() &&
- (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) {
+ (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf ||
+ TraitKind == UETT_PreferredAlignOf)) {
// sizeof(function)/alignof(function) is allowed as an extension.
S.Diag(Loc, diag::ext_sizeof_alignof_function_type)
<< TraitKind << ArgRange;
@@ -3666,7 +3722,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
// the expression to be complete. 'sizeof' requires the expression's type to
// be complete (and will attempt to complete it if it's an array of unknown
// bound).
- if (ExprKind == UETT_AlignOf) {
+ if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
if (RequireCompleteType(E->getExprLoc(),
Context.getBaseElementType(E->getType()),
diag::err_sizeof_alignof_incomplete_type, ExprKind,
@@ -3690,7 +3746,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
// The operand for sizeof and alignof is in an unevaluated expression context,
// so side effects could result in unintended consequences.
- if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) &&
+ if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
+ ExprKind == UETT_PreferredAlignOf) &&
!inTemplateInstantiation() && E->HasSideEffects(Context, false))
Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
@@ -3759,7 +3816,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
// C11 6.5.3.4/3, C++11 [expr.alignof]p3:
// When alignof or _Alignof is applied to an array type, the result
// is the alignment of the element type.
- if (ExprKind == UETT_AlignOf || ExprKind == UETT_OpenMPRequiredSimdAlign)
+ if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf ||
+ ExprKind == UETT_OpenMPRequiredSimdAlign)
ExprType = Context.getBaseElementType(ExprType);
if (ExprKind == UETT_VecStep)
@@ -3788,7 +3846,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
return false;
}
-static bool CheckAlignOfExpr(Sema &S, Expr *E) {
+static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) {
E = E->IgnoreParens();
// Cannot know anything else if the expression is dependent.
@@ -3842,7 +3900,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) {
return false;
}
- return S.CheckUnaryExprOrTypeTraitOperand(E, UETT_AlignOf);
+ return S.CheckUnaryExprOrTypeTraitOperand(E, ExprKind);
}
bool Sema::CheckVecStepExpr(Expr *E) {
@@ -4038,8 +4096,8 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
bool isInvalid = false;
if (E->isTypeDependent()) {
// Delay type-checking for type-dependent expressions.
- } else if (ExprKind == UETT_AlignOf) {
- isInvalid = CheckAlignOfExpr(*this, E);
+ } else if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
+ isInvalid = CheckAlignOfExpr(*this, E, ExprKind);
} else if (ExprKind == UETT_VecStep) {
isInvalid = CheckVecStepExpr(E);
} else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {
@@ -4238,7 +4296,57 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, idx);
}
- return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);
+ ExprResult Res = CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);
+
+ if (!Res.isInvalid() && isa<ArraySubscriptExpr>(Res.get()))
+ CheckSubscriptAccessOfNoDeref(cast<ArraySubscriptExpr>(Res.get()));
+
+ return Res;
+}
+
+void Sema::CheckAddressOfNoDeref(const Expr *E) {
+ ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back();
+ const Expr *StrippedExpr = E->IgnoreParenImpCasts();
+
+ // For expressions like `&(*s).b`, the base is recorded and what should be
+ // checked.
+ const MemberExpr *Member = nullptr;
+ while ((Member = dyn_cast<MemberExpr>(StrippedExpr)) && !Member->isArrow())
+ StrippedExpr = Member->getBase()->IgnoreParenImpCasts();
+
+ LastRecord.PossibleDerefs.erase(StrippedExpr);
+}
+
+void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
+ QualType ResultTy = E->getType();
+ ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back();
+
+ // Bail if the element is an array since it is not memory access.
+ if (isa<ArrayType>(ResultTy))
+ return;
+
+ if (ResultTy->hasAttr(attr::NoDeref)) {
+ LastRecord.PossibleDerefs.insert(E);
+ return;
+ }
+
+ // Check if the base type is a pointer to a member access of a struct
+ // marked with noderef.
+ const Expr *Base = E->getBase();
+ QualType BaseTy = Base->getType();
+ if (!(isa<ArrayType>(BaseTy) || isa<PointerType>(BaseTy)))
+ // Not a pointer access
+ return;
+
+ const MemberExpr *Member = nullptr;
+ while ((Member = dyn_cast<MemberExpr>(Base->IgnoreParenCasts())) &&
+ Member->isArrow())
+ Base = Member->getBase();
+
+ if (const auto *Ptr = dyn_cast<PointerType>(Base->getType())) {
+ if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
+ LastRecord.PossibleDerefs.insert(E);
+ }
}
ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
@@ -4339,10 +4447,11 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
return ExprError();
if (LowerBound && !OriginalTy->isAnyPointerType()) {
- llvm::APSInt LowerBoundValue;
- if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) {
+ Expr::EvalResult Result;
+ if (LowerBound->EvaluateAsInt(Result, Context)) {
// OpenMP 4.5, [2.4 Array Sections]
// The array section must be a subset of the original array.
+ llvm::APSInt LowerBoundValue = Result.Val.getInt();
if (LowerBoundValue.isNegative()) {
Diag(LowerBound->getExprLoc(), diag::err_omp_section_not_subset_of_array)
<< LowerBound->getSourceRange();
@@ -4352,10 +4461,11 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
}
if (Length) {
- llvm::APSInt LengthValue;
- if (Length->EvaluateAsInt(LengthValue, Context)) {
+ Expr::EvalResult Result;
+ if (Length->EvaluateAsInt(Result, Context)) {
// OpenMP 4.5, [2.4 Array Sections]
// The length must evaluate to non-negative integers.
+ llvm::APSInt LengthValue = Result.Val.getInt();
if (LengthValue.isNegative()) {
Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
<< LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
@@ -4488,8 +4598,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// wasn't promoted because of the C90 rule that doesn't
// allow promoting non-lvalue arrays. Warn, then
// force the promotion here.
- Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
- LHSExp->getSourceRange();
+ Diag(LHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue)
+ << LHSExp->getSourceRange();
LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
CK_ArrayToPointerDecay).get();
LHSTy = LHSExp->getType();
@@ -4499,8 +4609,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
ResultType = LHSTy->getAs<PointerType>()->getPointeeType();
} else if (RHSTy->isArrayType()) {
// Same as previous, except for 123[f().a] case
- Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
- RHSExp->getSourceRange();
+ Diag(RHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue)
+ << RHSExp->getSourceRange();
RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
CK_ArrayToPointerDecay).get();
RHSTy = RHSExp->getType();
@@ -4527,8 +4637,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// type. Note that Functions are not objects, and that (in C99 parlance)
// incomplete types are not object types.
if (ResultType->isFunctionType()) {
- Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type)
- << ResultType << BaseExpr->getSourceRange();
+ Diag(BaseExpr->getBeginLoc(), diag::err_subscript_function_type)
+ << ResultType << BaseExpr->getSourceRange();
return ExprError();
}
@@ -4594,7 +4704,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
if (Inst.isInvalid())
return true;
if (Inst.isAlreadyInstantiating()) {
- Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD;
+ Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
Param->setInvalidDecl();
return true;
}
@@ -4616,9 +4726,9 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
// Check the expression as an initializer for the parameter.
InitializedEntity Entity
= InitializedEntity::InitializeParameter(Context, Param);
- InitializationKind Kind
- = InitializationKind::CreateCopy(Param->getLocation(),
- /*FIXME:EqualLoc*/UninstExpr->getLocStart());
+ InitializationKind Kind = InitializationKind::CreateCopy(
+ Param->getLocation(),
+ /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc());
Expr *ResultE = Result.getAs<Expr>();
InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
@@ -4626,8 +4736,9 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
if (Result.isInvalid())
return true;
- Result = ActOnFinishFullExpr(Result.getAs<Expr>(),
- Param->getOuterLocStart());
+ Result =
+ ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(),
+ /*DiscardedValue*/ false);
if (Result.isInvalid())
return true;
@@ -4640,7 +4751,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
// If the default argument expression is not set yet, we are building it now.
if (!Param->hasInit()) {
- Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD;
+ Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
Param->setInvalidDecl();
return true;
}
@@ -4725,7 +4836,7 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
ArrayRef<Expr *> Args) {
MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
DeclarationName FuncName = FDecl->getDeclName();
- SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getLocStart();
+ SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getBeginLoc();
if (TypoCorrection Corrected = S.CorrectTypo(
DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName,
@@ -4816,12 +4927,14 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
- Diag(FDecl->getLocStart(), diag::note_callee_decl)
- << FDecl;
+ Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl;
return true;
}
- Call->setNumArgs(Context, NumParams);
+ // We reserve space for the default arguments when we create
+ // the call expression, before calling ConvertArgumentsForCall.
+ assert((Call->getNumArgs() == NumParams) &&
+ "We should have reserved space for the default arguments before!");
}
// If too many are passed and not variadic, error on the extras and drop
@@ -4839,39 +4952,38 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
<< TC.getCorrectionRange());
} else if (NumParams == 1 && FDecl &&
FDecl->getParamDecl(0)->getDeclName())
- Diag(Args[NumParams]->getLocStart(),
+ Diag(Args[NumParams]->getBeginLoc(),
MinArgs == NumParams
? diag::err_typecheck_call_too_many_args_one
: diag::err_typecheck_call_too_many_args_at_most_one)
<< FnKind << FDecl->getParamDecl(0)
<< static_cast<unsigned>(Args.size()) << Fn->getSourceRange()
- << SourceRange(Args[NumParams]->getLocStart(),
- Args.back()->getLocEnd());
+ << SourceRange(Args[NumParams]->getBeginLoc(),
+ Args.back()->getEndLoc());
else
- Diag(Args[NumParams]->getLocStart(),
+ Diag(Args[NumParams]->getBeginLoc(),
MinArgs == NumParams
? diag::err_typecheck_call_too_many_args
: diag::err_typecheck_call_too_many_args_at_most)
<< FnKind << NumParams << static_cast<unsigned>(Args.size())
<< Fn->getSourceRange()
- << SourceRange(Args[NumParams]->getLocStart(),
- Args.back()->getLocEnd());
+ << SourceRange(Args[NumParams]->getBeginLoc(),
+ Args.back()->getEndLoc());
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
- Diag(FDecl->getLocStart(), diag::note_callee_decl)
- << FDecl;
+ Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl;
// This deletes the extra arguments.
- Call->setNumArgs(Context, NumParams);
+ Call->shrinkNumArgs(NumParams);
return true;
}
}
SmallVector<Expr *, 8> AllArgs;
VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn);
- Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl,
- Proto, 0, Args, AllArgs, CallType);
+ Invalid = GatherArgumentsForCall(Call->getBeginLoc(), FDecl, Proto, 0, Args,
+ AllArgs, CallType);
if (Invalid)
return true;
unsigned TotalNumArgs = AllArgs.size();
@@ -4899,8 +5011,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
if (ArgIx < Args.size()) {
Arg = Args[ArgIx++];
- if (RequireCompleteType(Arg->getLocStart(),
- ProtoArgType,
+ if (RequireCompleteType(Arg->getBeginLoc(), ProtoArgType,
diag::err_call_incomplete_argument, Arg))
return true;
@@ -5058,6 +5169,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
#define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
#define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
#include "clang/AST/BuiltinTypes.def"
@@ -5153,10 +5267,13 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
continue;
}
+ QualType PointeeType = ParamType->getPointeeType();
+ if (PointeeType.getQualifiers().hasAddressSpace())
+ continue;
+
NeedsNewDecl = true;
LangAS AS = ArgType->getPointeeType().getAddressSpace();
- QualType PointeeType = ParamType->getPointeeType();
PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
OverloadParams.push_back(Context.getPointerType(PointeeType));
}
@@ -5205,7 +5322,7 @@ static void checkDirectCallValidity(Sema &S, const Expr *Fn,
return;
if (const EnableIfAttr *Attr = S.CheckEnableIf(Callee, ArgExprs, true)) {
- S.Diag(Fn->getLocStart(),
+ S.Diag(Fn->getBeginLoc(),
isa<CXXMethodDecl>(Callee)
? diag::err_ovl_no_viable_member_function_in_call
: diag::err_ovl_no_viable_function_in_call)
@@ -5317,14 +5434,14 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (isa<CXXPseudoDestructorExpr>(Fn)) {
if (!ArgExprs.empty()) {
// Pseudo-destructor calls should not have any arguments.
- Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
+ Diag(Fn->getBeginLoc(), diag::err_pseudo_dtor_call_with_args)
<< FixItHint::CreateRemoval(
- SourceRange(ArgExprs.front()->getLocStart(),
- ArgExprs.back()->getLocEnd()));
+ SourceRange(ArgExprs.front()->getBeginLoc(),
+ ArgExprs.back()->getEndLoc()));
}
- return new (Context)
- CallExpr(Context, Fn, None, Context.VoidTy, VK_RValue, RParenLoc);
+ return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy,
+ VK_RValue, RParenLoc);
}
if (Fn->getType() == Context.PseudoObjectTy) {
ExprResult result = CheckPlaceholderExpr(Fn);
@@ -5334,25 +5451,19 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
// Determine whether this is a dependent call inside a C++ template,
// in which case we won't do any semantic analysis now.
- bool Dependent = false;
- if (Fn->isTypeDependent())
- Dependent = true;
- else if (Expr::hasAnyTypeDependentArguments(ArgExprs))
- Dependent = true;
-
- if (Dependent) {
+ if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs)) {
if (ExecConfig) {
- return new (Context) CUDAKernelCallExpr(
+ return CUDAKernelCallExpr::Create(
Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs,
Context.DependentTy, VK_RValue, RParenLoc);
} else {
- tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
+ tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
*this, dyn_cast<UnresolvedMemberExpr>(Fn->IgnoreParens()),
- Fn->getLocStart());
+ Fn->getBeginLoc());
- return new (Context) CallExpr(
- Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc);
+ return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
+ VK_RValue, RParenLoc);
}
}
@@ -5380,8 +5491,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
// We aren't supposed to apply this logic if there's an '&' involved.
if (!find.HasFormOfMemberPointer) {
if (Expr::hasAnyTypeDependentArguments(ArgExprs))
- return new (Context) CallExpr(
- Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc);
+ return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
+ VK_RValue, RParenLoc);
OverloadExpr *ovl = find.Expression;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
return BuildOverloadedCallExpr(
@@ -5430,9 +5541,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) {
- if (CallingNDeclIndirectly &&
- !checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
- Fn->getLocStart()))
+ if (CallingNDeclIndirectly && !checkAddressOfFunctionIsAvailable(
+ FD, /*Complain=*/true, Fn->getBeginLoc()))
return ExprError();
if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn))
@@ -5484,12 +5594,11 @@ ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
/// block-pointer type.
///
/// \param NDecl the declaration being called, if available
-ExprResult
-Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
- SourceLocation LParenLoc,
- ArrayRef<Expr *> Args,
- SourceLocation RParenLoc,
- Expr *Config, bool IsExecConfig) {
+ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc, Expr *Config,
+ bool IsExecConfig, ADLCallKind UsesADL) {
FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
@@ -5514,28 +5623,71 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// We special-case function promotion here because we only allow promoting
// builtin functions to function pointers in the callee of a call.
ExprResult Result;
+ QualType ResultTy;
if (BuiltinID &&
Fn->getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)) {
- Result = ImpCastExprToType(Fn, Context.getPointerType(FDecl->getType()),
- CK_BuiltinFnToFnPtr).get();
+ // Extract the return type from the (builtin) function pointer type.
+ // FIXME Several builtins still have setType in
+ // Sema::CheckBuiltinFunctionCall. One should review their definitions in
+ // Builtins.def to ensure they are correct before removing setType calls.
+ QualType FnPtrTy = Context.getPointerType(FDecl->getType());
+ Result = ImpCastExprToType(Fn, FnPtrTy, CK_BuiltinFnToFnPtr).get();
+ ResultTy = FDecl->getCallResultType();
} else {
Result = CallExprUnaryConversions(Fn);
+ ResultTy = Context.BoolTy;
}
if (Result.isInvalid())
return ExprError();
Fn = Result.get();
- // Make the call expr early, before semantic checks. This guarantees cleanup
- // of arguments and function on error.
+ // Check for a valid function type, but only if it is not a builtin which
+ // requires custom type checking. These will be handled by
+ // CheckBuiltinFunctionCall below just after creation of the call expression.
+ const FunctionType *FuncT = nullptr;
+ if (!BuiltinID || !Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) {
+ retry:
+ if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
+ // C99 6.5.2.2p1 - "The expression that denotes the called function shall
+ // have type pointer to function".
+ FuncT = PT->getPointeeType()->getAs<FunctionType>();
+ if (!FuncT)
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ } else if (const BlockPointerType *BPT =
+ Fn->getType()->getAs<BlockPointerType>()) {
+ FuncT = BPT->getPointeeType()->castAs<FunctionType>();
+ } else {
+ // Handle calls to expressions of unknown-any type.
+ if (Fn->getType() == Context.UnknownAnyTy) {
+ ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
+ if (rewrite.isInvalid()) return ExprError();
+ Fn = rewrite.get();
+ goto retry;
+ }
+
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ }
+ }
+
+ // Get the number of parameters in the function prototype, if any.
+ // We will allocate space for max(Args.size(), NumParams) arguments
+ // in the call expression.
+ const auto *Proto = dyn_cast_or_null<FunctionProtoType>(FuncT);
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
+
CallExpr *TheCall;
- if (Config)
- TheCall = new (Context) CUDAKernelCallExpr(Context, Fn,
- cast<CallExpr>(Config), Args,
- Context.BoolTy, VK_RValue,
- RParenLoc);
- else
- TheCall = new (Context) CallExpr(Context, Fn, Args, Context.BoolTy,
- VK_RValue, RParenLoc);
+ if (Config) {
+ assert(UsesADL == ADLCallKind::NotADL &&
+ "CUDAKernelCallExpr should not use ADL");
+ TheCall =
+ CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), Args,
+ ResultTy, VK_RValue, RParenLoc, NumParams);
+ } else {
+ TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
+ RParenLoc, NumParams, UsesADL);
+ }
if (!getLangOpts().CPlusPlus) {
// C cannot always handle TypoExpr nodes in builtin calls and direct
@@ -5546,39 +5698,16 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (!Result.isUsable()) return ExprError();
TheCall = dyn_cast<CallExpr>(Result.get());
if (!TheCall) return Result;
- Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
+ // TheCall at this point has max(Args.size(), NumParams) arguments,
+ // with extra arguments nulled. We don't want to introduce nulled
+ // arguments in Args and so we only take the first Args.size() arguments.
+ Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size());
}
- // Bail out early if calling a builtin with custom typechecking.
+ // Bail out early if calling a builtin with custom type checking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
- retry:
- const FunctionType *FuncT;
- if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
- // C99 6.5.2.2p1 - "The expression that denotes the called function shall
- // have type pointer to function".
- FuncT = PT->getPointeeType()->getAs<FunctionType>();
- if (!FuncT)
- return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
- } else if (const BlockPointerType *BPT =
- Fn->getType()->getAs<BlockPointerType>()) {
- FuncT = BPT->getPointeeType()->castAs<FunctionType>();
- } else {
- // Handle calls to expressions of unknown-any type.
- if (Fn->getType() == Context.UnknownAnyTy) {
- ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
- if (rewrite.isInvalid()) return ExprError();
- Fn = rewrite.get();
- TheCall->setCallee(Fn);
- goto retry;
- }
-
- return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
- }
-
if (getLangOpts().CUDA) {
if (Config) {
// CUDA: Kernel calls must be to global functions
@@ -5599,7 +5728,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
}
// Check for a valid return type
- if (CheckCallReturnType(FuncT->getReturnType(), Fn->getLocStart(), TheCall,
+ if (CheckCallReturnType(FuncT->getReturnType(), Fn->getBeginLoc(), TheCall,
FDecl))
return ExprError();
@@ -5607,7 +5736,6 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
TheCall->setType(FuncT->getCallResultType(Context));
TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType()));
- const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
if (Proto) {
if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc,
IsExecConfig))
@@ -5655,8 +5783,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
Arg = ArgE.getAs<Expr>();
}
- if (RequireCompleteType(Arg->getLocStart(),
- Arg->getType(),
+ if (RequireCompleteType(Arg->getBeginLoc(), Arg->getType(),
diag::err_call_incomplete_argument, Arg))
return ExprError();
@@ -5739,13 +5866,6 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
LiteralExpr = Result.get();
bool isFileScope = !CurContext->isFunctionOrMethod();
- if (isFileScope &&
- !LiteralExpr->isTypeDependent() &&
- !LiteralExpr->isValueDependent() &&
- !literalType->isDependentType()) { // 6.5.2.5p3
- if (CheckForConstantInitializer(LiteralExpr, literalType))
- return ExprError();
- }
// In C, compound literals are l-values for some reason.
// For GCC compatibility, in C++, file-scope array compound literals with
@@ -5770,9 +5890,32 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
? VK_RValue
: VK_LValue;
- return MaybeBindToTemporary(
- new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
- VK, LiteralExpr, isFileScope));
+ if (isFileScope)
+ if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
+ for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
+ Expr *Init = ILE->getInit(i);
+ ILE->setInit(i, ConstantExpr::Create(Context, Init));
+ }
+
+ Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+ VK, LiteralExpr, isFileScope);
+ if (isFileScope) {
+ if (!LiteralExpr->isTypeDependent() &&
+ !LiteralExpr->isValueDependent() &&
+ !literalType->isDependentType()) // C99 6.5.2.5p3
+ if (CheckForConstantInitializer(LiteralExpr, literalType))
+ return ExprError();
+ } else if (literalType.getAddressSpace() != LangAS::opencl_private &&
+ literalType.getAddressSpace() != LangAS::Default) {
+ // Embedded-C extensions to C99 6.5.2.5:
+ // "If the compound literal occurs inside the body of a function, the
+ // type name shall not be qualified by an address-space qualifier."
+ Diag(LParenLoc, diag::err_compound_literal_with_address_space)
+ << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd());
+ return ExprError();
+ }
+
+ return MaybeBindToTemporary(E);
}
ExprResult
@@ -5854,6 +5997,8 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
LangAS DestAS = DestTy->getPointeeType().getAddressSpace();
if (SrcAS != DestAS)
return CK_AddressSpaceConversion;
+ if (Context.hasCvrSimilarType(SrcTy, DestTy))
+ return CK_NoOp;
return CK_BitCast;
}
case Type::STK_BlockPointer:
@@ -5874,10 +6019,33 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
case Type::STK_FloatingComplex:
case Type::STK_IntegralComplex:
case Type::STK_MemberPointer:
+ case Type::STK_FixedPoint:
llvm_unreachable("illegal cast from pointer");
}
llvm_unreachable("Should have returned before this");
+ case Type::STK_FixedPoint:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_FixedPoint:
+ return CK_FixedPointCast;
+ case Type::STK_Bool:
+ return CK_FixedPointToBoolean;
+ case Type::STK_Integral:
+ case Type::STK_Floating:
+ case Type::STK_IntegralComplex:
+ case Type::STK_FloatingComplex:
+ Diag(Src.get()->getExprLoc(),
+ diag::err_unimplemented_conversion_with_fixed_point_type)
+ << DestTy;
+ return CK_IntegralCast;
+ case Type::STK_CPointer:
+ case Type::STK_ObjCObjectPointer:
+ case Type::STK_BlockPointer:
+ case Type::STK_MemberPointer:
+ llvm_unreachable("illegal cast to pointer type");
+ }
+ llvm_unreachable("Should have returned before this");
+
case Type::STK_Bool: // casting from bool is like casting from an integer
case Type::STK_Integral:
switch (DestTy->getScalarTypeKind()) {
@@ -5906,6 +6074,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
return CK_FloatingRealToComplex;
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
+ case Type::STK_FixedPoint:
+ Diag(Src.get()->getExprLoc(),
+ diag::err_unimplemented_conversion_with_fixed_point_type)
+ << SrcTy;
+ return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
@@ -5933,6 +6106,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
llvm_unreachable("valid float->pointer cast?");
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
+ case Type::STK_FixedPoint:
+ Diag(Src.get()->getExprLoc(),
+ diag::err_unimplemented_conversion_with_fixed_point_type)
+ << SrcTy;
+ return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
@@ -5962,6 +6140,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
llvm_unreachable("valid complex float->pointer cast?");
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
+ case Type::STK_FixedPoint:
+ Diag(Src.get()->getExprLoc(),
+ diag::err_unimplemented_conversion_with_fixed_point_type)
+ << SrcTy;
+ return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
@@ -5991,6 +6174,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
llvm_unreachable("valid complex int->pointer cast?");
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
+ case Type::STK_FixedPoint:
+ Diag(Src.get()->getExprLoc(),
+ diag::err_unimplemented_conversion_with_fixed_point_type)
+ << SrcTy;
+ return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
}
@@ -6323,8 +6511,7 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
ExprResult Sema::ActOnParenListExpr(SourceLocation L,
SourceLocation R,
MultiExprArg Val) {
- Expr *expr = new (Context) ParenListExpr(Context, L, Val, R);
- return expr;
+ return ParenListExpr::Create(Context, L, Val, R);
}
/// Emit a specialized diagnostic when one expression is a null pointer
@@ -6394,11 +6581,11 @@ static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
Expr *RHSExpr = RHS.get();
if (!LHSExpr->getType()->isVoidType())
- S.Diag(RHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void)
- << RHSExpr->getSourceRange();
+ S.Diag(RHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void)
+ << RHSExpr->getSourceRange();
if (!RHSExpr->getType()->isVoidType())
- S.Diag(LHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void)
- << LHSExpr->getSourceRange();
+ S.Diag(LHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void)
+ << LHSExpr->getSourceRange();
LHS = S.ImpCastExprToType(LHS.get(), S.Context.VoidTy, CK_ToVoid);
RHS = S.ImpCastExprToType(RHS.get(), S.Context.VoidTy, CK_ToVoid);
return S.Context.VoidTy;
@@ -6458,20 +6645,18 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
LangAS ResultAddrSpace = LangAS::Default;
LangAS LAddrSpace = lhQual.getAddressSpace();
LangAS RAddrSpace = rhQual.getAddressSpace();
- if (S.getLangOpts().OpenCL) {
- // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
- // spaces is disallowed.
- if (lhQual.isAddressSpaceSupersetOf(rhQual))
- ResultAddrSpace = LAddrSpace;
- else if (rhQual.isAddressSpaceSupersetOf(lhQual))
- ResultAddrSpace = RAddrSpace;
- else {
- S.Diag(Loc,
- diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
- << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
- return QualType();
- }
+
+ // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
+ // spaces is disallowed.
+ if (lhQual.isAddressSpaceSupersetOf(rhQual))
+ ResultAddrSpace = LAddrSpace;
+ else if (rhQual.isAddressSpaceSupersetOf(lhQual))
+ ResultAddrSpace = RAddrSpace;
+ else {
+ S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+ << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
+ return QualType();
}
unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
@@ -6489,16 +6674,12 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
// Thus for conditional operator we merge CVR and address space unqualified
// pointees and if there is a composite type we return a pointer to it with
// merged qualifiers.
- if (S.getLangOpts().OpenCL) {
- LHSCastKind = LAddrSpace == ResultAddrSpace
- ? CK_BitCast
- : CK_AddressSpaceConversion;
- RHSCastKind = RAddrSpace == ResultAddrSpace
- ? CK_BitCast
- : CK_AddressSpaceConversion;
- lhQual.removeAddressSpace();
- rhQual.removeAddressSpace();
- }
+ LHSCastKind =
+ LAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+ RHSCastKind =
+ RAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+ lhQual.removeAddressSpace();
+ rhQual.removeAddressSpace();
lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual);
rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual);
@@ -6514,6 +6695,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace));
LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind);
RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind);
+
// FIXME: For OpenCL the warning emission and cast to void* leaves a room
// for casts between types with incompatible address space qualifiers.
// For the following code the compiler produces casts between global and
@@ -6524,6 +6706,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
+
return incompatTy;
}
@@ -7219,14 +7402,15 @@ static void DiagnoseConditionalPrecedence(Sema &Self,
<< Condition->getSourceRange()
<< BinaryOperator::getOpcodeStr(CondOpcode);
- SuggestParentheses(Self, OpLoc,
- Self.PDiag(diag::note_precedence_silence)
- << BinaryOperator::getOpcodeStr(CondOpcode),
- SourceRange(Condition->getLocStart(), Condition->getLocEnd()));
+ SuggestParentheses(
+ Self, OpLoc,
+ Self.PDiag(diag::note_precedence_silence)
+ << BinaryOperator::getOpcodeStr(CondOpcode),
+ SourceRange(Condition->getBeginLoc(), Condition->getEndLoc()));
SuggestParentheses(Self, OpLoc,
- Self.PDiag(diag::note_precedence_conditional_first),
- SourceRange(CondRHS->getLocStart(), RHSExpr->getLocEnd()));
+ Self.PDiag(diag::note_precedence_conditional_first),
+ SourceRange(CondRHS->getBeginLoc(), RHSExpr->getEndLoc()));
}
/// Compute the nullability of a conditional expression.
@@ -7757,7 +7941,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (isa<PointerType>(RHSType)) {
LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace();
- Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
+ if (AddrSpaceL != AddrSpaceR)
+ Kind = CK_AddressSpaceConversion;
+ else if (Context.hasCvrSimilarType(RHSType, LHSType))
+ Kind = CK_NoOp;
+ else
+ Kind = CK_BitCast;
return checkPointerTypesForAssignment(*this, LHSType, RHSType);
}
@@ -7825,7 +8014,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
}
// id -> T^
- if (getLangOpts().ObjC1 && RHSType->isObjCIdType()) {
+ if (getLangOpts().ObjC && RHSType->isObjCIdType()) {
Kind = CK_AnyPointerToBlockPointerCast;
return Compatible;
}
@@ -8029,6 +8218,17 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
ExprResult LocalRHS = CallerRHS;
ExprResult &RHS = ConvertRHS ? CallerRHS : LocalRHS;
+ if (const auto *LHSPtrType = LHSType->getAs<PointerType>()) {
+ if (const auto *RHSPtrType = RHS.get()->getType()->getAs<PointerType>()) {
+ if (RHSPtrType->getPointeeType()->hasAttr(attr::NoDeref) &&
+ !LHSPtrType->getPointeeType()->hasAttr(attr::NoDeref)) {
+ Diag(RHS.get()->getExprLoc(),
+ diag::warn_noderef_to_dereferenceable_pointer)
+ << RHS.get()->getSourceRange();
+ }
+ }
+ }
+
if (getLangOpts().CPlusPlus) {
if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
// C++ 5.17p3: If the left operand is not of class type, the
@@ -8092,6 +8292,13 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
return Compatible;
}
+ // OpenCL queue_t type assignment.
+ if (LHSType->isQueueT() && RHS.get()->isNullPointerConstant(
+ Context, Expr::NPC_ValueDependentIsNull)) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
+ return Compatible;
+ }
+
// This check seems unnatural, however it is necessary to ensure the proper
// conversion of functions/arrays. If the conversion were done for all
// DeclExpr's (created by ActOnIdExpression), it would mess up the unary
@@ -8104,16 +8311,6 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
if (RHS.isInvalid())
return Incompatible;
}
-
- Expr *PRE = RHS.get()->IgnoreParenCasts();
- if (Diagnose && isa<ObjCProtocolExpr>(PRE)) {
- ObjCProtocolDecl *PDecl = cast<ObjCProtocolExpr>(PRE)->getProtocol();
- if (PDecl && !PDecl->hasDefinition()) {
- Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl;
- Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
- }
- }
-
CastKind Kind;
Sema::AssignConvertType result =
CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS);
@@ -8137,8 +8334,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
if (!Diagnose)
return Incompatible;
}
- if (getLangOpts().ObjC1 &&
- (CheckObjCBridgeRelatedConversions(E->getLocStart(), LHSType,
+ if (getLangOpts().ObjC &&
+ (CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType,
E->getType(), E, Diagnose) ||
ConversionToObjCStringLiteralCheck(LHSType, E, Diagnose))) {
if (!Diagnose)
@@ -8152,6 +8349,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
if (ConvertRHS)
RHS = ImpCastExprToType(E, Ty, Kind);
}
+
return result;
}
@@ -8314,8 +8512,8 @@ static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int,
// Reject cases where the value of the Int is unknown as that would
// possibly cause truncation, but accept cases where the scalar can be
// demoted without loss of precision.
- llvm::APSInt Result;
- bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context);
+ Expr::EvalResult EVResult;
+ bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context);
int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy);
bool IntSigned = IntTy->hasSignedIntegerRepresentation();
bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation();
@@ -8323,6 +8521,7 @@ static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int,
if (CstInt) {
// If the scalar is constant and is of a higher order and has more active
// bits that the vector element type, reject it.
+ llvm::APSInt Result = EVResult.Val.getInt();
unsigned NumBits = IntSigned
? (Result.isNegative() ? Result.getMinSignedBits()
: Result.getActiveBits())
@@ -8350,8 +8549,9 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int,
// Determine if the integer constant can be expressed as a floating point
// number of the appropriate type.
- llvm::APSInt Result;
- bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context);
+ Expr::EvalResult EVResult;
+ bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context);
+
uint64_t Bits = 0;
if (CstInt) {
// Reject constants that would be truncated if they were converted to
@@ -8359,6 +8559,7 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int,
// FIXME: Ideally the conversion to an APFloat and from an APFloat
// could be avoided if there was a convertFromAPInt method
// which could signal back if implicit truncation occurred.
+ llvm::APSInt Result = EVResult.Val.getInt();
llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy));
Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(),
llvm::APFloat::rmTowardZero);
@@ -8668,13 +8869,40 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
+static void DiagnoseDivisionSizeofPointer(Sema &S, Expr *LHS, Expr *RHS,
+ SourceLocation Loc) {
+ const auto *LUE = dyn_cast<UnaryExprOrTypeTraitExpr>(LHS);
+ const auto *RUE = dyn_cast<UnaryExprOrTypeTraitExpr>(RHS);
+ if (!LUE || !RUE)
+ return;
+ if (LUE->getKind() != UETT_SizeOf || LUE->isArgumentType() ||
+ RUE->getKind() != UETT_SizeOf)
+ return;
+
+ QualType LHSTy = LUE->getArgumentExpr()->IgnoreParens()->getType();
+ QualType RHSTy;
+
+ if (RUE->isArgumentType())
+ RHSTy = RUE->getArgumentType();
+ else
+ RHSTy = RUE->getArgumentExpr()->IgnoreParens()->getType();
+
+ if (!LHSTy->isPointerType() || RHSTy->isPointerType())
+ return;
+ if (LHSTy->getPointeeType() != RHSTy)
+ return;
+
+ S.Diag(Loc, diag::warn_division_sizeof_ptr) << LHS << LHS->getSourceRange();
+}
+
static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc, bool IsDiv) {
// Check for division/remainder by zero.
- llvm::APSInt RHSValue;
+ Expr::EvalResult RHSValue;
if (!RHS.get()->isValueDependent() &&
- RHS.get()->EvaluateAsInt(RHSValue, S.Context) && RHSValue == 0)
+ RHS.get()->EvaluateAsInt(RHSValue, S.Context) &&
+ RHSValue.Val.getInt() == 0)
S.DiagRuntimeBehavior(Loc, RHS.get(),
S.PDiag(diag::warn_remainder_division_by_zero)
<< IsDiv << RHS.get()->getSourceRange());
@@ -8698,8 +8926,10 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
if (compType.isNull() || !compType->isArithmeticType())
return InvalidOperands(Loc, LHS, RHS);
- if (IsDiv)
+ if (IsDiv) {
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
+ DiagnoseDivisionSizeofPointer(*this, LHS.get(), RHS.get(), Loc);
+ }
return compType;
}
@@ -8914,24 +9144,15 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
if (!IsStringPlusInt || IndexExpr->isValueDependent())
return;
- llvm::APSInt index;
- if (IndexExpr->EvaluateAsInt(index, Self.getASTContext())) {
- unsigned StrLenWithNull = StrExpr->getLength() + 1;
- if (index.isNonNegative() &&
- index <= llvm::APSInt(llvm::APInt(index.getBitWidth(), StrLenWithNull),
- index.isUnsigned()))
- return;
- }
-
- SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+ SourceRange DiagRange(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
Self.Diag(OpLoc, diag::warn_string_plus_int)
<< DiagRange << IndexExpr->IgnoreImpCasts()->getType();
// Only print a fixit for "str" + int, not for int + "str".
if (IndexExpr == RHSExpr) {
- SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getEndLoc());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
- << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
+ << FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
<< FixItHint::CreateInsertion(EndLoc, "]");
} else
@@ -8964,7 +9185,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
return;
ASTContext &Ctx = Self.getASTContext();
- SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+ SourceRange DiagRange(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
const QualType CharType = CharExpr->getType();
if (!CharType->isAnyCharacterType() &&
@@ -8979,9 +9200,9 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
// Only print a fixit for str + char, not for char + str.
if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) {
- SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getEndLoc());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
- << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
+ << FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
<< FixItHint::CreateInsertion(EndLoc, "]");
} else {
@@ -9059,10 +9280,11 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
if (PExp->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined.
- llvm::APSInt KnownVal;
+ Expr::EvalResult KnownVal;
if (!getLangOpts().CPlusPlus ||
(!IExp->isValueDependent() &&
- (!IExp->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) {
+ (!IExp->EvaluateAsInt(KnownVal, Context) ||
+ KnownVal.Val.getInt() != 0))) {
// Check the conditions to see if this is the 'p = nullptr + n' idiom.
bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension(
Context, BO_Add, PExp, IExp);
@@ -9137,10 +9359,11 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined.
- llvm::APSInt KnownVal;
+ Expr::EvalResult KnownVal;
if (!getLangOpts().CPlusPlus ||
(!RHS.get()->isValueDependent() &&
- (!RHS.get()->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) {
+ (!RHS.get()->EvaluateAsInt(KnownVal, Context) ||
+ KnownVal.Val.getInt() != 0))) {
diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false);
}
}
@@ -9216,11 +9439,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
if (S.getLangOpts().OpenCL)
return;
- llvm::APSInt Right;
// Check right/shifter operand
+ Expr::EvalResult RHSResult;
if (RHS.get()->isValueDependent() ||
- !RHS.get()->EvaluateAsInt(Right, S.Context))
+ !RHS.get()->EvaluateAsInt(RHSResult, S.Context))
return;
+ llvm::APSInt Right = RHSResult.Val.getInt();
if (Right.isNegative()) {
S.DiagRuntimeBehavior(Loc, RHS.get(),
@@ -9243,11 +9467,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
// according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned
// integers have defined behavior modulo one more than the maximum value
// representable in the result type, so never warn for those.
- llvm::APSInt Left;
+ Expr::EvalResult LHSResult;
if (LHS.get()->isValueDependent() ||
LHSType->hasUnsignedIntegerRepresentation() ||
- !LHS.get()->EvaluateAsInt(Left, S.Context))
+ !LHS.get()->EvaluateAsInt(LHSResult, S.Context))
return;
+ llvm::APSInt Left = LHSResult.Val.getInt();
// If LHS does not have a signed type and non-negative value
// then, the behavior is undefined. Warn about it.
@@ -9653,8 +9878,8 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
if (BinaryOperator::isEqualityOp(Opc) &&
hasIsEqualMethod(S, LHS.get(), RHS.get())) {
- SourceLocation Start = LHS.get()->getLocStart();
- SourceLocation End = S.getLocForEndOfToken(RHS.get()->getLocEnd());
+ SourceLocation Start = LHS.get()->getBeginLoc();
+ SourceLocation End = S.getLocForEndOfToken(RHS.get()->getEndLoc());
CharSourceRange OpRange =
CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
@@ -9686,8 +9911,8 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
<< Loc << IsBitwiseOp;
// First note suggest !(x < y)
- SourceLocation FirstOpen = SubExpr->getLocStart();
- SourceLocation FirstClose = RHS.get()->getLocEnd();
+ SourceLocation FirstOpen = SubExpr->getBeginLoc();
+ SourceLocation FirstClose = RHS.get()->getEndLoc();
FirstClose = S.getLocForEndOfToken(FirstClose);
if (FirstClose.isInvalid())
FirstOpen = SourceLocation();
@@ -9697,8 +9922,8 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
<< FixItHint::CreateInsertion(FirstClose, ")");
// Second note suggests (!x) < y
- SourceLocation SecondOpen = LHS.get()->getLocStart();
- SourceLocation SecondClose = LHS.get()->getLocEnd();
+ SourceLocation SecondOpen = LHS.get()->getBeginLoc();
+ SourceLocation SecondClose = LHS.get()->getEndLoc();
SecondClose = S.getLocForEndOfToken(SecondClose);
if (SecondClose.isInvalid())
SecondOpen = SourceLocation();
@@ -9734,7 +9959,7 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
QualType RHSType = RHS->getType();
if (LHSType->hasFloatingRepresentation() ||
(LHSType->isBlockPointerType() && !BinaryOperator::isEqualityOp(Opc)) ||
- LHS->getLocStart().isMacroID() || RHS->getLocStart().isMacroID() ||
+ LHS->getBeginLoc().isMacroID() || RHS->getBeginLoc().isMacroID() ||
S.inTemplateInstantiation())
return;
@@ -9888,7 +10113,7 @@ static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E,
case NK_Constant_Narrowing:
// Implicit conversion to a narrower type, and the value is not a constant
// expression.
- S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing)
+ S.Diag(E->getBeginLoc(), diag::err_spaceship_argument_narrowing)
<< /*Constant*/ 1
<< PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << ToType;
return true;
@@ -9897,7 +10122,7 @@ static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E,
// Implicit conversion to a narrower type, and the value is not a constant
// expression.
case NK_Type_Narrowing:
- S.Diag(E->getLocStart(), diag::err_spaceship_argument_narrowing)
+ S.Diag(E->getBeginLoc(), diag::err_spaceship_argument_narrowing)
<< /*Constant*/ 0 << FromType << ToType;
// TODO: It's not a constant expression, but what if the user intended it
// to be? Can we produce notes to help them figure out why it isn't?
@@ -9972,9 +10197,9 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
assert(Type->isArithmeticType() || Type->isEnumeralType());
bool HasNarrowing = checkThreeWayNarrowingConversion(
- S, Type, LHS.get(), LHSType, LHS.get()->getLocStart());
- HasNarrowing |= checkThreeWayNarrowingConversion(
- S, Type, RHS.get(), RHSType, RHS.get()->getLocStart());
+ S, Type, LHS.get(), LHSType, LHS.get()->getBeginLoc());
+ HasNarrowing |= checkThreeWayNarrowingConversion(S, Type, RHS.get(), RHSType,
+ RHS.get()->getBeginLoc());
if (HasNarrowing)
return QualType();
@@ -10439,6 +10664,14 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
if (getLangOpts().OpenCLVersion >= 200) {
+ if (LHSType->isClkEventT() && RHSType->isClkEventT()) {
+ return computeResultTy();
+ }
+
+ if (LHSType->isQueueT() && RHSType->isQueueT()) {
+ return computeResultTy();
+ }
+
if (LHSIsNull && RHSType->isQueueT()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return computeResultTy();
@@ -10609,8 +10842,9 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
// that isn't 0 or 1 (which indicate a potential logical operation that
// happened to fold to true/false) then warn.
// Parens on the RHS are ignored.
- llvm::APSInt Result;
- if (RHS.get()->EvaluateAsInt(Result, Context))
+ Expr::EvalResult EVResult;
+ if (RHS.get()->EvaluateAsInt(EVResult, Context)) {
+ llvm::APSInt Result = EVResult.Val.getInt();
if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() &&
!RHS.get()->getExprLoc().isMacroID()) ||
(Result != 0 && Result != 1)) {
@@ -10627,9 +10861,10 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
// Suggest replacing "Foo() && kNonZero" with "Foo()"
Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant)
<< FixItHint::CreateRemoval(
- SourceRange(getLocForEndOfToken(LHS.get()->getLocEnd()),
- RHS.get()->getLocEnd()));
+ SourceRange(getLocForEndOfToken(LHS.get()->getEndLoc()),
+ RHS.get()->getEndLoc()));
}
+ }
}
if (!Context.getLangOpts().CPlusPlus) {
@@ -10880,30 +11115,38 @@ static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD,
const RecordType *Ty,
SourceLocation Loc, SourceRange Range,
OriginalExprKind OEK,
- bool &DiagnosticEmitted,
- bool IsNested = false) {
+ bool &DiagnosticEmitted) {
+ std::vector<const RecordType *> RecordTypeList;
+ RecordTypeList.push_back(Ty);
+ unsigned NextToCheckIndex = 0;
// We walk the record hierarchy breadth-first to ensure that we print
// diagnostics in field nesting order.
- // First, check every field for constness.
- for (const FieldDecl *Field : Ty->getDecl()->fields()) {
- if (Field->getType().isConstQualified()) {
- if (!DiagnosticEmitted) {
- S.Diag(Loc, diag::err_typecheck_assign_const)
- << Range << NestedConstMember << OEK << VD
- << IsNested << Field;
- DiagnosticEmitted = true;
+ while (RecordTypeList.size() > NextToCheckIndex) {
+ bool IsNested = NextToCheckIndex > 0;
+ for (const FieldDecl *Field :
+ RecordTypeList[NextToCheckIndex]->getDecl()->fields()) {
+ // First, check every field for constness.
+ QualType FieldTy = Field->getType();
+ if (FieldTy.isConstQualified()) {
+ if (!DiagnosticEmitted) {
+ S.Diag(Loc, diag::err_typecheck_assign_const)
+ << Range << NestedConstMember << OEK << VD
+ << IsNested << Field;
+ DiagnosticEmitted = true;
+ }
+ S.Diag(Field->getLocation(), diag::note_typecheck_assign_const)
+ << NestedConstMember << IsNested << Field
+ << FieldTy << Field->getSourceRange();
+ }
+
+ // Then we append it to the list to check next in order.
+ FieldTy = FieldTy.getCanonicalType();
+ if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) {
+ if (llvm::find(RecordTypeList, FieldRecTy) == RecordTypeList.end())
+ RecordTypeList.push_back(FieldRecTy);
}
- S.Diag(Field->getLocation(), diag::note_typecheck_assign_const)
- << NestedConstMember << IsNested << Field
- << Field->getType() << Field->getSourceRange();
}
- }
- // Then, recurse.
- for (const FieldDecl *Field : Ty->getDecl()->fields()) {
- QualType FTy = Field->getType();
- if (const RecordType *FieldRecTy = FTy->getAs<RecordType>())
- DiagnoseRecursiveConstFields(S, VD, FieldRecTy, Loc, Range,
- OEK, DiagnosticEmitted, true);
+ ++NextToCheckIndex;
}
}
@@ -10971,17 +11214,23 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
if (var->isARCPseudoStrong() &&
(!var->getTypeSourceInfo() ||
!var->getTypeSourceInfo()->getType().isConstQualified())) {
- // There are two pseudo-strong cases:
+ // There are three pseudo-strong cases:
// - self
ObjCMethodDecl *method = S.getCurMethodDecl();
- if (method && var == method->getSelfDecl())
+ if (method && var == method->getSelfDecl()) {
DiagID = method->isClassMethod()
? diag::err_typecheck_arc_assign_self_class_method
: diag::err_typecheck_arc_assign_self;
+ // - Objective-C externally_retained attribute.
+ } else if (var->hasAttr<ObjCExternallyRetainedAttr>() ||
+ isa<ParmVarDecl>(var)) {
+ DiagID = diag::err_typecheck_arc_assign_externally_retained;
+
// - fast enumeration variables
- else
+ } else {
DiagID = diag::err_typecheck_arr_assign_enumeration;
+ }
SourceRange Assign;
if (Loc != OrigLoc)
@@ -11150,15 +11399,14 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
RHSCheck = ICE->getSubExpr();
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
- if ((UO->getOpcode() == UO_Plus ||
- UO->getOpcode() == UO_Minus) &&
+ if ((UO->getOpcode() == UO_Plus || UO->getOpcode() == UO_Minus) &&
Loc.isFileID() && UO->getOperatorLoc().isFileID() &&
// Only if the two operators are exactly adjacent.
Loc.getLocWithOffset(1) == UO->getOperatorLoc() &&
// And there is a space or other character before the subexpr of the
// unary +/-. We don't want to warn on "x=-1".
- Loc.getLocWithOffset(2) != UO->getSubExpr()->getLocStart() &&
- UO->getSubExpr()->getLocStart().isFileID()) {
+ Loc.getLocWithOffset(2) != UO->getSubExpr()->getBeginLoc() &&
+ UO->getSubExpr()->getBeginLoc().isFileID()) {
Diag(Loc, diag::warn_not_compound_assign)
<< (UO->getOpcode() == UO_Plus ? "+" : "-")
<< SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
@@ -11188,7 +11436,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
// For ObjCWeak only, we do not warn if the assign is to a non-weak
// variable, which will be valid for the current autorelease scope.
if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
- RHS.get()->getLocStart()))
+ RHS.get()->getBeginLoc()))
getCurFunction()->markSafeWeakUse(RHS.get());
} else if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) {
@@ -11225,6 +11473,12 @@ static bool IgnoreCommaOperand(const Expr *E) {
if (CE->getCastKind() == CK_ToVoid) {
return true;
}
+
+ // static_cast<void> on a dependent type will not show up as CK_ToVoid.
+ if (CE->getCastKind() == CK_Dependent && E->getType()->isVoidType() &&
+ CE->getSubExpr()->getType()->isDependentType()) {
+ return true;
+ }
}
return false;
@@ -11248,8 +11502,11 @@ void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) {
// The whitelisted locations are the initialization and increment portions
// of a for loop. The additional checks are on the condition of
// if statements, do/while loops, and for loops.
+ // Differences in scope flags for C89 mode requires the extra logic.
const unsigned ForIncrementFlags =
- Scope::ControlScope | Scope::ContinueScope | Scope::BreakScope;
+ getLangOpts().C99 || getLangOpts().CPlusPlus
+ ? Scope::ControlScope | Scope::ContinueScope | Scope::BreakScope
+ : Scope::ContinueScope | Scope::BreakScope;
const unsigned ForInitFlags = Scope::ControlScope | Scope::DeclScope;
const unsigned ScopeFlags = getCurScope()->getFlags();
if ((ScopeFlags & ForIncrementFlags) == ForIncrementFlags ||
@@ -11269,12 +11526,12 @@ void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) {
return;
Diag(Loc, diag::warn_comma_operator);
- Diag(LHS->getLocStart(), diag::note_cast_to_void)
+ Diag(LHS->getBeginLoc(), diag::note_cast_to_void)
<< LHS->getSourceRange()
- << FixItHint::CreateInsertion(LHS->getLocStart(),
+ << FixItHint::CreateInsertion(LHS->getBeginLoc(),
LangOpts.CPlusPlus ? "static_cast<void>("
: "(void)(")
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(LHS->getLocEnd()),
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(LHS->getEndLoc()),
")");
}
@@ -11551,7 +11808,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (auto *FD = dyn_cast_or_null<FunctionDecl>(dcl))
if (!checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
- op->getLocStart()))
+ op->getBeginLoc()))
return QualType();
Expr::LValueClassification lval = op->ClassifyLValue(Context);
@@ -11877,7 +12134,7 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
/// is usually indicative of introspection within the Objective-C pointer.
static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
SourceLocation OpLoc) {
- if (!S.getLangOpts().ObjC1)
+ if (!S.getLangOpts().ObjC)
return;
const Expr *ObjCPointerExpr = nullptr, *OtherExpr = nullptr;
@@ -12006,7 +12263,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
// The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning
// of x = {} is x = T().
InitializationKind Kind = InitializationKind::CreateDirectList(
- RHSExpr->getLocStart(), RHSExpr->getLocStart(), RHSExpr->getLocEnd());
+ RHSExpr->getBeginLoc(), RHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
InitializedEntity Entity =
InitializedEntity::InitializeTemporary(LHSExpr->getType());
InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr);
@@ -12035,7 +12292,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
// OpenCLC v2.0 s6.13.11.1 allows atomic variables to be initialized by
// the ATOMIC_VAR_INIT macro.
if (LHSTy->isAtomicType() || RHSTy->isAtomicType()) {
- SourceRange SR(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+ SourceRange SR(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
if (BO_Assign == Opc)
Diag(OpLoc, diag::err_opencl_atomic_init) << 0 << SR;
else
@@ -12197,11 +12454,13 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
&Context.Idents.get("object_setClass"),
SourceLocation(), LookupOrdinaryName);
if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) {
- SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getLocEnd());
- Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign) <<
- FixItHint::CreateInsertion(LHS.get()->getLocStart(), "object_setClass(") <<
- FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc), ",") <<
- FixItHint::CreateInsertion(RHSLocEnd, ")");
+ SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getEndLoc());
+ Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign)
+ << FixItHint::CreateInsertion(LHS.get()->getBeginLoc(),
+ "object_setClass(")
+ << FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc),
+ ",")
+ << FixItHint::CreateInsertion(RHSLocEnd, ")");
}
else
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign);
@@ -12258,13 +12517,14 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
if (isLeftBitwise || isRightBitwise)
return;
- SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(),
- OpLoc)
- : SourceRange(OpLoc, RHSExpr->getLocEnd());
+ SourceRange DiagRange = isLeftComp
+ ? SourceRange(LHSExpr->getBeginLoc(), OpLoc)
+ : SourceRange(OpLoc, RHSExpr->getEndLoc());
StringRef OpStr = isLeftComp ? LHSBO->getOpcodeStr() : RHSBO->getOpcodeStr();
- SourceRange ParensRange = isLeftComp ?
- SourceRange(LHSBO->getRHS()->getLocStart(), RHSExpr->getLocEnd())
- : SourceRange(LHSExpr->getLocStart(), RHSBO->getLHS()->getLocEnd());
+ SourceRange ParensRange =
+ isLeftComp
+ ? SourceRange(LHSBO->getRHS()->getBeginLoc(), RHSExpr->getEndLoc())
+ : SourceRange(LHSExpr->getBeginLoc(), RHSBO->getLHS()->getEndLoc());
Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel)
<< DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr;
@@ -12398,10 +12658,9 @@ static void DiagnoseShiftCompare(Sema &S, SourceLocation OpLoc,
S.PDiag(diag::note_precedence_silence)
<< (Kind == OO_LessLess ? "<<" : ">>"),
OCE->getSourceRange());
- SuggestParentheses(S, OpLoc,
- S.PDiag(diag::note_evaluate_comparison_first),
- SourceRange(OCE->getArg(1)->getLocStart(),
- RHSExpr->getLocEnd()));
+ SuggestParentheses(
+ S, OpLoc, S.PDiag(diag::note_evaluate_comparison_first),
+ SourceRange(OCE->getArg(1)->getBeginLoc(), RHSExpr->getEndLoc()));
}
/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
@@ -12643,6 +12902,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
break;
case UO_AddrOf:
resultType = CheckAddressOfOperand(Input, OpLoc);
+ CheckAddressOfNoDeref(InputExpr);
RecordModifiableNonNullParam(*this, InputExpr);
break;
case UO_Deref: {
@@ -12807,6 +13067,11 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
auto *UO = new (Context)
UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow);
+
+ if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
+ !isa<ArrayType>(UO->getType().getDesugaredType(Context)))
+ ExprEvalContexts.back().PossibleDerefs.insert(UO);
+
// Convert the result back to a half vector.
if (ConvertHalfVec)
return convertVector(UO, Context.HalfTy, *this);
@@ -13071,9 +13336,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// FIXME: An integral constant expression?
if (!Idx->isTypeDependent() && !Idx->isValueDependent() &&
!Idx->getType()->isIntegerType())
- return ExprError(Diag(Idx->getLocStart(),
- diag::err_typecheck_subscript_not_integer)
- << Idx->getSourceRange());
+ return ExprError(
+ Diag(Idx->getBeginLoc(), diag::err_typecheck_subscript_not_integer)
+ << Idx->getSourceRange());
// Record this array index.
Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd));
@@ -13294,7 +13559,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
// Drop the parameters.
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = false;
- EPI.TypeQuals |= DeclSpec::TQ_const;
+ EPI.TypeQuals.addConst();
T = Context.getFunctionType(Context.DependentTy, None, EPI);
Sig = Context.getTrivialTypeSourceInfo(T);
}
@@ -13365,7 +13630,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
} else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
for (const auto &I : Fn->param_types()) {
ParmVarDecl *Param = BuildParmVarDeclForTypedef(
- CurBlock->TheDecl, ParamInfo.getLocStart(), I);
+ CurBlock->TheDecl, ParamInfo.getBeginLoc(), I);
Params.push_back(Param);
}
}
@@ -13421,6 +13686,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
PopExpressionEvaluationContext();
BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back());
+ BlockDecl *BD = BSI->TheDecl;
if (BSI->HasImplicitReturnType)
deduceClosureReturnType(*BSI);
@@ -13431,7 +13697,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (!BSI->ReturnType.isNull())
RetTy = BSI->ReturnType;
- bool NoReturn = BSI->TheDecl->hasAttr<NoReturnAttr>();
+ bool NoReturn = BD->hasAttr<NoReturnAttr>();
QualType BlockTy;
// Set the captured variables on the block.
@@ -13444,7 +13710,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
Cap.isNested(), Cap.getInitExpr());
Captures.push_back(NewCap);
}
- BSI->TheDecl->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
+ BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
// If the user wrote a function type in some form, try to use that.
if (!BSI->FunctionType.isNull()) {
@@ -13469,7 +13735,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
} else {
const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- EPI.TypeQuals = 0; // FIXME: silently?
+ EPI.TypeQuals = Qualifiers();
EPI.ExtInfo = Ext;
BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
}
@@ -13481,7 +13747,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
BlockTy = Context.getFunctionType(RetTy, None, EPI);
}
- DiagnoseUnusedParameters(BSI->TheDecl->parameters());
+ DiagnoseUnusedParameters(BD->parameters());
BlockTy = Context.getBlockPointerType(BlockTy);
// If needed, diagnose invalid gotos and switches in the block.
@@ -13489,19 +13755,19 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
- BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
+ BD->setBody(cast<CompoundStmt>(Body));
if (Body && getCurFunction()->HasPotentialAvailabilityViolations)
- DiagnoseUnguardedAvailabilityViolations(BSI->TheDecl);
+ DiagnoseUnguardedAvailabilityViolations(BD);
// Try to apply the named return value optimization. We have to check again
// if we can do this, though, because blocks keep return statements around
// to deduce an implicit return type.
if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
- !BSI->TheDecl->isDependentContext())
+ !BD->isDependentContext())
computeNRVO(Body, BSI);
- BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
+ BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy);
AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
@@ -13523,6 +13789,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
}
}
+ if (getCurFunction())
+ getCurFunction()->addBlock(BD);
+
return Result;
}
@@ -13544,7 +13813,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
if (const FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) {
CUDAFunctionTarget T = IdentifyCUDATarget(F);
if (T == CFT_Global || T == CFT_Device || T == CFT_HostDevice)
- return ExprError(Diag(E->getLocStart(), diag::err_va_arg_in_device));
+ return ExprError(Diag(E->getBeginLoc(), diag::err_va_arg_in_device));
}
}
@@ -13594,9 +13863,10 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
if (!IsMS && !E->isTypeDependent() &&
!Context.hasSameType(VaListType, E->getType()))
- return ExprError(Diag(E->getLocStart(),
- diag::err_first_argument_to_va_arg_not_of_type_va_list)
- << OrigExpr->getType() << E->getSourceRange());
+ return ExprError(
+ Diag(E->getBeginLoc(),
+ diag::err_first_argument_to_va_arg_not_of_type_va_list)
+ << OrigExpr->getType() << E->getSourceRange());
if (!TInfo->getType()->isDependentType()) {
if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
@@ -13661,7 +13931,7 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp,
bool Diagnose) {
- if (!getLangOpts().ObjC1)
+ if (!getLangOpts().ObjC)
return false;
const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
@@ -13687,9 +13957,9 @@ bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp,
if (!SL || !SL->isAscii())
return false;
if (Diagnose) {
- Diag(SL->getLocStart(), diag::err_missing_atsign_prefix)
- << FixItHint::CreateInsertion(SL->getLocStart(), "@");
- Exp = BuildObjCStringLiteral(SL->getLocStart(), SL).get();
+ Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix)
+ << FixItHint::CreateInsertion(SL->getBeginLoc(), "@");
+ Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get();
}
return true;
}
@@ -13710,7 +13980,7 @@ static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType,
return !S.checkAddressOfFunctionIsAvailable(FD,
/*Complain=*/true,
- SrcExpr->getLocStart());
+ SrcExpr->getBeginLoc());
}
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
@@ -13963,7 +14233,7 @@ ExprResult
Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
VerifyICEDiagnoser &Diagnoser,
bool AllowFold) {
- SourceLocation DiagLoc = E->getLocStart();
+ SourceLocation DiagLoc = E->getBeginLoc();
if (getLangOpts().CPlusPlus11) {
// C++11 [expr.const]p5:
@@ -14030,11 +14300,14 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
return ExprError();
}
+ if (!isa<ConstantExpr>(E))
+ E = ConstantExpr::Create(Context, E);
+
// Circumvent ICE checking in C++11 to avoid evaluating the expression twice
// in the non-ICE case.
if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
if (Result)
- *Result = E->EvaluateKnownConstInt(Context);
+ *Result = E->EvaluateKnownConstIntCheckOverflow(Context);
return E;
}
@@ -14165,6 +14438,51 @@ Sema::PushExpressionEvaluationContext(
PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
}
+namespace {
+
+const DeclRefExpr *CheckPossibleDeref(Sema &S, const Expr *PossibleDeref) {
+ PossibleDeref = PossibleDeref->IgnoreParenImpCasts();
+ if (const auto *E = dyn_cast<UnaryOperator>(PossibleDeref)) {
+ if (E->getOpcode() == UO_Deref)
+ return CheckPossibleDeref(S, E->getSubExpr());
+ } else if (const auto *E = dyn_cast<ArraySubscriptExpr>(PossibleDeref)) {
+ return CheckPossibleDeref(S, E->getBase());
+ } else if (const auto *E = dyn_cast<MemberExpr>(PossibleDeref)) {
+ return CheckPossibleDeref(S, E->getBase());
+ } else if (const auto E = dyn_cast<DeclRefExpr>(PossibleDeref)) {
+ QualType Inner;
+ QualType Ty = E->getType();
+ if (const auto *Ptr = Ty->getAs<PointerType>())
+ Inner = Ptr->getPointeeType();
+ else if (const auto *Arr = S.Context.getAsArrayType(Ty))
+ Inner = Arr->getElementType();
+ else
+ return nullptr;
+
+ if (Inner->hasAttr(attr::NoDeref))
+ return E;
+ }
+ return nullptr;
+}
+
+} // namespace
+
+void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) {
+ for (const Expr *E : Rec.PossibleDerefs) {
+ const DeclRefExpr *DeclRef = CheckPossibleDeref(*this, E);
+ if (DeclRef) {
+ const ValueDecl *Decl = DeclRef->getDecl();
+ Diag(E->getExprLoc(), diag::warn_dereference_of_noderef_type)
+ << Decl->getName() << E->getSourceRange();
+ Diag(Decl->getLocation(), diag::note_previous_decl) << Decl->getName();
+ } else {
+ Diag(E->getExprLoc(), diag::warn_dereference_of_noderef_type_no_decl)
+ << E->getSourceRange();
+ }
+ }
+ Rec.PossibleDerefs.clear();
+}
+
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
unsigned NumTypos = Rec.NumTypos;
@@ -14193,7 +14511,7 @@ void Sema::PopExpressionEvaluationContext() {
llvm_unreachable("Couldn't infer lambda error message.");
for (const auto *L : Rec.Lambdas)
- Diag(L->getLocStart(), D);
+ Diag(L->getBeginLoc(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
@@ -14204,6 +14522,8 @@ void Sema::PopExpressionEvaluationContext() {
}
}
+ WarnOnPendingNoDerefs(Rec);
+
// When are coming out of an unevaluated context, clear out any
// temporaries that we may have created as part of the evaluation of
// the expression in that context: they aren't relevant because they
@@ -14224,11 +14544,8 @@ void Sema::PopExpressionEvaluationContext() {
// Pop the current expression evaluation context off the stack.
ExprEvalContexts.pop_back();
- if (!ExprEvalContexts.empty())
- ExprEvalContexts.back().NumTypos += NumTypos;
- else
- assert(NumTypos == 0 && "There are outstanding typos after popping the "
- "last ExpressionEvaluationContextRecord");
+ // The global expression evaluation context record is never popped.
+ ExprEvalContexts.back().NumTypos += NumTypos;
}
void Sema::DiscardCleanupsInEvaluationContext() {
@@ -14240,6 +14557,10 @@ void Sema::DiscardCleanupsInEvaluationContext() {
}
ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) {
+ ExprResult Result = CheckPlaceholderExpr(E);
+ if (Result.isInvalid())
+ return ExprError();
+ E = Result.get();
if (!E->getType()->isVariablyModifiedType())
return E;
return TransformToPotentiallyEvaluated(E);
@@ -14641,8 +14962,10 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
Expr *CopyExpr = nullptr;
bool ByRef = false;
- // Blocks are not allowed to capture arrays.
- if (CaptureType->isArrayType()) {
+ // Blocks are not allowed to capture arrays, excepting OpenCL.
+ // OpenCL v2.0 s1.12.5 (revision 40): arrays are captured by reference
+ // (decayed to pointers).
+ if (!S.getLangOpts().OpenCL && CaptureType->isArrayType()) {
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_ref_array_type);
S.Diag(Var->getLocation(), diag::note_previous_decl)
@@ -14665,15 +14988,15 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
// Warn about implicitly autoreleasing indirect parameters captured by blocks.
if (const auto *PT = CaptureType->getAs<PointerType>()) {
// This function finds out whether there is an AttributedType of kind
- // attr_objc_ownership in Ty. The existence of AttributedType of kind
- // attr_objc_ownership implies __autoreleasing was explicitly specified
+ // attr::ObjCOwnership in Ty. The existence of AttributedType of kind
+ // attr::ObjCOwnership implies __autoreleasing was explicitly specified
// rather than being added implicitly by the compiler.
auto IsObjCOwnershipAttributedType = [](QualType Ty) {
while (const auto *AttrTy = Ty->getAs<AttributedType>()) {
- if (AttrTy->getAttrKind() == AttributedType::attr_objc_ownership)
+ if (AttrTy->getAttrKind() == attr::ObjCOwnership)
return true;
- // Peel off AttributedTypes that are not of kind objc_ownership.
+ // Peel off AttributedTypes that are not of kind ObjCOwnership.
Ty = AttrTy->getModifiedType();
}
@@ -14722,9 +15045,8 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
// According to the blocks spec, the capture of a variable from
// the stack requires a const copy constructor. This is not true
// of the copy/move done to move a __block variable to the heap.
- Expr *DeclRef = new (S.Context) DeclRefExpr(Var, Nested,
- DeclRefType.withConst(),
- VK_LValue, Loc);
+ Expr *DeclRef = new (S.Context) DeclRefExpr(
+ S.Context, Var, Nested, DeclRefType.withConst(), VK_LValue, Loc);
ExprResult Result
= S.PerformCopyInitialization(
@@ -14800,8 +15122,8 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
S.setOpenMPCaptureKind(Field, Var, RSI->OpenMPLevel);
- CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable,
- DeclRefType, VK_LValue, Loc);
+ CopyExpr = new (S.Context) DeclRefExpr(
+ S.Context, Var, RefersToCapturedVariable, DeclRefType, VK_LValue, Loc);
Var->setReferenced(true);
Var->markUsed(S.Context);
}
@@ -14828,6 +15150,21 @@ static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI,
= FieldDecl::Create(S.Context, Lambda, Loc, Loc, nullptr, FieldType,
S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
nullptr, false, ICIS_NoInit);
+ // If the variable being captured has an invalid type, mark the lambda class
+ // as invalid as well.
+ if (!FieldType->isDependentType()) {
+ if (S.RequireCompleteType(Loc, FieldType, diag::err_field_incomplete)) {
+ Lambda->setInvalidDecl();
+ Field->setInvalidDecl();
+ } else {
+ NamedDecl *Def;
+ FieldType->isIncompleteType(&Def);
+ if (Def && Def->isInvalidDecl()) {
+ Lambda->setInvalidDecl();
+ Field->setInvalidDecl();
+ }
+ }
+ }
Field->setImplicit(true);
Field->setAccess(AS_private);
Lambda->addDecl(Field);
@@ -15023,7 +15360,7 @@ bool Sema::tryCaptureVariable(
Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
- Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl);
+ Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl);
} else
diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);
}
@@ -15077,7 +15414,7 @@ bool Sema::tryCaptureVariable(
Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
if (cast<LambdaScopeInfo>(CSI)->Lambda)
- Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(),
+ Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(),
diag::note_lambda_decl);
// FIXME: If we error out because an outer lambda can not implicitly
// capture a variable that an inner lambda explicitly captures, we
@@ -15435,8 +15772,8 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
if (Method->isPure())
MightBeOdrUse = false;
}
- SourceLocation Loc = E->getMemberLoc().isValid() ?
- E->getMemberLoc() : E->getLocStart();
+ SourceLocation Loc =
+ E->getMemberLoc().isValid() ? E->getMemberLoc() : E->getBeginLoc();
MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse);
}
@@ -15532,34 +15869,34 @@ namespace {
}
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
- S.MarkFunctionReferenced(E->getLocStart(),
- const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor()));
+ S.MarkFunctionReferenced(
+ E->getBeginLoc(),
+ const_cast<CXXDestructorDecl *>(E->getTemporary()->getDestructor()));
Visit(E->getSubExpr());
}
void VisitCXXNewExpr(CXXNewExpr *E) {
if (E->getOperatorNew())
- S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew());
+ S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorNew());
if (E->getOperatorDelete())
- S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete());
+ S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete());
Inherited::VisitCXXNewExpr(E);
}
void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
if (E->getOperatorDelete())
- S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete());
+ S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete());
QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- S.MarkFunctionReferenced(E->getLocStart(),
- S.LookupDestructor(Record));
+ S.MarkFunctionReferenced(E->getBeginLoc(), S.LookupDestructor(Record));
}
Inherited::VisitCXXDeleteExpr(E);
}
void VisitCXXConstructExpr(CXXConstructExpr *E) {
- S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor());
+ S.MarkFunctionReferenced(E->getBeginLoc(), E->getConstructor());
Inherited::VisitCXXConstructExpr(E);
}
@@ -15730,7 +16067,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
Diag(Loc, diagnostic) << E->getSourceRange();
- SourceLocation Open = E->getLocStart();
+ SourceLocation Open = E->getBeginLoc();
SourceLocation Close = getLocForEndOfToken(E->getSourceRange().getEnd());
Diag(Loc, diag::note_condition_assign_silence)
<< FixItHint::CreateInsertion(Open, "(")
@@ -15748,7 +16085,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
/// that the user intended an assignment used as condition.
void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
// Don't warn if the parens came from a macro.
- SourceLocation parenLoc = ParenE->getLocStart();
+ SourceLocation parenLoc = ParenE->getBeginLoc();
if (parenLoc.isInvalid() || parenLoc.isMacroID())
return;
// Don't warn for dependent expressions.
@@ -16211,7 +16548,7 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (DRE && Proto && Proto->getParamTypes().empty() && Proto->isVariadic()) {
SourceLocation Loc = FD->getLocation();
- FunctionDecl *NewFD = FunctionDecl::Create(FD->getASTContext(),
+ FunctionDecl *NewFD = FunctionDecl::Create(S.Context,
FD->getDeclContext(),
Loc, Loc, FD->getNameInfo().getName(),
DestType, FD->getTypeSourceInfo(),
@@ -16439,25 +16776,29 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
auto *FD = cast<FunctionDecl>(DRE->getDecl());
if (FD->getBuiltinID() == Builtin::BI__noop) {
E = ImpCastExprToType(E, Context.getPointerType(FD->getType()),
- CK_BuiltinFnToFnPtr).get();
- return new (Context) CallExpr(Context, E, None, Context.IntTy,
- VK_RValue, SourceLocation());
+ CK_BuiltinFnToFnPtr)
+ .get();
+ return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy,
+ VK_RValue, SourceLocation());
}
}
- Diag(E->getLocStart(), diag::err_builtin_fn_use);
+ Diag(E->getBeginLoc(), diag::err_builtin_fn_use);
return ExprError();
}
// Expressions of unknown type.
case BuiltinType::OMPArraySection:
- Diag(E->getLocStart(), diag::err_omp_array_section_use);
+ Diag(E->getBeginLoc(), diag::err_omp_array_section_use);
return ExprError();
// Everything else should be impossible.
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
#define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id:
#define PLACEHOLDER_TYPE(Id, SingletonId)
#include "clang/AST/BuiltinTypes.def"
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index a1168fa34d56..8c89a3cee3db 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -113,9 +113,15 @@ ParsedType Sema::getConstructorName(IdentifierInfo &II,
break;
}
}
- if (!InjectedClassName && CurClass->isInvalidDecl())
+ if (!InjectedClassName) {
+ if (!CurClass->isInvalidDecl()) {
+ // FIXME: RequireCompleteDeclContext doesn't check dependent contexts
+ // properly. Work around it here for now.
+ Diag(SS.getLastQualifierNameLoc(),
+ diag::err_incomplete_nested_name_spec) << CurClass << SS.getRange();
+ }
return ParsedType();
- assert(InjectedClassName && "couldn't find injected class name");
+ }
QualType T = Context.getTypeDeclType(InjectedClassName);
DiagnoseUseOfDecl(InjectedClassName, NameLoc);
@@ -413,8 +419,8 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
// namespace scope. Therefore, this unqualified-id cannot name anything.
// Reject it early, because we have no AST representation for this in the
// case where the scope is dependent.
- Diag(Name.getLocStart(), diag::err_literal_operator_id_outside_namespace)
- << SS.getScopeRep();
+ Diag(Name.getBeginLoc(), diag::err_literal_operator_id_outside_namespace)
+ << SS.getScopeRep();
return true;
case NestedNameSpecifier::Global:
@@ -1058,7 +1064,7 @@ QualType Sema::getCurrentThisType() {
if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
if (method && method->isInstance())
- ThisTy = method->getThisType(Context);
+ ThisTy = method->getThisType();
}
if (ThisTy.isNull() && isLambdaCallOperator(CurContext) &&
@@ -1088,7 +1094,7 @@ QualType Sema::getCurrentThisType() {
Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
Decl *ContextDecl,
- unsigned CXXThisTypeQuals,
+ Qualifiers CXXThisTypeQuals,
bool Enabled)
: S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
{
@@ -1101,11 +1107,10 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
else
Record = cast<CXXRecordDecl>(ContextDecl);
- // We care only for CVR qualifiers here, so cut everything else.
- CXXThisTypeQuals &= Qualifiers::FastMask;
- S.CXXThisTypeOverride
- = S.Context.getPointerType(
- S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals));
+ QualType T = S.Context.getRecordType(Record);
+ T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals);
+
+ S.CXXThisTypeOverride = S.Context.getPointerType(T);
this->Enabled = true;
}
@@ -1442,11 +1447,33 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
return Result;
}
+bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) {
+ // [CUDA] Ignore this function, if we can't call it.
+ const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext);
+ if (getLangOpts().CUDA &&
+ IdentifyCUDAPreference(Caller, Method) <= CFP_WrongSide)
+ return false;
+
+ SmallVector<const FunctionDecl*, 4> PreventedBy;
+ bool Result = Method->isUsualDeallocationFunction(PreventedBy);
+
+ if (Result || !getLangOpts().CUDA || PreventedBy.empty())
+ return Result;
+
+ // In case of CUDA, return true if none of the 1-argument deallocator
+ // functions are actually callable.
+ return llvm::none_of(PreventedBy, [&](const FunctionDecl *FD) {
+ assert(FD->getNumParams() == 1 &&
+ "Only single-operand functions should be in PreventedBy");
+ return IdentifyCUDAPreference(Caller, FD) >= CFP_HostDevice;
+ });
+}
+
/// Determine whether the given function is a non-placement
/// deallocation function.
static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
- return Method->isUsualDeallocationFunction();
+ return S.isUsualDeallocationFunction(Method);
if (FD->getOverloadedOperator() != OO_Delete &&
FD->getOverloadedOperator() != OO_Array_Delete)
@@ -1484,11 +1511,19 @@ namespace {
Destroying = true;
++NumBaseParams;
}
- if (FD->getNumParams() == NumBaseParams + 2)
- HasAlignValT = HasSizeT = true;
- else if (FD->getNumParams() == NumBaseParams + 1) {
- HasSizeT = FD->getParamDecl(NumBaseParams)->getType()->isIntegerType();
- HasAlignValT = !HasSizeT;
+
+ if (NumBaseParams < FD->getNumParams() &&
+ S.Context.hasSameUnqualifiedType(
+ FD->getParamDecl(NumBaseParams)->getType(),
+ S.Context.getSizeType())) {
+ ++NumBaseParams;
+ HasSizeT = true;
+ }
+
+ if (NumBaseParams < FD->getNumParams() &&
+ FD->getParamDecl(NumBaseParams)->getType()->isAlignValT()) {
+ ++NumBaseParams;
+ HasAlignValT = true;
}
// In CUDA, determine how much we'd like / dislike to call this.
@@ -1692,15 +1727,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer))
DirectInitRange = List->getSourceRange();
- return BuildCXXNew(SourceRange(StartLoc, D.getLocEnd()), UseGlobal,
- PlacementLParen,
- PlacementArgs,
- PlacementRParen,
- TypeIdParens,
- AllocType,
- TInfo,
- ArraySize,
- DirectInitRange,
+ return BuildCXXNew(SourceRange(StartLoc, D.getEndLoc()), UseGlobal,
+ PlacementLParen, PlacementArgs, PlacementRParen,
+ TypeIdParens, AllocType, TInfo, ArraySize, DirectInitRange,
Initializer);
}
@@ -1723,28 +1752,33 @@ static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style,
return false;
}
-// Emit a diagnostic if an aligned allocation/deallocation function that is not
-// implemented in the standard library is selected.
-static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
- SourceLocation Loc, bool IsDelete,
- Sema &S) {
- if (!S.getLangOpts().AlignedAllocationUnavailable)
- return;
-
- // Return if there is a definition.
+bool
+Sema::isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const {
+ if (!getLangOpts().AlignedAllocationUnavailable)
+ return false;
if (FD.isDefined())
- return;
-
+ return false;
bool IsAligned = false;
- if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) {
- const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple();
+ if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned)
+ return true;
+ return false;
+}
+
+// Emit a diagnostic if an aligned allocation/deallocation function that is not
+// implemented in the standard library is selected.
+void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
+ SourceLocation Loc) {
+ if (isUnavailableAlignedAllocationFunction(FD)) {
+ const llvm::Triple &T = getASTContext().getTargetInfo().getTriple();
StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling(
- S.getASTContext().getTargetInfo().getPlatformName());
+ getASTContext().getTargetInfo().getPlatformName());
- S.Diag(Loc, diag::warn_aligned_allocation_unavailable)
- << IsDelete << FD.getType().getAsString() << OSName
- << alignedAllocMinVersion(T.getOS()).getAsString();
- S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable);
+ OverloadedOperatorKind Kind = FD.getDeclName().getCXXOverloadedOperator();
+ bool IsDelete = Kind == OO_Delete || Kind == OO_Array_Delete;
+ Diag(Loc, diag::err_aligned_allocation_unavailable)
+ << IsDelete << FD.getType().getAsString() << OSName
+ << alignedAllocMinVersion(T.getOS()).getAsString();
+ Diag(Loc, diag::note_silence_aligned_allocation_unavailable);
}
}
@@ -1787,20 +1821,21 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// A new-expression that creates an object of type T initializes that
// object as follows:
InitializationKind Kind
- // - If the new-initializer is omitted, the object is default-
- // initialized (8.5); if no initialization is performed,
- // the object has indeterminate value
- = initStyle == CXXNewExpr::NoInit
- ? InitializationKind::CreateDefault(TypeRange.getBegin())
- // - Otherwise, the new-initializer is interpreted according to the
- // initialization rules of 8.5 for direct-initialization.
- : initStyle == CXXNewExpr::ListInit
- ? InitializationKind::CreateDirectList(TypeRange.getBegin(),
- Initializer->getLocStart(),
- Initializer->getLocEnd())
- : InitializationKind::CreateDirect(TypeRange.getBegin(),
- DirectInitRange.getBegin(),
- DirectInitRange.getEnd());
+ // - If the new-initializer is omitted, the object is default-
+ // initialized (8.5); if no initialization is performed,
+ // the object has indeterminate value
+ = initStyle == CXXNewExpr::NoInit
+ ? InitializationKind::CreateDefault(TypeRange.getBegin())
+ // - Otherwise, the new-initializer is interpreted according to
+ // the
+ // initialization rules of 8.5 for direct-initialization.
+ : initStyle == CXXNewExpr::ListInit
+ ? InitializationKind::CreateDirectList(
+ TypeRange.getBegin(), Initializer->getBeginLoc(),
+ Initializer->getEndLoc())
+ : InitializationKind::CreateDirect(TypeRange.getBegin(),
+ DirectInitRange.getBegin(),
+ DirectInitRange.getEnd());
// C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
auto *Deduced = AllocType->getContainedDeducedType();
@@ -1831,19 +1866,18 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
<< AllocType << TypeRange);
if (NumInits > 1) {
Expr *FirstBad = Inits[1];
- return ExprError(Diag(FirstBad->getLocStart(),
+ return ExprError(Diag(FirstBad->getBeginLoc(),
diag::err_auto_new_ctor_multiple_expressions)
<< AllocType << TypeRange);
}
if (Braced && !getLangOpts().CPlusPlus17)
- Diag(Initializer->getLocStart(), diag::ext_auto_new_list_init)
+ Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init)
<< AllocType << TypeRange;
- Expr *Deduce = Inits[0];
QualType DeducedType;
- if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed)
+ if (DeduceAutoType(AllocTypeInfo, Inits[0], DeducedType) == DAR_Failed)
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
- << AllocType << Deduce->getType()
- << TypeRange << Deduce->getSourceRange());
+ << AllocType << Inits[0]->getType()
+ << TypeRange << Inits[0]->getSourceRange());
if (DeducedType.isNull())
return ExprError();
AllocType = DeducedType;
@@ -1983,7 +2017,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// C++14 onwards, because Value is always unsigned here!
if (ArraySize->isIntegerConstantExpr(Value, Context)) {
if (Value.isSigned() && Value.isNegative()) {
- return ExprError(Diag(ArraySize->getLocStart(),
+ return ExprError(Diag(ArraySize->getBeginLoc(),
diag::err_typecheck_negative_array_size)
<< ArraySize->getSourceRange());
}
@@ -1992,19 +2026,18 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
unsigned ActiveSizeBits =
ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
- return ExprError(Diag(ArraySize->getLocStart(),
- diag::err_array_too_large)
- << Value.toString(10)
- << ArraySize->getSourceRange());
+ return ExprError(
+ Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
+ << Value.toString(10) << ArraySize->getSourceRange());
}
KnownArraySize = Value.getZExtValue();
} else if (TypeIdParens.isValid()) {
// Can't have dynamic array size when the type-id is in parentheses.
- Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst)
- << ArraySize->getSourceRange()
- << FixItHint::CreateRemoval(TypeIdParens.getBegin())
- << FixItHint::CreateRemoval(TypeIdParens.getEnd());
+ Diag(ArraySize->getBeginLoc(), diag::ext_new_paren_array_nonconst)
+ << ArraySize->getSourceRange()
+ << FixItHint::CreateRemoval(TypeIdParens.getBegin())
+ << FixItHint::CreateRemoval(TypeIdParens.getEnd());
TypeIdParens = SourceRange();
}
@@ -2066,8 +2099,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// global operator new.
if (PlacementArgs.empty() && !PassAlignment &&
(OperatorNew->isImplicit() ||
- (OperatorNew->getLocStart().isValid() &&
- getSourceManager().isInSystemHeader(OperatorNew->getLocStart())))) {
+ (OperatorNew->getBeginLoc().isValid() &&
+ getSourceManager().isInSystemHeader(OperatorNew->getBeginLoc())))) {
if (Alignment > NewAlignment)
Diag(StartLoc, diag::warn_overaligned_type)
<< AllocType
@@ -2080,8 +2113,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// Initializer lists are also allowed, in C++11. Rely on the parser for the
// dialect distinction.
if (ArraySize && !isLegalArrayNewInitializer(initStyle, Initializer)) {
- SourceRange InitRange(Inits[0]->getLocStart(),
- Inits[NumInits - 1]->getLocEnd());
+ SourceRange InitRange(Inits[0]->getBeginLoc(),
+ Inits[NumInits - 1]->getEndLoc());
Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
return ExprError();
}
@@ -2128,13 +2161,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (DiagnoseUseOfDecl(OperatorNew, StartLoc))
return ExprError();
MarkFunctionReferenced(StartLoc, OperatorNew);
- diagnoseUnavailableAlignedAllocation(*OperatorNew, StartLoc, false, *this);
}
if (OperatorDelete) {
if (DiagnoseUseOfDecl(OperatorDelete, StartLoc))
return ExprError();
MarkFunctionReferenced(StartLoc, OperatorDelete);
- diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true, *this);
}
// C++0x [expr.new]p17:
@@ -2155,11 +2186,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
}
- return new (Context)
- CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment,
- UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens,
- ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo,
- Range, DirectInitRange);
+ return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete,
+ PassAlignment, UsualArrayDeleteWantsSize,
+ PlacementArgs, TypeIdParens, ArraySize, initStyle,
+ Initializer, ResultType, AllocTypeInfo, Range,
+ DirectInitRange);
}
/// Checks that a type is suitable as the allocated type
@@ -2587,8 +2618,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
if (IsSizedDelete) {
SourceRange R = PlaceArgs.empty()
? SourceRange()
- : SourceRange(PlaceArgs.front()->getLocStart(),
- PlaceArgs.back()->getLocEnd());
+ : SourceRange(PlaceArgs.front()->getBeginLoc(),
+ PlaceArgs.back()->getEndLoc());
Diag(StartLoc, diag::err_placement_new_non_placement_delete) << R;
if (!OperatorDelete->isImplicit())
Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
@@ -2794,9 +2825,10 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
// Global allocation functions should always be visible.
Alloc->setVisibleDespiteOwningModule();
- // Implicit sized deallocation functions always have default visibility.
- Alloc->addAttr(
- VisibilityAttr::CreateImplicit(Context, VisibilityAttr::Default));
+ Alloc->addAttr(VisibilityAttr::CreateImplicit(
+ Context, LangOpts.GlobalAllocationFunctionVisibilityHidden
+ ? VisibilityAttr::Hidden
+ : VisibilityAttr::Default));
llvm::SmallVector<ParmVarDecl *, 3> ParamDecls;
for (QualType T : Params) {
@@ -3156,12 +3188,12 @@ void Sema::AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE) {
switch (Detector.analyzeDeleteExpr(DE)) {
case MismatchingNewDeleteDetector::VarInitMismatches:
case MismatchingNewDeleteDetector::MemberInitMismatches: {
- DiagnoseMismatchedNewDelete(*this, DE->getLocStart(), Detector);
+ DiagnoseMismatchedNewDelete(*this, DE->getBeginLoc(), Detector);
break;
}
case MismatchingNewDeleteDetector::AnalyzeLater: {
DeleteExprs[Detector.Field].push_back(
- std::make_pair(DE->getLocStart(), DE->isArrayForm()));
+ std::make_pair(DE->getBeginLoc(), DE->isArrayForm()));
break;
}
case MismatchingNewDeleteDetector::NoMismatch:
@@ -3280,10 +3312,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (Pointee.getAddressSpace() != LangAS::Default &&
!getLangOpts().OpenCLCPlusPlus)
- return Diag(Ex.get()->getLocStart(),
+ return Diag(Ex.get()->getBeginLoc(),
diag::err_address_space_qualified_delete)
- << Pointee.getUnqualifiedType()
- << Pointee.getQualifiers().getAddressSpaceAttributePrintValue();
+ << Pointee.getUnqualifiedType()
+ << Pointee.getQualifiers().getAddressSpaceAttributePrintValue();
CXXRecordDecl *PointeeRD = nullptr;
if (Pointee->isVoidType() && !isSFINAEContext()) {
@@ -3383,8 +3415,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
}
- diagnoseUnavailableAlignedAllocation(*OperatorDelete, StartLoc, true,
- *this);
+ DiagnoseUseOfDecl(OperatorDelete, StartLoc);
// Convert the operand to the type of the first parameter of operator
// delete. This is only necessary if we selected a destroying operator
@@ -3421,7 +3452,7 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall,
DeclarationName NewName = S.Context.DeclarationNames.getCXXOperatorName(
IsDelete ? OO_Delete : OO_New);
- LookupResult R(S, NewName, TheCall->getLocStart(), Sema::LookupOrdinaryName);
+ LookupResult R(S, NewName, TheCall->getBeginLoc(), Sema::LookupOrdinaryName);
S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl());
assert(!R.empty() && "implicitly declared allocation functions not found");
assert(!R.isAmbiguous() && "global allocation functions are ambiguous");
@@ -3517,13 +3548,16 @@ Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
return ExprError();
assert(OperatorNewOrDelete && "should be found");
+ DiagnoseUseOfDecl(OperatorNewOrDelete, TheCall->getExprLoc());
+ MarkFunctionReferenced(TheCall->getExprLoc(), OperatorNewOrDelete);
+
TheCall->setType(OperatorNewOrDelete->getReturnType());
for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) {
QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType();
InitializedEntity Entity =
InitializedEntity::InitializeParameter(Context, ParamTy, false);
ExprResult Arg = PerformCopyInitialization(
- Entity, TheCall->getArg(i)->getLocStart(), TheCall->getArg(i));
+ Entity, TheCall->getArg(i)->getBeginLoc(), TheCall->getArg(i));
if (Arg.isInvalid())
return ExprError();
TheCall->setArg(i, Arg.get());
@@ -3561,7 +3595,7 @@ void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
if (getSourceManager().isInSystemHeader(PointeeRD->getLocation()))
return;
- QualType ClassType = dtor->getThisType(Context)->getPointeeType();
+ QualType ClassType = dtor->getThisType()->getPointeeType();
if (PointeeRD->isAbstract()) {
// If the class is abstract, we warn by default, because we're
// sure the code has undefined behavior.
@@ -3811,14 +3845,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From = Res.get();
}
- ExprResult CastArg
- = BuildCXXCastArgument(*this,
- From->getLocStart(),
- ToType.getNonReferenceType(),
- CastKind, cast<CXXMethodDecl>(FD),
- ICS.UserDefined.FoundConversionFunction,
- ICS.UserDefined.HadMultipleCandidates,
- From);
+ ExprResult CastArg = BuildCXXCastArgument(
+ *this, From->getBeginLoc(), ToType.getNonReferenceType(), CastKind,
+ cast<CXXMethodDecl>(FD), ICS.UserDefined.FoundConversionFunction,
+ ICS.UserDefined.HadMultipleCandidates, From);
if (CastArg.isInvalid())
return ExprError();
@@ -3906,7 +3936,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (!Fn)
return ExprError();
- if (DiagnoseUseOfDecl(Fn, From->getLocStart()))
+ if (DiagnoseUseOfDecl(Fn, From->getBeginLoc()))
return ExprError();
From = FixOverloadedFunctionReference(From, Found, Fn);
@@ -4045,15 +4075,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (SCS.IncompatibleObjC && Action != AA_Casting) {
// Diagnose incompatible Objective-C conversions
if (Action == AA_Initializing || Action == AA_Assigning)
- Diag(From->getLocStart(),
+ Diag(From->getBeginLoc(),
diag::ext_typecheck_convert_incompatible_pointer)
- << ToType << From->getType() << Action
- << From->getSourceRange() << 0;
+ << ToType << From->getType() << Action << From->getSourceRange()
+ << 0;
else
- Diag(From->getLocStart(),
+ Diag(From->getBeginLoc(),
diag::ext_typecheck_convert_incompatible_pointer)
- << From->getType() << ToType << Action
- << From->getSourceRange() << 0;
+ << From->getType() << ToType << Action << From->getSourceRange()
+ << 0;
if (From->getType()->isObjCObjectPointerType() &&
ToType->isObjCObjectPointerType())
@@ -4062,13 +4092,11 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
!CheckObjCARCUnavailableWeakConversion(ToType,
From->getType())) {
if (Action == AA_Initializing)
- Diag(From->getLocStart(),
- diag::err_arc_weak_unavailable_assign);
+ Diag(From->getBeginLoc(), diag::err_arc_weak_unavailable_assign);
else
- Diag(From->getLocStart(),
- diag::err_arc_convesion_of_weak_unavailable)
- << (Action == AA_Casting) << From->getType() << ToType
- << From->getSourceRange();
+ Diag(From->getBeginLoc(), diag::err_arc_convesion_of_weak_unavailable)
+ << (Action == AA_Casting) << From->getType() << ToType
+ << From->getSourceRange();
}
CastKind Kind;
@@ -4124,12 +4152,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Derived_To_Base: {
CXXCastPath BasePath;
- if (CheckDerivedToBaseConversion(From->getType(),
- ToType.getNonReferenceType(),
- From->getLocStart(),
- From->getSourceRange(),
- &BasePath,
- CStyle))
+ if (CheckDerivedToBaseConversion(
+ From->getType(), ToType.getNonReferenceType(), From->getBeginLoc(),
+ From->getSourceRange(), &BasePath, CStyle))
return ExprError();
From = ImpCastExprToType(From, ToType.getNonReferenceType(),
@@ -4223,14 +4248,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
}
case ICK_Zero_Event_Conversion:
- From = ImpCastExprToType(From, ToType,
- CK_ZeroToOCLEvent,
- From->getValueKind()).get();
- break;
-
case ICK_Zero_Queue_Conversion:
From = ImpCastExprToType(From, ToType,
- CK_ZeroToOCLQueue,
+ CK_ZeroToOCLOpaqueType,
From->getValueKind()).get();
break;
@@ -4263,17 +4283,32 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Qualification: {
// The qualification keeps the category of the inner expression, unless the
// target type isn't a reference.
- ExprValueKind VK = ToType->isReferenceType() ?
- From->getValueKind() : VK_RValue;
- From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
- CK_NoOp, VK, /*BasePath=*/nullptr, CCK).get();
+ ExprValueKind VK =
+ ToType->isReferenceType() ? From->getValueKind() : VK_RValue;
+
+ CastKind CK = CK_NoOp;
+
+ if (ToType->isReferenceType() &&
+ ToType->getPointeeType().getAddressSpace() !=
+ From->getType().getAddressSpace())
+ CK = CK_AddressSpaceConversion;
+
+ if (ToType->isPointerType() &&
+ ToType->getPointeeType().getAddressSpace() !=
+ From->getType()->getPointeeType().getAddressSpace())
+ CK = CK_AddressSpaceConversion;
+
+ From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), CK, VK,
+ /*BasePath=*/nullptr, CCK)
+ .get();
if (SCS.DeprecatedStringLiteralToCharPtr &&
!getLangOpts().WritableStrings) {
- Diag(From->getLocStart(), getLangOpts().CPlusPlus11
- ? diag::ext_deprecated_string_literal_conversion
- : diag::warn_deprecated_string_literal_conversion)
- << ToType.getNonReferenceType();
+ Diag(From->getBeginLoc(),
+ getLangOpts().CPlusPlus11
+ ? diag::ext_deprecated_string_literal_conversion
+ : diag::warn_deprecated_string_literal_conversion)
+ << ToType.getNonReferenceType();
}
break;
@@ -4296,7 +4331,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// _Nullable type to a _Nonnull one, complain.
if (!isCast(CCK))
diagnoseNullableToNonnullConversion(ToType, InitialFromType,
- From->getLocStart());
+ From->getBeginLoc());
return From;
}
@@ -4926,7 +4961,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (ArgTy->isObjectType() || ArgTy->isFunctionType())
ArgTy = S.Context.getRValueReferenceType(ArgTy);
OpaqueArgExprs.push_back(
- OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
+ OpaqueValueExpr(Args[I]->getTypeLoc().getBeginLoc(),
ArgTy.getNonLValueExprType(S.Context),
Expr::getValueKindForType(ArgTy)));
}
@@ -5421,10 +5456,10 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
}
CXXCastPath BasePath;
- if (CheckDerivedToBaseConversion(LHSType, Class, Loc,
- SourceRange(LHS.get()->getLocStart(),
- RHS.get()->getLocEnd()),
- &BasePath))
+ if (CheckDerivedToBaseConversion(
+ LHSType, Class, Loc,
+ SourceRange(LHS.get()->getBeginLoc(), RHS.get()->getEndLoc()),
+ &BasePath))
return QualType();
// Cast LHS to type of use.
@@ -5518,8 +5553,8 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
HaveConversion = false;
ToType = To->getType();
- InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(),
- SourceLocation());
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(To->getBeginLoc(), SourceLocation());
// C++11 5.16p3
// The process for determining whether an operand expression E1 of type T1
// can be converted to match an operand expression E2 of type T2 is defined
@@ -5664,8 +5699,8 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS
/// TryClassUnification.
static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
- InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(),
- SourceLocation());
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(E.get()->getBeginLoc(), SourceLocation());
Expr *Arg = E.get();
InitializationSequence InitSeq(Self, Entity, Kind, Arg);
ExprResult Result = InitSeq.Perform(Self, Entity, Kind, Arg);
@@ -6515,6 +6550,11 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
ExpressionEvaluationContextRecord::EK_Decltype &&
"not in a decltype expression");
+ ExprResult Result = CheckPlaceholderExpr(E);
+ if (Result.isInvalid())
+ return ExprError();
+ E = Result.get();
+
// C++11 [expr.call]p11:
// If a function call is a prvalue of object type,
// -- if the function call is either
@@ -6571,8 +6611,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
continue;
if (CheckCallReturnType(Call->getCallReturnType(Context),
- Call->getLocStart(),
- Call, Call->getDirectCallee()))
+ Call->getBeginLoc(), Call, Call->getDirectCallee()))
return ExprError();
}
@@ -6707,7 +6746,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
<< BaseType << Base->getSourceRange();
CallExpr *CE = dyn_cast<CallExpr>(Base);
if (Decl *CD = (CE ? CE->getCalleeDecl() : nullptr)) {
- Diag(CD->getLocStart(),
+ Diag(CD->getBeginLoc(),
diag::note_member_reference_arrow_from_operator_arrow);
}
}
@@ -7162,9 +7201,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
- CXXMemberCallExpr *CE =
- new (Context) CXXMemberCallExpr(Context, ME, None, ResultType, VK,
- Exp.get()->getLocEnd());
+ CXXMemberCallExpr *CE = CXXMemberCallExpr::Create(
+ Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc());
if (CheckFunctionCall(Method, CE,
Method->getType()->castAs<FunctionProtoType>()))
@@ -7752,41 +7790,24 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl,
ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
bool DiscardedValue,
- bool IsConstexpr,
- bool IsLambdaInitCaptureInitializer) {
+ bool IsConstexpr) {
ExprResult FullExpr = FE;
if (!FullExpr.get())
return ExprError();
- // If we are an init-expression in a lambdas init-capture, we should not
- // diagnose an unexpanded pack now (will be diagnosed once lambda-expr
- // containing full-expression is done).
- // template<class ... Ts> void test(Ts ... t) {
- // test([&a(t)]() { <-- (t) is an init-expr that shouldn't be diagnosed now.
- // return a;
- // }() ...);
- // }
- // FIXME: This is a hack. It would be better if we pushed the lambda scope
- // when we parse the lambda introducer, and teach capturing (but not
- // unexpanded pack detection) to walk over LambdaScopeInfos which don't have a
- // corresponding class yet (that is, have LambdaScopeInfo either represent a
- // lambda where we've entered the introducer but not the body, or represent a
- // lambda where we've entered the body, depending on where the
- // parser/instantiation has got to).
- if (!IsLambdaInitCaptureInitializer &&
- DiagnoseUnexpandedParameterPack(FullExpr.get()))
+ if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
return ExprError();
- // Top-level expressions default to 'id' when we're in a debugger.
- if (DiscardedValue && getLangOpts().DebuggerCastResultToId &&
- FullExpr.get()->getType() == Context.UnknownAnyTy) {
- FullExpr = forceUnknownAnyToType(FullExpr.get(), Context.getObjCIdType());
- if (FullExpr.isInvalid())
- return ExprError();
- }
-
if (DiscardedValue) {
+ // Top-level expressions default to 'id' when we're in a debugger.
+ if (getLangOpts().DebuggerCastResultToId &&
+ FullExpr.get()->getType() == Context.UnknownAnyTy) {
+ FullExpr = forceUnknownAnyToType(FullExpr.get(), Context.getObjCIdType());
+ if (FullExpr.isInvalid())
+ return ExprError();
+ }
+
FullExpr = CheckPlaceholderExpr(FullExpr.get());
if (FullExpr.isInvalid())
return ExprError();
@@ -7794,6 +7815,8 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
FullExpr = IgnoredValueConversions(FullExpr.get());
if (FullExpr.isInvalid())
return ExprError();
+
+ DiagnoseUnusedExprResult(FullExpr.get());
}
FullExpr = CorrectDelayedTyposInExpr(FullExpr.get());
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index e6d2b5068fd5..b2b21ba9eefa 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -496,7 +496,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
// allows this, while still reporting an error if T is a struct pointer.
if (!IsArrow) {
const PointerType *PT = BaseType->getAs<PointerType>();
- if (PT && (!getLangOpts().ObjC1 ||
+ if (PT && (!getLangOpts().ObjC ||
PT->getPointeeType()->isRecordType())) {
assert(BaseExpr && "cannot happen with implicit member accesses");
Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
@@ -1708,9 +1708,31 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
}
ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
- return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS,
- TemplateKWLoc, FirstQualifierInScope,
- NameInfo, TemplateArgs, S, &ExtraArgs);
+ ExprResult Res = BuildMemberReferenceExpr(
+ Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,
+ FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs);
+
+ if (!Res.isInvalid() && isa<MemberExpr>(Res.get()))
+ CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get()));
+
+ return Res;
+}
+
+void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {
+ QualType ResultTy = E->getType();
+
+ // Do not warn on member accesses to arrays since this returns an array
+ // lvalue and does not actually dereference memory.
+ if (isa<ArrayType>(ResultTy))
+ return;
+
+ if (E->isArrow()) {
+ if (const auto *Ptr = dyn_cast<PointerType>(
+ E->getBase()->getType().getDesugaredType(Context))) {
+ if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
+ ExprEvalContexts.back().PossibleDerefs.insert(E);
+ }
+ }
}
ExprResult
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b291fc8691d5..ed780efd4cf3 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -50,8 +50,8 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
// ObjC strings can't be wide or UTF.
if (!S->isAscii()) {
- Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
- << S->getSourceRange();
+ Diag(S->getBeginLoc(), diag::err_cfstring_literal_not_string_constant)
+ << S->getSourceRange();
return true;
}
@@ -107,8 +107,8 @@ ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
} else {
// If there is no NSConstantString interface defined then treat this
// as error and recover from it.
- Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent
- << S->getSourceRange();
+ Diag(S->getBeginLoc(), diag::err_no_nsconstant_string_class)
+ << NSIdent << S->getSourceRange();
Ty = Context.getObjCIdType();
}
} else {
@@ -399,9 +399,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
InitializedEntity Entity
= InitializedEntity::InitializeParameter(S.Context, T,
/*Consumed=*/false);
- InitializationKind Kind
- = InitializationKind::CreateCopy(Element->getLocStart(),
- SourceLocation());
+ InitializationKind Kind = InitializationKind::CreateCopy(
+ Element->getBeginLoc(), SourceLocation());
InitializationSequence Seq(S, Entity, Kind, Element);
if (!Seq.Failed())
return Seq.Perform(S, Entity, Kind, Element);
@@ -432,12 +431,12 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2
: 3;
- S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
- << Which << OrigElement->getSourceRange()
- << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
+ S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)
+ << Which << OrigElement->getSourceRange()
+ << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");
- Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(),
- OrigElement);
+ Result =
+ S.BuildObjCNumericLiteral(OrigElement->getBeginLoc(), OrigElement);
if (Result.isInvalid())
return ExprError();
@@ -448,11 +447,11 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
// If this is potentially an Objective-C string literal, add the '@'.
else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) {
if (String->isAscii()) {
- S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
- << 0 << OrigElement->getSourceRange()
- << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
+ S.Diag(OrigElement->getBeginLoc(), diag::err_box_literal_collection)
+ << 0 << OrigElement->getSourceRange()
+ << FixItHint::CreateInsertion(OrigElement->getBeginLoc(), "@");
- Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String);
+ Result = S.BuildObjCStringLiteral(OrigElement->getBeginLoc(), String);
if (Result.isInvalid())
return ExprError();
@@ -462,8 +461,8 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
}
if (!Recovered) {
- S.Diag(Element->getLocStart(), diag::err_invalid_collection_element)
- << Element->getType();
+ S.Diag(Element->getBeginLoc(), diag::err_invalid_collection_element)
+ << Element->getType();
return ExprError();
}
}
@@ -481,9 +480,9 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
break;
}
if (!hasMacro)
- S.Diag(Element->getLocStart(),
+ S.Diag(Element->getBeginLoc(),
diag::warn_concatenated_nsarray_literal)
- << Element->getType();
+ << Element->getType();
}
}
}
@@ -491,9 +490,9 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
// Make sure that the element has the type that the container factory
// function expects.
return S.PerformCopyInitialization(
- InitializedEntity::InitializeParameter(S.Context, T,
- /*Consumed=*/false),
- Element->getLocStart(), Element);
+ InitializedEntity::InitializeParameter(S.Context, T,
+ /*Consumed=*/false),
+ Element->getBeginLoc(), Element);
}
ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
@@ -1034,8 +1033,8 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
!Element.Value->containsUnexpandedParameterPack()) {
Diag(Element.EllipsisLoc,
diag::err_pack_expansion_without_parameter_packs)
- << SourceRange(Element.Key->getLocStart(),
- Element.Value->getLocEnd());
+ << SourceRange(Element.Key->getBeginLoc(),
+ Element.Value->getEndLoc());
return ExprError();
}
@@ -1228,8 +1227,12 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
return true;
}
- if (PDecl->hasDefinition())
+ if (!PDecl->hasDefinition()) {
+ Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl;
+ Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
+ } else {
PDecl = PDecl->getDefinition();
+ }
QualType Ty = Context.getObjCProtoType();
if (Ty.isNull())
@@ -1343,7 +1346,8 @@ static QualType getBaseMessageSendResultType(Sema &S,
return transferNullability(ReceiverType);
}
-QualType Sema::getMessageSendResultType(QualType ReceiverType,
+QualType Sema::getMessageSendResultType(const Expr *Receiver,
+ QualType ReceiverType,
ObjCMethodDecl *Method,
bool isClassMessage,
bool isSuperMessage) {
@@ -1354,8 +1358,33 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
isSuperMessage);
// If this is a class message, ignore the nullability of the receiver.
- if (isClassMessage)
+ if (isClassMessage) {
+ // In a class method, class messages to 'self' that return instancetype can
+ // be typed as the current class. We can safely do this in ARC because self
+ // can't be reassigned, and we do it unsafely outside of ARC because in
+ // practice people never reassign self in class methods and there's some
+ // virtue in not being aggressively pedantic.
+ if (Receiver && Receiver->isObjCSelfExpr()) {
+ assert(ReceiverType->isObjCClassType() && "expected a Class self");
+ QualType T = Method->getSendResultType(ReceiverType);
+ AttributedType::stripOuterNullability(T);
+ if (T == Context.getObjCInstanceType()) {
+ const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(
+ cast<ImplicitParamDecl>(
+ cast<DeclRefExpr>(Receiver->IgnoreParenImpCasts())->getDecl())
+ ->getDeclContext());
+ assert(MD->isClassMethod() && "expected a class method");
+ QualType NewResultType = Context.getObjCObjectPointerType(
+ Context.getObjCInterfaceType(MD->getClassInterface()));
+ if (auto Nullability = resultType->getNullability(Context))
+ NewResultType = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*Nullability),
+ NewResultType, NewResultType);
+ return NewResultType;
+ }
+ }
return resultType;
+ }
// There is nothing left to do if the result type cannot have a nullability
// specifier.
@@ -1502,15 +1531,12 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) {
<< MsgSend->getType();
}
-bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
- MultiExprArg Args,
- Selector Sel,
- ArrayRef<SourceLocation> SelectorLocs,
- ObjCMethodDecl *Method,
- bool isClassMessage, bool isSuperMessage,
- SourceLocation lbrac, SourceLocation rbrac,
- SourceRange RecRange,
- QualType &ReturnType, ExprValueKind &VK) {
+bool Sema::CheckMessageArgumentTypes(
+ const Expr *Receiver, QualType ReceiverType, MultiExprArg Args,
+ Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method,
+ bool isClassMessage, bool isSuperMessage, SourceLocation lbrac,
+ SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType,
+ ExprValueKind &VK) {
SourceLocation SelLoc;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
SelLoc = SelectorLocs.front();
@@ -1587,8 +1613,8 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
return false;
}
- ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,
- isSuperMessage);
+ ReturnType = getMessageSendResultType(Receiver, ReceiverType, Method,
+ isClassMessage, isSuperMessage);
VK = Expr::getValueKindForType(Method->getReturnType());
unsigned NumNamedArgs = Sel.getNumArgs();
@@ -1693,12 +1719,12 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
} else {
// Check for extra arguments to non-variadic methods.
if (Args.size() != NumNamedArgs) {
- Diag(Args[NumNamedArgs]->getLocStart(),
+ Diag(Args[NumNamedArgs]->getBeginLoc(),
diag::err_typecheck_call_too_many_args)
- << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())
- << Method->getSourceRange()
- << SourceRange(Args[NumNamedArgs]->getLocStart(),
- Args.back()->getLocEnd());
+ << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())
+ << Method->getSourceRange()
+ << SourceRange(Args[NumNamedArgs]->getBeginLoc(),
+ Args.back()->getEndLoc());
}
}
@@ -2323,7 +2349,7 @@ static void checkFoundationAPI(Sema &S, SourceLocation Loc,
<< (!Ret->isRecordType()
? /*Vector*/ 2
: Ret->isUnionType() ? /*Union*/ 1 : /*Struct*/ 0);
- S.Diag(ImpliedMethod->getLocStart(),
+ S.Diag(ImpliedMethod->getBeginLoc(),
diag::note_objc_unsafe_perform_selector_method_declared_here)
<< ImpliedMethod->getSelector() << Ret;
}
@@ -2468,7 +2494,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
if (!Method)
Method = Class->lookupPrivateClassMethod(Sel);
- if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs,
+ nullptr, false, false, Class))
return ExprError();
}
@@ -2478,12 +2505,10 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
- if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
- Sel, SelectorLocs,
- Method, true,
- SuperLoc.isValid(), LBracLoc, RBracLoc,
- SourceRange(),
- ReturnType, VK))
+ if (CheckMessageArgumentTypes(/*Receiver=*/nullptr, ReceiverType,
+ MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
+ Method, true, SuperLoc.isValid(), LBracLoc,
+ RBracLoc, SourceRange(), ReturnType, VK))
return ExprError();
if (Method && !Method->getReturnType()->isVoidType() &&
@@ -2582,7 +2607,7 @@ static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) {
return false;
const IdentifierInfo *II = S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject);
if (const auto *RootClass = dyn_cast_or_null<ObjCInterfaceDecl>(
- S.LookupSingleName(S.TUScope, II, Protocol->getLocStart(),
+ S.LookupSingleName(S.TUScope, II, Protocol->getBeginLoc(),
Sema::LookupOrdinaryName))) {
for (const ObjCProtocolDecl *P : RootClass->all_referenced_protocols()) {
if (P->getCanonicalDecl() == Protocol->getCanonicalDecl())
@@ -2635,7 +2660,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
"use it instead.");
// The location of the receiver.
- SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
+ SourceLocation Loc = SuperLoc.isValid() ? SuperLoc : Receiver->getBeginLoc();
SourceRange RecRange =
SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
ArrayRef<SourceLocation> SelectorSlotLocs;
@@ -2781,14 +2806,19 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
} else {
if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+ // FIXME: Is this correct? Why are we assuming that a message to
+ // Class will call a method in the current interface?
+
// First check the public methods in the class interface.
Method = ClassDecl->lookupClassMethod(Sel);
if (!Method)
Method = ClassDecl->lookupPrivateClassMethod(Sel);
+
+ if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, nullptr,
+ false, false, ClassDecl))
+ return ExprError();
}
- if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs))
- return ExprError();
}
if (!Method) {
// If not messaging 'self', look for any factory method named 'Sel'.
@@ -2856,8 +2886,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
return ExprError();
forwardClass = OCIType->getInterfaceDecl();
- Diag(Receiver ? Receiver->getLocStart()
- : SuperLoc, diag::note_receiver_is_id);
+ Diag(Receiver ? Receiver->getBeginLoc() : SuperLoc,
+ diag::note_receiver_is_id);
Method = nullptr;
} else {
Method = ClassDecl->lookupInstanceMethod(Sel);
@@ -2973,9 +3003,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
ExprValueKind VK = VK_RValue;
bool ClassMessage = (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType());
- if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
- Sel, SelectorLocs, Method,
- ClassMessage, SuperLoc.isValid(),
+ if (CheckMessageArgumentTypes(Receiver, ReceiverType,
+ MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
+ Method, ClassMessage, SuperLoc.isValid(),
LBracLoc, RBracLoc, RecRange, ReturnType, VK))
return ExprError();
@@ -3131,7 +3161,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak;
if (!IsWeak && Sel.isUnarySelector())
IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
- if (IsWeak &&
+ if (IsWeak && !isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, LBracLoc))
getCurFunction()->recordUseOfWeak(Result, Prop);
}
@@ -3776,8 +3806,8 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
(CastClass && CastClass->isSuperClassOf(ExprClass)))
return true;
if (warn)
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
- << T << Target->getName() << castType->getPointeeType();
+ S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)
+ << T << Target->getName() << castType->getPointeeType();
return false;
} else if (castType->isObjCIdType() ||
(S.Context.ObjCObjectAdoptsQTypeProtocols(
@@ -3788,20 +3818,21 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
return true;
else {
if (warn) {
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
- << T << Target->getName() << castType;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
- S.Diag(Target->getLocStart(), diag::note_declared_at);
+ S.Diag(castExpr->getBeginLoc(), diag::warn_objc_invalid_bridge)
+ << T << Target->getName() << castType;
+ S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
+ S.Diag(Target->getBeginLoc(), diag::note_declared_at);
}
return false;
}
}
} else if (!castType->isObjCIdType()) {
- S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
- << castExpr->getType() << Parm;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(castExpr->getBeginLoc(),
+ diag::err_objc_cf_bridged_not_interface)
+ << castExpr->getType() << Parm;
+ S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
if (Target)
- S.Diag(Target->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getBeginLoc(), diag::note_declared_at);
}
return true;
}
@@ -3841,9 +3872,10 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,
(ExprClass && CastClass->isSuperClassOf(ExprClass)))
return true;
if (warn) {
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
- << castExpr->getType()->getPointeeType() << T;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(castExpr->getBeginLoc(),
+ diag::warn_objc_invalid_bridge_to_cf)
+ << castExpr->getType()->getPointeeType() << T;
+ S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
}
return false;
} else if (castExpr->getType()->isObjCIdType() ||
@@ -3855,20 +3887,22 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,
return true;
else {
if (warn) {
- S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
- << castExpr->getType() << castType;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
- S.Diag(Target->getLocStart(), diag::note_declared_at);
+ S.Diag(castExpr->getBeginLoc(),
+ diag::warn_objc_invalid_bridge_to_cf)
+ << castExpr->getType() << castType;
+ S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
+ S.Diag(Target->getBeginLoc(), diag::note_declared_at);
}
return false;
}
}
}
- S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject)
- << castExpr->getType() << castType;
- S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(castExpr->getBeginLoc(),
+ diag::err_objc_ns_bridged_invalid_cfobject)
+ << castExpr->getType() << castType;
+ S.Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
if (Target)
- S.Diag(Target->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getBeginLoc(), diag::note_declared_at);
return true;
}
return false;
@@ -3879,7 +3913,7 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,
}
void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
- if (!getLangOpts().ObjC1)
+ if (!getLangOpts().ObjC)
return;
// warn in presence of __bridge casting to or from a toll free bridge cast.
ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());
@@ -3945,13 +3979,13 @@ void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) {
ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType);
if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation)
return;
- CheckObjCBridgeRelatedConversions(castExpr->getLocStart(),
- castType, SrcType, castExpr);
+ CheckObjCBridgeRelatedConversions(castExpr->getBeginLoc(), castType, SrcType,
+ castExpr);
}
bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
CastKind &Kind) {
- if (!getLangOpts().ObjC1)
+ if (!getLangOpts().ObjC)
return false;
ARCConversionTypeClass exprACTC =
classifyTypeForARCConversion(castExpr->getType());
@@ -3991,7 +4025,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
if (Diagnose) {
Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId
<< SrcType << DestType;
- Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
}
return false;
}
@@ -4002,9 +4036,9 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
if (Diagnose) {
Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId
<< SrcType << DestType;
- Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
if (Target)
- Diag(Target->getLocStart(), diag::note_declared_at);
+ Diag(Target->getBeginLoc(), diag::note_declared_at);
}
return false;
}
@@ -4017,7 +4051,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
if (Diagnose) {
Diag(Loc, diag::err_objc_bridged_related_known_method)
<< SrcType << DestType << Sel << false;
- Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
}
return false;
}
@@ -4031,7 +4065,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
if (Diagnose) {
Diag(Loc, diag::err_objc_bridged_related_known_method)
<< SrcType << DestType << Sel << true;
- Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
}
return false;
}
@@ -4067,14 +4101,16 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
ExpressionString += RelatedClass->getNameAsString();
ExpressionString += " ";
ExpressionString += ClassMethod->getSelector().getAsString();
- SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd());
+ SourceLocation SrcExprEndLoc =
+ getLocForEndOfToken(SrcExpr->getEndLoc());
// Provide a fixit: [RelatedClass ClassMethod SrcExpr]
Diag(Loc, diag::err_objc_bridged_related_known_method)
- << SrcType << DestType << ClassMethod->getSelector() << false
- << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString)
- << FixItHint::CreateInsertion(SrcExprEndLoc, "]");
- Diag(RelatedClass->getLocStart(), diag::note_declared_at);
- Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ << SrcType << DestType << ClassMethod->getSelector() << false
+ << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(),
+ ExpressionString)
+ << FixItHint::CreateInsertion(SrcExprEndLoc, "]");
+ Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);
+ Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
QualType receiverType = Context.getObjCInterfaceType(RelatedClass);
// Argument.
@@ -4094,7 +4130,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
if (Diagnose) {
std::string ExpressionString;
SourceLocation SrcExprEndLoc =
- getLocForEndOfToken(SrcExpr->getLocEnd());
+ getLocForEndOfToken(SrcExpr->getEndLoc());
if (InstanceMethod->isPropertyAccessor())
if (const ObjCPropertyDecl *PDecl =
InstanceMethod->findPropertyDecl()) {
@@ -4113,11 +4149,11 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
Diag(Loc, diag::err_objc_bridged_related_known_method)
<< SrcType << DestType << InstanceMethod->getSelector() << true
- << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[")
+ << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "[")
<< FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
}
- Diag(RelatedClass->getLocStart(), diag::note_declared_at);
- Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ Diag(RelatedClass->getBeginLoc(), diag::note_declared_at);
+ Diag(TDNDecl->getBeginLoc(), diag::note_declared_at);
ExprResult msg =
BuildInstanceMessageImplicit(SrcExpr, SrcType,
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index f006a677b678..10c0c6bf33b3 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -194,15 +194,15 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
// [dcl.init.string]p2
if (StrLength > CAT->getSize().getZExtValue())
- S.Diag(Str->getLocStart(),
+ S.Diag(Str->getBeginLoc(),
diag::err_initializer_string_for_char_array_too_long)
- << Str->getSourceRange();
+ << Str->getSourceRange();
} else {
// C99 6.7.8p14.
if (StrLength-1 > CAT->getSize().getZExtValue())
- S.Diag(Str->getLocStart(),
+ S.Diag(Str->getBeginLoc(),
diag::ext_initializer_string_for_char_array_too_long)
- << Str->getSourceRange();
+ << Str->getSourceRange();
}
// Set the type to the actual size that we are initializing. If we have
@@ -518,10 +518,10 @@ void InitListChecker::FillInEmptyInitForBase(
if (!ILE->getInit(Init)) {
ExprResult BaseInit =
- FillWithNoInit ? new (SemaRef.Context) NoInitExpr(Base.getType())
- : PerformEmptyInit(SemaRef, ILE->getLocEnd(), BaseEntity,
- /*VerifyOnly*/ false,
- TreatUnavailableAsInvalid);
+ FillWithNoInit
+ ? new (SemaRef.Context) NoInitExpr(Base.getType())
+ : PerformEmptyInit(SemaRef, ILE->getEndLoc(), BaseEntity,
+ /*VerifyOnly*/ false, TreatUnavailableAsInvalid);
if (BaseInit.isInvalid()) {
hadError = true;
return;
@@ -545,7 +545,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
InitListExpr *ILE,
bool &RequiresSecondPass,
bool FillWithNoInit) {
- SourceLocation Loc = ILE->getLocEnd();
+ SourceLocation Loc = ILE->getEndLoc();
unsigned NumInits = ILE->getNumInits();
InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(Field, &ParentEntity);
@@ -765,10 +765,9 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
if (FillWithNoInit)
Filler = new (SemaRef.Context) NoInitExpr(ElementType);
else {
- ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(),
- ElementEntity,
- /*VerifyOnly*/false,
- TreatUnavailableAsInvalid);
+ ExprResult ElementInit =
+ PerformEmptyInit(SemaRef, ILE->getEndLoc(), ElementEntity,
+ /*VerifyOnly*/ false, TreatUnavailableAsInvalid);
if (ElementInit.isInvalid()) {
hadError = true;
return;
@@ -917,7 +916,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
if (maxElements == 0) {
if (!VerifyOnly)
- SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
+ SemaRef.Diag(ParentIList->getInit(Index)->getBeginLoc(),
diag::err_implicit_empty_initializer);
++Index;
hadError = true;
@@ -925,11 +924,10 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
}
// Build a structured initializer list corresponding to this subobject.
- InitListExpr *StructuredSubobjectInitList
- = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList,
- StructuredIndex,
- SourceRange(ParentIList->getInit(Index)->getLocStart(),
- ParentIList->getSourceRange().getEnd()));
+ InitListExpr *StructuredSubobjectInitList = getStructuredSubobjectInit(
+ ParentIList, Index, T, StructuredList, StructuredIndex,
+ SourceRange(ParentIList->getInit(Index)->getBeginLoc(),
+ ParentIList->getSourceRange().getEnd()));
unsigned StructuredSubobjectInitIndex = 0;
// Check the element types and build the structural subobject.
@@ -956,16 +954,24 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
if ((T->isArrayType() || T->isRecordType()) &&
!ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
!isIdiomaticBraceElisionEntity(Entity)) {
- SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
+ SemaRef.Diag(StructuredSubobjectInitList->getBeginLoc(),
diag::warn_missing_braces)
<< StructuredSubobjectInitList->getSourceRange()
<< FixItHint::CreateInsertion(
- StructuredSubobjectInitList->getLocStart(), "{")
+ StructuredSubobjectInitList->getBeginLoc(), "{")
<< FixItHint::CreateInsertion(
SemaRef.getLocForEndOfToken(
- StructuredSubobjectInitList->getLocEnd()),
+ StructuredSubobjectInitList->getEndLoc()),
"}");
}
+
+ // Warn if this type won't be an aggregate in future versions of C++.
+ auto *CXXRD = T->getAsCXXRecordDecl();
+ if (CXXRD && CXXRD->hasUserDeclaredConstructor()) {
+ SemaRef.Diag(StructuredSubobjectInitList->getBeginLoc(),
+ diag::warn_cxx2a_compat_aggregate_init_with_ctors)
+ << StructuredSubobjectInitList->getSourceRange() << T;
+ }
}
}
@@ -1080,8 +1086,8 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
hadError = true;
}
// Special-case
- SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
- << IList->getInit(Index)->getSourceRange();
+ SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
+ << IList->getInit(Index)->getSourceRange();
} else if (!T->isIncompleteType()) {
// Don't complain for incomplete types, since we'll get an error
// elsewhere
@@ -1103,14 +1109,35 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
hadError = true;
}
- SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
- << initKind << IList->getInit(Index)->getSourceRange();
+ SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
+ << initKind << IList->getInit(Index)->getSourceRange();
}
}
- if (!VerifyOnly && T->isScalarType() &&
- IList->getNumInits() == 1 && !isa<InitListExpr>(IList->getInit(0)))
- warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());
+ if (!VerifyOnly) {
+ if (T->isScalarType() && IList->getNumInits() == 1 &&
+ !isa<InitListExpr>(IList->getInit(0)))
+ warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());
+
+ // Warn if this is a class type that won't be an aggregate in future
+ // versions of C++.
+ auto *CXXRD = T->getAsCXXRecordDecl();
+ if (CXXRD && CXXRD->hasUserDeclaredConstructor()) {
+ // Don't warn if there's an equivalent default constructor that would be
+ // used instead.
+ bool HasEquivCtor = false;
+ if (IList->getNumInits() == 0) {
+ auto *CD = SemaRef.LookupDefaultConstructor(CXXRD);
+ HasEquivCtor = CD && !CD->isDeleted();
+ }
+
+ if (!HasEquivCtor) {
+ SemaRef.Diag(IList->getBeginLoc(),
+ diag::warn_cxx2a_compat_aggregate_init_with_ctors)
+ << IList->getSourceRange() << T;
+ }
+ }
+ }
}
void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
@@ -1155,21 +1182,24 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
// This type is invalid, issue a diagnostic.
++Index;
if (!VerifyOnly)
- SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
- << DeclType;
+ SemaRef.Diag(IList->getBeginLoc(), diag::err_illegal_initializer_type)
+ << DeclType;
hadError = true;
} else if (DeclType->isReferenceType()) {
CheckReferenceType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
} else if (DeclType->isObjCObjectType()) {
if (!VerifyOnly)
- SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
- << DeclType;
+ SemaRef.Diag(IList->getBeginLoc(), diag::err_init_objc_class) << DeclType;
hadError = true;
+ } else if (DeclType->isOCLIntelSubgroupAVCType()) {
+ // Checks for scalar type are sufficient for these types too.
+ CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
+ StructuredIndex);
} else {
if (!VerifyOnly)
- SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
- << DeclType;
+ SemaRef.Diag(IList->getBeginLoc(), diag::err_illegal_initializer_type)
+ << DeclType;
hadError = true;
}
}
@@ -1232,7 +1262,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// FIXME: Better EqualLoc?
InitializationKind Kind =
- InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
+ InitializationKind::CreateCopy(expr->getBeginLoc(), SourceLocation());
InitializationSequence Seq(SemaRef, Entity, Kind, expr,
/*TopLevelOfInitList*/ true);
@@ -1356,8 +1386,8 @@ void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
// This is an extension in C. (The builtin _Complex type does not exist
// in the C++ standard.)
if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly)
- SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init)
- << IList->getSourceRange();
+ SemaRef.Diag(IList->getBeginLoc(), diag::ext_complex_component_init)
+ << IList->getSourceRange();
// Initialize the complex number.
QualType elementType = DeclType->getAs<ComplexType>()->getElementType();
@@ -1378,11 +1408,11 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
unsigned &StructuredIndex) {
if (Index >= IList->getNumInits()) {
if (!VerifyOnly)
- SemaRef.Diag(IList->getLocStart(),
- SemaRef.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_empty_scalar_initializer :
- diag::err_empty_scalar_initializer)
- << IList->getSourceRange();
+ SemaRef.Diag(IList->getBeginLoc(),
+ SemaRef.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_empty_scalar_initializer
+ : diag::err_empty_scalar_initializer)
+ << IList->getSourceRange();
hadError = !SemaRef.getLangOpts().CPlusPlus11;
++Index;
++StructuredIndex;
@@ -1394,18 +1424,17 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
// FIXME: This is invalid, and accepting it causes overload resolution
// to pick the wrong overload in some corner cases.
if (!VerifyOnly)
- SemaRef.Diag(SubIList->getLocStart(),
+ SemaRef.Diag(SubIList->getBeginLoc(),
diag::ext_many_braces_around_scalar_init)
- << SubIList->getSourceRange();
+ << SubIList->getSourceRange();
CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
StructuredIndex);
return;
} else if (isa<DesignatedInitExpr>(expr)) {
if (!VerifyOnly)
- SemaRef.Diag(expr->getLocStart(),
- diag::err_designator_for_scalar_init)
- << DeclType << expr->getSourceRange();
+ SemaRef.Diag(expr->getBeginLoc(), diag::err_designator_for_scalar_init)
+ << DeclType << expr->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
@@ -1420,8 +1449,8 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
}
ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr,
- /*TopLevelOfInitList=*/true);
+ SemaRef.PerformCopyInitialization(Entity, expr->getBeginLoc(), expr,
+ /*TopLevelOfInitList=*/true);
Expr *ResultExpr = nullptr;
@@ -1453,10 +1482,9 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
// so that we know the location (or decl) of the "current object" being
// initialized.
if (!VerifyOnly)
- SemaRef.Diag(IList->getLocStart(),
- diag::err_init_reference_member_uninitialized)
- << DeclType
- << IList->getSourceRange();
+ SemaRef.Diag(IList->getBeginLoc(),
+ diag::err_init_reference_member_uninitialized)
+ << DeclType << IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
@@ -1466,8 +1494,8 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
Expr *expr = IList->getInit(Index);
if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus11) {
if (!VerifyOnly)
- SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
- << DeclType << IList->getSourceRange();
+ SemaRef.Diag(IList->getBeginLoc(), diag::err_init_non_aggr_init_list)
+ << DeclType << IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
@@ -1482,7 +1510,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
}
ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr,
+ SemaRef.PerformCopyInitialization(Entity, expr->getBeginLoc(), expr,
/*TopLevelOfInitList=*/true);
if (Result.isInvalid())
@@ -1513,7 +1541,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
if (VerifyOnly)
CheckEmptyInitializable(
InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity),
- IList->getLocEnd());
+ IList->getEndLoc());
return;
}
@@ -1529,9 +1557,9 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
return;
}
- ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(), Init,
- /*TopLevelOfInitList=*/true);
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, Init->getBeginLoc(), Init,
+ /*TopLevelOfInitList=*/true);
Expr *ResultExpr = nullptr;
if (Result.isInvalid())
@@ -1560,7 +1588,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
// Don't attempt to go past the end of the init list
if (Index >= IList->getNumInits()) {
if (VerifyOnly)
- CheckEmptyInitializable(ElementEntity, IList->getLocEnd());
+ CheckEmptyInitializable(ElementEntity, IList->getEndLoc());
break;
}
@@ -1586,7 +1614,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
//
// Because of this, explicitly call out that it is non-portable.
//
- SemaRef.Diag(IList->getLocStart(),
+ SemaRef.Diag(IList->getBeginLoc(),
diag::warn_neon_vector_initializer_non_portable);
const char *typeCode;
@@ -1601,11 +1629,11 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
else
llvm_unreachable("Invalid element type!");
- SemaRef.Diag(IList->getLocStart(),
- SemaRef.Context.getTypeSize(VT) > 64 ?
- diag::note_neon_vector_initializer_non_portable_q :
- diag::note_neon_vector_initializer_non_portable)
- << typeCode << typeSize;
+ SemaRef.Diag(IList->getBeginLoc(),
+ SemaRef.Context.getTypeSize(VT) > 64
+ ? diag::note_neon_vector_initializer_non_portable_q
+ : diag::note_neon_vector_initializer_non_portable)
+ << typeCode << typeSize;
}
return;
@@ -1646,9 +1674,9 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
// OpenCL requires all elements to be initialized.
if (numEltsInit != maxElements) {
if (!VerifyOnly)
- SemaRef.Diag(IList->getLocStart(),
+ SemaRef.Diag(IList->getBeginLoc(),
diag::err_vector_incorrect_num_initializers)
- << (numEltsInit < maxElements) << maxElements << numEltsInit;
+ << (numEltsInit < maxElements) << maxElements << numEltsInit;
hadError = true;
}
}
@@ -1686,9 +1714,9 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// earlier, but I don't know where clang accepts VLAs (gcc accepts
// them in all sorts of strange places).
if (!VerifyOnly)
- SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
- diag::err_variable_object_no_init)
- << VAT->getSizeExpr()->getSourceRange();
+ SemaRef.Diag(VAT->getSizeExpr()->getBeginLoc(),
+ diag::err_variable_object_no_init)
+ << VAT->getSizeExpr()->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
@@ -1765,8 +1793,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
if (maxElements == Zero && !Entity.isVariableLengthArrayNew()) {
// Sizing an array implicitly to zero is not allowed by ISO C,
// but is supported by GNU.
- SemaRef.Diag(IList->getLocStart(),
- diag::ext_typecheck_zero_array_size);
+ SemaRef.Diag(IList->getBeginLoc(), diag::ext_typecheck_zero_array_size);
}
DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
@@ -1780,9 +1807,9 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// FIXME: This needs to detect holes left by designated initializers too.
if ((maxElementsKnown && elementIndex < maxElements) ||
Entity.isVariableLengthArrayNew())
- CheckEmptyInitializable(InitializedEntity::InitializeElement(
- SemaRef.Context, 0, Entity),
- IList->getLocEnd());
+ CheckEmptyInitializable(
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity),
+ IList->getEndLoc());
}
}
@@ -1815,9 +1842,8 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
}
if (!VerifyOnly) {
- SemaRef.Diag(InitExpr->getLocStart(),
- FlexArrayDiag)
- << InitExpr->getLocStart();
+ SemaRef.Diag(InitExpr->getBeginLoc(), FlexArrayDiag)
+ << InitExpr->getBeginLoc();
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
<< Field;
}
@@ -1825,6 +1851,30 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
return FlexArrayDiag != diag::ext_flexible_array_init;
}
+/// Check if the type of a class element has an accessible destructor.
+///
+/// Aggregate initialization requires a class element's destructor be
+/// accessible per 11.6.1 [dcl.init.aggr]:
+///
+/// The destructor for each element of class type is potentially invoked
+/// (15.4 [class.dtor]) from the context where the aggregate initialization
+/// occurs.
+static bool hasAccessibleDestructor(QualType ElementType, SourceLocation Loc,
+ Sema &SemaRef) {
+ auto *CXXRD = ElementType->getAsCXXRecordDecl();
+ if (!CXXRD)
+ return false;
+
+ CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD);
+ SemaRef.CheckDestructorAccess(Loc, Destructor,
+ SemaRef.PDiag(diag::err_access_dtor_temp)
+ << ElementType);
+ SemaRef.MarkFunctionReferenced(Loc, Destructor);
+ if (SemaRef.DiagnoseUseOfDecl(Destructor, Loc))
+ return true;
+ return false;
+}
+
void InitListChecker::CheckStructUnionTypes(
const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType,
CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field,
@@ -1845,6 +1895,15 @@ void InitListChecker::CheckStructUnionTypes(
if (DeclType->isUnionType() && IList->getNumInits() == 0) {
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+ if (!VerifyOnly)
+ for (FieldDecl *FD : RD->fields()) {
+ QualType ET = SemaRef.Context.getBaseElementType(FD->getType());
+ if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) {
+ hadError = true;
+ return;
+ }
+ }
+
// If there's a default initializer, use it.
if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->hasInClassInitializer()) {
if (VerifyOnly)
@@ -1867,7 +1926,7 @@ void InitListChecker::CheckStructUnionTypes(
if (VerifyOnly)
CheckEmptyInitializable(
InitializedEntity::InitializeMember(*Field, &Entity),
- IList->getLocEnd());
+ IList->getEndLoc());
else
StructuredList->setInitializedFieldInUnion(*Field);
break;
@@ -1881,13 +1940,13 @@ void InitListChecker::CheckStructUnionTypes(
// If we have any base classes, they are initialized prior to the fields.
for (auto &Base : Bases) {
Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr;
- SourceLocation InitLoc = Init ? Init->getLocStart() : IList->getLocEnd();
// Designated inits always initialize fields, so if we see one, all
// remaining base classes have no explicit initializer.
if (Init && isa<DesignatedInitExpr>(Init))
Init = nullptr;
+ SourceLocation InitLoc = Init ? Init->getBeginLoc() : IList->getEndLoc();
InitializedEntity BaseEntity = InitializedEntity::InitializeBase(
SemaRef.Context, &Base, false, &Entity);
if (Init) {
@@ -1897,6 +1956,12 @@ void InitListChecker::CheckStructUnionTypes(
} else if (VerifyOnly) {
CheckEmptyInitializable(BaseEntity, InitLoc);
}
+
+ if (!VerifyOnly)
+ if (hasAccessibleDestructor(Base.getType(), InitLoc, SemaRef)) {
+ hadError = true;
+ return;
+ }
}
// If structDecl is a forward declaration, this loop won't do
@@ -1907,9 +1972,11 @@ void InitListChecker::CheckStructUnionTypes(
RecordDecl::field_iterator FieldEnd = RD->field_end();
bool CheckForMissingFields =
!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
+ bool HasDesignatedInit = false;
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
+ SourceLocation InitLoc = Init->getBeginLoc();
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
// If we're not the subobject that matches up with the '{' for
@@ -1918,6 +1985,8 @@ void InitListChecker::CheckStructUnionTypes(
if (!SubobjectIsDesignatorContext)
return;
+ HasDesignatedInit = true;
+
// Handle this designated initializer. Field will be updated to
// the next field that we'll be initializing.
if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
@@ -1925,6 +1994,17 @@ void InitListChecker::CheckStructUnionTypes(
StructuredList, StructuredIndex,
true, TopLevelObject))
hadError = true;
+ else if (!VerifyOnly) {
+ // Find the field named by the designated initializer.
+ RecordDecl::field_iterator F = RD->field_begin();
+ while (std::next(F) != Field)
+ ++F;
+ QualType ET = SemaRef.Context.getBaseElementType(F->getType());
+ if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) {
+ hadError = true;
+ return;
+ }
+ }
InitializedSomething = true;
@@ -1958,8 +2038,8 @@ void InitListChecker::CheckStructUnionTypes(
if (VerifyOnly)
InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid);
else
- InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field,
- IList->getInit(Index)->getLocStart());
+ InvalidUse = SemaRef.DiagnoseUseOfDecl(
+ *Field, IList->getInit(Index)->getBeginLoc());
if (InvalidUse) {
++Index;
++Field;
@@ -1967,6 +2047,14 @@ void InitListChecker::CheckStructUnionTypes(
continue;
}
+ if (!VerifyOnly) {
+ QualType ET = SemaRef.Context.getBaseElementType(Field->getType());
+ if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) {
+ hadError = true;
+ return;
+ }
+ }
+
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(*Field, &Entity);
CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
@@ -2005,7 +2093,22 @@ void InitListChecker::CheckStructUnionTypes(
if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
CheckEmptyInitializable(
InitializedEntity::InitializeMember(*Field, &Entity),
- IList->getLocEnd());
+ IList->getEndLoc());
+ }
+ }
+
+ // Check that the types of the remaining fields have accessible destructors.
+ if (!VerifyOnly) {
+ // If the initializer expression has a designated initializer, check the
+ // elements for which a designated initializer is not provided too.
+ RecordDecl::field_iterator I = HasDesignatedInit ? RD->field_begin()
+ : Field;
+ for (RecordDecl::field_iterator E = RD->field_end(); I != E; ++I) {
+ QualType ET = SemaRef.Context.getBaseElementType(I->getType());
+ if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) {
+ hadError = true;
+ return;
+ }
}
}
@@ -2182,11 +2285,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
ExistingInit = StructuredList->getArrayFiller();
if (!ExistingInit)
- StructuredList =
- getStructuredSubobjectInit(IList, Index, CurrentObjectType,
- StructuredList, StructuredIndex,
- SourceRange(D->getLocStart(),
- DIE->getLocEnd()));
+ StructuredList = getStructuredSubobjectInit(
+ IList, Index, CurrentObjectType, StructuredList, StructuredIndex,
+ SourceRange(D->getBeginLoc(), DIE->getEndLoc()));
else if (InitListExpr *Result = dyn_cast<InitListExpr>(ExistingInit))
StructuredList = Result;
else {
@@ -2194,10 +2295,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
dyn_cast<DesignatedInitUpdateExpr>(ExistingInit))
StructuredList = E->getUpdater();
else {
- DesignatedInitUpdateExpr *DIUE =
- new (SemaRef.Context) DesignatedInitUpdateExpr(SemaRef.Context,
- D->getLocStart(), ExistingInit,
- DIE->getLocEnd());
+ DesignatedInitUpdateExpr *DIUE = new (SemaRef.Context)
+ DesignatedInitUpdateExpr(SemaRef.Context, D->getBeginLoc(),
+ ExistingInit, DIE->getEndLoc());
StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE);
StructuredList = DIUE->getUpdater();
}
@@ -2222,14 +2322,13 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Here, xs[0].a == 0 and xs[0].b == 3, since the second,
// designated initializer re-initializes the whole
// subobject [0], overwriting previous initializers.
- SemaRef.Diag(D->getLocStart(),
+ SemaRef.Diag(D->getBeginLoc(),
diag::warn_subobject_initializer_overrides)
- << SourceRange(D->getLocStart(), DIE->getLocEnd());
+ << SourceRange(D->getBeginLoc(), DIE->getEndLoc());
- SemaRef.Diag(ExistingInit->getLocStart(),
+ SemaRef.Diag(ExistingInit->getBeginLoc(),
diag::note_previous_initializer)
- << /*FIXME:has side effects=*/0
- << ExistingInit->getSourceRange();
+ << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange();
}
}
}
@@ -2350,10 +2449,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
SemaRef.Diag(D->getFieldLoc(),
diag::warn_initializer_overrides)
<< D->getSourceRange();
- SemaRef.Diag(ExistingInit->getLocStart(),
+ SemaRef.Diag(ExistingInit->getBeginLoc(),
diag::note_previous_initializer)
- << /*FIXME:has side effects=*/0
- << ExistingInit->getSourceRange();
+ << /*FIXME:has side effects=*/0
+ << ExistingInit->getSourceRange();
}
// remove existing initializer
@@ -2395,10 +2494,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (!VerifyOnly) {
DesignatedInitExpr::Designator *NextD
= DIE->getDesignator(DesigIdx + 1);
- SemaRef.Diag(NextD->getLocStart(),
- diag::err_designator_into_flexible_array_member)
- << SourceRange(NextD->getLocStart(),
- DIE->getLocEnd());
+ SemaRef.Diag(NextD->getBeginLoc(),
+ diag::err_designator_into_flexible_array_member)
+ << SourceRange(NextD->getBeginLoc(), DIE->getEndLoc());
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
<< *Field;
}
@@ -2409,9 +2507,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
!isa<StringLiteral>(DIE->getInit())) {
// The initializer is not an initializer list.
if (!VerifyOnly) {
- SemaRef.Diag(DIE->getInit()->getLocStart(),
- diag::err_flexible_array_init_needs_braces)
- << DIE->getInit()->getSourceRange();
+ SemaRef.Diag(DIE->getInit()->getBeginLoc(),
+ diag::err_flexible_array_init_needs_braces)
+ << DIE->getInit()->getSourceRange();
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
<< *Field;
}
@@ -2553,10 +2651,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
if (DesignatedEndIndex >= MaxElements) {
if (!VerifyOnly)
- SemaRef.Diag(IndexExpr->getLocStart(),
- diag::err_array_designator_too_large)
- << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
- << IndexExpr->getSourceRange();
+ SemaRef.Diag(IndexExpr->getBeginLoc(),
+ diag::err_array_designator_too_large)
+ << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
+ << IndexExpr->getSourceRange();
++Index;
return true;
}
@@ -2728,10 +2826,8 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
SemaRef.Diag(InitRange.getBegin(),
diag::warn_subobject_initializer_overrides)
<< InitRange;
- SemaRef.Diag(ExistingInit->getLocStart(),
- diag::note_previous_initializer)
- << /*FIXME:has side effects=*/0
- << ExistingInit->getSourceRange();
+ SemaRef.Diag(ExistingInit->getBeginLoc(), diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange();
}
InitListExpr *Result
@@ -2810,14 +2906,11 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
// There is an overwrite taking place because the first braced initializer
// list "{ .a = 2 }' already provides value for .p.b (which is zero).
if (PrevInit->getSourceRange().isValid()) {
- SemaRef.Diag(expr->getLocStart(),
- diag::warn_initializer_overrides)
- << expr->getSourceRange();
+ SemaRef.Diag(expr->getBeginLoc(), diag::warn_initializer_overrides)
+ << expr->getSourceRange();
- SemaRef.Diag(PrevInit->getLocStart(),
- diag::note_previous_initializer)
- << /*FIXME:has side effects=*/0
- << PrevInit->getSourceRange();
+ SemaRef.Diag(PrevInit->getBeginLoc(), diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0 << PrevInit->getSourceRange();
}
}
@@ -2833,7 +2926,7 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
/// value of the constant expression.
static ExprResult
CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
- SourceLocation Loc = Index->getLocStart();
+ SourceLocation Loc = Index->getBeginLoc();
// Make sure this is an integer constant expression.
ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value);
@@ -2941,8 +3034,8 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
Init.getAs<Expr>());
if (!getLangOpts().C99)
- Diag(DIE->getLocStart(), diag::ext_designated_init)
- << DIE->getSourceRange();
+ Diag(DIE->getBeginLoc(), diag::ext_designated_init)
+ << DIE->getSourceRange();
return DIE;
}
@@ -3172,8 +3265,7 @@ void InitializationSequence::Step::Destroy() {
case SK_StdInitializerList:
case SK_StdInitializerListConstructorCall:
case SK_OCLSamplerInit:
- case SK_OCLZeroEvent:
- case SK_OCLZeroQueue:
+ case SK_OCLZeroOpaqueType:
break;
case SK_ConversionSequence:
@@ -3459,16 +3551,9 @@ void InitializationSequence::AddOCLSamplerInitStep(QualType T) {
Steps.push_back(S);
}
-void InitializationSequence::AddOCLZeroEventStep(QualType T) {
+void InitializationSequence::AddOCLZeroOpaqueTypeStep(QualType T) {
Step S;
- S.Kind = SK_OCLZeroEvent;
- S.Type = T;
- Steps.push_back(S);
-}
-
-void InitializationSequence::AddOCLZeroQueueStep(QualType T) {
- Step S;
- S.Kind = SK_OCLZeroQueue;
+ S.Kind = SK_OCLZeroOpaqueType;
S.Type = T;
Steps.push_back(S);
}
@@ -3507,11 +3592,11 @@ maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence,
return false;
VarDecl *VD = cast<VarDecl>(Entity.getDecl());
- if (VD->getInit() || VD->getLocEnd().isMacroID())
+ if (VD->getInit() || VD->getEndLoc().isMacroID())
return false;
QualType VariableTy = VD->getType().getCanonicalType();
- SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getEndLoc());
std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
if (!Init.empty()) {
Sequence.AddZeroInitializationStep(Entity.getType());
@@ -3583,7 +3668,7 @@ static bool TryInitializerListConstruction(Sema &S,
InitializedEntity HiddenArray =
InitializedEntity::InitializeTemporary(ArrayType);
InitializationKind Kind = InitializationKind::CreateDirectList(
- List->getExprLoc(), List->getLocStart(), List->getLocEnd());
+ List->getExprLoc(), List->getBeginLoc(), List->getEndLoc());
TryListInitialization(S, HiddenArray, Kind, List, Sequence,
TreatUnavailableAsInvalid);
if (Sequence)
@@ -3974,7 +4059,7 @@ static void TryReferenceListInitialization(Sema &S,
T1, Sequence))
return;
- SourceLocation DeclLoc = Initializer->getLocStart();
+ SourceLocation DeclLoc = Initializer->getBeginLoc();
bool dummy1, dummy2, dummy3;
Sema::ReferenceCompareResult RefRelationship
= S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1,
@@ -4031,7 +4116,7 @@ static void TryListInitialization(Sema &S,
}
if (DestType->isRecordType() &&
- !S.isCompleteType(InitList->getLocStart(), DestType)) {
+ !S.isCompleteType(InitList->getBeginLoc(), DestType)) {
Sequence.setIncompleteTypeFailure(DestType);
return;
}
@@ -4051,7 +4136,7 @@ static void TryListInitialization(Sema &S,
if (DestType->isRecordType()) {
QualType InitType = InitList->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
- S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) {
+ S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
Expr *InitListAsExpr = InitList;
TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
DestType, Sequence,
@@ -4218,9 +4303,8 @@ static OverloadingResult TryRefInitWithConversionFunction(
bool DerivedToBase;
bool ObjCConversion;
bool ObjCLifetimeConversion;
- assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
- T1, T2, DerivedToBase,
- ObjCConversion,
+ assert(!S.CompareReferenceRelationship(Initializer->getBeginLoc(), T1, T2,
+ DerivedToBase, ObjCConversion,
ObjCLifetimeConversion) &&
"Must have incompatible references when binding via conversion");
(void)DerivedToBase;
@@ -4313,7 +4397,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
return OR_No_Viable_Function;
- SourceLocation DeclLoc = Initializer->getLocStart();
+ SourceLocation DeclLoc = Initializer->getBeginLoc();
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
@@ -4439,7 +4523,7 @@ static void TryReferenceInitializationCore(Sema &S,
Qualifiers T2Quals,
InitializationSequence &Sequence) {
QualType DestType = Entity.getType();
- SourceLocation DeclLoc = Initializer->getLocStart();
+ SourceLocation DeclLoc = Initializer->getBeginLoc();
// Compute some basic properties of the types and the initializer.
bool isLValueRef = DestType->isLValueReferenceType();
bool isRValueRef = !isLValueRef;
@@ -4585,11 +4669,22 @@ static void TryReferenceInitializationCore(Sema &S,
// If the converted initializer is a prvalue, its type T4 is adjusted
// to type "cv1 T4" and the temporary materialization conversion is
// applied.
+ // Postpone address space conversions to after the temporary materialization
+ // conversion to allow creating temporaries in the alloca address space.
+ auto AS1 = T1Quals.getAddressSpace();
+ auto AS2 = T2Quals.getAddressSpace();
+ T1Quals.removeAddressSpace();
+ T2Quals.removeAddressSpace();
QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1Quals);
if (T1Quals != T2Quals)
Sequence.AddQualificationConversionStep(cv1T4, ValueKind);
Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue);
ValueKind = isLValueRef ? VK_LValue : VK_XValue;
+ if (AS1 != AS2) {
+ T1Quals.addAddressSpace(AS1);
+ QualType cv1AST4 = S.Context.getQualifiedType(cv2T2, T1Quals);
+ Sequence.AddQualificationConversionStep(cv1AST4, ValueKind);
+ }
// In any case, the reference is bound to the resulting glvalue (or to
// an appropriate base class subobject).
@@ -4867,7 +4962,7 @@ static void TryUserDefinedConversion(Sema &S,
}
}
- SourceLocation DeclLoc = Initializer->getLocStart();
+ SourceLocation DeclLoc = Initializer->getBeginLoc();
if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
// The type we're converting from is a class type, enumerate its conversion
@@ -5172,39 +5267,51 @@ static bool TryOCLSamplerInitialization(Sema &S,
return true;
}
-//
-// OpenCL 1.2 spec, s6.12.10
-//
-// The event argument can also be used to associate the
-// async_work_group_copy with a previous async copy allowing
-// an event to be shared by multiple async copies; otherwise
-// event should be zero.
-//
-static bool TryOCLZeroEventInitialization(Sema &S,
- InitializationSequence &Sequence,
- QualType DestType,
- Expr *Initializer) {
- if (!S.getLangOpts().OpenCL || !DestType->isEventT() ||
- !Initializer->isIntegerConstantExpr(S.getASTContext()) ||
- (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0))
- return false;
-
- Sequence.AddOCLZeroEventStep(DestType);
- return true;
+static bool IsZeroInitializer(Expr *Initializer, Sema &S) {
+ return Initializer->isIntegerConstantExpr(S.getASTContext()) &&
+ (Initializer->EvaluateKnownConstInt(S.getASTContext()) == 0);
}
-static bool TryOCLZeroQueueInitialization(Sema &S,
- InitializationSequence &Sequence,
- QualType DestType,
- Expr *Initializer) {
- if (!S.getLangOpts().OpenCL || S.getLangOpts().OpenCLVersion < 200 ||
- !DestType->isQueueT() ||
- !Initializer->isIntegerConstantExpr(S.getASTContext()) ||
- (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0))
+static bool TryOCLZeroOpaqueTypeInitialization(Sema &S,
+ InitializationSequence &Sequence,
+ QualType DestType,
+ Expr *Initializer) {
+ if (!S.getLangOpts().OpenCL)
return false;
- Sequence.AddOCLZeroQueueStep(DestType);
- return true;
+ //
+ // OpenCL 1.2 spec, s6.12.10
+ //
+ // The event argument can also be used to associate the
+ // async_work_group_copy with a previous async copy allowing
+ // an event to be shared by multiple async copies; otherwise
+ // event should be zero.
+ //
+ if (DestType->isEventT() || DestType->isQueueT()) {
+ if (!IsZeroInitializer(Initializer, S))
+ return false;
+
+ Sequence.AddOCLZeroOpaqueTypeStep(DestType);
+ return true;
+ }
+
+ // We should allow zero initialization for all types defined in the
+ // cl_intel_device_side_avc_motion_estimation extension, except
+ // intel_sub_group_avc_mce_payload_t and intel_sub_group_avc_mce_result_t.
+ if (S.getOpenCLOptions().isEnabled(
+ "cl_intel_device_side_avc_motion_estimation") &&
+ DestType->isOCLIntelSubgroupAVCType()) {
+ if (DestType->isOCLIntelSubgroupAVCMcePayloadType() ||
+ DestType->isOCLIntelSubgroupAVCMceResultType())
+ return false;
+ if (!IsZeroInitializer(Initializer, S))
+ return false;
+
+ Sequence.AddOCLZeroOpaqueTypeStep(DestType);
+ return true;
+ }
+
+ return false;
}
InitializationSequence::InitializationSequence(Sema &S,
@@ -5309,8 +5416,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
Expr *Initializer = nullptr;
if (Args.size() == 1) {
Initializer = Args[0];
- if (S.getLangOpts().ObjC1) {
- if (S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(),
+ if (S.getLangOpts().ObjC) {
+ if (S.CheckObjCBridgeRelatedConversions(Initializer->getBeginLoc(),
DestType, Initializer->getType(),
Initializer) ||
S.ConversionToObjCStringLiteralCheck(DestType, Initializer))
@@ -5431,7 +5538,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
// array from a compound literal that creates an array of the same
// type, so long as the initializer has no side effects.
if (!S.getLangOpts().CPlusPlus && Initializer &&
- isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
+ (isa<ConstantExpr>(Initializer->IgnoreParens()) ||
+ isa<CompoundLiteralExpr>(Initializer->IgnoreParens())) &&
Initializer->getType()->isArrayType()) {
const ArrayType *SourceAT
= Context.getAsArrayType(Initializer->getType());
@@ -5478,12 +5586,9 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
return;
- if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer))
+ if (TryOCLZeroOpaqueTypeInitialization(S, *this, DestType, Initializer))
return;
- if (TryOCLZeroQueueInitialization(S, *this, DestType, Initializer))
- return;
-
// Handle initialization in C
AddCAssignmentStep(DestType);
MaybeProduceObjCObject(S, *this, Entity);
@@ -5501,7 +5606,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Direct ||
(Kind.getKind() == InitializationKind::IK_Copy &&
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
- S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType))))
+ S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, DestType))))
TryConstructorInitialization(S, Entity, Kind, Args,
DestType, DestType, *this);
// - Otherwise (i.e., for the remaining copy-initialization cases),
@@ -5535,7 +5640,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
bool NeedAtomicConversion = false;
if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) {
if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) ||
- S.IsDerivedFrom(Initializer->getLocStart(), SourceType,
+ S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType,
Atomic->getValueType())) {
DestType = Atomic->getValueType();
NeedAtomicConversion = true;
@@ -5758,7 +5863,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_CompoundLiteralInit:
case InitializedEntity::EK_RelatedResult:
- return Initializer->getLocStart();
+ return Initializer->getBeginLoc();
}
llvm_unreachable("missed an InitializedEntity kind?");
}
@@ -6092,7 +6197,10 @@ PerformConstructorInitialization(Sema &S,
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
if (!TSInfo)
TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
- SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange();
+ SourceRange ParenOrBraceRange =
+ (Kind.getKind() == InitializationKind::IK_DirectList)
+ ? SourceRange(LBraceLoc, RBraceLoc)
+ : Kind.getParenOrBraceRange();
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
Step.Function.FoundDecl.getDecl())) {
@@ -6102,7 +6210,7 @@ PerformConstructorInitialization(Sema &S,
}
S.MarkFunctionReferenced(Loc, Constructor);
- CurInit = new (S.Context) CXXTemporaryObjectExpr(
+ CurInit = CXXTemporaryObjectExpr::Create(
S.Context, Constructor,
Entity.getType().getNonLValueExprType(S.Context), TSInfo,
ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates,
@@ -6353,7 +6461,7 @@ static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
}
static bool pathContainsInit(IndirectLocalPath &Path) {
- return std::any_of(Path.begin(), Path.end(), [=](IndirectLocalPathEntry E) {
+ return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
return E.Kind == IndirectLocalPathEntry::DefaultInit ||
E.Kind == IndirectLocalPathEntry::VarInit;
});
@@ -6371,10 +6479,14 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
if (!TSI)
return false;
+ // Don't declare this variable in the second operand of the for-statement;
+ // GCC miscompiles that by ending its lifetime before evaluating the
+ // third operand. See gcc.gnu.org/PR86769.
+ AttributedTypeLoc ATL;
for (TypeLoc TL = TSI->getTypeLoc();
- auto ATL = TL.getAsAdjusted<AttributedTypeLoc>();
+ (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
TL = ATL.getModifiedLoc()) {
- if (ATL.getAttrKind() == AttributedType::attr_lifetimebound)
+ if (ATL.getAttrAs<LifetimeBoundAttr>())
return true;
}
return false;
@@ -6437,8 +6549,8 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
do {
Old = Init;
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
// If this is just redundant braces around an initializer, step over it.
@@ -6561,8 +6673,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
Init = DIE->getExpr();
}
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
// Dig out the expression which constructs the extended temporary.
Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
@@ -6694,6 +6806,20 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
return;
}
+ // The lifetime of an init-capture is that of the closure object constructed
+ // by a lambda-expression.
+ if (auto *LE = dyn_cast<LambdaExpr>(Init)) {
+ for (Expr *E : LE->capture_inits()) {
+ if (!E)
+ continue;
+ if (E->isGLValue())
+ visitLocalsRetainedByReferenceBinding(Path, E, RK_ReferenceBinding,
+ Visit);
+ else
+ visitLocalsRetainedByInitializer(Path, E, Visit, true);
+ }
+ }
+
if (isa<CallExpr>(Init) || isa<CXXConstructExpr>(Init))
return visitLifetimeBoundArguments(Path, Init, Visit);
@@ -6938,6 +7064,10 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
} else if (isa<BlockExpr>(L)) {
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
} else if (isa<AddrLabelExpr>(L)) {
+ // Don't warn when returning a label from a statement expression.
+ // Leaving the scope doesn't end its lifetime.
+ if (LK == LK_StmtExprResult)
+ return false;
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
} else {
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
@@ -7063,18 +7193,18 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
return;
}
- S.Diag(CE->getLocStart(), DiagID);
+ S.Diag(CE->getBeginLoc(), DiagID);
// Get all the locations for a fix-it. Don't emit the fix-it if any location
// is within a macro.
- SourceLocation CallBegin = CE->getCallee()->getLocStart();
+ SourceLocation CallBegin = CE->getCallee()->getBeginLoc();
if (CallBegin.isMacroID())
return;
SourceLocation RParen = CE->getRParenLoc();
if (RParen.isMacroID())
return;
SourceLocation LParen;
- SourceLocation ArgLoc = Arg->getLocStart();
+ SourceLocation ArgLoc = Arg->getBeginLoc();
// Special testing for the argument location. Since the fix-it needs the
// location right before the argument, the argument location can be in a
@@ -7089,7 +7219,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
LParen = ArgLoc.getLocWithOffset(-1);
- S.Diag(CE->getLocStart(), diag::note_remove_move)
+ S.Diag(CE->getBeginLoc(), diag::note_remove_move)
<< FixItHint::CreateRemoval(SourceRange(CallBegin, LParen))
<< FixItHint::CreateRemoval(SourceRange(RParen, RParen));
}
@@ -7142,12 +7272,20 @@ ExprResult Sema::TemporaryMaterializationConversion(Expr *E) {
return CreateMaterializeTemporaryExpr(E->getType(), E, false);
}
-ExprResult
-InitializationSequence::Perform(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- MultiExprArg Args,
- QualType *ResultType) {
+ExprResult Sema::PerformQualificationConversion(Expr *E, QualType Ty,
+ ExprValueKind VK,
+ CheckedConversionKind CCK) {
+ CastKind CK = (Ty.getAddressSpace() != E->getType().getAddressSpace())
+ ? CK_AddressSpaceConversion
+ : CK_NoOp;
+ return ImpCastExprToType(E, Ty, CK, VK, /*BasePath=*/nullptr, CCK);
+}
+
+ExprResult InitializationSequence::Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ QualType *ResultType) {
if (Failed()) {
Diagnose(S, Entity, Kind, Args);
return ExprError();
@@ -7231,8 +7369,8 @@ InitializationSequence::Perform(Sema &S,
// from an initializer list. For parameters, we produce a better warning
// elsewhere.
Expr *Init = Args[0];
- S.Diag(Init->getLocStart(), diag::warn_cxx98_compat_reference_list_init)
- << Init->getSourceRange();
+ S.Diag(Init->getBeginLoc(), diag::warn_cxx98_compat_reference_list_init)
+ << Init->getSourceRange();
}
// OpenCL v2.0 s6.13.11.1. atomic variables can be initialized in global scope
@@ -7244,8 +7382,9 @@ InitializationSequence::Perform(Sema &S,
if (S.getLangOpts().OpenCLVersion >= 200 &&
ETy->isAtomicType() && !HasGlobalAS &&
Entity.getKind() == InitializedEntity::EK_Variable && Args.size() > 0) {
- S.Diag(Args[0]->getLocStart(), diag::err_opencl_atomic_init) << 1 <<
- SourceRange(Entity.getDecl()->getLocStart(), Args[0]->getLocEnd());
+ S.Diag(Args[0]->getBeginLoc(), diag::err_opencl_atomic_init)
+ << 1
+ << SourceRange(Entity.getDecl()->getBeginLoc(), Args[0]->getEndLoc());
return ExprError();
}
@@ -7296,8 +7435,7 @@ InitializationSequence::Perform(Sema &S,
case SK_ProduceObjCObject:
case SK_StdInitializerList:
case SK_OCLSamplerInit:
- case SK_OCLZeroEvent:
- case SK_OCLZeroQueue: {
+ case SK_OCLZeroOpaqueType: {
assert(Args.size() == 1);
CurInit = Args[0];
if (!CurInit.get()) return ExprError();
@@ -7361,10 +7499,9 @@ InitializationSequence::Perform(Sema &S,
// Casts to inaccessible base classes are allowed with C-style casts.
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
- if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
- CurInit.get()->getLocStart(),
- CurInit.get()->getSourceRange(),
- &BasePath, IgnoreBaseAccess))
+ if (S.CheckDerivedToBaseConversion(
+ SourceType, Step->Type, CurInit.get()->getBeginLoc(),
+ CurInit.get()->getSourceRange(), &BasePath, IgnoreBaseAccess))
return ExprError();
ExprValueKind VK =
@@ -7393,7 +7530,7 @@ InitializationSequence::Perform(Sema &S,
if (auto *DRE = dyn_cast<DeclRefExpr>(CurInit.get()->IgnoreParens())) {
if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
- DRE->getLocStart()))
+ DRE->getBeginLoc()))
return ExprError();
}
}
@@ -7454,7 +7591,7 @@ InitializationSequence::Perform(Sema &S,
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
// Build a call to the selected constructor.
SmallVector<Expr*, 8> ConstructorArgs;
- SourceLocation Loc = CurInit.get()->getLocStart();
+ SourceLocation Loc = CurInit.get()->getBeginLoc();
// Determine the arguments required to actually perform the constructor
// call.
@@ -7521,10 +7658,10 @@ InitializationSequence::Perform(Sema &S,
if (const RecordType *Record = T->getAs<RecordType>()) {
CXXDestructorDecl *Destructor
= S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
- S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor,
+ S.CheckDestructorAccess(CurInit.get()->getBeginLoc(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
- S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor);
- if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()))
+ S.MarkFunctionReferenced(CurInit.get()->getBeginLoc(), Destructor);
+ if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getBeginLoc()))
return ExprError();
}
}
@@ -7536,12 +7673,11 @@ InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionRValue: {
// Perform a qualification conversion; these can never go wrong.
ExprValueKind VK =
- Step->Kind == SK_QualificationConversionLValue ?
- VK_LValue :
- (Step->Kind == SK_QualificationConversionXValue ?
- VK_XValue :
- VK_RValue);
- CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK);
+ Step->Kind == SK_QualificationConversionLValue
+ ? VK_LValue
+ : (Step->Kind == SK_QualificationConversionXValue ? VK_XValue
+ : VK_RValue);
+ CurInit = S.PerformQualificationConversion(CurInit.get(), Step->Type, VK);
break;
}
@@ -7562,6 +7698,18 @@ InitializationSequence::Perform(Sema &S,
case SK_ConversionSequence:
case SK_ConversionSequenceNoNarrowing: {
+ if (const auto *FromPtrType =
+ CurInit.get()->getType()->getAs<PointerType>()) {
+ if (const auto *ToPtrType = Step->Type->getAs<PointerType>()) {
+ if (FromPtrType->getPointeeType()->hasAttr(attr::NoDeref) &&
+ !ToPtrType->getPointeeType()->hasAttr(attr::NoDeref)) {
+ S.Diag(CurInit.get()->getExprLoc(),
+ diag::warn_noderef_to_dereferenceable_pointer)
+ << CurInit.get()->getSourceRange();
+ }
+ }
+ }
+
Sema::CheckedConversionKind CCK
= Kind.isCStyleCast()? Sema::CCK_CStyleCast
: Kind.isFunctionalCast()? Sema::CCK_FunctionalCast
@@ -7728,6 +7876,7 @@ InitializationSequence::Perform(Sema &S,
case SK_CAssignment: {
QualType SourceType = CurInit.get()->getType();
+
// Save off the initial CurInit in case we need to emit a diagnostic
ExprResult InitialCurInit = CurInit;
ExprResult Result = CurInit;
@@ -7863,7 +8012,7 @@ InitializationSequence::Perform(Sema &S,
}
case SK_OCLSamplerInit: {
- // Sampler initialzation have 5 cases:
+ // Sampler initialization have 5 cases:
// 1. function argument passing
// 1a. argument is a file-scope variable
// 1b. argument is a function-scope variable
@@ -7925,8 +8074,9 @@ InitializationSequence::Perform(Sema &S,
break;
}
- llvm::APSInt Result;
- Init->EvaluateAsInt(Result, S.Context);
+ Expr::EvalResult EVResult;
+ Init->EvaluateAsInt(EVResult, S.Context);
+ llvm::APSInt Result = EVResult.Val.getInt();
const uint64_t SamplerValue = Result.getLimitedValue();
// 32-bit value of sampler's initializer is interpreted as
// bit-field with the following structure:
@@ -7936,7 +8086,9 @@ InitializationSequence::Perform(Sema &S,
// defined in SPIR spec v1.2 and also opencl-c.h
unsigned AddressingMode = (0x0E & SamplerValue) >> 1;
unsigned FilterMode = (0x30 & SamplerValue) >> 4;
- if (FilterMode != 1 && FilterMode != 2)
+ if (FilterMode != 1 && FilterMode != 2 &&
+ !S.getOpenCLOptions().isEnabled(
+ "cl_intel_device_side_avc_motion_estimation"))
S.Diag(Kind.getLocation(),
diag::warn_sampler_initializer_invalid_bits)
<< "Filter Mode";
@@ -7952,21 +8104,13 @@ InitializationSequence::Perform(Sema &S,
CK_IntToOCLSampler);
break;
}
- case SK_OCLZeroEvent: {
- assert(Step->Type->isEventT() &&
- "Event initialization on non-event type.");
-
- CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
- CK_ZeroToOCLEvent,
- CurInit.get()->getValueKind());
- break;
- }
- case SK_OCLZeroQueue: {
- assert(Step->Type->isQueueT() &&
- "Event initialization on non queue type.");
+ case SK_OCLZeroOpaqueType: {
+ assert((Step->Type->isEventT() || Step->Type->isQueueT() ||
+ Step->Type->isOCLIntelSubgroupAVCType()) &&
+ "Wrong type for initialization of OpenCL opaque type.");
CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
- CK_ZeroToOCLQueue,
+ CK_ZeroToOCLOpaqueType,
CurInit.get()->getValueKind());
break;
}
@@ -8019,7 +8163,7 @@ static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc,
}
for (const auto &BI : RD->bases()) {
- if (DiagnoseUninitializedReference(S, BI.getLocStart(), BI.getType())) {
+ if (DiagnoseUninitializedReference(S, BI.getBeginLoc(), BI.getType())) {
S.Diag(Loc, diag::note_value_initialization_here) << RD;
return true;
}
@@ -8074,7 +8218,7 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
// inner initialization failed.
QualType T = DestType->getAs<ReferenceType>()->getPointeeType();
diagnoseListInit(S, InitializedEntity::InitializeTemporary(T), InitList);
- SourceLocation Loc = InitList->getLocStart();
+ SourceLocation Loc = InitList->getBeginLoc();
if (auto *D = Entity.getDecl())
Loc = D->getLocation();
S.Diag(Loc, diag::note_in_reference_temporary_list_initializer) << T;
@@ -8124,7 +8268,7 @@ bool InitializationSequence::Diagnose(Sema &S,
(void)Diagnosed;
} else // FIXME: diagnostic below could be better!
S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
- << SourceRange(Args.front()->getLocStart(), Args.back()->getLocEnd());
+ << SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc());
break;
case FK_ParenthesizedListInitForReference:
S.Diag(Kind.getLocation(), diag::err_list_init_in_parens)
@@ -8153,13 +8297,14 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_PlainStringIntoUTF8Char:
S.Diag(Kind.getLocation(),
diag::err_array_init_plain_string_into_char8_t);
- S.Diag(Args.front()->getLocStart(),
+ S.Diag(Args.front()->getBeginLoc(),
diag::note_array_init_plain_string_into_char8_t)
- << FixItHint::CreateInsertion(Args.front()->getLocStart(), "u8");
+ << FixItHint::CreateInsertion(Args.front()->getBeginLoc(), "u8");
break;
case FK_UTF8StringIntoPlainChar:
S.Diag(Kind.getLocation(),
- diag::err_array_init_utf8_string_into_char);
+ diag::err_array_init_utf8_string_into_char)
+ << S.getLangOpts().CPlusPlus2a;
break;
case FK_ArrayTypeMismatch:
case FK_NonConstantArrayInit:
@@ -8189,7 +8334,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_AddressOfUnaddressableFunction: {
auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl());
S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
- OnlyArg->getLocStart());
+ OnlyArg->getBeginLoc());
break;
}
@@ -8335,10 +8480,10 @@ bool InitializationSequence::Diagnose(Sema &S,
auto *InitList = dyn_cast<InitListExpr>(Args[0]);
if (InitList && InitList->getNumInits() >= 1) {
- R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd());
+ R = SourceRange(InitList->getInit(0)->getEndLoc(), InitList->getEndLoc());
} else {
assert(Args.size() > 1 && "Expected multiple initializers!");
- R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
+ R = SourceRange(Args.front()->getEndLoc(), Args.back()->getEndLoc());
}
R.setBegin(S.getLocForEndOfToken(R.getBegin()));
@@ -8370,8 +8515,8 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_ConstructorOverloadFailed: {
SourceRange ArgsRange;
if (Args.size())
- ArgsRange = SourceRange(Args.front()->getLocStart(),
- Args.back()->getLocEnd());
+ ArgsRange =
+ SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc());
if (Failure == FK_ListConstructorOverloadFailed) {
assert(Args.size() == 1 &&
@@ -8849,12 +8994,8 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "OpenCL sampler_t from integer constant";
break;
- case SK_OCLZeroEvent:
- OS << "OpenCL event_t from zero";
- break;
-
- case SK_OCLZeroQueue:
- OS << "OpenCL queue_t from zero";
+ case SK_OCLZeroOpaqueType:
+ OS << "OpenCL opaque type from zero";
break;
}
@@ -8906,7 +9047,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
// This was a floating-to-integer conversion, which is always considered a
// narrowing conversion even if the value is a constant and can be
// represented exactly as an integer.
- S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts())
+ S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts())
? diag::ext_init_list_type_narrowing
: diag::warn_init_list_type_narrowing)
<< PostInit->getSourceRange()
@@ -8916,7 +9057,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
case NK_Constant_Narrowing:
// A constant value was narrowed.
- S.Diag(PostInit->getLocStart(),
+ S.Diag(PostInit->getBeginLoc(),
NarrowingErrs(S.getLangOpts())
? diag::ext_init_list_constant_narrowing
: diag::warn_init_list_constant_narrowing)
@@ -8927,7 +9068,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
case NK_Variable_Narrowing:
// A variable's value may have been narrowed.
- S.Diag(PostInit->getLocStart(),
+ S.Diag(PostInit->getBeginLoc(),
NarrowingErrs(S.getLangOpts())
? diag::ext_init_list_variable_narrowing
: diag::warn_init_list_variable_narrowing)
@@ -8955,11 +9096,11 @@ static void DiagnoseNarrowingInInitList(Sema &S,
return;
}
OS << ">(";
- S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_silence)
+ S.Diag(PostInit->getBeginLoc(), diag::note_init_list_narrowing_silence)
<< PostInit->getSourceRange()
- << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str())
+ << FixItHint::CreateInsertion(PostInit->getBeginLoc(), OS.str())
<< FixItHint::CreateInsertion(
- S.getLocForEndOfToken(PostInit->getLocEnd()), ")");
+ S.getLocForEndOfToken(PostInit->getEndLoc()), ")");
}
//===----------------------------------------------------------------------===//
@@ -8974,8 +9115,8 @@ Sema::CanPerformCopyInitialization(const InitializedEntity &Entity,
Expr *InitE = Init.get();
assert(InitE && "No initialization expression");
- InitializationKind Kind
- = InitializationKind::CreateCopy(InitE->getLocStart(), SourceLocation());
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(InitE->getBeginLoc(), SourceLocation());
InitializationSequence Seq(*this, Entity, Kind, InitE);
return !Seq.Failed();
}
@@ -8993,11 +9134,10 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
assert(InitE && "No initialization expression?");
if (EqualLoc.isInvalid())
- EqualLoc = InitE->getLocStart();
+ EqualLoc = InitE->getBeginLoc();
- InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(),
- EqualLoc,
- AllowExplicit);
+ InitializationKind Kind = InitializationKind::CreateCopy(
+ InitE->getBeginLoc(), EqualLoc, AllowExplicit);
InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);
// Prevent infinite recursion when performing parameter copy-initialization.
@@ -9060,8 +9200,11 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
TSInfo->getType()->getContainedDeducedType());
assert(DeducedTST && "not a deduced template specialization type");
- // We can only perform deduction for class templates.
auto TemplateName = DeducedTST->getTemplateName();
+ if (TemplateName.isDependent())
+ return Context.DependentTy;
+
+ // We can only perform deduction for class templates.
auto *Template =
dyn_cast_or_null<ClassTemplateDecl>(TemplateName.getAsTemplateDecl());
if (!Template) {
@@ -9074,8 +9217,12 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
}
// Can't deduce from dependent arguments.
- if (Expr::hasAnyTypeDependentArguments(Inits))
+ if (Expr::hasAnyTypeDependentArguments(Inits)) {
+ Diag(TSInfo->getTypeLoc().getBeginLoc(),
+ diag::warn_cxx14_compat_class_template_argument_deduction)
+ << TSInfo->getTypeLoc().getSourceRange() << 0;
return Context.DependentTy;
+ }
// FIXME: Perform "exact type" matching first, per CWG discussion?
// Or implement this via an implied 'T(T) -> T' deduction guide?
@@ -9278,5 +9425,10 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
// C++ [dcl.type.class.deduct]p1:
// The placeholder is replaced by the return type of the function selected
// by overload resolution for class template deduction.
- return SubstAutoType(TSInfo->getType(), Best->Function->getReturnType());
+ QualType DeducedType =
+ SubstAutoType(TSInfo->getType(), Best->Function->getReturnType());
+ Diag(TSInfo->getTypeLoc().getBeginLoc(),
+ diag::warn_cxx14_compat_class_template_argument_deduction)
+ << TSInfo->getTypeLoc().getSourceRange() << 1 << DeducedType;
+ return DeducedType;
}
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 440567e032e4..af233b96d69b 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -479,7 +479,7 @@ void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
if (!LSI->ReturnType->isDependentType() &&
!LSI->ReturnType->isVoidType()) {
- if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType,
+ if (RequireCompleteType(CallOperator->getBeginLoc(), LSI->ReturnType,
diag::err_lambda_incomplete_result)) {
// Do nothing.
}
@@ -493,7 +493,9 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
LSI->finishedExplicitCaptures();
}
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(
+ ArrayRef<LambdaIntroducer::LambdaCapture> Captures,
+ CXXMethodDecl *CallOperator, Scope *CurScope) {
// Introduce our parameters into the function scope
for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
@@ -501,7 +503,19 @@ void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
// If this has an identifier, add it to the scope stack.
if (CurScope && Param->getIdentifier()) {
- CheckShadow(CurScope, Param);
+ bool Error = false;
+ // Resolution of CWG 2211 in C++17 renders shadowing ill-formed, but we
+ // retroactively apply it.
+ for (const auto &Capture : Captures) {
+ if (Capture.Id == Param->getIdentifier()) {
+ Error = true;
+ Diag(Param->getLocation(), diag::err_parameter_shadow_capture);
+ Diag(Capture.Loc, diag::note_var_explicitly_captured_here)
+ << Capture.Id << true;
+ }
+ }
+ if (!Error)
+ CheckShadow(CurScope, Param);
PushOnScopeChains(Param, CurScope);
}
@@ -720,10 +734,9 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// FIXME: This is a poor diagnostic for ReturnStmts without expressions.
// TODO: It's possible that the *first* return is the divergent one.
- Diag(RS->getLocStart(),
+ Diag(RS->getBeginLoc(),
diag::err_typecheck_missing_return_type_incompatible)
- << ReturnType << CSI.ReturnType
- << isa<LambdaScopeInfo>(CSI);
+ << ReturnType << CSI.ReturnType << isa<LambdaScopeInfo>(CSI);
// Continue iterating so that we keep emitting diagnostics.
}
}
@@ -746,14 +759,15 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc,
TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
// Deduce the type of the init capture.
+ Expr *DeduceInit = Init;
QualType DeducedType = deduceVarTypeFromInitializer(
/*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI,
- SourceRange(Loc, Loc), IsDirectInit, Init);
+ SourceRange(Loc, Loc), IsDirectInit, DeduceInit);
if (DeducedType.isNull())
return QualType();
// Are we a non-list direct initialization?
- ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+ bool CXXDirectInit = isa<ParenListExpr>(Init);
// Perform initialization analysis and ensure any implicit conversions
// (such as lvalue-to-rvalue) are enforced.
@@ -762,30 +776,17 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc,
InitializationKind Kind =
IsDirectInit
? (CXXDirectInit ? InitializationKind::CreateDirect(
- Loc, Init->getLocStart(), Init->getLocEnd())
+ Loc, Init->getBeginLoc(), Init->getEndLoc())
: InitializationKind::CreateDirectList(Loc))
- : InitializationKind::CreateCopy(Loc, Init->getLocStart());
+ : InitializationKind::CreateCopy(Loc, Init->getBeginLoc());
- MultiExprArg Args = Init;
- if (CXXDirectInit)
- Args =
- MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs());
+ MultiExprArg Args = DeduceInit;
QualType DclT;
InitializationSequence InitSeq(*this, Entity, Kind, Args);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
if (Result.isInvalid())
return QualType();
- Init = Result.getAs<Expr>();
-
- // The init-capture initialization is a full-expression that must be
- // processed as one before we enter the declcontext of the lambda's
- // call-operator.
- Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false,
- /*IsConstexpr*/ false,
- /*IsLambdaInitCaptureInitializer*/ true);
- if (Result.isInvalid())
- return QualType();
Init = Result.getAs<Expr>();
return DeducedType;
@@ -856,7 +857,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
EPI.HasTrailingReturn = true;
- EPI.TypeQuals |= DeclSpec::TQ_const;
+ EPI.TypeQuals.addConst();
// C++1y [expr.prim.lambda]:
// The lambda return type is 'auto', which is replaced by the
// trailing-return type if provided and/or deduced from 'return'
@@ -881,8 +882,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// This function call operator is declared const (9.3.1) if and only if
// the lambda-expression's parameter-declaration-clause is not followed
// by mutable. It is neither virtual nor declared volatile. [...]
- if (!FTI.hasMutableQualifier())
- FTI.TypeQuals |= DeclSpec::TQ_const;
+ if (!FTI.hasMutableQualifier()) {
+ FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const,
+ SourceLocation());
+ }
MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
assert(MethodTyInfo && "no type from lambda-declarator");
@@ -1153,7 +1156,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
// Add lambda parameters into scope.
- addLambdaParameters(Method, CurScope);
+ addLambdaParameters(Intro.Captures, Method, CurScope);
// Enter a new evaluation context to insulate the lambda from any
// cleanups from the enclosing full-expression.
@@ -1195,7 +1198,7 @@ QualType Sema::getLambdaConversionFunctionResultType(
CallingConv CC = Context.getDefaultCallingConvention(
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
- InvokerExtInfo.TypeQuals = 0;
+ InvokerExtInfo.TypeQuals = Qualifiers();
assert(InvokerExtInfo.RefQualifier == RQ_None &&
"Lambda's call operator should not have a reference qualifier");
return Context.getFunctionType(CallOpProto->getReturnType(),
@@ -1226,7 +1229,8 @@ static void addFunctionPointerConversion(Sema &S,
S.Context.getDefaultCallingConvention(
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
// The conversion function is always const.
- ConvExtInfo.TypeQuals = Qualifiers::Const;
+ ConvExtInfo.TypeQuals = Qualifiers();
+ ConvExtInfo.TypeQuals.addConst();
QualType ConvTy =
S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo);
@@ -1286,29 +1290,23 @@ static void addFunctionPointerConversion(Sema &S,
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
ParmVarDecl *From = CallOperator->getParamDecl(I);
- InvokerParams.push_back(ParmVarDecl::Create(S.Context,
- // Temporarily add to the TU. This is set to the invoker below.
- S.Context.getTranslationUnitDecl(),
- From->getLocStart(),
- From->getLocation(),
- From->getIdentifier(),
- From->getType(),
- From->getTypeSourceInfo(),
- From->getStorageClass(),
- /*DefaultArg=*/nullptr));
+ InvokerParams.push_back(ParmVarDecl::Create(
+ S.Context,
+ // Temporarily add to the TU. This is set to the invoker below.
+ S.Context.getTranslationUnitDecl(), From->getBeginLoc(),
+ From->getLocation(), From->getIdentifier(), From->getType(),
+ From->getTypeSourceInfo(), From->getStorageClass(),
+ /*DefaultArg=*/nullptr));
CallOpConvTL.setParam(I, From);
CallOpConvNameTL.setParam(I, From);
}
- CXXConversionDecl *Conversion
- = CXXConversionDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(ConversionName,
- Loc, ConvNameLoc),
- ConvTy,
- ConvTSI,
- /*isInline=*/true, /*isExplicit=*/false,
- /*isConstexpr=*/S.getLangOpts().CPlusPlus17,
- CallOperator->getBody()->getLocEnd());
+ CXXConversionDecl *Conversion = CXXConversionDecl::Create(
+ S.Context, Class, Loc,
+ DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI,
+ /*isInline=*/true, /*isExplicit=*/false,
+ /*isConstexpr=*/S.getLangOpts().CPlusPlus17,
+ CallOperator->getBody()->getEndLoc());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
@@ -1343,14 +1341,11 @@ static void addFunctionPointerConversion(Sema &S,
// trailing return type of the invoker would require a visitor to rebuild
// the trailing return type and adjusting all back DeclRefExpr's to refer
// to the new static invoker parameters - not the call operator's.
- CXXMethodDecl *Invoke
- = CXXMethodDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(InvokerName, Loc),
- InvokerFunctionTy,
- CallOperator->getTypeSourceInfo(),
- SC_Static, /*IsInline=*/true,
- /*IsConstexpr=*/false,
- CallOperator->getBody()->getLocEnd());
+ CXXMethodDecl *Invoke = CXXMethodDecl::Create(
+ S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc),
+ InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static,
+ /*IsInline=*/true,
+ /*IsConstexpr=*/false, CallOperator->getBody()->getEndLoc());
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I)
InvokerParams[I]->setOwningFunction(Invoke);
Invoke->setParams(InvokerParams);
@@ -1383,7 +1378,8 @@ static void addBlockPointerConversion(Sema &S,
FunctionProtoType::ExtProtoInfo ConversionEPI(
S.Context.getDefaultCallingConvention(
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
- ConversionEPI.TypeQuals = Qualifiers::Const;
+ ConversionEPI.TypeQuals = Qualifiers();
+ ConversionEPI.TypeQuals.addConst();
QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI);
SourceLocation Loc = IntroducerRange.getBegin();
@@ -1392,26 +1388,24 @@ static void addBlockPointerConversion(Sema &S,
S.Context.getCanonicalType(BlockPtrTy));
DeclarationNameLoc NameLoc;
NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc);
- CXXConversionDecl *Conversion
- = CXXConversionDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(Name, Loc, NameLoc),
- ConvTy,
- S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
- /*isInline=*/true, /*isExplicit=*/false,
- /*isConstexpr=*/false,
- CallOperator->getBody()->getLocEnd());
+ CXXConversionDecl *Conversion = CXXConversionDecl::Create(
+ S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy,
+ S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
+ /*isInline=*/true, /*isExplicit=*/false,
+ /*isConstexpr=*/false, CallOperator->getBody()->getEndLoc());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
}
-static ExprResult performLambdaVarCaptureInitialization(Sema &S,
- const Capture &Capture,
- FieldDecl *Field) {
+static ExprResult performLambdaVarCaptureInitialization(
+ Sema &S, const Capture &Capture, FieldDecl *Field,
+ SourceLocation ImplicitCaptureLoc, bool IsImplicitCapture) {
assert(Capture.isVariableCapture() && "not a variable capture");
auto *Var = Capture.getVariable();
- SourceLocation Loc = Capture.getLocation();
+ SourceLocation Loc =
+ IsImplicitCapture ? ImplicitCaptureLoc : Capture.getLocation();
// C++11 [expr.prim.lambda]p21:
// When the lambda-expression is evaluated, the entities that
@@ -1442,7 +1436,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope) {
LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
ActOnFinishFunctionBody(LSI.CallOperator, Body);
- return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI);
+ return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI);
}
static LambdaCaptureDefault
@@ -1620,8 +1614,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
Var, From.getEllipsisLoc()));
Expr *Init = From.getInitExpr();
if (!Init) {
- auto InitResult =
- performLambdaVarCaptureInitialization(*this, From, *CurField);
+ auto InitResult = performLambdaVarCaptureInitialization(
+ *this, From, *CurField, CaptureDefaultLoc, IsImplicit);
if (InitResult.isInvalid())
return ExprError();
Init = InitResult.get();
@@ -1644,7 +1638,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// same parameter and return types as the closure type's function call
// operator.
// FIXME: Fix generic lambda to block conversions.
- if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda)
+ if (getLangOpts().Blocks && getLangOpts().ObjC && !IsGenericLambda)
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
// Finalize the lambda class.
@@ -1730,7 +1724,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
/*NRVO=*/false),
CurrentLocation, Src);
if (!Init.isInvalid())
- Init = ActOnFinishFullExpr(Init.get());
+ Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
if (Init.isInvalid())
return ExprError();
@@ -1747,14 +1741,11 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
SmallVector<ParmVarDecl *, 4> BlockParams;
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
ParmVarDecl *From = CallOperator->getParamDecl(I);
- BlockParams.push_back(ParmVarDecl::Create(Context, Block,
- From->getLocStart(),
- From->getLocation(),
- From->getIdentifier(),
- From->getType(),
- From->getTypeSourceInfo(),
- From->getStorageClass(),
- /*DefaultArg=*/nullptr));
+ BlockParams.push_back(ParmVarDecl::Create(
+ Context, Block, From->getBeginLoc(), From->getLocation(),
+ From->getIdentifier(), From->getType(), From->getTypeSourceInfo(),
+ From->getStorageClass(),
+ /*DefaultArg=*/nullptr));
}
Block->setParams(BlockParams);
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 0ab70e9dca37..effccc2f3d38 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -186,9 +186,7 @@ namespace {
list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
}
- void done() {
- llvm::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
- }
+ void done() { llvm::sort(list, UnqualUsingEntry::Comparator()); }
typedef ListTy::const_iterator const_iterator;
@@ -1392,23 +1390,25 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() {
return LookupModulesCache;
}
+/// Determine whether the module M is part of the current module from the
+/// perspective of a module-private visibility check.
+static bool isInCurrentModule(const Module *M, const LangOptions &LangOpts) {
+ // If M is the global module fragment of a module that we've not yet finished
+ // parsing, then it must be part of the current module.
+ return M->getTopLevelModuleName() == LangOpts.CurrentModule ||
+ (M->Kind == Module::GlobalModuleFragment && !M->Parent);
+}
+
bool Sema::hasVisibleMergedDefinition(NamedDecl *Def) {
- for (Module *Merged : Context.getModulesWithMergedDefinition(Def))
+ for (const Module *Merged : Context.getModulesWithMergedDefinition(Def))
if (isModuleVisible(Merged))
return true;
return false;
}
bool Sema::hasMergedDefinitionInCurrentModule(NamedDecl *Def) {
- // FIXME: When not in local visibility mode, we can't tell the difference
- // between a declaration being visible because we merged a local copy of
- // the same declaration into it, and it being visible because its owning
- // module is visible.
- if (Def->getModuleOwnershipKind() == Decl::ModuleOwnershipKind::Visible &&
- getLangOpts().ModulesLocalVisibility)
- return true;
- for (Module *Merged : Context.getModulesWithMergedDefinition(Def))
- if (Merged->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ for (const Module *Merged : Context.getModulesWithMergedDefinition(Def))
+ if (isInCurrentModule(Merged, getLangOpts()))
return true;
return false;
}
@@ -1428,8 +1428,6 @@ hasVisibleDefaultArgument(Sema &S, const ParmDecl *D,
if (!DefaultArg.isInherited() && Modules) {
auto *NonConstD = const_cast<ParmDecl*>(D);
Modules->push_back(S.getOwningModule(NonConstD));
- const auto &Merged = S.Context.getModulesWithMergedDefinition(NonConstD);
- Modules->insert(Modules->end(), Merged.begin(), Merged.end());
}
// If there was a previous default argument, maybe its parameter is visible.
@@ -1464,11 +1462,8 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
HasFilteredRedecls = true;
- if (Modules) {
+ if (Modules)
Modules->push_back(R->getOwningModule());
- const auto &Merged = S.Context.getModulesWithMergedDefinition(R);
- Modules->insert(Modules->end(), Merged.begin(), Merged.end());
- }
}
// Only return false if there is at least one redecl that is not filtered out.
@@ -1519,27 +1514,11 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
assert(D->isHidden() && "should not call this: not in slow case");
Module *DeclModule = SemaRef.getOwningModule(D);
- if (!DeclModule) {
- // A module-private declaration with no owning module means this is in the
- // global module in the C++ Modules TS. This is visible within the same
- // translation unit only.
- // FIXME: Don't assume that "same translation unit" means the same thing
- // as "not from an AST file".
- assert(D->isModulePrivate() && "hidden decl has no module");
- if (!D->isFromASTFile() || SemaRef.hasMergedDefinitionInCurrentModule(D))
- return true;
- } else {
- // If the owning module is visible, and the decl is not module private,
- // then the decl is visible too. (Module private is ignored within the same
- // top-level module.)
- if (D->isModulePrivate()
- ? DeclModule->getTopLevelModuleName() ==
- SemaRef.getLangOpts().CurrentModule ||
- SemaRef.hasMergedDefinitionInCurrentModule(D)
- : SemaRef.isModuleVisible(DeclModule) ||
- SemaRef.hasVisibleMergedDefinition(D))
- return true;
- }
+ assert(DeclModule && "hidden decl has no owning module");
+
+ // If the owning module is visible, the decl is visible.
+ if (SemaRef.isModuleVisible(DeclModule, D->isModulePrivate()))
+ return true;
// Determine whether a decl context is a file context for the purpose of
// visibility. This looks through some (export and linkage spec) transparent
@@ -1589,29 +1568,41 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
return VisibleWithinParent;
}
- // FIXME: All uses of DeclModule below this point should also check merged
- // modules.
- if (!DeclModule)
- return false;
+ return false;
+}
+
+bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) {
+ // The module might be ordinarily visible. For a module-private query, that
+ // means it is part of the current module. For any other query, that means it
+ // is in our visible module set.
+ if (ModulePrivate) {
+ if (isInCurrentModule(M, getLangOpts()))
+ return true;
+ } else {
+ if (VisibleModules.isVisible(M))
+ return true;
+ }
+
+ // Otherwise, it might be visible by virtue of the query being within a
+ // template instantiation or similar that is permitted to look inside M.
// Find the extra places where we need to look.
- const auto &LookupModules = SemaRef.getLookupModules();
+ const auto &LookupModules = getLookupModules();
if (LookupModules.empty())
return false;
- // If our lookup set contains the decl's module, it's visible.
- if (LookupModules.count(DeclModule))
+ // If our lookup set contains the module, it's visible.
+ if (LookupModules.count(M))
return true;
- // If the declaration isn't exported, it's not visible in any other module.
- if (D->isModulePrivate())
+ // For a module-private query, that's everywhere we get to look.
+ if (ModulePrivate)
return false;
- // Check whether DeclModule is transitively exported to an import of
- // the lookup set.
- return std::any_of(LookupModules.begin(), LookupModules.end(),
- [&](const Module *M) {
- return M->isModuleVisible(DeclModule); });
+ // Check whether M is transitively exported to an import of the lookup set.
+ return llvm::any_of(LookupModules, [&](const Module *LookupM) {
+ return LookupM->isModuleVisible(M);
+ });
}
bool Sema::isVisibleSlow(const NamedDecl *D) {
@@ -3346,38 +3337,29 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
!isa<FunctionTemplateDecl>(Underlying))
continue;
- if (!isVisible(D)) {
- D = findAcceptableDecl(
- *this, D, (Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend));
- if (!D)
- continue;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
- }
-
- // If the only declaration here is an ordinary friend, consider
- // it only if it was declared in an associated classes.
- if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) {
- // If it's neither ordinarily visible nor a friend, we can't find it.
- if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0)
- continue;
-
- bool DeclaredInAssociatedClass = false;
- for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) {
- DeclContext *LexDC = DI->getLexicalDeclContext();
- if (isa<CXXRecordDecl>(LexDC) &&
- AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)) &&
- isVisible(cast<NamedDecl>(DI))) {
- DeclaredInAssociatedClass = true;
+ // The declaration is visible to argument-dependent lookup if either
+ // it's ordinarily visible or declared as a friend in an associated
+ // class.
+ bool Visible = false;
+ for (D = D->getMostRecentDecl(); D;
+ D = cast_or_null<NamedDecl>(D->getPreviousDecl())) {
+ if (D->getIdentifierNamespace() & Decl::IDNS_Ordinary) {
+ if (isVisible(D)) {
+ Visible = true;
+ break;
+ }
+ } else if (D->getFriendObjectKind()) {
+ auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext());
+ if (AssociatedClasses.count(RD) && isVisible(D)) {
+ Visible = true;
break;
}
}
- if (!DeclaredInAssociatedClass)
- continue;
}
// FIXME: Preserve D as the FoundDecl.
- Result.insert(Underlying);
+ if (Visible)
+ Result.insert(Underlying);
}
}
}
@@ -3628,8 +3610,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Find results in this base class (and its bases).
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(RD, Result, QualifiedNameLookup, true, Consumer,
- Visited, IncludeDependentBases, LoadExternal);
+ LookupVisibleDecls(RD, Result, QualifiedNameLookup, /*InBaseClass=*/true,
+ Consumer, Visited, IncludeDependentBases,
+ LoadExternal);
}
}
@@ -3998,9 +3981,9 @@ void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
// Compute an upper bound on the allowable edit distance, so that the
// edit-distance algorithm can short-circuit.
- unsigned UpperBound = (TypoStr.size() + 2) / 3 + 1;
+ unsigned UpperBound = (TypoStr.size() + 2) / 3;
unsigned ED = TypoStr.edit_distance(Name, true, UpperBound);
- if (ED >= UpperBound) return;
+ if (ED > UpperBound) return;
TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED);
if (isKeyword) TC.makeKeyword();
@@ -4070,7 +4053,7 @@ void TypoCorrectionConsumer::addNamespaces(
}
// Do not transform this into an iterator-based loop. The loop body can
// trigger the creation of further types (through lazy deserialization) and
- // invalide iterators into this list.
+ // invalid iterators into this list.
auto &Types = SemaRef.getASTContext().getTypes();
for (unsigned I = 0; I != Types.size(); ++I) {
const auto *TI = Types[I];
@@ -4211,7 +4194,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
SS->getScopeRep()->print(OldOStream, SemaRef.getPrintingPolicy());
OldOStream << Typo->getName();
// If correction candidate would be an identical written qualified
- // identifer, then the existing CXXScopeSpec probably included a
+ // identifier, then the existing CXXScopeSpec probably included a
// typedef that didn't get accounted for properly.
if (OldOStream.str() == NewQualified)
break;
@@ -4628,7 +4611,7 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
getLangOpts().ModulesSearchAll) {
// The following has the side effect of loading the missing module.
getModuleLoader().lookupMissingImports(Typo->getName(),
- TypoName.getLocStart());
+ TypoName.getBeginLoc());
}
CorrectionCandidateCallback &CCCRef = *CCC;
@@ -5061,12 +5044,12 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
if (!Def)
Def = Decl;
- Module *Owner = getOwningModule(Decl);
+ Module *Owner = getOwningModule(Def);
assert(Owner && "definition of hidden declaration is not in a module");
llvm::SmallVector<Module*, 8> OwningModules;
OwningModules.push_back(Owner);
- auto Merged = Context.getModulesWithMergedDefinition(Decl);
+ auto Merged = Context.getModulesWithMergedDefinition(Def);
OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end());
diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, MIK,
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 3e55cf003fce..9412d0160048 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -609,12 +609,12 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
}
if (T->isObjCObjectType()) {
- SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
+ SourceLocation StarLoc = TInfo->getTypeLoc().getEndLoc();
StarLoc = getLocForEndOfToken(StarLoc);
Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(StarLoc, "*");
T = Context.getObjCObjectPointerType(T);
- SourceLocation TLoc = TInfo->getTypeLoc().getLocStart();
+ SourceLocation TLoc = TInfo->getTypeLoc().getBeginLoc();
TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
}
@@ -1061,7 +1061,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
PropertyIvarLoc = PropertyLoc;
SourceLocation PropertyDiagLoc = PropertyLoc;
if (PropertyDiagLoc.isInvalid())
- PropertyDiagLoc = ClassImpDecl->getLocStart();
+ PropertyDiagLoc = ClassImpDecl->getBeginLoc();
ObjCPropertyDecl *property = nullptr;
ObjCInterfaceDecl *IDecl = nullptr;
// Find the class or category class where this property must have
@@ -1412,9 +1412,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// FIXME. Eventually we want to do this for Objective-C as well.
SynthesizedFunctionScope Scope(*this, getterMethod);
ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
- DeclRefExpr *SelfExpr =
- new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
- VK_LValue, PropertyDiagLoc);
+ DeclRefExpr *SelfExpr = new (Context)
+ DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
+ PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
Expr *LoadSelfExpr =
ImplicitCastExpr::Create(Context, SelfDecl->getType(),
@@ -1464,9 +1464,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// FIXME. Eventually we want to do this for Objective-C as well.
SynthesizedFunctionScope Scope(*this, setterMethod);
ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
- DeclRefExpr *SelfExpr =
- new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
- VK_LValue, PropertyDiagLoc);
+ DeclRefExpr *SelfExpr = new (Context)
+ DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
+ PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
Expr *LoadSelfExpr =
ImplicitCastExpr::Create(Context, SelfDecl->getType(),
@@ -1481,8 +1481,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
ParmVarDecl *Param = (*P);
QualType T = Param->getType().getNonReferenceType();
- DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T,
- VK_LValue, PropertyDiagLoc);
+ DeclRefExpr *rhs = new (Context)
+ DeclRefExpr(Context, Param, false, T, VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(rhs);
ExprResult Res = BuildBinOp(S, PropertyDiagLoc,
BO_Assign, lhs, rhs);
@@ -1497,8 +1497,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Diag(PropertyDiagLoc,
diag::err_atomic_property_nontrivial_assign_op)
<< property->getType();
- Diag(FuncDecl->getLocStart(),
- diag::note_callee_decl) << FuncDecl;
+ Diag(FuncDecl->getBeginLoc(), diag::note_callee_decl)
+ << FuncDecl;
}
}
PIDecl->setSetterCXXAssignment(Res.getAs<Expr>());
@@ -2100,7 +2100,7 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl)
!impDecl->getInstanceMethod(getterMethod->getSelector())) {
SourceLocation loc = propertyImpl->getLocation();
if (loc.isInvalid())
- loc = impDecl->getLocStart();
+ loc = impDecl->getBeginLoc();
Diag(loc, diag::warn_null_resettable_setter)
<< setterMethod->getSelector() << property->getDeclName();
@@ -2235,7 +2235,7 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D
if (getterRedecl->getDeclContext() != PD->getDeclContext())
continue;
noteLoc = getterRedecl->getLocation();
- fixItLoc = getterRedecl->getLocEnd();
+ fixItLoc = getterRedecl->getEndLoc();
}
Preprocessor &PP = getPreprocessor();
@@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
QualType modifiedTy = resultTy;
if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
if (*nullability == NullabilityKind::Unspecified)
- resultTy = Context.getAttributedType(AttributedType::attr_nonnull,
+ resultTy = Context.getAttributedType(attr::TypeNonNull,
modifiedTy, modifiedTy);
}
}
@@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
QualType modifiedTy = paramTy;
if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
if (*nullability == NullabilityKind::Unspecified)
- paramTy = Context.getAttributedType(AttributedType::attr_nullable,
+ paramTy = Context.getAttributedType(attr::TypeNullable,
modifiedTy, modifiedTy);
}
}
@@ -2557,6 +2557,14 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
PropertyDecl->setInvalidDecl();
}
+ // Check for assign on object types.
+ if ((Attributes & ObjCDeclSpec::DQ_PR_assign) &&
+ !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
+ PropertyTy->isObjCRetainableType() &&
+ !PropertyTy->isObjCARCImplicitlyUnretainedType()) {
+ Diag(Loc, diag::warn_objc_property_assign_on_object);
+ }
+
// Check for more than one of { assign, copy, retain }.
if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index e1a4c420d402..36048a38b999 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
@@ -73,6 +74,8 @@ public:
};
using OperatorOffsetTy =
llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
+ using DoacrossDependMapTy =
+ llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
private:
struct DSAInfo {
@@ -97,8 +100,6 @@ private:
llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
using CriticalsWithHintsTy =
llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
- using DoacrossDependMapTy =
- llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
struct ReductionData {
using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
SourceRange ReductionRange;
@@ -137,13 +138,16 @@ private:
/// first argument (Expr *) contains optional argument of the
/// 'ordered' clause, the second one is true if the regions has 'ordered'
/// clause, false otherwise.
- llvm::PointerIntPair<const Expr *, 1, bool> OrderedRegion;
+ llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
+ unsigned AssociatedLoops = 1;
+ const Decl *PossiblyLoopCounter = nullptr;
bool NowaitRegion = false;
bool CancelRegion = false;
- unsigned AssociatedLoops = 1;
+ bool LoopStart = false;
SourceLocation InnerTeamsRegionLoc;
/// Reference to the taskgroup task_reduction reference expression.
Expr *TaskgroupReductionRef = nullptr;
+ llvm::DenseSet<QualType> MappedClassesQualTypes;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
: Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -162,6 +166,9 @@ private:
OpenMPClauseKind ClauseKindMode = OMPC_unknown;
Sema &SemaRef;
bool ForceCapturing = false;
+ /// true if all the vaiables in the target executable directives must be
+ /// captured by reference.
+ bool ForceCaptureByReferenceInTargetExecutable = false;
CriticalsWithHintsTy Criticals;
using iterator = StackTy::const_reverse_iterator;
@@ -177,6 +184,9 @@ private:
Stack.back().first.empty();
}
+ /// Vector of previously declared requires directives
+ SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
+
public:
explicit DSAStackTy(Sema &S) : SemaRef(S) {}
@@ -190,6 +200,13 @@ public:
bool isForceVarCapturing() const { return ForceCapturing; }
void setForceVarCapturing(bool V) { ForceCapturing = V; }
+ void setForceCaptureByReferenceInTargetExecutable(bool V) {
+ ForceCaptureByReferenceInTargetExecutable = V;
+ }
+ bool isForceCaptureByReferenceInTargetExecutable() const {
+ return ForceCaptureByReferenceInTargetExecutable;
+ }
+
void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
Scope *CurScope, SourceLocation Loc) {
if (Stack.empty() ||
@@ -205,6 +222,33 @@ public:
Stack.back().first.pop_back();
}
+ /// Marks that we're started loop parsing.
+ void loopInit() {
+ assert(isOpenMPLoopDirective(getCurrentDirective()) &&
+ "Expected loop-based directive.");
+ Stack.back().first.back().LoopStart = true;
+ }
+ /// Start capturing of the variables in the loop context.
+ void loopStart() {
+ assert(isOpenMPLoopDirective(getCurrentDirective()) &&
+ "Expected loop-based directive.");
+ Stack.back().first.back().LoopStart = false;
+ }
+ /// true, if variables are captured, false otherwise.
+ bool isLoopStarted() const {
+ assert(isOpenMPLoopDirective(getCurrentDirective()) &&
+ "Expected loop-based directive.");
+ return !Stack.back().first.back().LoopStart;
+ }
+ /// Marks (or clears) declaration as possibly loop counter.
+ void resetPossibleLoopCounter(const Decl *D = nullptr) {
+ Stack.back().first.back().PossiblyLoopCounter =
+ D ? D->getCanonicalDecl() : D;
+ }
+ /// Gets the possible loop counter decl.
+ const Decl *getPossiblyLoopCunter() const {
+ return Stack.back().first.back().PossiblyLoopCounter;
+ }
/// Start new OpenMP region stack in new non-capturing function.
void pushFunction() {
const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
@@ -352,6 +396,33 @@ public:
return std::next(Stack.back().first.rbegin())->Directive;
}
+ /// Add requires decl to internal vector
+ void addRequiresDecl(OMPRequiresDecl *RD) {
+ RequiresDecls.push_back(RD);
+ }
+
+ /// Checks for a duplicate clause amongst previously declared requires
+ /// directives
+ bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
+ bool IsDuplicate = false;
+ for (OMPClause *CNew : ClauseList) {
+ for (const OMPRequiresDecl *D : RequiresDecls) {
+ for (const OMPClause *CPrev : D->clauselists()) {
+ if (CNew->getClauseKind() == CPrev->getClauseKind()) {
+ SemaRef.Diag(CNew->getBeginLoc(),
+ diag::err_omp_requires_clause_redeclaration)
+ << getOpenMPClauseName(CNew->getClauseKind());
+ SemaRef.Diag(CPrev->getBeginLoc(),
+ diag::note_omp_requires_previous_clause)
+ << getOpenMPClauseName(CPrev->getClauseKind());
+ IsDuplicate = true;
+ }
+ }
+ }
+ }
+ return IsDuplicate;
+ }
+
/// Set default data sharing attribute to none.
void setDefaultDSANone(SourceLocation Loc) {
assert(!isStackEmpty());
@@ -398,23 +469,42 @@ public:
}
/// Marks current region as ordered (it has an 'ordered' clause).
- void setOrderedRegion(bool IsOrdered, const Expr *Param) {
+ void setOrderedRegion(bool IsOrdered, const Expr *Param,
+ OMPOrderedClause *Clause) {
assert(!isStackEmpty());
- Stack.back().first.back().OrderedRegion.setInt(IsOrdered);
- Stack.back().first.back().OrderedRegion.setPointer(Param);
+ if (IsOrdered)
+ Stack.back().first.back().OrderedRegion.emplace(Param, Clause);
+ else
+ Stack.back().first.back().OrderedRegion.reset();
+ }
+ /// Returns true, if region is ordered (has associated 'ordered' clause),
+ /// false - otherwise.
+ bool isOrderedRegion() const {
+ if (isStackEmpty())
+ return false;
+ return Stack.back().first.rbegin()->OrderedRegion.hasValue();
+ }
+ /// Returns optional parameter for the ordered region.
+ std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
+ if (isStackEmpty() ||
+ !Stack.back().first.rbegin()->OrderedRegion.hasValue())
+ return std::make_pair(nullptr, nullptr);
+ return Stack.back().first.rbegin()->OrderedRegion.getValue();
}
/// Returns true, if parent region is ordered (has associated
/// 'ordered' clause), false - otherwise.
bool isParentOrderedRegion() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return false;
- return std::next(Stack.back().first.rbegin())->OrderedRegion.getInt();
+ return std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue();
}
/// Returns optional parameter for the ordered region.
- const Expr *getParentOrderedRegionParam() const {
- if (isStackEmpty() || Stack.back().first.size() == 1)
- return nullptr;
- return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer();
+ std::pair<const Expr *, OMPOrderedClause *>
+ getParentOrderedRegionParam() const {
+ if (isStackEmpty() || Stack.back().first.size() == 1 ||
+ !std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue())
+ return std::make_pair(nullptr, nullptr);
+ return std::next(Stack.back().first.rbegin())->OrderedRegion.getValue();
}
/// Marks current region as nowait (it has a 'nowait' clause).
void setNowaitRegion(bool IsNowait = true) {
@@ -572,17 +662,34 @@ public:
return llvm::make_range(StackElem.DoacrossDepends.end(),
StackElem.DoacrossDepends.end());
}
+
+ // Store types of classes which have been explicitly mapped
+ void addMappedClassesQualTypes(QualType QT) {
+ SharingMapTy &StackElem = Stack.back().first.back();
+ StackElem.MappedClassesQualTypes.insert(QT);
+ }
+
+ // Return set of mapped classes types
+ bool isClassPreviouslyMapped(QualType QT) const {
+ const SharingMapTy &StackElem = Stack.back().first.back();
+ return StackElem.MappedClassesQualTypes.count(QT) != 0;
+ }
+
};
-bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
- return isOpenMPParallelDirective(DKind) || isOpenMPTaskingDirective(DKind) ||
- isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown;
+
+bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
+ return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
+}
+
+bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
+ return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) || DKind == OMPD_unknown;
}
} // namespace
static const Expr *getExprAsWritten(const Expr *E) {
- if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
- E = ExprTemp->getSubExpr();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
E = MTE->GetTemporaryExpr();
@@ -716,7 +823,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter,
DVar.CKind = OMPC_firstprivate;
return DVar;
}
- } while (I != E && !isParallelOrTaskRegion(I->Directive));
+ } while (I != E && !isImplicitTaskingRegion(I->Directive));
DVar.CKind =
(DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
return DVar;
@@ -963,7 +1070,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const {
if (!isStackEmpty()) {
iterator I = Iter, E = Stack.back().first.rend();
Scope *TopScope = nullptr;
- while (I != E && !isParallelOrTaskRegion(I->Directive) &&
+ while (I != E && !isImplicitOrExplicitTaskingRegion(I->Directive) &&
!isOpenMPTargetExecutionDirective(I->Directive))
++I;
if (I == E)
@@ -977,6 +1084,51 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const {
return false;
}
+static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
+ bool AcceptIfMutable = true,
+ bool *IsClassType = nullptr) {
+ ASTContext &Context = SemaRef.getASTContext();
+ Type = Type.getNonReferenceType().getCanonicalType();
+ bool IsConstant = Type.isConstant(Context);
+ Type = Context.getBaseElementType(Type);
+ const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
+ ? Type->getAsCXXRecordDecl()
+ : nullptr;
+ if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
+ if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
+ RD = CTD->getTemplatedDecl();
+ if (IsClassType)
+ *IsClassType = RD;
+ return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
+ RD->hasDefinition() && RD->hasMutableFields());
+}
+
+static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
+ QualType Type, OpenMPClauseKind CKind,
+ SourceLocation ELoc,
+ bool AcceptIfMutable = true,
+ bool ListItemNotVar = false) {
+ ASTContext &Context = SemaRef.getASTContext();
+ bool IsClassType;
+ if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
+ unsigned Diag = ListItemNotVar
+ ? diag::err_omp_const_list_item
+ : IsClassType ? diag::err_omp_const_not_mutable_variable
+ : diag::err_omp_const_variable;
+ SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
+ if (!ListItemNotVar && D) {
+ const VarDecl *VD = dyn_cast<VarDecl>(D);
+ bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ SemaRef.Diag(D->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << D;
+ }
+ return true;
+ }
+ return false;
+}
+
const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
bool FromParent) {
D = getCanonicalDecl(D);
@@ -1074,31 +1226,28 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
return DVar;
}
- QualType Type = D->getType().getNonReferenceType().getCanonicalType();
- bool IsConstant = Type.isConstant(SemaRef.getASTContext());
- Type = SemaRef.getASTContext().getBaseElementType(Type);
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.6]
- // Variables with const qualified type having no mutable member are
- // shared.
- const CXXRecordDecl *RD =
- SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
- if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
- if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
- RD = CTD->getTemplatedDecl();
- if (IsConstant &&
- !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasDefinition() &&
- RD->hasMutableFields())) {
- // Variables with const-qualified type having no mutable member may be
- // listed in a firstprivate clause, even if they are static data members.
- DSAVarData DVarTemp =
- hasDSA(D, [](OpenMPClauseKind C) { return C == OMPC_firstprivate; },
- MatchesAlways, FromParent);
- if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
- return DVarTemp;
+ // The predetermined shared attribute for const-qualified types having no
+ // mutable members was removed after OpenMP 3.1.
+ if (SemaRef.LangOpts.OpenMP <= 31) {
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.6]
+ // Variables with const qualified type having no mutable member are
+ // shared.
+ if (isConstNotMutableType(SemaRef, D->getType())) {
+ // Variables with const-qualified type having no mutable member may be
+ // listed in a firstprivate clause, even if they are static data members.
+ DSAVarData DVarTemp = hasInnermostDSA(
+ D,
+ [](OpenMPClauseKind C) {
+ return C == OMPC_firstprivate || C == OMPC_shared;
+ },
+ MatchesAlways, FromParent);
+ if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
+ return DVarTemp;
- DVar.CKind = OMPC_shared;
- return DVar;
+ DVar.CKind = OMPC_shared;
+ return DVar;
+ }
}
// Explicitly specified attributes and local variables with predetermined
@@ -1147,7 +1296,7 @@ DSAStackTy::hasDSA(ValueDecl *D,
if (FromParent && I != EndI)
std::advance(I, 1);
for (; I != EndI; std::advance(I, 1)) {
- if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
+ if (!DPred(I->Directive) && !isImplicitOrExplicitTaskingRegion(I->Directive))
continue;
iterator NewI = I;
DSAVarData DVar = getDSA(NewI, D);
@@ -1187,10 +1336,16 @@ bool DSAStackTy::hasExplicitDSA(
return false;
std::advance(StartI, Level);
auto I = StartI->SharingMap.find(D);
- return (I != StartI->SharingMap.end()) &&
+ if ((I != StartI->SharingMap.end()) &&
I->getSecond().RefExpr.getPointer() &&
CPred(I->getSecond().Attributes) &&
- (!NotLastprivate || !I->getSecond().RefExpr.getInt());
+ (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
+ return true;
+ // Check predetermined rules for the loop control variables.
+ auto LI = StartI->LCVMap.find(D);
+ if (LI != StartI->LCVMap.end())
+ return CPred(OMPC_private);
+ return false;
}
bool DSAStackTy::hasExplicitDirective(
@@ -1239,17 +1394,6 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
DSAStack->popFunction(OldFSI);
}
-static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
-isDeclareTargetDeclaration(const ValueDecl *VD) {
- for (const Decl *D : VD->redecls()) {
- if (!D->hasAttrs())
- continue;
- if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
- return Attr->getMapType();
- }
- return llvm::None;
-}
-
bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
@@ -1368,6 +1512,8 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const {
// By default, all the data that has a scalar type is mapped by copy
// (except for reduction variables).
IsByRef =
+ (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
+ !Ty->isAnyPointerType()) ||
!Ty->isScalarType() ||
DSAStack->getDefaultDMAAtLevel(Level) == DMA_tofrom_scalar ||
DSAStack->hasExplicitDSA(
@@ -1377,10 +1523,12 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const {
if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
IsByRef =
- !DSAStack->hasExplicitDSA(
- D,
- [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; },
- Level, /*NotLastprivate=*/true) &&
+ ((DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
+ !Ty->isAnyPointerType()) ||
+ !DSAStack->hasExplicitDSA(
+ D,
+ [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; },
+ Level, /*NotLastprivate=*/true)) &&
// If the variable is artificial and must be captured by value - try to
// capture by value.
!(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
@@ -1417,7 +1565,7 @@ bool Sema::isInOpenMPTargetExecutionDirective() const {
false);
}
-VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const {
+VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
D = getCanonicalDecl(D);
@@ -1425,13 +1573,65 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const {
// 'target' we return true so that this global is also mapped to the device.
//
auto *VD = dyn_cast<VarDecl>(D);
- if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective()) {
- // If the declaration is enclosed in a 'declare target' directive,
- // then it should not be captured.
- //
- if (isDeclareTargetDeclaration(VD))
+ if (VD && !VD->hasLocalStorage()) {
+ if (isInOpenMPDeclareTargetContext() &&
+ (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
+ // Try to mark variable as declare target if it is used in capturing
+ // regions.
+ if (!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
return nullptr;
- return VD;
+ } else if (isInOpenMPTargetExecutionDirective()) {
+ // If the declaration is enclosed in a 'declare target' directive,
+ // then it should not be captured.
+ //
+ if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ return nullptr;
+ return VD;
+ }
+ }
+ // Capture variables captured by reference in lambdas for target-based
+ // directives.
+ if (VD && !DSAStack->isClauseParsingMode()) {
+ if (const auto *RD = VD->getType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ ->getAsCXXRecordDecl()) {
+ bool SavedForceCaptureByReferenceInTargetExecutable =
+ DSAStack->isForceCaptureByReferenceInTargetExecutable();
+ DSAStack->setForceCaptureByReferenceInTargetExecutable(/*V=*/true);
+ if (RD->isLambda()) {
+ llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
+ FieldDecl *ThisCapture;
+ RD->getCaptureFields(Captures, ThisCapture);
+ for (const LambdaCapture &LC : RD->captures()) {
+ if (LC.getCaptureKind() == LCK_ByRef) {
+ VarDecl *VD = LC.getCapturedVar();
+ DeclContext *VDC = VD->getDeclContext();
+ if (!VDC->Encloses(CurContext))
+ continue;
+ DSAStackTy::DSAVarData DVarPrivate =
+ DSAStack->getTopDSA(VD, /*FromParent=*/false);
+ // Do not capture already captured variables.
+ if (!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
+ DVarPrivate.CKind == OMPC_unknown &&
+ !DSAStack->checkMappableExprComponentListsForDecl(
+ D, /*CurrentRegionOnly=*/true,
+ [](OMPClauseMappableExprCommon::
+ MappableExprComponentListRef,
+ OpenMPClauseKind) { return true; }))
+ MarkVariableReferenced(LC.getLocation(), LC.getCapturedVar());
+ } else if (LC.getCaptureKind() == LCK_This) {
+ QualType ThisTy = getCurrentThisType();
+ if (!ThisTy.isNull() &&
+ Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
+ CheckCXXThisCapture(LC.getLocation());
+ }
+ }
+ }
+ DSAStack->setForceCaptureByReferenceInTargetExecutable(
+ SavedForceCaptureByReferenceInTargetExecutable);
+ }
}
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
@@ -1440,7 +1640,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const {
auto &&Info = DSAStack->isLoopControlVariable(D);
if (Info.first ||
(VD && VD->hasLocalStorage() &&
- isParallelOrTaskRegion(DSAStack->getCurrentDirective())) ||
+ isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
(VD && DSAStack->isForceVarCapturing()))
return VD ? VD : Info.second;
DSAStackTy::DSAVarData DVarPrivate =
@@ -1463,8 +1663,28 @@ void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
FunctionScopesIndex -= Regions.size();
}
+void Sema::startOpenMPLoop() {
+ assert(LangOpts.OpenMP && "OpenMP must be enabled.");
+ if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
+ DSAStack->loopInit();
+}
+
bool Sema::isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
+ if (DSAStack->getAssociatedLoops() > 0 &&
+ !DSAStack->isLoopStarted()) {
+ DSAStack->resetPossibleLoopCounter(D);
+ DSAStack->loopStart();
+ return true;
+ }
+ if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
+ DSAStack->isLoopControlVariable(D).first) &&
+ !DSAStack->hasExplicitDSA(
+ D, [](OpenMPClauseKind K) { return K != OMPC_private; }, Level) &&
+ !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
+ return true;
+ }
return DSAStack->hasExplicitDSA(
D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) ||
(DSAStack->isClauseParsingMode() &&
@@ -1780,7 +2000,7 @@ public:
bool VisitDeclRefExpr(const DeclRefExpr *E) {
if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
if (VD->hasLocalStorage()) {
- SemaRef.Diag(E->getLocStart(),
+ SemaRef.Diag(E->getBeginLoc(),
diag::err_omp_local_var_in_threadprivate_init)
<< E->getSourceRange();
SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
@@ -1882,6 +2102,30 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
return D;
}
+Sema::DeclGroupPtrTy
+Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
+ ArrayRef<OMPClause *> ClauseList) {
+ OMPRequiresDecl *D = nullptr;
+ if (!CurContext->isFileContext()) {
+ Diag(Loc, diag::err_omp_invalid_scope) << "requires";
+ } else {
+ D = CheckOMPRequiresDecl(Loc, ClauseList);
+ if (D) {
+ CurContext->addDecl(D);
+ DSAStack->addRequiresDecl(D);
+ }
+ }
+ return DeclGroupPtrTy::make(DeclGroupRef(D));
+}
+
+OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
+ ArrayRef<OMPClause *> ClauseList) {
+ if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
+ return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
+ ClauseList);
+ return nullptr;
+}
+
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
const ValueDecl *D,
const DSAStackTy::DSAVarData &DVar,
@@ -1950,6 +2194,30 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
+ void VisitSubCaptures(OMPExecutableDirective *S) {
+ // Check implicitly captured variables.
+ if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
+ return;
+ for (const CapturedStmt::Capture &Cap :
+ S->getInnermostCapturedStmt()->captures()) {
+ if (!Cap.capturesVariable())
+ continue;
+ VarDecl *VD = Cap.getCapturedVar();
+ // Do not try to map the variable if it or its sub-component was mapped
+ // already.
+ if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
+ Stack->checkMappableExprComponentListsForDecl(
+ VD, /*CurrentRegionOnly=*/true,
+ [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind) { return true; }))
+ continue;
+ DeclRefExpr *DRE = buildDeclRefExpr(
+ SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
+ Cap.getLocation(), /*RefersToCapture=*/true);
+ Visit(DRE);
+ }
+ }
+
public:
void VisitDeclRefExpr(DeclRefExpr *E) {
if (E->isTypeDependent() || E->isValueDependent() ||
@@ -1968,7 +2236,7 @@ public:
// Skip internally declared static variables.
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD);
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) &&
(!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link))
return;
@@ -1980,7 +2248,7 @@ public:
// attribute, must have its data-sharing attribute explicitly determined
// by being listed in a data-sharing attribute clause.
if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none &&
- isParallelOrTaskRegion(DKind) &&
+ isImplicitOrExplicitTaskingRegion(DKind) &&
VarsWithInheritedDSA.count(VD) == 0) {
VarsWithInheritedDSA[VD] = E;
return;
@@ -2057,7 +2325,7 @@ public:
return;
auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
- if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
+ if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParens())) {
if (!FD)
return;
DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
@@ -2084,6 +2352,12 @@ public:
//
if (FD->isBitField())
return;
+
+ // Check to see if the member expression is referencing a class that
+ // has already been explicitly mapped
+ if (Stack->isClassPreviouslyMapped(TE->getType()))
+ return;
+
ImplicitMap.emplace_back(E);
return;
}
@@ -2110,8 +2384,14 @@ public:
// Define implicit data-sharing attributes for task.
DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
- !Stack->isLoopControlVariable(FD).first)
- ImplicitFirstprivate.push_back(E);
+ !Stack->isLoopControlVariable(FD).first) {
+ // Check if there is a captured expression for the current field in the
+ // region. Do not mark it as firstprivate unless there is no captured
+ // expression.
+ // TODO: try to make it firstprivate.
+ if (DVar.CKind != OMPC_unknown)
+ ImplicitFirstprivate.push_back(E);
+ }
return;
}
if (isOpenMPTargetExecutionDirective(DKind)) {
@@ -2171,11 +2451,16 @@ public:
}
}
}
+ // Check implicitly captured variables.
+ VisitSubCaptures(S);
}
void VisitStmt(Stmt *S) {
for (Stmt *C : S->children()) {
- if (C && !isa<OMPExecutableDirective>(C))
+ if (C) {
+ // Check implicitly captured variables in the task-based directives to
+ // check if they must be firstprivatized.
Visit(C);
+ }
}
}
@@ -2527,6 +2812,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_declare_simd:
case OMPD_declare_target:
case OMPD_end_declare_target:
+ case OMPD_requires:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -2560,7 +2846,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
WithInit = true;
}
auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty,
- CaptureExpr->getLocStart());
+ CaptureExpr->getBeginLoc());
if (!WithInit)
CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
S.CurContext->addHiddenDecl(CED);
@@ -2697,20 +2983,20 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
? SC->getFirstScheduleModifierLoc()
: SC->getSecondScheduleModifierLoc(),
diag::err_omp_schedule_nonmonotonic_ordered)
- << SourceRange(OC->getLocStart(), OC->getLocEnd());
+ << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
ErrorFound = true;
}
if (!LCs.empty() && OC && OC->getNumForLoops()) {
for (const OMPLinearClause *C : LCs) {
- Diag(C->getLocStart(), diag::err_omp_linear_ordered)
- << SourceRange(OC->getLocStart(), OC->getLocEnd());
+ Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
+ << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
}
ErrorFound = true;
}
if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
OC->getNumForLoops()) {
- Diag(OC->getLocStart(), diag::err_omp_ordered_simd)
+ Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
<< getOpenMPDirectiveName(DSAStack->getCurrentDirective());
ErrorFound = true;
}
@@ -2812,11 +3098,13 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
}
return false;
}
- // Allow some constructs (except teams) to be orphaned (they could be
- // used in functions, called from OpenMP regions with the required
- // preconditions).
+ // Allow some constructs (except teams and cancellation constructs) to be
+ // orphaned (they could be used in functions, called from OpenMP regions
+ // with the required preconditions).
if (ParentRegion == OMPD_unknown &&
- !isOpenMPNestingTeamsDirective(CurrentRegion))
+ !isOpenMPNestingTeamsDirective(CurrentRegion) &&
+ CurrentRegion != OMPD_cancellation_point &&
+ CurrentRegion != OMPD_cancel)
return false;
if (CurrentRegion == OMPD_cancellation_point ||
CurrentRegion == OMPD_cancel) {
@@ -2845,6 +3133,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
(CancelRegion == OMPD_sections &&
(ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
ParentRegion == OMPD_parallel_sections)));
+ OrphanSeen = ParentRegion == OMPD_unknown;
} else if (CurrentRegion == OMPD_master) {
// OpenMP [2.16, Nesting of Regions]
// A master region may not be closely nested inside a worksharing,
@@ -2989,7 +3278,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
// the directive.
OpenMPDirectiveKind CurNM = IC->getNameModifier();
if (FoundNameModifiers[CurNM]) {
- S.Diag(C->getLocStart(), diag::err_omp_more_one_clause)
+ S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
<< (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
ErrorFound = true;
@@ -3023,7 +3312,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
// all if clauses on the directive must include a directive-name-modifier.
if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
if (NamedModifiersNumber == AllowedNameModifiers.size()) {
- S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(),
+ S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
diag::err_omp_no_more_if_clause);
} else {
std::string Values;
@@ -3045,7 +3334,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
++AllowedCnt;
}
}
- S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(),
+ S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
diag::err_omp_unnamed_if_clause)
<< (TotalAllowedNum > 1) << Values;
}
@@ -3113,9 +3402,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
}
if (!ImplicitMaps.empty()) {
if (OMPClause *Implicit = ActOnOpenMPMapClause(
- OMPC_MAP_unknown, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true,
- SourceLocation(), SourceLocation(), ImplicitMaps,
- SourceLocation(), SourceLocation(), SourceLocation())) {
+ llvm::None, llvm::None, OMPC_MAP_tofrom,
+ /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
+ ImplicitMaps, SourceLocation(), SourceLocation(),
+ SourceLocation())) {
ClausesWithImplicit.emplace_back(Implicit);
ErrorFound |=
cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size();
@@ -3368,6 +3658,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_threadprivate:
case OMPD_declare_reduction:
case OMPD_declare_simd:
+ case OMPD_requires:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -3687,7 +3978,8 @@ class OpenMPIterationSpaceChecker {
/// Var <= UB
/// UB > Var
/// UB >= Var
- bool TestIsLessOp = false;
+ /// This will have no value when the condition is !=
+ llvm::Optional<bool> TestIsLessOp;
/// This flag is true when condition is strict ( < or > ).
bool TestIsStrictOp = false;
/// This flag is true when step is subtracted on each iteration.
@@ -3736,6 +4028,13 @@ public:
Expr *buildCounterInit() const;
/// Build step of the counter be used for codegen.
Expr *buildCounterStep() const;
+ /// Build loop data with counter value for depend clauses in ordered
+ /// directives.
+ Expr *
+ buildOrderedLoopData(Scope *S, Expr *Counter,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
+ SourceLocation Loc, Expr *Inc = nullptr,
+ OverloadedOperatorKind OOK = OO_Amp);
/// Return true if any expression is dependent.
bool dependent() const;
@@ -3746,8 +4045,8 @@ private:
/// Helper to set loop counter variable and its initializer.
bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB);
/// Helper to set upper bound.
- bool setUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR,
- SourceLocation SL);
+ bool setUB(Expr *NewUB, llvm::Optional<bool> LessOp, bool StrictOp,
+ SourceRange SR, SourceLocation SL);
/// Helper to set loop increment.
bool setStep(Expr *NewStep, bool Subtract);
};
@@ -3782,15 +4081,17 @@ bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
return false;
}
-bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, bool LessOp, bool StrictOp,
- SourceRange SR, SourceLocation SL) {
+bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, llvm::Optional<bool> LessOp,
+ bool StrictOp, SourceRange SR,
+ SourceLocation SL) {
// State consistency checking to ensure correct usage.
assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
if (!NewUB)
return true;
UB = NewUB;
- TestIsLessOp = LessOp;
+ if (LessOp)
+ TestIsLessOp = LessOp;
TestIsStrictOp = StrictOp;
ConditionSrcRange = SR;
ConditionLoc = SL;
@@ -3804,7 +4105,7 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
return true;
if (!NewStep->isValueDependent()) {
// Check that the step is integer expression.
- SourceLocation StepLoc = NewStep->getLocStart();
+ SourceLocation StepLoc = NewStep->getBeginLoc();
ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion(
StepLoc, getExprAsWritten(NewStep));
if (Val.isInvalid())
@@ -3830,18 +4131,23 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
bool IsConstPos =
IsConstant && Result.isSigned() && (Subtract == Result.isNegative());
bool IsConstZero = IsConstant && !Result.getBoolValue();
+
+ // != with increment is treated as <; != with decrement is treated as >
+ if (!TestIsLessOp.hasValue())
+ TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
if (UB && (IsConstZero ||
- (TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
- : (IsConstPos || (IsUnsigned && !Subtract))))) {
+ (TestIsLessOp.getValue() ?
+ (IsConstNeg || (IsUnsigned && Subtract)) :
+ (IsConstPos || (IsUnsigned && !Subtract))))) {
SemaRef.Diag(NewStep->getExprLoc(),
diag::err_omp_loop_incr_not_compatible)
- << LCDecl << TestIsLessOp << NewStep->getSourceRange();
+ << LCDecl << TestIsLessOp.getValue() << NewStep->getSourceRange();
SemaRef.Diag(ConditionLoc,
diag::note_omp_loop_cond_requres_compatible_incr)
- << TestIsLessOp << ConditionSrcRange;
+ << TestIsLessOp.getValue() << ConditionSrcRange;
return true;
}
- if (TestIsLessOp == Subtract) {
+ if (TestIsLessOp.getValue() == Subtract) {
NewStep =
SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
.get();
@@ -3897,10 +4203,15 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
if (Var->hasInit() && !Var->getType()->isReferenceType()) {
// Accept non-canonical init form here but emit ext. warning.
if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
- SemaRef.Diag(S->getLocStart(),
+ SemaRef.Diag(S->getBeginLoc(),
diag::ext_omp_loop_not_canonical_init)
<< S->getSourceRange();
- return setLCDeclAndLB(Var, nullptr, Var->getInit());
+ return setLCDeclAndLB(
+ Var,
+ buildDeclRefExpr(SemaRef, Var,
+ Var->getType().getNonReferenceType(),
+ DS->getBeginLoc()),
+ Var->getInit());
}
}
}
@@ -3924,7 +4235,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
if (EmitDiags) {
- SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
+ SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
<< S->getSourceRange();
}
return true;
@@ -3964,7 +4275,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
return true;
}
S = getExprAsWritten(S);
- SourceLocation CondLoc = S->getLocStart();
+ SourceLocation CondLoc = S->getBeginLoc();
if (auto *BO = dyn_cast<BinaryOperator>(S)) {
if (BO->isRelationalOp()) {
if (getInitLCDecl(BO->getLHS()) == LCDecl)
@@ -3977,7 +4288,12 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
(BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE),
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
BO->getSourceRange(), BO->getOperatorLoc());
- }
+ } else if (BO->getOpcode() == BO_NE)
+ return setUB(getInitLCDecl(BO->getLHS()) == LCDecl ?
+ BO->getRHS() : BO->getLHS(),
+ /*LessOp=*/llvm::None,
+ /*StrictOp=*/true,
+ BO->getSourceRange(), BO->getOperatorLoc());
} else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
if (CE->getNumArgs() == 2) {
auto Op = CE->getOperator();
@@ -3995,6 +4311,14 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
CE->getOperatorLoc());
break;
+ case OO_ExclaimEqual:
+ return setUB(getInitLCDecl(CE->getArg(0)) == LCDecl ?
+ CE->getArg(1) : CE->getArg(0),
+ /*LessOp=*/llvm::None,
+ /*StrictOp=*/true,
+ CE->getSourceRange(),
+ CE->getOperatorLoc());
+ break;
default:
break;
}
@@ -4033,7 +4357,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
}
if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
- SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr)
+ SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
<< RHS->getSourceRange() << LCDecl;
return true;
}
@@ -4066,7 +4390,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
if (UO->isIncrementDecrementOp() &&
getInitLCDecl(UO->getSubExpr()) == LCDecl)
return setStep(SemaRef
- .ActOnIntegerConstant(UO->getLocStart(),
+ .ActOnIntegerConstant(UO->getBeginLoc(),
(UO->isDecrementOp() ? -1 : 1))
.get(),
/*Subtract=*/false);
@@ -4091,7 +4415,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
if (getInitLCDecl(CE->getArg(0)) == LCDecl)
return setStep(SemaRef
.ActOnIntegerConstant(
- CE->getLocStart(),
+ CE->getBeginLoc(),
((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
.get(),
/*Subtract=*/false);
@@ -4111,7 +4435,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
}
if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
- SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr)
+ SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
<< S->getSourceRange() << LCDecl;
return true;
}
@@ -4143,8 +4467,8 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations(
if (VarType->isIntegerType() || VarType->isPointerType() ||
SemaRef.getLangOpts().CPlusPlus) {
// Upper - Lower
- Expr *UBExpr = TestIsLessOp ? UB : LB;
- Expr *LBExpr = TestIsLessOp ? LB : UB;
+ Expr *UBExpr = TestIsLessOp.getValue() ? UB : LB;
+ Expr *LBExpr = TestIsLessOp.getValue() ? LB : UB;
Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get();
Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get();
if (!Upper || !Lower)
@@ -4155,7 +4479,7 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations(
if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) {
// BuildBinOp already emitted error, this one is to point user to upper
// and lower bound, and to tell what is passed to 'operator-'.
- SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx)
+ SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
<< Upper->getSourceRange() << Lower->getSourceRange();
return nullptr;
}
@@ -4245,8 +4569,9 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond(
ExprResult CondExpr =
SemaRef.BuildBinOp(S, DefaultLoc,
- TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
- : (TestIsStrictOp ? BO_GT : BO_GE),
+ TestIsLessOp.getValue() ?
+ (TestIsStrictOp ? BO_LT : BO_LE) :
+ (TestIsStrictOp ? BO_GT : BO_GE),
NewLB.get(), NewUB.get());
if (CondExpr.isUsable()) {
if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
@@ -4262,7 +4587,8 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond(
/// Build reference expression to the counter be used for codegen.
DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
- llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const {
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
+ DSAStackTy &DSA) const {
auto *VD = dyn_cast<VarDecl>(LCDecl);
if (!VD) {
VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
@@ -4302,6 +4628,63 @@ Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
/// Build step of the counter be used for codegen.
Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
+Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
+ Scope *S, Expr *Counter,
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
+ Expr *Inc, OverloadedOperatorKind OOK) {
+ Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
+ if (!Cnt)
+ return nullptr;
+ if (Inc) {
+ assert((OOK == OO_Plus || OOK == OO_Minus) &&
+ "Expected only + or - operations for depend clauses.");
+ BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
+ Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
+ if (!Cnt)
+ return nullptr;
+ }
+ ExprResult Diff;
+ QualType VarType = LCDecl->getType().getNonReferenceType();
+ if (VarType->isIntegerType() || VarType->isPointerType() ||
+ SemaRef.getLangOpts().CPlusPlus) {
+ // Upper - Lower
+ Expr *Upper =
+ TestIsLessOp.getValue() ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get();
+ Expr *Lower =
+ TestIsLessOp.getValue() ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
+ if (!Upper || !Lower)
+ return nullptr;
+
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
+
+ if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) {
+ // BuildBinOp already emitted error, this one is to point user to upper
+ // and lower bound, and to tell what is passed to 'operator-'.
+ SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
+ << Upper->getSourceRange() << Lower->getSourceRange();
+ return nullptr;
+ }
+ }
+
+ if (!Diff.isUsable())
+ return nullptr;
+
+ // Parentheses (for dumping/debugging purposes only).
+ Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
+ if (!NewStep.isUsable())
+ return nullptr;
+ // (Upper - Lower) / Step
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ return Diff.get();
+}
+
/// Iteration space of a single for loop.
struct LoopIterationSpace final {
/// Condition of the loop.
@@ -4336,6 +4719,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
if (AssociatedLoops > 0 &&
isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
+ DSAStack->loopStart();
OpenMPIterationSpaceChecker ISC(*this, ForLoc);
if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
if (ValueDecl *D = ISC.getLoopDecl()) {
@@ -4350,6 +4734,15 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
}
}
DSAStack->addLoopControlVariable(D, VD);
+ const Decl *LD = DSAStack->getPossiblyLoopCunter();
+ if (LD != D->getCanonicalDecl()) {
+ DSAStack->resetPossibleLoopCounter();
+ if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
+ MarkDeclarationsReferencedInExpr(
+ buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
+ Var->getType().getNonLValueExprType(Context),
+ ForLoc, /*RefersToCapture=*/true));
+ }
}
}
DSAStack->setAssociatedLoops(AssociatedLoops - 1);
@@ -4361,7 +4754,8 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
static bool checkOpenMPIterationSpace(
OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
- Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,
+ unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
+ Expr *OrderedLoopCountExpr,
Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
LoopIterationSpace &ResultIterSpace,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
@@ -4369,11 +4763,11 @@ static bool checkOpenMPIterationSpace(
// for (init-expr; test-expr; incr-expr) structured-block
auto *For = dyn_cast_or_null<ForStmt>(S);
if (!For) {
- SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
+ SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
<< (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
- << getOpenMPDirectiveName(DKind) << NestedLoopCount
+ << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
<< (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
- if (NestedLoopCount > 1) {
+ if (TotalNestedLoopCount > 1) {
if (CollapseLoopCountExpr && OrderedLoopCountExpr)
SemaRef.Diag(DSA.getConstructLoc(),
diag::note_omp_collapse_ordered_expr)
@@ -4414,7 +4808,7 @@ static bool checkOpenMPIterationSpace(
if (!VarType->isDependentType() && !VarType->isIntegerType() &&
!VarType->isPointerType() &&
!(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
- SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_variable_type)
+ SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
<< SemaRef.getLangOpts().CPlusPlus;
HasErrors = true;
}
@@ -4452,7 +4846,7 @@ static bool checkOpenMPIterationSpace(
!isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
(DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
- SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
+ SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
<< getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(PredeterminedCKind);
if (DVar.RefExpr == nullptr)
@@ -4506,6 +4900,41 @@ static bool checkOpenMPIterationSpace(
ResultIterSpace.PrivateCounterVar == nullptr ||
ResultIterSpace.CounterInit == nullptr ||
ResultIterSpace.CounterStep == nullptr);
+ if (!HasErrors && DSA.isOrderedRegion()) {
+ if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
+ if (CurrentNestedLoopCount <
+ DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
+ DSA.getOrderedRegionParam().second->setLoopNumIterations(
+ CurrentNestedLoopCount, ResultIterSpace.NumIterations);
+ DSA.getOrderedRegionParam().second->setLoopCounter(
+ CurrentNestedLoopCount, ResultIterSpace.CounterVar);
+ }
+ }
+ for (auto &Pair : DSA.getDoacrossDependClauses()) {
+ if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
+ // Erroneous case - clause has some problems.
+ continue;
+ }
+ if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
+ Pair.second.size() <= CurrentNestedLoopCount) {
+ // Erroneous case - clause has some problems.
+ Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
+ continue;
+ }
+ Expr *CntValue;
+ if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
+ CntValue = ISC.buildOrderedLoopData(
+ DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
+ Pair.first->getDependencyLoc());
+ else
+ CntValue = ISC.buildOrderedLoopData(
+ DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
+ Pair.first->getDependencyLoc(),
+ Pair.second[CurrentNestedLoopCount].first,
+ Pair.second[CurrentNestedLoopCount].second);
+ Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
+ }
+ }
return HasErrors;
}
@@ -4687,14 +5116,16 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
unsigned NestedLoopCount = 1;
if (CollapseLoopCountExpr) {
// Found 'collapse' clause - calculate collapse number.
- llvm::APSInt Result;
+ Expr::EvalResult Result;
if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
- NestedLoopCount = Result.getLimitedValue();
+ NestedLoopCount = Result.Val.getInt().getLimitedValue();
}
+ unsigned OrderedLoopCount = 1;
if (OrderedLoopCountExpr) {
// Found 'ordered' clause - calculate collapse number.
- llvm::APSInt Result;
- if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
+ Expr::EvalResult EVResult;
+ if (OrderedLoopCountExpr->EvaluateAsInt(EVResult, SemaRef.getASTContext())) {
+ llvm::APSInt Result = EVResult.Val.getInt();
if (Result.getLimitedValue() < NestedLoopCount) {
SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
diag::err_omp_wrong_ordered_loop_count)
@@ -4703,20 +5134,21 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
diag::note_collapse_loop_count)
<< CollapseLoopCountExpr->getSourceRange();
}
- NestedLoopCount = Result.getLimitedValue();
+ OrderedLoopCount = Result.getLimitedValue();
}
}
// This is helper routine for loop directives (e.g., 'for', 'simd',
// 'for simd', etc.).
llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
SmallVector<LoopIterationSpace, 4> IterSpaces;
- IterSpaces.resize(NestedLoopCount);
+ IterSpaces.resize(std::max(OrderedLoopCount, NestedLoopCount));
Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
- if (checkOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
- NestedLoopCount, CollapseLoopCountExpr,
- OrderedLoopCountExpr, VarsWithImplicitDSA,
- IterSpaces[Cnt], Captures))
+ if (checkOpenMPIterationSpace(
+ DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
+ std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
+ OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
+ Captures))
return 0;
// Move on to the next nested for loop, or to the loop body.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -4725,6 +5157,27 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// any two loops.
CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
}
+ for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) {
+ if (checkOpenMPIterationSpace(
+ DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
+ std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
+ OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
+ Captures))
+ return 0;
+ if (Cnt > 0 && IterSpaces[Cnt].CounterVar) {
+ // Handle initialization of captured loop iterator variables.
+ auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
+ if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
+ Captures[DRE] = DRE;
+ }
+ }
+ // Move on to the next nested for loop, or to the loop body.
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // All loops associated with the construct must be perfectly nested; that
+ // is, there must be no intervening code nor any OpenMP directive between
+ // any two loops.
+ CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
+ }
Built.clear(/* size */ NestedLoopCount);
@@ -4817,13 +5270,14 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Choose either the 32-bit or 64-bit version.
ExprResult LastIteration = LastIteration64;
- if (LastIteration32.isUsable() &&
- C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
- (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
- fitsInto(
- /*Bits=*/32,
- LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
- LastIteration64.get(), SemaRef)))
+ if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
+ (LastIteration32.isUsable() &&
+ C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
+ (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
+ fitsInto(
+ /*Bits=*/32,
+ LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
+ LastIteration64.get(), SemaRef))))
LastIteration = LastIteration32;
QualType VType = LastIteration.get()->getType();
QualType RealVType = VType;
@@ -4913,7 +5367,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
LastIteration.get(), UB.get());
EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
CondOp.get());
- EUB = SemaRef.ActOnFinishFullExpr(EUB.get());
+ EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
// If we have a combined directive that combines 'distribute', 'for' or
// 'simd' we need to be able to access the bounds of the schedule of the
@@ -4942,7 +5396,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
LastIteration.get(), CombUB.get());
CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
CombCondOp.get());
- CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get());
+ CombEUB =
+ SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
// We expect to have at least 2 more parameters than the 'parallel'
@@ -4976,7 +5431,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
? LB.get()
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
- Init = SemaRef.ActOnFinishFullExpr(Init.get());
+ Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
if (isOpenMPLoopBoundSharingDirective(DKind)) {
Expr *CombRHS =
@@ -4987,32 +5442,40 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
CombInit =
SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
- CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get());
+ CombInit =
+ SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
}
}
// Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.
- SourceLocation CondLoc = AStmt->getLocStart();
+ SourceLocation CondLoc = AStmt->getBeginLoc();
ExprResult Cond =
(isOpenMPWorksharingDirective(DKind) ||
isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get())
: SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
NumIterations.get());
+ ExprResult CombDistCond;
+ if (isOpenMPLoopBoundSharingDirective(DKind)) {
+ CombDistCond =
+ SemaRef.BuildBinOp(
+ CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get());
+ }
+
ExprResult CombCond;
if (isOpenMPLoopBoundSharingDirective(DKind)) {
CombCond =
SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get());
}
// Loop increment (IV = IV + 1)
- SourceLocation IncLoc = AStmt->getLocStart();
+ SourceLocation IncLoc = AStmt->getBeginLoc();
ExprResult Inc =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
if (!Inc.isUsable())
return 0;
Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
- Inc = SemaRef.ActOnFinishFullExpr(Inc.get());
+ Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
if (!Inc.isUsable())
return 0;
@@ -5030,7 +5493,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// LB = LB + ST
NextLB =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
- NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get());
+ NextLB =
+ SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
if (!NextLB.isUsable())
return 0;
// UB + ST
@@ -5040,7 +5504,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// UB = UB + ST
NextUB =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
- NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get());
+ NextUB =
+ SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
if (!NextUB.isUsable())
return 0;
if (isOpenMPLoopBoundSharingDirective(DKind)) {
@@ -5051,7 +5516,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// LB = LB + ST
CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
CombNextLB.get());
- CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get());
+ CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
+ /*DiscardedValue*/ false);
if (!CombNextLB.isUsable())
return 0;
// UB + ST
@@ -5062,7 +5528,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// UB = UB + ST
CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
CombNextUB.get());
- CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get());
+ CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
+ /*DiscardedValue*/ false);
if (!CombNextUB.isUsable())
return 0;
}
@@ -5072,8 +5539,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// directive with for as IV = IV + ST; ensure upper bound expression based
// on PrevUB instead of NumIterations - used to implement 'for' when found
// in combination with 'distribute', like in 'distribute parallel for'
- SourceLocation DistIncLoc = AStmt->getLocStart();
- ExprResult DistCond, DistInc, PrevEUB;
+ SourceLocation DistIncLoc = AStmt->getBeginLoc();
+ ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
if (isOpenMPLoopBoundSharingDirective(DKind)) {
DistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get());
assert(DistCond.isUsable() && "distribute cond expr was not built");
@@ -5083,19 +5550,26 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
assert(DistInc.isUsable() && "distribute inc expr was not built");
DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
DistInc.get());
- DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get());
+ DistInc =
+ SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
assert(DistInc.isUsable() && "distribute inc expr was not built");
// Build expression: UB = min(UB, prevUB) for #for in composite or combined
// construct
- SourceLocation DistEUBLoc = AStmt->getLocStart();
+ SourceLocation DistEUBLoc = AStmt->getBeginLoc();
ExprResult IsUBGreater =
SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, UB.get(), PrevUB.get());
ExprResult CondOp = SemaRef.ActOnConditionalOp(
DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get());
PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
CondOp.get());
- PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get());
+ PrevEUB =
+ SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
+
+ // Build IV <= PrevUB to be used in parallel for is in combination with
+ // a distribute directive with schedule(static, 1)
+ ParForInDistCond =
+ SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), PrevUB.get());
}
// Build updates and final values of the loop counters.
@@ -5104,33 +5578,60 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Built.Inits.resize(NestedLoopCount);
Built.Updates.resize(NestedLoopCount);
Built.Finals.resize(NestedLoopCount);
- SmallVector<Expr *, 4> LoopMultipliers;
{
- ExprResult Div;
- // Go from inner nested loop to outer.
- for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) {
+ // We implement the following algorithm for obtaining the
+ // original loop iteration variable values based on the
+ // value of the collapsed loop iteration variable IV.
+ //
+ // Let n+1 be the number of collapsed loops in the nest.
+ // Iteration variables (I0, I1, .... In)
+ // Iteration counts (N0, N1, ... Nn)
+ //
+ // Acc = IV;
+ //
+ // To compute Ik for loop k, 0 <= k <= n, generate:
+ // Prod = N(k+1) * N(k+2) * ... * Nn;
+ // Ik = Acc / Prod;
+ // Acc -= Ik * Prod;
+ //
+ ExprResult Acc = IV;
+ for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
LoopIterationSpace &IS = IterSpaces[Cnt];
SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
- // Build: Iter = (IV / Div) % IS.NumIters
- // where Div is product of previous iterations' IS.NumIters.
ExprResult Iter;
- if (Div.isUsable()) {
- Iter =
- SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, IV.get(), Div.get());
- } else {
- Iter = IV;
- assert((Cnt == (int)NestedLoopCount - 1) &&
- "unusable div expected on first iteration only");
- }
- if (Cnt != 0 && Iter.isUsable())
- Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Rem, Iter.get(),
- IS.NumIterations);
+ // Compute prod
+ ExprResult Prod =
+ SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
+ for (unsigned int K = Cnt+1; K < NestedLoopCount; ++K)
+ Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
+ IterSpaces[K].NumIterations);
+
+ // Iter = Acc / Prod
+ // If there is at least one more inner loop to avoid
+ // multiplication by 1.
+ if (Cnt + 1 < NestedLoopCount)
+ Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div,
+ Acc.get(), Prod.get());
+ else
+ Iter = Acc;
if (!Iter.isUsable()) {
HasErrors = true;
break;
}
+ // Update Acc:
+ // Acc -= Iter * Prod
+ // Check if there is at least one more inner loop to avoid
+ // multiplication by 1.
+ if (Cnt + 1 < NestedLoopCount)
+ Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul,
+ Iter.get(), Prod.get());
+ else
+ Prod = Iter;
+ Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub,
+ Acc.get(), Prod.get());
+
// Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
DeclRefExpr *CounterVar = buildDeclRefExpr(
@@ -5159,23 +5660,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
break;
}
- // Build Div for the next iteration: Div <- Div * IS.NumIters
- if (Cnt != 0) {
- if (Div.isUnset())
- Div = IS.NumIterations;
- else
- Div = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Div.get(),
- IS.NumIterations);
-
- // Add parentheses (for debugging purposes only).
- if (Div.isUsable())
- Div = tryBuildCapture(SemaRef, Div.get(), Captures);
- if (!Div.isUsable()) {
- HasErrors = true;
- break;
- }
- LoopMultipliers.push_back(Div.get());
- }
if (!Update.isUsable() || !Final.isUsable()) {
HasErrors = true;
break;
@@ -5196,8 +5680,10 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Built.IterationVarRef = IV.get();
Built.LastIteration = LastIteration.get();
Built.NumIterations = NumIterations.get();
- Built.CalcLastIteration =
- SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get();
+ Built.CalcLastIteration = SemaRef
+ .ActOnFinishFullExpr(CalcLastIteration.get(),
+ /*DiscardedValue*/ false)
+ .get();
Built.PreCond = PreCond.get();
Built.PreInits = buildPreInits(C, Captures);
Built.Cond = Cond.get();
@@ -5221,55 +5707,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Built.DistCombinedFields.Cond = CombCond.get();
Built.DistCombinedFields.NLB = CombNextLB.get();
Built.DistCombinedFields.NUB = CombNextUB.get();
-
- Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get();
- // Fill data for doacross depend clauses.
- for (const auto &Pair : DSA.getDoacrossDependClauses()) {
- if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) {
- Pair.first->setCounterValue(CounterVal);
- } else {
- if (NestedLoopCount != Pair.second.size() ||
- NestedLoopCount != LoopMultipliers.size() + 1) {
- // Erroneous case - clause has some problems.
- Pair.first->setCounterValue(CounterVal);
- continue;
- }
- assert(Pair.first->getDependencyKind() == OMPC_DEPEND_sink);
- auto I = Pair.second.rbegin();
- auto IS = IterSpaces.rbegin();
- auto ILM = LoopMultipliers.rbegin();
- Expr *UpCounterVal = CounterVal;
- Expr *Multiplier = nullptr;
- for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) {
- if (I->first) {
- assert(IS->CounterStep);
- Expr *NormalizedOffset =
- SemaRef
- .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Div,
- I->first, IS->CounterStep)
- .get();
- if (Multiplier) {
- NormalizedOffset =
- SemaRef
- .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Mul,
- NormalizedOffset, Multiplier)
- .get();
- }
- assert(I->second == OO_Plus || I->second == OO_Minus);
- BinaryOperatorKind BOK = (I->second == OO_Plus) ? BO_Add : BO_Sub;
- UpCounterVal = SemaRef
- .BuildBinOp(CurScope, I->first->getExprLoc(), BOK,
- UpCounterVal, NormalizedOffset)
- .get();
- }
- Multiplier = *ILM;
- ++I;
- ++IS;
- ++ILM;
- }
- Pair.first->setCounterValue(UpCounterVal);
- }
- }
+ Built.DistCombinedFields.DistCond = CombDistCond.get();
+ Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
return NestedLoopCount;
}
@@ -5305,7 +5744,6 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
}
if (Simdlen && Safelen) {
- llvm::APSInt SimdlenRes, SafelenRes;
const Expr *SimdlenLength = Simdlen->getSimdlen();
const Expr *SafelenLength = Safelen->getSafelen();
if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
@@ -5316,8 +5754,11 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
SafelenLength->isInstantiationDependent() ||
SafelenLength->containsUnexpandedParameterPack())
return false;
- SimdlenLength->EvaluateAsInt(SimdlenRes, S.Context);
- SafelenLength->EvaluateAsInt(SafelenRes, S.Context);
+ Expr::EvalResult SimdlenResult, SafelenResult;
+ SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
+ SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
+ llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
+ llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
// OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
// If both simdlen and safelen clauses are specified, the value of the
// simdlen parameter must be less than or equal to the value of the safelen
@@ -5466,7 +5907,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
- Diag(SectionStmt->getLocStart(),
+ Diag(SectionStmt->getBeginLoc(),
diag::err_omp_sections_substmt_not_section);
return StmtError();
}
@@ -5474,7 +5915,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
->setHasCancel(DSAStack->isCancelRegion());
}
} else {
- Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt);
+ Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
return StmtError();
}
@@ -5520,9 +5961,9 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
else if (Clause->getClauseKind() == OMPC_copyprivate)
Copyprivate = Clause;
if (Copyprivate && Nowait) {
- Diag(Copyprivate->getLocStart(),
+ Diag(Copyprivate->getBeginLoc(),
diag::err_omp_single_copyprivate_with_nowait);
- Diag(Nowait->getLocStart(), diag::note_omp_nowait_clause_here);
+ Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
return StmtError();
}
}
@@ -5558,7 +5999,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
for (const OMPClause *C : Clauses) {
if (C->getClauseKind() == OMPC_hint) {
if (!DirName.getName()) {
- Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name);
+ Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
ErrorFound = true;
}
Expr *E = cast<OMPHintClause>(C)->getHint();
@@ -5567,7 +6008,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
DependentHint = true;
} else {
Hint = E->EvaluateKnownConstInt(Context);
- HintLoc = C->getLocStart();
+ HintLoc = C->getBeginLoc();
}
}
}
@@ -5583,12 +6024,12 @@ StmtResult Sema::ActOnOpenMPCriticalDirective(
else
Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
- Diag(C->getLocStart(), diag::note_omp_critical_hint_here)
+ Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
<< 1
<< C->getHint()->EvaluateKnownConstInt(Context).toString(
/*Radix=*/10, /*Signed=*/false);
} else {
- Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1;
+ Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
}
}
}
@@ -5709,7 +6150,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
- Diag(SectionStmt->getLocStart(),
+ Diag(SectionStmt->getBeginLoc(),
diag::err_omp_parallel_sections_substmt_not_section);
return StmtError();
}
@@ -5717,7 +6158,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
->setHasCancel(DSAStack->isCancelRegion());
}
} else {
- Diag(AStmt->getLocStart(),
+ Diag(AStmt->getBeginLoc(),
diag::err_omp_parallel_sections_not_compound_stmt);
return StmtError();
}
@@ -5801,7 +6242,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
DependFound = C;
if (DC->getDependencyKind() == OMPC_DEPEND_source) {
if (DependSourceClause) {
- Diag(C->getLocStart(), diag::err_omp_more_one_clause)
+ Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(OMPD_ordered)
<< getOpenMPClauseName(OMPC_depend) << 2;
ErrorFound = true;
@@ -5809,13 +6250,13 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
DependSourceClause = C;
}
if (DependSinkClause) {
- Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
<< 0;
ErrorFound = true;
}
} else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
if (DependSourceClause) {
- Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
<< 1;
ErrorFound = true;
}
@@ -5835,19 +6276,19 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
Diag(StartLoc, diag::err_omp_prohibited_region_simd);
ErrorFound = true;
} else if (DependFound && (TC || SC)) {
- Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd)
+ Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd)
<< getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
ErrorFound = true;
- } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) {
- Diag(DependFound->getLocStart(),
+ } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) {
+ Diag(DependFound->getBeginLoc(),
diag::err_omp_ordered_directive_without_param);
ErrorFound = true;
} else if (TC || Clauses.empty()) {
- if (const Expr *Param = DSAStack->getParentOrderedRegionParam()) {
- SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc;
+ if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
+ SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
<< (TC != nullptr);
- Diag(Param->getLocStart(), diag::note_omp_ordered_param);
+ Diag(Param->getBeginLoc(), diag::note_omp_ordered_param);
ErrorFound = true;
}
}
@@ -6068,12 +6509,12 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
}
} else {
ErrorFound = NotAScalarType;
- NoteLoc = ErrorLoc = AtomicBody->getLocStart();
+ NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
}
} else {
ErrorFound = NotAnExpression;
- NoteLoc = ErrorLoc = S->getLocStart();
+ NoteLoc = ErrorLoc = S->getBeginLoc();
NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
}
if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
@@ -6125,13 +6566,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
C->getClauseKind() == OMPC_update ||
C->getClauseKind() == OMPC_capture) {
if (AtomicKind != OMPC_unknown) {
- Diag(C->getLocStart(), diag::err_omp_atomic_several_clauses)
- << SourceRange(C->getLocStart(), C->getLocEnd());
+ Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
+ << SourceRange(C->getBeginLoc(), C->getEndLoc());
Diag(AtomicKindLoc, diag::note_omp_atomic_previous_clause)
<< getOpenMPClauseName(AtomicKind);
} else {
AtomicKind = C->getClauseKind();
- AtomicKindLoc = C->getLocStart();
+ AtomicKindLoc = C->getBeginLoc();
}
}
}
@@ -6219,7 +6660,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
} else {
ErrorFound = NotAnExpression;
- NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteLoc = ErrorLoc = Body->getBeginLoc();
NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
}
if (ErrorFound != NoError) {
@@ -6281,7 +6722,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
} else {
ErrorFound = NotAnExpression;
- NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteLoc = ErrorLoc = Body->getBeginLoc();
NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
}
if (ErrorFound != NoError) {
@@ -6465,7 +6906,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
ErrorFound = NotAnAssignmentOp;
NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
- : First->getLocStart();
+ : First->getBeginLoc();
NoteRange = ErrorRange = FirstBinOp
? FirstBinOp->getSourceRange()
: SourceRange(ErrorLoc, ErrorLoc);
@@ -6475,7 +6916,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
ErrorFound = NotAnAssignmentOp;
NoteLoc = ErrorLoc = SecondBinOp
? SecondBinOp->getOperatorLoc()
- : Second->getLocStart();
+ : Second->getBeginLoc();
NoteRange = ErrorRange =
SecondBinOp ? SecondBinOp->getSourceRange()
: SourceRange(ErrorLoc, ErrorLoc);
@@ -6509,15 +6950,15 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
}
} else {
- NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteLoc = ErrorLoc = Body->getBeginLoc();
NoteRange = ErrorRange =
- SourceRange(Body->getLocStart(), Body->getLocStart());
+ SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
ErrorFound = NotTwoSubstatements;
}
} else {
- NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteLoc = ErrorLoc = Body->getBeginLoc();
NoteRange = ErrorRange =
- SourceRange(Body->getLocStart(), Body->getLocStart());
+ SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
ErrorFound = NotACompoundStatement;
}
if (ErrorFound != NoError) {
@@ -6590,7 +7031,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
Diag(DSAStack->getInnerTeamsRegionLoc(),
diag::note_omp_nested_teams_construct_here);
- Diag(S->getLocStart(), diag::note_omp_nested_statement_here)
+ Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
<< isa<OMPExecutableDirective>(S);
return StmtError();
}
@@ -6894,11 +7335,11 @@ static bool checkGrainsizeNumTasksClauses(Sema &S,
if (!PrevClause)
PrevClause = C;
else if (PrevClause->getClauseKind() != C->getClauseKind()) {
- S.Diag(C->getLocStart(),
+ S.Diag(C->getBeginLoc(),
diag::err_omp_grainsize_num_tasks_mutually_exclusive)
<< getOpenMPClauseName(C->getClauseKind())
<< getOpenMPClauseName(PrevClause->getClauseKind());
- S.Diag(PrevClause->getLocStart(),
+ S.Diag(PrevClause->getBeginLoc(),
diag::note_omp_previous_grainsize_num_tasks)
<< getOpenMPClauseName(PrevClause->getClauseKind());
ErrorFound = true;
@@ -6927,9 +7368,9 @@ static bool checkReductionClauseWithNogroup(Sema &S,
}
}
if (ReductionClause && NogroupClause) {
- S.Diag(ReductionClause->getLocStart(), diag::err_omp_reduction_with_nogroup)
- << SourceRange(NogroupClause->getLocStart(),
- NogroupClause->getLocEnd());
+ S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
+ << SourceRange(NogroupClause->getBeginLoc(),
+ NogroupClause->getEndLoc());
return true;
}
return false;
@@ -7859,6 +8300,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
+ case OMPC_atomic_default_mem_order:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7944,6 +8390,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_distribute_simd:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
+ case OMPD_requires:
llvm_unreachable("Unexpected OpenMP directive with if-clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -8009,6 +8456,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_distribute_simd:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
+ case OMPD_requires:
llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -8072,6 +8520,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_distribute_simd:
+ case OMPD_requires:
llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -8135,6 +8584,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_distribute_simd:
+ case OMPD_requires:
llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -8198,6 +8648,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_atomic:
case OMPD_distribute_simd:
case OMPD_target_teams:
+ case OMPD_requires:
llvm_unreachable("Unexpected OpenMP directive with schedule clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -8261,6 +8712,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_target_teams:
+ case OMPD_requires:
llvm_unreachable("Unexpected OpenMP directive with schedule clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -8324,6 +8776,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_ordered:
case OMPD_atomic:
case OMPD_distribute_simd:
+ case OMPD_requires:
llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -8373,6 +8826,11 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
+ case OMPC_atomic_default_mem_order:
llvm_unreachable("Unexpected OpenMP clause.");
}
return CaptureRegion;
@@ -8619,9 +9077,11 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
} else {
NumForLoops = nullptr;
}
- DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops);
- return new (Context)
- OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc);
+ auto *Clause = OMPOrderedClause::Create(
+ Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
+ StartLoc, LParenLoc, EndLoc);
+ DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
+ return Clause;
}
OMPClause *Sema::ActOnOpenMPSimpleClause(
@@ -8639,6 +9099,11 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
static_cast<OpenMPProcBindClauseKind>(Argument), ArgumentLoc, StartLoc,
LParenLoc, EndLoc);
break;
+ case OMPC_atomic_default_mem_order:
+ Res = ActOnOpenMPAtomicDefaultMemOrderClause(
+ static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
+ ArgumentLoc, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -8688,6 +9153,10 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -8760,6 +9229,21 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
+ OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
+ if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
+ Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
+ << getListOfPossibleValues(
+ OMPC_atomic_default_mem_order, /*First=*/0,
+ /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
+ << getOpenMPClauseName(OMPC_atomic_default_mem_order);
+ return nullptr;
+ }
+ return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
+ LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
SourceLocation StartLoc, SourceLocation LParenLoc,
@@ -8844,6 +9328,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
+ case OMPC_atomic_default_mem_order:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -8923,7 +9412,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
!ChunkSize->isInstantiationDependent() &&
!ChunkSize->containsUnexpandedParameterPack()) {
- SourceLocation ChunkSizeLoc = ChunkSize->getLocStart();
+ SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
ExprResult Val =
PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
if (Val.isInvalid())
@@ -8999,6 +9488,18 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_nogroup:
Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
break;
+ case OMPC_unified_address:
+ Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
+ break;
+ case OMPC_unified_shared_memory:
+ Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
+ break;
+ case OMPC_reverse_offload:
+ Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
+ break;
+ case OMPC_dynamic_allocators:
+ Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -9038,6 +9539,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_atomic_default_mem_order:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -9099,12 +9601,34 @@ OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
return new (Context) OMPNogroupClause(StartLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
- OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPLinearClauseKind LinKind,
+ ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
SourceLocation DepLinMapLoc) {
OMPClause *Res = nullptr;
@@ -9157,9 +9681,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
StartLoc, LParenLoc, EndLoc);
break;
case OMPC_map:
- Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, IsMapTypeImplicit,
- DepLinMapLoc, ColonLoc, VarList, StartLoc,
- LParenLoc, EndLoc);
+ Res = ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc, MapType,
+ IsMapTypeImplicit, DepLinMapLoc, ColonLoc,
+ VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_to:
Res = ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc);
@@ -9206,6 +9730,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_defaultmap:
case OMPC_unknown:
case OMPC_uniform:
+ case OMPC_unified_address:
+ case OMPC_unified_shared_memory:
+ case OMPC_reverse_offload:
+ case OMPC_dynamic_allocators:
+ case OMPC_atomic_default_mem_order:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -9321,6 +9850,17 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
continue;
Type = Type.getNonReferenceType();
+ // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
+ // A variable that is privatized must not have a const-qualified type
+ // unless it is of class type with a mutable member. This restriction does
+ // not apply to the firstprivate clause.
+ //
+ // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
+ // A variable that appears in a private clause must not have a
+ // const-qualified type unless it is of class type with a mutable member.
+ if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
+ continue;
+
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
// Variables with the predetermined data-sharing attributes may not be
@@ -9742,6 +10282,17 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
continue;
Type = Type.getNonReferenceType();
+ // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
+ // A variable that is privatized must not have a const-qualified type
+ // unless it is of class type with a mutable member. This restriction does
+ // not apply to the firstprivate clause.
+ //
+ // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
+ // A variable that appears in a lastprivate clause must not have a
+ // const-qualified type unless it is of class type with a mutable member.
+ if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
+ continue;
+
OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
@@ -9807,8 +10358,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid())
continue;
- AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
- /*DiscardedValue=*/true);
+ AssignmentOp =
+ ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
if (AssignmentOp.isInvalid())
continue;
@@ -9971,6 +10522,79 @@ static T filterLookupForUDR(SmallVectorImpl<U> &Lookups,
return T();
}
+static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
+ assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
+
+ for (auto RD : D->redecls()) {
+ // Don't bother with extra checks if we already know this one isn't visible.
+ if (RD == D)
+ continue;
+
+ auto ND = cast<NamedDecl>(RD);
+ if (LookupResult::isVisible(SemaRef, ND))
+ return ND;
+ }
+
+ return nullptr;
+}
+
+static void
+argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &ReductionId,
+ SourceLocation Loc, QualType Ty,
+ SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
+ // Find all of the associated namespaces and classes based on the
+ // arguments we have.
+ Sema::AssociatedNamespaceSet AssociatedNamespaces;
+ Sema::AssociatedClassSet AssociatedClasses;
+ OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
+ SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
+ AssociatedClasses);
+
+ // C++ [basic.lookup.argdep]p3:
+ // Let X be the lookup set produced by unqualified lookup (3.4.1)
+ // and let Y be the lookup set produced by argument dependent
+ // lookup (defined as follows). If X contains [...] then Y is
+ // empty. Otherwise Y is the set of declarations found in the
+ // namespaces associated with the argument types as described
+ // below. The set of declarations found by the lookup of the name
+ // is the union of X and Y.
+ //
+ // Here, we compute Y and add its members to the overloaded
+ // candidate set.
+ for (auto *NS : AssociatedNamespaces) {
+ // When considering an associated namespace, the lookup is the
+ // same as the lookup performed when the associated namespace is
+ // used as a qualifier (3.4.3.2) except that:
+ //
+ // -- Any using-directives in the associated namespace are
+ // ignored.
+ //
+ // -- Any namespace-scope friend functions declared in
+ // associated classes are visible within their respective
+ // namespaces even if they are not visible during an ordinary
+ // lookup (11.4).
+ DeclContext::lookup_result R = NS->lookup(ReductionId.getName());
+ for (auto *D : R) {
+ auto *Underlying = D;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
+
+ if (!isa<OMPDeclareReductionDecl>(Underlying))
+ continue;
+
+ if (!SemaRef.isVisible(D)) {
+ D = findAcceptableDecl(SemaRef, D);
+ if (!D)
+ continue;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
+ }
+ Lookups.emplace_back();
+ Lookups.back().addDecl(Underlying);
+ }
+ }
+}
+
static ExprResult
buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
@@ -9989,7 +10613,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
} while (S && !S->isDeclScope(D));
if (S)
S = S->getParent();
- Lookups.push_back(UnresolvedSet<8>());
+ Lookups.emplace_back();
Lookups.back().append(Lookup.begin(), Lookup.end());
Lookup.clear();
}
@@ -10016,6 +10640,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
})) {
UnresolvedSet<8> ResSet;
for (const UnresolvedSet<8> &Set : Lookups) {
+ if (Set.empty())
+ continue;
ResSet.append(Set.begin(), Set.end());
// The last item marks the end of all declarations at the specified scope.
ResSet.addDecl(Set[Set.size() - 1]);
@@ -10025,6 +10651,36 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
/*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
}
+ // Lookup inside the classes.
+ // C++ [over.match.oper]p3:
+ // For a unary operator @ with an operand of a type whose
+ // cv-unqualified version is T1, and for a binary operator @ with
+ // a left operand of a type whose cv-unqualified version is T1 and
+ // a right operand of a type whose cv-unqualified version is T2,
+ // three sets of candidate functions, designated member
+ // candidates, non-member candidates and built-in candidates, are
+ // constructed as follows:
+ // -- If T1 is a complete class type or a class currently being
+ // defined, the set of member candidates is the result of the
+ // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
+ // the set of member candidates is empty.
+ LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
+ Lookup.suppressDiagnostics();
+ if (const auto *TyRec = Ty->getAs<RecordType>()) {
+ // Complete the type if it can be completed.
+ // If the type is neither complete nor being defined, bail out now.
+ if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
+ TyRec->getDecl()->getDefinition()) {
+ Lookup.clear();
+ SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
+ if (Lookup.empty()) {
+ Lookups.emplace_back();
+ Lookups.back().append(Lookup.begin(), Lookup.end());
+ }
+ }
+ }
+ // Perform ADL.
+ argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
if (auto *VD = filterLookupForUDR<ValueDecl *>(
Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
if (!D->isInvalidDecl() &&
@@ -10131,10 +10787,11 @@ static bool checkOMPArraySectionConstantForReduction(
SingleElement = true;
ArraySizes.push_back(llvm::APSInt::get(1));
} else {
- llvm::APSInt ConstantLengthValue;
- if (!Length->EvaluateAsInt(ConstantLengthValue, Context))
+ Expr::EvalResult Result;
+ if (!Length->EvaluateAsInt(Result, Context))
return false;
+ llvm::APSInt ConstantLengthValue = Result.Val.getInt();
SingleElement = (ConstantLengthValue.getSExtValue() == 1);
ArraySizes.push_back(ConstantLengthValue);
}
@@ -10155,9 +10812,12 @@ static bool checkOMPArraySectionConstantForReduction(
// This is an array subscript which has implicit length 1!
ArraySizes.push_back(llvm::APSInt::get(1));
} else {
- llvm::APSInt ConstantLengthValue;
- if (!Length->EvaluateAsInt(ConstantLengthValue, Context) ||
- ConstantLengthValue.getSExtValue() != 1)
+ Expr::EvalResult Result;
+ if (!Length->EvaluateAsInt(Result, Context))
+ return false;
+
+ llvm::APSInt ConstantLengthValue = Result.Val.getInt();
+ if (ConstantLengthValue.getSExtValue() != 1)
return false;
ArraySizes.push_back(ConstantLengthValue);
@@ -10342,76 +11002,71 @@ static bool actOnOMPReductionKindClause(
// OpenMP [2.14.3.6, reduction clause, Restrictions]
// A list item that appears in a reduction clause must not be
// const-qualified.
- if (Type.getNonReferenceType().isConstant(Context)) {
- S.Diag(ELoc, diag::err_omp_const_reduction_list_item) << ERange;
- if (!ASE && !OASE) {
- bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- S.Diag(D->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << D;
- }
+ if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
+ /*AcceptIfMutable*/ false, ASE || OASE))
continue;
- }
+
+ OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
// OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
// If a list-item is a reference type then it must bind to the same object
// for all threads of the team.
- if (!ASE && !OASE && VD) {
- VarDecl *VDDef = VD->getDefinition();
- if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
- DSARefChecker Check(Stack);
- if (Check.Visit(VDDef->getInit())) {
- S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
- << getOpenMPClauseName(ClauseKind) << ERange;
- S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
- continue;
+ if (!ASE && !OASE) {
+ if (VD) {
+ VarDecl *VDDef = VD->getDefinition();
+ if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
+ DSARefChecker Check(Stack);
+ if (Check.Visit(VDDef->getInit())) {
+ S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
+ << getOpenMPClauseName(ClauseKind) << ERange;
+ S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
+ continue;
+ }
}
}
- }
-
- // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct]
- // Variables with the predetermined data-sharing attributes may not be
- // listed in data-sharing attributes clauses, except for the cases
- // listed below. For these exceptions only, listing a predetermined
- // variable in a data-sharing attribute clause is allowed and overrides
- // the variable's predetermined data-sharing attributes.
- // OpenMP [2.14.3.6, Restrictions, p.3]
- // Any number of reduction clauses can be specified on the directive,
- // but a list item can appear only once in the reduction clauses for that
- // directive.
- DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
- if (DVar.CKind == OMPC_reduction) {
- S.Diag(ELoc, diag::err_omp_once_referenced)
- << getOpenMPClauseName(ClauseKind);
- if (DVar.RefExpr)
- S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
- continue;
- }
- if (DVar.CKind != OMPC_unknown) {
- S.Diag(ELoc, diag::err_omp_wrong_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPClauseName(OMPC_reduction);
- reportOriginalDsa(S, Stack, D, DVar);
- continue;
- }
- // OpenMP [2.14.3.6, Restrictions, p.1]
- // A list item that appears in a reduction clause of a worksharing
- // construct must be shared in the parallel regions to which any of the
- // worksharing regions arising from the worksharing construct bind.
- OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
- if (isOpenMPWorksharingDirective(CurrDir) &&
- !isOpenMPParallelDirective(CurrDir) &&
- !isOpenMPTeamsDirective(CurrDir)) {
- DVar = Stack->getImplicitDSA(D, true);
- if (DVar.CKind != OMPC_shared) {
- S.Diag(ELoc, diag::err_omp_required_access)
- << getOpenMPClauseName(OMPC_reduction)
- << getOpenMPClauseName(OMPC_shared);
+ // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct]
+ // Variables with the predetermined data-sharing attributes may not be
+ // listed in data-sharing attributes clauses, except for the cases
+ // listed below. For these exceptions only, listing a predetermined
+ // variable in a data-sharing attribute clause is allowed and overrides
+ // the variable's predetermined data-sharing attributes.
+ // OpenMP [2.14.3.6, Restrictions, p.3]
+ // Any number of reduction clauses can be specified on the directive,
+ // but a list item can appear only once in the reduction clauses for that
+ // directive.
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
+ if (DVar.CKind == OMPC_reduction) {
+ S.Diag(ELoc, diag::err_omp_once_referenced)
+ << getOpenMPClauseName(ClauseKind);
+ if (DVar.RefExpr)
+ S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
+ continue;
+ }
+ if (DVar.CKind != OMPC_unknown) {
+ S.Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_reduction);
reportOriginalDsa(S, Stack, D, DVar);
continue;
}
+
+ // OpenMP [2.14.3.6, Restrictions, p.1]
+ // A list item that appears in a reduction clause of a worksharing
+ // construct must be shared in the parallel regions to which any of the
+ // worksharing regions arising from the worksharing construct bind.
+ if (isOpenMPWorksharingDirective(CurrDir) &&
+ !isOpenMPParallelDirective(CurrDir) &&
+ !isOpenMPTeamsDirective(CurrDir)) {
+ DVar = Stack->getImplicitDSA(D, true);
+ if (DVar.CKind != OMPC_shared) {
+ S.Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_reduction)
+ << getOpenMPClauseName(OMPC_shared);
+ reportOriginalDsa(S, Stack, D, DVar);
+ continue;
+ }
+ }
}
// Try to find 'declare reduction' corresponding construct before using
@@ -10430,7 +11085,7 @@ static bool actOnOMPReductionKindClause(
}
if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
// Not allowed reduction identifier is found.
- S.Diag(ReductionId.getLocStart(),
+ S.Diag(ReductionId.getBeginLoc(),
diag::err_omp_unknown_reduction_identifier)
<< Type << ReductionIdRange;
continue;
@@ -10683,26 +11338,27 @@ static bool actOnOMPReductionKindClause(
ELoc, Context.getPointerType(FnTy), VK_RValue, OK_Ordinary,
S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
Expr *Args[] = {LHS.get(), RHS.get()};
- ReductionOp = new (Context)
- CallExpr(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc);
+ ReductionOp =
+ CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc);
} else {
ReductionOp = S.BuildBinOp(
- Stack->getCurScope(), ReductionId.getLocStart(), BOK, LHSDRE, RHSDRE);
+ Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE);
if (ReductionOp.isUsable()) {
if (BOK != BO_LT && BOK != BO_GT) {
ReductionOp =
- S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(),
+ S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
BO_Assign, LHSDRE, ReductionOp.get());
} else {
auto *ConditionalOp = new (Context)
ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, RHSDRE,
Type, VK_LValue, OK_Ordinary);
ReductionOp =
- S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(),
+ S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
BO_Assign, LHSDRE, ConditionalOp);
}
if (ReductionOp.isUsable())
- ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get());
+ ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
+ /*DiscardedValue*/ false);
}
if (!ReductionOp.isUsable())
continue;
@@ -10744,7 +11400,7 @@ static bool actOnOMPReductionKindClause(
EmitError = RedId != ParentRedId;
}
if (EmitError) {
- S.Diag(ReductionId.getLocStart(),
+ S.Diag(ReductionId.getBeginLoc(),
diag::err_omp_reduction_identifier_mismatch)
<< ReductionIdRange << RefExpr->getSourceRange();
S.Diag(ParentSR.getBegin(),
@@ -10895,20 +11551,12 @@ bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
}
Type = Type.getNonReferenceType();
- // A list item must not be const-qualified.
- if (Type.isConstant(Context)) {
- Diag(ELoc, diag::err_omp_const_variable)
- << getOpenMPClauseName(OMPC_linear);
- if (D) {
- bool IsDecl =
- !VD ||
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(D->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << D;
- }
+ // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
+ // A variable that is privatized must not have a const-qualified type
+ // unless it is of class type with a mutable member. This restriction does
+ // not apply to the firstprivate clause.
+ if (rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
return true;
- }
// A list item must be of integral or pointer type.
Type = Type.getUnqualifiedType().getCanonicalType();
@@ -10945,8 +11593,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
- auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
- /*AllowArraySection=*/false);
+ auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
if (Res.second) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -11028,7 +11675,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
!Step->isInstantiationDependent() &&
!Step->containsUnexpandedParameterPack()) {
- SourceLocation StepLoc = Step->getLocStart();
+ SourceLocation StepLoc = Step->getBeginLoc();
ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
if (Val.isInvalid())
return nullptr;
@@ -11041,7 +11688,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
ExprResult CalcStep =
BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
- CalcStep = ActOnFinishFullExpr(CalcStep.get());
+ CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
// Warn about zero linear step (it would be probably better specified as
// making corresponding variables 'const').
@@ -11086,8 +11733,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
- auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
- /*AllowArraySection=*/false);
+ auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
ValueDecl *D = Res.first;
if (Res.second || !D) {
Updates.push_back(nullptr);
@@ -11129,8 +11775,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
InitExpr, IV, Step, /* Subtract */ false);
else
Update = *CurPrivate;
- Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(),
- /*DiscardedValue=*/true);
+ Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
+ /*DiscardedValue*/ false);
// Build final: Var = InitExpr + NumIterations * Step
ExprResult Final;
@@ -11140,8 +11786,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
InitExpr, NumIterations, Step, /*Subtract=*/false);
else
Final = *CurPrivate;
- Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(),
- /*DiscardedValue=*/true);
+ Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
+ /*DiscardedValue*/ false);
if (!Update.isUsable() || !Final.isUsable()) {
Updates.push_back(nullptr);
@@ -11168,8 +11814,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause(
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
- auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
- /*AllowArraySection=*/false);
+ auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
if (Res.second) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -11293,12 +11938,12 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// operator for the class type.
QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
VarDecl *SrcVD =
- buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(),
+ buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
*this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
VarDecl *DstVD =
- buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst",
+ buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
VD->hasAttrs() ? &VD->getAttrs() : nullptr);
DeclRefExpr *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
@@ -11310,7 +11955,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
if (AssignmentOp.isInvalid())
continue;
AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
- /*DiscardedValue=*/true);
+ /*DiscardedValue*/ false);
if (AssignmentOp.isInvalid())
continue;
@@ -11341,8 +11986,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
- auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
- /*AllowArraySection=*/false);
+ auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
if (Res.second) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -11408,19 +12052,19 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
Type = Context.getBaseElementType(Type.getNonReferenceType())
.getUnqualifiedType();
VarDecl *SrcVD =
- buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.src",
+ buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
D->hasAttrs() ? &D->getAttrs() : nullptr);
DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
VarDecl *DstVD =
- buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.dst",
+ buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
D->hasAttrs() ? &D->getAttrs() : nullptr);
DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
ExprResult AssignmentOp = BuildBinOp(
DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid())
continue;
- AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
- /*DiscardedValue=*/true);
+ AssignmentOp =
+ ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
if (AssignmentOp.isInvalid())
continue;
@@ -11477,8 +12121,9 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
DSAStackTy::OperatorOffsetTy OpsOffs;
llvm::APSInt DepCounter(/*BitWidth=*/32);
llvm::APSInt TotalDepCount(/*BitWidth=*/32);
- if (DepKind == OMPC_DEPEND_sink) {
- if (const Expr *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
+ if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
+ if (const Expr *OrderedCountExpr =
+ DSAStack->getParentOrderedRegionParam().first) {
TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
TotalDepCount.setIsUnsigned(/*Val=*/true);
}
@@ -11494,7 +12139,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
SourceLocation ELoc = RefExpr->getExprLoc();
Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
if (DepKind == OMPC_DEPEND_sink) {
- if (DSAStack->getParentOrderedRegionParam() &&
+ if (DSAStack->getParentOrderedRegionParam().first &&
DepCounter >= TotalDepCount) {
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
continue;
@@ -11539,8 +12184,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
}
SourceLocation ELoc;
SourceRange ERange;
- auto Res = getPrivateItem(*this, LHS, ELoc, ERange,
- /*AllowArraySection=*/false);
+ auto Res = getPrivateItem(*this, LHS, ELoc, ERange);
if (Res.second) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -11560,7 +12204,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
continue;
}
if (!CurContext->isDependentContext() &&
- DSAStack->getParentOrderedRegionParam() &&
+ DSAStack->getParentOrderedRegionParam().first &&
DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
const ValueDecl *VD =
DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
@@ -11598,7 +12242,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
TotalDepCount > VarList.size() &&
- DSAStack->getParentOrderedRegionParam() &&
+ DSAStack->getParentOrderedRegionParam().first &&
DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
<< 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
@@ -11608,7 +12252,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
return nullptr;
auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- DepKind, DepLoc, ColonLoc, Vars);
+ DepKind, DepLoc, ColonLoc, Vars,
+ TotalDepCount.getZExtValue());
if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
DSAStack->isParentOrderedRegion())
DSAStack->addDoacrossDependClause(C, OpsOffs);
@@ -11680,9 +12325,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
// If there is a lower bound that does not evaluates to zero, we are not
// covering the whole dimension.
if (LowerBound) {
- llvm::APSInt ConstLowerBound;
- if (!LowerBound->EvaluateAsInt(ConstLowerBound, SemaRef.getASTContext()))
+ Expr::EvalResult Result;
+ if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
return false; // Can't get the integer value as a constant.
+
+ llvm::APSInt ConstLowerBound = Result.Val.getInt();
if (ConstLowerBound.getSExtValue())
return true;
}
@@ -11702,10 +12349,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
if (!CATy)
return false;
- llvm::APSInt ConstLength;
- if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext()))
+ Expr::EvalResult Result;
+ if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
return false; // Can't get the integer value as a constant.
+ llvm::APSInt ConstLength = Result.Val.getInt();
return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
}
@@ -11736,10 +12384,11 @@ static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
}
// Check if the length evaluates to 1.
- llvm::APSInt ConstLength;
- if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext()))
+ Expr::EvalResult Result;
+ if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
return false; // Can't get the integer value as a constant.
+ llvm::APSInt ConstLength = Result.Val.getInt();
return ConstLength.getSExtValue() != 1;
}
@@ -11896,6 +12545,19 @@ static const Expr *checkMapClauseExpressionBase(
E->getType()))
AllowWholeSizeArraySection = false;
+ if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
+ Expr::EvalResult Result;
+ if (CurE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext())) {
+ if (!Result.Val.getInt().isNullValue()) {
+ SemaRef.Diag(CurE->getIdx()->getExprLoc(),
+ diag::err_omp_invalid_map_this_expr);
+ SemaRef.Diag(CurE->getIdx()->getExprLoc(),
+ diag::note_omp_invalid_subscript_on_this_ptr_map);
+ }
+ }
+ RelevantExpr = TE;
+ }
+
// Record the component - we don't have any declaration associated.
CurComponents.emplace_back(CurE, nullptr);
} else if (auto *CurE = dyn_cast<OMPArraySectionExpr>(E)) {
@@ -11942,6 +12604,30 @@ static const Expr *checkMapClauseExpressionBase(
return nullptr;
}
+ if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
+ Expr::EvalResult ResultR;
+ Expr::EvalResult ResultL;
+ if (CurE->getLength()->EvaluateAsInt(ResultR,
+ SemaRef.getASTContext())) {
+ if (!ResultR.Val.getInt().isOneValue()) {
+ SemaRef.Diag(CurE->getLength()->getExprLoc(),
+ diag::err_omp_invalid_map_this_expr);
+ SemaRef.Diag(CurE->getLength()->getExprLoc(),
+ diag::note_omp_invalid_length_on_this_ptr_mapping);
+ }
+ }
+ if (CurE->getLowerBound() && CurE->getLowerBound()->EvaluateAsInt(
+ ResultL, SemaRef.getASTContext())) {
+ if (!ResultL.Val.getInt().isNullValue()) {
+ SemaRef.Diag(CurE->getLowerBound()->getExprLoc(),
+ diag::err_omp_invalid_map_this_expr);
+ SemaRef.Diag(CurE->getLowerBound()->getExprLoc(),
+ diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
+ }
+ }
+ RelevantExpr = TE;
+ }
+
// Record the component - we don't have any declaration associated.
CurComponents.emplace_back(CurE, nullptr);
} else {
@@ -12129,6 +12815,26 @@ static bool checkMapConflicts(
// An expression is a subset of the other.
if (CurrentRegionOnly && (CI == CE || SI == SE)) {
if (CKind == OMPC_map) {
+ if (CI != CE || SI != SE) {
+ // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
+ // a pointer.
+ auto Begin =
+ CI != CE ? CurComponents.begin() : StackComponents.begin();
+ auto End = CI != CE ? CurComponents.end() : StackComponents.end();
+ auto It = Begin;
+ while (It != End && !It->getAssociatedDeclaration())
+ std::advance(It, 1);
+ assert(It != End &&
+ "Expected at least one component with the declaration.");
+ if (It != Begin && It->getAssociatedDeclaration()
+ ->getType()
+ .getCanonicalType()
+ ->isAnyPointerType()) {
+ IsEnclosedByDataEnvironmentExpr = false;
+ EnclosingExpr = nullptr;
+ return false;
+ }
+ }
SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
} else {
assert(CKind == OMPC_to || CKind == OMPC_from);
@@ -12259,6 +12965,18 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
assert(!CurComponents.empty() &&
"Invalid mappable expression information.");
+ if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
+ // Add store "this" pointer to class in DSAStackTy for future checking
+ DSAS->addMappedClassesQualTypes(TE->getType());
+ // Skip restriction checking for variable or field declarations
+ MVLI.ProcessedVarList.push_back(RE);
+ MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
+ MVLI.VarComponents.back().append(CurComponents.begin(),
+ CurComponents.end());
+ MVLI.VarBaseDeclarations.push_back(nullptr);
+ continue;
+ }
+
// For the following checks, we rely on the base declaration which is
// expected to be associated with the last component. The declaration is
// expected to be a variable or a field (if 'this' is being mapped).
@@ -12388,7 +13106,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
}
OMPClause *
-Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+Sema::ActOnOpenMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
SourceLocation MapLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
@@ -12397,12 +13116,31 @@ Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, StartLoc,
MapType, IsMapTypeImplicit);
+ OpenMPMapModifierKind Modifiers[] = { OMPC_MAP_MODIFIER_unknown,
+ OMPC_MAP_MODIFIER_unknown };
+ SourceLocation ModifiersLoc[OMPMapClause::NumberOfModifiers];
+
+ // Process map-type-modifiers, flag errors for duplicate modifiers.
+ unsigned Count = 0;
+ for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
+ if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
+ llvm::find(Modifiers, MapTypeModifiers[I]) != std::end(Modifiers)) {
+ Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
+ continue;
+ }
+ assert(Count < OMPMapClause::NumberOfModifiers &&
+ "Modifiers exceed the allowed number of map type modifiers");
+ Modifiers[Count] = MapTypeModifiers[I];
+ ModifiersLoc[Count] = MapTypeModifiersLoc[I];
+ ++Count;
+ }
+
// We need to produce a map clause even if we don't have variables so that
// other diagnostics related with non-existing map clauses are accurate.
return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc,
MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
- MVLI.VarComponents, MapTypeModifier, MapType,
- IsMapTypeImplicit, MapLoc);
+ MVLI.VarComponents, Modifiers, ModifiersLoc,
+ MapType, IsMapTypeImplicit, MapLoc);
}
QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
@@ -12559,6 +13297,11 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
DRD->addDecl(OmpInParm);
DRD->addDecl(OmpOutParm);
}
+ Expr *InE =
+ ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
+ Expr *OutE =
+ ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
+ DRD->setCombinerData(InE, OutE);
}
void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
@@ -12614,6 +13357,11 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
DRD->addDecl(OmpPrivParm);
DRD->addDecl(OmpOrigParm);
}
+ Expr *OrigE =
+ ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
+ Expr *PrivE =
+ ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
+ DRD->setInitializerData(OrigE, PrivE);
return OmpPrivParm;
}
@@ -12785,7 +13533,7 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause(
if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
!ChunkSize->isInstantiationDependent() &&
!ChunkSize->containsUnexpandedParameterPack()) {
- SourceLocation ChunkSizeLoc = ChunkSize->getLocStart();
+ SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
ExprResult Val =
PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
if (Val.isInvalid())
@@ -12861,19 +13609,14 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
Diag(Loc, diag::err_omp_region_not_file_context);
return false;
}
- if (IsInOpenMPDeclareTargetContext) {
- Diag(Loc, diag::err_omp_enclosed_declare_target);
- return false;
- }
-
- IsInOpenMPDeclareTargetContext = true;
+ ++DeclareTargetNestingLevel;
return true;
}
void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
- assert(IsInOpenMPDeclareTargetContext &&
+ assert(DeclareTargetNestingLevel > 0 &&
"Unexpected ActOnFinishOpenMPDeclareTargetDirective");
- IsInOpenMPDeclareTargetContext = false;
+ --DeclareTargetNestingLevel;
}
void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
@@ -12904,16 +13647,20 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
}
NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
- if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
+ if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
+ isa<FunctionTemplateDecl>(ND)) {
if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl())))
Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName();
- if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) {
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
+ cast<ValueDecl>(ND));
+ if (!Res) {
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT);
ND->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Id.getLoc());
- } else if (ND->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() != MT) {
+ } else if (*Res != MT) {
Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link)
<< Id.getName();
}
@@ -12924,79 +13671,13 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
Sema &SemaRef, Decl *D) {
- if (!D)
+ if (!D || !isa<VarDecl>(D))
return;
- const Decl *LD = nullptr;
- if (isa<TagDecl>(D)) {
- LD = cast<TagDecl>(D)->getDefinition();
- } else if (isa<VarDecl>(D)) {
- LD = cast<VarDecl>(D)->getDefinition();
-
- // If this is an implicit variable that is legal and we do not need to do
- // anything.
- if (cast<VarDecl>(D)->isImplicit()) {
- auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
- D->addAttr(A);
- if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
- return;
- }
- } else if (const auto *F = dyn_cast<FunctionDecl>(D)) {
- const FunctionDecl *FD = nullptr;
- if (cast<FunctionDecl>(D)->hasBody(FD)) {
- LD = FD;
- // If the definition is associated with the current declaration in the
- // target region (it can be e.g. a lambda) that is legal and we do not
- // need to do anything else.
- if (LD == D) {
- auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
- D->addAttr(A);
- if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
- return;
- }
- } else if (F->isFunctionTemplateSpecialization() &&
- F->getTemplateSpecializationKind() ==
- TSK_ImplicitInstantiation) {
- // Check if the function is implicitly instantiated from the template
- // defined in the declare target region.
- const FunctionTemplateDecl *FTD = F->getPrimaryTemplate();
- if (FTD && FTD->hasAttr<OMPDeclareTargetDeclAttr>())
- return;
- }
- }
- if (!LD)
- LD = D;
- if (LD && !LD->hasAttr<OMPDeclareTargetDeclAttr>() &&
- ((isa<VarDecl>(LD) && !isa<ParmVarDecl>(LD)) || isa<FunctionDecl>(LD))) {
- // Outlined declaration is not declared target.
- if (!isa<FunctionDecl>(LD)) {
- if (LD->isOutOfLine()) {
- SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context);
- SemaRef.Diag(SL, diag::note_used_here) << SR;
- } else {
- const DeclContext *DC = LD->getDeclContext();
- while (DC &&
- (!isa<FunctionDecl>(DC) ||
- !cast<FunctionDecl>(DC)->hasAttr<OMPDeclareTargetDeclAttr>()))
- DC = DC->getParent();
- if (DC)
- return;
-
- // Is not declared in target context.
- SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context);
- SemaRef.Diag(SL, diag::note_used_here) << SR;
- }
- }
- // Mark decl as declared target to prevent further diagnostic.
- auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
- D->addAttr(A);
- if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
- }
+ auto *VD = cast<VarDecl>(D);
+ if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ return;
+ SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
+ SemaRef.Diag(SL, diag::note_used_here) << SR;
}
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
@@ -13012,10 +13693,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
if (!D || D->isInvalidDecl())
return;
SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
- SourceLocation SL = E ? E->getLocStart() : D->getLocation();
+ SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
if (auto *VD = dyn_cast<VarDecl>(D)) {
// Only global variables can be marked as declare target.
- if (VD->isLocalVarDeclOrParm())
+ if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
+ !VD->isStaticDataMember())
return;
// 2.10.6: threadprivate variable cannot appear in a declare target
// directive.
@@ -13025,56 +13707,39 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
return;
}
}
+ if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ D = FTD->getTemplatedDecl();
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
+ if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
+ assert(IdLoc.isValid() && "Source location is expected");
+ Diag(IdLoc, diag::err_omp_function_in_link_clause);
+ Diag(FD->getLocation(), diag::note_defined_here) << FD;
+ return;
+ }
+ }
if (auto *VD = dyn_cast<ValueDecl>(D)) {
// Problem if any with var declared with incomplete type will be reported
// as normal, so no need to check it here.
if ((E || !VD->getType()->isIncompleteType()) &&
- !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) {
- // Mark decl as declared target to prevent further diagnostic.
- if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD) ||
- isa<FunctionTemplateDecl>(VD)) {
+ !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
+ return;
+ if (!E && !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
+ // Checking declaration inside declare target region.
+ if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
+ isa<FunctionTemplateDecl>(D)) {
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
Context, OMPDeclareTargetDeclAttr::MT_To);
- VD->addAttr(A);
+ D->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(VD, A);
+ ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
}
return;
}
}
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->hasAttr<OMPDeclareTargetDeclAttr>() &&
- (FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
- OMPDeclareTargetDeclAttr::MT_Link)) {
- assert(IdLoc.isValid() && "Source location is expected");
- Diag(IdLoc, diag::err_omp_function_in_link_clause);
- Diag(FD->getLocation(), diag::note_defined_here) << FD;
- return;
- }
- }
- if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
- if (FTD->hasAttr<OMPDeclareTargetDeclAttr>() &&
- (FTD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
- OMPDeclareTargetDeclAttr::MT_Link)) {
- assert(IdLoc.isValid() && "Source location is expected");
- Diag(IdLoc, diag::err_omp_function_in_link_clause);
- Diag(FTD->getLocation(), diag::note_defined_here) << FTD;
- return;
- }
- }
- if (!E) {
- // Checking declaration inside declare target region.
- if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
- (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
- isa<FunctionTemplateDecl>(D))) {
- auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- Context, OMPDeclareTargetDeclAttr::MT_To);
- D->addAttr(A);
- if (ASTMutationListener *ML = Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
- }
+ if (!E)
return;
- }
checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 08af485ef4c7..52be0598fbc0 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -63,8 +63,8 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
return ExprError();
if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
S.ResolveExceptionSpec(Loc, FPT);
- DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(),
- VK_LValue, Loc, LocInfo);
+ DeclRefExpr *DRE = new (S.Context)
+ DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
DRE->setHadMultipleCandidates(true);
@@ -1041,6 +1041,36 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
}
}
+ // C++ [temp.friend]p1:
+ // For a friend function declaration that is not a template declaration:
+ // -- if the name of the friend is a qualified or unqualified template-id,
+ // [...], otherwise
+ // -- if the name of the friend is a qualified-id and a matching
+ // non-template function is found in the specified class or namespace,
+ // the friend declaration refers to that function, otherwise,
+ // -- if the name of the friend is a qualified-id and a matching function
+ // template is found in the specified class or namespace, the friend
+ // declaration refers to the deduced specialization of that function
+ // template, otherwise
+ // -- the name shall be an unqualified-id [...]
+ // If we get here for a qualified friend declaration, we've just reached the
+ // third bullet. If the type of the friend is dependent, skip this lookup
+ // until instantiation.
+ if (New->getFriendObjectKind() && New->getQualifier() &&
+ !New->getDependentSpecializationInfo() &&
+ !New->getType()->isDependentType()) {
+ LookupResult TemplateSpecResult(LookupResult::Temporary, Old);
+ TemplateSpecResult.addAllDecls(Old);
+ if (CheckFunctionTemplateSpecialization(New, nullptr, TemplateSpecResult,
+ /*QualifiedFriend*/true)) {
+ New->setInvalidDecl();
+ return Ovl_Overload;
+ }
+
+ Match = TemplateSpecResult.getAsSingle<FunctionDecl>();
+ return Ovl_Match;
+ }
+
return Ovl_Overload;
}
@@ -1105,7 +1135,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
false, TPL_TemplateMatch) ||
- OldType->getReturnType() != NewType->getReturnType()))
+ !Context.hasSameType(Old->getDeclaredReturnType(),
+ New->getDeclaredReturnType())))
return true;
// If the function is a class member, its signature includes the
@@ -1141,8 +1172,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
// function yet (because we haven't yet resolved whether this is a static
// or non-static member function). Add it now, on the assumption that this
// is a redeclaration of OldMethod.
- unsigned OldQuals = OldMethod->getTypeQualifiers();
- unsigned NewQuals = NewMethod->getTypeQualifiers();
+ // FIXME: OpenCL: Need to consider address spaces
+ unsigned OldQuals = OldMethod->getTypeQualifiers().getCVRUQualifiers();
+ unsigned NewQuals = NewMethod->getTypeQualifiers().getCVRUQualifiers();
if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() &&
!isa<CXXConstructorDecl>(NewMethod))
NewQuals |= Qualifiers::Const;
@@ -1263,7 +1295,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
= S.Context.getCanonicalType(ToType).getUnqualifiedType();
if (Constructor->isCopyConstructor() &&
(FromCanon == ToCanon ||
- S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) {
+ S.IsDerivedFrom(From->getBeginLoc(), FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
@@ -1355,7 +1387,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
QualType FromType = From->getType();
if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() &&
(S.Context.hasSameUnqualifiedType(FromType, ToType) ||
- S.IsDerivedFrom(From->getLocStart(), FromType, ToType))) {
+ S.IsDerivedFrom(From->getBeginLoc(), FromType, ToType))) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(FromType);
@@ -1417,9 +1449,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
bool AllowObjCWritebackConversion
= getLangOpts().ObjCAutoRefCount &&
(Action == AA_Passing || Action == AA_Sending);
- if (getLangOpts().ObjC1)
- CheckObjCBridgeRelatedConversions(From->getLocStart(),
- ToType, From->getType(), From);
+ if (getLangOpts().ObjC)
+ CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType,
+ From->getType(), From);
ICS = ::TryImplicitConversion(*this, From, ToType,
/*SuppressUserConversions=*/false,
AllowExplicit,
@@ -2011,7 +2043,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// We have already pre-calculated the promotion type, so this is trivial.
if (ToType->isIntegerType() &&
- isCompleteType(From->getLocStart(), FromType))
+ isCompleteType(From->getBeginLoc(), FromType))
return Context.hasSameUnqualifiedType(
ToType, FromEnumType->getDecl()->getPromotionType());
@@ -2353,10 +2385,10 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
//
// Note that we do not check for ambiguity or inaccessibility
// here. That is handled by CheckPointerConversion.
- if (getLangOpts().CPlusPlus &&
- FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+ if (getLangOpts().CPlusPlus && FromPointeeType->isRecordType() &&
+ ToPointeeType->isRecordType() &&
!Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) &&
- IsDerivedFrom(From->getLocStart(), FromPointeeType, ToPointeeType)) {
+ IsDerivedFrom(From->getBeginLoc(), FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
@@ -2394,7 +2426,7 @@ static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
QualType& ConvertedType,
bool &IncompatibleObjC) {
- if (!getLangOpts().ObjC1)
+ if (!getLangOpts().ObjC)
return false;
// The set of qualifiers on the type we're converting from.
@@ -2822,10 +2854,9 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
return;
}
- unsigned FromQuals = FromFunction->getTypeQuals(),
- ToQuals = ToFunction->getTypeQuals();
- if (FromQuals != ToQuals) {
- PDiag << ft_qualifer_mismatch << ToQuals << FromQuals;
+ if (FromFunction->getTypeQuals() != ToFunction->getTypeQuals()) {
+ PDiag << ft_qualifer_mismatch << ToFunction->getTypeQuals()
+ << FromFunction->getTypeQuals();
return;
}
@@ -2983,7 +3014,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
QualType ToClass(ToTypePtr->getClass(), 0);
if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
- IsDerivedFrom(From->getLocStart(), ToClass, FromClass)) {
+ IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) {
ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
ToClass.getTypePtr());
return true;
@@ -3027,7 +3058,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
bool DerivationOkay =
- IsDerivedFrom(From->getLocStart(), ToClass, FromClass, Paths);
+ IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass, Paths);
assert(DerivationOkay &&
"Should not have been called if derivation isn't OK.");
(void)DerivationOkay;
@@ -3242,13 +3273,12 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
OverloadCandidateSet::iterator Best;
switch (auto Result =
- CandidateSet.BestViableFunction(S, From->getLocStart(),
- Best)) {
+ CandidateSet.BestViableFunction(S, From->getBeginLoc(), Best)) {
case OR_Deleted:
case OR_Success: {
// Record the standard conversion we used and the conversion function.
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
- QualType ThisType = Constructor->getThisType(S.Context);
+ QualType ThisType = Constructor->getThisType();
// Initializer lists don't have conversions as such.
User.Before.setAsIdentityConversion();
User.HadMultipleCandidates = HadMultipleCandidates;
@@ -3308,7 +3338,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// the parentheses of the initializer.
if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
(From->getType()->getAs<RecordType>() &&
- S.IsDerivedFrom(From->getLocStart(), From->getType(), ToType)))
+ S.IsDerivedFrom(From->getBeginLoc(), From->getType(), ToType)))
ConstructorsOnly = true;
if (!S.isCompleteType(From->getExprLoc(), ToType)) {
@@ -3376,10 +3406,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// Enumerate conversion functions, if we're allowed to.
if (ConstructorsOnly || isa<InitListExpr>(From)) {
- } else if (!S.isCompleteType(From->getLocStart(), From->getType())) {
+ } else if (!S.isCompleteType(From->getBeginLoc(), From->getType())) {
// No conversion functions from incomplete types.
- } else if (const RecordType *FromRecordType
- = From->getType()->getAs<RecordType>()) {
+ } else if (const RecordType *FromRecordType =
+ From->getType()->getAs<RecordType>()) {
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
// Add all of the conversion functions as candidates.
@@ -3416,8 +3446,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
- switch (auto Result = CandidateSet.BestViableFunction(S, From->getLocStart(),
- Best)) {
+ switch (auto Result =
+ CandidateSet.BestViableFunction(S, From->getBeginLoc(), Best)) {
case OR_Success:
case OR_Deleted:
// Record the standard conversion we used and the conversion function.
@@ -3429,7 +3459,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// sequence converts the source type to the type required by
// the argument of the constructor.
//
- QualType ThisType = Constructor->getThisType(S.Context);
+ QualType ThisType = Constructor->getThisType();
if (isa<InitListExpr>(From)) {
// Initializer lists don't have conversions as such.
User.Before.setAsIdentityConversion();
@@ -3496,13 +3526,13 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, false, false);
if (OvResult == OR_Ambiguous)
- Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition)
+ Diag(From->getBeginLoc(), diag::err_typecheck_ambiguous_condition)
<< From->getType() << ToType << From->getSourceRange();
else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) {
- if (!RequireCompleteType(From->getLocStart(), ToType,
+ if (!RequireCompleteType(From->getBeginLoc(), ToType,
diag::err_typecheck_nonviable_condition_incomplete,
From->getType(), From->getSourceRange()))
- Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition)
+ Diag(From->getBeginLoc(), diag::err_typecheck_nonviable_condition)
<< false << From->getType() << From->getSourceRange() << ToType;
} else
return false;
@@ -3516,7 +3546,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
static ImplicitConversionSequence::CompareKind
compareConversionFunctions(Sema &S, FunctionDecl *Function1,
FunctionDecl *Function2) {
- if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11)
+ if (!S.getLangOpts().ObjC || !S.getLangOpts().CPlusPlus11)
return ImplicitConversionSequence::Indistinguishable;
// Objective-C++:
@@ -3900,6 +3930,31 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
S.Context.getTypeSize(SCS1.getToType(2)))
return ImplicitConversionSequence::Better;
+ // Prefer a compatible vector conversion over a lax vector conversion
+ // For example:
+ //
+ // typedef float __v4sf __attribute__((__vector_size__(16)));
+ // void f(vector float);
+ // void f(vector signed int);
+ // int main() {
+ // __v4sf a;
+ // f(a);
+ // }
+ // Here, we'd like to choose f(vector float) and not
+ // report an ambiguous call error
+ if (SCS1.Second == ICK_Vector_Conversion &&
+ SCS2.Second == ICK_Vector_Conversion) {
+ bool SCS1IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes(
+ SCS1.getFromType(), SCS1.getToType(2));
+ bool SCS2IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes(
+ SCS2.getFromType(), SCS2.getToType(2));
+
+ if (SCS1IsCompatibleVectorConversion != SCS2IsCompatibleVectorConversion)
+ return SCS1IsCompatibleVectorConversion
+ ? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
+ }
+
return ImplicitConversionSequence::Indistinguishable;
}
@@ -4750,7 +4805,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
// We need a complete type for what follows. Incomplete types can never be
// initialized from init lists.
- if (!S.isCompleteType(From->getLocStart(), ToType))
+ if (!S.isCompleteType(From->getBeginLoc(), ToType))
return Result;
// Per DR1467:
@@ -4767,7 +4822,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
if (ToType->isRecordType()) {
QualType InitType = From->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
- S.IsDerivedFrom(From->getLocStart(), InitType, ToType))
+ S.IsDerivedFrom(From->getBeginLoc(), InitType, ToType))
return TryCopyInitialization(S, From->getInit(0), ToType,
SuppressUserConversions,
InOverloadResolution,
@@ -4823,10 +4878,9 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
break;
}
// Otherwise, look for the worst conversion.
- if (Result.isBad() ||
- CompareImplicitConversionSequences(S, From->getLocStart(), ICS,
- Result) ==
- ImplicitConversionSequence::Worse)
+ if (Result.isBad() || CompareImplicitConversionSequences(
+ S, From->getBeginLoc(), ICS, Result) ==
+ ImplicitConversionSequence::Worse)
Result = ICS;
}
@@ -4920,12 +4974,12 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
bool dummy1 = false;
bool dummy2 = false;
bool dummy3 = false;
- Sema::ReferenceCompareResult RefRelationship
- = S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1,
+ Sema::ReferenceCompareResult RefRelationship =
+ S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2, dummy1,
dummy2, dummy3);
if (RefRelationship >= Sema::Ref_Related) {
- return TryReferenceInit(S, Init, ToType, /*FIXME*/From->getLocStart(),
+ return TryReferenceInit(S, Init, ToType, /*FIXME*/ From->getBeginLoc(),
SuppressUserConversions,
/*AllowExplicit=*/false);
}
@@ -5006,9 +5060,8 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
if (ToType->isReferenceType())
return TryReferenceInit(S, From, ToType,
- /*FIXME:*/From->getLocStart(),
- SuppressUserConversions,
- AllowExplicit);
+ /*FIXME:*/ From->getBeginLoc(),
+ SuppressUserConversions, AllowExplicit);
return TryImplicitConversion(S, From, ToType,
SuppressUserConversions,
@@ -5042,9 +5095,15 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
// [class.dtor]p2: A destructor can be invoked for a const, volatile or
// const volatile object.
- unsigned Quals = isa<CXXDestructorDecl>(Method) ?
- Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
- QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals);
+ Qualifiers Quals;
+ if (isa<CXXDestructorDecl>(Method)) {
+ Quals.addConst();
+ Quals.addVolatile();
+ } else {
+ Quals = Method->getTypeQualifiers();
+ }
+
+ QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals);
// Set up the conversion sequence as a "bad" conversion, to allow us
// to exit early.
@@ -5110,7 +5169,7 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
break;
case RQ_LValue:
- if (!FromClassification.isLValue() && Quals != Qualifiers::Const) {
+ if (!FromClassification.isLValue() && !Quals.hasOnlyConst()) {
// non-const lvalue reference cannot bind to an rvalue
ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType,
ImplicitParamType);
@@ -5154,12 +5213,12 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
CXXMethodDecl *Method) {
QualType FromRecordType, DestType;
QualType ImplicitParamRecordType =
- Method->getThisType(Context)->getAs<PointerType>()->getPointeeType();
+ Method->getThisType()->getAs<PointerType>()->getPointeeType();
Expr::Classification FromClassification;
if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
FromRecordType = PT->getPointeeType();
- DestType = Method->getThisType(Context);
+ DestType = Method->getThisType();
FromClassification = Expr::Classification::makeSimpleLValue();
} else {
FromRecordType = From->getType();
@@ -5177,7 +5236,7 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
// Note that we always use the true parent context when performing
// the actual argument initialization.
ImplicitConversionSequence ICS = TryObjectArgumentInitialization(
- *this, From->getLocStart(), From->getType(), FromClassification, Method,
+ *this, From->getBeginLoc(), From->getType(), FromClassification, Method,
Method->getParent());
if (ICS.isBad()) {
switch (ICS.Bad.Kind) {
@@ -5186,10 +5245,9 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
Qualifiers ToQs = DestType.getQualifiers();
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
if (CVR) {
- Diag(From->getLocStart(),
- diag::err_member_function_call_bad_cvr)
- << Method->getDeclName() << FromRecordType << (CVR - 1)
- << From->getSourceRange();
+ Diag(From->getBeginLoc(), diag::err_member_function_call_bad_cvr)
+ << Method->getDeclName() << FromRecordType << (CVR - 1)
+ << From->getSourceRange();
Diag(Method->getLocation(), diag::note_previous_decl)
<< Method->getDeclName();
return ExprError();
@@ -5201,9 +5259,9 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
case BadConversionSequence::rvalue_ref_to_lvalue: {
bool IsRValueQualified =
Method->getRefQualifier() == RefQualifierKind::RQ_RValue;
- Diag(From->getLocStart(), diag::err_member_function_call_bad_ref)
- << Method->getDeclName() << FromClassification.isRValue()
- << IsRValueQualified;
+ Diag(From->getBeginLoc(), diag::err_member_function_call_bad_ref)
+ << Method->getDeclName() << FromClassification.isRValue()
+ << IsRValueQualified;
Diag(Method->getLocation(), diag::note_previous_decl)
<< Method->getDeclName();
return ExprError();
@@ -5214,9 +5272,9 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
break;
}
- return Diag(From->getLocStart(),
- diag::err_member_function_call_bad_type)
- << ImplicitParamRecordType << FromRecordType << From->getSourceRange();
+ return Diag(From->getBeginLoc(), diag::err_member_function_call_bad_type)
+ << ImplicitParamRecordType << FromRecordType
+ << From->getSourceRange();
}
if (ICS.Standard.Second == ICK_Derived_To_Base) {
@@ -5227,9 +5285,14 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
From = FromRes.get();
}
- if (!Context.hasSameType(From->getType(), DestType))
- From = ImpCastExprToType(From, DestType, CK_NoOp,
+ if (!Context.hasSameType(From->getType(), DestType)) {
+ if (From->getType().getAddressSpace() != DestType.getAddressSpace())
+ From = ImpCastExprToType(From, DestType, CK_AddressSpaceConversion,
From->getValueKind()).get();
+ else
+ From = ImpCastExprToType(From, DestType, CK_NoOp,
+ From->getValueKind()).get();
+ }
return From;
}
@@ -5257,9 +5320,8 @@ ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
- return Diag(From->getLocStart(),
- diag::err_typecheck_bool_condition)
- << From->getType() << From->getSourceRange();
+ return Diag(From->getBeginLoc(), diag::err_typecheck_bool_condition)
+ << From->getType() << From->getSourceRange();
return ExprError();
}
@@ -5372,9 +5434,9 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
case ImplicitConversionSequence::AmbiguousConversion:
case ImplicitConversionSequence::BadConversion:
if (!S.DiagnoseMultipleUserDefinedConversion(From, T))
- return S.Diag(From->getLocStart(),
+ return S.Diag(From->getBeginLoc(),
diag::err_typecheck_converted_constant_expression)
- << From->getType() << From->getSourceRange() << T;
+ << From->getType() << From->getSourceRange() << T;
return ExprError();
case ImplicitConversionSequence::EllipsisConversion:
@@ -5383,15 +5445,15 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
// Check that we would only use permitted conversions.
if (!CheckConvertedConstantConversions(S, *SCS)) {
- return S.Diag(From->getLocStart(),
+ return S.Diag(From->getBeginLoc(),
diag::err_typecheck_converted_constant_expression_disallowed)
- << From->getType() << From->getSourceRange() << T;
+ << From->getType() << From->getSourceRange() << T;
}
// [...] and where the reference binding (if any) binds directly.
if (SCS->ReferenceBinding && !SCS->DirectBinding) {
- return S.Diag(From->getLocStart(),
+ return S.Diag(From->getBeginLoc(),
diag::err_typecheck_converted_constant_expression_indirect)
- << From->getType() << From->getSourceRange() << T;
+ << From->getType() << From->getSourceRange() << T;
}
ExprResult Result =
@@ -5414,14 +5476,14 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
break;
case NK_Constant_Narrowing:
- S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
- << CCE << /*Constant*/1
- << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
+ S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
+ << CCE << /*Constant*/ 1
+ << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
break;
case NK_Type_Narrowing:
- S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
- << CCE << /*Constant*/0 << From->getType() << T;
+ S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
+ << CCE << /*Constant*/ 0 << From->getType() << T;
break;
}
@@ -5448,7 +5510,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
if (Notes.empty()) {
// It's a constant expression.
- return Result;
+ return ConstantExpr::Create(S.Context, Result.get());
}
}
@@ -5457,8 +5519,8 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
else {
- S.Diag(From->getLocStart(), diag::err_expr_not_cce)
- << CCE << From->getSourceRange();
+ S.Diag(From->getBeginLoc(), diag::err_expr_not_cce)
+ << CCE << From->getSourceRange();
for (unsigned I = 0; I < Notes.size(); ++I)
S.Diag(Notes[I].first, Notes[I].second);
}
@@ -5586,10 +5648,10 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
ConvTy.getAsStringInternal(TypeStr, SemaRef.getPrintingPolicy());
Converter.diagnoseExplicitConv(SemaRef, Loc, T, ConvTy)
- << FixItHint::CreateInsertion(From->getLocStart(),
+ << FixItHint::CreateInsertion(From->getBeginLoc(),
"static_cast<" + TypeStr + ">(")
<< FixItHint::CreateInsertion(
- SemaRef.getLocForEndOfToken(From->getLocEnd()), ")");
+ SemaRef.getLocForEndOfToken(From->getEndLoc()), ")");
Converter.noteExplicitConv(SemaRef, Conversion, ConvTy);
// If we aren't in a SFINAE context, build a call to the
@@ -5925,15 +5987,13 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context,
/// \param PartialOverloading true if we are performing "partial" overloading
/// based on an incomplete set of function arguments. This feature is used by
/// code completion.
-void
-Sema::AddOverloadCandidate(FunctionDecl *Function,
- DeclAccessPair FoundDecl,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- bool SuppressUserConversions,
- bool PartialOverloading,
- bool AllowExplicit,
- ConversionSequenceList EarlyConversions) {
+void Sema::AddOverloadCandidate(FunctionDecl *Function,
+ DeclAccessPair FoundDecl, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ bool SuppressUserConversions,
+ bool PartialOverloading, bool AllowExplicit,
+ ADLCallKind IsADLCandidate,
+ ConversionSequenceList EarlyConversions) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
@@ -5992,6 +6052,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.Function = Function;
Candidate.Viable = true;
Candidate.IsSurrogate = false;
+ Candidate.IsADLCandidate = IsADLCandidate;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
@@ -6009,7 +6070,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
- IsDerivedFrom(Args[0]->getLocStart(), Args[0]->getType(),
+ IsDerivedFrom(Args[0]->getBeginLoc(), Args[0]->getType(),
ClassType))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_illegal_constructor;
@@ -6215,24 +6276,6 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance,
return nullptr;
}
-// specific_attr_iterator iterates over enable_if attributes in reverse, and
-// enable_if is order-sensitive. As a result, we need to reverse things
-// sometimes. Size of 4 elements is arbitrary.
-static SmallVector<EnableIfAttr *, 4>
-getOrderedEnableIfAttrs(const FunctionDecl *Function) {
- SmallVector<EnableIfAttr *, 4> Result;
- if (!Function->hasAttrs())
- return Result;
-
- const auto &FuncAttrs = Function->getAttrs();
- for (Attr *Attr : FuncAttrs)
- if (auto *EnableIf = dyn_cast<EnableIfAttr>(Attr))
- Result.push_back(EnableIf);
-
- std::reverse(Result.begin(), Result.end());
- return Result;
-}
-
static bool
convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
ArrayRef<Expr *> Args, Sema::SFINAETrap &Trap,
@@ -6306,9 +6349,8 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis) {
- SmallVector<EnableIfAttr *, 4> EnableIfAttrs =
- getOrderedEnableIfAttrs(Function);
- if (EnableIfAttrs.empty())
+ auto EnableIfAttrs = Function->specific_attrs<EnableIfAttr>();
+ if (EnableIfAttrs.begin() == EnableIfAttrs.end())
return nullptr;
SFINAETrap Trap(*this);
@@ -6318,7 +6360,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
if (!convertArgsForAvailabilityChecks(
*this, Function, /*ThisArg=*/nullptr, Args, Trap,
/*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs))
- return EnableIfAttrs[0];
+ return *EnableIfAttrs.begin();
for (auto *EIA : EnableIfAttrs) {
APValue Result;
@@ -6427,7 +6469,12 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
if (Expr *E = Args[0]) {
// Use the explicit base to restrict the lookup:
ObjectType = E->getType();
- ObjectClassification = E->Classify(Context);
+ // Pointers in the object arguments are implicitly dereferenced, so we
+ // always classify them as l-values.
+ if (!ObjectType.isNull() && ObjectType->isPointerType())
+ ObjectClassification = Expr::Classification::makeSimpleLValue();
+ else
+ ObjectClassification = E->Classify(Context);
} // .. else there is an implicit base.
FunctionArgs = Args.slice(1);
}
@@ -6708,14 +6755,11 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
/// Add a C++ function template specialization as a candidate
/// in the candidate set, using template argument deduction to produce
/// an appropriate function template specialization.
-void
-Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
- DeclAccessPair FoundDecl,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions,
- bool PartialOverloading) {
+void Sema::AddTemplateOverloadCandidate(
+ FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
+ bool PartialOverloading, ADLCallKind IsADLCandidate) {
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
@@ -6744,6 +6788,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
Candidate.IsSurrogate = false;
+ Candidate.IsADLCandidate = IsADLCandidate;
// Ignore the object argument if there is one, since we don't have an object
// type.
Candidate.IgnoreObjectArgument =
@@ -6765,7 +6810,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
assert(Specialization && "Missing function template specialization?");
AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
SuppressUserConversions, PartialOverloading,
- /*AllowExplicit*/false, Conversions);
+ /*AllowExplicit*/ false, IsADLCandidate, Conversions);
}
/// Check that implicit conversion sequences can be formed for each argument
@@ -6966,15 +7011,15 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// lvalues/rvalues and the type. Fortunately, we can allocate this
// call on the stack and we don't need its arguments to be
// well-formed.
- DeclRefExpr ConversionRef(Conversion, false, Conversion->getType(),
- VK_LValue, From->getLocStart());
+ DeclRefExpr ConversionRef(Context, Conversion, false, Conversion->getType(),
+ VK_LValue, From->getBeginLoc());
ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
Context.getPointerType(Conversion->getType()),
CK_FunctionToPointerDecay,
&ConversionRef, VK_RValue);
QualType ConversionType = Conversion->getConversionType();
- if (!isCompleteType(From->getLocStart(), ConversionType)) {
+ if (!isCompleteType(From->getBeginLoc(), ConversionType)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
return;
@@ -6986,13 +7031,17 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// there are 0 arguments (i.e., nothing is allocated using ASTContext's
// allocator).
QualType CallResultType = ConversionType.getNonLValueExprType(Context);
- CallExpr Call(Context, &ConversionFn, None, CallResultType, VK,
- From->getLocStart());
+
+ llvm::AlignedCharArray<alignof(CallExpr), sizeof(CallExpr) + sizeof(Stmt *)>
+ Buffer;
+ CallExpr *TheTemporaryCall = CallExpr::CreateTemporary(
+ Buffer.buffer, &ConversionFn, CallResultType, VK, From->getBeginLoc());
+
ImplicitConversionSequence ICS =
- TryCopyInitialization(*this, &Call, ToType,
- /*SuppressUserConversions=*/true,
- /*InOverloadResolution=*/false,
- /*AllowObjCWritebackConversion=*/false);
+ TryCopyInitialization(*this, TheTemporaryCall, ToType,
+ /*SuppressUserConversions=*/true,
+ /*InOverloadResolution=*/false,
+ /*AllowObjCWritebackConversion=*/false);
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
@@ -8928,16 +8977,20 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
// set.
for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
+
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
if (ExplicitTemplateArgs)
continue;
- AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, false,
- PartialOverloading);
- } else
- AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
- FoundDecl, ExplicitTemplateArgs,
- Args, CandidateSet, PartialOverloading);
+ AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet,
+ /*SupressUserConversions=*/false, PartialOverloading,
+ /*AllowExplicit=*/false, ADLCallKind::UsesADL);
+ } else {
+ AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl,
+ ExplicitTemplateArgs, Args, CandidateSet,
+ /*SupressUserConversions=*/false,
+ PartialOverloading, ADLCallKind::UsesADL);
+ }
}
}
@@ -8967,31 +9020,31 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
return Cand1Attr ? Comparison::Better : Comparison::Worse;
}
- // FIXME: The next several lines are just
- // specific_attr_iterator<EnableIfAttr> but going in declaration order,
- // instead of reverse order which is how they're stored in the AST.
- auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1);
- auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2);
-
- // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1
- // has fewer enable_if attributes than Cand2.
- if (Cand1Attrs.size() < Cand2Attrs.size())
- return Comparison::Worse;
+ auto Cand1Attrs = Cand1->specific_attrs<EnableIfAttr>();
+ auto Cand2Attrs = Cand2->specific_attrs<EnableIfAttr>();
- auto Cand1I = Cand1Attrs.begin();
llvm::FoldingSetNodeID Cand1ID, Cand2ID;
- for (auto &Cand2A : Cand2Attrs) {
+ for (auto Pair : zip_longest(Cand1Attrs, Cand2Attrs)) {
+ Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair);
+ Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair);
+
+ // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1
+ // has fewer enable_if attributes than Cand2, and vice versa.
+ if (!Cand1A)
+ return Comparison::Worse;
+ if (!Cand2A)
+ return Comparison::Better;
+
Cand1ID.clear();
Cand2ID.clear();
- auto &Cand1A = *Cand1I++;
- Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true);
- Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true);
+ (*Cand1A)->getCond()->Profile(Cand1ID, S.getASTContext(), true);
+ (*Cand2A)->getCond()->Profile(Cand2ID, S.getASTContext(), true);
if (Cand1ID != Cand2ID)
return Comparison::Worse;
}
- return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better;
+ return Comparison::Equal;
}
static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
@@ -9000,6 +9053,11 @@ static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
!Cand2.Function->isMultiVersion())
return false;
+ // If Cand1 is invalid, it cannot be a better match, if Cand2 is invalid, this
+ // is obviously better.
+ if (Cand1.Function->isInvalidDecl()) return false;
+ if (Cand2.Function->isInvalidDecl()) return true;
+
// If this is a cpu_dispatch/cpu_specific multiversion situation, prefer
// cpu_dispatch, else arbitrarily based on the identifiers.
bool Cand1CPUDisp = Cand1.Function->hasAttr<CPUDispatchAttr>();
@@ -9506,7 +9564,7 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
if (!isFunctionAlwaysEnabled(S.Context, FD)) {
if (Complain) {
if (InOverloadResolution)
- S.Diag(FD->getLocStart(),
+ S.Diag(FD->getBeginLoc(),
diag::note_addrof_ovl_candidate_disabled_by_enable_if_attr);
else
S.Diag(Loc, diag::err_addrof_function_disabled_by_enable_if_attr) << FD;
@@ -10010,7 +10068,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
DeductionFailure.getFirstArg()->getNonTypeTemplateArgumentType();
QualType T2 =
DeductionFailure.getSecondArg()->getNonTypeTemplateArgumentType();
- if (!S.Context.hasSameType(T1, T2)) {
+ if (!T1.isNull() && !T2.isNull() && !S.Context.hasSameType(T1, T2)) {
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_inconsistent_deduction_types)
<< ParamD->getDeclName() << *DeductionFailure.getFirstArg() << T1
@@ -10268,7 +10326,8 @@ static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Callee = Cand->Function;
S.Diag(Callee->getLocation(),
- diag::note_ovl_candidate_disabled_by_extension);
+ diag::note_ovl_candidate_disabled_by_extension)
+ << S.getOpenCLExtensionsFromDeclExtMap(Callee);
}
/// Generates a 'note' diagnostic for an overload candidate. We've
@@ -10836,8 +10895,7 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
// in general, want to list every possible builtin candidate.
}
- llvm::sort(Cands.begin(), Cands.end(),
- CompareTemplateSpecCandidatesForDisplay(S));
+ llvm::sort(Cands, CompareTemplateSpecCandidatesForDisplay(S));
// FIXME: Perhaps rename OverloadsShown and getShowOverloads()
// for generalization purposes (?).
@@ -11023,7 +11081,7 @@ private:
// Note: We explicitly leave Matches unmodified if there isn't a clear best
// option, so we can potentially give the user a better error
- if (!std::all_of(Matches.begin(), Matches.end(), IsBestOrInferiorToBest))
+ if (!llvm::all_of(Matches, IsBestOrInferiorToBest))
return false;
Matches[0] = *Best;
Matches.resize(1);
@@ -11114,7 +11172,7 @@ private:
// If any candidate has a placeholder return type, trigger its deduction
// now.
- if (completeFunctionType(S, FunDecl, SourceExpr->getLocStart(),
+ if (completeFunctionType(S, FunDecl, SourceExpr->getBeginLoc(),
Complain)) {
HasComplained |= Complain;
return false;
@@ -11190,7 +11248,7 @@ private:
// here, since the no_viable diagnostic has index 0.
UnresolvedSetIterator Result = S.getMostSpecialized(
MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
- SourceExpr->getLocStart(), S.PDiag(),
+ SourceExpr->getBeginLoc(), S.PDiag(),
S.PDiag(diag::err_addr_ovl_ambiguous)
<< Matches[0].second->getDeclName(),
S.PDiag(diag::note_ovl_candidate)
@@ -11226,7 +11284,7 @@ private:
public:
void ComplainNoMatchesFound() const {
assert(Matches.empty());
- S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
+ S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_no_viable)
<< OvlExpr->getName() << TargetFunctionType
<< OvlExpr->getSourceRange();
if (FailedCandidates.empty())
@@ -11244,7 +11302,7 @@ public:
if (!functionHasPassObjectSizeParams(Fun))
S.NoteOverloadCandidate(*I, Fun, TargetFunctionType,
/*TakingAddress=*/true);
- FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
+ FailedCandidates.NoteCandidates(S, OvlExpr->getBeginLoc());
}
}
@@ -11266,21 +11324,20 @@ public:
}
void ComplainIsStaticMemberFunctionFromBoundPointer() const {
- S.Diag(OvlExpr->getLocStart(),
+ S.Diag(OvlExpr->getBeginLoc(),
diag::err_invalid_form_pointer_member_function)
- << OvlExpr->getSourceRange();
+ << OvlExpr->getSourceRange();
}
void ComplainOfInvalidConversion() const {
- S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
- << OvlExpr->getName() << TargetType;
+ S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_not_func_ptrref)
+ << OvlExpr->getName() << TargetType;
}
void ComplainMultipleMatchesFound() const {
assert(Matches.size() > 1);
- S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous)
- << OvlExpr->getName()
- << OvlExpr->getSourceRange();
+ S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_ambiguous)
+ << OvlExpr->getName() << OvlExpr->getSourceRange();
S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType,
/*TakingAddress=*/true);
}
@@ -11530,7 +11587,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
ExprResult SingleFunctionExpression;
if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
ovl.Expression, /*complain*/ false, &found)) {
- if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getLocStart())) {
+ if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getBeginLoc())) {
SrcExpr = ExprError();
return true;
}
@@ -11966,14 +12023,14 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
OverloadCandidateSet::iterator Best;
if (CandidateSet->empty() ||
- CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best) ==
+ CandidateSet->BestViableFunction(*this, Fn->getBeginLoc(), Best) ==
OR_No_Viable_Function) {
- // In Microsoft mode, if we are inside a template class member function then
- // create a type dependent CallExpr. The goal is to postpone name lookup
- // to instantiation time to be able to search into type dependent base
- // classes.
- CallExpr *CE = new (Context) CallExpr(
- Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc);
+ // In Microsoft mode, if we are inside a template class member function
+ // then create a type dependent CallExpr. The goal is to postpone name
+ // lookup to instantiation time to be able to search into type dependent
+ // base classes.
+ CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy,
+ VK_RValue, RParenLoc);
CE->setTypeDependent(true);
CE->setValueDependent(true);
CE->setInstantiationDependent(true);
@@ -12015,7 +12072,8 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
return ExprError();
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
- ExecConfig);
+ ExecConfig, /*IsExecConfig=*/false,
+ (*Best)->IsADLCandidate);
}
case OR_No_Viable_Function: {
@@ -12043,24 +12101,23 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
}
}
- SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call)
+ SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_no_viable_function_in_call)
<< ULE->getName() << Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
break;
}
case OR_Ambiguous:
- SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call)
- << ULE->getName() << Fn->getSourceRange();
+ SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_ambiguous_call)
+ << ULE->getName() << Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, Args);
break;
case OR_Deleted: {
- SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_deleted_call)
- << (*Best)->Function->isDeleted()
- << ULE->getName()
- << SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function)
- << Fn->getSourceRange();
+ SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_deleted_call)
+ << (*Best)->Function->isDeleted() << ULE->getName()
+ << SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function)
+ << Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
// We emitted an error for the unavailable/deleted function call but keep
@@ -12068,7 +12125,8 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
FunctionDecl *FDecl = (*Best)->Function;
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
- ExecConfig);
+ ExecConfig, /*IsExecConfig=*/false,
+ (*Best)->IsADLCandidate);
}
}
@@ -12116,7 +12174,7 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
- CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best);
+ CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best);
return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args,
RParenLoc, ExecConfig, &CandidateSet,
@@ -12178,14 +12236,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
VK_RValue, OK_Ordinary, OpLoc, false);
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
- UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, NamingClass,
- NestedNameSpecifierLoc(), OpNameInfo,
- /*ADL*/ true, IsOverloaded(Fns),
- Fns.begin(), Fns.end());
- return new (Context)
- CXXOperatorCallExpr(Context, Op, Fn, ArgsArray, Context.DependentTy,
- VK_RValue, OpLoc, FPOptions());
+ UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
+ Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo,
+ /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end());
+ return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray,
+ Context.DependentTy, VK_RValue, OpLoc,
+ FPOptions());
}
// Build an empty overload set.
@@ -12257,9 +12313,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
ResultTy = ResultTy.getNonLValueExprType(Context);
Args[0] = Input;
- CallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(), ArgsArray,
- ResultTy, VK, OpLoc, FPOptions());
+ CallExpr *TheCall = CXXOperatorCallExpr::Create(
+ Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc,
+ FPOptions(), Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
@@ -12369,14 +12425,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
// TODO: provide better source location info in DNLoc component.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
- UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, NamingClass,
- NestedNameSpecifierLoc(), OpNameInfo,
- /*ADL*/PerformADL, IsOverloaded(Fns),
- Fns.begin(), Fns.end());
- return new (Context)
- CXXOperatorCallExpr(Context, Op, Fn, Args, Context.DependentTy,
- VK_RValue, OpLoc, FPFeatures);
+ UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
+ Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo,
+ /*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end());
+ return CXXOperatorCallExpr::Create(Context, Op, Fn, Args,
+ Context.DependentTy, VK_RValue, OpLoc,
+ FPFeatures);
}
// Always do placeholder-like conversions on the RHS.
@@ -12489,10 +12543,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(),
- Args, ResultTy, VK, OpLoc,
- FPFeatures);
+ CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
+ Context, Op, FnExpr.get(), Args, ResultTy, VK, OpLoc, FPFeatures,
+ Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
FnDecl))
@@ -12638,9 +12691,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
UnresolvedSetIterator());
// Can't add any actual overloads yet
- return new (Context)
- CXXOperatorCallExpr(Context, OO_Subscript, Fn, Args,
- Context.DependentTy, VK_RValue, RLoc, FPOptions());
+ return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
+ Context.DependentTy, VK_RValue, RLoc,
+ FPOptions());
}
// Handle placeholders on both operands.
@@ -12714,10 +12767,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
- FnExpr.get(), Args,
- ResultTy, VK, RLoc,
- FPOptions());
+ CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(),
+ Args, ResultTy, VK, RLoc, FPOptions());
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
@@ -12819,7 +12870,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Check that the object type isn't more qualified than the
// member function we're calling.
- Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals());
+ Qualifiers funcQuals = proto->getTypeQuals();
QualType objectType = op->getLHS()->getType();
if (op->getOpcode() == BO_PtrMemI)
@@ -12837,11 +12888,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
- CXXMemberCallExpr *call
- = new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
- resultType, valueKind, RParenLoc);
+ CXXMemberCallExpr *call =
+ CXXMemberCallExpr::Create(Context, MemExprE, Args, resultType,
+ valueKind, RParenLoc, proto->getNumParams());
- if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getLocStart(),
+ if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(),
call, nullptr))
return ExprError();
@@ -12855,8 +12906,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
if (isa<CXXPseudoDestructorExpr>(NakedMemExpr))
- return new (Context)
- CallExpr(Context, MemExprE, Args, Context.VoidTy, VK_RValue, RParenLoc);
+ return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue,
+ RParenLoc);
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
@@ -12927,7 +12978,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
UnbridgedCasts.restore();
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(),
+ switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
@@ -12989,9 +13040,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
ResultType = ResultType.getNonLValueExprType(Context);
assert(Method && "Member call to something that isn't a method?");
+ const auto *Proto = Method->getType()->getAs<FunctionProtoType>();
CXXMemberCallExpr *TheCall =
- new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
- ResultType, VK, RParenLoc);
+ CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK,
+ RParenLoc, Proto->getNumParams());
// Check for a valid return type.
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
@@ -13011,8 +13063,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
// Convert the rest of the arguments
- const FunctionProtoType *Proto =
- Method->getType()->getAs<FunctionProtoType>();
if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args,
RParenLoc))
return ExprError();
@@ -13044,17 +13094,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts()) &&
MemExpr->performsVirtualDispatch(getLangOpts())) {
- Diag(MemExpr->getLocStart(),
+ Diag(MemExpr->getBeginLoc(),
diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
- << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
- << MD->getParent()->getDeclName();
+ << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
+ << MD->getParent()->getDeclName();
- Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName();
+ Diag(MD->getBeginLoc(), diag::note_previous_decl) << MD->getDeclName();
if (getLangOpts().AppleKext)
- Diag(MemExpr->getLocStart(),
- diag::note_pure_qualified_call_kext)
- << MD->getParent()->getDeclName()
- << MD->getDeclName();
+ Diag(MemExpr->getBeginLoc(), diag::note_pure_qualified_call_kext)
+ << MD->getParent()->getDeclName() << MD->getDeclName();
}
}
@@ -13062,7 +13110,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
dyn_cast<CXXDestructorDecl>(TheCall->getMethodDecl())) {
// a->A::f() doesn't go through the vtable, except in AppleKext mode.
bool CallCanBeVirtual = !MemExpr->hasQualifier() || getLangOpts().AppleKext;
- CheckVirtualDtorCall(DD, MemExpr->getLocStart(), /*IsDelete=*/false,
+ CheckVirtualDtorCall(DD, MemExpr->getBeginLoc(), /*IsDelete=*/false,
CallCanBeVirtual, /*WarnOnNonAbstractTypes=*/true,
MemExpr->getMemberLoc());
}
@@ -13167,7 +13215,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(),
+ switch (CandidateSet.BestViableFunction(*this, Object.get()->getBeginLoc(),
Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the appropriate call
@@ -13176,30 +13224,26 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
case OR_No_Viable_Function:
if (CandidateSet.empty())
- Diag(Object.get()->getLocStart(), diag::err_ovl_no_oper)
- << Object.get()->getType() << /*call*/ 1
- << Object.get()->getSourceRange();
+ Diag(Object.get()->getBeginLoc(), diag::err_ovl_no_oper)
+ << Object.get()->getType() << /*call*/ 1
+ << Object.get()->getSourceRange();
else
- Diag(Object.get()->getLocStart(),
- diag::err_ovl_no_viable_object_call)
- << Object.get()->getType() << Object.get()->getSourceRange();
+ Diag(Object.get()->getBeginLoc(), diag::err_ovl_no_viable_object_call)
+ << Object.get()->getType() << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
break;
case OR_Ambiguous:
- Diag(Object.get()->getLocStart(),
- diag::err_ovl_ambiguous_object_call)
- << Object.get()->getType() << Object.get()->getSourceRange();
+ Diag(Object.get()->getBeginLoc(), diag::err_ovl_ambiguous_object_call)
+ << Object.get()->getType() << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args);
break;
case OR_Deleted:
- Diag(Object.get()->getLocStart(),
- diag::err_ovl_deleted_object_call)
- << Best->Function->isDeleted()
- << Object.get()->getType()
- << getDeletedOrUnavailableSuffix(Best->Function)
- << Object.get()->getSourceRange();
+ Diag(Object.get()->getBeginLoc(), diag::err_ovl_deleted_object_call)
+ << Best->Function->isDeleted() << Object.get()->getType()
+ << getDeletedOrUnavailableSuffix(Best->Function)
+ << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
break;
}
@@ -13266,29 +13310,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (NewFn.isInvalid())
return true;
+ // The number of argument slots to allocate in the call. If we have default
+ // arguments we need to allocate space for them as well. We additionally
+ // need one more slot for the object parameter.
+ unsigned NumArgsSlots = 1 + std::max<unsigned>(Args.size(), NumParams);
+
// Build the full argument list for the method call (the implicit object
// parameter is placed at the beginning of the list).
- SmallVector<Expr *, 8> MethodArgs(Args.size() + 1);
- MethodArgs[0] = Object.get();
- std::copy(Args.begin(), Args.end(), MethodArgs.begin() + 1);
-
- // Once we've built TheCall, all of the expressions are properly
- // owned.
- QualType ResultTy = Method->getReturnType();
- ExprValueKind VK = Expr::getValueKindForType(ResultTy);
- ResultTy = ResultTy.getNonLValueExprType(Context);
-
- CXXOperatorCallExpr *TheCall = new (Context)
- CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy,
- VK, RParenLoc, FPOptions());
-
- if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
- return true;
-
- // We may have default arguments. If so, we need to allocate more
- // slots in the call for them.
- if (Args.size() < NumParams)
- TheCall->setNumArgs(Context, NumParams + 1);
+ SmallVector<Expr *, 8> MethodArgs(NumArgsSlots);
bool IsError = false;
@@ -13300,7 +13329,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
IsError = true;
else
Object = ObjRes;
- TheCall->setArg(0, Object.get());
+ MethodArgs[0] = Object.get();
// Check the argument types.
for (unsigned i = 0; i != NumParams; i++) {
@@ -13329,7 +13358,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
Arg = DefArg.getAs<Expr>();
}
- TheCall->setArg(i + 1, Arg);
+ MethodArgs[i + 1] = Arg;
}
// If this is a variadic call, handle args passed through "...".
@@ -13339,14 +13368,27 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
nullptr);
IsError |= Arg.isInvalid();
- TheCall->setArg(i + 1, Arg.get());
+ MethodArgs[i + 1] = Arg.get();
}
}
- if (IsError) return true;
+ if (IsError)
+ return true;
DiagnoseSentinelCalls(Method, LParenLoc, Args);
+ // Once we've built TheCall, all of the expressions are properly owned.
+ QualType ResultTy = Method->getReturnType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
+ CXXOperatorCallExpr *TheCall =
+ CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(), MethodArgs,
+ ResultTy, VK, RParenLoc, FPOptions());
+
+ if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
+ return true;
+
if (CheckFunctionCall(Method, TheCall, Proto))
return true;
@@ -13458,9 +13500,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.get(),
- Base, ResultTy, VK, OpLoc, FPOptions());
+ CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
+ Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, FPOptions());
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
@@ -13532,10 +13573,9 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- UserDefinedLiteral *UDL =
- new (Context) UserDefinedLiteral(Context, Fn.get(),
- llvm::makeArrayRef(ConvArgs, Args.size()),
- ResultTy, VK, LitEndLoc, UDSuffixLoc);
+ UserDefinedLiteral *UDL = UserDefinedLiteral::Create(
+ Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy,
+ VK, LitEndLoc, UDSuffixLoc);
if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
@@ -13596,7 +13636,7 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
}
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
- CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best);
+ CandidateSet->BestViableFunction(*this, Fn->getBeginLoc(), Best);
if (OverloadResult == OR_No_Viable_Function) {
*CallExpr = ExprError();
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index a8af75d87c8d..ebf1d10aa16a 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -977,7 +977,7 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
if (isWeakProperty() && !S.isUnevaluatedContext() &&
!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
- SyntacticForm->getLocStart()))
+ SyntacticForm->getBeginLoc()))
S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
SyntacticRefExpr->isMessagingGetter());
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 377e2c4dfa23..9e30c9a396c0 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -42,12 +42,11 @@
using namespace clang;
using namespace sema;
-StmtResult Sema::ActOnExprStmt(ExprResult FE) {
+StmtResult Sema::ActOnExprStmt(ExprResult FE, bool DiscardedValue) {
if (FE.isInvalid())
return StmtError();
- FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(),
- /*DiscardedValue*/ true);
+ FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), DiscardedValue);
if (FE.isInvalid())
return StmtError();
@@ -246,7 +245,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
// we might want to make a more specific diagnostic. Check for one of these
// cases now.
unsigned DiagID = diag::warn_unused_expr;
- if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E))
+ if (const FullExpr *Temps = dyn_cast<FullExpr>(E))
E = Temps->getSubExpr();
if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
E = TempExpr->getSubExpr();
@@ -259,17 +258,16 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (E->getType()->isVoidType())
return;
+ if (const Attr *A = CE->getUnusedResultAttr(Context)) {
+ Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
+ return;
+ }
+
// If the callee has attribute pure, const, or warn_unused_result, warn with
// a more specific message to make it clear what is happening. If the call
// is written in a macro body, only warn if it has the warn_unused_result
// attribute.
if (const Decl *FD = CE->getCalleeDecl()) {
- if (const Attr *A = isa<FunctionDecl>(FD)
- ? cast<FunctionDecl>(FD)->getUnusedResultAttr()
- : FD->getAttr<WarnUnusedResultAttr>()) {
- Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
- return;
- }
if (ShouldSuppress)
return;
if (FD->hasAttr<PureAttr>()) {
@@ -349,6 +347,10 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const {
return getCurFunction()->CompoundScopes.back();
}
+bool Sema::isCurCompoundStmtAStmtExpr() const {
+ return getCurCompoundScope().IsStmtExpr;
+}
+
StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr) {
const unsigned NumElts = Elts.size();
@@ -371,14 +373,6 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
Diag(D->getLocation(), diag::ext_mixed_decls_code);
}
}
- // Warn about unused expressions in statements.
- for (unsigned i = 0; i != NumElts; ++i) {
- // Ignore statements that are last in a statement expression.
- if (isStmtExpr && i == NumElts - 1)
- continue;
-
- DiagnoseUnusedExprResult(Elts[i]);
- }
// Check for suspicious empty body (null statement) in `for' and `while'
// statements. Don't do anything for template instantiations, this just adds
@@ -462,25 +456,20 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal,
return StmtError();
}
- CaseStmt *CS = new (Context)
- CaseStmt(LHSVal.get(), RHSVal.get(), CaseLoc, DotDotDotLoc, ColonLoc);
+ auto *CS = CaseStmt::Create(Context, LHSVal.get(), RHSVal.get(),
+ CaseLoc, DotDotDotLoc, ColonLoc);
getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS);
return CS;
}
/// ActOnCaseStmtBody - This installs a statement as the body of a case.
-void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) {
- DiagnoseUnusedExprResult(SubStmt);
-
- CaseStmt *CS = static_cast<CaseStmt*>(caseStmt);
- CS->setSubStmt(SubStmt);
+void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) {
+ cast<CaseStmt>(S)->setSubStmt(SubStmt);
}
StmtResult
Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
Stmt *SubStmt, Scope *CurScope) {
- DiagnoseUnusedExprResult(SubStmt);
-
if (getCurFunction()->SwitchStack.empty()) {
Diag(DefaultLoc, diag::err_default_not_in_switch);
return SubStmt;
@@ -551,12 +540,13 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
false);
Expr *CondExpr = Cond.get().second;
- if (!Diags.isIgnored(diag::warn_comma_operator,
- CondExpr->getExprLoc()))
+ // Only call the CommaVisitor when not C89 due to differences in scope flags.
+ if ((getLangOpts().C99 || getLangOpts().CPlusPlus) &&
+ !Diags.isIgnored(diag::warn_comma_operator, CondExpr->getExprLoc()))
CommaVisitor(*this).Visit(CondExpr);
if (!elseStmt)
- DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), thenStmt,
+ DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt,
diag::warn_empty_if_body);
return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc,
@@ -573,12 +563,8 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second))
setFunctionHasBranchProtectedScope();
- DiagnoseUnusedExprResult(thenStmt);
- DiagnoseUnusedExprResult(elseStmt);
-
- return new (Context)
- IfStmt(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first,
- Cond.get().second, thenStmt, ElseLoc, elseStmt);
+ return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first,
+ Cond.get().second, thenStmt, ElseLoc, elseStmt);
}
namespace {
@@ -631,8 +617,8 @@ static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
/// potentially integral-promoted expression @p expr.
static QualType GetTypeBeforeIntegralPromotion(const Expr *&E) {
- if (const auto *CleanUps = dyn_cast<ExprWithCleanups>(E))
- E = CleanUps->getSubExpr();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
while (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() != CK_IntegralCast) break;
E = ImpCast->getSubExpr();
@@ -727,8 +713,7 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
setFunctionHasBranchIntoScope();
- SwitchStmt *SS = new (Context)
- SwitchStmt(Context, InitStmt, Cond.get().first, CondExpr);
+ auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr);
getCurFunction()->SwitchStack.push_back(
FunctionScopeInfo::SwitchInfo(SS, false));
return SS;
@@ -918,8 +903,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// Check the unconverted value is within the range of possible values of
// the switch expression.
- checkCaseValue(*this, Lo->getLocStart(), LoVal,
- CondWidthBeforePromotion, CondIsSignedBeforePromotion);
+ checkCaseValue(*this, Lo->getBeginLoc(), LoVal, CondWidthBeforePromotion,
+ CondIsSignedBeforePromotion);
// FIXME: This duplicates the check performed for warn_not_in_enum below.
checkEnumTypesInSwitchStmt(*this, CondExprBeforePromotion,
@@ -946,8 +931,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
llvm::APSInt ConstantCondValue;
bool HasConstantCond = false;
if (!HasDependentValue && !TheDefaultStmt) {
- HasConstantCond = CondExpr->EvaluateAsInt(ConstantCondValue, Context,
+ Expr::EvalResult Result;
+ HasConstantCond = CondExpr->EvaluateAsInt(Result, Context,
Expr::SE_AllowSideEffects);
+ if (Result.Val.isInt())
+ ConstantCondValue = Result.Val.getInt();
assert(!HasConstantCond ||
(ConstantCondValue.getBitWidth() == CondWidth &&
ConstantCondValue.isSigned() == CondIsSigned));
@@ -979,17 +967,17 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
CaseVals[i-1].first.toString(CaseValStr);
if (PrevString == CurrString)
- Diag(CaseVals[i].second->getLHS()->getLocStart(),
- diag::err_duplicate_case) <<
- (PrevString.empty() ? StringRef(CaseValStr) : PrevString);
+ Diag(CaseVals[i].second->getLHS()->getBeginLoc(),
+ diag::err_duplicate_case)
+ << (PrevString.empty() ? StringRef(CaseValStr) : PrevString);
else
- Diag(CaseVals[i].second->getLHS()->getLocStart(),
- diag::err_duplicate_case_differing_expr) <<
- (PrevString.empty() ? StringRef(CaseValStr) : PrevString) <<
- (CurrString.empty() ? StringRef(CaseValStr) : CurrString) <<
- CaseValStr;
+ Diag(CaseVals[i].second->getLHS()->getBeginLoc(),
+ diag::err_duplicate_case_differing_expr)
+ << (PrevString.empty() ? StringRef(CaseValStr) : PrevString)
+ << (CurrString.empty() ? StringRef(CaseValStr) : CurrString)
+ << CaseValStr;
- Diag(CaseVals[i-1].second->getLHS()->getLocStart(),
+ Diag(CaseVals[i - 1].second->getLHS()->getBeginLoc(),
diag::note_duplicate_case_prev);
// FIXME: We really want to remove the bogus case stmt from the
// substmt, but we have no way to do this right now.
@@ -1018,7 +1006,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// Check the unconverted value is within the range of possible values of
// the switch expression.
- checkCaseValue(*this, Hi->getLocStart(), HiVal,
+ checkCaseValue(*this, Hi->getBeginLoc(), HiVal,
CondWidthBeforePromotion, CondIsSignedBeforePromotion);
// Convert the value to the same width/sign as the condition.
@@ -1026,9 +1014,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// If the low value is bigger than the high value, the case is empty.
if (LoVal > HiVal) {
- Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
- << SourceRange(CR->getLHS()->getLocStart(),
- Hi->getLocEnd());
+ Diag(CR->getLHS()->getBeginLoc(), diag::warn_case_empty_range)
+ << SourceRange(CR->getLHS()->getBeginLoc(), Hi->getEndLoc());
CaseRanges.erase(CaseRanges.begin()+i);
--i;
--e;
@@ -1082,9 +1069,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
if (OverlapStmt) {
// If we have a duplicate, report it.
- Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case)
- << OverlapVal.toString(10);
- Diag(OverlapStmt->getLHS()->getLocStart(),
+ Diag(CR->getLHS()->getBeginLoc(), diag::err_duplicate_case)
+ << OverlapVal.toString(10);
+ Diag(OverlapStmt->getLHS()->getBeginLoc(),
diag::note_duplicate_case_prev);
// FIXME: We really want to remove the bogus case stmt from the
// substmt, but we have no way to do this right now.
@@ -1165,7 +1152,21 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
SmallVector<DeclarationName,8> UnhandledNames;
- for (EI = EnumVals.begin(); EI != EIEnd; EI++){
+ for (EI = EnumVals.begin(); EI != EIEnd; EI++) {
+ // Don't warn about omitted unavailable EnumConstantDecls.
+ switch (EI->second->getAvailability()) {
+ case AR_Deprecated:
+ // Omitting a deprecated constant is ok; it should never materialize.
+ case AR_Unavailable:
+ continue;
+
+ case AR_NotYetIntroduced:
+ // Partially available enum constants should be present. Note that we
+ // suppress -Wunguarded-availability diagnostics for such uses.
+ case AR_Available:
+ break;
+ }
+
// Drop unneeded case values
while (CI != CaseVals.end() && CI->first < EI->first)
CI++;
@@ -1209,7 +1210,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
}
if (BodyStmt)
- DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt,
+ DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), BodyStmt,
diag::warn_empty_switch_body);
// FIXME: If the case list was broken is some way, we don't have a good system
@@ -1289,13 +1290,11 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
!Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc()))
CommaVisitor(*this).Visit(CondVal.second);
- DiagnoseUnusedExprResult(Body);
-
if (isa<NullStmt>(Body))
getCurCompoundScope().setHasEmptyLoopBodies();
- return new (Context)
- WhileStmt(Context, CondVal.first, CondVal.second, Body, WhileLoc);
+ return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body,
+ WhileLoc);
}
StmtResult
@@ -1310,12 +1309,15 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
return StmtError();
Cond = CondResult.get();
- CondResult = ActOnFinishFullExpr(Cond, DoLoc);
+ CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false);
if (CondResult.isInvalid())
return StmtError();
Cond = CondResult.get();
- DiagnoseUnusedExprResult(Body);
+ // Only call the CommaVisitor for C89 due to differences in scope flags.
+ if (Cond && !getLangOpts().C99 && !getLangOpts().CPlusPlus &&
+ !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc()))
+ CommaVisitor(*this).Visit(Cond);
return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen);
}
@@ -1396,7 +1398,11 @@ namespace {
void VisitDeclRefExpr(DeclRefExpr *E) {
VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
- if (!VD) return;
+ if (!VD) {
+ // Don't allow unhandled Decl types.
+ Simple = false;
+ return;
+ }
Ranges.push_back(E->getSourceRange());
@@ -1492,7 +1498,7 @@ namespace {
if (!Second) return;
if (S.Diags.isIgnored(diag::warn_variables_not_in_loop_body,
- Second->getLocStart()))
+ Second->getBeginLoc()))
return;
PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body);
@@ -1634,6 +1640,8 @@ namespace {
void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
// Only visit the initialization of a for loop; the body
// has a different break/continue scope.
+ if (const Stmt *Init = S->getInit())
+ Visit(Init);
if (const Stmt *Range = S->getRangeStmt())
Visit(Range);
if (const Stmt *Begin = S->getBeginStmt())
@@ -1668,7 +1676,7 @@ namespace {
if (!Body || !Third) return;
if (S.Diags.isIgnored(diag::warn_redundant_loop_iteration,
- Third->getLocStart()))
+ Third->getBeginLoc()))
return;
// Get the last statement from the loop body.
@@ -1755,11 +1763,6 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
CommaVisitor(*this).Visit(Second.get().second);
Expr *Third = third.release().getAs<Expr>();
-
- DiagnoseUnusedExprResult(First);
- DiagnoseUnusedExprResult(Third);
- DiagnoseUnusedExprResult(Body);
-
if (isa<NullStmt>(Body))
getCurCompoundScope().setHasEmptyLoopBodies();
@@ -1779,7 +1782,7 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
if (result.isInvalid()) return StmtError();
E = result.get();
- ExprResult FullExpr = ActOnFinishFullExpr(E);
+ ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false);
if (FullExpr.isInvalid())
return StmtError();
return StmtResult(static_cast<Stmt*>(FullExpr.get()));
@@ -1914,9 +1917,9 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
} else {
Expr *FirstE = cast<Expr>(First);
if (!FirstE->isTypeDependent() && !FirstE->isLValue())
- return StmtError(Diag(First->getLocStart(),
- diag::err_selector_element_not_lvalue)
- << First->getSourceRange());
+ return StmtError(
+ Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue)
+ << First->getSourceRange());
FirstType = static_cast<Expr*>(First)->getType();
if (FirstType.isConstQualified())
@@ -1933,7 +1936,8 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
if (CollectionExprResult.isInvalid())
return StmtError();
- CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get());
+ CollectionExprResult =
+ ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false);
if (CollectionExprResult.isInvalid())
return StmtError();
@@ -2052,21 +2056,26 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
/// The body of the loop is not available yet, since it cannot be analysed until
/// we have determined the type of the for-range-declaration.
StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
- SourceLocation CoawaitLoc, Stmt *First,
- SourceLocation ColonLoc, Expr *Range,
- SourceLocation RParenLoc,
+ SourceLocation CoawaitLoc, Stmt *InitStmt,
+ Stmt *First, SourceLocation ColonLoc,
+ Expr *Range, SourceLocation RParenLoc,
BuildForRangeKind Kind) {
if (!First)
return StmtError();
- if (Range && ObjCEnumerationCollection(Range))
+ if (Range && ObjCEnumerationCollection(Range)) {
+ // FIXME: Support init-statements in Objective-C++20 ranged for statement.
+ if (InitStmt)
+ return Diag(InitStmt->getBeginLoc(), diag::err_objc_for_range_init_stmt)
+ << InitStmt->getSourceRange();
return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc);
+ }
DeclStmt *DS = dyn_cast<DeclStmt>(First);
assert(DS && "first part of for range not a decl stmt");
if (!DS->isSingleDecl()) {
- Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range);
+ Diag(DS->getBeginLoc(), diag::err_type_defined_in_for_range);
return StmtError();
}
@@ -2087,7 +2096,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
// Build auto && __range = range-init
// Divide by 2, since the variables are in the inner scope (loop body).
const auto DepthStr = std::to_string(S->getDepth() / 2);
- SourceLocation RangeLoc = Range->getLocStart();
+ SourceLocation RangeLoc = Range->getBeginLoc();
VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
Context.getAutoRRefDeductType(),
std::string("__range") + DepthStr);
@@ -2106,10 +2115,10 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
return StmtError();
}
- return BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, RangeDecl.get(),
- /*BeginStmt=*/nullptr, /*EndStmt=*/nullptr,
- /*Cond=*/nullptr, /*Inc=*/nullptr,
- DS, RParenLoc, Kind);
+ return BuildCXXForRangeStmt(
+ ForLoc, CoawaitLoc, InitStmt, ColonLoc, RangeDecl.get(),
+ /*BeginStmt=*/nullptr, /*EndStmt=*/nullptr,
+ /*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind);
}
/// Create the initialization, compare, and increment steps for
@@ -2136,6 +2145,56 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange,
Sema::LookupMemberName);
LookupResult EndMemberLookup(SemaRef, EndNameInfo, Sema::LookupMemberName);
+ auto BuildBegin = [&] {
+ *BEF = BEF_begin;
+ Sema::ForRangeStatus RangeStatus =
+ SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo,
+ BeginMemberLookup, CandidateSet,
+ BeginRange, BeginExpr);
+
+ if (RangeStatus != Sema::FRS_Success) {
+ if (RangeStatus == Sema::FRS_DiagnosticIssued)
+ SemaRef.Diag(BeginRange->getBeginLoc(), diag::note_in_for_range)
+ << ColonLoc << BEF_begin << BeginRange->getType();
+ return RangeStatus;
+ }
+ if (!CoawaitLoc.isInvalid()) {
+ // FIXME: getCurScope() should not be used during template instantiation.
+ // We should pick up the set of unqualified lookup results for operator
+ // co_await during the initial parse.
+ *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc,
+ BeginExpr->get());
+ if (BeginExpr->isInvalid())
+ return Sema::FRS_DiagnosticIssued;
+ }
+ if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,
+ diag::err_for_range_iter_deduction_failure)) {
+ NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);
+ return Sema::FRS_DiagnosticIssued;
+ }
+ return Sema::FRS_Success;
+ };
+
+ auto BuildEnd = [&] {
+ *BEF = BEF_end;
+ Sema::ForRangeStatus RangeStatus =
+ SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo,
+ EndMemberLookup, CandidateSet,
+ EndRange, EndExpr);
+ if (RangeStatus != Sema::FRS_Success) {
+ if (RangeStatus == Sema::FRS_DiagnosticIssued)
+ SemaRef.Diag(EndRange->getBeginLoc(), diag::note_in_for_range)
+ << ColonLoc << BEF_end << EndRange->getType();
+ return RangeStatus;
+ }
+ if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc,
+ diag::err_for_range_iter_deduction_failure)) {
+ NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF);
+ return Sema::FRS_DiagnosticIssued;
+ }
+ return Sema::FRS_Success;
+ };
+
if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) {
// - if _RangeT is a class type, the unqualified-ids begin and end are
// looked up in the scope of class _RangeT as if by class member access
@@ -2143,68 +2202,62 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange,
// declaration, begin-expr and end-expr are __range.begin() and
// __range.end(), respectively;
SemaRef.LookupQualifiedName(BeginMemberLookup, D);
+ if (BeginMemberLookup.isAmbiguous())
+ return Sema::FRS_DiagnosticIssued;
+
SemaRef.LookupQualifiedName(EndMemberLookup, D);
+ if (EndMemberLookup.isAmbiguous())
+ return Sema::FRS_DiagnosticIssued;
if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {
- SourceLocation RangeLoc = BeginVar->getLocation();
- *BEF = BeginMemberLookup.empty() ? BEF_end : BEF_begin;
-
- SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch)
- << RangeLoc << BeginRange->getType() << *BEF;
- return Sema::FRS_DiagnosticIssued;
+ // Look up the non-member form of the member we didn't find, first.
+ // This way we prefer a "no viable 'end'" diagnostic over a "i found
+ // a 'begin' but ignored it because there was no member 'end'"
+ // diagnostic.
+ auto BuildNonmember = [&](
+ BeginEndFunction BEFFound, LookupResult &Found,
+ llvm::function_ref<Sema::ForRangeStatus()> BuildFound,
+ llvm::function_ref<Sema::ForRangeStatus()> BuildNotFound) {
+ LookupResult OldFound = std::move(Found);
+ Found.clear();
+
+ if (Sema::ForRangeStatus Result = BuildNotFound())
+ return Result;
+
+ switch (BuildFound()) {
+ case Sema::FRS_Success:
+ return Sema::FRS_Success;
+
+ case Sema::FRS_NoViableFunction:
+ SemaRef.Diag(BeginRange->getBeginLoc(), diag::err_for_range_invalid)
+ << BeginRange->getType() << BEFFound;
+ CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, BeginRange);
+ LLVM_FALLTHROUGH;
+
+ case Sema::FRS_DiagnosticIssued:
+ for (NamedDecl *D : OldFound) {
+ SemaRef.Diag(D->getLocation(),
+ diag::note_for_range_member_begin_end_ignored)
+ << BeginRange->getType() << BEFFound;
+ }
+ return Sema::FRS_DiagnosticIssued;
+ }
+ llvm_unreachable("unexpected ForRangeStatus");
+ };
+ if (BeginMemberLookup.empty())
+ return BuildNonmember(BEF_end, EndMemberLookup, BuildEnd, BuildBegin);
+ return BuildNonmember(BEF_begin, BeginMemberLookup, BuildBegin, BuildEnd);
}
} else {
// - otherwise, begin-expr and end-expr are begin(__range) and
// end(__range), respectively, where begin and end are looked up with
// argument-dependent lookup (3.4.2). For the purposes of this name
// lookup, namespace std is an associated namespace.
-
- }
-
- *BEF = BEF_begin;
- Sema::ForRangeStatus RangeStatus =
- SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo,
- BeginMemberLookup, CandidateSet,
- BeginRange, BeginExpr);
-
- if (RangeStatus != Sema::FRS_Success) {
- if (RangeStatus == Sema::FRS_DiagnosticIssued)
- SemaRef.Diag(BeginRange->getLocStart(), diag::note_in_for_range)
- << ColonLoc << BEF_begin << BeginRange->getType();
- return RangeStatus;
- }
- if (!CoawaitLoc.isInvalid()) {
- // FIXME: getCurScope() should not be used during template instantiation.
- // We should pick up the set of unqualified lookup results for operator
- // co_await during the initial parse.
- *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc,
- BeginExpr->get());
- if (BeginExpr->isInvalid())
- return Sema::FRS_DiagnosticIssued;
- }
- if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,
- diag::err_for_range_iter_deduction_failure)) {
- NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);
- return Sema::FRS_DiagnosticIssued;
}
- *BEF = BEF_end;
- RangeStatus =
- SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo,
- EndMemberLookup, CandidateSet,
- EndRange, EndExpr);
- if (RangeStatus != Sema::FRS_Success) {
- if (RangeStatus == Sema::FRS_DiagnosticIssued)
- SemaRef.Diag(EndRange->getLocStart(), diag::note_in_for_range)
- << ColonLoc << BEF_end << EndRange->getType();
- return RangeStatus;
- }
- if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc,
- diag::err_for_range_iter_deduction_failure)) {
- NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF);
- return Sema::FRS_DiagnosticIssued;
- }
- return Sema::FRS_Success;
+ if (Sema::ForRangeStatus Result = BuildBegin())
+ return Result;
+ return BuildEnd();
}
/// Speculatively attempt to dereference an invalid range expression.
@@ -2213,6 +2266,7 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange,
static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
SourceLocation ForLoc,
SourceLocation CoawaitLoc,
+ Stmt *InitStmt,
Stmt *LoopVarDecl,
SourceLocation ColonLoc,
Expr *Range,
@@ -2229,8 +2283,8 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
return StmtResult();
StmtResult SR = SemaRef.ActOnCXXForRangeStmt(
- S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, AdjustedRange.get(),
- RParenLoc, Sema::BFRK_Check);
+ S, ForLoc, CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc,
+ AdjustedRange.get(), RParenLoc, Sema::BFRK_Check);
if (SR.isInvalid())
return StmtResult();
}
@@ -2240,9 +2294,9 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
// case there are any other (non-fatal) problems with it.
SemaRef.Diag(RangeLoc, diag::err_for_range_dereference)
<< Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*");
- return SemaRef.ActOnCXXForRangeStmt(S, ForLoc, CoawaitLoc, LoopVarDecl,
- ColonLoc, AdjustedRange.get(), RParenLoc,
- Sema::BFRK_Rebuild);
+ return SemaRef.ActOnCXXForRangeStmt(
+ S, ForLoc, CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc,
+ AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild);
}
namespace {
@@ -2262,12 +2316,13 @@ struct InvalidateOnErrorScope {
}
/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement.
-StmtResult
-Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
- SourceLocation ColonLoc, Stmt *RangeDecl,
- Stmt *Begin, Stmt *End, Expr *Cond,
- Expr *Inc, Stmt *LoopVarDecl,
- SourceLocation RParenLoc, BuildForRangeKind Kind) {
+StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
+ SourceLocation CoawaitLoc, Stmt *InitStmt,
+ SourceLocation ColonLoc, Stmt *RangeDecl,
+ Stmt *Begin, Stmt *End, Expr *Cond,
+ Expr *Inc, Stmt *LoopVarDecl,
+ SourceLocation RParenLoc,
+ BuildForRangeKind Kind) {
// FIXME: This should not be used during template instantiation. We should
// pick up the set of unqualified lookup results for the != and + operators
// in the initial parse.
@@ -2451,8 +2506,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
QualType ArrayTy = PVD->getOriginalType();
QualType PointerTy = PVD->getType();
if (PointerTy->isPointerType() && ArrayTy->isArrayType()) {
- Diag(Range->getLocStart(), diag::err_range_on_array_parameter)
- << RangeLoc << PVD << ArrayTy << PointerTy;
+ Diag(Range->getBeginLoc(), diag::err_range_on_array_parameter)
+ << RangeLoc << PVD << ArrayTy << PointerTy;
Diag(PVD->getLocation(), diag::note_declared_at);
return StmtError();
}
@@ -2462,7 +2517,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// If building the range failed, try dereferencing the range expression
// unless a diagnostic was issued or the end function is problematic.
StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc,
- CoawaitLoc,
+ CoawaitLoc, InitStmt,
LoopVarDecl, ColonLoc,
Range, RangeLoc,
RParenLoc);
@@ -2473,7 +2528,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// Otherwise, emit diagnostics if we haven't already.
if (RangeStatus == FRS_NoViableFunction) {
Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get();
- Diag(Range->getLocStart(), diag::err_for_range_invalid)
+ Diag(Range->getBeginLoc(), diag::err_for_range_invalid)
<< RangeLoc << Range->getType() << BEFFailure;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Range);
}
@@ -2519,7 +2574,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
if (!NotEqExpr.isInvalid())
NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get());
if (!NotEqExpr.isInvalid())
- NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get());
+ NotEqExpr =
+ ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false);
if (NotEqExpr.isInvalid()) {
Diag(RangeLoc, diag::note_for_range_invalid_iterator)
<< RangeLoc << 0 << BeginRangeRef.get()->getType();
@@ -2542,7 +2598,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// co_await during the initial parse.
IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
if (!IncrExpr.isInvalid())
- IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
+ IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false);
if (IncrExpr.isInvalid()) {
Diag(RangeLoc, diag::note_for_range_invalid_iterator)
<< RangeLoc << 2 << BeginRangeRef.get()->getType() ;
@@ -2579,7 +2635,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
return StmtResult();
return new (Context) CXXForRangeStmt(
- RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()),
+ InitStmt, RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()),
cast_or_null<DeclStmt>(EndDeclStmt.get()), NotEqExpr.get(),
IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc,
ColonLoc, RParenLoc);
@@ -2660,7 +2716,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
NonReferenceType.removeLocalConst();
QualType NewReferenceType =
SemaRef.Context.getLValueReferenceType(E->getType().withConst());
- SemaRef.Diag(VD->getLocStart(), diag::note_use_type_or_non_reference)
+ SemaRef.Diag(VD->getBeginLoc(), diag::note_use_type_or_non_reference)
<< NonReferenceType << NewReferenceType << VD->getSourceRange();
} else {
// The range always returns a copy, so a temporary is always created.
@@ -2669,7 +2725,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
<< VD << RangeInitType;
QualType NonReferenceType = VariableType.getNonReferenceType();
NonReferenceType.removeLocalConst();
- SemaRef.Diag(VD->getLocStart(), diag::note_use_non_reference_type)
+ SemaRef.Diag(VD->getBeginLoc(), diag::note_use_non_reference_type)
<< NonReferenceType << VD->getSourceRange();
}
}
@@ -2705,7 +2761,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
// if doing so will prevent a copy.
SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy)
<< VD << VariableType << InitExpr->getType();
- SemaRef.Diag(VD->getLocStart(), diag::note_use_reference_type)
+ SemaRef.Diag(VD->getBeginLoc(), diag::note_use_reference_type)
<< SemaRef.Context.getLValueReferenceType(VariableType)
<< VD->getSourceRange();
}
@@ -2721,11 +2777,11 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
const CXXForRangeStmt *ForStmt) {
if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy,
- ForStmt->getLocStart()) &&
+ ForStmt->getBeginLoc()) &&
SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy,
- ForStmt->getLocStart()) &&
+ ForStmt->getBeginLoc()) &&
SemaRef.Diags.isIgnored(diag::warn_for_range_copy,
- ForStmt->getLocStart())) {
+ ForStmt->getBeginLoc())) {
return;
}
@@ -2797,7 +2853,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
return StmtError();
}
- ExprResult ExprRes = ActOnFinishFullExpr(E);
+ ExprResult ExprRes = ActOnFinishFullExpr(E, /*DiscardedValue*/ false);
if (ExprRes.isInvalid())
return StmtError();
E = ExprRes.get();
@@ -2951,7 +3007,7 @@ static void TryMoveInitialization(Sema& S,
Expr *InitExpr = &AsRvalue;
InitializationKind Kind = InitializationKind::CreateCopy(
- Value->getLocStart(), Value->getLocStart());
+ Value->getBeginLoc(), Value->getBeginLoc());
InitializationSequence Seq(S, Entity, Kind, InitExpr);
@@ -3147,12 +3203,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
ExpressionEvaluationContext::DiscardedStatement &&
(HasDeducedReturnType || CurCap->HasImplicitReturnType)) {
if (RetValExp) {
- ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ ExprResult ER =
+ ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid())
return StmtError();
RetValExp = ER.get();
}
- return new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr);
+ return ReturnStmt::Create(Context, ReturnLoc, RetValExp,
+ /* NRVOCandidate=*/nullptr);
}
if (HasDeducedReturnType) {
@@ -3273,13 +3331,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
if (RetValExp) {
- ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ ExprResult ER =
+ ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid())
return StmtError();
RetValExp = ER.get();
}
- ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp,
- NRVOCandidate);
+ auto *Result =
+ ReturnStmt::Create(Context, ReturnLoc, RetValExp, NRVOCandidate);
// If we need to check for the named return value optimization,
// or if we need to infer the return type,
@@ -3503,12 +3562,14 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
ExpressionEvaluationContext::DiscardedStatement &&
FnRetType->getContainedAutoType()) {
if (RetValExp) {
- ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ ExprResult ER =
+ ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid())
return StmtError();
RetValExp = ER.get();
}
- return new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr);
+ return ReturnStmt::Create(Context, ReturnLoc, RetValExp,
+ /* NRVOCandidate=*/nullptr);
}
// FIXME: Add a flag to the ScopeInfo to indicate whether we're performing
@@ -3596,14 +3657,16 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
if (RetValExp) {
- ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ ExprResult ER =
+ ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid())
return StmtError();
RetValExp = ER.get();
}
}
- Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr);
+ Result = ReturnStmt::Create(Context, ReturnLoc, RetValExp,
+ /* NRVOCandidate=*/nullptr);
} else if (!RetValExp && !HasDependentReturnType) {
FunctionDecl *FD = getCurFunctionDecl();
@@ -3625,7 +3688,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
else
Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
- Result = new (Context) ReturnStmt(ReturnLoc);
+ Result = ReturnStmt::Create(Context, ReturnLoc, /* RetExpr=*/nullptr,
+ /* NRVOCandidate=*/nullptr);
} else {
assert(RetValExp || HasDependentReturnType);
const VarDecl *NRVOCandidate = nullptr;
@@ -3673,12 +3737,13 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
if (RetValExp) {
- ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
+ ExprResult ER =
+ ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid())
return StmtError();
RetValExp = ER.get();
}
- Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
+ Result = ReturnStmt::Create(Context, ReturnLoc, RetValExp, NRVOCandidate);
}
// If we need to check for the named return value optimization, save the
@@ -3726,7 +3791,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
if (Result.isInvalid())
return StmtError();
- Result = ActOnFinishFullExpr(Result.get());
+ Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false);
if (Result.isInvalid())
return StmtError();
Throw = Result.get();
@@ -3798,7 +3863,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
}
// The operand to @synchronized is a full-expression.
- return ActOnFinishFullExpr(operand);
+ return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false);
}
StmtResult
@@ -3969,7 +4034,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
// declarations that are invalid, since we can't usefully report on them.
if (!H->getExceptionDecl()) {
if (i < NumHandlers - 1)
- return StmtError(Diag(H->getLocStart(), diag::err_early_catch_all));
+ return StmtError(Diag(H->getBeginLoc(), diag::err_early_catch_all));
continue;
} else if (H->getExceptionDecl()->isInvalidDecl())
continue;
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 0db15ea1f646..9e084c99d0dd 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -27,6 +27,58 @@
using namespace clang;
using namespace sema;
+/// Remove the upper-level LValueToRValue cast from an expression.
+static void removeLValueToRValueCast(Expr *E) {
+ Expr *Parent = E;
+ Expr *ExprUnderCast = nullptr;
+ SmallVector<Expr *, 8> ParentsToUpdate;
+
+ while (true) {
+ ParentsToUpdate.push_back(Parent);
+ if (auto *ParenE = dyn_cast<ParenExpr>(Parent)) {
+ Parent = ParenE->getSubExpr();
+ continue;
+ }
+
+ Expr *Child = nullptr;
+ CastExpr *ParentCast = dyn_cast<CastExpr>(Parent);
+ if (ParentCast)
+ Child = ParentCast->getSubExpr();
+ else
+ return;
+
+ if (auto *CastE = dyn_cast<CastExpr>(Child))
+ if (CastE->getCastKind() == CK_LValueToRValue) {
+ ExprUnderCast = CastE->getSubExpr();
+ // LValueToRValue cast inside GCCAsmStmt requires an explicit cast.
+ ParentCast->setSubExpr(ExprUnderCast);
+ break;
+ }
+ Parent = Child;
+ }
+
+ // Update parent expressions to have same ValueType as the underlying.
+ assert(ExprUnderCast &&
+ "Should be reachable only if LValueToRValue cast was found!");
+ auto ValueKind = ExprUnderCast->getValueKind();
+ for (Expr *E : ParentsToUpdate)
+ E->setValueKind(ValueKind);
+}
+
+/// Emit a warning about usage of "noop"-like casts for lvalues (GNU extension)
+/// and fix the argument with removing LValueToRValue cast from the expression.
+static void emitAndFixInvalidAsmCastLValue(const Expr *LVal, Expr *BadArgument,
+ Sema &S) {
+ if (!S.getLangOpts().HeinousExtensions) {
+ S.Diag(LVal->getBeginLoc(), diag::err_invalid_asm_cast_lvalue)
+ << BadArgument->getSourceRange();
+ } else {
+ S.Diag(LVal->getBeginLoc(), diag::warn_invalid_asm_cast_lvalue)
+ << BadArgument->getSourceRange();
+ }
+ removeLValueToRValueCast(BadArgument);
+}
+
/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
/// ignore "noop" casts in places where an lvalue is required by an inline asm.
/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
@@ -34,7 +86,7 @@ using namespace sema;
///
/// This method checks to see if the argument is an acceptable l-value and
/// returns false if it is a case we can handle.
-static bool CheckAsmLValue(const Expr *E, Sema &S) {
+static bool CheckAsmLValue(Expr *E, Sema &S) {
// Type dependent expressions will be checked during instantiation.
if (E->isTypeDependent())
return false;
@@ -46,12 +98,7 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) {
// are supposed to allow.
const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
if (E != E2 && E2->isLValue()) {
- if (!S.getLangOpts().HeinousExtensions)
- S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
- << E->getSourceRange();
- else
- S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
- << E->getSourceRange();
+ emitAndFixInvalidAsmCastLValue(E2, E, S);
// Accept, even if we emitted an error diagnostic.
return false;
}
@@ -90,13 +137,13 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) {
while (WorkList.size()) {
Expr *E = WorkList.pop_back_val();
if (isa<CXXThisExpr>(E)) {
- S.Diag(E->getLocStart(), diag::err_asm_naked_this_ref);
+ S.Diag(E->getBeginLoc(), diag::err_asm_naked_this_ref);
S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
return true;
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
if (isa<ParmVarDecl>(DRE->getDecl())) {
- S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
+ S.Diag(DRE->getBeginLoc(), diag::err_asm_naked_parm_ref);
S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
return true;
}
@@ -131,7 +178,7 @@ static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
EType = ExprGlobalRegVar;
if (EType != ExprSafeType) {
- S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
+ S.Diag(E->getBeginLoc(), diag::err_asm_non_addr_value_in_memory_constraint)
<< EType << is_input_expr << Info.getConstraintStr()
<< E->getSourceRange();
return true;
@@ -185,7 +232,7 @@ getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
Clobber = Target.getNormalizedGCCRegisterName(Clobber, true);
// Go over the output's registers we collected
if (InOutVars.count(Clobber))
- return Clobbers[i]->getLocStart();
+ return Clobbers[i]->getBeginLoc();
}
return SourceLocation();
}
@@ -226,9 +273,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
if (!Context.getTargetInfo().validateOutputConstraint(Info))
- return StmtError(Diag(Literal->getLocStart(),
- diag::err_asm_invalid_output_constraint)
- << Info.getConstraintStr());
+ return StmtError(
+ Diag(Literal->getBeginLoc(), diag::err_asm_invalid_output_constraint)
+ << Info.getConstraintStr());
ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
if (ER.isInvalid())
@@ -264,24 +311,18 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
break;
case Expr::MLV_LValueCast: {
const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
- if (!getLangOpts().HeinousExtensions) {
- Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
- << OutputExpr->getSourceRange();
- } else {
- Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
- << OutputExpr->getSourceRange();
- }
+ emitAndFixInvalidAsmCastLValue(LVal, OutputExpr, *this);
// Accept, even if we emitted an error diagnostic.
break;
}
case Expr::MLV_IncompleteType:
case Expr::MLV_IncompleteVoidType:
- if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
+ if (RequireCompleteType(OutputExpr->getBeginLoc(), Exprs[i]->getType(),
diag::err_dereference_incomplete_type))
return StmtError();
LLVM_FALLTHROUGH;
default:
- return StmtError(Diag(OutputExpr->getLocStart(),
+ return StmtError(Diag(OutputExpr->getBeginLoc(),
diag::err_asm_invalid_lvalue_in_output)
<< OutputExpr->getSourceRange());
}
@@ -289,9 +330,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
unsigned Size = Context.getTypeSize(OutputExpr->getType());
if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
Size))
- return StmtError(Diag(OutputExpr->getLocStart(),
- diag::err_asm_invalid_output_size)
- << Info.getConstraintStr());
+ return StmtError(
+ Diag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_output_size)
+ << Info.getConstraintStr());
}
SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
@@ -307,9 +348,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
Info)) {
- return StmtError(Diag(Literal->getLocStart(),
- diag::err_asm_invalid_input_constraint)
- << Info.getConstraintStr());
+ return StmtError(
+ Diag(Literal->getBeginLoc(), diag::err_asm_invalid_input_constraint)
+ << Info.getConstraintStr());
}
ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
@@ -331,22 +372,23 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// Only allow void types for memory constraints.
if (Info.allowsMemory() && !Info.allowsRegister()) {
if (CheckAsmLValue(InputExpr, *this))
- return StmtError(Diag(InputExpr->getLocStart(),
+ return StmtError(Diag(InputExpr->getBeginLoc(),
diag::err_asm_invalid_lvalue_in_input)
<< Info.getConstraintStr()
<< InputExpr->getSourceRange());
} else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
if (!InputExpr->isValueDependent()) {
- llvm::APSInt Result;
- if (!InputExpr->EvaluateAsInt(Result, Context))
- return StmtError(
- Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
- << Info.getConstraintStr() << InputExpr->getSourceRange());
- if (!Info.isValidAsmImmediate(Result))
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_invalid_asm_value_for_constraint)
- << Result.toString(10) << Info.getConstraintStr()
- << InputExpr->getSourceRange());
+ Expr::EvalResult EVResult;
+ if (!InputExpr->EvaluateAsRValue(EVResult, Context, true))
+ return StmtError(
+ Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
+ << Info.getConstraintStr() << InputExpr->getSourceRange());
+ llvm::APSInt Result = EVResult.Val.getInt();
+ if (!Info.isValidAsmImmediate(Result))
+ return StmtError(Diag(InputExpr->getBeginLoc(),
+ diag::err_invalid_asm_value_for_constraint)
+ << Result.toString(10) << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
}
} else {
@@ -359,10 +401,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (Info.allowsRegister()) {
if (InputExpr->getType()->isVoidType()) {
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_asm_invalid_type_in_input)
- << InputExpr->getType() << Info.getConstraintStr()
- << InputExpr->getSourceRange());
+ return StmtError(
+ Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_type_in_input)
+ << InputExpr->getType() << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
}
}
@@ -373,16 +415,16 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
continue;
if (!Ty->isVoidType() || !Info.allowsMemory())
- if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
+ if (RequireCompleteType(InputExpr->getBeginLoc(), Exprs[i]->getType(),
diag::err_dereference_incomplete_type))
return StmtError();
unsigned Size = Context.getTypeSize(Ty);
if (!Context.getTargetInfo().validateInputSize(Literal->getString(),
Size))
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_asm_invalid_input_size)
- << Info.getConstraintStr());
+ return StmtError(
+ Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_input_size)
+ << Info.getConstraintStr());
}
// Check that the clobbers are valid.
@@ -393,8 +435,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
StringRef Clobber = Literal->getString();
if (!Context.getTargetInfo().isValidClobber(Clobber))
- return StmtError(Diag(Literal->getLocStart(),
- diag::err_asm_unknown_register_name) << Clobber);
+ return StmtError(
+ Diag(Literal->getBeginLoc(), diag::err_asm_unknown_register_name)
+ << Clobber);
}
GCCAsmStmt *NS =
@@ -446,7 +489,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (!Context.getTargetInfo().validateConstraintModifier(
Literal->getString(), Piece.getModifier(), Size,
SuggestedModifier)) {
- Diag(Exprs[ConstraintIdx]->getLocStart(),
+ Diag(Exprs[ConstraintIdx]->getBeginLoc(),
diag::warn_asm_mismatched_size_modifier);
if (!SuggestedModifier.empty()) {
@@ -469,7 +512,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (NumAlternatives == ~0U)
NumAlternatives = AltCount;
else if (NumAlternatives != AltCount)
- return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(),
+ return StmtError(Diag(NS->getOutputExpr(i)->getBeginLoc(),
diag::err_asm_unexpected_constraint_alternatives)
<< NumAlternatives << AltCount);
}
@@ -482,7 +525,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (NumAlternatives == ~0U)
NumAlternatives = AltCount;
else if (NumAlternatives != AltCount)
- return StmtError(Diag(NS->getInputExpr(i)->getLocStart(),
+ return StmtError(Diag(NS->getInputExpr(i)->getBeginLoc(),
diag::err_asm_unexpected_constraint_alternatives)
<< NumAlternatives << AltCount);
@@ -499,10 +542,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// Make sure no more than one input constraint matches each output.
assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
if (InputMatchedToOutput[TiedTo] != ~0U) {
- Diag(NS->getInputExpr(i)->getLocStart(),
+ Diag(NS->getInputExpr(i)->getBeginLoc(),
diag::err_asm_input_duplicate_match)
<< TiedTo;
- Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(),
+ Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getBeginLoc(),
diag::note_asm_input_duplicate_first)
<< TiedTo;
return StmtError();
@@ -590,10 +633,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
continue;
}
- Diag(InputExpr->getLocStart(),
- diag::err_asm_tying_incompatible_types)
- << InTy << OutTy << OutputExpr->getSourceRange()
- << InputExpr->getSourceRange();
+ Diag(InputExpr->getBeginLoc(), diag::err_asm_tying_incompatible_types)
+ << InTy << OutTy << OutputExpr->getSourceRange()
+ << InputExpr->getSourceRange();
return StmtError();
}
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index e39a65c6ce0c..a8e54b36b29b 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -16,7 +16,6 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/LoopHint.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"
@@ -29,7 +28,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
A.getAttributeSpellingListIndex());
if (!isa<NullStmt>(St)) {
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
- << Attr.getSpelling() << St->getLocStart();
+ << Attr.getSpelling() << St->getBeginLoc();
if (isa<SwitchCase>(St)) {
SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
@@ -56,8 +55,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
if (A.getNumArgs() < 1) {
- S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments)
- << A.getName() << 1;
+ S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) << A << 1;
return nullptr;
}
@@ -87,6 +85,9 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll";
bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll";
+ bool PragmaUnrollAndJam = PragmaNameLoc->Ident->getName() == "unroll_and_jam";
+ bool PragmaNoUnrollAndJam =
+ PragmaNameLoc->Ident->getName() == "nounroll_and_jam";
if (St->getStmtClass() != Stmt::DoStmtClass &&
St->getStmtClass() != Stmt::ForStmtClass &&
St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
@@ -95,8 +96,10 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName())
.Case("unroll", "#pragma unroll")
.Case("nounroll", "#pragma nounroll")
+ .Case("unroll_and_jam", "#pragma unroll_and_jam")
+ .Case("nounroll_and_jam", "#pragma nounroll_and_jam")
.Default("#pragma clang loop");
- S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
+ S.Diag(St->getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
return nullptr;
}
@@ -118,6 +121,20 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
Option = LoopHintAttr::Unroll;
State = LoopHintAttr::Enable;
}
+ } else if (PragmaNoUnrollAndJam) {
+ // #pragma nounroll_and_jam
+ Option = LoopHintAttr::UnrollAndJam;
+ State = LoopHintAttr::Disable;
+ } else if (PragmaUnrollAndJam) {
+ if (ValueExpr) {
+ // #pragma unroll_and_jam N
+ Option = LoopHintAttr::UnrollAndJamCount;
+ State = LoopHintAttr::Numeric;
+ } else {
+ // #pragma unroll_and_jam
+ Option = LoopHintAttr::UnrollAndJam;
+ State = LoopHintAttr::Enable;
+ }
} else {
// #pragma clang loop ...
assert(OptionLoc && OptionLoc->Ident &&
@@ -130,19 +147,24 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
.Case("interleave_count", LoopHintAttr::InterleaveCount)
.Case("unroll", LoopHintAttr::Unroll)
.Case("unroll_count", LoopHintAttr::UnrollCount)
+ .Case("pipeline", LoopHintAttr::PipelineDisabled)
+ .Case("pipeline_initiation_interval",
+ LoopHintAttr::PipelineInitiationInterval)
.Case("distribute", LoopHintAttr::Distribute)
.Default(LoopHintAttr::Vectorize);
if (Option == LoopHintAttr::VectorizeWidth ||
Option == LoopHintAttr::InterleaveCount ||
- Option == LoopHintAttr::UnrollCount) {
+ Option == LoopHintAttr::UnrollCount ||
+ Option == LoopHintAttr::PipelineInitiationInterval) {
assert(ValueExpr && "Attribute must have a valid value expression.");
- if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
+ if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc()))
return nullptr;
State = LoopHintAttr::Numeric;
} else if (Option == LoopHintAttr::Vectorize ||
Option == LoopHintAttr::Interleave ||
Option == LoopHintAttr::Unroll ||
- Option == LoopHintAttr::Distribute) {
+ Option == LoopHintAttr::Distribute ||
+ Option == LoopHintAttr::PipelineDisabled) {
assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
if (StateLoc->Ident->isStr("disable"))
State = LoopHintAttr::Disable;
@@ -165,21 +187,20 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
static void
CheckForIncompatibleAttributes(Sema &S,
const SmallVectorImpl<const Attr *> &Attrs) {
- // There are 4 categories of loop hints attributes: vectorize, interleave,
- // unroll and distribute. Except for distribute they come in two variants: a
- // state form and a numeric form. The state form selectively
- // defaults/enables/disables the transformation for the loop (for unroll,
- // default indicates full unrolling rather than enabling the transformation).
- // The numeric form form provides an integer hint (for example, unroll count)
- // to the transformer. The following array accumulates the hints encountered
- // while iterating through the attributes to check for compatibility.
+ // There are 6 categories of loop hints attributes: vectorize, interleave,
+ // unroll, unroll_and_jam, pipeline and distribute. Except for distribute they
+ // come in two variants: a state form and a numeric form. The state form
+ // selectively defaults/enables/disables the transformation for the loop
+ // (for unroll, default indicates full unrolling rather than enabling the
+ // transformation). The numeric form form provides an integer hint (for
+ // example, unroll count) to the transformer. The following array accumulates
+ // the hints encountered while iterating through the attributes to check for
+ // compatibility.
struct {
const LoopHintAttr *StateAttr;
const LoopHintAttr *NumericAttr;
- } HintAttrs[] = {{nullptr, nullptr},
- {nullptr, nullptr},
- {nullptr, nullptr},
- {nullptr, nullptr}};
+ } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr},
+ {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
for (const auto *I : Attrs) {
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
@@ -189,7 +210,14 @@ CheckForIncompatibleAttributes(Sema &S,
continue;
LoopHintAttr::OptionType Option = LH->getOption();
- enum { Vectorize, Interleave, Unroll, Distribute } Category;
+ enum {
+ Vectorize,
+ Interleave,
+ Unroll,
+ UnrollAndJam,
+ Distribute,
+ Pipeline
+ } Category;
switch (Option) {
case LoopHintAttr::Vectorize:
case LoopHintAttr::VectorizeWidth:
@@ -203,16 +231,27 @@ CheckForIncompatibleAttributes(Sema &S,
case LoopHintAttr::UnrollCount:
Category = Unroll;
break;
+ case LoopHintAttr::UnrollAndJam:
+ case LoopHintAttr::UnrollAndJamCount:
+ Category = UnrollAndJam;
+ break;
case LoopHintAttr::Distribute:
// Perform the check for duplicated 'distribute' hints.
Category = Distribute;
break;
+ case LoopHintAttr::PipelineDisabled:
+ case LoopHintAttr::PipelineInitiationInterval:
+ Category = Pipeline;
+ break;
};
+ assert(Category < sizeof(HintAttrs) / sizeof(HintAttrs[0]));
auto &CategoryState = HintAttrs[Category];
const LoopHintAttr *PrevAttr;
if (Option == LoopHintAttr::Vectorize ||
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
+ Option == LoopHintAttr::UnrollAndJam ||
+ Option == LoopHintAttr::PipelineDisabled ||
Option == LoopHintAttr::Distribute) {
// Enable|Disable|AssumeSafety hint. For example, vectorize(enable).
PrevAttr = CategoryState.StateAttr;
@@ -232,7 +271,7 @@ CheckForIncompatibleAttributes(Sema &S,
<< LH->getDiagnosticName(Policy);
if (CategoryState.StateAttr && CategoryState.NumericAttr &&
- (Category == Unroll ||
+ (Category == Unroll || Category == UnrollAndJam ||
CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
// Disable hints are not compatible with numeric hints of the same
// category. As a special case, numeric unroll hints are also not
@@ -257,8 +296,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
unsigned NumArgs = A.getNumArgs();
if (NumArgs > 1) {
- S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A.getName()
- << 1;
+ S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A << 1;
return nullptr;
}
@@ -270,7 +308,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
if (!E->isIntegerConstantExpr(ArgVal, S.Context)) {
S.Diag(A.getLoc(), diag::err_attribute_argument_type)
- << A.getName() << AANT_ArgumentIntegerConstant << E->getSourceRange();
+ << A << AANT_ArgumentIntegerConstant << E->getSourceRange();
return nullptr;
}
@@ -279,7 +317,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
if (Val <= 0) {
S.Diag(A.getRange().getBegin(),
diag::err_attribute_requires_positive_integer)
- << A.getName();
+ << A << /* positive */ 0;
return nullptr;
}
UnrollFactor = Val;
@@ -292,9 +330,10 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
switch (A.getKind()) {
case ParsedAttr::UnknownAttribute:
- S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
- diag::warn_unhandled_ms_attribute_ignored :
- diag::warn_unknown_attribute_ignored) << A.getName();
+ S.Diag(A.getLoc(), A.isDeclspecAttribute()
+ ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
+ : (unsigned)diag::warn_unknown_attribute_ignored)
+ << A.getName();
return nullptr;
case ParsedAttr::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
@@ -308,7 +347,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
- << A.getName() << St->getLocStart();
+ << A.getName() << St->getBeginLoc();
return nullptr;
}
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index fa002de3f5f1..3f9dc989103f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -194,7 +194,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
QualType ObjectType = ObjectTypePtr.get();
- LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName);
+ LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName);
if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
MemberOfUnknownSpecialization))
return TNK_Non_template;
@@ -539,9 +539,8 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
// If this is a dependent-scope lookup, diagnose that the 'template' keyword
// was missing.
if (MissingTemplateKeyword) {
- Diag(NameInfo.getLocStart(), diag::err_template_kw_missing)
- << "" << NameInfo.getName().getAsString()
- << SourceRange(Less, Greater);
+ Diag(NameInfo.getBeginLoc(), diag::err_template_kw_missing)
+ << "" << NameInfo.getName().getAsString() << SourceRange(Less, Greater);
return;
}
@@ -628,7 +627,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum &&
isa<CXXMethodDecl>(DC) && cast<CXXMethodDecl>(DC)->isInstance()) {
- QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context);
+ QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType();
// Since the 'this' expression is synthesized, we don't need to
// perform the double-lookup check.
@@ -892,7 +891,7 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {
// convertTypeTemplateArgumentToTemplate.
return ParsedTemplateArgument(ParsedTemplateArgument::Type,
ParsedType.get().getAsOpaquePtr(),
- TInfo->getTypeLoc().getLocStart());
+ TInfo->getTypeLoc().getBeginLoc());
}
/// ActOnTypeParameter - Called when a C++ template type parameter
@@ -974,7 +973,7 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
SourceLocation Loc) {
if (TSI->getType()->isUndeducedType()) {
- // C++1z [temp.dep.expr]p3:
+ // C++17 [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains
// - an identifier associated by name lookup with a non-type
// template-parameter declared with a type that contains a
@@ -1113,12 +1112,10 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
IdentifierInfo *ParamName = D.getIdentifier();
bool IsParameterPack = D.hasEllipsis();
- NonTypeTemplateParmDecl *Param
- = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
- D.getLocStart(),
- D.getIdentifierLoc(),
- Depth, Position, ParamName, T,
- IsParameterPack, TInfo);
+ NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(
+ Context, Context.getTranslationUnitDecl(), D.getBeginLoc(),
+ D.getIdentifierLoc(), Depth, Position, ParamName, T, IsParameterPack,
+ TInfo);
Param->setAccess(AS_public);
if (Invalid)
@@ -1258,9 +1255,10 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
RAngleLoc, RequiresClause);
}
-static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
+static void SetNestedNameSpecifier(Sema &S, TagDecl *T,
+ const CXXScopeSpec &SS) {
if (SS.isSet())
- T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext()));
+ T->setQualifierInfo(SS.getWithLocInContext(S.Context));
}
DeclResult Sema::CheckClassTemplate(
@@ -1459,10 +1457,11 @@ DeclResult Sema::CheckClassTemplate(
}();
if (RedeclACMismatch) {
- Diag(CurAC ? CurAC->getLocStart() : NameLoc,
+ Diag(CurAC ? CurAC->getBeginLoc() : NameLoc,
diag::err_template_different_associated_constraints);
- Diag(PrevAC ? PrevAC->getLocStart() : PrevClassTemplate->getLocation(),
- diag::note_template_prev_declaration) << /*declaration*/0;
+ Diag(PrevAC ? PrevAC->getBeginLoc() : PrevClassTemplate->getLocation(),
+ diag::note_template_prev_declaration)
+ << /*declaration*/ 0;
return true;
}
@@ -1489,19 +1488,19 @@ DeclResult Sema::CheckClassTemplate(
NamedDecl *Hidden = nullptr;
if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
SkipBody->ShouldSkip = true;
+ SkipBody->Previous = Def;
auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
assert(Tmpl && "original definition of a class template is not a "
"class template?");
makeMergedDefinitionVisible(Hidden);
makeMergedDefinitionVisible(Tmpl);
- return Def;
+ } else {
+ Diag(NameLoc, diag::err_redefinition) << Name;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ // FIXME: Would it make sense to try to "forget" the previous
+ // definition, as part of error recovery?
+ return true;
}
-
- Diag(NameLoc, diag::err_redefinition) << Name;
- Diag(Def->getLocation(), diag::note_previous_definition);
- // FIXME: Would it make sense to try to "forget" the previous
- // definition, as part of error recovery?
- return true;
}
}
} else if (PrevDecl) {
@@ -1522,13 +1521,14 @@ DeclResult Sema::CheckClassTemplate(
if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
CheckTemplateParameterList(
TemplateParams,
- PrevClassTemplate ? PrevClassTemplate->getTemplateParameters()
- : nullptr,
+ PrevClassTemplate
+ ? PrevClassTemplate->getMostRecentDecl()->getTemplateParameters()
+ : nullptr,
(SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
SemanticContext->isDependentContext())
? TPC_ClassTemplateMember
- : TUK == TUK_Friend ? TPC_FriendClassTemplate
- : TPC_ClassTemplate))
+ : TUK == TUK_Friend ? TPC_FriendClassTemplate : TPC_ClassTemplate,
+ SkipBody))
Invalid = true;
if (SS.isSet()) {
@@ -1555,7 +1555,7 @@ DeclResult Sema::CheckClassTemplate(
PrevClassTemplate && ShouldAddRedecl ?
PrevClassTemplate->getTemplatedDecl() : nullptr,
/*DelayTypeCreation=*/true);
- SetNestedNameSpecifier(NewClass, SS);
+ SetNestedNameSpecifier(*this, NewClass, SS);
if (NumOuterTemplateParamLists > 0)
NewClass->setTemplateParameterListsInfo(
Context, llvm::makeArrayRef(OuterTemplateParamLists,
@@ -1563,7 +1563,7 @@ DeclResult Sema::CheckClassTemplate(
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
- if (TUK == TUK_Definition) {
+ if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
AddAlignmentAttributesForRecord(NewClass);
AddMsStructLayoutForRecord(NewClass);
}
@@ -1606,7 +1606,7 @@ DeclResult Sema::CheckClassTemplate(
NewClass->setLexicalDeclContext(CurContext);
NewTemplate->setLexicalDeclContext(CurContext);
- if (TUK == TUK_Definition)
+ if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip))
NewClass->startDefinition();
ProcessDeclAttributeList(S, NewClass, Attr);
@@ -1655,6 +1655,9 @@ DeclResult Sema::CheckClassTemplate(
ActOnDocumentableDecl(NewTemplate);
+ if (SkipBody && SkipBody->ShouldSkip)
+ return SkipBody->Previous;
+
return NewTemplate;
}
@@ -1763,8 +1766,8 @@ struct ConvertConstructorToDeductionGuideTransform {
TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
return buildDeductionGuide(TemplateParams, CD->isExplicit(), NewTInfo,
- CD->getLocStart(), CD->getLocation(),
- CD->getLocEnd());
+ CD->getBeginLoc(), CD->getLocation(),
+ CD->getEndLoc());
}
/// Build a deduction guide with the specified parameter types.
@@ -1806,8 +1809,8 @@ private:
// TemplateTypeParmDecl's index cannot be changed after creation, so
// substitute it directly.
auto *NewTTP = TemplateTypeParmDecl::Create(
- SemaRef.Context, DC, TTP->getLocStart(), TTP->getLocation(),
- /*Depth*/0, Depth1IndexAdjustment + TTP->getIndex(),
+ SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(),
+ /*Depth*/ 0, Depth1IndexAdjustment + TTP->getIndex(),
TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
TTP->isParameterPack());
if (TTP->hasDefaultArgument()) {
@@ -1876,7 +1879,7 @@ private:
EPI.HasTrailingReturn = true;
QualType Result = SemaRef.BuildFunctionType(
- ReturnType, ParamTypes, TL.getLocStart(), DeductionGuideName, EPI);
+ ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI);
if (Result.isNull())
return QualType();
@@ -2152,10 +2155,17 @@ static bool DiagnoseUnexpandedParameterPacks(Sema &S,
/// \param TPC Describes the context in which we are checking the given
/// template parameter list.
///
+/// \param SkipBody If we might have already made a prior merged definition
+/// of this template visible, the corresponding body-skipping information.
+/// Default argument redefinition is not an error when skipping such a body,
+/// because (under the ODR) we can assume the default arguments are the same
+/// as the prior merged definition.
+///
/// \returns true if an error occurred, false otherwise.
bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
TemplateParameterList *OldParams,
- TemplateParamListContext TPC) {
+ TemplateParamListContext TPC,
+ SkipBodyInfo *SkipBody) {
bool Invalid = false;
// C++ [temp.param]p10:
@@ -2205,7 +2215,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
"Parameter packs can't have a default argument!");
SawParameterPack = true;
} else if (OldTypeParm && hasVisibleDefaultArgument(OldTypeParm) &&
- NewTypeParm->hasDefaultArgument()) {
+ NewTypeParm->hasDefaultArgument() &&
+ (!SkipBody || !SkipBody->ShouldSkip)) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
SawDefaultArgument = true;
@@ -2249,7 +2260,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
if (!NewNonTypeParm->isPackExpansion())
SawParameterPack = true;
} else if (OldNonTypeParm && hasVisibleDefaultArgument(OldNonTypeParm) &&
- NewNonTypeParm->hasDefaultArgument()) {
+ NewNonTypeParm->hasDefaultArgument() &&
+ (!SkipBody || !SkipBody->ShouldSkip)) {
OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
SawDefaultArgument = true;
@@ -2292,7 +2304,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
SawParameterPack = true;
} else if (OldTemplateParm &&
hasVisibleDefaultArgument(OldTemplateParm) &&
- NewTemplateParm->hasDefaultArgument()) {
+ NewTemplateParm->hasDefaultArgument() &&
+ (!SkipBody || !SkipBody->ShouldSkip)) {
OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
SawDefaultArgument = true;
@@ -3040,8 +3053,42 @@ static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
return Cond;
}
+namespace {
+
+// A PrinterHelper that prints more helpful diagnostics for some sub-expressions
+// within failing boolean expression, such as substituting template parameters
+// for actual types.
+class FailedBooleanConditionPrinterHelper : public PrinterHelper {
+public:
+ explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &P)
+ : Policy(P) {}
+
+ bool handledStmt(Stmt *E, raw_ostream &OS) override {
+ const auto *DR = dyn_cast<DeclRefExpr>(E);
+ if (DR && DR->getQualifier()) {
+ // If this is a qualified name, expand the template arguments in nested
+ // qualifiers.
+ DR->getQualifier()->print(OS, Policy, true);
+ // Then print the decl itself.
+ const ValueDecl *VD = DR->getDecl();
+ OS << VD->getName();
+ if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
+ // This is a template variable, print the expanded template arguments.
+ printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy);
+ }
+ return true;
+ }
+ return false;
+ }
+
+private:
+ const PrintingPolicy Policy;
+};
+
+} // end anonymous namespace
+
std::pair<Expr *, std::string>
-Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
+Sema::findFailedBooleanCondition(Expr *Cond) {
Cond = lookThroughRangesV3Condition(PP, Cond);
// Separate out all of the terms in a conjunction.
@@ -3070,18 +3117,16 @@ Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
break;
}
}
-
- if (!FailedCond) {
- if (!AllowTopLevelCond)
- return { nullptr, "" };
-
+ if (!FailedCond)
FailedCond = Cond->IgnoreParenImpCasts();
- }
std::string Description;
{
llvm::raw_string_ostream Out(Description);
- FailedCond->printPretty(Out, nullptr, getPrintingPolicy());
+ PrintingPolicy Policy = getPrintingPolicy();
+ Policy.PrintCanonicalTypes = true;
+ FailedBooleanConditionPrinterHelper Helper(Policy);
+ FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr);
}
return { FailedCond, Description };
}
@@ -3165,9 +3210,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedBooleanCondition(
- TemplateArgs[0].getSourceExpression(),
- /*AllowTopLevelCond=*/true);
+ findFailedBooleanCondition(TemplateArgs[0].getSourceExpression());
// Remove the old SFINAE diagnostic.
PartialDiagnosticAt OldDiag =
@@ -3247,13 +3290,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// This is the first time we have referenced this class template
// specialization. Create the canonical declaration and add it to
// the set of specializations.
- Decl = ClassTemplateSpecializationDecl::Create(Context,
- ClassTemplate->getTemplatedDecl()->getTagKind(),
- ClassTemplate->getDeclContext(),
- ClassTemplate->getTemplatedDecl()->getLocStart(),
- ClassTemplate->getLocation(),
- ClassTemplate,
- Converted, nullptr);
+ Decl = ClassTemplateSpecializationDecl::Create(
+ Context, ClassTemplate->getTemplatedDecl()->getTagKind(),
+ ClassTemplate->getDeclContext(),
+ ClassTemplate->getTemplatedDecl()->getBeginLoc(),
+ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr);
ClassTemplate->AddSpecialization(Decl, InsertPos);
if (ClassTemplate->isOutOfLine())
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@@ -4218,12 +4259,12 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
// a "not a template" case. FIXME: Refactor isTemplateName so we don't
// need to do this.
DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name);
- LookupResult R(*this, DNI.getName(), Name.getLocStart(),
+ LookupResult R(*this, DNI.getName(), Name.getBeginLoc(),
LookupOrdinaryName);
bool MOUS;
if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext,
MOUS, TemplateKWLoc))
- Diag(Name.getLocStart(), diag::err_no_member)
+ Diag(Name.getBeginLoc(), diag::err_no_member)
<< DNI.getName() << LookupCtx << SS.getRange();
return TNK_Non_template;
} else {
@@ -4241,10 +4282,11 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
// We don't get here if naming the constructor would be valid, so we
// just reject immediately and recover by treating the
// injected-class-name as naming the template.
- Diag(Name.getLocStart(),
+ Diag(Name.getBeginLoc(),
diag::ext_out_of_line_qualified_id_type_names_constructor)
- << Name.Identifier << 0 /*injected-class-name used as template name*/
- << 1 /*'template' keyword was used*/;
+ << Name.Identifier
+ << 0 /*injected-class-name used as template name*/
+ << 1 /*'template' keyword was used*/;
}
return TNK;
}
@@ -4270,11 +4312,9 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
break;
}
- Diag(Name.getLocStart(),
- diag::err_template_kw_refers_to_non_template)
- << GetNameFromUnqualifiedId(Name).getName()
- << Name.getSourceRange()
- << TemplateKWLoc;
+ Diag(Name.getBeginLoc(), diag::err_template_kw_refers_to_non_template)
+ << GetNameFromUnqualifiedId(Name).getName() << Name.getSourceRange()
+ << TemplateKWLoc;
return TNK_Non_template;
}
@@ -4425,7 +4465,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
// If the argument type is dependent, instantiate it now based
// on the previously-computed template arguments.
- if (ArgType->getType()->isDependentType()) {
+ if (ArgType->getType()->isInstantiationDependentType()) {
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
Param, Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
@@ -5629,8 +5669,8 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {
std::string Code = "static_cast<" + ParamType.getAsString() + ">(";
S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant)
- << ParamType << FixItHint::CreateInsertion(Arg->getLocStart(), Code)
- << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getLocEnd()),
+ << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code)
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()),
")");
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_NullPointer;
@@ -5670,9 +5710,9 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter(
unsigned ArgQuals = ArgType.getCVRQualifiers();
if ((ParamQuals | ArgQuals) != ParamQuals) {
- S.Diag(Arg->getLocStart(),
+ S.Diag(Arg->getBeginLoc(),
diag::err_template_arg_ref_bind_ignores_quals)
- << ParamType << Arg->getType() << Arg->getSourceRange();
+ << ParamType << Arg->getType() << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
@@ -5686,11 +5726,11 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter(
ParamType.getNonReferenceType())) {
// We can't perform this conversion or binding.
if (ParamType->isReferenceType())
- S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind)
- << ParamType << ArgIn->getType() << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_no_ref_bind)
+ << ParamType << ArgIn->getType() << Arg->getSourceRange();
else
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
- << ArgIn->getType() << ParamType << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible)
+ << ArgIn->getType() << ParamType << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
@@ -5736,8 +5776,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
if (FirstOpLoc.isValid()) {
if (ExtWarnMSTemplateArg)
- S.Diag(ArgIn->getLocStart(), diag::ext_ms_deref_template_argument)
- << ArgIn->getSourceRange();
+ S.Diag(ArgIn->getBeginLoc(), diag::ext_ms_deref_template_argument)
+ << ArgIn->getSourceRange();
if (FirstOpKind == UO_AddrOf)
AddressTaken = true;
@@ -5745,8 +5785,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// We cannot let pointers get dereferenced here, that is obviously not a
// constant expression.
assert(FirstOpKind == UO_Deref);
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
- << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
}
}
} else {
@@ -5770,7 +5810,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
bool ExtraParens = false;
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
if (!Invalid && !ExtraParens) {
- S.Diag(Arg->getLocStart(),
+ S.Diag(Arg->getBeginLoc(),
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_template_arg_extra_parens
: diag::ext_template_arg_extra_parens)
@@ -5836,16 +5876,16 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
if (!DRE) {
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
- << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
// Cannot refer to non-static data members
if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) {
- S.Diag(Arg->getLocStart(), diag::err_template_arg_field)
- << Entity << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field)
+ << Entity << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
@@ -5853,8 +5893,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// Cannot refer to non-static member functions
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) {
if (!Method->isStatic()) {
- S.Diag(Arg->getLocStart(), diag::err_template_arg_method)
- << Method << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method)
+ << Method << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
@@ -5866,23 +5906,24 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// A non-type template argument must refer to an object or function.
if (!Func && !Var) {
// We found something, but we don't know specifically what it is.
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_object_or_func)
- << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_object_or_func)
+ << Arg->getSourceRange();
S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
return true;
}
// Address / reference template args must have external linkage in C++98.
if (Entity->getFormalLinkage() == InternalLinkage) {
- S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_template_arg_object_internal :
- diag::ext_template_arg_object_internal)
- << !Func << Entity << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(),
+ S.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_template_arg_object_internal
+ : diag::ext_template_arg_object_internal)
+ << !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
<< !Func;
} else if (!Entity->hasLinkage()) {
- S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)
- << !Func << Entity << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_object_no_linkage)
+ << !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
<< !Func;
return true;
@@ -5914,17 +5955,16 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
} else {
// A value of reference type is not an object.
if (Var->getType()->isReferenceType()) {
- S.Diag(Arg->getLocStart(),
- diag::err_template_arg_reference_var)
- << Var->getType() << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var)
+ << Var->getType() << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
// A template argument must have static storage duration.
if (Var->getTLSKind()) {
- S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local)
- << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_thread_local)
+ << Arg->getSourceRange();
S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);
return true;
}
@@ -5961,15 +6001,14 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// taking the address of the entity.
ArgType = S.Context.getPointerType(Var->getType());
if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) {
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of)
- << ParamType;
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
+ << ParamType;
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of)
- << ParamType
- << FixItHint::CreateInsertion(Arg->getLocStart(), "&");
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
+ << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&");
S.Diag(Param->getLocation(), diag::note_template_param_here);
}
@@ -5983,7 +6022,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// Create the template argument.
Converted =
TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType);
- S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false);
+ S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false);
return false;
}
@@ -6012,11 +6051,11 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
bool ExtraParens = false;
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
if (!Invalid && !ExtraParens) {
- S.Diag(Arg->getLocStart(),
- S.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_template_arg_extra_parens :
- diag::ext_template_arg_extra_parens)
- << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(),
+ S.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_template_arg_extra_parens
+ : diag::ext_template_arg_extra_parens)
+ << Arg->getSourceRange();
ExtraParens = true;
}
@@ -6078,16 +6117,16 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
} else if (!S.Context.hasSameUnqualifiedType(
ResultArg->getType(), ParamType.getNonReferenceType())) {
// We can't perform this conversion.
- S.Diag(ResultArg->getLocStart(), diag::err_template_arg_not_convertible)
+ S.Diag(ResultArg->getBeginLoc(), diag::err_template_arg_not_convertible)
<< ResultArg->getType() << ParamType << ResultArg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
if (!DRE)
- return S.Diag(Arg->getLocStart(),
+ return S.Diag(Arg->getBeginLoc(),
diag::err_template_arg_not_pointer_to_member_form)
- << Arg->getSourceRange();
+ << Arg->getSourceRange();
if (isa<FieldDecl>(DRE->getDecl()) ||
isa<IndirectFieldDecl>(DRE->getDecl()) ||
@@ -6109,9 +6148,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
}
// We found something else, but we don't know specifically what it is.
- S.Diag(Arg->getLocStart(),
- diag::err_template_arg_not_pointer_to_member_form)
- << Arg->getSourceRange();
+ S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_pointer_to_member_form)
+ << Arg->getSourceRange();
S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
return true;
}
@@ -6127,7 +6165,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType ParamType, Expr *Arg,
TemplateArgument &Converted,
CheckTemplateArgumentKind CTAK) {
- SourceLocation StartLoc = Arg->getLocStart();
+ SourceLocation StartLoc = Arg->getBeginLoc();
// If the parameter type somehow involves auto, deduce the type now.
if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) {
@@ -6248,7 +6286,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// FIXME: We need TemplateArgument representation and mangling for these.
if (!Value.getMemberPointerPath().empty()) {
- Diag(Arg->getLocStart(),
+ Diag(Arg->getBeginLoc(),
diag::err_template_arg_member_ptr_base_derived_not_supported)
<< Value.getMemberPointerDecl() << ParamType
<< Arg->getSourceRange();
@@ -6274,8 +6312,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Converted = TemplateArgument(ArgResult.get());
break;
}
- Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
- << Arg->getSourceRange();
+ Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
return ExprError();
}
auto *VD = const_cast<ValueDecl *>(
@@ -6384,9 +6422,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- the name of a non-type template-parameter; or
llvm::APSInt Value;
if (!ArgType->isIntegralOrEnumerationType()) {
- Diag(Arg->getLocStart(),
- diag::err_template_arg_not_integral_or_enumeral)
- << ArgType << Arg->getSourceRange();
+ Diag(Arg->getBeginLoc(), diag::err_template_arg_not_integral_or_enumeral)
+ << ArgType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
} else if (!Arg->isValueDependent()) {
@@ -6424,9 +6461,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).get();
} else {
// We can't perform this conversion.
- Diag(Arg->getLocStart(),
- diag::err_template_arg_not_convertible)
- << Arg->getType() << ParamType << Arg->getSourceRange();
+ Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible)
+ << Arg->getType() << ParamType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
}
@@ -6465,9 +6501,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Complain if an unsigned parameter received a negative value.
if (IntegerType->isUnsignedIntegerOrEnumerationType()
&& (OldValue.isSigned() && OldValue.isNegative())) {
- Diag(Arg->getLocStart(), diag::warn_template_arg_negative)
- << OldValue.toString(10) << Value.toString(10) << Param->getType()
- << Arg->getSourceRange();
+ Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative)
+ << OldValue.toString(10) << Value.toString(10) << Param->getType()
+ << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
@@ -6480,10 +6516,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
else
RequiredBits = OldValue.getMinSignedBits();
if (RequiredBits > AllowedBits) {
- Diag(Arg->getLocStart(),
- diag::warn_template_arg_too_large)
- << OldValue.toString(10) << Value.toString(10) << Param->getType()
- << Arg->getSourceRange();
+ Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large)
+ << OldValue.toString(10) << Value.toString(10) << Param->getType()
+ << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
}
@@ -6526,7 +6561,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
true,
FoundResult)) {
- if (DiagnoseUseOfDecl(Fn, Arg->getLocStart()))
+ if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
@@ -6579,7 +6614,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ParamRefType->getPointeeType(),
true,
FoundResult)) {
- if (DiagnoseUseOfDecl(Fn, Arg->getLocStart()))
+ if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
@@ -7357,9 +7392,9 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
ParamUseRange = findTemplateParameter(
Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc());
if (ParamUseRange.isValid()) {
- S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getLocStart(),
+ S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(),
diag::err_dependent_typed_non_type_arg_in_partial_spec)
- << Param->getType();
+ << Param->getType();
S.Diag(Param->getLocation(), diag::note_template_param_here)
<< (IsDefaultArgument ? ParamUseRange : SourceRange())
<< ParamUseRange;
@@ -7616,7 +7651,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
TemplateArgs,
CanonType,
PrevPartial);
- SetNestedNameSpecifier(Partial, SS);
+ SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
Partial->setTemplateParameterListsInfo(
Context, TemplateParameterLists.drop_back(1));
@@ -7642,7 +7677,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplate,
Converted,
PrevDecl);
- SetNestedNameSpecifier(Specialization, SS);
+ SetNestedNameSpecifier(*this, Specialization, SS);
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
TemplateParameterLists);
@@ -7699,9 +7734,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
NamedDecl *Hidden = nullptr;
if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
SkipBody->ShouldSkip = true;
+ SkipBody->Previous = Def;
makeMergedDefinitionVisible(Hidden);
- // From here on out, treat this as just a redeclaration.
- TUK = TUK_Declaration;
} else if (Def) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_redefinition) << Specialization << Range;
@@ -7715,7 +7749,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
- if (TUK == TUK_Definition) {
+ if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
AddAlignmentAttributesForRecord(Specialization);
AddMsStructLayoutForRecord(Specialization);
}
@@ -7751,7 +7785,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
Specialization->setLexicalDeclContext(CurContext);
// We may be starting the definition of this specialization.
- if (TUK == TUK_Definition)
+ if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip))
Specialization->startDefinition();
if (TUK == TUK_Friend) {
@@ -7767,6 +7801,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// context. However, specializations are not found by name lookup.
CurContext->addDecl(Specialization);
}
+
+ if (SkipBody && SkipBody->ShouldSkip)
+ return SkipBody->Previous;
+
return Specialization;
}
@@ -7928,6 +7966,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
HasNoEffect = true;
return false;
}
+ llvm_unreachable("Unexpected TemplateSpecializationKind!");
case TSK_ExplicitInstantiationDefinition:
switch (PrevTSK) {
@@ -8065,9 +8104,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
///
/// \param Previous the set of declarations that may be specialized by
/// this function specialization.
+///
+/// \param QualifiedFriend whether this is a lookup for a qualified friend
+/// declaration with no explicit template argument list that might be
+/// befriending a function template specialization.
bool Sema::CheckFunctionTemplateSpecialization(
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
- LookupResult &Previous) {
+ LookupResult &Previous, bool QualifiedFriend) {
// The set of function template specializations that could match this
// explicit function template specialization.
UnresolvedSet<8> Candidates;
@@ -8100,7 +8143,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
if (OldMD && OldMD->isConst()) {
const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- EPI.TypeQuals |= Qualifiers::Const;
+ EPI.TypeQuals.addConst();
FT = Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI);
}
@@ -8154,10 +8197,25 @@ bool Sema::CheckFunctionTemplateSpecialization(
}
}
+ // For a qualified friend declaration (with no explicit marker to indicate
+ // that a template specialization was intended), note all (template and
+ // non-template) candidates.
+ if (QualifiedFriend && Candidates.empty()) {
+ Diag(FD->getLocation(), diag::err_qualified_friend_no_match)
+ << FD->getDeclName() << FDLookupContext;
+ // FIXME: We should form a single candidate list and diagnose all
+ // candidates at once, to get proper sorting and limiting.
+ for (auto *OldND : Previous) {
+ if (auto *OldFD = dyn_cast<FunctionDecl>(OldND->getUnderlyingDecl()))
+ NoteOverloadCandidate(OldND, OldFD, FD->getType(), false);
+ }
+ FailedCandidates.NoteCandidates(*this, FD->getLocation());
+ return true;
+ }
+
// Find the most specialized function template.
UnresolvedSetIterator Result = getMostSpecialized(
- Candidates.begin(), Candidates.end(), FailedCandidates,
- FD->getLocation(),
+ Candidates.begin(), Candidates.end(), FailedCandidates, FD->getLocation(),
PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
PDiag(diag::err_function_template_spec_ambiguous)
<< FD->getDeclName() << (ExplicitTemplateArgs != nullptr),
@@ -8304,6 +8362,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
QualType Adjusted = Function->getType();
if (!hasExplicitCallingConv(Adjusted))
Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+ // This doesn't handle deduced return types, but both function
+ // declarations should be undeduced at this point.
if (Context.hasSameType(Adjusted, Method->getType())) {
FoundInstantiation = *I;
Instantiation = Method;
@@ -8573,7 +8633,7 @@ static void dllExportImportClassTemplateSpecialization(
for (auto &B : Def->bases()) {
if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
B.getType()->getAsCXXRecordDecl()))
- S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart());
+ S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getBeginLoc());
}
S.referenceDLLExportedClassMethods();
@@ -8736,7 +8796,7 @@ DeclResult Sema::ActOnExplicitInstantiation(
ClassTemplate,
Converted,
PrevDecl);
- SetNestedNameSpecifier(Specialization, SS);
+ SetNestedNameSpecifier(*this, Specialization, SS);
if (!HasNoEffect && !PrevDecl) {
// Insert the new specialization.
@@ -8990,10 +9050,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
DeclarationName Name = NameInfo.getName();
if (!Name) {
if (!D.isInvalidType())
- Diag(D.getDeclSpec().getLocStart(),
+ Diag(D.getDeclSpec().getBeginLoc(),
diag::err_explicit_instantiation_requires_name)
- << D.getDeclSpec().getSourceRange()
- << D.getSourceRange();
+ << D.getDeclSpec().getSourceRange() << D.getSourceRange();
return true;
}
@@ -9046,8 +9105,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// A deduction guide is not on the list of entities that can be explicitly
// instantiated.
if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
- Diag(D.getDeclSpec().getLocStart(), diag::err_deduction_guide_specialized)
- << /*explicit instantiation*/ 0;
+ Diag(D.getDeclSpec().getBeginLoc(), diag::err_deduction_guide_specialized)
+ << /*explicit instantiation*/ 0;
return true;
}
@@ -9105,7 +9164,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
//
// This includes auto-typed variable template instantiations.
if (R->isUndeducedType()) {
- Diag(T->getTypeLoc().getLocStart(),
+ Diag(T->getTypeLoc().getBeginLoc(),
diag::err_auto_not_allowed_var_inst);
return true;
}
@@ -9165,17 +9224,15 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (!HasNoEffect) {
// Instantiate static data member or variable template.
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
- if (PrevTemplate) {
- // Merge attributes.
- ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes());
- }
+ // Merge attributes.
+ ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes());
if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
}
// Check the new variable specialization against the parsed input.
if (PrevTemplate && Prev && !Context.hasSameType(Prev->getType(), R)) {
- Diag(T->getTypeLoc().getLocStart(),
+ Diag(T->getTypeLoc().getBeginLoc(),
diag::err_invalid_var_template_spec_type)
<< 0 << PrevTemplate << R << Prev->getType();
Diag(PrevTemplate->getLocation(), diag::note_template_declared_here)
@@ -9293,7 +9350,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
PDiag(DiagID) << Specialization->getType(),
PDiag(diag::note_explicit_instantiation_here),
Specialization->getType()->getAs<FunctionProtoType>(),
- Specialization->getLocation(), FPT, D.getLocStart());
+ Specialization->getLocation(), FPT, D.getBeginLoc());
// In Microsoft mode, mismatching exception specifications just cause a
// warning.
if (!getLangOpts().MicrosoftExt && Result)
@@ -9621,7 +9678,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedBooleanCondition(Cond, /*AllowTopLevelCond=*/true);
+ findFailedBooleanCondition(Cond);
Diag(FailedCond->getExprLoc(),
diag::err_typename_nested_not_found_requirement)
@@ -9866,6 +9923,15 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation(
if (!NewTSI)
return true;
+ if (NewTSI->getType()->isUndeducedType()) {
+ // C++17 [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it contains
+ // - an identifier associated by name lookup with a non-type
+ // template-parameter declared with a type that contains a
+ // placeholder type (7.1.7.4),
+ NewTSI = SubstAutoTypeSourceInfo(NewTSI, Context.DependentTy);
+ }
+
if (NewTSI != NTTP->getTypeSourceInfo()) {
NTTP->setTypeSourceInfo(NewTSI);
NTTP->setType(NewTSI->getType());
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index df46d6115a20..f2f989ce1241 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -178,6 +178,8 @@ getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
while (true) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
+ else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
+ E = CE->getSubExpr();
else if (SubstNonTypeTemplateParmExpr *Subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(E))
E = Subst->getReplacement();
@@ -3076,7 +3078,7 @@ Sema::SubstituteExplicitTemplateArguments(
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
// and the end of the function-definition, member-declarator, or
// declarator.
- unsigned ThisTypeQuals = 0;
+ Qualifiers ThisTypeQuals;
CXXRecordDecl *ThisContext = nullptr;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
ThisContext = Method->getParent();
@@ -4423,11 +4425,15 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
if (const AutoType *AT = Type.getType()->getAs<AutoType>()) {
if (AT->isDecltypeAuto()) {
if (isa<InitListExpr>(Init)) {
- Diag(Init->getLocStart(), diag::err_decltype_auto_initializer_list);
+ Diag(Init->getBeginLoc(), diag::err_decltype_auto_initializer_list);
return DAR_FailedAlreadyDiagnosed;
}
- QualType Deduced = BuildDecltypeType(Init, Init->getLocStart(), false);
+ ExprResult ER = CheckPlaceholderExpr(Init);
+ if (ER.isInvalid())
+ return DAR_FailedAlreadyDiagnosed;
+ Init = ER.get();
+ QualType Deduced = BuildDecltypeType(Init, Init->getBeginLoc(), false);
if (Deduced.isNull())
return DAR_FailedAlreadyDiagnosed;
// FIXME: Support a non-canonical deduced type for 'auto'.
@@ -4438,7 +4444,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
return DAR_Succeeded;
} else if (!getLangOpts().CPlusPlus) {
if (isa<InitListExpr>(Init)) {
- Diag(Init->getLocStart(), diag::err_auto_init_list_from_c);
+ Diag(Init->getBeginLoc(), diag::err_auto_init_list_from_c);
return DAR_FailedAlreadyDiagnosed;
}
}
@@ -4655,8 +4661,7 @@ AddImplicitObjectParameterType(ASTContext &Context,
// The standard doesn't say explicitly, but we pick the appropriate kind of
// reference type based on [over.match.funcs]p4.
QualType ArgTy = Context.getTypeDeclType(Method->getParent());
- ArgTy = Context.getQualifiedType(ArgTy,
- Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
+ ArgTy = Context.getQualifiedType(ArgTy, Method->getTypeQualifiers());
if (Method->getRefQualifier() == RQ_RValue)
ArgTy = Context.getRValueReferenceType(ArgTy);
else
@@ -5225,6 +5230,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
while (true) {
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExpr();
+ else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
+ E = CE->getSubExpr();
else if (const SubstNonTypeTemplateParmExpr *Subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(E))
E = Subst->getReplacement();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 1aa69bd35d67..96abeed82493 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -199,6 +199,7 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case DefaultTemplateArgumentChecking:
case DeclaringSpecialMember:
case DefiningSynthesizedFunction:
+ case ExceptionSpecEvaluation:
return false;
// This function should never be called when Kind's value is Memoization.
@@ -621,6 +622,12 @@ void Sema::PrintInstantiationStack() {
break;
}
+ case CodeSynthesisContext::ExceptionSpecEvaluation:
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_evaluating_exception_spec_here)
+ << cast<FunctionDecl>(Active->Entity);
+ break;
+
case CodeSynthesisContext::ExceptionSpecInstantiation:
Diags.Report(Active->PointOfInstantiation,
diag::note_template_exception_spec_instantiation_here)
@@ -668,7 +675,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
// context, depending on what else is on the stack.
if (isa<TypeAliasTemplateDecl>(Active->Entity))
break;
- // Fall through.
+ LLVM_FALLTHROUGH;
case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
case CodeSynthesisContext::ExceptionSpecInstantiation:
// This is a template instantiation, so there is no SFINAE.
@@ -695,6 +702,12 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
// there is no SFINAE.
return None;
+ case CodeSynthesisContext::ExceptionSpecEvaluation:
+ // FIXME: This should not be treated as a SFINAE context, because
+ // we will cache an incorrect exception specification. However, clang
+ // bootstrap relies this! See PR31692.
+ break;
+
case CodeSynthesisContext::Memoization:
break;
}
@@ -894,7 +907,7 @@ namespace {
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals,
+ Qualifiers ThisTypeQuals,
Fn TransformExceptionSpec);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
@@ -1154,7 +1167,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return E;
- return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType());
+ return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind());
}
ExprResult
@@ -1414,7 +1427,7 @@ template<typename Fn>
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals,
+ Qualifiers ThisTypeQuals,
Fn TransformExceptionSpec) {
// We need a local instantiation scope for this function prototype.
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
@@ -1653,7 +1666,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
SourceLocation Loc,
DeclarationName Entity,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals) {
+ Qualifiers ThisTypeQuals) {
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
@@ -1708,7 +1721,7 @@ void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
Proto->getExtProtoInfo().ExceptionSpec;
SmallVector<QualType, 4> ExceptionStorage;
- if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getLocEnd(),
+ if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getEndLoc(),
ESI, ExceptionStorage, Args))
// On error, recover by dropping the exception specification.
ESI.Type = EST_None;
@@ -1789,7 +1802,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
if (NewArg.isUsable()) {
// It would be nice if we still had this.
- SourceLocation EqualLoc = NewArg.get()->getLocStart();
+ SourceLocation EqualLoc = NewArg.get()->getBeginLoc();
SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
}
} else {
@@ -2135,7 +2148,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
CXXRecordDecl *ThisContext =
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
- CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
+ CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
ND && ND->isCXXInstanceMember());
Attr *NewAttr =
@@ -2303,7 +2316,7 @@ bool Sema::InstantiateInClassInitializer(
Diag(PointOfInstantiation,
diag::err_in_class_initializer_not_yet_parsed)
<< OutermostClass << Pattern;
- Diag(Pattern->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed);
+ Diag(Pattern->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
Instantiation->setInvalidDecl();
return true;
}
@@ -2330,14 +2343,14 @@ bool Sema::InstantiateInClassInitializer(
// Instantiate the initializer.
ActOnStartCXXInClassMemberInitializer();
- CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), /*TypeQuals=*/0);
+ CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers());
ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
/*CXXDirectInit=*/false);
Expr *Init = NewInit.get();
assert((!Init || !isa<ParenListExpr>(Init)) && "call-style init in class");
ActOnFinishCXXInClassMemberInitializer(
- Instantiation, Init ? Init->getLocStart() : SourceLocation(), Init);
+ Instantiation, Init ? Init->getBeginLoc() : SourceLocation(), Init);
if (auto *L = getASTMutationListener())
L->DefaultMemberInitializerInstantiated(Instantiation);
@@ -2561,10 +2574,14 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
for (auto *D : Instantiation->decls()) {
bool SuppressNew = false;
if (auto *Function = dyn_cast<FunctionDecl>(D)) {
- if (FunctionDecl *Pattern
- = Function->getInstantiatedFromMemberFunction()) {
- MemberSpecializationInfo *MSInfo
- = Function->getMemberSpecializationInfo();
+ if (FunctionDecl *Pattern =
+ Function->getInstantiatedFromMemberFunction()) {
+
+ if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+ continue;
+
+ MemberSpecializationInfo *MSInfo =
+ Function->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
@@ -2605,6 +2622,9 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
continue;
if (Var->isStaticDataMember()) {
+ if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+ continue;
+
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
@@ -2636,6 +2656,9 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
} else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
+ if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+ continue;
+
// Always skip the injected-class-name, along with any
// redeclarations of nested classes, since both would cause us
// to try to instantiate the members of a class twice.
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 86492716f685..fad3c065e896 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -295,7 +295,7 @@ static void instantiateOMPDeclareSimdDeclAttr(
PVD, FD->getParamDecl(PVD->getFunctionScopeIndex()));
return S.SubstExpr(E, TemplateArgs);
}
- Sema::CXXThisScopeRAII ThisScope(S, ThisContext, /*TypeQuals=*/0,
+ Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(),
FD->isCXXInstanceMember());
return S.SubstExpr(E, TemplateArgs);
};
@@ -355,7 +355,7 @@ void Sema::InstantiateAttrsForDecl(
// applicable to template declaration, we'll need to add them here.
CXXThisScopeRAII ThisScope(
*this, dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()),
- /*TypeQuals*/ 0, ND->isCXXInstanceMember());
+ Qualifiers(), ND->isCXXInstanceMember());
Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
TmplAttr, Context, *this, TemplateArgs);
@@ -365,6 +365,20 @@ void Sema::InstantiateAttrsForDecl(
}
}
+static Sema::RetainOwnershipKind
+attrToRetainOwnershipKind(const Attr *A) {
+ switch (A->getKind()) {
+ case clang::attr::CFConsumed:
+ return Sema::RetainOwnershipKind::CF;
+ case clang::attr::OSConsumed:
+ return Sema::RetainOwnershipKind::OS;
+ case clang::attr::NSConsumed:
+ return Sema::RetainOwnershipKind::NS;
+ default:
+ llvm_unreachable("Wrong argument supplied");
+ }
+}
+
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
@@ -438,11 +452,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
- if (isa<NSConsumedAttr>(TmplAttr) || isa<CFConsumedAttr>(TmplAttr)) {
- AddNSConsumedAttr(TmplAttr->getRange(), New,
- TmplAttr->getSpellingListIndex(),
- isa<NSConsumedAttr>(TmplAttr),
- /*template instantiation*/ true);
+ if (isa<NSConsumedAttr>(TmplAttr) || isa<OSConsumedAttr>(TmplAttr) ||
+ isa<CFConsumedAttr>(TmplAttr)) {
+ AddXConsumedAttr(New, TmplAttr->getRange(),
+ TmplAttr->getSpellingListIndex(),
+ attrToRetainOwnershipKind(TmplAttr),
+ /*template instantiation=*/true);
continue;
}
@@ -459,7 +474,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
NamedDecl *ND = dyn_cast<NamedDecl>(New);
CXXRecordDecl *ThisContext =
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
- CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
+ CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
ND && ND->isCXXInstanceMember());
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
@@ -562,7 +577,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() &&
RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") &&
D->getIdentifier() && D->getIdentifier()->isStr("type") &&
- SemaRef.getSourceManager().isInSystemHeader(D->getLocStart()))
+ SemaRef.getSourceManager().isInSystemHeader(D->getBeginLoc()))
// Fold it to the (non-reference) type which g++ would have produced.
DI = SemaRef.Context.getTrivialTypeSourceInfo(
DI->getType().getNonReferenceType());
@@ -570,10 +585,10 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
// Create the new typedef
TypedefNameDecl *Typedef;
if (IsTypeAlias)
- Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
+ Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(),
D->getLocation(), D->getIdentifier(), DI);
else
- Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
+ Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(),
D->getLocation(), D->getIdentifier(), DI);
if (Invalid)
Typedef->setInvalidDecl();
@@ -748,6 +763,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
Var->setImplicit(D->isImplicit());
+ if (Var->isStaticLocal())
+ SemaRef.CheckStaticLocalForDllExport(Var);
+
return Var;
}
@@ -872,7 +890,7 @@ Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) {
MSPropertyDecl *Property = MSPropertyDecl::Create(
SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), DI->getType(),
- DI, D->getLocStart(), D->getGetterId(), D->getSetterId());
+ DI, D->getBeginLoc(), D->getGetterId(), D->getSetterId());
SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs,
StartingScope);
@@ -932,7 +950,7 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
if (!InstTy)
return nullptr;
- FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(),
+ FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getBeginLoc(),
D->getFriendLoc(), InstTy);
if (!FD)
return nullptr;
@@ -991,10 +1009,10 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
PrevDecl = cast<EnumDecl>(Prev);
}
- EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
- D->getLocation(), D->getIdentifier(),
- PrevDecl, D->isScoped(),
- D->isScopedUsingClassTag(), D->isFixed());
+ EnumDecl *Enum =
+ EnumDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(),
+ D->getLocation(), D->getIdentifier(), PrevDecl,
+ D->isScoped(), D->isScopedUsingClassTag(), D->isFixed());
if (D->isFixed()) {
if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) {
// If we have type source information for the underlying type, it means it
@@ -1228,7 +1246,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
}
TemplateParameterList *PrevParams
- = PrevClassTemplate->getTemplateParameters();
+ = PrevClassTemplate->getMostRecentDecl()->getTemplateParameters();
// Make sure the parameter lists match.
if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams,
@@ -1250,15 +1268,17 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
}
}
- CXXRecordDecl *RecordInst
- = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC,
- Pattern->getLocStart(), Pattern->getLocation(),
- Pattern->getIdentifier(), PrevDecl,
- /*DelayTypeCreation=*/true);
+ CXXRecordDecl *RecordInst = CXXRecordDecl::Create(
+ SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(),
+ Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl,
+ /*DelayTypeCreation=*/true);
if (QualifierLoc)
RecordInst->setQualifierInfo(QualifierLoc);
+ SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs,
+ StartingScope);
+
ClassTemplateDecl *Inst
= ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
D->getIdentifier(), InstParams, RecordInst);
@@ -1484,15 +1504,17 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
PrevDecl = cast<CXXRecordDecl>(Prev);
}
- CXXRecordDecl *Record
- = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
- D->getLocStart(), D->getLocation(),
- D->getIdentifier(), PrevDecl);
+ CXXRecordDecl *Record = CXXRecordDecl::Create(
+ SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
+ D->getLocation(), D->getIdentifier(), PrevDecl);
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
return nullptr;
+ SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs,
+ StartingScope);
+
Record->setImplicit(D->isImplicit());
// FIXME: Check against AS_none is an ugly hack to work around the issue that
// the tag decls introduced by friend class declarations don't have an access
@@ -1725,10 +1747,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
}
+ if (isFriend)
+ Function->setObjectOfFriendDecl();
+
if (InitFunctionInstantiation(Function, D))
Function->setInvalidDecl();
- bool isExplicitSpecialization = false;
+ bool IsExplicitSpecialization = false;
LookupResult Previous(
SemaRef, Function->getDeclName(), SourceLocation(),
@@ -1741,9 +1766,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
= D->getDependentSpecializationInfo()) {
assert(isFriend && "non-friend has dependent specialization info?");
- // This needs to be set now for future sanity.
- Function->setObjectOfFriendDecl();
-
// Instantiate the explicit template arguments.
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
Info->getRAngleLoc());
@@ -1766,8 +1788,25 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Previous))
Function->setInvalidDecl();
- isExplicitSpecialization = true;
+ IsExplicitSpecialization = true;
+ } else if (const ASTTemplateArgumentListInfo *Info =
+ D->getTemplateSpecializationArgsAsWritten()) {
+ // The name of this function was written as a template-id.
+ SemaRef.LookupQualifiedName(Previous, DC);
+
+ // Instantiate the explicit template arguments.
+ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
+ Info->getRAngleLoc());
+ if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
+ ExplicitArgs, TemplateArgs))
+ return nullptr;
+
+ if (SemaRef.CheckFunctionTemplateSpecialization(Function,
+ &ExplicitArgs,
+ Previous))
+ Function->setInvalidDecl();
+ IsExplicitSpecialization = true;
} else if (TemplateParams || !FunctionTemplate) {
// Look only into the namespace where the friend would be declared to
// find a previous declaration. This is the innermost enclosing namespace,
@@ -1782,11 +1821,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Previous.clear();
}
- if (isFriend)
- Function->setObjectOfFriendDecl();
-
SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous,
- isExplicitSpecialization);
+ IsExplicitSpecialization);
NamedDecl *PrincipalDecl = (TemplateParams
? cast<NamedDecl>(FunctionTemplate)
@@ -1795,7 +1831,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
// If the original function was part of a friend declaration,
// inherit its namespace state and add it to the owner.
if (isFriend) {
- PrincipalDecl->setObjectOfFriendDecl();
+ Function->setObjectOfFriendDecl();
+ if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate())
+ FT->setObjectOfFriendDecl();
DC->makeDeclVisibleInContext(PrincipalDecl);
bool QueuedInstantiation = false;
@@ -1945,26 +1983,23 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Constructor->isExplicit(),
Constructor->isInlineSpecified(),
false, Constructor->isConstexpr());
- Method->setRangeEnd(Constructor->getLocEnd());
+ Method->setRangeEnd(Constructor->getEndLoc());
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
StartLoc, NameInfo, T, TInfo,
Destructor->isInlineSpecified(),
false);
- Method->setRangeEnd(Destructor->getLocEnd());
+ Method->setRangeEnd(Destructor->getEndLoc());
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
- Method = CXXConversionDecl::Create(SemaRef.Context, Record,
- StartLoc, NameInfo, T, TInfo,
- Conversion->isInlineSpecified(),
- Conversion->isExplicit(),
- Conversion->isConstexpr(),
- Conversion->getLocEnd());
+ Method = CXXConversionDecl::Create(
+ SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
+ Conversion->isInlineSpecified(), Conversion->isExplicit(),
+ Conversion->isConstexpr(), Conversion->getEndLoc());
} else {
StorageClass SC = D->isStatic() ? SC_Static : SC_None;
- Method = CXXMethodDecl::Create(SemaRef.Context, Record,
- StartLoc, NameInfo, T, TInfo,
- SC, D->isInlineSpecified(),
- D->isConstexpr(), D->getLocEnd());
+ Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo,
+ T, TInfo, SC, D->isInlineSpecified(),
+ D->isConstexpr(), D->getEndLoc());
}
if (D->isInlined())
@@ -2034,7 +2069,54 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
Sema::ForExternalRedeclaration);
- if (!FunctionTemplate || TemplateParams || isFriend) {
+ bool IsExplicitSpecialization = false;
+
+ // If the name of this function was written as a template-id, instantiate
+ // the explicit template arguments.
+ if (DependentFunctionTemplateSpecializationInfo *Info
+ = D->getDependentSpecializationInfo()) {
+ assert(isFriend && "non-friend has dependent specialization info?");
+
+ // Instantiate the explicit template arguments.
+ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
+ Info->getRAngleLoc());
+ if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
+ ExplicitArgs, TemplateArgs))
+ return nullptr;
+
+ // Map the candidate templates to their instantiations.
+ for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
+ Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
+ Info->getTemplate(I),
+ TemplateArgs);
+ if (!Temp) return nullptr;
+
+ Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
+ }
+
+ if (SemaRef.CheckFunctionTemplateSpecialization(Method,
+ &ExplicitArgs,
+ Previous))
+ Method->setInvalidDecl();
+
+ IsExplicitSpecialization = true;
+ } else if (const ASTTemplateArgumentListInfo *Info =
+ D->getTemplateSpecializationArgsAsWritten()) {
+ SemaRef.LookupQualifiedName(Previous, DC);
+
+ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
+ Info->getRAngleLoc());
+ if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
+ ExplicitArgs, TemplateArgs))
+ return nullptr;
+
+ if (SemaRef.CheckFunctionTemplateSpecialization(Method,
+ &ExplicitArgs,
+ Previous))
+ Method->setInvalidDecl();
+
+ IsExplicitSpecialization = true;
+ } else if (!FunctionTemplate || TemplateParams || isFriend) {
SemaRef.LookupQualifiedName(Previous, Record);
// In C++, the previous declaration we find might be a tag type
@@ -2046,7 +2128,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
}
if (!IsClassScopeSpecialization)
- SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, false);
+ SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous,
+ IsExplicitSpecialization);
if (D->isPure())
SemaRef.CheckPureMethod(Method, SourceRange());
@@ -2119,7 +2202,7 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
assert(D->getTypeForDecl()->isTemplateTypeParmType());
TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create(
- SemaRef.Context, Owner, D->getLocStart(), D->getLocation(),
+ SemaRef.Context, Owner, D->getBeginLoc(), D->getLocation(),
D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(),
D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack());
Inst->setAccess(AS_public);
@@ -2683,26 +2766,28 @@ Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *Decl) {
+ ClassScopeFunctionSpecializationDecl *Decl) {
CXXMethodDecl *OldFD = Decl->getSpecialization();
CXXMethodDecl *NewFD =
cast_or_null<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, nullptr, true));
if (!NewFD)
return nullptr;
- LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
- Sema::ForExternalRedeclaration);
-
- TemplateArgumentListInfo TemplateArgs;
- TemplateArgumentListInfo *TemplateArgsPtr = nullptr;
+ TemplateArgumentListInfo ExplicitTemplateArgs;
+ TemplateArgumentListInfo *ExplicitTemplateArgsPtr = nullptr;
if (Decl->hasExplicitTemplateArgs()) {
- TemplateArgs = Decl->templateArgs();
- TemplateArgsPtr = &TemplateArgs;
+ if (SemaRef.Subst(Decl->templateArgs().getArgumentArray(),
+ Decl->templateArgs().size(), ExplicitTemplateArgs,
+ TemplateArgs))
+ return nullptr;
+ ExplicitTemplateArgsPtr = &ExplicitTemplateArgs;
}
+ LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
+ Sema::ForExternalRedeclaration);
SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext);
- if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, TemplateArgsPtr,
- Previous)) {
+ if (SemaRef.CheckFunctionTemplateSpecialization(
+ NewFD, ExplicitTemplateArgsPtr, Previous)) {
NewFD->setInvalidDecl();
return NewFD;
}
@@ -2735,13 +2820,27 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
return TD;
}
+Decl *TemplateDeclInstantiator::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
+ llvm_unreachable(
+ "Requires directive cannot be instantiated within a dependent context");
+}
+
Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
OMPDeclareReductionDecl *D) {
// Instantiate type and check if it is allowed.
- QualType SubstReductionType = SemaRef.ActOnOpenMPDeclareReductionType(
- D->getLocation(),
- ParsedType::make(SemaRef.SubstType(D->getType(), TemplateArgs,
- D->getLocation(), DeclarationName())));
+ const bool RequiresInstantiation =
+ D->getType()->isDependentType() ||
+ D->getType()->isInstantiationDependentType() ||
+ D->getType()->containsUnexpandedParameterPack();
+ QualType SubstReductionType;
+ if (RequiresInstantiation) {
+ SubstReductionType = SemaRef.ActOnOpenMPDeclareReductionType(
+ D->getLocation(),
+ ParsedType::make(SemaRef.SubstType(
+ D->getType(), TemplateArgs, D->getLocation(), DeclarationName())));
+ } else {
+ SubstReductionType = D->getType();
+ }
if (SubstReductionType.isNull())
return nullptr;
bool IsCorrect = !SubstReductionType.isNull();
@@ -2758,25 +2857,35 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
/*S=*/nullptr, Owner, D->getDeclName(), ReductionTypes, D->getAccess(),
PrevDeclInScope);
auto *NewDRD = cast<OMPDeclareReductionDecl>(DRD.get().getSingleDecl());
- if (isDeclWithinFunction(NewDRD))
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD);
+ if (!RequiresInstantiation) {
+ if (Expr *Combiner = D->getCombiner()) {
+ NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut());
+ NewDRD->setCombiner(Combiner);
+ if (Expr *Init = D->getInitializer()) {
+ NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv());
+ NewDRD->setInitializer(Init, D->getInitializerKind());
+ }
+ }
+ (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(
+ /*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl());
+ return NewDRD;
+ }
Expr *SubstCombiner = nullptr;
Expr *SubstInitializer = nullptr;
// Combiners instantiation sequence.
if (D->getCombiner()) {
SemaRef.ActOnOpenMPDeclareReductionCombinerStart(
/*S=*/nullptr, NewDRD);
- const char *Names[] = {"omp_in", "omp_out"};
- for (auto &Name : Names) {
- DeclarationName DN(&SemaRef.Context.Idents.get(Name));
- auto OldLookup = D->lookup(DN);
- auto Lookup = NewDRD->lookup(DN);
- if (!OldLookup.empty() && !Lookup.empty()) {
- assert(Lookup.size() == 1 && OldLookup.size() == 1);
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldLookup.front(),
- Lookup.front());
- }
- }
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(
+ cast<DeclRefExpr>(D->getCombinerIn())->getDecl(),
+ cast<DeclRefExpr>(NewDRD->getCombinerIn())->getDecl());
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(
+ cast<DeclRefExpr>(D->getCombinerOut())->getDecl(),
+ cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl());
+ auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
+ ThisContext);
SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get();
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
// Initializers instantiation sequence.
@@ -2784,19 +2893,12 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
VarDecl *OmpPrivParm =
SemaRef.ActOnOpenMPDeclareReductionInitializerStart(
/*S=*/nullptr, NewDRD);
- const char *Names[] = {"omp_orig", "omp_priv"};
- for (auto &Name : Names) {
- DeclarationName DN(&SemaRef.Context.Idents.get(Name));
- auto OldLookup = D->lookup(DN);
- auto Lookup = NewDRD->lookup(DN);
- if (!OldLookup.empty() && !Lookup.empty()) {
- assert(Lookup.size() == 1 && OldLookup.size() == 1);
- auto *OldVD = cast<VarDecl>(OldLookup.front());
- auto *NewVD = cast<VarDecl>(Lookup.front());
- SemaRef.InstantiateVariableInitializer(NewVD, OldVD, TemplateArgs);
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldVD, NewVD);
- }
- }
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(
+ cast<DeclRefExpr>(D->getInitOrig())->getDecl(),
+ cast<DeclRefExpr>(NewDRD->getInitOrig())->getDecl());
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(
+ cast<DeclRefExpr>(D->getInitPriv())->getDecl(),
+ cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl());
if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) {
SubstInitializer =
SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get();
@@ -2813,8 +2915,9 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
SubstInitializer) ||
(D->getInitializerKind() != OMPDeclareReductionDecl::CallInit &&
!SubstInitializer && !SubstInitializer));
- } else
+ } else {
IsCorrect = false;
+ }
(void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(/*S=*/nullptr, DRD,
IsCorrect);
@@ -2931,15 +3034,10 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
}
// Create the class template partial specialization declaration.
- ClassTemplateSpecializationDecl *InstD
- = ClassTemplateSpecializationDecl::Create(SemaRef.Context,
- D->getTagKind(),
- Owner,
- D->getLocStart(),
- D->getLocation(),
- InstClassTemplate,
- Converted,
- PrevDecl);
+ ClassTemplateSpecializationDecl *InstD =
+ ClassTemplateSpecializationDecl::Create(
+ SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
+ D->getLocation(), InstClassTemplate, Converted, PrevDecl);
// Add this partial specialization to the set of class template partial
// specializations.
@@ -3008,7 +3106,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
// Check that the template argument list is well-formed for this template.
SmallVector<TemplateArgument, 4> Converted;
if (SemaRef.CheckTemplateArgumentList(
- VarTemplate, VarTemplate->getLocStart(),
+ VarTemplate, VarTemplate->getBeginLoc(),
const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false,
Converted))
return nullptr;
@@ -3237,18 +3335,11 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Create the class template partial specialization declaration.
- ClassTemplatePartialSpecializationDecl *InstPartialSpec
- = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context,
- PartialSpec->getTagKind(),
- Owner,
- PartialSpec->getLocStart(),
- PartialSpec->getLocation(),
- InstParams,
- ClassTemplate,
- Converted,
- InstTemplateArgs,
- CanonType,
- nullptr);
+ ClassTemplatePartialSpecializationDecl *InstPartialSpec =
+ ClassTemplatePartialSpecializationDecl::Create(
+ SemaRef.Context, PartialSpec->getTagKind(), Owner,
+ PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
+ ClassTemplate, Converted, InstTemplateArgs, CanonType, nullptr);
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
return nullptr;
@@ -3412,7 +3503,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
assert(Params.empty() && "parameter vector is non-empty at start");
CXXRecordDecl *ThisContext = nullptr;
- unsigned ThisTypeQuals = 0;
+ Qualifiers ThisTypeQuals;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
ThisContext = cast<CXXRecordDecl>(Owner);
ThisTypeQuals = Method->getTypeQualifiers();
@@ -3707,6 +3798,9 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
if (InitFunctionInstantiation(New, Tmpl))
return true;
+ if (isa<CXXDestructorDecl>(New) && SemaRef.getLangOpts().CPlusPlus11)
+ SemaRef.AdjustDestructorExceptionSpec(cast<CXXDestructorDecl>(New));
+
New->setAccess(Tmpl->getAccess());
if (Tmpl->isVirtualAsWritten())
New->setVirtualAsWritten(true);
@@ -3823,7 +3917,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
std::make_pair(Function, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
- !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
+ !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) {
Diag(PointOfInstantiation, diag::warn_func_template_missing)
<< Function;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
@@ -4366,7 +4460,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
} else if (TSK == TSK_ImplicitInstantiation) {
// Warn about missing definition at the end of translation unit.
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
- !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
+ !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) {
Diag(PointOfInstantiation, diag::warn_var_template_missing)
<< Var;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
@@ -4911,7 +5005,9 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
return D;
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
- (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
+ ((ParentDC->isFunctionOrMethod() ||
+ isa<OMPDeclareReductionDecl>(ParentDC)) &&
+ ParentDC->isDependentContext()) ||
(isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
@@ -5192,10 +5288,20 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition;
- InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
- DefinitionRequired, true);
- if (Function->isDefined())
- Function->setInstantiationIsPending(false);
+ if (Function->isMultiVersion()) {
+ getASTContext().forEachMultiversionedFunctionVersion(
+ Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) {
+ InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true,
+ DefinitionRequired, true);
+ if (CurFD->isDefined())
+ CurFD->setInstantiationIsPending(false);
+ });
+ } else {
+ InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true,
+ DefinitionRequired, true);
+ if (Function->isDefined())
+ Function->setInstantiationIsPending(false);
+ }
continue;
}
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 6f9dddf5c05e..0e7fc20d2487 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -164,7 +164,7 @@ namespace {
// A function parameter pack is a pack expansion, so cannot contain
// an unexpanded parameter pack. Likewise for a template parameter
// pack that contains any references to other packs.
- if (D->isParameterPack())
+ if (D && D->isParameterPack())
return true;
return inherited::TraverseDecl(D);
@@ -392,7 +392,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
- return DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded);
+ return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded);
}
bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
@@ -976,6 +976,7 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
PDiag(diag::note_parameter_pack_here));
ParameterPack = Corrected.getCorrectionDecl();
}
+ break;
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
@@ -1125,8 +1126,8 @@ static void CheckFoldOperand(Sema &S, Expr *E) {
isa<AbstractConditionalOperator>(E)) {
S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand)
<< E->getSourceRange()
- << FixItHint::CreateInsertion(E->getLocStart(), "(")
- << FixItHint::CreateInsertion(E->getLocEnd(), ")");
+ << FixItHint::CreateInsertion(E->getBeginLoc(), "(")
+ << FixItHint::CreateInsertion(E->getEndLoc(), ")");
}
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 284d34b22c04..b4c075e9c46d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -116,6 +116,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
case ParsedAttr::AT_Pascal: \
case ParsedAttr::AT_SwiftCall: \
case ParsedAttr::AT_VectorCall: \
+ case ParsedAttr::AT_AArch64VectorPcs: \
case ParsedAttr::AT_MSABI: \
case ParsedAttr::AT_SysVABI: \
case ParsedAttr::AT_Pcs: \
@@ -172,11 +173,25 @@ namespace {
/// processing is complete.
SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
+ /// Attributes corresponding to AttributedTypeLocs that we have not yet
+ /// populated.
+ // FIXME: The two-phase mechanism by which we construct Types and fill
+ // their TypeLocs makes it hard to correctly assign these. We keep the
+ // attributes in creation order as an attempt to make them line up
+ // properly.
+ using TypeAttrPair = std::pair<const AttributedType*, const Attr*>;
+ SmallVector<TypeAttrPair, 8> AttrsForTypes;
+ bool AttrsForTypesSorted = true;
+
+ /// Flag to indicate we parsed a noderef attribute. This is used for
+ /// validating that noderef was used on a pointer or array.
+ bool parsedNoDeref;
+
public:
TypeProcessingState(Sema &sema, Declarator &declarator)
- : sema(sema), declarator(declarator),
- chunkIndex(declarator.getNumTypeObjects()),
- trivial(true), hasSavedAttrs(false) {}
+ : sema(sema), declarator(declarator),
+ chunkIndex(declarator.getNumTypeObjects()), trivial(true),
+ hasSavedAttrs(false), parsedNoDeref(false) {}
Sema &getSema() const {
return sema;
@@ -230,6 +245,47 @@ namespace {
diagnoseBadTypeAttribute(getSema(), *Attr, type);
}
+ /// Get an attributed type for the given attribute, and remember the Attr
+ /// object so that we can attach it to the AttributedTypeLoc.
+ QualType getAttributedType(Attr *A, QualType ModifiedType,
+ QualType EquivType) {
+ QualType T =
+ sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType);
+ AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A});
+ AttrsForTypesSorted = false;
+ return T;
+ }
+
+ /// Extract and remove the Attr* for a given attributed type.
+ const Attr *takeAttrForAttributedType(const AttributedType *AT) {
+ if (!AttrsForTypesSorted) {
+ std::stable_sort(AttrsForTypes.begin(), AttrsForTypes.end(),
+ [](const TypeAttrPair &A, const TypeAttrPair &B) {
+ return A.first < B.first;
+ });
+ AttrsForTypesSorted = true;
+ }
+
+ // FIXME: This is quadratic if we have lots of reuses of the same
+ // attributed type.
+ for (auto It = std::partition_point(
+ AttrsForTypes.begin(), AttrsForTypes.end(),
+ [=](const TypeAttrPair &A) { return A.first < AT; });
+ It != AttrsForTypes.end() && It->first == AT; ++It) {
+ if (It->second) {
+ const Attr *Result = It->second;
+ It->second = nullptr;
+ return Result;
+ }
+ }
+
+ llvm_unreachable("no Attr* for AttributedType*");
+ }
+
+ void setParsedNoDeref(bool parsed) { parsedNoDeref = parsed; }
+
+ bool didParseNoDeref() const { return parsedNoDeref; }
+
~TypeProcessingState() {
if (trivial) return;
@@ -246,7 +302,7 @@ namespace {
getMutableDeclSpec().getAttributes().clearListOnly();
for (ParsedAttr *AL : savedAttrs)
- getMutableDeclSpec().getAttributes().addAtStart(AL);
+ getMutableDeclSpec().getAttributes().addAtEnd(AL);
}
};
} // end anonymous namespace
@@ -255,7 +311,7 @@ static void moveAttrFromListToList(ParsedAttr &attr,
ParsedAttributesView &fromList,
ParsedAttributesView &toList) {
fromList.remove(&attr);
- toList.addAtStart(&attr);
+ toList.addAtEnd(&attr);
}
/// The location of a type attribute.
@@ -656,7 +712,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
// faking up the function chunk is still the right thing to do.
// Otherwise, we need to fake up a function declarator.
- SourceLocation loc = declarator.getLocStart();
+ SourceLocation loc = declarator.getBeginLoc();
// ...and *prepend* it to the declarator.
SourceLocation NoLoc;
@@ -668,12 +724,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*NumArgs=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
/*RefQualifierIsLvalueRef=*/true,
/*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc, EST_None,
/*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
@@ -681,8 +733,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None,
- loc, loc, declarator));
+ /*DeclsInPrototype=*/None, loc, loc, declarator));
// For consistency, make sure the state still has us as processing
// the decl spec.
@@ -808,17 +859,17 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
rangeToRemove = attr.getLocalSourceRange();
if (attr.getTypePtr()->getImmediateNullability()) {
typeArg = attr.getTypePtr()->getModifiedType();
- S.Diag(attr.getLocStart(),
+ S.Diag(attr.getBeginLoc(),
diag::err_objc_type_arg_explicit_nullability)
- << typeArg << FixItHint::CreateRemoval(rangeToRemove);
+ << typeArg << FixItHint::CreateRemoval(rangeToRemove);
diagnosed = true;
}
}
if (!diagnosed) {
- S.Diag(qual.getLocStart(), diag::err_objc_type_arg_qualified)
- << typeArg << typeArg.getQualifiers().getAsString()
- << FixItHint::CreateRemoval(rangeToRemove);
+ S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified)
+ << typeArg << typeArg.getQualifiers().getAsString()
+ << FixItHint::CreateRemoval(rangeToRemove);
}
}
@@ -878,9 +929,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
}
// Diagnose the mismatch.
- S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_arg_does_not_match_bound)
- << typeArg << bound << typeParam->getDeclName();
+ << typeArg << bound << typeParam->getDeclName();
S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
<< typeParam->getDeclName();
@@ -906,9 +957,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
continue;
// Diagnose the mismatch.
- S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_arg_does_not_match_bound)
- << typeArg << bound << typeParam->getDeclName();
+ << typeArg << bound << typeParam->getDeclName();
S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
<< typeParam->getDeclName();
@@ -924,10 +975,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
}
// Diagnose non-id-compatible type arguments.
- S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
+ S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_arg_not_id_compatible)
- << typeArg
- << typeArgInfo->getTypeLoc().getSourceRange();
+ << typeArg << typeArgInfo->getTypeLoc().getSourceRange();
if (failOnError)
return QualType();
@@ -1186,7 +1236,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
DeclSpec &DS = declarator.getMutableDeclSpec();
SourceLocation DeclLoc = declarator.getIdentifierLoc();
if (DeclLoc.isInvalid())
- DeclLoc = DS.getLocStart();
+ DeclLoc = DS.getBeginLoc();
ASTContext &Context = S.Context;
@@ -1268,8 +1318,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// when one is not allowed.
if (DS.isEmpty()) {
S.Diag(DeclLoc, diag::ext_missing_declspec)
- << DS.getSourceRange()
- << FixItHint::CreateInsertion(DS.getLocStart(), "int");
+ << DS.getSourceRange()
+ << FixItHint::CreateInsertion(DS.getBeginLoc(), "int");
}
} else if (!DS.hasTypeSpecifier()) {
// C99 and C++ require a type specifier. For example, C99 6.7.2p2 says:
@@ -1818,8 +1868,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
}
static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
- std::string Quals =
- Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
+ std::string Quals = FnTy->getTypeQuals().getAsString();
switch (FnTy->getRefQualifier()) {
case RQ_None:
@@ -1861,7 +1910,7 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
QualifiedFunctionKind QFK) {
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
- if (!FPT || (FPT->getTypeQuals() == 0 && FPT->getRefQualifier() == RQ_None))
+ if (!FPT || (FPT->getTypeQuals().empty() && FPT->getRefQualifier() == RQ_None))
return false;
S.Diag(Loc, diag::err_compound_qualified_function_type)
@@ -2117,8 +2166,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (!getLangOpts().CPlusPlus11 &&
ArraySize && !ArraySize->isTypeDependent() &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
- Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
- << ArraySize->getType() << ArraySize->getSourceRange();
+ Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int)
+ << ArraySize->getType() << ArraySize->getSourceRange();
return QualType();
}
@@ -2137,8 +2186,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
// of a VLA.
if (getLangOpts().CPlusPlus11 &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
- Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
- << ArraySize->getType() << ArraySize->getSourceRange();
+ Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int)
+ << ArraySize->getType() << ArraySize->getSourceRange();
return QualType();
}
@@ -2151,25 +2200,25 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
// have a value greater than zero.
if (ConstVal.isSigned() && ConstVal.isNegative()) {
if (Entity)
- Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size)
- << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
+ Diag(ArraySize->getBeginLoc(), diag::err_decl_negative_array_size)
+ << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
else
- Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange();
+ Diag(ArraySize->getBeginLoc(), diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange();
return QualType();
}
if (ConstVal == 0) {
// GCC accepts zero sized static arrays. We allow them when
// we're not in a SFINAE context.
- Diag(ArraySize->getLocStart(),
- isSFINAEContext()? diag::err_typecheck_zero_array_size
- : diag::ext_typecheck_zero_array_size)
- << ArraySize->getSourceRange();
+ Diag(ArraySize->getBeginLoc(), isSFINAEContext()
+ ? diag::err_typecheck_zero_array_size
+ : diag::ext_typecheck_zero_array_size)
+ << ArraySize->getSourceRange();
if (ASM == ArrayType::Static) {
- Diag(ArraySize->getLocStart(),
+ Diag(ArraySize->getBeginLoc(),
diag::warn_typecheck_zero_static_array_size)
- << ArraySize->getSourceRange();
+ << ArraySize->getSourceRange();
ASM = ArrayType::Normal;
}
} else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
@@ -2178,9 +2227,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
- Diag(ArraySize->getLocStart(), diag::err_array_too_large)
- << ConstVal.toString(10)
- << ArraySize->getSourceRange();
+ Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
+ << ConstVal.toString(10) << ArraySize->getSourceRange();
return QualType();
}
}
@@ -2842,6 +2890,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// class template argument deduction)?
bool IsCXXAutoType =
(Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
+ bool IsDeducedReturnType = false;
switch (D.getContext()) {
case DeclaratorContext::LambdaExprContext:
@@ -2873,9 +2922,9 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
TemplateTypeParmDecl *CorrespondingTemplateParam =
TemplateTypeParmDecl::Create(
SemaRef.Context, SemaRef.Context.getTranslationUnitDecl(),
- /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
+ /*KeyLoc*/ SourceLocation(), /*NameLoc*/ D.getBeginLoc(),
TemplateParameterDepth, AutoParameterPosition,
- /*Identifier*/nullptr, false, IsParameterPack);
+ /*Identifier*/ nullptr, false, IsParameterPack);
LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
// Replace the 'auto' in the function parameter with this invented
// template type parameter.
@@ -2933,10 +2982,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::TrailingReturnVarContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 13; // Function return type
+ IsDeducedReturnType = true;
break;
case DeclaratorContext::ConversionIdContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 14; // conversion-type-id
+ IsDeducedReturnType = true;
break;
case DeclaratorContext::FunctionalCastContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
@@ -3021,10 +3072,14 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
D.getContext() != DeclaratorContext::LambdaExprContext) {
// If there was a trailing return type, we already got
// warn_cxx98_compat_trailing_return_type in the parser.
- // If this was a lambda, we already warned on that too.
SemaRef.Diag(AutoRange.getBegin(),
- diag::warn_cxx98_compat_auto_type_specifier)
- << AutoRange;
+ D.getContext() ==
+ DeclaratorContext::LambdaExprParameterContext
+ ? diag::warn_cxx11_compat_generic_lambda
+ : IsDeducedReturnType
+ ? diag::warn_cxx11_compat_deduced_return_type
+ : diag::warn_cxx98_compat_auto_type_specifier)
+ << AutoRange;
}
}
@@ -3302,9 +3357,9 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
<< D.getIdentifier();
// FIXME: A cast to void is probably a better suggestion in cases where it's
// valid (when there is no initializer and we're not in a condition).
- S.Diag(D.getLocStart(), diag::note_function_style_cast_add_parentheses)
- << FixItHint::CreateInsertion(D.getLocStart(), "(")
- << FixItHint::CreateInsertion(S.getLocForEndOfToken(D.getLocEnd()), ")");
+ S.Diag(D.getBeginLoc(), diag::note_function_style_cast_add_parentheses)
+ << FixItHint::CreateInsertion(D.getBeginLoc(), "(")
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(D.getEndLoc()), ")");
S.Diag(Paren.Loc, diag::note_remove_parens_for_variable_declaration)
<< FixItHint::CreateRemoval(Paren.Loc)
<< FixItHint::CreateRemoval(Paren.EndLoc);
@@ -3834,6 +3889,37 @@ static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) {
return false;
}
+static bool IsNoDerefableChunk(DeclaratorChunk Chunk) {
+ return (Chunk.Kind == DeclaratorChunk::Pointer ||
+ Chunk.Kind == DeclaratorChunk::Array);
+}
+
+template<typename AttrT>
+static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) {
+ Attr.setUsedAsTypeAttr();
+ return ::new (Ctx)
+ AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex());
+}
+
+static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
+ NullabilityKind NK) {
+ switch (NK) {
+ case NullabilityKind::NonNull:
+ return createSimpleAttr<TypeNonNullAttr>(Ctx, Attr);
+
+ case NullabilityKind::Nullable:
+ return createSimpleAttr<TypeNullableAttr>(Ctx, Attr);
+
+ case NullabilityKind::Unspecified:
+ return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr);
+ }
+ llvm_unreachable("unknown NullabilityKind");
+}
+
+static TypeSourceInfo *
+GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
+ QualType T, TypeSourceInfo *ReturnTypeInfo);
+
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
@@ -3858,7 +3944,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
bool IsQualifiedFunction = T->isFunctionProtoType() &&
- (T->castAs<FunctionProtoType>()->getTypeQuals() != 0 ||
+ (!T->castAs<FunctionProtoType>()->getTypeQuals().empty() ||
T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
// If T is 'decltype(auto)', the only declarators we can have are parens
@@ -4128,7 +4214,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
SourceRange(pointerLoc), nullptr, SourceLocation(), nullptr, 0,
syntax);
- attrs.addAtStart(nullabilityAttr);
+ attrs.addAtEnd(nullabilityAttr);
if (inferNullabilityCS) {
state.getDeclarator().getMutableDeclSpec().getObjCQualifiers()
@@ -4184,11 +4270,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (auto *attr = inferPointerNullability(
pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
- D.getDeclSpec().getLocEnd(),
+ D.getDeclSpec().getEndLoc(),
D.getMutableDeclSpec().getAttributes())) {
- T = Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
- attr->setUsedAsTypeAttr();
+ T = state.getAttributedType(
+ createNullabilityAttr(Context, *attr, *inferNullability), T, T);
}
}
}
@@ -4202,6 +4287,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ bool ExpectNoDerefChunk =
+ state.getCurrentAttributes().hasAttribute(ParsedAttr::AT_NoDeref);
+
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -4247,7 +4335,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
DeclType.EndLoc, DeclType.getAttrs());
- if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
+ if (LangOpts.ObjC && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
if (DeclType.Ptr.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
@@ -4367,7 +4455,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// does not have a K&R-style identifier list), then the arguments are part
// of the type, otherwise the argument list is ().
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- IsQualifiedFunction = FTI.TypeQuals || FTI.hasRefQualifier();
+ IsQualifiedFunction =
+ FTI.hasMethodTypeQualifiers() || FTI.hasRefQualifier();
// Check for auto functions and trailing return type and adjust the
// return type accordingly.
@@ -4375,25 +4464,28 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// trailing-return-type is only required if we're declaring a function,
// and not, for instance, a pointer to a function.
if (D.getDeclSpec().hasAutoTypeSpec() &&
- !FTI.hasTrailingReturnType() && chunkIndex == 0 &&
- !S.getLangOpts().CPlusPlus14) {
- S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto
- ? diag::err_auto_missing_trailing_return
- : diag::err_deduced_return_type);
- T = Context.IntTy;
- D.setInvalidType(true);
+ !FTI.hasTrailingReturnType() && chunkIndex == 0) {
+ if (!S.getLangOpts().CPlusPlus14) {
+ S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto
+ ? diag::err_auto_missing_trailing_return
+ : diag::err_deduced_return_type);
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ } else {
+ S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+ diag::warn_cxx11_compat_deduced_return_type);
+ }
} else if (FTI.hasTrailingReturnType()) {
// T must be exactly 'auto' at this point. See CWG issue 681.
if (isa<ParenType>(T)) {
- S.Diag(D.getLocStart(),
- diag::err_trailing_return_in_parens)
- << T << D.getSourceRange();
+ S.Diag(D.getBeginLoc(), diag::err_trailing_return_in_parens)
+ << T << D.getSourceRange();
D.setInvalidType(true);
} else if (D.getName().getKind() ==
UnqualifiedIdKind::IK_DeductionGuideName) {
if (T != Context.DependentTy) {
- S.Diag(D.getDeclSpec().getLocStart(),
+ S.Diag(D.getDeclSpec().getBeginLoc(),
diag::err_deduction_guide_with_complex_decl)
<< D.getSourceRange();
D.setInvalidType(true);
@@ -4413,6 +4505,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = Context.IntTy;
D.setInvalidType(true);
}
+ } else {
+ // This function type is not the type of the entity being declared,
+ // so checking the 'auto' is not the responsibility of this chunk.
}
}
@@ -4475,11 +4570,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (T->isObjCObjectType()) {
SourceLocation DiagLoc, FixitLoc;
if (TInfo) {
- DiagLoc = TInfo->getTypeLoc().getLocStart();
- FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
+ DiagLoc = TInfo->getTypeLoc().getBeginLoc();
+ FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getEndLoc());
} else {
DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
- FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
+ FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getEndLoc());
}
S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value)
<< 0 << T
@@ -4599,7 +4694,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.ExtInfo = EI;
EPI.Variadic = FTI.isVariadic;
EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
- EPI.TypeQuals = FTI.TypeQuals;
+ EPI.TypeQuals.addCVRUQualifiers(
+ FTI.MethodQualifiers ? FTI.MethodQualifiers->getTypeQualifiers()
+ : 0);
EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
: FTI.RefQualifierIsLValueRef? RQ_LValue
: RQ_RValue;
@@ -4726,6 +4823,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
Exceptions,
EPI.ExceptionSpec);
+ const auto &Spec = D.getCXXScopeSpec();
+ // OpenCLCPlusPlus: A class member function has an address space.
+ if (state.getSema().getLangOpts().OpenCLCPlusPlus &&
+ ((!Spec.isEmpty() &&
+ Spec.getScopeRep()->getKind() == NestedNameSpecifier::TypeSpec) ||
+ state.getDeclarator().getContext() ==
+ DeclaratorContext::MemberContext)) {
+ LangAS CurAS = EPI.TypeQuals.getAddressSpace();
+ // If a class member function's address space is not set, set it to
+ // __generic.
+ LangAS AS =
+ (CurAS == LangAS::Default ? LangAS::opencl_generic : CurAS);
+ EPI.TypeQuals.addAddressSpace(AS);
+ }
T = Context.getFunctionType(T, ParamTys, EPI);
}
break;
@@ -4805,8 +4916,22 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// See if there are any attributes on this declarator chunk.
processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs());
+
+ if (DeclType.Kind != DeclaratorChunk::Paren) {
+ if (ExpectNoDerefChunk) {
+ if (!IsNoDerefableChunk(DeclType))
+ S.Diag(DeclType.Loc, diag::warn_noderef_on_non_pointer_or_array);
+ ExpectNoDerefChunk = false;
+ }
+
+ ExpectNoDerefChunk = state.didParseNoDeref();
+ }
}
+ if (ExpectNoDerefChunk)
+ S.Diag(state.getDeclarator().getBeginLoc(),
+ diag::warn_noderef_on_non_pointer_or_array);
+
// GNU warning -Wstrict-prototypes
// Warn if a function declaration is without a prototype.
// This warning is issued for all kinds of unprototyped function
@@ -4887,23 +5012,24 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
!IsTypedefName &&
D.getContext() != DeclaratorContext::TemplateArgContext &&
D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
- SourceLocation Loc = D.getLocStart();
+ SourceLocation Loc = D.getBeginLoc();
SourceRange RemovalRange;
unsigned I;
if (D.isFunctionDeclarator(I)) {
SmallVector<SourceLocation, 4> RemovalLocs;
const DeclaratorChunk &Chunk = D.getTypeObject(I);
assert(Chunk.Kind == DeclaratorChunk::Function);
+
if (Chunk.Fun.hasRefQualifier())
RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc());
- if (Chunk.Fun.TypeQuals & Qualifiers::Const)
- RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc());
- if (Chunk.Fun.TypeQuals & Qualifiers::Volatile)
- RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc());
- if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
- RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
+
+ if (Chunk.Fun.hasMethodTypeQualifiers())
+ Chunk.Fun.MethodQualifiers->forEachQualifier(
+ [&](DeclSpec::TQ TypeQual, StringRef QualName,
+ SourceLocation SL) { RemovalLocs.push_back(SL); });
+
if (!RemovalLocs.empty()) {
- llvm::sort(RemovalLocs.begin(), RemovalLocs.end(),
+ llvm::sort(RemovalLocs,
BeforeThanCompare<SourceLocation>(S.getSourceManager()));
RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
Loc = RemovalLocs.front();
@@ -4917,7 +5043,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Strip the cv-qualifiers and ref-qualifiers from the type.
FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
- EPI.TypeQuals = 0;
+ EPI.TypeQuals.removeCVRQualifiers();
EPI.RefQualifier = RQ_None;
T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(),
@@ -5028,7 +5154,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (D.isInvalidType())
return Context.getTrivialTypeSourceInfo(T);
- return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
+ return GetTypeSourceInfoForDeclarator(state, T, TInfo);
}
/// GetTypeForDeclarator - Convert the type for the specified
@@ -5093,7 +5219,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
&S.Context.Idents.get("objc_ownership"), SourceLocation(),
/*scope*/ nullptr, SourceLocation(),
/*args*/ &Args, 1, ParsedAttr::AS_GNU);
- chunk.getAttrs().addAtStart(attr);
+ chunk.getAttrs().addAtEnd(attr);
// TODO: mark whether we did this inference?
}
@@ -5155,7 +5281,7 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC) {
Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
if (ownership != Qualifiers::OCL_None)
transferARCOwnership(state, declSpecTy, ownership);
@@ -5164,131 +5290,25 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
}
-/// Map an AttributedType::Kind to an ParsedAttr::Kind.
-static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) {
- switch (kind) {
- case AttributedType::attr_address_space:
- return ParsedAttr::AT_AddressSpace;
- case AttributedType::attr_regparm:
- return ParsedAttr::AT_Regparm;
- case AttributedType::attr_vector_size:
- return ParsedAttr::AT_VectorSize;
- case AttributedType::attr_neon_vector_type:
- return ParsedAttr::AT_NeonVectorType;
- case AttributedType::attr_neon_polyvector_type:
- return ParsedAttr::AT_NeonPolyVectorType;
- case AttributedType::attr_objc_gc:
- return ParsedAttr::AT_ObjCGC;
- case AttributedType::attr_objc_ownership:
- case AttributedType::attr_objc_inert_unsafe_unretained:
- return ParsedAttr::AT_ObjCOwnership;
- case AttributedType::attr_noreturn:
- return ParsedAttr::AT_NoReturn;
- case AttributedType::attr_nocf_check:
- return ParsedAttr::AT_AnyX86NoCfCheck;
- case AttributedType::attr_cdecl:
- return ParsedAttr::AT_CDecl;
- case AttributedType::attr_fastcall:
- return ParsedAttr::AT_FastCall;
- case AttributedType::attr_stdcall:
- return ParsedAttr::AT_StdCall;
- case AttributedType::attr_thiscall:
- return ParsedAttr::AT_ThisCall;
- case AttributedType::attr_regcall:
- return ParsedAttr::AT_RegCall;
- case AttributedType::attr_pascal:
- return ParsedAttr::AT_Pascal;
- case AttributedType::attr_swiftcall:
- return ParsedAttr::AT_SwiftCall;
- case AttributedType::attr_vectorcall:
- return ParsedAttr::AT_VectorCall;
- case AttributedType::attr_pcs:
- case AttributedType::attr_pcs_vfp:
- return ParsedAttr::AT_Pcs;
- case AttributedType::attr_inteloclbicc:
- return ParsedAttr::AT_IntelOclBicc;
- case AttributedType::attr_ms_abi:
- return ParsedAttr::AT_MSABI;
- case AttributedType::attr_sysv_abi:
- return ParsedAttr::AT_SysVABI;
- case AttributedType::attr_preserve_most:
- return ParsedAttr::AT_PreserveMost;
- case AttributedType::attr_preserve_all:
- return ParsedAttr::AT_PreserveAll;
- case AttributedType::attr_ptr32:
- return ParsedAttr::AT_Ptr32;
- case AttributedType::attr_ptr64:
- return ParsedAttr::AT_Ptr64;
- case AttributedType::attr_sptr:
- return ParsedAttr::AT_SPtr;
- case AttributedType::attr_uptr:
- return ParsedAttr::AT_UPtr;
- case AttributedType::attr_nonnull:
- return ParsedAttr::AT_TypeNonNull;
- case AttributedType::attr_nullable:
- return ParsedAttr::AT_TypeNullable;
- case AttributedType::attr_null_unspecified:
- return ParsedAttr::AT_TypeNullUnspecified;
- case AttributedType::attr_objc_kindof:
- return ParsedAttr::AT_ObjCKindOf;
- case AttributedType::attr_ns_returns_retained:
- return ParsedAttr::AT_NSReturnsRetained;
- case AttributedType::attr_lifetimebound:
- return ParsedAttr::AT_LifetimeBound;
- }
- llvm_unreachable("unexpected attribute kind!");
-}
-
-static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) {
- TL.setAttrNameLoc(attr.getLoc());
- if (TL.hasAttrExprOperand()) {
- assert(attr.isArgExpr(0) && "mismatched attribute operand kind");
- TL.setAttrExprOperand(attr.getArgAsExpr(0));
- } else if (TL.hasAttrEnumOperand()) {
- assert((attr.isArgIdent(0) || attr.isArgExpr(0)) &&
- "unexpected attribute operand kind");
- if (attr.isArgIdent(0))
- TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc);
- else
- TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc());
- }
-
- // FIXME: preserve this information to here.
- if (TL.hasAttrOperand())
- TL.setAttrOperandParensRange(SourceRange());
-}
-
static void fillAttributedTypeLoc(AttributedTypeLoc TL,
- const ParsedAttributesView &Attrs,
- const ParsedAttributesView &DeclAttrs) {
- // DeclAttrs and Attrs cannot be both empty.
- assert((!Attrs.empty() || !DeclAttrs.empty()) &&
- "no type attributes in the expected location!");
-
- ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind());
- // Try to search for an attribute of matching kind in Attrs list.
- for (const ParsedAttr &AL : Attrs)
- if (AL.getKind() == parsedKind)
- return setAttributedTypeLoc(TL, AL);
-
- for (const ParsedAttr &AL : DeclAttrs)
- if (AL.isCXX11Attribute() || AL.getKind() == parsedKind)
- return setAttributedTypeLoc(TL, AL);
- llvm_unreachable("no matching type attribute in expected location!");
+ TypeProcessingState &State) {
+ TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
}
namespace {
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
ASTContext &Context;
+ TypeProcessingState &State;
const DeclSpec &DS;
public:
- TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
- : Context(Context), DS(DS) {}
+ TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State,
+ const DeclSpec &DS)
+ : Context(Context), State(State), DS(DS) {}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{});
Visit(TL.getModifiedLoc());
+ fillAttributedTypeLoc(TL, State);
}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
Visit(TL.getUnqualifiedLoc());
@@ -5301,7 +5321,7 @@ namespace {
// FIXME. We should have DS.getTypeSpecTypeEndLoc(). But, it requires
// addition field. What we have is good enough for dispay of location
// of 'fixit' on interface name.
- TL.setNameEndLoc(DS.getLocEnd());
+ TL.setNameEndLoc(DS.getEndLoc());
}
void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
TypeSourceInfo *RepTInfo = nullptr;
@@ -5445,11 +5465,13 @@ namespace {
class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
ASTContext &Context;
+ TypeProcessingState &State;
const DeclaratorChunk &Chunk;
public:
- DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
- : Context(Context), Chunk(Chunk) {}
+ DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State,
+ const DeclaratorChunk &Chunk)
+ : Context(Context), State(State), Chunk(Chunk) {}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
llvm_unreachable("qualified type locs not expected here!");
@@ -5459,7 +5481,7 @@ namespace {
}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});
+ fillAttributedTypeLoc(TL, State);
}
void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
// nothing
@@ -5616,10 +5638,13 @@ fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
/// up in the normal place in the declaration specifiers (such as a C++
/// conversion function), this pointer will refer to a type source information
/// for that return type.
-TypeSourceInfo *
-Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
- TypeSourceInfo *ReturnTypeInfo) {
- TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
+static TypeSourceInfo *
+GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
+ QualType T, TypeSourceInfo *ReturnTypeInfo) {
+ Sema &S = State.getSema();
+ Declarator &D = State.getDeclarator();
+
+ TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T);
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
// Handle parameter packs whose type is a pack expansion.
@@ -5629,13 +5654,6 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
}
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-
- if (DependentAddressSpaceTypeLoc DASTL =
- CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
- fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
- CurrTL = DASTL.getPointeeTypeLoc().getUnqualifiedLoc();
- }
-
// An AtomicTypeLoc might be produced by an atomic qualifier in this
// declarator chunk.
if (AtomicTypeLoc ATL = CurrTL.getAs<AtomicTypeLoc>()) {
@@ -5644,16 +5662,21 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
}
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
- fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),
- D.getAttributes());
+ fillAttributedTypeLoc(TL, State);
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
+ while (DependentAddressSpaceTypeLoc TL =
+ CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
+ fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
+ CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
+ }
+
// FIXME: Ordering here?
while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
- DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
+ DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -5664,7 +5687,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
} else {
- TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
+ TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL);
}
return TInfo;
@@ -5801,7 +5824,10 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
/// specified type. The attribute contains 1 argument, the id of the address
/// space for the type.
static void HandleAddressSpaceTypeAttribute(QualType &Type,
- const ParsedAttr &Attr, Sema &S) {
+ const ParsedAttr &Attr,
+ TypeProcessingState &State) {
+ Sema &S = State.getSema();
+
// ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
// qualified by an address-space qualifier."
if (Type->isFunctionType()) {
@@ -5815,8 +5841,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
+ << 1;
Attr.setInvalid();
return;
}
@@ -5843,10 +5869,15 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
// the type.
QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
- if (!T.isNull())
- Type = T;
- else
+ if (!T.isNull()) {
+ ASTContext &Ctx = S.Context;
+ auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+ Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
+ static_cast<unsigned>(T.getQualifiers().getAddressSpace()));
+ Type = State.getAttributedType(ASAttr, T, T);
+ } else {
Attr.setInvalid();
+ }
} else {
// The keyword-based type attributes imply which address space to use.
switch (Attr.getKind()) {
@@ -5893,7 +5924,7 @@ static bool hasDirectOwnershipQualifier(QualType type) {
while (true) {
// __strong id
if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
- if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
+ if (attr->getAttrKind() == attr::ObjCOwnership)
return true;
type = attr->getModifiedType();
@@ -5951,8 +5982,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
S.getSourceManager().getImmediateExpansionRange(AttrLoc).getBegin();
if (!attr.isArgIdent(0)) {
- S.Diag(AttrLoc, diag::err_attribute_argument_type)
- << attr.getName() << AANT_ArgumentString;
+ S.Diag(AttrLoc, diag::err_attribute_argument_type) << attr
+ << AANT_ArgumentString;
attr.setInvalid();
return true;
}
@@ -6037,9 +6068,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
// the coexistence problems with __unsafe_unretained.
if (!S.getLangOpts().ObjCAutoRefCount &&
lifetime == Qualifiers::OCL_ExplicitNone) {
- type = S.Context.getAttributedType(
- AttributedType::attr_objc_inert_unsafe_unretained,
- type, type);
+ type = state.getAttributedType(
+ createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr),
+ type, type);
return true;
}
@@ -6049,9 +6080,12 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
// If we have a valid source location for the attribute, use an
// AttributedType instead.
- if (AttrLoc.isValid())
- type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
- origType, type);
+ if (AttrLoc.isValid()) {
+ type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(
+ attr.getRange(), S.Context, II,
+ attr.getAttributeSpellingListIndex()),
+ origType, type);
+ }
auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
unsigned diagnostic, QualType type) {
@@ -6122,14 +6156,14 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
// Check the attribute arguments.
if (!attr.isArgIdent(0)) {
S.Diag(attr.getLoc(), diag::err_attribute_argument_type)
- << attr.getName() << AANT_ArgumentString;
+ << attr << AANT_ArgumentString;
attr.setInvalid();
return true;
}
Qualifiers::GC GCAttr;
if (attr.getNumArgs() > 1) {
- S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << attr.getName() << 1;
+ S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << attr
+ << 1;
attr.setInvalid();
return true;
}
@@ -6151,8 +6185,10 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
// Make an attributed type to preserve the source information.
if (attr.getLoc().isValid())
- type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
- origType, type);
+ type = state.getAttributedType(
+ ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,
+ attr.getAttributeSpellingListIndex()),
+ origType, type);
return true;
}
@@ -6295,37 +6331,50 @@ namespace {
} // end anonymous namespace
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
- ParsedAttr &Attr, QualType &Type) {
+ ParsedAttr &PAttr, QualType &Type) {
Sema &S = State.getSema();
- ParsedAttr::Kind Kind = Attr.getKind();
+ Attr *A;
+ switch (PAttr.getKind()) {
+ default: llvm_unreachable("Unknown attribute kind");
+ case ParsedAttr::AT_Ptr32:
+ A = createSimpleAttr<Ptr32Attr>(S.Context, PAttr);
+ break;
+ case ParsedAttr::AT_Ptr64:
+ A = createSimpleAttr<Ptr64Attr>(S.Context, PAttr);
+ break;
+ case ParsedAttr::AT_SPtr:
+ A = createSimpleAttr<SPtrAttr>(S.Context, PAttr);
+ break;
+ case ParsedAttr::AT_UPtr:
+ A = createSimpleAttr<UPtrAttr>(S.Context, PAttr);
+ break;
+ }
+
+ attr::Kind NewAttrKind = A->getKind();
QualType Desugared = Type;
const AttributedType *AT = dyn_cast<AttributedType>(Type);
while (AT) {
- AttributedType::Kind CurAttrKind = AT->getAttrKind();
+ attr::Kind CurAttrKind = AT->getAttrKind();
// You cannot specify duplicate type attributes, so if the attribute has
// already been applied, flag it.
- if (getAttrListKind(CurAttrKind) == Kind) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
- << Attr.getName();
+ if (NewAttrKind == CurAttrKind) {
+ S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)
+ << PAttr.getName();
return true;
}
// You cannot have both __sptr and __uptr on the same type, nor can you
// have __ptr32 and __ptr64.
- if ((CurAttrKind == AttributedType::attr_ptr32 &&
- Kind == ParsedAttr::AT_Ptr64) ||
- (CurAttrKind == AttributedType::attr_ptr64 &&
- Kind == ParsedAttr::AT_Ptr32)) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) ||
+ (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) {
+ S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__ptr32'" << "'__ptr64'";
return true;
- } else if ((CurAttrKind == AttributedType::attr_sptr &&
- Kind == ParsedAttr::AT_UPtr) ||
- (CurAttrKind == AttributedType::attr_uptr &&
- Kind == ParsedAttr::AT_SPtr)) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ } else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) ||
+ (CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) {
+ S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__sptr'" << "'__uptr'";
return true;
}
@@ -6336,43 +6385,64 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
// Pointer type qualifiers can only operate on pointer types, but not
// pointer-to-member types.
+ //
+ // FIXME: Should we really be disallowing this attribute if there is any
+ // type sugar between it and the pointer (other than attributes)? Eg, this
+ // disallows the attribute on a parenthesized pointer.
+ // And if so, should we really allow *any* type attribute?
if (!isa<PointerType>(Desugared)) {
if (Type->isMemberPointerType())
- S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers)
- << Attr.getName();
+ S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr;
else
- S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
- << Attr.getName() << 0;
+ S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0;
return true;
}
- AttributedType::Kind TAK;
- switch (Kind) {
- default: llvm_unreachable("Unknown attribute kind");
- case ParsedAttr::AT_Ptr32:
- TAK = AttributedType::attr_ptr32;
- break;
- case ParsedAttr::AT_Ptr64:
- TAK = AttributedType::attr_ptr64;
- break;
- case ParsedAttr::AT_SPtr:
- TAK = AttributedType::attr_sptr;
- break;
- case ParsedAttr::AT_UPtr:
- TAK = AttributedType::attr_uptr;
- break;
- }
-
- Type = S.Context.getAttributedType(TAK, Type, Type);
+ Type = State.getAttributedType(A, Type, Type);
return false;
}
-bool Sema::checkNullabilityTypeSpecifier(QualType &type,
- NullabilityKind nullability,
- SourceLocation nullabilityLoc,
- bool isContextSensitive,
- bool allowOnArrayType) {
- recordNullabilitySeen(*this, nullabilityLoc);
+/// Map a nullability attribute kind to a nullability kind.
+static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
+ switch (kind) {
+ case ParsedAttr::AT_TypeNonNull:
+ return NullabilityKind::NonNull;
+
+ case ParsedAttr::AT_TypeNullable:
+ return NullabilityKind::Nullable;
+
+ case ParsedAttr::AT_TypeNullUnspecified:
+ return NullabilityKind::Unspecified;
+
+ default:
+ llvm_unreachable("not a nullability attribute kind");
+ }
+}
+
+/// Applies a nullability type specifier to the given type, if possible.
+///
+/// \param state The type processing state.
+///
+/// \param type The type to which the nullability specifier will be
+/// added. On success, this type will be updated appropriately.
+///
+/// \param attr The attribute as written on the type.
+///
+/// \param allowOnArrayType Whether to accept nullability specifiers on an
+/// array type (e.g., because it will decay to a pointer).
+///
+/// \returns true if a problem has been diagnosed, false on success.
+static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
+ QualType &type,
+ ParsedAttr &attr,
+ bool allowOnArrayType) {
+ Sema &S = state.getSema();
+
+ NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind());
+ SourceLocation nullabilityLoc = attr.getLoc();
+ bool isContextSensitive = attr.isContextSensitiveKeywordAttribute();
+
+ recordNullabilitySeen(S, nullabilityLoc);
// Check for existing nullability attributes on the type.
QualType desugared = type;
@@ -6381,7 +6451,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
if (auto existingNullability = attributed->getImmediateNullability()) {
// Duplicated nullability.
if (nullability == *existingNullability) {
- Diag(nullabilityLoc, diag::warn_nullability_duplicate)
+ S.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
<< DiagNullabilityKind(nullability, isContextSensitive)
<< FixItHint::CreateRemoval(nullabilityLoc);
@@ -6389,7 +6459,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
}
// Conflicting nullability.
- Diag(nullabilityLoc, diag::err_nullability_conflicting)
+ S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< DiagNullabilityKind(nullability, isContextSensitive)
<< DiagNullabilityKind(*existingNullability, false);
return true;
@@ -6402,9 +6472,9 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// This (unlike the code above) looks through typedefs that might
// have nullability specifiers on them, which means we cannot
// provide a useful Fix-It.
- if (auto existingNullability = desugared->getNullability(Context)) {
+ if (auto existingNullability = desugared->getNullability(S.Context)) {
if (nullability != *existingNullability) {
- Diag(nullabilityLoc, diag::err_nullability_conflicting)
+ S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< DiagNullabilityKind(nullability, isContextSensitive)
<< DiagNullabilityKind(*existingNullability, false);
@@ -6415,7 +6485,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
if (auto typedefNullability
= AttributedType::stripOuterNullability(underlyingType)) {
if (*typedefNullability == *existingNullability) {
- Diag(typedefDecl->getLocation(), diag::note_nullability_here)
+ S.Diag(typedefDecl->getLocation(), diag::note_nullability_here)
<< DiagNullabilityKind(*existingNullability, false);
}
}
@@ -6428,7 +6498,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// If this definitely isn't a pointer type, reject the specifier.
if (!desugared->canHaveNullability() &&
!(allowOnArrayType && desugared->isArrayType())) {
- Diag(nullabilityLoc, diag::err_nullability_nonpointer)
+ S.Diag(nullabilityLoc, diag::err_nullability_nonpointer)
<< DiagNullabilityKind(nullability, isContextSensitive) << type;
return true;
}
@@ -6446,10 +6516,10 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
if (pointeeType->isAnyPointerType() ||
pointeeType->isObjCObjectPointerType() ||
pointeeType->isMemberPointerType()) {
- Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
+ S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
<< DiagNullabilityKind(nullability, true)
<< type;
- Diag(nullabilityLoc, diag::note_nullability_type_specifier)
+ S.Diag(nullabilityLoc, diag::note_nullability_type_specifier)
<< DiagNullabilityKind(nullability, false)
<< type
<< FixItHint::CreateReplacement(nullabilityLoc,
@@ -6459,16 +6529,21 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
}
// Form the attributed type.
- type = Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(nullability), type, type);
+ type = state.getAttributedType(
+ createNullabilityAttr(S.Context, attr, nullability), type, type);
return false;
}
-bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
+/// Check the application of the Objective-C '__kindof' qualifier to
+/// the given type.
+static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
+ ParsedAttr &attr) {
+ Sema &S = state.getSema();
+
if (isa<ObjCTypeParamType>(type)) {
// Build the attributed type to record where __kindof occurred.
- type = Context.getAttributedType(AttributedType::attr_objc_kindof,
- type, type);
+ type = state.getAttributedType(
+ createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type);
return false;
}
@@ -6480,7 +6555,7 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
// If not, we can't apply __kindof.
if (!objType) {
// FIXME: Handle dependent types that aren't yet object types.
- Diag(loc, diag::err_objc_kindof_nonobject)
+ S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject)
<< type;
return true;
}
@@ -6488,45 +6563,31 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
// Rebuild the "equivalent" type, which pushes __kindof down into
// the object type.
// There is no need to apply kindof on an unqualified id type.
- QualType equivType = Context.getObjCObjectType(
+ QualType equivType = S.Context.getObjCObjectType(
objType->getBaseType(), objType->getTypeArgsAsWritten(),
objType->getProtocols(),
/*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true);
// If we started with an object pointer type, rebuild it.
if (ptrType) {
- equivType = Context.getObjCObjectPointerType(equivType);
- if (auto nullability = type->getNullability(Context)) {
- auto attrKind = AttributedType::getNullabilityAttrKind(*nullability);
- equivType = Context.getAttributedType(attrKind, equivType, equivType);
+ equivType = S.Context.getObjCObjectPointerType(equivType);
+ if (auto nullability = type->getNullability(S.Context)) {
+ // We create a nullability attribute from the __kindof attribute.
+ // Make sure that will make sense.
+ assert(attr.getAttributeSpellingListIndex() == 0 &&
+ "multiple spellings for __kindof?");
+ Attr *A = createNullabilityAttr(S.Context, attr, *nullability);
+ A->setImplicit(true);
+ equivType = state.getAttributedType(A, equivType, equivType);
}
}
// Build the attributed type to record where __kindof occurred.
- type = Context.getAttributedType(AttributedType::attr_objc_kindof,
- type,
- equivType);
-
+ type = state.getAttributedType(
+ createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, equivType);
return false;
}
-/// Map a nullability attribute kind to a nullability kind.
-static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
- switch (kind) {
- case ParsedAttr::AT_TypeNonNull:
- return NullabilityKind::NonNull;
-
- case ParsedAttr::AT_TypeNullable:
- return NullabilityKind::Nullable;
-
- case ParsedAttr::AT_TypeNullUnspecified:
- return NullabilityKind::Unspecified;
-
- default:
- llvm_unreachable("not a nullability attribute kind");
- }
-}
-
/// Distribute a nullability type attribute that cannot be applied to
/// the type specifier to a pointer, block pointer, or member pointer
/// declarator, complaining if necessary.
@@ -6614,27 +6675,29 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
return false;
}
-static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
+static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
assert(!Attr.isInvalid());
switch (Attr.getKind()) {
default:
llvm_unreachable("not a calling convention attribute");
case ParsedAttr::AT_CDecl:
- return AttributedType::attr_cdecl;
+ return createSimpleAttr<CDeclAttr>(Ctx, Attr);
case ParsedAttr::AT_FastCall:
- return AttributedType::attr_fastcall;
+ return createSimpleAttr<FastCallAttr>(Ctx, Attr);
case ParsedAttr::AT_StdCall:
- return AttributedType::attr_stdcall;
+ return createSimpleAttr<StdCallAttr>(Ctx, Attr);
case ParsedAttr::AT_ThisCall:
- return AttributedType::attr_thiscall;
+ return createSimpleAttr<ThisCallAttr>(Ctx, Attr);
case ParsedAttr::AT_RegCall:
- return AttributedType::attr_regcall;
+ return createSimpleAttr<RegCallAttr>(Ctx, Attr);
case ParsedAttr::AT_Pascal:
- return AttributedType::attr_pascal;
+ return createSimpleAttr<PascalAttr>(Ctx, Attr);
case ParsedAttr::AT_SwiftCall:
- return AttributedType::attr_swiftcall;
+ return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
case ParsedAttr::AT_VectorCall:
- return AttributedType::attr_vectorcall;
+ return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
+ case ParsedAttr::AT_AArch64VectorPcs:
+ return createSimpleAttr<AArch64VectorPcsAttr>(Ctx, Attr);
case ParsedAttr::AT_Pcs: {
// The attribute may have had a fixit applied where we treated an
// identifier as a string literal. The contents of the string are valid,
@@ -6644,20 +6707,22 @@ static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
else
Str = Attr.getArgAsIdent(0)->Ident->getName();
- return llvm::StringSwitch<AttributedType::Kind>(Str)
- .Case("aapcs", AttributedType::attr_pcs)
- .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
+ PcsAttr::PCSType Type;
+ if (!PcsAttr::ConvertStrToPCSType(Str, Type))
+ llvm_unreachable("already validated the attribute");
+ return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type,
+ Attr.getAttributeSpellingListIndex());
}
case ParsedAttr::AT_IntelOclBicc:
- return AttributedType::attr_inteloclbicc;
+ return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
case ParsedAttr::AT_MSABI:
- return AttributedType::attr_ms_abi;
+ return createSimpleAttr<MSABIAttr>(Ctx, Attr);
case ParsedAttr::AT_SysVABI:
- return AttributedType::attr_sysv_abi;
+ return createSimpleAttr<SysVABIAttr>(Ctx, Attr);
case ParsedAttr::AT_PreserveMost:
- return AttributedType::attr_preserve_most;
+ return createSimpleAttr<PreserveMostAttr>(Ctx, Attr);
case ParsedAttr::AT_PreserveAll:
- return AttributedType::attr_preserve_all;
+ return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
}
llvm_unreachable("unexpected attribute kind!");
}
@@ -6705,8 +6770,9 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
= unwrapped.get()->getExtInfo().withProducesResult(true);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
}
- type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained,
- origType, type);
+ type = state.getAttributedType(
+ createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr),
+ origType, type);
return true;
}
@@ -6781,13 +6847,12 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
const FunctionType *fn = unwrapped.get();
CallingConv CCOld = fn->getCallConv();
- AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
+ Attr *CCAttr = getCCTypeAttr(S.Context, attr);
if (CCOld != CC) {
// Error out on when there's already an attribute on the type
// and the CCs don't match.
- const AttributedType *AT = S.getCallingConvAttributedType(type);
- if (AT && AT->getAttrKind() != CCAttrKind) {
+ if (S.getCallingConvAttributedType(type)) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
<< FunctionType::getNameForCallConv(CCOld);
@@ -6841,7 +6906,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
Equivalent =
unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
}
- type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
+ type = state.getAttributedType(CCAttr, type, Equivalent);
return true;
}
@@ -6906,8 +6971,8 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
+ << 1;
Attr.setInvalid();
return;
}
@@ -6943,8 +7008,8 @@ static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
+ << 1;
return;
}
@@ -7032,14 +7097,14 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S, VectorType::VectorKind VecKind) {
// Target must have NEON
if (!S.Context.getTargetInfo().hasFeature("neon")) {
- S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName();
+ S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr;
Attr.setInvalid();
return;
}
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
+ << 1;
Attr.setInvalid();
return;
}
@@ -7049,8 +7114,8 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
!numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << numEltsExpr->getSourceRange();
+ << Attr << AANT_ArgumentIntegerConstant
+ << numEltsExpr->getSourceRange();
Attr.setInvalid();
return;
}
@@ -7085,22 +7150,43 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr,
}
if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) {
- QualType PointeeTy = TypedefTy->desugar();
- S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers);
+ QualType BaseTy = TypedefTy->desugar();
std::string PrevAccessQual;
- switch (cast<BuiltinType>(PointeeTy.getTypePtr())->getKind()) {
- #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
- case BuiltinType::Id: \
- PrevAccessQual = #Access; \
- break;
- #include "clang/Basic/OpenCLImageTypes.def"
- default:
- assert(0 && "Unable to find corresponding image type.");
+ if (BaseTy->isPipeType()) {
+ if (TypedefTy->getDecl()->hasAttr<OpenCLAccessAttr>()) {
+ OpenCLAccessAttr *Attr =
+ TypedefTy->getDecl()->getAttr<OpenCLAccessAttr>();
+ PrevAccessQual = Attr->getSpelling();
+ } else {
+ PrevAccessQual = "read_only";
+ }
+ } else if (const BuiltinType* ImgType = BaseTy->getAs<BuiltinType>()) {
+
+ switch (ImgType->getKind()) {
+ #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id: \
+ PrevAccessQual = #Access; \
+ break;
+ #include "clang/Basic/OpenCLImageTypes.def"
+ default:
+ llvm_unreachable("Unable to find corresponding image type.");
+ }
+ } else {
+ llvm_unreachable("unexpected type");
+ }
+ StringRef AttrName = Attr.getName()->getName();
+ if (PrevAccessQual == AttrName.ltrim("_")) {
+ // Duplicated qualifiers
+ S.Diag(Attr.getLoc(), diag::warn_duplicate_declspec)
+ << AttrName << Attr.getRange();
+ } else {
+ // Contradicting qualifiers
+ S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers);
}
- S.Diag(TypedefTy->getDecl()->getLocStart(),
- diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
+ S.Diag(TypedefTy->getDecl()->getBeginLoc(),
+ diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
} else if (CurType->isPipeType()) {
if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) {
QualType ElemType = CurType->getAs<PipeType>()->getElementType();
@@ -7136,7 +7222,8 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
bool IsPointee =
ChunkIndex > 0 &&
(D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer ||
- D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer);
+ D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer ||
+ D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference);
bool IsFuncReturnType =
ChunkIndex > 0 &&
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function;
@@ -7156,10 +7243,13 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
!IsPointee) ||
// Do not deduce addr space of the void type, e.g. in f(void), otherwise
// it will fail some sema check.
- (T->isVoidType() && !IsPointee))
+ (T->isVoidType() && !IsPointee) ||
+ // Do not deduce address spaces for dependent types because they might end
+ // up instantiating to a type with an explicit address space qualifier.
+ T->isDependentType())
return;
- LangAS ImpAddr;
+ LangAS ImpAddr = LangAS::Default;
// Put OpenCL automatic variable in private address space.
// OpenCL v1.2 s6.5:
// The default address space name for arguments to a function in a
@@ -7181,7 +7271,9 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
if (IsPointee) {
ImpAddr = LangAS::opencl_generic;
} else {
- if (D.getContext() == DeclaratorContext::FileContext) {
+ if (D.getContext() == DeclaratorContext::TemplateArgContext) {
+ // Do not deduce address space for non-pointee type in template arg.
+ } else if (D.getContext() == DeclaratorContext::FileContext) {
ImpAddr = LangAS::opencl_global;
} else {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
@@ -7196,14 +7288,15 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
}
-static void HandleLifetimeBoundAttr(QualType &CurType,
- const ParsedAttr &Attr,
- Sema &S, Declarator &D) {
- if (D.isDeclarationOfFunction()) {
- CurType = S.Context.getAttributedType(AttributedType::attr_lifetimebound,
- CurType, CurType);
+static void HandleLifetimeBoundAttr(TypeProcessingState &State,
+ QualType &CurType,
+ ParsedAttr &Attr) {
+ if (State.getDeclarator().isDeclarationOfFunction()) {
+ CurType = State.getAttributedType(
+ createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
+ CurType, CurType);
} else {
- Attr.diagnoseAppertainsTo(S, nullptr);
+ Attr.diagnoseAppertainsTo(State.getSema(), nullptr);
}
}
@@ -7220,6 +7313,9 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// sure we visit every element once. Copy the attributes list, and iterate
// over that.
ParsedAttributesView AttrsCopy{attrs};
+
+ state.setParsedNoDeref(false);
+
for (ParsedAttr &attr : AttrsCopy) {
// Skip attributes that were marked to be invalid.
@@ -7231,7 +7327,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// not appertain to a DeclaratorChunk. If we handle them as type
// attributes, accept them in that position and diagnose the GCC
// incompatibility.
- if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) {
+ if (attr.isGNUScope()) {
bool IsTypeAttr = attr.isTypeAttr();
if (TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(),
@@ -7256,7 +7352,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// A C++11 attribute on a declarator chunk must appertain to a type.
if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr)
- << attr.getName();
+ << attr;
attr.setUsedAsTypeAttr();
}
break;
@@ -7282,7 +7378,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case ParsedAttr::AT_OpenCLConstantAddressSpace:
case ParsedAttr::AT_OpenCLGenericAddressSpace:
case ParsedAttr::AT_AddressSpace:
- HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+ HandleAddressSpaceTypeAttribute(type, attr, state);
attr.setUsedAsTypeAttr();
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
@@ -7313,12 +7409,18 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_LifetimeBound:
- if (TAL == TAL_DeclChunk) {
- HandleLifetimeBoundAttr(type, attr, state.getSema(),
- state.getDeclarator());
- attr.setUsedAsTypeAttr();
- }
+ if (TAL == TAL_DeclChunk)
+ HandleLifetimeBoundAttr(state, type, attr);
+ break;
+
+ case ParsedAttr::AT_NoDeref: {
+ ASTContext &Ctx = state.getSema().Context;
+ type = state.getAttributedType(createSimpleAttr<NoDerefAttr>(Ctx, attr),
+ type, type);
+ attr.setUsedAsTypeAttr();
+ state.setParsedNoDeref(true);
break;
+ }
MS_TYPE_ATTRS_CASELIST:
if (!handleMSPointerTypeQualifierAttr(state, attr, type))
@@ -7341,11 +7443,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
bool allowOnArrayType =
state.getDeclarator().isPrototypeContext() &&
!hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
- if (state.getSema().checkNullabilityTypeSpecifier(
+ if (checkNullabilityTypeSpecifier(
+ state,
type,
- mapNullabilityAttrKind(attr.getKind()),
- attr.getLoc(),
- attr.isContextSensitiveKeywordAttribute(),
+ attr,
allowOnArrayType)) {
attr.setInvalid();
}
@@ -7364,16 +7465,16 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case TAL_DeclName:
state.getSema().Diag(attr.getLoc(),
diag::err_objc_kindof_wrong_position)
- << FixItHint::CreateRemoval(attr.getLoc())
- << FixItHint::CreateInsertion(
- state.getDeclarator().getDeclSpec().getLocStart(), "__kindof ");
+ << FixItHint::CreateRemoval(attr.getLoc())
+ << FixItHint::CreateInsertion(
+ state.getDeclarator().getDeclSpec().getBeginLoc(),
+ "__kindof ");
break;
}
// Apply it regardless.
- if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
+ if (checkObjCKindOfType(state, type, attr))
attr.setInvalid();
- attr.setUsedAsTypeAttr();
break;
FUNCTION_TYPE_ATTRS_CASELIST:
@@ -7577,14 +7678,35 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
assert(D && "missing definition for pattern of instantiated definition");
*Suggested = D;
- if (isVisible(D))
+
+ auto DefinitionIsVisible = [&] {
+ // The (primary) definition might be in a visible module.
+ if (isVisible(D))
+ return true;
+
+ // A visible module might have a merged definition instead.
+ if (D->isModulePrivate() ? hasMergedDefinitionInCurrentModule(D)
+ : hasVisibleMergedDefinition(D)) {
+ if (CodeSynthesisContexts.empty() &&
+ !getLangOpts().ModulesLocalVisibility) {
+ // Cache the fact that this definition is implicitly visible because
+ // there is a visible merged definition.
+ D->setVisibleDespiteOwningModule();
+ }
+ return true;
+ }
+
+ return false;
+ };
+
+ if (DefinitionIsVisible())
return true;
// The external source may have additional definitions of this entity that are
// visible, so complete the redeclaration chain now and ask again.
if (auto *Source = Context.getExternalSource()) {
Source->CompleteRedeclChain(D);
- return isVisible(D);
+ return DefinitionIsVisible();
}
return false;
@@ -7684,39 +7806,24 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
return false;
}
- const TagType *Tag = T->getAs<TagType>();
- const ObjCInterfaceType *IFace = T->getAs<ObjCInterfaceType>();
+ TagDecl *Tag = dyn_cast_or_null<TagDecl>(Def);
+ ObjCInterfaceDecl *IFace = dyn_cast_or_null<ObjCInterfaceDecl>(Def);
- // If there's an unimported definition of this type in a module (for
- // instance, because we forward declared it, then imported the definition),
- // import that definition now.
- //
- // FIXME: What about other cases where an import extends a redeclaration
- // chain for a declaration that can be accessed through a mechanism other
- // than name lookup (eg, referenced in a template, or a variable whose type
- // could be completed by the module)?
- //
- // FIXME: Should we map through to the base array element type before
- // checking for a tag type?
+ // Give the external source a chance to provide a definition of the type.
+ // This is kept separate from completing the redeclaration chain so that
+ // external sources such as LLDB can avoid synthesizing a type definition
+ // unless it's actually needed.
if (Tag || IFace) {
- NamedDecl *D =
- Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
-
// Avoid diagnosing invalid decls as incomplete.
- if (D->isInvalidDecl())
+ if (Def->isInvalidDecl())
return true;
// Give the external AST source a chance to complete the type.
if (auto *Source = Context.getExternalSource()) {
- if (Tag) {
- TagDecl *TagD = Tag->getDecl();
- if (TagD->hasExternalLexicalStorage())
- Source->CompleteType(TagD);
- } else {
- ObjCInterfaceDecl *IFaceD = IFace->getDecl();
- if (IFaceD->hasExternalLexicalStorage())
- Source->CompleteType(IFace->getDecl());
- }
+ if (Tag && Tag->hasExternalLexicalStorage())
+ Source->CompleteType(Tag);
+ if (IFace && IFace->hasExternalLexicalStorage())
+ Source->CompleteType(IFace);
// If the external source completed the type, go through the motions
// again to ensure we're allowed to use the completed type.
if (!T->isIncompleteType())
@@ -7727,32 +7834,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// If we have a class template specialization or a class member of a
// class template specialization, or an array with known size of such,
// try to instantiate it.
- QualType MaybeTemplate = T;
- while (const ConstantArrayType *Array
- = Context.getAsConstantArrayType(MaybeTemplate))
- MaybeTemplate = Array->getElementType();
- if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
+ if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(Tag)) {
bool Instantiated = false;
bool Diagnosed = false;
- if (ClassTemplateSpecializationDecl *ClassTemplateSpec
- = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+ if (RD->isDependentContext()) {
+ // Don't try to instantiate a dependent class (eg, a member template of
+ // an instantiated class template specialization).
+ // FIXME: Can this ever happen?
+ } else if (auto *ClassTemplateSpec =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
Diagnosed = InstantiateClassTemplateSpecialization(
Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
/*Complain=*/Diagnoser);
Instantiated = true;
}
- } else if (CXXRecordDecl *Rec
- = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
- CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
- if (!Rec->isBeingDefined() && Pattern) {
- MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
+ } else {
+ CXXRecordDecl *Pattern = RD->getInstantiatedFromMemberClass();
+ if (!RD->isBeingDefined() && Pattern) {
+ MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo();
assert(MSI && "Missing member specialization information?");
// This record was instantiated from a class within a template.
if (MSI->getTemplateSpecializationKind() !=
TSK_ExplicitSpecialization) {
- Diagnosed = InstantiateClass(Loc, Rec, Pattern,
- getTemplateInstantiationArgs(Rec),
+ Diagnosed = InstantiateClass(Loc, RD, Pattern,
+ getTemplateInstantiationArgs(RD),
TSK_ImplicitInstantiation,
/*Complain=*/Diagnoser);
Instantiated = true;
@@ -7783,15 +7889,15 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// If the type was a forward declaration of a class/struct/union
// type, produce a note.
- if (Tag && !Tag->getDecl()->isInvalidDecl())
- Diag(Tag->getDecl()->getLocation(),
+ if (Tag && !Tag->isInvalidDecl())
+ Diag(Tag->getLocation(),
Tag->isBeingDefined() ? diag::note_type_being_defined
: diag::note_forward_declaration)
- << QualType(Tag, 0);
+ << Context.getTagDeclType(Tag);
// If the Objective-C class was a forward declaration, produce a note.
- if (IFace && !IFace->getDecl()->isInvalidDecl())
- Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
+ if (IFace && !IFace->isInvalidDecl())
+ Diag(IFace->getLocation(), diag::note_forward_class);
// If we have external information that we can use to suggest a fix,
// produce a note.
@@ -7880,7 +7986,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
<< getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
for (const auto &I : RD->vbases())
- Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here)
+ Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here)
<< I.getSourceRange();
} else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
!RD->hasTrivialDefaultConstructor()) {
@@ -7888,9 +7994,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
} else if (RD->hasNonLiteralTypeFieldsOrBases()) {
for (const auto &I : RD->bases()) {
if (!I.getType()->isLiteralType(Context)) {
- Diag(I.getLocStart(),
- diag::note_non_literal_base_class)
- << RD << I.getType() << I.getSourceRange();
+ Diag(I.getBeginLoc(), diag::note_non_literal_base_class)
+ << RD << I.getType() << I.getSourceRange();
return true;
}
}
@@ -7947,9 +8052,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
}
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
- ExprResult ER = CheckPlaceholderExpr(E);
- if (ER.isInvalid()) return QualType();
- E = ER.get();
+ assert(!E->hasPlaceholderType() && "unexpected placeholder");
if (!getLangOpts().CPlusPlus && E->refersToBitField())
Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
@@ -8034,9 +8137,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
bool AsUnevaluated) {
- ExprResult ER = CheckPlaceholderExpr(E);
- if (ER.isInvalid()) return QualType();
- E = ER.get();
+ assert(!E->hasPlaceholderType() && "unexpected placeholder");
if (AsUnevaluated && CodeSynthesisContexts.empty() &&
E->HasSideEffects(Context, false)) {
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index de962d775d73..df14768cbe81 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -328,7 +328,7 @@ public:
/// other mechanism.
///
/// \returns the transformed statement.
- StmtResult TransformStmt(Stmt *S);
+ StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false);
/// Transform the given statement.
///
@@ -597,7 +597,7 @@ public:
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals,
+ Qualifiers ThisTypeQuals,
Fn TransformExceptionSpec);
bool TransformExceptionSpec(SourceLocation Loc,
@@ -684,15 +684,13 @@ public:
OMPClause *Transform ## Class(Class *S);
#include "clang/Basic/OpenMPKinds.def"
- /// Build a new qualified type given its unqualified type and type
- /// qualifiers.
+ /// Build a new qualified type given its unqualified type and type location.
///
/// By default, this routine adds type qualifiers only to types that can
/// have qualifiers, and silently suppresses those qualifiers that are not
/// permitted. Subclasses may override this routine to provide different
/// behavior.
- QualType RebuildQualifiedType(QualType T, SourceLocation Loc,
- Qualifiers Quals);
+ QualType RebuildQualifiedType(QualType T, QualifiedTypeLoc TL);
/// Build a new pointer type given its pointee type.
///
@@ -1798,14 +1796,16 @@ public:
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *
- RebuildOMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+ RebuildOMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
SourceLocation MapLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc) {
- return getSema().ActOnOpenMPMapClause(MapTypeModifier, MapType,
- IsMapTypeImplicit, MapLoc, ColonLoc,
- VarList, StartLoc, LParenLoc, EndLoc);
+ return getSema().ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc,
+ MapType, IsMapTypeImplicit, MapLoc,
+ ColonLoc, VarList, StartLoc,
+ LParenLoc, EndLoc);
}
/// Build a new OpenMP 'num_teams' clause.
@@ -2021,11 +2021,10 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc,
- SourceLocation CoawaitLoc,
- SourceLocation ColonLoc,
- Stmt *Range, Stmt *Begin, Stmt *End,
- Expr *Cond, Expr *Inc,
- Stmt *LoopVar,
+ SourceLocation CoawaitLoc, Stmt *Init,
+ SourceLocation ColonLoc, Stmt *Range,
+ Stmt *Begin, Stmt *End, Expr *Cond,
+ Expr *Inc, Stmt *LoopVar,
SourceLocation RParenLoc) {
// If we've just learned that the range is actually an Objective-C
// collection, treat this as an Objective-C fast enumeration loop.
@@ -2037,17 +2036,24 @@ public:
Expr *RangeExpr = RangeVar->getInit();
if (!RangeExpr->isTypeDependent() &&
- RangeExpr->getType()->isObjCObjectPointerType())
- return getSema().ActOnObjCForCollectionStmt(ForLoc, LoopVar, RangeExpr,
- RParenLoc);
+ RangeExpr->getType()->isObjCObjectPointerType()) {
+ // FIXME: Support init-statements in Objective-C++20 ranged for
+ // statement.
+ if (Init) {
+ return SemaRef.Diag(Init->getBeginLoc(),
+ diag::err_objc_for_range_init_stmt)
+ << Init->getSourceRange();
+ }
+ return getSema().ActOnObjCForCollectionStmt(ForLoc, LoopVar,
+ RangeExpr, RParenLoc);
+ }
}
}
}
- return getSema().BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc,
- Range, Begin, End,
- Cond, Inc, LoopVar, RParenLoc,
- Sema::BFRK_Rebuild);
+ return getSema().BuildCXXForRangeStmt(ForLoc, CoawaitLoc, Init, ColonLoc,
+ Range, Begin, End, Cond, Inc, LoopVar,
+ RParenLoc, Sema::BFRK_Rebuild);
}
/// Build a new C++0x range-based for statement.
@@ -2090,8 +2096,8 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildPredefinedExpr(SourceLocation Loc,
- PredefinedExpr::IdentType IT) {
- return getSema().BuildPredefinedExpr(Loc, IT);
+ PredefinedExpr::IdentKind IK) {
+ return getSema().BuildPredefinedExpr(Loc, IK);
}
/// Build a new expression that references a declaration.
@@ -3124,15 +3130,15 @@ public:
// Build a reference to the __builtin_shufflevector builtin
FunctionDecl *Builtin = cast<FunctionDecl>(Lookup.front());
- Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, false,
- SemaRef.Context.BuiltinFnTy,
- VK_RValue, BuiltinLoc);
+ Expr *Callee = new (SemaRef.Context)
+ DeclRefExpr(SemaRef.Context, Builtin, false,
+ SemaRef.Context.BuiltinFnTy, VK_RValue, BuiltinLoc);
QualType CalleePtrTy = SemaRef.Context.getPointerType(Builtin->getType());
Callee = SemaRef.ImpCastExprToType(Callee, CalleePtrTy,
CK_BuiltinFnToFnPtr).get();
// Build the CallExpr
- ExprResult TheCall = new (SemaRef.Context) CallExpr(
+ ExprResult TheCall = CallExpr::Create(
SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(),
Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc);
@@ -3263,8 +3269,8 @@ private:
bool DeducibleTSTContext);
};
-template<typename Derived>
-StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) {
if (!S)
return S;
@@ -3288,7 +3294,7 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
if (E.isInvalid())
return StmtError();
- return getSema().ActOnExprStmt(E);
+ return getSema().ActOnExprStmt(E, DiscardedValue);
}
}
@@ -3338,8 +3344,8 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
if (!Init)
return Init;
- if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
- Init = ExprTemp->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
if (auto *AIL = dyn_cast<ArrayInitLoopExpr>(Init))
Init = AIL->getCommonExpr();
@@ -3386,6 +3392,11 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
if (Construct && Construct->isStdInitListInitialization())
return TransformInitializer(Construct->getArg(0), NotCopyInit);
+ // Enter a list-init context if this was list initialization.
+ EnterExpressionEvaluationContext Context(
+ getSema(), EnterExpressionEvaluationContext::InitList,
+ Construct->isListInitialization());
+
SmallVector<Expr*, 8> NewArgs;
bool ArgChanged = false;
if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(),
@@ -3394,8 +3405,8 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
// If this was list initialization, revert to syntactic list form.
if (Construct->isListInitialization())
- return getDerived().RebuildInitList(Construct->getLocStart(), NewArgs,
- Construct->getLocEnd());
+ return getDerived().RebuildInitList(Construct->getBeginLoc(), NewArgs,
+ Construct->getEndLoc());
// Build a ParenListExpr to represent anything else.
SourceRange Parens = Construct->getParenOrBraceRange();
@@ -4217,8 +4228,9 @@ TreeTransform<Derived>::TransformTypeWithDeducedTST(TypeSourceInfo *DI) {
return nullptr;
if (QTL) {
- Result = getDerived().RebuildQualifiedType(
- Result, QTL.getBeginLoc(), QTL.getType().getLocalQualifiers());
+ Result = getDerived().RebuildQualifiedType(Result, QTL);
+ if (Result.isNull())
+ return nullptr;
TLB.TypeWasModifiedSafely(Result);
}
@@ -4229,13 +4241,14 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
QualifiedTypeLoc T) {
- Qualifiers Quals = T.getType().getLocalQualifiers();
-
QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
if (Result.isNull())
return QualType();
- Result = getDerived().RebuildQualifiedType(Result, T.getBeginLoc(), Quals);
+ Result = getDerived().RebuildQualifiedType(Result, T);
+
+ if (Result.isNull())
+ return QualType();
// RebuildQualifiedType might have updated the type, but not in a way
// that invalidates the TypeLoc. (There's no location information for
@@ -4245,21 +4258,41 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
return Result;
}
-template<typename Derived>
+template <typename Derived>
QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T,
- SourceLocation Loc,
- Qualifiers Quals) {
+ QualifiedTypeLoc TL) {
+
+ SourceLocation Loc = TL.getBeginLoc();
+ Qualifiers Quals = TL.getType().getLocalQualifiers();
+
+ if (((T.getAddressSpace() != LangAS::Default &&
+ Quals.getAddressSpace() != LangAS::Default)) &&
+ T.getAddressSpace() != Quals.getAddressSpace()) {
+ SemaRef.Diag(Loc, diag::err_address_space_mismatch_templ_inst)
+ << TL.getType() << T;
+ return QualType();
+ }
+
// C++ [dcl.fct]p7:
// [When] adding cv-qualifications on top of the function type [...] the
// cv-qualifiers are ignored.
+ if (T->isFunctionType()) {
+ T = SemaRef.getASTContext().getAddrSpaceQualType(T,
+ Quals.getAddressSpace());
+ return T;
+ }
+
// C++ [dcl.ref]p1:
// when the cv-qualifiers are introduced through the use of a typedef-name
// or decltype-specifier [...] the cv-qualifiers are ignored.
// Note that [dcl.ref]p1 lists all cases in which cv-qualifiers can be
// applied to a reference type.
- // FIXME: This removes all qualifiers, not just cv-qualifiers!
- if (T->isFunctionType() || T->isReferenceType())
- return T;
+ if (T->isReferenceType()) {
+ // The only qualifier that applies to a reference type is restrict.
+ if (!Quals.hasRestrict())
+ return T;
+ Quals = Qualifiers::fromCVRMask(Qualifiers::Restrict);
+ }
// Suppress Objective-C lifetime qualifiers if they don't make sense for the
// resulting type.
@@ -4682,7 +4715,8 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
}
if (SizeResult.isInvalid())
return QualType();
- SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get());
+ SizeResult =
+ SemaRef.ActOnFinishFullExpr(SizeResult.get(), /*DiscardedValue*/ false);
if (SizeResult.isInvalid())
return QualType();
@@ -5214,7 +5248,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
SmallVector<QualType, 4> ExceptionStorage;
TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
return getDerived().TransformFunctionProtoType(
- TLB, TL, nullptr, 0,
+ TLB, TL, nullptr, Qualifiers(),
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
return This->TransformExceptionSpec(TL.getBeginLoc(), ESI,
ExceptionStorage, Changed);
@@ -5224,7 +5258,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
template<typename Derived> template<typename Fn>
QualType TreeTransform<Derived>::TransformFunctionProtoType(
TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals, Fn TransformExceptionSpec) {
+ Qualifiers ThisTypeQuals, Fn TransformExceptionSpec) {
// Transform the parameters and return type.
//
@@ -5267,6 +5301,13 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
if (ResultType.isNull())
return QualType();
+ // Return type can not be qualified with an address space.
+ if (ResultType.getAddressSpace() != LangAS::Default) {
+ SemaRef.Diag(TL.getReturnLoc().getBeginLoc(),
+ diag::err_attribute_address_function_type);
+ return QualType();
+ }
+
if (getDerived().TransformFunctionTypeParams(
TL.getBeginLoc(), TL.getParams(),
TL.getTypePtr()->param_type_begin(),
@@ -6058,6 +6099,12 @@ QualType TreeTransform<Derived>::TransformAttributedType(
if (modifiedType.isNull())
return QualType();
+ // oldAttr can be null if we started with a QualType rather than a TypeLoc.
+ const Attr *oldAttr = TL.getAttr();
+ const Attr *newAttr = oldAttr ? getDerived().TransformAttr(oldAttr) : nullptr;
+ if (oldAttr && !newAttr)
+ return QualType();
+
QualType result = TL.getType();
// FIXME: dependent operand expressions?
@@ -6074,26 +6121,20 @@ QualType TreeTransform<Derived>::TransformAttributedType(
// type sugar, and therefore cannot be diagnosed in any other way.
if (auto nullability = oldType->getImmediateNullability()) {
if (!modifiedType->canHaveNullability()) {
- SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer)
- << DiagNullabilityKind(*nullability, false) << modifiedType;
+ SemaRef.Diag(TL.getAttr()->getLocation(),
+ diag::err_nullability_nonpointer)
+ << DiagNullabilityKind(*nullability, false) << modifiedType;
return QualType();
}
}
- result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
+ result = SemaRef.Context.getAttributedType(TL.getAttrKind(),
modifiedType,
equivalentType);
}
AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
- newTL.setAttrNameLoc(TL.getAttrNameLoc());
- if (TL.hasAttrOperand())
- newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange());
- if (TL.hasAttrExprOperand())
- newTL.setAttrExprOperand(TL.getAttrExprOperand());
- else if (TL.hasAttrEnumOperand())
- newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc());
-
+ newTL.setAttr(newAttr);
return result;
}
@@ -6411,16 +6452,10 @@ TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
if (getDerived().AlwaysRebuild() || AnyChanged) {
// Rebuild the type.
Result = getDerived().RebuildObjCObjectType(
- BaseType,
- TL.getLocStart(),
- TL.getTypeArgsLAngleLoc(),
- NewTypeArgInfos,
- TL.getTypeArgsRAngleLoc(),
- TL.getProtocolLAngleLoc(),
- llvm::makeArrayRef(TL.getTypePtr()->qual_begin(),
- TL.getNumProtocols()),
- TL.getProtocolLocs(),
- TL.getProtocolRAngleLoc());
+ BaseType, TL.getBeginLoc(), TL.getTypeArgsLAngleLoc(), NewTypeArgInfos,
+ TL.getTypeArgsRAngleLoc(), TL.getProtocolLAngleLoc(),
+ llvm::makeArrayRef(TL.getTypePtr()->qual_begin(), TL.getNumProtocols()),
+ TL.getProtocolLocs(), TL.getProtocolRAngleLoc());
if (Result.isNull())
return QualType();
@@ -6486,7 +6521,9 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
bool SubStmtChanged = false;
SmallVector<Stmt*, 8> Statements;
for (auto *B : S->body()) {
- StmtResult Result = getDerived().TransformStmt(B);
+ StmtResult Result =
+ getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back());
+
if (Result.isInvalid()) {
// Immediately fail if this was a DeclStmt, since it's very
// likely that this will cause problems for future statements.
@@ -6656,7 +6693,7 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
if (Then.isInvalid())
return StmtError();
} else {
- Then = new (getSema().Context) NullStmt(S->getThen()->getLocStart());
+ Then = new (getSema().Context) NullStmt(S->getThen()->getBeginLoc());
}
// Transform the "else" branch.
@@ -6759,6 +6796,9 @@ TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
+ if (getSema().getLangOpts().OpenMP)
+ getSema().startOpenMPLoop();
+
// Transform the initialization statement
StmtResult Init = getDerived().TransformStmt(S->getInit());
if (Init.isInvalid())
@@ -6875,7 +6915,7 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
if (!getDerived().AlwaysRebuild() && !DeclChanged)
return S;
- return getDerived().RebuildDeclStmt(Decls, S->getStartLoc(), S->getEndLoc());
+ return getDerived().RebuildDeclStmt(Decls, S->getBeginLoc(), S->getEndLoc());
}
template<typename Derived>
@@ -7407,6 +7447,11 @@ StmtResult TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
+ StmtResult Init =
+ S->getInit() ? getDerived().TransformStmt(S->getInit()) : StmtResult();
+ if (Init.isInvalid())
+ return StmtError();
+
StmtResult Range = getDerived().TransformStmt(S->getRangeStmt());
if (Range.isInvalid())
return StmtError();
@@ -7440,6 +7485,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
StmtResult NewStmt = S;
if (getDerived().AlwaysRebuild() ||
+ Init.get() != S->getInit() ||
Range.get() != S->getRangeStmt() ||
Begin.get() != S->getBeginStmt() ||
End.get() != S->getEndStmt() ||
@@ -7447,7 +7493,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
Inc.get() != S->getInc() ||
LoopVar.get() != S->getLoopVarStmt()) {
NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
- S->getCoawaitLoc(),
+ S->getCoawaitLoc(), Init.get(),
S->getColonLoc(), Range.get(),
Begin.get(), End.get(),
Cond.get(),
@@ -7465,7 +7511,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
// it now so we have a new statement to attach the body to.
if (Body.get() != S->getBody() && NewStmt.get() == S) {
NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
- S->getCoawaitLoc(),
+ S->getCoawaitLoc(), Init.get(),
S->getColonLoc(), Range.get(),
Begin.get(), End.get(),
Cond.get(),
@@ -7708,7 +7754,7 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
return getDerived().RebuildOMPExecutableDirective(
D->getDirectiveKind(), DirName, CancelRegion, TClauses,
- AssociatedStmt.get(), D->getLocStart(), D->getLocEnd());
+ AssociatedStmt.get(), D->getBeginLoc(), D->getEndLoc());
}
template <typename Derived>
@@ -7716,7 +7762,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7727,7 +7773,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7738,7 +7784,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7749,7 +7795,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPForSimdDirective(OMPForSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_for_simd, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7760,7 +7806,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7771,7 +7817,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7782,7 +7828,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7793,7 +7839,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPMasterDirective(OMPMasterDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_master, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7803,7 +7849,7 @@ template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPCriticalDirective(OMPCriticalDirective *D) {
getDerived().getSema().StartOpenMPDSABlock(
- OMPD_critical, D->getDirectiveName(), nullptr, D->getLocStart());
+ OMPD_critical, D->getDirectiveName(), nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7814,7 +7860,7 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelForDirective(
OMPParallelForDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_for, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7825,7 +7871,7 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelForSimdDirective(
OMPParallelForSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_for_simd, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7836,7 +7882,7 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelSectionsDirective(
OMPParallelSectionsDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_sections, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7847,7 +7893,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPTaskDirective(OMPTaskDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_task, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7858,7 +7904,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskyieldDirective(
OMPTaskyieldDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_taskyield, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7869,7 +7915,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPBarrierDirective(OMPBarrierDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_barrier, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7880,7 +7926,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_taskwait, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7891,7 +7937,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskgroupDirective(
OMPTaskgroupDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_taskgroup, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7902,7 +7948,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPFlushDirective(OMPFlushDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_flush, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7913,7 +7959,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPOrderedDirective(OMPOrderedDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_ordered, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7924,7 +7970,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPAtomicDirective(OMPAtomicDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_atomic, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7935,7 +7981,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPTargetDirective(OMPTargetDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7946,7 +7992,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetDataDirective(
OMPTargetDataDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_data, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7957,7 +8003,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetEnterDataDirective(
OMPTargetEnterDataDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_enter_data, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7968,7 +8014,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetExitDataDirective(
OMPTargetExitDataDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_exit_data, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7979,7 +8025,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetParallelDirective(
OMPTargetParallelDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_parallel, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -7990,7 +8036,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetParallelForDirective(
OMPTargetParallelForDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_parallel_for, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8001,7 +8047,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetUpdateDirective(
OMPTargetUpdateDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_update, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8012,7 +8058,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_teams, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8023,7 +8069,7 @@ StmtResult TreeTransform<Derived>::TransformOMPCancellationPointDirective(
OMPCancellationPointDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_cancellation_point, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8034,7 +8080,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_cancel, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8045,7 +8091,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8056,7 +8102,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTaskLoopSimdDirective(
OMPTaskLoopSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop_simd, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8067,7 +8113,7 @@ StmtResult TreeTransform<Derived>::TransformOMPDistributeDirective(
OMPDistributeDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_distribute, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8078,7 +8124,7 @@ StmtResult TreeTransform<Derived>::TransformOMPDistributeParallelForDirective(
OMPDistributeParallelForDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(
- OMPD_distribute_parallel_for, DirName, nullptr, D->getLocStart());
+ OMPD_distribute_parallel_for, DirName, nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8090,7 +8136,7 @@ TreeTransform<Derived>::TransformOMPDistributeParallelForSimdDirective(
OMPDistributeParallelForSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(
- OMPD_distribute_parallel_for_simd, DirName, nullptr, D->getLocStart());
+ OMPD_distribute_parallel_for_simd, DirName, nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8101,7 +8147,7 @@ StmtResult TreeTransform<Derived>::TransformOMPDistributeSimdDirective(
OMPDistributeSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_distribute_simd, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8111,9 +8157,8 @@ template <typename Derived>
StmtResult TreeTransform<Derived>::TransformOMPTargetParallelForSimdDirective(
OMPTargetParallelForSimdDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_target_parallel_for_simd,
- DirName, nullptr,
- D->getLocStart());
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_target_parallel_for_simd, DirName, nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8124,7 +8169,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetSimdDirective(
OMPTargetSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_simd, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8135,7 +8180,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeDirective(
OMPTeamsDistributeDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_teams_distribute, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8146,7 +8191,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeSimdDirective(
OMPTeamsDistributeSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(
- OMPD_teams_distribute_simd, DirName, nullptr, D->getLocStart());
+ OMPD_teams_distribute_simd, DirName, nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8157,7 +8202,8 @@ StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeParallelForSimdDir
OMPTeamsDistributeParallelForSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(
- OMPD_teams_distribute_parallel_for_simd, DirName, nullptr, D->getLocStart());
+ OMPD_teams_distribute_parallel_for_simd, DirName, nullptr,
+ D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8167,8 +8213,8 @@ template <typename Derived>
StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeParallelForDirective(
OMPTeamsDistributeParallelForDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_teams_distribute_parallel_for,
- DirName, nullptr, D->getLocStart());
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_teams_distribute_parallel_for, DirName, nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8179,7 +8225,7 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetTeamsDirective(
OMPTargetTeamsDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_target_teams, DirName,
- nullptr, D->getLocStart());
+ nullptr, D->getBeginLoc());
auto Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8189,8 +8235,8 @@ template <typename Derived>
StmtResult TreeTransform<Derived>::TransformOMPTargetTeamsDistributeDirective(
OMPTargetTeamsDistributeDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_target_teams_distribute,
- DirName, nullptr, D->getLocStart());
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_target_teams_distribute, DirName, nullptr, D->getBeginLoc());
auto Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8203,7 +8249,7 @@ TreeTransform<Derived>::TransformOMPTargetTeamsDistributeParallelForDirective(
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(
OMPD_target_teams_distribute_parallel_for, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
auto Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8216,7 +8262,7 @@ StmtResult TreeTransform<Derived>::
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(
OMPD_target_teams_distribute_parallel_for_simd, DirName, nullptr,
- D->getLocStart());
+ D->getBeginLoc());
auto Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8228,7 +8274,7 @@ TreeTransform<Derived>::TransformOMPTargetTeamsDistributeSimdDirective(
OMPTargetTeamsDistributeSimdDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(
- OMPD_target_teams_distribute_simd, DirName, nullptr, D->getLocStart());
+ OMPD_target_teams_distribute_simd, DirName, nullptr, D->getBeginLoc());
auto Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -8244,8 +8290,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
if (Cond.isInvalid())
return nullptr;
return getDerived().RebuildOMPIfClause(
- C->getNameModifier(), Cond.get(), C->getLocStart(), C->getLParenLoc(),
- C->getNameModifierLoc(), C->getColonLoc(), C->getLocEnd());
+ C->getNameModifier(), Cond.get(), C->getBeginLoc(), C->getLParenLoc(),
+ C->getNameModifierLoc(), C->getColonLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8253,8 +8299,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFinalClause(OMPFinalClause *C) {
ExprResult Cond = getDerived().TransformExpr(C->getCondition());
if (Cond.isInvalid())
return nullptr;
- return getDerived().RebuildOMPFinalClause(Cond.get(), C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPFinalClause(Cond.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8264,7 +8310,7 @@ TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {
if (NumThreads.isInvalid())
return nullptr;
return getDerived().RebuildOMPNumThreadsClause(
- NumThreads.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ NumThreads.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8274,7 +8320,7 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPSafelenClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8284,7 +8330,7 @@ TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPSimdlenClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8294,23 +8340,23 @@ TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPCollapseClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
return getDerived().RebuildOMPDefaultClause(
- C->getDefaultKind(), C->getDefaultKindKwLoc(), C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ C->getDefaultKind(), C->getDefaultKindKwLoc(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPProcBindClause(OMPProcBindClause *C) {
return getDerived().RebuildOMPProcBindClause(
- C->getProcBindKind(), C->getProcBindKindKwLoc(), C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ C->getProcBindKind(), C->getProcBindKindKwLoc(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8321,9 +8367,9 @@ TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) {
return nullptr;
return getDerived().RebuildOMPScheduleClause(
C->getFirstScheduleModifier(), C->getSecondScheduleModifier(),
- C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
+ C->getScheduleKind(), E.get(), C->getBeginLoc(), C->getLParenLoc(),
C->getFirstScheduleModifierLoc(), C->getSecondScheduleModifierLoc(),
- C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
+ C->getScheduleKindLoc(), C->getCommaLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8335,7 +8381,7 @@ TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) {
if (E.isInvalid())
return nullptr;
}
- return getDerived().RebuildOMPOrderedClause(C->getLocStart(), C->getLocEnd(),
+ return getDerived().RebuildOMPOrderedClause(C->getBeginLoc(), C->getEndLoc(),
C->getLParenLoc(), E.get());
}
@@ -8414,6 +8460,39 @@ TreeTransform<Derived>::TransformOMPNogroupClause(OMPNogroupClause *C) {
}
template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPUnifiedAddressClause(
+ OMPUnifiedAddressClause *C) {
+ llvm_unreachable("unified_address clause cannot appear in dependent context");
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPUnifiedSharedMemoryClause(
+ OMPUnifiedSharedMemoryClause *C) {
+ llvm_unreachable(
+ "unified_shared_memory clause cannot appear in dependent context");
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPReverseOffloadClause(
+ OMPReverseOffloadClause *C) {
+ llvm_unreachable("reverse_offload clause cannot appear in dependent context");
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPDynamicAllocatorsClause(
+ OMPDynamicAllocatorsClause *C) {
+ llvm_unreachable(
+ "dynamic_allocators clause cannot appear in dependent context");
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPAtomicDefaultMemOrderClause(
+ OMPAtomicDefaultMemOrderClause *C) {
+ llvm_unreachable(
+ "atomic_default_mem_order clause cannot appear in dependent context");
+}
+
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
@@ -8425,7 +8504,7 @@ TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPPrivateClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8440,7 +8519,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPFirstprivateClause(
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPFirstprivateClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8455,7 +8534,7 @@ TreeTransform<Derived>::TransformOMPLastprivateClause(OMPLastprivateClause *C) {
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPLastprivateClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8469,8 +8548,8 @@ TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
return nullptr;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPSharedClause(Vars, C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPSharedClause(Vars, C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8516,8 +8595,8 @@ TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) {
UnresolvedReductions.push_back(nullptr);
}
return getDerived().RebuildOMPReductionClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
- C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(),
+ C->getEndLoc(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
}
template <typename Derived>
@@ -8561,8 +8640,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause(
UnresolvedReductions.push_back(nullptr);
}
return getDerived().RebuildOMPTaskReductionClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
- C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(),
+ C->getEndLoc(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
}
template <typename Derived>
@@ -8606,8 +8685,8 @@ TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) {
UnresolvedReductions.push_back(nullptr);
}
return getDerived().RebuildOMPInReductionClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
- C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(),
+ C->getEndLoc(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
}
template <typename Derived>
@@ -8625,8 +8704,8 @@ TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
if (Step.isInvalid())
return nullptr;
return getDerived().RebuildOMPLinearClause(
- Vars, Step.get(), C->getLocStart(), C->getLParenLoc(), C->getModifier(),
- C->getModifierLoc(), C->getColonLoc(), C->getLocEnd());
+ Vars, Step.get(), C->getBeginLoc(), C->getLParenLoc(), C->getModifier(),
+ C->getModifierLoc(), C->getColonLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8644,8 +8723,8 @@ TreeTransform<Derived>::TransformOMPAlignedClause(OMPAlignedClause *C) {
if (Alignment.isInvalid())
return nullptr;
return getDerived().RebuildOMPAlignedClause(
- Vars, Alignment.get(), C->getLocStart(), C->getLParenLoc(),
- C->getColonLoc(), C->getLocEnd());
+ Vars, Alignment.get(), C->getBeginLoc(), C->getLParenLoc(),
+ C->getColonLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8659,8 +8738,8 @@ TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
return nullptr;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPCopyinClause(Vars, C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPCopyinClause(Vars, C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8675,7 +8754,7 @@ TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause *C) {
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPCopyprivateClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8688,8 +8767,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) {
return nullptr;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPFlushClause(Vars, C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPFlushClause(Vars, C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8705,7 +8784,7 @@ TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
}
return getDerived().RebuildOMPDependClause(
C->getDependencyKind(), C->getDependencyLoc(), C->getColonLoc(), Vars,
- C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8714,8 +8793,8 @@ TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) {
ExprResult E = getDerived().TransformExpr(C->getDevice());
if (E.isInvalid())
return nullptr;
- return getDerived().RebuildOMPDeviceClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPDeviceClause(E.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8729,9 +8808,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) {
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPMapClause(
- C->getMapTypeModifier(), C->getMapType(), C->isImplicitMapType(),
- C->getMapLoc(), C->getColonLoc(), Vars, C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), C->getMapType(),
+ C->isImplicitMapType(), C->getMapLoc(), C->getColonLoc(), Vars,
+ C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8741,7 +8820,7 @@ TreeTransform<Derived>::TransformOMPNumTeamsClause(OMPNumTeamsClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPNumTeamsClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8751,7 +8830,7 @@ TreeTransform<Derived>::TransformOMPThreadLimitClause(OMPThreadLimitClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPThreadLimitClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8761,7 +8840,7 @@ TreeTransform<Derived>::TransformOMPPriorityClause(OMPPriorityClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPPriorityClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8771,7 +8850,7 @@ TreeTransform<Derived>::TransformOMPGrainsizeClause(OMPGrainsizeClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPGrainsizeClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8781,7 +8860,7 @@ TreeTransform<Derived>::TransformOMPNumTasksClause(OMPNumTasksClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPNumTasksClause(
- E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8789,8 +8868,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) {
ExprResult E = getDerived().TransformExpr(C->getHint());
if (E.isInvalid())
return nullptr;
- return getDerived().RebuildOMPHintClause(E.get(), C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPHintClause(E.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8800,8 +8879,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPDistScheduleClause(
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPDistScheduleClause(
- C->getDistScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
- C->getDistScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
+ C->getDistScheduleKind(), E.get(), C->getBeginLoc(), C->getLParenLoc(),
+ C->getDistScheduleKindLoc(), C->getCommaLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8820,8 +8899,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPToClause(OMPToClause *C) {
return 0;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPToClause(Vars, C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPToClause(Vars, C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8834,8 +8913,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPFromClause(OMPFromClause *C) {
return 0;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPFromClause(Vars, C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPFromClause(Vars, C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8850,7 +8929,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPUseDevicePtrClause(
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPUseDevicePtrClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -8865,7 +8944,7 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPIsDevicePtrClause(
- Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+ Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
//===----------------------------------------------------------------------===//
@@ -8873,12 +8952,18 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
//===----------------------------------------------------------------------===//
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformConstantExpr(ConstantExpr *E) {
+ return TransformExpr(E->getSubExpr());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return E;
return getDerived().RebuildPredefinedExpr(E->getLocation(),
- E->getIdentType());
+ E->getIdentKind());
}
template<typename Derived>
@@ -8973,7 +9058,7 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) {
if (FunctionDecl *FD = E->getDirectCallee())
- SemaRef.MarkFunctionReferenced(E->getLocStart(), FD);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), FD);
return SemaRef.MaybeBindToTemporary(E);
}
@@ -9227,10 +9312,9 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
RHS.get() == E->getRHS())
return E;
- return getDerived().RebuildArraySubscriptExpr(LHS.get(),
- /*FIXME:*/E->getLHS()->getLocStart(),
- RHS.get(),
- E->getRBracketLoc());
+ return getDerived().RebuildArraySubscriptExpr(
+ LHS.get(),
+ /*FIXME:*/ E->getLHS()->getBeginLoc(), RHS.get(), E->getRBracketLoc());
}
template <typename Derived>
@@ -9259,7 +9343,7 @@ TreeTransform<Derived>::TransformOMPArraySectionExpr(OMPArraySectionExpr *E) {
return E;
return getDerived().RebuildOMPArraySectionExpr(
- Base.get(), E->getBase()->getLocEnd(), LowerBound.get(), E->getColonLoc(),
+ Base.get(), E->getBase()->getEndLoc(), LowerBound.get(), E->getColonLoc(),
Length.get(), E->getRBracketLoc());
}
@@ -9512,9 +9596,9 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
// type-as-written, but that's okay, because it should always be
// derivable from the initializer.
- return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT,
- /*FIXME:*/E->getInitializer()->getLocEnd(),
- Init.get());
+ return getDerived().RebuildCompoundLiteralExpr(
+ E->getLParenLoc(), NewT,
+ /*FIXME:*/ E->getInitializer()->getEndLoc(), Init.get());
}
template<typename Derived>
@@ -9530,7 +9614,7 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
// FIXME: Bad source location
SourceLocation FakeOperatorLoc =
- SemaRef.getLocForEndOfToken(E->getBase()->getLocEnd());
+ SemaRef.getLocForEndOfToken(E->getBase()->getEndLoc());
return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc,
E->getAccessorLoc(),
E->getAccessor());
@@ -9544,6 +9628,9 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
bool InitChanged = false;
+ EnterExpressionEvaluationContext Context(
+ getSema(), EnterExpressionEvaluationContext::InitList);
+
SmallVector<Expr*, 4> Inits;
if (getDerived().TransformExprs(E->getInits(), E->getNumInits(), false,
Inits, &InitChanged))
@@ -9676,7 +9763,7 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformImplicitValueInitExpr(
ImplicitValueInitExpr *E) {
- TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+ TemporaryBase Rebase(*this, E->getBeginLoc(), DeclarationName());
// FIXME: Will we ever have proper type location here? Will we actually
// need to transform the type?
@@ -9818,7 +9905,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
// FIXME: Poor location information
SourceLocation FakeLParenLoc = SemaRef.getLocForEndOfToken(
- static_cast<Expr *>(Object.get())->getLocEnd());
+ static_cast<Expr *>(Object.get())->getEndLoc());
// Transform the call arguments.
SmallVector<Expr*, 8> Args;
@@ -9826,9 +9913,8 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
Args))
return ExprError();
- return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc,
- Args,
- E->getLocEnd());
+ return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc, Args,
+ E->getEndLoc());
}
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
@@ -10008,10 +10094,8 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
TInfo == E->getTypeOperandSourceInfo())
return E;
- return getDerived().RebuildCXXTypeidExpr(E->getType(),
- E->getLocStart(),
- TInfo,
- E->getLocEnd());
+ return getDerived().RebuildCXXTypeidExpr(E->getType(), E->getBeginLoc(),
+ TInfo, E->getEndLoc());
}
// We don't know whether the subexpression is potentially evaluated until
@@ -10030,10 +10114,8 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
SubExpr.get() == E->getExprOperand())
return E;
- return getDerived().RebuildCXXTypeidExpr(E->getType(),
- E->getLocStart(),
- SubExpr.get(),
- E->getLocEnd());
+ return getDerived().RebuildCXXTypeidExpr(E->getType(), E->getBeginLoc(),
+ SubExpr.get(), E->getEndLoc());
}
template<typename Derived>
@@ -10049,10 +10131,8 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
TInfo == E->getTypeOperandSourceInfo())
return E;
- return getDerived().RebuildCXXUuidofExpr(E->getType(),
- E->getLocStart(),
- TInfo,
- E->getLocEnd());
+ return getDerived().RebuildCXXUuidofExpr(E->getType(), E->getBeginLoc(),
+ TInfo, E->getEndLoc());
}
EnterExpressionEvaluationContext Unevaluated(
@@ -10066,10 +10146,8 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
SubExpr.get() == E->getExprOperand())
return E;
- return getDerived().RebuildCXXUuidofExpr(E->getType(),
- E->getLocStart(),
- SubExpr.get(),
- E->getLocEnd());
+ return getDerived().RebuildCXXUuidofExpr(E->getType(), E->getBeginLoc(),
+ SubExpr.get(), E->getEndLoc());
}
template<typename Derived>
@@ -10092,11 +10170,11 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
if (!getDerived().AlwaysRebuild() && T == E->getType()) {
// Make sure that we capture 'this'.
- getSema().CheckCXXThisCapture(E->getLocStart());
+ getSema().CheckCXXThisCapture(E->getBeginLoc());
return E;
}
- return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit());
+ return getDerived().RebuildCXXThisExpr(E->getBeginLoc(), T, E->isImplicit());
}
template<typename Derived>
@@ -10117,9 +10195,8 @@ TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
- ParmVarDecl *Param
- = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getLocStart(),
- E->getParam()));
+ ParmVarDecl *Param = cast_or_null<ParmVarDecl>(
+ getDerived().TransformDecl(E->getBeginLoc(), E->getParam()));
if (!Param)
return ExprError();
@@ -10133,9 +10210,8 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
- FieldDecl *Field
- = cast_or_null<FieldDecl>(getDerived().TransformDecl(E->getLocStart(),
- E->getField()));
+ FieldDecl *Field = cast_or_null<FieldDecl>(
+ getDerived().TransformDecl(E->getBeginLoc(), E->getField()));
if (!Field)
return ExprError();
@@ -10196,8 +10272,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
FunctionDecl *OperatorNew = nullptr;
if (E->getOperatorNew()) {
OperatorNew = cast_or_null<FunctionDecl>(
- getDerived().TransformDecl(E->getLocStart(),
- E->getOperatorNew()));
+ getDerived().TransformDecl(E->getBeginLoc(), E->getOperatorNew()));
if (!OperatorNew)
return ExprError();
}
@@ -10205,8 +10280,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
FunctionDecl *OperatorDelete = nullptr;
if (E->getOperatorDelete()) {
OperatorDelete = cast_or_null<FunctionDecl>(
- getDerived().TransformDecl(E->getLocStart(),
- E->getOperatorDelete()));
+ getDerived().TransformDecl(E->getBeginLoc(), E->getOperatorDelete()));
if (!OperatorDelete)
return ExprError();
}
@@ -10221,9 +10295,9 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
// Mark any declarations we need as referenced.
// FIXME: instantiation-specific.
if (OperatorNew)
- SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), OperatorNew);
if (OperatorDelete)
- SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), OperatorDelete);
if (E->isArray() && !E->getAllocatedType()->isDependentType()) {
QualType ElementType
@@ -10231,7 +10305,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
if (const RecordType *RecordT = ElementType->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordT->getDecl());
if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) {
- SemaRef.MarkFunctionReferenced(E->getLocStart(), Destructor);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Destructor);
}
}
}
@@ -10253,7 +10327,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
= dyn_cast<ConstantArrayType>(ArrayT)) {
ArraySize = IntegerLiteral::Create(SemaRef.Context, ConsArrayT->getSize(),
SemaRef.Context.getSizeType(),
- /*FIXME:*/ E->getLocStart());
+ /*FIXME:*/ E->getBeginLoc());
AllocType = ConsArrayT->getElementType();
} else if (const DependentSizedArrayType *DepArrayT
= dyn_cast<DependentSizedArrayType>(ArrayT)) {
@@ -10264,17 +10338,11 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
}
}
- return getDerived().RebuildCXXNewExpr(E->getLocStart(),
- E->isGlobalNew(),
- /*FIXME:*/E->getLocStart(),
- PlacementArgs,
- /*FIXME:*/E->getLocStart(),
- E->getTypeIdParens(),
- AllocType,
- AllocTypeInfo,
- ArraySize.get(),
- E->getDirectInitRange(),
- NewInit.get());
+ return getDerived().RebuildCXXNewExpr(
+ E->getBeginLoc(), E->isGlobalNew(),
+ /*FIXME:*/ E->getBeginLoc(), PlacementArgs,
+ /*FIXME:*/ E->getBeginLoc(), E->getTypeIdParens(), AllocType,
+ AllocTypeInfo, ArraySize.get(), E->getDirectInitRange(), NewInit.get());
}
template<typename Derived>
@@ -10288,8 +10356,7 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
FunctionDecl *OperatorDelete = nullptr;
if (E->getOperatorDelete()) {
OperatorDelete = cast_or_null<FunctionDecl>(
- getDerived().TransformDecl(E->getLocStart(),
- E->getOperatorDelete()));
+ getDerived().TransformDecl(E->getBeginLoc(), E->getOperatorDelete()));
if (!OperatorDelete)
return ExprError();
}
@@ -10300,14 +10367,14 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
// Mark any declarations we need as referenced.
// FIXME: instantiation-specific.
if (OperatorDelete)
- SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), OperatorDelete);
if (!E->getArgument()->isTypeDependent()) {
QualType Destroyed = SemaRef.Context.getBaseElementType(
E->getDestroyedType());
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- SemaRef.MarkFunctionReferenced(E->getLocStart(),
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(),
SemaRef.LookupDestructor(Record));
}
}
@@ -10315,10 +10382,8 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
return E;
}
- return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
- E->isGlobalDelete(),
- E->isArrayForm(),
- Operand.get());
+ return getDerived().RebuildCXXDeleteExpr(
+ E->getBeginLoc(), E->isGlobalDelete(), E->isArrayForm(), Operand.get());
}
template<typename Derived>
@@ -10651,10 +10716,8 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
if (!getDerived().AlwaysRebuild() && !ArgChanged)
return E;
- return getDerived().RebuildTypeTrait(E->getTrait(),
- E->getLocStart(),
- Args,
- E->getLocEnd());
+ return getDerived().RebuildTypeTrait(E->getTrait(), E->getBeginLoc(), Args,
+ E->getEndLoc());
}
template<typename Derived>
@@ -10680,11 +10743,8 @@ TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
return E;
}
- return getDerived().RebuildArrayTypeTrait(E->getTrait(),
- E->getLocStart(),
- T,
- SubExpr.get(),
- E->getLocEnd());
+ return getDerived().RebuildArrayTypeTrait(E->getTrait(), E->getBeginLoc(), T,
+ SubExpr.get(), E->getEndLoc());
}
template<typename Derived>
@@ -10702,8 +10762,8 @@ TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) {
return E;
}
- return getDerived().RebuildExpressionTrait(
- E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd());
+ return getDerived().RebuildExpressionTrait(E->getTrait(), E->getBeginLoc(),
+ SubExpr.get(), E->getEndLoc());
}
template <typename Derived>
@@ -10789,24 +10849,27 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
!E->isListInitialization())
return getDerived().TransformExpr(E->getArg(0));
- TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+ TemporaryBase Rebase(*this, /*FIXME*/ E->getBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
return ExprError();
- CXXConstructorDecl *Constructor
- = cast_or_null<CXXConstructorDecl>(
- getDerived().TransformDecl(E->getLocStart(),
- E->getConstructor()));
+ CXXConstructorDecl *Constructor = cast_or_null<CXXConstructorDecl>(
+ getDerived().TransformDecl(E->getBeginLoc(), E->getConstructor()));
if (!Constructor)
return ExprError();
bool ArgumentChanged = false;
SmallVector<Expr*, 8> Args;
- if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
- &ArgumentChanged))
- return ExprError();
+ {
+ EnterExpressionEvaluationContext Context(
+ getSema(), EnterExpressionEvaluationContext::InitList,
+ E->isListInitialization());
+ if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
+ &ArgumentChanged))
+ return ExprError();
+ }
if (!getDerived().AlwaysRebuild() &&
T == E->getType() &&
@@ -10814,19 +10877,15 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
!ArgumentChanged) {
// Mark the constructor as referenced.
// FIXME: Instantiation-specific
- SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Constructor);
return E;
}
- return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(),
- Constructor,
- E->isElidable(), Args,
- E->hadMultipleCandidates(),
- E->isListInitialization(),
- E->isStdInitListInitialization(),
- E->requiresZeroInitialization(),
- E->getConstructionKind(),
- E->getParenOrBraceRange());
+ return getDerived().RebuildCXXConstructExpr(
+ T, /*FIXME:*/ E->getBeginLoc(), Constructor, E->isElidable(), Args,
+ E->hadMultipleCandidates(), E->isListInitialization(),
+ E->isStdInitListInitialization(), E->requiresZeroInitialization(),
+ E->getConstructionKind(), E->getParenOrBraceRange());
}
template<typename Derived>
@@ -10837,7 +10896,7 @@ ExprResult TreeTransform<Derived>::TransformCXXInheritedCtorInitExpr(
return ExprError();
CXXConstructorDecl *Constructor = cast_or_null<CXXConstructorDecl>(
- getDerived().TransformDecl(E->getLocStart(), E->getConstructor()));
+ getDerived().TransformDecl(E->getBeginLoc(), E->getConstructor()));
if (!Constructor)
return ExprError();
@@ -10846,7 +10905,7 @@ ExprResult TreeTransform<Derived>::TransformCXXInheritedCtorInitExpr(
Constructor == E->getConstructor()) {
// Mark the constructor as referenced.
// FIXME: Instantiation-specific
- SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Constructor);
return E;
}
@@ -10885,26 +10944,29 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
if (!T)
return ExprError();
- CXXConstructorDecl *Constructor
- = cast_or_null<CXXConstructorDecl>(
- getDerived().TransformDecl(E->getLocStart(),
- E->getConstructor()));
+ CXXConstructorDecl *Constructor = cast_or_null<CXXConstructorDecl>(
+ getDerived().TransformDecl(E->getBeginLoc(), E->getConstructor()));
if (!Constructor)
return ExprError();
bool ArgumentChanged = false;
SmallVector<Expr*, 8> Args;
Args.reserve(E->getNumArgs());
- if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
- &ArgumentChanged))
- return ExprError();
+ {
+ EnterExpressionEvaluationContext Context(
+ getSema(), EnterExpressionEvaluationContext::InitList,
+ E->isListInitialization());
+ if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
+ &ArgumentChanged))
+ return ExprError();
+ }
if (!getDerived().AlwaysRebuild() &&
T == E->getTypeSourceInfo() &&
Constructor == E->getConstructor() &&
!ArgumentChanged) {
// FIXME: Instantiation-specific
- SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
+ SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Constructor);
return SemaRef.MaybeBindToTemporary(E);
}
@@ -10912,7 +10974,7 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
// prepared to handle list-initialization without a child InitListExpr.
SourceLocation LParenLoc = T->getTypeLoc().getEndLoc();
return getDerived().RebuildCXXTemporaryObjectExpr(
- T, LParenLoc, Args, E->getLocEnd(),
+ T, LParenLoc, Args, E->getEndLoc(),
/*ListInitialization=*/LParenLoc.isInvalid());
}
@@ -10970,7 +11032,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
SmallVector<QualType, 4> ExceptionStorage;
TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
QualType NewCallOpType = TransformFunctionProtoType(
- NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0,
+ NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
ExceptionStorage, Changed);
@@ -10996,7 +11058,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
// Build the call operator.
CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
Class, E->getIntroducerRange(), NewCallOpTSI,
- E->getCallOperator()->getLocEnd(),
+ E->getCallOperator()->getEndLoc(),
NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
E->getCallOperator()->isConstexpr());
@@ -11160,7 +11222,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
if (Body.isInvalid()) {
SavedContext.pop();
- getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr,
+ getSema().ActOnLambdaError(E->getBeginLoc(), /*CurScope=*/nullptr,
/*IsInstantiation=*/true);
return ExprError();
}
@@ -11173,7 +11235,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
/*IsInstantiation*/ true);
SavedContext.pop();
- return getSema().BuildLambdaExpr(E->getLocStart(), Body.get()->getLocEnd(),
+ return getSema().BuildLambdaExpr(E->getBeginLoc(), Body.get()->getEndLoc(),
&LSICopy);
}
@@ -11189,9 +11251,14 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
bool ArgumentChanged = false;
SmallVector<Expr*, 8> Args;
Args.reserve(E->arg_size());
- if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args,
- &ArgumentChanged))
- return ExprError();
+ {
+ EnterExpressionEvaluationContext Context(
+ getSema(), EnterExpressionEvaluationContext::InitList,
+ E->isListInitialization());
+ if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args,
+ &ArgumentChanged))
+ return ExprError();
+ }
if (!getDerived().AlwaysRebuild() &&
T == E->getTypeSourceInfo() &&
@@ -11620,8 +11687,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
return E;
return getDerived().RebuildCXXFoldExpr(
- E->getLocStart(), LHS.get(), E->getOperator(), E->getEllipsisLoc(),
- RHS.get(), E->getLocEnd());
+ E->getBeginLoc(), LHS.get(), E->getOperator(), E->getEllipsisLoc(),
+ RHS.get(), E->getEndLoc());
}
// The transform has determined that we should perform an elementwise
@@ -11641,8 +11708,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
return true;
Result = getDerived().RebuildCXXFoldExpr(
- E->getLocStart(), Out.get(), E->getOperator(), E->getEllipsisLoc(),
- Result.get(), E->getLocEnd());
+ E->getBeginLoc(), Out.get(), E->getOperator(), E->getEllipsisLoc(),
+ Result.get(), E->getEndLoc());
if (Result.isInvalid())
return true;
}
@@ -11657,11 +11724,9 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
if (Out.get()->containsUnexpandedParameterPack()) {
// We still have a pack; retain a pack expansion for this slice.
Result = getDerived().RebuildCXXFoldExpr(
- E->getLocStart(),
- LeftFold ? Result.get() : Out.get(),
+ E->getBeginLoc(), LeftFold ? Result.get() : Out.get(),
E->getOperator(), E->getEllipsisLoc(),
- LeftFold ? Out.get() : Result.get(),
- E->getLocEnd());
+ LeftFold ? Out.get() : Result.get(), E->getEndLoc());
} else if (Result.isUsable()) {
// We've got down to a single element; build a binary operator.
Result = getDerived().RebuildBinaryOperator(
@@ -11685,9 +11750,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
return true;
Result = getDerived().RebuildCXXFoldExpr(
- E->getLocStart(), Result.get(),
- E->getOperator(), E->getEllipsisLoc(),
- Out.get(), E->getLocEnd());
+ E->getBeginLoc(), Result.get(), E->getOperator(), E->getEllipsisLoc(),
+ Out.get(), E->getEndLoc());
if (Result.isInvalid())
return true;
}
@@ -11775,13 +11839,11 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
bool RetainExpansion = false;
Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions;
Optional<unsigned> NumExpansions = OrigNumExpansions;
- SourceRange PatternRange(OrigElement.Key->getLocStart(),
- OrigElement.Value->getLocEnd());
- if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc,
- PatternRange,
- Unexpanded,
- Expand, RetainExpansion,
- NumExpansions))
+ SourceRange PatternRange(OrigElement.Key->getBeginLoc(),
+ OrigElement.Value->getEndLoc());
+ if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc,
+ PatternRange, Unexpanded, Expand,
+ RetainExpansion, NumExpansions))
return ExprError();
if (!Expand) {
@@ -12651,9 +12713,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
if (Op == OO_Subscript) {
if (!First->getType()->isOverloadableType() &&
!Second->getType()->isOverloadableType())
- return getSema().CreateBuiltinArraySubscriptExpr(First,
- Callee->getLocStart(),
- Second, OpLoc);
+ return getSema().CreateBuiltinArraySubscriptExpr(
+ First, Callee->getBeginLoc(), Second, OpLoc);
} else if (Op == OO_Arrow) {
// -> is never a builtin operation.
return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc);
@@ -12727,8 +12788,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
RBrace = SourceLocation::getFromRawEncoding(
NameLoc.CXXOperatorName.EndOpNameLoc);
} else {
- LBrace = Callee->getLocStart();
- RBrace = OpLoc;
+ LBrace = Callee->getBeginLoc();
+ RBrace = OpLoc;
}
return SemaRef.CreateOverloadedArraySubscriptExpr(LBrace, RBrace,
@@ -12799,7 +12860,7 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) {
- SourceLocation Loc = S->getLocStart();
+ SourceLocation Loc = S->getBeginLoc();
CapturedDecl *CD = S->getCapturedDecl();
unsigned NumParams = CD->getNumParams();
unsigned ContextParamPos = CD->getContextParamPosition();
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index da482717f450..ca826d83d471 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/lib/Serialization/ASTCommon.cpp
@@ -213,6 +213,11 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
ID = PREDEF_TYPE_##Id##_ID; \
break;
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id: \
+ ID = PREDEF_TYPE_##Id##_ID; \
+ break;
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
ID = PREDEF_TYPE_SAMPLER_ID;
break;
@@ -383,6 +388,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::ClassScopeFunctionSpecialization:
case Decl::Import:
case Decl::OMPThreadPrivate:
+ case Decl::OMPRequires:
case Decl::OMPCapturedExpr:
case Decl::OMPDeclareReduction:
case Decl::BuiltinTemplate:
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 723839ff62bf..e0b2b24a0d32 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -61,7 +61,6 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/Version.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/MacroInfo.h"
@@ -81,6 +80,7 @@
#include "clang/Serialization/Module.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/ModuleManager.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
@@ -396,8 +396,8 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
ExistingTargetOpts.FeaturesAsWritten.end());
SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
TargetOpts.FeaturesAsWritten.end());
- llvm::sort(ExistingFeatures.begin(), ExistingFeatures.end());
- llvm::sort(ReadFeatures.begin(), ReadFeatures.end());
+ llvm::sort(ExistingFeatures);
+ llvm::sort(ReadFeatures);
// We compute the set difference in both directions explicitly so that we can
// diagnose the differences differently.
@@ -908,7 +908,7 @@ static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II,
(IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) ||
II.hasRevertedTokenIDToIdentifier() ||
(!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) &&
- II.getFETokenInfo<void>());
+ II.getFETokenInfo());
}
static bool readBit(unsigned &Bits) {
@@ -3780,22 +3780,15 @@ void ASTReader::makeModuleVisible(Module *Mod,
/// visible.
void ASTReader::mergeDefinitionVisibility(NamedDecl *Def,
NamedDecl *MergedDef) {
- // FIXME: This doesn't correctly handle the case where MergedDef is visible
- // in modules other than its owning module. We should instead give the
- // ASTContext a list of merged definitions for Def.
if (Def->isHidden()) {
// If MergedDef is visible or becomes visible, make the definition visible.
if (!MergedDef->isHidden())
Def->setVisibleDespiteOwningModule();
- else if (getContext().getLangOpts().ModulesLocalVisibility) {
+ else {
getContext().mergeDefinitionIntoModule(
Def, MergedDef->getImportedOwningModule(),
/*NotifyListeners*/ false);
PendingMergedDefinitionsToDeduplicate.insert(Def);
- } else {
- auto SubmoduleID = MergedDef->getOwningModuleID();
- assert(SubmoduleID && "hidden definition in no module");
- HiddenNamesMap[getSubmodule(SubmoduleID)].push_back(Def);
}
}
}
@@ -4868,11 +4861,11 @@ bool ASTReader::readASTFileControlBlock(
unsigned Idx = 0, N = Record.size();
while (Idx < N) {
// Read information about the AST file.
- Idx += 5; // ImportLoc, Size, ModTime, Signature
- SkipString(Record, Idx); // Module name; FIXME: pass to listener?
+ Idx += 1+1+1+1+5; // Kind, ImportLoc, Size, ModTime, Signature
+ std::string ModuleName = ReadString(Record, Idx);
std::string Filename = ReadString(Record, Idx);
ResolveImportedPath(Filename, ModuleDir);
- Listener.visitImport(Filename);
+ Listener.visitImport(ModuleName, Filename);
}
break;
}
@@ -5395,7 +5388,6 @@ bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
PPOpts.UsePredefines = Record[Idx++];
PPOpts.DetailedRecord = Record[Idx++];
PPOpts.ImplicitPCHInclude = ReadString(Record, Idx);
- PPOpts.ImplicitPTHInclude = ReadString(Record, Idx);
PPOpts.ObjCXXARCStandardLibrary =
static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);
SuggestedPredefines.clear();
@@ -6058,7 +6050,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
EPI.Variadic = Record[Idx++];
EPI.HasTrailingReturn = Record[Idx++];
- EPI.TypeQuals = Record[Idx++];
+ EPI.TypeQuals = Qualifiers::fromOpaqueValue(Record[Idx++]);
EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
SmallVector<QualType, 8> ExceptionStorage;
readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx);
@@ -6455,6 +6447,10 @@ class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx);
}
+ Attr *ReadAttr() {
+ return Reader->ReadAttr(*F, Record, Idx);
+ }
+
public:
TypeLocReader(ModuleFile &F, ASTReader &Reader,
const ASTReader::RecordData &Record, unsigned &Idx)
@@ -6646,20 +6642,7 @@ void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
}
void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- TL.setAttrNameLoc(ReadSourceLocation());
- if (TL.hasAttrOperand()) {
- SourceRange range;
- range.setBegin(ReadSourceLocation());
- range.setEnd(ReadSourceLocation());
- TL.setAttrOperandParensRange(range);
- }
- if (TL.hasAttrExprOperand()) {
- if (Record[Idx++])
- TL.setAttrExprOperand(Reader->ReadExpr(*F));
- else
- TL.setAttrExprOperand(nullptr);
- } else if (TL.hasAttrEnumOperand())
- TL.setAttrEnumOperandLoc(ReadSourceLocation());
+ TL.setAttr(ReadAttr());
}
void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
@@ -6979,6 +6962,11 @@ QualType ASTReader::GetType(TypeID ID) {
T = Context.SingletonId; \
break;
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case PREDEF_TYPE_##Id##_ID: \
+ T = Context.Id##Ty; \
+ break;
+#include "clang/Basic/OpenCLExtensionTypes.def"
case PREDEF_TYPE_SAMPLER_ID:
T = Context.OCLSamplerTy;
break;
@@ -9206,8 +9194,7 @@ void ASTReader::ReadComments() {
NextCursor:
// De-serialized SourceLocations get negative FileIDs for other modules,
// potentially invalidating the original order. Sort it again.
- llvm::sort(Comments.begin(), Comments.end(),
- BeforeThanCompare<RawComment>(SourceMgr));
+ llvm::sort(Comments, BeforeThanCompare<RawComment>(SourceMgr));
Context.Comments.addDeserializedComments(Comments);
}
}
@@ -9254,7 +9241,7 @@ std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
}
void ASTReader::finishPendingActions() {
- while (!PendingIdentifierInfos.empty() ||
+ while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() ||
!PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() ||
!PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() ||
!PendingUpdateRecords.empty()) {
@@ -9273,6 +9260,21 @@ void ASTReader::finishPendingActions() {
SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]);
}
+ // Load each function type that we deferred loading because it was a
+ // deduced type that might refer to a local type declared within itself.
+ for (unsigned I = 0; I != PendingFunctionTypes.size(); ++I) {
+ auto *FD = PendingFunctionTypes[I].first;
+ FD->setType(GetType(PendingFunctionTypes[I].second));
+
+ // If we gave a function a deduced return type, remember that we need to
+ // propagate that along the redeclaration chain.
+ auto *DT = FD->getReturnType()->getContainedDeducedType();
+ if (DT && DT->isDeduced())
+ PendingDeducedTypeUpdates.insert(
+ {FD->getCanonicalDecl(), FD->getReturnType()});
+ }
+ PendingFunctionTypes.clear();
+
// For each decl chain that we wanted to complete while deserializing, mark
// it as "still needs to be completed".
for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) {
@@ -9282,7 +9284,8 @@ void ASTReader::finishPendingActions() {
// Load pending declaration chains.
for (unsigned I = 0; I != PendingDeclChains.size(); ++I)
- loadPendingDeclChain(PendingDeclChains[I].first, PendingDeclChains[I].second);
+ loadPendingDeclChain(PendingDeclChains[I].first,
+ PendingDeclChains[I].second);
PendingDeclChains.clear();
// Make the most recent of the top-level declarations visible.
@@ -9677,8 +9680,8 @@ void ASTReader::diagnoseOdrViolations() {
unsigned NumBases = DD->NumBases;
if (NumBases == 0) return SourceRange();
auto bases = DD->bases();
- return SourceRange(bases[0].getLocStart(),
- bases[NumBases - 1].getLocEnd());
+ return SourceRange(bases[0].getBeginLoc(),
+ bases[NumBases - 1].getEndLoc());
};
if (FirstNumBases != SecondNumBases) {
@@ -10179,10 +10182,10 @@ void ASTReader::diagnoseOdrViolations() {
unsigned FirstODRHash = ComputeODRHash(FirstExpr);
unsigned SecondODRHash = ComputeODRHash(SecondExpr);
if (FirstODRHash != SecondODRHash) {
- ODRDiagError(FirstExpr->getLocStart(), FirstExpr->getSourceRange(),
+ ODRDiagError(FirstExpr->getBeginLoc(), FirstExpr->getSourceRange(),
StaticAssertCondition);
- ODRDiagNote(SecondExpr->getLocStart(),
- SecondExpr->getSourceRange(), StaticAssertCondition);
+ ODRDiagNote(SecondExpr->getBeginLoc(), SecondExpr->getSourceRange(),
+ StaticAssertCondition);
Diagnosed = true;
break;
}
@@ -10194,17 +10197,17 @@ void ASTReader::diagnoseOdrViolations() {
SourceLocation FirstLoc, SecondLoc;
SourceRange FirstRange, SecondRange;
if (FirstStr) {
- FirstLoc = FirstStr->getLocStart();
+ FirstLoc = FirstStr->getBeginLoc();
FirstRange = FirstStr->getSourceRange();
} else {
- FirstLoc = FirstSA->getLocStart();
+ FirstLoc = FirstSA->getBeginLoc();
FirstRange = FirstSA->getSourceRange();
}
if (SecondStr) {
- SecondLoc = SecondStr->getLocStart();
+ SecondLoc = SecondStr->getBeginLoc();
SecondRange = SecondStr->getSourceRange();
} else {
- SecondLoc = SecondSA->getLocStart();
+ SecondLoc = SecondSA->getBeginLoc();
SecondRange = SecondSA->getSourceRange();
}
ODRDiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage)
@@ -10217,9 +10220,9 @@ void ASTReader::diagnoseOdrViolations() {
if (FirstStr && SecondStr &&
FirstStr->getString() != SecondStr->getString()) {
- ODRDiagError(FirstStr->getLocStart(), FirstStr->getSourceRange(),
+ ODRDiagError(FirstStr->getBeginLoc(), FirstStr->getSourceRange(),
StaticAssertMessage);
- ODRDiagNote(SecondStr->getLocStart(), SecondStr->getSourceRange(),
+ ODRDiagNote(SecondStr->getBeginLoc(), SecondStr->getSourceRange(),
StaticAssertMessage);
Diagnosed = true;
break;
@@ -11531,11 +11534,16 @@ void ASTReader::FinishedDeserializing() {
--NumCurrentElementsDeserializing;
if (NumCurrentElementsDeserializing == 0) {
- // Propagate exception specification updates along redeclaration chains.
- while (!PendingExceptionSpecUpdates.empty()) {
- auto Updates = std::move(PendingExceptionSpecUpdates);
+ // Propagate exception specification and deduced type updates along
+ // redeclaration chains.
+ //
+ // We do this now rather than in finishPendingActions because we want to
+ // be able to walk the complete redeclaration chains of the updated decls.
+ while (!PendingExceptionSpecUpdates.empty() ||
+ !PendingDeducedTypeUpdates.empty()) {
+ auto ESUpdates = std::move(PendingExceptionSpecUpdates);
PendingExceptionSpecUpdates.clear();
- for (auto Update : Updates) {
+ for (auto Update : ESUpdates) {
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
auto ESI = FPT->getExtProtoInfo().ExceptionSpec;
@@ -11544,6 +11552,15 @@ void ASTReader::FinishedDeserializing() {
for (auto *Redecl : Update.second->redecls())
getContext().adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
}
+
+ auto DTUpdates = std::move(PendingDeducedTypeUpdates);
+ PendingDeducedTypeUpdates.clear();
+ for (auto Update : DTUpdates) {
+ ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
+ // FIXME: If the return type is already deduced, check that it matches.
+ getContext().adjustDeducedFunctionResultType(Update.first,
+ Update.second);
+ }
}
if (ReadTimer)
@@ -11637,3 +11654,910 @@ unsigned ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor,
Record.clear();
return Cursor.readRecord(AbbrevID, Record);
}
+//===----------------------------------------------------------------------===//
+//// OMPClauseReader implementation
+////===----------------------------------------------------------------------===//
+
+OMPClause *OMPClauseReader::readClause() {
+ OMPClause *C;
+ switch (Record.readInt()) {
+ case OMPC_if:
+ C = new (Context) OMPIfClause();
+ break;
+ case OMPC_final:
+ C = new (Context) OMPFinalClause();
+ break;
+ case OMPC_num_threads:
+ C = new (Context) OMPNumThreadsClause();
+ break;
+ case OMPC_safelen:
+ C = new (Context) OMPSafelenClause();
+ break;
+ case OMPC_simdlen:
+ C = new (Context) OMPSimdlenClause();
+ break;
+ case OMPC_collapse:
+ C = new (Context) OMPCollapseClause();
+ break;
+ case OMPC_default:
+ C = new (Context) OMPDefaultClause();
+ break;
+ case OMPC_proc_bind:
+ C = new (Context) OMPProcBindClause();
+ break;
+ case OMPC_schedule:
+ C = new (Context) OMPScheduleClause();
+ break;
+ case OMPC_ordered:
+ C = OMPOrderedClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_nowait:
+ C = new (Context) OMPNowaitClause();
+ break;
+ case OMPC_untied:
+ C = new (Context) OMPUntiedClause();
+ break;
+ case OMPC_mergeable:
+ C = new (Context) OMPMergeableClause();
+ break;
+ case OMPC_read:
+ C = new (Context) OMPReadClause();
+ break;
+ case OMPC_write:
+ C = new (Context) OMPWriteClause();
+ break;
+ case OMPC_update:
+ C = new (Context) OMPUpdateClause();
+ break;
+ case OMPC_capture:
+ C = new (Context) OMPCaptureClause();
+ break;
+ case OMPC_seq_cst:
+ C = new (Context) OMPSeqCstClause();
+ break;
+ case OMPC_threads:
+ C = new (Context) OMPThreadsClause();
+ break;
+ case OMPC_simd:
+ C = new (Context) OMPSIMDClause();
+ break;
+ case OMPC_nogroup:
+ C = new (Context) OMPNogroupClause();
+ break;
+ case OMPC_unified_address:
+ C = new (Context) OMPUnifiedAddressClause();
+ break;
+ case OMPC_unified_shared_memory:
+ C = new (Context) OMPUnifiedSharedMemoryClause();
+ break;
+ case OMPC_reverse_offload:
+ C = new (Context) OMPReverseOffloadClause();
+ break;
+ case OMPC_dynamic_allocators:
+ C = new (Context) OMPDynamicAllocatorsClause();
+ break;
+ case OMPC_atomic_default_mem_order:
+ C = new (Context) OMPAtomicDefaultMemOrderClause();
+ break;
+ case OMPC_private:
+ C = OMPPrivateClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_firstprivate:
+ C = OMPFirstprivateClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_lastprivate:
+ C = OMPLastprivateClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_shared:
+ C = OMPSharedClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_reduction:
+ C = OMPReductionClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_task_reduction:
+ C = OMPTaskReductionClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_in_reduction:
+ C = OMPInReductionClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_linear:
+ C = OMPLinearClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_aligned:
+ C = OMPAlignedClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_copyin:
+ C = OMPCopyinClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_copyprivate:
+ C = OMPCopyprivateClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_flush:
+ C = OMPFlushClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case OMPC_depend: {
+ unsigned NumVars = Record.readInt();
+ unsigned NumLoops = Record.readInt();
+ C = OMPDependClause::CreateEmpty(Context, NumVars, NumLoops);
+ break;
+ }
+ case OMPC_device:
+ C = new (Context) OMPDeviceClause();
+ break;
+ case OMPC_map: {
+ unsigned NumVars = Record.readInt();
+ unsigned NumDeclarations = Record.readInt();
+ unsigned NumLists = Record.readInt();
+ unsigned NumComponents = Record.readInt();
+ C = OMPMapClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
+ NumComponents);
+ break;
+ }
+ case OMPC_num_teams:
+ C = new (Context) OMPNumTeamsClause();
+ break;
+ case OMPC_thread_limit:
+ C = new (Context) OMPThreadLimitClause();
+ break;
+ case OMPC_priority:
+ C = new (Context) OMPPriorityClause();
+ break;
+ case OMPC_grainsize:
+ C = new (Context) OMPGrainsizeClause();
+ break;
+ case OMPC_num_tasks:
+ C = new (Context) OMPNumTasksClause();
+ break;
+ case OMPC_hint:
+ C = new (Context) OMPHintClause();
+ break;
+ case OMPC_dist_schedule:
+ C = new (Context) OMPDistScheduleClause();
+ break;
+ case OMPC_defaultmap:
+ C = new (Context) OMPDefaultmapClause();
+ break;
+ case OMPC_to: {
+ unsigned NumVars = Record.readInt();
+ unsigned NumDeclarations = Record.readInt();
+ unsigned NumLists = Record.readInt();
+ unsigned NumComponents = Record.readInt();
+ C = OMPToClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
+ NumComponents);
+ break;
+ }
+ case OMPC_from: {
+ unsigned NumVars = Record.readInt();
+ unsigned NumDeclarations = Record.readInt();
+ unsigned NumLists = Record.readInt();
+ unsigned NumComponents = Record.readInt();
+ C = OMPFromClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
+ NumComponents);
+ break;
+ }
+ case OMPC_use_device_ptr: {
+ unsigned NumVars = Record.readInt();
+ unsigned NumDeclarations = Record.readInt();
+ unsigned NumLists = Record.readInt();
+ unsigned NumComponents = Record.readInt();
+ C = OMPUseDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations,
+ NumLists, NumComponents);
+ break;
+ }
+ case OMPC_is_device_ptr: {
+ unsigned NumVars = Record.readInt();
+ unsigned NumDeclarations = Record.readInt();
+ unsigned NumLists = Record.readInt();
+ unsigned NumComponents = Record.readInt();
+ C = OMPIsDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations,
+ NumLists, NumComponents);
+ break;
+ }
+ }
+ Visit(C);
+ C->setLocStart(Record.readSourceLocation());
+ C->setLocEnd(Record.readSourceLocation());
+
+ return C;
+}
+
+void OMPClauseReader::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
+ C->setPreInitStmt(Record.readSubStmt(),
+ static_cast<OpenMPDirectiveKind>(Record.readInt()));
+}
+
+void OMPClauseReader::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setPostUpdateExpr(Record.readSubExpr());
+}
+
+void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setNameModifier(static_cast<OpenMPDirectiveKind>(Record.readInt()));
+ C->setNameModifierLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ C->setCondition(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) {
+ C->setCondition(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setNumThreads(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) {
+ C->setSafelen(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
+ C->setSimdlen(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) {
+ C->setNumForLoops(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
+ C->setDefaultKind(
+ static_cast<OpenMPDefaultClauseKind>(Record.readInt()));
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setDefaultKindKwLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
+ C->setProcBindKind(
+ static_cast<OpenMPProcBindClauseKind>(Record.readInt()));
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setProcBindKindKwLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setScheduleKind(
+ static_cast<OpenMPScheduleClauseKind>(Record.readInt()));
+ C->setFirstScheduleModifier(
+ static_cast<OpenMPScheduleClauseModifier>(Record.readInt()));
+ C->setSecondScheduleModifier(
+ static_cast<OpenMPScheduleClauseModifier>(Record.readInt()));
+ C->setChunkSize(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setFirstScheduleModifierLoc(Record.readSourceLocation());
+ C->setSecondScheduleModifierLoc(Record.readSourceLocation());
+ C->setScheduleKindLoc(Record.readSourceLocation());
+ C->setCommaLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ C->setNumForLoops(Record.readSubExpr());
+ for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I)
+ C->setLoopNumIterations(I, Record.readSubExpr());
+ for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I)
+ C->setLoopCounter(I, Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {}
+
+void OMPClauseReader::VisitOMPUntiedClause(OMPUntiedClause *) {}
+
+void OMPClauseReader::VisitOMPMergeableClause(OMPMergeableClause *) {}
+
+void OMPClauseReader::VisitOMPReadClause(OMPReadClause *) {}
+
+void OMPClauseReader::VisitOMPWriteClause(OMPWriteClause *) {}
+
+void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *) {}
+
+void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {}
+
+void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+
+void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {}
+
+void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
+
+void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {}
+
+void OMPClauseReader::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}
+
+void OMPClauseReader::VisitOMPUnifiedSharedMemoryClause(
+ OMPUnifiedSharedMemoryClause *) {}
+
+void OMPClauseReader::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {}
+
+void
+OMPClauseReader::VisitOMPDynamicAllocatorsClause(OMPDynamicAllocatorsClause *) {
+}
+
+void OMPClauseReader::VisitOMPAtomicDefaultMemOrderClause(
+ OMPAtomicDefaultMemOrderClause *C) {
+ C->setAtomicDefaultMemOrderKind(
+ static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Record.readInt()));
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setAtomicDefaultMemOrderKindKwLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivateCopies(Vars);
+}
+
+void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setLParenLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivateCopies(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setInits(Vars);
+}
+
+void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
+ C->setLParenLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivateCopies(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setSourceExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setDestinationExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setAssignmentOps(Vars);
+}
+
+void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+}
+
+void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ NestedNameSpecifierLoc NNSL = Record.readNestedNameSpecifierLoc();
+ DeclarationNameInfo DNI;
+ Record.readDeclarationNameInfo(DNI);
+ C->setQualifierLoc(NNSL);
+ C->setNameInfo(DNI);
+
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setLHSExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setRHSExprs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setReductionOps(Vars);
+}
+
+void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ NestedNameSpecifierLoc NNSL = Record.readNestedNameSpecifierLoc();
+ DeclarationNameInfo DNI;
+ Record.readDeclarationNameInfo(DNI);
+ C->setQualifierLoc(NNSL);
+ C->setNameInfo(DNI);
+
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setLHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setRHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setReductionOps(Vars);
+}
+
+void OMPClauseReader::VisitOMPInReductionClause(OMPInReductionClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ NestedNameSpecifierLoc NNSL = Record.readNestedNameSpecifierLoc();
+ DeclarationNameInfo DNI;
+ Record.readDeclarationNameInfo(DNI);
+ C->setQualifierLoc(NNSL);
+ C->setNameInfo(DNI);
+
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setLHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setRHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setReductionOps(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setTaskgroupDescriptors(Vars);
+}
+
+void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ C->setModifier(static_cast<OpenMPLinearClauseKind>(Record.readInt()));
+ C->setModifierLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setInits(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setUpdates(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setFinals(Vars);
+ C->setStep(Record.readSubExpr());
+ C->setCalcStep(Record.readSubExpr());
+}
+
+void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ C->setAlignment(Record.readSubExpr());
+}
+
+void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Exprs;
+ Exprs.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setVarRefs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setSourceExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setDestinationExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setAssignmentOps(Exprs);
+}
+
+void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Exprs;
+ Exprs.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setVarRefs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setSourceExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setDestinationExprs(Exprs);
+ Exprs.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Exprs.push_back(Record.readSubExpr());
+ C->setAssignmentOps(Exprs);
+}
+
+void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+}
+
+void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setDependencyKind(
+ static_cast<OpenMPDependClauseKind>(Record.readInt()));
+ C->setDependencyLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
+ C->setLoopData(I, Record.readSubExpr());
+}
+
+void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setDevice(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) {
+ C->setMapTypeModifier(
+ I, static_cast<OpenMPMapModifierKind>(Record.readInt()));
+ C->setMapTypeModifierLoc(I, Record.readSourceLocation());
+ }
+ C->setMapType(
+ static_cast<OpenMPMapClauseKind>(Record.readInt()));
+ C->setMapLoc(Record.readSourceLocation());
+ C->setColonLoc(Record.readSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Record.readSubExpr();
+ auto *AssociatedDecl = Record.readDeclAs<ValueDecl>();
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
+}
+
+void OMPClauseReader::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setNumTeams(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setThreadLimit(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) {
+ C->setPriority(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
+ C->setGrainsize(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
+ C->setNumTasks(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) {
+ C->setHint(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setDistScheduleKind(
+ static_cast<OpenMPDistScheduleClauseKind>(Record.readInt()));
+ C->setChunkSize(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setDistScheduleKindLoc(Record.readSourceLocation());
+ C->setCommaLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {
+ C->setDefaultmapKind(
+ static_cast<OpenMPDefaultmapClauseKind>(Record.readInt()));
+ C->setDefaultmapModifier(
+ static_cast<OpenMPDefaultmapClauseModifier>(Record.readInt()));
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setDefaultmapModifierLoc(Record.readSourceLocation());
+ C->setDefaultmapKindLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPToClause(OMPToClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Record.readSubExpr();
+ auto *AssociatedDecl = Record.readDeclAs<ValueDecl>();
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
+}
+
+void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Record.readSubExpr();
+ auto *AssociatedDecl = Record.readDeclAs<ValueDecl>();
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
+}
+
+void OMPClauseReader::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setPrivateCopies(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setInits(Vars);
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Record.readSubExpr();
+ auto *AssociatedDecl = Record.readDeclAs<ValueDecl>();
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
+}
+
+void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
+ C->setLParenLoc(Record.readSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Record.readSubExpr();
+ auto *AssociatedDecl = Record.readDeclAs<ValueDecl>();
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
+}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index ad37a2978df1..763ab527570d 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -30,6 +30,7 @@
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
@@ -47,7 +48,6 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Sema/IdentifierResolver.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ContinuousRangeMap.h"
@@ -274,7 +274,7 @@ namespace clang {
if (auto &Old = LazySpecializations) {
IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
- llvm::sort(IDs.begin(), IDs.end());
+ llvm::sort(IDs);
IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
}
@@ -446,6 +446,7 @@ namespace clang {
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
+ void VisitOMPRequiresDecl(OMPRequiresDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
};
@@ -506,8 +507,8 @@ void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
if (Record.readInt())
Reader.DefinitionSource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile;
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- CD->NumCtorInitializers = Record.readInt();
- if (CD->NumCtorInitializers)
+ CD->setNumCtorInitializers(Record.readInt());
+ if (CD->getNumCtorInitializers())
CD->CtorInitializers = ReadGlobalOffset();
}
// Store the offset of the body so we can lazily load it later.
@@ -541,9 +542,6 @@ void ASTDeclReader::Visit(Decl *D) {
// if we have a fully initialized TypeDecl, we can safely read its type now.
ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull();
} else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (DeferredTypeID)
- FD->setType(Reader.GetType(DeferredTypeID));
-
// FunctionDecl's body was written last after all other Stmts/Exprs.
// We only read it if FD doesn't already have a body (e.g., from another
// module).
@@ -742,16 +740,16 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
ED->setPromotionType(Record.readType());
ED->setNumPositiveBits(Record.readInt());
ED->setNumNegativeBits(Record.readInt());
- ED->IsScoped = Record.readInt();
- ED->IsScopedUsingClassTag = Record.readInt();
- ED->IsFixed = Record.readInt();
+ ED->setScoped(Record.readInt());
+ ED->setScopedUsingClassTag(Record.readInt());
+ ED->setFixed(Record.readInt());
- ED->HasODRHash = true;
+ ED->setHasODRHash(true);
ED->ODRHash = Record.readInt();
// If this is a definition subject to the ODR, and we already have a
// definition, merge this one into it.
- if (ED->IsCompleteDefinition &&
+ if (ED->isCompleteDefinition() &&
Reader.getContext().getLangOpts().Modules &&
Reader.getContext().getLangOpts().CPlusPlus) {
EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
@@ -767,7 +765,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
}
if (OldDef) {
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
- ED->IsCompleteDefinition = false;
+ ED->setCompleteDefinition(false);
Reader.mergeDefinitionVisibility(OldDef, ED);
if (OldDef->getODRHash() != ED->getODRHash())
Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
@@ -844,10 +842,11 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
// We'll set up the real type in Visit, once we've finished loading the
// function.
FD->setType(FD->getTypeSourceInfo()->getType());
+ Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID});
} else {
FD->setType(Reader.GetType(DeferredTypeID));
- DeferredTypeID = 0;
}
+ DeferredTypeID = 0;
ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName());
FD->IdentifierNamespace = Record.readInt();
@@ -855,30 +854,31 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
// after everything else is read.
- FD->SClass = (StorageClass)Record.readInt();
- FD->IsInline = Record.readInt();
- FD->IsInlineSpecified = Record.readInt();
- FD->IsExplicitSpecified = Record.readInt();
- FD->IsVirtualAsWritten = Record.readInt();
- FD->IsPure = Record.readInt();
- FD->HasInheritedPrototype = Record.readInt();
- FD->HasWrittenPrototype = Record.readInt();
- FD->IsDeleted = Record.readInt();
- FD->IsTrivial = Record.readInt();
- FD->IsTrivialForCall = Record.readInt();
- FD->IsDefaulted = Record.readInt();
- FD->IsExplicitlyDefaulted = Record.readInt();
- FD->HasImplicitReturnZero = Record.readInt();
- FD->IsConstexpr = Record.readInt();
- FD->UsesSEHTry = Record.readInt();
- FD->HasSkippedBody = Record.readInt();
- FD->IsMultiVersion = Record.readInt();
- FD->IsLateTemplateParsed = Record.readInt();
- FD->setCachedLinkage(Linkage(Record.readInt()));
+ FD->setStorageClass(static_cast<StorageClass>(Record.readInt()));
+ FD->setInlineSpecified(Record.readInt());
+ FD->setImplicitlyInline(Record.readInt());
+ FD->setExplicitSpecified(Record.readInt());
+ FD->setVirtualAsWritten(Record.readInt());
+ FD->setPure(Record.readInt());
+ FD->setHasInheritedPrototype(Record.readInt());
+ FD->setHasWrittenPrototype(Record.readInt());
+ FD->setDeletedAsWritten(Record.readInt());
+ FD->setTrivial(Record.readInt());
+ FD->setTrivialForCall(Record.readInt());
+ FD->setDefaulted(Record.readInt());
+ FD->setExplicitlyDefaulted(Record.readInt());
+ FD->setHasImplicitReturnZero(Record.readInt());
+ FD->setConstexpr(Record.readInt());
+ FD->setUsesSEHTry(Record.readInt());
+ FD->setHasSkippedBody(Record.readInt());
+ FD->setIsMultiVersion(Record.readInt());
+ FD->setLateTemplateParsed(Record.readInt());
+
+ FD->setCachedLinkage(static_cast<Linkage>(Record.readInt()));
FD->EndRangeLoc = ReadSourceLocation();
FD->ODRHash = Record.readInt();
- FD->HasODRHash = true;
+ FD->setHasODRHash(true);
switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
case FunctionDecl::TK_NonTemplate:
@@ -1006,18 +1006,18 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
MD->setVariadic(Record.readInt());
MD->setPropertyAccessor(Record.readInt());
MD->setDefined(Record.readInt());
- MD->IsOverriding = Record.readInt();
- MD->HasSkippedBody = Record.readInt();
+ MD->setOverriding(Record.readInt());
+ MD->setHasSkippedBody(Record.readInt());
- MD->IsRedeclaration = Record.readInt();
- MD->HasRedeclaration = Record.readInt();
- if (MD->HasRedeclaration)
+ MD->setIsRedeclaration(Record.readInt());
+ MD->setHasRedeclaration(Record.readInt());
+ if (MD->hasRedeclaration())
Reader.getContext().setObjCMethodRedeclaration(MD,
ReadDeclAs<ObjCMethodDecl>());
MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record.readInt());
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record.readInt());
- MD->SetRelatedResultType(Record.readInt());
+ MD->setRelatedResultType(Record.readInt());
MD->setReturnType(Record.readType());
MD->setReturnTypeSourceInfo(GetTypeSourceInfo());
MD->DeclEndLoc = ReadSourceLocation();
@@ -1027,7 +1027,7 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
for (unsigned I = 0; I != NumParams; ++I)
Params.push_back(ReadDeclAs<ParmVarDecl>());
- MD->SelLocsKind = Record.readInt();
+ MD->setSelLocsKind((SelectorLocationsKind)Record.readInt());
unsigned NumStoredSelLocs = Record.readInt();
SmallVector<SourceLocation, 16> SelLocs;
SelLocs.reserve(NumStoredSelLocs);
@@ -1350,6 +1350,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->VarDeclBits.SClass = (StorageClass)Record.readInt();
VD->VarDeclBits.TSCSpec = Record.readInt();
VD->VarDeclBits.InitStyle = Record.readInt();
+ VD->VarDeclBits.ARCPseudoStrong = Record.readInt();
if (!isa<ParmVarDecl>(VD)) {
VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition =
Record.readInt();
@@ -1357,13 +1358,13 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->NonParmVarDeclBits.NRVOVariable = Record.readInt();
VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt();
VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt();
- VD->NonParmVarDeclBits.ARCPseudoStrong = Record.readInt();
VD->NonParmVarDeclBits.IsInline = Record.readInt();
VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
VD->NonParmVarDeclBits.IsConstexpr = Record.readInt();
VD->NonParmVarDeclBits.IsInitCapture = Record.readInt();
VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt();
VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt();
+ VD->NonParmVarDeclBits.EscapingByref = Record.readInt();
}
auto VarLinkage = Linkage(Record.readInt());
VD->setCachedLinkage(VarLinkage);
@@ -1382,6 +1383,12 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
}
}
+ if (VD->hasAttr<BlocksAttr>() && VD->getType()->getAsCXXRecordDecl()) {
+ Expr *CopyExpr = Record.readExpr();
+ if (CopyExpr)
+ Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt());
+ }
+
if (VD->getStorageDuration() == SD_Static && Record.readInt())
Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile;
@@ -1471,6 +1478,7 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
BD->setIsVariadic(Record.readInt());
BD->setBlockMissingReturnType(Record.readInt());
BD->setIsConversionFromLambda(Record.readInt());
+ BD->setDoesNotEscape(Record.readInt());
bool capturesCXXThis = Record.readInt();
unsigned numCaptures = Record.readInt();
@@ -1744,7 +1752,7 @@ void ASTDeclReader::MergeDefinitionData(
Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition,
DD.Definition));
Reader.PendingDefinitions.erase(MergeDD.Definition);
- MergeDD.Definition->IsCompleteDefinition = false;
+ MergeDD.Definition->setCompleteDefinition(false);
Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&
"already loaded pending lookups for merged definition");
@@ -1884,7 +1892,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
}
// Mark this declaration as being a definition.
- D->IsCompleteDefinition = true;
+ D->setCompleteDefinition(true);
// If this is not the first declaration or is an update record, we can have
// other redeclarations already. Make a note that we need to propagate the
@@ -1946,7 +1954,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
// compute it.
if (WasDefinition) {
DeclID KeyFn = ReadDeclID();
- if (KeyFn && D->IsCompleteDefinition)
+ if (KeyFn && D->isCompleteDefinition())
// FIXME: This is wrong for the ARM ABI, where some other module may have
// made this function no longer be a key function. We need an update
// record or similar for that case.
@@ -1958,7 +1966,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
VisitFunctionDecl(D);
- D->IsCopyDeductionCandidate = Record.readInt();
+ D->setIsCopyDeductionCandidate(Record.readInt());
}
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
@@ -2624,13 +2632,31 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
D->setVars(Vars);
}
+void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) {
+ VisitDecl(D);
+ unsigned NumClauses = D->clauselist_size();
+ SmallVector<OMPClause *, 8> Clauses;
+ Clauses.reserve(NumClauses);
+ OMPClauseReader ClauseReader(Record);
+ for (unsigned I = 0; I != NumClauses; ++I)
+ Clauses.push_back(ClauseReader.readClause());
+ D->setClauses(Clauses);
+}
+
void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
VisitValueDecl(D);
D->setLocation(ReadSourceLocation());
- D->setCombiner(Record.readExpr());
- D->setInitializer(
- Record.readExpr(),
- static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt()));
+ Expr *In = Record.readExpr();
+ Expr *Out = Record.readExpr();
+ D->setCombinerData(In, Out);
+ Expr *Combiner = Record.readExpr();
+ D->setCombiner(Combiner);
+ Expr *Orig = Record.readExpr();
+ Expr *Priv = Record.readExpr();
+ D->setInitializerData(Orig, Priv);
+ Expr *Init = Record.readExpr();
+ auto IK = static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt());
+ D->setInitializer(Init, IK);
D->PrevDeclInScope = ReadDeclID();
}
@@ -2642,19 +2668,72 @@ void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
// Attribute Reading
//===----------------------------------------------------------------------===//
-/// Reads attributes from the current stream position.
-void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
- for (unsigned i = 0, e = Record.readInt(); i != e; ++i) {
- Attr *New = nullptr;
- auto Kind = (attr::Kind)Record.readInt();
- SourceRange Range = Record.readSourceRange();
- ASTContext &Context = getContext();
+namespace {
+class AttrReader {
+ ModuleFile *F;
+ ASTReader *Reader;
+ const ASTReader::RecordData &Record;
+ unsigned &Idx;
-#include "clang/Serialization/AttrPCHRead.inc"
+public:
+ AttrReader(ModuleFile &F, ASTReader &Reader,
+ const ASTReader::RecordData &Record, unsigned &Idx)
+ : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {}
- assert(New && "Unable to decode attribute?");
- Attrs.push_back(New);
+ const uint64_t &readInt() { return Record[Idx++]; }
+
+ SourceRange readSourceRange() {
+ return Reader->ReadSourceRange(*F, Record, Idx);
}
+
+ Expr *readExpr() { return Reader->ReadExpr(*F); }
+
+ std::string readString() {
+ return Reader->ReadString(Record, Idx);
+ }
+
+ TypeSourceInfo *getTypeSourceInfo() {
+ return Reader->GetTypeSourceInfo(*F, Record, Idx);
+ }
+
+ IdentifierInfo *getIdentifierInfo() {
+ return Reader->GetIdentifierInfo(*F, Record, Idx);
+ }
+
+ VersionTuple readVersionTuple() {
+ return ASTReader::ReadVersionTuple(Record, Idx);
+ }
+
+ template <typename T> T *GetLocalDeclAs(uint32_t LocalID) {
+ return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
+ }
+};
+}
+
+Attr *ASTReader::ReadAttr(ModuleFile &M, const RecordData &Rec,
+ unsigned &Idx) {
+ AttrReader Record(M, *this, Rec, Idx);
+ auto V = Record.readInt();
+ if (!V)
+ return nullptr;
+
+ Attr *New = nullptr;
+ // Kind is stored as a 1-based integer because 0 is used to indicate a null
+ // Attr pointer.
+ auto Kind = static_cast<attr::Kind>(V - 1);
+ SourceRange Range = Record.readSourceRange();
+ ASTContext &Context = getContext();
+
+#include "clang/Serialization/AttrPCHRead.inc"
+
+ assert(New && "Unable to decode attribute?");
+ return New;
+}
+
+/// Reads attributes from the current stream position.
+void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
+ for (unsigned I = 0, E = Record.readInt(); I != E; ++I)
+ Attrs.push_back(Record.readAttr());
}
//===----------------------------------------------------------------------===//
@@ -2702,7 +2781,8 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
return !D->getDeclContext()->isFunctionOrMethod();
if (const auto *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
- Var->isThisDeclarationADefinition() == VarDecl::Definition;
+ (Var->isThisDeclarationADefinition() == VarDecl::Definition ||
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Var));
if (const auto *Func = dyn_cast<FunctionDecl>(D))
return Func->doesThisDeclarationHaveABody() || HasBody;
@@ -2832,35 +2912,29 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
// Note that pass_object_size attributes are represented in the function's
// ExtParameterInfo, so we don't need to check them here.
- SmallVector<const EnableIfAttr *, 4> AEnableIfs;
- // Since this is an equality check, we can ignore that enable_if attrs show up
- // in reverse order.
- for (const auto *EIA : A->specific_attrs<EnableIfAttr>())
- AEnableIfs.push_back(EIA);
-
- SmallVector<const EnableIfAttr *, 4> BEnableIfs;
- for (const auto *EIA : B->specific_attrs<EnableIfAttr>())
- BEnableIfs.push_back(EIA);
+ llvm::FoldingSetNodeID Cand1ID, Cand2ID;
+ auto AEnableIfAttrs = A->specific_attrs<EnableIfAttr>();
+ auto BEnableIfAttrs = B->specific_attrs<EnableIfAttr>();
- // Two very common cases: either we have 0 enable_if attrs, or we have an
- // unequal number of enable_if attrs.
- if (AEnableIfs.empty() && BEnableIfs.empty())
- return true;
+ for (auto Pair : zip_longest(AEnableIfAttrs, BEnableIfAttrs)) {
+ Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair);
+ Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair);
- if (AEnableIfs.size() != BEnableIfs.size())
- return false;
+ // Return false if the number of enable_if attributes is different.
+ if (!Cand1A || !Cand2A)
+ return false;
- llvm::FoldingSetNodeID Cand1ID, Cand2ID;
- for (unsigned I = 0, E = AEnableIfs.size(); I != E; ++I) {
Cand1ID.clear();
Cand2ID.clear();
- AEnableIfs[I]->getCond()->Profile(Cand1ID, A->getASTContext(), true);
- BEnableIfs[I]->getCond()->Profile(Cand2ID, B->getASTContext(), true);
+ (*Cand1A)->getCond()->Profile(Cand1ID, A->getASTContext(), true);
+ (*Cand2A)->getCond()->Profile(Cand2ID, B->getASTContext(), true);
+
+ // Return false if any of the enable_if expressions of A and B are
+ // different.
if (Cand1ID != Cand2ID)
return false;
}
-
return true;
}
@@ -3076,7 +3150,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
// we load the update record.
if (!DD) {
DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD);
- RD->IsCompleteDefinition = true;
+ RD->setCompleteDefinition(true);
RD->DefinitionData = DD;
RD->getCanonicalDecl()->DefinitionData = DD;
@@ -3368,6 +3442,11 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
}
}
+static bool isUndeducedReturnType(QualType T) {
+ auto *DT = T->getContainedDeducedType();
+ return DT && !DT->isDeduced();
+}
+
template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<FunctionDecl> *D,
@@ -3380,7 +3459,7 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
// If the previous declaration is an inline function declaration, then this
// declaration is too.
- if (PrevFD->IsInline != FD->IsInline) {
+ if (PrevFD->isInlined() != FD->isInlined()) {
// FIXME: [dcl.fct.spec]p4:
// If a function with external linkage is declared inline in one
// translation unit, it shall be declared inline in all translation
@@ -3396,20 +3475,29 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
// module C instantiates the definition of X<int>::f
//
// If module B and C are merged, we do not have a violation of this rule.
- FD->IsInline = true;
+ FD->setImplicitlyInline(true);
}
- // If we need to propagate an exception specification along the redecl
- // chain, make a note of that so that we can do so later.
auto *FPT = FD->getType()->getAs<FunctionProtoType>();
auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
if (FPT && PrevFPT) {
+ // If we need to propagate an exception specification along the redecl
+ // chain, make a note of that so that we can do so later.
bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
bool WasUnresolved =
isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
if (IsUnresolved != WasUnresolved)
Reader.PendingExceptionSpecUpdates.insert(
- std::make_pair(Canon, IsUnresolved ? PrevFD : FD));
+ {Canon, IsUnresolved ? PrevFD : FD});
+
+ // If we need to propagate a deduced return type along the redecl chain,
+ // make a note of that so that we can do it later.
+ bool IsUndeduced = isUndeducedReturnType(FPT->getReturnType());
+ bool WasUndeduced = isUndeducedReturnType(PrevFPT->getReturnType());
+ if (IsUndeduced != WasUndeduced)
+ Reader.PendingDeducedTypeUpdates.insert(
+ {cast<FunctionDecl>(Canon),
+ (IsUndeduced ? PrevFPT : FPT)->getReturnType()});
}
}
@@ -3760,6 +3848,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_OMP_THREADPRIVATE:
D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
+ case DECL_OMP_REQUIRES:
+ D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt());
+ break;
case DECL_OMP_DECLARE_REDUCTION:
D = OMPDeclareReductionDecl::CreateDeserialized(Context, ID);
break;
@@ -4326,14 +4417,10 @@ void ASTDeclReader::UpdateDecl(Decl *D,
}
case UPD_CXX_DEDUCED_RETURN_TYPE: {
- // FIXME: Also do this when merging redecls.
+ auto *FD = cast<FunctionDecl>(D);
QualType DeducedResultType = Record.readType();
- for (auto *Redecl : merged_redecls(D)) {
- // FIXME: If the return type is already deduced, check that it matches.
- auto *FD = cast<FunctionDecl>(Redecl);
- Reader.getContext().adjustDeducedFunctionResultType(FD,
- DeducedResultType);
- }
+ Reader.PendingDeducedTypeUpdates.insert(
+ {FD->getCanonicalDecl(), DeducedResultType});
break;
}
@@ -4360,26 +4447,19 @@ void ASTDeclReader::UpdateDecl(Decl *D,
case UPD_DECL_EXPORTED: {
unsigned SubmoduleID = readSubmoduleID();
auto *Exported = cast<NamedDecl>(D);
- if (auto *TD = dyn_cast<TagDecl>(Exported))
- Exported = TD->getDefinition();
Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr;
- if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
- Reader.getContext().mergeDefinitionIntoModule(cast<NamedDecl>(Exported),
- Owner);
- Reader.PendingMergedDefinitionsToDeduplicate.insert(
- cast<NamedDecl>(Exported));
- } else if (Owner && Owner->NameVisibility != Module::AllVisible) {
- // If Owner is made visible at some later point, make this declaration
- // visible too.
- Reader.HiddenNamesMap[Owner].push_back(Exported);
- } else {
- // The declaration is now visible.
- Exported->setVisibleDespiteOwningModule();
- }
+ Reader.getContext().mergeDefinitionIntoModule(Exported, Owner);
+ Reader.PendingMergedDefinitionsToDeduplicate.insert(Exported);
break;
}
case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
+ D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
+ Reader.getContext(),
+ static_cast<OMPDeclareTargetDeclAttr::MapTypeTy>(Record.readInt()),
+ ReadSourceRange()));
+ break;
+
case UPD_ADDED_ATTR_TO_RECORD:
AttrVec Attrs;
Record.readAttributes(Attrs);
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index d9d780b25b31..60abea95bfaf 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -154,7 +154,7 @@ void ASTStmtReader::VisitStmt(Stmt *S) {
void ASTStmtReader::VisitNullStmt(NullStmt *S) {
VisitStmt(S);
S->setSemiLoc(ReadSourceLocation());
- S->HasLeadingEmptyMacro = Record.readInt();
+ S->NullStmtBits.HasLeadingEmptyMacro = Record.readInt();
}
void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) {
@@ -164,7 +164,7 @@ void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) {
while (NumStmts--)
Stmts.push_back(Record.readSubStmt());
S->setStmts(Stmts);
- S->LBraceLoc = ReadSourceLocation();
+ S->CompoundStmtBits.LBraceLoc = ReadSourceLocation();
S->RBraceLoc = ReadSourceLocation();
}
@@ -177,10 +177,13 @@ void ASTStmtReader::VisitSwitchCase(SwitchCase *S) {
void ASTStmtReader::VisitCaseStmt(CaseStmt *S) {
VisitSwitchCase(S);
+ bool CaseStmtIsGNURange = Record.readInt();
S->setLHS(Record.readSubExpr());
- S->setRHS(Record.readSubExpr());
S->setSubStmt(Record.readSubStmt());
- S->setEllipsisLoc(ReadSourceLocation());
+ if (CaseStmtIsGNURange) {
+ S->setRHS(Record.readSubExpr());
+ S->setEllipsisLoc(ReadSourceLocation());
+ }
}
void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) {
@@ -199,38 +202,59 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
VisitStmt(S);
+ // NumAttrs in AttributedStmt is set when creating an empty
+ // AttributedStmt in AttributedStmt::CreateEmpty, since it is needed
+ // to allocate the right amount of space for the trailing Attr *.
uint64_t NumAttrs = Record.readInt();
AttrVec Attrs;
Record.readAttributes(Attrs);
(void)NumAttrs;
- assert(NumAttrs == S->NumAttrs);
+ assert(NumAttrs == S->AttributedStmtBits.NumAttrs);
assert(NumAttrs == Attrs.size());
std::copy(Attrs.begin(), Attrs.end(), S->getAttrArrayPtr());
S->SubStmt = Record.readSubStmt();
- S->AttrLoc = ReadSourceLocation();
+ S->AttributedStmtBits.AttrLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
+
S->setConstexpr(Record.readInt());
- S->setInit(Record.readSubStmt());
- S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+ bool HasElse = Record.readInt();
+ bool HasVar = Record.readInt();
+ bool HasInit = Record.readInt();
+
S->setCond(Record.readSubExpr());
S->setThen(Record.readSubStmt());
- S->setElse(Record.readSubStmt());
+ if (HasElse)
+ S->setElse(Record.readSubStmt());
+ if (HasVar)
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+ if (HasInit)
+ S->setInit(Record.readSubStmt());
+
S->setIfLoc(ReadSourceLocation());
- S->setElseLoc(ReadSourceLocation());
+ if (HasElse)
+ S->setElseLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
- S->setInit(Record.readSubStmt());
- S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+
+ bool HasInit = Record.readInt();
+ bool HasVar = Record.readInt();
+ bool AllEnumCasesCovered = Record.readInt();
+ if (AllEnumCasesCovered)
+ S->setAllEnumCasesCovered();
+
S->setCond(Record.readSubExpr());
S->setBody(Record.readSubStmt());
+ if (HasInit)
+ S->setInit(Record.readSubStmt());
+ if (HasVar)
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+
S->setSwitchLoc(ReadSourceLocation());
- if (Record.readInt())
- S->setAllEnumCasesCovered();
SwitchCase *PrevSC = nullptr;
for (auto E = Record.size(); Record.getIdx() != E; ) {
@@ -246,10 +270,14 @@ void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
void ASTStmtReader::VisitWhileStmt(WhileStmt *S) {
VisitStmt(S);
- S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+
+ bool HasVar = Record.readInt();
S->setCond(Record.readSubExpr());
S->setBody(Record.readSubStmt());
+ if (HasVar)
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+
S->setWhileLoc(ReadSourceLocation());
}
@@ -300,9 +328,14 @@ void ASTStmtReader::VisitBreakStmt(BreakStmt *S) {
void ASTStmtReader::VisitReturnStmt(ReturnStmt *S) {
VisitStmt(S);
+
+ bool HasNRVOCandidate = Record.readInt();
+
S->setRetValue(Record.readSubExpr());
+ if (HasNRVOCandidate)
+ S->setNRVOCandidate(ReadDeclAs<VarDecl>());
+
S->setReturnLoc(ReadSourceLocation());
- S->setNRVOCandidate(ReadDeclAs<VarDecl>());
}
void ASTStmtReader::VisitDeclStmt(DeclStmt *S) {
@@ -491,11 +524,19 @@ void ASTStmtReader::VisitExpr(Expr *E) {
"Incorrect expression field count");
}
+void ASTStmtReader::VisitConstantExpr(ConstantExpr *E) {
+ VisitExpr(E);
+ E->setSubExpr(Record.readSubExpr());
+}
+
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
+ bool HasFunctionName = Record.readInt();
+ E->PredefinedExprBits.HasFunctionName = HasFunctionName;
+ E->PredefinedExprBits.Kind = Record.readInt();
E->setLocation(ReadSourceLocation());
- E->Type = (PredefinedExpr::IdentType)Record.readInt();
- E->FnName = cast_or_null<StringLiteral>(Record.readSubExpr());
+ if (HasFunctionName)
+ E->setFunctionName(cast<StringLiteral>(Record.readSubExpr()));
}
void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
@@ -554,22 +595,35 @@ void ASTStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) {
void ASTStmtReader::VisitStringLiteral(StringLiteral *E) {
VisitExpr(E);
- unsigned Len = Record.readInt();
- assert(Record.peekInt() == E->getNumConcatenated() &&
- "Wrong number of concatenated tokens!");
- Record.skipInts(1);
- auto kind = static_cast<StringLiteral::StringKind>(Record.readInt());
- bool isPascal = Record.readInt();
- // Read string data
- auto B = &Record.peekInt();
- SmallString<16> Str(B, B + Len);
- E->setString(Record.getContext(), Str, kind, isPascal);
- Record.skipInts(Len);
-
- // Read source locations
- for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
+ // NumConcatenated, Length and CharByteWidth are set by the empty
+ // ctor since they are needed to allocate storage for the trailing objects.
+ unsigned NumConcatenated = Record.readInt();
+ unsigned Length = Record.readInt();
+ unsigned CharByteWidth = Record.readInt();
+ assert((NumConcatenated == E->getNumConcatenated()) &&
+ "Wrong number of concatenated tokens!");
+ assert((Length == E->getLength()) && "Wrong Length!");
+ assert((CharByteWidth == E->getCharByteWidth()) && "Wrong character width!");
+ E->StringLiteralBits.Kind = Record.readInt();
+ E->StringLiteralBits.IsPascal = Record.readInt();
+
+ // The character width is originally computed via mapCharByteWidth.
+ // Check that the deserialized character width is consistant with the result
+ // of calling mapCharByteWidth.
+ assert((CharByteWidth ==
+ StringLiteral::mapCharByteWidth(Record.getContext().getTargetInfo(),
+ E->getKind())) &&
+ "Wrong character width!");
+
+ // Deserialize the trailing array of SourceLocation.
+ for (unsigned I = 0; I < NumConcatenated; ++I)
E->setStrTokenLoc(I, ReadSourceLocation());
+
+ // Deserialize the trailing array of char holding the string data.
+ char *StrData = E->getStrDataAsChar();
+ for (unsigned I = 0; I < Length * CharByteWidth; ++I)
+ StrData[I] = Record.readInt();
}
void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
@@ -589,10 +643,9 @@ void ASTStmtReader::VisitParenExpr(ParenExpr *E) {
void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) {
VisitExpr(E);
unsigned NumExprs = Record.readInt();
- E->Exprs = new (Record.getContext()) Stmt*[NumExprs];
- for (unsigned i = 0; i != NumExprs; ++i)
- E->Exprs[i] = Record.readSubStmt();
- E->NumExprs = NumExprs;
+ assert((NumExprs == E->getNumExprs()) && "Wrong NumExprs!");
+ for (unsigned I = 0; I != NumExprs; ++I)
+ E->getTrailingObjects<Stmt *>()[I] = Record.readSubStmt();
E->LParenLoc = ReadSourceLocation();
E->RParenLoc = ReadSourceLocation();
}
@@ -678,11 +731,13 @@ void ASTStmtReader::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) {
void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
- E->setNumArgs(Record.getContext(), Record.readInt());
+ unsigned NumArgs = Record.readInt();
+ assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!");
E->setRParenLoc(ReadSourceLocation());
E->setCallee(Record.readSubExpr());
- for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+ for (unsigned I = 0; I != NumArgs; ++I)
E->setArg(I, Record.readSubExpr());
+ E->setADLCallKind(static_cast<CallExpr::ADLCallKind>(Record.readInt()));
}
void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
@@ -1270,6 +1325,7 @@ void ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
S->CoawaitLoc = ReadSourceLocation();
S->ColonLoc = ReadSourceLocation();
S->RParenLoc = ReadSourceLocation();
+ S->setInit(Record.readSubStmt());
S->setRangeStmt(Record.readSubStmt());
S->setBeginStmt(Record.readSubStmt());
S->setEndStmt(Record.readSubStmt());
@@ -1290,27 +1346,29 @@ void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
- E->Operator = (OverloadedOperatorKind)Record.readInt();
+ E->CXXOperatorCallExprBits.OperatorKind = Record.readInt();
+ E->CXXOperatorCallExprBits.FPFeatures = Record.readInt();
E->Range = Record.readSourceRange();
- E->setFPFeatures(FPOptions(Record.readInt()));
}
void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
VisitExpr(E);
- E->NumArgs = Record.readInt();
- if (E->NumArgs)
- E->Args = new (Record.getContext()) Stmt*[E->NumArgs];
- for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
- E->setArg(I, Record.readSubExpr());
- E->setConstructor(ReadDeclAs<CXXConstructorDecl>());
- E->setLocation(ReadSourceLocation());
- E->setElidable(Record.readInt());
- E->setHadMultipleCandidates(Record.readInt());
- E->setListInitialization(Record.readInt());
- E->setStdInitListInitialization(Record.readInt());
- E->setRequiresZeroInitialization(Record.readInt());
- E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record.readInt());
+
+ unsigned NumArgs = Record.readInt();
+ assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!");
+
+ E->CXXConstructExprBits.Elidable = Record.readInt();
+ E->CXXConstructExprBits.HadMultipleCandidates = Record.readInt();
+ E->CXXConstructExprBits.ListInitialization = Record.readInt();
+ E->CXXConstructExprBits.StdInitListInitialization = Record.readInt();
+ E->CXXConstructExprBits.ZeroInitialization = Record.readInt();
+ E->CXXConstructExprBits.ConstructionKind = Record.readInt();
+ E->CXXConstructExprBits.Loc = ReadSourceLocation();
+ E->Constructor = ReadDeclAs<CXXConstructorDecl>();
E->ParenOrBraceRange = ReadSourceRange();
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ E->setArg(I, Record.readSubExpr());
}
void ASTStmtReader::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) {
@@ -1323,7 +1381,7 @@ void ASTStmtReader::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) {
void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
VisitCXXConstructExpr(E);
- E->Type = GetTypeSourceInfo();
+ E->TSI = GetTypeSourceInfo();
}
void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) {
@@ -1418,21 +1476,21 @@ void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) {
void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) {
VisitExpr(E);
- E->ThrowLoc = ReadSourceLocation();
- E->Op = Record.readSubExpr();
- E->IsThrownVariableInScope = Record.readInt();
+ E->CXXThrowExprBits.ThrowLoc = ReadSourceLocation();
+ E->Operand = Record.readSubExpr();
+ E->CXXThrowExprBits.IsThrownVariableInScope = Record.readInt();
}
void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
E->Param = ReadDeclAs<ParmVarDecl>();
- E->Loc = ReadSourceLocation();
+ E->CXXDefaultArgExprBits.Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
VisitExpr(E);
E->Field = ReadDeclAs<FieldDecl>();
- E->Loc = ReadSourceLocation();
+ E->CXXDefaultInitExprBits.Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
@@ -1444,42 +1502,55 @@ void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
VisitExpr(E);
E->TypeInfo = GetTypeSourceInfo();
- E->RParenLoc = ReadSourceLocation();
+ E->CXXScalarValueInitExprBits.RParenLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) {
VisitExpr(E);
- E->GlobalNew = Record.readInt();
- bool isArray = Record.readInt();
- E->PassAlignment = Record.readInt();
- E->UsualArrayDeleteWantsSize = Record.readInt();
+
+ bool IsArray = Record.readInt();
+ bool HasInit = Record.readInt();
unsigned NumPlacementArgs = Record.readInt();
- E->StoredInitializationStyle = Record.readInt();
+ bool IsParenTypeId = Record.readInt();
+
+ E->CXXNewExprBits.IsGlobalNew = Record.readInt();
+ E->CXXNewExprBits.ShouldPassAlignment = Record.readInt();
+ E->CXXNewExprBits.UsualArrayDeleteWantsSize = Record.readInt();
+ E->CXXNewExprBits.StoredInitializationStyle = Record.readInt();
+
+ assert((IsArray == E->isArray()) && "Wrong IsArray!");
+ assert((HasInit == E->hasInitializer()) && "Wrong HasInit!");
+ assert((NumPlacementArgs == E->getNumPlacementArgs()) &&
+ "Wrong NumPlacementArgs!");
+ assert((IsParenTypeId == E->isParenTypeId()) && "Wrong IsParenTypeId!");
+ (void)IsArray;
+ (void)HasInit;
+ (void)NumPlacementArgs;
+
E->setOperatorNew(ReadDeclAs<FunctionDecl>());
E->setOperatorDelete(ReadDeclAs<FunctionDecl>());
E->AllocatedTypeInfo = GetTypeSourceInfo();
- E->TypeIdParens = ReadSourceRange();
+ if (IsParenTypeId)
+ E->getTrailingObjects<SourceRange>()[0] = ReadSourceRange();
E->Range = ReadSourceRange();
E->DirectInitRange = ReadSourceRange();
- E->AllocateArgsArray(Record.getContext(), isArray, NumPlacementArgs,
- E->StoredInitializationStyle != 0);
-
// Install all the subexpressions.
- for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end();
- I != e; ++I)
+ for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),
+ N = E->raw_arg_end();
+ I != N; ++I)
*I = Record.readSubStmt();
}
void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
VisitExpr(E);
- E->GlobalDelete = Record.readInt();
- E->ArrayForm = Record.readInt();
- E->ArrayFormAsWritten = Record.readInt();
- E->UsualArrayDeleteWantsSize = Record.readInt();
+ E->CXXDeleteExprBits.GlobalDelete = Record.readInt();
+ E->CXXDeleteExprBits.ArrayForm = Record.readInt();
+ E->CXXDeleteExprBits.ArrayFormAsWritten = Record.readInt();
+ E->CXXDeleteExprBits.UsualArrayDeleteWantsSize = Record.readInt();
E->OperatorDelete = ReadDeclAs<FunctionDecl>();
E->Argument = Record.readSubExpr();
- E->Loc = ReadSourceLocation();
+ E->CXXDeleteExprBits.Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
@@ -1513,22 +1584,37 @@ void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) {
E->SubExpr = Record.readSubExpr();
}
-void
-ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
+void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
+ CXXDependentScopeMemberExpr *E) {
VisitExpr(E);
- if (Record.readInt()) // HasTemplateKWAndArgsInfo
+ bool HasTemplateKWAndArgsInfo = Record.readInt();
+ unsigned NumTemplateArgs = Record.readInt();
+ bool HasFirstQualifierFoundInScope = Record.readInt();
+
+ assert((HasTemplateKWAndArgsInfo == E->hasTemplateKWAndArgsInfo()) &&
+ "Wrong HasTemplateKWAndArgsInfo!");
+ assert(
+ (HasFirstQualifierFoundInScope == E->hasFirstQualifierFoundInScope()) &&
+ "Wrong HasFirstQualifierFoundInScope!");
+
+ if (HasTemplateKWAndArgsInfo)
ReadTemplateKWAndArgsInfo(
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
- E->getTrailingObjects<TemplateArgumentLoc>(),
- /*NumTemplateArgs=*/Record.readInt());
+ E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
- E->Base = Record.readSubExpr();
+ assert((NumTemplateArgs == E->getNumTemplateArgs()) &&
+ "Wrong NumTemplateArgs!");
+
+ E->CXXDependentScopeMemberExprBits.IsArrow = Record.readInt();
+ E->CXXDependentScopeMemberExprBits.OperatorLoc = ReadSourceLocation();
E->BaseType = Record.readType();
- E->IsArrow = Record.readInt();
- E->OperatorLoc = ReadSourceLocation();
E->QualifierLoc = Record.readNestedNameSpecifierLoc();
- E->FirstQualifierFoundInScope = ReadDeclAs<NamedDecl>();
+ E->Base = Record.readSubExpr();
+
+ if (HasFirstQualifierFoundInScope)
+ *E->getTrailingObjects<NamedDecl *>() = ReadDeclAs<NamedDecl>();
+
ReadDeclarationNameInfo(E->MemberNameInfo);
}
@@ -1554,7 +1640,7 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
Record.skipInts(1);
for (unsigned I = 0, N = E->arg_size(); I != N; ++I)
E->setArg(I, Record.readSubExpr());
- E->Type = GetTypeSourceInfo();
+ E->TSI = GetTypeSourceInfo();
E->setLParenLoc(ReadSourceLocation());
E->setRParenLoc(ReadSourceLocation());
}
@@ -1562,19 +1648,33 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
- if (Record.readInt()) // HasTemplateKWAndArgsInfo
+ unsigned NumResults = Record.readInt();
+ bool HasTemplateKWAndArgsInfo = Record.readInt();
+ assert((E->getNumDecls() == NumResults) && "Wrong NumResults!");
+ assert((E->hasTemplateKWAndArgsInfo() == HasTemplateKWAndArgsInfo) &&
+ "Wrong HasTemplateKWAndArgsInfo!");
+
+ if (HasTemplateKWAndArgsInfo) {
+ unsigned NumTemplateArgs = Record.readInt();
ReadTemplateKWAndArgsInfo(*E->getTrailingASTTemplateKWAndArgsInfo(),
E->getTrailingTemplateArgumentLoc(),
- /*NumTemplateArgs=*/Record.readInt());
+ NumTemplateArgs);
+ assert((E->getNumTemplateArgs() == NumTemplateArgs) &&
+ "Wrong NumTemplateArgs!");
+ }
- unsigned NumDecls = Record.readInt();
UnresolvedSet<8> Decls;
- for (unsigned i = 0; i != NumDecls; ++i) {
+ for (unsigned I = 0; I != NumResults; ++I) {
auto *D = ReadDeclAs<NamedDecl>();
auto AS = (AccessSpecifier)Record.readInt();
Decls.addDecl(D, AS);
}
- E->initializeResults(Record.getContext(), Decls.begin(), Decls.end());
+
+ DeclAccessPair *Results = E->getTrailingResults();
+ UnresolvedSetIterator Iter = Decls.begin();
+ for (unsigned I = 0; I != NumResults; ++I) {
+ Results[I] = (Iter + I).getPair();
+ }
ReadDeclarationNameInfo(E->NameInfo);
E->QualifierLoc = Record.readNestedNameSpecifierLoc();
@@ -1582,8 +1682,8 @@ void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
VisitOverloadExpr(E);
- E->IsArrow = Record.readInt();
- E->HasUnresolvedUsing = Record.readInt();
+ E->UnresolvedMemberExprBits.IsArrow = Record.readInt();
+ E->UnresolvedMemberExprBits.HasUnresolvedUsing = Record.readInt();
E->Base = Record.readSubExpr();
E->BaseType = Record.readType();
E->OperatorLoc = ReadSourceLocation();
@@ -1591,8 +1691,8 @@ void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
- E->RequiresADL = Record.readInt();
- E->Overloaded = Record.readInt();
+ E->UnresolvedLookupExprBits.RequiresADL = Record.readInt();
+ E->UnresolvedLookupExprBits.Overloaded = Record.readInt();
E->NamingClass = ReadDeclAs<CXXRecordDecl>();
}
@@ -1633,7 +1733,7 @@ void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
VisitExpr(E);
- E->Value = (bool)Record.readInt();
+ E->CXXNoexceptExprBits.Value = Record.readInt();
E->Range = ReadSourceRange();
E->Operand = Record.readSubExpr();
}
@@ -1667,7 +1767,7 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
VisitExpr(E);
E->Param = ReadDeclAs<NonTypeTemplateParmDecl>();
- E->NameLoc = ReadSourceLocation();
+ E->SubstNonTypeTemplateParmExprBits.NameLoc = ReadSourceLocation();
E->Replacement = Record.readSubExpr();
}
@@ -1715,7 +1815,7 @@ void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) {
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
E->SourceExpr = Record.readSubExpr();
- E->Loc = ReadSourceLocation();
+ E->OpaqueValueExprBits.Loc = ReadSourceLocation();
E->setIsUnique(Record.readInt());
}
@@ -1803,895 +1903,13 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) {
}
//===----------------------------------------------------------------------===//
-// OpenMP Clauses.
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-
-class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> {
- ASTStmtReader *Reader;
- ASTContext &Context;
-
-public:
- OMPClauseReader(ASTStmtReader *R, ASTRecordReader &Record)
- : Reader(R), Context(Record.getContext()) {}
-
-#define OPENMP_CLAUSE(Name, Class) void Visit##Class(Class *C);
-#include "clang/Basic/OpenMPKinds.def"
- OMPClause *readClause();
- void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
- void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);
-};
-
-} // namespace clang
-
-OMPClause *OMPClauseReader::readClause() {
- OMPClause *C;
- switch (Reader->Record.readInt()) {
- case OMPC_if:
- C = new (Context) OMPIfClause();
- break;
- case OMPC_final:
- C = new (Context) OMPFinalClause();
- break;
- case OMPC_num_threads:
- C = new (Context) OMPNumThreadsClause();
- break;
- case OMPC_safelen:
- C = new (Context) OMPSafelenClause();
- break;
- case OMPC_simdlen:
- C = new (Context) OMPSimdlenClause();
- break;
- case OMPC_collapse:
- C = new (Context) OMPCollapseClause();
- break;
- case OMPC_default:
- C = new (Context) OMPDefaultClause();
- break;
- case OMPC_proc_bind:
- C = new (Context) OMPProcBindClause();
- break;
- case OMPC_schedule:
- C = new (Context) OMPScheduleClause();
- break;
- case OMPC_ordered:
- C = new (Context) OMPOrderedClause();
- break;
- case OMPC_nowait:
- C = new (Context) OMPNowaitClause();
- break;
- case OMPC_untied:
- C = new (Context) OMPUntiedClause();
- break;
- case OMPC_mergeable:
- C = new (Context) OMPMergeableClause();
- break;
- case OMPC_read:
- C = new (Context) OMPReadClause();
- break;
- case OMPC_write:
- C = new (Context) OMPWriteClause();
- break;
- case OMPC_update:
- C = new (Context) OMPUpdateClause();
- break;
- case OMPC_capture:
- C = new (Context) OMPCaptureClause();
- break;
- case OMPC_seq_cst:
- C = new (Context) OMPSeqCstClause();
- break;
- case OMPC_threads:
- C = new (Context) OMPThreadsClause();
- break;
- case OMPC_simd:
- C = new (Context) OMPSIMDClause();
- break;
- case OMPC_nogroup:
- C = new (Context) OMPNogroupClause();
- break;
- case OMPC_private:
- C = OMPPrivateClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_firstprivate:
- C = OMPFirstprivateClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_lastprivate:
- C = OMPLastprivateClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_shared:
- C = OMPSharedClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_reduction:
- C = OMPReductionClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_task_reduction:
- C = OMPTaskReductionClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_in_reduction:
- C = OMPInReductionClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_linear:
- C = OMPLinearClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_aligned:
- C = OMPAlignedClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_copyin:
- C = OMPCopyinClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_copyprivate:
- C = OMPCopyprivateClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_flush:
- C = OMPFlushClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_depend:
- C = OMPDependClause::CreateEmpty(Context, Reader->Record.readInt());
- break;
- case OMPC_device:
- C = new (Context) OMPDeviceClause();
- break;
- case OMPC_map: {
- unsigned NumVars = Reader->Record.readInt();
- unsigned NumDeclarations = Reader->Record.readInt();
- unsigned NumLists = Reader->Record.readInt();
- unsigned NumComponents = Reader->Record.readInt();
- C = OMPMapClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
- NumComponents);
- break;
- }
- case OMPC_num_teams:
- C = new (Context) OMPNumTeamsClause();
- break;
- case OMPC_thread_limit:
- C = new (Context) OMPThreadLimitClause();
- break;
- case OMPC_priority:
- C = new (Context) OMPPriorityClause();
- break;
- case OMPC_grainsize:
- C = new (Context) OMPGrainsizeClause();
- break;
- case OMPC_num_tasks:
- C = new (Context) OMPNumTasksClause();
- break;
- case OMPC_hint:
- C = new (Context) OMPHintClause();
- break;
- case OMPC_dist_schedule:
- C = new (Context) OMPDistScheduleClause();
- break;
- case OMPC_defaultmap:
- C = new (Context) OMPDefaultmapClause();
- break;
- case OMPC_to: {
- unsigned NumVars = Reader->Record.readInt();
- unsigned NumDeclarations = Reader->Record.readInt();
- unsigned NumLists = Reader->Record.readInt();
- unsigned NumComponents = Reader->Record.readInt();
- C = OMPToClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
- NumComponents);
- break;
- }
- case OMPC_from: {
- unsigned NumVars = Reader->Record.readInt();
- unsigned NumDeclarations = Reader->Record.readInt();
- unsigned NumLists = Reader->Record.readInt();
- unsigned NumComponents = Reader->Record.readInt();
- C = OMPFromClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
- NumComponents);
- break;
- }
- case OMPC_use_device_ptr: {
- unsigned NumVars = Reader->Record.readInt();
- unsigned NumDeclarations = Reader->Record.readInt();
- unsigned NumLists = Reader->Record.readInt();
- unsigned NumComponents = Reader->Record.readInt();
- C = OMPUseDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations,
- NumLists, NumComponents);
- break;
- }
- case OMPC_is_device_ptr: {
- unsigned NumVars = Reader->Record.readInt();
- unsigned NumDeclarations = Reader->Record.readInt();
- unsigned NumLists = Reader->Record.readInt();
- unsigned NumComponents = Reader->Record.readInt();
- C = OMPIsDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations,
- NumLists, NumComponents);
- break;
- }
- }
- Visit(C);
- C->setLocStart(Reader->ReadSourceLocation());
- C->setLocEnd(Reader->ReadSourceLocation());
-
- return C;
-}
-
-void OMPClauseReader::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
- C->setPreInitStmt(Reader->Record.readSubStmt(),
- static_cast<OpenMPDirectiveKind>(Reader->Record.readInt()));
-}
-
-void OMPClauseReader::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {
- VisitOMPClauseWithPreInit(C);
- C->setPostUpdateExpr(Reader->Record.readSubExpr());
-}
-
-void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setNameModifier(static_cast<OpenMPDirectiveKind>(Reader->Record.readInt()));
- C->setNameModifierLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- C->setCondition(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) {
- C->setCondition(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setNumThreads(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) {
- C->setSafelen(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
- C->setSimdlen(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) {
- C->setNumForLoops(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
- C->setDefaultKind(
- static_cast<OpenMPDefaultClauseKind>(Reader->Record.readInt()));
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setDefaultKindKwLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
- C->setProcBindKind(
- static_cast<OpenMPProcBindClauseKind>(Reader->Record.readInt()));
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setProcBindKindKwLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setScheduleKind(
- static_cast<OpenMPScheduleClauseKind>(Reader->Record.readInt()));
- C->setFirstScheduleModifier(
- static_cast<OpenMPScheduleClauseModifier>(Reader->Record.readInt()));
- C->setSecondScheduleModifier(
- static_cast<OpenMPScheduleClauseModifier>(Reader->Record.readInt()));
- C->setChunkSize(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setFirstScheduleModifierLoc(Reader->ReadSourceLocation());
- C->setSecondScheduleModifierLoc(Reader->ReadSourceLocation());
- C->setScheduleKindLoc(Reader->ReadSourceLocation());
- C->setCommaLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) {
- C->setNumForLoops(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {}
-
-void OMPClauseReader::VisitOMPUntiedClause(OMPUntiedClause *) {}
-
-void OMPClauseReader::VisitOMPMergeableClause(OMPMergeableClause *) {}
-
-void OMPClauseReader::VisitOMPReadClause(OMPReadClause *) {}
-
-void OMPClauseReader::VisitOMPWriteClause(OMPWriteClause *) {}
-
-void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *) {}
-
-void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {}
-
-void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
-
-void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {}
-
-void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
-
-void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {}
-
-void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivateCopies(Vars);
-}
-
-void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setLParenLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivateCopies(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setInits(Vars);
-}
-
-void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
- VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivateCopies(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setSourceExprs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setDestinationExprs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setAssignmentOps(Vars);
-}
-
-void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
-}
-
-void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
- VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc();
- DeclarationNameInfo DNI;
- Reader->ReadDeclarationNameInfo(DNI);
- C->setQualifierLoc(NNSL);
- C->setNameInfo(DNI);
-
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivates(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setLHSExprs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setRHSExprs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setReductionOps(Vars);
-}
-
-void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
- VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc();
- DeclarationNameInfo DNI;
- Reader->ReadDeclarationNameInfo(DNI);
- C->setQualifierLoc(NNSL);
- C->setNameInfo(DNI);
-
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivates(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setLHSExprs(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setRHSExprs(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setReductionOps(Vars);
-}
-
-void OMPClauseReader::VisitOMPInReductionClause(OMPInReductionClause *C) {
- VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc();
- DeclarationNameInfo DNI;
- Reader->ReadDeclarationNameInfo(DNI);
- C->setQualifierLoc(NNSL);
- C->setNameInfo(DNI);
-
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivates(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setLHSExprs(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setRHSExprs(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setReductionOps(Vars);
- Vars.clear();
- for (unsigned I = 0; I != NumVars; ++I)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setTaskgroupDescriptors(Vars);
-}
-
-void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
- VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- C->setModifier(static_cast<OpenMPLinearClauseKind>(Reader->Record.readInt()));
- C->setModifierLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivates(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setInits(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setUpdates(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setFinals(Vars);
- C->setStep(Reader->Record.readSubExpr());
- C->setCalcStep(Reader->Record.readSubExpr());
-}
-
-void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- C->setAlignment(Reader->Record.readSubExpr());
-}
-
-void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Exprs;
- Exprs.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Exprs);
- Exprs.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setSourceExprs(Exprs);
- Exprs.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setDestinationExprs(Exprs);
- Exprs.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setAssignmentOps(Exprs);
-}
-
-void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Exprs;
- Exprs.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Exprs);
- Exprs.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setSourceExprs(Exprs);
- Exprs.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setDestinationExprs(Exprs);
- Exprs.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Record.readSubExpr());
- C->setAssignmentOps(Exprs);
-}
-
-void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
-}
-
-void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setDependencyKind(
- static_cast<OpenMPDependClauseKind>(Reader->Record.readInt()));
- C->setDependencyLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- unsigned NumVars = C->varlist_size();
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- C->setCounterValue(Reader->Record.readSubExpr());
-}
-
-void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setDevice(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setMapTypeModifier(
- static_cast<OpenMPMapClauseKind>(Reader->Record.readInt()));
- C->setMapType(
- static_cast<OpenMPMapClauseKind>(Reader->Record.readInt()));
- C->setMapLoc(Reader->ReadSourceLocation());
- C->setColonLoc(Reader->ReadSourceLocation());
- auto NumVars = C->varlist_size();
- auto UniqueDecls = C->getUniqueDeclarationsNum();
- auto TotalLists = C->getTotalComponentListNum();
- auto TotalComponents = C->getTotalComponentsNum();
-
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
-
- SmallVector<ValueDecl *, 16> Decls;
- Decls.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
- C->setUniqueDecls(Decls);
-
- SmallVector<unsigned, 16> ListsPerDecl;
- ListsPerDecl.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Reader->Record.readInt());
- C->setDeclNumLists(ListsPerDecl);
-
- SmallVector<unsigned, 32> ListSizes;
- ListSizes.reserve(TotalLists);
- for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Reader->Record.readInt());
- C->setComponentListSizes(ListSizes);
-
- SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
- Components.reserve(TotalComponents);
- for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Record.readSubExpr();
- auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
- Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
- AssociatedExpr, AssociatedDecl));
- }
- C->setComponents(Components, ListSizes);
-}
-
-void OMPClauseReader::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setNumTeams(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setThreadLimit(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) {
- C->setPriority(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
- C->setGrainsize(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
- C->setNumTasks(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) {
- C->setHint(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
- VisitOMPClauseWithPreInit(C);
- C->setDistScheduleKind(
- static_cast<OpenMPDistScheduleClauseKind>(Reader->Record.readInt()));
- C->setChunkSize(Reader->Record.readSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setDistScheduleKindLoc(Reader->ReadSourceLocation());
- C->setCommaLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {
- C->setDefaultmapKind(
- static_cast<OpenMPDefaultmapClauseKind>(Reader->Record.readInt()));
- C->setDefaultmapModifier(
- static_cast<OpenMPDefaultmapClauseModifier>(Reader->Record.readInt()));
- C->setLParenLoc(Reader->ReadSourceLocation());
- C->setDefaultmapModifierLoc(Reader->ReadSourceLocation());
- C->setDefaultmapKindLoc(Reader->ReadSourceLocation());
-}
-
-void OMPClauseReader::VisitOMPToClause(OMPToClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- auto NumVars = C->varlist_size();
- auto UniqueDecls = C->getUniqueDeclarationsNum();
- auto TotalLists = C->getTotalComponentListNum();
- auto TotalComponents = C->getTotalComponentsNum();
-
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
-
- SmallVector<ValueDecl *, 16> Decls;
- Decls.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
- C->setUniqueDecls(Decls);
-
- SmallVector<unsigned, 16> ListsPerDecl;
- ListsPerDecl.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Reader->Record.readInt());
- C->setDeclNumLists(ListsPerDecl);
-
- SmallVector<unsigned, 32> ListSizes;
- ListSizes.reserve(TotalLists);
- for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Reader->Record.readInt());
- C->setComponentListSizes(ListSizes);
-
- SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
- Components.reserve(TotalComponents);
- for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Record.readSubExpr();
- auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
- Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
- AssociatedExpr, AssociatedDecl));
- }
- C->setComponents(Components, ListSizes);
-}
-
-void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- auto NumVars = C->varlist_size();
- auto UniqueDecls = C->getUniqueDeclarationsNum();
- auto TotalLists = C->getTotalComponentListNum();
- auto TotalComponents = C->getTotalComponentsNum();
-
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
-
- SmallVector<ValueDecl *, 16> Decls;
- Decls.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
- C->setUniqueDecls(Decls);
-
- SmallVector<unsigned, 16> ListsPerDecl;
- ListsPerDecl.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Reader->Record.readInt());
- C->setDeclNumLists(ListsPerDecl);
-
- SmallVector<unsigned, 32> ListSizes;
- ListSizes.reserve(TotalLists);
- for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Reader->Record.readInt());
- C->setComponentListSizes(ListSizes);
-
- SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
- Components.reserve(TotalComponents);
- for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Record.readSubExpr();
- auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
- Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
- AssociatedExpr, AssociatedDecl));
- }
- C->setComponents(Components, ListSizes);
-}
-
-void OMPClauseReader::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- auto NumVars = C->varlist_size();
- auto UniqueDecls = C->getUniqueDeclarationsNum();
- auto TotalLists = C->getTotalComponentListNum();
- auto TotalComponents = C->getTotalComponentsNum();
-
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setPrivateCopies(Vars);
- Vars.clear();
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setInits(Vars);
-
- SmallVector<ValueDecl *, 16> Decls;
- Decls.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
- C->setUniqueDecls(Decls);
-
- SmallVector<unsigned, 16> ListsPerDecl;
- ListsPerDecl.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Reader->Record.readInt());
- C->setDeclNumLists(ListsPerDecl);
-
- SmallVector<unsigned, 32> ListSizes;
- ListSizes.reserve(TotalLists);
- for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Reader->Record.readInt());
- C->setComponentListSizes(ListSizes);
-
- SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
- Components.reserve(TotalComponents);
- for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Record.readSubExpr();
- auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
- Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
- AssociatedExpr, AssociatedDecl));
- }
- C->setComponents(Components, ListSizes);
-}
-
-void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation());
- auto NumVars = C->varlist_size();
- auto UniqueDecls = C->getUniqueDeclarationsNum();
- auto TotalLists = C->getTotalComponentListNum();
- auto TotalComponents = C->getTotalComponentsNum();
-
- SmallVector<Expr *, 16> Vars;
- Vars.reserve(NumVars);
- for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Record.readSubExpr());
- C->setVarRefs(Vars);
- Vars.clear();
-
- SmallVector<ValueDecl *, 16> Decls;
- Decls.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
- C->setUniqueDecls(Decls);
-
- SmallVector<unsigned, 16> ListsPerDecl;
- ListsPerDecl.reserve(UniqueDecls);
- for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Reader->Record.readInt());
- C->setDeclNumLists(ListsPerDecl);
-
- SmallVector<unsigned, 32> ListSizes;
- ListSizes.reserve(TotalLists);
- for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Reader->Record.readInt());
- C->setComponentListSizes(ListSizes);
-
- SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
- Components.reserve(TotalComponents);
- for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Record.readSubExpr();
- auto *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
- Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
- AssociatedExpr, AssociatedDecl));
- }
- C->setComponents(Components, ListSizes);
-}
-
-//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
E->setLocStart(ReadSourceLocation());
E->setLocEnd(ReadSourceLocation());
- OMPClauseReader ClauseReader(this, Record);
+ OMPClauseReader ClauseReader(Record);
SmallVector<OMPClause *, 5> Clauses;
for (unsigned i = 0; i < E->getNumClauses(); ++i)
Clauses.push_back(ClauseReader.readClause());
@@ -2737,6 +1955,8 @@ void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
D->setCombinedCond(Record.readSubExpr());
D->setCombinedNextLowerBound(Record.readSubExpr());
D->setCombinedNextUpperBound(Record.readSubExpr());
+ D->setCombinedDistCond(Record.readSubExpr());
+ D->setCombinedParForInDistCond(Record.readSubExpr());
}
SmallVector<Expr *, 4> Sub;
unsigned CollapsedNum = D->getCollapsedNumber();
@@ -3142,7 +2362,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_CASE:
- S = new (Context) CaseStmt(Empty);
+ S = CaseStmt::CreateEmpty(
+ Context,
+ /*CaseStmtIsGNURange*/ Record[ASTStmtReader::NumStmtFields + 3]);
break;
case STMT_DEFAULT:
@@ -3160,15 +2382,24 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_IF:
- S = new (Context) IfStmt(Empty);
+ S = IfStmt::CreateEmpty(
+ Context,
+ /* HasElse=*/Record[ASTStmtReader::NumStmtFields + 1],
+ /* HasVar=*/Record[ASTStmtReader::NumStmtFields + 2],
+ /* HasInit=*/Record[ASTStmtReader::NumStmtFields + 3]);
break;
case STMT_SWITCH:
- S = new (Context) SwitchStmt(Empty);
+ S = SwitchStmt::CreateEmpty(
+ Context,
+ /* HasInit=*/Record[ASTStmtReader::NumStmtFields],
+ /* HasVar=*/Record[ASTStmtReader::NumStmtFields + 1]);
break;
case STMT_WHILE:
- S = new (Context) WhileStmt(Empty);
+ S = WhileStmt::CreateEmpty(
+ Context,
+ /* HasVar=*/Record[ASTStmtReader::NumStmtFields]);
break;
case STMT_DO:
@@ -3196,7 +2427,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_RETURN:
- S = new (Context) ReturnStmt(Empty);
+ S = ReturnStmt::CreateEmpty(
+ Context, /* HasNRVOCandidate=*/Record[ASTStmtReader::NumStmtFields]);
break;
case STMT_DECL:
@@ -3212,12 +2444,18 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_CAPTURED:
- S = CapturedStmt::CreateDeserialized(Context,
- Record[ASTStmtReader::NumStmtFields]);
+ S = CapturedStmt::CreateDeserialized(
+ Context, Record[ASTStmtReader::NumStmtFields]);
+ break;
+
+ case EXPR_CONSTANT:
+ S = new (Context) ConstantExpr(Empty);
break;
case EXPR_PREDEFINED:
- S = new (Context) PredefinedExpr(Empty);
+ S = PredefinedExpr::CreateEmpty(
+ Context,
+ /*HasFunctionName*/ Record[ASTStmtReader::NumExprFields]);
break;
case EXPR_DECL_REF:
@@ -3243,8 +2481,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_STRING_LITERAL:
- S = StringLiteral::CreateEmpty(Context,
- Record[ASTStmtReader::NumExprFields + 1]);
+ S = StringLiteral::CreateEmpty(
+ Context,
+ /* NumConcatenated=*/Record[ASTStmtReader::NumExprFields],
+ /* Length=*/Record[ASTStmtReader::NumExprFields + 1],
+ /* CharByteWidth=*/Record[ASTStmtReader::NumExprFields + 2]);
break;
case EXPR_CHARACTER_LITERAL:
@@ -3256,7 +2497,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_PAREN_LIST:
- S = new (Context) ParenListExpr(Empty);
+ S = ParenListExpr::CreateEmpty(
+ Context,
+ /* NumExprs=*/Record[ASTStmtReader::NumExprFields]);
break;
case EXPR_UNARY_OPERATOR:
@@ -3282,7 +2525,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CALL:
- S = new (Context) CallExpr(Context, Stmt::CallExprClass, Empty);
+ S = CallExpr::CreateEmpty(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
break;
case EXPR_MEMBER: {
@@ -3872,15 +3116,19 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
}
case EXPR_CXX_OPERATOR_CALL:
- S = new (Context) CXXOperatorCallExpr(Context, Empty);
+ S = CXXOperatorCallExpr::CreateEmpty(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
break;
case EXPR_CXX_MEMBER_CALL:
- S = new (Context) CXXMemberCallExpr(Context, Empty);
+ S = CXXMemberCallExpr::CreateEmpty(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
break;
case EXPR_CXX_CONSTRUCT:
- S = new (Context) CXXConstructExpr(Empty);
+ S = CXXConstructExpr::CreateEmpty(
+ Context,
+ /* NumArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
case EXPR_CXX_INHERITED_CTOR_INIT:
@@ -3888,7 +3136,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CXX_TEMPORARY_OBJECT:
- S = new (Context) CXXTemporaryObjectExpr(Empty);
+ S = CXXTemporaryObjectExpr::CreateEmpty(
+ Context,
+ /* NumArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
case EXPR_CXX_STATIC_CAST:
@@ -3916,7 +3166,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_USER_DEFINED_LITERAL:
- S = new (Context) UserDefinedLiteral(Context, Empty);
+ S = UserDefinedLiteral::CreateEmpty(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
break;
case EXPR_CXX_STD_INITIALIZER_LIST:
@@ -3980,7 +3231,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CXX_NEW:
- S = new (Context) CXXNewExpr(Empty);
+ S = CXXNewExpr::CreateEmpty(
+ Context,
+ /*IsArray=*/Record[ASTStmtReader::NumExprFields],
+ /*HasInit=*/Record[ASTStmtReader::NumExprFields + 1],
+ /*NumPlacementArgs=*/Record[ASTStmtReader::NumExprFields + 2],
+ /*IsParenTypeId=*/Record[ASTStmtReader::NumExprFields + 3]);
break;
case EXPR_CXX_DELETE:
@@ -3997,11 +3253,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
- S = CXXDependentScopeMemberExpr::CreateEmpty(Context,
- /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
- /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
- ? Record[ASTStmtReader::NumExprFields + 1]
- : 0);
+ S = CXXDependentScopeMemberExpr::CreateEmpty(
+ Context,
+ /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1],
+ /*HasFirstQualifierFoundInScope=*/
+ Record[ASTStmtReader::NumExprFields + 2]);
break;
case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
@@ -4018,19 +3275,25 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CXX_UNRESOLVED_MEMBER:
- S = UnresolvedMemberExpr::CreateEmpty(Context,
- /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
- /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
- ? Record[ASTStmtReader::NumExprFields + 1]
- : 0);
+ S = UnresolvedMemberExpr::CreateEmpty(
+ Context,
+ /*NumResults=*/Record[ASTStmtReader::NumExprFields],
+ /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 1],
+ /*NumTemplateArgs=*/
+ Record[ASTStmtReader::NumExprFields + 1]
+ ? Record[ASTStmtReader::NumExprFields + 2]
+ : 0);
break;
case EXPR_CXX_UNRESOLVED_LOOKUP:
- S = UnresolvedLookupExpr::CreateEmpty(Context,
- /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
- /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
- ? Record[ASTStmtReader::NumExprFields + 1]
- : 0);
+ S = UnresolvedLookupExpr::CreateEmpty(
+ Context,
+ /*NumResults=*/Record[ASTStmtReader::NumExprFields],
+ /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 1],
+ /*NumTemplateArgs=*/
+ Record[ASTStmtReader::NumExprFields + 1]
+ ? Record[ASTStmtReader::NumExprFields + 2]
+ : 0);
break;
case EXPR_TYPE_TRAIT:
@@ -4086,7 +3349,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CUDA_KERNEL_CALL:
- S = new (Context) CUDAKernelCallExpr(Context, Empty);
+ S = CUDAKernelCallExpr::CreateEmpty(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
break;
case EXPR_ASTYPE:
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 1a8d806e9d24..37adcb70640d 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -310,7 +310,7 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
Record.push_back(T->isVariadic());
Record.push_back(T->hasTrailingReturn());
- Record.push_back(T->getTypeQuals());
+ Record.push_back(T->getTypeQuals().getAsOpaqueValue());
Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
addExceptionSpec(T, Record);
@@ -770,19 +770,7 @@ void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
}
void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- Record.AddSourceLocation(TL.getAttrNameLoc());
- if (TL.hasAttrOperand()) {
- SourceRange range = TL.getAttrOperandParensRange();
- Record.AddSourceLocation(range.getBegin());
- Record.AddSourceLocation(range.getEnd());
- }
- if (TL.hasAttrExprOperand()) {
- Expr *operand = TL.getAttrExprOperand();
- Record.push_back(operand ? 1 : 0);
- if (operand) Record.AddStmt(operand);
- } else if (TL.hasAttrEnumOperand()) {
- Record.AddSourceLocation(TL.getAttrEnumOperandLoc());
- }
+ Record.AddAttr(TL.getAttr());
}
void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
@@ -1707,7 +1695,6 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
// Detailed record is important since it is used for the module cache hash.
Record.push_back(PPOpts.DetailedRecord);
AddString(PPOpts.ImplicitPCHInclude, Record);
- AddString(PPOpts.ImplicitPTHInclude, Record);
Record.push_back(static_cast<unsigned>(PPOpts.ObjCXXARCStandardLibrary));
Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record);
@@ -2507,8 +2494,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
MacroIdentifiers.push_back(Id.second);
// Sort the set of macro definitions that need to be serialized by the
// name of the macro, to provide a stable ordering.
- llvm::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
- llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(MacroIdentifiers, llvm::less_ptr<IdentifierInfo>());
// Emit the macro directives as a list and associate the offset with the
// identifier they belong to.
@@ -3242,8 +3228,7 @@ void ASTWriter::WriteFileDeclIDsMap() {
SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs(
FileDeclIDs.begin(), FileDeclIDs.end());
- llvm::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(),
- llvm::less_first());
+ llvm::sort(SortedFileDeclIDs, llvm::less_first());
// Join the vectors of DeclIDs from all files.
SmallVector<DeclID, 256> FileGroupedDeclIDs;
@@ -3586,7 +3571,7 @@ class ASTIdentifierTableTrait {
II->isPoisoned() ||
(IsModule ? II->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) ||
II->hasRevertedTokenIDToIdentifier() ||
- (NeedDecls && II->getFETokenInfo<void>()))
+ (NeedDecls && II->getFETokenInfo()))
return true;
return false;
@@ -3749,7 +3734,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
IIs.push_back(ID.second);
// Sort the identifiers lexicographically before getting them references so
// that their order is stable.
- llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(IIs, llvm::less_ptr<IdentifierInfo>());
for (const IdentifierInfo *II : IIs)
if (Trait.isInterestingNonMacroIdentifier(II))
getIdentifierRef(II);
@@ -3960,7 +3945,8 @@ public:
bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
DeclContext *DC) {
- return Result.hasExternalDecls() && DC->NeedToReconcileExternalVisibleStorage;
+ return Result.hasExternalDecls() &&
+ DC->hasNeedToReconcileExternalVisibleStorage();
}
bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
@@ -3975,8 +3961,8 @@ bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
void
ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
llvm::SmallVectorImpl<char> &LookupTable) {
- assert(!ConstDC->HasLazyLocalLexicalLookups &&
- !ConstDC->HasLazyExternalLexicalLookups &&
+ assert(!ConstDC->hasLazyLocalLexicalLookups() &&
+ !ConstDC->hasLazyExternalLexicalLookups() &&
"must call buildLookups first");
// FIXME: We need to build the lookups table, which is logically const.
@@ -4046,7 +4032,7 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
}
// Sort the names into a stable order.
- llvm::sort(Names.begin(), Names.end());
+ llvm::sort(Names);
if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {
// We need to establish an ordering of constructor and conversion function
@@ -4183,7 +4169,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
std::make_pair(Entry.first, Entry.second.getLookupResult()));
}
- llvm::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
+ llvm::sort(LookupResults, llvm::less_first());
for (auto &NameAndResult : LookupResults) {
DeclarationName Name = NameAndResult.first;
DeclContext::lookup_result Result = NameAndResult.second;
@@ -4480,16 +4466,21 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
// General Serialization Routines
//===----------------------------------------------------------------------===//
-/// Emit the list of attributes to the specified record.
-void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
+void ASTRecordWriter::AddAttr(const Attr *A) {
auto &Record = *this;
- Record.push_back(Attrs.size());
- for (const auto *A : Attrs) {
- Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
- Record.AddSourceRange(A->getRange());
+ if (!A)
+ return Record.push_back(0);
+ Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs
+ Record.AddSourceRange(A->getRange());
#include "clang/Serialization/AttrPCHWrite.inc"
- }
+}
+
+/// Emit the list of attributes to the specified record.
+void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
+ push_back(Attrs.size());
+ for (const auto *A : Attrs)
+ AddAttr(A);
}
void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {
@@ -4881,7 +4872,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
IIs.push_back(II);
}
// Sort the identifiers to visit based on their name.
- llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ llvm::sort(IIs, llvm::less_ptr<IdentifierInfo>());
for (const IdentifierInfo *II : IIs) {
for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
DEnd = SemaRef.IdResolver.end();
@@ -5022,13 +5013,16 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
WriteFPPragmaOptions(SemaRef.getFPOptions());
WriteOpenCLExtensions(SemaRef);
WriteOpenCLExtensionTypes(SemaRef);
- WriteOpenCLExtensionDecls(SemaRef);
WriteCUDAPragmas(SemaRef);
// If we're emitting a module, write out the submodule information.
if (WritingModule)
WriteSubmodules(WritingModule);
+ // We need to have information about submodules to correctly deserialize
+ // decls from OpenCLExtensionDecls block
+ WriteOpenCLExtensionDecls(SemaRef);
+
Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
// Write the record containing external, unnamed definitions.
@@ -5118,7 +5112,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
};
// Sort and deduplicate module IDs.
- llvm::sort(Imports.begin(), Imports.end(), Cmp);
+ llvm::sort(Imports, Cmp);
Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq),
Imports.end());
@@ -5254,7 +5248,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
}
Record.push_back(RD->getTagKind());
Record.AddSourceLocation(RD->getLocation());
- Record.AddSourceLocation(RD->getLocStart());
+ Record.AddSourceLocation(RD->getBeginLoc());
Record.AddSourceRange(RD->getBraceRange());
// Instantiation may change attributes; write them all out afresh.
@@ -5295,6 +5289,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
break;
case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
+ Record.push_back(D->getAttr<OMPDeclareTargetDeclAttr>()->getMapType());
Record.AddSourceRange(
D->getAttr<OMPDeclareTargetDeclAttr>()->getRange());
break;
@@ -6472,3 +6467,489 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
DeclsToEmitEvenIfUnreferenced.push_back(D);
}
+
+//===----------------------------------------------------------------------===//
+//// OMPClause Serialization
+////===----------------------------------------------------------------------===//
+
+void OMPClauseWriter::writeClause(OMPClause *C) {
+ Record.push_back(C->getClauseKind());
+ Visit(C);
+ Record.AddSourceLocation(C->getBeginLoc());
+ Record.AddSourceLocation(C->getEndLoc());
+}
+
+void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
+ Record.push_back(C->getCaptureRegion());
+ Record.AddStmt(C->getPreInitStmt());
+}
+
+void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getPostUpdateExpr());
+}
+
+void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.push_back(C->getNameModifier());
+ Record.AddSourceLocation(C->getNameModifierLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ Record.AddStmt(C->getCondition());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) {
+ Record.AddStmt(C->getCondition());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getNumThreads());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {
+ Record.AddStmt(C->getSafelen());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
+ Record.AddStmt(C->getSimdlen());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {
+ Record.AddStmt(C->getNumForLoops());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
+ Record.push_back(C->getDefaultKind());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getDefaultKindKwLoc());
+}
+
+void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
+ Record.push_back(C->getProcBindKind());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getProcBindKindKwLoc());
+}
+
+void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.push_back(C->getScheduleKind());
+ Record.push_back(C->getFirstScheduleModifier());
+ Record.push_back(C->getSecondScheduleModifier());
+ Record.AddStmt(C->getChunkSize());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getFirstScheduleModifierLoc());
+ Record.AddSourceLocation(C->getSecondScheduleModifierLoc());
+ Record.AddSourceLocation(C->getScheduleKindLoc());
+ Record.AddSourceLocation(C->getCommaLoc());
+}
+
+void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ Record.push_back(C->getLoopNumIterations().size());
+ Record.AddStmt(C->getNumForLoops());
+ for (Expr *NumIter : C->getLoopNumIterations())
+ Record.AddStmt(NumIter);
+ for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I)
+ Record.AddStmt(C->getLoopCounter(I));
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {}
+
+void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {}
+
+void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {}
+
+void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {}
+
+void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {}
+
+void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {}
+
+void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}
+
+void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+
+void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}
+
+void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}
+
+void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}
+
+void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *VE : C->varlists()) {
+ Record.AddStmt(VE);
+ }
+ for (auto *VE : C->private_copies()) {
+ Record.AddStmt(VE);
+ }
+}
+
+void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPreInit(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *VE : C->varlists()) {
+ Record.AddStmt(VE);
+ }
+ for (auto *VE : C->private_copies()) {
+ Record.AddStmt(VE);
+ }
+ for (auto *VE : C->inits()) {
+ Record.AddStmt(VE);
+ }
+}
+
+void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *E : C->private_copies())
+ Record.AddStmt(E);
+ for (auto *E : C->source_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Record.AddStmt(E);
+}
+
+void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+}
+
+void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
+ Record.AddDeclarationNameInfo(C->getNameInfo());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *VE : C->privates())
+ Record.AddStmt(VE);
+ for (auto *E : C->lhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->rhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->reduction_ops())
+ Record.AddStmt(E);
+}
+
+void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
+ Record.AddDeclarationNameInfo(C->getNameInfo());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *VE : C->privates())
+ Record.AddStmt(VE);
+ for (auto *E : C->lhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->rhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->reduction_ops())
+ Record.AddStmt(E);
+}
+
+void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
+ Record.AddDeclarationNameInfo(C->getNameInfo());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *VE : C->privates())
+ Record.AddStmt(VE);
+ for (auto *E : C->lhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->rhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->reduction_ops())
+ Record.AddStmt(E);
+ for (auto *E : C->taskgroup_descriptors())
+ Record.AddStmt(E);
+}
+
+void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ Record.push_back(C->getModifier());
+ Record.AddSourceLocation(C->getModifierLoc());
+ for (auto *VE : C->varlists()) {
+ Record.AddStmt(VE);
+ }
+ for (auto *VE : C->privates()) {
+ Record.AddStmt(VE);
+ }
+ for (auto *VE : C->inits()) {
+ Record.AddStmt(VE);
+ }
+ for (auto *VE : C->updates()) {
+ Record.AddStmt(VE);
+ }
+ for (auto *VE : C->finals()) {
+ Record.AddStmt(VE);
+ }
+ Record.AddStmt(C->getStep());
+ Record.AddStmt(C->getCalcStep());
+}
+
+void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ Record.AddStmt(C->getAlignment());
+}
+
+void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *E : C->source_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Record.AddStmt(E);
+}
+
+void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *E : C->source_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->destination_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->assignment_ops())
+ Record.AddStmt(E);
+}
+
+void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+}
+
+void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.push_back(C->getNumLoops());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.push_back(C->getDependencyKind());
+ Record.AddSourceLocation(C->getDependencyLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
+ Record.AddStmt(C->getLoopData(I));
+}
+
+void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getDevice());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) {
+ Record.push_back(C->getMapTypeModifier(I));
+ Record.AddSourceLocation(C->getMapTypeModifierLoc(I));
+ }
+ Record.push_back(C->getMapType());
+ Record.AddSourceLocation(C->getMapLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
+ }
+}
+
+void OMPClauseWriter::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getNumTeams());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getThreadLimit());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) {
+ Record.AddStmt(C->getPriority());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
+ Record.AddStmt(C->getGrainsize());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
+ Record.AddStmt(C->getNumTasks());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {
+ Record.AddStmt(C->getHint());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.push_back(C->getDistScheduleKind());
+ Record.AddStmt(C->getChunkSize());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getDistScheduleKindLoc());
+ Record.AddSourceLocation(C->getCommaLoc());
+}
+
+void OMPClauseWriter::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {
+ Record.push_back(C->getDefaultmapKind());
+ Record.push_back(C->getDefaultmapModifier());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getDefaultmapModifierLoc());
+ Record.AddSourceLocation(C->getDefaultmapKindLoc());
+}
+
+void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
+ }
+}
+
+void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
+ }
+}
+
+void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *VE : C->private_copies())
+ Record.AddStmt(VE);
+ for (auto *VE : C->inits())
+ Record.AddStmt(VE);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
+ }
+}
+
+void OMPClauseWriter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
+ }
+}
+
+void OMPClauseWriter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}
+
+void OMPClauseWriter::VisitOMPUnifiedSharedMemoryClause(
+ OMPUnifiedSharedMemoryClause *) {}
+
+void OMPClauseWriter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {}
+
+void
+OMPClauseWriter::VisitOMPDynamicAllocatorsClause(OMPDynamicAllocatorsClause *) {
+}
+
+void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause(
+ OMPAtomicDefaultMemOrderClause *C) {
+ Record.push_back(C->getAtomicDefaultMemOrderKind());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc());
+}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 7286f2cac178..002b43f81121 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Serialization/ASTReader.h"
@@ -144,6 +145,7 @@ namespace clang {
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
+ void VisitOMPRequiresDecl(OMPRequiresDecl *D);
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
@@ -328,7 +330,7 @@ void ASTDeclWriter::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
StringRef Arg = D->getArg();
Record.push_back(Arg.size());
VisitDecl(D);
- Record.AddSourceLocation(D->getLocStart());
+ Record.AddSourceLocation(D->getBeginLoc());
Record.push_back(D->getCommentKind());
Record.AddString(Arg);
Code = serialization::DECL_PRAGMA_COMMENT;
@@ -340,7 +342,7 @@ void ASTDeclWriter::VisitPragmaDetectMismatchDecl(
StringRef Value = D->getValue();
Record.push_back(Name.size() + 1 + Value.size());
VisitDecl(D);
- Record.AddSourceLocation(D->getLocStart());
+ Record.AddSourceLocation(D->getBeginLoc());
Record.AddString(Name);
Record.AddString(Value);
Code = serialization::DECL_PRAGMA_DETECT_MISMATCH;
@@ -360,7 +362,7 @@ void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
VisitNamedDecl(D);
- Record.AddSourceLocation(D->getLocStart());
+ Record.AddSourceLocation(D->getBeginLoc());
Record.AddTypeRef(QualType(D->getTypeForDecl(), 0));
}
@@ -529,28 +531,27 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
// FunctionDecl's body is handled last at ASTWriterDecl::Visit,
// after everything else is written.
-
- Record.push_back((int)D->SClass); // FIXME: stable encoding
- Record.push_back(D->IsInline);
- Record.push_back(D->IsInlineSpecified);
- Record.push_back(D->IsExplicitSpecified);
- Record.push_back(D->IsVirtualAsWritten);
- Record.push_back(D->IsPure);
- Record.push_back(D->HasInheritedPrototype);
- Record.push_back(D->HasWrittenPrototype);
- Record.push_back(D->IsDeleted);
- Record.push_back(D->IsTrivial);
- Record.push_back(D->IsTrivialForCall);
- Record.push_back(D->IsDefaulted);
- Record.push_back(D->IsExplicitlyDefaulted);
- Record.push_back(D->HasImplicitReturnZero);
- Record.push_back(D->IsConstexpr);
- Record.push_back(D->UsesSEHTry);
- Record.push_back(D->HasSkippedBody);
- Record.push_back(D->IsMultiVersion);
- Record.push_back(D->IsLateTemplateParsed);
+ Record.push_back(static_cast<int>(D->getStorageClass())); // FIXME: stable encoding
+ Record.push_back(D->isInlineSpecified());
+ Record.push_back(D->isInlined());
+ Record.push_back(D->isExplicitSpecified());
+ Record.push_back(D->isVirtualAsWritten());
+ Record.push_back(D->isPure());
+ Record.push_back(D->hasInheritedPrototype());
+ Record.push_back(D->hasWrittenPrototype());
+ Record.push_back(D->isDeletedBit());
+ Record.push_back(D->isTrivial());
+ Record.push_back(D->isTrivialForCall());
+ Record.push_back(D->isDefaulted());
+ Record.push_back(D->isExplicitlyDefaulted());
+ Record.push_back(D->hasImplicitReturnZero());
+ Record.push_back(D->isConstexpr());
+ Record.push_back(D->usesSEHTry());
+ Record.push_back(D->hasSkippedBody());
+ Record.push_back(D->isMultiVersion());
+ Record.push_back(D->isLateTemplateParsed());
Record.push_back(D->getLinkageInternal());
- Record.AddSourceLocation(D->getLocEnd());
+ Record.AddSourceLocation(D->getEndLoc());
Record.push_back(D->getODRHash());
@@ -628,7 +629,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
VisitFunctionDecl(D);
- Record.push_back(D->IsCopyDeductionCandidate);
+ Record.push_back(D->isCopyDeductionCandidate());
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
}
@@ -648,12 +649,12 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Record.push_back(D->isVariadic());
Record.push_back(D->isPropertyAccessor());
Record.push_back(D->isDefined());
- Record.push_back(D->IsOverriding);
- Record.push_back(D->HasSkippedBody);
+ Record.push_back(D->isOverriding());
+ Record.push_back(D->hasSkippedBody());
- Record.push_back(D->IsRedeclaration);
- Record.push_back(D->HasRedeclaration);
- if (D->HasRedeclaration) {
+ Record.push_back(D->isRedeclaration());
+ Record.push_back(D->hasRedeclaration());
+ if (D->hasRedeclaration()) {
assert(Context.getObjCMethodRedeclaration(D));
Record.AddDeclRef(Context.getObjCMethodRedeclaration(D));
}
@@ -665,12 +666,12 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Record.push_back(D->hasRelatedResultType());
Record.AddTypeRef(D->getReturnType());
Record.AddTypeSourceInfo(D->getReturnTypeSourceInfo());
- Record.AddSourceLocation(D->getLocEnd());
+ Record.AddSourceLocation(D->getEndLoc());
Record.push_back(D->param_size());
for (const auto *P : D->parameters())
Record.AddDeclRef(P);
- Record.push_back(D->SelLocsKind);
+ Record.push_back(D->getSelLocsKind());
unsigned NumStoredSelLocs = D->getNumStoredSelLocs();
SourceLocation *SelLocs = D->getStoredSelLocs();
Record.push_back(NumStoredSelLocs);
@@ -854,7 +855,7 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
VisitDecl(D);
- Record.AddSourceLocation(D->getLocStart());
+ Record.AddSourceLocation(D->getBeginLoc());
Record.AddDeclRef(D->getPropertyDecl());
Record.AddDeclRef(D->getPropertyIvarDecl());
Record.AddSourceLocation(D->getPropertyIvarDeclLoc());
@@ -921,13 +922,13 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(D->getStorageClass());
Record.push_back(D->getTSCSpec());
Record.push_back(D->getInitStyle());
+ Record.push_back(D->isARCPseudoStrong());
if (!isa<ParmVarDecl>(D)) {
Record.push_back(D->isThisDeclarationADemotedDefinition());
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
Record.push_back(D->isCXXForRangeDecl());
Record.push_back(D->isObjCForDecl());
- Record.push_back(D->isARCPseudoStrong());
Record.push_back(D->isInline());
Record.push_back(D->isInlineSpecified());
Record.push_back(D->isConstexpr());
@@ -937,6 +938,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(static_cast<unsigned>(IPD->getParameterKind()));
else
Record.push_back(0);
+ Record.push_back(D->isEscapingByref());
}
Record.push_back(D->getLinkageInternal());
@@ -947,6 +949,13 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(0);
}
+ if (D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) {
+ ASTContext::BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D);
+ Record.AddStmt(Init.getCopyExpr());
+ if (Init.getCopyExpr())
+ Record.push_back(Init.canThrow());
+ }
+
if (D->getStorageDuration() == SD_Static) {
bool ModulesCodegen = false;
if (Writer.WritingModule &&
@@ -999,6 +1008,8 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
!D->isConstexpr() &&
!D->isInitCapture() &&
!D->isPreviousDeclInSameBlockScope() &&
+ !(D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) &&
+ !D->isEscapingByref() &&
D->getStorageDuration() != SD_Static &&
!D->getMemberSpecializationInfo())
AbbrevToUse = Writer.getDeclVarAbbrev();
@@ -1098,6 +1109,7 @@ void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) {
Record.push_back(D->isVariadic());
Record.push_back(D->blockMissingReturnType());
Record.push_back(D->isConversionFromLambda());
+ Record.push_back(D->doesNotEscape());
Record.push_back(D->capturesCXXThis());
Record.push_back(D->getNumCaptures());
for (const auto &capture : D->captures()) {
@@ -1142,7 +1154,7 @@ void ASTDeclWriter::VisitExportDecl(ExportDecl *D) {
void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) {
VisitNamedDecl(D);
- Record.AddSourceLocation(D->getLocStart());
+ Record.AddSourceLocation(D->getBeginLoc());
Code = serialization::DECL_LABEL;
}
@@ -1151,7 +1163,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
VisitRedeclarable(D);
VisitNamedDecl(D);
Record.push_back(D->isInline());
- Record.AddSourceLocation(D->getLocStart());
+ Record.AddSourceLocation(D->getBeginLoc());
Record.AddSourceLocation(D->getRBraceLoc());
if (D->isOriginalNamespace())
@@ -1275,7 +1287,7 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
// Store (what we currently believe to be) the key function to avoid
// deserializing every method so we can compute it.
- if (D->IsCompleteDefinition)
+ if (D->isCompleteDefinition())
Record.AddDeclRef(Context.getCurrentKeyFunction(D));
Code = serialization::DECL_CXX_RECORD;
@@ -1343,7 +1355,7 @@ void ASTDeclWriter::VisitImportDecl(ImportDecl *D) {
ArrayRef<SourceLocation> IdentifierLocs = D->getIdentifierLocs();
Record.push_back(!IdentifierLocs.empty());
if (IdentifierLocs.empty()) {
- Record.AddSourceLocation(D->getLocEnd());
+ Record.AddSourceLocation(D->getEndLoc());
Record.push_back(1);
} else {
for (unsigned I = 0, N = IdentifierLocs.size(); I != N; ++I)
@@ -1731,10 +1743,23 @@ void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
Code = serialization::DECL_OMP_THREADPRIVATE;
}
+void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
+ Record.push_back(D->clauselist_size());
+ VisitDecl(D);
+ OMPClauseWriter ClauseWriter(Record);
+ for (OMPClause *C : D->clauselists())
+ ClauseWriter.writeClause(C);
+ Code = serialization::DECL_OMP_REQUIRES;
+}
+
void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
VisitValueDecl(D);
- Record.AddSourceLocation(D->getLocStart());
+ Record.AddSourceLocation(D->getBeginLoc());
+ Record.AddStmt(D->getCombinerIn());
+ Record.AddStmt(D->getCombinerOut());
Record.AddStmt(D->getCombiner());
+ Record.AddStmt(D->getInitOrig());
+ Record.AddStmt(D->getInitPriv());
Record.AddStmt(D->getInitializer());
Record.push_back(D->getInitializerKind());
Record.AddDeclRef(D->getPrevDeclInScope());
@@ -1961,6 +1986,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // SClass
Abv->Add(BitCodeAbbrevOp(0)); // TSCSpec
Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
+ Abv->Add(BitCodeAbbrevOp(0)); // ARCPseudoStrong
Abv->Add(BitCodeAbbrevOp(0)); // Linkage
Abv->Add(BitCodeAbbrevOp(0)); // HasInit
Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo
@@ -2037,18 +2063,19 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // SClass
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // InitStyle
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsThisDeclarationADemotedDefinition
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong
Abv->Add(BitCodeAbbrevOp(0)); // isInline
Abv->Add(BitCodeAbbrevOp(0)); // isInlineSpecified
Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr
Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture
Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope
Abv->Add(BitCodeAbbrevOp(0)); // ImplicitParamKind
+ Abv->Add(BitCodeAbbrevOp(0)); // EscapingByref
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // IsInitICE (local)
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum)
@@ -2229,8 +2256,7 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context,
// File scoped assembly or obj-c or OMP declare target implementation must be
// seen.
- if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D) ||
- D->hasAttr<OMPDeclareTargetDeclAttr>())
+ if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D))
return true;
if (WritingModule && (isa<VarDecl>(D) || isa<ImportDecl>(D))) {
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 48c3f79a4380..6f8b86edcdfc 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -73,7 +73,7 @@ void ASTStmtWriter::VisitStmt(Stmt *S) {
void ASTStmtWriter::VisitNullStmt(NullStmt *S) {
VisitStmt(S);
Record.AddSourceLocation(S->getSemiLoc());
- Record.push_back(S->HasLeadingEmptyMacro);
+ Record.push_back(S->NullStmtBits.HasLeadingEmptyMacro);
Code = serialization::STMT_NULL;
}
@@ -96,10 +96,13 @@ void ASTStmtWriter::VisitSwitchCase(SwitchCase *S) {
void ASTStmtWriter::VisitCaseStmt(CaseStmt *S) {
VisitSwitchCase(S);
+ Record.push_back(S->caseStmtIsGNURange());
Record.AddStmt(S->getLHS());
- Record.AddStmt(S->getRHS());
Record.AddStmt(S->getSubStmt());
- Record.AddSourceLocation(S->getEllipsisLoc());
+ if (S->caseStmtIsGNURange()) {
+ Record.AddStmt(S->getRHS());
+ Record.AddSourceLocation(S->getEllipsisLoc());
+ }
Code = serialization::STMT_CASE;
}
@@ -128,25 +131,50 @@ void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) {
void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
+
+ bool HasElse = S->getElse() != nullptr;
+ bool HasVar = S->getConditionVariableDeclStmt() != nullptr;
+ bool HasInit = S->getInit() != nullptr;
+
Record.push_back(S->isConstexpr());
- Record.AddStmt(S->getInit());
- Record.AddDeclRef(S->getConditionVariable());
+ Record.push_back(HasElse);
+ Record.push_back(HasVar);
+ Record.push_back(HasInit);
+
Record.AddStmt(S->getCond());
Record.AddStmt(S->getThen());
- Record.AddStmt(S->getElse());
+ if (HasElse)
+ Record.AddStmt(S->getElse());
+ if (HasVar)
+ Record.AddDeclRef(S->getConditionVariable());
+ if (HasInit)
+ Record.AddStmt(S->getInit());
+
Record.AddSourceLocation(S->getIfLoc());
- Record.AddSourceLocation(S->getElseLoc());
+ if (HasElse)
+ Record.AddSourceLocation(S->getElseLoc());
+
Code = serialization::STMT_IF;
}
void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
- Record.AddStmt(S->getInit());
- Record.AddDeclRef(S->getConditionVariable());
+
+ bool HasInit = S->getInit() != nullptr;
+ bool HasVar = S->getConditionVariableDeclStmt() != nullptr;
+ Record.push_back(HasInit);
+ Record.push_back(HasVar);
+ Record.push_back(S->isAllEnumCasesCovered());
+
Record.AddStmt(S->getCond());
Record.AddStmt(S->getBody());
+ if (HasInit)
+ Record.AddStmt(S->getInit());
+ if (HasVar)
+ Record.AddDeclRef(S->getConditionVariable());
+
Record.AddSourceLocation(S->getSwitchLoc());
- Record.push_back(S->isAllEnumCasesCovered());
+
for (SwitchCase *SC = S->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase())
Record.push_back(Writer.RecordSwitchCaseID(SC));
@@ -155,9 +183,15 @@ void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
void ASTStmtWriter::VisitWhileStmt(WhileStmt *S) {
VisitStmt(S);
- Record.AddDeclRef(S->getConditionVariable());
+
+ bool HasVar = S->getConditionVariableDeclStmt() != nullptr;
+ Record.push_back(HasVar);
+
Record.AddStmt(S->getCond());
Record.AddStmt(S->getBody());
+ if (HasVar)
+ Record.AddDeclRef(S->getConditionVariable());
+
Record.AddSourceLocation(S->getWhileLoc());
Code = serialization::STMT_WHILE;
}
@@ -215,15 +249,21 @@ void ASTStmtWriter::VisitBreakStmt(BreakStmt *S) {
void ASTStmtWriter::VisitReturnStmt(ReturnStmt *S) {
VisitStmt(S);
+
+ bool HasNRVOCandidate = S->getNRVOCandidate() != nullptr;
+ Record.push_back(HasNRVOCandidate);
+
Record.AddStmt(S->getRetValue());
+ if (HasNRVOCandidate)
+ Record.AddDeclRef(S->getNRVOCandidate());
+
Record.AddSourceLocation(S->getReturnLoc());
- Record.AddDeclRef(S->getNRVOCandidate());
Code = serialization::STMT_RETURN;
}
void ASTStmtWriter::VisitDeclStmt(DeclStmt *S) {
VisitStmt(S);
- Record.AddSourceLocation(S->getStartLoc());
+ Record.AddSourceLocation(S->getBeginLoc());
Record.AddSourceLocation(S->getEndLoc());
DeclGroupRef DG = S->getDeclGroup();
for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D)
@@ -386,11 +426,21 @@ void ASTStmtWriter::VisitExpr(Expr *E) {
Record.push_back(E->getObjectKind());
}
+void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) {
+ VisitExpr(E);
+ Record.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_CONSTANT;
+}
+
void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
+
+ bool HasFunctionName = E->getFunctionName() != nullptr;
+ Record.push_back(HasFunctionName);
+ Record.push_back(E->getIdentKind()); // FIXME: stable encoding
Record.AddSourceLocation(E->getLocation());
- Record.push_back(E->getIdentType()); // FIXME: stable encoding
- Record.AddStmt(E->getFunctionName());
+ if (HasFunctionName)
+ Record.AddStmt(E->getFunctionName());
Code = serialization::EXPR_PREDEFINED;
}
@@ -468,17 +518,23 @@ void ASTStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) {
VisitExpr(E);
- Record.push_back(E->getByteLength());
+
+ // Store the various bits of data of StringLiteral.
Record.push_back(E->getNumConcatenated());
+ Record.push_back(E->getLength());
+ Record.push_back(E->getCharByteWidth());
Record.push_back(E->getKind());
Record.push_back(E->isPascal());
- // FIXME: String data should be stored as a blob at the end of the
- // StringLiteral. However, we can't do so now because we have no
- // provision for coping with abbreviations when we're jumping around
- // the AST file during deserialization.
- Record.append(E->getBytes().begin(), E->getBytes().end());
+
+ // Store the trailing array of SourceLocation.
for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
Record.AddSourceLocation(E->getStrTokenLoc(I));
+
+ // Store the trailing array of char holding the string data.
+ StringRef StrData = E->getBytes();
+ for (unsigned I = 0, N = E->getByteLength(); I != N; ++I)
+ Record.push_back(StrData[I]);
+
Code = serialization::EXPR_STRING_LITERAL;
}
@@ -503,11 +559,11 @@ void ASTStmtWriter::VisitParenExpr(ParenExpr *E) {
void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) {
VisitExpr(E);
- Record.push_back(E->NumExprs);
- for (unsigned i=0; i != E->NumExprs; ++i)
- Record.AddStmt(E->Exprs[i]);
- Record.AddSourceLocation(E->LParenLoc);
- Record.AddSourceLocation(E->RParenLoc);
+ Record.push_back(E->getNumExprs());
+ for (auto *SubStmt : E->exprs())
+ Record.AddStmt(SubStmt);
+ Record.AddSourceLocation(E->getLParenLoc());
+ Record.AddSourceLocation(E->getRParenLoc());
Code = serialization::EXPR_PAREN_LIST;
}
@@ -595,6 +651,7 @@ void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
Arg != ArgEnd; ++Arg)
Record.AddStmt(*Arg);
+ Record.push_back(static_cast<unsigned>(E->getADLCallKind()));
Code = serialization::EXPR_CALL;
}
@@ -605,8 +662,8 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
if (E->hasQualifier())
Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
- Record.push_back(E->HasTemplateKWAndArgsInfo);
- if (E->HasTemplateKWAndArgsInfo) {
+ Record.push_back(E->hasTemplateKWAndArgsInfo());
+ if (E->hasTemplateKWAndArgsInfo()) {
Record.AddSourceLocation(E->getTemplateKeywordLoc());
unsigned NumTemplateArgs = E->getNumTemplateArgs();
Record.push_back(NumTemplateArgs);
@@ -1222,6 +1279,7 @@ void ASTStmtWriter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
Record.AddSourceLocation(S->getCoawaitLoc());
Record.AddSourceLocation(S->getColonLoc());
Record.AddSourceLocation(S->getRParenLoc());
+ Record.AddStmt(S->getInit());
Record.AddStmt(S->getRangeStmt());
Record.AddStmt(S->getBeginStmt());
Record.AddStmt(S->getEndStmt());
@@ -1245,8 +1303,8 @@ void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
Record.push_back(E->getOperator());
- Record.AddSourceRange(E->Range);
Record.push_back(E->getFPFeatures().getInt());
+ Record.AddSourceRange(E->Range);
Code = serialization::EXPR_CXX_OPERATOR_CALL;
}
@@ -1257,18 +1315,21 @@ void ASTStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
VisitExpr(E);
+
Record.push_back(E->getNumArgs());
- for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
- Record.AddStmt(E->getArg(I));
- Record.AddDeclRef(E->getConstructor());
- Record.AddSourceLocation(E->getLocation());
Record.push_back(E->isElidable());
Record.push_back(E->hadMultipleCandidates());
Record.push_back(E->isListInitialization());
Record.push_back(E->isStdInitListInitialization());
Record.push_back(E->requiresZeroInitialization());
Record.push_back(E->getConstructionKind()); // FIXME: stable encoding
+ Record.AddSourceLocation(E->getLocation());
+ Record.AddDeclRef(E->getConstructor());
Record.AddSourceRange(E->getParenOrBraceRange());
+
+ for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+ Record.AddStmt(E->getArg(I));
+
Code = serialization::EXPR_CXX_CONSTRUCT;
}
@@ -1422,20 +1483,27 @@ void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) {
VisitExpr(E);
- Record.push_back(E->isGlobalNew());
+
Record.push_back(E->isArray());
+ Record.push_back(E->hasInitializer());
+ Record.push_back(E->getNumPlacementArgs());
+ Record.push_back(E->isParenTypeId());
+
+ Record.push_back(E->isGlobalNew());
Record.push_back(E->passAlignment());
Record.push_back(E->doesUsualArrayDeleteWantSize());
- Record.push_back(E->getNumPlacementArgs());
- Record.push_back(E->StoredInitializationStyle);
+ Record.push_back(E->CXXNewExprBits.StoredInitializationStyle);
+
Record.AddDeclRef(E->getOperatorNew());
Record.AddDeclRef(E->getOperatorDelete());
Record.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo());
- Record.AddSourceRange(E->getTypeIdParens());
+ if (E->isParenTypeId())
+ Record.AddSourceRange(E->getTypeIdParens());
Record.AddSourceRange(E->getSourceRange());
Record.AddSourceRange(E->getDirectInitRange());
- for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end();
- I != e; ++I)
+
+ for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), N = E->raw_arg_end();
+ I != N; ++I)
Record.AddStmt(*I);
Code = serialization::EXPR_CXX_NEW;
@@ -1449,7 +1517,7 @@ void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
Record.push_back(E->doesUsualArrayDeleteWantSize());
Record.AddDeclRef(E->getOperatorDelete());
Record.AddStmt(E->getArgument());
- Record.AddSourceLocation(E->getSourceRange().getBegin());
+ Record.AddSourceLocation(E->getBeginLoc());
Code = serialization::EXPR_CXX_DELETE;
}
@@ -1486,31 +1554,36 @@ void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) {
Code = serialization::EXPR_EXPR_WITH_CLEANUPS;
}
-void
-ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
+void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(
+ CXXDependentScopeMemberExpr *E) {
VisitExpr(E);
- // Don't emit anything here, HasTemplateKWAndArgsInfo must be
- // emitted first.
+ // Don't emit anything here (or if you do you will have to update
+ // the corresponding deserialization function).
- Record.push_back(E->HasTemplateKWAndArgsInfo);
- if (E->HasTemplateKWAndArgsInfo) {
+ Record.push_back(E->hasTemplateKWAndArgsInfo());
+ Record.push_back(E->getNumTemplateArgs());
+ Record.push_back(E->hasFirstQualifierFoundInScope());
+
+ if (E->hasTemplateKWAndArgsInfo()) {
const ASTTemplateKWAndArgsInfo &ArgInfo =
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
- Record.push_back(ArgInfo.NumTemplateArgs);
AddTemplateKWAndArgsInfo(ArgInfo,
E->getTrailingObjects<TemplateArgumentLoc>());
}
+ Record.push_back(E->isArrow());
+ Record.AddSourceLocation(E->getOperatorLoc());
+ Record.AddTypeRef(E->getBaseType());
+ Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
if (!E->isImplicitAccess())
Record.AddStmt(E->getBase());
else
Record.AddStmt(nullptr);
- Record.AddTypeRef(E->getBaseType());
- Record.push_back(E->isArrow());
- Record.AddSourceLocation(E->getOperatorLoc());
- Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
- Record.AddDeclRef(E->getFirstQualifierFoundInScope());
+
+ if (E->hasFirstQualifierFoundInScope())
+ Record.AddDeclRef(E->getFirstQualifierFoundInScope());
+
Record.AddDeclarationNameInfo(E->MemberNameInfo);
Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
}
@@ -1522,8 +1595,8 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
// Don't emit anything here, HasTemplateKWAndArgsInfo must be
// emitted first.
- Record.push_back(E->HasTemplateKWAndArgsInfo);
- if (E->HasTemplateKWAndArgsInfo) {
+ Record.push_back(E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo);
+ if (E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo) {
const ASTTemplateKWAndArgsInfo &ArgInfo =
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
Record.push_back(ArgInfo.NumTemplateArgs);
@@ -1552,25 +1625,23 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
- // Don't emit anything here, HasTemplateKWAndArgsInfo must be
- // emitted first.
-
- Record.push_back(E->HasTemplateKWAndArgsInfo);
- if (E->HasTemplateKWAndArgsInfo) {
+ Record.push_back(E->getNumDecls());
+ Record.push_back(E->hasTemplateKWAndArgsInfo());
+ if (E->hasTemplateKWAndArgsInfo()) {
const ASTTemplateKWAndArgsInfo &ArgInfo =
*E->getTrailingASTTemplateKWAndArgsInfo();
Record.push_back(ArgInfo.NumTemplateArgs);
AddTemplateKWAndArgsInfo(ArgInfo, E->getTrailingTemplateArgumentLoc());
}
- Record.push_back(E->getNumDecls());
- for (OverloadExpr::decls_iterator
- OvI = E->decls_begin(), OvE = E->decls_end(); OvI != OvE; ++OvI) {
+ for (OverloadExpr::decls_iterator OvI = E->decls_begin(),
+ OvE = E->decls_end();
+ OvI != OvE; ++OvI) {
Record.AddDeclRef(OvI.getDecl());
Record.push_back(OvI.getAccess());
}
- Record.AddDeclarationNameInfo(E->NameInfo);
+ Record.AddDeclarationNameInfo(E->getNameInfo());
Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
}
@@ -1803,483 +1874,11 @@ void ASTStmtWriter::VisitSEHLeaveStmt(SEHLeaveStmt *S) {
}
//===----------------------------------------------------------------------===//
-// OpenMP Clauses.
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> {
- ASTRecordWriter &Record;
-public:
- OMPClauseWriter(ASTRecordWriter &Record) : Record(Record) {}
-#define OPENMP_CLAUSE(Name, Class) \
- void Visit##Class(Class *S);
-#include "clang/Basic/OpenMPKinds.def"
- void writeClause(OMPClause *C);
- void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
- void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);
-};
-}
-
-void OMPClauseWriter::writeClause(OMPClause *C) {
- Record.push_back(C->getClauseKind());
- Visit(C);
- Record.AddSourceLocation(C->getLocStart());
- Record.AddSourceLocation(C->getLocEnd());
-}
-
-void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
- Record.push_back(C->getCaptureRegion());
- Record.AddStmt(C->getPreInitStmt());
-}
-
-void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {
- VisitOMPClauseWithPreInit(C);
- Record.AddStmt(C->getPostUpdateExpr());
-}
-
-void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
- VisitOMPClauseWithPreInit(C);
- Record.push_back(C->getNameModifier());
- Record.AddSourceLocation(C->getNameModifierLoc());
- Record.AddSourceLocation(C->getColonLoc());
- Record.AddStmt(C->getCondition());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) {
- Record.AddStmt(C->getCondition());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
- VisitOMPClauseWithPreInit(C);
- Record.AddStmt(C->getNumThreads());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {
- Record.AddStmt(C->getSafelen());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
- Record.AddStmt(C->getSimdlen());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {
- Record.AddStmt(C->getNumForLoops());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
- Record.push_back(C->getDefaultKind());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getDefaultKindKwLoc());
-}
-
-void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
- Record.push_back(C->getProcBindKind());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getProcBindKindKwLoc());
-}
-
-void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
- VisitOMPClauseWithPreInit(C);
- Record.push_back(C->getScheduleKind());
- Record.push_back(C->getFirstScheduleModifier());
- Record.push_back(C->getSecondScheduleModifier());
- Record.AddStmt(C->getChunkSize());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getFirstScheduleModifierLoc());
- Record.AddSourceLocation(C->getSecondScheduleModifierLoc());
- Record.AddSourceLocation(C->getScheduleKindLoc());
- Record.AddSourceLocation(C->getCommaLoc());
-}
-
-void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {
- Record.AddStmt(C->getNumForLoops());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {}
-
-void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {}
-
-void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {}
-
-void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {}
-
-void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {}
-
-void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {}
-
-void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}
-
-void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
-
-void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}
-
-void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}
-
-void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}
-
-void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
- Record.push_back(C->varlist_size());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists()) {
- Record.AddStmt(VE);
- }
- for (auto *VE : C->private_copies()) {
- Record.AddStmt(VE);
- }
-}
-
-void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
- Record.push_back(C->varlist_size());
- VisitOMPClauseWithPreInit(C);
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists()) {
- Record.AddStmt(VE);
- }
- for (auto *VE : C->private_copies()) {
- Record.AddStmt(VE);
- }
- for (auto *VE : C->inits()) {
- Record.AddStmt(VE);
- }
-}
-
-void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
- Record.push_back(C->varlist_size());
- VisitOMPClauseWithPostUpdate(C);
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- for (auto *E : C->private_copies())
- Record.AddStmt(E);
- for (auto *E : C->source_exprs())
- Record.AddStmt(E);
- for (auto *E : C->destination_exprs())
- Record.AddStmt(E);
- for (auto *E : C->assignment_ops())
- Record.AddStmt(E);
-}
-
-void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
- Record.push_back(C->varlist_size());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
-}
-
-void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
- Record.push_back(C->varlist_size());
- VisitOMPClauseWithPostUpdate(C);
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getColonLoc());
- Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
- Record.AddDeclarationNameInfo(C->getNameInfo());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- for (auto *VE : C->privates())
- Record.AddStmt(VE);
- for (auto *E : C->lhs_exprs())
- Record.AddStmt(E);
- for (auto *E : C->rhs_exprs())
- Record.AddStmt(E);
- for (auto *E : C->reduction_ops())
- Record.AddStmt(E);
-}
-
-void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
- Record.push_back(C->varlist_size());
- VisitOMPClauseWithPostUpdate(C);
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getColonLoc());
- Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
- Record.AddDeclarationNameInfo(C->getNameInfo());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- for (auto *VE : C->privates())
- Record.AddStmt(VE);
- for (auto *E : C->lhs_exprs())
- Record.AddStmt(E);
- for (auto *E : C->rhs_exprs())
- Record.AddStmt(E);
- for (auto *E : C->reduction_ops())
- Record.AddStmt(E);
-}
-
-void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {
- Record.push_back(C->varlist_size());
- VisitOMPClauseWithPostUpdate(C);
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getColonLoc());
- Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
- Record.AddDeclarationNameInfo(C->getNameInfo());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- for (auto *VE : C->privates())
- Record.AddStmt(VE);
- for (auto *E : C->lhs_exprs())
- Record.AddStmt(E);
- for (auto *E : C->rhs_exprs())
- Record.AddStmt(E);
- for (auto *E : C->reduction_ops())
- Record.AddStmt(E);
- for (auto *E : C->taskgroup_descriptors())
- Record.AddStmt(E);
-}
-
-void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
- Record.push_back(C->varlist_size());
- VisitOMPClauseWithPostUpdate(C);
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getColonLoc());
- Record.push_back(C->getModifier());
- Record.AddSourceLocation(C->getModifierLoc());
- for (auto *VE : C->varlists()) {
- Record.AddStmt(VE);
- }
- for (auto *VE : C->privates()) {
- Record.AddStmt(VE);
- }
- for (auto *VE : C->inits()) {
- Record.AddStmt(VE);
- }
- for (auto *VE : C->updates()) {
- Record.AddStmt(VE);
- }
- for (auto *VE : C->finals()) {
- Record.AddStmt(VE);
- }
- Record.AddStmt(C->getStep());
- Record.AddStmt(C->getCalcStep());
-}
-
-void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) {
- Record.push_back(C->varlist_size());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getColonLoc());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- Record.AddStmt(C->getAlignment());
-}
-
-void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
- Record.push_back(C->varlist_size());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- for (auto *E : C->source_exprs())
- Record.AddStmt(E);
- for (auto *E : C->destination_exprs())
- Record.AddStmt(E);
- for (auto *E : C->assignment_ops())
- Record.AddStmt(E);
-}
-
-void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
- Record.push_back(C->varlist_size());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- for (auto *E : C->source_exprs())
- Record.AddStmt(E);
- for (auto *E : C->destination_exprs())
- Record.AddStmt(E);
- for (auto *E : C->assignment_ops())
- Record.AddStmt(E);
-}
-
-void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
- Record.push_back(C->varlist_size());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
-}
-
-void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
- Record.push_back(C->varlist_size());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.push_back(C->getDependencyKind());
- Record.AddSourceLocation(C->getDependencyLoc());
- Record.AddSourceLocation(C->getColonLoc());
- for (auto *VE : C->varlists())
- Record.AddStmt(VE);
- Record.AddStmt(C->getCounterValue());
-}
-
-void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
- VisitOMPClauseWithPreInit(C);
- Record.AddStmt(C->getDevice());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) {
- Record.push_back(C->varlist_size());
- Record.push_back(C->getUniqueDeclarationsNum());
- Record.push_back(C->getTotalComponentListNum());
- Record.push_back(C->getTotalComponentsNum());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.push_back(C->getMapTypeModifier());
- Record.push_back(C->getMapType());
- Record.AddSourceLocation(C->getMapLoc());
- Record.AddSourceLocation(C->getColonLoc());
- for (auto *E : C->varlists())
- Record.AddStmt(E);
- for (auto *D : C->all_decls())
- Record.AddDeclRef(D);
- for (auto N : C->all_num_lists())
- Record.push_back(N);
- for (auto N : C->all_lists_sizes())
- Record.push_back(N);
- for (auto &M : C->all_components()) {
- Record.AddStmt(M.getAssociatedExpression());
- Record.AddDeclRef(M.getAssociatedDeclaration());
- }
-}
-
-void OMPClauseWriter::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
- VisitOMPClauseWithPreInit(C);
- Record.AddStmt(C->getNumTeams());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
- VisitOMPClauseWithPreInit(C);
- Record.AddStmt(C->getThreadLimit());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) {
- Record.AddStmt(C->getPriority());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
- Record.AddStmt(C->getGrainsize());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
- Record.AddStmt(C->getNumTasks());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {
- Record.AddStmt(C->getHint());
- Record.AddSourceLocation(C->getLParenLoc());
-}
-
-void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
- VisitOMPClauseWithPreInit(C);
- Record.push_back(C->getDistScheduleKind());
- Record.AddStmt(C->getChunkSize());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getDistScheduleKindLoc());
- Record.AddSourceLocation(C->getCommaLoc());
-}
-
-void OMPClauseWriter::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {
- Record.push_back(C->getDefaultmapKind());
- Record.push_back(C->getDefaultmapModifier());
- Record.AddSourceLocation(C->getLParenLoc());
- Record.AddSourceLocation(C->getDefaultmapModifierLoc());
- Record.AddSourceLocation(C->getDefaultmapKindLoc());
-}
-
-void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) {
- Record.push_back(C->varlist_size());
- Record.push_back(C->getUniqueDeclarationsNum());
- Record.push_back(C->getTotalComponentListNum());
- Record.push_back(C->getTotalComponentsNum());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *E : C->varlists())
- Record.AddStmt(E);
- for (auto *D : C->all_decls())
- Record.AddDeclRef(D);
- for (auto N : C->all_num_lists())
- Record.push_back(N);
- for (auto N : C->all_lists_sizes())
- Record.push_back(N);
- for (auto &M : C->all_components()) {
- Record.AddStmt(M.getAssociatedExpression());
- Record.AddDeclRef(M.getAssociatedDeclaration());
- }
-}
-
-void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {
- Record.push_back(C->varlist_size());
- Record.push_back(C->getUniqueDeclarationsNum());
- Record.push_back(C->getTotalComponentListNum());
- Record.push_back(C->getTotalComponentsNum());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *E : C->varlists())
- Record.AddStmt(E);
- for (auto *D : C->all_decls())
- Record.AddDeclRef(D);
- for (auto N : C->all_num_lists())
- Record.push_back(N);
- for (auto N : C->all_lists_sizes())
- Record.push_back(N);
- for (auto &M : C->all_components()) {
- Record.AddStmt(M.getAssociatedExpression());
- Record.AddDeclRef(M.getAssociatedDeclaration());
- }
-}
-
-void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
- Record.push_back(C->varlist_size());
- Record.push_back(C->getUniqueDeclarationsNum());
- Record.push_back(C->getTotalComponentListNum());
- Record.push_back(C->getTotalComponentsNum());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *E : C->varlists())
- Record.AddStmt(E);
- for (auto *VE : C->private_copies())
- Record.AddStmt(VE);
- for (auto *VE : C->inits())
- Record.AddStmt(VE);
- for (auto *D : C->all_decls())
- Record.AddDeclRef(D);
- for (auto N : C->all_num_lists())
- Record.push_back(N);
- for (auto N : C->all_lists_sizes())
- Record.push_back(N);
- for (auto &M : C->all_components()) {
- Record.AddStmt(M.getAssociatedExpression());
- Record.AddDeclRef(M.getAssociatedDeclaration());
- }
-}
-
-void OMPClauseWriter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
- Record.push_back(C->varlist_size());
- Record.push_back(C->getUniqueDeclarationsNum());
- Record.push_back(C->getTotalComponentListNum());
- Record.push_back(C->getTotalComponentsNum());
- Record.AddSourceLocation(C->getLParenLoc());
- for (auto *E : C->varlists())
- Record.AddStmt(E);
- for (auto *D : C->all_decls())
- Record.AddDeclRef(D);
- for (auto N : C->all_num_lists())
- Record.push_back(N);
- for (auto N : C->all_lists_sizes())
- Record.push_back(N);
- for (auto &M : C->all_components()) {
- Record.AddStmt(M.getAssociatedExpression());
- Record.AddDeclRef(M.getAssociatedDeclaration());
- }
-}
-
-//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
- Record.AddSourceLocation(E->getLocStart());
- Record.AddSourceLocation(E->getLocEnd());
+ Record.AddSourceLocation(E->getBeginLoc());
+ Record.AddSourceLocation(E->getEndLoc());
OMPClauseWriter ClauseWriter(Record);
for (unsigned i = 0; i < E->getNumClauses(); ++i) {
ClauseWriter.writeClause(E->getClause(i));
@@ -2325,6 +1924,8 @@ void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
Record.AddStmt(D->getCombinedCond());
Record.AddStmt(D->getCombinedNextLowerBound());
Record.AddStmt(D->getCombinedNextUpperBound());
+ Record.AddStmt(D->getCombinedDistCond());
+ Record.AddStmt(D->getCombinedParForInDistCond());
}
for (auto I : D->counters()) {
Record.AddStmt(I);
diff --git a/lib/Serialization/CMakeLists.txt b/lib/Serialization/CMakeLists.txt
index 95b33c388c56..a312cb91eb0d 100644
--- a/lib/Serialization/CMakeLists.txt
+++ b/lib/Serialization/CMakeLists.txt
@@ -17,6 +17,7 @@ add_clang_library(clangSerialization
Module.cpp
ModuleFileExtension.cpp
ModuleManager.cpp
+ PCHContainerOperations.cpp
ADDITIONAL_HEADERS
ASTCommon.h
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp
index 3733638d2977..e7642a38924d 100644
--- a/lib/Serialization/GlobalModuleIndex.cpp
+++ b/lib/Serialization/GlobalModuleIndex.cpp
@@ -12,12 +12,12 @@
//===----------------------------------------------------------------------===//
#include "ASTReaderInternals.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Basic/FileManager.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/Module.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h"
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp
index 57ebaca10c99..54e0c08c5bc9 100644
--- a/lib/Serialization/ModuleManager.cpp
+++ b/lib/Serialization/ModuleManager.cpp
@@ -16,12 +16,11 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/MemoryBufferCache.h"
-#include "clang/Basic/VirtualFileSystem.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/Module.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -33,6 +32,7 @@
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <algorithm>
#include <cassert>
#include <memory>
@@ -150,7 +150,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
if (NewModule->Kind == MK_ImplicitModule) {
std::string TimestampFilename = NewModule->getTimestampFilename();
- vfs::Status Status;
+ llvm::vfs::Status Status;
// A cached stat value would be fine as well.
if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
NewModule->InputFilesValidationTimestamp =
@@ -161,21 +161,24 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
// The buffer was already provided for us.
NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(Buffer));
+ // Since the cached buffer is reused, it is safe to close the file
+ // descriptor that was opened while stat()ing the PCM in
+ // lookupModuleFile() above, it won't be needed any longer.
+ Entry->closeFile();
} else if (llvm::MemoryBuffer *Buffer = PCMCache->lookupBuffer(FileName)) {
NewModule->Buffer = Buffer;
+ // As above, the file descriptor is no longer needed.
+ Entry->closeFile();
} else {
// Open the AST file.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
if (FileName == "-") {
Buf = llvm::MemoryBuffer::getSTDIN();
} else {
- // Leave the FileEntry open so if it gets read again by another
- // ModuleManager it must be the same underlying file.
- // FIXME: Because FileManager::getFile() doesn't guarantee that it will
- // give us an open file, this may not be 100% reliable.
+ // Get a buffer of the file and close the file descriptor when done.
Buf = FileMgr.getBufferForFile(NewModule->File,
/*IsVolatile=*/false,
- /*ShouldClose=*/false);
+ /*ShouldClose=*/true);
}
if (!Buf) {
diff --git a/lib/Frontend/PCHContainerOperations.cpp b/lib/Serialization/PCHContainerOperations.cpp
index 340e8ce63ff4..fbc613efeb63 100644
--- a/lib/Frontend/PCHContainerOperations.cpp
+++ b/lib/Serialization/PCHContainerOperations.cpp
@@ -1,4 +1,4 @@
-//===--- Frontend/PCHContainerOperations.cpp - PCH Containers ---*- C++ -*-===//
+//=== Serialization/PCHContainerOperations.cpp - PCH Containers -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Serialization/PCHContainerOperations.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Lex/ModuleLoader.h"
#include "llvm/Bitcode/BitstreamReader.h"
diff --git a/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp b/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp
deleted file mode 100644
index 3dec8a58c929..000000000000
--- a/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//=- AllocationDiagnostics.cpp - Config options for allocation diags *- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Declares the configuration functions for leaks/allocation diagnostics.
-//
-//===--------------------------
-
-#include "AllocationDiagnostics.h"
-
-namespace clang {
-namespace ento {
-
-bool shouldIncludeAllocationSiteInLeakDiagnostics(AnalyzerOptions &AOpts) {
- return AOpts.getBooleanOption("leak-diagnostics-reference-allocation",
- false);
-}
-
-}}
diff --git a/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h b/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h
deleted file mode 100644
index 62b7fab0739a..000000000000
--- a/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//=--- AllocationDiagnostics.h - Config options for allocation diags *- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Declares the configuration functions for leaks/allocation diagnostics.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONDIAGNOSTICS_H
-#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONDIAGNOSTICS_H
-
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-
-namespace clang { namespace ento {
-
-/// Returns true if leak diagnostics should directly reference
-/// the allocatin site (where possible).
-///
-/// The default is false.
-///
-bool shouldIncludeAllocationSiteInLeakDiagnostics(AnalyzerOptions &AOpts);
-
-}}
-
-#endif
-
diff --git a/lib/StaticAnalyzer/Checkers/AllocationState.h b/lib/StaticAnalyzer/Checkers/AllocationState.h
index a6908bd7a651..c8193f77f928 100644
--- a/lib/StaticAnalyzer/Checkers/AllocationState.h
+++ b/lib/StaticAnalyzer/Checkers/AllocationState.h
@@ -26,6 +26,11 @@ ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym,
/// AF_InnerBuffer symbols.
std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym);
+/// 'Sym' represents a pointer to the inner buffer of a container object.
+/// This function looks up the memory region of that object in
+/// DanglingInternalBufferChecker's program state map.
+const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym);
+
} // end namespace allocation_state
} // end namespace ento
diff --git a/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp b/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
index e4cdc500de6a..b5d0f6620a1d 100644
--- a/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -14,8 +14,9 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -37,14 +38,15 @@ class AnalysisOrderChecker
check::PostStmt<OffsetOfExpr>,
check::PreCall,
check::PostCall,
+ check::EndFunction,
check::NewAllocator,
check::Bind,
check::RegionChanges,
check::LiveSymbols> {
bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const {
- return Opts.getBooleanOption("*", false, this) ||
- Opts.getBooleanOption(CallbackName, false, this);
+ return Opts.getCheckerBooleanOption("*", false, this) ||
+ Opts.getCheckerBooleanOption(CallbackName, false, this);
}
bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const {
@@ -54,7 +56,7 @@ class AnalysisOrderChecker
bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const {
AnalyzerOptions &Opts = State->getStateManager().getOwningEngine()
- ->getAnalysisManager().getAnalyzerOptions();
+ .getAnalysisManager().getAnalyzerOptions();
return isCallbackEnabled(Opts, CallbackName);
}
@@ -121,6 +123,23 @@ public:
}
}
+ void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "EndFunction")) {
+ llvm::errs() << "EndFunction\nReturnStmt: " << (S ? "yes" : "no") << "\n";
+ if (!S)
+ return;
+
+ llvm::errs() << "CFGElement: ";
+ CFGStmtMap *Map = C.getCurrentAnalysisDeclContext()->getCFGStmtMap();
+ CFGElement LastElement = Map->getBlock(S)->back();
+
+ if (LastElement.getAs<CFGStmt>())
+ llvm::errs() << "CFGStmt\n";
+ else if (LastElement.getAs<CFGAutomaticObjDtor>())
+ llvm::errs() << "CFGAutomaticObjDtor\n";
+ }
+ }
+
void checkNewAllocator(const CXXNewExpr *CNE, SVal Target,
CheckerContext &C) const {
if (isCallbackEnabled(C, "NewAllocator"))
diff --git a/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
index aadc6bac8d00..5e01012401b2 100644
--- a/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
// This file reports various statistics about analyzer visitation.
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
diff --git a/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
index c092610afe2b..20f3092fdba4 100644
--- a/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index 933380d494a4..26887be9f258 100644
--- a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/CharUnits.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 7d6358acbbac..577b5349f62e 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -13,14 +13,14 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
-#include "SelectorExtras.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Analysis/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -36,6 +36,7 @@
using namespace clang;
using namespace ento;
+using namespace llvm;
namespace {
class APIMisuse : public BugType {
@@ -156,6 +157,11 @@ void NilArgChecker::warnIfNilArg(CheckerContext &C,
if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
return;
+ // NOTE: We cannot throw non-fatal errors from warnIfNilExpr,
+ // because it's called multiple times from some callers, so it'd cause
+ // an unwanted state split if two or more non-fatal errors are thrown
+ // within the same checker callback. For now we don't want to, but
+ // it'll need to be fixed if we ever want to.
if (ExplodedNode *N = C.generateErrorNode()) {
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
@@ -208,7 +214,7 @@ void NilArgChecker::generateBugReport(ExplodedNode *N,
auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
R->addRange(Range);
- bugreporter::trackNullOrUndefValue(N, E, *R);
+ bugreporter::trackExpressionValue(N, E, *R);
C.emitReport(std::move(R));
}
@@ -526,93 +532,59 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE,
//===----------------------------------------------------------------------===//
namespace {
-class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
- mutable std::unique_ptr<APIMisuse> BT;
- mutable IdentifierInfo *Retain, *Release, *MakeCollectable, *Autorelease;
+class CFRetainReleaseChecker : public Checker<check::PreCall> {
+ mutable APIMisuse BT{this, "null passed to CF memory management function"};
+ CallDescription CFRetain{"CFRetain", 1},
+ CFRelease{"CFRelease", 1},
+ CFMakeCollectable{"CFMakeCollectable", 1},
+ CFAutorelease{"CFAutorelease", 1};
public:
- CFRetainReleaseChecker()
- : Retain(nullptr), Release(nullptr), MakeCollectable(nullptr),
- Autorelease(nullptr) {}
- void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
};
} // end anonymous namespace
-void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
+void CFRetainReleaseChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
- // If the CallExpr doesn't have exactly 1 argument just give up checking.
- if (CE->getNumArgs() != 1)
+ // TODO: Make this check part of CallDescription.
+ if (!Call.isGlobalCFunction())
return;
- ProgramStateRef state = C.getState();
- const FunctionDecl *FD = C.getCalleeDecl(CE);
- if (!FD)
- return;
-
- if (!BT) {
- ASTContext &Ctx = C.getASTContext();
- Retain = &Ctx.Idents.get("CFRetain");
- Release = &Ctx.Idents.get("CFRelease");
- MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
- Autorelease = &Ctx.Idents.get("CFAutorelease");
- BT.reset(new APIMisuse(
- this, "null passed to CF memory management function"));
- }
-
// Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
- const IdentifierInfo *FuncII = FD->getIdentifier();
- if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable ||
- FuncII == Autorelease))
+ if (!(Call.isCalled(CFRetain) || Call.isCalled(CFRelease) ||
+ Call.isCalled(CFMakeCollectable) || Call.isCalled(CFAutorelease)))
return;
- // FIXME: The rest of this just checks that the argument is non-null.
- // It should probably be refactored and combined with NonNullParamChecker.
-
// Get the argument's value.
- const Expr *Arg = CE->getArg(0);
- SVal ArgVal = C.getSVal(Arg);
+ SVal ArgVal = Call.getArgSVal(0);
Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
if (!DefArgVal)
return;
- // Get a NULL value.
- SValBuilder &svalBuilder = C.getSValBuilder();
- DefinedSVal zero =
- svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
-
- // Make an expression asserting that they're equal.
- DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
-
- // Are they equal?
- ProgramStateRef stateTrue, stateFalse;
- std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
+ // Is it null?
+ ProgramStateRef state = C.getState();
+ ProgramStateRef stateNonNull, stateNull;
+ std::tie(stateNonNull, stateNull) = state->assume(*DefArgVal);
- if (stateTrue && !stateFalse) {
- ExplodedNode *N = C.generateErrorNode(stateTrue);
+ if (!stateNonNull) {
+ ExplodedNode *N = C.generateErrorNode(stateNull);
if (!N)
return;
- const char *description;
- if (FuncII == Retain)
- description = "Null pointer argument in call to CFRetain";
- else if (FuncII == Release)
- description = "Null pointer argument in call to CFRelease";
- else if (FuncII == MakeCollectable)
- description = "Null pointer argument in call to CFMakeCollectable";
- else if (FuncII == Autorelease)
- description = "Null pointer argument in call to CFAutorelease";
- else
- llvm_unreachable("impossible case");
+ SmallString<64> Str;
+ raw_svector_ostream OS(Str);
+ OS << "Null pointer argument in call to "
+ << cast<FunctionDecl>(Call.getDecl())->getName();
- auto report = llvm::make_unique<BugReport>(*BT, description, N);
- report->addRange(Arg->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, Arg, *report);
+ auto report = llvm::make_unique<BugReport>(BT, OS.str(), N);
+ report->addRange(Call.getArgSourceRange(0));
+ bugreporter::trackExpressionValue(N, Call.getArgExpr(0), *report);
C.emitReport(std::move(report));
return;
}
// From here on, we know the argument is non-null.
- C.addTransition(stateFalse);
+ C.addTransition(stateNonNull);
}
//===----------------------------------------------------------------------===//
@@ -828,7 +800,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
//===----------------------------------------------------------------------===//
// The map from container symbol to the container count symbol.
-// We currently will remember the last countainer count symbol encountered.
+// We currently will remember the last container count symbol encountered.
REGISTER_MAP_WITH_PROGRAMSTATE(ContainerCountMap, SymbolRef, SymbolRef)
REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
diff --git a/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index c31f2794df6a..00d08b371f37 100644
--- a/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
diff --git a/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
index f26f73129e78..3008eddd397e 100644
--- a/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index 0e781d08e24c..f98027942e18 100644
--- a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Basic/Builtins.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -101,9 +101,10 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
// This must be resolvable at compile time, so we defer to the constant
// evaluator for a value.
SVal V = UnknownVal();
- llvm::APSInt Result;
- if (CE->EvaluateAsInt(Result, C.getASTContext(), Expr::SE_NoSideEffects)) {
+ Expr::EvalResult EVResult;
+ if (CE->EvaluateAsInt(EVResult, C.getASTContext(), Expr::SE_NoSideEffects)) {
// Make sure the result has the correct type.
+ llvm::APSInt Result = EVResult.Val.getInt();
SValBuilder &SVB = C.getSValBuilder();
BasicValueFactory &BVF = SVB.getBasicValueFactory();
BVF.getAPSIntType(CE->getType()).apply(Result);
diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 5bb4770b5675..10fb0bd3536c 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -3,7 +3,6 @@ set(LLVM_LINK_COMPONENTS
)
add_clang_library(clangStaticAnalyzerCheckers
- AllocationDiagnostics.cpp
AnalysisOrderChecker.cpp
AnalyzerStatsChecker.cpp
ArrayBoundChecker.cpp
@@ -23,7 +22,6 @@ add_clang_library(clangStaticAnalyzerCheckers
CheckSizeofPointer.cpp
CheckerDocumentation.cpp
ChrootChecker.cpp
- ClangCheckers.cpp
CloneChecker.cpp
ConversionChecker.cpp
CXXSelfAssignmentChecker.cpp
@@ -35,6 +33,7 @@ add_clang_library(clangStaticAnalyzerCheckers
DivZeroChecker.cpp
DynamicTypePropagation.cpp
DynamicTypeChecker.cpp
+ EnumCastOutOfRangeChecker.cpp
ExprInspectionChecker.cpp
FixedAddressChecker.cpp
GCDAntipatternChecker.cpp
@@ -52,7 +51,7 @@ add_clang_library(clangStaticAnalyzerCheckers
MallocOverflowSecurityChecker.cpp
MallocSizeofChecker.cpp
MmapWriteExecChecker.cpp
- MisusedMovedObjectChecker.cpp
+ MoveChecker.cpp
MPI-Checker/MPIBugReporter.cpp
MPI-Checker/MPIChecker.cpp
MPI-Checker/MPIFunctionClassifier.cpp
@@ -76,7 +75,8 @@ add_clang_library(clangStaticAnalyzerCheckers
PointerArithChecker.cpp
PointerSubChecker.cpp
PthreadLockChecker.cpp
- RetainCountChecker.cpp
+ RetainCountChecker/RetainCountChecker.cpp
+ RetainCountChecker/RetainCountDiagnostics.cpp
ReturnPointerRangeChecker.cpp
ReturnUndefChecker.cpp
RunLoopAutoreleaseLeakChecker.cpp
@@ -93,7 +93,8 @@ add_clang_library(clangStaticAnalyzerCheckers
UndefResultChecker.cpp
UndefinedArraySubscriptChecker.cpp
UndefinedAssignmentChecker.cpp
- UninitializedObjectChecker.cpp
+ UninitializedObject/UninitializedObjectChecker.cpp
+ UninitializedObject/UninitializedPointee.cpp
UnixAPIChecker.cpp
UnreachableCodeChecker.cpp
VforkChecker.cpp
@@ -101,9 +102,6 @@ add_clang_library(clangStaticAnalyzerCheckers
ValistChecker.cpp
VirtualCallChecker.cpp
- DEPENDS
- ClangSACheckers
-
LINK_LIBS
clangAST
clangASTMatchers
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 12a576e5d80d..8bffada69b9b 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "InterCheckerAPI.h"
#include "clang/Basic/CharInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -124,6 +124,7 @@ public:
void evalStdCopyBackward(CheckerContext &C, const CallExpr *CE) const;
void evalStdCopyCommon(CheckerContext &C, const CallExpr *CE) const;
void evalMemset(CheckerContext &C, const CallExpr *CE) const;
+ void evalBzero(CheckerContext &C, const CallExpr *CE) const;
// Utility methods
std::pair<ProgramStateRef , ProgramStateRef >
@@ -158,7 +159,7 @@ public:
static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const MemRegion *MR);
- static bool memsetAux(const Expr *DstBuffer, const Expr *CharE,
+ static bool memsetAux(const Expr *DstBuffer, SVal CharE,
const Expr *Size, CheckerContext &C,
ProgramStateRef &State);
@@ -187,7 +188,7 @@ public:
const Expr *Buf,
const char *message = nullptr,
bool WarnAboutSize = false) const {
- // This is a convenience override.
+ // This is a convenience overload.
return CheckBufferAccess(C, state, Size, Buf, nullptr, message, nullptr,
WarnAboutSize);
}
@@ -553,7 +554,8 @@ void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State,
BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Null.get());
auto Report = llvm::make_unique<BugReport>(*BT, WarningMsg, N);
Report->addRange(S->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, S, *Report);
+ if (const auto *Ex = dyn_cast<Expr>(S))
+ bugreporter::trackExpressionValue(N, Ex, *Report);
C.emitReport(std::move(Report));
}
}
@@ -1004,11 +1006,10 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
}
}
-bool CStringChecker::memsetAux(const Expr *DstBuffer, const Expr *CharE,
+bool CStringChecker::memsetAux(const Expr *DstBuffer, SVal CharVal,
const Expr *Size, CheckerContext &C,
ProgramStateRef &State) {
SVal MemVal = C.getSVal(DstBuffer);
- SVal CharVal = C.getSVal(CharE);
SVal SizeVal = C.getSVal(Size);
const MemRegion *MR = MemVal.getAsRegion();
if (!MR)
@@ -2183,13 +2184,59 @@ void CStringChecker::evalMemset(CheckerContext &C, const CallExpr *CE) const {
// According to the values of the arguments, bind the value of the second
// argument to the destination buffer and set string length, or just
// invalidate the destination buffer.
- if (!memsetAux(Mem, CharE, Size, C, State))
+ if (!memsetAux(Mem, C.getSVal(CharE), Size, C, State))
return;
State = State->BindExpr(CE, LCtx, MemVal);
C.addTransition(State);
}
+void CStringChecker::evalBzero(CheckerContext &C, const CallExpr *CE) const {
+ if (CE->getNumArgs() != 2)
+ return;
+
+ CurrentFunctionDescription = "memory clearance function";
+
+ const Expr *Mem = CE->getArg(0);
+ const Expr *Size = CE->getArg(1);
+ SVal Zero = C.getSValBuilder().makeZeroVal(C.getASTContext().IntTy);
+
+ ProgramStateRef State = C.getState();
+
+ // See if the size argument is zero.
+ SVal SizeVal = C.getSVal(Size);
+ QualType SizeTy = Size->getType();
+
+ ProgramStateRef StateZeroSize, StateNonZeroSize;
+ std::tie(StateZeroSize, StateNonZeroSize) =
+ assumeZero(C, State, SizeVal, SizeTy);
+
+ // If the size is zero, there won't be any actual memory access,
+ // In this case we just return.
+ if (StateZeroSize && !StateNonZeroSize) {
+ C.addTransition(StateZeroSize);
+ return;
+ }
+
+ // Get the value of the memory area.
+ SVal MemVal = C.getSVal(Mem);
+
+ // Ensure the memory area is not null.
+ // If it is NULL there will be a NULL pointer dereference.
+ State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
+ if (!State)
+ return;
+
+ State = CheckBufferAccess(C, State, Size, Mem);
+ if (!State)
+ return;
+
+ if (!memsetAux(Mem, Zero, Size, C, State))
+ return;
+
+ C.addTransition(State);
+}
+
static bool isCPPStdLibraryFunction(const FunctionDecl *FD, StringRef Name) {
IdentifierInfo *II = FD->getIdentifier();
if (!II)
@@ -2207,60 +2254,86 @@ static bool isCPPStdLibraryFunction(const FunctionDecl *FD, StringRef Name) {
// The driver method, and other Checker callbacks.
//===----------------------------------------------------------------------===//
-bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
+static CStringChecker::FnCheck identifyCall(const CallExpr *CE,
+ CheckerContext &C) {
const FunctionDecl *FDecl = C.getCalleeDecl(CE);
-
if (!FDecl)
- return false;
+ return nullptr;
+
+ // Pro-actively check that argument types are safe to do arithmetic upon.
+ // We do not want to crash if someone accidentally passes a structure
+ // into, say, a C++ overload of any of these functions.
+ if (isCPPStdLibraryFunction(FDecl, "copy")) {
+ if (CE->getNumArgs() < 3 || !CE->getArg(2)->getType()->isPointerType())
+ return nullptr;
+ return &CStringChecker::evalStdCopy;
+ } else if (isCPPStdLibraryFunction(FDecl, "copy_backward")) {
+ if (CE->getNumArgs() < 3 || !CE->getArg(2)->getType()->isPointerType())
+ return nullptr;
+ return &CStringChecker::evalStdCopyBackward;
+ } else {
+ // An umbrella check for all C library functions.
+ for (auto I: CE->arguments()) {
+ QualType T = I->getType();
+ if (!T->isIntegralOrEnumerationType() && !T->isPointerType())
+ return nullptr;
+ }
+ }
// FIXME: Poorly-factored string switches are slow.
- FnCheck evalFunction = nullptr;
if (C.isCLibraryFunction(FDecl, "memcpy"))
- evalFunction = &CStringChecker::evalMemcpy;
+ return &CStringChecker::evalMemcpy;
else if (C.isCLibraryFunction(FDecl, "mempcpy"))
- evalFunction = &CStringChecker::evalMempcpy;
+ return &CStringChecker::evalMempcpy;
else if (C.isCLibraryFunction(FDecl, "memcmp"))
- evalFunction = &CStringChecker::evalMemcmp;
+ return &CStringChecker::evalMemcmp;
else if (C.isCLibraryFunction(FDecl, "memmove"))
- evalFunction = &CStringChecker::evalMemmove;
- else if (C.isCLibraryFunction(FDecl, "memset"))
- evalFunction = &CStringChecker::evalMemset;
+ return &CStringChecker::evalMemmove;
+ else if (C.isCLibraryFunction(FDecl, "memset") ||
+ C.isCLibraryFunction(FDecl, "explicit_memset"))
+ return &CStringChecker::evalMemset;
else if (C.isCLibraryFunction(FDecl, "strcpy"))
- evalFunction = &CStringChecker::evalStrcpy;
+ return &CStringChecker::evalStrcpy;
else if (C.isCLibraryFunction(FDecl, "strncpy"))
- evalFunction = &CStringChecker::evalStrncpy;
+ return &CStringChecker::evalStrncpy;
else if (C.isCLibraryFunction(FDecl, "stpcpy"))
- evalFunction = &CStringChecker::evalStpcpy;
+ return &CStringChecker::evalStpcpy;
else if (C.isCLibraryFunction(FDecl, "strlcpy"))
- evalFunction = &CStringChecker::evalStrlcpy;
+ return &CStringChecker::evalStrlcpy;
else if (C.isCLibraryFunction(FDecl, "strcat"))
- evalFunction = &CStringChecker::evalStrcat;
+ return &CStringChecker::evalStrcat;
else if (C.isCLibraryFunction(FDecl, "strncat"))
- evalFunction = &CStringChecker::evalStrncat;
+ return &CStringChecker::evalStrncat;
else if (C.isCLibraryFunction(FDecl, "strlcat"))
- evalFunction = &CStringChecker::evalStrlcat;
+ return &CStringChecker::evalStrlcat;
else if (C.isCLibraryFunction(FDecl, "strlen"))
- evalFunction = &CStringChecker::evalstrLength;
+ return &CStringChecker::evalstrLength;
else if (C.isCLibraryFunction(FDecl, "strnlen"))
- evalFunction = &CStringChecker::evalstrnLength;
+ return &CStringChecker::evalstrnLength;
else if (C.isCLibraryFunction(FDecl, "strcmp"))
- evalFunction = &CStringChecker::evalStrcmp;
+ return &CStringChecker::evalStrcmp;
else if (C.isCLibraryFunction(FDecl, "strncmp"))
- evalFunction = &CStringChecker::evalStrncmp;
+ return &CStringChecker::evalStrncmp;
else if (C.isCLibraryFunction(FDecl, "strcasecmp"))
- evalFunction = &CStringChecker::evalStrcasecmp;
+ return &CStringChecker::evalStrcasecmp;
else if (C.isCLibraryFunction(FDecl, "strncasecmp"))
- evalFunction = &CStringChecker::evalStrncasecmp;
+ return &CStringChecker::evalStrncasecmp;
else if (C.isCLibraryFunction(FDecl, "strsep"))
- evalFunction = &CStringChecker::evalStrsep;
+ return &CStringChecker::evalStrsep;
else if (C.isCLibraryFunction(FDecl, "bcopy"))
- evalFunction = &CStringChecker::evalBcopy;
+ return &CStringChecker::evalBcopy;
else if (C.isCLibraryFunction(FDecl, "bcmp"))
- evalFunction = &CStringChecker::evalMemcmp;
- else if (isCPPStdLibraryFunction(FDecl, "copy"))
- evalFunction = &CStringChecker::evalStdCopy;
- else if (isCPPStdLibraryFunction(FDecl, "copy_backward"))
- evalFunction = &CStringChecker::evalStdCopyBackward;
+ return &CStringChecker::evalMemcmp;
+ else if (C.isCLibraryFunction(FDecl, "bzero") ||
+ C.isCLibraryFunction(FDecl, "explicit_bzero"))
+ return &CStringChecker::evalBzero;
+
+ return nullptr;
+}
+
+bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
+
+ FnCheck evalFunction = identifyCall(CE, C);
// If the callee isn't a string function, let another checker handle it.
if (!evalFunction)
@@ -2384,9 +2457,6 @@ void CStringChecker::checkLiveSymbols(ProgramStateRef state,
void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
CheckerContext &C) const {
- if (!SR.hasDeadSymbols())
- return;
-
ProgramStateRef state = C.getState();
CStringLengthTy Entries = state->get<CStringLength>();
if (Entries.isEmpty())
diff --git a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
index 8b4aa857e775..bbeb41c5f3cf 100644
--- a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp
@@ -12,7 +12,7 @@
// of bytes to copy.
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Expr.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/StmtVisitor.h"
@@ -90,7 +90,16 @@ class WalkAST: public StmtVisitor<WalkAST> {
/// strlcpy(dst, "abcd", 4);
/// strlcpy(dst + 3, "abcd", 2);
/// strlcpy(dst, "abcd", cpy);
- bool containsBadStrlcpyPattern(const CallExpr *CE);
+ /// Identify erroneous patterns in the last argument to strlcat - the number
+ /// of bytes to copy.
+ /// The bad pattern checked is when the last argument is basically
+ /// pointing to the destination buffer size or argument larger or
+ /// equal to.
+ /// char dst[2];
+ /// strlcat(dst, src2, sizeof(dst));
+ /// strlcat(dst, src2, 2);
+ /// strlcat(dst, src2, 10);
+ bool containsBadStrlcpyStrlcatPattern(const CallExpr *CE);
public:
WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC)
@@ -142,15 +151,19 @@ bool WalkAST::containsBadStrncatPattern(const CallExpr *CE) {
return false;
}
-bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
+bool WalkAST::containsBadStrlcpyStrlcatPattern(const CallExpr *CE) {
if (CE->getNumArgs() != 3)
return false;
+ const FunctionDecl *FD = CE->getDirectCallee();
+ bool Append = CheckerContext::isCLibraryFunction(FD, "strlcat");
const Expr *DstArg = CE->getArg(0);
const Expr *LenArg = CE->getArg(2);
const auto *DstArgDecl = dyn_cast<DeclRefExpr>(DstArg->IgnoreParenImpCasts());
const auto *LenArgDecl = dyn_cast<DeclRefExpr>(LenArg->IgnoreParenLValueCasts());
uint64_t DstOff = 0;
+ if (isSizeof(LenArg, DstArg))
+ return false;
// - size_t dstlen = sizeof(dst)
if (LenArgDecl) {
const auto *LenArgVal = dyn_cast<VarDecl>(LenArgDecl->getDecl());
@@ -181,8 +194,14 @@ bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) {
if (const auto *Buffer = dyn_cast<ConstantArrayType>(DstArgDecl->getType())) {
ASTContext &C = BR.getContext();
uint64_t BufferLen = C.getTypeSize(Buffer) / 8;
- if ((BufferLen - DstOff) < ILRawVal)
- return true;
+ auto RemainingBufferLen = BufferLen - DstOff;
+ if (Append) {
+ if (RemainingBufferLen <= ILRawVal)
+ return true;
+ } else {
+ if (RemainingBufferLen < ILRawVal)
+ return true;
+ }
}
}
}
@@ -219,8 +238,9 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
"C String API", os.str(), Loc,
LenArg->getSourceRange());
}
- } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) {
- if (containsBadStrlcpyPattern(CE)) {
+ } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy") ||
+ CheckerContext::isCLibraryFunction(FD, "strlcat")) {
+ if (containsBadStrlcpyStrlcatPattern(CE)) {
const Expr *DstArg = CE->getArg(0);
const Expr *LenArg = CE->getArg(2);
PathDiagnosticLocation Loc =
@@ -230,13 +250,17 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
SmallString<256> S;
llvm::raw_svector_ostream os(S);
- os << "The third argument is larger than the size of the input buffer. ";
+ os << "The third argument allows to potentially copy more bytes than it should. ";
+ os << "Replace with the value ";
if (!DstName.empty())
- os << "Replace with the value 'sizeof(" << DstName << ")` or lower";
+ os << "sizeof(" << DstName << ")";
+ else
+ os << "sizeof(<destination buffer>)";
+ os << " or lower";
BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument",
- "C String API", os.str(), Loc,
- LenArg->getSourceRange());
+ "C String API", os.str(), Loc,
+ LenArg->getSourceRange());
}
}
diff --git a/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
index d1d37c75dfcc..0b539e1188eb 100644
--- a/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
@@ -18,7 +18,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 20a46843e23e..ef30dc74c39d 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -108,7 +108,7 @@ void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
R->addRange(BadE->getSourceRange());
if (BadE->isGLValue())
BadE = bugreporter::getDerefExpr(BadE);
- bugreporter::trackNullOrUndefValue(N, BadE, *R);
+ bugreporter::trackExpressionValue(N, BadE, *R);
}
C.emitReport(std::move(R));
}
@@ -185,9 +185,9 @@ bool CallAndMessageChecker::uninitRefOrPointer(
LazyInit_BT(BD, BT);
auto R = llvm::make_unique<BugReport>(*BT, Os.str(), N);
R->addRange(ArgRange);
- if (ArgEx) {
- bugreporter::trackNullOrUndefValue(N, ArgEx, *R);
- }
+ if (ArgEx)
+ bugreporter::trackExpressionValue(N, ArgEx, *R);
+
C.emitReport(std::move(R));
}
return true;
@@ -196,6 +196,47 @@ bool CallAndMessageChecker::uninitRefOrPointer(
return false;
}
+namespace {
+class FindUninitializedField {
+public:
+ SmallVector<const FieldDecl *, 10> FieldChain;
+
+private:
+ StoreManager &StoreMgr;
+ MemRegionManager &MrMgr;
+ Store store;
+
+public:
+ FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr,
+ Store s)
+ : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
+
+ bool Find(const TypedValueRegion *R) {
+ QualType T = R->getValueType();
+ if (const RecordType *RT = T->getAsStructureType()) {
+ const RecordDecl *RD = RT->getDecl()->getDefinition();
+ assert(RD && "Referred record has no definition");
+ for (const auto *I : RD->fields()) {
+ const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
+ FieldChain.push_back(I);
+ T = I->getType();
+ if (T->getAsStructureType()) {
+ if (Find(FR))
+ return true;
+ } else {
+ const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
+ if (V.isUndef())
+ return true;
+ }
+ FieldChain.pop_back();
+ }
+ }
+
+ return false;
+ }
+};
+} // namespace
+
bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
SVal V,
SourceRange ArgRange,
@@ -223,7 +264,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
R->addRange(ArgRange);
if (ArgEx)
- bugreporter::trackNullOrUndefValue(N, ArgEx, *R);
+ bugreporter::trackExpressionValue(N, ArgEx, *R);
C.emitReport(std::move(R));
}
return true;
@@ -232,47 +273,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
if (!CheckUninitFields)
return false;
- if (Optional<nonloc::LazyCompoundVal> LV =
- V.getAs<nonloc::LazyCompoundVal>()) {
-
- class FindUninitializedField {
- public:
- SmallVector<const FieldDecl *, 10> FieldChain;
- private:
- StoreManager &StoreMgr;
- MemRegionManager &MrMgr;
- Store store;
- public:
- FindUninitializedField(StoreManager &storeMgr,
- MemRegionManager &mrMgr, Store s)
- : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
-
- bool Find(const TypedValueRegion *R) {
- QualType T = R->getValueType();
- if (const RecordType *RT = T->getAsStructureType()) {
- const RecordDecl *RD = RT->getDecl()->getDefinition();
- assert(RD && "Referred record has no definition");
- for (const auto *I : RD->fields()) {
- const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
- FieldChain.push_back(I);
- T = I->getType();
- if (T->getAsStructureType()) {
- if (Find(FR))
- return true;
- }
- else {
- const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
- if (V.isUndef())
- return true;
- }
- FieldChain.pop_back();
- }
- }
-
- return false;
- }
- };
-
+ if (auto LV = V.getAs<nonloc::LazyCompoundVal>()) {
const LazyCompoundValData *D = LV->getCVData();
FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
C.getSValBuilder().getRegionManager(),
@@ -305,6 +306,8 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
auto R = llvm::make_unique<BugReport>(*BT, os.str(), N);
R->addRange(ArgRange);
+ if (ArgEx)
+ bugreporter::trackExpressionValue(N, ArgEx, *R);
// FIXME: enhance track back for uninitialized value for arbitrary
// memregions
C.emitReport(std::move(R));
@@ -364,7 +367,7 @@ void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
Desc = "Argument to 'delete' is uninitialized";
BugType *BT = BT_cxx_delete_undef.get();
auto R = llvm::make_unique<BugReport>(*BT, Desc, N);
- bugreporter::trackNullOrUndefValue(N, DE, *R);
+ bugreporter::trackExpressionValue(N, DE, *R);
C.emitReport(std::move(R));
return;
}
@@ -493,7 +496,7 @@ void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
// FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
if (const Expr *ReceiverE = ME->getInstanceReceiver())
- bugreporter::trackNullOrUndefValue(N, ReceiverE, *R);
+ bugreporter::trackExpressionValue(N, ReceiverE, *R);
C.emitReport(std::move(R));
}
return;
@@ -534,7 +537,7 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
report->addRange(ME->getReceiverRange());
// FIXME: This won't track "self" in messages to super.
if (const Expr *receiver = ME->getInstanceReceiver()) {
- bugreporter::trackNullOrUndefValue(N, receiver, *report);
+ bugreporter::trackExpressionValue(N, receiver, *report);
}
C.emitReport(std::move(report));
}
diff --git a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 059553b21995..5deb62d32311 100644
--- a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -11,7 +11,7 @@
// whether the size of the symbolic region is a multiple of the size of T.
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/CharUnits.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index 00e903355720..2bd3879627cb 100644
--- a/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index f4d2e32cef11..00a912f27a8d 100644
--- a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -28,7 +28,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -178,20 +178,12 @@ private:
};
} // End anonymous namespace.
-typedef llvm::ImmutableSet<SymbolRef> SymbolSet;
/// Maps from the symbol for a class instance to the set of
/// symbols remaining that must be released in -dealloc.
+REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(SymbolSet, SymbolRef)
REGISTER_MAP_WITH_PROGRAMSTATE(UnreleasedIvarMap, SymbolRef, SymbolSet)
-namespace clang {
-namespace ento {
-template<> struct ProgramStateTrait<SymbolSet>
-: public ProgramStatePartialTrait<SymbolSet> {
- static void *GDMIndex() { static int index = 0; return &index; }
-};
-}
-}
/// An AST check that diagnose when the class requires a -dealloc method and
/// is missing one.
@@ -723,6 +715,10 @@ bool ObjCDeallocChecker::diagnoseExtraRelease(SymbolRef ReleasedValue,
bool ObjCDeallocChecker::diagnoseMistakenDealloc(SymbolRef DeallocedValue,
const ObjCMethodCall &M,
CheckerContext &C) const {
+ // TODO: Apart from unknown/undefined receivers, this may happen when
+ // dealloc is called as a class method. Should we warn?
+ if (!DeallocedValue)
+ return false;
// Find the property backing the instance variable that M
// is dealloc'ing.
@@ -761,15 +757,15 @@ ObjCDeallocChecker::ObjCDeallocChecker()
MissingReleaseBugType.reset(
new BugType(this, "Missing ivar release (leak)",
- categories::MemoryCoreFoundationObjectiveC));
+ categories::MemoryRefCount));
ExtraReleaseBugType.reset(
new BugType(this, "Extra ivar release",
- categories::MemoryCoreFoundationObjectiveC));
+ categories::MemoryRefCount));
MistakenDeallocBugType.reset(
new BugType(this, "Mistaken dealloc",
- categories::MemoryCoreFoundationObjectiveC));
+ categories::MemoryRefCount));
}
void ObjCDeallocChecker::initIdentifierInfoAndSelectors(
diff --git a/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp b/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
index cc4c0c3db846..fe6715595e6f 100644
--- a/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
diff --git a/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index 202233acffab..163ca9d8556f 100644
--- a/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/TargetInfo.h"
@@ -29,10 +29,10 @@ static bool isArc4RandomAvailable(const ASTContext &Ctx) {
const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
return T.getVendor() == llvm::Triple::Apple ||
T.getOS() == llvm::Triple::CloudABI ||
- T.getOS() == llvm::Triple::FreeBSD ||
- T.getOS() == llvm::Triple::NetBSD ||
- T.getOS() == llvm::Triple::OpenBSD ||
- T.getOS() == llvm::Triple::DragonFly;
+ T.isOSFreeBSD() ||
+ T.isOSNetBSD() ||
+ T.isOSOpenBSD() ||
+ T.isOSDragonFly();
}
namespace {
@@ -188,7 +188,7 @@ void WalkAST::VisitForStmt(ForStmt *FS) {
}
//===----------------------------------------------------------------------===//
-// Check: floating poing variable used as loop counter.
+// Check: floating point variable used as loop counter.
// Originally: <rdar://problem/6336718>
// Implements: CERT security coding advisory FLP-30.
//===----------------------------------------------------------------------===//
@@ -597,9 +597,10 @@ void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
unsigned suffix = 0;
if (ArgSuffix.second >= 0) {
const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
- llvm::APSInt Result;
- if (!suffixEx->EvaluateAsInt(Result, BR.getContext()))
+ Expr::EvalResult EVResult;
+ if (!suffixEx->EvaluateAsInt(EVResult, BR.getContext()))
return;
+ llvm::APSInt Result = EVResult.Val.getInt();
// FIXME: Issue a warning.
if (Result.isNegative())
return;
@@ -650,14 +651,14 @@ void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
const auto *Target = CE->getArg(0)->IgnoreImpCasts(),
*Source = CE->getArg(1)->IgnoreImpCasts();
- if (const auto *DeclRef = dyn_cast<DeclRefExpr>(Target))
- if (const auto *Array = dyn_cast<ConstantArrayType>(DeclRef->getType())) {
- uint64_t ArraySize = BR.getContext().getTypeSize(Array) / 8;
- if (const auto *String = dyn_cast<StringLiteral>(Source)) {
- if (ArraySize >= String->getLength() + 1)
- return;
- }
+
+ if (const auto *Array = dyn_cast<ConstantArrayType>(Target->getType())) {
+ uint64_t ArraySize = BR.getContext().getTypeSize(Array) / 8;
+ if (const auto *String = dyn_cast<StringLiteral>(Source)) {
+ if (ArraySize >= String->getLength() + 1)
+ return;
}
+ }
// Issue a warning.
PathDiagnosticLocation CELoc =
diff --git a/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp b/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
index e079a8cb12be..7688b713b06b 100644
--- a/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 7862a4c25681..44fac0278bdd 100644
--- a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -169,7 +169,7 @@ public:
/// This callback should be used by the checkers to aggressively clean
/// up/reduce the checker state, which is important for reducing the overall
/// memory usage. Specifically, if a checker keeps symbol specific information
- /// in the sate, it can and should be dropped after the symbol becomes dead.
+ /// in the state, it can and should be dropped after the symbol becomes dead.
/// In addition, reporting a bug as soon as the checker becomes dead leads to
/// more precise diagnostics. (For example, one should report that a malloced
/// variable is not freed right after it goes out of scope.)
diff --git a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index b38992b0e030..673608db1a1d 100644
--- a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp b/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp
deleted file mode 100644
index fb9e366c3de0..000000000000
--- a/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===--- ClangCheckers.h - Provides builtin checkers ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
-#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
-
-// FIXME: This is only necessary as long as there are checker registration
-// functions that do additional work besides mgr.registerChecker<CLASS>().
-// The only checkers that currently do this are:
-// - NSAutoreleasePoolChecker
-// - NSErrorChecker
-// - ObjCAtSyncChecker
-// It's probably worth including this information in Checkers.td to minimize
-// boilerplate code.
-#include "ClangSACheckers.h"
-
-using namespace clang;
-using namespace ento;
-
-void ento::registerBuiltinCheckers(CheckerRegistry &registry) {
-#define GET_CHECKERS
-#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,GROUPINDEX,HIDDEN) \
- registry.addChecker(register##CLASS, FULLNAME, HELPTEXT);
-#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
-#undef GET_CHECKERS
-}
diff --git a/lib/StaticAnalyzer/Checkers/CloneChecker.cpp b/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
index ee517ed97770..89354b866004 100644
--- a/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
@@ -13,7 +13,7 @@
///
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Analysis/CloneDetection.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -42,7 +42,7 @@ public:
void reportClones(BugReporter &BR, AnalysisManager &Mgr,
std::vector<CloneDetector::CloneGroup> &CloneGroups) const;
- /// Reports only suspicious clones to the user along with informaton
+ /// Reports only suspicious clones to the user along with information
/// that explain why they are suspicious.
void reportSuspiciousClones(
BugReporter &BR, AnalysisManager &Mgr,
@@ -63,18 +63,18 @@ void CloneChecker::checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
// At this point, every statement in the translation unit has been analyzed by
// the CloneDetector. The only thing left to do is to report the found clones.
- int MinComplexity = Mgr.getAnalyzerOptions().getOptionAsInteger(
+ int MinComplexity = Mgr.getAnalyzerOptions().getCheckerIntegerOption(
"MinimumCloneComplexity", 50, this);
assert(MinComplexity >= 0);
- bool ReportSuspiciousClones = Mgr.getAnalyzerOptions().getBooleanOption(
- "ReportSuspiciousClones", true, this);
+ bool ReportSuspiciousClones = Mgr.getAnalyzerOptions()
+ .getCheckerBooleanOption("ReportSuspiciousClones", true, this);
- bool ReportNormalClones = Mgr.getAnalyzerOptions().getBooleanOption(
+ bool ReportNormalClones = Mgr.getAnalyzerOptions().getCheckerBooleanOption(
"ReportNormalClones", true, this);
- StringRef IgnoredFilesPattern = Mgr.getAnalyzerOptions().getOptionAsString(
- "IgnoredFilesPattern", "", this);
+ StringRef IgnoredFilesPattern = Mgr.getAnalyzerOptions()
+ .getCheckerStringOption("IgnoredFilesPattern", "", this);
// Let the CloneDetector create a list of clones from all the analyzed
// statements. We don't filter for matching variable patterns at this point
diff --git a/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp b/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
index 17ec2c288777..a5c67c2a5b45 100644
--- a/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
@@ -14,20 +14,25 @@
// of expressions. A warning is reported when:
// * a negative value is implicitly converted to an unsigned value in an
// assignment, comparison or multiplication.
-// * assignment / initialization when source value is greater than the max
-// value of target
+// * assignment / initialization when the source value is greater than the max
+// value of the target integer type
+// * assignment / initialization when the source integer is above the range
+// where the target floating point type can represent all integers
//
// Many compilers and tools have similar checks that are based on semantic
// analysis. Those checks are sound but have poor precision. ConversionChecker
// is an alternative to those checks.
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/APFloat.h"
+
+#include <climits>
using namespace clang;
using namespace ento;
@@ -40,11 +45,9 @@ public:
private:
mutable std::unique_ptr<BuiltinBug> BT;
- // Is there loss of precision
bool isLossOfPrecision(const ImplicitCastExpr *Cast, QualType DestType,
CheckerContext &C) const;
- // Is there loss of sign
bool isLossOfSign(const ImplicitCastExpr *Cast, CheckerContext &C) const;
void reportBug(ExplodedNode *N, CheckerContext &C, const char Msg[]) const;
@@ -132,19 +135,51 @@ bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast,
QualType SubType = Cast->IgnoreParenImpCasts()->getType();
- if (!DestType->isIntegerType() || !SubType->isIntegerType())
+ if (!DestType->isRealType() || !SubType->isIntegerType())
return false;
- if (C.getASTContext().getIntWidth(DestType) >=
- C.getASTContext().getIntWidth(SubType))
+ const bool isFloat = DestType->isFloatingType();
+
+ const auto &AC = C.getASTContext();
+
+ // We will find the largest RepresentsUntilExp value such that the DestType
+ // can exactly represent all nonnegative integers below 2^RepresentsUntilExp.
+ unsigned RepresentsUntilExp;
+
+ if (isFloat) {
+ const llvm::fltSemantics &Sema = AC.getFloatTypeSemantics(DestType);
+ RepresentsUntilExp = llvm::APFloat::semanticsPrecision(Sema);
+ } else {
+ RepresentsUntilExp = AC.getIntWidth(DestType);
+ if (RepresentsUntilExp == 1) {
+ // This is just casting a number to bool, probably not a bug.
+ return false;
+ }
+ if (DestType->isSignedIntegerType())
+ RepresentsUntilExp--;
+ }
+
+ if (RepresentsUntilExp >= sizeof(unsigned long long) * CHAR_BIT) {
+ // Avoid overflow in our later calculations.
return false;
+ }
+
+ unsigned CorrectedSrcWidth = AC.getIntWidth(SubType);
+ if (SubType->isSignedIntegerType())
+ CorrectedSrcWidth--;
- unsigned W = C.getASTContext().getIntWidth(DestType);
- if (W == 1 || W >= 64U)
+ if (RepresentsUntilExp >= CorrectedSrcWidth) {
+ // Simple case: the destination can store all values of the source type.
return false;
+ }
- unsigned long long MaxVal = 1ULL << W;
+ unsigned long long MaxVal = 1ULL << RepresentsUntilExp;
+ if (isFloat) {
+ // If this is a floating point type, it can also represent MaxVal exactly.
+ MaxVal++;
+ }
return C.isGreaterOrEqual(Cast->getSubExpr(), MaxVal);
+ // TODO: maybe also check negative values with too large magnitude.
}
bool ConversionChecker::isLossOfSign(const ImplicitCastExpr *Cast,
diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index f7b5f61cfb8a..4e0f6d3bedfd 100644
--- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/ParentMap.h"
@@ -262,7 +262,7 @@ public:
currentBlock = block;
// Skip statements in macros.
- if (S->getLocStart().isMacroID())
+ if (S->getBeginLoc().isMacroID())
return;
// Only cover dead stores from regular assignments. ++/-- dead stores
@@ -329,9 +329,8 @@ public:
return;
if (const Expr *E = V->getInit()) {
- while (const ExprWithCleanups *exprClean =
- dyn_cast<ExprWithCleanups>(E))
- E = exprClean->getSubExpr();
+ while (const FullExpr *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
// Look through transitive assignments, e.g.:
// int x = y = 0;
diff --git a/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
index 810a33ed404d..90b1111aff0f 100644
--- a/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
+++ b/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Analysis/Analyses/Dominators.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CallGraph.h"
@@ -69,6 +69,25 @@ void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
}
//===----------------------------------------------------------------------===//
+// LiveStatementsDumper
+//===----------------------------------------------------------------------===//
+
+namespace {
+class LiveStatementsDumper : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
+ BugReporter &BR) const {
+ if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
+ L->dumpStmtLiveness(Mgr.getSourceManager());
+ }
+};
+}
+
+void ento::registerLiveStatementsDumper(CheckerManager &mgr) {
+ mgr.registerChecker<LiveStatementsDumper>();
+}
+
+//===----------------------------------------------------------------------===//
// CFGViewer
//===----------------------------------------------------------------------===//
@@ -182,7 +201,9 @@ public:
llvm::errs() << "[config]\n";
for (unsigned I = 0, E = Keys.size(); I != E; ++I)
- llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
+ llvm::errs() << Keys[I]->getKey() << " = "
+ << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
+ << '\n';
llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
}
diff --git a/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp b/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
index d3489282ab62..adf5a8e77a74 100644
--- a/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
@@ -21,7 +21,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -47,7 +47,6 @@ class DeleteWithNonVirtualDtorChecker
ID.AddPointer(&X);
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -104,7 +103,7 @@ void DeleteWithNonVirtualDtorChecker::checkPreStmt(const CXXDeleteExpr *DE,
std::shared_ptr<PathDiagnosticPiece>
DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode(
- const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+ const ExplodedNode *N, BugReporterContext &BRC,
BugReport &BR) {
// Stop traversal after the first conversion was found on a path.
if (Satisfied)
diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index 152b937bb03f..d01a889d256a 100644
--- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -111,6 +111,12 @@ static bool suppressReport(const Expr *E) {
return E->getType().getQualifiers().hasAddressSpace();
}
+static bool isDeclRefExprToReference(const Expr *E) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ return DRE->getDecl()->getType()->isReferenceType();
+ return false;
+}
+
void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
CheckerContext &C) const {
// Generate an error node.
@@ -154,7 +160,7 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
}
case Stmt::MemberExprClass: {
const MemberExpr *M = cast<MemberExpr>(S);
- if (M->isArrow() || bugreporter::isDeclRefExprToReference(M->getBase())) {
+ if (M->isArrow() || isDeclRefExprToReference(M->getBase())) {
os << "Access to field '" << M->getMemberNameInfo()
<< "' results in a dereference of a null pointer";
AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(),
@@ -177,7 +183,7 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
auto report = llvm::make_unique<BugReport>(
*BT_null, buf.empty() ? BT_null->getDescription() : StringRef(buf), N);
- bugreporter::trackNullOrUndefValue(N, bugreporter::getDerefExpr(S), *report);
+ bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report);
for (SmallVectorImpl<SourceRange>::iterator
I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
@@ -197,8 +203,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
auto report =
llvm::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
- bugreporter::trackNullOrUndefValue(N, bugreporter::getDerefExpr(S),
- *report);
+ bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report);
C.emitReport(std::move(report));
}
return;
diff --git a/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp b/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
index 5efb9096f2ff..2a559422df34 100644
--- a/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
+++ b/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
@@ -21,7 +21,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtVisitor.h"
diff --git a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index bc39c92ea970..a220a0513e28 100644
--- a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -32,6 +32,13 @@ public:
};
} // end anonymous namespace
+static const Expr *getDenomExpr(const ExplodedNode *N) {
+ const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
+ if (const auto *BE = dyn_cast<BinaryOperator>(S))
+ return BE->getRHS();
+ return nullptr;
+}
+
void DivZeroChecker::reportBug(
const char *Msg, ProgramStateRef StateZero, CheckerContext &C,
std::unique_ptr<BugReporterVisitor> Visitor) const {
@@ -41,7 +48,7 @@ void DivZeroChecker::reportBug(
auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
R->addVisitor(std::move(Visitor));
- bugreporter::trackNullOrUndefValue(N, bugreporter::GetDenomExpr(N), *R);
+ bugreporter::trackExpressionValue(N, getDenomExpr(N), *R);
C.emitReport(std::move(R));
}
}
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
index 4e4d81cd6714..803d7ae22a71 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
@@ -17,7 +17,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -49,7 +49,6 @@ class DynamicTypeChecker : public Checker<check::PostStmt<ImplicitCastExpr>> {
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -92,11 +91,10 @@ void DynamicTypeChecker::reportTypeError(QualType DynamicType,
std::shared_ptr<PathDiagnosticPiece>
DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR) {
+ BugReport &) {
ProgramStateRef State = N->getState();
- ProgramStateRef StatePrev = PrevN->getState();
+ ProgramStateRef StatePrev = N->getFirstPred()->getState();
DynamicTypeInfo TrackedType = getDynamicTypeInfo(State, Reg);
DynamicTypeInfo TrackedTypePrev = getDynamicTypeInfo(StatePrev, Reg);
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 126e57645a43..31d4eebe8968 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -21,7 +21,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Builtins.h"
@@ -85,7 +85,6 @@ class DynamicTypePropagation:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -124,11 +123,6 @@ void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
}
}
- if (!SR.hasDeadSymbols()) {
- C.addTransition(State);
- return;
- }
-
MostSpecializedTypeArgsMapTy TyArgMap =
State->get<MostSpecializedTypeArgsMap>();
for (MostSpecializedTypeArgsMapTy::iterator I = TyArgMap.begin(),
@@ -937,11 +931,10 @@ void DynamicTypePropagation::reportGenericsBug(
std::shared_ptr<PathDiagnosticPiece>
DynamicTypePropagation::GenericsBugVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) {
ProgramStateRef state = N->getState();
- ProgramStateRef statePrev = PrevN->getState();
+ ProgramStateRef statePrev = N->getFirstPred()->getState();
const ObjCObjectPointerType *const *TrackedType =
state->get<MostSpecializedTypeArgsMap>(Sym);
diff --git a/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
new file mode 100644
index 000000000000..4e51cffaa744
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
@@ -0,0 +1,128 @@
+//===- EnumCastOutOfRangeChecker.cpp ---------------------------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The EnumCastOutOfRangeChecker is responsible for checking integer to
+// enumeration casts that could result in undefined values. This could happen
+// if the value that we cast from is out of the value range of the enumeration.
+// Reference:
+// [ISO/IEC 14882-2014] ISO/IEC 14882-2014.
+// Programming Languages — C++, Fourth Edition. 2014.
+// C++ Standard, [dcl.enum], in paragraph 8, which defines the range of an enum
+// C++ Standard, [expr.static.cast], paragraph 10, which defines the behaviour
+// of casting an integer value that is out of range
+// SEI CERT C++ Coding Standard, INT50-CPP. Do not cast to an out-of-range
+// enumeration value
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+// This evaluator checks two SVals for equality. The first SVal is provided via
+// the constructor, the second is the parameter of the overloaded () operator.
+// It uses the in-built ConstraintManager to resolve the equlity to possible or
+// not possible ProgramStates.
+class ConstraintBasedEQEvaluator {
+ const DefinedOrUnknownSVal CompareValue;
+ const ProgramStateRef PS;
+ SValBuilder &SVB;
+
+public:
+ ConstraintBasedEQEvaluator(CheckerContext &C,
+ const DefinedOrUnknownSVal CompareValue)
+ : CompareValue(CompareValue), PS(C.getState()), SVB(C.getSValBuilder()) {}
+
+ bool operator()(const llvm::APSInt &EnumDeclInitValue) {
+ DefinedOrUnknownSVal EnumDeclValue = SVB.makeIntVal(EnumDeclInitValue);
+ DefinedOrUnknownSVal ElemEqualsValueToCast =
+ SVB.evalEQ(PS, EnumDeclValue, CompareValue);
+
+ return static_cast<bool>(PS->assume(ElemEqualsValueToCast, true));
+ }
+};
+
+// This checker checks CastExpr statements.
+// If the value provided to the cast is one of the values the enumeration can
+// represent, the said value matches the enumeration. If the checker can
+// establish the impossibility of matching it gives a warning.
+// Being conservative, it does not warn if there is slight possibility the
+// value can be matching.
+class EnumCastOutOfRangeChecker : public Checker<check::PreStmt<CastExpr>> {
+ mutable std::unique_ptr<BuiltinBug> EnumValueCastOutOfRange;
+ void reportWarning(CheckerContext &C) const;
+
+public:
+ void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
+};
+
+using EnumValueVector = llvm::SmallVector<llvm::APSInt, 6>;
+
+// Collects all of the values an enum can represent (as SVals).
+EnumValueVector getDeclValuesForEnum(const EnumDecl *ED) {
+ EnumValueVector DeclValues(
+ std::distance(ED->enumerator_begin(), ED->enumerator_end()));
+ llvm::transform(ED->enumerators(), DeclValues.begin(),
+ [](const EnumConstantDecl *D) { return D->getInitVal(); });
+ return DeclValues;
+}
+} // namespace
+
+void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C) const {
+ if (const ExplodedNode *N = C.generateNonFatalErrorNode()) {
+ if (!EnumValueCastOutOfRange)
+ EnumValueCastOutOfRange.reset(
+ new BuiltinBug(this, "Enum cast out of range",
+ "The value provided to the cast expression is not in "
+ "the valid range of values for the enum"));
+ C.emitReport(llvm::make_unique<BugReport>(
+ *EnumValueCastOutOfRange, EnumValueCastOutOfRange->getDescription(),
+ N));
+ }
+}
+
+void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE,
+ CheckerContext &C) const {
+ // Get the value of the expression to cast.
+ const llvm::Optional<DefinedOrUnknownSVal> ValueToCast =
+ C.getSVal(CE->getSubExpr()).getAs<DefinedOrUnknownSVal>();
+
+ // If the value cannot be reasoned about (not even a DefinedOrUnknownSVal),
+ // don't analyze further.
+ if (!ValueToCast)
+ return;
+
+ const QualType T = CE->getType();
+ // Check whether the cast type is an enum.
+ if (!T->isEnumeralType())
+ return;
+
+ // If the cast is an enum, get its declaration.
+ // If the isEnumeralType() returned true, then the declaration must exist
+ // even if it is a stub declaration. It is up to the getDeclValuesForEnum()
+ // function to handle this.
+ const EnumDecl *ED = T->castAs<EnumType>()->getDecl();
+
+ EnumValueVector DeclValues = getDeclValuesForEnum(ED);
+ // Check if any of the enum values possibly match.
+ bool PossibleValueMatch = llvm::any_of(
+ DeclValues, ConstraintBasedEQEvaluator(C, *ValueToCast));
+
+ // If there is no value that can possibly match any of the enum values, then
+ // warn.
+ if (!PossibleValueMatch)
+ reportWarning(C);
+}
+
+void ento::registerEnumCastOutOfRangeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<EnumCastOutOfRangeChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 8de653c10f7e..2553f54bbcac 100644
--- a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Checkers/SValExplainer.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -43,6 +43,8 @@ class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols,
void analyzerPrintState(const CallExpr *CE, CheckerContext &C) const;
void analyzerGetExtent(const CallExpr *CE, CheckerContext &C) const;
void analyzerHashDump(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerDenote(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerExpress(const CallExpr *CE, CheckerContext &C) const;
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
CheckerContext &C) const;
@@ -60,6 +62,7 @@ public:
}
REGISTER_SET_WITH_PROGRAMSTATE(MarkedSymbols, SymbolRef)
+REGISTER_MAP_WITH_PROGRAMSTATE(DenotedSymbols, SymbolRef, const StringLiteral *)
bool ExprInspectionChecker::evalCall(const CallExpr *CE,
CheckerContext &C) const {
@@ -82,6 +85,8 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
.Case("clang_analyzer_numTimesReached",
&ExprInspectionChecker::analyzerNumTimesReached)
.Case("clang_analyzer_hashDump", &ExprInspectionChecker::analyzerHashDump)
+ .Case("clang_analyzer_denote", &ExprInspectionChecker::analyzerDenote)
+ .Case("clang_analyzer_express", &ExprInspectionChecker::analyzerExpress)
.Default(nullptr);
if (!Handler)
@@ -264,6 +269,13 @@ void ExprInspectionChecker::checkDeadSymbols(SymbolReaper &SymReaper,
N = BugNode;
State = State->remove<MarkedSymbols>(Sym);
}
+
+ for (auto I : State->get<DenotedSymbols>()) {
+ SymbolRef Sym = I.first;
+ if (!SymReaper.isLive(Sym))
+ State = State->remove<DenotedSymbols>(Sym);
+ }
+
C.addTransition(State, N);
}
@@ -287,7 +299,7 @@ void ExprInspectionChecker::analyzerHashDump(const CallExpr *CE,
CheckerContext &C) const {
const LangOptions &Opts = C.getLangOpts();
const SourceManager &SM = C.getSourceManager();
- FullSourceLoc FL(CE->getArg(0)->getLocStart(), SM);
+ FullSourceLoc FL(CE->getArg(0)->getBeginLoc(), SM);
std::string HashContent =
GetIssueString(SM, FL, getCheckName().getName(), "Category",
C.getLocationContext()->getDecl(), Opts);
@@ -295,6 +307,105 @@ void ExprInspectionChecker::analyzerHashDump(const CallExpr *CE,
reportBug(HashContent, C);
}
+void ExprInspectionChecker::analyzerDenote(const CallExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getNumArgs() < 2) {
+ reportBug("clang_analyzer_denote() requires a symbol and a string literal",
+ C);
+ return;
+ }
+
+ SymbolRef Sym = C.getSVal(CE->getArg(0)).getAsSymbol();
+ if (!Sym) {
+ reportBug("Not a symbol", C);
+ return;
+ }
+
+ const auto *E = dyn_cast<StringLiteral>(CE->getArg(1)->IgnoreParenCasts());
+ if (!E) {
+ reportBug("Not a string literal", C);
+ return;
+ }
+
+ ProgramStateRef State = C.getState();
+
+ C.addTransition(C.getState()->set<DenotedSymbols>(Sym, E));
+}
+
+namespace {
+class SymbolExpressor
+ : public SymExprVisitor<SymbolExpressor, Optional<std::string>> {
+ ProgramStateRef State;
+
+public:
+ SymbolExpressor(ProgramStateRef State) : State(State) {}
+
+ Optional<std::string> lookup(const SymExpr *S) {
+ if (const StringLiteral *const *SLPtr = State->get<DenotedSymbols>(S)) {
+ const StringLiteral *SL = *SLPtr;
+ return std::string(SL->getBytes());
+ }
+ return None;
+ }
+
+ Optional<std::string> VisitSymExpr(const SymExpr *S) {
+ return lookup(S);
+ }
+
+ Optional<std::string> VisitSymIntExpr(const SymIntExpr *S) {
+ if (Optional<std::string> Str = lookup(S))
+ return Str;
+ if (Optional<std::string> Str = Visit(S->getLHS()))
+ return (*Str + " " + BinaryOperator::getOpcodeStr(S->getOpcode()) + " " +
+ std::to_string(S->getRHS().getLimitedValue()) +
+ (S->getRHS().isUnsigned() ? "U" : ""))
+ .str();
+ return None;
+ }
+
+ Optional<std::string> VisitSymSymExpr(const SymSymExpr *S) {
+ if (Optional<std::string> Str = lookup(S))
+ return Str;
+ if (Optional<std::string> Str1 = Visit(S->getLHS()))
+ if (Optional<std::string> Str2 = Visit(S->getRHS()))
+ return (*Str1 + " " + BinaryOperator::getOpcodeStr(S->getOpcode()) +
+ " " + *Str2).str();
+ return None;
+ }
+
+ Optional<std::string> VisitSymbolCast(const SymbolCast *S) {
+ if (Optional<std::string> Str = lookup(S))
+ return Str;
+ if (Optional<std::string> Str = Visit(S->getOperand()))
+ return (Twine("(") + S->getType().getAsString() + ")" + *Str).str();
+ return None;
+ }
+};
+} // namespace
+
+void ExprInspectionChecker::analyzerExpress(const CallExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getNumArgs() == 0) {
+ reportBug("clang_analyzer_express() requires a symbol", C);
+ return;
+ }
+
+ SymbolRef Sym = C.getSVal(CE->getArg(0)).getAsSymbol();
+ if (!Sym) {
+ reportBug("Not a symbol", C);
+ return;
+ }
+
+ SymbolExpressor V(C.getState());
+ auto Str = V.Visit(Sym);
+ if (!Str) {
+ reportBug("Unable to express", C);
+ return;
+ }
+
+ reportBug(*Str, C);
+}
+
void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
Mgr.registerChecker<ExprInspectionChecker>();
}
diff --git a/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index 059203fca730..165a4e4490eb 100644
--- a/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp b/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
index 5cb51b01f044..248b9c3f7693 100644
--- a/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
@@ -29,7 +29,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
diff --git a/lib/StaticAnalyzer/Checkers/GTestChecker.cpp b/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
index 3ef95e673b87..818716dd6070 100644
--- a/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LangOptions.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 899586745a0b..32fed202d3ab 100644
--- a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -14,7 +14,7 @@
// aggressively, even if the involved symbols are under constrained.
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/Basic/Builtins.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -28,10 +28,13 @@ using namespace clang;
using namespace ento;
namespace {
-class GenericTaintChecker : public Checker< check::PostStmt<CallExpr>,
- check::PreStmt<CallExpr> > {
+class GenericTaintChecker
+ : public Checker<check::PostStmt<CallExpr>, check::PreStmt<CallExpr>> {
public:
- static void *getTag() { static int Tag; return &Tag; }
+ static void *getTag() {
+ static int Tag;
+ return &Tag;
+ }
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
@@ -69,8 +72,8 @@ private:
static Optional<SVal> getPointedToSVal(CheckerContext &C, const Expr *Arg);
/// Functions defining the attack surface.
- typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
- CheckerContext &C) const;
+ typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(
+ const CallExpr *, CheckerContext &C) const;
ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
@@ -120,16 +123,15 @@ private:
TaintPropagationRule() {}
- TaintPropagationRule(unsigned SArg,
- unsigned DArg, bool TaintRet = false) {
+ TaintPropagationRule(unsigned SArg, unsigned DArg, bool TaintRet = false) {
SrcArgs.push_back(SArg);
DstArgs.push_back(DArg);
if (TaintRet)
DstArgs.push_back(ReturnValueIndex);
}
- TaintPropagationRule(unsigned SArg1, unsigned SArg2,
- unsigned DArg, bool TaintRet = false) {
+ TaintPropagationRule(unsigned SArg1, unsigned SArg2, unsigned DArg,
+ bool TaintRet = false) {
SrcArgs.push_back(SArg1);
SrcArgs.push_back(SArg2);
DstArgs.push_back(DArg);
@@ -139,18 +141,17 @@ private:
/// Get the propagation rule for a given function.
static TaintPropagationRule
- getTaintPropagationRule(const FunctionDecl *FDecl,
- StringRef Name,
- CheckerContext &C);
+ getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
+ CheckerContext &C);
inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
- inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
+ inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
inline bool isNull() const { return SrcArgs.empty(); }
inline bool isDestinationArgument(unsigned ArgNum) const {
- return (std::find(DstArgs.begin(),
- DstArgs.end(), ArgNum) != DstArgs.end());
+ return (std::find(DstArgs.begin(), DstArgs.end(), ArgNum) !=
+ DstArgs.end());
}
static inline bool isTaintedOrPointsToTainted(const Expr *E,
@@ -169,7 +170,6 @@ private:
/// Pre-process a function which propagates taint according to the
/// taint rule.
ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
-
};
};
@@ -177,17 +177,18 @@ const unsigned GenericTaintChecker::ReturnValueIndex;
const unsigned GenericTaintChecker::InvalidArgIndex;
const char GenericTaintChecker::MsgUncontrolledFormatString[] =
- "Untrusted data is used as a format string "
- "(CWE-134: Uncontrolled Format String)";
+ "Untrusted data is used as a format string "
+ "(CWE-134: Uncontrolled Format String)";
const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
- "Untrusted data is passed to a system call "
- "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
+ "Untrusted data is passed to a system call "
+ "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
const char GenericTaintChecker::MsgTaintedBufferSize[] =
- "Untrusted data is used to specify the buffer size "
- "(CERT/STR31-C. Guarantee that storage for strings has sufficient space for "
- "character data and the null terminator)";
+ "Untrusted data is used to specify the buffer size "
+ "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
+ "for "
+ "character data and the null terminator)";
} // end of anonymous namespace
@@ -199,33 +200,32 @@ REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
GenericTaintChecker::TaintPropagationRule
GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
- const FunctionDecl *FDecl,
- StringRef Name,
- CheckerContext &C) {
+ const FunctionDecl *FDecl, StringRef Name, CheckerContext &C) {
// TODO: Currently, we might lose precision here: we always mark a return
// value as tainted even if it's just a pointer, pointing to tainted data.
// Check for exact name match for functions without builtin substitutes.
- TaintPropagationRule Rule = llvm::StringSwitch<TaintPropagationRule>(Name)
- .Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
- .Case("atol", TaintPropagationRule(0, ReturnValueIndex))
- .Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
- .Case("getc", TaintPropagationRule(0, ReturnValueIndex))
- .Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
- .Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex))
- .Case("getw", TaintPropagationRule(0, ReturnValueIndex))
- .Case("toupper", TaintPropagationRule(0, ReturnValueIndex))
- .Case("tolower", TaintPropagationRule(0, ReturnValueIndex))
- .Case("strchr", TaintPropagationRule(0, ReturnValueIndex))
- .Case("strrchr", TaintPropagationRule(0, ReturnValueIndex))
- .Case("read", TaintPropagationRule(0, 2, 1, true))
- .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true))
- .Case("gets", TaintPropagationRule(InvalidArgIndex, 0, true))
- .Case("fgets", TaintPropagationRule(2, 0, true))
- .Case("getline", TaintPropagationRule(2, 0))
- .Case("getdelim", TaintPropagationRule(3, 0))
- .Case("fgetln", TaintPropagationRule(0, ReturnValueIndex))
- .Default(TaintPropagationRule());
+ TaintPropagationRule Rule =
+ llvm::StringSwitch<TaintPropagationRule>(Name)
+ .Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("atol", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("getc", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("getw", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("toupper", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("tolower", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("strchr", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("strrchr", TaintPropagationRule(0, ReturnValueIndex))
+ .Case("read", TaintPropagationRule(0, 2, 1, true))
+ .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true))
+ .Case("gets", TaintPropagationRule(InvalidArgIndex, 0, true))
+ .Case("fgets", TaintPropagationRule(2, 0, true))
+ .Case("getline", TaintPropagationRule(2, 0))
+ .Case("getdelim", TaintPropagationRule(3, 0))
+ .Case("fgetln", TaintPropagationRule(0, ReturnValueIndex))
+ .Default(TaintPropagationRule());
if (!Rule.isNull())
return Rule;
@@ -233,8 +233,8 @@ GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
// Check if it's one of the memory setting/copying functions.
// This check is specialized but faster then calling isCLibraryFunction.
unsigned BId = 0;
- if ( (BId = FDecl->getMemoryFunctionKind()) )
- switch(BId) {
+ if ((BId = FDecl->getMemoryFunctionKind()))
+ switch (BId) {
case Builtin::BImemcpy:
case Builtin::BImemmove:
case Builtin::BIstrncpy:
@@ -305,7 +305,7 @@ void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
// First, try generating a propagation rule for this function.
TaintPropagationRule Rule =
- TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
+ TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
if (!Rule.isNull()) {
State = Rule.process(CE, C);
if (!State)
@@ -316,15 +316,14 @@ void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
// Otherwise, check if we have custom pre-processing implemented.
FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
- .Case("fscanf", &GenericTaintChecker::preFscanf)
- .Default(nullptr);
+ .Case("fscanf", &GenericTaintChecker::preFscanf)
+ .Default(nullptr);
// Check and evaluate the call.
if (evalFunction)
State = (this->*evalFunction)(CE, C);
if (!State)
return;
C.addTransition(State);
-
}
bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
@@ -338,9 +337,10 @@ bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
if (TaintArgs.isEmpty())
return false;
- for (llvm::ImmutableSet<unsigned>::iterator
- I = TaintArgs.begin(), E = TaintArgs.end(); I != E; ++I) {
- unsigned ArgNum = *I;
+ for (llvm::ImmutableSet<unsigned>::iterator I = TaintArgs.begin(),
+ E = TaintArgs.end();
+ I != E; ++I) {
+ unsigned ArgNum = *I;
// Special handling for the tainted return value.
if (ArgNum == ReturnValueIndex) {
@@ -352,7 +352,7 @@ bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
// tainted after the call.
if (CE->getNumArgs() < (ArgNum + 1))
return false;
- const Expr* Arg = CE->getArg(ArgNum);
+ const Expr *Arg = CE->getArg(ArgNum);
Optional<SVal> V = getPointedToSVal(C, Arg);
if (V)
State = State->addTaint(*V);
@@ -379,19 +379,20 @@ void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
StringRef Name = C.getCalleeName(FDecl);
if (Name.empty())
return;
- FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
- .Case("scanf", &GenericTaintChecker::postScanf)
- // TODO: Add support for vfscanf & family.
- .Case("getchar", &GenericTaintChecker::postRetTaint)
- .Case("getchar_unlocked", &GenericTaintChecker::postRetTaint)
- .Case("getenv", &GenericTaintChecker::postRetTaint)
- .Case("fopen", &GenericTaintChecker::postRetTaint)
- .Case("fdopen", &GenericTaintChecker::postRetTaint)
- .Case("freopen", &GenericTaintChecker::postRetTaint)
- .Case("getch", &GenericTaintChecker::postRetTaint)
- .Case("wgetch", &GenericTaintChecker::postRetTaint)
- .Case("socket", &GenericTaintChecker::postSocket)
- .Default(nullptr);
+ FnCheck evalFunction =
+ llvm::StringSwitch<FnCheck>(Name)
+ .Case("scanf", &GenericTaintChecker::postScanf)
+ // TODO: Add support for vfscanf & family.
+ .Case("getchar", &GenericTaintChecker::postRetTaint)
+ .Case("getchar_unlocked", &GenericTaintChecker::postRetTaint)
+ .Case("getenv", &GenericTaintChecker::postRetTaint)
+ .Case("fopen", &GenericTaintChecker::postRetTaint)
+ .Case("fdopen", &GenericTaintChecker::postRetTaint)
+ .Case("freopen", &GenericTaintChecker::postRetTaint)
+ .Case("getch", &GenericTaintChecker::postRetTaint)
+ .Case("wgetch", &GenericTaintChecker::postRetTaint)
+ .Case("socket", &GenericTaintChecker::postSocket)
+ .Default(nullptr);
// If the callee isn't defined, it is not of security concern.
// Check and evaluate the call.
@@ -404,7 +405,8 @@ void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
C.addTransition(State);
}
-bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
+bool GenericTaintChecker::checkPre(const CallExpr *CE,
+ CheckerContext &C) const {
if (checkUncontrolledFormatString(CE, C))
return true;
@@ -458,8 +460,8 @@ GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
// Check for taint in arguments.
bool IsTainted = false;
- for (ArgVector::const_iterator I = SrcArgs.begin(),
- E = SrcArgs.end(); I != E; ++I) {
+ for (ArgVector::const_iterator I = SrcArgs.begin(), E = SrcArgs.end(); I != E;
+ ++I) {
unsigned ArgNum = *I;
if (ArgNum == InvalidArgIndex) {
@@ -483,8 +485,8 @@ GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
return State;
// Mark the arguments which should be tainted after the function returns.
- for (ArgVector::const_iterator I = DstArgs.begin(),
- E = DstArgs.end(); I != E; ++I) {
+ for (ArgVector::const_iterator I = DstArgs.begin(), E = DstArgs.end(); I != E;
+ ++I) {
unsigned ArgNum = *I;
// Should we mark all arguments as tainted?
@@ -498,8 +500,8 @@ GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
// Process pointer argument.
const Type *ArgTy = Arg->getType().getTypePtr();
QualType PType = ArgTy->getPointeeType();
- if ((!PType.isNull() && !PType.isConstQualified())
- || (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
+ if ((!PType.isNull() && !PType.isConstQualified()) ||
+ (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
State = State->add<TaintArgsOnPostVisit>(i);
}
continue;
@@ -519,11 +521,10 @@ GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
return State;
}
-
// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
// and arg 1 should get taint.
ProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE,
- CheckerContext &C) const {
+ CheckerContext &C) const {
assert(CE->getNumArgs() >= 2);
ProgramStateRef State = C.getState();
@@ -532,14 +533,13 @@ ProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE,
isStdin(CE->getArg(0), C)) {
// All arguments except for the first two should get taint.
for (unsigned int i = 2; i < CE->getNumArgs(); ++i)
- State = State->add<TaintArgsOnPostVisit>(i);
+ State = State->add<TaintArgsOnPostVisit>(i);
return State;
}
return nullptr;
}
-
// If argument 0(protocol domain) is network, the return value should get taint.
ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE,
CheckerContext &C) const {
@@ -558,7 +558,7 @@ ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE,
}
ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE,
- CheckerContext &C) const {
+ CheckerContext &C) const {
ProgramStateRef State = C.getState();
if (CE->getNumArgs() < 2)
return State;
@@ -567,7 +567,7 @@ ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE,
for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
// The arguments are pointer arguments. The data they are pointing at is
// tainted after the call.
- const Expr* Arg = CE->getArg(i);
+ const Expr *Arg = CE->getArg(i);
Optional<SVal> V = getPointedToSVal(C, Arg);
if (V)
State = State->addTaint(*V);
@@ -593,7 +593,8 @@ bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
return false;
// Get it's symbol and find the declaration region it's pointing to.
- const SymbolRegionValue *Sm =dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
+ const SymbolRegionValue *Sm =
+ dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
if (!Sm)
return false;
const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
@@ -605,11 +606,11 @@ bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
if (const VarDecl *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
D = D->getCanonicalDecl();
if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC())
- if (const PointerType * PtrTy =
+ if (const PointerType *PtrTy =
dyn_cast<PointerType>(D->getType().getTypePtr()))
- if (PtrTy->getPointeeType().getCanonicalType() ==
- C.getASTContext().getFILEType().getCanonicalType())
- return true;
+ if (PtrTy->getPointeeType().getCanonicalType() ==
+ C.getASTContext().getFILEType().getCanonicalType())
+ return true;
}
return false;
}
@@ -625,8 +626,7 @@ static bool getPrintfFormatArgumentNum(const CallExpr *CE,
return false;
for (const auto *Format : FDecl->specific_attrs<FormatAttr>()) {
ArgNum = Format->getFormatIdx() - 1;
- if ((Format->getType()->getName() == "printf") &&
- CE->getNumArgs() > ArgNum)
+ if ((Format->getType()->getName() == "printf") && CE->getNumArgs() > ArgNum)
return true;
}
@@ -667,36 +667,36 @@ bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
return false;
}
-bool GenericTaintChecker::checkUncontrolledFormatString(const CallExpr *CE,
- CheckerContext &C) const{
+bool GenericTaintChecker::checkUncontrolledFormatString(
+ const CallExpr *CE, CheckerContext &C) const {
// Check if the function contains a format string argument.
unsigned int ArgNum = 0;
if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
return false;
- // If either the format string content or the pointer itself are tainted, warn.
+ // If either the format string content or the pointer itself are tainted,
+ // warn.
return generateReportIfTainted(CE->getArg(ArgNum),
MsgUncontrolledFormatString, C);
}
-bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
- StringRef Name,
+bool GenericTaintChecker::checkSystemCall(const CallExpr *CE, StringRef Name,
CheckerContext &C) const {
// TODO: It might make sense to run this check on demand. In some cases,
// we should check if the environment has been cleansed here. We also might
// need to know if the user was reset before these calls(seteuid).
unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
- .Case("system", 0)
- .Case("popen", 0)
- .Case("execl", 0)
- .Case("execle", 0)
- .Case("execlp", 0)
- .Case("execv", 0)
- .Case("execvp", 0)
- .Case("execvP", 0)
- .Case("execve", 0)
- .Case("dlopen", 0)
- .Default(UINT_MAX);
+ .Case("system", 0)
+ .Case("popen", 0)
+ .Case("execl", 0)
+ .Case("execle", 0)
+ .Case("execlp", 0)
+ .Case("execv", 0)
+ .Case("execvp", 0)
+ .Case("execvP", 0)
+ .Case("execve", 0)
+ .Case("dlopen", 0)
+ .Default(UINT_MAX);
if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1))
return false;
@@ -712,8 +712,8 @@ bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
// If the function has a buffer size argument, set ArgNum.
unsigned ArgNum = InvalidArgIndex;
unsigned BId = 0;
- if ( (BId = FDecl->getMemoryFunctionKind()) )
- switch(BId) {
+ if ((BId = FDecl->getMemoryFunctionKind()))
+ switch (BId) {
case Builtin::BImemcpy:
case Builtin::BImemmove:
case Builtin::BIstrncpy:
diff --git a/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index f102ca96a5c1..4c2a229428d9 100644
--- a/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -16,7 +16,7 @@
///
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
index 29677f737f5c..a4f47d727a8f 100644
--- a/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
@@ -14,7 +14,8 @@
//===----------------------------------------------------------------------===//
#include "AllocationState.h"
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "InterCheckerAPI.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -24,23 +25,10 @@
using namespace clang;
using namespace ento;
-using PtrSet = llvm::ImmutableSet<SymbolRef>;
-
// Associate container objects with a set of raw pointer symbols.
+REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(PtrSet, SymbolRef)
REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, PtrSet)
-// This is a trick to gain access to PtrSet's Factory.
-namespace clang {
-namespace ento {
-template <>
-struct ProgramStateTrait<PtrSet> : public ProgramStatePartialTrait<PtrSet> {
- static void *GDMIndex() {
- static int Index = 0;
- return &Index;
- }
-};
-} // end namespace ento
-} // end namespace clang
namespace {
@@ -67,8 +55,7 @@ public:
ID.AddPointer(getTag());
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
+ virtual std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -85,14 +72,20 @@ public:
};
InnerPointerChecker()
- : AppendFn("append"), AssignFn("assign"), ClearFn("clear"),
- CStrFn("c_str"), DataFn("data"), EraseFn("erase"), InsertFn("insert"),
- PopBackFn("pop_back"), PushBackFn("push_back"), ReplaceFn("replace"),
- ReserveFn("reserve"), ResizeFn("resize"),
- ShrinkToFitFn("shrink_to_fit"), SwapFn("swap") {}
-
- /// Check if the object of this member function call is a `basic_string`.
- bool isCalledOnStringObject(const CXXInstanceCall *ICall) const;
+ : AppendFn({"std", "basic_string", "append"}),
+ AssignFn({"std", "basic_string", "assign"}),
+ ClearFn({"std", "basic_string", "clear"}),
+ CStrFn({"std", "basic_string", "c_str"}),
+ DataFn({"std", "basic_string", "data"}),
+ EraseFn({"std", "basic_string", "erase"}),
+ InsertFn({"std", "basic_string", "insert"}),
+ PopBackFn({"std", "basic_string", "pop_back"}),
+ PushBackFn({"std", "basic_string", "push_back"}),
+ ReplaceFn({"std", "basic_string", "replace"}),
+ ReserveFn({"std", "basic_string", "reserve"}),
+ ResizeFn({"std", "basic_string", "resize"}),
+ ShrinkToFitFn({"std", "basic_string", "shrink_to_fit"}),
+ SwapFn({"std", "basic_string", "swap"}) {}
/// Check whether the called member function potentially invalidates
/// pointers referring to the container object's inner buffer.
@@ -121,21 +114,6 @@ public:
} // end anonymous namespace
-bool InnerPointerChecker::isCalledOnStringObject(
- const CXXInstanceCall *ICall) const {
- const auto *ObjRegion =
- dyn_cast_or_null<TypedValueRegion>(ICall->getCXXThisVal().getAsRegion());
- if (!ObjRegion)
- return false;
-
- QualType ObjTy = ObjRegion->getValueType();
- if (ObjTy.isNull() ||
- ObjTy->getAsCXXRecordDecl()->getName() != "basic_string")
- return false;
-
- return true;
-}
-
bool InnerPointerChecker::isInvalidatingMemberFunction(
const CallEvent &Call) const {
if (const auto *MemOpCall = dyn_cast<CXXMemberOperatorCall>(&Call)) {
@@ -219,33 +197,34 @@ void InnerPointerChecker::checkPostCall(const CallEvent &Call,
ProgramStateRef State = C.getState();
if (const auto *ICall = dyn_cast<CXXInstanceCall>(&Call)) {
- if (isCalledOnStringObject(ICall)) {
- const auto *ObjRegion = dyn_cast_or_null<TypedValueRegion>(
- ICall->getCXXThisVal().getAsRegion());
-
- if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) {
- SVal RawPtr = Call.getReturnValue();
- if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) {
- // Start tracking this raw pointer by adding it to the set of symbols
- // associated with this container object in the program state map.
-
- PtrSet::Factory &F = State->getStateManager().get_context<PtrSet>();
- const PtrSet *SetPtr = State->get<RawPtrMap>(ObjRegion);
- PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet();
- assert(C.wasInlined || !Set.contains(Sym));
- Set = F.add(Set, Sym);
-
- State = State->set<RawPtrMap>(ObjRegion, Set);
- C.addTransition(State);
- }
- return;
- }
+ // TODO: Do we need these to be typed?
+ const auto *ObjRegion = dyn_cast_or_null<TypedValueRegion>(
+ ICall->getCXXThisVal().getAsRegion());
+ if (!ObjRegion)
+ return;
+
+ if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) {
+ SVal RawPtr = Call.getReturnValue();
+ if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) {
+ // Start tracking this raw pointer by adding it to the set of symbols
+ // associated with this container object in the program state map.
- // Check [string.require] / second point.
- if (isInvalidatingMemberFunction(Call)) {
- markPtrSymbolsReleased(Call, State, ObjRegion, C);
- return;
+ PtrSet::Factory &F = State->getStateManager().get_context<PtrSet>();
+ const PtrSet *SetPtr = State->get<RawPtrMap>(ObjRegion);
+ PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet();
+ assert(C.wasInlined || !Set.contains(Sym));
+ Set = F.add(Set, Sym);
+
+ State = State->set<RawPtrMap>(ObjRegion, Set);
+ C.addTransition(State);
}
+ return;
+ }
+
+ // Check [string.require] / second point.
+ if (isInvalidatingMemberFunction(Call)) {
+ markPtrSymbolsReleased(Call, State, ObjRegion, C);
+ return;
}
}
@@ -278,41 +257,56 @@ void InnerPointerChecker::checkDeadSymbols(SymbolReaper &SymReaper,
C.addTransition(State);
}
+namespace clang {
+namespace ento {
+namespace allocation_state {
+
+std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym) {
+ return llvm::make_unique<InnerPointerChecker::InnerPointerBRVisitor>(Sym);
+}
+
+const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym) {
+ RawPtrMapTy Map = State->get<RawPtrMap>();
+ for (const auto Entry : Map) {
+ if (Entry.second.contains(Sym)) {
+ return Entry.first;
+ }
+ }
+ return nullptr;
+}
+
+} // end namespace allocation_state
+} // end namespace ento
+} // end namespace clang
+
std::shared_ptr<PathDiagnosticPiece>
InnerPointerChecker::InnerPointerBRVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR) {
+ BugReport &) {
if (!isSymbolTracked(N->getState(), PtrToBuf) ||
- isSymbolTracked(PrevN->getState(), PtrToBuf))
+ isSymbolTracked(N->getFirstPred()->getState(), PtrToBuf))
return nullptr;
const Stmt *S = PathDiagnosticLocation::getStmt(N);
if (!S)
return nullptr;
+ const MemRegion *ObjRegion =
+ allocation_state::getContainerObjRegion(N->getState(), PtrToBuf);
+ const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
+ QualType ObjTy = TypedRegion->getValueType();
+
SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
- OS << "Dangling inner pointer obtained here";
+ OS << "Pointer to inner buffer of '" << ObjTy.getAsString()
+ << "' obtained here";
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true,
nullptr);
}
-namespace clang {
-namespace ento {
-namespace allocation_state {
-
-std::unique_ptr<BugReporterVisitor> getInnerPointerBRVisitor(SymbolRef Sym) {
- return llvm::make_unique<InnerPointerChecker::InnerPointerBRVisitor>(Sym);
-}
-
-} // end namespace allocation_state
-} // end namespace ento
-} // end namespace clang
-
void ento::registerInnerPointerChecker(CheckerManager &Mgr) {
- registerNewDeleteChecker(Mgr);
+ registerInnerPointerCheckerAux(Mgr);
Mgr.registerChecker<InnerPointerChecker>();
}
diff --git a/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h b/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
index d38d63cd05ce..81c95a4813a6 100644
--- a/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
+++ b/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
@@ -20,5 +20,8 @@ namespace ento {
/// Register the checker which evaluates CString API calls.
void registerCStringCheckerBasic(CheckerManager &Mgr);
+/// Register the part of MallocChecker connected to InnerPointerChecker.
+void registerInnerPointerCheckerAux(CheckerManager &Mgr);
+
}}
#endif /* INTERCHECKERAPI_H_ */
diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index 520c32e1c770..e719e19d68e9 100644
--- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -66,11 +66,15 @@
// making an assumption e.g. `S1 + n == S2 + m` we store `S1 - S2 == m - n` as
// a constraint which we later retrieve when doing an actual comparison.
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+
+#include <utility>
using namespace clang;
using namespace ento;
@@ -85,34 +89,47 @@ private:
// Container the iterator belongs to
const MemRegion *Cont;
+ // Whether iterator is valid
+ const bool Valid;
+
// Abstract offset
const SymbolRef Offset;
- IteratorPosition(const MemRegion *C, SymbolRef Of)
- : Cont(C), Offset(Of) {}
+ IteratorPosition(const MemRegion *C, bool V, SymbolRef Of)
+ : Cont(C), Valid(V), Offset(Of) {}
public:
const MemRegion *getContainer() const { return Cont; }
+ bool isValid() const { return Valid; }
SymbolRef getOffset() const { return Offset; }
+ IteratorPosition invalidate() const {
+ return IteratorPosition(Cont, false, Offset);
+ }
+
static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) {
- return IteratorPosition(C, Of);
+ return IteratorPosition(C, true, Of);
}
IteratorPosition setTo(SymbolRef NewOf) const {
- return IteratorPosition(Cont, NewOf);
+ return IteratorPosition(Cont, Valid, NewOf);
+ }
+
+ IteratorPosition reAssign(const MemRegion *NewCont) const {
+ return IteratorPosition(NewCont, Valid, Offset);
}
bool operator==(const IteratorPosition &X) const {
- return Cont == X.Cont && Offset == X.Offset;
+ return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset;
}
bool operator!=(const IteratorPosition &X) const {
- return Cont != X.Cont || Offset != X.Offset;
+ return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset;
}
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(Cont);
+ ID.AddInteger(Valid);
ID.Add(Offset);
}
};
@@ -181,15 +198,17 @@ public:
class IteratorChecker
: public Checker<check::PreCall, check::PostCall,
- check::PreStmt<CXXOperatorCallExpr>,
- check::PostStmt<MaterializeTemporaryExpr>,
+ check::PostStmt<MaterializeTemporaryExpr>, check::Bind,
check::LiveSymbols, check::DeadSymbols,
eval::Assume> {
std::unique_ptr<BugType> OutOfRangeBugType;
+ std::unique_ptr<BugType> MismatchedBugType;
+ std::unique_ptr<BugType> InvalidatedBugType;
void handleComparison(CheckerContext &C, const SVal &RetVal, const SVal &LVal,
const SVal &RVal, OverloadedOperatorKind Op) const;
+ void verifyAccess(CheckerContext &C, const SVal &Val) const;
void verifyDereference(CheckerContext &C, const SVal &Val) const;
void handleIncrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter,
bool Postfix) const;
@@ -204,17 +223,50 @@ class IteratorChecker
const SVal &Cont) const;
void assignToContainer(CheckerContext &C, const Expr *CE, const SVal &RetVal,
const MemRegion *Cont) const;
+ void handleAssign(CheckerContext &C, const SVal &Cont,
+ const Expr *CE = nullptr,
+ const SVal &OldCont = UndefinedVal()) const;
+ void handleClear(CheckerContext &C, const SVal &Cont) const;
+ void handlePushBack(CheckerContext &C, const SVal &Cont) const;
+ void handlePopBack(CheckerContext &C, const SVal &Cont) const;
+ void handlePushFront(CheckerContext &C, const SVal &Cont) const;
+ void handlePopFront(CheckerContext &C, const SVal &Cont) const;
+ void handleInsert(CheckerContext &C, const SVal &Iter) const;
+ void handleErase(CheckerContext &C, const SVal &Iter) const;
+ void handleErase(CheckerContext &C, const SVal &Iter1,
+ const SVal &Iter2) const;
+ void handleEraseAfter(CheckerContext &C, const SVal &Iter) const;
+ void handleEraseAfter(CheckerContext &C, const SVal &Iter1,
+ const SVal &Iter2) const;
+ void verifyIncrement(CheckerContext &C, const SVal &Iter) const;
+ void verifyDecrement(CheckerContext &C, const SVal &Iter) const;
void verifyRandomIncrOrDecr(CheckerContext &C, OverloadedOperatorKind Op,
- const SVal &RetVal, const SVal &LHS,
- const SVal &RHS) const;
+ const SVal &LHS, const SVal &RHS) const;
+ void verifyMatch(CheckerContext &C, const SVal &Iter,
+ const MemRegion *Cont) const;
+ void verifyMatch(CheckerContext &C, const SVal &Iter1,
+ const SVal &Iter2) const;
+ IteratorPosition advancePosition(CheckerContext &C, OverloadedOperatorKind Op,
+ const IteratorPosition &Pos,
+ const SVal &Distance) const;
void reportOutOfRangeBug(const StringRef &Message, const SVal &Val,
CheckerContext &C, ExplodedNode *ErrNode) const;
+ void reportMismatchedBug(const StringRef &Message, const SVal &Val1,
+ const SVal &Val2, CheckerContext &C,
+ ExplodedNode *ErrNode) const;
+ void reportMismatchedBug(const StringRef &Message, const SVal &Val,
+ const MemRegion *Reg, CheckerContext &C,
+ ExplodedNode *ErrNode) const;
+ void reportInvalidatedBug(const StringRef &Message, const SVal &Val,
+ CheckerContext &C, ExplodedNode *ErrNode) const;
public:
IteratorChecker();
enum CheckKind {
CK_IteratorRangeChecker,
+ CK_MismatchedIteratorChecker,
+ CK_InvalidatedIteratorChecker,
CK_NumCheckKinds
};
@@ -223,7 +275,9 @@ public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
- void checkPreStmt(const CXXOperatorCallExpr *COCE, CheckerContext &C) const;
+ void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const;
+ void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const;
+ void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;
void checkPostStmt(const MaterializeTemporaryExpr *MTE,
CheckerContext &C) const;
void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
@@ -246,13 +300,31 @@ namespace {
bool isIteratorType(const QualType &Type);
bool isIterator(const CXXRecordDecl *CRD);
+bool isComparisonOperator(OverloadedOperatorKind OK);
bool isBeginCall(const FunctionDecl *Func);
bool isEndCall(const FunctionDecl *Func);
+bool isAssignCall(const FunctionDecl *Func);
+bool isClearCall(const FunctionDecl *Func);
+bool isPushBackCall(const FunctionDecl *Func);
+bool isEmplaceBackCall(const FunctionDecl *Func);
+bool isPopBackCall(const FunctionDecl *Func);
+bool isPushFrontCall(const FunctionDecl *Func);
+bool isEmplaceFrontCall(const FunctionDecl *Func);
+bool isPopFrontCall(const FunctionDecl *Func);
+bool isInsertCall(const FunctionDecl *Func);
+bool isEraseCall(const FunctionDecl *Func);
+bool isEraseAfterCall(const FunctionDecl *Func);
+bool isEmplaceCall(const FunctionDecl *Func);
+bool isAssignmentOperator(OverloadedOperatorKind OK);
bool isSimpleComparisonOperator(OverloadedOperatorKind OK);
+bool isAccessOperator(OverloadedOperatorKind OK);
bool isDereferenceOperator(OverloadedOperatorKind OK);
bool isIncrementOperator(OverloadedOperatorKind OK);
bool isDecrementOperator(OverloadedOperatorKind OK);
bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK);
+bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg);
+bool frontModifiable(ProgramStateRef State, const MemRegion *Reg);
+bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
BinaryOperator::Opcode getOpcode(const SymExpr *SE);
const RegionOrSymbol getRegionOrSymbol(const SVal &Val);
const ProgramStateRef processComparison(ProgramStateRef State,
@@ -287,12 +359,41 @@ ProgramStateRef relateIteratorPositions(ProgramStateRef State,
const IteratorPosition &Pos1,
const IteratorPosition &Pos2,
bool Equal);
+ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
+ const MemRegion *Cont);
+ProgramStateRef
+invalidateAllIteratorPositionsExcept(ProgramStateRef State,
+ const MemRegion *Cont, SymbolRef Offset,
+ BinaryOperator::Opcode Opc);
+ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
+ SymbolRef Offset,
+ BinaryOperator::Opcode Opc);
+ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
+ SymbolRef Offset1,
+ BinaryOperator::Opcode Opc1,
+ SymbolRef Offset2,
+ BinaryOperator::Opcode Opc2);
+ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
+ const MemRegion *Cont,
+ const MemRegion *NewCont);
+ProgramStateRef reassignAllIteratorPositionsUnless(ProgramStateRef State,
+ const MemRegion *Cont,
+ const MemRegion *NewCont,
+ SymbolRef Offset,
+ BinaryOperator::Opcode Opc);
+ProgramStateRef rebaseSymbolInIteratorPositionsIf(
+ ProgramStateRef State, SValBuilder &SVB, SymbolRef OldSym,
+ SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc);
const ContainerData *getContainerData(ProgramStateRef State,
const MemRegion *Cont);
ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
const ContainerData &CData);
bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
-bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos);
+bool isBoundThroughLazyCompoundVal(const Environment &Env,
+ const MemRegion *Reg);
+bool isPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos);
+bool isAheadOfRange(ProgramStateRef State, const IteratorPosition &Pos);
+bool isBehindPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos);
bool isZero(ProgramStateRef State, const NonLoc &Val);
} // namespace
@@ -300,39 +401,198 @@ IteratorChecker::IteratorChecker() {
OutOfRangeBugType.reset(
new BugType(this, "Iterator out of range", "Misuse of STL APIs"));
OutOfRangeBugType->setSuppressOnSink(true);
+ MismatchedBugType.reset(
+ new BugType(this, "Iterator(s) mismatched", "Misuse of STL APIs"));
+ MismatchedBugType->setSuppressOnSink(true);
+ InvalidatedBugType.reset(
+ new BugType(this, "Iterator invalidated", "Misuse of STL APIs"));
+ InvalidatedBugType->setSuppressOnSink(true);
}
void IteratorChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
- // Check for out of range access
+ // Check for out of range access or access of invalidated position and
+ // iterator mismatches
const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
if (!Func)
return;
if (Func->isOverloadedOperator()) {
- if (ChecksEnabled[CK_IteratorRangeChecker] &&
- isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
+ if (ChecksEnabled[CK_InvalidatedIteratorChecker] &&
+ isAccessOperator(Func->getOverloadedOperator())) {
+ // Check for any kind of access of invalidated iterator positions
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
- // Check for out-of-range incrementions and decrementions
- if (Call.getNumArgs() >= 1) {
- verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
- Call.getReturnValue(),
- InstCall->getCXXThisVal(), Call.getArgSVal(0));
- }
+ verifyAccess(C, InstCall->getCXXThisVal());
} else {
- if (Call.getNumArgs() >= 2) {
- verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
- Call.getReturnValue(), Call.getArgSVal(0),
- Call.getArgSVal(1));
+ verifyAccess(C, Call.getArgSVal(0));
+ }
+ }
+ if (ChecksEnabled[CK_IteratorRangeChecker]) {
+ if (isIncrementOperator(Func->getOverloadedOperator())) {
+ // Check for out-of-range incrementions
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ verifyIncrement(C, InstCall->getCXXThisVal());
+ } else {
+ if (Call.getNumArgs() >= 1) {
+ verifyIncrement(C, Call.getArgSVal(0));
+ }
+ }
+ } else if (isDecrementOperator(Func->getOverloadedOperator())) {
+ // Check for out-of-range decrementions
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ verifyDecrement(C, InstCall->getCXXThisVal());
+ } else {
+ if (Call.getNumArgs() >= 1) {
+ verifyDecrement(C, Call.getArgSVal(0));
+ }
+ }
+ } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ // Check for out-of-range incrementions and decrementions
+ if (Call.getNumArgs() >= 1) {
+ verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
+ InstCall->getCXXThisVal(),
+ Call.getArgSVal(0));
+ }
+ } else {
+ if (Call.getNumArgs() >= 2) {
+ verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
+ Call.getArgSVal(0), Call.getArgSVal(1));
+ }
+ }
+ } else if (isDereferenceOperator(Func->getOverloadedOperator())) {
+ // Check for dereference of out-of-range iterators
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ verifyDereference(C, InstCall->getCXXThisVal());
+ } else {
+ verifyDereference(C, Call.getArgSVal(0));
}
}
- } else if (ChecksEnabled[CK_IteratorRangeChecker] &&
- isDereferenceOperator(Func->getOverloadedOperator())) {
- // Check for dereference of out-of-range iterators
+ } else if (ChecksEnabled[CK_MismatchedIteratorChecker] &&
+ isComparisonOperator(Func->getOverloadedOperator())) {
+ // Check for comparisons of iterators of different containers
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
- verifyDereference(C, InstCall->getCXXThisVal());
+ if (Call.getNumArgs() < 1)
+ return;
+
+ if (!isIteratorType(InstCall->getCXXThisExpr()->getType()) ||
+ !isIteratorType(Call.getArgExpr(0)->getType()))
+ return;
+
+ verifyMatch(C, InstCall->getCXXThisVal(), Call.getArgSVal(0));
} else {
- verifyDereference(C, Call.getArgSVal(0));
+ if (Call.getNumArgs() < 2)
+ return;
+
+ if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
+ !isIteratorType(Call.getArgExpr(1)->getType()))
+ return;
+
+ verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+ }
+ }
+ } else if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ if (!ChecksEnabled[CK_MismatchedIteratorChecker])
+ return;
+
+ const auto *ContReg = InstCall->getCXXThisVal().getAsRegion();
+ if (!ContReg)
+ return;
+ // Check for erase, insert and emplace using iterator of another container
+ if (isEraseCall(Func) || isEraseAfterCall(Func)) {
+ verifyMatch(C, Call.getArgSVal(0),
+ InstCall->getCXXThisVal().getAsRegion());
+ if (Call.getNumArgs() == 2) {
+ verifyMatch(C, Call.getArgSVal(1),
+ InstCall->getCXXThisVal().getAsRegion());
+ }
+ } else if (isInsertCall(Func)) {
+ verifyMatch(C, Call.getArgSVal(0),
+ InstCall->getCXXThisVal().getAsRegion());
+ if (Call.getNumArgs() == 3 &&
+ isIteratorType(Call.getArgExpr(1)->getType()) &&
+ isIteratorType(Call.getArgExpr(2)->getType())) {
+ verifyMatch(C, Call.getArgSVal(1), Call.getArgSVal(2));
+ }
+ } else if (isEmplaceCall(Func)) {
+ verifyMatch(C, Call.getArgSVal(0),
+ InstCall->getCXXThisVal().getAsRegion());
+ }
+ } else if (isa<CXXConstructorCall>(&Call)) {
+ // Check match of first-last iterator pair in a constructor of a container
+ if (Call.getNumArgs() < 2)
+ return;
+
+ const auto *Ctr = cast<CXXConstructorDecl>(Call.getDecl());
+ if (Ctr->getNumParams() < 2)
+ return;
+
+ if (Ctr->getParamDecl(0)->getName() != "first" ||
+ Ctr->getParamDecl(1)->getName() != "last")
+ return;
+
+ if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
+ !isIteratorType(Call.getArgExpr(1)->getType()))
+ return;
+
+ verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+ } else {
+ // The main purpose of iterators is to abstract away from different
+ // containers and provide a (maybe limited) uniform access to them.
+ // This implies that any correctly written template function that
+ // works on multiple containers using iterators takes different
+ // template parameters for different containers. So we can safely
+ // assume that passing iterators of different containers as arguments
+ // whose type replaces the same template parameter is a bug.
+ //
+ // Example:
+ // template<typename I1, typename I2>
+ // void f(I1 first1, I1 last1, I2 first2, I2 last2);
+ //
+ // In this case the first two arguments to f() must be iterators must belong
+ // to the same container and the last to also to the same container but
+ // not necessarily to the same as the first two.
+
+ if (!ChecksEnabled[CK_MismatchedIteratorChecker])
+ return;
+
+ const auto *Templ = Func->getPrimaryTemplate();
+ if (!Templ)
+ return;
+
+ const auto *TParams = Templ->getTemplateParameters();
+ const auto *TArgs = Func->getTemplateSpecializationArgs();
+
+ // Iterate over all the template parameters
+ for (size_t I = 0; I < TParams->size(); ++I) {
+ const auto *TPDecl = dyn_cast<TemplateTypeParmDecl>(TParams->getParam(I));
+ if (!TPDecl)
+ continue;
+
+ if (TPDecl->isParameterPack())
+ continue;
+
+ const auto TAType = TArgs->get(I).getAsType();
+ if (!isIteratorType(TAType))
+ continue;
+
+ SVal LHS = UndefinedVal();
+
+ // For every template parameter which is an iterator type in the
+ // instantiation look for all functions' parameters' type by it and
+ // check whether they belong to the same container
+ for (auto J = 0U; J < Func->getNumParams(); ++J) {
+ const auto *Param = Func->getParamDecl(J);
+ const auto *ParamType =
+ Param->getType()->getAs<SubstTemplateTypeParmType>();
+ if (!ParamType ||
+ ParamType->getReplacedParameter()->getDecl() != TPDecl)
+ continue;
+ if (LHS.isUndef()) {
+ LHS = Call.getArgSVal(J);
+ } else {
+ verifyMatch(C, LHS, Call.getArgSVal(J));
+ }
}
}
}
@@ -347,7 +607,15 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
if (Func->isOverloadedOperator()) {
const auto Op = Func->getOverloadedOperator();
- if (isSimpleComparisonOperator(Op)) {
+ if (isAssignmentOperator(Op)) {
+ const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call);
+ if (Func->getParamDecl(0)->getType()->isRValueReferenceType()) {
+ handleAssign(C, InstCall->getCXXThisVal(), Call.getOriginExpr(),
+ Call.getArgSVal(0));
+ } else {
+ handleAssign(C, InstCall->getCXXThisVal());
+ }
+ } else if (isSimpleComparisonOperator(Op)) {
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
handleComparison(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
Call.getArgSVal(0), Op);
@@ -387,6 +655,36 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
}
}
} else {
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ if (isAssignCall(Func)) {
+ handleAssign(C, InstCall->getCXXThisVal());
+ } else if (isClearCall(Func)) {
+ handleClear(C, InstCall->getCXXThisVal());
+ } else if (isPushBackCall(Func) || isEmplaceBackCall(Func)) {
+ handlePushBack(C, InstCall->getCXXThisVal());
+ } else if (isPopBackCall(Func)) {
+ handlePopBack(C, InstCall->getCXXThisVal());
+ } else if (isPushFrontCall(Func) || isEmplaceFrontCall(Func)) {
+ handlePushFront(C, InstCall->getCXXThisVal());
+ } else if (isPopFrontCall(Func)) {
+ handlePopFront(C, InstCall->getCXXThisVal());
+ } else if (isInsertCall(Func) || isEmplaceCall(Func)) {
+ handleInsert(C, Call.getArgSVal(0));
+ } else if (isEraseCall(Func)) {
+ if (Call.getNumArgs() == 1) {
+ handleErase(C, Call.getArgSVal(0));
+ } else if (Call.getNumArgs() == 2) {
+ handleErase(C, Call.getArgSVal(0), Call.getArgSVal(1));
+ }
+ } else if (isEraseAfterCall(Func)) {
+ if (Call.getNumArgs() == 1) {
+ handleEraseAfter(C, Call.getArgSVal(0));
+ } else if (Call.getNumArgs() == 2) {
+ handleEraseAfter(C, Call.getArgSVal(0), Call.getArgSVal(1));
+ }
+ }
+ }
+
const auto *OrigExpr = Call.getOriginExpr();
if (!OrigExpr)
return;
@@ -395,9 +693,6 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
return;
auto State = C.getState();
- // Already bound to container?
- if (getIteratorPosition(State, Call.getReturnValue()))
- return;
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
if (isBeginCall(Func)) {
@@ -412,6 +707,10 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
}
}
+ // Already bound to container?
+ if (getIteratorPosition(State, Call.getReturnValue()))
+ return;
+
// Copy-like and move constructors
if (isa<CXXConstructorCall>(&Call) && Call.getNumArgs() == 1) {
if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(0))) {
@@ -441,33 +740,19 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
}
}
-void IteratorChecker::checkPreStmt(const CXXOperatorCallExpr *COCE,
- CheckerContext &C) const {
- const auto *ThisExpr = COCE->getArg(0);
-
+void IteratorChecker::checkBind(SVal Loc, SVal Val, const Stmt *S,
+ CheckerContext &C) const {
auto State = C.getState();
- const auto *LCtx = C.getLocationContext();
-
- const auto CurrentThis = State->getSVal(ThisExpr, LCtx);
- if (const auto *Reg = CurrentThis.getAsRegion()) {
- if (!Reg->getAs<CXXTempObjectRegion>())
- return;
- const auto OldState = C.getPredecessor()->getFirstPred()->getState();
- const auto OldThis = OldState->getSVal(ThisExpr, LCtx);
- // FIXME: This solution is unreliable. It may happen that another checker
- // subscribes to the pre-statement check of `CXXOperatorCallExpr`
- // and adds a transition before us. The proper fix is to make the
- // CFG provide a `ConstructionContext` for the `CXXOperatorCallExpr`,
- // which would turn the corresponding `CFGStmt` element into a
- // `CFGCXXRecordTypedCall` element, which will allow `ExprEngine` to
- // foresee that the `begin()`/`end()` call constructs the object
- // directly in the temporary region that `CXXOperatorCallExpr` takes
- // as its implicit object argument.
- const auto *Pos = getIteratorPosition(OldState, OldThis);
- if (!Pos)
- return;
- State = setIteratorPosition(State, CurrentThis, *Pos);
+ const auto *Pos = getIteratorPosition(State, Val);
+ if (Pos) {
+ State = setIteratorPosition(State, Loc, *Pos);
C.addTransition(State);
+ } else {
+ const auto *OldPos = getIteratorPosition(State, Loc);
+ if (OldPos) {
+ State = removeIteratorPosition(State, Loc);
+ C.addTransition(State);
+ }
}
}
@@ -508,9 +793,13 @@ void IteratorChecker::checkLiveSymbols(ProgramStateRef State,
const auto CData = Cont.second;
if (CData.getBegin()) {
SR.markLive(CData.getBegin());
+ if(const auto *SIE = dyn_cast<SymIntExpr>(CData.getBegin()))
+ SR.markLive(SIE->getLHS());
}
if (CData.getEnd()) {
SR.markLive(CData.getEnd());
+ if(const auto *SIE = dyn_cast<SymIntExpr>(CData.getEnd()))
+ SR.markLive(SIE->getLHS());
}
}
}
@@ -523,7 +812,12 @@ void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
auto RegionMap = State->get<IteratorRegionMap>();
for (const auto Reg : RegionMap) {
if (!SR.isLiveRegion(Reg.first)) {
- State = State->remove<IteratorRegionMap>(Reg.first);
+ // The region behind the `LazyCompoundVal` is often cleaned up before
+ // the `LazyCompoundVal` itself. If there are iterator positions keyed
+ // by these regions their cleanup must be deferred.
+ if (!isBoundThroughLazyCompoundVal(State->getEnvironment(), Reg.first)) {
+ State = State->remove<IteratorRegionMap>(Reg.first);
+ }
}
}
@@ -623,14 +917,24 @@ void IteratorChecker::verifyDereference(CheckerContext &C,
const SVal &Val) const {
auto State = C.getState();
const auto *Pos = getIteratorPosition(State, Val);
- if (Pos && isOutOfRange(State, *Pos)) {
- // If I do not put a tag here, some range tests will fail
- static CheckerProgramPointTag Tag("IteratorRangeChecker",
- "IteratorOutOfRange");
- auto *N = C.generateNonFatalErrorNode(State, &Tag);
+ if (Pos && isPastTheEnd(State, *Pos)) {
+ auto *N = C.generateNonFatalErrorNode(State);
if (!N)
return;
- reportOutOfRangeBug("Iterator accessed outside of its range.", Val, C, N);
+ reportOutOfRangeBug("Past-the-end iterator dereferenced.", Val, C, N);
+ return;
+ }
+}
+
+void IteratorChecker::verifyAccess(CheckerContext &C, const SVal &Val) const {
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, Val);
+ if (Pos && !Pos->isValid()) {
+ auto *N = C.generateNonFatalErrorNode(State);
+ if (!N) {
+ return;
+ }
+ reportInvalidatedBug("Invalidated iterator accessed.", Val, C, N);
}
}
@@ -643,14 +947,9 @@ void IteratorChecker::handleIncrement(CheckerContext &C, const SVal &RetVal,
if (Pos) {
auto &SymMgr = C.getSymbolManager();
auto &BVF = SymMgr.getBasicVals();
- auto &SVB = C.getSValBuilder();
- const auto OldOffset = Pos->getOffset();
- auto NewOffset =
- SVB.evalBinOp(State, BO_Add,
- nonloc::SymbolVal(OldOffset),
- nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
- SymMgr.getType(OldOffset)).getAsSymbol();
- auto NewPos = Pos->setTo(NewOffset);
+ const auto NewPos =
+ advancePosition(C, OO_Plus, *Pos,
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
State = setIteratorPosition(State, Iter, NewPos);
State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos);
C.addTransition(State);
@@ -666,14 +965,9 @@ void IteratorChecker::handleDecrement(CheckerContext &C, const SVal &RetVal,
if (Pos) {
auto &SymMgr = C.getSymbolManager();
auto &BVF = SymMgr.getBasicVals();
- auto &SVB = C.getSValBuilder();
- const auto OldOffset = Pos->getOffset();
- auto NewOffset =
- SVB.evalBinOp(State, BO_Sub,
- nonloc::SymbolVal(OldOffset),
- nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
- SymMgr.getType(OldOffset)).getAsSymbol();
- auto NewPos = Pos->setTo(NewOffset);
+ const auto NewPos =
+ advancePosition(C, OO_Minus, *Pos,
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
State = setIteratorPosition(State, Iter, NewPos);
State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos);
C.addTransition(State);
@@ -739,69 +1033,95 @@ void IteratorChecker::handleRandomIncrOrDecr(CheckerContext &C,
value = &val;
}
- auto &SymMgr = C.getSymbolManager();
- auto &SVB = C.getSValBuilder();
- auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
- const auto OldOffset = Pos->getOffset();
- SymbolRef NewOffset;
- if (const auto intValue = value->getAs<nonloc::ConcreteInt>()) {
- // For concrete integers we can calculate the new position
- NewOffset = SVB.evalBinOp(State, BinOp, nonloc::SymbolVal(OldOffset),
- *intValue,
- SymMgr.getType(OldOffset)).getAsSymbol();
- } else {
- // For other symbols create a new symbol to keep expressions simple
- const auto &LCtx = C.getLocationContext();
- NewOffset = SymMgr.conjureSymbol(nullptr, LCtx, SymMgr.getType(OldOffset),
- C.blockCount());
- State = assumeNoOverflow(State, NewOffset, 4);
- }
- auto NewPos = Pos->setTo(NewOffset);
auto &TgtVal = (Op == OO_PlusEqual || Op == OO_MinusEqual) ? LHS : RetVal;
- State = setIteratorPosition(State, TgtVal, NewPos);
+ State =
+ setIteratorPosition(State, TgtVal, advancePosition(C, Op, *Pos, *value));
C.addTransition(State);
}
+void IteratorChecker::verifyIncrement(CheckerContext &C,
+ const SVal &Iter) const {
+ auto &BVF = C.getSValBuilder().getBasicValueFactory();
+ verifyRandomIncrOrDecr(C, OO_Plus, Iter,
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
+}
+
+void IteratorChecker::verifyDecrement(CheckerContext &C,
+ const SVal &Iter) const {
+ auto &BVF = C.getSValBuilder().getBasicValueFactory();
+ verifyRandomIncrOrDecr(C, OO_Minus, Iter,
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
+}
+
void IteratorChecker::verifyRandomIncrOrDecr(CheckerContext &C,
OverloadedOperatorKind Op,
- const SVal &RetVal,
const SVal &LHS,
const SVal &RHS) const {
auto State = C.getState();
// If the iterator is initially inside its range, then the operation is valid
const auto *Pos = getIteratorPosition(State, LHS);
- if (!Pos || !isOutOfRange(State, *Pos))
+ if (!Pos)
return;
- auto value = RHS;
- if (auto loc = RHS.getAs<Loc>()) {
- value = State->getRawSVal(*loc);
+ auto Value = RHS;
+ if (auto ValAsLoc = RHS.getAs<Loc>()) {
+ Value = State->getRawSVal(*ValAsLoc);
}
- // Incremention or decremention by 0 is never bug
- if (isZero(State, value.castAs<NonLoc>()))
+ if (Value.isUnknown())
return;
- auto &SymMgr = C.getSymbolManager();
- auto &SVB = C.getSValBuilder();
- auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
- const auto OldOffset = Pos->getOffset();
- const auto intValue = value.getAs<nonloc::ConcreteInt>();
- if (!intValue)
+ // Incremention or decremention by 0 is never a bug.
+ if (isZero(State, Value.castAs<NonLoc>()))
return;
- auto NewOffset = SVB.evalBinOp(State, BinOp, nonloc::SymbolVal(OldOffset),
- *intValue,
- SymMgr.getType(OldOffset)).getAsSymbol();
- auto NewPos = Pos->setTo(NewOffset);
+ // The result may be the past-end iterator of the container, but any other
+ // out of range position is undefined behaviour
+ if (isAheadOfRange(State, advancePosition(C, Op, *Pos, Value))) {
+ auto *N = C.generateNonFatalErrorNode(State);
+ if (!N)
+ return;
+ reportOutOfRangeBug("Iterator decremented ahead of its valid range.", LHS,
+ C, N);
+ }
+ if (isBehindPastTheEnd(State, advancePosition(C, Op, *Pos, Value))) {
+ auto *N = C.generateNonFatalErrorNode(State);
+ if (!N)
+ return;
+ reportOutOfRangeBug("Iterator incremented behind the past-the-end "
+ "iterator.", LHS, C, N);
+ }
+}
+
+void IteratorChecker::verifyMatch(CheckerContext &C, const SVal &Iter,
+ const MemRegion *Cont) const {
+ // Verify match between a container and the container of an iterator
+ Cont = Cont->getMostDerivedObjectRegion();
+
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, Iter);
+ if (Pos && Pos->getContainer() != Cont) {
+ auto *N = C.generateNonFatalErrorNode(State);
+ if (!N) {
+ return;
+ }
+ reportMismatchedBug("Container accessed using foreign iterator argument.", Iter, Cont, C, N);
+ }
+}
- // If out of range, the only valid operation is to step into the range
- if (isOutOfRange(State, NewPos)) {
+void IteratorChecker::verifyMatch(CheckerContext &C, const SVal &Iter1,
+ const SVal &Iter2) const {
+ // Verify match between the containers of two iterators
+ auto State = C.getState();
+ const auto *Pos1 = getIteratorPosition(State, Iter1);
+ const auto *Pos2 = getIteratorPosition(State, Iter2);
+ if (Pos1 && Pos2 && Pos1->getContainer() != Pos2->getContainer()) {
auto *N = C.generateNonFatalErrorNode(State);
if (!N)
return;
- reportOutOfRangeBug("Iterator accessed past its end.", LHS, C, N);
+ reportMismatchedBug("Iterators of different containers used where the "
+ "same container is expected.", Iter1, Iter2, C, N);
}
}
@@ -811,9 +1131,7 @@ void IteratorChecker::handleBegin(CheckerContext &C, const Expr *CE,
if (!ContReg)
return;
- while (const auto *CBOR = ContReg->getAs<CXXBaseObjectRegion>()) {
- ContReg = CBOR->getSuperRegion();
- }
+ ContReg = ContReg->getMostDerivedObjectRegion();
// If the container already has a begin symbol then use it. Otherwise first
// create a new one.
@@ -837,9 +1155,7 @@ void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE,
if (!ContReg)
return;
- while (const auto *CBOR = ContReg->getAs<CXXBaseObjectRegion>()) {
- ContReg = CBOR->getSuperRegion();
- }
+ ContReg = ContReg->getMostDerivedObjectRegion();
// If the container already has an end symbol then use it. Otherwise first
// create a new one.
@@ -860,9 +1176,7 @@ void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE,
void IteratorChecker::assignToContainer(CheckerContext &C, const Expr *CE,
const SVal &RetVal,
const MemRegion *Cont) const {
- while (const auto *CBOR = Cont->getAs<CXXBaseObjectRegion>()) {
- Cont = CBOR->getSuperRegion();
- }
+ Cont = Cont->getMostDerivedObjectRegion();
auto State = C.getState();
auto &SymMgr = C.getSymbolManager();
@@ -874,6 +1188,399 @@ void IteratorChecker::assignToContainer(CheckerContext &C, const Expr *CE,
C.addTransition(State);
}
+void IteratorChecker::handleAssign(CheckerContext &C, const SVal &Cont,
+ const Expr *CE, const SVal &OldCont) const {
+ const auto *ContReg = Cont.getAsRegion();
+ if (!ContReg)
+ return;
+
+ ContReg = ContReg->getMostDerivedObjectRegion();
+
+ // Assignment of a new value to a container always invalidates all its
+ // iterators
+ auto State = C.getState();
+ const auto CData = getContainerData(State, ContReg);
+ if (CData) {
+ State = invalidateAllIteratorPositions(State, ContReg);
+ }
+
+ // In case of move, iterators of the old container (except the past-end
+ // iterators) remain valid but refer to the new container
+ if (!OldCont.isUndef()) {
+ const auto *OldContReg = OldCont.getAsRegion();
+ if (OldContReg) {
+ OldContReg = OldContReg->getMostDerivedObjectRegion();
+ const auto OldCData = getContainerData(State, OldContReg);
+ if (OldCData) {
+ if (const auto OldEndSym = OldCData->getEnd()) {
+ // If we already assigned an "end" symbol to the old container, then
+ // first reassign all iterator positions to the new container which
+ // are not past the container (thus not greater or equal to the
+ // current "end" symbol).
+ State = reassignAllIteratorPositionsUnless(State, OldContReg, ContReg,
+ OldEndSym, BO_GE);
+ auto &SymMgr = C.getSymbolManager();
+ auto &SVB = C.getSValBuilder();
+ // Then generate and assign a new "end" symbol for the new container.
+ auto NewEndSym =
+ SymMgr.conjureSymbol(CE, C.getLocationContext(),
+ C.getASTContext().LongTy, C.blockCount());
+ State = assumeNoOverflow(State, NewEndSym, 4);
+ if (CData) {
+ State = setContainerData(State, ContReg, CData->newEnd(NewEndSym));
+ } else {
+ State = setContainerData(State, ContReg,
+ ContainerData::fromEnd(NewEndSym));
+ }
+ // Finally, replace the old "end" symbol in the already reassigned
+ // iterator positions with the new "end" symbol.
+ State = rebaseSymbolInIteratorPositionsIf(
+ State, SVB, OldEndSym, NewEndSym, OldEndSym, BO_LT);
+ } else {
+ // There was no "end" symbol assigned yet to the old container,
+ // so reassign all iterator positions to the new container.
+ State = reassignAllIteratorPositions(State, OldContReg, ContReg);
+ }
+ if (const auto OldBeginSym = OldCData->getBegin()) {
+ // If we already assigned a "begin" symbol to the old container, then
+ // assign it to the new container and remove it from the old one.
+ if (CData) {
+ State =
+ setContainerData(State, ContReg, CData->newBegin(OldBeginSym));
+ } else {
+ State = setContainerData(State, ContReg,
+ ContainerData::fromBegin(OldBeginSym));
+ }
+ State =
+ setContainerData(State, OldContReg, OldCData->newEnd(nullptr));
+ }
+ } else {
+ // There was neither "begin" nor "end" symbol assigned yet to the old
+ // container, so reassign all iterator positions to the new container.
+ State = reassignAllIteratorPositions(State, OldContReg, ContReg);
+ }
+ }
+ }
+ C.addTransition(State);
+}
+
+void IteratorChecker::handleClear(CheckerContext &C, const SVal &Cont) const {
+ const auto *ContReg = Cont.getAsRegion();
+ if (!ContReg)
+ return;
+
+ ContReg = ContReg->getMostDerivedObjectRegion();
+
+ // The clear() operation invalidates all the iterators, except the past-end
+ // iterators of list-like containers
+ auto State = C.getState();
+ if (!hasSubscriptOperator(State, ContReg) ||
+ !backModifiable(State, ContReg)) {
+ const auto CData = getContainerData(State, ContReg);
+ if (CData) {
+ if (const auto EndSym = CData->getEnd()) {
+ State =
+ invalidateAllIteratorPositionsExcept(State, ContReg, EndSym, BO_GE);
+ C.addTransition(State);
+ return;
+ }
+ }
+ }
+ State = invalidateAllIteratorPositions(State, ContReg);
+ C.addTransition(State);
+}
+
+void IteratorChecker::handlePushBack(CheckerContext &C,
+ const SVal &Cont) const {
+ const auto *ContReg = Cont.getAsRegion();
+ if (!ContReg)
+ return;
+
+ ContReg = ContReg->getMostDerivedObjectRegion();
+
+ // For deque-like containers invalidate all iterator positions
+ auto State = C.getState();
+ if (hasSubscriptOperator(State, ContReg) && frontModifiable(State, ContReg)) {
+ State = invalidateAllIteratorPositions(State, ContReg);
+ C.addTransition(State);
+ return;
+ }
+
+ const auto CData = getContainerData(State, ContReg);
+ if (!CData)
+ return;
+
+ // For vector-like containers invalidate the past-end iterator positions
+ if (const auto EndSym = CData->getEnd()) {
+ if (hasSubscriptOperator(State, ContReg)) {
+ State = invalidateIteratorPositions(State, EndSym, BO_GE);
+ }
+ auto &SymMgr = C.getSymbolManager();
+ auto &BVF = SymMgr.getBasicVals();
+ auto &SVB = C.getSValBuilder();
+ const auto newEndSym =
+ SVB.evalBinOp(State, BO_Add,
+ nonloc::SymbolVal(EndSym),
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
+ SymMgr.getType(EndSym)).getAsSymbol();
+ State = setContainerData(State, ContReg, CData->newEnd(newEndSym));
+ }
+ C.addTransition(State);
+}
+
+void IteratorChecker::handlePopBack(CheckerContext &C, const SVal &Cont) const {
+ const auto *ContReg = Cont.getAsRegion();
+ if (!ContReg)
+ return;
+
+ ContReg = ContReg->getMostDerivedObjectRegion();
+
+ auto State = C.getState();
+ const auto CData = getContainerData(State, ContReg);
+ if (!CData)
+ return;
+
+ if (const auto EndSym = CData->getEnd()) {
+ auto &SymMgr = C.getSymbolManager();
+ auto &BVF = SymMgr.getBasicVals();
+ auto &SVB = C.getSValBuilder();
+ const auto BackSym =
+ SVB.evalBinOp(State, BO_Sub,
+ nonloc::SymbolVal(EndSym),
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
+ SymMgr.getType(EndSym)).getAsSymbol();
+ // For vector-like and deque-like containers invalidate the last and the
+ // past-end iterator positions. For list-like containers only invalidate
+ // the last position
+ if (hasSubscriptOperator(State, ContReg) &&
+ backModifiable(State, ContReg)) {
+ State = invalidateIteratorPositions(State, BackSym, BO_GE);
+ State = setContainerData(State, ContReg, CData->newEnd(nullptr));
+ } else {
+ State = invalidateIteratorPositions(State, BackSym, BO_EQ);
+ }
+ auto newEndSym = BackSym;
+ State = setContainerData(State, ContReg, CData->newEnd(newEndSym));
+ C.addTransition(State);
+ }
+}
+
+void IteratorChecker::handlePushFront(CheckerContext &C,
+ const SVal &Cont) const {
+ const auto *ContReg = Cont.getAsRegion();
+ if (!ContReg)
+ return;
+
+ ContReg = ContReg->getMostDerivedObjectRegion();
+
+ // For deque-like containers invalidate all iterator positions
+ auto State = C.getState();
+ if (hasSubscriptOperator(State, ContReg)) {
+ State = invalidateAllIteratorPositions(State, ContReg);
+ C.addTransition(State);
+ } else {
+ const auto CData = getContainerData(State, ContReg);
+ if (!CData)
+ return;
+
+ if (const auto BeginSym = CData->getBegin()) {
+ auto &SymMgr = C.getSymbolManager();
+ auto &BVF = SymMgr.getBasicVals();
+ auto &SVB = C.getSValBuilder();
+ const auto newBeginSym =
+ SVB.evalBinOp(State, BO_Sub,
+ nonloc::SymbolVal(BeginSym),
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
+ SymMgr.getType(BeginSym)).getAsSymbol();
+ State = setContainerData(State, ContReg, CData->newBegin(newBeginSym));
+ C.addTransition(State);
+ }
+ }
+}
+
+void IteratorChecker::handlePopFront(CheckerContext &C,
+ const SVal &Cont) const {
+ const auto *ContReg = Cont.getAsRegion();
+ if (!ContReg)
+ return;
+
+ ContReg = ContReg->getMostDerivedObjectRegion();
+
+ auto State = C.getState();
+ const auto CData = getContainerData(State, ContReg);
+ if (!CData)
+ return;
+
+ // For deque-like containers invalidate all iterator positions. For list-like
+ // iterators only invalidate the first position
+ if (const auto BeginSym = CData->getBegin()) {
+ if (hasSubscriptOperator(State, ContReg)) {
+ State = invalidateIteratorPositions(State, BeginSym, BO_LE);
+ } else {
+ State = invalidateIteratorPositions(State, BeginSym, BO_EQ);
+ }
+ auto &SymMgr = C.getSymbolManager();
+ auto &BVF = SymMgr.getBasicVals();
+ auto &SVB = C.getSValBuilder();
+ const auto newBeginSym =
+ SVB.evalBinOp(State, BO_Add,
+ nonloc::SymbolVal(BeginSym),
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
+ SymMgr.getType(BeginSym)).getAsSymbol();
+ State = setContainerData(State, ContReg, CData->newBegin(newBeginSym));
+ C.addTransition(State);
+ }
+}
+
+void IteratorChecker::handleInsert(CheckerContext &C, const SVal &Iter) const {
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, Iter);
+ if (!Pos)
+ return;
+
+ // For deque-like containers invalidate all iterator positions. For
+ // vector-like containers invalidate iterator positions after the insertion.
+ const auto *Cont = Pos->getContainer();
+ if (hasSubscriptOperator(State, Cont) && backModifiable(State, Cont)) {
+ if (frontModifiable(State, Cont)) {
+ State = invalidateAllIteratorPositions(State, Cont);
+ } else {
+ State = invalidateIteratorPositions(State, Pos->getOffset(), BO_GE);
+ }
+ if (const auto *CData = getContainerData(State, Cont)) {
+ if (const auto EndSym = CData->getEnd()) {
+ State = invalidateIteratorPositions(State, EndSym, BO_GE);
+ State = setContainerData(State, Cont, CData->newEnd(nullptr));
+ }
+ }
+ C.addTransition(State);
+ }
+}
+
+void IteratorChecker::handleErase(CheckerContext &C, const SVal &Iter) const {
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, Iter);
+ if (!Pos)
+ return;
+
+ // For deque-like containers invalidate all iterator positions. For
+ // vector-like containers invalidate iterator positions at and after the
+ // deletion. For list-like containers only invalidate the deleted position.
+ const auto *Cont = Pos->getContainer();
+ if (hasSubscriptOperator(State, Cont) && backModifiable(State, Cont)) {
+ if (frontModifiable(State, Cont)) {
+ State = invalidateAllIteratorPositions(State, Cont);
+ } else {
+ State = invalidateIteratorPositions(State, Pos->getOffset(), BO_GE);
+ }
+ if (const auto *CData = getContainerData(State, Cont)) {
+ if (const auto EndSym = CData->getEnd()) {
+ State = invalidateIteratorPositions(State, EndSym, BO_GE);
+ State = setContainerData(State, Cont, CData->newEnd(nullptr));
+ }
+ }
+ } else {
+ State = invalidateIteratorPositions(State, Pos->getOffset(), BO_EQ);
+ }
+ C.addTransition(State);
+}
+
+void IteratorChecker::handleErase(CheckerContext &C, const SVal &Iter1,
+ const SVal &Iter2) const {
+ auto State = C.getState();
+ const auto *Pos1 = getIteratorPosition(State, Iter1);
+ const auto *Pos2 = getIteratorPosition(State, Iter2);
+ if (!Pos1 || !Pos2)
+ return;
+
+ // For deque-like containers invalidate all iterator positions. For
+ // vector-like containers invalidate iterator positions at and after the
+ // deletion range. For list-like containers only invalidate the deleted
+ // position range [first..last].
+ const auto *Cont = Pos1->getContainer();
+ if (hasSubscriptOperator(State, Cont) && backModifiable(State, Cont)) {
+ if (frontModifiable(State, Cont)) {
+ State = invalidateAllIteratorPositions(State, Cont);
+ } else {
+ State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GE);
+ }
+ if (const auto *CData = getContainerData(State, Cont)) {
+ if (const auto EndSym = CData->getEnd()) {
+ State = invalidateIteratorPositions(State, EndSym, BO_GE);
+ State = setContainerData(State, Cont, CData->newEnd(nullptr));
+ }
+ }
+ } else {
+ State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GE,
+ Pos2->getOffset(), BO_LT);
+ }
+ C.addTransition(State);
+}
+
+void IteratorChecker::handleEraseAfter(CheckerContext &C,
+ const SVal &Iter) const {
+ auto State = C.getState();
+ const auto *Pos = getIteratorPosition(State, Iter);
+ if (!Pos)
+ return;
+
+ // Invalidate the deleted iterator position, which is the position of the
+ // parameter plus one.
+ auto &SymMgr = C.getSymbolManager();
+ auto &BVF = SymMgr.getBasicVals();
+ auto &SVB = C.getSValBuilder();
+ const auto NextSym =
+ SVB.evalBinOp(State, BO_Add,
+ nonloc::SymbolVal(Pos->getOffset()),
+ nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
+ SymMgr.getType(Pos->getOffset())).getAsSymbol();
+ State = invalidateIteratorPositions(State, NextSym, BO_EQ);
+ C.addTransition(State);
+}
+
+void IteratorChecker::handleEraseAfter(CheckerContext &C, const SVal &Iter1,
+ const SVal &Iter2) const {
+ auto State = C.getState();
+ const auto *Pos1 = getIteratorPosition(State, Iter1);
+ const auto *Pos2 = getIteratorPosition(State, Iter2);
+ if (!Pos1 || !Pos2)
+ return;
+
+ // Invalidate the deleted iterator position range (first..last)
+ State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GT,
+ Pos2->getOffset(), BO_LT);
+ C.addTransition(State);
+}
+
+IteratorPosition IteratorChecker::advancePosition(CheckerContext &C,
+ OverloadedOperatorKind Op,
+ const IteratorPosition &Pos,
+ const SVal &Distance) const {
+ auto State = C.getState();
+ auto &SymMgr = C.getSymbolManager();
+ auto &SVB = C.getSValBuilder();
+
+ assert ((Op == OO_Plus || Op == OO_PlusEqual ||
+ Op == OO_Minus || Op == OO_MinusEqual) &&
+ "Advance operator must be one of +, -, += and -=.");
+ auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
+ if (const auto IntDist = Distance.getAs<nonloc::ConcreteInt>()) {
+ // For concrete integers we can calculate the new position
+ return Pos.setTo(SVB.evalBinOp(State, BinOp,
+ nonloc::SymbolVal(Pos.getOffset()), *IntDist,
+ SymMgr.getType(Pos.getOffset()))
+ .getAsSymbol());
+ } else {
+ // For other symbols create a new symbol to keep expressions simple
+ const auto &LCtx = C.getLocationContext();
+ const auto NewPosSym = SymMgr.conjureSymbol(nullptr, LCtx,
+ SymMgr.getType(Pos.getOffset()),
+ C.blockCount());
+ State = assumeNoOverflow(State, NewPosSym, 4);
+ return Pos.setTo(NewPosSym);
+ }
+}
+
void IteratorChecker::reportOutOfRangeBug(const StringRef &Message,
const SVal &Val, CheckerContext &C,
ExplodedNode *ErrNode) const {
@@ -882,14 +1589,47 @@ void IteratorChecker::reportOutOfRangeBug(const StringRef &Message,
C.emitReport(std::move(R));
}
+void IteratorChecker::reportMismatchedBug(const StringRef &Message,
+ const SVal &Val1, const SVal &Val2,
+ CheckerContext &C,
+ ExplodedNode *ErrNode) const {
+ auto R = llvm::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
+ R->markInteresting(Val1);
+ R->markInteresting(Val2);
+ C.emitReport(std::move(R));
+}
+
+void IteratorChecker::reportMismatchedBug(const StringRef &Message,
+ const SVal &Val, const MemRegion *Reg,
+ CheckerContext &C,
+ ExplodedNode *ErrNode) const {
+ auto R = llvm::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
+ R->markInteresting(Val);
+ R->markInteresting(Reg);
+ C.emitReport(std::move(R));
+}
+
+void IteratorChecker::reportInvalidatedBug(const StringRef &Message,
+ const SVal &Val, CheckerContext &C,
+ ExplodedNode *ErrNode) const {
+ auto R = llvm::make_unique<BugReport>(*InvalidatedBugType, Message, ErrNode);
+ R->markInteresting(Val);
+ C.emitReport(std::move(R));
+}
+
namespace {
bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
-bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
+bool isGreater(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
+bool isEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
BinaryOperator::Opcode Opc);
bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
BinaryOperator::Opcode Opc);
+const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,
+ const MemRegion *Reg);
+SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB, SymbolRef Expr,
+ SymbolRef OldSym, SymbolRef NewSym);
bool isIteratorType(const QualType &Type) {
if (Type->isPointerType())
@@ -943,6 +1683,11 @@ bool isIterator(const CXXRecordDecl *CRD) {
HasPostIncrOp && HasDerefOp;
}
+bool isComparisonOperator(OverloadedOperatorKind OK) {
+ return OK == OO_EqualEqual || OK == OO_ExclaimEqual || OK == OO_Less ||
+ OK == OO_LessEqual || OK == OO_Greater || OK == OO_GreaterEqual;
+}
+
bool isBeginCall(const FunctionDecl *Func) {
const auto *IdInfo = Func->getIdentifier();
if (!IdInfo)
@@ -957,10 +1702,139 @@ bool isEndCall(const FunctionDecl *Func) {
return IdInfo->getName().endswith_lower("end");
}
+bool isAssignCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() > 2)
+ return false;
+ return IdInfo->getName() == "assign";
+}
+
+bool isClearCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() > 0)
+ return false;
+ return IdInfo->getName() == "clear";
+}
+
+bool isPushBackCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() != 1)
+ return false;
+ return IdInfo->getName() == "push_back";
+}
+
+bool isEmplaceBackCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() < 1)
+ return false;
+ return IdInfo->getName() == "emplace_back";
+}
+
+bool isPopBackCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() > 0)
+ return false;
+ return IdInfo->getName() == "pop_back";
+}
+
+bool isPushFrontCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() != 1)
+ return false;
+ return IdInfo->getName() == "push_front";
+}
+
+bool isEmplaceFrontCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() < 1)
+ return false;
+ return IdInfo->getName() == "emplace_front";
+}
+
+bool isPopFrontCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() > 0)
+ return false;
+ return IdInfo->getName() == "pop_front";
+}
+
+bool isInsertCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() < 2 || Func->getNumParams() > 3)
+ return false;
+ if (!isIteratorType(Func->getParamDecl(0)->getType()))
+ return false;
+ return IdInfo->getName() == "insert";
+}
+
+bool isEmplaceCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() < 2)
+ return false;
+ if (!isIteratorType(Func->getParamDecl(0)->getType()))
+ return false;
+ return IdInfo->getName() == "emplace";
+}
+
+bool isEraseCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() < 1 || Func->getNumParams() > 2)
+ return false;
+ if (!isIteratorType(Func->getParamDecl(0)->getType()))
+ return false;
+ if (Func->getNumParams() == 2 &&
+ !isIteratorType(Func->getParamDecl(1)->getType()))
+ return false;
+ return IdInfo->getName() == "erase";
+}
+
+bool isEraseAfterCall(const FunctionDecl *Func) {
+ const auto *IdInfo = Func->getIdentifier();
+ if (!IdInfo)
+ return false;
+ if (Func->getNumParams() < 1 || Func->getNumParams() > 2)
+ return false;
+ if (!isIteratorType(Func->getParamDecl(0)->getType()))
+ return false;
+ if (Func->getNumParams() == 2 &&
+ !isIteratorType(Func->getParamDecl(1)->getType()))
+ return false;
+ return IdInfo->getName() == "erase_after";
+}
+
+bool isAssignmentOperator(OverloadedOperatorKind OK) { return OK == OO_Equal; }
+
bool isSimpleComparisonOperator(OverloadedOperatorKind OK) {
return OK == OO_EqualEqual || OK == OO_ExclaimEqual;
}
+bool isAccessOperator(OverloadedOperatorKind OK) {
+ return isDereferenceOperator(OK) || isIncrementOperator(OK) ||
+ isDecrementOperator(OK) || isRandomIncrOrDecrOperator(OK);
+}
+
bool isDereferenceOperator(OverloadedOperatorKind OK) {
return OK == OO_Star || OK == OO_Arrow || OK == OO_ArrowStar ||
OK == OO_Subscript;
@@ -996,6 +1870,66 @@ BinaryOperator::Opcode getOpcode(const SymExpr *SE) {
return BO_Comma; // Extremal value, neither EQ nor NE
}
+bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg) {
+ const auto *CRD = getCXXRecordDecl(State, Reg);
+ if (!CRD)
+ return false;
+
+ for (const auto *Method : CRD->methods()) {
+ if (!Method->isOverloadedOperator())
+ continue;
+ const auto OPK = Method->getOverloadedOperator();
+ if (OPK == OO_Subscript) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool frontModifiable(ProgramStateRef State, const MemRegion *Reg) {
+ const auto *CRD = getCXXRecordDecl(State, Reg);
+ if (!CRD)
+ return false;
+
+ for (const auto *Method : CRD->methods()) {
+ if (!Method->getDeclName().isIdentifier())
+ continue;
+ if (Method->getName() == "push_front" || Method->getName() == "pop_front") {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool backModifiable(ProgramStateRef State, const MemRegion *Reg) {
+ const auto *CRD = getCXXRecordDecl(State, Reg);
+ if (!CRD)
+ return false;
+
+ for (const auto *Method : CRD->methods()) {
+ if (!Method->getDeclName().isIdentifier())
+ continue;
+ if (Method->getName() == "push_back" || Method->getName() == "pop_back") {
+ return true;
+ }
+ }
+ return false;
+}
+
+const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,
+ const MemRegion *Reg) {
+ auto TI = getDynamicTypeInfo(State, Reg);
+ if (!TI.isValid())
+ return nullptr;
+
+ auto Type = TI.getType();
+ if (const auto *RefT = Type->getAs<ReferenceType>()) {
+ Type = RefT->getPointeeType();
+ }
+
+ return Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl();
+}
+
const RegionOrSymbol getRegionOrSymbol(const SVal &Val) {
if (const auto Reg = Val.getAsRegion()) {
return Reg;
@@ -1097,7 +2031,8 @@ ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
const IteratorPosition *getIteratorPosition(ProgramStateRef State,
const SVal &Val) {
- if (const auto Reg = Val.getAsRegion()) {
+ if (auto Reg = Val.getAsRegion()) {
+ Reg = Reg->getMostDerivedObjectRegion();
return State->get<IteratorRegionMap>(Reg);
} else if (const auto Sym = Val.getAsSymbol()) {
return State->get<IteratorSymbolMap>(Sym);
@@ -1110,7 +2045,8 @@ const IteratorPosition *getIteratorPosition(ProgramStateRef State,
const IteratorPosition *getIteratorPosition(ProgramStateRef State,
RegionOrSymbol RegOrSym) {
if (RegOrSym.is<const MemRegion *>()) {
- return State->get<IteratorRegionMap>(RegOrSym.get<const MemRegion *>());
+ auto Reg = RegOrSym.get<const MemRegion *>()->getMostDerivedObjectRegion();
+ return State->get<IteratorRegionMap>(Reg);
} else if (RegOrSym.is<SymbolRef>()) {
return State->get<IteratorSymbolMap>(RegOrSym.get<SymbolRef>());
}
@@ -1119,7 +2055,8 @@ const IteratorPosition *getIteratorPosition(ProgramStateRef State,
ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
const IteratorPosition &Pos) {
- if (const auto Reg = Val.getAsRegion()) {
+ if (auto Reg = Val.getAsRegion()) {
+ Reg = Reg->getMostDerivedObjectRegion();
return State->set<IteratorRegionMap>(Reg, Pos);
} else if (const auto Sym = Val.getAsSymbol()) {
return State->set<IteratorSymbolMap>(Sym, Pos);
@@ -1133,8 +2070,8 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State,
RegionOrSymbol RegOrSym,
const IteratorPosition &Pos) {
if (RegOrSym.is<const MemRegion *>()) {
- return State->set<IteratorRegionMap>(RegOrSym.get<const MemRegion *>(),
- Pos);
+ auto Reg = RegOrSym.get<const MemRegion *>()->getMostDerivedObjectRegion();
+ return State->set<IteratorRegionMap>(Reg, Pos);
} else if (RegOrSym.is<SymbolRef>()) {
return State->set<IteratorSymbolMap>(RegOrSym.get<SymbolRef>(), Pos);
}
@@ -1142,7 +2079,8 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State,
}
ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val) {
- if (const auto Reg = Val.getAsRegion()) {
+ if (auto Reg = Val.getAsRegion()) {
+ Reg = Reg->getMostDerivedObjectRegion();
return State->remove<IteratorRegionMap>(Reg);
} else if (const auto Sym = Val.getAsSymbol()) {
return State->remove<IteratorSymbolMap>(Sym);
@@ -1211,6 +2149,164 @@ bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) {
return false;
}
+bool isBoundThroughLazyCompoundVal(const Environment &Env,
+ const MemRegion *Reg) {
+ for (const auto Binding: Env) {
+ if (const auto LCVal = Binding.second.getAs<nonloc::LazyCompoundVal>()) {
+ if (LCVal->getRegion() == Reg)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+template <typename Condition, typename Process>
+ProgramStateRef processIteratorPositions(ProgramStateRef State, Condition Cond,
+ Process Proc) {
+ auto &RegionMapFactory = State->get_context<IteratorRegionMap>();
+ auto RegionMap = State->get<IteratorRegionMap>();
+ bool Changed = false;
+ for (const auto Reg : RegionMap) {
+ if (Cond(Reg.second)) {
+ RegionMap = RegionMapFactory.add(RegionMap, Reg.first, Proc(Reg.second));
+ Changed = true;
+ }
+ }
+
+ if (Changed)
+ State = State->set<IteratorRegionMap>(RegionMap);
+
+ auto &SymbolMapFactory = State->get_context<IteratorSymbolMap>();
+ auto SymbolMap = State->get<IteratorSymbolMap>();
+ Changed = false;
+ for (const auto Sym : SymbolMap) {
+ if (Cond(Sym.second)) {
+ SymbolMap = SymbolMapFactory.add(SymbolMap, Sym.first, Proc(Sym.second));
+ Changed = true;
+ }
+ }
+
+ if (Changed)
+ State = State->set<IteratorSymbolMap>(SymbolMap);
+
+ return State;
+}
+
+ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
+ const MemRegion *Cont) {
+ auto MatchCont = [&](const IteratorPosition &Pos) {
+ return Pos.getContainer() == Cont;
+ };
+ auto Invalidate = [&](const IteratorPosition &Pos) {
+ return Pos.invalidate();
+ };
+ return processIteratorPositions(State, MatchCont, Invalidate);
+}
+
+ProgramStateRef
+invalidateAllIteratorPositionsExcept(ProgramStateRef State,
+ const MemRegion *Cont, SymbolRef Offset,
+ BinaryOperator::Opcode Opc) {
+ auto MatchContAndCompare = [&](const IteratorPosition &Pos) {
+ return Pos.getContainer() == Cont &&
+ !compare(State, Pos.getOffset(), Offset, Opc);
+ };
+ auto Invalidate = [&](const IteratorPosition &Pos) {
+ return Pos.invalidate();
+ };
+ return processIteratorPositions(State, MatchContAndCompare, Invalidate);
+}
+
+ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
+ SymbolRef Offset,
+ BinaryOperator::Opcode Opc) {
+ auto Compare = [&](const IteratorPosition &Pos) {
+ return compare(State, Pos.getOffset(), Offset, Opc);
+ };
+ auto Invalidate = [&](const IteratorPosition &Pos) {
+ return Pos.invalidate();
+ };
+ return processIteratorPositions(State, Compare, Invalidate);
+}
+
+ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
+ SymbolRef Offset1,
+ BinaryOperator::Opcode Opc1,
+ SymbolRef Offset2,
+ BinaryOperator::Opcode Opc2) {
+ auto Compare = [&](const IteratorPosition &Pos) {
+ return compare(State, Pos.getOffset(), Offset1, Opc1) &&
+ compare(State, Pos.getOffset(), Offset2, Opc2);
+ };
+ auto Invalidate = [&](const IteratorPosition &Pos) {
+ return Pos.invalidate();
+ };
+ return processIteratorPositions(State, Compare, Invalidate);
+}
+
+ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
+ const MemRegion *Cont,
+ const MemRegion *NewCont) {
+ auto MatchCont = [&](const IteratorPosition &Pos) {
+ return Pos.getContainer() == Cont;
+ };
+ auto ReAssign = [&](const IteratorPosition &Pos) {
+ return Pos.reAssign(NewCont);
+ };
+ return processIteratorPositions(State, MatchCont, ReAssign);
+}
+
+ProgramStateRef reassignAllIteratorPositionsUnless(ProgramStateRef State,
+ const MemRegion *Cont,
+ const MemRegion *NewCont,
+ SymbolRef Offset,
+ BinaryOperator::Opcode Opc) {
+ auto MatchContAndCompare = [&](const IteratorPosition &Pos) {
+ return Pos.getContainer() == Cont &&
+ !compare(State, Pos.getOffset(), Offset, Opc);
+ };
+ auto ReAssign = [&](const IteratorPosition &Pos) {
+ return Pos.reAssign(NewCont);
+ };
+ return processIteratorPositions(State, MatchContAndCompare, ReAssign);
+}
+
+// This function rebases symbolic expression `OldSym + Int` to `NewSym + Int`,
+// `OldSym - Int` to `NewSym - Int` and `OldSym` to `NewSym` in any iterator
+// position offsets where `CondSym` is true.
+ProgramStateRef rebaseSymbolInIteratorPositionsIf(
+ ProgramStateRef State, SValBuilder &SVB, SymbolRef OldSym,
+ SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc) {
+ auto LessThanEnd = [&](const IteratorPosition &Pos) {
+ return compare(State, Pos.getOffset(), CondSym, Opc);
+ };
+ auto RebaseSymbol = [&](const IteratorPosition &Pos) {
+ return Pos.setTo(rebaseSymbol(State, SVB, Pos.getOffset(), OldSym,
+ NewSym));
+ };
+ return processIteratorPositions(State, LessThanEnd, RebaseSymbol);
+}
+
+// This function rebases symbolic expression `OldExpr + Int` to `NewExpr + Int`,
+// `OldExpr - Int` to `NewExpr - Int` and `OldExpr` to `NewExpr` in expression
+// `OrigExpr`.
+SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB,
+ SymbolRef OrigExpr, SymbolRef OldExpr,
+ SymbolRef NewSym) {
+ auto &SymMgr = SVB.getSymbolManager();
+ auto Diff = SVB.evalBinOpNN(State, BO_Sub, nonloc::SymbolVal(OrigExpr),
+ nonloc::SymbolVal(OldExpr),
+ SymMgr.getType(OrigExpr));
+
+ const auto DiffInt = Diff.getAs<nonloc::ConcreteInt>();
+ if (!DiffInt)
+ return OrigExpr;
+
+ return SVB.evalBinOpNN(State, BO_Add, *DiffInt, nonloc::SymbolVal(NewSym),
+ SymMgr.getType(OrigExpr)).getAsSymbol();
+}
+
bool isZero(ProgramStateRef State, const NonLoc &Val) {
auto &BVF = State->getBasicVals();
return compare(State, Val,
@@ -1218,14 +2314,27 @@ bool isZero(ProgramStateRef State, const NonLoc &Val) {
BO_EQ);
}
-bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) {
+bool isPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos) {
const auto *Cont = Pos.getContainer();
const auto *CData = getContainerData(State, Cont);
if (!CData)
return false;
- // Out of range means less than the begin symbol or greater or equal to the
- // end symbol.
+ const auto End = CData->getEnd();
+ if (End) {
+ if (isEqual(State, Pos.getOffset(), End)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool isAheadOfRange(ProgramStateRef State, const IteratorPosition &Pos) {
+ const auto *Cont = Pos.getContainer();
+ const auto *CData = getContainerData(State, Cont);
+ if (!CData)
+ return false;
const auto Beg = CData->getBegin();
if (Beg) {
@@ -1234,9 +2343,18 @@ bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) {
}
}
+ return false;
+}
+
+bool isBehindPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos) {
+ const auto *Cont = Pos.getContainer();
+ const auto *CData = getContainerData(State, Cont);
+ if (!CData)
+ return false;
+
const auto End = CData->getEnd();
if (End) {
- if (isGreaterOrEqual(State, Pos.getOffset(), End)) {
+ if (isGreater(State, Pos.getOffset(), End)) {
return true;
}
}
@@ -1248,8 +2366,12 @@ bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
return compare(State, Sym1, Sym2, BO_LT);
}
-bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
- return compare(State, Sym1, Sym2, BO_GE);
+bool isGreater(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
+ return compare(State, Sym1, Sym2, BO_GT);
+}
+
+bool isEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
+ return compare(State, Sym1, Sym2, BO_EQ);
}
bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
@@ -1257,6 +2379,7 @@ bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
return compare(State, nonloc::SymbolVal(Sym1), nonloc::SymbolVal(Sym2), Opc);
}
+
bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
BinaryOperator::Opcode Opc) {
auto &SVB = State->getStateManager().getSValBuilder();
@@ -1281,4 +2404,5 @@ bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
}
REGISTER_CHECKER(IteratorRangeChecker)
-
+REGISTER_CHECKER(MismatchedIteratorChecker)
+REGISTER_CHECKER(InvalidatedIteratorChecker)
diff --git a/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp b/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
index 2fb627184eb9..aade62fd7491 100644
--- a/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
@@ -28,7 +28,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtVisitor.h"
diff --git a/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
index db4fbca36deb..df238f2b2e45 100644
--- a/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -32,8 +32,7 @@ static bool IsLLVMStringRef(QualType T) {
if (!RT)
return false;
- return StringRef(QualType(RT, 0).getAsString()) ==
- "class StringRef";
+ return StringRef(QualType(RT, 0).getAsString()) == "class StringRef";
}
/// Check whether the declaration is semantically inside the top-level
diff --git a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
index 849b1193c042..eda39efeca17 100644
--- a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@@ -125,7 +125,6 @@ public:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -1003,7 +1002,6 @@ void NonLocalizedStringChecker::checkPostStmt(const ObjCStringLiteral *SL,
std::shared_ptr<PathDiagnosticPiece>
NonLocalizedStringBRVisitor::VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC, BugReport &BR) {
if (Satisfied)
return nullptr;
@@ -1400,7 +1398,8 @@ void ento::registerNonLocalizedStringChecker(CheckerManager &mgr) {
NonLocalizedStringChecker *checker =
mgr.registerChecker<NonLocalizedStringChecker>();
checker->IsAggressive =
- mgr.getAnalyzerOptions().getBooleanOption("AggressiveReport", false);
+ mgr.getAnalyzerOptions().getCheckerBooleanOption("AggressiveReport",
+ false, checker);
}
void ento::registerEmptyLocalizationContextChecker(CheckerManager &mgr) {
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
index e9ec7a0c4365..fb9bccebe465 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
@@ -87,7 +87,6 @@ void MPIBugReporter::reportUnmatchedWait(
std::shared_ptr<PathDiagnosticPiece>
MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) {
@@ -96,13 +95,13 @@ MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
const Request *const Req = N->getState()->get<RequestMap>(RequestRegion);
const Request *const PrevReq =
- PrevN->getState()->get<RequestMap>(RequestRegion);
+ N->getFirstPred()->getState()->get<RequestMap>(RequestRegion);
// Check if request was previously unused or in a different state.
if ((Req && !PrevReq) || (Req->CurrentState != PrevReq->CurrentState)) {
IsNodeFound = true;
- ProgramPoint P = PrevN->getLocation();
+ ProgramPoint P = N->getFirstPred()->getLocation();
PathDiagnosticLocation L =
PathDiagnosticLocation::create(P, BRC.getSourceManager());
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
index 40eb0631d7c5..32fcb07e3371 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
@@ -91,7 +91,6 @@ private:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
index 696cf39473d5..28c6898f7947 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -16,7 +16,7 @@
//===----------------------------------------------------------------------===//
#include "MPIChecker.h"
-#include "../ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
namespace clang {
namespace ento {
@@ -100,9 +100,6 @@ void MPIChecker::checkUnmatchedWaits(const CallEvent &PreCallEvent,
void MPIChecker::checkMissingWaits(SymbolReaper &SymReaper,
CheckerContext &Ctx) const {
- if (!SymReaper.hasDeadSymbols())
- return;
-
ProgramStateRef State = Ctx.getState();
const auto &Requests = State->get<RequestMap>();
if (Requests.isEmpty())
diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index b8ef6701c0df..06e27fc5718d 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -12,10 +12,11 @@
// to be freed using a call to SecKeychainItemFreeContent.
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
@@ -29,6 +30,7 @@ namespace {
class MacOSKeychainAPIChecker : public Checker<check::PreStmt<CallExpr>,
check::PostStmt<CallExpr>,
check::DeadSymbols,
+ check::PointerEscape,
eval::Assume> {
mutable std::unique_ptr<BugType> BT;
@@ -58,6 +60,10 @@ public:
void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
void checkPostStmt(const CallExpr *S, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+ ProgramStateRef checkPointerEscape(ProgramStateRef State,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call,
+ PointerEscapeKind Kind) const;
ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
bool Assumption) const;
void printState(raw_ostream &Out, ProgramStateRef State,
@@ -135,7 +141,6 @@ private:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -571,14 +576,52 @@ void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
C.addTransition(State, N);
}
+ProgramStateRef MacOSKeychainAPIChecker::checkPointerEscape(
+ ProgramStateRef State, const InvalidatedSymbols &Escaped,
+ const CallEvent *Call, PointerEscapeKind Kind) const {
+ // FIXME: This branch doesn't make any sense at all, but it is an overfitted
+ // replacement for a previous overfitted code that was making even less sense.
+ if (!Call || Call->getDecl())
+ return State;
+
+ for (auto I : State->get<AllocatedData>()) {
+ SymbolRef Sym = I.first;
+ if (Escaped.count(Sym))
+ State = State->remove<AllocatedData>(Sym);
+
+ // This checker is special. Most checkers in fact only track symbols of
+ // SymbolConjured type, eg. symbols returned from functions such as
+ // malloc(). This checker tracks symbols returned as out-parameters.
+ //
+ // When a function is evaluated conservatively, the out-parameter's pointee
+ // base region gets invalidated with a SymbolConjured. If the base region is
+ // larger than the region we're interested in, the value we're interested in
+ // would be SymbolDerived based on that SymbolConjured. However, such
+ // SymbolDerived will never be listed in the Escaped set when the base
+ // region is invalidated because ExprEngine doesn't know which symbols
+ // were derived from a given symbol, while there can be infinitely many
+ // valid symbols derived from any given symbol.
+ //
+ // Hence the extra boilerplate: remove the derived symbol when its parent
+ // symbol escapes.
+ //
+ if (const auto *SD = dyn_cast<SymbolDerived>(Sym)) {
+ SymbolRef ParentSym = SD->getParentSymbol();
+ if (Escaped.count(ParentSym))
+ State = State->remove<AllocatedData>(Sym);
+ }
+ }
+ return State;
+}
+
std::shared_ptr<PathDiagnosticPiece>
MacOSKeychainAPIChecker::SecKeychainBugVisitor::VisitNode(
- const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
- BugReport &BR) {
+ const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
const AllocationState *AS = N->getState()->get<AllocatedData>(Sym);
if (!AS)
return nullptr;
- const AllocationState *ASPrev = PrevN->getState()->get<AllocatedData>(Sym);
+ const AllocationState *ASPrev =
+ N->getFirstPred()->getState()->get<AllocatedData>(Sym);
if (ASPrev)
return nullptr;
diff --git a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index 437378e53daa..f5976d7da4c1 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -83,7 +83,7 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
// that dispatch_once is a macro that wraps a call to _dispatch_once.
// _dispatch_once is then a function which then calls the real dispatch_once.
// Users do not care; they just want the warning at the top-level call.
- if (CE->getLocStart().isMacroID()) {
+ if (CE->getBeginLoc().isMacroID()) {
StringRef TrimmedFName = FName.ltrim('_');
if (TrimmedFName != FName)
FName = TrimmedFName;
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index ebaf79a780c0..ae1b1fc837be 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "InterCheckerAPI.h"
#include "clang/AST/Attr.h"
#include "clang/AST/ParentMap.h"
@@ -161,6 +161,7 @@ class MallocChecker : public Checker<check::DeadSymbols,
check::PointerEscape,
check::ConstPointerEscape,
check::PreStmt<ReturnStmt>,
+ check::EndFunction,
check::PreCall,
check::PostStmt<CallExpr>,
check::PostStmt<CXXNewExpr>,
@@ -193,6 +194,7 @@ public:
CK_NewDeleteChecker,
CK_NewDeleteLeaksChecker,
CK_MismatchedDeallocatorChecker,
+ CK_InnerPointerChecker,
CK_NumCheckKinds
};
@@ -217,6 +219,7 @@ public:
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const;
ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
bool Assumption) const;
void checkLocation(SVal l, bool isLoad, const Stmt *S,
@@ -353,7 +356,7 @@ private:
static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
ProgramStateRef State);
- ///Check if the memory associated with this symbol was released.
+ /// Check if the memory associated with this symbol was released.
bool isReleased(SymbolRef Sym, CheckerContext &C) const;
bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
@@ -377,13 +380,16 @@ private:
ProgramStateRef State,
SymbolRef &EscapingSymbol) const;
- // Implementation of the checkPointerEscape callabcks.
+ // Implementation of the checkPointerEscape callbacks.
ProgramStateRef checkPointerEscapeAux(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
bool(*CheckRefState)(const RefState*)) const;
+ // Implementation of the checkPreStmt and checkEndFunction callbacks.
+ void checkEscapeOnReturn(const ReturnStmt *S, CheckerContext &C) const;
+
///@{
/// Tells if a given family/call/symbol is tracked by the current checker.
/// Sets CheckKind to the kind of the checker responsible for this
@@ -511,7 +517,6 @@ private:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -707,10 +712,8 @@ bool MallocChecker::isCMemFunction(const FunctionDecl *FD,
return false;
}
-// Tells if the callee is one of the following:
-// 1) A global non-placement new/delete operator function.
-// 2) A global placement operator function with the single placement argument
-// of type std::nothrow_t.
+// Tells if the callee is one of the builtin new/delete operators, including
+// placement operators and other standard overloads.
bool MallocChecker::isStandardNewDelete(const FunctionDecl *FD,
ASTContext &C) const {
if (!FD)
@@ -721,23 +724,11 @@ bool MallocChecker::isStandardNewDelete(const FunctionDecl *FD,
Kind != OO_Delete && Kind != OO_Array_Delete)
return false;
- // Skip all operator new/delete methods.
- if (isa<CXXMethodDecl>(FD))
- return false;
-
- // Return true if tested operator is a standard placement nothrow operator.
- if (FD->getNumParams() == 2) {
- QualType T = FD->getParamDecl(1)->getType();
- if (const IdentifierInfo *II = T.getBaseTypeIdentifier())
- return II->getName().equals("nothrow_t");
- }
-
- // Skip placement operators.
- if (FD->getNumParams() != 1 || FD->isVariadic())
- return false;
-
- // One of the standard new/new[]/delete/delete[] non-placement operators.
- return true;
+ // This is standard if and only if it's not defined in a user file.
+ SourceLocation L = FD->getLocation();
+ // If the header for operator delete is not included, it's still defined
+ // in an invalid source location. Check to make sure we don't crash.
+ return !L.isValid() || C.getSourceManager().isInSystemHeader(L);
}
llvm::Optional<ProgramStateRef> MallocChecker::performKernelMalloc(
@@ -1082,12 +1073,6 @@ static bool treatUnusedNewEscaped(const CXXNewExpr *NE) {
void MallocChecker::processNewAllocation(const CXXNewExpr *NE,
CheckerContext &C,
SVal Target) const {
- if (NE->getNumPlacementArgs())
- for (CXXNewExpr::const_arg_iterator I = NE->placement_arg_begin(),
- E = NE->placement_arg_end(); I != E; ++I)
- if (SymbolRef Sym = C.getSVal(*I).getAsSymbol())
- checkUseAfterFree(Sym, C, *I);
-
if (!isStandardNewDelete(NE->getOperatorNew(), C.getASTContext()))
return;
@@ -1098,7 +1083,7 @@ void MallocChecker::processNewAllocation(const CXXNewExpr *NE,
ProgramStateRef State = C.getState();
// The return value from operator new is bound to a specified initialization
// value (if any) and we don't want to loose this value. So we call
- // MallocUpdateRefState() instead of MallocMemAux() which breakes the
+ // MallocUpdateRefState() instead of MallocMemAux() which breaks the
// existing binding.
State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
: AF_CXXNew, Target);
@@ -1109,7 +1094,7 @@ void MallocChecker::processNewAllocation(const CXXNewExpr *NE,
void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
CheckerContext &C) const {
- if (!C.getAnalysisManager().getAnalyzerOptions().mayInlineCXXAllocator())
+ if (!C.getAnalysisManager().getAnalyzerOptions().MayInlineCXXAllocator)
processNewAllocation(NE, C, C.getSVal(NE));
}
@@ -1657,13 +1642,10 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family,
case AF_IfNameIndex: {
if (ChecksEnabled[CK_MallocChecker])
return CK_MallocChecker;
-
- return Optional<MallocChecker::CheckKind>();
+ return None;
}
case AF_CXXNew:
- case AF_CXXNewArray:
- // FIXME: Add new CheckKind for AF_InnerBuffer.
- case AF_InnerBuffer: {
+ case AF_CXXNewArray: {
if (IsALeakCheck) {
if (ChecksEnabled[CK_NewDeleteLeaksChecker])
return CK_NewDeleteLeaksChecker;
@@ -1672,7 +1654,12 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family,
if (ChecksEnabled[CK_NewDeleteChecker])
return CK_NewDeleteChecker;
}
- return Optional<MallocChecker::CheckKind>();
+ return None;
+ }
+ case AF_InnerBuffer: {
+ if (ChecksEnabled[CK_InnerPointerChecker])
+ return CK_InnerPointerChecker;
+ return None;
}
case AF_None: {
llvm_unreachable("no family");
@@ -1975,7 +1962,8 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const {
if (!ChecksEnabled[CK_MallocChecker] &&
- !ChecksEnabled[CK_NewDeleteChecker])
+ !ChecksEnabled[CK_NewDeleteChecker] &&
+ !ChecksEnabled[CK_InnerPointerChecker])
return;
Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
@@ -1987,15 +1975,20 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
BT_UseFree[*CheckKind].reset(new BugType(
CheckNames[*CheckKind], "Use-after-free", categories::MemoryError));
+ AllocationFamily AF =
+ C.getState()->get<RegionState>(Sym)->getAllocationFamily();
+
auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
- "Use of memory after it is freed", N);
+ AF == AF_InnerBuffer
+ ? "Inner pointer of container used after re/deallocation"
+ : "Use of memory after it is freed",
+ N);
R->markInteresting(Sym);
R->addRange(Range);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
- const RefState *RS = C.getState()->get<RegionState>(Sym);
- if (RS->getAllocationFamily() == AF_InnerBuffer)
+ if (AF == AF_InnerBuffer)
R->addVisitor(allocation_state::getInnerPointerBRVisitor(Sym));
C.emitReport(std::move(R));
@@ -2352,13 +2345,11 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
CheckerContext &C) const
{
- if (!SymReaper.hasDeadSymbols())
- return;
-
ProgramStateRef state = C.getState();
- RegionStateTy RS = state->get<RegionState>();
+ RegionStateTy OldRS = state->get<RegionState>();
RegionStateTy::Factory &F = state->get_context<RegionState>();
+ RegionStateTy RS = OldRS;
SmallVector<SymbolRef, 2> Errors;
for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
if (SymReaper.isDead(I->first)) {
@@ -2366,10 +2357,18 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
Errors.push_back(I->first);
// Remove the dead symbol from the map.
RS = F.remove(RS, I->first);
-
}
}
+ if (RS == OldRS) {
+ // We shouldn't have touched other maps yet.
+ assert(state->get<ReallocPairs>() ==
+ C.getState()->get<ReallocPairs>());
+ assert(state->get<FreeReturnValue>() ==
+ C.getState()->get<FreeReturnValue>());
+ return;
+ }
+
// Cleanup the Realloc Pairs Map.
ReallocPairsTy RP = state->get<ReallocPairs>();
for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
@@ -2425,10 +2424,6 @@ void MallocChecker::checkPreCall(const CallEvent &Call,
isCMemFunction(FD, Ctx, AF_IfNameIndex,
MemoryOperationKind::MOK_Free)))
return;
-
- if (ChecksEnabled[CK_NewDeleteChecker] &&
- isStandardNewDelete(FD, Ctx))
- return;
}
// Check if the callee of a method is deleted.
@@ -2451,7 +2446,24 @@ void MallocChecker::checkPreCall(const CallEvent &Call,
}
}
-void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
+void MallocChecker::checkPreStmt(const ReturnStmt *S,
+ CheckerContext &C) const {
+ checkEscapeOnReturn(S, C);
+}
+
+// In the CFG, automatic destructors come after the return statement.
+// This callback checks for returning memory that is freed by automatic
+// destructors, as those cannot be reached in checkPreStmt().
+void MallocChecker::checkEndFunction(const ReturnStmt *S,
+ CheckerContext &C) const {
+ checkEscapeOnReturn(S, C);
+}
+
+void MallocChecker::checkEscapeOnReturn(const ReturnStmt *S,
+ CheckerContext &C) const {
+ if (!S)
+ return;
+
const Expr *E = S->getRetValue();
if (!E)
return;
@@ -2509,8 +2521,7 @@ void MallocChecker::checkPostStmt(const BlockExpr *BE,
}
state =
- state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
- Regions.data() + Regions.size()).getState();
+ state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
C.addTransition(state);
}
@@ -2858,11 +2869,10 @@ static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD) {
}
std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
- const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
- BugReport &BR) {
+ const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
ProgramStateRef state = N->getState();
- ProgramStateRef statePrev = PrevN->getState();
+ ProgramStateRef statePrev = N->getFirstPred()->getState();
const RefState *RS = state->get<RegionState>(Sym);
const RefState *RSPrev = statePrev->get<RegionState>(Sym);
@@ -2918,13 +2928,22 @@ std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
case AF_CXXNewArray:
case AF_IfNameIndex:
Msg = "Memory is released";
+ StackHint = new StackHintGeneratorForSymbol(Sym,
+ "Returning; memory was released");
break;
case AF_InnerBuffer: {
- OS << "Inner pointer invalidated by call to ";
+ const MemRegion *ObjRegion =
+ allocation_state::getContainerObjRegion(statePrev, Sym);
+ const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
+ QualType ObjTy = TypedRegion->getValueType();
+ OS << "Inner buffer of '" << ObjTy.getAsString() << "' ";
+
if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) {
- OS << "destructor";
+ OS << "deallocated by call to destructor";
+ StackHint = new StackHintGeneratorForSymbol(Sym,
+ "Returning; inner buffer was deallocated");
} else {
- OS << "'";
+ OS << "reallocated by call to '";
const Stmt *S = RS->getStmt();
if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
OS << MemCallE->getMethodDecl()->getNameAsString();
@@ -2937,6 +2956,8 @@ std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
OS << (D ? D->getNameAsString() : "unknown");
}
OS << "'";
+ StackHint = new StackHintGeneratorForSymbol(Sym,
+ "Returning; inner buffer was reallocated");
}
Msg = OS.str();
break;
@@ -2944,8 +2965,6 @@ std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
case AF_None:
llvm_unreachable("Unhandled allocation family!");
}
- StackHint = new StackHintGeneratorForSymbol(Sym,
- "Returning; memory was released");
// See if we're releasing memory while inlining a destructor
// (or one of its callees). This turns on various common
@@ -3071,7 +3090,7 @@ markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) {
void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
registerCStringCheckerBasic(mgr);
MallocChecker *checker = mgr.registerChecker<MallocChecker>();
- checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption(
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption(
"Optimistic", false, checker);
checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] = true;
checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
@@ -3087,11 +3106,23 @@ void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
}
}
+// Intended to be used in InnerPointerChecker to register the part of
+// MallocChecker connected to it.
+void ento::registerInnerPointerCheckerAux(CheckerManager &mgr) {
+ registerCStringCheckerBasic(mgr);
+ MallocChecker *checker = mgr.registerChecker<MallocChecker>();
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption(
+ "Optimistic", false, checker);
+ checker->ChecksEnabled[MallocChecker::CK_InnerPointerChecker] = true;
+ checker->CheckNames[MallocChecker::CK_InnerPointerChecker] =
+ mgr.getCurrentCheckName();
+}
+
#define REGISTER_CHECKER(name) \
void ento::register##name(CheckerManager &mgr) { \
registerCStringCheckerBasic(mgr); \
MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \
- checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption( \
"Optimistic", false, checker); \
checker->ChecksEnabled[MallocChecker::CK_##name] = true; \
checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
diff --git a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
index fc2ab1d6e3f7..d02ed48bceaa 100644
--- a/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
@@ -18,7 +18,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -135,9 +135,9 @@ private:
bool isIntZeroExpr(const Expr *E) const {
if (!E->getType()->isIntegralOrEnumerationType())
return false;
- llvm::APSInt Result;
+ Expr::EvalResult Result;
if (E->EvaluateAsInt(Result, Context))
- return Result == 0;
+ return Result.Val.getInt() == 0;
return false;
}
@@ -191,8 +191,11 @@ private:
if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(rhse)) {
if (BOp->getOpcode() == BO_Div) {
const Expr *denom = BOp->getRHS()->IgnoreParenImpCasts();
- if (denom->EvaluateAsInt(denomVal, Context))
+ Expr::EvalResult Result;
+ if (denom->EvaluateAsInt(Result, Context)) {
+ denomVal = Result.Val.getInt();
denomKnown = true;
+ }
const Expr *numerator = BOp->getLHS()->IgnoreParenImpCasts();
if (numerator->isEvaluatable(Context))
numeratorKnown = true;
diff --git a/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
index 80a3fbe1a409..bb245d82bc2b 100644
--- a/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
diff --git a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
deleted file mode 100644
index 19c1d077afa1..000000000000
--- a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
+++ /dev/null
@@ -1,525 +0,0 @@
-// MisusedMovedObjectChecker.cpp - Check use of moved-from objects. - C++ -===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This defines checker which checks for potential misuses of a moved-from
-// object. That means method calls on the object or copying it in moved-from
-// state.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckers.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-
-using namespace clang;
-using namespace ento;
-
-namespace {
-
-struct RegionState {
-private:
- enum Kind { Moved, Reported } K;
- RegionState(Kind InK) : K(InK) {}
-
-public:
- bool isReported() const { return K == Reported; }
- bool isMoved() const { return K == Moved; }
-
- static RegionState getReported() { return RegionState(Reported); }
- static RegionState getMoved() { return RegionState(Moved); }
-
- bool operator==(const RegionState &X) const { return K == X.K; }
- void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
-};
-
-class MisusedMovedObjectChecker
- : public Checker<check::PreCall, check::PostCall, check::EndFunction,
- check::DeadSymbols, check::RegionChanges> {
-public:
- void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
- void checkPreCall(const CallEvent &MC, CheckerContext &C) const;
- void checkPostCall(const CallEvent &MC, CheckerContext &C) const;
- void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
- ProgramStateRef
- checkRegionChanges(ProgramStateRef State,
- const InvalidatedSymbols *Invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const LocationContext *LCtx, const CallEvent *Call) const;
- void printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) const override;
-
-private:
- enum MisuseKind {MK_FunCall, MK_Copy, MK_Move};
- class MovedBugVisitor : public BugReporterVisitor {
- public:
- MovedBugVisitor(const MemRegion *R) : Region(R), Found(false) {}
-
- void Profile(llvm::FoldingSetNodeID &ID) const override {
- static int X = 0;
- ID.AddPointer(&X);
- ID.AddPointer(Region);
- }
-
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override;
-
- private:
- // The tracked region.
- const MemRegion *Region;
- bool Found;
- };
-
- mutable std::unique_ptr<BugType> BT;
- ExplodedNode *reportBug(const MemRegion *Region, const CallEvent &Call,
- CheckerContext &C, MisuseKind MK) const;
- bool isInMoveSafeContext(const LocationContext *LC) const;
- bool isStateResetMethod(const CXXMethodDecl *MethodDec) const;
- bool isMoveSafeMethod(const CXXMethodDecl *MethodDec) const;
- const ExplodedNode *getMoveLocation(const ExplodedNode *N,
- const MemRegion *Region,
- CheckerContext &C) const;
-};
-} // end anonymous namespace
-
-REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, RegionState)
-
-// If a region is removed all of the subregions needs to be removed too.
-static ProgramStateRef removeFromState(ProgramStateRef State,
- const MemRegion *Region) {
- if (!Region)
- return State;
- for (auto &E : State->get<TrackedRegionMap>()) {
- if (E.first->isSubRegionOf(Region))
- State = State->remove<TrackedRegionMap>(E.first);
- }
- return State;
-}
-
-static bool isAnyBaseRegionReported(ProgramStateRef State,
- const MemRegion *Region) {
- for (auto &E : State->get<TrackedRegionMap>()) {
- if (Region->isSubRegionOf(E.first) && E.second.isReported())
- return true;
- }
- return false;
-}
-
-std::shared_ptr<PathDiagnosticPiece>
-MisusedMovedObjectChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) {
- // We need only the last move of the reported object's region.
- // The visitor walks the ExplodedGraph backwards.
- if (Found)
- return nullptr;
- ProgramStateRef State = N->getState();
- ProgramStateRef StatePrev = PrevN->getState();
- const RegionState *TrackedObject = State->get<TrackedRegionMap>(Region);
- const RegionState *TrackedObjectPrev =
- StatePrev->get<TrackedRegionMap>(Region);
- if (!TrackedObject)
- return nullptr;
- if (TrackedObjectPrev && TrackedObject)
- return nullptr;
-
- // Retrieve the associated statement.
- const Stmt *S = PathDiagnosticLocation::getStmt(N);
- if (!S)
- return nullptr;
- Found = true;
-
- std::string ObjectName;
- if (const auto DecReg = Region->getAs<DeclRegion>()) {
- const auto *RegionDecl = dyn_cast<NamedDecl>(DecReg->getDecl());
- ObjectName = RegionDecl->getNameAsString();
- }
- std::string InfoText;
- if (ObjectName != "")
- InfoText = "'" + ObjectName + "' became 'moved-from' here";
- else
- InfoText = "Became 'moved-from' here";
-
- // Generate the extra diagnostic.
- PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
- N->getLocationContext());
- return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
-}
-
-const ExplodedNode *MisusedMovedObjectChecker::getMoveLocation(
- const ExplodedNode *N, const MemRegion *Region, CheckerContext &C) const {
- // Walk the ExplodedGraph backwards and find the first node that referred to
- // the tracked region.
- const ExplodedNode *MoveNode = N;
-
- while (N) {
- ProgramStateRef State = N->getState();
- if (!State->get<TrackedRegionMap>(Region))
- break;
- MoveNode = N;
- N = N->pred_empty() ? nullptr : *(N->pred_begin());
- }
- return MoveNode;
-}
-
-ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
- const CallEvent &Call,
- CheckerContext &C,
- MisuseKind MK) const {
- if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
- if (!BT)
- BT.reset(new BugType(this, "Usage of a 'moved-from' object",
- "C++ move semantics"));
-
- // Uniqueing report to the same object.
- PathDiagnosticLocation LocUsedForUniqueing;
- const ExplodedNode *MoveNode = getMoveLocation(N, Region, C);
-
- if (const Stmt *MoveStmt = PathDiagnosticLocation::getStmt(MoveNode))
- LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
- MoveStmt, C.getSourceManager(), MoveNode->getLocationContext());
-
- // Creating the error message.
- std::string ErrorMessage;
- switch(MK) {
- case MK_FunCall:
- ErrorMessage = "Method call on a 'moved-from' object";
- break;
- case MK_Copy:
- ErrorMessage = "Copying a 'moved-from' object";
- break;
- case MK_Move:
- ErrorMessage = "Moving a 'moved-from' object";
- break;
- }
- if (const auto DecReg = Region->getAs<DeclRegion>()) {
- const auto *RegionDecl = dyn_cast<NamedDecl>(DecReg->getDecl());
- ErrorMessage += " '" + RegionDecl->getNameAsString() + "'";
- }
-
- auto R =
- llvm::make_unique<BugReport>(*BT, ErrorMessage, N, LocUsedForUniqueing,
- MoveNode->getLocationContext()->getDecl());
- R->addVisitor(llvm::make_unique<MovedBugVisitor>(Region));
- C.emitReport(std::move(R));
- return N;
- }
- return nullptr;
-}
-
-// Removing the function parameters' MemRegion from the state. This is needed
-// for PODs where the trivial destructor does not even created nor executed.
-void MisusedMovedObjectChecker::checkEndFunction(const ReturnStmt *RS,
- CheckerContext &C) const {
- auto State = C.getState();
- TrackedRegionMapTy Objects = State->get<TrackedRegionMap>();
- if (Objects.isEmpty())
- return;
-
- auto LC = C.getLocationContext();
-
- const auto LD = dyn_cast_or_null<FunctionDecl>(LC->getDecl());
- if (!LD)
- return;
- llvm::SmallSet<const MemRegion *, 8> InvalidRegions;
-
- for (auto Param : LD->parameters()) {
- auto Type = Param->getType().getTypePtrOrNull();
- if (!Type)
- continue;
- if (!Type->isPointerType() && !Type->isReferenceType()) {
- InvalidRegions.insert(State->getLValue(Param, LC).getAsRegion());
- }
- }
-
- if (InvalidRegions.empty())
- return;
-
- for (const auto &E : State->get<TrackedRegionMap>()) {
- if (InvalidRegions.count(E.first->getBaseRegion()))
- State = State->remove<TrackedRegionMap>(E.first);
- }
-
- C.addTransition(State);
-}
-
-void MisusedMovedObjectChecker::checkPostCall(const CallEvent &Call,
- CheckerContext &C) const {
- const auto *AFC = dyn_cast<AnyFunctionCall>(&Call);
- if (!AFC)
- return;
-
- ProgramStateRef State = C.getState();
- const auto MethodDecl = dyn_cast_or_null<CXXMethodDecl>(AFC->getDecl());
- if (!MethodDecl)
- return;
-
- const auto *ConstructorDecl = dyn_cast<CXXConstructorDecl>(MethodDecl);
-
- const auto *CC = dyn_cast_or_null<CXXConstructorCall>(&Call);
- // Check if an object became moved-from.
- // Object can become moved from after a call to move assignment operator or
- // move constructor .
- if (ConstructorDecl && !ConstructorDecl->isMoveConstructor())
- return;
-
- if (!ConstructorDecl && !MethodDecl->isMoveAssignmentOperator())
- return;
-
- const auto ArgRegion = AFC->getArgSVal(0).getAsRegion();
- if (!ArgRegion)
- return;
-
- // Skip moving the object to itself.
- if (CC && CC->getCXXThisVal().getAsRegion() == ArgRegion)
- return;
- if (const auto *IC = dyn_cast<CXXInstanceCall>(AFC))
- if (IC->getCXXThisVal().getAsRegion() == ArgRegion)
- return;
-
- const MemRegion *BaseRegion = ArgRegion->getBaseRegion();
- // Skip temp objects because of their short lifetime.
- if (BaseRegion->getAs<CXXTempObjectRegion>() ||
- AFC->getArgExpr(0)->isRValue())
- return;
- // If it has already been reported do not need to modify the state.
-
- if (State->get<TrackedRegionMap>(ArgRegion))
- return;
- // Mark object as moved-from.
- State = State->set<TrackedRegionMap>(ArgRegion, RegionState::getMoved());
- C.addTransition(State);
-}
-
-bool MisusedMovedObjectChecker::isMoveSafeMethod(
- const CXXMethodDecl *MethodDec) const {
- // We abandon the cases where bool/void/void* conversion happens.
- if (const auto *ConversionDec =
- dyn_cast_or_null<CXXConversionDecl>(MethodDec)) {
- const Type *Tp = ConversionDec->getConversionType().getTypePtrOrNull();
- if (!Tp)
- return false;
- if (Tp->isBooleanType() || Tp->isVoidType() || Tp->isVoidPointerType())
- return true;
- }
- // Function call `empty` can be skipped.
- if (MethodDec && MethodDec->getDeclName().isIdentifier() &&
- (MethodDec->getName().lower() == "empty" ||
- MethodDec->getName().lower() == "isempty"))
- return true;
-
- return false;
-}
-
-bool MisusedMovedObjectChecker::isStateResetMethod(
- const CXXMethodDecl *MethodDec) const {
- if (MethodDec && MethodDec->getDeclName().isIdentifier()) {
- std::string MethodName = MethodDec->getName().lower();
- if (MethodName == "reset" || MethodName == "clear" ||
- MethodName == "destroy")
- return true;
- }
- return false;
-}
-
-// Don't report an error inside a move related operation.
-// We assume that the programmer knows what she does.
-bool MisusedMovedObjectChecker::isInMoveSafeContext(
- const LocationContext *LC) const {
- do {
- const auto *CtxDec = LC->getDecl();
- auto *CtorDec = dyn_cast_or_null<CXXConstructorDecl>(CtxDec);
- auto *DtorDec = dyn_cast_or_null<CXXDestructorDecl>(CtxDec);
- auto *MethodDec = dyn_cast_or_null<CXXMethodDecl>(CtxDec);
- if (DtorDec || (CtorDec && CtorDec->isCopyOrMoveConstructor()) ||
- (MethodDec && MethodDec->isOverloadedOperator() &&
- MethodDec->getOverloadedOperator() == OO_Equal) ||
- isStateResetMethod(MethodDec) || isMoveSafeMethod(MethodDec))
- return true;
- } while ((LC = LC->getParent()));
- return false;
-}
-
-void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
- CheckerContext &C) const {
- ProgramStateRef State = C.getState();
- const LocationContext *LC = C.getLocationContext();
- ExplodedNode *N = nullptr;
-
- // Remove the MemRegions from the map on which a ctor/dtor call or assignment
- // happened.
-
- // Checking constructor calls.
- if (const auto *CC = dyn_cast<CXXConstructorCall>(&Call)) {
- State = removeFromState(State, CC->getCXXThisVal().getAsRegion());
- auto CtorDec = CC->getDecl();
- // Check for copying a moved-from object and report the bug.
- if (CtorDec && CtorDec->isCopyOrMoveConstructor()) {
- const MemRegion *ArgRegion = CC->getArgSVal(0).getAsRegion();
- const RegionState *ArgState = State->get<TrackedRegionMap>(ArgRegion);
- if (ArgState && ArgState->isMoved()) {
- if (!isInMoveSafeContext(LC)) {
- if(CtorDec->isMoveConstructor())
- N = reportBug(ArgRegion, Call, C, MK_Move);
- else
- N = reportBug(ArgRegion, Call, C, MK_Copy);
- State = State->set<TrackedRegionMap>(ArgRegion,
- RegionState::getReported());
- }
- }
- }
- C.addTransition(State, N);
- return;
- }
-
- const auto IC = dyn_cast<CXXInstanceCall>(&Call);
- if (!IC)
- return;
- // In case of destructor call we do not track the object anymore.
- const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
- if (!ThisRegion)
- return;
-
- if (dyn_cast_or_null<CXXDestructorDecl>(Call.getDecl())) {
- State = removeFromState(State, ThisRegion);
- C.addTransition(State);
- return;
- }
-
- const auto MethodDecl = dyn_cast_or_null<CXXMethodDecl>(IC->getDecl());
- if (!MethodDecl)
- return;
- // Checking assignment operators.
- bool OperatorEq = MethodDecl->isOverloadedOperator() &&
- MethodDecl->getOverloadedOperator() == OO_Equal;
- // Remove the tracked object for every assignment operator, but report bug
- // only for move or copy assignment's argument.
- if (OperatorEq) {
- State = removeFromState(State, ThisRegion);
- if (MethodDecl->isCopyAssignmentOperator() ||
- MethodDecl->isMoveAssignmentOperator()) {
- const RegionState *ArgState =
- State->get<TrackedRegionMap>(IC->getArgSVal(0).getAsRegion());
- if (ArgState && ArgState->isMoved() && !isInMoveSafeContext(LC)) {
- const MemRegion *ArgRegion = IC->getArgSVal(0).getAsRegion();
- if(MethodDecl->isMoveAssignmentOperator())
- N = reportBug(ArgRegion, Call, C, MK_Move);
- else
- N = reportBug(ArgRegion, Call, C, MK_Copy);
- State =
- State->set<TrackedRegionMap>(ArgRegion, RegionState::getReported());
- }
- }
- C.addTransition(State, N);
- return;
- }
-
- // The remaining part is check only for method call on a moved-from object.
-
- // We want to investigate the whole object, not only sub-object of a parent
- // class in which the encountered method defined.
- while (const CXXBaseObjectRegion *BR =
- dyn_cast<CXXBaseObjectRegion>(ThisRegion))
- ThisRegion = BR->getSuperRegion();
-
- if (isMoveSafeMethod(MethodDecl))
- return;
-
- if (isStateResetMethod(MethodDecl)) {
- State = removeFromState(State, ThisRegion);
- C.addTransition(State);
- return;
- }
-
- // If it is already reported then we don't report the bug again.
- const RegionState *ThisState = State->get<TrackedRegionMap>(ThisRegion);
- if (!(ThisState && ThisState->isMoved()))
- return;
-
- // Don't report it in case if any base region is already reported
- if (isAnyBaseRegionReported(State, ThisRegion))
- return;
-
- if (isInMoveSafeContext(LC))
- return;
-
- N = reportBug(ThisRegion, Call, C, MK_FunCall);
- State = State->set<TrackedRegionMap>(ThisRegion, RegionState::getReported());
- C.addTransition(State, N);
-}
-
-void MisusedMovedObjectChecker::checkDeadSymbols(SymbolReaper &SymReaper,
- CheckerContext &C) const {
- ProgramStateRef State = C.getState();
- TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
- for (TrackedRegionMapTy::value_type E : TrackedRegions) {
- const MemRegion *Region = E.first;
- bool IsRegDead = !SymReaper.isLiveRegion(Region);
-
- // Remove the dead regions from the region map.
- if (IsRegDead) {
- State = State->remove<TrackedRegionMap>(Region);
- }
- }
- C.addTransition(State);
-}
-
-ProgramStateRef MisusedMovedObjectChecker::checkRegionChanges(
- ProgramStateRef State, const InvalidatedSymbols *Invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
- const CallEvent *Call) const {
- // In case of an InstanceCall don't remove the ThisRegion from the GDM since
- // it is handled in checkPreCall and checkPostCall.
- const MemRegion *ThisRegion = nullptr;
- if (const auto *IC = dyn_cast_or_null<CXXInstanceCall>(Call)) {
- ThisRegion = IC->getCXXThisVal().getAsRegion();
- }
-
- for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
- E = ExplicitRegions.end();
- I != E; ++I) {
- const auto *Region = *I;
- if (ThisRegion != Region) {
- State = removeFromState(State, Region);
- }
- }
-
- return State;
-}
-
-void MisusedMovedObjectChecker::printState(raw_ostream &Out,
- ProgramStateRef State,
- const char *NL,
- const char *Sep) const {
-
- TrackedRegionMapTy RS = State->get<TrackedRegionMap>();
-
- if (!RS.isEmpty()) {
- Out << Sep << "Moved-from objects :" << NL;
- for (auto I: RS) {
- I.first->dumpToStream(Out);
- if (I.second.isMoved())
- Out << ": moved";
- else
- Out << ": moved and reported";
- Out << NL;
- }
- }
-}
-void ento::registerMisusedMovedObjectChecker(CheckerManager &mgr) {
- mgr.registerChecker<MisusedMovedObjectChecker>();
-}
diff --git a/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
index 5060b0e0a6e0..e3b24f20b0f0 100644
--- a/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -82,7 +82,9 @@ void ento::registerMmapWriteExecChecker(CheckerManager &mgr) {
MmapWriteExecChecker *Mwec =
mgr.registerChecker<MmapWriteExecChecker>();
Mwec->ProtExecOv =
- mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtExec", 0x04, Mwec);
+ mgr.getAnalyzerOptions()
+ .getCheckerIntegerOption("MmapProtExec", 0x04, Mwec);
Mwec->ProtReadOv =
- mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtRead", 0x01, Mwec);
+ mgr.getAnalyzerOptions()
+ .getCheckerIntegerOption("MmapProtRead", 0x01, Mwec);
}
diff --git a/lib/StaticAnalyzer/Checkers/MoveChecker.cpp b/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
new file mode 100644
index 000000000000..6efa2dfbe5b4
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -0,0 +1,740 @@
+// MoveChecker.cpp - Check use of moved-from objects. - C++ ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines checker which checks for potential misuses of a moved-from
+// object. That means method calls on the object or copying it in moved-from
+// state.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ExprCXX.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+struct RegionState {
+private:
+ enum Kind { Moved, Reported } K;
+ RegionState(Kind InK) : K(InK) {}
+
+public:
+ bool isReported() const { return K == Reported; }
+ bool isMoved() const { return K == Moved; }
+
+ static RegionState getReported() { return RegionState(Reported); }
+ static RegionState getMoved() { return RegionState(Moved); }
+
+ bool operator==(const RegionState &X) const { return K == X.K; }
+ void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
+};
+} // end of anonymous namespace
+
+namespace {
+class MoveChecker
+ : public Checker<check::PreCall, check::PostCall,
+ check::DeadSymbols, check::RegionChanges> {
+public:
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
+ void checkPreCall(const CallEvent &MC, CheckerContext &C) const;
+ void checkPostCall(const CallEvent &MC, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+ ProgramStateRef
+ checkRegionChanges(ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> RequestedRegions,
+ ArrayRef<const MemRegion *> InvalidatedRegions,
+ const LocationContext *LCtx, const CallEvent *Call) const;
+ void printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const override;
+
+private:
+ enum MisuseKind { MK_FunCall, MK_Copy, MK_Move, MK_Dereference };
+ enum StdObjectKind { SK_NonStd, SK_Unsafe, SK_Safe, SK_SmartPtr };
+
+ enum AggressivenessKind { // In any case, don't warn after a reset.
+ AK_Invalid = -1,
+ AK_KnownsOnly = 0, // Warn only about known move-unsafe classes.
+ AK_KnownsAndLocals = 1, // Also warn about all local objects.
+ AK_All = 2, // Warn on any use-after-move.
+ AK_NumKinds = AK_All
+ };
+
+ static bool misuseCausesCrash(MisuseKind MK) {
+ return MK == MK_Dereference;
+ }
+
+ struct ObjectKind {
+ // Is this a local variable or a local rvalue reference?
+ bool IsLocal;
+ // Is this an STL object? If so, of what kind?
+ StdObjectKind StdKind;
+ };
+
+ // STL smart pointers are automatically re-initialized to null when moved
+ // from. So we can't warn on many methods, but we can warn when it is
+ // dereferenced, which is UB even if the resulting lvalue never gets read.
+ const llvm::StringSet<> StdSmartPtrClasses = {
+ "shared_ptr",
+ "unique_ptr",
+ "weak_ptr",
+ };
+
+ // Not all of these are entirely move-safe, but they do provide *some*
+ // guarantees, and it means that somebody is using them after move
+ // in a valid manner.
+ // TODO: We can still try to identify *unsafe* use after move,
+ // like we did with smart pointers.
+ const llvm::StringSet<> StdSafeClasses = {
+ "basic_filebuf",
+ "basic_ios",
+ "future",
+ "optional",
+ "packaged_task"
+ "promise",
+ "shared_future",
+ "shared_lock",
+ "thread",
+ "unique_lock",
+ };
+
+ // Should we bother tracking the state of the object?
+ bool shouldBeTracked(ObjectKind OK) const {
+ // In non-aggressive mode, only warn on use-after-move of local variables
+ // (or local rvalue references) and of STL objects. The former is possible
+ // because local variables (or local rvalue references) are not tempting
+ // their user to re-use the storage. The latter is possible because STL
+ // objects are known to end up in a valid but unspecified state after the
+ // move and their state-reset methods are also known, which allows us to
+ // predict precisely when use-after-move is invalid.
+ // Some STL objects are known to conform to additional contracts after move,
+ // so they are not tracked. However, smart pointers specifically are tracked
+ // because we can perform extra checking over them.
+ // In aggressive mode, warn on any use-after-move because the user has
+ // intentionally asked us to completely eliminate use-after-move
+ // in his code.
+ return (Aggressiveness == AK_All) ||
+ (Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
+ OK.StdKind == SK_Unsafe || OK.StdKind == SK_SmartPtr;
+ }
+
+ // Some objects only suffer from some kinds of misuses, but we need to track
+ // them anyway because we cannot know in advance what misuse will we find.
+ bool shouldWarnAbout(ObjectKind OK, MisuseKind MK) const {
+ // Additionally, only warn on smart pointers when they are dereferenced (or
+ // local or we are aggressive).
+ return shouldBeTracked(OK) &&
+ ((Aggressiveness == AK_All) ||
+ (Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
+ OK.StdKind != SK_SmartPtr || MK == MK_Dereference);
+ }
+
+ // Obtains ObjectKind of an object. Because class declaration cannot always
+ // be easily obtained from the memory region, it is supplied separately.
+ ObjectKind classifyObject(const MemRegion *MR, const CXXRecordDecl *RD) const;
+
+ // Classifies the object and dumps a user-friendly description string to
+ // the stream.
+ void explainObject(llvm::raw_ostream &OS, const MemRegion *MR,
+ const CXXRecordDecl *RD, MisuseKind MK) const;
+
+ bool belongsTo(const CXXRecordDecl *RD, const llvm::StringSet<> &Set) const;
+
+ class MovedBugVisitor : public BugReporterVisitor {
+ public:
+ MovedBugVisitor(const MoveChecker &Chk, const MemRegion *R,
+ const CXXRecordDecl *RD, MisuseKind MK)
+ : Chk(Chk), Region(R), RD(RD), MK(MK), Found(false) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int X = 0;
+ ID.AddPointer(&X);
+ ID.AddPointer(Region);
+ // Don't add RD because it's, in theory, uniquely determined by
+ // the region. In practice though, it's not always possible to obtain
+ // the declaration directly from the region, that's why we store it
+ // in the first place.
+ }
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ private:
+ const MoveChecker &Chk;
+ // The tracked region.
+ const MemRegion *Region;
+ // The class of the tracked object.
+ const CXXRecordDecl *RD;
+ // How exactly the object was misused.
+ const MisuseKind MK;
+ bool Found;
+ };
+
+ AggressivenessKind Aggressiveness;
+
+public:
+ void setAggressiveness(StringRef Str) {
+ Aggressiveness =
+ llvm::StringSwitch<AggressivenessKind>(Str)
+ .Case("KnownsOnly", AK_KnownsOnly)
+ .Case("KnownsAndLocals", AK_KnownsAndLocals)
+ .Case("All", AK_All)
+ .Default(AK_KnownsAndLocals); // A sane default.
+ };
+
+private:
+ mutable std::unique_ptr<BugType> BT;
+
+ // Check if the given form of potential misuse of a given object
+ // should be reported. If so, get it reported. The callback from which
+ // this function was called should immediately return after the call
+ // because this function adds one or two transitions.
+ void modelUse(ProgramStateRef State, const MemRegion *Region,
+ const CXXRecordDecl *RD, MisuseKind MK,
+ CheckerContext &C) const;
+
+ // Returns the exploded node against which the report was emitted.
+ // The caller *must* add any further transitions against this node.
+ ExplodedNode *reportBug(const MemRegion *Region, const CXXRecordDecl *RD,
+ CheckerContext &C, MisuseKind MK) const;
+
+ bool isInMoveSafeContext(const LocationContext *LC) const;
+ bool isStateResetMethod(const CXXMethodDecl *MethodDec) const;
+ bool isMoveSafeMethod(const CXXMethodDecl *MethodDec) const;
+ const ExplodedNode *getMoveLocation(const ExplodedNode *N,
+ const MemRegion *Region,
+ CheckerContext &C) const;
+};
+} // end anonymous namespace
+
+REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, RegionState)
+
+// If a region is removed all of the subregions needs to be removed too.
+static ProgramStateRef removeFromState(ProgramStateRef State,
+ const MemRegion *Region) {
+ if (!Region)
+ return State;
+ for (auto &E : State->get<TrackedRegionMap>()) {
+ if (E.first->isSubRegionOf(Region))
+ State = State->remove<TrackedRegionMap>(E.first);
+ }
+ return State;
+}
+
+static bool isAnyBaseRegionReported(ProgramStateRef State,
+ const MemRegion *Region) {
+ for (auto &E : State->get<TrackedRegionMap>()) {
+ if (Region->isSubRegionOf(E.first) && E.second.isReported())
+ return true;
+ }
+ return false;
+}
+
+static const MemRegion *unwrapRValueReferenceIndirection(const MemRegion *MR) {
+ if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(MR)) {
+ SymbolRef Sym = SR->getSymbol();
+ if (Sym->getType()->isRValueReferenceType())
+ if (const MemRegion *OriginMR = Sym->getOriginRegion())
+ return OriginMR;
+ }
+ return MR;
+}
+
+std::shared_ptr<PathDiagnosticPiece>
+MoveChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC, BugReport &BR) {
+ // We need only the last move of the reported object's region.
+ // The visitor walks the ExplodedGraph backwards.
+ if (Found)
+ return nullptr;
+ ProgramStateRef State = N->getState();
+ ProgramStateRef StatePrev = N->getFirstPred()->getState();
+ const RegionState *TrackedObject = State->get<TrackedRegionMap>(Region);
+ const RegionState *TrackedObjectPrev =
+ StatePrev->get<TrackedRegionMap>(Region);
+ if (!TrackedObject)
+ return nullptr;
+ if (TrackedObjectPrev && TrackedObject)
+ return nullptr;
+
+ // Retrieve the associated statement.
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ if (!S)
+ return nullptr;
+ Found = true;
+
+ SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+
+ ObjectKind OK = Chk.classifyObject(Region, RD);
+ switch (OK.StdKind) {
+ case SK_SmartPtr:
+ if (MK == MK_Dereference) {
+ OS << "Smart pointer";
+ Chk.explainObject(OS, Region, RD, MK);
+ OS << " is reset to null when moved from";
+ break;
+ }
+
+ // If it's not a dereference, we don't care if it was reset to null
+ // or that it is even a smart pointer.
+ LLVM_FALLTHROUGH;
+ case SK_NonStd:
+ case SK_Safe:
+ OS << "Object";
+ Chk.explainObject(OS, Region, RD, MK);
+ OS << " is moved";
+ break;
+ case SK_Unsafe:
+ OS << "Object";
+ Chk.explainObject(OS, Region, RD, MK);
+ OS << " is left in a valid but unspecified state after move";
+ break;
+ }
+
+ // Generate the extra diagnostic.
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
+}
+
+const ExplodedNode *MoveChecker::getMoveLocation(const ExplodedNode *N,
+ const MemRegion *Region,
+ CheckerContext &C) const {
+ // Walk the ExplodedGraph backwards and find the first node that referred to
+ // the tracked region.
+ const ExplodedNode *MoveNode = N;
+
+ while (N) {
+ ProgramStateRef State = N->getState();
+ if (!State->get<TrackedRegionMap>(Region))
+ break;
+ MoveNode = N;
+ N = N->pred_empty() ? nullptr : *(N->pred_begin());
+ }
+ return MoveNode;
+}
+
+void MoveChecker::modelUse(ProgramStateRef State, const MemRegion *Region,
+ const CXXRecordDecl *RD, MisuseKind MK,
+ CheckerContext &C) const {
+ assert(!C.isDifferent() && "No transitions should have been made by now");
+ const RegionState *RS = State->get<TrackedRegionMap>(Region);
+ ObjectKind OK = classifyObject(Region, RD);
+
+ // Just in case: if it's not a smart pointer but it does have operator *,
+ // we shouldn't call the bug a dereference.
+ if (MK == MK_Dereference && OK.StdKind != SK_SmartPtr)
+ MK = MK_FunCall;
+
+ if (!RS || !shouldWarnAbout(OK, MK)
+ || isInMoveSafeContext(C.getLocationContext())) {
+ // Finalize changes made by the caller.
+ C.addTransition(State);
+ return;
+ }
+
+ // Don't report it in case if any base region is already reported.
+ // But still generate a sink in case of UB.
+ // And still finalize changes made by the caller.
+ if (isAnyBaseRegionReported(State, Region)) {
+ if (misuseCausesCrash(MK)) {
+ C.generateSink(State, C.getPredecessor());
+ } else {
+ C.addTransition(State);
+ }
+ return;
+ }
+
+ ExplodedNode *N = reportBug(Region, RD, C, MK);
+
+ // If the program has already crashed on this path, don't bother.
+ if (N->isSink())
+ return;
+
+ State = State->set<TrackedRegionMap>(Region, RegionState::getReported());
+ C.addTransition(State, N);
+}
+
+ExplodedNode *MoveChecker::reportBug(const MemRegion *Region,
+ const CXXRecordDecl *RD, CheckerContext &C,
+ MisuseKind MK) const {
+ if (ExplodedNode *N = misuseCausesCrash(MK) ? C.generateErrorNode()
+ : C.generateNonFatalErrorNode()) {
+
+ if (!BT)
+ BT.reset(new BugType(this, "Use-after-move",
+ "C++ move semantics"));
+
+ // Uniqueing report to the same object.
+ PathDiagnosticLocation LocUsedForUniqueing;
+ const ExplodedNode *MoveNode = getMoveLocation(N, Region, C);
+
+ if (const Stmt *MoveStmt = PathDiagnosticLocation::getStmt(MoveNode))
+ LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
+ MoveStmt, C.getSourceManager(), MoveNode->getLocationContext());
+
+ // Creating the error message.
+ llvm::SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+ switch(MK) {
+ case MK_FunCall:
+ OS << "Method called on moved-from object";
+ explainObject(OS, Region, RD, MK);
+ break;
+ case MK_Copy:
+ OS << "Moved-from object";
+ explainObject(OS, Region, RD, MK);
+ OS << " is copied";
+ break;
+ case MK_Move:
+ OS << "Moved-from object";
+ explainObject(OS, Region, RD, MK);
+ OS << " is moved";
+ break;
+ case MK_Dereference:
+ OS << "Dereference of null smart pointer";
+ explainObject(OS, Region, RD, MK);
+ break;
+ }
+
+ auto R =
+ llvm::make_unique<BugReport>(*BT, OS.str(), N, LocUsedForUniqueing,
+ MoveNode->getLocationContext()->getDecl());
+ R->addVisitor(llvm::make_unique<MovedBugVisitor>(*this, Region, RD, MK));
+ C.emitReport(std::move(R));
+ return N;
+ }
+ return nullptr;
+}
+
+void MoveChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto *AFC = dyn_cast<AnyFunctionCall>(&Call);
+ if (!AFC)
+ return;
+
+ ProgramStateRef State = C.getState();
+ const auto MethodDecl = dyn_cast_or_null<CXXMethodDecl>(AFC->getDecl());
+ if (!MethodDecl)
+ return;
+
+ // Check if an object became moved-from.
+ // Object can become moved from after a call to move assignment operator or
+ // move constructor .
+ const auto *ConstructorDecl = dyn_cast<CXXConstructorDecl>(MethodDecl);
+ if (ConstructorDecl && !ConstructorDecl->isMoveConstructor())
+ return;
+
+ if (!ConstructorDecl && !MethodDecl->isMoveAssignmentOperator())
+ return;
+
+ const auto ArgRegion = AFC->getArgSVal(0).getAsRegion();
+ if (!ArgRegion)
+ return;
+
+ // Skip moving the object to itself.
+ const auto *CC = dyn_cast_or_null<CXXConstructorCall>(&Call);
+ if (CC && CC->getCXXThisVal().getAsRegion() == ArgRegion)
+ return;
+
+ if (const auto *IC = dyn_cast<CXXInstanceCall>(AFC))
+ if (IC->getCXXThisVal().getAsRegion() == ArgRegion)
+ return;
+
+ const MemRegion *BaseRegion = ArgRegion->getBaseRegion();
+ // Skip temp objects because of their short lifetime.
+ if (BaseRegion->getAs<CXXTempObjectRegion>() ||
+ AFC->getArgExpr(0)->isRValue())
+ return;
+ // If it has already been reported do not need to modify the state.
+
+ if (State->get<TrackedRegionMap>(ArgRegion))
+ return;
+
+ const CXXRecordDecl *RD = MethodDecl->getParent();
+ ObjectKind OK = classifyObject(ArgRegion, RD);
+ if (shouldBeTracked(OK)) {
+ // Mark object as moved-from.
+ State = State->set<TrackedRegionMap>(ArgRegion, RegionState::getMoved());
+ C.addTransition(State);
+ return;
+ }
+ assert(!C.isDifferent() && "Should not have made transitions on this path!");
+}
+
+bool MoveChecker::isMoveSafeMethod(const CXXMethodDecl *MethodDec) const {
+ // We abandon the cases where bool/void/void* conversion happens.
+ if (const auto *ConversionDec =
+ dyn_cast_or_null<CXXConversionDecl>(MethodDec)) {
+ const Type *Tp = ConversionDec->getConversionType().getTypePtrOrNull();
+ if (!Tp)
+ return false;
+ if (Tp->isBooleanType() || Tp->isVoidType() || Tp->isVoidPointerType())
+ return true;
+ }
+ // Function call `empty` can be skipped.
+ return (MethodDec && MethodDec->getDeclName().isIdentifier() &&
+ (MethodDec->getName().lower() == "empty" ||
+ MethodDec->getName().lower() == "isempty"));
+}
+
+bool MoveChecker::isStateResetMethod(const CXXMethodDecl *MethodDec) const {
+ if (!MethodDec)
+ return false;
+ if (MethodDec->hasAttr<ReinitializesAttr>())
+ return true;
+ if (MethodDec->getDeclName().isIdentifier()) {
+ std::string MethodName = MethodDec->getName().lower();
+ // TODO: Some of these methods (eg., resize) are not always resetting
+ // the state, so we should consider looking at the arguments.
+ if (MethodName == "reset" || MethodName == "clear" ||
+ MethodName == "destroy" || MethodName == "resize" ||
+ MethodName == "shrink")
+ return true;
+ }
+ return false;
+}
+
+// Don't report an error inside a move related operation.
+// We assume that the programmer knows what she does.
+bool MoveChecker::isInMoveSafeContext(const LocationContext *LC) const {
+ do {
+ const auto *CtxDec = LC->getDecl();
+ auto *CtorDec = dyn_cast_or_null<CXXConstructorDecl>(CtxDec);
+ auto *DtorDec = dyn_cast_or_null<CXXDestructorDecl>(CtxDec);
+ auto *MethodDec = dyn_cast_or_null<CXXMethodDecl>(CtxDec);
+ if (DtorDec || (CtorDec && CtorDec->isCopyOrMoveConstructor()) ||
+ (MethodDec && MethodDec->isOverloadedOperator() &&
+ MethodDec->getOverloadedOperator() == OO_Equal) ||
+ isStateResetMethod(MethodDec) || isMoveSafeMethod(MethodDec))
+ return true;
+ } while ((LC = LC->getParent()));
+ return false;
+}
+
+bool MoveChecker::belongsTo(const CXXRecordDecl *RD,
+ const llvm::StringSet<> &Set) const {
+ const IdentifierInfo *II = RD->getIdentifier();
+ return II && Set.count(II->getName());
+}
+
+MoveChecker::ObjectKind
+MoveChecker::classifyObject(const MemRegion *MR,
+ const CXXRecordDecl *RD) const {
+ // Local variables and local rvalue references are classified as "Local".
+ // For the purposes of this checker, we classify move-safe STL types
+ // as not-"STL" types, because that's how the checker treats them.
+ MR = unwrapRValueReferenceIndirection(MR);
+ bool IsLocal =
+ MR && isa<VarRegion>(MR) && isa<StackSpaceRegion>(MR->getMemorySpace());
+
+ if (!RD || !RD->getDeclContext()->isStdNamespace())
+ return { IsLocal, SK_NonStd };
+
+ if (belongsTo(RD, StdSmartPtrClasses))
+ return { IsLocal, SK_SmartPtr };
+
+ if (belongsTo(RD, StdSafeClasses))
+ return { IsLocal, SK_Safe };
+
+ return { IsLocal, SK_Unsafe };
+}
+
+void MoveChecker::explainObject(llvm::raw_ostream &OS, const MemRegion *MR,
+ const CXXRecordDecl *RD, MisuseKind MK) const {
+ // We may need a leading space every time we actually explain anything,
+ // and we never know if we are to explain anything until we try.
+ if (const auto DR =
+ dyn_cast_or_null<DeclRegion>(unwrapRValueReferenceIndirection(MR))) {
+ const auto *RegionDecl = cast<NamedDecl>(DR->getDecl());
+ OS << " '" << RegionDecl->getNameAsString() << "'";
+ }
+
+ ObjectKind OK = classifyObject(MR, RD);
+ switch (OK.StdKind) {
+ case SK_NonStd:
+ case SK_Safe:
+ break;
+ case SK_SmartPtr:
+ if (MK != MK_Dereference)
+ break;
+
+ // We only care about the type if it's a dereference.
+ LLVM_FALLTHROUGH;
+ case SK_Unsafe:
+ OS << " of type '" << RD->getQualifiedNameAsString() << "'";
+ break;
+ };
+}
+
+void MoveChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+
+ // Remove the MemRegions from the map on which a ctor/dtor call or assignment
+ // happened.
+
+ // Checking constructor calls.
+ if (const auto *CC = dyn_cast<CXXConstructorCall>(&Call)) {
+ State = removeFromState(State, CC->getCXXThisVal().getAsRegion());
+ auto CtorDec = CC->getDecl();
+ // Check for copying a moved-from object and report the bug.
+ if (CtorDec && CtorDec->isCopyOrMoveConstructor()) {
+ const MemRegion *ArgRegion = CC->getArgSVal(0).getAsRegion();
+ const CXXRecordDecl *RD = CtorDec->getParent();
+ MisuseKind MK = CtorDec->isMoveConstructor() ? MK_Move : MK_Copy;
+ modelUse(State, ArgRegion, RD, MK, C);
+ return;
+ }
+ }
+
+ const auto IC = dyn_cast<CXXInstanceCall>(&Call);
+ if (!IC)
+ return;
+
+ // Calling a destructor on a moved object is fine.
+ if (isa<CXXDestructorCall>(IC))
+ return;
+
+ const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
+ if (!ThisRegion)
+ return;
+
+ // The remaining part is check only for method call on a moved-from object.
+ const auto MethodDecl = dyn_cast_or_null<CXXMethodDecl>(IC->getDecl());
+ if (!MethodDecl)
+ return;
+
+ // We want to investigate the whole object, not only sub-object of a parent
+ // class in which the encountered method defined.
+ ThisRegion = ThisRegion->getMostDerivedObjectRegion();
+
+ if (isStateResetMethod(MethodDecl)) {
+ State = removeFromState(State, ThisRegion);
+ C.addTransition(State);
+ return;
+ }
+
+ if (isMoveSafeMethod(MethodDecl))
+ return;
+
+ // Store class declaration as well, for bug reporting purposes.
+ const CXXRecordDecl *RD = MethodDecl->getParent();
+
+ if (MethodDecl->isOverloadedOperator()) {
+ OverloadedOperatorKind OOK = MethodDecl->getOverloadedOperator();
+
+ if (OOK == OO_Equal) {
+ // Remove the tracked object for every assignment operator, but report bug
+ // only for move or copy assignment's argument.
+ State = removeFromState(State, ThisRegion);
+
+ if (MethodDecl->isCopyAssignmentOperator() ||
+ MethodDecl->isMoveAssignmentOperator()) {
+ const MemRegion *ArgRegion = IC->getArgSVal(0).getAsRegion();
+ MisuseKind MK =
+ MethodDecl->isMoveAssignmentOperator() ? MK_Move : MK_Copy;
+ modelUse(State, ArgRegion, RD, MK, C);
+ return;
+ }
+ C.addTransition(State);
+ return;
+ }
+
+ if (OOK == OO_Star || OOK == OO_Arrow) {
+ modelUse(State, ThisRegion, RD, MK_Dereference, C);
+ return;
+ }
+ }
+
+ modelUse(State, ThisRegion, RD, MK_FunCall, C);
+}
+
+void MoveChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
+ for (TrackedRegionMapTy::value_type E : TrackedRegions) {
+ const MemRegion *Region = E.first;
+ bool IsRegDead = !SymReaper.isLiveRegion(Region);
+
+ // Remove the dead regions from the region map.
+ if (IsRegDead) {
+ State = State->remove<TrackedRegionMap>(Region);
+ }
+ }
+ C.addTransition(State);
+}
+
+ProgramStateRef MoveChecker::checkRegionChanges(
+ ProgramStateRef State, const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> RequestedRegions,
+ ArrayRef<const MemRegion *> InvalidatedRegions,
+ const LocationContext *LCtx, const CallEvent *Call) const {
+ if (Call) {
+ // Relax invalidation upon function calls: only invalidate parameters
+ // that are passed directly via non-const pointers or non-const references
+ // or rvalue references.
+ // In case of an InstanceCall don't invalidate the this-region since
+ // it is fully handled in checkPreCall and checkPostCall.
+ const MemRegion *ThisRegion = nullptr;
+ if (const auto *IC = dyn_cast<CXXInstanceCall>(Call))
+ ThisRegion = IC->getCXXThisVal().getAsRegion();
+
+ // Requested ("explicit") regions are the regions passed into the call
+ // directly, but not all of them end up being invalidated.
+ // But when they do, they appear in the InvalidatedRegions array as well.
+ for (const auto *Region : RequestedRegions) {
+ if (ThisRegion != Region) {
+ if (llvm::find(InvalidatedRegions, Region) !=
+ std::end(InvalidatedRegions)) {
+ State = removeFromState(State, Region);
+ }
+ }
+ }
+ } else {
+ // For invalidations that aren't caused by calls, assume nothing. In
+ // particular, direct write into an object's field invalidates the status.
+ for (const auto *Region : InvalidatedRegions)
+ State = removeFromState(State, Region->getBaseRegion());
+ }
+
+ return State;
+}
+
+void MoveChecker::printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const {
+
+ TrackedRegionMapTy RS = State->get<TrackedRegionMap>();
+
+ if (!RS.isEmpty()) {
+ Out << Sep << "Moved-from objects :" << NL;
+ for (auto I: RS) {
+ I.first->dumpToStream(Out);
+ if (I.second.isMoved())
+ Out << ": moved";
+ else
+ Out << ": moved and reported";
+ Out << NL;
+ }
+ }
+}
+void ento::registerMoveChecker(CheckerManager &mgr) {
+ MoveChecker *chk = mgr.registerChecker<MoveChecker>();
+ chk->setAggressiveness(
+ mgr.getAnalyzerOptions().getCheckerStringOption("WarnOn", "", chk));
+}
diff --git a/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
index 0e7894788c87..4ed1b25cb09e 100644
--- a/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
diff --git a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
index 2bd68b625c1f..06c43c6b9470 100644
--- a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
diff --git a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
index 8a5c769b6b50..83d4b5b0758b 100644
--- a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -12,9 +12,9 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
-#include "SelectorExtras.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
+#include "clang/Analysis/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
diff --git a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 01d2c0491b85..3c4363b6850e 100644
--- a/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -192,7 +192,7 @@ NonNullParamChecker::genReportNullAttrNonNull(const ExplodedNode *ErrorNode,
*BTAttrNonNull,
"Null pointer passed as an argument to a 'nonnull' parameter", ErrorNode);
if (ArgE)
- bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R);
+ bugreporter::trackExpressionValue(ErrorNode, ArgE, *R);
return R;
}
@@ -208,9 +208,7 @@ std::unique_ptr<BugReport> NonNullParamChecker::genReportReferenceToNullPointer(
const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
if (!ArgEDeref)
ArgEDeref = ArgE;
- bugreporter::trackNullOrUndefValue(ErrorNode,
- ArgEDeref,
- *R);
+ bugreporter::trackExpressionValue(ErrorNode, ArgEDeref, *R);
}
return R;
diff --git a/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
index 6f3180eb839a..ce9e950aa9ba 100644
--- a/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
@@ -21,7 +21,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index 7d1ca61c97a9..e535d1ae27ac 100644
--- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -25,7 +25,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -139,7 +139,6 @@ private:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -175,7 +174,8 @@ private:
if (Error == ErrorKind::NilAssignedToNonnull ||
Error == ErrorKind::NilPassedToNonnull ||
Error == ErrorKind::NilReturnedToNonnull)
- bugreporter::trackNullOrUndefValue(N, ValueExpr, *R);
+ if (const auto *Ex = dyn_cast<Expr>(ValueExpr))
+ bugreporter::trackExpressionValue(N, Ex, *R);
}
BR.emitReport(std::move(R));
}
@@ -185,7 +185,7 @@ private:
const SymbolicRegion *getTrackRegion(SVal Val,
bool CheckSuperRegion = false) const;
- /// Returns true if the call is diagnosable in the currrent analyzer
+ /// Returns true if the call is diagnosable in the current analyzer
/// configuration.
bool isDiagnosableCall(const CallEvent &Call) const {
if (NoDiagnoseCallsToSystemHeaders && Call.isInSystemHeader())
@@ -293,11 +293,10 @@ NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
std::shared_ptr<PathDiagnosticPiece>
NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) {
ProgramStateRef State = N->getState();
- ProgramStateRef StatePrev = PrevN->getState();
+ ProgramStateRef StatePrev = N->getFirstPred()->getState();
const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
const NullabilityState *TrackedNullabPrev =
@@ -311,7 +310,7 @@ NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
// Retrieve the associated statement.
const Stmt *S = TrackedNullab->getNullabilitySource();
- if (!S || S->getLocStart().isInvalid()) {
+ if (!S || S->getBeginLoc().isInvalid()) {
S = PathDiagnosticLocation::getStmt(N);
}
@@ -330,8 +329,8 @@ NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
nullptr);
}
-/// Returns true when the value stored at the given location is null
-/// and the passed in type is nonnnull.
+/// Returns true when the value stored at the given location has been
+/// constrained to null after being passed through an object of nonnnull type.
static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
SVal LV, QualType T) {
if (getNullabilityAnnotation(T) != Nullability::Nonnull)
@@ -341,9 +340,14 @@ static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
if (!RegionVal)
return false;
- auto StoredVal =
- State->getSVal(RegionVal->getRegion()).getAs<DefinedOrUnknownSVal>();
- if (!StoredVal)
+ // If the value was constrained to null *after* it was passed through that
+ // location, it could not have been a concrete pointer *when* it was passed.
+ // In that case we would have handled the situation when the value was
+ // bound to that location, by emitting (or not emitting) a report.
+ // Therefore we are only interested in symbolic regions that can be either
+ // null or non-null depending on the value of their respective symbol.
+ auto StoredVal = State->getSVal(*RegionVal).getAs<loc::MemRegionVal>();
+ if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
return false;
if (getNullConstraint(*StoredVal, State) == NullConstraint::IsNull)
@@ -447,9 +451,6 @@ void NullabilityChecker::reportBugIfInvariantHolds(StringRef Msg,
/// Cleaning up the program state.
void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
CheckerContext &C) const {
- if (!SR.hasDeadSymbols())
- return;
-
ProgramStateRef State = C.getState();
NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
for (NullabilityMapTy::iterator I = Nullabilities.begin(),
@@ -766,7 +767,7 @@ void NullabilityChecker::checkPostCall(const CallEvent &Call,
// CG headers are misannotated. Do not warn for symbols that are the results
// of CG calls.
const SourceManager &SM = C.getSourceManager();
- StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getLocStart()));
+ StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getBeginLoc()));
if (llvm::sys::path::filename(FilePath).startswith("CG")) {
State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
C.addTransition(State);
@@ -1174,10 +1175,15 @@ void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
NullabilityMapTy B = State->get<NullabilityMap>();
+ if (State->get<InvariantViolated>())
+ Out << Sep << NL
+ << "Nullability invariant was violated, warnings suppressed." << NL;
+
if (B.isEmpty())
return;
- Out << Sep << NL;
+ if (!State->get<InvariantViolated>())
+ Out << Sep << NL;
for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
Out << I->first << " : ";
@@ -1194,7 +1200,7 @@ void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
checker->NeedTracking = checker->NeedTracking || trackingRequired; \
checker->NoDiagnoseCallsToSystemHeaders = \
checker->NoDiagnoseCallsToSystemHeaders || \
- mgr.getAnalyzerOptions().getBooleanOption( \
+ mgr.getAnalyzerOptions().getCheckerBooleanOption( \
"NoDiagnoseCallsToSystemHeaders", false, checker, true); \
}
diff --git a/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp b/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
index d1749cfdbe27..4e3a7205f1f4 100644
--- a/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
@@ -26,7 +26,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -77,7 +77,7 @@ void Callback::run(const MatchFinder::MatchResult &Result) {
// to zero literals in non-pedantic mode.
// FIXME: Introduce an AST matcher to implement the macro-related logic?
bool MacroIndicatesWeShouldSkipTheCheck = false;
- SourceLocation Loc = CheckIfNull->getLocStart();
+ SourceLocation Loc = CheckIfNull->getBeginLoc();
if (Loc.isMacroID()) {
StringRef MacroName = Lexer::getImmediateMacroName(
Loc, ACtx.getSourceManager(), ACtx.getLangOpts());
@@ -87,9 +87,10 @@ void Callback::run(const MatchFinder::MatchResult &Result) {
MacroIndicatesWeShouldSkipTheCheck = true;
}
if (!MacroIndicatesWeShouldSkipTheCheck) {
- llvm::APSInt Result;
+ Expr::EvalResult EVResult;
if (CheckIfNull->IgnoreParenCasts()->EvaluateAsInt(
- Result, ACtx, Expr::SE_AllowSideEffects)) {
+ EVResult, ACtx, Expr::SE_AllowSideEffects)) {
+ llvm::APSInt Result = EVResult.Val.getInt();
if (Result == 0) {
if (!C->Pedantic)
return;
@@ -346,5 +347,5 @@ void ento::registerNumberObjectConversionChecker(CheckerManager &Mgr) {
NumberObjectConversionChecker *Chk =
Mgr.registerChecker<NumberObjectConversionChecker>();
Chk->Pedantic =
- Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk);
+ Mgr.getAnalyzerOptions().getCheckerBooleanOption("Pedantic", false, Chk);
}
diff --git a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index b7339fe79f69..185b57575cb0 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/StmtObjC.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -49,7 +49,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
"for @synchronized"));
auto report =
llvm::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
- bugreporter::trackNullOrUndefValue(N, Ex, *report);
+ bugreporter::trackExpressionValue(N, Ex, *report);
C.emitReport(std::move(report));
}
return;
@@ -73,7 +73,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
"(no synchronization will occur)"));
auto report =
llvm::make_unique<BugReport>(*BT_null, BT_null->getDescription(), N);
- bugreporter::trackNullOrUndefValue(N, Ex, *report);
+ bugreporter::trackExpressionValue(N, Ex, *report);
C.emitReport(std::move(report));
return;
@@ -89,6 +89,6 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
}
void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
- if (mgr.getLangOpts().ObjC2)
+ if (mgr.getLangOpts().ObjC)
mgr.registerChecker<ObjCAtSyncChecker>();
}
diff --git a/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
index 81bcda51b8f8..0424958f8e65 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
@@ -27,7 +27,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
diff --git a/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
index e4737fcee7fb..34ce47823d51 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
@@ -11,7 +11,7 @@
// 'CFDictionary', 'CFSet' APIs.
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/TargetInfo.h"
diff --git a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index fb05ca630b45..1c8c0d8dedda 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -16,7 +16,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -57,6 +57,9 @@ public:
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind) const;
+
+ void printState(raw_ostream &OS, ProgramStateRef State,
+ const char *NL, const char *Sep) const;
};
} // end anonymous namespace
@@ -144,6 +147,8 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
initBugType();
auto R = llvm::make_unique<BugReport>(*BT, "Index is out of bounds", N);
R->addRange(IdxExpr->getSourceRange());
+ bugreporter::trackExpressionValue(N, IdxExpr, *R,
+ /*EnableNullFPSuppression=*/false);
C.emitReport(std::move(R));
return;
}
@@ -166,6 +171,18 @@ ObjCContainersChecker::checkPointerEscape(ProgramStateRef State,
return State;
}
+void ObjCContainersChecker::printState(raw_ostream &OS, ProgramStateRef State,
+ const char *NL, const char *Sep) const {
+ ArraySizeMapTy Map = State->get<ArraySizeMap>();
+ if (Map.isEmpty())
+ return;
+
+ OS << Sep << "ObjC container sizes :" << NL;
+ for (auto I : Map) {
+ OS << I.first << " : " << I.second << NL;
+ }
+}
+
/// Register checker.
void ento::registerObjCContainersChecker(CheckerManager &mgr) {
mgr.registerChecker<ObjCContainersChecker>();
diff --git a/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
index d01c6ae6e093..d383302b2790 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
diff --git a/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp
index dfd2c9afe7fb..018d3fcfceb9 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 629520437369..efa804220765 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -36,7 +36,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
index fcba3b33f3e0..9058784dd345 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -72,7 +72,6 @@ public:
Satisfied(false) {}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -247,8 +246,7 @@ ObjCSuperDeallocChecker::isSuperDeallocMessage(const ObjCMethodCall &M) const {
std::shared_ptr<PathDiagnosticPiece>
SuperDeallocBRVisitor::VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
- BugReporterContext &BRC, BugReport &BR) {
+ BugReporterContext &BRC, BugReport &) {
if (Satisfied)
return nullptr;
@@ -257,7 +255,8 @@ SuperDeallocBRVisitor::VisitNode(const ExplodedNode *Succ,
bool CalledNow =
Succ->getState()->contains<CalledSuperDealloc>(ReceiverSymbol);
bool CalledBefore =
- Pred->getState()->contains<CalledSuperDealloc>(ReceiverSymbol);
+ Succ->getFirstPred()->getState()->contains<CalledSuperDealloc>(
+ ReceiverSymbol);
// Is Succ the node on which the analyzer noted that [super dealloc] was
// called on ReceiverSymbol?
diff --git a/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
index c6da37eac0c0..7f7b45316087 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -98,7 +98,7 @@ static void Scan(IvarUsageMap &M, const DeclContext *C, const FileID FID,
SourceManager &SM) {
for (const auto *I : C->decls())
if (const auto *FD = dyn_cast<FunctionDecl>(I)) {
- SourceLocation L = FD->getLocStart();
+ SourceLocation L = FD->getBeginLoc();
if (SM.getFileID(L) == FID)
Scan(M, FD->getBody());
}
diff --git a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index f69f3492edb1..211db392bf71 100644
--- a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecordLayout.h"
@@ -41,7 +41,8 @@ public:
BugReporter &BRArg) const {
BR = &BRArg;
AllowedPad =
- MGR.getAnalyzerOptions().getOptionAsInteger("AllowedPad", 24, this);
+ MGR.getAnalyzerOptions()
+ .getCheckerIntegerOption("AllowedPad", 24, this);
assert(AllowedPad >= 0 && "AllowedPad option should be non-negative");
// The calls to checkAST* from AnalysisConsumer don't
@@ -75,6 +76,20 @@ public:
if (shouldSkipDecl(RD))
return;
+ // TODO: Figure out why we are going through declarations and not only
+ // definitions.
+ if (!(RD = RD->getDefinition()))
+ return;
+
+ // This is the simplest correct case: a class with no fields and one base
+ // class. Other cases are more complicated because of how the base classes
+ // & fields might interact, so we don't bother dealing with them.
+ // TODO: Support other combinations of base classes and fields.
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ if (CXXRD->field_empty() && CXXRD->getNumBases() == 1)
+ return visitRecord(CXXRD->bases().begin()->getType()->getAsRecordDecl(),
+ PadMultiplier);
+
auto &ASTContext = RD->getASTContext();
const ASTRecordLayout &RL = ASTContext.getASTRecordLayout(RD);
assert(llvm::isPowerOf2_64(RL.getAlignment().getQuantity()));
@@ -112,12 +127,15 @@ public:
if (RT == nullptr)
return;
- // TODO: Recurse into the fields and base classes to see if any
- // of those have excess padding.
+ // TODO: Recurse into the fields to see if they have excess padding.
visitRecord(RT->getDecl(), Elts);
}
bool shouldSkipDecl(const RecordDecl *RD) const {
+ // TODO: Figure out why we are going through declarations and not only
+ // definitions.
+ if (!(RD = RD->getDefinition()))
+ return true;
auto Location = RD->getLocation();
// If the construct doesn't have a source file, then it's not something
// we want to diagnose.
@@ -132,13 +150,14 @@ public:
// Not going to attempt to optimize unions.
if (RD->isUnion())
return true;
- // How do you reorder fields if you haven't got any?
- if (RD->field_empty())
- return true;
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
// Tail padding with base classes ends up being very complicated.
- // We will skip objects with base classes for now.
- if (CXXRD->getNumBases() != 0)
+ // We will skip objects with base classes for now, unless they do not
+ // have fields.
+ // TODO: Handle more base class scenarios.
+ if (!CXXRD->field_empty() && CXXRD->getNumBases() != 0)
+ return true;
+ if (CXXRD->field_empty() && CXXRD->getNumBases() != 1)
return true;
// Virtual bases are complicated, skipping those for now.
if (CXXRD->getNumVBases() != 0)
@@ -150,6 +169,10 @@ public:
if (CXXRD->getTypeForDecl()->isInstantiationDependentType())
return true;
}
+ // How do you reorder fields if you haven't got any?
+ else if (RD->field_empty())
+ return true;
+
auto IsTrickyField = [](const FieldDecl *FD) -> bool {
// Bitfield layout is hard.
if (FD->isBitField())
@@ -237,7 +260,7 @@ public:
};
std::transform(RD->field_begin(), RD->field_end(),
std::back_inserter(Fields), GatherSizesAndAlignments);
- llvm::sort(Fields.begin(), Fields.end());
+ llvm::sort(Fields);
// This lets us skip over vptrs and non-virtual bases,
// so that we can just worry about the fields in our object.
// Note that this does cause us to miss some cases where we
@@ -323,7 +346,7 @@ public:
BR->emitReport(std::move(Report));
}
};
-}
+} // namespace
void ento::registerPaddingChecker(CheckerManager &Mgr) {
Mgr.registerChecker<PaddingChecker>();
diff --git a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 63f82b275ba2..de3a16ebc729 100644
--- a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -112,7 +112,7 @@ PointerArithChecker::getPointedRegion(const MemRegion *Region,
}
/// Checks whether a region is the part of an array.
-/// In case there is a dericed to base cast above the array element, the
+/// In case there is a derived to base cast above the array element, the
/// Polymorphic output value is set to true. AKind output value is set to the
/// allocation kind of the inspected region.
const MemRegion *PointerArithChecker::getArrayRegion(const MemRegion *Region,
diff --git a/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index 9aa5348e4c34..41490e45f241 100644
--- a/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 10ab952e069b..66cc37278809 100644
--- a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
deleted file mode 100644
index 9c85c0983723..000000000000
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ /dev/null
@@ -1,4156 +0,0 @@
-//==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the methods for RetainCountChecker, which implements
-// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
-//
-//===----------------------------------------------------------------------===//
-
-#include "AllocationDiagnostics.h"
-#include "ClangSACheckers.h"
-#include "SelectorExtras.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/ImmutableList.h"
-#include "llvm/ADT/ImmutableMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include <cstdarg>
-#include <utility>
-
-using namespace clang;
-using namespace ento;
-using namespace objc_retain;
-using llvm::StrInStrNoCase;
-
-//===----------------------------------------------------------------------===//
-// Adapters for FoldingSet.
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-template <> struct FoldingSetTrait<ArgEffect> {
-static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
- ID.AddInteger((unsigned) X);
-}
-};
-template <> struct FoldingSetTrait<RetEffect> {
- static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
- ID.AddInteger((unsigned) X.getKind());
- ID.AddInteger((unsigned) X.getObjKind());
-}
-};
-} // end llvm namespace
-
-//===----------------------------------------------------------------------===//
-// Reference-counting logic (typestate + counts).
-//===----------------------------------------------------------------------===//
-
-/// ArgEffects summarizes the effects of a function/method call on all of
-/// its arguments.
-typedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
-
-namespace {
-class RefVal {
-public:
- enum Kind {
- Owned = 0, // Owning reference.
- NotOwned, // Reference is not owned by still valid (not freed).
- Released, // Object has been released.
- ReturnedOwned, // Returned object passes ownership to caller.
- ReturnedNotOwned, // Return object does not pass ownership to caller.
- ERROR_START,
- ErrorDeallocNotOwned, // -dealloc called on non-owned object.
- ErrorDeallocGC, // Calling -dealloc with GC enabled.
- ErrorUseAfterRelease, // Object used after released.
- ErrorReleaseNotOwned, // Release of an object that was not owned.
- ERROR_LEAK_START,
- ErrorLeak, // A memory leak due to excessive reference counts.
- ErrorLeakReturned, // A memory leak due to the returning method not having
- // the correct naming conventions.
- ErrorGCLeakReturned,
- ErrorOverAutorelease,
- ErrorReturnedNotOwned
- };
-
- /// Tracks how an object referenced by an ivar has been used.
- ///
- /// This accounts for us not knowing if an arbitrary ivar is supposed to be
- /// stored at +0 or +1.
- enum class IvarAccessHistory {
- None,
- AccessedDirectly,
- ReleasedAfterDirectAccess
- };
-
-private:
- /// The number of outstanding retains.
- unsigned Cnt;
- /// The number of outstanding autoreleases.
- unsigned ACnt;
- /// The (static) type of the object at the time we started tracking it.
- QualType T;
-
- /// The current state of the object.
- ///
- /// See the RefVal::Kind enum for possible values.
- unsigned RawKind : 5;
-
- /// The kind of object being tracked (CF or ObjC), if known.
- ///
- /// See the RetEffect::ObjKind enum for possible values.
- unsigned RawObjectKind : 2;
-
- /// True if the current state and/or retain count may turn out to not be the
- /// best possible approximation of the reference counting state.
- ///
- /// If true, the checker may decide to throw away ("override") this state
- /// in favor of something else when it sees the object being used in new ways.
- ///
- /// This setting should not be propagated to state derived from this state.
- /// Once we start deriving new states, it would be inconsistent to override
- /// them.
- unsigned RawIvarAccessHistory : 2;
-
- RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t,
- IvarAccessHistory IvarAccess)
- : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
- RawObjectKind(static_cast<unsigned>(o)),
- RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
- assert(getKind() == k && "not enough bits for the kind");
- assert(getObjKind() == o && "not enough bits for the object kind");
- assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
- }
-
-public:
- Kind getKind() const { return static_cast<Kind>(RawKind); }
-
- RetEffect::ObjKind getObjKind() const {
- return static_cast<RetEffect::ObjKind>(RawObjectKind);
- }
-
- unsigned getCount() const { return Cnt; }
- unsigned getAutoreleaseCount() const { return ACnt; }
- unsigned getCombinedCounts() const { return Cnt + ACnt; }
- void clearCounts() {
- Cnt = 0;
- ACnt = 0;
- }
- void setCount(unsigned i) {
- Cnt = i;
- }
- void setAutoreleaseCount(unsigned i) {
- ACnt = i;
- }
-
- QualType getType() const { return T; }
-
- /// Returns what the analyzer knows about direct accesses to a particular
- /// instance variable.
- ///
- /// If the object with this refcount wasn't originally from an Objective-C
- /// ivar region, this should always return IvarAccessHistory::None.
- IvarAccessHistory getIvarAccessHistory() const {
- return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
- }
-
- bool isOwned() const {
- return getKind() == Owned;
- }
-
- bool isNotOwned() const {
- return getKind() == NotOwned;
- }
-
- bool isReturnedOwned() const {
- return getKind() == ReturnedOwned;
- }
-
- bool isReturnedNotOwned() const {
- return getKind() == ReturnedNotOwned;
- }
-
- /// Create a state for an object whose lifetime is the responsibility of the
- /// current function, at least partially.
- ///
- /// Most commonly, this is an owned object with a retain count of +1.
- static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
- unsigned Count = 1) {
- return RefVal(Owned, o, Count, 0, t, IvarAccessHistory::None);
- }
-
- /// Create a state for an object whose lifetime is not the responsibility of
- /// the current function.
- ///
- /// Most commonly, this is an unowned object with a retain count of +0.
- static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
- unsigned Count = 0) {
- return RefVal(NotOwned, o, Count, 0, t, IvarAccessHistory::None);
- }
-
- RefVal operator-(size_t i) const {
- return RefVal(getKind(), getObjKind(), getCount() - i,
- getAutoreleaseCount(), getType(), getIvarAccessHistory());
- }
-
- RefVal operator+(size_t i) const {
- return RefVal(getKind(), getObjKind(), getCount() + i,
- getAutoreleaseCount(), getType(), getIvarAccessHistory());
- }
-
- RefVal operator^(Kind k) const {
- return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
- getType(), getIvarAccessHistory());
- }
-
- RefVal autorelease() const {
- return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
- getType(), getIvarAccessHistory());
- }
-
- RefVal withIvarAccess() const {
- assert(getIvarAccessHistory() == IvarAccessHistory::None);
- return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
- getType(), IvarAccessHistory::AccessedDirectly);
- }
-
- RefVal releaseViaIvar() const {
- assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
- return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
- getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
- }
-
- // Comparison, profiling, and pretty-printing.
-
- bool hasSameState(const RefVal &X) const {
- return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
- getIvarAccessHistory() == X.getIvarAccessHistory();
- }
-
- bool operator==(const RefVal& X) const {
- return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.Add(T);
- ID.AddInteger(RawKind);
- ID.AddInteger(Cnt);
- ID.AddInteger(ACnt);
- ID.AddInteger(RawObjectKind);
- ID.AddInteger(RawIvarAccessHistory);
- }
-
- void print(raw_ostream &Out) const;
-};
-
-void RefVal::print(raw_ostream &Out) const {
- if (!T.isNull())
- Out << "Tracked " << T.getAsString() << '/';
-
- switch (getKind()) {
- default: llvm_unreachable("Invalid RefVal kind");
- case Owned: {
- Out << "Owned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case NotOwned: {
- Out << "NotOwned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case ReturnedOwned: {
- Out << "ReturnedOwned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case ReturnedNotOwned: {
- Out << "ReturnedNotOwned";
- unsigned cnt = getCount();
- if (cnt) Out << " (+ " << cnt << ")";
- break;
- }
-
- case Released:
- Out << "Released";
- break;
-
- case ErrorDeallocGC:
- Out << "-dealloc (GC)";
- break;
-
- case ErrorDeallocNotOwned:
- Out << "-dealloc (not-owned)";
- break;
-
- case ErrorLeak:
- Out << "Leaked";
- break;
-
- case ErrorLeakReturned:
- Out << "Leaked (Bad naming)";
- break;
-
- case ErrorGCLeakReturned:
- Out << "Leaked (GC-ed at return)";
- break;
-
- case ErrorUseAfterRelease:
- Out << "Use-After-Release [ERROR]";
- break;
-
- case ErrorReleaseNotOwned:
- Out << "Release of Not-Owned [ERROR]";
- break;
-
- case RefVal::ErrorOverAutorelease:
- Out << "Over-autoreleased";
- break;
-
- case RefVal::ErrorReturnedNotOwned:
- Out << "Non-owned object returned instead of owned";
- break;
- }
-
- switch (getIvarAccessHistory()) {
- case IvarAccessHistory::None:
- break;
- case IvarAccessHistory::AccessedDirectly:
- Out << " [direct ivar access]";
- break;
- case IvarAccessHistory::ReleasedAfterDirectAccess:
- Out << " [released after direct ivar access]";
- }
-
- if (ACnt) {
- Out << " [autorelease -" << ACnt << ']';
- }
-}
-} //end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// RefBindings - State used to track object reference counts.
-//===----------------------------------------------------------------------===//
-
-REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
-
-static inline const RefVal *getRefBinding(ProgramStateRef State,
- SymbolRef Sym) {
- return State->get<RefBindings>(Sym);
-}
-
-static inline ProgramStateRef setRefBinding(ProgramStateRef State,
- SymbolRef Sym, RefVal Val) {
- return State->set<RefBindings>(Sym, Val);
-}
-
-static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
- return State->remove<RefBindings>(Sym);
-}
-
-//===----------------------------------------------------------------------===//
-// Function/Method behavior summaries.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class RetainSummary {
- /// Args - a map of (index, ArgEffect) pairs, where index
- /// specifies the argument (starting from 0). This can be sparsely
- /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
- ArgEffects Args;
-
- /// DefaultArgEffect - The default ArgEffect to apply to arguments that
- /// do not have an entry in Args.
- ArgEffect DefaultArgEffect;
-
- /// Receiver - If this summary applies to an Objective-C message expression,
- /// this is the effect applied to the state of the receiver.
- ArgEffect Receiver;
-
- /// Ret - The effect on the return value. Used to indicate if the
- /// function/method call returns a new tracked symbol.
- RetEffect Ret;
-
-public:
- RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
- ArgEffect ReceiverEff)
- : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
-
- /// getArg - Return the argument effect on the argument specified by
- /// idx (starting from 0).
- ArgEffect getArg(unsigned idx) const {
- if (const ArgEffect *AE = Args.lookup(idx))
- return *AE;
-
- return DefaultArgEffect;
- }
-
- void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
- Args = af.add(Args, idx, e);
- }
-
- /// setDefaultArgEffect - Set the default argument effect.
- void setDefaultArgEffect(ArgEffect E) {
- DefaultArgEffect = E;
- }
-
- /// getRetEffect - Returns the effect on the return value of the call.
- RetEffect getRetEffect() const { return Ret; }
-
- /// setRetEffect - Set the effect of the return value of the call.
- void setRetEffect(RetEffect E) { Ret = E; }
-
-
- /// Sets the effect on the receiver of the message.
- void setReceiverEffect(ArgEffect e) { Receiver = e; }
-
- /// getReceiverEffect - Returns the effect on the receiver of the call.
- /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
- ArgEffect getReceiverEffect() const { return Receiver; }
-
- /// Test if two retain summaries are identical. Note that merely equivalent
- /// summaries are not necessarily identical (for example, if an explicit
- /// argument effect matches the default effect).
- bool operator==(const RetainSummary &Other) const {
- return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
- Receiver == Other.Receiver && Ret == Other.Ret;
- }
-
- /// Profile this summary for inclusion in a FoldingSet.
- void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.Add(Args);
- ID.Add(DefaultArgEffect);
- ID.Add(Receiver);
- ID.Add(Ret);
- }
-
- /// A retain summary is simple if it has no ArgEffects other than the default.
- bool isSimple() const {
- return Args.isEmpty();
- }
-
-private:
- ArgEffects getArgEffects() const { return Args; }
- ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
-
- friend class RetainSummaryManager;
- friend class RetainCountChecker;
-};
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// Data structures for constructing summaries.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class ObjCSummaryKey {
- IdentifierInfo* II;
- Selector S;
-public:
- ObjCSummaryKey(IdentifierInfo* ii, Selector s)
- : II(ii), S(s) {}
-
- ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
- : II(d ? d->getIdentifier() : nullptr), S(s) {}
-
- ObjCSummaryKey(Selector s)
- : II(nullptr), S(s) {}
-
- IdentifierInfo *getIdentifier() const { return II; }
- Selector getSelector() const { return S; }
-};
-} // end anonymous namespace
-
-namespace llvm {
-template <> struct DenseMapInfo<ObjCSummaryKey> {
- static inline ObjCSummaryKey getEmptyKey() {
- return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
- DenseMapInfo<Selector>::getEmptyKey());
- }
-
- static inline ObjCSummaryKey getTombstoneKey() {
- return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
- DenseMapInfo<Selector>::getTombstoneKey());
- }
-
- static unsigned getHashValue(const ObjCSummaryKey &V) {
- typedef std::pair<IdentifierInfo*, Selector> PairTy;
- return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
- V.getSelector()));
- }
-
- static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
- return LHS.getIdentifier() == RHS.getIdentifier() &&
- LHS.getSelector() == RHS.getSelector();
- }
-
-};
-} // end llvm namespace
-
-namespace {
-class ObjCSummaryCache {
- typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
- MapTy M;
-public:
- ObjCSummaryCache() {}
-
- const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
- // Do a lookup with the (D,S) pair. If we find a match return
- // the iterator.
- ObjCSummaryKey K(D, S);
- MapTy::iterator I = M.find(K);
-
- if (I != M.end())
- return I->second;
- if (!D)
- return nullptr;
-
- // Walk the super chain. If we find a hit with a parent, we'll end
- // up returning that summary. We actually allow that key (null,S), as
- // we cache summaries for the null ObjCInterfaceDecl* to allow us to
- // generate initial summaries without having to worry about NSObject
- // being declared.
- // FIXME: We may change this at some point.
- for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
- if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
- break;
-
- if (!C)
- return nullptr;
- }
-
- // Cache the summary with original key to make the next lookup faster
- // and return the iterator.
- const RetainSummary *Summ = I->second;
- M[K] = Summ;
- return Summ;
- }
-
- const RetainSummary *find(IdentifierInfo* II, Selector S) {
- // FIXME: Class method lookup. Right now we don't have a good way
- // of going between IdentifierInfo* and the class hierarchy.
- MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
-
- if (I == M.end())
- I = M.find(ObjCSummaryKey(S));
-
- return I == M.end() ? nullptr : I->second;
- }
-
- const RetainSummary *& operator[](ObjCSummaryKey K) {
- return M[K];
- }
-
- const RetainSummary *& operator[](Selector S) {
- return M[ ObjCSummaryKey(S) ];
- }
-};
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// Data structures for managing collections of summaries.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class RetainSummaryManager {
-
- //==-----------------------------------------------------------------==//
- // Typedefs.
- //==-----------------------------------------------------------------==//
-
- typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
- FuncSummariesTy;
-
- typedef ObjCSummaryCache ObjCMethodSummariesTy;
-
- typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
-
- //==-----------------------------------------------------------------==//
- // Data.
- //==-----------------------------------------------------------------==//
-
- /// Ctx - The ASTContext object for the analyzed ASTs.
- ASTContext &Ctx;
-
- /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
- const bool GCEnabled;
-
- /// Records whether or not the analyzed code runs in ARC mode.
- const bool ARCEnabled;
-
- /// FuncSummaries - A map from FunctionDecls to summaries.
- FuncSummariesTy FuncSummaries;
-
- /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
- /// to summaries.
- ObjCMethodSummariesTy ObjCClassMethodSummaries;
-
- /// ObjCMethodSummaries - A map from selectors to summaries.
- ObjCMethodSummariesTy ObjCMethodSummaries;
-
- /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
- /// and all other data used by the checker.
- llvm::BumpPtrAllocator BPAlloc;
-
- /// AF - A factory for ArgEffects objects.
- ArgEffects::Factory AF;
-
- /// ScratchArgs - A holding buffer for construct ArgEffects.
- ArgEffects ScratchArgs;
-
- /// ObjCAllocRetE - Default return effect for methods returning Objective-C
- /// objects.
- RetEffect ObjCAllocRetE;
-
- /// ObjCInitRetE - Default return effect for init methods returning
- /// Objective-C objects.
- RetEffect ObjCInitRetE;
-
- /// SimpleSummaries - Used for uniquing summaries that don't have special
- /// effects.
- llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
-
- //==-----------------------------------------------------------------==//
- // Methods.
- //==-----------------------------------------------------------------==//
-
- /// getArgEffects - Returns a persistent ArgEffects object based on the
- /// data in ScratchArgs.
- ArgEffects getArgEffects();
-
- enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
-
- const RetainSummary *getUnarySummary(const FunctionType* FT,
- UnaryFuncKind func);
-
- const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
- const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
- const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
-
- const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
-
- const RetainSummary *getPersistentSummary(RetEffect RetEff,
- ArgEffect ReceiverEff = DoNothing,
- ArgEffect DefaultEff = MayEscape) {
- RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
- return getPersistentSummary(Summ);
- }
-
- const RetainSummary *getDoNothingSummary() {
- return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- }
-
- const RetainSummary *getDefaultSummary() {
- return getPersistentSummary(RetEffect::MakeNoRet(),
- DoNothing, MayEscape);
- }
-
- const RetainSummary *getPersistentStopSummary() {
- return getPersistentSummary(RetEffect::MakeNoRet(),
- StopTracking, StopTracking);
- }
-
- void InitializeClassMethodSummaries();
- void InitializeMethodSummaries();
-private:
- void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
- ObjCClassMethodSummaries[S] = Summ;
- }
-
- void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
- ObjCMethodSummaries[S] = Summ;
- }
-
- void addClassMethSummary(const char* Cls, const char* name,
- const RetainSummary *Summ, bool isNullary = true) {
- IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
- Selector S = isNullary ? GetNullarySelector(name, Ctx)
- : GetUnarySelector(name, Ctx);
- ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
- }
-
- void addInstMethSummary(const char* Cls, const char* nullaryName,
- const RetainSummary *Summ) {
- IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
- Selector S = GetNullarySelector(nullaryName, Ctx);
- ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
- }
-
- template <typename... Keywords>
- void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
- const RetainSummary *Summ, Keywords *... Kws) {
- Selector S = getKeywordSelector(Ctx, Kws...);
- Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
- }
-
- template <typename... Keywords>
- void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
- Keywords *... Kws) {
- addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
- }
-
- template <typename... Keywords>
- void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
- Keywords *... Kws) {
- addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
- Kws...);
- }
-
- template <typename... Keywords>
- void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
- Keywords *... Kws) {
- addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
- }
-
-public:
-
- RetainSummaryManager(ASTContext &ctx, bool gcenabled, bool usesARC)
- : Ctx(ctx),
- GCEnabled(gcenabled),
- ARCEnabled(usesARC),
- AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
- ObjCAllocRetE(gcenabled
- ? RetEffect::MakeGCNotOwned()
- : (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
- : RetEffect::MakeOwned(RetEffect::ObjC))),
- ObjCInitRetE(gcenabled
- ? RetEffect::MakeGCNotOwned()
- : (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
- : RetEffect::MakeOwnedWhenTrackedReceiver())) {
- InitializeClassMethodSummaries();
- InitializeMethodSummaries();
- }
-
- const RetainSummary *getSummary(const CallEvent &Call,
- ProgramStateRef State = nullptr);
-
- const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
-
- const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
- const ObjCMethodDecl *MD,
- QualType RetTy,
- ObjCMethodSummariesTy &CachedSummaries);
-
- const RetainSummary *getInstanceMethodSummary(const ObjCMethodCall &M,
- ProgramStateRef State);
-
- const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
- assert(!M.isInstanceMessage());
- const ObjCInterfaceDecl *Class = M.getReceiverInterface();
-
- return getMethodSummary(M.getSelector(), Class, M.getDecl(),
- M.getResultType(), ObjCClassMethodSummaries);
- }
-
- /// getMethodSummary - This version of getMethodSummary is used to query
- /// the summary for the current method being analyzed.
- const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
- const ObjCInterfaceDecl *ID = MD->getClassInterface();
- Selector S = MD->getSelector();
- QualType ResultTy = MD->getReturnType();
-
- ObjCMethodSummariesTy *CachedSummaries;
- if (MD->isInstanceMethod())
- CachedSummaries = &ObjCMethodSummaries;
- else
- CachedSummaries = &ObjCClassMethodSummaries;
-
- return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
- }
-
- const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
- Selector S, QualType RetTy);
-
- /// Determine if there is a special return effect for this function or method.
- Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
- const Decl *D);
-
- void updateSummaryFromAnnotations(const RetainSummary *&Summ,
- const ObjCMethodDecl *MD);
-
- void updateSummaryFromAnnotations(const RetainSummary *&Summ,
- const FunctionDecl *FD);
-
- void updateSummaryForCall(const RetainSummary *&Summ,
- const CallEvent &Call);
-
- bool isGCEnabled() const { return GCEnabled; }
-
- bool isARCEnabled() const { return ARCEnabled; }
-
- bool isARCorGCEnabled() const { return GCEnabled || ARCEnabled; }
-
- RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
-
- friend class RetainSummaryTemplate;
-};
-
-// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
-// summaries. If a function or method looks like it has a default summary, but
-// it has annotations, the annotations are added to the stack-based template
-// and then copied into managed memory.
-class RetainSummaryTemplate {
- RetainSummaryManager &Manager;
- const RetainSummary *&RealSummary;
- RetainSummary ScratchSummary;
- bool Accessed;
-public:
- RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
- : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
-
- ~RetainSummaryTemplate() {
- if (Accessed)
- RealSummary = Manager.getPersistentSummary(ScratchSummary);
- }
-
- RetainSummary &operator*() {
- Accessed = true;
- return ScratchSummary;
- }
-
- RetainSummary *operator->() {
- Accessed = true;
- return &ScratchSummary;
- }
-};
-
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// Implementation of checker data structures.
-//===----------------------------------------------------------------------===//
-
-ArgEffects RetainSummaryManager::getArgEffects() {
- ArgEffects AE = ScratchArgs;
- ScratchArgs = AF.getEmptyMap();
- return AE;
-}
-
-const RetainSummary *
-RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
- // Unique "simple" summaries -- those without ArgEffects.
- if (OldSumm.isSimple()) {
- llvm::FoldingSetNodeID ID;
- OldSumm.Profile(ID);
-
- void *Pos;
- CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
-
- if (!N) {
- N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
- new (N) CachedSummaryNode(OldSumm);
- SimpleSummaries.InsertNode(N, Pos);
- }
-
- return &N->getValue();
- }
-
- RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
- new (Summ) RetainSummary(OldSumm);
- return Summ;
-}
-
-//===----------------------------------------------------------------------===//
-// Summary creation for functions (largely uses of Core Foundation).
-//===----------------------------------------------------------------------===//
-
-static bool isRetain(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("retain") || FName.endswith_lower("retain");
-}
-
-static bool isRelease(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("release") || FName.endswith_lower("release");
-}
-
-static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("autorelease") ||
- FName.endswith_lower("autorelease");
-}
-
-static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName) {
- // FIXME: Remove FunctionDecl parameter.
- // FIXME: Is it really okay if MakeCollectable isn't a suffix?
- return FName.find_lower("MakeCollectable") != StringRef::npos;
-}
-
-static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
- switch (E) {
- case DoNothing:
- case Autorelease:
- case DecRefBridgedTransferred:
- case IncRef:
- case IncRefMsg:
- case MakeCollectable:
- case UnretainedOutParameter:
- case RetainedOutParameter:
- case MayEscape:
- case StopTracking:
- case StopTrackingHard:
- return StopTrackingHard;
- case DecRef:
- case DecRefAndStopTrackingHard:
- return DecRefAndStopTrackingHard;
- case DecRefMsg:
- case DecRefMsgAndStopTrackingHard:
- return DecRefMsgAndStopTrackingHard;
- case Dealloc:
- return Dealloc;
- }
-
- llvm_unreachable("Unknown ArgEffect kind");
-}
-
-void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
- const CallEvent &Call) {
- if (Call.hasNonZeroCallbackArg()) {
- ArgEffect RecEffect =
- getStopTrackingHardEquivalent(S->getReceiverEffect());
- ArgEffect DefEffect =
- getStopTrackingHardEquivalent(S->getDefaultArgEffect());
-
- ArgEffects CustomArgEffects = S->getArgEffects();
- for (ArgEffects::iterator I = CustomArgEffects.begin(),
- E = CustomArgEffects.end();
- I != E; ++I) {
- ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
- if (Translated != DefEffect)
- ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
- }
-
- RetEffect RE = RetEffect::MakeNoRetHard();
-
- // Special cases where the callback argument CANNOT free the return value.
- // This can generally only happen if we know that the callback will only be
- // called when the return value is already being deallocated.
- if (const SimpleFunctionCall *FC = dyn_cast<SimpleFunctionCall>(&Call)) {
- if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
- // When the CGBitmapContext is deallocated, the callback here will free
- // the associated data buffer.
- // The callback in dispatch_data_create frees the buffer, but not
- // the data object.
- if (Name->isStr("CGBitmapContextCreateWithData") ||
- Name->isStr("dispatch_data_create"))
- RE = S->getRetEffect();
- }
- }
-
- S = getPersistentSummary(RE, RecEffect, DefEffect);
- }
-
- // Special case '[super init];' and '[self init];'
- //
- // Even though calling '[super init]' without assigning the result to self
- // and checking if the parent returns 'nil' is a bad pattern, it is common.
- // Additionally, our Self Init checker already warns about it. To avoid
- // overwhelming the user with messages from both checkers, we model the case
- // of '[super init]' in cases when it is not consumed by another expression
- // as if the call preserves the value of 'self'; essentially, assuming it can
- // never fail and return 'nil'.
- // Note, we don't want to just stop tracking the value since we want the
- // RetainCount checker to report leaks and use-after-free if SelfInit checker
- // is turned off.
- if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {
- if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {
-
- // Check if the message is not consumed, we know it will not be used in
- // an assignment, ex: "self = [super init]".
- const Expr *ME = MC->getOriginExpr();
- const LocationContext *LCtx = MC->getLocationContext();
- ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
- if (!PM.isConsumedExpr(ME)) {
- RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
- ModifiableSummaryTemplate->setReceiverEffect(DoNothing);
- ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
- }
- }
- }
-}
-
-const RetainSummary *
-RetainSummaryManager::getSummary(const CallEvent &Call,
- ProgramStateRef State) {
- const RetainSummary *Summ;
- switch (Call.getKind()) {
- case CE_Function:
- Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());
- break;
- case CE_CXXMember:
- case CE_CXXMemberOperator:
- case CE_Block:
- case CE_CXXConstructor:
- case CE_CXXDestructor:
- case CE_CXXAllocator:
- // FIXME: These calls are currently unsupported.
- return getPersistentStopSummary();
- case CE_ObjCMessage: {
- const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
- if (Msg.isInstanceMessage())
- Summ = getInstanceMethodSummary(Msg, State);
- else
- Summ = getClassMethodSummary(Msg);
- break;
- }
- }
-
- updateSummaryForCall(Summ, Call);
-
- assert(Summ && "Unknown call type?");
- return Summ;
-}
-
-const RetainSummary *
-RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
- // If we don't know what function we're calling, use our default summary.
- if (!FD)
- return getDefaultSummary();
-
- // Look up a summary in our cache of FunctionDecls -> Summaries.
- FuncSummariesTy::iterator I = FuncSummaries.find(FD);
- if (I != FuncSummaries.end())
- return I->second;
-
- // No summary? Generate one.
- const RetainSummary *S = nullptr;
- bool AllowAnnotations = true;
-
- do {
- // We generate "stop" summaries for implicitly defined functions.
- if (FD->isImplicit()) {
- S = getPersistentStopSummary();
- break;
- }
-
- // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
- // function's type.
- const FunctionType* FT = FD->getType()->getAs<FunctionType>();
- const IdentifierInfo *II = FD->getIdentifier();
- if (!II)
- break;
-
- StringRef FName = II->getName();
-
- // Strip away preceding '_'. Doing this here will effect all the checks
- // down below.
- FName = FName.substr(FName.find_first_not_of('_'));
-
- // Inspect the result type.
- QualType RetTy = FT->getReturnType();
- std::string RetTyName = RetTy.getAsString();
-
- // FIXME: This should all be refactored into a chain of "summary lookup"
- // filters.
- assert(ScratchArgs.isEmpty());
-
- if (FName == "pthread_create" || FName == "pthread_setspecific") {
- // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
- // This will be addressed better with IPA.
- S = getPersistentStopSummary();
- } else if (FName == "NSMakeCollectable") {
- // Handle: id NSMakeCollectable(CFTypeRef)
- S = (RetTy->isObjCIdType())
- ? getUnarySummary(FT, cfmakecollectable)
- : getPersistentStopSummary();
- // The headers on OS X 10.8 use cf_consumed/ns_returns_retained,
- // but we can fully model NSMakeCollectable ourselves.
- AllowAnnotations = false;
- } else if (FName == "CFPlugInInstanceCreate") {
- S = getPersistentSummary(RetEffect::MakeNoRet());
- } else if (FName == "IORegistryEntrySearchCFProperty"
- || (RetTyName == "CFMutableDictionaryRef" && (
- FName == "IOBSDNameMatching" ||
- FName == "IOServiceMatching" ||
- FName == "IOServiceNameMatching" ||
- FName == "IORegistryEntryIDMatching" ||
- FName == "IOOpenFirmwarePathMatching"
- ))) {
- // Part of <rdar://problem/6961230>. (IOKit)
- // This should be addressed using a API table.
- S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF),
- DoNothing, DoNothing);
- } else if (FName == "IOServiceGetMatchingService" ||
- FName == "IOServiceGetMatchingServices") {
- // FIXES: <rdar://problem/6326900>
- // This should be addressed using a API table. This strcmp is also
- // a little gross, but there is no need to super optimize here.
- ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- } else if (FName == "IOServiceAddNotification" ||
- FName == "IOServiceAddMatchingNotification") {
- // Part of <rdar://problem/6961230>. (IOKit)
- // This should be addressed using a API table.
- ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- } else if (FName == "CVPixelBufferCreateWithBytes") {
- // FIXES: <rdar://problem/7283567>
- // Eventually this can be improved by recognizing that the pixel
- // buffer passed to CVPixelBufferCreateWithBytes is released via
- // a callback and doing full IPA to make sure this is done correctly.
- // FIXME: This function has an out parameter that returns an
- // allocated object.
- ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- } else if (FName == "CGBitmapContextCreateWithData") {
- // FIXES: <rdar://problem/7358899>
- // Eventually this can be improved by recognizing that 'releaseInfo'
- // passed to CGBitmapContextCreateWithData is released via
- // a callback and doing full IPA to make sure this is done correctly.
- ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
- S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF),
- DoNothing, DoNothing);
- } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
- // FIXES: <rdar://problem/7283567>
- // Eventually this can be improved by recognizing that the pixel
- // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
- // via a callback and doing full IPA to make sure this is done
- // correctly.
- ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- } else if (FName == "VTCompressionSessionEncodeFrame") {
- // The context argument passed to VTCompressionSessionEncodeFrame()
- // is passed to the callback specified when creating the session
- // (e.g. with VTCompressionSessionCreate()) which can release it.
- // To account for this possibility, conservatively stop tracking
- // the context.
- ScratchArgs = AF.add(ScratchArgs, 5, StopTracking);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- } else if (FName == "dispatch_set_context" ||
- FName == "xpc_connection_set_context") {
- // <rdar://problem/11059275> - The analyzer currently doesn't have
- // a good way to reason about the finalizer function for libdispatch.
- // If we pass a context object that is memory managed, stop tracking it.
- // <rdar://problem/13783514> - Same problem, but for XPC.
- // FIXME: this hack should possibly go away once we can handle
- // libdispatch and XPC finalizers.
- ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- } else if (FName.startswith("NSLog")) {
- S = getDoNothingSummary();
- } else if (FName.startswith("NS") &&
- (FName.find("Insert") != StringRef::npos)) {
- // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
- // be deallocated by NSMapRemove. (radar://11152419)
- ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
- ScratchArgs = AF.add(ScratchArgs, 2, StopTracking);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
- }
-
- // Did we get a summary?
- if (S)
- break;
-
- if (RetTy->isPointerType()) {
- // For CoreFoundation ('CF') types.
- if (cocoa::isRefType(RetTy, "CF", FName)) {
- if (isRetain(FD, FName)) {
- S = getUnarySummary(FT, cfretain);
- // CFRetain isn't supposed to be annotated. However, this may as well
- // be a user-made "safe" CFRetain function that is incorrectly
- // annotated as cf_returns_retained due to lack of better options.
- // We want to ignore such annotation.
- AllowAnnotations = false;
- } else if (isAutorelease(FD, FName)) {
- S = getUnarySummary(FT, cfautorelease);
- // The headers use cf_consumed, but we can fully model CFAutorelease
- // ourselves.
- AllowAnnotations = false;
- } else if (isMakeCollectable(FD, FName)) {
- S = getUnarySummary(FT, cfmakecollectable);
- AllowAnnotations = false;
- } else {
- S = getCFCreateGetRuleSummary(FD);
- }
-
- break;
- }
-
- // For CoreGraphics ('CG') and CoreVideo ('CV') types.
- if (cocoa::isRefType(RetTy, "CG", FName) ||
- cocoa::isRefType(RetTy, "CV", FName)) {
- if (isRetain(FD, FName))
- S = getUnarySummary(FT, cfretain);
- else
- S = getCFCreateGetRuleSummary(FD);
-
- break;
- }
-
- // For all other CF-style types, use the Create/Get
- // rule for summaries but don't support Retain functions
- // with framework-specific prefixes.
- if (coreFoundation::isCFObjectRef(RetTy)) {
- S = getCFCreateGetRuleSummary(FD);
- break;
- }
-
- if (FD->hasAttr<CFAuditedTransferAttr>()) {
- S = getCFCreateGetRuleSummary(FD);
- break;
- }
-
- break;
- }
-
- // Check for release functions, the only kind of functions that we care
- // about that don't return a pointer type.
- if (FName.size() >= 2 &&
- FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
- // Test for 'CGCF'.
- FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
-
- if (isRelease(FD, FName))
- S = getUnarySummary(FT, cfrelease);
- else {
- assert (ScratchArgs.isEmpty());
- // Remaining CoreFoundation and CoreGraphics functions.
- // We use to assume that they all strictly followed the ownership idiom
- // and that ownership cannot be transferred. While this is technically
- // correct, many methods allow a tracked object to escape. For example:
- //
- // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
- // CFDictionaryAddValue(y, key, x);
- // CFRelease(x);
- // ... it is okay to use 'x' since 'y' has a reference to it
- //
- // We handle this and similar cases with the follow heuristic. If the
- // function name contains "InsertValue", "SetValue", "AddValue",
- // "AppendValue", or "SetAttribute", then we assume that arguments may
- // "escape." This means that something else holds on to the object,
- // allowing it be used even after its local retain count drops to 0.
- ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
- StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
- StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
- StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
- StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
- ? MayEscape : DoNothing;
-
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
- }
- }
- }
- while (0);
-
- // If we got all the way here without any luck, use a default summary.
- if (!S)
- S = getDefaultSummary();
-
- // Annotations override defaults.
- if (AllowAnnotations)
- updateSummaryFromAnnotations(S, FD);
-
- FuncSummaries[FD] = S;
- return S;
-}
-
-const RetainSummary *
-RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
- if (coreFoundation::followsCreateRule(FD))
- return getCFSummaryCreateRule(FD);
-
- return getCFSummaryGetRule(FD);
-}
-
-const RetainSummary *
-RetainSummaryManager::getUnarySummary(const FunctionType* FT,
- UnaryFuncKind func) {
-
- // Sanity check that this is *really* a unary function. This can
- // happen if people do weird things.
- const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
- if (!FTP || FTP->getNumParams() != 1)
- return getPersistentStopSummary();
-
- assert (ScratchArgs.isEmpty());
-
- ArgEffect Effect;
- switch (func) {
- case cfretain: Effect = IncRef; break;
- case cfrelease: Effect = DecRef; break;
- case cfautorelease: Effect = Autorelease; break;
- case cfmakecollectable: Effect = MakeCollectable; break;
- }
-
- ScratchArgs = AF.add(ScratchArgs, 0, Effect);
- return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
-}
-
-const RetainSummary *
-RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
- assert (ScratchArgs.isEmpty());
-
- return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
-}
-
-const RetainSummary *
-RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
- assert (ScratchArgs.isEmpty());
- return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
- DoNothing, DoNothing);
-}
-
-/// Returns true if the declaration 'D' is annotated with 'rcAnnotation'.
-static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
- for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
- if (Ann->getAnnotation() == rcAnnotation)
- return true;
- }
- return false;
-}
-
-/// Returns true if the function declaration 'FD' contains
-/// 'rc_ownership_trusted_implementation' annotate attribute.
-static bool isTrustedReferenceCountImplementation(const FunctionDecl *FD) {
- return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
-}
-
-static bool isGeneralizedObjectRef(QualType Ty) {
- if (Ty.getAsString().substr(0, 4) == "isl_")
- return true;
- else
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Summary creation for Selectors.
-//===----------------------------------------------------------------------===//
-
-Optional<RetEffect>
-RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
- const Decl *D) {
- if (cocoa::isCocoaObjectRef(RetTy)) {
- if (D->hasAttr<NSReturnsRetainedAttr>())
- return ObjCAllocRetE;
-
- if (D->hasAttr<NSReturnsNotRetainedAttr>() ||
- D->hasAttr<NSReturnsAutoreleasedAttr>())
- return RetEffect::MakeNotOwned(RetEffect::ObjC);
-
- } else if (!RetTy->isPointerType()) {
- return None;
- }
-
- if (D->hasAttr<CFReturnsRetainedAttr>())
- return RetEffect::MakeOwned(RetEffect::CF);
- else if (hasRCAnnotation(D, "rc_ownership_returns_retained"))
- return RetEffect::MakeOwned(RetEffect::Generalized);
-
- if (D->hasAttr<CFReturnsNotRetainedAttr>())
- return RetEffect::MakeNotOwned(RetEffect::CF);
-
- return None;
-}
-
-void
-RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
- const FunctionDecl *FD) {
- if (!FD)
- return;
-
- assert(Summ && "Must have a summary to add annotations to.");
- RetainSummaryTemplate Template(Summ, *this);
-
- // Effects on the parameters.
- unsigned parm_idx = 0;
- for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
- pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
- const ParmVarDecl *pd = *pi;
- if (pd->hasAttr<NSConsumedAttr>())
- Template->addArg(AF, parm_idx, DecRefMsg);
- else if (pd->hasAttr<CFConsumedAttr>() ||
- hasRCAnnotation(pd, "rc_ownership_consumed"))
- Template->addArg(AF, parm_idx, DecRef);
- else if (pd->hasAttr<CFReturnsRetainedAttr>() ||
- hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
- QualType PointeeTy = pd->getType()->getPointeeType();
- if (!PointeeTy.isNull())
- if (coreFoundation::isCFObjectRef(PointeeTy))
- Template->addArg(AF, parm_idx, RetainedOutParameter);
- } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
- QualType PointeeTy = pd->getType()->getPointeeType();
- if (!PointeeTy.isNull())
- if (coreFoundation::isCFObjectRef(PointeeTy))
- Template->addArg(AF, parm_idx, UnretainedOutParameter);
- }
- }
-
- QualType RetTy = FD->getReturnType();
- if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
- Template->setRetEffect(*RetE);
-}
-
-void
-RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
- const ObjCMethodDecl *MD) {
- if (!MD)
- return;
-
- assert(Summ && "Must have a valid summary to add annotations to");
- RetainSummaryTemplate Template(Summ, *this);
-
- // Effects on the receiver.
- if (MD->hasAttr<NSConsumesSelfAttr>())
- Template->setReceiverEffect(DecRefMsg);
-
- // Effects on the parameters.
- unsigned parm_idx = 0;
- for (ObjCMethodDecl::param_const_iterator
- pi=MD->param_begin(), pe=MD->param_end();
- pi != pe; ++pi, ++parm_idx) {
- const ParmVarDecl *pd = *pi;
- if (pd->hasAttr<NSConsumedAttr>())
- Template->addArg(AF, parm_idx, DecRefMsg);
- else if (pd->hasAttr<CFConsumedAttr>()) {
- Template->addArg(AF, parm_idx, DecRef);
- } else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
- QualType PointeeTy = pd->getType()->getPointeeType();
- if (!PointeeTy.isNull())
- if (coreFoundation::isCFObjectRef(PointeeTy))
- Template->addArg(AF, parm_idx, RetainedOutParameter);
- } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
- QualType PointeeTy = pd->getType()->getPointeeType();
- if (!PointeeTy.isNull())
- if (coreFoundation::isCFObjectRef(PointeeTy))
- Template->addArg(AF, parm_idx, UnretainedOutParameter);
- }
- }
-
- QualType RetTy = MD->getReturnType();
- if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
- Template->setRetEffect(*RetE);
-}
-
-const RetainSummary *
-RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
- Selector S, QualType RetTy) {
- // Any special effects?
- ArgEffect ReceiverEff = DoNothing;
- RetEffect ResultEff = RetEffect::MakeNoRet();
-
- // Check the method family, and apply any default annotations.
- switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
- case OMF_None:
- case OMF_initialize:
- case OMF_performSelector:
- // Assume all Objective-C methods follow Cocoa Memory Management rules.
- // FIXME: Does the non-threaded performSelector family really belong here?
- // The selector could be, say, @selector(copy).
- if (cocoa::isCocoaObjectRef(RetTy))
- ResultEff = RetEffect::MakeNotOwned(RetEffect::ObjC);
- else if (coreFoundation::isCFObjectRef(RetTy)) {
- // ObjCMethodDecl currently doesn't consider CF objects as valid return
- // values for alloc, new, copy, or mutableCopy, so we have to
- // double-check with the selector. This is ugly, but there aren't that
- // many Objective-C methods that return CF objects, right?
- if (MD) {
- switch (S.getMethodFamily()) {
- case OMF_alloc:
- case OMF_new:
- case OMF_copy:
- case OMF_mutableCopy:
- ResultEff = RetEffect::MakeOwned(RetEffect::CF);
- break;
- default:
- ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
- break;
- }
- } else {
- ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
- }
- }
- break;
- case OMF_init:
- ResultEff = ObjCInitRetE;
- ReceiverEff = DecRefMsg;
- break;
- case OMF_alloc:
- case OMF_new:
- case OMF_copy:
- case OMF_mutableCopy:
- if (cocoa::isCocoaObjectRef(RetTy))
- ResultEff = ObjCAllocRetE;
- else if (coreFoundation::isCFObjectRef(RetTy))
- ResultEff = RetEffect::MakeOwned(RetEffect::CF);
- break;
- case OMF_autorelease:
- ReceiverEff = Autorelease;
- break;
- case OMF_retain:
- ReceiverEff = IncRefMsg;
- break;
- case OMF_release:
- ReceiverEff = DecRefMsg;
- break;
- case OMF_dealloc:
- ReceiverEff = Dealloc;
- break;
- case OMF_self:
- // -self is handled specially by the ExprEngine to propagate the receiver.
- break;
- case OMF_retainCount:
- case OMF_finalize:
- // These methods don't return objects.
- break;
- }
-
- // If one of the arguments in the selector has the keyword 'delegate' we
- // should stop tracking the reference count for the receiver. This is
- // because the reference count is quite possibly handled by a delegate
- // method.
- if (S.isKeywordSelector()) {
- for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
- StringRef Slot = S.getNameForSlot(i);
- if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
- if (ResultEff == ObjCInitRetE)
- ResultEff = RetEffect::MakeNoRetHard();
- else
- ReceiverEff = StopTrackingHard;
- }
- }
- }
-
- if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing &&
- ResultEff.getKind() == RetEffect::NoRet)
- return getDefaultSummary();
-
- return getPersistentSummary(ResultEff, ReceiverEff, MayEscape);
-}
-
-const RetainSummary *
-RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg,
- ProgramStateRef State) {
- const ObjCInterfaceDecl *ReceiverClass = nullptr;
-
- // We do better tracking of the type of the object than the core ExprEngine.
- // See if we have its type in our private state.
- // FIXME: Eventually replace the use of state->get<RefBindings> with
- // a generic API for reasoning about the Objective-C types of symbolic
- // objects.
- SVal ReceiverV = Msg.getReceiverSVal();
- if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
- if (const RefVal *T = getRefBinding(State, Sym))
- if (const ObjCObjectPointerType *PT =
- T->getType()->getAs<ObjCObjectPointerType>())
- ReceiverClass = PT->getInterfaceDecl();
-
- // If we don't know what kind of object this is, fall back to its static type.
- if (!ReceiverClass)
- ReceiverClass = Msg.getReceiverInterface();
-
- // FIXME: The receiver could be a reference to a class, meaning that
- // we should use the class method.
- // id x = [NSObject class];
- // [x performSelector:... withObject:... afterDelay:...];
- Selector S = Msg.getSelector();
- const ObjCMethodDecl *Method = Msg.getDecl();
- if (!Method && ReceiverClass)
- Method = ReceiverClass->getInstanceMethod(S);
-
- return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
- ObjCMethodSummaries);
-}
-
-const RetainSummary *
-RetainSummaryManager::getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
- const ObjCMethodDecl *MD, QualType RetTy,
- ObjCMethodSummariesTy &CachedSummaries) {
-
- // Look up a summary in our summary cache.
- const RetainSummary *Summ = CachedSummaries.find(ID, S);
-
- if (!Summ) {
- Summ = getStandardMethodSummary(MD, S, RetTy);
-
- // Annotations override defaults.
- updateSummaryFromAnnotations(Summ, MD);
-
- // Memoize the summary.
- CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
- }
-
- return Summ;
-}
-
-void RetainSummaryManager::InitializeClassMethodSummaries() {
- assert(ScratchArgs.isEmpty());
- // Create the [NSAssertionHandler currentHander] summary.
- addClassMethSummary("NSAssertionHandler", "currentHandler",
- getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
-
- // Create the [NSAutoreleasePool addObject:] summary.
- ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
- addClassMethSummary("NSAutoreleasePool", "addObject",
- getPersistentSummary(RetEffect::MakeNoRet(),
- DoNothing, Autorelease));
-}
-
-void RetainSummaryManager::InitializeMethodSummaries() {
-
- assert (ScratchArgs.isEmpty());
-
- // Create the "init" selector. It just acts as a pass-through for the
- // receiver.
- const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
- addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
-
- // awakeAfterUsingCoder: behaves basically like an 'init' method. It
- // claims the receiver and returns a retained object.
- addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
- InitSumm);
-
- // The next methods are allocators.
- const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
- const RetainSummary *CFAllocSumm =
- getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
-
- // Create the "retain" selector.
- RetEffect NoRet = RetEffect::MakeNoRet();
- const RetainSummary *Summ = getPersistentSummary(NoRet, IncRefMsg);
- addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
-
- // Create the "release" selector.
- Summ = getPersistentSummary(NoRet, DecRefMsg);
- addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
-
- // Create the -dealloc summary.
- Summ = getPersistentSummary(NoRet, Dealloc);
- addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
-
- // Create the "autorelease" selector.
- Summ = getPersistentSummary(NoRet, Autorelease);
- addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
-
- // For NSWindow, allocated objects are (initially) self-owned.
- // FIXME: For now we opt for false negatives with NSWindow, as these objects
- // self-own themselves. However, they only do this once they are displayed.
- // Thus, we need to track an NSWindow's display status.
- // This is tracked in <rdar://problem/6062711>.
- // See also http://llvm.org/bugs/show_bug.cgi?id=3714.
- const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
- StopTracking,
- StopTracking);
-
- addClassMethSummary("NSWindow", "alloc", NoTrackYet);
-
- // For NSPanel (which subclasses NSWindow), allocated objects are not
- // self-owned.
- // FIXME: For now we don't track NSPanels. object for the same reason
- // as for NSWindow objects.
- addClassMethSummary("NSPanel", "alloc", NoTrackYet);
-
- // For NSNull, objects returned by +null are singletons that ignore
- // retain/release semantics. Just don't track them.
- // <rdar://problem/12858915>
- addClassMethSummary("NSNull", "null", NoTrackYet);
-
- // Don't track allocated autorelease pools, as it is okay to prematurely
- // exit a method.
- addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
- addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
- addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
-
- // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
- addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType");
- addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType");
-
- // Create summaries for CIContext, 'createCGImage' and
- // 'createCGLayerWithSize'. These objects are CF objects, and are not
- // automatically garbage collected.
- addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect");
- addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",
- "format", "colorSpace");
- addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
-}
-
-//===----------------------------------------------------------------------===//
-// Error reporting.
-//===----------------------------------------------------------------------===//
-namespace {
- typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
- SummaryLogTy;
-
- //===-------------===//
- // Bug Descriptions. //
- //===-------------===//
-
- class CFRefBug : public BugType {
- protected:
- CFRefBug(const CheckerBase *checker, StringRef name)
- : BugType(checker, name, categories::MemoryCoreFoundationObjectiveC) {}
-
- public:
-
- // FIXME: Eventually remove.
- virtual const char *getDescription() const = 0;
-
- virtual bool isLeak() const { return false; }
- };
-
- class UseAfterRelease : public CFRefBug {
- public:
- UseAfterRelease(const CheckerBase *checker)
- : CFRefBug(checker, "Use-after-release") {}
-
- const char *getDescription() const override {
- return "Reference-counted object is used after it is released";
- }
- };
-
- class BadRelease : public CFRefBug {
- public:
- BadRelease(const CheckerBase *checker) : CFRefBug(checker, "Bad release") {}
-
- const char *getDescription() const override {
- return "Incorrect decrement of the reference count of an object that is "
- "not owned at this point by the caller";
- }
- };
-
- class DeallocGC : public CFRefBug {
- public:
- DeallocGC(const CheckerBase *checker)
- : CFRefBug(checker, "-dealloc called while using garbage collection") {}
-
- const char *getDescription() const override {
- return "-dealloc called while using garbage collection";
- }
- };
-
- class DeallocNotOwned : public CFRefBug {
- public:
- DeallocNotOwned(const CheckerBase *checker)
- : CFRefBug(checker, "-dealloc sent to non-exclusively owned object") {}
-
- const char *getDescription() const override {
- return "-dealloc sent to object that may be referenced elsewhere";
- }
- };
-
- class OverAutorelease : public CFRefBug {
- public:
- OverAutorelease(const CheckerBase *checker)
- : CFRefBug(checker, "Object autoreleased too many times") {}
-
- const char *getDescription() const override {
- return "Object autoreleased too many times";
- }
- };
-
- class ReturnedNotOwnedForOwned : public CFRefBug {
- public:
- ReturnedNotOwnedForOwned(const CheckerBase *checker)
- : CFRefBug(checker, "Method should return an owned object") {}
-
- const char *getDescription() const override {
- return "Object with a +0 retain count returned to caller where a +1 "
- "(owning) retain count is expected";
- }
- };
-
- class Leak : public CFRefBug {
- public:
- Leak(const CheckerBase *checker, StringRef name) : CFRefBug(checker, name) {
- // Leaks should not be reported if they are post-dominated by a sink.
- setSuppressOnSink(true);
- }
-
- const char *getDescription() const override { return ""; }
-
- bool isLeak() const override { return true; }
- };
-
- //===---------===//
- // Bug Reports. //
- //===---------===//
- class CFRefReportVisitor : public BugReporterVisitor {
- protected:
- SymbolRef Sym;
- const SummaryLogTy &SummaryLog;
- bool GCEnabled;
-
- public:
- CFRefReportVisitor(SymbolRef sym, bool gcEnabled, const SummaryLogTy &log)
- : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
-
- void Profile(llvm::FoldingSetNodeID &ID) const override {
- static int x = 0;
- ID.AddPointer(&x);
- ID.AddPointer(Sym);
- }
-
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override;
-
- std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) override;
- };
-
- class CFRefLeakReportVisitor : public CFRefReportVisitor {
- public:
- CFRefLeakReportVisitor(SymbolRef sym, bool GCEnabled,
- const SummaryLogTy &log)
- : CFRefReportVisitor(sym, GCEnabled, log) {}
-
- std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) override;
- };
-
- class CFRefReport : public BugReport {
- void addGCModeDescription(const LangOptions &LOpts, bool GCEnabled);
-
- public:
- CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
- const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
- bool registerVisitor = true)
- : BugReport(D, D.getDescription(), n) {
- if (registerVisitor)
- addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
- addGCModeDescription(LOpts, GCEnabled);
- }
-
- CFRefReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
- const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
- StringRef endText)
- : BugReport(D, D.getDescription(), endText, n) {
- addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
- addGCModeDescription(LOpts, GCEnabled);
- }
-
- llvm::iterator_range<ranges_iterator> getRanges() override {
- const CFRefBug& BugTy = static_cast<CFRefBug&>(getBugType());
- if (!BugTy.isLeak())
- return BugReport::getRanges();
- return llvm::make_range(ranges_iterator(), ranges_iterator());
- }
- };
-
- class CFRefLeakReport : public CFRefReport {
- const MemRegion* AllocBinding;
- const Stmt *AllocStmt;
-
- // Finds the function declaration where a leak warning for the parameter 'sym' should be raised.
- void deriveParamLocation(CheckerContext &Ctx, SymbolRef sym);
- // Finds the location where a leak warning for 'sym' should be raised.
- void deriveAllocLocation(CheckerContext &Ctx, SymbolRef sym);
- // Produces description of a leak warning which is printed on the console.
- void createDescription(CheckerContext &Ctx, bool GCEnabled, bool IncludeAllocationLine);
-
- public:
- CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled,
- const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
- CheckerContext &Ctx,
- bool IncludeAllocationLine);
-
- PathDiagnosticLocation getLocation(const SourceManager &SM) const override {
- assert(Location.isValid());
- return Location;
- }
- };
-} // end anonymous namespace
-
-void CFRefReport::addGCModeDescription(const LangOptions &LOpts,
- bool GCEnabled) {
- const char *GCModeDescription = nullptr;
-
- switch (LOpts.getGC()) {
- case LangOptions::GCOnly:
- assert(GCEnabled);
- GCModeDescription = "Code is compiled to only use garbage collection";
- break;
-
- case LangOptions::NonGC:
- assert(!GCEnabled);
- GCModeDescription = "Code is compiled to use reference counts";
- break;
-
- case LangOptions::HybridGC:
- if (GCEnabled) {
- GCModeDescription = "Code is compiled to use either garbage collection "
- "(GC) or reference counts (non-GC). The bug occurs "
- "with GC enabled";
- break;
- } else {
- GCModeDescription = "Code is compiled to use either garbage collection "
- "(GC) or reference counts (non-GC). The bug occurs "
- "in non-GC mode";
- break;
- }
- }
-
- assert(GCModeDescription && "invalid/unknown GC mode");
- addExtraText(GCModeDescription);
-}
-
-static bool isNumericLiteralExpression(const Expr *E) {
- // FIXME: This set of cases was copied from SemaExprObjC.
- return isa<IntegerLiteral>(E) ||
- isa<CharacterLiteral>(E) ||
- isa<FloatingLiteral>(E) ||
- isa<ObjCBoolLiteralExpr>(E) ||
- isa<CXXBoolLiteralExpr>(E);
-}
-
-static Optional<std::string> describeRegion(const MemRegion *MR) {
- if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
- return std::string(VR->getDecl()->getName());
- // Once we support more storage locations for bindings,
- // this would need to be improved.
- return None;
-}
-
-/// Returns true if this stack frame is for an Objective-C method that is a
-/// property getter or setter whose body has been synthesized by the analyzer.
-static bool isSynthesizedAccessor(const StackFrameContext *SFC) {
- auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
- if (!Method || !Method->isPropertyAccessor())
- return false;
-
- return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
-}
-
-std::shared_ptr<PathDiagnosticPiece>
-CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN,
- BugReporterContext &BRC, BugReport &BR) {
- // FIXME: We will eventually need to handle non-statement-based events
- // (__attribute__((cleanup))).
- if (!N->getLocation().getAs<StmtPoint>())
- return nullptr;
-
- // Check if the type state has changed.
- ProgramStateRef PrevSt = PrevN->getState();
- ProgramStateRef CurrSt = N->getState();
- const LocationContext *LCtx = N->getLocationContext();
-
- const RefVal* CurrT = getRefBinding(CurrSt, Sym);
- if (!CurrT) return nullptr;
-
- const RefVal &CurrV = *CurrT;
- const RefVal *PrevT = getRefBinding(PrevSt, Sym);
-
- // Create a string buffer to constain all the useful things we want
- // to tell the user.
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
-
- // This is the allocation site since the previous node had no bindings
- // for this symbol.
- if (!PrevT) {
- const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
-
- if (isa<ObjCIvarRefExpr>(S) &&
- isSynthesizedAccessor(LCtx->getStackFrame())) {
- S = LCtx->getStackFrame()->getCallSite();
- }
-
- if (isa<ObjCArrayLiteral>(S)) {
- os << "NSArray literal is an object with a +0 retain count";
- }
- else if (isa<ObjCDictionaryLiteral>(S)) {
- os << "NSDictionary literal is an object with a +0 retain count";
- }
- else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
- if (isNumericLiteralExpression(BL->getSubExpr()))
- os << "NSNumber literal is an object with a +0 retain count";
- else {
- const ObjCInterfaceDecl *BoxClass = nullptr;
- if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
- BoxClass = Method->getClassInterface();
-
- // We should always be able to find the boxing class interface,
- // but consider this future-proofing.
- if (BoxClass)
- os << *BoxClass << " b";
- else
- os << "B";
-
- os << "oxed expression produces an object with a +0 retain count";
- }
- }
- else if (isa<ObjCIvarRefExpr>(S)) {
- os << "Object loaded from instance variable";
- }
- else {
- if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
- // Get the name of the callee (if it is available).
- SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
- if (const FunctionDecl *FD = X.getAsFunctionDecl())
- os << "Call to function '" << *FD << '\'';
- else
- os << "function call";
- }
- else {
- assert(isa<ObjCMessageExpr>(S));
- CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
- CallEventRef<ObjCMethodCall> Call
- = Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
-
- switch (Call->getMessageKind()) {
- case OCM_Message:
- os << "Method";
- break;
- case OCM_PropertyAccess:
- os << "Property";
- break;
- case OCM_Subscript:
- os << "Subscript";
- break;
- }
- }
-
- if (CurrV.getObjKind() == RetEffect::CF) {
- os << " returns a Core Foundation object of type "
- << Sym->getType().getAsString() << " with a ";
- } else if (CurrV.getObjKind() == RetEffect::Generalized) {
- os << " returns an object of type " << Sym->getType().getAsString()
- << " with a ";
- } else {
- assert (CurrV.getObjKind() == RetEffect::ObjC);
- QualType T = Sym->getType();
- if (!isa<ObjCObjectPointerType>(T)) {
- os << " returns an Objective-C object with a ";
- } else {
- const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
- os << " returns an instance of "
- << PT->getPointeeType().getAsString() << " with a ";
- }
- }
-
- if (CurrV.isOwned()) {
- os << "+1 retain count";
-
- if (GCEnabled) {
- assert(CurrV.getObjKind() == RetEffect::CF);
- os << ". "
- "Core Foundation objects are not automatically garbage collected.";
- }
- }
- else {
- assert (CurrV.isNotOwned());
- os << "+0 retain count";
- }
- }
-
- PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
- N->getLocationContext());
- return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
- }
-
- // Gather up the effects that were performed on the object at this
- // program point
- SmallVector<ArgEffect, 2> AEffects;
-
- const ExplodedNode *OrigNode = BRC.getNodeResolver().getOriginalNode(N);
- if (const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
- // We only have summaries attached to nodes after evaluating CallExpr and
- // ObjCMessageExprs.
- const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
-
- if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
- // Iterate through the parameter expressions and see if the symbol
- // was ever passed as an argument.
- unsigned i = 0;
-
- for (CallExpr::const_arg_iterator AI=CE->arg_begin(), AE=CE->arg_end();
- AI!=AE; ++AI, ++i) {
-
- // Retrieve the value of the argument. Is it the symbol
- // we are interested in?
- if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
- continue;
-
- // We have an argument. Get the effect!
- AEffects.push_back(Summ->getArg(i));
- }
- }
- else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
- if (const Expr *receiver = ME->getInstanceReceiver())
- if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
- .getAsLocSymbol() == Sym) {
- // The symbol we are tracking is the receiver.
- AEffects.push_back(Summ->getReceiverEffect());
- }
- }
- }
-
- do {
- // Get the previous type state.
- RefVal PrevV = *PrevT;
-
- // Specially handle -dealloc.
- if (!GCEnabled && std::find(AEffects.begin(), AEffects.end(), Dealloc) !=
- AEffects.end()) {
- // Determine if the object's reference count was pushed to zero.
- assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
- // We may not have transitioned to 'release' if we hit an error.
- // This case is handled elsewhere.
- if (CurrV.getKind() == RefVal::Released) {
- assert(CurrV.getCombinedCounts() == 0);
- os << "Object released by directly sending the '-dealloc' message";
- break;
- }
- }
-
- // Specially handle CFMakeCollectable and friends.
- if (std::find(AEffects.begin(), AEffects.end(), MakeCollectable) !=
- AEffects.end()) {
- // Get the name of the function.
- const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
- SVal X =
- CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
- const FunctionDecl *FD = X.getAsFunctionDecl();
-
- if (GCEnabled) {
- // Determine if the object's reference count was pushed to zero.
- assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
-
- os << "In GC mode a call to '" << *FD
- << "' decrements an object's retain count and registers the "
- "object with the garbage collector. ";
-
- if (CurrV.getKind() == RefVal::Released) {
- assert(CurrV.getCount() == 0);
- os << "Since it now has a 0 retain count the object can be "
- "automatically collected by the garbage collector.";
- }
- else
- os << "An object must have a 0 retain count to be garbage collected. "
- "After this call its retain count is +" << CurrV.getCount()
- << '.';
- }
- else
- os << "When GC is not enabled a call to '" << *FD
- << "' has no effect on its argument.";
-
- // Nothing more to say.
- break;
- }
-
- // Determine if the typestate has changed.
- if (!PrevV.hasSameState(CurrV))
- switch (CurrV.getKind()) {
- case RefVal::Owned:
- case RefVal::NotOwned:
- if (PrevV.getCount() == CurrV.getCount()) {
- // Did an autorelease message get sent?
- if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
- return nullptr;
-
- assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
- os << "Object autoreleased";
- break;
- }
-
- if (PrevV.getCount() > CurrV.getCount())
- os << "Reference count decremented.";
- else
- os << "Reference count incremented.";
-
- if (unsigned Count = CurrV.getCount())
- os << " The object now has a +" << Count << " retain count.";
-
- if (PrevV.getKind() == RefVal::Released) {
- assert(GCEnabled && CurrV.getCount() > 0);
- os << " The object is not eligible for garbage collection until "
- "the retain count reaches 0 again.";
- }
-
- break;
-
- case RefVal::Released:
- if (CurrV.getIvarAccessHistory() ==
- RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
- CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
- os << "Strong instance variable relinquished. ";
- }
- os << "Object released.";
- break;
-
- case RefVal::ReturnedOwned:
- // Autoreleases can be applied after marking a node ReturnedOwned.
- if (CurrV.getAutoreleaseCount())
- return nullptr;
-
- os << "Object returned to caller as an owning reference (single "
- "retain count transferred to caller)";
- break;
-
- case RefVal::ReturnedNotOwned:
- os << "Object returned to caller with a +0 retain count";
- break;
-
- default:
- return nullptr;
- }
-
- // Emit any remaining diagnostics for the argument effects (if any).
- for (SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
- E=AEffects.end(); I != E; ++I) {
-
- // A bunch of things have alternate behavior under GC.
- if (GCEnabled)
- switch (*I) {
- default: break;
- case Autorelease:
- os << "In GC mode an 'autorelease' has no effect.";
- continue;
- case IncRefMsg:
- os << "In GC mode the 'retain' message has no effect.";
- continue;
- case DecRefMsg:
- os << "In GC mode the 'release' message has no effect.";
- continue;
- }
- }
- } while (0);
-
- if (os.str().empty())
- return nullptr; // We have nothing to say!
-
- const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
- PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
- N->getLocationContext());
- auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
-
- // Add the range by scanning the children of the statement for any bindings
- // to Sym.
- for (const Stmt *Child : S->children())
- if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
- if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
- P->addRange(Exp->getSourceRange());
- break;
- }
-
- return std::move(P);
-}
-
-namespace {
-// Find the first node in the current function context that referred to the
-// tracked symbol and the memory location that value was stored to. Note, the
-// value is only reported if the allocation occurred in the same function as
-// the leak. The function can also return a location context, which should be
-// treated as interesting.
-struct AllocationInfo {
- const ExplodedNode* N;
- const MemRegion *R;
- const LocationContext *InterestingMethodContext;
- AllocationInfo(const ExplodedNode *InN,
- const MemRegion *InR,
- const LocationContext *InInterestingMethodContext) :
- N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
-};
-} // end anonymous namespace
-
-static AllocationInfo
-GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
- SymbolRef Sym) {
- const ExplodedNode *AllocationNode = N;
- const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
- const MemRegion *FirstBinding = nullptr;
- const LocationContext *LeakContext = N->getLocationContext();
-
- // The location context of the init method called on the leaked object, if
- // available.
- const LocationContext *InitMethodContext = nullptr;
-
- while (N) {
- ProgramStateRef St = N->getState();
- const LocationContext *NContext = N->getLocationContext();
-
- if (!getRefBinding(St, Sym))
- break;
-
- StoreManager::FindUniqueBinding FB(Sym);
- StateMgr.iterBindings(St, FB);
-
- if (FB) {
- const MemRegion *R = FB.getRegion();
- const VarRegion *VR = R->getBaseRegion()->getAs<VarRegion>();
- // Do not show local variables belonging to a function other than
- // where the error is reported.
- if (!VR || VR->getStackFrame() == LeakContext->getStackFrame())
- FirstBinding = R;
- }
-
- // AllocationNode is the last node in which the symbol was tracked.
- AllocationNode = N;
-
- // AllocationNodeInCurrentContext, is the last node in the current or
- // parent context in which the symbol was tracked.
- //
- // Note that the allocation site might be in the parent conext. For example,
- // the case where an allocation happens in a block that captures a reference
- // to it and that reference is overwritten/dropped by another call to
- // the block.
- if (NContext == LeakContext || NContext->isParentOf(LeakContext))
- AllocationNodeInCurrentOrParentContext = N;
-
- // Find the last init that was called on the given symbol and store the
- // init method's location context.
- if (!InitMethodContext)
- if (Optional<CallEnter> CEP = N->getLocation().getAs<CallEnter>()) {
- const Stmt *CE = CEP->getCallExpr();
- if (const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
- const Stmt *RecExpr = ME->getInstanceReceiver();
- if (RecExpr) {
- SVal RecV = St->getSVal(RecExpr, NContext);
- if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
- InitMethodContext = CEP->getCalleeContext();
- }
- }
- }
-
- N = N->pred_empty() ? nullptr : *(N->pred_begin());
- }
-
- // If we are reporting a leak of the object that was allocated with alloc,
- // mark its init method as interesting.
- const LocationContext *InterestingMethodContext = nullptr;
- if (InitMethodContext) {
- const ProgramPoint AllocPP = AllocationNode->getLocation();
- if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
- if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
- if (ME->getMethodFamily() == OMF_alloc)
- InterestingMethodContext = InitMethodContext;
- }
-
- // If allocation happened in a function different from the leak node context,
- // do not report the binding.
- assert(N && "Could not find allocation node");
- if (N->getLocationContext() != LeakContext) {
- FirstBinding = nullptr;
- }
-
- return AllocationInfo(AllocationNodeInCurrentOrParentContext,
- FirstBinding,
- InterestingMethodContext);
-}
-
-std::shared_ptr<PathDiagnosticPiece>
-CFRefReportVisitor::getEndPath(BugReporterContext &BRC,
- const ExplodedNode *EndN, BugReport &BR) {
- BR.markInteresting(Sym);
- return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
-}
-
-std::shared_ptr<PathDiagnosticPiece>
-CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
- const ExplodedNode *EndN, BugReport &BR) {
-
- // Tell the BugReporterContext to report cases when the tracked symbol is
- // assigned to different variables, etc.
- BR.markInteresting(Sym);
-
- // We are reporting a leak. Walk up the graph to get to the first node where
- // the symbol appeared, and also get the first VarDecl that tracked object
- // is stored to.
- AllocationInfo AllocI =
- GetAllocationSite(BRC.getStateManager(), EndN, Sym);
-
- const MemRegion* FirstBinding = AllocI.R;
- BR.markInteresting(AllocI.InterestingMethodContext);
-
- SourceManager& SM = BRC.getSourceManager();
-
- // Compute an actual location for the leak. Sometimes a leak doesn't
- // occur at an actual statement (e.g., transition between blocks; end
- // of function) so we need to walk the graph and compute a real location.
- const ExplodedNode *LeakN = EndN;
- PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM);
-
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
-
- os << "Object leaked: ";
-
- Optional<std::string> RegionDescription = describeRegion(FirstBinding);
- if (RegionDescription) {
- os << "object allocated and stored into '" << *RegionDescription << '\'';
- }
- else
- os << "allocated object";
-
- // Get the retain count.
- const RefVal* RV = getRefBinding(EndN->getState(), Sym);
- assert(RV);
-
- if (RV->getKind() == RefVal::ErrorLeakReturned) {
- // FIXME: Per comments in rdar://6320065, "create" only applies to CF
- // objects. Only "copy", "alloc", "retain" and "new" transfer ownership
- // to the caller for NS objects.
- const Decl *D = &EndN->getCodeDecl();
-
- os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
- : " is returned from a function ");
-
- if (D->hasAttr<CFReturnsNotRetainedAttr>())
- os << "that is annotated as CF_RETURNS_NOT_RETAINED";
- else if (D->hasAttr<NSReturnsNotRetainedAttr>())
- os << "that is annotated as NS_RETURNS_NOT_RETAINED";
- else {
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
- os << "managed by Automatic Reference Counting";
- } else {
- os << "whose name ('" << MD->getSelector().getAsString()
- << "') does not start with "
- "'copy', 'mutableCopy', 'alloc' or 'new'."
- " This violates the naming convention rules"
- " given in the Memory Management Guide for Cocoa";
- }
- }
- else {
- const FunctionDecl *FD = cast<FunctionDecl>(D);
- os << "whose name ('" << *FD
- << "') does not contain 'Copy' or 'Create'. This violates the naming"
- " convention rules given in the Memory Management Guide for Core"
- " Foundation";
- }
- }
- }
- else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
- const ObjCMethodDecl &MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
- os << " and returned from method '" << MD.getSelector().getAsString()
- << "' is potentially leaked when using garbage collection. Callers "
- "of this method do not expect a returned object with a +1 retain "
- "count since they expect the object to be managed by the garbage "
- "collector";
- }
- else
- os << " is not referenced later in this execution path and has a retain "
- "count of +" << RV->getCount();
-
- return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
-}
-
-void CFRefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
- const SourceManager& SMgr = Ctx.getSourceManager();
-
- if (!sym->getOriginRegion())
- return;
-
- auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
- if (Region) {
- const Decl *PDecl = Region->getDecl();
- if (PDecl && isa<ParmVarDecl>(PDecl)) {
- PathDiagnosticLocation ParamLocation = PathDiagnosticLocation::create(PDecl, SMgr);
- Location = ParamLocation;
- UniqueingLocation = ParamLocation;
- UniqueingDecl = Ctx.getLocationContext()->getDecl();
- }
- }
-}
-
-void CFRefLeakReport::deriveAllocLocation(CheckerContext &Ctx,SymbolRef sym) {
- // Most bug reports are cached at the location where they occurred.
- // With leaks, we want to unique them by the location where they were
- // allocated, and only report a single path. To do this, we need to find
- // the allocation site of a piece of tracked memory, which we do via a
- // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
- // Note that this is *not* the trimmed graph; we are guaranteed, however,
- // that all ancestor nodes that represent the allocation site have the
- // same SourceLocation.
- const ExplodedNode *AllocNode = nullptr;
-
- const SourceManager& SMgr = Ctx.getSourceManager();
-
- AllocationInfo AllocI =
- GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
-
- AllocNode = AllocI.N;
- AllocBinding = AllocI.R;
- markInteresting(AllocI.InterestingMethodContext);
-
- // Get the SourceLocation for the allocation site.
- // FIXME: This will crash the analyzer if an allocation comes from an
- // implicit call (ex: a destructor call).
- // (Currently there are no such allocations in Cocoa, though.)
- AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
-
- if (!AllocStmt) {
- AllocBinding = nullptr;
- return;
- }
-
- PathDiagnosticLocation AllocLocation =
- PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
- AllocNode->getLocationContext());
- Location = AllocLocation;
-
- // Set uniqieing info, which will be used for unique the bug reports. The
- // leaks should be uniqued on the allocation site.
- UniqueingLocation = AllocLocation;
- UniqueingDecl = AllocNode->getLocationContext()->getDecl();
-}
-
-void CFRefLeakReport::createDescription(CheckerContext &Ctx, bool GCEnabled,
- bool IncludeAllocationLine) {
- assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
- Description.clear();
- llvm::raw_string_ostream os(Description);
- os << "Potential leak ";
- if (GCEnabled)
- os << "(when using garbage collection) ";
- os << "of an object";
-
- Optional<std::string> RegionDescription = describeRegion(AllocBinding);
- if (RegionDescription) {
- os << " stored into '" << *RegionDescription << '\'';
- if (IncludeAllocationLine) {
- FullSourceLoc SL(AllocStmt->getLocStart(), Ctx.getSourceManager());
- os << " (allocated on line " << SL.getSpellingLineNumber() << ")";
- }
- }
-}
-
-CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
- bool GCEnabled, const SummaryLogTy &Log,
- ExplodedNode *n, SymbolRef sym,
- CheckerContext &Ctx,
- bool IncludeAllocationLine)
- : CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) {
-
- deriveAllocLocation(Ctx, sym);
- if (!AllocBinding)
- deriveParamLocation(Ctx, sym);
-
- createDescription(Ctx, GCEnabled, IncludeAllocationLine);
-
- addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
-}
-
-//===----------------------------------------------------------------------===//
-// Main checker logic.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class RetainCountChecker
- : public Checker< check::Bind,
- check::DeadSymbols,
- check::EndAnalysis,
- check::BeginFunction,
- check::EndFunction,
- check::PostStmt<BlockExpr>,
- check::PostStmt<CastExpr>,
- check::PostStmt<ObjCArrayLiteral>,
- check::PostStmt<ObjCDictionaryLiteral>,
- check::PostStmt<ObjCBoxedExpr>,
- check::PostStmt<ObjCIvarRefExpr>,
- check::PostCall,
- check::PreStmt<ReturnStmt>,
- check::RegionChanges,
- eval::Assume,
- eval::Call > {
- mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
- mutable std::unique_ptr<CFRefBug> deallocGC, deallocNotOwned;
- mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
- mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
- mutable std::unique_ptr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
-
- typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
-
- // This map is only used to ensure proper deletion of any allocated tags.
- mutable SymbolTagMap DeadSymbolTags;
-
- mutable std::unique_ptr<RetainSummaryManager> Summaries;
- mutable std::unique_ptr<RetainSummaryManager> SummariesGC;
- mutable SummaryLogTy SummaryLog;
- mutable bool ShouldResetSummaryLog;
-
- /// Optional setting to indicate if leak reports should include
- /// the allocation line.
- mutable bool IncludeAllocationLine;
-
-public:
- RetainCountChecker(AnalyzerOptions &AO)
- : ShouldResetSummaryLog(false),
- IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {}
-
- ~RetainCountChecker() override { DeleteContainerSeconds(DeadSymbolTags); }
-
- void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
- ExprEngine &Eng) const {
- // FIXME: This is a hack to make sure the summary log gets cleared between
- // analyses of different code bodies.
- //
- // Why is this necessary? Because a checker's lifetime is tied to a
- // translation unit, but an ExplodedGraph's lifetime is just a code body.
- // Once in a blue moon, a new ExplodedNode will have the same address as an
- // old one with an associated summary, and the bug report visitor gets very
- // confused. (To make things worse, the summary lifetime is currently also
- // tied to a code body, so we get a crash instead of incorrect results.)
- //
- // Why is this a bad solution? Because if the lifetime of the ExplodedGraph
- // changes, things will start going wrong again. Really the lifetime of this
- // log needs to be tied to either the specific nodes in it or the entire
- // ExplodedGraph, not to a specific part of the code being analyzed.
- //
- // (Also, having stateful local data means that the same checker can't be
- // used from multiple threads, but a lot of checkers have incorrect
- // assumptions about that anyway. So that wasn't a priority at the time of
- // this fix.)
- //
- // This happens at the end of analysis, but bug reports are emitted /after/
- // this point. So we can't just clear the summary log now. Instead, we mark
- // that the next time we access the summary log, it should be cleared.
-
- // If we never reset the summary log during /this/ code body analysis,
- // there were no new summaries. There might still have been summaries from
- // the /last/ analysis, so clear them out to make sure the bug report
- // visitors don't get confused.
- if (ShouldResetSummaryLog)
- SummaryLog.clear();
-
- ShouldResetSummaryLog = !SummaryLog.empty();
- }
-
- CFRefBug *getLeakWithinFunctionBug(const LangOptions &LOpts,
- bool GCEnabled) const {
- if (GCEnabled) {
- if (!leakWithinFunctionGC)
- leakWithinFunctionGC.reset(new Leak(this, "Leak of object when using "
- "garbage collection"));
- return leakWithinFunctionGC.get();
- } else {
- if (!leakWithinFunction) {
- if (LOpts.getGC() == LangOptions::HybridGC) {
- leakWithinFunction.reset(new Leak(this,
- "Leak of object when not using "
- "garbage collection (GC) in "
- "dual GC/non-GC code"));
- } else {
- leakWithinFunction.reset(new Leak(this, "Leak"));
- }
- }
- return leakWithinFunction.get();
- }
- }
-
- CFRefBug *getLeakAtReturnBug(const LangOptions &LOpts, bool GCEnabled) const {
- if (GCEnabled) {
- if (!leakAtReturnGC)
- leakAtReturnGC.reset(new Leak(this,
- "Leak of returned object when using "
- "garbage collection"));
- return leakAtReturnGC.get();
- } else {
- if (!leakAtReturn) {
- if (LOpts.getGC() == LangOptions::HybridGC) {
- leakAtReturn.reset(new Leak(this,
- "Leak of returned object when not using "
- "garbage collection (GC) in dual "
- "GC/non-GC code"));
- } else {
- leakAtReturn.reset(new Leak(this, "Leak of returned object"));
- }
- }
- return leakAtReturn.get();
- }
- }
-
- RetainSummaryManager &getSummaryManager(ASTContext &Ctx,
- bool GCEnabled) const {
- // FIXME: We don't support ARC being turned on and off during one analysis.
- // (nor, for that matter, do we support changing ASTContexts)
- bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
- if (GCEnabled) {
- if (!SummariesGC)
- SummariesGC.reset(new RetainSummaryManager(Ctx, true, ARCEnabled));
- else
- assert(SummariesGC->isARCEnabled() == ARCEnabled);
- return *SummariesGC;
- } else {
- if (!Summaries)
- Summaries.reset(new RetainSummaryManager(Ctx, false, ARCEnabled));
- else
- assert(Summaries->isARCEnabled() == ARCEnabled);
- return *Summaries;
- }
- }
-
- RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
- return getSummaryManager(C.getASTContext(), C.isObjCGCEnabled());
- }
-
- void printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) const override;
-
- void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
- void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
- void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
-
- void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
- void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
- void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
-
- void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
-
- void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
-
- void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
- CheckerContext &C) const;
-
- void processSummaryOfInlined(const RetainSummary &Summ,
- const CallEvent &Call,
- CheckerContext &C) const;
-
- bool evalCall(const CallExpr *CE, CheckerContext &C) const;
-
- ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
- bool Assumption) const;
-
- ProgramStateRef
- checkRegionChanges(ProgramStateRef state,
- const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const LocationContext* LCtx,
- const CallEvent *Call) const;
-
- void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
- void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
- ExplodedNode *Pred, RetEffect RE, RefVal X,
- SymbolRef Sym, ProgramStateRef state) const;
-
- void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
- void checkBeginFunction(CheckerContext &C) const;
- void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
-
- ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
- RefVal V, ArgEffect E, RefVal::Kind &hasErr,
- CheckerContext &C) const;
-
- void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
- RefVal::Kind ErrorKind, SymbolRef Sym,
- CheckerContext &C) const;
-
- void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
-
- const ProgramPointTag *getDeadSymbolTag(SymbolRef sym) const;
-
- ProgramStateRef handleSymbolDeath(ProgramStateRef state,
- SymbolRef sid, RefVal V,
- SmallVectorImpl<SymbolRef> &Leaked) const;
-
- ProgramStateRef
- handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
- const ProgramPointTag *Tag, CheckerContext &Ctx,
- SymbolRef Sym, RefVal V) const;
-
- ExplodedNode *processLeaks(ProgramStateRef state,
- SmallVectorImpl<SymbolRef> &Leaked,
- CheckerContext &Ctx,
- ExplodedNode *Pred = nullptr) const;
-};
-} // end anonymous namespace
-
-namespace {
-class StopTrackingCallback final : public SymbolVisitor {
- ProgramStateRef state;
-public:
- StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
- ProgramStateRef getState() const { return state; }
-
- bool VisitSymbol(SymbolRef sym) override {
- state = state->remove<RefBindings>(sym);
- return true;
- }
-};
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// Handle statements that may have an effect on refcounts.
-//===----------------------------------------------------------------------===//
-
-void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
- CheckerContext &C) const {
-
- // Scan the BlockDecRefExprs for any object the retain count checker
- // may be tracking.
- if (!BE->getBlockDecl()->hasCaptures())
- return;
-
- ProgramStateRef state = C.getState();
- auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
-
- BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
- E = R->referenced_vars_end();
-
- if (I == E)
- return;
-
- // FIXME: For now we invalidate the tracking of all symbols passed to blocks
- // via captured variables, even though captured variables result in a copy
- // and in implicit increment/decrement of a retain count.
- SmallVector<const MemRegion*, 10> Regions;
- const LocationContext *LC = C.getLocationContext();
- MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
-
- for ( ; I != E; ++I) {
- const VarRegion *VR = I.getCapturedRegion();
- if (VR->getSuperRegion() == R) {
- VR = MemMgr.getVarRegion(VR->getDecl(), LC);
- }
- Regions.push_back(VR);
- }
-
- state =
- state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
- Regions.data() + Regions.size()).getState();
- C.addTransition(state);
-}
-
-void RetainCountChecker::checkPostStmt(const CastExpr *CE,
- CheckerContext &C) const {
- const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
- if (!BE)
- return;
-
- ArgEffect AE = IncRef;
-
- switch (BE->getBridgeKind()) {
- case clang::OBC_Bridge:
- // Do nothing.
- return;
- case clang::OBC_BridgeRetained:
- AE = IncRef;
- break;
- case clang::OBC_BridgeTransfer:
- AE = DecRefBridgedTransferred;
- break;
- }
-
- ProgramStateRef state = C.getState();
- SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();
- if (!Sym)
- return;
- const RefVal* T = getRefBinding(state, Sym);
- if (!T)
- return;
-
- RefVal::Kind hasErr = (RefVal::Kind) 0;
- state = updateSymbol(state, Sym, *T, AE, hasErr, C);
-
- if (hasErr) {
- // FIXME: If we get an error during a bridge cast, should we report it?
- return;
- }
-
- C.addTransition(state);
-}
-
-void RetainCountChecker::processObjCLiterals(CheckerContext &C,
- const Expr *Ex) const {
- ProgramStateRef state = C.getState();
- const ExplodedNode *pred = C.getPredecessor();
- for (const Stmt *Child : Ex->children()) {
- SVal V = pred->getSVal(Child);
- if (SymbolRef sym = V.getAsSymbol())
- if (const RefVal* T = getRefBinding(state, sym)) {
- RefVal::Kind hasErr = (RefVal::Kind) 0;
- state = updateSymbol(state, sym, *T, MayEscape, hasErr, C);
- if (hasErr) {
- processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
- return;
- }
- }
- }
-
- // Return the object as autoreleased.
- // RetEffect RE = RetEffect::MakeNotOwned(RetEffect::ObjC);
- if (SymbolRef sym =
- state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
- QualType ResultTy = Ex->getType();
- state = setRefBinding(state, sym,
- RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
- }
-
- C.addTransition(state);
-}
-
-void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
- CheckerContext &C) const {
- // Apply the 'MayEscape' to all values.
- processObjCLiterals(C, AL);
-}
-
-void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
- CheckerContext &C) const {
- // Apply the 'MayEscape' to all keys and values.
- processObjCLiterals(C, DL);
-}
-
-void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
- CheckerContext &C) const {
- const ExplodedNode *Pred = C.getPredecessor();
- ProgramStateRef State = Pred->getState();
-
- if (SymbolRef Sym = Pred->getSVal(Ex).getAsSymbol()) {
- QualType ResultTy = Ex->getType();
- State = setRefBinding(State, Sym,
- RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
- }
-
- C.addTransition(State);
-}
-
-void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
- CheckerContext &C) const {
- Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
- if (!IVarLoc)
- return;
-
- ProgramStateRef State = C.getState();
- SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
- if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->getOriginRegion()))
- return;
-
- // Accessing an ivar directly is unusual. If we've done that, be more
- // forgiving about what the surrounding code is allowed to do.
-
- QualType Ty = Sym->getType();
- RetEffect::ObjKind Kind;
- if (Ty->isObjCRetainableType())
- Kind = RetEffect::ObjC;
- else if (coreFoundation::isCFObjectRef(Ty))
- Kind = RetEffect::CF;
- else
- return;
-
- // If the value is already known to be nil, don't bother tracking it.
- ConstraintManager &CMgr = State->getConstraintManager();
- if (CMgr.isNull(State, Sym).isConstrainedTrue())
- return;
-
- if (const RefVal *RV = getRefBinding(State, Sym)) {
- // If we've seen this symbol before, or we're only seeing it now because
- // of something the analyzer has synthesized, don't do anything.
- if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
- isSynthesizedAccessor(C.getStackFrame())) {
- return;
- }
-
- // Note that this value has been loaded from an ivar.
- C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
- return;
- }
-
- RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
-
- // In a synthesized accessor, the effective retain count is +0.
- if (isSynthesizedAccessor(C.getStackFrame())) {
- C.addTransition(setRefBinding(State, Sym, PlusZero));
- return;
- }
-
- State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
- C.addTransition(State);
-}
-
-void RetainCountChecker::checkPostCall(const CallEvent &Call,
- CheckerContext &C) const {
- RetainSummaryManager &Summaries = getSummaryManager(C);
- const RetainSummary *Summ = Summaries.getSummary(Call, C.getState());
-
- if (C.wasInlined) {
- processSummaryOfInlined(*Summ, Call, C);
- return;
- }
- checkSummary(*Summ, Call, C);
-}
-
-/// GetReturnType - Used to get the return type of a message expression or
-/// function call with the intention of affixing that type to a tracked symbol.
-/// While the return type can be queried directly from RetEx, when
-/// invoking class methods we augment to the return type to be that of
-/// a pointer to the class (as opposed it just being id).
-// FIXME: We may be able to do this with related result types instead.
-// This function is probably overestimating.
-static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
- QualType RetTy = RetE->getType();
- // If RetE is not a message expression just return its type.
- // If RetE is a message expression, return its types if it is something
- /// more specific than id.
- if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
- if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
- if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
- PT->isObjCClassType()) {
- // At this point we know the return type of the message expression is
- // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
- // is a call to a class method whose type we can resolve. In such
- // cases, promote the return type to XXX* (where XXX is the class).
- const ObjCInterfaceDecl *D = ME->getReceiverInterface();
- return !D ? RetTy :
- Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
- }
-
- return RetTy;
-}
-
-// We don't always get the exact modeling of the function with regards to the
-// retain count checker even when the function is inlined. For example, we need
-// to stop tracking the symbols which were marked with StopTrackingHard.
-void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
- const CallEvent &CallOrMsg,
- CheckerContext &C) const {
- ProgramStateRef state = C.getState();
-
- // Evaluate the effect of the arguments.
- for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
- if (Summ.getArg(idx) == StopTrackingHard) {
- SVal V = CallOrMsg.getArgSVal(idx);
- if (SymbolRef Sym = V.getAsLocSymbol()) {
- state = removeRefBinding(state, Sym);
- }
- }
- }
-
- // Evaluate the effect on the message receiver.
- const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg);
- if (MsgInvocation) {
- if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
- if (Summ.getReceiverEffect() == StopTrackingHard) {
- state = removeRefBinding(state, Sym);
- }
- }
- }
-
- // Consult the summary for the return value.
- RetEffect RE = Summ.getRetEffect();
- if (RE.getKind() == RetEffect::NoRetHard) {
- SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
- if (Sym)
- state = removeRefBinding(state, Sym);
- }
-
- C.addTransition(state);
-}
-
-static ProgramStateRef updateOutParameter(ProgramStateRef State,
- SVal ArgVal,
- ArgEffect Effect) {
- auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
- if (!ArgRegion)
- return State;
-
- QualType PointeeTy = ArgRegion->getValueType();
- if (!coreFoundation::isCFObjectRef(PointeeTy))
- return State;
-
- SVal PointeeVal = State->getSVal(ArgRegion);
- SymbolRef Pointee = PointeeVal.getAsLocSymbol();
- if (!Pointee)
- return State;
-
- switch (Effect) {
- case UnretainedOutParameter:
- State = setRefBinding(State, Pointee,
- RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
- break;
- case RetainedOutParameter:
- // Do nothing. Retained out parameters will either point to a +1 reference
- // or NULL, but the way you check for failure differs depending on the API.
- // Consequently, we don't have a good way to track them yet.
- break;
-
- default:
- llvm_unreachable("only for out parameters");
- }
-
- return State;
-}
-
-void RetainCountChecker::checkSummary(const RetainSummary &Summ,
- const CallEvent &CallOrMsg,
- CheckerContext &C) const {
- ProgramStateRef state = C.getState();
-
- // Evaluate the effect of the arguments.
- RefVal::Kind hasErr = (RefVal::Kind) 0;
- SourceRange ErrorRange;
- SymbolRef ErrorSym = nullptr;
-
- for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
- SVal V = CallOrMsg.getArgSVal(idx);
-
- ArgEffect Effect = Summ.getArg(idx);
- if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) {
- state = updateOutParameter(state, V, Effect);
- } else if (SymbolRef Sym = V.getAsLocSymbol()) {
- if (const RefVal *T = getRefBinding(state, Sym)) {
- state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
- if (hasErr) {
- ErrorRange = CallOrMsg.getArgSourceRange(idx);
- ErrorSym = Sym;
- break;
- }
- }
- }
- }
-
- // Evaluate the effect on the message receiver.
- bool ReceiverIsTracked = false;
- if (!hasErr) {
- const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg);
- if (MsgInvocation) {
- if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
- if (const RefVal *T = getRefBinding(state, Sym)) {
- ReceiverIsTracked = true;
- state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
- hasErr, C);
- if (hasErr) {
- ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
- ErrorSym = Sym;
- }
- }
- }
- }
- }
-
- // Process any errors.
- if (hasErr) {
- processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
- return;
- }
-
- // Consult the summary for the return value.
- RetEffect RE = Summ.getRetEffect();
-
- if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
- if (ReceiverIsTracked)
- RE = getSummaryManager(C).getObjAllocRetEffect();
- else
- RE = RetEffect::MakeNoRet();
- }
-
- switch (RE.getKind()) {
- default:
- llvm_unreachable("Unhandled RetEffect.");
-
- case RetEffect::NoRet:
- case RetEffect::NoRetHard:
- // No work necessary.
- break;
-
- case RetEffect::OwnedSymbol: {
- SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
- if (!Sym)
- break;
-
- // Use the result type from the CallEvent as it automatically adjusts
- // for methods/functions that return references.
- QualType ResultTy = CallOrMsg.getResultType();
- state = setRefBinding(state, Sym, RefVal::makeOwned(RE.getObjKind(),
- ResultTy));
-
- // FIXME: Add a flag to the checker where allocations are assumed to
- // *not* fail.
- break;
- }
-
- case RetEffect::GCNotOwnedSymbol:
- case RetEffect::NotOwnedSymbol: {
- const Expr *Ex = CallOrMsg.getOriginExpr();
- SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
- if (!Sym)
- break;
- assert(Ex);
- // Use GetReturnType in order to give [NSFoo alloc] the type NSFoo *.
- QualType ResultTy = GetReturnType(Ex, C.getASTContext());
- state = setRefBinding(state, Sym, RefVal::makeNotOwned(RE.getObjKind(),
- ResultTy));
- break;
- }
- }
-
- // This check is actually necessary; otherwise the statement builder thinks
- // we've hit a previously-found path.
- // Normally addTransition takes care of this, but we want the node pointer.
- ExplodedNode *NewNode;
- if (state == C.getState()) {
- NewNode = C.getPredecessor();
- } else {
- NewNode = C.addTransition(state);
- }
-
- // Annotate the node with summary we used.
- if (NewNode) {
- // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
- if (ShouldResetSummaryLog) {
- SummaryLog.clear();
- ShouldResetSummaryLog = false;
- }
- SummaryLog[NewNode] = &Summ;
- }
-}
-
-ProgramStateRef
-RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
- RefVal V, ArgEffect E, RefVal::Kind &hasErr,
- CheckerContext &C) const {
- // In GC mode [... release] and [... retain] do nothing.
- // In ARC mode they shouldn't exist at all, but we just ignore them.
- bool IgnoreRetainMsg = C.isObjCGCEnabled();
- if (!IgnoreRetainMsg)
- IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
-
- switch (E) {
- default:
- break;
- case IncRefMsg:
- E = IgnoreRetainMsg ? DoNothing : IncRef;
- break;
- case DecRefMsg:
- E = IgnoreRetainMsg ? DoNothing : DecRef;
- break;
- case DecRefMsgAndStopTrackingHard:
- E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard;
- break;
- case MakeCollectable:
- E = C.isObjCGCEnabled() ? DecRef : DoNothing;
- break;
- }
-
- // Handle all use-after-releases.
- if (!C.isObjCGCEnabled() && V.getKind() == RefVal::Released) {
- V = V ^ RefVal::ErrorUseAfterRelease;
- hasErr = V.getKind();
- return setRefBinding(state, sym, V);
- }
-
- switch (E) {
- case DecRefMsg:
- case IncRefMsg:
- case MakeCollectable:
- case DecRefMsgAndStopTrackingHard:
- llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
-
- case UnretainedOutParameter:
- case RetainedOutParameter:
- llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
- "not have ref state.");
-
- case Dealloc:
- // Any use of -dealloc in GC is *bad*.
- if (C.isObjCGCEnabled()) {
- V = V ^ RefVal::ErrorDeallocGC;
- hasErr = V.getKind();
- break;
- }
-
- switch (V.getKind()) {
- default:
- llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
- case RefVal::Owned:
- // The object immediately transitions to the released state.
- V = V ^ RefVal::Released;
- V.clearCounts();
- return setRefBinding(state, sym, V);
- case RefVal::NotOwned:
- V = V ^ RefVal::ErrorDeallocNotOwned;
- hasErr = V.getKind();
- break;
- }
- break;
-
- case MayEscape:
- if (V.getKind() == RefVal::Owned) {
- V = V ^ RefVal::NotOwned;
- break;
- }
-
- // Fall-through.
-
- case DoNothing:
- return state;
-
- case Autorelease:
- if (C.isObjCGCEnabled())
- return state;
- // Update the autorelease counts.
- V = V.autorelease();
- break;
-
- case StopTracking:
- case StopTrackingHard:
- return removeRefBinding(state, sym);
-
- case IncRef:
- switch (V.getKind()) {
- default:
- llvm_unreachable("Invalid RefVal state for a retain.");
- case RefVal::Owned:
- case RefVal::NotOwned:
- V = V + 1;
- break;
- case RefVal::Released:
- // Non-GC cases are handled above.
- assert(C.isObjCGCEnabled());
- V = (V ^ RefVal::Owned) + 1;
- break;
- }
- break;
-
- case DecRef:
- case DecRefBridgedTransferred:
- case DecRefAndStopTrackingHard:
- switch (V.getKind()) {
- default:
- // case 'RefVal::Released' handled above.
- llvm_unreachable("Invalid RefVal state for a release.");
-
- case RefVal::Owned:
- assert(V.getCount() > 0);
- if (V.getCount() == 1) {
- if (E == DecRefBridgedTransferred ||
- V.getIvarAccessHistory() ==
- RefVal::IvarAccessHistory::AccessedDirectly)
- V = V ^ RefVal::NotOwned;
- else
- V = V ^ RefVal::Released;
- } else if (E == DecRefAndStopTrackingHard) {
- return removeRefBinding(state, sym);
- }
-
- V = V - 1;
- break;
-
- case RefVal::NotOwned:
- if (V.getCount() > 0) {
- if (E == DecRefAndStopTrackingHard)
- return removeRefBinding(state, sym);
- V = V - 1;
- } else if (V.getIvarAccessHistory() ==
- RefVal::IvarAccessHistory::AccessedDirectly) {
- // Assume that the instance variable was holding on the object at
- // +1, and we just didn't know.
- if (E == DecRefAndStopTrackingHard)
- return removeRefBinding(state, sym);
- V = V.releaseViaIvar() ^ RefVal::Released;
- } else {
- V = V ^ RefVal::ErrorReleaseNotOwned;
- hasErr = V.getKind();
- }
- break;
-
- case RefVal::Released:
- // Non-GC cases are handled above.
- assert(C.isObjCGCEnabled());
- V = V ^ RefVal::ErrorUseAfterRelease;
- hasErr = V.getKind();
- break;
- }
- break;
- }
- return setRefBinding(state, sym, V);
-}
-
-void RetainCountChecker::processNonLeakError(ProgramStateRef St,
- SourceRange ErrorRange,
- RefVal::Kind ErrorKind,
- SymbolRef Sym,
- CheckerContext &C) const {
- // HACK: Ignore retain-count issues on values accessed through ivars,
- // because of cases like this:
- // [_contentView retain];
- // [_contentView removeFromSuperview];
- // [self addSubview:_contentView]; // invalidates 'self'
- // [_contentView release];
- if (const RefVal *RV = getRefBinding(St, Sym))
- if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
- return;
-
- ExplodedNode *N = C.generateErrorNode(St);
- if (!N)
- return;
-
- CFRefBug *BT;
- switch (ErrorKind) {
- default:
- llvm_unreachable("Unhandled error.");
- case RefVal::ErrorUseAfterRelease:
- if (!useAfterRelease)
- useAfterRelease.reset(new UseAfterRelease(this));
- BT = useAfterRelease.get();
- break;
- case RefVal::ErrorReleaseNotOwned:
- if (!releaseNotOwned)
- releaseNotOwned.reset(new BadRelease(this));
- BT = releaseNotOwned.get();
- break;
- case RefVal::ErrorDeallocGC:
- if (!deallocGC)
- deallocGC.reset(new DeallocGC(this));
- BT = deallocGC.get();
- break;
- case RefVal::ErrorDeallocNotOwned:
- if (!deallocNotOwned)
- deallocNotOwned.reset(new DeallocNotOwned(this));
- BT = deallocNotOwned.get();
- break;
- }
-
- assert(BT);
- auto report = std::unique_ptr<BugReport>(
- new CFRefReport(*BT, C.getASTContext().getLangOpts(), C.isObjCGCEnabled(),
- SummaryLog, N, Sym));
- report->addRange(ErrorRange);
- C.emitReport(std::move(report));
-}
-
-//===----------------------------------------------------------------------===//
-// Handle the return values of retain-count-related functions.
-//===----------------------------------------------------------------------===//
-
-bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
- // Get the callee. We're only interested in simple C functions.
- ProgramStateRef state = C.getState();
- const FunctionDecl *FD = C.getCalleeDecl(CE);
- if (!FD)
- return false;
-
- IdentifierInfo *II = FD->getIdentifier();
- if (!II)
- return false;
-
- // For now, we're only handling the functions that return aliases of their
- // arguments: CFRetain and CFMakeCollectable (and their families).
- // Eventually we should add other functions we can model entirely,
- // such as CFRelease, which don't invalidate their arguments or globals.
- if (CE->getNumArgs() != 1)
- return false;
-
- // Get the name of the function.
- StringRef FName = II->getName();
- FName = FName.substr(FName.find_first_not_of('_'));
-
- // See if it's one of the specific functions we know how to eval.
- bool canEval = false;
- // See if the function has 'rc_ownership_trusted_implementation'
- // annotate attribute. If it does, we will not inline it.
- bool hasTrustedImplementationAnnotation = false;
-
- QualType ResultTy = CE->getCallReturnType(C.getASTContext());
- if (ResultTy->isObjCIdType()) {
- // Handle: id NSMakeCollectable(CFTypeRef)
- canEval = II->isStr("NSMakeCollectable");
- } else if (ResultTy->isPointerType()) {
- // Handle: (CF|CG|CV)Retain
- // CFAutorelease
- // CFMakeCollectable
- // It's okay to be a little sloppy here (CGMakeCollectable doesn't exist).
- if (cocoa::isRefType(ResultTy, "CF", FName) ||
- cocoa::isRefType(ResultTy, "CG", FName) ||
- cocoa::isRefType(ResultTy, "CV", FName)) {
- canEval = isRetain(FD, FName) || isAutorelease(FD, FName) ||
- isMakeCollectable(FD, FName);
- } else {
- if (FD->getDefinition()) {
- canEval = isTrustedReferenceCountImplementation(FD->getDefinition());
- hasTrustedImplementationAnnotation = canEval;
- }
- }
- }
-
- if (!canEval)
- return false;
-
- // Bind the return value.
- const LocationContext *LCtx = C.getLocationContext();
- SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
- if (RetVal.isUnknown() ||
- (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
- // If the receiver is unknown or the function has
- // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
- // return value.
- SValBuilder &SVB = C.getSValBuilder();
- RetVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
- }
- state = state->BindExpr(CE, LCtx, RetVal, false);
-
- // FIXME: This should not be necessary, but otherwise the argument seems to be
- // considered alive during the next statement.
- if (const MemRegion *ArgRegion = RetVal.getAsRegion()) {
- // Save the refcount status of the argument.
- SymbolRef Sym = RetVal.getAsLocSymbol();
- const RefVal *Binding = nullptr;
- if (Sym)
- Binding = getRefBinding(state, Sym);
-
- // Invalidate the argument region.
- state = state->invalidateRegions(
- ArgRegion, CE, C.blockCount(), LCtx,
- /*CausesPointerEscape*/ hasTrustedImplementationAnnotation);
-
- // Restore the refcount status of the argument.
- if (Binding)
- state = setRefBinding(state, Sym, *Binding);
- }
-
- C.addTransition(state);
- return true;
-}
-
-//===----------------------------------------------------------------------===//
-// Handle return statements.
-//===----------------------------------------------------------------------===//
-
-void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
- CheckerContext &C) const {
-
- // Only adjust the reference count if this is the top-level call frame,
- // and not the result of inlining. In the future, we should do
- // better checking even for inlined calls, and see if they match
- // with their expected semantics (e.g., the method should return a retained
- // object, etc.).
- if (!C.inTopFrame())
- return;
-
- const Expr *RetE = S->getRetValue();
- if (!RetE)
- return;
-
- ProgramStateRef state = C.getState();
- SymbolRef Sym =
- state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
- if (!Sym)
- return;
-
- // Get the reference count binding (if any).
- const RefVal *T = getRefBinding(state, Sym);
- if (!T)
- return;
-
- // Change the reference count.
- RefVal X = *T;
-
- switch (X.getKind()) {
- case RefVal::Owned: {
- unsigned cnt = X.getCount();
- assert(cnt > 0);
- X.setCount(cnt - 1);
- X = X ^ RefVal::ReturnedOwned;
- break;
- }
-
- case RefVal::NotOwned: {
- unsigned cnt = X.getCount();
- if (cnt) {
- X.setCount(cnt - 1);
- X = X ^ RefVal::ReturnedOwned;
- }
- else {
- X = X ^ RefVal::ReturnedNotOwned;
- }
- break;
- }
-
- default:
- return;
- }
-
- // Update the binding.
- state = setRefBinding(state, Sym, X);
- ExplodedNode *Pred = C.addTransition(state);
-
- // At this point we have updated the state properly.
- // Everything after this is merely checking to see if the return value has
- // been over- or under-retained.
-
- // Did we cache out?
- if (!Pred)
- return;
-
- // Update the autorelease counts.
- static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
- state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
-
- // Did we cache out?
- if (!state)
- return;
-
- // Get the updated binding.
- T = getRefBinding(state, Sym);
- assert(T);
- X = *T;
-
- // Consult the summary of the enclosing method.
- RetainSummaryManager &Summaries = getSummaryManager(C);
- const Decl *CD = &Pred->getCodeDecl();
- RetEffect RE = RetEffect::MakeNoRet();
-
- // FIXME: What is the convention for blocks? Is there one?
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
- const RetainSummary *Summ = Summaries.getMethodSummary(MD);
- RE = Summ->getRetEffect();
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
- if (!isa<CXXMethodDecl>(FD)) {
- const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
- RE = Summ->getRetEffect();
- }
- }
-
- checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
-}
-
-void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
- CheckerContext &C,
- ExplodedNode *Pred,
- RetEffect RE, RefVal X,
- SymbolRef Sym,
- ProgramStateRef state) const {
- // HACK: Ignore retain-count issues on values accessed through ivars,
- // because of cases like this:
- // [_contentView retain];
- // [_contentView removeFromSuperview];
- // [self addSubview:_contentView]; // invalidates 'self'
- // [_contentView release];
- if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
- return;
-
- // Any leaks or other errors?
- if (X.isReturnedOwned() && X.getCount() == 0) {
- if (RE.getKind() != RetEffect::NoRet) {
- bool hasError = false;
- if (C.isObjCGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
- // Things are more complicated with garbage collection. If the
- // returned object is suppose to be an Objective-C object, we have
- // a leak (as the caller expects a GC'ed object) because no
- // method should return ownership unless it returns a CF object.
- hasError = true;
- X = X ^ RefVal::ErrorGCLeakReturned;
- }
- else if (!RE.isOwned()) {
- // Either we are using GC and the returned object is a CF type
- // or we aren't using GC. In either case, we expect that the
- // enclosing method is expected to return ownership.
- hasError = true;
- X = X ^ RefVal::ErrorLeakReturned;
- }
-
- if (hasError) {
- // Generate an error node.
- state = setRefBinding(state, Sym, X);
-
- static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
- ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
- if (N) {
- const LangOptions &LOpts = C.getASTContext().getLangOpts();
- bool GCEnabled = C.isObjCGCEnabled();
- C.emitReport(std::unique_ptr<BugReport>(new CFRefLeakReport(
- *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
- SummaryLog, N, Sym, C, IncludeAllocationLine)));
- }
- }
- }
- } else if (X.isReturnedNotOwned()) {
- if (RE.isOwned()) {
- if (X.getIvarAccessHistory() ==
- RefVal::IvarAccessHistory::AccessedDirectly) {
- // Assume the method was trying to transfer a +1 reference from a
- // strong ivar to the caller.
- state = setRefBinding(state, Sym,
- X.releaseViaIvar() ^ RefVal::ReturnedOwned);
- } else {
- // Trying to return a not owned object to a caller expecting an
- // owned object.
- state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
-
- static CheckerProgramPointTag
- ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
-
- ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
- if (N) {
- if (!returnNotOwnedForOwned)
- returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
-
- C.emitReport(std::unique_ptr<BugReport>(new CFRefReport(
- *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
- C.isObjCGCEnabled(), SummaryLog, N, Sym)));
- }
- }
- }
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Check various ways a symbol can be invalidated.
-//===----------------------------------------------------------------------===//
-
-void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
- CheckerContext &C) const {
- // Are we storing to something that causes the value to "escape"?
- bool escapes = true;
-
- // A value escapes in three possible cases (this may change):
- //
- // (1) we are binding to something that is not a memory region.
- // (2) we are binding to a memregion that does not have stack storage
- // (3) we are binding to a memregion with stack storage that the store
- // does not understand.
- ProgramStateRef state = C.getState();
-
- if (Optional<loc::MemRegionVal> regionLoc = loc.getAs<loc::MemRegionVal>()) {
- escapes = !regionLoc->getRegion()->hasStackStorage();
-
- if (!escapes) {
- // To test (3), generate a new state with the binding added. If it is
- // the same state, then it escapes (since the store cannot represent
- // the binding).
- // Do this only if we know that the store is not supposed to generate the
- // same state.
- SVal StoredVal = state->getSVal(regionLoc->getRegion());
- if (StoredVal != val)
- escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext())));
- }
- if (!escapes) {
- // Case 4: We do not currently model what happens when a symbol is
- // assigned to a struct field, so be conservative here and let the symbol
- // go. TODO: This could definitely be improved upon.
- escapes = !isa<VarRegion>(regionLoc->getRegion());
- }
- }
-
- // If we are storing the value into an auto function scope variable annotated
- // with (__attribute__((cleanup))), stop tracking the value to avoid leak
- // false positives.
- if (const VarRegion *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) {
- const VarDecl *VD = LVR->getDecl();
- if (VD->hasAttr<CleanupAttr>()) {
- escapes = true;
- }
- }
-
- // If our store can represent the binding and we aren't storing to something
- // that doesn't have local storage then just return and have the simulation
- // state continue as is.
- if (!escapes)
- return;
-
- // Otherwise, find all symbols referenced by 'val' that we are tracking
- // and stop tracking them.
- state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
- C.addTransition(state);
-}
-
-ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
- SVal Cond,
- bool Assumption) const {
- // FIXME: We may add to the interface of evalAssume the list of symbols
- // whose assumptions have changed. For now we just iterate through the
- // bindings and check if any of the tracked symbols are NULL. This isn't
- // too bad since the number of symbols we will track in practice are
- // probably small and evalAssume is only called at branches and a few
- // other places.
- RefBindingsTy B = state->get<RefBindings>();
-
- if (B.isEmpty())
- return state;
-
- bool changed = false;
- RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
-
- for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- // Check if the symbol is null stop tracking the symbol.
- ConstraintManager &CMgr = state->getConstraintManager();
- ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
- if (AllocFailed.isConstrainedTrue()) {
- changed = true;
- B = RefBFactory.remove(B, I.getKey());
- }
- }
-
- if (changed)
- state = state->set<RefBindings>(B);
-
- return state;
-}
-
-ProgramStateRef
-RetainCountChecker::checkRegionChanges(ProgramStateRef state,
- const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const LocationContext *LCtx,
- const CallEvent *Call) const {
- if (!invalidated)
- return state;
-
- llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
- for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
- E = ExplicitRegions.end(); I != E; ++I) {
- if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
- WhitelistedSymbols.insert(SR->getSymbol());
- }
-
- for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
- E = invalidated->end(); I!=E; ++I) {
- SymbolRef sym = *I;
- if (WhitelistedSymbols.count(sym))
- continue;
- // Remove any existing reference-count binding.
- state = removeRefBinding(state, sym);
- }
- return state;
-}
-
-//===----------------------------------------------------------------------===//
-// Handle dead symbols and end-of-path.
-//===----------------------------------------------------------------------===//
-
-ProgramStateRef
-RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
- ExplodedNode *Pred,
- const ProgramPointTag *Tag,
- CheckerContext &Ctx,
- SymbolRef Sym, RefVal V) const {
- unsigned ACnt = V.getAutoreleaseCount();
-
- // No autorelease counts? Nothing to be done.
- if (!ACnt)
- return state;
-
- assert(!Ctx.isObjCGCEnabled() && "Autorelease counts in GC mode?");
- unsigned Cnt = V.getCount();
-
- // FIXME: Handle sending 'autorelease' to already released object.
-
- if (V.getKind() == RefVal::ReturnedOwned)
- ++Cnt;
-
- // If we would over-release here, but we know the value came from an ivar,
- // assume it was a strong ivar that's just been relinquished.
- if (ACnt > Cnt &&
- V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
- V = V.releaseViaIvar();
- --ACnt;
- }
-
- if (ACnt <= Cnt) {
- if (ACnt == Cnt) {
- V.clearCounts();
- if (V.getKind() == RefVal::ReturnedOwned)
- V = V ^ RefVal::ReturnedNotOwned;
- else
- V = V ^ RefVal::NotOwned;
- } else {
- V.setCount(V.getCount() - ACnt);
- V.setAutoreleaseCount(0);
- }
- return setRefBinding(state, Sym, V);
- }
-
- // HACK: Ignore retain-count issues on values accessed through ivars,
- // because of cases like this:
- // [_contentView retain];
- // [_contentView removeFromSuperview];
- // [self addSubview:_contentView]; // invalidates 'self'
- // [_contentView release];
- if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
- return state;
-
- // Woah! More autorelease counts then retain counts left.
- // Emit hard error.
- V = V ^ RefVal::ErrorOverAutorelease;
- state = setRefBinding(state, Sym, V);
-
- ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
- if (N) {
- SmallString<128> sbuf;
- llvm::raw_svector_ostream os(sbuf);
- os << "Object was autoreleased ";
- if (V.getAutoreleaseCount() > 1)
- os << V.getAutoreleaseCount() << " times but the object ";
- else
- os << "but ";
- os << "has a +" << V.getCount() << " retain count";
-
- if (!overAutorelease)
- overAutorelease.reset(new OverAutorelease(this));
-
- const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
- Ctx.emitReport(std::unique_ptr<BugReport>(
- new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
- SummaryLog, N, Sym, os.str())));
- }
-
- return nullptr;
-}
-
-ProgramStateRef
-RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
- SymbolRef sid, RefVal V,
- SmallVectorImpl<SymbolRef> &Leaked) const {
- bool hasLeak;
-
- // HACK: Ignore retain-count issues on values accessed through ivars,
- // because of cases like this:
- // [_contentView retain];
- // [_contentView removeFromSuperview];
- // [self addSubview:_contentView]; // invalidates 'self'
- // [_contentView release];
- if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
- hasLeak = false;
- else if (V.isOwned())
- hasLeak = true;
- else if (V.isNotOwned() || V.isReturnedOwned())
- hasLeak = (V.getCount() > 0);
- else
- hasLeak = false;
-
- if (!hasLeak)
- return removeRefBinding(state, sid);
-
- Leaked.push_back(sid);
- return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
-}
-
-ExplodedNode *
-RetainCountChecker::processLeaks(ProgramStateRef state,
- SmallVectorImpl<SymbolRef> &Leaked,
- CheckerContext &Ctx,
- ExplodedNode *Pred) const {
- // Generate an intermediate node representing the leak point.
- ExplodedNode *N = Ctx.addTransition(state, Pred);
-
- if (N) {
- for (SmallVectorImpl<SymbolRef>::iterator
- I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
-
- const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
- bool GCEnabled = Ctx.isObjCGCEnabled();
- CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
- : getLeakAtReturnBug(LOpts, GCEnabled);
- assert(BT && "BugType not initialized.");
-
- Ctx.emitReport(std::unique_ptr<BugReport>(
- new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
- IncludeAllocationLine)));
- }
- }
-
- return N;
-}
-
-void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
- if (!Ctx.inTopFrame())
- return;
-
- const LocationContext *LCtx = Ctx.getLocationContext();
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
-
- if (!FD || isTrustedReferenceCountImplementation(FD))
- return;
-
- ProgramStateRef state = Ctx.getState();
-
- const RetainSummary *FunctionSummary = getSummaryManager(Ctx).getFunctionSummary(FD);
- ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
-
- for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
- const ParmVarDecl *Param = FD->getParamDecl(idx);
- SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
-
- QualType Ty = Param->getType();
- const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
- if (AE && *AE == DecRef && isGeneralizedObjectRef(Ty))
- state = setRefBinding(state, Sym, RefVal::makeOwned(RetEffect::ObjKind::Generalized, Ty));
- else if (isGeneralizedObjectRef(Ty))
- state = setRefBinding(state, Sym, RefVal::makeNotOwned(RetEffect::ObjKind::Generalized, Ty));
- }
-
- Ctx.addTransition(state);
-}
-
-void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
- CheckerContext &Ctx) const {
- ProgramStateRef state = Ctx.getState();
- RefBindingsTy B = state->get<RefBindings>();
- ExplodedNode *Pred = Ctx.getPredecessor();
-
- // Don't process anything within synthesized bodies.
- const LocationContext *LCtx = Pred->getLocationContext();
- if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
- assert(!LCtx->inTopFrame());
- return;
- }
-
- for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
- I->first, I->second);
- if (!state)
- return;
- }
-
- // If the current LocationContext has a parent, don't check for leaks.
- // We will do that later.
- // FIXME: we should instead check for imbalances of the retain/releases,
- // and suggest annotations.
- if (LCtx->getParent())
- return;
-
- B = state->get<RefBindings>();
- SmallVector<SymbolRef, 10> Leaked;
-
- for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
- state = handleSymbolDeath(state, I->first, I->second, Leaked);
-
- processLeaks(state, Leaked, Ctx, Pred);
-}
-
-const ProgramPointTag *
-RetainCountChecker::getDeadSymbolTag(SymbolRef sym) const {
- const CheckerProgramPointTag *&tag = DeadSymbolTags[sym];
- if (!tag) {
- SmallString<64> buf;
- llvm::raw_svector_ostream out(buf);
- out << "Dead Symbol : ";
- sym->dumpToStream(out);
- tag = new CheckerProgramPointTag(this, out.str());
- }
- return tag;
-}
-
-void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
- CheckerContext &C) const {
- ExplodedNode *Pred = C.getPredecessor();
-
- ProgramStateRef state = C.getState();
- RefBindingsTy B = state->get<RefBindings>();
- SmallVector<SymbolRef, 10> Leaked;
-
- // Update counts from autorelease pools
- for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
- E = SymReaper.dead_end(); I != E; ++I) {
- SymbolRef Sym = *I;
- if (const RefVal *T = B.lookup(Sym)){
- // Use the symbol as the tag.
- // FIXME: This might not be as unique as we would like.
- const ProgramPointTag *Tag = getDeadSymbolTag(Sym);
- state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
- if (!state)
- return;
-
- // Fetch the new reference count from the state, and use it to handle
- // this symbol.
- state = handleSymbolDeath(state, *I, *getRefBinding(state, Sym), Leaked);
- }
- }
-
- if (Leaked.empty()) {
- C.addTransition(state);
- return;
- }
-
- Pred = processLeaks(state, Leaked, C, Pred);
-
- // Did we cache out?
- if (!Pred)
- return;
-
- // Now generate a new node that nukes the old bindings.
- // The only bindings left at this point are the leaked symbols.
- RefBindingsTy::Factory &F = state->get_context<RefBindings>();
- B = state->get<RefBindings>();
-
- for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
- E = Leaked.end();
- I != E; ++I)
- B = F.remove(B, *I);
-
- state = state->set<RefBindings>(B);
- C.addTransition(state, Pred);
-}
-
-void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) const {
-
- RefBindingsTy B = State->get<RefBindings>();
-
- if (B.isEmpty())
- return;
-
- Out << Sep << NL;
-
- for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- Out << I->first << " : ";
- I->second.print(Out);
- Out << NL;
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Checker registration.
-//===----------------------------------------------------------------------===//
-
-void ento::registerRetainCountChecker(CheckerManager &Mgr) {
- Mgr.registerChecker<RetainCountChecker>(Mgr.getAnalyzerOptions());
-}
-
-//===----------------------------------------------------------------------===//
-// Implementation of the CallEffects API.
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-namespace ento {
-namespace objc_retain {
-
-// This is a bit gross, but it allows us to populate CallEffects without
-// creating a bunch of accessors. This kind is very localized, so the
-// damage of this macro is limited.
-#define createCallEffect(D, KIND)\
- ASTContext &Ctx = D->getASTContext();\
- LangOptions L = Ctx.getLangOpts();\
- RetainSummaryManager M(Ctx, L.GCOnly, L.ObjCAutoRefCount);\
- const RetainSummary *S = M.get ## KIND ## Summary(D);\
- CallEffects CE(S->getRetEffect());\
- CE.Receiver = S->getReceiverEffect();\
- unsigned N = D->param_size();\
- for (unsigned i = 0; i < N; ++i) {\
- CE.Args.push_back(S->getArg(i));\
- }
-
-CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
- createCallEffect(MD, Method);
- return CE;
-}
-
-CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
- createCallEffect(FD, Function);
- return CE;
-}
-
-#undef createCallEffect
-
-} // end namespace objc_retain
-} // end namespace ento
-} // end namespace clang
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
new file mode 100644
index 000000000000..0652af856643
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -0,0 +1,1547 @@
+//==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the methods for RetainCountChecker, which implements
+// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#include "RetainCountChecker.h"
+
+using namespace clang;
+using namespace ento;
+using namespace retaincountchecker;
+using llvm::StrInStrNoCase;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
+
+namespace clang {
+namespace ento {
+namespace retaincountchecker {
+
+const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym) {
+ return State->get<RefBindings>(Sym);
+}
+
+ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym,
+ RefVal Val) {
+ assert(Sym != nullptr);
+ return State->set<RefBindings>(Sym, Val);
+}
+
+ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
+ return State->remove<RefBindings>(Sym);
+}
+
+class UseAfterRelease : public RefCountBug {
+public:
+ UseAfterRelease(const CheckerBase *checker)
+ : RefCountBug(checker, "Use-after-release") {}
+
+ const char *getDescription() const override {
+ return "Reference-counted object is used after it is released";
+ }
+};
+
+class BadRelease : public RefCountBug {
+public:
+ BadRelease(const CheckerBase *checker) : RefCountBug(checker, "Bad release") {}
+
+ const char *getDescription() const override {
+ return "Incorrect decrement of the reference count of an object that is "
+ "not owned at this point by the caller";
+ }
+};
+
+class DeallocNotOwned : public RefCountBug {
+public:
+ DeallocNotOwned(const CheckerBase *checker)
+ : RefCountBug(checker, "-dealloc sent to non-exclusively owned object") {}
+
+ const char *getDescription() const override {
+ return "-dealloc sent to object that may be referenced elsewhere";
+ }
+};
+
+class OverAutorelease : public RefCountBug {
+public:
+ OverAutorelease(const CheckerBase *checker)
+ : RefCountBug(checker, "Object autoreleased too many times") {}
+
+ const char *getDescription() const override {
+ return "Object autoreleased too many times";
+ }
+};
+
+class ReturnedNotOwnedForOwned : public RefCountBug {
+public:
+ ReturnedNotOwnedForOwned(const CheckerBase *checker)
+ : RefCountBug(checker, "Method should return an owned object") {}
+
+ const char *getDescription() const override {
+ return "Object with a +0 retain count returned to caller where a +1 "
+ "(owning) retain count is expected";
+ }
+};
+
+class Leak : public RefCountBug {
+public:
+ Leak(const CheckerBase *checker, StringRef name) : RefCountBug(checker, name) {
+ // Leaks should not be reported if they are post-dominated by a sink.
+ setSuppressOnSink(true);
+ }
+
+ const char *getDescription() const override { return ""; }
+
+ bool isLeak() const override { return true; }
+};
+
+} // end namespace retaincountchecker
+} // end namespace ento
+} // end namespace clang
+
+void RefVal::print(raw_ostream &Out) const {
+ if (!T.isNull())
+ Out << "Tracked " << T.getAsString() << " | ";
+
+ switch (getKind()) {
+ default: llvm_unreachable("Invalid RefVal kind");
+ case Owned: {
+ Out << "Owned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case NotOwned: {
+ Out << "NotOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case ReturnedOwned: {
+ Out << "ReturnedOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case ReturnedNotOwned: {
+ Out << "ReturnedNotOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case Released:
+ Out << "Released";
+ break;
+
+ case ErrorDeallocNotOwned:
+ Out << "-dealloc (not-owned)";
+ break;
+
+ case ErrorLeak:
+ Out << "Leaked";
+ break;
+
+ case ErrorLeakReturned:
+ Out << "Leaked (Bad naming)";
+ break;
+
+ case ErrorUseAfterRelease:
+ Out << "Use-After-Release [ERROR]";
+ break;
+
+ case ErrorReleaseNotOwned:
+ Out << "Release of Not-Owned [ERROR]";
+ break;
+
+ case RefVal::ErrorOverAutorelease:
+ Out << "Over-autoreleased";
+ break;
+
+ case RefVal::ErrorReturnedNotOwned:
+ Out << "Non-owned object returned instead of owned";
+ break;
+ }
+
+ switch (getIvarAccessHistory()) {
+ case IvarAccessHistory::None:
+ break;
+ case IvarAccessHistory::AccessedDirectly:
+ Out << " [direct ivar access]";
+ break;
+ case IvarAccessHistory::ReleasedAfterDirectAccess:
+ Out << " [released after direct ivar access]";
+ }
+
+ if (ACnt) {
+ Out << " [autorelease -" << ACnt << ']';
+ }
+}
+
+namespace {
+class StopTrackingCallback final : public SymbolVisitor {
+ ProgramStateRef state;
+public:
+ StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
+ ProgramStateRef getState() const { return state; }
+
+ bool VisitSymbol(SymbolRef sym) override {
+ state = state->remove<RefBindings>(sym);
+ return true;
+ }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Handle statements that may have an effect on refcounts.
+//===----------------------------------------------------------------------===//
+
+void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
+ CheckerContext &C) const {
+
+ // Scan the BlockDecRefExprs for any object the retain count checker
+ // may be tracking.
+ if (!BE->getBlockDecl()->hasCaptures())
+ return;
+
+ ProgramStateRef state = C.getState();
+ auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
+
+ BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
+ E = R->referenced_vars_end();
+
+ if (I == E)
+ return;
+
+ // FIXME: For now we invalidate the tracking of all symbols passed to blocks
+ // via captured variables, even though captured variables result in a copy
+ // and in implicit increment/decrement of a retain count.
+ SmallVector<const MemRegion*, 10> Regions;
+ const LocationContext *LC = C.getLocationContext();
+ MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
+
+ for ( ; I != E; ++I) {
+ const VarRegion *VR = I.getCapturedRegion();
+ if (VR->getSuperRegion() == R) {
+ VR = MemMgr.getVarRegion(VR->getDecl(), LC);
+ }
+ Regions.push_back(VR);
+ }
+
+ state = state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
+ C.addTransition(state);
+}
+
+void RetainCountChecker::checkPostStmt(const CastExpr *CE,
+ CheckerContext &C) const {
+ const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
+ if (!BE)
+ return;
+
+ ArgEffect AE = ArgEffect(IncRef, ObjKind::ObjC);
+
+ switch (BE->getBridgeKind()) {
+ case OBC_Bridge:
+ // Do nothing.
+ return;
+ case OBC_BridgeRetained:
+ AE = AE.withKind(IncRef);
+ break;
+ case OBC_BridgeTransfer:
+ AE = AE.withKind(DecRefBridgedTransferred);
+ break;
+ }
+
+ ProgramStateRef state = C.getState();
+ SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();
+ if (!Sym)
+ return;
+ const RefVal* T = getRefBinding(state, Sym);
+ if (!T)
+ return;
+
+ RefVal::Kind hasErr = (RefVal::Kind) 0;
+ state = updateSymbol(state, Sym, *T, AE, hasErr, C);
+
+ if (hasErr) {
+ // FIXME: If we get an error during a bridge cast, should we report it?
+ return;
+ }
+
+ C.addTransition(state);
+}
+
+void RetainCountChecker::processObjCLiterals(CheckerContext &C,
+ const Expr *Ex) const {
+ ProgramStateRef state = C.getState();
+ const ExplodedNode *pred = C.getPredecessor();
+ for (const Stmt *Child : Ex->children()) {
+ SVal V = pred->getSVal(Child);
+ if (SymbolRef sym = V.getAsSymbol())
+ if (const RefVal* T = getRefBinding(state, sym)) {
+ RefVal::Kind hasErr = (RefVal::Kind) 0;
+ state = updateSymbol(state, sym, *T,
+ ArgEffect(MayEscape, ObjKind::ObjC), hasErr, C);
+ if (hasErr) {
+ processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
+ return;
+ }
+ }
+ }
+
+ // Return the object as autoreleased.
+ // RetEffect RE = RetEffect::MakeNotOwned(ObjKind::ObjC);
+ if (SymbolRef sym =
+ state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
+ QualType ResultTy = Ex->getType();
+ state = setRefBinding(state, sym,
+ RefVal::makeNotOwned(ObjKind::ObjC, ResultTy));
+ }
+
+ C.addTransition(state);
+}
+
+void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
+ CheckerContext &C) const {
+ // Apply the 'MayEscape' to all values.
+ processObjCLiterals(C, AL);
+}
+
+void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
+ CheckerContext &C) const {
+ // Apply the 'MayEscape' to all keys and values.
+ processObjCLiterals(C, DL);
+}
+
+void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
+ CheckerContext &C) const {
+ const ExplodedNode *Pred = C.getPredecessor();
+ ProgramStateRef State = Pred->getState();
+
+ if (SymbolRef Sym = Pred->getSVal(Ex).getAsSymbol()) {
+ QualType ResultTy = Ex->getType();
+ State = setRefBinding(State, Sym,
+ RefVal::makeNotOwned(ObjKind::ObjC, ResultTy));
+ }
+
+ C.addTransition(State);
+}
+
+void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
+ CheckerContext &C) const {
+ Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
+ if (!IVarLoc)
+ return;
+
+ ProgramStateRef State = C.getState();
+ SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
+ if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->getOriginRegion()))
+ return;
+
+ // Accessing an ivar directly is unusual. If we've done that, be more
+ // forgiving about what the surrounding code is allowed to do.
+
+ QualType Ty = Sym->getType();
+ ObjKind Kind;
+ if (Ty->isObjCRetainableType())
+ Kind = ObjKind::ObjC;
+ else if (coreFoundation::isCFObjectRef(Ty))
+ Kind = ObjKind::CF;
+ else
+ return;
+
+ // If the value is already known to be nil, don't bother tracking it.
+ ConstraintManager &CMgr = State->getConstraintManager();
+ if (CMgr.isNull(State, Sym).isConstrainedTrue())
+ return;
+
+ if (const RefVal *RV = getRefBinding(State, Sym)) {
+ // If we've seen this symbol before, or we're only seeing it now because
+ // of something the analyzer has synthesized, don't do anything.
+ if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
+ isSynthesizedAccessor(C.getStackFrame())) {
+ return;
+ }
+
+ // Note that this value has been loaded from an ivar.
+ C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
+ return;
+ }
+
+ RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
+
+ // In a synthesized accessor, the effective retain count is +0.
+ if (isSynthesizedAccessor(C.getStackFrame())) {
+ C.addTransition(setRefBinding(State, Sym, PlusZero));
+ return;
+ }
+
+ State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
+ C.addTransition(State);
+}
+
+void RetainCountChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ RetainSummaryManager &Summaries = getSummaryManager(C);
+
+ // Leave null if no receiver.
+ QualType ReceiverType;
+ if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) {
+ if (MC->isInstanceMessage()) {
+ SVal ReceiverV = MC->getReceiverSVal();
+ if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
+ if (const RefVal *T = getRefBinding(C.getState(), Sym))
+ ReceiverType = T->getType();
+ }
+ }
+
+ const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType);
+
+ if (C.wasInlined) {
+ processSummaryOfInlined(*Summ, Call, C);
+ return;
+ }
+ checkSummary(*Summ, Call, C);
+}
+
+RefCountBug *
+RetainCountChecker::getLeakWithinFunctionBug(const LangOptions &LOpts) const {
+ if (!leakWithinFunction)
+ leakWithinFunction.reset(new Leak(this, "Leak"));
+ return leakWithinFunction.get();
+}
+
+RefCountBug *
+RetainCountChecker::getLeakAtReturnBug(const LangOptions &LOpts) const {
+ if (!leakAtReturn)
+ leakAtReturn.reset(new Leak(this, "Leak of returned object"));
+ return leakAtReturn.get();
+}
+
+/// GetReturnType - Used to get the return type of a message expression or
+/// function call with the intention of affixing that type to a tracked symbol.
+/// While the return type can be queried directly from RetEx, when
+/// invoking class methods we augment to the return type to be that of
+/// a pointer to the class (as opposed it just being id).
+// FIXME: We may be able to do this with related result types instead.
+// This function is probably overestimating.
+static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
+ QualType RetTy = RetE->getType();
+ // If RetE is not a message expression just return its type.
+ // If RetE is a message expression, return its types if it is something
+ /// more specific than id.
+ if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
+ if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
+ if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
+ PT->isObjCClassType()) {
+ // At this point we know the return type of the message expression is
+ // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
+ // is a call to a class method whose type we can resolve. In such
+ // cases, promote the return type to XXX* (where XXX is the class).
+ const ObjCInterfaceDecl *D = ME->getReceiverInterface();
+ return !D ? RetTy :
+ Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
+ }
+
+ return RetTy;
+}
+
+static Optional<RefVal> refValFromRetEffect(RetEffect RE,
+ QualType ResultTy) {
+ if (RE.isOwned()) {
+ return RefVal::makeOwned(RE.getObjKind(), ResultTy);
+ } else if (RE.notOwned()) {
+ return RefVal::makeNotOwned(RE.getObjKind(), ResultTy);
+ }
+
+ return None;
+}
+
+static bool isPointerToObject(QualType QT) {
+ QualType PT = QT->getPointeeType();
+ if (!PT.isNull())
+ if (PT->getAsCXXRecordDecl())
+ return true;
+ return false;
+}
+
+/// Whether the tracked value should be escaped on a given call.
+/// OSObjects are escaped when passed to void * / etc.
+static bool shouldEscapeOSArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
+ const RefVal *TrackedValue) {
+ if (TrackedValue->getObjKind() != ObjKind::OS)
+ return false;
+ if (ArgIdx >= CE.parameters().size())
+ return false;
+ return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
+}
+
+// We don't always get the exact modeling of the function with regards to the
+// retain count checker even when the function is inlined. For example, we need
+// to stop tracking the symbols which were marked with StopTrackingHard.
+void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
+ const CallEvent &CallOrMsg,
+ CheckerContext &C) const {
+ ProgramStateRef state = C.getState();
+
+ // Evaluate the effect of the arguments.
+ for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
+ SVal V = CallOrMsg.getArgSVal(idx);
+
+ if (SymbolRef Sym = V.getAsLocSymbol()) {
+ bool ShouldRemoveBinding = Summ.getArg(idx).getKind() == StopTrackingHard;
+ if (const RefVal *T = getRefBinding(state, Sym))
+ if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T))
+ ShouldRemoveBinding = true;
+
+ if (ShouldRemoveBinding)
+ state = removeRefBinding(state, Sym);
+ }
+ }
+
+ // Evaluate the effect on the message receiver.
+ if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
+ if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
+ if (Summ.getReceiverEffect().getKind() == StopTrackingHard) {
+ state = removeRefBinding(state, Sym);
+ }
+ }
+ }
+
+ // Consult the summary for the return value.
+ RetEffect RE = Summ.getRetEffect();
+
+ if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
+ if (RE.getKind() == RetEffect::NoRetHard)
+ state = removeRefBinding(state, Sym);
+ }
+
+ C.addTransition(state);
+}
+
+static bool shouldEscapeRegion(const MemRegion *R) {
+
+ // We do not currently model what happens when a symbol is
+ // assigned to a struct field, so be conservative here and let the symbol
+ // go. TODO: This could definitely be improved upon.
+ return !R->hasStackStorage() || !isa<VarRegion>(R);
+}
+
+static SmallVector<ProgramStateRef, 2>
+updateOutParameters(ProgramStateRef State, const RetainSummary &Summ,
+ const CallEvent &CE) {
+
+ SVal L = CE.getReturnValue();
+
+ // Splitting is required to support out parameters,
+ // as out parameters might be created only on the "success" branch.
+ // We want to avoid eagerly splitting unless out parameters are actually
+ // needed.
+ bool SplitNecessary = false;
+ for (auto &P : Summ.getArgEffects())
+ if (P.second.getKind() == RetainedOutParameterOnNonZero ||
+ P.second.getKind() == RetainedOutParameterOnZero)
+ SplitNecessary = true;
+
+ ProgramStateRef AssumeNonZeroReturn = State;
+ ProgramStateRef AssumeZeroReturn = State;
+
+ if (SplitNecessary) {
+ if (auto DL = L.getAs<DefinedOrUnknownSVal>()) {
+ AssumeNonZeroReturn = AssumeNonZeroReturn->assume(*DL, true);
+ AssumeZeroReturn = AssumeZeroReturn->assume(*DL, false);
+ }
+ }
+
+ for (unsigned idx = 0, e = CE.getNumArgs(); idx != e; ++idx) {
+ SVal ArgVal = CE.getArgSVal(idx);
+ ArgEffect AE = Summ.getArg(idx);
+
+ auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
+ if (!ArgRegion)
+ continue;
+
+ QualType PointeeTy = ArgRegion->getValueType();
+ SVal PointeeVal = State->getSVal(ArgRegion);
+ SymbolRef Pointee = PointeeVal.getAsLocSymbol();
+ if (!Pointee)
+ continue;
+
+ if (shouldEscapeRegion(ArgRegion))
+ continue;
+
+ auto makeNotOwnedParameter = [&](ProgramStateRef St) {
+ return setRefBinding(St, Pointee,
+ RefVal::makeNotOwned(AE.getObjKind(), PointeeTy));
+ };
+ auto makeOwnedParameter = [&](ProgramStateRef St) {
+ return setRefBinding(St, Pointee,
+ RefVal::makeOwned(ObjKind::OS, PointeeTy));
+ };
+
+ switch (AE.getKind()) {
+ case UnretainedOutParameter:
+ AssumeNonZeroReturn = makeNotOwnedParameter(AssumeNonZeroReturn);
+ AssumeZeroReturn = makeNotOwnedParameter(AssumeZeroReturn);
+ break;
+ case RetainedOutParameter:
+ AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
+ AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
+ break;
+ case RetainedOutParameterOnNonZero:
+ AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
+ break;
+ case RetainedOutParameterOnZero:
+ AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (SplitNecessary) {
+ return {AssumeNonZeroReturn, AssumeZeroReturn};
+ } else {
+ assert(AssumeZeroReturn == AssumeNonZeroReturn);
+ return {AssumeZeroReturn};
+ }
+}
+
+void RetainCountChecker::checkSummary(const RetainSummary &Summ,
+ const CallEvent &CallOrMsg,
+ CheckerContext &C) const {
+ ProgramStateRef state = C.getState();
+
+ // Evaluate the effect of the arguments.
+ RefVal::Kind hasErr = (RefVal::Kind) 0;
+ SourceRange ErrorRange;
+ SymbolRef ErrorSym = nullptr;
+
+ // Helper tag for providing diagnostics: indicate whether dealloc was sent
+ // at this location.
+ static CheckerProgramPointTag DeallocSentTag(this, DeallocTagDescription);
+ bool DeallocSent = false;
+
+ for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
+ SVal V = CallOrMsg.getArgSVal(idx);
+
+ ArgEffect Effect = Summ.getArg(idx);
+ if (SymbolRef Sym = V.getAsLocSymbol()) {
+ if (const RefVal *T = getRefBinding(state, Sym)) {
+
+ if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T))
+ Effect = ArgEffect(StopTrackingHard, ObjKind::OS);
+
+ state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
+ if (hasErr) {
+ ErrorRange = CallOrMsg.getArgSourceRange(idx);
+ ErrorSym = Sym;
+ break;
+ } else if (Effect.getKind() == Dealloc) {
+ DeallocSent = true;
+ }
+ }
+ }
+ }
+
+ // Evaluate the effect on the message receiver / `this` argument.
+ bool ReceiverIsTracked = false;
+ if (!hasErr) {
+ if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
+ if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
+ if (const RefVal *T = getRefBinding(state, Sym)) {
+ ReceiverIsTracked = true;
+ state = updateSymbol(state, Sym, *T,
+ Summ.getReceiverEffect(), hasErr, C);
+ if (hasErr) {
+ ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
+ ErrorSym = Sym;
+ } else if (Summ.getReceiverEffect().getKind() == Dealloc) {
+ DeallocSent = true;
+ }
+ }
+ }
+ } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
+ if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
+ if (const RefVal *T = getRefBinding(state, Sym)) {
+ state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
+ hasErr, C);
+ if (hasErr) {
+ ErrorRange = MCall->getOriginExpr()->getSourceRange();
+ ErrorSym = Sym;
+ }
+ }
+ }
+ }
+ }
+
+ // Process any errors.
+ if (hasErr) {
+ processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
+ return;
+ }
+
+ // Consult the summary for the return value.
+ RetEffect RE = Summ.getRetEffect();
+
+ if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
+ if (ReceiverIsTracked)
+ RE = getSummaryManager(C).getObjAllocRetEffect();
+ else
+ RE = RetEffect::MakeNoRet();
+ }
+
+ if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
+ QualType ResultTy = CallOrMsg.getResultType();
+ if (RE.notOwned()) {
+ const Expr *Ex = CallOrMsg.getOriginExpr();
+ assert(Ex);
+ ResultTy = GetReturnType(Ex, C.getASTContext());
+ }
+ if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy))
+ state = setRefBinding(state, Sym, *updatedRefVal);
+ }
+
+ SmallVector<ProgramStateRef, 2> Out =
+ updateOutParameters(state, Summ, CallOrMsg);
+
+ for (ProgramStateRef St : Out) {
+ if (DeallocSent) {
+ C.addTransition(St, C.getPredecessor(), &DeallocSentTag);
+ } else {
+ C.addTransition(St);
+ }
+ }
+}
+
+ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state,
+ SymbolRef sym, RefVal V,
+ ArgEffect AE,
+ RefVal::Kind &hasErr,
+ CheckerContext &C) const {
+ bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
+ if (AE.getObjKind() == ObjKind::ObjC && IgnoreRetainMsg) {
+ switch (AE.getKind()) {
+ default:
+ break;
+ case IncRef:
+ AE = AE.withKind(DoNothing);
+ break;
+ case DecRef:
+ AE = AE.withKind(DoNothing);
+ break;
+ case DecRefAndStopTrackingHard:
+ AE = AE.withKind(StopTracking);
+ break;
+ }
+ }
+
+ // Handle all use-after-releases.
+ if (V.getKind() == RefVal::Released) {
+ V = V ^ RefVal::ErrorUseAfterRelease;
+ hasErr = V.getKind();
+ return setRefBinding(state, sym, V);
+ }
+
+ switch (AE.getKind()) {
+ case UnretainedOutParameter:
+ case RetainedOutParameter:
+ case RetainedOutParameterOnZero:
+ case RetainedOutParameterOnNonZero:
+ llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
+ "not have ref state.");
+
+ case Dealloc: // NB. we only need to add a note in a non-error case.
+ switch (V.getKind()) {
+ default:
+ llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
+ case RefVal::Owned:
+ // The object immediately transitions to the released state.
+ V = V ^ RefVal::Released;
+ V.clearCounts();
+ return setRefBinding(state, sym, V);
+ case RefVal::NotOwned:
+ V = V ^ RefVal::ErrorDeallocNotOwned;
+ hasErr = V.getKind();
+ break;
+ }
+ break;
+
+ case MayEscape:
+ if (V.getKind() == RefVal::Owned) {
+ V = V ^ RefVal::NotOwned;
+ break;
+ }
+
+ LLVM_FALLTHROUGH;
+
+ case DoNothing:
+ return state;
+
+ case Autorelease:
+ // Update the autorelease counts.
+ V = V.autorelease();
+ break;
+
+ case StopTracking:
+ case StopTrackingHard:
+ return removeRefBinding(state, sym);
+
+ case IncRef:
+ switch (V.getKind()) {
+ default:
+ llvm_unreachable("Invalid RefVal state for a retain.");
+ case RefVal::Owned:
+ case RefVal::NotOwned:
+ V = V + 1;
+ break;
+ }
+ break;
+
+ case DecRef:
+ case DecRefBridgedTransferred:
+ case DecRefAndStopTrackingHard:
+ switch (V.getKind()) {
+ default:
+ // case 'RefVal::Released' handled above.
+ llvm_unreachable("Invalid RefVal state for a release.");
+
+ case RefVal::Owned:
+ assert(V.getCount() > 0);
+ if (V.getCount() == 1) {
+ if (AE.getKind() == DecRefBridgedTransferred ||
+ V.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::AccessedDirectly)
+ V = V ^ RefVal::NotOwned;
+ else
+ V = V ^ RefVal::Released;
+ } else if (AE.getKind() == DecRefAndStopTrackingHard) {
+ return removeRefBinding(state, sym);
+ }
+
+ V = V - 1;
+ break;
+
+ case RefVal::NotOwned:
+ if (V.getCount() > 0) {
+ if (AE.getKind() == DecRefAndStopTrackingHard)
+ return removeRefBinding(state, sym);
+ V = V - 1;
+ } else if (V.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::AccessedDirectly) {
+ // Assume that the instance variable was holding on the object at
+ // +1, and we just didn't know.
+ if (AE.getKind() == DecRefAndStopTrackingHard)
+ return removeRefBinding(state, sym);
+ V = V.releaseViaIvar() ^ RefVal::Released;
+ } else {
+ V = V ^ RefVal::ErrorReleaseNotOwned;
+ hasErr = V.getKind();
+ }
+ break;
+ }
+ break;
+ }
+ return setRefBinding(state, sym, V);
+}
+
+void RetainCountChecker::processNonLeakError(ProgramStateRef St,
+ SourceRange ErrorRange,
+ RefVal::Kind ErrorKind,
+ SymbolRef Sym,
+ CheckerContext &C) const {
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (const RefVal *RV = getRefBinding(St, Sym))
+ if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return;
+
+ ExplodedNode *N = C.generateErrorNode(St);
+ if (!N)
+ return;
+
+ RefCountBug *BT;
+ switch (ErrorKind) {
+ default:
+ llvm_unreachable("Unhandled error.");
+ case RefVal::ErrorUseAfterRelease:
+ if (!useAfterRelease)
+ useAfterRelease.reset(new UseAfterRelease(this));
+ BT = useAfterRelease.get();
+ break;
+ case RefVal::ErrorReleaseNotOwned:
+ if (!releaseNotOwned)
+ releaseNotOwned.reset(new BadRelease(this));
+ BT = releaseNotOwned.get();
+ break;
+ case RefVal::ErrorDeallocNotOwned:
+ if (!deallocNotOwned)
+ deallocNotOwned.reset(new DeallocNotOwned(this));
+ BT = deallocNotOwned.get();
+ break;
+ }
+
+ assert(BT);
+ auto report = llvm::make_unique<RefCountReport>(
+ *BT, C.getASTContext().getLangOpts(), N, Sym);
+ report->addRange(ErrorRange);
+ C.emitReport(std::move(report));
+}
+
+//===----------------------------------------------------------------------===//
+// Handle the return values of retain-count-related functions.
+//===----------------------------------------------------------------------===//
+
+bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
+ // Get the callee. We're only interested in simple C functions.
+ ProgramStateRef state = C.getState();
+ const FunctionDecl *FD = C.getCalleeDecl(CE);
+ if (!FD)
+ return false;
+
+ RetainSummaryManager &SmrMgr = getSummaryManager(C);
+ QualType ResultTy = CE->getCallReturnType(C.getASTContext());
+
+ // See if the function has 'rc_ownership_trusted_implementation'
+ // annotate attribute. If it does, we will not inline it.
+ bool hasTrustedImplementationAnnotation = false;
+
+ const LocationContext *LCtx = C.getLocationContext();
+
+ using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
+ Optional<BehaviorSummary> BSmr =
+ SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
+
+ // See if it's one of the specific functions we know how to eval.
+ if (!BSmr)
+ return false;
+
+ // Bind the return value.
+ if (BSmr == BehaviorSummary::Identity ||
+ BSmr == BehaviorSummary::IdentityOrZero) {
+ SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
+
+ // If the receiver is unknown or the function has
+ // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
+ // return value.
+ if (RetVal.isUnknown() ||
+ (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
+ SValBuilder &SVB = C.getSValBuilder();
+ RetVal =
+ SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
+ }
+ state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
+
+ if (BSmr == BehaviorSummary::IdentityOrZero) {
+ // Add a branch where the output is zero.
+ ProgramStateRef NullOutputState = C.getState();
+
+ // Assume that output is zero on the other branch.
+ NullOutputState = NullOutputState->BindExpr(
+ CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
+
+ C.addTransition(NullOutputState);
+
+ // And on the original branch assume that both input and
+ // output are non-zero.
+ if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
+ state = state->assume(*L, /*Assumption=*/true);
+
+ }
+ }
+
+ C.addTransition(state);
+ return true;
+}
+
+ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
+ CheckerContext &C) const {
+ ExplodedNode *Pred = C.getPredecessor();
+
+ // Only adjust the reference count if this is the top-level call frame,
+ // and not the result of inlining. In the future, we should do
+ // better checking even for inlined calls, and see if they match
+ // with their expected semantics (e.g., the method should return a retained
+ // object, etc.).
+ if (!C.inTopFrame())
+ return Pred;
+
+ if (!S)
+ return Pred;
+
+ const Expr *RetE = S->getRetValue();
+ if (!RetE)
+ return Pred;
+
+ ProgramStateRef state = C.getState();
+ SymbolRef Sym =
+ state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
+ if (!Sym)
+ return Pred;
+
+ // Get the reference count binding (if any).
+ const RefVal *T = getRefBinding(state, Sym);
+ if (!T)
+ return Pred;
+
+ // Change the reference count.
+ RefVal X = *T;
+
+ switch (X.getKind()) {
+ case RefVal::Owned: {
+ unsigned cnt = X.getCount();
+ assert(cnt > 0);
+ X.setCount(cnt - 1);
+ X = X ^ RefVal::ReturnedOwned;
+ break;
+ }
+
+ case RefVal::NotOwned: {
+ unsigned cnt = X.getCount();
+ if (cnt) {
+ X.setCount(cnt - 1);
+ X = X ^ RefVal::ReturnedOwned;
+ } else {
+ X = X ^ RefVal::ReturnedNotOwned;
+ }
+ break;
+ }
+
+ default:
+ return Pred;
+ }
+
+ // Update the binding.
+ state = setRefBinding(state, Sym, X);
+ Pred = C.addTransition(state);
+
+ // At this point we have updated the state properly.
+ // Everything after this is merely checking to see if the return value has
+ // been over- or under-retained.
+
+ // Did we cache out?
+ if (!Pred)
+ return nullptr;
+
+ // Update the autorelease counts.
+ static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
+ state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
+
+ // Have we generated a sink node?
+ if (!state)
+ return nullptr;
+
+ // Get the updated binding.
+ T = getRefBinding(state, Sym);
+ assert(T);
+ X = *T;
+
+ // Consult the summary of the enclosing method.
+ RetainSummaryManager &Summaries = getSummaryManager(C);
+ const Decl *CD = &Pred->getCodeDecl();
+ RetEffect RE = RetEffect::MakeNoRet();
+
+ // FIXME: What is the convention for blocks? Is there one?
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
+ const RetainSummary *Summ = Summaries.getMethodSummary(MD);
+ RE = Summ->getRetEffect();
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
+ if (!isa<CXXMethodDecl>(FD)) {
+ const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
+ RE = Summ->getRetEffect();
+ }
+ }
+
+ return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
+}
+
+ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
+ CheckerContext &C,
+ ExplodedNode *Pred,
+ RetEffect RE, RefVal X,
+ SymbolRef Sym,
+ ProgramStateRef state) const {
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return Pred;
+
+ // Any leaks or other errors?
+ if (X.isReturnedOwned() && X.getCount() == 0) {
+ if (RE.getKind() != RetEffect::NoRet) {
+ if (!RE.isOwned()) {
+
+ // The returning type is a CF, we expect the enclosing method should
+ // return ownership.
+ X = X ^ RefVal::ErrorLeakReturned;
+
+ // Generate an error node.
+ state = setRefBinding(state, Sym, X);
+
+ static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
+ ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
+ if (N) {
+ const LangOptions &LOpts = C.getASTContext().getLangOpts();
+ auto R = llvm::make_unique<RefLeakReport>(
+ *getLeakAtReturnBug(LOpts), LOpts, N, Sym, C);
+ C.emitReport(std::move(R));
+ }
+ return N;
+ }
+ }
+ } else if (X.isReturnedNotOwned()) {
+ if (RE.isOwned()) {
+ if (X.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::AccessedDirectly) {
+ // Assume the method was trying to transfer a +1 reference from a
+ // strong ivar to the caller.
+ state = setRefBinding(state, Sym,
+ X.releaseViaIvar() ^ RefVal::ReturnedOwned);
+ } else {
+ // Trying to return a not owned object to a caller expecting an
+ // owned object.
+ state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
+
+ static CheckerProgramPointTag
+ ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
+
+ ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
+ if (N) {
+ if (!returnNotOwnedForOwned)
+ returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
+
+ auto R = llvm::make_unique<RefCountReport>(
+ *returnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym);
+ C.emitReport(std::move(R));
+ }
+ return N;
+ }
+ }
+ }
+ return Pred;
+}
+
+//===----------------------------------------------------------------------===//
+// Check various ways a symbol can be invalidated.
+//===----------------------------------------------------------------------===//
+
+void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
+ CheckerContext &C) const {
+ // Are we storing to something that causes the value to "escape"?
+ bool escapes = true;
+
+ // A value escapes in three possible cases (this may change):
+ //
+ // (1) we are binding to something that is not a memory region.
+ // (2) we are binding to a memregion that does not have stack storage
+ ProgramStateRef state = C.getState();
+
+ if (auto regionLoc = loc.getAs<loc::MemRegionVal>()) {
+ escapes = shouldEscapeRegion(regionLoc->getRegion());
+ }
+
+ // If we are storing the value into an auto function scope variable annotated
+ // with (__attribute__((cleanup))), stop tracking the value to avoid leak
+ // false positives.
+ if (const auto *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) {
+ const VarDecl *VD = LVR->getDecl();
+ if (VD->hasAttr<CleanupAttr>()) {
+ escapes = true;
+ }
+ }
+
+ // If our store can represent the binding and we aren't storing to something
+ // that doesn't have local storage then just return and have the simulation
+ // state continue as is.
+ if (!escapes)
+ return;
+
+ // Otherwise, find all symbols referenced by 'val' that we are tracking
+ // and stop tracking them.
+ state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
+ C.addTransition(state);
+}
+
+ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
+ SVal Cond,
+ bool Assumption) const {
+ // FIXME: We may add to the interface of evalAssume the list of symbols
+ // whose assumptions have changed. For now we just iterate through the
+ // bindings and check if any of the tracked symbols are NULL. This isn't
+ // too bad since the number of symbols we will track in practice are
+ // probably small and evalAssume is only called at branches and a few
+ // other places.
+ RefBindingsTy B = state->get<RefBindings>();
+
+ if (B.isEmpty())
+ return state;
+
+ bool changed = false;
+ RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
+
+ for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ // Check if the symbol is null stop tracking the symbol.
+ ConstraintManager &CMgr = state->getConstraintManager();
+ ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
+ if (AllocFailed.isConstrainedTrue()) {
+ changed = true;
+ B = RefBFactory.remove(B, I.getKey());
+ }
+ }
+
+ if (changed)
+ state = state->set<RefBindings>(B);
+
+ return state;
+}
+
+ProgramStateRef
+RetainCountChecker::checkRegionChanges(ProgramStateRef state,
+ const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const LocationContext *LCtx,
+ const CallEvent *Call) const {
+ if (!invalidated)
+ return state;
+
+ llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
+ for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
+ E = ExplicitRegions.end(); I != E; ++I) {
+ if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
+ WhitelistedSymbols.insert(SR->getSymbol());
+ }
+
+ for (SymbolRef sym :
+ llvm::make_range(invalidated->begin(), invalidated->end())) {
+ if (WhitelistedSymbols.count(sym))
+ continue;
+ // Remove any existing reference-count binding.
+ state = removeRefBinding(state, sym);
+ }
+ return state;
+}
+
+ProgramStateRef
+RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
+ ExplodedNode *Pred,
+ const ProgramPointTag *Tag,
+ CheckerContext &Ctx,
+ SymbolRef Sym,
+ RefVal V,
+ const ReturnStmt *S) const {
+ unsigned ACnt = V.getAutoreleaseCount();
+
+ // No autorelease counts? Nothing to be done.
+ if (!ACnt)
+ return state;
+
+ unsigned Cnt = V.getCount();
+
+ // FIXME: Handle sending 'autorelease' to already released object.
+
+ if (V.getKind() == RefVal::ReturnedOwned)
+ ++Cnt;
+
+ // If we would over-release here, but we know the value came from an ivar,
+ // assume it was a strong ivar that's just been relinquished.
+ if (ACnt > Cnt &&
+ V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
+ V = V.releaseViaIvar();
+ --ACnt;
+ }
+
+ if (ACnt <= Cnt) {
+ if (ACnt == Cnt) {
+ V.clearCounts();
+ if (V.getKind() == RefVal::ReturnedOwned) {
+ V = V ^ RefVal::ReturnedNotOwned;
+ } else {
+ V = V ^ RefVal::NotOwned;
+ }
+ } else {
+ V.setCount(V.getCount() - ACnt);
+ V.setAutoreleaseCount(0);
+ }
+ return setRefBinding(state, Sym, V);
+ }
+
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ return state;
+
+ // Woah! More autorelease counts then retain counts left.
+ // Emit hard error.
+ V = V ^ RefVal::ErrorOverAutorelease;
+ state = setRefBinding(state, Sym, V);
+
+ ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
+ if (N) {
+ SmallString<128> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
+ os << "Object was autoreleased ";
+ if (V.getAutoreleaseCount() > 1)
+ os << V.getAutoreleaseCount() << " times but the object ";
+ else
+ os << "but ";
+ os << "has a +" << V.getCount() << " retain count";
+
+ if (!overAutorelease)
+ overAutorelease.reset(new OverAutorelease(this));
+
+ const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
+ auto R = llvm::make_unique<RefCountReport>(*overAutorelease, LOpts, N, Sym,
+ os.str());
+ Ctx.emitReport(std::move(R));
+ }
+
+ return nullptr;
+}
+
+ProgramStateRef
+RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
+ SymbolRef sid, RefVal V,
+ SmallVectorImpl<SymbolRef> &Leaked) const {
+ bool hasLeak;
+
+ // HACK: Ignore retain-count issues on values accessed through ivars,
+ // because of cases like this:
+ // [_contentView retain];
+ // [_contentView removeFromSuperview];
+ // [self addSubview:_contentView]; // invalidates 'self'
+ // [_contentView release];
+ if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
+ hasLeak = false;
+ else if (V.isOwned())
+ hasLeak = true;
+ else if (V.isNotOwned() || V.isReturnedOwned())
+ hasLeak = (V.getCount() > 0);
+ else
+ hasLeak = false;
+
+ if (!hasLeak)
+ return removeRefBinding(state, sid);
+
+ Leaked.push_back(sid);
+ return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
+}
+
+ExplodedNode *
+RetainCountChecker::processLeaks(ProgramStateRef state,
+ SmallVectorImpl<SymbolRef> &Leaked,
+ CheckerContext &Ctx,
+ ExplodedNode *Pred) const {
+ // Generate an intermediate node representing the leak point.
+ ExplodedNode *N = Ctx.addTransition(state, Pred);
+
+ if (N) {
+ for (SmallVectorImpl<SymbolRef>::iterator
+ I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
+
+ const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
+ RefCountBug *BT = Pred ? getLeakWithinFunctionBug(LOpts)
+ : getLeakAtReturnBug(LOpts);
+ assert(BT && "BugType not initialized.");
+
+ Ctx.emitReport(
+ llvm::make_unique<RefLeakReport>(*BT, LOpts, N, *I, Ctx));
+ }
+ }
+
+ return N;
+}
+
+static bool isISLObjectRef(QualType Ty) {
+ return StringRef(Ty.getAsString()).startswith("isl_");
+}
+
+void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
+ if (!Ctx.inTopFrame())
+ return;
+
+ RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
+ const LocationContext *LCtx = Ctx.getLocationContext();
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
+
+ if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
+ return;
+
+ ProgramStateRef state = Ctx.getState();
+ const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
+ ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
+
+ for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
+ const ParmVarDecl *Param = FD->getParamDecl(idx);
+ SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
+
+ QualType Ty = Param->getType();
+ const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
+ if (AE && AE->getKind() == DecRef && isISLObjectRef(Ty)) {
+ state = setRefBinding(
+ state, Sym, RefVal::makeOwned(ObjKind::Generalized, Ty));
+ } else if (isISLObjectRef(Ty)) {
+ state = setRefBinding(
+ state, Sym,
+ RefVal::makeNotOwned(ObjKind::Generalized, Ty));
+ }
+ }
+
+ Ctx.addTransition(state);
+}
+
+void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
+ CheckerContext &Ctx) const {
+ ExplodedNode *Pred = processReturn(RS, Ctx);
+
+ // Created state cached out.
+ if (!Pred) {
+ return;
+ }
+
+ ProgramStateRef state = Pred->getState();
+ RefBindingsTy B = state->get<RefBindings>();
+
+ // Don't process anything within synthesized bodies.
+ const LocationContext *LCtx = Pred->getLocationContext();
+ if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
+ assert(!LCtx->inTopFrame());
+ return;
+ }
+
+ for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
+ I->first, I->second);
+ if (!state)
+ return;
+ }
+
+ // If the current LocationContext has a parent, don't check for leaks.
+ // We will do that later.
+ // FIXME: we should instead check for imbalances of the retain/releases,
+ // and suggest annotations.
+ if (LCtx->getParent())
+ return;
+
+ B = state->get<RefBindings>();
+ SmallVector<SymbolRef, 10> Leaked;
+
+ for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
+ state = handleSymbolDeath(state, I->first, I->second, Leaked);
+
+ processLeaks(state, Leaked, Ctx, Pred);
+}
+
+void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
+ ExplodedNode *Pred = C.getPredecessor();
+
+ ProgramStateRef state = C.getState();
+ RefBindingsTy B = state->get<RefBindings>();
+ SmallVector<SymbolRef, 10> Leaked;
+
+ // Update counts from autorelease pools
+ for (const auto &I: state->get<RefBindings>()) {
+ SymbolRef Sym = I.first;
+ if (SymReaper.isDead(Sym)) {
+ static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
+ const RefVal &V = I.second;
+ state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V);
+ if (!state)
+ return;
+
+ // Fetch the new reference count from the state, and use it to handle
+ // this symbol.
+ state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked);
+ }
+ }
+
+ if (Leaked.empty()) {
+ C.addTransition(state);
+ return;
+ }
+
+ Pred = processLeaks(state, Leaked, C, Pred);
+
+ // Did we cache out?
+ if (!Pred)
+ return;
+
+ // Now generate a new node that nukes the old bindings.
+ // The only bindings left at this point are the leaked symbols.
+ RefBindingsTy::Factory &F = state->get_context<RefBindings>();
+ B = state->get<RefBindings>();
+
+ for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
+ E = Leaked.end();
+ I != E; ++I)
+ B = F.remove(B, *I);
+
+ state = state->set<RefBindings>(B);
+ C.addTransition(state, Pred);
+}
+
+void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const {
+
+ RefBindingsTy B = State->get<RefBindings>();
+
+ if (B.isEmpty())
+ return;
+
+ Out << Sep << NL;
+
+ for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ Out << I->first << " : ";
+ I->second.print(Out);
+ Out << NL;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Checker registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerRetainCountChecker(CheckerManager &Mgr) {
+ auto *Chk = Mgr.registerChecker<RetainCountChecker>();
+ Chk->TrackObjCAndCFObjects = true;
+}
+
+// FIXME: remove this, hack for backwards compatibility:
+// it should be possible to enable the NS/CF retain count checker as
+// osx.cocoa.RetainCount, and it should be possible to disable
+// osx.OSObjectRetainCount using osx.cocoa.RetainCount:CheckOSObject=false.
+static bool hasPrevCheckOSObjectOptionDisabled(AnalyzerOptions &Options) {
+ auto I = Options.Config.find("osx.cocoa.RetainCount:CheckOSObject");
+ if (I != Options.Config.end())
+ return I->getValue() == "false";
+ return false;
+}
+
+void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
+ auto *Chk = Mgr.registerChecker<RetainCountChecker>();
+ if (!hasPrevCheckOSObjectOptionDisabled(Mgr.getAnalyzerOptions()))
+ Chk->TrackOSObjects = true;
+}
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
new file mode 100644
index 000000000000..31e2d9ae4932
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
@@ -0,0 +1,393 @@
+//==--- RetainCountChecker.h - Checks for leaks and other issues -*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the methods for RetainCountChecker, which implements
+// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "RetainCountDiagnostics.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Analysis/SelectorExtras.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include <cstdarg>
+#include <utility>
+
+namespace clang {
+namespace ento {
+namespace retaincountchecker {
+
+/// Metadata on reference.
+class RefVal {
+public:
+ enum Kind {
+ Owned = 0, // Owning reference.
+ NotOwned, // Reference is not owned by still valid (not freed).
+ Released, // Object has been released.
+ ReturnedOwned, // Returned object passes ownership to caller.
+ ReturnedNotOwned, // Return object does not pass ownership to caller.
+ ERROR_START,
+ ErrorDeallocNotOwned, // -dealloc called on non-owned object.
+ ErrorUseAfterRelease, // Object used after released.
+ ErrorReleaseNotOwned, // Release of an object that was not owned.
+ ERROR_LEAK_START,
+ ErrorLeak, // A memory leak due to excessive reference counts.
+ ErrorLeakReturned, // A memory leak due to the returning method not having
+ // the correct naming conventions.
+ ErrorOverAutorelease,
+ ErrorReturnedNotOwned
+ };
+
+ /// Tracks how an object referenced by an ivar has been used.
+ ///
+ /// This accounts for us not knowing if an arbitrary ivar is supposed to be
+ /// stored at +0 or +1.
+ enum class IvarAccessHistory {
+ None,
+ AccessedDirectly,
+ ReleasedAfterDirectAccess
+ };
+
+private:
+ /// The number of outstanding retains.
+ unsigned Cnt;
+ /// The number of outstanding autoreleases.
+ unsigned ACnt;
+ /// The (static) type of the object at the time we started tracking it.
+ QualType T;
+
+ /// The current state of the object.
+ ///
+ /// See the RefVal::Kind enum for possible values.
+ unsigned RawKind : 5;
+
+ /// The kind of object being tracked (CF or ObjC or OSObject), if known.
+ ///
+ /// See the ObjKind enum for possible values.
+ unsigned RawObjectKind : 3;
+
+ /// True if the current state and/or retain count may turn out to not be the
+ /// best possible approximation of the reference counting state.
+ ///
+ /// If true, the checker may decide to throw away ("override") this state
+ /// in favor of something else when it sees the object being used in new ways.
+ ///
+ /// This setting should not be propagated to state derived from this state.
+ /// Once we start deriving new states, it would be inconsistent to override
+ /// them.
+ unsigned RawIvarAccessHistory : 2;
+
+ RefVal(Kind k, ObjKind o, unsigned cnt, unsigned acnt, QualType t,
+ IvarAccessHistory IvarAccess)
+ : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
+ RawObjectKind(static_cast<unsigned>(o)),
+ RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
+ assert(getKind() == k && "not enough bits for the kind");
+ assert(getObjKind() == o && "not enough bits for the object kind");
+ assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
+ }
+
+public:
+ Kind getKind() const { return static_cast<Kind>(RawKind); }
+
+ ObjKind getObjKind() const {
+ return static_cast<ObjKind>(RawObjectKind);
+ }
+
+ unsigned getCount() const { return Cnt; }
+ unsigned getAutoreleaseCount() const { return ACnt; }
+ unsigned getCombinedCounts() const { return Cnt + ACnt; }
+ void clearCounts() {
+ Cnt = 0;
+ ACnt = 0;
+ }
+ void setCount(unsigned i) {
+ Cnt = i;
+ }
+ void setAutoreleaseCount(unsigned i) {
+ ACnt = i;
+ }
+
+ QualType getType() const { return T; }
+
+ /// Returns what the analyzer knows about direct accesses to a particular
+ /// instance variable.
+ ///
+ /// If the object with this refcount wasn't originally from an Objective-C
+ /// ivar region, this should always return IvarAccessHistory::None.
+ IvarAccessHistory getIvarAccessHistory() const {
+ return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
+ }
+
+ bool isOwned() const {
+ return getKind() == Owned;
+ }
+
+ bool isNotOwned() const {
+ return getKind() == NotOwned;
+ }
+
+ bool isReturnedOwned() const {
+ return getKind() == ReturnedOwned;
+ }
+
+ bool isReturnedNotOwned() const {
+ return getKind() == ReturnedNotOwned;
+ }
+
+ /// Create a state for an object whose lifetime is the responsibility of the
+ /// current function, at least partially.
+ ///
+ /// Most commonly, this is an owned object with a retain count of +1.
+ static RefVal makeOwned(ObjKind o, QualType t) {
+ return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None);
+ }
+
+ /// Create a state for an object whose lifetime is not the responsibility of
+ /// the current function.
+ ///
+ /// Most commonly, this is an unowned object with a retain count of +0.
+ static RefVal makeNotOwned(ObjKind o, QualType t) {
+ return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None);
+ }
+
+ RefVal operator-(size_t i) const {
+ return RefVal(getKind(), getObjKind(), getCount() - i,
+ getAutoreleaseCount(), getType(), getIvarAccessHistory());
+ }
+
+ RefVal operator+(size_t i) const {
+ return RefVal(getKind(), getObjKind(), getCount() + i,
+ getAutoreleaseCount(), getType(), getIvarAccessHistory());
+ }
+
+ RefVal operator^(Kind k) const {
+ return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
+ getType(), getIvarAccessHistory());
+ }
+
+ RefVal autorelease() const {
+ return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
+ getType(), getIvarAccessHistory());
+ }
+
+ RefVal withIvarAccess() const {
+ assert(getIvarAccessHistory() == IvarAccessHistory::None);
+ return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
+ getType(), IvarAccessHistory::AccessedDirectly);
+ }
+
+ RefVal releaseViaIvar() const {
+ assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
+ return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
+ getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
+ }
+
+ // Comparison, profiling, and pretty-printing.
+ bool hasSameState(const RefVal &X) const {
+ return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
+ getIvarAccessHistory() == X.getIvarAccessHistory();
+ }
+
+ bool operator==(const RefVal& X) const {
+ return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.Add(T);
+ ID.AddInteger(RawKind);
+ ID.AddInteger(Cnt);
+ ID.AddInteger(ACnt);
+ ID.AddInteger(RawObjectKind);
+ ID.AddInteger(RawIvarAccessHistory);
+ }
+
+ void print(raw_ostream &Out) const;
+};
+
+class RetainCountChecker
+ : public Checker< check::Bind,
+ check::DeadSymbols,
+ check::BeginFunction,
+ check::EndFunction,
+ check::PostStmt<BlockExpr>,
+ check::PostStmt<CastExpr>,
+ check::PostStmt<ObjCArrayLiteral>,
+ check::PostStmt<ObjCDictionaryLiteral>,
+ check::PostStmt<ObjCBoxedExpr>,
+ check::PostStmt<ObjCIvarRefExpr>,
+ check::PostCall,
+ check::RegionChanges,
+ eval::Assume,
+ eval::Call > {
+ mutable std::unique_ptr<RefCountBug> useAfterRelease, releaseNotOwned;
+ mutable std::unique_ptr<RefCountBug> deallocNotOwned;
+ mutable std::unique_ptr<RefCountBug> overAutorelease, returnNotOwnedForOwned;
+ mutable std::unique_ptr<RefCountBug> leakWithinFunction, leakAtReturn;
+
+ mutable std::unique_ptr<RetainSummaryManager> Summaries;
+public:
+ static constexpr const char *DeallocTagDescription = "DeallocSent";
+
+ /// Track Objective-C and CoreFoundation objects.
+ bool TrackObjCAndCFObjects = false;
+
+ /// Track sublcasses of OSObject.
+ bool TrackOSObjects = false;
+
+ RetainCountChecker() {}
+
+ RefCountBug *getLeakWithinFunctionBug(const LangOptions &LOpts) const;
+
+ RefCountBug *getLeakAtReturnBug(const LangOptions &LOpts) const;
+
+ RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
+ // FIXME: We don't support ARC being turned on and off during one analysis.
+ // (nor, for that matter, do we support changing ASTContexts)
+ bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
+ if (!Summaries) {
+ Summaries.reset(new RetainSummaryManager(
+ Ctx, ARCEnabled, TrackObjCAndCFObjects, TrackOSObjects));
+ } else {
+ assert(Summaries->isARCEnabled() == ARCEnabled);
+ }
+ return *Summaries;
+ }
+
+ RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
+ return getSummaryManager(C.getASTContext());
+ }
+
+ void printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const override;
+
+ void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
+ void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
+ void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
+
+ void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
+ void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
+ void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
+
+ void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
+
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+
+ void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
+ CheckerContext &C) const;
+
+ void processSummaryOfInlined(const RetainSummary &Summ,
+ const CallEvent &Call,
+ CheckerContext &C) const;
+
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+
+ ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
+ bool Assumption) const;
+
+ ProgramStateRef
+ checkRegionChanges(ProgramStateRef state,
+ const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const LocationContext* LCtx,
+ const CallEvent *Call) const;
+
+ ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
+ ExplodedNode *Pred, RetEffect RE, RefVal X,
+ SymbolRef Sym, ProgramStateRef state) const;
+
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+ void checkBeginFunction(CheckerContext &C) const;
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
+
+ ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
+ RefVal V, ArgEffect E, RefVal::Kind &hasErr,
+ CheckerContext &C) const;
+
+ void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
+ RefVal::Kind ErrorKind, SymbolRef Sym,
+ CheckerContext &C) const;
+
+ void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
+
+ ProgramStateRef handleSymbolDeath(ProgramStateRef state,
+ SymbolRef sid, RefVal V,
+ SmallVectorImpl<SymbolRef> &Leaked) const;
+
+ ProgramStateRef
+ handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
+ const ProgramPointTag *Tag, CheckerContext &Ctx,
+ SymbolRef Sym,
+ RefVal V,
+ const ReturnStmt *S=nullptr) const;
+
+ ExplodedNode *processLeaks(ProgramStateRef state,
+ SmallVectorImpl<SymbolRef> &Leaked,
+ CheckerContext &Ctx,
+ ExplodedNode *Pred = nullptr) const;
+
+private:
+ /// Perform the necessary checks and state adjustments at the end of the
+ /// function.
+ /// \p S Return statement, may be null.
+ ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const;
+};
+
+//===----------------------------------------------------------------------===//
+// RefBindings - State used to track object reference counts.
+//===----------------------------------------------------------------------===//
+
+const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
+
+ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym,
+ RefVal Val);
+
+ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym);
+
+/// Returns true if this stack frame is for an Objective-C method that is a
+/// property getter or setter whose body has been synthesized by the analyzer.
+inline bool isSynthesizedAccessor(const StackFrameContext *SFC) {
+ auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
+ if (!Method || !Method->isPropertyAccessor())
+ return false;
+
+ return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
+}
+
+} // end namespace retaincountchecker
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
new file mode 100644
index 000000000000..cda1a928de13
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
@@ -0,0 +1,794 @@
+// RetainCountDiagnostics.cpp - Checks for leaks and other issues -*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines diagnostics for RetainCountChecker, which implements
+// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#include "RetainCountDiagnostics.h"
+#include "RetainCountChecker.h"
+
+using namespace clang;
+using namespace ento;
+using namespace retaincountchecker;
+
+static bool isNumericLiteralExpression(const Expr *E) {
+ // FIXME: This set of cases was copied from SemaExprObjC.
+ return isa<IntegerLiteral>(E) ||
+ isa<CharacterLiteral>(E) ||
+ isa<FloatingLiteral>(E) ||
+ isa<ObjCBoolLiteralExpr>(E) ||
+ isa<CXXBoolLiteralExpr>(E);
+}
+
+/// If type represents a pointer to CXXRecordDecl,
+/// and is not a typedef, return the decl name.
+/// Otherwise, return the serialization of type.
+static std::string getPrettyTypeName(QualType QT) {
+ QualType PT = QT->getPointeeType();
+ if (!PT.isNull() && !QT->getAs<TypedefType>())
+ if (const auto *RD = PT->getAsCXXRecordDecl())
+ return RD->getName();
+ return QT.getAsString();
+}
+
+/// Write information about the type state change to {@code os},
+/// return whether the note should be generated.
+static bool shouldGenerateNote(llvm::raw_string_ostream &os,
+ const RefVal *PrevT, const RefVal &CurrV,
+ bool DeallocSent) {
+ // Get the previous type state.
+ RefVal PrevV = *PrevT;
+
+ // Specially handle -dealloc.
+ if (DeallocSent) {
+ // Determine if the object's reference count was pushed to zero.
+ assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
+ // We may not have transitioned to 'release' if we hit an error.
+ // This case is handled elsewhere.
+ if (CurrV.getKind() == RefVal::Released) {
+ assert(CurrV.getCombinedCounts() == 0);
+ os << "Object released by directly sending the '-dealloc' message";
+ return true;
+ }
+ }
+
+ // Determine if the typestate has changed.
+ if (!PrevV.hasSameState(CurrV))
+ switch (CurrV.getKind()) {
+ case RefVal::Owned:
+ case RefVal::NotOwned:
+ if (PrevV.getCount() == CurrV.getCount()) {
+ // Did an autorelease message get sent?
+ if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
+ return false;
+
+ assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
+ os << "Object autoreleased";
+ return true;
+ }
+
+ if (PrevV.getCount() > CurrV.getCount())
+ os << "Reference count decremented.";
+ else
+ os << "Reference count incremented.";
+
+ if (unsigned Count = CurrV.getCount())
+ os << " The object now has a +" << Count << " retain count.";
+
+ return true;
+
+ case RefVal::Released:
+ if (CurrV.getIvarAccessHistory() ==
+ RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
+ CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
+ os << "Strong instance variable relinquished. ";
+ }
+ os << "Object released.";
+ return true;
+
+ case RefVal::ReturnedOwned:
+ // Autoreleases can be applied after marking a node ReturnedOwned.
+ if (CurrV.getAutoreleaseCount())
+ return false;
+
+ os << "Object returned to caller as an owning reference (single "
+ "retain count transferred to caller)";
+ return true;
+
+ case RefVal::ReturnedNotOwned:
+ os << "Object returned to caller with a +0 retain count";
+ return true;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+/// Finds argument index of the out paramter in the call {@code S}
+/// corresponding to the symbol {@code Sym}.
+/// If none found, returns None.
+static Optional<unsigned> findArgIdxOfSymbol(ProgramStateRef CurrSt,
+ const LocationContext *LCtx,
+ SymbolRef &Sym,
+ Optional<CallEventRef<>> CE) {
+ if (!CE)
+ return None;
+
+ for (unsigned Idx = 0; Idx < (*CE)->getNumArgs(); Idx++)
+ if (const MemRegion *MR = (*CE)->getArgSVal(Idx).getAsRegion())
+ if (const auto *TR = dyn_cast<TypedValueRegion>(MR))
+ if (CurrSt->getSVal(MR, TR->getValueType()).getAsSymExpr() == Sym)
+ return Idx;
+
+ return None;
+}
+
+static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
+ const LocationContext *LCtx,
+ const RefVal &CurrV, SymbolRef &Sym,
+ const Stmt *S,
+ llvm::raw_string_ostream &os) {
+ CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
+ if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
+ // Get the name of the callee (if it is available)
+ // from the tracked SVal.
+ SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
+ const FunctionDecl *FD = X.getAsFunctionDecl();
+
+ // If failed, try to get it from AST.
+ if (!FD)
+ FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
+
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
+ os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
+ } else if (FD) {
+ os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
+ } else {
+ os << "function call";
+ }
+ } else if (isa<CXXNewExpr>(S)) {
+ os << "Operator 'new'";
+ } else {
+ assert(isa<ObjCMessageExpr>(S));
+ CallEventRef<ObjCMethodCall> Call =
+ Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
+
+ switch (Call->getMessageKind()) {
+ case OCM_Message:
+ os << "Method";
+ break;
+ case OCM_PropertyAccess:
+ os << "Property";
+ break;
+ case OCM_Subscript:
+ os << "Subscript";
+ break;
+ }
+ }
+
+ Optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, LCtx);
+ auto Idx = findArgIdxOfSymbol(CurrSt, LCtx, Sym, CE);
+
+ // If index is not found, we assume that the symbol was returned.
+ if (!Idx) {
+ os << " returns ";
+ } else {
+ os << " writes ";
+ }
+
+ if (CurrV.getObjKind() == ObjKind::CF) {
+ os << "a Core Foundation object of type '"
+ << Sym->getType().getAsString() << "' with a ";
+ } else if (CurrV.getObjKind() == ObjKind::OS) {
+ os << "an OSObject of type '" << getPrettyTypeName(Sym->getType())
+ << "' with a ";
+ } else if (CurrV.getObjKind() == ObjKind::Generalized) {
+ os << "an object of type '" << Sym->getType().getAsString()
+ << "' with a ";
+ } else {
+ assert(CurrV.getObjKind() == ObjKind::ObjC);
+ QualType T = Sym->getType();
+ if (!isa<ObjCObjectPointerType>(T)) {
+ os << "an Objective-C object with a ";
+ } else {
+ const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
+ os << "an instance of " << PT->getPointeeType().getAsString()
+ << " with a ";
+ }
+ }
+
+ if (CurrV.isOwned()) {
+ os << "+1 retain count";
+ } else {
+ assert(CurrV.isNotOwned());
+ os << "+0 retain count";
+ }
+
+ if (Idx) {
+ os << " into an out parameter '";
+ const ParmVarDecl *PVD = (*CE)->parameters()[*Idx];
+ PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
+ /*Qualified=*/false);
+ os << "'";
+
+ QualType RT = (*CE)->getResultType();
+ if (!RT.isNull() && !RT->isVoidType()) {
+ SVal RV = (*CE)->getReturnValue();
+ if (CurrSt->isNull(RV).isConstrainedTrue()) {
+ os << " (assuming the call returns zero)";
+ } else if (CurrSt->isNonNull(RV).isConstrainedTrue()) {
+ os << " (assuming the call returns non-zero)";
+ }
+
+ }
+ }
+}
+
+namespace clang {
+namespace ento {
+namespace retaincountchecker {
+
+class RefCountReportVisitor : public BugReporterVisitor {
+protected:
+ SymbolRef Sym;
+
+public:
+ RefCountReportVisitor(SymbolRef sym) : Sym(sym) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int x = 0;
+ ID.AddPointer(&x);
+ ID.AddPointer(Sym);
+ }
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
+ const ExplodedNode *N,
+ BugReport &BR) override;
+};
+
+class RefLeakReportVisitor : public RefCountReportVisitor {
+public:
+ RefLeakReportVisitor(SymbolRef sym) : RefCountReportVisitor(sym) {}
+
+ std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
+ const ExplodedNode *N,
+ BugReport &BR) override;
+};
+
+} // end namespace retaincountchecker
+} // end namespace ento
+} // end namespace clang
+
+
+/// Find the first node with the parent stack frame.
+static const ExplodedNode *getCalleeNode(const ExplodedNode *Pred) {
+ const StackFrameContext *SC = Pred->getStackFrame();
+ if (SC->inTopFrame())
+ return nullptr;
+ const StackFrameContext *PC = SC->getParent()->getStackFrame();
+ if (!PC)
+ return nullptr;
+
+ const ExplodedNode *N = Pred;
+ while (N && N->getStackFrame() != PC) {
+ N = N->getFirstPred();
+ }
+ return N;
+}
+
+
+/// Insert a diagnostic piece at function exit
+/// if a function parameter is annotated as "os_consumed",
+/// but it does not actually consume the reference.
+static std::shared_ptr<PathDiagnosticEventPiece>
+annotateConsumedSummaryMismatch(const ExplodedNode *N,
+ CallExitBegin &CallExitLoc,
+ const SourceManager &SM,
+ CallEventManager &CEMgr) {
+
+ const ExplodedNode *CN = getCalleeNode(N);
+ if (!CN)
+ return nullptr;
+
+ CallEventRef<> Call = CEMgr.getCaller(N->getStackFrame(), N->getState());
+
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ ArrayRef<const ParmVarDecl *> Parameters = Call->parameters();
+ for (unsigned I=0; I < Call->getNumArgs() && I < Parameters.size(); ++I) {
+ const ParmVarDecl *PVD = Parameters[I];
+
+ if (!PVD->hasAttr<OSConsumedAttr>())
+ continue;
+
+ if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {
+ const RefVal *CountBeforeCall = getRefBinding(CN->getState(), SR);
+ const RefVal *CountAtExit = getRefBinding(N->getState(), SR);
+
+ if (!CountBeforeCall || !CountAtExit)
+ continue;
+
+ unsigned CountBefore = CountBeforeCall->getCount();
+ unsigned CountAfter = CountAtExit->getCount();
+
+ bool AsExpected = CountBefore > 0 && CountAfter == CountBefore - 1;
+ if (!AsExpected) {
+ os << "Parameter '";
+ PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
+ /*Qualified=*/false);
+ os << "' is marked as consuming, but the function did not consume "
+ << "the reference\n";
+ }
+ }
+ }
+
+ if (os.str().empty())
+ return nullptr;
+
+ // FIXME: remove the code duplication with NoStoreFuncVisitor.
+ PathDiagnosticLocation L;
+ if (const ReturnStmt *RS = CallExitLoc.getReturnStmt()) {
+ L = PathDiagnosticLocation::createBegin(RS, SM, N->getLocationContext());
+ } else {
+ L = PathDiagnosticLocation(
+ Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(), SM);
+ }
+
+ return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
+}
+
+std::shared_ptr<PathDiagnosticPiece>
+RefCountReportVisitor::VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC, BugReport &BR) {
+
+ const SourceManager &SM = BRC.getSourceManager();
+ CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
+ if (auto CE = N->getLocationAs<CallExitBegin>())
+ if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr))
+ return PD;
+
+ // FIXME: We will eventually need to handle non-statement-based events
+ // (__attribute__((cleanup))).
+ if (!N->getLocation().getAs<StmtPoint>())
+ return nullptr;
+
+ // Check if the type state has changed.
+ const ExplodedNode *PrevNode = N->getFirstPred();
+ ProgramStateRef PrevSt = PrevNode->getState();
+ ProgramStateRef CurrSt = N->getState();
+ const LocationContext *LCtx = N->getLocationContext();
+
+ const RefVal* CurrT = getRefBinding(CurrSt, Sym);
+ if (!CurrT) return nullptr;
+
+ const RefVal &CurrV = *CurrT;
+ const RefVal *PrevT = getRefBinding(PrevSt, Sym);
+
+ // Create a string buffer to constain all the useful things we want
+ // to tell the user.
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ // This is the allocation site since the previous node had no bindings
+ // for this symbol.
+ if (!PrevT) {
+ const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
+
+ if (isa<ObjCIvarRefExpr>(S) &&
+ isSynthesizedAccessor(LCtx->getStackFrame())) {
+ S = LCtx->getStackFrame()->getCallSite();
+ }
+
+ if (isa<ObjCArrayLiteral>(S)) {
+ os << "NSArray literal is an object with a +0 retain count";
+ } else if (isa<ObjCDictionaryLiteral>(S)) {
+ os << "NSDictionary literal is an object with a +0 retain count";
+ } else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
+ if (isNumericLiteralExpression(BL->getSubExpr()))
+ os << "NSNumber literal is an object with a +0 retain count";
+ else {
+ const ObjCInterfaceDecl *BoxClass = nullptr;
+ if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
+ BoxClass = Method->getClassInterface();
+
+ // We should always be able to find the boxing class interface,
+ // but consider this future-proofing.
+ if (BoxClass) {
+ os << *BoxClass << " b";
+ } else {
+ os << "B";
+ }
+
+ os << "oxed expression produces an object with a +0 retain count";
+ }
+ } else if (isa<ObjCIvarRefExpr>(S)) {
+ os << "Object loaded from instance variable";
+ } else {
+ generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os);
+ }
+
+ PathDiagnosticLocation Pos(S, SM, N->getLocationContext());
+ return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
+ }
+
+ // Gather up the effects that were performed on the object at this
+ // program point
+ bool DeallocSent = false;
+
+ if (N->getLocation().getTag() &&
+ N->getLocation().getTag()->getTagDescription().contains(
+ RetainCountChecker::DeallocTagDescription)) {
+ // We only have summaries attached to nodes after evaluating CallExpr and
+ // ObjCMessageExprs.
+ const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
+ // Iterate through the parameter expressions and see if the symbol
+ // was ever passed as an argument.
+ unsigned i = 0;
+
+ for (auto AI=CE->arg_begin(), AE=CE->arg_end(); AI!=AE; ++AI, ++i) {
+
+ // Retrieve the value of the argument. Is it the symbol
+ // we are interested in?
+ if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
+ continue;
+
+ // We have an argument. Get the effect!
+ DeallocSent = true;
+ }
+ } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
+ if (const Expr *receiver = ME->getInstanceReceiver()) {
+ if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
+ .getAsLocSymbol() == Sym) {
+ // The symbol we are tracking is the receiver.
+ DeallocSent = true;
+ }
+ }
+ }
+ }
+
+ if (!shouldGenerateNote(os, PrevT, CurrV, DeallocSent))
+ return nullptr;
+
+ if (os.str().empty())
+ return nullptr; // We have nothing to say!
+
+ const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
+
+ // Add the range by scanning the children of the statement for any bindings
+ // to Sym.
+ for (const Stmt *Child : S->children())
+ if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
+ if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
+ P->addRange(Exp->getSourceRange());
+ break;
+ }
+
+ return std::move(P);
+}
+
+static Optional<std::string> describeRegion(const MemRegion *MR) {
+ if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
+ return std::string(VR->getDecl()->getName());
+ // Once we support more storage locations for bindings,
+ // this would need to be improved.
+ return None;
+}
+
+namespace {
+// Find the first node in the current function context that referred to the
+// tracked symbol and the memory location that value was stored to. Note, the
+// value is only reported if the allocation occurred in the same function as
+// the leak. The function can also return a location context, which should be
+// treated as interesting.
+struct AllocationInfo {
+ const ExplodedNode* N;
+ const MemRegion *R;
+ const LocationContext *InterestingMethodContext;
+ AllocationInfo(const ExplodedNode *InN,
+ const MemRegion *InR,
+ const LocationContext *InInterestingMethodContext) :
+ N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
+};
+} // end anonymous namespace
+
+static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
+ const ExplodedNode *N, SymbolRef Sym) {
+ const ExplodedNode *AllocationNode = N;
+ const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
+ const MemRegion *FirstBinding = nullptr;
+ const LocationContext *LeakContext = N->getLocationContext();
+
+ // The location context of the init method called on the leaked object, if
+ // available.
+ const LocationContext *InitMethodContext = nullptr;
+
+ while (N) {
+ ProgramStateRef St = N->getState();
+ const LocationContext *NContext = N->getLocationContext();
+
+ if (!getRefBinding(St, Sym))
+ break;
+
+ StoreManager::FindUniqueBinding FB(Sym);
+ StateMgr.iterBindings(St, FB);
+
+ if (FB) {
+ const MemRegion *R = FB.getRegion();
+ // Do not show local variables belonging to a function other than
+ // where the error is reported.
+ if (auto MR = dyn_cast<StackSpaceRegion>(R->getMemorySpace()))
+ if (MR->getStackFrame() == LeakContext->getStackFrame())
+ FirstBinding = R;
+ }
+
+ // AllocationNode is the last node in which the symbol was tracked.
+ AllocationNode = N;
+
+ // AllocationNodeInCurrentContext, is the last node in the current or
+ // parent context in which the symbol was tracked.
+ //
+ // Note that the allocation site might be in the parent context. For example,
+ // the case where an allocation happens in a block that captures a reference
+ // to it and that reference is overwritten/dropped by another call to
+ // the block.
+ if (NContext == LeakContext || NContext->isParentOf(LeakContext))
+ AllocationNodeInCurrentOrParentContext = N;
+
+ // Find the last init that was called on the given symbol and store the
+ // init method's location context.
+ if (!InitMethodContext)
+ if (auto CEP = N->getLocation().getAs<CallEnter>()) {
+ const Stmt *CE = CEP->getCallExpr();
+ if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
+ const Stmt *RecExpr = ME->getInstanceReceiver();
+ if (RecExpr) {
+ SVal RecV = St->getSVal(RecExpr, NContext);
+ if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
+ InitMethodContext = CEP->getCalleeContext();
+ }
+ }
+ }
+
+ N = N->getFirstPred();
+ }
+
+ // If we are reporting a leak of the object that was allocated with alloc,
+ // mark its init method as interesting.
+ const LocationContext *InterestingMethodContext = nullptr;
+ if (InitMethodContext) {
+ const ProgramPoint AllocPP = AllocationNode->getLocation();
+ if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
+ if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
+ if (ME->getMethodFamily() == OMF_alloc)
+ InterestingMethodContext = InitMethodContext;
+ }
+
+ // If allocation happened in a function different from the leak node context,
+ // do not report the binding.
+ assert(N && "Could not find allocation node");
+
+ if (AllocationNodeInCurrentOrParentContext &&
+ AllocationNodeInCurrentOrParentContext->getLocationContext() !=
+ LeakContext)
+ FirstBinding = nullptr;
+
+ return AllocationInfo(AllocationNodeInCurrentOrParentContext,
+ FirstBinding,
+ InterestingMethodContext);
+}
+
+std::shared_ptr<PathDiagnosticPiece>
+RefCountReportVisitor::getEndPath(BugReporterContext &BRC,
+ const ExplodedNode *EndN, BugReport &BR) {
+ BR.markInteresting(Sym);
+ return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
+}
+
+std::shared_ptr<PathDiagnosticPiece>
+RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
+ const ExplodedNode *EndN, BugReport &BR) {
+
+ // Tell the BugReporterContext to report cases when the tracked symbol is
+ // assigned to different variables, etc.
+ BR.markInteresting(Sym);
+
+ // We are reporting a leak. Walk up the graph to get to the first node where
+ // the symbol appeared, and also get the first VarDecl that tracked object
+ // is stored to.
+ AllocationInfo AllocI = GetAllocationSite(BRC.getStateManager(), EndN, Sym);
+
+ const MemRegion* FirstBinding = AllocI.R;
+ BR.markInteresting(AllocI.InterestingMethodContext);
+
+ SourceManager& SM = BRC.getSourceManager();
+
+ // Compute an actual location for the leak. Sometimes a leak doesn't
+ // occur at an actual statement (e.g., transition between blocks; end
+ // of function) so we need to walk the graph and compute a real location.
+ const ExplodedNode *LeakN = EndN;
+ PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM);
+
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ os << "Object leaked: ";
+
+ Optional<std::string> RegionDescription = describeRegion(FirstBinding);
+ if (RegionDescription) {
+ os << "object allocated and stored into '" << *RegionDescription << '\'';
+ } else {
+ os << "allocated object of type '" << getPrettyTypeName(Sym->getType())
+ << "'";
+ }
+
+ // Get the retain count.
+ const RefVal* RV = getRefBinding(EndN->getState(), Sym);
+ assert(RV);
+
+ if (RV->getKind() == RefVal::ErrorLeakReturned) {
+ // FIXME: Per comments in rdar://6320065, "create" only applies to CF
+ // objects. Only "copy", "alloc", "retain" and "new" transfer ownership
+ // to the caller for NS objects.
+ const Decl *D = &EndN->getCodeDecl();
+
+ os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
+ : " is returned from a function ");
+
+ if (D->hasAttr<CFReturnsNotRetainedAttr>()) {
+ os << "that is annotated as CF_RETURNS_NOT_RETAINED";
+ } else if (D->hasAttr<NSReturnsNotRetainedAttr>()) {
+ os << "that is annotated as NS_RETURNS_NOT_RETAINED";
+ } else if (D->hasAttr<OSReturnsNotRetainedAttr>()) {
+ os << "that is annotated as OS_RETURNS_NOT_RETAINED";
+ } else {
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
+ os << "managed by Automatic Reference Counting";
+ } else {
+ os << "whose name ('" << MD->getSelector().getAsString()
+ << "') does not start with "
+ "'copy', 'mutableCopy', 'alloc' or 'new'."
+ " This violates the naming convention rules"
+ " given in the Memory Management Guide for Cocoa";
+ }
+ } else {
+ const FunctionDecl *FD = cast<FunctionDecl>(D);
+ os << "whose name ('" << *FD
+ << "') does not contain 'Copy' or 'Create'. This violates the naming"
+ " convention rules given in the Memory Management Guide for Core"
+ " Foundation";
+ }
+ }
+ } else {
+ os << " is not referenced later in this execution path and has a retain "
+ "count of +" << RV->getCount();
+ }
+
+ return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
+}
+
+RefCountReport::RefCountReport(RefCountBug &D, const LangOptions &LOpts,
+ ExplodedNode *n, SymbolRef sym,
+ bool registerVisitor)
+ : BugReport(D, D.getDescription(), n), Sym(sym) {
+ if (registerVisitor)
+ addVisitor(llvm::make_unique<RefCountReportVisitor>(sym));
+}
+
+RefCountReport::RefCountReport(RefCountBug &D, const LangOptions &LOpts,
+ ExplodedNode *n, SymbolRef sym,
+ StringRef endText)
+ : BugReport(D, D.getDescription(), endText, n) {
+
+ addVisitor(llvm::make_unique<RefCountReportVisitor>(sym));
+}
+
+void RefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
+ const SourceManager& SMgr = Ctx.getSourceManager();
+
+ if (!sym->getOriginRegion())
+ return;
+
+ auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
+ if (Region) {
+ const Decl *PDecl = Region->getDecl();
+ if (PDecl && isa<ParmVarDecl>(PDecl)) {
+ PathDiagnosticLocation ParamLocation =
+ PathDiagnosticLocation::create(PDecl, SMgr);
+ Location = ParamLocation;
+ UniqueingLocation = ParamLocation;
+ UniqueingDecl = Ctx.getLocationContext()->getDecl();
+ }
+ }
+}
+
+void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx,
+ SymbolRef sym) {
+ // Most bug reports are cached at the location where they occurred.
+ // With leaks, we want to unique them by the location where they were
+ // allocated, and only report a single path. To do this, we need to find
+ // the allocation site of a piece of tracked memory, which we do via a
+ // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
+ // Note that this is *not* the trimmed graph; we are guaranteed, however,
+ // that all ancestor nodes that represent the allocation site have the
+ // same SourceLocation.
+ const ExplodedNode *AllocNode = nullptr;
+
+ const SourceManager& SMgr = Ctx.getSourceManager();
+
+ AllocationInfo AllocI =
+ GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
+
+ AllocNode = AllocI.N;
+ AllocBinding = AllocI.R;
+ markInteresting(AllocI.InterestingMethodContext);
+
+ // Get the SourceLocation for the allocation site.
+ // FIXME: This will crash the analyzer if an allocation comes from an
+ // implicit call (ex: a destructor call).
+ // (Currently there are no such allocations in Cocoa, though.)
+ AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
+
+ if (!AllocStmt) {
+ AllocBinding = nullptr;
+ return;
+ }
+
+ PathDiagnosticLocation AllocLocation =
+ PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
+ AllocNode->getLocationContext());
+ Location = AllocLocation;
+
+ // Set uniqieing info, which will be used for unique the bug reports. The
+ // leaks should be uniqued on the allocation site.
+ UniqueingLocation = AllocLocation;
+ UniqueingDecl = AllocNode->getLocationContext()->getDecl();
+}
+
+void RefLeakReport::createDescription(CheckerContext &Ctx) {
+ assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
+ Description.clear();
+ llvm::raw_string_ostream os(Description);
+ os << "Potential leak of an object";
+
+ Optional<std::string> RegionDescription = describeRegion(AllocBinding);
+ if (RegionDescription) {
+ os << " stored into '" << *RegionDescription << '\'';
+ } else {
+
+ // If we can't figure out the name, just supply the type information.
+ os << " of type '" << getPrettyTypeName(Sym->getType()) << "'";
+ }
+}
+
+RefLeakReport::RefLeakReport(RefCountBug &D, const LangOptions &LOpts,
+ ExplodedNode *n, SymbolRef sym,
+ CheckerContext &Ctx)
+ : RefCountReport(D, LOpts, n, sym, false) {
+
+ deriveAllocLocation(Ctx, sym);
+ if (!AllocBinding)
+ deriveParamLocation(Ctx, sym);
+
+ createDescription(Ctx);
+
+ addVisitor(llvm::make_unique<RefLeakReportVisitor>(sym));
+}
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
new file mode 100644
index 000000000000..9f796abe8eae
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
@@ -0,0 +1,85 @@
+//== RetainCountDiagnostics.h - Checks for leaks and other issues -*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines diagnostics for RetainCountChecker, which implements
+// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
+
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
+
+namespace clang {
+namespace ento {
+namespace retaincountchecker {
+
+class RefCountBug : public BugType {
+protected:
+ RefCountBug(const CheckerBase *checker, StringRef name)
+ : BugType(checker, name, categories::MemoryRefCount) {}
+
+public:
+ virtual const char *getDescription() const = 0;
+
+ virtual bool isLeak() const { return false; }
+};
+
+class RefCountReport : public BugReport {
+protected:
+ SymbolRef Sym;
+
+public:
+ RefCountReport(RefCountBug &D, const LangOptions &LOpts,
+ ExplodedNode *n, SymbolRef sym,
+ bool registerVisitor = true);
+
+ RefCountReport(RefCountBug &D, const LangOptions &LOpts,
+ ExplodedNode *n, SymbolRef sym,
+ StringRef endText);
+
+ llvm::iterator_range<ranges_iterator> getRanges() override {
+ const RefCountBug& BugTy = static_cast<RefCountBug&>(getBugType());
+ if (!BugTy.isLeak())
+ return BugReport::getRanges();
+ return llvm::make_range(ranges_iterator(), ranges_iterator());
+ }
+};
+
+class RefLeakReport : public RefCountReport {
+ const MemRegion* AllocBinding;
+ const Stmt *AllocStmt;
+
+ // Finds the function declaration where a leak warning for the parameter
+ // 'sym' should be raised.
+ void deriveParamLocation(CheckerContext &Ctx, SymbolRef sym);
+ // Finds the location where a leak warning for 'sym' should be raised.
+ void deriveAllocLocation(CheckerContext &Ctx, SymbolRef sym);
+ // Produces description of a leak warning which is printed on the console.
+ void createDescription(CheckerContext &Ctx);
+
+public:
+ RefLeakReport(RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n,
+ SymbolRef sym, CheckerContext &Ctx);
+
+ PathDiagnosticLocation getLocation(const SourceManager &SM) const override {
+ assert(Location.isValid());
+ return Location;
+ }
+};
+
+} // end namespace retaincountchecker
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index 1952715a9b7c..17ef39531628 100644
--- a/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index c5e826a84b84..3e0613e8ba68 100644
--- a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -13,7 +13,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -87,7 +87,7 @@ static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
auto Report = llvm::make_unique<BugReport>(BT, BT.getDescription(), N);
Report->addRange(RetE->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, TrackingE ? TrackingE : RetE, *Report);
+ bugreporter::trackExpressionValue(N, TrackingE ? TrackingE : RetE, *Report);
C.emitReport(std::move(Report));
}
diff --git a/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp b/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
index 55516a34d1a7..cf03b3c21132 100644
--- a/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
@@ -23,7 +23,7 @@
//===----------------------------------------------------------------------===//
//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -58,13 +58,12 @@ public:
} // end anonymous namespace
-
-using TriBoolTy = Optional<bool>;
-using MemoizationMapTy = llvm::DenseMap<const Stmt *, Optional<TriBoolTy>>;
-
-static TriBoolTy
-seenBeforeRec(const Stmt *Parent, const Stmt *A, const Stmt *B,
- MemoizationMapTy &Memoization) {
+/// \return Whether {@code A} occurs before {@code B} in traversal of
+/// {@code Parent}.
+/// Conceptually a very incomplete/unsound approximation of happens-before
+/// relationship (A is likely to be evaluated before B),
+/// but useful enough in this case.
+static bool seenBefore(const Stmt *Parent, const Stmt *A, const Stmt *B) {
for (const Stmt *C : Parent->children()) {
if (!C) continue;
@@ -74,26 +73,9 @@ seenBeforeRec(const Stmt *Parent, const Stmt *A, const Stmt *B,
if (C == B)
return false;
- Optional<TriBoolTy> &Cached = Memoization[C];
- if (!Cached)
- Cached = seenBeforeRec(C, A, B, Memoization);
-
- if (Cached->hasValue())
- return Cached->getValue();
+ return seenBefore(C, A, B);
}
-
- return None;
-}
-
-/// \return Whether {@code A} occurs before {@code B} in traversal of
-/// {@code Parent}.
-/// Conceptually a very incomplete/unsound approximation of happens-before
-/// relationship (A is likely to be evaluated before B),
-/// but useful enough in this case.
-static bool seenBefore(const Stmt *Parent, const Stmt *A, const Stmt *B) {
- MemoizationMapTy Memoization;
- TriBoolTy Val = seenBeforeRec(Parent, A, B, Memoization);
- return Val.getValue();
+ return false;
}
static void emitDiagnostics(BoundNodes &Match,
diff --git a/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
index ab4b4d3bd91b..819d437e6883 100644
--- a/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
diff --git a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index e7a20fa03a4a..0f53d826a5f6 100644
--- a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -79,17 +79,17 @@ SourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R,
const CompoundLiteralExpr *CL = CR->getLiteralExpr();
os << "stack memory associated with a compound literal "
"declared on line "
- << SM.getExpansionLineNumber(CL->getLocStart()) << " returned to caller";
+ << SM.getExpansionLineNumber(CL->getBeginLoc()) << " returned to caller";
range = CL->getSourceRange();
} else if (const auto *AR = dyn_cast<AllocaRegion>(R)) {
const Expr *ARE = AR->getExpr();
- SourceLocation L = ARE->getLocStart();
+ SourceLocation L = ARE->getBeginLoc();
range = ARE->getSourceRange();
os << "stack memory allocated by call to alloca() on line "
<< SM.getExpansionLineNumber(L);
} else if (const auto *BR = dyn_cast<BlockDataRegion>(R)) {
const BlockDecl *BD = BR->getCodeRegion()->getDecl();
- SourceLocation L = BD->getLocStart();
+ SourceLocation L = BD->getBeginLoc();
range = BD->getSourceRange();
os << "stack-allocated block declared on line "
<< SM.getExpansionLineNumber(L);
diff --git a/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 2f9f5d2d9cf8..6478128ce954 100644
--- a/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -51,7 +51,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
diff --git a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index d77975559e3f..92647f032730 100644
--- a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -383,26 +383,26 @@ ProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE,
void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
CheckerContext &C) const {
+ ProgramStateRef state = C.getState();
+
// TODO: Clean up the state.
- for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
- E = SymReaper.dead_end(); I != E; ++I) {
- SymbolRef Sym = *I;
- ProgramStateRef state = C.getState();
- const StreamState *SS = state->get<StreamMap>(Sym);
- if (!SS)
+ const StreamMapTy &Map = state->get<StreamMap>();
+ for (const auto &I: Map) {
+ SymbolRef Sym = I.first;
+ const StreamState &SS = I.second;
+ if (!SymReaper.isDead(Sym) || !SS.isOpened())
continue;
- if (SS->isOpened()) {
- ExplodedNode *N = C.generateErrorNode();
- if (N) {
- if (!BT_ResourceLeak)
- BT_ResourceLeak.reset(new BuiltinBug(
- this, "Resource Leak",
- "Opened File never closed. Potential Resource leak."));
- C.emitReport(llvm::make_unique<BugReport>(
- *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N));
- }
- }
+ ExplodedNode *N = C.generateErrorNode();
+ if (!N)
+ return;
+
+ if (!BT_ResourceLeak)
+ BT_ResourceLeak.reset(
+ new BuiltinBug(this, "Resource Leak",
+ "Opened File never closed. Potential Resource leak."));
+ C.emitReport(llvm::make_unique<BugReport>(
+ *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N));
}
}
diff --git a/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp b/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
index 2e0529015ca6..3aa8e95d0ad0 100644
--- a/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
@@ -10,7 +10,7 @@
// This checker can be used for testing how taint data is propagated.
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
index f4c0edbab3f0..527e371571f1 100644
--- a/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -71,7 +71,6 @@ public:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -95,7 +94,7 @@ public:
REGISTER_SET_WITH_PROGRAMSTATE(DivZeroMap, ZeroState)
std::shared_ptr<PathDiagnosticPiece>
-DivisionBRVisitor::VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred,
+DivisionBRVisitor::VisitNode(const ExplodedNode *Succ,
BugReporterContext &BRC, BugReport &BR) {
if (Satisfied)
return nullptr;
@@ -180,7 +179,7 @@ void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
}
}
-void TestAfterDivZeroChecker::checkEndFunction(const ReturnStmt *RS,
+void TestAfterDivZeroChecker::checkEndFunction(const ReturnStmt *,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
diff --git a/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp b/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
index ee185b813611..2f06469bb209 100644
--- a/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
@@ -11,7 +11,7 @@
// as it builds the ExplodedGraph.
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtObjC.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -47,7 +47,7 @@ void TraversalDumper::checkBranchCondition(const Stmt *Condition,
// It is mildly evil to print directly to llvm::outs() rather than emitting
// warnings, but this ensures things do not get filtered out by the rest of
// the static analyzer machinery.
- SourceLocation Loc = Parent->getLocStart();
+ SourceLocation Loc = Parent->getBeginLoc();
llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
<< Parent->getStmtClassName() << "\n";
}
diff --git a/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
index f3d68014224d..5e777803af00 100644
--- a/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
@@ -1,4 +1,4 @@
-//== TrustNonnullChecker.cpp - Checker for trusting annotations -*- C++ -*--==//
+//== TrustNonnullChecker.cpp --------- API nullability modeling -*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,20 @@
//
//===----------------------------------------------------------------------===//
//
-// This checker adds an assumption that methods annotated with _Nonnull
+// This checker adds nullability-related assumptions:
+//
+// 1. Methods annotated with _Nonnull
// which come from system headers actually return a non-null pointer.
//
+// 2. NSDictionary key is non-null after the keyword subscript operation
+// on read if and only if the resulting expression is non-null.
+//
+// 3. NSMutableDictionary index is non-null after a write operation.
+//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/Analysis/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
@@ -22,10 +30,129 @@
using namespace clang;
using namespace ento;
+/// Records implications between symbols.
+/// The semantics is:
+/// (antecedent != 0) => (consequent != 0)
+/// These implications are then read during the evaluation of the assumption,
+/// and the appropriate antecedents are applied.
+REGISTER_MAP_WITH_PROGRAMSTATE(NonNullImplicationMap, SymbolRef, SymbolRef)
+
+/// The semantics is:
+/// (antecedent == 0) => (consequent == 0)
+REGISTER_MAP_WITH_PROGRAMSTATE(NullImplicationMap, SymbolRef, SymbolRef)
+
namespace {
-class TrustNonnullChecker : public Checker<check::PostCall> {
+class TrustNonnullChecker : public Checker<check::PostCall,
+ check::PostObjCMessage,
+ check::DeadSymbols,
+ eval::Assume> {
+ // Do not try to iterate over symbols with higher complexity.
+ static unsigned constexpr ComplexityThreshold = 10;
+ Selector ObjectForKeyedSubscriptSel;
+ Selector ObjectForKeySel;
+ Selector SetObjectForKeyedSubscriptSel;
+ Selector SetObjectForKeySel;
+
+public:
+ TrustNonnullChecker(ASTContext &Ctx)
+ : ObjectForKeyedSubscriptSel(
+ getKeywordSelector(Ctx, "objectForKeyedSubscript")),
+ ObjectForKeySel(getKeywordSelector(Ctx, "objectForKey")),
+ SetObjectForKeyedSubscriptSel(
+ getKeywordSelector(Ctx, "setObject", "forKeyedSubscript")),
+ SetObjectForKeySel(getKeywordSelector(Ctx, "setObject", "forKey")) {}
+
+ ProgramStateRef evalAssume(ProgramStateRef State,
+ SVal Cond,
+ bool Assumption) const {
+ const SymbolRef CondS = Cond.getAsSymbol();
+ if (!CondS || CondS->computeComplexity() > ComplexityThreshold)
+ return State;
+
+ for (auto B=CondS->symbol_begin(), E=CondS->symbol_end(); B != E; ++B) {
+ const SymbolRef Antecedent = *B;
+ State = addImplication(Antecedent, State, true);
+ State = addImplication(Antecedent, State, false);
+ }
+
+ return State;
+ }
+
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
+ // Only trust annotations for system headers for non-protocols.
+ if (!Call.isInSystemHeader())
+ return;
+
+ ProgramStateRef State = C.getState();
+
+ if (isNonNullPtr(Call, C))
+ if (auto L = Call.getReturnValue().getAs<Loc>())
+ State = State->assume(*L, /*Assumption=*/true);
+
+ C.addTransition(State);
+ }
+
+ void checkPostObjCMessage(const ObjCMethodCall &Msg,
+ CheckerContext &C) const {
+ const ObjCInterfaceDecl *ID = Msg.getReceiverInterface();
+ if (!ID)
+ return;
+
+ ProgramStateRef State = C.getState();
+
+ // Index to setter for NSMutableDictionary is assumed to be non-null,
+ // as an exception is thrown otherwise.
+ if (interfaceHasSuperclass(ID, "NSMutableDictionary") &&
+ (Msg.getSelector() == SetObjectForKeyedSubscriptSel ||
+ Msg.getSelector() == SetObjectForKeySel)) {
+ if (auto L = Msg.getArgSVal(1).getAs<Loc>())
+ State = State->assume(*L, /*Assumption=*/true);
+ }
+
+ // Record an implication: index is non-null if the output is non-null.
+ if (interfaceHasSuperclass(ID, "NSDictionary") &&
+ (Msg.getSelector() == ObjectForKeyedSubscriptSel ||
+ Msg.getSelector() == ObjectForKeySel)) {
+ SymbolRef ArgS = Msg.getArgSVal(0).getAsSymbol();
+ SymbolRef RetS = Msg.getReturnValue().getAsSymbol();
+
+ if (ArgS && RetS) {
+ // Emulate an implication: the argument is non-null if
+ // the return value is non-null.
+ State = State->set<NonNullImplicationMap>(RetS, ArgS);
+
+ // Conversely, when the argument is null, the return value
+ // is definitely null.
+ State = State->set<NullImplicationMap>(ArgS, RetS);
+ }
+ }
+
+ C.addTransition(State);
+ }
+
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+
+ State = dropDeadFromGDM<NullImplicationMap>(SymReaper, State);
+ State = dropDeadFromGDM<NonNullImplicationMap>(SymReaper, State);
+
+ C.addTransition(State);
+ }
+
private:
+
+ /// \returns State with GDM \p MapName where all dead symbols were
+ // removed.
+ template <typename MapName>
+ ProgramStateRef dropDeadFromGDM(SymbolReaper &SymReaper,
+ ProgramStateRef State) const {
+ for (const std::pair<SymbolRef, SymbolRef> &P : State->get<MapName>())
+ if (!SymReaper.isLive(P.first) || !SymReaper.isLive(P.second))
+ State = State->remove<MapName>(P.first);
+ return State;
+ }
+
/// \returns Whether we trust the result of the method call to be
/// a non-null pointer.
bool isNonNullPtr(const CallEvent &Call, CheckerContext &C) const {
@@ -66,19 +193,57 @@ private:
return false;
}
-public:
- void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
- // Only trust annotations for system headers for non-protocols.
- if (!Call.isInSystemHeader())
- return;
+ /// \return Whether \p ID has a superclass by the name \p ClassName.
+ bool interfaceHasSuperclass(const ObjCInterfaceDecl *ID,
+ StringRef ClassName) const {
+ if (ID->getIdentifier()->getName() == ClassName)
+ return true;
- ProgramStateRef State = C.getState();
+ if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
+ return interfaceHasSuperclass(Super, ClassName);
- if (isNonNullPtr(Call, C))
- if (auto L = Call.getReturnValue().getAs<Loc>())
- State = State->assume(*L, /*Assumption=*/true);
+ return false;
+ }
- C.addTransition(State);
+
+ /// \return a state with an optional implication added (if exists)
+ /// from a map of recorded implications.
+ /// If \p Negated is true, checks NullImplicationMap, and assumes
+ /// the negation of \p Antecedent.
+ /// Checks NonNullImplicationMap and assumes \p Antecedent otherwise.
+ ProgramStateRef addImplication(SymbolRef Antecedent,
+ ProgramStateRef InputState,
+ bool Negated) const {
+ if (!InputState)
+ return nullptr;
+ SValBuilder &SVB = InputState->getStateManager().getSValBuilder();
+ const SymbolRef *Consequent =
+ Negated ? InputState->get<NonNullImplicationMap>(Antecedent)
+ : InputState->get<NullImplicationMap>(Antecedent);
+ if (!Consequent)
+ return InputState;
+
+ SVal AntecedentV = SVB.makeSymbolVal(Antecedent);
+ ProgramStateRef State = InputState;
+
+ if ((Negated && InputState->isNonNull(AntecedentV).isConstrainedTrue())
+ || (!Negated && InputState->isNull(AntecedentV).isConstrainedTrue())) {
+ SVal ConsequentS = SVB.makeSymbolVal(*Consequent);
+ State = InputState->assume(ConsequentS.castAs<DefinedSVal>(), Negated);
+ if (!State)
+ return nullptr;
+
+ // Drop implications from the map.
+ if (Negated) {
+ State = State->remove<NonNullImplicationMap>(Antecedent);
+ State = State->remove<NullImplicationMap>(*Consequent);
+ } else {
+ State = State->remove<NullImplicationMap>(Antecedent);
+ State = State->remove<NonNullImplicationMap>(*Consequent);
+ }
+ }
+
+ return State;
}
};
@@ -86,5 +251,5 @@ public:
void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {
- Mgr.registerChecker<TrustNonnullChecker>();
+ Mgr.registerChecker<TrustNonnullChecker>(Mgr.getASTContext());
}
diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index 934ee63318fa..d7fad4e475ab 100644
--- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -98,7 +98,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
// Emit the bug report.
auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
- bugreporter::trackNullOrUndefValue(N, Ex, *R);
+ bugreporter::trackExpressionValue(N, Ex, *R);
R->addRange(Ex->getSourceRange());
Ctx.emitReport(std::move(R));
diff --git a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 6a93c10c7644..8a625227b81e 100644
--- a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
diff --git a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index b9a93bedca2e..624cff6048fd 100644
--- a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -69,6 +69,7 @@ static bool isLeftShiftResultUnrepresentable(const BinaryOperator *B,
ProgramStateRef State = C.getState();
const llvm::APSInt *LHS = SB.getKnownValue(State, C.getSVal(B->getLHS()));
const llvm::APSInt *RHS = SB.getKnownValue(State, C.getSVal(B->getRHS()));
+ assert(LHS && RHS && "Values unknown, inconsistent state");
return (unsigned)RHS->getZExtValue() > LHS->countLeadingZeros();
}
@@ -122,6 +123,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
<< ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left"
: "right")
<< " shift is undefined because the right operand is negative";
+ Ex = B->getRHS();
} else if ((B->getOpcode() == BinaryOperatorKind::BO_Shl ||
B->getOpcode() == BinaryOperatorKind::BO_Shr) &&
isShiftOverflow(B, C)) {
@@ -130,6 +132,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
<< ((B->getOpcode() == BinaryOperatorKind::BO_Shl) ? "left"
: "right")
<< " shift is undefined due to shifting by ";
+ Ex = B->getRHS();
SValBuilder &SB = C.getSValBuilder();
const llvm::APSInt *I =
@@ -147,6 +150,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
C.isNegative(B->getLHS())) {
OS << "The result of the left shift is undefined because the left "
"operand is negative";
+ Ex = B->getLHS();
} else if (B->getOpcode() == BinaryOperatorKind::BO_Shl &&
isLeftShiftResultUnrepresentable(B, C)) {
ProgramStateRef State = C.getState();
@@ -160,6 +164,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
<< "\', which is unrepresentable in the unsigned version of "
<< "the return type \'" << B->getLHS()->getType().getAsString()
<< "\'";
+ Ex = B->getLHS();
} else {
OS << "The result of the '"
<< BinaryOperator::getOpcodeStr(B->getOpcode())
@@ -169,10 +174,10 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
auto report = llvm::make_unique<BugReport>(*BT, OS.str(), N);
if (Ex) {
report->addRange(Ex->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, Ex, *report);
+ bugreporter::trackExpressionValue(N, Ex, *report);
}
else
- bugreporter::trackNullOrUndefValue(N, B, *report);
+ bugreporter::trackExpressionValue(N, B, *report);
C.emitReport(std::move(report));
}
diff --git a/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
index fe07eafd281f..1d78d7cebd67 100644
--- a/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/DeclCXX.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -55,7 +55,7 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
// Generate a report for this bug.
auto R = llvm::make_unique<BugReport>(*BT, BT->getName(), N);
R->addRange(A->getIdx()->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, A->getIdx(), *R);
+ bugreporter::trackExpressionValue(N, A->getIdx(), *R);
C.emitReport(std::move(R));
}
diff --git a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index 2ef6855ba6b7..8e10bfdd2f3c 100644
--- a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -112,7 +112,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
auto R = llvm::make_unique<BugReport>(*BT, OS.str(), N);
if (ex) {
R->addRange(ex->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, ex, *R);
+ bugreporter::trackExpressionValue(N, ex, *R);
}
C.emitReport(std::move(R));
}
diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h
new file mode 100644
index 000000000000..c3291a21c164
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h
@@ -0,0 +1,349 @@
+//===----- UninitializedObject.h ---------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helper classes for UninitializedObjectChecker and
+// documentation about the logic of it.
+//
+// The checker reports uninitialized fields in objects created after a
+// constructor call.
+//
+// This checker has several options:
+// - "Pedantic" (boolean). If its not set or is set to false, the checker
+// won't emit warnings for objects that don't have at least one initialized
+// field. This may be set with
+//
+// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`.
+//
+// - "NotesAsWarnings" (boolean). If set to true, the checker will emit a
+// warning for each uninitialized field, as opposed to emitting one warning
+// per constructor call, and listing the uninitialized fields that belongs
+// to it in notes. Defaults to false.
+//
+// `-analyzer-config \
+// alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`.
+//
+// - "CheckPointeeInitialization" (boolean). If set to false, the checker will
+// not analyze the pointee of pointer/reference fields, and will only check
+// whether the object itself is initialized. Defaults to false.
+//
+// `-analyzer-config \
+// alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`.
+//
+// - "IgnoreRecordsWithField" (string). If supplied, the checker will not
+// analyze structures that have a field with a name or type name that
+// matches the given pattern. Defaults to "".
+//
+// `-analyzer-config \
+// alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"`.
+//
+// TODO: With some clever heuristics, some pointers should be dereferenced
+// by default. For example, if the pointee is constructed within the
+// constructor call, it's reasonable to say that no external object
+// references it, and we wouldn't generate multiple report on the same
+// pointee.
+//
+// Most of the following methods as well as the checker itself is defined in
+// UninitializedObjectChecker.cpp.
+//
+// Some methods are implemented in UninitializedPointee.cpp, to reduce the
+// complexity of the main checker file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_UNINITIALIZEDOBJECT_H
+#define LLVM_CLANG_STATICANALYZER_UNINITIALIZEDOBJECT_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+namespace clang {
+namespace ento {
+
+struct UninitObjCheckerOptions {
+ bool IsPedantic = false;
+ bool ShouldConvertNotesToWarnings = false;
+ bool CheckPointeeInitialization = false;
+ std::string IgnoredRecordsWithFieldPattern;
+};
+
+/// A lightweight polymorphic wrapper around FieldRegion *. We'll use this
+/// interface to store addinitional information about fields. As described
+/// later, a list of these objects (i.e. "fieldchain") will be constructed and
+/// used for printing note messages should an uninitialized value be found.
+class FieldNode {
+protected:
+ const FieldRegion *FR;
+
+ /// FieldNodes are never meant to be created on the heap, see
+ /// FindUninitializedFields::addFieldToUninits().
+ /* non-virtual */ ~FieldNode() = default;
+
+public:
+ FieldNode(const FieldRegion *FR) : FR(FR) {}
+
+ // We'll delete all of these special member functions to force the users of
+ // this interface to only store references to FieldNode objects in containers.
+ FieldNode() = delete;
+ FieldNode(const FieldNode &) = delete;
+ FieldNode(FieldNode &&) = delete;
+ FieldNode &operator=(const FieldNode &) = delete;
+ FieldNode &operator=(const FieldNode &&) = delete;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(this); }
+
+ /// Helper method for uniqueing.
+ bool isSameRegion(const FieldRegion *OtherFR) const {
+ // Special FieldNode descendants may wrap nullpointers (for example if they
+ // describe a special relationship between two elements of the fieldchain)
+ // -- we wouldn't like to unique these objects.
+ if (FR == nullptr)
+ return false;
+
+ return FR == OtherFR;
+ }
+
+ const FieldRegion *getRegion() const { return FR; }
+ const FieldDecl *getDecl() const {
+ assert(FR);
+ return FR->getDecl();
+ }
+
+ // When a fieldchain is printed, it will have the following format (without
+ // newline, indices are in order of insertion, from 1 to n):
+ //
+ // <note_message_n>'<prefix_n><prefix_n-1>...<prefix_1>
+ // this-><node_1><separator_1><node_2><separator_2>...<node_n>'
+
+ /// If this is the last element of the fieldchain, this method will print the
+ /// note message associated with it.
+ /// The note message should state something like "uninitialized field" or
+ /// "uninitialized pointee" etc.
+ virtual void printNoteMsg(llvm::raw_ostream &Out) const = 0;
+
+ /// Print any prefixes before the fieldchain. Could contain casts, etc.
+ virtual void printPrefix(llvm::raw_ostream &Out) const = 0;
+
+ /// Print the node. Should contain the name of the field stored in FR.
+ virtual void printNode(llvm::raw_ostream &Out) const = 0;
+
+ /// Print the separator. For example, fields may be separated with '.' or
+ /// "->".
+ virtual void printSeparator(llvm::raw_ostream &Out) const = 0;
+
+ virtual bool isBase() const { return false; }
+};
+
+/// Returns with Field's name. This is a helper function to get the correct name
+/// even if Field is a captured lambda variable.
+std::string getVariableName(const FieldDecl *Field);
+
+/// Represents a field chain. A field chain is a list of fields where the first
+/// element of the chain is the object under checking (not stored), and every
+/// other element is a field, and the element that precedes it is the object
+/// that contains it.
+///
+/// Note that this class is immutable (essentially a wrapper around an
+/// ImmutableList), new FieldChainInfo objects may be created by member
+/// functions such as add() and replaceHead().
+class FieldChainInfo {
+public:
+ using FieldChain = llvm::ImmutableList<const FieldNode &>;
+
+private:
+ FieldChain::Factory &ChainFactory;
+ FieldChain Chain;
+
+ FieldChainInfo(FieldChain::Factory &F, FieldChain NewChain)
+ : FieldChainInfo(F) {
+ Chain = NewChain;
+ }
+
+public:
+ FieldChainInfo() = delete;
+ FieldChainInfo(FieldChain::Factory &F) : ChainFactory(F) {}
+ FieldChainInfo(const FieldChainInfo &Other) = default;
+
+ /// Constructs a new FieldChainInfo object with \p FN appended.
+ template <class FieldNodeT> FieldChainInfo add(const FieldNodeT &FN);
+
+ /// Constructs a new FieldChainInfo object with \p FN as the new head of the
+ /// list.
+ template <class FieldNodeT> FieldChainInfo replaceHead(const FieldNodeT &FN);
+
+ bool contains(const FieldRegion *FR) const;
+ bool isEmpty() const { return Chain.isEmpty(); }
+
+ const FieldNode &getHead() const { return Chain.getHead(); }
+ const FieldRegion *getUninitRegion() const { return getHead().getRegion(); }
+
+ void printNoteMsg(llvm::raw_ostream &Out) const;
+};
+
+using UninitFieldMap = std::map<const FieldRegion *, llvm::SmallString<50>>;
+
+/// Searches for and stores uninitialized fields in a non-union object.
+class FindUninitializedFields {
+ ProgramStateRef State;
+ const TypedValueRegion *const ObjectR;
+
+ const UninitObjCheckerOptions Opts;
+ bool IsAnyFieldInitialized = false;
+
+ FieldChainInfo::FieldChain::Factory ChainFactory;
+
+ /// A map for assigning uninitialized regions to note messages. For example,
+ ///
+ /// struct A {
+ /// int x;
+ /// };
+ ///
+ /// A a;
+ ///
+ /// After analyzing `a`, the map will contain a pair for `a.x`'s region and
+ /// the note message "uninitialized field 'this->x'.
+ UninitFieldMap UninitFields;
+
+public:
+ /// Constructs the FindUninitializedField object, searches for and stores
+ /// uninitialized fields in R.
+ FindUninitializedFields(ProgramStateRef State,
+ const TypedValueRegion *const R,
+ const UninitObjCheckerOptions &Opts);
+
+ /// Returns with the modified state and a map of (uninitialized region,
+ /// note message) pairs.
+ std::pair<ProgramStateRef, const UninitFieldMap &> getResults() {
+ return {State, UninitFields};
+ }
+
+ /// Returns whether the analyzed region contains at least one initialized
+ /// field. Note that this includes subfields as well, not just direct ones,
+ /// and will return false if an uninitialized pointee is found with
+ /// CheckPointeeInitialization enabled.
+ bool isAnyFieldInitialized() { return IsAnyFieldInitialized; }
+
+private:
+ // For the purposes of this checker, we'll regard the analyzed region as a
+ // directed tree, where
+ // * the root is the object under checking
+ // * every node is an object that is
+ // - a union
+ // - a non-union record
+ // - dereferenceable (see isDereferencableType())
+ // - an array
+ // - of a primitive type (see isPrimitiveType())
+ // * the parent of each node is the object that contains it
+ // * every leaf is an array, a primitive object, a nullptr or an undefined
+ // pointer.
+ //
+ // Example:
+ //
+ // struct A {
+ // struct B {
+ // int x, y = 0;
+ // };
+ // B b;
+ // int *iptr = new int;
+ // B* bptr;
+ //
+ // A() {}
+ // };
+ //
+ // The directed tree:
+ //
+ // ->x
+ // /
+ // ->b--->y
+ // /
+ // A-->iptr->(int value)
+ // \
+ // ->bptr
+ //
+ // From this we'll construct a vector of fieldchains, where each fieldchain
+ // represents an uninitialized field. An uninitialized field may be a
+ // primitive object, a pointer, a pointee or a union without a single
+ // initialized field.
+ // In the above example, for the default constructor call we'll end up with
+ // these fieldchains:
+ //
+ // this->b.x
+ // this->iptr (pointee uninit)
+ // this->bptr (pointer uninit)
+ //
+ // We'll traverse each node of the above graph with the appropriate one of
+ // these methods:
+
+ /// Checks the region of a union object, and returns true if no field is
+ /// initialized within the region.
+ bool isUnionUninit(const TypedValueRegion *R);
+
+ /// Checks a region of a non-union object, and returns true if an
+ /// uninitialized field is found within the region.
+ bool isNonUnionUninit(const TypedValueRegion *R, FieldChainInfo LocalChain);
+
+ /// Checks a region of a pointer or reference object, and returns true if the
+ /// ptr/ref object itself or any field within the pointee's region is
+ /// uninitialized.
+ bool isDereferencableUninit(const FieldRegion *FR, FieldChainInfo LocalChain);
+
+ /// Returns true if the value of a primitive object is uninitialized.
+ bool isPrimitiveUninit(const SVal &V);
+
+ // Note that we don't have a method for arrays -- the elements of an array are
+ // often left uninitialized intentionally even when it is of a C++ record
+ // type, so we'll assume that an array is always initialized.
+ // TODO: Add a support for nonloc::LocAsInteger.
+
+ /// Processes LocalChain and attempts to insert it into UninitFields. Returns
+ /// true on success. Also adds the head of the list and \p PointeeR (if
+ /// supplied) to the GDM as already analyzed objects.
+ ///
+ /// Since this class analyzes regions with recursion, we'll only store
+ /// references to temporary FieldNode objects created on the stack. This means
+ /// that after analyzing a leaf of the directed tree described above, the
+ /// elements LocalChain references will be destructed, so we can't store it
+ /// directly.
+ bool addFieldToUninits(FieldChainInfo LocalChain,
+ const MemRegion *PointeeR = nullptr);
+};
+
+/// Returns true if T is a primitive type. An object of a primitive type only
+/// needs to be analyzed as much as checking whether their value is undefined.
+inline bool isPrimitiveType(const QualType &T) {
+ return T->isBuiltinType() || T->isEnumeralType() ||
+ T->isMemberPointerType() || T->isBlockPointerType() ||
+ T->isFunctionType();
+}
+
+inline bool isDereferencableType(const QualType &T) {
+ return T->isAnyPointerType() || T->isReferenceType();
+}
+
+// Template method definitions.
+
+template <class FieldNodeT>
+inline FieldChainInfo FieldChainInfo::add(const FieldNodeT &FN) {
+ assert(!contains(FN.getRegion()) &&
+ "Can't add a field that is already a part of the "
+ "fieldchain! Is this a cyclic reference?");
+
+ FieldChainInfo NewChain = *this;
+ NewChain.Chain = ChainFactory.add(FN, Chain);
+ return NewChain;
+}
+
+template <class FieldNodeT>
+inline FieldChainInfo FieldChainInfo::replaceHead(const FieldNodeT &FN) {
+ FieldChainInfo NewChain(ChainFactory, Chain.getTail());
+ return NewChain.add(FN);
+}
+
+} // end of namespace ento
+} // end of namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_UNINITIALIZEDOBJECT_H
diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
new file mode 100644
index 000000000000..208e303e8295
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
@@ -0,0 +1,538 @@
+//===----- UninitializedObjectChecker.cpp ------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a checker that reports uninitialized fields in objects
+// created after a constructor call.
+//
+// To read about command line options and how the checker works, refer to the
+// top of the file and inline comments in UninitializedObject.h.
+//
+// Some of the logic is implemented in UninitializedPointee.cpp, to reduce the
+// complexity of this file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "UninitializedObject.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+
+using namespace clang;
+using namespace clang::ento;
+
+/// We'll mark fields (and pointee of fields) that are confirmed to be
+/// uninitialized as already analyzed.
+REGISTER_SET_WITH_PROGRAMSTATE(AnalyzedRegions, const MemRegion *)
+
+namespace {
+
+class UninitializedObjectChecker
+ : public Checker<check::EndFunction, check::DeadSymbols> {
+ std::unique_ptr<BuiltinBug> BT_uninitField;
+
+public:
+ // The fields of this struct will be initialized when registering the checker.
+ UninitObjCheckerOptions Opts;
+
+ UninitializedObjectChecker()
+ : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
+
+ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+};
+
+/// A basic field type, that is not a pointer or a reference, it's dynamic and
+/// static type is the same.
+class RegularField final : public FieldNode {
+public:
+ RegularField(const FieldRegion *FR) : FieldNode(FR) {}
+
+ virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
+ Out << "uninitialized field ";
+ }
+
+ virtual void printPrefix(llvm::raw_ostream &Out) const override {}
+
+ virtual void printNode(llvm::raw_ostream &Out) const override {
+ Out << getVariableName(getDecl());
+ }
+
+ virtual void printSeparator(llvm::raw_ostream &Out) const override {
+ Out << '.';
+ }
+};
+
+/// Represents that the FieldNode that comes after this is declared in a base
+/// of the previous FieldNode. As such, this descendant doesn't wrap a
+/// FieldRegion, and is purely a tool to describe a relation between two other
+/// FieldRegion wrapping descendants.
+class BaseClass final : public FieldNode {
+ const QualType BaseClassT;
+
+public:
+ BaseClass(const QualType &T) : FieldNode(nullptr), BaseClassT(T) {
+ assert(!T.isNull());
+ assert(T->getAsCXXRecordDecl());
+ }
+
+ virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
+ llvm_unreachable("This node can never be the final node in the "
+ "fieldchain!");
+ }
+
+ virtual void printPrefix(llvm::raw_ostream &Out) const override {}
+
+ virtual void printNode(llvm::raw_ostream &Out) const override {
+ Out << BaseClassT->getAsCXXRecordDecl()->getName() << "::";
+ }
+
+ virtual void printSeparator(llvm::raw_ostream &Out) const override {}
+
+ virtual bool isBase() const override { return true; }
+};
+
+} // end of anonymous namespace
+
+// Utility function declarations.
+
+/// Returns the region that was constructed by CtorDecl, or nullptr if that
+/// isn't possible.
+static const TypedValueRegion *
+getConstructedRegion(const CXXConstructorDecl *CtorDecl,
+ CheckerContext &Context);
+
+/// Checks whether the object constructed by \p Ctor will be analyzed later
+/// (e.g. if the object is a field of another object, in which case we'd check
+/// it multiple times).
+static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor,
+ CheckerContext &Context);
+
+/// Checks whether RD contains a field with a name or type name that matches
+/// \p Pattern.
+static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern);
+
+//===----------------------------------------------------------------------===//
+// Methods for UninitializedObjectChecker.
+//===----------------------------------------------------------------------===//
+
+void UninitializedObjectChecker::checkEndFunction(
+ const ReturnStmt *RS, CheckerContext &Context) const {
+
+ const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(
+ Context.getLocationContext()->getDecl());
+ if (!CtorDecl)
+ return;
+
+ if (!CtorDecl->isUserProvided())
+ return;
+
+ if (CtorDecl->getParent()->isUnion())
+ return;
+
+ // This avoids essentially the same error being reported multiple times.
+ if (willObjectBeAnalyzedLater(CtorDecl, Context))
+ return;
+
+ const TypedValueRegion *R = getConstructedRegion(CtorDecl, Context);
+ if (!R)
+ return;
+
+ FindUninitializedFields F(Context.getState(), R, Opts);
+
+ std::pair<ProgramStateRef, const UninitFieldMap &> UninitInfo =
+ F.getResults();
+
+ ProgramStateRef UpdatedState = UninitInfo.first;
+ const UninitFieldMap &UninitFields = UninitInfo.second;
+
+ if (UninitFields.empty()) {
+ Context.addTransition(UpdatedState);
+ return;
+ }
+
+ // There are uninitialized fields in the record.
+
+ ExplodedNode *Node = Context.generateNonFatalErrorNode(UpdatedState);
+ if (!Node)
+ return;
+
+ PathDiagnosticLocation LocUsedForUniqueing;
+ const Stmt *CallSite = Context.getStackFrame()->getCallSite();
+ if (CallSite)
+ LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
+ CallSite, Context.getSourceManager(), Node->getLocationContext());
+
+ // For Plist consumers that don't support notes just yet, we'll convert notes
+ // to warnings.
+ if (Opts.ShouldConvertNotesToWarnings) {
+ for (const auto &Pair : UninitFields) {
+
+ auto Report = llvm::make_unique<BugReport>(
+ *BT_uninitField, Pair.second, Node, LocUsedForUniqueing,
+ Node->getLocationContext()->getDecl());
+ Context.emitReport(std::move(Report));
+ }
+ return;
+ }
+
+ SmallString<100> WarningBuf;
+ llvm::raw_svector_ostream WarningOS(WarningBuf);
+ WarningOS << UninitFields.size() << " uninitialized field"
+ << (UninitFields.size() == 1 ? "" : "s")
+ << " at the end of the constructor call";
+
+ auto Report = llvm::make_unique<BugReport>(
+ *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
+ Node->getLocationContext()->getDecl());
+
+ for (const auto &Pair : UninitFields) {
+ Report->addNote(Pair.second,
+ PathDiagnosticLocation::create(Pair.first->getDecl(),
+ Context.getSourceManager()));
+ }
+ Context.emitReport(std::move(Report));
+}
+
+void UninitializedObjectChecker::checkDeadSymbols(SymbolReaper &SR,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ for (const MemRegion *R : State->get<AnalyzedRegions>()) {
+ if (!SR.isLiveRegion(R))
+ State = State->remove<AnalyzedRegions>(R);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Methods for FindUninitializedFields.
+//===----------------------------------------------------------------------===//
+
+FindUninitializedFields::FindUninitializedFields(
+ ProgramStateRef State, const TypedValueRegion *const R,
+ const UninitObjCheckerOptions &Opts)
+ : State(State), ObjectR(R), Opts(Opts) {
+
+ isNonUnionUninit(ObjectR, FieldChainInfo(ChainFactory));
+
+ // In non-pedantic mode, if ObjectR doesn't contain a single initialized
+ // field, we'll assume that Object was intentionally left uninitialized.
+ if (!Opts.IsPedantic && !isAnyFieldInitialized())
+ UninitFields.clear();
+}
+
+bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain,
+ const MemRegion *PointeeR) {
+ const FieldRegion *FR = Chain.getUninitRegion();
+
+ assert((PointeeR || !isDereferencableType(FR->getDecl()->getType())) &&
+ "One must also pass the pointee region as a parameter for "
+ "dereferenceable fields!");
+
+ if (State->contains<AnalyzedRegions>(FR))
+ return false;
+
+ if (PointeeR) {
+ if (State->contains<AnalyzedRegions>(PointeeR)) {
+ return false;
+ }
+ State = State->add<AnalyzedRegions>(PointeeR);
+ }
+
+ State = State->add<AnalyzedRegions>(FR);
+
+ if (State->getStateManager().getContext().getSourceManager().isInSystemHeader(
+ FR->getDecl()->getLocation()))
+ return false;
+
+ UninitFieldMap::mapped_type NoteMsgBuf;
+ llvm::raw_svector_ostream OS(NoteMsgBuf);
+ Chain.printNoteMsg(OS);
+ return UninitFields.insert({FR, std::move(NoteMsgBuf)}).second;
+}
+
+bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R,
+ FieldChainInfo LocalChain) {
+ assert(R->getValueType()->isRecordType() &&
+ !R->getValueType()->isUnionType() &&
+ "This method only checks non-union record objects!");
+
+ const RecordDecl *RD = R->getValueType()->getAsRecordDecl()->getDefinition();
+
+ if (!RD) {
+ IsAnyFieldInitialized = true;
+ return true;
+ }
+
+ if (!Opts.IgnoredRecordsWithFieldPattern.empty() &&
+ shouldIgnoreRecord(RD, Opts.IgnoredRecordsWithFieldPattern)) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ bool ContainsUninitField = false;
+
+ // Are all of this non-union's fields initialized?
+ for (const FieldDecl *I : RD->fields()) {
+
+ const auto FieldVal =
+ State->getLValue(I, loc::MemRegionVal(R)).castAs<loc::MemRegionVal>();
+ const auto *FR = FieldVal.getRegionAs<FieldRegion>();
+ QualType T = I->getType();
+
+ // If LocalChain already contains FR, then we encountered a cyclic
+ // reference. In this case, region FR is already under checking at an
+ // earlier node in the directed tree.
+ if (LocalChain.contains(FR))
+ return false;
+
+ if (T->isStructureOrClassType()) {
+ if (isNonUnionUninit(FR, LocalChain.add(RegularField(FR))))
+ ContainsUninitField = true;
+ continue;
+ }
+
+ if (T->isUnionType()) {
+ if (isUnionUninit(FR)) {
+ if (addFieldToUninits(LocalChain.add(RegularField(FR))))
+ ContainsUninitField = true;
+ } else
+ IsAnyFieldInitialized = true;
+ continue;
+ }
+
+ if (T->isArrayType()) {
+ IsAnyFieldInitialized = true;
+ continue;
+ }
+
+ SVal V = State->getSVal(FieldVal);
+
+ if (isDereferencableType(T) || V.getAs<nonloc::LocAsInteger>()) {
+ if (isDereferencableUninit(FR, LocalChain))
+ ContainsUninitField = true;
+ continue;
+ }
+
+ if (isPrimitiveType(T)) {
+ if (isPrimitiveUninit(V)) {
+ if (addFieldToUninits(LocalChain.add(RegularField(FR))))
+ ContainsUninitField = true;
+ }
+ continue;
+ }
+
+ llvm_unreachable("All cases are handled!");
+ }
+
+ // Checking bases. The checker will regard inherited data members as direct
+ // fields.
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+ if (!CXXRD)
+ return ContainsUninitField;
+
+ for (const CXXBaseSpecifier &BaseSpec : CXXRD->bases()) {
+ const auto *BaseRegion = State->getLValue(BaseSpec, R)
+ .castAs<loc::MemRegionVal>()
+ .getRegionAs<TypedValueRegion>();
+
+ // If the head of the list is also a BaseClass, we'll overwrite it to avoid
+ // note messages like 'this->A::B::x'.
+ if (!LocalChain.isEmpty() && LocalChain.getHead().isBase()) {
+ if (isNonUnionUninit(BaseRegion, LocalChain.replaceHead(
+ BaseClass(BaseSpec.getType()))))
+ ContainsUninitField = true;
+ } else {
+ if (isNonUnionUninit(BaseRegion,
+ LocalChain.add(BaseClass(BaseSpec.getType()))))
+ ContainsUninitField = true;
+ }
+ }
+
+ return ContainsUninitField;
+}
+
+bool FindUninitializedFields::isUnionUninit(const TypedValueRegion *R) {
+ assert(R->getValueType()->isUnionType() &&
+ "This method only checks union objects!");
+ // TODO: Implement support for union fields.
+ return false;
+}
+
+bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) {
+ if (V.isUndef())
+ return true;
+
+ IsAnyFieldInitialized = true;
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods for FieldChainInfo.
+//===----------------------------------------------------------------------===//
+
+bool FieldChainInfo::contains(const FieldRegion *FR) const {
+ for (const FieldNode &Node : Chain) {
+ if (Node.isSameRegion(FR))
+ return true;
+ }
+ return false;
+}
+
+/// Prints every element except the last to `Out`. Since ImmutableLists store
+/// elements in reverse order, and have no reverse iterators, we use a
+/// recursive function to print the fieldchain correctly. The last element in
+/// the chain is to be printed by `FieldChainInfo::print`.
+static void printTail(llvm::raw_ostream &Out,
+ const FieldChainInfo::FieldChain L);
+
+// FIXME: This function constructs an incorrect string in the following case:
+//
+// struct Base { int x; };
+// struct D1 : Base {}; struct D2 : Base {};
+//
+// struct MostDerived : D1, D2 {
+// MostDerived() {}
+// }
+//
+// A call to MostDerived::MostDerived() will cause two notes that say
+// "uninitialized field 'this->x'", but we can't refer to 'x' directly,
+// we need an explicit namespace resolution whether the uninit field was
+// 'D1::x' or 'D2::x'.
+void FieldChainInfo::printNoteMsg(llvm::raw_ostream &Out) const {
+ if (Chain.isEmpty())
+ return;
+
+ const FieldNode &LastField = getHead();
+
+ LastField.printNoteMsg(Out);
+ Out << '\'';
+
+ for (const FieldNode &Node : Chain)
+ Node.printPrefix(Out);
+
+ Out << "this->";
+ printTail(Out, Chain.getTail());
+ LastField.printNode(Out);
+ Out << '\'';
+}
+
+static void printTail(llvm::raw_ostream &Out,
+ const FieldChainInfo::FieldChain L) {
+ if (L.isEmpty())
+ return;
+
+ printTail(Out, L.getTail());
+
+ L.getHead().printNode(Out);
+ L.getHead().printSeparator(Out);
+}
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static const TypedValueRegion *
+getConstructedRegion(const CXXConstructorDecl *CtorDecl,
+ CheckerContext &Context) {
+
+ Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl,
+ Context.getStackFrame());
+
+ SVal ObjectV = Context.getState()->getSVal(ThisLoc);
+
+ auto *R = ObjectV.getAsRegion()->getAs<TypedValueRegion>();
+ if (R && !R->getValueType()->getAsCXXRecordDecl())
+ return nullptr;
+
+ return R;
+}
+
+static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor,
+ CheckerContext &Context) {
+
+ const TypedValueRegion *CurrRegion = getConstructedRegion(Ctor, Context);
+ if (!CurrRegion)
+ return false;
+
+ const LocationContext *LC = Context.getLocationContext();
+ while ((LC = LC->getParent())) {
+
+ // If \p Ctor was called by another constructor.
+ const auto *OtherCtor = dyn_cast<CXXConstructorDecl>(LC->getDecl());
+ if (!OtherCtor)
+ continue;
+
+ const TypedValueRegion *OtherRegion =
+ getConstructedRegion(OtherCtor, Context);
+ if (!OtherRegion)
+ continue;
+
+ // If the CurrRegion is a subregion of OtherRegion, it will be analyzed
+ // during the analysis of OtherRegion.
+ if (CurrRegion->isSubRegionOf(OtherRegion))
+ return true;
+ }
+
+ return false;
+}
+
+static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern) {
+ llvm::Regex R(Pattern);
+
+ for (const FieldDecl *FD : RD->fields()) {
+ if (R.match(FD->getType().getAsString()))
+ return true;
+ if (R.match(FD->getName()))
+ return true;
+ }
+
+ return false;
+}
+
+std::string clang::ento::getVariableName(const FieldDecl *Field) {
+ // If Field is a captured lambda variable, Field->getName() will return with
+ // an empty string. We can however acquire it's name from the lambda's
+ // captures.
+ const auto *CXXParent = dyn_cast<CXXRecordDecl>(Field->getParent());
+
+ if (CXXParent && CXXParent->isLambda()) {
+ assert(CXXParent->captures_begin());
+ auto It = CXXParent->captures_begin() + Field->getFieldIndex();
+
+ if (It->capturesVariable())
+ return llvm::Twine("/*captured variable*/" +
+ It->getCapturedVar()->getName())
+ .str();
+
+ if (It->capturesThis())
+ return "/*'this' capture*/";
+
+ llvm_unreachable("No other capture type is expected!");
+ }
+
+ return Field->getName();
+}
+
+void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) {
+ auto Chk = Mgr.registerChecker<UninitializedObjectChecker>();
+
+ AnalyzerOptions &AnOpts = Mgr.getAnalyzerOptions();
+ UninitObjCheckerOptions &ChOpts = Chk->Opts;
+
+ ChOpts.IsPedantic =
+ AnOpts.getCheckerBooleanOption("Pedantic", /*DefaultVal*/ false, Chk);
+ ChOpts.ShouldConvertNotesToWarnings =
+ AnOpts.getCheckerBooleanOption("NotesAsWarnings", /*DefaultVal*/ false, Chk);
+ ChOpts.CheckPointeeInitialization = AnOpts.getCheckerBooleanOption(
+ "CheckPointeeInitialization", /*DefaultVal*/ false, Chk);
+ ChOpts.IgnoredRecordsWithFieldPattern =
+ AnOpts.getCheckerStringOption("IgnoreRecordsWithField",
+ /*DefaultVal*/ "", Chk);
+}
diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp
new file mode 100644
index 000000000000..aead59c7bf87
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp
@@ -0,0 +1,282 @@
+//===----- UninitializedPointee.cpp ------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions and methods for handling pointers and references
+// to reduce the size and complexity of UninitializedObjectChecker.cpp.
+//
+// To read about command line options and documentation about how the checker
+// works, refer to UninitializedObjectChecker.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UninitializedObject.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+
+using namespace clang;
+using namespace clang::ento;
+
+namespace {
+
+/// Represents a pointer or a reference field.
+class LocField final : public FieldNode {
+ /// We'll store whether the pointee or the pointer itself is uninitialited.
+ const bool IsDereferenced;
+
+public:
+ LocField(const FieldRegion *FR, const bool IsDereferenced = true)
+ : FieldNode(FR), IsDereferenced(IsDereferenced) {}
+
+ virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
+ if (IsDereferenced)
+ Out << "uninitialized pointee ";
+ else
+ Out << "uninitialized pointer ";
+ }
+
+ virtual void printPrefix(llvm::raw_ostream &Out) const override {}
+
+ virtual void printNode(llvm::raw_ostream &Out) const override {
+ Out << getVariableName(getDecl());
+ }
+
+ virtual void printSeparator(llvm::raw_ostream &Out) const override {
+ if (getDecl()->getType()->isPointerType())
+ Out << "->";
+ else
+ Out << '.';
+ }
+};
+
+/// Represents a nonloc::LocAsInteger or void* field, that point to objects, but
+/// needs to be casted back to its dynamic type for a correct note message.
+class NeedsCastLocField final : public FieldNode {
+ QualType CastBackType;
+
+public:
+ NeedsCastLocField(const FieldRegion *FR, const QualType &T)
+ : FieldNode(FR), CastBackType(T) {}
+
+ virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
+ Out << "uninitialized pointee ";
+ }
+
+ virtual void printPrefix(llvm::raw_ostream &Out) const override {
+ // If this object is a nonloc::LocAsInteger.
+ if (getDecl()->getType()->isIntegerType())
+ Out << "reinterpret_cast";
+ // If this pointer's dynamic type is different then it's static type.
+ else
+ Out << "static_cast";
+ Out << '<' << CastBackType.getAsString() << ">(";
+ }
+
+ virtual void printNode(llvm::raw_ostream &Out) const override {
+ Out << getVariableName(getDecl()) << ')';
+ }
+
+ virtual void printSeparator(llvm::raw_ostream &Out) const override {
+ Out << "->";
+ }
+};
+
+/// Represents a Loc field that points to itself.
+class CyclicLocField final : public FieldNode {
+
+public:
+ CyclicLocField(const FieldRegion *FR) : FieldNode(FR) {}
+
+ virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
+ Out << "object references itself ";
+ }
+
+ virtual void printPrefix(llvm::raw_ostream &Out) const override {}
+
+ virtual void printNode(llvm::raw_ostream &Out) const override {
+ Out << getVariableName(getDecl());
+ }
+
+ virtual void printSeparator(llvm::raw_ostream &Out) const override {
+ llvm_unreachable("CyclicLocField objects must be the last node of the "
+ "fieldchain!");
+ }
+};
+
+} // end of anonymous namespace
+
+// Utility function declarations.
+
+struct DereferenceInfo {
+ const TypedValueRegion *R;
+ const bool NeedsCastBack;
+ const bool IsCyclic;
+ DereferenceInfo(const TypedValueRegion *R, bool NCB, bool IC)
+ : R(R), NeedsCastBack(NCB), IsCyclic(IC) {}
+};
+
+/// Dereferences \p FR and returns with the pointee's region, and whether it
+/// needs to be casted back to it's location type. If for whatever reason
+/// dereferencing fails, returns with None.
+static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
+ const FieldRegion *FR);
+
+/// Returns whether \p T can be (transitively) dereferenced to a void pointer
+/// type (void*, void**, ...).
+static bool isVoidPointer(QualType T);
+
+//===----------------------------------------------------------------------===//
+// Methods for FindUninitializedFields.
+//===----------------------------------------------------------------------===//
+
+bool FindUninitializedFields::isDereferencableUninit(
+ const FieldRegion *FR, FieldChainInfo LocalChain) {
+
+ SVal V = State->getSVal(FR);
+
+ assert((isDereferencableType(FR->getDecl()->getType()) ||
+ V.getAs<nonloc::LocAsInteger>()) &&
+ "This method only checks dereferenceable objects!");
+
+ if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ if (V.isUndef()) {
+ return addFieldToUninits(
+ LocalChain.add(LocField(FR, /*IsDereferenced*/ false)), FR);
+ }
+
+ if (!Opts.CheckPointeeInitialization) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ // At this point the pointer itself is initialized and points to a valid
+ // location, we'll now check the pointee.
+ llvm::Optional<DereferenceInfo> DerefInfo = dereference(State, FR);
+ if (!DerefInfo) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ if (DerefInfo->IsCyclic)
+ return addFieldToUninits(LocalChain.add(CyclicLocField(FR)), FR);
+
+ const TypedValueRegion *R = DerefInfo->R;
+ const bool NeedsCastBack = DerefInfo->NeedsCastBack;
+
+ QualType DynT = R->getLocationType();
+ QualType PointeeT = DynT->getPointeeType();
+
+ if (PointeeT->isStructureOrClassType()) {
+ if (NeedsCastBack)
+ return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT)));
+ return isNonUnionUninit(R, LocalChain.add(LocField(FR)));
+ }
+
+ if (PointeeT->isUnionType()) {
+ if (isUnionUninit(R)) {
+ if (NeedsCastBack)
+ return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)),
+ R);
+ return addFieldToUninits(LocalChain.add(LocField(FR)), R);
+ } else {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+ }
+
+ if (PointeeT->isArrayType()) {
+ IsAnyFieldInitialized = true;
+ return false;
+ }
+
+ assert((isPrimitiveType(PointeeT) || isDereferencableType(PointeeT)) &&
+ "At this point FR must either have a primitive dynamic type, or it "
+ "must be a null, undefined, unknown or concrete pointer!");
+
+ SVal PointeeV = State->getSVal(R);
+
+ if (isPrimitiveUninit(PointeeV)) {
+ if (NeedsCastBack)
+ return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)), R);
+ return addFieldToUninits(LocalChain.add(LocField(FR)), R);
+ }
+
+ IsAnyFieldInitialized = true;
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
+ const FieldRegion *FR) {
+
+ llvm::SmallSet<const TypedValueRegion *, 5> VisitedRegions;
+
+ SVal V = State->getSVal(FR);
+ assert(V.getAsRegion() && "V must have an underlying region!");
+
+ // If the static type of the field is a void pointer, or it is a
+ // nonloc::LocAsInteger, we need to cast it back to the dynamic type before
+ // dereferencing.
+ bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) ||
+ V.getAs<nonloc::LocAsInteger>();
+
+ // The region we'd like to acquire.
+ const auto *R = V.getAsRegion()->getAs<TypedValueRegion>();
+ if (!R)
+ return None;
+
+ VisitedRegions.insert(R);
+
+ // We acquire the dynamic type of R,
+ QualType DynT = R->getLocationType();
+
+ while (const MemRegion *Tmp = State->getSVal(R, DynT).getAsRegion()) {
+
+ R = Tmp->getAs<TypedValueRegion>();
+ if (!R)
+ return None;
+
+ // We found a cyclic pointer, like int *ptr = (int *)&ptr.
+ if (!VisitedRegions.insert(R).second)
+ return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ true};
+
+ DynT = R->getLocationType();
+ // In order to ensure that this loop terminates, we're also checking the
+ // dynamic type of R, since type hierarchy is finite.
+ if (isDereferencableType(DynT->getPointeeType()))
+ break;
+ }
+
+ while (R->getAs<CXXBaseObjectRegion>()) {
+ NeedsCastBack = true;
+
+ if (!isa<TypedValueRegion>(R->getSuperRegion()))
+ break;
+ R = R->getSuperRegion()->getAs<TypedValueRegion>();
+ }
+
+ return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ false};
+}
+
+static bool isVoidPointer(QualType T) {
+ while (!T.isNull()) {
+ if (T->isVoidPointerType())
+ return true;
+ T = T->getPointeeType();
+ }
+ return false;
+}
diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
deleted file mode 100644
index 398228a9d887..000000000000
--- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
+++ /dev/null
@@ -1,688 +0,0 @@
-//===----- UninitializedObjectChecker.cpp ------------------------*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a checker that reports uninitialized fields in objects
-// created after a constructor call.
-//
-// This checker has two options:
-// - "Pedantic" (boolean). If its not set or is set to false, the checker
-// won't emit warnings for objects that don't have at least one initialized
-// field. This may be set with
-//
-// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`.
-//
-// - "NotesAsWarnings" (boolean). If set to true, the checker will emit a
-// warning for each uninitalized field, as opposed to emitting one warning
-// per constructor call, and listing the uninitialized fields that belongs
-// to it in notes. Defaults to false.
-//
-// `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckers.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include <algorithm>
-
-using namespace clang;
-using namespace clang::ento;
-
-namespace {
-
-class UninitializedObjectChecker : public Checker<check::EndFunction> {
- std::unique_ptr<BuiltinBug> BT_uninitField;
-
-public:
- // These fields will be initialized when registering the checker.
- bool IsPedantic;
- bool ShouldConvertNotesToWarnings;
-
- UninitializedObjectChecker()
- : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
- void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
-};
-
-/// Represents a field chain. A field chain is a vector of fields where the
-/// first element of the chain is the object under checking (not stored), and
-/// every other element is a field, and the element that precedes it is the
-/// object that contains it.
-///
-/// Note that this class is immutable, and new fields may only be added through
-/// constructor calls.
-class FieldChainInfo {
- using FieldChain = llvm::ImmutableList<const FieldRegion *>;
-
- FieldChain Chain;
-
- const bool IsDereferenced = false;
-
-public:
- FieldChainInfo() = default;
-
- FieldChainInfo(const FieldChainInfo &Other, const bool IsDereferenced)
- : Chain(Other.Chain), IsDereferenced(IsDereferenced) {}
-
- FieldChainInfo(const FieldChainInfo &Other, const FieldRegion *FR,
- const bool IsDereferenced = false);
-
- bool contains(const FieldRegion *FR) const { return Chain.contains(FR); }
- bool isPointer() const;
-
- /// If this is a fieldchain whose last element is an uninitialized region of a
- /// pointer type, `IsDereferenced` will store whether the pointer itself or
- /// the pointee is uninitialized.
- bool isDereferenced() const;
- const FieldDecl *getEndOfChain() const;
- void print(llvm::raw_ostream &Out) const;
-
-private:
- /// Prints every element except the last to `Out`. Since ImmutableLists store
- /// elements in reverse order, and have no reverse iterators, we use a
- /// recursive function to print the fieldchain correctly. The last element in
- /// the chain is to be printed by `print`.
- static void printTail(llvm::raw_ostream &Out,
- const llvm::ImmutableListImpl<const FieldRegion *> *L);
- friend struct FieldChainInfoComparator;
-};
-
-struct FieldChainInfoComparator {
- bool operator()(const FieldChainInfo &lhs, const FieldChainInfo &rhs) const {
- assert(!lhs.Chain.isEmpty() && !rhs.Chain.isEmpty() &&
- "Attempted to store an empty fieldchain!");
- return *lhs.Chain.begin() < *rhs.Chain.begin();
- }
-};
-
-using UninitFieldSet = std::set<FieldChainInfo, FieldChainInfoComparator>;
-
-/// Searches for and stores uninitialized fields in a non-union object.
-class FindUninitializedFields {
- ProgramStateRef State;
- const TypedValueRegion *const ObjectR;
-
- const bool IsPedantic;
- bool IsAnyFieldInitialized = false;
-
- UninitFieldSet UninitFields;
-
-public:
- FindUninitializedFields(ProgramStateRef State,
- const TypedValueRegion *const R, bool IsPedantic);
- const UninitFieldSet &getUninitFields();
-
-private:
- /// Adds a FieldChainInfo object to UninitFields. Return true if an insertion
- /// took place.
- bool addFieldToUninits(FieldChainInfo LocalChain);
-
- // For the purposes of this checker, we'll regard the object under checking as
- // a directed tree, where
- // * the root is the object under checking
- // * every node is an object that is
- // - a union
- // - a non-union record
- // - a pointer/reference
- // - an array
- // - of a primitive type, which we'll define later in a helper function.
- // * the parent of each node is the object that contains it
- // * every leaf is an array, a primitive object, a nullptr or an undefined
- // pointer.
- //
- // Example:
- //
- // struct A {
- // struct B {
- // int x, y = 0;
- // };
- // B b;
- // int *iptr = new int;
- // B* bptr;
- //
- // A() {}
- // };
- //
- // The directed tree:
- //
- // ->x
- // /
- // ->b--->y
- // /
- // A-->iptr->(int value)
- // \
- // ->bptr
- //
- // From this we'll construct a vector of fieldchains, where each fieldchain
- // represents an uninitialized field. An uninitialized field may be a
- // primitive object, a pointer, a pointee or a union without a single
- // initialized field.
- // In the above example, for the default constructor call we'll end up with
- // these fieldchains:
- //
- // this->b.x
- // this->iptr (pointee uninit)
- // this->bptr (pointer uninit)
- //
- // We'll traverse each node of the above graph with the appropiate one of
- // these methods:
-
- /// This method checks a region of a union object, and returns true if no
- /// field is initialized within the region.
- bool isUnionUninit(const TypedValueRegion *R);
-
- /// This method checks a region of a non-union object, and returns true if
- /// an uninitialized field is found within the region.
- bool isNonUnionUninit(const TypedValueRegion *R, FieldChainInfo LocalChain);
-
- /// This method checks a region of a pointer or reference object, and returns
- /// true if the ptr/ref object itself or any field within the pointee's region
- /// is uninitialized.
- bool isPointerOrReferenceUninit(const FieldRegion *FR,
- FieldChainInfo LocalChain);
-
- /// This method returns true if the value of a primitive object is
- /// uninitialized.
- bool isPrimitiveUninit(const SVal &V);
-
- // Note that we don't have a method for arrays -- the elements of an array are
- // often left uninitialized intentionally even when it is of a C++ record
- // type, so we'll assume that an array is always initialized.
- // TODO: Add a support for nonloc::LocAsInteger.
-};
-
-} // end of anonymous namespace
-
-// Static variable instantionations.
-
-static llvm::ImmutableListFactory<const FieldRegion *> Factory;
-
-// Utility function declarations.
-
-/// Returns the object that was constructed by CtorDecl, or None if that isn't
-/// possible.
-static Optional<nonloc::LazyCompoundVal>
-getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context);
-
-/// Checks whether the constructor under checking is called by another
-/// constructor.
-static bool isCalledByConstructor(const CheckerContext &Context);
-
-/// Returns whether FD can be (transitively) dereferenced to a void pointer type
-/// (void*, void**, ...). The type of the region behind a void pointer isn't
-/// known, and thus FD can not be analyzed.
-static bool isVoidPointer(const FieldDecl *FD);
-
-/// Returns true if T is a primitive type. We defined this type so that for
-/// objects that we'd only like analyze as much as checking whether their
-/// value is undefined or not, such as ints and doubles, can be analyzed with
-/// ease. This also helps ensuring that every special field type is handled
-/// correctly.
-static bool isPrimitiveType(const QualType &T) {
- return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType();
-}
-
-/// Constructs a note message for a given FieldChainInfo object.
-static void printNoteMessage(llvm::raw_ostream &Out,
- const FieldChainInfo &Chain);
-
-/// Returns with Field's name. This is a helper function to get the correct name
-/// even if Field is a captured lambda variable.
-static StringRef getVariableName(const FieldDecl *Field);
-
-//===----------------------------------------------------------------------===//
-// Methods for UninitializedObjectChecker.
-//===----------------------------------------------------------------------===//
-
-void UninitializedObjectChecker::checkEndFunction(
- const ReturnStmt *RS, CheckerContext &Context) const {
-
- const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(
- Context.getLocationContext()->getDecl());
- if (!CtorDecl)
- return;
-
- if (!CtorDecl->isUserProvided())
- return;
-
- if (CtorDecl->getParent()->isUnion())
- return;
-
- // This avoids essentially the same error being reported multiple times.
- if (isCalledByConstructor(Context))
- return;
-
- Optional<nonloc::LazyCompoundVal> Object = getObjectVal(CtorDecl, Context);
- if (!Object)
- return;
-
- FindUninitializedFields F(Context.getState(), Object->getRegion(),
- IsPedantic);
-
- const UninitFieldSet &UninitFields = F.getUninitFields();
-
- if (UninitFields.empty())
- return;
-
- // There are uninitialized fields in the record.
-
- ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState());
- if (!Node)
- return;
-
- PathDiagnosticLocation LocUsedForUniqueing;
- const Stmt *CallSite = Context.getStackFrame()->getCallSite();
- if (CallSite)
- LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
- CallSite, Context.getSourceManager(), Node->getLocationContext());
-
- // For Plist consumers that don't support notes just yet, we'll convert notes
- // to warnings.
- if (ShouldConvertNotesToWarnings) {
- for (const auto &Chain : UninitFields) {
- SmallString<100> WarningBuf;
- llvm::raw_svector_ostream WarningOS(WarningBuf);
-
- printNoteMessage(WarningOS, Chain);
-
- auto Report = llvm::make_unique<BugReport>(
- *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
- Node->getLocationContext()->getDecl());
- Context.emitReport(std::move(Report));
- }
- return;
- }
-
- SmallString<100> WarningBuf;
- llvm::raw_svector_ostream WarningOS(WarningBuf);
- WarningOS << UninitFields.size() << " uninitialized field"
- << (UninitFields.size() == 1 ? "" : "s")
- << " at the end of the constructor call";
-
- auto Report = llvm::make_unique<BugReport>(
- *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
- Node->getLocationContext()->getDecl());
-
- for (const auto &Chain : UninitFields) {
- SmallString<200> NoteBuf;
- llvm::raw_svector_ostream NoteOS(NoteBuf);
-
- printNoteMessage(NoteOS, Chain);
-
- Report->addNote(NoteOS.str(),
- PathDiagnosticLocation::create(Chain.getEndOfChain(),
- Context.getSourceManager()));
- }
- Context.emitReport(std::move(Report));
-}
-
-//===----------------------------------------------------------------------===//
-// Methods for FindUninitializedFields.
-//===----------------------------------------------------------------------===//
-
-FindUninitializedFields::FindUninitializedFields(
- ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic)
- : State(State), ObjectR(R), IsPedantic(IsPedantic) {}
-
-const UninitFieldSet &FindUninitializedFields::getUninitFields() {
- isNonUnionUninit(ObjectR, FieldChainInfo());
-
- if (!IsPedantic && !IsAnyFieldInitialized)
- UninitFields.clear();
-
- return UninitFields;
-}
-
-bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain) {
- if (State->getStateManager().getContext().getSourceManager().isInSystemHeader(
- Chain.getEndOfChain()->getLocation()))
- return false;
-
- return UninitFields.insert(Chain).second;
-}
-
-bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R,
- FieldChainInfo LocalChain) {
- assert(R->getValueType()->isRecordType() &&
- !R->getValueType()->isUnionType() &&
- "This method only checks non-union record objects!");
-
- const RecordDecl *RD =
- R->getValueType()->getAs<RecordType>()->getDecl()->getDefinition();
- assert(RD && "Referred record has no definition");
-
- bool ContainsUninitField = false;
-
- // Are all of this non-union's fields initialized?
- for (const FieldDecl *I : RD->fields()) {
-
- const auto FieldVal =
- State->getLValue(I, loc::MemRegionVal(R)).castAs<loc::MemRegionVal>();
- const auto *FR = FieldVal.getRegionAs<FieldRegion>();
- QualType T = I->getType();
-
- // If LocalChain already contains FR, then we encountered a cyclic
- // reference. In this case, region FR is already under checking at an
- // earlier node in the directed tree.
- if (LocalChain.contains(FR))
- return false;
-
- if (T->isStructureOrClassType()) {
- if (isNonUnionUninit(FR, {LocalChain, FR}))
- ContainsUninitField = true;
- continue;
- }
-
- if (T->isUnionType()) {
- if (isUnionUninit(FR)) {
- if (addFieldToUninits({LocalChain, FR}))
- ContainsUninitField = true;
- } else
- IsAnyFieldInitialized = true;
- continue;
- }
-
- if (T->isArrayType()) {
- IsAnyFieldInitialized = true;
- continue;
- }
-
- if (T->isPointerType() || T->isReferenceType()) {
- if (isPointerOrReferenceUninit(FR, LocalChain))
- ContainsUninitField = true;
- continue;
- }
-
- if (isPrimitiveType(T)) {
- SVal V = State->getSVal(FieldVal);
-
- if (isPrimitiveUninit(V)) {
- if (addFieldToUninits({LocalChain, FR}))
- ContainsUninitField = true;
- }
- continue;
- }
-
- llvm_unreachable("All cases are handled!");
- }
-
- // Checking bases.
- // FIXME: As of now, because of `isCalledByConstructor`, objects whose type
- // is a descendant of another type will emit warnings for uninitalized
- // inherited members.
- // This is not the only way to analyze bases of an object -- if we didn't
- // filter them out, and didn't analyze the bases, this checker would run for
- // each base of the object in order of base initailization and in theory would
- // find every uninitalized field. This approach could also make handling
- // diamond inheritances more easily.
- //
- // This rule (that a descendant type's cunstructor is responsible for
- // initializing inherited data members) is not obvious, and should it should
- // be.
- const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
- if (!CXXRD)
- return ContainsUninitField;
-
- for (const CXXBaseSpecifier &BaseSpec : CXXRD->bases()) {
- const auto *BaseRegion = State->getLValue(BaseSpec, R)
- .castAs<loc::MemRegionVal>()
- .getRegionAs<TypedValueRegion>();
-
- if (isNonUnionUninit(BaseRegion, LocalChain))
- ContainsUninitField = true;
- }
-
- return ContainsUninitField;
-}
-
-bool FindUninitializedFields::isUnionUninit(const TypedValueRegion *R) {
- assert(R->getValueType()->isUnionType() &&
- "This method only checks union objects!");
- // TODO: Implement support for union fields.
- return false;
-}
-
-// Note that pointers/references don't contain fields themselves, so in this
-// function we won't add anything to LocalChain.
-bool FindUninitializedFields::isPointerOrReferenceUninit(
- const FieldRegion *FR, FieldChainInfo LocalChain) {
-
- assert((FR->getDecl()->getType()->isPointerType() ||
- FR->getDecl()->getType()->isReferenceType()) &&
- "This method only checks pointer/reference objects!");
-
- SVal V = State->getSVal(FR);
-
- if (V.isUnknown() || V.isZeroConstant()) {
- IsAnyFieldInitialized = true;
- return false;
- }
-
- if (V.isUndef()) {
- return addFieldToUninits({LocalChain, FR});
- }
-
- const FieldDecl *FD = FR->getDecl();
-
- // TODO: The dynamic type of a void pointer may be retrieved with
- // `getDynamicTypeInfo`.
- if (isVoidPointer(FD)) {
- IsAnyFieldInitialized = true;
- return false;
- }
-
- assert(V.getAs<Loc>() && "V should be Loc at this point!");
-
- // At this point the pointer itself is initialized and points to a valid
- // location, we'll now check the pointee.
- SVal DerefdV = State->getSVal(V.castAs<Loc>());
-
- // TODO: Dereferencing should be done according to the dynamic type.
- while (Optional<Loc> L = DerefdV.getAs<Loc>()) {
- DerefdV = State->getSVal(*L);
- }
-
- // If V is a pointer pointing to a record type.
- if (Optional<nonloc::LazyCompoundVal> RecordV =
- DerefdV.getAs<nonloc::LazyCompoundVal>()) {
-
- const TypedValueRegion *R = RecordV->getRegion();
-
- // We can't reason about symbolic regions, assume its initialized.
- // Note that this also avoids a potential infinite recursion, because
- // constructors for list-like classes are checked without being called, and
- // the Static Analyzer will construct a symbolic region for Node *next; or
- // similar code snippets.
- if (R->getSymbolicBase()) {
- IsAnyFieldInitialized = true;
- return false;
- }
-
- const QualType T = R->getValueType();
-
- if (T->isStructureOrClassType())
- return isNonUnionUninit(R, {LocalChain, FR});
-
- if (T->isUnionType()) {
- if (isUnionUninit(R)) {
- return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true});
- } else {
- IsAnyFieldInitialized = true;
- return false;
- }
- }
-
- if (T->isArrayType()) {
- IsAnyFieldInitialized = true;
- return false;
- }
-
- llvm_unreachable("All cases are handled!");
- }
-
- // TODO: If possible, it should be asserted that the DerefdV at this point is
- // primitive.
-
- if (isPrimitiveUninit(DerefdV))
- return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true});
-
- IsAnyFieldInitialized = true;
- return false;
-}
-
-bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) {
- if (V.isUndef())
- return true;
-
- IsAnyFieldInitialized = true;
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Methods for FieldChainInfo.
-//===----------------------------------------------------------------------===//
-
-FieldChainInfo::FieldChainInfo(const FieldChainInfo &Other,
- const FieldRegion *FR, const bool IsDereferenced)
- : FieldChainInfo(Other, IsDereferenced) {
- assert(!contains(FR) && "Can't add a field that is already a part of the "
- "fieldchain! Is this a cyclic reference?");
- Chain = Factory.add(FR, Other.Chain);
-}
-
-bool FieldChainInfo::isPointer() const {
- assert(!Chain.isEmpty() && "Empty fieldchain!");
- return (*Chain.begin())->getDecl()->getType()->isPointerType();
-}
-
-bool FieldChainInfo::isDereferenced() const {
- assert(isPointer() && "Only pointers may or may not be dereferenced!");
- return IsDereferenced;
-}
-
-const FieldDecl *FieldChainInfo::getEndOfChain() const {
- assert(!Chain.isEmpty() && "Empty fieldchain!");
- return (*Chain.begin())->getDecl();
-}
-
-// TODO: This function constructs an incorrect fieldchain string in the
-// following case:
-//
-// struct Base { int x; };
-// struct D1 : Base {}; struct D2 : Base {};
-//
-// struct MostDerived : D1, D2 {
-// MostDerived() {}
-// }
-//
-// A call to MostDerived::MostDerived() will cause two notes that say
-// "uninitialized field 'this->x'", but we can't refer to 'x' directly,
-// we need an explicit namespace resolution whether the uninit field was
-// 'D1::x' or 'D2::x'.
-void FieldChainInfo::print(llvm::raw_ostream &Out) const {
- if (Chain.isEmpty())
- return;
-
- const llvm::ImmutableListImpl<const FieldRegion *> *L =
- Chain.getInternalPointer();
- printTail(Out, L->getTail());
- Out << getVariableName(L->getHead()->getDecl());
-}
-
-void FieldChainInfo::printTail(
- llvm::raw_ostream &Out,
- const llvm::ImmutableListImpl<const FieldRegion *> *L) {
- if (!L)
- return;
-
- printTail(Out, L->getTail());
- const FieldDecl *Field = L->getHead()->getDecl();
- Out << getVariableName(Field);
- Out << (Field->getType()->isPointerType() ? "->" : ".");
-}
-
-//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static bool isVoidPointer(const FieldDecl *FD) {
- QualType T = FD->getType();
-
- while (!T.isNull()) {
- if (T->isVoidPointerType())
- return true;
- T = T->getPointeeType();
- }
- return false;
-}
-
-static Optional<nonloc::LazyCompoundVal>
-getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context) {
-
- Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl->getParent(),
- Context.getStackFrame());
- // Getting the value for 'this'.
- SVal This = Context.getState()->getSVal(ThisLoc);
-
- // Getting the value for '*this'.
- SVal Object = Context.getState()->getSVal(This.castAs<Loc>());
-
- return Object.getAs<nonloc::LazyCompoundVal>();
-}
-
-// TODO: We should also check that if the constructor was called by another
-// constructor, whether those two are in any relation to one another. In it's
-// current state, this introduces some false negatives.
-static bool isCalledByConstructor(const CheckerContext &Context) {
- const LocationContext *LC = Context.getLocationContext()->getParent();
-
- while (LC) {
- if (isa<CXXConstructorDecl>(LC->getDecl()))
- return true;
-
- LC = LC->getParent();
- }
- return false;
-}
-
-static void printNoteMessage(llvm::raw_ostream &Out,
- const FieldChainInfo &Chain) {
- if (Chain.isPointer()) {
- if (Chain.isDereferenced())
- Out << "uninitialized pointee 'this->";
- else
- Out << "uninitialized pointer 'this->";
- } else
- Out << "uninitialized field 'this->";
- Chain.print(Out);
- Out << "'";
-}
-
-static StringRef getVariableName(const FieldDecl *Field) {
- // If Field is a captured lambda variable, Field->getName() will return with
- // an empty string. We can however acquire it's name from the lambda's
- // captures.
- const auto *CXXParent = dyn_cast<CXXRecordDecl>(Field->getParent());
-
- if (CXXParent && CXXParent->isLambda()) {
- assert(CXXParent->captures_begin());
- auto It = CXXParent->captures_begin() + Field->getFieldIndex();
- return It->getCapturedVar()->getName();
- }
-
- return Field->getName();
-}
-
-void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) {
- auto Chk = Mgr.registerChecker<UninitializedObjectChecker>();
- Chk->IsPedantic = Mgr.getAnalyzerOptions().getBooleanOption(
- "Pedantic", /*DefaultVal*/ false, Chk);
- Chk->ShouldConvertNotesToWarnings = Mgr.getAnalyzerOptions().getBooleanOption(
- "NotesAsWarnings", /*DefaultVal*/ false, Chk);
-}
diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index a6b50dc37740..bab0c12704fa 100644
--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -314,7 +314,7 @@ bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
auto report = llvm::make_unique<BugReport>(*BT_mallocZero, os.str(), N);
report->addRange(arg->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, arg, *report);
+ bugreporter::trackExpressionValue(N, arg, *report);
C.emitReport(std::move(report));
return true;
diff --git a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index dbd12cc9b65a..16b4d5e925ba 100644
--- a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -13,7 +13,7 @@
// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
@@ -150,7 +150,7 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
if (const Stmt *S = getUnreachableStmt(CB)) {
// In macros, 'do {...} while (0)' is often used. Don't warn about the
// condition 0 when it is unreachable.
- if (S->getLocStart().isMacroID())
+ if (S->getBeginLoc().isMacroID())
if (const auto *I = dyn_cast<IntegerLiteral>(S))
if (I->getValue() == 0ULL)
if (const Stmt *Parent = PM->getParent(S))
@@ -232,7 +232,7 @@ bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
if (!pred)
return false;
- // Get the predecessor block's terminator conditon
+ // Get the predecessor block's terminator condition
const Stmt *cond = pred->getTerminatorCondition();
//assert(cond && "CFGBlock's predecessor has a terminator condition");
diff --git a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index 2584f2011819..e458e0554ee2 100644
--- a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -14,7 +14,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/CharUnits.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -74,7 +74,7 @@ void VLASizeChecker::reportBug(
auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
report->addVisitor(std::move(Visitor));
report->addRange(SizeE->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, SizeE, *report);
+ bugreporter::trackExpressionValue(N, SizeE, *report);
C.emitReport(std::move(report));
}
diff --git a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
index bd657340fcfb..748b226b7a1e 100644
--- a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -90,7 +90,6 @@ private:
return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(), false);
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -376,10 +375,10 @@ void ValistChecker::checkVAListEndCall(const CallEvent &Call,
}
std::shared_ptr<PathDiagnosticPiece> ValistChecker::ValistBugVisitor::VisitNode(
- const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+ const ExplodedNode *N, BugReporterContext &BRC,
BugReport &) {
ProgramStateRef State = N->getState();
- ProgramStateRef StatePrev = PrevN->getState();
+ ProgramStateRef StatePrev = N->getFirstPred()->getState();
const Stmt *S = PathDiagnosticLocation::getStmt(N);
if (!S)
diff --git a/lib/StaticAnalyzer/Checkers/VforkChecker.cpp b/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
index 75aefc0e8384..3ee9f1a07fa2 100644
--- a/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
@@ -25,7 +25,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index 5b602468cdd4..567063197405 100644
--- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/DeclCXX.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -72,7 +72,6 @@ private:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
};
@@ -84,9 +83,8 @@ REGISTER_MAP_WITH_PROGRAMSTATE(CtorDtorMap, const MemRegion *, ObjectState)
std::shared_ptr<PathDiagnosticPiece>
VirtualCallChecker::VirtualBugVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR) {
+ BugReport &) {
// We need the last ctor/dtor which call the virtual function.
// The visitor walks the ExplodedGraph backwards.
if (Found)
@@ -282,5 +280,6 @@ void ento::registerVirtualCallChecker(CheckerManager &mgr) {
VirtualCallChecker *checker = mgr.registerChecker<VirtualCallChecker>();
checker->IsPureOnly =
- mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false, checker);
+ mgr.getAnalyzerOptions().getCheckerBooleanOption("PureOnly", false,
+ checker);
}
diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index dc0d3ec8493a..7fb1c09ca049 100644
--- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -14,28 +14,33 @@ using namespace ento;
void AnalysisManager::anchor() { }
-AnalysisManager::AnalysisManager(
- ASTContext &ASTCtx, DiagnosticsEngine &diags, const LangOptions &lang,
- const PathDiagnosticConsumers &PDC, StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr,
- AnalyzerOptions &Options, CodeInjector *injector)
- : AnaCtxMgr(ASTCtx, Options.UnoptimizedCFG,
- Options.includeImplicitDtorsInCFG(),
- /*AddInitializers=*/true, Options.includeTemporaryDtorsInCFG(),
- Options.includeLifetimeInCFG(),
- // Adding LoopExit elements to the CFG is a requirement for loop
- // unrolling.
- Options.includeLoopExitInCFG() || Options.shouldUnrollLoops(),
- Options.includeScopesInCFG(),
- Options.shouldSynthesizeBodies(),
- Options.shouldConditionalizeStaticInitializers(),
- /*addCXXNewAllocator=*/true,
- Options.includeRichConstructorsInCFG(),
- Options.shouldElideConstructors(),
- injector),
- Ctx(ASTCtx), Diags(diags), LangOpts(lang), PathConsumers(PDC),
- CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
- CheckerMgr(checkerMgr), options(Options) {
+AnalysisManager::AnalysisManager(ASTContext &ASTCtx, DiagnosticsEngine &diags,
+ const PathDiagnosticConsumers &PDC,
+ StoreManagerCreator storemgr,
+ ConstraintManagerCreator constraintmgr,
+ CheckerManager *checkerMgr,
+ AnalyzerOptions &Options,
+ CodeInjector *injector)
+ : AnaCtxMgr(
+ ASTCtx, Options.UnoptimizedCFG,
+ Options.ShouldIncludeImplicitDtorsInCFG,
+ /*AddInitializers=*/true,
+ Options.ShouldIncludeTemporaryDtorsInCFG,
+ Options.ShouldIncludeLifetimeInCFG,
+ // Adding LoopExit elements to the CFG is a requirement for loop
+ // unrolling.
+ Options.ShouldIncludeLoopExitInCFG ||
+ Options.ShouldUnrollLoops,
+ Options.ShouldIncludeScopesInCFG,
+ Options.ShouldSynthesizeBodies,
+ Options.ShouldConditionalizeStaticInitializers,
+ /*addCXXNewAllocator=*/true,
+ Options.ShouldIncludeRichConstructorsInCFG,
+ Options.ShouldElideConstructors, injector),
+ Ctx(ASTCtx), Diags(diags), LangOpts(ASTCtx.getLangOpts()),
+ PathConsumers(PDC), CreateStoreMgr(storemgr),
+ CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),
+ options(Options) {
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
}
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 9b2dc32e0600..0588c2bd3d35 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -34,7 +34,7 @@ std::vector<StringRef>
AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
static const StringRef StaticAnalyzerChecks[] = {
#define GET_CHECKERS
-#define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN) \
+#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
FULLNAME,
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef CHECKER
@@ -49,114 +49,71 @@ AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
return Result;
}
-AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
- if (UserMode == UMK_NotSet) {
- StringRef ModeStr =
- Config.insert(std::make_pair("mode", "deep")).first->second;
- UserMode = llvm::StringSwitch<UserModeKind>(ModeStr)
- .Case("shallow", UMK_Shallow)
- .Case("deep", UMK_Deep)
- .Default(UMK_NotSet);
- assert(UserMode != UMK_NotSet && "User mode is invalid.");
- }
- return UserMode;
-}
-
-AnalyzerOptions::ExplorationStrategyKind
-AnalyzerOptions::getExplorationStrategy() {
- if (ExplorationStrategy == ExplorationStrategyKind::NotSet) {
- StringRef StratStr =
- Config
- .insert(std::make_pair("exploration_strategy", "unexplored_first_queue"))
- .first->second;
- ExplorationStrategy =
- llvm::StringSwitch<ExplorationStrategyKind>(StratStr)
- .Case("dfs", ExplorationStrategyKind::DFS)
- .Case("bfs", ExplorationStrategyKind::BFS)
- .Case("unexplored_first",
- ExplorationStrategyKind::UnexploredFirst)
- .Case("unexplored_first_queue",
- ExplorationStrategyKind::UnexploredFirstQueue)
- .Case("bfs_block_dfs_contents",
- ExplorationStrategyKind::BFSBlockDFSContents)
- .Default(ExplorationStrategyKind::NotSet);
- assert(ExplorationStrategy != ExplorationStrategyKind::NotSet &&
- "User mode is invalid.");
- }
- return ExplorationStrategy;
-}
-
-IPAKind AnalyzerOptions::getIPAMode() {
- if (IPAMode == IPAK_NotSet) {
- // Use the User Mode to set the default IPA value.
- // Note, we have to add the string to the Config map for the ConfigDumper
- // checker to function properly.
- const char *DefaultIPA = nullptr;
- UserModeKind HighLevelMode = getUserMode();
- if (HighLevelMode == UMK_Shallow)
- DefaultIPA = "inlining";
- else if (HighLevelMode == UMK_Deep)
- DefaultIPA = "dynamic-bifurcate";
- assert(DefaultIPA);
-
- // Lookup the ipa configuration option, use the default from User Mode.
- StringRef ModeStr =
- Config.insert(std::make_pair("ipa", DefaultIPA)).first->second;
- IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr)
- .Case("none", IPAK_None)
- .Case("basic-inlining", IPAK_BasicInlining)
- .Case("inlining", IPAK_Inlining)
- .Case("dynamic", IPAK_DynamicDispatch)
- .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
- .Default(IPAK_NotSet);
- assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid.");
-
- // Set the member variable.
- IPAMode = IPAConfig;
- }
-
- return IPAMode;
+ExplorationStrategyKind
+AnalyzerOptions::getExplorationStrategy() const {
+ auto K =
+ llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
+ ExplorationStrategy)
+ .Case("dfs", ExplorationStrategyKind::DFS)
+ .Case("bfs", ExplorationStrategyKind::BFS)
+ .Case("unexplored_first",
+ ExplorationStrategyKind::UnexploredFirst)
+ .Case("unexplored_first_queue",
+ ExplorationStrategyKind::UnexploredFirstQueue)
+ .Case("unexplored_first_location_queue",
+ ExplorationStrategyKind::UnexploredFirstLocationQueue)
+ .Case("bfs_block_dfs_contents",
+ ExplorationStrategyKind::BFSBlockDFSContents)
+ .Default(None);
+ assert(K.hasValue() && "User mode is invalid.");
+ return K.getValue();
+}
+
+IPAKind AnalyzerOptions::getIPAMode() const {
+ auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
+ .Case("none", IPAK_None)
+ .Case("basic-inlining", IPAK_BasicInlining)
+ .Case("inlining", IPAK_Inlining)
+ .Case("dynamic", IPAK_DynamicDispatch)
+ .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
+ .Default(None);
+ assert(K.hasValue() && "IPA Mode is invalid.");
+
+ return K.getValue();
}
bool
-AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) {
+AnalyzerOptions::mayInlineCXXMemberFunction(
+ CXXInlineableMemberKind Param) const {
if (getIPAMode() < IPAK_Inlining)
return false;
- if (!CXXMemberInliningMode) {
- static const char *ModeKey = "c++-inlining";
-
- StringRef ModeStr =
- Config.insert(std::make_pair(ModeKey, "destructors")).first->second;
+ auto K =
+ llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
+ CXXMemberInliningMode)
+ .Case("constructors", CIMK_Constructors)
+ .Case("destructors", CIMK_Destructors)
+ .Case("methods", CIMK_MemberFunctions)
+ .Case("none", CIMK_None)
+ .Default(None);
- CXXInlineableMemberKind &MutableMode =
- const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode);
-
- MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr)
- .Case("constructors", CIMK_Constructors)
- .Case("destructors", CIMK_Destructors)
- .Case("none", CIMK_None)
- .Case("methods", CIMK_MemberFunctions)
- .Default(CXXInlineableMemberKind());
-
- if (!MutableMode) {
- // FIXME: We should emit a warning here about an unknown inlining kind,
- // but the AnalyzerOptions doesn't have access to a diagnostic engine.
- MutableMode = CIMK_None;
- }
- }
+ assert(K.hasValue() && "Invalid c++ member function inlining mode.");
- return CXXMemberInliningMode >= K;
+ return *K >= Param;
}
-static StringRef toString(bool b) { return b ? "true" : "false"; }
-
-StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
- StringRef OptionName,
- StringRef Default,
- bool SearchInParents) {
+StringRef AnalyzerOptions::getCheckerStringOption(StringRef OptionName,
+ StringRef DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) const {
+ assert(C);
// Search for a package option if the option for the checker is not specified
// and search in parents is enabled.
+ StringRef CheckerName = C->getTagDescription();
+
+ assert(!CheckerName.empty() &&
+ "Empty checker name! Make sure the checker object (including it's "
+ "bases!) if fully initialized before calling this function!");
ConfigTable::const_iterator E = Config.end();
do {
ConfigTable::const_iterator I =
@@ -165,331 +122,35 @@ StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
return StringRef(I->getValue());
size_t Pos = CheckerName.rfind('.');
if (Pos == StringRef::npos)
- return Default;
+ return DefaultVal;
CheckerName = CheckerName.substr(0, Pos);
} while (!CheckerName.empty() && SearchInParents);
- return Default;
+ return DefaultVal;
}
-bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
- const CheckerBase *C,
- bool SearchInParents) {
+bool AnalyzerOptions::getCheckerBooleanOption(StringRef Name, bool DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) const {
// FIXME: We should emit a warning here if the value is something other than
// "true", "false", or the empty string (meaning the default value),
// but the AnalyzerOptions doesn't have access to a diagnostic engine.
- StringRef Default = toString(DefaultVal);
- StringRef V =
- C ? getCheckerOption(C->getTagDescription(), Name, Default,
- SearchInParents)
- : StringRef(Config.insert(std::make_pair(Name, Default)).first->second);
- return llvm::StringSwitch<bool>(V)
+ assert(C);
+ return llvm::StringSwitch<bool>(
+ getCheckerStringOption(Name, DefaultVal ? "true" : "false", C,
+ SearchInParents))
.Case("true", true)
.Case("false", false)
.Default(DefaultVal);
}
-bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
- bool DefaultVal, const CheckerBase *C,
- bool SearchInParents) {
- if (!V.hasValue())
- V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
- return V.getValue();
-}
-
-bool AnalyzerOptions::includeTemporaryDtorsInCFG() {
- return getBooleanOption(IncludeTemporaryDtorsInCFG,
- "cfg-temporary-dtors",
- /* Default = */ true);
-}
-
-bool AnalyzerOptions::includeImplicitDtorsInCFG() {
- return getBooleanOption(IncludeImplicitDtorsInCFG,
- "cfg-implicit-dtors",
- /* Default = */ true);
-}
-
-bool AnalyzerOptions::includeLifetimeInCFG() {
- return getBooleanOption(IncludeLifetimeInCFG, "cfg-lifetime",
- /* Default = */ false);
-}
-
-bool AnalyzerOptions::includeLoopExitInCFG() {
- return getBooleanOption(IncludeLoopExitInCFG, "cfg-loopexit",
- /* Default = */ false);
-}
-
-bool AnalyzerOptions::includeRichConstructorsInCFG() {
- return getBooleanOption(IncludeRichConstructorsInCFG,
- "cfg-rich-constructors",
- /* Default = */ true);
-}
-
-bool AnalyzerOptions::includeScopesInCFG() {
- return getBooleanOption(IncludeScopesInCFG,
- "cfg-scopes",
- /* Default = */ false);
-}
-
-bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
- return getBooleanOption(InlineCXXStandardLibrary,
- "c++-stdlib-inlining",
- /*Default=*/true);
-}
-
-bool AnalyzerOptions::mayInlineTemplateFunctions() {
- return getBooleanOption(InlineTemplateFunctions,
- "c++-template-inlining",
- /*Default=*/true);
-}
-
-bool AnalyzerOptions::mayInlineCXXAllocator() {
- return getBooleanOption(InlineCXXAllocator,
- "c++-allocator-inlining",
- /*Default=*/true);
-}
-
-bool AnalyzerOptions::mayInlineCXXContainerMethods() {
- return getBooleanOption(InlineCXXContainerMethods,
- "c++-container-inlining",
- /*Default=*/false);
-}
-
-bool AnalyzerOptions::mayInlineCXXSharedPtrDtor() {
- return getBooleanOption(InlineCXXSharedPtrDtor,
- "c++-shared_ptr-inlining",
- /*Default=*/false);
-}
-
-bool AnalyzerOptions::mayInlineCXXTemporaryDtors() {
- return getBooleanOption(InlineCXXTemporaryDtors,
- "c++-temp-dtor-inlining",
- /*Default=*/true);
-}
-
-bool AnalyzerOptions::mayInlineObjCMethod() {
- return getBooleanOption(ObjCInliningMode,
- "objc-inlining",
- /* Default = */ true);
-}
-
-bool AnalyzerOptions::shouldSuppressNullReturnPaths() {
- return getBooleanOption(SuppressNullReturnPaths,
- "suppress-null-return-paths",
- /* Default = */ true);
-}
-
-bool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() {
- return getBooleanOption(AvoidSuppressingNullArgumentPaths,
- "avoid-suppressing-null-argument-paths",
- /* Default = */ false);
-}
-
-bool AnalyzerOptions::shouldSuppressInlinedDefensiveChecks() {
- return getBooleanOption(SuppressInlinedDefensiveChecks,
- "suppress-inlined-defensive-checks",
- /* Default = */ true);
-}
-
-bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() {
- return getBooleanOption(SuppressFromCXXStandardLibrary,
- "suppress-c++-stdlib",
- /* Default = */ true);
-}
-
-bool AnalyzerOptions::shouldCrosscheckWithZ3() {
- return getBooleanOption(CrosscheckWithZ3,
- "crosscheck-with-z3",
- /* Default = */ false);
-}
-
-bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() {
- return getBooleanOption(ReportIssuesInMainSourceFile,
- "report-in-main-source-file",
- /* Default = */ false);
-}
-
-
-bool AnalyzerOptions::shouldWriteStableReportFilename() {
- return getBooleanOption(StableReportFilename,
- "stable-report-filename",
- /* Default = */ false);
-}
-
-bool AnalyzerOptions::shouldSerializeStats() {
- return getBooleanOption(SerializeStats,
- "serialize-stats",
- /* Default = */ false);
-}
-
-bool AnalyzerOptions::shouldElideConstructors() {
- return getBooleanOption(ElideConstructors,
- "elide-constructors",
- /* Default = */ true);
-}
-
-int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
+int AnalyzerOptions::getCheckerIntegerOption(StringRef Name, int DefaultVal,
const CheckerBase *C,
- bool SearchInParents) {
- SmallString<10> StrBuf;
- llvm::raw_svector_ostream OS(StrBuf);
- OS << DefaultVal;
-
- StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
- SearchInParents)
- : StringRef(Config.insert(std::make_pair(Name, OS.str()))
- .first->second);
-
- int Res = DefaultVal;
- bool b = V.getAsInteger(10, Res);
- assert(!b && "analyzer-config option should be numeric");
- (void)b;
- return Res;
-}
-
-StringRef AnalyzerOptions::getOptionAsString(StringRef Name,
- StringRef DefaultVal,
- const CheckerBase *C,
- bool SearchInParents) {
- return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
- SearchInParents)
- : StringRef(
- Config.insert(std::make_pair(Name, DefaultVal)).first->second);
-}
-
-unsigned AnalyzerOptions::getAlwaysInlineSize() {
- if (!AlwaysInlineSize.hasValue())
- AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
- return AlwaysInlineSize.getValue();
-}
-
-unsigned AnalyzerOptions::getMaxInlinableSize() {
- if (!MaxInlinableSize.hasValue()) {
- int DefaultValue = 0;
- UserModeKind HighLevelMode = getUserMode();
- switch (HighLevelMode) {
- default:
- llvm_unreachable("Invalid mode.");
- case UMK_Shallow:
- DefaultValue = 4;
- break;
- case UMK_Deep:
- DefaultValue = 100;
- break;
- }
-
- MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
- }
- return MaxInlinableSize.getValue();
-}
-
-unsigned AnalyzerOptions::getGraphTrimInterval() {
- if (!GraphTrimInterval.hasValue())
- GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
- return GraphTrimInterval.getValue();
-}
-
-unsigned AnalyzerOptions::getMaxSymbolComplexity() {
- if (!MaxSymbolComplexity.hasValue())
- MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 35);
- return MaxSymbolComplexity.getValue();
-}
-
-unsigned AnalyzerOptions::getMaxTimesInlineLarge() {
- if (!MaxTimesInlineLarge.hasValue())
- MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
- return MaxTimesInlineLarge.getValue();
-}
-
-unsigned AnalyzerOptions::getMinCFGSizeTreatFunctionsAsLarge() {
- if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
- MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
- "min-cfg-size-treat-functions-as-large", 14);
- return MinCFGSizeTreatFunctionsAsLarge.getValue();
-}
-
-unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() {
- if (!MaxNodesPerTopLevelFunction.hasValue()) {
- int DefaultValue = 0;
- UserModeKind HighLevelMode = getUserMode();
- switch (HighLevelMode) {
- default:
- llvm_unreachable("Invalid mode.");
- case UMK_Shallow:
- DefaultValue = 75000;
- break;
- case UMK_Deep:
- DefaultValue = 225000;
- break;
- }
- MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
- }
- return MaxNodesPerTopLevelFunction.getValue();
-}
-
-bool AnalyzerOptions::shouldSynthesizeBodies() {
- return getBooleanOption("faux-bodies", true);
-}
-
-bool AnalyzerOptions::shouldPrunePaths() {
- return getBooleanOption("prune-paths", true);
-}
-
-bool AnalyzerOptions::shouldConditionalizeStaticInitializers() {
- return getBooleanOption("cfg-conditional-static-initializers", true);
-}
-
-bool AnalyzerOptions::shouldInlineLambdas() {
- if (!InlineLambdas.hasValue())
- InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
- return InlineLambdas.getValue();
-}
-
-bool AnalyzerOptions::shouldWidenLoops() {
- if (!WidenLoops.hasValue())
- WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
- return WidenLoops.getValue();
-}
-
-bool AnalyzerOptions::shouldUnrollLoops() {
- if (!UnrollLoops.hasValue())
- UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
- return UnrollLoops.getValue();
-}
-
-bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
- if (!DisplayNotesAsEvents.hasValue())
- DisplayNotesAsEvents =
- getBooleanOption("notes-as-events", /*Default=*/false);
- return DisplayNotesAsEvents.getValue();
-}
-
-bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() {
- if (!AggressiveBinaryOperationSimplification.hasValue())
- AggressiveBinaryOperationSimplification =
- getBooleanOption("aggressive-binary-operation-simplification",
- /*Default=*/false);
- return AggressiveBinaryOperationSimplification.getValue();
-}
-
-StringRef AnalyzerOptions::getCTUDir() {
- if (!CTUDir.hasValue()) {
- CTUDir = getOptionAsString("ctu-dir", "");
- if (!llvm::sys::fs::is_directory(*CTUDir))
- CTUDir = "";
- }
- return CTUDir.getValue();
-}
-
-bool AnalyzerOptions::naiveCTUEnabled() {
- if (!NaiveCTU.hasValue()) {
- NaiveCTU = getBooleanOption("experimental-enable-naive-ctu-analysis",
- /*Default=*/false);
- }
- return NaiveCTU.getValue();
-}
-
-StringRef AnalyzerOptions::getCTUIndexName() {
- if (!CTUIndexName.hasValue())
- CTUIndexName = getOptionAsString("ctu-index-name", "externalFnMap.txt");
- return CTUIndexName.getValue();
+ bool SearchInParents) const {
+ int Ret = DefaultVal;
+ bool HasFailed = getCheckerStringOption(Name, std::to_string(DefaultVal), C,
+ SearchInParents)
+ .getAsInteger(10, Ret);
+ assert(!HasFailed && "analyzer-config option should be numeric");
+ (void)HasFailed;
+ return Ret;
}
diff --git a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index db4c1432ccc3..d8ed6942de81 100644
--- a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -207,7 +207,7 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1, const llvm::APSInt& V2) {
switch (Op) {
default:
- assert(false && "Invalid Opcode.");
+ llvm_unreachable("Invalid Opcode.");
case BO_Mul:
return &getValue( V1 * V2 );
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index f990eb6a058d..fd7f53210490 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -546,7 +546,8 @@ static void updateStackPiecesWithMessage(PathDiagnosticPiece &P,
}
}
-static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
+static void CompactMacroExpandedPieces(PathPieces &path,
+ const SourceManager& SM);
std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForSwitchOP(
@@ -819,7 +820,7 @@ void generateMinimalDiagForBlockEdge(const ExplodedNode *N, BlockEdge BE,
// and values by tracing interesting calculations backwards through evaluated
// expressions along a path. This is probably overly complicated, but the idea
// is that if an expression computed an "interesting" value, the child
-// expressions are are also likely to be "interesting" as well (which then
+// expressions are also likely to be "interesting" as well (which then
// propagates to the values they in turn compute). This reverse propagation
// is needed to track interesting correlations across function call boundaries,
// where formal arguments bind to actual arguments, etc. This is also needed
@@ -841,7 +842,7 @@ static void reversePropagateIntererstingSymbols(BugReport &R,
default:
if (!isa<CastExpr>(Ex))
break;
- // Fall through.
+ LLVM_FALLTHROUGH;
case Stmt::BinaryOperatorClass:
case Stmt::UnaryOperatorClass: {
for (const Stmt *SubStmt : Ex->children()) {
@@ -861,8 +862,7 @@ static void reversePropagateIntererstingSymbols(BugReport &R,
static void reversePropagateInterestingSymbols(BugReport &R,
InterestingExprs &IE,
const ProgramState *State,
- const LocationContext *CalleeCtx,
- const LocationContext *CallerCtx)
+ const LocationContext *CalleeCtx)
{
// FIXME: Handle non-CallExpr-based CallEvents.
const StackFrameContext *Callee = CalleeCtx->getStackFrame();
@@ -967,8 +967,7 @@ static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
/// Adds a sanitized control-flow diagnostic edge to a path.
static void addEdgeToPath(PathPieces &path,
PathDiagnosticLocation &PrevLoc,
- PathDiagnosticLocation NewLoc,
- const LocationContext *LC) {
+ PathDiagnosticLocation NewLoc) {
if (!NewLoc.isValid())
return;
@@ -1043,7 +1042,7 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N,
// not from declaration.
if (D->hasBody())
addEdgeToPath(PD.getActivePath(), PrevLoc,
- PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
+ PathDiagnosticLocation::createBegin(D, SM));
}
// Did we visit an entire call?
@@ -1108,7 +1107,7 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N,
// We are descending into a call (backwards). Construct
// a new call piece to contain the path pieces for that call.
- auto C = PathDiagnosticCallPiece::construct(N, *CE, SM);
+ auto C = PathDiagnosticCallPiece::construct(*CE, SM);
// Record the mapping from call piece to LocationContext.
LCM[&C->path] = CE->getCalleeContext();
@@ -1121,7 +1120,7 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N,
N->getLocationContext());
}
// Add the edge to the return site.
- addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC);
+ addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn);
PrevLoc.invalidate();
}
@@ -1151,7 +1150,7 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N,
if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
PathDiagnosticLocation L =
PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC);
- addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
+ addEdgeToPath(PD.getActivePath(), PrevLoc, L);
}
} else if (auto BE = P.getAs<BlockEdge>()) {
@@ -1168,8 +1167,7 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N,
const LocationContext *CalleeCtx = PDB.LC;
if (CallerCtx != CalleeCtx && AddPathEdges) {
reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
- N->getState().get(),
- CalleeCtx, CallerCtx);
+ N->getState().get(), CalleeCtx);
}
}
@@ -1194,13 +1192,12 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N,
"of the loop");
p->setPrunable(true);
- addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
+ addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation());
PD.getActivePath().push_front(std::move(p));
if (const auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
addEdgeToPath(PD.getActivePath(), PrevLoc,
- PathDiagnosticLocation::createEndBrace(CS, SM),
- PDB.LC);
+ PathDiagnosticLocation::createEndBrace(CS, SM));
}
}
@@ -1236,13 +1233,13 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N,
auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
PE->setPrunable(true);
addEdgeToPath(PD.getActivePath(), PrevLoc,
- PE->getLocation(), PDB.LC);
+ PE->getLocation());
PD.getActivePath().push_front(std::move(PE));
}
} else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
isa<GotoStmt>(Term)) {
PathDiagnosticLocation L(Term, SM, PDB.LC);
- addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
+ addEdgeToPath(PD.getActivePath(), PrevLoc, L);
}
}
}
@@ -1269,7 +1266,7 @@ static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
if (!S)
break;
- if (isa<ExprWithCleanups>(S) ||
+ if (isa<FullExpr>(S) ||
isa<CXXBindTemporaryExpr>(S) ||
isa<SubstNonTypeTemplateParmExpr>(S))
continue;
@@ -1540,8 +1537,7 @@ static Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
/// - if there is an inlined call between the edges instead of a single event.
/// - if the whole statement is large enough that having subexpression arrows
/// might be helpful.
-static void removeContextCycles(PathPieces &Path, SourceManager &SM,
- ParentMap &PM) {
+static void removeContextCycles(PathPieces &Path, SourceManager &SM) {
for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
// Pattern match the current piece and its successor.
const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
@@ -1632,8 +1628,8 @@ static void removePunyEdges(PathPieces &path, SourceManager &SM,
if (isConditionForTerminator(end, endParent))
continue;
- SourceLocation FirstLoc = start->getLocStart();
- SourceLocation SecondLoc = end->getLocStart();
+ SourceLocation FirstLoc = start->getBeginLoc();
+ SourceLocation SecondLoc = end->getBeginLoc();
if (!SM.isWrittenInSameFile(FirstLoc, SecondLoc))
continue;
@@ -1844,7 +1840,7 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
// and aesthetically pleasing.
addContextEdges(path, SM, PM, LC);
// Remove "cyclical" edges that include one or more context edges.
- removeContextCycles(path, SM, PM);
+ removeContextCycles(path, SM);
// Hoist edges originating from branch conditions to branches
// for simple branches.
simplifySimpleBranches(path);
@@ -1881,6 +1877,22 @@ static void dropFunctionEntryEdge(PathPieces &Path, LocationContextMap &LCM,
using VisitorsDiagnosticsTy = llvm::DenseMap<const ExplodedNode *,
std::vector<std::shared_ptr<PathDiagnosticPiece>>>;
+/// Populate executes lines with lines containing at least one diagnostics.
+static void updateExecutedLinesWithDiagnosticPieces(
+ PathDiagnostic &PD) {
+
+ PathPieces path = PD.path.flatten(/*ShouldFlattenMacros=*/true);
+ FilesToLineNumsMap &ExecutedLines = PD.getExecutedLines();
+
+ for (const auto &P : path) {
+ FullSourceLoc Loc = P->getLocation().asLocation().getExpansionLoc();
+ FileID FID = Loc.getFileID();
+ unsigned LineNo = Loc.getLineNumber();
+ assert(FID.isValid());
+ ExecutedLines[FID].insert(LineNo);
+ }
+}
+
/// This function is responsible for generating diagnostic pieces that are
/// *not* provided by bug report visitors.
/// These diagnostics may differ depending on the consumer's settings,
@@ -1946,8 +1958,7 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
continue;
if (AddPathEdges)
- addEdgeToPath(PD->getActivePath(), PrevLoc, Note->getLocation(),
- PDB.LC);
+ addEdgeToPath(PD->getActivePath(), PrevLoc, Note->getLocation());
updateStackPiecesWithMessage(*Note, CallStack);
PD->getActivePath().push_front(Note);
}
@@ -1959,15 +1970,13 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
const StackFrameContext *CalleeLC = PDB.LC->getStackFrame();
const Decl *D = CalleeLC->getDecl();
addEdgeToPath(PD->getActivePath(), PrevLoc,
- PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
+ PathDiagnosticLocation::createBegin(D, SM));
}
- if (!AddPathEdges && GenerateDiagnostics)
- CompactPathDiagnostic(PD->getMutablePieces(), SM);
// Finally, prune the diagnostic path of uninteresting stuff.
if (!PD->path.empty()) {
- if (R->shouldPrunePath() && Opts.shouldPrunePaths()) {
+ if (R->shouldPrunePath() && Opts.ShouldPrunePaths) {
bool stillHasNotes =
removeUnneededCalls(PD->getMutablePieces(), R, LCM);
assert(stillHasNotes);
@@ -1997,6 +2006,10 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
removeRedundantMsgs(PD->getMutablePieces());
removeEdgesToDefaultInitializers(PD->getMutablePieces());
}
+
+ if (GenerateDiagnostics && Opts.ShouldDisplayMacroExpansions)
+ CompactMacroExpandedPieces(PD->getMutablePieces(), SM);
+
return PD;
}
@@ -2007,8 +2020,6 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
void BugType::anchor() {}
-void BugType::FlushReports(BugReporter &BR) {}
-
void BuiltinBug::anchor() {}
//===----------------------------------------------------------------------===//
@@ -2237,14 +2248,6 @@ void BugReporter::FlushReports() {
if (BugTypes.isEmpty())
return;
- // First flush the warnings for each BugType. This may end up creating new
- // warnings and new BugTypes.
- // FIXME: Only NSErrorChecker needs BugType's FlushReports.
- // Turn NSErrorChecker into a proper checker and remove this.
- SmallVector<const BugType *, 16> bugTypes(BugTypes.begin(), BugTypes.end());
- for (const auto I : bugTypes)
- const_cast<BugType*>(I)->FlushReports(*this);
-
// We need to flush reports in deterministic order to ensure the order
// of the reports is consistent between runs.
for (const auto EQ : EQClassesVector)
@@ -2380,8 +2383,7 @@ TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
}
// Sort the error paths from longest to shortest.
- llvm::sort(ReportNodes.begin(), ReportNodes.end(),
- PriorityCompare<true>(PriorityMap));
+ llvm::sort(ReportNodes, PriorityCompare<true>(PriorityMap));
}
bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
@@ -2437,9 +2439,10 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
return true;
}
-/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
-/// and collapses PathDiagosticPieces that are expanded by macros.
-static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
+/// CompactMacroExpandedPieces - This function postprocesses a PathDiagnostic
+/// object and collapses PathDiagosticPieces that are expanded by macros.
+static void CompactMacroExpandedPieces(PathPieces &path,
+ const SourceManager& SM) {
using MacroStackTy =
std::vector<
std::pair<std::shared_ptr<PathDiagnosticMacroPiece>, SourceLocation>>;
@@ -2455,7 +2458,7 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
// Recursively compact calls.
if (auto *call = dyn_cast<PathDiagnosticCallPiece>(&*piece)) {
- CompactPathDiagnostic(call->path, SM);
+ CompactMacroExpandedPieces(call->path, SM);
}
// Get the location of the PathDiagnosticPiece.
@@ -2569,7 +2572,7 @@ generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode,
}
for (auto &V : visitors) {
- auto P = V->VisitNode(NextNode, Pred, BRC, *R);
+ auto P = V->VisitNode(NextNode, BRC, *R);
if (P)
(*Notes)[NextNode].push_back(std::move(P));
}
@@ -2618,7 +2621,7 @@ std::pair<BugReport*, std::unique_ptr<VisitorsDiagnosticsTy>> findValidReport(
generateVisitorsDiagnostics(R, ErrorNode, BRC);
if (R->isValid()) {
- if (Opts.shouldCrosscheckWithZ3()) {
+ if (Opts.ShouldCrosscheckWithZ3) {
// If crosscheck is enabled, remove all visitors, add the refutation
// visitor and check again
R->clearVisitors();
@@ -2806,16 +2809,15 @@ static bool isInevitablySinking(const ExplodedNode *N) {
DFSWorkList.pop_back();
Visited.insert(Blk);
+ // If at least one path reaches the CFG exit, it means that control is
+ // returned to the caller. For now, say that we are not sure what
+ // happens next. If necessary, this can be improved to analyze
+ // the parent StackFrameContext's call site in a similar manner.
+ if (Blk == &Cfg.getExit())
+ return false;
+
for (const auto &Succ : Blk->succs()) {
if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
- if (SuccBlk == &Cfg.getExit()) {
- // If at least one path reaches the CFG exit, it means that control is
- // returned to the caller. For now, say that we are not sure what
- // happens next. If necessary, this can be improved to analyze
- // the parent StackFrameContext's call site in a similar manner.
- return false;
- }
-
if (!isImmediateSinkBlock(SuccBlk) && !Visited.count(SuccBlk)) {
// If the block has reachable child blocks that aren't no-return,
// add them to the worklist.
@@ -2961,7 +2963,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
}
PathPieces &Pieces = PD->getMutablePieces();
- if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) {
+ if (getAnalyzerOptions().ShouldDisplayNotesAsEvents) {
// For path diagnostic consumers that don't support extra notes,
// we may optionally convert those to path notes.
for (auto I = report->getNotes().rbegin(),
@@ -2985,6 +2987,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
for (const auto &i : Meta)
PD->addMeta(i);
+ updateExecutedLinesWithDiagnosticPieces(*PD);
Consumer->HandlePathDiagnostic(std::move(PD));
}
}
@@ -2993,7 +2996,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
/// into \p ExecutedLines.
static void populateExecutedLinesWithFunctionSignature(
const Decl *Signature, SourceManager &SM,
- std::unique_ptr<FilesToLineNumsMap> &ExecutedLines) {
+ FilesToLineNumsMap &ExecutedLines) {
SourceRange SignatureSourceRange;
const Stmt* Body = Signature->getBody();
if (const auto FD = dyn_cast<FunctionDecl>(Signature)) {
@@ -3006,22 +3009,26 @@ static void populateExecutedLinesWithFunctionSignature(
SourceLocation Start = SignatureSourceRange.getBegin();
SourceLocation End = Body ? Body->getSourceRange().getBegin()
: SignatureSourceRange.getEnd();
+ if (!Start.isValid() || !End.isValid())
+ return;
unsigned StartLine = SM.getExpansionLineNumber(Start);
unsigned EndLine = SM.getExpansionLineNumber(End);
FileID FID = SM.getFileID(SM.getExpansionLoc(Start));
for (unsigned Line = StartLine; Line <= EndLine; Line++)
- ExecutedLines->operator[](FID.getHashValue()).insert(Line);
+ ExecutedLines[FID].insert(Line);
}
static void populateExecutedLinesWithStmt(
const Stmt *S, SourceManager &SM,
- std::unique_ptr<FilesToLineNumsMap> &ExecutedLines) {
+ FilesToLineNumsMap &ExecutedLines) {
SourceLocation Loc = S->getSourceRange().getBegin();
+ if (!Loc.isValid())
+ return;
SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
FileID FID = SM.getFileID(ExpansionLoc);
unsigned LineNo = SM.getExpansionLineNumber(ExpansionLoc);
- ExecutedLines->operator[](FID.getHashValue()).insert(LineNo);
+ ExecutedLines[FID].insert(LineNo);
}
/// \return all executed lines including function signatures on the path
@@ -3034,13 +3041,13 @@ findExecutedLines(SourceManager &SM, const ExplodedNode *N) {
if (N->getFirstPred() == nullptr) {
// First node: show signature of the entrance point.
const Decl *D = N->getLocationContext()->getDecl();
- populateExecutedLinesWithFunctionSignature(D, SM, ExecutedLines);
+ populateExecutedLinesWithFunctionSignature(D, SM, *ExecutedLines);
} else if (auto CE = N->getLocationAs<CallEnter>()) {
// Inlined function: show signature.
const Decl* D = CE->getCalleeContext()->getDecl();
- populateExecutedLinesWithFunctionSignature(D, SM, ExecutedLines);
+ populateExecutedLinesWithFunctionSignature(D, SM, *ExecutedLines);
} else if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) {
- populateExecutedLinesWithStmt(S, SM, ExecutedLines);
+ populateExecutedLinesWithStmt(S, SM, *ExecutedLines);
// Show extra context for some parent kinds.
const Stmt *P = N->getParentMap().getParent(S);
@@ -3049,12 +3056,12 @@ findExecutedLines(SourceManager &SM, const ExplodedNode *N) {
// return statement is generated, but we do want to show the whole
// return.
if (const auto *RS = dyn_cast_or_null<ReturnStmt>(P)) {
- populateExecutedLinesWithStmt(RS, SM, ExecutedLines);
+ populateExecutedLinesWithStmt(RS, SM, *ExecutedLines);
P = N->getParentMap().getParent(RS);
}
if (P && (isa<SwitchCase>(P) || isa<LabelStmt>(P)))
- populateExecutedLinesWithStmt(P, SM, ExecutedLines);
+ populateExecutedLinesWithStmt(P, SM, *ExecutedLines);
}
N = N->getFirstPred();
@@ -3093,7 +3100,7 @@ BugReporter::generateDiagnosticForConsumerMap(
// report location to the last piece in the main source file.
AnalyzerOptions &Opts = getAnalyzerOptions();
for (auto const &P : *Out)
- if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
+ if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll)
P.second->resetDiagnosticLocationToMainFile();
return Out;
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index d4d33c1746ce..da94b6eb21e9 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -42,10 +42,10 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
@@ -71,12 +71,6 @@ using namespace ento;
// Utility functions.
//===----------------------------------------------------------------------===//
-bool bugreporter::isDeclRefExprToReference(const Expr *E) {
- if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
- return DRE->getDecl()->getType()->isReferenceType();
- return false;
-}
-
static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) {
if (B->isAdditiveOp() && B->getType()->isPointerType()) {
if (B->getLHS()->getType()->isPointerType()) {
@@ -142,8 +136,8 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
E = AE->getBase();
} else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
E = PE->getSubExpr();
- } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) {
- E = EWC->getSubExpr();
+ } else if (const auto *FE = dyn_cast<FullExpr>(E)) {
+ E = FE->getSubExpr();
} else {
// Other arbitrary stuff.
break;
@@ -160,34 +154,19 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
return E;
}
-const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
- const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
- if (const auto *BE = dyn_cast<BinaryOperator>(S))
- return BE->getRHS();
- return nullptr;
-}
-
-const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
- const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
- if (const auto *RS = dyn_cast<ReturnStmt>(S))
- return RS->getRetValue();
- return nullptr;
-}
-
//===----------------------------------------------------------------------===//
// Definitions for bug reporter visitors.
//===----------------------------------------------------------------------===//
std::shared_ptr<PathDiagnosticPiece>
-BugReporterVisitor::getEndPath(BugReporterContext &BRC,
- const ExplodedNode *EndPathNode, BugReport &BR) {
+BugReporterVisitor::getEndPath(BugReporterContext &,
+ const ExplodedNode *, BugReport &) {
return nullptr;
}
void
-BugReporterVisitor::finalizeVisitor(BugReporterContext &BRC,
- const ExplodedNode *EndPathNode,
- BugReport &BR) {}
+BugReporterVisitor::finalizeVisitor(BugReporterContext &,
+ const ExplodedNode *, BugReport &) {}
std::shared_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
@@ -269,10 +248,14 @@ namespace {
/// pointer dereference outside.
class NoStoreFuncVisitor final : public BugReporterVisitor {
const SubRegion *RegionOfInterest;
+ MemRegionManager &MmrMgr;
const SourceManager &SM;
const PrintingPolicy &PP;
- static constexpr const char *DiagnosticsMsg =
- "Returning without writing to '";
+
+ /// Recursion limit for dereferencing fields when looking for the
+ /// region of interest.
+ /// The limit of two indicates that we will dereference fields only once.
+ static const unsigned DEREFERENCE_LIMIT = 2;
/// Frames writing into \c RegionOfInterest.
/// This visitor generates a note only if a function does not write into
@@ -285,21 +268,22 @@ class NoStoreFuncVisitor final : public BugReporterVisitor {
llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
+ using RegionVector = SmallVector<const MemRegion *, 5>;
public:
NoStoreFuncVisitor(const SubRegion *R)
- : RegionOfInterest(R),
- SM(R->getMemRegionManager()->getContext().getSourceManager()),
- PP(R->getMemRegionManager()->getContext().getPrintingPolicy()) {}
+ : RegionOfInterest(R), MmrMgr(*R->getMemRegionManager()),
+ SM(MmrMgr.getContext().getSourceManager()),
+ PP(MmrMgr.getContext().getPrintingPolicy()) {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int Tag = 0;
ID.AddPointer(&Tag);
+ ID.AddPointer(RegionOfInterest);
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override {
+ BugReporterContext &BR,
+ BugReport &) override {
const LocationContext *Ctx = N->getLocationContext();
const StackFrameContext *SCtx = Ctx->getStackFrame();
@@ -307,48 +291,66 @@ public:
auto CallExitLoc = N->getLocationAs<CallExitBegin>();
// No diagnostic if region was modified inside the frame.
- if (!CallExitLoc)
+ if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N))
return nullptr;
CallEventRef<> Call =
- BRC.getStateManager().getCallEventManager().getCaller(SCtx, State);
+ BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
+
+ if (SM.isInSystemHeader(Call->getDecl()->getSourceRange().getBegin()))
+ return nullptr;
// Region of interest corresponds to an IVar, exiting a method
// which could have written into that IVar, but did not.
- if (const auto *MC = dyn_cast<ObjCMethodCall>(Call))
- if (const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest))
- if (potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
- IvarR->getDecl()) &&
- !isRegionOfInterestModifiedInFrame(N))
- return notModifiedMemberDiagnostics(
- Ctx, *CallExitLoc, Call, MC->getReceiverSVal().getAsRegion());
+ if (const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
+ if (const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
+ const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion();
+ if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
+ potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
+ IvarR->getDecl()))
+ return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, SelfRegion,
+ "self", /*FirstIsReferenceType=*/false,
+ 1);
+ }
+ }
if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
if (RegionOfInterest->isSubRegionOf(ThisR)
- && !CCall->getDecl()->isImplicit()
- && !isRegionOfInterestModifiedInFrame(N))
- return notModifiedMemberDiagnostics(Ctx, *CallExitLoc, Call, ThisR);
+ && !CCall->getDecl()->isImplicit())
+ return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, ThisR,
+ "this",
+ /*FirstIsReferenceType=*/false, 1);
+
+ // Do not generate diagnostics for not modified parameters in
+ // constructors.
+ return nullptr;
}
ArrayRef<ParmVarDecl *> parameters = getCallParameters(Call);
for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
const ParmVarDecl *PVD = parameters[I];
SVal S = Call->getArgSVal(I);
- unsigned IndirectionLevel = 1;
+ bool ParamIsReferenceType = PVD->getType()->isReferenceType();
+ std::string ParamName = PVD->getNameAsString();
+
+ int IndirectionLevel = 1;
QualType T = PVD->getType();
while (const MemRegion *R = S.getAsRegion()) {
- if (RegionOfInterest->isSubRegionOf(R)
- && !isPointerToConst(PVD->getType())) {
+ if (RegionOfInterest->isSubRegionOf(R) && !isPointerToConst(T))
+ return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, R,
+ ParamName, ParamIsReferenceType,
+ IndirectionLevel);
- if (isRegionOfInterestModifiedInFrame(N))
- return nullptr;
-
- return notModifiedParameterDiagnostics(
- Ctx, *CallExitLoc, Call, PVD, R, IndirectionLevel);
- }
QualType PT = T->getPointeeType();
if (PT.isNull() || PT->isVoidType()) break;
+
+ if (const RecordDecl *RD = PT->getAsRecordDecl())
+ if (auto P = findRegionOfInterestInRecord(RD, State, R))
+ return notModifiedDiagnostics(
+ Ctx, *CallExitLoc, Call, *P, RegionOfInterest, ParamName,
+ ParamIsReferenceType, IndirectionLevel);
+
S = State->getSVal(R, PT);
T = PT;
IndirectionLevel++;
@@ -359,20 +361,94 @@ public:
}
private:
+ /// Attempts to find the region of interest in a given CXX decl,
+ /// by either following the base classes or fields.
+ /// Dereferences fields up to a given recursion limit.
+ /// Note that \p Vec is passed by value, leading to quadratic copying cost,
+ /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
+ /// \return A chain fields leading to the region of interest or None.
+ const Optional<RegionVector>
+ findRegionOfInterestInRecord(const RecordDecl *RD, ProgramStateRef State,
+ const MemRegion *R,
+ const RegionVector &Vec = {},
+ int depth = 0) {
+
+ if (depth == DEREFERENCE_LIMIT) // Limit the recursion depth.
+ return None;
+
+ if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
+ if (!RDX->hasDefinition())
+ return None;
+
+ // Recursively examine the base classes.
+ // Note that following base classes does not increase the recursion depth.
+ if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
+ for (const auto II : RDX->bases())
+ if (const RecordDecl *RRD = II.getType()->getAsRecordDecl())
+ if (auto Out = findRegionOfInterestInRecord(RRD, State, R, Vec, depth))
+ return Out;
+
+ for (const FieldDecl *I : RD->fields()) {
+ QualType FT = I->getType();
+ const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
+ const SVal V = State->getSVal(FR);
+ const MemRegion *VR = V.getAsRegion();
+
+ RegionVector VecF = Vec;
+ VecF.push_back(FR);
+
+ if (RegionOfInterest == VR)
+ return VecF;
+
+ if (const RecordDecl *RRD = FT->getAsRecordDecl())
+ if (auto Out =
+ findRegionOfInterestInRecord(RRD, State, FR, VecF, depth + 1))
+ return Out;
+
+ QualType PT = FT->getPointeeType();
+ if (PT.isNull() || PT->isVoidType() || !VR) continue;
+
+ if (const RecordDecl *RRD = PT->getAsRecordDecl())
+ if (auto Out =
+ findRegionOfInterestInRecord(RRD, State, VR, VecF, depth + 1))
+ return Out;
+
+ }
+
+ return None;
+ }
/// \return Whether the method declaration \p Parent
/// syntactically has a binary operation writing into the ivar \p Ivar.
bool potentiallyWritesIntoIvar(const Decl *Parent,
const ObjCIvarDecl *Ivar) {
using namespace ast_matchers;
- if (!Parent || !Parent->getBody())
+ const char * IvarBind = "Ivar";
+ if (!Parent || !Parent->hasBody())
return false;
StatementMatcher WriteIntoIvarM = binaryOperator(
- hasOperatorName("="), hasLHS(ignoringParenImpCasts(objcIvarRefExpr(
- hasDeclaration(equalsNode(Ivar))))));
+ hasOperatorName("="),
+ hasLHS(ignoringParenImpCasts(
+ objcIvarRefExpr(hasDeclaration(equalsNode(Ivar))).bind(IvarBind))));
StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM));
auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext());
- return !Matches.empty();
+ for (BoundNodes &Match : Matches) {
+ auto IvarRef = Match.getNodeAs<ObjCIvarRefExpr>(IvarBind);
+ if (IvarRef->isFreeIvar())
+ return true;
+
+ const Expr *Base = IvarRef->getBase();
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
+ Base = ICE->getSubExpr();
+
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Base))
+ if (const auto *ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
+ if (ID->getParameterKind() == ImplicitParamDecl::ObjCSelf)
+ return true;
+
+ return false;
+ }
+ return false;
}
/// Check and lazily calculate whether the region of interest is
@@ -433,6 +509,8 @@ private:
RuntimeDefinition RD = Call->getRuntimeDefinition();
if (const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
return FD->parameters();
+ if (const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl()))
+ return MD->parameters();
return Call->parameters();
}
@@ -443,123 +521,112 @@ private:
Ty->getPointeeType().getCanonicalType().isConstQualified();
}
- /// \return Diagnostics piece for the member field not modified
- /// in a given function.
- std::shared_ptr<PathDiagnosticPiece> notModifiedMemberDiagnostics(
- const LocationContext *Ctx,
- CallExitBegin &CallExitLoc,
- CallEventRef<> Call,
- const MemRegion *ArgRegion) {
- const char *TopRegionName = isa<ObjCMethodCall>(Call) ? "self" : "this";
+ /// \return Diagnostics piece for region not modified in the current function.
+ std::shared_ptr<PathDiagnosticPiece>
+ notModifiedDiagnostics(const LocationContext *Ctx, CallExitBegin &CallExitLoc,
+ CallEventRef<> Call, const RegionVector &FieldChain,
+ const MemRegion *MatchedRegion, StringRef FirstElement,
+ bool FirstIsReferenceType, unsigned IndirectionLevel) {
+
+ PathDiagnosticLocation L;
+ if (const ReturnStmt *RS = CallExitLoc.getReturnStmt()) {
+ L = PathDiagnosticLocation::createBegin(RS, SM, Ctx);
+ } else {
+ L = PathDiagnosticLocation(
+ Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(),
+ SM);
+ }
+
SmallString<256> sbuf;
llvm::raw_svector_ostream os(sbuf);
- os << DiagnosticsMsg;
- bool out = prettyPrintRegionName(TopRegionName, "->", /*IsReference=*/true,
- /*IndirectionLevel=*/1, ArgRegion, os, PP);
+ os << "Returning without writing to '";
- // Return nothing if we have failed to pretty-print.
- if (!out)
+ // Do not generate the note if failed to pretty-print.
+ if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType,
+ MatchedRegion, FieldChain, IndirectionLevel, os))
return nullptr;
os << "'";
- PathDiagnosticLocation L =
- getPathDiagnosticLocation(CallExitLoc.getReturnStmt(), SM, Ctx, Call);
return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
}
- /// \return Diagnostics piece for the parameter \p PVD not modified
- /// in a given function.
- /// \p IndirectionLevel How many times \c ArgRegion has to be dereferenced
- /// before we get to the super region of \c RegionOfInterest
- std::shared_ptr<PathDiagnosticPiece>
- notModifiedParameterDiagnostics(const LocationContext *Ctx,
- CallExitBegin &CallExitLoc,
- CallEventRef<> Call,
- const ParmVarDecl *PVD,
- const MemRegion *ArgRegion,
- unsigned IndirectionLevel) {
- PathDiagnosticLocation L = getPathDiagnosticLocation(
- CallExitLoc.getReturnStmt(), SM, Ctx, Call);
- SmallString<256> sbuf;
- llvm::raw_svector_ostream os(sbuf);
- os << DiagnosticsMsg;
- bool IsReference = PVD->getType()->isReferenceType();
- const char *Sep = IsReference && IndirectionLevel == 1 ? "." : "->";
- bool Success = prettyPrintRegionName(
- PVD->getQualifiedNameAsString().c_str(),
- Sep, IsReference, IndirectionLevel, ArgRegion, os, PP);
-
- // Print the parameter name if the pretty-printing has failed.
- if (!Success)
- PVD->printQualifiedName(os);
- os << "'";
- return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
- }
+ /// Pretty-print region \p MatchedRegion to \p os.
+ /// \return Whether printing succeeded.
+ bool prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType,
+ const MemRegion *MatchedRegion,
+ const RegionVector &FieldChain,
+ int IndirectionLevel,
+ llvm::raw_svector_ostream &os) {
- /// \return a path diagnostic location for the optionally
- /// present return statement \p RS.
- PathDiagnosticLocation getPathDiagnosticLocation(const ReturnStmt *RS,
- const SourceManager &SM,
- const LocationContext *Ctx,
- CallEventRef<> Call) {
- if (RS)
- return PathDiagnosticLocation::createBegin(RS, SM, Ctx);
- return PathDiagnosticLocation(
- Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(), SM);
- }
+ if (FirstIsReferenceType)
+ IndirectionLevel--;
- /// Pretty-print region \p ArgRegion starting from parent to \p os.
- /// \return whether printing has succeeded
- bool prettyPrintRegionName(StringRef TopRegionName,
- StringRef Sep,
- bool IsReference,
- int IndirectionLevel,
- const MemRegion *ArgRegion,
- llvm::raw_svector_ostream &os,
- const PrintingPolicy &PP) {
- SmallVector<const MemRegion *, 5> Subregions;
+ RegionVector RegionSequence;
+
+ // Add the regions in the reverse order, then reverse the resulting array.
+ assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
const MemRegion *R = RegionOfInterest;
- while (R != ArgRegion) {
- if (!(isa<FieldRegion>(R) || isa<CXXBaseObjectRegion>(R) ||
- isa<ObjCIvarRegion>(R)))
- return false; // Pattern-matching failed.
- Subregions.push_back(R);
+ while (R != MatchedRegion) {
+ RegionSequence.push_back(R);
R = cast<SubRegion>(R)->getSuperRegion();
}
- bool IndirectReference = !Subregions.empty();
+ std::reverse(RegionSequence.begin(), RegionSequence.end());
+ RegionSequence.append(FieldChain.begin(), FieldChain.end());
+
+ StringRef Sep;
+ for (const MemRegion *R : RegionSequence) {
+
+ // Just keep going up to the base region.
+ // Element regions may appear due to casts.
+ if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
+ continue;
+
+ if (Sep.empty())
+ Sep = prettyPrintFirstElement(FirstElement,
+ /*MoreItemsExpected=*/true,
+ IndirectionLevel, os);
- if (IndirectReference)
- IndirectionLevel--; // Due to "->" symbol.
+ os << Sep;
- if (IsReference)
- IndirectionLevel--; // Due to reference semantics.
+ // Can only reasonably pretty-print DeclRegions.
+ if (!isa<DeclRegion>(R))
+ return false;
- bool ShouldSurround = IndirectReference && IndirectionLevel > 0;
+ const auto *DR = cast<DeclRegion>(R);
+ Sep = DR->getValueType()->isAnyPointerType() ? "->" : ".";
+ DR->getDecl()->getDeclName().print(os, PP);
+ }
- if (ShouldSurround)
+ if (Sep.empty())
+ prettyPrintFirstElement(FirstElement,
+ /*MoreItemsExpected=*/false, IndirectionLevel,
+ os);
+ return true;
+ }
+
+ /// Print first item in the chain, return new separator.
+ StringRef prettyPrintFirstElement(StringRef FirstElement,
+ bool MoreItemsExpected,
+ int IndirectionLevel,
+ llvm::raw_svector_ostream &os) {
+ StringRef Out = ".";
+
+ if (IndirectionLevel > 0 && MoreItemsExpected) {
+ IndirectionLevel--;
+ Out = "->";
+ }
+
+ if (IndirectionLevel > 0 && MoreItemsExpected)
os << "(";
- for (int i = 0; i < IndirectionLevel; i++)
+
+ for (int i=0; i<IndirectionLevel; i++)
os << "*";
- os << TopRegionName;
- if (ShouldSurround)
+ os << FirstElement;
+
+ if (IndirectionLevel > 0 && MoreItemsExpected)
os << ")";
- for (auto I = Subregions.rbegin(), E = Subregions.rend(); I != E; ++I) {
- if (const auto *FR = dyn_cast<FieldRegion>(*I)) {
- os << Sep;
- FR->getDecl()->getDeclName().print(os, PP);
- Sep = ".";
- } else if (const auto *IR = dyn_cast<ObjCIvarRegion>(*I)) {
- os << "->";
- IR->getDecl()->getDeclName().print(os, PP);
- Sep = ".";
- } else if (isa<CXXBaseObjectRegion>(*I)) {
- continue; // Just keep going up to the base region.
- } else {
- llvm_unreachable("Previous check has missed an unexpected region");
- }
- }
- return true;
+ return Out;
}
};
@@ -579,7 +646,6 @@ public:
ValueAtDereference(V) {}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override {
if (WasModified)
@@ -590,10 +656,10 @@ public:
return nullptr;
const SourceManager &SMgr = BRC.getSourceManager();
- if (auto Loc = matchAssignment(N, BRC)) {
+ if (auto Loc = matchAssignment(N)) {
if (isFunctionMacroExpansion(*Loc, SMgr)) {
std::string MacroName = getMacroName(*Loc, BRC);
- SourceLocation BugLoc = BugPoint->getStmt()->getLocStart();
+ SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
if (!BugLoc.isMacroID() || getMacroName(BugLoc, BRC) != MacroName)
BR.markInvalid(getTag(), MacroName.c_str());
}
@@ -610,8 +676,8 @@ public:
bool EnableNullFPSuppression, BugReport &BR,
const SVal V) {
AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
- if (EnableNullFPSuppression && Options.shouldSuppressNullReturnPaths()
- && V.getAs<Loc>())
+ if (EnableNullFPSuppression &&
+ Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
R->getAs<SubRegion>(), V));
}
@@ -628,8 +694,7 @@ public:
private:
/// \return Source location of right hand side of an assignment
/// into \c RegionOfInterest, empty optional if none found.
- Optional<SourceLocation> matchAssignment(const ExplodedNode *N,
- BugReporterContext &BRC) {
+ Optional<SourceLocation> matchAssignment(const ExplodedNode *N) {
const Stmt *S = PathDiagnosticLocation::getStmt(N);
ProgramStateRef State = N->getState();
auto *LCtx = N->getLocationContext();
@@ -641,12 +706,12 @@ private:
if (const Expr *RHS = VD->getInit())
if (RegionOfInterest->isSubRegionOf(
State->getLValue(VD, LCtx).getAsRegion()))
- return RHS->getLocStart();
+ return RHS->getBeginLoc();
} else if (const auto *BO = dyn_cast<BinaryOperator>(S)) {
const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
const Expr *RHS = BO->getRHS();
if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
- return RHS->getLocStart();
+ return RHS->getBeginLoc();
}
}
return None;
@@ -670,10 +735,14 @@ class ReturnVisitor : public BugReporterVisitor {
bool EnableNullFPSuppression;
bool ShouldInvalidate = true;
+ AnalyzerOptions& Options;
public:
- ReturnVisitor(const StackFrameContext *Frame, bool Suppressed)
- : StackFrame(Frame), EnableNullFPSuppression(Suppressed) {}
+ ReturnVisitor(const StackFrameContext *Frame,
+ bool Suppressed,
+ AnalyzerOptions &Options)
+ : StackFrame(Frame), EnableNullFPSuppression(Suppressed),
+ Options(Options) {}
static void *getTag() {
static int Tag = 0;
@@ -701,10 +770,10 @@ public:
// First, find when we processed the statement.
do {
- if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>())
+ if (auto CEE = Node->getLocationAs<CallExitEnd>())
if (CEE->getCalleeContext()->getCallSite() == S)
break;
- if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>())
+ if (auto SP = Node->getLocationAs<StmtPoint>())
if (SP->getStmt() == S)
break;
@@ -739,23 +808,19 @@ public:
AnalyzerOptions &Options = State->getAnalysisManager().options;
bool EnableNullFPSuppression = false;
- if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths())
+ if (InEnableNullFPSuppression &&
+ Options.ShouldSuppressNullReturnPaths)
if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
BR.markInteresting(CalleeContext);
BR.addVisitor(llvm::make_unique<ReturnVisitor>(CalleeContext,
- EnableNullFPSuppression));
- }
-
- /// Returns true if any counter-suppression heuristics are enabled for
- /// ReturnVisitor.
- static bool hasCounterSuppression(AnalyzerOptions &Options) {
- return Options.shouldAvoidSuppressingNullArgumentPaths();
+ EnableNullFPSuppression,
+ Options));
}
std::shared_ptr<PathDiagnosticPiece>
- visitNodeInitial(const ExplodedNode *N, const ExplodedNode *PrevN,
+ visitNodeInitial(const ExplodedNode *N,
BugReporterContext &BRC, BugReport &BR) {
// Only print a message at the interesting return statement.
if (N->getLocationContext() != StackFrame)
@@ -799,37 +864,40 @@ public:
RetE = RetE->IgnoreParenCasts();
- // If we can't prove the return value is 0, just mark it interesting, and
- // make sure to track it into any further inner functions.
- if (!State->isNull(V).isConstrainedTrue()) {
- BR.markInteresting(V);
- ReturnVisitor::addVisitorIfNecessary(N, RetE, BR,
- EnableNullFPSuppression);
- return nullptr;
- }
-
// If we're returning 0, we should track where that 0 came from.
- bugreporter::trackNullOrUndefValue(N, RetE, BR, /*IsArg*/ false,
- EnableNullFPSuppression);
+ bugreporter::trackExpressionValue(N, RetE, BR, EnableNullFPSuppression);
// Build an appropriate message based on the return value.
SmallString<64> Msg;
llvm::raw_svector_ostream Out(Msg);
- if (V.getAs<Loc>()) {
- // If we have counter-suppression enabled, make sure we keep visiting
- // future nodes. We want to emit a path note as well, in case
- // the report is resurrected as valid later on.
- AnalyzerOptions &Options = BRC.getAnalyzerOptions();
- if (EnableNullFPSuppression && hasCounterSuppression(Options))
- Mode = MaybeUnsuppress;
+ if (State->isNull(V).isConstrainedTrue()) {
+ if (V.getAs<Loc>()) {
+
+ // If we have counter-suppression enabled, make sure we keep visiting
+ // future nodes. We want to emit a path note as well, in case
+ // the report is resurrected as valid later on.
+ if (EnableNullFPSuppression &&
+ Options.ShouldAvoidSuppressingNullArgumentPaths)
+ Mode = MaybeUnsuppress;
+
+ if (RetE->getType()->isObjCObjectPointerType()) {
+ Out << "Returning nil";
+ } else {
+ Out << "Returning null pointer";
+ }
+ } else {
+ Out << "Returning zero";
+ }
- if (RetE->getType()->isObjCObjectPointerType())
- Out << "Returning nil";
- else
- Out << "Returning null pointer";
} else {
- Out << "Returning zero";
+ if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
+ Out << "Returning the value " << CI->getValue();
+ } else if (V.getAs<Loc>()) {
+ Out << "Returning pointer";
+ } else {
+ Out << "Returning value";
+ }
}
if (LValue) {
@@ -855,11 +923,10 @@ public:
}
std::shared_ptr<PathDiagnosticPiece>
- visitNodeMaybeUnsuppress(const ExplodedNode *N, const ExplodedNode *PrevN,
+ visitNodeMaybeUnsuppress(const ExplodedNode *N,
BugReporterContext &BRC, BugReport &BR) {
#ifndef NDEBUG
- AnalyzerOptions &Options = BRC.getAnalyzerOptions();
- assert(hasCounterSuppression(Options));
+ assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
#endif
// Are we at the entry node for this call?
@@ -893,8 +960,7 @@ public:
if (!State->isNull(*ArgV).isConstrainedTrue())
continue;
- if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true,
- EnableNullFPSuppression))
+ if (bugreporter::trackExpressionValue(N, ArgE, BR, EnableNullFPSuppression))
ShouldInvalidate = false;
// If we /can't/ track the null pointer, we should err on the side of
@@ -906,14 +972,13 @@ public:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override {
switch (Mode) {
case Initial:
- return visitNodeInitial(N, PrevN, BRC, BR);
+ return visitNodeInitial(N, BRC, BR);
case MaybeUnsuppress:
- return visitNodeMaybeUnsuppress(N, PrevN, BRC, BR);
+ return visitNodeMaybeUnsuppress(N, BRC, BR);
case Satisfied:
return nullptr;
}
@@ -921,7 +986,7 @@ public:
llvm_unreachable("Invalid visit mode!");
}
- void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
+ void finalizeVisitor(BugReporterContext &, const ExplodedNode *,
BugReport &BR) override {
if (EnableNullFPSuppression && ShouldInvalidate)
BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
@@ -1087,12 +1152,12 @@ static void showBRDefaultDiagnostics(llvm::raw_svector_ostream& os,
std::shared_ptr<PathDiagnosticPiece>
FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC, BugReport &BR) {
if (Satisfied)
return nullptr;
const ExplodedNode *StoreSite = nullptr;
+ const ExplodedNode *Pred = Succ->getFirstPred();
const Expr *InitE = nullptr;
bool IsParam = false;
@@ -1173,12 +1238,11 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
if (!IsParam)
InitE = InitE->IgnoreParenCasts();
- bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam,
- EnableNullFPSuppression);
- } else {
- ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(),
- BR, EnableNullFPSuppression);
+ bugreporter::trackExpressionValue(StoreSite, InitE, BR,
+ EnableNullFPSuppression);
}
+ ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(),
+ BR, EnableNullFPSuppression);
}
// Okay, we've found the binding. Emit an appropriate message.
@@ -1204,8 +1268,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
if (const auto *BDR =
dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
- if (Optional<KnownSVal> KV =
- State->getSVal(OriginalR).getAs<KnownSVal>())
+ if (auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
*KV, OriginalR, EnableNullFPSuppression));
}
@@ -1260,8 +1323,8 @@ bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
std::shared_ptr<PathDiagnosticPiece>
TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC, BugReport &BR) {
+ BugReporterContext &BRC, BugReport &) {
+ const ExplodedNode *PrevN = N->getFirstPred();
if (IsSatisfied)
return nullptr;
@@ -1316,7 +1379,7 @@ SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N)
: V(Value) {
// Check if the visitor is disabled.
AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
- if (!Options.shouldSuppressInlinedDefensiveChecks())
+ if (!Options.ShouldSuppressInlinedDefensiveChecks)
IsSatisfied = true;
assert(N->getState()->isNull(V).isConstrainedTrue() &&
@@ -1336,9 +1399,9 @@ const char *SuppressInlineDefensiveChecksVisitor::getTag() {
std::shared_ptr<PathDiagnosticPiece>
SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
BugReporterContext &BRC,
BugReport &BR) {
+ const ExplodedNode *Pred = Succ->getFirstPred();
if (IsSatisfied)
return nullptr;
@@ -1379,7 +1442,7 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
} else if (auto SP = CurPoint.getAs<StmtPoint>()) {
const Stmt *CurStmt = SP->getStmt();
- if (!CurStmt->getLocStart().isMacroID())
+ if (!CurStmt->getBeginLoc().isMacroID())
return nullptr;
CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
@@ -1391,9 +1454,9 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
if (!CurTerminatorStmt)
return nullptr;
- SourceLocation TerminatorLoc = CurTerminatorStmt->getLocStart();
+ SourceLocation TerminatorLoc = CurTerminatorStmt->getBeginLoc();
if (TerminatorLoc.isMacroID()) {
- SourceLocation BugLoc = BugPoint->getStmt()->getLocStart();
+ SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
// Suppress reports unless we are in that same macro.
if (!BugLoc.isMacroID() ||
@@ -1427,11 +1490,13 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
return nullptr;
}
+/// \return A subexpression of {@code Ex} which represents the
+/// expression-of-interest.
static const Expr *peelOffOuterExpr(const Expr *Ex,
const ExplodedNode *N) {
Ex = Ex->IgnoreParenCasts();
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(Ex))
- return peelOffOuterExpr(EWC->getSubExpr(), N);
+ if (const auto *FE = dyn_cast<FullExpr>(Ex))
+ return peelOffOuterExpr(FE->getSubExpr(), N);
if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
return peelOffOuterExpr(OVE->getSourceExpr(), N);
if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
@@ -1471,121 +1536,72 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
if (const Expr *SubEx = peelOffPointerArithmetic(BO))
return peelOffOuterExpr(SubEx, N);
- return Ex;
-}
+ if (auto *UO = dyn_cast<UnaryOperator>(Ex)) {
+ if (UO->getOpcode() == UO_LNot)
+ return peelOffOuterExpr(UO->getSubExpr(), N);
-/// Walk through nodes until we get one that matches the statement exactly.
-/// Alternately, if we hit a known lvalue for the statement, we know we've
-/// gone too far (though we can likely track the lvalue better anyway).
-static const ExplodedNode* findNodeForStatement(const ExplodedNode *N,
- const Stmt *S,
- const Expr *Inner) {
- do {
- const ProgramPoint &pp = N->getLocation();
- if (auto ps = pp.getAs<StmtPoint>()) {
- if (ps->getStmt() == S || ps->getStmt() == Inner)
- break;
- } else if (auto CEE = pp.getAs<CallExitEnd>()) {
- if (CEE->getCalleeContext()->getCallSite() == S ||
- CEE->getCalleeContext()->getCallSite() == Inner)
- break;
- }
- N = N->getFirstPred();
- } while (N);
- return N;
+ // FIXME: There's a hack in our Store implementation that always computes
+ // field offsets around null pointers as if they are always equal to 0.
+ // The idea here is to report accesses to fields as null dereferences
+ // even though the pointer value that's being dereferenced is actually
+ // the offset of the field rather than exactly 0.
+ // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
+ // This code interacts heavily with this hack; otherwise the value
+ // would not be null at all for most fields, so we'd be unable to track it.
+ if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
+ if (const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
+ return peelOffOuterExpr(DerefEx, N);
+ }
+
+ return Ex;
}
/// Find the ExplodedNode where the lvalue (the value of 'Ex')
/// was computed.
static const ExplodedNode* findNodeForExpression(const ExplodedNode *N,
- const Expr *Inner) {
+ const Expr *Inner) {
while (N) {
- if (auto P = N->getLocation().getAs<PostStmt>()) {
- if (P->getStmt() == Inner)
- break;
- }
+ if (PathDiagnosticLocation::getStmt(N) == Inner)
+ return N;
N = N->getFirstPred();
}
- assert(N && "Unable to find the lvalue node.");
return N;
}
-/// Performing operator `&' on an lvalue expression is essentially a no-op.
-/// Then, if we are taking addresses of fields or elements, these are also
-/// unlikely to matter.
-static const Expr* peelOfOuterAddrOf(const Expr* Ex) {
- Ex = Ex->IgnoreParenCasts();
-
- // FIXME: There's a hack in our Store implementation that always computes
- // field offsets around null pointers as if they are always equal to 0.
- // The idea here is to report accesses to fields as null dereferences
- // even though the pointer value that's being dereferenced is actually
- // the offset of the field rather than exactly 0.
- // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
- // This code interacts heavily with this hack; otherwise the value
- // would not be null at all for most fields, so we'd be unable to track it.
- if (const auto *Op = dyn_cast<UnaryOperator>(Ex))
- if (Op->getOpcode() == UO_AddrOf && Op->getSubExpr()->isLValue())
- if (const Expr *DerefEx = bugreporter::getDerefExpr(Op->getSubExpr()))
- return DerefEx;
- return Ex;
-}
-
-bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
- const Stmt *S,
- BugReport &report, bool IsArg,
- bool EnableNullFPSuppression) {
- if (!S || !N)
+bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
+ const Expr *E, BugReport &report,
+ bool EnableNullFPSuppression) {
+ if (!E || !InputNode)
return false;
- if (const auto *Ex = dyn_cast<Expr>(S))
- S = peelOffOuterExpr(Ex, N);
-
- const Expr *Inner = nullptr;
- if (const auto *Ex = dyn_cast<Expr>(S)) {
- Ex = peelOfOuterAddrOf(Ex);
- Ex = Ex->IgnoreParenCasts();
-
- if (Ex && (ExplodedGraph::isInterestingLValueExpr(Ex)
- || CallEvent::isCallStmt(Ex)))
- Inner = Ex;
- }
-
- if (IsArg && !Inner) {
- assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call");
- } else {
- N = findNodeForStatement(N, S, Inner);
- if (!N)
- return false;
- }
+ const Expr *Inner = peelOffOuterExpr(E, InputNode);
+ const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
+ if (!LVNode)
+ return false;
- ProgramStateRef state = N->getState();
+ ProgramStateRef LVState = LVNode->getState();
// The message send could be nil due to the receiver being nil.
// At this point in the path, the receiver should be live since we are at the
// message send expr. If it is nil, start tracking it.
- if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(S, N))
- trackNullOrUndefValue(N, Receiver, report, /* IsArg=*/ false,
- EnableNullFPSuppression);
+ if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
+ trackExpressionValue(LVNode, Receiver, report, EnableNullFPSuppression);
// See if the expression we're interested refers to a variable.
// If so, we can track both its contents and constraints on its value.
- if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) {
- const ExplodedNode *LVNode = findNodeForExpression(N, Inner);
- ProgramStateRef LVState = LVNode->getState();
+ if (ExplodedGraph::isInterestingLValueExpr(Inner)) {
SVal LVal = LVNode->getSVal(Inner);
- const MemRegion *RR = getLocationRegionIfReference(Inner, N);
+ const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode);
bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
// If this is a C++ reference to a null pointer, we are tracking the
// pointer. In addition, we should find the store at which the reference
// got initialized.
- if (RR && !LVIsNull) {
+ if (RR && !LVIsNull)
if (auto KV = LVal.getAs<KnownSVal>())
report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
*KV, RR, EnableNullFPSuppression));
- }
// In case of C++ references, we want to differentiate between a null
// reference and reference to null pointer.
@@ -1602,9 +1618,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
llvm::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R)));
MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
- N, R, EnableNullFPSuppression, report, V);
+ LVNode, R, EnableNullFPSuppression, report, V);
- report.markInteresting(R);
report.markInteresting(V);
report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R));
@@ -1614,14 +1629,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
V.castAs<DefinedSVal>(), false));
// Add visitor, which will suppress inline defensive checks.
- if (auto DV = V.getAs<DefinedSVal>()) {
+ if (auto DV = V.getAs<DefinedSVal>())
if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
- EnableNullFPSuppression) {
+ EnableNullFPSuppression)
report.addVisitor(
llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
- LVNode));
- }
- }
+ LVNode));
if (auto KV = V.getAs<KnownSVal>())
report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
@@ -1632,40 +1645,44 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
// If the expression is not an "lvalue expression", we can still
// track the constraints on its contents.
- SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
+ SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
- // If the value came from an inlined function call, we should at least make
- // sure that function isn't pruned in our output.
- if (const auto *E = dyn_cast<Expr>(S))
- S = E->IgnoreParenCasts();
+ ReturnVisitor::addVisitorIfNecessary(
+ LVNode, Inner, report, EnableNullFPSuppression);
- ReturnVisitor::addVisitorIfNecessary(N, S, report, EnableNullFPSuppression);
-
- // Uncomment this to find cases where we aren't properly getting the
- // base value that was dereferenced.
- // assert(!V.isUnknownOrUndef());
// Is it a symbolic value?
if (auto L = V.getAs<loc::MemRegionVal>()) {
report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
+ // FIXME: this is a hack for fixing a later crash when attempting to
+ // dereference a void* pointer.
+ // We should not try to dereference pointers at all when we don't care
+ // what is written inside the pointer.
+ bool CanDereference = true;
+ if (const auto *SR = dyn_cast<SymbolicRegion>(L->getRegion()))
+ if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
+ CanDereference = false;
+
// At this point we are dealing with the region's LValue.
// However, if the rvalue is a symbolic region, we should track it as well.
// Try to use the correct type when looking up the value.
SVal RVal;
- if (const auto *E = dyn_cast<Expr>(S))
- RVal = state->getRawSVal(L.getValue(), E->getType());
- else
- RVal = state->getSVal(L->getRegion());
+ if (ExplodedGraph::isInterestingLValueExpr(Inner)) {
+ RVal = LVState->getRawSVal(L.getValue(), Inner->getType());
+ } else if (CanDereference) {
+ RVal = LVState->getSVal(L->getRegion());
+ }
- if (auto KV = RVal.getAs<KnownSVal>())
- report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
+ if (CanDereference)
+ if (auto KV = RVal.getAs<KnownSVal>())
+ report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
*KV, L->getRegion(), EnableNullFPSuppression));
const MemRegion *RegionRVal = RVal.getAsRegion();
if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
report.markInteresting(RegionRVal);
report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
- loc::MemRegionVal(RegionRVal), false));
+ loc::MemRegionVal(RegionRVal), /*assumption=*/false));
}
}
return true;
@@ -1687,7 +1704,6 @@ const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S,
std::shared_ptr<PathDiagnosticPiece>
NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC, BugReport &BR) {
Optional<PreStmt> P = N->getLocationAs<PreStmt>();
if (!P)
@@ -1714,8 +1730,8 @@ NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
// The receiver was nil, and hence the method was skipped.
// Register a BugReporterVisitor to issue a message telling us how
// the receiver was null.
- bugreporter::trackNullOrUndefValue(N, Receiver, BR, /*IsArg*/ false,
- /*EnableNullFPSuppression*/ false);
+ bugreporter::trackExpressionValue(N, Receiver, BR,
+ /*EnableNullFPSuppression*/ false);
// Issue a message saying that the method was skipped.
PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
N->getLocationContext());
@@ -1768,9 +1784,9 @@ const char *ConditionBRVisitor::getTag() {
}
std::shared_ptr<PathDiagnosticPiece>
-ConditionBRVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *Prev,
+ConditionBRVisitor::VisitNode(const ExplodedNode *N,
BugReporterContext &BRC, BugReport &BR) {
- auto piece = VisitNodeImpl(N, Prev, BRC, BR);
+ auto piece = VisitNodeImpl(N, BRC, BR);
if (piece) {
piece->setTag(getTag());
if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
@@ -1781,11 +1797,10 @@ ConditionBRVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *Prev,
std::shared_ptr<PathDiagnosticPiece>
ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
- const ExplodedNode *Prev,
BugReporterContext &BRC, BugReport &BR) {
ProgramPoint progPoint = N->getLocation();
ProgramStateRef CurrentState = N->getState();
- ProgramStateRef PrevState = Prev->getState();
+ ProgramStateRef PrevState = N->getFirstPred()->getState();
// Compare the GDMs of the state, because that is where constraints
// are managed. Note that ensure that we only look at nodes that
@@ -1936,8 +1951,8 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex,
// Use heuristics to determine if Ex is a macro expending to a literal and
// if so, use the macro's name.
- SourceLocation LocStart = Ex->getLocStart();
- SourceLocation LocEnd = Ex->getLocEnd();
+ SourceLocation LocStart = Ex->getBeginLoc();
+ SourceLocation LocEnd = Ex->getEndLoc();
if (LocStart.isMacroID() && LocEnd.isMacroID() &&
(isa<GNUNullExpr>(Ex) ||
isa<ObjCBoolLiteralExpr>(Ex) ||
@@ -1951,10 +1966,10 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex,
bool beginAndEndAreTheSameMacro = StartName.equals(EndName);
bool partOfParentMacro = false;
- if (ParentEx->getLocStart().isMacroID()) {
+ if (ParentEx->getBeginLoc().isMacroID()) {
StringRef PName = Lexer::getImmediateMacroNameForDiagnostics(
- ParentEx->getLocStart(), BRC.getSourceManager(),
- BRC.getASTContext().getLangOpts());
+ ParentEx->getBeginLoc(), BRC.getSourceManager(),
+ BRC.getASTContext().getLangOpts());
partOfParentMacro = PName.equals(StartName);
}
@@ -2205,7 +2220,7 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
// the user's fault, we currently don't report them very well, and
// Note that this will not help for any other data structure libraries, like
// TR1, Boost, or llvm/ADT.
- if (Options.shouldSuppressFromCXXStandardLibrary()) {
+ if (Options.ShouldSuppressFromCXXStandardLibrary) {
BR.markInvalid(getTag(), nullptr);
return;
} else {
@@ -2277,7 +2292,6 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
std::shared_ptr<PathDiagnosticPiece>
UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC, BugReport &BR) {
ProgramStateRef State = N->getState();
ProgramPoint ProgLoc = N->getLocation();
@@ -2328,8 +2342,7 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
std::shared_ptr<PathDiagnosticPiece>
CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
- BugReporterContext &BRC, BugReport &BR) {
+ BugReporterContext &BRC, BugReport &) {
if (Satisfied)
return nullptr;
@@ -2380,11 +2393,11 @@ CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ,
}
std::shared_ptr<PathDiagnosticPiece>
-TaintBugVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN,
- BugReporterContext &BRC, BugReport &BR) {
+TaintBugVisitor::VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC, BugReport &) {
// Find the ExplodedNode where the taint was first introduced
- if (!N->getState()->isTainted(V) || PrevN->getState()->isTainted(V))
+ if (!N->getState()->isTainted(V) || N->getFirstPred()->getState()->isTainted(V))
return nullptr;
const Stmt *S = PathDiagnosticLocation::getStmt(N);
@@ -2406,36 +2419,43 @@ FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
void FalsePositiveRefutationBRVisitor::finalizeVisitor(
BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
// Collect new constraints
- VisitNode(EndPathNode, nullptr, BRC, BR);
+ VisitNode(EndPathNode, BRC, BR);
// Create a refutation manager
- std::unique_ptr<SMTSolver> RefutationSolver = CreateZ3Solver();
+ SMTSolverRef RefutationSolver = CreateZ3Solver();
ASTContext &Ctx = BRC.getASTContext();
// Add constraints to the solver
for (const auto &I : Constraints) {
- SymbolRef Sym = I.first;
+ const SymbolRef Sym = I.first;
+ auto RangeIt = I.second.begin();
- SMTExprRef Constraints = RefutationSolver->fromBoolean(false);
- for (const auto &Range : I.second) {
+ SMTExprRef Constraints = SMTConv::getRangeExpr(
+ RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
+ /*InRange=*/true);
+ while ((++RangeIt) != I.second.end()) {
Constraints = RefutationSolver->mkOr(
- Constraints,
- RefutationSolver->getRangeExpr(Ctx, Sym, Range.From(), Range.To(),
- /*InRange=*/true));
+ Constraints, SMTConv::getRangeExpr(RefutationSolver, Ctx, Sym,
+ RangeIt->From(), RangeIt->To(),
+ /*InRange=*/true));
}
+
RefutationSolver->addConstraint(Constraints);
}
// And check for satisfiability
- if (RefutationSolver->check().isConstrainedFalse())
+ Optional<bool> isSat = RefutationSolver->check();
+ if (!isSat.hasValue())
+ return;
+
+ if (!isSat.getValue())
BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext());
}
std::shared_ptr<PathDiagnosticPiece>
FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) {
+ BugReporterContext &,
+ BugReport &) {
// Collect new constraints
const ConstraintRangeTy &NewCs = N->getState()->get<ConstraintRange>();
ConstraintRangeTy::Factory &CF =
diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index de994b598e59..167f78af6289 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -20,7 +20,6 @@ add_clang_library(clangStaticAnalyzerCore
CheckerContext.cpp
CheckerHelpers.cpp
CheckerManager.cpp
- CheckerRegistry.cpp
CommonBugCategories.cpp
ConstraintManager.cpp
CoreEngine.cpp
@@ -44,14 +43,16 @@ add_clang_library(clangStaticAnalyzerCore
RangeConstraintManager.cpp
RangedConstraintManager.cpp
RegionStore.cpp
- SValBuilder.cpp
- SVals.cpp
+ RetainSummaryManager.cpp
+ SarifDiagnostics.cpp
SimpleConstraintManager.cpp
SimpleSValBuilder.cpp
- SMTConstraintManager.cpp
Store.cpp
SubEngine.cpp
+ SValBuilder.cpp
+ SVals.cpp
SymbolManager.cpp
+ TaintManager.cpp
WorkList.cpp
Z3ConstraintManager.cpp
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index fe9260e32dd8..0e7f31502e81 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -169,18 +169,27 @@ bool CallEvent::isGlobalCFunction(StringRef FunctionName) const {
AnalysisDeclContext *CallEvent::getCalleeAnalysisDeclContext() const {
const Decl *D = getDecl();
-
- // If the callee is completely unknown, we cannot construct the stack frame.
if (!D)
return nullptr;
- // FIXME: Skip virtual functions for now. There's no easy procedure to foresee
- // the exact decl that should be used, especially when it's not a definition.
- if (const Decl *RD = getRuntimeDefinition().getDecl())
- if (RD != D)
- return nullptr;
+ // TODO: For now we skip functions without definitions, even if we have
+ // our own getDecl(), because it's hard to find out which re-declaration
+ // is going to be used, and usually clients don't really care about this
+ // situation because there's a loss of precision anyway because we cannot
+ // inline the call.
+ RuntimeDefinition RD = getRuntimeDefinition();
+ if (!RD.getDecl())
+ return nullptr;
+
+ AnalysisDeclContext *ADC =
+ LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
+
+ // TODO: For now we skip virtual functions, because this also rises
+ // the problem of which decl to use, but now it's across different classes.
+ if (RD.mayHaveOtherDefinitions() || RD.getDecl() != ADC->getDecl())
+ return nullptr;
- return LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
+ return ADC;
}
const StackFrameContext *CallEvent::getCalleeStackFrame() const {
@@ -218,7 +227,24 @@ const VarRegion *CallEvent::getParameterLocation(unsigned Index) const {
if (!SFC)
return nullptr;
- const ParmVarDecl *PVD = parameters()[Index];
+ // Retrieve parameters of the definition, which are different from
+ // CallEvent's parameters() because getDecl() isn't necessarily
+ // the definition. SFC contains the definition that would be used
+ // during analysis.
+ const Decl *D = SFC->getDecl();
+
+ // TODO: Refactor into a virtual method of CallEvent, like parameters().
+ const ParmVarDecl *PVD = nullptr;
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ PVD = FD->parameters()[Index];
+ else if (const auto *BD = dyn_cast<BlockDecl>(D))
+ PVD = BD->parameters()[Index];
+ else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ PVD = MD->parameters()[Index];
+ else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
+ PVD = CD->parameters()[Index];
+ assert(PVD && "Unexpected Decl kind!");
+
const VarRegion *VR =
State->getStateManager().getRegionManager().getVarRegion(PVD, SFC);
@@ -285,6 +311,20 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
// TODO: Factor this out + handle the lower level const pointers.
ValuesToInvalidate.push_back(getArgSVal(Idx));
+
+ // If a function accepts an object by argument (which would of course be a
+ // temporary that isn't lifetime-extended), invalidate the object itself,
+ // not only other objects reachable from it. This is necessary because the
+ // destructor has access to the temporary object after the call.
+ // TODO: Support placement arguments once we start
+ // constructing them directly.
+ // TODO: This is unnecessary when there's no destructor, but that's
+ // currently hard to figure out.
+ if (getKind() != CE_CXXAllocator)
+ if (isArgumentConstructedDirectly(Idx))
+ if (auto AdjIdx = getAdjustedParameterIndex(Idx))
+ if (const VarRegion *VR = getParameterLocation(*AdjIdx))
+ ValuesToInvalidate.push_back(loc::MemRegionVal(VR));
}
// Invalidate designated regions using the batch invalidation API.
@@ -319,11 +359,41 @@ bool CallEvent::isCalled(const CallDescription &CD) const {
return false;
if (!CD.IsLookupDone) {
CD.IsLookupDone = true;
- CD.II = &getState()->getStateManager().getContext().Idents.get(CD.FuncName);
+ CD.II = &getState()->getStateManager().getContext().Idents.get(
+ CD.getFunctionName());
}
const IdentifierInfo *II = getCalleeIdentifier();
if (!II || II != CD.II)
return false;
+
+ const Decl *D = getDecl();
+ // If CallDescription provides prefix names, use them to improve matching
+ // accuracy.
+ if (CD.QualifiedName.size() > 1 && D) {
+ const DeclContext *Ctx = D->getDeclContext();
+ // See if we'll be able to match them all.
+ size_t NumUnmatched = CD.QualifiedName.size() - 1;
+ for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) {
+ if (NumUnmatched == 0)
+ break;
+
+ if (const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) {
+ if (ND->getName() == CD.QualifiedName[NumUnmatched - 1])
+ --NumUnmatched;
+ continue;
+ }
+
+ if (const auto *RD = dyn_cast<RecordDecl>(Ctx)) {
+ if (RD->getName() == CD.QualifiedName[NumUnmatched - 1])
+ --NumUnmatched;
+ continue;
+ }
+ }
+
+ if (NumUnmatched > 0)
+ return false;
+ }
+
return (CD.RequiredArgs == CallDescription::NoArgRequirement ||
CD.RequiredArgs == getNumArgs());
}
@@ -433,6 +503,14 @@ static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
const ParmVarDecl *ParamDecl = *I;
assert(ParamDecl && "Formal parameter has no decl?");
+ // TODO: Support allocator calls.
+ if (Call.getKind() != CE_CXXAllocator)
+ if (Call.isArgumentConstructedDirectly(Idx))
+ continue;
+
+ // TODO: Allocators should receive the correct size and possibly alignment,
+ // determined in compile-time but not represented as arg-expressions,
+ // which makes getArgSVal() fail and return UnknownVal.
SVal ArgVal = Call.getArgSVal(Idx);
if (!ArgVal.isUnknown()) {
Loc ParamLoc = SVB.makeLoc(MRMgr.getVarRegion(ParamDecl, CalleeCtx));
@@ -472,17 +550,18 @@ RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const {
return RuntimeDefinition(Decl);
}
- SubEngine *Engine = getState()->getStateManager().getOwningEngine();
- AnalyzerOptions &Opts = Engine->getAnalysisManager().options;
+ SubEngine &Engine = getState()->getStateManager().getOwningEngine();
+ AnalyzerOptions &Opts = Engine.getAnalysisManager().options;
// Try to get CTU definition only if CTUDir is provided.
- if (!Opts.naiveCTUEnabled())
+ if (!Opts.IsNaiveCTUEnabled)
return {};
cross_tu::CrossTranslationUnitContext &CTUCtx =
- *Engine->getCrossTranslationUnitContext();
+ *Engine.getCrossTranslationUnitContext();
llvm::Expected<const FunctionDecl *> CTUDeclOrError =
- CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+ CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir, Opts.CTUIndexName,
+ Opts.DisplayCTUProgress);
if (!CTUDeclOrError) {
handleAllErrors(CTUDeclOrError.takeError(),
@@ -758,7 +837,7 @@ const BlockDataRegion *BlockCall::getBlockRegion() const {
ArrayRef<ParmVarDecl*> BlockCall::parameters() const {
const BlockDecl *D = getDecl();
if (!D)
- return nullptr;
+ return None;
return D->parameters();
}
@@ -1008,7 +1087,7 @@ bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
Selector Sel) const {
assert(IDecl);
AnalysisManager &AMgr =
- getState()->getStateManager().getOwningEngine()->getAnalysisManager();
+ getState()->getStateManager().getOwningEngine().getAnalysisManager();
// If the class interface is declared inside the main file, assume it is not
// subcassed.
// TODO: It could actually be subclassed if the subclass is private as well.
@@ -1290,28 +1369,20 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
const Stmt *CallSite = CalleeCtx->getCallSite();
if (CallSite) {
- if (const CallExpr *CE = dyn_cast<CallExpr>(CallSite))
- return getSimpleCall(CE, State, CallerCtx);
-
- switch (CallSite->getStmtClass()) {
- case Stmt::CXXConstructExprClass:
- case Stmt::CXXTemporaryObjectExprClass: {
- SValBuilder &SVB = State->getStateManager().getSValBuilder();
- const auto *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl());
- Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx);
- SVal ThisVal = State->getSVal(ThisPtr);
-
- return getCXXConstructorCall(cast<CXXConstructExpr>(CallSite),
- ThisVal.getAsRegion(), State, CallerCtx);
- }
- case Stmt::CXXNewExprClass:
- return getCXXAllocatorCall(cast<CXXNewExpr>(CallSite), State, CallerCtx);
- case Stmt::ObjCMessageExprClass:
- return getObjCMethodCall(cast<ObjCMessageExpr>(CallSite),
- State, CallerCtx);
- default:
- llvm_unreachable("This is not an inlineable statement.");
- }
+ if (CallEventRef<> Out = getCall(CallSite, State, CallerCtx))
+ return Out;
+
+ // All other cases are handled by getCall.
+ assert(isa<CXXConstructExpr>(CallSite) &&
+ "This is not an inlineable statement");
+
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ const auto *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl());
+ Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx);
+ SVal ThisVal = State->getSVal(ThisPtr);
+
+ return getCXXConstructorCall(cast<CXXConstructExpr>(CallSite),
+ ThisVal.getAsRegion(), State, CallerCtx);
}
// Fall back to the CFG. The only thing we haven't handled yet is
@@ -1338,3 +1409,16 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
E.getAs<CFGBaseDtor>().hasValue(), State,
CallerCtx);
}
+
+CallEventRef<> CallEventManager::getCall(const Stmt *S, ProgramStateRef State,
+ const LocationContext *LC) {
+ if (const auto *CE = dyn_cast<CallExpr>(S)) {
+ return getSimpleCall(CE, State, LC);
+ } else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
+ return getCXXAllocatorCall(NE, State, LC);
+ } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
+ return getObjCMethodCall(ME, State, LC);
+ } else {
+ return nullptr;
+ }
+}
diff --git a/lib/StaticAnalyzer/Core/Checker.cpp b/lib/StaticAnalyzer/Core/Checker.cpp
index b422a8871983..72bfd84b40a3 100644
--- a/lib/StaticAnalyzer/Core/Checker.cpp
+++ b/lib/StaticAnalyzer/Core/Checker.cpp
@@ -17,6 +17,8 @@
using namespace clang;
using namespace ento;
+int ImplicitNullDerefEvent::Tag;
+
StringRef CheckerBase::getTagDescription() const {
return getCheckName().getName();
}
diff --git a/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index b9facffcc8b5..e73a22ae3981 100644
--- a/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -21,10 +21,10 @@ namespace ento {
// Recursively find any substatements containing macros
bool containsMacro(const Stmt *S) {
- if (S->getLocStart().isMacroID())
+ if (S->getBeginLoc().isMacroID())
return true;
- if (S->getLocEnd().isMacroID())
+ if (S->getEndLoc().isMacroID())
return true;
for (const Stmt *Child : S->children())
@@ -103,9 +103,9 @@ Nullability getNullabilityAnnotation(QualType Type) {
const auto *AttrType = Type->getAs<AttributedType>();
if (!AttrType)
return Nullability::Unspecified;
- if (AttrType->getAttrKind() == AttributedType::attr_nullable)
+ if (AttrType->getAttrKind() == attr::TypeNullable)
return Nullability::Nullable;
- else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
+ else if (AttrType->getAttrKind() == attr::TypeNonNull)
return Nullability::Nonnull;
return Nullability::Unspecified;
}
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 712872a15d8a..688c47e984cc 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -441,14 +441,13 @@ void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
ExplodedNode *Pred,
ExprEngine &Eng,
const ReturnStmt *RS) {
- // We define the builder outside of the loop bacause if at least one checkers
- // creates a sucsessor for Pred, we do not need to generate an
+ // We define the builder outside of the loop because if at least one checker
+ // creates a successor for Pred, we do not need to generate an
// autotransition for it.
NodeBuilder Bldr(Pred, Dst, BC);
for (const auto checkFn : EndFunctionCheckers) {
- const ProgramPoint &L = BlockEntrance(BC.Block,
- Pred->getLocationContext(),
- checkFn.Checker);
+ const ProgramPoint &L =
+ FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
checkFn(RS, C);
}
diff --git a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
deleted file mode 100644
index 645845ec2181..000000000000
--- a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-//===- CheckerRegistry.cpp - Maintains all available checkers -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cstddef>
-#include <tuple>
-
-using namespace clang;
-using namespace ento;
-
-static const char PackageSeparator = '.';
-
-using CheckerInfoSet = llvm::SetVector<const CheckerRegistry::CheckerInfo *>;
-
-static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
- const CheckerRegistry::CheckerInfo &b) {
- return a.FullName < b.FullName;
-}
-
-static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
- StringRef packageName) {
- // Does the checker's full name have the package as a prefix?
- if (!checker.FullName.startswith(packageName))
- return false;
-
- // Is the package actually just the name of a specific checker?
- if (checker.FullName.size() == packageName.size())
- return true;
-
- // Is the checker in the package (or a subpackage)?
- if (checker.FullName[packageName.size()] == PackageSeparator)
- return true;
-
- return false;
-}
-
-static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers,
- const llvm::StringMap<size_t> &packageSizes,
- CheckerOptInfo &opt, CheckerInfoSet &collected) {
- // Use a binary search to find the possible start of the package.
- CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.getName(), "");
- auto end = checkers.cend();
- auto i = std::lower_bound(checkers.cbegin(), end, packageInfo, checkerNameLT);
-
- // If we didn't even find a possible package, give up.
- if (i == end)
- return;
-
- // If what we found doesn't actually start the package, give up.
- if (!isInPackage(*i, opt.getName()))
- return;
-
- // There is at least one checker in the package; claim the option.
- opt.claim();
-
- // See how large the package is.
- // If the package doesn't exist, assume the option refers to a single checker.
- size_t size = 1;
- llvm::StringMap<size_t>::const_iterator packageSize =
- packageSizes.find(opt.getName());
- if (packageSize != packageSizes.end())
- size = packageSize->getValue();
-
- // Step through all the checkers in the package.
- for (auto checkEnd = i+size; i != checkEnd; ++i)
- if (opt.isEnabled())
- collected.insert(&*i);
- else
- collected.remove(&*i);
-}
-
-void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
- StringRef desc) {
- Checkers.push_back(CheckerInfo(fn, name, desc));
-
- // Record the presence of the checker in its packages.
- StringRef packageName, leafName;
- std::tie(packageName, leafName) = name.rsplit(PackageSeparator);
- while (!leafName.empty()) {
- Packages[packageName] += 1;
- std::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
- }
-}
-
-void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
- SmallVectorImpl<CheckerOptInfo> &opts) const {
- // Sort checkers for efficient collection.
- llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
-
- // Collect checkers enabled by the options.
- CheckerInfoSet enabledCheckers;
- for (auto &i : opts)
- collectCheckers(Checkers, Packages, i, enabledCheckers);
-
- // Initialize the CheckerManager with all enabled checkers.
- for (const auto *i :enabledCheckers) {
- checkerMgr.setCurrentCheckName(CheckName(i->FullName));
- i->Initialize(checkerMgr);
- }
-}
-
-void CheckerRegistry::validateCheckerOptions(const AnalyzerOptions &opts,
- DiagnosticsEngine &diags) const {
- for (const auto &config : opts.Config) {
- size_t pos = config.getKey().find(':');
- if (pos == StringRef::npos)
- continue;
-
- bool hasChecker = false;
- StringRef checkerName = config.getKey().substr(0, pos);
- for (const auto &checker : Checkers) {
- if (checker.FullName.startswith(checkerName) &&
- (checker.FullName.size() == pos || checker.FullName[pos] == '.')) {
- hasChecker = true;
- break;
- }
- }
- if (!hasChecker)
- diags.Report(diag::err_unknown_analyzer_checker) << checkerName;
- }
-}
-
-void CheckerRegistry::printHelp(raw_ostream &out,
- size_t maxNameChars) const {
- // FIXME: Alphabetical sort puts 'experimental' in the middle.
- // Would it be better to name it '~experimental' or something else
- // that's ASCIIbetically last?
- llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
-
- // FIXME: Print available packages.
-
- out << "CHECKERS:\n";
-
- // Find the maximum option length.
- size_t optionFieldWidth = 0;
- for (const auto &i : Checkers) {
- // Limit the amount of padding we are willing to give up for alignment.
- // Package.Name Description [Hidden]
- size_t nameLength = i.FullName.size();
- if (nameLength <= maxNameChars)
- optionFieldWidth = std::max(optionFieldWidth, nameLength);
- }
-
- const size_t initialPad = 2;
- for (const auto &i : Checkers) {
- out.indent(initialPad) << i.FullName;
-
- int pad = optionFieldWidth - i.FullName.size();
-
- // Break on long option names.
- if (pad < 0) {
- out << '\n';
- pad = optionFieldWidth + initialPad;
- }
- out.indent(pad + 2) << i.Desc;
-
- out << '\n';
- }
-}
-
-void CheckerRegistry::printList(
- raw_ostream &out, SmallVectorImpl<CheckerOptInfo> &opts) const {
- llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
-
- // Collect checkers enabled by the options.
- CheckerInfoSet enabledCheckers;
- for (auto &i : opts)
- collectCheckers(Checkers, Packages, i, enabledCheckers);
-
- for (const auto *i : enabledCheckers)
- out << i->FullName << '\n';
-}
diff --git a/lib/StaticAnalyzer/Core/CommonBugCategories.cpp b/lib/StaticAnalyzer/Core/CommonBugCategories.cpp
index 421dfa48c97b..cdae3ef0116a 100644
--- a/lib/StaticAnalyzer/Core/CommonBugCategories.cpp
+++ b/lib/StaticAnalyzer/Core/CommonBugCategories.cpp
@@ -14,8 +14,8 @@ namespace clang { namespace ento { namespace categories {
const char * const CoreFoundationObjectiveC = "Core Foundation/Objective-C";
const char * const LogicError = "Logic error";
-const char * const MemoryCoreFoundationObjectiveC =
- "Memory (Core Foundation/Objective-C)";
+const char * const MemoryRefCount =
+ "Memory (Core Foundation/Objective-C/OSObject)";
const char * const MemoryError = "Memory error";
const char * const UnixAPI = "Unix API";
}}}
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index c17b6aae37e2..196854cb09da 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -53,26 +53,28 @@ STATISTIC(NumPathsExplored,
// Core analysis engine.
//===----------------------------------------------------------------------===//
-static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts) {
+static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts,
+ SubEngine &subengine) {
switch (Opts.getExplorationStrategy()) {
- case AnalyzerOptions::ExplorationStrategyKind::DFS:
+ case ExplorationStrategyKind::DFS:
return WorkList::makeDFS();
- case AnalyzerOptions::ExplorationStrategyKind::BFS:
+ case ExplorationStrategyKind::BFS:
return WorkList::makeBFS();
- case AnalyzerOptions::ExplorationStrategyKind::BFSBlockDFSContents:
+ case ExplorationStrategyKind::BFSBlockDFSContents:
return WorkList::makeBFSBlockDFSContents();
- case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirst:
+ case ExplorationStrategyKind::UnexploredFirst:
return WorkList::makeUnexploredFirst();
- case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirstQueue:
+ case ExplorationStrategyKind::UnexploredFirstQueue:
return WorkList::makeUnexploredFirstPriorityQueue();
- default:
- llvm_unreachable("Unexpected case");
+ case ExplorationStrategyKind::UnexploredFirstLocationQueue:
+ return WorkList::makeUnexploredFirstPriorityLocationQueue();
}
+ llvm_unreachable("Unknown AnalyzerOptions::ExplorationStrategyKind");
}
CoreEngine::CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS,
AnalyzerOptions &Opts)
- : SubEng(subengine), WList(generateWorkList(Opts)),
+ : SubEng(subengine), WList(generateWorkList(Opts, subengine)),
BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {}
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
@@ -146,7 +148,7 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
dispatchWorkItem(Node, Node->getLocation(), WU);
}
- SubEng.processEndWorklist(hasWorkRemaining());
+ SubEng.processEndWorklist();
return WList->hasWork();
}
@@ -223,8 +225,12 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
// Get return statement..
const ReturnStmt *RS = nullptr;
if (!L.getSrc()->empty()) {
- if (Optional<CFGStmt> LastStmt = L.getSrc()->back().getAs<CFGStmt>()) {
+ CFGElement LastElement = L.getSrc()->back();
+ if (Optional<CFGStmt> LastStmt = LastElement.getAs<CFGStmt>()) {
RS = dyn_cast<ReturnStmt>(LastStmt->getStmt());
+ } else if (Optional<CFGAutomaticObjDtor> AutoDtor =
+ LastElement.getAs<CFGAutomaticObjDtor>()) {
+ RS = dyn_cast<ReturnStmt>(AutoDtor->getTriggerStmt());
}
}
@@ -392,8 +398,8 @@ void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
assert(B->succ_size() == 2);
NodeBuilderContext Ctx(*this, B, Pred);
ExplodedNodeSet Dst;
- SubEng.processBranch(Cond, Term, Ctx, Pred, Dst,
- *(B->succ_begin()), *(B->succ_begin()+1));
+ SubEng.processBranch(Cond, Ctx, Pred, Dst, *(B->succ_begin()),
+ *(B->succ_begin() + 1));
// Enqueue the new frontier onto the worklist.
enqueue(Dst);
}
diff --git a/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp b/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
index 530933916889..da7854df1def 100644
--- a/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
+++ b/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
@@ -77,5 +77,10 @@ void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out,
}
}
+void *ProgramStateTrait<DynamicTypeMap>::GDMIndex() {
+ static int index = 0;
+ return &index;
+}
+
} // namespace ento
} // namespace clang
diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp
index eccaee292c40..b45f93b6dde8 100644
--- a/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/lib/StaticAnalyzer/Core/Environment.cpp
@@ -44,6 +44,9 @@ static const Expr *ignoreTransparentExprs(const Expr *E) {
case Stmt::ExprWithCleanupsClass:
E = cast<ExprWithCleanups>(E)->getSubExpr();
break;
+ case Stmt::ConstantExprClass:
+ E = cast<ConstantExpr>(E)->getSubExpr();
+ break;
case Stmt::CXXBindTemporaryExprClass:
E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
break;
@@ -89,6 +92,7 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry,
case Stmt::ExprWithCleanupsClass:
case Stmt::GenericSelectionExprClass:
case Stmt::OpaqueValueExprClass:
+ case Stmt::ConstantExprClass:
case Stmt::ParenExprClass:
case Stmt::SubstNonTypeTemplateParmExprClass:
llvm_unreachable("Should have been handled by ignoreTransparentExprs");
@@ -189,11 +193,6 @@ EnvironmentManager::removeDeadBindings(Environment Env,
// Mark all symbols in the block expr's value live.
RSScaner.scan(X);
- continue;
- } else {
- SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
- for (; SI != SE; ++SI)
- SymReaper.maybeDead(*SI);
}
}
@@ -202,7 +201,9 @@ EnvironmentManager::removeDeadBindings(Environment Env,
}
void Environment::print(raw_ostream &Out, const char *NL,
- const char *Sep, const LocationContext *WithLC) const {
+ const char *Sep,
+ const ASTContext &Context,
+ const LocationContext *WithLC) const {
if (ExprBindings.isEmpty())
return;
@@ -222,10 +223,9 @@ void Environment::print(raw_ostream &Out, const char *NL,
assert(WithLC);
- LangOptions LO; // FIXME.
- PrintingPolicy PP(LO);
+ PrintingPolicy PP = Context.getPrintingPolicy();
- Out << NL << NL << "Expressions by stack frame:" << NL;
+ Out << NL << "Expressions by stack frame:" << NL;
WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
for (auto I : ExprBindings) {
if (I.first.getLocationContext() != LC)
@@ -234,8 +234,8 @@ void Environment::print(raw_ostream &Out, const char *NL,
const Stmt *S = I.first.getStmt();
assert(S != nullptr && "Expected non-null Stmt");
- Out << "(" << (const void *)LC << ',' << (const void *)S << ") ";
- S->printPretty(Out, nullptr, PP);
+ Out << "(LC" << LC->getID() << ", S" << S->getID(Context) << ") ";
+ S->printPretty(Out, /*Helper=*/nullptr, PP);
Out << " : " << I.second << NL;
}
});
diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index ece103d9d09a..d6bcbb96b55f 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -36,23 +36,6 @@ using namespace clang;
using namespace ento;
//===----------------------------------------------------------------------===//
-// Node auditing.
-//===----------------------------------------------------------------------===//
-
-// An out of line virtual method to provide a home for the class vtable.
-ExplodedNode::Auditor::~Auditor() = default;
-
-#ifndef NDEBUG
-static ExplodedNode::Auditor* NodeAuditor = nullptr;
-#endif
-
-void ExplodedNode::SetAuditor(ExplodedNode::Auditor* A) {
-#ifndef NDEBUG
- NodeAuditor = A;
-#endif
-}
-
-//===----------------------------------------------------------------------===//
// Cleanup.
//===----------------------------------------------------------------------===//
@@ -224,9 +207,6 @@ void ExplodedNode::addPredecessor(ExplodedNode *V, ExplodedGraph &G) {
assert(!V->isSink());
Preds.addNode(V, G);
V->Succs.addNode(this, G);
-#ifndef NDEBUG
- if (NodeAuditor) NodeAuditor->AddEdge(V, this);
-#endif
}
void ExplodedNode::NodeGroup::replaceNode(ExplodedNode *node) {
@@ -303,6 +283,16 @@ ExplodedNode * const *ExplodedNode::NodeGroup::end() const {
return Storage.getAddrOfPtr1() + 1;
}
+int64_t ExplodedNode::getID(ExplodedGraph *G) const {
+ return G->getAllocator().identifyKnownAlignedObject<ExplodedNode>(this);
+}
+
+bool ExplodedNode::isTrivial() const {
+ return pred_size() == 1 && succ_size() == 1 &&
+ getFirstPred()->getState()->getID() == getState()->getID() &&
+ getFirstPred()->succ_size() == 1;
+}
+
ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L,
ProgramStateRef State,
bool IsSink,
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 2b4bdd754fdb..151eef56fece 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -98,11 +98,12 @@ STATISTIC(NumMaxBlockCountReachedInInlined,
STATISTIC(NumTimesRetriedWithoutInlining,
"The # of times we re-evaluated a call without inlining");
-
//===----------------------------------------------------------------------===//
// Internal program state traits.
//===----------------------------------------------------------------------===//
+namespace {
+
// When modeling a C++ constructor, for a variety of reasons we need to track
// the location of the object for the duration of its ConstructionContext.
// ObjectsUnderConstruction maps statements within the construction context
@@ -137,9 +138,17 @@ public:
const ConstructionContextItem &getItem() const { return Impl.first; }
const LocationContext *getLocationContext() const { return Impl.second; }
+ ASTContext &getASTContext() const {
+ return getLocationContext()->getDecl()->getASTContext();
+ }
+
void print(llvm::raw_ostream &OS, PrinterHelper *Helper, PrintingPolicy &PP) {
- OS << '(' << getLocationContext() << ',' << getAnyASTNodePtr() << ','
- << getItem().getKindAsString();
+ OS << "(LC" << getLocationContext()->getID() << ',';
+ if (const Stmt *S = getItem().getStmtOrNull())
+ OS << 'S' << S->getID(getASTContext());
+ else
+ OS << 'I' << getItem().getCXXCtorInitializer()->getID(getASTContext());
+ OS << ',' << getItem().getKindAsString();
if (getItem().getKind() == ConstructionContextItem::ArgumentKind)
OS << " #" << getItem().getIndex();
OS << ") ";
@@ -164,6 +173,7 @@ public:
return Impl < RHS.Impl;
}
};
+} // namespace
typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
ObjectsUnderConstructionMap;
@@ -177,7 +187,7 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,
static const char* TagProviderName = "ExprEngine";
ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
- AnalysisManager &mgr, bool gcEnabled,
+ AnalysisManager &mgr,
SetOfConstDecls *VisitedCalleesIn,
FunctionSummariesTy *FS,
InliningModes HowToInlineIn)
@@ -189,11 +199,11 @@ ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
this),
SymMgr(StateMgr.getSymbolManager()),
svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
- ObjCGCEnabled(gcEnabled), BR(mgr, *this),
+ BR(mgr, *this),
VisitedCallees(VisitedCalleesIn), HowToInline(HowToInlineIn) {
- unsigned TrimInterval = mgr.options.getGraphTrimInterval();
+ unsigned TrimInterval = mgr.options.GraphTrimInterval;
if (TrimInterval != 0) {
- // Enable eager node reclaimation when constructing the ExplodedGraph.
+ // Enable eager node reclamation when constructing the ExplodedGraph.
G.enableNodeReclamation(TrimInterval);
}
}
@@ -283,11 +293,10 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
return state;
}
-ProgramStateRef
-ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
- const LocationContext *LC,
- const Expr *InitWithAdjustments,
- const Expr *Result) {
+ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
+ ProgramStateRef State, const LocationContext *LC,
+ const Expr *InitWithAdjustments, const Expr *Result,
+ const SubRegion **OutRegionWithAdjustments) {
// FIXME: This function is a hack that works around the quirky AST
// we're often having with respect to C++ temporaries. If only we modelled
// the actual execution order of statements properly in the CFG,
@@ -297,8 +306,11 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
if (!Result) {
// If we don't have an explicit result expression, we're in "if needed"
// mode. Only create a region if the current value is a NonLoc.
- if (!InitValWithAdjustments.getAs<NonLoc>())
+ if (!InitValWithAdjustments.getAs<NonLoc>()) {
+ if (OutRegionWithAdjustments)
+ *OutRegionWithAdjustments = nullptr;
return State;
+ }
Result = InitWithAdjustments;
} else {
// We need to create a region no matter what. For sanity, make sure we don't
@@ -418,11 +430,17 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
// The result expression would now point to the correct sub-region of the
// newly created temporary region. Do this last in order to getSVal of Init
// correctly in case (Result == Init).
- State = State->BindExpr(Result, LC, Reg);
+ if (Result->isGLValue()) {
+ State = State->BindExpr(Result, LC, Reg);
+ } else {
+ State = State->BindExpr(Result, LC, InitValWithAdjustments);
+ }
// Notify checkers once for two bindLoc()s.
State = processRegionChange(State, TR, LC);
+ if (OutRegionWithAdjustments)
+ *OutRegionWithAdjustments = cast<SubRegion>(Reg.getAsRegion());
return State;
}
@@ -523,7 +541,6 @@ ExprEngine::processRegionChanges(ProgramStateRef state,
static void printObjectsUnderConstructionForContext(raw_ostream &Out,
ProgramStateRef State,
const char *NL,
- const char *Sep,
const LocationContext *LC) {
PrintingPolicy PP =
LC->getAnalysisDeclContext()->getASTContext().getPrintingPolicy();
@@ -545,7 +562,7 @@ void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
Out << Sep << "Objects under construction:" << NL;
LCtx->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
- printObjectsUnderConstructionForContext(Out, State, NL, Sep, LC);
+ printObjectsUnderConstructionForContext(Out, State, NL, LC);
});
}
}
@@ -553,7 +570,7 @@ void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep);
}
-void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
+void ExprEngine::processEndWorklist() {
getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
}
@@ -666,44 +683,35 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
// Process any special transfer function for dead symbols.
// A tag to track convenience transitions, which can be removed at cleanup.
static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");
- if (!SymReaper.hasDeadSymbols()) {
- // Generate a CleanedNode that has the environment and store cleaned
- // up. Since no symbols are dead, we can optimize and not clean out
- // the constraint manager.
- StmtNodeBuilder Bldr(Pred, Out, *currBldrCtx);
- Bldr.generateNode(DiagnosticStmt, Pred, CleanedState, &cleanupTag, K);
-
- } else {
- // Call checkers with the non-cleaned state so that they could query the
- // values of the soon to be dead symbols.
- ExplodedNodeSet CheckedSet;
- getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
- DiagnosticStmt, *this, K);
-
- // For each node in CheckedSet, generate CleanedNodes that have the
- // environment, the store, and the constraints cleaned up but have the
- // user-supplied states as the predecessors.
- StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);
- for (const auto I : CheckedSet) {
- ProgramStateRef CheckerState = I->getState();
-
- // The constraint manager has not been cleaned up yet, so clean up now.
- CheckerState = getConstraintManager().removeDeadBindings(CheckerState,
- SymReaper);
-
- assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
- "Checkers are not allowed to modify the Environment as a part of "
- "checkDeadSymbols processing.");
- assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
- "Checkers are not allowed to modify the Store as a part of "
- "checkDeadSymbols processing.");
-
- // Create a state based on CleanedState with CheckerState GDM and
- // generate a transition to that state.
- ProgramStateRef CleanedCheckerSt =
+ // Call checkers with the non-cleaned state so that they could query the
+ // values of the soon to be dead symbols.
+ ExplodedNodeSet CheckedSet;
+ getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
+ DiagnosticStmt, *this, K);
+
+ // For each node in CheckedSet, generate CleanedNodes that have the
+ // environment, the store, and the constraints cleaned up but have the
+ // user-supplied states as the predecessors.
+ StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);
+ for (const auto I : CheckedSet) {
+ ProgramStateRef CheckerState = I->getState();
+
+ // The constraint manager has not been cleaned up yet, so clean up now.
+ CheckerState =
+ getConstraintManager().removeDeadBindings(CheckerState, SymReaper);
+
+ assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
+ "Checkers are not allowed to modify the Environment as a part of "
+ "checkDeadSymbols processing.");
+ assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
+ "Checkers are not allowed to modify the Store as a part of "
+ "checkDeadSymbols processing.");
+
+ // Create a state based on CleanedState with CheckerState GDM and
+ // generate a transition to that state.
+ ProgramStateRef CleanedCheckerSt =
StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
- Bldr.generateNode(DiagnosticStmt, I, CleanedCheckerSt, &cleanupTag, K);
- }
+ Bldr.generateNode(DiagnosticStmt, I, CleanedCheckerSt, &cleanupTag, K);
}
}
@@ -712,7 +720,7 @@ void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
G.reclaimRecentlyAllocatedNodes();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- currStmt->getLocStart(),
+ currStmt->getBeginLoc(),
"Error evaluating statement");
// Remove dead bindings and symbols.
@@ -739,14 +747,14 @@ void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- S->getLocStart(),
+ S->getBeginLoc(),
"Error evaluating end of the loop");
ExplodedNodeSet Dst;
Dst.Add(Pred);
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
ProgramStateRef NewState = Pred->getState();
- if(AMgr.options.shouldUnrollLoops())
+ if(AMgr.options.ShouldUnrollLoops)
NewState = processLoopEnd(S, NewState);
LoopExit PP(S, Pred->getLocationContext());
@@ -878,12 +886,12 @@ void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
// TODO: We're not evaluating allocators for all cases just yet as
// we're not handling the return value correctly, which causes false
// positives when the alpha.cplusplus.NewDeleteLeaks check is on.
- if (Opts.mayInlineCXXAllocator())
+ if (Opts.MayInlineCXXAllocator)
VisitCXXNewAllocatorCall(NE, Pred, Dst);
else {
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
const LocationContext *LCtx = Pred->getLocationContext();
- PostImplicitCall PP(NE->getOperatorNew(), NE->getLocStart(), LCtx);
+ PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx);
Bldr.generateNode(PP, Pred->getState(), Pred);
}
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
@@ -940,7 +948,7 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();
const CXXDestructorDecl *Dtor = RD->getDestructor();
- PostImplicitCall PP(Dtor, DE->getLocStart(), LCtx);
+ PostImplicitCall PP(Dtor, DE->getBeginLoc(), LCtx);
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
Bldr.generateNode(PP, Pred->getState(), Pred);
return;
@@ -1025,13 +1033,13 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
MR = V->getAsRegion();
}
- // If copy elision has occured, and the constructor corresponding to the
+ // If copy elision has occurred, and the constructor corresponding to the
// destructor was elided, we need to skip the destructor as well.
if (isDestructorElided(State, BTE, LC)) {
State = cleanupElidedDestructor(State, BTE, LC);
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
PostImplicitCall PP(D.getDestructorDecl(getContext()),
- D.getBindTemporaryExpr()->getLocStart(),
+ D.getBindTemporaryExpr()->getBeginLoc(),
Pred->getLocationContext());
Bldr.generateNode(PP, State, Pred);
return;
@@ -1093,7 +1101,7 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
// This is a fallback solution in case we didn't have a construction
// context when we were constructing the temporary. Otherwise the map should
// have been populated there.
- if (!getAnalysisManager().options.includeTemporaryDtorsInCFG()) {
+ if (!getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {
// In case we don't have temporary destructors in the CFG, do not mark
// the initialization - we would otherwise never clean it up.
Dst = PreVisit;
@@ -1120,7 +1128,7 @@ ProgramStateRef ExprEngine::escapeValue(ProgramStateRef State, SVal V,
InvalidatedSymbols Symbols;
public:
- explicit CollectReachableSymbolsCallback(ProgramStateRef State) {}
+ explicit CollectReachableSymbolsCallback(ProgramStateRef) {}
const InvalidatedSymbols &getSymbols() const { return Symbols; }
@@ -1139,8 +1147,7 @@ ProgramStateRef ExprEngine::escapeValue(ProgramStateRef State, SVal V,
void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet &DstTop) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- S->getLocStart(),
- "Error evaluating statement");
+ S->getBeginLoc(), "Error evaluating statement");
ExplodedNodeSet Dst;
StmtNodeBuilder Bldr(Pred, DstTop, *currBldrCtx);
@@ -1274,6 +1281,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.addNodes(Dst);
break;
+ case Expr::ConstantExprClass:
case Stmt::ExprWithCleanupsClass:
// Handled due to fully linearised CFG.
break;
@@ -1454,7 +1462,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break;
case Stmt::LambdaExprClass:
- if (AMgr.options.shouldInlineLambdas()) {
+ if (AMgr.options.ShouldInlineLambdas) {
Bldr.takeNodes(Pred);
VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
@@ -1483,7 +1491,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.takeNodes(Pred);
- if (AMgr.options.eagerlyAssumeBinOpBifurcation &&
+ if (AMgr.options.ShouldEagerlyAssume &&
(B->isRelationalOp() || B->isEqualityOp())) {
ExplodedNodeSet Tmp;
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
@@ -1747,7 +1755,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::UnaryOperatorClass: {
Bldr.takeNodes(Pred);
const auto *U = cast<UnaryOperator>(S);
- if (AMgr.options.eagerlyAssumeBinOpBifurcation && (U->getOpcode() == UO_LNot)) {
+ if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
ExplodedNodeSet Tmp;
VisitUnaryOperator(U, Pred, Tmp);
evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
@@ -1848,7 +1856,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
// If we reach a loop which has a known bound (and meets
// other constraints) then consider completely unrolling it.
- if(AMgr.options.shouldUnrollLoops()) {
+ if(AMgr.options.ShouldUnrollLoops) {
unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
if (Term) {
@@ -1870,7 +1878,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
// maximum number of times, widen the loop.
unsigned int BlockCount = nodeBuilder.getContext().blockCount();
if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
- AMgr.options.shouldWidenLoops()) {
+ AMgr.options.ShouldWidenLoops) {
const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
if (!(Term &&
(isa<ForStmt>(Term) || isa<WhileStmt>(Term) || isa<DoStmt>(Term))))
@@ -1923,8 +1931,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
/// integers that promote their values (which are currently not tracked well).
/// This function returns the SVal bound to Condition->IgnoreCasts if all the
// cast(s) did was sign-extend the original value.
-static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
- ProgramStateRef state,
+static SVal RecoverCastedSymbol(ProgramStateRef state,
const Stmt *Condition,
const LocationContext *LCtx,
ASTContext &Ctx) {
@@ -2021,7 +2028,7 @@ static const Stmt *ResolveCondition(const Stmt *Condition,
llvm_unreachable("could not resolve condition");
}
-void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
+void ExprEngine::processBranch(const Stmt *Condition,
NodeBuilderContext& BldCtx,
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
@@ -2046,7 +2053,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
Condition = ResolveCondition(Condition, BldCtx.getBlock());
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- Condition->getLocStart(),
+ Condition->getBeginLoc(),
"Error evaluating branch");
ExplodedNodeSet CheckersOutSet;
@@ -2072,8 +2079,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
// integers that promote their values are currently not tracked well.
// If 'Condition' is such an expression, try and recover the
// underlying value and use that instead.
- SVal recovered = RecoverCastedSymbol(getStateManager(),
- PrevState, Condition,
+ SVal recovered = RecoverCastedSymbol(PrevState, Condition,
PredI->getLocationContext(),
getContext());
@@ -2200,17 +2206,21 @@ void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred,
const ReturnStmt *RS) {
+ ProgramStateRef State = Pred->getState();
+
+ if (!Pred->getStackFrame()->inTopFrame())
+ State = finishArgumentConstruction(
+ State, *getStateManager().getCallEventManager().getCaller(
+ Pred->getStackFrame(), Pred->getState()));
+
// FIXME: We currently cannot assert that temporaries are clear, because
// lifetime extended temporaries are not always modelled correctly. In some
// cases when we materialize the temporary, we do
// createTemporaryRegionIfNeeded(), and the region changes, and also the
// respective destructor becomes automatic from temporary. So for now clean up
- // the state manually before asserting. Ideally, the code above the assertion
- // should go away, but the assertion should remain.
+ // the state manually before asserting. Ideally, this braced block of code
+ // should go away.
{
- ExplodedNodeSet CleanUpObjects;
- NodeBuilder Bldr(Pred, CleanUpObjects, BC);
- ProgramStateRef State = Pred->getState();
const LocationContext *FromLC = Pred->getLocationContext();
const LocationContext *ToLC = FromLC->getStackFrame()->getParent();
const LocationContext *LC = FromLC;
@@ -2229,15 +2239,20 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
}
LC = LC->getParent();
}
- if (State != Pred->getState()) {
- Pred = Bldr.generateNode(Pred->getLocation(), State, Pred);
- if (!Pred) {
- // The node with clean temporaries already exists. We might have reached
- // it on a path on which we initialize different temporaries.
- return;
- }
+ }
+
+ // Perform the transition with cleanups.
+ if (State != Pred->getState()) {
+ ExplodedNodeSet PostCleanup;
+ NodeBuilder Bldr(Pred, PostCleanup, BC);
+ Pred = Bldr.generateNode(Pred->getLocation(), State, Pred);
+ if (!Pred) {
+ // The node with clean temporaries already exists. We might have reached
+ // it on a path on which we initialize different temporaries.
+ return;
}
}
+
assert(areAllObjectsFullyConstructed(Pred->getState(),
Pred->getLocationContext(),
Pred->getStackFrame()->getParent()));
@@ -2364,7 +2379,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
Optional<std::pair<SVal, QualType>> VInfo;
- if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
+ if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
MD->getParent()->isLambda()) {
// Lookup the field of the lambda.
@@ -2524,8 +2539,12 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
}
// Handle regular struct fields / member variables.
- state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
- SVal baseExprVal = state->getSVal(BaseExpr, LCtx);
+ const SubRegion *MR = nullptr;
+ state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
+ /*Result=*/nullptr,
+ /*OutRegionWithAdjustments=*/&MR);
+ SVal baseExprVal =
+ MR ? loc::MemRegionVal(MR) : state->getSVal(BaseExpr, LCtx);
const auto *field = cast<FieldDecl>(Member);
SVal L = state->getLValue(field, baseExprVal);
@@ -2645,7 +2664,6 @@ ProgramStateRef
ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) {
if (!Invalidated || Invalidated->empty())
@@ -2755,7 +2773,7 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
// Evaluate the location (checks for bad dereferences).
ExplodedNodeSet Tmp;
- evalLocation(Tmp, AssignE, LocationE, Pred, state, location, tag, false);
+ evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);
if (Tmp.empty())
return;
@@ -2780,7 +2798,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
assert(BoundEx);
// Evaluate the location (checks for bad dereferences).
ExplodedNodeSet Tmp;
- evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, tag, true);
+ evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);
if (Tmp.empty())
return;
@@ -2811,7 +2829,6 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
ExplodedNode *Pred,
ProgramStateRef state,
SVal location,
- const ProgramPointTag *tag,
bool isLoad) {
StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);
// Early checks for performance reason.
@@ -2927,211 +2944,108 @@ void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
//===----------------------------------------------------------------------===//
#ifndef NDEBUG
-static ExprEngine* GraphPrintCheckerState;
-static SourceManager* GraphPrintSourceManager;
-
namespace llvm {
template<>
-struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
+struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
- // FIXME: Since we do not cache error nodes in ExprEngine now, this does not
- // work.
- static std::string getNodeAttributes(const ExplodedNode *N, void*) {
- return {};
- }
-
- // De-duplicate some source location pretty-printing.
- static void printLocation(raw_ostream &Out, SourceLocation SLoc) {
- if (SLoc.isFileID()) {
- Out << "\\lline="
- << GraphPrintSourceManager->getExpansionLineNumber(SLoc)
- << " col="
- << GraphPrintSourceManager->getExpansionColumnNumber(SLoc)
- << "\\l";
- }
- }
-
- static std::string getNodeLabel(const ExplodedNode *N, void*){
- std::string sbuf;
- llvm::raw_string_ostream Out(sbuf);
-
- // Program Location.
- ProgramPoint Loc = N->getLocation();
-
- switch (Loc.getKind()) {
- case ProgramPoint::BlockEntranceKind:
- Out << "Block Entrance: B"
- << Loc.castAs<BlockEntrance>().getBlock()->getBlockID();
- break;
-
- case ProgramPoint::BlockExitKind:
- assert(false);
- break;
-
- case ProgramPoint::CallEnterKind:
- Out << "CallEnter";
- break;
-
- case ProgramPoint::CallExitBeginKind:
- Out << "CallExitBegin";
- break;
+ static bool nodeHasBugReport(const ExplodedNode *N) {
+ BugReporter &BR = static_cast<ExprEngine &>(
+ N->getState()->getStateManager().getOwningEngine()).getBugReporter();
- case ProgramPoint::CallExitEndKind:
- Out << "CallExitEnd";
- break;
-
- case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
- Out << "PostStmtPurgeDeadSymbols";
- break;
-
- case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
- Out << "PreStmtPurgeDeadSymbols";
- break;
-
- case ProgramPoint::EpsilonKind:
- Out << "Epsilon Point";
- break;
+ const auto EQClasses =
+ llvm::make_range(BR.EQClasses_begin(), BR.EQClasses_end());
- case ProgramPoint::LoopExitKind: {
- LoopExit LE = Loc.castAs<LoopExit>();
- Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName();
- break;
+ for (const auto &EQ : EQClasses) {
+ for (const BugReport &Report : EQ) {
+ if (Report.getErrorNode() == N)
+ return true;
}
+ }
+ return false;
+ }
- case ProgramPoint::PreImplicitCallKind: {
- ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>();
- Out << "PreCall: ";
-
- // FIXME: Get proper printing options.
- PC.getDecl()->print(Out, LangOptions());
- printLocation(Out, PC.getLocation());
- break;
- }
-
- case ProgramPoint::PostImplicitCallKind: {
- ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>();
- Out << "PostCall: ";
-
- // FIXME: Get proper printing options.
- PC.getDecl()->print(Out, LangOptions());
- printLocation(Out, PC.getLocation());
- break;
- }
-
- case ProgramPoint::PostInitializerKind: {
- Out << "PostInitializer: ";
- const CXXCtorInitializer *Init =
- Loc.castAs<PostInitializer>().getInitializer();
- if (const FieldDecl *FD = Init->getAnyMember())
- Out << *FD;
- else {
- QualType Ty = Init->getTypeSourceInfo()->getType();
- Ty = Ty.getLocalUnqualifiedType();
- LangOptions LO; // FIXME.
- Ty.print(Out, LO);
- }
- break;
- }
-
- case ProgramPoint::BlockEdgeKind: {
- const BlockEdge &E = Loc.castAs<BlockEdge>();
- Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
- << E.getDst()->getBlockID() << ')';
-
- if (const Stmt *T = E.getSrc()->getTerminator()) {
- SourceLocation SLoc = T->getLocStart();
-
- Out << "\\|Terminator: ";
- LangOptions LO; // FIXME.
- E.getSrc()->printTerminator(Out, LO);
-
- if (SLoc.isFileID()) {
- Out << "\\lline="
- << GraphPrintSourceManager->getExpansionLineNumber(SLoc)
- << " col="
- << GraphPrintSourceManager->getExpansionColumnNumber(SLoc);
- }
-
- if (isa<SwitchStmt>(T)) {
- const Stmt *Label = E.getDst()->getLabel();
-
- if (Label) {
- if (const auto *C = dyn_cast<CaseStmt>(Label)) {
- Out << "\\lcase ";
- LangOptions LO; // FIXME.
- if (C->getLHS())
- C->getLHS()->printPretty(Out, nullptr, PrintingPolicy(LO));
-
- if (const Stmt *RHS = C->getRHS()) {
- Out << " .. ";
- RHS->printPretty(Out, nullptr, PrintingPolicy(LO));
- }
-
- Out << ":";
- }
- else {
- assert(isa<DefaultStmt>(Label));
- Out << "\\ldefault:";
- }
- }
- else
- Out << "\\l(implicit) default:";
- }
- else if (isa<IndirectGotoStmt>(T)) {
- // FIXME
- }
- else {
- Out << "\\lCondition: ";
- if (*E.getSrc()->succ_begin() == E.getDst())
- Out << "true";
- else
- Out << "false";
- }
-
- Out << "\\l";
- }
+ /// \p PreCallback: callback before break.
+ /// \p PostCallback: callback after break.
+ /// \p Stop: stop iteration if returns {@code true}
+ /// \return Whether {@code Stop} ever returned {@code true}.
+ static bool traverseHiddenNodes(
+ const ExplodedNode *N,
+ llvm::function_ref<void(const ExplodedNode *)> PreCallback,
+ llvm::function_ref<void(const ExplodedNode *)> PostCallback,
+ llvm::function_ref<bool(const ExplodedNode *)> Stop) {
+ const ExplodedNode *FirstHiddenNode = N;
+ while (FirstHiddenNode->pred_size() == 1 &&
+ isNodeHidden(*FirstHiddenNode->pred_begin())) {
+ FirstHiddenNode = *FirstHiddenNode->pred_begin();
+ }
+ const ExplodedNode *OtherNode = FirstHiddenNode;
+ while (true) {
+ PreCallback(OtherNode);
+ if (Stop(OtherNode))
+ return true;
+ if (OtherNode == N)
break;
- }
+ PostCallback(OtherNode);
- default: {
- const Stmt *S = Loc.castAs<StmtPoint>().getStmt();
- assert(S != nullptr && "Expecting non-null Stmt");
-
- Out << S->getStmtClassName() << ' ' << (const void*) S << ' ';
- LangOptions LO; // FIXME.
- S->printPretty(Out, nullptr, PrintingPolicy(LO));
- printLocation(Out, S->getLocStart());
-
- if (Loc.getAs<PreStmt>())
- Out << "\\lPreStmt\\l;";
- else if (Loc.getAs<PostLoad>())
- Out << "\\lPostLoad\\l;";
- else if (Loc.getAs<PostStore>())
- Out << "\\lPostStore\\l";
- else if (Loc.getAs<PostLValue>())
- Out << "\\lPostLValue\\l";
- else if (Loc.getAs<PostAllocatorCall>())
- Out << "\\lPostAllocatorCall\\l";
+ OtherNode = *OtherNode->succ_begin();
+ }
+ return false;
+ }
- break;
- }
+ static std::string getNodeAttributes(const ExplodedNode *N,
+ ExplodedGraph *) {
+ SmallVector<StringRef, 10> Out;
+ auto Noop = [](const ExplodedNode*){};
+ if (traverseHiddenNodes(N, Noop, Noop, &nodeHasBugReport)) {
+ Out.push_back("style=filled");
+ Out.push_back("fillcolor=red");
}
- ProgramStateRef state = N->getState();
- Out << "\\|StateID: " << (const void*) state.get()
- << " NodeID: " << (const void*) N << "\\|";
+ if (traverseHiddenNodes(N, Noop, Noop,
+ [](const ExplodedNode *C) { return C->isSink(); }))
+ Out.push_back("color=blue");
+ return llvm::join(Out, ",");
+ }
- state->printDOT(Out, N->getLocationContext());
+ static bool isNodeHidden(const ExplodedNode *N) {
+ return N->isTrivial();
+ }
- Out << "\\l";
+ static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
+ std::string sbuf;
+ llvm::raw_string_ostream Out(sbuf);
- if (const ProgramPointTag *tag = Loc.getTag()) {
- Out << "\\|Tag: " << tag->getTagDescription();
- Out << "\\l";
- }
+ ProgramStateRef State = N->getState();
+
+ // Dump program point for all the previously skipped nodes.
+ traverseHiddenNodes(
+ N,
+ [&](const ExplodedNode *OtherNode) {
+ OtherNode->getLocation().print(/*CR=*/"\\l", Out);
+ if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
+ Out << "\\lTag:" << Tag->getTagDescription();
+ if (N->isSink())
+ Out << "\\lNode is sink\\l";
+ if (nodeHasBugReport(N))
+ Out << "\\lBug report attached\\l";
+ },
+ [&](const ExplodedNode *) { Out << "\\l--------\\l"; },
+ [&](const ExplodedNode *) { return false; });
+
+ Out << "\\l\\|";
+
+ Out << "StateID: ST" << State->getID() << ", NodeID: N" << N->getID(G)
+ << " <" << (const void *)N << ">\\|";
+
+ bool SameAsAllPredecessors =
+ std::all_of(N->pred_begin(), N->pred_end(), [&](const ExplodedNode *P) {
+ return P->getState() == State;
+ });
+ if (!SameAsAllPredecessors)
+ State->printDOT(Out, N->getLocationContext());
return Out.str();
}
};
@@ -3141,48 +3055,61 @@ struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
void ExprEngine::ViewGraph(bool trim) {
#ifndef NDEBUG
+ std::string Filename = DumpGraph(trim);
+ llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
+#endif
+ llvm::errs() << "Warning: viewing graph requires assertions" << "\n";
+}
+
+
+void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode*> Nodes) {
+#ifndef NDEBUG
+ std::string Filename = DumpGraph(Nodes);
+ llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
+#endif
+ llvm::errs() << "Warning: viewing graph requires assertions" << "\n";
+}
+
+std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) {
+#ifndef NDEBUG
if (trim) {
std::vector<const ExplodedNode *> Src;
- // Flush any outstanding reports to make sure we cover all the nodes.
- // This does not cause them to get displayed.
- for (const auto I : BR)
- const_cast<BugType *>(I)->FlushReports(BR);
-
// Iterate through the reports and get their nodes.
for (BugReporter::EQClasses_iterator
EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
const auto *N = const_cast<ExplodedNode *>(EI->begin()->getErrorNode());
if (N) Src.push_back(N);
}
-
- ViewGraph(Src);
- }
- else {
- GraphPrintCheckerState = this;
- GraphPrintSourceManager = &getContext().getSourceManager();
-
- llvm::ViewGraph(*G.roots_begin(), "ExprEngine");
-
- GraphPrintCheckerState = nullptr;
- GraphPrintSourceManager = nullptr;
+ return DumpGraph(Src, Filename);
+ } else {
+ return llvm::WriteGraph(&G, "ExprEngine", /*ShortNames=*/false,
+ /*Title=*/"Exploded Graph", /*Filename=*/Filename);
}
#endif
+ llvm::errs() << "Warning: dumping graph requires assertions" << "\n";
+ return "";
}
-void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode*> Nodes) {
+std::string ExprEngine::DumpGraph(ArrayRef<const ExplodedNode*> Nodes,
+ StringRef Filename) {
#ifndef NDEBUG
- GraphPrintCheckerState = this;
- GraphPrintSourceManager = &getContext().getSourceManager();
-
std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
- if (!TrimmedG.get())
+ if (!TrimmedG.get()) {
llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
- else
- llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedExprEngine");
-
- GraphPrintCheckerState = nullptr;
- GraphPrintSourceManager = nullptr;
+ } else {
+ return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",
+ /*ShortNames=*/false,
+ /*Title=*/"Trimmed Exploded Graph",
+ /*Filename=*/Filename);
+ }
#endif
+ llvm::errs() << "Warning: dumping graph requires assertions" << "\n";
+ return "";
+}
+
+void *ProgramStateTrait<ReplayWithoutInlining>::GDMIndex() {
+ static int index = 0;
+ return &index;
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 61b7a290e42a..b980628878e9 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -412,10 +412,11 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
- case CK_ZeroToOCLEvent:
- case CK_ZeroToOCLQueue:
+ case CK_ZeroToOCLOpaqueType:
case CK_IntToOCLSampler:
- case CK_LValueBitCast: {
+ case CK_LValueBitCast:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean: {
state =
handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
continue;
@@ -809,8 +810,9 @@ void ExprEngine::
VisitOffsetOfExpr(const OffsetOfExpr *OOE,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
- APSInt IV;
- if (OOE->EvaluateAsInt(IV, getContext())) {
+ Expr::EvalResult Result;
+ if (OOE->EvaluateAsInt(Result, getContext())) {
+ APSInt IV = Result.Val.getInt();
assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
assert(OOE->getType()->isBuiltinType());
assert(OOE->getType()->getAs<BuiltinType>()->isInteger());
@@ -956,7 +958,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
}
case UO_Plus:
assert(!U->isGLValue());
- // FALL-THROUGH.
+ LLVM_FALLTHROUGH;
case UO_Deref:
case UO_Extension: {
handleUOExtension(I, U, Bldr);
@@ -1050,7 +1052,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Perform the store, so that the uninitialized value detection happens.
Bldr.takeNodes(*I);
ExplodedNodeSet Dst3;
- evalStore(Dst3, U, U, *I, state, loc, V2_untested);
+ evalStore(Dst3, U, Ex, *I, state, loc, V2_untested);
Bldr.addNodes(Dst3);
continue;
@@ -1118,7 +1120,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Perform the store.
Bldr.takeNodes(*I);
ExplodedNodeSet Dst3;
- evalStore(Dst3, U, U, *I, state, loc, Result);
+ evalStore(Dst3, U, Ex, *I, state, loc, Result);
Bldr.addNodes(Dst3);
}
Dst.insert(Dst2);
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 4f1766a813c6..6445b9df5a58 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -113,7 +113,9 @@ SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue,
std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
const ConstructionContext *CC, EvalCallOptions &CallOpts) {
- MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
+ SValBuilder &SVB = getSValBuilder();
+ MemRegionManager &MRMgr = SVB.getRegionManager();
+ ASTContext &ACtx = SVB.getContext();
// See if we're constructing an existing region by looking at the
// current construction context.
@@ -139,7 +141,7 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
assert(Init->isAnyMemberInitializer());
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
Loc ThisPtr =
- getSValBuilder().getCXXThis(CurCtor, LCtx->getStackFrame());
+ SVB.getCXXThis(CurCtor, LCtx->getStackFrame());
SVal ThisVal = State->getSVal(ThisPtr);
const ValueDecl *Field;
@@ -159,7 +161,7 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
return std::make_pair(State, FieldVal);
}
case ConstructionContext::NewAllocatedObjectKind: {
- if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
const auto *NE = NECC->getCXXNewExpr();
SVal V = *getObjectUnderConstruction(State, NE, LCtx);
@@ -199,18 +201,31 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
RTC->getConstructionContext(), CallOpts);
} else {
- // We are on the top frame of the analysis.
- // TODO: What exactly happens when we are? Does the temporary object
- // live long enough in the region store in this case? Would checkers
- // think that this object immediately goes out of scope?
- CallOpts.IsTemporaryCtorOrDtor = true;
- SVal V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
+ // We are on the top frame of the analysis. We do not know where is the
+ // object returned to. Conjure a symbolic region for the return value.
+ // TODO: We probably need a new MemRegion kind to represent the storage
+ // of that SymbolicRegion, so that we cound produce a fancy symbol
+ // instead of an anonymous conjured symbol.
+ // TODO: Do we need to track the region to avoid having it dead
+ // too early? It does die too early, at least in C++17, but because
+ // putting anything into a SymbolicRegion causes an immediate escape,
+ // it doesn't cause any leak false positives.
+ const auto *RCC = cast<ReturnedValueConstructionContext>(CC);
+ // Make sure that this doesn't coincide with any other symbol
+ // conjured for the returned expression.
+ static const int TopLevelSymRegionTag = 0;
+ const Expr *RetE = RCC->getReturnStmt()->getRetValue();
+ assert(RetE && "Void returns should not have a construction context");
+ QualType ReturnTy = RetE->getType();
+ QualType RegionTy = ACtx.getPointerType(ReturnTy);
+ SVal V = SVB.conjureSymbolVal(&TopLevelSymRegionTag, RetE, SFC,
+ RegionTy, currBldrCtx->blockCount());
return std::make_pair(State, V);
}
llvm_unreachable("Unhandled return value construction context!");
}
case ConstructionContext::ElidedTemporaryObjectKind: {
- assert(AMgr.getAnalyzerOptions().shouldElideConstructors());
+ assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
@@ -292,8 +307,75 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
return std::make_pair(State, V);
}
case ConstructionContext::ArgumentKind: {
- // Function argument constructors. Not implemented yet.
- break;
+ // Arguments are technically temporaries.
+ CallOpts.IsTemporaryCtorOrDtor = true;
+
+ const auto *ACC = cast<ArgumentConstructionContext>(CC);
+ const Expr *E = ACC->getCallLikeExpr();
+ unsigned Idx = ACC->getIndex();
+ const CXXBindTemporaryExpr *BTE = ACC->getCXXBindTemporaryExpr();
+
+ CallEventManager &CEMgr = getStateManager().getCallEventManager();
+ SVal V = UnknownVal();
+ auto getArgLoc = [&](CallEventRef<> Caller) -> Optional<SVal> {
+ const LocationContext *FutureSFC = Caller->getCalleeStackFrame();
+ // Return early if we are unable to reliably foresee
+ // the future stack frame.
+ if (!FutureSFC)
+ return None;
+
+ // This should be equivalent to Caller->getDecl() for now, but
+ // FutureSFC->getDecl() is likely to support better stuff (like
+ // virtual functions) earlier.
+ const Decl *CalleeD = FutureSFC->getDecl();
+
+ // FIXME: Support for variadic arguments is not implemented here yet.
+ if (CallEvent::isVariadic(CalleeD))
+ return None;
+
+ // Operator arguments do not correspond to operator parameters
+ // because this-argument is implemented as a normal argument in
+ // operator call expressions but not in operator declarations.
+ const VarRegion *VR = Caller->getParameterLocation(
+ *Caller->getAdjustedParameterIndex(Idx));
+ if (!VR)
+ return None;
+
+ return loc::MemRegionVal(VR);
+ };
+
+ if (const auto *CE = dyn_cast<CallExpr>(E)) {
+ CallEventRef<> Caller = CEMgr.getSimpleCall(CE, State, LCtx);
+ if (auto OptV = getArgLoc(Caller))
+ V = *OptV;
+ else
+ break;
+ State = addObjectUnderConstruction(State, {CE, Idx}, LCtx, V);
+ } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {
+ // Don't bother figuring out the target region for the future
+ // constructor because we won't need it.
+ CallEventRef<> Caller =
+ CEMgr.getCXXConstructorCall(CCE, /*Target=*/nullptr, State, LCtx);
+ if (auto OptV = getArgLoc(Caller))
+ V = *OptV;
+ else
+ break;
+ State = addObjectUnderConstruction(State, {CCE, Idx}, LCtx, V);
+ } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
+ CallEventRef<> Caller = CEMgr.getObjCMethodCall(ME, State, LCtx);
+ if (auto OptV = getArgLoc(Caller))
+ V = *OptV;
+ else
+ break;
+ State = addObjectUnderConstruction(State, {ME, Idx}, LCtx, V);
+ }
+
+ assert(!V.isUnknown());
+
+ if (BTE)
+ State = addObjectUnderConstruction(State, BTE, LCtx, V);
+
+ return std::make_pair(State, V);
}
}
}
@@ -359,7 +441,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
}
}
}
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case CXXConstructExpr::CK_NonVirtualBase:
// In C++17, classes with non-virtual bases may be aggregates, so they would
// be initialized as aggregates without a constructor call, so we may have
@@ -378,7 +460,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
break;
}
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case CXXConstructExpr::CK_Delegating: {
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
@@ -502,8 +584,15 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
}
}
+ ExplodedNodeSet DstPostArgumentCleanup;
+ for (auto I : DstEvaluated)
+ finishArgumentConstruction(DstPostArgumentCleanup, I, *Call);
+
+ // If there were other constructors called for object-type arguments
+ // of this constructor, clean them up.
ExplodedNodeSet DstPostCall;
- getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated,
+ getCheckerManager().runCheckersForPostCall(DstPostCall,
+ DstPostArgumentCleanup,
*Call, *this);
getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
}
@@ -551,7 +640,7 @@ void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
ProgramStateRef State = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- CNE->getStartLoc(),
+ CNE->getBeginLoc(),
"Error evaluating New Allocator Call");
CallEventManager &CEMgr = getStateManager().getCallEventManager();
CallEventRef<CXXAllocatorCall> Call =
@@ -632,7 +721,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ProgramStateRef State = Pred->getState();
// Retrieve the stored operator new() return value.
- if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
symVal = *getObjectUnderConstruction(State, CNE, LCtx);
State = finishObjectConstruction(State, CNE, LCtx);
}
@@ -652,7 +741,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
CallEventRef<CXXAllocatorCall> Call =
CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
- if (!AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
// Invalidate placement args.
// FIXME: Once we figure out how we want allocators to work,
// we should be using the usual pre-/(default-)eval-/post-call checks here.
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 3ee67f3d6882..758195d8d911 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -349,7 +349,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
/*WasInlined=*/true);
} else if (CE &&
!(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
- AMgr.getAnalyzerOptions().mayInlineCXXAllocator())) {
+ AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
*this, /*WasInlined=*/true);
} else {
@@ -386,7 +386,7 @@ void ExprEngine::examineStackFrames(const Decl *D, const LocationContext *LCtx,
// Do not count the small functions when determining the stack depth.
AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
const CFG *CalleeCFG = CalleeADC->getCFG();
- if (CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize())
+ if (CalleeCFG->getNumBlockIDs() > AMgr.options.AlwaysInlineSize)
++StackDepth;
}
LCtx = LCtx->getParent();
@@ -406,9 +406,8 @@ namespace {
};
} // end anonymous namespace
-REGISTER_TRAIT_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap,
- CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *,
- unsigned))
+REGISTER_MAP_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap,
+ const MemRegion *, unsigned)
bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
NodeBuilder &Bldr, ExplodedNode *Pred,
@@ -505,6 +504,50 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
*this);
}
+ProgramStateRef ExprEngine::finishArgumentConstruction(ProgramStateRef State,
+ const CallEvent &Call) {
+ const Expr *E = Call.getOriginExpr();
+ // FIXME: Constructors to placement arguments of operator new
+ // are not supported yet.
+ if (!E || isa<CXXNewExpr>(E))
+ return State;
+
+ const LocationContext *LC = Call.getLocationContext();
+ for (unsigned CallI = 0, CallN = Call.getNumArgs(); CallI != CallN; ++CallI) {
+ unsigned I = Call.getASTArgumentIndex(CallI);
+ if (Optional<SVal> V =
+ getObjectUnderConstruction(State, {E, I}, LC)) {
+ SVal VV = *V;
+ (void)VV;
+ assert(cast<VarRegion>(VV.castAs<loc::MemRegionVal>().getRegion())
+ ->getStackFrame()->getParent()
+ ->getStackFrame() == LC->getStackFrame());
+ State = finishObjectConstruction(State, {E, I}, LC);
+ }
+ }
+
+ return State;
+}
+
+void ExprEngine::finishArgumentConstruction(ExplodedNodeSet &Dst,
+ ExplodedNode *Pred,
+ const CallEvent &Call) {
+ ProgramStateRef State = Pred->getState();
+ ProgramStateRef CleanedState = finishArgumentConstruction(State, Call);
+ if (CleanedState == State) {
+ Dst.insert(Pred);
+ return;
+ }
+
+ const Expr *E = Call.getOriginExpr();
+ const LocationContext *LC = Call.getLocationContext();
+ NodeBuilder B(Pred, Dst, *currBldrCtx);
+ static SimpleProgramPointTag Tag("ExprEngine",
+ "Finish argument construction");
+ PreStmt PP(E, LC, &Tag);
+ B.generateNode(PP, CleanedState, Pred);
+}
+
void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
const CallEvent &Call) {
// WARNING: At this time, the state attached to 'Call' may be older than the
@@ -516,7 +559,8 @@ void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
// Run any pre-call checks using the generic call interface.
ExplodedNodeSet dstPreVisit;
- getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred, Call, *this);
+ getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred,
+ Call, *this);
// Actually evaluate the function call. We try each of the checkers
// to see if the can evaluate the function call, and get a callback at
@@ -525,8 +569,14 @@ void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, dstPreVisit,
Call, *this);
+ // If there were other constructors called for object-type arguments
+ // of this call, clean them up.
+ ExplodedNodeSet dstArgumentCleanup;
+ for (auto I : dstCallEvaluated)
+ finishArgumentConstruction(dstArgumentCleanup, I, Call);
+
// Finally, run any post-call checks.
- getCheckerManager().runCheckersForPostCall(Dst, dstCallEvaluated,
+ getCheckerManager().runCheckersForPostCall(Dst, dstArgumentCleanup,
Call, *this);
}
@@ -633,7 +683,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
: nullptr;
if (CC && isa<NewAllocatedObjectConstructionContext>(CC) &&
- !Opts.mayInlineCXXAllocator())
+ !Opts.MayInlineCXXAllocator)
return CIP_DisallowedOnce;
// FIXME: We don't handle constructors or destructors for arrays properly.
@@ -662,7 +712,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
// If we don't handle temporary destructors, we shouldn't inline
// their constructors.
if (CallOpts.IsTemporaryCtorOrDtor &&
- !Opts.includeTemporaryDtorsInCFG())
+ !Opts.ShouldIncludeTemporaryDtorsInCFG)
return CIP_DisallowedOnce;
// If we did not find the correct this-region, it would be pointless
@@ -693,7 +743,8 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
return CIP_DisallowedOnce;
// Allow disabling temporary destructor inlining with a separate option.
- if (CallOpts.IsTemporaryCtorOrDtor && !Opts.mayInlineCXXTemporaryDtors())
+ if (CallOpts.IsTemporaryCtorOrDtor &&
+ !Opts.MayInlineCXXTemporaryDtors)
return CIP_DisallowedOnce;
// If we did not find the correct this-region, it would be pointless
@@ -704,13 +755,13 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
break;
}
case CE_CXXAllocator:
- if (Opts.mayInlineCXXAllocator())
+ if (Opts.MayInlineCXXAllocator)
break;
// Do not inline allocators until we model deallocators.
// This is unfortunate, but basically necessary for smart pointers and such.
return CIP_DisallowedAlways;
case CE_ObjCMessage:
- if (!Opts.mayInlineObjCMethod())
+ if (!Opts.MayInlineObjCMethod)
return CIP_DisallowedAlways;
if (!(Opts.getIPAMode() == IPAK_DynamicDispatch ||
Opts.getIPAMode() == IPAK_DynamicDispatchBifurcate))
@@ -794,19 +845,19 @@ static bool mayInlineDecl(AnalysisManager &AMgr,
if (Ctx.getLangOpts().CPlusPlus) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->getDecl())) {
// Conditionally control the inlining of template functions.
- if (!Opts.mayInlineTemplateFunctions())
+ if (!Opts.MayInlineTemplateFunctions)
if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
return false;
// Conditionally control the inlining of C++ standard library functions.
- if (!Opts.mayInlineCXXStandardLibrary())
+ if (!Opts.MayInlineCXXStandardLibrary)
if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation()))
if (AnalysisDeclContext::isInStdNamespace(FD))
return false;
// Conditionally control the inlining of methods on objects that look
// like C++ containers.
- if (!Opts.mayInlineCXXContainerMethods())
+ if (!Opts.MayInlineCXXContainerMethods)
if (!AMgr.isInCodeFile(FD->getLocation()))
if (isContainerMethod(Ctx, FD))
return false;
@@ -815,7 +866,7 @@ static bool mayInlineDecl(AnalysisManager &AMgr,
// We don't currently do a good job modeling shared_ptr because we can't
// see the reference count, so treating as opaque is probably the best
// idea.
- if (!Opts.mayInlineCXXSharedPtrDtor())
+ if (!Opts.MayInlineCXXSharedPtrDtor)
if (isCXXSharedPtrDtor(FD))
return false;
}
@@ -828,7 +879,7 @@ static bool mayInlineDecl(AnalysisManager &AMgr,
return false;
// Do not inline large functions.
- if (CalleeCFG->getNumBlockIDs() > Opts.getMaxInlinableSize())
+ if (CalleeCFG->getNumBlockIDs() > Opts.MaxInlinableSize)
return false;
// It is possible that the live variables analysis cannot be
@@ -896,21 +947,21 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
unsigned StackDepth = 0;
examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
if ((StackDepth >= Opts.InlineMaxStackDepth) &&
- ((CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize())
+ ((CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize)
|| IsRecursive))
return false;
// Do not inline large functions too many times.
if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
- Opts.getMaxTimesInlineLarge()) &&
+ Opts.MaxTimesInlineLarge) &&
CalleeCFG->getNumBlockIDs() >=
- Opts.getMinCFGSizeTreatFunctionsAsLarge()) {
+ Opts.MinCFGSizeTreatFunctionsAsLarge) {
NumReachedInlineCountMax++;
return false;
}
if (HowToInline == Inline_Minimal &&
- (CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize()
+ (CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize
|| IsRecursive))
return false;
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index d76b9cbcfaca..6b8402f621e0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -129,7 +129,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
bool isContainerNull = state->isNull(collectionV).isConstrainedTrue();
ExplodedNodeSet dstLocation;
- evalLocation(dstLocation, S, elem, Pred, state, elementV, nullptr, false);
+ evalLocation(dstLocation, S, elem, Pred, state, elementV, false);
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
@@ -197,7 +197,8 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
// Receiver is definitely nil, so run ObjCMessageNil callbacks and return.
if (nilState && !notNilState) {
- StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ ExplodedNodeSet dstNil;
+ StmtNodeBuilder Bldr(Pred, dstNil, *currBldrCtx);
bool HasTag = Pred->getLocation().getTag();
Pred = Bldr.generateNode(ME, Pred, nilState, nullptr,
ProgramPoint::PreStmtKind);
@@ -205,8 +206,12 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
(void)HasTag;
if (!Pred)
return;
- getCheckerManager().runCheckersForObjCMessageNil(Dst, Pred,
+
+ ExplodedNodeSet dstPostCheckers;
+ getCheckerManager().runCheckersForObjCMessageNil(dstPostCheckers, Pred,
*Msg, *this);
+ for (auto I : dstPostCheckers)
+ finishArgumentConstruction(Dst, I, *Msg);
return;
}
@@ -267,8 +272,13 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
defaultEvalCall(Bldr, Pred, *UpdatedMsg);
}
+ // If there were constructors called for object-type arguments, clean them up.
+ ExplodedNodeSet dstArgCleanup;
+ for (auto I : dstEval)
+ finishArgumentConstruction(dstArgCleanup, I, *Msg);
+
ExplodedNodeSet dstPostvisit;
- getCheckerManager().runCheckersForPostCall(dstPostvisit, dstEval,
+ getCheckerManager().runCheckersForPostCall(dstPostvisit, dstArgCleanup,
*Msg, *this);
// Finally, perform the post-condition check of the ObjCMessageExpr and store
diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index d5e5f96dee0f..fc82f1176942 100644
--- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -112,15 +112,24 @@ public:
FileID FID, const FileEntry *Entry, const char *declName);
// Rewrite the file specified by FID with HTML formatting.
- void RewriteFile(Rewriter &R, const SourceManager& SMgr,
- const PathPieces& path, FileID FID);
+ void RewriteFile(Rewriter &R, const PathPieces& path, FileID FID);
- /// \return Javascript for navigating the HTML report using j/k keys.
- std::string generateKeyboardNavigationJavascript();
private:
/// \return Javascript for displaying shortcuts help;
- std::string showHelpJavascript();
+ StringRef showHelpJavascript();
+
+ /// \return Javascript for navigating the HTML report using j/k keys.
+ StringRef generateKeyboardNavigationJavascript();
+
+ /// \return JavaScript for an option to only show relevant lines.
+ std::string showRelevantLinesJavascript(
+ const PathDiagnostic &D, const PathPieces &path);
+
+ /// Write executed lines from \p D in JSON format into \p os.
+ void dumpCoverageData(const PathDiagnostic &D,
+ const PathPieces &path,
+ llvm::raw_string_ostream &os);
};
} // namespace
@@ -194,7 +203,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
FullSourceLoc L(
SMgr.getExpansionLoc(path.back()->getLocation().asLocation()),
SMgr);
- FullSourceLoc FunL(SMgr.getExpansionLoc(Body->getLocStart()), SMgr);
+ FullSourceLoc FunL(SMgr.getExpansionLoc(Body->getBeginLoc()), SMgr);
offsetDecl = L.getExpansionLineNumber() - FunL.getExpansionLineNumber();
}
}
@@ -209,7 +218,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
int FD;
SmallString<128> Model, ResultPath;
- if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
+ if (!AnalyzerOpts.ShouldWriteStableReportFilename) {
llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
if (std::error_code EC =
llvm::sys::fs::make_absolute(Model)) {
@@ -269,7 +278,7 @@ std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,
continue;
FileIDs.push_back(FID);
- RewriteFile(R, SMgr, path, FID);
+ RewriteFile(R, path, FID);
}
if (SupportsCrossFileDiagnostics && FileIDs.size() > 1) {
@@ -332,28 +341,12 @@ std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,
return os.str();
}
-/// Write executed lines from \p D in JSON format into \p os.
-static void serializeExecutedLines(
+void HTMLDiagnostics::dumpCoverageData(
const PathDiagnostic &D,
const PathPieces &path,
llvm::raw_string_ostream &os) {
- // Copy executed lines from path diagnostics.
- std::map<unsigned, std::set<unsigned>> ExecutedLines;
- for (auto I = D.executedLines_begin(),
- E = D.executedLines_end(); I != E; ++I) {
- std::set<unsigned> &LinesInFile = ExecutedLines[I->first];
- for (unsigned LineNo : I->second) {
- LinesInFile.insert(LineNo);
- }
- }
- // We need to include all lines for which any kind of diagnostics appears.
- for (const auto &P : path) {
- FullSourceLoc Loc = P->getLocation().asLocation().getExpansionLoc();
- FileID FID = Loc.getFileID();
- unsigned LineNo = Loc.getLineNumber();
- ExecutedLines[FID.getHashValue()].insert(LineNo);
- }
+ const FilesToLineNumsMap &ExecutedLines = D.getExecutedLines();
os << "var relevant_lines = {";
for (auto I = ExecutedLines.begin(),
@@ -361,7 +354,7 @@ static void serializeExecutedLines(
if (I != ExecutedLines.begin())
os << ", ";
- os << "\"" << I->first << "\": {";
+ os << "\"" << I->first.getHashValue() << "\": {";
for (unsigned LineNo : I->second) {
if (LineNo != *(I->second.begin()))
os << ", ";
@@ -374,13 +367,12 @@ static void serializeExecutedLines(
os << "};";
}
-/// \return JavaScript for an option to only show relevant lines.
-static std::string showRelevantLinesJavascript(
+std::string HTMLDiagnostics::showRelevantLinesJavascript(
const PathDiagnostic &D, const PathPieces &path) {
std::string s;
llvm::raw_string_ostream os(s);
os << "<script type='text/javascript'>\n";
- serializeExecutedLines(D, path, os);
+ dumpCoverageData(D, path, os);
os << R"<<<(
var filterCounterexample = function (hide) {
@@ -586,7 +578,7 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
}
-std::string HTMLDiagnostics::showHelpJavascript() {
+StringRef HTMLDiagnostics::showHelpJavascript() {
return R"<<<(
<script type='text/javascript'>
@@ -614,8 +606,8 @@ window.addEventListener("keydown", function (event) {
)<<<";
}
-void HTMLDiagnostics::RewriteFile(Rewriter &R, const SourceManager& SMgr,
- const PathPieces& path, FileID FID) {
+void HTMLDiagnostics::RewriteFile(Rewriter &R,
+ const PathPieces& path, FileID FID) {
// Process the path.
// Maintain the counts of extra note pieces separately.
unsigned TotalPieces = path.size();
@@ -944,7 +936,7 @@ void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
}
-std::string HTMLDiagnostics::generateKeyboardNavigationJavascript() {
+StringRef HTMLDiagnostics::generateKeyboardNavigationJavascript() {
return R"<<<(
<script type='text/javascript'>
var digitMatcher = new RegExp("[0-9]+");
@@ -997,7 +989,8 @@ var numToId = function(num) {
};
var navigateTo = function(up) {
- var numItems = document.querySelectorAll(".line > .msg").length;
+ var numItems = document.querySelectorAll(
+ ".line > .msgEvent, .line > .msgControl").length;
var currentSelected = findNum();
var newSelected = move(currentSelected, up, numItems);
var newEl = numToId(newSelected, numItems);
diff --git a/lib/StaticAnalyzer/Core/LoopWidening.cpp b/lib/StaticAnalyzer/Core/LoopWidening.cpp
index 9192f49eac6d..8f6cb9a6b09e 100644
--- a/lib/StaticAnalyzer/Core/LoopWidening.cpp
+++ b/lib/StaticAnalyzer/Core/LoopWidening.cpp
@@ -81,11 +81,12 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
// 'this' pointer is not an lvalue, we should not invalidate it. If the loop
// is located in a method, constructor or destructor, the value of 'this'
- // pointer shoule remain unchanged.
- if (const CXXMethodDecl *CXXMD = dyn_cast<CXXMethodDecl>(STC->getDecl())) {
- const CXXThisRegion *ThisR = MRMgr.getCXXThisRegion(
- CXXMD->getThisType(STC->getAnalysisDeclContext()->getASTContext()),
- STC);
+ // pointer should remain unchanged. Ignore static methods, since they do not
+ // have 'this' pointers.
+ const CXXMethodDecl *CXXMD = dyn_cast<CXXMethodDecl>(STC->getDecl());
+ if (CXXMD && !CXXMD->isStatic()) {
+ const CXXThisRegion *ThisR =
+ MRMgr.getCXXThisRegion(CXXMD->getThisType(), STC);
ITraits.setTrait(ThisR,
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
}
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index cb2122c7749e..9a1d4d73c20b 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -225,6 +225,10 @@ QualType CXXBaseObjectRegion::getValueType() const {
return QualType(getDecl()->getTypeForDecl(), 0);
}
+QualType CXXDerivedObjectRegion::getValueType() const {
+ return QualType(getDecl()->getTypeForDecl(), 0);
+}
+
//===----------------------------------------------------------------------===//
// FoldingSet profiling.
//===----------------------------------------------------------------------===//
@@ -404,6 +408,17 @@ void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ProfileRegion(ID, getDecl(), isVirtual(), superRegion);
}
+void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const CXXRecordDecl *RD,
+ const MemRegion *SReg) {
+ ID.AddPointer(RD);
+ ID.AddPointer(SReg);
+}
+
+void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ ProfileRegion(ID, getDecl(), superRegion);
+}
+
//===----------------------------------------------------------------------===//
// Region anchors.
//===----------------------------------------------------------------------===//
@@ -442,7 +457,7 @@ void MemRegion::dumpToStream(raw_ostream &os) const {
}
void AllocaRegion::dumpToStream(raw_ostream &os) const {
- os << "alloca{" << static_cast<const void *>(Ex) << ',' << Cnt << '}';
+ os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}';
}
void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
@@ -466,16 +481,20 @@ void BlockDataRegion::dumpToStream(raw_ostream &os) const {
void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
// FIXME: More elaborate pretty-printing.
- os << "{ " << static_cast<const void *>(CL) << " }";
+ os << "{ S" << CL->getID(getContext()) << " }";
}
void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
- os << "temp_object{" << getValueType().getAsString() << ','
- << static_cast<const void *>(Ex) << '}';
+ os << "temp_object{" << getValueType().getAsString() << ", "
+ << "S" << Ex->getID(getContext()) << '}';
}
void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
- os << "base{" << superRegion << ',' << getDecl()->getName() << '}';
+ os << "Base{" << superRegion << ',' << getDecl()->getName() << '}';
+}
+
+void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const {
+ os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}';
}
void CXXThisRegion::dumpToStream(raw_ostream &os) const {
@@ -483,7 +502,7 @@ void CXXThisRegion::dumpToStream(raw_ostream &os) const {
}
void ElementRegion::dumpToStream(raw_ostream &os) const {
- os << "element{" << superRegion << ','
+ os << "Element{" << superRegion << ','
<< Index << ',' << getElementType().getAsString() << '}';
}
@@ -492,7 +511,7 @@ void FieldRegion::dumpToStream(raw_ostream &os) const {
}
void ObjCIvarRegion::dumpToStream(raw_ostream &os) const {
- os << "ivar{" << superRegion << ',' << *getDecl() << '}';
+ os << "Ivar{" << superRegion << ',' << *getDecl() << '}';
}
void StringRegion::dumpToStream(raw_ostream &os) const {
@@ -516,7 +535,7 @@ void VarRegion::dumpToStream(raw_ostream &os) const {
if (const IdentifierInfo *ID = VD->getIdentifier())
os << ID->getName();
else
- os << "VarRegion{" << static_cast<const void *>(this) << '}';
+ os << "VarRegion{D" << VD->getID() << '}';
}
LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
@@ -578,7 +597,7 @@ void MemRegion::printPretty(raw_ostream &os) const {
os << "'";
}
-void MemRegion::printPrettyAsExpr(raw_ostream &os) const {
+void MemRegion::printPrettyAsExpr(raw_ostream &) const {
llvm_unreachable("This region cannot be printed pretty.");
}
@@ -630,6 +649,14 @@ void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
superRegion->printPrettyAsExpr(os);
}
+bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const {
+ return superRegion->canPrintPrettyAsExpr();
+}
+
+void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
+ superRegion->printPrettyAsExpr(os);
+}
+
std::string MemRegion::getDescriptiveName(bool UseQuotes) const {
std::string VariableName;
std::string ArrayIndices;
@@ -1061,6 +1088,12 @@ MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super);
}
+const CXXDerivedObjectRegion *
+MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD,
+ const SubRegion *Super) {
+ return getSubRegion<CXXDerivedObjectRegion>(RD, Super);
+}
+
const CXXThisRegion*
MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
const LocationContext *LC) {
@@ -1072,9 +1105,8 @@ MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
// FIXME: when operator() of lambda is analyzed as a top level function and
// 'this' refers to a this to the enclosing scope, there is no right region to
// return.
- while (!LC->inTopFrame() &&
- (!D || D->isStatic() ||
- PT != D->getThisType(getContext())->getAs<PointerType>())) {
+ while (!LC->inTopFrame() && (!D || D->isStatic() ||
+ PT != D->getThisType()->getAs<PointerType>())) {
LC = LC->getParent();
D = dyn_cast<CXXMethodDecl>(LC->getDecl());
}
@@ -1131,6 +1163,7 @@ const MemRegion *MemRegion::getBaseRegion() const {
case MemRegion::FieldRegionKind:
case MemRegion::ObjCIvarRegionKind:
case MemRegion::CXXBaseObjectRegionKind:
+ case MemRegion::CXXDerivedObjectRegionKind:
R = cast<SubRegion>(R)->getSuperRegion();
continue;
default:
@@ -1141,7 +1174,16 @@ const MemRegion *MemRegion::getBaseRegion() const {
return R;
}
-bool MemRegion::isSubRegionOf(const MemRegion *R) const {
+// getgetMostDerivedObjectRegion gets the region of the root class of a C++
+// class hierarchy.
+const MemRegion *MemRegion::getMostDerivedObjectRegion() const {
+ const MemRegion *R = this;
+ while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
+ R = BR->getSuperRegion();
+ return R;
+}
+
+bool MemRegion::isSubRegionOf(const MemRegion *) const {
return false;
}
@@ -1149,7 +1191,7 @@ bool MemRegion::isSubRegionOf(const MemRegion *R) const {
// View handling.
//===----------------------------------------------------------------------===//
-const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const {
+const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const {
const MemRegion *R = this;
while (true) {
switch (R->getKind()) {
@@ -1161,9 +1203,10 @@ const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const {
break;
}
case CXXBaseObjectRegionKind:
- if (!StripBaseCasts)
+ case CXXDerivedObjectRegionKind:
+ if (!StripBaseAndDerivedCasts)
return R;
- R = cast<CXXBaseObjectRegion>(R)->getSuperRegion();
+ R = cast<TypedValueRegion>(R)->getSuperRegion();
break;
default:
return R;
@@ -1344,6 +1387,12 @@ static RegionOffset calculateOffset(const MemRegion *R) {
Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth();
break;
}
+
+ case MemRegion::CXXDerivedObjectRegionKind: {
+ // TODO: Store the base type in the CXXDerivedObjectRegion and use it.
+ goto Finish;
+ }
+
case MemRegion::ElementRegionKind: {
const auto *ER = cast<ElementRegion>(R);
R = ER->getSuperRegion();
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 1b698ec5c086..3e93bb6a7c4f 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -536,7 +536,7 @@ PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
static SourceLocation getValidSourceLocation(const Stmt* S,
LocationOrAnalysisDeclContext LAC,
bool UseEnd = false) {
- SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart();
+ SourceLocation L = UseEnd ? S->getEndLoc() : S->getBeginLoc();
assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
"be passed to PathDiagnosticLocation upon creation.");
@@ -562,13 +562,13 @@ static SourceLocation getValidSourceLocation(const Stmt* S,
if (!Parent) {
const Stmt *Body = ADC->getBody();
if (Body)
- L = Body->getLocStart();
+ L = Body->getBeginLoc();
else
- L = ADC->getDecl()->getLocEnd();
+ L = ADC->getDecl()->getEndLoc();
break;
}
- L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
+ L = UseEnd ? Parent->getEndLoc() : Parent->getBeginLoc();
} while (!L.isValid());
}
@@ -635,7 +635,7 @@ getLocationForCaller(const StackFrameContext *SFC,
PathDiagnosticLocation
PathDiagnosticLocation::createBegin(const Decl *D,
const SourceManager &SM) {
- return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
+ return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
}
PathDiagnosticLocation
@@ -695,7 +695,7 @@ PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
// FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
if (!CS->body_empty()) {
- SourceLocation Loc = (*CS->body_begin())->getLocStart();
+ SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
return PathDiagnosticLocation(Loc, SM, SingleLocK);
}
@@ -723,6 +723,8 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
} else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
SMng);
+ } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
+ return PathDiagnosticLocation(PIC->getLocation(), SMng);
} else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
return PathDiagnosticLocation(PIE->getLocation(), SMng);
} else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
@@ -736,10 +738,10 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
} else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
CFGElement BlockFront = BE->getBlock()->front();
if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
- return PathDiagnosticLocation(StmtElt->getStmt()->getLocStart(), SMng);
+ return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
} else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
return PathDiagnosticLocation(
- NewAllocElt->getAllocatorExpr()->getLocStart(), SMng);
+ NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
}
llvm_unreachable("Unexpected CFG element at front of block");
} else {
@@ -774,18 +776,20 @@ const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
}
// Otherwise, see if the node's program point directly points to a statement.
ProgramPoint P = N->getLocation();
- if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
+ if (auto SP = P.getAs<StmtPoint>())
return SP->getStmt();
- if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
+ if (auto BE = P.getAs<BlockEdge>())
return BE->getSrc()->getTerminator();
- if (Optional<CallEnter> CE = P.getAs<CallEnter>())
+ if (auto CE = P.getAs<CallEnter>())
return CE->getCallExpr();
- if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
+ if (auto CEE = P.getAs<CallExitEnd>())
return CEE->getCalleeContext()->getCallSite();
- if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
+ if (auto PIPP = P.getAs<PostInitializer>())
return PIPP->getInitializer()->getInit();
- if (Optional<CallExitBegin> CEB = P.getAs<CallExitBegin>())
+ if (auto CEB = P.getAs<CallExitBegin>())
return CEB->getReturnStmt();
+ if (auto FEP = P.getAs<FunctionExitPoint>())
+ return FEP->getStmt();
return nullptr;
}
@@ -822,17 +826,21 @@ PathDiagnosticLocation
const SourceManager &SM) {
assert(N && "Cannot create a location with a null node.");
const Stmt *S = getStmt(N);
+ const LocationContext *LC = N->getLocationContext();
if (!S) {
// If this is an implicit call, return the implicit call point location.
if (Optional<PreImplicitCall> PIE = N->getLocationAs<PreImplicitCall>())
return PathDiagnosticLocation(PIE->getLocation(), SM);
+ if (auto FE = N->getLocationAs<FunctionExitPoint>()) {
+ if (const ReturnStmt *RS = FE->getStmt())
+ return PathDiagnosticLocation::createBegin(RS, SM, LC);
+ }
S = getNextStmt(N);
}
if (S) {
ProgramPoint P = N->getLocation();
- const LocationContext *LC = N->getLocationContext();
// For member expressions, return the location of the '.' or '->'.
if (const auto *ME = dyn_cast<MemberExpr>(S))
@@ -845,7 +853,7 @@ PathDiagnosticLocation
if (P.getAs<PostStmtPurgeDeadSymbols>())
return PathDiagnosticLocation::createEnd(S, SM, LC);
- if (S->getLocStart().isValid())
+ if (S->getBeginLoc().isValid())
return PathDiagnosticLocation(S, SM, LC);
return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM);
}
@@ -904,7 +912,7 @@ PathDiagnosticRange
const auto *DS = cast<DeclStmt>(S);
if (DS->isSingleDecl()) {
// Should always be the case, but we'll be defensive.
- return SourceRange(DS->getLocStart(),
+ return SourceRange(DS->getBeginLoc(),
DS->getSingleDecl()->getLocation());
}
break;
@@ -964,7 +972,7 @@ void PathDiagnosticLocation::flatten() {
//===----------------------------------------------------------------------===//
std::shared_ptr<PathDiagnosticCallPiece>
-PathDiagnosticCallPiece::construct(const ExplodedNode *N, const CallExitEnd &CE,
+PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
const SourceManager &SM) {
const Decl *caller = CE.getLocationContext()->getDecl();
PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index cfe780db9ec9..db4cf76578d8 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/TokenConcatenation.h"
#include "clang/Rewrite/Core/HTMLRewrite.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
@@ -24,20 +25,26 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
+
using namespace clang;
using namespace ento;
using namespace markup;
+//===----------------------------------------------------------------------===//
+// Declarations of helper classes and functions for emitting bug reports in
+// plist format.
+//===----------------------------------------------------------------------===//
+
namespace {
class PlistDiagnostics : public PathDiagnosticConsumer {
const std::string OutputFile;
- const LangOptions &LangOpts;
+ const Preprocessor &PP;
+ AnalyzerOptions &AnOpts;
const bool SupportsCrossFileDiagnostics;
- const bool SerializeStatistics;
public:
PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
const std::string& prefix,
- const LangOptions &LangOpts,
+ const Preprocessor &PP,
bool supportsMultipleFiles);
~PlistDiagnostics() override {}
@@ -59,37 +66,116 @@ namespace {
};
} // end anonymous namespace
-PlistDiagnostics::PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
- const std::string& output,
- const LangOptions &LO,
- bool supportsMultipleFiles)
- : OutputFile(output),
- LangOpts(LO),
- SupportsCrossFileDiagnostics(supportsMultipleFiles),
- SerializeStatistics(AnalyzerOpts.shouldSerializeStats()) {}
+namespace {
-void ento::createPlistDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
- PathDiagnosticConsumers &C,
- const std::string& s,
- const Preprocessor &PP) {
- C.push_back(new PlistDiagnostics(AnalyzerOpts, s,
- PP.getLangOpts(), false));
-}
+/// A helper class for emitting a single report.
+class PlistPrinter {
+ const FIDMap& FM;
+ AnalyzerOptions &AnOpts;
+ const Preprocessor &PP;
+ llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
+
+public:
+ PlistPrinter(const FIDMap& FM, AnalyzerOptions &AnOpts,
+ const Preprocessor &PP)
+ : FM(FM), AnOpts(AnOpts), PP(PP) {
+ }
-void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
- PathDiagnosticConsumers &C,
- const std::string &s,
- const Preprocessor &PP) {
- C.push_back(new PlistDiagnostics(AnalyzerOpts, s,
- PP.getLangOpts(), true));
-}
+ void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
+ ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true);
+
+ // Don't emit a warning about an unused private field.
+ (void)AnOpts;
+ }
+
+ /// Print the expansions of the collected macro pieces.
+ ///
+ /// Each time ReportDiag is called on a PathDiagnosticMacroPiece (or, if one
+ /// is found through a call piece, etc), it's subpieces are reported, and the
+ /// piece itself is collected. Call this function after the entire bugpath
+ /// was reported.
+ void ReportMacroExpansions(raw_ostream &o, unsigned indent);
+
+private:
+ void ReportPiece(raw_ostream &o, const PathDiagnosticPiece &P,
+ unsigned indent, unsigned depth, bool includeControlFlow,
+ bool isKeyEvent = false) {
+ switch (P.getKind()) {
+ case PathDiagnosticPiece::ControlFlow:
+ if (includeControlFlow)
+ ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), indent);
+ break;
+ case PathDiagnosticPiece::Call:
+ ReportCall(o, cast<PathDiagnosticCallPiece>(P), indent,
+ depth);
+ break;
+ case PathDiagnosticPiece::Event:
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(P), indent, depth,
+ isKeyEvent);
+ break;
+ case PathDiagnosticPiece::Macro:
+ ReportMacroSubPieces(o, cast<PathDiagnosticMacroPiece>(P), indent,
+ depth);
+ break;
+ case PathDiagnosticPiece::Note:
+ ReportNote(o, cast<PathDiagnosticNotePiece>(P), indent);
+ break;
+ }
+ }
+
+ void EmitRanges(raw_ostream &o, const ArrayRef<SourceRange> Ranges,
+ unsigned indent);
+ void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent);
+
+ void ReportControlFlow(raw_ostream &o,
+ const PathDiagnosticControlFlowPiece& P,
+ unsigned indent);
+ void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
+ unsigned indent, unsigned depth, bool isKeyEvent = false);
+ void ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
+ unsigned indent, unsigned depth);
+ void ReportMacroSubPieces(raw_ostream &o, const PathDiagnosticMacroPiece& P,
+ unsigned indent, unsigned depth);
+ void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
+ unsigned indent);
+};
+
+} // end of anonymous namespace
-static void EmitRanges(raw_ostream &o,
- const ArrayRef<SourceRange> Ranges,
- const FIDMap& FM,
- const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent) {
+namespace {
+
+struct ExpansionInfo {
+ std::string MacroName;
+ std::string Expansion;
+ ExpansionInfo(std::string N, std::string E)
+ : MacroName(std::move(N)), Expansion(std::move(E)) {}
+};
+
+} // end of anonymous namespace
+
+static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
+ AnalyzerOptions &AnOpts,
+ const Preprocessor &PP,
+ const PathPieces &Path);
+
+/// Print coverage information to output stream {@code o}.
+/// May modify the used list of files {@code Fids} by inserting new ones.
+static void printCoverage(const PathDiagnostic *D,
+ unsigned InputIndentLevel,
+ SmallVectorImpl<FileID> &Fids,
+ FIDMap &FM,
+ llvm::raw_fd_ostream &o);
+
+static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
+ const Preprocessor &PP);
+
+//===----------------------------------------------------------------------===//
+// Methods of PlistPrinter.
+//===----------------------------------------------------------------------===//
+
+void PlistPrinter::EmitRanges(raw_ostream &o,
+ const ArrayRef<SourceRange> Ranges,
+ unsigned indent) {
if (Ranges.empty())
return;
@@ -97,6 +183,10 @@ static void EmitRanges(raw_ostream &o,
Indent(o, indent) << "<key>ranges</key>\n";
Indent(o, indent) << "<array>\n";
++indent;
+
+ const SourceManager &SM = PP.getSourceManager();
+ const LangOptions &LangOpts = PP.getLangOpts();
+
for (auto &R : Ranges)
EmitRange(o, SM,
Lexer::getAsCharRange(SM.getExpansionRange(R), SM, LangOpts),
@@ -105,7 +195,8 @@ static void EmitRanges(raw_ostream &o,
Indent(o, indent) << "</array>\n";
}
-static void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent) {
+void PlistPrinter::EmitMessage(raw_ostream &o, StringRef Message,
+ unsigned indent) {
// Output the text.
assert(!Message.empty());
Indent(o, indent) << "<key>extended_message</key>\n";
@@ -119,12 +210,12 @@ static void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent) {
EmitString(o, Message) << '\n';
}
-static void ReportControlFlow(raw_ostream &o,
- const PathDiagnosticControlFlowPiece& P,
- const FIDMap& FM,
- const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent) {
+void PlistPrinter::ReportControlFlow(raw_ostream &o,
+ const PathDiagnosticControlFlowPiece& P,
+ unsigned indent) {
+
+ const SourceManager &SM = PP.getSourceManager();
+ const LangOptions &LangOpts = PP.getLangOpts();
Indent(o, indent) << "<dict>\n";
++indent;
@@ -173,13 +264,11 @@ static void ReportControlFlow(raw_ostream &o,
Indent(o, indent) << "</dict>\n";
}
-static void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
- const FIDMap& FM,
- const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent,
- unsigned depth,
- bool isKeyEvent = false) {
+void PlistPrinter::ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
+ unsigned indent, unsigned depth,
+ bool isKeyEvent) {
+
+ const SourceManager &SM = PP.getSourceManager();
Indent(o, indent) << "<dict>\n";
++indent;
@@ -198,7 +287,7 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
// Output the ranges (if any).
ArrayRef<SourceRange> Ranges = P.getRanges();
- EmitRanges(o, Ranges, FM, SM, LangOpts, indent);
+ EmitRanges(o, Ranges, indent);
// Output the call depth.
Indent(o, indent) << "<key>depth</key>";
@@ -212,61 +301,80 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
Indent(o, indent); o << "</dict>\n";
}
-static void ReportPiece(raw_ostream &o,
- const PathDiagnosticPiece &P,
- const FIDMap& FM, const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent,
- unsigned depth,
- bool includeControlFlow,
- bool isKeyEvent = false);
-
-static void ReportCall(raw_ostream &o,
- const PathDiagnosticCallPiece &P,
- const FIDMap& FM, const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent,
- unsigned depth) {
+void PlistPrinter::ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
+ unsigned indent,
+ unsigned depth) {
if (auto callEnter = P.getCallEnterEvent())
- ReportPiece(o, *callEnter, FM, SM, LangOpts, indent, depth, true,
+ ReportPiece(o, *callEnter, indent, depth, /*includeControlFlow*/ true,
P.isLastInMainSourceFile());
++depth;
if (auto callEnterWithinCaller = P.getCallEnterWithinCallerEvent())
- ReportPiece(o, *callEnterWithinCaller, FM, SM, LangOpts,
- indent, depth, true);
+ ReportPiece(o, *callEnterWithinCaller, indent, depth,
+ /*includeControlFlow*/ true);
for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
- ReportPiece(o, **I, FM, SM, LangOpts, indent, depth, true);
+ ReportPiece(o, **I, indent, depth, /*includeControlFlow*/ true);
--depth;
if (auto callExit = P.getCallExitEvent())
- ReportPiece(o, *callExit, FM, SM, LangOpts, indent, depth, true);
+ ReportPiece(o, *callExit, indent, depth, /*includeControlFlow*/ true);
}
-static void ReportMacro(raw_ostream &o,
- const PathDiagnosticMacroPiece& P,
- const FIDMap& FM, const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent,
- unsigned depth) {
+void PlistPrinter::ReportMacroSubPieces(raw_ostream &o,
+ const PathDiagnosticMacroPiece& P,
+ unsigned indent, unsigned depth) {
+ MacroPieces.push_back(&P);
- for (PathPieces::const_iterator I = P.subPieces.begin(), E=P.subPieces.end();
- I!=E; ++I) {
- ReportPiece(o, **I, FM, SM, LangOpts, indent, depth, false);
+ for (PathPieces::const_iterator I = P.subPieces.begin(),
+ E = P.subPieces.end();
+ I != E; ++I) {
+ ReportPiece(o, **I, indent, depth, /*includeControlFlow*/ false);
+ }
+}
+
+void PlistPrinter::ReportMacroExpansions(raw_ostream &o, unsigned indent) {
+
+ for (const PathDiagnosticMacroPiece *P : MacroPieces) {
+ const SourceManager &SM = PP.getSourceManager();
+ ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP);
+
+ Indent(o, indent) << "<dict>\n";
+ ++indent;
+
+ // Output the location.
+ FullSourceLoc L = P->getLocation().asLocation();
+
+ Indent(o, indent) << "<key>location</key>\n";
+ EmitLocation(o, SM, L, FM, indent);
+
+ // Output the ranges (if any).
+ ArrayRef<SourceRange> Ranges = P->getRanges();
+ EmitRanges(o, Ranges, indent);
+
+ // Output the macro name.
+ Indent(o, indent) << "<key>name</key>";
+ EmitString(o, EI.MacroName) << '\n';
+
+ // Output what it expands into.
+ Indent(o, indent) << "<key>expansion</key>";
+ EmitString(o, EI.Expansion) << '\n';
+
+ // Finish up.
+ --indent;
+ Indent(o, indent);
+ o << "</dict>\n";
}
}
-static void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
- const FIDMap& FM,
- const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent,
- unsigned depth) {
+void PlistPrinter::ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
+ unsigned indent) {
+
+ const SourceManager &SM = PP.getSourceManager();
Indent(o, indent) << "<dict>\n";
++indent;
@@ -279,7 +387,7 @@ static void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
// Output the ranges (if any).
ArrayRef<SourceRange> Ranges = P.getRanges();
- EmitRanges(o, Ranges, FM, SM, LangOpts, indent);
+ EmitRanges(o, Ranges, indent);
// Output the text.
EmitMessage(o, P.getString(), indent);
@@ -289,45 +397,115 @@ static void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
Indent(o, indent); o << "</dict>\n";
}
-static void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P,
- const FIDMap& FM, const SourceManager &SM,
- const LangOptions &LangOpts) {
- ReportPiece(o, P, FM, SM, LangOpts, 4, 0, true);
+//===----------------------------------------------------------------------===//
+// Static function definitions.
+//===----------------------------------------------------------------------===//
+
+/// Print coverage information to output stream {@code o}.
+/// May modify the used list of files {@code Fids} by inserting new ones.
+static void printCoverage(const PathDiagnostic *D,
+ unsigned InputIndentLevel,
+ SmallVectorImpl<FileID> &Fids,
+ FIDMap &FM,
+ llvm::raw_fd_ostream &o) {
+ unsigned IndentLevel = InputIndentLevel;
+
+ Indent(o, IndentLevel) << "<key>ExecutedLines</key>\n";
+ Indent(o, IndentLevel) << "<dict>\n";
+ IndentLevel++;
+
+ // Mapping from file IDs to executed lines.
+ const FilesToLineNumsMap &ExecutedLines = D->getExecutedLines();
+ for (auto I = ExecutedLines.begin(), E = ExecutedLines.end(); I != E; ++I) {
+ unsigned FileKey = AddFID(FM, Fids, I->first);
+ Indent(o, IndentLevel) << "<key>" << FileKey << "</key>\n";
+ Indent(o, IndentLevel) << "<array>\n";
+ IndentLevel++;
+ for (unsigned LineNo : I->second) {
+ Indent(o, IndentLevel);
+ EmitInteger(o, LineNo) << "\n";
+ }
+ IndentLevel--;
+ Indent(o, IndentLevel) << "</array>\n";
+ }
+ IndentLevel--;
+ Indent(o, IndentLevel) << "</dict>\n";
+
+ assert(IndentLevel == InputIndentLevel);
}
-static void ReportPiece(raw_ostream &o,
- const PathDiagnosticPiece &P,
- const FIDMap& FM, const SourceManager &SM,
- const LangOptions &LangOpts,
- unsigned indent,
- unsigned depth,
- bool includeControlFlow,
- bool isKeyEvent) {
- switch (P.getKind()) {
- case PathDiagnosticPiece::ControlFlow:
- if (includeControlFlow)
- ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
- LangOpts, indent);
- break;
- case PathDiagnosticPiece::Call:
- ReportCall(o, cast<PathDiagnosticCallPiece>(P), FM, SM, LangOpts,
- indent, depth);
- break;
- case PathDiagnosticPiece::Event:
- ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
- indent, depth, isKeyEvent);
- break;
- case PathDiagnosticPiece::Macro:
- ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
- indent, depth);
- break;
- case PathDiagnosticPiece::Note:
- ReportNote(o, cast<PathDiagnosticNotePiece>(P), FM, SM, LangOpts,
- indent, depth);
- break;
+static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
+ AnalyzerOptions &AnOpts,
+ const Preprocessor &PP,
+ const PathPieces &Path) {
+ PlistPrinter Printer(FM, AnOpts, PP);
+ assert(std::is_partitioned(
+ Path.begin(), Path.end(),
+ [](const std::shared_ptr<PathDiagnosticPiece> &E)
+ { return E->getKind() == PathDiagnosticPiece::Note; }) &&
+ "PathDiagnostic is not partitioned so that notes precede the rest");
+
+ PathPieces::const_iterator FirstNonNote = std::partition_point(
+ Path.begin(), Path.end(),
+ [](const std::shared_ptr<PathDiagnosticPiece> &E)
+ { return E->getKind() == PathDiagnosticPiece::Note; });
+
+ PathPieces::const_iterator I = Path.begin();
+
+ if (FirstNonNote != Path.begin()) {
+ o << " <key>notes</key>\n"
+ " <array>\n";
+
+ for (; I != FirstNonNote; ++I)
+ Printer.ReportDiag(o, **I);
+
+ o << " </array>\n";
}
+
+ o << " <key>path</key>\n";
+
+ o << " <array>\n";
+
+ for (PathPieces::const_iterator E = Path.end(); I != E; ++I)
+ Printer.ReportDiag(o, **I);
+
+ o << " </array>\n";
+
+ if (!AnOpts.ShouldDisplayMacroExpansions)
+ return;
+
+ o << " <key>macro_expansions</key>\n"
+ " <array>\n";
+ Printer.ReportMacroExpansions(o, /* indent */ 4);
+ o << " </array>\n";
}
+//===----------------------------------------------------------------------===//
+// Methods of PlistDiagnostics.
+//===----------------------------------------------------------------------===//
+
+PlistDiagnostics::PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
+ const std::string& output,
+ const Preprocessor &PP,
+ bool supportsMultipleFiles)
+ : OutputFile(output), PP(PP), AnOpts(AnalyzerOpts),
+ SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
+
+void ento::createPlistDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
+ PathDiagnosticConsumers &C,
+ const std::string& s,
+ const Preprocessor &PP) {
+ C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP,
+ /*supportsMultipleFiles*/ false));
+}
+
+void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
+ PathDiagnosticConsumers &C,
+ const std::string &s,
+ const Preprocessor &PP) {
+ C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP,
+ /*supportsMultipleFiles*/ true));
+}
void PlistDiagnostics::FlushDiagnosticsImpl(
std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) {
@@ -335,17 +513,15 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// ranges of the diagnostics.
FIDMap FM;
SmallVector<FileID, 10> Fids;
- const SourceManager* SM = nullptr;
-
- if (!Diags.empty())
- SM = &Diags.front()->path.front()->getLocation().getManager();
+ const SourceManager& SM = PP.getSourceManager();
+ const LangOptions &LangOpts = PP.getLangOpts();
- auto AddPieceFID = [&FM, &Fids, SM](const PathDiagnosticPiece &Piece) {
- AddFID(FM, Fids, *SM, Piece.getLocation().asLocation());
+ auto AddPieceFID = [&FM, &Fids, &SM](const PathDiagnosticPiece &Piece) {
+ AddFID(FM, Fids, SM, Piece.getLocation().asLocation());
ArrayRef<SourceRange> Ranges = Piece.getRanges();
for (const SourceRange &Range : Ranges) {
- AddFID(FM, Fids, *SM, Range.getBegin());
- AddFID(FM, Fids, *SM, Range.getEnd());
+ AddFID(FM, Fids, SM, Range.getBegin());
+ AddFID(FM, Fids, SM, Range.getEnd());
}
};
@@ -395,14 +571,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << "<dict>\n" <<
" <key>clang_version</key>\n";
EmitString(o, getClangFullVersion()) << '\n';
- o << " <key>files</key>\n"
- " <array>\n";
-
- for (FileID FID : Fids)
- EmitString(o << " ", SM->getFileEntryForID(FID)->getName()) << '\n';
-
- o << " </array>\n"
- " <key>diagnostics</key>\n"
+ o << " <key>diagnostics</key>\n"
" <array>\n";
for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
@@ -411,39 +580,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << " <dict>\n";
const PathDiagnostic *D = *DI;
- const PathPieces &PP = D->path;
-
- assert(std::is_partitioned(
- PP.begin(), PP.end(),
- [](const std::shared_ptr<PathDiagnosticPiece> &E)
- { return E->getKind() == PathDiagnosticPiece::Note; }) &&
- "PathDiagnostic is not partitioned so that notes precede the rest");
-
- PathPieces::const_iterator FirstNonNote = std::partition_point(
- PP.begin(), PP.end(),
- [](const std::shared_ptr<PathDiagnosticPiece> &E)
- { return E->getKind() == PathDiagnosticPiece::Note; });
-
- PathPieces::const_iterator I = PP.begin();
-
- if (FirstNonNote != PP.begin()) {
- o << " <key>notes</key>\n"
- " <array>\n";
-
- for (; I != FirstNonNote; ++I)
- ReportDiag(o, **I, FM, *SM, LangOpts);
-
- o << " </array>\n";
- }
-
- o << " <key>path</key>\n";
-
- o << " <array>\n";
-
- for (PathPieces::const_iterator E = PP.end(); I != E; ++I)
- ReportDiag(o, **I, FM, *SM, LangOpts);
-
- o << " </array>\n";
+ printBugPath(o, FM, AnOpts, PP, D->path);
// Output the bug type and bug category.
o << " <key>description</key>";
@@ -458,12 +595,12 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << " <!-- This hash is experimental and going to change! -->\n";
o << " <key>issue_hash_content_of_line_in_context</key>";
PathDiagnosticLocation UPDLoc = D->getUniqueingLoc();
- FullSourceLoc L(SM->getExpansionLoc(UPDLoc.isValid()
+ FullSourceLoc L(SM.getExpansionLoc(UPDLoc.isValid()
? UPDLoc.asLocation()
: D->getLocation().asLocation()),
- *SM);
+ SM);
const Decl *DeclWithIssue = D->getDeclWithIssue();
- EmitString(o, GetIssueHash(*SM, L, D->getCheckName(), D->getBugType(),
+ EmitString(o, GetIssueHash(SM, L, D->getCheckName(), D->getBugType(),
DeclWithIssue, LangOpts))
<< '\n';
@@ -507,15 +644,17 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// the leak location even after code is added between the allocation
// site and the end of scope (leak report location).
if (UPDLoc.isValid()) {
- FullSourceLoc UFunL(SM->getExpansionLoc(
- D->getUniqueingDecl()->getBody()->getLocStart()), *SM);
+ FullSourceLoc UFunL(
+ SM.getExpansionLoc(
+ D->getUniqueingDecl()->getBody()->getBeginLoc()),
+ SM);
o << " <key>issue_hash_function_offset</key><string>"
<< L.getExpansionLineNumber() - UFunL.getExpansionLineNumber()
<< "</string>\n";
// Otherwise, use the location on which the bug is reported.
} else {
- FullSourceLoc FunL(SM->getExpansionLoc(Body->getLocStart()), *SM);
+ FullSourceLoc FunL(SM.getExpansionLoc(Body->getBeginLoc()), SM);
o << " <key>issue_hash_function_offset</key><string>"
<< L.getExpansionLineNumber() - FunL.getExpansionLineNumber()
<< "</string>\n";
@@ -527,7 +666,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// Output the location of the bug.
o << " <key>location</key>\n";
- EmitLocation(o, *SM, D->getLocation().asLocation(), FM, 2);
+ EmitLocation(o, SM, D->getLocation().asLocation(), FM, 2);
// Output the diagnostic to the sub-diagnostic client, if any.
if (!filesMade->empty()) {
@@ -551,13 +690,21 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
}
}
+ printCoverage(D, /*IndentLevel=*/2, Fids, FM, o);
+
// Close up the entry.
o << " </dict>\n";
}
o << " </array>\n";
- if (llvm::AreStatisticsEnabled() && SerializeStatistics) {
+ o << " <key>files</key>\n"
+ " <array>\n";
+ for (FileID FID : Fids)
+ EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n';
+ o << " </array>\n";
+
+ if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
o << " <key>statistics</key>\n";
std::string stats;
llvm::raw_string_ostream os(stats);
@@ -569,3 +716,402 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// Finish.
o << "</dict>\n</plist>";
}
+
+//===----------------------------------------------------------------------===//
+// Declarations of helper functions and data structures for expanding macros.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+using ExpArgTokens = llvm::SmallVector<Token, 2>;
+
+/// Maps unexpanded macro arguments to expanded arguments. A macro argument may
+/// need to expanded further when it is nested inside another macro.
+class MacroArgMap : public std::map<const IdentifierInfo *, ExpArgTokens> {
+public:
+ void expandFromPrevMacro(const MacroArgMap &Super);
+};
+
+struct MacroNameAndArgs {
+ std::string Name;
+ const MacroInfo *MI = nullptr;
+ MacroArgMap Args;
+
+ MacroNameAndArgs(std::string N, const MacroInfo *MI, MacroArgMap M)
+ : Name(std::move(N)), MI(MI), Args(std::move(M)) {}
+};
+
+class TokenPrinter {
+ llvm::raw_ostream &OS;
+ const Preprocessor &PP;
+
+ Token PrevTok, PrevPrevTok;
+ TokenConcatenation ConcatInfo;
+
+public:
+ TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP)
+ : OS(OS), PP(PP), ConcatInfo(PP) {
+ PrevTok.setKind(tok::unknown);
+ PrevPrevTok.setKind(tok::unknown);
+ }
+
+ void printToken(const Token &Tok);
+};
+
+} // end of anonymous namespace
+
+/// The implementation method of getMacroExpansion: It prints the expansion of
+/// a macro to \p Printer, and returns with the name of the macro.
+///
+/// Since macros can be nested in one another, this function may call itself
+/// recursively.
+///
+/// Unfortunately, macro arguments have to expanded manually. To understand why,
+/// observe the following example:
+///
+/// #define PRINT(x) print(x)
+/// #define DO_SOMETHING(str) PRINT(str)
+///
+/// DO_SOMETHING("Cute panda cubs.");
+///
+/// As we expand the last line, we'll immediately replace PRINT(str) with
+/// print(x). The information that both 'str' and 'x' refers to the same string
+/// is an information we have to forward, hence the argument \p PrevArgs.
+static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
+ SourceLocation MacroLoc,
+ const Preprocessor &PP,
+ const MacroArgMap &PrevArgs);
+
+/// Retrieves the name of the macro and what it's arguments expand into
+/// at \p ExpanLoc.
+///
+/// For example, for the following macro expansion:
+///
+/// #define SET_TO_NULL(x) x = 0
+/// #define NOT_SUSPICIOUS(a) \
+/// { \
+/// int b = 0; \
+/// } \
+/// SET_TO_NULL(a)
+///
+/// int *ptr = new int(4);
+/// NOT_SUSPICIOUS(&ptr);
+/// *ptr = 5;
+///
+/// When \p ExpanLoc references the last line, the macro name "NOT_SUSPICIOUS"
+/// and the MacroArgMap map { (a, &ptr) } will be returned.
+///
+/// When \p ExpanLoc references "SET_TO_NULL(a)" within the definition of
+/// "NOT_SUSPICOUS", the macro name "SET_TO_NULL" and the MacroArgMap map
+/// { (x, a) } will be returned.
+static MacroNameAndArgs getMacroNameAndArgs(SourceLocation ExpanLoc,
+ const Preprocessor &PP);
+
+/// Retrieves the ')' token that matches '(' \p It points to.
+static MacroInfo::tokens_iterator getMatchingRParen(
+ MacroInfo::tokens_iterator It,
+ MacroInfo::tokens_iterator End);
+
+/// Retrieves the macro info for \p II refers to at \p Loc. This is important
+/// because macros can be redefined or undefined.
+static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
+ const SourceManager &SM,
+ const IdentifierInfo *II,
+ SourceLocation Loc);
+
+//===----------------------------------------------------------------------===//
+// Definitions of helper functions and methods for expanding macros.
+//===----------------------------------------------------------------------===//
+
+static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
+ const Preprocessor &PP) {
+
+ llvm::SmallString<200> ExpansionBuf;
+ llvm::raw_svector_ostream OS(ExpansionBuf);
+ TokenPrinter Printer(OS, PP);
+ std::string MacroName =
+ getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{});
+ return { MacroName, OS.str() };
+}
+
+static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
+ SourceLocation MacroLoc,
+ const Preprocessor &PP,
+ const MacroArgMap &PrevArgs) {
+
+ const SourceManager &SM = PP.getSourceManager();
+
+ MacroNameAndArgs Info = getMacroNameAndArgs(SM.getExpansionLoc(MacroLoc), PP);
+
+ // Manually expand its arguments from the previous macro.
+ Info.Args.expandFromPrevMacro(PrevArgs);
+
+ // Iterate over the macro's tokens and stringify them.
+ for (auto It = Info.MI->tokens_begin(), E = Info.MI->tokens_end(); It != E;
+ ++It) {
+ Token T = *It;
+
+ // If this token is not an identifier, we only need to print it.
+ if (T.isNot(tok::identifier)) {
+ Printer.printToken(T);
+ continue;
+ }
+
+ const auto *II = T.getIdentifierInfo();
+ assert(II &&
+ "This token is an identifier but has no IdentifierInfo!");
+
+ // If this token is a macro that should be expanded inside the current
+ // macro.
+ if (const MacroInfo *MI =
+ getMacroInfoForLocation(PP, SM, II, T.getLocation())) {
+ getMacroNameAndPrintExpansion(Printer, T.getLocation(), PP, Info.Args);
+
+ // If this is a function-like macro, skip its arguments, as
+ // getExpandedMacro() already printed them. If this is the case, let's
+ // first jump to the '(' token.
+ if (MI->getNumParams() != 0)
+ It = getMatchingRParen(++It, E);
+ continue;
+ }
+
+ // If this token is the current macro's argument, we should expand it.
+ auto ArgMapIt = Info.Args.find(II);
+ if (ArgMapIt != Info.Args.end()) {
+ for (MacroInfo::tokens_iterator ArgIt = ArgMapIt->second.begin(),
+ ArgEnd = ArgMapIt->second.end();
+ ArgIt != ArgEnd; ++ArgIt) {
+
+ // These tokens may still be macros, if that is the case, handle it the
+ // same way we did above.
+ const auto *ArgII = ArgIt->getIdentifierInfo();
+ if (!ArgII) {
+ Printer.printToken(*ArgIt);
+ continue;
+ }
+
+ const auto *MI = PP.getMacroInfo(ArgII);
+ if (!MI) {
+ Printer.printToken(*ArgIt);
+ continue;
+ }
+
+ getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP,
+ Info.Args);
+ if (MI->getNumParams() != 0)
+ ArgIt = getMatchingRParen(++ArgIt, ArgEnd);
+ }
+ continue;
+ }
+
+ // If control reached here, then this token isn't a macro identifier, nor an
+ // unexpanded macro argument that we need to handle, print it.
+ Printer.printToken(T);
+ }
+
+ return Info.Name;
+}
+
+static MacroNameAndArgs getMacroNameAndArgs(SourceLocation ExpanLoc,
+ const Preprocessor &PP) {
+
+ const SourceManager &SM = PP.getSourceManager();
+ const LangOptions &LangOpts = PP.getLangOpts();
+
+ // First, we create a Lexer to lex *at the expansion location* the tokens
+ // referring to the macro's name and its arguments.
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ExpanLoc);
+ const llvm::MemoryBuffer *MB = SM.getBuffer(LocInfo.first);
+ const char *MacroNameTokenPos = MB->getBufferStart() + LocInfo.second;
+
+ Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts,
+ MB->getBufferStart(), MacroNameTokenPos, MB->getBufferEnd());
+
+ // Acquire the macro's name.
+ Token TheTok;
+ RawLexer.LexFromRawLexer(TheTok);
+
+ std::string MacroName = PP.getSpelling(TheTok);
+
+ const auto *II = PP.getIdentifierInfo(MacroName);
+ assert(II && "Failed to acquire the IndetifierInfo for the macro!");
+
+ const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc);
+ assert(MI && "The macro must've been defined at it's expansion location!");
+
+ // Acquire the macro's arguments.
+ //
+ // The rough idea here is to lex from the first left parentheses to the last
+ // right parentheses, and map the macro's unexpanded arguments to what they
+ // will be expanded to. An expanded macro argument may contain several tokens
+ // (like '3 + 4'), so we'll lex until we find a tok::comma or tok::r_paren, at
+ // which point we start lexing the next argument or finish.
+ ArrayRef<const IdentifierInfo *> MacroArgs = MI->params();
+ if (MacroArgs.empty())
+ return { MacroName, MI, {} };
+
+ RawLexer.LexFromRawLexer(TheTok);
+ assert(TheTok.is(tok::l_paren) &&
+ "The token after the macro's identifier token should be '('!");
+
+ MacroArgMap Args;
+
+ // When the macro's argument is a function call, like
+ // CALL_FN(someFunctionName(param1, param2))
+ // we will find tok::l_paren, tok::r_paren, and tok::comma that do not divide
+ // actual macro arguments, or do not represent the macro argument's closing
+ // parentheses, so we'll count how many parentheses aren't closed yet.
+ // If ParanthesesDepth
+ // * = 0, then there are no more arguments to lex.
+ // * = 1, then if we find a tok::comma, we can start lexing the next arg.
+ // * > 1, then tok::comma is a part of the current arg.
+ int ParenthesesDepth = 1;
+
+ // If we encounter __VA_ARGS__, we will lex until the closing tok::r_paren,
+ // even if we lex a tok::comma and ParanthesesDepth == 1.
+ const IdentifierInfo *__VA_ARGS__II = PP.getIdentifierInfo("__VA_ARGS__");
+
+ for (const IdentifierInfo *UnexpArgII : MacroArgs) {
+ MacroArgMap::mapped_type ExpandedArgTokens;
+
+ // One could also simply not supply a single argument to __VA_ARGS__ -- this
+ // results in a preprocessor warning, but is not an error:
+ // #define VARIADIC(ptr, ...) \
+ // someVariadicTemplateFunction(__VA_ARGS__)
+ //
+ // int *ptr;
+ // VARIADIC(ptr); // Note that there are no commas, this isn't just an
+ // // empty parameter -- there are no parameters for '...'.
+ // In any other case, ParenthesesDepth mustn't be 0 here.
+ if (ParenthesesDepth != 0) {
+
+ // Lex the first token of the next macro parameter.
+ RawLexer.LexFromRawLexer(TheTok);
+
+ while (!(ParenthesesDepth == 1 &&
+ (UnexpArgII == __VA_ARGS__II ? false : TheTok.is(tok::comma)))) {
+ assert(TheTok.isNot(tok::eof) &&
+ "EOF encountered while looking for expanded macro args!");
+
+ if (TheTok.is(tok::l_paren))
+ ++ParenthesesDepth;
+
+ if (TheTok.is(tok::r_paren))
+ --ParenthesesDepth;
+
+ if (ParenthesesDepth == 0)
+ break;
+
+ if (TheTok.is(tok::raw_identifier))
+ PP.LookUpIdentifierInfo(TheTok);
+
+ ExpandedArgTokens.push_back(TheTok);
+ RawLexer.LexFromRawLexer(TheTok);
+ }
+ } else {
+ assert(UnexpArgII == __VA_ARGS__II);
+ }
+
+ Args.emplace(UnexpArgII, std::move(ExpandedArgTokens));
+ }
+
+ assert(TheTok.is(tok::r_paren) &&
+ "Expanded macro argument acquisition failed! After the end of the loop"
+ " this token should be ')'!");
+
+ return { MacroName, MI, Args };
+}
+
+static MacroInfo::tokens_iterator getMatchingRParen(
+ MacroInfo::tokens_iterator It,
+ MacroInfo::tokens_iterator End) {
+
+ assert(It->is(tok::l_paren) && "This token should be '('!");
+
+ // Skip until we find the closing ')'.
+ int ParenthesesDepth = 1;
+ while (ParenthesesDepth != 0) {
+ ++It;
+
+ assert(It->isNot(tok::eof) &&
+ "Encountered EOF while attempting to skip macro arguments!");
+ assert(It != End &&
+ "End of the macro definition reached before finding ')'!");
+
+ if (It->is(tok::l_paren))
+ ++ParenthesesDepth;
+
+ if (It->is(tok::r_paren))
+ --ParenthesesDepth;
+ }
+ return It;
+}
+
+static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
+ const SourceManager &SM,
+ const IdentifierInfo *II,
+ SourceLocation Loc) {
+
+ const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
+ if (!MD)
+ return nullptr;
+
+ return MD->findDirectiveAtLoc(Loc, SM).getMacroInfo();
+}
+
+void MacroArgMap::expandFromPrevMacro(const MacroArgMap &Super) {
+
+ for (value_type &Pair : *this) {
+ ExpArgTokens &CurrExpArgTokens = Pair.second;
+
+ // For each token in the expanded macro argument.
+ auto It = CurrExpArgTokens.begin();
+ while (It != CurrExpArgTokens.end()) {
+ if (It->isNot(tok::identifier)) {
+ ++It;
+ continue;
+ }
+
+ const auto *II = It->getIdentifierInfo();
+ assert(II);
+
+ // Is this an argument that "Super" expands further?
+ if (!Super.count(II)) {
+ ++It;
+ continue;
+ }
+
+ const ExpArgTokens &SuperExpArgTokens = Super.at(II);
+
+ It = CurrExpArgTokens.insert(
+ It, SuperExpArgTokens.begin(), SuperExpArgTokens.end());
+ std::advance(It, SuperExpArgTokens.size());
+ It = CurrExpArgTokens.erase(It);
+ }
+ }
+}
+
+void TokenPrinter::printToken(const Token &Tok) {
+ // If this is the first token to be printed, don't print space.
+ if (PrevTok.isNot(tok::unknown)) {
+ // If the tokens were already space separated, or if they must be to avoid
+ // them being implicitly pasted, add a space between them.
+ if(Tok.hasLeadingSpace() || ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok,
+ Tok)) {
+ // AvoidConcat doesn't check for ##, don't print a space around it.
+ if (PrevTok.isNot(tok::hashhash) && Tok.isNot(tok::hashhash)) {
+ OS << ' ';
+ }
+ }
+ }
+
+ if (!Tok.isOneOf(tok::hash, tok::hashhash)) {
+ if (PrevTok.is(tok::hash))
+ OS << '\"' << PP.getSpelling(Tok) << '\"';
+ else
+ OS << PP.getSpelling(Tok);
+ }
+
+ PrevPrevTok = PrevTok;
+ PrevTok = Tok;
+}
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index 94e2e00d8bbc..2e2e2ec94f39 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -69,6 +69,10 @@ ProgramState::~ProgramState() {
stateMgr->getStoreManager().decrementReferenceCount(store);
}
+int64_t ProgramState::getID() const {
+ return getStateManager().Alloc.identifyKnownAlignedObject<ProgramState>(this);
+}
+
ProgramStateManager::ProgramStateManager(ASTContext &Ctx,
StoreManagerCreator CreateSMgr,
ConstraintManagerCreator CreateCMgr,
@@ -121,8 +125,8 @@ ProgramStateRef ProgramState::bindLoc(Loc LV,
ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
LV, V));
const MemRegion *MR = LV.getAsRegion();
- if (MR && Mgr.getOwningEngine() && notifyChanges)
- return Mgr.getOwningEngine()->processRegionChange(newState, MR, LCtx);
+ if (MR && notifyChanges)
+ return Mgr.getOwningEngine().processRegionChange(newState, MR, LCtx);
return newState;
}
@@ -134,9 +138,7 @@ ProgramState::bindDefaultInitial(SVal loc, SVal V,
const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
const StoreRef &newStore = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
ProgramStateRef new_state = makeWithStore(newStore);
- return Mgr.getOwningEngine()
- ? Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx)
- : new_state;
+ return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
}
ProgramStateRef
@@ -145,9 +147,7 @@ ProgramState::bindDefaultZero(SVal loc, const LocationContext *LCtx) const {
const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
const StoreRef &newStore = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
ProgramStateRef new_state = makeWithStore(newStore);
- return Mgr.getOwningEngine()
- ? Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx)
- : new_state;
+ return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
}
typedef ArrayRef<const MemRegion *> RegionList;
@@ -192,41 +192,34 @@ ProgramState::invalidateRegionsImpl(ValueList Values,
RegionAndSymbolInvalidationTraits *ITraits,
const CallEvent *Call) const {
ProgramStateManager &Mgr = getStateManager();
- SubEngine* Eng = Mgr.getOwningEngine();
+ SubEngine &Eng = Mgr.getOwningEngine();
- InvalidatedSymbols Invalidated;
+ InvalidatedSymbols InvalidatedSyms;
if (!IS)
- IS = &Invalidated;
+ IS = &InvalidatedSyms;
RegionAndSymbolInvalidationTraits ITraitsLocal;
if (!ITraits)
ITraits = &ITraitsLocal;
- if (Eng) {
- StoreManager::InvalidatedRegions TopLevelInvalidated;
- StoreManager::InvalidatedRegions Invalidated;
- const StoreRef &newStore
- = Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
- *IS, *ITraits, &TopLevelInvalidated,
- &Invalidated);
-
- ProgramStateRef newState = makeWithStore(newStore);
-
- if (CausedByPointerEscape) {
- newState = Eng->notifyCheckersOfPointerEscape(newState, IS,
- TopLevelInvalidated,
- Invalidated, Call,
- *ITraits);
- }
+ StoreManager::InvalidatedRegions TopLevelInvalidated;
+ StoreManager::InvalidatedRegions Invalidated;
+ const StoreRef &newStore
+ = Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
+ *IS, *ITraits, &TopLevelInvalidated,
+ &Invalidated);
+
+ ProgramStateRef newState = makeWithStore(newStore);
- return Eng->processRegionChanges(newState, IS, TopLevelInvalidated,
- Invalidated, LCtx, Call);
+ if (CausedByPointerEscape) {
+ newState = Eng.notifyCheckersOfPointerEscape(newState, IS,
+ TopLevelInvalidated,
+ Call,
+ *ITraits);
}
- const StoreRef &newStore =
- Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
- *IS, *ITraits, nullptr, nullptr);
- return makeWithStore(newStore);
+ return Eng.processRegionChanges(newState, IS, TopLevelInvalidated,
+ Invalidated, LCtx, Call);
}
ProgramStateRef ProgramState::killBinding(Loc LV) const {
@@ -449,14 +442,16 @@ void ProgramState::setStore(const StoreRef &newStore) {
// State pretty-printing.
//===----------------------------------------------------------------------===//
-void ProgramState::print(raw_ostream &Out, const char *NL, const char *Sep,
+void ProgramState::print(raw_ostream &Out,
+ const char *NL, const char *Sep,
const LocationContext *LC) const {
// Print the store.
ProgramStateManager &Mgr = getStateManager();
- Mgr.getStoreManager().print(getStore(), Out, NL, Sep);
+ const ASTContext &Context = getStateManager().getContext();
+ Mgr.getStoreManager().print(getStore(), Out, NL);
// Print out the environment.
- Env.print(Out, NL, Sep, LC);
+ Env.print(Out, NL, Sep, Context, LC);
// Print out the constraints.
Mgr.getConstraintManager().print(this, Out, NL, Sep);
@@ -465,13 +460,14 @@ void ProgramState::print(raw_ostream &Out, const char *NL, const char *Sep,
printDynamicTypeInfo(this, Out, NL, Sep);
// Print out tainted symbols.
- printTaint(Out, NL, Sep);
+ printTaint(Out, NL);
// Print checker-specific data.
- Mgr.getOwningEngine()->printState(Out, this, NL, Sep, LC);
+ Mgr.getOwningEngine().printState(Out, this, NL, Sep, LC);
}
-void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LC) const {
+void ProgramState::printDOT(raw_ostream &Out,
+ const LocationContext *LC) const {
print(Out, "\\l", "\\|", LC);
}
@@ -480,7 +476,7 @@ LLVM_DUMP_METHOD void ProgramState::dump() const {
}
void ProgramState::printTaint(raw_ostream &Out,
- const char *NL, const char *Sep) const {
+ const char *NL) const {
TaintMapImpl TM = get<TaintMap>();
if (!TM.isEmpty())
@@ -496,7 +492,7 @@ void ProgramState::dumpTaint() const {
}
AnalysisManager& ProgramState::getAnalysisManager() const {
- return stateMgr->getOwningEngine()->getAnalysisManager();
+ return stateMgr->getOwningEngine().getAnalysisManager();
}
//===----------------------------------------------------------------------===//
@@ -652,22 +648,12 @@ bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const
return S.scan(val);
}
-bool ProgramState::scanReachableSymbols(const SVal *I, const SVal *E,
- SymbolVisitor &visitor) const {
+bool ProgramState::scanReachableSymbols(
+ llvm::iterator_range<region_iterator> Reachable,
+ SymbolVisitor &visitor) const {
ScanReachableSymbols S(this, visitor);
- for ( ; I != E; ++I) {
- if (!S.scan(*I))
- return false;
- }
- return true;
-}
-
-bool ProgramState::scanReachableSymbols(const MemRegion * const *I,
- const MemRegion * const *E,
- SymbolVisitor &visitor) const {
- ScanReachableSymbols S(this, visitor);
- for ( ; I != E; ++I) {
- if (!S.scan(*I))
+ for (const MemRegion *R : Reachable) {
+ if (!S.scan(R))
return false;
}
return true;
@@ -835,4 +821,3 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const {
return false;
}
-
diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index e8c7bdbde385..d9b58d0f5185 100644
--- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -399,7 +399,7 @@ RangeConstraintManager::removeDeadBindings(ProgramStateRef State,
for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
SymbolRef Sym = I.getKey();
- if (SymReaper.maybeDead(Sym)) {
+ if (SymReaper.isDead(Sym)) {
Changed = true;
CR = CRFactory.remove(CR, Sym);
}
diff --git a/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
index f99853f07073..146dc20ad021 100644
--- a/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
@@ -200,6 +200,11 @@ void RangedConstraintManager::computeAdjustment(SymbolRef &Sym,
}
}
+void *ProgramStateTrait<ConstraintRange>::GDMIndex() {
+ static int Index;
+ return &Index;
+}
+
} // end of namespace ento
} // end of namespace clang
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index db6449e6d5f3..b2339be4f263 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/TargetInfo.h"
@@ -61,7 +62,9 @@ private:
: P(r, k), Data(offset) {
assert(r && "Must have known regions.");
assert(getOffset() == offset && "Failed to store offset");
- assert((r == r->getBaseRegion() || isa<ObjCIvarRegion>(r)) && "Not a base");
+ assert((r == r->getBaseRegion() || isa<ObjCIvarRegion>(r) ||
+ isa <CXXDerivedObjectRegion>(r)) &&
+ "Not a base");
}
public:
@@ -308,7 +311,7 @@ public:
//===----------------------------------------------------------------------===//
namespace {
-class invalidateRegionsWorker;
+class InvalidateRegionsWorker;
class RegionStoreManager : public StoreManager {
public:
@@ -335,7 +338,7 @@ private:
/// A helper used to populate the work list with the given set of
/// regions.
- void populateWorkList(invalidateRegionsWorker &W,
+ void populateWorkList(InvalidateRegionsWorker &W,
ArrayRef<SVal> Values,
InvalidatedRegions *TopLevelRegions);
@@ -344,11 +347,9 @@ public:
: StoreManager(mgr), Features(f),
RBFactory(mgr.getAllocator()), CBFactory(mgr.getAllocator()),
SmallStructLimit(0) {
- if (SubEngine *Eng = StateMgr.getOwningEngine()) {
- AnalyzerOptions &Options = Eng->getAnalysisManager().options;
- SmallStructLimit =
- Options.getOptionAsInteger("region-store-small-struct-limit", 2);
- }
+ SubEngine &Eng = StateMgr.getOwningEngine();
+ AnalyzerOptions &Options = Eng.getAnalysisManager().options;
+ SmallStructLimit = Options.RegionStoreSmallStructLimit;
}
@@ -598,8 +599,7 @@ public: // Part of public interface to class.
RBFactory.getTreeFactory());
}
- void print(Store store, raw_ostream &Out, const char* nl,
- const char *sep) override;
+ void print(Store store, raw_ostream &Out, const char* nl) override;
void iterBindings(Store store, BindingsHandler& f) override {
RegionBindingsRef B = getRegionBindings(store);
@@ -945,7 +945,7 @@ RegionStoreManager::removeSubRegionBindings(RegionBindingsConstRef B,
}
namespace {
-class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
+class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
{
const Expr *Ex;
unsigned Count;
@@ -955,7 +955,7 @@ class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
StoreManager::InvalidatedRegions *Regions;
GlobalsFilterKind GlobalsFilter;
public:
- invalidateRegionsWorker(RegionStoreManager &rm,
+ InvalidateRegionsWorker(RegionStoreManager &rm,
ProgramStateManager &stateMgr,
RegionBindingsRef b,
const Expr *ex, unsigned count,
@@ -964,7 +964,7 @@ public:
RegionAndSymbolInvalidationTraits &ITraitsIn,
StoreManager::InvalidatedRegions *r,
GlobalsFilterKind GFK)
- : ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b),
+ : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b),
Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
GlobalsFilter(GFK) {}
@@ -985,14 +985,14 @@ public:
};
}
-bool invalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
+bool InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
bool doNotInvalidateSuperRegion = ITraits.hasTrait(
R, RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion();
return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
}
-void invalidateRegionsWorker::VisitBinding(SVal V) {
+void InvalidateRegionsWorker::VisitBinding(SVal V) {
// A symbol? Mark it touched by the invalidation.
if (SymbolRef Sym = V.getAsSymbol())
IS.insert(Sym);
@@ -1017,7 +1017,7 @@ void invalidateRegionsWorker::VisitBinding(SVal V) {
}
}
-void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
+void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
const ClusterBindings *C) {
bool PreserveRegionsContents =
@@ -1033,6 +1033,32 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
B = B.remove(baseR);
}
+ if (const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
+ if (const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
+
+ // Lambdas can affect all static local variables without explicitly
+ // capturing those.
+ // We invalidate all static locals referenced inside the lambda body.
+ if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
+ using namespace ast_matchers;
+
+ const char *DeclBind = "DeclBind";
+ StatementMatcher RefToStatic = stmt(hasDescendant(declRefExpr(
+ to(varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
+ auto Matches =
+ match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
+ RD->getASTContext());
+
+ for (BoundNodes &Match : Matches) {
+ auto *VD = Match.getNodeAs<VarDecl>(DeclBind);
+ const VarRegion *ToInvalidate =
+ RM.getRegionManager().getVarRegion(VD, LCtx);
+ AddToWorkList(ToInvalidate);
+ }
+ }
+ }
+ }
+
// BlockDataRegion? If so, invalidate captured variables that are passed
// by reference.
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
@@ -1181,7 +1207,7 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
B = B.addBinding(baseR, BindingKey::Direct, V);
}
-bool invalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
+bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
const MemRegion *R) {
switch (GlobalsFilter) {
case GFK_None:
@@ -1195,7 +1221,7 @@ bool invalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
llvm_unreachable("unknown globals filter");
}
-bool invalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
+bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
if (isInitiallyIncludedGlobalRegion(Base))
return true;
@@ -1229,7 +1255,7 @@ RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K,
return B;
}
-void RegionStoreManager::populateWorkList(invalidateRegionsWorker &W,
+void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
ArrayRef<SVal> Values,
InvalidatedRegions *TopLevelRegions) {
for (ArrayRef<SVal>::iterator I = Values.begin(),
@@ -1280,7 +1306,7 @@ RegionStoreManager::invalidateRegions(Store store,
}
RegionBindingsRef B = getRegionBindings(store);
- invalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, ITraits,
+ InvalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, ITraits,
Invalidated, GlobalsFilter);
// Scan the bindings and generate the clusters.
@@ -1302,11 +1328,11 @@ RegionStoreManager::invalidateRegions(Store store,
case GFK_All:
B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
Ex, Count, LCtx, B, Invalidated);
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case GFK_SystemOnly:
B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
Ex, Count, LCtx, B, Invalidated);
- // FALLTHROUGH
+ LLVM_FALLTHROUGH;
case GFK_None:
break;
}
@@ -2363,40 +2389,45 @@ RegionStoreManager::bindAggregate(RegionBindingsConstRef B,
//===----------------------------------------------------------------------===//
namespace {
-class removeDeadBindingsWorker :
- public ClusterAnalysis<removeDeadBindingsWorker> {
- SmallVector<const SymbolicRegion*, 12> Postponed;
+class RemoveDeadBindingsWorker
+ : public ClusterAnalysis<RemoveDeadBindingsWorker> {
+ using ChildrenListTy = SmallVector<const SymbolDerived *, 4>;
+ using MapParentsToDerivedTy = llvm::DenseMap<SymbolRef, ChildrenListTy>;
+
+ MapParentsToDerivedTy ParentsToDerived;
SymbolReaper &SymReaper;
const StackFrameContext *CurrentLCtx;
public:
- removeDeadBindingsWorker(RegionStoreManager &rm,
+ RemoveDeadBindingsWorker(RegionStoreManager &rm,
ProgramStateManager &stateMgr,
RegionBindingsRef b, SymbolReaper &symReaper,
const StackFrameContext *LCtx)
- : ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b),
+ : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr, b),
SymReaper(symReaper), CurrentLCtx(LCtx) {}
// Called by ClusterAnalysis.
void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C);
void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
- using ClusterAnalysis<removeDeadBindingsWorker>::VisitCluster;
+ using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
using ClusterAnalysis::AddToWorkList;
bool AddToWorkList(const MemRegion *R);
- bool UpdatePostponed();
void VisitBinding(SVal V);
+
+private:
+ void populateWorklistFromSymbol(SymbolRef s);
};
}
-bool removeDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
+bool RemoveDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
const MemRegion *BaseR = R->getBaseRegion();
return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
}
-void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
+void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
const ClusterBindings &C) {
if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
@@ -2407,10 +2438,11 @@ void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
}
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
- if (SymReaper.isLive(SR->getSymbol()))
+ if (SymReaper.isLive(SR->getSymbol())) {
AddToWorkList(SR, &C);
- else
- Postponed.push_back(SR);
+ } else if (const auto *SD = dyn_cast<SymbolDerived>(SR->getSymbol())) {
+ ParentsToDerived[SD->getParentSymbol()].push_back(SD);
+ }
return;
}
@@ -2422,7 +2454,7 @@ void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
// CXXThisRegion in the current or parent location context is live.
if (const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
- const StackArgumentsSpaceRegion *StackReg =
+ const auto *StackReg =
cast<StackArgumentsSpaceRegion>(TR->getSuperRegion());
const StackFrameContext *RegCtx = StackReg->getStackFrame();
if (CurrentLCtx &&
@@ -2431,7 +2463,7 @@ void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
}
}
-void removeDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
+void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
const ClusterBindings *C) {
if (!C)
return;
@@ -2449,7 +2481,7 @@ void removeDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
}
}
-void removeDeadBindingsWorker::VisitBinding(SVal V) {
+void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
// Is it a LazyCompoundVal? All referenced regions are live as well.
if (Optional<nonloc::LazyCompoundVal> LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
@@ -2467,6 +2499,15 @@ void removeDeadBindingsWorker::VisitBinding(SVal V) {
// If V is a region, then add it to the worklist.
if (const MemRegion *R = V.getAsRegion()) {
AddToWorkList(R);
+
+ if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) {
+ DefinedOrUnknownSVal RVS =
+ RM.getSValBuilder().getRegionValueSymbolVal(TVR);
+ if (const MemRegion *SR = RVS.getAsRegion()) {
+ AddToWorkList(SR);
+ }
+ }
+
SymReaper.markLive(R);
// All regions captured by a block are also live.
@@ -2480,34 +2521,37 @@ void removeDeadBindingsWorker::VisitBinding(SVal V) {
// Update the set of live symbols.
- for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end();
- SI!=SE; ++SI)
+ for (auto SI = V.symbol_begin(), SE = V.symbol_end(); SI != SE; ++SI) {
+ populateWorklistFromSymbol(*SI);
+
+ for (const auto *SD : ParentsToDerived[*SI])
+ populateWorklistFromSymbol(SD);
+
SymReaper.markLive(*SI);
+ }
}
-bool removeDeadBindingsWorker::UpdatePostponed() {
- // See if any postponed SymbolicRegions are actually live now, after
- // having done a scan.
- bool changed = false;
+void RemoveDeadBindingsWorker::populateWorklistFromSymbol(SymbolRef S) {
+ if (const auto *SD = dyn_cast<SymbolData>(S)) {
+ if (Loc::isLocType(SD->getType()) && !SymReaper.isLive(SD)) {
+ const SymbolicRegion *SR = RM.getRegionManager().getSymbolicRegion(SD);
- for (SmallVectorImpl<const SymbolicRegion*>::iterator
- I = Postponed.begin(), E = Postponed.end() ; I != E ; ++I) {
- if (const SymbolicRegion *SR = *I) {
- if (SymReaper.isLive(SR->getSymbol())) {
- changed |= AddToWorkList(SR);
- *I = nullptr;
- }
+ if (B.contains(SR))
+ AddToWorkList(SR);
+
+ const SymbolicRegion *SHR =
+ RM.getRegionManager().getSymbolicHeapRegion(SD);
+ if (B.contains(SHR))
+ AddToWorkList(SHR);
}
}
-
- return changed;
}
StoreRef RegionStoreManager::removeDeadBindings(Store store,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper) {
RegionBindingsRef B = getRegionBindings(store);
- removeDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
+ RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
W.GenerateClusters();
// Enqueue the region roots onto the worklist.
@@ -2516,7 +2560,7 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store,
W.AddToWorkList(*I);
}
- do W.RunWorkList(); while (W.UpdatePostponed());
+ W.RunWorkList();
// We have now scanned the store, marking reachable regions and symbols
// as live. We now remove all the regions that are dead from the store
@@ -2525,24 +2569,9 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store,
const MemRegion *Base = I.getKey();
// If the cluster has been visited, we know the region has been marked.
- if (W.isVisited(Base))
- continue;
-
- // Remove the dead entry.
- B = B.remove(Base);
-
- if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(Base))
- SymReaper.maybeDead(SymR->getSymbol());
-
- // Mark all non-live symbols that this binding references as dead.
- const ClusterBindings &Cluster = I.getData();
- for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
- CI != CE; ++CI) {
- SVal X = CI.getData();
- SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
- for (; SI != SE; ++SI)
- SymReaper.maybeDead(*SI);
- }
+ // Otherwise, remove the dead entry.
+ if (!W.isVisited(Base))
+ B = B.remove(Base);
}
return StoreRef(B.asStore(), *this);
@@ -2553,7 +2582,7 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store,
//===----------------------------------------------------------------------===//
void RegionStoreManager::print(Store store, raw_ostream &OS,
- const char* nl, const char *sep) {
+ const char* nl) {
RegionBindingsRef B = getRegionBindings(store);
OS << "Store (direct and default bindings), "
<< B.asStore()
diff --git a/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp b/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
new file mode 100644
index 000000000000..2e40cc33381c
--- /dev/null
+++ b/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
@@ -0,0 +1,1229 @@
+//== RetainSummaryManager.cpp - Summaries for reference counting --*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines summaries implementation for retain counting, which
+// implements a reference count checker for Core Foundation, Cocoa
+// and OSObject (on Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang;
+using namespace ento;
+
+template <class T>
+constexpr static bool isOneOf() {
+ return false;
+}
+
+/// Helper function to check whether the class is one of the
+/// rest of varargs.
+template <class T, class P, class... ToCompare>
+constexpr static bool isOneOf() {
+ return std::is_same<T, P>::value || isOneOf<T, ToCompare...>();
+}
+
+namespace {
+
+/// Fake attribute class for RC* attributes.
+struct GeneralizedReturnsRetainedAttr {
+ static bool classof(const Attr *A) {
+ if (auto AA = dyn_cast<AnnotateAttr>(A))
+ return AA->getAnnotation() == "rc_ownership_returns_retained";
+ return false;
+ }
+};
+
+struct GeneralizedReturnsNotRetainedAttr {
+ static bool classof(const Attr *A) {
+ if (auto AA = dyn_cast<AnnotateAttr>(A))
+ return AA->getAnnotation() == "rc_ownership_returns_not_retained";
+ return false;
+ }
+};
+
+struct GeneralizedConsumedAttr {
+ static bool classof(const Attr *A) {
+ if (auto AA = dyn_cast<AnnotateAttr>(A))
+ return AA->getAnnotation() == "rc_ownership_consumed";
+ return false;
+ }
+};
+
+}
+
+template <class T>
+Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
+ QualType QT) {
+ ObjKind K;
+ if (isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr,
+ CFReturnsNotRetainedAttr>()) {
+ if (!TrackObjCAndCFObjects)
+ return None;
+
+ K = ObjKind::CF;
+ } else if (isOneOf<T, NSConsumedAttr, NSConsumesSelfAttr,
+ NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr,
+ NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) {
+
+ if (!TrackObjCAndCFObjects)
+ return None;
+
+ if (isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr,
+ NSReturnsNotRetainedAttr>() &&
+ !cocoa::isCocoaObjectRef(QT))
+ return None;
+ K = ObjKind::ObjC;
+ } else if (isOneOf<T, OSConsumedAttr, OSConsumesThisAttr,
+ OSReturnsNotRetainedAttr, OSReturnsRetainedAttr,
+ OSReturnsRetainedOnZeroAttr,
+ OSReturnsRetainedOnNonZeroAttr>()) {
+ if (!TrackOSObjects)
+ return None;
+ K = ObjKind::OS;
+ } else if (isOneOf<T, GeneralizedReturnsNotRetainedAttr,
+ GeneralizedReturnsRetainedAttr,
+ GeneralizedConsumedAttr>()) {
+ K = ObjKind::Generalized;
+ } else {
+ llvm_unreachable("Unexpected attribute");
+ }
+ if (D->hasAttr<T>())
+ return K;
+ return None;
+}
+
+template <class T1, class T2, class... Others>
+Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
+ QualType QT) {
+ if (auto Out = hasAnyEnabledAttrOf<T1>(D, QT))
+ return Out;
+ return hasAnyEnabledAttrOf<T2, Others...>(D, QT);
+}
+
+const RetainSummary *
+RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
+ // Unique "simple" summaries -- those without ArgEffects.
+ if (OldSumm.isSimple()) {
+ ::llvm::FoldingSetNodeID ID;
+ OldSumm.Profile(ID);
+
+ void *Pos;
+ CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
+
+ if (!N) {
+ N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
+ new (N) CachedSummaryNode(OldSumm);
+ SimpleSummaries.InsertNode(N, Pos);
+ }
+
+ return &N->getValue();
+ }
+
+ RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
+ new (Summ) RetainSummary(OldSumm);
+ return Summ;
+}
+
+static bool isSubclass(const Decl *D,
+ StringRef ClassName) {
+ using namespace ast_matchers;
+ DeclarationMatcher SubclassM = cxxRecordDecl(isSameOrDerivedFrom(ClassName));
+ return !(match(SubclassM, *D, D->getASTContext()).empty());
+}
+
+static bool isOSObjectSubclass(const Decl *D) {
+ return isSubclass(D, "OSObject");
+}
+
+static bool isOSObjectDynamicCast(StringRef S) {
+ return S == "safeMetaCast";
+}
+
+static bool isOSIteratorSubclass(const Decl *D) {
+ return isSubclass(D, "OSIterator");
+}
+
+static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
+ for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
+ if (Ann->getAnnotation() == rcAnnotation)
+ return true;
+ }
+ return false;
+}
+
+static bool isRetain(const FunctionDecl *FD, StringRef FName) {
+ return FName.startswith_lower("retain") || FName.endswith_lower("retain");
+}
+
+static bool isRelease(const FunctionDecl *FD, StringRef FName) {
+ return FName.startswith_lower("release") || FName.endswith_lower("release");
+}
+
+static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
+ return FName.startswith_lower("autorelease") ||
+ FName.endswith_lower("autorelease");
+}
+
+static bool isMakeCollectable(StringRef FName) {
+ return FName.contains_lower("MakeCollectable");
+}
+
+/// A function is OSObject related if it is declared on a subclass
+/// of OSObject, or any of the parameters is a subclass of an OSObject.
+static bool isOSObjectRelated(const CXXMethodDecl *MD) {
+ if (isOSObjectSubclass(MD->getParent()))
+ return true;
+
+ for (ParmVarDecl *Param : MD->parameters()) {
+ QualType PT = Param->getType()->getPointeeType();
+ if (!PT.isNull())
+ if (CXXRecordDecl *RD = PT->getAsCXXRecordDecl())
+ if (isOSObjectSubclass(RD))
+ return true;
+ }
+
+ return false;
+}
+
+const RetainSummary *
+RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD,
+ StringRef FName, QualType RetTy) {
+ if (RetTy->isPointerType()) {
+ const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl();
+ if (PD && isOSObjectSubclass(PD)) {
+ if (const IdentifierInfo *II = FD->getIdentifier()) {
+ if (isOSObjectDynamicCast(II->getName()))
+ return getDefaultSummary();
+
+ // All objects returned with functions *not* starting with
+ // get, or iterators, are returned at +1.
+ if ((!II->getName().startswith("get") &&
+ !II->getName().startswith("Get")) ||
+ isOSIteratorSubclass(PD)) {
+ return getOSSummaryCreateRule(FD);
+ } else {
+ return getOSSummaryGetRule(FD);
+ }
+ }
+ }
+ }
+
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXRecordDecl *Parent = MD->getParent();
+ if (TrackOSObjects && Parent && isOSObjectSubclass(Parent)) {
+ if (FName == "release")
+ return getOSSummaryReleaseRule(FD);
+
+ if (FName == "retain")
+ return getOSSummaryRetainRule(FD);
+
+ if (FName == "free")
+ return getOSSummaryFreeRule(FD);
+
+ if (MD->getOverloadedOperator() == OO_New)
+ return getOSSummaryCreateRule(MD);
+ }
+ }
+
+ return nullptr;
+}
+
+const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
+ const FunctionDecl *FD,
+ StringRef FName,
+ QualType RetTy,
+ const FunctionType *FT,
+ bool &AllowAnnotations) {
+
+ ArgEffects ScratchArgs(AF.getEmptyMap());
+
+ std::string RetTyName = RetTy.getAsString();
+ if (FName == "pthread_create" || FName == "pthread_setspecific") {
+ // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
+ // This will be addressed better with IPA.
+ return getPersistentStopSummary();
+ } else if(FName == "NSMakeCollectable") {
+ // Handle: id NSMakeCollectable(CFTypeRef)
+ AllowAnnotations = false;
+ return RetTy->isObjCIdType() ? getUnarySummary(FT, DoNothing)
+ : getPersistentStopSummary();
+ } else if (FName == "CMBufferQueueDequeueAndRetain" ||
+ FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
+ // Part of: <rdar://problem/39390714>.
+ return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
+ ScratchArgs,
+ ArgEffect(DoNothing),
+ ArgEffect(DoNothing));
+ } else if (FName == "CFPlugInInstanceCreate") {
+ return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs);
+ } else if (FName == "IORegistryEntrySearchCFProperty" ||
+ (RetTyName == "CFMutableDictionaryRef" &&
+ (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||
+ FName == "IOServiceNameMatching" ||
+ FName == "IORegistryEntryIDMatching" ||
+ FName == "IOOpenFirmwarePathMatching"))) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName == "IOServiceGetMatchingService" ||
+ FName == "IOServiceGetMatchingServices") {
+ // FIXES: <rdar://problem/6326900>
+ // This should be addressed using a API table. This strcmp is also
+ // a little gross, but there is no need to super optimize here.
+ ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF));
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName == "IOServiceAddNotification" ||
+ FName == "IOServiceAddMatchingNotification") {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF));
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName == "CVPixelBufferCreateWithBytes") {
+ // FIXES: <rdar://problem/7283567>
+ // Eventually this can be improved by recognizing that the pixel
+ // buffer passed to CVPixelBufferCreateWithBytes is released via
+ // a callback and doing full IPA to make sure this is done correctly.
+ // FIXME: This function has an out parameter that returns an
+ // allocated object.
+ ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking));
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName == "CGBitmapContextCreateWithData") {
+ // FIXES: <rdar://problem/7358899>
+ // Eventually this can be improved by recognizing that 'releaseInfo'
+ // passed to CGBitmapContextCreateWithData is released via
+ // a callback and doing full IPA to make sure this is done correctly.
+ ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking)));
+ return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
+ // FIXES: <rdar://problem/7283567>
+ // Eventually this can be improved by recognizing that the pixel
+ // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
+ // via a callback and doing full IPA to make sure this is done
+ // correctly.
+ ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking));
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName == "VTCompressionSessionEncodeFrame") {
+ // The context argument passed to VTCompressionSessionEncodeFrame()
+ // is passed to the callback specified when creating the session
+ // (e.g. with VTCompressionSessionCreate()) which can release it.
+ // To account for this possibility, conservatively stop tracking
+ // the context.
+ ScratchArgs = AF.add(ScratchArgs, 5, ArgEffect(StopTracking));
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName == "dispatch_set_context" ||
+ FName == "xpc_connection_set_context") {
+ // <rdar://problem/11059275> - The analyzer currently doesn't have
+ // a good way to reason about the finalizer function for libdispatch.
+ // If we pass a context object that is memory managed, stop tracking it.
+ // <rdar://problem/13783514> - Same problem, but for XPC.
+ // FIXME: this hack should possibly go away once we can handle
+ // libdispatch and XPC finalizers.
+ ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ } else if (FName.startswith("NSLog")) {
+ return getDoNothingSummary();
+ } else if (FName.startswith("NS") &&
+ (FName.find("Insert") != StringRef::npos)) {
+ // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
+ // be deallocated by NSMapRemove. (radar://11152419)
+ ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
+ ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(StopTracking));
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs, ArgEffect(DoNothing),
+ ArgEffect(DoNothing));
+ }
+
+ if (RetTy->isPointerType()) {
+
+ // For CoreFoundation ('CF') types.
+ if (cocoa::isRefType(RetTy, "CF", FName)) {
+ if (isRetain(FD, FName)) {
+ // CFRetain isn't supposed to be annotated. However, this may as
+ // well be a user-made "safe" CFRetain function that is incorrectly
+ // annotated as cf_returns_retained due to lack of better options.
+ // We want to ignore such annotation.
+ AllowAnnotations = false;
+
+ return getUnarySummary(FT, IncRef);
+ } else if (isAutorelease(FD, FName)) {
+ // The headers use cf_consumed, but we can fully model CFAutorelease
+ // ourselves.
+ AllowAnnotations = false;
+
+ return getUnarySummary(FT, Autorelease);
+ } else if (isMakeCollectable(FName)) {
+ AllowAnnotations = false;
+ return getUnarySummary(FT, DoNothing);
+ } else {
+ return getCFCreateGetRuleSummary(FD);
+ }
+ }
+
+ // For CoreGraphics ('CG') and CoreVideo ('CV') types.
+ if (cocoa::isRefType(RetTy, "CG", FName) ||
+ cocoa::isRefType(RetTy, "CV", FName)) {
+ if (isRetain(FD, FName))
+ return getUnarySummary(FT, IncRef);
+ else
+ return getCFCreateGetRuleSummary(FD);
+ }
+
+ // For all other CF-style types, use the Create/Get
+ // rule for summaries but don't support Retain functions
+ // with framework-specific prefixes.
+ if (coreFoundation::isCFObjectRef(RetTy)) {
+ return getCFCreateGetRuleSummary(FD);
+ }
+
+ if (FD->hasAttr<CFAuditedTransferAttr>()) {
+ return getCFCreateGetRuleSummary(FD);
+ }
+ }
+
+ // Check for release functions, the only kind of functions that we care
+ // about that don't return a pointer type.
+ if (FName.startswith("CG") || FName.startswith("CF")) {
+ // Test for 'CGCF'.
+ FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
+
+ if (isRelease(FD, FName))
+ return getUnarySummary(FT, DecRef);
+ else {
+ assert(ScratchArgs.isEmpty());
+ // Remaining CoreFoundation and CoreGraphics functions.
+ // We use to assume that they all strictly followed the ownership idiom
+ // and that ownership cannot be transferred. While this is technically
+ // correct, many methods allow a tracked object to escape. For example:
+ //
+ // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
+ // CFDictionaryAddValue(y, key, x);
+ // CFRelease(x);
+ // ... it is okay to use 'x' since 'y' has a reference to it
+ //
+ // We handle this and similar cases with the follow heuristic. If the
+ // function name contains "InsertValue", "SetValue", "AddValue",
+ // "AppendValue", or "SetAttribute", then we assume that arguments may
+ // "escape." This means that something else holds on to the object,
+ // allowing it be used even after its local retain count drops to 0.
+ ArgEffectKind E =
+ (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
+ ? MayEscape
+ : DoNothing;
+
+ return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(E, ObjKind::CF));
+ }
+ }
+
+ return nullptr;
+}
+
+const RetainSummary *
+RetainSummaryManager::generateSummary(const FunctionDecl *FD,
+ bool &AllowAnnotations) {
+ // We generate "stop" summaries for implicitly defined functions.
+ if (FD->isImplicit())
+ return getPersistentStopSummary();
+
+ const IdentifierInfo *II = FD->getIdentifier();
+
+ StringRef FName = II ? II->getName() : "";
+
+ // Strip away preceding '_'. Doing this here will effect all the checks
+ // down below.
+ FName = FName.substr(FName.find_first_not_of('_'));
+
+ // Inspect the result type. Strip away any typedefs.
+ const auto *FT = FD->getType()->getAs<FunctionType>();
+ QualType RetTy = FT->getReturnType();
+
+ if (TrackOSObjects)
+ if (const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy))
+ return S;
+
+ if (TrackObjCAndCFObjects)
+ if (const RetainSummary *S =
+ getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations))
+ return S;
+
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
+ if (!(TrackOSObjects && isOSObjectRelated(MD)))
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ArgEffects(AF.getEmptyMap()),
+ ArgEffect(DoNothing),
+ ArgEffect(StopTracking),
+ ArgEffect(DoNothing));
+
+ return getDefaultSummary();
+}
+
+const RetainSummary *
+RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
+ // If we don't know what function we're calling, use our default summary.
+ if (!FD)
+ return getDefaultSummary();
+
+ // Look up a summary in our cache of FunctionDecls -> Summaries.
+ FuncSummariesTy::iterator I = FuncSummaries.find(FD);
+ if (I != FuncSummaries.end())
+ return I->second;
+
+ // No summary? Generate one.
+ bool AllowAnnotations = true;
+ const RetainSummary *S = generateSummary(FD, AllowAnnotations);
+
+ // Annotations override defaults.
+ if (AllowAnnotations)
+ updateSummaryFromAnnotations(S, FD);
+
+ FuncSummaries[FD] = S;
+ return S;
+}
+
+//===----------------------------------------------------------------------===//
+// Summary creation for functions (largely uses of Core Foundation).
+//===----------------------------------------------------------------------===//
+
+static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
+ switch (E.getKind()) {
+ case DoNothing:
+ case Autorelease:
+ case DecRefBridgedTransferred:
+ case IncRef:
+ case UnretainedOutParameter:
+ case RetainedOutParameter:
+ case RetainedOutParameterOnZero:
+ case RetainedOutParameterOnNonZero:
+ case MayEscape:
+ case StopTracking:
+ case StopTrackingHard:
+ return E.withKind(StopTrackingHard);
+ case DecRef:
+ case DecRefAndStopTrackingHard:
+ return E.withKind(DecRefAndStopTrackingHard);
+ case Dealloc:
+ return E.withKind(Dealloc);
+ }
+
+ llvm_unreachable("Unknown ArgEffect kind");
+}
+
+void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
+ const CallEvent &Call) {
+ if (Call.hasNonZeroCallbackArg()) {
+ ArgEffect RecEffect =
+ getStopTrackingHardEquivalent(S->getReceiverEffect());
+ ArgEffect DefEffect =
+ getStopTrackingHardEquivalent(S->getDefaultArgEffect());
+
+ ArgEffects ScratchArgs(AF.getEmptyMap());
+ ArgEffects CustomArgEffects = S->getArgEffects();
+ for (ArgEffects::iterator I = CustomArgEffects.begin(),
+ E = CustomArgEffects.end();
+ I != E; ++I) {
+ ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
+ if (Translated.getKind() != DefEffect.getKind())
+ ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
+ }
+
+ RetEffect RE = RetEffect::MakeNoRetHard();
+
+ // Special cases where the callback argument CANNOT free the return value.
+ // This can generally only happen if we know that the callback will only be
+ // called when the return value is already being deallocated.
+ if (const SimpleFunctionCall *FC = dyn_cast<SimpleFunctionCall>(&Call)) {
+ if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
+ // When the CGBitmapContext is deallocated, the callback here will free
+ // the associated data buffer.
+ // The callback in dispatch_data_create frees the buffer, but not
+ // the data object.
+ if (Name->isStr("CGBitmapContextCreateWithData") ||
+ Name->isStr("dispatch_data_create"))
+ RE = S->getRetEffect();
+ }
+ }
+
+ S = getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
+ }
+
+ // Special case '[super init];' and '[self init];'
+ //
+ // Even though calling '[super init]' without assigning the result to self
+ // and checking if the parent returns 'nil' is a bad pattern, it is common.
+ // Additionally, our Self Init checker already warns about it. To avoid
+ // overwhelming the user with messages from both checkers, we model the case
+ // of '[super init]' in cases when it is not consumed by another expression
+ // as if the call preserves the value of 'self'; essentially, assuming it can
+ // never fail and return 'nil'.
+ // Note, we don't want to just stop tracking the value since we want the
+ // RetainCount checker to report leaks and use-after-free if SelfInit checker
+ // is turned off.
+ if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {
+ if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {
+
+ // Check if the message is not consumed, we know it will not be used in
+ // an assignment, ex: "self = [super init]".
+ const Expr *ME = MC->getOriginExpr();
+ const LocationContext *LCtx = MC->getLocationContext();
+ ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
+ if (!PM.isConsumedExpr(ME)) {
+ RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
+ ModifiableSummaryTemplate->setReceiverEffect(ArgEffect(DoNothing));
+ ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
+ }
+ }
+ }
+}
+
+const RetainSummary *
+RetainSummaryManager::getSummary(const CallEvent &Call,
+ QualType ReceiverType) {
+ const RetainSummary *Summ;
+ switch (Call.getKind()) {
+ case CE_Function:
+ case CE_CXXMember:
+ case CE_CXXMemberOperator:
+ case CE_CXXConstructor:
+ case CE_CXXAllocator:
+ Summ = getFunctionSummary(cast_or_null<FunctionDecl>(Call.getDecl()));
+ break;
+ case CE_Block:
+ case CE_CXXDestructor:
+ // FIXME: These calls are currently unsupported.
+ return getPersistentStopSummary();
+ case CE_ObjCMessage: {
+ const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
+ if (Msg.isInstanceMessage())
+ Summ = getInstanceMethodSummary(Msg, ReceiverType);
+ else
+ Summ = getClassMethodSummary(Msg);
+ break;
+ }
+ }
+
+ updateSummaryForCall(Summ, Call);
+
+ assert(Summ && "Unknown call type?");
+ return Summ;
+}
+
+
+const RetainSummary *
+RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
+ if (coreFoundation::followsCreateRule(FD))
+ return getCFSummaryCreateRule(FD);
+
+ return getCFSummaryGetRule(FD);
+}
+
+bool RetainSummaryManager::isTrustedReferenceCountImplementation(
+ const FunctionDecl *FD) {
+ return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
+}
+
+Optional<RetainSummaryManager::BehaviorSummary>
+RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD,
+ bool &hasTrustedImplementationAnnotation) {
+
+ IdentifierInfo *II = FD->getIdentifier();
+ if (!II)
+ return None;
+
+ StringRef FName = II->getName();
+ FName = FName.substr(FName.find_first_not_of('_'));
+
+ QualType ResultTy = CE->getCallReturnType(Ctx);
+ if (ResultTy->isObjCIdType()) {
+ if (II->isStr("NSMakeCollectable"))
+ return BehaviorSummary::Identity;
+ } else if (ResultTy->isPointerType()) {
+ // Handle: (CF|CG|CV)Retain
+ // CFAutorelease
+ // It's okay to be a little sloppy here.
+ if (FName == "CMBufferQueueDequeueAndRetain" ||
+ FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
+ // Part of: <rdar://problem/39390714>.
+ // These are not retain. They just return something and retain it.
+ return None;
+ }
+ if (cocoa::isRefType(ResultTy, "CF", FName) ||
+ cocoa::isRefType(ResultTy, "CG", FName) ||
+ cocoa::isRefType(ResultTy, "CV", FName))
+ if (isRetain(FD, FName) || isAutorelease(FD, FName) ||
+ isMakeCollectable(FName))
+ return BehaviorSummary::Identity;
+
+ // safeMetaCast is called by OSDynamicCast.
+ // We assume that OSDynamicCast is either an identity (cast is OK,
+ // the input was non-zero),
+ // or that it returns zero (when the cast failed, or the input
+ // was zero).
+ if (TrackOSObjects && isOSObjectDynamicCast(FName)) {
+ return BehaviorSummary::IdentityOrZero;
+ }
+
+ const FunctionDecl* FDD = FD->getDefinition();
+ if (FDD && isTrustedReferenceCountImplementation(FDD)) {
+ hasTrustedImplementationAnnotation = true;
+ return BehaviorSummary::Identity;
+ }
+ }
+
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXRecordDecl *Parent = MD->getParent();
+ if (TrackOSObjects && Parent && isOSObjectSubclass(Parent))
+ if (FName == "release" || FName == "retain")
+ return BehaviorSummary::NoOp;
+ }
+
+ return None;
+}
+
+const RetainSummary *
+RetainSummaryManager::getUnarySummary(const FunctionType* FT,
+ ArgEffectKind AE) {
+
+ // Unary functions have no arg effects by definition.
+ ArgEffects ScratchArgs(AF.getEmptyMap());
+
+ // Sanity check that this is *really* a unary function. This can
+ // happen if people do weird things.
+ const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
+ if (!FTP || FTP->getNumParams() != 1)
+ return getPersistentStopSummary();
+
+ ArgEffect Effect(AE, ObjKind::CF);
+
+ ScratchArgs = AF.add(ScratchArgs, 0, Effect);
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryRetainRule(const FunctionDecl *FD) {
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ AF.getEmptyMap(),
+ /*ReceiverEff=*/ArgEffect(DoNothing),
+ /*DefaultEff=*/ArgEffect(DoNothing),
+ /*ThisEff=*/ArgEffect(IncRef, ObjKind::OS));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryReleaseRule(const FunctionDecl *FD) {
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ AF.getEmptyMap(),
+ /*ReceiverEff=*/ArgEffect(DoNothing),
+ /*DefaultEff=*/ArgEffect(DoNothing),
+ /*ThisEff=*/ArgEffect(DecRef, ObjKind::OS));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) {
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ AF.getEmptyMap(),
+ /*ReceiverEff=*/ArgEffect(DoNothing),
+ /*DefaultEff=*/ArgEffect(DoNothing),
+ /*ThisEff=*/ArgEffect(Dealloc, ObjKind::OS));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryCreateRule(const FunctionDecl *FD) {
+ return getPersistentSummary(RetEffect::MakeOwned(ObjKind::OS),
+ AF.getEmptyMap());
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryGetRule(const FunctionDecl *FD) {
+ return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::OS),
+ AF.getEmptyMap());
+}
+
+const RetainSummary *
+RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
+ return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
+ ArgEffects(AF.getEmptyMap()));
+}
+
+const RetainSummary *
+RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
+ return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::CF),
+ ArgEffects(AF.getEmptyMap()),
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Summary creation for Selectors.
+//===----------------------------------------------------------------------===//
+
+Optional<RetEffect>
+RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
+ const Decl *D) {
+ if (hasAnyEnabledAttrOf<NSReturnsRetainedAttr>(D, RetTy))
+ return ObjCAllocRetE;
+
+ if (auto K = hasAnyEnabledAttrOf<CFReturnsRetainedAttr, OSReturnsRetainedAttr,
+ GeneralizedReturnsRetainedAttr>(D, RetTy))
+ return RetEffect::MakeOwned(*K);
+
+ if (auto K = hasAnyEnabledAttrOf<
+ CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr,
+ GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr,
+ NSReturnsAutoreleasedAttr>(D, RetTy))
+ return RetEffect::MakeNotOwned(*K);
+
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
+ for (const auto *PD : MD->overridden_methods())
+ if (auto RE = getRetEffectFromAnnotations(RetTy, PD))
+ return RE;
+
+ return None;
+}
+
+/// \return Whether the chain of typedefs starting from {@code QT}
+/// has a typedef with a given name {@code Name}.
+static bool hasTypedefNamed(QualType QT,
+ StringRef Name) {
+ while (auto *T = dyn_cast<TypedefType>(QT)) {
+ const auto &Context = T->getDecl()->getASTContext();
+ if (T->getDecl()->getIdentifier() == &Context.Idents.get(Name))
+ return true;
+ QT = T->getDecl()->getUnderlyingType();
+ }
+ return false;
+}
+
+static QualType getCallableReturnType(const NamedDecl *ND) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
+ return FD->getReturnType();
+ } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(ND)) {
+ return MD->getReturnType();
+ } else {
+ llvm_unreachable("Unexpected decl");
+ }
+}
+
+bool RetainSummaryManager::applyParamAnnotationEffect(
+ const ParmVarDecl *pd, unsigned parm_idx, const NamedDecl *FD,
+ RetainSummaryTemplate &Template) {
+ QualType QT = pd->getType();
+ if (auto K =
+ hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr,
+ GeneralizedConsumedAttr>(pd, QT)) {
+ Template->addArg(AF, parm_idx, ArgEffect(DecRef, *K));
+ return true;
+ } else if (auto K = hasAnyEnabledAttrOf<
+ CFReturnsRetainedAttr, OSReturnsRetainedAttr,
+ OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr,
+ GeneralizedReturnsRetainedAttr>(pd, QT)) {
+
+ // For OSObjects, we try to guess whether the object is created based
+ // on the return value.
+ if (K == ObjKind::OS) {
+ QualType QT = getCallableReturnType(FD);
+
+ bool HasRetainedOnZero = pd->hasAttr<OSReturnsRetainedOnZeroAttr>();
+ bool HasRetainedOnNonZero = pd->hasAttr<OSReturnsRetainedOnNonZeroAttr>();
+
+ // The usual convention is to create an object on non-zero return, but
+ // it's reverted if the typedef chain has a typedef kern_return_t,
+ // because kReturnSuccess constant is defined as zero.
+ // The convention can be overwritten by custom attributes.
+ bool SuccessOnZero =
+ HasRetainedOnZero ||
+ (hasTypedefNamed(QT, "kern_return_t") && !HasRetainedOnNonZero);
+ bool ShouldSplit = !QT.isNull() && !QT->isVoidType();
+ ArgEffectKind AK = RetainedOutParameter;
+ if (ShouldSplit && SuccessOnZero) {
+ AK = RetainedOutParameterOnZero;
+ } else if (ShouldSplit && (!SuccessOnZero || HasRetainedOnNonZero)) {
+ AK = RetainedOutParameterOnNonZero;
+ }
+ Template->addArg(AF, parm_idx, ArgEffect(AK, ObjKind::OS));
+ }
+
+ // For others:
+ // Do nothing. Retained out parameters will either point to a +1 reference
+ // or NULL, but the way you check for failure differs depending on the
+ // API. Consequently, we don't have a good way to track them yet.
+ return true;
+ } else if (auto K = hasAnyEnabledAttrOf<CFReturnsNotRetainedAttr,
+ OSReturnsNotRetainedAttr,
+ GeneralizedReturnsNotRetainedAttr>(
+ pd, QT)) {
+ Template->addArg(AF, parm_idx, ArgEffect(UnretainedOutParameter, *K));
+ return true;
+ }
+
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ for (const auto *OD : MD->overridden_methods()) {
+ const ParmVarDecl *OP = OD->parameters()[parm_idx];
+ if (applyParamAnnotationEffect(OP, parm_idx, OD, Template))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
+ const FunctionDecl *FD) {
+ if (!FD)
+ return;
+
+ assert(Summ && "Must have a summary to add annotations to.");
+ RetainSummaryTemplate Template(Summ, *this);
+
+ // Effects on the parameters.
+ unsigned parm_idx = 0;
+ for (auto pi = FD->param_begin(),
+ pe = FD->param_end(); pi != pe; ++pi, ++parm_idx)
+ applyParamAnnotationEffect(*pi, parm_idx, FD, Template);
+
+ QualType RetTy = FD->getReturnType();
+ if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
+ Template->setRetEffect(*RetE);
+
+ if (hasAnyEnabledAttrOf<OSConsumesThisAttr>(FD, RetTy))
+ Template->setThisEffect(ArgEffect(DecRef, ObjKind::OS));
+}
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
+ const ObjCMethodDecl *MD) {
+ if (!MD)
+ return;
+
+ assert(Summ && "Must have a valid summary to add annotations to");
+ RetainSummaryTemplate Template(Summ, *this);
+
+ // Effects on the receiver.
+ if (hasAnyEnabledAttrOf<NSConsumesSelfAttr>(MD, MD->getReturnType()))
+ Template->setReceiverEffect(ArgEffect(DecRef, ObjKind::ObjC));
+
+ // Effects on the parameters.
+ unsigned parm_idx = 0;
+ for (auto pi = MD->param_begin(), pe = MD->param_end(); pi != pe;
+ ++pi, ++parm_idx)
+ applyParamAnnotationEffect(*pi, parm_idx, MD, Template);
+
+ QualType RetTy = MD->getReturnType();
+ if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
+ Template->setRetEffect(*RetE);
+}
+
+const RetainSummary *
+RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
+ Selector S, QualType RetTy) {
+ // Any special effects?
+ ArgEffect ReceiverEff = ArgEffect(DoNothing, ObjKind::ObjC);
+ RetEffect ResultEff = RetEffect::MakeNoRet();
+
+ // Check the method family, and apply any default annotations.
+ switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
+ case OMF_None:
+ case OMF_initialize:
+ case OMF_performSelector:
+ // Assume all Objective-C methods follow Cocoa Memory Management rules.
+ // FIXME: Does the non-threaded performSelector family really belong here?
+ // The selector could be, say, @selector(copy).
+ if (cocoa::isCocoaObjectRef(RetTy))
+ ResultEff = RetEffect::MakeNotOwned(ObjKind::ObjC);
+ else if (coreFoundation::isCFObjectRef(RetTy)) {
+ // ObjCMethodDecl currently doesn't consider CF objects as valid return
+ // values for alloc, new, copy, or mutableCopy, so we have to
+ // double-check with the selector. This is ugly, but there aren't that
+ // many Objective-C methods that return CF objects, right?
+ if (MD) {
+ switch (S.getMethodFamily()) {
+ case OMF_alloc:
+ case OMF_new:
+ case OMF_copy:
+ case OMF_mutableCopy:
+ ResultEff = RetEffect::MakeOwned(ObjKind::CF);
+ break;
+ default:
+ ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
+ break;
+ }
+ } else {
+ ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
+ }
+ }
+ break;
+ case OMF_init:
+ ResultEff = ObjCInitRetE;
+ ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
+ break;
+ case OMF_alloc:
+ case OMF_new:
+ case OMF_copy:
+ case OMF_mutableCopy:
+ if (cocoa::isCocoaObjectRef(RetTy))
+ ResultEff = ObjCAllocRetE;
+ else if (coreFoundation::isCFObjectRef(RetTy))
+ ResultEff = RetEffect::MakeOwned(ObjKind::CF);
+ break;
+ case OMF_autorelease:
+ ReceiverEff = ArgEffect(Autorelease, ObjKind::ObjC);
+ break;
+ case OMF_retain:
+ ReceiverEff = ArgEffect(IncRef, ObjKind::ObjC);
+ break;
+ case OMF_release:
+ ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
+ break;
+ case OMF_dealloc:
+ ReceiverEff = ArgEffect(Dealloc, ObjKind::ObjC);
+ break;
+ case OMF_self:
+ // -self is handled specially by the ExprEngine to propagate the receiver.
+ break;
+ case OMF_retainCount:
+ case OMF_finalize:
+ // These methods don't return objects.
+ break;
+ }
+
+ // If one of the arguments in the selector has the keyword 'delegate' we
+ // should stop tracking the reference count for the receiver. This is
+ // because the reference count is quite possibly handled by a delegate
+ // method.
+ if (S.isKeywordSelector()) {
+ for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
+ StringRef Slot = S.getNameForSlot(i);
+ if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
+ if (ResultEff == ObjCInitRetE)
+ ResultEff = RetEffect::MakeNoRetHard();
+ else
+ ReceiverEff = ArgEffect(StopTrackingHard, ObjKind::ObjC);
+ }
+ }
+ }
+
+ if (ReceiverEff.getKind() == DoNothing &&
+ ResultEff.getKind() == RetEffect::NoRet)
+ return getDefaultSummary();
+
+ return getPersistentSummary(ResultEff, ArgEffects(AF.getEmptyMap()),
+ ArgEffect(ReceiverEff), ArgEffect(MayEscape));
+}
+
+const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
+ const ObjCMethodCall &Msg,
+ QualType ReceiverType) {
+ const ObjCInterfaceDecl *ReceiverClass = nullptr;
+
+ // We do better tracking of the type of the object than the core ExprEngine.
+ // See if we have its type in our private state.
+ if (!ReceiverType.isNull())
+ if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>())
+ ReceiverClass = PT->getInterfaceDecl();
+
+ // If we don't know what kind of object this is, fall back to its static type.
+ if (!ReceiverClass)
+ ReceiverClass = Msg.getReceiverInterface();
+
+ // FIXME: The receiver could be a reference to a class, meaning that
+ // we should use the class method.
+ // id x = [NSObject class];
+ // [x performSelector:... withObject:... afterDelay:...];
+ Selector S = Msg.getSelector();
+ const ObjCMethodDecl *Method = Msg.getDecl();
+ if (!Method && ReceiverClass)
+ Method = ReceiverClass->getInstanceMethod(S);
+
+ return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
+ ObjCMethodSummaries);
+}
+
+const RetainSummary *
+RetainSummaryManager::getMethodSummary(Selector S,
+ const ObjCInterfaceDecl *ID,
+ const ObjCMethodDecl *MD, QualType RetTy,
+ ObjCMethodSummariesTy &CachedSummaries) {
+
+ // Objective-C method summaries are only applicable to ObjC and CF objects.
+ if (!TrackObjCAndCFObjects)
+ return getDefaultSummary();
+
+ // Look up a summary in our summary cache.
+ const RetainSummary *Summ = CachedSummaries.find(ID, S);
+
+ if (!Summ) {
+ Summ = getStandardMethodSummary(MD, S, RetTy);
+
+ // Annotations override defaults.
+ updateSummaryFromAnnotations(Summ, MD);
+
+ // Memoize the summary.
+ CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
+ }
+
+ return Summ;
+}
+
+void RetainSummaryManager::InitializeClassMethodSummaries() {
+ ArgEffects ScratchArgs = AF.getEmptyMap();
+
+ // Create the [NSAssertionHandler currentHander] summary.
+ addClassMethSummary("NSAssertionHandler", "currentHandler",
+ getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::ObjC),
+ ScratchArgs));
+
+ // Create the [NSAutoreleasePool addObject:] summary.
+ ScratchArgs = AF.add(ScratchArgs, 0, ArgEffect(Autorelease));
+ addClassMethSummary("NSAutoreleasePool", "addObject",
+ getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+ ArgEffect(DoNothing),
+ ArgEffect(Autorelease)));
+}
+
+void RetainSummaryManager::InitializeMethodSummaries() {
+
+ ArgEffects ScratchArgs = AF.getEmptyMap();
+ // Create the "init" selector. It just acts as a pass-through for the
+ // receiver.
+ const RetainSummary *InitSumm = getPersistentSummary(
+ ObjCInitRetE, ScratchArgs, ArgEffect(DecRef, ObjKind::ObjC));
+ addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
+
+ // awakeAfterUsingCoder: behaves basically like an 'init' method. It
+ // claims the receiver and returns a retained object.
+ addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
+ InitSumm);
+
+ // The next methods are allocators.
+ const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE,
+ ScratchArgs);
+ const RetainSummary *CFAllocSumm =
+ getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs);
+
+ // Create the "retain" selector.
+ RetEffect NoRet = RetEffect::MakeNoRet();
+ const RetainSummary *Summ = getPersistentSummary(
+ NoRet, ScratchArgs, ArgEffect(IncRef, ObjKind::ObjC));
+ addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
+
+ // Create the "release" selector.
+ Summ = getPersistentSummary(NoRet, ScratchArgs,
+ ArgEffect(DecRef, ObjKind::ObjC));
+ addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
+
+ // Create the -dealloc summary.
+ Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc,
+ ObjKind::ObjC));
+ addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
+
+ // Create the "autorelease" selector.
+ Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease,
+ ObjKind::ObjC));
+ addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
+
+ // For NSWindow, allocated objects are (initially) self-owned.
+ // FIXME: For now we opt for false negatives with NSWindow, as these objects
+ // self-own themselves. However, they only do this once they are displayed.
+ // Thus, we need to track an NSWindow's display status.
+ // This is tracked in <rdar://problem/6062711>.
+ // See also http://llvm.org/bugs/show_bug.cgi?id=3714.
+ const RetainSummary *NoTrackYet =
+ getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+ ArgEffect(StopTracking), ArgEffect(StopTracking));
+
+ addClassMethSummary("NSWindow", "alloc", NoTrackYet);
+
+ // For NSPanel (which subclasses NSWindow), allocated objects are not
+ // self-owned.
+ // FIXME: For now we don't track NSPanels. object for the same reason
+ // as for NSWindow objects.
+ addClassMethSummary("NSPanel", "alloc", NoTrackYet);
+
+ // For NSNull, objects returned by +null are singletons that ignore
+ // retain/release semantics. Just don't track them.
+ // <rdar://problem/12858915>
+ addClassMethSummary("NSNull", "null", NoTrackYet);
+
+ // Don't track allocated autorelease pools, as it is okay to prematurely
+ // exit a method.
+ addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
+ addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
+ addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
+
+ // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
+ addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType");
+ addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType");
+
+ // Create summaries for CIContext, 'createCGImage' and
+ // 'createCGLayerWithSize'. These objects are CF objects, and are not
+ // automatically garbage collected.
+ addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect");
+ addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",
+ "format", "colorSpace");
+ addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
+}
+
+CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
+ ASTContext &Ctx = MD->getASTContext();
+ LangOptions L = Ctx.getLangOpts();
+ RetainSummaryManager M(Ctx, L.ObjCAutoRefCount,
+ /*TrackNSAndCFObjects=*/true,
+ /*TrackOSObjects=*/false);
+ const RetainSummary *S = M.getMethodSummary(MD);
+ CallEffects CE(S->getRetEffect(), S->getReceiverEffect());
+ unsigned N = MD->param_size();
+ for (unsigned i = 0; i < N; ++i) {
+ CE.Args.push_back(S->getArg(i));
+ }
+ return CE;
+}
+
+CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
+ ASTContext &Ctx = FD->getASTContext();
+ LangOptions L = Ctx.getLangOpts();
+ RetainSummaryManager M(Ctx, L.ObjCAutoRefCount,
+ /*TrackNSAndCFObjects=*/true,
+ /*TrackOSObjects=*/false);
+ const RetainSummary *S = M.getFunctionSummary(FD);
+ CallEffects CE(S->getRetEffect());
+ unsigned N = FD->param_size();
+ for (unsigned i = 0; i < N; ++i) {
+ CE.Args.push_back(S->getArg(i));
+ }
+ return CE;
+}
diff --git a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp
deleted file mode 100644
index d379562bf325..000000000000
--- a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-//== SMTConstraintManager.cpp -----------------------------------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-
-using namespace clang;
-using namespace ento;
-
-ProgramStateRef SMTConstraintManager::assumeSym(ProgramStateRef State,
- SymbolRef Sym,
- bool Assumption) {
- ASTContext &Ctx = getBasicVals().getContext();
-
- QualType RetTy;
- bool hasComparison;
-
- SMTExprRef Exp = Solver->getExpr(Ctx, Sym, &RetTy, &hasComparison);
-
- // Create zero comparison for implicit boolean cast, with reversed assumption
- if (!hasComparison && !RetTy->isBooleanType())
- return assumeExpr(State, Sym,
- Solver->getZeroExpr(Ctx, Exp, RetTy, !Assumption));
-
- return assumeExpr(State, Sym, Assumption ? Exp : Solver->mkNot(Exp));
-}
-
-ProgramStateRef SMTConstraintManager::assumeSymInclusiveRange(
- ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
- const llvm::APSInt &To, bool InRange) {
- ASTContext &Ctx = getBasicVals().getContext();
- return assumeExpr(State, Sym,
- Solver->getRangeExpr(Ctx, Sym, From, To, InRange));
-}
-
-ProgramStateRef
-SMTConstraintManager::assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym,
- bool Assumption) {
- // Skip anything that is unsupported
- return State;
-}
-
-ConditionTruthVal SMTConstraintManager::checkNull(ProgramStateRef State,
- SymbolRef Sym) {
- ASTContext &Ctx = getBasicVals().getContext();
-
- QualType RetTy;
- // The expression may be casted, so we cannot call getZ3DataExpr() directly
- SMTExprRef VarExp = Solver->getExpr(Ctx, Sym, &RetTy);
- SMTExprRef Exp = Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/true);
-
- // Negate the constraint
- SMTExprRef NotExp =
- Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/false);
-
- Solver->reset();
- addStateConstraints(State);
-
- Solver->push();
- Solver->addConstraint(Exp);
- ConditionTruthVal isSat = Solver->check();
-
- Solver->pop();
- Solver->addConstraint(NotExp);
- ConditionTruthVal isNotSat = Solver->check();
-
- // Zero is the only possible solution
- if (isSat.isConstrainedTrue() && isNotSat.isConstrainedFalse())
- return true;
-
- // Zero is not a solution
- if (isSat.isConstrainedFalse() && isNotSat.isConstrainedTrue())
- return false;
-
- // Zero may be a solution
- return ConditionTruthVal();
-}
-
-const llvm::APSInt *SMTConstraintManager::getSymVal(ProgramStateRef State,
- SymbolRef Sym) const {
- BasicValueFactory &BVF = getBasicVals();
- ASTContext &Ctx = BVF.getContext();
-
- if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
- QualType Ty = Sym->getType();
- assert(!Ty->isRealFloatingType());
- llvm::APSInt Value(Ctx.getTypeSize(Ty),
- !Ty->isSignedIntegerOrEnumerationType());
-
- SMTExprRef Exp =
- Solver->fromData(SD->getSymbolID(), Ty, Ctx.getTypeSize(Ty));
-
- Solver->reset();
- addStateConstraints(State);
-
- // Constraints are unsatisfiable
- ConditionTruthVal isSat = Solver->check();
- if (!isSat.isConstrainedTrue())
- return nullptr;
-
- // Model does not assign interpretation
- if (!Solver->getInterpretation(Exp, Value))
- return nullptr;
-
- // A value has been obtained, check if it is the only value
- SMTExprRef NotExp = Solver->fromBinOp(
- Exp, BO_NE,
- Ty->isBooleanType() ? Solver->fromBoolean(Value.getBoolValue())
- : Solver->fromAPSInt(Value),
- false);
-
- Solver->addConstraint(NotExp);
-
- ConditionTruthVal isNotSat = Solver->check();
- if (isNotSat.isConstrainedTrue())
- return nullptr;
-
- // This is the only solution, store it
- return &BVF.getValue(Value);
- }
-
- if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
- SymbolRef CastSym = SC->getOperand();
- QualType CastTy = SC->getType();
- // Skip the void type
- if (CastTy->isVoidType())
- return nullptr;
-
- const llvm::APSInt *Value;
- if (!(Value = getSymVal(State, CastSym)))
- return nullptr;
- return &BVF.Convert(SC->getType(), *Value);
- }
-
- if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
- const llvm::APSInt *LHS, *RHS;
- if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
- LHS = getSymVal(State, SIE->getLHS());
- RHS = &SIE->getRHS();
- } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
- LHS = &ISE->getLHS();
- RHS = getSymVal(State, ISE->getRHS());
- } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
- // Early termination to avoid expensive call
- LHS = getSymVal(State, SSM->getLHS());
- RHS = LHS ? getSymVal(State, SSM->getRHS()) : nullptr;
- } else {
- llvm_unreachable("Unsupported binary expression to get symbol value!");
- }
-
- if (!LHS || !RHS)
- return nullptr;
-
- llvm::APSInt ConvertedLHS, ConvertedRHS;
- QualType LTy, RTy;
- std::tie(ConvertedLHS, LTy) = Solver->fixAPSInt(Ctx, *LHS);
- std::tie(ConvertedRHS, RTy) = Solver->fixAPSInt(Ctx, *RHS);
- Solver->doIntTypeConversion<llvm::APSInt, &SMTSolver::castAPSInt>(
- Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
- return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
- }
-
- llvm_unreachable("Unsupported expression to get symbol value!");
-}
-
-ConditionTruthVal
-SMTConstraintManager::checkModel(ProgramStateRef State,
- const SMTExprRef &Exp) const {
- Solver->reset();
- Solver->addConstraint(Exp);
- addStateConstraints(State);
- return Solver->check();
-}
diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp
index f292dca8e99f..6c0d487c8a87 100644
--- a/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -271,8 +271,8 @@ DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
/// Return a memory region for the 'this' object reference.
loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
const StackFrameContext *SFC) {
- return loc::MemRegionVal(getRegionManager().
- getCXXThisRegion(D->getThisType(getContext()), SFC));
+ return loc::MemRegionVal(
+ getRegionManager().getCXXThisRegion(D->getThisType(), SFC));
}
/// Return a memory region for the 'this' object reference.
@@ -362,9 +362,9 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
return None;
ASTContext &Ctx = getContext();
- llvm::APSInt Result;
+ Expr::EvalResult Result;
if (E->EvaluateAsInt(Result, Ctx))
- return makeIntVal(Result);
+ return makeIntVal(Result.Val.getInt());
if (Loc::isLocType(E->getType()))
if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
@@ -375,8 +375,7 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
}
}
-SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
- BinaryOperator::Opcode Op,
+SVal SValBuilder::makeSymExprValNN(BinaryOperator::Opcode Op,
NonLoc LHS, NonLoc RHS,
QualType ResultTy) {
const SymExpr *symLHS = LHS.getAsSymExpr();
@@ -385,8 +384,8 @@ SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
// TODO: When the Max Complexity is reached, we should conjure a symbol
// instead of generating an Unknown value and propagate the taint info to it.
const unsigned MaxComp = StateMgr.getOwningEngine()
- ->getAnalysisManager()
- .options.getMaxSymbolComplexity();
+ .getAnalysisManager()
+ .options.MaxSymbolComplexity;
if (symLHS && symRHS &&
(symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp)
diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp
index 559ca2c9840d..933c5c330072 100644
--- a/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/lib/StaticAnalyzer/Core/SVals.cpp
@@ -85,7 +85,7 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
- return X->getLoc().getAsLocSymbol();
+ return X->getLoc().getAsLocSymbol(IncludeBaseRegions);
if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
const MemRegion *R = X->getRegion();
@@ -171,6 +171,10 @@ const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
return static_cast<const LazyCompoundValData*>(Data)->getRegion();
}
+bool nonloc::PointerToMember::isNullMemberPointer() const {
+ return getPTMData().isNull();
+}
+
const DeclaratorDecl *nonloc::PointerToMember::getDecl() const {
const auto PTMD = this->getPTMData();
if (PTMD.isNull())
diff --git a/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
new file mode 100644
index 000000000000..fecbc0001079
--- /dev/null
+++ b/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
@@ -0,0 +1,349 @@
+//===--- SarifDiagnostics.cpp - Sarif Diagnostics for Paths -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SarifDiagnostics object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Version.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Path.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace ento;
+
+namespace {
+class SarifDiagnostics : public PathDiagnosticConsumer {
+ std::string OutputFile;
+
+public:
+ SarifDiagnostics(AnalyzerOptions &, const std::string &Output)
+ : OutputFile(Output) {}
+ ~SarifDiagnostics() override = default;
+
+ void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
+ FilesMade *FM) override;
+
+ StringRef getName() const override { return "SarifDiagnostics"; }
+ PathGenerationScheme getGenerationScheme() const override { return Minimal; }
+ bool supportsLogicalOpControlFlow() const override { return true; }
+ bool supportsCrossFileDiagnostics() const override { return true; }
+};
+} // end anonymous namespace
+
+void ento::createSarifDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
+ PathDiagnosticConsumers &C,
+ const std::string &Output,
+ const Preprocessor &) {
+ C.push_back(new SarifDiagnostics(AnalyzerOpts, Output));
+}
+
+static StringRef getFileName(const FileEntry &FE) {
+ StringRef Filename = FE.tryGetRealPathName();
+ if (Filename.empty())
+ Filename = FE.getName();
+ return Filename;
+}
+
+static std::string percentEncodeURICharacter(char C) {
+ // RFC 3986 claims alpha, numeric, and this handful of
+ // characters are not reserved for the path component and
+ // should be written out directly. Otherwise, percent
+ // encode the character and write that out instead of the
+ // reserved character.
+ if (llvm::isAlnum(C) ||
+ StringRef::npos != StringRef("-._~:@!$&'()*+,;=").find(C))
+ return std::string(&C, 1);
+ return "%" + llvm::toHex(StringRef(&C, 1));
+}
+
+static std::string fileNameToURI(StringRef Filename) {
+ llvm::SmallString<32> Ret = StringRef("file://");
+
+ // Get the root name to see if it has a URI authority.
+ StringRef Root = sys::path::root_name(Filename);
+ if (Root.startswith("//")) {
+ // There is an authority, so add it to the URI.
+ Ret += Root.drop_front(2).str();
+ } else if (!Root.empty()) {
+ // There is no authority, so end the component and add the root to the URI.
+ Ret += Twine("/" + Root).str();
+ }
+
+ auto Iter = sys::path::begin(Filename), End = sys::path::end(Filename);
+ assert(Iter != End && "Expected there to be a non-root path component.");
+ // Add the rest of the path components, encoding any reserved characters;
+ // we skip past the first path component, as it was handled it above.
+ std::for_each(++Iter, End, [&Ret](StringRef Component) {
+ // For reasons unknown to me, we may get a backslash with Windows native
+ // paths for the initial backslash following the drive component, which
+ // we need to ignore as a URI path part.
+ if (Component == "\\")
+ return;
+
+ // Add the separator between the previous path part and the one being
+ // currently processed.
+ Ret += "/";
+
+ // URI encode the part.
+ for (char C : Component) {
+ Ret += percentEncodeURICharacter(C);
+ }
+ });
+
+ return Ret.str().str();
+}
+
+static json::Object createFileLocation(const FileEntry &FE) {
+ return json::Object{{"uri", fileNameToURI(getFileName(FE))}};
+}
+
+static json::Object createFile(const FileEntry &FE) {
+ return json::Object{{"fileLocation", createFileLocation(FE)},
+ {"roles", json::Array{"resultFile"}},
+ {"length", FE.getSize()},
+ {"mimeType", "text/plain"}};
+}
+
+static json::Object createFileLocation(const FileEntry &FE,
+ json::Array &Files) {
+ std::string FileURI = fileNameToURI(getFileName(FE));
+
+ // See if the Files array contains this URI already. If it does not, create
+ // a new file object to add to the array.
+ auto I = llvm::find_if(Files, [&](const json::Value &File) {
+ if (const json::Object *Obj = File.getAsObject()) {
+ if (const json::Object *FileLoc = Obj->getObject("fileLocation")) {
+ Optional<StringRef> URI = FileLoc->getString("uri");
+ return URI && URI->equals(FileURI);
+ }
+ }
+ return false;
+ });
+
+ // Calculate the index within the file location array so it can be stored in
+ // the JSON object.
+ auto Index = static_cast<unsigned>(std::distance(Files.begin(), I));
+ if (I == Files.end())
+ Files.push_back(createFile(FE));
+
+ return json::Object{{"uri", FileURI}, {"fileIndex", Index}};
+}
+
+static json::Object createTextRegion(SourceRange R, const SourceManager &SM) {
+ return json::Object{
+ {"startLine", SM.getExpansionLineNumber(R.getBegin())},
+ {"endLine", SM.getExpansionLineNumber(R.getEnd())},
+ {"startColumn", SM.getExpansionColumnNumber(R.getBegin())},
+ {"endColumn", SM.getExpansionColumnNumber(R.getEnd())}};
+}
+
+static json::Object createPhysicalLocation(SourceRange R, const FileEntry &FE,
+ const SourceManager &SMgr,
+ json::Array &Files) {
+ return json::Object{{{"fileLocation", createFileLocation(FE, Files)},
+ {"region", createTextRegion(R, SMgr)}}};
+}
+
+enum class Importance { Important, Essential, Unimportant };
+
+static StringRef importanceToStr(Importance I) {
+ switch (I) {
+ case Importance::Important:
+ return "important";
+ case Importance::Essential:
+ return "essential";
+ case Importance::Unimportant:
+ return "unimportant";
+ }
+ llvm_unreachable("Fully covered switch is not so fully covered");
+}
+
+static json::Object createThreadFlowLocation(json::Object &&Location,
+ Importance I) {
+ return json::Object{{"location", std::move(Location)},
+ {"importance", importanceToStr(I)}};
+}
+
+static json::Object createMessage(StringRef Text) {
+ return json::Object{{"text", Text.str()}};
+}
+
+static json::Object createLocation(json::Object &&PhysicalLocation,
+ StringRef Message = "") {
+ json::Object Ret{{"physicalLocation", std::move(PhysicalLocation)}};
+ if (!Message.empty())
+ Ret.insert({"message", createMessage(Message)});
+ return Ret;
+}
+
+static Importance calculateImportance(const PathDiagnosticPiece &Piece) {
+ switch (Piece.getKind()) {
+ case PathDiagnosticPiece::Kind::Call:
+ case PathDiagnosticPiece::Kind::Macro:
+ case PathDiagnosticPiece::Kind::Note:
+ // FIXME: What should be reported here?
+ break;
+ case PathDiagnosticPiece::Kind::Event:
+ return Piece.getTagStr() == "ConditionBRVisitor" ? Importance::Important
+ : Importance::Essential;
+ case PathDiagnosticPiece::Kind::ControlFlow:
+ return Importance::Unimportant;
+ }
+ return Importance::Unimportant;
+}
+
+static json::Object createThreadFlow(const PathPieces &Pieces,
+ json::Array &Files) {
+ const SourceManager &SMgr = Pieces.front()->getLocation().getManager();
+ json::Array Locations;
+ for (const auto &Piece : Pieces) {
+ const PathDiagnosticLocation &P = Piece->getLocation();
+ Locations.push_back(createThreadFlowLocation(
+ createLocation(createPhysicalLocation(P.asRange(),
+ *P.asLocation().getFileEntry(),
+ SMgr, Files),
+ Piece->getString()),
+ calculateImportance(*Piece)));
+ }
+ return json::Object{{"locations", std::move(Locations)}};
+}
+
+static json::Object createCodeFlow(const PathPieces &Pieces,
+ json::Array &Files) {
+ return json::Object{
+ {"threadFlows", json::Array{createThreadFlow(Pieces, Files)}}};
+}
+
+static json::Object createTool() {
+ return json::Object{{"name", "clang"},
+ {"fullName", "clang static analyzer"},
+ {"language", "en-US"},
+ {"version", getClangFullVersion()}};
+}
+
+static json::Object createResult(const PathDiagnostic &Diag, json::Array &Files,
+ const StringMap<unsigned> &RuleMapping) {
+ const PathPieces &Path = Diag.path.flatten(false);
+ const SourceManager &SMgr = Path.front()->getLocation().getManager();
+
+ auto Iter = RuleMapping.find(Diag.getCheckName());
+ assert(Iter != RuleMapping.end() && "Rule ID is not in the array index map?");
+
+ return json::Object{
+ {"message", createMessage(Diag.getVerboseDescription())},
+ {"codeFlows", json::Array{createCodeFlow(Path, Files)}},
+ {"locations",
+ json::Array{createLocation(createPhysicalLocation(
+ Diag.getLocation().asRange(),
+ *Diag.getLocation().asLocation().getFileEntry(), SMgr, Files))}},
+ {"ruleIndex", Iter->getValue()},
+ {"ruleId", Diag.getCheckName()}};
+}
+
+static StringRef getRuleDescription(StringRef CheckName) {
+ return llvm::StringSwitch<StringRef>(CheckName)
+#define GET_CHECKERS
+#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
+ .Case(FULLNAME, HELPTEXT)
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+ ;
+}
+
+static StringRef getRuleHelpURIStr(StringRef CheckName) {
+ return llvm::StringSwitch<StringRef>(CheckName)
+#define GET_CHECKERS
+#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
+ .Case(FULLNAME, DOC_URI)
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+ ;
+}
+
+static json::Object createRule(const PathDiagnostic &Diag) {
+ StringRef CheckName = Diag.getCheckName();
+ json::Object Ret{
+ {"fullDescription", createMessage(getRuleDescription(CheckName))},
+ {"name", createMessage(CheckName)},
+ {"id", CheckName}};
+
+ std::string RuleURI = getRuleHelpURIStr(CheckName);
+ if (!RuleURI.empty())
+ Ret["helpUri"] = RuleURI;
+
+ return Ret;
+}
+
+static json::Array createRules(std::vector<const PathDiagnostic *> &Diags,
+ StringMap<unsigned> &RuleMapping) {
+ json::Array Rules;
+ llvm::StringSet<> Seen;
+
+ llvm::for_each(Diags, [&](const PathDiagnostic *D) {
+ StringRef RuleID = D->getCheckName();
+ std::pair<llvm::StringSet<>::iterator, bool> P = Seen.insert(RuleID);
+ if (P.second) {
+ RuleMapping[RuleID] = Rules.size(); // Maps RuleID to an Array Index.
+ Rules.push_back(createRule(*D));
+ }
+ });
+
+ return Rules;
+}
+
+static json::Object createResources(std::vector<const PathDiagnostic *> &Diags,
+ StringMap<unsigned> &RuleMapping) {
+ return json::Object{{"rules", createRules(Diags, RuleMapping)}};
+}
+
+static json::Object createRun(std::vector<const PathDiagnostic *> &Diags) {
+ json::Array Results, Files;
+ StringMap<unsigned> RuleMapping;
+ json::Object Resources = createResources(Diags, RuleMapping);
+
+ llvm::for_each(Diags, [&](const PathDiagnostic *D) {
+ Results.push_back(createResult(*D, Files, RuleMapping));
+ });
+
+ return json::Object{{"tool", createTool()},
+ {"resources", std::move(Resources)},
+ {"results", std::move(Results)},
+ {"files", std::move(Files)}};
+}
+
+void SarifDiagnostics::FlushDiagnosticsImpl(
+ std::vector<const PathDiagnostic *> &Diags, FilesMade *) {
+ // We currently overwrite the file if it already exists. However, it may be
+ // useful to add a feature someday that allows the user to append a run to an
+ // existing SARIF file. One danger from that approach is that the size of the
+ // file can become large very quickly, so decoding into JSON to append a run
+ // may be an expensive operation.
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
+ if (EC) {
+ llvm::errs() << "warning: could not create file: " << EC.message() << '\n';
+ return;
+ }
+ json::Object Sarif{
+ {"$schema",
+ "http://json.schemastore.org/sarif-2.0.0-csd.2.beta.2018-11-28"},
+ {"version", "2.0.0-csd.2.beta.2018-11-28"},
+ {"runs", json::Array{createRun(Diags)}}};
+ OS << llvm::formatv("{0:2}", json::Value(std::move(Sarif)));
+}
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 62c54fc956a9..fc57cecac9cb 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -454,12 +454,12 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
QualType SingleTy;
auto &Opts =
- StateMgr.getOwningEngine()->getAnalysisManager().getAnalyzerOptions();
+ StateMgr.getOwningEngine().getAnalysisManager().getAnalyzerOptions();
// FIXME: After putting complexity threshold to the symbols we can always
// rearrange additive operations but rearrange comparisons only if
// option is set.
- if(!Opts.shouldAggressivelySimplifyBinaryOperation())
+ if(!Opts.ShouldAggressivelySimplifyBinaryOperation)
return None;
SymbolRef LSym = Lhs.getAsSymbol();
@@ -475,9 +475,6 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
SingleTy = ResultTy;
if (LSym->getType() != SingleTy)
return None;
- // Substracting unsigned integers is a nightmare.
- if (!SingleTy->isSignedIntegerOrEnumerationType())
- return None;
} else {
// Don't rearrange other operations.
return None;
@@ -485,6 +482,10 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
assert(!SingleTy.isNull() && "We should have figured out the type by now!");
+ // Rearrange signed symbolic expressions only
+ if (!SingleTy->isSignedIntegerOrEnumerationType())
+ return None;
+
SymbolRef RSym = Rhs.getAsSymbol();
if (!RSym || RSym->getType() != SingleTy)
return None;
@@ -534,7 +535,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
while (1) {
switch (lhs.getSubKind()) {
default:
- return makeSymExprValNN(state, op, lhs, rhs, resultTy);
+ return makeSymExprValNN(op, lhs, rhs, resultTy);
case nonloc::PointerToMemberKind: {
assert(rhs.getSubKind() == nonloc::PointerToMemberKind &&
"Both SVals should have pointer-to-member-type");
@@ -582,7 +583,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
return makeTruthVal(true, resultTy);
default:
// This case also handles pointer arithmetic.
- return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
+ return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
}
}
}
@@ -624,7 +625,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
case BO_LE:
case BO_GE:
op = BinaryOperator::reverseComparisonOp(op);
- // FALL-THROUGH
+ LLVM_FALLTHROUGH;
case BO_EQ:
case BO_NE:
case BO_Add:
@@ -638,14 +639,14 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
// (~0)>>a
if (LHSValue.isAllOnesValue() && LHSValue.isSigned())
return evalCastFromNonLoc(lhs, resultTy);
- // FALL-THROUGH
+ LLVM_FALLTHROUGH;
case BO_Shl:
// 0<<a and 0>>a
if (LHSValue == 0)
return evalCastFromNonLoc(lhs, resultTy);
- return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
+ return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
default:
- return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
+ return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
}
}
case nonloc::SymbolValKind: {
@@ -757,7 +758,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
return *V;
// Give up -- this is not a symbolic expression we can handle.
- return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
+ return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
}
}
}
@@ -1201,6 +1202,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
SVal V) {
+ V = simplifySVal(state, V);
if (V.isUnknownOrUndef())
return nullptr;
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index 94188a9ef698..4fa937d9658d 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/lib/StaticAnalyzer/Core/Store.cpp
@@ -88,7 +88,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
return R;
// We don't know what to make of it. Return a NULL region, which
- // will be interpretted as UnknownVal.
+ // will be interpreted as UnknownVal.
return nullptr;
}
@@ -138,6 +138,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
case MemRegion::VarRegionKind:
case MemRegion::CXXTempObjectRegionKind:
case MemRegion::CXXBaseObjectRegionKind:
+ case MemRegion::CXXDerivedObjectRegionKind:
return MakeElementRegion(cast<SubRegion>(R), PointeeTy);
case MemRegion::ElementRegionKind: {
@@ -272,9 +273,8 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) {
SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
bool IsVirtual) {
- Optional<loc::MemRegionVal> DerivedRegVal =
- Derived.getAs<loc::MemRegionVal>();
- if (!DerivedRegVal)
+ const MemRegion *DerivedReg = Derived.getAsRegion();
+ if (!DerivedReg)
return Derived;
const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl();
@@ -282,8 +282,18 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
BaseDecl = BaseType->getAsCXXRecordDecl();
assert(BaseDecl && "not a C++ object?");
+ if (const auto *AlreadyDerivedReg =
+ dyn_cast<CXXDerivedObjectRegion>(DerivedReg)) {
+ if (const auto *SR =
+ dyn_cast<SymbolicRegion>(AlreadyDerivedReg->getSuperRegion()))
+ if (SR->getSymbol()->getType()->getPointeeCXXRecordDecl() == BaseDecl)
+ return loc::MemRegionVal(SR);
+
+ DerivedReg = AlreadyDerivedReg->getSuperRegion();
+ }
+
const MemRegion *BaseReg = MRMgr.getCXXBaseObjectRegion(
- BaseDecl, cast<SubRegion>(DerivedRegVal->getRegion()), IsVirtual);
+ BaseDecl, cast<SubRegion>(DerivedReg), IsVirtual);
return loc::MemRegionVal(BaseReg);
}
@@ -365,6 +375,20 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
MR = Uncasted;
}
+ // If we're casting a symbolic base pointer to a derived class, use
+ // CXXDerivedObjectRegion to represent the cast. If it's a pointer to an
+ // unrelated type, it must be a weird reinterpret_cast and we have to
+ // be fine with ElementRegion. TODO: Should we instead make
+ // Derived{TargetClass, Element{SourceClass, SR}}?
+ if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) {
+ QualType T = SR->getSymbol()->getType();
+ const CXXRecordDecl *SourceClass = T->getPointeeCXXRecordDecl();
+ if (TargetClass && SourceClass && TargetClass->isDerivedFrom(SourceClass))
+ return loc::MemRegionVal(
+ MRMgr.getCXXDerivedObjectRegion(TargetClass, SR));
+ return loc::MemRegionVal(GetElementZeroRegion(SR, TargetType));
+ }
+
// We failed if the region we ended up with has perfect type info.
Failed = isa<TypedValueRegion>(MR);
return UnknownVal();
@@ -378,6 +402,17 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
if (castTy.isNull() || V.isUnknownOrUndef())
return V;
+ // The dispatchCast() call below would convert the int into a float.
+ // What we want, however, is a bit-by-bit reinterpretation of the int
+ // as a float, which usually yields nothing garbage. For now skip casts
+ // from ints to floats.
+ // TODO: What other combinations of types are affected?
+ if (castTy->isFloatingType()) {
+ SymbolRef Sym = V.getAsSymbol();
+ if (Sym && !Sym->getType()->isFloatingType())
+ return UnknownVal();
+ }
+
// When retrieving symbolic pointer and expecting a non-void pointer,
// wrap them into element regions of the expected type if necessary.
// SValBuilder::dispatchCast() doesn't do that, but it is necessary to
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index ed197010ebb7..66273f099a38 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -83,7 +83,13 @@ void SymbolCast::dumpToStream(raw_ostream &os) const {
}
void SymbolConjured::dumpToStream(raw_ostream &os) const {
- os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}';
+ os << "conj_$" << getSymbolID() << '{' << T.getAsString() << ", LC"
+ << LCtx->getID();
+ if (S)
+ os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
+ else
+ os << ", no stmt";
+ os << ", #" << Count << '}';
}
void SymbolDerived::dumpToStream(raw_ostream &os) const {
@@ -395,7 +401,6 @@ void SymbolReaper::markDependentsLive(SymbolRef sym) {
void SymbolReaper::markLive(SymbolRef sym) {
TheLiving[sym] = NotProcessed;
- TheDead.erase(sym);
markDependentsLive(sym);
}
@@ -420,14 +425,6 @@ void SymbolReaper::markInUse(SymbolRef sym) {
MetadataInUse.insert(sym);
}
-bool SymbolReaper::maybeDead(SymbolRef sym) {
- if (isLive(sym))
- return false;
-
- TheDead.insert(sym);
- return true;
-}
-
bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
if (RegionRoots.count(MR))
return true;
diff --git a/lib/StaticAnalyzer/Core/TaintManager.cpp b/lib/StaticAnalyzer/Core/TaintManager.cpp
new file mode 100644
index 000000000000..c34b0ca1839d
--- /dev/null
+++ b/lib/StaticAnalyzer/Core/TaintManager.cpp
@@ -0,0 +1,23 @@
+//== TaintManager.cpp ------------------------------------------ -*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h"
+
+using namespace clang;
+using namespace ento;
+
+void *ProgramStateTrait<TaintMap>::GDMIndex() {
+ static int index = 0;
+ return &index;
+}
+
+void *ProgramStateTrait<DerivedSymTaint>::GDMIndex() {
+ static int index;
+ return &index;
+}
diff --git a/lib/StaticAnalyzer/Core/WorkList.cpp b/lib/StaticAnalyzer/Core/WorkList.cpp
index 4b227375da9b..e705393cb83a 100644
--- a/lib/StaticAnalyzer/Core/WorkList.cpp
+++ b/lib/StaticAnalyzer/Core/WorkList.cpp
@@ -152,7 +152,7 @@ public:
auto BE = N->getLocation().getAs<BlockEntrance>();
if (!BE) {
- // Assume the choice of the order of the preceeding block entrance was
+ // Assume the choice of the order of the preceding block entrance was
// correct.
StackUnexplored.push_back(U);
} else {
@@ -252,3 +252,63 @@ public:
std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityQueue() {
return llvm::make_unique<UnexploredFirstPriorityQueue>();
}
+
+namespace {
+class UnexploredFirstPriorityLocationQueue : public WorkList {
+ using LocIdentifier = const CFGBlock *;
+
+ // How many times each location was visited.
+ // Is signed because we negate it later in order to have a reversed
+ // comparison.
+ using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
+
+ // Compare by number of times the location was visited first (negated
+ // to prefer less often visited locations), then by insertion time (prefer
+ // expanding nodes inserted sooner first).
+ using QueuePriority = std::pair<int, unsigned long>;
+ using QueueItem = std::pair<WorkListUnit, QueuePriority>;
+
+ struct ExplorationComparator {
+ bool operator() (const QueueItem &LHS, const QueueItem &RHS) {
+ return LHS.second < RHS.second;
+ }
+ };
+
+ // Number of inserted nodes, used to emulate DFS ordering in the priority
+ // queue when insertions are equal.
+ unsigned long Counter = 0;
+
+ // Number of times a current location was reached.
+ VisitedTimesMap NumReached;
+
+ // The top item is the largest one.
+ llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
+ queue;
+
+public:
+ bool hasWork() const override {
+ return !queue.empty();
+ }
+
+ void enqueue(const WorkListUnit &U) override {
+ const ExplodedNode *N = U.getNode();
+ unsigned NumVisited = 0;
+ if (auto BE = N->getLocation().getAs<BlockEntrance>())
+ NumVisited = NumReached[BE->getBlock()]++;
+
+ queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
+ }
+
+ WorkListUnit dequeue() override {
+ QueueItem U = queue.top();
+ queue.pop();
+ return U.first;
+ }
+
+};
+
+}
+
+std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityLocationQueue() {
+ return llvm::make_unique<UnexploredFirstPriorityLocationQueue>();
+}
diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
index 7379ded49c80..c4729f969f33 100644
--- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -11,10 +11,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
#include "clang/Config/config.h"
@@ -49,15 +46,15 @@ public:
// Function used to report errors
void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) {
llvm::report_fatal_error("Z3 error: " +
- llvm::Twine(Z3_get_error_msg_ex(Context, Error)));
+ llvm::Twine(Z3_get_error_msg(Context, Error)));
}
/// Wrapper for Z3 context
-class Z3Context : public SMTContext {
+class Z3Context {
public:
Z3_context Context;
- Z3Context() : SMTContext() {
+ Z3Context() {
Context = Z3_mk_context_rc(Z3Config().Config);
// The error function is set here because the context is the first object
// created by the backend
@@ -80,32 +77,27 @@ class Z3Sort : public SMTSort {
public:
/// Default constructor, mainly used by make_shared
- Z3Sort(Z3Context &C, Z3_sort ZS) : SMTSort(), Context(C), Sort(ZS) {
+ Z3Sort(Z3Context &C, Z3_sort ZS) : Context(C), Sort(ZS) {
Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
}
/// Override implicit copy constructor for correct reference counting.
- Z3Sort(const Z3Sort &Copy)
- : SMTSort(), Context(Copy.Context), Sort(Copy.Sort) {
+ Z3Sort(const Z3Sort &Other) : Context(Other.Context), Sort(Other.Sort) {
Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
}
- /// Provide move constructor
- Z3Sort(Z3Sort &&Move) : SMTSort(), Context(Move.Context), Sort(nullptr) {
- *this = std::move(Move);
- }
-
- /// Provide move assignment constructor
- Z3Sort &operator=(Z3Sort &&Move) {
- if (this != &Move) {
- if (Sort)
- Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
- Sort = Move.Sort;
- Move.Sort = nullptr;
- }
+ /// Override implicit copy assignment constructor for correct reference
+ /// counting.
+ Z3Sort &operator=(const Z3Sort &Other) {
+ Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Other.Sort));
+ Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
+ Sort = Other.Sort;
return *this;
}
+ Z3Sort(Z3Sort &&Other) = delete;
+ Z3Sort &operator=(Z3Sort &&Other) = delete;
+
~Z3Sort() {
if (Sort)
Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
@@ -137,13 +129,6 @@ public:
static_cast<const Z3Sort &>(Other).Sort);
}
- Z3Sort &operator=(const Z3Sort &Move) {
- Z3_inc_ref(Context.Context, reinterpret_cast<Z3_ast>(Move.Sort));
- Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
- Sort = Move.Sort;
- return *this;
- }
-
void print(raw_ostream &OS) const override {
OS << Z3_sort_to_string(Context.Context, Sort);
}
@@ -170,22 +155,18 @@ public:
Z3_inc_ref(Context.Context, AST);
}
- /// Provide move constructor
- Z3Expr(Z3Expr &&Move) : SMTExpr(), Context(Move.Context), AST(nullptr) {
- *this = std::move(Move);
- }
-
- /// Provide move assignment constructor
- Z3Expr &operator=(Z3Expr &&Move) {
- if (this != &Move) {
- if (AST)
- Z3_dec_ref(Context.Context, AST);
- AST = Move.AST;
- Move.AST = nullptr;
- }
+ /// Override implicit copy assignment constructor for correct reference
+ /// counting.
+ Z3Expr &operator=(const Z3Expr &Other) {
+ Z3_inc_ref(Context.Context, Other.AST);
+ Z3_dec_ref(Context.Context, AST);
+ AST = Other.AST;
return *this;
}
+ Z3Expr(Z3Expr &&Other) = delete;
+ Z3Expr &operator=(Z3Expr &&Other) = delete;
+
~Z3Expr() {
if (AST)
Z3_dec_ref(Context.Context, AST);
@@ -205,14 +186,6 @@ public:
static_cast<const Z3Expr &>(Other).AST);
}
- /// Override implicit move constructor for correct reference counting.
- Z3Expr &operator=(const Z3Expr &Move) {
- Z3_inc_ref(Context.Context, Move.AST);
- Z3_dec_ref(Context.Context, AST);
- AST = Move.AST;
- return *this;
- }
-
void print(raw_ostream &OS) const override {
OS << Z3_ast_to_string(Context.Context, AST);
}
@@ -231,30 +204,13 @@ class Z3Model {
public:
Z3Model(Z3Context &C, Z3_model ZM) : Context(C), Model(ZM) {
- assert(C.Context != nullptr);
Z3_model_inc_ref(Context.Context, Model);
}
- /// Override implicit copy constructor for correct reference counting.
- Z3Model(const Z3Model &Copy) : Context(Copy.Context), Model(Copy.Model) {
- Z3_model_inc_ref(Context.Context, Model);
- }
-
- /// Provide move constructor
- Z3Model(Z3Model &&Move) : Context(Move.Context), Model(nullptr) {
- *this = std::move(Move);
- }
-
- /// Provide move assignment constructor
- Z3Model &operator=(Z3Model &&Move) {
- if (this != &Move) {
- if (Model)
- Z3_model_dec_ref(Context.Context, Model);
- Model = Move.Model;
- Move.Model = nullptr;
- }
- return *this;
- }
+ Z3Model(const Z3Model &Other) = delete;
+ Z3Model(Z3Model &&Other) = delete;
+ Z3Model &operator=(Z3Model &Other) = delete;
+ Z3Model &operator=(Z3Model &&Other) = delete;
~Z3Model() {
if (Model)
@@ -313,32 +269,14 @@ class Z3Solver : public SMTSolver {
Z3_solver Solver;
public:
- Z3Solver() : SMTSolver(), Solver(Z3_mk_simple_solver(Context.Context)) {
- Z3_solver_inc_ref(Context.Context, Solver);
- }
-
- /// Override implicit copy constructor for correct reference counting.
- Z3Solver(const Z3Solver &Copy)
- : SMTSolver(), Context(Copy.Context), Solver(Copy.Solver) {
+ Z3Solver() : Solver(Z3_mk_simple_solver(Context.Context)) {
Z3_solver_inc_ref(Context.Context, Solver);
}
- /// Provide move constructor
- Z3Solver(Z3Solver &&Move)
- : SMTSolver(), Context(Move.Context), Solver(nullptr) {
- *this = std::move(Move);
- }
-
- /// Provide move assignment constructor
- Z3Solver &operator=(Z3Solver &&Move) {
- if (this != &Move) {
- if (Solver)
- Z3_solver_dec_ref(Context.Context, Solver);
- Solver = Move.Solver;
- Move.Solver = nullptr;
- }
- return *this;
- }
+ Z3Solver(const Z3Solver &Other) = delete;
+ Z3Solver(Z3Solver &&Other) = delete;
+ Z3Solver &operator=(Z3Solver &Other) = delete;
+ Z3Solver &operator=(Z3Solver &&Other) = delete;
~Z3Solver() {
if (Solver)
@@ -674,7 +612,7 @@ public:
toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
}
- SMTExprRef mkFPtoSBV(const SMTExprRef &From, const SMTSortRef &To) override {
+ SMTExprRef mkSBVtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
SMTExprRef RoundingMode = getFloatRoundingMode();
return newExprRef(Z3Expr(
Context,
@@ -682,7 +620,7 @@ public:
toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
}
- SMTExprRef mkFPtoUBV(const SMTExprRef &From, const SMTSortRef &To) override {
+ SMTExprRef mkUBVtoFP(const SMTExprRef &From, const SMTSortRef &To) override {
SMTExprRef RoundingMode = getFloatRoundingMode();
return newExprRef(Z3Expr(
Context,
@@ -690,14 +628,14 @@ public:
toZ3Expr(*From).AST, toZ3Sort(*To).Sort)));
}
- SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) override {
+ SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) override {
SMTExprRef RoundingMode = getFloatRoundingMode();
return newExprRef(Z3Expr(
Context, Z3_mk_fpa_to_sbv(Context.Context, toZ3Expr(*RoundingMode).AST,
toZ3Expr(*From).AST, ToWidth)));
}
- SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) override {
+ SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) override {
SMTExprRef RoundingMode = getFloatRoundingMode();
return newExprRef(Z3Expr(
Context, Z3_mk_fpa_to_ubv(Context.Context, toZ3Expr(*RoundingMode).AST,
@@ -736,9 +674,11 @@ public:
llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
bool isUnsigned) override {
- return llvm::APSInt(llvm::APInt(
- BitWidth, Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST),
- 10));
+ return llvm::APSInt(
+ llvm::APInt(BitWidth,
+ Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST),
+ 10),
+ isUnsigned);
}
bool getBoolean(const SMTExprRef &Exp) override {
@@ -750,42 +690,6 @@ public:
return newExprRef(Z3Expr(Context, Z3_mk_fpa_rne(Context.Context)));
}
- SMTExprRef fromData(const SymbolID ID, const QualType &Ty,
- uint64_t BitWidth) override {
- llvm::Twine Name = "$" + llvm::Twine(ID);
- return mkSymbol(Name.str().c_str(), mkSort(Ty, BitWidth));
- }
-
- SMTExprRef fromBoolean(const bool Bool) override {
- Z3_ast AST =
- Bool ? Z3_mk_true(Context.Context) : Z3_mk_false(Context.Context);
- return newExprRef(Z3Expr(Context, AST));
- }
-
- SMTExprRef fromAPFloat(const llvm::APFloat &Float) override {
- SMTSortRef Sort =
- getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics()));
-
- llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false);
- SMTExprRef Z3Int = fromAPSInt(Int);
- return newExprRef(Z3Expr(
- Context, Z3_mk_fpa_to_fp_bv(Context.Context, toZ3Expr(*Z3Int).AST,
- toZ3Sort(*Sort).Sort)));
- }
-
- SMTExprRef fromAPSInt(const llvm::APSInt &Int) override {
- SMTSortRef Sort = getBitvectorSort(Int.getBitWidth());
- Z3_ast AST = Z3_mk_numeral(Context.Context, Int.toString(10).c_str(),
- toZ3Sort(*Sort).Sort);
- return newExprRef(Z3Expr(Context, AST));
- }
-
- SMTExprRef fromInt(const char *Int, uint64_t BitWidth) override {
- SMTSortRef Sort = getBitvectorSort(BitWidth);
- Z3_ast AST = Z3_mk_numeral(Context.Context, Int, toZ3Sort(*Sort).Sort);
- return newExprRef(Z3Expr(Context, AST));
- }
-
bool toAPFloat(const SMTSortRef &Sort, const SMTExprRef &AST,
llvm::APFloat &Float, bool useSemantics) {
assert(Sort->isFloatSort() && "Unsupported sort to floating-point!");
@@ -846,7 +750,7 @@ public:
}
bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) override {
- Z3Model Model = getModel();
+ Z3Model Model(Context, Z3_solver_get_model(Context.Context, Solver));
Z3_func_decl Func = Z3_get_app_decl(
Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
@@ -860,7 +764,7 @@ public:
}
bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) override {
- Z3Model Model = getModel();
+ Z3Model Model(Context, Z3_solver_get_model(Context.Context, Solver));
Z3_func_decl Func = Z3_get_app_decl(
Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST));
if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE)
@@ -873,7 +777,7 @@ public:
return toAPFloat(Sort, Assign, Float, true);
}
- ConditionTruthVal check() const override {
+ Optional<bool> check() const override {
Z3_lbool res = Z3_solver_check(Context.Context, Solver);
if (res == Z3_L_TRUE)
return true;
@@ -881,7 +785,7 @@ public:
if (res == Z3_L_FALSE)
return false;
- return ConditionTruthVal();
+ return Optional<bool>();
}
void push() override { return Z3_solver_push(Context.Context, Solver); }
@@ -891,138 +795,34 @@ public:
return Z3_solver_pop(Context.Context, Solver, NumStates);
}
- /// Get a model from the solver. Caller should check the model is
- /// satisfiable.
- Z3Model getModel() {
- return Z3Model(Context, Z3_solver_get_model(Context.Context, Solver));
- }
+ bool isFPSupported() override { return true; }
/// Reset the solver and remove all constraints.
- void reset() const override { Z3_solver_reset(Context.Context, Solver); }
+ void reset() override { Z3_solver_reset(Context.Context, Solver); }
void print(raw_ostream &OS) const override {
OS << Z3_solver_to_string(Context.Context, Solver);
}
}; // end class Z3Solver
-class Z3ConstraintManager : public SMTConstraintManager {
+class Z3ConstraintManager : public SMTConstraintManager<ConstraintZ3, Z3Expr> {
SMTSolverRef Solver = CreateZ3Solver();
public:
Z3ConstraintManager(SubEngine *SE, SValBuilder &SB)
: SMTConstraintManager(SE, SB, Solver) {}
-
- void addStateConstraints(ProgramStateRef State) const override {
- // TODO: Don't add all the constraints, only the relevant ones
- ConstraintZ3Ty CZ = State->get<ConstraintZ3>();
- ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end();
-
- // Construct the logical AND of all the constraints
- if (I != IE) {
- std::vector<SMTExprRef> ASTs;
-
- SMTExprRef Constraint = Solver->newExprRef(I++->second);
- while (I != IE) {
- Constraint = Solver->mkAnd(Constraint, Solver->newExprRef(I++->second));
- }
-
- Solver->addConstraint(Constraint);
- }
- }
-
- bool canReasonAbout(SVal X) const override {
- const TargetInfo &TI = getBasicVals().getContext().getTargetInfo();
-
- Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
- if (!SymVal)
- return true;
-
- const SymExpr *Sym = SymVal->getSymbol();
- QualType Ty = Sym->getType();
-
- // Complex types are not modeled
- if (Ty->isComplexType() || Ty->isComplexIntegerType())
- return false;
-
- // Non-IEEE 754 floating-point types are not modeled
- if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) &&
- (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() ||
- &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())))
- return false;
-
- if (isa<SymbolData>(Sym))
- return true;
-
- SValBuilder &SVB = getSValBuilder();
-
- if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
- return canReasonAbout(SVB.makeSymbolVal(SC->getOperand()));
-
- if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
- if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE))
- return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS()));
-
- if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE))
- return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS()));
-
- if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE))
- return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) &&
- canReasonAbout(SVB.makeSymbolVal(SSE->getRHS()));
- }
-
- llvm_unreachable("Unsupported expression to reason about!");
- }
-
- ProgramStateRef removeDeadBindings(ProgramStateRef State,
- SymbolReaper &SymReaper) override {
- ConstraintZ3Ty CZ = State->get<ConstraintZ3>();
- ConstraintZ3Ty::Factory &CZFactory = State->get_context<ConstraintZ3>();
-
- for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) {
- if (SymReaper.maybeDead(I->first))
- CZ = CZFactory.remove(CZ, *I);
- }
-
- return State->set<ConstraintZ3>(CZ);
- }
-
- ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym,
- const SMTExprRef &Exp) override {
- // Check the model, avoid simplifying AST to save time
- if (checkModel(State, Exp).isConstrainedTrue())
- return State->add<ConstraintZ3>(std::make_pair(Sym, toZ3Expr(*Exp)));
-
- return nullptr;
- }
-
- //==------------------------------------------------------------------------==/
- // Pretty-printing.
- //==------------------------------------------------------------------------==/
-
- void print(ProgramStateRef St, raw_ostream &OS, const char *nl,
- const char *sep) override {
-
- ConstraintZ3Ty CZ = St->get<ConstraintZ3>();
-
- OS << nl << sep << "Constraints:";
- for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) {
- OS << nl << ' ' << I->first << " : ";
- I->second.print(OS);
- }
- OS << nl;
- }
}; // end class Z3ConstraintManager
} // end anonymous namespace
#endif
-std::unique_ptr<SMTSolver> clang::ento::CreateZ3Solver() {
+SMTSolverRef clang::ento::CreateZ3Solver() {
#if CLANG_ANALYZER_WITH_Z3
return llvm::make_unique<Z3Solver>();
#else
llvm::report_fatal_error("Clang was not compiled with Z3 support, rebuild "
- "with -DCLANG_ANALYZER_BUILD_Z3=ON",
+ "with -DCLANG_ANALYZER_ENABLE_Z3_SOLVER=ON",
false);
return nullptr;
#endif
@@ -1034,7 +834,7 @@ ento::CreateZ3ConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) {
return llvm::make_unique<Z3ConstraintManager>(Eng, StMgr.getSValBuilder());
#else
llvm::report_fatal_error("Clang was not compiled with Z3 support, rebuild "
- "with -DCLANG_ANALYZER_BUILD_Z3=ON",
+ "with -DCLANG_ANALYZER_ENABLE_Z3_SOLVER=ON",
false);
return nullptr;
#endif
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 44abde5da6d1..d87937d9b63d 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -50,8 +50,6 @@ using namespace ento;
#define DEBUG_TYPE "AnalysisConsumer"
-static std::unique_ptr<ExplodedNode::Auditor> CreateUbiViz();
-
STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
STATISTIC(NumFunctionsAnalyzed,
"The # of functions and blocks analyzed (as top level "
@@ -206,7 +204,7 @@ public:
PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
Plugins(plugins), Injector(injector), CTU(CI) {
DigestAnalyzerOptions();
- if (Opts->PrintStats || Opts->shouldSerializeStats()) {
+ if (Opts->PrintStats || Opts->ShouldSerializeStats) {
AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
"analyzer", "Analyzer timers");
TUTotalTimer = llvm::make_unique<llvm::Timer>(
@@ -295,13 +293,12 @@ public:
void Initialize(ASTContext &Context) override {
Ctx = &Context;
- checkerMgr =
- createCheckerManager(*Opts, PP.getLangOpts(), Plugins,
- CheckerRegistrationFns, PP.getDiagnostics());
+ checkerMgr = createCheckerManager(
+ *Ctx, *Opts, Plugins, CheckerRegistrationFns, PP.getDiagnostics());
Mgr = llvm::make_unique<AnalysisManager>(
- *Ctx, PP.getDiagnostics(), PP.getLangOpts(), PathConsumers,
- CreateStoreMgr, CreateConstraintMgr, checkerMgr.get(), *Opts, Injector);
+ *Ctx, PP.getDiagnostics(), PathConsumers, CreateStoreMgr,
+ CreateConstraintMgr, checkerMgr.get(), *Opts, Injector);
}
/// Store the top level decls in the set to be processed later on.
@@ -334,9 +331,6 @@ public:
void RunPathSensitiveChecks(Decl *D,
ExprEngine::InliningModes IMode,
SetOfConstDecls *VisitedCallees);
- void ActionExprEngine(Decl *D, bool ObjCGCEnabled,
- ExprEngine::InliningModes IMode,
- SetOfConstDecls *VisitedCallees);
/// Visitors for the RecursiveASTVisitor.
bool shouldWalkTypesOfTypeLocs() const { return false; }
@@ -682,7 +676,7 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
// - System headers: don't run any checks.
SourceManager &SM = Ctx->getSourceManager();
const Stmt *Body = D->getBody();
- SourceLocation SL = Body ? Body->getLocStart() : D->getLocation();
+ SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
SL = SM.getExpansionLoc(SL);
if (!Opts->AnalyzeAll && !Mgr->isInCodeFile(SL)) {
@@ -729,9 +723,9 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
// Path-sensitive checking.
//===----------------------------------------------------------------------===//
-void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
- ExprEngine::InliningModes IMode,
- SetOfConstDecls *VisitedCallees) {
+void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
+ ExprEngine::InliningModes IMode,
+ SetOfConstDecls *VisitedCallees) {
// Construct the analysis engine. First check if the CFG is valid.
// FIXME: Inter-procedural analysis will need to handle invalid CFGs.
if (!Mgr->getCFG(D))
@@ -741,23 +735,14 @@ void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
return;
- ExprEngine Eng(CTU, *Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries,
- IMode);
-
- // Set the graph auditor.
- std::unique_ptr<ExplodedNode::Auditor> Auditor;
- if (Mgr->options.visualizeExplodedGraphWithUbiGraph) {
- Auditor = CreateUbiViz();
- ExplodedNode::SetAuditor(Auditor.get());
- }
+ ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
// Execute the worklist algorithm.
Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
- Mgr->options.getMaxNodesPerTopLevelFunction());
+ Mgr->options.MaxNodesPerTopLevelFunction);
- // Release the auditor (if any) so that it doesn't monitor the graph
- // created BugReporter.
- ExplodedNode::SetAuditor(nullptr);
+ if (!Mgr->options.DumpExplodedGraphTo.empty())
+ Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
// Visualize the exploded graph.
if (Mgr->options.visualizeExplodedGraphWithGraphViz)
@@ -767,26 +752,6 @@ void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
Eng.getBugReporter().FlushReports();
}
-void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
- ExprEngine::InliningModes IMode,
- SetOfConstDecls *Visited) {
-
- switch (Mgr->getLangOpts().getGC()) {
- case LangOptions::NonGC:
- ActionExprEngine(D, false, IMode, Visited);
- break;
-
- case LangOptions::GCOnly:
- ActionExprEngine(D, true, IMode, Visited);
- break;
-
- case LangOptions::HybridGC:
- ActionExprEngine(D, false, IMode, Visited);
- ActionExprEngine(D, true, IMode, Visited);
- break;
- }
-}
-
//===----------------------------------------------------------------------===//
// AnalysisConsumer creation.
//===----------------------------------------------------------------------===//
@@ -804,98 +769,3 @@ ento::CreateAnalysisConsumer(CompilerInstance &CI) {
CI.getFrontendOpts().Plugins,
hasModelPath ? new ModelInjector(CI) : nullptr);
}
-
-//===----------------------------------------------------------------------===//
-// Ubigraph Visualization. FIXME: Move to separate file.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class UbigraphViz : public ExplodedNode::Auditor {
- std::unique_ptr<raw_ostream> Out;
- std::string Filename;
- unsigned Cntr;
-
- typedef llvm::DenseMap<void*,unsigned> VMap;
- VMap M;
-
-public:
- UbigraphViz(std::unique_ptr<raw_ostream> Out, StringRef Filename);
-
- ~UbigraphViz() override;
-
- void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) override;
-};
-
-} // end anonymous namespace
-
-static std::unique_ptr<ExplodedNode::Auditor> CreateUbiViz() {
- SmallString<128> P;
- int FD;
- llvm::sys::fs::createTemporaryFile("llvm_ubi", "", FD, P);
- llvm::errs() << "Writing '" << P << "'.\n";
-
- auto Stream = llvm::make_unique<llvm::raw_fd_ostream>(FD, true);
-
- return llvm::make_unique<UbigraphViz>(std::move(Stream), P);
-}
-
-void UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
-
- assert (Src != Dst && "Self-edges are not allowed.");
-
- // Lookup the Src. If it is a new node, it's a root.
- VMap::iterator SrcI= M.find(Src);
- unsigned SrcID;
-
- if (SrcI == M.end()) {
- M[Src] = SrcID = Cntr++;
- *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
- }
- else
- SrcID = SrcI->second;
-
- // Lookup the Dst.
- VMap::iterator DstI= M.find(Dst);
- unsigned DstID;
-
- if (DstI == M.end()) {
- M[Dst] = DstID = Cntr++;
- *Out << "('vertex', " << DstID << ")\n";
- }
- else {
- // We have hit DstID before. Change its style to reflect a cache hit.
- DstID = DstI->second;
- *Out << "('change_vertex_style', " << DstID << ", 1)\n";
- }
-
- // Add the edge.
- *Out << "('edge', " << SrcID << ", " << DstID
- << ", ('arrow','true'), ('oriented', 'true'))\n";
-}
-
-UbigraphViz::UbigraphViz(std::unique_ptr<raw_ostream> OutStream,
- StringRef Filename)
- : Out(std::move(OutStream)), Filename(Filename), Cntr(0) {
-
- *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
- *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
- " ('size', '1.5'))\n";
-}
-
-UbigraphViz::~UbigraphViz() {
- Out.reset();
- llvm::errs() << "Running 'ubiviz' program... ";
- std::string ErrMsg;
- std::string Ubiviz;
- if (auto Path = llvm::sys::findProgramByName("ubiviz"))
- Ubiviz = *Path;
- std::array<StringRef, 2> Args{{Ubiviz, Filename}};
-
- if (llvm::sys::ExecuteAndWait(Ubiviz, Args, llvm::None, {}, 0, 0, &ErrMsg)) {
- llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
- }
-
- // Delete the file.
- llvm::sys::fs::remove(Filename);
-}
diff --git a/lib/StaticAnalyzer/Frontend/CMakeLists.txt b/lib/StaticAnalyzer/Frontend/CMakeLists.txt
index ff0a6e19fc97..5e7dd8f18cd7 100644
--- a/lib/StaticAnalyzer/Frontend/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Frontend/CMakeLists.txt
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangStaticAnalyzerFrontend
AnalysisConsumer.cpp
CheckerRegistration.cpp
+ CheckerRegistry.cpp
FrontendActions.cpp
ModelConsumer.cpp
ModelInjector.cpp
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index a260c2d85b11..1c31c35b75e4 100644
--- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -14,146 +14,124 @@
#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
-#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/Path.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
using namespace clang;
using namespace ento;
-using llvm::sys::DynamicLibrary;
-
-namespace {
-class ClangCheckerRegistry : public CheckerRegistry {
- typedef void (*RegisterCheckersFn)(CheckerRegistry &);
-
- static bool isCompatibleAPIVersion(const char *versionString);
- static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath,
- const char *pluginAPIVersion);
-
-public:
- ClangCheckerRegistry(ArrayRef<std::string> plugins,
- DiagnosticsEngine *diags = nullptr);
-};
-
-} // end anonymous namespace
-
-ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins,
- DiagnosticsEngine *diags) {
- registerBuiltinCheckers(*this);
-
- for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end();
- i != e; ++i) {
- // Get access to the plugin.
- std::string err;
- DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str(), &err);
- if (!lib.isValid()) {
- diags->Report(diag::err_fe_unable_to_load_plugin) << *i << err;
- continue;
- }
-
- // See if it's compatible with this build of clang.
- const char *pluginAPIVersion =
- (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString");
- if (!isCompatibleAPIVersion(pluginAPIVersion)) {
- warnIncompatible(diags, *i, pluginAPIVersion);
- continue;
- }
-
- // Register its checkers.
- RegisterCheckersFn registerPluginCheckers =
- (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol(
- "clang_registerCheckers");
- if (registerPluginCheckers)
- registerPluginCheckers(*this);
- }
-}
-
-bool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) {
- // If the version string is null, it's not an analyzer plugin.
- if (!versionString)
- return false;
-
- // For now, none of the static analyzer API is considered stable.
- // Versions must match exactly.
- return strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
-}
-
-void ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags,
- StringRef pluginPath,
- const char *pluginAPIVersion) {
- if (!diags)
- return;
- if (!pluginAPIVersion)
- return;
-
- diags->Report(diag::warn_incompatible_analyzer_plugin_api)
- << llvm::sys::path::filename(pluginPath);
- diags->Report(diag::note_incompatible_analyzer_plugin_api)
- << CLANG_ANALYZER_API_VERSION_STRING
- << pluginAPIVersion;
-}
-
-static SmallVector<CheckerOptInfo, 8>
-getCheckerOptList(const AnalyzerOptions &opts) {
- SmallVector<CheckerOptInfo, 8> checkerOpts;
- for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
- const std::pair<std::string, bool> &opt = opts.CheckersControlList[i];
- checkerOpts.push_back(CheckerOptInfo(opt.first, opt.second));
- }
- return checkerOpts;
-}
std::unique_ptr<CheckerManager> ento::createCheckerManager(
- AnalyzerOptions &opts, const LangOptions &langOpts,
+ ASTContext &context,
+ AnalyzerOptions &opts,
ArrayRef<std::string> plugins,
ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
DiagnosticsEngine &diags) {
- std::unique_ptr<CheckerManager> checkerMgr(
- new CheckerManager(langOpts, opts));
-
- SmallVector<CheckerOptInfo, 8> checkerOpts = getCheckerOptList(opts);
+ auto checkerMgr = llvm::make_unique<CheckerManager>(context, opts);
- ClangCheckerRegistry allCheckers(plugins, &diags);
+ CheckerRegistry allCheckers(plugins, diags);
for (const auto &Fn : checkerRegistrationFns)
Fn(allCheckers);
- allCheckers.initializeManager(*checkerMgr, checkerOpts);
- allCheckers.validateCheckerOptions(opts, diags);
+ allCheckers.initializeManager(*checkerMgr, opts);
+ allCheckers.validateCheckerOptions(opts);
checkerMgr->finishedCheckerRegistration();
- for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) {
- if (checkerOpts[i].isUnclaimed()) {
- diags.Report(diag::err_unknown_analyzer_checker)
- << checkerOpts[i].getName();
- diags.Report(diag::note_suggest_disabling_all_checkers);
- }
-
- }
-
return checkerMgr;
}
-void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) {
+void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins,
+ DiagnosticsEngine &diags) {
out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
- ClangCheckerRegistry(plugins).printHelp(out);
+ CheckerRegistry(plugins, diags).printHelp(out);
}
void ento::printEnabledCheckerList(raw_ostream &out,
ArrayRef<std::string> plugins,
- const AnalyzerOptions &opts) {
+ const AnalyzerOptions &opts,
+ DiagnosticsEngine &diags) {
out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n";
- SmallVector<CheckerOptInfo, 8> checkerOpts = getCheckerOptList(opts);
- ClangCheckerRegistry(plugins).printList(out, checkerOpts);
+ CheckerRegistry(plugins, diags).printList(out, opts);
+}
+
+void ento::printAnalyzerConfigList(raw_ostream &out) {
+ out << "OVERVIEW: Clang Static Analyzer -analyzer-config Option List\n\n";
+ out << "USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config "
+ "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
+ out << " clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, "
+ "-analyzer-config OPTION2=VALUE, ...\n\n";
+ out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang"
+ "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
+ out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang "
+ "OPTION1=VALUE, -Xclang -analyzer-config -Xclang "
+ "OPTION2=VALUE, ...\n\n";
+ out << "OPTIONS:\n\n";
+
+ using OptionAndDescriptionTy = std::pair<StringRef, std::string>;
+ OptionAndDescriptionTy PrintableOptions[] = {
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
+ { \
+ CMDFLAG, \
+ llvm::Twine(llvm::Twine() + "(" + \
+ (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
+ ") " DESC \
+ " (default: " #DEFAULT_VAL ")").str() \
+ },
+
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL) \
+ { \
+ CMDFLAG, \
+ llvm::Twine(llvm::Twine() + "(" + \
+ (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
+ ") " DESC \
+ " (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL \
+ " in deep mode)").str() \
+ },
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+ };
+
+ llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS,
+ const OptionAndDescriptionTy &RHS) {
+ return LHS.first < RHS.first;
+ });
+
+ constexpr size_t MinLineWidth = 70;
+ constexpr size_t PadForOpt = 2;
+ constexpr size_t OptionWidth = 30;
+ constexpr size_t PadForDesc = PadForOpt + OptionWidth;
+ static_assert(MinLineWidth > PadForDesc, "MinLineWidth must be greater!");
+
+ llvm::formatted_raw_ostream FOut(out);
+
+ for (const auto &Pair : PrintableOptions) {
+ FOut.PadToColumn(PadForOpt) << Pair.first;
+
+ // If the buffer's length is greater then PadForDesc, print a newline.
+ if (FOut.getColumn() > PadForDesc)
+ FOut << '\n';
+
+ FOut.PadToColumn(PadForDesc);
+
+ for (char C : Pair.second) {
+ if (FOut.getColumn() > MinLineWidth && C == ' ') {
+ FOut << '\n';
+ FOut.PadToColumn(PadForDesc);
+ continue;
+ }
+ FOut << C;
+ }
+ FOut << "\n\n";
+ }
}
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
new file mode 100644
index 000000000000..620c0e588906
--- /dev/null
+++ b/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
@@ -0,0 +1,247 @@
+//===- CheckerRegistry.cpp - Maintains all available checkers -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+using namespace clang;
+using namespace ento;
+using llvm::sys::DynamicLibrary;
+
+using RegisterCheckersFn = void (*)(CheckerRegistry &);
+
+static bool isCompatibleAPIVersion(const char *versionString) {
+ // If the version string is null, it's not an analyzer plugin.
+ if (!versionString)
+ return false;
+
+ // For now, none of the static analyzer API is considered stable.
+ // Versions must match exactly.
+ return strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
+}
+
+CheckerRegistry::CheckerRegistry(ArrayRef<std::string> plugins,
+ DiagnosticsEngine &diags) : Diags(diags) {
+#define GET_CHECKERS
+#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
+ addChecker(register##CLASS, FULLNAME, HELPTEXT, DOC_URI);
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+
+ for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end();
+ i != e; ++i) {
+ // Get access to the plugin.
+ std::string err;
+ DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str(), &err);
+ if (!lib.isValid()) {
+ diags.Report(diag::err_fe_unable_to_load_plugin) << *i << err;
+ continue;
+ }
+
+ // See if it's compatible with this build of clang.
+ const char *pluginAPIVersion =
+ (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString");
+ if (!isCompatibleAPIVersion(pluginAPIVersion)) {
+ Diags.Report(diag::warn_incompatible_analyzer_plugin_api)
+ << llvm::sys::path::filename(*i);
+ Diags.Report(diag::note_incompatible_analyzer_plugin_api)
+ << CLANG_ANALYZER_API_VERSION_STRING
+ << pluginAPIVersion;
+ continue;
+ }
+
+ // Register its checkers.
+ RegisterCheckersFn registerPluginCheckers =
+ (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol(
+ "clang_registerCheckers");
+ if (registerPluginCheckers)
+ registerPluginCheckers(*this);
+ }
+}
+
+static constexpr char PackageSeparator = '.';
+
+static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
+ const CheckerRegistry::CheckerInfo &b) {
+ return a.FullName < b.FullName;
+}
+
+static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
+ StringRef packageName) {
+ // Does the checker's full name have the package as a prefix?
+ if (!checker.FullName.startswith(packageName))
+ return false;
+
+ // Is the package actually just the name of a specific checker?
+ if (checker.FullName.size() == packageName.size())
+ return true;
+
+ // Is the checker in the package (or a subpackage)?
+ if (checker.FullName[packageName.size()] == PackageSeparator)
+ return true;
+
+ return false;
+}
+
+CheckerRegistry::CheckerInfoSet CheckerRegistry::getEnabledCheckers(
+ const AnalyzerOptions &Opts) const {
+
+ assert(std::is_sorted(Checkers.begin(), Checkers.end(), checkerNameLT) &&
+ "In order to efficiently gather checkers, this function expects them "
+ "to be already sorted!");
+
+ CheckerInfoSet enabledCheckers;
+ const auto end = Checkers.cend();
+
+ for (const std::pair<std::string, bool> &opt : Opts.CheckersControlList) {
+ // Use a binary search to find the possible start of the package.
+ CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.first, "", "");
+ auto firstRelatedChecker =
+ std::lower_bound(Checkers.cbegin(), end, packageInfo, checkerNameLT);
+
+ if (firstRelatedChecker == end ||
+ !isInPackage(*firstRelatedChecker, opt.first)) {
+ Diags.Report(diag::err_unknown_analyzer_checker) << opt.first;
+ Diags.Report(diag::note_suggest_disabling_all_checkers);
+ return {};
+ }
+
+ // See how large the package is.
+ // If the package doesn't exist, assume the option refers to a single
+ // checker.
+ size_t size = 1;
+ llvm::StringMap<size_t>::const_iterator packageSize =
+ Packages.find(opt.first);
+ if (packageSize != Packages.end())
+ size = packageSize->getValue();
+
+ // Step through all the checkers in the package.
+ for (auto lastRelatedChecker = firstRelatedChecker+size;
+ firstRelatedChecker != lastRelatedChecker; ++firstRelatedChecker)
+ if (opt.second)
+ enabledCheckers.insert(&*firstRelatedChecker);
+ else
+ enabledCheckers.remove(&*firstRelatedChecker);
+ }
+
+ return enabledCheckers;
+}
+
+void CheckerRegistry::addChecker(InitializationFunction Fn, StringRef Name,
+ StringRef Desc, StringRef DocsUri) {
+ Checkers.emplace_back(Fn, Name, Desc, DocsUri);
+
+ // Record the presence of the checker in its packages.
+ StringRef packageName, leafName;
+ std::tie(packageName, leafName) = Name.rsplit(PackageSeparator);
+ while (!leafName.empty()) {
+ Packages[packageName] += 1;
+ std::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
+ }
+}
+
+void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
+ const AnalyzerOptions &Opts) const {
+ // Sort checkers for efficient collection.
+ llvm::sort(Checkers, checkerNameLT);
+
+ // Collect checkers enabled by the options.
+ CheckerInfoSet enabledCheckers = getEnabledCheckers(Opts);
+
+ // Initialize the CheckerManager with all enabled checkers.
+ for (const auto *i : enabledCheckers) {
+ checkerMgr.setCurrentCheckName(CheckName(i->FullName));
+ i->Initialize(checkerMgr);
+ }
+}
+
+void CheckerRegistry::validateCheckerOptions(
+ const AnalyzerOptions &opts) const {
+ for (const auto &config : opts.Config) {
+ size_t pos = config.getKey().find(':');
+ if (pos == StringRef::npos)
+ continue;
+
+ bool hasChecker = false;
+ StringRef checkerName = config.getKey().substr(0, pos);
+ for (const auto &checker : Checkers) {
+ if (checker.FullName.startswith(checkerName) &&
+ (checker.FullName.size() == pos || checker.FullName[pos] == '.')) {
+ hasChecker = true;
+ break;
+ }
+ }
+ if (!hasChecker)
+ Diags.Report(diag::err_unknown_analyzer_checker) << checkerName;
+ }
+}
+
+void CheckerRegistry::printHelp(raw_ostream &out,
+ size_t maxNameChars) const {
+ // FIXME: Alphabetical sort puts 'experimental' in the middle.
+ // Would it be better to name it '~experimental' or something else
+ // that's ASCIIbetically last?
+ llvm::sort(Checkers, checkerNameLT);
+
+ // FIXME: Print available packages.
+
+ out << "CHECKERS:\n";
+
+ // Find the maximum option length.
+ size_t optionFieldWidth = 0;
+ for (const auto &i : Checkers) {
+ // Limit the amount of padding we are willing to give up for alignment.
+ // Package.Name Description [Hidden]
+ size_t nameLength = i.FullName.size();
+ if (nameLength <= maxNameChars)
+ optionFieldWidth = std::max(optionFieldWidth, nameLength);
+ }
+
+ const size_t initialPad = 2;
+ for (const auto &i : Checkers) {
+ out.indent(initialPad) << i.FullName;
+
+ int pad = optionFieldWidth - i.FullName.size();
+
+ // Break on long option names.
+ if (pad < 0) {
+ out << '\n';
+ pad = optionFieldWidth + initialPad;
+ }
+ out.indent(pad + 2) << i.Desc;
+
+ out << '\n';
+ }
+}
+
+void CheckerRegistry::printList(raw_ostream &out,
+ const AnalyzerOptions &opts) const {
+ // Sort checkers for efficient collection.
+ llvm::sort(Checkers, checkerNameLT);
+
+ // Collect checkers enabled by the options.
+ CheckerInfoSet enabledCheckers = getEnabledCheckers(opts);
+
+ for (const auto *i : enabledCheckers)
+ out << i->FullName << '\n';
+}
diff --git a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index c43d30440c8f..b1927c8401d6 100644
--- a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -48,7 +48,7 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
FileID mainFileID = SM.getMainFileID();
AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
- llvm::StringRef modelPath = analyzerOpts->Config["model-path"];
+ llvm::StringRef modelPath = analyzerOpts->ModelPath;
llvm::SmallString<128> fileName;
diff --git a/lib/StaticAnalyzer/README.txt b/lib/StaticAnalyzer/README.txt
index d4310c57d849..79a16ec7673d 100644
--- a/lib/StaticAnalyzer/README.txt
+++ b/lib/StaticAnalyzer/README.txt
@@ -69,23 +69,23 @@ triggered the problem.
= Notes about C++ =
-Since now constructors are seen before the variable that is constructed
-in the CFG, we create a temporary object as the destination region that
+Since now constructors are seen before the variable that is constructed
+in the CFG, we create a temporary object as the destination region that
is constructed into. See ExprEngine::VisitCXXConstructExpr().
In ExprEngine::processCallExit(), we always bind the object region to the
evaluated CXXConstructExpr. Then in VisitDeclStmt(), we compute the
corresponding lazy compound value if the variable is not a reference, and
bind the variable region to the lazy compound value. If the variable
-is a reference, just use the object region as the initilizer value.
+is a reference, just use the object region as the initializer value.
Before entering a C++ method (or ctor/dtor), the 'this' region is bound
-to the object region. In ctors, we synthesize 'this' region with
+to the object region. In ctors, we synthesize 'this' region with
CXXRecordDecl*, which means we do not use type qualifiers. In methods, we
-synthesize 'this' region with CXXMethodDecl*, which has getThisType()
+synthesize 'this' region with CXXMethodDecl*, which has getThisType()
taking type qualifiers into account. It does not matter we use qualified
'this' region in one method and unqualified 'this' region in another
-method, because we only need to ensure the 'this' region is consistent
+method, because we only need to ensure the 'this' region is consistent
when we synthesize it and create it directly from CXXThisExpr in a single
method call.
diff --git a/lib/Tooling/ASTDiff/ASTDiff.cpp b/lib/Tooling/ASTDiff/ASTDiff.cpp
index a5d2d1d24729..592e8572c770 100644
--- a/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -741,7 +741,7 @@ public:
List.pop();
}
// TODO this is here to get a stable output, not a good heuristic
- llvm::sort(Result.begin(), Result.end());
+ llvm::sort(Result);
return Result;
}
int peekMax() const {
@@ -845,9 +845,8 @@ void ASTDiff::Impl::matchBottomUp(Mapping &M) const {
}
bool Matched = M.hasSrc(Id1);
const Node &N1 = T1.getNode(Id1);
- bool MatchedChildren =
- std::any_of(N1.Children.begin(), N1.Children.end(),
- [&](NodeId Child) { return M.hasSrc(Child); });
+ bool MatchedChildren = llvm::any_of(
+ N1.Children, [&](NodeId Child) { return M.hasSrc(Child); });
if (Matched || !MatchedChildren)
continue;
NodeId Id2 = findCandidate(M, Id1);
diff --git a/lib/Tooling/AllTUsExecution.cpp b/lib/Tooling/AllTUsExecution.cpp
index b761556ee76b..0f172b782963 100644
--- a/lib/Tooling/AllTUsExecution.cpp
+++ b/lib/Tooling/AllTUsExecution.cpp
@@ -53,6 +53,12 @@ private:
} // namespace
+llvm::cl::opt<std::string>
+ Filter("filter",
+ llvm::cl::desc("Only process files that match this filter. "
+ "This flag only applies to all-TUs."),
+ llvm::cl::init(".*"));
+
AllTUsToolExecutor::AllTUsToolExecutor(
const CompilationDatabase &Compilations, unsigned ThreadCount,
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
@@ -90,7 +96,12 @@ llvm::Error AllTUsToolExecutor::execute(
llvm::errs() << Msg.str() << "\n";
};
- auto Files = Compilations.getAllFiles();
+ std::vector<std::string> Files;
+ llvm::Regex RegexFilter(Filter);
+ for (const auto& File : Compilations.getAllFiles()) {
+ if (RegexFilter.match(File))
+ Files.push_back(File);
+ }
// Add a counter to track the progress.
const std::string TotalNumStr = std::to_string(Files.size());
unsigned Counter = 0;
@@ -104,7 +115,12 @@ llvm::Error AllTUsToolExecutor::execute(
{
llvm::ThreadPool Pool(ThreadCount == 0 ? llvm::hardware_concurrency()
: ThreadCount);
-
+ llvm::SmallString<128> InitialWorkingDir;
+ if (auto EC = llvm::sys::fs::current_path(InitialWorkingDir)) {
+ InitialWorkingDir = "";
+ llvm::errs() << "Error while getting current working directory: "
+ << EC.message() << "\n";
+ }
for (std::string File : Files) {
Pool.async(
[&](std::string Path) {
@@ -116,12 +132,21 @@ llvm::Error AllTUsToolExecutor::execute(
for (const auto &FileAndContent : OverlayFiles)
Tool.mapVirtualFile(FileAndContent.first(),
FileAndContent.second);
+ // Do not restore working dir from multiple threads to avoid races.
+ Tool.setRestoreWorkingDir(false);
if (Tool.run(Action.first.get()))
AppendError(llvm::Twine("Failed to run action on ") + Path +
"\n");
},
File);
}
+ // Make sure all tasks have finished before resetting the working directory.
+ Pool.wait();
+ if (!InitialWorkingDir.empty()) {
+ if (auto EC = llvm::sys::fs::set_current_path(InitialWorkingDir))
+ llvm::errs() << "Error while restoring working directory: "
+ << EC.message() << "\n";
+ }
}
if (!ErrorMsg.empty())
@@ -133,7 +158,8 @@ llvm::Error AllTUsToolExecutor::execute(
static llvm::cl::opt<unsigned> ExecutorConcurrency(
"execute-concurrency",
llvm::cl::desc("The number of threads used to process all files in "
- "parallel. Set to 0 for hardware concurrency."),
+ "parallel. Set to 0 for hardware concurrency. "
+ "This flag only applies to all-TUs."),
llvm::cl::init(0));
class AllTUsToolExecutorPlugin : public ToolExecutorPlugin {
diff --git a/lib/Tooling/CMakeLists.txt b/lib/Tooling/CMakeLists.txt
index 031d8b51dec4..4b671e299ab7 100644
--- a/lib/Tooling/CMakeLists.txt
+++ b/lib/Tooling/CMakeLists.txt
@@ -35,5 +35,6 @@ add_clang_library(clangTooling
clangFrontend
clangLex
clangRewrite
+ clangSerialization
clangToolingCore
)
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index 31a769fa21e5..cce8e1f1df24 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/lib/Tooling/CompilationDatabase.cpp
@@ -218,6 +218,25 @@ private:
ArrayRef<std::string> Arr;
};
+// Filter of tools unused flags such as -no-integrated-as and -Wa,*.
+// They are not used for syntax checking, and could confuse targets
+// which don't support these options.
+struct FilterUnusedFlags {
+ bool operator() (StringRef S) {
+ return (S == "-no-integrated-as") || S.startswith("-Wa,");
+ }
+};
+
+std::string GetClangToolCommand() {
+ static int Dummy;
+ std::string ClangExecutable =
+ llvm::sys::fs::getMainExecutable("clang", (void *)&Dummy);
+ SmallString<128> ClangToolPath;
+ ClangToolPath = llvm::sys::path::parent_path(ClangExecutable);
+ llvm::sys::path::append(ClangToolPath, "clang-tool");
+ return ClangToolPath.str();
+}
+
} // namespace
/// Strips any positional args and possible argv[0] from a command-line
@@ -257,9 +276,10 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
Diagnostics));
NewDriver->setCheckInputsExist(false);
- // This becomes the new argv[0]. The value is actually not important as it
- // isn't used for invoking Tools.
- Args.insert(Args.begin(), "clang-tool");
+ // This becomes the new argv[0]. The value is used to detect libc++ include
+ // dirs on Mac, it isn't used for other platforms.
+ std::string Argv0 = GetClangToolCommand();
+ Args.insert(Args.begin(), Argv0.c_str());
// By adding -c, we force the driver to treat compilation as the last phase.
// It will then issue warnings via Diagnostics about un-used options that
@@ -275,10 +295,7 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
// up with no jobs but then this is the user's fault.
Args.push_back("placeholder.cpp");
- // Remove -no-integrated-as; it's not used for syntax checking,
- // and it confuses targets which don't support this option.
- Args.erase(std::remove_if(Args.begin(), Args.end(),
- MatchesAny(std::string("-no-integrated-as"))),
+ Args.erase(std::remove_if(Args.begin(), Args.end(), FilterUnusedFlags()),
Args.end());
const std::unique_ptr<driver::Compilation> Compilation(
@@ -291,9 +308,11 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
CompileJobAnalyzer CompileAnalyzer;
for (const auto &Cmd : Jobs) {
- // Collect only for Assemble and Compile jobs. If we do all jobs we get
- // duplicates since Link jobs point to Assemble jobs as inputs.
+ // Collect only for Assemble, Backend, and Compile jobs. If we do all jobs
+ // we get duplicates since Link jobs point to Assemble jobs as inputs.
+ // -flto* flags make the BackendJobClass, which still needs analyzer.
if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass ||
+ Cmd.getSource().getKind() == driver::Action::BackendJobClass ||
Cmd.getSource().getKind() == driver::Action::CompileJobClass) {
CompileAnalyzer.run(&Cmd.getSource());
}
@@ -358,7 +377,7 @@ FixedCompilationDatabase::loadFromFile(StringRef Path, std::string &ErrorMsg) {
FixedCompilationDatabase::
FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
- std::vector<std::string> ToolCommandLine(1, "clang-tool");
+ std::vector<std::string> ToolCommandLine(1, GetClangToolCommand());
ToolCommandLine.insert(ToolCommandLine.end(),
CommandLine.begin(), CommandLine.end());
CompileCommands.emplace_back(Directory, StringRef(),
diff --git a/lib/Tooling/Core/Diagnostic.cpp b/lib/Tooling/Core/Diagnostic.cpp
index 9e4833f2eff4..e3a33d9a3755 100644
--- a/lib/Tooling/Core/Diagnostic.cpp
+++ b/lib/Tooling/Core/Diagnostic.cpp
@@ -23,10 +23,15 @@ DiagnosticMessage::DiagnosticMessage(llvm::StringRef Message)
DiagnosticMessage::DiagnosticMessage(llvm::StringRef Message,
const SourceManager &Sources,
SourceLocation Loc)
- : Message(Message) {
+ : Message(Message), FileOffset(0) {
assert(Loc.isValid() && Loc.isFileID());
FilePath = Sources.getFilename(Loc);
- FileOffset = Sources.getFileOffset(Loc);
+
+ // Don't store offset in the scratch space. It doesn't tell anything to the
+ // user. Moreover, it depends on the history of macro expansions and thus
+ // prevents deduplication of warnings in headers.
+ if (!FilePath.empty())
+ FileOffset = Sources.getFileOffset(Loc);
}
Diagnostic::Diagnostic(llvm::StringRef DiagnosticName,
diff --git a/lib/Tooling/Core/Lookup.cpp b/lib/Tooling/Core/Lookup.cpp
index 6edf61b8050d..cc448d144e2c 100644
--- a/lib/Tooling/Core/Lookup.cpp
+++ b/lib/Tooling/Core/Lookup.cpp
@@ -14,6 +14,7 @@
#include "clang/Tooling/Core/Lookup.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
using namespace clang;
using namespace clang::tooling;
@@ -114,6 +115,37 @@ static bool isFullyQualified(const NestedNameSpecifier *NNS) {
return false;
}
+// Returns true if spelling symbol \p QName as \p Spelling in \p UseContext is
+// ambiguous. For example, if QName is "::y::bar" and the spelling is "y::bar"
+// in `UseContext` "a" that contains a nested namespace "a::y", then "y::bar"
+// can be resolved to ::a::y::bar, which can cause compile error.
+// FIXME: consider using namespaces.
+static bool isAmbiguousNameInScope(StringRef Spelling, StringRef QName,
+ const DeclContext &UseContext) {
+ assert(QName.startswith("::"));
+ if (Spelling.startswith("::"))
+ return false;
+
+ // Lookup the first component of Spelling in all enclosing namespaces and
+ // check if there is any existing symbols with the same name but in different
+ // scope.
+ StringRef Head = Spelling.split("::").first;
+
+ llvm::SmallVector<const NamespaceDecl *, 4> UseNamespaces =
+ getAllNamedNamespaces(&UseContext);
+ auto &AST = UseContext.getParentASTContext();
+ StringRef TrimmedQName = QName.substr(2);
+ for (const auto *NS : UseNamespaces) {
+ auto LookupRes = NS->lookup(DeclarationName(&AST.Idents.get(Head)));
+ if (!LookupRes.empty()) {
+ for (const NamedDecl *Res : LookupRes)
+ if (!TrimmedQName.startswith(Res->getQualifiedNameAsString()))
+ return true;
+ }
+ }
+ return false;
+}
+
std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
const DeclContext *UseContext,
const NamedDecl *FromDecl,
@@ -146,6 +178,14 @@ std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
// figure out how good a namespace match we have with our destination type.
// We work backwards (from most specific possible namespace to least
// specific).
- return getBestNamespaceSubstr(UseContext, ReplacementString,
- isFullyQualified(Use));
+ StringRef Suggested = getBestNamespaceSubstr(UseContext, ReplacementString,
+ isFullyQualified(Use));
+ // Use the fully qualified name if the suggested name is ambiguous.
+ // FIXME: consider re-shortening the name until the name is not ambiguous. We
+ // are not doing this because ambiguity is pretty bad and we should not try to
+ // be clever in handling such cases. Making this noticeable to users seems to
+ // be a better option.
+ return isAmbiguousNameInScope(Suggested, ReplacementString, *UseContext)
+ ? ReplacementString
+ : Suggested;
}
diff --git a/lib/Tooling/Core/Replacement.cpp b/lib/Tooling/Core/Replacement.cpp
index 67e2dcfd73c1..3b7e39814afa 100644
--- a/lib/Tooling/Core/Replacement.cpp
+++ b/lib/Tooling/Core/Replacement.cpp
@@ -19,7 +19,6 @@
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "clang/Rewrite/Core/Rewriter.h"
@@ -29,6 +28,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -483,12 +483,11 @@ Replacements Replacements::merge(const Replacements &ReplacesToMerge) const {
// Returns a set of non-overlapping and sorted ranges that is equivalent to
// \p Ranges.
static std::vector<Range> combineAndSortRanges(std::vector<Range> Ranges) {
- llvm::sort(Ranges.begin(), Ranges.end(),
- [](const Range &LHS, const Range &RHS) {
- if (LHS.getOffset() != RHS.getOffset())
- return LHS.getOffset() < RHS.getOffset();
- return LHS.getLength() < RHS.getLength();
- });
+ llvm::sort(Ranges, [](const Range &LHS, const Range &RHS) {
+ if (LHS.getOffset() != RHS.getOffset())
+ return LHS.getOffset() < RHS.getOffset();
+ return LHS.getLength() < RHS.getLength();
+ });
std::vector<Range> Result;
for (const auto &R : Ranges) {
if (Result.empty() ||
@@ -584,8 +583,8 @@ llvm::Expected<std::string> applyAllReplacements(StringRef Code,
if (Replaces.empty())
return Code.str();
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
diff --git a/lib/Tooling/Execution.cpp b/lib/Tooling/Execution.cpp
index 7ae67747acb2..9ddb18a57b46 100644
--- a/lib/Tooling/Execution.cpp
+++ b/lib/Tooling/Execution.cpp
@@ -16,7 +16,7 @@ LLVM_INSTANTIATE_REGISTRY(clang::tooling::ToolExecutorPluginRegistry)
namespace clang {
namespace tooling {
-static llvm::cl::opt<std::string>
+llvm::cl::opt<std::string>
ExecutorName("executor", llvm::cl::desc("The name of the executor to use."),
llvm::cl::init("standalone"));
diff --git a/lib/Tooling/Inclusions/HeaderIncludes.cpp b/lib/Tooling/Inclusions/HeaderIncludes.cpp
index 99c0866a6855..c74ad0b9cd56 100644
--- a/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ b/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -10,6 +10,7 @@
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/Support/FormatVariadic.h"
namespace clang {
namespace tooling {
@@ -23,8 +24,7 @@ LangOptions createLangOpts() {
LangOpts.LineComment = 1;
LangOpts.CXXOperatorNames = 1;
LangOpts.Bool = 1;
- LangOpts.ObjC1 = 1;
- LangOpts.ObjC2 = 1;
+ LangOpts.ObjC = 1;
LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
LangOpts.DeclSpecKeyword = 1; // To get __declspec.
LangOpts.WChar = 1; // To get wchar_t
@@ -181,7 +181,7 @@ bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
if (FileStem.startswith(HeaderStem) ||
FileStem.startswith_lower(HeaderStem)) {
- llvm::Regex MainIncludeRegex((HeaderStem + Style.IncludeIsMainRegex).str(),
+ llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
llvm::Regex::IgnoreCase);
if (MainIncludeRegex.match(FileStem))
return true;
@@ -275,8 +275,8 @@ HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
(!IsAngled && StringRef(Inc.Name).startswith("\"")))
return llvm::None;
- std::string Quoted = IsAngled ? ("<" + IncludeName + ">").str()
- : ("\"" + IncludeName + "\"").str();
+ std::string Quoted =
+ llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName);
StringRef QuotedName = Quoted;
int Priority = Categories.getIncludePriority(
QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
@@ -293,7 +293,7 @@ HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
}
}
assert(InsertOffset <= Code.size());
- std::string NewInclude = ("#include " + QuotedName + "\n").str();
+ std::string NewInclude = llvm::formatv("#include {0}\n", QuotedName);
// When inserting headers at end of the code, also append '\n' to the code
// if it does not end with '\n'.
// FIXME: when inserting multiple #includes at the end of code, only one
diff --git a/lib/Tooling/InterpolatingCompilationDatabase.cpp b/lib/Tooling/InterpolatingCompilationDatabase.cpp
index bc564584bd01..4d0d84f660a2 100644
--- a/lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ b/lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -48,6 +48,7 @@
#include "clang/Frontend/LangStandard.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
@@ -123,55 +124,79 @@ static types::ID foldType(types::ID Lang) {
struct TransferableCommand {
// Flags that should not apply to all files are stripped from CommandLine.
CompileCommand Cmd;
- // Language detected from -x or the filename.
- types::ID Type = types::TY_INVALID;
+ // Language detected from -x or the filename. Never TY_INVALID.
+ Optional<types::ID> Type;
// Standard specified by -std.
LangStandard::Kind Std = LangStandard::lang_unspecified;
+ // Whether the command line is for the cl-compatible driver.
+ bool ClangCLMode;
TransferableCommand(CompileCommand C)
- : Cmd(std::move(C)), Type(guessType(Cmd.Filename)) {
- std::vector<std::string> NewArgs = {Cmd.CommandLine.front()};
+ : Cmd(std::move(C)), Type(guessType(Cmd.Filename)),
+ ClangCLMode(checkIsCLMode(Cmd.CommandLine)) {
+ std::vector<std::string> OldArgs = std::move(Cmd.CommandLine);
+ Cmd.CommandLine.clear();
+
+ // Wrap the old arguments in an InputArgList.
+ llvm::opt::InputArgList ArgList;
+ {
+ SmallVector<const char *, 16> TmpArgv;
+ for (const std::string &S : OldArgs)
+ TmpArgv.push_back(S.c_str());
+ ArgList = {TmpArgv.begin(), TmpArgv.end()};
+ }
+
// Parse the old args in order to strip out and record unwanted flags.
+ // We parse each argument individually so that we can retain the exact
+ // spelling of each argument; re-rendering is lossy for aliased flags.
+ // E.g. in CL mode, /W4 maps to -Wall.
auto OptTable = clang::driver::createDriverOptTable();
- std::vector<const char *> Argv;
- for (unsigned I = 1; I < Cmd.CommandLine.size(); ++I)
- Argv.push_back(Cmd.CommandLine[I].c_str());
- unsigned MissingI, MissingC;
- auto ArgList = OptTable->ParseArgs(Argv, MissingI, MissingC);
- for (const auto *Arg : ArgList) {
- const auto &option = Arg->getOption();
+ Cmd.CommandLine.emplace_back(OldArgs.front());
+ for (unsigned Pos = 1; Pos < OldArgs.size();) {
+ using namespace driver::options;
+
+ const unsigned OldPos = Pos;
+ std::unique_ptr<llvm::opt::Arg> Arg(OptTable->ParseOneArg(
+ ArgList, Pos,
+ /* Include */ClangCLMode ? CoreOption | CLOption : 0,
+ /* Exclude */ClangCLMode ? 0 : CLOption));
+
+ if (!Arg)
+ continue;
+
+ const llvm::opt::Option &Opt = Arg->getOption();
+
// Strip input and output files.
- if (option.matches(clang::driver::options::OPT_INPUT) ||
- option.matches(clang::driver::options::OPT_o)) {
+ if (Opt.matches(OPT_INPUT) || Opt.matches(OPT_o) ||
+ (ClangCLMode && (Opt.matches(OPT__SLASH_Fa) ||
+ Opt.matches(OPT__SLASH_Fe) ||
+ Opt.matches(OPT__SLASH_Fi) ||
+ Opt.matches(OPT__SLASH_Fo))))
continue;
- }
+
// Strip -x, but record the overridden language.
- if (option.matches(clang::driver::options::OPT_x)) {
- for (const char *Value : Arg->getValues())
- Type = types::lookupTypeForTypeSpecifier(Value);
+ if (const auto GivenType = tryParseTypeArg(*Arg)) {
+ Type = *GivenType;
continue;
}
- // Strip --std, but record the value.
- if (option.matches(clang::driver::options::OPT_std_EQ)) {
- for (const char *Value : Arg->getValues()) {
- Std = llvm::StringSwitch<LangStandard::Kind>(Value)
-#define LANGSTANDARD(id, name, lang, desc, features) \
- .Case(name, LangStandard::lang_##id)
-#define LANGSTANDARD_ALIAS(id, alias) .Case(alias, LangStandard::lang_##id)
-#include "clang/Frontend/LangStandards.def"
- .Default(Std);
- }
+
+ // Strip -std, but record the value.
+ if (const auto GivenStd = tryParseStdArg(*Arg)) {
+ if (*GivenStd != LangStandard::lang_unspecified)
+ Std = *GivenStd;
continue;
}
- llvm::opt::ArgStringList ArgStrs;
- Arg->render(ArgList, ArgStrs);
- NewArgs.insert(NewArgs.end(), ArgStrs.begin(), ArgStrs.end());
+
+ Cmd.CommandLine.insert(Cmd.CommandLine.end(),
+ OldArgs.data() + OldPos, OldArgs.data() + Pos);
}
- Cmd.CommandLine = std::move(NewArgs);
if (Std != LangStandard::lang_unspecified) // -std take precedence over -x
Type = toType(LangStandard::getLangStandardForKind(Std).getLanguage());
- Type = foldType(Type);
+ Type = foldType(*Type);
+ // The contract is to store None instead of TY_INVALID.
+ if (Type == types::TY_INVALID)
+ Type = llvm::None;
}
// Produce a CompileCommand for \p filename, based on this one.
@@ -181,25 +206,43 @@ struct TransferableCommand {
bool TypeCertain;
auto TargetType = guessType(Filename, &TypeCertain);
// If the filename doesn't determine the language (.h), transfer with -x.
- if (!TypeCertain) {
+ if (TargetType != types::TY_INVALID && !TypeCertain && Type) {
TargetType = types::onlyPrecompileType(TargetType) // header?
- ? types::lookupHeaderTypeForSourceType(Type)
- : Type;
- Result.CommandLine.push_back("-x");
- Result.CommandLine.push_back(types::getTypeName(TargetType));
+ ? types::lookupHeaderTypeForSourceType(*Type)
+ : *Type;
+ if (ClangCLMode) {
+ const StringRef Flag = toCLFlag(TargetType);
+ if (!Flag.empty())
+ Result.CommandLine.push_back(Flag);
+ } else {
+ Result.CommandLine.push_back("-x");
+ Result.CommandLine.push_back(types::getTypeName(TargetType));
+ }
}
// --std flag may only be transferred if the language is the same.
// We may consider "translating" these, e.g. c++11 -> c11.
if (Std != LangStandard::lang_unspecified && foldType(TargetType) == Type) {
- Result.CommandLine.push_back(
- "-std=" +
- std::string(LangStandard::getLangStandardForKind(Std).getName()));
+ Result.CommandLine.emplace_back((
+ llvm::Twine(ClangCLMode ? "/std:" : "-std=") +
+ LangStandard::getLangStandardForKind(Std).getName()).str());
}
Result.CommandLine.push_back(Filename);
return Result;
}
private:
+ // Determine whether the given command line is intended for the CL driver.
+ static bool checkIsCLMode(ArrayRef<std::string> CmdLine) {
+ // First look for --driver-mode.
+ for (StringRef S : llvm::reverse(CmdLine)) {
+ if (S.consume_front("--driver-mode="))
+ return S == "cl";
+ }
+
+ // Otherwise just check the clang executable file name.
+ return llvm::sys::path::stem(CmdLine.front()).endswith_lower("cl");
+ }
+
// Map the language from the --std flag to that of the -x flag.
static types::ID toType(InputKind::Language Lang) {
switch (Lang) {
@@ -215,64 +258,111 @@ private:
return types::TY_INVALID;
}
}
+
+ // Convert a file type to the matching CL-style type flag.
+ static StringRef toCLFlag(types::ID Type) {
+ switch (Type) {
+ case types::TY_C:
+ case types::TY_CHeader:
+ return "/TC";
+ case types::TY_CXX:
+ case types::TY_CXXHeader:
+ return "/TP";
+ default:
+ return StringRef();
+ }
+ }
+
+ // Try to interpret the argument as a type specifier, e.g. '-x'.
+ Optional<types::ID> tryParseTypeArg(const llvm::opt::Arg &Arg) {
+ const llvm::opt::Option &Opt = Arg.getOption();
+ using namespace driver::options;
+ if (ClangCLMode) {
+ if (Opt.matches(OPT__SLASH_TC) || Opt.matches(OPT__SLASH_Tc))
+ return types::TY_C;
+ if (Opt.matches(OPT__SLASH_TP) || Opt.matches(OPT__SLASH_Tp))
+ return types::TY_CXX;
+ } else {
+ if (Opt.matches(driver::options::OPT_x))
+ return types::lookupTypeForTypeSpecifier(Arg.getValue());
+ }
+ return None;
+ }
+
+ // Try to interpret the argument as '-std='.
+ Optional<LangStandard::Kind> tryParseStdArg(const llvm::opt::Arg &Arg) {
+ using namespace driver::options;
+ if (Arg.getOption().matches(ClangCLMode ? OPT__SLASH_std : OPT_std_EQ)) {
+ return llvm::StringSwitch<LangStandard::Kind>(Arg.getValue())
+#define LANGSTANDARD(id, name, lang, ...) .Case(name, LangStandard::lang_##id)
+#define LANGSTANDARD_ALIAS(id, alias) .Case(alias, LangStandard::lang_##id)
+#include "clang/Frontend/LangStandards.def"
+#undef LANGSTANDARD_ALIAS
+#undef LANGSTANDARD
+ .Default(LangStandard::lang_unspecified);
+ }
+ return None;
+ }
};
-// CommandIndex does the real work: given a filename, it produces the best
-// matching TransferableCommand by matching filenames. Basic strategy:
+// Given a filename, FileIndex picks the best matching file from the underlying
+// DB. This is the proxy file whose CompileCommand will be reused. The
+// heuristics incorporate file name, extension, and directory structure.
+// Strategy:
// - Build indexes of each of the substrings we want to look up by.
// These indexes are just sorted lists of the substrings.
-// - Forward requests to the inner CDB. If it fails, we must pick a proxy.
// - Each criterion corresponds to a range lookup into the index, so we only
// need O(log N) string comparisons to determine scores.
-// - We then break ties among the candidates with the highest score.
-class CommandIndex {
+//
+// Apart from path proximity signals, also takes file extensions into account
+// when scoring the candidates.
+class FileIndex {
public:
- CommandIndex(std::vector<TransferableCommand> AllCommands)
- : Commands(std::move(AllCommands)), Strings(Arena) {
+ FileIndex(std::vector<std::string> Files)
+ : OriginalPaths(std::move(Files)), Strings(Arena) {
// Sort commands by filename for determinism (index is a tiebreaker later).
- llvm::sort(
- Commands.begin(), Commands.end(),
- [](const TransferableCommand &Left, const TransferableCommand &Right) {
- return Left.Cmd.Filename < Right.Cmd.Filename;
- });
- for (size_t I = 0; I < Commands.size(); ++I) {
- StringRef Path =
- Strings.save(StringRef(Commands[I].Cmd.Filename).lower());
- Paths.push_back({Path, I});
+ llvm::sort(OriginalPaths);
+ Paths.reserve(OriginalPaths.size());
+ Types.reserve(OriginalPaths.size());
+ Stems.reserve(OriginalPaths.size());
+ for (size_t I = 0; I < OriginalPaths.size(); ++I) {
+ StringRef Path = Strings.save(StringRef(OriginalPaths[I]).lower());
+
+ Paths.emplace_back(Path, I);
+ Types.push_back(foldType(guessType(Path)));
Stems.emplace_back(sys::path::stem(Path), I);
auto Dir = ++sys::path::rbegin(Path), DirEnd = sys::path::rend(Path);
for (int J = 0; J < DirectorySegmentsIndexed && Dir != DirEnd; ++J, ++Dir)
if (Dir->size() > ShortDirectorySegment) // not trivial ones
Components.emplace_back(*Dir, I);
}
- llvm::sort(Paths.begin(), Paths.end());
- llvm::sort(Stems.begin(), Stems.end());
- llvm::sort(Components.begin(), Components.end());
+ llvm::sort(Paths);
+ llvm::sort(Stems);
+ llvm::sort(Components);
}
- bool empty() const { return Commands.empty(); }
+ bool empty() const { return Paths.empty(); }
- // Returns the command that best fits OriginalFilename.
- // Candidates with PreferLanguage will be chosen over others (unless it's
- // TY_INVALID, or all candidates are bad).
- const TransferableCommand &chooseProxy(StringRef OriginalFilename,
- types::ID PreferLanguage) const {
+ // Returns the path for the file that best fits OriginalFilename.
+ // Candidates with extensions matching PreferLanguage will be chosen over
+ // others (unless it's TY_INVALID, or all candidates are bad).
+ StringRef chooseProxy(StringRef OriginalFilename,
+ types::ID PreferLanguage) const {
assert(!empty() && "need at least one candidate!");
std::string Filename = OriginalFilename.lower();
auto Candidates = scoreCandidates(Filename);
std::pair<size_t, int> Best =
pickWinner(Candidates, Filename, PreferLanguage);
- DEBUG_WITH_TYPE("interpolate",
- llvm::dbgs()
- << "interpolate: chose "
- << Commands[Best.first].Cmd.Filename << " as proxy for "
- << OriginalFilename << " preferring "
- << (PreferLanguage == types::TY_INVALID
- ? "none"
- : types::getTypeName(PreferLanguage))
- << " score=" << Best.second << "\n");
- return Commands[Best.first];
+ DEBUG_WITH_TYPE(
+ "interpolate",
+ llvm::dbgs() << "interpolate: chose " << OriginalPaths[Best.first]
+ << " as proxy for " << OriginalFilename << " preferring "
+ << (PreferLanguage == types::TY_INVALID
+ ? "none"
+ : types::getTypeName(PreferLanguage))
+ << " score=" << Best.second << "\n");
+ return OriginalPaths[Best.first];
}
private:
@@ -338,7 +428,7 @@ private:
ScoredCandidate S;
S.Index = Candidate.first;
S.Preferred = PreferredLanguage == types::TY_INVALID ||
- PreferredLanguage == Commands[S.Index].Type;
+ PreferredLanguage == Types[S.Index];
S.Points = Candidate.second;
if (!S.Preferred && Best.Preferred)
continue;
@@ -371,7 +461,7 @@ private:
// If Prefix is true, it's instead the range starting with Key.
template <bool Prefix>
ArrayRef<SubstringAndIndex>
- indexLookup(StringRef Key, const std::vector<SubstringAndIndex> &Idx) const {
+ indexLookup(StringRef Key, ArrayRef<SubstringAndIndex> Idx) const {
// Use pointers as iteratiors to ease conversion of result to ArrayRef.
auto Range = std::equal_range(Idx.data(), Idx.data() + Idx.size(), Key,
Less<Prefix>());
@@ -379,8 +469,8 @@ private:
}
// Performs a point lookup into a nonempty index, returning a longest match.
- SubstringAndIndex
- longestMatch(StringRef Key, const std::vector<SubstringAndIndex> &Idx) const {
+ SubstringAndIndex longestMatch(StringRef Key,
+ ArrayRef<SubstringAndIndex> Idx) const {
assert(!Idx.empty());
// Longest substring match will be adjacent to a direct lookup.
auto It =
@@ -395,22 +485,27 @@ private:
return Prefix > PrevPrefix ? *It : *--It;
}
- std::vector<TransferableCommand> Commands; // Indexes point into this.
+ // Original paths, everything else is in lowercase.
+ std::vector<std::string> OriginalPaths;
BumpPtrAllocator Arena;
StringSaver Strings;
// Indexes of candidates by certain substrings.
// String is lowercase and sorted, index points into OriginalPaths.
std::vector<SubstringAndIndex> Paths; // Full path.
+ // Lang types obtained by guessing on the corresponding path. I-th element is
+ // a type for the I-th path.
+ std::vector<types::ID> Types;
std::vector<SubstringAndIndex> Stems; // Basename, without extension.
std::vector<SubstringAndIndex> Components; // Last path components.
};
// The actual CompilationDatabase wrapper delegates to its inner database.
-// If no match, looks up a command in CommandIndex and transfers it to the file.
+// If no match, looks up a proxy file in FileIndex and transfers its
+// command to the requested file.
class InterpolatingCompilationDatabase : public CompilationDatabase {
public:
InterpolatingCompilationDatabase(std::unique_ptr<CompilationDatabase> Inner)
- : Inner(std::move(Inner)), Index(allCommands()) {}
+ : Inner(std::move(Inner)), Index(this->Inner->getAllFiles()) {}
std::vector<CompileCommand>
getCompileCommands(StringRef Filename) const override {
@@ -421,7 +516,11 @@ public:
auto Lang = guessType(Filename, &TypeCertain);
if (!TypeCertain)
Lang = types::TY_INVALID;
- return {Index.chooseProxy(Filename, foldType(Lang)).transferTo(Filename)};
+ auto ProxyCommands =
+ Inner->getCompileCommands(Index.chooseProxy(Filename, foldType(Lang)));
+ if (ProxyCommands.empty())
+ return {};
+ return {TransferableCommand(ProxyCommands[0]).transferTo(Filename)};
}
std::vector<std::string> getAllFiles() const override {
@@ -433,18 +532,8 @@ public:
}
private:
- std::vector<TransferableCommand> allCommands() {
- std::vector<TransferableCommand> Result;
- for (auto Command : Inner->getAllCompileCommands()) {
- Result.emplace_back(std::move(Command));
- if (Result.back().Type == types::TY_INVALID)
- Result.pop_back();
- }
- return Result;
- }
-
std::unique_ptr<CompilationDatabase> Inner;
- CommandIndex Index;
+ FileIndex Index;
};
} // namespace
diff --git a/lib/Tooling/JSONCompilationDatabase.cpp b/lib/Tooling/JSONCompilationDatabase.cpp
index 2fa5fce279d6..b0feaa229c11 100644
--- a/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/lib/Tooling/JSONCompilationDatabase.cpp
@@ -157,13 +157,16 @@ std::vector<std::string> unescapeCommandLine(JSONCommandLineSyntax Syntax,
return parser.parse();
}
+// This plugin locates a nearby compile_command.json file, and also infers
+// compile commands for files not present in the database.
class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin {
std::unique_ptr<CompilationDatabase>
loadFromDirectory(StringRef Directory, std::string &ErrorMessage) override {
SmallString<1024> JSONDatabasePath(Directory);
llvm::sys::path::append(JSONDatabasePath, "compile_commands.json");
- return JSONCompilationDatabase::loadFromFile(
+ auto Base = JSONCompilationDatabase::loadFromFile(
JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect);
+ return Base ? inferMissingCompileCommands(std::move(Base)) : nullptr;
}
};
diff --git a/lib/Tooling/Refactoring/ASTSelection.cpp b/lib/Tooling/Refactoring/ASTSelection.cpp
index 7123fc32cec9..b8f996d8218c 100644
--- a/lib/Tooling/Refactoring/ASTSelection.cpp
+++ b/lib/Tooling/Refactoring/ASTSelection.cpp
@@ -250,8 +250,6 @@ static bool hasAnyDirectChildrenWithKind(const SelectedASTNode &Node,
namespace {
struct SelectedNodeWithParents {
- SelectedNodeWithParents(SelectedNodeWithParents &&) = default;
- SelectedNodeWithParents &operator=(SelectedNodeWithParents &&) = default;
SelectedASTNode::ReferenceType Node;
llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents;
diff --git a/lib/Tooling/Refactoring/Extract/Extract.cpp b/lib/Tooling/Refactoring/Extract/Extract.cpp
index a12454cd29ef..7a741bdb2e91 100644
--- a/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ b/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -52,7 +52,7 @@ SourceLocation computeFunctionExtractionLocation(const Decl *D) {
while (const auto *RD = dyn_cast<CXXRecordDecl>(D->getLexicalDeclContext()))
D = RD;
}
- return D->getLocStart();
+ return D->getBeginLoc();
}
} // end anonymous namespace
@@ -102,8 +102,8 @@ ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) {
assert(ParentDecl && "missing parent");
// Compute the source range of the code that should be extracted.
- SourceRange ExtractedRange(Code[0]->getLocStart(),
- Code[Code.size() - 1]->getLocEnd());
+ SourceRange ExtractedRange(Code[0]->getBeginLoc(),
+ Code[Code.size() - 1]->getEndLoc());
// FIXME (Alex L): Add code that accounts for macro locations.
ASTContext &AST = Context.getASTContext();
diff --git a/lib/Tooling/Refactoring/Rename/USRFinder.cpp b/lib/Tooling/Refactoring/Rename/USRFinder.cpp
index 63f536c72a6f..4ed805fd504c 100644
--- a/lib/Tooling/Refactoring/Rename/USRFinder.cpp
+++ b/lib/Tooling/Refactoring/Rename/USRFinder.cpp
@@ -83,8 +83,8 @@ const NamedDecl *getNamedDeclAt(const ASTContext &Context,
// see. If both start and end is either before or after the point we're
// looking for the point cannot be inside of this decl. Don't even look at it.
for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
- SourceLocation StartLoc = CurrDecl->getLocStart();
- SourceLocation EndLoc = CurrDecl->getLocEnd();
+ SourceLocation StartLoc = CurrDecl->getBeginLoc();
+ SourceLocation EndLoc = CurrDecl->getEndLoc();
if (StartLoc.isValid() && EndLoc.isValid() &&
SM.isBeforeInTranslationUnit(StartLoc, Point) !=
SM.isBeforeInTranslationUnit(EndLoc, Point))
diff --git a/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index fb06b91118b0..7f60cf54c8ec 100644
--- a/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -117,7 +117,7 @@ SourceLocation StartLocationForType(TypeLoc TL) {
return NestedNameSpecifier.getBeginLoc();
TL = TL.getNextTypeLoc();
}
- return TL.getLocStart();
+ return TL.getBeginLoc();
}
SourceLocation EndLocationForType(TypeLoc TL) {
@@ -255,12 +255,12 @@ public:
Decl = UsingShadow->getTargetDecl();
}
- auto StartLoc = Expr->getLocStart();
+ auto StartLoc = Expr->getBeginLoc();
// For template function call expressions like `foo<int>()`, we want to
// restrict the end of location to just before the `<` character.
SourceLocation EndLoc = Expr->hasExplicitTemplateArgs()
? Expr->getLAngleLoc().getLocWithOffset(-1)
- : Expr->getLocEnd();
+ : Expr->getEndLoc();
if (const auto *MD = llvm::dyn_cast<CXXMethodDecl>(Decl)) {
if (isInUSRSet(MD)) {
@@ -576,7 +576,7 @@ createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
// Hanlde using declarations explicitly as "using a::Foo" don't trigger
// typeLoc for "a::Foo".
for (const auto *Using : Finder.getUsingDecls())
- Replace(Using->getLocStart(), Using->getLocEnd(), "using " + NewName.str());
+ Replace(Using->getBeginLoc(), Using->getEndLoc(), "using " + NewName.str());
return AtomicChanges;
}
diff --git a/lib/Tooling/StandaloneExecution.cpp b/lib/Tooling/StandaloneExecution.cpp
index 7312baf9dc77..1daf792fb86f 100644
--- a/lib/Tooling/StandaloneExecution.cpp
+++ b/lib/Tooling/StandaloneExecution.cpp
@@ -30,7 +30,7 @@ static ArgumentsAdjuster getDefaultArgumentsAdjusters() {
StandaloneToolExecutor::StandaloneToolExecutor(
const CompilationDatabase &Compilations,
llvm::ArrayRef<std::string> SourcePaths,
- IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: Tool(Compilations, SourcePaths, std::move(PCHContainerOps),
std::move(BaseFS)),
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index a106154f4b28..63aa64a5330d 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -19,7 +19,6 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Job.h"
@@ -51,6 +50,7 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstring>
@@ -74,9 +74,9 @@ FrontendActionFactory::~FrontendActionFactory() = default;
// it to be based on the same framework.
/// Builds a clang driver initialized for running clang tools.
-static driver::Driver *newDriver(
- DiagnosticsEngine *Diagnostics, const char *BinaryName,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+static driver::Driver *
+newDriver(DiagnosticsEngine *Diagnostics, const char *BinaryName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
driver::Driver *CompilerDriver =
new driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(),
*Diagnostics, std::move(VFS));
@@ -155,7 +155,7 @@ namespace tooling {
bool runToolOnCodeWithArgs(
FrontendAction *ToolAction, const Twine &Code,
- llvm::IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const std::vector<std::string> &Args, const Twine &FileName,
const Twine &ToolName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
@@ -178,10 +178,10 @@ bool runToolOnCodeWithArgs(
const Twine &ToolName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const FileContentMappings &VirtualMappedFiles) {
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
+ new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
SmallString<1024> CodeStorage;
@@ -199,7 +199,8 @@ bool runToolOnCodeWithArgs(
FileName, ToolName);
}
-std::string getAbsolutePath(StringRef File) {
+llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS,
+ StringRef File) {
StringRef RelativePath(File);
// FIXME: Should '.\\' be accepted on Win32?
if (RelativePath.startswith("./")) {
@@ -207,13 +208,16 @@ std::string getAbsolutePath(StringRef File) {
}
SmallString<1024> AbsolutePath = RelativePath;
- std::error_code EC = llvm::sys::fs::make_absolute(AbsolutePath);
- assert(!EC);
- (void)EC;
+ if (auto EC = FS.makeAbsolute(AbsolutePath))
+ return llvm::errorCodeToError(EC);
llvm::sys::path::native(AbsolutePath);
return AbsolutePath.str();
}
+std::string getAbsolutePath(StringRef File) {
+ return llvm::cantFail(getAbsolutePath(*llvm::vfs::getRealFileSystem(), File));
+}
+
void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
StringRef InvokedAs) {
if (!CommandLine.empty() && !InvokedAs.empty()) {
@@ -299,8 +303,12 @@ bool ToolInvocation::run() {
const std::unique_ptr<driver::Driver> Driver(
newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem()));
- // Since the input might only be virtual, don't check whether it exists.
- Driver->setCheckInputsExist(false);
+ // The "input file not found" diagnostics from the driver are useful.
+ // The driver is only aware of the VFS working directory, but some clients
+ // change this at the FileManager level instead.
+ // In this case the checks have false positives, so skip them.
+ if (!Files->getFileSystemOpts().WorkingDir.empty())
+ Driver->setCheckInputsExist(false);
const std::unique_ptr<driver::Compilation> Compilation(
Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
if (!Compilation)
@@ -361,18 +369,18 @@ bool FrontendActionFactory::runInvocation(
const bool Success = Compiler.ExecuteAction(*ScopedToolAction);
- Files->clearStatCaches();
+ Files->clearStatCache();
return Success;
}
ClangTool::ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- IntrusiveRefCntPtr<vfs::FileSystem> BaseFS)
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS)
: Compilations(Compilations), SourcePaths(SourcePaths),
PCHContainerOps(std::move(PCHContainerOps)),
- OverlayFileSystem(new vfs::OverlayFileSystem(std::move(BaseFS))),
- InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))),
+ InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) {
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
appendArgumentsAdjuster(getClangStripOutputAdjuster());
@@ -411,15 +419,6 @@ int ClangTool::run(ToolAction *Action) {
// This just needs to be some symbol in the binary.
static int StaticSymbol;
- std::string InitialDirectory;
- if (llvm::ErrorOr<std::string> CWD =
- OverlayFileSystem->getCurrentWorkingDirectory()) {
- InitialDirectory = std::move(*CWD);
- } else {
- llvm::report_fatal_error("Cannot detect current path: " +
- Twine(CWD.getError().message()));
- }
-
// First insert all absolute paths into the in-memory VFS. These are global
// for all compile commands.
if (SeenWorkingDirectories.insert("/").second)
@@ -431,9 +430,33 @@ int ClangTool::run(ToolAction *Action) {
bool ProcessingFailed = false;
bool FileSkipped = false;
+ // Compute all absolute paths before we run any actions, as those will change
+ // the working directory.
+ std::vector<std::string> AbsolutePaths;
+ AbsolutePaths.reserve(SourcePaths.size());
for (const auto &SourcePath : SourcePaths) {
- std::string File(getAbsolutePath(SourcePath));
+ auto AbsPath = getAbsolutePath(*OverlayFileSystem, SourcePath);
+ if (!AbsPath) {
+ llvm::errs() << "Skipping " << SourcePath
+ << ". Error while getting an absolute path: "
+ << llvm::toString(AbsPath.takeError()) << "\n";
+ continue;
+ }
+ AbsolutePaths.push_back(std::move(*AbsPath));
+ }
+
+ // Remember the working directory in case we need to restore it.
+ std::string InitialWorkingDir;
+ if (RestoreCWD) {
+ if (auto CWD = OverlayFileSystem->getCurrentWorkingDirectory()) {
+ InitialWorkingDir = std::move(*CWD);
+ } else {
+ llvm::errs() << "Could not get working directory: "
+ << CWD.getError().message() << "\n";
+ }
+ }
+ for (llvm::StringRef File : AbsolutePaths) {
// Currently implementations of CompilationDatabase::getCompileCommands can
// change the state of the file system (e.g. prepare generated headers), so
// this method needs to run right before we invoke the tool, as the next
@@ -498,13 +521,15 @@ int ClangTool::run(ToolAction *Action) {
llvm::errs() << "Error while processing " << File << ".\n";
ProcessingFailed = true;
}
- // Return to the initial directory to correctly resolve next file by
- // relative path.
- if (OverlayFileSystem->setCurrentWorkingDirectory(InitialDirectory.c_str()))
- llvm::report_fatal_error("Cannot chdir into \"" +
- Twine(InitialDirectory) + "\n!");
}
}
+
+ if (!InitialWorkingDir.empty()) {
+ if (auto EC =
+ OverlayFileSystem->setCurrentWorkingDirectory(InitialWorkingDir))
+ llvm::errs() << "Error when trying to restore working dir: "
+ << EC.message() << "\n";
+ }
return ProcessingFailed ? 1 : (FileSkipped ? 2 : 0);
}
@@ -541,42 +566,40 @@ int ClangTool::buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs) {
return run(&Action);
}
+void ClangTool::setRestoreWorkingDir(bool RestoreCWD) {
+ this->RestoreCWD = RestoreCWD;
+}
+
namespace clang {
namespace tooling {
std::unique_ptr<ASTUnit>
-buildASTFromCode(const Twine &Code, const Twine &FileName,
+buildASTFromCode(StringRef Code, StringRef FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName,
"clang-tool", std::move(PCHContainerOps));
}
std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
- const Twine &Code, const std::vector<std::string> &Args,
- const Twine &FileName, const Twine &ToolName,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ StringRef Code, const std::vector<std::string> &Args, StringRef FileName,
+ StringRef ToolName, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArgumentsAdjuster Adjuster) {
- SmallString<16> FileNameStorage;
- StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
-
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
+ new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), OverlayFileSystem));
ToolInvocation Invocation(
- getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef),
+ getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName),
&Action, Files.get(), std::move(PCHContainerOps));
- SmallString<1024> CodeStorage;
- InMemoryFileSystem->addFile(FileNameRef, 0,
- llvm::MemoryBuffer::getMemBuffer(
- Code.toNullTerminatedStringRef(CodeStorage)));
+ InMemoryFileSystem->addFile(FileName, 0,
+ llvm::MemoryBuffer::getMemBufferCopy(Code));
if (!Invocation.run())
return nullptr;
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 9c2f5cd9cf12..6f453f96d753 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -28,7 +28,7 @@ set(COMPILER_RT_SRC_ROOT ${LLVM_MAIN_SRC_DIR}/projects/compiler-rt)
# variable) as in add_llvm_external_project
if(NOT EXISTS ${COMPILER_RT_SRC_ROOT})
# We don't want to set it if LLVM_EXTERNAL_COMPILER_RT_SOURCE_DIR is ""
- if(${LLVM_EXTERNAL_COMPILER_RT_SOURCE_DIR})
+ if(LLVM_EXTERNAL_COMPILER_RT_SOURCE_DIR)
set(COMPILER_RT_SRC_ROOT ${LLVM_EXTERNAL_COMPILER_RT_SOURCE_DIR})
endif()
endif()
@@ -126,7 +126,7 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/)
FileCheck count not llvm-nm llvm-objdump llvm-symbolizer)
# Add top-level targets for various compiler-rt test suites.
- set(COMPILER_RT_TEST_SUITES check-fuzzer check-asan check-asan-dynamic check-dfsan
+ set(COMPILER_RT_TEST_SUITES check-fuzzer check-asan check-hwasan check-asan-dynamic check-dfsan
check-lsan check-msan check-sanitizer check-tsan check-ubsan check-ubsan-minimal
check-profile check-cfi check-cfi-and-supported check-safestack)
foreach(test_suite ${COMPILER_RT_TEST_SUITES})
diff --git a/test/ARCMT/objcmt-arc-cf-annotations.m.result b/test/ARCMT/objcmt-arc-cf-annotations.m.result
index 84bc43dcb5ca..ac4794820eeb 100644
--- a/test/ARCMT/objcmt-arc-cf-annotations.m.result
+++ b/test/ARCMT/objcmt-arc-cf-annotations.m.result
@@ -299,11 +299,11 @@ extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn stat
@protocol QCCompositionRenderer - (NSDictionary*) attributes;
@end @interface QCRenderer : NSObject <QCCompositionRenderer> {
}
-- (id) createSnapshotImageOfType:(NSString*)type;
+- (id) createSnapshotImageOfType:(NSString*)type NS_RETURNS_RETAINED;
@end extern NSString* const QCViewDidStartRenderingNotification;
@interface QCView : NSView <QCCompositionRenderer> {
}
-- (id) createSnapshotImageOfType:(NSString*)type;
+- (id) createSnapshotImageOfType:(NSString*)type NS_RETURNS_RETAINED;
@end enum {
ICEXIFOrientation1 = 1, ICEXIFOrientation2 = 2, ICEXIFOrientation3 = 3, ICEXIFOrientation4 = 4, ICEXIFOrientation5 = 5, ICEXIFOrientation6 = 6, ICEXIFOrientation7 = 7, ICEXIFOrientation8 = 8, };
@class ICDevice;
diff --git a/test/Misc/Inputs/module.modulemap b/test/AST/Inputs/module.modulemap
index a8ecb09390a2..a8ecb09390a2 100644
--- a/test/Misc/Inputs/module.modulemap
+++ b/test/AST/Inputs/module.modulemap
diff --git a/test/AST/Inputs/std-coroutine.h b/test/AST/Inputs/std-coroutine.h
new file mode 100644
index 000000000000..7a424f1e99cf
--- /dev/null
+++ b/test/AST/Inputs/std-coroutine.h
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wno-unreachable-code -Wno-unused-value
+#ifndef STD_COROUTINE_H
+#define STD_COROUTINE_H
+
+namespace std {
+namespace experimental {
+
+template <class Ret, typename... T>
+struct coroutine_traits { using promise_type = typename Ret::promise_type; };
+
+template <class Promise = void>
+struct coroutine_handle {
+ static coroutine_handle from_address(void *);
+};
+template <>
+struct coroutine_handle<void> {
+ template <class PromiseType>
+ coroutine_handle(coroutine_handle<PromiseType>);
+ static coroutine_handle from_address(void *);
+};
+
+struct suspend_always {
+ bool await_ready() { return false; }
+ void await_suspend(coroutine_handle<>) {}
+ void await_resume() {}
+};
+
+struct suspend_never {
+ bool await_ready() { return true; }
+ void await_suspend(coroutine_handle<>) {}
+ void await_resume() {}
+};
+
+} // namespace experimental
+} // namespace std
+
+#endif // STD_COROUTINE_H
diff --git a/test/Misc/ast-dump-arm-attr.c b/test/AST/ast-dump-arm-attr.c
index 41328165d210..41328165d210 100644
--- a/test/Misc/ast-dump-arm-attr.c
+++ b/test/AST/ast-dump-arm-attr.c
diff --git a/test/AST/ast-dump-array.cpp b/test/AST/ast-dump-array.cpp
new file mode 100644
index 000000000000..bfea13534a5d
--- /dev/null
+++ b/test/AST/ast-dump-array.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck -strict-whitespace %s
+
+void testArrayInitExpr()
+{
+ int a[10];
+ auto l = [a]{
+ };
+ // CHECK: |-ArrayInitLoopExpr 0x{{[^ ]*}} <col:15> 'int [10]'
+ // CHECK: | `-ArrayInitIndexExpr 0x{{[^ ]*}} <<invalid sloc>> 'unsigned long'
+}
+
+template<typename T, int Size>
+class array {
+ T data[Size];
+
+ using array_T_size = T[Size];
+ // CHECK: `-DependentSizedArrayType 0x{{[^ ]*}} 'T [Size]' dependent <col:25, col:30>
+};
+
diff --git a/test/Misc/ast-dump-attr.cpp b/test/AST/ast-dump-attr.cpp
index 1e4eb7c31955..b0b08dd6f00e 100644
--- a/test/Misc/ast-dump-attr.cpp
+++ b/test/AST/ast-dump-attr.cpp
@@ -35,7 +35,8 @@ int TestAlignedNull __attribute__((aligned));
int TestAlignedExpr __attribute__((aligned(4)));
// CHECK: VarDecl{{.*}}TestAlignedExpr
// CHECK-NEXT: AlignedAttr {{.*}} aligned
-// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
int TestEnum __attribute__((visibility("default")));
// CHECK: VarDecl{{.*}}TestEnum
@@ -209,3 +210,24 @@ namespace TestSuppress {
}
}
}
+
+// Verify the order of attributes in the Ast. It must reflect the order
+// in the parsed source.
+int mergeAttrTest() __attribute__((deprecated)) __attribute__((warn_unused_result));
+int mergeAttrTest() __attribute__((annotate("test")));
+int mergeAttrTest() __attribute__((unused,no_thread_safety_analysis));
+// CHECK: FunctionDecl{{.*}} mergeAttrTest
+// CHECK-NEXT: DeprecatedAttr
+// CHECK-NEXT: WarnUnusedResultAttr
+
+// CHECK: FunctionDecl{{.*}} mergeAttrTest
+// CHECK-NEXT: DeprecatedAttr{{.*}} Inherited
+// CHECK-NEXT: WarnUnusedResultAttr{{.*}} Inherited
+// CHECK-NEXT: AnnotateAttr{{.*}}
+
+// CHECK: FunctionDecl{{.*}} mergeAttrTest
+// CHECK-NEXT: DeprecatedAttr{{.*}} Inherited
+// CHECK-NEXT: WarnUnusedResultAttr{{.*}} Inherited
+// CHECK-NEXT: AnnotateAttr{{.*}} Inherited
+// CHECK-NEXT: UnusedAttr
+// CHECK-NEXT: NoThreadSafetyAnalysisAttr
diff --git a/test/Misc/ast-dump-attr.m b/test/AST/ast-dump-attr.m
index 8775d40d9985..8775d40d9985 100644
--- a/test/Misc/ast-dump-attr.m
+++ b/test/AST/ast-dump-attr.m
diff --git a/test/Misc/ast-dump-c-attr.c b/test/AST/ast-dump-c-attr.c
index df9c347bb412..8452b797e2bd 100644
--- a/test/Misc/ast-dump-c-attr.c
+++ b/test/AST/ast-dump-c-attr.c
@@ -1,46 +1,47 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux -fdouble-square-bracket-attributes -Wno-deprecated-declarations -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s
-
-int Test1 [[deprecated]];
-// CHECK: VarDecl{{.*}}Test1
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:13> "" ""
-
-enum [[deprecated("Frobble")]] Test2 {
- Test3 [[deprecated]]
-};
-// CHECK: EnumDecl{{.*}}Test2
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:8, col:28> "Frobble" ""
-// CHECK-NEXT: EnumConstantDecl{{.*}}Test3
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:11> "" ""
-
-struct [[deprecated]] Test4 {
- [[deprecated("Frobble")]] int Test5, Test6;
- int Test7 [[deprecated]] : 12;
-};
-// CHECK: RecordDecl{{.*}}Test4
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:10> "" ""
-// CHECK-NEXT: FieldDecl{{.*}}Test5
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:5, col:25> "Frobble" ""
-// CHECK-NEXT: FieldDecl{{.*}}Test6
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:5, col:25> "Frobble" ""
-// CHECK-NEXT: FieldDecl{{.*}}Test7
-// CHECK-NEXT: IntegerLiteral{{.*}}'int' 12
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:15> "" ""
-
-struct [[deprecated]] Test8;
-// CHECK: RecordDecl{{.*}}Test8
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:10> "" ""
-
-[[deprecated]] void Test9(int Test10 [[deprecated]]);
-// CHECK: FunctionDecl{{.*}}Test9
-// CHECK-NEXT: ParmVarDecl{{.*}}Test10
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:40> "" ""
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:3> "" ""
-
-void Test11 [[deprecated]](void);
-// CHECK: FunctionDecl{{.*}}Test11
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:15> "" ""
-
-void Test12(void) [[deprecated]] {}
-// CHECK: FunctionDecl{{.*}}Test12
-// CHECK-NEXT: CompoundStmt
-// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:21> "" ""
+// RUN: %clang_cc1 -triple x86_64-pc-linux -fdouble-square-bracket-attributes -Wno-deprecated-declarations -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s
+
+int Test1 [[deprecated]];
+// CHECK: VarDecl{{.*}}Test1
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:13> "" ""
+
+enum [[deprecated("Frobble")]] Test2 {
+ Test3 [[deprecated]]
+};
+// CHECK: EnumDecl{{.*}}Test2
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:8, col:28> "Frobble" ""
+// CHECK-NEXT: EnumConstantDecl{{.*}}Test3
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:11> "" ""
+
+struct [[deprecated]] Test4 {
+ [[deprecated("Frobble")]] int Test5, Test6;
+ int Test7 [[deprecated]] : 12;
+};
+// CHECK: RecordDecl{{.*}}Test4
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:10> "" ""
+// CHECK-NEXT: FieldDecl{{.*}}Test5
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:5, col:25> "Frobble" ""
+// CHECK-NEXT: FieldDecl{{.*}}Test6
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:5, col:25> "Frobble" ""
+// CHECK-NEXT: FieldDecl{{.*}}Test7
+// CHECK-NEXT: Constant{{.*}}'int'
+// CHECK-NEXT: IntegerLiteral{{.*}}'int' 12
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:15> "" ""
+
+struct [[deprecated]] Test8;
+// CHECK: RecordDecl{{.*}}Test8
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:10> "" ""
+
+[[deprecated]] void Test9(int Test10 [[deprecated]]);
+// CHECK: FunctionDecl{{.*}}Test9
+// CHECK-NEXT: ParmVarDecl{{.*}}Test10
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:40> "" ""
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:3> "" ""
+
+void Test11 [[deprecated]](void);
+// CHECK: FunctionDecl{{.*}}Test11
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:15> "" ""
+
+void Test12(void) [[deprecated]] {}
+// CHECK: FunctionDecl{{.*}}Test12
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeprecatedAttr 0x{{[^ ]*}} <col:21> "" ""
diff --git a/test/Misc/ast-dump-color.cpp b/test/AST/ast-dump-color.cpp
index ad7ea3023a86..8cf52049251b 100644
--- a/test/Misc/ast-dump-color.cpp
+++ b/test/AST/ast-dump-color.cpp
@@ -46,18 +46,17 @@ struct Invalid {
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]FunctionDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:9:1[[RESET]], [[Yellow]]line:16:1[[RESET]]> [[Yellow]]line:9:6[[RESET]][[CYAN]] TestAttributedStmt[[RESET]] [[Green]]'void ()'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[MAGENTA:.\[0;1;35m]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]], [[Yellow]]line:16:1[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]SwitchStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:10:3[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[Blue:.\[0;34m]]<<<NULL>>>[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:10:11[[RESET]]> [[Green]]'int'[[RESET]][[Cyan:.\[0;36m]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:14[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:3[[RESET]], [[Yellow]]line:12:27[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| | | |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]| | | |-[[RESET]][[Blue]]<<<NULL>>>[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| | | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| | | | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| | | `-[[RESET]][[MAGENTA]]AttributedStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:12:5[[RESET]], [[Yellow]]col:27[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | | |-[[RESET]][[BLUE]]FallThroughAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:7[[RESET]], [[Yellow]]col:14[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | | `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:3[[RESET]], [[Yellow]]line:14:5[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[Blue]]<<<NULL>>>[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| | | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:14:5[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]FullComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:8:4[[RESET]], [[Yellow]]col:11[[RESET]]>{{$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]ParagraphComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:4[[RESET]], [[Yellow]]col:11[[RESET]]>{{$}}
diff --git a/test/Misc/ast-dump-comment.cpp b/test/AST/ast-dump-comment.cpp
index 5bd6934d80cf..5bd6934d80cf 100644
--- a/test/Misc/ast-dump-comment.cpp
+++ b/test/AST/ast-dump-comment.cpp
diff --git a/test/AST/ast-dump-decl-stmts.cpp b/test/AST/ast-dump-decl-stmts.cpp
new file mode 100644
index 000000000000..3705bc5785c5
--- /dev/null
+++ b/test/AST/ast-dump-decl-stmts.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck -strict-whitespace %s
+
+void test_func() {
+ int a, b, c;
+ // CHECK: DeclStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:14>
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:3, col:7> col:7 a 'int'
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:3, col:10> col:10 b 'int'
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:3, col:13> col:13 c 'int'
+ void d(), e(int);
+ // CHECK: DeclStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:19>
+ // CHECK-NEXT: FunctionDecl 0x{{[^ ]*}} parent 0x{{[^ ]*}} <col:3, col:10> col:8 d 'void ()'
+ // CHECK-NEXT: FunctionDecl 0x{{[^ ]*}} parent 0x{{[^ ]*}} <col:3, col:18> col:13 e 'void (int)'
+ // CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:15> col:18 'int'
+ int f;
+ // CHECK: DeclStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8>
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:3, col:7> col:7 f 'int'
+}
+
+// FIXME: These currently do not show up as a DeclStmt.
+int a, b, c;
+// CHECK: VarDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:5> col:5 a 'int'
+// CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:1, col:8> col:8 b 'int'
+// CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:1, col:11> col:11 c 'int'
+void d(), e(int);
+// CHECK: FunctionDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:8> col:6 d 'void ()'
+// CHECK-NEXT: FunctionDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <col:1, col:16> col:11 e 'void (int)'
+// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:13> col:16 'int'
+int f;
+// CHECK: VarDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:5> col:5 f 'int'
+
diff --git a/test/Misc/ast-dump-decl.c b/test/AST/ast-dump-decl.c
index 71b98c9443cf..e0a8b56f70a5 100644
--- a/test/Misc/ast-dump-decl.c
+++ b/test/AST/ast-dump-decl.c
@@ -96,7 +96,8 @@ enum testEnumConstantDecl {
};
// CHECK: EnumConstantDecl{{.*}} TestEnumConstantDecl 'int'
// CHECK: EnumConstantDecl{{.*}} TestEnumConstantDeclInit 'int'
-// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
struct testIndirectFieldDecl {
struct {
@@ -140,7 +141,8 @@ struct testFieldDecl {
};
// CHECK: FieldDecl{{.*}} TestFieldDecl 'int'
// CHECK: FieldDecl{{.*}} TestFieldDeclWidth 'int'
-// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
// CHECK-MODULE: FieldDecl{{.*}} TestFieldDeclPrivate 'int' __module_private__
int TestVarDecl;
diff --git a/test/Misc/ast-dump-decl.cpp b/test/AST/ast-dump-decl.cpp
index 21ba7ec8dad2..6386d340eb79 100644
--- a/test/Misc/ast-dump-decl.cpp
+++ b/test/AST/ast-dump-decl.cpp
@@ -263,6 +263,15 @@ namespace testClassTemplateDecl {
template<typename T1> class TestClassTemplatePartial<T1, A> {
int j;
};
+
+ template<typename T = int> struct TestTemplateDefaultType;
+ template<typename T> struct TestTemplateDefaultType { };
+
+ template<int I = 42> struct TestTemplateDefaultNonType;
+ template<int I> struct TestTemplateDefaultNonType { };
+
+ template<template<typename> class TT = TestClassTemplate> struct TestTemplateTemplateDefaultType;
+ template<template<typename> class TT> struct TestTemplateTemplateDefaultType { };
}
// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
// CHECK-NEXT: TemplateTypeParmDecl
@@ -316,6 +325,24 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial
// CHECK-NEXT: FieldDecl{{.*}} j
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} {{.*}} TestTemplateDefaultType
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK-NEXT: inherited from TemplateTypeParm 0x{{[^ ]*}} 'T'
+
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} {{.*}} TestTemplateDefaultNonType
+// CHECK-NEXT: NonTypeTemplateParmDecl
+// CHECK-NEXT: TemplateArgument expr
+// CHECK-NEXT: inherited from NonTypeTemplateParm 0x{{[^ ]*}} 'I' 'int'
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} {{.*}} TestTemplateTemplateDefaultType
+// CHECK-NEXT: TemplateTemplateParmDecl
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: TemplateArgument
+// CHECK-NEXT: inherited from TemplateTemplateParm 0x{{[^ ]*}} 'TT'
+
// PR15220 dump instantiation only once
namespace testCanonicalTemplate {
class A {};
@@ -381,7 +408,8 @@ namespace TestNonTypeTemplateParmDecl {
// CHECK-NEXT: FunctionTemplateDecl
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I
// CHECK-NEXT: TemplateArgument expr
-// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
+// CHECK-NEXT: ConstantExpr{{.*}} 'int'
+// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J
namespace TestTemplateTemplateParmDecl {
diff --git a/test/Misc/ast-dump-decl.m b/test/AST/ast-dump-decl.m
index 4cfb8aa0c41d..7f114dd7cb28 100644
--- a/test/Misc/ast-dump-decl.m
+++ b/test/AST/ast-dump-decl.m
@@ -81,6 +81,14 @@
// CHECK-NEXT: ObjCProtocol{{.*}} 'P'
// CHECK-NEXT: ObjCMethodDecl{{.*}} bar
+@interface TestGenericInterface<T> : A<P> {
+}
+@end
+// CHECK: ObjCInterfaceDecl{{.*}} TestGenericInterface
+// CHECK-NEXT: -super ObjCInterface {{.+}} 'A'
+// CHECK-NEXT: -ObjCProtocol {{.+}} 'P'
+// CHECK-NEXT: -ObjCTypeParamDecl {{.+}} <col:33> col:33 T 'id':'id'
+
@implementation TestObjCClass (TestObjCCategoryDecl)
- (void) bar {
}
diff --git a/test/Misc/ast-dump-decl.mm b/test/AST/ast-dump-decl.mm
index be245f7ef5cd..be245f7ef5cd 100644
--- a/test/Misc/ast-dump-decl.mm
+++ b/test/AST/ast-dump-decl.mm
diff --git a/test/AST/ast-dump-expr.c b/test/AST/ast-dump-expr.c
new file mode 100644
index 000000000000..6011ab7975b0
--- /dev/null
+++ b/test/AST/ast-dump-expr.c
@@ -0,0 +1,339 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu11 -ast-dump %s | FileCheck -strict-whitespace %s
+
+void Comma(void) {
+ 1, 2, 3;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> 'int' ','
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:3, col:6> 'int' ','
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:3> 'int' 1
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:6> 'int' 2
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 3
+}
+
+void Assignment(int a) {
+ a = 12;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '='
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:7> 'int' 12
+
+ a += a;
+ // CHECK: CompoundAssignOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '+=' ComputeLHSTy='int' ComputeResultTy='int'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+}
+
+void Conditionals(int a) {
+ a ? 0 : 1;
+ // CHECK: ConditionalOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:7> 'int' 0
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 1
+
+ a ?: 0;
+ // CHECK: BinaryConditionalOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: OpaqueValueExpr 0x{{[^ ]*}} <col:3> 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: OpaqueValueExpr 0x{{[^ ]*}} <col:3> 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:8> 'int' 0
+}
+
+void BinaryOperators(int a, int b) {
+ // Logical operators
+ a || b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '||'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a && b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '&&'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ // Bitwise operators
+ a | b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '|'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a ^ b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '^'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a & b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '&'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ // Equality operators
+ a == b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '=='
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a != b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '!='
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ // Relational operators
+ a < b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '<'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a > b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '>'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a <= b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '<='
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a >= b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '>='
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ // Bit shifting operators
+ a << b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '<<'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a >> b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'int' '>>'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ // Additive operators
+ a + b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '+'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a - b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '-'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ // Multiplicative operators
+ a * b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '*'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a / b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '/'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+
+ a % b;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> 'int' '%'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> 'int' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int'
+}
+
+void UnaryOperators(int a, int *b) {
+ // Cast operators
+ (float)a;
+ // CHECK: CStyleCastExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:10> 'float' <IntegralToFloating>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ // ++, --, and ~ are covered elsewhere.
+
+ -a;
+ // CHECK: UnaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:4> 'int' prefix '-'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ +a;
+ // CHECK: UnaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:4> 'int' prefix '+' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ &a;
+ // CHECK: UnaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:4> 'int *' prefix '&' cannot overflow
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ *b;
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:3, col:4> 'int' lvalue prefix '*' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'b' 'int *'
+
+ !a;
+ // CHECK: UnaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:4> 'int' prefix '!' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ sizeof a;
+ // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:10> 'unsigned long' sizeof
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ sizeof(int);
+ // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:13> 'unsigned long' sizeof 'int'
+
+ _Alignof(int);
+ // FIXME: Uses C++ spelling for alignof in C mode.
+ // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} <line:[[@LINE-2]]:3, col:15> 'unsigned long' alignof 'int'
+}
+
+struct S {
+ int a;
+};
+
+void PostfixOperators(int *a, struct S b, struct S *c) {
+ a[0];
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: ArraySubscriptExpr 0x{{[^ ]*}} <col:3, col:6> 'int' lvalue
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int *'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:5> 'int' 0
+
+ UnaryOperators(*a, a);
+ // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:23> 'void'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'void (int, int *)' Function 0x{{[^ ]*}} 'UnaryOperators' 'void (int, int *)'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:18, col:19> 'int' lvalue prefix '*' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:19> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int *'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:22> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int *'
+
+ b.a;
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:5> 'int' lvalue .a 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'struct S':'struct S' lvalue ParmVar 0x{{[^ ]*}} 'b' 'struct S':'struct S'
+
+ c->a;
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:6> 'int' lvalue ->a 0x{{[^ ]*}}
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'struct S *' lvalue ParmVar 0x{{[^ ]*}} 'c' 'struct S *'
+
+ // Postfix ++ and -- are covered elsewhere.
+
+ (int [4]){1, 2, 3, 4, };
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: CompoundLiteralExpr 0x{{[^ ]*}} <col:3, col:25> 'int [4]' lvalue
+ // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} <col:12, col:25> 'int [4]'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:13> 'int' 1
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:16> 'int' 2
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:19> 'int' 3
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:22> 'int' 4
+
+ (struct S){1};
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: CompoundLiteralExpr 0x{{[^ ]*}} <col:3, col:15> 'struct S':'struct S' lvalue
+ // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} <col:13, col:15> 'struct S':'struct S'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:14> 'int' 1
+}
+
+enum E { One };
+
+void PrimaryExpressions(int a) {
+ a;
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ 'a';
+ // CHECK: CharacterLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'int' 97
+
+ L'a';
+ // CHECK: CharacterLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'int' 97
+
+ "a";
+ // ImplicitCastExpr
+ // CHECK: StringLiteral 0x{{[^ ]*}} <col:3> 'char [2]' lvalue "a"
+
+ L"a";
+ // ImplicitCastExpr
+ // CHECK: StringLiteral 0x{{[^ ]*}} <col:3> 'int [2]' lvalue L"a"
+
+ u8"a";
+ // ImplicitCastExpr
+ // CHECK: StringLiteral 0x{{[^ ]*}} <col:3> 'char [2]' lvalue u8"a"
+
+ U"a";
+ // ImplicitCastExpr
+ // CHECK: StringLiteral 0x{{[^ ]*}} <col:3> 'unsigned int [2]' lvalue U"a"
+
+ u"a";
+ // ImplicitCastExpr
+ // CHECK: StringLiteral 0x{{[^ ]*}} <col:3> 'unsigned short [2]' lvalue u"a"
+
+ 1;
+ // CHECK: IntegerLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'int' 1
+
+ 1u;
+ // CHECK: IntegerLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'unsigned int' 1
+
+ 1ll;
+ // CHECK: IntegerLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'long long' 1
+
+ 1.0;
+ // CHECK: FloatingLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'double' {{1\.[0]*e[\+]?[0]+}}
+
+ 1.0f;
+ // CHECK: FloatingLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'float' {{1\.[0]*e[\+]?[0]+}}
+
+ 1.0l;
+ // CHECK: FloatingLiteral 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'long double' {{1\.[0]*e[\+]?[0]+}}
+
+ One;
+ // CHECK: DeclRefExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'int' EnumConstant 0x{{[^ ]*}} 'One' 'int'
+
+ (a);
+ // CHECK: ImplicitCastExpr
+ // CHECK-NEXT: ParenExpr 0x{{[^ ]*}} <col:3, col:5> 'int' lvalue
+ // CHECK: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int'
+
+ // Generic selection expressions are covered elsewhere.
+}
diff --git a/test/AST/ast-dump-expr.cpp b/test/AST/ast-dump-expr.cpp
new file mode 100644
index 000000000000..5d668aad4ae9
--- /dev/null
+++ b/test/AST/ast-dump-expr.cpp
@@ -0,0 +1,553 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -fcxx-exceptions -std=gnu++17 -ast-dump %s | FileCheck -strict-whitespace %s
+
+namespace std {
+using size_t = decltype(sizeof(0));
+
+class type_info {
+public:
+ virtual ~type_info();
+ bool operator==(const type_info& rhs) const noexcept;
+ bool operator!=(const type_info& rhs) const noexcept;
+ type_info(const type_info& rhs) = delete; // cannot be copied
+ type_info& operator=(const type_info& rhs) = delete; // cannot be copied
+};
+
+class bad_typeid {
+public:
+ bad_typeid() noexcept;
+ bad_typeid(const bad_typeid&) noexcept;
+ virtual ~bad_typeid();
+ bad_typeid& operator=(const bad_typeid&) noexcept;
+ const char* what() const noexcept;
+};
+} // namespace std
+void *operator new(std::size_t, void *ptr);
+
+struct S {
+ virtual ~S() = default;
+
+ void func(int);
+ template <typename Ty>
+ Ty foo();
+
+ int i;
+};
+
+struct T : S {};
+
+template <typename>
+struct U {};
+
+void Throw() {
+ throw 12;
+ // CHECK: CXXThrowExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> 'void'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 12
+
+ throw;
+ // CHECK: CXXThrowExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3> 'void'
+}
+
+void PointerToMember(S obj1, S *obj2, int S::* data, void (S::*call)(int)) {
+ obj1.*data;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> 'int' lvalue '.*'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S' lvalue ParmVar 0x{{[^ ]*}} 'obj1' 'S'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:9> 'int S::*' lvalue ParmVar 0x{{[^ ]*}} 'data' 'int S::*'
+
+ obj2->*data;
+ // CHECK: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:10> 'int' lvalue '->*'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'obj2' 'S *'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'int S::*' lvalue ParmVar 0x{{[^ ]*}} 'data' 'int S::*'
+
+ (obj1.*call)(12);
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:18> 'void'
+ // CHECK-NEXT: ParenExpr 0x{{[^ ]*}} <col:3, col:14> '<bound member function type>'
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:4, col:10> '<bound member function type>' '.*'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'S' lvalue ParmVar 0x{{[^ ]*}} 'obj1' 'S'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'void (S::*)(int)' lvalue ParmVar 0x{{[^ ]*}} 'call' 'void (S::*)(int)'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:16> 'int' 12
+
+ (obj2->*call)(12);
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:19> 'void'
+ // CHECK-NEXT: ParenExpr 0x{{[^ ]*}} <col:3, col:15> '<bound member function type>'
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:4, col:11> '<bound member function type>' '->*'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'obj2' 'S *'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:11> 'void (S::*)(int)' lvalue ParmVar 0x{{[^ ]*}} 'call' 'void (S::*)(int)'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:17> 'int' 12
+}
+
+void Casting(const S *s) {
+ // FIXME: The cast expressions contain "struct S" instead of "S".
+
+ const_cast<S *>(s);
+ // CHECK: CXXConstCastExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:20> 'S *' const_cast<struct S *> <NoOp>
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:19> 'const S *' <LValueToRValue> part_of_explicit_cast
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:19> 'const S *' lvalue ParmVar 0x{{[^ ]*}} 's' 'const S *'
+
+ static_cast<const T *>(s);
+ // CHECK: CXXStaticCastExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:27> 'const T *' static_cast<const struct T *> <BaseToDerived (S)>
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:26> 'const S *' <LValueToRValue> part_of_explicit_cast
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:26> 'const S *' lvalue ParmVar 0x{{[^ ]*}} 's' 'const S *'
+
+ dynamic_cast<const T *>(s);
+ // CHECK: CXXDynamicCastExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:28> 'const T *' dynamic_cast<const struct T *> <Dynamic>
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:27> 'const S *' <LValueToRValue> part_of_explicit_cast
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:27> 'const S *' lvalue ParmVar 0x{{[^ ]*}} 's' 'const S *'
+
+ reinterpret_cast<const int *>(s);
+ // CHECK: CXXReinterpretCastExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:34> 'const int *' reinterpret_cast<const int *> <BitCast>
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:33> 'const S *' <LValueToRValue> part_of_explicit_cast
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:33> 'const S *' lvalue ParmVar 0x{{[^ ]*}} 's' 'const S *'
+}
+
+template <typename... Ts>
+void UnaryExpressions(int *p) {
+ sizeof...(Ts);
+ // CHECK: SizeOfPackExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> 'unsigned long' 0x{{[^ ]*}} Ts
+
+ noexcept(p - p);
+ // CHECK: CXXNoexceptExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:17> 'bool'
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:12, col:16> 'long' '-'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
+
+ ::new int;
+ // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> 'int *' global Function 0x{{[^ ]*}} 'operator new' 'void *(unsigned long)'
+
+ new (int);
+ // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(unsigned long)'
+
+ new int{12};
+ // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:13> 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(unsigned long)'
+ // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} <col:10, col:13> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 12
+
+ new int[2];
+ // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> 'int *' array Function 0x{{[^ ]*}} 'operator new[]' 'void *(unsigned long)'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 2
+
+ new int[2]{1, 2};
+ // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:18> 'int *' array Function 0x{{[^ ]*}} 'operator new[]' 'void *(unsigned long)'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 2
+ // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} <col:13, col:18> 'int [2]'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:14> 'int' 1
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:17> 'int' 2
+
+ new (p) int;
+ // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(std::size_t, void *)'
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void *' <BitCast>
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <LValueToRValue>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
+
+ new (p) int{12};
+ // CHECK: CXXNewExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:17> 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(std::size_t, void *)'
+ // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} <col:14, col:17> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:15> 'int' 12
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void *' <BitCast>
+ // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <LValueToRValue>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
+
+ ::delete p;
+ // CHECK: CXXDeleteExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *) noexcept'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
+
+ delete [] p;
+ // CHECK: CXXDeleteExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:13> 'void' array Function 0x{{[^ ]*}} 'operator delete[]' 'void (void *) noexcept'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:13> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
+}
+
+void PostfixExpressions(S a, S *p, U<int> *r) {
+ a.func(0);
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> 'void'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:5> '<bound member function type>' .func 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S' lvalue ParmVar 0x{{[^ ]*}} 'a' 'S'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:10> 'int' 0
+
+ p->func(0);
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> 'void'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:6> '<bound member function type>' ->func 0x{{[^ ]*}}
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 0
+
+ // FIXME: there is no mention that this used the template keyword.
+ p->template foo<int>();
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:24> 'int':'int'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:22> '<bound member function type>' ->foo 0x{{[^ ]*}}
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *'
+
+ // FIXME: there is no mention that this used the template keyword.
+ a.template foo<float>();
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:25> 'float':'float'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:23> '<bound member function type>' .foo 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S' lvalue ParmVar 0x{{[^ ]*}} 'a' 'S'
+
+ p->~S();
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> 'void'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:7> '<bound member function type>' ->~S 0x{{[^ ]*}}
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *'
+
+ a.~S();
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'void'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:6> '<bound member function type>' .~S 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S' lvalue ParmVar 0x{{[^ ]*}} 'a' 'S'
+
+ // FIXME: there seems to be no way to distinguish the construct below from
+ // the construct above.
+ a.~decltype(a)();
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:18> 'void'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:5> '<bound member function type>' .~S 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S' lvalue ParmVar 0x{{[^ ]*}} 'a' 'S'
+
+ // FIXME: similarly, there is no way to distinguish the construct below from
+ // the p->~S() case.
+ p->::S::~S();
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:14> 'void'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:12> '<bound member function type>' ->~S 0x{{[^ ]*}}
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *'
+
+ // FIXME: there is no mention that this used the template keyword.
+ r->template U<int>::~U();
+ // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:26> 'void'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:24> '<bound member function type>' ->~U 0x{{[^ ]*}}
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'U<int> *' lvalue ParmVar 0x{{[^ ]*}} 'r' 'U<int> *'
+
+ typeid(a);
+ // CHECK: CXXTypeidExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> 'const std::type_info' lvalue
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'S' lvalue ParmVar 0x{{[^ ]*}} 'a' 'S'
+
+ // FIXME: no type information is printed for the argument.
+ typeid(S);
+ // CHECK: CXXTypeidExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> 'const std::type_info' lvalue
+}
+
+template <typename... Ts>
+void PrimaryExpressions(Ts... a) {
+ struct V {
+ void f() {
+ this;
+ // CHECK: CXXThisExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:7> 'V *' this
+ [this]{};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:7, col:14>
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:7> col:7 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V *'
+ // CHECK-NEXT: CXXMethodDecl
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' this
+
+ [*this]{};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:7, col:15>
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:7> col:7 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V'
+ // CHECK-NEXT: CXXMethodDecl
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:8> 'NULL TYPE'
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:8> '<dependent type>' prefix '*' cannot overflow
+ // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' this
+ }
+ };
+
+ int b, c;
+
+ [](){};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:6, col:8> col:3 operator() 'auto () const' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:8> col:3 implicit constexpr operator auto (*)() 'auto (*() const)()' inline
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:8> col:3 implicit __invoke 'auto ()' static inline
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:7, col:8>
+
+ [a...]{};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:10> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...'
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:10> col:3 operator() 'auto () const -> auto' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:4> 'NULL TYPE'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:9, col:10>
+
+ [=]{};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:5, col:7> col:3 operator() 'auto () const -> auto' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:6, col:7>
+
+ [=] { return b; };
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:19> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:5, col:19> col:3 operator() 'auto () const -> auto' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:9, col:16>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> 'const int' lvalue Var 0x{{[^ ]*}} 'b' 'int'
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:7, col:19>
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:9, col:16>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> 'const int' lvalue Var 0x{{[^ ]*}} 'b' 'int'
+
+ [&]{};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:5, col:7> col:3 operator() 'auto () const -> auto' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:6, col:7>
+
+ [&] { return c; };
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:19> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:5, col:19> col:3 operator() 'auto () const -> auto' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:9, col:16>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> 'int' lvalue Var 0x{{[^ ]*}} 'c' 'int'
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:7, col:19>
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:9, col:16>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> 'int' lvalue Var 0x{{[^ ]*}} 'c' 'int'
+
+ [b, &c]{ return b + c; };
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:26> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'int &'
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:9, col:26> col:3 operator() 'auto () const -> auto' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:12, col:23>
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:19, col:23> 'int' '+'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:19> 'const int' lvalue Var 0x{{[^ ]*}} 'b' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:23> 'int' lvalue Var 0x{{[^ ]*}} 'c' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'int' lvalue Var 0x{{[^ ]*}} 'b' 'int'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> 'int' lvalue Var 0x{{[^ ]*}} 'c' 'int'
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:10, col:26>
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:12, col:23>
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:19, col:23> 'int' '+'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:19> 'const int' lvalue Var 0x{{[^ ]*}} 'b' 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:23> 'int' lvalue Var 0x{{[^ ]*}} 'c' 'int'
+
+ [a..., x = 12]{};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:18> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:10> col:10 implicit 'int':'int'
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:16, col:18> col:3 operator() 'auto () const -> auto' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:4> 'NULL TYPE'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:14> 'int' 12
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:17, col:18>
+
+ []() constexpr {};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:19> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:19> col:3 constexpr operator() 'auto () const' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:19> col:3 implicit constexpr operator auto (*)() 'auto (*() const)()' inline
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:19> col:3 implicit __invoke 'auto ()' static inline
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:18, col:19>
+
+ []() mutable {};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:17> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:17> col:3 operator() 'auto ()' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:17> col:3 implicit constexpr operator auto (*)() 'auto (*() const)()' inline
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:17> col:3 implicit __invoke 'auto ()' static inline
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:16, col:17>
+
+ []() noexcept {};
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:18> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:8, col:18> col:3 operator() 'auto () const noexcept' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit constexpr operator auto (*)() noexcept 'auto (*() const)() noexcept' inline
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:18> col:3 implicit __invoke 'auto () noexcept' static inline
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:17, col:18>
+
+ []() -> int { return 0; };
+ // CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:27> '(lambda at {{.*}}:[[@LINE-1]]:3)'
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:3> col:3 implicit class definition
+ // CHECK-NEXT: DefinitionData lambda
+ // CHECK-NEXT: DefaultConstructor
+ // CHECK-NEXT: CopyConstructor
+ // CHECK-NEXT: MoveConstructor
+ // CHECK-NEXT: CopyAssignment
+ // CHECK-NEXT: MoveAssignment
+ // CHECK-NEXT: Destructor
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:11, col:27> col:3 operator() 'auto () const -> int' inline
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:17, col:24>
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:24> 'int' 0
+ // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} <col:3, col:27> col:3 implicit constexpr operator int (*)() 'auto (*() const)() -> int' inline
+ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} <col:3, col:27> col:3 implicit __invoke 'auto () -> int' static inline
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:15, col:27>
+ // CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <col:17, col:24>
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:24> 'int' 0
+
+ (a + ...);
+ // CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> '<dependent type>'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
+ // CHECK-NEXT: <<<NULL>>>
+
+ (... + a);
+ // CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> '<dependent type>'
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
+
+ (a + ... + b);
+ // CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> '<dependent type>'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int' lvalue Var 0x{{[^ ]*}} 'b' 'int'
+}
+
+
+namespace NS {
+struct X {};
+void f(X);
+void y(...);
+} // namespace NS
+
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}ADLCall 'void ()'
+void ADLCall() {
+ NS::X x;
+ // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void' adl{{$}}
+ f(x);
+ // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void' adl{{$}}
+ y(x);
+}
+
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}NonADLCall 'void ()'
+void NonADLCall() {
+ NS::X x;
+ // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void'{{$}}
+ NS::f(x);
+}
+
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}NonADLCall2 'void ()'
+void NonADLCall2() {
+ NS::X x;
+ using NS::f;
+ // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void'{{$}}
+ f(x);
+ // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void' adl{{$}}
+ y(x);
+}
+
+namespace test_adl_call_three {
+using namespace NS;
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}NonADLCall3 'void ()'
+void NonADLCall3() {
+ X x;
+ // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void'{{$}}
+ f(x);
+}
+} // namespace test_adl_call_three \ No newline at end of file
diff --git a/test/AST/ast-dump-funcs.cpp b/test/AST/ast-dump-funcs.cpp
new file mode 100644
index 000000000000..62ae9648dde0
--- /dev/null
+++ b/test/AST/ast-dump-funcs.cpp
@@ -0,0 +1,124 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck -strict-whitespace %s
+
+struct R {
+ R() = default;
+ // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> col:3 used constexpr R 'void () noexcept' default trivial
+ ~R() {} // not trivial
+ // CHECK: CXXDestructorDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:3 used ~R 'void () noexcept'
+ R(const R&) = delete;
+ // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:22> col:3 R 'void (const R &)' delete trivial
+ R(R&&) = default;
+ // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:18> col:3 constexpr R 'void (R &&)' default trivial noexcept-unevaluated
+
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-10]]:8> col:8 implicit operator= 'R &(const R &)' inline default_delete trivial noexcept-unevaluated
+};
+
+struct S {
+ int i, j;
+ R r;
+
+ S() : i(0), j(0) {}
+ // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:21> col:3 S 'void ()'
+ // CHECK-NEXT: CXXCtorInitializer Field 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 0
+ // CHECK-NEXT: CXXCtorInitializer Field 0x{{[^ ]*}} 'j' 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:17> 'int' 0
+ // CHECK-NEXT: CXXCtorInitializer Field 0x{{[^ ]*}} 'r' 'R'
+ // CHECK-NEXT: CXXConstructExpr 0x{{[^ ]*}} <col:3> 'R' 'void () noexcept'
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:20, col:21>
+
+ void a();
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:10> col:8 a 'void ()'
+ void b() const;
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> col:8 b 'void () const'
+ void c() volatile;
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> col:8 c 'void () volatile'
+ void d() &;
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> col:8 d 'void () &'
+ void e() &&;
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:12> col:8 e 'void () &&'
+ virtual void f(float, int = 12);
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:33> col:16 f 'void (float, int)' virtual
+ // CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:18> col:23 'float'
+ // CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:25, col:31> col:29 'int' cinit
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:31> 'int' 12
+
+ virtual void g() = 0;
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:22> col:16 g 'void ()' virtual pure
+
+ // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-33]]:8> col:8 implicit S 'void (const S &)' inline default_delete noexcept-unevaluated
+ // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <col:8> col:8 implicit constexpr S 'void (S &&)' inline default noexcept-unevaluated
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'S &(const S &)' inline default_delete noexcept-unevaluated
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'S &(S &&)' inline default_delete noexcept-unevaluated
+ // CHECK: CXXDestructorDecl 0x{{[^ ]*}} <col:8> col:8 implicit ~S 'void ()' inline default noexcept-unevaluated
+};
+
+struct T : S { // T is not referenced, but S is
+ void f(float, int = 100) override;
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:28> col:8 f 'void (float, int)'
+ // CHECK-NEXT: Overrides: [ 0x{{[^ ]*}} S::f 'void (float, int)' ]
+ // CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:10> col:15 'float'
+ // CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:17, col:23> col:21 'int' cinit
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:23> 'int' 100
+ // CHECK-NEXT: OverrideAttr
+
+ // CHECK: CXXConstructorDecl 0x{{[^ ]*}} <line:[[@LINE-9]]:8> col:8 implicit T 'void (const T &)' inline default_delete noexcept-unevaluated
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'T &(const T &)' inline default_delete noexcept-unevaluated
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <col:8> col:8 implicit operator= 'T &(T &&)' inline default_delete noexcept-unevaluated
+ // CHECK: CXXDestructorDecl 0x{{[^ ]*}} <col:8> col:8 implicit ~T 'void ()' inline default noexcept-unevaluated
+};
+
+struct U {
+ void f();
+ // CHECK: CXXMethodDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:10> col:8 f 'void ()'
+};
+void U::f() {} // parent
+// CHECK: CXXMethodDecl 0x{{[^ ]*}} parent 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:14> col:9 f 'void ()'
+// CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:13, col:14>
+
+void a1();
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:9> col:6 used a1 'void ()'
+void a2(void);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:13> col:6 a2 'void ()'
+void b(int a, int b);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:20> col:6 b 'void (int, int)'
+// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:8, col:12> col:12 a 'int'
+// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:15, col:19> col:19 b 'int'
+void c(int a, int b = 12);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:25> col:6 c 'void (int, int)'
+// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:8, col:12> col:12 a 'int'
+// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:15, col:23> col:19 b 'int' cinit
+// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:23> 'int' 12
+constexpr void d(void);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:22> col:16 constexpr d 'void ()'
+static void e(void);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:19> col:13 e 'void ()' static
+extern void f(void);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:19> col:13 f 'void ()' extern
+extern "C" void g(void);
+// CHECK: LinkageSpecDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:23> col:8 C
+// CHECK: FunctionDecl 0x{{[^ ]*}} <col:12, col:23> col:17 g 'void ()'
+inline void h(void);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:19> col:13 h 'void ()' inline
+void i(void) noexcept;
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:14> col:6 i 'void () noexcept'
+void j(void) noexcept(false);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:28> col:6 j 'void () noexcept(false)'
+void k(void) noexcept(1);
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:24> col:6 k 'void () noexcept(1)'
+template <typename T>
+T l(T&);
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:1, line:[[@LINE-1]]:7> col:3 l
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-3]]:11, col:20> col:20 referenced typename depth 0 index 0 T
+// CHECK-NEXT: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-3]]:1, col:7> col:3 l 'T (T &)'
+// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:5, col:6> col:7 'T &'
+
+void m(int) {}
+// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:14> col:6 m 'void (int)'
+// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:8> col:11 'int'
+// CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:13, col:14>
+
+int main() {
+ // CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:5 main 'int ()'
+ a1(); // Causes this to be marked 'used'
+}
diff --git a/test/Misc/ast-dump-invalid.cpp b/test/AST/ast-dump-invalid.cpp
index 1f7442155e33..8f7e6eb14e5e 100644
--- a/test/Misc/ast-dump-invalid.cpp
+++ b/test/AST/ast-dump-invalid.cpp
@@ -1,64 +1,62 @@
-// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s
-
-namespace TestInvalidRParenOnCXXUnresolvedConstructExpr {
-template <class T>
-void f(T i, T j) {
- return T (i, j;
-}
-}
-
-// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidRParenOnCXXUnresolvedConstructExpr
-// CHECK-NEXT: `-FunctionTemplateDecl
-// CHECK-NEXT: |-TemplateTypeParmDecl
-// CHECK-NEXT: `-FunctionDecl
-// CHECK-NEXT: |-ParmVarDecl
-// CHECK-NEXT: |-ParmVarDecl
-// CHECK-NEXT: `-CompoundStmt
-// CHECK-NEXT: `-ReturnStmt
-// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} <col:10, col:16> 'T'
-// CHECK-NEXT: |-DeclRefExpr {{.*}} <col:13> 'T' lvalue ParmVar {{.*}} 'i' 'T'
-// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:16> 'T' lvalue ParmVar {{.*}} 'j' 'T'
-
-
-namespace TestInvalidIf {
-int g(int i) {
- if (invalid_condition)
- return 4;
- else
- return i;
-}
-}
-// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf
-// CHECK-NEXT: `-FunctionDecl
-// CHECK-NEXT: |-ParmVarDecl
-// CHECK-NEXT: `-CompoundStmt
-// CHECK-NEXT: `-IfStmt {{.*}} <line:25:3, line:28:12>
-// CHECK-NEXT: |-<<<NULL>>>
-// CHECK-NEXT: |-<<<NULL>>>
-// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <<invalid sloc>> 'bool'
-// CHECK-NEXT: |-ReturnStmt {{.*}} <line:26:5, col:12>
-// CHECK-NEXT: | `-IntegerLiteral {{.*}} <col:12> 'int' 4
-// CHECK-NEXT: `-ReturnStmt {{.*}} <line:28:5, col:12>
-// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:12> 'int' <LValueToRValue>
-// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:12> 'int' lvalue ParmVar {{.*}} 'i' 'int'
-
-namespace TestInvalidFunctionDecl {
-struct Str {
- double foo1(double, invalid_type);
-};
-double Str::foo1(double, invalid_type)
-{ return 45; }
-}
-// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
-// CHECK-NEXT: |-CXXRecordDecl {{.*}} <line:46:1, line:48:1> line:46:8 struct Str definition
-// CHECK: | |-CXXRecordDecl {{.*}} <col:1, col:8> col:8 implicit struct Str
-// CHECK-NEXT: | `-CXXMethodDecl {{.*}} <line:47:4, col:36> col:11 invalid foo1 'double (double, int)'
-// CHECK-NEXT: | |-ParmVarDecl {{.*}} <col:16> col:22 'double'
-// CHECK-NEXT: | `-ParmVarDecl {{.*}} <col:24, <invalid sloc>> col:36 invalid 'int'
-// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} <line:49:1, line:50:14> line:49:13 invalid foo1 'double (double, int)'
-// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:18> col:24 'double'
-// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:26, <invalid sloc>> col:38 invalid 'int'
-// CHECK-NEXT: `-CompoundStmt {{.*}} <line:50:1, col:14>
-// CHECK-NEXT: `-ReturnStmt {{.*}} <col:3, col:10>
-// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:10> 'double' <IntegralToFloating>
-// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:10> 'int' 45
+// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s
+
+namespace TestInvalidRParenOnCXXUnresolvedConstructExpr {
+template <class T>
+void f(T i, T j) {
+ return T (i, j;
+}
+}
+
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidRParenOnCXXUnresolvedConstructExpr
+// CHECK-NEXT: `-FunctionTemplateDecl
+// CHECK-NEXT: |-TemplateTypeParmDecl
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT: |-ParmVarDecl
+// CHECK-NEXT: |-ParmVarDecl
+// CHECK-NEXT: `-CompoundStmt
+// CHECK-NEXT: `-ReturnStmt
+// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} <col:10, col:16> 'T'
+// CHECK-NEXT: |-DeclRefExpr {{.*}} <col:13> 'T' lvalue ParmVar {{.*}} 'i' 'T'
+// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:16> 'T' lvalue ParmVar {{.*}} 'j' 'T'
+
+
+namespace TestInvalidIf {
+int g(int i) {
+ if (invalid_condition)
+ return 4;
+ else
+ return i;
+}
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT: |-ParmVarDecl
+// CHECK-NEXT: `-CompoundStmt
+// CHECK-NEXT: `-IfStmt {{.*}} <line:25:3, line:28:12>
+// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <<invalid sloc>> 'bool'
+// CHECK-NEXT: |-ReturnStmt {{.*}} <line:26:5, col:12>
+// CHECK-NEXT: | `-IntegerLiteral {{.*}} <col:12> 'int' 4
+// CHECK-NEXT: `-ReturnStmt {{.*}} <line:28:5, col:12>
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:12> 'int' <LValueToRValue>
+// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:12> 'int' lvalue ParmVar {{.*}} 'i' 'int'
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+ double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}} <line:44:1, line:46:1> line:44:8 struct Str definition
+// CHECK: | |-CXXRecordDecl {{.*}} <col:1, col:8> col:8 implicit struct Str
+// CHECK-NEXT: | `-CXXMethodDecl {{.*}} <line:45:4, col:36> col:11 invalid foo1 'double (double, int)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} <col:16> col:22 'double'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} <col:24, <invalid sloc>> col:36 invalid 'int'
+// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} <line:47:1, line:48:14> line:47:13 invalid foo1 'double (double, int)'
+// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:18> col:24 'double'
+// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:26, <invalid sloc>> col:38 invalid 'int'
+// CHECK-NEXT: `-CompoundStmt {{.*}} <line:48:1, col:14>
+// CHECK-NEXT: `-ReturnStmt {{.*}} <col:3, col:10>
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:10> 'double' <IntegralToFloating>
+// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:10> 'int' 45
diff --git a/test/Misc/ast-dump-lookups.cpp b/test/AST/ast-dump-lookups.cpp
index 2d235010cb73..2d235010cb73 100644
--- a/test/Misc/ast-dump-lookups.cpp
+++ b/test/AST/ast-dump-lookups.cpp
diff --git a/test/Misc/ast-dump-msp430-attr.c b/test/AST/ast-dump-msp430-attr.c
index 3ccb3bdb705f..3ccb3bdb705f 100644
--- a/test/Misc/ast-dump-msp430-attr.c
+++ b/test/AST/ast-dump-msp430-attr.c
diff --git a/test/Misc/ast-dump-pipe.cl b/test/AST/ast-dump-pipe.cl
index ceed2f6f8992..ceed2f6f8992 100644
--- a/test/Misc/ast-dump-pipe.cl
+++ b/test/AST/ast-dump-pipe.cl
diff --git a/test/AST/ast-dump-record-definition-data.cpp b/test/AST/ast-dump-record-definition-data.cpp
new file mode 100644
index 000000000000..37ed54b1dee1
--- /dev/null
+++ b/test/AST/ast-dump-record-definition-data.cpp
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump %s | FileCheck -strict-whitespace %s
+
+void f() {
+ auto IsNotGenericLambda = [](){};
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <col:29> col:29 implicit class definition
+ // CHECK-NOT: DefinitionData {{.*}}generic{{.*}}
+ // CHECK-NEXT: DefinitionData {{.*}}lambda{{.*}}
+ auto IsGenericLambda = [](auto){};
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <col:26> col:26 implicit class definition
+ // CHECK-NEXT: DefinitionData {{.*}}generic{{.*}}lambda{{.*}}
+}
+
+struct CanPassInRegisters {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CanPassInRegisters definition
+ // CHECK-NEXT: DefinitionData {{.*}}pass_in_registers{{.*}}
+ CanPassInRegisters(const CanPassInRegisters&) = default;
+};
+
+struct CantPassInRegisters {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CantPassInRegisters definition
+ // CHECK-NOT: DefinitionData {{.*}}pass_in_registers{{.*}}
+ CantPassInRegisters(const CantPassInRegisters&) = delete;
+};
+
+struct IsEmpty {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct IsEmpty definition
+ // CHECK-NEXT: DefinitionData {{.*}}empty{{.*}}
+};
+
+struct IsNotEmpty {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotEmpty definition
+ // CHECK-NOT: DefinitionData {{.*}}empty{{.*}}
+ int a;
+};
+
+struct IsAggregate {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsAggregate definition
+ // CHECK-NEXT: DefinitionData {{.*}}aggregate{{.*}}
+ int a;
+};
+
+struct IsNotAggregate {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+4]]:1> line:[[@LINE-1]]:8 struct IsNotAggregate definition
+ // CHECK-NOT: DefinitionData {{.*}}aggregate{{.*}}
+private:
+ int a;
+};
+
+struct IsStandardLayout {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsStandardLayout definition
+ // CHECK-NEXT: DefinitionData {{.*}}standard_layout{{.*}}
+ void f();
+};
+
+struct IsNotStandardLayout {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotStandardLayout definition
+ // CHECK-NOT: DefinitionData {{.*}}standard_layout{{.*}}
+ virtual void f();
+};
+
+struct IsTriviallyCopyable {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct IsTriviallyCopyable definition
+ // CHECK-NEXT: DefinitionData {{.*}}trivially_copyable{{.*}}
+};
+
+struct IsNotTriviallyCopyable {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotTriviallyCopyable definition
+ // CHECK-NOT: DefinitionData {{.*}}trivially_copyable{{.*}}
+ IsNotTriviallyCopyable(const IsNotTriviallyCopyable&) {}
+};
+
+struct IsPOD {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsPOD definition
+ // CHECK-NEXT: DefinitionData {{.*}}pod{{.*}}
+ int a;
+};
+
+struct IsNotPOD {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotPOD definition
+ // CHECK-NOT: DefinitionData {{.*}}pod{{.*}}
+ int &a;
+};
+
+struct IsTrivial {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsTrivial definition
+ // CHECK-NEXT: DefinitionData {{.*}}trivial {{.*}}
+ IsTrivial() = default;
+};
+
+struct IsNotTrivial {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotTrivial definition
+ // CHECK-NOT: DefinitionData {{.*}}trivial {{.*}}
+ IsNotTrivial() {}
+};
+
+struct IsPolymorphic {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsPolymorphic definition
+ // CHECK-NEXT: DefinitionData {{.*}}polymorphic{{.*}}
+ virtual void f();
+};
+
+struct IsNotPolymorphic {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotPolymorphic definition
+ // CHECK-NOT: DefinitionData {{.*}}polymorphic{{.*}}
+ void f();
+};
+
+struct IsAbstract {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsAbstract definition
+ // CHECK-NEXT: DefinitionData {{.*}}abstract{{.*}}
+ virtual void f() = 0;
+};
+
+struct IsNotAbstract {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotAbstract definition
+ // CHECK-NOT: DefinitionData {{.*}}abstract{{.*}}
+ virtual void f();
+};
+
+struct IsLiteral {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsLiteral definition
+ // CHECK-NEXT: DefinitionData {{.*}}literal{{.*}}
+ ~IsLiteral() = default;
+};
+
+struct IsNotLiteral {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct IsNotLiteral definition
+ // CHECK-NOT: DefinitionData {{.*}}literal{{.*}}
+ ~IsNotLiteral() {}
+};
+
+struct HasUserDeclaredConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct HasUserDeclaredConstructor definition
+ // CHECK-NEXT: DefinitionData {{.*}}has_user_declared_ctor{{.*}}
+ HasUserDeclaredConstructor() {}
+};
+
+struct HasNoUserDeclaredConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct HasNoUserDeclaredConstructor definition
+ // CHECK-NOT: DefinitionData {{.*}}has_user_declared_ctor{{.*}}
+};
+
+struct HasConstexprNonCopyMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct HasConstexprNonCopyMoveConstructor definition
+ // CHECK-NEXT: DefinitionData {{.*}}has_constexpr_non_copy_move_ctor{{.*}}
+ constexpr HasConstexprNonCopyMoveConstructor() {}
+};
+
+struct HasNoConstexprNonCopyMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct HasNoConstexprNonCopyMoveConstructor definition
+ // CHECK-NOT: DefinitionData {{.*}}has_constexpr_non_copy_move_ctor{{.*}}
+ HasNoConstexprNonCopyMoveConstructor() {}
+};
+
+struct HasMutableFields {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct HasMutableFields definition
+ // CHECK-NEXT: DefinitionData {{.*}}has_mutable_fields{{.*}}
+ mutable int i;
+};
+
+struct HasNoMutableFields {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct HasNoMutableFields definition
+ // CHECK-NOT: DefinitionData {{.*}}has_mutable_fields{{.*}}
+ int i;
+};
+
+struct HasVariantMembers {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+5]]:1> line:[[@LINE-1]]:8 struct HasVariantMembers definition
+ // CHECK-NEXT: DefinitionData {{.*}}has_variant_members{{.*}}
+ union {
+ int i;
+ };
+};
+
+struct HasNoVariantMembers {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct HasNoVariantMembers definition
+ // CHECK-NOT: DefinitionData {{.*}}has_variant_members{{.*}}
+};
+
+struct AllowsConstDefaultInit {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct AllowsConstDefaultInit definition
+ // CHECK-NEXT: DefinitionData {{.*}}can_const_default_init{{.*}}
+ int i = 12;
+};
+
+struct DoesNotAllowConstDefaultInit {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotAllowConstDefaultInit definition
+ // CHECK-NOT: DefinitionData {{.*}}can_const_default_init{{.*}}
+ int i;
+};
diff --git a/test/AST/ast-dump-records.c b/test/AST/ast-dump-records.c
new file mode 100644
index 000000000000..e24c6047794d
--- /dev/null
+++ b/test/AST/ast-dump-records.c
@@ -0,0 +1,150 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck -strict-whitespace %s
+
+struct A;
+// CHECK: RecordDecl 0x{{[^ ]*}} <{{.*}}:1, col:8> col:8 struct A
+
+struct B;
+// CHECK: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:8> col:8 struct B
+
+struct A {
+ // CHECK: RecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+20]]:1> line:[[@LINE-1]]:8 struct A definition
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 a 'int'
+ int b, c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 b 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:3, col:10> col:10 c 'int'
+ int d : 12;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 d 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 12
+ int : 0;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:3 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:9> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 0
+ int e : 10;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 e 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 10
+ struct B *f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:13> col:13 f 'struct B *'
+};
+
+struct C {
+ // CHECK: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+36]]:1> line:[[@LINE-1]]:8 struct C definition
+ struct {
+ // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+3]]:3> line:[[@LINE-1]]:3 struct definition
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
+ } b;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (anonymous struct at {{.*}}:[[@LINE-5]]:3)':'struct C::(anonymous at {{.*}}:[[@LINE-5]]:3)'
+
+ union {
+ // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+5]]:3> line:[[@LINE-1]]:3 union definition
+ int c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 c 'int'
+ float d;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:11> col:11 d 'float'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-7]]:3> col:3 implicit 'union C::(anonymous at {{.*}}:[[@LINE-7]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-6]]:9> col:9 implicit c 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'union C::(anonymous at {{.*}}:[[@LINE-9]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'c' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-7]]:11> col:11 implicit d 'float'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'union C::(anonymous at {{.*}}:[[@LINE-12]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'd' 'float'
+
+ struct {
+ // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+4]]:3> line:[[@LINE-1]]:3 struct definition
+ int e, f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 e 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:5, col:12> col:12 f 'int'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-6]]:3> col:3 implicit 'struct C::(anonymous at {{.*}}:[[@LINE-6]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:9> col:9 implicit e 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'struct C::(anonymous at {{.*}}:[[@LINE-8]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'e' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <col:12> col:12 implicit f 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'struct C::(anonymous at {{.*}}:[[@LINE-11]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'f' 'int'
+};
+
+struct D {
+ // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+7]]:1> line:[[@LINE-1]]:8 struct D definition
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 a 'int'
+ int b[10];
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 b 'int [10]'
+ int c[];
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:7 c 'int []'
+};
+
+union E;
+// CHECK: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:7> col:7 union E
+
+union F;
+// CHECK: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:7> col:7 union F
+
+union E {
+ // CHECK: RecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+20]]:1> line:[[@LINE-1]]:7 union E definition
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 a 'int'
+ int b, c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 b 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:3, col:10> col:10 c 'int'
+ int d : 12;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 d 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 12
+ int : 0;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:3 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:9> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 0
+ int e : 10;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 e 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 10
+ struct B *f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:13> col:13 f 'struct B *'
+};
+
+union G {
+ // CHECK: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+38]]:1> line:[[@LINE-1]]:7 union G definition
+ struct {
+ // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+3]]:3> line:[[@LINE-1]]:3 struct definition
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
+ } b;
+ // FIXME: note that it talks about 'struct G' below; the same happens in
+ // other cases with union G as well.
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-7]]:3, line:[[@LINE-3]]:5> col:5 b 'struct (anonymous struct at {{.*}}:[[@LINE-7]]:3)':'struct G::(anonymous at {{.*}}:[[@LINE-7]]:3)'
+
+ union {
+ // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+5]]:3> line:[[@LINE-1]]:3 union definition
+ int c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 c 'int'
+ float d;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:11> col:11 d 'float'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-7]]:3> col:3 implicit 'union G::(anonymous at {{.*}}:[[@LINE-7]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-6]]:9> col:9 implicit c 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'union G::(anonymous at {{.*}}:[[@LINE-9]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'c' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-7]]:11> col:11 implicit d 'float'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'union G::(anonymous at {{.*}}:[[@LINE-12]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'd' 'float'
+
+ struct {
+ // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+4]]:3> line:[[@LINE-1]]:3 struct definition
+ int e, f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 e 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:5, col:12> col:12 f 'int'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-6]]:3> col:3 implicit 'struct G::(anonymous at {{.*}}:[[@LINE-6]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:9> col:9 implicit e 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'struct G::(anonymous at {{.*}}:[[@LINE-8]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'e' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <col:12> col:12 implicit f 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'struct G::(anonymous at {{.*}}:[[@LINE-11]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'f' 'int'
+};
+
diff --git a/test/AST/ast-dump-records.cpp b/test/AST/ast-dump-records.cpp
new file mode 100644
index 000000000000..e48d406bafdd
--- /dev/null
+++ b/test/AST/ast-dump-records.cpp
@@ -0,0 +1,276 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump %s | FileCheck -strict-whitespace %s
+
+struct A;
+// CHECK: CXXRecordDecl 0x{{[^ ]*}} <{{.*}}:1, col:8> col:8 struct A
+
+struct B;
+// CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:8> col:8 referenced struct B
+
+struct A {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+29]]:1> line:[[@LINE-1]]:8 struct A definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:8> col:8 implicit struct A
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 a 'int'
+ int b, c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 b 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:3, col:10> col:10 c 'int'
+ int d : 12;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 d 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 12
+ int : 0;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:7 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:9> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 0
+ int e : 10;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 e 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 10
+ B *f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:6> col:6 f 'B *'
+};
+
+struct C {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+66]]:1> line:[[@LINE-1]]:8 struct C definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal has_variant_members
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:8> col:8 implicit struct C
+ struct {
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+10]]:3> line:[[@LINE-1]]:3 struct definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
+ } b;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-12]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (anonymous struct at {{.*}}:[[@LINE-12]]:3)':'C::(anonymous struct at {{.*}}:[[@LINE-12]]:3)'
+
+ union {
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+12]]:3> line:[[@LINE-1]]:3 union definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+ int c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 c 'int'
+ float d;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:11> col:11 d 'float'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-14]]:3> col:3 implicit 'C::(anonymous union at {{.*}}:[[@LINE-14]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-6]]:9> col:9 implicit c 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'C::(anonymous union at {{.*}}:[[@LINE-16]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'c' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-7]]:11> col:11 implicit d 'float'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'C::(anonymous union at {{.*}}:[[@LINE-19]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'd' 'float'
+
+ struct {
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+11]]:3> line:[[@LINE-1]]:3 struct definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+ int e, f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 e 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:5, col:12> col:12 f 'int'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-13]]:3> col:3 implicit 'C::(anonymous struct at {{.*}}:[[@LINE-13]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:9> col:9 implicit e 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'C::(anonymous struct at {{.*}}:[[@LINE-15]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'e' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <col:12> col:12 implicit f 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'C::(anonymous struct at {{.*}}:[[@LINE-18]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'f' 'int'
+};
+
+struct D {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+16]]:1> line:[[@LINE-1]]:8 struct D definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:8> col:8 implicit struct D
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 a 'int'
+ int b[10];
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 b 'int [10]'
+ int c[];
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:7 c 'int []'
+};
+
+union E;
+// CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:7> col:7 union E
+
+union F;
+// CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:7> col:7 union F
+
+union E {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+29]]:1> line:[[@LINE-1]]:7 union E definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:7> col:7 implicit union E
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 a 'int'
+ int b, c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:7> col:7 b 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:3, col:10> col:10 c 'int'
+ int d : 12;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 d 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 12
+ int : 0;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:7 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:9> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 0
+ int e : 10;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 e 'int'
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 10
+ B *f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:6> col:6 f 'B *'
+};
+
+union G {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+71]]:1> line:[[@LINE-1]]:7 union G definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:7> col:7 implicit union G
+ struct {
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+11]]:3> line:[[@LINE-1]]:3 struct definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ int a;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
+ } b;
+ // FIXME: note that it talks about 'struct G' below; the same happens in
+ // other cases with union G as well.
+ // CHECK: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-15]]:3, line:[[@LINE-3]]:5> col:5 b 'struct (anonymous struct at {{.*}}:[[@LINE-15]]:3)':'G::(anonymous struct at {{.*}}:[[@LINE-15]]:3)'
+
+ union {
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+13]]:3> line:[[@LINE-1]]:3 union definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ int c;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 c 'int'
+ float d;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:11> col:11 d 'float'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-15]]:3> col:3 implicit 'G::(anonymous union at {{.*}}:[[@LINE-15]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-6]]:9> col:9 implicit c 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'G::(anonymous union at {{.*}}:[[@LINE-17]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'c' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-7]]:11> col:11 implicit d 'float'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'G::(anonymous union at {{.*}}:[[@LINE-20]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'd' 'float'
+
+ struct {
+ // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+12]]:3> line:[[@LINE-1]]:3 struct definition
+ // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+ // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
+ // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
+ // CHECK-NEXT: CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
+ // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
+ // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+
+ int e, f;
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 e 'int'
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:5, col:12> col:12 f 'int'
+ };
+ // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-14]]:3> col:3 implicit 'G::(anonymous struct at {{.*}}:[[@LINE-14]]:3)'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:9> col:9 implicit e 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'G::(anonymous struct at {{.*}}:[[@LINE-16]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'e' 'int'
+ // CHECK-NEXT: IndirectFieldDecl 0x{{[^ ]*}} <col:12> col:12 implicit f 'int'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} '' 'G::(anonymous struct at {{.*}}:[[@LINE-19]]:3)'
+ // CHECK-NEXT: Field 0x{{[^ ]*}} 'f' 'int'
+};
+
+struct Base1 {};
+struct Base2 {};
+struct Base3 {};
+
+struct Derived1 : Base1 {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct Derived1 definition
+ // CHECK: public 'Base1'
+};
+
+struct Derived2 : private Base1 {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct Derived2 definition
+ // CHECK: private 'Base1'
+};
+
+struct Derived3 : virtual Base1 {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct Derived3 definition
+ // CHECK: virtual public 'Base1'
+};
+
+struct Derived4 : Base1, virtual Base2, protected Base3 {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+4]]:1> line:[[@LINE-1]]:8 struct Derived4 definition
+ // CHECK: public 'Base1'
+ // CHECK-NEXT: virtual public 'Base2'
+ // CHECK-NEXT: protected 'Base3'
+};
+
+struct Derived5 : protected virtual Base1 {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct Derived5 definition
+ // CHECK: virtual protected 'Base1'
+};
+
+template <typename... Bases>
+struct Derived6 : virtual public Bases... {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct Derived6 definition
+ // CHECK: virtual public 'Bases'...
+};
diff --git a/test/AST/ast-dump-special-member-functions.cpp b/test/AST/ast-dump-special-member-functions.cpp
new file mode 100644
index 000000000000..0b025397fa93
--- /dev/null
+++ b/test/AST/ast-dump-special-member-functions.cpp
@@ -0,0 +1,446 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump %s | FileCheck -strict-whitespace %s
+
+// FIXME: exists
+
+struct TrivialDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <{{.*}}:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct TrivialDefaultConstructor definition
+ // CHECK: DefaultConstructor {{.*}} trivial{{.*}}
+ TrivialDefaultConstructor() = default;
+};
+
+struct NontrivialDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NontrivialDefaultConstructor definition
+ // CHECK: DefaultConstructor {{.*}}non_trivial{{.*}}
+ NontrivialDefaultConstructor() {}
+};
+
+struct UserProvidedDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct UserProvidedDefaultConstructor definition
+ // CHECK: DefaultConstructor {{.*}}user_provided{{.*}}
+ UserProvidedDefaultConstructor() {}
+};
+
+struct NonUserProvidedDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct NonUserProvidedDefaultConstructor definition
+ // CHECK-NOT: DefaultConstructor {{.*}}user_provided{{.*}}
+};
+
+struct HasConstexprDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct HasConstexprDefaultConstructor definition
+ // CHECK: DefaultConstructor {{.*}}constexpr{{.*}}
+ constexpr HasConstexprDefaultConstructor() {}
+};
+
+struct DoesNotHaveConstexprDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotHaveConstexprDefaultConstructor definition
+ // CHECK-NOT: DefaultConstructor {{.*}} constexpr{{.*}}
+ DoesNotHaveConstexprDefaultConstructor() {}
+};
+
+struct NeedsImplicitDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NeedsImplicitDefaultConstructor definition
+ // CHECK: DefaultConstructor {{.*}}needs_implicit{{.*}}
+ int i = 12;
+};
+
+struct DoesNotNeedImplicitDefaultConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotNeedImplicitDefaultConstructor definition
+ // CHECK-NOT: DefaultConstructor {{.*}}needs_implicit{{.*}}
+ DoesNotNeedImplicitDefaultConstructor() {}
+};
+
+struct DefaultedDefaultConstructorIsConstexpr {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DefaultedDefaultConstructorIsConstexpr definition
+ // CHECK: DefaultConstructor {{.*}}defaulted_is_constexpr{{.*}}
+ DefaultedDefaultConstructorIsConstexpr() = default;
+};
+
+struct DefaultedDefaultConstructorIsNotConstexpr {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+6]]:1> line:[[@LINE-1]]:8 struct DefaultedDefaultConstructorIsNotConstexpr definition
+ // CHECK-NOT: DefaultConstructor {{.*}}defaulted_is_constexpr{{.*}}
+ DefaultedDefaultConstructorIsNotConstexpr() = default;
+ union {
+ int i;
+ };
+};
+
+struct SimpleCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct SimpleCopyConstructor definition
+ // CHECK: CopyConstructor {{.*}}simple{{.*}}
+ int i = 12;
+};
+
+struct NotSimpleCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NotSimpleCopyConstructor definition
+ // CHECK-NOT: CopyConstructor {{.*}}simple{{.*}}
+ NotSimpleCopyConstructor(const NotSimpleCopyConstructor&) = delete;
+};
+
+struct TrivialCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct TrivialCopyConstructor definition
+ // CHECK: CopyConstructor {{.*}} trivial{{.*}}
+ TrivialCopyConstructor() = default;
+};
+
+struct NontrivialCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NontrivialCopyConstructor definition
+ // CHECK: CopyConstructor {{.*}}non_trivial{{.*}}
+ NontrivialCopyConstructor(const NontrivialCopyConstructor&) {}
+};
+
+struct UserDeclaredCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct UserDeclaredCopyConstructor definition
+ // CHECK: CopyConstructor {{.*}}user_declared{{.*}}
+ UserDeclaredCopyConstructor(const UserDeclaredCopyConstructor&) {}
+};
+
+struct NonUserDeclaredCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct NonUserDeclaredCopyConstructor definition
+ // CHECK-NOT: CopyConstructor {{.*}}user_declared{{.*}}
+};
+
+struct CopyConstructorHasConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CopyConstructorHasConstParam definition
+ // CHECK: CopyConstructor {{.*}}has_const_param{{.*}}
+ CopyConstructorHasConstParam(const CopyConstructorHasConstParam&) {}
+};
+
+struct CopyConstructorDoesNotHaveConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CopyConstructorDoesNotHaveConstParam definition
+ // CHECK-NOT: CopyConstructor {{.*}} has_const_param{{.*}}
+ CopyConstructorDoesNotHaveConstParam(CopyConstructorDoesNotHaveConstParam&) {}
+};
+
+struct NeedsImplicitCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NeedsImplicitCopyConstructor definition
+ // CHECK: CopyConstructor {{.*}}needs_implicit{{.*}}
+ int i = 12;
+};
+
+struct DoesNotNeedImplicitCopyConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotNeedImplicitCopyConstructor definition
+ // CHECK-NOT: CopyConstructor {{.*}}needs_implicit{{.*}}
+ DoesNotNeedImplicitCopyConstructor(const DoesNotNeedImplicitCopyConstructor&) {}
+};
+
+struct DeletedDestructor {
+private:
+ ~DeletedDestructor() = delete;
+};
+
+struct CopyConstructorNeedsOverloadResolution : virtual DeletedDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct CopyConstructorNeedsOverloadResolution definition
+ // CHECK: CopyConstructor {{.*}}needs_overload_resolution{{.*}}
+};
+
+struct CopyConstructorDoesNotNeedOverloadResolution {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct CopyConstructorDoesNotNeedOverloadResolution definition
+ // CHECK-NOT: CopyConstructor {{.*}}needs_overload_resolution{{.*}}
+};
+
+struct DefaultedCopyConstructorIsDeleted {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+4]]:1> line:[[@LINE-1]]:8 struct DefaultedCopyConstructorIsDeleted definition
+ // CHECK: CopyConstructor {{.*}}defaulted_is_deleted{{.*}}
+ int &&i;
+ DefaultedCopyConstructorIsDeleted(const DefaultedCopyConstructorIsDeleted&) = default;
+};
+
+struct DefaultedCopyConstructorIsNotDeleted {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+4]]:1> line:[[@LINE-1]]:8 struct DefaultedCopyConstructorIsNotDeleted definition
+ // CHECK-NOT: CopyConstructor {{.*}}defaulted_is_deleted{{.*}}
+ int i;
+ DefaultedCopyConstructorIsNotDeleted(const DefaultedCopyConstructorIsNotDeleted&) = default;
+};
+
+struct BaseWithoutCopyConstructorConstParam {
+ BaseWithoutCopyConstructorConstParam(BaseWithoutCopyConstructorConstParam&);
+};
+
+struct ImplicitCopyConstructorHasConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct ImplicitCopyConstructorHasConstParam definition
+ // CHECK: CopyConstructor {{.*}}implicit_has_const_param{{.*}}
+};
+
+struct ImplicitCopyConstructorDoesNotHaveConstParam : BaseWithoutCopyConstructorConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct ImplicitCopyConstructorDoesNotHaveConstParam definition
+ // CHECK-NOT: CopyConstructor {{.*}}implicit_has_const_param{{.*}}
+};
+
+struct MoveConstructorExists {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct MoveConstructorExists definition
+ // CHECK: MoveConstructor {{.*}}exists{{.*}}
+};
+
+struct MoveConstructorDoesNotExist {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct MoveConstructorDoesNotExist definition
+ // CHECK-NOT: MoveConstructor {{.*}}exists{{.*}}
+ MoveConstructorDoesNotExist(const MoveConstructorDoesNotExist&);
+};
+
+struct SimpleMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct SimpleMoveConstructor definition
+ // CHECK: MoveConstructor {{.*}}simple{{.*}}
+ int i = 12;
+};
+
+struct NotSimpleMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NotSimpleMoveConstructor definition
+ // CHECK-NOT: MoveConstructor {{.*}}simple{{.*}}
+ NotSimpleMoveConstructor(NotSimpleMoveConstructor&&) = delete;
+};
+
+struct TrivialMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct TrivialMoveConstructor definition
+ // CHECK: MoveConstructor {{.*}} trivial{{.*}}
+ TrivialMoveConstructor() = default;
+};
+
+struct NontrivialMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NontrivialMoveConstructor definition
+ // CHECK: MoveConstructor {{.*}}non_trivial{{.*}}
+ NontrivialMoveConstructor(NontrivialMoveConstructor&&) {}
+};
+
+struct UserDeclaredMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct UserDeclaredMoveConstructor definition
+ // CHECK: MoveConstructor {{.*}}user_declared{{.*}}
+ UserDeclaredMoveConstructor(UserDeclaredMoveConstructor&&) {}
+};
+
+struct NonUserDeclaredMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct NonUserDeclaredMoveConstructor definition
+ // CHECK-NOT: MoveConstructor {{.*}}user_declared{{.*}}
+};
+
+struct NeedsImplicitMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NeedsImplicitMoveConstructor definition
+ // CHECK: MoveConstructor {{.*}}needs_implicit{{.*}}
+ int i = 12;
+};
+
+struct DoesNotNeedImplicitMoveConstructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotNeedImplicitMoveConstructor definition
+ // CHECK-NOT: MoveConstructor {{.*}}needs_implicit{{.*}}
+ DoesNotNeedImplicitMoveConstructor(DoesNotNeedImplicitMoveConstructor&&) {}
+};
+
+struct MoveConstructorNeedsOverloadResolution : virtual DeletedDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct MoveConstructorNeedsOverloadResolution definition
+ // CHECK: MoveConstructor {{.*}}needs_overload_resolution{{.*}}
+};
+
+struct MoveConstructorDoesNotNeedOverloadResolution {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct MoveConstructorDoesNotNeedOverloadResolution definition
+ // CHECK-NOT: MoveConstructor {{.*}}needs_overload_resolution{{.*}}
+};
+
+// FIXME: defaulted_is_deleted
+
+struct TrivialCopyAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct TrivialCopyAssignment definition
+ // CHECK: CopyAssignment {{.*}} trivial{{.*}}
+ TrivialCopyAssignment& operator=(const TrivialCopyAssignment&) = default;
+};
+
+struct NontrivialCopyAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NontrivialCopyAssignment definition
+ // CHECK: CopyAssignment {{.*}}non_trivial{{.*}}
+ NontrivialCopyAssignment& operator=(const NontrivialCopyAssignment&) {}
+};
+
+struct CopyAssignmentHasConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CopyAssignmentHasConstParam definition
+ // CHECK: CopyAssignment {{.*}}has_const_param{{.*}}
+ CopyAssignmentHasConstParam& operator=(const CopyAssignmentHasConstParam&) {}
+};
+
+struct CopyAssignmentDoesNotHaveConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CopyAssignmentDoesNotHaveConstParam definition
+ // CHECK-NOT: CopyAssignment {{.*}} has_const_param{{.*}}
+ CopyAssignmentDoesNotHaveConstParam& operator=(CopyAssignmentDoesNotHaveConstParam&) {}
+};
+
+struct UserDeclaredCopyAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct UserDeclaredCopyAssignment definition
+ // CHECK: CopyAssignment {{.*}}user_declared{{.*}}
+ UserDeclaredCopyAssignment& operator=(const UserDeclaredCopyAssignment&) {}
+};
+
+struct NonUserDeclaredCopyAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct NonUserDeclaredCopyAssignment definition
+ // CHECK-NOT: CopyAssignment {{.*}}user_declared{{.*}}
+};
+
+struct NeedsImplicitCopyAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NeedsImplicitCopyAssignment definition
+ // CHECK: CopyAssignment {{.*}}needs_implicit{{.*}}
+ int i = 12;
+};
+
+struct DoesNotNeedImplicitCopyAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotNeedImplicitCopyAssignment definition
+ // CHECK-NOT: CopyAssignment {{.*}}needs_implicit{{.*}}
+ DoesNotNeedImplicitCopyAssignment& operator=(const DoesNotNeedImplicitCopyAssignment&) {}
+};
+
+struct CopyAssignmentNeedsOverloadResolution {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct CopyAssignmentNeedsOverloadResolution definition
+ // CHECK: CopyAssignment {{.*}}needs_overload_resolution{{.*}}
+ mutable int i;
+};
+
+struct CopyAssignmentDoesNotNeedOverloadResolution {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct CopyAssignmentDoesNotNeedOverloadResolution definition
+ // CHECK-NOT: CopyAssignment {{.*}}needs_overload_resolution{{.*}}
+};
+
+struct BaseWithoutCopyAssignmentConstParam {
+ BaseWithoutCopyAssignmentConstParam& operator=(BaseWithoutCopyAssignmentConstParam&);
+};
+
+struct ImplicitCopyAssignmentHasConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct ImplicitCopyAssignmentHasConstParam definition
+ // CHECK: CopyAssignment {{.*}}implicit_has_const_param{{.*}}
+};
+
+struct ImplicitCopyAssignmentDoesNotHaveConstParam : BaseWithoutCopyAssignmentConstParam {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct ImplicitCopyAssignmentDoesNotHaveConstParam definition
+ // CHECK-NOT: CopyAssignment {{.*}}implicit_has_const_param{{.*}}
+};
+
+struct MoveAssignmentExists {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct MoveAssignmentExists definition
+ // CHECK: MoveAssignment {{.*}}exists{{.*}}
+};
+
+struct MoveAssignmentDoesNotExist {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct MoveAssignmentDoesNotExist definition
+ // CHECK-NOT: MoveAssignment {{.*}}exists{{.*}}
+ MoveAssignmentDoesNotExist& operator=(const MoveAssignmentDoesNotExist&);
+};
+
+struct SimpleMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct SimpleMoveAssignment definition
+ // CHECK: MoveAssignment {{.*}}simple{{.*}}
+ int i = 12;
+};
+
+struct NotSimpleMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NotSimpleMoveAssignment definition
+ // CHECK-NOT: MoveAssignment {{.*}}simple{{.*}}
+ NotSimpleMoveAssignment& operator=(NotSimpleMoveAssignment&&) = delete;
+};
+
+struct TrivialMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct TrivialMoveAssignment definition
+ // CHECK: MoveAssignment {{.*}} trivial{{.*}}
+ TrivialMoveAssignment() = default;
+};
+
+struct NontrivialMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NontrivialMoveAssignment definition
+ // CHECK: MoveAssignment {{.*}}non_trivial{{.*}}
+ NontrivialMoveAssignment& operator=(NontrivialMoveAssignment&&) {}
+};
+
+struct UserDeclaredMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct UserDeclaredMoveAssignment definition
+ // CHECK: MoveAssignment {{.*}}user_declared{{.*}}
+ UserDeclaredMoveAssignment& operator=(UserDeclaredMoveAssignment&&) {}
+};
+
+struct NonUserDeclaredMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct NonUserDeclaredMoveAssignment definition
+ // CHECK-NOT: MoveAssignment {{.*}}user_declared{{.*}}
+};
+
+struct NeedsImplicitMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NeedsImplicitMoveAssignment definition
+ // CHECK: MoveAssignment {{.*}}needs_implicit{{.*}}
+ int i = 12;
+};
+
+struct DoesNotNeedImplicitMoveAssignment {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotNeedImplicitMoveAssignment definition
+ // CHECK-NOT: MoveAssignment {{.*}}needs_implicit{{.*}}
+ DoesNotNeedImplicitMoveAssignment& operator=(DoesNotNeedImplicitMoveAssignment&&) {}
+};
+
+struct MoveAssignmentNeedsOverloadResolution : virtual DeletedDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct MoveAssignmentNeedsOverloadResolution definition
+ // CHECK: MoveAssignment {{.*}}needs_overload_resolution{{.*}}
+};
+
+struct MoveAssignmentDoesNotNeedOverloadResolution {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct MoveAssignmentDoesNotNeedOverloadResolution definition
+ // CHECK-NOT: MoveAssignment {{.*}}needs_overload_resolution{{.*}}
+};
+
+struct SimpleDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct SimpleDestructor definition
+ // CHECK: Destructor {{.*}}simple{{.*}}
+};
+
+struct NotSimpleDestructor : DeletedDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct NotSimpleDestructor definition
+ // CHECK-NOT: Destructor {{.*}}simple{{.*}}
+};
+
+struct IrrelevantDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct IrrelevantDestructor definition
+ // CHECK: Destructor {{.*}}irrelevant{{.*}}
+};
+
+struct RelevantDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct RelevantDestructor definition
+ // CHECK-NOT: Destructor {{.*}}irrelevant{{.*}}
+ ~RelevantDestructor() {}
+};
+
+struct TrivialDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct TrivialDestructor definition
+ // CHECK: Destructor {{.*}} trivial{{.*}}
+ ~TrivialDestructor() = default;
+};
+
+struct NontrivialDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NontrivialDestructor definition
+ // CHECK: Destructor {{.*}}non_trivial{{.*}}
+ ~NontrivialDestructor() {}
+};
+
+struct UserDeclaredDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct UserDeclaredDestructor definition
+ // CHECK: Destructor {{.*}}user_declared{{.*}}
+ ~UserDeclaredDestructor() {}
+};
+
+struct NonUserDeclaredDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct NonUserDeclaredDestructor definition
+ // CHECK-NOT: Destructor {{.*}}user_declared{{.*}}
+};
+
+struct NeedsImplicitDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct NeedsImplicitDestructor definition
+ // CHECK: Destructor {{.*}}needs_implicit{{.*}}
+ int i = 12;
+};
+
+struct DoesNotNeedImplicitDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DoesNotNeedImplicitDestructor definition
+ // CHECK-NOT: Destructor {{.*}}needs_implicit{{.*}}
+ ~DoesNotNeedImplicitDestructor() {}
+};
+
+struct DestructorNeedsOverloadResolution : virtual DeletedDestructor {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:1> line:[[@LINE-1]]:8 struct DestructorNeedsOverloadResolution definition
+ // CHECK: Destructor {{.*}}needs_overload_resolution{{.*}}
+ ~DestructorNeedsOverloadResolution();
+};
+
+struct DestructorDoesNotNeedOverloadResolution {
+ // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:1> line:[[@LINE-1]]:8 struct DestructorDoesNotNeedOverloadResolution definition
+ // CHECK-NOT: Destructor {{.*}}needs_overload_resolution{{.*}}
+};
+
+// FIXME: defaulted_is_deleted
diff --git a/test/AST/ast-dump-stmt.c b/test/AST/ast-dump-stmt.c
new file mode 100644
index 000000000000..8fec31d95a0e
--- /dev/null
+++ b/test/AST/ast-dump-stmt.c
@@ -0,0 +1,375 @@
+// RUN: %clang_cc1 -std=gnu11 -ast-dump %s | FileCheck -strict-whitespace %s
+
+int TestLocation = 0;
+// CHECK: VarDecl{{.*}}TestLocation
+// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:20> 'int' 0
+
+int TestIndent = 1 + (1);
+// CHECK: VarDecl{{.*}}TestIndent
+// CHECK-NEXT: {{^}}| `-BinaryOperator{{[^()]*$}}
+// CHECK-NEXT: {{^}}| |-IntegerLiteral{{.*0[^()]*$}}
+// CHECK-NEXT: {{^}}| `-ParenExpr{{.*0[^()]*$}}
+// CHECK-NEXT: {{^}}| `-IntegerLiteral{{.*0[^()]*$}}
+
+void TestDeclStmt() {
+ int x = 0;
+ int y, z;
+}
+// CHECK: FunctionDecl{{.*}}TestDeclStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl{{.*}}x
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl{{.*}}y
+// CHECK-NEXT: VarDecl{{.*}}z
+
+int TestOpaqueValueExpr = 0 ?: 1;
+// CHECK: VarDecl{{.*}}TestOpaqueValueExpr
+// CHECK-NEXT: BinaryConditionalOperator
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: OpaqueValueExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: OpaqueValueExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: IntegerLiteral
+
+void TestUnaryOperatorExpr(void) {
+ char T1 = 1;
+ int T2 = 1;
+
+ T1++;
+ T2++;
+ // CHECK: UnaryOperator{{.*}}postfix '++' cannot overflow
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
+ // CHECK-NOT: UnaryOperator{{.*}}postfix '++' cannot overflow
+ // CHECK: DeclRefExpr{{.*}}'T2' 'int'
+
+ -T1;
+ -T2;
+ // CHECK: UnaryOperator{{.*}}prefix '-' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
+ // CHECK-NOT: UnaryOperator{{.*}}prefix '-' cannot overflow
+ // CHECK: ImplicitCastExpr
+ // CHECK: DeclRefExpr{{.*}}'T2' 'int'
+
+ ~T1;
+ ~T2;
+ // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
+ // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'T2' 'int'
+}
+
+void TestGenericSelectionExpressions(int i) {
+ _Generic(i, int : 12);
+ // CHECK: GenericSelectionExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:23> 'int'
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // FIXME: note that the following test line has a spurious whitespace.
+ // CHECK-NEXT: case 'int' selected
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:21> 'int' 12
+ _Generic(i, int : 12, default : 0);
+ // CHECK: GenericSelectionExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:36> 'int'
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // FIXME: note that the following test line has a spurious whitespace.
+ // CHECK-NEXT: case 'int' selected
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:21> 'int' 12
+ // CHECK-NEXT: default
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:35> 'int' 0
+ _Generic(i, default : 0, int : 12);
+ // CHECK: GenericSelectionExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:36> 'int'
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // CHECK-NEXT: default
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:25> 'int' 0
+ // FIXME: note that the following test line has a spurious whitespace.
+ // CHECK-NEXT: case 'int' selected
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:34> 'int' 12
+ _Generic(i, int : 12, float : 10, default : 100);
+ // CHECK: GenericSelectionExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:50> 'int'
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // FIXME: note that the following test line has a spurious whitespace.
+ // CHECK-NEXT: case 'int' selected
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:21> 'int' 12
+ // FIXME: note that the following test line has a spurious whitespace.
+ // CHECK-NEXT: case 'float'
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'float'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:33> 'int' 10
+ // CHECK-NEXT: default
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:47> 'int' 100
+
+ int j = _Generic(i, int : 12);
+ // CHECK: DeclStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:32>
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:3, col:31> col:7 j 'int' cinit
+ // CHECK-NEXT: GenericSelectionExpr 0x{{[^ ]*}} <col:11, col:31> 'int'
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}}
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:20> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // FIXME: note that the following test line has a spurious whitespace.
+ // CHECK-NEXT: case 'int' selected
+ // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:29> 'int' 12
+}
+
+void TestLabelsAndGoto(void) {
+ // Note: case and default labels are handled by TestSwitch().
+
+label1:
+ ;
+ // CHECK: LabelStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:1, line:[[@LINE-1]]:3> 'label1'
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <col:3>
+
+ goto label2;
+ // CHECK-NEXT: GotoStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:8> 'label2' 0x{{[^ ]*}}
+
+label2:
+ 0;
+ // CHECK-NEXT: LabelStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:1, line:[[@LINE-1]]:3> 'label2'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:3> 'int' 0
+
+ void *ptr = &&label1;
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl
+ // CHECK-NEXT: AddrLabelExpr 0x{{[^ ]*}} <col:15, col:17> 'void *' label1 0x{{[^ ]*}}
+
+ goto *ptr;
+ // CHECK-NEXT: IndirectGotoStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:9> 'void *' lvalue Var 0x{{[^ ]*}} 'ptr' 'void *'
+}
+
+void TestSwitch(int i) {
+ switch (i) {
+ // CHECK: SwitchStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+32]]:3>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:11> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:14, line:[[@LINE+29]]:3>
+ case 0:
+ break;
+ // CHECK-NEXT: CaseStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: ConstantExpr
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:8> 'int' 0
+ // CHECK-NEXT: BreakStmt 0x{{[^ ]*}} <line:[[@LINE-4]]:5>
+ case 1:
+ case 2:
+ break;
+ // CHECK-NEXT: CaseStmt 0x{{[^ ]*}} <line:[[@LINE-3]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: ConstantExpr
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:8> 'int' 1
+ // CHECK-NEXT: CaseStmt 0x{{[^ ]*}} <line:[[@LINE-5]]:3, line:[[@LINE-4]]:5>
+ // CHECK-NEXT: ConstantExpr
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:8> 'int' 2
+ // CHECK-NEXT: BreakStmt 0x{{[^ ]*}} <line:[[@LINE-7]]:5>
+ default:
+ break;
+ // CHECK-NEXT: DefaultStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: BreakStmt 0x{{[^ ]*}} <col:5>
+ case 3 ... 5:
+ break;
+ // CHECK-NEXT: CaseStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5> gnu_range
+ // CHECK-NEXT: ConstantExpr
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:8> 'int' 3
+ // CHECK-NEXT: ConstantExpr
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:14> 'int' 5
+ // CHECK-NEXT: BreakStmt 0x{{[^ ]*}} <line:[[@LINE-6]]:5>
+ }
+}
+
+void TestIf(_Bool b) {
+ if (b)
+ ;
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt
+
+ if (b) {}
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: CompoundStmt
+
+ if (b)
+ ;
+ else
+ ;
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-4]]:3, line:[[@LINE-1]]:5> has_else
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-6]]:5>
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-5]]:5>
+
+ if (b) {}
+ else {}
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:9> has_else
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:10, col:11>
+ // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <line:[[@LINE-5]]:8, col:9>
+
+ if (b)
+ ;
+ else if (b)
+ ;
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-4]]:3, line:[[@LINE-1]]:5> has_else
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-6]]:5>
+ // CHECK-NEXT: IfStmt 0x{{[^ ]*}} <line:[[@LINE-6]]:8, line:[[@LINE-5]]:5>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-8]]:5>
+
+ if (b)
+ ;
+ else if (b)
+ ;
+ else
+ ;
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-6]]:3, line:[[@LINE-1]]:5> has_else
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:7> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-8]]:5>
+ // CHECK-NEXT: IfStmt 0x{{[^ ]*}} <line:[[@LINE-8]]:8, line:[[@LINE-5]]:5> has_else
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-10]]:5>
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-9]]:5>
+}
+
+void TestIteration(_Bool b) {
+ while (b)
+ ;
+ // CHECK: WhileStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-4]]:5>
+
+ do
+ ;
+ while (b);
+ // CHECK: DoStmt 0x{{[^ ]*}} <line:[[@LINE-3]]:3, line:[[@LINE-1]]:11>
+ // CHECK-NEXT: NullStmt 0x{{[^ ]*}} <line:[[@LINE-3]]:5>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+
+ for (int i = 0; i < 10; ++i)
+ ;
+ // CHECK: ForStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:8, col:16> col:12 used i 'int' cinit
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:16> 'int' 0
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:19, col:23> 'int' '<'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:19> 'int' lvalue Var 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:23> 'int' 10
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:27, col:29> 'int' prefix '++'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:29> 'int' lvalue Var 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: NullStmt
+
+ for (b; b; b)
+ ;
+ // CHECK: ForStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:8> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:11> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt
+
+ for (; b; b = !b)
+ ;
+ // CHECK: ForStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:13, col:18> '_Bool' '='
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:13> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:17, col:18> 'int' prefix '!' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:18> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt
+
+ for (; b;)
+ ;
+ // CHECK: ForStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: NullStmt
+
+ for (;; b = !b)
+ ;
+ // CHECK: ForStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <line:[[@LINE-6]]:11, col:16> '_Bool' '='
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:11> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:15, col:16> 'int' prefix '!' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> '_Bool' lvalue ParmVar 0x{{[^ ]*}} 'b' '_Bool'
+ // CHECK-NEXT: NullStmt
+
+ for (;;)
+ ;
+ // CHECK: ForStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: NullStmt
+}
+
+void TestJumps(void) {
+ // goto and computed goto was tested in TestLabelsAndGoto().
+
+ while (1) {
+ continue;
+ // CHECK: ContinueStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:5>
+ break;
+ // CHECK: BreakStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:5>
+ }
+ return;
+ // CHECK: ReturnStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3>
+
+ return TestSwitch(1);
+ // CHECK: ReturnStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:22>
+ // CHECK-NEXT: CallExpr 0x{{[^ ]*}} <col:10, col:22> 'void'
+}
+
+void TestMiscStmts(void) {
+ ({int a = 10; a;});
+ // CHECK: StmtExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:20> 'int'
+ // CHECK-NEXT: CompoundStmt
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:5, col:13> col:9 used a 'int' cinit
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:13> 'int' 10
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:17> 'int' lvalue Var 0x{{[^ ]*}} 'a' 'int'
+}
diff --git a/test/AST/ast-dump-stmt.cpp b/test/AST/ast-dump-stmt.cpp
new file mode 100644
index 000000000000..9df4ee26cd9a
--- /dev/null
+++ b/test/AST/ast-dump-stmt.cpp
@@ -0,0 +1,272 @@
+// RUN: %clang_cc1 -std=c++2a -triple x86_64-linux-gnu -fcxx-exceptions -ast-dump %s | FileCheck -strict-whitespace %s
+
+namespace n {
+void function() {}
+int Variable;
+}
+using n::function;
+using n::Variable;
+void TestFunction() {
+ void (*f)() = &function;
+// CHECK: DeclRefExpr{{.*}} (UsingShadow{{.*}}function
+ Variable = 4;
+// CHECK: DeclRefExpr{{.*}} (UsingShadow{{.*}}Variable
+}
+
+// CHECK: FunctionDecl {{.*}} TestCatch1
+void TestCatch1() {
+// CHECK: CXXTryStmt
+// CHECK-NEXT: CompoundStmt
+ try {
+ }
+// CHECK-NEXT: CXXCatchStmt
+// CHECK-NEXT: VarDecl {{.*}} x
+// CHECK-NEXT: CompoundStmt
+ catch (int x) {
+ }
+}
+
+// CHECK: FunctionDecl {{.*}} TestCatch2
+void TestCatch2() {
+// CHECK: CXXTryStmt
+// CHECK-NEXT: CompoundStmt
+ try {
+ }
+// CHECK-NEXT: CXXCatchStmt
+// CHECK-NEXT: NULL
+// CHECK-NEXT: CompoundStmt
+ catch (...) {
+ }
+}
+
+void TestAllocationExprs() {
+ int *p;
+ p = new int;
+ delete p;
+ p = new int[2];
+ delete[] p;
+ p = ::new int;
+ ::delete p;
+}
+// CHECK: FunctionDecl {{.*}} TestAllocationExprs
+// CHECK: CXXNewExpr {{.*}} 'int *' Function {{.*}} 'operator new'
+// CHECK: CXXDeleteExpr {{.*}} 'void' Function {{.*}} 'operator delete'
+// CHECK: CXXNewExpr {{.*}} 'int *' array Function {{.*}} 'operator new[]'
+// CHECK: CXXDeleteExpr {{.*}} 'void' array Function {{.*}} 'operator delete[]'
+// CHECK: CXXNewExpr {{.*}} 'int *' global Function {{.*}} 'operator new'
+// CHECK: CXXDeleteExpr {{.*}} 'void' global Function {{.*}} 'operator delete'
+
+// Don't crash on dependent exprs that haven't been resolved yet.
+template <typename T>
+void TestDependentAllocationExpr() {
+ T *p = new T;
+ delete p;
+}
+// CHECK: FunctionTemplateDecl {{.*}} TestDependentAllocationExpr
+// CHECK: CXXNewExpr {{.*'T \*'$}}
+// CHECK: CXXDeleteExpr {{.*'void'$}}
+
+template <typename T>
+class DependentScopeMemberExprWrapper {
+ T member;
+};
+
+template <typename T>
+void TestDependentScopeMemberExpr() {
+ DependentScopeMemberExprWrapper<T> obj;
+ obj.member = T();
+ (&obj)->member = T();
+}
+// CHECK: FunctionTemplateDecl {{.*}} TestDependentScopeMemberExpr
+// CHECK: CXXDependentScopeMemberExpr {{.*}} lvalue .member
+// CHECK: CXXDependentScopeMemberExpr {{.*}} lvalue ->member
+
+union U {
+ int i;
+ long l;
+};
+
+void TestUnionInitList()
+{
+ U us[3] = {1};
+// CHECK: VarDecl {{.+}} <col:3, col:15> col:5 us 'U [3]' cinit
+// CHECK-NEXT: `-InitListExpr {{.+}} <col:13, col:15> 'U [3]'
+// CHECK-NEXT: |-array_filler: InitListExpr {{.+}} <col:15> 'U' field Field {{.+}} 'i' 'int'
+// CHECK-NEXT: `-InitListExpr {{.+}} <col:14> 'U' field Field {{.+}} 'i' 'int'
+// CHECK-NEXT: `-IntegerLiteral {{.+}} <col:14> 'int' 1
+}
+
+void TestSwitch(int i) {
+ switch (int a; i)
+ ;
+ // CHECK: SwitchStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5> has_init
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:11, col:15> col:15 a 'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:18> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: NullStmt
+}
+
+void TestIf(bool b) {
+ if (int i = 12; b)
+ ;
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5> has_init
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:7, col:15> col:11 i 'int' cinit
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:15> 'int' 12
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:19> 'bool' lvalue ParmVar 0x{{[^ ]*}} 'b' 'bool'
+ // CHECK-NEXT: NullStmt
+
+ if constexpr (sizeof(b) == 1)
+ ;
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <line:[[@LINE-3]]:17, col:30> 'bool'
+ // CHECK-NEXT: BinaryOperator
+ // CHECK-NEXT: UnaryExprOrTypeTraitExpr
+ // CHECK-NEXT: ParenExpr
+ // CHECK-NEXT: DeclRefExpr
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: IntegerLiteral
+ // CHECK-NEXT: NullStmt
+
+ if constexpr (sizeof(b) == 1)
+ ;
+ else
+ ;
+ // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-4]]:3, line:[[@LINE-1]]:5> has_else
+ // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <line:[[@LINE-5]]:17, col:30> 'bool'
+ // CHECK-NEXT: BinaryOperator
+ // CHECK-NEXT: UnaryExprOrTypeTraitExpr
+ // CHECK-NEXT: ParenExpr
+ // CHECK-NEXT: DeclRefExpr
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: IntegerLiteral
+ // CHECK-NEXT: NullStmt
+ // CHECK-NEXT: NullStmt
+}
+
+struct Container {
+ int *begin() const;
+ int *end() const;
+};
+
+void TestIteration() {
+ for (int i = 0; int j = i; ++i)
+ ;
+ // CHECK: ForStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:8, col:16> col:12 used i 'int' cinit
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:16> 'int' 0
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:19, col:27> col:23 used j 'int' cinit
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:27> 'int' lvalue Var 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:23> 'bool' <IntegralToBoolean>
+ // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:23> 'int' <LValueToRValue>
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:23> 'int' lvalue Var 0x{{[^ ]*}} 'j' 'int'
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:30, col:32> 'int' lvalue prefix '++'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:32> 'int' lvalue Var 0x{{[^ ]*}} 'i' 'int'
+ // CHECK-NEXT: NullStmt
+
+ int vals[10];
+ for (int v : vals)
+ ;
+ // CHECK: CXXForRangeStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:16> col:16 implicit used __range1 'int (&)[10]' cinit
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> 'int [10]' lvalue Var 0x{{[^ ]*}} 'vals' 'int [10]'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:14> col:14 implicit used __begin1 'int *':'int *' cinit
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int [10]' lvalue Var 0x{{[^ ]*}} '__range1' 'int (&)[10]'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:14, col:16> col:14 implicit used __end1 'int *':'int *' cinit
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:14, col:16> 'int *' '+'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int [10]' lvalue Var 0x{{[^ ]*}} '__range1' 'int (&)[10]'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:16> 'long' 10
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:14> 'bool' '!='
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__end1' 'int *':'int *'
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue prefix '++'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:8, col:14> col:12 v 'int' cinit
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:14> 'int' lvalue prefix '*' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: NullStmt
+
+ Container C;
+ for (int v : C)
+ ;
+ // CHECK: CXXForRangeStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: <<<NULL>>>
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:16> col:16 implicit used __range1 'Container &' cinit
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:16> 'Container' lvalue Var 0x{{[^ ]*}} 'C' 'Container'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:14> col:14 implicit used __begin1 'int *':'int *' cinit
+ // CHECK-NEXT: CXXMemberCallExpr 0x{{[^ ]*}} <col:14> 'int *'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:14> '<bound member function type>' .begin 0x{{[^ ]*}}
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'Container' lvalue Var 0x{{[^ ]*}} '__range1' 'Container &'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:14> col:14 implicit used __end1 'int *':'int *' cinit
+ // CHECK-NEXT: CXXMemberCallExpr 0x{{[^ ]*}} <col:14> 'int *'
+ // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:14> '<bound member function type>' .end 0x{{[^ ]*}}
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'Container' lvalue Var 0x{{[^ ]*}} '__range1' 'Container &'
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:14> 'bool' '!='
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__end1' 'int *':'int *'
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue prefix '++'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:8, col:14> col:12 v 'int' cinit
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:14> 'int' lvalue prefix '*' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: NullStmt
+
+ for (int a; int v : vals)
+ ;
+ // CHECK: CXXForRangeStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:8, col:12> col:12 a 'int'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:23> col:23 implicit used __range1 'int (&)[10]' cinit
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:23> 'int [10]' lvalue Var 0x{{[^ ]*}} 'vals' 'int [10]'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:21> col:21 implicit used __begin1 'int *':'int *' cinit
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int [10]' lvalue Var 0x{{[^ ]*}} '__range1' 'int (&)[10]'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:21, col:23> col:21 implicit used __end1 'int *':'int *' cinit
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:21, col:23> 'int *' '+'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int [10]' lvalue Var 0x{{[^ ]*}} '__range1' 'int (&)[10]'
+ // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:23> 'long' 10
+ // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} <col:21> 'bool' '!='
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__end1' 'int *':'int *'
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:21> 'int *':'int *' lvalue prefix '++'
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: DeclStmt
+ // CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:15, col:21> col:19 v 'int' cinit
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:21> 'int' lvalue prefix '*' cannot overflow
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:21> 'int *':'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *':'int *'
+ // CHECK-NEXT: NullStmt
+}
diff --git a/test/Misc/ast-dump-stmt.m b/test/AST/ast-dump-stmt.m
index 8c0ca897e511..8c0ca897e511 100644
--- a/test/Misc/ast-dump-stmt.m
+++ b/test/AST/ast-dump-stmt.m
diff --git a/test/AST/ast-dump-template-decls.cpp b/test/AST/ast-dump-template-decls.cpp
new file mode 100644
index 000000000000..a1f355b4da0d
--- /dev/null
+++ b/test/AST/ast-dump-template-decls.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck -strict-whitespace %s
+
+template <typename Ty>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <{{.*}}:1, line:[[@LINE+2]]:10> col:6 a
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:20> col:20 referenced typename depth 0 index 0 Ty
+void a(Ty);
+
+template <typename... Ty>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:13> col:6 b
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:23> col:23 referenced typename depth 0 index 0 ... Ty
+void b(Ty...);
+
+template <typename Ty, typename Uy>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:14> col:6 c
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:20> col:20 referenced typename depth 0 index 0 Ty
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <col:24, col:33> col:33 referenced typename depth 0 index 1 Uy
+void c(Ty, Uy);
+
+template <>
+void c<float, int>(float, int);
+// CHECK: FunctionDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-2]]:1, line:[[@LINE-1]]:30> col:6 c 'void (float, int)'
+// CHECK: TemplateArgument type 'float'
+// CHECK: TemplateArgument type 'int'
+
+template <typename Ty, template<typename> typename Uy>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+4]]:18> col:6 d
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:20> col:20 referenced typename depth 0 index 0 Ty
+// CHECK-NEXT: TemplateTemplateParmDecl 0x{{[^ ]*}} <col:24, col:52> col:52 depth 0 index 1 Uy
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <col:33> col:33 typename depth 1 index 0
+void d(Ty, Uy<Ty>);
+
+template <class Ty>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:10> col:6 e
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:17> col:17 referenced class depth 0 index 0 Ty
+void e(Ty);
+
+template <int N>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:17> col:6 f
+// CHECK-NEXT: NonTypeTemplateParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:15> col:15 referenced 'int' depth 0 index 0 N
+void f(int i = N);
+
+template <typename Ty = int>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:10> col:6 g
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:25> col:20 referenced typename depth 0 index 0 Ty
+// CHECK-NEXT: TemplateArgument type 'int'
+void g(Ty);
+
+template <typename = void>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:8> col:6 h
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:22> col:11 typename depth 0 index 0
+// CHECK-NEXT: TemplateArgument type 'void'
+void h();
+
+template <typename Ty>
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:11> col:8 R
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:20> col:20 typename depth 0 index 0 Ty
+// CHECK: ClassTemplateSpecialization 0x{{[^ ]*}} 'R'
+struct R {};
+
+template <>
+// CHECK: ClassTemplateSpecializationDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:16> col:8 struct R definition
+// CHECK: TemplateArgument type 'int'
+struct R<int> {};
+
+template <typename Ty, class Uy>
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+3]]:11> col:8 S
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:20> col:20 typename depth 0 index 0 Ty
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <col:24, col:30> col:30 class depth 0 index 1 Uy
+struct S {};
+
+template <typename Ty>
+// CHECK: ClassTemplatePartialSpecializationDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+4]]:20> col:8 struct S definition
+// CHECK: TemplateArgument type 'type-parameter-0-0'
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-4]]:11, col:20> col:20 referenced typename depth 0 index 0 Ty
+struct S<Ty, int> {};
+
+template <auto>
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:11> col:8 T
+// CHECK-NEXT: NonTypeTemplateParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11> col:15 'auto' depth 0 index 0
+struct T {};
+
+template <decltype(auto)>
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:11> col:8 U
+// CHECK-NEXT: NonTypeTemplateParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11> col:25 'decltype(auto)' depth 0 index 0
+struct U {};
+
+template <typename Ty>
+// CHECK: ClassTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+7]]:1> line:[[@LINE+2]]:8 V
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:20> col:20 typename depth 0 index 0 Ty
+struct V {
+ template <typename Uy>
+ // CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+2]]:10> col:8 f
+ // CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:13, col:22> col:22 typename depth 1 index 0 Uy
+ void f();
+};
+
+template <typename Ty>
+template <typename Uy>
+// CHECK: FunctionTemplateDecl 0x{{[^ ]*}} parent 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:18> col:13 f
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:20> col:20 typename depth 1 index 0 Uy
+void V<Ty>::f() {}
diff --git a/test/Misc/ast-dump-templates.cpp b/test/AST/ast-dump-templates.cpp
index 89feee75268a..89feee75268a 100644
--- a/test/Misc/ast-dump-templates.cpp
+++ b/test/AST/ast-dump-templates.cpp
diff --git a/test/Misc/ast-dump-wchar.cpp b/test/AST/ast-dump-wchar.cpp
index 339295c133d1..339295c133d1 100644
--- a/test/Misc/ast-dump-wchar.cpp
+++ b/test/AST/ast-dump-wchar.cpp
diff --git a/test/AST/ast-print-attr.c b/test/AST/ast-print-attr.c
new file mode 100644
index 000000000000..223e27b39790
--- /dev/null
+++ b/test/AST/ast-print-attr.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -ast-print -x objective-c++ -fms-extensions %s -o - | FileCheck %s
+
+// CHECK: using A = __kindof id (*)[1];
+using A = __kindof id (*)[1];
+
+// CHECK: using B = int ** __ptr32 *[3];
+using B = int ** __ptr32 *[3];
+
+// FIXME: This is the wrong spelling for the attribute.
+// FIXME: Too many parens here!
+// CHECK: using C = int ((*))() __attribute__((cdecl));
+using C = int (*)() [[gnu::cdecl]];
diff --git a/test/Misc/ast-print-bool.c b/test/AST/ast-print-bool.c
index 05519bcd4e54..05519bcd4e54 100644
--- a/test/Misc/ast-print-bool.c
+++ b/test/AST/ast-print-bool.c
diff --git a/test/Misc/ast-print-char-literal.cpp b/test/AST/ast-print-char-literal.cpp
index 614b3ca9d73c..614b3ca9d73c 100644
--- a/test/Misc/ast-print-char-literal.cpp
+++ b/test/AST/ast-print-char-literal.cpp
diff --git a/test/Misc/ast-print-enum-decl.c b/test/AST/ast-print-enum-decl.c
index fba931344285..fba931344285 100644
--- a/test/Misc/ast-print-enum-decl.c
+++ b/test/AST/ast-print-enum-decl.c
diff --git a/test/Misc/ast-print-objectivec.m b/test/AST/ast-print-objectivec.m
index 05a0a5d4aa74..05a0a5d4aa74 100644
--- a/test/Misc/ast-print-objectivec.m
+++ b/test/AST/ast-print-objectivec.m
diff --git a/test/Misc/ast-print-out-of-line-func.cpp b/test/AST/ast-print-out-of-line-func.cpp
index 7d42f1f4037f..7d42f1f4037f 100644
--- a/test/Misc/ast-print-out-of-line-func.cpp
+++ b/test/AST/ast-print-out-of-line-func.cpp
diff --git a/test/Misc/ast-print-pragmas-xfail.cpp b/test/AST/ast-print-pragmas-xfail.cpp
index 69ba48d0de29..69ba48d0de29 100644
--- a/test/Misc/ast-print-pragmas-xfail.cpp
+++ b/test/AST/ast-print-pragmas-xfail.cpp
diff --git a/test/Misc/ast-print-pragmas.cpp b/test/AST/ast-print-pragmas.cpp
index f1a7b2479b6b..a87be2a3403f 100644
--- a/test/Misc/ast-print-pragmas.cpp
+++ b/test/AST/ast-print-pragmas.cpp
@@ -1,11 +1,8 @@
// RUN: %clang_cc1 -ast-print %s -o - | FileCheck %s
// RUN: %clang_cc1 -DMS_EXT -fsyntax-only -fms-extensions %s -triple x86_64-pc-win32 -ast-print | FileCheck %s --check-prefix=MS-EXT
-// FIXME: A bug in ParsedAttributes causes the order of the attributes to be
-// reversed. The checks are consequently in the reverse order below.
-
-// CHECK: #pragma clang loop interleave_count(8){{$}}
-// CHECK-NEXT: #pragma clang loop vectorize_width(4)
+// CHECK: #pragma clang loop vectorize_width(4)
+// CHECK-NEXT: #pragma clang loop interleave_count(8){{$}}
void test(int *List, int Length) {
int i = 0;
@@ -17,9 +14,9 @@ void test(int *List, int Length) {
i++;
}
-// CHECK: #pragma clang loop interleave(disable)
+// CHECK: #pragma clang loop distribute(disable)
// CHECK-NEXT: #pragma clang loop vectorize(enable)
-// CHECK-NEXT: #pragma clang loop distribute(disable)
+// CHECK-NEXT: #pragma clang loop interleave(disable)
#pragma clang loop distribute(disable)
#pragma clang loop vectorize(enable)
@@ -30,9 +27,9 @@ void test(int *List, int Length) {
i++;
}
-// CHECK: #pragma clang loop interleave(enable)
+// CHECK: #pragma clang loop distribute(enable)
// CHECK-NEXT: #pragma clang loop vectorize(disable)
-// CHECK-NEXT: #pragma clang loop distribute(enable)
+// CHECK-NEXT: #pragma clang loop interleave(enable)
#pragma clang loop distribute(enable)
#pragma clang loop vectorize(disable)
@@ -52,8 +49,8 @@ void test_nontype_template_param(int *List, int Length) {
}
}
-// CHECK: #pragma clang loop interleave_count(I)
// CHECK: #pragma clang loop vectorize_width(V)
+// CHECK: #pragma clang loop interleave_count(I)
void test_templates(int *List, int Length) {
test_nontype_template_param<2, 4>(List, Length);
diff --git a/test/Misc/ast-print-record-decl.c b/test/AST/ast-print-record-decl.c
index c27fdf42f337..c27fdf42f337 100644
--- a/test/Misc/ast-print-record-decl.c
+++ b/test/AST/ast-print-record-decl.c
diff --git a/test/Misc/attr-print-emit.cpp b/test/AST/attr-print-emit.cpp
index cc7413baf10e..cc7413baf10e 100644
--- a/test/Misc/attr-print-emit.cpp
+++ b/test/AST/attr-print-emit.cpp
diff --git a/test/Sema/attr-target-ast.c b/test/AST/attr-target-ast.c
index 6e8497ea9c8d..6e8497ea9c8d 100644
--- a/test/Sema/attr-target-ast.c
+++ b/test/AST/attr-target-ast.c
diff --git a/test/SemaCXX/auto-pragma.cpp b/test/AST/auto-pragma.cpp
index 1cd0781fe9a7..1cd0781fe9a7 100644
--- a/test/SemaCXX/auto-pragma.cpp
+++ b/test/AST/auto-pragma.cpp
diff --git a/test/SemaObjC/bool-type.m b/test/AST/bool-type.m
index 830a7ef0614f..830a7ef0614f 100644
--- a/test/SemaObjC/bool-type.m
+++ b/test/AST/bool-type.m
diff --git a/test/Sema/builtins-arm-strex-rettype.c b/test/AST/builtins-arm-strex-rettype.c
index 4ee96ce3277e..4ee96ce3277e 100644
--- a/test/Sema/builtins-arm-strex-rettype.c
+++ b/test/AST/builtins-arm-strex-rettype.c
diff --git a/test/AST/c-casts.c b/test/AST/c-casts.c
new file mode 100644
index 000000000000..c3a58ed8274c
--- /dev/null
+++ b/test/AST/c-casts.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -w -ast-dump %s | FileCheck %s
+
+// The cast construction code both for implicit and c-style casts is very
+// different in C vs C++. This file is intended to test the C behavior.
+
+// TODO: add tests covering the rest of the code in
+// Sema::CheckAssignmentConstraints and Sema::PrepareScalarCast
+
+// CHECK-LABEL: FunctionDecl {{.*}} cast_cvr_pointer
+void cast_cvr_pointer(char volatile * __restrict * const * p) {
+ char*** x;
+ // CHECK: ImplicitCastExpr {{.*}} 'char ***' <NoOp>
+ x = p;
+ // CHECK: CStyleCastExpr {{.*}} 'char ***' <NoOp>
+ x = (char***)p;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} cast_pointer_type
+void cast_pointer_type(char *p) {
+ void *x;
+ // CHECK: ImplicitCastExpr {{.*}} 'void *' <BitCast>
+ x = p;
+ // CHECK: CStyleCastExpr {{.*}} 'void *' <BitCast>
+ x = (void*)p;
+}
diff --git a/test/SemaObjC/category-attribute.m b/test/AST/category-attribute.m
index 7efe3df00ec8..7efe3df00ec8 100644
--- a/test/SemaObjC/category-attribute.m
+++ b/test/AST/category-attribute.m
diff --git a/test/SemaCXX/coroutine-source-location-crash.cpp b/test/AST/coroutine-source-location-crash.cpp
index 04fb1d45c524..04fb1d45c524 100644
--- a/test/SemaCXX/coroutine-source-location-crash.cpp
+++ b/test/AST/coroutine-source-location-crash.cpp
diff --git a/test/OpenMP/dump.cpp b/test/AST/dump.cpp
index 812afb72f680..b460e9325e2d 100644
--- a/test/OpenMP/dump.cpp
+++ b/test/AST/dump.cpp
@@ -13,14 +13,14 @@ int ga, gb;
#pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
-// CHECK: |-OMPDeclareReductionDecl {{.+}} <line:12:35> col:35 operator+ 'int' combiner
+// CHECK: |-OMPDeclareReductionDecl {{.+}} <line:[[@LINE-4]]:35> col:35 operator+ 'int' combiner 0x{{.+}}
// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int'
// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'int' lvalue Var {{.+}} 'omp_out' 'int'
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <LValueToRValue>
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'int' lvalue Var {{.+}} 'omp_in' 'int'
// CHECK-NEXT: | |-VarDecl {{.+}} <col:35> col:35 implicit used omp_in 'int'
// CHECK-NEXT: | `-VarDecl {{.+}} <col:35> col:35 implicit used omp_out 'int'
-// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <col:40> col:40 operator+ 'char' combiner
+// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <col:40> col:40 operator+ 'char' combiner 0x{{.+}}
// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'char' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int'
// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'char' lvalue Var {{.+}} 'omp_out' 'char'
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <IntegralCast>
@@ -28,11 +28,18 @@ int ga, gb;
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'char' lvalue Var {{.+}} 'omp_in' 'char'
// CHECK-NEXT: | |-VarDecl {{.+}} <col:40> col:40 implicit used omp_in 'char'
// CHECK-NEXT: | `-VarDecl {{.+}} <col:40> col:40 implicit used omp_out 'char'
-// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <line:14:37> col:37 fun 'float' combiner initializer
+// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <line:[[@LINE-17]]:37> col:37 fun 'float' combiner 0x{{.+}} initializer 0x{{.+}}
// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:45, col:56> 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float'
// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:45> 'float' lvalue Var {{.+}} 'omp_out' 'float'
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:56> 'float' <LValueToRValue>
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:56> 'float' lvalue Var {{.+}} 'omp_in' 'float'
+// CHECK-NEXT: | |-BinaryOperator {{.+}} <col:76, col:98> 'float' lvalue '='
+// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:76> 'float' lvalue Var {{.+}} 'omp_priv' 'float'
+// CHECK-NEXT: | | `-BinaryOperator {{.+}} <col:87, col:98> 'float' '+'
+// CHECK-NEXT: | | |-ImplicitCastExpr {{.+}} <col:87> 'float' <LValueToRValue>
+// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} <col:87> 'float' lvalue Var {{.+}} 'omp_orig' 'float'
+// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:98> 'float' <IntegralToFloating>
+// CHECK-NEXT: | | `-IntegerLiteral {{.+}} <col:98> 'int' 15
struct S {
int a, b;
@@ -43,7 +50,7 @@ struct S {
}
};
-// CHECK: | `-OMPParallelForDirective {{.+}} {{<line:40:9, col:80>|<col:9, col:80>}}
+// CHECK: | `-OMPParallelForDirective {{.+}} {{<line:.+:9, col:80>|<col:9, col:80>}}
// CHECK-NEXT: | |-OMPDefaultClause {{.+}} <col:26, col:38>
// CHECK-NEXT: | |-OMPPrivateClause {{.+}} <col:40, col:49>
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:48> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
@@ -53,19 +60,19 @@ struct S {
// CHECK-NEXT: | |-OMPScheduleClause {{.+}} <col:61, col:79>
// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:78> 'int' <LValueToRValue>
// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:78> 'int' lvalue OMPCapturedExpr {{.+}} '.capture_expr.' 'int'
-// CHECK-NEXT: | `-CapturedStmt {{.+}} <line:41:5, line:42:9>
+// CHECK-NEXT: | `-CapturedStmt {{.+}} <line:[[@LINE-15]]:5, line:[[@LINE-14]]:9>
// CHECK-NEXT: | |-CapturedDecl {{.+}} <<invalid sloc>> <invalid sloc>
-// CHECK-NEXT: | | |-ForStmt {{.+}} <line:41:5, line:42:9>
-// CHECK: | | | `-UnaryOperator {{.+}} <line:42:7, col:9> 'int' lvalue prefix '++'
+// CHECK-NEXT: | | |-ForStmt {{.+}} <line:[[@LINE-17]]:5, line:[[@LINE-16]]:9>
+// CHECK: | | | `-UnaryOperator {{.+}} <line:[[@LINE-17]]:7, col:9> 'int' lvalue prefix '++'
// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} <col:9> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
#pragma omp declare simd
#pragma omp declare simd inbranch
void foo();
-// CHECK: |-FunctionDecl {{.+}} <line:64:1, col:10> col:6 foo 'void ()'
-// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:63:9, col:34> Implicit BS_Inbranch
-// CHECK: `-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:25> Implicit BS_Undefined
+// CHECK: |-FunctionDecl {{.+}} <line:[[@LINE-2]]:1, col:10> col:6 foo 'void ()'
+// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:[[@LINE-4]]:9, col:34> Implicit BS_Inbranch
+// CHECK: `-OMPDeclareSimdDeclAttr {{.+}} <line:[[@LINE-6]]:9, col:25> Implicit BS_Undefined
#pragma omp declare target
int bar() {
@@ -74,11 +81,11 @@ int bar() {
}
#pragma omp end declare target
-// CHECK: `-FunctionDecl {{.+}} <line:71:1, line:74:1> line:71:5 bar 'int ()'
-// CHECK-NEXT: |-CompoundStmt {{.+}} <col:11, line:74:1>
-// CHECK-NEXT: | |-DeclStmt {{.+}} <line:72:3, col:8>
+// CHECK: `-FunctionDecl {{.+}} <line:[[@LINE-6]]:1, line:[[@LINE-3]]:1> line:[[@LINE-6]]:5 bar 'int ()'
+// CHECK-NEXT: |-CompoundStmt {{.+}} <col:11, line:[[@LINE-4]]:1>
+// CHECK-NEXT: | |-DeclStmt {{.+}} <line:[[@LINE-7]]:3, col:8>
// CHECK-NEXT: | | `-VarDecl {{.+}} <col:3, col:7> col:7 used f 'int'
-// CHECK-NEXT: | `-ReturnStmt {{.+}} <line:73:3, col:10>
+// CHECK-NEXT: | `-ReturnStmt {{.+}} <line:[[@LINE-8]]:3, col:10>
// CHECK-NEXT: | `-ImplicitCastExpr {{.+}} <col:10> 'int' <LValueToRValue>
// CHECK-NEXT: | `-DeclRefExpr {{.+}} <col:10> 'int' lvalue Var {{.+}} 'f' 'int'
// CHECK-NEXT: `-OMPDeclareTargetDeclAttr {{.+}} <<invalid sloc>> Implicit MT_To
diff --git a/test/SemaObjC/finally-msvc.m b/test/AST/finally-msvc.m
index 5db08a7f7100..5db08a7f7100 100644
--- a/test/SemaObjC/finally-msvc.m
+++ b/test/AST/finally-msvc.m
diff --git a/test/Frontend/fixed_point.c b/test/AST/fixed_point.c
index 3a67718fba8e..3a67718fba8e 100644
--- a/test/Frontend/fixed_point.c
+++ b/test/AST/fixed_point.c
diff --git a/test/AST/fixed_point_to_string.c b/test/AST/fixed_point_to_string.c
new file mode 100644
index 000000000000..ad71d1024f53
--- /dev/null
+++ b/test/AST/fixed_point_to_string.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -ast-dump -ffixed-point %s | FileCheck %s
+// RUN: %clang_cc1 -ast-dump -ffixed-point -fpadding-on-unsigned-fixed-point %s | FileCheck %s
+
+/**
+ * Check the same values are printed in the AST regardless of if unsigned types
+ * have the same number of fractional bits as signed types.
+ */
+
+unsigned short _Accum u_short_accum = 0.5uhk;
+unsigned _Accum u_accum = 0.5uk;
+unsigned long _Accum u_long_accum = 0.5ulk;
+unsigned short _Fract u_short_fract = 0.5uhr;
+unsigned _Fract u_fract = 0.5ur;
+unsigned long _Fract u_long_fract = 0.5ulr;
+
+//CHECK: FixedPointLiteral {{.*}} 'unsigned short _Accum' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned _Accum' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned long _Accum' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned short _Fract' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned _Fract' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned long _Fract' 0.5
diff --git a/test/Frontend/float16.cpp b/test/AST/float16.cpp
index fa00eae75360..aa65270c75d4 100644
--- a/test/Frontend/float16.cpp
+++ b/test/AST/float16.cpp
@@ -1,326 +1,326 @@
-// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace
-// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace
-
-/* Various contexts where type _Float16 can appear. */
-
-/* Namespace */
-namespace {
- _Float16 f1n;
- _Float16 f2n = 33.f16;
- _Float16 arr1n[10];
- _Float16 arr2n[] = { 1.2, 3.0, 3.e4 };
- const volatile _Float16 func1n(const _Float16 &arg) {
- return arg + f2n + arr1n[4] - arr2n[1];
- }
-}
-
-//CHECK: |-NamespaceDecl
-//CHECK-NEXT: | |-VarDecl {{.*}} f1n '_Float16'
-//CHECK-NEXT: | |-VarDecl {{.*}} f2n '_Float16' cinit
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 3.300000e+01
-//CHECK-NEXT: | |-VarDecl {{.*}} arr1n '_Float16 [10]'
-//CHECK-NEXT: | |-VarDecl {{.*}} arr2n '_Float16 [3]' cinit
-//CHECK-NEXT: | | `-InitListExpr {{.*}} '_Float16 [3]'
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+04
-//CHECK-NEXT: | `-FunctionDecl {{.*}} func1n 'const volatile _Float16 (const _Float16 &)'
-
-/* File */
-_Float16 f1f;
-_Float16 f2f = 32.4;
-_Float16 arr1f[10];
-_Float16 arr2f[] = { -1.2, -3.0, -3.e4 };
-_Float16 func1f(_Float16 arg);
-
-//CHECK: |-VarDecl {{.*}} f1f '_Float16'
-//CHECK-NEXT: |-VarDecl {{.*}} f2f '_Float16' cinit
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.240000e+01
-//CHECK-NEXT: |-VarDecl {{.*}} arr1f '_Float16 [10]'
-//CHECK-NEXT: |-VarDecl {{.*}} arr2f '_Float16 [3]' cinit
-//CHECK-NEXT: | `-InitListExpr {{.*}} '_Float16 [3]'
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.000000e+04
-//CHECK-NEXT: |-FunctionDecl {{.*}} func1f '_Float16 (_Float16)'
-//CHECK-NEXT: | `-ParmVarDecl {{.*}} arg '_Float16'
-
-
-// Mixing __fp16 and Float16 types:
-// The _Float16 type is first converted to __fp16 type and then the operation
-// is completed as if both operands were of __fp16 type.
-
-__fp16 B = -0.1;
-auto C = -1.0f16 + B;
-
-// When we do *not* have native half types, we expect __fp16 to be promoted to
-// float, and consequently also _Float16 promotions to float:
-
-//CHECK: -VarDecl {{.*}} used B '__fp16' cinit
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
-//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01
-//CHECK-NEXT: |-VarDecl {{.*}} C 'float':'float' cinit
-//CHECK-NEXT: | `-BinaryOperator {{.*}} 'float' '+'
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'
-
-// When do have native half types, we expect to see promotions to fp16:
-
-//CHECK-NATIVE: |-VarDecl {{.*}} used B '__fp16' cinit
-//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
-//CHECK-NATIVE: | `-UnaryOperator {{.*}} 'double' prefix '-'
-//CHECK-NATIVE: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01
-//CHECK-NATIVE: |-VarDecl {{.*}} C '__fp16':'__fp16' cinit
-//CHECK-NATIVE: | `-BinaryOperator {{.*}} '__fp16' '+'
-//CHECK-NATIVE: | |-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
-//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
-//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
-//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
-//CHECK-NATIVE: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'
-
-
-/* Class */
-
-class C1 {
- _Float16 f1c;
- static const _Float16 f2c;
- volatile _Float16 f3c;
-public:
- C1(_Float16 arg) : f1c(arg), f3c(arg) { }
- _Float16 func1c(_Float16 arg ) {
- return f1c + arg;
- }
- static _Float16 func2c(_Float16 arg) {
- return arg * C1::f2c;
- }
-};
-
-//CHECK: |-CXXRecordDecl {{.*}} referenced class C1 definition
-//CHECK: | |-CXXRecordDecl {{.*}} implicit referenced class C1
-//CHECK-NEXT: | |-FieldDecl {{.*}} referenced f1c '_Float16'
-//CHECK-NEXT: | |-VarDecl {{.*}} used f2c 'const _Float16' static
-//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile _Float16'
-//CHECK-NEXT: | |-AccessSpecDecl
-//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} used C1 'void (_Float16)
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
-//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f1c' '_Float16'
-//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
-//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16'
-//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
-//CHECK-NEXT: | | `-CompoundStmt
-//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func1c '_Float16 (_Float16)
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
-//CHECK-NEXT: | | `-CompoundStmt
-//CHECK-NEXT: | | `-ReturnStmt
-//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '+'
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}}
-//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'C1 *' this
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
-//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
-//CHECK-NEXT: | | `-CompoundStmt
-//CHECK-NEXT: | | `-ReturnStmt
-//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '*'
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16'
-
-
-/* Template */
-
-template <class C> C func1t(C arg) {
- return arg * 2.f16;
-}
-
-//CHECK: |-FunctionTemplateDecl {{.*}} func1t
-//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} C
-//CHECK-NEXT: | |-FunctionDecl {{.*}} func1t 'C (C)'
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} referenced arg 'C'
-//CHECK-NEXT: | | `-CompoundStmt
-//CHECK-NEXT: | | `-ReturnStmt
-//CHECK-NEXT: | | `-BinaryOperator {{.*}} '<dependent type>' '*'
-//CHECK-NEXT: | | |-DeclRefExpr {{.*}} 'C' lvalue ParmVar {{.*}} 'arg' 'C'
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00
-//CHECK-NEXT: | `-FunctionDecl {{.*}} used func1t '_Float16 (_Float16)'
-//CHECK-NEXT: | |-TemplateArgument type '_Float16'
-//CHECK-NEXT: | |-ParmVarDecl {{.*}} used arg '_Float16':'_Float16'
-//CHECK-NEXT: | `-CompoundStmt
-//CHECK-NEXT: | `-ReturnStmt
-//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '*'
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16':'_Float16' <LValueToRValue>
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16'
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00
-
-
-template <class C> struct S1 {
- C mem1;
-};
-
-//CHECK: |-ClassTemplateDecl {{.*}} S1
-//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 C
-//CHECK-NEXT: | |-CXXRecordDecl {{.*}} struct S1 definition
-//CHECK: | | |-CXXRecordDecl {{.*}} implicit struct S1
-//CHECK-NEXT: | | `-FieldDecl {{.*}} mem1 'C'
-//CHECK-NEXT: | `-ClassTemplateSpecialization {{.*}} 'S1'
-
-template <> struct S1<_Float16> {
- _Float16 mem2;
-};
-
-
-/* Local */
-
-extern int printf (const char *__restrict __format, ...);
-
-int main(void) {
- _Float16 f1l = 1e3f16;
-//CHECK: | `-VarDecl {{.*}} used f1l '_Float16' cinit
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+03
-
- _Float16 f2l = -0.f16;
-//CHECK: | `-VarDecl {{.*}} used f2l '_Float16' cinit
-//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' prefix '-'
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00
-
- _Float16 f3l = 1.000976562;
-//CHECK: | `-VarDecl {{.*}} used f3l '_Float16' cinit
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00
-
- C1 c1(f1l);
-//CHECK: | `-VarDecl{{.*}} used c1 'C1' callinit
-//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'C1' 'void (_Float16)
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16'
-
- S1<_Float16> s1 = { 132.f16 };
-//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'S1<_Float16>' cinit
-//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'S1<_Float16>'
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02
-
- _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
- func1t(f1l) + s1.mem2 - f1n + f2n;
-//CHECK: | `-VarDecl {{.*}} used f4l '_Float16' cinit
-//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '+'
-//CHECK-NEXT: | |-BinaryOperator {{.*}} '_Float16' '-'
-//CHECK-NEXT: | | |-BinaryOperator {{.*}} '_Float16' '+'
-//CHECK-NEXT: | | | |-BinaryOperator {{.*}} '_Float16' '+'
-//CHECK-NEXT: | | | | |-BinaryOperator {{.*}} '_Float16' '+'
-//CHECK-NEXT: | | | | | |-BinaryOperator {{.*}} '_Float16' '+'
-//CHECK-NEXT: | | | | | | |-BinaryOperator {{.*}} '_Float16' '+'
-//CHECK-NEXT: | | | | | | | |-CallExpr {{.*}} '_Float16'
-//CHECK-NEXT: | | | | | | | | |-ImplicitCastExpr {{.*}} 'const volatile _Float16 (*)(const _Float16 &)' <FunctionToPointerDecay>
-//CHECK-NEXT: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)'
-//CHECK-NEXT: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue <NoOp>
-//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
-//CHECK-NEXT: | | | | | | | `-CallExpr {{.*}} '_Float16'
-//CHECK-NEXT: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
-//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)'
-//CHECK-NEXT: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
-//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16'
-//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '<bound member function type>' .func1c {{.*}}
-//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
-//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
-//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16'
-//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
-//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}}
-//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
-//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
-//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16'
-//CHECK-NEXT: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
-//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
-//CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
-//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}}
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'S1<_Float16>'
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16'
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
-
- auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l);
-//CHECK: | |-VarDecl {{.*}} f5l '_Float16':'_Float16' cinit
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
-//CHECK-NEXT: | |-VarDecl {{.*}} f6l '_Float16 *' cinit
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16 *' prefix '&'
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
-//CHECK-NEXT: | `-VarDecl {{.*}} f7l '_Float16':'_Float16' cinit
-//CHECK-NEXT: | `-CallExpr {{.*}} '_Float16':'_Float16'
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
-
- _Float16 f8l = f4l++;
-//CHECK: | `-VarDecl {{.*}} f8l '_Float16' cinit
-//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' postfix '++'
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f4l' '_Float16'
-
- _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 };
-//CHECK: `-VarDecl {{.*}} arr1l '_Float16 [3]' cinit
-//CHECK-NEXT: `-InitListExpr {{.*}} '_Float16 [3]'
-//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
-//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00
-//CHECK-NEXT: `-UnaryOperator {{.*}} '_Float16' prefix '-'
-//CHECK-NEXT: `-FloatingLiteral {{.*}} '_Float16' 1.100000e+01
-
- float cvtf = f2n;
-//CHECK: `-VarDecl {{.*}} cvtf 'float' cinit
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
-
- double cvtd = f2n;
-//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' <FloatingCast>
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
-
- long double cvtld = f2n;
-//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'long double' <FloatingCast>
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
-//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
-
- _Float16 f2h = 42.0f;
-//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: `-FloatingLiteral {{.*}} 'float' 4.200000e+01
-
- _Float16 d2h = 42.0;
-//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: `-FloatingLiteral {{.*}} 'double' 4.200000e+01
-
- _Float16 ld2h = 42.0l;
-//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
-//CHECK-NEXT: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01
-}
+// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace
+// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace
+
+/* Various contexts where type _Float16 can appear. */
+
+/* Namespace */
+namespace {
+ _Float16 f1n;
+ _Float16 f2n = 33.f16;
+ _Float16 arr1n[10];
+ _Float16 arr2n[] = { 1.2, 3.0, 3.e4 };
+ const volatile _Float16 func1n(const _Float16 &arg) {
+ return arg + f2n + arr1n[4] - arr2n[1];
+ }
+}
+
+//CHECK: |-NamespaceDecl
+//CHECK-NEXT: | |-VarDecl {{.*}} f1n '_Float16'
+//CHECK-NEXT: | |-VarDecl {{.*}} f2n '_Float16' cinit
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 3.300000e+01
+//CHECK-NEXT: | |-VarDecl {{.*}} arr1n '_Float16 [10]'
+//CHECK-NEXT: | |-VarDecl {{.*}} arr2n '_Float16 [3]' cinit
+//CHECK-NEXT: | | `-InitListExpr {{.*}} '_Float16 [3]'
+//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
+//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+04
+//CHECK-NEXT: | `-FunctionDecl {{.*}} func1n 'const volatile _Float16 (const _Float16 &)'
+
+/* File */
+_Float16 f1f;
+_Float16 f2f = 32.4;
+_Float16 arr1f[10];
+_Float16 arr2f[] = { -1.2, -3.0, -3.e4 };
+_Float16 func1f(_Float16 arg);
+
+//CHECK: |-VarDecl {{.*}} f1f '_Float16'
+//CHECK-NEXT: |-VarDecl {{.*}} f2f '_Float16' cinit
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.240000e+01
+//CHECK-NEXT: |-VarDecl {{.*}} arr1f '_Float16 [10]'
+//CHECK-NEXT: |-VarDecl {{.*}} arr2f '_Float16 [3]' cinit
+//CHECK-NEXT: | `-InitListExpr {{.*}} '_Float16 [3]'
+//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
+//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.000000e+04
+//CHECK-NEXT: |-FunctionDecl {{.*}} func1f '_Float16 (_Float16)'
+//CHECK-NEXT: | `-ParmVarDecl {{.*}} arg '_Float16'
+
+
+// Mixing __fp16 and Float16 types:
+// The _Float16 type is first converted to __fp16 type and then the operation
+// is completed as if both operands were of __fp16 type.
+
+__fp16 B = -0.1;
+auto C = -1.0f16 + B;
+
+// When we do *not* have native half types, we expect __fp16 to be promoted to
+// float, and consequently also _Float16 promotions to float:
+
+//CHECK: -VarDecl {{.*}} used B '__fp16' cinit
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
+//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01
+//CHECK-NEXT: |-VarDecl {{.*}} C 'float':'float' cinit
+//CHECK-NEXT: | `-BinaryOperator {{.*}} 'float' '+'
+//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
+//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'
+
+// When do have native half types, we expect to see promotions to fp16:
+
+//CHECK-NATIVE: |-VarDecl {{.*}} used B '__fp16' cinit
+//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
+//CHECK-NATIVE: | `-UnaryOperator {{.*}} 'double' prefix '-'
+//CHECK-NATIVE: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01
+//CHECK-NATIVE: |-VarDecl {{.*}} C '__fp16':'__fp16' cinit
+//CHECK-NATIVE: | `-BinaryOperator {{.*}} '__fp16' '+'
+//CHECK-NATIVE: | |-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
+//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
+//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
+//CHECK-NATIVE: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'
+
+
+/* Class */
+
+class C1 {
+ _Float16 f1c;
+ static const _Float16 f2c;
+ volatile _Float16 f3c;
+public:
+ C1(_Float16 arg) : f1c(arg), f3c(arg) { }
+ _Float16 func1c(_Float16 arg ) {
+ return f1c + arg;
+ }
+ static _Float16 func2c(_Float16 arg) {
+ return arg * C1::f2c;
+ }
+};
+
+//CHECK: |-CXXRecordDecl {{.*}} referenced class C1 definition
+//CHECK: | |-CXXRecordDecl {{.*}} implicit referenced class C1
+//CHECK-NEXT: | |-FieldDecl {{.*}} referenced f1c '_Float16'
+//CHECK-NEXT: | |-VarDecl {{.*}} used f2c 'const _Float16' static
+//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile _Float16'
+//CHECK-NEXT: | |-AccessSpecDecl
+//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} used C1 'void (_Float16)
+//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
+//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f1c' '_Float16'
+//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
+//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16'
+//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
+//CHECK-NEXT: | | `-CompoundStmt
+//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func1c '_Float16 (_Float16)
+//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
+//CHECK-NEXT: | | `-CompoundStmt
+//CHECK-NEXT: | | `-ReturnStmt
+//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '+'
+//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}}
+//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'C1 *' this
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
+//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static
+//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
+//CHECK-NEXT: | | `-CompoundStmt
+//CHECK-NEXT: | | `-ReturnStmt
+//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '*'
+//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16'
+
+
+/* Template */
+
+template <class C> C func1t(C arg) {
+ return arg * 2.f16;
+}
+
+//CHECK: |-FunctionTemplateDecl {{.*}} func1t
+//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} C
+//CHECK-NEXT: | |-FunctionDecl {{.*}} func1t 'C (C)'
+//CHECK-NEXT: | | |-ParmVarDecl {{.*}} referenced arg 'C'
+//CHECK-NEXT: | | `-CompoundStmt
+//CHECK-NEXT: | | `-ReturnStmt
+//CHECK-NEXT: | | `-BinaryOperator {{.*}} '<dependent type>' '*'
+//CHECK-NEXT: | | |-DeclRefExpr {{.*}} 'C' lvalue ParmVar {{.*}} 'arg' 'C'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00
+//CHECK-NEXT: | `-FunctionDecl {{.*}} used func1t '_Float16 (_Float16)'
+//CHECK-NEXT: | |-TemplateArgument type '_Float16'
+//CHECK-NEXT: | |-ParmVarDecl {{.*}} used arg '_Float16':'_Float16'
+//CHECK-NEXT: | `-CompoundStmt
+//CHECK-NEXT: | `-ReturnStmt
+//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '*'
+//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16':'_Float16' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00
+
+
+template <class C> struct S1 {
+ C mem1;
+};
+
+//CHECK: |-ClassTemplateDecl {{.*}} S1
+//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 C
+//CHECK-NEXT: | |-CXXRecordDecl {{.*}} struct S1 definition
+//CHECK: | | |-CXXRecordDecl {{.*}} implicit struct S1
+//CHECK-NEXT: | | `-FieldDecl {{.*}} mem1 'C'
+//CHECK-NEXT: | `-ClassTemplateSpecialization {{.*}} 'S1'
+
+template <> struct S1<_Float16> {
+ _Float16 mem2;
+};
+
+
+/* Local */
+
+extern int printf (const char *__restrict __format, ...);
+
+int main(void) {
+ _Float16 f1l = 1e3f16;
+//CHECK: | `-VarDecl {{.*}} used f1l '_Float16' cinit
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+03
+
+ _Float16 f2l = -0.f16;
+//CHECK: | `-VarDecl {{.*}} used f2l '_Float16' cinit
+//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00
+
+ _Float16 f3l = 1.000976562;
+//CHECK: | `-VarDecl {{.*}} used f3l '_Float16' cinit
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00
+
+ C1 c1(f1l);
+//CHECK: | `-VarDecl{{.*}} used c1 'C1' callinit
+//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'C1' 'void (_Float16)
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16'
+
+ S1<_Float16> s1 = { 132.f16 };
+//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'S1<_Float16>' cinit
+//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'S1<_Float16>'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02
+
+ _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
+ func1t(f1l) + s1.mem2 - f1n + f2n;
+//CHECK: | `-VarDecl {{.*}} used f4l '_Float16' cinit
+//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '+'
+//CHECK-NEXT: | |-BinaryOperator {{.*}} '_Float16' '-'
+//CHECK-NEXT: | | |-BinaryOperator {{.*}} '_Float16' '+'
+//CHECK-NEXT: | | | |-BinaryOperator {{.*}} '_Float16' '+'
+//CHECK-NEXT: | | | | |-BinaryOperator {{.*}} '_Float16' '+'
+//CHECK-NEXT: | | | | | |-BinaryOperator {{.*}} '_Float16' '+'
+//CHECK-NEXT: | | | | | | |-BinaryOperator {{.*}} '_Float16' '+'
+//CHECK-NEXT: | | | | | | | |-CallExpr {{.*}} '_Float16'
+//CHECK-NEXT: | | | | | | | | |-ImplicitCastExpr {{.*}} 'const volatile _Float16 (*)(const _Float16 &)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)'
+//CHECK-NEXT: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue <NoOp>
+//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
+//CHECK-NEXT: | | | | | | | `-CallExpr {{.*}} '_Float16'
+//CHECK-NEXT: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)'
+//CHECK-NEXT: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
+//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16'
+//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '<bound member function type>' .func1c {{.*}}
+//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
+//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
+//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16'
+//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}}
+//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
+//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
+//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16'
+//CHECK-NEXT: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
+//CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
+//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}}
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'S1<_Float16>'
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16'
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
+
+ auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l);
+//CHECK: | |-VarDecl {{.*}} f5l '_Float16':'_Float16' cinit
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
+//CHECK-NEXT: | |-VarDecl {{.*}} f6l '_Float16 *' cinit
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16 *' prefix '&'
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
+//CHECK-NEXT: | `-VarDecl {{.*}} f7l '_Float16':'_Float16' cinit
+//CHECK-NEXT: | `-CallExpr {{.*}} '_Float16':'_Float16'
+//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
+
+ _Float16 f8l = f4l++;
+//CHECK: | `-VarDecl {{.*}} f8l '_Float16' cinit
+//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' postfix '++'
+//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f4l' '_Float16'
+
+ _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 };
+//CHECK: `-VarDecl {{.*}} arr1l '_Float16 [3]' cinit
+//CHECK-NEXT: `-InitListExpr {{.*}} '_Float16 [3]'
+//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
+//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00
+//CHECK-NEXT: `-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NEXT: `-FloatingLiteral {{.*}} '_Float16' 1.100000e+01
+
+ float cvtf = f2n;
+//CHECK: `-VarDecl {{.*}} cvtf 'float' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
+
+ double cvtd = f2n;
+//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' <FloatingCast>
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
+
+ long double cvtld = f2n;
+//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'long double' <FloatingCast>
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
+
+ _Float16 f2h = 42.0f;
+//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: `-FloatingLiteral {{.*}} 'float' 4.200000e+01
+
+ _Float16 d2h = 42.0;
+//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: `-FloatingLiteral {{.*}} 'double' 4.200000e+01
+
+ _Float16 ld2h = 42.0l;
+//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01
+}
diff --git a/test/SemaObjC/foreachtemplatized.mm b/test/AST/foreachtemplatized.mm
index ab2770a7cefb..ab2770a7cefb 100644
--- a/test/SemaObjC/foreachtemplatized.mm
+++ b/test/AST/foreachtemplatized.mm
diff --git a/test/Sema/implicit-cast-dump.c b/test/AST/implicit-cast-dump.c
index 4cd855fb1d46..4cd855fb1d46 100644
--- a/test/Sema/implicit-cast-dump.c
+++ b/test/AST/implicit-cast-dump.c
diff --git a/test/Sema/multistep-explicit-cast.c b/test/AST/multistep-explicit-cast.c
index aeb591961812..aeb591961812 100644
--- a/test/Sema/multistep-explicit-cast.c
+++ b/test/AST/multistep-explicit-cast.c
diff --git a/test/SemaCXX/multistep-explicit-cast.cpp b/test/AST/multistep-explicit-cast.cpp
index 58466791354c..58466791354c 100644
--- a/test/SemaCXX/multistep-explicit-cast.cpp
+++ b/test/AST/multistep-explicit-cast.cpp
diff --git a/test/Parser/objc-default-ctor-init.mm b/test/AST/objc-default-ctor-init.mm
index a14a243a31cc..a14a243a31cc 100644
--- a/test/Parser/objc-default-ctor-init.mm
+++ b/test/AST/objc-default-ctor-init.mm
diff --git a/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp b/test/AST/pragma-attribute-cxx-subject-match-rules.cpp
index 18dfb43a384d..18dfb43a384d 100644
--- a/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp
+++ b/test/AST/pragma-attribute-cxx-subject-match-rules.cpp
diff --git a/test/Misc/pragma-attribute-objc-subject-match-rules.m b/test/AST/pragma-attribute-objc-subject-match-rules.m
index 09ab5e1f33a0..09ab5e1f33a0 100644
--- a/test/Misc/pragma-attribute-objc-subject-match-rules.m
+++ b/test/AST/pragma-attribute-objc-subject-match-rules.m
diff --git a/test/SemaObjC/property-atomic-bool.m b/test/AST/property-atomic-bool.m
index 4110b5e04459..4110b5e04459 100644
--- a/test/SemaObjC/property-atomic-bool.m
+++ b/test/AST/property-atomic-bool.m
diff --git a/test/Sema/rdr6094103-unordered-compare-promote.c b/test/AST/rdr6094103-unordered-compare-promote.c
index 7bb363e797c8..7bb363e797c8 100644
--- a/test/Sema/rdr6094103-unordered-compare-promote.c
+++ b/test/AST/rdr6094103-unordered-compare-promote.c
diff --git a/test/SemaCXX/sourceranges.cpp b/test/AST/sourceranges.cpp
index 58772a063915..53f2f57e6754 100644
--- a/test/SemaCXX/sourceranges.cpp
+++ b/test/AST/sourceranges.cpp
@@ -52,6 +52,13 @@ void construct() {
// CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
}
+namespace PR38987 {
+struct A { A(); };
+template <class T> void f() { T{}; }
+template void f<A>();
+// CHECK: CXXTemporaryObjectExpr {{.*}} <col:31, col:33> 'PR38987::A':'PR38987::A'
+}
+
void abort() __attribute__((noreturn));
namespace std {
diff --git a/test/SemaCXX/template-implicit-vars.cpp b/test/AST/template-implicit-vars.cpp
index 25d35fbdb84f..25d35fbdb84f 100644
--- a/test/SemaCXX/template-implicit-vars.cpp
+++ b/test/AST/template-implicit-vars.cpp
diff --git a/test/Sema/variadic-promotion.c b/test/AST/variadic-promotion.c
index 01d8e934b4eb..01d8e934b4eb 100644
--- a/test/Sema/variadic-promotion.c
+++ b/test/AST/variadic-promotion.c
diff --git a/test/ASTMerge/unnamed_fields/Inputs/il.cpp b/test/ASTMerge/unnamed_fields/Inputs/il.cpp
new file mode 100644
index 000000000000..1bb0f358dcff
--- /dev/null
+++ b/test/ASTMerge/unnamed_fields/Inputs/il.cpp
@@ -0,0 +1,3 @@
+void f(int X, int Y, bool Z) {
+ auto x = [X, Y, Z] { (void)Z; };
+}
diff --git a/test/ASTMerge/unnamed_fields/test.cpp b/test/ASTMerge/unnamed_fields/test.cpp
new file mode 100644
index 000000000000..6ae3176df4f3
--- /dev/null
+++ b/test/ASTMerge/unnamed_fields/test.cpp
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp
+// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
+// CHECK-NOT: warning: field '' declared with incompatible types in different translation units ('bool' vs. 'int')
diff --git a/test/Analysis/CFContainers.mm b/test/Analysis/CFContainers.mm
index 0a45bffe5acf..2e094d3cb7d2 100644
--- a/test/Analysis/CFContainers.mm
+++ b/test/Analysis/CFContainers.mm
@@ -1,4 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=osx.coreFoundation.containers.PointerSizedValues,osx.coreFoundation.containers.OutOfBounds -analyzer-store=region -triple x86_64-apple-darwin -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin -analyzer-output=text\
+// RUN: -analyzer-checker=osx.coreFoundation.containers.PointerSizedValues\
+// RUN: -analyzer-checker=osx.coreFoundation.containers.OutOfBounds\
+// RUN: -verify %s
typedef const struct __CFAllocator * CFAllocatorRef;
typedef const struct __CFString * CFStringRef;
@@ -94,17 +97,21 @@ CFSetRef CFSetCreate(CFAllocatorRef allocator, const void **values, CFIndex numV
#define CFSTR(cStr) ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr ""))
#define NULL __null
-// Done with the headers.
+// Done with the headers.
// Test alpha.osx.cocoa.ContainerAPI checker.
void testContainers(int **xNoWarn, CFIndex count) {
int x[] = { 1, 2, 3 };
- CFArrayRef foo = CFArrayCreate(kCFAllocatorDefault, (const void **) x, sizeof(x) / sizeof(x[0]), 0);// expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
+ CFArrayRef foo = CFArrayCreate(kCFAllocatorDefault, (const void **) x, sizeof(x) / sizeof(x[0]), 0);
+ // expected-warning@-1 {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
+ // expected-note@-2 {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
CFArrayRef fooNoWarn = CFArrayCreate(kCFAllocatorDefault, (const void **) xNoWarn, sizeof(xNoWarn) / sizeof(xNoWarn[0]), 0); // no warning
CFArrayRef fooNoWarn2 = CFArrayCreate(kCFAllocatorDefault, 0, sizeof(xNoWarn) / sizeof(xNoWarn[0]), 0);// no warning, passing in 0
CFArrayRef fooNoWarn3 = CFArrayCreate(kCFAllocatorDefault, NULL, sizeof(xNoWarn) / sizeof(xNoWarn[0]), 0);// no warning, passing in NULL
- CFSetRef set = CFSetCreate(NULL, (const void **)x, 3, &kCFTypeSetCallBacks); // expected-warning {{The second argument to 'CFSetCreate' must be a C array of pointer-sized values}}
+ CFSetRef set = CFSetCreate(NULL, (const void **)x, 3, &kCFTypeSetCallBacks);
+ // expected-warning@-1 {{The second argument to 'CFSetCreate' must be a C array of pointer-sized values}}
+ // expected-note@-2 {{The second argument to 'CFSetCreate' must be a C array of pointer-sized values}}
CFArrayRef* pairs = new CFArrayRef[count];
CFSetRef fSet = CFSetCreate(kCFAllocatorDefault, (const void**) pairs, count - 1, &kCFTypeSetCallBacks);// no warning
}
@@ -126,8 +133,13 @@ void CreateDict(int *elems) {
const CFDictionaryKeyCallBacks keyCB = kCFCopyStringDictionaryKeyCallBacks;
const CFDictionaryValueCallBacks valCB = kCFTypeDictionaryValueCallBacks;
CFDictionaryRef dict1 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, numValues, &keyCB, &valCB); // no warning
- CFDictionaryRef dict2 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)elems[0], (const void**)values, numValues, &keyCB, &valCB); //expected-warning {{The second argument to 'CFDictionaryCreate' must be a C array of}} expected-warning {{cast to 'const void **' from smaller integer type 'int'}}
- CFDictionaryRef dict3 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)elems, numValues, &keyCB, &valCB); // expected-warning {{The third argument to 'CFDictionaryCreate' must be a C array of pointer-sized values}}
+ CFDictionaryRef dict2 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)elems[0], (const void**)values, numValues, &keyCB, &valCB);
+ // expected-warning@-1 {{The second argument to 'CFDictionaryCreate' must be a C array of}}
+ // expected-note@-2 {{The second argument to 'CFDictionaryCreate' must be a C array of}}
+ // expected-warning@-3{{cast to 'const void **' from smaller integer type 'int'}}
+ CFDictionaryRef dict3 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)elems, numValues, &keyCB, &valCB);
+ // expected-warning@-1 {{The third argument to 'CFDictionaryCreate' must be a C array of pointer-sized values}}
+ // expected-note@-2 {{The third argument to 'CFDictionaryCreate' must be a C array of pointer-sized values}}
}
void OutOfBoundsSymbolicOffByOne(const void ** input, CFIndex S) {
@@ -136,6 +148,7 @@ void OutOfBoundsSymbolicOffByOne(const void ** input, CFIndex S) {
const void *s1 = CFArrayGetValueAtIndex(array, 0); // no warning
const void *s2 = CFArrayGetValueAtIndex(array, S-1); // no warning
const void *s3 = CFArrayGetValueAtIndex(array, S); // expected-warning {{Index is out of bounds}}
+ // expected-note@-1 {{Index is out of bounds}}
}
void OutOfBoundsConst(const void ** input, CFIndex S) {
@@ -144,6 +157,7 @@ void OutOfBoundsConst(const void ** input, CFIndex S) {
const void *s1 = CFArrayGetValueAtIndex(array, 0); // no warning
const void *s2 = CFArrayGetValueAtIndex(array, 2); // no warning
const void *s3 = CFArrayGetValueAtIndex(array, 5); // expected-warning {{Index is out of bounds}}
+ // expected-note@-1 {{Index is out of bounds}}
// TODO: The solver is probably not strong enough here.
CFIndex sIndex;
@@ -157,13 +171,16 @@ void OutOfBoundsZiro(const void ** input, CFIndex S) {
// The API allows to set the size to 0. Check that we don't undeflow when the size is 0.
array = CFArrayCreate(kCFAllocatorDefault, 0, 0, 0);
const void *s1 = CFArrayGetValueAtIndex(array, 0); // expected-warning {{Index is out of bounds}}
+ // expected-note@-1 {{Index is out of bounds}}
}
void TestGetCount(CFArrayRef A, CFIndex sIndex) {
- CFIndex sCount = CFArrayGetCount(A);
- if (sCount > sIndex)
+ CFIndex sCount = CFArrayGetCount(A); // expected-note{{'sCount' initialized here}}
+ if (sCount > sIndex) // expected-note{{Assuming 'sCount' is <= 'sIndex'}}
+ // expected-note@-1{{Taking false branch}}
const void *s1 = CFArrayGetValueAtIndex(A, sIndex);
const void *s2 = CFArrayGetValueAtIndex(A, sCount);// expected-warning {{Index is out of bounds}}
+ // expected-note@-1 {{Index is out of bounds}}
}
typedef void* XX[3];
@@ -179,10 +196,13 @@ void TestPointerToArray(int *elems, void *p1, void *p2, void *p3, unsigned count
CFArrayCreate(0, (const void **) &fn, count, 0); // false negative
CFArrayCreate(0, (const void **) fn, count, 0); // no warning
CFArrayCreate(0, (const void **) cp, count, 0); // expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
+ // expected-note@-1 {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
char cc[] = { 0, 2, 3 };
CFArrayCreate(0, (const void **) &cc, count, 0); // expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
+ // expected-note@-1 {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
CFArrayCreate(0, (const void **) cc, count, 0); // expected-warning {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
+ // expected-note@-1 {{The second argument to 'CFArrayCreate' must be a C array of pointer-sized}}
}
void TestUndef(CFArrayRef A, CFIndex sIndex, void* x[]) {
@@ -217,10 +237,11 @@ void TestCFMutableArrayRefEscapeViaMutableArgument(CFMutableArrayRef a) {
}
void TestCFMutableArrayRefEscapeViaImmutableArgument(CFMutableArrayRef a) {
- CFIndex aLen = CFArrayGetCount(a);
+ CFIndex aLen = CFArrayGetCount(a); // expected-note{{'aLen' initialized here}}
ArrayRefEscape(a);
// ArrayRefEscape is declared to take a CFArrayRef (i.e, an immutable array)
// so we assume it does not change the length of a.
CFArrayGetValueAtIndex(a, aLen); // expected-warning {{Index is out of bounds}}
+ // expected-note@-1 {{Index is out of bounds}}
}
diff --git a/test/Analysis/CFDateGC.m b/test/Analysis/CFDateGC.m
deleted file mode 100644
index 714e213f9577..000000000000
--- a/test/Analysis/CFDateGC.m
+++ /dev/null
@@ -1,85 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify -fobjc-gc %s -Wno-implicit-function-declaration
-
-//===----------------------------------------------------------------------===//
-// The following code is reduced using delta-debugging from
-// Foundation.h and CoreFoundation.h (Mac OS X).
-//
-// It includes the basic definitions for the test cases below.
-// Not directly including [Core]Foundation.h directly makes this test case
-// both svelte and portable to non-Mac platforms.
-//===----------------------------------------------------------------------===//
-
-typedef const void * CFTypeRef;
-void CFRelease(CFTypeRef cf);
-CFTypeRef CFRetain(CFTypeRef cf);
-CFTypeRef CFMakeCollectable(CFTypeRef cf);
-typedef const struct __CFAllocator * CFAllocatorRef;
-typedef double CFTimeInterval;
-typedef CFTimeInterval CFAbsoluteTime;
-typedef const struct __CFDate * CFDateRef;
-extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
-extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
-typedef struct objc_object {} *id;
-typedef signed char BOOL;
-static __inline__ __attribute__((always_inline)) id NSMakeCollectable(CFTypeRef cf) { return 0; }
-@protocol NSObject - (BOOL)isEqual:(id)object;
-- (oneway void)release;
-- (id)retain;
-@end
-@class NSArray;
-
-//===----------------------------------------------------------------------===//
-// Test cases.
-//===----------------------------------------------------------------------===//
-
-CFAbsoluteTime CFAbsoluteTimeGetCurrent();
-
-CFAbsoluteTime f1_use_after_release() {
- CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
- CFDateRef date = CFDateCreate(0, t);
- CFRetain(date);
- [NSMakeCollectable(date) release];
- CFDateGetAbsoluteTime(date); // no-warning
- CFRelease(date);
- t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}}
- return t;
-}
-
-// The following two test cases verifies that CFMakeCollectable is a no-op
-// in non-GC mode and a "release" in GC mode.
-CFAbsoluteTime f2_use_after_release() {
- CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
- CFDateRef date = CFDateCreate(0, t);
- CFRetain(date);
- [(id) CFMakeCollectable(date) release];
- CFDateGetAbsoluteTime(date); // no-warning
- CFRelease(date);
- t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}}
- return t;
-}
-
-CFAbsoluteTime f2_noleak() {
- CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
- CFDateRef date = CFDateCreate(0, t);
- CFRetain(date);
- [(id) CFMakeCollectable(date) release];
- CFDateGetAbsoluteTime(date); // no-warning
- t = CFDateGetAbsoluteTime(date); // no-warning
- CFRelease(date); // no-warning
- return t;
-}
-
-void f3_leak_with_gc() {
- CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); // expected-warning 2 {{leak}}
- [[(id) date retain] release];
-}
-
-// The following test case verifies that we "stop tracking" a retained object
-// when it is passed as an argument to an implicitly defined function.
-CFAbsoluteTime f4() {
- CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
- CFDateRef date = CFDateCreate(0, t);
- CFRetain(date);
- some_implicitly_defined_function_stop_tracking(date); // no-warning
- return t;
-}
diff --git a/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m b/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m
index b00d71b1a4d0..2bf86410f3ff 100644
--- a/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m
+++ b/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m
@@ -1,9 +1,15 @@
-// UNSUPPORTED: system-windows
-// RUN: %clang_analyze_cc1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
-// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP1=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
-// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP2=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
-// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP3=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
-// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP4=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify
+// RUN: %clang_analyze_cc1 -fobjc-arc -triple x86_64-darwin\
+// RUN: -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak -verify %s
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP1=1 -fobjc-arc -triple x86_64-darwin\
+// RUN: -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak -verify %s
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP2=1 -fobjc-arc -triple x86_64-darwin\
+// RUN: -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak -verify %s
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP3=1 -fobjc-arc -triple x86_64-darwin\
+// RUN: -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak -verify %s
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP4=1 -fobjc-arc -triple x86_64-darwin\
+// RUN: -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak -verify %s
+// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP5=1 -fobjc-arc -triple x86_64-darwin\
+// RUN: -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak -verify %s
#include "../Inputs/system-header-simulator-for-objc-dealloc.h"
@@ -122,3 +128,34 @@ int main() {
return 0;
}
#endif
+
+#ifdef AP5
+@class NSString;
+@class NSConstantString;
+#define CF_BRIDGED_TYPE(T) __attribute__((objc_bridge(T)))
+typedef const CF_BRIDGED_TYPE(id) void * CFTypeRef;
+typedef const struct CF_BRIDGED_TYPE(NSString) __CFString * CFStringRef;
+
+typedef enum { WARNING } Level;
+id do_log(Level, const char *);
+#define log(level, msg) __extension__({ (do_log(level, msg)); })
+
+@interface I
+- foo;
+@end
+
+CFStringRef processString(const __NSConstantString *, void *);
+
+#define CFSTR __builtin___CFStringMakeConstantString
+
+int main() {
+ I *i;
+ @autoreleasepool {
+ NSString *s1 = (__bridge_transfer NSString *)processString(0, 0);
+ NSString *s2 = (__bridge_transfer NSString *)processString((CFSTR("")), ((void *)0));
+ log(WARNING, "Hello world!");
+ }
+ [[NSRunLoop mainRunLoop] run];
+ [i foo]; // no-crash // expected-warning{{Temporary objects allocated in the autorelease pool of last resort followed by the launch of main run loop may never get released; consider moving them to a separate autorelease pool}}
+}
+#endif
diff --git a/test/Analysis/Inputs/ctu-other.c b/test/Analysis/Inputs/ctu-other.c
new file mode 100644
index 000000000000..9a952061102f
--- /dev/null
+++ b/test/Analysis/Inputs/ctu-other.c
@@ -0,0 +1,49 @@
+// Test typedef and global variable in function.
+typedef struct {
+ int a;
+ int b;
+} FooBar;
+FooBar fb;
+int f(int i) {
+ if (fb.a) {
+ fb.b = i;
+ }
+ return 1;
+}
+
+// Test enums.
+enum B { x = 42,
+ l,
+ s };
+int enumCheck(void) {
+ return x;
+}
+
+// Test reporting an error in macro definition
+#define MYMACRO(ctx) \
+ ctx->a;
+struct S {
+ int a;
+};
+int g(struct S *ctx) {
+ MYMACRO(ctx);
+ return 0;
+}
+
+// Test that asm import does not fail.
+int inlineAsm() {
+ int res;
+ asm("mov $42, %0"
+ : "=r"(res));
+ return res;
+}
+
+// Implicit function.
+int identImplicit(int in) {
+ return in;
+}
+
+// ASTImporter doesn't support this construct.
+int structInProto(struct DataType {int a;int b; } * d) {
+ return 0;
+}
diff --git a/test/Analysis/Inputs/ctu-other.c.externalDefMap.txt b/test/Analysis/Inputs/ctu-other.c.externalDefMap.txt
new file mode 100644
index 000000000000..9abaa501a4cb
--- /dev/null
+++ b/test/Analysis/Inputs/ctu-other.c.externalDefMap.txt
@@ -0,0 +1,6 @@
+c:@F@inlineAsm ctu-other.c.ast
+c:@F@g ctu-other.c.ast
+c:@F@f ctu-other.c.ast
+c:@F@enumCheck ctu-other.c.ast
+c:@F@identImplicit ctu-other.c.ast
+c:@F@structInProto ctu-other.c.ast
diff --git a/test/Analysis/Inputs/externalFnMap.txt b/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
index 5461685dc62b..5461685dc62b 100644
--- a/test/Analysis/Inputs/externalFnMap.txt
+++ b/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
diff --git a/test/Analysis/Inputs/expected-plists/NewDelete-path-notes.cpp.plist b/test/Analysis/Inputs/expected-plists/NewDelete-path-notes.cpp.plist
new file mode 100644
index 000000000000..d74d9fc7c677
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/NewDelete-path-notes.cpp.plist
@@ -0,0 +1,464 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is released</string>
+ <key>message</key>
+ <string>Memory is released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Attempt to free released memory</string>
+ <key>message</key>
+ <string>Attempt to free released memory</string>
+ </dict>
+ </array>
+ <key>description</key><string>Attempt to free released memory</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Double free</string>
+ <key>check_name</key><string>cplusplus.NewDelete</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bd8e324d09c70b9e2be6f824a4942e5a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>7</integer>
+ <integer>9</integer>
+ <integer>11</integer>
+ <integer>14</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;Odd::kill&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;Odd::kill&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is released</string>
+ <key>message</key>
+ <string>Memory is released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning; memory was released</string>
+ <key>message</key>
+ <string>Returning; memory was released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Attempt to free released memory</string>
+ <key>message</key>
+ <string>Attempt to free released memory</string>
+ </dict>
+ </array>
+ <key>description</key><string>Attempt to free released memory</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Double free</string>
+ <key>check_name</key><string>cplusplus.NewDelete</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8bf1a5b9fdae9d86780aa6c4cdce2605</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>19</integer>
+ <integer>20</integer>
+ <integer>24</integer>
+ <integer>25</integer>
+ <integer>27</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/NewDelete-path-notes.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/conditional-path-notes.c.plist b/test/Analysis/Inputs/expected-plists/conditional-path-notes.c.plist
new file mode 100644
index 000000000000..2cc68feb5c5c
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/conditional-path-notes.c.plist
@@ -0,0 +1,1772 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8ea3f4e6a3100c73f078fac15acb0a9c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCondOp</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>5</integer>
+ <integer>6</integer>
+ <integer>10</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2c219a33e961fc1be7d54b700867259e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCondProblem</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>14</integer>
+ <integer>15</integer>
+ <integer>19</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8d43b511137326eab7d1242950e72984</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLHSProblem</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>24</integer>
+ <integer>25</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b8e93b7355a6779a960f9a942fafac15</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testRHSProblem</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>32</integer>
+ <integer>33</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a944281d096940ca43ec995649b48b5f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testBinaryCondOp</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>40</integer>
+ <integer>41</integer>
+ <integer>44</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4db164bbf5cea42d75c5e838be1eef6f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testBinaryLHSProblem</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>48</integer>
+ <integer>49</integer>
+ <integer>53</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>778d56ad485369222613ac2c03b97700</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testDiagnosableBranch</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>62</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;b&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;b&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a2b345c9681d9dd3aa15d12810759cb9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testDiagnosableBranchLogical</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>73</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f56671e5f67c73abef619b56f7c29fa4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testNonDiagnosableBranchArithmetic</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>78</integer>
+ <integer>79</integer>
+ <integer>82</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/conditional-path-notes.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/cstring-plist.c.plist b/test/Analysis/Inputs/expected-plists/cstring-plist.c.plist
new file mode 100644
index 000000000000..84f23be16cd6
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/cstring-plist.c.plist
@@ -0,0 +1,8 @@
+<key>diagnostics</key>
+<array>
+</array>
+</dict>
+</plist>
+
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist b/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist
new file mode 100644
index 000000000000..9afb8055793b
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist
@@ -0,0 +1,1960 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7c0b35987817cf3d44b88c5349bcd4f2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLoop</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>7</integer>
+ <integer>8</integer>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>14</integer>
+ <integer>15</integer>
+ <integer>16</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;get&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;get&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testLoopErrorInRange&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testLoopErrorInRange&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f53792d63dffe6176babc00ee455a3e0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>get</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>31</integer>
+ <integer>32</integer>
+ <integer>33</integer>
+ <integer>87</integer>
+ <integer>88</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is equal to 2</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is equal to 2</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7bc3cb8a56be029296ec61f7ee83fc9e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLoopOpaqueCollection</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>31</integer>
+ <integer>32</integer>
+ <integer>34</integer>
+ <integer>37</integer>
+ <integer>38</integer>
+ <integer>39</integer>
+ <integer>40</integer>
+ <integer>41</integer>
+ <integer>42</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when range is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when range is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dc7b457a64bd56c30467c1af44049756</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLoopOpaqueCollection</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>31</integer>
+ <integer>32</integer>
+ <integer>34</integer>
+ <integer>37</integer>
+ <integer>38</integer>
+ <integer>48</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>74</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>74</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>74</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>74</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is equal to 2</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is equal to 2</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f4697ded3a92318349a3969238e05387</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLoopOpaqueIterator</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>68</integer>
+ <integer>69</integer>
+ <integer>72</integer>
+ <integer>73</integer>
+ <integer>74</integer>
+ <integer>75</integer>
+ <integer>76</integer>
+ <integer>77</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when range is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when range is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6855b29ad2407a5af43c57f062bc4602</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLoopOpaqueIterator</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>68</integer>
+ <integer>69</integer>
+ <integer>72</integer>
+ <integer>73</integer>
+ <integer>83</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Initializing to a null pointer value</string>
+ <key>message</key>
+ <string>Initializing to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>56</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ad377f8d4510dfd77d6485c402d57a2d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testForRangeInit</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>101</integer>
+ <integer>102</integer>
+ <integer>103</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/cxx-for-range.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/edges-new.mm.plist b/test/Analysis/Inputs/expected-plists/edges-new.mm.plist
new file mode 100644
index 000000000000..bcb659c0b31f
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/edges-new.mm.plist
@@ -0,0 +1,21452 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dc9c2a657ca759f9744cde2e093cfd59</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_init</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>51</integer>
+ <integer>52</integer>
+ <integer>53</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8f95d9681490a4e52c167969d0957b39</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_assign</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>64</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>64</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>64</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>64</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>64</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>64</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>64</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>94c43fbcad6aaff4ee7433f2d2db0bbe</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_assign_transitive</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>62</integer>
+ <integer>63</integer>
+ <integer>64</integer>
+ <integer>65</integer>
+ <integer>66</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>659f01507ffd7efd3ca3eab7179fd7d2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_cond</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>69</integer>
+ <integer>70</integer>
+ <integer>71</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;q&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;q&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c90d51e62139e614b57aff7021240a82</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_cond_transitive</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>75</integer>
+ <integer>76</integer>
+ <integer>77</integer>
+ <integer>78</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;x.p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;x.p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>245408d2bc416e324064d990e6dd82a8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_field</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>82</integer>
+ <integer>83</integer>
+ <integer>84</integer>
+ <integer>85</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;b&apos; is equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;b&apos; is equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b12acffa40177b55b695aa2292533410</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_assumptions</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>88</integer>
+ <integer>89</integer>
+ <integer>90</integer>
+ <integer>93</integer>
+ <integer>96</integer>
+ <integer>97</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value assigned to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Value assigned to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c0a32b8291b0fc7230f847f05f415625</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_cond_assign</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>101</integer>
+ <integer>102</integer>
+ <integer>103</integer>
+ <integer>105</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>82</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>122</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>122</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>122</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>122</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>123</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>123</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>123</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>29a10ca4af622b6146ca082e49d919d6</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar8331641</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>123</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>117</integer>
+ <integer>118</integer>
+ <integer>119</integer>
+ <integer>120</integer>
+ <integer>122</integer>
+ <integer>123</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ed7251f5b34b8380abd60cddfd3db46b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_fast_enumeration</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>129</integer>
+ <integer>130</integer>
+ <integer>131</integer>
+ <integer>132</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;x&apos; is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;x&apos; is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;x&apos; is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead increment</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dd09640bb87b201c2adcf5ef37bfcfaa</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_fast_enumeration_2</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>140</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when collection is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when collection is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
+ <key>message</key>
+ <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
+ </dict>
+ </array>
+ <key>description</key><string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Assigned value is garbage or undefined</string>
+ <key>check_name</key><string>core.uninitialized.Assign</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>025372576cd3ba6716044f93a51c978c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_fast_enumeration_2</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>135</integer>
+ <integer>136</integer>
+ <integer>137</integer>
+ <integer>140</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>08f9a01186cb2f1b78b08ec20260f1c1</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar12280665</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>144</integer>
+ <integer>145</integer>
+ <integer>146</integer>
+ <integer>147</integer>
+ <integer>148</integer>
+ <integer>150</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>157</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>157</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>93a53e4c8f02d191b07477940ddcf89c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>radar12322528_for</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>156</integer>
+ <integer>157</integer>
+ <integer>158</integer>
+ <integer>159</integer>
+ <integer>162</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f2d2dbf579b0b21a6b68726df6a041fc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>radar12322528_while</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>165</integer>
+ <integer>166</integer>
+ <integer>167</integer>
+ <integer>168</integer>
+ <integer>172</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>95c7d39fb9d0d8c172b894e02855a07c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>radar12322528_foo_2</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>175</integer>
+ <integer>176</integer>
+ <integer>177</integer>
+ <integer>178</integer>
+ <integer>179</integer>
+ <integer>181</integer>
+ <integer>183</integer>
+ <integer>185</integer>
+ <integer>186</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4cbbc713c8267513fef8a33f1327d7ca</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_diagnostics</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>189</integer>
+ <integer>190</integer>
+ <integer>191</integer>
+ <integer>192</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>198</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a5aa7cf7ce6ba6683bebfff63df926fd</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_diagnostics_2</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>195</integer>
+ <integer>196</integer>
+ <integer>198</integer>
+ <integer>200</integer>
+ <integer>202</integer>
+ <integer>204</integer>
+ <integer>206</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>210</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>210</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>218</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>940ba28399417701285cc8f80b1b8c2d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_diagnostics_3</string>
+ <key>issue_hash_function_offset</key><string>10</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>209</integer>
+ <integer>210</integer>
+ <integer>211</integer>
+ <integer>212</integer>
+ <integer>213</integer>
+ <integer>214</integer>
+ <integer>215</integer>
+ <integer>216</integer>
+ <integer>217</integer>
+ <integer>218</integer>
+ <integer>219</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>89eb0611013a66315f63bf4de8130c3d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_do_while</string>
+ <key>issue_hash_function_offset</key><string>12</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>222</integer>
+ <integer>223</integer>
+ <integer>225</integer>
+ <integer>227</integer>
+ <integer>229</integer>
+ <integer>230</integer>
+ <integer>232</integer>
+ <integer>234</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>483f7a1c29cc32152ca2ea651443e16f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_logical_and</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>238</integer>
+ <integer>239</integer>
+ <integer>240</integer>
+ <integer>241</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>852b510b1e204194a9fe3045cabc952c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_logical_or</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>245</integer>
+ <integer>246</integer>
+ <integer>247</integer>
+ <integer>248</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a5081bea3b0e9f4f8132ecdb2c17991b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_logical_or_call</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>252</integer>
+ <integer>254</integer>
+ <integer>255</integer>
+ <integer>256</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;coin&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;coin&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>16c21155317ccfddb4f482db43b6c635</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_nested_logicals</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>264</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>260</integer>
+ <integer>261</integer>
+ <integer>263</integer>
+ <integer>264</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;coin&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;coin&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>267</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>16c21155317ccfddb4f482db43b6c635</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_nested_logicals</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>260</integer>
+ <integer>261</integer>
+ <integer>263</integer>
+ <integer>267</integer>
+ <integer>268</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>274</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>274</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>274</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>274</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>274</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5fec1fd2724e271bb73fa4dd4be2a7f5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_deeply_nested_logicals</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>272</integer>
+ <integer>274</integer>
+ <integer>276</integer>
+ <integer>278</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>283</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c4ebf7f3e8a792521541ffae22ae2378</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_ternary</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>287</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>282</integer>
+ <integer>283</integer>
+ <integer>285</integer>
+ <integer>287</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>294</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>294</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>137a2333a17b5eecff7ff7a4b56d38d9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testUseless</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>298</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>290</integer>
+ <integer>291</integer>
+ <integer>294</integer>
+ <integer>297</integer>
+ <integer>298</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>310</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d1a1b27348a9c4d0abaaea4a4df9b649</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testFoo</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>312</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>309</integer>
+ <integer>310</integer>
+ <integer>312</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>320</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>320</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>320</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; initialized to nil</string>
+ <key>message</key>
+ <string>&apos;x&apos; initialized to nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>320</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>320</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;getPointer&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;getPointer&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1d7470f8b42e1cff6ab697162911b488</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test1_IPA_X</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>321</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>319</integer>
+ <integer>320</integer>
+ <integer>321</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;opaque&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;opaque&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;getX&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;getX&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; initialized to nil</string>
+ <key>message</key>
+ <string>&apos;x&apos; initialized to nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>340</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;getPointer&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;getPointer&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3fda62f72d88e4bc250c415cbc45a9e2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_IPA_Y</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>341</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>336</integer>
+ <integer>337</integer>
+ <integer>340</integer>
+ <integer>341</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;causeDivByZeroInMain&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;causeDivByZeroInMain&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;mainPlusMain&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;mainPlusMain&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;m&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;m&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d0d513aa4710781c2b56c44226354403</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>causeDivByZeroInMain</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>345</integer>
+ <integer>346</integer>
+ <integer>347</integer>
+ <integer>351</integer>
+ <integer>352</integer>
+ <integer>353</integer>
+ <integer>354</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>383</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>383</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>383</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>383</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>383</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b21eba78798501dc6b716bb91e3f7f01</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>384</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>382</integer>
+ <integer>383</integer>
+ <integer>384</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>392</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>392</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>392</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;s.i&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;s.i&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>392</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>392</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>394</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>394</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>394</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>394</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>394</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
+ <key>message</key>
+ <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
+ <key>category</key><string>API</string>
+ <key>type</key><string>Argument with &apos;nonnull&apos; attribute passed null</string>
+ <key>check_name</key><string>core.NonNullParamChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c0b359a043c633f1b8d1581f68743361</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>RDar13295437</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>394</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>391</integer>
+ <integer>392</integer>
+ <integer>393</integer>
+ <integer>394</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;coin&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;coin&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>400</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>573a1a599cc8abe987f5227676d04abc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCast</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>404</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>399</integer>
+ <integer>400</integer>
+ <integer>401</integer>
+ <integer>402</integer>
+ <integer>403</integer>
+ <integer>404</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>420</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>421</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>421</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>421</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>421</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>421</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>421</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>421</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ea1d5db6b4c380a432c88139fdd18f42</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>419</integer>
+ <integer>420</integer>
+ <integer>421</integer>
+ <integer>422</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;foo&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3dd1ebf91fa4e92eeec82faaeb48beda</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>431</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>430</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of RDar10797980 with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of RDar10797980 with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>431</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f533db5cbb9c20d171f9f92105789dc4</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>429</integer>
+ <integer>430</integer>
+ <integer>431</integer>
+ <integer>433</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>446</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>446</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>446</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>446</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>449</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>446</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>449</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a76c8ba29cdedecd0dfa5e24711cd236</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>20</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>452</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>455</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>458</integer>
+ <integer>459</integer>
+ <integer>460</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>463</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>463</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>463</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>463</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>26</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>464</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>452</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>455</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>459</integer>
+ <integer>460</integer>
+ <integer>462</integer>
+ <integer>463</integer>
+ <integer>464</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>468</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>468</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>468</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>468</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>34</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>472</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>452</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>455</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>459</integer>
+ <integer>460</integer>
+ <integer>462</integer>
+ <integer>467</integer>
+ <integer>468</integer>
+ <integer>469</integer>
+ <integer>470</integer>
+ <integer>471</integer>
+ <integer>472</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when collection is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when collection is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when range is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when range is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>499</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>499</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>499</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>499</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>62</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>500</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>452</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>455</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>459</integer>
+ <integer>460</integer>
+ <integer>462</integer>
+ <integer>467</integer>
+ <integer>475</integer>
+ <integer>476</integer>
+ <integer>477</integer>
+ <integer>478</integer>
+ <integer>479</integer>
+ <integer>480</integer>
+ <integer>481</integer>
+ <integer>483</integer>
+ <integer>484</integer>
+ <integer>491</integer>
+ <integer>492</integer>
+ <integer>493</integer>
+ <integer>494</integer>
+ <integer>497</integer>
+ <integer>498</integer>
+ <integer>499</integer>
+ <integer>500</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when collection is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when collection is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when range is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when range is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>504</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>504</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>504</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>504</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>67</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>505</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>452</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>455</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>459</integer>
+ <integer>460</integer>
+ <integer>462</integer>
+ <integer>467</integer>
+ <integer>475</integer>
+ <integer>476</integer>
+ <integer>477</integer>
+ <integer>478</integer>
+ <integer>479</integer>
+ <integer>480</integer>
+ <integer>481</integer>
+ <integer>483</integer>
+ <integer>484</integer>
+ <integer>491</integer>
+ <integer>492</integer>
+ <integer>493</integer>
+ <integer>494</integer>
+ <integer>497</integer>
+ <integer>498</integer>
+ <integer>503</integer>
+ <integer>504</integer>
+ <integer>505</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when collection is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when collection is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when range is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when range is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>509</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>509</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>509</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>509</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>510</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>74</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>512</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>452</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>455</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>459</integer>
+ <integer>460</integer>
+ <integer>462</integer>
+ <integer>467</integer>
+ <integer>475</integer>
+ <integer>476</integer>
+ <integer>477</integer>
+ <integer>478</integer>
+ <integer>479</integer>
+ <integer>480</integer>
+ <integer>481</integer>
+ <integer>483</integer>
+ <integer>484</integer>
+ <integer>491</integer>
+ <integer>492</integer>
+ <integer>493</integer>
+ <integer>494</integer>
+ <integer>497</integer>
+ <integer>498</integer>
+ <integer>503</integer>
+ <integer>508</integer>
+ <integer>509</integer>
+ <integer>510</integer>
+ <integer>512</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>452</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>459</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>462</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when collection is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when collection is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>467</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>475</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>477</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>480</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>481</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>476</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when range is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when range is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>484</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>491</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>492</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>493</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>494</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>497</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>498</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>503</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>508</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>515</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>515</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>515</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>515</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>515</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>515</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>515</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>517</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>518</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>518</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>518</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>518</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6c3e2dd10c375325a3089b996dd460c3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variousLoops</string>
+ <key>issue_hash_function_offset</key><string>83</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>521</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>438</integer>
+ <integer>445</integer>
+ <integer>452</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>455</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>459</integer>
+ <integer>460</integer>
+ <integer>462</integer>
+ <integer>467</integer>
+ <integer>475</integer>
+ <integer>476</integer>
+ <integer>477</integer>
+ <integer>478</integer>
+ <integer>479</integer>
+ <integer>480</integer>
+ <integer>481</integer>
+ <integer>483</integer>
+ <integer>484</integer>
+ <integer>491</integer>
+ <integer>492</integer>
+ <integer>493</integer>
+ <integer>494</integer>
+ <integer>497</integer>
+ <integer>498</integer>
+ <integer>503</integer>
+ <integer>508</integer>
+ <integer>515</integer>
+ <integer>516</integer>
+ <integer>517</integer>
+ <integer>518</integer>
+ <integer>521</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>529</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>529</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>529</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>529</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>529</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>531</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>531</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>531</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>531</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>531</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Attempt to reallocate memory</string>
+ <key>message</key>
+ <string>Attempt to reallocate memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>531</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>531</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;tmp&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;tmp&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reallocation failed</string>
+ <key>message</key>
+ <string>Reallocation failed</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>532</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>533</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>533</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>533</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>51180616cd69dc1776be708299ec90fb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>reallocDiagnostics</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>533</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>528</integer>
+ <integer>529</integer>
+ <integer>530</integer>
+ <integer>531</integer>
+ <integer>532</integer>
+ <integer>533</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>548</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>548</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>551</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>551</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>551</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>551</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>551</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>551</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>551</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>553</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>553</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>553</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>553</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;~unique_ptr&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;~unique_ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ <key>message</key>
+ <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Bad deallocator</string>
+ <key>check_name</key><string>unix.MismatchedDeallocator</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>046c88d1c91ff46d6506dff5ff880756</string>
+ <key>issue_hash_function_offset</key><string>0</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>544</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>543</integer>
+ <integer>544</integer>
+ <integer>547</integer>
+ <integer>548</integer>
+ <integer>549</integer>
+ <integer>551</integer>
+ <integer>553</integer>
+ <integer>555</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>558</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>558</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>558</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>558</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>558</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>559</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>559</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>560</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>561</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>562</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>87</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>567</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>568</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>568</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>568</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5616a7601faa1a8c2ac56fa1b595b172</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>longLines</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>568</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>557</integer>
+ <integer>558</integer>
+ <integer>559</integer>
+ <integer>560</integer>
+ <integer>561</integer>
+ <integer>562</integer>
+ <integer>564</integer>
+ <integer>566</integer>
+ <integer>567</integer>
+ <integer>568</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dff4970e681578e07d0512d3258aeddd</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testMacroInFunctionDecl</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>573</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>571</integer>
+ <integer>572</integer>
+ <integer>573</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>584</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>584</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>585</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>585</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>585</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>585</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>de83c7c8cc706cf47429f220bfa49458</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>583</integer>
+ <integer>584</integer>
+ <integer>585</integer>
+ <integer>587</integer>
+ <integer>588</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/edges-new.mm</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/generics.m.plist b/test/Analysis/Inputs/expected-plists/generics.m.plist
new file mode 100644
index 000000000000..acee11772013
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/generics.m.plist
@@ -0,0 +1,7196 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>33d4584e2bf66b029ab9d152cc9cd8f7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>incompatibleTypesErased</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>97</integer>
+ <integer>98</integer>
+ <integer>99</integer>
+ <integer>100</integer>
+ <integer>101</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6edc910aaa9dc1f2d823abc8cb75360f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>incompatibleTypesErased</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>97</integer>
+ <integer>98</integer>
+ <integer>99</integer>
+ <integer>100</integer>
+ <integer>101</integer>
+ <integer>102</integer>
+ <integer>103</integer>
+ <integer>104</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>73c71c858082f5d7a2258f707927da3c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>incompatibleTypesErased</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>97</integer>
+ <integer>98</integer>
+ <integer>99</integer>
+ <integer>100</integer>
+ <integer>101</integer>
+ <integer>102</integer>
+ <integer>103</integer>
+ <integer>104</integer>
+ <integer>106</integer>
+ <integer>107</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getTypedStuff&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getTypedStuff&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;crossProceduralErasedTypes&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;crossProceduralErasedTypes&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getTypedStuff&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getTypedStuff&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>82c378fdcfcc5c0318d2f3ca46420ec1</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>crossProceduralErasedTypes</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>86</integer>
+ <integer>87</integer>
+ <integer>88</integer>
+ <integer>110</integer>
+ <integer>111</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>234e3c299ee75a4dd4563e0ea88b9ed9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>114</integer>
+ <integer>115</integer>
+ <integer>116</integer>
+ <integer>117</integer>
+ <integer>118</integer>
+ <integer>119</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e875afc5479fec33a693ce2b550a9573</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>114</integer>
+ <integer>115</integer>
+ <integer>116</integer>
+ <integer>117</integer>
+ <integer>118</integer>
+ <integer>119</integer>
+ <integer>121</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d7fa9fa89fe860ed8f5d22631233a5fa</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>124</integer>
+ <integer>125</integer>
+ <integer>126</integer>
+ <integer>127</integer>
+ <integer>128</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7de91182a5d6e40a85fa3b91cf3fd089</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>124</integer>
+ <integer>125</integer>
+ <integer>126</integer>
+ <integer>127</integer>
+ <integer>128</integer>
+ <integer>130</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8960776d84319407ac2bf7a1531d19b0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>idErasedIncompatibleTypes</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>133</integer>
+ <integer>134</integer>
+ <integer>135</integer>
+ <integer>136</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>93b114c7a385294dce5c25ed04a8b25a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>idErasedIncompatibleTypes</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>133</integer>
+ <integer>134</integer>
+ <integer>135</integer>
+ <integer>136</integer>
+ <integer>137</integer>
+ <integer>138</integer>
+ <integer>139</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4c17f22d7e977f3343d2e2129b9229c3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>idErasedIncompatibleTypes</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>133</integer>
+ <integer>134</integer>
+ <integer>135</integer>
+ <integer>136</integer>
+ <integer>137</integer>
+ <integer>138</integer>
+ <integer>139</integer>
+ <integer>141</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>24a08781e7d8971a7d8f8f607ce40074</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>pathSensitiveInference</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>144</integer>
+ <integer>145</integer>
+ <integer>146</integer>
+ <integer>150</integer>
+ <integer>151</integer>
+ <integer>153</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a8534f675404d57d833dc3c371d49845</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>verifyAPIusage</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>157</integer>
+ <integer>158</integer>
+ <integer>159</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>187</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>187</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d113e22b9ee9ded1cd94750c3557eff4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>subtypeOfGeneric</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>184</integer>
+ <integer>185</integer>
+ <integer>186</integer>
+ <integer>187</integer>
+ <integer>188</integer>
+ <integer>189</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f1b900572a63726a729714a765595c38</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>genericSubtypeOfGeneric</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>199</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>192</integer>
+ <integer>193</integer>
+ <integer>194</integer>
+ <integer>195</integer>
+ <integer>196</integer>
+ <integer>197</integer>
+ <integer>198</integer>
+ <integer>199</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cbb926c9de226a3eac85fb961a93f39a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>genericSubtypeOfGeneric</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>192</integer>
+ <integer>193</integer>
+ <integer>194</integer>
+ <integer>195</integer>
+ <integer>196</integer>
+ <integer>197</integer>
+ <integer>198</integer>
+ <integer>199</integer>
+ <integer>201</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b6ee3b22fbad45f213b4bf14bec7eeaf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>204</integer>
+ <integer>205</integer>
+ <integer>206</integer>
+ <integer>207</integer>
+ <integer>208</integer>
+ <integer>209</integer>
+ <integer>210</integer>
+ <integer>211</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>213</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>213</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>213</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>213</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>213</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6561f05506a8ceca3afc79fc59912b94</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>213</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>204</integer>
+ <integer>205</integer>
+ <integer>206</integer>
+ <integer>207</integer>
+ <integer>208</integer>
+ <integer>209</integer>
+ <integer>210</integer>
+ <integer>211</integer>
+ <integer>213</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6aab15d40b39ec0a6b749e561d486e6a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>inferenceFromAPI</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>216</integer>
+ <integer>219</integer>
+ <integer>220</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bd1da1b7775323773555e5d5c122661f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>inferenceFromAPI2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>223</integer>
+ <integer>224</integer>
+ <integer>225</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3f2abd3c0b4b4a80a71bcbb668124ffb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>228</integer>
+ <integer>229</integer>
+ <integer>230</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>73a50f2592e8b3c9af898749f24176f7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>233</integer>
+ <integer>234</integer>
+ <integer>235</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>239</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>240</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>23ca540c8961ab9a362a194e1e895f86</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes3</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>238</integer>
+ <integer>239</integer>
+ <integer>240</integer>
+ <integer>241</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>245</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>245</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>245</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>245</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>245</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>be7e9426f827314f05fd4e15b25909df</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>inferenceFromAPIWithBuggyTypes</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>244</integer>
+ <integer>245</integer>
+ <integer>246</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0f97a618ccac913d7c8631b5b86a133e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>251</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>249</integer>
+ <integer>250</integer>
+ <integer>251</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>67</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>725c54c88bb271138b1de545ee59a8aa</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes3</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>257</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>254</integer>
+ <integer>255</integer>
+ <integer>256</integer>
+ <integer>257</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>45</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>45</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>45</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>fb867af384c612fe5c09f821127eeaf0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes4</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>260</integer>
+ <integer>261</integer>
+ <integer>262</integer>
+ <integer>263</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>category</key><string>Type Error</string>
+ <key>type</key><string>Dynamic and static type mismatch</string>
+ <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2e9f738345d9fa7dae2324ff7accd1ae</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>workWithProperties</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>276</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>274</integer>
+ <integer>275</integer>
+ <integer>276</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>category</key><string>Type Error</string>
+ <key>type</key><string>Dynamic and static type mismatch</string>
+ <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d85392b4efadf710b8da65a043a65e24</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>workWithProperties</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>278</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>274</integer>
+ <integer>275</integer>
+ <integer>276</integer>
+ <integer>277</integer>
+ <integer>278</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>category</key><string>Type Error</string>
+ <key>type</key><string>Dynamic and static type mismatch</string>
+ <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>456c6227549a5e577088c9dce4cea452</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>workWithProperties</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>274</integer>
+ <integer>275</integer>
+ <integer>276</integer>
+ <integer>277</integer>
+ <integer>278</integer>
+ <integer>279</integer>
+ <integer>280</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>275</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>category</key><string>Type Error</string>
+ <key>type</key><string>Dynamic and static type mismatch</string>
+ <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>df7f090d2b72ac07bc2351177ed6552d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>workWithProperties</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>274</integer>
+ <integer>275</integer>
+ <integer>276</integer>
+ <integer>277</integer>
+ <integer>278</integer>
+ <integer>279</integer>
+ <integer>280</integer>
+ <integer>281</integer>
+ <integer>282</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>288</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>288</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>288</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>288</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>288</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a0fa75143d7a7ac234292642a6d93360</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>findMethodDeclInTrackedType</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>291</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>286</integer>
+ <integer>287</integer>
+ <integer>288</integer>
+ <integer>289</integer>
+ <integer>290</integer>
+ <integer>291</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>300</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>300</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>300</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>300</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>300</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>301</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>302</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>302</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>302</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>302</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>302</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d0b99c8523e81ec43ba4ea80aeedef1b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>findMethodDeclInTrackedType2</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>302</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>298</integer>
+ <integer>299</integer>
+ <integer>300</integer>
+ <integer>301</integer>
+ <integer>302</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>326</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>326</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>46aa94b866747bcbe1ded581da7a2633</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>trackedClassVariables</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>325</integer>
+ <integer>326</integer>
+ <integer>327</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>326</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>326</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a759006d1ce88e15fcd6de6a29e2579c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>trackedClassVariables</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>325</integer>
+ <integer>326</integer>
+ <integer>327</integer>
+ <integer>328</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>332</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>332</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>332</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>332</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>332</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4bb1729ff86647750b458e6f8d883f08</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>nestedCollections</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>333</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>331</integer>
+ <integer>332</integer>
+ <integer>333</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>346</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>38831553eaecfb6c02b51e71d21ec6ea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>returnCollectionToIdVariable</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>344</integer>
+ <integer>345</integer>
+ <integer>346</integer>
+ <integer>347</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>9fcbd4dcf212f004877292aa5085322b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>eraseSpecialization</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>350</integer>
+ <integer>351</integer>
+ <integer>352</integer>
+ <integer>353</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>357</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>357</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
+ <key>message</key>
+ <string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
+ <key>category</key><string>Type Error</string>
+ <key>type</key><string>Dynamic and static type mismatch</string>
+ <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>be6714fed24af6e7ac522b87a5098de0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>returnToUnrelatedType</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>358</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>356</integer>
+ <integer>357</integer>
+ <integer>358</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>363</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>363</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;NSString *&apos; is inferred from this context</string>
+ <key>message</key>
+ <string>Type &apos;NSString *&apos; is inferred from this context</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
+ <key>message</key>
+ <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
+ <key>category</key><string>Type Error</string>
+ <key>type</key><string>Dynamic and static type mismatch</string>
+ <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5e96ef711c8f115bc64f69baa3f6ea7a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>returnToIdVariable</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>362</integer>
+ <integer>363</integer>
+ <integer>364</integer>
+ <integer>365</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8347f65fb51a85ccd462d75ffd761078</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>372</integer>
+ <integer>373</integer>
+ <integer>374</integer>
+ <integer>375</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ <key>message</key>
+ <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>380</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>380</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>380</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>380</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>380</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+ <key>category</key><string>Core Foundation/Objective-C</string>
+ <key>type</key><string>Generics</string>
+ <key>check_name</key><string>core.DynamicTypePropagation</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6528db66f562ac0c2a94933f3ca5f6a8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>380</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>372</integer>
+ <integer>373</integer>
+ <integer>374</integer>
+ <integer>375</integer>
+ <integer>379</integer>
+ <integer>380</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>389</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>389</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>70</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>79</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>70</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>70</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>79</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>message</key>
+ <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+ <key>category</key><string>Type Error</string>
+ <key>type</key><string>Dynamic and static type mismatch</string>
+ <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>56326e7b73d049256717eba7005ccc4d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testArgumentAfterUpcastWithCovariantTypeParameter</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>391</integer>
+ <key>col</key><integer>70</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>388</integer>
+ <integer>389</integer>
+ <integer>390</integer>
+ <integer>391</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/generics.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/inline-plist.c.plist b/test/Analysis/Inputs/expected-plists/inline-plist.c.plist
new file mode 100644
index 000000000000..b6248158f15a
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/inline-plist.c.plist
@@ -0,0 +1,1986 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8bca94f2f862468bb877fb70e66a3304</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>foo</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>7</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>18</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;has_bug&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;has_bug&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_has_bug&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_has_bug&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>62ddaf4e66ff527b230b474b98791ced</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>has_bug</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>22</integer>
+ <integer>23</integer>
+ <integer>26</integer>
+ <integer>27</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;triggers_bug&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;triggers_bug&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;bar&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;bar&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1ee3fb0b2fbd9c66e0cc34ca1181ece3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>triggers_bug</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>32</integer>
+ <integer>33</integer>
+ <integer>38</integer>
+ <integer>39</integer>
+ <integer>45</integer>
+ <integer>47</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_block__capture_null&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_block__capture_null&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a2e7504f29818834127c44ba841f4da8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_block_ret&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_block_ret&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer (loaded from &apos;q&apos;)</string>
+ <key>message</key>
+ <string>Returning null pointer (loaded from &apos;q&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>931be9c3a45b61c0a9c99b4772bd6fca</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_block_ret</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>65</integer>
+ <integer>66</integer>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>70</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>74</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>74</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_block_blockvar&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_block_blockvar&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>524a8647c40f017409d858ff70900c1a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_block_blockvar</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>73</integer>
+ <integer>74</integer>
+ <integer>75</integer>
+ <integer>76</integer>
+ <integer>78</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_block_arg&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_block_arg&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0efdf891fbddf2932f9d434968b94164</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_block_arg</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>81</integer>
+ <integer>82</integer>
+ <integer>83</integer>
+ <integer>84</integer>
+ <integer>85</integer>
+ <integer>86</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/inline-plist.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/inline-unique-reports.c.plist b/test/Analysis/Inputs/expected-plists/inline-unique-reports.c.plist
new file mode 100644
index 000000000000..73c8707520bd
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/inline-unique-reports.c.plist
@@ -0,0 +1,278 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;bug&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;bug&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>4</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_bug_2&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_bug_2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>4</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>4</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a6ef969f9d5a84fe3b6d153fa488020a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>bug</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>4</integer>
+ <integer>5</integer>
+ <integer>13</integer>
+ <integer>14</integer>
+ <integer>15</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/inline-unique-reports.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist b/test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist
new file mode 100644
index 000000000000..ad3ebad2e1a9
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist
@@ -0,0 +1,205 @@
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The value 0 is assigned to field &apos;&apos;</string>
+ <key>message</key>
+ <string>The value 0 is assigned to field &apos;&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;operator()&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;operator()&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;diagnosticFromLambda&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;diagnosticFromLambda&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bd4eed3234018edced5efc2ed5562a74</string>
+ <key>issue_context_kind</key><string>C++ method</string>
+ <key>issue_context</key><string>operator()</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>7</integer>
+ <integer>8</integer>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>12</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/lambda-notes.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/malloc-plist.c.plist b/test/Analysis/Inputs/expected-plists/malloc-plist.c.plist
new file mode 100644
index 000000000000..98a783435a52
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/malloc-plist.c.plist
@@ -0,0 +1,5262 @@
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;in&apos; is &gt; 5</string>
+ <key>message</key>
+ <string>Assuming &apos;in&apos; is &gt; 5</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;p&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;p&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;p&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c60b35a3e46fd104f362f430a1eaca5d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>diagnosticTest</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>14</integer>
+ <integer>16</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;A&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;A&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;A&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>9b732ec46c4a08108dfbd37aa0955c51</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>myArrayAllocation</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>19</integer>
+ <integer>20</integer>
+ <integer>21</integer>
+ <integer>22</integer>
+ <integer>23</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Attempt to reallocate memory</string>
+ <key>message</key>
+ <string>Attempt to reallocate memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;tmp&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;tmp&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reallocation failed</string>
+ <key>message</key>
+ <string>Reallocation failed</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>37c0b1a1e65d26af6f9fb840cf159149</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>reallocDiagnostics</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>25</integer>
+ <integer>26</integer>
+ <integer>27</integer>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>30</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;wrapper&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_wrapper&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returned allocated memory</string>
+ <key>message</key>
+ <string>Returned allocated memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>384d1700f3d9c8eeea96d171e3030bdf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>36</integer>
+ <integer>37</integer>
+ <integer>39</integer>
+ <integer>40</integer>
+ <integer>44</integer>
+ <integer>45</integer>
+ <integer>46</integer>
+ <integer>47</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;my_malloc_and_free&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;my_malloc_and_free&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_double_action_call&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_double_action_call&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;my_free&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;my_free&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;my_malloc_and_free&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;my_malloc_and_free&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Memory is released</string>
+ <key>message</key>
+ <string>Memory is released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning; memory was released via 1st parameter</string>
+ <key>message</key>
+ <string>Returning; memory was released via 1st parameter</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning; memory was released via 1st parameter</string>
+ <key>message</key>
+ <string>Returning; memory was released via 1st parameter</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Use of memory after it is freed</string>
+ <key>message</key>
+ <string>Use of memory after it is freed</string>
+ </dict>
+ </array>
+ <key>description</key><string>Use of memory after it is freed</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Use-after-free</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>422436dc85b85cde7e15046a5616ee99</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_double_action_call</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>51</integer>
+ <integer>52</integer>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>60</integer>
+ <integer>61</integer>
+ <integer>62</integer>
+ <integer>63</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;my_realloc&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;my_realloc&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;reallocIntra&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;reallocIntra&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Attempt to reallocate memory</string>
+ <key>message</key>
+ <string>Attempt to reallocate memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;tmp&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;tmp&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Reallocation failed</string>
+ <key>message</key>
+ <string>Reallocation failed</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>70</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reallocation of 1st parameter failed</string>
+ <key>message</key>
+ <string>Reallocation of 1st parameter failed</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>23a6c295a515c455bea1c81519bc05b6</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>reallocIntra</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>69</integer>
+ <integer>70</integer>
+ <integer>71</integer>
+ <integer>75</integer>
+ <integer>76</integer>
+ <integer>77</integer>
+ <integer>78</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;malloc_wrapper_ret&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;malloc_wrapper_ret&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_ret&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_ret&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returned allocated memory</string>
+ <key>message</key>
+ <string>Returned allocated memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;v&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;v&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;v&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>45181c7fc1df81a732346f1ed1b3f238</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>use_ret</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>82</integer>
+ <integer>83</integer>
+ <integer>85</integer>
+ <integer>86</integer>
+ <integer>87</integer>
+ <integer>88</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;myfree_takingblock&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;myfree_takingblock&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;call_myfree_takingblock&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;call_myfree_takingblock&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is released</string>
+ <key>message</key>
+ <string>Memory is released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning; memory was released via 2nd parameter</string>
+ <key>message</key>
+ <string>Returning; memory was released via 2nd parameter</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Use of memory after it is freed</string>
+ <key>message</key>
+ <string>Use of memory after it is freed</string>
+ </dict>
+ </array>
+ <key>description</key><string>Use of memory after it is freed</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Use-after-free</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>652c97005df876a65d64ecd286d6030a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>call_myfree_takingblock</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>93</integer>
+ <integer>94</integer>
+ <integer>97</integer>
+ <integer>98</integer>
+ <integer>100</integer>
+ <integer>101</integer>
+ <integer>102</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;m&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;m&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;m&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d8483ccf1d5a1af1e8bcaac6905a18b3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>LeakedSymbol</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>106</integer>
+ <integer>107</integer>
+ <integer>108</integer>
+ <integer>109</integer>
+ <integer>110</integer>
+ <integer>111</integer>
+ <integer>112</integer>
+ <integer>113</integer>
+ <integer>114</integer>
+ <integer>115</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>123</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>123</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>123</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;function_with_leak1&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;function_with_leak1&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_function_with_leak1&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_function_with_leak1&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b07aebe89e4ba5ea104a9f957df9531b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>function_with_leak1</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>119</integer>
+ <integer>120</integer>
+ <integer>121</integer>
+ <integer>122</integer>
+ <integer>123</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;function_with_leak2&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;function_with_leak2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_function_with_leak2&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_function_with_leak2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>efe2ffcb7c227e872aa732c5f793895d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>function_with_leak2</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>127</integer>
+ <integer>128</integer>
+ <integer>129</integer>
+ <integer>131</integer>
+ <integer>132</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;function_with_leak3&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;function_with_leak3&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_function_with_leak3&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_function_with_leak3&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>138</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>138</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>138</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0ddc87e8a7e7104428af3905f3057611</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>function_with_leak3</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>138</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>135</integer>
+ <integer>136</integer>
+ <integer>137</integer>
+ <integer>138</integer>
+ <integer>140</integer>
+ <integer>141</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;function_with_leak4&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;function_with_leak4&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_function_with_leak4&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_function_with_leak4&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>149</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>149</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>149</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>948d356840e67fc4baa8cc5d0600463c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>function_with_leak4</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>149</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>144</integer>
+ <integer>145</integer>
+ <integer>146</integer>
+ <integer>149</integer>
+ <integer>151</integer>
+ <integer>152</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;function_with_leak5&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;function_with_leak5&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_function_with_leak5&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_function_with_leak5&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>158</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2b0361060027060b94915ff4de8aa782</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>function_with_leak5</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>158</integer>
+ <integer>159</integer>
+ <integer>160</integer>
+ <integer>162</integer>
+ <integer>163</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>174</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>174</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>174</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;function_with_leak6&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;function_with_leak6&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>169</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_function_with_leak6&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_function_with_leak6&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>169</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>169</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>73f573faa903ad4308d5155ef979cf31</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>function_with_leak6</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>169</integer>
+ <integer>170</integer>
+ <integer>171</integer>
+ <integer>173</integer>
+ <integer>174</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;function_with_leak7&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;function_with_leak7&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use_function_with_leak7&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use_function_with_leak7&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>183</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returned allocated memory</string>
+ <key>message</key>
+ <string>Returned allocated memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>187</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>187</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>187</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential memory leak</string>
+ <key>message</key>
+ <string>Potential memory leak</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential memory leak</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>eb5628850b9b9118fbda903e721436a5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>use_function_with_leak7</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>187</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>182</integer>
+ <integer>183</integer>
+ <integer>185</integer>
+ <integer>186</integer>
+ <integer>187</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;my_malloc&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;my_malloc&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testOnlyRefferToVisibleVariables&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testOnlyRefferToVisibleVariables&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returned allocated memory</string>
+ <key>message</key>
+ <string>Returned allocated memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential memory leak</string>
+ <key>message</key>
+ <string>Potential memory leak</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential memory leak</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ad5b603037bc3581ff94947e86dbb1c8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testOnlyRefferToVisibleVariables</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>191</integer>
+ <integer>192</integer>
+ <integer>193</integer>
+ <integer>195</integer>
+ <integer>196</integer>
+ <integer>197</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;my_malloc_into_struct&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;my_malloc_into_struct&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testMyMalloc&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testMyMalloc&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>204</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returned allocated memory</string>
+ <key>message</key>
+ <string>Returned allocated memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential memory leak</string>
+ <key>message</key>
+ <string>Potential memory leak</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential memory leak</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8d59cc5cc4b7db55d432abc18b0e6c23</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testMyMalloc</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>202</integer>
+ <integer>203</integer>
+ <integer>204</integer>
+ <integer>205</integer>
+ <integer>207</integer>
+ <integer>208</integer>
+ <integer>209</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/malloc-plist.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/method-call-path-notes.cpp.plist b/test/Analysis/Inputs/expected-plists/method-call-path-notes.cpp.plist
new file mode 100644
index 000000000000..9c6fd13d811e
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/method-call-path-notes.cpp.plist
@@ -0,0 +1,845 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;p&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is uninitialized</string>
+ <key>message</key>
+ <string>Called C++ object pointer is uninitialized</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is uninitialized</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is uninitialized</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8c0cdb645ae6be246ed75941dcefd32d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_ic</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>14</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is null</string>
+ <key>message</key>
+ <string>Called C++ object pointer is null</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is null</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is null</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>98e39ef0e4bbc0b9b2b1832285634d67</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_ic_null</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>17</integer>
+ <integer>18</integer>
+ <integer>19</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is null</string>
+ <key>message</key>
+ <string>Called C++ object pointer is null</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is null</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is null</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>84f3d9d5009d2ac455b46b4aae88f67f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_ic_set_to_null</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>22</integer>
+ <integer>23</integer>
+ <integer>24</integer>
+ <integer>25</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is null</string>
+ <key>message</key>
+ <string>Called C++ object pointer is null</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is null</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is null</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c5bd8e35fb6da070914016804720ae4d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_ic_null</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>30</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is null</string>
+ <key>message</key>
+ <string>Called C++ object pointer is null</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is null</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is null</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4681ee922f6860377317b26b3a4bb5d4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_ic_member_ptr</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>33</integer>
+ <integer>34</integer>
+ <integer>36</integer>
+ <integer>37</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is null</string>
+ <key>message</key>
+ <string>Called C++ object pointer is null</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is null</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is null</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e23397f9f2eff1b08593c2b2db137494</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_cast</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>40</integer>
+ <integer>41</integer>
+ <integer>42</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/method-call-path-notes.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/model-file.cpp.plist b/test/Analysis/Inputs/expected-plists/model-file.cpp.plist
new file mode 100644
index 000000000000..f7965488f25e
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/model-file.cpp.plist
@@ -0,0 +1,309 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>86cb845e4f1e6abde1c5b319d5b08eca</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>main</string>
+ <key>issue_hash_function_offset</key><string>15</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>20</integer>
+ <integer>22</integer>
+ <integer>24</integer>
+ <integer>25</integer>
+ <integer>31</integer>
+ <integer>35</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>1</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/model-file.cpp</string>
+ <string>/clang/test/Analysis/Inputs/Models/notzero.model</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist b/test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist
new file mode 100644
index 000000000000..f2b6392433eb
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist
@@ -0,0 +1,1028 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;obj&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;obj&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3ff6dd9f2084f4a0dac8c3688c02fd0f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testNull</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>13</integer>
+ <integer>14</integer>
+ <integer>18</integer>
+ <integer>19</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value assigned to &apos;self&apos;</string>
+ <key>message</key>
+ <string>Value assigned to &apos;self&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;self&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;self&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Access to instance variable &apos;uniqueID&apos; results in a dereference of a null pointer (loaded from variable &apos;self&apos;)</string>
+ <key>message</key>
+ <string>Access to instance variable &apos;uniqueID&apos; results in a dereference of a null pointer (loaded from variable &apos;self&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Access to instance variable &apos;uniqueID&apos; results in a dereference of a null pointer (loaded from variable &apos;self&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>208c1267ca2da821fcc1b9183e1d624b</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>initWithID:</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>27</integer>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>33</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;coin&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;coin&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>9e1f67627fbbfb46b4e3a618246e6b0a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>repeatedStores</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>39</integer>
+ <integer>40</integer>
+ <integer>41</integer>
+ <integer>47</integer>
+ <integer>50</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;useArray&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;useArray&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testWithArrayPtr&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testWithArrayPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Array access (via ivar &apos;p&apos;) results in a null pointer dereference</string>
+ <key>message</key>
+ <string>Array access (via ivar &apos;p&apos;) results in a null pointer dereference</string>
+ </dict>
+ </array>
+ <key>description</key><string>Array access (via ivar &apos;p&apos;) results in a null pointer dereference</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>fb0ad1e4e3090d9834d542eb54bc9d2e</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>useArray</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>60</integer>
+ <integer>61</integer>
+ <integer>66</integer>
+ <integer>67</integer>
+ <integer>68</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/null-deref-path-notes.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/nullability-notes.m.plist b/test/Analysis/Inputs/expected-plists/nullability-notes.m.plist
new file mode 100644
index 000000000000..687520b495f9
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/nullability-notes.m.plist
@@ -0,0 +1,205 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Nullability &apos;nullable&apos; is inferred</string>
+ <key>message</key>
+ <string>Nullability &apos;nullable&apos; is inferred</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string>
+ <key>message</key>
+ <string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string>
+ </dict>
+ </array>
+ <key>description</key><string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Nullability</string>
+ <key>check_name</key><string>nullability.NullPassedToNonnull</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b6bc8126de8e6eb3375483a656fe858d</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>method</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>10</integer>
+ <integer>14</integer>
+ <integer>16</integer>
+ <integer>17</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/nullability-notes.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/objc-arc.m.plist b/test/Analysis/Inputs/expected-plists/objc-arc.m.plist
new file mode 100644
index 000000000000..650da0909064
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/objc-arc.m.plist
@@ -0,0 +1,2089 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b41b510812f2a0d8735c67dfff6a9a5c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_working</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>52</integer>
+ <integer>53</integer>
+ <integer>54</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>61d185b2522d15fb327f6784e0217adf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_cf_leak</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>92</integer>
+ <integer>93</integer>
+ <integer>94</integer>
+ <integer>95</integer>
+ <integer>96</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;x&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;x&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;x&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>63df5972efc8a7acccdbd2aca10c9e9e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar9424882</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>119</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;obj1&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;obj1&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;obj1&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>125290ceaf2b55f5778c262d87b2b6d5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>from_cf</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>139</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>45</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;obj4&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;obj4&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;obj4&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>54627578ee3b8520400ae899bc32b3d6</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>from_cf</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>144</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;obj5&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;obj5&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;obj5&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>27c31d7f5825a1613c0206b5be082800</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>from_cf</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>145</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;obj6&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;obj6&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;obj6&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a59b85c1e38300cb17eaeedcf193f94b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>from_cf</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>146</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj5&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj5&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;obj5&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5baa7d5f38420d0a035aa61607675f3e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>from_cf</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>138</integer>
+ <integer>139</integer>
+ <integer>140</integer>
+ <integer>141</integer>
+ <integer>142</integer>
+ <integer>143</integer>
+ <integer>144</integer>
+ <integer>145</integer>
+ <integer>146</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type &apos;CFStringRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type &apos;CFStringRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj6&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj6&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;obj6&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4665e04694fd55e7c4ed7a67860b3b74</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>from_cf</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>138</integer>
+ <integer>139</integer>
+ <integer>140</integer>
+ <integer>141</integer>
+ <integer>142</integer>
+ <integer>143</integer>
+ <integer>144</integer>
+ <integer>145</integer>
+ <integer>146</integer>
+ <integer>147</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>64</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;cf1&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;cf1&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;cf1&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>70a67cc8fefa3ad133a35c3ffb579b9e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>to_cf</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>150</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>67</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;cf2&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;cf2&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;cf2&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>afc41cacb8f32bfbe4a4152f20cec5bc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>to_cf</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>151</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>55</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;cf3&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;cf3&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;cf3&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e512cd0ada59beca5acfa53e2a632670</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>to_cf</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>152</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;cf4&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;cf4&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;cf4&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a43ae78dcef14395931eeb452f81819f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>to_cf</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>153</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>164</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>164</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>798e65f80df0526369f9bb240e3d91fd</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_unretainedObject</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>163</integer>
+ <integer>164</integer>
+ <integer>165</integer>
+ <integer>166</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>178</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>189</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type &apos;CFStringRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type &apos;CFStringRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>200</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFStringRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFStringRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFStringRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e1fbcc142b678b3c2c43737ee35b64d9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>24</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>176</integer>
+ <integer>178</integer>
+ <integer>179</integer>
+ <integer>180</integer>
+ <integer>181</integer>
+ <integer>185</integer>
+ <integer>186</integer>
+ <integer>187</integer>
+ <integer>188</integer>
+ <integer>189</integer>
+ <integer>193</integer>
+ <integer>194</integer>
+ <integer>195</integer>
+ <integer>196</integer>
+ <integer>200</integer>
+ <integer>202</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSObject with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSObject with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;o&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e300a279615a384d2b310329651d3978</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar11059275_positive</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>213</integer>
+ <integer>214</integer>
+ <integer>215</integer>
+ <integer>216</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>229</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>37efdaee587b783c6d49a228ff5ba49f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar14061675</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>230</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>222</integer>
+ <integer>223</integer>
+ <integer>226</integer>
+ <integer>229</integer>
+ <integer>230</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/objc-arc.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/objc-radar17039661.m.plist b/test/Analysis/Inputs/expected-plists/objc-radar17039661.m.plist
new file mode 100644
index 000000000000..b778e98bff75
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/objc-radar17039661.m.plist
@@ -0,0 +1,1309 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;performAction&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;performAction&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;runTest&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;runTest&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;reallyPerformAction&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;reallyPerformAction&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;performAction&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;performAction&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;reallyPerformAction&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;reallyPerformAction&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;cond&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;cond&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>4</integer>
+ <key>extended_message</key>
+ <string>Entered call</string>
+ <key>message</key>
+ <string>Entered call</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>4</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;reallyPerformAction&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;reallyPerformAction&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;cond&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;cond&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>4</integer>
+ <key>extended_message</key>
+ <string>Entered call</string>
+ <key>message</key>
+ <string>Entered call</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>4</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSNumber *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSNumber *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSNumber *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>500e2bbda41c8086771ad98b6bcfdc50</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>23</integer>
+ <integer>24</integer>
+ <integer>25</integer>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>30</integer>
+ <integer>32</integer>
+ <integer>34</integer>
+ <integer>36</integer>
+ <integer>38</integer>
+ <integer>41</integer>
+ <integer>48</integer>
+ <integer>49</integer>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>53</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/Volumes/Transcend/code/monorepo/llvm-project/clang/test/Analysis/objc-radar17039661.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist b/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist
new file mode 100644
index 000000000000..4d1d42438ef9
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist
@@ -0,0 +1,5452 @@
+<?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>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>SET_PTR_VAR_TO_NULL</string>
+ <key>expansion</key><string>ptr = 0</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f8fbc46cc5afbb056d92bd3d3d702781</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>nonFunctionLikeMacroTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>24</integer>
+ <integer>25</integer>
+ <integer>26</integer>
+ <integer>27</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO</string>
+ <key>expansion</key><string>ptr =0</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d5eba61193b41c27fc7b2705cbd607ba</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>nonFunctionLikeNestedMacroTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>37</integer>
+ <integer>38</integer>
+ <integer>39</integer>
+ <integer>40</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;functionLikeMacroTest&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;functionLikeMacroTest&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>TO_NULL</string>
+ <key>expansion</key><string>setToNull(&amp;ptr)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>370a457744311752aac789447b4ef16c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>functionLikeMacroTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;functionLikeNestedMacroTest&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;functionLikeNestedMacroTest&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>80</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>80</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>80</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>TO_NULL</string>
+ <key>expansion</key><string>setToNull(&amp;a)</string>
+ </dict>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>80</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>DEREF</string>
+ <key>expansion</key><string>{ int b; b = 5; } print(a); *a</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>873802674657bba4565f64c7bbf0ded9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>functionLikeNestedMacroTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>80</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>77</integer>
+ <integer>78</integer>
+ <integer>79</integer>
+ <integer>80</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>WILL_UNDEF_SET_NULL_TO_PTR</string>
+ <key>expansion</key><string>ptr = nullptr;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>79ce7ac344a15505929edba2fdf178b6</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>undefinedMacroByTheEndOfParsingTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>96</integer>
+ <integer>97</integer>
+ <integer>98</integer>
+ <integer>99</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>47</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL</string>
+ <key>expansion</key><string>ptr = nullptr;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cbbecfb64198aebb884f3729dff84896</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroRedefinedMultipleTimesTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>113</integer>
+ <integer>114</integer>
+ <integer>115</integer>
+ <integer>116</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD</string>
+ <key>expansion</key><string>ptr = nullptr;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>01684c77381713fd6c7be31ebc9b647a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>undefinedMacroInsideAnotherMacroTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>133</integer>
+ <integer>134</integer>
+ <integer>135</integer>
+ <integer>136</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>162</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>TO_NULL_AND_PRINT</string>
+ <key>expansion</key><string>a = 0; print( &quot;Will this , cause a crash?&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7a7344244350405a514682fe228e304e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsCommaInStringTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>160</integer>
+ <integer>161</integer>
+ <integer>162</integer>
+ <integer>163</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>TO_NULL_AND_PRINT</string>
+ <key>expansion</key><string>a = 0; print( &quot;Will this ( cause a crash?&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1d6d14e3f566cec02bd1f3542e3c8044</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsLParenInStringTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>169</integer>
+ <integer>170</integer>
+ <integer>171</integer>
+ <integer>172</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>TO_NULL_AND_PRINT</string>
+ <key>expansion</key><string>a = 0; print( &quot;Will this ) cause a crash?&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7354d762d71f0d0a3ffc9d6d827fe580</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsRParenInStringTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>178</integer>
+ <integer>179</integer>
+ <integer>180</integer>
+ <integer>181</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>193</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;macroArgContainsLParenRParenTest&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;macroArgContainsLParenRParenTest&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>CALL_FUNCTION</string>
+ <key>expansion</key><string>setToNull(&amp;a)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f00b6f77288a374e864a58609e9a42ea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsLParenRParenTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>195</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>192</integer>
+ <integer>193</integer>
+ <integer>194</integer>
+ <integer>195</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNullAndPrint&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNullAndPrint&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;macroArgContainsCommaLParenRParenTest&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;macroArgContainsCommaLParenRParenTest&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;setToNullAndPrint&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;setToNullAndPrint&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNullAndPrint&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNullAndPrint&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>208</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>CALL_FUNCTION</string>
+ <key>expansion</key><string>setToNullAndPrint(&amp;a, &quot;Hello!&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c5805abeb71bb4edb41b49ab317439b9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsCommaLParenRParenTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>201</integer>
+ <integer>202</integer>
+ <integer>203</integer>
+ <integer>206</integer>
+ <integer>207</integer>
+ <integer>208</integer>
+ <integer>209</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>219</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>64</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNullAndPrint&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNullAndPrint&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;macroArgContainsCommaLParenRParenTest2&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;macroArgContainsCommaLParenRParenTest2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>201</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;setToNullAndPrint&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;setToNullAndPrint&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>202</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>64</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNullAndPrint&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNullAndPrint&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>CALL_FUNCTION_WITH_TWO_PARAMS</string>
+ <key>expansion</key><string>setToNullAndPrint( &amp;a, &quot;Hello!&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4014a22ef054933e6ce9be43623ea85e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsCommaLParenRParenTest2</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>201</integer>
+ <integer>202</integer>
+ <integer>203</integer>
+ <integer>218</integer>
+ <integer>219</integer>
+ <integer>220</integer>
+ <integer>221</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>231</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>231</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;operator()&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;operator()&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;commaInBracketsTest&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;commaInBracketsTest&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;operator()&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;operator()&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;operator()&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;operator()&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>CALL_LAMBDA</string>
+ <key>expansion</key><string>([&amp;ptr, str] () mutable { setToNull(&amp;ptr); })()</string>
+ </dict>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>CALL_LAMBDA</string>
+ <key>expansion</key><string>([&amp;ptr, str] () mutable { setToNull(&amp;ptr); })()</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a8918c38ddfa6a991701e7d19c9cd6bb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>commaInBracketsTest</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>230</integer>
+ <integer>231</integer>
+ <integer>232</integer>
+ <integer>235</integer>
+ <integer>236</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;ptr&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;ptr&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>PASTE_CODE</string>
+ <key>expansion</key><string>{ int *ptr = nullptr; *ptr = 5; }</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>63042e03ae0d2f3832b141a63b1d4d49</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>commaInBracesTest</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>246</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>245</integer>
+ <integer>246</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>270</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>270</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>270</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>270</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>270</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>270</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>POTENTIALLY_EMPTY_PARAM</string>
+ <key>expansion</key><string>;ptr = nullptr</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cd980e278fbcd8f77bbeac79285084e2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>emptyParamTest</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>271</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>267</integer>
+ <integer>268</integer>
+ <integer>270</integer>
+ <integer>271</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>282</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>284</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>284</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>284</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>284</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>284</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>284</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>NESTED_EMPTY_PARAM</string>
+ <key>expansion</key><string>; ptr = nullptr;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f6a5f6c93b6e3734842ddabd3d5a7341</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>nestedEmptyParamTest</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>285</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>281</integer>
+ <integer>282</integer>
+ <integer>284</integer>
+ <integer>285</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>295</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>295</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>61</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;lParenRParenInNestedMacro&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;lParenRParenInNestedMacro&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>61</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO</string>
+ <key>expansion</key><string>setToNull( &amp;ptr)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ff00c8344e685317303e814970082d5f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>lParenRParenInNestedMacro</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>297</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>294</integer>
+ <integer>295</integer>
+ <integer>296</integer>
+ <integer>297</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>315</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>315</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>316</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>316</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>316</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>316</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>316</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>316</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>VARIADIC_SET_TO_NULL</string>
+ <key>expansion</key><string>ptr = nullptr; variadicFunc( 1, 5, &quot;haha!&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1b0880549df23e9ce0edb60955ad5ac1</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variadicMacroArgumentTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>317</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>314</integer>
+ <integer>315</integer>
+ <integer>316</integer>
+ <integer>317</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>324</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>324</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>327</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>VARIADIC_SET_TO_NULL</string>
+ <key>expansion</key><string>ptr = nullptr; variadicFunc()</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6aa30fd6a1e997027333f16c2064d973</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>variadicMacroArgumentWithoutAnyArgumentTest</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>328</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>323</integer>
+ <integer>324</integer>
+ <integer>327</integer>
+ <integer>328</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>343</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>343</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>344</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>344</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>344</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>344</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>344</integer>
+ <key>col</key><integer>45</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>344</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>DECLARE_FUNC_AND_SET_TO_NULL</string>
+ <key>expansion</key><string>void generated_whatever(); ptr = nullptr;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>453ed8096f5394e74e16f965886e5623</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>hashHashOperatorTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>345</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>342</integer>
+ <integer>343</integer>
+ <integer>344</integer>
+ <integer>345</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>352</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>TO_NULL_AND_PRINT</string>
+ <key>expansion</key><string>a = 0; print( &quot;Will this ## cause a crash?&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6817572ced27cb7d28fc87b2aba75fb4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsHashHashInStringTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>351</integer>
+ <integer>352</integer>
+ <integer>353</integer>
+ <integer>354</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>366</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>366</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>366</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>366</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>366</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>366</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>PRINT_STR</string>
+ <key>expansion</key><string>print(&quot;Hello&quot;); ptr = nullptr</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e6947ee72df70243a3b4c9e9eaed0888</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>hashOperatorTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>367</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>364</integer>
+ <integer>365</integer>
+ <integer>366</integer>
+ <integer>367</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>374</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>375</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>TO_NULL_AND_PRINT</string>
+ <key>expansion</key><string>a = 0; print( &quot;Will this # cause a crash?&quot;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b1da2db423e721067ed5cfda858890be</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroArgContainsHashInStringTest</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>373</integer>
+ <integer>374</integer>
+ <integer>375</integer>
+ <integer>376</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>422</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getLowestCommonDenominator&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getLowestCommonDenominator&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testVeryComplexAlgorithm&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testVeryComplexAlgorithm&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>EUCLIDEAN_ALGORITHM</string>
+ <key>expansion</key><string>if (A&lt;0 ){A=-A;} if ( B&lt;0 ){ B=- B;}return B / ( B - B);</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3484e210b755ea46d632296fffd709e0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>getLowestCommonDenominator</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>417</integer>
+ <integer>418</integer>
+ <integer>421</integer>
+ <integer>422</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>437</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>437</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>438</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>438</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>438</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>438</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>438</integer>
+ <key>col</key><integer>67</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>macro_expansions</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>438</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>name</key><string>YET_ANOTHER_SET_TO_NULL</string>
+ <key>expansion</key><string>print((void *)5); print((void *)&quot;Remember the Vasa&quot;); ptr = nullptr;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>42143f52fc9638fb2c0af41916e09d2f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>439</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>436</integer>
+ <integer>437</integer>
+ <integer>438</integer>
+ <integer>439</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/home/szelethus/Documents/macro_expansion/clang/test/Analysis/plist-macros-with-expansion.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/plist-macros.cpp.plist b/test/Analysis/Inputs/expected-plists/plist-macros.cpp.plist
new file mode 100644
index 000000000000..996ab0a7333e
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/plist-macros.cpp.plist
@@ -0,0 +1,1761 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory allocated by malloc() should be deallocated by free(), not &apos;delete&apos;</string>
+ <key>message</key>
+ <string>Memory allocated by malloc() should be deallocated by free(), not &apos;delete&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Memory allocated by malloc() should be deallocated by free(), not &apos;delete&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Bad deallocator</string>
+ <key>check_name</key><string>unix.MismatchedDeallocator</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>81d63a132b4ef0cc96734c17440a1c26</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>noteOnMacro</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>14</integer>
+ <integer>15</integer>
+ <integer>16</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>message</key>
+ <string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Memory leak</string>
+ <key>check_name</key><string>unix.Malloc</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2d723d9fb4e5f10dd54a7396866dfce4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroIsFirstInFunction</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>19</integer>
+ <integer>20</integer>
+ <integer>21</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is equal to null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is equal to null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3570104919aab3f953357f8c87b68bd7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroInExpression</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>26</integer>
+ <integer>27</integer>
+ <integer>28</integer>
+ <integer>30</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>deff163b13f3fd860bc332498b0dbc59</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroInExpressionNoNote</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>34</integer>
+ <integer>35</integer>
+ <integer>36</integer>
+ <integer>37</integer>
+ <integer>39</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is equal to null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is equal to null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b67b58d85375752578e947b77c6aa70c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>macroWithArgInExpression</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>43</integer>
+ <integer>44</integer>
+ <integer>45</integer>
+ <integer>47</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b53410f6c0d3d07e62ce5c6f91a1810a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>useMultiNoteMacroWithError</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>56</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>41f58f9549aa1867e461a7996a8d335c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>useMultiNote</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>66</integer>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>69</integer>
+ <integer>71</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;a&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;null_deref&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;null_deref&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test1&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test1&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2dc47a4afc2f349f12217b38588769f4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>null_deref</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>76</integer>
+ <integer>77</integer>
+ <integer>79</integer>
+ <integer>82</integer>
+ <integer>83</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/plist-macros.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/plist-output-alternate.m.plist b/test/Analysis/Inputs/expected-plists/plist-output-alternate.m.plist
new file mode 100644
index 000000000000..aedf06267269
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/plist-output-alternate.m.plist
@@ -0,0 +1,1520 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dc9c2a657ca759f9744cde2e093cfd59</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_init</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>4</integer>
+ <integer>5</integer>
+ <integer>6</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8f95d9681490a4e52c167969d0957b39</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_assign</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>94c43fbcad6aaff4ee7433f2d2db0bbe</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_assign_transitive</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>15</integer>
+ <integer>16</integer>
+ <integer>17</integer>
+ <integer>18</integer>
+ <integer>19</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>659f01507ffd7efd3ca3eab7179fd7d2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_cond</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>22</integer>
+ <integer>23</integer>
+ <integer>24</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;q&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;q&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c90d51e62139e614b57aff7021240a82</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_cond_transitive</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>30</integer>
+ <integer>31</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;x.p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;x.p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>245408d2bc416e324064d990e6dd82a8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_field</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>35</integer>
+ <integer>36</integer>
+ <integer>37</integer>
+ <integer>38</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>82</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>29a10ca4af622b6146ca082e49d919d6</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar8331641</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>52</integer>
+ <integer>53</integer>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/plist-output-alternate.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/plist-output.m.plist b/test/Analysis/Inputs/expected-plists/plist-output.m.plist
new file mode 100644
index 000000000000..cafa9f3b94e8
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/plist-output.m.plist
@@ -0,0 +1,6220 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dc9c2a657ca759f9744cde2e093cfd59</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_init</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>4</integer>
+ <integer>5</integer>
+ <integer>6</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8f95d9681490a4e52c167969d0957b39</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_assign</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;q&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>94c43fbcad6aaff4ee7433f2d2db0bbe</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_assign_transitive</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>15</integer>
+ <integer>16</integer>
+ <integer>17</integer>
+ <integer>18</integer>
+ <integer>19</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>659f01507ffd7efd3ca3eab7179fd7d2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_cond</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>22</integer>
+ <integer>23</integer>
+ <integer>24</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;q&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;q&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c90d51e62139e614b57aff7021240a82</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_cond_transitive</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>30</integer>
+ <integer>31</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;x.p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;x.p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>245408d2bc416e324064d990e6dd82a8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_null_field</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>35</integer>
+ <integer>36</integer>
+ <integer>37</integer>
+ <integer>38</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;a&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>43</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;b&apos; is equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;b&apos; is equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b12acffa40177b55b695aa2292533410</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_assumptions</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>41</integer>
+ <integer>42</integer>
+ <integer>43</integer>
+ <integer>46</integer>
+ <integer>49</integer>
+ <integer>50</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value assigned to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Value assigned to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c0a32b8291b0fc7230f847f05f415625</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_cond_assign</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>56</integer>
+ <integer>58</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>75</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>76</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ea1d5db6b4c380a432c88139fdd18f42</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>74</integer>
+ <integer>75</integer>
+ <integer>76</integer>
+ <integer>77</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;foo&apos; during its initialization is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead initialization</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3dd1ebf91fa4e92eeec82faaeb48beda</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>86</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is true</string>
+ <key>message</key>
+ <string>Assuming the condition is true</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>86</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f533db5cbb9c20d171f9f92105789dc4</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>84</integer>
+ <integer>85</integer>
+ <integer>86</integer>
+ <integer>88</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>100</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>08f9a01186cb2f1b78b08ec20260f1c1</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar12280665</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>94</integer>
+ <integer>95</integer>
+ <integer>96</integer>
+ <integer>97</integer>
+ <integer>98</integer>
+ <integer>100</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>107</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>108</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>108</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>108</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>108</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>108</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>108</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>108</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>93a53e4c8f02d191b07477940ddcf89c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>radar12322528_for</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>111</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>106</integer>
+ <integer>107</integer>
+ <integer>108</integer>
+ <integer>111</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body executed 0 times</string>
+ <key>message</key>
+ <string>Loop body executed 0 times</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f2d2dbf579b0b21a6b68726df6a041fc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>radar12322528_while</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>114</integer>
+ <integer>115</integer>
+ <integer>116</integer>
+ <integer>117</integer>
+ <integer>121</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>129</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>127</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>95c7d39fb9d0d8c172b894e02855a07c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>radar12322528_foo_2</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>124</integer>
+ <integer>125</integer>
+ <integer>126</integer>
+ <integer>127</integer>
+ <integer>128</integer>
+ <integer>129</integer>
+ <integer>130</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4cbbc713c8267513fef8a33f1327d7ca</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_diagnostics</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>133</integer>
+ <integer>134</integer>
+ <integer>135</integer>
+ <integer>136</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>144</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a5aa7cf7ce6ba6683bebfff63df926fd</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_diagnostics_2</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>139</integer>
+ <integer>140</integer>
+ <integer>141</integer>
+ <integer>142</integer>
+ <integer>143</integer>
+ <integer>144</integer>
+ <integer>145</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>149</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>149</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>154</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Looping back to the head of the loop</string>
+ <key>message</key>
+ <string>Looping back to the head of the loop</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3917bac4f8fdce1f6c6393b1f14a1320</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_diagnostics_3</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>148</integer>
+ <integer>149</integer>
+ <integer>150</integer>
+ <integer>151</integer>
+ <integer>152</integer>
+ <integer>153</integer>
+ <integer>154</integer>
+ <integer>155</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value stored to &apos;x&apos; is never read</string>
+ <key>message</key>
+ <string>Value stored to &apos;x&apos; is never read</string>
+ </dict>
+ </array>
+ <key>description</key><string>Value stored to &apos;x&apos; is never read</string>
+ <key>category</key><string>Dead store</string>
+ <key>type</key><string>Dead increment</string>
+ <key>check_name</key><string>deadcode.DeadStores</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c94f341ebaf0fac5d6703aaa7e6bee9b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_fast_enumeration</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>163</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Loop body skipped when collection is empty</string>
+ <key>message</key>
+ <string>Loop body skipped when collection is empty</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
+ <key>message</key>
+ <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
+ </dict>
+ </array>
+ <key>description</key><string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Assigned value is garbage or undefined</string>
+ <key>check_name</key><string>core.uninitialized.Assign</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>21c774309bdfd487c3d09a61a671bbcc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_loop_fast_enumeration</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>163</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>158</integer>
+ <integer>159</integer>
+ <integer>160</integer>
+ <integer>163</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b21eba78798501dc6b716bb91e3f7f01</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>172</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>170</integer>
+ <integer>171</integer>
+ <integer>172</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;s.i&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;s.i&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>182</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>184</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>184</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>184</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>184</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>184</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
+ <key>message</key>
+ <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
+ <key>category</key><string>API</string>
+ <key>type</key><string>Argument with &apos;nonnull&apos; attribute passed null</string>
+ <key>check_name</key><string>core.NonNullParamChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c0b359a043c633f1b8d1581f68743361</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>RDar13295437</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>184</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>181</integer>
+ <integer>182</integer>
+ <integer>183</integer>
+ <integer>184</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>192</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a225fec9dc1e56142b68b3df82b00b6c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testFoo</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>194</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>191</integer>
+ <integer>192</integer>
+ <integer>194</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/plist-output.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/plist-stats-output.c.plist b/test/Analysis/Inputs/expected-plists/plist-stats-output.c.plist
new file mode 100644
index 000000000000..8d4cab4832dd
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/plist-stats-output.c.plist
@@ -0,0 +1,9 @@
+ <key>diagnostics</key>
+ <array>
+ </array>
+<key>statistics</key>
+<string>{
+}
+</string>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist b/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
new file mode 100644
index 000000000000..b2b90adad1d3
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
@@ -0,0 +1,5022 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>47</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d21e9660cc6434ef84a51f39ffcdce86</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>creationViaAlloc</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>46</integer>
+ <integer>47</integer>
+ <integer>48</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f8ec2601a04113e567aa1d09c9902c91</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>creationViaCFCreate</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>51</integer>
+ <integer>52</integer>
+ <integer>53</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dd26a8ad9a7a057feaa636974b43ccb0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>acquisitionViaMethod</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ <integer>61</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Property returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Property returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2f2de5d7fe728958585598b619069e5a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>acquisitionViaProperty</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>64</integer>
+ <integer>65</integer>
+ <integer>66</integer>
+ <integer>67</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1c02b65e83dad1b22270ff5a71de3118</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>acquisitionViaCFFunction</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>70</integer>
+ <integer>71</integer>
+ <integer>72</integer>
+ <integer>73</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
+ <key>message</key>
+ <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>03c23f0f82d7f2fd880a22e0d9cf14b9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>explicitDealloc</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>76</integer>
+ <integer>77</integer>
+ <integer>78</integer>
+ <integer>79</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6f1b3f0c6c7f79f1af9b313273a01e92</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>implicitDealloc</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>85</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>82</integer>
+ <integer>83</integer>
+ <integer>84</integer>
+ <integer>85</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>89</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>89</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>89</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>89</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>89</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>90</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>91</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cb5e4205a8f925230a70715914a2e3d2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>overAutorelease</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>88</integer>
+ <integer>89</integer>
+ <integer>90</integer>
+ <integer>91</integer>
+ <integer>92</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Property returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Property returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1edd178e5ad76c79ce9812f519e8f467</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>autoreleaseUnowned</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>95</integer>
+ <integer>96</integer>
+ <integer>97</integer>
+ <integer>98</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3f08690fae9687c29bb23b7a7cb7995b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>makeCollectableIgnored</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>101</integer>
+ <integer>102</integer>
+ <integer>103</integer>
+ <integer>104</integer>
+ <integer>105</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4b621ab5f8f2ef9240699119f4d874cb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>CFCopyRuleViolation</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>108</integer>
+ <integer>109</integer>
+ <integer>110</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;object&apos; is returned from a function whose name (&apos;CFGetRuleViolation&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;object&apos; is returned from a function whose name (&apos;CFGetRuleViolation&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;object&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5248d2310322982d02e5f3d564249b4f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>CFGetRuleViolation</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>113</integer>
+ <integer>114</integer>
+ <integer>115</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Property returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Property returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4f23ad2725fb68134cec8b8354cd295c</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>copyViolation</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>121</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>119</integer>
+ <integer>120</integer>
+ <integer>121</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Subscript returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Subscript returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>da1dab126ed46b144040160ae8628460</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>copyViolationIndexedSubscript</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>124</integer>
+ <integer>125</integer>
+ <integer>126</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Subscript returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Subscript returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>130</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>52877f9471b1ecdaf213b39016b84e52</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>copyViolationKeyedSubscript</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>129</integer>
+ <integer>130</integer>
+ <integer>131</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of Foo with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of Foo with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;result&apos; is returned from a method whose name (&apos;getViolation&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;result&apos; is returned from a method whose name (&apos;getViolation&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;result&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cf8c65a18ad9982cb9848a266cd9c61b</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>getViolation</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>134</integer>
+ <integer>135</integer>
+ <integer>136</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of Foo with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of Foo with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>140</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e7b798151545b45a994592df0d27d250</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>copyAutorelease</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>139</integer>
+ <integer>140</integer>
+ <integer>141</integer>
+ <integer>142</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4e0c810e2b301aca3f636ad7e3d6b0b8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testNumericLiteral</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>171</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>169</integer>
+ <integer>170</integer>
+ <integer>171</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>175</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>175</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>175</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>175</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>175</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1d054002016aa4360aaf23a4c4d8fbb7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testBoxedInt</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>176</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>174</integer>
+ <integer>175</integer>
+ <integer>176</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSString boxed expression produces an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSString boxed expression produces an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>67ca92144b05322ee4569aea88d08595</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testBoxedString</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>181</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>179</integer>
+ <integer>180</integer>
+ <integer>181</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>185</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>32fcec71872b8f62d8d7b1b05284b0fe</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testArray</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>186</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>184</integer>
+ <integer>185</integer>
+ <integer>186</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSDictionary literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSDictionary literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d9584825bb1e62066879949e3ade8570</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testDictionary</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>189</integer>
+ <integer>190</integer>
+ <integer>191</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;initX&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;initX&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>206</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;Cond&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;Cond&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>207</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>209</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;initX&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;initX&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;MyObj *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;MyObj *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;MyObj *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>eef2aef4b58abf21fcfa4bbf69e19c02</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>206</integer>
+ <integer>207</integer>
+ <integer>209</integer>
+ <integer>224</integer>
+ <integer>226</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>226</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;initY&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;initY&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;initY&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;initY&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;y&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8c27524f691296551f9e52856b824326</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>206</integer>
+ <integer>207</integer>
+ <integer>209</integer>
+ <integer>214</integer>
+ <integer>215</integer>
+ <integer>216</integer>
+ <integer>224</integer>
+ <integer>226</integer>
+ <integer>232</integer>
+ <integer>237</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>248</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>249</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4fc36e73ba317d307dc9cc4b3d62fd0a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>CFOverAutorelease</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>250</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>246</integer>
+ <integer>247</integer>
+ <integer>248</integer>
+ <integer>249</integer>
+ <integer>250</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>255</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>08e6a3931d34cda45c09dfda76976e17</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>CFAutoreleaseUnowned</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>253</integer>
+ <integer>254</integer>
+ <integer>255</integer>
+ <integer>256</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>260</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>260</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>260</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>260</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>260</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>262</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d9bb23a5435fe15df9d7ffdc27a8a072</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>CFAutoreleaseUnownedMixed</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>263</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>259</integer>
+ <integer>260</integer>
+ <integer>261</integer>
+ <integer>262</integer>
+ <integer>263</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/test/Analysis/retain-release-path-notes.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist b/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
new file mode 100644
index 000000000000..01c317def20d
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
@@ -0,0 +1,26113 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>348</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>348</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5928b2a4699cbae0686391c20e639007</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f1</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>347</integer>
+ <integer>348</integer>
+ <integer>349</integer>
+ <integer>350</integer>
+ <integer>351</integer>
+ <integer>352</integer>
+ <integer>353</integer>
+ <integer>354</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>359</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>359</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6b2e175938153ac041f52ebbf50b1f43</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f2</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>358</integer>
+ <integer>359</integer>
+ <integer>360</integer>
+ <integer>361</integer>
+ <integer>362</integer>
+ <integer>363</integer>
+ <integer>364</integer>
+ <integer>365</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>395</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>395</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3fdbd844ddb925306ba2bb1b3626f310</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f5</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>394</integer>
+ <integer>395</integer>
+ <integer>396</integer>
+ <integer>398</integer>
+ <integer>401</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8529da75e357c59fb0a7fefb0b6e0952</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f6</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>406</integer>
+ <integer>407</integer>
+ <integer>408</integer>
+ <integer>409</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>eb0faa12081b1e28b218e4c6e53d57ec</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f7</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>414</integer>
+ <integer>415</integer>
+ <integer>416</integer>
+ <integer>417</integer>
+ <integer>418</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is returned from a function whose name (&apos;f7&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is returned from a function whose name (&apos;f7&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>404d4de8faa444bc52fd510380bd0a63</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f7</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>414</integer>
+ <integer>415</integer>
+ <integer>416</integer>
+ <integer>417</integer>
+ <integer>418</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;MyDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;MyDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>251dff6727b3d99ec95caa28672669ea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f8</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>425</integer>
+ <integer>426</integer>
+ <integer>427</integer>
+ <integer>428</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>432</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>432</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;date&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;date&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4af5d8d1438976cc7fa006af5f843b13</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f9</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>431</integer>
+ <integer>432</integer>
+ <integer>433</integer>
+ <integer>435</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCreateFromBSDName&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCreateFromBSDName&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>69ae08a90fe52a921ed423df38ed7480</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCopyDescription&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCopyDescription&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a7f8c63b1cdc39df79b7457e27ff4930</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCopyWholeDisk&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCopyWholeDisk&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cace8e35bed93ecdfa0455ac166aaa97</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>10</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCreateFromIOMedia&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCreateFromIOMedia&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>778f70549a15e78703b4dcb3a287df33</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>456</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>68</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADissenterCreate&apos; returns a Core Foundation object of type &apos;DADissenterRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADissenterCreate&apos; returns a Core Foundation object of type &apos;DADissenterRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dissenter&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;dissenter&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dissenter&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dissenter&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dissenter&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6c188b4716e84cdc55b93d40e6c2daf3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>458</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dissenter&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dissenter&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>61</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DASessionCreate&apos; returns a Core Foundation object of type &apos;DASessionRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DASessionCreate&apos; returns a Core Foundation object of type &apos;DASessionRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;session&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;session&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;session&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;session&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;session&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>35b9ac7ff198890c88d5839a898b7fea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>17</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>458</integer>
+ <integer>460</integer>
+ <integer>461</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CMCreateFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CMCreateFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;f&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;f&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;f&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>17d84d673b35235b52d8f8f00c1d1eea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLeakCoreMediaReferenceType</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>477</integer>
+ <integer>478</integer>
+ <integer>479</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CMGetFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CMGetFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1702285448a953b02ab74a8eb9a610d9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testOverReleaseMediaReferenceType</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>481</integer>
+ <integer>482</integer>
+ <integer>483</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>FALSE</string>
+ <key>message</key>
+ <string>FALSE</string>
+ </dict>
+ </array>
+ <key>description</key><string>FALSE</string>
+ <key>category</key><string>debug</string>
+ <key>type</key><string>Checking analyzer assumptions</string>
+ <key>check_name</key><string>debug.ExprInspection</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>78b71dc497a2059b950406cb2a1cfd01</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCMBufferQueueDequeueAndRetain</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>515</integer>
+ <integer>516</integer>
+ <integer>520</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;buffer&apos; is equal to &apos;queue&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;buffer&apos; is equal to &apos;queue&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>TRUE</string>
+ <key>message</key>
+ <string>TRUE</string>
+ </dict>
+ </array>
+ <key>description</key><string>TRUE</string>
+ <key>category</key><string>debug</string>
+ <key>type</key><string>Checking analyzer assumptions</string>
+ <key>check_name</key><string>debug.ExprInspection</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>78b71dc497a2059b950406cb2a1cfd01</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCMBufferQueueDequeueAndRetain</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>515</integer>
+ <integer>516</integer>
+ <integer>520</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CMBufferQueueDequeueAndRetain&apos; returns a Core Foundation object of type &apos;CMBufferRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CMBufferQueueDequeueAndRetain&apos; returns a Core Foundation object of type &apos;CMBufferRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;buffer&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;buffer&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;buffer&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>402566b4ddf1683dac1aefc1ab3e76e9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCMBufferQueueDequeueAndRetain</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>515</integer>
+ <integer>516</integer>
+ <integer>520</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>527</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>527</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayGetValueAtIndex&apos; returns a Core Foundation object of type &apos;const void *&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayGetValueAtIndex&apos; returns a Core Foundation object of type &apos;const void *&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>143ef5974bfece95e9894da5250aaff0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f11</string>
+ <key>issue_hash_function_offset</key><string>21</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>525</integer>
+ <integer>527</integer>
+ <integer>530</integer>
+ <integer>531</integer>
+ <integer>534</integer>
+ <integer>537</integer>
+ <integer>540</integer>
+ <integer>543</integer>
+ <integer>546</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;MyCreateFun&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;MyCreateFun&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;o&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>af4ad99c5fb565d82e1b4848aaca4e24</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f12</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>553</integer>
+ <integer>554</integer>
+ <integer>555</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>58a0b3f8332f42561f89b11f6eb5e91f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f13_autorelease_b</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>562</integer>
+ <integer>563</integer>
+ <integer>564</integer>
+ <integer>565</integer>
+ <integer>566</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>612dc6574d54c8010703a9776d8a4a0a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f13_autorelease_c</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>568</integer>
+ <integer>569</integer>
+ <integer>570</integer>
+ <integer>571</integer>
+ <integer>572</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c57037289bc3acc586de325df25951ed</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f13_autorelease_d</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>575</integer>
+ <integer>576</integer>
+ <integer>577</integer>
+ <integer>578</integer>
+ <integer>579</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6abb479bc4c7782a125d680fddf825ef</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f14_leakimmediately</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>586</integer>
+ <integer>587</integer>
+ <integer>588</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFRelease</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFRelease</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFRelease</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e7e2ba205af363f2c4cec7d01dcb6d6c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>606</integer>
+ <integer>607</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFRetain</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFRetain</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFRetain</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>64f4a3367d5d8e832ca8a23ca4d72717</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>9</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>609</integer>
+ <integer>610</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFMakeCollectable</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFMakeCollectable</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFMakeCollectable</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>61123dbb677396de5abbdd778c399140</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>12</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>612</integer>
+ <integer>613</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFAutorelease</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFAutorelease</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFAutorelease</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>965bca78fe04bfa55b6ea428da3c20e3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>15</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>615</integer>
+ <integer>616</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;isl_basic_map_cow&apos; returns an object of type &apos;isl_basic_map *&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;isl_basic_map_cow&apos; returns an object of type &apos;isl_basic_map *&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;bmap&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;bmap&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;bmap&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2cfebefee7b63ce3954419e571be4f63</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f18</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>654</integer>
+ <integer>656</integer>
+ <integer>657</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>55</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dcd3becc58a149abe6ade5598138d3dd</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>newString</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>681</integer>
+ <integer>682</integer>
+ <integer>683</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;name&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;name&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;kind&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;kind&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;kind&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6688c9cb12f0c76ec80eb03b1d2eddf8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6659160</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>690</integer>
+ <integer>691</integer>
+ <integer>696</integer>
+ <integer>702</integer>
+ <integer>703</integer>
+ <integer>704</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ <key>message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;kindC&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;kindC&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;kind&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;kind&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
+ <key>message</key>
+ <string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
+ </dict>
+ </array>
+ <key>description</key><string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2824c4e1d4ab13c3ae5a0ebb2aa4ed89</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6659160</string>
+ <key>issue_hash_function_offset</key><string>27</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>690</integer>
+ <integer>691</integer>
+ <integer>696</integer>
+ <integer>702</integer>
+ <integer>703</integer>
+ <integer>706</integer>
+ <integer>707</integer>
+ <integer>714</integer>
+ <integer>716</integer>
+ <integer>717</integer>
+ <integer>718</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ <key>message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;kind&apos; is non-nil</string>
+ <key>message</key>
+ <string>Assuming &apos;kind&apos; is non-nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d04966e9b8e981d8f69bf03823253033</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6659160</string>
+ <key>issue_hash_function_offset</key><string>33</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>690</integer>
+ <integer>691</integer>
+ <integer>696</integer>
+ <integer>702</integer>
+ <integer>703</integer>
+ <integer>706</integer>
+ <integer>707</integer>
+ <integer>714</integer>
+ <integer>715</integer>
+ <integer>716</integer>
+ <integer>717</integer>
+ <integer>718</integer>
+ <integer>720</integer>
+ <integer>723</integer>
+ <integer>724</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
+ <key>message</key>
+ <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1b35183a6aca4df5a8732c8da94e3205</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>pr3820_ReleaseAfterDealloc</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>744</integer>
+ <integer>745</integer>
+ <integer>746</integer>
+ <integer>747</integer>
+ <integer>748</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>754</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>754</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>54f2bd1534fa675b58c4f8eef3120373</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>pr3820_DeallocAfterRelease</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>752</integer>
+ <integer>753</integer>
+ <integer>754</integer>
+ <integer>755</integer>
+ <integer>756</integer>
+ <integer>757</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>84</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>055e6f3413539276fedeac241fccd9b8</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>applicationDidFinishLaunching:</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>808</integer>
+ <integer>809</integer>
+ <integer>811</integer>
+ <integer>813</integer>
+ <integer>814</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>84</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>444f6019b048a95dd71c6be49ecb73ff</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>radar10102244</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>820</integer>
+ <integer>821</integer>
+ <integer>822</integer>
+ <integer>824</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>832</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>832</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>641de26edd3d85ca241de577afbcda86</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6257780_Case1</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>831</integer>
+ <integer>832</integer>
+ <integer>833</integer>
+ <integer>834</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>909</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>909</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;RDar6320065Subclass *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;RDar6320065Subclass *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;RDar6320065Subclass *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8e8ae80fd006f27a952f77494bd1c05f</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>_initReturningNewClassBad</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>908</integer>
+ <integer>909</integer>
+ <integer>910</integer>
+ <integer>911</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>914</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>914</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>625e26ef3ae9de238f30175e4e9f4937</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>initReturningNewClassBad2</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>913</integer>
+ <integer>914</integer>
+ <integer>915</integer>
+ <integer>916</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;NoCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;NoCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>666dce676597e2cfa3199521864f7b96</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>NoCopyString</string>
+ <key>issue_hash_function_offset</key><string>0</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>954</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;noCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;noCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>31104cdb408dbc3faf693a5c31973486</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>noCopyString</string>
+ <key>issue_hash_function_offset</key><string>0</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>955</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;NoCopyString&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;NoCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;NoCopyString&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;NoCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>909638940b4d7020f51062089653b231</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_RDar6859457</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>954</integer>
+ <integer>958</integer>
+ <integer>959</integer>
+ <integer>960</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;noCopyString&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;noCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;noCopyString&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;noCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>54</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2a37743e32cfa0a86958fed215c30e87</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_RDar6859457</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>954</integer>
+ <integer>955</integer>
+ <integer>958</integer>
+ <integer>959</integer>
+ <integer>960</integer>
+ <integer>961</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;:&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;:&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>20b25f0ba6268e055d8491c67c6a26bd</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>:</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>993</integer>
+ <integer>994</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;id&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>706b9d732ece93a88487dbbf0b82fd23</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;id&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>631eebb0c921191c24734f98fe93f6bf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ <integer>1026</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>69</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGImageRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ee36a48521a32c183a086066d3c5ae1f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ <integer>1026</integer>
+ <integer>1027</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>69</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGImageRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>70a2dd4ee6b6f7caad87a46dc6dd3580</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ <integer>1026</integer>
+ <integer>1027</integer>
+ <integer>1028</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>45</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGLayerRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGLayerRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGLayerRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGLayerRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGLayerRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a82448687d1cbf5cb517914dbe6de4fe</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6945561</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1035</integer>
+ <integer>1036</integer>
+ <integer>1037</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOBSDNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOBSDNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>540e0145994c1e14ea750fe91a497855</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOBSDNameMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1044</integer>
+ <integer>1045</integer>
+ <integer>1046</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOServiceMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOServiceMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>99d7012d797e181ef8e9a289ee9099eb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1048</integer>
+ <integer>1049</integer>
+ <integer>1050</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOServiceNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOServiceNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5d956e58f05bcc1b67ff65e02cbba302</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceNameMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1052</integer>
+ <integer>1053</integer>
+ <integer>1054</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>65</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>84a53bfb58a3a929535b47e28b997382</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceAddNotification_wrapper</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1058</integer>
+ <integer>1059</integer>
+ <integer>1061</integer>
+ <integer>1062</integer>
+ <integer>1063</integer>
+ <integer>1064</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IORegistryEntryIDMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IORegistryEntryIDMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>36337ff486f6a8b702e68d13393bc975</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IORegistryEntryIDMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1067</integer>
+ <integer>1068</integer>
+ <integer>1069</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>55</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOOpenFirmwarePathMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOOpenFirmwarePathMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ee83ca968ddc2ecad7ae4318ce7d1d95</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOOpenFirmwarePathMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1071</integer>
+ <integer>1072</integer>
+ <integer>1073</integer>
+ <integer>1074</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e8c08b2b3d53f5890907888e16927805</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceGetMatchingService_wrapper</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1076</integer>
+ <integer>1077</integer>
+ <integer>1078</integer>
+ <integer>1079</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>31664b5acc7980da73f5545fb16b0910</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceGetMatchingServices_wrapper</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1082</integer>
+ <integer>1083</integer>
+ <integer>1084</integer>
+ <integer>1085</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>106</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>73</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6edae46016a9671e2d5400b100d5efb5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceAddMatchingNotification_wrapper</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1088</integer>
+ <integer>1089</integer>
+ <integer>1091</integer>
+ <integer>1092</integer>
+ <integer>1093</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1131</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented</string>
+ <key>message</key>
+ <string>Reference count decremented</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dcec4e2bd254a3c24e84e598b5a827bf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7152619</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>69</integer>
+ <integer>70</integer>
+ <integer>71</integer>
+ <integer>1130</integer>
+ <integer>1131</integer>
+ <integer>1132</integer>
+ <integer>1133</integer>
+ <integer>1134</integer>
+ <integer>1135</integer>
+ <integer>1136</integer>
+ <integer>1137</integer>
+ <integer>1138</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1147</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>67</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>69</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>67</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGColorSpaceRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>9317a6bf07dd10dc988f2415cc2c4ef7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7184450</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1145</integer>
+ <integer>1146</integer>
+ <integer>1147</integer>
+ <integer>1148</integer>
+ <integer>1149</integer>
+ <integer>1150</integer>
+ <integer>1151</integer>
+ <integer>1152</integer>
+ <integer>1153</integer>
+ <integer>1154</integer>
+ <integer>1155</integer>
+ <integer>1158</integer>
+ <integer>1159</integer>
+ <integer>1160</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>68</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGColorSpaceRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ec3e6216b279aa48d8403c6aab30d996</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7184450_pos</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1167</integer>
+ <integer>1168</integer>
+ <integer>1169</integer>
+ <integer>1170</integer>
+ <integer>1171</integer>
+ <integer>1172</integer>
+ <integer>1173</integer>
+ <integer>1174</integer>
+ <integer>1175</integer>
+ <integer>1176</integer>
+ <integer>1177</integer>
+ <integer>1180</integer>
+ <integer>1181</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>107</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGGradientCreateWithColorComponents&apos; returns a Core Foundation object of type &apos;CGGradientRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGGradientCreateWithColorComponents&apos; returns a Core Foundation object of type &apos;CGGradientRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;myGradient&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;myGradient&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;myGradient&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4b3d6bb6b8dc5c51b7dfa8554b24eb66</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7184450_pos</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1167</integer>
+ <integer>1168</integer>
+ <integer>1169</integer>
+ <integer>1170</integer>
+ <integer>1171</integer>
+ <integer>1172</integer>
+ <integer>1173</integer>
+ <integer>1174</integer>
+ <integer>1175</integer>
+ <integer>1176</integer>
+ <integer>1177</integer>
+ <integer>1180</integer>
+ <integer>1181</integer>
+ <integer>1183</integer>
+ <integer>1184</integer>
+ <integer>1185</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>42a83016e862ec323e24920873073a5a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7299394_positive</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1218</integer>
+ <integer>1219</integer>
+ <integer>1220</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1454</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1457</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGBitmapContextCreateWithData&apos; returns a Core Foundation object of type &apos;CGContextRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGBitmapContextCreateWithData&apos; returns a Core Foundation object of type &apos;CGContextRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGContextRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGContextRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGContextRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a416473fed3a9dbc6bfee885bee38216</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7358899</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1446</integer>
+ <integer>1447</integer>
+ <integer>1448</integer>
+ <integer>1449</integer>
+ <integer>1454</integer>
+ <integer>1456</integer>
+ <integer>1457</integer>
+ <integer>1458</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;y&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>980dd45e9cf6581dbc2be9ebfc500b7f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7265711_a</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1473</integer>
+ <integer>1474</integer>
+ <integer>1475</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1494</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1494</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ebf51fb2b16499cf3a5c57d251a91061</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7306898</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1491</integer>
+ <integer>1494</integer>
+ <integer>1495</integer>
+ <integer>1496</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bdc4aaf3d712232f4ae72dce230189f9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b767178ef573c7bd520dc62faabc32fc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ <integer>1506</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3dbe304966f8bffa6bdefc5f3ada7df6</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ <integer>1506</integer>
+ <integer>1507</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c519bce30f1da4bb6e3ecc46453d6958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ <integer>1506</integer>
+ <integer>1507</integer>
+ <integer>1508</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1174ccc2a30887ebf80fe25fc6722b1a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr_1</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1534</integer>
+ <integer>1535</integer>
+ <integer>1536</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;NSString *&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;NSString *&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ce9963dd1c85ac22cea4e4fef615354e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr_1b</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1538</integer>
+ <integer>1539</integer>
+ <integer>1540</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str2&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0183088266857082f35eb17f1377fd69</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr1c</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1542</integer>
+ <integer>1543</integer>
+ <integer>1544</integer>
+ <integer>1545</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str4&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str4&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str4&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>352a17ef8eddd3aa5f7f6e74a74a4df3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr1c</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1542</integer>
+ <integer>1543</integer>
+ <integer>1544</integer>
+ <integer>1545</integer>
+ <integer>1546</integer>
+ <integer>1547</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of TestOwnershipAttr with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of TestOwnershipAttr with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d0e564404585060990202acb33f0bb1e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testattr2_a</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1549</integer>
+ <integer>1550</integer>
+ <integer>1551</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>567dfcbc22471ca4ba9f2fccd9ff14fb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testattr2_b</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1553</integer>
+ <integer>1554</integer>
+ <integer>1555</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>83cd2670977d513443836653fee8147b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testattr2_b_11358224_self_assign_looses_the_leak</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1557</integer>
+ <integer>1558</integer>
+ <integer>1559</integer>
+ <integer>1560</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method that is annotated as NS_RETURNS_NOT_RETAINED</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method that is annotated as NS_RETURNS_NOT_RETAINED</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f83246e7e738918426df1adc915f4eca</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>newString</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1589</integer>
+ <integer>1590</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsCFRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsCFRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1614</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;newCFRetainedAsCFNoAttr&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;newCFRetainedAsCFNoAttr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1614</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1614</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;returnsCFRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;returnsCFRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsCFRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsCFRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5f233261d96f1d461af36fc3e0efc8eb</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>newCFRetainedAsCFNoAttr</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1604</integer>
+ <integer>1605</integer>
+ <integer>1606</integer>
+ <integer>1614</integer>
+ <integer>1615</integer>
+ <integer>1622</integer>
+ <integer>1623</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;alsoReturnsRetained&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;alsoReturnsRetained&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetained&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetained&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFDateRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7ee55b74b5ee01c6ffa2a3d83c8cf88b</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>alsoReturnsRetained</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1604</integer>
+ <integer>1605</integer>
+ <integer>1606</integer>
+ <integer>1626</integer>
+ <integer>1627</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;alsoReturnsRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;alsoReturnsRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetainedAsCF&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetainedAsCF&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFDateRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>177b2cf7eb3d8334393ee0861f5a38ac</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>alsoReturnsRetainedAsCF</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1604</integer>
+ <integer>1605</integer>
+ <integer>1606</integer>
+ <integer>1630</integer>
+ <integer>1631</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1651</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1651</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>82</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>85e9d8130a1f1ec37f0ba26746abd749</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_panic_negative</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1650</integer>
+ <integer>1651</integer>
+ <integer>1652</integer>
+ <integer>1653</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1662</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1662</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>82</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4a0b16976e0517b38b2ccc16e2928c2e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_panic_neg_2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1661</integer>
+ <integer>1662</integer>
+ <integer>1663</integer>
+ <integer>1664</integer>
+ <integer>1666</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>af73d9c62952a300a7c393ebd5073f75</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_blocks_1_pos</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1685</integer>
+ <integer>1686</integer>
+ <integer>1687</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_blocks_1_indirect_retain_via_call&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_blocks_1_indirect_retain_via_call&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>771b2a332053388ffbdd9ba74ea84c5e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_blocks_1_indirect_retain_via_call</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1706</integer>
+ <integer>1707</integer>
+ <integer>1708</integer>
+ <integer>1709</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1759</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1759</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;error_to_dump&apos; is not equal to null</string>
+ <key>message</key>
+ <string>Assuming &apos;error_to_dump&apos; is not equal to null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFErrorCopyUserInfo&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFErrorCopyUserInfo&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;info&apos; is not equal to null</string>
+ <key>message</key>
+ <string>Assuming &apos;info&apos; is not equal to null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;info&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;info&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;info&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>39f8c30f7436f678d5259c0fdd3a0dad</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_8724287</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1757</integer>
+ <integer>1758</integer>
+ <integer>1759</integer>
+ <integer>1761</integer>
+ <integer>1762</integer>
+ <integer>1763</integer>
+ <integer>1765</integer>
+ <integer>1767</integer>
+ <integer>1770</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_createno&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_createno&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>107e3efdeb8cdff4bef4c64183c4f6fa</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camelcase_createno</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1814</integer>
+ <integer>1815</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_copying&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_copying&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>20c973a013858abb0a926276c956f858</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camelcase_copying</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1822</integer>
+ <integer>1823</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_creat&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_creat&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>80ee99e51561a37297429740e3a4da0c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camel_creat</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1843</integer>
+ <integer>1844</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_copymachine&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_copymachine&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a4e28a04f6a8d87c8aaf4d71c37cac0f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camel_copymachine</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1855</integer>
+ <integer>1856</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1876</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1876</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;vals&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;vals&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;vals&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6b727a438d8411c058fd32867b9402bc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6582778</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1875</integer>
+ <integer>1876</integer>
+ <integer>1877</integer>
+ <integer>1878</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1902</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1902</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>64</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b39dcf9df7cec8dd73cbbe25b2a7d6c5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar10232019_positive</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1901</integer>
+ <integer>1902</integer>
+ <integer>1904</integer>
+ <integer>1905</integer>
+ <integer>1907</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a501f743b22f1feb5dc317fcad4f7556</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>56</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a2&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a141a6ad33e8ff2ae3b13da0ad36ebc5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>12</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a3&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a3&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a3&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2b072d75e8da8e3fe8f7968a85efb37c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>20</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ <integer>2051</integer>
+ <integer>2052</integer>
+ <integer>2053</integer>
+ <integer>2054</integer>
+ <integer>2055</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0bfdfb7e392626e0fccc6ab9f58f1ca8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>28</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ <integer>2051</integer>
+ <integer>2052</integer>
+ <integer>2053</integer>
+ <integer>2054</integer>
+ <integer>2055</integer>
+ <integer>2059</integer>
+ <integer>2060</integer>
+ <integer>2061</integer>
+ <integer>2063</integer>
+ <integer>2064</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSDictionary literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSDictionary literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ff7c34e661a42d06a7fb3e9669e70339</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>37</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ <integer>2051</integer>
+ <integer>2052</integer>
+ <integer>2053</integer>
+ <integer>2054</integer>
+ <integer>2055</integer>
+ <integer>2059</integer>
+ <integer>2060</integer>
+ <integer>2061</integer>
+ <integer>2063</integer>
+ <integer>2064</integer>
+ <integer>2068</integer>
+ <integer>2069</integer>
+ <integer>2070</integer>
+ <integer>2072</integer>
+ <integer>2073</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>73e84c042932d2e17e00f00dc3d36d5a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_integer_literals</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2077</integer>
+ <integer>2078</integer>
+ <integer>2079</integer>
+ <integer>2080</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>465e592d4f7a187717d00b8154a614b5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_boxed_expressions</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2082</integer>
+ <integer>2083</integer>
+ <integer>2084</integer>
+ <integer>2086</integer>
+ <integer>2087</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSString boxed expression produces an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSString boxed expression produces an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c701bd0c60f51d96c047aa78c9e0eb99</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_boxed_expressions</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2082</integer>
+ <integer>2083</integer>
+ <integer>2084</integer>
+ <integer>2086</integer>
+ <integer>2087</integer>
+ <integer>2088</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2094</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2094</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is &lt;= 2</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is &lt;= 2</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a4cedbb647e9632da7a5072cb839e54a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar11400885</string>
+ <key>issue_hash_function_offset</key><string>9</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2091</integer>
+ <integer>2092</integer>
+ <integer>2094</integer>
+ <integer>2095</integer>
+ <integer>2098</integer>
+ <integer>2099</integer>
+ <integer>2100</integer>
+ <integer>2101</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2119</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>fd9427d86a2357fd92478c9c7abbc1f4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testConsumeAndStopTracking</string>
+ <key>issue_hash_function_offset</key><string>10</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2118</integer>
+ <integer>2119</integer>
+ <integer>2120</integer>
+ <integer>2122</integer>
+ <integer>2123</integer>
+ <integer>2127</integer>
+ <integer>2128</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2132</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2132</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0e65e51476e5671dcd37f632806e5147</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCFConsumeAndStopTracking</string>
+ <key>issue_hash_function_offset</key><string>10</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2131</integer>
+ <integer>2132</integer>
+ <integer>2133</integer>
+ <integer>2135</integer>
+ <integer>2136</integer>
+ <integer>2140</integer>
+ <integer>2141</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateMyCFType&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateMyCFType&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a0ba9c47505e923763ea5323ad2f71b7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_custom_cf</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2152</integer>
+ <integer>2153</integer>
+ <integer>2154</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;makeCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;makeCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;obj&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7a6cf8cb3c5e0ca3125d7e27695a810a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCustomReturnsRetained</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2187</integer>
+ <integer>2188</integer>
+ <integer>2189</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;getCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;getCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>810fce32373fe40ba8e2d0894d46f667</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCustomReturnsNotRetained</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2191</integer>
+ <integer>2192</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of MyObj12706177 with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of MyObj12706177 with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;initX&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;initX&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2204</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test12706177&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test12706177&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2204</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2204</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;Cond&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;Cond&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2206</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2206</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;initX&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;initX&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;MyObj12706177 *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;MyObj12706177 *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;MyObj12706177 *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>68ee7961ffb62c575cc2298cb4836090</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test12706177</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2204</integer>
+ <integer>2205</integer>
+ <integer>2206</integer>
+ <integer>2210</integer>
+ <integer>2211</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1dc376fbbe90d14b6766585a0e2b7bee</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>getIncorrectlyAutoreleasedCFType</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2225</integer>
+ <integer>2227</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6ae8ea9fe4bf203e6b7bfaf649a6ca6a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>createIncorrectlyAutoreleasedCFType</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2230</integer>
+ <integer>2232</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d4e28f96fc8610b5b4b849f4760956eb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>useAfterRelease</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2244</integer>
+ <integer>2247</integer>
+ <integer>2248</integer>
+ <integer>2251</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;obj&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7986c4b7fb29301c109343dfe4155202</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testAutoreleaseReturnsInput</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2254</integer>
+ <integer>2256</integer>
+ <integer>2257</integer>
+ <integer>2258</integer>
+ <integer>2259</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>70</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>61</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;arr&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;arr&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;arr&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2e0dbfdf379acf2f09e46db47d753e8a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>autoreleaseReturningTypedObject</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2275</integer>
+ <integer>2276</integer>
+ <integer>2277</integer>
+ <integer>2278</integer>
+ <integer>2279</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2290</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2290</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>41a2d6f91fdfa9b5f396102a60571e21</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>autoreleaseObjC</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2289</integer>
+ <integer>2290</integer>
+ <integer>2291</integer>
+ <integer>2293</integer>
+ <integer>2294</integer>
+ <integer>2295</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2345</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2345</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;getViaParam&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ <key>message</key>
+ <string>Call to function &apos;getViaParam&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>95dd5581ae4195b71e9a11f34290af5d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCFReturnsNotRetained</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2343</integer>
+ <integer>2345</integer>
+ <integer>2346</integer>
+ <integer>2347</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2352</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2352</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;getViaParam2&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ <key>message</key>
+ <string>Call to function &apos;getViaParam2&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>014103674df4a8a65a96bcdf936637a2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCFReturnsNotRetainedAnnotated</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2350</integer>
+ <integer>2352</integer>
+ <integer>2353</integer>
+ <integer>2354</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/Volumes/Transcend/code/monorepo/llvm-project/clang/test/Analysis/retain-release.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist b/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
new file mode 100644
index 000000000000..88e92cb3e64b
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
@@ -0,0 +1,26182 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>348</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>348</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>349</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>350</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>351</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5928b2a4699cbae0686391c20e639007</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f1</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>354</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>347</integer>
+ <integer>348</integer>
+ <integer>349</integer>
+ <integer>350</integer>
+ <integer>351</integer>
+ <integer>352</integer>
+ <integer>353</integer>
+ <integer>354</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>359</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>359</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>360</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>361</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count decremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>362</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>364</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6b2e175938153ac041f52ebbf50b1f43</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f2</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>365</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>358</integer>
+ <integer>359</integer>
+ <integer>360</integer>
+ <integer>361</integer>
+ <integer>362</integer>
+ <integer>363</integer>
+ <integer>364</integer>
+ <integer>365</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>395</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>395</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>396</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>398</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3fdbd844ddb925306ba2bb1b3626f310</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f5</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>401</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>394</integer>
+ <integer>395</integer>
+ <integer>396</integer>
+ <integer>398</integer>
+ <integer>401</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>407</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>408</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8529da75e357c59fb0a7fefb0b6e0952</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f6</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>409</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>406</integer>
+ <integer>407</integer>
+ <integer>408</integer>
+ <integer>409</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>416</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>eb0faa12081b1e28b218e4c6e53d57ec</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f7</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>414</integer>
+ <integer>415</integer>
+ <integer>416</integer>
+ <integer>417</integer>
+ <integer>418</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>415</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>417</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is returned from a function whose name (&apos;f7&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is returned from a function whose name (&apos;f7&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>404d4de8faa444bc52fd510380bd0a63</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f7</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>418</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>414</integer>
+ <integer>415</integer>
+ <integer>416</integer>
+ <integer>417</integer>
+ <integer>418</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;MyDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;MyDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>426</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>427</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>251dff6727b3d99ec95caa28672669ea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f8</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>428</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>425</integer>
+ <integer>426</integer>
+ <integer>427</integer>
+ <integer>428</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>432</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>432</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>433</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;date&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;date&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4af5d8d1438976cc7fa006af5f843b13</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f9</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>435</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>431</integer>
+ <integer>432</integer>
+ <integer>433</integer>
+ <integer>435</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCreateFromBSDName&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCreateFromBSDName&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>69ae08a90fe52a921ed423df38ed7480</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCopyDescription&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCopyDescription&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a7f8c63b1cdc39df79b7457e27ff4930</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCopyWholeDisk&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCopyWholeDisk&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cace8e35bed93ecdfa0455ac166aaa97</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>10</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADiskCreateFromIOMedia&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADiskCreateFromIOMedia&apos; returns a Core Foundation object of type &apos;DADiskRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>778f70549a15e78703b4dcb3a287df33</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>456</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>457</integer>
+ <key>col</key><integer>68</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DADissenterCreate&apos; returns a Core Foundation object of type &apos;DADissenterRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DADissenterCreate&apos; returns a Core Foundation object of type &apos;DADissenterRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dissenter&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;dissenter&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dissenter&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dissenter&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dissenter&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6c188b4716e84cdc55b93d40e6c2daf3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>458</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>444</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>445</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>447</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>448</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>450</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dict&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>451</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>453</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;disk&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>454</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>456</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;dissenter&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;dissenter&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>458</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>61</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;DASessionCreate&apos; returns a Core Foundation object of type &apos;DASessionRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;DASessionCreate&apos; returns a Core Foundation object of type &apos;DASessionRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>460</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;session&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;session&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;session&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;session&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;session&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>35b9ac7ff198890c88d5839a898b7fea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f10</string>
+ <key>issue_hash_function_offset</key><string>17</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>461</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>443</integer>
+ <integer>444</integer>
+ <integer>445</integer>
+ <integer>447</integer>
+ <integer>448</integer>
+ <integer>450</integer>
+ <integer>451</integer>
+ <integer>453</integer>
+ <integer>454</integer>
+ <integer>456</integer>
+ <integer>457</integer>
+ <integer>458</integer>
+ <integer>460</integer>
+ <integer>461</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CMCreateFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CMCreateFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>478</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;f&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;f&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;f&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>17d84d673b35235b52d8f8f00c1d1eea</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testLeakCoreMediaReferenceType</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>479</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>477</integer>
+ <integer>478</integer>
+ <integer>479</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CMGetFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CMGetFooRef&apos; returns a Core Foundation object of type &apos;CMFooRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>482</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1702285448a953b02ab74a8eb9a610d9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testOverReleaseMediaReferenceType</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>483</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>481</integer>
+ <integer>482</integer>
+ <integer>483</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>FALSE</string>
+ <key>message</key>
+ <string>FALSE</string>
+ </dict>
+ </array>
+ <key>description</key><string>FALSE</string>
+ <key>category</key><string>debug</string>
+ <key>type</key><string>Checking analyzer assumptions</string>
+ <key>check_name</key><string>debug.ExprInspection</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>78b71dc497a2059b950406cb2a1cfd01</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCMBufferQueueDequeueAndRetain</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>515</integer>
+ <integer>516</integer>
+ <integer>520</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;buffer&apos; is equal to &apos;queue&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;buffer&apos; is equal to &apos;queue&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>TRUE</string>
+ <key>message</key>
+ <string>TRUE</string>
+ </dict>
+ </array>
+ <key>description</key><string>TRUE</string>
+ <key>category</key><string>debug</string>
+ <key>type</key><string>Checking analyzer assumptions</string>
+ <key>check_name</key><string>debug.ExprInspection</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>78b71dc497a2059b950406cb2a1cfd01</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCMBufferQueueDequeueAndRetain</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>515</integer>
+ <integer>516</integer>
+ <integer>520</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CMBufferQueueDequeueAndRetain&apos; returns a Core Foundation object of type &apos;CMBufferRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CMBufferQueueDequeueAndRetain&apos; returns a Core Foundation object of type &apos;CMBufferRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>516</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ <key>message</key>
+ <string>Assuming &apos;buffer&apos; is not equal to &apos;queue&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;buffer&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;buffer&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;buffer&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>402566b4ddf1683dac1aefc1ab3e76e9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCMBufferQueueDequeueAndRetain</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>520</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>515</integer>
+ <integer>516</integer>
+ <integer>520</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>527</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>527</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayGetValueAtIndex&apos; returns a Core Foundation object of type &apos;const void *&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayGetValueAtIndex&apos; returns a Core Foundation object of type &apos;const void *&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>540</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>143ef5974bfece95e9894da5250aaff0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f11</string>
+ <key>issue_hash_function_offset</key><string>21</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>525</integer>
+ <integer>527</integer>
+ <integer>530</integer>
+ <integer>531</integer>
+ <integer>534</integer>
+ <integer>537</integer>
+ <integer>540</integer>
+ <integer>543</integer>
+ <integer>546</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;MyCreateFun&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;MyCreateFun&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>554</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;o&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>af4ad99c5fb565d82e1b4848aaca4e24</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f12</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>553</integer>
+ <integer>554</integer>
+ <integer>555</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>563</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>564</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>565</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>58a0b3f8332f42561f89b11f6eb5e91f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f13_autorelease_b</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>566</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>562</integer>
+ <integer>563</integer>
+ <integer>564</integer>
+ <integer>565</integer>
+ <integer>566</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>569</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>570</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>571</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>612dc6574d54c8010703a9776d8a4a0a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f13_autorelease_c</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>572</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>568</integer>
+ <integer>569</integer>
+ <integer>570</integer>
+ <integer>571</integer>
+ <integer>572</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>576</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>577</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>578</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>75</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c57037289bc3acc586de325df25951ed</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f13_autorelease_d</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>579</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>575</integer>
+ <integer>576</integer>
+ <integer>577</integer>
+ <integer>578</integer>
+ <integer>579</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>587</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6abb479bc4c7782a125d680fddf825ef</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f14_leakimmediately</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>588</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>586</integer>
+ <integer>587</integer>
+ <integer>588</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFRelease</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFRelease</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFRelease</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e7e2ba205af363f2c4cec7d01dcb6d6c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>607</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>606</integer>
+ <integer>607</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFRetain</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFRetain</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFRetain</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>64f4a3367d5d8e832ca8a23ca4d72717</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>9</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>610</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>609</integer>
+ <integer>610</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFMakeCollectable</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFMakeCollectable</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFMakeCollectable</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>61123dbb677396de5abbdd778c399140</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>12</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>613</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>612</integer>
+ <integer>613</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;p&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>602</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>605</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFAutorelease</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFAutorelease</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFAutorelease</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>965bca78fe04bfa55b6ea428da3c20e3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f16</string>
+ <key>issue_hash_function_offset</key><string>15</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>616</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>601</integer>
+ <integer>602</integer>
+ <integer>605</integer>
+ <integer>615</integer>
+ <integer>616</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;isl_basic_map_cow&apos; returns an object of type &apos;isl_basic_map *&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;isl_basic_map_cow&apos; returns an object of type &apos;isl_basic_map *&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>656</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;bmap&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;bmap&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;bmap&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2cfebefee7b63ce3954419e571be4f63</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>f18</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>657</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>654</integer>
+ <integer>656</integer>
+ <integer>657</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>55</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>682</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dcd3becc58a149abe6ade5598138d3dd</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>newString</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>683</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>681</integer>
+ <integer>682</integer>
+ <integer>683</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;name&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;name&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;kind&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;kind&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;kind&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6688c9cb12f0c76ec80eb03b1d2eddf8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6659160</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>704</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>690</integer>
+ <integer>691</integer>
+ <integer>696</integer>
+ <integer>702</integer>
+ <integer>703</integer>
+ <integer>704</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ <key>message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;kindC&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;kindC&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;kind&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;kind&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
+ <key>message</key>
+ <string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
+ </dict>
+ </array>
+ <key>description</key><string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2824c4e1d4ab13c3ae5a0ebb2aa4ed89</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6659160</string>
+ <key>issue_hash_function_offset</key><string>27</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>690</integer>
+ <integer>691</integer>
+ <integer>696</integer>
+ <integer>702</integer>
+ <integer>703</integer>
+ <integer>706</integer>
+ <integer>707</integer>
+ <integer>714</integer>
+ <integer>716</integer>
+ <integer>717</integer>
+ <integer>718</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>696</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>702</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ <key>message</key>
+ <string>Assuming &apos;name&apos; is non-nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>703</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>706</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;kind&apos; is non-nil</string>
+ <key>message</key>
+ <string>Assuming &apos;kind&apos; is non-nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>714</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>715</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>716</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>717</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>718</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>720</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>723</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d04966e9b8e981d8f69bf03823253033</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6659160</string>
+ <key>issue_hash_function_offset</key><string>33</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>724</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>690</integer>
+ <integer>691</integer>
+ <integer>696</integer>
+ <integer>702</integer>
+ <integer>703</integer>
+ <integer>706</integer>
+ <integer>707</integer>
+ <integer>714</integer>
+ <integer>715</integer>
+ <integer>716</integer>
+ <integer>717</integer>
+ <integer>718</integer>
+ <integer>720</integer>
+ <integer>723</integer>
+ <integer>724</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>746</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
+ <key>message</key>
+ <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>747</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1b35183a6aca4df5a8732c8da94e3205</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>pr3820_ReleaseAfterDealloc</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>748</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>744</integer>
+ <integer>745</integer>
+ <integer>746</integer>
+ <integer>747</integer>
+ <integer>748</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>754</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>754</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>755</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>756</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>54f2bd1534fa675b58c4f8eef3120373</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>pr3820_DeallocAfterRelease</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>757</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>752</integer>
+ <integer>753</integer>
+ <integer>754</integer>
+ <integer>755</integer>
+ <integer>756</integer>
+ <integer>757</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>84</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>809</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>813</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>055e6f3413539276fedeac241fccd9b8</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>applicationDidFinishLaunching:</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>814</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>808</integer>
+ <integer>809</integer>
+ <integer>811</integer>
+ <integer>813</integer>
+ <integer>814</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>84</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>76</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>821</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>822</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>444f6019b048a95dd71c6be49ecb73ff</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>radar10102244</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>824</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>820</integer>
+ <integer>821</integer>
+ <integer>822</integer>
+ <integer>824</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>832</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>832</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>833</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>641de26edd3d85ca241de577afbcda86</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_6257780_Case1</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>834</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>831</integer>
+ <integer>832</integer>
+ <integer>833</integer>
+ <integer>834</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>909</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>909</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>910</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;RDar6320065Subclass *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;RDar6320065Subclass *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;RDar6320065Subclass *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8e8ae80fd006f27a952f77494bd1c05f</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>_initReturningNewClassBad</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>911</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>908</integer>
+ <integer>909</integer>
+ <integer>910</integer>
+ <integer>911</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>914</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>914</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of RDar6320065Subclass with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>915</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>625e26ef3ae9de238f30175e4e9f4937</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>initReturningNewClassBad2</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>916</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>913</integer>
+ <integer>914</integer>
+ <integer>915</integer>
+ <integer>916</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;NoCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;NoCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>666dce676597e2cfa3199521864f7b96</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>NoCopyString</string>
+ <key>issue_hash_function_offset</key><string>0</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>954</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;noCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;noCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>31104cdb408dbc3faf693a5c31973486</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>noCopyString</string>
+ <key>issue_hash_function_offset</key><string>0</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>955</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;NoCopyString&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;NoCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>954</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;NoCopyString&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;NoCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>909638940b4d7020f51062089653b231</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_RDar6859457</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>954</integer>
+ <integer>958</integer>
+ <integer>959</integer>
+ <integer>960</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>959</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;noCopyString&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;noCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_RDar6859457&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>955</integer>
+ <key>col</key><integer>59</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;noCopyString&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;noCopyString&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>960</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>54</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2a37743e32cfa0a86958fed215c30e87</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_RDar6859457</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>961</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>954</integer>
+ <integer>955</integer>
+ <integer>958</integer>
+ <integer>959</integer>
+ <integer>960</integer>
+ <integer>961</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;:&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method whose name (&apos;:&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>20b25f0ba6268e055d8491c67c6a26bd</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>:</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>994</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>993</integer>
+ <integer>994</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;id&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>706b9d732ece93a88487dbbf0b82fd23</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1025</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;id&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;id&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>631eebb0c921191c24734f98fe93f6bf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ <integer>1026</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1026</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGImageRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ee36a48521a32c183a086066d3c5ae1f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ <integer>1026</integer>
+ <integer>1027</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1024</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>69</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGImageRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1027</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGImageRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGImageRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>70a2dd4ee6b6f7caad87a46dc6dd3580</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6902710</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1028</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1021</integer>
+ <integer>1022</integer>
+ <integer>1023</integer>
+ <integer>1024</integer>
+ <integer>1025</integer>
+ <integer>1026</integer>
+ <integer>1027</integer>
+ <integer>1028</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>45</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGLayerRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;CGLayerRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1036</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGLayerRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGLayerRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGLayerRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a82448687d1cbf5cb517914dbe6de4fe</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6945561</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1037</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1035</integer>
+ <integer>1036</integer>
+ <integer>1037</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOBSDNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOBSDNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1045</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>540e0145994c1e14ea750fe91a497855</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOBSDNameMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1046</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1044</integer>
+ <integer>1045</integer>
+ <integer>1046</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOServiceMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOServiceMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1049</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>99d7012d797e181ef8e9a289ee9099eb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1050</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1048</integer>
+ <integer>1049</integer>
+ <integer>1050</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOServiceNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOServiceNameMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1053</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5d956e58f05bcc1b67ff65e02cbba302</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceNameMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1054</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1052</integer>
+ <integer>1053</integer>
+ <integer>1054</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1061</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1062</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>58</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>65</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>84a53bfb58a3a929535b47e28b997382</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceAddNotification_wrapper</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1063</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1058</integer>
+ <integer>1059</integer>
+ <integer>1061</integer>
+ <integer>1062</integer>
+ <integer>1063</integer>
+ <integer>1064</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IORegistryEntryIDMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IORegistryEntryIDMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1068</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>36337ff486f6a8b702e68d13393bc975</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IORegistryEntryIDMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1069</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1067</integer>
+ <integer>1068</integer>
+ <integer>1069</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>55</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;IOOpenFirmwarePathMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;IOOpenFirmwarePathMatching&apos; returns a Core Foundation object of type &apos;CFMutableDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1073</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableDictionaryRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableDictionaryRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ee83ca968ddc2ecad7ae4318ce7d1d95</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOOpenFirmwarePathMatching_wrapper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1074</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1071</integer>
+ <integer>1072</integer>
+ <integer>1073</integer>
+ <integer>1074</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1077</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1078</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>e8c08b2b3d53f5890907888e16927805</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceGetMatchingService_wrapper</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1076</integer>
+ <integer>1077</integer>
+ <integer>1078</integer>
+ <integer>1079</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1083</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1084</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>31664b5acc7980da73f5545fb16b0910</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceGetMatchingServices_wrapper</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1085</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1082</integer>
+ <integer>1083</integer>
+ <integer>1084</integer>
+ <integer>1085</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1091</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>106</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>73</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1092</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6edae46016a9671e2d5400b100d5efb5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>IOServiceAddMatchingNotification_wrapper</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1093</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1088</integer>
+ <integer>1089</integer>
+ <integer>1091</integer>
+ <integer>1092</integer>
+ <integer>1093</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1131</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1134</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count decremented</string>
+ <key>message</key>
+ <string>Reference count decremented</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1136</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dcec4e2bd254a3c24e84e598b5a827bf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7152619</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1138</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>63</integer>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>69</integer>
+ <integer>70</integer>
+ <integer>71</integer>
+ <integer>1130</integer>
+ <integer>1131</integer>
+ <integer>1132</integer>
+ <integer>1133</integer>
+ <integer>1134</integer>
+ <integer>1135</integer>
+ <integer>1136</integer>
+ <integer>1137</integer>
+ <integer>1138</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1147</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>67</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>69</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1159</integer>
+ <key>col</key><integer>67</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGColorSpaceRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>9317a6bf07dd10dc988f2415cc2c4ef7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7184450</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1158</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1145</integer>
+ <integer>1146</integer>
+ <integer>1147</integer>
+ <integer>1148</integer>
+ <integer>1149</integer>
+ <integer>1150</integer>
+ <integer>1151</integer>
+ <integer>1152</integer>
+ <integer>1153</integer>
+ <integer>1154</integer>
+ <integer>1155</integer>
+ <integer>1158</integer>
+ <integer>1159</integer>
+ <integer>1160</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>68</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object of type &apos;CGColorSpaceRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGColorSpaceRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGColorSpaceRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ec3e6216b279aa48d8403c6aab30d996</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7184450_pos</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1167</integer>
+ <integer>1168</integer>
+ <integer>1169</integer>
+ <integer>1170</integer>
+ <integer>1171</integer>
+ <integer>1172</integer>
+ <integer>1173</integer>
+ <integer>1174</integer>
+ <integer>1175</integer>
+ <integer>1176</integer>
+ <integer>1177</integer>
+ <integer>1180</integer>
+ <integer>1181</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1169</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1180</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>107</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGGradientCreateWithColorComponents&apos; returns a Core Foundation object of type &apos;CGGradientRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGGradientCreateWithColorComponents&apos; returns a Core Foundation object of type &apos;CGGradientRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1181</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1183</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;myGradient&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;myGradient&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;myGradient&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4b3d6bb6b8dc5c51b7dfa8554b24eb66</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7184450_pos</string>
+ <key>issue_hash_function_offset</key><string>13</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1185</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1167</integer>
+ <integer>1168</integer>
+ <integer>1169</integer>
+ <integer>1170</integer>
+ <integer>1171</integer>
+ <integer>1172</integer>
+ <integer>1173</integer>
+ <integer>1174</integer>
+ <integer>1175</integer>
+ <integer>1176</integer>
+ <integer>1177</integer>
+ <integer>1180</integer>
+ <integer>1181</integer>
+ <integer>1183</integer>
+ <integer>1184</integer>
+ <integer>1185</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1219</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>42a83016e862ec323e24920873073a5a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7299394_positive</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1220</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1218</integer>
+ <integer>1219</integer>
+ <integer>1220</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1454</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1454</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1457</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CGBitmapContextCreateWithData&apos; returns a Core Foundation object of type &apos;CGContextRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CGBitmapContextCreateWithData&apos; returns a Core Foundation object of type &apos;CGContextRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1456</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CGContextRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CGContextRef&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CGContextRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a416473fed3a9dbc6bfee885bee38216</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_7358899</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1458</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1446</integer>
+ <integer>1447</integer>
+ <integer>1448</integer>
+ <integer>1449</integer>
+ <integer>1454</integer>
+ <integer>1456</integer>
+ <integer>1457</integer>
+ <integer>1458</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1474</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;y&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>980dd45e9cf6581dbc2be9ebfc500b7f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7265711_a</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1475</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1473</integer>
+ <integer>1474</integer>
+ <integer>1475</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1494</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1494</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1495</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ebf51fb2b16499cf3a5c57d251a91061</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7306898</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1496</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1491</integer>
+ <integer>1494</integer>
+ <integer>1495</integer>
+ <integer>1496</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>bdc4aaf3d712232f4ae72dce230189f9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b767178ef573c7bd520dc62faabc32fc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1506</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ <integer>1506</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3dbe304966f8bffa6bdefc5f3ada7df6</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1507</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ <integer>1506</integer>
+ <integer>1507</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1505</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
+ <key>message</key>
+ <string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
+ </dict>
+ </array>
+ <key>description</key><string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>message incorrectly sent to class instead of class instance</string>
+ <key>check_name</key><string>osx.cocoa.ClassRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c519bce30f1da4bb6e3ecc46453d6958</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar7252064</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1508</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1504</integer>
+ <integer>1505</integer>
+ <integer>1506</integer>
+ <integer>1507</integer>
+ <integer>1508</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1535</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1174ccc2a30887ebf80fe25fc6722b1a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr_1</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1536</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1534</integer>
+ <integer>1535</integer>
+ <integer>1536</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns a Core Foundation object of type &apos;NSString *&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns a Core Foundation object of type &apos;NSString *&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1539</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ce9963dd1c85ac22cea4e4fef615354e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr_1b</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1540</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1538</integer>
+ <integer>1539</integer>
+ <integer>1540</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1544</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str2&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0183088266857082f35eb17f1377fd69</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr1c</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1545</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1542</integer>
+ <integer>1543</integer>
+ <integer>1544</integer>
+ <integer>1545</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1543</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +0 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>46</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1546</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;str4&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;str4&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;str4&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>352a17ef8eddd3aa5f7f6e74a74a4df3</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_attr1c</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1547</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1542</integer>
+ <integer>1543</integer>
+ <integer>1544</integer>
+ <integer>1545</integer>
+ <integer>1546</integer>
+ <integer>1547</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of TestOwnershipAttr with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of TestOwnershipAttr with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1550</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d0e564404585060990202acb33f0bb1e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testattr2_a</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1551</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1549</integer>
+ <integer>1550</integer>
+ <integer>1551</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1554</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>567dfcbc22471ca4ba9f2fccd9ff14fb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testattr2_b</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1555</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1553</integer>
+ <integer>1554</integer>
+ <integer>1555</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an Objective-C object with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1558</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1559</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>83cd2670977d513443836653fee8147b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testattr2_b_11358224_self_assign_looses_the_leak</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1560</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1557</integer>
+ <integer>1558</integer>
+ <integer>1559</integer>
+ <integer>1560</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method that is annotated as NS_RETURNS_NOT_RETAINED</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;NSString *&apos; is returned from a method that is annotated as NS_RETURNS_NOT_RETAINED</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;NSString *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f83246e7e738918426df1adc915f4eca</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>newString</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1590</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1589</integer>
+ <integer>1590</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsCFRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsCFRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1614</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;newCFRetainedAsCFNoAttr&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;newCFRetainedAsCFNoAttr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1614</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1614</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;returnsCFRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;returnsCFRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1615</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsCFRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsCFRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5f233261d96f1d461af36fc3e0efc8eb</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>newCFRetainedAsCFNoAttr</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1623</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1604</integer>
+ <integer>1605</integer>
+ <integer>1606</integer>
+ <integer>1614</integer>
+ <integer>1615</integer>
+ <integer>1622</integer>
+ <integer>1623</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;alsoReturnsRetained&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;alsoReturnsRetained&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetained&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetained&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFDateRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7ee55b74b5ee01c6ffa2a3d83c8cf88b</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>alsoReturnsRetained</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1627</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1604</integer>
+ <integer>1605</integer>
+ <integer>1606</integer>
+ <integer>1626</integer>
+ <integer>1627</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;alsoReturnsRetainedAsCF&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;alsoReturnsRetainedAsCF&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1604</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1606</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetainedAsCF&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFDateRef&apos; is returned from a method whose name (&apos;alsoReturnsRetainedAsCF&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFDateRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>177b2cf7eb3d8334393ee0861f5a38ac</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>alsoReturnsRetainedAsCF</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1631</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1604</integer>
+ <integer>1605</integer>
+ <integer>1606</integer>
+ <integer>1630</integer>
+ <integer>1631</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1651</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1651</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>82</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1652</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>85e9d8130a1f1ec37f0ba26746abd749</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_panic_negative</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1653</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1650</integer>
+ <integer>1651</integer>
+ <integer>1652</integer>
+ <integer>1653</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1662</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1662</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>82</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type &apos;CFNumberRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1663</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1664</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4a0b16976e0517b38b2ccc16e2928c2e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_panic_neg_2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1666</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1661</integer>
+ <integer>1662</integer>
+ <integer>1663</integer>
+ <integer>1664</integer>
+ <integer>1666</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1686</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>af73d9c62952a300a7c393ebd5073f75</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_blocks_1_pos</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1687</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1685</integer>
+ <integer>1686</integer>
+ <integer>1687</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>53</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSNumber with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1707</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_blocks_1_indirect_retain_via_call&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_blocks_1_indirect_retain_via_call&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1708</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +2</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>771b2a332053388ffbdd9ba74ea84c5e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_blocks_1_indirect_retain_via_call</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1709</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1706</integer>
+ <integer>1707</integer>
+ <integer>1708</integer>
+ <integer>1709</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1759</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1759</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;error_to_dump&apos; is not equal to null</string>
+ <key>message</key>
+ <string>Assuming &apos;error_to_dump&apos; is not equal to null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Entering loop body</string>
+ <key>message</key>
+ <string>Entering loop body</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1762</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1763</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>49</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFErrorCopyUserInfo&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFErrorCopyUserInfo&apos; returns a Core Foundation object of type &apos;CFDictionaryRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1765</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;info&apos; is not equal to null</string>
+ <key>message</key>
+ <string>Assuming &apos;info&apos; is not equal to null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1767</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;info&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;info&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;info&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>39f8c30f7436f678d5259c0fdd3a0dad</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar_8724287</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1770</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1757</integer>
+ <integer>1758</integer>
+ <integer>1759</integer>
+ <integer>1761</integer>
+ <integer>1762</integer>
+ <integer>1763</integer>
+ <integer>1765</integer>
+ <integer>1767</integer>
+ <integer>1770</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_createno&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_createno&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>107e3efdeb8cdff4bef4c64183c4f6fa</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camelcase_createno</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1815</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1814</integer>
+ <integer>1815</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_copying&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camelcase_copying&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>20c973a013858abb0a926276c956f858</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camelcase_copying</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1823</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1822</integer>
+ <integer>1823</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_creat&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_creat&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>80ee99e51561a37297429740e3a4da0c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camel_creat</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1844</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1843</integer>
+ <integer>1844</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>60</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_copymachine&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;CFMutableArrayRef&apos; is returned from a function whose name (&apos;camel_copymachine&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;CFMutableArrayRef&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak of returned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a4e28a04f6a8d87c8aaf4d71c37cac0f</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>camel_copymachine</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1856</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1855</integer>
+ <integer>1856</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1876</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1876</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type &apos;CFDateRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1877</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;vals&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;vals&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;vals&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6b727a438d8411c058fd32867b9402bc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar6582778</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1878</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1875</integer>
+ <integer>1876</integer>
+ <integer>1877</integer>
+ <integer>1878</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1902</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1902</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>64</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1904</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1905</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b39dcf9df7cec8dd73cbbe25b2a7d6c5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar10232019_positive</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1907</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>1901</integer>
+ <integer>1902</integer>
+ <integer>1904</integer>
+ <integer>1905</integer>
+ <integer>1907</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2035</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a501f743b22f1feb5dc317fcad4f7556</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>56</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2044</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a2&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a2&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a141a6ad33e8ff2ae3b13da0ad36ebc5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>12</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2052</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a3&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a3&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a3&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2b072d75e8da8e3fe8f7968a85efb37c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>20</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ <integer>2051</integer>
+ <integer>2052</integer>
+ <integer>2053</integer>
+ <integer>2054</integer>
+ <integer>2055</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>57</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSArray with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2060</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0bfdfb7e392626e0fccc6ab9f58f1ca8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>28</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ <integer>2051</integer>
+ <integer>2052</integer>
+ <integer>2053</integer>
+ <integer>2054</integer>
+ <integer>2055</integer>
+ <integer>2059</integer>
+ <integer>2060</integer>
+ <integer>2061</integer>
+ <integer>2063</integer>
+ <integer>2064</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2034</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2038</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2042</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2047</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2051</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2055</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2059</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2064</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2068</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSDictionary literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSDictionary literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2069</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ff7c34e661a42d06a7fb3e9669e70339</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_arrays</string>
+ <key>issue_hash_function_offset</key><string>37</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2073</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2032</integer>
+ <integer>2034</integer>
+ <integer>2035</integer>
+ <integer>2036</integer>
+ <integer>2037</integer>
+ <integer>2038</integer>
+ <integer>2042</integer>
+ <integer>2043</integer>
+ <integer>2044</integer>
+ <integer>2045</integer>
+ <integer>2046</integer>
+ <integer>2047</integer>
+ <integer>2051</integer>
+ <integer>2052</integer>
+ <integer>2053</integer>
+ <integer>2054</integer>
+ <integer>2055</integer>
+ <integer>2059</integer>
+ <integer>2060</integer>
+ <integer>2061</integer>
+ <integer>2063</integer>
+ <integer>2064</integer>
+ <integer>2068</integer>
+ <integer>2069</integer>
+ <integer>2070</integer>
+ <integer>2072</integer>
+ <integer>2073</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2078</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2079</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>73e84c042932d2e17e00f00dc3d36d5a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_integer_literals</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2080</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2077</integer>
+ <integer>2078</integer>
+ <integer>2079</integer>
+ <integer>2080</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber boxed expression produces an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>465e592d4f7a187717d00b8154a614b5</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_boxed_expressions</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2082</integer>
+ <integer>2083</integer>
+ <integer>2084</integer>
+ <integer>2086</integer>
+ <integer>2087</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2083</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSString boxed expression produces an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSString boxed expression produces an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2086</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2087</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c701bd0c60f51d96c047aa78c9e0eb99</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_objc_boxed_expressions</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2088</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2082</integer>
+ <integer>2083</integer>
+ <integer>2084</integer>
+ <integer>2086</integer>
+ <integer>2087</integer>
+ <integer>2088</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2094</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2094</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;y&apos; is &lt;= 2</string>
+ <key>message</key>
+ <string>Assuming &apos;y&apos; is &lt;= 2</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2095</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSString with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2098</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2099</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2100</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a4cedbb647e9632da7a5072cb839e54a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>rdar11400885</string>
+ <key>issue_hash_function_offset</key><string>9</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2101</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2091</integer>
+ <integer>2092</integer>
+ <integer>2094</integer>
+ <integer>2095</integer>
+ <integer>2098</integer>
+ <integer>2099</integer>
+ <integer>2100</integer>
+ <integer>2101</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2119</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2127</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>fd9427d86a2357fd92478c9c7abbc1f4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testConsumeAndStopTracking</string>
+ <key>issue_hash_function_offset</key><string>10</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2128</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2118</integer>
+ <integer>2119</integer>
+ <integer>2120</integer>
+ <integer>2122</integer>
+ <integer>2123</integer>
+ <integer>2127</integer>
+ <integer>2128</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2132</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2132</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSArray literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2140</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0e65e51476e5671dcd37f632806e5147</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCFConsumeAndStopTracking</string>
+ <key>issue_hash_function_offset</key><string>10</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2141</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2131</integer>
+ <integer>2132</integer>
+ <integer>2133</integer>
+ <integer>2135</integer>
+ <integer>2136</integer>
+ <integer>2140</integer>
+ <integer>2141</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CreateMyCFType&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CreateMyCFType&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2153</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a0ba9c47505e923763ea5323ad2f71b7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_custom_cf</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2154</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2152</integer>
+ <integer>2153</integer>
+ <integer>2154</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;makeCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;makeCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2188</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;obj&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7a6cf8cb3c5e0ca3125d7e27695a810a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCustomReturnsRetained</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2189</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2187</integer>
+ <integer>2188</integer>
+ <integer>2189</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;getCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;getCustom&apos; returns a Core Foundation object of type &apos;MyCFType&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>810fce32373fe40ba8e2d0894d46f667</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCustomReturnsNotRetained</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2192</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2191</integer>
+ <integer>2192</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of MyObj12706177 with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of MyObj12706177 with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;initX&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;initX&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2204</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test12706177&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test12706177&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2204</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2204</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;Cond&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;Cond&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2205</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2206</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2206</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;initX&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;initX&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: allocated object of type &apos;MyObj12706177 *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: allocated object of type &apos;MyObj12706177 *&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object of type &apos;MyObj12706177 *&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>68ee7961ffb62c575cc2298cb4836090</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test12706177</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2204</integer>
+ <integer>2205</integer>
+ <integer>2206</integer>
+ <integer>2210</integer>
+ <integer>2211</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1dc376fbbe90d14b6766585a0e2b7bee</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>getIncorrectlyAutoreleasedCFType</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2225</integer>
+ <integer>2227</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>40</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>42</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>43</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>message</key>
+ <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Method should return an owned object</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6ae8ea9fe4bf203e6b7bfaf649a6ca6a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>createIncorrectlyAutoreleasedCFType</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2230</integer>
+ <integer>2232</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2247</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object released</string>
+ <key>message</key>
+ <string>Object released</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2248</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference-counted object is used after it is released</string>
+ <key>message</key>
+ <string>Reference-counted object is used after it is released</string>
+ </dict>
+ </array>
+ <key>description</key><string>Reference-counted object is used after it is released</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Use-after-release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d4e28f96fc8610b5b4b849f4760956eb</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>useAfterRelease</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2251</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2244</integer>
+ <integer>2247</integer>
+ <integer>2248</integer>
+ <integer>2251</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type &apos;CFTypeRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2256</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>39</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2257</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2258</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;obj&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7986c4b7fb29301c109343dfe4155202</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testAutoreleaseReturnsInput</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2259</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2254</integer>
+ <integer>2256</integer>
+ <integer>2257</integer>
+ <integer>2258</integer>
+ <integer>2259</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>70</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ <key>message</key>
+ <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object of type &apos;CFMutableArrayRef&apos; with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2276</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>62</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>48</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>61</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2277</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ <key>message</key>
+ <string>Reference count incremented. The object now has a +2 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2278</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into &apos;arr&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into &apos;arr&apos; is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into &apos;arr&apos;</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2e0dbfdf379acf2f09e46db47d753e8a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>autoreleaseReturningTypedObject</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2279</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2275</integer>
+ <integer>2276</integer>
+ <integer>2277</integer>
+ <integer>2278</integer>
+ <integer>2279</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2290</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2290</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ <key>message</key>
+ <string>NSNumber literal is an object with a +0 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2293</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2294</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased but has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>41a2d6f91fdfa9b5f396102a60571e21</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>autoreleaseObjC</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2295</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2289</integer>
+ <integer>2290</integer>
+ <integer>2291</integer>
+ <integer>2293</integer>
+ <integer>2294</integer>
+ <integer>2295</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2345</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2345</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;getViaParam&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ <key>message</key>
+ <string>Call to function &apos;getViaParam&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2346</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>95dd5581ae4195b71e9a11f34290af5d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCFReturnsNotRetained</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2343</integer>
+ <integer>2345</integer>
+ <integer>2346</integer>
+ <integer>2347</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2352</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2352</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to function &apos;getViaParam2&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ <key>message</key>
+ <string>Call to function &apos;getViaParam2&apos; writes a Core Foundation object of type &apos;CFTypeRef&apos; with a +0 retain count into an out parameter &apos;outObj&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2353</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>message</key>
+ <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Bad release</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>014103674df4a8a65a96bcdf936637a2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCFReturnsNotRetainedAnnotated</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2354</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>2350</integer>
+ <integer>2352</integer>
+ <integer>2353</integer>
+ <integer>2354</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/Volumes/Transcend/code/monorepo/llvm-project/clang/test/Analysis/retain-release.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/unix-fns.c.plist b/test/Analysis/Inputs/expected-plists/unix-fns.c.plist
new file mode 100644
index 000000000000..b21d5bde1aeb
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/unix-fns.c.plist
@@ -0,0 +1,3021 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;fd&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;fd&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>84</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
+ <key>message</key>
+ <string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Improper use of &apos;open&apos;</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5ef25c5c47db3dbfb329901d426452e7</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_open</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>81</integer>
+ <integer>82</integer>
+ <integer>83</integer>
+ <integer>84</integer>
+ <integer>87</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;fd&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;fd&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>95</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>44</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>50</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
+ <key>message</key>
+ <string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Improper use of &apos;open&apos;</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>433b17840bb989e7a13dc6337c1ed220</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_open_at</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>98</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>92</integer>
+ <integer>93</integer>
+ <integer>94</integer>
+ <integer>95</integer>
+ <integer>98</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>104</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>64</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>66</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>72</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ <key>message</key>
+ <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
+ <key>check_name</key><string>osx.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>173fbcac3fc64dbaec32768d4cfda250</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_dispatch_once</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>52</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>103</integer>
+ <integer>104</integer>
+ <integer>105</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>115</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ <key>message</key>
+ <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Improper use of &apos;pthread_once&apos;</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1e2f657a65cf8ee3c3ac2227de05ade4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_pthread_once</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>114</integer>
+ <integer>115</integer>
+ <integer>116</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0e841458f0cb7cf161d35f9db5862dcf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>pr2899</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>125</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>124</integer>
+ <integer>125</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a267ff573c7e8b959a3f886677893eb0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_calloc</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>136</integer>
+ <integer>137</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>14eb72957baab3c63bac610a10e6f48b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_calloc2</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>142</integer>
+ <integer>143</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7f6f67ebe3d481aed7750005bea7e371</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_realloc</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>154</integer>
+ <integer>155</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>4941698efbd81601653dff10ef9c645b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_reallocf</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>160</integer>
+ <integer>161</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b7ca3488e81d9d9d4b8dc545258ce97c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_alloca</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>179</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>178</integer>
+ <integer>179</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1ec52551362b070237f47f6bb6c3847d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_builtin_alloca</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>191</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>190</integer>
+ <integer>191</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
+ <key>message</key>
+ <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
+ <key>category</key><string>Unix API</string>
+ <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+ <key>check_name</key><string>unix.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>675741e04c8d0071d280324e23f41d35</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_valloc</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>202</integer>
+ <integer>203</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ <key>message</key>
+ <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ </dict>
+ </array>
+ <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
+ <key>check_name</key><string>osx.API</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8ded1f2025c1e4a4bcd5302dc97006d9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_dispatch_once_in_macro</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>217</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>215</integer>
+ <integer>216</integer>
+ <integer>217</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>222</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>222</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>222</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>222</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>222</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; captured by block as a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; captured by block as a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;dispatch_sync&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;dispatch_sync&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>227</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;dispatch_sync&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;dispatch_sync&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>223</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;q&apos; is non-null</string>
+ <key>message</key>
+ <string>Assuming &apos;q&apos; is non-null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>224</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5d3f4c433004c7a6d4a06aa30cc3ea85</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>225</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>40</integer>
+ <integer>221</integer>
+ <integer>222</integer>
+ <integer>223</integer>
+ <integer>224</integer>
+ <integer>225</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>232</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>233</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>233</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>233</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>233</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>233</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>233</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>233</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; captured by block as a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; captured by block as a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>236</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;_dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;_dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_inline_dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_inline_dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>265c4fd608dafee211bfa93d21c28866</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>235</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>44</integer>
+ <integer>45</integer>
+ <integer>46</integer>
+ <integer>47</integer>
+ <integer>48</integer>
+ <integer>52</integer>
+ <integer>53</integer>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ <integer>61</integer>
+ <integer>231</integer>
+ <integer>232</integer>
+ <integer>233</integer>
+ <integer>234</integer>
+ <integer>235</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>241</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>245</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;_dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;_dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test_inline_dispatch_once_reachable&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test_inline_dispatch_once_reachable&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>52</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>244</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>244</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>244</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>244</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>244</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>61</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>245</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;_dispatch_once&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;_dispatch_once&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1e83bd4361a2351df0b4e77eb3a9109b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_inline_dispatch_once_reachable</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>247</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>44</integer>
+ <integer>45</integer>
+ <integer>46</integer>
+ <integer>47</integer>
+ <integer>48</integer>
+ <integer>52</integer>
+ <integer>53</integer>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ <integer>61</integer>
+ <integer>65</integer>
+ <integer>240</integer>
+ <integer>241</integer>
+ <integer>242</integer>
+ <integer>243</integer>
+ <integer>244</integer>
+ <integer>247</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/unix-fns.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/expected-plists/yaccignore.c.plist b/test/Analysis/Inputs/expected-plists/yaccignore.c.plist
new file mode 100644
index 000000000000..c3ff6dfb7f55
--- /dev/null
+++ b/test/Analysis/Inputs/expected-plists/yaccignore.c.plist
@@ -0,0 +1,4 @@
+<key>diagnostics</key>
+
+</dict>
+</plist>
diff --git a/test/Analysis/Inputs/system-header-simulator-cxx.h b/test/Analysis/Inputs/system-header-simulator-cxx.h
index 5d7e553ed5f4..6f92a42173da 100644
--- a/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ b/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -12,6 +12,13 @@ typedef __typeof__((char*)0-(char*)0) ptrdiff_t;
void *memmove(void *s1, const void *s2, size_t n);
namespace std {
+ typedef size_t size_type;
+#if __cplusplus >= 201103L
+ using nullptr_t = decltype(nullptr);
+#endif
+}
+
+namespace std {
struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag : public input_iterator_tag { };
@@ -230,6 +237,13 @@ namespace std {
return static_cast<RvalRef>(a);
}
+ template <class T>
+ void swap(T &a, T &b) {
+ T c(std::move(a));
+ a = std::move(b);
+ b = std::move(c);
+ }
+
template<typename T>
class vector {
typedef T value_type;
@@ -252,12 +266,38 @@ namespace std {
return size_t(_finish - _start);
}
+ vector& operator=(const vector &other);
+ vector& operator=(vector &&other);
+ vector& operator=(std::initializer_list<T> ilist);
+
+ void assign(size_type count, const T &value);
+ template <typename InputIterator >
+ void assign(InputIterator first, InputIterator last);
+ void assign(std::initializer_list<T> ilist);
+
void clear();
void push_back(const T &value);
void push_back(T &&value);
+ template<class... Args>
+ void emplace_back(Args&&... args);
void pop_back();
+ iterator insert(const_iterator position, const value_type &val);
+ iterator insert(const_iterator position, size_type n,
+ const value_type &val);
+ template <typename InputIterator>
+ iterator insert(const_iterator position, InputIterator first,
+ InputIterator last);
+ iterator insert(const_iterator position, value_type &&val);
+ iterator insert(const_iterator position, initializer_list<value_type> il);
+
+ template <class... Args>
+ iterator emplace(const_iterator position, Args&&... args);
+
+ iterator erase(const_iterator position);
+ iterator erase(const_iterator first, const_iterator last);
+
T &operator[](size_t n) {
return _start[n];
}
@@ -301,8 +341,40 @@ namespace std {
list& operator=(list &&other);
list& operator=(std::initializer_list<T> ilist);
+ void assign(size_type count, const T &value);
+ template <typename InputIterator >
+ void assign(InputIterator first, InputIterator last);
+ void assign(std::initializer_list<T> ilist);
+
void clear();
+ void push_back(const T &value);
+ void push_back(T &&value);
+ template<class... Args>
+ void emplace_back(Args&&... args);
+ void pop_back();
+
+ void push_front(const T &value);
+ void push_front(T &&value);
+ template<class... Args>
+ void emplace_front(Args&&... args);
+ void pop_front();
+
+ iterator insert(const_iterator position, const value_type &val);
+ iterator insert(const_iterator position, size_type n,
+ const value_type &val);
+ template <typename InputIterator>
+ iterator insert(const_iterator position, InputIterator first,
+ InputIterator last);
+ iterator insert(const_iterator position, value_type &&val);
+ iterator insert(const_iterator position, initializer_list<value_type> il);
+
+ template <class... Args>
+ iterator emplace(const_iterator position, Args&&... args);
+
+ iterator erase(const_iterator position);
+ iterator erase(const_iterator first, const_iterator last);
+
iterator begin() { return iterator(_start); }
const_iterator begin() const { return const_iterator(_start); }
const_iterator cbegin() const { return const_iterator(_start); }
@@ -338,24 +410,52 @@ namespace std {
return size_t(_finish - _start);
}
+ deque& operator=(const deque &other);
+ deque& operator=(deque &&other);
+ deque& operator=(std::initializer_list<T> ilist);
+
+ void assign(size_type count, const T &value);
+ template <typename InputIterator >
+ void assign(InputIterator first, InputIterator last);
+ void assign(std::initializer_list<T> ilist);
+
void clear();
void push_back(const T &value);
void push_back(T &&value);
+ template<class... Args>
+ void emplace_back(Args&&... args);
void pop_back();
void push_front(const T &value);
void push_front(T &&value);
+ template<class... Args>
+ void emplace_front(Args&&... args);
void pop_front();
+ iterator insert(const_iterator position, const value_type &val);
+ iterator insert(const_iterator position, size_type n,
+ const value_type &val);
+ template <typename InputIterator>
+ iterator insert(const_iterator position, InputIterator first,
+ InputIterator last);
+ iterator insert(const_iterator position, value_type &&val);
+ iterator insert(const_iterator position, initializer_list<value_type> il);
+
+ template <class... Args>
+ iterator emplace(const_iterator position, Args&&... args);
+
+ iterator erase(const_iterator position);
+ iterator erase(const_iterator first, const_iterator last);
+
T &operator[](size_t n) {
return _start[n];
}
-
+
const T &operator[](size_t n) const {
return _start[n];
}
-
+
iterator begin() { return iterator(_start); }
const_iterator begin() const { return const_iterator(_start); }
const_iterator cbegin() const { return const_iterator(_start); }
@@ -367,7 +467,7 @@ namespace std {
T& back() { return *(end() - 1); }
const T& back() const { return *(end() - 1); }
};
-
+
template<typename T>
class forward_list {
struct __item {
@@ -387,12 +487,39 @@ namespace std {
forward_list(forward_list &&other);
~forward_list();
+ forward_list& operator=(const forward_list &other);
+ forward_list& operator=(forward_list &&other);
+ forward_list& operator=(std::initializer_list<T> ilist);
+
+ void assign(size_type count, const T &value);
+ template <typename InputIterator >
+ void assign(InputIterator first, InputIterator last);
+ void assign(std::initializer_list<T> ilist);
+
void clear();
void push_front(const T &value);
void push_front(T &&value);
+ template<class... Args>
+ void emplace_front(Args&&... args);
void pop_front();
+ iterator insert_after(const_iterator position, const value_type &val);
+ iterator insert_after(const_iterator position, value_type &&val);
+ iterator insert_after(const_iterator position, size_type n,
+ const value_type &val);
+ template <typename InputIterator>
+ iterator insert_after(const_iterator position, InputIterator first,
+ InputIterator last);
+ iterator insert_after(const_iterator position,
+ initializer_list<value_type> il);
+
+ template <class... Args>
+ iterator emplace_after(const_iterator position, Args&&... args);
+
+ iterator erase_after(const_iterator position);
+ iterator erase_after(const_iterator first, const_iterator last);
+
iterator begin() { return iterator(_start); }
const_iterator begin() const { return const_iterator(_start); }
const_iterator cbegin() const { return const_iterator(_start); }
@@ -404,6 +531,42 @@ namespace std {
const T& front() const { return *begin(); }
};
+ template <typename CharT>
+ class basic_string {
+ public:
+ basic_string();
+ basic_string(const CharT *s);
+
+ ~basic_string();
+ void clear();
+
+ basic_string &operator=(const basic_string &str);
+ basic_string &operator+=(const basic_string &str);
+
+ const CharT *c_str() const;
+ const CharT *data() const;
+ CharT *data();
+
+ basic_string &append(size_type count, CharT ch);
+ basic_string &assign(size_type count, CharT ch);
+ basic_string &erase(size_type index, size_type count);
+ basic_string &insert(size_type index, size_type count, CharT ch);
+ basic_string &replace(size_type pos, size_type count, const basic_string &str);
+ void pop_back();
+ void push_back(CharT ch);
+ void reserve(size_type new_cap);
+ void resize(size_type count);
+ void shrink_to_fit();
+ void swap(basic_string &other);
+ };
+
+ typedef basic_string<char> string;
+ typedef basic_string<wchar_t> wstring;
+#if __cplusplus >= 201103L
+ typedef basic_string<char16_t> u16string;
+ typedef basic_string<char32_t> u32string;
+#endif
+
class exception {
public:
exception() throw();
@@ -602,12 +765,34 @@ namespace std {
template <class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T &val);
+ template <class ForwardIterator1, class ForwardIterator2>
+ ForwardIterator1 find_first_of(ForwardIterator1 first1,
+ ForwardIterator1 last1,
+ ForwardIterator2 first2,
+ ForwardIterator2 last2);
+
template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
}
+#if __cplusplus >= 201103L
+namespace std {
+ template <typename T> // TODO: Implement the stub for deleter.
+ class unique_ptr {
+ public:
+ unique_ptr(const unique_ptr &) = delete;
+ unique_ptr(unique_ptr &&);
+
+ T *get() const;
+
+ typename std::add_lvalue_reference<T>::type operator*() const;
+ T *operator->() const;
+ };
+}
+#endif
+
#ifdef TEST_INLINABLE_ALLOCATORS
namespace std {
void *malloc(size_t);
diff --git a/test/Analysis/Inputs/system-header-simulator-for-nullability.h b/test/Analysis/Inputs/system-header-simulator-for-nullability.h
index 751057dd450e..1f6a2b1b29d1 100644
--- a/test/Analysis/Inputs/system-header-simulator-for-nullability.h
+++ b/test/Analysis/Inputs/system-header-simulator-for-nullability.h
@@ -9,6 +9,8 @@
NS_ASSUME_NONNULL_BEGIN
typedef struct _NSZone NSZone;
+typedef unsigned long NSUInteger;
+@class NSCoder, NSEnumerator;
@protocol NSObject
+ (instancetype)alloc;
@@ -24,6 +26,22 @@ typedef struct _NSZone NSZone;
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
@end
+@protocol NSCoding
+- (void)encodeWithCoder:(NSCoder *)aCoder;
+@end
+
+@protocol NSSecureCoding <NSCoding>
+@required
++ (BOOL)supportsSecureCoding;
+@end
+
+typedef struct {
+ unsigned long state;
+ id *itemsPtr;
+ unsigned long *mutationsPtr;
+ unsigned long extra[5];
+} NSFastEnumerationState;
+
__attribute__((objc_root_class))
@interface
NSObject<NSObject>
@@ -52,3 +70,36 @@ NSString* _Nonnull getString();
@end
NS_ASSUME_NONNULL_END
+
+@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
+
+- (NSUInteger)count;
+- (id)objectForKey:(id)aKey;
+- (NSEnumerator *)keyEnumerator;
+- (id)objectForKeyedSubscript:(id)aKey;
+
+@end
+
+@interface NSDictionary (NSDictionaryCreation)
+
++ (id)dictionary;
++ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
++ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
+
+@end
+
+@interface NSMutableDictionary : NSDictionary
+
+- (void)removeObjectForKey:(id)aKey;
+- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
+
+@end
+
+@interface NSMutableDictionary (NSExtendedMutableDictionary)
+
+- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
+- (void)removeAllObjects;
+- (void)setDictionary:(NSDictionary *)otherDictionary;
+- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key __attribute__((availability(macosx,introduced=10.8)));
+
+@end
diff --git a/test/Analysis/MismatchedDeallocator-path-notes.cpp b/test/Analysis/MismatchedDeallocator-path-notes.cpp
index 4e4ffc42423e..8cbd401c5a08 100644
--- a/test/Analysis/MismatchedDeallocator-path-notes.cpp
+++ b/test/Analysis/MismatchedDeallocator-path-notes.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=plist %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: tail -n +11 %t.plist | diff -u -w -I "<string>/" -I "<string>.:" -I "version" - %S/copypaste/Inputs/expected-plists/MismatchedDeallocator-path-notes.cpp.plist
void changePointee(int *p);
int *allocIntArray(unsigned c) {
@@ -13,293 +13,3 @@ void test() {
delete p; // expected-warning {{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
// expected-note@-1 {{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
}
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;allocIntArray&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;allocIntArray&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Bad deallocator</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.MismatchedDeallocator</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2009ca1da75217064b6052ba7465dff9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/MissingDealloc.m b/test/Analysis/MissingDealloc.m
index bedd1e7fc25a..bdba93c8815a 100644
--- a/test/Analysis/MissingDealloc.m
+++ b/test/Analysis/MissingDealloc.m
@@ -183,4 +183,17 @@ __attribute__((objc_root_class))
@implementation NonNSObjectMissingDealloc
@end
-// CHECK: 4 warnings generated.
+
+//===------------------------------------------------------------------------===
+// Don't crash on calls to dealloc as a class method.
+
+@interface DeallocingClass : NSObject {}
+@end
+@implementation DeallocingClass
+- (void)dealloc {
+ [DeallocingClass dealloc]; // FIXME: Should we warn on this specifically?
+}
+#if NON_ARC
+// expected-warning@-2{{method possibly missing a [super dealloc] call}}
+#endif
+@end
diff --git a/test/Analysis/MisusedMovedObject.cpp b/test/Analysis/MisusedMovedObject.cpp
deleted file mode 100644
index 07d52c8236da..000000000000
--- a/test/Analysis/MisusedMovedObject.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -verify -analyzer-output=text -analyzer-config exploration_strategy=unexplored_first_queue %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -analyzer-config exploration_strategy=dfs -verify -analyzer-output=text -DDFS=1 %s
-
-namespace std {
-
-template <typename>
-struct remove_reference;
-
-template <typename _Tp>
-struct remove_reference { typedef _Tp type; };
-
-template <typename _Tp>
-struct remove_reference<_Tp &> { typedef _Tp type; };
-
-template <typename _Tp>
-struct remove_reference<_Tp &&> { typedef _Tp type; };
-
-template <typename _Tp>
-typename remove_reference<_Tp>::type &&move(_Tp &&__t) {
- return static_cast<typename remove_reference<_Tp>::type &&>(__t);
-}
-
-template <typename _Tp>
-_Tp &&forward(typename remove_reference<_Tp>::type &__t) noexcept {
- return static_cast<_Tp &&>(__t);
-}
-
-template <class T>
-void swap(T &a, T &b) {
- T c(std::move(a));
- a = std::move(b);
- b = std::move(c);
-}
-
-} // namespace std
-
-class B {
-public:
- B() = default;
- B(const B &) = default;
- B(B &&) = default;
- B& operator=(const B &q) = default;
- void operator=(B &&b) {
- return;
- }
- void foo() { return; }
-};
-
-class A {
- int i;
- double d;
-
-public:
- B b;
- A(int ii = 42, double dd = 1.0) : d(dd), i(ii), b(B()) {}
- void moveconstruct(A &&other) {
- std::swap(b, other.b);
- std::swap(d, other.d);
- std::swap(i, other.i);
- return;
- }
- static A get() {
- A v(12, 13);
- return v;
- }
- A(A *a) {
- moveconstruct(std::move(*a));
- }
- A(const A &other) : i(other.i), d(other.d), b(other.b) {}
- A(A &&other) : i(other.i), d(other.d), b(std::move(other.b)) { // expected-note {{'b' became 'moved-from' here}}
- }
- A(A &&other, char *k) {
- moveconstruct(std::move(other));
- }
- void operator=(const A &other) {
- i = other.i;
- d = other.d;
- b = other.b;
- return;
- }
- void operator=(A &&other) {
- moveconstruct(std::move(other));
- return;
- }
- int getI() { return i; }
- int foo() const;
- void bar() const;
- void reset();
- void destroy();
- void clear();
- bool empty() const;
- bool isEmpty() const;
- operator bool() const;
-};
-
-int bignum();
-
-void moveInsideFunctionCall(A a) {
- A b = std::move(a);
-}
-void leftRefCall(A &a) {
- a.foo();
-}
-void rightRefCall(A &&a) {
- a.foo();
-}
-void constCopyOrMoveCall(const A a) {
- a.foo();
-}
-
-void copyOrMoveCall(A a) {
- a.foo();
-}
-
-void simpleMoveCtorTest() {
- {
- A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- }
- {
- A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- b = a; // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
- }
- {
- A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- b = std::move(a); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
- }
-}
-
-void simpleMoveAssignementTest() {
- {
- A a;
- A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- }
- {
- A a;
- A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- A c(a); // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
- }
- {
- A a;
- A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- A c(std::move(a)); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
- }
-}
-
-void moveInInitListTest() {
- struct S {
- A a;
- };
- A a;
- S s{std::move(a)}; // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-}
-
-// Don't report a bug if the variable was assigned to in the meantime.
-void reinitializationTest(int i) {
- {
- A a;
- A b;
- b = std::move(a);
- a = A();
- a.foo();
- }
- {
- A a;
- if (i == 1) { // expected-note {{Assuming 'i' is not equal to 1}} expected-note {{Taking false branch}}
- // expected-note@-1 {{Assuming 'i' is not equal to 1}} expected-note@-1 {{Taking false branch}}
- A b;
- b = std::move(a);
- a = A();
- }
- if (i == 2) { // expected-note {{Assuming 'i' is not equal to 2}} expected-note {{Taking false branch}}
- //expected-note@-1 {{Assuming 'i' is not equal to 2}} expected-note@-1 {{Taking false branch}}
- a.foo(); // no-warning
- }
- }
- {
- A a;
- if (i == 1) { // expected-note {{Taking false branch}} expected-note {{Taking false branch}}
- std::move(a);
- }
- if (i == 2) { // expected-note {{Taking false branch}} expected-note {{Taking false branch}}
- a = A();
- a.foo();
- }
- }
- // The built-in assignment operator should also be recognized as a
- // reinitialization. (std::move() may be called on built-in types in template
- // code.)
- {
- int a1 = 1, a2 = 2;
- std::swap(a1, a2);
- }
- // A std::move() after the assignment makes the variable invalid again.
- {
- A a;
- A b;
- b = std::move(a);
- a = A();
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- }
- // If a path exist where we not reinitialize the variable we report a bug.
- {
- A a;
- A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- if (i < 10) { // expected-note {{Assuming 'i' is >= 10}} expected-note {{Taking false branch}}
- a = A();
- }
- if (i > 5) { // expected-note {{Taking true branch}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- }
- }
-}
-
-// Using decltype on an expression is not a use.
-void decltypeIsNotUseTest() {
- A a;
- // A b(std::move(a));
- decltype(a) other_a; // no-warning
-}
-
-void loopTest() {
- {
- A a;
- for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
- rightRefCall(std::move(a)); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true. Entering loop body}}
- //expected-note@-1 {{Loop condition is true. Entering loop body}}
- //expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
- rightRefCall(std::move(a)); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
- leftRefCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true. Entering loop body}}
- //expected-note@-1 {{Loop condition is true. Entering loop body}}
- //expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
- leftRefCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
- constCopyOrMoveCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true. Entering loop body}}
- //expected-note@-1 {{Loop condition is true. Entering loop body}}
- //expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
- constCopyOrMoveCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
- moveInsideFunctionCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true. Entering loop body}}
- //expected-note@-1 {{Loop condition is true. Entering loop body}}
- //expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
- moveInsideFunctionCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
- copyOrMoveCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.}}
- //expected-note@-1 {{Loop condition is true. Entering loop body}}
- //expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
- copyOrMoveCall(a); // no-warning
- }
- }
- {
- A a;
- for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is true. Entering loop body}} expected-note {{Loop condition is true. Entering loop body}}
- constCopyOrMoveCall(std::move(a)); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
- // expected-note@-1 {{'a' became 'moved-from' here}}
- }
- }
-
- // Don't warn if we return after the move.
- {
- A a;
- for (int i = 0; i < 3; ++i) {
- a.bar();
- if (a.foo() > 0) {
- A b;
- b = std::move(a); // no-warning
- return;
- }
- }
- }
-}
-
-//report a usage of a moved-from object only at the first use
-void uniqueTest(bool cond) {
- A a(42, 42.0);
- A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-
- if (cond) { // expected-note {{Assuming 'cond' is not equal to 0}} expected-note {{Taking true branch}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- }
- if (cond) {
- a.bar(); // no-warning
- }
-
- a.bar(); // no-warning
-}
-
-void uniqueTest2() {
- A a;
- A a1 = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-
- A a2 = std::move(a); // no-warning
- a.foo(); // no-warning
-}
-
-// There are exceptions where we assume in general that the method works fine
-//even on moved-from objects.
-void moveSafeFunctionsTest() {
- A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.empty(); // no-warning
- a.isEmpty(); // no-warning
- (void)a; // no-warning
- (bool)a; // expected-warning {{expression result unused}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-}
-
-void moveStateResetFunctionsTest() {
- {
- A a;
- A b = std::move(a);
- a.reset(); // no-warning
- a.foo(); // no-warning
- // Test if resets the state of subregions as well.
- a.b.foo(); // no-warning
- }
- {
- A a;
- A b = std::move(a);
- a.destroy(); // no-warning
- a.foo(); // no-warning
- }
- {
- A a;
- A b = std::move(a);
- a.clear(); // no-warning
- a.foo(); // no-warning
- a.b.foo(); // no-warning
- }
-}
-
-// Moves or uses that occur as part of template arguments.
-template <int>
-class ClassTemplate {
-public:
- void foo(A a);
-};
-
-template <int>
-void functionTemplate(A a);
-
-void templateArgIsNotUseTest() {
- {
- // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
- // Google Test.
- A a;
- ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a)); // no-warning
- }
- {
- A a;
- functionTemplate<sizeof(A(std::move(a)))>(std::move(a)); // no-warning
- }
-}
-
-// Moves of global variables are not reported.
-A global_a;
-void globalVariablesTest() {
- std::move(global_a);
- global_a.foo(); // no-warning
-}
-
-// Moves of member variables.
-class memberVariablesTest {
- A a;
- static A static_a;
-
- void f() {
- A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object 'a'}}
-
- b = std::move(static_a); // expected-note {{'static_a' became 'moved-from' here}}
- static_a.foo(); // expected-warning {{Method call on a 'moved-from' object 'static_a'}} expected-note {{Method call on a 'moved-from' object 'static_a'}}
- }
-};
-
-void PtrAndArrayTest() {
- A *Ptr = new A(1, 1.5);
- A Arr[10];
- Arr[2] = std::move(*Ptr); // expected-note {{Became 'moved-from' here}}
- (*Ptr).foo(); // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object}}
-
- Ptr = &Arr[1];
- Arr[3] = std::move(Arr[1]); // expected-note {{Became 'moved-from' here}}
- Ptr->foo(); // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object}}
-
- Arr[3] = std::move(Arr[2]); // expected-note {{Became 'moved-from' here}}
- Arr[2].foo(); // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object}}
-
- Arr[2] = std::move(Arr[3]); // reinitialization
- Arr[2].foo(); // no-warning
-}
-
-void exclusiveConditionsTest(bool cond) {
- A a;
- if (cond) {
- A b;
- b = std::move(a);
- }
- if (!cond) {
- a.bar(); // no-warning
- }
-}
-
-void differentBranchesTest(int i) {
- // Don't warn if the use is in a different branch from the move.
- {
- A a;
- if (i > 0) { // expected-note {{Assuming 'i' is > 0}} expected-note {{Taking true branch}}
- A b;
- b = std::move(a);
- } else {
- a.foo(); // no-warning
- }
- }
- // Same thing, but with a ternary operator.
- {
- A a, b;
- i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning // expected-note {{'?' condition is true}}
- }
- // A variation on the theme above.
- {
- A a;
-#ifdef DFS
- a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is false}} expected-note {{'?' condition is false}}
-#else
- a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is true}} expected-note {{'?' condition is true}}
-#endif
- }
- // Same thing, but with a switch statement.
- {
- A a, b;
- switch (i) { // expected-note {{Control jumps to 'case 1:'}}
- case 1:
- b = std::move(a); // no-warning
- break; // expected-note {{Execution jumps to the end of the function}}
- case 2:
- a.foo(); // no-warning
- break;
- }
- }
- // However, if there's a fallthrough, we do warn.
- {
- A a, b;
- switch (i) { // expected-note {{Control jumps to 'case 1:'}}
- case 1:
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- case 2:
- a.foo(); // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object 'a'}}
- break;
- }
- }
-}
-
-void tempTest() {
- A a = A::get();
- A::get().foo(); // no-warning
- for (int i = 0; i < bignum(); i++) {
- A::get().foo(); // no-warning
- }
-}
-
-void interFunTest1(A &a) {
- a.bar(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-}
-
-void interFunTest2() {
- A a;
- A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- interFunTest1(a); // expected-note {{Calling 'interFunTest1'}}
-}
-
-void foobar(A a, int i);
-void foobar(int i, A a);
-
-void paramEvaluateOrderTest() {
- A a;
- foobar(std::move(a), a.getI()); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- // expected-note@-1 {{'a' became 'moved-from' here}}
-
- //FALSE NEGATIVE since parameters evaluate order is undefined
- foobar(a.getI(), std::move(a)); //no-warning
-}
-
-void not_known(A &a);
-void not_known(A *a);
-
-void regionAndPointerEscapeTest() {
- {
- A a;
- A b;
- b = std::move(a);
- not_known(a);
- a.foo(); //no-warning
- }
- {
- A a;
- A b;
- b = std::move(a);
- not_known(&a);
- a.foo(); // no-warning
- }
-}
-
-// A declaration statement containing multiple declarations sequences the
-// initializer expressions.
-void declarationSequenceTest() {
- {
- A a;
- A a1 = a, a2 = std::move(a); // no-warning
- }
- {
- A a;
- A a1 = std::move(a), a2 = a; // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
- // expected-note@-1 {{'a' became 'moved-from' here}}
- }
-}
-
-// The logical operators && and || sequence their operands.
-void logicalOperatorsSequenceTest() {
- {
- A a;
- if (a.foo() > 0 && A(std::move(a)).foo() > 0) { // expected-note {{Assuming the condition is false}} expected-note {{Assuming the condition is false}}
- // expected-note@-1 {{Left side of '&&' is false}} expected-note@-1 {{Left side of '&&' is false}}
- //expected-note@-2 {{Taking false branch}} expected-note@-2 {{Taking false branch}}
- A().bar();
- }
- }
- // A variation: Negate the result of the && (which pushes the && further down
- // into the AST).
- {
- A a;
- if (!(a.foo() > 0 && A(std::move(a)).foo() > 0)) { // expected-note {{Assuming the condition is false}} expected-note {{Assuming the condition is false}}
- // expected-note@-1 {{Left side of '&&' is false}} expected-note@-1 {{Left side of '&&' is false}}
- // expected-note@-2 {{Taking true branch}} expected-note@-2 {{Taking true branch}}
- A().bar();
- }
- }
- {
- A a;
- if (A(std::move(a)).foo() > 0 && a.foo() > 0) { // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- // expected-note@-1 {{'a' became 'moved-from' here}} expected-note@-1 {{Assuming the condition is true}} expected-note@-1 {{Assuming the condition is false}}
- // expected-note@-2 {{Left side of '&&' is false}} expected-note@-2 {{Left side of '&&' is true}}
- // expected-note@-3 {{Taking false branch}}
- A().bar();
- }
- }
- {
- A a;
- if (a.foo() > 0 || A(std::move(a)).foo() > 0) { // expected-note {{Assuming the condition is true}}
- //expected-note@-1 {{Left side of '||' is true}}
- //expected-note@-2 {{Taking true branch}}
- A().bar();
- }
- }
- {
- A a;
- if (A(std::move(a)).foo() > 0 || a.foo() > 0) { // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- // expected-note@-1 {{'a' became 'moved-from' here}} expected-note@-1 {{Assuming the condition is false}} expected-note@-1 {{Left side of '||' is false}}
- A().bar();
- }
- }
-}
-
-// A range-based for sequences the loop variable declaration before the body.
-void forRangeSequencesTest() {
- A v[2] = {A(), A()};
- for (A &a : v) {
- A b;
- b = std::move(a); // no-warning
- }
-}
-
-// If a variable is declared in an if statement, the declaration of the variable
-// (which is treated like a reinitialization by the check) is sequenced before
-// the evaluation of the condition (which constitutes a use).
-void ifStmtSequencesDeclAndConditionTest() {
- for (int i = 0; i < 3; ++i) {
- if (A a = A()) {
- A b;
- b = std::move(a); // no-warning
- }
- }
-}
-
-class C : public A {};
-void subRegionMoveTest() {
- {
- A a;
- B b = std::move(a.b); // expected-note {{'b' became 'moved-from' here}}
- a.b.foo(); // expected-warning {{Method call on a 'moved-from' object 'b'}} expected-note {{Method call on a 'moved-from' object 'b'}}
- }
- {
- A a;
- A a1 = std::move(a); // expected-note {{Calling move constructor for 'A'}} expected-note {{Returning from move constructor for 'A'}}
- a.b.foo(); // expected-warning {{Method call on a 'moved-from' object 'b'}} expected-note {{Method call on a 'moved-from' object 'b'}}
- }
- // Don't report a misuse if any SuperRegion is already reported.
- {
- A a;
- A a1 = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- a.b.foo(); // no-warning
- }
- {
- C c;
- C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}}
- c.foo(); // expected-warning {{Method call on a 'moved-from' object 'c'}} expected-note {{Method call on a 'moved-from' object 'c'}}
- c.b.foo(); // no-warning
- }
-}
-
-void resetSuperClass() {
- C c;
- C c1 = std::move(c);
- c.clear();
- C c2 = c; // no-warning
-}
-
-void reportSuperClass() {
- C c;
- C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}}
- c.foo(); // expected-warning {{Method call on a 'moved-from' object 'c'}} expected-note {{Method call on a 'moved-from' object 'c'}}
- C c2 = c; // no-warning
-}
diff --git a/test/Analysis/NewDelete-custom.cpp b/test/Analysis/NewDelete-custom.cpp
index f5a2952699ff..8c4d9a663a31 100644
--- a/test/Analysis/NewDelete-custom.cpp
+++ b/test/Analysis/NewDelete-custom.cpp
@@ -1,12 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,unix.Malloc -std=c++11 -analyzer-config c++-allocator-inlining=false -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -analyzer-config c++-allocator-inlining=false -DLEAKS=1 -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,unix.Malloc -std=c++11 -DALLOCATOR_INLINING=1 -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -DLEAKS=1 -DALLOCATOR_INLINING=1 -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -fblocks -verify %s -analyzer-config c++-allocator-inlining=false
#include "Inputs/system-header-simulator-cxx.h"
-#if !(LEAKS && !ALLOCATOR_INLINING)
// expected-no-diagnostics
-#endif
void *allocator(std::size_t size);
@@ -24,24 +20,18 @@ public:
void testNewMethod() {
void *p1 = C::operator new(0); // no warn
- C *p2 = new C; // no warn
+ C *p2 = new C; // no-warning
- C *c3 = ::new C;
+ C *c3 = ::new C; // no-warning
}
-#if LEAKS && !ALLOCATOR_INLINING
-// expected-warning@-2{{Potential leak of memory pointed to by 'c3'}}
-#endif
void testOpNewArray() {
void *p = operator new[](0); // call is inlined, no warn
}
void testNewExprArray() {
- int *p = new int[0];
+ int *p = new int[0]; // no-warning
}
-#if LEAKS && !ALLOCATOR_INLINING
-// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
-#endif
//----- Custom non-placement operators
@@ -50,12 +40,8 @@ void testOpNew() {
}
void testNewExpr() {
- int *p = new int;
+ int *p = new int; // no-warning
}
-#if LEAKS && !ALLOCATOR_INLINING
-// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
-#endif
-
//----- Custom NoThrow placement operators
void testOpNewNoThrow() {
@@ -63,11 +49,8 @@ void testOpNewNoThrow() {
}
void testNewExprNoThrow() {
- int *p = new(std::nothrow) int;
+ int *p = new(std::nothrow) int; // no-warning
}
-#if LEAKS && !ALLOCATOR_INLINING
-// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
-#endif
//----- Custom placement operators
void testOpNewPlacement() {
diff --git a/test/Analysis/NewDelete-path-notes.cpp b/test/Analysis/NewDelete-path-notes.cpp
index 48c402d25c60..2195b9d42a4b 100644
--- a/test/Analysis/NewDelete-path-notes.cpp
+++ b/test/Analysis/NewDelete-path-notes.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -analyzer-config c++-allocator-inlining=true -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=plist %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/NewDelete-path-notes.cpp.plist -
void test() {
int *p = new int;
@@ -28,433 +28,3 @@ void test(Odd *odd) {
// expected-note@-1 {{Attempt to free released memory}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Attempt to free released memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Attempt to free released memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Attempt to free released memory</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Double free</string>
-// CHECK-NEXT: <key>check_name</key><string>cplusplus.NewDelete</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bd8e324d09c70b9e2be6f824a4942e5a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;Odd::kill&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;Odd::kill&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning; memory was released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning; memory was released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Attempt to free released memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Attempt to free released memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Attempt to free released memory</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Double free</string>
-// CHECK-NEXT: <key>check_name</key><string>cplusplus.NewDelete</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8bf1a5b9fdae9d86780aa6c4cdce2605</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/NewDelete-sized-deallocation.cpp b/test/Analysis/NewDelete-sized-deallocation.cpp
new file mode 100644
index 000000000000..b0f2cfb765c3
--- /dev/null
+++ b/test/Analysis/NewDelete-sized-deallocation.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -fsized-deallocation
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -DINCLUDE_INCLUDES
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -DINCLUDE_INCLUDES -fsized-deallocation
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -DINCLUDE_INCLUDES -DTEST_INLINABLE_ALLOCATORS
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -DINCLUDE_INCLUDES -DTEST_INLINABLE_ALLOCATORS -fsized-deallocation
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++14
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++14 -fsized-deallocation
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++14 -DINCLUDE_INCLUDES
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++14 -DINCLUDE_INCLUDES -fsized-deallocation
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++14 -DINCLUDE_INCLUDES -DTEST_INLINABLE_ALLOCATORS
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++14 -DINCLUDE_INCLUDES -DTEST_INLINABLE_ALLOCATORS -fsized-deallocation
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++17
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++17 -fsized-deallocation
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++17 -DINCLUDE_INCLUDES
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++17 -DINCLUDE_INCLUDES -fsized-deallocation
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++17 -DINCLUDE_INCLUDES -DTEST_INLINABLE_ALLOCATORS
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus -verify -analyzer-output=text %s -std=c++17 -DINCLUDE_INCLUDES -DTEST_INLINABLE_ALLOCATORS -fsized-deallocation
+
+// Test all three: undeclared operator delete, operator delete forward-declared
+// in the system header, operator delete defined in system header.
+#ifdef INCLUDE_INCLUDES
+// TEST_INLINABLE_ALLOCATORS is used within this include.
+#include "Inputs/system-header-simulator-cxx.h"
+#endif
+
+void leak() {
+ int *x = new int; // expected-note{{Memory is allocated}}
+} // expected-warning{{Potential leak of memory pointed to by 'x'}}
+ // expected-note@-1{{Potential leak of memory pointed to by 'x'}}
+
+// This function was incorrectly diagnosed as leak under -fsized-deallocation
+// because the sized operator delete was mistaken for a custom delete.
+void no_leak() {
+ int *x = new int; // no-note
+ delete x;
+} // no-warning
diff --git a/test/Analysis/PR24184.cpp b/test/Analysis/PR24184.cpp
index bfc5ae6ea56b..172d3e7e3386 100644
--- a/test/Analysis/PR24184.cpp
+++ b/test/Analysis/PR24184.cpp
@@ -1,5 +1,5 @@
// UNSUPPORTED: z3
-// RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s
+// RUN: %clang_analyze_cc1 -w -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s
// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify %s
// These tests used to hit an assertion in the bug report. Test case from http://llvm.org/PR24184.
diff --git a/test/Analysis/PR2599.m b/test/Analysis/PR2599.m
deleted file mode 100644
index 1c2270e6aa66..000000000000
--- a/test/Analysis/PR2599.m
+++ /dev/null
@@ -1,63 +0,0 @@
-// RUN: %clang_analyze_cc1 -triple %itanium_abi_triple -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -fobjc-gc -verify %s
-
-typedef const void * CFTypeRef;
-typedef const struct __CFString * CFStringRef;
-typedef const struct __CFAllocator * CFAllocatorRef;
-typedef const struct __CFDictionary * CFDictionaryRef;
-CFTypeRef CFMakeCollectable(CFTypeRef cf) ;
-extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...);
-typedef signed char BOOL;
-typedef unsigned int NSUInteger;
-typedef struct _NSZone NSZone;
-@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
-@protocol NSObject
-- (BOOL)isEqual:(id)object;
-- (id)autorelease;
-@end
-@protocol NSCopying
-- (id)copyWithZone:(NSZone *)zone;
-@end @protocol NSMutableCopying
-- (id)mutableCopyWithZone:(NSZone *)zone;
-@end
-@protocol
-NSCoding
-- (void)encodeWithCoder:(NSCoder *)aCoder;
-@end
-@interface NSObject <NSObject> {}
-- (id)init;
-+ (id)alloc;
-@end
-enum { NSASCIIStringEncoding = 1, NSNEXTSTEPStringEncoding = 2, NSJapaneseEUCStringEncoding = 3, NSUTF8StringEncoding = 4, NSISOLatin1StringEncoding = 5, NSSymbolStringEncoding = 6, NSNonLossyASCIIStringEncoding = 7, NSShiftJISStringEncoding = 8, NSISOLatin2StringEncoding = 9, NSUnicodeStringEncoding = 10, NSWindowsCP1251StringEncoding = 11, NSWindowsCP1252StringEncoding = 12, NSWindowsCP1253StringEncoding = 13, NSWindowsCP1254StringEncoding = 14, NSWindowsCP1250StringEncoding = 15, NSISO2022JPStringEncoding = 21, NSMacOSRomanStringEncoding = 30, NSUTF16StringEncoding = NSUnicodeStringEncoding, NSUTF16BigEndianStringEncoding = 0x90000100, NSUTF16LittleEndianStringEncoding = 0x94000100, NSUTF32StringEncoding = 0x8c000100, NSUTF32BigEndianStringEncoding = 0x98000100, NSUTF32LittleEndianStringEncoding = 0x9c000100 };
-typedef NSUInteger NSStringEncoding;
-@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
-- (NSUInteger)length;
-- (id)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)len encoding:(NSStringEncoding)encoding freeWhenDone:(BOOL)freeBuffer;
-@end
-@interface NSAutoreleasePool : NSObject {}
-- (void)drain;
-@end
-extern NSString * const NSXMLParserErrorDomain ;
-
-// The actual test case. UTIL_AUTORELEASE_CF_AS_ID is a macro that doesn't
-// actually do what it was intended to.
-
-#define NSSTRINGWRAPPER(bytes,len) \
- [[[NSString alloc] initWithBytesNoCopy: (void*)(bytes) length: (len) encoding: NSUTF8StringEncoding freeWhenDone: (BOOL)0] autorelease]
-
-#define UTIL_AUTORELEASE_CF_AS_ID(cf) ( (((void*)0) == (cf)) ? ((void*)0) : [(id) CFMakeCollectable( (CFTypeRef) cf) autorelease] )
-
-#define UTIL_AUTORELEASE_CF_AS_ID_WITHOUT_TEST(cf) ( [(id) CFMakeCollectable( (CFTypeRef) cf) autorelease] )
-
-static char *lorem = "fooBarBaz";
-
-void NSLog(NSString *, ...);
-
-int main (int argc, const char * argv[]) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- NSString *tmp1 = NSSTRINGWRAPPER(lorem, 6); // no-warning
- NSString *tmp2 = UTIL_AUTORELEASE_CF_AS_ID( CFStringCreateWithFormat(((void*)0), ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "lorem: %@" "")), tmp1) ); // expected-warning 2 {{leak}}
- NSString *tmp3 = UTIL_AUTORELEASE_CF_AS_ID_WITHOUT_TEST( CFStringCreateWithFormat(((void*)0), ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "lorem: %@" "")), tmp1) );
- NSLog(@"tmp2: %@ tmp3: %@", tmp2, tmp3);
- [pool drain];
- return 0;
-}
diff --git a/test/Analysis/PR37855.c b/test/Analysis/PR37855.c
index 0779796531fd..e9c2564ba008 100644
--- a/test/Analysis/PR37855.c
+++ b/test/Analysis/PR37855.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -w -DNO_CROSSCHECK -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -w -analyzer-config crosscheck-with-z3=true -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -w -DNO_CROSSCHECK -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -w -analyzer-config crosscheck-with-z3=true -verify %s
// REQUIRES: z3
typedef struct o p;
diff --git a/test/Analysis/additive-folding-range-constraints.c b/test/Analysis/additive-folding-range-constraints.c
index 87d1b1cd8958..e75223eab05b 100644
--- a/test/Analysis/additive-folding-range-constraints.c
+++ b/test/Analysis/additive-folding-range-constraints.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config eagerly-assume=false -verify %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/additive-folding.cpp b/test/Analysis/additive-folding.cpp
index 823b17600428..6c84bf345e5e 100644
--- a/test/Analysis/additive-folding.cpp
+++ b/test/Analysis/additive-folding.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -Wno-tautological-compare %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -Wno-tautological-compare -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/analyzer-config.c b/test/Analysis/analyzer-config.c
index c09800f44b63..50b5c2dcf65f 100644
--- a/test/Analysis/analyzer-config.c
+++ b/test/Analysis/analyzer-config.c
@@ -1,16 +1,16 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
// RUN: FileCheck --input-file=%t %s --match-full-lines
-void bar() {}
-void foo() {
- // Call bar 33 times so max-times-inline-large is met and
- // min-blocks-for-inline-large is checked
- for (int i = 0; i < 34; ++i) {
- bar();
- }
-}
-
// CHECK: [config]
+// CHECK-NEXT: aggressive-binary-operation-simplification = false
+// CHECK-NEXT: avoid-suppressing-null-argument-paths = false
+// CHECK-NEXT: c++-allocator-inlining = true
+// CHECK-NEXT: c++-container-inlining = false
+// CHECK-NEXT: c++-inlining = destructors
+// CHECK-NEXT: c++-shared_ptr-inlining = false
+// CHECK-NEXT: c++-stdlib-inlining = true
+// CHECK-NEXT: c++-temp-dtor-inlining = true
+// CHECK-NEXT: c++-template-inlining = true
// CHECK-NEXT: cfg-conditional-static-initializers = true
// CHECK-NEXT: cfg-implicit-dtors = true
// CHECK-NEXT: cfg-lifetime = false
@@ -18,7 +18,14 @@ void foo() {
// CHECK-NEXT: cfg-rich-constructors = true
// CHECK-NEXT: cfg-scopes = false
// CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: crosscheck-with-z3 = false
+// CHECK-NEXT: ctu-dir = ""
+// CHECK-NEXT: ctu-index-name = externalDefMap.txt
+// CHECK-NEXT: display-ctu-progress = false
+// CHECK-NEXT: eagerly-assume = true
// CHECK-NEXT: elide-constructors = true
+// CHECK-NEXT: expand-macros = false
+// CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
// CHECK-NEXT: exploration_strategy = unexplored_first_queue
// CHECK-NEXT: faux-bodies = true
// CHECK-NEXT: graph-trim-interval = 1000
@@ -27,12 +34,22 @@ void foo() {
// CHECK-NEXT: ipa-always-inline-size = 3
// CHECK-NEXT: max-inlinable-size = 100
// CHECK-NEXT: max-nodes = 225000
+// CHECK-NEXT: max-symbol-complexity = 35
// CHECK-NEXT: max-times-inline-large = 32
// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
// CHECK-NEXT: mode = deep
+// CHECK-NEXT: model-path = ""
+// CHECK-NEXT: notes-as-events = false
+// CHECK-NEXT: objc-inlining = true
+// CHECK-NEXT: prune-paths = true
// CHECK-NEXT: region-store-small-struct-limit = 2
+// CHECK-NEXT: report-in-main-source-file = false
// CHECK-NEXT: serialize-stats = false
+// CHECK-NEXT: stable-report-filename = false
+// CHECK-NEXT: suppress-c++-stdlib = true
+// CHECK-NEXT: suppress-inlined-defensive-checks = true
+// CHECK-NEXT: suppress-null-return-paths = true
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 23
+// CHECK-NEXT: num-entries = 49
diff --git a/test/Analysis/analyzer-config.cpp b/test/Analysis/analyzer-config.cpp
deleted file mode 100644
index e87045448d3a..000000000000
--- a/test/Analysis/analyzer-config.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
-// RUN: FileCheck --input-file=%t %s --match-full-lines
-
-void bar() {}
-void foo() {
- // Call bar 33 times so max-times-inline-large is met and
- // min-blocks-for-inline-large is checked
- for (int i = 0; i < 34; ++i) {
- bar();
- }
-}
-
-class Foo {
-public:
- ~Foo() {}
- void baz() { Foo(); }
- void bar() { const Foo &f = Foo(); }
- void foo() { bar(); }
-};
-
-// CHECK: [config]
-// CHECK-NEXT: c++-container-inlining = false
-// CHECK-NEXT: c++-inlining = destructors
-// CHECK-NEXT: c++-shared_ptr-inlining = false
-// CHECK-NEXT: c++-stdlib-inlining = true
-// CHECK-NEXT: c++-temp-dtor-inlining = true
-// CHECK-NEXT: c++-template-inlining = true
-// CHECK-NEXT: cfg-conditional-static-initializers = true
-// CHECK-NEXT: cfg-implicit-dtors = true
-// CHECK-NEXT: cfg-lifetime = false
-// CHECK-NEXT: cfg-loopexit = false
-// CHECK-NEXT: cfg-rich-constructors = true
-// CHECK-NEXT: cfg-scopes = false
-// CHECK-NEXT: cfg-temporary-dtors = true
-// CHECK-NEXT: elide-constructors = true
-// CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
-// CHECK-NEXT: exploration_strategy = unexplored_first_queue
-// CHECK-NEXT: faux-bodies = true
-// CHECK-NEXT: graph-trim-interval = 1000
-// CHECK-NEXT: inline-lambdas = true
-// CHECK-NEXT: ipa = dynamic-bifurcate
-// CHECK-NEXT: ipa-always-inline-size = 3
-// CHECK-NEXT: max-inlinable-size = 100
-// CHECK-NEXT: max-nodes = 225000
-// CHECK-NEXT: max-times-inline-large = 32
-// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
-// CHECK-NEXT: mode = deep
-// CHECK-NEXT: region-store-small-struct-limit = 2
-// CHECK-NEXT: serialize-stats = false
-// CHECK-NEXT: unroll-loops = false
-// CHECK-NEXT: widen-loops = false
-// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 30
diff --git a/test/Analysis/analyzer-list-configs.c b/test/Analysis/analyzer-list-configs.c
new file mode 100644
index 000000000000..c9f6e55167fd
--- /dev/null
+++ b/test/Analysis/analyzer-list-configs.c
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -analyzer-config-help 2>&1 | FileCheck %s
+// CHECK: OVERVIEW: Clang Static Analyzer -analyzer-config Option List
+//
+// CHECK: USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>
+//
+// CHCEK: clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, -analyzer-config OPTION2=VALUE, ...
+//
+// CHECK: clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang<OPTION1=VALUE,OPTION2=VALUE,...>
+//
+// CHECK: clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang OPTION1=VALUE, -Xclang -analyzer-config -Xclang OPTION2=VALUE, ...
+//
+//
+// CHECK: OPTIONS:
+//
+// CHECK: aggressive-binary-operation-simplification
+// CHECK: (bool) Whether SValBuilder should rearrange
+// CHECK: comparisons and additive operations of symbolic
+// CHECK: expressions which consist of a sum of a
+// CHECK: symbol and a concrete integer into the format
+// CHECK: where symbols are on the left-hand side
+// CHECK: and the integer is on the right. This is
+// CHECK: only done if both symbols and both concrete
+// CHECK: integers are signed, greater than or equal
+// CHECK: to the quarter of the minimum value of the
+// CHECK: type and less than or equal to the quarter
+// CHECK: of the maximum value of that type. A
+// CHECK: + n
+// CHECK: <OP> B + m becomes A - B <OP> m - n, where
+// CHECK: A and B symbolic, n and m are integers.
+// CHECK: <OP> is any of '==', '!=', '<', '<=', '>',
+// CHECK: '>=', '+' or '-'. The rearrangement also
+// CHECK: happens with '-' instead of '+' on either
+// CHECK: or both side and also if any or both integers
+// CHECK: are missing. (default: false)
diff --git a/test/Analysis/analyzer_test.py b/test/Analysis/analyzer_test.py
index 0aa2dbc1bb09..03124333fe7b 100644
--- a/test/Analysis/analyzer_test.py
+++ b/test/Analysis/analyzer_test.py
@@ -4,6 +4,10 @@ import lit.TestRunner
# Custom format class for static analyzer tests
class AnalyzerTest(lit.formats.ShTest):
+ def __init__(self, execute_external, use_z3_solver=False):
+ super(AnalyzerTest, self).__init__(execute_external)
+ self.use_z3_solver = use_z3_solver
+
def execute(self, test, litConfig):
results = []
@@ -19,7 +23,8 @@ class AnalyzerTest(lit.formats.ShTest):
return results[-1]
# If z3 backend available, add an additional run line for it
- if test.config.clang_staticanalyzer_z3 == '1':
+ if self.use_z3_solver == '1':
+ assert(test.config.clang_staticanalyzer_z3 == '1')
results.append(self.executeWithAnalyzeSubstitution(
saved_test, litConfig, '-analyzer-constraints=z3 -DANALYZER_CM_Z3'))
diff --git a/test/Analysis/array-struct-region.c b/test/Analysis/array-struct-region.c
index cdfec456cdae..c27abfb6ac98 100644
--- a/test/Analysis/array-struct-region.c
+++ b/test/Analysis/array-struct-region.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/asm.cpp b/test/Analysis/asm.cpp
new file mode 100644
index 000000000000..118006350216
--- /dev/null
+++ b/test/Analysis/asm.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -fheinous-gnu-extensions -w %s -verify
+
+int clang_analyzer_eval(int);
+
+int global;
+void testRValueOutput() {
+ int &ref = global;
+ ref = 1;
+ __asm__("" : "=r"(((int)(global)))); // don't crash on rvalue output operand
+ clang_analyzer_eval(global == 1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(ref == 1); // expected-warning{{UNKNOWN}}
+}
diff --git a/test/Analysis/atomics.c b/test/Analysis/atomics.c
index 6fe4ec580b86..b3d2d352a228 100644
--- a/test/Analysis/atomics.c
+++ b/test/Analysis/atomics.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s -analyzer-config eagerly-assume=false
// Tests for c11 atomics. Many of these tests currently yield unknown
// because we don't fully model the atomics and instead imprecisely
diff --git a/test/Analysis/blocks-no-inline.c b/test/Analysis/blocks-no-inline.c
index 859eedfbc3af..9fa3138ec277 100644
--- a/test/Analysis/blocks-no-inline.c
+++ b/test/Analysis/blocks-no-inline.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -fblocks -verify -x c++ %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -fblocks -analyzer-config eagerly-assume=false -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -fblocks -analyzer-config eagerly-assume=false -verify -x c++ %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/bstring.c b/test/Analysis/bstring.c
index 89a77cdff866..e8c3021f27be 100644
--- a/test/Analysis/bstring.c
+++ b/test/Analysis/bstring.c
@@ -1,7 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
//===----------------------------------------------------------------------===
// Declarations
diff --git a/test/Analysis/bstring.cpp b/test/Analysis/bstring.cpp
index 19978f913cb1..ef03aafbbb81 100644
--- a/test/Analysis/bstring.cpp
+++ b/test/Analysis/bstring.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
#include "Inputs/system-header-simulator-cxx.h"
#include "Inputs/system-header-simulator-for-malloc.h"
diff --git a/test/Analysis/builtin-functions.cpp b/test/Analysis/builtin-functions.cpp
index 19984963b4fa..da2fcf915d31 100644
--- a/test/Analysis/builtin-functions.cpp
+++ b/test/Analysis/builtin-functions.cpp
@@ -70,14 +70,14 @@ void test_constant_p() {
const int j = 2;
constexpr int k = 3;
clang_analyzer_eval(__builtin_constant_p(42) == 1); // expected-warning {{TRUE}}
- clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(__builtin_constant_p(j) == 1); // expected-warning {{TRUE}}
clang_analyzer_eval(__builtin_constant_p(k) == 1); // expected-warning {{TRUE}}
- clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(__builtin_constant_p(j + 42) == 1); // expected-warning {{TRUE}}
clang_analyzer_eval(__builtin_constant_p(k + 42) == 1); // expected-warning {{TRUE}}
clang_analyzer_eval(__builtin_constant_p(" ") == 1); // expected-warning {{TRUE}}
- clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{TRUE}}
+ clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(__builtin_constant_p(k - 3) == 0); // expected-warning {{FALSE}}
clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}}
}
diff --git a/test/Analysis/call-invalidation.cpp b/test/Analysis/call-invalidation.cpp
index d3b5fca9cd5b..c107e1070544 100644
--- a/test/Analysis/call-invalidation.cpp
+++ b/test/Analysis/call-invalidation.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c
index 86fb7da58ec2..2d96aa3571d3 100644
--- a/test/Analysis/casts.c
+++ b/test/Analysis/casts.c
@@ -1,5 +1,7 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify %s
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -w %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -DBIT32=1 -w %s
extern void clang_analyzer_eval(_Bool);
@@ -16,6 +18,8 @@ struct sockaddr_storage {};
void getsockname();
+#ifndef EAGERLY_ASSUME
+
void f(int sock) {
struct sockaddr_storage storage;
struct sockaddr* sockaddr = (struct sockaddr*)&storage; // expected-warning{{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
@@ -182,3 +186,62 @@ void testLocNonLocSymbolRemainder(int a, int *b) {
c += 1;
}
}
+
+void testSwitchWithSizeofs() {
+ switch (sizeof(char) == 1) { // expected-warning{{switch condition has boolean value}}
+ case sizeof(char):; // no-crash
+ }
+}
+
+#endif
+
+#ifdef EAGERLY_ASSUME
+
+int globalA;
+extern int globalFunc();
+void no_crash_on_symsym_cast_to_long() {
+ char c = globalFunc() - 5;
+ c == 0;
+ globalA -= c;
+ globalA == 3;
+ (long)globalA << 48;
+ #ifdef BIT32
+ // expected-warning@-2{{The result of the left shift is undefined due to shifting by '48', which is greater or equal to the width of type 'long'}}
+ #else
+ // expected-no-diagnostics
+ #endif
+}
+
+#endif
+
+char no_crash_SymbolCast_of_float_type_aux(int *p) {
+ *p += 1;
+ return *p;
+}
+
+void no_crash_SymbolCast_of_float_type() {
+ extern float x;
+ char (*f)() = no_crash_SymbolCast_of_float_type_aux;
+ f(&x);
+}
+
+double no_crash_reinterpret_double_as_int(double a) {
+ *(int *)&a = 1;
+ return a * a;
+}
+
+double no_crash_reinterpret_double_as_ptr(double a) {
+ *(void **)&a = 0;
+ return a * a;
+}
+
+double no_crash_reinterpret_double_as_sym_int(double a, int b) {
+ *(int *)&a = b;
+ return a * a;
+}
+
+double no_crash_reinterpret_double_as_sym_ptr(double a, void * b) {
+ *(void **)&a = b;
+ return a * a;
+}
+
diff --git a/test/Analysis/casts.cpp b/test/Analysis/casts.cpp
index 757eb6da6623..aa2bd9c1fadc 100644
--- a/test/Analysis/casts.cpp
+++ b/test/Analysis/casts.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s
+
+void clang_analyzer_eval(bool);
bool PR14634(int x) {
double y = (double)x;
@@ -41,3 +43,74 @@ bool retrievePointerFromBoolean(int *p) {
*reinterpret_cast<int **>(&q) = p;
return q;
}
+
+namespace base_to_derived {
+struct A {};
+struct B : public A{};
+
+void foo(A* a) {
+ B* b = (B* ) a;
+ A* a2 = (A *) b;
+ clang_analyzer_eval(a2 == a); // expected-warning{{TRUE}}
+}
+}
+
+namespace base_to_derived_double_inheritance {
+struct A {
+ int x;
+};
+struct B {
+ int y;
+};
+struct C : A, B {};
+
+void foo(B *b) {
+ C *c = (C *)b;
+ b->y = 1;
+ clang_analyzer_eval(c->x); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(c->y); // expected-warning{{TRUE}}
+}
+} // namespace base_to_derived_double_inheritance
+
+namespace base_to_derived_opaque_class {
+class NotInt {
+public:
+ operator int() { return !x; } // no-crash
+ int x;
+};
+
+typedef struct Opaque *OpaqueRef;
+typedef void *VeryOpaqueRef;
+
+class Transparent {
+public:
+ int getNotInt() { return NI; }
+ NotInt NI;
+};
+
+class SubTransparent : public Transparent {};
+
+SubTransparent *castToDerived(Transparent *TRef) {
+ return (SubTransparent *)TRef;
+}
+
+void foo(OpaqueRef ORef) {
+ castToDerived(reinterpret_cast<Transparent *>(ORef))->getNotInt();
+}
+
+void foo(VeryOpaqueRef ORef) {
+ castToDerived(reinterpret_cast<Transparent *>(ORef))->getNotInt();
+}
+} // namespace base_to_derived_opaque_class
+
+namespace bool_to_nullptr {
+struct S {
+ int *a[1];
+ bool b;
+};
+void foo(S s) {
+ s.b = true;
+ for (int i = 0; i < 2; ++i)
+ (void)(s.a[i] != nullptr); // no-crash
+}
+} // namespace bool_to_nullptr
diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp
index 88b03788da43..31c306bbfe9c 100644
--- a/test/Analysis/cfg-rich-constructors.cpp
+++ b/test/Analysis/cfg-rich-constructors.cpp
@@ -820,6 +820,7 @@ public:
class E {
public:
E(D d);
+ E(D d1, D d2);
};
void useC(C c);
@@ -939,6 +940,38 @@ void passArgumentWithDestructorByReference() {
void passArgumentIntoAnotherConstructor() {
E e = E(D());
}
+
+
+// CHECK: void passTwoArgumentsIntoAnotherConstructor()
+// CXX11-ELIDE: 1: argument_constructors::D() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class argument_constructors::D)
+// CXX11-NOELIDE: 1: argument_constructors::D() (CXXConstructExpr, [B1.2], [B1.4], class argument_constructors::D)
+// CXX11-NEXT: 2: [B1.1] (BindTemporary)
+// CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], [B1.13]+0, class argument_constructors::D)
+// CXX11-NEXT: 6: [B1.5] (BindTemporary)
+// CXX11-ELIDE-NEXT: 7: argument_constructors::D() (CXXConstructExpr, [B1.8], [B1.10], [B1.11], class argument_constructors::D)
+// CXX11-NOELIDE-NEXT: 7: argument_constructors::D() (CXXConstructExpr, [B1.8], [B1.10], class argument_constructors::D)
+// CXX11-NEXT: 8: [B1.7] (BindTemporary)
+// CXX11-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CXX11-NEXT: 10: [B1.9]
+// CXX11-NEXT: 11: [B1.10] (CXXConstructExpr, [B1.12], [B1.13]+1, class argument_constructors::D)
+// CXX11-NEXT: 12: [B1.11] (BindTemporary)
+// CXX11-NEXT: 13: argument_constructors::E([B1.6], [B1.12]) (CXXConstructExpr, class argument_constructors::E)
+// CXX11-NEXT: 14: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT: 15: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT: 16: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT: 17: ~argument_constructors::D() (Temporary object destructor)
+// CXX17: 1: argument_constructors::D() (CXXConstructExpr, [B1.2], [B1.5]+0, class argument_constructors::D)
+// CXX17-NEXT: 2: [B1.1] (BindTemporary)
+// CXX17-NEXT: 3: argument_constructors::D() (CXXConstructExpr, [B1.4], [B1.5]+1, class argument_constructors::D)
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// CXX17-NEXT: 5: argument_constructors::E([B1.2], [B1.4]) (CXXConstructExpr, class argument_constructors::E)
+// CXX17-NEXT: 6: ~argument_constructors::D() (Temporary object destructor)
+// CXX17-NEXT: 7: ~argument_constructors::D() (Temporary object destructor)
+void passTwoArgumentsIntoAnotherConstructor() {
+ E(D(), D());
+}
} // end namespace argument_constructors
namespace copy_elision_with_extra_arguments {
@@ -963,3 +996,50 @@ void testCopyElisionWhenCopyConstructorHasExtraArguments() {
C c = C();
}
} // namespace copy_elision_with_extra_arguments
+
+
+namespace operators {
+class C {
+public:
+ C(int);
+ C &operator+(C Other);
+};
+
+// FIXME: Find construction context for the this-argument of the operator.
+// CHECK: void testOperators()
+// CHECK: [B1]
+// CHECK-NEXT: 1: operator+
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class operators::C &(*)(class o
+// CHECK-NEXT: 3: 1
+// CHECK-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], class operators::C)
+// CHECK-NEXT: 5: operators::C([B1.4]) (CXXFunctionalCastExpr, ConstructorConversion, class operato
+// CHECK-NEXT: 6: [B1.5]
+// CHECK-NEXT: 7: 2
+// CXX11-ELIDE-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.10], [B1.11], class operators::C)
+// CXX11-NOELIDE-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.10], class operators::C)
+// CXX11-NEXT: 9: operators::C([B1.8]) (CXXFunctionalCastExpr, ConstructorConversion, class operato
+// CXX11-NEXT: 10: [B1.9]
+// CXX11-NEXT: 11: [B1.10] (CXXConstructExpr, [B1.12]+1, class operators::C)
+// CXX11-NEXT: 12: [B1.6] + [B1.11] (OperatorCall)
+// CXX17-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.10]+1, class operators::C)
+// CXX17-NEXT: 9: operators::C([B1.8]) (CXXFunctionalCastExpr, ConstructorConversion, class operato
+// CXX17-NEXT: 10: [B1.6] + [B1.9] (OperatorCall)
+void testOperators() {
+ C(1) + C(2);
+}
+} // namespace operators
+
+namespace variadic_function_arguments {
+class C {
+ public:
+ C(int);
+};
+
+int variadic(...);
+
+// This code is quite exotic, so let's not test the CFG for it,
+// but only make sure we don't crash.
+void testCrashOnVariadicArgument() {
+ C c(variadic(0 ? c : 0)); // no-crash
+}
+} // namespace variadic_function_arguments
diff --git a/test/Analysis/cfg.cpp b/test/Analysis/cfg.cpp
index 85c5be5a9819..f43a809c77ef 100644
--- a/test/Analysis/cfg.cpp
+++ b/test/Analysis/cfg.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -analyzer-config cfg-rich-constructors=false %s > %t 2>&1
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -fheinous-gnu-extensions -std=c++11 -analyzer-config cfg-rich-constructors=false %s > %t 2>&1
// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -analyzer-config cfg-rich-constructors=true %s > %t 2>&1
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -fheinous-gnu-extensions -std=c++11 -analyzer-config cfg-rich-constructors=true %s > %t 2>&1
// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s
// This file tests how we construct two different flavors of the Clang CFG -
@@ -84,6 +84,24 @@ void checkDeclStmts() {
static_assert(1, "abc");
}
+
+// CHECK-LABEL: void checkGCCAsmRValueOutput()
+// CHECK: [B2 (ENTRY)]
+// CHECK-NEXT: Succs (1): B1
+// CHECK: [B1]
+// CHECK-NEXT: 1: int arg
+// CHECK-NEXT: 2: arg
+// CHECK-NEXT: 3: (int)[B1.2] (CStyleCastExpr, NoOp, int)
+// CHECK-NEXT: 4: asm ("" : "=r" ([B1.3]));
+// CHECK-NEXT: 5: arg
+// CHECK-NEXT: 6: asm ("" : "=r" ([B1.5]));
+void checkGCCAsmRValueOutput() {
+ int arg;
+ __asm__("" : "=r"((int)arg)); // rvalue output operand
+ __asm__("" : "=r"(arg)); // lvalue output operand
+}
+
+
// CHECK-LABEL: void F(EmptyE e)
// CHECK: ENTRY
// CHECK-NEXT: Succs (1): B1
diff --git a/test/Analysis/conditional-operator.cpp b/test/Analysis/conditional-operator.cpp
index 32978c66fa14..5060ec0c804f 100644
--- a/test/Analysis/conditional-operator.cpp
+++ b/test/Analysis/conditional-operator.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection %s -analyzer-output=text -verify
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config eagerly-assume=false %s -analyzer-output=text -verify
void clang_analyzer_eval(bool);
@@ -14,4 +14,4 @@ void OperatorEvaluationTest(int y) {
// TODO: We are not precise when processing the "?:" operator in C++.
clang_analyzer_eval(w == 1); // expected-warning{{UNKNOWN}}
// expected-note@-1{{UNKNOWN}}
-} \ No newline at end of file
+}
diff --git a/test/Analysis/conditional-path-notes.c b/test/Analysis/conditional-path-notes.c
index 8fc27be391be..fb2dd9f2ca54 100644
--- a/test/Analysis/conditional-path-notes.c
+++ b/test/Analysis/conditional-path-notes.c
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=text -verify
// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -o %t
-// RUN: FileCheck --input-file=%t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/conditional-path-notes.c.plist -
void testCondOp(int *p) {
int *x = p ? p : p;
@@ -84,1684 +84,3 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8ea3f4e6a3100c73f078fac15acb0a9c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCondOp</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2c219a33e961fc1be7d54b700867259e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCondProblem</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8d43b511137326eab7d1242950e72984</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testLHSProblem</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b8e93b7355a6779a960f9a942fafac15</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testRHSProblem</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a944281d096940ca43ec995649b48b5f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testBinaryCondOp</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4db164bbf5cea42d75c5e838be1eef6f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testBinaryLHSProblem</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>778d56ad485369222613ac2c03b97700</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testDiagnosableBranch</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;b&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;b&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a2b345c9681d9dd3aa15d12810759cb9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testDiagnosableBranchLogical</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f56671e5f67c73abef619b56f7c29fa4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testNonDiagnosableBranchArithmetic</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/const-method-call.cpp b/test/Analysis/const-method-call.cpp
index a5a38929c22f..902bdee27721 100644
--- a/test/Analysis/const-method-call.cpp
+++ b/test/Analysis/const-method-call.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/constant-folding.c b/test/Analysis/constant-folding.c
index e21d629e9a41..fc04e608f7ef 100644
--- a/test/Analysis/constant-folding.c
+++ b/test/Analysis/constant-folding.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/conversion.c b/test/Analysis/conversion.c
index 7adb336eb249..8b77e25358ee 100644
--- a/test/Analysis/conversion.c
+++ b/test/Analysis/conversion.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -Wno-conversion -Wno-tautological-constant-compare -analyzer-checker=core,alpha.core.Conversion -verify %s
+// RUN: %clang_analyze_cc1 -Wno-conversion -Wno-tautological-constant-compare -analyzer-checker=core,apiModeling,alpha.core.Conversion -verify %s
unsigned char U8;
signed char S8;
@@ -137,16 +137,21 @@ void dontwarn5() {
U8 = S + 10;
}
+char dontwarn6(long long x) {
+ long long y = 42;
+ y += x;
+ return y == 42;
+}
+
-// false positives..
+// C library functions, handled via apiModeling.StdCLibraryFunctions
int isascii(int c);
-void falsePositive1() {
+void libraryFunction1() {
char kb2[5];
int X = 1000;
if (isascii(X)) {
- // FIXME: should not warn here:
- kb2[0] = X; // expected-warning {{Loss of precision}}
+ kb2[0] = X; // no-warning
}
}
@@ -155,8 +160,8 @@ typedef struct FILE {} FILE; int getc(FILE *stream);
# define EOF (-1)
char reply_string[8192];
FILE *cin;
-extern int dostuff (void);
-int falsePositive2() {
+extern int dostuff(void);
+int libraryFunction2() {
int c, n;
int dig;
char *cp = reply_string;
@@ -175,9 +180,31 @@ int falsePositive2() {
if (c == EOF)
return(4);
if (cp < &reply_string[sizeof(reply_string) - 1])
- // FIXME: should not warn here:
- *cp++ = c; // expected-warning {{Loss of precision}}
+ *cp++ = c; // no-warning
}
}
}
+double floating_point(long long a, int b) {
+ if (a > 1LL << 55) {
+ double r = a; // expected-warning {{Loss of precision}}
+ return r;
+ } else if (b > 1 << 25) {
+ float f = b; // expected-warning {{Loss of precision}}
+ return f;
+ }
+ return 137;
+}
+
+double floating_point2() {
+ int a = 1 << 24;
+ long long b = 1LL << 53;
+ float f = a; // no-warning
+ double d = b; // no-warning
+ return d - f;
+}
+
+int floating_point_3(unsigned long long a) {
+ double b = a; // no-warning
+ return 42;
+}
diff --git a/test/Analysis/copy-elision.cpp b/test/Analysis/copy-elision.cpp
index cf77912ea6c4..3d2055f6392c 100644
--- a/test/Analysis/copy-elision.cpp
+++ b/test/Analysis/copy-elision.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify -analyzer-config eagerly-assume=false %s
// Copy elision always occurs in C++17, otherwise it's under
// an on-by-default flag.
@@ -122,7 +122,7 @@ void foo(int coin) {
namespace address_vector_tests {
template <typename T> struct AddressVector {
- T *buf[10];
+ T *buf[20];
int len;
AddressVector() : len(0) {}
@@ -138,13 +138,13 @@ class ClassWithoutDestructor {
public:
ClassWithoutDestructor(AddressVector<ClassWithoutDestructor> &v) : v(v) {
- v.push(this);
+ push();
}
- ClassWithoutDestructor(ClassWithoutDestructor &&c) : v(c.v) { v.push(this); }
- ClassWithoutDestructor(const ClassWithoutDestructor &c) : v(c.v) {
- v.push(this);
- }
+ ClassWithoutDestructor(ClassWithoutDestructor &&c) : v(c.v) { push(); }
+ ClassWithoutDestructor(const ClassWithoutDestructor &c) : v(c.v) { push(); }
+
+ void push() { v.push(this); }
};
ClassWithoutDestructor make1(AddressVector<ClassWithoutDestructor> &v) {
@@ -174,20 +174,44 @@ void testMultipleReturns() {
#endif
}
+void consume(ClassWithoutDestructor c) {
+ c.push();
+}
+
+void testArgumentConstructorWithoutDestructor() {
+ AddressVector<ClassWithoutDestructor> v;
+
+ consume(make3(v));
+
+#if ELIDE
+ clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
+#else
+ clang_analyzer_eval(v.len == 6); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] != v.buf[1]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] != v.buf[2]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[2] != v.buf[3]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[3] != v.buf[4]); // expected-warning{{TRUE}}
+ // We forced a push() in consume(), let's see if the address here matches
+ // the address during construction.
+ clang_analyzer_eval(v.buf[4] == v.buf[5]); // expected-warning{{TRUE}}
+#endif
+}
+
class ClassWithDestructor {
AddressVector<ClassWithDestructor> &v;
public:
ClassWithDestructor(AddressVector<ClassWithDestructor> &v) : v(v) {
- v.push(this);
+ push();
}
- ClassWithDestructor(ClassWithDestructor &&c) : v(c.v) { v.push(this); }
- ClassWithDestructor(const ClassWithDestructor &c) : v(c.v) {
- v.push(this);
- }
+ ClassWithDestructor(ClassWithDestructor &&c) : v(c.v) { push(); }
+ ClassWithDestructor(const ClassWithDestructor &c) : v(c.v) { push(); }
- ~ClassWithDestructor() { v.push(this); }
+ ~ClassWithDestructor() { push(); }
+
+ void push() { v.push(this); }
};
void testVariable() {
@@ -301,4 +325,43 @@ void testMultipleReturnsWithDestructors() {
clang_analyzer_eval(v.buf[7] == v.buf[9]); // expected-warning{{TRUE}}
#endif
}
+
+void consume(ClassWithDestructor c) {
+ c.push();
+}
+
+void testArgumentConstructorWithDestructor() {
+ AddressVector<ClassWithDestructor> v;
+
+ consume(make3(v));
+
+#if ELIDE
+ // 0. Construct the argument.
+ // 1. Forced push() in consume().
+ // 2. Destroy the argument.
+ clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] == v.buf[2]); // expected-warning{{TRUE}}
+#else
+ // 0. Construct the temporary in make1().
+ // 1. Construct the temporary in make2().
+ // 2. Destroy the temporary in make1().
+ // 3. Construct the temporary in make3().
+ // 4. Destroy the temporary in make2().
+ // 5. Construct the temporary here.
+ // 6. Destroy the temporary in make3().
+ // 7. Construct the argument.
+ // 8. Forced push() in consume().
+ // 9. Destroy the argument. Notice the reverse order!
+ // 10. Destroy the temporary here.
+ clang_analyzer_eval(v.len == 11); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[1] == v.buf[4]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[3] == v.buf[6]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[5] == v.buf[10]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[7] == v.buf[8]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(v.buf[8] == v.buf[9]); // expected-warning{{TRUE}}
+#endif
+}
+
} // namespace address_vector_tests
diff --git a/test/Analysis/copypaste/Inputs/expected-plists/MismatchedDeallocator-path-notes.cpp.plist b/test/Analysis/copypaste/Inputs/expected-plists/MismatchedDeallocator-path-notes.cpp.plist
new file mode 100644
index 000000000000..94d925edaeb5
--- /dev/null
+++ b/test/Analysis/copypaste/Inputs/expected-plists/MismatchedDeallocator-path-notes.cpp.plist
@@ -0,0 +1,303 @@
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;allocIntArray&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;allocIntArray&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returned allocated memory</string>
+ <key>message</key>
+ <string>Returned allocated memory</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ <key>message</key>
+ <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Bad deallocator</string>
+ <key>check_name</key><string>unix.MismatchedDeallocator</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2009ca1da75217064b6052ba7465dff9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>7</integer>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>12</integer>
+ <integer>13</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/MismatchedDeallocator-path-notes.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics-notes-as-events.cpp.plist b/test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics-notes-as-events.cpp.plist
new file mode 100644
index 000000000000..ecdf3216b965
--- /dev/null
+++ b/test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics-notes-as-events.cpp.plist
@@ -0,0 +1,98 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Similar code here</string>
+ <key>message</key>
+ <string>Similar code here</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Duplicate code detected</string>
+ <key>message</key>
+ <string>Duplicate code detected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Duplicate code detected</string>
+ <key>category</key><string>Code clone</string>
+ <key>type</key><string>Exact code clone</string>
+ <key>check_name</key><string>alpha.clone.CloneChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>13</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics.cpp.plist b/test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics.cpp.plist
new file mode 100644
index 000000000000..2813377cf00c
--- /dev/null
+++ b/test/Analysis/copypaste/Inputs/expected-plists/plist-diagnostics.cpp.plist
@@ -0,0 +1,99 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>notes</key>
+ <array>
+ <dict>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>extended_message</key>
+ <string>Similar code here</string>
+ <key>message</key>
+ <string>Similar code here</string>
+ </dict>
+ </array>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Duplicate code detected</string>
+ <key>message</key>
+ <string>Duplicate code detected</string>
+ </dict>
+ </array>
+ <key>description</key><string>Duplicate code detected</string>
+ <key>category</key><string>Code clone</string>
+ <key>type</key><string>Exact code clone</string>
+ <key>check_name</key><string>alpha.clone.CloneChecker</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>13</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/copypaste/plist-diagnostics.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp b/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp
index d4402a9dd58c..301a30b1c151 100644
--- a/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp
+++ b/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-output=plist -analyzer-config notes-as-events=true -o %t.plist -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:MinimumCloneComplexity=10 -verify %s
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/plist-diagnostics-notes-as-events.cpp.plist -
void log();
@@ -17,81 +17,3 @@ int maxClone(int a, int b) { // no-note (converted into event)
return b;
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Similar code here</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Similar code here</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Duplicate code detected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Duplicate code detected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Duplicate code detected</string>
-// CHECK-NEXT: <key>category</key><string>Code clone</string>
-// CHECK-NEXT: <key>type</key><string>Exact code clone</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.clone.CloneChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/copypaste/plist-diagnostics.cpp b/test/Analysis/copypaste/plist-diagnostics.cpp
index 38237b03c95f..c5ea2ae20e01 100644
--- a/test/Analysis/copypaste/plist-diagnostics.cpp
+++ b/test/Analysis/copypaste/plist-diagnostics.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:MinimumCloneComplexity=10 -verify %s
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/plist-diagnostics.cpp.plist -
void log();
@@ -17,82 +17,3 @@ int maxClone(int a, int b) { // expected-note{{Similar code here}}
return b;
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>notes</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Similar code here</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Similar code here</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Duplicate code detected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Duplicate code detected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Duplicate code detected</string>
-// CHECK-NEXT: <key>category</key><string>Code clone</string>
-// CHECK-NEXT: <key>type</key><string>Exact code clone</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.clone.CloneChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/cstring-plist.c b/test/Analysis/cstring-plist.c
index 19d0e46fd366..c527564d49e3 100644
--- a/test/Analysis/cstring-plist.c
+++ b/test/Analysis/cstring-plist.c
@@ -1,5 +1,8 @@
// RUN: rm -f %t
-// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc,unix.cstring.NullArg -analyzer-disable-checker=alpha.unix.cstring.OutOfBounds -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s
+// RUN: %clang_analyze_cc1 -fblocks \
+// RUN: -analyzer-checker=core,unix.Malloc,unix.cstring.NullArg \
+// RUN: -analyzer-disable-checker=alpha.unix.cstring.OutOfBounds \
+// RUN: -analyzer-output=plist -o %t %s
// RUN: FileCheck -input-file %t %s
typedef __typeof(sizeof(int)) size_t;
@@ -18,5 +21,8 @@ void cstringchecker_bounds_nocrash() {
// CHECK: <key>diagnostics</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>files</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </plist>
diff --git a/test/Analysis/cstring-syntax.c b/test/Analysis/cstring-syntax.c
index fe1253bedba3..d2e12e8303b1 100644
--- a/test/Analysis/cstring-syntax.c
+++ b/test/Analysis/cstring-syntax.c
@@ -7,6 +7,7 @@ typedef __SIZE_TYPE__ size_t;
char *strncat(char *, const char *, size_t);
size_t strlen (const char *s);
size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
void testStrncat(const char *src) {
char dest[10];
@@ -27,9 +28,27 @@ void testStrlcpy(const char *src) {
strlcpy(dest, src, sizeof(dest));
strlcpy(dest, src, destlen);
strlcpy(dest, src, 10);
- strlcpy(dest, src, 20); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
- strlcpy(dest, src, badlen); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}}
+ strlcpy(dest, src, 20); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+ strlcpy(dest, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
strlcpy(dest, src, ulen);
strlcpy(dest + 5, src, 5);
- strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}}
+ strlcpy(dest + 5, src, 10); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(<destination buffer>) or lower}}
+}
+
+void testStrlcat(const char *src) {
+ char dest[10];
+ size_t badlen = 20;
+ size_t ulen;
+ strlcpy(dest, "aaaaa", sizeof("aaaaa") - 1);
+ strlcat(dest, "bbbb", (sizeof("bbbb") - 1) - sizeof(dest) - 1);
+ strlcpy(dest, "012345678", sizeof(dest));
+ strlcat(dest, "910", sizeof(dest));
+ strlcpy(dest, "0123456789", sizeof(dest));
+ strlcpy(dest, "0123456789", sizeof(dest));
+ strlcat(dest, "0123456789", badlen / 2);
+ strlcat(dest, "0123456789", badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(dest) or lower}}
+ strlcat(dest, "0123456789", badlen - strlen(dest) - 1);
+ strlcat(dest, src, ulen);
+ strlcpy(dest, src, 5);
+ strlcat(dest + 5, src, badlen); // expected-warning {{The third argument allows to potentially copy more bytes than it should. Replace with the value sizeof(<destination buffer>) or lower}}
}
diff --git a/test/Analysis/ctor.mm b/test/Analysis/ctor.mm
index 751cdb944dc7..08f06e75aebf 100644
--- a/test/Analysis/ctor.mm
+++ b/test/Analysis/ctor.mm
@@ -1,7 +1,7 @@
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS -analyzer-config eagerly-assume=false %s
#include "Inputs/system-header-simulator-cxx.h"
diff --git a/test/Analysis/ctu-different-triples.cpp b/test/Analysis/ctu-different-triples.cpp
new file mode 100644
index 000000000000..dbfa82fb483d
--- /dev/null
+++ b/test/Analysis/ctu-different-triples.cpp
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/ctu-other.cpp.externalDefMap.txt %t/ctudir/externalDefMap.txt
+// RUN: %clang_analyze_cc1 -triple powerpc64-montavista-linux-gnu \
+// RUN: -analyzer-checker=core,debug.ExprInspection \
+// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN: -analyzer-config ctu-dir=%t/ctudir \
+// RUN: -Werror=ctu \
+// RUN: -verify %s
+
+// We expect an error in this file, but without a location.
+// expected-error-re@./ctu-different-triples.cpp:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}}
+
+int f(int);
+
+int main() {
+ return f(5);
+}
diff --git a/test/Analysis/ctu-main.c b/test/Analysis/ctu-main.c
new file mode 100644
index 000000000000..114d694020a1
--- /dev/null
+++ b/test/Analysis/ctu-main.c
@@ -0,0 +1,67 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir2
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -emit-pch -o %t/ctudir2/ctu-other.c.ast %S/Inputs/ctu-other.c
+// RUN: cp %S/Inputs/ctu-other.c.externalDefMap.txt %t/ctudir2/externalDefMap.txt
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -std=c89 -analyze \
+// RUN: -analyzer-checker=core,debug.ExprInspection \
+// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN: -analyzer-config ctu-dir=%t/ctudir2 \
+// RUN: -verify %s
+
+void clang_analyzer_eval(int);
+
+// Test typedef and global variable in function.
+typedef struct {
+ int a;
+ int b;
+} FooBar;
+extern FooBar fb;
+int f(int);
+void testGlobalVariable() {
+ clang_analyzer_eval(f(5) == 1); // expected-warning{{TRUE}}
+}
+
+// Test enums.
+int enumCheck(void);
+enum A { x,
+ y,
+ z };
+void testEnum() {
+ clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(enumCheck() == 42); // expected-warning{{TRUE}}
+}
+
+// Test that asm import does not fail.
+int inlineAsm();
+int testInlineAsm() {
+ return inlineAsm();
+}
+
+// Test reporting error in a macro.
+struct S;
+int g(struct S *);
+void testMacro(void) {
+ g(0); // expected-warning@Inputs/ctu-other.c:29 {{Access to field 'a' results in a dereference of a null pointer (loaded from variable 'ctx')}}
+}
+
+// The external function prototype is incomplete.
+// warning:implicit functions are prohibited by c99
+void testImplicit() {
+ int res = identImplicit(6); // external implicit functions are not inlined
+ clang_analyzer_eval(res == 6); // expected-warning{{TRUE}}
+}
+
+// Tests the import of functions that have a struct parameter
+// defined in its prototype.
+struct DataType {
+ int a;
+ int b;
+};
+int structInProto(struct DataType *d);
+void testStructDefInArgument() {
+ struct DataType d;
+ d.a = 1;
+ d.b = 0;
+ clang_analyzer_eval(structInProto(&d) == 0); // expected-warning{{TRUE}} expected-warning{{FALSE}}
+}
diff --git a/test/Analysis/ctu-main.cpp b/test/Analysis/ctu-main.cpp
index 33da84962cef..35d1f52ad044 100644
--- a/test/Analysis/ctu-main.cpp
+++ b/test/Analysis/ctu-main.cpp
@@ -1,8 +1,23 @@
-// RUN: mkdir -p %T/ctudir
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
-// RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
+// RUN: cp %S/Inputs/ctu-other.cpp.externalDefMap.txt %t/ctudir/externalDefMap.txt
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -analyzer-checker=core,debug.ExprInspection \
+// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN: -analyzer-config ctu-dir=%t/ctudir \
+// RUN: -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -analyzer-checker=core,debug.ExprInspection \
+// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN: -analyzer-config ctu-dir=%t/ctudir \
+// RUN: -analyzer-config display-ctu-progress=true 2>&1 %s | FileCheck %s
+
+// CHECK: CTU loaded AST file: {{.*}}ctu-other.cpp.ast
+// CHECK: CTU loaded AST file: {{.*}}ctu-chain.cpp.ast
#include "ctu-hdr.h"
diff --git a/test/Analysis/ctu-unknown-parts-in-triples.cpp b/test/Analysis/ctu-unknown-parts-in-triples.cpp
new file mode 100644
index 000000000000..5e643c164dd7
--- /dev/null
+++ b/test/Analysis/ctu-unknown-parts-in-triples.cpp
@@ -0,0 +1,22 @@
+// We do not expect any error when one part of the triple is unknown, but other
+// known parts are equal.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
+// RUN: cp %S/Inputs/ctu-other.cpp.externalDefMap.txt %t/ctudir/externalDefMap.txt
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu \
+// RUN: -analyzer-checker=core,debug.ExprInspection \
+// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN: -analyzer-config ctu-dir=%t/ctudir \
+// RUN: -Werror=ctu \
+// RUN: -verify %s
+
+// expected-no-diagnostics
+
+int f(int);
+
+int main() {
+ return f(5);
+}
diff --git a/test/Analysis/cxx-for-range.cpp b/test/Analysis/cxx-for-range.cpp
index d1a689b62cdb..4e5fb0ea7ff5 100644
--- a/test/Analysis/cxx-for-range.cpp
+++ b/test/Analysis/cxx-for-range.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-output=plist-multi-file -o %t.plist -verify %s
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-output=plist-multi-file -o %t.plist -verify -analyzer-config eagerly-assume=false %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/cxx-for-range.cpp.plist -
extern void work();
@@ -97,1590 +97,8 @@ void testLoopErrorInRange() {
*(volatile int *)0 = 1; // no-warning
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7c0b35987817cf3d44b88c5349bcd4f2</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testLoop</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;get&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;get&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testLoopErrorInRange&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testLoopErrorInRange&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f53792d63dffe6176babc00ee455a3e0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>get</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is equal to 2</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is equal to 2</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7bc3cb8a56be029296ec61f7ee83fc9e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testLoopOpaqueCollection</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dc7b457a64bd56c30467c1af44049756</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testLoopOpaqueCollection</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>74</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>74</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>74</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>74</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is equal to 2</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is equal to 2</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f4697ded3a92318349a3969238e05387</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testLoopOpaqueIterator</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6855b29ad2407a5af43c57f062bc4602</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testLoopOpaqueIterator</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+
+void testForRangeInit() {
+ for (int *arr[3] = {nullptr, nullptr, nullptr}; int *p : arr) // expected-warning {{extension}}
+ *p = 1; // expected-warning {{Dereference of null pointer}}
+}
diff --git a/test/Analysis/cxx-uninitialized-object-inheritance.cpp b/test/Analysis/cxx-uninitialized-object-inheritance.cpp
index 3b048b759e13..b24783af05fd 100644
--- a/test/Analysis/cxx-uninitialized-object-inheritance.cpp
+++ b/test/Analysis/cxx-uninitialized-object-inheritance.cpp
@@ -1,4 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN: -std=c++11 -verify %s
//===----------------------------------------------------------------------===//
// Non-polymorphic inheritance tests
@@ -32,7 +35,7 @@ void fNonPolymorphicInheritanceTest1() {
}
class NonPolymorphicBaseClass2 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->NonPolymorphicBaseClass2::x'}}
protected:
int y;
@@ -59,7 +62,7 @@ class NonPolymorphicBaseClass3 {
int x;
protected:
- int y; // expected-note{{uninitialized field 'this->y'}}
+ int y; // expected-note{{uninitialized field 'this->NonPolymorphicBaseClass3::y'}}
public:
NonPolymorphicBaseClass3() = default;
NonPolymorphicBaseClass3(int) : x(7) {}
@@ -137,7 +140,7 @@ void fPolymorphicInheritanceTest1() {
}
class PolymorphicRight1 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->PolymorphicRight1::x'}}
protected:
int y;
@@ -165,7 +168,7 @@ class PolymorphicBaseClass3 {
int x;
protected:
- int y; // expected-note{{uninitialized field 'this->y'}}
+ int y; // expected-note{{uninitialized field 'this->PolymorphicBaseClass3::y'}}
public:
virtual ~PolymorphicBaseClass3() = default;
PolymorphicBaseClass3() = default;
@@ -245,7 +248,7 @@ void fVirtualInheritanceTest1() {
}
class VirtualPolymorphicRight1 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->VirtualPolymorphicRight1::x'}}
protected:
int y;
@@ -273,7 +276,7 @@ class VirtualPolymorphicBaseClass3 {
int x;
protected:
- int y; // expected-note{{uninitialized field 'this->y'}}
+ int y; // expected-note{{uninitialized field 'this->VirtualPolymorphicBaseClass3::y'}}
public:
virtual ~VirtualPolymorphicBaseClass3() = default;
VirtualPolymorphicBaseClass3() = default;
@@ -355,7 +358,7 @@ struct Left2 {
Left2(int) : x(36) {}
};
struct Right2 {
- int y; // expected-note{{uninitialized field 'this->y'}}
+ int y; // expected-note{{uninitialized field 'this->Right2::y'}}
Right2() = default;
Right2(int) : y(37) {}
};
@@ -375,7 +378,7 @@ void fMultipleInheritanceTest2() {
}
struct Left3 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->Left3::x'}}
Left3() = default;
Left3(int) : x(39) {}
};
@@ -430,7 +433,7 @@ struct Left5 {
Left5(int) : x(44) {}
};
struct Right5 {
- int y; // expected-note{{uninitialized field 'this->y'}}
+ int y; // expected-note{{uninitialized field 'this->Right5::y'}}
Right5() = default;
Right5(int) : y(45) {}
};
@@ -511,7 +514,7 @@ void fNonVirtualDiamondInheritanceTest1() {
}
struct NonVirtualBase2 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->NonVirtualBase2::x'}}
NonVirtualBase2() = default;
NonVirtualBase2(int) : x(52) {}
};
@@ -539,7 +542,7 @@ void fNonVirtualDiamondInheritanceTest2() {
}
struct NonVirtualBase3 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->NonVirtualBase3::x'}}
NonVirtualBase3() = default;
NonVirtualBase3(int) : x(54) {}
};
@@ -567,8 +570,8 @@ void fNonVirtualDiamondInheritanceTest3() {
}
struct NonVirtualBase4 {
- int x; // expected-note{{uninitialized field 'this->x'}}
- // expected-note@-1{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->NonVirtualBase4::x'}}
+ // expected-note@-1{{uninitialized field 'this->NonVirtualBase4::x'}}
NonVirtualBase4() = default;
NonVirtualBase4(int) : x(56) {}
};
@@ -623,7 +626,7 @@ void fNonVirtualDiamondInheritanceTest5() {
}
struct NonVirtualBase6 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->NonVirtualBase6::x'}}
NonVirtualBase6() = default;
NonVirtualBase6(int) : x(59) {}
};
@@ -709,7 +712,7 @@ void fVirtualDiamondInheritanceTest1() {
}
struct VirtualBase2 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->VirtualBase2::x'}}
VirtualBase2() = default;
VirtualBase2(int) : x(63) {}
};
@@ -748,7 +751,7 @@ void fVirtualDiamondInheritanceTest2() {
}
struct VirtualBase3 {
- int x; // expected-note{{uninitialized field 'this->x'}}
+ int x; // expected-note{{uninitialized field 'this->VirtualBase3::x'}}
VirtualBase3() = default;
VirtualBase3(int) : x(66) {}
};
@@ -773,3 +776,58 @@ public:
void fVirtualDiamondInheritanceTest3() {
VirtualDiamondInheritanceTest3();
}
+
+//===----------------------------------------------------------------------===//
+// Dynamic type test.
+//===----------------------------------------------------------------------===//
+
+struct DynTBase1 {};
+struct DynTDerived1 : DynTBase1 {
+ int y; // expected-note{{uninitialized field 'static_cast<struct DynTDerived1 *>(this->bptr)->y'}}
+};
+
+struct DynamicTypeTest1 {
+ DynTBase1 *bptr;
+ int i = 0;
+
+ DynamicTypeTest1(DynTBase1 *bptr) : bptr(bptr) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fDynamicTypeTest1() {
+ DynTDerived1 d;
+ DynamicTypeTest1 t(&d);
+};
+
+struct DynTBase2 {
+ int x; // expected-note{{uninitialized field 'static_cast<struct DynTDerived2 *>(this->bptr)->DynTBase2::x'}}
+};
+struct DynTDerived2 : DynTBase2 {
+ int y; // expected-note{{uninitialized field 'static_cast<struct DynTDerived2 *>(this->bptr)->y'}}
+};
+
+struct DynamicTypeTest2 {
+ DynTBase2 *bptr;
+ int i = 0;
+
+ DynamicTypeTest2(DynTBase2 *bptr) : bptr(bptr) {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fDynamicTypeTest2() {
+ DynTDerived2 d;
+ DynamicTypeTest2 t(&d);
+}
+
+struct SymbolicSuperRegionBase {
+ SymbolicSuperRegionBase() {}
+};
+
+struct SymbolicSuperRegionDerived : SymbolicSuperRegionBase {
+ SymbolicSuperRegionBase *bptr; // no-crash
+ SymbolicSuperRegionDerived(SymbolicSuperRegionBase *bptr) : bptr(bptr) {}
+};
+
+SymbolicSuperRegionDerived *getSymbolicRegion();
+
+void fSymbolicSuperRegionTest() {
+ SymbolicSuperRegionDerived test(getSymbolicRegion());
+}
diff --git a/test/Analysis/cxx-uninitialized-object-no-dereference.cpp b/test/Analysis/cxx-uninitialized-object-no-dereference.cpp
new file mode 100644
index 000000000000..0309c28b3e13
--- /dev/null
+++ b/test/Analysis/cxx-uninitialized-object-no-dereference.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -std=c++11 -DPEDANTIC -verify %s
+
+class UninitPointerTest {
+ int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+public:
+ UninitPointerTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fUninitPointerTest() {
+ UninitPointerTest();
+}
+
+class UninitPointeeTest {
+ int *ptr; // no-note
+ int dontGetFilteredByNonPedanticMode = 0;
+
+public:
+ UninitPointeeTest(int *ptr) : ptr(ptr) {} // no-warning
+};
+
+void fUninitPointeeTest() {
+ int a;
+ UninitPointeeTest t(&a);
+}
diff --git a/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp b/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp
index a49507a1aa5d..2a5fcbc92390 100644
--- a/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp
+++ b/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp
@@ -1,4 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN: -std=c++11 -verify %s
class NotesAsWarningsTest {
int a;
diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
index 1507098c5e75..edc594a0bf1b 100644
--- a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
+++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
@@ -1,6 +1,11 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN: -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN: -std=c++11 -verify %s
//===----------------------------------------------------------------------===//
// Concrete location tests.
@@ -17,6 +22,24 @@ void fConcreteIntLocTest() {
}
//===----------------------------------------------------------------------===//
+// nonloc::LocAsInteger tests.
+//===----------------------------------------------------------------------===//
+
+using intptr_t = unsigned long long;
+
+struct LocAsIntegerTest {
+ intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast<char *>(this->ptr)'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast<intptr_t>(ptr)) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fLocAsIntegerTest() {
+ char c;
+ LocAsIntegerTest t(&c);
+}
+
+//===----------------------------------------------------------------------===//
// Null pointer tests.
//===----------------------------------------------------------------------===//
@@ -41,6 +64,50 @@ void fNullPtrTest() {
}
//===----------------------------------------------------------------------===//
+// Alloca tests.
+//===----------------------------------------------------------------------===//
+
+struct UntypedAllocaTest {
+ void *allocaPtr;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ UntypedAllocaTest() : allocaPtr(__builtin_alloca(sizeof(int))) {
+ // All good!
+ }
+};
+
+void fUntypedAllocaTest() {
+ UntypedAllocaTest();
+}
+
+struct TypedAllocaTest1 {
+ int *allocaPtr; // expected-note{{uninitialized pointee 'this->allocaPtr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ TypedAllocaTest1() // expected-warning{{1 uninitialized field}}
+ : allocaPtr(static_cast<int *>(__builtin_alloca(sizeof(int)))) {}
+};
+
+void fTypedAllocaTest1() {
+ TypedAllocaTest1();
+}
+
+struct TypedAllocaTest2 {
+ int *allocaPtr;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ TypedAllocaTest2()
+ : allocaPtr(static_cast<int *>(__builtin_alloca(sizeof(int)))) {
+ *allocaPtr = 55555;
+ // All good!
+ }
+};
+
+void fTypedAllocaTest2() {
+ TypedAllocaTest2();
+}
+
+//===----------------------------------------------------------------------===//
// Heap pointer tests.
//===----------------------------------------------------------------------===//
@@ -189,13 +256,26 @@ void fCharPointerTest() {
CharPointerTest();
}
-struct CyclicPointerTest {
- int *ptr;
- CyclicPointerTest() : ptr(reinterpret_cast<int*>(&ptr)) {}
+struct CyclicPointerTest1 {
+ int *ptr; // expected-note{{object references itself 'this->ptr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ CyclicPointerTest1() : ptr(reinterpret_cast<int *>(&ptr)) {} // expected-warning{{1 uninitialized field}}
};
-void fCyclicPointerTest() {
- CyclicPointerTest();
+void fCyclicPointerTest1() {
+ CyclicPointerTest1();
+}
+
+struct CyclicPointerTest2 {
+ int **pptr; // expected-note{{object references itself 'this->pptr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ CyclicPointerTest2() : pptr(reinterpret_cast<int **>(&pptr)) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fCyclicPointerTest2() {
+ CyclicPointerTest2();
}
//===----------------------------------------------------------------------===//
@@ -277,16 +357,66 @@ void fVoidPointerLRefTest() {
}
struct CyclicVoidPointerTest {
- void *vptr; // no-crash
-
- CyclicVoidPointerTest() : vptr(&vptr) {}
+ void *vptr; // expected-note{{object references itself 'this->vptr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+ CyclicVoidPointerTest() : vptr(&vptr) {} // expected-warning{{1 uninitialized field}}
};
void fCyclicVoidPointerTest() {
CyclicVoidPointerTest();
}
+struct IntDynTypedVoidPointerTest1 {
+ void *vptr; // expected-note{{uninitialized pointee 'static_cast<int *>(this->vptr)'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IntDynTypedVoidPointerTest1(void *vptr) : vptr(vptr) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fIntDynTypedVoidPointerTest1() {
+ int a;
+ IntDynTypedVoidPointerTest1 tmp(&a);
+}
+
+struct RecordDynTypedVoidPointerTest {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
+ int y; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
+ };
+
+ void *vptr;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ RecordDynTypedVoidPointerTest(void *vptr) : vptr(vptr) {} // expected-warning{{2 uninitialized fields}}
+};
+
+void fRecordDynTypedVoidPointerTest() {
+ RecordDynTypedVoidPointerTest::RecordType a;
+ RecordDynTypedVoidPointerTest tmp(&a);
+}
+
+struct NestedNonVoidDynTypedVoidPointerTest {
+ struct RecordType {
+ int x; // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
+ int y; // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
+ void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}}
+ };
+
+ void *vptr;
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ NestedNonVoidDynTypedVoidPointerTest(void *vptr, void *c) : vptr(vptr) {
+ static_cast<RecordType *>(vptr)->vptr = c; // expected-warning{{3 uninitialized fields}}
+ }
+};
+
+void fNestedNonVoidDynTypedVoidPointerTest() {
+ NestedNonVoidDynTypedVoidPointerTest::RecordType a;
+ char c;
+ NestedNonVoidDynTypedVoidPointerTest tmp(&a, &c);
+}
+
//===----------------------------------------------------------------------===//
// Multipointer tests.
//===----------------------------------------------------------------------===//
@@ -404,6 +534,39 @@ void fMultiPointerTest3() {
}
//===----------------------------------------------------------------------===//
+// Incomplete pointee tests.
+//===----------------------------------------------------------------------===//
+
+class IncompleteType;
+
+struct IncompletePointeeTypeTest {
+ IncompleteType *pImpl; //no-crash
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IncompletePointeeTypeTest(IncompleteType *A) : pImpl(A) {}
+};
+
+void fIncompletePointeeTypeTest(void *ptr) {
+ IncompletePointeeTypeTest(reinterpret_cast<IncompleteType *>(ptr));
+}
+
+//===----------------------------------------------------------------------===//
+// Function pointer tests.
+//===----------------------------------------------------------------------===//
+
+struct FunctionPointerWithDifferentDynTypeTest {
+ using Func1 = void *(*)();
+ using Func2 = int *(*)();
+
+ Func1 f; // no-crash
+ FunctionPointerWithDifferentDynTypeTest(Func2 f) : f((Func1)f) {}
+};
+
+// Note that there isn't a function calling the constructor of
+// FunctionPointerWithDifferentDynTypeTest, because a crash could only be
+// reproduced without it.
+
+//===----------------------------------------------------------------------===//
// Member pointer tests.
//===----------------------------------------------------------------------===//
@@ -578,6 +741,15 @@ void fCyclicList() {
CyclicList(&n1, int());
}
+struct RingListTest {
+ RingListTest *next; // no-crash
+ RingListTest() : next(this) {}
+};
+
+void fRingListTest() {
+ RingListTest();
+}
+
//===----------------------------------------------------------------------===//
// Tests for classes containing references.
//===----------------------------------------------------------------------===//
@@ -693,3 +865,44 @@ void fReferenceTest5() {
ReferenceTest4::RecordType c, d{37, 38};
ReferenceTest4(d, c);
}
+
+//===----------------------------------------------------------------------===//
+// Tests for objects containing multiple references to the same object.
+//===----------------------------------------------------------------------===//
+
+struct IntMultipleReferenceToSameObjectTest {
+ int *iptr; // expected-note{{uninitialized pointee 'this->iptr'}}
+ int &iref; // no-note, pointee of this->iref was already reported
+
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IntMultipleReferenceToSameObjectTest(int *i) : iptr(i), iref(*i) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fIntMultipleReferenceToSameObjectTest() {
+ int a;
+ IntMultipleReferenceToSameObjectTest Test(&a);
+}
+
+struct IntReferenceWrapper1 {
+ int &a; // expected-note{{uninitialized pointee 'this->a'}}
+
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IntReferenceWrapper1(int &a) : a(a) {} // expected-warning{{1 uninitialized field}}
+};
+
+struct IntReferenceWrapper2 {
+ int &a; // no-note, pointee of this->a was already reported
+
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ IntReferenceWrapper2(int &a) : a(a) {} // no-warning
+};
+
+void fMultipleObjectsReferencingTheSameObjectTest() {
+ int a;
+
+ IntReferenceWrapper1 T1(a);
+ IntReferenceWrapper2 T2(a);
+}
diff --git a/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp b/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp
new file mode 100644
index 000000000000..dc52afd90195
--- /dev/null
+++ b/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp
@@ -0,0 +1,136 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind" \
+// RUN: -std=c++11 -verify %s
+
+// expected-no-diagnostics
+
+// Both type and name contains "kind".
+struct UnionLikeStruct1 {
+ enum Kind {
+ volume,
+ area
+ } kind;
+
+ int Volume;
+ int Area;
+
+ UnionLikeStruct1(Kind kind, int Val) : kind(kind) {
+ switch (kind) {
+ case volume:
+ Volume = Val;
+ break;
+ case area:
+ Area = Val;
+ break;
+ }
+ }
+};
+
+void fUnionLikeStruct1() {
+ UnionLikeStruct1 t(UnionLikeStruct1::volume, 10);
+}
+
+// Only name contains "kind".
+struct UnionLikeStruct2 {
+ enum Type {
+ volume,
+ area
+ } kind;
+
+ int Volume;
+ int Area;
+
+ UnionLikeStruct2(Type kind, int Val) : kind(kind) {
+ switch (kind) {
+ case volume:
+ Volume = Val;
+ break;
+ case area:
+ Area = Val;
+ break;
+ }
+ }
+};
+
+void fUnionLikeStruct2() {
+ UnionLikeStruct2 t(UnionLikeStruct2::volume, 10);
+}
+
+// Only type contains "kind".
+struct UnionLikeStruct3 {
+ enum Kind {
+ volume,
+ area
+ } type;
+
+ int Volume;
+ int Area;
+
+ UnionLikeStruct3(Kind type, int Val) : type(type) {
+ switch (type) {
+ case volume:
+ Volume = Val;
+ break;
+ case area:
+ Area = Val;
+ break;
+ }
+ }
+};
+
+void fUnionLikeStruct3() {
+ UnionLikeStruct3 t(UnionLikeStruct3::volume, 10);
+}
+
+// Only type contains "tag".
+struct UnionLikeStruct4 {
+ enum Tag {
+ volume,
+ area
+ } type;
+
+ int Volume;
+ int Area;
+
+ UnionLikeStruct4(Tag type, int Val) : type(type) {
+ switch (type) {
+ case volume:
+ Volume = Val;
+ break;
+ case area:
+ Area = Val;
+ break;
+ }
+ }
+};
+
+void fUnionLikeStruct4() {
+ UnionLikeStruct4 t(UnionLikeStruct4::volume, 10);
+}
+
+// Both name and type name contains but does not equal to tag/kind.
+struct UnionLikeStruct5 {
+ enum WhateverTagBlahBlah {
+ volume,
+ area
+ } FunnyKindName;
+
+ int Volume;
+ int Area;
+
+ UnionLikeStruct5(WhateverTagBlahBlah type, int Val) : FunnyKindName(type) {
+ switch (FunnyKindName) {
+ case volume:
+ Volume = Val;
+ break;
+ case area:
+ Area = Val;
+ break;
+ }
+ }
+};
+
+void fUnionLikeStruct5() {
+ UnionLikeStruct5 t(UnionLikeStruct5::volume, 10);
+}
diff --git a/test/Analysis/cxx-uninitialized-object.cpp b/test/Analysis/cxx-uninitialized-object.cpp
index 39d4a7f80183..07006bea4781 100644
--- a/test/Analysis/cxx-uninitialized-object.cpp
+++ b/test/Analysis/cxx-uninitialized-object.cpp
@@ -1,6 +1,11 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN: -std=c++14 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN: -std=c++14 -verify %s
//===----------------------------------------------------------------------===//
// Default constructor test.
@@ -776,7 +781,7 @@ struct LambdaTest2 {
void fLambdaTest2() {
int b;
- auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized field 'this->functor.b'}}
+ auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized pointee 'this->functor./*captured variable*/b'}}
LambdaTest2<decltype(equals)>(equals, int());
}
#else
@@ -798,8 +803,8 @@ void fLambdaTest2() {
namespace LT3Detail {
struct RecordType {
- int x; // expected-note{{uninitialized field 'this->functor.rec1.x'}}
- int y; // expected-note{{uninitialized field 'this->functor.rec1.y'}}
+ int x; // expected-note{{uninitialized field 'this->functor./*captured variable*/rec1.x'}}
+ int y; // expected-note{{uninitialized field 'this->functor./*captured variable*/rec1.y'}}
};
} // namespace LT3Detail
@@ -852,8 +857,8 @@ struct MultipleLambdaCapturesTest1 {
void fMultipleLambdaCapturesTest1() {
int b1, b2 = 3, b3;
- auto equals = [&b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized field 'this->functor.b1'}}
- // expected-note@-1{{uninitialized field 'this->functor.b3'}}
+ auto equals = [&b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized pointee 'this->functor./*captured variable*/b1'}}
+ // expected-note@-1{{uninitialized pointee 'this->functor./*captured variable*/b3'}}
MultipleLambdaCapturesTest1<decltype(equals)>(equals, int());
}
@@ -867,10 +872,35 @@ struct MultipleLambdaCapturesTest2 {
void fMultipleLambdaCapturesTest2() {
int b1, b2 = 3, b3;
- auto equals = [b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized field 'this->functor.b3'}}
+ auto equals = [b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized pointee 'this->functor./*captured variable*/b3'}}
MultipleLambdaCapturesTest2<decltype(equals)>(equals, int());
}
+struct LambdaWrapper {
+ void *func; // no-crash
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ LambdaWrapper(void *ptr) : func(ptr) {} // expected-warning{{1 uninitialized field}}
+};
+
+struct ThisCapturingLambdaFactory {
+ int a; // expected-note{{uninitialized field 'static_cast<decltype(a.ret()) *>(this->func)->/*'this' capture*/->a'}}
+
+ auto ret() {
+ return [this] { (void)this; };
+ }
+};
+
+void fLambdaFieldWithInvalidThisCapture() {
+ void *ptr;
+ {
+ ThisCapturingLambdaFactory a;
+ decltype(a.ret()) lambda = a.ret();
+ ptr = &lambda;
+ }
+ LambdaWrapper t(ptr);
+}
+
//===----------------------------------------------------------------------===//
// System header tests.
//===----------------------------------------------------------------------===//
@@ -1035,13 +1065,12 @@ void assert(int b) {
// While a singleton would make more sense as a static variable, that would zero
// initialize all of its fields, hence the not too practical implementation.
struct Singleton {
- // TODO: we'd expect the note: {{uninitialized field 'this->i'}}
- int i; // no-note
+ int i; // expected-note{{uninitialized field 'this->i'}}
+ int dontGetFilteredByNonPedanticMode = 0;
Singleton() {
assert(!isInstantiated);
- // TODO: we'd expect the warning: {{1 uninitialized field}}
- isInstantiated = true; // no-warning
+ isInstantiated = true; // expected-warning{{1 uninitialized field}}
}
~Singleton() {
diff --git a/test/Analysis/debug-CallGraph.c b/test/Analysis/debug-CallGraph.cpp
index 9f3865b35a4e..1d6844fad94f 100644
--- a/test/Analysis/debug-CallGraph.c
+++ b/test/Analysis/debug-CallGraph.cpp
@@ -51,8 +51,28 @@ void test_single_call() {
do_nothing();
}
+namespace SomeNS {
+template<typename T>
+void templ(T t) {
+ ccc();
+}
+
+template<>
+void templ<double>(double t) {
+ eee();
+}
+
+void templUser() {
+ templ(5);
+ templ(5.5);
+}
+}
+
// CHECK:--- Call graph Dump ---
-// CHECK-NEXT: {{Function: < root > calls: get5 add test_add mmm foo aaa < > bbb ddd ccc eee fff do_nothing test_single_call $}}
+// CHECK-NEXT: {{Function: < root > calls: get5 add test_add mmm foo aaa < > bbb ddd ccc eee fff do_nothing test_single_call SomeNS::templ SomeNS::templ SomeNS::templUser $}}
+// CHECK-NEXT: {{Function: SomeNS::templUser calls: SomeNS::templ SomeNS::templ $}}
+// CHECK-NEXT: {{Function: SomeNS::templ calls: eee $}}
+// CHECK-NEXT: {{Function: SomeNS::templ calls: ccc $}}
// CHECK-NEXT: {{Function: test_single_call calls: do_nothing $}}
// CHECK-NEXT: {{Function: do_nothing calls: $}}
// CHECK-NEXT: {{Function: fff calls: eee $}}
diff --git a/test/Analysis/diagnostics/Inputs/expected-plists/deref-track-symbolic-region.c.plist b/test/Analysis/diagnostics/Inputs/expected-plists/deref-track-symbolic-region.c.plist
new file mode 100644
index 000000000000..35b14fba4c89
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-plists/deref-track-symbolic-region.c.plist
@@ -0,0 +1,657 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value assigned to &apos;syz.x&apos;</string>
+ <key>message</key>
+ <string>Value assigned to &apos;syz.x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>17</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5cafa075eb4d5b0bf1f228608a3ec87e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>14</integer>
+ <integer>16</integer>
+ <integer>17</integer>
+ <integer>23</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value assigned to &apos;syz.x&apos;</string>
+ <key>message</key>
+ <string>Value assigned to &apos;syz.x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a213f858dacf7993492e6b32080aaa64</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testTrackConstraintBRVisitorIsTrackingTurnedOn</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>27</integer>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>31</integer>
+ <integer>32</integer>
+ <integer>37</integer>
+ <integer>38</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/diagnostics/deref-track-symbolic-region.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/diagnostics/Inputs/expected-plists/plist-diagnostics-include-check.cpp.plist b/test/Analysis/diagnostics/Inputs/expected-plists/plist-diagnostics-include-check.cpp.plist
new file mode 100644
index 000000000000..802534d0c165
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-plists/plist-diagnostics-include-check.cpp.plist
@@ -0,0 +1,147 @@
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>2</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;PlistCheckMacro::run&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;PlistCheckMacro::run&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;foo&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;foo&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>REACHABLE</string>
+ <key>message</key>
+ <string>REACHABLE</string>
+ </dict>
+ </array>
+ <key>description</key><string>REACHABLE</string>
+ <key>category</key><string>debug</string>
+ <key>type</key><string>Checking analyzer assumptions</string>
+ <key>check_name</key><string>debug.ExprInspection</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>93b4eab05b21c892c8e31723e5af3f59</string>
+ <key>issue_context_kind</key><string>C++ method</string>
+ <key>issue_context</key><string>run</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>7</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>5</integer>
+ <integer>6</integer>
+ <integer>7</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp</string>
+ <string>/clang/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.h</string>
+ <string>/clang/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.def</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist b/test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist
new file mode 100644
index 000000000000..86c203245d4e
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist
@@ -0,0 +1,212 @@
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;foo&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;foo&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>1</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;bar&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;bar&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>1</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>1</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2058c95994cab381890af28e7bf354bf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>foo</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>2</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>HTMLDiagnostics_files</key>
+ <array>
+ <string>report-288847.html</string>
+ </array>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>6</integer>
+ <integer>7</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>1</integer>
+ <integer>2</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/diagnostics/plist-multi-file.c</string>
+ <string>/clang/test/Analysis/diagnostics/plist-multi-file.h</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/diagnostics/Inputs/expected-plists/report-issues-within-main-file.cpp.plist b/test/Analysis/diagnostics/Inputs/expected-plists/report-issues-within-main-file.cpp.plist
new file mode 100644
index 000000000000..e0959e719a74
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-plists/report-issues-within-main-file.cpp.plist
@@ -0,0 +1,1835 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>49</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header2&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;callInMacro&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;callInMacro&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;h2&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;h2&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>81ef0773d42c0309a03a9a11048f497e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>cause_div_by_zero_in_header2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>48</integer>
+ <integer>49</integer>
+ <integer>50</integer>
+ <integer>51</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>21</integer>
+ <integer>22</integer>
+ <integer>23</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;callInMacro3&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;callInMacro3&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;callCallInMacro3&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;callCallInMacro3&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>55</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header3&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header3&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;callInMacro3&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;callInMacro3&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>29</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>&apos;h3&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;h3&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a4f425d2b2715e682b08a754fc88d2c8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>cause_div_by_zero_in_header3</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>55</integer>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>62</integer>
+ <integer>63</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>29</integer>
+ <integer>30</integer>
+ <integer>31</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>69</integer>
+ <key>col</key><integer>51</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header4&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header4&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;callInMacroArg&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;callInMacroArg&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>37</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;h4&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;h4&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>38</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>35f2ebe7ff6b3b34233a5465a6eaf661</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>cause_div_by_zero_in_header4</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>66</integer>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>69</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>37</integer>
+ <integer>38</integer>
+ <integer>39</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Memory is allocated</string>
+ <key>message</key>
+ <string>Memory is allocated</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>key_event</key><true/>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;~auto_ptr&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;~auto_ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;mainPlusHeader&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;mainPlusHeader&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ <key>message</key>
+ <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
+ </dict>
+ </array>
+ <key>description</key><string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos; (within a call to &apos;~auto_ptr&apos;)</string>
+ <key>category</key><string>Memory error</string>
+ <key>type</key><string>Bad deallocator</string>
+ <key>check_name</key><string>unix.MismatchedDeallocator</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f689fbd54138491e228f0f89bb02bfb2</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>mainPlusHeader</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>5</integer>
+ <integer>6</integer>
+ <integer>7</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>6</integer>
+ <integer>7</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>16</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>18</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;auxInMain&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;auxInMain&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;mainPlusMainPlusHeader&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;mainPlusMainPlusHeader&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>key_event</key><true/>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;cause_div_by_zero_in_header&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;auxInMain&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;auxInMain&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>&apos;h&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;h&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>1</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero (within a call to &apos;cause_div_by_zero_in_header&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>dceba279187ce4f6514f4a4c43a51063</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>auxInMain</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ <integer>15</integer>
+ <integer>16</integer>
+ <integer>17</integer>
+ <integer>18</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;causeDivByZeroInMain&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;causeDivByZeroInMain&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;mainPlusMain&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;mainPlusMain&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;m&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;m&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d0d513aa4710781c2b56c44226354403</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>causeDivByZeroInMain</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>22</integer>
+ <integer>23</integer>
+ <integer>24</integer>
+ <integer>27</integer>
+ <integer>28</integer>
+ <integer>29</integer>
+ <integer>30</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;causeDivByZeroInMain2&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;causeDivByZeroInMain2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;mainPlustHeaderCallAndReturnPlusMain&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;mainPlustHeaderCallAndReturnPlusMain&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;m2&apos; initialized to 0</string>
+ <key>message</key>
+ <string>&apos;m2&apos; initialized to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>577ddcf4482f18dec120e21890ed234a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>causeDivByZeroInMain2</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>34</integer>
+ <integer>35</integer>
+ <integer>36</integer>
+ <integer>40</integer>
+ <integer>41</integer>
+ <integer>42</integer>
+ <integer>43</integer>
+ <integer>44</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>16</integer>
+ <integer>17</integer>
+ <integer>18</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/diagnostics/report-issues-within-main-file.cpp</string>
+ <string>/clang/test/Analysis/diagnostics/Inputs/include/report-issues-within-main-file.h</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-caller.c.plist b/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-caller.c.plist
new file mode 100644
index 000000000000..867807be846a
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-caller.c.plist
@@ -0,0 +1,142 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Undefined or garbage value returned to caller</string>
+ <key>message</key>
+ <string>Undefined or garbage value returned to caller</string>
+ </dict>
+ </array>
+ <key>description</key><string>Undefined or garbage value returned to caller</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Garbage return value</string>
+ <key>check_name</key><string>core.uninitialized.UndefReturn</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1ef750c5562c09a467ea54ea4b4de771</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test_calling_unimportant_callee</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>8</integer>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>11</integer>
+ </array>
+ <key>1</key>
+ <array>
+ <integer>2</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/diagnostics/undef-value-caller.c</string>
+ <string>/clang/test/Analysis/diagnostics/undef-value-callee.h</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.c.plist b/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.c.plist
new file mode 100644
index 000000000000..5d351624f183
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.c.plist
@@ -0,0 +1,1344 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;xx&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;xx&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>20</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;foo&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;foo&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;use&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;use&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;c&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;c&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning without writing to &apos;*x&apos;</string>
+ <key>message</key>
+ <string>Returning without writing to &apos;*x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>15</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;foo&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;foo&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>22</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>25</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The left operand of &apos;+&apos; is a garbage value</string>
+ <key>message</key>
+ <string>The left operand of &apos;+&apos; is a garbage value</string>
+ </dict>
+ </array>
+ <key>description</key><string>The left operand of &apos;+&apos; is a garbage value</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Result of operation is garbage or undefined</string>
+ <key>check_name</key><string>core.UndefinedBinaryOperatorResult</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ae5e3bd03d6d97614947942dae18e1da</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>use</string>
+ <key>issue_hash_function_offset</key><string>7</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>26</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>5</integer>
+ <integer>6</integer>
+ <integer>7</integer>
+ <integer>11</integer>
+ <integer>12</integer>
+ <integer>15</integer>
+ <integer>19</integer>
+ <integer>20</integer>
+ <integer>21</integer>
+ <integer>22</integer>
+ <integer>25</integer>
+ <integer>26</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;initArray&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;initArray&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testPassingParentRegionArray&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testPassingParentRegionArray&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>30</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is &lt;= 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is &lt;= 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;initArray&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;initArray&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>The right operand of &apos;*&apos; is a garbage value</string>
+ <key>message</key>
+ <string>The right operand of &apos;*&apos; is a garbage value</string>
+ </dict>
+ </array>
+ <key>description</key><string>The right operand of &apos;*&apos; is a garbage value</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Result of operation is garbage or undefined</string>
+ <key>check_name</key><string>core.UndefinedBinaryOperatorResult</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>96cf3258da3df14d13cd5c2236c9cb27</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testPassingParentRegionArray</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>42</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>30</integer>
+ <integer>31</integer>
+ <integer>33</integer>
+ <integer>38</integer>
+ <integer>39</integer>
+ <integer>40</integer>
+ <integer>42</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>58</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;st.f1&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;st.f1&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;initStruct&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;initStruct&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testPassingParentRegionStruct&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testPassingParentRegionStruct&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>50</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;x&apos; is &lt;= 0</string>
+ <key>message</key>
+ <string>Assuming &apos;x&apos; is &lt;= 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
+ <key>message</key>
+ <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;initStruct&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;initStruct&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;f1&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;f1&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;f1&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>299055864402de225b0ab4f2ecd8e76c</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testPassingParentRegionStruct</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>50</integer>
+ <integer>51</integer>
+ <integer>54</integer>
+ <integer>57</integer>
+ <integer>58</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ <integer>62</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/diagnostics/undef-value-param.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.m.plist b/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.m.plist
new file mode 100644
index 000000000000..bc88cf7c546f
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-plists/undef-value-param.m.plist
@@ -0,0 +1,1027 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>35</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;CreateRef&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;CreateRef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>53</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>54</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;err&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;err&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>59</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>nil object reference stored to &apos;ref&apos;</string>
+ <key>message</key>
+ <string>nil object reference stored to &apos;ref&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>nil object reference stored to &apos;storeRef&apos;</string>
+ <key>message</key>
+ <string>nil object reference stored to &apos;storeRef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;CreateRef&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;CreateRef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>36</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer argument in call to CFRelease</string>
+ <key>message</key>
+ <string>Null pointer argument in call to CFRelease</string>
+ </dict>
+ </array>
+ <key>description</key><string>Null pointer argument in call to CFRelease</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>null passed to CF memory management function</string>
+ <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>102c9a15c089fdc618a4c209bd5560bc</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>34</integer>
+ <integer>35</integer>
+ <integer>36</integer>
+ <integer>39</integer>
+ <integer>53</integer>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>56</integer>
+ <integer>59</integer>
+ <integer>60</integer>
+ <integer>62</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;storeRef&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;storeRef&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;CreateRefUndef&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;CreateRefUndef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test2&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>66</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;err&apos; is not equal to 0</string>
+ <key>message</key>
+ <string>Assuming &apos;err&apos; is not equal to 0</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>71</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning without writing to &apos;*storeRef&apos;</string>
+ <key>message</key>
+ <string>Returning without writing to &apos;*storeRef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>32</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;CreateRefUndef&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;CreateRefUndef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>45</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>1st function call argument is an uninitialized value</string>
+ <key>message</key>
+ <string>1st function call argument is an uninitialized value</string>
+ </dict>
+ </array>
+ <key>description</key><string>1st function call argument is an uninitialized value</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Uninitialized argument value</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>fe2bb14813e15196c0180196fc1cce4c</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>test2</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>48</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>43</integer>
+ <integer>44</integer>
+ <integer>45</integer>
+ <integer>48</integer>
+ <integer>65</integer>
+ <integer>66</integer>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>71</integer>
+ <integer>72</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/diagnostics/undef-value-param.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif b/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif
new file mode 100644
index 000000000000..70efae4574d6
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif
@@ -0,0 +1,114 @@
+{
+ "$schema": "http://json.schemastore.org/sarif-2.0.0-csd.2.beta.2018-11-28",
+ "runs": [
+ {
+ "files": [
+ {
+ "fileLocation": {
+ "uri": "file:sarif-diagnostics-taint-test.c"
+ },
+ "length": 415,
+ "mimeType": "text/plain",
+ "roles": [
+ "resultFile"
+ ]
+ }
+ ],
+ "resources": {
+ "rules": [
+ {
+ "fullDescription": {
+ "text": "Mark tainted symbols as such."
+ },
+ "id": "debug.TaintTest",
+ "name": {
+ "text": "debug.TaintTest"
+ }
+ }
+ ]
+ },
+ "results": [
+ {
+ "codeFlows": [
+ {
+ "threadFlows": [
+ {
+ "locations": [
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "Calling 'f'"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-diagnostics-taint-test.c"
+ },
+ "region": {
+ "endColumn": 5,
+ "endLine": 13,
+ "startColumn": 3,
+ "startLine": 13
+ }
+ }
+ }
+ },
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "tainted"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-diagnostics-taint-test.c"
+ },
+ "region": {
+ "endColumn": 17,
+ "endLine": 9,
+ "startColumn": 11,
+ "startLine": 9
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "locations": [
+ {
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-diagnostics-taint-test.c"
+ },
+ "region": {
+ "endColumn": 17,
+ "endLine": 9,
+ "startColumn": 11,
+ "startLine": 9
+ }
+ }
+ }
+ ],
+ "message": {
+ "text": "tainted"
+ },
+ "ruleId": "debug.TaintTest",
+ "ruleIndex": 0
+ }
+ ],
+ "tool": {
+ "fullName": "clang static analyzer",
+ "language": "en-US",
+ "name": "clang",
+ "version": "clang version 8.0.0"
+ }
+ }
+ ],
+ "version": "2.0.0-csd.2.beta.2018-11-28"
+}
diff --git a/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif b/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif
new file mode 100644
index 000000000000..8bd8c0adf248
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif
@@ -0,0 +1,320 @@
+{
+ "$schema": "http://json.schemastore.org/sarif-2.0.0-csd.2.beta.2018-11-28",
+ "runs": [
+ {
+ "files": [
+ {
+ "fileLocation": {
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "length": 667,
+ "mimeType": "text/plain",
+ "roles": [
+ "resultFile"
+ ]
+ }
+ ],
+ "resources": {
+ "rules": [
+ {
+ "fullDescription": {
+ "text": "Mark tainted symbols as such."
+ },
+ "id": "debug.TaintTest",
+ "name": {
+ "text": "debug.TaintTest"
+ }
+ },
+ {
+ "fullDescription": {
+ "text": "Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)"
+ },
+ "helpUri": "https://clang-analyzer.llvm.org/available_checks.html#core.CallAndMessage",
+ "id": "core.CallAndMessage",
+ "name": {
+ "text": "core.CallAndMessage"
+ }
+ },
+ {
+ "fullDescription": {
+ "text": "Check for division by zero"
+ },
+ "helpUri": "https://clang-analyzer.llvm.org/available_checks.html#core.DivideZero",
+ "id": "core.DivideZero",
+ "name": {
+ "text": "core.DivideZero"
+ }
+ }
+ ]
+ },
+ "results": [
+ {
+ "codeFlows": [
+ {
+ "threadFlows": [
+ {
+ "locations": [
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "Calling 'f'"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 5,
+ "endLine": 24,
+ "startColumn": 3,
+ "startLine": 24
+ }
+ }
+ }
+ },
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "tainted"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 17,
+ "endLine": 9,
+ "startColumn": 11,
+ "startLine": 9
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "locations": [
+ {
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 17,
+ "endLine": 9,
+ "startColumn": 11,
+ "startLine": 9
+ }
+ }
+ }
+ ],
+ "message": {
+ "text": "tainted"
+ },
+ "ruleId": "debug.TaintTest",
+ "ruleIndex": 0
+ },
+ {
+ "codeFlows": [
+ {
+ "threadFlows": [
+ {
+ "locations": [
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "Calling 'g'"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 5,
+ "endLine": 25,
+ "startColumn": 3,
+ "startLine": 25
+ }
+ }
+ }
+ },
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "'fp' declared without an initial value"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 10,
+ "endLine": 13,
+ "startColumn": 3,
+ "startLine": 13
+ }
+ }
+ }
+ },
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "Called function pointer is an uninitialized pointer value"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 8,
+ "endLine": 14,
+ "startColumn": 3,
+ "startLine": 14
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "locations": [
+ {
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 8,
+ "endLine": 14,
+ "startColumn": 3,
+ "startLine": 14
+ }
+ }
+ }
+ ],
+ "message": {
+ "text": "Called function pointer is an uninitialized pointer value"
+ },
+ "ruleId": "core.CallAndMessage",
+ "ruleIndex": 1
+ },
+ {
+ "codeFlows": [
+ {
+ "threadFlows": [
+ {
+ "locations": [
+ {
+ "importance": "important",
+ "location": {
+ "message": {
+ "text": "Assuming 'i' is equal to 0"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 12,
+ "endLine": 18,
+ "startColumn": 7,
+ "startLine": 18
+ }
+ }
+ }
+ },
+ {
+ "importance": "unimportant",
+ "location": {
+ "message": {
+ "text": "Taking true branch"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 3,
+ "endLine": 18,
+ "startColumn": 3,
+ "startLine": 18
+ }
+ }
+ }
+ },
+ {
+ "importance": "essential",
+ "location": {
+ "message": {
+ "text": "Division by zero"
+ },
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 14,
+ "endLine": 19,
+ "startColumn": 14,
+ "startLine": 19
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "locations": [
+ {
+ "physicalLocation": {
+ "fileLocation": {
+ "fileIndex": 0,
+ "uri": "file:sarif-multi-diagnostic-test.c"
+ },
+ "region": {
+ "endColumn": 14,
+ "endLine": 19,
+ "startColumn": 14,
+ "startLine": 19
+ }
+ }
+ }
+ ],
+ "message": {
+ "text": "Division by zero"
+ },
+ "ruleId": "core.DivideZero",
+ "ruleIndex": 2
+ }
+ ],
+ "tool": {
+ "fullName": "clang static analyzer",
+ "language": "en-US",
+ "name": "clang",
+ "version": "clang version 8.0.0 (trunk 345822) (llvm/trunk 345824)"
+ }
+ }
+ ],
+ "version": "2.0.0-csd.2.beta.2018-11-28"
+}
diff --git a/test/Analysis/diagnostics/deref-track-symbolic-region.c b/test/Analysis/diagnostics/deref-track-symbolic-region.c
index 48c659f2b8e6..63d0971b85d6 100644
--- a/test/Analysis/diagnostics/deref-track-symbolic-region.c
+++ b/test/Analysis/diagnostics/deref-track-symbolic-region.c
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/deref-track-symbolic-region.c.plist -
struct S {
int *x;
@@ -39,623 +39,3 @@ void testTrackConstraintBRVisitorIsTrackingTurnedOn(struct S syz, int *pp) {
// expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;syz.x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;syz.x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5cafa075eb4d5b0bf1f228608a3ec87e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;syz.x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;syz.x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a213f858dacf7993492e6b32080aaa64</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testTrackConstraintBRVisitorIsTrackingTurnedOn</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/diagnostics/dtors.cpp b/test/Analysis/diagnostics/dtors.cpp
new file mode 100644
index 000000000000..094917e432f0
--- /dev/null
+++ b/test/Analysis/diagnostics/dtors.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus -verify %s
+
+// expected-no-diagnostics
+
+namespace no_crash_on_delete_dtor {
+// We were crashing when producing diagnostics for this code.
+struct S {
+ void foo();
+ ~S();
+};
+
+struct smart_ptr {
+ int x;
+ S *s;
+ smart_ptr(S *);
+ S *get() {
+ return (x || 0) ? nullptr : s;
+ }
+};
+
+void bar(smart_ptr p) {
+ delete p.get();
+ p.get()->foo();
+}
+} // namespace no_crash_on_delete_dtor
diff --git a/test/Analysis/diagnostics/explicit-suppression.cpp b/test/Analysis/diagnostics/explicit-suppression.cpp
index 092591836baa..2bb969059ffb 100644
--- a/test/Analysis/diagnostics/explicit-suppression.cpp
+++ b/test/Analysis/diagnostics/explicit-suppression.cpp
@@ -19,6 +19,6 @@ class C {
void testCopyNull(C *I, C *E) {
std::copy(I, E, (C *)0);
#ifndef SUPPRESSED
- // expected-warning@../Inputs/system-header-simulator-cxx.h:514 {{Called C++ object pointer is null}}
+ // expected-warning@../Inputs/system-header-simulator-cxx.h:677 {{Called C++ object pointer is null}}
#endif
}
diff --git a/test/Analysis/diagnostics/find_last_store.c b/test/Analysis/diagnostics/find_last_store.c
new file mode 100644
index 000000000000..9bf601ea30e2
--- /dev/null
+++ b/test/Analysis/diagnostics/find_last_store.c
@@ -0,0 +1,17 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
+typedef struct { float b; } c;
+void *a();
+void *d() {
+ return a(); // expected-note{{Returning pointer}}
+}
+
+void no_find_last_store() {
+ c *e = d(); // expected-note{{Calling 'd'}}
+ // expected-note@-1{{Returning from 'd'}}
+ // expected-note@-2{{'e' initialized here}}
+
+ (void)(e || e->b); // expected-note{{Assuming 'e' is null}}
+ // expected-note@-1{{Left side of '||' is false}}
+ // expected-note@-2{{Access to field 'b' results in a dereference of a null pointer (loaded from variable 'e')}}
+ // expected-warning@-3{{Access to field 'b' results in a dereference of a null pointer (loaded from variable 'e')}}
+}
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.c b/test/Analysis/diagnostics/no-store-func-path-notes.c
index a444ab60261b..2050f6217ca1 100644
--- a/test/Analysis/diagnostics/no-store-func-path-notes.c
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.c
@@ -224,3 +224,23 @@ int useindirectingstruct() {
return s.x; // expected-warning{{Undefined or garbage value returned to caller}}
// expected-note@-1{{Undefined or garbage value returned to caller}}
}
+
+typedef struct {
+ int *x;
+} D;
+
+void initializeMaybeInStruct(D* pD) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ *pD->x = 120;
+} // expected-note{{Returning without writing to 'pD->x'}}
+
+int useInitializeMaybeInStruct() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ D d;
+ d.x = &z;
+ initializeMaybeInStruct(&d); // expected-note{{Calling 'initializeMaybeInStruct'}}
+ // expected-note@-1{{Returning from 'initializeMaybeInStruct'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/test/Analysis/diagnostics/no-store-func-path-notes.cpp
index 17ec96ae5b75..587c08fae13d 100644
--- a/test/Analysis/diagnostics/no-store-func-path-notes.cpp
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=core -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -x c++ -std=c++14 -analyzer-checker=core -analyzer-output=text -verify %s
int initializer1(int &p, int x) {
if (x) { // expected-note{{Taking false branch}}
@@ -10,10 +10,10 @@ int initializer1(int &p, int x) {
}
int param_not_initialized_by_func() {
- int p; // expected-note {{'p' declared without an initial value}}
- int out = initializer1(p, 0); // expected-note{{Calling 'initializer1'}}
+ int outP; // expected-note {{'outP' declared without an initial value}}
+ int out = initializer1(outP, 0); // expected-note{{Calling 'initializer1'}}
// expected-note@-1{{Returning from 'initializer1'}}
- return p; // expected-note{{Undefined or garbage value returned to caller}}
+ return outP; // expected-note{{Undefined or garbage value returned to caller}}
// expected-warning@-1{{Undefined or garbage value returned to caller}}
}
@@ -175,3 +175,200 @@ void rdar40335545() {
//expected-note@-1{{}}
(void)useLocal;
}
+
+////////
+
+struct HasRef {
+ int &a;
+ HasRef(int &a) : a(a) {}
+};
+
+
+void maybeInitialize(const HasRef &&pA) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ pA.a = 120;
+} // expected-note{{Returning without writing to 'pA.a'}}
+
+int useMaybeInitializerWritingIntoField() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ maybeInitialize(HasRef(z)); // expected-note{{Calling constructor for 'HasRef'}}
+ // expected-note@-1{{Returning from constructor for 'HasRef'}}
+ // expected-note@-2{{Calling 'maybeInitialize'}}
+ // expected-note@-3{{Returning from 'maybeInitialize'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////////
+
+struct HasRefToItself {
+ HasRefToItself &Ref; // no infinite loop
+ int &z;
+ HasRefToItself(int &z) : Ref(*this), z(z) {}
+};
+
+void maybeInitialize(const HasRefToItself &&pA) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ pA.z = 120;
+} // expected-note{{Returning without writing to 'pA.Ref.z'}}
+
+int useMaybeInitializerWritingIntoFieldWithRefToItself() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ maybeInitialize(HasRefToItself(z)); // expected-note{{Calling constructor for 'HasRefToItself'}}
+ // expected-note@-1{{Returning from constructor for 'HasRefToItself'}}
+ // expected-note@-2{{Calling 'maybeInitialize'}}
+ // expected-note@-3{{Returning from 'maybeInitialize'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////
+
+void maybeInitialize(const HasRef *pA) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ pA->a = 120;
+} // expected-note{{Returning without writing to 'pA->a'}}
+
+int useMaybeInitializerStructByPointer() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ HasRef wrapper(z); // expected-note{{Calling constructor for 'HasRef'}}
+ // expected-note@-1{{Returning from constructor for 'HasRef'}}
+ maybeInitialize(&wrapper); // expected-note{{Calling 'maybeInitialize'}}
+ // expected-note@-1{{Returning from 'maybeInitialize'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////////
+
+struct HasParentWithRef : public HasRef {
+ HasParentWithRef(int &a) : HasRef(a) {} // expected-note{{Calling constructor for 'HasRef'}}
+ // expected-note@-1{{Returning from constructor for 'HasRef'}}
+};
+
+void maybeInitializeWithParent(const HasParentWithRef &pA) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ pA.a = 120;
+} // expected-note{{Returning without writing to 'pA.a'}}
+
+int useMaybeInitializerWritingIntoParentField() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ maybeInitializeWithParent(HasParentWithRef(z)); // expected-note{{Calling constructor for 'HasParentWithRef'}}
+ // expected-note@-1{{Returning from constructor for 'HasParentWithRef'}}
+ // expected-note@-2{{Calling 'maybeInitializeWithParent'}}
+ // expected-note@-3{{Returning from 'maybeInitializeWithParent'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////////
+
+struct HasIndirectRef {
+ HasRef &Ref;
+ HasIndirectRef(HasRef &Ref) : Ref(Ref) {}
+};
+
+void maybeInitializeIndirectly(const HasIndirectRef &pA) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ pA.Ref.a = 120;
+} // expected-note{{Returning without writing to 'pA.Ref.a'}}
+
+int useMaybeInitializeIndirectly() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
+ // expected-note@-1{{Returning from constructor for 'HasRef'}}
+ maybeInitializeIndirectly(HasIndirectRef(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
+ // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////////
+
+struct HasIndirectRefByValue {
+ HasRef Ref;
+ HasIndirectRefByValue(HasRef Ref) : Ref(Ref) {}
+};
+
+void maybeInitializeIndirectly(const HasIndirectRefByValue &pA) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ pA.Ref.a = 120;
+} // expected-note{{Returning without writing to 'pA.Ref.a'}}
+
+int useMaybeInitializeIndirectlyIndirectRefByValue() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
+ // expected-note@-1{{Returning from constructor for 'HasRef'}}
+ maybeInitializeIndirectly(HasIndirectRefByValue(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
+ // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////////
+
+struct HasIndirectPointerRef {
+ HasRef *Ref;
+ HasIndirectPointerRef(HasRef *Ref) : Ref(Ref) {}
+};
+
+void maybeInitializeIndirectly(const HasIndirectPointerRef &pA) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ pA.Ref->a = 120;
+} // expected-note{{Returning without writing to 'pA.Ref->a'}}
+
+int useMaybeInitializeIndirectlyWithPointer() {
+ int z; // expected-note{{'z' declared without an initial value}}
+ HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
+ // expected-note@-1{{Returning from constructor for 'HasRef'}}
+ maybeInitializeIndirectly(HasIndirectPointerRef(&r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
+ // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
+ return z; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////////
+
+struct HasFieldA {
+ int x;
+};
+
+struct HasFieldB {
+ int x;
+};
+
+void maybeInitializeHasField(HasFieldA *b) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ ((HasFieldB*)b)->x = 120;
+}
+
+int forceElementRegionApperence() {
+ HasFieldA a;
+ maybeInitializeHasField(&a); // expected-note{{Calling 'maybeInitializeHasField'}}
+ // expected-note@-1{{Returning from 'maybeInitializeHasField'}}
+ return ((HasFieldB*)&a)->x; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
+////////
+
+struct HasForgottenField {
+ int x;
+ HasForgottenField() {} // expected-note{{Returning without writing to 'this->x'}}
+};
+
+// Test that tracking across exclamation mark works.
+bool tracksThroughExclamationMark() {
+ HasForgottenField a; // expected-note{{Calling default constructor for 'HasForgottenField'}}
+ // expected-note@-1{{Returning from default constructor for 'HasForgottenField'}}
+ return !a.x; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.m b/test/Analysis/diagnostics/no-store-func-path-notes.m
index 51d1515e860a..c0aa5144e763 100644
--- a/test/Analysis/diagnostics/no-store-func-path-notes.m
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.m
@@ -52,7 +52,6 @@ int initFromBlock() {
extern void expectNonNull(NSString * _Nonnull a);
@interface A : NSObject
-- (void) func;
- (void) initAMaybe;
@end
@@ -66,7 +65,7 @@ extern void expectNonNull(NSString * _Nonnull a);
a = @"string";
} // expected-note{{Returning without writing to 'self->a'}}
-- (void) func {
+- (void) passNullToNonnull {
a = nil; // expected-note{{nil object reference stored to 'a'}}
[self initAMaybe]; // expected-note{{Calling 'initAMaybe'}}
// expected-note@-1{{Returning from 'initAMaybe'}}
@@ -74,4 +73,33 @@ extern void expectNonNull(NSString * _Nonnull a);
// expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}}
}
+- (void) initAMaybeWithExplicitSelf {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ self->a = @"string";
+} // expected-note{{Returning without writing to 'self->a'}}
+
+- (void) passNullToNonnullWithExplicitSelf {
+ self->a = nil; // expected-note{{nil object reference stored to 'a'}}
+ [self initAMaybeWithExplicitSelf]; // expected-note{{Calling 'initAMaybeWithExplicitSelf'}}
+ // expected-note@-1{{Returning from 'initAMaybeWithExplicitSelf'}}
+ expectNonNull(a); // expected-warning{{nil passed to a callee that requires a non-null 1st parameter}}
+ // expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}}
+}
+
+- (void) initPassedAMaybe:(A *) param {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ param->a = @"string";
+} // expected-note{{Returning without writing to 'param->a'}}
+
+- (void) useInitPassedAMaybe:(A *) paramA {
+ paramA->a = nil; // expected-note{{nil object reference stored to 'a'}}
+ [self initPassedAMaybe:paramA]; // expected-note{{Calling 'initPassedAMaybe:'}}
+ // expected-note@-1{{Returning from 'initPassedAMaybe:'}}
+ expectNonNull(paramA->a); // expected-warning{{nil passed to a callee that requires a non-null 1st parameter}}
+ // expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}}
+
+}
+
@end
diff --git a/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp b/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp
index 8c66b96007eb..dd86129e2fd2 100644
--- a/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp
+++ b/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -analyzer-output=plist-multi-file %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: tail -n +11 %t.plist | diff -u -w -I "<string>/" -I "<string>.:" -I "version" - %S/Inputs/expected-plists/plist-diagnostics-include-check.cpp.plist
#include "Inputs/include/plist-diagnostics-include-check-macro.h"
@@ -8,133 +8,3 @@ void foo() {
#define PLIST_DEF_MACRO .run();
#include "Inputs/include/plist-diagnostics-include-check-macro.def"
}
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>2</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;PlistCheckMacro::run&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;PlistCheckMacro::run&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;foo&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;foo&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>REACHABLE</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>REACHABLE</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>REACHABLE</string>
-// CHECK-NEXT: <key>category</key><string>debug</string>
-// CHECK-NEXT: <key>type</key><string>Checking analyzer assumptions</string>
-// CHECK-NEXT: <key>check_name</key><string>debug.ExprInspection</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>93b4eab05b21c892c8e31723e5af3f59</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
-// CHECK-NEXT: <key>issue_context</key><string>run</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/diagnostics/plist-multi-file.c b/test/Analysis/diagnostics/plist-multi-file.c
index ff68d4850862..878f373aaccf 100644
--- a/test/Analysis/diagnostics/plist-multi-file.c
+++ b/test/Analysis/diagnostics/plist-multi-file.c
@@ -1,205 +1,8 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-html -o %t.plist -verify %s
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: tail -n +11 %t.plist | diff -u -w -I "<string>/" -I "<string>.:" -I "version" --ignore-matching-lines=report - %S/Inputs/expected-plists/plist-multi-file.c.plist
#include "plist-multi-file.h"
void bar() {
foo(0);
}
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;foo&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;foo&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;bar&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;bar&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2058c95994cab381890af28e7bf354bf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>foo</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>HTMLDiagnostics_files</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <string>report-{{([0-9a-f]{6})}}.html</string>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/diagnostics/report-issues-within-main-file.cpp b/test/Analysis/diagnostics/report-issues-within-main-file.cpp
index 18795d25bd85..f166e311c538 100644
--- a/test/Analysis/diagnostics/report-issues-within-main-file.cpp
+++ b/test/Analysis/diagnostics/report-issues-within-main-file.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-output=plist-multi-file -analyzer-config report-in-main-source-file=true %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/report-issues-within-main-file.cpp.plist -
#include "Inputs/include/report-issues-within-main-file.h"
void mainPlusHeader() {
@@ -69,1710 +69,3 @@ void callInMacroArg() {
TAKE_CALL_AS_ARG(cause_div_by_zero_in_header4(5));
j--;
}
-
-// CHECK: </array>
-// CHECK-NEXT: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callInMacro&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callInMacro&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;h2&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;h2&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>81ef0773d42c0309a03a9a11048f497e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>cause_div_by_zero_in_header2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;callInMacro3&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;callInMacro3&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callCallInMacro3&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callCallInMacro3&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header3&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header3&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callInMacro3&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callInMacro3&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;h3&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;h3&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a4f425d2b2715e682b08a754fc88d2c8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>cause_div_by_zero_in_header3</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>51</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header4&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header4&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callInMacroArg&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callInMacroArg&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;h4&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;h4&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>35f2ebe7ff6b3b34233a5465a6eaf661</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>cause_div_by_zero_in_header4</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>key_event</key><true/>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;~auto_ptr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;~auto_ptr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusHeader&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusHeader&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos; (within a call to &apos;~auto_ptr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Bad deallocator</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.MismatchedDeallocator</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f689fbd54138491e228f0f89bb02bfb2</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>mainPlusHeader</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;auxInMain&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;auxInMain&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusMainPlusHeader&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusMainPlusHeader&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>key_event</key><true/>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;cause_div_by_zero_in_header&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;auxInMain&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;auxInMain&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;h&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;h&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>1</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero (within a call to &apos;cause_div_by_zero_in_header&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dceba279187ce4f6514f4a4c43a51063</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>auxInMain</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;causeDivByZeroInMain&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;causeDivByZeroInMain&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusMain&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusMain&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;m&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;m&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d0d513aa4710781c2b56c44226354403</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>causeDivByZeroInMain</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;causeDivByZeroInMain2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;causeDivByZeroInMain2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlustHeaderCallAndReturnPlusMain&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlustHeaderCallAndReturnPlusMain&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;m2&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;m2&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>577ddcf4482f18dec120e21890ed234a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>causeDivByZeroInMain2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/diagnostics/sarif-diagnostics-taint-test.c b/test/Analysis/diagnostics/sarif-diagnostics-taint-test.c
new file mode 100644
index 000000000000..37ddc9df6a24
--- /dev/null
+++ b/test/Analysis/diagnostics/sarif-diagnostics-taint-test.c
@@ -0,0 +1,15 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.security.taint,debug.TaintTest %s -verify -analyzer-output=sarif -o - | %diff_sarif %S/Inputs/expected-sarif/sarif-diagnostics-taint-test.c.sarif -
+#include "../Inputs/system-header-simulator.h"
+
+int atoi(const char *nptr);
+
+void f(void) {
+ char s[80];
+ scanf("%s", s);
+ int d = atoi(s); // expected-warning {{tainted}}
+}
+
+int main(void) {
+ f();
+ return 0;
+}
diff --git a/test/Analysis/diagnostics/sarif-multi-diagnostic-test.c b/test/Analysis/diagnostics/sarif-multi-diagnostic-test.c
new file mode 100644
index 000000000000..459128a05fa0
--- /dev/null
+++ b/test/Analysis/diagnostics/sarif-multi-diagnostic-test.c
@@ -0,0 +1,29 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.security.taint,debug.TaintTest %s -verify -analyzer-output=sarif -o - | %diff_sarif %S/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif -
+#include "../Inputs/system-header-simulator.h"
+
+int atoi(const char *nptr);
+
+void f(void) {
+ char s[80];
+ scanf("%s", s);
+ int d = atoi(s); // expected-warning {{tainted}}
+}
+
+void g(void) {
+ void (*fp)(int);
+ fp(12); // expected-warning {{Called function pointer is an uninitialized pointer value}}
+}
+
+int h(int i) {
+ if (i == 0)
+ return 1 / i; // expected-warning {{Division by zero}}
+ return 0;
+}
+
+int main(void) {
+ f();
+ g();
+ h(0);
+ return 0;
+}
+
diff --git a/test/Analysis/diagnostics/track_subexpressions.cpp b/test/Analysis/diagnostics/track_subexpressions.cpp
new file mode 100644
index 000000000000..e5a6b8ff1156
--- /dev/null
+++ b/test/Analysis/diagnostics/track_subexpressions.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=core -analyzer-output=text -verify %s
+
+typedef unsigned char uint8_t;
+
+#define UINT8_MAX 255
+#define TCP_MAXWIN 65535
+
+uint8_t get_uint8_max() {
+ uint8_t rcvscale = UINT8_MAX; // expected-note{{'rcvscale' initialized to 255}}
+ return rcvscale; // expected-note{{Returning the value 255 (loaded from 'rcvscale')}}
+}
+
+void shift_by_undefined_value() {
+ uint8_t shift_amount = get_uint8_max(); // expected-note{{'shift_amount' initialized to 255}}
+ // expected-note@-1{{Calling 'get_uint8_max'}}
+ // expected-note@-2{{Returning from 'get_uint8_max'}}
+ (void)(TCP_MAXWIN << shift_amount); // expected-warning{{The result of the left shift is undefined due to shifting by '255', which is greater or equal to the width of type 'int'}}
+ // expected-note@-1{{The result of the left shift is undefined due to shifting by '255', which is greater or equal to the width of type 'int'}}
+}
diff --git a/test/Analysis/diagnostics/undef-value-caller.c b/test/Analysis/diagnostics/undef-value-caller.c
index 60a885afe292..d537f726f865 100644
--- a/test/Analysis/diagnostics/undef-value-caller.c
+++ b/test/Analysis/diagnostics/undef-value-caller.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist -o %t %s
-// RUN: FileCheck --input-file %t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/undef-value-caller.c.plist -
#include "undef-value-callee.h"
@@ -11,118 +11,3 @@ int test_calling_unimportant_callee(int argc, char *argv[]) {
return x; // expected-warning {{Undefined or garbage value returned to caller}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Undefined or garbage value returned to caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Undefined or garbage value returned to caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Undefined or garbage value returned to caller</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Garbage return value</string>
-// CHECK-NEXT: <key>check_name</key><string>core.uninitialized.UndefReturn</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1ef750c5562c09a467ea54ea4b4de771</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_calling_unimportant_callee</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/diagnostics/undef-value-param.c b/test/Analysis/diagnostics/undef-value-param.c
index 99e31d2e6c55..de128dafc427 100644
--- a/test/Analysis/diagnostics/undef-value-param.c
+++ b/test/Analysis/diagnostics/undef-value-param.c
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/undef-value-param.c.plist -
void foo_irrelevant(int c) {
if (c)
@@ -63,1290 +63,3 @@ double testPassingParentRegionStruct(int x) {
//expected-note@-1{{Dereference of null pointer (loaded from field 'f1')}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;xx&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;xx&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;foo&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;foo&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;c&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;c&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning without writing to &apos;*x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning without writing to &apos;*x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;foo&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;foo&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The left operand of &apos;+&apos; is a garbage value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The left operand of &apos;+&apos; is a garbage value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The left operand of &apos;+&apos; is a garbage value</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Result of operation is garbage or undefined</string>
-// CHECK-NEXT: <key>check_name</key><string>core.UndefinedBinaryOperatorResult</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ae5e3bd03d6d97614947942dae18e1da</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>use</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;initArray&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;initArray&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testPassingParentRegionArray&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testPassingParentRegionArray&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;initArray&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;initArray&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The right operand of &apos;*&apos; is a garbage value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The right operand of &apos;*&apos; is a garbage value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The right operand of &apos;*&apos; is a garbage value</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Result of operation is garbage or undefined</string>
-// CHECK-NEXT: <key>check_name</key><string>core.UndefinedBinaryOperatorResult</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>96cf3258da3df14d13cd5c2236c9cb27</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testPassingParentRegionArray</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;st.f1&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;st.f1&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;initStruct&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;initStruct&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testPassingParentRegionStruct&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testPassingParentRegionStruct&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning without writing to &apos;X-&gt;f1&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;initStruct&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;initStruct&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;f1&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;f1&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;f1&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>299055864402de225b0ab4f2ecd8e76c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testPassingParentRegionStruct</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/diagnostics/undef-value-param.m b/test/Analysis/diagnostics/undef-value-param.m
index 69bc9b991da6..5dfd9f8216b6 100644
--- a/test/Analysis/diagnostics/undef-value-param.m
+++ b/test/Analysis/diagnostics/undef-value-param.m
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=plist-multi-file %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/undef-value-param.m.plist -
typedef signed char BOOL;
@protocol NSObject - (BOOL)isEqual:(id)object; @end
@@ -74,985 +74,3 @@ static void CreateRefUndef(SCDynamicStoreRef *storeRef, unsigned x) {
*storeRef = ref;
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;CreateRef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;CreateRef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;err&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;err&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>nil object reference stored to &apos;ref&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>nil object reference stored to &apos;ref&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>nil object reference stored to &apos;storeRef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>nil object reference stored to &apos;storeRef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;CreateRef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;CreateRef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFRelease</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFRelease</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRelease</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.coreFoundation.CFRetainRelease</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>102c9a15c089fdc618a4c209bd5560bc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;storeRef&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;storeRef&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;CreateRefUndef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;CreateRefUndef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;err&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;err&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning without writing to &apos;*storeRef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning without writing to &apos;*storeRef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;CreateRefUndef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;CreateRefUndef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>1st function call argument is an uninitialized value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>1st function call argument is an uninitialized value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>1st function call argument is an uninitialized value</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Uninitialized argument value</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fe2bb14813e15196c0180196fc1cce4c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/disable-all-checks.c b/test/Analysis/disable-all-checks.c
index eb55799c259f..fba53429ab5e 100644
--- a/test/Analysis/disable-all-checks.c
+++ b/test/Analysis/disable-all-checks.c
@@ -1,9 +1,18 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-disable-all-checks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-disable-all-checks -analyzer-checker=core -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region \
+// RUN: -analyzer-disable-all-checks -verify %s
+//
+// RUN: %clang_analyze_cc1 -analyzer-disable-all-checks -analyzer-checker=core \
+// RUN: -analyzer-store=region -verify %s
+//
// RUN: %clang_analyze_cc1 -analyzer-disable-all-checks -verify %s
-// RUN: not %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-disable-checker -verify %s 2>&1 | FileCheck %s
+//
+// RUN: not %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region \
+// RUN: -analyzer-disable-checker non.existant.Checker -verify %s 2>&1 \
+// RUN: | FileCheck %s
+//
// expected-no-diagnostics
+// CHECK: no analyzer checkers are associated with 'non.existant.Checker'
// CHECK: use -analyzer-disable-all-checks to disable all static analyzer checkers
int buggy() {
int x = 0;
diff --git a/test/Analysis/dtor.cpp b/test/Analysis/dtor.cpp
index c31bbe774b81..d843f03aada7 100644
--- a/test/Analysis/dtor.cpp
+++ b/test/Analysis/dtor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection,cplusplus -analyzer-config c++-inlining=destructors -Wno-null-dereference -Wno-inaccessible-base -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection,cplusplus -analyzer-config c++-inlining=destructors -Wno-null-dereference -Wno-inaccessible-base -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
void clang_analyzer_checkInlined(bool);
diff --git a/test/Analysis/dump_egraph.c b/test/Analysis/dump_egraph.c
new file mode 100644
index 000000000000..6e8793b202be
--- /dev/null
+++ b/test/Analysis/dump_egraph.c
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-dump-egraph=%t.dot %s
+// RUN: cat %t.dot | FileCheck %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-dump-egraph=%t.dot -trim-egraph %s
+// REQUIRES: asserts
+
+int getJ();
+
+int foo() {
+ int *x = 0, *y = 0;
+ return *x + *y;
+}
+
+// CHECK: digraph "Exploded Graph" {
+// CHECK: Edge: (B2, B1)
+// CHECK: Block Entrance: B1
+// CHECK: Bug report attached
diff --git a/test/Analysis/dump_egraph.cpp b/test/Analysis/dump_egraph.cpp
new file mode 100644
index 000000000000..10e33a7523f5
--- /dev/null
+++ b/test/Analysis/dump_egraph.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-dump-egraph=%t.dot %s
+// RUN: cat %t.dot | FileCheck %s
+// REQUIRES: asserts
+
+struct S {
+ ~S();
+};
+
+struct T {
+ S s;
+ T() : s() {}
+};
+
+void foo() {
+ // Test that dumping symbols conjured on null statements doesn't crash.
+ T t;
+}
+
+// CHECK: (LC1,S{{[0-9]*}},construct into local variable) T t;\n : &t
+// CHECK: (LC2,I{{[0-9]*}},construct into member variable) s : &t-\>s
+// CHECK: conj_$5\{int, LC3, no stmt, #1\}
+
diff --git a/test/Analysis/edges-new.mm b/test/Analysis/edges-new.mm
index 3e9615b94b6c..5a58850d0684 100644
--- a/test/Analysis/edges-new.mm
+++ b/test/Analysis/edges-new.mm
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-eagerly-assume -analyzer-output=plist -o %t -w %s
-// RUN: FileCheck --input-file %t %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-output=plist -o %t -w %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/edges-new.mm.plist -
//===----------------------------------------------------------------------===//
// Forward declarations (from headers).
@@ -590,20757 +590,3 @@ namespace rdar14960554 {
};
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dc9c2a657ca759f9744cde2e093cfd59</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_init</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8f95d9681490a4e52c167969d0957b39</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_assign</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>64</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>64</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>64</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>64</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>64</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>64</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>64</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>94c43fbcad6aaff4ee7433f2d2db0bbe</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_assign_transitive</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>659f01507ffd7efd3ca3eab7179fd7d2</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_cond</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c90d51e62139e614b57aff7021240a82</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_cond_transitive</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;x.p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;x.p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>245408d2bc416e324064d990e6dd82a8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_field</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;b&apos; is equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;b&apos; is equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b12acffa40177b55b695aa2292533410</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_assumptions</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c0a32b8291b0fc7230f847f05f415625</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_cond_assign</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>82</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>122</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>122</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>122</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>122</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>29a10ca4af622b6146ca082e49d919d6</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar8331641</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ed7251f5b34b8380abd60cddfd3db46b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_fast_enumeration</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;x&apos; is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;x&apos; is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;x&apos; is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead increment</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dd09640bb87b201c2adcf5ef37bfcfaa</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_fast_enumeration_2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Assigned value is garbage or undefined</string>
-// CHECK-NEXT: <key>check_name</key><string>core.uninitialized.Assign</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>025372576cd3ba6716044f93a51c978c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_fast_enumeration_2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>08f9a01186cb2f1b78b08ec20260f1c1</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar12280665</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>157</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>157</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>93a53e4c8f02d191b07477940ddcf89c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>radar12322528_for</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;i&apos; is &gt;= &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f2d2dbf579b0b21a6b68726df6a041fc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>radar12322528_while</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>179</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>179</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>179</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>179</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>95c7d39fb9d0d8c172b894e02855a07c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>radar12322528_foo_2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4cbbc713c8267513fef8a33f1327d7ca</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_diagnostics</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a5aa7cf7ce6ba6683bebfff63df926fd</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_diagnostics_2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>210</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>210</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>217</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>940ba28399417701285cc8f80b1b8c2d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_diagnostics_3</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>10</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>227</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>227</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>227</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>227</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>227</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>227</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>227</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>89eb0611013a66315f63bf4de8130c3d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_do_while</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>12</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>483f7a1c29cc32152ca2ea651443e16f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_logical_and</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>852b510b1e204194a9fe3045cabc952c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_logical_or</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a5081bea3b0e9f4f8132ecdb2c17991b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_logical_or_call</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>16c21155317ccfddb4f482db43b6c635</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_nested_logicals</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>267</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>16c21155317ccfddb4f482db43b6c635</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_nested_logicals</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>274</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>274</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>274</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>274</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>274</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>51</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>51</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>51</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>51</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>57</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5fec1fd2724e271bb73fa4dd4be2a7f5</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_deeply_nested_logicals</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>283</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>285</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c4ebf7f3e8a792521541ffae22ae2378</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_ternary</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>287</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>294</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>294</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>294</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>294</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>297</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>297</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>297</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>297</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>297</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>297</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>297</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>137a2333a17b5eecff7ff7a4b56d38d9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testUseless</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>298</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d1a1b27348a9c4d0abaaea4a4df9b649</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testFoo</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>312</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>320</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>320</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>320</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>320</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>320</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;getPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;getPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1d7470f8b42e1cff6ab697162911b488</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test1_IPA_X</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;opaque&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;opaque&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;getX&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;getX&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;getPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;getPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3fda62f72d88e4bc250c415cbc45a9e2</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_IPA_Y</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>341</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>354</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>354</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>354</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>354</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>354</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;causeDivByZeroInMain&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;causeDivByZeroInMain&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>345</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusMain&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;mainPlusMain&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>345</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>345</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;m&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;m&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d0d513aa4710781c2b56c44226354403</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>causeDivByZeroInMain</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>383</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>383</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>383</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>383</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>383</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b21eba78798501dc6b716bb91e3f7f01</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>392</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>392</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>392</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;s.i&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;s.i&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>392</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>392</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
-// CHECK-NEXT: <key>category</key><string>API</string>
-// CHECK-NEXT: <key>type</key><string>Argument with &apos;nonnull&apos; attribute passed null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NonNullParamChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c0b359a043c633f1b8d1581f68743361</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>RDar13295437</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>400</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>573a1a599cc8abe987f5227676d04abc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCast</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>420</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ea1d5db6b4c380a432c88139fdd18f42</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>422</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;foo&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3dd1ebf91fa4e92eeec82faaeb48beda</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of RDar10797980 with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of RDar10797980 with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f533db5cbb9c20d171f9f92105789dc4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>449</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a76c8ba29cdedecd0dfa5e24711cd236</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>20</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>458</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>463</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>463</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>463</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>463</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>26</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>464</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>468</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>468</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>468</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>468</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>34</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>499</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>499</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>499</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>499</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>62</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>500</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>67</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>509</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>509</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>509</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>509</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>510</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bfb65e90e76fe7a219616d1d0b36f958</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>74</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>512</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>445</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>452</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>454</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>457</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>459</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>460</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>467</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>475</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>477</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>476</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when range is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>484</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>493</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>494</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>515</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>515</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>515</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>515</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>515</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>515</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>515</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>516</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>516</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>516</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>516</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>517</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>518</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>518</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>518</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>518</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6c3e2dd10c375325a3089b996dd460c3</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>variousLoops</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>83</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>521</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>529</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>529</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>529</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>529</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>529</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>533</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>533</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>533</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>51180616cd69dc1776be708299ec90fb</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>reallocDiagnostics</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>533</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>548</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>548</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>551</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>551</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>551</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>551</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>551</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>551</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>551</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>553</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>553</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>553</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>553</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>555</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>555</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>555</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;~unique_ptr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;~unique_ptr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Memory allocated by &apos;new[]&apos; should be deallocated by &apos;delete[]&apos;, not &apos;delete&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Bad deallocator</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.MismatchedDeallocator</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>046c88d1c91ff46d6506dff5ff880756</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>0</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>544</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>558</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>558</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>558</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>558</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>558</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>559</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>559</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>559</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>559</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>560</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>561</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>563</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>562</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>564</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>87</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>566</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>567</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>568</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>568</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>568</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5616a7601faa1a8c2ac56fa1b595b172</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>longLines</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>568</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>572</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>572</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>572</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>572</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>572</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dff4970e681578e07d0512d3258aeddd</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testMacroInFunctionDecl</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>573</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>584</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>584</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>587</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>587</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>587</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>587</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>de83c7c8cc706cf47429f220bfa49458</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>588</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/end-function-return-stmt.cpp b/test/Analysis/end-function-return-stmt.cpp
new file mode 100644
index 000000000000..036ccba3aa93
--- /dev/null
+++ b/test/Analysis/end-function-return-stmt.cpp
@@ -0,0 +1,34 @@
+//RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:EndFunction=true %s 2>&1 | FileCheck %s
+
+// At the end of a function, we can only obtain a ReturnStmt if the last
+// CFGElement in the CFGBlock is either a CFGStmt or a CFGAutomaticObjDtor.
+
+void noReturnStmt() {}
+
+struct S {
+ S();
+ ~S();
+};
+
+int dtorAfterReturnStmt() {
+ S s;
+ return 0;
+}
+
+S endsWithReturnStmt() {
+ return S();
+}
+
+// endsWithReturnStmt()
+// CHECK: EndFunction
+// CHECK-NEXT: ReturnStmt: yes
+// CHECK-NEXT: CFGElement: CFGStmt
+
+// dtorAfterReturnStmt()
+// CHECK: EndFunction
+// CHECK-NEXT: ReturnStmt: yes
+// CHECK-NEXT: CFGElement: CFGAutomaticObjDtor
+
+// noReturnStmt()
+// CHECK: EndFunction
+// CHECK-NEXT: ReturnStmt: no
diff --git a/test/Analysis/enum-cast-out-of-range.cpp b/test/Analysis/enum-cast-out-of-range.cpp
new file mode 100644
index 000000000000..e77339b551e0
--- /dev/null
+++ b/test/Analysis/enum-cast-out-of-range.cpp
@@ -0,0 +1,192 @@
+// RUN: %clang_analyze_cc1 \
+// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \
+// RUN: -std=c++11 -verify %s
+
+enum unscoped_unspecified_t {
+ unscoped_unspecified_0 = -4,
+ unscoped_unspecified_1,
+ unscoped_unspecified_2 = 1,
+ unscoped_unspecified_3,
+ unscoped_unspecified_4 = 4
+};
+
+enum unscoped_specified_t : int {
+ unscoped_specified_0 = -4,
+ unscoped_specified_1,
+ unscoped_specified_2 = 1,
+ unscoped_specified_3,
+ unscoped_specified_4 = 4
+};
+
+enum class scoped_unspecified_t {
+ scoped_unspecified_0 = -4,
+ scoped_unspecified_1,
+ scoped_unspecified_2 = 1,
+ scoped_unspecified_3,
+ scoped_unspecified_4 = 4
+};
+
+enum class scoped_specified_t : int {
+ scoped_specified_0 = -4,
+ scoped_specified_1,
+ scoped_specified_2 = 1,
+ scoped_specified_3,
+ scoped_specified_4 = 4
+};
+
+struct S {
+ unscoped_unspecified_t E : 5;
+};
+
+void unscopedUnspecified() {
+ unscoped_unspecified_t InvalidBeforeRangeBegin = static_cast<unscoped_unspecified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t ValidNegativeValue1 = static_cast<unscoped_unspecified_t>(-4); // OK.
+ unscoped_unspecified_t ValidNegativeValue2 = static_cast<unscoped_unspecified_t>(-3); // OK.
+ unscoped_unspecified_t InvalidInsideRange1 = static_cast<unscoped_unspecified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t InvalidInsideRange2 = static_cast<unscoped_unspecified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t InvalidInsideRange3 = static_cast<unscoped_unspecified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t ValidPositiveValue1 = static_cast<unscoped_unspecified_t>(1); // OK.
+ unscoped_unspecified_t ValidPositiveValue2 = static_cast<unscoped_unspecified_t>(2); // OK.
+ unscoped_unspecified_t InvalidInsideRange4 = static_cast<unscoped_unspecified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t ValidPositiveValue3 = static_cast<unscoped_unspecified_t>(4); // OK.
+ unscoped_unspecified_t InvalidAfterRangeEnd = static_cast<unscoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void unscopedSpecified() {
+ unscoped_specified_t InvalidBeforeRangeBegin = static_cast<unscoped_specified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t ValidNegativeValue1 = static_cast<unscoped_specified_t>(-4); // OK.
+ unscoped_specified_t ValidNegativeValue2 = static_cast<unscoped_specified_t>(-3); // OK.
+ unscoped_specified_t InvalidInsideRange1 = static_cast<unscoped_specified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t InvalidInsideRange2 = static_cast<unscoped_specified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t InvalidInsideRange3 = static_cast<unscoped_specified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t ValidPositiveValue1 = static_cast<unscoped_specified_t>(1); // OK.
+ unscoped_specified_t ValidPositiveValue2 = static_cast<unscoped_specified_t>(2); // OK.
+ unscoped_specified_t InvalidInsideRange4 = static_cast<unscoped_specified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t ValidPositiveValue3 = static_cast<unscoped_specified_t>(4); // OK.
+ unscoped_specified_t InvalidAfterRangeEnd = static_cast<unscoped_specified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void scopedUnspecified() {
+ scoped_unspecified_t InvalidBeforeRangeBegin = static_cast<scoped_unspecified_t>(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t ValidNegativeValue1 = static_cast<scoped_unspecified_t>(-4); // OK.
+ scoped_unspecified_t ValidNegativeValue2 = static_cast<scoped_unspecified_t>(-3); // OK.
+ scoped_unspecified_t InvalidInsideRange1 = static_cast<scoped_unspecified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t InvalidInsideRange2 = static_cast<scoped_unspecified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t InvalidInsideRange3 = static_cast<scoped_unspecified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t ValidPositiveValue1 = static_cast<scoped_unspecified_t>(1); // OK.
+ scoped_unspecified_t ValidPositiveValue2 = static_cast<scoped_unspecified_t>(2); // OK.
+ scoped_unspecified_t InvalidInsideRange4 = static_cast<scoped_unspecified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t ValidPositiveValue3 = static_cast<scoped_unspecified_t>(4); // OK.
+ scoped_unspecified_t InvalidAfterRangeEnd = static_cast<scoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void scopedSpecified() {
+ scoped_specified_t InvalidBeforeRangeBegin = static_cast<scoped_specified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t ValidNegativeValue1 = static_cast<scoped_specified_t>(-4); // OK.
+ scoped_specified_t ValidNegativeValue2 = static_cast<scoped_specified_t>(-3); // OK.
+ scoped_specified_t InvalidInsideRange1 = static_cast<scoped_specified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t InvalidInsideRange2 = static_cast<scoped_specified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t InvalidInsideRange3 = static_cast<scoped_specified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t ValidPositiveValue1 = static_cast<scoped_specified_t>(1); // OK.
+ scoped_specified_t ValidPositiveValue2 = static_cast<scoped_specified_t>(2); // OK.
+ scoped_specified_t InvalidInsideRange4 = static_cast<scoped_specified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t ValidPositiveValue3 = static_cast<scoped_specified_t>(4); // OK.
+ scoped_specified_t InvalidAfterRangeEnd = static_cast<scoped_specified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void unscopedUnspecifiedCStyle() {
+ unscoped_unspecified_t InvalidBeforeRangeBegin = (unscoped_unspecified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t ValidNegativeValue1 = (unscoped_unspecified_t)(-4); // OK.
+ unscoped_unspecified_t ValidNegativeValue2 = (unscoped_unspecified_t)(-3); // OK.
+ unscoped_unspecified_t InvalidInsideRange1 = (unscoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t InvalidInsideRange2 = (unscoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t InvalidInsideRange3 = (unscoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t ValidPositiveValue1 = (unscoped_unspecified_t)(1); // OK.
+ unscoped_unspecified_t ValidPositiveValue2 = (unscoped_unspecified_t)(2); // OK.
+ unscoped_unspecified_t InvalidInsideRange4 = (unscoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_unspecified_t ValidPositiveValue3 = (unscoped_unspecified_t)(4); // OK.
+ unscoped_unspecified_t InvalidAfterRangeEnd = (unscoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void unscopedSpecifiedCStyle() {
+ unscoped_specified_t InvalidBeforeRangeBegin = (unscoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t ValidNegativeValue1 = (unscoped_specified_t)(-4); // OK.
+ unscoped_specified_t ValidNegativeValue2 = (unscoped_specified_t)(-3); // OK.
+ unscoped_specified_t InvalidInsideRange1 = (unscoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t InvalidInsideRange2 = (unscoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t InvalidInsideRange3 = (unscoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t ValidPositiveValue1 = (unscoped_specified_t)(1); // OK.
+ unscoped_specified_t ValidPositiveValue2 = (unscoped_specified_t)(2); // OK.
+ unscoped_specified_t InvalidInsideRange4 = (unscoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ unscoped_specified_t ValidPositiveValue3 = (unscoped_specified_t)(4); // OK.
+ unscoped_specified_t InvalidAfterRangeEnd = (unscoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void scopedUnspecifiedCStyle() {
+ scoped_unspecified_t InvalidBeforeRangeBegin = (scoped_unspecified_t)(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t ValidNegativeValue1 = (scoped_unspecified_t)(-4); // OK.
+ scoped_unspecified_t ValidNegativeValue2 = (scoped_unspecified_t)(-3); // OK.
+ scoped_unspecified_t InvalidInsideRange1 = (scoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t InvalidInsideRange2 = (scoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t InvalidInsideRange3 = (scoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t ValidPositiveValue1 = (scoped_unspecified_t)(1); // OK.
+ scoped_unspecified_t ValidPositiveValue2 = (scoped_unspecified_t)(2); // OK.
+ scoped_unspecified_t InvalidInsideRange4 = (scoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_unspecified_t ValidPositiveValue3 = (scoped_unspecified_t)(4); // OK.
+ scoped_unspecified_t InvalidAfterRangeEnd = (scoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void scopedSpecifiedCStyle() {
+ scoped_specified_t InvalidBeforeRangeBegin = (scoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t ValidNegativeValue1 = (scoped_specified_t)(-4); // OK.
+ scoped_specified_t ValidNegativeValue2 = (scoped_specified_t)(-3); // OK.
+ scoped_specified_t InvalidInsideRange1 = (scoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t InvalidInsideRange2 = (scoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t InvalidInsideRange3 = (scoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t ValidPositiveValue1 = (scoped_specified_t)(1); // OK.
+ scoped_specified_t ValidPositiveValue2 = (scoped_specified_t)(2); // OK.
+ scoped_specified_t InvalidInsideRange4 = (scoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+ scoped_specified_t ValidPositiveValue3 = (scoped_specified_t)(4); // OK.
+ scoped_specified_t InvalidAfterRangeEnd = (scoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void rangeContstrained1(int input) {
+ if (input > -5 && input < 5)
+ auto value = static_cast<scoped_specified_t>(input); // OK. Being conservative, this is a possibly good value.
+}
+
+void rangeConstrained2(int input) {
+ if (input < -5)
+ auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void rangeConstrained3(int input) {
+ if (input >= -2 && input <= -1)
+ auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void rangeConstrained4(int input) {
+ if (input >= -2 && input <= 1)
+ auto value = static_cast<scoped_specified_t>(input); // OK. Possibly 1.
+}
+
+void rangeConstrained5(int input) {
+ if (input >= 1 && input <= 2)
+ auto value = static_cast<scoped_specified_t>(input); // OK. Strict inner matching.
+}
+
+void rangeConstrained6(int input) {
+ if (input >= 2 && input <= 4)
+ auto value = static_cast<scoped_specified_t>(input); // OK. The value is possibly 2 or 4, dont warn.
+}
+
+void rangeConstrained7(int input) {
+ if (input >= 3 && input <= 3)
+ auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
+
+void enumBitFieldAssignment() {
+ S s;
+ s.E = static_cast<unscoped_unspecified_t>(4); // OK.
+ s.E = static_cast<unscoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
+}
diff --git a/test/Analysis/expr-inspection.cpp b/test/Analysis/expr-inspection.cpp
new file mode 100644
index 000000000000..609b44ca6d4c
--- /dev/null
+++ b/test/Analysis/expr-inspection.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=debug.ExprInspection -verify %s
+
+// Self-tests for the debug.ExprInspection checker.
+
+void clang_analyzer_denote(int x, const char *str);
+void clang_analyzer_express(int x);
+
+// Invalid declarations to test sanity checks.
+void clang_analyzer_denote();
+void clang_analyzer_denote(int x);
+void clang_analyzer_express();
+
+void foo(int x, unsigned y) {
+ clang_analyzer_denote(); // expected-warning{{clang_analyzer_denote() requires a symbol and a string literal}}
+ clang_analyzer_express(); // expected-warning{{clang_analyzer_express() requires a symbol}}
+
+ clang_analyzer_denote(x); // expected-warning{{clang_analyzer_denote() requires a symbol and a string literal}}
+ clang_analyzer_express(x); // expected-warning{{Unable to express}}
+
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x + y); // expected-warning{{$x + $y}}
+
+ clang_analyzer_denote(1, "$z"); // expected-warning{{Not a symbol}}
+ clang_analyzer_express(1); // expected-warning{{Not a symbol}}
+
+ clang_analyzer_denote(x + 1, "$w");
+ clang_analyzer_express(x + 1); // expected-warning{{$w}}
+ clang_analyzer_express(y + 1); // expected-warning{{$y + 1U}}
+}
diff --git a/test/Analysis/func-mapping-test.cpp b/test/Analysis/func-mapping-test.cpp
index 37e653882b7b..a5d7cfb449c7 100644
--- a/test/Analysis/func-mapping-test.cpp
+++ b/test/Analysis/func-mapping-test.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_func_map %s -- | FileCheck %s
+// RUN: %clang_extdef_map %s -- | FileCheck %s
int f(int) {
return 0;
diff --git a/test/Analysis/func.c b/test/Analysis/func.c
index 58d4f45eeb50..44d09f498992 100644
--- a/test/Analysis/func.c
+++ b/test/Analysis/func.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
diff --git a/test/Analysis/generics.m b/test/Analysis/generics.m
index e506e89bdf51..1d6fa84a9c52 100644
--- a/test/Analysis/generics.m
+++ b/test/Analysis/generics.m
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.ObjCGenerics,alpha.core.DynamicTypeChecker -verify -Wno-objc-method-access %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.ObjCGenerics,alpha.core.DynamicTypeChecker -verify -Wno-objc-method-access %s -analyzer-output=plist -o %t.plist
-// RUN: FileCheck --input-file %t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/generics.m.plist -
#if !__has_feature(objc_generics)
# error Compiler does not support Objective-C generics?
@@ -406,6705 +406,3 @@ void testCallToMethodWithCovariantParameterOnInstanceOfSubclassWithInvariantPara
[arrayOfStrings containsObject:someString]; // no-warning
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>33d4584e2bf66b029ab9d152cc9cd8f7</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6edc910aaa9dc1f2d823abc8cb75360f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>73c71c858082f5d7a2258f707927da3c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getTypedStuff&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getTypedStuff&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;crossProceduralErasedTypes&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;crossProceduralErasedTypes&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getTypedStuff&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getTypedStuff&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>82c378fdcfcc5c0318d2f3ca46420ec1</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>crossProceduralErasedTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>234e3c299ee75a4dd4563e0ea88b9ed9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>e875afc5479fec33a693ce2b550a9573</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d7fa9fa89fe860ed8f5d22631233a5fa</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7de91182a5d6e40a85fa3b91cf3fd089</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8960776d84319407ac2bf7a1531d19b0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>93b114c7a385294dce5c25ed04a8b25a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4c17f22d7e977f3343d2e2129b9229c3</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>24a08781e7d8971a7d8f8f607ce40074</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>pathSensitiveInference</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a8534f675404d57d833dc3c371d49845</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>verifyAPIusage</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d113e22b9ee9ded1cd94750c3557eff4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>subtypeOfGeneric</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f1b900572a63726a729714a765595c38</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGeneric</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>195</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>cbb926c9de226a3eac85fb961a93f39a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGeneric</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b6ee3b22fbad45f213b4bf14bec7eeaf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6561f05506a8ceca3afc79fc59912b94</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>219</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6aab15d40b39ec0a6b749e561d486e6a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPI</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>224</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>224</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>224</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>224</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>224</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bd1da1b7775323773555e5d5c122661f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPI2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3f2abd3c0b4b4a80a71bcbb668124ffb</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>73a50f2592e8b3c9af898749f24176f7</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>235</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>240</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>23ca540c8961ab9a362a194e1e895f86</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes3</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>be7e9426f827314f05fd4e15b25909df</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithBuggyTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>246</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0f97a618ccac913d7c8631b5b86a133e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>67</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>725c54c88bb271138b1de545ee59a8aa</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes3</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>257</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fb867af384c612fe5c09f821127eeaf0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes4</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2e9f738345d9fa7dae2324ff7accd1ae</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>276</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d85392b4efadf710b8da65a043a65e24</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>456c6227549a5e577088c9dce4cea452</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>275</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>df7f090d2b72ac07bc2351177ed6552d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>282</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>288</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>288</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>288</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>288</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>288</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a0fa75143d7a7ac234292642a6d93360</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>findMethodDeclInTrackedType</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>300</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>300</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>300</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>300</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>300</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>301</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>302</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>302</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>302</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>302</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>302</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d0b99c8523e81ec43ba4ea80aeedef1b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>findMethodDeclInTrackedType2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>302</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>326</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>326</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>46aa94b866747bcbe1ded581da7a2633</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>trackedClassVariables</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>326</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>326</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a759006d1ce88e15fcd6de6a29e2579c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>trackedClassVariables</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>332</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>332</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>332</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>332</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>332</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4bb1729ff86647750b458e6f8d883f08</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>nestedCollections</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>333</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>345</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>345</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>38831553eaecfb6c02b51e71d21ec6ea</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>returnCollectionToIdVariable</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>352</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>9fcbd4dcf212f004877292aa5085322b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>eraseSpecialization</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>353</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>357</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>357</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>be6714fed24af6e7ac522b87a5098de0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>returnToUnrelatedType</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>358</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>363</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>363</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>364</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>364</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>364</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>364</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>364</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSString *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSString *&apos; is inferred from this context</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>364</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>364</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5e96ef711c8f115bc64f69baa3f6ea7a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>returnToIdVariable</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>365</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8347f65fb51a85ccd462d75ffd761078</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>375</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>374</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>380</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>380</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>380</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>380</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>380</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6528db66f562ac0c2a94933f3ca5f6a8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>380</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>389</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>389</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>70</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>79</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>70</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>70</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>79</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>56326e7b73d049256717eba7005ccc4d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testArgumentAfterUpcastWithCovariantTypeParameter</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>391</integer>
-// CHECK-NEXT: <key>col</key><integer>70</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/global-region-invalidation.c b/test/Analysis/global-region-invalidation.c
index 83df292f5885..a40ab392b697 100644
--- a/test/Analysis/global-region-invalidation.c
+++ b/test/Analysis/global-region-invalidation.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -disable-free -analyzer-eagerly-assume -analyzer-checker=core,deadcode,alpha.security.taint,debug.TaintTest,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -disable-free -analyzer-checker=core,deadcode,alpha.security.taint,debug.TaintTest,debug.ExprInspection -verify %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/global_region_invalidation.mm b/test/Analysis/global_region_invalidation.mm
index aee3b66a63d3..57a695edd3fb 100644
--- a/test/Analysis/global_region_invalidation.mm
+++ b/test/Analysis/global_region_invalidation.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/gtest.cpp b/test/Analysis/gtest.cpp
index e68303d5492a..43c823a8c126 100644
--- a/test/Analysis/gtest.cpp
+++ b/test/Analysis/gtest.cpp
@@ -1,5 +1,5 @@
-//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -analyzer-eagerly-assume %s -verify
-//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -analyzer-eagerly-assume -DGTEST_VERSION_1_8_AND_LATER=1 %s -verify
+//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection %s -verify
+//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -DGTEST_VERSION_1_8_AND_LATER=1 %s -verify
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
diff --git a/test/Analysis/html_diagnostics/relevant_lines/synthesized_body.cpp b/test/Analysis/html_diagnostics/relevant_lines/synthesized_body.cpp
new file mode 100644
index 000000000000..2ed8355f6e60
--- /dev/null
+++ b/test/Analysis/html_diagnostics/relevant_lines/synthesized_body.cpp
@@ -0,0 +1,25 @@
+// Faking std::call_once implementation.
+namespace std {
+typedef struct once_flag_s {
+ int _M_once = 0;
+} once_flag;
+
+template <class Callable, class... Args>
+void call_once(once_flag &o, Callable&& func, Args&&... args);
+} // namespace std
+
+int deref(int *x) {
+ return *x;
+}
+
+void call_deref_once() {
+ static std::once_flag once;
+ int *p = nullptr;
+ std::call_once(once, &deref, p);
+}
+
+
+// RUN: rm -rf %t.output
+// RUN: %clang_analyze_cc1 -std=c++11 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
+// RUN: cat %t.output/* | FileCheck %s --match-full-lines
+// CHECK: var relevant_lines = {"1": {"3": 1, "8": 1, "11": 1, "12": 1, "15": 1, "16": 1, "17": 1, "18": 1}};
diff --git a/test/Analysis/inline-plist.c b/test/Analysis/inline-plist.c
index 457fb266420f..b3fb554da704 100644
--- a/test/Analysis/inline-plist.c
+++ b/test/Analysis/inline-plist.c
@@ -1,6 +1,6 @@
-// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=text -analyzer-config suppress-null-return-paths=false -verify %s
-// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=plist -analyzer-config suppress-null-return-paths=false -o %t
-// RUN: FileCheck -input-file %t %s
+// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=text -analyzer-config suppress-null-return-paths=false -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-config eagerly-assume=false %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=plist -analyzer-config suppress-null-return-paths=false -o %t
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/inline-plist.c.plist -
// <rdar://problem/10967815>
void mmm(int y) {
@@ -86,1899 +86,3 @@ void test_block_arg() {
*p = 1; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}} expected-note{{Dereference of null pointer (loaded from variable 'p')}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8bca94f2f862468bb877fb70e66a3304</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>foo</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;has_bug&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;has_bug&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_has_bug&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_has_bug&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>62ddaf4e66ff527b230b474b98791ced</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>has_bug</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;triggers_bug&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;triggers_bug&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;bar&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;bar&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1ee3fb0b2fbd9c66e0cc34ca1181ece3</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>triggers_bug</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block__capture_null&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block__capture_null&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a2e7504f29818834127c44ba841f4da8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block_ret&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block_ret&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;q&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;q&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>931be9c3a45b61c0a9c99b4772bd6fca</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_block_ret</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>74</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>74</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block_blockvar&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block_blockvar&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>524a8647c40f017409d858ff70900c1a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_block_blockvar</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block_arg&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_block_arg&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0efdf891fbddf2932f9d434968b94164</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_block_arg</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/inline-unique-reports.c b/test/Analysis/inline-unique-reports.c
index 0044d14e5224..94289a1e8dd9 100644
--- a/test/Analysis/inline-unique-reports.c
+++ b/test/Analysis/inline-unique-reports.c
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -o %t > /dev/null 2>&1
-// RUN: FileCheck -input-file %t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/inline-unique-reports.c.plist -
static inline bug(int *p) {
*p = 0xDEADBEEF;
@@ -16,258 +16,3 @@ void test_bug_2() {
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>15</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;bug&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;bug&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>4</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_bug_2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_bug_2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>4</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>4</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a6ef969f9d5a84fe3b6d153fa488020a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>bug</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp
index c362fc93090b..2b31460330e4 100644
--- a/test/Analysis/inline.cpp
+++ b/test/Analysis/inline.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
void clang_analyzer_checkInlined(bool);
diff --git a/test/Analysis/inlining/InlineObjCClassMethod.m b/test/Analysis/inlining/InlineObjCClassMethod.m
index bb869c5e5297..11b2d63afa59 100644
--- a/test/Analysis/inlining/InlineObjCClassMethod.m
+++ b/test/Analysis/inlining/InlineObjCClassMethod.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=dynamic-bifurcate -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=dynamic-bifurcate -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_checkInlined(int);
void clang_analyzer_eval(int);
diff --git a/test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.c.plist b/test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.c.plist
new file mode 100644
index 000000000000..184aa195e376
--- /dev/null
+++ b/test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.c.plist
@@ -0,0 +1,653 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>21</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;use&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;use&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testSimple&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testSimple&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5c273b7f0421359833fde3f06e8a5c07</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>use</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>5</integer>
+ <integer>6</integer>
+ <integer>10</integer>
+ <integer>15</integer>
+ <integer>18</integer>
+ <integer>19</integer>
+ <integer>21</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;ptr&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;ptr&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;passThrough&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;passThrough&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testChainedCalls&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testChainedCalls&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;use2&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;use2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;passThrough&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;passThrough&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>27</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1d1fa98a8e9fbfa90777dac9fc2795a8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>use2</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>28</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>10</integer>
+ <integer>15</integer>
+ <integer>27</integer>
+ <integer>28</integer>
+ <integer>32</integer>
+ <integer>33</integer>
+ <integer>38</integer>
+ <integer>39</integer>
+ <integer>41</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/inlining/eager-reclamation-path-notes.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.cpp.plist b/test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.cpp.plist
new file mode 100644
index 000000000000..cc699ae1d154
--- /dev/null
+++ b/test/Analysis/inlining/Inputs/expected-plists/eager-reclamation-path-notes.cpp.plist
@@ -0,0 +1,377 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getNullWrapper&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getNullWrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;memberCallBaseDisappears&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;memberCallBaseDisappears&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>9</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>10</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer</string>
+ <key>message</key>
+ <string>Returning null pointer</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getNullWrapper&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getNullWrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;ptr&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;ptr&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is null</string>
+ <key>message</key>
+ <string>Called C++ object pointer is null</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is null</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is null</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f4a4cee851880ebbe93d3b657920ebe9</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>memberCallBaseDisappears</string>
+ <key>issue_hash_function_offset</key><string>19</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>33</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>9</integer>
+ <integer>10</integer>
+ <integer>14</integer>
+ <integer>24</integer>
+ <integer>30</integer>
+ <integer>31</integer>
+ <integer>33</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/inlining/eager-reclamation-path-notes.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/inlining/Inputs/expected-plists/path-notes.c.plist b/test/Analysis/inlining/Inputs/expected-plists/path-notes.c.plist
new file mode 100644
index 000000000000..d9001556a2a8
--- /dev/null
+++ b/test/Analysis/inlining/Inputs/expected-plists/path-notes.c.plist
@@ -0,0 +1,3780 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;zero&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;zero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testZero&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>5</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>6</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;zero&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;zero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>11</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>52499a849b132453be19ec9167d8c021</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testZero</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>14</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>5</integer>
+ <integer>6</integer>
+ <integer>10</integer>
+ <integer>11</integer>
+ <integer>14</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;a&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;a&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>19</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>cb893891b6a08ee4b7dc3d0c11df856e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCheck</string>
+ <key>issue_hash_function_offset</key><string>6</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>18</integer>
+ <integer>19</integer>
+ <integer>24</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;a&apos; initialized here</string>
+ <key>message</key>
+ <string>&apos;a&apos; initialized here</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;a&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;a&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ec20b5e53a72c82d442b3ca04c81e138</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testInitCheck</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>39</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>31</integer>
+ <integer>32</integer>
+ <integer>34</integer>
+ <integer>39</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Value assigned to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Value assigned to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;a&apos; is null</string>
+ <key>message</key>
+ <string>Assuming &apos;a&apos; is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1ae8e7c84d15f307abc1df9f5612078b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testStoreCheck</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>51</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>43</integer>
+ <integer>44</integer>
+ <integer>46</integer>
+ <integer>51</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testReturnZero&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testReturnZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d03346854b8f45b55cbd5efe29bf2c8e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testReturnZero</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>65</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>60</integer>
+ <integer>64</integer>
+ <integer>65</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testReturnZero2&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testReturnZero2&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>5a72f98932a4061a833287a12b28ba8b</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testReturnZero2</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>60</integer>
+ <integer>71</integer>
+ <integer>72</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testInitZero&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testInitZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;a&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;a&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6d3745ba4b32e1858de16c61fecf8ed4</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testInitZero</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>60</integer>
+ <integer>78</integer>
+ <integer>79</integer>
+ <integer>83</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testStoreZero&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testStoreZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;a&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2d25b170621486480ca76aaba4c7a0c0</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testStoreZero</string>
+ <key>issue_hash_function_offset</key><string>5</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>92</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>60</integer>
+ <integer>87</integer>
+ <integer>88</integer>
+ <integer>92</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>56</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>57</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>60</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Returning null pointer (loaded from &apos;p&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>103</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;usePointer&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;usePointer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>96</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>567151df0ae29b0f0e1a412114d544dc</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>usePointer</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>56</integer>
+ <integer>57</integer>
+ <integer>60</integer>
+ <integer>96</integer>
+ <integer>97</integer>
+ <integer>101</integer>
+ <integer>103</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;setFieldToNull&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;setFieldToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testSetFieldToNull&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testSetFieldToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>113</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>113</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>113</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>113</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>113</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to field &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to field &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;setFieldToNull&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;setFieldToNull&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>117</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>7849ab11af99aee1e3603a24ae95cdfd</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testSetFieldToNull</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>119</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>112</integer>
+ <integer>113</integer>
+ <integer>116</integer>
+ <integer>117</integer>
+ <integer>119</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to field &apos;p&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to field &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>131</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>3ccb5e7e2cc82aba5c28a1cc873c83a1</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>132</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>130</integer>
+ <integer>131</integer>
+ <integer>132</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>137</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>19292468c6c6f83fbbdb2ff072bb2ae8</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test4</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>139</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>136</integer>
+ <integer>137</integer>
+ <integer>139</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;interestingCallee&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;interestingCallee&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testBoringCalleeOfInterestingCallee&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testBoringCalleeOfInterestingCallee&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>146</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>The value 0 is assigned to &apos;x&apos;</string>
+ <key>message</key>
+ <string>The value 0 is assigned to &apos;x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>147</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>148</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;interestingCallee&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;interestingCallee&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>fcd480c0f73d071bac6f908387893e26</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testBoringCalleeOfInterestingCallee</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>155</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>143</integer>
+ <integer>146</integer>
+ <integer>147</integer>
+ <integer>148</integer>
+ <integer>151</integer>
+ <integer>152</integer>
+ <integer>153</integer>
+ <integer>155</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/inlining/path-notes.c</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist b/test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist
new file mode 100644
index 000000000000..f517d4dddbc6
--- /dev/null
+++ b/test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist
@@ -0,0 +1,5227 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>31</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>32</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>34</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;~Bar&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;~Bar&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>23</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>24</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling constructor for &apos;Foo&apos;</string>
+ <key>message</key>
+ <string>Calling constructor for &apos;Foo&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;~Bar&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;~Bar&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>12</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>13</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;Foo::use&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;Foo::use&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Entered call from constructor for &apos;Foo&apos;</string>
+ <key>message</key>
+ <string>Entered call from constructor for &apos;Foo&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>7</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>3</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2bf06135909de50c70d8390e77bddf9e</string>
+ <key>issue_context_kind</key><string>C++ method</string>
+ <key>issue_context</key><string>use</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>8</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>7</integer>
+ <integer>8</integer>
+ <integer>12</integer>
+ <integer>13</integer>
+ <integer>21</integer>
+ <integer>23</integer>
+ <integer>24</integer>
+ <integer>30</integer>
+ <integer>31</integer>
+ <integer>32</integer>
+ <integer>34</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>44</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>46</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;method&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;method&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testAnonymous&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testAnonymous&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>40</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>efde323086a985fe1e8ccc6cd0123c12</string>
+ <key>issue_context_kind</key><string>C++ method</string>
+ <key>issue_context</key><string>method</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>41</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>37</integer>
+ <integer>38</integer>
+ <integer>40</integer>
+ <integer>41</integer>
+ <integer>44</integer>
+ <integer>46</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>110</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling implicit default constructor for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Calling implicit default constructor for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>112</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling default constructor for &apos;Dereferencer&apos;</string>
+ <key>message</key>
+ <string>Calling default constructor for &apos;Dereferencer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from default constructor for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Entered call from default constructor for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>62</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8162ef7a27137328a4a7a131e8d52cbe</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>63</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>62</integer>
+ <integer>63</integer>
+ <integer>93</integer>
+ <integer>109</integer>
+ <integer>110</integer>
+ <integer>112</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling implicit copy constructor for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Calling implicit copy constructor for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling copy constructor for &apos;Dereferencer&apos;</string>
+ <key>message</key>
+ <string>Calling copy constructor for &apos;Dereferencer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from copy constructor for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Entered call from copy constructor for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>67</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>675157873c1414a885eb1f429b26f389</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>68</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>67</integer>
+ <integer>68</integer>
+ <integer>93</integer>
+ <integer>117</integer>
+ <integer>118</integer>
+ <integer>120</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>126</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>128</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling defaulted move constructor for &apos;MovableWrapper&apos;</string>
+ <key>message</key>
+ <string>Calling defaulted move constructor for &apos;MovableWrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>102</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling move constructor for &apos;Dereferencer&apos;</string>
+ <key>message</key>
+ <string>Calling move constructor for &apos;Dereferencer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from move constructor for &apos;MovableWrapper&apos;</string>
+ <key>message</key>
+ <string>Entered call from move constructor for &apos;MovableWrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>aff5e83726a1ce1144580e4c80bde47c</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>72</integer>
+ <integer>73</integer>
+ <integer>102</integer>
+ <integer>125</integer>
+ <integer>126</integer>
+ <integer>128</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>133</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>133</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling implicit copy assignment operator for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Calling implicit copy assignment operator for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>136</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling copy assignment operator for &apos;Dereferencer&apos;</string>
+ <key>message</key>
+ <string>Calling copy assignment operator for &apos;Dereferencer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from copy assignment operator for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Entered call from copy assignment operator for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>77</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>9484c73e190dfe4b8c6c5bdfad9700c1</string>
+ <key>issue_context_kind</key><string>C++ method</string>
+ <key>issue_context</key><string>operator=</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>78</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>62</integer>
+ <integer>63</integer>
+ <integer>77</integer>
+ <integer>78</integer>
+ <integer>93</integer>
+ <integer>132</integer>
+ <integer>133</integer>
+ <integer>134</integer>
+ <integer>136</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>142</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling defaulted move assignment operator for &apos;MovableWrapper&apos;</string>
+ <key>message</key>
+ <string>Calling defaulted move assignment operator for &apos;MovableWrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>105</integer>
+ <key>col</key><integer>63</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling move assignment operator for &apos;Dereferencer&apos;</string>
+ <key>message</key>
+ <string>Calling move assignment operator for &apos;Dereferencer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from move assignment operator for &apos;MovableWrapper&apos;</string>
+ <key>message</key>
+ <string>Entered call from move assignment operator for &apos;MovableWrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>82</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a0f0ac76cf282b61236bfac7eb2eca62</string>
+ <key>issue_context_kind</key><string>C++ method</string>
+ <key>issue_context</key><string>operator=</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>83</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>54</integer>
+ <integer>55</integer>
+ <integer>62</integer>
+ <integer>63</integer>
+ <integer>82</integer>
+ <integer>83</integer>
+ <integer>100</integer>
+ <integer>105</integer>
+ <integer>141</integer>
+ <integer>142</integer>
+ <integer>143</integer>
+ <integer>145</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;globalPtr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>151</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling implicit destructor for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Calling implicit destructor for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>93</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>153</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;~Dereferencer&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;~Dereferencer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from destructor for &apos;Wrapper&apos;</string>
+ <key>message</key>
+ <string>Entered call from destructor for &apos;Wrapper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>87</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>74b213f52cad2a4cbfcc8c5766bdd974</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>62</integer>
+ <integer>63</integer>
+ <integer>87</integer>
+ <integer>88</integer>
+ <integer>93</integer>
+ <integer>149</integer>
+ <integer>150</integer>
+ <integer>151</integer>
+ <integer>153</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>160</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning zero</string>
+ <key>message</key>
+ <string>Returning zero</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZero&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>29</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>0d5730cf85cea686ed80d788ab666603</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>173</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>159</integer>
+ <integer>160</integer>
+ <integer>172</integer>
+ <integer>173</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZeroByRef&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZeroByRef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>164</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testRef&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testRef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>164</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>164</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>165</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>The value 0 is assigned to &apos;zeroVar&apos;</string>
+ <key>message</key>
+ <string>The value 0 is assigned to &apos;zeroVar&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>166</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>168</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning zero (reference to &apos;zeroVar&apos;)</string>
+ <key>message</key>
+ <string>Returning zero (reference to &apos;zeroVar&apos;)</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZeroByRef&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZeroByRef&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>992e0f2917d29d0977d09ee64b3d10ef</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testRef</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>180</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>164</integer>
+ <integer>165</integer>
+ <integer>166</integer>
+ <integer>168</integer>
+ <integer>179</integer>
+ <integer>180</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;x&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>188</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning null reference</string>
+ <key>message</key>
+ <string>Returning null reference</string>
+ </dict>
+ </array>
+ <key>description</key><string>Returning null reference</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Returning null reference</string>
+ <key>check_name</key><string>core.uninitialized.UndefReturn</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ece17cf25bc055cbc118d903744a00cf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>returnNullReference</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>190</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>187</integer>
+ <integer>188</integer>
+ <integer>190</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ <key>message</key>
+ <string>&apos;p&apos; initialized to a null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>203</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>205</integer>
+ <key>col</key><integer>24</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling constructor for &apos;FooWithInitializer&apos;</string>
+ <key>message</key>
+ <string>Calling constructor for &apos;FooWithInitializer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testPathNoteOnInitializer&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testPathNoteOnInitializer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;f.ptr&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;f.ptr&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>31</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>196</integer>
+ <key>col</key><integer>33</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;ptr&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;ptr&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;ptr&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>32677550226a34f422a4165a34f6a124</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>197</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>196</integer>
+ <integer>197</integer>
+ <integer>202</integer>
+ <integer>203</integer>
+ <integer>205</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>210</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>210</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>210</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;y&apos; initialized here</string>
+ <key>message</key>
+ <string>&apos;y&apos; initialized here</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>210</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>210</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Storing null pointer value</string>
+ <key>message</key>
+ <string>Storing null pointer value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>211</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;y&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;y&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;y&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>b5460cc5ca67af5b9f4943d7117f9bcf</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testNonPrintableAssignment</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>212</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>209</integer>
+ <integer>210</integer>
+ <integer>211</integer>
+ <integer>212</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Null pointer value stored to &apos;d.x&apos;</string>
+ <key>message</key>
+ <string>Null pointer value stored to &apos;d.x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>220</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>749bda64658e48896477213e90176f5e</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>test</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>221</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>219</integer>
+ <integer>220</integer>
+ <integer>221</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>234</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>2f9098b97145118cf80f1c9f2b9f8a90</string>
+ <key>issue_context_kind</key><string>C++ method</string>
+ <key>issue_context</key><string>testGetDerefExprOnMemberExprWithADot</string>
+ <key>issue_hash_function_offset</key><string>4</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>237</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>233</integer>
+ <integer>234</integer>
+ <integer>237</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>242</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>242</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>242</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;arr&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;arr&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>242</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>242</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>2</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of undefined pointer value</string>
+ <key>message</key>
+ <string>Dereference of undefined pointer value</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of undefined pointer value</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of undefined pointer value</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>41b38aba8763180af245befa02f63d61</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testGetDerefExprOnMemberExprWithADot</string>
+ <key>issue_hash_function_offset</key><string>2</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>243</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>241</integer>
+ <integer>242</integer>
+ <integer>243</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;val&apos; initialized here</string>
+ <key>message</key>
+ <string>&apos;val&apos; initialized here</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>254</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>259</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Called C++ object pointer is null</string>
+ <key>message</key>
+ <string>Called C++ object pointer is null</string>
+ </dict>
+ </array>
+ <key>description</key><string>Called C++ object pointer is null</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Called C++ object pointer is null</string>
+ <key>check_name</key><string>core.CallAndMessage</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>8b577b362ffa5a7290d00d03635c1fca</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testDeclRefExprToReferenceInGetDerefExpr</string>
+ <key>issue_hash_function_offset</key><string>8</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>261</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>253</integer>
+ <integer>254</integer>
+ <integer>259</integer>
+ <integer>261</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>38</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing the value 0 via 2nd parameter &apos;two&apos;</string>
+ <key>message</key>
+ <string>Passing the value 0 via 2nd parameter &apos;two&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>273</integer>
+ <key>col</key><integer>41</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;generateNoteOnDefaultArgument&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;generateNoteOnDefaultArgument&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;callGenerateNoteOnDefaultArgument&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;callGenerateNoteOnDefaultArgument&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>268</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>269</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>269</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>269</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>269</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>269</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>f7fcdbc77cfb95588c0e5b606288013d</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>generateNoteOnDefaultArgument</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>269</integer>
+ <key>col</key><integer>13</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>268</integer>
+ <integer>269</integer>
+ <integer>272</integer>
+ <integer>273</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>296</integer>
+ <key>col</key><integer>16</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;~Outer&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;~Outer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;test&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>289</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>290</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;~Inner&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;~Inner&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;~Outer&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;~Outer&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>280</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>28</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>ff61a6b893cd2d64c7ccaa2a9805311d</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>281</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>280</integer>
+ <integer>281</integer>
+ <integer>289</integer>
+ <integer>290</integer>
+ <integer>295</integer>
+ <integer>296</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/inlining/path-notes.cpp</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/inlining/Inputs/expected-plists/path-notes.m.plist b/test/Analysis/inlining/Inputs/expected-plists/path-notes.m.plist
new file mode 100644
index 000000000000..1974e7ab2541
--- /dev/null
+++ b/test/Analysis/inlining/Inputs/expected-plists/path-notes.m.plist
@@ -0,0 +1,2001 @@
+<?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>clang_version</key>
+<string>clang version 8.0.0 </string>
+ <key>diagnostics</key>
+ <array>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing nil object reference via 1st parameter &apos;x&apos;</string>
+ <key>message</key>
+ <string>Passing nil object reference via 1st parameter &apos;x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;getZeroIfNil&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;getZeroIfNil&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testReturnZeroIfNil&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testReturnZeroIfNil&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>72</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>&apos;p&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;p&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>73</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning null pointer</string>
+ <key>message</key>
+ <string>Returning null pointer</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>18</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;getZeroIfNil&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;getZeroIfNil&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>22</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer</string>
+ <key>message</key>
+ <string>Dereference of null pointer</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>24947a6942bfa6030ab81e53a201d816</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testReturnZeroIfNil</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>79</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>72</integer>
+ <integer>73</integer>
+ <integer>78</integer>
+ <integer>79</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>88</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;dispatch_sync&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;dispatch_sync&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;dispatch_sync&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;dispatch_sync&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>97</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>The value 0 is assigned to &apos;x&apos;</string>
+ <key>message</key>
+ <string>The value 0 is assigned to &apos;x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Returning to caller</string>
+ <key>message</key>
+ <string>Returning to caller</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>99</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from &apos;dispatch_sync&apos;</string>
+ <key>message</key>
+ <string>Returning from &apos;dispatch_sync&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>94</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>14</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Division by zero</string>
+ <key>message</key>
+ <string>Division by zero</string>
+ </dict>
+ </array>
+ <key>description</key><string>Division by zero</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Division by zero</string>
+ <key>check_name</key><string>core.DivideZero</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>fd12d9853f5c0f7398305ff4047f4848</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testDispatchSyncInlining</string>
+ <key>issue_hash_function_offset</key><string>14</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>101</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>7</integer>
+ <integer>87</integer>
+ <integer>88</integer>
+ <integer>90</integer>
+ <integer>94</integer>
+ <integer>97</integer>
+ <integer>101</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>109</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>15</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;dispatch_sync&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;dispatch_sync&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>120</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Calling anonymous block</string>
+ <key>message</key>
+ <string>Calling anonymous block</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;dispatch_sync&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;dispatch_sync&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>114</integer>
+ <key>col</key><integer>30</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>9</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ <key>message</key>
+ <string>&apos;x&apos; declared without an initial value</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>116</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>2</integer>
+ <key>extended_message</key>
+ <string>Variable &apos;x&apos; is uninitialized when captured by block</string>
+ <key>message</key>
+ <string>Variable &apos;x&apos; is uninitialized when captured by block</string>
+ </dict>
+ </array>
+ <key>description</key><string>Variable &apos;x&apos; is uninitialized when captured by block</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>uninitialized variable captured by block</string>
+ <key>check_name</key><string>core.uninitialized.CapturedBlockVariable</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>6763f0438bcb4337c8f8c9863b35b8c1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>118</integer>
+ <key>col</key><integer>5</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>7</integer>
+ <integer>105</integer>
+ <integer>109</integer>
+ <integer>111</integer>
+ <integer>114</integer>
+ <integer>116</integer>
+ <integer>118</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>143</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming pointer value is null</string>
+ <key>message</key>
+ <string>Assuming pointer value is null</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>145</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming the condition is false</string>
+ <key>message</key>
+ <string>Assuming the condition is false</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>150</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>26</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>27</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>&apos;getPtr&apos; not called because the receiver is nil</string>
+ <key>message</key>
+ <string>&apos;getPtr&apos; not called because the receiver is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>35</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
+ <key>message</key>
+ <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>25</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>152</integer>
+ <key>col</key><integer>36</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling &apos;testNilReceiverHelper&apos;</string>
+ <key>message</key>
+ <string>Calling &apos;testNilReceiverHelper&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from &apos;testNilReceiver&apos;</string>
+ <key>message</key>
+ <string>Entered call from &apos;testNilReceiver&apos;</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>134</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>message</key>
+ <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ </dict>
+ </array>
+ <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
+ <key>category</key><string>Logic error</string>
+ <key>type</key><string>Dereference of null pointer</string>
+ <key>check_name</key><string>core.NullDereference</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>d32b4cd912950f7b38ae28dbf29d9e63</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testNilReceiverHelper</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>135</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>134</integer>
+ <integer>135</integer>
+ <integer>139</integer>
+ <integer>143</integer>
+ <integer>145</integer>
+ <integer>150</integer>
+ <integer>152</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Assuming &apos;myNil&apos; is nil</string>
+ <key>message</key>
+ <string>Assuming &apos;myNil&apos; is nil</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>7</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>159</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>19</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>23</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Array element cannot be nil</string>
+ <key>message</key>
+ <string>Array element cannot be nil</string>
+ </dict>
+ </array>
+ <key>description</key><string>Array element cannot be nil</string>
+ <key>category</key><string>API Misuse (Apple)</string>
+ <key>type</key><string>nil argument</string>
+ <key>check_name</key><string>osx.cocoa.NilArg</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a90589ba5d063fbfecc615bf06f84f5a</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testCreateArrayLiteral</string>
+ <key>issue_hash_function_offset</key><string>3</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>161</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>158</integer>
+ <integer>159</integer>
+ <integer>161</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>167</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>167</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of NSObject with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>11</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>47</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>12</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>34</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object autoreleased</string>
+ <key>message</key>
+ <string>Object autoreleased</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>170</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ <key>message</key>
+ <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
+ </dict>
+ </array>
+ <key>description</key><string>Object autoreleased too many times</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Object autoreleased too many times</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>a3c91a7a52619d81ebe032dcc49ebb93</string>
+ <key>issue_context_kind</key><string>function</string>
+ <key>issue_context</key><string>testAutoreleaseTakesEffectInDispatch</string>
+ <key>issue_hash_function_offset</key><string>11</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>177</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>13</integer>
+ <integer>166</integer>
+ <integer>167</integer>
+ <integer>168</integer>
+ <integer>170</integer>
+ <integer>175</integer>
+ <integer>177</integer>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>files</key>
+ <array>
+ <string>/clang/test/Analysis/inlining/path-notes.m</string>
+ </array>
+</dict>
+</plist>
diff --git a/test/Analysis/inlining/containers.cpp b/test/Analysis/inlining/containers.cpp
index ffa3b511344a..e88787c08311 100644
--- a/test/Analysis/inlining/containers.cpp
+++ b/test/Analysis/inlining/containers.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -verify %s
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DINLINE=1 -verify %s
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -DTEST_INLINABLE_ALLOCATORS -verify %s
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DTEST_INLINABLE_ALLOCATORS -DINLINE=1 -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DINLINE=1 -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -DTEST_INLINABLE_ALLOCATORS -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DTEST_INLINABLE_ALLOCATORS -DINLINE=1 -verify -analyzer-config eagerly-assume=false %s
#ifndef HEADER
diff --git a/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp b/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp
index 02084839c55b..531fc3485450 100644
--- a/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp
+++ b/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=dynamic-bifurcate -verify -Wno-reinterpret-base-class %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=dynamic-bifurcate -verify -Wno-reinterpret-base-class -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/inlining/eager-reclamation-path-notes.c b/test/Analysis/inlining/eager-reclamation-path-notes.c
index a31ab9ed0ad9..8dfd14dd34dd 100644
--- a/test/Analysis/inlining/eager-reclamation-path-notes.c
+++ b/test/Analysis/inlining/eager-reclamation-path-notes.c
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config graph-trim-interval=5 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/eager-reclamation-path-notes.c.plist -
void use(int *ptr, int val) {
*ptr = val; // expected-warning {{Dereference of null pointer (loaded from variable 'ptr')}}
@@ -43,616 +43,3 @@ void testChainedCalls() {
// expected-note@-2 {{Calling 'passThrough'}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;use&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;use&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testSimple&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testSimple&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5c273b7f0421359833fde3f06e8a5c07</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>use</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;ptr&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;ptr&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;passThrough&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;passThrough&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testChainedCalls&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testChainedCalls&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;ptr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;use2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;use2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;passThrough&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;passThrough&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1d1fa98a8e9fbfa90777dac9fc2795a8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>use2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/inlining/eager-reclamation-path-notes.cpp b/test/Analysis/inlining/eager-reclamation-path-notes.cpp
index 9a9b01c3bdd4..7cbda91b6573 100644
--- a/test/Analysis/inlining/eager-reclamation-path-notes.cpp
+++ b/test/Analysis/inlining/eager-reclamation-path-notes.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/eager-reclamation-path-notes.cpp.plist -
typedef struct {
int getValue();
@@ -34,355 +34,3 @@ int memberCallBaseDisappears() {
// expected-note@-1 {{Called C++ object pointer is null}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getNullWrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getNullWrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;memberCallBaseDisappears&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;memberCallBaseDisappears&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getNullWrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getNullWrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;ptr&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;ptr&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f4a4cee851880ebbe93d3b657920ebe9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>memberCallBaseDisappears</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>19</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/inlining/false-positive-suppression.c b/test/Analysis/inlining/false-positive-suppression.c
index 4d472e0861e0..e060eb1d1e88 100644
--- a/test/Analysis/inlining/false-positive-suppression.c
+++ b/test/Analysis/inlining/false-positive-suppression.c
@@ -1,6 +1,6 @@
-// RUN: %clang_analyze_cc1 -analyzer-eagerly-assume -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-eagerly-assume -analyzer-checker=core -verify -DSUPPRESSED=1 %s
-// RUN: %clang_analyze_cc1 -analyzer-eagerly-assume -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -DSUPPRESSED=1 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
int opaquePropertyCheck(void *object);
int coin();
diff --git a/test/Analysis/inlining/path-notes.c b/test/Analysis/inlining/path-notes.c
index 15441d4a3ccd..253ff949dc51 100644
--- a/test/Analysis/inlining/path-notes.c
+++ b/test/Analysis/inlining/path-notes.c
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config suppress-null-return-paths=false -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/path-notes.c.plist -
void zero(int **p) {
*p = 0;
@@ -156,3629 +156,3 @@ int testBoringCalleeOfInterestingCallee() {
// expected-note@-1{{Division by zero}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;zero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;zero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;a&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;a&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;zero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;zero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>52499a849b132453be19ec9167d8c021</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testZero</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>cb893891b6a08ee4b7dc3d0c11df856e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCheck</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;a&apos; initialized here</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;a&apos; initialized here</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ec20b5e53a72c82d442b3ca04c81e138</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testInitCheck</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;a&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;a&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1ae8e7c84d15f307abc1df9f5612078b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testStoreCheck</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testReturnZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testReturnZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d03346854b8f45b55cbd5efe29bf2c8e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testReturnZero</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testReturnZero2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testReturnZero2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5a72f98932a4061a833287a12b28ba8b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testReturnZero2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testInitZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testInitZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;a&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;a&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6d3745ba4b32e1858de16c61fecf8ed4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testInitZero</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testStoreZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testStoreZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;a&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;a&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2d25b170621486480ca76aaba4c7a0c0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testStoreZero</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer (loaded from &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;usePointer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;usePointer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testUseOfNullPointer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>567151df0ae29b0f0e1a412114d544dc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>usePointer</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;setFieldToNull&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;setFieldToNull&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testSetFieldToNull&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testSetFieldToNull&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to field &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to field &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;setFieldToNull&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;setFieldToNull&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7849ab11af99aee1e3603a24ae95cdfd</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testSetFieldToNull</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to field &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to field &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3ccb5e7e2cc82aba5c28a1cc873c83a1</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>19292468c6c6f83fbbdb2ff072bb2ae8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test4</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;interestingCallee&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;interestingCallee&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testBoringCalleeOfInterestingCallee&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testBoringCalleeOfInterestingCallee&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;interestingCallee&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;interestingCallee&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fcd480c0f73d071bac6f908387893e26</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testBoringCalleeOfInterestingCallee</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/inlining/path-notes.cpp b/test/Analysis/inlining/path-notes.cpp
index e475399f605f..43859237438f 100644
--- a/test/Analysis/inlining/path-notes.cpp
+++ b/test/Analysis/inlining/path-notes.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config c++-inlining=destructors -std=c++11 -verify -Wno-tautological-undefined-compare %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config c++-inlining=destructors -std=c++11 %s -o %t.plist -Wno-tautological-undefined-compare
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/path-notes.cpp.plist -
class Foo {
public:
@@ -298,4992 +298,3 @@ namespace PR17746 {
}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>32</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;~Bar&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;~Bar&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling constructor for &apos;Foo&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling constructor for &apos;Foo&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;~Bar&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;~Bar&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;Foo::use&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;Foo::use&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from constructor for &apos;Foo&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from constructor for &apos;Foo&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>7</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2bf06135909de50c70d8390e77bddf9e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
-// CHECK-NEXT: <key>issue_context</key><string>use</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;method&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;method&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testAnonymous&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testAnonymous&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>efde323086a985fe1e8ccc6cd0123c12</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
-// CHECK-NEXT: <key>issue_context</key><string>method</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling implicit default constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling implicit default constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling default constructor for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling default constructor for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from default constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from default constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8162ef7a27137328a4a7a131e8d52cbe</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling implicit copy constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling implicit copy constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling copy constructor for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling copy constructor for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from copy constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from copy constructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>675157873c1414a885eb1f429b26f389</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling defaulted move constructor for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling defaulted move constructor for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling move constructor for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling move constructor for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from move constructor for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from move constructor for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>aff5e83726a1ce1144580e4c80bde47c</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>133</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>133</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling implicit copy assignment operator for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling implicit copy assignment operator for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling copy assignment operator for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling copy assignment operator for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from copy assignment operator for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from copy assignment operator for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>9484c73e190dfe4b8c6c5bdfad9700c1</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
-// CHECK-NEXT: <key>issue_context</key><string>operator=</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling defaulted move assignment operator for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling defaulted move assignment operator for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling move assignment operator for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling move assignment operator for &apos;Dereferencer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from move assignment operator for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from move assignment operator for &apos;MovableWrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a0f0ac76cf282b61236bfac7eb2eca62</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
-// CHECK-NEXT: <key>issue_context</key><string>operator=</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;globalPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling implicit destructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling implicit destructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;~Dereferencer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;~Dereferencer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from destructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from destructor for &apos;Wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;globalPtr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>74b213f52cad2a4cbfcc8c5766bdd974</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZero&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0d5730cf85cea686ed80d788ab666603</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>173</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZeroByRef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZeroByRef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testRef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testRef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to &apos;zeroVar&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to &apos;zeroVar&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>168</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning zero (reference to &apos;zeroVar&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning zero (reference to &apos;zeroVar&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZeroByRef&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZeroByRef&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>992e0f2917d29d0977d09ee64b3d10ef</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testRef</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null reference</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null reference</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Returning null reference</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Returning null reference</string>
-// CHECK-NEXT: <key>check_name</key><string>core.uninitialized.UndefReturn</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ece17cf25bc055cbc118d903744a00cf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>returnNullReference</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling constructor for &apos;FooWithInitializer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling constructor for &apos;FooWithInitializer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testPathNoteOnInitializer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testPathNoteOnInitializer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;f.ptr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;f.ptr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;ptr&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;ptr&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>32677550226a34f422a4165a34f6a124</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>210</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>210</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>210</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;y&apos; initialized here</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;y&apos; initialized here</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>210</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>210</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Storing null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Storing null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>211</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;y&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;y&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;y&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b5460cc5ca67af5b9f4943d7117f9bcf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testNonPrintableAssignment</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>212</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;d.x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;d.x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;x&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>749bda64658e48896477213e90176f5e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2f9098b97145118cf80f1c9f2b9f8a90</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
-// CHECK-NEXT: <key>issue_context</key><string>testGetDerefExprOnMemberExprWithADot</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;arr&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;arr&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of undefined pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of undefined pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of undefined pointer value</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of undefined pointer value</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>41b38aba8763180af245befa02f63d61</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testGetDerefExprOnMemberExprWithADot</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;val&apos; initialized here</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;val&apos; initialized here</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>259</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8b577b362ffa5a7290d00d03635c1fca</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testDeclRefExprToReferenceInGetDerefExpr</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing the value 0 via 2nd parameter &apos;two&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing the value 0 via 2nd parameter &apos;two&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>273</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;generateNoteOnDefaultArgument&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;generateNoteOnDefaultArgument&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callGenerateNoteOnDefaultArgument&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;callGenerateNoteOnDefaultArgument&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>268</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f7fcdbc77cfb95588c0e5b606288013d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>generateNoteOnDefaultArgument</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>269</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>296</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>296</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>296</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;~Outer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;~Outer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;~Inner&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;~Inner&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;~Outer&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;~Outer&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>280</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ff61a6b893cd2d64c7ccaa2a9805311d</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>281</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/inlining/path-notes.m b/test/Analysis/inlining/path-notes.m
index a372dab6bb4d..d48a89197625 100644
--- a/test/Analysis/inlining/path-notes.m
+++ b/test/Analysis/inlining/path-notes.m
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=text -analyzer-config suppress-null-return-paths=false -fblocks -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -fblocks %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/path-notes.m.plist -
typedef struct dispatch_queue_s *dispatch_queue_t;
typedef void (^dispatch_block_t)(void);
@@ -182,1921 +182,3 @@ void testNullDereferenceInDispatch() {
dispatch_once(0, ^{}); // no-warning, don't crash
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing nil object reference via 1st parameter &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing nil object reference via 1st parameter &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;getZeroIfNil&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getZeroIfNil&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testReturnZeroIfNil&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testReturnZeroIfNil&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZeroIfNil&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getZeroIfNil&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>24947a6942bfa6030ab81e53a201d816</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testReturnZeroIfNil</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>99</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>99</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>99</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>99</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fd12d9853f5c0f7398305ff4047f4848</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testDispatchSyncInlining</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>14</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>116</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Variable &apos;x&apos; is uninitialized when captured by block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Variable &apos;x&apos; is uninitialized when captured by block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Variable &apos;x&apos; is uninitialized when captured by block</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>uninitialized variable captured by block</string>
-// CHECK-NEXT: <key>check_name</key><string>core.uninitialized.CapturedBlockVariable</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6763f0438bcb4337c8f8c9863b35b8c1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is false</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;getPtr&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;getPtr&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;testNilReceiverHelper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;testNilReceiverHelper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testNilReceiver&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testNilReceiver&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d32b4cd912950f7b38ae28dbf29d9e63</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testNilReceiverHelper</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;myNil&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;myNil&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Array element cannot be nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Array element cannot be nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Array element cannot be nil</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>nil argument</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.NilArg</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a90589ba5d063fbfecc615bf06f84f5a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCreateArrayLiteral</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>161</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>167</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>167</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>47</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a3c91a7a52619d81ebe032dcc49ebb93</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testAutoreleaseTakesEffectInDispatch</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/inlining/stl.cpp b/test/Analysis/inlining/stl.cpp
index b672be2ba245..6678b5d20d0a 100644
--- a/test/Analysis/inlining/stl.cpp
+++ b/test/Analysis/inlining/stl.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=false -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=true -std=c++11 -DINLINE=1 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=false -std=c++11 -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete,debug.ExprInspection -analyzer-config c++-container-inlining=true -analyzer-config c++-stdlib-inlining=true -std=c++11 -DINLINE=1 -verify -analyzer-config eagerly-assume=false %s
#include "../Inputs/system-header-simulator-cxx.h"
diff --git a/test/Analysis/inner-pointer.cpp b/test/Analysis/inner-pointer.cpp
index 230e3396c59e..81b750d7e5dd 100644
--- a/test/Analysis/inner-pointer.cpp
+++ b/test/Analysis/inner-pointer.cpp
@@ -1,43 +1,9 @@
-//RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer %s -analyzer-output=text -verify
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer \
+// RUN: %s -analyzer-output=text -verify
+#include "Inputs/system-header-simulator-cxx.h"
namespace std {
-typedef int size_type;
-
-template <typename CharT>
-class basic_string {
-public:
- basic_string();
- basic_string(const CharT *s);
-
- ~basic_string();
- void clear();
-
- basic_string &operator=(const basic_string &str);
- basic_string &operator+=(const basic_string &str);
-
- const CharT *c_str() const;
- const CharT *data() const;
- CharT *data();
-
- basic_string &append(size_type count, CharT ch);
- basic_string &assign(size_type count, CharT ch);
- basic_string &erase(size_type index, size_type count);
- basic_string &insert(size_type index, size_type count, CharT ch);
- basic_string &replace(size_type pos, size_type count, const basic_string &str);
- void pop_back();
- void push_back(CharT ch);
- void reserve(size_type new_cap);
- void resize(size_type count);
- void shrink_to_fit();
- void swap(basic_string &other);
-};
-
-typedef basic_string<char> string;
-typedef basic_string<wchar_t> wstring;
-typedef basic_string<char16_t> u16string;
-typedef basic_string<char32_t> u32string;
-
template <typename T>
void func_ref(T &a);
@@ -65,10 +31,10 @@ void deref_after_scope_char(bool cond) {
const char *c, *d;
{
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- d = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
- // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ d = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
std::string s;
const char *c2 = s.c_str();
if (cond) {
@@ -76,11 +42,11 @@ void deref_after_scope_char(bool cond) {
// expected-note@-2 {{Taking true branch}}
// expected-note@-3 {{Assuming 'cond' is 0}}
// expected-note@-4 {{Taking false branch}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
} else {
- consume(d); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
}
@@ -88,22 +54,22 @@ void deref_after_scope_char_data_non_const() {
char *c;
{
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
std::string s;
char *c2 = s.data();
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_scope_wchar_t(bool cond) {
const wchar_t *c, *d;
{
std::wstring s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- d = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
- // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}}
+ d = s.data(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}}
+ } // expected-note {{Inner buffer of 'std::wstring' deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer of 'std::wstring' deallocated by call to destructor}}
std::wstring s;
const wchar_t *c2 = s.c_str();
if (cond) {
@@ -111,11 +77,11 @@ void deref_after_scope_wchar_t(bool cond) {
// expected-note@-2 {{Taking true branch}}
// expected-note@-3 {{Assuming 'cond' is 0}}
// expected-note@-4 {{Taking false branch}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
} else {
- consume(d); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
}
@@ -123,36 +89,36 @@ void deref_after_scope_char16_t_cstr() {
const char16_t *c16;
{
std::u16string s16;
- c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
+ c16 = s16.c_str(); // expected-note {{Pointer to inner buffer of 'std::u16string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::u16string' deallocated by call to destructor}}
std::u16string s16;
const char16_t *c16_2 = s16.c_str();
- consume(c16); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c16); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_scope_char32_t_data() {
const char32_t *c32;
{
std::u32string s32;
- c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
+ c32 = s32.data(); // expected-note {{Pointer to inner buffer of 'std::u32string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::u32string' deallocated by call to destructor}}
std::u32string s32;
const char32_t *c32_2 = s32.data();
- consume(c32); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c32); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void multiple_symbols(bool cond) {
const char *c1, *d1;
{
std::string s1;
- c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- d1 = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
+ c1 = s1.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ d1 = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
const char *local = s1.c_str();
consume(local); // no-warning
- } // expected-note {{Inner pointer invalidated by call to destructor}}
- // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
std::string s2;
const char *c2 = s2.c_str();
if (cond) {
@@ -160,11 +126,11 @@ void multiple_symbols(bool cond) {
// expected-note@-2 {{Taking true branch}}
// expected-note@-3 {{Assuming 'cond' is 0}}
// expected-note@-4 {{Taking false branch}}
- consume(c1); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c1); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
} else {
- consume(d1); // expected-warning {{Use of memory after it is freed}}
- } // expected-note@-1 {{Use of memory after it is freed}}
+ consume(d1); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ } // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_scope_ok(bool cond) {
@@ -183,127 +149,159 @@ void deref_after_scope_ok(bool cond) {
void deref_after_equals() {
const char *c;
std::string s = "hello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s = "world"; // expected-note {{Inner pointer invalidated by call to 'operator='}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s = "world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator='}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_plus_equals() {
const char *c;
std::string s = "hello";
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s += " world"; // expected-note {{Inner pointer invalidated by call to 'operator+='}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s += " world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator+='}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_clear() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.clear(); // expected-note {{Inner pointer invalidated by call to 'clear'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_append() {
const char *c;
std::string s = "hello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.append(2, 'x'); // expected-note {{Inner pointer invalidated by call to 'append'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.append(2, 'x'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'append'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_assign() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.assign(4, 'a'); // expected-note {{Inner pointer invalidated by call to 'assign'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.assign(4, 'a'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'assign'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_erase() {
const char *c;
std::string s = "hello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.erase(0, 2); // expected-note {{Inner pointer invalidated by call to 'erase'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.erase(0, 2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'erase'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_insert() {
const char *c;
std::string s = "ello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.insert(0, 1, 'h'); // expected-note {{Inner pointer invalidated by call to 'insert'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.insert(0, 1, 'h'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'insert'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_replace() {
const char *c;
std::string s = "hello world";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.replace(6, 5, "string"); // expected-note {{Inner pointer invalidated by call to 'replace'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.replace(6, 5, "string"); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'replace'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_pop_back() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.pop_back(); // expected-note {{Inner pointer invalidated by call to 'pop_back'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.pop_back(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'pop_back'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_push_back() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.push_back('c'); // expected-note {{Inner pointer invalidated by call to 'push_back'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.push_back('c'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'push_back'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_reserve() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.reserve(5); // expected-note {{Inner pointer invalidated by call to 'reserve'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.reserve(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'reserve'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_resize() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.resize(5); // expected-note {{Inner pointer invalidated by call to 'resize'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.resize(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'resize'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_shrink_to_fit() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.shrink_to_fit(); // expected-note {{Inner pointer invalidated by call to 'shrink_to_fit'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.shrink_to_fit(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'shrink_to_fit'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_swap() {
const char *c;
std::string s1, s2;
- c = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
- s1.swap(s2); // expected-note {{Inner pointer invalidated by call to 'swap'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s1.swap(s2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'swap'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
+}
+
+struct S {
+ std::string s;
+ const char *name() {
+ return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ // expected-note@-1 {{Pointer to inner buffer of 'std::string' obtained here}}
+ }
+ void clear() {
+ s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}}
+ }
+ ~S() {} // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
+};
+
+void cleared_through_method() {
+ S x;
+ const char *c = x.name(); // expected-note {{Calling 'S::name'}}
+ // expected-note@-1 {{Returning from 'S::name'}}
+ x.clear(); // expected-note {{Calling 'S::clear'}}
+ // expected-note@-1 {{Returning; inner buffer was reallocated}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
+}
+
+void destroyed_through_method() {
+ S y;
+ const char *c = y.name(); // expected-note {{Calling 'S::name'}}
+ // expected-note@-1 {{Returning from 'S::name'}}
+ y.~S(); // expected-note {{Calling '~S'}}
+ // expected-note@-1 {{Returning; inner buffer was deallocated}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
//=---------------------------=//
@@ -313,10 +311,10 @@ void deref_after_swap() {
void STL_func_ref() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- std::func_ref(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ std::func_ref(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void STL_func_const_ref() {
@@ -339,10 +337,10 @@ void func_ptr_known() {
const char *c;
std::string s;
void (*func_ptr)(std::string &) = std::func_ref<std::string>;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- func_ptr(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ func_ptr(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void func_ptr_unknown(void (*func_ptr)(std::string &)) {
@@ -356,8 +354,44 @@ void func_ptr_unknown(void (*func_ptr)(std::string &)) {
void func_default_arg() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- default_arg(3, s); // expected-note {{Inner pointer invalidated by call to 'default_arg'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ default_arg(3, s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'default_arg'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
+}
+
+struct T {
+ std::string to_string() { return s; }
+private:
+ std::string s;
+};
+
+const char *escape_via_return_temp() {
+ T x;
+ return x.to_string().c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-warning@-2 {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-3 {{Inner pointer of container used after re/deallocation}}
+}
+
+const char *escape_via_return_local() {
+ std::string s;
+ return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-warning@-2 {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-3 {{Inner pointer of container used after re/deallocation}}
+}
+
+
+char *c();
+class A {};
+
+void no_CXXRecordDecl() {
+ A a, *b;
+ *(void **)&b = c() + 1;
+ *b = a; // no-crash
+}
+
+void checkReference(std::string &s) {
+ const char *c = s.c_str();
}
diff --git a/test/Analysis/invalid-a-na-ly-zer-con-fig-value.c b/test/Analysis/invalid-a-na-ly-zer-con-fig-value.c
new file mode 100644
index 000000000000..ec967d3c47c2
--- /dev/null
+++ b/test/Analysis/invalid-a-na-ly-zer-con-fig-value.c
@@ -0,0 +1,84 @@
+// Same as invalid-analyzer-config-value.c but without -analyzer-config
+// in the file name, so that argument string pattern matching
+// didn't accidentally match it.
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config notes-as-events=yesplease \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-BOOL-INPUT
+
+// CHECK-BOOL-INPUT: (frontend): invalid input for analyzer-config option
+// CHECK-BOOL-INPUT-SAME: 'notes-as-events', that expects a boolean value
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config notes-as-events=yesplease
+
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config max-inlinable-size=400km/h \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-UINT-INPUT
+
+// CHECK-UINT-INPUT: (frontend): invalid input for analyzer-config option
+// CHECK-UINT-INPUT-SAME: 'max-inlinable-size', that expects an unsigned
+// CHECK-UINT-INPUT-SAME: value
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config max-inlinable-size=400km/h
+
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config ctu-dir=0123012301230123 \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-FILENAME-INPUT
+
+// CHECK-FILENAME-INPUT: (frontend): invalid input for analyzer-config option
+// CHECK-FILENAME-INPUT-SAME: 'ctu-dir', that expects a filename
+// CHECK-FILENAME-INPUT-SAME: value
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config ctu-dir=0123012301230123
+
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config no-false-positives=true \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-CFG
+
+// CHECK-UNKNOWN-CFG: (frontend): unknown analyzer-config 'no-false-positives'
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config no-false-positives=true
+
+
+// Test the driver properly using "analyzer-config-compatibility-mode=true",
+// no longer causing an error on input error.
+// RUN: %clang --analyze %s
+
+// RUN: not %clang --analyze %s \
+// RUN: -Xclang -analyzer-config -Xclang no-false-positives=true \
+// RUN: -Xclang -analyzer-config-compatibility-mode=false \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-NO-COMPAT
+
+// CHECK-NO-COMPAT: error: unknown analyzer-config 'no-false-positives'
+
+// Test the driver properly using "analyzer-config-compatibility-mode=true",
+// even if -analyze isn't specified.
+// RUN: %clang -fsyntax-only -Xclang -analyzer-config\
+// RUN: -Xclang remember=TheVasa %s
+// RUN: %clang -fsyntax-only -Xanalyzer -analyzer-config\
+// RUN: -Xanalyzer remember=TheVasa %s
+// RUN: %clang --analyze -Xanalyzer -analyzer-config\
+// RUN: -Xanalyzer remember=TheVasa %s
+
+// expected-no-diagnostics
+
+int main() {}
diff --git a/test/Analysis/invalid-analyzer-config-value.c b/test/Analysis/invalid-analyzer-config-value.c
new file mode 100644
index 000000000000..f942dd3e6226
--- /dev/null
+++ b/test/Analysis/invalid-analyzer-config-value.c
@@ -0,0 +1,80 @@
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config notes-as-events=yesplease \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-BOOL-INPUT
+
+// CHECK-BOOL-INPUT: (frontend): invalid input for analyzer-config option
+// CHECK-BOOL-INPUT-SAME: 'notes-as-events', that expects a boolean value
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config notes-as-events=yesplease
+
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config max-inlinable-size=400km/h \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-UINT-INPUT
+
+// CHECK-UINT-INPUT: (frontend): invalid input for analyzer-config option
+// CHECK-UINT-INPUT-SAME: 'max-inlinable-size', that expects an unsigned
+// CHECK-UINT-INPUT-SAME: value
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config max-inlinable-size=400km/h
+
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config ctu-dir=0123012301230123 \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-FILENAME-INPUT
+
+// CHECK-FILENAME-INPUT: (frontend): invalid input for analyzer-config option
+// CHECK-FILENAME-INPUT-SAME: 'ctu-dir', that expects a filename
+// CHECK-FILENAME-INPUT-SAME: value
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config ctu-dir=0123012301230123
+
+
+// RUN: not %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config no-false-positives=true \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-UNKNOWN-CFG
+
+// CHECK-UNKNOWN-CFG: (frontend): unknown analyzer-config 'no-false-positives'
+
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config-compatibility-mode=true \
+// RUN: -analyzer-config no-false-positives=true
+
+
+// Test the driver properly using "analyzer-config-compatibility-mode=true",
+// no longer causing an error on input error.
+// RUN: %clang --analyze %s
+
+// RUN: not %clang --analyze %s \
+// RUN: -Xclang -analyzer-config -Xclang no-false-positives=true \
+// RUN: -Xclang -analyzer-config-compatibility-mode=false \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-NO-COMPAT
+
+// CHECK-NO-COMPAT: error: unknown analyzer-config 'no-false-positives'
+
+// Test the driver properly using "analyzer-config-compatibility-mode=true",
+// even if -analyze isn't specified.
+// RUN: %clang -fsyntax-only -Xclang -analyzer-config\
+// RUN: -Xclang remember=TheVasa %s
+// RUN: %clang -fsyntax-only -Xanalyzer -analyzer-config\
+// RUN: -Xanalyzer remember=TheVasa %s
+// RUN: %clang --analyze -Xanalyzer -analyzer-config\
+// RUN: -Xanalyzer remember=TheVasa %s
+
+// expected-no-diagnostics
+
+int main() {}
diff --git a/test/Analysis/invalidated-iterator.cpp b/test/Analysis/invalidated-iterator.cpp
new file mode 100644
index 000000000000..1151838bb843
--- /dev/null
+++ b/test/Analysis/invalidated-iterator.cpp
@@ -0,0 +1,399 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.InvalidatedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.InvalidatedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+void bad_copy_assign_operator_list1(std::list<int> &L1,
+ const std::list<int> &L2) {
+ auto i0 = L1.cbegin();
+ L1 = L2;
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_copy_assign_operator_vector1(std::vector<int> &V1,
+ const std::vector<int> &V2) {
+ auto i0 = V1.cbegin();
+ V1 = V2;
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_copy_assign_operator_deque1(std::deque<int> &D1,
+ const std::deque<int> &D2) {
+ auto i0 = D1.cbegin();
+ D1 = D2;
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_copy_assign_operator_forward_list1(std::forward_list<int> &FL1,
+ const std::forward_list<int> &FL2) {
+ auto i0 = FL1.cbegin();
+ FL1 = FL2;
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_assign_list1(std::list<int> &L, int n) {
+ auto i0 = L.cbegin();
+ L.assign(10, n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_assign_vector1(std::vector<int> &V, int n) {
+ auto i0 = V.cbegin();
+ V.assign(10, n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_assign_deque1(std::deque<int> &D, int n) {
+ auto i0 = D.cbegin();
+ D.assign(10, n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_assign_forward_list1(std::forward_list<int> &FL, int n) {
+ auto i0 = FL.cbegin();
+ FL.assign(10, n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_clear_list1(std::list<int> &L) {
+ auto i0 = L.cend();
+ L.clear();
+ --i0; // no-warning
+}
+
+void bad_clear_list1(std::list<int> &L) {
+ auto i0 = L.cbegin(), i1 = L.cend();
+ L.clear();
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_clear_vector1(std::vector<int> &V) {
+ auto i0 = V.cbegin(), i1 = V.cend();
+ V.clear();
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_clear_deque1(std::deque<int> &D) {
+ auto i0 = D.cbegin(), i1 = D.cend();
+ D.clear();
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_push_back_list1(std::list<int> &L, int n) {
+ auto i0 = L.cbegin(), i1 = L.cend();
+ L.push_back(n);
+ *i0; // no-warning
+ --i1; // no-warning
+}
+
+void good_push_back_vector1(std::vector<int> &V, int n) {
+ auto i0 = V.cbegin(), i1 = V.cend();
+ V.push_back(n);
+ *i0; // no-warning
+}
+
+void bad_push_back_vector1(std::vector<int> &V, int n) {
+ auto i0 = V.cbegin(), i1 = V.cend();
+ V.push_back(n);
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_push_back_deque1(std::deque<int> &D, int n) {
+ auto i0 = D.cbegin(), i1 = D.cend();
+ D.push_back(n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_emplace_back_list1(std::list<int> &L, int n) {
+ auto i0 = L.cbegin(), i1 = L.cend();
+ L.emplace_back(n);
+ *i0; // no-warning
+ --i1; // no-warning
+}
+
+void good_emplace_back_vector1(std::vector<int> &V, int n) {
+ auto i0 = V.cbegin(), i1 = V.cend();
+ V.emplace_back(n);
+ *i0; // no-warning
+}
+
+void bad_emplace_back_vector1(std::vector<int> &V, int n) {
+ auto i0 = V.cbegin(), i1 = V.cend();
+ V.emplace_back(n);
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_emplace_back_deque1(std::deque<int> &D, int n) {
+ auto i0 = D.cbegin(), i1 = D.cend();
+ D.emplace_back(n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_pop_back_list1(std::list<int> &L, int n) {
+ auto i0 = L.cbegin(), i1 = L.cend(), i2 = i1--;
+ L.pop_back();
+ *i0; // no-warning
+ *i2; // no-warning
+}
+
+void bad_pop_back_list1(std::list<int> &L, int n) {
+ auto i0 = L.cbegin(), i1 = L.cend(), i2 = i1--;
+ L.pop_back();
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_pop_back_vector1(std::vector<int> &V, int n) {
+ auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--;
+ V.pop_back();
+ *i0; // no-warning
+}
+
+void bad_pop_back_vector1(std::vector<int> &V, int n) {
+ auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--;
+ V.pop_back();
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+ --i2; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_pop_back_deque1(std::deque<int> &D, int n) {
+ auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--;
+ D.pop_back();
+ *i0; // no-warning
+}
+
+void bad_pop_back_deque1(std::deque<int> &D, int n) {
+ auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--;
+ D.pop_back();
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+ --i2; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_push_front_list1(std::list<int> &L, int n) {
+ auto i0 = L.cbegin(), i1 = L.cend();
+ L.push_front(n);
+ *i0; // no-warning
+ --i1; // no-warning
+}
+
+void bad_push_front_deque1(std::deque<int> &D, int n) {
+ auto i0 = D.cbegin(), i1 = D.cend();
+ D.push_front(n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_push_front_forward_list1(std::forward_list<int> &FL, int n) {
+ auto i0 = FL.cbegin(), i1 = FL.cend();
+ FL.push_front(n);
+ *i0; // no-warning
+}
+
+void good_emplace_front_list1(std::list<int> &L, int n) {
+ auto i0 = L.cbegin(), i1 = L.cend();
+ L.emplace_front(n);
+ *i0; // no-warning
+ --i1; // no-warning
+}
+
+void bad_emplace_front_deque1(std::deque<int> &D, int n) {
+ auto i0 = D.cbegin(), i1 = D.cend();
+ D.emplace_front(n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ --i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_emplace_front_forward_list1(std::forward_list<int> &FL, int n) {
+ auto i0 = FL.cbegin(), i1 = FL.cend();
+ FL.emplace_front(n);
+ *i0; // no-warning
+}
+
+void good_pop_front_list1(std::list<int> &L, int n) {
+ auto i1 = L.cbegin(), i0 = i1++;
+ L.pop_front();
+ *i1; // no-warning
+}
+
+void bad_pop_front_list1(std::list<int> &L, int n) {
+ auto i1 = L.cbegin(), i0 = i1++;
+ L.pop_front();
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_pop_front_deque1(std::deque<int> &D, int n) {
+ auto i1 = D.cbegin(), i0 = i1++;
+ D.pop_front();
+ *i1; // no-warning
+}
+
+void bad_pop_front_deque1(std::deque<int> &D, int n) {
+ auto i1 = D.cbegin(), i0 = i1++;
+ D.pop_front();
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_pop_front_forward_list1(std::forward_list<int> &FL, int n) {
+ auto i1 = FL.cbegin(), i0 = i1++;
+ FL.pop_front();
+ *i1; // no-warning
+}
+
+void bad_pop_front_forward_list1(std::forward_list<int> &FL, int n) {
+ auto i1 = FL.cbegin(), i0 = i1++;
+ FL.pop_front();
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_insert_list1(std::list<int> &L, int n) {
+ auto i1 = L.cbegin(), i0 = i1++;
+ L.insert(i1, n);
+ *i0; // no-warning
+ *i1; // no-warning
+}
+
+void good_insert_vector1(std::vector<int> &V, int n) {
+ auto i1 = V.cbegin(), i0 = i1++;
+ V.insert(i1, n);
+ *i0; // no-warning
+}
+
+void bad_insert_vector1(std::vector<int> &V, int n) {
+ auto i1 = V.cbegin(), i0 = i1++;
+ V.insert(i1, n);
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_insert_deque1(std::deque<int> &D, int n) {
+ auto i1 = D.cbegin(), i0 = i1++;
+ D.insert(i1, n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_emplace_list1(std::list<int> &L, int n) {
+ auto i1 = L.cbegin(), i0 = i1++;
+ L.emplace(i1, n);
+ *i0; // no-warning
+ *i1; // no-warning
+}
+
+void good_emplace_vector1(std::vector<int> &V, int n) {
+ auto i1 = V.cbegin(), i0 = i1++;
+ V.emplace(i1, n);
+ *i0; // no-warning
+}
+
+void bad_emplace_vector1(std::vector<int> &V, int n) {
+ auto i1 = V.cbegin(), i0 = i1++;
+ V.emplace(i1, n);
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_emplace_deque1(std::deque<int> &D, int n) {
+ auto i1 = D.cbegin(), i0 = i1++;
+ D.emplace(i1, n);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_erase_list1(std::list<int> &L) {
+ auto i2 = L.cbegin(), i0 = i2++, i1 = i2++;
+ L.erase(i1);
+ *i0; // no-warning
+ *i2; // no-warning
+}
+
+void bad_erase_list1(std::list<int> &L) {
+ auto i0 = L.cbegin();
+ L.erase(i0);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_erase_vector1(std::vector<int> &V) {
+ auto i2 = V.cbegin(), i0 = i2++, i1 = i2++;
+ V.erase(i1);
+ *i0; // no-warning
+}
+
+void bad_erase_vector1(std::vector<int> &V) {
+ auto i1 = V.cbegin(), i0 = i1++;
+ V.erase(i0);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_erase_deque1(std::deque<int> &D) {
+ auto i2 = D.cbegin(), i0 = i2++, i1 = i2++;
+ D.erase(i1);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+ *i2; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_erase_list2(std::list<int> &L) {
+ auto i3 = L.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
+ L.erase(i1, i3);
+ *i0; // no-warning
+ *i3; // no-warning
+}
+
+void bad_erase_list2(std::list<int> &L) {
+ auto i2 = L.cbegin(), i0 = i2++, i1 = i2++;
+ L.erase(i0, i2);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_erase_vector2(std::vector<int> &V) {
+ auto i3 = V.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;;
+ V.erase(i1, i3);
+ *i0; // no-warning
+}
+
+void bad_erase_vector2(std::vector<int> &V) {
+ auto i2 = V.cbegin(), i0 = i2++, i1 = i2++;
+ V.erase(i0, i2);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+ *i2; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void bad_erase_deque2(std::deque<int> &D) {
+ auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
+ D.erase(i1, i3);
+ *i0; // expected-warning{{Invalidated iterator accessed}}
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+ *i2; // expected-warning{{Invalidated iterator accessed}}
+ *i3; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_erase_after_forward_list1(std::forward_list<int> &FL) {
+ auto i2 = FL.cbegin(), i0 = i2++, i1 = i2++;
+ FL.erase_after(i0);
+ *i0; // no-warning
+ *i2; // no-warning
+}
+
+void bad_erase_after_forward_list1(std::forward_list<int> &FL) {
+ auto i1 = FL.cbegin(), i0 = i1++;
+ FL.erase_after(i0);
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+}
+
+void good_erase_after_forward_list2(std::forward_list<int> &FL) {
+ auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
+ FL.erase_after(i0, i3);
+ *i0; // no-warning
+ *i3; // no-warning
+}
+
+void bad_erase_after_forward_list2(std::forward_list<int> &FL) {
+ auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
+ FL.erase_after(i0, i3);
+ *i1; // expected-warning{{Invalidated iterator accessed}}
+ *i2; // expected-warning{{Invalidated iterator accessed}}
+}
diff --git a/test/Analysis/iterator-range.cpp b/test/Analysis/iterator-range.cpp
index 8a4ba29b0cd7..6fc8939c8e84 100644
--- a/test/Analysis/iterator-range.cpp
+++ b/test/Analysis/iterator-range.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
#include "Inputs/system-header-simulator-cxx.h"
@@ -23,34 +23,13 @@ void simple_good_end_negated(const std::vector<int> &v) {
void simple_bad_end(const std::vector<int> &v) {
auto i = v.end();
- *i; // expected-warning{{Iterator accessed outside of its range}}
-}
-
-void simple_good_begin(const std::vector<int> &v) {
- auto i = v.begin();
- if (i != v.begin()) {
- clang_analyzer_warnIfReached();
- *--i; // no-warning
- }
-}
-
-void simple_good_begin_negated(const std::vector<int> &v) {
- auto i = v.begin();
- if (!(i == v.begin())) {
- clang_analyzer_warnIfReached();
- *--i; // no-warning
- }
-}
-
-void simple_bad_begin(const std::vector<int> &v) {
- auto i = v.begin();
- *--i; // expected-warning{{Iterator accessed outside of its range}}
+ *i; // expected-warning{{Past-the-end iterator dereferenced}}
}
void copy(const std::vector<int> &v) {
auto i1 = v.end();
auto i2 = i1;
- *i2; // expected-warning{{Iterator accessed outside of its range}}
+ *i2; // expected-warning{{Past-the-end iterator dereferenced}}
}
void decrease(const std::vector<int> &v) {
@@ -70,7 +49,7 @@ void copy_and_decrease2(const std::vector<int> &v) {
auto i1 = v.end();
auto i2 = i1;
--i1;
- *i2; // expected-warning{{Iterator accessed outside of its range}}
+ *i2; // expected-warning{{Past-the-end iterator dereferenced}}
}
void copy_and_increase1(const std::vector<int> &v) {
@@ -86,7 +65,7 @@ void copy_and_increase2(const std::vector<int> &v) {
auto i2 = i1;
++i1;
if (i2 == v.end())
- *i2; // expected-warning{{Iterator accessed outside of its range}}
+ *i2; // expected-warning{{Past-the-end iterator dereferenced}}
}
void copy_and_increase3(const std::vector<int> &v) {
@@ -94,14 +73,36 @@ void copy_and_increase3(const std::vector<int> &v) {
auto i2 = i1;
++i1;
if (v.end() == i2)
- *i2; // expected-warning{{Iterator accessed outside of its range}}
+ *i2; // expected-warning{{Past-the-end iterator dereferenced}}
+}
+
+template <class InputIterator, class T>
+InputIterator nonStdFind(InputIterator first, InputIterator last,
+ const T &val) {
+ for (auto i = first; i != last; ++i) {
+ if (*i == val) {
+ return i;
+ }
+ }
+ return last;
+}
+
+void good_non_std_find(std::vector<int> &V, int e) {
+ auto first = nonStdFind(V.begin(), V.end(), e);
+ if (V.end() != first)
+ *first; // no-warning
+}
+
+void bad_non_std_find(std::vector<int> &V, int e) {
+ auto first = nonStdFind(V.begin(), V.end(), e);
+ *first; // expected-warning{{Past-the-end iterator dereferenced}}
}
void tricky(std::vector<int> &V, int e) {
const auto first = V.begin();
const auto comp1 = (first != V.end()), comp2 = (first == V.end());
if (comp1)
- *first;
+ *first; // no-warning
}
void loop(std::vector<int> &V, int e) {
@@ -115,8 +116,123 @@ void loop(std::vector<int> &V, int e) {
}
}
+void good_push_back(std::list<int> &L, int n) {
+ auto i0 = --L.cend();
+ L.push_back(n);
+ *++i0; // no-warning
+}
+
+void bad_push_back(std::list<int> &L, int n) {
+ auto i0 = --L.cend();
+ L.push_back(n);
+ ++i0;
+ *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+}
+
+void good_pop_back(std::list<int> &L, int n) {
+ auto i0 = --L.cend(); --i0;
+ L.pop_back();
+ *i0; // no-warning
+}
+
+void bad_pop_back(std::list<int> &L, int n) {
+ auto i0 = --L.cend(); --i0;
+ L.pop_back();
+ *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+}
+
+void good_push_front(std::list<int> &L, int n) {
+ auto i0 = L.cbegin();
+ L.push_front(n);
+ *--i0; // no-warning
+}
+
+void bad_push_front(std::list<int> &L, int n) {
+ auto i0 = L.cbegin();
+ L.push_front(n);
+ --i0;
+ --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
+}
+
+void good_pop_front(std::list<int> &L, int n) {
+ auto i0 = ++L.cbegin();
+ L.pop_front();
+ *i0; // no-warning
+}
+
+void bad_pop_front(std::list<int> &L, int n) {
+ auto i0 = ++L.cbegin();
+ L.pop_front();
+ --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
+}
+
void bad_move(std::list<int> &L1, std::list<int> &L2) {
auto i0 = --L2.cend();
L1 = std::move(L2);
- *++i0; // expected-warning{{Iterator accessed outside of its range}}
+ *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+}
+
+void bad_move_push_back(std::list<int> &L1, std::list<int> &L2, int n) {
+ auto i0 = --L2.cend();
+ L2.push_back(n);
+ L1 = std::move(L2);
+ ++i0;
+ *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+}
+
+void good_incr_begin(const std::list<int> &L) {
+ auto i0 = L.begin();
+ ++i0; // no-warning
+}
+
+void bad_decr_begin(const std::list<int> &L) {
+ auto i0 = L.begin();
+ --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
+}
+
+void good_decr_end(const std::list<int> &L) {
+ auto i0 = L.end();
+ --i0; // no-warning
+}
+
+void bad_incr_end(const std::list<int> &L) {
+ auto i0 = L.end();
+ ++i0; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
+}
+
+struct simple_iterator_base {
+ simple_iterator_base();
+ simple_iterator_base(const simple_iterator_base& rhs);
+ simple_iterator_base &operator=(const simple_iterator_base& rhs);
+ virtual ~simple_iterator_base();
+ bool friend operator==(const simple_iterator_base &lhs,
+ const simple_iterator_base &rhs);
+ bool friend operator!=(const simple_iterator_base &lhs,
+ const simple_iterator_base &rhs);
+private:
+ int *ptr;
+};
+
+struct simple_derived_iterator: public simple_iterator_base {
+ int& operator*();
+ int* operator->();
+ simple_iterator_base &operator++();
+ simple_iterator_base operator++(int);
+ simple_iterator_base &operator--();
+ simple_iterator_base operator--(int);
+};
+
+struct simple_container {
+ typedef simple_derived_iterator iterator;
+
+ iterator begin();
+ iterator end();
+};
+
+void good_derived(simple_container c) {
+ auto i0 = c.end();
+ if (i0 != c.end()) {
+ clang_analyzer_warnIfReached();
+ *i0; // no-warning
+ }
}
diff --git a/test/Analysis/ivars.m b/test/Analysis/ivars.m
index 11514d2f8309..c0bb4bc1749a 100644
--- a/test/Analysis/ivars.m
+++ b/test/Analysis/ivars.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -fblocks -verify -Wno-objc-root-class %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -fblocks -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/keychainAPI.m b/test/Analysis/keychainAPI.m
index 1725ce15f0e6..15a3b66b1a38 100644
--- a/test/Analysis/keychainAPI.m
+++ b/test/Analysis/keychainAPI.m
@@ -212,7 +212,7 @@ int foo(CFTypeRef keychainOrArray, SecProtocolType protocol,
if (st == noErr)
SecKeychainItemFreeContent(ptr, outData[3]);
}
- if (length) { // TODO: We do not report a warning here since the symbol is no longer live, but it's not marked as dead.
+ if (length) { // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
length++;
}
return 0;
@@ -454,3 +454,15 @@ int radar_19196494() {
}
return 0;
}
+int radar_19196494_v2() {
+ @autoreleasepool {
+ AuthorizationValue login_password = {};
+ OSStatus err = SecKeychainFindGenericPassword(0, 0, "", 0, "", (UInt32 *)&login_password.length, (void**)&login_password.data, 0);
+ if (!login_password.data) return 0;
+ cb.SetContextVal(&login_password);
+ if (err == noErr) {
+ SecKeychainItemFreeContent(0, login_password.data);
+ }
+ }
+ return 0;
+}
diff --git a/test/Analysis/lambda-notes.cpp b/test/Analysis/lambda-notes.cpp
index d4318284df01..c23ba7677879 100644
--- a/test/Analysis/lambda-notes.cpp
+++ b/test/Analysis/lambda-notes.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core.DivideZero -analyzer-config inline-lambdas=true -analyzer-output plist -verify %s -o %t
-// RUN: FileCheck --input-file=%t %s
+// RUN: tail -n +11 %t | diff -u -w -I "<string>/" -I "<string>.:" -I "version" - %S/Inputs/expected-plists/lambda-notes.cpp.plist
// Diagnostic inside a lambda
@@ -11,196 +11,3 @@ void diagnosticFromLambda() {
(void)p;
}();
}
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>8</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to field &apos;&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The value 0 is assigned to field &apos;&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;operator()&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;operator()&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;diagnosticFromLambda&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;diagnosticFromLambda&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>9</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bd4eed3234018edced5efc2ed5562a74</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
-// CHECK-NEXT: <key>issue_context</key><string>operator()</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/lambdas.cpp b/test/Analysis/lambdas.cpp
index 320ba2aabc22..fdd1c61164f4 100644
--- a/test/Analysis/lambdas.cpp
+++ b/test/Analysis/lambdas.cpp
@@ -1,10 +1,26 @@
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,deadcode,debug.ExprInspection -analyzer-config inline-lambdas=true -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-config inline-lambdas=false -DNO_INLINING=1 -verify %s
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -analyzer-config inline-lambdas=true %s > %t 2>&1
// RUN: FileCheck --input-file=%t %s
void clang_analyzer_warnIfReached();
void clang_analyzer_eval(int);
+#ifdef NO_INLINING
+
+// expected-no-diagnostics
+
+int& invalidate_static_on_unknown_lambda() {
+ static int* z;
+ auto f = [] {
+ z = nullptr;
+ }; // should invalidate "z" when inlining is disabled.
+ f();
+ return *z; // no-warning
+}
+
+#else
+
struct X { X(const X&); };
void f(X x) { (void) [x]{}; }
@@ -348,6 +364,18 @@ void testCapturedConstExprFloat() {
lambda();
}
+void escape(void*);
+
+int& invalidate_static_on_unknown_lambda() {
+ static int* z;
+ auto lambda = [] {
+ static float zz;
+ z = new int(120);
+ };
+ escape(&lambda);
+ return *z; // no-warning
+}
+
static int b = 0;
@@ -365,6 +393,8 @@ int f() {
return 0;
}
+#endif
+
// CHECK: [B2 (ENTRY)]
// CHECK: Succs (1): B1
// CHECK: [B1]
diff --git a/test/Analysis/lifetime-extension.cpp b/test/Analysis/lifetime-extension.cpp
index 4337632b31c8..8ce2000787a7 100644
--- a/test/Analysis/lifetime-extension.cpp
+++ b/test/Analysis/lifetime-extension.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify %s
-// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -verify %s
-// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES %s
-// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -DMOVES -verify %s
-// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES -verify %s
-// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -DMOVES -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++11 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -Wno-unused -std=c++17 -analyzer-checker=core,debug.ExprInspection -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true -DTEMPORARIES -DMOVES -analyzer-config eagerly-assume=false %s
// Note: The C++17 run-lines don't -verify yet - it is a no-crash test.
diff --git a/test/Analysis/lit.local.cfg b/test/Analysis/lit.local.cfg
index a594c5dada58..84f7569152c9 100644
--- a/test/Analysis/lit.local.cfg
+++ b/test/Analysis/lit.local.cfg
@@ -7,7 +7,16 @@ import site
site.addsitedir(os.path.dirname(__file__))
import analyzer_test
config.test_format = analyzer_test.AnalyzerTest(
- config.test_format.execute_external)
+ config.test_format.execute_external, config.use_z3_solver)
+
+# Diff command used by Clang Analyzer tests (when comparing .plist files
+# with reference output)
+config.substitutions.append(('%diff_plist',
+ 'diff -u -w -I "<string>/" -I "<string>.:" -I "version"'))
+
+# Diff command for testing SARIF output to reference output.
+config.substitutions.append(('%diff_sarif',
+ '''diff -U1 -w -I ".*file:.*%basename_t" -I '"version":' -I "2\.0\.0\-csd\.[0-9]*\.beta\."'''))
if not config.root.clang_staticanalyzer:
config.unsupported = True
diff --git a/test/Analysis/live-stmts.cpp b/test/Analysis/live-stmts.cpp
new file mode 100644
index 000000000000..1b8a750c5e5c
--- /dev/null
+++ b/test/Analysis/live-stmts.cpp
@@ -0,0 +1,167 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=debug.DumpLiveStmts %s 2>&1\
+// RUN: | FileCheck %s
+
+int coin();
+
+
+int testThatDumperWorks(int x, int y, int z) {
+ return x ? y : z;
+}
+// CHECK: [ B0 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B1 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B2 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int'
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int'
+// CHECK-EMPTY:
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <IntegralToBoolean>
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <LValueToRValue>
+// CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int'
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B3 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int'
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int'
+// CHECK-EMPTY:
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <IntegralToBoolean>
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <LValueToRValue>
+// CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int'
+// CHECK: [ B4 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int'
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int'
+// CHECK-EMPTY:
+// CHECK-NEXT: ImplicitCastExpr {{.*}} <IntegralToBoolean>
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <LValueToRValue>
+// CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int'
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B5 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int'
+// CHECK-EMPTY:
+// CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int'
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+
+
+void testIfBranchExpression(bool flag) {
+ // No expressions should be carried over from one block to another here.
+ while (flag) {
+ int e = 1;
+ if (true)
+ e;
+ }
+}
+// CHECK: [ B0 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B1 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B2 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B3 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B4 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B5 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+
+
+void testWhileBodyExpression(bool flag) {
+ // No expressions should be carried over from one block to another here.
+ while (flag) {
+ int e = 1;
+ while (coin())
+ e;
+ }
+}
+// CHECK: [ B0 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B1 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B2 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B3 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B4 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B5 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+
+
+void testDoWhileBodyExpression(bool flag) {
+ // No expressions should be carried over from one block to another here.
+ while (flag) {
+ int e = 1;
+ do
+ e;
+ while (coin());
+ }
+}
+// CHECK: [ B0 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B1 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B2 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B3 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B4 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B5 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+
+
+void testForBodyExpression(bool flag) {
+ // No expressions should be carried over from one block to another here.
+ while (flag) {
+ int e = 1;
+ for (; coin();)
+ e;
+ }
+}
+// CHECK: [ B0 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B1 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B2 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B3 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B4 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+// CHECK: [ B5 (live statements at block exit) ]
+// CHECK-EMPTY:
+// CHECK-EMPTY:
+
diff --git a/test/Analysis/llvm-conventions.cpp b/test/Analysis/llvm-conventions.cpp
new file mode 100644
index 000000000000..49bdc6380bc8
--- /dev/null
+++ b/test/Analysis/llvm-conventions.cpp
@@ -0,0 +1,225 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.llvm.Conventions \
+// RUN: -std=c++14 -verify %s
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+//===----------------------------------------------------------------------===//
+// Forward declarations for StringRef tests.
+//===----------------------------------------------------------------------===//
+
+using size_type = size_t;
+
+namespace std {
+
+template <class T>
+struct numeric_limits { const static bool is_signed; };
+
+} // end of namespace std
+
+namespace llvm {
+
+template <class T>
+struct iterator_range;
+
+template <class Func>
+struct function_ref;
+
+struct hash_code;
+
+template <class T>
+struct SmallVectorImpl;
+
+struct APInt;
+
+class StringRef {
+public:
+ static const size_t npos = ~size_t(0);
+ using iterator = const char *;
+ using const_iterator = const char *;
+ using size_type = size_t;
+
+ /*implicit*/ StringRef() = default;
+ StringRef(std::nullptr_t) = delete;
+ /*implicit*/ StringRef(const char *Str);
+ /*implicit*/ constexpr StringRef(const char *data, size_t length);
+ /*implicit*/ StringRef(const std::string &Str);
+
+ static StringRef withNullAsEmpty(const char *data);
+ iterator begin() const;
+ iterator end() const;
+ const unsigned char *bytes_begin() const;
+ const unsigned char *bytes_end() const;
+ iterator_range<const unsigned char *> bytes() const;
+ const char *data() const;
+ bool empty() const;
+ size_t size() const;
+ char front() const;
+ char back() const;
+ template <typename Allocator>
+ StringRef copy(Allocator &A) const;
+ bool equals(StringRef RHS) const;
+ bool equals_lower(StringRef RHS) const;
+ int compare(StringRef RHS) const;
+ int compare_lower(StringRef RHS) const;
+ int compare_numeric(StringRef RHS) const;
+ unsigned edit_distance(StringRef Other, bool AllowReplacements = true,
+ unsigned MaxEditDistance = 0) const;
+ std::string str() const;
+ char operator[](size_t Index) const;
+ template <typename T>
+ typename std::enable_if<std::is_same<T, std::string>::value,
+ StringRef>::type &
+ operator=(T &&Str) = delete;
+ operator std::string() const;
+ bool startswith(StringRef Prefix) const;
+ bool startswith_lower(StringRef Prefix) const;
+ bool endswith(StringRef Suffix) const;
+ bool endswith_lower(StringRef Suffix) const;
+ size_t find(char C, size_t From = 0) const;
+ size_t find_lower(char C, size_t From = 0) const;
+ size_t find_if(function_ref<bool(char)> F, size_t From = 0) const;
+ size_t find_if_not(function_ref<bool(char)> F, size_t From = 0) const;
+ size_t find(StringRef Str, size_t From = 0) const;
+ size_t find_lower(StringRef Str, size_t From = 0) const;
+ size_t rfind(char C, size_t From = npos) const;
+ size_t rfind_lower(char C, size_t From = npos) const;
+ size_t rfind(StringRef Str) const;
+ size_t rfind_lower(StringRef Str) const;
+ size_t find_first_of(char C, size_t From = 0) const;
+ size_t find_first_of(StringRef Chars, size_t From = 0) const;
+ size_t find_first_not_of(char C, size_t From = 0) const;
+ size_t find_first_not_of(StringRef Chars, size_t From = 0) const;
+ size_t find_last_of(char C, size_t From = npos) const;
+ size_t find_last_of(StringRef Chars, size_t From = npos) const;
+ size_t find_last_not_of(char C, size_t From = npos) const;
+ size_t find_last_not_of(StringRef Chars, size_t From = npos) const;
+ bool contains(StringRef Other) const;
+ bool contains(char C) const;
+ bool contains_lower(StringRef Other) const;
+ bool contains_lower(char C) const;
+ size_t count(char C) const;
+ size_t count(StringRef Str) const;
+ template <typename T>
+ typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
+ getAsInteger(unsigned Radix, T &Result) const;
+ template <typename T>
+ typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
+ getAsInteger(unsigned Radix, T &Result) const;
+ template <typename T>
+ typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
+ consumeInteger(unsigned Radix, T &Result);
+ template <typename T>
+ typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
+ consumeInteger(unsigned Radix, T &Result);
+ bool getAsInteger(unsigned Radix, APInt &Result) const;
+ bool getAsDouble(double &Result, bool AllowInexact = true) const;
+ std::string lower() const;
+ std::string upper() const;
+ StringRef substr(size_t Start, size_t N = npos) const;
+ StringRef take_front(size_t N = 1) const;
+ StringRef take_back(size_t N = 1) const;
+ StringRef take_while(function_ref<bool(char)> F) const;
+ StringRef take_until(function_ref<bool(char)> F) const;
+ StringRef drop_front(size_t N = 1) const;
+ StringRef drop_back(size_t N = 1) const;
+ StringRef drop_while(function_ref<bool(char)> F) const;
+ StringRef drop_until(function_ref<bool(char)> F) const;
+ bool consume_front(StringRef Prefix);
+ bool consume_back(StringRef Suffix);
+ StringRef slice(size_t Start, size_t End) const;
+ std::pair<StringRef, StringRef> split(char Separator) const;
+ std::pair<StringRef, StringRef> split(StringRef Separator) const;
+ std::pair<StringRef, StringRef> rsplit(StringRef Separator) const;
+ void split(SmallVectorImpl<StringRef> &A,
+ StringRef Separator, int MaxSplit = -1,
+ bool KeepEmpty = true) const;
+ void split(SmallVectorImpl<StringRef> &A, char Separator, int MaxSplit = -1,
+ bool KeepEmpty = true) const;
+ std::pair<StringRef, StringRef> rsplit(char Separator) const;
+ StringRef ltrim(char Char) const;
+ StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const;
+ StringRef rtrim(char Char) const;
+ StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const;
+ StringRef trim(char Char) const;
+ StringRef trim(StringRef Chars = " \t\n\v\f\r") const;
+};
+
+inline bool operator==(StringRef LHS, StringRef RHS);
+inline bool operator!=(StringRef LHS, StringRef RHS);
+inline bool operator<(StringRef LHS, StringRef RHS);
+inline bool operator<=(StringRef LHS, StringRef RHS);
+inline bool operator>(StringRef LHS, StringRef RHS);
+inline bool operator>=(StringRef LHS, StringRef RHS);
+inline std::string &operator+=(std::string &buffer, StringRef string);
+hash_code hash_value(StringRef S);
+template <typename T> struct isPodLike;
+template <> struct isPodLike<StringRef> { static const bool value = true; };
+
+} // end of namespace llvm
+
+//===----------------------------------------------------------------------===//
+// Tests for StringRef.
+//===----------------------------------------------------------------------===//
+
+void temporarayStringToStringRefAssignmentTest() {
+ // TODO: Emit a warning.
+ llvm::StringRef Ref = std::string("Yimmy yummy test.");
+}
+
+void assigningStringToStringRefWithLongerLifetimeTest() {
+ llvm::StringRef Ref;
+ {
+ // TODO: Emit a warning.
+ std::string TmpStr("This is a fine string.");
+ Ref = TmpStr;
+ }
+}
+
+std::string getTemporaryString() {
+ return "One two three.";
+}
+
+void assigningTempStringFromFunctionToStringRefTest() {
+ // TODO: Emit a warning.
+ llvm::StringRef Ref = getTemporaryString();
+}
+
+//===----------------------------------------------------------------------===//
+// Forward declaration for Clang AST nodes.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+template <class T, int Size>
+struct SmallVector {};
+
+} // end of namespace llvm
+
+namespace clang {
+
+struct Type;
+struct Decl;
+struct Stmt;
+struct Attr;
+
+} // end of namespace clang
+
+//===----------------------------------------------------------------------===//
+// Tests for Clang AST nodes.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+
+struct Type {
+ std::string str; // expected-warning{{AST class 'Type' has a field 'str' that allocates heap memory (type std::string)}}
+};
+
+} // end of namespace clang
+
+namespace clang {
+
+struct Decl {
+ llvm::SmallVector<int, 5> Vec; // expected-warning{{AST class 'Decl' has a field 'Vec' that allocates heap memory (type llvm::SmallVector<int, 5>)}}
+};
+
+} // end of namespace clang
diff --git a/test/Analysis/localization-aggressive.m b/test/Analysis/localization-aggressive.m
index ea5e0b152945..2e273e0c4821 100644
--- a/test/Analysis/localization-aggressive.m
+++ b/test/Analysis/localization-aggressive.m
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -fblocks -x objective-c-header -emit-pch -o %t.pch %S/Inputs/localization-pch.h
-// RUN: %clang_analyze_cc1 -fblocks -analyzer-store=region -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=optin.osx.cocoa.localizability.EmptyLocalizationContextChecker -include-pch %t.pch -verify -analyzer-config AggressiveReport=true %s
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-store=region \
+// RUN: -analyzer-config optin.osx.cocoa.localizability.NonLocalizedStringChecker:AggressiveReport=true \
+// RUN: -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker \
+// RUN: -analyzer-checker=optin.osx.cocoa.localizability.EmptyLocalizationContextChecker \
+// RUN: -include-pch %t.pch -verify %s
// These declarations were reduced using Delta-Debugging from Foundation.h
// on Mac OS X.
diff --git a/test/Analysis/logical-ops.c b/test/Analysis/logical-ops.c
index 553050173b02..f839b1bf22bd 100644
--- a/test/Analysis/logical-ops.c
+++ b/test/Analysis/logical-ops.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -Wno-pointer-bool-conversion -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -Wno-pointer-bool-conversion -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/loop-block-counts.c b/test/Analysis/loop-block-counts.c
new file mode 100644
index 000000000000..04a3f747c2ee
--- /dev/null
+++ b/test/Analysis/loop-block-counts.c
@@ -0,0 +1,26 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+
+void callee(void **p) {
+ int x;
+ *p = &x;
+}
+
+void loop() {
+ void *arr[2];
+ for (int i = 0; i < 2; ++i)
+ callee(&arr[i]);
+ // FIXME: Should be UNKNOWN.
+ clang_analyzer_eval(arr[0] == arr[1]); // expected-warning{{TRUE}}
+}
+
+void loopWithCall() {
+ void *arr[2];
+ for (int i = 0; i < 2; ++i) {
+ int x;
+ arr[i] = &x;
+ }
+ // FIXME: Should be UNKNOWN.
+ clang_analyzer_eval(arr[0] == arr[1]); // expected-warning{{TRUE}}
+}
diff --git a/test/Analysis/loop-widening-ignore-static-methods.cpp b/test/Analysis/loop-widening-ignore-static-methods.cpp
new file mode 100644
index 000000000000..bcf4f8b23a60
--- /dev/null
+++ b/test/Analysis/loop-widening-ignore-static-methods.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config widen-loops=true -analyzer-max-loop 2 %s
+// REQUIRES: asserts
+// expected-no-diagnostics
+//
+// This test checks that the loop-widening code ignores static methods. If that is not the
+// case, then an assertion will trigger.
+
+class Test {
+ static void foo() {
+ for (;;) {}
+ }
+};
diff --git a/test/Analysis/loop-widening-notes.cpp b/test/Analysis/loop-widening-notes.cpp
index 56bde7416af5..2c26a1490e5c 100644
--- a/test/Analysis/loop-widening-notes.cpp
+++ b/test/Analysis/loop-widening-notes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha -analyzer-max-loop 2 -analyzer-config widen-loops=true -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha -analyzer-max-loop 2 -analyzer-config widen-loops=true -analyzer-output=text -verify -analyzer-config eagerly-assume=false %s
int *p_a;
int bar();
diff --git a/test/Analysis/loop-widening.c b/test/Analysis/loop-widening.c
index 3378893b3257..edaabfb28e97 100644
--- a/test/Analysis/loop-widening.c
+++ b/test/Analysis/loop-widening.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
-// RUN: %clang_analyze_cc1 -DTEST_NULL_TERM -analyzer-checker=core,unix.Malloc,debug.ExprInspection,alpha.cplusplus.IteratorRange -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DTEST_NULL_TERM -analyzer-checker=core,unix.Malloc,debug.ExprInspection,alpha.cplusplus.IteratorRange -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
diff --git a/test/Analysis/malloc-annotations.c b/test/Analysis/malloc-annotations.c
index 21eaab72b766..50a18c5b9616 100644
--- a/test/Analysis/malloc-annotations.c
+++ b/test/Analysis/malloc-annotations.c
@@ -1,4 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc -analyzer-store=region -verify -analyzer-config unix.Malloc:Optimistic=true %s
+// RUN: %clang_analyze_cc1 -analyzer-store=region -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \
+// RUN: -analyzer-checker=alpha.core.CastSize,unix.Malloc \
+// RUN: -analyzer-config unix.Malloc:Optimistic=true
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
void free(void *);
diff --git a/test/Analysis/malloc-free-after-return.cpp b/test/Analysis/malloc-free-after-return.cpp
new file mode 100644
index 000000000000..cebd79a1a15e
--- /dev/null
+++ b/test/Analysis/malloc-free-after-return.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete -verify %s
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+struct S {
+ S() : Data(new int) {}
+ ~S() { delete Data; }
+ int *getData() { return Data; }
+
+private:
+ int *Data;
+};
+
+int *freeAfterReturnTemp() {
+ return S().getData(); // expected-warning {{Use of memory after it is freed}}
+}
+
+int *freeAfterReturnLocal() {
+ S X;
+ return X.getData(); // expected-warning {{Use of memory after it is freed}}
+}
diff --git a/test/Analysis/malloc-plist.c b/test/Analysis/malloc-plist.c
index 1f2870863cc7..3338a63c69d1 100644
--- a/test/Analysis/malloc-plist.c
+++ b/test/Analysis/malloc-plist.c
@@ -1,6 +1,6 @@
// RUN: rm -f %t
-// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -verify -o %t %s
-// RUN: FileCheck -input-file %t %s
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -verify -o %t -analyzer-config eagerly-assume=false %s
+// RUN: tail -n +11 %t | diff -u -w -I "<string>/" -I "<string>.:" -I "version" - %S/Inputs/expected-plists/malloc-plist.c.plist
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
@@ -207,5038 +207,3 @@ int *my_malloc_into_struct() {
void testMyMalloc() {
my_malloc_into_struct();
} // expected-warning{{Potential memory leak}}
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;in&apos; is &gt; 5</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;in&apos; is &gt; 5</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;p&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c60b35a3e46fd104f362f430a1eaca5d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>diagnosticTest</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;A&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;A&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;A&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>9b732ec46c4a08108dfbd37aa0955c51</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>myArrayAllocation</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>26</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>37c0b1a1e65d26af6f9fb840cf159149</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>reallocDiagnostics</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_wrapper&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_wrapper&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>384d1700f3d9c8eeea96d171e3030bdf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_wrapper</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;my_malloc_and_free&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_malloc_and_free&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_double_action_call&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_double_action_call&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;my_free&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_free&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;my_malloc_and_free&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;my_malloc_and_free&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning; memory was released via 1st parameter</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning; memory was released via 1st parameter</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning; memory was released via 1st parameter</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning; memory was released via 1st parameter</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Use of memory after it is freed</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Use of memory after it is freed</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Use of memory after it is freed</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-free</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>422436dc85b85cde7e15046a5616ee99</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_double_action_call</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;my_realloc&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_realloc&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;reallocIntra&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;reallocIntra&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Attempt to reallocate memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;tmp&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reallocation failed</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>70</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reallocation of 1st parameter failed</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reallocation of 1st parameter failed</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;buf&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>23a6c295a515c455bea1c81519bc05b6</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>reallocIntra</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;malloc_wrapper_ret&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;malloc_wrapper_ret&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_ret&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_ret&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>87</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;v&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;v&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;v&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>45181c7fc1df81a732346f1ed1b3f238</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>use_ret</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;myfree_takingblock&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;myfree_takingblock&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;call_myfree_takingblock&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;call_myfree_takingblock&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning; memory was released via 2nd parameter</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning; memory was released via 2nd parameter</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>101</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Use of memory after it is freed</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Use of memory after it is freed</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Use of memory after it is freed</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-free</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>652c97005df876a65d64ecd286d6030a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>call_myfree_takingblock</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;m&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;m&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;m&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d8483ccf1d5a1af1e8bcaac6905a18b3</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>LeakedSymbol</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak1&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak1&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak1&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak1&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b07aebe89e4ba5ea104a9f957df9531b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>function_with_leak1</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>132</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak2&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak2&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>efe2ffcb7c227e872aa732c5f793895d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>function_with_leak2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak3&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak3&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak3&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak3&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>137</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>138</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>138</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>138</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0ddc87e8a7e7104428af3905f3057611</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>function_with_leak3</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>138</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak4&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak4&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak4&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak4&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>149</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>149</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>149</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>948d356840e67fc4baa8cc5d0600463c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>function_with_leak4</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>149</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak5&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak5&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak5&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak5&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>158</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2b0361060027060b94915ff4de8aa782</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>function_with_leak5</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>174</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>174</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>174</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak6&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak6&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak6&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak6&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>169</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>73f573faa903ad4308d5155ef979cf31</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>function_with_leak6</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak7&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;function_with_leak7&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak7&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;use_function_with_leak7&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential memory leak</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential memory leak</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential memory leak</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>eb5628850b9b9118fbda903e721436a5</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>use_function_with_leak7</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;my_malloc&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_malloc&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testOnlyRefferToVisibleVariables&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testOnlyRefferToVisibleVariables&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>193</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>193</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential memory leak</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential memory leak</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential memory leak</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ad5b603037bc3581ff94947e86dbb1c8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testOnlyRefferToVisibleVariables</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>197</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;my_malloc_into_struct&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;my_malloc_into_struct&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testMyMalloc&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testMyMalloc&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>205</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returned allocated memory</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential memory leak</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential memory leak</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential memory leak</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8d59cc5cc4b7db55d432abc18b0e6c23</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testMyMalloc</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index 3e86c29a55a5..8e0f5c04ca2d 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -1,4 +1,9 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-store=region -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-checker=alpha.deadcode.UnreachableCode \
+// RUN: -analyzer-checker=alpha.core.CastSize \
+// RUN: -analyzer-checker=unix.Malloc \
+// RUN: -analyzer-checker=debug.ExprInspection
#include "Inputs/system-header-simulator.h"
diff --git a/test/Analysis/member-expr.cpp b/test/Analysis/member-expr.cpp
index 9951943e3060..8fb6fe48f01c 100644
--- a/test/Analysis/member-expr.cpp
+++ b/test/Analysis/member-expr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection %s -verify
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,debug.ExprInspection %s -verify
void clang_analyzer_checkInlined(bool);
void clang_analyzer_eval(int);
diff --git a/test/Analysis/method-call-path-notes.cpp b/test/Analysis/method-call-path-notes.cpp
index 7c93c99bfd8c..0da25117b067 100644
--- a/test/Analysis/method-call-path-notes.cpp
+++ b/test/Analysis/method-call-path-notes.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/method-call-path-notes.cpp.plist -
// Test warning about null or uninitialized pointer values used as instance member
// calls.
@@ -42,780 +42,3 @@ void test_cast(const TestInstanceCall *p) {
const_cast<TestInstanceCall *>(p)->foo(); // expected-warning {{Called C++ object pointer is null}} expected-note {{Called C++ object pointer is null}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is uninitialized</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is uninitialized</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is uninitialized</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is uninitialized</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8c0cdb645ae6be246ed75941dcefd32d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_ic</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>98e39ef0e4bbc0b9b2b1832285634d67</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_ic_null</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>84f3d9d5009d2ac455b46b4aae88f67f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_ic_set_to_null</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c5bd8e35fb6da070914016804720ae4d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_ic_null</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>34</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4681ee922f6860377317b26b3a4bb5d4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_ic_member_ptr</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Called C++ object pointer is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Called C++ object pointer is null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>e23397f9f2eff1b08593c2b2db137494</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_cast</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>42</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/misc-ps-eager-assume.m b/test/Analysis/misc-ps-eager-assume.m
index dbeecf235f9f..f61e0ae9f808 100644
--- a/test/Analysis/misc-ps-eager-assume.m
+++ b/test/Analysis/misc-ps-eager-assume.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s -analyzer-eagerly-assume
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s
// expected-no-diagnostics
// Delta-reduced header stuff (needed for test cases).
@@ -86,7 +86,7 @@ void pr3836(int *a, int *b) {
// This false positive occurred because the symbolic constraint on a short was
// not maintained via sign extension. The analyzer doesn't properly handle
// the sign extension, but now tracks the constraint. This particular
-// case relies on -analyzer-eagerly-assume because of the expression
+// case relies on -analyzer-options eagerly-assume=true because of the expression
// 'Flag1 != Count > 0'.
//===---------------------------------------------------------------------===//
@@ -125,8 +125,8 @@ void rdar7342806() {
//===---------------------------------------------------------------------===//
// PR 5627 - http://llvm.org/bugs/show_bug.cgi?id=5627
-// This test case depends on using -analyzer-eagerly-assume and
-// -analyzer-store=region. The '-analyzer-eagerly-assume' causes the path
+// This test case depends on using -analyzer-config eagerly-assume=true and
+// -analyzer-store=region. The 'eagerly-assume=true' causes the path
// to bifurcate when evaluating the function call argument, and a state
// caching bug in GRExprEngine::CheckerVisit (and friends) caused the store
// to 'p' to not be evaluated along one path, but then an autotransition caused
diff --git a/test/Analysis/misc-ps.c b/test/Analysis/misc-ps.c
index 3044dc98d3c7..68704a6b1eb2 100644
--- a/test/Analysis/misc-ps.c
+++ b/test/Analysis/misc-ps.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -disable-free -analyzer-eagerly-assume -analyzer-checker=core,deadcode,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -disable-free -analyzer-checker=core,deadcode,debug.ExprInspection -verify %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/mismatched-iterator.cpp b/test/Analysis/mismatched-iterator.cpp
new file mode 100644
index 000000000000..756d09544357
--- /dev/null
+++ b/test/Analysis/mismatched-iterator.cpp
@@ -0,0 +1,191 @@
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.MismatchedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.MismatchedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+void good_insert1(std::vector<int> &v, int n) {
+ v.insert(v.cbegin(), n); // no-warning
+}
+
+
+void good_insert2(std::vector<int> &v, int len, int n) {
+ v.insert(v.cbegin(), len, n); // no-warning
+}
+
+void good_insert3(std::vector<int> &v1, std::vector<int> &v2) {
+ v1.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // no-warning
+}
+
+void good_insert4(std::vector<int> &v, int len, int n) {
+ v.insert(v.cbegin(), {n-1, n, n+1}); // no-warning
+}
+
+void good_insert_find(std::vector<int> &v, int n, int m) {
+ auto i = std::find(v.cbegin(), v.cend(), n);
+ v.insert(i, m); // no-warning
+}
+
+void good_erase1(std::vector<int> &v) {
+ v.erase(v.cbegin()); // no-warning
+}
+
+void good_erase2(std::vector<int> &v) {
+ v.erase(v.cbegin(), v.cend()); // no-warning
+}
+
+void good_emplace(std::vector<int> &v, int n) {
+ v.emplace(v.cbegin(), n); // no-warning
+}
+
+void good_ctor(std::vector<int> &v) {
+ std::vector<int> new_v(v.cbegin(), v.cend()); // no-warning
+}
+
+void good_find(std::vector<int> &v, int n) {
+ std::find(v.cbegin(), v.cend(), n); // no-warning
+}
+
+void good_find_first_of(std::vector<int> &v1, std::vector<int> &v2) {
+ std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v2.cend()); // no-warning
+}
+
+void good_copy(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ std::copy(v1.cbegin(), v1.cend(), v2.begin()); // no-warning
+}
+
+void good_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i0 = v2.cbegin();
+ v1 = std::move(v2);
+ std::find(i0, v1.cend(), n); // no-warning
+}
+
+void bad_insert1(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ v2.insert(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+void bad_insert2(std::vector<int> &v1, std::vector<int> &v2, int len, int n) {
+ v2.insert(v1.cbegin(), len, n); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+void bad_insert3(std::vector<int> &v1, std::vector<int> &v2) {
+ v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+ v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}}
+ v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}}
+}
+
+void bad_insert4(std::vector<int> &v1, std::vector<int> &v2, int len, int n) {
+ v2.insert(v1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+void bad_erase1(std::vector<int> &v1, std::vector<int> &v2) {
+ v2.erase(v1.cbegin()); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+void bad_erase2(std::vector<int> &v1, std::vector<int> &v2) {
+ v2.erase(v2.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+ v2.erase(v1.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+ v2.erase(v1.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+void bad_emplace(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ v2.emplace(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+void good_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i0 = --v2.cend();
+ v1 = std::move(v2);
+ std::find(i0, v1.cend(), n); // no-warning
+}
+
+void good_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i0 = v2.cend();
+ v1 = std::move(v2);
+ v2.push_back(n); // expected-warning{{Method called on moved-from object of type 'std::vector'}}
+ std::find(v2.cbegin(), i0, n); // no-warning
+}
+
+void good_comparison(std::vector<int> &v) {
+ if (v.cbegin() == v.cend()) {} // no-warning
+}
+
+void bad_ctor(std::vector<int> &v1, std::vector<int> &v2) {
+ std::vector<int> new_v(v1.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}}
+}
+
+void bad_find(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ std::find(v1.cbegin(), v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}}
+}
+
+void bad_find_first_of(std::vector<int> &v1, std::vector<int> &v2) {
+ std::find_first_of(v1.cbegin(), v2.cend(), v2.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}}
+ std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}}
+}
+
+void bad_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i0 = v2.cbegin();
+ v1 = std::move(v2);
+ std::find(i0, v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}}
+ // expected-warning@-1{{Method called on moved-from object of type 'std::vector'}}
+}
+
+void bad_insert_find(std::vector<int> &v1, std::vector<int> &v2, int n, int m) {
+ auto i = std::find(v1.cbegin(), v1.cend(), n);
+ v2.insert(i, m); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+void good_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i = v1.cbegin();
+ i = v2.cbegin();
+ v2.insert(i, n); // no-warning
+}
+
+void bad_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i = v1.cbegin();
+ i = v2.cbegin();
+ v1.insert(i, n); // expected-warning{{Container accessed using foreign iterator argument}}
+}
+
+template<typename Container, typename Iterator>
+bool is_cend(Container cont, Iterator it) {
+ return it == cont.cend();
+}
+
+void good_empty(std::vector<int> &v) {
+ is_cend(v, v.cbegin()); // no-warning
+}
+
+void bad_empty(std::vector<int> &v1, std::vector<int> &v2) {
+ is_cend(v1, v2.cbegin()); // expected-warning@-8{{Iterators of different containers used where the same container is expected}}
+}
+
+void good_move(std::vector<int> &v1, std::vector<int> &v2) {
+ const auto i0 = ++v2.cbegin();
+ v1 = std::move(v2);
+ v1.erase(i0); // no-warning
+}
+
+void bad_move(std::vector<int> &v1, std::vector<int> &v2) {
+ const auto i0 = ++v2.cbegin();
+ v1 = std::move(v2);
+ v2.erase(i0); // expected-warning{{Container accessed using foreign iterator argument}}
+ // expected-warning@-1{{Method called on moved-from object of type 'std::vector'}}
+}
+
+void bad_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i0 = --v2.cend();
+ v1 = std::move(v2);
+ std::find(i0, v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}}
+ // expected-warning@-1{{Method called on moved-from object of type 'std::vector'}}
+}
+
+void bad_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) {
+ auto i0 = v2.cend();
+ v1 = std::move(v2);
+ std::find(v1.cbegin(), i0, n); // expected-warning{{Iterators of different containers used where the same container is expected}}
+}
+
+void bad_comparison(std::vector<int> &v1, std::vector<int> &v2) {
+ if (v1.cbegin() != v2.cend()) { // expected-warning{{Iterators of different containers used where the same container is expected}}
+ *v1.cbegin();
+ }
+}
diff --git a/test/Analysis/missing-bind-temporary.cpp b/test/Analysis/missing-bind-temporary.cpp
index 6071f5b5fae1..7be4e2ddf300 100644
--- a/test/Analysis/missing-bind-temporary.cpp
+++ b/test/Analysis/missing-bind-temporary.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=debug.DumpCFG -std=c++14 %s > %t 2>&1
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=debug.DumpCFG -std=c++14 -analyzer-config eagerly-assume=false %s > %t 2>&1
// RUN: FileCheck --input-file=%t %s
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=core,debug.ExprInspection -std=c++14 -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=core,debug.ExprInspection -std=c++14 -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/model-file.cpp b/test/Analysis/model-file.cpp
index de5a888ab223..c5615e92714d 100644
--- a/test/Analysis/model-file.cpp
+++ b/test/Analysis/model-file.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config faux-bodies=true,model-path=%S/Inputs/Models -analyzer-output=plist-multi-file -verify %s -o %t
-// RUN: FileCheck --input-file=%t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/model-file.cpp.plist -
typedef int* intptr;
@@ -38,283 +38,3 @@ int main() {
return 0;
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>22</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>25</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Division by zero</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Division by zero</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Division by zero</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DivideZero</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>86cb845e4f1e6abde1c5b319d5b08eca</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>main</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>15</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/new-aligned.cpp b/test/Analysis/new-aligned.cpp
new file mode 100644
index 000000000000..fae1f4864856
--- /dev/null
+++ b/test/Analysis/new-aligned.cpp
@@ -0,0 +1,14 @@
+//RUN: %clang_analyze_cc1 -std=c++17 -analyze -analyzer-checker=core -verify %s
+
+// expected-no-diagnostics
+
+// Notice the weird alignment.
+struct alignas(1024) S {};
+
+void foo() {
+ // Operator new() here is the C++17 aligned new that takes two arguments:
+ // size and alignment. Size is passed implicitly as usual, and alignment
+ // is passed implicitly in a similar manner.
+ S *s = new S; // no-warning
+ delete s;
+}
diff --git a/test/Analysis/new-ctor-conservative.cpp b/test/Analysis/new-ctor-conservative.cpp
index b82df9abf1e2..6cd403b50e5a 100644
--- a/test/Analysis/new-ctor-conservative.cpp
+++ b/test/Analysis/new-ctor-conservative.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
void clang_analyzer_warnIfReached();
diff --git a/test/Analysis/new-ctor-inlined.cpp b/test/Analysis/new-ctor-inlined.cpp
index 1506bf27f353..ca8c4da392d6 100644
--- a/test/Analysis/new-ctor-inlined.cpp
+++ b/test/Analysis/new-ctor-inlined.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/new-ctor-recursive.cpp b/test/Analysis/new-ctor-recursive.cpp
index e0c654bc74ab..f21795d1739a 100644
--- a/test/Analysis/new-ctor-recursive.cpp
+++ b/test/Analysis/new-ctor-recursive.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
void clang_analyzer_dump(int);
diff --git a/test/Analysis/new-ctor-symbolic.cpp b/test/Analysis/new-ctor-symbolic.cpp
index 8bef2ed2402c..be4379151278 100644
--- a/test/Analysis/new-ctor-symbolic.cpp
+++ b/test/Analysis/new-ctor-symbolic.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
void clang_analyzer_warnOnDeadSymbol(int);
diff --git a/test/Analysis/new.cpp b/test/Analysis/new.cpp
index 31f763266c38..3384cfeb6141 100644
--- a/test/Analysis/new.cpp
+++ b/test/Analysis/new.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify -analyzer-config eagerly-assume=false %s
#include "Inputs/system-header-simulator-cxx.h"
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/null-deref-path-notes.cpp b/test/Analysis/null-deref-path-notes.cpp
index 617f5def150a..dd54b24e7847 100644
--- a/test/Analysis/null-deref-path-notes.cpp
+++ b/test/Analysis/null-deref-path-notes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -w -x c++ -analyzer-checker=core -analyzer-output=text -analyzer-eagerly-assume -verify %s
+// RUN: %clang_analyze_cc1 -w -x c++ -analyzer-checker=core -analyzer-output=text -verify %s
namespace pr34731 {
int b;
diff --git a/test/Analysis/null-deref-path-notes.m b/test/Analysis/null-deref-path-notes.m
index 4a68d8f6fbae..46ca4b3e7819 100644
--- a/test/Analysis/null-deref-path-notes.m
+++ b/test/Analysis/null-deref-path-notes.m
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=text -fblocks -verify -Wno-objc-root-class %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=plist-multi-file -fblocks -Wno-objc-root-class %s -o %t
-// RUN: FileCheck --input-file=%t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/null-deref-path-notes.m.plist -
@interface Root {
@public
@@ -68,977 +68,3 @@ void testWithArrayPtr(WithArrayPtr *w) {
[w useArray]; // expected-note{{Calling 'useArray'}}
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;obj&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;obj&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>14</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;x&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3ff6dd9f2084f4a0dac8c3688c02fd0f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testNull</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;self&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;self&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;self&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;self&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Access to instance variable &apos;uniqueID&apos; results in a dereference of a null pointer (loaded from variable &apos;self&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Access to instance variable &apos;uniqueID&apos; results in a dereference of a null pointer (loaded from variable &apos;self&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Access to instance variable &apos;uniqueID&apos; results in a dereference of a null pointer (loaded from variable &apos;self&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>208c1267ca2da821fcc1b9183e1d624b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>initWithID:</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>33</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>40</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;coin&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>41</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>9e1f67627fbbfb46b4e3a618246e6b0a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>repeatedStores</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;useArray&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;useArray&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testWithArrayPtr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;testWithArrayPtr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Array access (via ivar &apos;p&apos;) results in a null pointer dereference</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Array access (via ivar &apos;p&apos;) results in a null pointer dereference</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Array access (via ivar &apos;p&apos;) results in a null pointer dereference</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fb0ad1e4e3090d9834d542eb54bc9d2e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>useArray</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/nullability-arc.mm b/test/Analysis/nullability-arc.mm
new file mode 100644
index 000000000000..5c68dda42ed3
--- /dev/null
+++ b/test/Analysis/nullability-arc.mm
@@ -0,0 +1,39 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,nullability\
+// RUN: -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,nullability\
+// RUN: -analyzer-output=text -verify %s -fobjc-arc
+
+#if !__has_feature(objc_arc)
+// expected-no-diagnostics
+#endif
+
+
+#define nil ((id)0)
+
+@interface Param
+@end
+
+@interface Base
+- (void)foo:(Param *_Nonnull)param;
+@end
+
+@interface Derived : Base
+@end
+
+@implementation Derived
+- (void)foo:(Param *)param {
+ // FIXME: Why do we not emit the warning under ARC?
+ [super foo:param];
+#if __has_feature(objc_arc)
+ // expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}}
+ // expected-note@-3 {{nil passed to a callee that requires a non-null 1st parameter}}
+#endif
+
+ [self foo:nil];
+#if __has_feature(objc_arc)
+ // expected-note@-2{{Calling 'foo:'}}
+ // expected-note@-3{{Passing nil object reference via 1st parameter 'param'}}
+#endif
+}
+@end
+
diff --git a/test/Analysis/nullability-notes.m b/test/Analysis/nullability-notes.m
index 8b6e1b02b642..850d18327ec7 100644
--- a/test/Analysis/nullability-notes.m
+++ b/test/Analysis/nullability-notes.m
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=plist -o %t.plist %s
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/nullability-notes.m.plist -
#include "Inputs/system-header-simulator-for-nullability.h"
@@ -19,186 +19,3 @@ void takesNonnull(NSObject *_Nonnull y);
}
@end
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Nullability &apos;nullable&apos; is inferred</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Nullability &apos;nullable&apos; is inferred</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Nullability</string>
-// CHECK-NEXT: <key>check_name</key><string>nullability.NullPassedToNonnull</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b6bc8126de8e6eb3375483a656fe858d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>method</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/nullability.mm b/test/Analysis/nullability.mm
index 2278efff3e99..c3f27e4d22a4 100644
--- a/test/Analysis/nullability.mm
+++ b/test/Analysis/nullability.mm
@@ -1,5 +1,36 @@
-// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -DNOSYSTEMHEADERS=0 -verify %s
-// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -DNOSYSTEMHEADERS=1 -verify %s
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \
+// RUN: -analyzer-checker=nullability.NullPassedToNonnull \
+// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull \
+// RUN: -analyzer-checker=nullability.NullablePassedToNonnull \
+// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull \
+// RUN: -analyzer-checker=nullability.NullableDereferenced \
+// RUN: -DNOSYSTEMHEADERS=0
+
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core \
+// RUN: -analyzer-checker=nullability.NullPassedToNonnull \
+// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull \
+// RUN: -analyzer-checker=nullability.NullablePassedToNonnull \
+// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull \
+// RUN: -analyzer-checker=nullability.NullableDereferenced \
+// RUN: -DNOSYSTEMHEADERS=1 \
+// RUN: -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true
+
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\
+// RUN: -analyzer-checker=nullability.NullPassedToNonnull\
+// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull\
+// RUN: -analyzer-checker=nullability.NullablePassedToNonnull\
+// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull\
+// RUN: -analyzer-checker=nullability.NullableDereferenced\
+// RUN: -DNOSYSTEMHEADERS=0 -fobjc-arc
+
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-checker=core\
+// RUN: -analyzer-checker=nullability.NullPassedToNonnull\
+// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull\
+// RUN: -analyzer-checker=nullability.NullablePassedToNonnull\
+// RUN: -analyzer-checker=nullability.NullableReturnedFromNonnull\
+// RUN: -analyzer-checker=nullability.NullableDereferenced\
+// RUN: -DNOSYSTEMHEADERS=1 -fobjc-arc\
+// RUN: -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true
#include "Inputs/system-header-simulator-for-nullability.h"
diff --git a/test/Analysis/objc-arc.m b/test/Analysis/objc-arc.m
index 687d63e24ee5..08fca7659cd7 100644
--- a/test/Analysis/objc-arc.m
+++ b/test/Analysis/objc-arc.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc -analyzer-output=plist-multi-file -o %t.plist %s
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/objc-arc.m.plist -
typedef signed char BOOL;
typedef struct _NSZone NSZone;
@@ -231,1913 +231,3 @@ id rdar14061675() {
return result;
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b41b510812f2a0d8735c67dfff6a9a5c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_working</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>61d185b2522d15fb327f6784e0217adf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_cf_leak</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;x&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;x&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;x&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>63df5972efc8a7acccdbd2aca10c9e9e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar9424882</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>119</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj1&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj1&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;obj1&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>125290ceaf2b55f5778c262d87b2b6d5</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>from_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj4&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj4&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;obj4&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>54627578ee3b8520400ae899bc32b3d6</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>from_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj5&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj5&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;obj5&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>27c31d7f5825a1613c0206b5be082800</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>from_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>48</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj6&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;obj6&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;obj6&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a59b85c1e38300cb17eaeedcf193f94b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>from_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>48</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj5&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj5&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;obj5&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5baa7d5f38420d0a035aa61607675f3e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>from_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>139</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>48</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>146</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj6&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj6&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;obj6&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4665e04694fd55e7c4ed7a67860b3b74</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>from_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>147</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>64</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf1&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf1&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;cf1&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>70a67cc8fefa3ad133a35c3ffb579b9e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>to_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>150</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>67</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf2&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf2&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;cf2&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>afc41cacb8f32bfbe4a4152f20cec5bc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>to_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>55</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf3&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf3&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;cf3&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>e512cd0ada59beca5acfa53e2a632670</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>to_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>58</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf4&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;cf4&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;cf4&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a43ae78dcef14395931eeb452f81819f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>to_cf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>165</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>798e65f80df0526369f9bb240e3d91fd</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_unretainedObject</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>178</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>193</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>193</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>193</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>193</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>196</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>e1fbcc142b678b3c2c43737ee35b64d9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_arrays</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>24</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;o&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>e300a279615a384d2b310329651d3978</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar11059275_positive</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>229</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>37efdaee587b783c6d49a228ff5ba49f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar14061675</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/objc-for.m b/test/Analysis/objc-for.m
index b59a5c2cf177..d4a04c1c3e80 100644
--- a/test/Analysis/objc-for.m
+++ b/test/Analysis/objc-for.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.Loops,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.Loops,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
diff --git a/test/Analysis/objc-radar17039661.m b/test/Analysis/objc-radar17039661.m
index 0d2ddbfc3060..484e43c5dd2c 100644
--- a/test/Analysis/objc-radar17039661.m
+++ b/test/Analysis/objc-radar17039661.m
@@ -1,6 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -analyzer-output=plist-multi-file %s -o %t
-// RUN: FileCheck --input-file=%t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/objc-radar17039661.m.plist -
+
@class NSString;
typedef long NSInteger;
typedef unsigned char BOOL;
@@ -58,1276 +59,3 @@ void runTest() {
return;
}
}
-
-// CHECK: <key>diagnostics</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>path</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>48</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>48</integer>
-// CHECK: <key>col</key><integer>15</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>26</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>38</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>26</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>26</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>53</integer>
-// CHECK: <key>col</key><integer>4</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>0</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Calling &apos;performAction&apos;</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Calling &apos;performAction&apos;</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>27</integer>
-// CHECK: <key>col</key><integer>1</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>depth</key><integer>1</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Entered call from &apos;runTest&apos;</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Entered call from &apos;runTest&apos;</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>27</integer>
-// CHECK: <key>col</key><integer>1</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>27</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>28</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>28</integer>
-// CHECK: <key>col</key><integer>15</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>28</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>28</integer>
-// CHECK: <key>col</key><integer>15</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>21</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>43</integer>
-// CHECK: <key>col</key><integer>4</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>1</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Calling &apos;reallyPerformAction&apos;</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Calling &apos;reallyPerformAction&apos;</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>22</integer>
-// CHECK: <key>col</key><integer>1</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>depth</key><integer>2</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Entered call from &apos;performAction&apos;</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Entered call from &apos;performAction&apos;</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>22</integer>
-// CHECK: <key>col</key><integer>1</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>22</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>16</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>58</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>2</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>23</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Entered call from &apos;reallyPerformAction&apos;</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Entered call from &apos;reallyPerformAction&apos;</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>23</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>23</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>12</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>12</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Assuming &apos;cond&apos; is not equal to 0</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Assuming &apos;cond&apos; is not equal to 0</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>12</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>30</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>30</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>50</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>NSNumber boxed expression produces an object with a +0 retain count</string>
-// CHECK: <key>message</key>
-// CHECK: <string>NSNumber boxed expression produces an object with a +0 retain count</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>38</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>50</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>40</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>depth</key><integer>4</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Entered call</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Entered call</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>40</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>40</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>17</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>21</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>21</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>39</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>22</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>31</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>4</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>17</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>10</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>50</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Returning to caller</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Returning to caller</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>38</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>37</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>37</integer>
-// CHECK: <key>col</key><integer>8</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>37</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>37</integer>
-// CHECK: <key>col</key><integer>8</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>40</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>40</integer>
-// CHECK: <key>col</key><integer>18</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>58</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>2</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Returning to caller</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Returning to caller</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>23</integer>
-// CHECK: <key>col</key><integer>16</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>24</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>24</integer>
-// CHECK: <key>col</key><integer>16</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>24</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>24</integer>
-// CHECK: <key>col</key><integer>3</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>24</integer>
-// CHECK: <key>col</key><integer>58</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>2</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>23</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Entered call from &apos;reallyPerformAction&apos;</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Entered call from &apos;reallyPerformAction&apos;</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>23</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>29</integer>
-// CHECK: <key>col</key><integer>23</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>6</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>12</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>12</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Assuming &apos;cond&apos; is not equal to 0</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Assuming &apos;cond&apos; is not equal to 0</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>9</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>31</integer>
-// CHECK: <key>col</key><integer>12</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>33</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>7</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>14</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>38</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>33</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>35</integer>
-// CHECK: <key>col</key><integer>50</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>3</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Calling anonymous block</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>40</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>depth</key><integer>4</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Entered call</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Entered call</string>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>40</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>49</integer>
-// CHECK: <key>col</key><integer>40</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>17</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>control</string>
-// CHECK: <key>edges</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>start</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>50</integer>
-// CHECK: <key>col</key><integer>17</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>end</key>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>10</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>kind</key><string>event</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <key>ranges</key>
-// CHECK: <array>
-// CHECK: <array>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>21</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: </array>
-// CHECK: <key>depth</key><integer>4</integer>
-// CHECK: <key>extended_message</key>
-// CHECK: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK: <key>message</key>
-// CHECK: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK: </dict>
-// CHECK: </array>
-// CHECK: <key>description</key><string>Potential leak of an object</string>
-// CHECK: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK: <key>type</key><string>Leak</string>
-// CHECK: <key>location</key>
-// CHECK: <dict>
-// CHECK: <key>line</key><integer>52</integer>
-// CHECK: <key>col</key><integer>5</integer>
-// CHECK: <key>file</key><integer>0</integer>
-// CHECK: </dict>
-// CHECK: </dict>
-// CHECK: </array>
diff --git a/test/Analysis/objcpp-uninitialized-object.mm b/test/Analysis/objcpp-uninitialized-object.mm
new file mode 100644
index 000000000000..8ea4b56998fc
--- /dev/null
+++ b/test/Analysis/objcpp-uninitialized-object.mm
@@ -0,0 +1,32 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -fblocks -verify %s
+
+typedef void (^myBlock) ();
+
+struct StructWithBlock {
+ int a;
+ myBlock z; // expected-note{{uninitialized field 'this->z'}}
+
+ StructWithBlock() : a(0), z(^{}) {}
+
+ // Miss initialization of field `z`.
+ StructWithBlock(int pA) : a(pA) {} // expected-warning{{1 uninitialized field at the end of the constructor call}}
+
+};
+
+void warnOnUninitializedBlock() {
+ StructWithBlock a(10);
+}
+
+void noWarningWhenInitialized() {
+ StructWithBlock a;
+}
+
+struct StructWithId {
+ int a;
+ id z; // expected-note{{uninitialized pointer 'this->z'}}
+ StructWithId() : a(0) {} // expected-warning{{1 uninitialized field at the end of the constructor call}}
+};
+
+void warnOnUninitializedId() {
+ StructWithId s;
+}
diff --git a/test/Analysis/osobject-retain-release.cpp b/test/Analysis/osobject-retain-release.cpp
new file mode 100644
index 000000000000..9d11a0623167
--- /dev/null
+++ b/test/Analysis/osobject-retain-release.cpp
@@ -0,0 +1,611 @@
+// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-output=text\
+// RUN: -analyzer-checker=core,osx -verify %s
+
+struct OSMetaClass;
+
+#define OS_CONSUME __attribute__((os_consumed))
+#define OS_RETURNS_RETAINED __attribute__((os_returns_retained))
+#define OS_RETURNS_RETAINED_ON_ZERO __attribute__((os_returns_retained_on_zero))
+#define OS_RETURNS_RETAINED_ON_NONZERO __attribute__((os_returns_retained_on_non_zero))
+#define OS_RETURNS_NOT_RETAINED __attribute__((os_returns_not_retained))
+#define OS_CONSUMES_THIS __attribute__((os_consumes_this))
+
+#define OSTypeID(type) (type::metaClass)
+
+#define OSDynamicCast(type, inst) \
+ ((type *) OSMetaClassBase::safeMetaCast((inst), OSTypeID(type)))
+
+using size_t = decltype(sizeof(int));
+
+struct OSObject {
+ virtual void retain();
+ virtual void release() {};
+ virtual void free();
+ virtual ~OSObject(){}
+
+ unsigned int foo() { return 42; }
+
+ virtual OS_RETURNS_NOT_RETAINED OSObject *identity();
+
+ static OSObject *generateObject(int);
+
+ static OSObject *getObject();
+ static OSObject *GetObject();
+
+ static void * operator new(size_t size);
+
+ static const OSMetaClass * const metaClass;
+};
+
+struct OSIterator : public OSObject {
+
+ static const OSMetaClass * const metaClass;
+};
+
+struct OSArray : public OSObject {
+ unsigned int getCount();
+
+ OSIterator * getIterator();
+
+ OSObject *identity() override;
+
+ virtual OSObject *generateObject(OSObject *input);
+
+ virtual void consumeReference(OS_CONSUME OSArray *other);
+
+ void putIntoArray(OSArray *array) OS_CONSUMES_THIS;
+
+ template <typename T>
+ void putIntoT(T *owner) OS_CONSUMES_THIS;
+
+ static OSArray *generateArrayHasCode() {
+ return new OSArray;
+ }
+
+ static OSArray *withCapacity(unsigned int capacity);
+ static void consumeArray(OS_CONSUME OSArray * array);
+
+ static OSArray* consumeArrayHasCode(OS_CONSUME OSArray * array) {
+ return nullptr;
+ }
+
+ static OS_RETURNS_NOT_RETAINED OSArray *MaskedGetter();
+ static OS_RETURNS_RETAINED OSArray *getOoopsActuallyCreate();
+
+ static const OSMetaClass * const metaClass;
+};
+
+struct MyArray : public OSArray {
+ void consumeReference(OSArray *other) override;
+
+ OSObject *identity() override;
+
+ OSObject *generateObject(OSObject *input) override;
+};
+
+struct OtherStruct {
+ static void doNothingToArray(OSArray *array);
+ OtherStruct(OSArray *arr);
+};
+
+struct OSMetaClassBase {
+ static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
+};
+
+void escape(void *);
+void escape_with_source(void *p) {}
+bool coin();
+
+typedef int kern_return_t;
+typedef kern_return_t IOReturn;
+typedef kern_return_t OSReturn;
+#define kOSReturnSuccess 0
+#define kIOReturnSuccess 0
+
+bool write_into_out_param_on_success(OS_RETURNS_RETAINED OSObject **obj);
+
+void use_out_param() {
+ OSObject *obj;
+ if (write_into_out_param_on_success(&obj)) {
+ obj->release();
+ }
+}
+
+void use_out_param_leak() {
+ OSObject *obj;
+ write_into_out_param_on_success(&obj); // expected-note-re{{Call to function 'write_into_out_param_on_success' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'obj' (assuming the call returns non-zero){{$}}}}
+} // expected-warning{{Potential leak of an object stored into 'obj'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+
+bool write_into_out_param_on_failure(OS_RETURNS_RETAINED_ON_ZERO OSObject **obj);
+
+void use_out_param_leak2() {
+ OSObject *obj;
+ write_into_out_param_on_failure(&obj); // expected-note-re{{Call to function 'write_into_out_param_on_failure' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'obj' (assuming the call returns zero){{$}}}}
+} // expected-warning{{Potential leak of an object stored into 'obj'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+
+void use_out_param_on_failure() {
+ OSObject *obj;
+ if (!write_into_out_param_on_failure(&obj)) {
+ obj->release();
+ }
+}
+
+IOReturn write_into_out_param_on_nonzero(OS_RETURNS_RETAINED_ON_NONZERO OSObject **obj);
+
+void use_out_param_on_nonzero() {
+ OSObject *obj;
+ if (write_into_out_param_on_nonzero(&obj) != kIOReturnSuccess) {
+ obj->release();
+ }
+}
+
+bool write_into_two_out_params(OS_RETURNS_RETAINED OSObject **a,
+ OS_RETURNS_RETAINED OSObject **b);
+
+void use_write_into_two_out_params() {
+ OSObject *obj1;
+ OSObject *obj2;
+ if (write_into_two_out_params(&obj1, &obj2)) {
+ obj1->release();
+ obj2->release();
+ }
+}
+
+void use_write_two_out_params_leak() {
+ OSObject *obj1;
+ OSObject *obj2;
+ write_into_two_out_params(&obj1, &obj2); // expected-note-re{{Call to function 'write_into_two_out_params' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'a' (assuming the call returns non-zero){{$}}}}
+ // expected-note-re@-1{{Call to function 'write_into_two_out_params' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'b' (assuming the call returns non-zero){{$}}}}
+} // expected-warning{{Potential leak of an object stored into 'obj1'}}
+ // expected-warning@-1{{Potential leak of an object stored into 'obj2'}}
+ // expected-note@-2{{Object leaked: object allocated and stored into 'obj1' is not referenced later in this execution path and has a retain count of +1}}
+ // expected-note@-3{{Object leaked: object allocated and stored into 'obj2' is not referenced later in this execution path and has a retain count of +1}}
+
+void always_write_into_two_out_params(OS_RETURNS_RETAINED OSObject **a,
+ OS_RETURNS_RETAINED OSObject **b);
+
+void use_always_write_into_two_out_params() {
+ OSObject *obj1;
+ OSObject *obj2;
+ always_write_into_two_out_params(&obj1, &obj2);
+ obj1->release();
+ obj2->release();
+}
+
+void use_always_write_into_two_out_params_leak() {
+ OSObject *obj1;
+ OSObject *obj2;
+ always_write_into_two_out_params(&obj1, &obj2); // expected-note-re{{Call to function 'always_write_into_two_out_params' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'a'{{$}}}}
+ // expected-note-re@-1{{Call to function 'always_write_into_two_out_params' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'b'{{$}}}}
+} // expected-warning{{Potential leak of an object stored into 'obj1'}}
+ // expected-warning@-1{{Potential leak of an object stored into 'obj2'}}
+ // expected-note@-2{{Object leaked: object allocated and stored into 'obj1' is not referenced later in this execution path and has a retain count of +1}}
+ // expected-note@-3{{Object leaked: object allocated and stored into 'obj2' is not referenced later in this execution path and has a retain count of +1}}
+
+char *write_into_out_param_on_nonnull(OS_RETURNS_RETAINED OSObject **obj);
+
+void use_out_param_osreturn_on_nonnull() {
+ OSObject *obj;
+ if (write_into_out_param_on_nonnull(&obj)) {
+ obj->release();
+ }
+}
+
+void use_out_param_leak_osreturn_on_nonnull() {
+ OSObject *obj;
+ write_into_out_param_on_nonnull(&obj); // expected-note-re{{Call to function 'write_into_out_param_on_nonnull' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'obj' (assuming the call returns non-zero){{$}}}}
+} // expected-warning{{Potential leak of an object stored into 'obj'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+
+bool write_optional_out_param(OS_RETURNS_RETAINED OSObject **obj=nullptr);
+
+void use_optional_out_param() {
+ if (write_optional_out_param()) {};
+}
+
+OSReturn write_into_out_param_on_os_success(OS_RETURNS_RETAINED OSObject **obj);
+
+void write_into_non_retained_out_param(OS_RETURNS_NOT_RETAINED OSObject **obj);
+
+void use_write_into_non_retained_out_param() {
+ OSObject *obj;
+ write_into_non_retained_out_param(&obj);
+}
+
+void use_write_into_non_retained_out_param_uaf() {
+ OSObject *obj;
+ write_into_non_retained_out_param(&obj); // expected-note-re{{Call to function 'write_into_non_retained_out_param' writes an OSObject of type 'OSObject' with a +0 retain count into an out parameter 'obj'{{$}}}}
+ obj->release(); // expected-warning{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+ // expected-note@-1{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+}
+
+void always_write_into_out_param(OS_RETURNS_RETAINED OSObject **obj);
+
+void pass_through_out_param(OSObject **obj) {
+ always_write_into_out_param(obj);
+}
+
+void always_write_into_out_param_has_source(OS_RETURNS_RETAINED OSObject **obj) {
+ *obj = new OSObject; // expected-note{{Operator 'new' returns an OSObject of type 'OSObject' with a +1 retain count}}
+}
+
+void use_always_write_into_out_param_has_source_leak() {
+ OSObject *obj;
+ always_write_into_out_param_has_source(&obj); // expected-note{{Calling 'always_write_into_out_param_has_source'}}
+ // expected-note@-1{{Returning from 'always_write_into_out_param_has_source'}}
+} // expected-warning{{Potential leak of an object stored into 'obj'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+
+void use_void_out_param_osreturn() {
+ OSObject *obj;
+ always_write_into_out_param(&obj);
+ obj->release();
+}
+
+void use_void_out_param_osreturn_leak() {
+ OSObject *obj;
+ always_write_into_out_param(&obj); // expected-note-re{{Call to function 'always_write_into_out_param' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'obj'{{$}}}}
+} // expected-warning{{Potential leak of an object stored into 'obj'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+
+void use_out_param_osreturn() {
+ OSObject *obj;
+ if (write_into_out_param_on_os_success(&obj) == kOSReturnSuccess) {
+ obj->release();
+ }
+}
+
+void use_out_param_leak_osreturn() {
+ OSObject *obj;
+ write_into_out_param_on_os_success(&obj); // expected-note-re{{Call to function 'write_into_out_param_on_os_success' writes an OSObject of type 'OSObject' with a +1 retain count into an out parameter 'obj' (assuming the call returns zero){{$}}}}
+} // expected-warning{{Potential leak of an object stored into 'obj'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+
+struct StructWithField {
+ OSObject *obj;
+
+ void initViaOutParamCall() { // no warning on writing into fields
+ always_write_into_out_param(&obj);
+ }
+
+};
+
+bool os_consume_violation_two_args(OS_CONSUME OSObject *obj, bool extra) {
+ if (coin()) { // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ escape(obj);
+ return true;
+ }
+ return false; // expected-note{{Parameter 'obj' is marked as consuming, but the function did not consume the reference}}
+}
+
+bool os_consume_violation(OS_CONSUME OSObject *obj) {
+ if (coin()) { // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ escape(obj);
+ return true;
+ }
+ return false; // expected-note{{Parameter 'obj' is marked as consuming, but the function did not consume the reference}}
+}
+
+void os_consume_ok(OS_CONSUME OSObject *obj) {
+ escape(obj);
+}
+
+void use_os_consume_violation() {
+ OSObject *obj = new OSObject; // expected-note{{Operator 'new' returns an OSObject of type 'OSObject' with a +1 retain count}}
+ os_consume_violation(obj); // expected-note{{Calling 'os_consume_violation'}}
+ // expected-note@-1{{Returning from 'os_consume_violation'}}
+} // expected-note{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+ // expected-warning@-1{{Potential leak of an object stored into 'obj'}}
+
+void use_os_consume_violation_two_args() {
+ OSObject *obj = new OSObject; // expected-note{{Operator 'new' returns an OSObject of type 'OSObject' with a +1 retain count}}
+ os_consume_violation_two_args(obj, coin()); // expected-note{{Calling 'os_consume_violation_two_args'}}
+ // expected-note@-1{{Returning from 'os_consume_violation_two_args'}}
+} // expected-note{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+ // expected-warning@-1{{Potential leak of an object stored into 'obj'}}
+
+void use_os_consume_ok() {
+ OSObject *obj = new OSObject;
+ os_consume_ok(obj);
+}
+
+void test_escaping_into_voidstar() {
+ OSObject *obj = new OSObject;
+ escape(obj);
+}
+
+void test_escape_has_source() {
+ OSObject *obj = new OSObject;
+ if (obj)
+ escape_with_source(obj);
+ return;
+}
+
+void test_no_infinite_check_recursion(MyArray *arr) {
+ OSObject *input = new OSObject;
+ OSObject *o = arr->generateObject(input);
+ o->release();
+ input->release();
+}
+
+
+void check_param_attribute_propagation(MyArray *parent) {
+ OSArray *arr = new OSArray;
+ parent->consumeReference(arr);
+}
+
+unsigned int check_attribute_propagation(OSArray *arr) {
+ OSObject *other = arr->identity();
+ OSArray *casted = OSDynamicCast(OSArray, other);
+ if (casted)
+ return casted->getCount();
+ return 0;
+}
+
+unsigned int check_attribute_indirect_propagation(MyArray *arr) {
+ OSObject *other = arr->identity();
+ OSArray *casted = OSDynamicCast(OSArray, other);
+ if (casted)
+ return casted->getCount();
+ return 0;
+}
+
+void check_consumes_this(OSArray *owner) {
+ OSArray *arr = new OSArray;
+ arr->putIntoArray(owner);
+}
+
+void check_consumes_this_with_template(OSArray *owner) {
+ OSArray *arr = new OSArray;
+ arr->putIntoT(owner);
+}
+
+void check_free_no_error() {
+ OSArray *arr = OSArray::withCapacity(10);
+ arr->retain();
+ arr->retain();
+ arr->retain();
+ arr->free();
+}
+
+void check_free_use_after_free() {
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ arr->retain(); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
+ arr->free(); // expected-note{{Object released}}
+ arr->retain(); // expected-warning{{Reference-counted object is used after it is released}}
+ // expected-note@-1{{Reference-counted object is used after it is released}}
+}
+
+unsigned int check_leak_explicit_new() {
+ OSArray *arr = new OSArray; // expected-note{{Operator 'new' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ return arr->getCount(); // expected-note{{Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1}}
+ // expected-warning@-1{{Potential leak of an object stored into 'arr'}}
+}
+
+unsigned int check_leak_factory() {
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ return arr->getCount(); // expected-note{{Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1}}
+ // expected-warning@-1{{Potential leak of an object stored into 'arr'}}
+}
+
+void check_get_object() {
+ OSObject::getObject();
+}
+
+void check_Get_object() {
+ OSObject::GetObject();
+}
+
+void check_custom_iterator_rule(OSArray *arr) {
+ OSIterator *it = arr->getIterator();
+ it->release();
+}
+
+void check_iterator_leak(OSArray *arr) {
+ arr->getIterator(); // expected-note{{Call to method 'OSArray::getIterator' returns an OSObject of type 'OSIterator' with a +1 retain count}}
+} // expected-note{{Object leaked: allocated object of type 'OSIterator' is not referenced later}}
+ // expected-warning@-1{{Potential leak of an object of type 'OSIterator}}'
+
+void check_no_invalidation() {
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ OtherStruct::doNothingToArray(arr);
+} // expected-warning{{Potential leak of an object stored into 'arr'}}
+ // expected-note@-1{{Object leaked}}
+
+void check_no_invalidation_other_struct() {
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ OtherStruct other(arr); // expected-warning{{Potential leak}}
+ // expected-note@-1{{Object leaked}}
+}
+
+struct ArrayOwner : public OSObject {
+ OSArray *arr;
+ ArrayOwner(OSArray *arr) : arr(arr) {}
+
+ static ArrayOwner* create(OSArray *arr) {
+ return new ArrayOwner(arr);
+ }
+
+ OSArray *getArray() {
+ return arr;
+ }
+
+ OSArray *createArray() {
+ return OSArray::withCapacity(10);
+ }
+
+ OSArray *createArraySourceUnknown();
+
+ OSArray *getArraySourceUnknown();
+};
+
+OSArray *generateArray() {
+ return OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ // expected-note@-1{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+}
+
+unsigned int check_leak_good_error_message() {
+ unsigned int out;
+ {
+ OSArray *leaked = generateArray(); // expected-note{{Calling 'generateArray'}}
+ // expected-note@-1{{Returning from 'generateArray'}}
+ out = leaked->getCount(); // expected-warning{{Potential leak of an object stored into 'leaked'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
+ }
+ return out;
+}
+
+unsigned int check_leak_msg_temporary() {
+ return generateArray()->getCount(); // expected-warning{{Potential leak of an object}}
+ // expected-note@-1{{Calling 'generateArray'}}
+ // expected-note@-2{{Returning from 'generateArray'}}
+ // expected-note@-3{{Object leaked: allocated object of type 'OSArray' is not referenced later in this execution path and has a retain count of +1}}
+}
+
+void check_confusing_getters() {
+ OSArray *arr = OSArray::withCapacity(10);
+
+ ArrayOwner *AO = ArrayOwner::create(arr);
+ AO->getArray();
+
+ AO->release();
+ arr->release();
+}
+
+void check_rc_consumed() {
+ OSArray *arr = OSArray::withCapacity(10);
+ OSArray::consumeArray(arr);
+}
+
+void check_rc_consume_temporary() {
+ OSArray::consumeArray(OSArray::withCapacity(10));
+}
+
+void check_rc_getter() {
+ OSArray *arr = OSArray::MaskedGetter();
+ (void)arr;
+}
+
+void check_rc_create() {
+ OSArray *arr = OSArray::getOoopsActuallyCreate();
+ arr->release();
+}
+
+
+void check_dynamic_cast() {
+ OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1));
+ arr->release();
+}
+
+unsigned int check_dynamic_cast_no_null_on_orig(OSObject *obj) {
+ OSArray *arr = OSDynamicCast(OSArray, obj);
+ if (arr) {
+ return arr->getCount();
+ } else {
+
+ // The fact that dynamic cast has failed should not imply that
+ // the input object was null.
+ return obj->foo(); // no-warning
+ }
+}
+
+void check_dynamic_cast_null_branch(OSObject *obj) {
+ OSArray *arr1 = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject}}
+ OSArray *arr = OSDynamicCast(OSArray, obj);
+ if (!arr) // expected-note{{Taking true branch}}
+ return; // expected-warning{{Potential leak of an object stored into 'arr1'}}
+ // expected-note@-1{{Object leaked}}
+ arr1->release();
+}
+
+void check_dynamic_cast_null_check() {
+ OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); // expected-note{{Call to method 'OSObject::generateObject' returns an OSObject}}
+ // expected-warning@-1{{Potential leak of an object}}
+ // expected-note@-2{{Object leaked}}
+ if (!arr)
+ return;
+ arr->release();
+}
+
+void use_after_release() {
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ arr->release(); // expected-note{{Object released}}
+ arr->getCount(); // expected-warning{{Reference-counted object is used after it is released}}
+ // expected-note@-1{{Reference-counted object is used after it is released}}
+}
+
+void potential_leak() {
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject of type 'OSArray' with a +1 retain count}}
+ arr->retain(); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
+ arr->release(); // expected-note{{Reference count decremented. The object now has a +1 retain count}}
+ arr->getCount();
+} // expected-warning{{Potential leak of an object stored into 'arr'}}
+ // expected-note@-1{{Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1}}
+
+void proper_cleanup() {
+ OSArray *arr = OSArray::withCapacity(10); // +1
+ arr->retain(); // +2
+ arr->release(); // +1
+ arr->getCount();
+ arr->release(); // 0
+}
+
+unsigned int no_warning_on_getter(ArrayOwner *owner) {
+ OSArray *arr = owner->getArray();
+ return arr->getCount();
+}
+
+unsigned int warn_on_overrelease(ArrayOwner *owner) {
+ // FIXME: summaries are not applied in case the source of the getter/setter
+ // is known.
+ // rdar://45681203
+ OSArray *arr = owner->getArray();
+ arr->release();
+ return arr->getCount();
+}
+
+unsigned int nowarn_on_release_of_created(ArrayOwner *owner) {
+ OSArray *arr = owner->createArray();
+ unsigned int out = arr->getCount();
+ arr->release();
+ return out;
+}
+
+unsigned int nowarn_on_release_of_created_source_unknown(ArrayOwner *owner) {
+ OSArray *arr = owner->createArraySourceUnknown();
+ unsigned int out = arr->getCount();
+ arr->release();
+ return out;
+}
+
+unsigned int no_warn_ok_release(ArrayOwner *owner) {
+ OSArray *arr = owner->getArray(); // +0
+ arr->retain(); // +1
+ arr->release(); // +0
+ return arr->getCount(); // no-warning
+}
+
+unsigned int warn_on_overrelease_with_unknown_source(ArrayOwner *owner) {
+ OSArray *arr = owner->getArraySourceUnknown(); // expected-note{{Call to method 'ArrayOwner::getArraySourceUnknown' returns an OSObject of type 'OSArray' with a +0 retain count}}
+ arr->release(); // expected-warning{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+ // expected-note@-1{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+ return arr->getCount();
+}
+
+unsigned int ok_release_with_unknown_source(ArrayOwner *owner) {
+ OSArray *arr = owner->getArraySourceUnknown(); // +0
+ arr->retain(); // +1
+ arr->release(); // +0
+ return arr->getCount();
+}
+
+OSObject *getObject();
+typedef bool (^Blk)(OSObject *);
+
+void test_escape_to_unknown_block(Blk blk) {
+ blk(getObject()); // no-crash
+}
diff --git a/test/Analysis/padding_inherit.cpp b/test/Analysis/padding_inherit.cpp
new file mode 100644
index 000000000000..2222c990a1dc
--- /dev/null
+++ b/test/Analysis/padding_inherit.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=optin.performance -analyzer-config optin.performance.Padding:AllowedPad=20 -verify %s
+
+// A class that has no fields and one base class should visit that base class
+// instead. Note that despite having excess padding of 2, this is flagged
+// because of its usage in an array of 100 elements below (`ais').
+// TODO: Add a note to the bug report with BugReport::addNote() to mention the
+// variable using the class and also mention what class is inherting from what.
+// expected-warning@+1{{Excessive padding in 'struct FakeIntSandwich'}}
+struct FakeIntSandwich {
+ char c1;
+ int i;
+ char c2;
+};
+
+struct AnotherIntSandwich : FakeIntSandwich { // no-warning
+};
+
+// But we don't yet support multiple base classes.
+struct IntSandwich {};
+struct TooManyBaseClasses : FakeIntSandwich, IntSandwich { // no-warning
+};
+
+AnotherIntSandwich ais[100];
+
+struct Empty {};
+struct DoubleEmpty : Empty { // no-warning
+ Empty e;
+};
diff --git a/test/Analysis/plist-macros-with-expansion.cpp b/test/Analysis/plist-macros-with-expansion.cpp
new file mode 100644
index 000000000000..c3175a332115
--- /dev/null
+++ b/test/Analysis/plist-macros-with-expansion.cpp
@@ -0,0 +1,442 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+//
+// RUN: %clang_analyze_cc1 -analyzer-checker=core %s \
+// RUN: -analyzer-output=plist -o %t.plist \
+// RUN: -analyzer-config expand-macros=true
+//
+// Check the actual plist output.
+// RUN: cat %t.plist | %diff_plist \
+// RUN: %S/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist -
+//
+// Check the macro expansions from the plist output here, to make the test more
+// understandable.
+// RUN: FileCheck --input-file=%t.plist %s
+
+void print(const void*);
+
+//===----------------------------------------------------------------------===//
+// Tests for non-function-like macro expansions.
+//===----------------------------------------------------------------------===//
+
+#define SET_PTR_VAR_TO_NULL \
+ ptr = 0
+
+void nonFunctionLikeMacroTest() {
+ int *ptr;
+ SET_PTR_VAR_TO_NULL;
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>SET_PTR_VAR_TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>ptr = 0</string>
+
+#define NULL 0
+#define SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO \
+ ptr = NULL
+
+void nonFunctionLikeNestedMacroTest() {
+ int *ptr;
+ SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO;
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO</string>
+// CHECK-NEXT: <key>expansion</key><string>ptr =0</string>
+
+//===----------------------------------------------------------------------===//
+// Tests for function-like macro expansions.
+//===----------------------------------------------------------------------===//
+
+void setToNull(int **vptr) {
+ *vptr = nullptr;
+}
+
+#define TO_NULL(x) \
+ setToNull(x)
+
+void functionLikeMacroTest() {
+ int *ptr;
+ TO_NULL(&ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>setToNull(&amp;ptr)</string>
+
+#define DOES_NOTHING(x) \
+ { \
+ int b; \
+ b = 5; \
+ } \
+ print(x)
+
+#define DEREF(x) \
+ DOES_NOTHING(x); \
+ *x
+
+void functionLikeNestedMacroTest() {
+ int *a;
+ TO_NULL(&a);
+ DEREF(a) = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>setToNull(&amp;a)</string>
+
+// CHECK: <key>name</key><string>DEREF</string>
+// CHECK-NEXT: <key>expansion</key><string>{ int b; b = 5; } print(a); *a</string>
+
+//===----------------------------------------------------------------------===//
+// Tests for undefining and/or redifining macros.
+//===----------------------------------------------------------------------===//
+
+#define WILL_UNDEF_SET_NULL_TO_PTR(ptr) \
+ ptr = nullptr;
+
+void undefinedMacroByTheEndOfParsingTest() {
+ int *ptr;
+ WILL_UNDEF_SET_NULL_TO_PTR(ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+#undef WILL_UNDEF_SET_NULL_TO_PTR
+
+// CHECK: <key>name</key><string>WILL_UNDEF_SET_NULL_TO_PTR</string>
+// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string>
+
+#define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
+ /* Nothing */
+#undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL
+#define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
+ ptr = nullptr;
+
+void macroRedefinedMultipleTimesTest() {
+ int *ptr;
+ WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr)
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+#undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL
+#define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
+ print("This string shouldn't be in the plist file at all. Or anywhere, " \
+ "but here.");
+
+// CHECK: <key>name</key><string>WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string>
+
+#define WILL_UNDEF_SET_NULL_TO_PTR_2(ptr) \
+ ptr = nullptr;
+
+#define PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr) \
+ WILL_UNDEF_SET_NULL_TO_PTR_2(ptr)
+
+void undefinedMacroInsideAnotherMacroTest() {
+ int *ptr;
+ PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// TODO: Expand arguments.
+// CHECK: <key>name</key><string>PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD</string>
+// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string>
+
+#undef WILL_UNDEF_SET_NULL_TO_PTR_2
+
+//===----------------------------------------------------------------------===//
+// Tests for macro arguments containing commas and parantheses.
+//
+// As of writing these tests, the algorithm expands macro arguments by lexing
+// the macro's expansion location, and relies on finding tok::comma and
+// tok::l_paren/tok::r_paren.
+//===----------------------------------------------------------------------===//
+
+// Note that this commas, parantheses in strings aren't parsed as tok::comma or
+// tok::l_paren/tok::r_paren, but why not test them.
+
+#define TO_NULL_AND_PRINT(x, str) \
+ x = 0; \
+ print(str)
+
+void macroArgContainsCommaInStringTest() {
+ int *a;
+ TO_NULL_AND_PRINT(a, "Will this , cause a crash?");
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string>
+// CHECK-NEXT: <key>expansion</key><string>a = 0; print( &quot;Will this , cause a crash?&quot;)</string>
+
+void macroArgContainsLParenInStringTest() {
+ int *a;
+ TO_NULL_AND_PRINT(a, "Will this ( cause a crash?");
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string>
+// CHECK-NEXT: <key>expansion</key><string>a = 0; print( &quot;Will this ( cause a crash?&quot;)</string>
+
+void macroArgContainsRParenInStringTest() {
+ int *a;
+ TO_NULL_AND_PRINT(a, "Will this ) cause a crash?");
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string>
+// CHECK-NEXT: <key>expansion</key><string>a = 0; print( &quot;Will this ) cause a crash?&quot;)</string>
+
+#define CALL_FUNCTION(funcCall) \
+ funcCall
+
+// Function calls do contain both tok::comma and tok::l_paren/tok::r_paren.
+
+void macroArgContainsLParenRParenTest() {
+ int *a;
+ CALL_FUNCTION(setToNull(&a));
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>CALL_FUNCTION</string>
+// CHECK-NEXT: <key>expansion</key><string>setToNull(&amp;a)</string>
+
+void setToNullAndPrint(int **vptr, const char *str) {
+ setToNull(vptr);
+ print(str);
+}
+
+void macroArgContainsCommaLParenRParenTest() {
+ int *a;
+ CALL_FUNCTION(setToNullAndPrint(&a, "Hello!"));
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>CALL_FUNCTION</string>
+// CHECK-NEXT: <key>expansion</key><string>setToNullAndPrint(&amp;a, &quot;Hello!&quot;)</string>
+
+#define CALL_FUNCTION_WITH_TWO_PARAMS(funcCall, param1, param2) \
+ funcCall(param1, param2)
+
+void macroArgContainsCommaLParenRParenTest2() {
+ int *a;
+ CALL_FUNCTION_WITH_TWO_PARAMS(setToNullAndPrint, &a, "Hello!");
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>CALL_FUNCTION_WITH_TWO_PARAMS</string>
+// CHECK-NEXT: <key>expansion</key><string>setToNullAndPrint( &amp;a, &quot;Hello!&quot;)</string>
+
+#define CALL_LAMBDA(l) \
+ l()
+
+void commaInBracketsTest() {
+ int *ptr;
+ const char str[] = "Hello!";
+ // You need to add parantheses around a lambda expression to compile this,
+ // else the comma in the capture will be parsed as divider of macro args.
+ CALL_LAMBDA(([&ptr, str] () mutable { TO_NULL(&ptr); }));
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>CALL_LAMBDA</string>
+// CHECK-NEXT: <key>expansion</key><string>([&amp;ptr, str] () mutable { setToNull(&amp;ptr); })()</string>
+
+#define PASTE_CODE(code) \
+ code
+
+void commaInBracesTest() {
+ PASTE_CODE({ // expected-warning{{Dereference of null pointer}}
+ // NOTE: If we were to add a new variable here after a comma, we'd get a
+ // compilation error, so this test is mainly here to show that this was also
+ // investigated.
+
+ // int *ptr = nullptr, a;
+ int *ptr = nullptr;
+ *ptr = 5;
+ })
+}
+
+// CHECK: <key>name</key><string>PASTE_CODE</string>
+// CHECK-NEXT: <key>expansion</key><string>{ int *ptr = nullptr; *ptr = 5; }</string>
+
+// Example taken from
+// https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html#Macro-Arguments.
+
+#define POTENTIALLY_EMPTY_PARAM(x, y) \
+ x; \
+ y = nullptr
+
+void emptyParamTest() {
+ int *ptr;
+
+ POTENTIALLY_EMPTY_PARAM(,ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>POTENTIALLY_EMPTY_PARAM</string>
+// CHECK-NEXT: <key>expansion</key><string>;ptr = nullptr</string>
+
+#define NESTED_EMPTY_PARAM(a, b) \
+ POTENTIALLY_EMPTY_PARAM(a, b);
+
+
+void nestedEmptyParamTest() {
+ int *ptr;
+
+ NESTED_EMPTY_PARAM(, ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>NESTED_EMPTY_PARAM</string>
+// CHECK-NEXT: <key>expansion</key><string>; ptr = nullptr;</string>
+
+#define CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO(func, param) \
+ CALL_FUNCTION(func(param))
+
+void lParenRParenInNestedMacro() {
+ int *ptr;
+ CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO(setToNull, &ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO</string>
+// CHECK-NEXT: <key>expansion</key><string>setToNull( &amp;ptr)</string>
+
+//===----------------------------------------------------------------------===//
+// Tests for variadic macro arguments.
+//===----------------------------------------------------------------------===//
+
+template <typename ...Args>
+void variadicFunc(Args ...args);
+
+#define VARIADIC_SET_TO_NULL(ptr, ...) \
+ ptr = nullptr; \
+ variadicFunc(__VA_ARGS__)
+
+void variadicMacroArgumentTest() {
+ int *ptr;
+ VARIADIC_SET_TO_NULL(ptr, 1, 5, "haha!");
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>VARIADIC_SET_TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr; variadicFunc( 1, 5, &quot;haha!&quot;)</string>
+
+void variadicMacroArgumentWithoutAnyArgumentTest() {
+ int *ptr;
+ // Not adding a single parameter to ... is silly (and also causes a
+ // preprocessor warning), but is not an excuse to crash on it.
+ VARIADIC_SET_TO_NULL(ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>VARIADIC_SET_TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>ptr = nullptr; variadicFunc()</string>
+
+//===----------------------------------------------------------------------===//
+// Tests for # and ##.
+//===----------------------------------------------------------------------===//
+
+#define DECLARE_FUNC_AND_SET_TO_NULL(funcName, ptr) \
+ void generated_##funcName(); \
+ ptr = nullptr;
+
+void hashHashOperatorTest() {
+ int *ptr;
+ DECLARE_FUNC_AND_SET_TO_NULL(whatever, ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>DECLARE_FUNC_AND_SET_TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>void generated_whatever(); ptr = nullptr;</string>
+
+void macroArgContainsHashHashInStringTest() {
+ int *a;
+ TO_NULL_AND_PRINT(a, "Will this ## cause a crash?");
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string>
+// CHECK-NEXT: <key>expansion</key><string>a = 0; print( &quot;Will this ## cause a crash?&quot;)</string>
+
+#define PRINT_STR(str, ptr) \
+ print(#str); \
+ ptr = nullptr
+
+void hashOperatorTest() {
+ int *ptr;
+ PRINT_STR(Hello, ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>PRINT_STR</string>
+// CHECK-NEXT: <key>expansion</key><string>print(&quot;Hello&quot;); ptr = nullptr</string>
+
+void macroArgContainsHashInStringTest() {
+ int *a;
+ TO_NULL_AND_PRINT(a, "Will this # cause a crash?");
+ *a = 5; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string>
+// CHECK-NEXT: <key>expansion</key><string>a = 0; print( &quot;Will this # cause a crash?&quot;)</string>
+
+//===----------------------------------------------------------------------===//
+// Tests for more complex macro expansions.
+//
+// We won't cover anything that wasn't covered up to this point, but rather
+// show more complex, macros with deeper nesting, more arguments (some unused)
+// and so on.
+//===----------------------------------------------------------------------===//
+
+#define IF(Condition) \
+ if ( Condition )
+
+#define L_BRACE {
+#define R_BRACE }
+#define LESS <
+#define GREATER >
+#define EQUALS =
+#define SEMICOLON ;
+#define NEGATIVE -
+#define RETURN return
+#define ZERO 0
+
+#define EUCLIDEAN_ALGORITHM(A, B) \
+ IF(A LESS ZERO) L_BRACE \
+ A EQUALS NEGATIVE A SEMICOLON \
+ R_BRACE \
+ IF(B LESS ZERO) L_BRACE \
+ B EQUALS NEGATIVE B SEMICOLON \
+ R_BRACE \
+ \
+ /* This is where a while loop would be, but that seems to be too complex */ \
+ /* for the analyzer just yet. Let's just pretend that this algorithm */ \
+ /* works. */ \
+ \
+ RETURN B / (B - B) SEMICOLON
+
+int getLowestCommonDenominator(int A, int B) {
+ EUCLIDEAN_ALGORITHM(A, B) // expected-warning{{Division by zero}}
+}
+
+void testVeryComplexAlgorithm() {
+ int tmp = 8 / (getLowestCommonDenominator(5, 7) - 1);
+ print(&tmp);
+}
+// CHECK: <key>name</key><string>EUCLIDEAN_ALGORITHM</string>
+// CHECK-NEXT: <key>expansion</key><string>if (A&lt;0 ){A=-A;} if ( B&lt;0 ){ B=- B;}return B / ( B - B);</string>
+
+#define YET_ANOTHER_SET_TO_NULL(x, y, z) \
+ print((void *) x); \
+ print((void *) y); \
+ z = nullptr;
+
+#define DO_NOTHING(str) str
+#define DO_NOTHING2(str2) DO_NOTHING(str2)
+
+void test() {
+ int *ptr;
+ YET_ANOTHER_SET_TO_NULL(5, DO_NOTHING2("Remember the Vasa"), ptr);
+ *ptr = 5; // expected-warning{{Dereference of null pointer}}
+}
+// CHECK: <key>name</key><string>YET_ANOTHER_SET_TO_NULL</string>
+// CHECK-NEXT: <key>expansion</key><string>print((void *)5); print((void *)&quot;Remember the Vasa&quot;); ptr = nullptr;</string>
diff --git a/test/Analysis/plist-macros.cpp b/test/Analysis/plist-macros.cpp
index 4f7d3a254574..3eb604e2edd5 100644
--- a/test/Analysis/plist-macros.cpp
+++ b/test/Analysis/plist-macros.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -analyzer-output=plist-multi-file %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-output=plist-multi-file %s -o %t.plist
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/plist-macros.cpp.plist -
typedef __typeof(sizeof(int)) size_t;
@@ -86,1668 +86,3 @@ void test1() {
void test2(int *p) {
CALL_FN(p);
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>13</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory allocated by malloc() should be deallocated by free(), not &apos;delete&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory allocated by malloc() should be deallocated by free(), not &apos;delete&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Memory allocated by malloc() should be deallocated by free(), not &apos;delete&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Bad deallocator</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.MismatchedDeallocator</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>81d63a132b4ef0cc96734c17440a1c26</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>noteOnMacro</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Memory is allocated</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>20</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of memory pointed to by &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory error</string>
-// CHECK-NEXT: <key>type</key><string>Memory leak</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.Malloc</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2d723d9fb4e5f10dd54a7396866dfce4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>macroIsFirstInFunction</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>21</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>27</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is equal to null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is equal to null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>28</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3570104919aab3f953357f8c87b68bd7</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>macroInExpression</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>35</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>deff163b13f3fd860bc332498b0dbc59</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>macroInExpressionNoNote</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>39</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is equal to null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is equal to null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>45</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b67b58d85375752578e947b77c6aa70c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>macroWithArgInExpression</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b53410f6c0d3d07e62ce5c6f91a1810a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>useMultiNoteMacroWithError</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>68</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>69</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>41f58f9549aa1867e461a7996a8d335c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>useMultiNote</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;a&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Passing null pointer value via 1st parameter &apos;a&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;null_deref&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;null_deref&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test1&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test1&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;a&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2dc47a4afc2f349f12217b38588769f4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>null_deref</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/plist-output-alternate.m b/test/Analysis/plist-output-alternate.m
index 1a80a4d5c637..525f738dc7b7 100644
--- a/test/Analysis/plist-output-alternate.m
+++ b/test/Analysis/plist-output-alternate.m
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -fblocks -analyzer-output=plist -o %t %s
-// RUN: FileCheck --input-file %t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/plist-output-alternate.m.plist -
void test_null_init(void) {
int *p = 0;
@@ -57,1440 +57,3 @@ void rdar8331641(int x) {
(void) value;
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dc9c2a657ca759f9744cde2e093cfd59</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_init</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8f95d9681490a4e52c167969d0957b39</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_assign</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>94c43fbcad6aaff4ee7433f2d2db0bbe</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_assign_transitive</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>659f01507ffd7efd3ca3eab7179fd7d2</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_cond</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c90d51e62139e614b57aff7021240a82</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_cond_transitive</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;x.p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;x.p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>245408d2bc416e324064d990e6dd82a8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_field</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>82</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>54</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>29a10ca4af622b6146ca082e49d919d6</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar8331641</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m
index 6b39e31e0e30..21602fc47224 100644
--- a/test/Analysis/plist-output.m
+++ b/test/Analysis/plist-output.m
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 %s -analyzer-checker=osx.cocoa.RetainCount,deadcode.DeadStores,core -analyzer-output=plist -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: %clang_analyze_cc1 -analyzer-config eagerly-assume=false %s -analyzer-checker=osx.cocoa.RetainCount,deadcode.DeadStores,core -analyzer-output=plist -o %t.plist
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/plist-output.m.plist -
void test_null_init(void) {
int *p = 0;
@@ -194,5975 +194,3 @@ int testFoo(Foo *x) {
return *[x returnsPointer];
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>5</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dc9c2a657ca759f9744cde2e093cfd59</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_init</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>6</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>10</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>11</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8f95d9681490a4e52c167969d0957b39</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_assign</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>12</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>16</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>17</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;q&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>18</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;q&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>94c43fbcad6aaff4ee7433f2d2db0bbe</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_assign_transitive</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>19</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>23</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>659f01507ffd7efd3ca3eab7179fd7d2</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_cond</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>24</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>29</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>30</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c90d51e62139e614b57aff7021240a82</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_cond_transitive</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>31</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>36</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;x.p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;x.p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>37</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from field &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>245408d2bc416e324064d990e6dd82a8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_null_field</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>38</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;b&apos; is equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;b&apos; is equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>46</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b12acffa40177b55b695aa2292533410</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_assumptions</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value assigned to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming pointer value is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>56</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c0a32b8291b0fc7230f847f05f415625</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_cond_assign</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>75</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>76</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ea1d5db6b4c380a432c88139fdd18f42</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;foo&apos; during its initialization is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;foo&apos; during its initialization is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead initialization</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3dd1ebf91fa4e92eeec82faaeb48beda</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming the condition is true</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>86</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;foo&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f533db5cbb9c20d171f9f92105789dc4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>88</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>95</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>08f9a01186cb2f1b78b08ec20260f1c1</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar12280665</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>107</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>93a53e4c8f02d191b07477940ddcf89c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>radar12322528_for</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>111</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body executed 0 times</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>117</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f2d2dbf579b0b21a6b68726df6a041fc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>radar12322528_while</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>127</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>128</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>95c7d39fb9d0d8c172b894e02855a07c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>radar12322528_foo_2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>134</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4cbbc713c8267513fef8a33f1327d7ca</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_diagnostics</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>143</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>144</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a5aa7cf7ce6ba6683bebfff63df926fd</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_diagnostics_2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>145</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>149</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>149</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>152</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>154</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Looping back to the head of the loop</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>151</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3917bac4f8fdce1f6c6393b1f14a1320</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_diagnostics_3</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>155</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Value stored to &apos;x&apos; is never read</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Value stored to &apos;x&apos; is never read</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Value stored to &apos;x&apos; is never read</string>
-// CHECK-NEXT: <key>category</key><string>Dead store</string>
-// CHECK-NEXT: <key>type</key><string>Dead increment</string>
-// CHECK-NEXT: <key>check_name</key><string>deadcode.DeadStores</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c94f341ebaf0fac5d6703aaa7e6bee9b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_fast_enumeration</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;x&apos; declared without an initial value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Loop body skipped when collection is empty</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Assigned value is garbage or undefined</string>
-// CHECK-NEXT: <key>check_name</key><string>core.uninitialized.Assign</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>21c774309bdfd487c3d09a61a671bbcc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_loop_fast_enumeration</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>163</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from ivar &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b21eba78798501dc6b716bb91e3f7f01</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;s.i&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;s.i&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Null pointer passed as an argument to a &apos;nonnull&apos; parameter</string>
-// CHECK-NEXT: <key>category</key><string>API</string>
-// CHECK-NEXT: <key>type</key><string>Argument with &apos;nonnull&apos; attribute passed null</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NonNullParamChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c0b359a043c633f1b8d1581f68743361</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>RDar13295437</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;returnsPointer&apos; not called because the receiver is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a225fec9dc1e56142b68b3df82b00b6c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testFoo</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>194</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/plist-stats-output.c b/test/Analysis/plist-stats-output.c
index 072fe5e2971a..cab9523d79bc 100644
--- a/test/Analysis/plist-stats-output.c
+++ b/test/Analysis/plist-stats-output.c
@@ -8,6 +8,9 @@ int foo() {}
// CHECK: <key>diagnostics</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>files</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
// CHECK-NEXT: <key>statistics</key>
// CHECK-NEXT: <string>{
// CHECK: }
diff --git a/test/Analysis/pr22954.c b/test/Analysis/pr22954.c
index b4273c0a8943..6d5b04417a1e 100644
--- a/test/Analysis/pr22954.c
+++ b/test/Analysis/pr22954.c
@@ -3,7 +3,7 @@
// At the moment the whole of the destination array content is invalidated.
// If a.s1 region has a symbolic offset, the whole region of 'a' is invalidated.
// Specific triple set to test structures of size 0.
-// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
typedef __typeof(sizeof(int)) size_t;
@@ -585,7 +585,7 @@ int f28(int i, int j, int k, int l) {
m28[j].s3[k] = 1;
struct ll * l28 = (struct ll*)(&m28[1]);
l28->s1[l] = 2;
- char input[] = {'a', 'b', 'c', 'd'};
+ char input[] = {'a', 'b', 'c', 'd'}; // expected-warning{{Potential leak of memory pointed to by field 's4'}}
memcpy(l28->s1, input, 4);
clang_analyzer_eval(m28[0].s3[0] == 1); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(m28[0].s3[1] == 1); // expected-warning{{UNKNOWN}}
diff --git a/test/Analysis/properties.m b/test/Analysis/properties.m
index e792bb2e6bad..461639f4c2bf 100644
--- a/test/Analysis/properties.m
+++ b/test/Analysis/properties.m
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c
index c0b20508d8f5..8c57ab827cf7 100644
--- a/test/Analysis/ptr-arith.c
+++ b/test/Analysis/ptr-arith.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/reference.cpp b/test/Analysis/reference.cpp
index c269dd7bad10..9f3082a8b856 100644
--- a/test/Analysis/reference.cpp
+++ b/test/Analysis/reference.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -Wno-null-dereference -Wno-tautological-undefined-compare %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -Wno-null-dereference -Wno-tautological-undefined-compare -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/region-store.c b/test/Analysis/region-store.c
index 673baafa0959..f4b149d28207 100644
--- a/test/Analysis/region-store.c
+++ b/test/Analysis/region-store.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
int printf(const char *restrict,...);
diff --git a/test/Analysis/retain-release-arc.m b/test/Analysis/retain-release-arc.m
index 78115ac5bde0..31081e964abb 100644
--- a/test/Analysis/retain-release-arc.m
+++ b/test/Analysis/retain-release-arc.m
@@ -90,13 +90,12 @@ void _dispatch_object_validate(dispatch_object_t object);
CFErrorRef error;
CFDictionaryRef testDict = CFPropertyListCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)plistData, 0, 0, &error);
#if HAS_ARC
- // expected-note@-2 {{Call to function 'CFPropertyListCreateWithData' returns a Core Foundation object of type CFPropertyListRef with a +1 retain count}}
+ // expected-note@-2 {{Call to function 'CFPropertyListCreateWithData' returns a Core Foundation object of type 'CFPropertyListRef' with a +1 retain count}}
#endif
return (__bridge NSDictionary *)testDict;
#if HAS_ARC
// expected-warning@-2 {{Potential leak of an object stored into 'testDict'}}
- // expected-note@-3 {{Object returned to caller as an owning reference (single retain count transferred to caller)}}
- // expected-note@-4 {{Object leaked: object allocated and stored into 'testDict' is returned from a method managed by Automatic Reference Counting}}
+ // expected-note@-3 {{Object leaked: object allocated and stored into 'testDict' is returned from a method managed by Automatic Reference Counting}}
#endif
}
diff --git a/test/Analysis/retain-release-cpp-classes.cpp b/test/Analysis/retain-release-cpp-classes.cpp
new file mode 100644
index 000000000000..9ed1c0b3b567
--- /dev/null
+++ b/test/Analysis/retain-release-cpp-classes.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=text -verify %s
+
+// expected-no-diagnostics
+
+typedef void *CFTypeRef;
+typedef struct _CFURLCacheRef *CFURLCacheRef;
+
+CFTypeRef CustomCFRetain(CFTypeRef);
+void invalidate(void *);
+struct S1 {
+ CFTypeRef s;
+ CFTypeRef returnFieldAtPlus0() {
+ return s;
+ }
+};
+struct S2 {
+ S1 *s1;
+};
+void foo(S1 *s1) {
+ invalidate(s1);
+ S2 s2;
+ s2.s1 = s1;
+ CustomCFRetain(s1->returnFieldAtPlus0());
+
+ // Definitely no leak end-of-path note here. The retained pointer
+ // is still accessible through s1 and s2.
+ ((void) 0); // no-warning
+
+ // FIXME: Ideally we need to warn after this invalidate(). The per-function
+ // retain-release contract is violated: the programmer should release
+ // the symbol after it was retained, within the same function.
+ invalidate(&s2);
+}
diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m
deleted file mode 100644
index 6305942ac20a..000000000000
--- a/test/Analysis/retain-release-gc-only.m
+++ /dev/null
@@ -1,434 +0,0 @@
-// RUN: %clang_analyze_cc1 -triple %itanium_abi_triple -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.NSAutoreleasePool -analyzer-store=region -fobjc-gc-only -fblocks -verify -Wno-objc-root-class %s
-
-//===----------------------------------------------------------------------===//
-// Header stuff.
-//===----------------------------------------------------------------------===//
-
-typedef unsigned int __darwin_natural_t;
-typedef unsigned long uintptr_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
-typedef unsigned int UInt32;
-typedef signed long CFIndex;
-typedef struct {
- CFIndex location;
- CFIndex length;
-} CFRange;
-static __inline__ __attribute__((always_inline)) CFRange CFRangeMake(CFIndex loc, CFIndex len) {
- CFRange range;
- range.location = loc;
- range.length = len;
- return range;
-}
-typedef const void * CFTypeRef;
-typedef const struct __CFString * CFStringRef;
-typedef const struct __CFAllocator * CFAllocatorRef;
-extern const CFAllocatorRef kCFAllocatorDefault;
-extern CFTypeRef CFRetain(CFTypeRef cf);
-extern void CFRelease(CFTypeRef cf);
-typedef struct {
-}
-CFArrayCallBacks;
-extern const CFArrayCallBacks kCFTypeArrayCallBacks;
-typedef const struct __CFArray * CFArrayRef;
-typedef struct __CFArray * CFMutableArrayRef;
-extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks);
-extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);
-extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value);
-typedef struct {
-}
-CFDictionaryKeyCallBacks;
-extern const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks;
-typedef struct {
-}
-CFDictionaryValueCallBacks;
-extern const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks;
-typedef const struct __CFDictionary * CFDictionaryRef;
-typedef struct __CFDictionary * CFMutableDictionaryRef;
-extern CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks);
-typedef UInt32 CFStringEncoding;
-enum {
-kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 };
-extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding);
-typedef double CFTimeInterval;
-typedef CFTimeInterval CFAbsoluteTime;
-extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void);
-typedef const struct __CFDate * CFDateRef;
-extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
-extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
-typedef __darwin_natural_t natural_t;
-typedef natural_t mach_port_name_t;
-typedef mach_port_name_t mach_port_t;
-typedef int kern_return_t;
-typedef kern_return_t mach_error_t;
-enum {
-kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2, kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4, kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6, kCFNumberCharType = 7, kCFNumberShortType = 8, kCFNumberIntType = 9, kCFNumberLongType = 10, kCFNumberLongLongType = 11, kCFNumberFloatType = 12, kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14, kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16, kCFNumberMaxType = 16 };
-typedef CFIndex CFNumberType;
-typedef const struct __CFNumber * CFNumberRef;
-extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
-typedef const struct __CFAttributedString *CFAttributedStringRef;
-typedef struct __CFAttributedString *CFMutableAttributedStringRef;
-extern CFAttributedStringRef CFAttributedStringCreate(CFAllocatorRef alloc, CFStringRef str, CFDictionaryRef attributes) ;
-extern CFMutableAttributedStringRef CFAttributedStringCreateMutableCopy(CFAllocatorRef alloc, CFIndex maxLength, CFAttributedStringRef aStr) ;
-extern void CFAttributedStringSetAttribute(CFMutableAttributedStringRef aStr, CFRange range, CFStringRef attrName, CFTypeRef value) ;
-typedef signed char BOOL;
-typedef unsigned long NSUInteger;
-@class NSString, Protocol;
-extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
-typedef struct _NSZone NSZone;
-@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
-@protocol NSObject
-- (BOOL)isEqual:(id)object;
-- (id)retain;
-- (oneway void)release;
-- (id)autorelease;
-- (Class)class;
-@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone;
-@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone;
-@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;
-@end
-@interface NSObject <NSObject> {}
-+ (id)allocWithZone:(NSZone *)zone;
-+ (id)alloc;
-- (void)dealloc;
-- (oneway void)release;
-- (id)copy;
-@end
-@interface NSObject (NSCoderMethods)
-- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder;
-@end
-extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
-typedef struct {
-}
-NSFastEnumerationState;
-@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
-@end @class NSString, NSDictionary;
-@interface NSValue : NSObject <NSCopying, NSCoding> - (void)getValue:(void *)value;
-@end @interface NSNumber : NSValue - (char)charValue;
-- (id)initWithInt:(int)value;
-@end @class NSString;
-@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
-- (NSUInteger)count;
-@end
-@interface NSArray (NSArrayCreation)
-+ (id)array;
-+ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
-@end
- @interface NSAutoreleasePool : NSObject {
-}
-- (void)drain;
-- (id)init;
-@end extern NSString * const NSBundleDidLoadNotification;
-typedef double NSTimeInterval;
-@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate;
-@end typedef unsigned short unichar;
-@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
-- ( const char *)UTF8String;
-- (id)initWithUTF8String:(const char *)nullTerminatedCString;
-+ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
-@end @class NSString, NSURL, NSError;
-@interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
-+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
-+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
-@end @class NSLocale, NSDate, NSCalendar, NSTimeZone, NSError, NSArray, NSMutableDictionary;
-@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
-@end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey;
-- (void)setObject:(id)anObject forKey:(id)aKey;
-@end @interface NSMutableDictionary (NSMutableDictionaryCreation) + (id)dictionaryWithCapacity:(NSUInteger)numItems;
-@end typedef double CGFloat;
-struct CGSize {
-};
-typedef struct CGSize CGSize;
-struct CGRect {
-};
-typedef struct CGRect CGRect;
-typedef mach_port_t io_object_t;
-typedef char io_name_t[128];
-typedef io_object_t io_iterator_t;
-typedef io_object_t io_service_t;
-typedef struct IONotificationPort * IONotificationPortRef;
-typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator );
-io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching );
-kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing );
-kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) __attribute__((deprecated));
-kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification );
-CFMutableDictionaryRef IOServiceMatching( const char * name );
-CFMutableDictionaryRef IOServiceNameMatching( const char * name );
-CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName );
-CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path );
-CFMutableDictionaryRef IORegistryEntryIDMatching( uint64_t entryID );
-typedef struct __DASession * DASessionRef;
-extern DASessionRef DASessionCreate( CFAllocatorRef allocator );
-typedef struct __DADisk * DADiskRef;
-extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name );
-extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media );
-extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk );
-extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk );
-@interface NSTask : NSObject - (id)init;
-@end typedef struct CGColorSpace *CGColorSpaceRef;
-typedef struct CGImage *CGImageRef;
-typedef struct CGLayer *CGLayerRef;
-@interface NSResponder : NSObject <NSCoding> {
-}
-@end @protocol NSAnimatablePropertyContainer - (id)animator;
-@end extern NSString *NSAnimationTriggerOrderIn ;
-@interface NSView : NSResponder <NSAnimatablePropertyContainer> {
-}
-@end @protocol NSValidatedUserInterfaceItem - (SEL)action;
-@end @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem;
-@end @class NSDate, NSDictionary, NSError, NSException, NSNotification;
-@interface NSApplication : NSResponder <NSUserInterfaceValidations> {
-}
-@end enum {
-NSTerminateCancel = 0, NSTerminateNow = 1, NSTerminateLater = 2 };
-typedef NSUInteger NSApplicationTerminateReply;
-@protocol NSApplicationDelegate <NSObject> @optional - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
-@end @class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView, NSTextView;
-@interface NSCell : NSObject <NSCopying, NSCoding> {
-}
-@end @class NSTextField, NSPanel, NSArray, NSWindow, NSImage, NSButton, NSError;
-typedef struct {
-}
-CVTimeStamp;
-@interface CIImage : NSObject <NSCoding, NSCopying> {
-}
-typedef int CIFormat;
-@end enum {
-kDAReturnSuccess = 0, kDAReturnError = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C };
-typedef mach_error_t DAReturn;
-typedef const struct __DADissenter * DADissenterRef;
-extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string );
-@interface CIContext: NSObject {
-}
-- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r;
-- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs;
-- (CGLayerRef)createCGLayerWithSize:(CGSize)size info:(CFDictionaryRef)d;
-@end extern NSString* const QCRendererEventKey;
-@protocol QCCompositionRenderer - (NSDictionary*) attributes;
-@end @interface QCRenderer : NSObject <QCCompositionRenderer> {
-}
-- (id) createSnapshotImageOfType:(NSString*)type;
-@end extern NSString* const QCViewDidStartRenderingNotification;
-@interface QCView : NSView <QCCompositionRenderer> {
-}
-- (id) createSnapshotImageOfType:(NSString*)type;
-@end enum {
-ICEXIFOrientation1 = 1, ICEXIFOrientation2 = 2, ICEXIFOrientation3 = 3, ICEXIFOrientation4 = 4, ICEXIFOrientation5 = 5, ICEXIFOrientation6 = 6, ICEXIFOrientation7 = 7, ICEXIFOrientation8 = 8, };
-@class ICDevice;
-@protocol ICDeviceDelegate <NSObject> @required - (void)didRemoveDevice:(ICDevice*)device;
-@end extern NSString *const ICScannerStatusWarmingUp;
-@class ICScannerDevice;
-@protocol ICScannerDeviceDelegate <ICDeviceDelegate> @optional - (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner;
-@end
-CFTypeRef CFMakeCollectable(CFTypeRef cf) ;
-
-static __inline__ __attribute__((always_inline)) id NSMakeCollectable(CFTypeRef
-cf) {
- return cf ? (id)CFMakeCollectable(cf) : ((void*)0);
-}
-
-//===----------------------------------------------------------------------===//
-// Test cases.
-//===----------------------------------------------------------------------===//
-
-void f1() {
- CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning
- id x = [(id) A autorelease];
- CFRelease((CFMutableArrayRef) x);
-}
-
-void f2() {
- CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}}
- id x = [(id) A retain];
- [x release];
- [x release];
-}
-
-void f3() {
- CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}}
- CFMakeCollectable(A);
- CFRetain(A);
-}
-
-void f3b() {
- CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning
- CFMakeCollectable(A);
-}
-
-
-void f4() {
- CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}}
- NSMakeCollectable(A);
- CFRetain(A);
-}
-
-void f4b() {
- CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning
- NSMakeCollectable(A);
-}
-
-void f5() {
- id x = [NSMakeCollectable(CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks)) autorelease]; // no-warning
-}
-
-void f5b() {
- id x = [(id) CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks) autorelease]; // expected-warning{{leak}}
-}
-
-// Test return of non-owned objects in contexts where an owned object
-// is expected.
-@interface TestReturnNotOwnedWhenExpectedOwned
-- (NSString*)newString;
-- (CFMutableArrayRef)newArray;
-@end
-
-@implementation TestReturnNotOwnedWhenExpectedOwned
-- (NSString*)newString {
- NSString *s = [NSString stringWithUTF8String:"hello"]; // expected-warning{{Potential leak (when using garbage collection) of an object}}
- CFRetain(s);
- return s;
-}
-- (CFMutableArrayRef)newArray{
- return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning
-}
-@end
-
-//===----------------------------------------------------------------------===//
-// <rdar://problem/6948053> False positive: object substitution during -init*
-// methods warns about returning +0 when using -fobjc-gc-only
-//===----------------------------------------------------------------------===//
-
-@interface MyClassRdar6948053 : NSObject
-- (id) init;
-+ (id) shared;
-@end
-
-@implementation MyClassRdar6948053
-+(id) shared {
- return (id) 0;
-}
-- (id) init
-{
- Class myClass = [self class];
- [self release];
- return [[myClass shared] retain]; // no-warning
-}
-@end
-
-//===----------------------------------------------------------------------===//
-// <rdar://problem/7174400> 'ciContext createCGImage:outputImage fromRect:' returns a retained CF object (not GC'ed)//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-void rdar_7174400(QCView *view, QCRenderer *renderer, CIContext *context,
- NSString *str, CIImage *img, CGRect rect,
- CIFormat form, CGColorSpaceRef cs) {
- [view createSnapshotImageOfType:str]; // no-warning
- [renderer createSnapshotImageOfType:str]; // no-warning
- [context createCGImage:img fromRect:rect]; // expected-warning{{leak}}
- [context createCGImage:img fromRect:rect format:form colorSpace:cs]; // expected-warning{{leak}}
-}
-
-//===----------------------------------------------------------------------===//
-// <rdar://problem/6250216> Warn against using -[NSAutoreleasePool release] in
-// GC mode
-//===----------------------------------------------------------------------===//
-
-void rdar_6250216(void) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- [pool release]; // expected-warning{{Use -drain instead of -release when using NSAutoreleasePool and garbage collection}}
-}
-
-
-//===----------------------------------------------------------------------===//
-// <rdar://problem/7407273> Don't crash when analyzing messages sent to blocks
-//===----------------------------------------------------------------------===//
-
-@class RDar7407273;
-typedef void (^RDar7407273Block)(RDar7407273 *operation);
-void rdar7407273(RDar7407273Block b) {
- [b copy];
-}
-
-//===----------------------------------------------------------------------===//
-// Tests of ownership attributes.
-//===----------------------------------------------------------------------===//
-
-@interface TestOwnershipAttr : NSObject
-- (NSString*) returnsAnOwnedString __attribute__((ns_returns_retained));
-- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_retained));
-@end
-
-void test_attr_1(TestOwnershipAttr *X) {
- NSString *str = [X returnsAnOwnedString]; // no-warning
-}
-
-void test_attr_1b(TestOwnershipAttr *X) {
- NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
-}
-
-@interface MyClassTestCFAttr : NSObject {}
-- (NSDate*) returnsCFRetained __attribute__((cf_returns_retained));
-- (NSDate*) alsoReturnsRetained;
-- (NSDate*) returnsNSRetained __attribute__((ns_returns_retained));
-@end
-
-__attribute__((cf_returns_retained))
-CFDateRef returnsRetainedCFDate() {
- return CFDateCreate(0, CFAbsoluteTimeGetCurrent());
-}
-
-@implementation MyClassTestCFAttr
-- (NSDate*) returnsCFRetained {
- return (NSDate*) returnsRetainedCFDate(); // No leak.
-}
-
-- (NSDate*) alsoReturnsRetained {
- return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
-}
-
-- (NSDate*) returnsNSRetained {
- return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
-}
-@end
-
-
-#if __has_feature(attribute_ns_consumed)
-#define NS_CONSUMED __attribute__((ns_consumed))
-#endif
-#if __has_feature(attribute_cf_consumed)
-#define CF_CONSUMED __attribute__((cf_consumed))
-#endif
-
-void consumeAndStopTracking(id NS_CONSUMED obj, void (^callback)(void));
-void CFConsumeAndStopTracking(CFTypeRef CF_CONSUMED obj, void (^callback)(void));
-
-void testConsumeAndStopTracking() {
- id retained = [@[] retain]; // +0, GC
- consumeAndStopTracking(retained, ^{}); // no-warning
-
- id doubleRetained = [[@[] retain] retain]; // +0, GC
- consumeAndStopTracking(doubleRetained, ^{
- [doubleRetained release];
- }); // no-warning
-
- id unretained = @[]; // +0
- consumeAndStopTracking(unretained, ^{}); // no-warning, GC
-}
-
-void testCFConsumeAndStopTrackingMsg() {
- id retained = [@[] retain]; // +0, GC
- CFConsumeAndStopTracking((CFTypeRef)retained, ^{}); // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
-}
-
-void testCFConsumeAndStopTracking() {
- CFTypeRef retained = returnsRetainedCFDate(); // +1
- CFConsumeAndStopTracking(retained, ^{}); // no-warning
-
- CFTypeRef doubleRetained = CFRetain(returnsRetainedCFDate()); // +2
- CFConsumeAndStopTracking(doubleRetained, ^{
- CFRelease(doubleRetained);
- }); // no-warning
-
- id unretained = @[]; // +0
- CFConsumeAndStopTracking((CFTypeRef)unretained, ^{}); // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
-}
diff --git a/test/Analysis/retain-release-path-notes-gc.m b/test/Analysis/retain-release-path-notes-gc.m
deleted file mode 100644
index 307aef1a5e20..000000000000
--- a/test/Analysis/retain-release-path-notes-gc.m
+++ /dev/null
@@ -1,1245 +0,0 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=plist-multi-file %s -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
-
-/***
-This file is for testing the path-sensitive notes for retain/release errors.
-Its goal is to have simple branch coverage of any path-based diagnostics,
-not to actually check all possible retain/release errors.
-
-This file is for notes that only appear in a GC-enabled analysis.
-Non-specific and ref-count-only notes should go in retain-release-path-notes.m.
-***/
-
-@interface NSObject
-+ (id)alloc;
-- (id)init;
-- (void)dealloc;
-
-- (Class)class;
-
-- (id)retain;
-- (void)release;
-- (void)autorelease;
-@end
-
-@interface Foo : NSObject
-- (id)methodWithValue;
-@property(retain) id propertyValue;
-@end
-
-typedef struct CFType *CFTypeRef;
-CFTypeRef CFRetain(CFTypeRef);
-void CFRelease(CFTypeRef);
-
-id NSMakeCollectable(CFTypeRef);
-CFTypeRef CFMakeCollectable(CFTypeRef);
-
-CFTypeRef CFCreateSomething();
-CFTypeRef CFGetSomething();
-
-
-void creationViaCFCreate () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
- return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
-}
-
-void makeCollectable () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
- CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
- CFMakeCollectable(leaked); // expected-note{{In GC mode a call to 'CFMakeCollectable' decrements an object's retain count and registers the object with the garbage collector. An object must have a 0 retain count to be garbage collected. After this call its retain count is +1}}
- NSMakeCollectable(leaked); // expected-note{{In GC mode a call to 'NSMakeCollectable' decrements an object's retain count and registers the object with the garbage collector. Since it now has a 0 retain count the object can be automatically collected by the garbage collector}}
- CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +1 retain count. The object is not eligible for garbage collection until the retain count reaches 0 again}}
- return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
-}
-
-void retainReleaseIgnored () {
- id object = [[NSObject alloc] init]; // expected-note{{Method returns an instance of NSObject with a +0 retain count}}
- [object retain]; // expected-note{{In GC mode the 'retain' message has no effect}}
- [object release]; // expected-note{{In GC mode the 'release' message has no effect}}
- [object autorelease]; // expected-note{{In GC mode an 'autorelease' has no effect}}
- CFRelease((CFTypeRef)object); // expected-warning{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}} expected-note{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
-}
-
-@implementation Foo (FundamentalRuleUnderGC)
-- (id)getViolation {
- id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
- return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'getViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
-}
-
-- (id)copyViolation {
- id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
- return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'copyViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
-}
-@end
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>43</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak (when using garbage collection) of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of object when using garbage collection</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>487197d1f3d333a1fb4d7610b6d852df</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>creationViaCFCreate</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>44</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>49</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>In GC mode a call to &apos;CFMakeCollectable&apos; decrements an object&apos;s retain count and registers the object with the garbage collector. An object must have a 0 retain count to be garbage collected. After this call its retain count is +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>In GC mode a call to &apos;CFMakeCollectable&apos; decrements an object&apos;s retain count and registers the object with the garbage collector. An object must have a 0 retain count to be garbage collected. After this call its retain count is +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>In GC mode a call to &apos;NSMakeCollectable&apos; decrements an object&apos;s retain count and registers the object with the garbage collector. Since it now has a 0 retain count the object can be automatically collected by the garbage collector</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>In GC mode a call to &apos;NSMakeCollectable&apos; decrements an object&apos;s retain count and registers the object with the garbage collector. Since it now has a 0 retain count the object can be automatically collected by the garbage collector</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>51</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count. The object is not eligible for garbage collection until the retain count reaches 0 again</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count. The object is not eligible for garbage collection until the retain count reaches 0 again</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak (when using garbage collection) of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of object when using garbage collection</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4f71073d5e7f2546564c1614dfc95420</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>makeCollectable</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>In GC mode the &apos;retain&apos; message has no effect</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>In GC mode the &apos;retain&apos; message has no effect</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>In GC mode the &apos;release&apos; message has no effect</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>In GC mode the &apos;release&apos; message has no effect</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>In GC mode an &apos;autorelease&apos; has no effect</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>In GC mode an &apos;autorelease&apos; has no effect</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3d18c66bf99e8cd2938e8c63c345f6ea</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>retainReleaseIgnored</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;object&apos; and returned from method &apos;getViolation&apos; is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;object&apos; and returned from method &apos;getViolation&apos; is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak (when using garbage collection) of an object stored into &apos;object&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object when using garbage collection</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d012b4dfd7d763f06cdb53f8b5708275</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>getViolation</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;object&apos; and returned from method &apos;copyViolation&apos; is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;object&apos; and returned from method &apos;copyViolation&apos; is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak (when using garbage collection) of an object stored into &apos;object&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object when using garbage collection</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b241509266f9d666b8335e0ee2f45adf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>copyViolation</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/retain-release-path-notes.m b/test/Analysis/retain-release-path-notes.m
index 719a4d488cc0..23171eda1cc3 100644
--- a/test/Analysis/retain-release-path-notes.m
+++ b/test/Analysis/retain-release-path-notes.m
@@ -1,6 +1,6 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -verify %s
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=plist-multi-file %s -o %t
-// RUN: FileCheck --input-file=%t %s
+// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/retain-release-path-notes.m.plist -
/***
This file is for testing the path-sensitive notes for retain/release errors.
@@ -49,7 +49,7 @@ void creationViaAlloc () {
}
void creationViaCFCreate () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type 'CFTypeRef' with a +1 retain count}}
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
@@ -68,7 +68,7 @@ void acquisitionViaProperty (Foo *foo) {
}
void acquisitionViaCFFunction () {
- CFTypeRef leaked = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
+ CFTypeRef leaked = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type 'CFTypeRef' with a +0 retain count}}
CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +1 retain count}}
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
@@ -98,42 +98,42 @@ void autoreleaseUnowned (Foo *foo) {
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased but has a +0 retain count}}
}
-void makeCollectableIgnored () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
- CFMakeCollectable(leaked); // expected-note{{When GC is not enabled a call to 'CFMakeCollectable' has no effect on its argument}}
- NSMakeCollectable(leaked); // expected-note{{When GC is not enabled a call to 'NSMakeCollectable' has no effect on its argument}}
+void makeCollectableIgnored() {
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type 'CFTypeRef' with a +1 retain count}}
+ CFMakeCollectable(leaked);
+ NSMakeCollectable(leaked);
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
CFTypeRef CFCopyRuleViolation () {
- CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
- return object; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+ CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type 'CFTypeRef' with a +0 retain count}}
+ return object; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
}
CFTypeRef CFGetRuleViolation () {
- CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
- return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' is returned from a function whose name ('CFGetRuleViolation') does not contain 'Copy' or 'Create'. This violates the naming convention rules given in the Memory Management Guide for Core Foundation}}
+ CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type 'CFTypeRef' with a +1 retain count}}
+ return object; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'object' is returned from a function whose name ('CFGetRuleViolation') does not contain 'Copy' or 'Create'. This violates the naming convention rules given in the Memory Management Guide for Core Foundation}}
}
@implementation Foo (FundamentalMemoryManagementRules)
- (id)copyViolation {
id result = self.propertyValue; // expected-note{{Property returns an Objective-C object with a +0 retain count}}
- return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+ return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
}
- (id)copyViolationIndexedSubscript {
id result = self[0]; // expected-note{{Subscript returns an Objective-C object with a +0 retain count}}
- return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+ return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
}
- (id)copyViolationKeyedSubscript {
id result = self[self]; // expected-note{{Subscript returns an Objective-C object with a +0 retain count}}
- return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+ return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
}
- (id)getViolation {
id result = [[Foo alloc] init]; // expected-note{{Method returns an instance of Foo with a +1 retain count}}
- return result; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'result' is returned from a method whose name ('getViolation') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'. This violates the naming convention rules given in the Memory Management Guide for Cocoa}}
+ return result; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'result' is returned from a method whose name ('getViolation') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'. This violates the naming convention rules given in the Memory Management Guide for Cocoa}}
}
- (id)copyAutorelease {
@@ -227,7 +227,7 @@ static int Cond;
// expected-note@-1 {{Method returns an instance of MyObj with a +1 retain count}}
// expected-note@-2 {{Calling 'initX'}}
// expected-note@-3 {{Returning from 'initX'}}
- // expected-note@-4 {{Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1}}
+ // expected-note@-4 {{Object leaked: allocated object of type 'MyObj *' is not referenced later in this execution path and has a retain count of +1}}
// initI is inlined because the allocation happens within initY
id y = [[MyObj alloc] initY];
// expected-note@-1 {{Calling 'initY'}}
@@ -235,7 +235,7 @@ static int Cond;
// initZ is not inlined
id z = [[MyObj alloc] initZ]; // expected-warning {{Potential leak of an object}}
- // expected-note@-1 {{Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1}}
+ // expected-note@-1 {{Object leaked: object allocated and stored into 'y' is not referenced later in this execution path and has a retain count of +1}}
[x release];
[z release];
@@ -244,20 +244,20 @@ static int Cond;
void CFOverAutorelease() {
- CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
+ CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type 'CFTypeRef' with a +1 retain count}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased 2 times but the object has a +1 retain count}}
}
void CFAutoreleaseUnowned() {
- CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
+ CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type 'CFTypeRef' with a +0 retain count}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased but has a +0 retain count}}
}
void CFAutoreleaseUnownedMixed() {
- CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
+ CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type 'CFTypeRef' with a +0 retain count}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
[(id)object autorelease]; // expected-note{{Object autoreleased}}
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased 2 times but the object has a +0 retain count}}
@@ -329,5139 +329,3 @@ void CFAutoreleaseUnownedMixed() {
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>47</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d21e9660cc6434ef84a51f39ffcdce86</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>creationViaAlloc</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>48</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f8ec2601a04113e567aa1d09c9902c91</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>creationViaCFCreate</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>53</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>57</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>60</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>dd26a8ad9a7a057feaa636974b43ccb0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>acquisitionViaMethod</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Property returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Property returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>65</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>66</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2f2de5d7fe728958585598b619069e5a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>acquisitionViaProperty</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>67</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1c02b65e83dad1b22270ff5a71de3118</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>acquisitionViaCFFunction</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>78</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>03c23f0f82d7f2fd880a22e0d9cf14b9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>explicitDealloc</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>83</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>84</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6f1b3f0c6c7f79f1af9b313273a01e92</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>implicitDealloc</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>89</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>90</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>cb5e4205a8f925230a70715914a2e3d2</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>overAutorelease</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>92</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Property returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Property returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>97</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1edd178e5ad76c79ce9812f519e8f467</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>autoreleaseUnowned</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>98</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>When GC is not enabled a call to &apos;CFMakeCollectable&apos; has no effect on its argument</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>When GC is not enabled a call to &apos;CFMakeCollectable&apos; has no effect on its argument</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>When GC is not enabled a call to &apos;NSMakeCollectable&apos; has no effect on its argument</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>When GC is not enabled a call to &apos;NSMakeCollectable&apos; has no effect on its argument</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>104</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;leaked&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3f08690fae9687c29bb23b7a7cb7995b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>makeCollectableIgnored</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>109</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4b621ab5f8f2ef9240699119f4d874cb</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>CFCopyRuleViolation</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>110</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;object&apos; is returned from a function whose name (&apos;CFGetRuleViolation&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;object&apos; is returned from a function whose name (&apos;CFGetRuleViolation&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;object&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5248d2310322982d02e5f3d564249b4f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>CFGetRuleViolation</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Property returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Property returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4f23ad2725fb68134cec8b8354cd295c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>copyViolation</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Subscript returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Subscript returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>125</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>da1dab126ed46b144040160ae8628460</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>copyViolationIndexedSubscript</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>126</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Subscript returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Subscript returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>130</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>52877f9471b1ecdaf213b39016b84e52</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>copyViolationKeyedSubscript</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>131</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;result&apos; is returned from a method whose name (&apos;getViolation&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;result&apos; is returned from a method whose name (&apos;getViolation&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;result&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>cf8c65a18ad9982cb9848a266cd9c61b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>getViolation</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>140</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>e7b798151545b45a994592df0d27d250</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>copyAutorelease</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSNumber literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSNumber literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>170</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4e0c810e2b301aca3f636ad7e3d6b0b8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testNumericLiteral</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>171</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSNumber boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSNumber boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>175</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1d054002016aa4360aaf23a4c4d8fbb7</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testBoxedInt</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSString boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSString boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>180</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>67ca92144b05322ee4569aea88d08595</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testBoxedString</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>181</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>185</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>32fcec71872b8f62d8d7b1b05284b0fe</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testArray</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>186</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSDictionary literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSDictionary literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d9584825bb1e62066879949e3ade8570</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testDictionary</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;initX&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;initX&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>206</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;Cond&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;Cond&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>207</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;initX&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;initX&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>eef2aef4b58abf21fcfa4bbf69e19c02</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;initY&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;initY&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an instance of MyObj with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>216</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;initY&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;initY&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8c27524f691296551f9e52856b824326</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>237</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>247</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>248</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>249</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4fc36e73ba317d307dc9cc4b3d62fd0a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>CFOverAutorelease</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>250</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>255</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>08e6a3931d34cda45c09dfda76976e17</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>CFAutoreleaseUnowned</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>260</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>261</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>262</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.cocoa.RetainCount</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d9bb23a5435fe15df9d7ffdc27a8a072</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>CFAutoreleaseUnownedMixed</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index 4add50eb5d0d..5e858f9f543e 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -1,8 +1,19 @@
// RUN: rm -f %t.objc.plist %t.objcpp.plist
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify -Wno-objc-root-class %s -analyzer-output=plist -o %t.objc.plist
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify -x objective-c++ -std=gnu++98 -Wno-objc-root-class %s -analyzer-output=plist -o %t.objcpp.plist
-// FIXLATER: cat %t.objc.plist ; FileCheck --input-file=%t.objc.plist %s
-// FIXLATER: cat %t.objcpp.plist ; FileCheck --input-file=%t.objcpp.plist %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\
+// RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\
+// RUN: -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\
+// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify %s\
+// RUN: -Wno-objc-root-class -analyzer-output=plist -o %t.objc.plist
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\
+// RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\
+// RUN: -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\
+// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify %s\
+// RUN: -Wno-objc-root-class -analyzer-output=plist -o %t.objcpp.plist\
+// RUN: -x objective-c++ -std=gnu++98
+// RUN: cat %t.objcpp.plist | %diff_plist %S/Inputs/expected-plists/retain-release.m.objcpp.plist -
+// RUN: cat %t.objc.plist | %diff_plist %S/Inputs/expected-plists/retain-release.m.objc.plist -
+
+void clang_analyzer_eval(int);
#if __has_feature(attribute_ns_returns_retained)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
@@ -495,6 +506,21 @@ void testLeakWithReturnsRetainedOutParameter() {
// status is returned.
}
+typedef CFTypeRef CMBufferRef;
+
+typedef CFTypeRef *CMBufferQueueRef;
+
+CMBufferRef CMBufferQueueDequeueAndRetain(CMBufferQueueRef);
+
+void testCMBufferQueueDequeueAndRetain(CMBufferQueueRef queue) {
+ CMBufferRef buffer = CMBufferQueueDequeueAndRetain(queue); // expected-warning{{Potential leak of an object stored into 'buffer'}}
+ // There's a state split due to the eagerly-assume behavior.
+ // The point here is that we don't treat CMBufferQueueDequeueAndRetain
+ // as some sort of CFRetain() that returns its argument.
+ clang_analyzer_eval((CMFooRef)buffer == (CMFooRef)queue); // expected-warning{{TRUE}}
+ // expected-warning@-1{{FALSE}}
+}
+
// Test retain/release checker with CFString and CFMutableArray.
void f11() {
// Create the array.
@@ -2086,7 +2112,6 @@ id makeCollectableNonLeak() {
return [objCObject autorelease]; // +0
}
-
void consumeAndStopTracking(id NS_CONSUMED obj, void (^callback)(void));
void CFConsumeAndStopTracking(CFTypeRef CF_CONSUMED obj, void (^callback)(void));
@@ -2344,24032 +2369,3 @@ void testCFReturnsRetainedError() {
return; // no-warning
CFRelease(obj);
}
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>334</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>334</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>335</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>335</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>335</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>335</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>335</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>335</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>335</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>336</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>339</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f1</string>
-// CHECK-NEXT: <key>issue_hash</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>340</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>345</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>345</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>346</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>347</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count decremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>348</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>350</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f2</string>
-// CHECK-NEXT: <key>issue_hash</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>351</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>381</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>381</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>382</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>382</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>382</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>382</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>382</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>382</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>382</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>384</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f5</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>387</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>393</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>393</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>393</integer>
-// CHECK-NEXT: <key>col</key><integer>62</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>393</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>393</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>394</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>395</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>396</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>396</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>396</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f6</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>396</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>62</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>402</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +2</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +2</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f7</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>401</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>403</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>403</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>403</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>403</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>403</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>403</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>403</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is returned from a function whose name (&apos;f7&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is returned from a function whose name (&apos;f7&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f7</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>404</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>412</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>412</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>412</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;MyDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;MyDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>412</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>412</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>413</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>414</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>415</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>415</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>415</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;date&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f8</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>415</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>418</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>418</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>419</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>419</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>419</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>419</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>419</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>419</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>419</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;date&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;date&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f9</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>421</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>75</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCreateFromBSDName&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCreateFromBSDName&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f10</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>49</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCopyDescription&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCopyDescription&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f10</string>
-// CHECK-NEXT: <key>issue_hash</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCopyWholeDisk&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCopyWholeDisk&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f10</string>
-// CHECK-NEXT: <key>issue_hash</key><string>10</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCreateFromIOMedia&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADiskCreateFromIOMedia&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;disk&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;disk&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f10</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>443</integer>
-// CHECK-NEXT: <key>col</key><integer>68</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADissenterCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;DADissenterCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;dissenter&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;dissenter&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dissenter&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dissenter&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;dissenter&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f10</string>
-// CHECK-NEXT: <key>issue_hash</key><string>13</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>430</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>433</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>434</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>436</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;dict&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>437</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>439</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;disk&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>440</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>442</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;dissenter&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;dissenter&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>444</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>61</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;DASessionCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;DASessionCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>446</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;session&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;session&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;session&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;session&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;session&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f10</string>
-// CHECK-NEXT: <key>issue_hash</key><string>17</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>447</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>453</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>466</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>466</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>466</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>466</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>466</integer>
-// CHECK-NEXT: <key>col</key><integer>49</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayGetValueAtIndex&apos; returns a Core Foundation object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayGetValueAtIndex&apos; returns a Core Foundation object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>466</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>466</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f11</string>
-// CHECK-NEXT: <key>issue_hash</key><string>21</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>472</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;MyCreateFun&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;MyCreateFun&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>480</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;o&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;o&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f12</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>481</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>489</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>489</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>489</integer>
-// CHECK-NEXT: <key>col</key><integer>75</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>489</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>489</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>490</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>491</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f13_autorelease_b</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>492</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>495</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>495</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>495</integer>
-// CHECK-NEXT: <key>col</key><integer>75</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>495</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>495</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>496</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>497</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f13_autorelease_c</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>502</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>502</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>502</integer>
-// CHECK-NEXT: <key>col</key><integer>75</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>502</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>502</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>504</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>75</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased 2 times but the object has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f13_autorelease_d</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>505</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>513</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>513</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>513</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>513</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>513</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>514</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>514</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>514</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f14_leakimmediately</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>514</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &gt; 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &gt; 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFRelease</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFRelease</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRelease</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f16</string>
-// CHECK-NEXT: <key>issue_hash</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>532</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt; 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt; 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>535</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>535</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>535</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>535</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>535</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFRetain</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFRetain</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRetain</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f16</string>
-// CHECK-NEXT: <key>issue_hash</key><string>8</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>535</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;p&apos; is null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>528</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &lt;= 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>531</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &gt;= 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is &gt;= 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>534</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>538</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>538</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>538</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>538</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>538</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFMakeCollectable</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer argument in call to CFMakeCollectable</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFMakeCollectable</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>f16</string>
-// CHECK-NEXT: <key>issue_hash</key><string>11</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>538</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>584</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>584</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>584</integer>
-// CHECK-NEXT: <key>col</key><integer>55</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>584</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>584</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>newString</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>585</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;name&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;name&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>606</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>606</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>606</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>606</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>606</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;kind&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;kind&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;kind&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_6659160</string>
-// CHECK-NEXT: <key>issue_hash</key><string>5</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>606</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;name&apos; is non-nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;name&apos; is non-nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;kindC&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;kindC&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;kind&apos; is nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;kind&apos; is nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Array access (from variable &apos;kindC&apos;) results in a null pointer dereference</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_6659160</string>
-// CHECK-NEXT: <key>issue_hash</key><string>27</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>598</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>604</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>604</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>604</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>604</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>604</integer>
-// CHECK-NEXT: <key>col</key><integer>57</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>604</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>604</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;name&apos; is non-nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;name&apos; is non-nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>605</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>608</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;kind&apos; is non-nil</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;kind&apos; is non-nil</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>616</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>617</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>617</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>617</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>617</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>618</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>619</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>620</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>622</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>622</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>622</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>622</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>625</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>625</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>625</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>625</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>626</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>626</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>626</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>626</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>626</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_6659160</string>
-// CHECK-NEXT: <key>issue_hash</key><string>33</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>626</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>648</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>648</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>648</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>648</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>648</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released by directly sending the &apos;-dealloc&apos; message</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>649</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>650</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>650</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>650</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>650</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>650</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>pr3820_ReleaseAfterDealloc</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>650</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>656</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>656</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>657</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>657</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>657</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>657</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>657</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>657</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>657</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>658</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>659</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>659</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>659</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>659</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>659</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>pr3820_DeallocAfterRelease</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>659</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>76</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>84</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>76</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>711</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>715</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>715</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>715</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>715</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>716</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>716</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>716</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>applicationDidFinishLaunching:</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>716</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>76</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>84</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>76</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>723</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>724</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>726</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>726</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>726</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;dict&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;dict&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>radar10102244</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>726</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>734</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>734</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>735</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>735</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>735</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>735</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>735</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>735</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>735</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>736</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>736</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>736</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>736</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>736</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_6257780_Case1</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>736</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>811</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>811</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>812</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>812</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>812</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>812</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>812</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>812</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>812</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>813</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>813</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>813</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>813</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>813</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>_initReturningNewClassBad</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>813</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>816</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>816</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>817</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>817</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>817</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>817</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>817</integer>
-// CHECK-NEXT: <key>col</key><integer>43</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>817</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>817</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>initReturningNewClassBad2</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>818</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;NoCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;NoCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>NoCopyString</string>
-// CHECK-NEXT: <key>issue_hash</key><string>0</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;noCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;noCopyString&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>noCopyString</string>
-// CHECK-NEXT: <key>issue_hash</key><string>0</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;NoCopyString&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;NoCopyString&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_RDar6859457&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_RDar6859457&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>856</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;NoCopyString&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;NoCopyString&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_RDar6859457</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>861</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;noCopyString&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;noCopyString&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_RDar6859457&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_RDar6859457&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>857</integer>
-// CHECK-NEXT: <key>col</key><integer>59</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;noCopyString&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;noCopyString&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>862</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>863</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>863</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>863</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>863</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>863</integer>
-// CHECK-NEXT: <key>col</key><integer>54</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_RDar6859457</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>863</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;:&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;:&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>:</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>896</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar6902710</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>927</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar6902710</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>43</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar6902710</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>926</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>69</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>930</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>930</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>930</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar6902710</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>930</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>938</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>938</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>938</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>938</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>938</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>939</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>939</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>939</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar6945561</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>939</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>947</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>947</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>947</integer>
-// CHECK-NEXT: <key>col</key><integer>49</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOBSDNameMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOBSDNameMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>947</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>947</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>948</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>948</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>948</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOBSDNameMatching_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>948</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>951</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>951</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>951</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOServiceMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOServiceMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>951</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>951</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>952</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>952</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>952</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOServiceMatching_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>952</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>955</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>955</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>955</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOServiceNameMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOServiceNameMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>955</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>955</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>956</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>956</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>956</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOServiceNameMatching_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>956</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>963</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>963</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>963</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>963</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>963</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>964</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>965</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>965</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>965</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>965</integer>
-// CHECK-NEXT: <key>col</key><integer>58</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>965</integer>
-// CHECK-NEXT: <key>col</key><integer>65</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOServiceAddNotification_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>965</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>970</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>970</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>970</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;IORegistryEntryIDMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;IORegistryEntryIDMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>970</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>970</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>971</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>971</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>971</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IORegistryEntryIDMatching_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>971</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>975</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>975</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>975</integer>
-// CHECK-NEXT: <key>col</key><integer>55</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOOpenFirmwarePathMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;IOOpenFirmwarePathMatching&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>975</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>975</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>976</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>976</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>976</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOOpenFirmwarePathMatching_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>976</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>979</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>979</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>979</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>979</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>979</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>51</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>43</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>50</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>980</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>981</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>981</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>981</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>981</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>981</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOServiceGetMatchingService_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>981</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>985</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>985</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>985</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>985</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>985</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>62</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>51</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>986</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>987</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>987</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>987</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>987</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>987</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOServiceGetMatchingServices_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>987</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>993</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>993</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>993</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateDict&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>993</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>993</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>106</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>73</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>994</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>995</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>995</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>995</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>995</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>995</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>IOServiceAddMatchingNotification_wrapper</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>995</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1033</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1033</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1036</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1036</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1036</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1036</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1036</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1036</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1036</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count decremented</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count decremented</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1038</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1039</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1040</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1040</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1040</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1040</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1040</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_7152619</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1040</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1049</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1049</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1061</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1061</integer>
-// CHECK-NEXT: <key>col</key><integer>67</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1061</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1061</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1061</integer>
-// CHECK-NEXT: <key>col</key><integer>69</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1061</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1061</integer>
-// CHECK-NEXT: <key>col</key><integer>67</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_7184450</string>
-// CHECK-NEXT: <key>issue_hash</key><string>13</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1060</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1071</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1071</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>68</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGColorSpaceCreateDeviceRGB&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_7184450_pos</string>
-// CHECK-NEXT: <key>issue_hash</key><string>13</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1071</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1071</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1082</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>107</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGGradientCreateWithColorComponents&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGGradientCreateWithColorComponents&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1083</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1085</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1085</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1085</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1085</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1087</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1087</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1087</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;myGradient&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;myGradient&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;myGradient&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_7184450_pos</string>
-// CHECK-NEXT: <key>issue_hash</key><string>13</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1087</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1121</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1121</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1121</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1121</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1121</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1122</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1122</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1122</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_7299394_positive</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1122</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1254</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1254</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1256</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1257</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGBitmapContextCreateWithData&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CGBitmapContextCreateWithData&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1256</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1256</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1258</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1258</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1258</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_7358899</string>
-// CHECK-NEXT: <key>issue_hash</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1258</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1274</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1274</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1274</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1274</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1274</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1275</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1275</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1275</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;y&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;y&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar7265711_a</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1275</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1294</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1294</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1295</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1295</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1295</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1295</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1295</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1295</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1295</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1296</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1296</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1296</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar7306898</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1296</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The &apos;release&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>message incorrectly sent to class instead of class instance</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar7252064</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1306</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1306</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1306</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1306</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1306</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The &apos;retain&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>message incorrectly sent to class instead of class instance</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar7252064</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1306</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1307</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1307</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1307</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1307</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1307</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The &apos;autorelease&apos; message should be sent to instances of class &apos;RDar7252064&apos; and not the class directly</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>message incorrectly sent to class instead of class instance</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar7252064</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1307</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1305</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1308</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1308</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1308</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1308</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1308</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>The &apos;drain&apos; message should be sent to instances of class &apos;NSAutoreleasePool&apos; and not the class directly</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>message incorrectly sent to class instead of class instance</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar7252064</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1308</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1335</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1335</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1335</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1335</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1335</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1336</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1336</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1336</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;str&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_attr_1</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1336</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1339</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1339</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1339</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1339</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1339</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1340</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1340</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1340</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;str&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_attr_1b</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1340</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1343</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1343</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1344</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1344</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1344</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1344</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1344</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1344</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1344</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str2&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str2&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;str2&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_attr1c</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1345</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1343</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1343</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>46</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1346</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1347</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1347</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1347</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str4&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;str4&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;str4&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_attr1c</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1347</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1350</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1350</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1350</integer>
-// CHECK-NEXT: <key>col</key><integer>50</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1350</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1350</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1351</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1351</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1351</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testattr2_a</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1351</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1354</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1354</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1354</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1354</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1354</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1355</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1355</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1355</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testattr2_b</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1355</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1358</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1358</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1358</integer>
-// CHECK-NEXT: <key>col</key><integer>63</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1358</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1358</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1359</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1359</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1359</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1359</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1360</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1360</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1360</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testattr2_b_11358224_self_assign_looses_the_leak</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1360</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method that is annotated as NS_RETURNS_NOT_RETAINED</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method that is annotated as NS_RETURNS_NOT_RETAINED</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>newString</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1390</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsCFRetainedAsCF&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsCFRetainedAsCF&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1414</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;newCFRetainedAsCFNoAttr&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;newCFRetainedAsCFNoAttr&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1414</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1414</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;returnsCFRetainedAsCF&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;returnsCFRetainedAsCF&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1415</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsCFRetainedAsCF&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsCFRetainedAsCF&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>newCFRetainedAsCFNoAttr</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1423</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;alsoReturnsRetained&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;alsoReturnsRetained&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;alsoReturnsRetained&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;alsoReturnsRetained&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>alsoReturnsRetained</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1427</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;alsoReturnsRetainedAsCF&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;alsoReturnsRetainedAsCF&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1404</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1406</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;returnsRetainedCFDate&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>32</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;alsoReturnsRetainedAsCF&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a method whose name (&apos;alsoReturnsRetainedAsCF&apos;) does not start with &apos;copy&apos;, &apos;mutableCopy&apos;, &apos;alloc&apos; or &apos;new&apos;. This violates the naming convention rules given in the Memory Management Guide for Cocoa</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>alsoReturnsRetainedAsCF</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1431</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1451</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1451</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1452</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1452</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1452</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1452</integer>
-// CHECK-NEXT: <key>col</key><integer>82</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1452</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1452</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1453</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1453</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1453</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_panic_negative</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1453</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1462</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1463</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1463</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1463</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1463</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1463</integer>
-// CHECK-NEXT: <key>col</key><integer>82</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1463</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1463</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;x&apos; is 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1464</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1466</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1466</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1466</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_panic_neg_2</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1466</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1486</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1486</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1486</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1486</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1486</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1487</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1487</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1487</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1487</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1487</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_blocks_1_pos</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1487</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1507</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1507</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1507</integer>
-// CHECK-NEXT: <key>col</key><integer>53</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1507</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1507</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_blocks_1_indirect_retain_via_call&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_blocks_1_indirect_retain_via_call&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1509</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1509</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1509</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +2</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;number&apos; is not referenced later in this execution path and has a retain count of +2</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;number&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_blocks_1_indirect_retain_via_call</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1509</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1559</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1559</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1562</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1562</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1562</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1562</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entering loop body</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1562</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1562</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1563</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1563</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1563</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1563</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1565</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1565</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1565</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1565</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1565</integer>
-// CHECK-NEXT: <key>col</key><integer>49</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFErrorCopyUserInfo&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFErrorCopyUserInfo&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1565</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1565</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;info&apos; is not equal to null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;info&apos; is not equal to null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1567</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1570</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1570</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1570</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;info&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;info&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;info&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar_8724287</string>
-// CHECK-NEXT: <key>issue_hash</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1570</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camelcase_createno&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camelcase_createno&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>camelcase_createno</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1615</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camelcase_copying&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camelcase_copying&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>camelcase_copying</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1623</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camel_creat&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camel_creat&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>camel_creat</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1644</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller as an owning reference (single retain count transferred to caller)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>60</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camel_copymachine&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is returned from a function whose name (&apos;camel_copymachine&apos;) does not contain &apos;Copy&apos; or &apos;Create&apos;. This violates the naming convention rules given in the Memory Management Guide for Core Foundation</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak of returned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>camel_copymachine</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1656</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1676</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1676</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1677</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1677</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1677</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1677</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1677</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1677</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1677</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1678</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1678</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1678</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;vals&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;vals&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;vals&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar6582778</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1678</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1702</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1702</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1704</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1704</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1704</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1704</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1704</integer>
-// CHECK-NEXT: <key>col</key><integer>64</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1704</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1704</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1705</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar10232019_positive</string>
-// CHECK-NEXT: <key>issue_hash</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1707</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1835</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1835</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1835</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1835</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1835</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1835</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1835</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_arrays</string>
-// CHECK-NEXT: <key>issue_hash</key><string>3</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1844</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1844</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1844</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1844</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1844</integer>
-// CHECK-NEXT: <key>col</key><integer>56</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1844</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1844</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a2&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a2&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;a2&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_arrays</string>
-// CHECK-NEXT: <key>issue_hash</key><string>12</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1852</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a3&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a3&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;a3&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_arrays</string>
-// CHECK-NEXT: <key>issue_hash</key><string>20</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1860</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1860</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1860</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1860</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1860</integer>
-// CHECK-NEXT: <key>col</key><integer>57</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1860</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1860</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_arrays</string>
-// CHECK-NEXT: <key>issue_hash</key><string>28</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1834</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1838</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1842</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1847</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1851</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1855</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1859</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1864</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1868</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1868</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1868</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1868</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSDictionary literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSDictionary literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>43</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1869</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1873</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1873</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1873</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1873</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1873</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;a&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;a&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_arrays</string>
-// CHECK-NEXT: <key>issue_hash</key><string>37</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1873</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSNumber literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSNumber literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1878</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1879</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1879</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1879</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1879</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1880</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1880</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1880</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_integer_literals</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1880</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSNumber boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSNumber boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_boxed_expressions</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1883</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSString boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSString boxed expression produces an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1886</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1887</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1888</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1888</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1888</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;value&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_objc_boxed_expressions</string>
-// CHECK-NEXT: <key>issue_hash</key><string>4</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1888</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1894</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1894</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is &lt;= 2</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;y&apos; is &lt;= 2</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1895</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1898</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1898</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1898</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1898</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1898</integer>
-// CHECK-NEXT: <key>col</key><integer>43</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1898</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1898</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1899</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1899</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1899</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1899</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1900</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1901</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1901</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1901</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1901</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1901</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>rdar11400885</string>
-// CHECK-NEXT: <key>issue_hash</key><string>9</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1901</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1920</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1920</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1928</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1928</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1928</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1928</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1928</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1928</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1929</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1929</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1929</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testConsumeAndStopTracking</string>
-// CHECK-NEXT: <key>issue_hash</key><string>10</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1929</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1933</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1933</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1941</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1941</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1941</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1941</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1941</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSArray literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1941</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1941</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1942</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1942</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1942</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1942</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1942</integer>
-// CHECK-NEXT: <key>col</key><integer>48</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCFConsumeAndStopTracking</string>
-// CHECK-NEXT: <key>issue_hash</key><string>10</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1942</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1954</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1954</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1954</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateMyCFType&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CreateMyCFType&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1954</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1954</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1955</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1955</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1955</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;x&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;x&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_custom_cf</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1955</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1989</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1989</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1989</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;makeCustom&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;makeCustom&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1989</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1989</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1990</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1990</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1990</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;obj&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCustomReturnsRetained</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1990</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1993</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1993</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1993</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;getCustom&apos; returns a Core Foundation object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;getCustom&apos; returns a Core Foundation object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1993</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1993</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1993</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Bad release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testCustomReturnsNotRetained</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>1993</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;initX&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;initX&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2005</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test12706177&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test12706177&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2005</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2005</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;Cond&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;Cond&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2006</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2007</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2007</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;initX&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;initX&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
-// CHECK-NEXT: <key>issue_context</key><string>test12706177</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2012</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object returned to caller with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>getIncorrectlyAutoreleasedCFType</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2028</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>40</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>43</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>43</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Method should return an owned object</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>createIncorrectlyAutoreleasedCFType</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2033</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2048</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2048</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2048</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2048</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2048</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2049</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2052</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2052</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2052</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2052</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2052</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Reference-counted object is used after it is released</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Use-after-release</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>useAfterRelease</string>
-// CHECK-NEXT: <key>issue_hash</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2052</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2057</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2057</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2057</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2057</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2057</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>36</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2058</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2059</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2060</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2060</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2060</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;obj&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;obj&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testAutoreleaseReturnsInput</string>
-// CHECK-NEXT: <key>issue_hash</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2060</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2077</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2077</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2077</integer>
-// CHECK-NEXT: <key>col</key><integer>70</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFArrayCreateMutable&apos; returns a Core Foundation object with a +1 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2077</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2077</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>34</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>62</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>48</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>61</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2078</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Reference count incremented. The object now has a +2 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2079</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2080</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2080</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2080</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;arr&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object leaked: object allocated and stored into &apos;arr&apos; is not referenced later in this execution path and has a retain count of +1</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Potential leak of an object stored into &apos;arr&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Leak</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>autoreleaseReturningTypedObject</string>
-// CHECK-NEXT: <key>issue_hash</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2080</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2091</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2091</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2094</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2094</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2094</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2094</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2094</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>NSNumber literal is an object with a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>NSNumber literal is an object with a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2094</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2094</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object autoreleased</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2095</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2096</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2096</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2096</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object was autoreleased but has a +0 retain count</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
-// CHECK-NEXT: <key>type</key><string>Object autoreleased too many times</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>autoreleaseObjC</string>
-// CHECK-NEXT: <key>issue_hash</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>2096</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </plist>
diff --git a/test/Analysis/retain-release.mm b/test/Analysis/retain-release.mm
index ac83c1a48e36..5dc8f857d87d 100644
--- a/test/Analysis/retain-release.mm
+++ b/test/Analysis/retain-release.mm
@@ -470,3 +470,18 @@ void* IOBSDNameMatching();
void rdar33832412() {
void* x = IOBSDNameMatching(); // no-warning
}
+
+
+namespace member_CFRetains {
+class Foo {
+public:
+ void CFRetain(const Foo &) {}
+ void CFRetain(int) {}
+};
+
+void bar() {
+ Foo foo;
+ foo.CFRetain(foo); // no-warning
+ foo.CFRetain(0); // no-warning
+}
+}
diff --git a/test/Analysis/retaincountchecker-compoundregion.m b/test/Analysis/retaincountchecker-compoundregion.m
index d9967b7fabfc..83857e268d98 100644
--- a/test/Analysis/retaincountchecker-compoundregion.m
+++ b/test/Analysis/retaincountchecker-compoundregion.m
@@ -19,7 +19,7 @@ void foo(CFAllocatorRef allocator) {
int width = 0;
int height = 0;
CFTypeRef* values = (CFTypeRef[]){
- CFNumberCreate(allocator, kCFNumberSInt32Type, &width), //expected-warning-re{{Potential leak of an object{{$}}}}
- CFNumberCreate(allocator, kCFNumberSInt32Type, &height), //expected-warning-re{{Potential leak of an object{{$}}}}
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &width), //expected-warning{{Potential leak of an object of type 'CFNumberRef'}}
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &height), //expected-warning{{Potential leak of an object of type 'CFNumberRef'}}
};
}
diff --git a/test/Analysis/scopes-cfg-output.cpp b/test/Analysis/scopes-cfg-output.cpp
index 0f2201abb096..f8d84b60deb1 100644
--- a/test/Analysis/scopes-cfg-output.cpp
+++ b/test/Analysis/scopes-cfg-output.cpp
@@ -820,10 +820,9 @@ void test_for_compound_and_break() {
// CHECK-NEXT: 3: __end1
// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, LValueToRValue, class A *)
// CHECK-NEXT: 5: [B2.2] != [B2.4]
-// CHECK-NEXT: T: for (auto &i : [B5.4]) {
+// CHECK-NEXT: T: for (auto &i : [B5.4])
// CHECK: [B4.11];
-// CHECK-NEXT:}
-// CHECK-NEXT: Preds (2): B3 B5
+// CHECK: Preds (2): B3 B5
// CHECK-NEXT: Succs (2): B4 B1
// CHECK: [B3]
// CHECK-NEXT: 1: __begin1
diff --git a/test/Analysis/security-syntax-checks.m b/test/Analysis/security-syntax-checks.m
index 2c569727addd..1fd00dffe4f8 100644
--- a/test/Analysis/security-syntax-checks.m
+++ b/test/Analysis/security-syntax-checks.m
@@ -177,6 +177,11 @@ void test_strcpy_safe() {
strcpy(x, "abcd");
}
+void test_strcpy_safe_2() {
+ struct {char s1[100];} s;
+ strcpy(s.s1, "hello");
+}
+
//===----------------------------------------------------------------------===
// strcat()
//===----------------------------------------------------------------------===
diff --git a/test/Analysis/self-assign.cpp b/test/Analysis/self-assign.cpp
index 580a3ab00ead..ca28c534f1e2 100644
--- a/test/Analysis/self-assign.cpp
+++ b/test/Analysis/self-assign.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,unix.Malloc,debug.ExprInspection %s -verify -analyzer-output=text
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,unix.Malloc,debug.ExprInspection -analyzer-config eagerly-assume=false %s -verify -analyzer-output=text
extern "C" char *strdup(const char* s);
extern "C" void free(void* ptr);
@@ -32,13 +32,14 @@ StringUsed& StringUsed::operator=(const StringUsed &rhs) { // expected-note{{Ass
clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
free(str); // expected-note{{Memory is released}}
str = strdup(rhs.str); // expected-warning{{Use of memory after it is freed}} expected-note{{Use of memory after it is freed}}
+// expected-note@-1{{Memory is allocated}}
return *this;
}
StringUsed& StringUsed::operator=(StringUsed &&rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
str = rhs.str;
- rhs.str = nullptr; // FIXME: An improved leak checker should warn here
+ rhs.str = nullptr; // expected-warning{{Potential memory leak}} expected-note{{Potential memory leak}}
return *this;
}
@@ -83,7 +84,7 @@ StringUnused::operator const char*() const {
int main() {
StringUsed s1 ("test"), s2;
- s2 = s1;
- s2 = std::move(s1);
+ s2 = s1; // expected-note{{Calling copy assignment operator for 'StringUsed'}} // expected-note{{Returned allocated memory}}
+ s2 = std::move(s1); // expected-note{{Calling move assignment operator for 'StringUsed'}}
return 0;
}
diff --git a/test/Analysis/simple-stream-checks.c b/test/Analysis/simple-stream-checks.c
index ca1c78157547..f37a7039f5e3 100644
--- a/test/Analysis/simple-stream-checks.c
+++ b/test/Analysis/simple-stream-checks.c
@@ -89,3 +89,8 @@ void testPassToSystemHeaderFunctionIndirectly() {
fs.p = fopen("myfile.txt", "w");
fakeSystemHeaderCall(&fs); // invalidates fs, making fs.p unreachable
} // no-warning
+
+void testOverwrite() {
+ FILE *fp = fopen("myfile.txt", "w");
+ fp = 0;
+} // expected-warning {{Opened file is never closed; potential resource leak}}
diff --git a/test/Analysis/std-c-library-functions-inlined.c b/test/Analysis/std-c-library-functions-inlined.c
new file mode 100644
index 000000000000..e22df1408572
--- /dev/null
+++ b/test/Analysis/std-c-library-functions-inlined.c
@@ -0,0 +1,17 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=apiModeling.StdCLibraryFunctions -verify %s
+// RUN: %clang_analyze_cc1 -triple i686-unknown-linux -analyzer-checker=apiModeling.StdCLibraryFunctions -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=apiModeling.StdCLibraryFunctions -verify %s
+// RUN: %clang_analyze_cc1 -triple armv7-a15-linux -analyzer-checker=apiModeling.StdCLibraryFunctions -verify %s
+// RUN: %clang_analyze_cc1 -triple thumbv7-a15-linux -analyzer-checker=apiModeling.StdCLibraryFunctions -verify %s
+
+// This test tests crashes that occur when standard functions are available
+// for inlining.
+
+// expected-no-diagnostics
+
+int isdigit(int _) { return !0; }
+void test_redefined_isdigit(int x) {
+ int (*func)(int) = isdigit;
+ for (; func(x);) // no-crash
+ ;
+}
diff --git a/test/Analysis/std-c-library-functions.c b/test/Analysis/std-c-library-functions.c
index b8eb3e54bdf0..9fb8833175be 100644
--- a/test/Analysis/std-c-library-functions.c
+++ b/test/Analysis/std-c-library-functions.c
@@ -1,8 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
-// RUN: %clang_analyze_cc1 -triple i686-unknown-linux -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
-// RUN: %clang_analyze_cc1 -triple armv7-a15-linux -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
-// RUN: %clang_analyze_cc1 -triple thumbv7-a15-linux -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=apiModeling.StdCLibraryFunctions,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple i686-unknown-linux -analyzer-checker=apiModeling.StdCLibraryFunctions,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=apiModeling.StdCLibraryFunctions,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple armv7-a15-linux -analyzer-checker=apiModeling.StdCLibraryFunctions,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -triple thumbv7-a15-linux -analyzer-checker=apiModeling.StdCLibraryFunctions,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/std-c-library-functions.cpp b/test/Analysis/std-c-library-functions.cpp
index 00b341af5f92..87f84fa88118 100644
--- a/test/Analysis/std-c-library-functions.cpp
+++ b/test/Analysis/std-c-library-functions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=apiModeling.StdCLibraryFunctions,debug.ExprInspection -verify %s
// Test that we don't model functions with broken prototypes.
// Because they probably work differently as well.
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index 7e8a7361cd4b..024e224a2b5b 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -1,8 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s
//===----------------------------------------------------------------------===
// Declarations
@@ -1184,11 +1184,14 @@ void strsep_changes_input_string() {
}
//===----------------------------------------------------------------------===
-// memset()
+// memset() / explicit_bzero() / bzero()
//===----------------------------------------------------------------------===
void *memset(void *dest, int ch, size_t count);
+void bzero(void *dst, size_t count);
+void explicit_bzero(void *dest, size_t count);
+
void *malloc(size_t size);
void free(void *);
@@ -1383,6 +1386,57 @@ void memset26_upper_UCHAR_MAX() {
clang_analyzer_eval(array[4] == 0); // expected-warning{{TRUE}}
}
+void bzero1_null() {
+ char *a = NULL;
+
+ bzero(a, 10); // expected-warning{{Null pointer argument in call to memory clearance function}}
+}
+
+void bzero2_char_array_null() {
+ char str[] = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ bzero(str, 2);
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}}
+}
+
+void bzero3_char_ptr_null() {
+ char *str = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ bzero(str + 2, 2);
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{FALSE}}
+}
+
+void explicit_bzero1_null() {
+ char *a = NULL;
+
+ explicit_bzero(a, 10); // expected-warning{{Null pointer argument in call to memory clearance function}}
+}
+
+void explicit_bzero2_clear_mypassword() {
+ char passwd[7] = "passwd";
+
+ explicit_bzero(passwd, sizeof(passwd)); // no-warning
+
+ clang_analyzer_eval(strlen(passwd) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(passwd[0] == '\0'); // expected-warning{{TRUE}}
+}
+
+void explicit_bzero3_out_ofbound() {
+ char *privkey = (char *)malloc(7);
+ const char newprivkey[10] = "mysafekey";
+
+ strcpy(privkey, "random");
+ explicit_bzero(privkey, sizeof(newprivkey));
+#ifndef SUPPRESS_OUT_OF_BOUND
+ // expected-warning@-2 {{Memory clearance function accesses out-of-bound array element}}
+#endif
+ clang_analyzer_eval(privkey[0] == '\0');
+#ifdef SUPPRESS_OUT_OF_BOUND
+ // expected-warning@-2 {{UNKNOWN}}
+#endif
+ free(privkey);
+}
+
//===----------------------------------------------------------------------===
// FIXMEs
//===----------------------------------------------------------------------===
diff --git a/test/Analysis/string.cpp b/test/Analysis/string.cpp
new file mode 100644
index 000000000000..f86416da6ee2
--- /dev/null
+++ b/test/Analysis/string.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -verify %s
+
+// expected-no-diagnostics
+
+// Test functions that are called "memcpy" but aren't the memcpy
+// we're looking for. Unfortunately, this test cannot be put into
+// a namespace. The out-of-class weird memcpy needs to be recognized
+// as a normal C function for the test to make sense.
+typedef __typeof(sizeof(int)) size_t;
+void *memcpy(void *, const void *, size_t);
+
+struct S {
+ static S s1, s2;
+
+ // A weird overload within the class that accepts a structure reference
+ // instead of a pointer.
+ void memcpy(void *, const S &, size_t);
+ void test_in_class_weird_memcpy() {
+ memcpy(this, s2, 1); // no-crash
+ }
+};
+
+// A similarly weird overload outside of the class.
+void *memcpy(void *, const S &, size_t);
+
+void test_out_of_class_weird_memcpy() {
+ memcpy(&S::s1, S::s2, 1); // no-crash
+}
diff --git a/test/Analysis/svalbuilder-float-cast.c b/test/Analysis/svalbuilder-float-cast.c
new file mode 100644
index 000000000000..0f5760cbfca0
--- /dev/null
+++ b/test/Analysis/svalbuilder-float-cast.c
@@ -0,0 +1,20 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -verify %s
+void clang_analyzer_denote(int, const char *);
+void clang_analyzer_express(int);
+
+void SymbolCast_of_float_type_aux(int *p) {
+ *p += 0;
+ // FIXME: Ideally, all unknown values should be symbolicated.
+ clang_analyzer_denote(*p, "$x"); // expected-warning{{Not a symbol}}
+
+ *p += 1;
+ // This should NOT be (float)$x + 1. Symbol $x was never casted to float.
+ // FIXME: Ideally, this should be $x + 1.
+ clang_analyzer_express(*p); // expected-warning{{Not a symbol}}
+}
+
+void SymbolCast_of_float_type() {
+ extern float x;
+ void (*f)() = SymbolCast_of_float_type_aux;
+ f(&x);
+}
diff --git a/test/Analysis/svalbuilder-rearrange-comparisons.c b/test/Analysis/svalbuilder-rearrange-comparisons.c
index ac186120fe11..9e9bf0a9db9b 100644
--- a/test/Analysis/svalbuilder-rearrange-comparisons.c
+++ b/test/Analysis/svalbuilder-rearrange-comparisons.c
@@ -1,7 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify -analyzer-config eagerly-assume=false %s
-void clang_analyzer_dump(int x);
void clang_analyzer_eval(int x);
+void clang_analyzer_denote(int x, const char *literal);
+void clang_analyzer_express(int x);
void exit(int);
@@ -26,907 +27,951 @@ int f() {
void compare_different_symbol_equal() {
int x = f(), y = f();
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 0}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 0}}
}
void compare_different_symbol_plus_left_int_equal() {
- int x = f()+1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 1;
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}}
}
void compare_different_symbol_minus_left_int_equal() {
- int x = f()-1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 1;
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}}
}
void compare_different_symbol_plus_right_int_equal() {
- int x = f(), y = f()+2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 2}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ y += 2;
+ clang_analyzer_express(y); // expected-warning {{$y + 2}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 2}}
}
void compare_different_symbol_minus_right_int_equal() {
- int x = f(), y = f()-2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 2}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ y -= 2;
+ clang_analyzer_express(y); // expected-warning {{$y - 2}}
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 2}}
}
void compare_different_symbol_plus_left_plus_right_int_equal() {
- int x = f()+2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 2;
+ y += 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}}
}
void compare_different_symbol_plus_left_minus_right_int_equal() {
- int x = f()+2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 3}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 2;
+ y -= 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 3}}
}
void compare_different_symbol_minus_left_plus_right_int_equal() {
- int x = f()-2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 3}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 2;
+ y += 1;
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 3}}
}
void compare_different_symbol_minus_left_minus_right_int_equal() {
- int x = f()-2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 2;
+ y -= 1;
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}}
}
void compare_same_symbol_equal() {
int x = f(), y = x;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_int_equal() {
int x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x == y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_left_int_equal() {
int x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x == y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_right_int_equal() {
- int x = f(), y = x+1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{FALSE}}
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_right_int_equal() {
- int x = f(), y = x-1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{FALSE}}
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_left_plus_right_int_equal() {
- int x = f(), y = x+1;
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_minus_right_int_equal() {
- int x = f(), y = x-1;
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_left_plus_right_int_equal() {
- int x = f(), y = x+1;
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_left_minus_right_int_equal() {
- int x = f(), y = x-1;
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
}
void compare_different_symbol_less_or_equal() {
int x = f(), y = f();
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 0}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 0}}
}
void compare_different_symbol_plus_left_int_less_or_equal() {
- int x = f()+1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}}
}
void compare_different_symbol_minus_left_int_less_or_equal() {
- int x = f()-1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 1;
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}}
}
void compare_different_symbol_plus_right_int_less_or_equal() {
- int x = f(), y = f()+2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 2}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ y += 2;
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 2}}
}
void compare_different_symbol_minus_right_int_less_or_equal() {
- int x = f(), y = f()-2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 2}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ y -= 2;
+ clang_analyzer_express(y); // expected-warning {{$y - 2}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 2}}
}
void compare_different_symbol_plus_left_plus_right_int_less_or_equal() {
- int x = f()+2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 2;
+ y += 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}}
}
void compare_different_symbol_plus_left_minus_right_int_less_or_equal() {
- int x = f()+2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 3}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 2;
+ y -= 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 3}}
}
void compare_different_symbol_minus_left_plus_right_int_less_or_equal() {
- int x = f()-2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 3}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 2;
+ y += 1;
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 3}}
}
void compare_different_symbol_minus_left_minus_right_int_less_or_equal() {
- int x = f()-2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 2;
+ y -= 1;
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}}
}
void compare_same_symbol_less_or_equal() {
int x = f(), y = x;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_int_less_or_equal() {
int x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x <= y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_left_int_less_or_equal() {
int x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_right_int_less_or_equal() {
- int x = f(), y = x+1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_same_symbol_minus_right_int_less_or_equal() {
- int x = f(), y = x-1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{FALSE}}
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_left_plus_right_int_less_or_equal() {
- int x = f(), y = x+1;
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_minus_right_int_less_or_equal() {
- int x = f(), y = x-1;
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_left_plus_right_int_less_or_equal() {
- int x = f(), y = x+1;
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_same_symbol_minus_left_minus_right_int_less_or_equal() {
- int x = f(), y = x-1;
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_different_symbol_less() {
int x = f(), y = f();
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 0}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 0}}
}
void compare_different_symbol_plus_left_int_less() {
- int x = f()+1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}}
}
void compare_different_symbol_minus_left_int_less() {
- int x = f()-1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 1;
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}}
}
void compare_different_symbol_plus_right_int_less() {
- int x = f(), y = f()+2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 2}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ y += 2;
+ clang_analyzer_express(y); // expected-warning {{$y + 2}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 2}}
}
void compare_different_symbol_minus_right_int_less() {
- int x = f(), y = f()-2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 2}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ y -= 2;
+ clang_analyzer_express(y); // expected-warning {{$y - 2}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 2}}
}
void compare_different_symbol_plus_left_plus_right_int_less() {
- int x = f()+2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 2;
+ y += 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}}
}
void compare_different_symbol_plus_left_minus_right_int_less() {
- int x = f()+2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 3}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x += 2;
+ y -= 1;
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 3}}
}
void compare_different_symbol_minus_left_plus_right_int_less() {
- int x = f()-2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 3}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 2;
+ y += 1;
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 3}}
}
void compare_different_symbol_minus_left_minus_right_int_less() {
- int x = f()-2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+ int x = f(), y = f();
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ x -= 2;
+ y -= 1;
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}}
}
void compare_same_symbol_less() {
int x = f(), y = x;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_left_int_less() {
int x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_left_int_less() {
int x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x < y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_right_int_less() {
- int x = f(), y = x+1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{TRUE}}
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{TRUE}}
}
void compare_same_symbol_minus_right_int_less() {
- int x = f(), y = x-1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_left_plus_right_int_less() {
- int x = f(), y = x+1;
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_left_minus_right_int_less() {
- int x = f(), y = x-1;
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_same_symbol_minus_left_plus_right_int_less() {
- int x = f(), y = x+1;
+ int x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{TRUE}}
}
void compare_same_symbol_minus_left_minus_right_int_less() {
- int x = f(), y = x-1;
+ int x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_different_symbol_equal_unsigned() {
unsigned x = f(), y = f();
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 0}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 0}}
}
void compare_different_symbol_plus_left_int_equal_unsigned() {
- unsigned x = f()+1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+ unsigned x = f() + 1, y = f();
+ clang_analyzer_denote(x - 1, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}}
}
void compare_different_symbol_minus_left_int_equal_unsigned() {
- unsigned x = f()-1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+ unsigned x = f() - 1, y = f();
+ clang_analyzer_denote(x + 1, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}}
}
void compare_different_symbol_plus_right_int_equal_unsigned() {
- unsigned x = f(), y = f()+2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 2}}
+ unsigned x = f(), y = f() + 2;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y - 2, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y + 2}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 2}}
}
void compare_different_symbol_minus_right_int_equal_unsigned() {
- unsigned x = f(), y = f()-2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 2}}
+ unsigned x = f(), y = f() - 2;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y + 2, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y - 2}}
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 2}}
}
void compare_different_symbol_plus_left_plus_right_int_equal_unsigned() {
- unsigned x = f()+2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 1}}
+ unsigned x = f() + 2, y = f() + 1;
+ clang_analyzer_denote(x - 2, "$x");
+ clang_analyzer_denote(y - 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 1}}
}
void compare_different_symbol_plus_left_minus_right_int_equal_unsigned() {
- unsigned x = f()+2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) == 3}}
+ unsigned x = f() + 2, y = f() - 1;
+ clang_analyzer_denote(x - 2, "$x");
+ clang_analyzer_denote(y + 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$y - $x == 3}}
}
void compare_different_symbol_minus_left_plus_right_int_equal_unsigned() {
- unsigned x = f()-2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 3}}
+ unsigned x = f() - 2, y = f() + 1;
+ clang_analyzer_denote(x + 2, "$x");
+ clang_analyzer_denote(y - 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 3}}
}
void compare_different_symbol_minus_left_minus_right_int_equal_unsigned() {
- unsigned x = f()-2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) == 1}}
+ unsigned x = f() - 2, y = f() - 1;
+ clang_analyzer_denote(x + 2, "$x");
+ clang_analyzer_denote(y + 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - $y == 1}}
}
void compare_same_symbol_equal_unsigned() {
unsigned x = f(), y = x;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_int_equal_unsigned() {
unsigned x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) + 1U) == (conj_$2{int})}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $x}}
}
void compare_same_symbol_minus_left_int_equal_unsigned() {
unsigned x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - 1U) == (conj_$2{int})}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - 1U == $x}}
}
void compare_same_symbol_plus_right_int_equal_unsigned() {
- unsigned x = f(), y = x+1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{(conj_$2{int}) == ((conj_$2{int}) + 1U)}}
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x == $x + 1U}}
}
void compare_same_symbol_minus_right_int_equal_unsigned() {
- unsigned x = f(), y = x-1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{(conj_$2{int}) == ((conj_$2{int}) - 1U)}}
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x == $x - 1U}}
}
void compare_same_symbol_plus_left_plus_right_int_equal_unsigned() {
- unsigned x = f(), y = x+1;
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_minus_right_int_equal_unsigned() {
- unsigned x = f(), y = x-1;
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) + 1U) == ((conj_$2{int}) - 1U)}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $x - 1U}}
}
void compare_same_symbol_minus_left_plus_right_int_equal_unsigned() {
- unsigned x = f(), y = x+1;
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(x == y);
- // expected-warning@-1{{((conj_$2{int}) - 1U) == ((conj_$2{int}) + 1U)}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_express(x == y); // expected-warning {{$x - 1U == $x + 1U}}
}
void compare_same_symbol_minus_left_minus_right_int_equal_unsigned() {
- unsigned x = f(), y = x-1;
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x == y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
}
void compare_different_symbol_less_or_equal_unsigned() {
unsigned x = f(), y = f();
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 0}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 0}}
}
void compare_different_symbol_plus_left_int_less_or_equal_unsigned() {
- unsigned x = f()+1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+ unsigned x = f() + 1, y = f();
+ clang_analyzer_denote(x - 1, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}}
}
void compare_different_symbol_minus_left_int_less_or_equal_unsigned() {
- unsigned x = f()-1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+ unsigned x = f() - 1, y = f();
+ clang_analyzer_denote(x + 1, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}}
}
void compare_different_symbol_plus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = f()+2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 2}}
+ unsigned x = f(), y = f() + 2;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y - 2, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y + 2}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 2}}
}
void compare_different_symbol_minus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = f()-2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 2}}
+ unsigned x = f(), y = f() - 2;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y + 2, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y - 2}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 2}}
}
void compare_different_symbol_plus_left_plus_right_int_less_or_equal_unsigned() {
- unsigned x = f()+2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 1}}
+ unsigned x = f() + 2, y = f() + 1;
+ clang_analyzer_denote(x - 2, "$x");
+ clang_analyzer_denote(y - 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 1}}
}
void compare_different_symbol_plus_left_minus_right_int_less_or_equal_unsigned() {
- unsigned x = f()+2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) >= 3}}
+ unsigned x = f() + 2, y = f() - 1;
+ clang_analyzer_denote(x - 2, "$x");
+ clang_analyzer_denote(y + 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$y - $x >= 3}}
}
void compare_different_symbol_minus_left_plus_right_int_less_or_equal_unsigned() {
- unsigned x = f()-2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 3}}
+ unsigned x = f() - 2, y = f() + 1;
+ clang_analyzer_denote(x + 2, "$x");
+ clang_analyzer_denote(y - 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 3}}
}
void compare_different_symbol_minus_left_minus_right_int_less_or_equal_unsigned() {
- unsigned x = f()-2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) <= 1}}
+ unsigned x = f() - 2, y = f() - 1;
+ clang_analyzer_denote(x + 2, "$x");
+ clang_analyzer_denote(y + 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - $y <= 1}}
}
void compare_same_symbol_less_or_equal_unsigned() {
unsigned x = f(), y = x;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_int_less_or_equal_unsigned() {
unsigned x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) + 1U) <= (conj_$2{int})}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x + 1U <= $x}}
}
void compare_same_symbol_minus_left_int_less_or_equal_unsigned() {
unsigned x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - 1U) <= (conj_$2{int})}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - 1U <= $x}}
}
void compare_same_symbol_plus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = x+1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{(conj_$2{int}) <= ((conj_$2{int}) + 1U)}}
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x <= $x + 1U}}
}
void compare_same_symbol_minus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = x-1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{(conj_$2{int}) <= ((conj_$2{int}) - 1U)}}
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x <= $x - 1U}}
}
void compare_same_symbol_plus_left_plus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = x+1;
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_same_symbol_plus_left_minus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = x-1;
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) + 1U) <= ((conj_$2{int}) - 1U)}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x + 1U <= $x - 1U}}
}
void compare_same_symbol_minus_left_plus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = x+1;
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(x <= y);
- // expected-warning@-1{{((conj_$2{int}) - 1U) <= ((conj_$2{int}) + 1U)}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_express(x <= y); // expected-warning {{$x - 1U <= $x + 1U}}
}
void compare_same_symbol_minus_left_minus_right_int_less_or_equal_unsigned() {
- unsigned x = f(), y = x-1;
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x <= y);
- // expected-warning@-1{{TRUE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x <= y); // expected-warning {{TRUE}}
}
void compare_different_symbol_less_unsigned() {
unsigned x = f(), y = f();
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 0}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 0}}
}
void compare_different_symbol_plus_left_int_less_unsigned() {
- unsigned x = f()+1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+ unsigned x = f() + 1, y = f();
+ clang_analyzer_denote(x - 1, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}}
}
void compare_different_symbol_minus_left_int_less_unsigned() {
- unsigned x = f()-1, y = f();
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$9{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+ unsigned x = f() - 1, y = f();
+ clang_analyzer_denote(x + 1, "$x");
+ clang_analyzer_denote(y, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}}
}
void compare_different_symbol_plus_right_int_less_unsigned() {
- unsigned x = f(), y = f()+2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 2}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 2}}
+ unsigned x = f(), y = f() + 2;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y - 2, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y + 2}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 2}}
}
void compare_different_symbol_minus_right_int_less_unsigned() {
- unsigned x = f(), y = f()-2;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 2}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 2}}
+ unsigned x = f(), y = f() - 2;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_denote(y + 2, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y - 2}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 2}}
}
void compare_different_symbol_plus_left_plus_right_int_less_unsigned() {
- unsigned x = f()+2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 1}}
+ unsigned x = f() + 2, y = f() + 1;
+ clang_analyzer_denote(x - 2, "$x");
+ clang_analyzer_denote(y - 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 1}}
}
void compare_different_symbol_plus_left_minus_right_int_less_unsigned() {
- unsigned x = f()+2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$9{int}) - (conj_$2{int})) > 3}}
+ unsigned x = f() + 2, y = f() - 1;
+ clang_analyzer_denote(x - 2, "$x");
+ clang_analyzer_denote(y + 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x + 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$y - $x > 3}}
}
void compare_different_symbol_minus_left_plus_right_int_less_unsigned() {
- unsigned x = f()-2, y = f()+1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) + 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 3}}
+ unsigned x = f() - 2, y = f() + 1;
+ clang_analyzer_denote(x + 2, "$x");
+ clang_analyzer_denote(y - 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y + 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 3}}
}
void compare_different_symbol_minus_left_minus_right_int_less_unsigned() {
- unsigned x = f()-2, y = f()-1;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 2}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$9{int}) - 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - (conj_$9{int})) < 1}}
+ unsigned x = f() - 2, y = f() - 1;
+ clang_analyzer_denote(x + 2, "$x");
+ clang_analyzer_denote(y + 1, "$y");
+ clang_analyzer_express(x); // expected-warning {{$x - 2}}
+ clang_analyzer_express(y); // expected-warning {{$y - 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - $y < 1}}
}
void compare_same_symbol_less_unsigned() {
unsigned x = f(), y = x;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_left_int_less_unsigned() {
unsigned x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) + 1U) < (conj_$2{int})}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_express(x < y); // expected-warning {{$x + 1U < $x}}
}
void compare_same_symbol_minus_left_int_less_unsigned() {
unsigned x = f(), y = x;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - 1U) < (conj_$2{int})}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - 1U < $x}}
}
void compare_same_symbol_plus_right_int_less_unsigned() {
- unsigned x = f(), y = x+1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{(conj_$2{int}) < ((conj_$2{int}) + 1U)}}
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x < $x + 1U}}
}
void compare_same_symbol_minus_right_int_less_unsigned() {
- unsigned x = f(), y = x-1;
- clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{(conj_$2{int}) < ((conj_$2{int}) - 1U)}}
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x < $x - 1U}}
}
void compare_same_symbol_plus_left_plus_right_int_less_unsigned() {
- unsigned x = f(), y = x+1;
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void compare_same_symbol_plus_left_minus_right_int_less_unsigned() {
- unsigned x = f(), y = x-1;
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
++x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) + 1U) < ((conj_$2{int}) - 1U)}}
+ clang_analyzer_express(x); // expected-warning {{$x + 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x + 1U < $x - 1U}}
}
void compare_same_symbol_minus_left_plus_right_int_less_unsigned() {
- unsigned x = f(), y = x+1;
+ unsigned x = f(), y = x + 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}}
- clang_analyzer_dump(x < y);
- // expected-warning@-1{{((conj_$2{int}) - 1U) < ((conj_$2{int}) + 1U)}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x + 1}}
+ clang_analyzer_express(x < y); // expected-warning {{$x - 1U < $x + 1U}}
}
void compare_same_symbol_minus_left_minus_right_int_less_unsigned() {
- unsigned x = f(), y = x-1;
+ unsigned x = f(), y = x - 1;
+ clang_analyzer_denote(x, "$x");
--x;
- clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}}
- clang_analyzer_eval(x < y);
- // expected-warning@-1{{FALSE}}
+ clang_analyzer_express(x); // expected-warning {{$x - 1}}
+ clang_analyzer_express(y); // expected-warning {{$x - 1}}
+ clang_analyzer_eval(x < y); // expected-warning {{FALSE}}
}
void overflow(signed char n, signed char m) {
if (n + 0 > m + 0) {
- clang_analyzer_eval(n - 126 == m + 3); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(n - 126 == m + 3); // expected-warning {{UNKNOWN}}
}
}
@@ -934,3 +979,20 @@ int mixed_integer_types(int x, int y) {
short a = x - 1U;
return a - y;
}
+
+unsigned gu();
+unsigned fu() {
+ unsigned x = gu();
+ // Assert that no overflows occur in this test file.
+ // Assuming that concrete integers are also within that range.
+ assert(x <= ((unsigned)UINT_MAX / 4));
+ return x;
+}
+
+void unsigned_concrete_int_no_crash() {
+ unsigned x = fu() + 1U, y = fu() + 1U;
+ clang_analyzer_denote(x - 1U, "$x");
+ clang_analyzer_denote(y - 1U, "$y");
+ clang_analyzer_express(y); // expected-warning {{$y}}
+ clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $y + 1U}}
+}
diff --git a/test/Analysis/switch-case.c b/test/Analysis/switch-case.c
index 08403937e019..1391f437f1f0 100644
--- a/test/Analysis/switch-case.c
+++ b/test/Analysis/switch-case.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(int);
void clang_analyzer_warnIfReached();
diff --git a/test/Analysis/symbol-reaper.c b/test/Analysis/symbol-reaper.c
index a47161bea2e3..ef8ff18a2d83 100644
--- a/test/Analysis/symbol-reaper.c
+++ b/test/Analysis/symbol-reaper.c
@@ -85,8 +85,7 @@ void test_loc_as_integer_element_index_lifetime() {
x = (int)&(s->field);
ptr = &arr[x];
if (s) {}
- // FIXME: Should not warn. The symbol is still alive within the ptr's index.
- } while (0); // expected-warning{{SYMBOL DEAD}}
+ } while (0);
}
// Test below checks lifetime of SymbolRegionValue in certain conditions.
diff --git a/test/Analysis/temp-obj-dtors-option.cpp b/test/Analysis/temp-obj-dtors-option.cpp
index 25cc86ebde43..a78dee2bd311 100644
--- a/test/Analysis/temp-obj-dtors-option.cpp
+++ b/test/Analysis/temp-obj-dtors-option.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-temp-dtor-inlining=false -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-temp-dtor-inlining=true -DINLINE -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-temp-dtor-inlining=false -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-temp-dtor-inlining=true -DINLINE -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/templates.cpp b/test/Analysis/templates.cpp
index c1631e0db90c..e7c30a764f72 100644
--- a/test/Analysis/templates.cpp
+++ b/test/Analysis/templates.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -fblocks -analyzer-config c++-template-inlining=false -DNO_INLINE -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -fblocks -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -fblocks -analyzer-config c++-template-inlining=false -DNO_INLINE -verify -analyzer-config eagerly-assume=false %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp
index e760d7ea283a..6191abfb4d2e 100644
--- a/test/Analysis/temporaries.cpp
+++ b/test/Analysis/temporaries.cpp
@@ -1,15 +1,31 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++03 %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -analyzer-config cfg-temporary-dtors=false -verify -w -std=c++11 %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++11
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus,debug.ExprInspection -DTEMPORARY_DTORS -w -analyzer-config cfg-temporary-dtors=true,c++-temp-dtor-inlining=true %s -std=c++17
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
+// RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
+// RUN: -analyzer-config eagerly-assume=false -verify %s\
+// RUN: -std=c++03 -analyzer-config cfg-temporary-dtors=false
+
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
+// RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
+// RUN: -analyzer-config eagerly-assume=false -verify %s\
+// RUN: -std=c++11 -analyzer-config cfg-temporary-dtors=false
+
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
+// RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
+// RUN: -analyzer-config eagerly-assume=false -verify %s\
+// RUN: -std=c++11 -analyzer-config cfg-temporary-dtors=true\
+// RUN: -DTEMPORARY_DTORS
+
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
+// RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
+// RUN: -analyzer-config eagerly-assume=false -verify %s\
+// RUN: -std=c++17 -analyzer-config cfg-temporary-dtors=true\
+// RUN: -DTEMPORARY_DTORS
-// Note: The C++17 run-line doesn't -verify yet - it is a no-crash test.
extern bool clang_analyzer_eval(bool);
extern bool clang_analyzer_warnIfReached();
void clang_analyzer_checkInlined(bool);
-#include "Inputs/system-header-simulator-cxx.h";
+#include "Inputs/system-header-simulator-cxx.h"
struct Trivial {
Trivial(int x) : value(x) {}
@@ -450,7 +466,16 @@ namespace destructors {
}
#if __cplusplus >= 201103L
- CtorWithNoReturnDtor returnNoReturnDtor() {
+ struct CtorWithNoReturnDtor2 {
+ CtorWithNoReturnDtor2() = default;
+
+ CtorWithNoReturnDtor2(int x) {
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+ }
+
+ ~CtorWithNoReturnDtor2() __attribute__((noreturn));
+ };
+ CtorWithNoReturnDtor2 returnNoReturnDtor() {
return {1}; // no-crash
}
#endif
@@ -805,7 +830,12 @@ void test_ternary_temporary_with_copy(int coin) {
// On each branch the variable is constructed directly.
if (coin) {
clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
+#if __cplusplus < 201703L
clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}
+#else
+ // FIXME: Destructor called twice in C++17?
+ clang_analyzer_eval(y == 2); // expected-warning{{TRUE}}
+#endif
clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}
@@ -813,7 +843,12 @@ void test_ternary_temporary_with_copy(int coin) {
clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(z == 1); // expected-warning{{TRUE}}
+#if __cplusplus < 201703L
clang_analyzer_eval(w == 1); // expected-warning{{TRUE}}
+#else
+ // FIXME: Destructor called twice in C++17?
+ clang_analyzer_eval(w == 2); // expected-warning{{TRUE}}
+#endif
}
}
} // namespace test_match_constructors_and_destructors
@@ -865,9 +900,12 @@ class C {
public:
~C() {
glob = 1;
+ // FIXME: Why is destructor not inlined in C++17
clang_analyzer_checkInlined(true);
#ifdef TEMPORARY_DTORS
- // expected-warning@-2{{TRUE}}
+#if __cplusplus < 201703L
+ // expected-warning@-3{{TRUE}}
+#endif
#endif
}
};
@@ -886,11 +924,16 @@ void test(int coin) {
// temporaries returned from functions, so we took the wrong branch.
coin && is(get()); // no-crash
if (coin) {
+ // FIXME: Why is destructor not inlined in C++17
clang_analyzer_eval(glob);
#ifdef TEMPORARY_DTORS
- // expected-warning@-2{{TRUE}}
+#if __cplusplus < 201703L
+ // expected-warning@-3{{TRUE}}
+#else
+ // expected-warning@-5{{UNKNOWN}}
+#endif
#else
- // expected-warning@-4{{UNKNOWN}}
+ // expected-warning@-8{{UNKNOWN}}
#endif
} else {
// The destructor is not called on this branch.
@@ -962,6 +1005,92 @@ C &&bar2() { return foo2(); } // no-crash
} // end namespace pass_references_through
+namespace arguments {
+int glob;
+
+struct S {
+ int x;
+ S(int x): x(x) {}
+ S(const S &s) : x(s.x) {}
+ ~S() {}
+
+ S &operator+(S s) {
+ glob = s.x;
+ x += s.x;
+ return *this;
+ }
+};
+
+class C {
+public:
+ virtual void bar3(S s) {}
+};
+
+class D: public C {
+public:
+ D() {}
+ virtual void bar3(S s) override { glob = s.x; }
+};
+
+void bar1(S s) {
+ glob = s.x;
+}
+
+// Record-typed calls are a different CFGStmt, let's see if we handle that
+// as well.
+S bar2(S s) {
+ glob = s.x;
+ return S(3);
+}
+
+void bar5(int, ...);
+
+void foo(void (*bar4)(S)) {
+ bar1(S(1));
+ clang_analyzer_eval(glob == 1);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+
+ bar2(S(2));
+ // FIXME: Why are we losing information in C++17?
+ clang_analyzer_eval(glob == 2);
+#ifdef TEMPORARY_DTORS
+#if __cplusplus < 201703L
+ // expected-warning@-3{{TRUE}}
+#else
+ // expected-warning@-5{{UNKNOWN}}
+#endif
+#else
+ // expected-warning@-8{{UNKNOWN}}
+#endif
+
+ C *c = new D();
+ c->bar3(S(3));
+ // FIXME: Should be TRUE.
+ clang_analyzer_eval(glob == 3); // expected-warning{{UNKNOWN}}
+ delete c;
+
+ // What if we've no idea what we're calling?
+ bar4(S(4)); // no-crash
+
+ S(5) + S(6);
+ clang_analyzer_eval(glob == 6);
+#ifdef TEMPORARY_DTORS
+ // expected-warning@-2{{TRUE}}
+#else
+ // expected-warning@-4{{UNKNOWN}}
+#endif
+
+ // Variadic functions. This will __builtin_trap() because you cannot pass
+ // an object as a variadic argument.
+ bar5(7, S(7)); // no-crash
+ clang_analyzer_warnIfReached(); // no-warning
+}
+} // namespace arguments
+
namespace ctor_argument {
// Stripped down unique_ptr<int>
struct IntPtr {
@@ -986,3 +1115,134 @@ void bar() {
*i = 99; // no-warning
}
} // namespace ctor_argument
+
+namespace operator_implicit_argument {
+struct S {
+ bool x;
+ S(bool x): x(x) {}
+ operator bool() const { return x; }
+};
+
+void foo() {
+ if (S(false)) {
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+ if (S(true)) {
+ clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ }
+}
+} // namespace operator_implicit_argument
+
+
+#if __cplusplus >= 201103L
+namespace argument_lazy_bindings {
+int glob;
+
+struct S {
+ int x, y, z;
+};
+
+struct T {
+ S s;
+ int w;
+ T(int w): s{5, 6, 7}, w(w) {}
+};
+
+void foo(T t) {
+ t.s = {1, 2, 3};
+ glob = t.w;
+}
+
+void bar() {
+ foo(T(4));
+ clang_analyzer_eval(glob == 4); // expected-warning{{TRUE}}
+}
+} // namespace argument_lazy_bindings
+#endif
+
+namespace operator_argument_cleanup {
+struct S {
+ S();
+};
+
+class C {
+public:
+ void operator=(S);
+};
+
+void foo() {
+ C c;
+ c = S(); // no-crash
+}
+} // namespace operator_argument_cleanup
+
+namespace argument_decl_lookup {
+class C {};
+int foo(C);
+int bar(C c) { foo(c); }
+int foo(C c) {}
+} // namespace argument_decl_lookup
+
+namespace argument_virtual_decl_lookup {
+class C {};
+
+struct T {
+ virtual void foo(C);
+};
+
+void run() {
+ T *t;
+ t->foo(C()); // no-crash // expected-warning{{Called C++ object pointer is uninitialized}}
+}
+
+// This is after run() because the test is about picking the correct decl
+// for the parameter region, which should belong to the correct function decl,
+// and the non-definition decl should be found by direct lookup.
+void T::foo(C) {}
+} // namespace argument_virtual_decl_lookup
+
+namespace union_indirect_field_crash {
+union U {
+ struct {
+ int x;
+ };
+};
+
+template <typename T> class C {
+public:
+ void foo() const {
+ (void)(true ? U().x : 0);
+ }
+};
+
+void test() {
+ C<int> c;
+ c.foo();
+}
+} // namespace union_indirect_field_crash
+
+namespace return_from_top_frame {
+struct S {
+ int *p;
+ S() { p = new int; }
+ S(S &&s) : p(s.p) { s.p = 0; }
+ ~S(); // Presumably releases 'p'.
+};
+
+S foo() {
+ S s;
+ return s;
+}
+
+S bar1() {
+ return foo(); // no-warning
+}
+
+S bar2() {
+ return S();
+}
+
+S bar3(int coin) {
+ return coin ? S() : foo(); // no-warning
+}
+} // namespace return_from_top_frame
diff --git a/test/Analysis/temporaries.mm b/test/Analysis/temporaries.mm
index 3b6166db6e30..43546ae3441d 100644
--- a/test/Analysis/temporaries.mm
+++ b/test/Analysis/temporaries.mm
@@ -2,6 +2,8 @@
// expected-no-diagnostics
+#define nil ((id)0)
+
// Stripped down unique_ptr<int>
struct IntPtr {
IntPtr(): i(new int) {}
@@ -15,9 +17,13 @@ struct IntPtr {
-(void) foo: (IntPtr)arg;
@end
-void bar(Foo *f) {
+void testArgumentRegionInvalidation(Foo *f) {
IntPtr ptr;
int *i = ptr.i;
[f foo: static_cast<IntPtr &&>(ptr)];
*i = 99; // no-warning
}
+
+void testNilReceiverCleanup() {
+ [nil foo: IntPtr()];
+}
diff --git a/test/Analysis/test-after-div-zero.c b/test/Analysis/test-after-div-zero.c
index 159c80c11d86..451c9adfee23 100644
--- a/test/Analysis/test-after-div-zero.c
+++ b/test/Analysis/test-after-div-zero.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -std=c99 -Dbool=_Bool -analyzer-checker=core,alpha.core.TestAfterDivZero -analyzer-output=text -verify %s
-// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=core,alpha.core.TestAfterDivZero -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -std=c99 -Dbool=_Bool -analyzer-checker=core,alpha.core.TestAfterDivZero -analyzer-output=text -verify -analyzer-config eagerly-assume=false %s
+// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=core,alpha.core.TestAfterDivZero -analyzer-output=text -verify -analyzer-config eagerly-assume=false %s
int var;
diff --git a/test/Analysis/test-separate-retaincount.cpp b/test/Analysis/test-separate-retaincount.cpp
new file mode 100644
index 000000000000..be6534f544bd
--- /dev/null
+++ b/test/Analysis/test-separate-retaincount.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-disable-checker osx.cocoa.RetainCount -DNO_CF_OBJECT -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-disable-checker osx.OSObjectRetainCount -DNO_OS_OBJECT -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-config "osx.cocoa.RetainCount:CheckOSObject=false" -DNO_OS_OBJECT -verify %s
+
+typedef const void * CFTypeRef;
+extern CFTypeRef CFRetain(CFTypeRef cf);
+extern void CFRelease(CFTypeRef cf);
+
+#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
+extern CFTypeRef CFCreate() CF_RETURNS_RETAINED;
+
+using size_t = decltype(sizeof(int));
+
+struct OSObject {
+ virtual void retain();
+ virtual void release();
+
+ static void * operator new(size_t size);
+ virtual ~OSObject(){}
+};
+
+void cf_overrelease() {
+ CFTypeRef cf = CFCreate();
+ CFRelease(cf);
+ CFRelease(cf);
+#ifndef NO_CF_OBJECT
+ // expected-warning@-2{{Reference-counted object is used after it is released}}
+#endif
+}
+
+void osobject_overrelease() {
+ OSObject *o = new OSObject;
+ o->release();
+ o->release();
+#ifndef NO_OS_OBJECT
+ // expected-warning@-2{{Reference-counted object is used after it is released}}
+#endif
+}
diff --git a/test/Analysis/trustnonnullchecker_test.m b/test/Analysis/trustnonnullchecker_test.m
index 67b6bd27c918..81eac863d5eb 100644
--- a/test/Analysis/trustnonnullchecker_test.m
+++ b/test/Analysis/trustnonnullchecker_test.m
@@ -1,7 +1,12 @@
-// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling -verify %s
+// Temporarily disabling the test, it failes the "system is over-constrained"
+// assertion in *non* optimized builds.
+// REQUIRES: rdar44992170
+// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling,debug.ExprInspection -verify %s
#include "Inputs/system-header-simulator-for-nullability.h"
+void clang_analyzer_warnIfReached();
+
NSString* _Nonnull trust_nonnull_framework_annotation() {
NSString* out = [NSString generateString];
if (out) {}
@@ -67,3 +72,126 @@ NSString * _Nonnull distrustProtocol(id<MyProtocol> o) {
return out; // expected-warning{{}}
}
+// If the return value is non-nil, the index is non-nil.
+NSString *_Nonnull retImpliesIndex(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (s) {}
+ if (obj)
+ return s; // no-warning
+ return @"foo";
+}
+
+NSString *_Nonnull retImpliesIndexOtherMethod(NSString *s,
+ NSDictionary *dic) {
+ id obj = [dic objectForKey:s];
+ if (s) {}
+ if (obj)
+ return s; // no-warning
+ return @"foo";
+}
+
+NSString *_Nonnull retImpliesIndexOnRHS(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (s) {}
+ if (nil != obj)
+ return s; // no-warning
+ return @"foo";
+}
+
+NSString *_Nonnull retImpliesIndexReverseCheck(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (s) {}
+ if (!obj)
+ return @"foo";
+ return s; // no-warning
+}
+
+NSString *_Nonnull retImpliesIndexReverseCheckOnRHS(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (s) {}
+ if (nil == obj)
+ return @"foo";
+ return s; // no-warning
+}
+
+NSString *_Nonnull retImpliesIndexWrongBranch(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (s) {}
+ if (!obj)
+ return s; // expected-warning{{}}
+ return @"foo";
+}
+
+NSString *_Nonnull retImpliesIndexWrongBranchOnRHS(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (s) {}
+ if (nil == obj)
+ return s; // expected-warning{{}}
+ return @"foo";
+}
+
+// The return value could still be nil for a non-nil index.
+NSDictionary *_Nonnull indexDoesNotImplyRet(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (obj) {}
+ if (s)
+ return obj; // expected-warning{{}}
+ return [[NSDictionary alloc] init];
+}
+
+// The return value could still be nil for a non-nil index.
+NSDictionary *_Nonnull notIndexImpliesNotRet(NSString *s,
+ NSDictionary *dic) {
+ id obj = dic[s];
+ if (!s) {
+ if (obj != nil) {
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+ }
+ return [[NSDictionary alloc] init];
+}
+
+NSString *_Nonnull checkAssumeOnMutableDictionary(NSMutableDictionary *d,
+ NSString *k,
+ NSString *val) {
+ d[k] = val;
+ if (k) {}
+ return k; // no-warning
+}
+
+NSString *_Nonnull checkAssumeOnMutableDictionaryOtherMethod(NSMutableDictionary *d,
+ NSString *k,
+ NSString *val) {
+ [d setObject:val forKey:k];
+ if (k) {}
+ return k; // no-warning
+}
+
+// Check that we don't crash when the added assumption is enough
+// to make the state unfeasible.
+@class DummyClass;
+@interface DictionarySubclass : NSDictionary {
+ DummyClass *g;
+ DictionarySubclass *d;
+}
+@end
+@implementation DictionarySubclass
+- (id) objectForKey:(id)e {
+ if (e) {}
+ return d;
+}
+- (void) coder {
+ for (id e in g) {
+ id f = [self objectForKey:e];
+ if (f)
+ (void)e;
+ }
+}
+@end
diff --git a/test/Analysis/ubigraph-viz.cpp b/test/Analysis/ubigraph-viz.cpp
deleted file mode 100644
index 228dd660c7ff..000000000000
--- a/test/Analysis/ubigraph-viz.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API -analyzer-viz-egraph-ubigraph -verify %s
-// expected-no-diagnostics
-
-int f(int x) {
- return x < 0 ? 0 : 42;
-}
-
diff --git a/test/Analysis/undef-call.c b/test/Analysis/undef-call.c
index 35c0b685ce7e..c7aa844d7982 100644
--- a/test/Analysis/undef-call.c
+++ b/test/Analysis/undef-call.c
@@ -1,3 +1,5 @@
+// RUN: rm -rf %T/ctudir
+// RUN: mkdir %T/ctudir
// RUN: %clang_cc1 -fsyntax-only -analyze -analyzer-checker=debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s
// expected-no-diagnostics
diff --git a/test/Analysis/uninit-const.cpp b/test/Analysis/uninit-const.cpp
index f5166e6b27b2..b6430307dc52 100644
--- a/test/Analysis/uninit-const.cpp
+++ b/test/Analysis/uninit-const.cpp
@@ -49,15 +49,17 @@ void f7(void) {
int& f6_1_sub(int &p) {
- return p;
+ return p; // expected-note{{Returning without writing to 'p'}}
+ // expected-note@-1{{Returning pointer (reference to 't')}}
}
void f6_1(void) {
int t; // expected-note{{'t' declared without an initial value}}
int p = f6_1_sub(t); //expected-warning {{Assigned value is garbage or undefined}}
- //expected-note@-1 {{Calling 'f6_1_sub'}}
- //expected-note@-2 {{Returning from 'f6_1_sub'}}
- //expected-note@-3 {{Assigned value is garbage or undefined}}
+ //expected-note@-1 {{Passing value via 1st parameter 'p'}}
+ //expected-note@-2 {{Calling 'f6_1_sub'}}
+ //expected-note@-3 {{Returning from 'f6_1_sub'}}
+ //expected-note@-4 {{Assigned value is garbage or undefined}}
int q = p;
doStuff6(q);
}
diff --git a/test/Analysis/uninit-vals-ps-region.m b/test/Analysis/uninit-vals-ps-region.m
deleted file mode 100644
index 18010f240d3d..000000000000
--- a/test/Analysis/uninit-vals-ps-region.m
+++ /dev/null
@@ -1,93 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-store=region -analyzer-checker=core -verify %s
-
-struct s {
- int data;
-};
-
-struct s global;
-
-void g(int);
-
-void f4() {
- int a;
- if (global.data == 0)
- a = 3;
- if (global.data == 0) // When the true branch is feasible 'a = 3'.
- g(a); // no-warning
-}
-
-
-// Test uninitialized value due to part of the structure being uninitialized.
-struct TestUninit { int x; int y; };
-struct TestUninit test_uninit_aux();
-void test_unit_aux2(int);
-void test_uninit_pos() {
- struct TestUninit v1 = { 0, 0 };
- struct TestUninit v2 = test_uninit_aux();
- int z;
- v1.y = z; // expected-warning{{Assigned value is garbage or undefined}}
- test_unit_aux2(v2.x + v1.y);
-}
-void test_uninit_pos_2() {
- struct TestUninit v1 = { 0, 0 };
- struct TestUninit v2;
- test_unit_aux2(v2.x + v1.y); // expected-warning{{The left operand of '+' is a garbage value}}
-}
-void test_uninit_pos_3() {
- struct TestUninit v1 = { 0, 0 };
- struct TestUninit v2;
- test_unit_aux2(v1.y + v2.x); // expected-warning{{The right operand of '+' is a garbage value}}
-}
-
-void test_uninit_neg() {
- struct TestUninit v1 = { 0, 0 };
- struct TestUninit v2 = test_uninit_aux();
- test_unit_aux2(v2.x + v1.y);
-}
-
-extern void test_uninit_struct_arg_aux(struct TestUninit arg);
-void test_uninit_struct_arg() {
- struct TestUninit x;
- test_uninit_struct_arg_aux(x); // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
-}
-
-@interface Foo
-- (void) passVal:(struct TestUninit)arg;
-@end
-void testFoo(Foo *o) {
- struct TestUninit x;
- [o passVal:x]; // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
-}
-
-// Test case from <rdar://problem/7780304>. That shows an uninitialized value
-// being used in the LHS of a compound assignment.
-void rdar_7780304() {
- typedef struct s_r7780304 { int x; } s_r7780304;
- s_r7780304 b;
- b.x |= 1; // expected-warning{{The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage}}
-}
-
-
-// The flip side of PR10163 -- float arrays that are actually uninitialized
-// (The main test is in uninit-vals.m)
-void test_PR10163(float);
-void PR10163 (void) {
- float x[2];
- test_PR10163(x[1]); // expected-warning{{uninitialized value}}
-}
-
-struct MyStr {
- int x;
- int y;
-};
-void swap(struct MyStr *To, struct MyStr *From) {
- // This is not really a swap but close enough for our test.
- To->x = From->x;
- To->y = From->y; // no warning
-}
-int test_undefined_member_assignment_in_swap(struct MyStr *s2) {
- struct MyStr s1;
- s1.x = 5;
- swap(s2, &s1);
- return s2->y; // expected-warning{{Undefined or garbage value returned to caller}}
-}
diff --git a/test/Analysis/uninit-vals-ps.c b/test/Analysis/uninit-vals.c
index ee25d9d9a602..d24b45874738 100644
--- a/test/Analysis/uninit-vals-ps.c
+++ b/test/Analysis/uninit-vals.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify -analyzer-output=text %s
struct FPRec {
void (*my_func)(int * x);
@@ -13,30 +13,34 @@ int f1_a(struct FPRec* foo) {
}
int f1_b() {
- int x;
+ int x; // expected-note{{'x' declared without an initial value}}
return bar(x)+1; // expected-warning{{1st function call argument is an uninitialized value}}
+ // expected-note@-1{{1st function call argument is an uninitialized value}}
}
int f2() {
- int x;
+ int x; // expected-note{{'x' declared without an initial value}}
if (x+1) // expected-warning{{The left operand of '+' is a garbage value}}
+ // expected-note@-1{{The left operand of '+' is a garbage value}}
return 1;
return 2;
}
int f2_b() {
- int x;
+ int x; // expected-note{{'x' declared without an initial value}}
return ((1+x)+2+((x))) + 1 ? 1 : 2; // expected-warning{{The right operand of '+' is a garbage value}}
+ // expected-note@-1{{The right operand of '+' is a garbage value}}
}
int f3(void) {
- int i;
+ int i; // expected-note{{'i' declared without an initial value}}
int *p = &i;
if (*p > 0) // expected-warning{{The left operand of '>' is a garbage value}}
+ // expected-note@-1{{The left operand of '>' is a garbage value}}
return 0;
else
return 1;
@@ -59,14 +63,17 @@ int f5(void) {
void f6(int x) {
int a[20];
- if (x == 25) {}
+ if (x == 25) {} // expected-note{{Assuming 'x' is equal to 25}}
+ // expected-note@-1{{Taking true branch}}
if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}}
+ // expected-note@-1{{The left operand of '==' is a garbage value due to array index out of bounds}}
}
int ret_uninit() {
- int i;
+ int i; // expected-note{{'i' declared without an initial value}}
int *p = &i;
return *p; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
}
// <rdar://problem/6451816>
@@ -141,6 +148,9 @@ typedef void (*RetVoidFuncType)();
int test_radar12278788_FP() {
RetVoidFuncType f = foo_radar12278788_fp;
return ((RetIntFuncType)f)(); //expected-warning {{Undefined or garbage value returned to caller}}
+ //expected-note@-1 {{Undefined or garbage value returned to caller}}
+ //expected-note@-2 {{Calling 'foo_radar12278788_fp'}}
+ //expected-note@-3 {{Returning from 'foo_radar12278788_fp'}}
}
void rdar13665798() {
@@ -150,8 +160,40 @@ void rdar13665798() {
^void() {
return foo_radar12278788(); // no-warning
}();
- ^int() {
+ ^int() { // expected-note{{Calling anonymous block}}
RetVoidFuncType f = foo_radar12278788_fp;
return ((RetIntFuncType)f)(); //expected-warning {{Undefined or garbage value returned to caller}}
+ //expected-note@-1 {{Undefined or garbage value returned to caller}}
+ //expected-note@-2 {{Calling 'foo_radar12278788_fp'}}
+ //expected-note@-3 {{Returning from 'foo_radar12278788_fp'}}
}();
}
+
+struct Point {
+ int x, y;
+};
+
+struct Point getHalfPoint() {
+ struct Point p;
+ p.x = 0;
+ return p;
+}
+
+void use(struct Point p);
+
+void testUseHalfPoint() {
+ struct Point p = getHalfPoint(); // expected-note{{Calling 'getHalfPoint'}}
+ // expected-note@-1{{Returning from 'getHalfPoint'}}
+ // expected-note@-2{{'p' initialized here}}
+ use(p); // expected-warning{{uninitialized}}
+ // expected-note@-1{{uninitialized}}
+}
+
+void testUseHalfPoint2() {
+ struct Point p;
+ p = getHalfPoint(); // expected-note{{Calling 'getHalfPoint'}}
+ // expected-note@-1{{Returning from 'getHalfPoint'}}
+ // expected-note@-2{{Value assigned to 'p'}}
+ use(p); // expected-warning{{uninitialized}}
+ // expected-note@-1{{uninitialized}}
+}
diff --git a/test/Analysis/uninit-vals.cpp b/test/Analysis/uninit-vals.cpp
index 5ab1348ae5c0..6ba56f0c4e78 100644
--- a/test/Analysis/uninit-vals.cpp
+++ b/test/Analysis/uninit-vals.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core.builtin -verify -DCHECK_FOR_CRASH %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -analyzer-output=text %s
#ifdef CHECK_FOR_CRASH
// expected-no-diagnostics
@@ -28,6 +28,7 @@ void foo() {
c1.b.a = c2->b.a;
#else
c1.b.a = c2->b.a; // expected-warning{{1st function call argument is an uninitialized value}}
+ // expected-note@-1{{1st function call argument is an uninitialized value}}
#endif
}
}
diff --git a/test/Analysis/uninit-vals.m b/test/Analysis/uninit-vals.m
index 7c18dee97606..f97af1a6633c 100644
--- a/test/Analysis/uninit-vals.m
+++ b/test/Analysis/uninit-vals.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-store=region -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-output=text -verify %s
typedef unsigned int NSUInteger;
typedef __typeof__(sizeof(int)) size_t;
@@ -9,6 +9,112 @@ void free(void *);
void clang_analyzer_eval(int);
+struct s {
+ int data;
+};
+
+struct s global;
+
+void g(int);
+
+void f4() {
+ int a;
+ if (global.data == 0)
+ a = 3;
+ if (global.data == 0) // When the true branch is feasible 'a = 3'.
+ g(a); // no-warning
+}
+
+
+// Test uninitialized value due to part of the structure being uninitialized.
+struct TestUninit { int x; int y; };
+struct TestUninit test_uninit_aux();
+void test_unit_aux2(int);
+void test_uninit_pos() {
+ struct TestUninit v1 = { 0, 0 };
+ struct TestUninit v2 = test_uninit_aux();
+ int z; // expected-note{{'z' declared without an initial value}}
+ v1.y = z; // expected-warning{{Assigned value is garbage or undefined}}
+ // expected-note@-1{{Assigned value is garbage or undefined}}
+ test_unit_aux2(v2.x + v1.y);
+}
+void test_uninit_pos_2() {
+ struct TestUninit v1 = { 0, 0 };
+ struct TestUninit v2;
+ test_unit_aux2(v2.x + v1.y); // expected-warning{{The left operand of '+' is a garbage value}}
+ // expected-note@-1{{The left operand of '+' is a garbage value}}
+}
+void test_uninit_pos_3() {
+ struct TestUninit v1 = { 0, 0 };
+ struct TestUninit v2;
+ test_unit_aux2(v1.y + v2.x); // expected-warning{{The right operand of '+' is a garbage value}}
+ // expected-note@-1{{The right operand of '+' is a garbage value}}
+}
+
+void test_uninit_neg() {
+ struct TestUninit v1 = { 0, 0 };
+ struct TestUninit v2 = test_uninit_aux();
+ test_unit_aux2(v2.x + v1.y);
+}
+
+extern void test_uninit_struct_arg_aux(struct TestUninit arg);
+void test_uninit_struct_arg() {
+ struct TestUninit x; // expected-note{{'x' initialized here}}
+ test_uninit_struct_arg_aux(x); // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
+ // expected-note@-1{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
+}
+
+@interface Foo
+- (void) passVal:(struct TestUninit)arg;
+@end
+void testFoo(Foo *o) {
+ struct TestUninit x; // expected-note{{'x' initialized here}}
+ [o passVal:x]; // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
+ // expected-note@-1{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
+}
+
+// Test case from <rdar://problem/7780304>. That shows an uninitialized value
+// being used in the LHS of a compound assignment.
+void rdar_7780304() {
+ typedef struct s_r7780304 { int x; } s_r7780304;
+ s_r7780304 b;
+ b.x |= 1; // expected-warning{{The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage}}
+ // expected-note@-1{{The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage}}
+}
+
+
+// The flip side of PR10163 -- float arrays that are actually uninitialized
+void test_PR10163(float);
+void PR10163 (void) {
+ float x[2];
+ test_PR10163(x[1]); // expected-warning{{uninitialized value}}
+ // expected-note@-1{{1st function call argument is an uninitialized value}}
+}
+
+// PR10163 -- don't warn for default-initialized float arrays.
+void PR10163_default_initialized_arrays(void) {
+ float x[2] = {0};
+ test_PR10163(x[1]); // no-warning
+}
+
+struct MyStr {
+ int x;
+ int y;
+};
+void swap(struct MyStr *To, struct MyStr *From) {
+ // This is not really a swap but close enough for our test.
+ To->x = From->x;
+ To->y = From->y; // expected-note{{Uninitialized value stored to field 'y'}}
+}
+int test_undefined_member_assignment_in_swap(struct MyStr *s2) {
+ struct MyStr s1;
+ s1.x = 5;
+ swap(s2, &s1); // expected-note{{Calling 'swap'}}
+ // expected-note@-1{{Returning from 'swap'}}
+ return s2->y; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}
+
@interface A
- (NSUInteger)foo;
@end
@@ -31,13 +137,6 @@ NSUInteger f8(A* x){
}
-// PR10163 -- don't warn for default-initialized float arrays.
-// (An additional test is in uninit-vals-ps-region.m)
-void test_PR10163(float);
-void PR10163 (void) {
- float x[2] = {0};
- test_PR10163(x[1]); // no-warning
-}
typedef struct {
@@ -62,15 +161,17 @@ void PR14765_test() {
Circle *testObj = calloc(sizeof(Circle), 1);
clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
testObj->origin = makePoint(0.0, 0.0);
- if (testObj->size > 0) { ; } // warning occurs here
+ if (testObj->size > 0) { ; } // expected-note{{Taking false branch}}
// FIXME: Assigning to 'testObj->origin' kills the default binding for the
// whole region, meaning that we've forgotten that testObj->size should also
// default to 0. Tracked by <rdar://problem/12701038>.
// This should be TRUE.
clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
+ // expected-note@-1{{UNKNOWN}}
free(testObj);
}
@@ -78,9 +179,11 @@ void PR14765_test() {
void PR14765_argument(Circle *testObj) {
int oldSize = testObj->size;
clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
testObj->origin = makePoint(0.0, 0.0);
clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
}
@@ -106,21 +209,32 @@ void PR14765_test_int() {
IntCircle *testObj = calloc(sizeof(IntCircle), 1);
clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
testObj->origin = makeIntPoint(1, 2);
- if (testObj->size > 0) { ; } // warning occurs here
+ if (testObj->size > 0) { ; } // expected-note{{Taking false branch}}
+ // expected-note@-1{{Taking false branch}}
+ // expected-note@-2{{Taking false branch}}
+ // expected-note@-3{{Taking false branch}}
// FIXME: Assigning to 'testObj->origin' kills the default binding for the
// whole region, meaning that we've forgotten that testObj->size should also
// default to 0. Tracked by <rdar://problem/12701038>.
// This should be TRUE.
clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
+ // expected-note@-1{{UNKNOWN}}
clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
free(testObj);
}
@@ -128,12 +242,17 @@ void PR14765_test_int() {
void PR14765_argument_int(IntCircle *testObj) {
int oldSize = testObj->size;
clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
testObj->origin = makeIntPoint(1, 2);
clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
}
@@ -173,6 +292,7 @@ void testSmallStructsCopiedPerField() {
extern void useInt(int);
useInt(b.x); // no-warning
useInt(b.y); // expected-warning{{uninitialized}}
+ // expected-note@-1{{uninitialized}}
}
void testLargeStructsNotCopiedPerField() {
@@ -189,15 +309,23 @@ void testSmallStructInLargerStruct() {
IntCircle2D *testObj = calloc(sizeof(IntCircle2D), 1);
clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
testObj->origin = makeIntPoint2D(1, 2);
- if (testObj->size > 0) { ; } // warning occurs here
+ if (testObj->size > 0) { ; } // expected-note{{Taking false branch}}
+ // expected-note@-1{{Taking false branch}}
+ // expected-note@-2{{Taking false branch}}
clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
free(testObj);
}
@@ -205,11 +333,15 @@ void testSmallStructInLargerStruct() {
void testCopySmallStructIntoArgument(IntCircle2D *testObj) {
int oldSize = testObj->size;
clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
testObj->origin = makeIntPoint2D(1, 2);
clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
}
void testSmallStructBitfields() {
@@ -223,7 +355,9 @@ void testSmallStructBitfields() {
b = a;
clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
}
void testSmallStructBitfieldsFirstUndef() {
@@ -236,7 +370,9 @@ void testSmallStructBitfieldsFirstUndef() {
b = a;
clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}
+ // expected-note@-1{{garbage}}
}
void testSmallStructBitfieldsSecondUndef() {
@@ -249,7 +385,9 @@ void testSmallStructBitfieldsSecondUndef() {
b = a;
clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}
+ // expected-note@-1{{garbage}}
}
void testSmallStructBitfieldsFirstUnnamed() {
@@ -260,11 +398,13 @@ void testSmallStructBitfieldsFirstUnnamed() {
a.y = 2;
- b = a;
+ b = a; // expected-note{{Value assigned to 'c'}}
clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
- b = c;
+ b = c; // expected-note{{Uninitialized value stored to 'b.y'}}
clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}
+ // expected-note@-1{{garbage}}
}
void testSmallStructBitfieldsSecondUnnamed() {
@@ -275,10 +415,11 @@ void testSmallStructBitfieldsSecondUnnamed() {
a.x = 1;
- b = a;
+ b = a; // expected-note{{Value assigned to 'c'}}
clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
- b = c;
+ b = c; // expected-note{{Uninitialized value stored to 'b.x'}}
clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}
+ // expected-note@-1{{garbage}}
}
-
diff --git a/test/Analysis/unions.cpp b/test/Analysis/unions.cpp
index 2d6d0ae4a0db..618d4c314aa3 100644
--- a/test/Analysis/unions.cpp
+++ b/test/Analysis/unions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -verify
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -analyzer-config eagerly-assume=false -verify
extern void clang_analyzer_eval(bool);
extern "C" char *strdup(const char *s);
@@ -90,9 +90,8 @@ namespace PR17596 {
char str[] = "abc";
vv.s = str;
- // FIXME: This is a leak of uu.s.
uu = vv;
- }
+ } // expected-warning{{leak}}
void testIndirectInvalidation() {
IntOrString uu;
diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c
index 44e7a2e643e3..96e5d1d44537 100644
--- a/test/Analysis/unix-fns.c
+++ b/test/Analysis/unix-fns.c
@@ -1,8 +1,10 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist
-// RUN: FileCheck --input-file=%t.plist %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist
+// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/unix-fns.c.plist -
// RUN: mkdir -p %t.dir
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API,optin.portability -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s
// RUN: rm -fR %t.dir
+
+
struct _opaque_pthread_once_t {
long __sig;
char __opaque[8];
@@ -244,2834 +246,3 @@ void test_inline_dispatch_once_reachable() {
*p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
}
-
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>80</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>80</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>25</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;open&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5ef25c5c47db3dbfb329901d426452e7</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_open</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>85</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>91</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>44</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>50</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;open&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>433b17840bb989e7a13dc6337c1ed220</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_open_at</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>96</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>102</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>64</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>72</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>173fbcac3fc64dbaec32768d4cfda250</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_dispatch_once</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>103</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;pthread_once&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1e2f657a65cf8ee3c3ac2227de05ade4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_pthread_once</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>114</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0e841458f0cb7cf161d35f9db5862dcf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>pr2899</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>123</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a267ff573c7e8b959a3f886677893eb0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_calloc</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>135</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>14eb72957baab3c63bac610a10e6f48b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_calloc2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7f6f67ebe3d481aed7750005bea7e371</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_realloc</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>153</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4941698efbd81601653dff10ef9c645b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_reallocf</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>159</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b7ca3488e81d9d9d4b8dc545258ce97c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_alloca</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1ec52551362b070237f47f6bb6c3847d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_builtin_alloca</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>675741e04c8d0071d280324e23f41d35</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_valloc</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>1</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8ded1f2025c1e4a4bcd5302dc97006d9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_dispatch_once_in_macro</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>215</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>221</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is non-null</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>222</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5d3f4c433004c7a6d4a06aa30cc3ea85</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>223</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>230</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>231</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>231</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>231</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>231</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>231</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>231</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>231</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>234</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;_dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;_dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_inline_dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_inline_dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>232</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>265c4fd608dafee211bfa93d21c28866</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>233</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</integer>
-// CHECK-NEXT: <key>col</key><integer>8</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;_dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;_dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_inline_dispatch_once_reachable&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_inline_dispatch_once_reachable&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>1</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>50</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>58</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>242</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning to caller</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>59</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>2</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>63</integer>
-// CHECK-NEXT: <key>col</key><integer>17</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Returning from &apos;_dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;_dispatch_once&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>241</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>category</key><string>Logic error</string>
-// CHECK-NEXT: <key>type</key><string>Dereference of null pointer</string>
-// CHECK-NEXT: <key>check_name</key><string>core.NullDereference</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1e83bd4361a2351df0b4e77eb3a9109b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_inline_dispatch_once_reachable</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</integer>
-// CHECK-NEXT: <key>col</key><integer>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
diff --git a/test/Analysis/use-after-move.cpp b/test/Analysis/use-after-move.cpp
new file mode 100644
index 000000000000..280724512f8a
--- /dev/null
+++ b/test/Analysis/use-after-move.cpp
@@ -0,0 +1,1139 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
+// RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN: -analyzer-config exploration_strategy=unexplored_first_queue\
+// RUN: -analyzer-checker debug.ExprInspection
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
+// RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN: -analyzer-config exploration_strategy=dfs -DDFS=1\
+// RUN: -analyzer-checker debug.ExprInspection
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
+// RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN: -analyzer-config exploration_strategy=unexplored_first_queue\
+// RUN: -analyzer-config cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\
+// RUN: -analyzer-checker debug.ExprInspection
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
+// RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN: -analyzer-config exploration_strategy=dfs -DDFS=1\
+// RUN: -analyzer-config cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\
+// RUN: -analyzer-checker debug.ExprInspection
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
+// RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN: -analyzer-config exploration_strategy=unexplored_first_queue\
+// RUN: -analyzer-config cplusplus.Move:WarnOn=All -DAGGRESSIVE\
+// RUN: -analyzer-checker debug.ExprInspection
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
+// RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN: -analyzer-config exploration_strategy=dfs -DDFS=1\
+// RUN: -analyzer-config cplusplus.Move:WarnOn=All -DAGGRESSIVE\
+// RUN: -analyzer-checker debug.ExprInspection
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+void clang_analyzer_warnIfReached();
+
+class B {
+public:
+ B() = default;
+ B(const B &) = default;
+ B(B &&) = default;
+ B& operator=(const B &q) = default;
+ void operator=(B &&b) {
+ return;
+ }
+ void foo() { return; }
+};
+
+class A {
+ int i;
+ double d;
+
+public:
+ B b;
+ A(int ii = 42, double dd = 1.0) : d(dd), i(ii), b(B()) {}
+ void moveconstruct(A &&other) {
+ std::swap(b, other.b);
+ std::swap(d, other.d);
+ std::swap(i, other.i);
+ return;
+ }
+ static A get() {
+ A v(12, 13);
+ return v;
+ }
+ A(A *a) {
+ moveconstruct(std::move(*a));
+ }
+ A(const A &other) : i(other.i), d(other.d), b(other.b) {}
+ A(A &&other) : i(other.i), d(other.d), b(std::move(other.b)) {
+#ifdef AGGRESSIVE
+ // expected-note@-2{{Object 'b' is moved}}
+#endif
+ }
+ A(A &&other, char *k) {
+ moveconstruct(std::move(other));
+ }
+ void operator=(const A &other) {
+ i = other.i;
+ d = other.d;
+ b = other.b;
+ return;
+ }
+ void operator=(A &&other) {
+ moveconstruct(std::move(other));
+ return;
+ }
+ int getI() { return i; }
+ int foo() const;
+ void bar() const;
+ void reset();
+ void destroy();
+ void clear();
+ void resize(std::size_t);
+ bool empty() const;
+ bool isEmpty() const;
+ operator bool() const;
+
+ void testUpdateField() {
+ A a;
+ A b = std::move(a);
+ a.i = 1;
+ a.foo(); // no-warning
+ }
+ void testUpdateFieldDouble() {
+ A a;
+ A b = std::move(a);
+ a.d = 1.0;
+ a.foo(); // no-warning
+ }
+};
+
+int bignum();
+
+void moveInsideFunctionCall(A a) {
+ A b = std::move(a);
+}
+void leftRefCall(A &a) {
+ a.foo();
+}
+void rightRefCall(A &&a) {
+ a.foo();
+}
+void constCopyOrMoveCall(const A a) {
+ a.foo();
+}
+
+void copyOrMoveCall(A a) {
+ a.foo();
+}
+
+void simpleMoveCtorTest() {
+ {
+ A a;
+ A b = std::move(a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+ }
+ {
+ A a;
+ A b = std::move(a);
+ b = a;
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Moved-from object 'a' is copied}}
+ // expected-note@-4 {{Moved-from object 'a' is copied}}
+#endif
+ }
+ {
+ A a;
+ A b = std::move(a);
+ b = std::move(a);
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Moved-from object 'a' is moved}}
+ // expected-note@-4 {{Moved-from object 'a' is moved}}
+#endif
+ }
+}
+
+void simpleMoveAssignementTest() {
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ A c(a);
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Moved-from object 'a' is copied}}
+ // expected-note@-4 {{Moved-from object 'a' is copied}}
+#endif
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ A c(std::move(a));
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Moved-from object 'a' is moved}}
+ // expected-note@-4 {{Moved-from object 'a' is moved}}
+#endif
+ }
+}
+
+void moveInInitListTest() {
+ struct S {
+ A a;
+ };
+ A a;
+ S s{std::move(a)};
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+}
+
+// Don't report a bug if the variable was assigned to in the meantime.
+void reinitializationTest(int i) {
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ a = A();
+ a.foo();
+ }
+ {
+ A a;
+ if (i == 1) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Assuming 'i' is not equal to 1}}
+ // expected-note@-3 {{Taking false branch}}
+ // And the other report:
+ // expected-note@-5 {{Assuming 'i' is not equal to 1}}
+ // expected-note@-6 {{Taking false branch}}
+#endif
+ A b;
+ b = std::move(a);
+ a = A();
+ }
+ if (i == 2) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Assuming 'i' is not equal to 2}}
+ // expected-note@-3 {{Taking false branch}}
+ // And the other report:
+ // expected-note@-5 {{Assuming 'i' is not equal to 2}}
+ // expected-note@-6 {{Taking false branch}}
+#endif
+ a.foo(); // no-warning
+ }
+ }
+ {
+ A a;
+ if (i == 1) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Taking false branch}}
+ // expected-note@-3 {{Taking false branch}}
+#endif
+ std::move(a);
+ }
+ if (i == 2) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Taking false branch}}
+ // expected-note@-3 {{Taking false branch}}
+#endif
+ a = A();
+ a.foo();
+ }
+ }
+ // The built-in assignment operator should also be recognized as a
+ // reinitialization. (std::move() may be called on built-in types in template
+ // code.)
+ {
+ int a1 = 1, a2 = 2;
+ std::swap(a1, a2);
+ }
+ // A std::move() after the assignment makes the variable invalid again.
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ a = A();
+ b = std::move(a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+ }
+ // If a path exist where we not reinitialize the variable we report a bug.
+ {
+ A a;
+ A b;
+ b = std::move(a);
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+#endif
+ if (i < 10) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Assuming 'i' is >= 10}}
+ // expected-note@-3 {{Taking false branch}}
+#endif
+ a = A();
+ }
+ if (i > 5) {
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Taking true branch}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+ }
+ }
+}
+
+// Using decltype on an expression is not a use.
+void decltypeIsNotUseTest() {
+ A a;
+ // A b(std::move(a));
+ decltype(a) other_a; // no-warning
+}
+
+void loopTest() {
+ {
+ A a;
+ for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ rightRefCall(std::move(a)); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is true. Entering loop body}}
+ // expected-note@-3 {{Loop condition is true. Entering loop body}}
+ // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ rightRefCall(std::move(a)); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ leftRefCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is true. Entering loop body}}
+ // expected-note@-3 {{Loop condition is true. Entering loop body}}
+ // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ leftRefCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ constCopyOrMoveCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is true. Entering loop body}}
+ // expected-note@-3 {{Loop condition is true. Entering loop body}}
+ // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ constCopyOrMoveCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ moveInsideFunctionCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is true. Entering loop body}}
+ // expected-note@-3 {{Loop condition is true. Entering loop body}}
+ // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ moveInsideFunctionCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ copyOrMoveCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is true. Entering loop body}}
+ // expected-note@-3 {{Loop condition is true. Entering loop body}}
+ // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
+ copyOrMoveCall(a); // no-warning
+ }
+ }
+ {
+ A a;
+ for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Loop condition is true. Entering loop body}}
+ // expected-note@-3 {{Loop condition is true. Entering loop body}}
+#endif
+ constCopyOrMoveCall(std::move(a));
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Moved-from object 'a' is moved}}
+ // expected-note@-4 {{Moved-from object 'a' is moved}}
+#endif
+ }
+ }
+
+ // Don't warn if we return after the move.
+ {
+ A a;
+ for (int i = 0; i < 3; ++i) {
+ a.bar();
+ if (a.foo() > 0) {
+ A b;
+ b = std::move(a); // no-warning
+ return;
+ }
+ }
+ }
+}
+
+// Report a usage of a moved-from object only at the first use.
+void uniqueTest(bool cond) {
+ A a(42, 42.0);
+ A b;
+ b = std::move(a);
+
+ if (cond) {
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-5 {{Object 'a' is moved}}
+ // expected-note@-4 {{Assuming 'cond' is not equal to 0}}
+ // expected-note@-5 {{Taking true branch}}
+ // expected-warning@-5 {{Method called on moved-from object 'a'}}
+ // expected-note@-6 {{Method called on moved-from object 'a'}}
+#endif
+ }
+ if (cond) {
+ a.bar(); // no-warning
+ }
+
+ a.bar(); // no-warning
+}
+
+void uniqueTest2() {
+ A a;
+ A a1 = std::move(a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+
+ A a2 = std::move(a); // no-warning
+ a.foo(); // no-warning
+}
+
+// There are exceptions where we assume in general that the method works fine
+//even on moved-from objects.
+void moveSafeFunctionsTest() {
+ A a;
+ A b = std::move(a);
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+#endif
+ a.empty(); // no-warning
+ a.isEmpty(); // no-warning
+ (void)a; // no-warning
+ (bool)a; // expected-warning {{expression result unused}}
+ a.foo();
+#ifndef PEACEFUL
+ // expected-warning@-2 {{Method called on moved-from object 'a'}}
+ // expected-note@-3 {{Method called on moved-from object 'a'}}
+#endif
+}
+
+void moveStateResetFunctionsTest() {
+ {
+ A a;
+ A b = std::move(a);
+ a.reset(); // no-warning
+ a.foo(); // no-warning
+ // Test if resets the state of subregions as well.
+ a.b.foo(); // no-warning
+ }
+ {
+ A a;
+ A b = std::move(a);
+ a.destroy(); // no-warning
+ a.foo(); // no-warning
+ }
+ {
+ A a;
+ A b = std::move(a);
+ a.clear(); // no-warning
+ a.foo(); // no-warning
+ a.b.foo(); // no-warning
+ }
+ {
+ A a;
+ A b = std::move(a);
+ a.resize(0); // no-warning
+ a.foo(); // no-warning
+ a.b.foo(); // no-warning
+ }
+}
+
+// Moves or uses that occur as part of template arguments.
+template <int>
+class ClassTemplate {
+public:
+ void foo(A a);
+};
+
+template <int>
+void functionTemplate(A a);
+
+void templateArgIsNotUseTest() {
+ {
+ // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
+ // Google Test.
+ A a;
+ ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a)); // no-warning
+ }
+ {
+ A a;
+ functionTemplate<sizeof(A(std::move(a)))>(std::move(a)); // no-warning
+ }
+}
+
+// Moves of global variables are not reported.
+A global_a;
+void globalVariablesTest() {
+ std::move(global_a);
+ global_a.foo(); // no-warning
+}
+
+// Moves of member variables.
+class memberVariablesTest {
+ A a;
+ static A static_a;
+
+ void f() {
+ A b;
+ b = std::move(a);
+ a.foo();
+#ifdef AGGRESSIVE
+ // expected-note@-3{{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4{{Method called on moved-from object 'a'}}
+#endif
+
+ b = std::move(static_a);
+ static_a.foo();
+#ifdef AGGRESSIVE
+ // expected-note@-3{{Object 'static_a' is moved}}
+ // expected-warning@-3{{Method called on moved-from object 'static_a'}}
+ // expected-note@-4{{Method called on moved-from object 'static_a'}}
+#endif
+ }
+};
+
+void PtrAndArrayTest() {
+ A *Ptr = new A(1, 1.5);
+ A Arr[10];
+ Arr[2] = std::move(*Ptr);
+ (*Ptr).foo();
+#ifdef AGGRESSIVE
+ // expected-note@-3{{Object is moved}}
+ // expected-warning@-3{{Method called on moved-from object}}
+ // expected-note@-4{{Method called on moved-from object}}
+#endif
+
+ Ptr = &Arr[1];
+ Arr[3] = std::move(Arr[1]);
+ Ptr->foo();
+#ifdef AGGRESSIVE
+ // expected-note@-3{{Object is moved}}
+ // expected-warning@-3{{Method called on moved-from object}}
+ // expected-note@-4{{Method called on moved-from object}}
+#endif
+
+ Arr[3] = std::move(Arr[2]);
+ Arr[2].foo();
+#ifdef AGGRESSIVE
+ // expected-note@-3{{Object is moved}}
+ // expected-warning@-3{{Method called on moved-from object}}
+ // expected-note@-4{{Method called on moved-from object}}
+#endif
+
+ Arr[2] = std::move(Arr[3]); // reinitialization
+ Arr[2].foo(); // no-warning
+}
+
+void exclusiveConditionsTest(bool cond) {
+ A a;
+ if (cond) {
+ A b;
+ b = std::move(a);
+ }
+ if (!cond) {
+ a.bar(); // no-warning
+ }
+}
+
+void differentBranchesTest(int i) {
+ // Don't warn if the use is in a different branch from the move.
+ {
+ A a;
+ if (i > 0) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Assuming 'i' is > 0}}
+ // expected-note@-3 {{Taking true branch}}
+#endif
+ A b;
+ b = std::move(a);
+ } else {
+ a.foo(); // no-warning
+ }
+ }
+ // Same thing, but with a ternary operator.
+ {
+ A a, b;
+ i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning
+#ifndef PEACEFUL
+ // expected-note@-2 {{'?' condition is true}}
+#endif
+ }
+ // A variation on the theme above.
+ {
+ A a;
+ a.foo() > 0 ? a.foo() : A(std::move(a)).foo();
+#ifdef DFS
+ #ifndef PEACEFUL
+ // expected-note@-3 {{Assuming the condition is false}}
+ // expected-note@-4 {{'?' condition is false}}
+ #endif
+#else
+ #ifndef PEACEFUL
+ // expected-note@-8 {{Assuming the condition is true}}
+ // expected-note@-9 {{'?' condition is true}}
+ #endif
+#endif
+ }
+ // Same thing, but with a switch statement.
+ {
+ A a, b;
+ switch (i) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Control jumps to 'case 1:'}}
+#endif
+ case 1:
+ b = std::move(a); // no-warning
+ break;
+#ifndef PEACEFUL
+ // expected-note@-2 {{Execution jumps to the end of the function}}
+#endif
+ case 2:
+ a.foo(); // no-warning
+ break;
+ }
+ }
+ // However, if there's a fallthrough, we do warn.
+ {
+ A a, b;
+ switch (i) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Control jumps to 'case 1:'}}
+#endif
+ case 1:
+ b = std::move(a);
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+#endif
+ case 2:
+ a.foo();
+#ifndef PEACEFUL
+ // expected-warning@-2 {{Method called on moved-from object}}
+ // expected-note@-3 {{Method called on moved-from object 'a'}}
+#endif
+ break;
+ }
+ }
+}
+
+void tempTest() {
+ A a = A::get();
+ A::get().foo(); // no-warning
+ for (int i = 0; i < bignum(); i++) {
+ A::get().foo(); // no-warning
+ }
+}
+
+void interFunTest1(A &a) {
+ a.bar();
+#ifndef PEACEFUL
+ // expected-warning@-2 {{Method called on moved-from object 'a'}}
+ // expected-note@-3 {{Method called on moved-from object 'a'}}
+#endif
+}
+
+void interFunTest2() {
+ A a;
+ A b;
+ b = std::move(a);
+ interFunTest1(a);
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-note@-3 {{Calling 'interFunTest1'}}
+#endif
+}
+
+void foobar(A a, int i);
+void foobar(int i, A a);
+
+void paramEvaluateOrderTest() {
+ A a;
+ foobar(std::move(a), a.getI());
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+
+ //FALSE NEGATIVE since parameters evaluate order is undefined
+ foobar(a.getI(), std::move(a)); //no-warning
+}
+
+void not_known_pass_by_ref(A &a);
+void not_known_pass_by_const_ref(const A &a);
+void not_known_pass_by_rvalue_ref(A &&a);
+void not_known_pass_by_ptr(A *a);
+void not_known_pass_by_const_ptr(const A *a);
+
+void regionAndPointerEscapeTest() {
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ not_known_pass_by_ref(a);
+ a.foo(); // no-warning
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ not_known_pass_by_const_ref(a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-4{{Object 'a' is moved}}
+ // expected-warning@-3{{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ not_known_pass_by_rvalue_ref(std::move(a));
+ a.foo(); // no-warning
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ not_known_pass_by_ptr(&a);
+ a.foo(); // no-warning
+ }
+ {
+ A a;
+ A b;
+ b = std::move(a);
+ not_known_pass_by_const_ptr(&a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-4{{Object 'a' is moved}}
+ // expected-warning@-3{{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+ }
+}
+
+// A declaration statement containing multiple declarations sequences the
+// initializer expressions.
+void declarationSequenceTest() {
+ {
+ A a;
+ A a1 = a, a2 = std::move(a); // no-warning
+ }
+ {
+ A a;
+ A a1 = std::move(a), a2 = a;
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Moved-from object 'a' is copied}}
+ // expected-note@-4 {{Moved-from object 'a' is copied}}
+#endif
+ }
+}
+
+// The logical operators && and || sequence their operands.
+void logicalOperatorsSequenceTest() {
+ {
+ A a;
+ if (a.foo() > 0 && A(std::move(a)).foo() > 0) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Assuming the condition is false}}
+ // expected-note@-3 {{Left side of '&&' is false}}
+ // expected-note@-4 {{Taking false branch}}
+ // And the other report:
+ // expected-note@-6 {{Assuming the condition is false}}
+ // expected-note@-7 {{Left side of '&&' is false}}
+ // expected-note@-8 {{Taking false branch}}
+ A().bar();
+#endif
+ }
+ }
+ // A variation: Negate the result of the && (which pushes the && further down
+ // into the AST).
+ {
+ A a;
+ if (!(a.foo() > 0 && A(std::move(a)).foo() > 0)) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Assuming the condition is false}}
+ // expected-note@-3 {{Left side of '&&' is false}}
+ // expected-note@-4 {{Taking true branch}}
+ // And the other report:
+ // expected-note@-6 {{Assuming the condition is false}}
+ // expected-note@-7 {{Left side of '&&' is false}}
+ // expected-note@-8 {{Taking true branch}}
+#endif
+ A().bar();
+ }
+ }
+ {
+ A a;
+ if (A(std::move(a)).foo() > 0 && a.foo() > 0) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+ // expected-note@-3 {{Assuming the condition is true}}
+ // expected-note@-4 {{Left side of '&&' is true}}
+ // expected-warning@-5 {{Method called on moved-from object 'a'}}
+ // expected-note@-6 {{Method called on moved-from object 'a'}}
+ // And the other report:
+ // expected-note@-8 {{Assuming the condition is false}}
+ // expected-note@-9 {{Left side of '&&' is false}}
+ // expected-note@-10{{Taking false branch}}
+#endif
+ A().bar();
+ }
+ }
+ {
+ A a;
+ if (a.foo() > 0 || A(std::move(a)).foo() > 0) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Assuming the condition is true}}
+ // expected-note@-3 {{Left side of '||' is true}}
+ // expected-note@-4 {{Taking true branch}}
+#endif
+ A().bar();
+ }
+ }
+ {
+ A a;
+ if (A(std::move(a)).foo() > 0 || a.foo() > 0) {
+#ifndef PEACEFUL
+ // expected-note@-2 {{Object 'a' is moved}}
+ // expected-note@-3 {{Assuming the condition is false}}
+ // expected-note@-4 {{Left side of '||' is false}}
+ // expected-warning@-5 {{Method called on moved-from object 'a'}}
+ // expected-note@-6 {{Method called on moved-from object 'a'}}
+#endif
+ A().bar();
+ }
+ }
+}
+
+// A range-based for sequences the loop variable declaration before the body.
+void forRangeSequencesTest() {
+ A v[2] = {A(), A()};
+ for (A &a : v) {
+ A b;
+ b = std::move(a); // no-warning
+ }
+}
+
+// If a variable is declared in an if statement, the declaration of the variable
+// (which is treated like a reinitialization by the check) is sequenced before
+// the evaluation of the condition (which constitutes a use).
+void ifStmtSequencesDeclAndConditionTest() {
+ for (int i = 0; i < 3; ++i) {
+ if (A a = A()) {
+ A b;
+ b = std::move(a); // no-warning
+ }
+ }
+}
+
+struct C : public A {
+ [[clang::reinitializes]] void reinit();
+};
+
+void subRegionMoveTest() {
+ {
+ A a;
+ B b = std::move(a.b);
+ a.b.foo();
+#ifdef AGGRESSIVE
+ // expected-note@-3{{Object 'b' is moved}}
+ // expected-warning@-3{{Method called on moved-from object 'b'}}
+ // expected-note@-4 {{Method called on moved-from object 'b'}}
+#endif
+ }
+ {
+ A a;
+ A a1 = std::move(a);
+ a.b.foo();
+#ifdef AGGRESSIVE
+ // expected-note@-3{{Calling move constructor for 'A'}}
+ // expected-note@-4{{Returning from move constructor for 'A'}}
+ // expected-warning@-4{{Method called on moved-from object 'b'}}
+ // expected-note@-5{{Method called on moved-from object 'b'}}
+#endif
+ }
+ // Don't report a misuse if any SuperRegion is already reported.
+ {
+ A a;
+ A a1 = std::move(a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+ a.b.foo(); // no-warning
+ }
+ {
+ C c;
+ C c1 = std::move(c);
+ c.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'c' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'c'}}
+ // expected-note@-4 {{Method called on moved-from object 'c'}}
+#endif
+ c.b.foo(); // no-warning
+ }
+}
+
+void resetSuperClass() {
+ C c;
+ C c1 = std::move(c);
+ c.clear();
+ C c2 = c; // no-warning
+}
+
+void resetSuperClass2() {
+ C c;
+ C c1 = std::move(c);
+ c.reinit();
+ C c2 = c; // no-warning
+}
+
+void reportSuperClass() {
+ C c;
+ C c1 = std::move(c);
+ c.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'c' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'c'}}
+ // expected-note@-4 {{Method called on moved-from object 'c'}}
+#endif
+ C c2 = c; // no-warning
+}
+
+struct Empty {};
+
+Empty inlinedCall() {
+ // Used to warn because region 'e' failed to be cleaned up because no symbols
+ // have ever died during the analysis and the checkDeadSymbols callback
+ // was skipped entirely.
+ Empty e{};
+ return e; // no-warning
+}
+
+void checkInlinedCallZombies() {
+ while (true)
+ inlinedCall();
+}
+
+void checkLoopZombies() {
+ while (true) {
+ Empty e{};
+ Empty f = std::move(e); // no-warning
+ }
+}
+
+void checkMoreLoopZombies1(bool flag) {
+ while (flag) {
+ Empty e{};
+ if (true)
+ e; // expected-warning {{expression result unused}}
+ Empty f = std::move(e); // no-warning
+ }
+}
+
+bool coin();
+
+void checkMoreLoopZombies2(bool flag) {
+ while (flag) {
+ Empty e{};
+ while (coin())
+ e; // expected-warning {{expression result unused}}
+ Empty f = std::move(e); // no-warning
+ }
+}
+
+void checkMoreLoopZombies3(bool flag) {
+ while (flag) {
+ Empty e{};
+ do
+ e; // expected-warning {{expression result unused}}
+ while (coin());
+ Empty f = std::move(e); // no-warning
+ }
+}
+
+void checkMoreLoopZombies4(bool flag) {
+ while (flag) {
+ Empty e{};
+ for (; coin();)
+ e; // expected-warning {{expression result unused}}
+ Empty f = std::move(e); // no-warning
+ }
+}
+
+struct MoveOnlyWithDestructor {
+ MoveOnlyWithDestructor();
+ ~MoveOnlyWithDestructor();
+ MoveOnlyWithDestructor(const MoveOnlyWithDestructor &m) = delete;
+ MoveOnlyWithDestructor(MoveOnlyWithDestructor &&m);
+};
+
+MoveOnlyWithDestructor foo() {
+ MoveOnlyWithDestructor m;
+ return m;
+}
+
+class HasSTLField {
+ std::vector<int> V;
+ void testVector() {
+ // Warn even in non-aggressive mode when it comes to STL, because
+ // in STL the object is left in "valid but unspecified state" after move.
+ std::vector<int> W = std::move(V); // expected-note{{Object 'V' of type 'std::vector' is left in a valid but unspecified state after move}}
+ V.push_back(123); // expected-warning{{Method called on moved-from object 'V'}}
+ // expected-note@-1{{Method called on moved-from object 'V'}}
+ }
+
+ std::unique_ptr<int> P;
+ void testUniquePtr() {
+ // unique_ptr remains in a well-defined state after move.
+ std::unique_ptr<int> Q = std::move(P);
+ P.get();
+#ifdef AGGRESSIVE
+ // expected-warning@-2{{Method called on moved-from object 'P'}}
+ // expected-note@-4{{Object 'P' is moved}}
+ // expected-note@-4{{Method called on moved-from object 'P'}}
+#endif
+
+ // Because that well-defined state is null, dereference is still UB.
+ // Note that in aggressive mode we already warned about 'P',
+ // so no extra warning is generated.
+ *P += 1;
+#ifndef AGGRESSIVE
+ // expected-warning@-2{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
+ // expected-note@-14{{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}}
+ // expected-note@-4{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
+#endif
+
+ // The program should have crashed by now.
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+};
+
+void localRValueMove(A &&a) {
+ A b = std::move(a);
+ a.foo();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'a' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'a'}}
+ // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
+}
+
+void localUniquePtr(std::unique_ptr<int> P) {
+ // Even though unique_ptr is safe to use after move,
+ // reusing a local variable this way usually indicates a bug.
+ std::unique_ptr<int> Q = std::move(P);
+ P.get();
+#ifndef PEACEFUL
+ // expected-note@-3 {{Object 'P' is moved}}
+ // expected-warning@-3 {{Method called on moved-from object 'P'}}
+ // expected-note@-4 {{Method called on moved-from object 'P'}}
+#endif
+}
+
+void localUniquePtrWithArrow(std::unique_ptr<A> P) {
+ std::unique_ptr<A> Q = std::move(P); // expected-note{{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}}
+ P->foo(); // expected-warning{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
+ // expected-note@-1{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
+}
diff --git a/test/Analysis/weak-functions.c b/test/Analysis/weak-functions.c
index 514a94388722..b3d8b043f8df 100644
--- a/test/Analysis/weak-functions.c
+++ b/test/Analysis/weak-functions.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection,unix.Malloc,unix.cstring,alpha.unix.cstring,unix.API,osx.API,osx.cocoa.RetainCount -Wno-null-dereference -Wno-tautological-compare -analyzer-store=region -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection,unix.Malloc,unix.cstring,alpha.unix.cstring,unix.API,osx.API,osx.cocoa.RetainCount -Wno-null-dereference -Wno-tautological-compare -analyzer-store=region -fblocks -verify -analyzer-config eagerly-assume=false %s
#define NULL 0
void clang_analyzer_eval(int);
void myFunc();
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 4951d8669806..7d9dc429a41b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -61,7 +61,7 @@ list(APPEND CLANG_TEST_DEPS
if(CLANG_ENABLE_STATIC_ANALYZER)
list(APPEND CLANG_TEST_DEPS
clang-check
- clang-func-mapping
+ clang-extdef-mapping
)
endif()
@@ -88,8 +88,15 @@ endif ()
set(CLANG_TEST_PARAMS
clang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ USE_Z3_SOLVER=0
)
+set(ANALYZER_TEST_PARAMS
+ USE_Z3_SOLVER=0)
+
+set(ANALYZER_TEST_PARAMS_Z3
+ USE_Z3_SOLVER=1)
+
if( NOT CLANG_BUILT_STANDALONE )
list(APPEND CLANG_TEST_DEPS
llvm-config
@@ -126,6 +133,28 @@ add_lit_testsuite(check-clang "Running the Clang regression tests"
)
set_target_properties(check-clang PROPERTIES FOLDER "Clang tests")
+if (CLANG_ENABLE_STATIC_ANALYZER)
+ # check-all would launch those tests via check-clang.
+ set(EXCLUDE_FROM_ALL ON)
+
+ add_lit_testsuite(check-clang-analyzer "Running the Clang analyzer tests"
+ ${CMAKE_CURRENT_BINARY_DIR}/Analysis
+ PARAMS ${ANALYZER_TEST_PARAMS}
+ DEPENDS ${CLANG_TEST_DEPS})
+ set_target_properties(check-clang-analyzer PROPERTIES FOLDER "Clang tests")
+
+
+ if (CLANG_ANALYZER_WITH_Z3)
+ add_lit_testsuite(check-clang-analyzer-z3 "Running the Clang analyzer tests, using Z3 as a solver"
+ ${CMAKE_CURRENT_BINARY_DIR}/Analysis
+ PARAMS ${ANALYZER_TEST_PARAMS_Z3}
+ DEPENDS ${CLANG_TEST_DEPS})
+ set_target_properties(check-clang-analyzer-z3 PROPERTIES FOLDER "Clang tests")
+ endif()
+
+ set(EXCLUDE_FROM_ALL OFF)
+endif()
+
add_lit_testsuites(CLANG ${CMAKE_CURRENT_SOURCE_DIR}
PARAMS ${CLANG_TEST_PARAMS}
DEPENDS ${CLANG_TEST_DEPS}
diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp
index b6a1bcdab926..b335b0a8c884 100644
--- a/test/CXX/class.access/class.friend/p1.cpp
+++ b/test/CXX/class.access/class.friend/p1.cpp
@@ -11,12 +11,11 @@
// friends members of the befriending class.
struct S { static void f(); }; // expected-note 2 {{'S' declared here}}
-S* g() { return 0; }
+S* g() { return 0; } // expected-note 2 {{'g' declared here}}
struct X {
friend struct S;
- friend S* g(); // expected-note 2 {{'g' declared here}}
- // FIXME: The above two notes would be better attached to line 11.
+ friend S* g();
};
void test1() {
diff --git a/test/CXX/class.access/class.friend/p11.cpp b/test/CXX/class.access/class.friend/p11.cpp
index 0d25c59c9b62..0deead19a0fb 100644
--- a/test/CXX/class.access/class.friend/p11.cpp
+++ b/test/CXX/class.access/class.friend/p11.cpp
@@ -19,17 +19,16 @@ namespace test1 {
}
namespace test2 {
- void bar(); // expected-note {{'::test2::bar' declared here}}
+ void bar(); // expected-note 3{{'::test2::bar' declared here}}
- void foo() { // expected-note {{'::test2::foo' declared here}}
+ void foo() { // expected-note 2{{'::test2::foo' declared here}}
struct S1 {
friend void foo(); // expected-error {{no matching function 'foo' found in local scope; did you mean '::test2::foo'?}}
};
void foo(); // expected-note {{local declaration nearly matches}}
struct S2 {
- friend void foo(); // expected-note{{'::test2::foo' declared here}}
- // TODO: the above note should go on line 24
+ friend void foo();
};
{
@@ -47,8 +46,6 @@ namespace test2 {
struct S4 {
friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}}
- // expected-note@-1 {{'::test2::bar' declared here}}
- // TODO: the above note should go on line 22
};
{ void bar(); }
@@ -81,8 +78,6 @@ namespace test2 {
struct S9 {
struct Inner {
friend void baz(); // expected-error {{no matching function 'baz' found in local scope; did you mean 'bar'?}}
- // expected-note@-1 {{'::test2::bar' declared here}}
- // TODO: the above note should go on line 22
};
};
diff --git a/test/CXX/class.access/class.friend/p3-cxx0x.cpp b/test/CXX/class.access/class.friend/p3-cxx0x.cpp
index 5a1ab49321d0..9aabdbe540a6 100644
--- a/test/CXX/class.access/class.friend/p3-cxx0x.cpp
+++ b/test/CXX/class.access/class.friend/p3-cxx0x.cpp
@@ -52,14 +52,25 @@ struct {
// Ill-formed
int friend; // expected-error {{'friend' must appear first in a non-function declaration}}
unsigned friend int; // expected-error {{'friend' must appear first in a non-function declaration}}
- const volatile friend int; // expected-error {{'friend' must appear first in a non-function declaration}}
+ const volatile friend int; // expected-error {{'friend' must appear first in a non-function declaration}} \
+ // expected-error {{'const' is invalid in friend declarations}} \
+ // expected-error {{'volatile' is invalid in friend declarations}}
int
friend; // expected-error {{'friend' must appear first in a non-function declaration}}
+ friend const int; // expected-error {{'const' is invalid in friend declarations}}
+ friend volatile int; // expected-error {{'volatile' is invalid in friend declarations}}
+ template <typename T> friend const class X; // expected-error {{'const' is invalid in friend declarations}}
+ // C++ doesn't have restrict and _Atomic, but they're both the same sort
+ // of qualifier.
+ typedef int *PtrToInt;
+ friend __restrict PtrToInt; // expected-error {{'restrict' is invalid in friend declarations}} \
+ // expected-error {{restrict requires a pointer or reference}}
+ friend _Atomic int; // expected-error {{'_Atomic' is invalid in friend declarations}}
// OK
int friend foo(void);
+ const int friend foo2(void);
friend int;
- friend const volatile int;
friend
float;
diff --git a/test/CXX/class.derived/class.abstract/p16.cpp b/test/CXX/class.derived/class.abstract/p16.cpp
index 80396a96d9ec..fe31b7321bd0 100644
--- a/test/CXX/class.derived/class.abstract/p16.cpp
+++ b/test/CXX/class.derived/class.abstract/p16.cpp
@@ -44,8 +44,8 @@ struct G : D {};
// expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}}
// expected-note@-4 {{while declaring the implicit move assignment operator for 'G'}}
// expected-note@-5 {{move assignment operator of 'G' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}}
-struct H : D {
- H &operator=(H&&) = default;
+struct H : D { // expected-note {{deleted because base class 'D' has an inaccessible move assignment}}
+ H &operator=(H&&) = default; // expected-warning {{implicitly deleted}}
// expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}}
// expected-note@-3 {{move assignment operator of 'H' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}}
~H();
diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp
index 037fc3dadb96..08498c07330e 100644
--- a/test/CXX/class/class.friend/p1.cpp
+++ b/test/CXX/class/class.friend/p1.cpp
@@ -51,9 +51,9 @@ class A {
friend class A::AInner; // this is okay as an extension
friend class AInner; // okay, refers to ::AInner
- friend void Derived::missing_member(); // expected-error {{no function named 'missing_member' with type 'void ()' was found in the specified scope}}
+ friend void Derived::missing_member(); // expected-error {{friend declaration of 'missing_member' does not match any declaration in 'Derived'}}
- friend void Derived::base_member(); // expected-error {{no function named 'base_member' with type 'void ()' was found in the specified scope}}
+ friend void Derived::base_member(); // expected-error {{friend declaration of 'base_member' does not match any declaration in 'Derived'}}
friend int Base::typedeffed_member(); // okay: should look through typedef
diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
index 49c418a68764..43de9343bd4d 100644
--- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
+++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
@@ -32,6 +32,35 @@ void g() {
// OK, warning suppressed.
(void)fp();
}
+
+namespace PR31526 {
+typedef E (*fp1)();
+typedef S (*fp2)();
+
+typedef S S_alias;
+typedef S_alias (*fp3)();
+
+typedef fp2 fp2_alias;
+
+void f() {
+ fp1 one;
+ fp2 two;
+ fp3 three;
+ fp2_alias four;
+
+ one(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ two(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ three(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ four(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ // These are all okay because of the explicit cast to void.
+ (void)one();
+ (void)two();
+ (void)three();
+ (void)four();
+}
+} // namespace PR31526
+
#ifdef EXT
// expected-warning@4 {{use of the 'nodiscard' attribute is a C++17 extension}}
// expected-warning@8 {{use of the 'nodiscard' attribute is a C++17 extension}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
index 3986dc9565c3..ffc408cddbf4 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s
namespace N {
typedef char C;
@@ -78,7 +79,12 @@ struct T2 {
};
struct T3 {
constexpr T3 &operator=(const T3&) const = default;
- // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#ifndef CXX2A
+ // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+#else
+ // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}}
+ // expected-note@-5 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}}
+#endif
};
#endif
struct U {
@@ -129,9 +135,22 @@ constexpr int DisallowedStmtsCXX1Y_2() {
x:
return 0;
}
+constexpr int DisallowedStmtsCXX1Y_2_1() {
+ try {
+ return 0;
+ } catch (...) {
+ merp: goto merp; // expected-error {{statement not allowed in constexpr function}}
+ }
+}
constexpr int DisallowedStmtsCXX1Y_3() {
// - a try-block,
- try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}}
+ try {} catch (...) {}
+#ifndef CXX2A
+ // expected-error@-2 {{use of this statement in a constexpr function is a C++2a extension}}
+#ifndef CXX1Y
+ // expected-error@-4 {{use of this statement in a constexpr function is a C++14 extension}}
+#endif
+#endif
return 0;
}
constexpr int DisallowedStmtsCXX1Y_4() {
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
index 9c1cab54b617..54aabe6ef376 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s
-// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s
+// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y -Werror=c++2a-extensions %s
+// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s
namespace N {
typedef char C;
@@ -49,8 +50,14 @@ namespace IndirectVBase {
// - its function-body shall not be a function-try-block;
struct U {
constexpr U()
- try // expected-error {{function try block not allowed in constexpr constructor}}
+ try
+#ifndef CXX2A
+ // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
: u() {
+#ifndef CXX1Y
+ // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
} catch (...) {
throw;
}
diff --git a/test/CXX/dcl.decl/dcl.decomp/p3.cpp b/test/CXX/dcl.decl/dcl.decomp/p3.cpp
index b7092e3af023..b3f0cf187446 100644
--- a/test/CXX/dcl.decl/dcl.decomp/p3.cpp
+++ b/test/CXX/dcl.decl/dcl.decomp/p3.cpp
@@ -36,7 +36,7 @@ void no_get_2() {
auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}
}
-template<int> float &get(A);
+template<int> float &get(A); // expected-note 2 {{no known conversion}}
void no_tuple_element_1() {
auto [a0, a1, a2] = A(); // expected-error-re {{'std::tuple_element<0U{{L*}}, A>::type' does not name a type}} expected-note {{in implicit}}
@@ -57,7 +57,7 @@ void no_tuple_element_3() {
template<> struct std::tuple_element<1, A> { typedef float &type; };
template<> struct std::tuple_element<2, A> { typedef const float &type; };
-template<int N> auto get(B) -> int (&)[N + 1];
+template<int N> auto get(B) -> int (&)[N + 1]; // expected-note 2 {{no known conversion}}
template<int N> struct std::tuple_element<N, B> { typedef int type[N +1 ]; };
template<typename T> struct std::tuple_size<const T> : std::tuple_size<T> {};
@@ -138,19 +138,25 @@ int member_get() {
return c;
}
-struct D { template<int> struct get {}; }; // expected-note {{declared here}}
+struct D {
+ // FIXME: Emit a note here explaining why this was ignored.
+ template<int> struct get {};
+};
template<> struct std::tuple_size<D> { static const int value = 1; };
template<> struct std::tuple_element<0, D> { typedef D::get<0> type; };
void member_get_class_template() {
- auto [d] = D(); // expected-error {{cannot refer to member 'get' in 'D' with '.'}} expected-note {{in implicit init}}
+ auto [d] = D(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}
}
-struct E { int get(); };
+struct E {
+ // FIXME: Emit a note here explaining why this was ignored.
+ int get();
+};
template<> struct std::tuple_size<E> { static const int value = 1; };
template<> struct std::tuple_element<0, E> { typedef int type; };
void member_get_non_template() {
// FIXME: This diagnostic is not very good.
- auto [e] = E(); // expected-error {{no member named 'get'}} expected-note {{in implicit init}}
+ auto [e] = E(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}
}
namespace ADL {
@@ -230,3 +236,62 @@ namespace constant {
}
static_assert(g() == 4); // expected-error {{constant}} expected-note {{in call to 'g()'}}
}
+
+// P0961R1
+struct InvalidMemberGet {
+ int get();
+ template <class T> int get();
+ struct get {};
+};
+template <> struct std::tuple_size<InvalidMemberGet> { static constexpr size_t value = 1; };
+template <> struct std::tuple_element<0, InvalidMemberGet> { typedef float type; };
+template <size_t> float get(InvalidMemberGet) { return 0; }
+int f() {
+ InvalidMemberGet img;
+ auto [x] = img;
+ typedef decltype(x) same_as_float;
+ typedef float same_as_float;
+}
+
+struct ValidMemberGet {
+ int get();
+ template <class T> int get() { return 0; }
+ template <size_t N> float get() { return 0; }
+};
+template <> struct std::tuple_size<ValidMemberGet> { static constexpr size_t value = 1; };
+template <> struct std::tuple_element<0, ValidMemberGet> { typedef float type; };
+// Don't use this one; we should use the member get.
+template <size_t N> int get(ValidMemberGet) { static_assert(N && false, ""); }
+int f2() {
+ ValidMemberGet img;
+ auto [x] = img;
+ typedef decltype(x) same_as_float;
+ typedef float same_as_float;
+}
+
+struct Base1 {
+ int get(); // expected-note{{member found by ambiguous name lookup}}
+};
+struct Base2 {
+ template<int> int get(); // expected-note{{member found by ambiguous name lookup}}
+};
+struct Derived : Base1, Base2 {};
+
+template <> struct std::tuple_size<Derived> { static constexpr size_t value = 1; };
+template <> struct std::tuple_element<0, Derived> { typedef int type; };
+
+auto [x] = Derived(); // expected-error{{member 'get' found in multiple base classes of different types}}
+
+struct Base {
+ template<int> int get();
+};
+struct UsingGet : Base {
+ using Base::get;
+};
+
+template <> struct std::tuple_size<UsingGet> {
+ static constexpr size_t value = 1;
+};
+template <> struct std::tuple_element<0, UsingGet> { typedef int type; };
+
+auto [y] = UsingGet();
diff --git a/test/CXX/dcl.decl/dcl.decomp/p4.cpp b/test/CXX/dcl.decl/dcl.decomp/p4.cpp
index c461eb6f54b7..f14c0d02c16e 100644
--- a/test/CXX/dcl.decl/dcl.decomp/p4.cpp
+++ b/test/CXX/dcl.decl/dcl.decomp/p4.cpp
@@ -20,15 +20,15 @@ namespace NonPublicMembers {
int a; // expected-note 2{{declared private here}}
};
- struct NonPublic3 : private A {}; // expected-note {{constrained by private inheritance}}
+ struct NonPublic3 : private A {}; // expected-note {{declared private here}}
struct NonPublic4 : NonPublic2 {};
void test() {
- auto [a1] = NonPublic1(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic1'}}
- auto [a2] = NonPublic2(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic2'}}
- auto [a3] = NonPublic3(); // expected-error {{cannot decompose members of non-public base class 'A' of 'NonPublic3'}}
- auto [a4] = NonPublic4(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic4'}}
+ auto [a1] = NonPublic1(); // expected-error {{cannot decompose protected member 'a' of 'NonPublicMembers::NonPublic1'}}
+ auto [a2] = NonPublic2(); // expected-error {{cannot decompose private member 'a' of 'NonPublicMembers::NonPublic2'}}
+ auto [a3] = NonPublic3(); // expected-error {{cannot decompose members of inaccessible base class 'A' of 'NonPublicMembers::NonPublic3'}}
+ auto [a4] = NonPublic4(); // expected-error {{cannot decompose private member 'a' of 'NonPublicMembers::NonPublic2'}}
}
}
@@ -198,3 +198,44 @@ namespace std_example {
same<decltype((x)), const int&> same1;
same<decltype((y)), const volatile double&> same2;
}
+
+namespace p0969r0 {
+ struct A {
+ int x;
+ int y;
+ };
+ struct B : private A { // expected-note {{declared private here}}
+ void test_member() {
+ auto &[x, y] = *this;
+ }
+ friend void test_friend(B);
+ };
+ void test_friend(B b) {
+ auto &[x, y] = b;
+ }
+ void test_external(B b) {
+ auto &[x, y] = b; // expected-error {{cannot decompose members of inaccessible base class 'p0969r0::A' of 'p0969r0::B'}}
+ }
+
+ struct C {
+ int x;
+ protected:
+ int y; // expected-note {{declared protected here}} expected-note {{can only access this member on an object of type 'p0969r0::D'}}
+ void test_member() {
+ auto &[x, y] = *this;
+ }
+ friend void test_friend(struct D);
+ };
+ struct D : C {
+ static void test_member(D d, C c) {
+ auto &[x1, y1] = d;
+ auto &[x2, y2] = c; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}}
+ }
+ };
+ void test_friend(D d) {
+ auto &[x, y] = d;
+ }
+ void test_external(D d) {
+ auto &[x, y] = d; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}}
+ }
+}
diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp
index 51993307cfff..3f2bc569edf6 100644
--- a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp
+++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp
@@ -1,15 +1,30 @@
// RUN: %clang_cc1 -verify %s -std=c++11
+// RUN: %clang_cc1 -verify %s -std=c++17
+// RUN: %clang_cc1 -verify %s -std=c++2a
// A function that is explicitly defaulted shall
struct A {
// -- be a special member function,
A(int) = default; // expected-error {{only special member functions may be defaulted}}
+ A(A) = default; // expected-error {{must pass its first argument by reference}}
// -- have the same declared function type as if it had been implicitly
// declared
void operator=(const A &) = default; // expected-error {{must return 'A &'}}
- A(...) = default; // expected-error {{cannot be variadic}}
- A(const A &, ...) = default; // expected-error {{cannot be variadic}}
+ A(...) = default;
+ A(const A &, ...) = default;
+ A &operator=(const A&) const = default;
+ A &operator=(A) const = default; // expected-error {{must be an lvalue refe}}
+#if __cplusplus <= 201703L
+ // expected-error@-5 {{cannot be variadic}}
+ // expected-error@-5 {{cannot be variadic}}
+ // expected-error@-5 {{may not have 'const'}}
+ // expected-error@-5 {{may not have 'const'}}
+#else
+ // expected-warning@-10 {{implicitly deleted}} expected-note@-10 {{declared type does not match the type of an implicit default constructor}}
+ // expected-warning@-10 {{implicitly deleted}} expected-note@-10 {{declared type does not match the type of an implicit copy constructor}}
+ // expected-warning@-10 {{implicitly deleted}} expected-note@-10 {{declared type does not match the type of an implicit copy assignment}}
+#endif
// (except for possibly differing ref-qualifiers
A &operator=(A &&) & = default;
@@ -23,3 +38,35 @@ struct A {
A(double = 0.0) = default; // expected-error {{cannot have default arguments}}
A(const A & = 0) = default; // expected-error {{cannot have default arguments}}
};
+
+struct A2 {
+ A2(...);
+ A2(const A2 &, ...);
+ A2 &operator=(const A2&) const;
+};
+A2::A2(...) = default; // expected-error {{cannot be variadic}}
+A2::A2(const A2&, ...) = default; // expected-error {{cannot be variadic}}
+A2 &A2::operator=(const A2&) const = default; // expected-error {{may not have 'const'}}
+
+struct B {
+ B(B&);
+ B &operator=(B&);
+};
+struct C : B {
+ C(const C&) = default;
+ C &operator=(const C&) = default;
+#if __cplusplus <= 201703L
+ // expected-error@-3 {{is const, but a member or base requires it to be non-const}}
+ // expected-error@-3 {{is const, but a member or base requires it to be non-const}}
+#else
+ // expected-warning@-6 {{implicitly deleted}} expected-note@-6 {{type does not match}}
+ // expected-warning@-6 {{implicitly deleted}} expected-note@-6 {{type does not match}}
+#endif
+};
+
+struct D : B { // expected-note 2{{base class}}
+ D(const D&);
+ D &operator=(const D&);
+};
+D::D(const D&) = default; // expected-error {{would delete}} expected-error {{is const, but}}
+D &D::operator=(const D&) = default; // expected-error {{would delete}} expected-error {{is const, but}}
diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp
index f193c8e024fb..208ab8a03b0a 100644
--- a/test/CXX/drs/dr13xx.cpp
+++ b/test/CXX/drs/dr13xx.cpp
@@ -226,10 +226,10 @@ namespace dr1330 { // dr1330: 4 c++11
#endif
void f(D &d) { d = d; } // ok
- // FIXME: In C++11 onwards, we should also note the declaration of 'e' as the
- // line that triggers the use of E::E()'s exception specification.
struct E : C<int> {}; // expected-note {{in instantiation of}}
- E e;
+#if __cplusplus >= 201103L
+ E e; // expected-note {{needed here}}
+#endif
}
namespace dr1346 { // dr1346: 3.5
diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp
index a92501128b5f..26ab67d54d31 100644
--- a/test/CXX/drs/dr1xx.cpp
+++ b/test/CXX/drs/dr1xx.cpp
@@ -401,13 +401,12 @@ namespace dr136 { // dr136: 3.4
extern "C" void k(int, int, int, int); // expected-note {{previous declaration is here}}
namespace NSA {
struct A {
- friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}} \
- // expected-note {{previous declaration is here}}
+ friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
};
}
namespace NSB {
struct A {
- friend void dr136::k(int, int, int = 0, int); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
+ friend void dr136::k(int, int, int = 0, int); // expected-error {{missing default argument on parameter}}
};
}
struct B {
diff --git a/test/CXX/drs/dr22xx.cpp b/test/CXX/drs/dr22xx.cpp
index 021707d876b7..70a26db757c3 100644
--- a/test/CXX/drs/dr22xx.cpp
+++ b/test/CXX/drs/dr22xx.cpp
@@ -15,3 +15,14 @@ struct AnonBitfieldQualifiers {
const volatile unsigned i3 : 1;
};
}
+
+#if __cplusplus >= 201103L
+namespace dr2211 { // dr2211: 8
+void f() {
+ int a;
+ auto f = [a](int a) { (void)a; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
+ // expected-note@-1{{variable 'a' is explicitly captured here}}
+ auto g = [=](int a) { (void)a; };
+}
+}
+#endif
diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp
index 4e745ef2f4d0..b69c014b587f 100644
--- a/test/CXX/drs/dr2xx.cpp
+++ b/test/CXX/drs/dr2xx.cpp
@@ -718,7 +718,7 @@ namespace dr261 { // dr261: no
A() {}
};
- // FIXME: These are ill-formed, with a required diagnostic, for the same
+ // FIXME: This is ill-formed, with a required diagnostic, for the same
// reason.
struct B {
inline void operator delete(void*) __attribute__((unused));
@@ -726,7 +726,7 @@ namespace dr261 { // dr261: no
};
struct C {
inline void operator delete(void*) __attribute__((unused));
- virtual ~C() {}
+ virtual ~C() {} // expected-warning {{'operator delete' was marked unused but was used}}
};
struct D {
diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp
index c20a873fc1c7..2099612e23f3 100644
--- a/test/CXX/drs/dr5xx.cpp
+++ b/test/CXX/drs/dr5xx.cpp
@@ -740,17 +740,17 @@ namespace dr573 { // dr573: no
namespace dr574 { // dr574: yes
struct A {
- A &operator=(const A&) const; // expected-note {{does not match because it is const}}
+ A &operator=(const A&) const; // expected-note {{different qualifiers}}
};
struct B {
- B &operator=(const B&) volatile; // expected-note {{nearly matches}}
+ B &operator=(const B&) volatile; // expected-note {{different qualifiers}}
};
#if __cplusplus >= 201103L
struct C {
- C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}}
+ C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}}
};
struct D {
- D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}}
+ D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}}
};
void test(C c, D d) {
c = c;
diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp
index c3c867b7a54d..b4247b22607d 100644
--- a/test/CXX/drs/dr6xx.cpp
+++ b/test/CXX/drs/dr6xx.cpp
@@ -492,7 +492,13 @@ namespace dr647 { // dr647: yes
struct C {
constexpr C(NonLiteral);
constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}}
- constexpr C() try {} catch (...) {} // expected-error {{function try block}}
+ constexpr C() try {} catch (...) {}
+#if __cplusplus <= 201703L
+ // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}}
+#endif
+#if __cplusplus < 201402L
+ // expected-error@-5 {{use of this statement in a constexpr constructor is a C++14 extension}}
+#endif
};
struct D {
@@ -757,8 +763,8 @@ namespace dr666 { // dr666: yes
#if __cplusplus >= 201103L
namespace dr667 { // dr667: yes
struct A {
- A() = default;
- int &r;
+ A() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}}
+ int &r; // expected-note {{because field 'r' of reference type 'int &' would not be initialized}}
};
static_assert(!__is_trivially_constructible(A), "");
@@ -833,7 +839,7 @@ namespace dr673 { // dr673: yes
F *f; // expected-error {{unknown type name}}
}
-namespace dr674 { // dr674: no
+namespace dr674 { // dr674: 8
template<typename T> int f(T);
int g(int);
@@ -843,22 +849,50 @@ namespace dr674 { // dr674: no
template<typename T> int h(T);
class X {
- // FIXME: This should deduce dr674::f<int>.
- friend int dr674::f(int); // expected-error {{does not match any}}
+ friend int dr674::f(int);
friend int dr674::g(int);
friend int dr674::h<>(int);
- int n;
+ int n; // expected-note 2{{private}}
};
template<typename T> int f(T) { return X().n; }
int g(int) { return X().n; }
- template<typename T> int g(T) { return X().n; }
- int h(int) { return X().n; }
+ template<typename T> int g(T) { return X().n; } // expected-error {{private}}
+ int h(int) { return X().n; } // expected-error {{private}}
template<typename T> int h(T) { return X().n; }
template int f(int);
- template int g(int);
+ template int g(int); // expected-note {{in instantiation of}}
template int h(int);
+
+
+ struct Y {
+ template<typename T> int f(T);
+
+ int g(int);
+ template<typename T> int g(T);
+
+ int h(int);
+ template<typename T> int h(T);
+ };
+
+ class Z {
+ friend int Y::f(int);
+ friend int Y::g(int);
+ friend int Y::h<>(int);
+ int n; // expected-note 2{{private}}
+ };
+
+ template<typename T> int Y::f(T) { return Z().n; }
+ int Y::g(int) { return Z().n; }
+ template<typename T> int Y::g(T) { return Z().n; } // expected-error {{private}}
+ int Y::h(int) { return Z().n; } // expected-error {{private}}
+ template<typename T> int Y::h(T) { return Z().n; }
+
+ // FIXME: Should the <> be required here?
+ template int Y::f<>(int);
+ template int Y::g<>(int); // expected-note {{in instantiation of}}
+ template int Y::h<>(int);
}
namespace dr675 { // dr675: dup 739
diff --git a/test/CXX/expr/expr.const/p6.cpp b/test/CXX/expr/expr.const/p6.cpp
new file mode 100644
index 000000000000..a8fc7754e7db
--- /dev/null
+++ b/test/CXX/expr/expr.const/p6.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++17 -verify %s
+
+template<typename T> int not_constexpr() { return T::error; }
+template<typename T> constexpr int is_constexpr() { return T::error; } // expected-error {{'::'}}
+
+template<typename T> int not_constexpr_var = T::error;
+template<typename T> constexpr int is_constexpr_var = T::error; // expected-error {{'::'}}
+template<typename T> const int is_const_var = T::error; // expected-error {{'::'}}
+template<typename T> const volatile int is_const_volatile_var = T::error;
+template<typename T> T is_dependent_var = T::error; // expected-error {{'::'}}
+template<typename T> int &is_reference_var = T::error; // expected-error {{'::'}}
+template<typename T> float is_float_var = T::error;
+
+void test() {
+ // Do not instantiate functions referenced in unevaluated operands...
+ (void)sizeof(not_constexpr<long>());
+ (void)sizeof(is_constexpr<long>());
+ (void)sizeof(not_constexpr_var<long>);
+ (void)sizeof(is_constexpr_var<long>);
+ (void)sizeof(is_const_var<long>);
+ (void)sizeof(is_const_volatile_var<long>);
+ (void)sizeof(is_dependent_var<long>);
+ (void)sizeof(is_dependent_var<const long>);
+ (void)sizeof(is_reference_var<long>);
+ (void)sizeof(is_float_var<long>);
+
+ // ... but do if they are potentially constant evaluated, and refer to
+ // constexpr functions or to variables usable in constant expressions.
+ (void)sizeof(int{not_constexpr<int>()});
+ (void)sizeof(int{is_constexpr<int>()}); // expected-note {{instantiation of}}
+ (void)sizeof(int{not_constexpr_var<int>});
+ (void)sizeof(int{is_constexpr_var<int>}); // expected-note {{instantiation of}}
+ (void)sizeof(int{is_const_var<int>}); // expected-note {{instantiation of}}
+ (void)sizeof(int{is_const_volatile_var<int>});
+ (void)sizeof(int{is_dependent_var<int>});
+ (void)sizeof(int{is_dependent_var<const int>}); // expected-note {{instantiation of}}
+ (void)sizeof(int{is_reference_var<int>}); // expected-note {{instantiation of}}
+ (void)sizeof(int{is_float_var<int>}); // expected-error {{cannot be narrowed}} expected-note {{cast}}
+}
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
index 551c100ff7af..7fc86e810927 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
@@ -15,8 +15,8 @@ public:
void capture_by_copy(NonCopyable nc, NonCopyable &ncr, const NonConstCopy nco) {
(void)[nc] { }; // expected-error{{capture of variable 'nc' as type 'NonCopyable' calls private copy constructor}}
- (void)[=] {
- ncr.foo(); // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}}
+ (void)[=] { // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}}
+ ncr.foo();
}();
[nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}}
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
index 31213c9ebc33..2bb75df7ac6a 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
@@ -88,8 +88,8 @@ namespace p2 {
template<typename R, typename T>
void odr_used2(R &r, Boom<T> boom) {
const std::type_info &ti
- = typeid([=,&r] () -> R& {
- boom.tickle(); // expected-note{{in instantiation of member function}}
+ = typeid([=,&r] () -> R& { // expected-note{{in instantiation of member function 'p2::Boom<float>::Boom' requested here}}
+ boom.tickle();
return r;
}());
}
@@ -139,11 +139,11 @@ namespace NonLocalLambdaInstantation {
}
template<typename T>
- struct X2 {
+ struct X2 { // expected-note{{in instantiation of default member initializer 'NonLocalLambdaInstantation::X2<int *>::x'}}
int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}}
};
X2<int> x2i;
X2<float> x2f;
- X2<int*> x2ip; // expected-note{{in instantiation of default member initializer 'NonLocalLambdaInstantation::X2<int *>::x'}}
+ X2<int*> x2ip; // expected-note {{in evaluation of exception spec}}
}
diff --git a/test/CXX/special/class.copy/p12-0x.cpp b/test/CXX/special/class.copy/p12-0x.cpp
index 1b23b5a4b179..a0ef49d9b64d 100644
--- a/test/CXX/special/class.copy/p12-0x.cpp
+++ b/test/CXX/special/class.copy/p12-0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-defaulted-function-deleted
// expected-no-diagnostics
diff --git a/test/CXX/special/class.copy/p23-cxx11.cpp b/test/CXX/special/class.copy/p23-cxx11.cpp
index ac21cc61a2c5..0b9652b50fcf 100644
--- a/test/CXX/special/class.copy/p23-cxx11.cpp
+++ b/test/CXX/special/class.copy/p23-cxx11.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify %s -std=c++11
+// RUN: %clang_cc1 -verify %s -std=c++11 -Wno-defaulted-function-deleted
struct Trivial {};
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index 061a3d1f0738..5fa61008e8b7 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-defaulted-function-deleted
struct DefaultedDefCtor1 {};
struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; };
diff --git a/test/CXX/special/class.dtor/p5-0x.cpp b/test/CXX/special/class.dtor/p5-0x.cpp
index 595784f0d5f9..f69baca53bf3 100644
--- a/test/CXX/special/class.dtor/p5-0x.cpp
+++ b/test/CXX/special/class.dtor/p5-0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -std=c++11 %s
+// RUN: %clang_cc1 -verify -std=c++11 %s -Wno-defaulted-function-deleted
struct NonTrivDtor {
~NonTrivDtor();
diff --git a/test/CXX/special/class.temporary/p6.cpp b/test/CXX/special/class.temporary/p6.cpp
new file mode 100644
index 000000000000..077385fb7aaa
--- /dev/null
+++ b/test/CXX/special/class.temporary/p6.cpp
@@ -0,0 +1,240 @@
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s --implicit-check-not='call{{.*}}dtor'
+
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ template <class E>
+ struct initializer_list {
+ const E *begin;
+ size_t size;
+ initializer_list() : begin(nullptr), size(0) {}
+ };
+}
+
+void then();
+
+struct dtor {
+ ~dtor();
+};
+
+dtor ctor();
+
+auto &&lambda = [a = {ctor()}] {};
+// CHECK-LABEL: define
+// CHECK: call {{.*}}ctor
+// CHECK: call {{.*}}atexit{{.*}}global_array_dtor
+
+// CHECK-LABEL: define{{.*}}global_array_dtor
+// CHECK: call {{.*}}dtor
+
+// [lifetime extension occurs if the object was obtained by]
+// -- a temporary materialization conversion
+// CHECK-LABEL: ref_binding
+void ref_binding() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = ctor();
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+
+// -- ( expression )
+// CHECK-LABEL: parens
+void parens() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = ctor();
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+
+// -- subscripting of an array
+// CHECK-LABEL: array_subscript_1
+void array_subscript_1() {
+ using T = dtor[1];
+ // CHECK: call {{.*}}ctor
+ auto &&x = T{ctor()}[0];
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+// CHECK-LABEL: array_subscript_2
+void array_subscript_2() {
+ using T = dtor[1];
+ // CHECK: call {{.*}}ctor
+ auto &&x = ((dtor*)T{ctor()})[0];
+ // CHECK: call {{.*}}dtor
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: }
+}
+
+struct with_member { dtor d; ~with_member(); };
+struct with_ref_member { dtor &&d; ~with_ref_member(); };
+
+// -- a class member access using the . operator [...]
+// CHECK-LABEL: member_access_1
+void member_access_1() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = with_member{ctor()}.d;
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}with_member
+ // CHECK: }
+}
+// CHECK-LABEL: member_access_2
+void member_access_2() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = with_ref_member{ctor()}.d;
+ // CHECK: call {{.*}}with_ref_member
+ // CHECK: call {{.*}}dtor
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: }
+}
+// CHECK-LABEL: member_access_3
+void member_access_3() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = (&(const with_member&)with_member{ctor()})->d;
+ // CHECK: call {{.*}}with_member
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: }
+}
+
+// -- a pointer-to-member operation using the .* operator [...]
+// CHECK-LABEL: member_ptr_access_1
+void member_ptr_access_1() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = with_member{ctor()}.*&with_member::d;
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}with_member
+ // CHECK: }
+}
+// CHECK-LABEL: member_ptr_access_2
+void member_ptr_access_2() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = (&(const with_member&)with_member{ctor()})->*&with_member::d;
+ // CHECK: call {{.*}}with_member
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: }
+}
+
+// -- a [named] cast [...]
+// CHECK-LABEL: static_cast
+void test_static_cast() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = static_cast<dtor&&>(ctor());
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+// CHECK-LABEL: const_cast
+void test_const_cast() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = const_cast<dtor&&>(ctor());
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+// CHECK-LABEL: reinterpret_cast
+void test_reinterpret_cast() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = reinterpret_cast<dtor&&>(static_cast<dtor&&>(ctor()));
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+// CHECK-LABEL: dynamic_cast
+void test_dynamic_cast() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = dynamic_cast<dtor&&>(ctor());
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+
+// -- [explicit cast notation is defined in terms of the above]
+// CHECK-LABEL: c_style_cast
+void c_style_cast() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = (dtor&&)ctor();
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+// CHECK-LABEL: function_style_cast
+void function_style_cast() {
+ // CHECK: call {{.*}}ctor
+ using R = dtor&&;
+ auto &&x = R(ctor());
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+
+// -- a conditional operator
+// CHECK-LABEL: conditional
+void conditional(bool b) {
+ // CHECK: call {{.*}}ctor
+ // CHECK: call {{.*}}ctor
+ auto &&x = b ? (dtor&&)ctor() : (dtor&&)ctor();
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+
+// -- a comma expression
+// CHECK-LABEL: comma
+void comma() {
+ // CHECK: call {{.*}}ctor
+ auto &&x = (true, (dtor&&)ctor());
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+
+
+// This applies recursively: if an object is lifetime-extended and contains a
+// reference, the referent is also extended.
+// CHECK-LABEL: init_capture_ref
+void init_capture_ref() {
+ // CHECK: call {{.*}}ctor
+ auto x = [&a = (const dtor&)ctor()] {};
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+// CHECK-LABEL: init_capture_ref_indirect
+void init_capture_ref_indirect() {
+ // CHECK: call {{.*}}ctor
+ auto x = [&a = (const dtor&)ctor()] {};
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
+// CHECK-LABEL: init_capture_init_list
+void init_capture_init_list() {
+ // CHECK: call {{.*}}ctor
+ auto x = [a = {ctor()}] {};
+ // CHECK: call {{.*}}then
+ then();
+ // CHECK: call {{.*}}dtor
+ // CHECK: }
+}
diff --git a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index 34202494c0d8..f42fc9b6e5aa 100644
--- a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -108,7 +108,7 @@ void g() {
extern int incomplete[];
for (auto a : incomplete) // expected-error {{cannot use incomplete type 'int []' as a range}}
;
- extern struct Incomplete also_incomplete[2]; // expected-note {{forward declaration}}
+ extern struct Incomplete also_incomplete[2]; // expected-note 2{{forward declaration}}
for (auto &a : also_incomplete) // expected-error {{cannot use incomplete type 'struct Incomplete [2]' as a range}}
;
@@ -150,9 +150,9 @@ void g() {
struct NoEnd {
null_t begin();
};
- for (auto u : NoBegin()) { // expected-error {{range type 'NoBegin' has 'end' member but no 'begin' member}}
+ for (auto u : NoBegin()) { // expected-error {{no viable 'begin' function available}}
}
- for (auto u : NoEnd()) { // expected-error {{range type 'NoEnd' has 'begin' member but no 'end' member}}
+ for (auto u : NoEnd()) { // expected-error {{no viable 'end' function available}}
}
struct NoIncr {
@@ -271,3 +271,58 @@ namespace rdar13712739 {
template void foo(const int&); // expected-note{{in instantiation of function template specialization}}
}
+
+namespace p0962r1 {
+ namespace NA {
+ struct A {
+ void begin();
+ };
+ int *begin(A);
+ int *end(A);
+ }
+
+ namespace NB {
+ struct B {
+ void end();
+ };
+ int *begin(B);
+ int *end(B);
+ }
+
+ namespace NC {
+ struct C {
+ void begin();
+ };
+ int *begin(C);
+ }
+
+ namespace ND {
+ struct D {
+ void end();
+ };
+ int *end(D);
+ }
+
+ namespace NE {
+ struct E {
+ void begin(); // expected-note {{member is not a candidate because range type 'p0962r1::NE::E' has no 'end' member}}
+ };
+ int *end(E);
+ }
+
+ namespace NF {
+ struct F {
+ void end(); // expected-note {{member is not a candidate because range type 'p0962r1::NF::F' has no 'begin' member}}
+ };
+ int *begin(F);
+ }
+
+ void use(NA::A a, NB::B b, NC::C c, ND::D d, NE::E e, NF::F f) {
+ for (auto x : a) {}
+ for (auto x : b) {}
+ for (auto x : c) {} // expected-error {{no viable 'end' function}}
+ for (auto x : d) {} // expected-error {{no viable 'begin' function}}
+ for (auto x : e) {} // expected-error {{no viable 'begin' function}}
+ for (auto x : f) {} // expected-error {{no viable 'end' function}}
+ }
+}
diff --git a/test/CXX/stmt.stmt/stmt.select/p3.cpp b/test/CXX/stmt.stmt/stmt.select/p3.cpp
index 7a6a408ec955..4804cc559d00 100644
--- a/test/CXX/stmt.stmt/stmt.select/p3.cpp
+++ b/test/CXX/stmt.stmt/stmt.select/p3.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -std=c++1z -Wc++14-compat -verify %s -DCPP17
int f();
@@ -71,7 +71,6 @@ void whileInitStatement() {
// last loop above. It would be nice to remove this.
void whileInitStatement2() {
while (; false) {} // expected-error {{expected expression}}
- // expected-warning@-1 {{expression result unused}}
- // expected-error@-2 {{expected ';' after expression}}
- // expected-error@-3 {{expected expression}}
+ // expected-error@-1 {{expected ';' after expression}}
+ // expected-error@-2 {{expected expression}}
}
diff --git a/test/CXX/temp/temp.param/p2.cpp b/test/CXX/temp/temp.param/p2.cpp
index 656bd26ff08d..c70b1d354f7c 100644
--- a/test/CXX/temp/temp.param/p2.cpp
+++ b/test/CXX/temp/temp.param/p2.cpp
@@ -8,14 +8,17 @@
template<class T> struct X;
template<typename T> struct X;
-// typename followed by aqualified-id denotes the type in a non-type
+// typename followed by a qualified-id denotes the type in a non-type
// parameter-declaration.
template<typename T, typename T::type Value> struct Y0;
template<typename T, typename X<T>::type Value> struct Y1;
+template<typename T typename U> struct Y2; // expected-error{{expected ',' or '>'}}
+template<typename T U> struct Y3; // expected-error{{expected a qualified name after 'typename'}} expected-error{{expected ',' or '>'}}
+template<typedef T typename U> struct Y4; // expected-error{{expected template parameter}} expected-note {{did you mean to use 'typename'?}} expected-error{{expected ',' or '>'}}
// A storage class shall not be specified in a template-parameter declaration.
template<static int Value> struct Z; //expected-error{{invalid declaration specifier}}
-template<typedef int Value> struct Z0; //expected-error{{expected template parameter}} expected-error{{expected identifier}} expected-error{{extraneous 'template<>' in declaration of struct 'Z0'}} expected-note{{did you mean to use 'typename'?}}
+template<typedef int Value> struct Z0; //expected-error{{invalid declaration specifier}}
template<extern inline int Value> struct Z1; //expected-error2{{invalid declaration specifier}}
template<virtual int Value> struct Z2; //expected-error{{invalid declaration specifier}}
template<explicit int Value> struct Z3; //expected-error{{invalid declaration specifier}}
@@ -43,6 +46,6 @@ template<auto> struct Z13; // OK
// Make sure that we properly disambiguate non-type template parameters that
// start with 'class'.
class X1 { };
-template<class X1 *xptr> struct Y2 { };
+template<class X1 *xptr> struct X2 { };
// FIXME: add the example from p2
diff --git a/test/CXX/temp/temp.param/p3.cpp b/test/CXX/temp/temp.param/p3.cpp
index c3c93396cb13..f709630504cd 100644
--- a/test/CXX/temp/temp.param/p3.cpp
+++ b/test/CXX/temp/temp.param/p3.cpp
@@ -16,7 +16,7 @@ template<template<class T> class Y> struct X1 {
// [Note: because of the name lookup rules, a template-parameter that
// could be interpreted as either a non-type template-parameter or a
// type-parameter (because its identifier is the name of an already
-// existing class) is taken as a type-parameter. For example,
+// existing class) is taken as a type-parameter. For example,
class T { /* ... */ }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}}
#if __cplusplus >= 201103L // C++11 or later
// expected-note@-2 {{candidate constructor (the implicit move constructor) not viable}}
@@ -27,7 +27,7 @@ int i;
template<class T, T i> struct X2 {
void f(T t)
{
- T t1 = i; //template-parameters T and i
+ T t1 = i; // template-parameters T and i
::T t2 = ::i; // global namespace members T and i \
// expected-error{{no viable conversion}}
}
diff --git a/test/CXX/temp/temp.spec/temp.inst/p7.cpp b/test/CXX/temp/temp.spec/temp.inst/p7.cpp
new file mode 100644
index 000000000000..5145dafdc5b4
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.inst/p7.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -verify -std=c++17 %s
+
+template<typename T> constexpr int f() { return T::value; } // expected-error {{'::'}}
+template<bool B, typename T> void g(decltype(B ? f<T>() : 0));
+template<bool B, typename T> void g(...);
+template<bool B, typename T> void h(decltype(int{B ? f<T>() : 0})); // expected-note {{instantiation of}}
+template<bool B, typename T> void h(...);
+void x() {
+ g<false, int>(0); // ok
+ g<true, int>(0); // ok
+ h<false, int>(0); // expected-note {{while substituting}}
+}
diff --git a/test/CodeCompletion/accessibility-crash.cpp b/test/CodeCompletion/accessibility-crash.cpp
new file mode 100644
index 000000000000..b54f7cea3e20
--- /dev/null
+++ b/test/CodeCompletion/accessibility-crash.cpp
@@ -0,0 +1,23 @@
+class X {
+public:
+ int pub;
+protected:
+ int prot;
+private:
+ int priv;
+};
+
+class Y : public X {
+ int test() {
+ []() {
+
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:13:1 %s -o - \
+ // RUN: | FileCheck %s
+ // CHECK: priv (InBase,Inaccessible)
+ // CHECK: prot (InBase)
+ // CHECK: pub (InBase)
+ };
+ }
+};
+
+
diff --git a/test/CodeCompletion/accessibility.cpp b/test/CodeCompletion/accessibility.cpp
new file mode 100644
index 000000000000..a050efc9a73d
--- /dev/null
+++ b/test/CodeCompletion/accessibility.cpp
@@ -0,0 +1,122 @@
+class X {
+public:
+ int pub;
+protected:
+ int prot;
+private:
+ int priv;
+};
+
+class Unrelated {
+public:
+ static int pub;
+protected:
+ static int prot;
+private:
+ static int priv;
+};
+
+class Y : public X {
+ int test() {
+ this->pub = 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:21:11 %s -o - \
+ // RUN: | FileCheck -check-prefix=THIS %s
+ // THIS: priv (InBase,Inaccessible)
+ // THIS: prot (InBase)
+ // THIS: pub (InBase)
+ //
+ // Also check implicit 'this->', i.e. complete at the start of the line.
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:21:1 %s -o - \
+ // RUN: | FileCheck -check-prefix=THIS %s
+
+ X().pub + 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:32:9 %s -o - \
+ // RUN: | FileCheck -check-prefix=X-OBJ %s
+ // X-OBJ: priv (Inaccessible)
+ // X-OBJ: prot (Inaccessible)
+ // X-OBJ: pub : [#int#]pub
+
+ Y().pub + 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:39:9 %s -o - \
+ // RUN: | FileCheck -check-prefix=Y-OBJ %s
+ // Y-OBJ: priv (InBase,Inaccessible)
+ // Y-OBJ: prot (InBase)
+ // Y-OBJ: pub (InBase)
+
+ this->X::pub = 10;
+ X::pub = 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:46:14 %s -o - \
+ // RUN: | FileCheck -check-prefix=THIS-BASE %s
+ //
+ // THIS-BASE: priv (Inaccessible)
+ // THIS-BASE: prot : [#int#]prot
+ // THIS-BASE: pub : [#int#]pub
+ //
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:47:8 %s -o - \
+ // RUN: | FileCheck -check-prefix=THIS-BASE %s
+
+
+ this->Unrelated::pub = 10; // a check we don't crash in this cases.
+ Y().Unrelated::pub = 10; // a check we don't crash in this cases.
+ Unrelated::pub = 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:59:22 %s -o - \
+ // RUN: | FileCheck -check-prefix=UNRELATED %s
+ // UNRELATED: priv (Inaccessible)
+ // UNRELATED: prot (Inaccessible)
+ // UNRELATED: pub : [#int#]pub
+ //
+ // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:60:20 %s -o - \
+ // RUN: | FileCheck -check-prefix=UNRELATED %s
+ // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:61:16 %s -o - \
+ // RUN: | FileCheck -check-prefix=UNRELATED %s
+ }
+};
+
+class Outer {
+ public:
+ static int pub;
+ protected:
+ static int prot;
+ private:
+ static int priv;
+
+ class Inner {
+ int test() {
+ Outer::pub = 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:85:14 %s -o - \
+ // RUN: | FileCheck -check-prefix=OUTER %s
+ // OUTER: priv : [#int#]priv
+ // OUTER: prot : [#int#]prot
+ // OUTER: pub : [#int#]pub
+
+ // Also check the unqualified case.
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:85:1 %s -o - \
+ // RUN: | FileCheck -check-prefix=OUTER %s
+ }
+ };
+};
+
+class Base {
+public:
+ int pub;
+};
+
+class Accessible : public Base {
+};
+
+class Inaccessible : private Base {
+};
+
+class Test : public Accessible, public Inaccessible {
+ int test() {
+ this->Accessible::pub = 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:112:23 %s -o - \
+ // RUN: | FileCheck -check-prefix=ACCESSIBLE %s
+ // ACCESSIBLE: pub (InBase)
+
+ this->Inaccessible::pub = 10;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:117:25 %s -o - \
+ // RUN: | FileCheck -check-prefix=INACCESSIBLE %s
+ // INACCESSIBLE: pub (InBase,Inaccessible)
+ }
+};
diff --git a/test/CodeCompletion/call.cpp b/test/CodeCompletion/call.cpp
index 3e062109a9aa..c57c339cd130 100644
--- a/test/CodeCompletion/call.cpp
+++ b/test/CodeCompletion/call.cpp
@@ -18,10 +18,10 @@ void f();
void test() {
f(Y(), 0, 0);
// RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
- // CHECK-CC1: COMPLETION: Pattern : dynamic_cast<<#type#>>(<#expression#>)
// CHECK-CC1: f(Y y, <#int ZZ#>)
// CHECK-CC1-NEXT: f(int i, <#int j#>, int k)
// CHECK-CC1-NEXT: f(float x, <#float y#>)
+ // CHECK-CC1: COMPLETION: Pattern : dynamic_cast<<#type#>>(<#expression#>)
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2-NOT: f(Y y, int ZZ)
// CHECK-CC2: f(int i, int j, <#int k#>)
diff --git a/test/CodeCompletion/crash-func-decl.cpp b/test/CodeCompletion/crash-func-decl.cpp
new file mode 100644
index 000000000000..7abcdcdb271f
--- /dev/null
+++ b/test/CodeCompletion/crash-func-decl.cpp
@@ -0,0 +1,5 @@
+// Important that BB is unknown.
+// This triggers completion in PCC_RecoveryInFunction context, with no function.
+int AA(BB cc);
+// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:3:12 %s | FileCheck %s
+// CHECK: COMPLETION: char
diff --git a/test/CodeCompletion/ctor-initializer.cpp b/test/CodeCompletion/ctor-initializer.cpp
index e1a0d1436874..ead99f087ca8 100644
--- a/test/CodeCompletion/ctor-initializer.cpp
+++ b/test/CodeCompletion/ctor-initializer.cpp
@@ -2,14 +2,14 @@ struct Base1 {
Base1() : {}
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
- // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>)
- // CHECK-CC1: COMPLETION: Pattern : member2(<#args#>
+ // CHECK-CC1: COMPLETION: Pattern : member1(<#int#>)
+ // CHECK-CC1: COMPLETION: Pattern : member2(<#float#>)
Base1(int) : member1(123), {}
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
- // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>)
- // CHECK-CC2: COMPLETION: Pattern : member2(<#args#>
+ // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#int#>)
+ // CHECK-CC2: COMPLETION: Pattern : member2(<#float#>)
int member1;
float member2;
@@ -25,42 +25,81 @@ struct Derived : public Base1 {
Derived::Derived() : {}
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>)
-// CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>)
+// CHECK-CC3: COMPLETION: Pattern : Base1()
+// CHECK-CC3: COMPLETION: Pattern : Base1(<#int#>)
+// CHECK-CC3: COMPLETION: Pattern : deriv1(<#int#>)
Derived::Derived(int) try : {
} catch (...) {
}
-// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
-// CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>)
-// CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>)
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:32:29 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:32:29 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
Derived::Derived(float) try : Base1(),
{
} catch (...) {
}
-// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>)
-// CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>)
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:38:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:38:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5-NOT: COMPLETION: Pattern : Base1
+// CHECK-CC5: COMPLETION: Pattern : deriv1(<#int#>)
struct A {
A() : , member2() {}
- // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
- // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
- // CHECK-CC6: COMPLETION: Pattern : member1(<#args#>
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:48:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:48:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+ // CHECK-CC6: COMPLETION: Pattern : member1(<#int#>)
int member1, member2;
};
struct B {
B() : member2() {}
- // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
- // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
- // CHECK-CC7: COMPLETION: Pattern : member1(<#args#>
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:56:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:56:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
+ // CHECK-CC7: COMPLETION: Pattern : member1(<#int#>)
// Check in the middle and at the end of identifier too.
- // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:13 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
- // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:16 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
- // CHECK-CC8: COMPLETION: Pattern : member2(<#args#>
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:56:13 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:56:16 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
+ // CHECK-CC8: COMPLETION: Pattern : member2(<#int#>)
int member1, member2;
};
+
+struct Base2 {
+ Base2(int);
+};
+
+struct Composition1 {
+ Composition1() : b2_elem(2) {}
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:72:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:72:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // CHECK-CC9: OVERLOAD: Base2(<#int#>)
+ // CHECK-CC9: OVERLOAD: Base2(<#const Base2 &#>)
+ // CHECK-CC9-NOT: OVERLOAD: Composition1
+ Composition1(Base2);
+ Base2 b2_elem;
+};
+
+struct Composition2 {
+ Composition2() : c1_elem(Base2(1)) {}
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:83:34 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:83:34 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:83:35 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:83:35 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ Composition1 c1_elem;
+};
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:83:20 %s -o - | FileCheck -check-prefix=CHECK-CC10 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:83:20 %s -o - | FileCheck -check-prefix=CHECK-CC10 %s
+// CHECK-CC10: Pattern : c1_elem()
+// CHECK-CC10: Pattern : c1_elem(<#Base2#>)
+
+template <class T>
+struct Y : T {};
+
+template <class T>
+struct X : Y<T> {
+ X() : Y<T>() {};
+};
+
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:100:9 %s -o - | FileCheck -check-prefix=CHECK-CC11 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:100:9 %s -o - | FileCheck -check-prefix=CHECK-CC11 %s
+// CHECK-CC11: Pattern : Y<T>(<#Y<T>#>)
diff --git a/test/CodeCompletion/function-overloads.cpp b/test/CodeCompletion/function-overloads.cpp
new file mode 100644
index 000000000000..11c864c28107
--- /dev/null
+++ b/test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,43 @@
+int f(int i, int j = 2, int k = 5);
+int f(float x, float y...);
+
+class A {
+ public:
+ A(int, int, int);
+};
+
+void test() {
+ A a(f(1, 2, 3, 4), 2, 3);
+}
+
+
+namespace NS {
+ struct X { };
+ struct Y { Y(X); };
+ template <class T = int>
+ void g(X, Y);
+}
+
+void test_adl() {
+ NS::X x;
+ g(x, x);
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:7 %s -o - | \
+// RUN: FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
+// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
+// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
+// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y)
+// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i)
+// CHECK-CC3: OVERLOAD: A(<#int#>, int, int)
+// CHECK-CC3: OVERLOAD: A(<#const A &#>)
+// CHECK-CC3: OVERLOAD: A(<#A &&#>)
+// CHECK-CC4: OVERLOAD: A(int, <#int#>, int)
+// CHECK-CC5: OVERLOAD: [#void#]g(X, <#Y#>)
diff --git a/test/CodeCompletion/included-files.cpp b/test/CodeCompletion/included-files.cpp
new file mode 100644
index 000000000000..ba153e6e2754
--- /dev/null
+++ b/test/CodeCompletion/included-files.cpp
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t && mkdir %t && cp %s %t/main.cc && mkdir %t/a
+// RUN: touch %t/foo.h && touch %t/foo.cc && touch %t/a/foosys %t/a/foosys.h
+
+// Quoted string shows header-ish files from CWD, and all from system.
+#include "foo.h"
+// RUN: %clang -fsyntax-only -isystem %t/a -Xclang -code-completion-at=%t/main.cc:5:13 %t/main.cc | FileCheck -check-prefix=CHECK-1 %s
+// CHECK-1-NOT: foo.cc"
+// CHECK-1: foo.h"
+// CHECK-1: foosys"
+
+// Quoted string with dir shows header-ish files in that subdir.
+#include "a/foosys"
+// RUN: %clang -fsyntax-only -isystem %t/a -Xclang -code-completion-at=%t/main.cc:12:13 %t/main.cc | FileCheck -check-prefix=CHECK-2 %s
+// CHECK-2-NOT: foo.h"
+// CHECK-2: foosys.h"
+// CHECK-2-NOT: foosys"
+
+// Angled shows headers from system dirs.
+#include <foosys>
+// RUN: %clang -fsyntax-only -isystem %t/a -Xclang -code-completion-at=%t/main.cc:19:13 %t/main.cc | FileCheck -check-prefix=CHECK-3 %s
+// CHECK-3-NOT: foo.cc>
+// CHECK-3-NOT: foo.h>
+// CHECK-3: foosys>
+
+// With -I rather than -isystem, the header extension is required.
+#include <foosys>
+// RUN: %clang -fsyntax-only -I %t/a -Xclang -code-completion-at=%t/main.cc:26:13 %t/main.cc | FileCheck -check-prefix=CHECK-4 %s
+// CHECK-4-NOT: foo.cc>
+// CHECK-4-NOT: foo.h>
+// CHECK-4-NOT: foosys>
+
+// Backslash handling.
+#include "a\foosys"
+// RUN: %clang -fsyntax-only -isystem %t/a -Xclang -code-completion-at=%t/main.cc:33:13 %t/main.cc -fms-compatibility | FileCheck -check-prefix=CHECK-5 %s
+// CHECK-5: foosys.h"
diff --git a/test/CodeCompletion/member-access.c b/test/CodeCompletion/member-access.c
index 226e182ab15f..72afbf2ff947 100644
--- a/test/CodeCompletion/member-access.c
+++ b/test/CodeCompletion/member-access.c
@@ -10,3 +10,22 @@ void test(struct Point *p) {
// CHECK-CC1: x
// CHECK-CC1: y
// CHECK-CC1: z
+}
+
+struct Point2 {
+ float x;
+};
+
+void test2(struct Point2 p) {
+ p->
+}
+
+void test3(struct Point2 *p) {
+ p.
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:20:6 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: x (requires fix-it: {20:4-20:6} to ".")
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:24:5 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: x (requires fix-it: {24:4-24:5} to "->")
diff --git a/test/CodeCompletion/member-access.cpp b/test/CodeCompletion/member-access.cpp
index 008e223716bb..003d224fbe24 100644
--- a/test/CodeCompletion/member-access.cpp
+++ b/test/CodeCompletion/member-access.cpp
@@ -51,16 +51,16 @@ struct Bar {
};
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:31:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 --implicit-check-not="Derived : Derived(" %s
- // CHECK-CC1: Base1 : Base1::
- // CHECK-CC1: member1 : [#int#][#Base1::#]member1
- // CHECK-CC1: member1 : [#int#][#Base2::#]member1
- // CHECK-CC1: member2 : [#float#][#Base1::#]member2
- // CHECK-CC1: member3
+ // CHECK-CC1: Base1 (InBase) : Base1::
+ // CHECK-CC1: member1 (InBase) : [#int#][#Base1::#]member1
+ // CHECK-CC1: member1 (InBase) : [#int#][#Base2::#]member1
+ // CHECK-CC1: member2 (InBase) : [#float#][#Base1::#]member2
+ // CHECK-CC1: member3 (InBase)
// CHECK-CC1: member4
- // CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#float#>)
- // CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
- // CHECK-CC1: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>)
- // CHECK-CC1: memfun2 : [#void#][#Base3::#]memfun2(<#int#>)
+ // CHECK-CC1: memfun1 (InBase) : [#void#][#Base3::#]memfun1(<#float#>)
+ // CHECK-CC1: memfun1 (InBase) : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
+ // CHECK-CC1: memfun1 (Hidden,InBase) : [#void#]Base2::memfun1(<#int#>)
+ // CHECK-CC1: memfun2 (InBase) : [#void#][#Base3::#]memfun2(<#int#>)
// CHECK-CC1: memfun3 : [#int#]memfun3(<#int#>)
// Make sure this doesn't crash
@@ -93,12 +93,12 @@ void completeDependentMembers(TemplateClass<T, S> &object,
TemplateClass<int, S> *object2) {
object.field;
object2->field;
-// CHECK-CC2: baseTemplateField : [#T#][#BaseTemplate<T>::#]baseTemplateField
-// CHECK-CC2: baseTemplateFunction : [#T#][#BaseTemplate<T>::#]baseTemplateFunction()
+// CHECK-CC2: baseTemplateField (InBase) : [#T#][#BaseTemplate<T>::#]baseTemplateField
+// CHECK-CC2: baseTemplateFunction (InBase) : [#T#][#BaseTemplate<T>::#]baseTemplateFunction()
// CHECK-CC2: field : [#T#]field
// CHECK-CC2: function : [#T#]function()
-// CHECK-CC2: member1 : [#int#][#Base1::#]member1
-// CHECK-CC2: member2 : [#float#][#Base1::#]member2
+// CHECK-CC2: member1 (InBase) : [#int#][#Base1::#]member1
+// CHECK-CC2: member2 (InBase) : [#float#][#Base1::#]member2
// CHECK-CC2: overload1 : [#void#]overload1(<#const T &#>)
// CHECK-CC2: overload1 : [#void#]overload1(<#const S &#>)
@@ -111,12 +111,12 @@ void completeDependentSpecializedMembers(TemplateClass<int, double> &object,
TemplateClass<int, double> *object2) {
object.field;
object2->field;
-// CHECK-CC3: baseTemplateField : [#int#][#BaseTemplate<int>::#]baseTemplateField
-// CHECK-CC3: baseTemplateFunction : [#int#][#BaseTemplate<int>::#]baseTemplateFunction()
+// CHECK-CC3: baseTemplateField (InBase) : [#int#][#BaseTemplate<int>::#]baseTemplateField
+// CHECK-CC3: baseTemplateFunction (InBase) : [#int#][#BaseTemplate<int>::#]baseTemplateFunction()
// CHECK-CC3: field : [#int#]field
// CHECK-CC3: function : [#int#]function()
-// CHECK-CC3: member1 : [#int#][#Base1::#]member1
-// CHECK-CC3: member2 : [#float#][#Base1::#]member2
+// CHECK-CC3: member1 (InBase) : [#int#][#Base1::#]member1
+// CHECK-CC3: member2 (InBase) : [#float#][#Base1::#]member2
// CHECK-CC3: overload1 : [#void#]overload1(<#const int &#>)
// CHECK-CC3: overload1 : [#void#]overload1(<#const double &#>)
@@ -182,31 +182,31 @@ void test3(const Proxy2 &p) {
}
// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:177:6 %s -o - | FileCheck -check-prefix=CHECK-CC8 --implicit-check-not="Derived : Derived(" %s
-// CHECK-CC8: Base1 : Base1::
-// CHECK-CC8: member1 : [#int#][#Base1::#]member1
-// CHECK-CC8: member1 : [#int#][#Base2::#]member1
-// CHECK-CC8: member2 : [#float#][#Base1::#]member2
-// CHECK-CC8: member3 : [#double#][#Base2::#]member3
+// CHECK-CC8: Base1 (InBase) : Base1::
+// CHECK-CC8: member1 (InBase) : [#int#][#Base1::#]member1
+// CHECK-CC8: member1 (InBase) : [#int#][#Base2::#]member1
+// CHECK-CC8: member2 (InBase) : [#float#][#Base1::#]member2
+// CHECK-CC8: member3 (InBase) : [#double#][#Base2::#]member3
// CHECK-CC8: member4 : [#int#]member4
// CHECK-CC8: member5 : [#int#]member5 (requires fix-it: {177:4-177:6} to ".")
-// CHECK-CC8: memfun1 : [#void#][#Base3::#]memfun1(<#float#>)
-// CHECK-CC8: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
-// CHECK-CC8: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>)
-// CHECK-CC8: memfun2 : [#void#][#Base3::#]memfun2(<#int#>)
+// CHECK-CC8: memfun1 (InBase) : [#void#][#Base3::#]memfun1(<#float#>)
+// CHECK-CC8: memfun1 (InBase) : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
+// CHECK-CC8: memfun1 (Hidden,InBase) : [#void#]Base2::memfun1(<#int#>)
+// CHECK-CC8: memfun2 (InBase) : [#void#][#Base3::#]memfun2(<#int#>)
// CHECK-CC8: memfun3 : [#int#]memfun3(<#int#>)
// CHECK-CC8: operator-> : [#Derived *#]operator->()[# const#] (requires fix-it: {177:4-177:6} to ".")
// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:181:6 %s -o - | FileCheck -check-prefix=CHECK-CC9 --implicit-check-not="Derived : Derived(" %s
-// CHECK-CC9: Base1 : Base1::
-// CHECK-CC9: member1 : [#int#][#Base1::#]member1 (requires fix-it: {181:4-181:5} to "->")
-// CHECK-CC9: member1 : [#int#][#Base2::#]member1 (requires fix-it: {181:4-181:5} to "->")
-// CHECK-CC9: member2 : [#float#][#Base1::#]member2 (requires fix-it: {181:4-181:5} to "->")
-// CHECK-CC9: member3 : [#double#][#Base2::#]member3 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: Base1 (InBase) : Base1::
+// CHECK-CC9: member1 (InBase) : [#int#][#Base1::#]member1 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member1 (InBase) : [#int#][#Base2::#]member1 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member2 (InBase) : [#float#][#Base1::#]member2 (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: member3 (InBase) : [#double#][#Base2::#]member3 (requires fix-it: {181:4-181:5} to "->")
// CHECK-CC9: member4 : [#int#]member4 (requires fix-it: {181:4-181:5} to "->")
// CHECK-CC9: member5 : [#int#]member5
-// CHECK-CC9: memfun1 : [#void#][#Base3::#]memfun1(<#float#>) (requires fix-it: {181:4-181:5} to "->")
-// CHECK-CC9: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#] (requires fix-it: {181:4-181:5} to "->")
-// CHECK-CC9: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>) (requires fix-it: {181:4-181:5} to "->")
-// CHECK-CC9: memfun2 : [#void#][#Base3::#]memfun2(<#int#>) (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun1 (InBase) : [#void#][#Base3::#]memfun1(<#float#>) (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun1 (InBase) : [#void#][#Base3::#]memfun1(<#double#>)[# const#] (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun1 (Hidden,InBase) : [#void#]Base2::memfun1(<#int#>) (requires fix-it: {181:4-181:5} to "->")
+// CHECK-CC9: memfun2 (InBase) : [#void#][#Base3::#]memfun2(<#int#>) (requires fix-it: {181:4-181:5} to "->")
// CHECK-CC9: memfun3 : [#int#]memfun3(<#int#>) (requires fix-it: {181:4-181:5} to "->")
// CHECK-CC9: operator-> : [#Derived *#]operator->()[# const#]
diff --git a/test/CodeCompletion/objc-message.mm b/test/CodeCompletion/objc-message.mm
index 7a503097e076..33f392f5e0dc 100644
--- a/test/CodeCompletion/objc-message.mm
+++ b/test/CodeCompletion/objc-message.mm
@@ -41,6 +41,6 @@ void func(const RetainPtr<id <FooTestProtocol>>& ptr)
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:33:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: categoryInstanceMethod : [#id#]categoryInstanceMethod
// CHECK-CC1: instanceMethod1 : [#id#]instanceMethod1
-// CHECK-CC1: protocolInstanceMethod : [#id#]protocolInstanceMethod
+// CHECK-CC1: protocolInstanceMethod (InBase) : [#id#]protocolInstanceMethod
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:38:8 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: protocolInstanceMethod : [#id#]protocolInstanceMethod
diff --git a/test/CodeCompletion/objc-protocol-member-access.m b/test/CodeCompletion/objc-protocol-member-access.m
index 0ed55387e3d6..9e769d5afa86 100644
--- a/test/CodeCompletion/objc-protocol-member-access.m
+++ b/test/CodeCompletion/objc-protocol-member-access.m
@@ -19,6 +19,6 @@ int getFoo(id object) {
}
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:25 %s -o - | FileCheck %s
-// CHECK: bar : [#int#]bar
-// CHECK: foo : [#int#]foo
+// CHECK: bar (InBase) : [#int#]bar
+// CHECK: foo (InBase) : [#int#]foo
// CHECK-NOT: foobar
diff --git a/test/CodeCompletion/ordinary-name-cxx11.cpp b/test/CodeCompletion/ordinary-name-cxx11.cpp
index 34c3bf96a9d5..0125ffbbb3cf 100644
--- a/test/CodeCompletion/ordinary-name-cxx11.cpp
+++ b/test/CodeCompletion/ordinary-name-cxx11.cpp
@@ -197,7 +197,6 @@ void foo() {
// CHECK-CC4-NEXT: COMPLETION: volatile
// CHECK-CC4-NEXT: COMPLETION: wchar_t
// CHECK-CC4-NEXT: COMPLETION: X : X
- // CHECK-CC4-NEXT: COMPLETION: y : [#int#]y
// CHECK-CC4-NEXT: COMPLETION: z : [#void#]z(<#int#>)
// RUN: %clang_cc1 -fsyntax-only -fno-rtti -code-completion-patterns -code-completion-at=%s:6:14 -std=gnu++11 %s -o - | FileCheck -check-prefix=CHECK-NO-RTTI %s
diff --git a/test/CodeCompletion/ordinary-name.cpp b/test/CodeCompletion/ordinary-name.cpp
index 03dbbcaf7448..ba613bc9152b 100644
--- a/test/CodeCompletion/ordinary-name.cpp
+++ b/test/CodeCompletion/ordinary-name.cpp
@@ -171,7 +171,6 @@ void foo() {
// CHECK-CC4-NEXT: COMPLETION: volatile
// CHECK-CC4-NEXT: COMPLETION: wchar_t
// CHECK-CC4-NEXT: COMPLETION: X : X
- // CHECK-CC4-NEXT: COMPLETION: y : [#int#]y
// CHECK-CC4-NEXT: COMPLETION: z : [#void#]z(<#int#>)
// RUN: %clang_cc1 -fsyntax-only -fno-rtti -code-completion-patterns -code-completion-at=%s:6:14 -std=gnu++98 %s -o - | FileCheck -check-prefix=CHECK-NO-RTTI %s
diff --git a/test/CodeCompletion/overrides.cpp b/test/CodeCompletion/overrides.cpp
new file mode 100644
index 000000000000..06cff6af4d12
--- /dev/null
+++ b/test/CodeCompletion/overrides.cpp
@@ -0,0 +1,33 @@
+class A {
+ public:
+ virtual void vfunc(bool param);
+ virtual void vfunc(bool param, int p);
+ void func(bool param);
+};
+class B : public A {
+virtual int ttt(bool param, int x = 3) const;
+void vfunc(bool param, int p) override;
+};
+class C : public B {
+ public:
+ void vfunc(bool param) override;
+ void
+};
+
+// Runs completion at ^void.
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:3 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}}
+// CHECK-CC1: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
+// CHECK-CC1-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}}
+//
+// Runs completion at vo^id.
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:5 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
+// CHECK-CC2-NOT: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}}
+// CHECK-CC2-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}}
+//
+// Runs completion at void ^.
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:8 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3-NOT: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}}
+// CHECK-CC3-NOT: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
+// CHECK-CC3-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}}
diff --git a/test/CodeCompletion/paren_locs.cpp b/test/CodeCompletion/paren_locs.cpp
new file mode 100644
index 000000000000..303264cff725
--- /dev/null
+++ b/test/CodeCompletion/paren_locs.cpp
@@ -0,0 +1,33 @@
+void foo(int a, int b);
+void foo(int a, int b, int c);
+
+void test() {
+ foo(10, );
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:10 %s -o - \
+ // RUN: | FileCheck -check-prefix=CHECK-CC1 %s
+ // CHECK-CC1: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:5:6
+
+#define FOO foo(
+ FOO 10, );
+#undef FOO
+ // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:11:10 %s -o - \
+ // RUN: | FileCheck -check-prefix=CHECK-CC2 %s
+ // CHECK-CC2: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:11:3
+
+ struct Foo {
+ Foo(int a, int b);
+ Foo(int a, int b, int c);
+ };
+ Foo a(10, );
+ // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:21:12 %s -o - \
+ // RUN: | FileCheck -check-prefix=CHECK-CC3 %s
+ // CHECK-CC3: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:21:8
+ Foo(10, );
+ // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:25:10 %s -o - \
+ // RUN: | FileCheck -check-prefix=CHECK-CC4 %s
+ // CHECK-CC4: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:25:6
+ new Foo(10, );
+ // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:29:15 %s -o - \
+ // RUN: | FileCheck -check-prefix=CHECK-CC5 %s
+ // CHECK-CC5: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:29:10
+}
diff --git a/test/CodeCompletion/pragma-macro-token-caching.c b/test/CodeCompletion/pragma-macro-token-caching.c
index 432706e85ceb..59b6621b56ad 100644
--- a/test/CodeCompletion/pragma-macro-token-caching.c
+++ b/test/CodeCompletion/pragma-macro-token-caching.c
@@ -12,7 +12,7 @@ void completeParam(int param) {
void completeParamPragmaError(int param) {
Outer(__extension__({ _Pragma(2) })); // expected-error {{_Pragma takes a parenthesized string literal}}
- param;
+ param; // expected-warning {{expression result unused}}
}
// RUN: %clang_cc1 -fsyntax-only -verify -code-completion-at=%s:16:1 %s | FileCheck %s
diff --git a/test/CodeCompletion/preferred-type.cpp b/test/CodeCompletion/preferred-type.cpp
new file mode 100644
index 000000000000..5048dfac8954
--- /dev/null
+++ b/test/CodeCompletion/preferred-type.cpp
@@ -0,0 +1,15 @@
+void test(bool x) {
+ if (x) {}
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:7 %s | FileCheck %s
+ // CHECK: PREFERRED-TYPE: _Bool
+
+ while (x) {}
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:6:10 %s | FileCheck %s
+
+ for (; x;) {}
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:9:10 %s | FileCheck %s
+
+ // FIXME(ibiryukov): the condition in do-while is parsed as expression, so we
+ // fail to detect it should be converted to bool.
+ // do {} while (x);
+}
diff --git a/test/CodeCompletion/self-inits.cpp b/test/CodeCompletion/self-inits.cpp
new file mode 100644
index 000000000000..a64209534ae6
--- /dev/null
+++ b/test/CodeCompletion/self-inits.cpp
@@ -0,0 +1,3 @@
+int foo = 10;
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:1:11 %s -o - | FileCheck --check-prefix=CC1 %s
+// CC1-NOT: foo
diff --git a/test/CodeCompletion/signatures-crash.cpp b/test/CodeCompletion/signatures-crash.cpp
new file mode 100644
index 000000000000..c58ae0cc2fd9
--- /dev/null
+++ b/test/CodeCompletion/signatures-crash.cpp
@@ -0,0 +1,15 @@
+struct map {
+ void find(int);
+ void find();
+};
+
+int main() {
+ map *m;
+ m->find(10);
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:8:11 %s -o - | FileCheck %s
+ // CHECK: OVERLOAD: [#void#]find(<#int#>)
+
+ // Also check when the lhs is an explicit pr-value.
+ (m+0)->find(10);
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:13:15 %s -o - | FileCheck %s
+}
diff --git a/test/CodeCompletion/this-quals.cpp b/test/CodeCompletion/this-quals.cpp
new file mode 100644
index 000000000000..eeaed00aa857
--- /dev/null
+++ b/test/CodeCompletion/this-quals.cpp
@@ -0,0 +1,21 @@
+class foo {
+ void mut_func() {
+ [this]() {
+
+ }();
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:4:1 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ // CHECK-CC1: const_func
+ // CHECK-CC1: mut_func
+ }
+
+ void const_func() const {
+ [this]() {
+
+ }();
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:13:1 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+ // CHECK-CC2-NOT: mut_func
+ // CHECK-CC2: const_func
+ };
+};
+
+
diff --git a/test/CodeGen/2007-06-18-SextAttrAggregate.c b/test/CodeGen/2007-06-18-SextAttrAggregate.c
index e781bd567374..4bac5c61bc58 100644
--- a/test/CodeGen/2007-06-18-SextAttrAggregate.c
+++ b/test/CodeGen/2007-06-18-SextAttrAggregate.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -o - -emit-llvm | FileCheck %s
-// XFAIL: aarch64, arm64, x86_64-pc-win32, x86_64-w64-mingw32, x86_64-pc-windows-gnu
+// XFAIL: aarch64, arm64, x86_64-pc-windows-msvc, x86_64-w64-windows-gnu, x86_64-pc-windows-gnu
// PR1513
diff --git a/test/CodeGen/2008-07-31-asm-labels.c b/test/CodeGen/2008-07-31-asm-labels.c
index 733742bd85ed..65a02b6fa00e 100644
--- a/test/CodeGen/2008-07-31-asm-labels.c
+++ b/test/CodeGen/2008-07-31-asm-labels.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -emit-llvm -o %t %s
// RUN: not grep "@pipe()" %t
// RUN: grep '_thisIsNotAPipe' %t | count 3
-// RUN: not grep 'g0' %t
+// RUN: not grep '@g0' %t
// RUN: grep '_renamed' %t | count 2
// RUN: %clang_cc1 -DUSE_DEF -emit-llvm -o %t %s
// RUN: not grep "@pipe()" %t
diff --git a/test/CodeGen/64bit-swiftcall.c b/test/CodeGen/64bit-swiftcall.c
index 7486e44406ed..6175553ec967 100644
--- a/test/CodeGen/64bit-swiftcall.c
+++ b/test/CodeGen/64bit-swiftcall.c
@@ -10,7 +10,7 @@
#define ERROR __attribute__((swift_error_result))
#define CONTEXT __attribute__((swift_context))
-// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, float 0.000000e+00, float 0.000000e+00 }
+// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, i32 0, i32 0 }
/*****************************************************************************/
/****************************** PARAMETER ABIS *******************************/
@@ -102,8 +102,8 @@ typedef struct {
int x;
char c0;
char c1;
- float f0;
- float f1;
+ int f0;
+ int f1;
} struct_1;
TEST(struct_1);
// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_1() {{.*}}{
@@ -150,8 +150,8 @@ typedef struct {
int x;
char c0;
__attribute__((aligned(2))) char c1;
- float f0;
- float f1;
+ int f0;
+ int f1;
} struct_2;
TEST(struct_2);
// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_2() {{.*}}{
@@ -308,20 +308,30 @@ typedef union {
TEST(union_hom_fp_partial)
// CHECK: define void @test_union_hom_fp_partial()
// CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_hom_fp_partial()
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
-// CHECK: store i64 [[T1]], i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK: store i64 [[T1]], i64* [[T0]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK: call swiftcc void @take_union_hom_fp_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: [[CALL:%.*]] = call swiftcc { float, float, float, float } @return_union_hom_fp_partial()
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 0
+// CHECK: store float [[T1]], float* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 1
+// CHECK: store float [[T1]], float* [[T0]], align 4
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 2
+// CHECK: store float [[T1]], float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 3
+// CHECK: store float [[T1]], float* [[T0]], align 4
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load float, float* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load float, float* [[T0]], align 4
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[V2:%.*]] = load float, float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK: [[V3:%.*]] = load float, float* [[T0]], align 4
+// CHECK: call swiftcc void @take_union_hom_fp_partial(float [[V0]], float [[V1]], float [[V2]], float [[V3]])
// CHECK: ret void
// CHECK: }
@@ -332,20 +342,25 @@ typedef union {
TEST(union_het_fpv_partial)
// CHECK-LABEL: define void @test_union_het_fpv_partial()
// CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_het_fpv_partial()
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: [[CALL:%.*]] = call swiftcc { i64, float, float } @return_union_het_fpv_partial()
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 0
// CHECK: store i64 [[T1]], i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK: store i64 [[T1]], i64* [[T0]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 1
+// CHECK: store float [[T1]], float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 2
+// CHECK: store float [[T1]], float* [[T0]], align 4
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load float, float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[V2:%.*]] = load float, float* [[T0]], align 4
+// CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], float [[V1]], float [[V2]])
// CHECK: ret void
// CHECK: }
@@ -464,8 +479,8 @@ typedef struct {
float f1;
} struct_f2;
TEST(struct_f2)
-// CHECK-LABEL: define swiftcc i64 @return_struct_f2()
-// CHECK-LABEL: define swiftcc void @take_struct_f2(i64)
+// CHECK-LABEL: define swiftcc { float, float } @return_struct_f2()
+// CHECK-LABEL: define swiftcc void @take_struct_f2(float, float)
typedef struct {
float f0;
@@ -473,8 +488,8 @@ typedef struct {
float f2;
} struct_f3;
TEST(struct_f3)
-// CHECK-LABEL: define swiftcc { i64, float } @return_struct_f3()
-// CHECK-LABEL: define swiftcc void @take_struct_f3(i64, float)
+// CHECK-LABEL: define swiftcc { float, float, float } @return_struct_f3()
+// CHECK-LABEL: define swiftcc void @take_struct_f3(float, float, float)
typedef struct {
float f0;
@@ -483,8 +498,8 @@ typedef struct {
float f3;
} struct_f4;
TEST(struct_f4)
-// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_f4()
-// CHECK-LABEL: define swiftcc void @take_struct_f4(i64, i64)
+// CHECK-LABEL: define swiftcc { float, float, float, float } @return_struct_f4()
+// CHECK-LABEL: define swiftcc void @take_struct_f4(float, float, float, float)
typedef struct {
@@ -1016,8 +1031,8 @@ typedef union {
float3 fv2;
} union_hom_fp_partial2;
TEST(union_hom_fp_partial2)
-// X86-64-LABEL: take_union_hom_fp_partial2(i64, float)
-// ARM64-LABEL: take_union_hom_fp_partial2(i64, float)
+// X86-64-LABEL: take_union_hom_fp_partial2(float, float, float)
+// ARM64-LABEL: take_union_hom_fp_partial2(float, float, float)
// At one point, we emitted lifetime.ends without a matching lifetime.start for
// CoerceAndExpanded args. Since we're not performing optimizations, neither
diff --git a/test/CodeGen/Inputs/code-coverage-filter1.h b/test/CodeGen/Inputs/code-coverage-filter1.h
new file mode 100644
index 000000000000..4c0de6c5e569
--- /dev/null
+++ b/test/CodeGen/Inputs/code-coverage-filter1.h
@@ -0,0 +1 @@
+void test1() {}
diff --git a/test/CodeGen/Inputs/code-coverage-filter2.h b/test/CodeGen/Inputs/code-coverage-filter2.h
new file mode 100644
index 000000000000..91e68ccae978
--- /dev/null
+++ b/test/CodeGen/Inputs/code-coverage-filter2.h
@@ -0,0 +1 @@
+void test2() {}
diff --git a/test/CodeGen/Inputs/thinlto_backend_local_name_conflict1.ll b/test/CodeGen/Inputs/thinlto_backend_local_name_conflict1.ll
new file mode 100644
index 000000000000..fb5306fc337f
--- /dev/null
+++ b/test/CodeGen/Inputs/thinlto_backend_local_name_conflict1.ll
@@ -0,0 +1,13 @@
+; ModuleID = 'local_name_conflict_var.o'
+source_filename = "local_name_conflict_var.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@baz = internal global i32 10, align 4
+
+; Function Attrs: noinline nounwind uwtable
+define i32 @a() {
+entry:
+ %0 = load i32, i32* @baz, align 4
+ ret i32 %0
+}
diff --git a/test/CodeGen/Inputs/thinlto_backend_local_name_conflict2.ll b/test/CodeGen/Inputs/thinlto_backend_local_name_conflict2.ll
new file mode 100644
index 000000000000..bf3c262f180b
--- /dev/null
+++ b/test/CodeGen/Inputs/thinlto_backend_local_name_conflict2.ll
@@ -0,0 +1,13 @@
+; ModuleID = 'local_name_conflict_var.o'
+source_filename = "local_name_conflict_var.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@baz = internal global i32 10, align 4
+
+; Function Attrs: noinline nounwind uwtable
+define i32 @b() {
+entry:
+ %0 = load i32, i32* @baz, align 4
+ ret i32 %0
+}
diff --git a/test/CodeGen/aapcs-align.cc b/test/CodeGen/aapcs-align.cpp
index 40fba7823524..40fba7823524 100644
--- a/test/CodeGen/aapcs-align.cc
+++ b/test/CodeGen/aapcs-align.cpp
diff --git a/test/CodeGen/aapcs64-align.cc b/test/CodeGen/aapcs64-align.cpp
index 1b7c99ea8719..1b7c99ea8719 100644
--- a/test/CodeGen/aapcs64-align.cc
+++ b/test/CodeGen/aapcs64-align.cpp
diff --git a/test/CodeGen/aarch64-neon-3v.c b/test/CodeGen/aarch64-neon-3v.c
index de38e95c44ea..0ededf940d16 100644
--- a/test/CodeGen/aarch64-neon-3v.c
+++ b/test/CodeGen/aarch64-neon-3v.c
@@ -11,7 +11,7 @@ int8x8_t test_vand_s8(int8x8_t a, int8x8_t b) {
return vand_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vandq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vandq_s8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[AND_I]]
int8x16_t test_vandq_s8(int8x16_t a, int8x16_t b) {
@@ -25,7 +25,7 @@ int16x4_t test_vand_s16(int16x4_t a, int16x4_t b) {
return vand_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vandq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vandq_s16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[AND_I]]
int16x8_t test_vandq_s16(int16x8_t a, int16x8_t b) {
@@ -39,7 +39,7 @@ int32x2_t test_vand_s32(int32x2_t a, int32x2_t b) {
return vand_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vandq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vandq_s32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[AND_I]]
int32x4_t test_vandq_s32(int32x4_t a, int32x4_t b) {
@@ -53,7 +53,7 @@ int64x1_t test_vand_s64(int64x1_t a, int64x1_t b) {
return vand_s64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vandq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vandq_s64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[AND_I]]
int64x2_t test_vandq_s64(int64x2_t a, int64x2_t b) {
@@ -67,7 +67,7 @@ uint8x8_t test_vand_u8(uint8x8_t a, uint8x8_t b) {
return vand_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vandq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vandq_u8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[AND_I]]
uint8x16_t test_vandq_u8(uint8x16_t a, uint8x16_t b) {
@@ -81,7 +81,7 @@ uint16x4_t test_vand_u16(uint16x4_t a, uint16x4_t b) {
return vand_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vandq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vandq_u16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[AND_I]]
uint16x8_t test_vandq_u16(uint16x8_t a, uint16x8_t b) {
@@ -95,7 +95,7 @@ uint32x2_t test_vand_u32(uint32x2_t a, uint32x2_t b) {
return vand_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vandq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vandq_u32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[AND_I]]
uint32x4_t test_vandq_u32(uint32x4_t a, uint32x4_t b) {
@@ -109,7 +109,7 @@ uint64x1_t test_vand_u64(uint64x1_t a, uint64x1_t b) {
return vand_u64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vandq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vandq_u64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[AND_I]]
uint64x2_t test_vandq_u64(uint64x2_t a, uint64x2_t b) {
@@ -123,7 +123,7 @@ int8x8_t test_vorr_s8(int8x8_t a, int8x8_t b) {
return vorr_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vorrq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vorrq_s8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[OR_I]]
int8x16_t test_vorrq_s8(int8x16_t a, int8x16_t b) {
@@ -137,7 +137,7 @@ int16x4_t test_vorr_s16(int16x4_t a, int16x4_t b) {
return vorr_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vorrq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vorrq_s16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[OR_I]]
int16x8_t test_vorrq_s16(int16x8_t a, int16x8_t b) {
@@ -151,7 +151,7 @@ int32x2_t test_vorr_s32(int32x2_t a, int32x2_t b) {
return vorr_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vorrq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vorrq_s32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[OR_I]]
int32x4_t test_vorrq_s32(int32x4_t a, int32x4_t b) {
@@ -165,7 +165,7 @@ int64x1_t test_vorr_s64(int64x1_t a, int64x1_t b) {
return vorr_s64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vorrq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vorrq_s64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[OR_I]]
int64x2_t test_vorrq_s64(int64x2_t a, int64x2_t b) {
@@ -179,7 +179,7 @@ uint8x8_t test_vorr_u8(uint8x8_t a, uint8x8_t b) {
return vorr_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vorrq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vorrq_u8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[OR_I]]
uint8x16_t test_vorrq_u8(uint8x16_t a, uint8x16_t b) {
@@ -193,7 +193,7 @@ uint16x4_t test_vorr_u16(uint16x4_t a, uint16x4_t b) {
return vorr_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vorrq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vorrq_u16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[OR_I]]
uint16x8_t test_vorrq_u16(uint16x8_t a, uint16x8_t b) {
@@ -207,7 +207,7 @@ uint32x2_t test_vorr_u32(uint32x2_t a, uint32x2_t b) {
return vorr_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vorrq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vorrq_u32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[OR_I]]
uint32x4_t test_vorrq_u32(uint32x4_t a, uint32x4_t b) {
@@ -221,7 +221,7 @@ uint64x1_t test_vorr_u64(uint64x1_t a, uint64x1_t b) {
return vorr_u64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vorrq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vorrq_u64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[OR_I]]
uint64x2_t test_vorrq_u64(uint64x2_t a, uint64x2_t b) {
@@ -235,7 +235,7 @@ int8x8_t test_veor_s8(int8x8_t a, int8x8_t b) {
return veor_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_veorq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_veorq_s8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[XOR_I]]
int8x16_t test_veorq_s8(int8x16_t a, int8x16_t b) {
@@ -249,7 +249,7 @@ int16x4_t test_veor_s16(int16x4_t a, int16x4_t b) {
return veor_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_veorq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_veorq_s16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[XOR_I]]
int16x8_t test_veorq_s16(int16x8_t a, int16x8_t b) {
@@ -263,7 +263,7 @@ int32x2_t test_veor_s32(int32x2_t a, int32x2_t b) {
return veor_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_veorq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_veorq_s32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[XOR_I]]
int32x4_t test_veorq_s32(int32x4_t a, int32x4_t b) {
@@ -277,7 +277,7 @@ int64x1_t test_veor_s64(int64x1_t a, int64x1_t b) {
return veor_s64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_veorq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_veorq_s64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[XOR_I]]
int64x2_t test_veorq_s64(int64x2_t a, int64x2_t b) {
@@ -291,7 +291,7 @@ uint8x8_t test_veor_u8(uint8x8_t a, uint8x8_t b) {
return veor_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_veorq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_veorq_u8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[XOR_I]]
uint8x16_t test_veorq_u8(uint8x16_t a, uint8x16_t b) {
@@ -305,7 +305,7 @@ uint16x4_t test_veor_u16(uint16x4_t a, uint16x4_t b) {
return veor_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_veorq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_veorq_u16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[XOR_I]]
uint16x8_t test_veorq_u16(uint16x8_t a, uint16x8_t b) {
@@ -319,7 +319,7 @@ uint32x2_t test_veor_u32(uint32x2_t a, uint32x2_t b) {
return veor_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_veorq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_veorq_u32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[XOR_I]]
uint32x4_t test_veorq_u32(uint32x4_t a, uint32x4_t b) {
@@ -333,7 +333,7 @@ uint64x1_t test_veor_u64(uint64x1_t a, uint64x1_t b) {
return veor_u64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_veorq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_veorq_u64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[XOR_I:%.*]] = xor <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[XOR_I]]
uint64x2_t test_veorq_u64(uint64x2_t a, uint64x2_t b) {
@@ -348,7 +348,7 @@ int8x8_t test_vbic_s8(int8x8_t a, int8x8_t b) {
return vbic_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vbicq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vbicq_s8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[AND_I]]
@@ -364,7 +364,7 @@ int16x4_t test_vbic_s16(int16x4_t a, int16x4_t b) {
return vbic_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vbicq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vbicq_s16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[AND_I]]
@@ -380,7 +380,7 @@ int32x2_t test_vbic_s32(int32x2_t a, int32x2_t b) {
return vbic_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vbicq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vbicq_s32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[AND_I]]
@@ -396,7 +396,7 @@ int64x1_t test_vbic_s64(int64x1_t a, int64x1_t b) {
return vbic_s64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vbicq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vbicq_s64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[AND_I]]
@@ -412,7 +412,7 @@ uint8x8_t test_vbic_u8(uint8x8_t a, uint8x8_t b) {
return vbic_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vbicq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vbicq_u8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[AND_I]]
@@ -428,7 +428,7 @@ uint16x4_t test_vbic_u16(uint16x4_t a, uint16x4_t b) {
return vbic_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vbicq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vbicq_u16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[AND_I]]
@@ -444,7 +444,7 @@ uint32x2_t test_vbic_u32(uint32x2_t a, uint32x2_t b) {
return vbic_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vbicq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vbicq_u32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[AND_I]]
@@ -460,7 +460,7 @@ uint64x1_t test_vbic_u64(uint64x1_t a, uint64x1_t b) {
return vbic_u64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vbicq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vbicq_u64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[AND_I]]
@@ -476,7 +476,7 @@ int8x8_t test_vorn_s8(int8x8_t a, int8x8_t b) {
return vorn_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vornq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vornq_s8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[OR_I]]
@@ -492,7 +492,7 @@ int16x4_t test_vorn_s16(int16x4_t a, int16x4_t b) {
return vorn_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vornq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vornq_s16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[OR_I]]
@@ -508,7 +508,7 @@ int32x2_t test_vorn_s32(int32x2_t a, int32x2_t b) {
return vorn_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vornq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vornq_s32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[OR_I]]
@@ -524,7 +524,7 @@ int64x1_t test_vorn_s64(int64x1_t a, int64x1_t b) {
return vorn_s64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vornq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vornq_s64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[OR_I]]
@@ -540,7 +540,7 @@ uint8x8_t test_vorn_u8(uint8x8_t a, uint8x8_t b) {
return vorn_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vornq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vornq_u8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[OR_I]]
@@ -556,7 +556,7 @@ uint16x4_t test_vorn_u16(uint16x4_t a, uint16x4_t b) {
return vorn_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vornq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vornq_u16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[OR_I]]
@@ -572,7 +572,7 @@ uint32x2_t test_vorn_u32(uint32x2_t a, uint32x2_t b) {
return vorn_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vornq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vornq_u32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[OR_I]]
@@ -588,10 +588,13 @@ uint64x1_t test_vorn_u64(uint64x1_t a, uint64x1_t b) {
return vorn_u64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vornq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vornq_u64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[OR_I]]
uint64x2_t test_vornq_u64(uint64x2_t a, uint64x2_t b) {
return vornq_u64(a, b);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/aarch64-neon-across.c b/test/CodeGen/aarch64-neon-across.c
index 767825461b4c..4431d117a80b 100644
--- a/test/CodeGen/aarch64-neon-across.c
+++ b/test/CodeGen/aarch64-neon-across.c
@@ -6,7 +6,7 @@
#include <arm_neon.h>
// CHECK-LABEL: define i16 @test_vaddlv_s8(<8 x i8> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDLV_I]] to i16
// CHECK: ret i16 [[TMP0]]
int16_t test_vaddlv_s8(int8x8_t a) {
@@ -14,14 +14,14 @@ int16_t test_vaddlv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i32 @test_vaddlv_s16(<4 x i16> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v4i16(<4 x i16> %a) #3
// CHECK: ret i32 [[VADDLV_I]]
int32_t test_vaddlv_s16(int16x4_t a) {
return vaddlv_s16(a);
}
// CHECK-LABEL: define i16 @test_vaddlv_u8(<8 x i8> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDLV_I]] to i16
// CHECK: ret i16 [[TMP0]]
uint16_t test_vaddlv_u8(uint8x8_t a) {
@@ -29,58 +29,58 @@ uint16_t test_vaddlv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i32 @test_vaddlv_u16(<4 x i16> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v4i16(<4 x i16> %a) #3
// CHECK: ret i32 [[VADDLV_I]]
uint32_t test_vaddlv_u16(uint16x4_t a) {
return vaddlv_u16(a);
}
-// CHECK-LABEL: define i16 @test_vaddlvq_s8(<16 x i8> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i16 @test_vaddlvq_s8(<16 x i8> %a) #1 {
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDLV_I]] to i16
// CHECK: ret i16 [[TMP0]]
int16_t test_vaddlvq_s8(int8x16_t a) {
return vaddlvq_s8(a);
}
-// CHECK-LABEL: define i32 @test_vaddlvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i32 @test_vaddlvq_s16(<8 x i16> %a) #1 {
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v8i16(<8 x i16> %a) #3
// CHECK: ret i32 [[VADDLV_I]]
int32_t test_vaddlvq_s16(int16x8_t a) {
return vaddlvq_s16(a);
}
-// CHECK-LABEL: define i64 @test_vaddlvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[VADDLVQ_S32_I:%.*]] = call i64 @llvm.aarch64.neon.saddlv.i64.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i64 @test_vaddlvq_s32(<4 x i32> %a) #1 {
+// CHECK: [[VADDLVQ_S32_I:%.*]] = call i64 @llvm.aarch64.neon.saddlv.i64.v4i32(<4 x i32> %a) #3
// CHECK: ret i64 [[VADDLVQ_S32_I]]
int64_t test_vaddlvq_s32(int32x4_t a) {
return vaddlvq_s32(a);
}
-// CHECK-LABEL: define i16 @test_vaddlvq_u8(<16 x i8> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i16 @test_vaddlvq_u8(<16 x i8> %a) #1 {
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDLV_I]] to i16
// CHECK: ret i16 [[TMP0]]
uint16_t test_vaddlvq_u8(uint8x16_t a) {
return vaddlvq_u8(a);
}
-// CHECK-LABEL: define i32 @test_vaddlvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i32 @test_vaddlvq_u16(<8 x i16> %a) #1 {
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v8i16(<8 x i16> %a) #3
// CHECK: ret i32 [[VADDLV_I]]
uint32_t test_vaddlvq_u16(uint16x8_t a) {
return vaddlvq_u16(a);
}
-// CHECK-LABEL: define i64 @test_vaddlvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[VADDLVQ_U32_I:%.*]] = call i64 @llvm.aarch64.neon.uaddlv.i64.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i64 @test_vaddlvq_u32(<4 x i32> %a) #1 {
+// CHECK: [[VADDLVQ_U32_I:%.*]] = call i64 @llvm.aarch64.neon.uaddlv.i64.v4i32(<4 x i32> %a) #3
// CHECK: ret i64 [[VADDLVQ_U32_I]]
uint64_t test_vaddlvq_u32(uint32x4_t a) {
return vaddlvq_u32(a);
}
// CHECK-LABEL: define i8 @test_vmaxv_s8(<8 x i8> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMAXV_I]] to i8
// CHECK: ret i8 [[TMP0]]
int8_t test_vmaxv_s8(int8x8_t a) {
@@ -88,7 +88,7 @@ int8_t test_vmaxv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vmaxv_s16(<4 x i16> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i16(<4 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vmaxv_s16(int16x4_t a) {
@@ -96,7 +96,7 @@ int16_t test_vmaxv_s16(int16x4_t a) {
}
// CHECK-LABEL: define i8 @test_vmaxv_u8(<8 x i8> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMAXV_I]] to i8
// CHECK: ret i8 [[TMP0]]
uint8_t test_vmaxv_u8(uint8x8_t a) {
@@ -104,61 +104,61 @@ uint8_t test_vmaxv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vmaxv_u16(<4 x i16> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vmaxv_u16(uint16x4_t a) {
return vmaxv_u16(a);
}
-// CHECK-LABEL: define i8 @test_vmaxvq_s8(<16 x i8> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i8 @test_vmaxvq_s8(<16 x i8> %a) #1 {
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMAXV_I]] to i8
// CHECK: ret i8 [[TMP0]]
int8_t test_vmaxvq_s8(int8x16_t a) {
return vmaxvq_s8(a);
}
-// CHECK-LABEL: define i16 @test_vmaxvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i16 @test_vmaxvq_s16(<8 x i16> %a) #1 {
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v8i16(<8 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vmaxvq_s16(int16x8_t a) {
return vmaxvq_s16(a);
}
-// CHECK-LABEL: define i32 @test_vmaxvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[VMAXVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i32 @test_vmaxvq_s32(<4 x i32> %a) #1 {
+// CHECK: [[VMAXVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i32(<4 x i32> %a) #3
// CHECK: ret i32 [[VMAXVQ_S32_I]]
int32_t test_vmaxvq_s32(int32x4_t a) {
return vmaxvq_s32(a);
}
-// CHECK-LABEL: define i8 @test_vmaxvq_u8(<16 x i8> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i8 @test_vmaxvq_u8(<16 x i8> %a) #1 {
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMAXV_I]] to i8
// CHECK: ret i8 [[TMP0]]
uint8_t test_vmaxvq_u8(uint8x16_t a) {
return vmaxvq_u8(a);
}
-// CHECK-LABEL: define i16 @test_vmaxvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i16 @test_vmaxvq_u16(<8 x i16> %a) #1 {
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vmaxvq_u16(uint16x8_t a) {
return vmaxvq_u16(a);
}
-// CHECK-LABEL: define i32 @test_vmaxvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[VMAXVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i32 @test_vmaxvq_u32(<4 x i32> %a) #1 {
+// CHECK: [[VMAXVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i32(<4 x i32> %a) #3
// CHECK: ret i32 [[VMAXVQ_U32_I]]
uint32_t test_vmaxvq_u32(uint32x4_t a) {
return vmaxvq_u32(a);
}
// CHECK-LABEL: define i8 @test_vminv_s8(<8 x i8> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMINV_I]] to i8
// CHECK: ret i8 [[TMP0]]
int8_t test_vminv_s8(int8x8_t a) {
@@ -166,7 +166,7 @@ int8_t test_vminv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vminv_s16(<4 x i16> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i16(<4 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vminv_s16(int16x4_t a) {
@@ -174,7 +174,7 @@ int16_t test_vminv_s16(int16x4_t a) {
}
// CHECK-LABEL: define i8 @test_vminv_u8(<8 x i8> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMINV_I]] to i8
// CHECK: ret i8 [[TMP0]]
uint8_t test_vminv_u8(uint8x8_t a) {
@@ -182,61 +182,61 @@ uint8_t test_vminv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vminv_u16(<4 x i16> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i16(<4 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vminv_u16(uint16x4_t a) {
return vminv_u16(a);
}
-// CHECK-LABEL: define i8 @test_vminvq_s8(<16 x i8> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i8 @test_vminvq_s8(<16 x i8> %a) #1 {
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMINV_I]] to i8
// CHECK: ret i8 [[TMP0]]
int8_t test_vminvq_s8(int8x16_t a) {
return vminvq_s8(a);
}
-// CHECK-LABEL: define i16 @test_vminvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i16 @test_vminvq_s16(<8 x i16> %a) #1 {
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v8i16(<8 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vminvq_s16(int16x8_t a) {
return vminvq_s16(a);
}
-// CHECK-LABEL: define i32 @test_vminvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[VMINVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i32 @test_vminvq_s32(<4 x i32> %a) #1 {
+// CHECK: [[VMINVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i32(<4 x i32> %a) #3
// CHECK: ret i32 [[VMINVQ_S32_I]]
int32_t test_vminvq_s32(int32x4_t a) {
return vminvq_s32(a);
}
-// CHECK-LABEL: define i8 @test_vminvq_u8(<16 x i8> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i8 @test_vminvq_u8(<16 x i8> %a) #1 {
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VMINV_I]] to i8
// CHECK: ret i8 [[TMP0]]
uint8_t test_vminvq_u8(uint8x16_t a) {
return vminvq_u8(a);
}
-// CHECK-LABEL: define i16 @test_vminvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i16 @test_vminvq_u16(<8 x i16> %a) #1 {
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v8i16(<8 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vminvq_u16(uint16x8_t a) {
return vminvq_u16(a);
}
-// CHECK-LABEL: define i32 @test_vminvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[VMINVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i32 @test_vminvq_u32(<4 x i32> %a) #1 {
+// CHECK: [[VMINVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i32(<4 x i32> %a) #3
// CHECK: ret i32 [[VMINVQ_U32_I]]
uint32_t test_vminvq_u32(uint32x4_t a) {
return vminvq_u32(a);
}
// CHECK-LABEL: define i8 @test_vaddv_s8(<8 x i8> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDV_I]] to i8
// CHECK: ret i8 [[TMP0]]
int8_t test_vaddv_s8(int8x8_t a) {
@@ -244,7 +244,7 @@ int8_t test_vaddv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vaddv_s16(<4 x i16> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i16(<4 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vaddv_s16(int16x4_t a) {
@@ -252,7 +252,7 @@ int16_t test_vaddv_s16(int16x4_t a) {
}
// CHECK-LABEL: define i8 @test_vaddv_u8(<8 x i8> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v8i8(<8 x i8> %a) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v8i8(<8 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDV_I]] to i8
// CHECK: ret i8 [[TMP0]]
uint8_t test_vaddv_u8(uint8x8_t a) {
@@ -260,83 +260,86 @@ uint8_t test_vaddv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vaddv_u16(<4 x i16> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16> %a) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vaddv_u16(uint16x4_t a) {
return vaddv_u16(a);
}
-// CHECK-LABEL: define i8 @test_vaddvq_s8(<16 x i8> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i8 @test_vaddvq_s8(<16 x i8> %a) #1 {
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDV_I]] to i8
// CHECK: ret i8 [[TMP0]]
int8_t test_vaddvq_s8(int8x16_t a) {
return vaddvq_s8(a);
}
-// CHECK-LABEL: define i16 @test_vaddvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i16 @test_vaddvq_s16(<8 x i16> %a) #1 {
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v8i16(<8 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vaddvq_s16(int16x8_t a) {
return vaddvq_s16(a);
}
-// CHECK-LABEL: define i32 @test_vaddvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[VADDVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i32 @test_vaddvq_s32(<4 x i32> %a) #1 {
+// CHECK: [[VADDVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i32(<4 x i32> %a) #3
// CHECK: ret i32 [[VADDVQ_S32_I]]
int32_t test_vaddvq_s32(int32x4_t a) {
return vaddvq_s32(a);
}
-// CHECK-LABEL: define i8 @test_vaddvq_u8(<16 x i8> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v16i8(<16 x i8> %a) #2
+// CHECK-LABEL: define i8 @test_vaddvq_u8(<16 x i8> %a) #1 {
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v16i8(<16 x i8> %a) #3
// CHECK: [[TMP0:%.*]] = trunc i32 [[VADDV_I]] to i8
// CHECK: ret i8 [[TMP0]]
uint8_t test_vaddvq_u8(uint8x16_t a) {
return vaddvq_u8(a);
}
-// CHECK-LABEL: define i16 @test_vaddvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v8i16(<8 x i16> %a) #2
+// CHECK-LABEL: define i16 @test_vaddvq_u16(<8 x i16> %a) #1 {
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v8i16(<8 x i16> %a) #3
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vaddvq_u16(uint16x8_t a) {
return vaddvq_u16(a);
}
-// CHECK-LABEL: define i32 @test_vaddvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[VADDVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32> %a) #2
+// CHECK-LABEL: define i32 @test_vaddvq_u32(<4 x i32> %a) #1 {
+// CHECK: [[VADDVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32> %a) #3
// CHECK: ret i32 [[VADDVQ_U32_I]]
uint32_t test_vaddvq_u32(uint32x4_t a) {
return vaddvq_u32(a);
}
-// CHECK-LABEL: define float @test_vmaxvq_f32(<4 x float> %a) #0 {
-// CHECK: [[VMAXVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define float @test_vmaxvq_f32(<4 x float> %a) #1 {
+// CHECK: [[VMAXVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float> %a) #3
// CHECK: ret float [[VMAXVQ_F32_I]]
float32_t test_vmaxvq_f32(float32x4_t a) {
return vmaxvq_f32(a);
}
-// CHECK-LABEL: define float @test_vminvq_f32(<4 x float> %a) #0 {
-// CHECK: [[VMINVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define float @test_vminvq_f32(<4 x float> %a) #1 {
+// CHECK: [[VMINVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> %a) #3
// CHECK: ret float [[VMINVQ_F32_I]]
float32_t test_vminvq_f32(float32x4_t a) {
return vminvq_f32(a);
}
-// CHECK-LABEL: define float @test_vmaxnmvq_f32(<4 x float> %a) #0 {
-// CHECK: [[VMAXNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define float @test_vmaxnmvq_f32(<4 x float> %a) #1 {
+// CHECK: [[VMAXNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float> %a) #3
// CHECK: ret float [[VMAXNMVQ_F32_I]]
float32_t test_vmaxnmvq_f32(float32x4_t a) {
return vmaxnmvq_f32(a);
}
-// CHECK-LABEL: define float @test_vminnmvq_f32(<4 x float> %a) #0 {
-// CHECK: [[VMINNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define float @test_vminnmvq_f32(<4 x float> %a) #1 {
+// CHECK: [[VMINNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> %a) #3
// CHECK: ret float [[VMINNMVQ_F32_I]]
float32_t test_vminnmvq_f32(float32x4_t a) {
return vminnmvq_f32(a);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/aarch64-neon-extract.c b/test/CodeGen/aarch64-neon-extract.c
index 6b62d9f1cff7..cd40b311390d 100644
--- a/test/CodeGen/aarch64-neon-extract.c
+++ b/test/CodeGen/aarch64-neon-extract.c
@@ -46,14 +46,14 @@ int64x1_t test_vext_s64(int64x1_t a, int64x1_t b) {
return vext_s64(a, b, 0);
}
-// CHECK-LABEL: define <16 x i8> @test_vextq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vextq_s8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[VEXT:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17>
// CHECK: ret <16 x i8> [[VEXT]]
int8x16_t test_vextq_s8(int8x16_t a, int8x16_t b) {
return vextq_s8(a, b, 2);
}
-// CHECK-LABEL: define <8 x i16> @test_vextq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vextq_s16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -64,7 +64,7 @@ int16x8_t test_vextq_s16(int16x8_t a, int16x8_t b) {
return vextq_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vextq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vextq_s32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -75,7 +75,7 @@ int32x4_t test_vextq_s32(int32x4_t a, int32x4_t b) {
return vextq_s32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vextq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vextq_s64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -126,14 +126,14 @@ uint64x1_t test_vext_u64(uint64x1_t a, uint64x1_t b) {
return vext_u64(a, b, 0);
}
-// CHECK-LABEL: define <16 x i8> @test_vextq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vextq_u8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[VEXT:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17>
// CHECK: ret <16 x i8> [[VEXT]]
uint8x16_t test_vextq_u8(uint8x16_t a, uint8x16_t b) {
return vextq_u8(a, b, 2);
}
-// CHECK-LABEL: define <8 x i16> @test_vextq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vextq_u16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -144,7 +144,7 @@ uint16x8_t test_vextq_u16(uint16x8_t a, uint16x8_t b) {
return vextq_u16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vextq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vextq_u32(<4 x i32> %a, <4 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -155,7 +155,7 @@ uint32x4_t test_vextq_u32(uint32x4_t a, uint32x4_t b) {
return vextq_u32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vextq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vextq_u64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -188,7 +188,7 @@ float64x1_t test_vext_f64(float64x1_t a, float64x1_t b) {
return vext_f64(a, b, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vextq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: define <4 x float> @test_vextq_f32(<4 x float> %a, <4 x float> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
@@ -199,7 +199,7 @@ float32x4_t test_vextq_f32(float32x4_t a, float32x4_t b) {
return vextq_f32(a, b, 1);
}
-// CHECK-LABEL: define <2 x double> @test_vextq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: define <2 x double> @test_vextq_f64(<2 x double> %a, <2 x double> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
@@ -228,14 +228,14 @@ poly16x4_t test_vext_p16(poly16x4_t a, poly16x4_t b) {
return vext_p16(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vextq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vextq_p8(<16 x i8> %a, <16 x i8> %b) #1 {
// CHECK: [[VEXT:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17>
// CHECK: ret <16 x i8> [[VEXT]]
poly8x16_t test_vextq_p8(poly8x16_t a, poly8x16_t b) {
return vextq_p8(a, b, 2);
}
-// CHECK-LABEL: define <8 x i16> @test_vextq_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vextq_p16(<8 x i16> %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
diff --git a/test/CodeGen/aarch64-neon-fma.c b/test/CodeGen/aarch64-neon-fma.c
index 3a84834e1176..564bd37e7895 100644
--- a/test/CodeGen/aarch64-neon-fma.c
+++ b/test/CodeGen/aarch64-neon-fma.c
@@ -14,7 +14,7 @@ float32x2_t test_vmla_n_f32(float32x2_t a, float32x2_t b, float32_t c) {
return vmla_n_f32(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_n_f32(<4 x float> %a, <4 x float> %b, float %c) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlaq_n_f32(<4 x float> %a, <4 x float> %b, float %c) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %c, i32 2
@@ -26,7 +26,7 @@ float32x4_t test_vmlaq_n_f32(float32x4_t a, float32x4_t b, float32_t c) {
return vmlaq_n_f32(a, b, c);
}
-// CHECK-LABEL: define <2 x double> @test_vmlaq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #0 {
+// CHECK-LABEL: define <2 x double> @test_vmlaq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x double> undef, double %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x double> [[VECINIT_I]], double %c, i32 1
// CHECK: [[MUL_I:%.*]] = fmul <2 x double> %b, [[VECINIT1_I]]
@@ -36,7 +36,7 @@ float64x2_t test_vmlaq_n_f64(float64x2_t a, float64x2_t b, float64_t c) {
return vmlaq_n_f64(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_n_f32(<4 x float> %a, <4 x float> %b, float %c) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlsq_n_f32(<4 x float> %a, <4 x float> %b, float %c) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %c, i32 2
@@ -58,7 +58,7 @@ float32x2_t test_vmls_n_f32(float32x2_t a, float32x2_t b, float32_t c) {
return vmls_n_f32(a, b, c);
}
-// CHECK-LABEL: define <2 x double> @test_vmlsq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #0 {
+// CHECK-LABEL: define <2 x double> @test_vmlsq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x double> undef, double %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x double> [[VECINIT_I]], double %c, i32 1
// CHECK: [[MUL_I:%.*]] = fmul <2 x double> %b, [[VECINIT1_I]]
@@ -77,7 +77,7 @@ float32x2_t test_vmla_lane_f32_0(float32x2_t a, float32x2_t b, float32x2_t v) {
return vmla_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_lane_f32_0(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlaq_lane_f32_0(<4 x float> %a, <4 x float> %b, <2 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <4 x float> %a, [[MUL]]
@@ -86,7 +86,7 @@ float32x4_t test_vmlaq_lane_f32_0(float32x4_t a, float32x4_t b, float32x2_t v) {
return vmlaq_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmla_laneq_f32_0(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <2 x float> @test_vmla_laneq_f32_0(<2 x float> %a, <2 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <2 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <2 x float> %a, [[MUL]]
@@ -95,7 +95,7 @@ float32x2_t test_vmla_laneq_f32_0(float32x2_t a, float32x2_t b, float32x4_t v) {
return vmla_laneq_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_laneq_f32_0(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlaq_laneq_f32_0(<4 x float> %a, <4 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <4 x float> %a, [[MUL]]
@@ -113,7 +113,7 @@ float32x2_t test_vmls_lane_f32_0(float32x2_t a, float32x2_t b, float32x2_t v) {
return vmls_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_lane_f32_0(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlsq_lane_f32_0(<4 x float> %a, <4 x float> %b, <2 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <4 x float> %a, [[MUL]]
@@ -122,7 +122,7 @@ float32x4_t test_vmlsq_lane_f32_0(float32x4_t a, float32x4_t b, float32x2_t v) {
return vmlsq_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmls_laneq_f32_0(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <2 x float> @test_vmls_laneq_f32_0(<2 x float> %a, <2 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <2 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <2 x float> %a, [[MUL]]
@@ -131,7 +131,7 @@ float32x2_t test_vmls_laneq_f32_0(float32x2_t a, float32x2_t b, float32x4_t v) {
return vmls_laneq_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_laneq_f32_0(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlsq_laneq_f32_0(<4 x float> %a, <4 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <4 x float> %a, [[MUL]]
@@ -149,7 +149,7 @@ float32x2_t test_vmla_lane_f32(float32x2_t a, float32x2_t b, float32x2_t v) {
return vmla_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlaq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <4 x float> %a, [[MUL]]
@@ -158,7 +158,7 @@ float32x4_t test_vmlaq_lane_f32(float32x4_t a, float32x4_t b, float32x2_t v) {
return vmlaq_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vmla_laneq_f32(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <2 x float> @test_vmla_laneq_f32(<2 x float> %a, <2 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = fmul <2 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <2 x float> %a, [[MUL]]
@@ -167,7 +167,7 @@ float32x2_t test_vmla_laneq_f32(float32x2_t a, float32x2_t b, float32x4_t v) {
return vmla_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_laneq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlaq_laneq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <4 x float> %a, [[MUL]]
@@ -185,7 +185,7 @@ float32x2_t test_vmls_lane_f32(float32x2_t a, float32x2_t b, float32x2_t v) {
return vmls_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlsq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <4 x float> %a, [[MUL]]
@@ -193,7 +193,7 @@ float32x2_t test_vmls_lane_f32(float32x2_t a, float32x2_t b, float32x2_t v) {
float32x4_t test_vmlsq_lane_f32(float32x4_t a, float32x4_t b, float32x2_t v) {
return vmlsq_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vmls_laneq_f32(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <2 x float> @test_vmls_laneq_f32(<2 x float> %a, <2 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = fmul <2 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <2 x float> %a, [[MUL]]
@@ -202,7 +202,7 @@ float32x2_t test_vmls_laneq_f32(float32x2_t a, float32x2_t b, float32x4_t v) {
return vmls_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_laneq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: define <4 x float> @test_vmlsq_laneq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %v) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <4 x float> %a, [[MUL]]
@@ -211,7 +211,7 @@ float32x4_t test_vmlsq_laneq_f32(float32x4_t a, float32x4_t b, float32x4_t v) {
return vmlsq_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x double> @test_vfmaq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #0 {
+// CHECK-LABEL: define <2 x double> @test_vfmaq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x double> undef, double %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x double> [[VECINIT_I]], double %c, i32 1
// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> [[VECINIT1_I]], <2 x double> %a)
@@ -220,12 +220,15 @@ float64x2_t test_vfmaq_n_f64(float64x2_t a, float64x2_t b, float64_t c) {
return vfmaq_n_f64(a, b, c);
}
-// CHECK-LABEL: define <2 x double> @test_vfmsq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #0 {
+// CHECK-LABEL: define <2 x double> @test_vfmsq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #1 {
// CHECK: [[SUB_I:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %b
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x double> undef, double %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x double> [[VECINIT_I]], double %c, i32 1
-// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[SUB_I]], <2 x double> [[VECINIT1_I]], <2 x double> %a) #2
+// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[SUB_I]], <2 x double> [[VECINIT1_I]], <2 x double> %a) #3
// CHECK: ret <2 x double> [[TMP6]]
float64x2_t test_vfmsq_n_f64(float64x2_t a, float64x2_t b, float64_t c) {
return vfmsq_n_f64(a, b, c);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/aarch64-neon-fp16fml.c b/test/CodeGen/aarch64-neon-fp16fml.c
new file mode 100644
index 000000000000..ad3dd9c22689
--- /dev/null
+++ b/test/CodeGen/aarch64-neon-fp16fml.c
@@ -0,0 +1,196 @@
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +v8.2a -target-feature +neon -target-feature +fp16fml \
+// RUN: -fallow-half-arguments-and-returns -disable-O0-optnone -emit-llvm -o - %s | opt -S -instcombine | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+// Test AArch64 Armv8.2-A FP16 Fused Multiply-Add Long intrinsics
+
+#include <arm_neon.h>
+
+// Vector form
+
+float32x2_t test_vfmlal_low_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlal_low_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlal.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlal_low_u32(a, b, c);
+}
+
+float32x2_t test_vfmlsl_low_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlsl_low_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlsl.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlsl_low_u32(a, b, c);
+}
+
+float32x2_t test_vfmlal_high_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlal_high_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlal2.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlal_high_u32(a, b, c);
+}
+
+float32x2_t test_vfmlsl_high_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlsl_high_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlsl2.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlsl_high_u32(a, b, c);
+}
+
+float32x4_t test_vfmlalq_low_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlalq_low_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlal.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlalq_low_u32(a, b, c);
+}
+
+float32x4_t test_vfmlslq_low_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlslq_low_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlsl.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlslq_low_u32(a, b, c);
+}
+
+float32x4_t test_vfmlalq_high_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlalq_high_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlal2.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlalq_high_u32(a, b, c);
+}
+
+float32x4_t test_vfmlslq_high_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlslq_high_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlsl2.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlslq_high_u32(a, b, c);
+}
+
+// Indexed form
+
+float32x2_t test_vfmlal_lane_low_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlal_lane_low_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <4 x i32> zeroinitializer
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlal.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlal_lane_low_u32(a, b, c, 0);
+}
+
+float32x2_t test_vfmlal_lane_high_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlal_lane_high_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlal2.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlal_lane_high_u32(a, b, c, 1);
+}
+
+float32x4_t test_vfmlalq_lane_low_u32(float32x4_t a, float16x8_t b, float16x4_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlalq_lane_low_u32(<4 x float> %a, <8 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlal.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlalq_lane_low_u32(a, b, c, 2);
+}
+
+float32x4_t test_vfmlalq_lane_high_u32(float32x4_t a, float16x8_t b, float16x4_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlalq_lane_high_u32(<4 x float> %a, <8 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlal2.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlalq_lane_high_u32(a, b, c, 3);
+}
+
+float32x2_t test_vfmlal_laneq_low_u32(float32x2_t a, float16x4_t b, float16x8_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlal_laneq_low_u32(<2 x float> %a, <4 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <4 x i32> <i32 4, i32 4, i32 4, i32 4>
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlal.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlal_laneq_low_u32(a, b, c, 4);
+}
+
+float32x2_t test_vfmlal_laneq_high_u32(float32x2_t a, float16x4_t b, float16x8_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlal_laneq_high_u32(<2 x float> %a, <4 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlal2.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlal_laneq_high_u32(a, b, c, 5);
+}
+
+float32x4_t test_vfmlalq_laneq_low_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlalq_laneq_low_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <8 x i32> <i32 6, i32 6, i32 6, i32 6, i32 6, i32 6, i32 6, i32 6>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlal.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlalq_laneq_low_u32(a, b, c, 6);
+}
+
+float32x4_t test_vfmlalq_laneq_high_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlalq_laneq_high_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlal2.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlalq_laneq_high_u32(a, b, c, 7);
+}
+
+float32x2_t test_vfmlsl_lane_low_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlsl_lane_low_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <4 x i32> zeroinitializer
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlsl.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlsl_lane_low_u32(a, b, c, 0);
+}
+
+float32x2_t test_vfmlsl_lane_high_u32(float32x2_t a, float16x4_t b, float16x4_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlsl_lane_high_u32(<2 x float> %a, <4 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlsl2.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlsl_lane_high_u32(a, b, c, 1);
+}
+
+float32x4_t test_vfmlslq_lane_low_u32(float32x4_t a, float16x8_t b, float16x4_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlslq_lane_low_u32(<4 x float> %a, <8 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlsl.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlslq_lane_low_u32(a, b, c, 2);
+}
+
+float32x4_t test_vfmlslq_lane_high_u32(float32x4_t a, float16x8_t b, float16x4_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlslq_lane_high_u32(<4 x float> %a, <8 x half> %b, <4 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x half> %c, <4 x half> undef, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlsl2.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlslq_lane_high_u32(a, b, c, 3);
+}
+
+float32x2_t test_vfmlsl_laneq_low_u32(float32x2_t a, float16x4_t b, float16x8_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlsl_laneq_low_u32(<2 x float> %a, <4 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <4 x i32> <i32 4, i32 4, i32 4, i32 4>
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlsl.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlsl_laneq_low_u32(a, b, c, 4);
+}
+
+float32x2_t test_vfmlsl_laneq_high_u32(float32x2_t a, float16x4_t b, float16x8_t c) {
+// CHECK-LABEL: define <2 x float> @test_vfmlsl_laneq_high_u32(<2 x float> %a, <4 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <4 x i32> <i32 5, i32 5, i32 5, i32 5>
+// CHECK: [[RESULT:%.*]] = call <2 x float> @llvm.aarch64.neon.fmlsl2.v2f32.v4f16(<2 x float> %a, <4 x half> %b, <4 x half> [[SHUFFLE]])
+// CHECK: ret <2 x float> [[RESULT]]
+ return vfmlsl_laneq_high_u32(a, b, c, 5);
+}
+
+float32x4_t test_vfmlslq_laneq_low_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlslq_laneq_low_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <8 x i32> <i32 6, i32 6, i32 6, i32 6, i32 6, i32 6, i32 6, i32 6>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlsl.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlslq_laneq_low_u32(a, b, c, 6);
+}
+
+float32x4_t test_vfmlslq_laneq_high_u32(float32x4_t a, float16x8_t b, float16x8_t c) {
+// CHECK-LABEL: define <4 x float> @test_vfmlslq_laneq_high_u32(<4 x float> %a, <8 x half> %b, <8 x half> %c)
+// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x half> %c, <8 x half> undef, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+// CHECK: [[RESULT:%.*]] = call <4 x float> @llvm.aarch64.neon.fmlsl2.v4f32.v8f16(<4 x float> %a, <8 x half> %b, <8 x half> [[SHUFFLE]])
+// CHECK: ret <4 x float> [[RESULT]]
+ return vfmlslq_laneq_high_u32(a, b, c, 7);
+}
diff --git a/test/CodeGen/aarch64-neon-ldst-one.c b/test/CodeGen/aarch64-neon-ldst-one.c
index 592b2ceffa6a..0d20982408cf 100644
--- a/test/CodeGen/aarch64-neon-ldst-one.c
+++ b/test/CodeGen/aarch64-neon-ldst-one.c
@@ -152,7 +152,7 @@ poly64x2_t test_vld1q_dup_p64(poly64_t *a) {
return vld1q_dup_p64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_dup_u8(i8* %a) #0 {
+// CHECK-LABEL: define <8 x i8> @test_vld1_dup_u8(i8* %a) #1 {
// CHECK: [[TMP0:%.*]] = load i8, i8* %a
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
@@ -161,7 +161,7 @@ uint8x8_t test_vld1_dup_u8(uint8_t *a) {
return vld1_dup_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_dup_u16(i16* %a) #0 {
+// CHECK-LABEL: define <4 x i16> @test_vld1_dup_u16(i16* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]]
@@ -172,7 +172,7 @@ uint16x4_t test_vld1_dup_u16(uint16_t *a) {
return vld1_dup_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_dup_u32(i32* %a) #0 {
+// CHECK-LABEL: define <2 x i32> @test_vld1_dup_u32(i32* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
// CHECK: [[TMP2:%.*]] = load i32, i32* [[TMP1]]
@@ -183,7 +183,7 @@ uint32x2_t test_vld1_dup_u32(uint32_t *a) {
return vld1_dup_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_dup_u64(i64* %a) #0 {
+// CHECK-LABEL: define <1 x i64> @test_vld1_dup_u64(i64* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i64*
// CHECK: [[TMP2:%.*]] = load i64, i64* [[TMP1]]
@@ -194,7 +194,7 @@ uint64x1_t test_vld1_dup_u64(uint64_t *a) {
return vld1_dup_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_dup_s8(i8* %a) #0 {
+// CHECK-LABEL: define <8 x i8> @test_vld1_dup_s8(i8* %a) #1 {
// CHECK: [[TMP0:%.*]] = load i8, i8* %a
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
@@ -203,7 +203,7 @@ int8x8_t test_vld1_dup_s8(int8_t *a) {
return vld1_dup_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_dup_s16(i16* %a) #0 {
+// CHECK-LABEL: define <4 x i16> @test_vld1_dup_s16(i16* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]]
@@ -214,7 +214,7 @@ int16x4_t test_vld1_dup_s16(int16_t *a) {
return vld1_dup_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_dup_s32(i32* %a) #0 {
+// CHECK-LABEL: define <2 x i32> @test_vld1_dup_s32(i32* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
// CHECK: [[TMP2:%.*]] = load i32, i32* [[TMP1]]
@@ -225,7 +225,7 @@ int32x2_t test_vld1_dup_s32(int32_t *a) {
return vld1_dup_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_dup_s64(i64* %a) #0 {
+// CHECK-LABEL: define <1 x i64> @test_vld1_dup_s64(i64* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i64*
// CHECK: [[TMP2:%.*]] = load i64, i64* [[TMP1]]
@@ -236,7 +236,7 @@ int64x1_t test_vld1_dup_s64(int64_t *a) {
return vld1_dup_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vld1_dup_f16(half* %a) #0 {
+// CHECK-LABEL: define <4 x half> @test_vld1_dup_f16(half* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to half*
// CHECK: [[TMP2:%.*]] = load half, half* [[TMP1]]
@@ -247,7 +247,7 @@ float16x4_t test_vld1_dup_f16(float16_t *a) {
return vld1_dup_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vld1_dup_f32(float* %a) #0 {
+// CHECK-LABEL: define <2 x float> @test_vld1_dup_f32(float* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to float*
// CHECK: [[TMP2:%.*]] = load float, float* [[TMP1]]
@@ -258,7 +258,7 @@ float32x2_t test_vld1_dup_f32(float32_t *a) {
return vld1_dup_f32(a);
}
-// CHECK-LABEL: define <1 x double> @test_vld1_dup_f64(double* %a) #0 {
+// CHECK-LABEL: define <1 x double> @test_vld1_dup_f64(double* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast double* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to double*
// CHECK: [[TMP2:%.*]] = load double, double* [[TMP1]]
@@ -269,7 +269,7 @@ float64x1_t test_vld1_dup_f64(float64_t *a) {
return vld1_dup_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_dup_p8(i8* %a) #0 {
+// CHECK-LABEL: define <8 x i8> @test_vld1_dup_p8(i8* %a) #1 {
// CHECK: [[TMP0:%.*]] = load i8, i8* %a
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
@@ -278,7 +278,7 @@ poly8x8_t test_vld1_dup_p8(poly8_t *a) {
return vld1_dup_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_dup_p16(i16* %a) #0 {
+// CHECK-LABEL: define <4 x i16> @test_vld1_dup_p16(i16* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]]
@@ -289,7 +289,7 @@ poly16x4_t test_vld1_dup_p16(poly16_t *a) {
return vld1_dup_p16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_dup_p64(i64* %a) #0 {
+// CHECK-LABEL: define <1 x i64> @test_vld1_dup_p64(i64* %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i64*
// CHECK: [[TMP2:%.*]] = load i64, i64* [[TMP1]]
@@ -300,7 +300,7 @@ poly64x1_t test_vld1_dup_p64(poly64_t *a) {
return vld1_dup_p64(a);
}
-// CHECK-LABEL: define %struct.uint64x2x2_t @test_vld2q_dup_u64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.uint64x2x2_t @test_vld2q_dup_u64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__RET]] to i8*
@@ -318,7 +318,7 @@ uint64x2x2_t test_vld2q_dup_u64(uint64_t *a) {
return vld2q_dup_u64(a);
}
-// CHECK-LABEL: define %struct.int64x2x2_t @test_vld2q_dup_s64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.int64x2x2_t @test_vld2q_dup_s64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__RET]] to i8*
@@ -336,7 +336,7 @@ int64x2x2_t test_vld2q_dup_s64(int64_t *a) {
return vld2q_dup_s64(a);
}
-// CHECK-LABEL: define %struct.float64x2x2_t @test_vld2q_dup_f64(double* %a) #0 {
+// CHECK-LABEL: define %struct.float64x2x2_t @test_vld2q_dup_f64(double* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
@@ -354,7 +354,7 @@ float64x2x2_t test_vld2q_dup_f64(float64_t *a) {
return vld2q_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_dup_p64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_dup_p64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
@@ -372,7 +372,7 @@ poly64x2x2_t test_vld2q_dup_p64(poly64_t *a) {
return vld2q_dup_p64(a);
}
-// CHECK-LABEL: define %struct.float64x1x2_t @test_vld2_dup_f64(double* %a) #0 {
+// CHECK-LABEL: define %struct.float64x1x2_t @test_vld2_dup_f64(double* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
@@ -390,7 +390,7 @@ float64x1x2_t test_vld2_dup_f64(float64_t *a) {
return vld2_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_dup_p64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_dup_p64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
@@ -408,7 +408,7 @@ poly64x1x2_t test_vld2_dup_p64(poly64_t *a) {
return vld2_dup_p64(a);
}
-// CHECK-LABEL: define %struct.uint64x2x3_t @test_vld3q_dup_u64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.uint64x2x3_t @test_vld3q_dup_u64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__RET]] to i8*
@@ -427,7 +427,7 @@ uint64x2x3_t test_vld3q_dup_u64(uint64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.int64x2x3_t @test_vld3q_dup_s64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.int64x2x3_t @test_vld3q_dup_s64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__RET]] to i8*
@@ -446,7 +446,7 @@ int64x2x3_t test_vld3q_dup_s64(int64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.float64x2x3_t @test_vld3q_dup_f64(double* %a) #0 {
+// CHECK-LABEL: define %struct.float64x2x3_t @test_vld3q_dup_f64(double* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
@@ -465,7 +465,7 @@ float64x2x3_t test_vld3q_dup_f64(float64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_dup_p64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_dup_p64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
@@ -484,7 +484,7 @@ poly64x2x3_t test_vld3q_dup_p64(poly64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.float64x1x3_t @test_vld3_dup_f64(double* %a) #0 {
+// CHECK-LABEL: define %struct.float64x1x3_t @test_vld3_dup_f64(double* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
@@ -503,7 +503,7 @@ float64x1x3_t test_vld3_dup_f64(float64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_dup_p64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_dup_p64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
@@ -522,7 +522,7 @@ poly64x1x3_t test_vld3_dup_p64(poly64_t *a) {
// [{{x[0-9]+|sp}}]
}
-// CHECK-LABEL: define %struct.uint64x2x4_t @test_vld4q_dup_u64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.uint64x2x4_t @test_vld4q_dup_u64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__RET]] to i8*
@@ -540,7 +540,7 @@ uint64x2x4_t test_vld4q_dup_u64(uint64_t *a) {
return vld4q_dup_u64(a);
}
-// CHECK-LABEL: define %struct.int64x2x4_t @test_vld4q_dup_s64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.int64x2x4_t @test_vld4q_dup_s64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__RET]] to i8*
@@ -558,7 +558,7 @@ int64x2x4_t test_vld4q_dup_s64(int64_t *a) {
return vld4q_dup_s64(a);
}
-// CHECK-LABEL: define %struct.float64x2x4_t @test_vld4q_dup_f64(double* %a) #0 {
+// CHECK-LABEL: define %struct.float64x2x4_t @test_vld4q_dup_f64(double* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
@@ -576,7 +576,7 @@ float64x2x4_t test_vld4q_dup_f64(float64_t *a) {
return vld4q_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_dup_p64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_dup_p64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
@@ -594,7 +594,7 @@ poly64x2x4_t test_vld4q_dup_p64(poly64_t *a) {
return vld4q_dup_p64(a);
}
-// CHECK-LABEL: define %struct.float64x1x4_t @test_vld4_dup_f64(double* %a) #0 {
+// CHECK-LABEL: define %struct.float64x1x4_t @test_vld4_dup_f64(double* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
@@ -612,7 +612,7 @@ float64x1x4_t test_vld4_dup_f64(float64_t *a) {
return vld4_dup_f64(a);
}
-// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_dup_p64(i64* %a) #0 {
+// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_dup_p64(i64* %a) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
@@ -786,7 +786,7 @@ poly64x2_t test_vld1q_lane_p64(poly64_t *a, poly64x2_t b) {
return vld1q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_lane_u8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: define <8 x i8> @test_vld1_lane_u8(i8* %a, <8 x i8> %b) #1 {
// CHECK: [[TMP0:%.*]] = load i8, i8* %a
// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i8> %b, i8 [[TMP0]], i32 7
// CHECK: ret <8 x i8> [[VLD1_LANE]]
@@ -794,7 +794,7 @@ uint8x8_t test_vld1_lane_u8(uint8_t *a, uint8x8_t b) {
return vld1_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_lane_u16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: define <4 x i16> @test_vld1_lane_u16(i16* %a, <4 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -806,7 +806,7 @@ uint16x4_t test_vld1_lane_u16(uint16_t *a, uint16x4_t b) {
return vld1_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_lane_u32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: define <2 x i32> @test_vld1_lane_u32(i32* %a, <2 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -818,7 +818,7 @@ uint32x2_t test_vld1_lane_u32(uint32_t *a, uint32x2_t b) {
return vld1_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_lane_u64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: define <1 x i64> @test_vld1_lane_u64(i64* %a, <1 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -830,7 +830,7 @@ uint64x1_t test_vld1_lane_u64(uint64_t *a, uint64x1_t b) {
return vld1_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_lane_s8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: define <8 x i8> @test_vld1_lane_s8(i8* %a, <8 x i8> %b) #1 {
// CHECK: [[TMP0:%.*]] = load i8, i8* %a
// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i8> %b, i8 [[TMP0]], i32 7
// CHECK: ret <8 x i8> [[VLD1_LANE]]
@@ -838,7 +838,7 @@ int8x8_t test_vld1_lane_s8(int8_t *a, int8x8_t b) {
return vld1_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_lane_s16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: define <4 x i16> @test_vld1_lane_s16(i16* %a, <4 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -850,7 +850,7 @@ int16x4_t test_vld1_lane_s16(int16_t *a, int16x4_t b) {
return vld1_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_lane_s32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: define <2 x i32> @test_vld1_lane_s32(i32* %a, <2 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -862,7 +862,7 @@ int32x2_t test_vld1_lane_s32(int32_t *a, int32x2_t b) {
return vld1_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_lane_s64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: define <1 x i64> @test_vld1_lane_s64(i64* %a, <1 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -874,7 +874,7 @@ int64x1_t test_vld1_lane_s64(int64_t *a, int64x1_t b) {
return vld1_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define <4 x half> @test_vld1_lane_f16(half* %a, <4 x half> %b) #0 {
+// CHECK-LABEL: define <4 x half> @test_vld1_lane_f16(half* %a, <4 x half> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
@@ -886,7 +886,7 @@ float16x4_t test_vld1_lane_f16(float16_t *a, float16x4_t b) {
return vld1_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define <2 x float> @test_vld1_lane_f32(float* %a, <2 x float> %b) #0 {
+// CHECK-LABEL: define <2 x float> @test_vld1_lane_f32(float* %a, <2 x float> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
@@ -898,7 +898,7 @@ float32x2_t test_vld1_lane_f32(float32_t *a, float32x2_t b) {
return vld1_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define <1 x double> @test_vld1_lane_f64(double* %a, <1 x double> %b) #0 {
+// CHECK-LABEL: define <1 x double> @test_vld1_lane_f64(double* %a, <1 x double> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast double* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
@@ -910,7 +910,7 @@ float64x1_t test_vld1_lane_f64(float64_t *a, float64x1_t b) {
return vld1_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_lane_p8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: define <8 x i8> @test_vld1_lane_p8(i8* %a, <8 x i8> %b) #1 {
// CHECK: [[TMP0:%.*]] = load i8, i8* %a
// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i8> %b, i8 [[TMP0]], i32 7
// CHECK: ret <8 x i8> [[VLD1_LANE]]
@@ -918,7 +918,7 @@ poly8x8_t test_vld1_lane_p8(poly8_t *a, poly8x8_t b) {
return vld1_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_lane_p16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: define <4 x i16> @test_vld1_lane_p16(i16* %a, <4 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -930,7 +930,7 @@ poly16x4_t test_vld1_lane_p16(poly16_t *a, poly16x4_t b) {
return vld1_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_lane_p64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: define <1 x i64> @test_vld1_lane_p64(i64* %a, <1 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -942,7 +942,7 @@ poly64x1_t test_vld1_lane_p64(poly64_t *a, poly64x1_t b) {
return vld1_lane_p64(a, b, 0);
}
-// CHECK-LABEL: define %struct.int8x16x2_t @test_vld2q_lane_s8(i8* %ptr, [2 x <16 x i8>] %src.coerce) #0 {
+// CHECK-LABEL: define %struct.int8x16x2_t @test_vld2q_lane_s8(i8* %ptr, [2 x <16 x i8>] %src.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[SRC:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align 16
@@ -971,7 +971,7 @@ int8x16x2_t test_vld2q_lane_s8(int8_t const * ptr, int8x16x2_t src) {
return vld2q_lane_s8(ptr, src, 15);
}
-// CHECK-LABEL: define %struct.uint8x16x2_t @test_vld2q_lane_u8(i8* %ptr, [2 x <16 x i8>] %src.coerce) #0 {
+// CHECK-LABEL: define %struct.uint8x16x2_t @test_vld2q_lane_u8(i8* %ptr, [2 x <16 x i8>] %src.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[SRC:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align 16
@@ -1000,7 +1000,7 @@ uint8x16x2_t test_vld2q_lane_u8(uint8_t const * ptr, uint8x16x2_t src) {
return vld2q_lane_u8(ptr, src, 15);
}
-// CHECK-LABEL: define %struct.poly8x16x2_t @test_vld2q_lane_p8(i8* %ptr, [2 x <16 x i8>] %src.coerce) #0 {
+// CHECK-LABEL: define %struct.poly8x16x2_t @test_vld2q_lane_p8(i8* %ptr, [2 x <16 x i8>] %src.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[SRC:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align 16
@@ -1029,7 +1029,7 @@ poly8x16x2_t test_vld2q_lane_p8(poly8_t const * ptr, poly8x16x2_t src) {
return vld2q_lane_p8(ptr, src, 15);
}
-// CHECK-LABEL: define %struct.int8x16x3_t @test_vld3q_lane_s8(i8* %ptr, [3 x <16 x i8>] %src.coerce) #0 {
+// CHECK-LABEL: define %struct.int8x16x3_t @test_vld3q_lane_s8(i8* %ptr, [3 x <16 x i8>] %src.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[SRC:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align 16
@@ -1061,7 +1061,7 @@ int8x16x3_t test_vld3q_lane_s8(int8_t const * ptr, int8x16x3_t src) {
return vld3q_lane_s8(ptr, src, 15);
}
-// CHECK-LABEL: define %struct.uint8x16x3_t @test_vld3q_lane_u8(i8* %ptr, [3 x <16 x i8>] %src.coerce) #0 {
+// CHECK-LABEL: define %struct.uint8x16x3_t @test_vld3q_lane_u8(i8* %ptr, [3 x <16 x i8>] %src.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[SRC:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align 16
@@ -1093,7 +1093,7 @@ uint8x16x3_t test_vld3q_lane_u8(uint8_t const * ptr, uint8x16x3_t src) {
return vld3q_lane_u8(ptr, src, 15);
}
-// CHECK-LABEL: define %struct.uint16x8x2_t @test_vld2q_lane_u16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint16x8x2_t @test_vld2q_lane_u16(i16* %a, [2 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16
@@ -1127,7 +1127,7 @@ uint16x8x2_t test_vld2q_lane_u16(uint16_t *a, uint16x8x2_t b) {
return vld2q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define %struct.uint32x4x2_t @test_vld2q_lane_u32(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint32x4x2_t @test_vld2q_lane_u32(i32* %a, [2 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16
@@ -1161,7 +1161,7 @@ uint32x4x2_t test_vld2q_lane_u32(uint32_t *a, uint32x4x2_t b) {
return vld2q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define %struct.uint64x2x2_t @test_vld2q_lane_u64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint64x2x2_t @test_vld2q_lane_u64(i64* %a, [2 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x2_t, align 16
@@ -1195,7 +1195,7 @@ uint64x2x2_t test_vld2q_lane_u64(uint64_t *a, uint64x2x2_t b) {
return vld2q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define %struct.int16x8x2_t @test_vld2q_lane_s16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int16x8x2_t @test_vld2q_lane_s16(i16* %a, [2 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16
@@ -1229,7 +1229,7 @@ int16x8x2_t test_vld2q_lane_s16(int16_t *a, int16x8x2_t b) {
return vld2q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define %struct.int32x4x2_t @test_vld2q_lane_s32(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int32x4x2_t @test_vld2q_lane_s32(i32* %a, [2 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16
@@ -1263,7 +1263,7 @@ int32x4x2_t test_vld2q_lane_s32(int32_t *a, int32x4x2_t b) {
return vld2q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define %struct.int64x2x2_t @test_vld2q_lane_s64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int64x2x2_t @test_vld2q_lane_s64(i64* %a, [2 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x2_t, align 16
@@ -1297,7 +1297,7 @@ int64x2x2_t test_vld2q_lane_s64(int64_t *a, int64x2x2_t b) {
return vld2q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define %struct.float16x8x2_t @test_vld2q_lane_f16(half* %a, [2 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float16x8x2_t @test_vld2q_lane_f16(half* %a, [2 x <8 x half>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16
@@ -1331,7 +1331,7 @@ float16x8x2_t test_vld2q_lane_f16(float16_t *a, float16x8x2_t b) {
return vld2q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define %struct.float32x4x2_t @test_vld2q_lane_f32(float* %a, [2 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float32x4x2_t @test_vld2q_lane_f32(float* %a, [2 x <4 x float>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16
@@ -1365,7 +1365,7 @@ float32x4x2_t test_vld2q_lane_f32(float32_t *a, float32x4x2_t b) {
return vld2q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define %struct.float64x2x2_t @test_vld2q_lane_f64(double* %a, [2 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float64x2x2_t @test_vld2q_lane_f64(double* %a, [2 x <2 x double>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x2_t, align 16
@@ -1399,7 +1399,7 @@ float64x2x2_t test_vld2q_lane_f64(float64_t *a, float64x2x2_t b) {
return vld2q_lane_f64(a, b, 1);
}
-// CHECK-LABEL: define %struct.poly16x8x2_t @test_vld2q_lane_p16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly16x8x2_t @test_vld2q_lane_p16(i16* %a, [2 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16
@@ -1433,7 +1433,7 @@ poly16x8x2_t test_vld2q_lane_p16(poly16_t *a, poly16x8x2_t b) {
return vld2q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_lane_p64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_lane_p64(i64* %a, [2 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x2_t, align 16
@@ -1467,7 +1467,7 @@ poly64x2x2_t test_vld2q_lane_p64(poly64_t *a, poly64x2x2_t b) {
return vld2q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define %struct.uint8x8x2_t @test_vld2_lane_u8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint8x8x2_t @test_vld2_lane_u8(i8* %a, [2 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x2_t, align 8
@@ -1496,7 +1496,7 @@ uint8x8x2_t test_vld2_lane_u8(uint8_t *a, uint8x8x2_t b) {
return vld2_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define %struct.uint16x4x2_t @test_vld2_lane_u16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint16x4x2_t @test_vld2_lane_u16(i16* %a, [2 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x2_t, align 8
@@ -1530,7 +1530,7 @@ uint16x4x2_t test_vld2_lane_u16(uint16_t *a, uint16x4x2_t b) {
return vld2_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define %struct.uint32x2x2_t @test_vld2_lane_u32(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint32x2x2_t @test_vld2_lane_u32(i32* %a, [2 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x2_t, align 8
@@ -1564,7 +1564,7 @@ uint32x2x2_t test_vld2_lane_u32(uint32_t *a, uint32x2x2_t b) {
return vld2_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define %struct.uint64x1x2_t @test_vld2_lane_u64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint64x1x2_t @test_vld2_lane_u64(i64* %a, [2 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x2_t, align 8
@@ -1598,7 +1598,7 @@ uint64x1x2_t test_vld2_lane_u64(uint64_t *a, uint64x1x2_t b) {
return vld2_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define %struct.int8x8x2_t @test_vld2_lane_s8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int8x8x2_t @test_vld2_lane_s8(i8* %a, [2 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x2_t, align 8
@@ -1627,7 +1627,7 @@ int8x8x2_t test_vld2_lane_s8(int8_t *a, int8x8x2_t b) {
return vld2_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define %struct.int16x4x2_t @test_vld2_lane_s16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int16x4x2_t @test_vld2_lane_s16(i16* %a, [2 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x2_t, align 8
@@ -1661,7 +1661,7 @@ int16x4x2_t test_vld2_lane_s16(int16_t *a, int16x4x2_t b) {
return vld2_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define %struct.int32x2x2_t @test_vld2_lane_s32(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int32x2x2_t @test_vld2_lane_s32(i32* %a, [2 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x2_t, align 8
@@ -1695,7 +1695,7 @@ int32x2x2_t test_vld2_lane_s32(int32_t *a, int32x2x2_t b) {
return vld2_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define %struct.int64x1x2_t @test_vld2_lane_s64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int64x1x2_t @test_vld2_lane_s64(i64* %a, [2 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x2_t, align 8
@@ -1729,7 +1729,7 @@ int64x1x2_t test_vld2_lane_s64(int64_t *a, int64x1x2_t b) {
return vld2_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define %struct.float16x4x2_t @test_vld2_lane_f16(half* %a, [2 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float16x4x2_t @test_vld2_lane_f16(half* %a, [2 x <4 x half>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x2_t, align 8
@@ -1763,7 +1763,7 @@ float16x4x2_t test_vld2_lane_f16(float16_t *a, float16x4x2_t b) {
return vld2_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define %struct.float32x2x2_t @test_vld2_lane_f32(float* %a, [2 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float32x2x2_t @test_vld2_lane_f32(float* %a, [2 x <2 x float>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x2_t, align 8
@@ -1797,7 +1797,7 @@ float32x2x2_t test_vld2_lane_f32(float32_t *a, float32x2x2_t b) {
return vld2_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define %struct.float64x1x2_t @test_vld2_lane_f64(double* %a, [2 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float64x1x2_t @test_vld2_lane_f64(double* %a, [2 x <1 x double>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x2_t, align 8
@@ -1831,7 +1831,7 @@ float64x1x2_t test_vld2_lane_f64(float64_t *a, float64x1x2_t b) {
return vld2_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define %struct.poly8x8x2_t @test_vld2_lane_p8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly8x8x2_t @test_vld2_lane_p8(i8* %a, [2 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x2_t, align 8
@@ -1860,7 +1860,7 @@ poly8x8x2_t test_vld2_lane_p8(poly8_t *a, poly8x8x2_t b) {
return vld2_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define %struct.poly16x4x2_t @test_vld2_lane_p16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly16x4x2_t @test_vld2_lane_p16(i16* %a, [2 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x2_t, align 8
@@ -1894,7 +1894,7 @@ poly16x4x2_t test_vld2_lane_p16(poly16_t *a, poly16x4x2_t b) {
return vld2_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_lane_p64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_lane_p64(i64* %a, [2 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x2_t, align 8
@@ -1928,7 +1928,7 @@ poly64x1x2_t test_vld2_lane_p64(poly64_t *a, poly64x1x2_t b) {
return vld2_lane_p64(a, b, 0);
}
-// CHECK-LABEL: define %struct.uint16x8x3_t @test_vld3q_lane_u16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint16x8x3_t @test_vld3q_lane_u16(i16* %a, [3 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16
@@ -1967,7 +1967,7 @@ uint16x8x3_t test_vld3q_lane_u16(uint16_t *a, uint16x8x3_t b) {
return vld3q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define %struct.uint32x4x3_t @test_vld3q_lane_u32(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint32x4x3_t @test_vld3q_lane_u32(i32* %a, [3 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16
@@ -2006,7 +2006,7 @@ uint32x4x3_t test_vld3q_lane_u32(uint32_t *a, uint32x4x3_t b) {
return vld3q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define %struct.uint64x2x3_t @test_vld3q_lane_u64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint64x2x3_t @test_vld3q_lane_u64(i64* %a, [3 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x3_t, align 16
@@ -2045,7 +2045,7 @@ uint64x2x3_t test_vld3q_lane_u64(uint64_t *a, uint64x2x3_t b) {
return vld3q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define %struct.int16x8x3_t @test_vld3q_lane_s16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int16x8x3_t @test_vld3q_lane_s16(i16* %a, [3 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16
@@ -2084,7 +2084,7 @@ int16x8x3_t test_vld3q_lane_s16(int16_t *a, int16x8x3_t b) {
return vld3q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define %struct.int32x4x3_t @test_vld3q_lane_s32(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int32x4x3_t @test_vld3q_lane_s32(i32* %a, [3 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16
@@ -2123,7 +2123,7 @@ int32x4x3_t test_vld3q_lane_s32(int32_t *a, int32x4x3_t b) {
return vld3q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define %struct.int64x2x3_t @test_vld3q_lane_s64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int64x2x3_t @test_vld3q_lane_s64(i64* %a, [3 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x3_t, align 16
@@ -2162,7 +2162,7 @@ int64x2x3_t test_vld3q_lane_s64(int64_t *a, int64x2x3_t b) {
return vld3q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define %struct.float16x8x3_t @test_vld3q_lane_f16(half* %a, [3 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float16x8x3_t @test_vld3q_lane_f16(half* %a, [3 x <8 x half>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16
@@ -2201,7 +2201,7 @@ float16x8x3_t test_vld3q_lane_f16(float16_t *a, float16x8x3_t b) {
return vld3q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define %struct.float32x4x3_t @test_vld3q_lane_f32(float* %a, [3 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float32x4x3_t @test_vld3q_lane_f32(float* %a, [3 x <4 x float>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16
@@ -2240,7 +2240,7 @@ float32x4x3_t test_vld3q_lane_f32(float32_t *a, float32x4x3_t b) {
return vld3q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define %struct.float64x2x3_t @test_vld3q_lane_f64(double* %a, [3 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float64x2x3_t @test_vld3q_lane_f64(double* %a, [3 x <2 x double>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x3_t, align 16
@@ -2279,7 +2279,7 @@ float64x2x3_t test_vld3q_lane_f64(float64_t *a, float64x2x3_t b) {
return vld3q_lane_f64(a, b, 1);
}
-// CHECK-LABEL: define %struct.poly8x16x3_t @test_vld3q_lane_p8(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly8x16x3_t @test_vld3q_lane_p8(i8* %a, [3 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align 16
@@ -2311,7 +2311,7 @@ poly8x16x3_t test_vld3q_lane_p8(poly8_t *a, poly8x16x3_t b) {
return vld3q_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define %struct.poly16x8x3_t @test_vld3q_lane_p16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly16x8x3_t @test_vld3q_lane_p16(i16* %a, [3 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16
@@ -2350,7 +2350,7 @@ poly16x8x3_t test_vld3q_lane_p16(poly16_t *a, poly16x8x3_t b) {
return vld3q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_lane_p64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_lane_p64(i64* %a, [3 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x3_t, align 16
@@ -2389,7 +2389,7 @@ poly64x2x3_t test_vld3q_lane_p64(poly64_t *a, poly64x2x3_t b) {
return vld3q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define %struct.uint8x8x3_t @test_vld3_lane_u8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint8x8x3_t @test_vld3_lane_u8(i8* %a, [3 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x3_t, align 8
@@ -2421,7 +2421,7 @@ uint8x8x3_t test_vld3_lane_u8(uint8_t *a, uint8x8x3_t b) {
return vld3_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define %struct.uint16x4x3_t @test_vld3_lane_u16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint16x4x3_t @test_vld3_lane_u16(i16* %a, [3 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x3_t, align 8
@@ -2460,7 +2460,7 @@ uint16x4x3_t test_vld3_lane_u16(uint16_t *a, uint16x4x3_t b) {
return vld3_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define %struct.uint32x2x3_t @test_vld3_lane_u32(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint32x2x3_t @test_vld3_lane_u32(i32* %a, [3 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x3_t, align 8
@@ -2499,7 +2499,7 @@ uint32x2x3_t test_vld3_lane_u32(uint32_t *a, uint32x2x3_t b) {
return vld3_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define %struct.uint64x1x3_t @test_vld3_lane_u64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint64x1x3_t @test_vld3_lane_u64(i64* %a, [3 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x3_t, align 8
@@ -2538,7 +2538,7 @@ uint64x1x3_t test_vld3_lane_u64(uint64_t *a, uint64x1x3_t b) {
return vld3_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define %struct.int8x8x3_t @test_vld3_lane_s8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int8x8x3_t @test_vld3_lane_s8(i8* %a, [3 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x3_t, align 8
@@ -2570,7 +2570,7 @@ int8x8x3_t test_vld3_lane_s8(int8_t *a, int8x8x3_t b) {
return vld3_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define %struct.int16x4x3_t @test_vld3_lane_s16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int16x4x3_t @test_vld3_lane_s16(i16* %a, [3 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x3_t, align 8
@@ -2609,7 +2609,7 @@ int16x4x3_t test_vld3_lane_s16(int16_t *a, int16x4x3_t b) {
return vld3_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define %struct.int32x2x3_t @test_vld3_lane_s32(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int32x2x3_t @test_vld3_lane_s32(i32* %a, [3 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x3_t, align 8
@@ -2648,7 +2648,7 @@ int32x2x3_t test_vld3_lane_s32(int32_t *a, int32x2x3_t b) {
return vld3_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define %struct.int64x1x3_t @test_vld3_lane_s64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int64x1x3_t @test_vld3_lane_s64(i64* %a, [3 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x3_t, align 8
@@ -2687,7 +2687,7 @@ int64x1x3_t test_vld3_lane_s64(int64_t *a, int64x1x3_t b) {
return vld3_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define %struct.float16x4x3_t @test_vld3_lane_f16(half* %a, [3 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float16x4x3_t @test_vld3_lane_f16(half* %a, [3 x <4 x half>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x3_t, align 8
@@ -2726,7 +2726,7 @@ float16x4x3_t test_vld3_lane_f16(float16_t *a, float16x4x3_t b) {
return vld3_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define %struct.float32x2x3_t @test_vld3_lane_f32(float* %a, [3 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float32x2x3_t @test_vld3_lane_f32(float* %a, [3 x <2 x float>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x3_t, align 8
@@ -2765,7 +2765,7 @@ float32x2x3_t test_vld3_lane_f32(float32_t *a, float32x2x3_t b) {
return vld3_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define %struct.float64x1x3_t @test_vld3_lane_f64(double* %a, [3 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float64x1x3_t @test_vld3_lane_f64(double* %a, [3 x <1 x double>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x3_t, align 8
@@ -2804,7 +2804,7 @@ float64x1x3_t test_vld3_lane_f64(float64_t *a, float64x1x3_t b) {
return vld3_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define %struct.poly8x8x3_t @test_vld3_lane_p8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly8x8x3_t @test_vld3_lane_p8(i8* %a, [3 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x3_t, align 8
@@ -2836,7 +2836,7 @@ poly8x8x3_t test_vld3_lane_p8(poly8_t *a, poly8x8x3_t b) {
return vld3_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define %struct.poly16x4x3_t @test_vld3_lane_p16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly16x4x3_t @test_vld3_lane_p16(i16* %a, [3 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x3_t, align 8
@@ -2875,7 +2875,7 @@ poly16x4x3_t test_vld3_lane_p16(poly16_t *a, poly16x4x3_t b) {
return vld3_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_lane_p64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_lane_p64(i64* %a, [3 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x3_t, align 8
@@ -2914,7 +2914,7 @@ poly64x1x3_t test_vld3_lane_p64(poly64_t *a, poly64x1x3_t b) {
return vld3_lane_p64(a, b, 0);
}
-// CHECK-LABEL: define %struct.uint8x16x4_t @test_vld4q_lane_u8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint8x16x4_t @test_vld4q_lane_u8(i8* %a, [4 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align 16
@@ -2949,7 +2949,7 @@ uint8x16x4_t test_vld4q_lane_u8(uint8_t *a, uint8x16x4_t b) {
return vld4q_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define %struct.uint16x8x4_t @test_vld4q_lane_u16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint16x8x4_t @test_vld4q_lane_u16(i16* %a, [4 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16
@@ -2993,7 +2993,7 @@ uint16x8x4_t test_vld4q_lane_u16(uint16_t *a, uint16x8x4_t b) {
return vld4q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define %struct.uint32x4x4_t @test_vld4q_lane_u32(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint32x4x4_t @test_vld4q_lane_u32(i32* %a, [4 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16
@@ -3037,7 +3037,7 @@ uint32x4x4_t test_vld4q_lane_u32(uint32_t *a, uint32x4x4_t b) {
return vld4q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define %struct.uint64x2x4_t @test_vld4q_lane_u64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint64x2x4_t @test_vld4q_lane_u64(i64* %a, [4 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x4_t, align 16
@@ -3081,7 +3081,7 @@ uint64x2x4_t test_vld4q_lane_u64(uint64_t *a, uint64x2x4_t b) {
return vld4q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define %struct.int8x16x4_t @test_vld4q_lane_s8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int8x16x4_t @test_vld4q_lane_s8(i8* %a, [4 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align 16
@@ -3116,7 +3116,7 @@ int8x16x4_t test_vld4q_lane_s8(int8_t *a, int8x16x4_t b) {
return vld4q_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define %struct.int16x8x4_t @test_vld4q_lane_s16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int16x8x4_t @test_vld4q_lane_s16(i16* %a, [4 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16
@@ -3160,7 +3160,7 @@ int16x8x4_t test_vld4q_lane_s16(int16_t *a, int16x8x4_t b) {
return vld4q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define %struct.int32x4x4_t @test_vld4q_lane_s32(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int32x4x4_t @test_vld4q_lane_s32(i32* %a, [4 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16
@@ -3204,7 +3204,7 @@ int32x4x4_t test_vld4q_lane_s32(int32_t *a, int32x4x4_t b) {
return vld4q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define %struct.int64x2x4_t @test_vld4q_lane_s64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int64x2x4_t @test_vld4q_lane_s64(i64* %a, [4 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x4_t, align 16
@@ -3248,7 +3248,7 @@ int64x2x4_t test_vld4q_lane_s64(int64_t *a, int64x2x4_t b) {
return vld4q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define %struct.float16x8x4_t @test_vld4q_lane_f16(half* %a, [4 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float16x8x4_t @test_vld4q_lane_f16(half* %a, [4 x <8 x half>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16
@@ -3292,7 +3292,7 @@ float16x8x4_t test_vld4q_lane_f16(float16_t *a, float16x8x4_t b) {
return vld4q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define %struct.float32x4x4_t @test_vld4q_lane_f32(float* %a, [4 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float32x4x4_t @test_vld4q_lane_f32(float* %a, [4 x <4 x float>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16
@@ -3336,7 +3336,7 @@ float32x4x4_t test_vld4q_lane_f32(float32_t *a, float32x4x4_t b) {
return vld4q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define %struct.float64x2x4_t @test_vld4q_lane_f64(double* %a, [4 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float64x2x4_t @test_vld4q_lane_f64(double* %a, [4 x <2 x double>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x4_t, align 16
@@ -3380,7 +3380,7 @@ float64x2x4_t test_vld4q_lane_f64(float64_t *a, float64x2x4_t b) {
return vld4q_lane_f64(a, b, 1);
}
-// CHECK-LABEL: define %struct.poly8x16x4_t @test_vld4q_lane_p8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly8x16x4_t @test_vld4q_lane_p8(i8* %a, [4 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align 16
@@ -3415,7 +3415,7 @@ poly8x16x4_t test_vld4q_lane_p8(poly8_t *a, poly8x16x4_t b) {
return vld4q_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define %struct.poly16x8x4_t @test_vld4q_lane_p16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly16x8x4_t @test_vld4q_lane_p16(i16* %a, [4 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16
@@ -3459,7 +3459,7 @@ poly16x8x4_t test_vld4q_lane_p16(poly16_t *a, poly16x8x4_t b) {
return vld4q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_lane_p64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_lane_p64(i64* %a, [4 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x4_t, align 16
@@ -3503,7 +3503,7 @@ poly64x2x4_t test_vld4q_lane_p64(poly64_t *a, poly64x2x4_t b) {
return vld4q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define %struct.uint8x8x4_t @test_vld4_lane_u8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint8x8x4_t @test_vld4_lane_u8(i8* %a, [4 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x4_t, align 8
@@ -3538,7 +3538,7 @@ uint8x8x4_t test_vld4_lane_u8(uint8_t *a, uint8x8x4_t b) {
return vld4_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define %struct.uint16x4x4_t @test_vld4_lane_u16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint16x4x4_t @test_vld4_lane_u16(i16* %a, [4 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x4_t, align 8
@@ -3582,7 +3582,7 @@ uint16x4x4_t test_vld4_lane_u16(uint16_t *a, uint16x4x4_t b) {
return vld4_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define %struct.uint32x2x4_t @test_vld4_lane_u32(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint32x2x4_t @test_vld4_lane_u32(i32* %a, [4 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x4_t, align 8
@@ -3626,7 +3626,7 @@ uint32x2x4_t test_vld4_lane_u32(uint32_t *a, uint32x2x4_t b) {
return vld4_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define %struct.uint64x1x4_t @test_vld4_lane_u64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.uint64x1x4_t @test_vld4_lane_u64(i64* %a, [4 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x4_t, align 8
@@ -3670,7 +3670,7 @@ uint64x1x4_t test_vld4_lane_u64(uint64_t *a, uint64x1x4_t b) {
return vld4_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define %struct.int8x8x4_t @test_vld4_lane_s8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int8x8x4_t @test_vld4_lane_s8(i8* %a, [4 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x4_t, align 8
@@ -3705,7 +3705,7 @@ int8x8x4_t test_vld4_lane_s8(int8_t *a, int8x8x4_t b) {
return vld4_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define %struct.int16x4x4_t @test_vld4_lane_s16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int16x4x4_t @test_vld4_lane_s16(i16* %a, [4 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x4_t, align 8
@@ -3749,7 +3749,7 @@ int16x4x4_t test_vld4_lane_s16(int16_t *a, int16x4x4_t b) {
return vld4_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define %struct.int32x2x4_t @test_vld4_lane_s32(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int32x2x4_t @test_vld4_lane_s32(i32* %a, [4 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x4_t, align 8
@@ -3793,7 +3793,7 @@ int32x2x4_t test_vld4_lane_s32(int32_t *a, int32x2x4_t b) {
return vld4_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define %struct.int64x1x4_t @test_vld4_lane_s64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.int64x1x4_t @test_vld4_lane_s64(i64* %a, [4 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x4_t, align 8
@@ -3837,7 +3837,7 @@ int64x1x4_t test_vld4_lane_s64(int64_t *a, int64x1x4_t b) {
return vld4_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define %struct.float16x4x4_t @test_vld4_lane_f16(half* %a, [4 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float16x4x4_t @test_vld4_lane_f16(half* %a, [4 x <4 x half>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x4_t, align 8
@@ -3881,7 +3881,7 @@ float16x4x4_t test_vld4_lane_f16(float16_t *a, float16x4x4_t b) {
return vld4_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define %struct.float32x2x4_t @test_vld4_lane_f32(float* %a, [4 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float32x2x4_t @test_vld4_lane_f32(float* %a, [4 x <2 x float>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x4_t, align 8
@@ -3925,7 +3925,7 @@ float32x2x4_t test_vld4_lane_f32(float32_t *a, float32x2x4_t b) {
return vld4_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define %struct.float64x1x4_t @test_vld4_lane_f64(double* %a, [4 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.float64x1x4_t @test_vld4_lane_f64(double* %a, [4 x <1 x double>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x4_t, align 8
@@ -3969,7 +3969,7 @@ float64x1x4_t test_vld4_lane_f64(float64_t *a, float64x1x4_t b) {
return vld4_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define %struct.poly8x8x4_t @test_vld4_lane_p8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly8x8x4_t @test_vld4_lane_p8(i8* %a, [4 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x4_t, align 8
@@ -4004,7 +4004,7 @@ poly8x8x4_t test_vld4_lane_p8(poly8_t *a, poly8x8x4_t b) {
return vld4_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define %struct.poly16x4x4_t @test_vld4_lane_p16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly16x4x4_t @test_vld4_lane_p16(i16* %a, [4 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x4_t, align 8
@@ -4048,7 +4048,7 @@ poly16x4x4_t test_vld4_lane_p16(poly16_t *a, poly16x4x4_t b) {
return vld4_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_lane_p64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_lane_p64(i64* %a, [4 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x4_t, align 8
@@ -4248,7 +4248,7 @@ void test_vst1q_lane_p64(poly64_t *a, poly64x2_t b) {
vst1q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1_lane_u8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_u8(i8* %a, <8 x i8> %b) #1 {
// CHECK: [[TMP0:%.*]] = extractelement <8 x i8> %b, i32 7
// CHECK: store i8 [[TMP0]], i8* %a
// CHECK: ret void
@@ -4256,7 +4256,7 @@ void test_vst1_lane_u8(uint8_t *a, uint8x8_t b) {
vst1_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1_lane_u16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_u16(i16* %a, <4 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -4268,7 +4268,7 @@ void test_vst1_lane_u16(uint16_t *a, uint16x4_t b) {
vst1_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1_lane_u32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_u32(i32* %a, <2 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -4280,7 +4280,7 @@ void test_vst1_lane_u32(uint32_t *a, uint32x2_t b) {
vst1_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1_lane_u64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_u64(i64* %a, <1 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -4292,7 +4292,7 @@ void test_vst1_lane_u64(uint64_t *a, uint64x1_t b) {
vst1_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst1_lane_s8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_s8(i8* %a, <8 x i8> %b) #1 {
// CHECK: [[TMP0:%.*]] = extractelement <8 x i8> %b, i32 7
// CHECK: store i8 [[TMP0]], i8* %a
// CHECK: ret void
@@ -4300,7 +4300,7 @@ void test_vst1_lane_s8(int8_t *a, int8x8_t b) {
vst1_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1_lane_s16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_s16(i16* %a, <4 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -4312,7 +4312,7 @@ void test_vst1_lane_s16(int16_t *a, int16x4_t b) {
vst1_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1_lane_s32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_s32(i32* %a, <2 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -4324,7 +4324,7 @@ void test_vst1_lane_s32(int32_t *a, int32x2_t b) {
vst1_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1_lane_s64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_s64(i64* %a, <1 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -4336,7 +4336,7 @@ void test_vst1_lane_s64(int64_t *a, int64x1_t b) {
vst1_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst1_lane_f16(half* %a, <4 x half> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_f16(half* %a, <4 x half> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
@@ -4348,7 +4348,7 @@ void test_vst1_lane_f16(float16_t *a, float16x4_t b) {
vst1_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1_lane_f32(float* %a, <2 x float> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_f32(float* %a, <2 x float> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
@@ -4360,7 +4360,7 @@ void test_vst1_lane_f32(float32_t *a, float32x2_t b) {
vst1_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1_lane_f64(double* %a, <1 x double> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_f64(double* %a, <1 x double> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast double* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
@@ -4372,7 +4372,7 @@ void test_vst1_lane_f64(float64_t *a, float64x1_t b) {
vst1_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst1_lane_p8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_p8(i8* %a, <8 x i8> %b) #1 {
// CHECK: [[TMP0:%.*]] = extractelement <8 x i8> %b, i32 7
// CHECK: store i8 [[TMP0]], i8* %a
// CHECK: ret void
@@ -4380,7 +4380,7 @@ void test_vst1_lane_p8(poly8_t *a, poly8x8_t b) {
vst1_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1_lane_p16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_p16(i16* %a, <4 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -4392,7 +4392,7 @@ void test_vst1_lane_p16(poly16_t *a, poly16x4_t b) {
vst1_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1_lane_p64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: define void @test_vst1_lane_p64(i64* %a, <1 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -4404,7 +4404,7 @@ void test_vst1_lane_p64(poly64_t *a, poly64x1_t b) {
vst1_lane_p64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst2q_lane_u8(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_u8(i8* %a, [2 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[B]], i32 0, i32 0
@@ -4424,7 +4424,7 @@ void test_vst2q_lane_u8(uint8_t *a, uint8x16x2_t b) {
vst2q_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst2q_lane_u16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_u16(i16* %a, [2 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0
@@ -4449,7 +4449,7 @@ void test_vst2q_lane_u16(uint16_t *a, uint16x8x2_t b) {
vst2q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2q_lane_u32(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_u32(i32* %a, [2 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0
@@ -4474,7 +4474,7 @@ void test_vst2q_lane_u32(uint32_t *a, uint32x4x2_t b) {
vst2q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2q_lane_u64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_u64(i64* %a, [2 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[B]], i32 0, i32 0
@@ -4499,7 +4499,7 @@ void test_vst2q_lane_u64(uint64_t *a, uint64x2x2_t b) {
vst2q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2q_lane_s8(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_s8(i8* %a, [2 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[B]], i32 0, i32 0
@@ -4519,7 +4519,7 @@ void test_vst2q_lane_s8(int8_t *a, int8x16x2_t b) {
vst2q_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst2q_lane_s16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_s16(i16* %a, [2 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0
@@ -4544,7 +4544,7 @@ void test_vst2q_lane_s16(int16_t *a, int16x8x2_t b) {
vst2q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2q_lane_s32(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_s32(i32* %a, [2 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0
@@ -4569,7 +4569,7 @@ void test_vst2q_lane_s32(int32_t *a, int32x4x2_t b) {
vst2q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2q_lane_s64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_s64(i64* %a, [2 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[B]], i32 0, i32 0
@@ -4594,7 +4594,7 @@ void test_vst2q_lane_s64(int64_t *a, int64x2x2_t b) {
vst2q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2q_lane_f16(half* %a, [2 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_f16(half* %a, [2 x <8 x half>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0
@@ -4619,7 +4619,7 @@ void test_vst2q_lane_f16(float16_t *a, float16x8x2_t b) {
vst2q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2q_lane_f32(float* %a, [2 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_f32(float* %a, [2 x <4 x float>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0
@@ -4644,7 +4644,7 @@ void test_vst2q_lane_f32(float32_t *a, float32x4x2_t b) {
vst2q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2q_lane_f64(double* %a, [2 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_f64(double* %a, [2 x <2 x double>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x2_t, %struct.float64x2x2_t* [[B]], i32 0, i32 0
@@ -4669,7 +4669,7 @@ void test_vst2q_lane_f64(float64_t *a, float64x2x2_t b) {
vst2q_lane_f64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2q_lane_p8(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_p8(i8* %a, [2 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[B]], i32 0, i32 0
@@ -4689,7 +4689,7 @@ void test_vst2q_lane_p8(poly8_t *a, poly8x16x2_t b) {
vst2q_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst2q_lane_p16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_p16(i16* %a, [2 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0
@@ -4714,7 +4714,7 @@ void test_vst2q_lane_p16(poly16_t *a, poly16x8x2_t b) {
vst2q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2q_lane_p64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_lane_p64(i64* %a, [2 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[B]], i32 0, i32 0
@@ -4739,7 +4739,7 @@ void test_vst2q_lane_p64(poly64_t *a, poly64x2x2_t b) {
vst2q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2_lane_u8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_u8(i8* %a, [2 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[B]], i32 0, i32 0
@@ -4759,7 +4759,7 @@ void test_vst2_lane_u8(uint8_t *a, uint8x8x2_t b) {
vst2_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2_lane_u16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_u16(i16* %a, [2 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[B]], i32 0, i32 0
@@ -4784,7 +4784,7 @@ void test_vst2_lane_u16(uint16_t *a, uint16x4x2_t b) {
vst2_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2_lane_u32(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_u32(i32* %a, [2 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[B]], i32 0, i32 0
@@ -4809,7 +4809,7 @@ void test_vst2_lane_u32(uint32_t *a, uint32x2x2_t b) {
vst2_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2_lane_u64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_u64(i64* %a, [2 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[B]], i32 0, i32 0
@@ -4834,7 +4834,7 @@ void test_vst2_lane_u64(uint64_t *a, uint64x1x2_t b) {
vst2_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst2_lane_s8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_s8(i8* %a, [2 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[B]], i32 0, i32 0
@@ -4854,7 +4854,7 @@ void test_vst2_lane_s8(int8_t *a, int8x8x2_t b) {
vst2_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2_lane_s16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_s16(i16* %a, [2 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[B]], i32 0, i32 0
@@ -4879,7 +4879,7 @@ void test_vst2_lane_s16(int16_t *a, int16x4x2_t b) {
vst2_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2_lane_s32(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_s32(i32* %a, [2 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[B]], i32 0, i32 0
@@ -4904,7 +4904,7 @@ void test_vst2_lane_s32(int32_t *a, int32x2x2_t b) {
vst2_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2_lane_s64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_s64(i64* %a, [2 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[B]], i32 0, i32 0
@@ -4929,7 +4929,7 @@ void test_vst2_lane_s64(int64_t *a, int64x1x2_t b) {
vst2_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst2_lane_f16(half* %a, [2 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_f16(half* %a, [2 x <4 x half>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[B]], i32 0, i32 0
@@ -4954,7 +4954,7 @@ void test_vst2_lane_f16(float16_t *a, float16x4x2_t b) {
vst2_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2_lane_f32(float* %a, [2 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_f32(float* %a, [2 x <2 x float>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[B]], i32 0, i32 0
@@ -4979,7 +4979,7 @@ void test_vst2_lane_f32(float32_t *a, float32x2x2_t b) {
vst2_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2_lane_f64(double* %a, [2 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_f64(double* %a, [2 x <1 x double>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[B]], i32 0, i32 0
@@ -5004,7 +5004,7 @@ void test_vst2_lane_f64(float64_t *a, float64x1x2_t b) {
vst2_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst2_lane_p8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_p8(i8* %a, [2 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[B]], i32 0, i32 0
@@ -5024,7 +5024,7 @@ void test_vst2_lane_p8(poly8_t *a, poly8x8x2_t b) {
vst2_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2_lane_p16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_p16(i16* %a, [2 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[B]], i32 0, i32 0
@@ -5049,7 +5049,7 @@ void test_vst2_lane_p16(poly16_t *a, poly16x4x2_t b) {
vst2_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2_lane_p64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_lane_p64(i64* %a, [2 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[B]], i32 0, i32 0
@@ -5074,7 +5074,7 @@ void test_vst2_lane_p64(poly64_t *a, poly64x1x2_t b) {
vst2_lane_p64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst3q_lane_u8(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_u8(i8* %a, [3 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[B]], i32 0, i32 0
@@ -5097,7 +5097,7 @@ void test_vst3q_lane_u8(uint8_t *a, uint8x16x3_t b) {
vst3q_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst3q_lane_u16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_u16(i16* %a, [3 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0
@@ -5127,7 +5127,7 @@ void test_vst3q_lane_u16(uint16_t *a, uint16x8x3_t b) {
vst3q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3q_lane_u32(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_u32(i32* %a, [3 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0
@@ -5157,7 +5157,7 @@ void test_vst3q_lane_u32(uint32_t *a, uint32x4x3_t b) {
vst3q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3q_lane_u64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_u64(i64* %a, [3 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[B]], i32 0, i32 0
@@ -5187,7 +5187,7 @@ void test_vst3q_lane_u64(uint64_t *a, uint64x2x3_t b) {
vst3q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3q_lane_s8(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_s8(i8* %a, [3 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[B]], i32 0, i32 0
@@ -5210,7 +5210,7 @@ void test_vst3q_lane_s8(int8_t *a, int8x16x3_t b) {
vst3q_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst3q_lane_s16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_s16(i16* %a, [3 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0
@@ -5240,7 +5240,7 @@ void test_vst3q_lane_s16(int16_t *a, int16x8x3_t b) {
vst3q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3q_lane_s32(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_s32(i32* %a, [3 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0
@@ -5270,7 +5270,7 @@ void test_vst3q_lane_s32(int32_t *a, int32x4x3_t b) {
vst3q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3q_lane_s64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_s64(i64* %a, [3 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[B]], i32 0, i32 0
@@ -5300,7 +5300,7 @@ void test_vst3q_lane_s64(int64_t *a, int64x2x3_t b) {
vst3q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3q_lane_f16(half* %a, [3 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_f16(half* %a, [3 x <8 x half>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0
@@ -5330,7 +5330,7 @@ void test_vst3q_lane_f16(float16_t *a, float16x8x3_t b) {
vst3q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3q_lane_f32(float* %a, [3 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_f32(float* %a, [3 x <4 x float>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0
@@ -5360,7 +5360,7 @@ void test_vst3q_lane_f32(float32_t *a, float32x4x3_t b) {
vst3q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3q_lane_f64(double* %a, [3 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_f64(double* %a, [3 x <2 x double>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[B]], i32 0, i32 0
@@ -5390,7 +5390,7 @@ void test_vst3q_lane_f64(float64_t *a, float64x2x3_t b) {
vst3q_lane_f64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3q_lane_p8(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_p8(i8* %a, [3 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[B]], i32 0, i32 0
@@ -5413,7 +5413,7 @@ void test_vst3q_lane_p8(poly8_t *a, poly8x16x3_t b) {
vst3q_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst3q_lane_p16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_p16(i16* %a, [3 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0
@@ -5443,7 +5443,7 @@ void test_vst3q_lane_p16(poly16_t *a, poly16x8x3_t b) {
vst3q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3q_lane_p64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_lane_p64(i64* %a, [3 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[B]], i32 0, i32 0
@@ -5473,7 +5473,7 @@ void test_vst3q_lane_p64(poly64_t *a, poly64x2x3_t b) {
vst3q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3_lane_u8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_u8(i8* %a, [3 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[B]], i32 0, i32 0
@@ -5496,7 +5496,7 @@ void test_vst3_lane_u8(uint8_t *a, uint8x8x3_t b) {
vst3_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3_lane_u16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_u16(i16* %a, [3 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[B]], i32 0, i32 0
@@ -5526,7 +5526,7 @@ void test_vst3_lane_u16(uint16_t *a, uint16x4x3_t b) {
vst3_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3_lane_u32(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_u32(i32* %a, [3 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[B]], i32 0, i32 0
@@ -5556,7 +5556,7 @@ void test_vst3_lane_u32(uint32_t *a, uint32x2x3_t b) {
vst3_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3_lane_u64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_u64(i64* %a, [3 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[B]], i32 0, i32 0
@@ -5586,7 +5586,7 @@ void test_vst3_lane_u64(uint64_t *a, uint64x1x3_t b) {
vst3_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst3_lane_s8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_s8(i8* %a, [3 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[B]], i32 0, i32 0
@@ -5609,7 +5609,7 @@ void test_vst3_lane_s8(int8_t *a, int8x8x3_t b) {
vst3_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3_lane_s16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_s16(i16* %a, [3 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[B]], i32 0, i32 0
@@ -5639,7 +5639,7 @@ void test_vst3_lane_s16(int16_t *a, int16x4x3_t b) {
vst3_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3_lane_s32(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_s32(i32* %a, [3 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[B]], i32 0, i32 0
@@ -5669,7 +5669,7 @@ void test_vst3_lane_s32(int32_t *a, int32x2x3_t b) {
vst3_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3_lane_s64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_s64(i64* %a, [3 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[B]], i32 0, i32 0
@@ -5699,7 +5699,7 @@ void test_vst3_lane_s64(int64_t *a, int64x1x3_t b) {
vst3_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst3_lane_f16(half* %a, [3 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_f16(half* %a, [3 x <4 x half>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[B]], i32 0, i32 0
@@ -5729,7 +5729,7 @@ void test_vst3_lane_f16(float16_t *a, float16x4x3_t b) {
vst3_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3_lane_f32(float* %a, [3 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_f32(float* %a, [3 x <2 x float>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[B]], i32 0, i32 0
@@ -5759,7 +5759,7 @@ void test_vst3_lane_f32(float32_t *a, float32x2x3_t b) {
vst3_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3_lane_f64(double* %a, [3 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_f64(double* %a, [3 x <1 x double>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[B]], i32 0, i32 0
@@ -5789,7 +5789,7 @@ void test_vst3_lane_f64(float64_t *a, float64x1x3_t b) {
vst3_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst3_lane_p8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_p8(i8* %a, [3 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[B]], i32 0, i32 0
@@ -5812,7 +5812,7 @@ void test_vst3_lane_p8(poly8_t *a, poly8x8x3_t b) {
vst3_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3_lane_p16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_p16(i16* %a, [3 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[B]], i32 0, i32 0
@@ -5842,7 +5842,7 @@ void test_vst3_lane_p16(poly16_t *a, poly16x4x3_t b) {
vst3_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3_lane_p64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_lane_p64(i64* %a, [3 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[B]], i32 0, i32 0
@@ -5872,7 +5872,7 @@ void test_vst3_lane_p64(poly64_t *a, poly64x1x3_t b) {
vst3_lane_p64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst4q_lane_u8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_u8(i8* %a, [4 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[B]], i32 0, i32 0
@@ -5898,7 +5898,7 @@ void test_vst4q_lane_u8(uint8_t *a, uint8x16x4_t b) {
vst4q_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst4q_lane_u16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_u16(i16* %a, [4 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0
@@ -5933,7 +5933,7 @@ void test_vst4q_lane_u16(uint16_t *a, uint16x8x4_t b) {
vst4q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4q_lane_u32(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_u32(i32* %a, [4 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0
@@ -5968,7 +5968,7 @@ void test_vst4q_lane_u32(uint32_t *a, uint32x4x4_t b) {
vst4q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4q_lane_u64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_u64(i64* %a, [4 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[B]], i32 0, i32 0
@@ -6003,7 +6003,7 @@ void test_vst4q_lane_u64(uint64_t *a, uint64x2x4_t b) {
vst4q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4q_lane_s8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_s8(i8* %a, [4 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[B]], i32 0, i32 0
@@ -6029,7 +6029,7 @@ void test_vst4q_lane_s8(int8_t *a, int8x16x4_t b) {
vst4q_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst4q_lane_s16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_s16(i16* %a, [4 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0
@@ -6064,7 +6064,7 @@ void test_vst4q_lane_s16(int16_t *a, int16x8x4_t b) {
vst4q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4q_lane_s32(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_s32(i32* %a, [4 x <4 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0
@@ -6099,7 +6099,7 @@ void test_vst4q_lane_s32(int32_t *a, int32x4x4_t b) {
vst4q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4q_lane_s64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_s64(i64* %a, [4 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[B]], i32 0, i32 0
@@ -6134,7 +6134,7 @@ void test_vst4q_lane_s64(int64_t *a, int64x2x4_t b) {
vst4q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4q_lane_f16(half* %a, [4 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_f16(half* %a, [4 x <8 x half>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0
@@ -6169,7 +6169,7 @@ void test_vst4q_lane_f16(float16_t *a, float16x8x4_t b) {
vst4q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4q_lane_f32(float* %a, [4 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_f32(float* %a, [4 x <4 x float>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0
@@ -6204,7 +6204,7 @@ void test_vst4q_lane_f32(float32_t *a, float32x4x4_t b) {
vst4q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4q_lane_f64(double* %a, [4 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_f64(double* %a, [4 x <2 x double>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[B]], i32 0, i32 0
@@ -6239,7 +6239,7 @@ void test_vst4q_lane_f64(float64_t *a, float64x2x4_t b) {
vst4q_lane_f64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4q_lane_p8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_p8(i8* %a, [4 x <16 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[B]], i32 0, i32 0
@@ -6265,7 +6265,7 @@ void test_vst4q_lane_p8(poly8_t *a, poly8x16x4_t b) {
vst4q_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst4q_lane_p16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_p16(i16* %a, [4 x <8 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0
@@ -6300,7 +6300,7 @@ void test_vst4q_lane_p16(poly16_t *a, poly16x8x4_t b) {
vst4q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4q_lane_p64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_lane_p64(i64* %a, [4 x <2 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[B]], i32 0, i32 0
@@ -6335,7 +6335,7 @@ void test_vst4q_lane_p64(poly64_t *a, poly64x2x4_t b) {
vst4q_lane_p64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4_lane_u8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_u8(i8* %a, [4 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[B]], i32 0, i32 0
@@ -6361,7 +6361,7 @@ void test_vst4_lane_u8(uint8_t *a, uint8x8x4_t b) {
vst4_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4_lane_u16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_u16(i16* %a, [4 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[B]], i32 0, i32 0
@@ -6396,7 +6396,7 @@ void test_vst4_lane_u16(uint16_t *a, uint16x4x4_t b) {
vst4_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4_lane_u32(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_u32(i32* %a, [4 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[B]], i32 0, i32 0
@@ -6431,7 +6431,7 @@ void test_vst4_lane_u32(uint32_t *a, uint32x2x4_t b) {
vst4_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4_lane_u64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_u64(i64* %a, [4 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.uint64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[B]], i32 0, i32 0
@@ -6466,7 +6466,7 @@ void test_vst4_lane_u64(uint64_t *a, uint64x1x4_t b) {
vst4_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst4_lane_s8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_s8(i8* %a, [4 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[B]], i32 0, i32 0
@@ -6492,7 +6492,7 @@ void test_vst4_lane_s8(int8_t *a, int8x8x4_t b) {
vst4_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4_lane_s16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_s16(i16* %a, [4 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[B]], i32 0, i32 0
@@ -6527,7 +6527,7 @@ void test_vst4_lane_s16(int16_t *a, int16x4x4_t b) {
vst4_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4_lane_s32(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_s32(i32* %a, [4 x <2 x i32>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[B]], i32 0, i32 0
@@ -6562,7 +6562,7 @@ void test_vst4_lane_s32(int32_t *a, int32x2x4_t b) {
vst4_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4_lane_s64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_s64(i64* %a, [4 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.int64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[B]], i32 0, i32 0
@@ -6597,7 +6597,7 @@ void test_vst4_lane_s64(int64_t *a, int64x1x4_t b) {
vst4_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst4_lane_f16(half* %a, [4 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_f16(half* %a, [4 x <4 x half>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[B]], i32 0, i32 0
@@ -6632,7 +6632,7 @@ void test_vst4_lane_f16(float16_t *a, float16x4x4_t b) {
vst4_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4_lane_f32(float* %a, [4 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_f32(float* %a, [4 x <2 x float>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[B]], i32 0, i32 0
@@ -6667,7 +6667,7 @@ void test_vst4_lane_f32(float32_t *a, float32x2x4_t b) {
vst4_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4_lane_f64(double* %a, [4 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_f64(double* %a, [4 x <1 x double>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x4_t, %struct.float64x1x4_t* [[B]], i32 0, i32 0
@@ -6702,7 +6702,7 @@ void test_vst4_lane_f64(float64_t *a, float64x1x4_t b) {
vst4_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst4_lane_p8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_p8(i8* %a, [4 x <8 x i8>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[B]], i32 0, i32 0
@@ -6728,7 +6728,7 @@ void test_vst4_lane_p8(poly8_t *a, poly8x8x4_t b) {
vst4_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4_lane_p16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_p16(i16* %a, [4 x <4 x i16>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[B]], i32 0, i32 0
@@ -6763,7 +6763,7 @@ void test_vst4_lane_p16(poly16_t *a, poly16x4x4_t b) {
vst4_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4_lane_p64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_lane_p64(i64* %a, [4 x <1 x i64>] %b.coerce) #2 {
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[B]], i32 0, i32 0
@@ -6797,3 +6797,7 @@ void test_vst4_lane_p16(poly16_t *a, poly16x4x4_t b) {
void test_vst4_lane_p64(poly64_t *a, poly64x1x4_t b) {
vst4_lane_p64(a, b, 0);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="128"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #2 ={{.*}}"min-legal-vector-width"="0"
diff --git a/test/CodeGen/aarch64-neon-scalar-copy.c b/test/CodeGen/aarch64-neon-scalar-copy.c
index 28cff5fbf3b9..d7daf82998e2 100644
--- a/test/CodeGen/aarch64-neon-scalar-copy.c
+++ b/test/CodeGen/aarch64-neon-scalar-copy.c
@@ -23,7 +23,7 @@ float64_t test_vdupd_lane_f64(float64x1_t a) {
}
-// CHECK-LABEL: define float @test_vdups_laneq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: define float @test_vdups_laneq_f32(<4 x float> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
@@ -33,7 +33,7 @@ float32_t test_vdups_laneq_f32(float32x4_t a) {
}
-// CHECK-LABEL: define double @test_vdupd_laneq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: define double @test_vdupd_laneq_f64(<2 x double> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
@@ -118,7 +118,7 @@ uint64_t test_vdupd_lane_u64(uint64x1_t a) {
return vdupd_lane_u64(a, 0);
}
-// CHECK-LABEL: define i8 @test_vdupb_laneq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i8 @test_vdupb_laneq_s8(<16 x i8> %a) #1 {
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGETQ_LANE]]
int8_t test_vdupb_laneq_s8(int8x16_t a) {
@@ -126,7 +126,7 @@ int8_t test_vdupb_laneq_s8(int8x16_t a) {
}
-// CHECK-LABEL: define i16 @test_vduph_laneq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i16 @test_vduph_laneq_s16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -136,7 +136,7 @@ int16_t test_vduph_laneq_s16(int16x8_t a) {
}
-// CHECK-LABEL: define i32 @test_vdups_laneq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: define i32 @test_vdups_laneq_s32(<4 x i32> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -146,7 +146,7 @@ int32_t test_vdups_laneq_s32(int32x4_t a) {
}
-// CHECK-LABEL: define i64 @test_vdupd_laneq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: define i64 @test_vdupd_laneq_s64(<2 x i64> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -156,7 +156,7 @@ int64_t test_vdupd_laneq_s64(int64x2_t a) {
}
-// CHECK-LABEL: define i8 @test_vdupb_laneq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i8 @test_vdupb_laneq_u8(<16 x i8> %a) #1 {
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGETQ_LANE]]
uint8_t test_vdupb_laneq_u8(uint8x16_t a) {
@@ -164,7 +164,7 @@ uint8_t test_vdupb_laneq_u8(uint8x16_t a) {
}
-// CHECK-LABEL: define i16 @test_vduph_laneq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i16 @test_vduph_laneq_u16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -174,7 +174,7 @@ uint16_t test_vduph_laneq_u16(uint16x8_t a) {
}
-// CHECK-LABEL: define i32 @test_vdups_laneq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: define i32 @test_vdups_laneq_u32(<4 x i32> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -184,7 +184,7 @@ uint32_t test_vdups_laneq_u32(uint32x4_t a) {
}
-// CHECK-LABEL: define i64 @test_vdupd_laneq_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: define i64 @test_vdupd_laneq_u64(<2 x i64> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -209,14 +209,14 @@ poly16_t test_vduph_lane_p16(poly16x4_t a) {
return vduph_lane_p16(a, 3);
}
-// CHECK-LABEL: define i8 @test_vdupb_laneq_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i8 @test_vdupb_laneq_p8(<16 x i8> %a) #1 {
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGETQ_LANE]]
poly8_t test_vdupb_laneq_p8(poly8x16_t a) {
return vdupb_laneq_p8(a, 15);
}
-// CHECK-LABEL: define i16 @test_vduph_laneq_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i16 @test_vduph_laneq_p16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -225,3 +225,5 @@ poly16_t test_vduph_laneq_p16(poly16x8_t a) {
return vduph_laneq_p16(a, 7);
}
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c b/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
index e85b918d5ace..88ab0c50ba2d 100644
--- a/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
+++ b/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
@@ -26,7 +26,7 @@ float64_t test_vmuld_lane_f64(float64_t a, float64x1_t b) {
return vmuld_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define float @test_vmuls_laneq_f32(float %a, <4 x float> %b) #0 {
+// CHECK-LABEL: define float @test_vmuls_laneq_f32(float %a, <4 x float> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
@@ -36,7 +36,7 @@ float32_t test_vmuls_laneq_f32(float32_t a, float32x4_t b) {
return vmuls_laneq_f32(a, b, 3);
}
-// CHECK-LABEL: define double @test_vmuld_laneq_f64(double %a, <2 x double> %b) #0 {
+// CHECK-LABEL: define double @test_vmuld_laneq_f64(double %a, <2 x double> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
@@ -65,7 +65,7 @@ float32_t test_vmulxs_lane_f32(float32_t a, float32x2_t b) {
return vmulxs_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define float @test_vmulxs_laneq_f32(float %a, <4 x float> %b) #0 {
+// CHECK-LABEL: define float @test_vmulxs_laneq_f32(float %a, <4 x float> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
@@ -85,7 +85,7 @@ float64_t test_vmulxd_lane_f64(float64_t a, float64x1_t b) {
return vmulxd_lane_f64(a, b, 0);
}
-// CHECK-LABEL: define double @test_vmulxd_laneq_f64(double %a, <2 x double> %b) #0 {
+// CHECK-LABEL: define double @test_vmulxd_laneq_f64(double %a, <2 x double> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
@@ -112,7 +112,7 @@ float64x1_t test_vmulx_lane_f64(float64x1_t a, float64x1_t b) {
}
-// CHECK-LABEL: define <1 x double> @test_vmulx_laneq_f64_0(<1 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: define <1 x double> @test_vmulx_laneq_f64_0(<1 x double> %a, <2 x double> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
// CHECK: [[VGET_LANE:%.*]] = extractelement <1 x double> [[TMP1]], i32 0
@@ -128,7 +128,7 @@ float64x1_t test_vmulx_laneq_f64_0(float64x1_t a, float64x2_t b) {
return vmulx_laneq_f64(a, b, 0);
}
-// CHECK-LABEL: define <1 x double> @test_vmulx_laneq_f64_1(<1 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: define <1 x double> @test_vmulx_laneq_f64_1(<1 x double> %a, <2 x double> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
// CHECK: [[VGET_LANE:%.*]] = extractelement <1 x double> [[TMP1]], i32 0
@@ -165,7 +165,7 @@ float64_t test_vfmad_lane_f64(float64_t a, float64_t b, float64x1_t c) {
return vfmad_lane_f64(a, b, c, 0);
}
-// CHECK-LABEL: define double @test_vfmad_laneq_f64(double %a, double %b, <2 x double> %c) #0 {
+// CHECK-LABEL: define double @test_vfmad_laneq_f64(double %a, double %b, <2 x double> %c) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %c to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
// CHECK: [[EXTRACT:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
@@ -215,7 +215,7 @@ float64x1_t test_vfms_lane_f64(float64x1_t a, float64x1_t b, float64x1_t v) {
return vfms_lane_f64(a, b, v, 0);
}
-// CHECK-LABEL: define <1 x double> @test_vfma_laneq_f64(<1 x double> %a, <1 x double> %b, <2 x double> %v) #0 {
+// CHECK-LABEL: define <1 x double> @test_vfma_laneq_f64(<1 x double> %a, <1 x double> %b, <2 x double> %v) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x double> %v to <16 x i8>
@@ -230,7 +230,7 @@ float64x1_t test_vfma_laneq_f64(float64x1_t a, float64x1_t b, float64x2_t v) {
return vfma_laneq_f64(a, b, v, 0);
}
-// CHECK-LABEL: define <1 x double> @test_vfms_laneq_f64(<1 x double> %a, <1 x double> %b, <2 x double> %v) #0 {
+// CHECK-LABEL: define <1 x double> @test_vfms_laneq_f64(<1 x double> %a, <1 x double> %b, <2 x double> %v) #1 {
// CHECK: [[SUB:%.*]] = fsub <1 x double> <double -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> [[SUB]] to <8 x i8>
@@ -269,7 +269,7 @@ int64_t test_vqdmulls_lane_s32(int32_t a, int32x2_t b) {
return vqdmulls_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define i32 @test_vqdmullh_laneq_s16(i16 %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define i32 @test_vqdmullh_laneq_s16(i16 %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -282,7 +282,7 @@ int32_t test_vqdmullh_laneq_s16(int16_t a, int16x8_t b) {
return vqdmullh_laneq_s16(a, b, 7);
}
-// CHECK-LABEL: define i64 @test_vqdmulls_laneq_s32(i32 %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define i64 @test_vqdmulls_laneq_s32(i32 %a, <4 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -316,7 +316,7 @@ int32_t test_vqdmulhs_lane_s32(int32_t a, int32x2_t b) {
}
-// CHECK-LABEL: define i16 @test_vqdmulhh_laneq_s16(i16 %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define i16 @test_vqdmulhh_laneq_s16(i16 %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -330,7 +330,7 @@ int16_t test_vqdmulhh_laneq_s16(int16_t a, int16x8_t b) {
}
-// CHECK-LABEL: define i32 @test_vqdmulhs_laneq_s32(i32 %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define i32 @test_vqdmulhs_laneq_s32(i32 %a, <4 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -364,7 +364,7 @@ int32_t test_vqrdmulhs_lane_s32(int32_t a, int32x2_t b) {
}
-// CHECK-LABEL: define i16 @test_vqrdmulhh_laneq_s16(i16 %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define i16 @test_vqrdmulhh_laneq_s16(i16 %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -378,7 +378,7 @@ int16_t test_vqrdmulhh_laneq_s16(int16_t a, int16x8_t b) {
}
-// CHECK-LABEL: define i32 @test_vqrdmulhs_laneq_s32(i32 %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define i32 @test_vqrdmulhs_laneq_s32(i32 %a, <4 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -413,7 +413,7 @@ int64_t test_vqdmlals_lane_s32(int64_t a, int32_t b, int32x2_t c) {
return vqdmlals_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define i32 @test_vqdmlalh_laneq_s16(i32 %a, i16 %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: define i32 @test_vqdmlalh_laneq_s16(i32 %a, i16 %b, <8 x i16> %c) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %c to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -427,7 +427,7 @@ int32_t test_vqdmlalh_laneq_s16(int32_t a, int16_t b, int16x8_t c) {
return vqdmlalh_laneq_s16(a, b, c, 7);
}
-// CHECK-LABEL: define i64 @test_vqdmlals_laneq_s32(i64 %a, i32 %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: define i64 @test_vqdmlals_laneq_s32(i64 %a, i32 %b, <4 x i32> %c) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %c to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -463,7 +463,7 @@ int64_t test_vqdmlsls_lane_s32(int64_t a, int32_t b, int32x2_t c) {
return vqdmlsls_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define i32 @test_vqdmlslh_laneq_s16(i32 %a, i16 %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: define i32 @test_vqdmlslh_laneq_s16(i32 %a, i16 %b, <8 x i16> %c) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %c to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -477,7 +477,7 @@ int32_t test_vqdmlslh_laneq_s16(int32_t a, int16_t b, int16x8_t c) {
return vqdmlslh_laneq_s16(a, b, c, 7);
}
-// CHECK-LABEL: define i64 @test_vqdmlsls_laneq_s32(i64 %a, i32 %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: define i64 @test_vqdmlsls_laneq_s32(i64 %a, i32 %b, <4 x i32> %c) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %c to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -513,7 +513,7 @@ float64x1_t test_vmulx_lane_f64_0() {
return result;
}
-// CHECK-LABEL: define <1 x double> @test_vmulx_laneq_f64_2() #0 {
+// CHECK-LABEL: define <1 x double> @test_vmulx_laneq_f64_2() #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64 4599917171378402754 to <1 x double>
// CHECK: [[TMP1:%.*]] = bitcast i64 4606655882138939123 to <1 x double>
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <1 x double> [[TMP0]], <1 x double> [[TMP1]], <2 x i32> <i32 0, i32 1>
@@ -540,3 +540,6 @@ float64x1_t test_vmulx_laneq_f64_2() {
result = vmulx_laneq_f64(arg1, arg3, 1);
return result;
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/aarch64-neon-tbl.c b/test/CodeGen/aarch64-neon-tbl.c
index 28881830bfb3..aa117facb706 100644
--- a/test/CodeGen/aarch64-neon-tbl.c
+++ b/test/CodeGen/aarch64-neon-tbl.c
@@ -7,14 +7,14 @@
// CHECK-LABEL: define <8 x i8> @test_vtbl1_s8(<8 x i8> %a, <8 x i8> %b) #0 {
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL11_I]]
int8x8_t test_vtbl1_s8(int8x8_t a, int8x8_t b) {
return vtbl1_s8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqtbl1_s8(<16 x i8> %a, <8 x i8> %b) #0 {
-// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> %a, <8 x i8> %b) #2
+// CHECK-LABEL: define <8 x i8> @test_vqtbl1_s8(<16 x i8> %a, <8 x i8> %b) #1 {
+// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> %a, <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL1_I]]
int8x8_t test_vqtbl1_s8(int8x16_t a, int8x8_t b) {
return vqtbl1_s8(a, b);
@@ -36,7 +36,7 @@ int8x8_t test_vqtbl1_s8(int8x16_t a, int8x8_t b) {
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2_I]], align 8
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL13_I]]
int8x8_t test_vtbl2_s8(int8x8x2_t a, int8x8_t b) {
return vtbl2_s8(a, b);
@@ -57,7 +57,7 @@ int8x8_t test_vtbl2_s8(int8x8x2_t a, int8x8_t b) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBL2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %b) #2
+// CHECK: [[VTBL2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL2_I]]
int8x8_t test_vqtbl2_s8(int8x16x2_t a, int8x8_t b) {
return vqtbl2_s8(a, b);
@@ -83,7 +83,7 @@ int8x8_t test_vqtbl2_s8(int8x16x2_t a, int8x8_t b) {
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL25_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL26_I]]
int8x8_t test_vtbl3_s8(int8x8x3_t a, int8x8_t b) {
return vtbl3_s8(a, b);
@@ -107,7 +107,7 @@ int8x8_t test_vtbl3_s8(int8x8x3_t a, int8x8_t b) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBL3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl3.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %b) #2
+// CHECK: [[VTBL3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl3.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL3_I]]
int8x8_t test_vqtbl3_s8(int8x16x3_t a, int8x8_t b) {
return vqtbl3_s8(a, b);
@@ -136,7 +136,7 @@ int8x8_t test_vqtbl3_s8(int8x16x3_t a, int8x8_t b) {
// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL27_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL27_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL27_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL28_I]]
int8x8_t test_vtbl4_s8(int8x8x4_t a, int8x8_t b) {
return vtbl4_s8(a, b);
@@ -163,20 +163,20 @@ int8x8_t test_vtbl4_s8(int8x8x4_t a, int8x8_t b) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBL4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl4.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %b) #2
+// CHECK: [[VTBL4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl4.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL4_I]]
int8x8_t test_vqtbl4_s8(int8x16x4_t a, int8x8_t b) {
return vqtbl4_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl1q_s8(<16 x i8> %a, <16 x i8> %b) #0 {
-// CHECK: [[VTBL1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl1.v16i8(<16 x i8> %a, <16 x i8> %b) #2
+// CHECK-LABEL: define <16 x i8> @test_vqtbl1q_s8(<16 x i8> %a, <16 x i8> %b) #1 {
+// CHECK: [[VTBL1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl1.v16i8(<16 x i8> %a, <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL1_I]]
int8x16_t test_vqtbl1q_s8(int8x16_t a, int8x16_t b) {
return vqtbl1q_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl2q_s8([2 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl2q_s8([2 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[A]], i32 0, i32 0
@@ -191,13 +191,13 @@ int8x16_t test_vqtbl1q_s8(int8x16_t a, int8x16_t b) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBL2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl2.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %b) #2
+// CHECK: [[VTBL2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl2.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL2_I]]
int8x16_t test_vqtbl2q_s8(int8x16x2_t a, int8x16_t b) {
return vqtbl2q_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl3q_s8([3 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl3q_s8([3 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[A]], i32 0, i32 0
@@ -215,13 +215,13 @@ int8x16_t test_vqtbl2q_s8(int8x16x2_t a, int8x16_t b) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBL3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl3.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %b) #2
+// CHECK: [[VTBL3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl3.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL3_I]]
int8x16_t test_vqtbl3q_s8(int8x16x3_t a, int8x16_t b) {
return vqtbl3q_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl4q_s8([4 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl4q_s8([4 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[A]], i32 0, i32 0
@@ -242,7 +242,7 @@ int8x16_t test_vqtbl3q_s8(int8x16x3_t a, int8x16_t b) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBL4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl4.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %b) #2
+// CHECK: [[VTBL4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl4.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL4_I]]
int8x16_t test_vqtbl4q_s8(int8x16x4_t a, int8x16_t b) {
return vqtbl4q_s8(a, b);
@@ -250,7 +250,7 @@ int8x16_t test_vqtbl4q_s8(int8x16x4_t a, int8x16_t b) {
// CHECK-LABEL: define <8 x i8> @test_vtbx1_s8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> %b, <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %c) #2
+// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %c) #3
// CHECK: [[TMP0:%.*]] = icmp uge <8 x i8> %c, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
// CHECK: [[TMP1:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = and <8 x i8> [[TMP1]], %a
@@ -278,7 +278,7 @@ int8x8_t test_vtbx1_s8(int8x8_t a, int8x8_t b, int8x8_t c) {
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2_I]], align 8
// CHECK: [[VTBX1_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBX13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> [[VTBX1_I]], <8 x i8> %c) #2
+// CHECK: [[VTBX13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> [[VTBX1_I]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX13_I]]
int8x8_t test_vtbx2_s8(int8x8_t a, int8x8x2_t b, int8x8_t c) {
return vtbx2_s8(a, b, c);
@@ -304,7 +304,7 @@ int8x8_t test_vtbx2_s8(int8x8_t a, int8x8x2_t b, int8x8_t c) {
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL25_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %c) #2
+// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %c) #3
// CHECK: [[TMP4:%.*]] = icmp uge <8 x i8> %c, <i8 24, i8 24, i8 24, i8 24, i8 24, i8 24, i8 24, i8 24>
// CHECK: [[TMP5:%.*]] = sext <8 x i1> [[TMP4]] to <8 x i8>
// CHECK: [[TMP6:%.*]] = and <8 x i8> [[TMP5]], %a
@@ -339,14 +339,14 @@ int8x8_t test_vtbx3_s8(int8x8_t a, int8x8x3_t b, int8x8_t c) {
// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6_I]], align 8
// CHECK: [[VTBX2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBX27_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBX28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[VTBX2_I]], <16 x i8> [[VTBX27_I]], <8 x i8> %c) #2
+// CHECK: [[VTBX28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[VTBX2_I]], <16 x i8> [[VTBX27_I]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX28_I]]
int8x8_t test_vtbx4_s8(int8x8_t a, int8x8x4_t b, int8x8_t c) {
return vtbx4_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vqtbx1_s8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #0 {
-// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #2
+// CHECK-LABEL: define <8 x i8> @test_vqtbx1_s8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #1 {
+// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX1_I]]
int8x8_t test_vqtbx1_s8(int8x8_t a, int8x16_t b, int8x8_t c) {
return vqtbx1_s8(a, b, c);
@@ -367,7 +367,7 @@ int8x8_t test_vqtbx1_s8(int8x8_t a, int8x16_t b, int8x8_t c) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBX2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %c) #2
+// CHECK: [[VTBX2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX2_I]]
int8x8_t test_vqtbx2_s8(int8x8_t a, int8x16x2_t b, int8x8_t c) {
return vqtbx2_s8(a, b, c);
@@ -391,7 +391,7 @@ int8x8_t test_vqtbx2_s8(int8x8_t a, int8x16x2_t b, int8x8_t c) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBX3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx3.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %c) #2
+// CHECK: [[VTBX3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx3.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX3_I]]
int8x8_t test_vqtbx3_s8(int8x8_t a, int8x16x3_t b, int8x8_t c) {
return vqtbx3_s8(a, b, c);
@@ -418,20 +418,20 @@ int8x8_t test_vqtbx3_s8(int8x8_t a, int8x16x3_t b, int8x8_t c) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBX4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx4.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %c) #2
+// CHECK: [[VTBX4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx4.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX4_I]]
int8x8_t test_vqtbx4_s8(int8x8_t a, int8x16x4_t b, int8x8_t c) {
return vqtbx4_s8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx1q_s8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
-// CHECK: [[VTBX1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx1.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #2
+// CHECK-LABEL: define <16 x i8> @test_vqtbx1q_s8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #1 {
+// CHECK: [[VTBX1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx1.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX1_I]]
int8x16_t test_vqtbx1q_s8(int8x16_t a, int8x16_t b, int8x16_t c) {
return vqtbx1q_s8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx2q_s8(<16 x i8> %a, [2 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx2q_s8(<16 x i8> %a, [2 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[B]], i32 0, i32 0
@@ -446,13 +446,13 @@ int8x16_t test_vqtbx1q_s8(int8x16_t a, int8x16_t b, int8x16_t c) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBX2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx2.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %c) #2
+// CHECK: [[VTBX2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx2.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX2_I]]
int8x16_t test_vqtbx2q_s8(int8x16_t a, int8x16x2_t b, int8x16_t c) {
return vqtbx2q_s8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx3q_s8(<16 x i8> %a, [3 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx3q_s8(<16 x i8> %a, [3 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[B]], i32 0, i32 0
@@ -470,13 +470,13 @@ int8x16_t test_vqtbx2q_s8(int8x16_t a, int8x16x2_t b, int8x16_t c) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBX3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx3.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %c) #2
+// CHECK: [[VTBX3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx3.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX3_I]]
int8x16_t test_vqtbx3q_s8(int8x16_t a, int8x16x3_t b, int8x16_t c) {
return vqtbx3q_s8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx4q_s8(<16 x i8> %a, [4 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx4q_s8(<16 x i8> %a, [4 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[B]], i32 0, i32 0
@@ -497,7 +497,7 @@ int8x16_t test_vqtbx3q_s8(int8x16_t a, int8x16x3_t b, int8x16_t c) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBX4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx4.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %c) #2
+// CHECK: [[VTBX4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx4.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX4_I]]
int8x16_t test_vqtbx4q_s8(int8x16_t a, int8x16x4_t b, int8x16_t c) {
return vqtbx4q_s8(a, b, c);
@@ -505,14 +505,14 @@ int8x16_t test_vqtbx4q_s8(int8x16_t a, int8x16x4_t b, int8x16_t c) {
// CHECK-LABEL: define <8 x i8> @test_vtbl1_u8(<8 x i8> %a, <8 x i8> %b) #0 {
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL11_I]]
uint8x8_t test_vtbl1_u8(uint8x8_t a, uint8x8_t b) {
return vtbl1_u8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqtbl1_u8(<16 x i8> %a, <8 x i8> %b) #0 {
-// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> %a, <8 x i8> %b) #2
+// CHECK-LABEL: define <8 x i8> @test_vqtbl1_u8(<16 x i8> %a, <8 x i8> %b) #1 {
+// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> %a, <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL1_I]]
uint8x8_t test_vqtbl1_u8(uint8x16_t a, uint8x8_t b) {
return vqtbl1_u8(a, b);
@@ -534,7 +534,7 @@ uint8x8_t test_vqtbl1_u8(uint8x16_t a, uint8x8_t b) {
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2_I]], align 8
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL13_I]]
uint8x8_t test_vtbl2_u8(uint8x8x2_t a, uint8x8_t b) {
return vtbl2_u8(a, b);
@@ -555,7 +555,7 @@ uint8x8_t test_vtbl2_u8(uint8x8x2_t a, uint8x8_t b) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBL2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %b) #2
+// CHECK: [[VTBL2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL2_I]]
uint8x8_t test_vqtbl2_u8(uint8x16x2_t a, uint8x8_t b) {
return vqtbl2_u8(a, b);
@@ -581,7 +581,7 @@ uint8x8_t test_vqtbl2_u8(uint8x16x2_t a, uint8x8_t b) {
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL25_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL26_I]]
uint8x8_t test_vtbl3_u8(uint8x8x3_t a, uint8x8_t b) {
return vtbl3_u8(a, b);
@@ -605,7 +605,7 @@ uint8x8_t test_vtbl3_u8(uint8x8x3_t a, uint8x8_t b) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBL3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl3.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %b) #2
+// CHECK: [[VTBL3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl3.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL3_I]]
uint8x8_t test_vqtbl3_u8(uint8x16x3_t a, uint8x8_t b) {
return vqtbl3_u8(a, b);
@@ -634,7 +634,7 @@ uint8x8_t test_vqtbl3_u8(uint8x16x3_t a, uint8x8_t b) {
// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL27_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL27_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL27_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL28_I]]
uint8x8_t test_vtbl4_u8(uint8x8x4_t a, uint8x8_t b) {
return vtbl4_u8(a, b);
@@ -661,20 +661,20 @@ uint8x8_t test_vtbl4_u8(uint8x8x4_t a, uint8x8_t b) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBL4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl4.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %b) #2
+// CHECK: [[VTBL4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl4.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL4_I]]
uint8x8_t test_vqtbl4_u8(uint8x16x4_t a, uint8x8_t b) {
return vqtbl4_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl1q_u8(<16 x i8> %a, <16 x i8> %b) #0 {
-// CHECK: [[VTBL1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl1.v16i8(<16 x i8> %a, <16 x i8> %b) #2
+// CHECK-LABEL: define <16 x i8> @test_vqtbl1q_u8(<16 x i8> %a, <16 x i8> %b) #1 {
+// CHECK: [[VTBL1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl1.v16i8(<16 x i8> %a, <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL1_I]]
uint8x16_t test_vqtbl1q_u8(uint8x16_t a, uint8x16_t b) {
return vqtbl1q_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl2q_u8([2 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl2q_u8([2 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[A]], i32 0, i32 0
@@ -689,13 +689,13 @@ uint8x16_t test_vqtbl1q_u8(uint8x16_t a, uint8x16_t b) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBL2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl2.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %b) #2
+// CHECK: [[VTBL2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl2.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL2_I]]
uint8x16_t test_vqtbl2q_u8(uint8x16x2_t a, uint8x16_t b) {
return vqtbl2q_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl3q_u8([3 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl3q_u8([3 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[A]], i32 0, i32 0
@@ -713,13 +713,13 @@ uint8x16_t test_vqtbl2q_u8(uint8x16x2_t a, uint8x16_t b) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBL3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl3.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %b) #2
+// CHECK: [[VTBL3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl3.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL3_I]]
uint8x16_t test_vqtbl3q_u8(uint8x16x3_t a, uint8x16_t b) {
return vqtbl3q_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl4q_u8([4 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl4q_u8([4 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[A]], i32 0, i32 0
@@ -740,7 +740,7 @@ uint8x16_t test_vqtbl3q_u8(uint8x16x3_t a, uint8x16_t b) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBL4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl4.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %b) #2
+// CHECK: [[VTBL4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl4.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL4_I]]
uint8x16_t test_vqtbl4q_u8(uint8x16x4_t a, uint8x16_t b) {
return vqtbl4q_u8(a, b);
@@ -748,7 +748,7 @@ uint8x16_t test_vqtbl4q_u8(uint8x16x4_t a, uint8x16_t b) {
// CHECK-LABEL: define <8 x i8> @test_vtbx1_u8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> %b, <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %c) #2
+// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %c) #3
// CHECK: [[TMP0:%.*]] = icmp uge <8 x i8> %c, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
// CHECK: [[TMP1:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = and <8 x i8> [[TMP1]], %a
@@ -776,7 +776,7 @@ uint8x8_t test_vtbx1_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c) {
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2_I]], align 8
// CHECK: [[VTBX1_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBX13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> [[VTBX1_I]], <8 x i8> %c) #2
+// CHECK: [[VTBX13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> [[VTBX1_I]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX13_I]]
uint8x8_t test_vtbx2_u8(uint8x8_t a, uint8x8x2_t b, uint8x8_t c) {
return vtbx2_u8(a, b, c);
@@ -802,7 +802,7 @@ uint8x8_t test_vtbx2_u8(uint8x8_t a, uint8x8x2_t b, uint8x8_t c) {
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL25_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %c) #2
+// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %c) #3
// CHECK: [[TMP4:%.*]] = icmp uge <8 x i8> %c, <i8 24, i8 24, i8 24, i8 24, i8 24, i8 24, i8 24, i8 24>
// CHECK: [[TMP5:%.*]] = sext <8 x i1> [[TMP4]] to <8 x i8>
// CHECK: [[TMP6:%.*]] = and <8 x i8> [[TMP5]], %a
@@ -837,14 +837,14 @@ uint8x8_t test_vtbx3_u8(uint8x8_t a, uint8x8x3_t b, uint8x8_t c) {
// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6_I]], align 8
// CHECK: [[VTBX2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBX27_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBX28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[VTBX2_I]], <16 x i8> [[VTBX27_I]], <8 x i8> %c) #2
+// CHECK: [[VTBX28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[VTBX2_I]], <16 x i8> [[VTBX27_I]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX28_I]]
uint8x8_t test_vtbx4_u8(uint8x8_t a, uint8x8x4_t b, uint8x8_t c) {
return vtbx4_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vqtbx1_u8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #0 {
-// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #2
+// CHECK-LABEL: define <8 x i8> @test_vqtbx1_u8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #1 {
+// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX1_I]]
uint8x8_t test_vqtbx1_u8(uint8x8_t a, uint8x16_t b, uint8x8_t c) {
return vqtbx1_u8(a, b, c);
@@ -865,7 +865,7 @@ uint8x8_t test_vqtbx1_u8(uint8x8_t a, uint8x16_t b, uint8x8_t c) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBX2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %c) #2
+// CHECK: [[VTBX2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX2_I]]
uint8x8_t test_vqtbx2_u8(uint8x8_t a, uint8x16x2_t b, uint8x8_t c) {
return vqtbx2_u8(a, b, c);
@@ -889,7 +889,7 @@ uint8x8_t test_vqtbx2_u8(uint8x8_t a, uint8x16x2_t b, uint8x8_t c) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBX3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx3.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %c) #2
+// CHECK: [[VTBX3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx3.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX3_I]]
uint8x8_t test_vqtbx3_u8(uint8x8_t a, uint8x16x3_t b, uint8x8_t c) {
return vqtbx3_u8(a, b, c);
@@ -916,20 +916,20 @@ uint8x8_t test_vqtbx3_u8(uint8x8_t a, uint8x16x3_t b, uint8x8_t c) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBX4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx4.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %c) #2
+// CHECK: [[VTBX4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx4.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX4_I]]
uint8x8_t test_vqtbx4_u8(uint8x8_t a, uint8x16x4_t b, uint8x8_t c) {
return vqtbx4_u8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx1q_u8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
-// CHECK: [[VTBX1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx1.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #2
+// CHECK-LABEL: define <16 x i8> @test_vqtbx1q_u8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #1 {
+// CHECK: [[VTBX1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx1.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX1_I]]
uint8x16_t test_vqtbx1q_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c) {
return vqtbx1q_u8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx2q_u8(<16 x i8> %a, [2 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx2q_u8(<16 x i8> %a, [2 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[B]], i32 0, i32 0
@@ -944,13 +944,13 @@ uint8x16_t test_vqtbx1q_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBX2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx2.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %c) #2
+// CHECK: [[VTBX2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx2.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX2_I]]
uint8x16_t test_vqtbx2q_u8(uint8x16_t a, uint8x16x2_t b, uint8x16_t c) {
return vqtbx2q_u8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx3q_u8(<16 x i8> %a, [3 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx3q_u8(<16 x i8> %a, [3 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[B]], i32 0, i32 0
@@ -968,13 +968,13 @@ uint8x16_t test_vqtbx2q_u8(uint8x16_t a, uint8x16x2_t b, uint8x16_t c) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBX3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx3.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %c) #2
+// CHECK: [[VTBX3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx3.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX3_I]]
uint8x16_t test_vqtbx3q_u8(uint8x16_t a, uint8x16x3_t b, uint8x16_t c) {
return vqtbx3q_u8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx4q_u8(<16 x i8> %a, [4 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx4q_u8(<16 x i8> %a, [4 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[B]], i32 0, i32 0
@@ -995,7 +995,7 @@ uint8x16_t test_vqtbx3q_u8(uint8x16_t a, uint8x16x3_t b, uint8x16_t c) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBX4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx4.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %c) #2
+// CHECK: [[VTBX4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx4.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX4_I]]
uint8x16_t test_vqtbx4q_u8(uint8x16_t a, uint8x16x4_t b, uint8x16_t c) {
return vqtbx4q_u8(a, b, c);
@@ -1003,14 +1003,14 @@ uint8x16_t test_vqtbx4q_u8(uint8x16_t a, uint8x16x4_t b, uint8x16_t c) {
// CHECK-LABEL: define <8 x i8> @test_vtbl1_p8(<8 x i8> %a, <8 x i8> %b) #0 {
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL11_I]]
poly8x8_t test_vtbl1_p8(poly8x8_t a, uint8x8_t b) {
return vtbl1_p8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqtbl1_p8(<16 x i8> %a, <8 x i8> %b) #0 {
-// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> %a, <8 x i8> %b) #2
+// CHECK-LABEL: define <8 x i8> @test_vqtbl1_p8(<16 x i8> %a, <8 x i8> %b) #1 {
+// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> %a, <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL1_I]]
poly8x8_t test_vqtbl1_p8(poly8x16_t a, uint8x8_t b) {
return vqtbl1_p8(a, b);
@@ -1032,7 +1032,7 @@ poly8x8_t test_vqtbl1_p8(poly8x16_t a, uint8x8_t b) {
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2_I]], align 8
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL13_I]]
poly8x8_t test_vtbl2_p8(poly8x8x2_t a, uint8x8_t b) {
return vtbl2_p8(a, b);
@@ -1053,7 +1053,7 @@ poly8x8_t test_vtbl2_p8(poly8x8x2_t a, uint8x8_t b) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBL2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %b) #2
+// CHECK: [[VTBL2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL2_I]]
poly8x8_t test_vqtbl2_p8(poly8x16x2_t a, uint8x8_t b) {
return vqtbl2_p8(a, b);
@@ -1079,7 +1079,7 @@ poly8x8_t test_vqtbl2_p8(poly8x16x2_t a, uint8x8_t b) {
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL25_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL26_I]]
poly8x8_t test_vtbl3_p8(poly8x8x3_t a, uint8x8_t b) {
return vtbl3_p8(a, b);
@@ -1103,7 +1103,7 @@ poly8x8_t test_vtbl3_p8(poly8x8x3_t a, uint8x8_t b) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBL3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl3.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %b) #2
+// CHECK: [[VTBL3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl3.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL3_I]]
poly8x8_t test_vqtbl3_p8(poly8x16x3_t a, uint8x8_t b) {
return vqtbl3_p8(a, b);
@@ -1132,7 +1132,7 @@ poly8x8_t test_vqtbl3_p8(poly8x16x3_t a, uint8x8_t b) {
// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL27_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL27_I]], <8 x i8> %b) #2
+// CHECK: [[VTBL28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL27_I]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL28_I]]
poly8x8_t test_vtbl4_p8(poly8x8x4_t a, uint8x8_t b) {
return vtbl4_p8(a, b);
@@ -1159,20 +1159,20 @@ poly8x8_t test_vtbl4_p8(poly8x8x4_t a, uint8x8_t b) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBL4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl4.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %b) #2
+// CHECK: [[VTBL4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl4.v8i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %b) #3
// CHECK: ret <8 x i8> [[VTBL4_I]]
poly8x8_t test_vqtbl4_p8(poly8x16x4_t a, uint8x8_t b) {
return vqtbl4_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl1q_p8(<16 x i8> %a, <16 x i8> %b) #0 {
-// CHECK: [[VTBL1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl1.v16i8(<16 x i8> %a, <16 x i8> %b) #2
+// CHECK-LABEL: define <16 x i8> @test_vqtbl1q_p8(<16 x i8> %a, <16 x i8> %b) #1 {
+// CHECK: [[VTBL1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl1.v16i8(<16 x i8> %a, <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL1_I]]
poly8x16_t test_vqtbl1q_p8(poly8x16_t a, uint8x16_t b) {
return vqtbl1q_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl2q_p8([2 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl2q_p8([2 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[A]], i32 0, i32 0
@@ -1187,13 +1187,13 @@ poly8x16_t test_vqtbl1q_p8(poly8x16_t a, uint8x16_t b) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBL2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl2.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %b) #2
+// CHECK: [[VTBL2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl2.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL2_I]]
poly8x16_t test_vqtbl2q_p8(poly8x16x2_t a, uint8x16_t b) {
return vqtbl2q_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl3q_p8([3 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl3q_p8([3 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[A]], i32 0, i32 0
@@ -1211,13 +1211,13 @@ poly8x16_t test_vqtbl2q_p8(poly8x16x2_t a, uint8x16_t b) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBL3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl3.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %b) #2
+// CHECK: [[VTBL3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl3.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL3_I]]
poly8x16_t test_vqtbl3q_p8(poly8x16x3_t a, uint8x16_t b) {
return vqtbl3q_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbl4q_p8([4 x <16 x i8>] %a.coerce, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbl4q_p8([4 x <16 x i8>] %a.coerce, <16 x i8> %b) #1 {
// CHECK: [[__P0_I:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[A:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[A]], i32 0, i32 0
@@ -1238,7 +1238,7 @@ poly8x16_t test_vqtbl3q_p8(poly8x16x3_t a, uint8x16_t b) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__P0_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBL4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl4.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %b) #2
+// CHECK: [[VTBL4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbl4.v16i8(<16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %b) #3
// CHECK: ret <16 x i8> [[VTBL4_I]]
poly8x16_t test_vqtbl4q_p8(poly8x16x4_t a, uint8x16_t b) {
return vqtbl4q_p8(a, b);
@@ -1246,7 +1246,7 @@ poly8x16_t test_vqtbl4q_p8(poly8x16x4_t a, uint8x16_t b) {
// CHECK-LABEL: define <8 x i8> @test_vtbx1_p8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
// CHECK: [[VTBL1_I:%.*]] = shufflevector <8 x i8> %b, <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %c) #2
+// CHECK: [[VTBL11_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl1.v8i8(<16 x i8> [[VTBL1_I]], <8 x i8> %c) #3
// CHECK: [[TMP0:%.*]] = icmp uge <8 x i8> %c, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
// CHECK: [[TMP1:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = and <8 x i8> [[TMP1]], %a
@@ -1274,7 +1274,7 @@ poly8x8_t test_vtbx1_p8(poly8x8_t a, poly8x8_t b, uint8x8_t c) {
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2_I]], align 8
// CHECK: [[VTBX1_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBX13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> [[VTBX1_I]], <8 x i8> %c) #2
+// CHECK: [[VTBX13_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> [[VTBX1_I]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX13_I]]
poly8x8_t test_vtbx2_p8(poly8x8_t a, poly8x8x2_t b, uint8x8_t c) {
return vtbx2_p8(a, b, c);
@@ -1300,7 +1300,7 @@ poly8x8_t test_vtbx2_p8(poly8x8_t a, poly8x8x2_t b, uint8x8_t c) {
// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4_I]], align 8
// CHECK: [[VTBL2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBL25_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %c) #2
+// CHECK: [[VTBL26_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbl2.v8i8(<16 x i8> [[VTBL2_I]], <16 x i8> [[VTBL25_I]], <8 x i8> %c) #3
// CHECK: [[TMP4:%.*]] = icmp uge <8 x i8> %c, <i8 24, i8 24, i8 24, i8 24, i8 24, i8 24, i8 24, i8 24>
// CHECK: [[TMP5:%.*]] = sext <8 x i1> [[TMP4]] to <8 x i8>
// CHECK: [[TMP6:%.*]] = and <8 x i8> [[TMP5]], %a
@@ -1335,14 +1335,14 @@ poly8x8_t test_vtbx3_p8(poly8x8_t a, poly8x8x3_t b, uint8x8_t c) {
// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6_I]], align 8
// CHECK: [[VTBX2_I:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VTBX27_I:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
-// CHECK: [[VTBX28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[VTBX2_I]], <16 x i8> [[VTBX27_I]], <8 x i8> %c) #2
+// CHECK: [[VTBX28_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[VTBX2_I]], <16 x i8> [[VTBX27_I]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX28_I]]
poly8x8_t test_vtbx4_p8(poly8x8_t a, poly8x8x4_t b, uint8x8_t c) {
return vtbx4_p8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vqtbx1_p8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #0 {
-// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #2
+// CHECK-LABEL: define <8 x i8> @test_vqtbx1_p8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #1 {
+// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx1.v8i8(<8 x i8> %a, <16 x i8> %b, <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX1_I]]
poly8x8_t test_vqtbx1_p8(poly8x8_t a, uint8x16_t b, uint8x8_t c) {
return vqtbx1_p8(a, b, c);
@@ -1363,7 +1363,7 @@ poly8x8_t test_vqtbx1_p8(poly8x8_t a, uint8x16_t b, uint8x8_t c) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBX2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %c) #2
+// CHECK: [[VTBX2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx2.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX2_I]]
poly8x8_t test_vqtbx2_p8(poly8x8_t a, poly8x16x2_t b, uint8x8_t c) {
return vqtbx2_p8(a, b, c);
@@ -1387,7 +1387,7 @@ poly8x8_t test_vqtbx2_p8(poly8x8_t a, poly8x16x2_t b, uint8x8_t c) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBX3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx3.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %c) #2
+// CHECK: [[VTBX3_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx3.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX3_I]]
poly8x8_t test_vqtbx3_p8(poly8x8_t a, poly8x16x3_t b, uint8x8_t c) {
return vqtbx3_p8(a, b, c);
@@ -1414,20 +1414,20 @@ poly8x8_t test_vqtbx3_p8(poly8x8_t a, poly8x16x3_t b, uint8x8_t c) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBX4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx4.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %c) #2
+// CHECK: [[VTBX4_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.tbx4.v8i8(<8 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <8 x i8> %c) #3
// CHECK: ret <8 x i8> [[VTBX4_I]]
poly8x8_t test_vqtbx4_p8(poly8x8_t a, poly8x16x4_t b, uint8x8_t c) {
return vqtbx4_p8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx1q_p8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
-// CHECK: [[VTBX1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx1.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #2
+// CHECK-LABEL: define <16 x i8> @test_vqtbx1q_p8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #1 {
+// CHECK: [[VTBX1_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx1.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX1_I]]
poly8x16_t test_vqtbx1q_p8(poly8x16_t a, uint8x16_t b, uint8x16_t c) {
return vqtbx1q_p8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx2q_p8(<16 x i8> %a, [2 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx2q_p8(<16 x i8> %a, [2 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[B]], i32 0, i32 0
@@ -1442,13 +1442,13 @@ poly8x16_t test_vqtbx1q_p8(poly8x16_t a, uint8x16_t b, uint8x16_t c) {
// CHECK: [[VAL1_I:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX2_I:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1_I]], i64 0, i64 1
// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2_I]], align 16
-// CHECK: [[VTBX2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx2.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %c) #2
+// CHECK: [[VTBX2_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx2.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX2_I]]
poly8x16_t test_vqtbx2q_p8(poly8x16_t a, poly8x16x2_t b, uint8x16_t c) {
return vqtbx2q_p8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx3q_p8(<16 x i8> %a, [3 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx3q_p8(<16 x i8> %a, [3 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[B]], i32 0, i32 0
@@ -1466,13 +1466,13 @@ poly8x16_t test_vqtbx2q_p8(poly8x16_t a, poly8x16x2_t b, uint8x16_t c) {
// CHECK: [[VAL3_I:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX4_I:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3_I]], i64 0, i64 2
// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4_I]], align 16
-// CHECK: [[VTBX3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx3.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %c) #2
+// CHECK: [[VTBX3_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx3.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX3_I]]
poly8x16_t test_vqtbx3q_p8(poly8x16_t a, poly8x16x3_t b, uint8x16_t c) {
return vqtbx3q_p8(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vqtbx4q_p8(<16 x i8> %a, [4 x <16 x i8>] %b.coerce, <16 x i8> %c) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vqtbx4q_p8(<16 x i8> %a, [4 x <16 x i8>] %b.coerce, <16 x i8> %c) #1 {
// CHECK: [[__P1_I:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[B]], i32 0, i32 0
@@ -1493,8 +1493,11 @@ poly8x16_t test_vqtbx3q_p8(poly8x16_t a, poly8x16x3_t b, uint8x16_t c) {
// CHECK: [[VAL5_I:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__P1_I]], i32 0, i32 0
// CHECK: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5_I]], i64 0, i64 3
// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6_I]], align 16
-// CHECK: [[VTBX4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx4.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %c) #2
+// CHECK: [[VTBX4_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.tbx4.v16i8(<16 x i8> %a, <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> %c) #3
// CHECK: ret <16 x i8> [[VTBX4_I]]
poly8x16_t test_vqtbx4q_p8(poly8x16_t a, poly8x16x4_t b, uint8x16_t c) {
return vqtbx4q_p8(a, b, c);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/aarch64-neon-vget.c b/test/CodeGen/aarch64-neon-vget.c
index ac7bc2d68a43..cd25ec3ee236 100644
--- a/test/CodeGen/aarch64-neon-vget.c
+++ b/test/CodeGen/aarch64-neon-vget.c
@@ -97,14 +97,14 @@ float32_t test_vget_lane_f16(float16x4_t a) {
return vget_lane_f16(a, 1);
}
-// CHECK-LABEL: define i8 @test_vgetq_lane_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i8 @test_vgetq_lane_u8(<16 x i8> %a) #1 {
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGETQ_LANE]]
uint8_t test_vgetq_lane_u8(uint8x16_t a) {
return vgetq_lane_u8(a, 15);
}
-// CHECK-LABEL: define i16 @test_vgetq_lane_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i16 @test_vgetq_lane_u16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -113,7 +113,7 @@ uint16_t test_vgetq_lane_u16(uint16x8_t a) {
return vgetq_lane_u16(a, 7);
}
-// CHECK-LABEL: define i32 @test_vgetq_lane_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: define i32 @test_vgetq_lane_u32(<4 x i32> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -122,14 +122,14 @@ uint32_t test_vgetq_lane_u32(uint32x4_t a) {
return vgetq_lane_u32(a, 3);
}
-// CHECK-LABEL: define i8 @test_vgetq_lane_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i8 @test_vgetq_lane_s8(<16 x i8> %a) #1 {
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGETQ_LANE]]
int8_t test_vgetq_lane_s8(int8x16_t a) {
return vgetq_lane_s8(a, 15);
}
-// CHECK-LABEL: define i16 @test_vgetq_lane_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i16 @test_vgetq_lane_s16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -138,7 +138,7 @@ int16_t test_vgetq_lane_s16(int16x8_t a) {
return vgetq_lane_s16(a, 7);
}
-// CHECK-LABEL: define i32 @test_vgetq_lane_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: define i32 @test_vgetq_lane_s32(<4 x i32> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -147,14 +147,14 @@ int32_t test_vgetq_lane_s32(int32x4_t a) {
return vgetq_lane_s32(a, 3);
}
-// CHECK-LABEL: define i8 @test_vgetq_lane_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i8 @test_vgetq_lane_p8(<16 x i8> %a) #1 {
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGETQ_LANE]]
poly8_t test_vgetq_lane_p8(poly8x16_t a) {
return vgetq_lane_p8(a, 15);
}
-// CHECK-LABEL: define i16 @test_vgetq_lane_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i16 @test_vgetq_lane_p16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -163,7 +163,7 @@ poly16_t test_vgetq_lane_p16(poly16x8_t a) {
return vgetq_lane_p16(a, 7);
}
-// CHECK-LABEL: define float @test_vgetq_lane_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: define float @test_vgetq_lane_f32(<4 x float> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
@@ -172,7 +172,7 @@ float32_t test_vgetq_lane_f32(float32x4_t a) {
return vgetq_lane_f32(a, 3);
}
-// CHECK-LABEL: define float @test_vgetq_lane_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: define float @test_vgetq_lane_f16(<8 x half> %a) #1 {
// CHECK: [[__REINT_244:%.*]] = alloca <8 x half>, align 16
// CHECK: [[__REINT1_244:%.*]] = alloca i16, align 2
// CHECK: store <8 x half> %a, <8 x half>* [[__REINT_244]], align 16
@@ -208,7 +208,7 @@ uint64_t test_vget_lane_u64(uint64x1_t a) {
return vget_lane_u64(a, 0);
}
-// CHECK-LABEL: define i64 @test_vgetq_lane_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: define i64 @test_vgetq_lane_s64(<2 x i64> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -217,7 +217,7 @@ int64_t test_vgetq_lane_s64(int64x2_t a) {
return vgetq_lane_s64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vgetq_lane_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: define i64 @test_vgetq_lane_u64(<2 x i64> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -324,14 +324,14 @@ float16x4_t test_vset_lane_f16(float16_t *a, float16x4_t b) {
return vset_lane_f16(*a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_u8(i8 %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_u8(i8 %a, <16 x i8> %b) #1 {
// CHECK: [[VSET_LANE:%.*]] = insertelement <16 x i8> %b, i8 %a, i32 15
// CHECK: ret <16 x i8> [[VSET_LANE]]
uint8x16_t test_vsetq_lane_u8(uint8_t a, uint8x16_t b) {
return vsetq_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_u16(i16 %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_u16(i16 %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i16> [[TMP1]], i16 %a, i32 7
@@ -340,7 +340,7 @@ uint16x8_t test_vsetq_lane_u16(uint16_t a, uint16x8_t b) {
return vsetq_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define <4 x i32> @test_vsetq_lane_u32(i32 %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vsetq_lane_u32(i32 %a, <4 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x i32> [[TMP1]], i32 %a, i32 3
@@ -349,14 +349,14 @@ uint32x4_t test_vsetq_lane_u32(uint32_t a, uint32x4_t b) {
return vsetq_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_s8(i8 %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_s8(i8 %a, <16 x i8> %b) #1 {
// CHECK: [[VSET_LANE:%.*]] = insertelement <16 x i8> %b, i8 %a, i32 15
// CHECK: ret <16 x i8> [[VSET_LANE]]
int8x16_t test_vsetq_lane_s8(int8_t a, int8x16_t b) {
return vsetq_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_s16(i16 %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_s16(i16 %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i16> [[TMP1]], i16 %a, i32 7
@@ -365,7 +365,7 @@ int16x8_t test_vsetq_lane_s16(int16_t a, int16x8_t b) {
return vsetq_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define <4 x i32> @test_vsetq_lane_s32(i32 %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vsetq_lane_s32(i32 %a, <4 x i32> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x i32> [[TMP1]], i32 %a, i32 3
@@ -374,14 +374,14 @@ int32x4_t test_vsetq_lane_s32(int32_t a, int32x4_t b) {
return vsetq_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_p8(i8 %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_p8(i8 %a, <16 x i8> %b) #1 {
// CHECK: [[VSET_LANE:%.*]] = insertelement <16 x i8> %b, i8 %a, i32 15
// CHECK: ret <16 x i8> [[VSET_LANE]]
poly8x16_t test_vsetq_lane_p8(poly8_t a, poly8x16_t b) {
return vsetq_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_p16(i16 %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_p16(i16 %a, <8 x i16> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i16> [[TMP1]], i16 %a, i32 7
@@ -390,7 +390,7 @@ poly16x8_t test_vsetq_lane_p16(poly16_t a, poly16x8_t b) {
return vsetq_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define <4 x float> @test_vsetq_lane_f32(float %a, <4 x float> %b) #0 {
+// CHECK-LABEL: define <4 x float> @test_vsetq_lane_f32(float %a, <4 x float> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x float> [[TMP1]], float %a, i32 3
@@ -399,7 +399,7 @@ float32x4_t test_vsetq_lane_f32(float32_t a, float32x4_t b) {
return vsetq_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define <8 x half> @test_vsetq_lane_f16(half* %a, <8 x half> %b) #0 {
+// CHECK-LABEL: define <8 x half> @test_vsetq_lane_f16(half* %a, <8 x half> %b) #1 {
// CHECK: [[__REINT_248:%.*]] = alloca half, align 2
// CHECK: [[__REINT1_248:%.*]] = alloca <8 x half>, align 16
// CHECK: [[__REINT2_248:%.*]] = alloca <8 x i16>, align 16
@@ -439,7 +439,7 @@ uint64x1_t test_vset_lane_u64(uint64_t a, uint64x1_t b) {
return vset_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_s64(i64 %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_s64(i64 %a, <2 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x i64> [[TMP1]], i64 %a, i32 1
@@ -448,7 +448,7 @@ int64x2_t test_vsetq_lane_s64(int64_t a, int64x2_t b) {
return vsetq_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_u64(i64 %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_u64(i64 %a, <2 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x i64> [[TMP1]], i64 %a, i32 1
@@ -456,3 +456,6 @@ int64x2_t test_vsetq_lane_s64(int64_t a, int64x2_t b) {
uint64x2_t test_vsetq_lane_u64(uint64_t a, uint64x2_t b) {
return vsetq_lane_u64(a, b, 1);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/aarch64-poly128.c b/test/CodeGen/aarch64-poly128.c
index d33d936717dc..d139cfecb31e 100644
--- a/test/CodeGen/aarch64-poly128.c
+++ b/test/CodeGen/aarch64-poly128.c
@@ -47,201 +47,201 @@ void test_ld_st_p128(poly128_t * ptr) {
}
// CHECK-LABEL: define i128 @test_vmull_p64(i64 %a, i64 %b) #0 {
-// CHECK: [[VMULL_P64_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.pmull64(i64 %a, i64 %b) #2
+// CHECK: [[VMULL_P64_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.pmull64(i64 %a, i64 %b) #3
// CHECK: [[VMULL_P641_I:%.*]] = bitcast <16 x i8> [[VMULL_P64_I]] to i128
// CHECK: ret i128 [[VMULL_P641_I]]
poly128_t test_vmull_p64(poly64_t a, poly64_t b) {
return vmull_p64(a, b);
}
-// CHECK-LABEL: define i128 @test_vmull_high_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define i128 @test_vmull_high_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %a, <1 x i32> <i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> [[SHUFFLE_I_I]] to i64
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <2 x i64> %b, <2 x i64> %b, <1 x i32> <i32 1>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> [[SHUFFLE_I7_I]] to i64
-// CHECK: [[VMULL_P64_I_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.pmull64(i64 [[TMP0]], i64 [[TMP1]]) #2
+// CHECK: [[VMULL_P64_I_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.pmull64(i64 [[TMP0]], i64 [[TMP1]]) #3
// CHECK: [[VMULL_P641_I_I:%.*]] = bitcast <16 x i8> [[VMULL_P64_I_I]] to i128
// CHECK: ret i128 [[VMULL_P641_I_I]]
poly128_t test_vmull_high_p64(poly64x2_t a, poly64x2_t b) {
return vmull_high_p64(a, b);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s8(<16 x i8> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_s8(int8x16_t a) {
return vreinterpretq_p128_s8(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_s16(int16x8_t a) {
return vreinterpretq_p128_s16(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s32(<4 x i32> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_s32(int32x4_t a) {
return vreinterpretq_p128_s32(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_s64(<2 x i64> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_s64(int64x2_t a) {
return vreinterpretq_p128_s64(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u8(<16 x i8> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_u8(uint8x16_t a) {
return vreinterpretq_p128_u8(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_u16(uint16x8_t a) {
return vreinterpretq_p128_u16(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u32(<4 x i32> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_u32(uint32x4_t a) {
return vreinterpretq_p128_u32(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_u64(<2 x i64> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_u64(uint64x2_t a) {
return vreinterpretq_p128_u64(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_f32(<4 x float> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_f32(float32x4_t a) {
return vreinterpretq_p128_f32(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_f64(<2 x double> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_f64(float64x2_t a) {
return vreinterpretq_p128_f64(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_p8(<16 x i8> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_p8(poly8x16_t a) {
return vreinterpretq_p128_p8(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_p16(<8 x i16> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_p16(poly16x8_t a) {
return vreinterpretq_p128_p16(a);
}
-// CHECK-LABEL: define i128 @test_vreinterpretq_p128_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: define i128 @test_vreinterpretq_p128_p64(<2 x i64> %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to i128
// CHECK: ret i128 [[TMP0]]
poly128_t test_vreinterpretq_p128_p64(poly64x2_t a) {
return vreinterpretq_p128_p64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_p128(i128 %a) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_p128(poly128_t a) {
return vreinterpretq_s8_p128(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_p128(i128 %a) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_p128(poly128_t a) {
return vreinterpretq_s16_p128(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_p128(i128 %a) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_p128(poly128_t a) {
return vreinterpretq_s32_p128(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_p128(i128 %a) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_p128(poly128_t a) {
return vreinterpretq_s64_p128(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_p128(i128 %a) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_p128(poly128_t a) {
return vreinterpretq_u8_p128(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_p128(i128 %a) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_p128(poly128_t a) {
return vreinterpretq_u16_p128(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_p128(i128 %a) #0 {
+// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_p128(poly128_t a) {
return vreinterpretq_u32_p128(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_p128(i128 %a) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_p128(poly128_t a) {
return vreinterpretq_u64_p128(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_p128(i128 %a) #0 {
+// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_p128(poly128_t a) {
return vreinterpretq_f32_p128(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_p128(i128 %a) #0 {
+// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_p128(poly128_t a) {
return vreinterpretq_f64_p128(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_p128(i128 %a) #0 {
+// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_p128(poly128_t a) {
return vreinterpretq_p8_p128(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_p128(i128 %a) #0 {
+// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_p128(poly128_t a) {
return vreinterpretq_p16_p128(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_p128(i128 %a) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_p128(i128 %a) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i128 %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_p128(poly128_t a) {
diff --git a/test/CodeGen/aarch64-poly64.c b/test/CodeGen/aarch64-poly64.c
index b70e5f0765e2..cdf91699c9b0 100644
--- a/test/CodeGen/aarch64-poly64.c
+++ b/test/CodeGen/aarch64-poly64.c
@@ -14,7 +14,7 @@ uint64x1_t test_vceq_p64(poly64x1_t a, poly64x1_t b) {
return vceq_p64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vceqq_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vceqq_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[CMP_I:%.*]] = icmp eq <2 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -31,7 +31,7 @@ uint64x1_t test_vtst_p64(poly64x1_t a, poly64x1_t b) {
return vtst_p64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vtstq_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vtstq_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[TMP4:%.*]] = and <2 x i64> %a, %b
// CHECK: [[TMP5:%.*]] = icmp ne <2 x i64> [[TMP4]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i64>
@@ -50,7 +50,7 @@ poly64x1_t test_vbsl_p64(poly64x1_t a, poly64x1_t b, poly64x1_t c) {
return vbsl_p64(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vbslq_p64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vbslq_p64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) #1 {
// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> %a, %b
// CHECK: [[TMP3:%.*]] = xor <2 x i64> %a, <i64 -1, i64 -1>
// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], %c
@@ -69,7 +69,7 @@ poly64_t test_vget_lane_p64(poly64x1_t v) {
return vget_lane_p64(v, 0);
}
-// CHECK-LABEL: define i64 @test_vgetq_lane_p64(<2 x i64> %v) #0 {
+// CHECK-LABEL: define i64 @test_vgetq_lane_p64(<2 x i64> %v) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %v to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -87,7 +87,7 @@ poly64x1_t test_vset_lane_p64(poly64_t a, poly64x1_t v) {
return vset_lane_p64(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_p64(i64 %a, <2 x i64> %v) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_p64(i64 %a, <2 x i64> %v) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %v to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x i64> [[TMP1]], i64 %a, i32 1
@@ -109,7 +109,7 @@ poly64x1_t test_vcopy_lane_p64(poly64x1_t a, poly64x1_t b) {
}
-// CHECK-LABEL: define <2 x i64> @test_vcopyq_lane_p64(<2 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vcopyq_lane_p64(<2 x i64> %a, <1 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VGET_LANE:%.*]] = extractelement <1 x i64> [[TMP1]], i32 0
@@ -121,7 +121,7 @@ poly64x2_t test_vcopyq_lane_p64(poly64x2_t a, poly64x1_t b) {
return vcopyq_lane_p64(a, 1, b, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vcopyq_laneq_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vcopyq_laneq_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGETQ_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -146,7 +146,7 @@ poly64x1_t test_vcreate_p64(uint64_t a) {
poly64x1_t test_vdup_n_p64(poly64_t a) {
return vdup_n_p64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vdupq_n_p64(i64 %a) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vdupq_n_p64(i64 %a) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i64> undef, i64 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i64> [[VECINIT_I]], i64 %a, i32 1
// CHECK: ret <2 x i64> [[VECINIT1_I]]
@@ -161,7 +161,7 @@ poly64x1_t test_vmov_n_p64(poly64_t a) {
return vmov_n_p64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovq_n_p64(i64 %a) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vmovq_n_p64(i64 %a) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i64> undef, i64 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i64> [[VECINIT_I]], i64 %a, i32 1
// CHECK: ret <2 x i64> [[VECINIT1_I]]
@@ -176,21 +176,21 @@ poly64x1_t test_vdup_lane_p64(poly64x1_t vec) {
return vdup_lane_p64(vec, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vdupq_lane_p64(<1 x i64> %vec) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vdupq_lane_p64(<1 x i64> %vec) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x i64> %vec, <1 x i64> %vec, <2 x i32> zeroinitializer
// CHECK: ret <2 x i64> [[SHUFFLE]]
poly64x2_t test_vdupq_lane_p64(poly64x1_t vec) {
return vdupq_lane_p64(vec, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vdupq_laneq_p64(<2 x i64> %vec) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vdupq_laneq_p64(<2 x i64> %vec) #1 {
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i64> %vec, <2 x i64> %vec, <2 x i32> <i32 1, i32 1>
// CHECK: ret <2 x i64> [[SHUFFLE]]
poly64x2_t test_vdupq_laneq_p64(poly64x2_t vec) {
return vdupq_laneq_p64(vec, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vcombine_p64(<1 x i64> %low, <1 x i64> %high) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vcombine_p64(<1 x i64> %low, <1 x i64> %high) #1 {
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <1 x i64> %low, <1 x i64> %high, <2 x i32> <i32 0, i32 1>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
poly64x2_t test_vcombine_p64(poly64x1_t low, poly64x1_t high) {
@@ -206,7 +206,7 @@ poly64x1_t test_vld1_p64(poly64_t const * ptr) {
return vld1_p64(ptr);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_p64(i64* %ptr) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vld1q_p64(i64* %ptr) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <2 x i64>*
// CHECK: [[TMP2:%.*]] = load <2 x i64>, <2 x i64>* [[TMP1]]
@@ -226,7 +226,7 @@ void test_vst1_p64(poly64_t * ptr, poly64x1_t val) {
return vst1_p64(ptr, val);
}
-// CHECK-LABEL: define void @test_vst1q_p64(i64* %ptr, <2 x i64> %val) #0 {
+// CHECK-LABEL: define void @test_vst1q_p64(i64* %ptr, <2 x i64> %val) #1 {
// CHECK: [[TMP0:%.*]] = bitcast i64* %ptr to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %val to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <2 x i64>*
@@ -237,7 +237,7 @@ void test_vst1q_p64(poly64_t * ptr, poly64x2_t val) {
return vst1q_p64(ptr, val);
}
-// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_p64(i64* %ptr) #0 {
+// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_p64(i64* %ptr) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
@@ -255,7 +255,7 @@ poly64x1x2_t test_vld2_p64(poly64_t const * ptr) {
return vld2_p64(ptr);
}
-// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_p64(i64* %ptr) #0 {
+// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_p64(i64* %ptr) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
@@ -273,7 +273,7 @@ poly64x2x2_t test_vld2q_p64(poly64_t const * ptr) {
return vld2q_p64(ptr);
}
-// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_p64(i64* %ptr) #0 {
+// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_p64(i64* %ptr) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
@@ -291,7 +291,7 @@ poly64x1x3_t test_vld3_p64(poly64_t const * ptr) {
return vld3_p64(ptr);
}
-// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_p64(i64* %ptr) #0 {
+// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_p64(i64* %ptr) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
@@ -309,7 +309,7 @@ poly64x2x3_t test_vld3q_p64(poly64_t const * ptr) {
return vld3q_p64(ptr);
}
-// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_p64(i64* %ptr) #0 {
+// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_p64(i64* %ptr) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
@@ -327,7 +327,7 @@ poly64x1x4_t test_vld4_p64(poly64_t const * ptr) {
return vld4_p64(ptr);
}
-// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_p64(i64* %ptr) #0 {
+// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_p64(i64* %ptr) #2 {
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
@@ -345,7 +345,7 @@ poly64x2x4_t test_vld4q_p64(poly64_t const * ptr) {
return vld4q_p64(ptr);
}
-// CHECK-LABEL: define void @test_vst2_p64(i64* %ptr, [2 x <1 x i64>] %val.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2_p64(i64* %ptr, [2 x <1 x i64>] %val.coerce) #2 {
// CHECK: [[VAL:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[VAL]], i32 0, i32 0
@@ -370,7 +370,7 @@ void test_vst2_p64(poly64_t * ptr, poly64x1x2_t val) {
return vst2_p64(ptr, val);
}
-// CHECK-LABEL: define void @test_vst2q_p64(i64* %ptr, [2 x <2 x i64>] %val.coerce) #0 {
+// CHECK-LABEL: define void @test_vst2q_p64(i64* %ptr, [2 x <2 x i64>] %val.coerce) #2 {
// CHECK: [[VAL:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[VAL]], i32 0, i32 0
@@ -395,7 +395,7 @@ void test_vst2q_p64(poly64_t * ptr, poly64x2x2_t val) {
return vst2q_p64(ptr, val);
}
-// CHECK-LABEL: define void @test_vst3_p64(i64* %ptr, [3 x <1 x i64>] %val.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3_p64(i64* %ptr, [3 x <1 x i64>] %val.coerce) #2 {
// CHECK: [[VAL:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[VAL]], i32 0, i32 0
@@ -425,7 +425,7 @@ void test_vst3_p64(poly64_t * ptr, poly64x1x3_t val) {
return vst3_p64(ptr, val);
}
-// CHECK-LABEL: define void @test_vst3q_p64(i64* %ptr, [3 x <2 x i64>] %val.coerce) #0 {
+// CHECK-LABEL: define void @test_vst3q_p64(i64* %ptr, [3 x <2 x i64>] %val.coerce) #2 {
// CHECK: [[VAL:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[VAL]], i32 0, i32 0
@@ -455,7 +455,7 @@ void test_vst3q_p64(poly64_t * ptr, poly64x2x3_t val) {
return vst3q_p64(ptr, val);
}
-// CHECK-LABEL: define void @test_vst4_p64(i64* %ptr, [4 x <1 x i64>] %val.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4_p64(i64* %ptr, [4 x <1 x i64>] %val.coerce) #2 {
// CHECK: [[VAL:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[VAL]], i32 0, i32 0
@@ -490,7 +490,7 @@ void test_vst4_p64(poly64_t * ptr, poly64x1x4_t val) {
return vst4_p64(ptr, val);
}
-// CHECK-LABEL: define void @test_vst4q_p64(i64* %ptr, [4 x <2 x i64>] %val.coerce) #0 {
+// CHECK-LABEL: define void @test_vst4q_p64(i64* %ptr, [4 x <2 x i64>] %val.coerce) #2 {
// CHECK: [[VAL:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[VAL]], i32 0, i32 0
@@ -537,7 +537,7 @@ poly64x1_t test_vext_p64(poly64x1_t a, poly64x1_t b) {
}
-// CHECK-LABEL: define <2 x i64> @test_vextq_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vextq_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -548,42 +548,42 @@ poly64x2_t test_vextq_p64(poly64x2_t a, poly64x2_t b) {
return vextq_p64(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vzip1q_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vzip1q_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
poly64x2_t test_vzip1q_p64(poly64x2_t a, poly64x2_t b) {
return vzip1q_p64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vzip2q_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vzip2q_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
poly64x2_t test_vzip2q_p64(poly64x2_t a, poly64x2_t b) {
return vzip2q_u64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vuzp1q_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vuzp1q_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
poly64x2_t test_vuzp1q_p64(poly64x2_t a, poly64x2_t b) {
return vuzp1q_p64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vuzp2q_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vuzp2q_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
poly64x2_t test_vuzp2q_p64(poly64x2_t a, poly64x2_t b) {
return vuzp2q_u64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vtrn1q_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vtrn1q_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
poly64x2_t test_vtrn1q_p64(poly64x2_t a, poly64x2_t b) {
return vtrn1q_p64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vtrn2q_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vtrn2q_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
poly64x2_t test_vtrn2q_p64(poly64x2_t a, poly64x2_t b) {
@@ -601,7 +601,7 @@ poly64x1_t test_vsri_n_p64(poly64x1_t a, poly64x1_t b) {
return vsri_n_p64(a, b, 33);
}
-// CHECK-LABEL: define <2 x i64> @test_vsriq_n_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: define <2 x i64> @test_vsriq_n_p64(<2 x i64> %a, <2 x i64> %b) #1 {
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -612,3 +612,6 @@ poly64x2_t test_vsriq_n_p64(poly64x2_t a, poly64x2_t b) {
return vsriq_n_p64(a, b, 64);
}
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
+// CHECK: attributes #2 ={{.*}}"min-legal-vector-width"="0"
diff --git a/test/CodeGen/aarch64-sign-return-address.c b/test/CodeGen/aarch64-sign-return-address.c
new file mode 100644
index 000000000000..d062685e40c9
--- /dev/null
+++ b/test/CodeGen/aarch64-sign-return-address.c
@@ -0,0 +1,27 @@
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=none %s | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.2-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=non-leaf %s | FileCheck %s --check-prefix=CHECK --check-prefix=PARTIAL --check-prefix=A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.4-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PARTIAL --check-prefix=B-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=B-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
+
+// REQUIRES: aarch64-registered-target
+
+// CHECK: @foo() #[[ATTR:[0-9]*]]
+//
+// NONE-NOT: "sign-return-address"={{.*}}
+
+// PARTIAL: "sign-return-address"="non-leaf"
+
+// ALL: "sign-return-address"="all"
+
+// BTE: "branch-target-enforcement"
+
+// A-KEY: "sign-return-address-key"="a_key"
+
+// B-KEY: "sign-return-address-key"="b_key"
+
+void foo() {}
diff --git a/test/CodeGen/aarch64-vpcs.c b/test/CodeGen/aarch64-vpcs.c
new file mode 100644
index 000000000000..0fc2e9651155
--- /dev/null
+++ b/test/CodeGen/aarch64-vpcs.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECKC
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -x c++ -o - %s | FileCheck %s -check-prefix=CHECKCXX
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -verify %s
+
+void __attribute__((aarch64_vector_pcs)) f(int *); // expected-warning {{calling convention 'aarch64_vector_pcs' ignored for this target}}
+
+// CHECKC: define void @g(
+// CHECKCXX: define void @_Z1gPi(
+void g(int *a) {
+
+// CHECKC: call aarch64_vector_pcs void @f(
+// CHECKCXX: call aarch64_vector_pcs void @_Z1fPi
+ f(a);
+}
+
+// CHECKC: declare aarch64_vector_pcs void @f(
+// CHECKCXX: declare aarch64_vector_pcs void @_Z1fPi
+
+void __attribute__((aarch64_vector_pcs)) h(int *a){ // expected-warning {{calling convention 'aarch64_vector_pcs' ignored for this target}}
+// CHECKC: define aarch64_vector_pcs void @h(
+// CHECKCXX: define aarch64_vector_pcs void @_Z1hPi(
+ f(a);
+}
diff --git a/test/CodeGen/adc-builtins.c b/test/CodeGen/adc-builtins.c
index d41fa8f446e6..036c25ceb71c 100644
--- a/test/CodeGen/adc-builtins.c
+++ b/test/CodeGen/adc-builtins.c
@@ -5,7 +5,10 @@
unsigned char test_addcarry_u32(unsigned char __cf, unsigned int __x,
unsigned int __y, unsigned int *__p) {
// CHECK-LABEL: test_addcarry_u32
-// CHECK: call i8 @llvm.x86.addcarry.u32
+// CHECK: [[ADC:%.*]] = call { i8, i32 } @llvm.x86.addcarry.32
+// CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[ADC]], 1
+// CHECK: store i32 [[DATA]], i32* %{{.*}}
+// CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[ADC]], 0
return _addcarry_u32(__cf, __x, __y, __p);
}
@@ -13,14 +16,20 @@ unsigned char test_addcarry_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y,
unsigned long long *__p) {
// CHECK-LABEL: test_addcarry_u64
-// CHECK: call i8 @llvm.x86.addcarry.u64
+// CHECK: [[ADC:%.*]] = call { i8, i64 } @llvm.x86.addcarry.64
+// CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[ADC]], 1
+// CHECK: store i64 [[DATA]], i64* %{{.*}}
+// CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[ADC]], 0
return _addcarry_u64(__cf, __x, __y, __p);
}
unsigned char test_subborrow_u32(unsigned char __cf, unsigned int __x,
unsigned int __y, unsigned int *__p) {
// CHECK-LABEL: test_subborrow_u32
-// CHECK: call i8 @llvm.x86.subborrow.u32
+// CHECK: [[SBB:%.*]] = call { i8, i32 } @llvm.x86.subborrow.32
+// CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[SBB]], 1
+// CHECK: store i32 [[DATA]], i32* %{{.*}}
+// CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[SBB]], 0
return _subborrow_u32(__cf, __x, __y, __p);
}
@@ -28,6 +37,9 @@ unsigned char test_subborrow_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y,
unsigned long long *__p) {
// CHECK-LABEL: test_subborrow_u64
-// CHECK: call i8 @llvm.x86.subborrow.u64
+// CHECK: [[SBB:%.*]] = call { i8, i64 } @llvm.x86.subborrow.64
+// CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[SBB]], 1
+// CHECK: store i64 [[DATA]], i64* %{{.*}}
+// CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[SBB]], 0
return _subborrow_u64(__cf, __x, __y, __p);
}
diff --git a/test/CodeGen/address-sanitizer-and-array-cookie.cpp b/test/CodeGen/address-sanitizer-and-array-cookie.cpp
index e2267a10c2be..821f1b032b61 100644
--- a/test/CodeGen/address-sanitizer-and-array-cookie.cpp
+++ b/test/CodeGen/address-sanitizer-and-array-cookie.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - %s | FileCheck %s -check-prefix=PLAIN
// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - -fsanitize=address %s | FileCheck %s -check-prefix=ASAN
-// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - -fsanitize=address -fsanitize-address-poison-class-member-array-new-cookie %s | FileCheck %s -check-prefix=ASAN-POISON-ALL-NEW-ARRAY
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - -fsanitize=address -fsanitize-address-poison-custom-array-cookie %s | FileCheck %s -check-prefix=ASAN-POISON-ALL-NEW-ARRAY
typedef __typeof__(sizeof(0)) size_t;
namespace std {
diff --git a/test/CodeGen/adx-builtins.c b/test/CodeGen/adx-builtins.c
index ac33367d0ebd..4047bbab0694 100644
--- a/test/CodeGen/adx-builtins.c
+++ b/test/CodeGen/adx-builtins.c
@@ -5,7 +5,10 @@
unsigned char test_addcarryx_u32(unsigned char __cf, unsigned int __x,
unsigned int __y, unsigned int *__p) {
// CHECK-LABEL: test_addcarryx_u32
-// CHECK: call i8 @llvm.x86.addcarryx.u32
+// CHECK: [[ADC:%.*]] = call { i8, i32 } @llvm.x86.addcarry.32
+// CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[ADC]], 1
+// CHECK: store i32 [[DATA]], i32* %{{.*}}
+// CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[ADC]], 0
return _addcarryx_u32(__cf, __x, __y, __p);
}
@@ -13,6 +16,9 @@ unsigned char test_addcarryx_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y,
unsigned long long *__p) {
// CHECK-LABEL: test_addcarryx_u64
-// CHECK: call i8 @llvm.x86.addcarryx.u64
+// CHECK: [[ADC:%.*]] = call { i8, i64 } @llvm.x86.addcarry.64
+// CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[ADC]], 1
+// CHECK: store i64 [[DATA]], i64* %{{.*}}
+// CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[ADC]], 0
return _addcarryx_u64(__cf, __x, __y, __p);
}
diff --git a/test/CodeGen/annotations-field.c b/test/CodeGen/annotations-field.c
index 02bae15a2bc1..27e64de7bbd3 100644
--- a/test/CodeGen/annotations-field.c
+++ b/test/CodeGen/annotations-field.c
@@ -21,7 +21,6 @@ int main(int argc, char **argv) {
// CHECK-NEXT: call i8* @llvm.ptr.annotation.p0i8({{.*}}str{{.*}}str{{.*}}i32 8)
// CHECK-NEXT: bitcast i8* {{.*}} to i32*
gf.v = argc;
-// CHECK: bitcast i32* getelementptr inbounds (%struct.foo, %struct.foo* @gf, i32 0, i32 0) to i8*
-// CHECK-NEXT: call i8* @llvm.ptr.annotation.p0i8({{.*}}str{{.*}}str{{.*}}i32 8)
+// CHECK: call i8* @llvm.ptr.annotation.p0i8(i8* bitcast (%struct.foo* @gf to i8*), {{.*}}str{{.*}}str{{.*}}i32 8)
return 0;
}
diff --git a/test/CodeGen/arc/arguments.c b/test/CodeGen/arc/arguments.c
new file mode 100644
index 000000000000..fdc6037da730
--- /dev/null
+++ b/test/CodeGen/arc/arguments.c
@@ -0,0 +1,135 @@
+// RUN: %clang_cc1 -triple arc-unknown-unknown %s -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// Basic argument tests for ARC.
+
+// CHECK: define void @f0(i32 inreg %i, i32 inreg %j, i64 inreg %k)
+void f0(int i, long j, long long k) {}
+
+typedef struct {
+ int aa;
+ int bb;
+} s1;
+// CHECK: define void @f1(i32 inreg %i.coerce0, i32 inreg %i.coerce1)
+void f1(s1 i) {}
+
+typedef struct {
+ char aa; char bb; char cc; char dd;
+} cs1;
+// CHECK: define void @cf1(i32 inreg %i.coerce)
+void cf1(cs1 i) {}
+
+typedef struct {
+ int cc;
+} s2;
+// CHECK: define void @f2(%struct.s2* noalias sret %agg.result)
+s2 f2() {
+ s2 foo;
+ return foo;
+}
+
+typedef struct {
+ int cc;
+ int dd;
+} s3;
+// CHECK: define void @f3(%struct.s3* noalias sret %agg.result)
+s3 f3() {
+ s3 foo;
+ return foo;
+}
+
+// CHECK: define void @f4(i64 inreg %i)
+void f4(long long i) {}
+
+// CHECK: define void @f5(i8 inreg signext %a, i16 inreg signext %b)
+void f5(signed char a, short b) {}
+
+// CHECK: define void @f6(i8 inreg zeroext %a, i16 inreg zeroext %b)
+void f6(unsigned char a, unsigned short b) {}
+
+enum my_enum {
+ ENUM1,
+ ENUM2,
+ ENUM3,
+};
+// Enums should be treated as the underlying i32.
+// CHECK: define void @f7(i32 inreg %a)
+void f7(enum my_enum a) {}
+
+enum my_big_enum {
+ ENUM4 = 0xFFFFFFFFFFFFFFFF,
+};
+// Big enums should be treated as the underlying i64.
+// CHECK: define void @f8(i64 inreg %a)
+void f8(enum my_big_enum a) {}
+
+union simple_union {
+ int a;
+ char b;
+};
+// Unions should be passed inreg.
+// CHECK: define void @f9(i32 inreg %s.coerce)
+void f9(union simple_union s) {}
+
+typedef struct {
+ int b4 : 4;
+ int b3 : 3;
+ int b8 : 8;
+} bitfield1;
+// Bitfields should be passed inreg.
+// CHECK: define void @f10(i32 inreg %bf1.coerce)
+void f10(bitfield1 bf1) {}
+
+// CHECK: define inreg { float, float } @cplx1(float inreg %r)
+_Complex float cplx1(float r) {
+ return r + 2.0fi;
+}
+
+// CHECK: define inreg { double, double } @cplx2(double inreg %r)
+_Complex double cplx2(double r) {
+ return r + 2.0i;
+}
+
+// CHECK: define inreg { i32, i32 } @cplx3(i32 inreg %r)
+_Complex int cplx3(int r) {
+ return r + 2i;
+}
+
+// CHECK: define inreg { i64, i64 } @cplx4(i64 inreg %r)
+_Complex long long cplx4(long long r) {
+ return r + 2i;
+}
+
+// CHECK: define inreg { i8, i8 } @cplx6(i8 inreg signext %r)
+_Complex signed char cplx6(signed char r) {
+ return r + 2i;
+}
+
+// CHECK: define inreg { i16, i16 } @cplx7(i16 inreg signext %r)
+_Complex short cplx7(short r) {
+ return r + 2i;
+}
+
+typedef struct {
+ int aa; int bb;
+} s8;
+
+typedef struct {
+ int aa; int bb; int cc; int dd;
+} s16;
+
+// Use 16-byte struct 2 times, gets 8 registers.
+void st2(s16 a, s16 b) {}
+// CHECK: define void @st2(i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %a.coerce2, i32 inreg %a.coerce3, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3)
+
+// Use 8-byte struct 3 times, gets 8 registers, 1 byval struct argument.
+void st3(s16 a, s16 b, s16 c) {}
+// CHECK: define void @st3(i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %a.coerce2, i32 inreg %a.coerce3, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce)
+
+// 1 sret + 1 i32 + 2*(i32 coerce) + 4*(i32 coerce) + 1 byval
+s16 st4(int x, s8 a, s16 b, s16 c) { return b; }
+// CHECK: define void @st4(%struct.s16* noalias sret %agg.result, i32 inreg %x, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce)
+
+// 1 sret + 2*(i32 coerce) + 4*(i32 coerce) + 4*(i32 coerce)
+s16 st5(s8 a, s16 b, s16 c) { return b; }
+// CHECK: define void @st5(%struct.s16* noalias sret %agg.result, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce)
diff --git a/test/CodeGen/arc/struct-align.c b/test/CodeGen/arc/struct-align.c
new file mode 100644
index 000000000000..2aa7e7fc47ee
--- /dev/null
+++ b/test/CodeGen/arc/struct-align.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple arc-unknown-unknown %s -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// 64-bit fields need only be 32-bit aligned for arc.
+
+typedef struct {
+ int aa;
+ double bb;
+} s1;
+
+// CHECK: define i32 @f1
+// CHECK: ret i32 12
+int f1() {
+ return sizeof(s1);
+}
+
+typedef struct {
+ int aa;
+ long long bb;
+} s2;
+// CHECK: define i32 @f2
+// CHECK: ret i32 12
+int f2() {
+ return sizeof(s2);
+}
+
diff --git a/test/CodeGen/arm-neon-fma.c b/test/CodeGen/arm-neon-fma.c
index 5f6737aaa771..0d85c6b7567a 100644
--- a/test/CodeGen/arm-neon-fma.c
+++ b/test/CodeGen/arm-neon-fma.c
@@ -8,14 +8,14 @@
#include <arm_neon.h>
// CHECK-LABEL: define <2 x float> @test_fma_order(<2 x float> %accum, <2 x float> %lhs, <2 x float> %rhs) #0 {
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> %lhs, <2 x float> %rhs, <2 x float> %accum) #2
+// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> %lhs, <2 x float> %rhs, <2 x float> %accum) #3
// CHECK: ret <2 x float> [[TMP6]]
float32x2_t test_fma_order(float32x2_t accum, float32x2_t lhs, float32x2_t rhs) {
return vfma_f32(accum, lhs, rhs);
}
-// CHECK-LABEL: define <4 x float> @test_fmaq_order(<4 x float> %accum, <4 x float> %lhs, <4 x float> %rhs) #0 {
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %lhs, <4 x float> %rhs, <4 x float> %accum) #2
+// CHECK-LABEL: define <4 x float> @test_fmaq_order(<4 x float> %accum, <4 x float> %lhs, <4 x float> %rhs) #1 {
+// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %lhs, <4 x float> %rhs, <4 x float> %accum) #3
// CHECK: ret <4 x float> [[TMP6]]
float32x4_t test_fmaq_order(float32x4_t accum, float32x4_t lhs, float32x4_t rhs) {
return vfmaq_f32(accum, lhs, rhs);
@@ -32,7 +32,7 @@ float32x2_t test_vfma_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
return vfma_n_f32(a, b, n);
}
-// CHECK-LABEL: define <4 x float> @test_vfmaq_n_f32(<4 x float> %a, <4 x float> %b, float %n) #0 {
+// CHECK-LABEL: define <4 x float> @test_vfmaq_n_f32(<4 x float> %a, <4 x float> %b, float %n) #1 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %n, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %n, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %n, i32 2
@@ -44,3 +44,6 @@ float32x2_t test_vfma_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
float32x4_t test_vfmaq_n_f32(float32x4_t a, float32x4_t b, float32_t n) {
return vfmaq_n_f32(a, b, n);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/arm-neon-numeric-maxmin.c b/test/CodeGen/arm-neon-numeric-maxmin.c
index d4f5674cd932..e844de7c81c3 100644
--- a/test/CodeGen/arm-neon-numeric-maxmin.c
+++ b/test/CodeGen/arm-neon-numeric-maxmin.c
@@ -3,29 +3,32 @@
#include <arm_neon.h>
// CHECK-LABEL: define <2 x float> @test_vmaxnm_f32(<2 x float> %a, <2 x float> %b) #0 {
-// CHECK: [[VMAXNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmaxnm.v2f32(<2 x float> %a, <2 x float> %b) #2
+// CHECK: [[VMAXNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmaxnm.v2f32(<2 x float> %a, <2 x float> %b) #3
// CHECK: ret <2 x float> [[VMAXNM_V2_I]]
float32x2_t test_vmaxnm_f32(float32x2_t a, float32x2_t b) {
return vmaxnm_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmaxnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
-// CHECK: [[VMAXNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmaxnm.v4f32(<4 x float> %a, <4 x float> %b) #2
+// CHECK-LABEL: define <4 x float> @test_vmaxnmq_f32(<4 x float> %a, <4 x float> %b) #1 {
+// CHECK: [[VMAXNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmaxnm.v4f32(<4 x float> %a, <4 x float> %b) #3
// CHECK: ret <4 x float> [[VMAXNMQ_V2_I]]
float32x4_t test_vmaxnmq_f32(float32x4_t a, float32x4_t b) {
return vmaxnmq_f32(a, b);
}
// CHECK-LABEL: define <2 x float> @test_vminnm_f32(<2 x float> %a, <2 x float> %b) #0 {
-// CHECK: [[VMINNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vminnm.v2f32(<2 x float> %a, <2 x float> %b) #2
+// CHECK: [[VMINNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vminnm.v2f32(<2 x float> %a, <2 x float> %b) #3
// CHECK: ret <2 x float> [[VMINNM_V2_I]]
float32x2_t test_vminnm_f32(float32x2_t a, float32x2_t b) {
return vminnm_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vminnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
-// CHECK: [[VMINNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vminnm.v4f32(<4 x float> %a, <4 x float> %b) #2
+// CHECK-LABEL: define <4 x float> @test_vminnmq_f32(<4 x float> %a, <4 x float> %b) #1 {
+// CHECK: [[VMINNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vminnm.v4f32(<4 x float> %a, <4 x float> %b) #3
// CHECK: ret <4 x float> [[VMINNMQ_V2_I]]
float32x4_t test_vminnmq_f32(float32x4_t a, float32x4_t b) {
return vminnmq_f32(a, b);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/arm-neon-vcvtX.c b/test/CodeGen/arm-neon-vcvtX.c
index 43d48a0a4f18..627c455d21e6 100644
--- a/test/CodeGen/arm-neon-vcvtX.c
+++ b/test/CodeGen/arm-neon-vcvtX.c
@@ -3,113 +3,116 @@
#include <arm_neon.h>
// CHECK-LABEL: define <2 x i32> @test_vcvta_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTA_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtas.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTA_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtas.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTA_S32_V1_I]]
int32x2_t test_vcvta_s32_f32(float32x2_t a) {
return vcvta_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvta_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTA_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtau.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTA_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtau.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTA_U32_V1_I]]
uint32x2_t test_vcvta_u32_f32(float32x2_t a) {
return vcvta_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtaq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTAQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtas.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtaq_s32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTAQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtas.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTAQ_S32_V1_I]]
int32x4_t test_vcvtaq_s32_f32(float32x4_t a) {
return vcvtaq_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtaq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTAQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtau.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtaq_u32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTAQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtau.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTAQ_U32_V1_I]]
uint32x4_t test_vcvtaq_u32_f32(float32x4_t a) {
return vcvtaq_u32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtn_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTN_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtns.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTN_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtns.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTN_S32_V1_I]]
int32x2_t test_vcvtn_s32_f32(float32x2_t a) {
return vcvtn_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtn_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTN_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtnu.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTN_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtnu.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTN_U32_V1_I]]
uint32x2_t test_vcvtn_u32_f32(float32x2_t a) {
return vcvtn_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtnq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTNQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtns.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtnq_s32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTNQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtns.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTNQ_S32_V1_I]]
int32x4_t test_vcvtnq_s32_f32(float32x4_t a) {
return vcvtnq_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtnq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTNQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtnu.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtnq_u32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTNQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtnu.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTNQ_U32_V1_I]]
uint32x4_t test_vcvtnq_u32_f32(float32x4_t a) {
return vcvtnq_u32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtp_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTP_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtps.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTP_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtps.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTP_S32_V1_I]]
int32x2_t test_vcvtp_s32_f32(float32x2_t a) {
return vcvtp_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtp_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTP_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtpu.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTP_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtpu.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTP_U32_V1_I]]
uint32x2_t test_vcvtp_u32_f32(float32x2_t a) {
return vcvtp_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtpq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTPQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtps.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtpq_s32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTPQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtps.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTPQ_S32_V1_I]]
int32x4_t test_vcvtpq_s32_f32(float32x4_t a) {
return vcvtpq_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtpq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTPQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtpu.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtpq_u32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTPQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtpu.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTPQ_U32_V1_I]]
uint32x4_t test_vcvtpq_u32_f32(float32x4_t a) {
return vcvtpq_u32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtm_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTM_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtms.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTM_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtms.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTM_S32_V1_I]]
int32x2_t test_vcvtm_s32_f32(float32x2_t a) {
return vcvtm_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtm_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[VCVTM_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtmu.v2i32.v2f32(<2 x float> %a) #2
+// CHECK: [[VCVTM_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtmu.v2i32.v2f32(<2 x float> %a) #3
// CHECK: ret <2 x i32> [[VCVTM_U32_V1_I]]
uint32x2_t test_vcvtm_u32_f32(float32x2_t a) {
return vcvtm_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtmq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTMQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtms.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtmq_s32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTMQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtms.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTMQ_S32_V1_I]]
int32x4_t test_vcvtmq_s32_f32(float32x4_t a) {
return vcvtmq_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtmq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[VCVTMQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtmu.v4i32.v4f32(<4 x float> %a) #2
+// CHECK-LABEL: define <4 x i32> @test_vcvtmq_u32_f32(<4 x float> %a) #1 {
+// CHECK: [[VCVTMQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtmu.v4i32.v4f32(<4 x float> %a) #3
// CHECK: ret <4 x i32> [[VCVTMQ_U32_V1_I]]
uint32x4_t test_vcvtmq_u32_f32(float32x4_t a) {
return vcvtmq_u32_f32(a);
}
+
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="64"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="128"
diff --git a/test/CodeGen/arm-neon-vld.c b/test/CodeGen/arm-neon-vld.c
index 2bf55bb1c6cb..2c7af92f4796 100644
--- a/test/CodeGen/arm-neon-vld.c
+++ b/test/CodeGen/arm-neon-vld.c
@@ -2,8 +2,8 @@
// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
// RUN: FileCheck -check-prefixes=CHECK,CHECK-A64 %s
// RUN: %clang_cc1 -triple armv8-none-linux-gnueabi -target-feature +neon \
-// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
-// RUN: FileCheck -check-prefixes=CHECK,CHECK-A32 %s
+// RUN: -target-feature +fp16 -S -disable-O0-optnone -emit-llvm -o - %s | \
+// RUN: opt -S -mem2reg | FileCheck -check-prefixes=CHECK,CHECK-A32 %s
#include <arm_neon.h>
diff --git a/test/CodeGen/arm-neon-vst.c b/test/CodeGen/arm-neon-vst.c
index 404c4d9c295c..dc7105a7322c 100644
--- a/test/CodeGen/arm-neon-vst.c
+++ b/test/CodeGen/arm-neon-vst.c
@@ -2,8 +2,8 @@
// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
// RUN: FileCheck -check-prefixes=CHECK,CHECK-A64 %s
// RUN: %clang_cc1 -triple armv8-none-linux-gnueabi -target-feature +neon \
-// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \
-// RUN: FileCheck -check-prefixes=CHECK,CHECK-A32 %s
+// RUN: -target-feature +fp16 -S -disable-O0-optnone -emit-llvm -o - %s | \
+// RUN: opt -S -mem2reg | FileCheck -check-prefixes=CHECK,CHECK-A32 %s
#include <arm_neon.h>
diff --git a/test/CodeGen/arm-target-features.c b/test/CodeGen/arm-target-features.c
index 6bc56be4f4ca..ca574cc05d52 100644
--- a/test/CodeGen/arm-target-features.c
+++ b/test/CodeGen/arm-target-features.c
@@ -28,9 +28,11 @@
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
-// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// CHECK-BASIC-V8: "target-features"="+armv8-a,+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,+thumb-mode"
+// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V82
+// CHECK-BASIC-V82: "target-features"="+armv8.2-a,+crc,+crypto,+dotprod,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,+ras,+thumb-mode"
+
// RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8-ARM
// CHECK-BASIC-V8-ARM: "target-features"="+armv8-a,+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,-thumb-mode"
diff --git a/test/CodeGen/arm-vfp16-arguments.c b/test/CodeGen/arm-vfp16-arguments.c
new file mode 100644
index 000000000000..32f1bb7b2a77
--- /dev/null
+++ b/test/CodeGen/arm-vfp16-arguments.c
@@ -0,0 +1,76 @@
+// RUN: %clang_cc1 -triple armv7a--none-eabi -target-abi aapcs \
+// RUN: -mfloat-abi soft -target-feature +neon -emit-llvm -o - -O1 %s \
+// RUN: | FileCheck %s --check-prefix=CHECK-SOFT
+// RUN: %clang_cc1 -triple armv7a--none-eabi -target-abi aapcs \
+// RUN: -mfloat-abi hard -target-feature +neon -emit-llvm -o - -O1 %s \
+// RUN: | FileCheck %s --check-prefix=CHECK-HARD
+// RUN: %clang_cc1 -triple armv7a--none-eabi -target-abi aapcs \
+// RUN: -mfloat-abi hard -target-feature +neon -target-feature +fullfp16 \
+// RUN: -emit-llvm -o - -O1 %s \
+// RUN: | FileCheck %s --check-prefix=CHECK-FULL
+
+typedef __attribute__((neon_vector_type(4))) __fp16 float16x4_t;
+typedef __attribute__((neon_vector_type(8))) __fp16 float16x8_t;
+
+typedef struct { float16x4_t x[2]; } hfa_t;
+// CHECK-FULL: %struct.hfa_t = type { [2 x <4 x half>] }
+
+float16x4_t g4;
+float16x8_t g8;
+
+void st4(float16x4_t a) { g4 = a; }
+// CHECK-SOFT: define void @st4(<2 x i32> %a.coerce)
+// CHECK-SOFT: store <2 x i32> %a.coerce, <2 x i32>* bitcast (<4 x half>* @g4 to <2 x i32>*)
+//
+// CHECK-HARD: define arm_aapcs_vfpcc void @st4(<2 x i32> %a.coerce)
+// CHECK-HARD: store <2 x i32> %a.coerce, <2 x i32>* bitcast (<4 x half>* @g4 to <2 x i32>*)
+//
+// CHECK-FULL: define arm_aapcs_vfpcc void @st4(<4 x half> %a)
+// CHECK-FULL: store <4 x half> %a, <4 x half>* @g4
+
+float16x4_t ld4(void) { return g4; }
+// CHECK-SOFT: define <2 x i32> @ld4()
+// CHECK-SOFT: %0 = load <2 x i32>, <2 x i32>* bitcast (<4 x half>* @g4 to <2 x i32>*)
+// CHECK-SOFT: ret <2 x i32> %0
+//
+// CHECK-HARD: define arm_aapcs_vfpcc <2 x i32> @ld4()
+// CHECK-HARD: %0 = load <2 x i32>, <2 x i32>* bitcast (<4 x half>* @g4 to <2 x i32>*)
+// CHECK-HARD: ret <2 x i32> %0
+//
+// CHECK-FULL: define arm_aapcs_vfpcc <4 x half> @ld4()
+// CHECK-FULL: %0 = load <4 x half>, <4 x half>* @g4
+// CHECK-FULL: ret <4 x half> %0
+
+void st8(float16x8_t a) { g8 = a; }
+// CHECK-SOFT: define void @st8(<4 x i32> %a.coerce)
+// CHECK-SOFT: store <4 x i32> %a.coerce, <4 x i32>* bitcast (<8 x half>* @g8 to <4 x i32>*)
+//
+// CHECK-HARD: define arm_aapcs_vfpcc void @st8(<4 x i32> %a.coerce)
+// CHECK-HARD: store <4 x i32> %a.coerce, <4 x i32>* bitcast (<8 x half>* @g8 to <4 x i32>*)
+//
+// CHECK-FULL: define arm_aapcs_vfpcc void @st8(<8 x half> %a)
+// CHECK-FULL: store <8 x half> %a, <8 x half>* @g8
+
+float16x8_t ld8(void) { return g8; }
+// CHECK-SOFT: define <4 x i32> @ld8()
+// CHECK-SOFT: %0 = load <4 x i32>, <4 x i32>* bitcast (<8 x half>* @g8 to <4 x i32>*)
+// CHECK-SOFT: ret <4 x i32> %0
+//
+// CHECK-HARD: define arm_aapcs_vfpcc <4 x i32> @ld8()
+// CHECK-HARD: %0 = load <4 x i32>, <4 x i32>* bitcast (<8 x half>* @g8 to <4 x i32>*)
+// CHECK-HARD: ret <4 x i32> %0
+//
+// CHECK-FULL: define arm_aapcs_vfpcc <8 x half> @ld8()
+// CHECK-FULL: %0 = load <8 x half>, <8 x half>* @g8
+// CHECK-FULL: ret <8 x half> %0
+
+void test_hfa(hfa_t a) {}
+// CHECK-SOFT: define void @test_hfa([2 x i64] %a.coerce)
+// CHECK-HARD: define arm_aapcs_vfpcc void @test_hfa([2 x <2 x i32>] %a.coerce)
+// CHECK-FULL: define arm_aapcs_vfpcc void @test_hfa(%struct.hfa_t %a.coerce)
+
+hfa_t ghfa;
+hfa_t test_ret_hfa(void) { return ghfa; }
+// CHECK-SOFT: define void @test_ret_hfa(%struct.hfa_t* noalias nocapture sret %agg.result)
+// CHECK-HARD: define arm_aapcs_vfpcc [2 x <2 x i32>] @test_ret_hfa()
+// CHECK-FULL: define arm_aapcs_vfpcc %struct.hfa_t @test_ret_hfa()
diff --git a/test/CodeGen/arm64-microsoft-intrinsics.c b/test/CodeGen/arm64-microsoft-intrinsics.c
index 2dbf1f9ea0f4..eeb09e89727d 100644
--- a/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -4,6 +4,16 @@
// RUN: not %clang_cc1 -triple arm64-linux -Werror -S -o /dev/null %s 2>&1 \
// RUN: | FileCheck %s -check-prefix CHECK-LINUX
+long test_InterlockedAdd(long volatile *Addend, long Value) {
+ return _InterlockedAdd(Addend, Value);
+}
+
+// CHECK-LABEL: define {{.*}} i32 @test_InterlockedAdd(i32* %Addend, i32 %Value) {{.*}} {
+// CHECK-MSVC: %[[OLDVAL:[0-9]+]] = atomicrmw add i32* %1, i32 %2 seq_cst
+// CHECK-MSVC: %[[NEWVAL:[0-9]+]] = add i32 %[[OLDVAL:[0-9]+]], %2
+// CHECK-MSVC: ret i32 %[[NEWVAL:[0-9]+]]
+// CHECK-LINUX: error: implicit declaration of function '_InterlockedAdd'
+
void check__dmb(void) {
__dmb(0);
}
@@ -59,3 +69,22 @@ void check__sevl(void) {
// CHECK-MSVC: @llvm.aarch64.hint(i32 5)
// CHECK-LINUX: error: implicit declaration of function '__sevl'
+
+void check_ReadWriteBarrier() {
+ _ReadWriteBarrier();
+}
+
+// CHECK-MSVC: fence syncscope("singlethread")
+// CHECK-LINUX: error: implicit declaration of function '_ReadWriteBarrier'
+
+unsigned __int64 check__getReg() {
+ unsigned volatile __int64 reg;
+ reg = __getReg(18);
+ reg = __getReg(31);
+ return reg;
+}
+
+// CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
+// CHECK-MSVC: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+// CHECK-MSVC: ![[MD2]] = !{!"x18"}
+// CHECK-MSVC: ![[MD3]] = !{!"sp"}
diff --git a/test/CodeGen/arm64-microsoft-status-reg.cpp b/test/CodeGen/arm64-microsoft-status-reg.cpp
new file mode 100644
index 000000000000..eb59bae50f0a
--- /dev/null
+++ b/test/CodeGen/arm64-microsoft-status-reg.cpp
@@ -0,0 +1,119 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm -S \
+// RUN: -o - %s | FileCheck %s -check-prefix CHECK-ASM
+
+// RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm \
+// RUN: -o - %s | FileCheck %s -check-prefix CHECK-IR
+
+// From winnt.h
+#define ARM64_SYSREG(op0, op1, crn, crm, op2) \
+ ( ((op0 & 1) << 14) | \
+ ((op1 & 7) << 11) | \
+ ((crn & 15) << 7) | \
+ ((crm & 15) << 3) | \
+ ((op2 & 7) << 0) )
+
+#define ARM64_CNTVCT ARM64_SYSREG(3,3,14, 0,2) // Generic Timer counter register
+#define ARM64_PMCCNTR_EL0 ARM64_SYSREG(3,3, 9,13,0) // Cycle Count Register [CP15_PMCCNTR]
+#define ARM64_PMSELR_EL0 ARM64_SYSREG(3,3, 9,12,5) // Event Counter Selection Register [CP15_PMSELR]
+#define ARM64_PMXEVCNTR_EL0 ARM64_SYSREG(3,3, 9,13,2) // Event Count Register [CP15_PMXEVCNTR]
+#define ARM64_PMXEVCNTRn_EL0(n) ARM64_SYSREG(3,3,14, 8+((n)/8), (n)%8) // Direct Event Count Register [n/a]
+#define ARM64_TPIDR_EL0 ARM64_SYSREG(3,3,13, 0,2) // Thread ID Register, User Read/Write [CP15_TPIDRURW]
+#define ARM64_TPIDRRO_EL0 ARM64_SYSREG(3,3,13, 0,3) // Thread ID Register, User Read Only [CP15_TPIDRURO]
+#define ARM64_TPIDR_EL1 ARM64_SYSREG(3,0,13, 0,4) // Thread ID Register, Privileged Only [CP15_TPIDRPRW]
+
+void check_ReadWriteStatusReg(int v) {
+ int ret;
+ ret = _ReadStatusReg(ARM64_CNTVCT);
+// CHECK-ASM: mrs x8, CNTVCT_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
+
+ ret = _ReadStatusReg(ARM64_PMCCNTR_EL0);
+// CHECK-ASM: mrs x8, PMCCNTR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
+
+ ret = _ReadStatusReg(ARM64_PMSELR_EL0);
+// CHECK-ASM: mrs x8, PMSELR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD4:.*]])
+
+ ret = _ReadStatusReg(ARM64_PMXEVCNTR_EL0);
+// CHECK-ASM: mrs x8, PMXEVCNTR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD5:.*]])
+
+ ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(0));
+// CHECK-ASM: mrs x8, PMEVCNTR0_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD6:.*]])
+
+ ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(1));
+// CHECK-ASM: mrs x8, PMEVCNTR1_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD7:.*]])
+
+ ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(30));
+// CHECK-ASM: mrs x8, PMEVCNTR30_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD8:.*]])
+
+ ret = _ReadStatusReg(ARM64_TPIDR_EL0);
+// CHECK-ASM: mrs x8, TPIDR_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD9:.*]])
+
+ ret = _ReadStatusReg(ARM64_TPIDRRO_EL0);
+// CHECK-ASM: mrs x8, TPIDRRO_EL0
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD10:.*]])
+
+ ret = _ReadStatusReg(ARM64_TPIDR_EL1);
+// CHECK-ASM: mrs x8, TPIDR_EL1
+// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD11:.*]])
+
+
+ _WriteStatusReg(ARM64_CNTVCT, v);
+// CHECK-ASM: msr S3_3_C14_C0_2, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_PMCCNTR_EL0, v);
+// CHECK-ASM: msr PMCCNTR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_PMSELR_EL0, v);
+// CHECK-ASM: msr PMSELR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_PMXEVCNTR_EL0, v);
+// CHECK-ASM: msr PMXEVCNTR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(0), v);
+// CHECK-ASM: msr PMEVCNTR0_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(1), v);
+// CHECK-ASM: msr PMEVCNTR1_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD7:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(30), v);
+// CHECK-ASM: msr PMEVCNTR30_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD8:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_TPIDR_EL0, v);
+// CHECK-ASM: msr TPIDR_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD9:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_TPIDRRO_EL0, v);
+// CHECK-ASM: msr TPIDRRO_EL0, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD10:.*]], i64 {{%.*}})
+
+ _WriteStatusReg(ARM64_TPIDR_EL1, v);
+// CHECK-ASM: msr TPIDR_EL1, x8
+// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD11:.*]], i64 {{%.*}})
+}
+
+// CHECK-IR: ![[MD2]] = !{!"3:3:14:0:2"}
+// CHECK-IR: ![[MD3]] = !{!"3:3:9:13:0"}
+// CHECK-IR: ![[MD4]] = !{!"3:3:9:12:5"}
+// CHECK-IR: ![[MD5]] = !{!"3:3:9:13:2"}
+// CHECK-IR: ![[MD6]] = !{!"3:3:14:8:0"}
+// CHECK-IR: ![[MD7]] = !{!"3:3:14:8:1"}
+// CHECK-IR: ![[MD8]] = !{!"3:3:14:11:6"}
+// CHECK-IR: ![[MD9]] = !{!"3:3:13:0:2"}
+// CHECK-IR: ![[MD10]] = !{!"3:3:13:0:3"}
+// CHECK-IR: ![[MD11]] = !{!"3:0:13:0:4"}
diff --git a/test/CodeGen/arm64_vdupq_n_f64.c b/test/CodeGen/arm64_vdupq_n_f64.c
index e9e814e92a05..24c57c4f0de3 100644
--- a/test/CodeGen/arm64_vdupq_n_f64.c
+++ b/test/CodeGen/arm64_vdupq_n_f64.c
@@ -44,7 +44,7 @@ float64x2_t test_vmovq_n_f64(float64_t w) {
return vmovq_n_f64(w);
}
-// CHECK-LABEL: define <4 x half> @test_vmov_n_f16(half* %a1) #0 {
+// CHECK-LABEL: define <4 x half> @test_vmov_n_f16(half* %a1) #1 {
// CHECK: [[TMP0:%.*]] = load half, half* %a1, align 2
// CHECK: [[VECINIT:%.*]] = insertelement <4 x half> undef, half [[TMP0]], i32 0
// CHECK: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[TMP0]], i32 1
@@ -76,3 +76,5 @@ float16x8_t test_vmovq_n_f16(float16_t *a1) {
return vmovq_n_f16(*a1);
}
+// CHECK: attributes #0 ={{.*}}"min-legal-vector-width"="128"
+// CHECK: attributes #1 ={{.*}}"min-legal-vector-width"="64"
diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c
index f6305062e8fd..c0e0dee0d32e 100644
--- a/test/CodeGen/arm_neon_intrinsics.c
+++ b/test/CodeGen/arm_neon_intrinsics.c
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple thumbv7s-apple-darwin -target-abi apcs-gnu\
-// RUN: -target-cpu swift -fallow-half-arguments-and-returns -ffreestanding \
+// RUN: -target-cpu swift -fallow-half-arguments-and-returns \
+// RUN: -target-feature +fullfp16 -ffreestanding \
// RUN: -disable-O0-optnone -emit-llvm -o - %s \
// RUN: | opt -S -mem2reg | FileCheck %s
@@ -3896,9 +3897,8 @@ int64x2_t test_vld1q_s64(int64_t const * a) {
// CHECK-LABEL: @test_vld1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD1:%.*]] = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* [[TMP0]], i32 2)
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[VLD1]] to <8 x half>
-// CHECK: ret <8 x half> [[TMP1]]
+// CHECK: [[VLD1:%.*]] = call <8 x half> @llvm.arm.neon.vld1.v8f16.p0i8(i8* [[TMP0]], i32 2)
+// CHECK: ret <8 x half> [[VLD1]]
float16x8_t test_vld1q_f16(float16_t const * a) {
return vld1q_f16(a);
}
@@ -3990,9 +3990,8 @@ int64x1_t test_vld1_s64(int64_t const * a) {
// CHECK-LABEL: @test_vld1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD1:%.*]] = call <4 x i16> @llvm.arm.neon.vld1.v4i16.p0i8(i8* [[TMP0]], i32 2)
-// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VLD1]] to <4 x half>
-// CHECK: ret <4 x half> [[TMP1]]
+// CHECK: [[VLD1:%.*]] = call <4 x half> @llvm.arm.neon.vld1.v4f16.p0i8(i8* [[TMP0]], i32 2)
+// CHECK: ret <4 x half> [[VLD1]]
float16x4_t test_vld1_f16(float16_t const * a) {
return vld1_f16(a);
}
@@ -4106,12 +4105,11 @@ int64x2_t test_vld1q_dup_s64(int64_t const * a) {
// CHECK-LABEL: @test_vld1q_dup_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
-// CHECK: [[TMP3:%.*]] = insertelement <8 x i16> undef, i16 [[TMP2]], i32 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[LANE]] to <8 x half>
-// CHECK: ret <8 x half> [[TMP4]]
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP2:%.*]] = load half, half* [[TMP1]], align 2
+// CHECK: [[TMP3:%.*]] = insertelement <8 x half> undef, half [[TMP2]], i32 0
+// CHECK: [[LANE:%.*]] = shufflevector <8 x half> [[TMP3]], <8 x half> [[TMP3]], <8 x i32> zeroinitializer
+// CHECK: ret <8 x half> [[LANE]]
float16x8_t test_vld1q_dup_f16(float16_t const * a) {
return vld1q_dup_f16(a);
}
@@ -4233,12 +4231,11 @@ int64x1_t test_vld1_dup_s64(int64_t const * a) {
// CHECK-LABEL: @test_vld1_dup_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
-// CHECK: [[TMP3:%.*]] = insertelement <4 x i16> undef, i16 [[TMP2]], i32 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP3]], <4 x i16> [[TMP3]], <4 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[LANE]] to <4 x half>
-// CHECK: ret <4 x half> [[TMP4]]
+// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP2:%.*]] = load half, half* [[TMP1]], align 2
+// CHECK: [[TMP3:%.*]] = insertelement <4 x half> undef, half [[TMP2]], i32 0
+// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP3]], <4 x half> [[TMP3]], <4 x i32> zeroinitializer
+// CHECK: ret <4 x half> [[LANE]]
float16x4_t test_vld1_dup_f16(float16_t const * a) {
return vld1_dup_f16(a);
}
@@ -4365,12 +4362,11 @@ int64x2_t test_vld1q_lane_s64(int64_t const * a, int64x2_t b) {
// CHECK-LABEL: @test_vld1q_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP4:%.*]] = load i16, i16* [[TMP3]], align 2
-// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i16> [[TMP2]], i16 [[TMP4]], i32 7
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[VLD1_LANE]] to <8 x half>
-// CHECK: ret <8 x half> [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP4:%.*]] = load half, half* [[TMP3]], align 2
+// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x half> [[TMP2]], half [[TMP4]], i32 7
+// CHECK: ret <8 x half> [[VLD1_LANE]]
float16x8_t test_vld1q_lane_f16(float16_t const * a, float16x8_t b) {
return vld1q_lane_f16(a, b, 7);
}
@@ -4498,12 +4494,11 @@ int64x1_t test_vld1_lane_s64(int64_t const * a, int64x1_t b) {
// CHECK-LABEL: @test_vld1_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: [[TMP4:%.*]] = load i16, i16* [[TMP3]], align 2
-// CHECK: [[VLD1_LANE:%.*]] = insertelement <4 x i16> [[TMP2]], i16 [[TMP4]], i32 3
-// CHECK: [[TMP5:%.*]] = bitcast <4 x i16> [[VLD1_LANE]] to <4 x half>
-// CHECK: ret <4 x half> [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: [[TMP4:%.*]] = load half, half* [[TMP3]], align 2
+// CHECK: [[VLD1_LANE:%.*]] = insertelement <4 x half> [[TMP2]], half [[TMP4]], i32 3
+// CHECK: ret <4 x half> [[VLD1_LANE]]
float16x4_t test_vld1_lane_f16(float16_t const * a, float16x4_t b) {
return vld1_lane_f16(a, b, 3);
}
@@ -4596,7 +4591,7 @@ int32x4x2_t test_vld2q_s32(int32_t const * a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16>
+// CHECK: [[VLD2Q_V:%.*]] = call { <8 x half>, <8 x half>
float16x8x2_t test_vld2q_f16(float16_t const * a) {
return vld2q_f16(a);
}
@@ -4701,7 +4696,7 @@ int64x1x2_t test_vld2_s64(int64_t const * a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16>
+// CHECK: [[VLD2_V:%.*]] = call { <4 x half>, <4 x half>
float16x4x2_t test_vld2_f16(float16_t const * a) {
return vld2_f16(a);
}
@@ -4860,9 +4855,9 @@ int32x4x2_t test_vld2q_lane_s32(int32_t const * a, int32x4x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i32 0, i32 1
// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>
+// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x half>, <8 x half>
float16x8x2_t test_vld2q_lane_f16(float16_t const * a, float16x8x2_t b) {
return vld2q_lane_f16(a, b, 7);
}
@@ -5093,9 +5088,9 @@ int32x2x2_t test_vld2_lane_s32(int32_t const * a, int32x2x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i32 0, i32 1
// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>
+// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x half>, <4 x half>
float16x4x2_t test_vld2_lane_f16(float16_t const * a, float16x4x2_t b) {
return vld2_lane_f16(a, b, 3);
}
@@ -5232,7 +5227,7 @@ int32x4x3_t test_vld3q_s32(int32_t const * a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
+// CHECK: [[VLD3Q_V:%.*]] = call { <8 x half>, <8 x half>, <8 x half>
float16x8x3_t test_vld3q_f16(float16_t const * a) {
return vld3q_f16(a);
}
@@ -5337,7 +5332,7 @@ int64x1x3_t test_vld3_s64(int64_t const * a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
+// CHECK: [[VLD3_V:%.*]] = call { <4 x half>, <4 x half>, <4 x half>
float16x4x3_t test_vld3_f16(float16_t const * a) {
return vld3_f16(a);
}
@@ -5520,10 +5515,10 @@ int32x4x3_t test_vld3q_lane_s32(int32_t const * a, int32x4x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i32 0, i32 2
// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x half>
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x half>, <8 x half>, <8 x half>
float16x8x3_t test_vld3q_lane_f16(float16_t const * a, float16x8x3_t b) {
return vld3q_lane_f16(a, b, 7);
}
@@ -5794,10 +5789,10 @@ int32x2x3_t test_vld3_lane_s32(int32_t const * a, int32x2x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i32 0, i32 2
// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x half>
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x half>, <4 x half>, <4 x half>
float16x4x3_t test_vld3_lane_f16(float16_t const * a, float16x4x3_t b) {
return vld3_lane_f16(a, b, 3);
}
@@ -5947,7 +5942,7 @@ int32x4x4_t test_vld4q_s32(int32_t const * a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
+// CHECK: [[VLD4Q_V:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half>
float16x8x4_t test_vld4q_f16(float16_t const * a) {
return vld4q_f16(a);
}
@@ -6052,7 +6047,7 @@ int64x1x4_t test_vld4_s64(int64_t const * a) {
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8*
-// CHECK: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
+// CHECK: [[VLD4_V:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half>
float16x4x4_t test_vld4_f16(float16_t const * a) {
return vld4_f16(a);
}
@@ -6259,11 +6254,11 @@ int32x4x4_t test_vld4q_lane_s32(int32_t const * a, int32x4x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i32 0, i32 3
// CHECK: [[TMP11:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
// CHECK: [[TMP12:%.*]] = bitcast <8 x half> [[TMP11]] to <16 x i8>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <8 x i16>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x half>
+// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <8 x half>
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half>
float16x8x4_t test_vld4q_lane_f16(float16_t const * a, float16x8x4_t b) {
return vld4q_lane_f16(a, b, 7);
}
@@ -6574,11 +6569,11 @@ int32x2x4_t test_vld4_lane_s32(int32_t const * a, int32x2x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i32 0, i32 3
// CHECK: [[TMP11:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
// CHECK: [[TMP12:%.*]] = bitcast <4 x half> [[TMP11]] to <8 x i8>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <4 x i16>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x half>
+// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <4 x half>
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half>
float16x4x4_t test_vld4_lane_f16(float16_t const * a, float16x4x4_t b) {
return vld4_lane_f16(a, b, 3);
}
@@ -15469,8 +15464,8 @@ void test_vst1q_s64(int64_t * a, int64x2_t b) {
// CHECK-LABEL: @test_vst1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* [[TMP0]], <8 x i16> [[TMP2]], i32 2)
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: call void @llvm.arm.neon.vst1.p0i8.v8f16(i8* [[TMP0]], <8 x half> [[TMP2]], i32 2)
// CHECK: ret void
void test_vst1q_f16(float16_t * a, float16x8_t b) {
vst1q_f16(a, b);
@@ -15580,8 +15575,8 @@ void test_vst1_s64(int64_t * a, int64x1_t b) {
// CHECK-LABEL: @test_vst1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: call void @llvm.arm.neon.vst1.p0i8.v4i16(i8* [[TMP0]], <4 x i16> [[TMP2]], i32 2)
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: call void @llvm.arm.neon.vst1.p0i8.v4f16(i8* [[TMP0]], <4 x half> [[TMP2]], i32 2)
// CHECK: ret void
void test_vst1_f16(float16_t * a, float16x4_t b) {
vst1_f16(a, b);
@@ -15703,10 +15698,10 @@ void test_vst1q_lane_s64(int64_t * a, int64x2_t b) {
// CHECK-LABEL: @test_vst1q_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = extractelement <8 x i16> [[TMP2]], i32 7
-// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: store i16 [[TMP3]], i16* [[TMP4]], align 2
+// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
+// CHECK: [[TMP3:%.*]] = extractelement <8 x half> [[TMP2]], i32 7
+// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: store half [[TMP3]], half* [[TMP4]], align 2
// CHECK: ret void
void test_vst1q_lane_f16(float16_t * a, float16x8_t b) {
vst1q_lane_f16(a, b, 7);
@@ -15835,10 +15830,10 @@ void test_vst1_lane_s64(int64_t * a, int64x1_t b) {
// CHECK-LABEL: @test_vst1_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = extractelement <4 x i16> [[TMP2]], i32 3
-// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16*
-// CHECK: store i16 [[TMP3]], i16* [[TMP4]], align 2
+// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
+// CHECK: [[TMP3:%.*]] = extractelement <4 x half> [[TMP2]], i32 3
+// CHECK: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to half*
+// CHECK: store half [[TMP3]], half* [[TMP4]], align 2
// CHECK: ret void
void test_vst1_lane_f16(float16_t * a, float16x4_t b) {
vst1_lane_f16(a, b, 3);
@@ -16040,9 +16035,9 @@ void test_vst2q_s32(int32_t * a, int32x4x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i32 0, i32 1
// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
// CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: call void @llvm.arm.neon.vst2.p0i8.v8i16(i8* [[TMP3]], <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], i32 2)
+// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: call void @llvm.arm.neon.vst2.p0i8.v8f16(i8* [[TMP3]], <8 x half> [[TMP8]], <8 x half> [[TMP9]], i32 2)
// CHECK: ret void
void test_vst2q_f16(float16_t * a, float16x8x2_t b) {
vst2q_f16(a, b);
@@ -16337,9 +16332,9 @@ void test_vst2_s64(int64_t * a, int64x1x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i32 0, i32 1
// CHECK: [[TMP6:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
// CHECK: [[TMP7:%.*]] = bitcast <4 x half> [[TMP6]] to <8 x i8>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: call void @llvm.arm.neon.vst2.p0i8.v4i16(i8* [[TMP3]], <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], i32 2)
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: call void @llvm.arm.neon.vst2.p0i8.v4f16(i8* [[TMP3]], <4 x half> [[TMP8]], <4 x half> [[TMP9]], i32 2)
// CHECK: ret void
void test_vst2_f16(float16_t * a, float16x4x2_t b) {
vst2_f16(a, b);
@@ -16540,9 +16535,9 @@ void test_vst2q_lane_s32(int32_t * a, int32x4x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i32 0, i32 1
// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16
// CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8>
-// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: call void @llvm.arm.neon.vst2lane.p0i8.v8i16(i8* [[TMP3]], <8 x i16> [[TMP8]], <8 x i16> [[TMP9]], i32 7, i32 2)
+// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: call void @llvm.arm.neon.vst2lane.p0i8.v8f16(i8* [[TMP3]], <8 x half> [[TMP8]], <8 x half> [[TMP9]], i32 7, i32 2)
// CHECK: ret void
void test_vst2q_lane_f16(float16_t * a, float16x8x2_t b) {
vst2q_lane_f16(a, b, 7);
@@ -16764,9 +16759,9 @@ void test_vst2_lane_s32(int32_t * a, int32x2x2_t b) {
// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i32 0, i32 1
// CHECK: [[TMP6:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8
// CHECK: [[TMP7:%.*]] = bitcast <4 x half> [[TMP6]] to <8 x i8>
-// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: call void @llvm.arm.neon.vst2lane.p0i8.v4i16(i8* [[TMP3]], <4 x i16> [[TMP8]], <4 x i16> [[TMP9]], i32 3, i32 2)
+// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: call void @llvm.arm.neon.vst2lane.p0i8.v4f16(i8* [[TMP3]], <4 x half> [[TMP8]], <4 x half> [[TMP9]], i32 3, i32 2)
// CHECK: ret void
void test_vst2_lane_f16(float16_t * a, float16x4x2_t b) {
vst2_lane_f16(a, b, 3);
@@ -17039,10 +17034,10 @@ void test_vst3q_s32(int32_t * a, int32x4x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i32 0, i32 2
// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
// CHECK: [[TMP9:%.*]] = bitcast <8 x half> [[TMP8]] to <16 x i8>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x i16>
-// CHECK: call void @llvm.arm.neon.vst3.p0i8.v8i16(i8* [[TMP3]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], i32 2)
+// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x half>
+// CHECK: call void @llvm.arm.neon.vst3.p0i8.v8f16(i8* [[TMP3]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], <8 x half> [[TMP12]], i32 2)
// CHECK: ret void
void test_vst3q_f16(float16_t * a, float16x8x3_t b) {
vst3q_f16(a, b);
@@ -17390,10 +17385,10 @@ void test_vst3_s64(int64_t * a, int64x1x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i32 0, i32 2
// CHECK: [[TMP8:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
// CHECK: [[TMP9:%.*]] = bitcast <4 x half> [[TMP8]] to <8 x i8>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x i16>
-// CHECK: call void @llvm.arm.neon.vst3.p0i8.v4i16(i8* [[TMP3]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], i32 2)
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x half>
+// CHECK: call void @llvm.arm.neon.vst3.p0i8.v4f16(i8* [[TMP3]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], <4 x half> [[TMP12]], i32 2)
// CHECK: ret void
void test_vst3_f16(float16_t * a, float16x4x3_t b) {
vst3_f16(a, b);
@@ -17631,10 +17626,10 @@ void test_vst3q_lane_s32(int32_t * a, int32x4x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i32 0, i32 2
// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16
// CHECK: [[TMP9:%.*]] = bitcast <8 x half> [[TMP8]] to <16 x i8>
-// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x i16>
-// CHECK: call void @llvm.arm.neon.vst3lane.p0i8.v8i16(i8* [[TMP3]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], i32 7, i32 2)
+// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x half>
+// CHECK: call void @llvm.arm.neon.vst3lane.p0i8.v8f16(i8* [[TMP3]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], <8 x half> [[TMP12]], i32 7, i32 2)
// CHECK: ret void
void test_vst3q_lane_f16(float16_t * a, float16x8x3_t b) {
vst3q_lane_f16(a, b, 7);
@@ -17896,10 +17891,10 @@ void test_vst3_lane_s32(int32_t * a, int32x2x3_t b) {
// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i32 0, i32 2
// CHECK: [[TMP8:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8
// CHECK: [[TMP9:%.*]] = bitcast <4 x half> [[TMP8]] to <8 x i8>
-// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x i16>
-// CHECK: call void @llvm.arm.neon.vst3lane.p0i8.v4i16(i8* [[TMP3]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], i32 3, i32 2)
+// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x half>
+// CHECK: call void @llvm.arm.neon.vst3lane.p0i8.v4f16(i8* [[TMP3]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], <4 x half> [[TMP12]], i32 3, i32 2)
// CHECK: ret void
void test_vst3_lane_f16(float16_t * a, float16x4x3_t b) {
vst3_lane_f16(a, b, 3);
@@ -18215,11 +18210,11 @@ void test_vst4q_s32(int32_t * a, int32x4x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i32 0, i32 3
// CHECK: [[TMP10:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
// CHECK: [[TMP11:%.*]] = bitcast <8 x half> [[TMP10]] to <16 x i8>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP11]] to <8 x i16>
-// CHECK: call void @llvm.arm.neon.vst4.p0i8.v8i16(i8* [[TMP3]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], <8 x i16> [[TMP15]], i32 2)
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP11]] to <8 x half>
+// CHECK: call void @llvm.arm.neon.vst4.p0i8.v8f16(i8* [[TMP3]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], <8 x half> [[TMP15]], i32 2)
// CHECK: ret void
void test_vst4q_f16(float16_t * a, float16x8x4_t b) {
vst4q_f16(a, b);
@@ -18620,11 +18615,11 @@ void test_vst4_s64(int64_t * a, int64x1x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i32 0, i32 3
// CHECK: [[TMP10:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
// CHECK: [[TMP11:%.*]] = bitcast <4 x half> [[TMP10]] to <8 x i8>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP11]] to <4 x i16>
-// CHECK: call void @llvm.arm.neon.vst4.p0i8.v4i16(i8* [[TMP3]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], <4 x i16> [[TMP15]], i32 2)
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP11]] to <4 x half>
+// CHECK: call void @llvm.arm.neon.vst4.p0i8.v4f16(i8* [[TMP3]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], <4 x half> [[TMP15]], i32 2)
// CHECK: ret void
void test_vst4_f16(float16_t * a, float16x4x4_t b) {
vst4_f16(a, b);
@@ -18899,11 +18894,11 @@ void test_vst4q_lane_s32(int32_t * a, int32x4x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i32 0, i32 3
// CHECK: [[TMP10:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16
// CHECK: [[TMP11:%.*]] = bitcast <8 x half> [[TMP10]] to <16 x i8>
-// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP11]] to <8 x i16>
-// CHECK: call void @llvm.arm.neon.vst4lane.p0i8.v8i16(i8* [[TMP3]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], <8 x i16> [[TMP15]], i32 7, i32 2)
+// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP9]] to <8 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP11]] to <8 x half>
+// CHECK: call void @llvm.arm.neon.vst4lane.p0i8.v8f16(i8* [[TMP3]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], <8 x half> [[TMP15]], i32 7, i32 2)
// CHECK: ret void
void test_vst4q_lane_f16(float16_t * a, float16x8x4_t b) {
vst4q_lane_f16(a, b, 7);
@@ -19205,11 +19200,11 @@ void test_vst4_lane_s32(int32_t * a, int32x2x4_t b) {
// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i32 0, i32 3
// CHECK: [[TMP10:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8
// CHECK: [[TMP11:%.*]] = bitcast <4 x half> [[TMP10]] to <8 x i8>
-// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x i16>
-// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x i16>
-// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x i16>
-// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP11]] to <4 x i16>
-// CHECK: call void @llvm.arm.neon.vst4lane.p0i8.v4i16(i8* [[TMP3]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], <4 x i16> [[TMP15]], i32 3, i32 2)
+// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP5]] to <4 x half>
+// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP7]] to <4 x half>
+// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP9]] to <4 x half>
+// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP11]] to <4 x half>
+// CHECK: call void @llvm.arm.neon.vst4lane.p0i8.v4f16(i8* [[TMP3]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], <4 x half> [[TMP15]], i32 3, i32 2)
// CHECK: ret void
void test_vst4_lane_f16(float16_t * a, float16x4x4_t b) {
vst4_lane_f16(a, b, 3);
diff --git a/test/CodeGen/asan-globals-odr.cpp b/test/CodeGen/asan-globals-odr.cpp
new file mode 100644
index 000000000000..4a148c3ce32f
--- /dev/null
+++ b/test/CodeGen/asan-globals-odr.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,INDICATOR0,GLOB_VAR,ALIAS0
+// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-use-odr-indicator -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,INDICATOR1,GLOB_ALIAS_INDICATOR,ALIAS1
+// RUN: %clang_cc1 -fsanitize=address -fno-sanitize-address-use-odr-indicator -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,INDICATOR0,GLOB_VAR,ALIAS0
+// RUN: %clang_cc1 -fsanitize=address -fno-sanitize-address-use-odr-indicator -fsanitize-address-use-odr-indicator -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,INDICATOR1,GLOB_ALIAS_INDICATOR,ALIAS1
+// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-use-odr-indicator -fno-sanitize-address-use-odr-indicator -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,INDICATOR0,GLOB_VAR,ALIAS0
+
+// No alias on Windows but indicators should work.
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefixes=CHECK,GLOB_VAR,ALIAS0
+// RUN: %clang_cc1 -fsanitize=address -fsanitize-address-use-odr-indicator -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefixes=CHECK,INDICATOR1,GLOB_VAR_INDICATOR,ALIAS0
+
+int global;
+
+int main() {
+ return global;
+}
+
+// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [60 x i8] } zeroinitializer, align 32
+
+// INDICATOR0-NOT: __odr_asan_gen
+// INDICATOR1: [[ODR:@.*__odr_asan_gen_.*global.*]] = global i8 0, align 1
+
+// GLOB_VAR: @0 = internal global {{.*}} [[VAR]] to i64), {{.*}}, i64 0 }]
+// GLOB_VAR_INDICATOR: @0 = internal global {{.*}} [[VAR]] to i64), {{.*}}, i64 ptrtoint (i8* [[ODR]] to i64) }]
+// GLOB_ALIAS_INDICATOR: @0 = internal global {{.*}} @1 to i64), {{.*}}, i64 ptrtoint (i8* [[ODR]] to i64) }]
+
+// ALIAS0-NOT: private alias
+// ALIAS1: @1 = private alias {{.*}} [[VAR]]
+
+// CHECK: call void @__asan_register_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)
+// CHECK: call void @__asan_unregister_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)
diff --git a/test/CodeGen/asan-static-odr.cpp b/test/CodeGen/asan-static-odr.cpp
new file mode 100644
index 000000000000..6b23b62e16fb
--- /dev/null
+++ b/test/CodeGen/asan-static-odr.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,ALIAS1
+
+// No alias on Windows but indicators should work.
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefixes=CHECK,ALIAS0
+
+static int global;
+
+int main() {
+ return global;
+}
+
+// CHECK-NOT: __odr_asan_gen
+// CHECK-NOT: private alias
+// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [60 x i8] } zeroinitializer, align 32
+// CHECK: @0 = internal global {{.*}} [[VAR]] to i64), {{.*}}, i64 -1 }]
+// CHECK: call void @__asan_register_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)
+// CHECK: call void @__asan_unregister_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)
diff --git a/test/CodeGen/asan-strings.c b/test/CodeGen/asan-strings.c
new file mode 100644
index 000000000000..fc9c31bcd8a2
--- /dev/null
+++ b/test/CodeGen/asan-strings.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=address -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fsanitize=address -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefix=WINDOWS
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fsanitize=address -fwritable-strings -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefix=WINWRITE
+
+// On Linux (and basically every non-MS target) string literals are emitted with
+// private linkage, which means ASan can freely instrument them. On Windows,
+// they are emitted with comdats. ASan's global instrumentation code for COFF
+// knows how to make the metadata comdat associative, so the string literal
+// global is only registered if the instrumented global prevails during linking.
+
+const char *foo() { return "asdf"; }
+
+// LINUX: @.str = private unnamed_addr constant [5 x i8] c"asdf\00", align 1
+
+// WINDOWS: @"??_C@_04JIHMPGLA@asdf?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i8] c"asdf\00", comdat, align 1
+
+// WINWRITE: @.str = private unnamed_addr global [5 x i8] c"asdf\00", align 1
diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c
index 500939f6fd75..c3a9729d4901 100644
--- a/test/CodeGen/atomic-ops.c
+++ b/test/CodeGen/atomic-ops.c
@@ -198,10 +198,12 @@ struct S implicit_load(_Atomic(struct S) *a) {
struct S fd1(struct S *a) {
// CHECK-LABEL: @fd1
// CHECK: [[RETVAL:%.*]] = alloca %struct.S, align 4
- // CHECK: bitcast %struct.S* {{.*}} to i64*
+ // CHECK: [[A:%.*]] = bitcast %struct.S* {{.*}} to i64*
// CHECK: [[CAST:%.*]] = bitcast %struct.S* [[RETVAL]] to i64*
- // CHECK: [[CALL:%.*]] = call i64 @__atomic_load_8(
- // CHECK: store i64 [[CALL]], i64* [[CAST]], align 4
+ // CHECK: [[SRC:%.*]] = bitcast i64* [[A]] to i8*
+ // CHECK: [[DEST:%.*]] = bitcast i64* [[CAST]] to i8*
+ // CHECK: call void @__atomic_load(i32 8, i8* [[SRC]], i8* [[DEST]], i32 5)
+ // CHECK: ret
struct S ret;
__atomic_load(a, &ret, memory_order_seq_cst);
return ret;
@@ -218,8 +220,8 @@ void fd2(struct S *a, struct S *b) {
// CHECK-NEXT: [[COERCED_A_TMP:%.*]] = bitcast %struct.S* [[LOAD_A_PTR]] to i64*
// CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i64*
// CHECK-NEXT: [[COERCED_A:%.*]] = bitcast i64* [[COERCED_A_TMP]] to i8*
- // CHECK-NEXT: [[LOAD_B:%.*]] = load i64, i64* [[COERCED_B]], align 4
- // CHECK-NEXT: call void @__atomic_store_8(i8* [[COERCED_A]], i64 [[LOAD_B]],
+ // CHECK-NEXT: [[CAST_B:%.*]] = bitcast i64* [[COERCED_B]] to i8*
+ // CHECK-NEXT: call void @__atomic_store(i32 8, i8* [[COERCED_A]], i8* [[CAST_B]],
// CHECK-NEXT: ret void
__atomic_store(a, b, memory_order_seq_cst);
}
@@ -239,9 +241,9 @@ void fd3(struct S *a, struct S *b, struct S *c) {
// CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i64*
// CHECK-NEXT: [[COERCED_C:%.*]] = bitcast %struct.S* [[LOAD_C_PTR]] to i64*
// CHECK-NEXT: [[COERCED_A:%.*]] = bitcast i64* [[COERCED_A_TMP]] to i8*
- // CHECK-NEXT: [[LOAD_B:%.*]] = load i64, i64* [[COERCED_B]], align 4
- // CHECK-NEXT: [[CALL:%.*]] = call i64 @__atomic_exchange_8(i8* [[COERCED_A]], i64 [[LOAD_B]],
- // CHECK-NEXT: store i64 [[CALL]], i64* [[COERCED_C]], align 4
+ // CHECK-NEXT: [[CAST_B:%.*]] = bitcast i64* [[COERCED_B]] to i8*
+ // CHECK-NEXT: [[CAST_C:%.*]] = bitcast i64* [[COERCED_C]] to i8*
+ // CHECK-NEXT: call void @__atomic_exchange(i32 8, i8* [[COERCED_A]], i8* [[CAST_B]], i8* [[CAST_C]],
__atomic_exchange(a, b, c, memory_order_seq_cst);
}
@@ -262,8 +264,8 @@ _Bool fd4(struct S *a, struct S *b, struct S *c) {
// CHECK-NEXT: [[COERCED_C:%.*]] = bitcast %struct.S* [[LOAD_C_PTR]] to i64*
// CHECK-NEXT: [[COERCED_A:%.*]] = bitcast i64* [[COERCED_A_TMP]] to i8*
// CHECK-NEXT: [[COERCED_B:%.*]] = bitcast i64* [[COERCED_B_TMP]] to i8*
- // CHECK-NEXT: [[LOAD_C:%.*]] = load i64, i64* [[COERCED_C]], align 4
- // CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange_8(i8* [[COERCED_A]], i8* [[COERCED_B]], i64 [[LOAD_C]]
+ // CHECK-NEXT: [[CAST_C:%.*]] = bitcast i64* [[COERCED_C]] to i8*
+ // CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i32 8, i8* [[COERCED_A]], i8* [[COERCED_B]], i8* [[CAST_C]],
// CHECK-NEXT: ret i1 [[CALL]]
return __atomic_compare_exchange(a, b, c, 1, 5, 5);
}
@@ -634,4 +636,29 @@ int PR17306_2(volatile int *i, int value) {
return __atomic_add_fetch(i, value, memory_order_seq_cst);
}
+void test_underaligned() {
+ // CHECK-LABEL: @test_underaligned
+ struct Underaligned { char c[8]; } underaligned_a, underaligned_b, underaligned_c;
+
+ // CHECK: call void @__atomic_load(i32 8,
+ __atomic_load(&underaligned_a, &underaligned_b, memory_order_seq_cst);
+ // CHECK: call void @__atomic_store(i32 8,
+ __atomic_store(&underaligned_a, &underaligned_b, memory_order_seq_cst);
+ // CHECK: call void @__atomic_exchange(i32 8,
+ __atomic_exchange(&underaligned_a, &underaligned_b, &underaligned_c, memory_order_seq_cst);
+ // CHECK: call {{.*}} @__atomic_compare_exchange(i32 8,
+ __atomic_compare_exchange(&underaligned_a, &underaligned_b, &underaligned_c, 1, memory_order_seq_cst, memory_order_seq_cst);
+
+ __attribute__((aligned)) struct Underaligned aligned_a, aligned_b, aligned_c;
+
+ // CHECK: load atomic
+ __atomic_load(&aligned_a, &aligned_b, memory_order_seq_cst);
+ // CHECK: store atomic
+ __atomic_store(&aligned_a, &aligned_b, memory_order_seq_cst);
+ // CHECK: atomicrmw xchg
+ __atomic_exchange(&aligned_a, &aligned_b, &aligned_c, memory_order_seq_cst);
+ // CHECK: cmpxchg weak
+ __atomic_compare_exchange(&aligned_a, &aligned_b, &aligned_c, 1, memory_order_seq_cst, memory_order_seq_cst);
+}
+
#endif
diff --git a/test/CodeGen/atomics-inlining.c b/test/CodeGen/atomics-inlining.c
index fc23c0b3f64f..7ba3f7f59b7b 100644
--- a/test/CodeGen/atomics-inlining.c
+++ b/test/CodeGen/atomics-inlining.c
@@ -2,7 +2,10 @@
// RUN: %clang_cc1 -triple powerpc-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=PPC32
// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=PPC64
// RUN: %clang_cc1 -triple mipsel-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS32
+// RUN: %clang_cc1 -triple mipsisa32r6el-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS32
// RUN: %clang_cc1 -triple mips64el-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS64
+// RUN: %clang_cc1 -triple mips64el-linux-gnuabi64 -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS64
+// RUN: %clang_cc1 -triple mipsisa64r6el-linux-gnuabi64 -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS64
// RUN: %clang_cc1 -triple sparc-unknown-eabi -emit-llvm %s -o - | FileCheck %s -check-prefix=SPARCV8 -check-prefix=SPARC
// RUN: %clang_cc1 -triple sparcv9-unknown-eabi -emit-llvm %s -o - | FileCheck %s -check-prefix=SPARCV9 -check-prefix=SPARC
diff --git a/test/CodeGen/atomics-sema-alignment.c b/test/CodeGen/atomics-sema-alignment.c
index 364743dd53f0..9443af354ec5 100644
--- a/test/CodeGen/atomics-sema-alignment.c
+++ b/test/CodeGen/atomics-sema-alignment.c
@@ -12,10 +12,10 @@ typedef int __attribute__((aligned(1))) unaligned_int;
void func(IntPair *p) {
IntPair res;
- __atomic_load(p, &res, 0); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
- __atomic_store(p, &res, 0); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
- __atomic_fetch_add((unaligned_int *)p, 1, 2); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
- __atomic_fetch_sub((unaligned_int *)p, 1, 3); // expected-warning {{misaligned or large atomic operation may incur significant performance penalty}}
+ __atomic_load(p, &res, 0); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
+ __atomic_store(p, &res, 0); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
+ __atomic_fetch_add((unaligned_int *)p, 1, 2); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
+ __atomic_fetch_sub((unaligned_int *)p, 1, 3); // expected-warning {{misaligned atomic operation may incur significant performance penalty}}
}
void func1(LongStruct *p) {
diff --git a/test/CodeGen/attr-cpuspecific.c b/test/CodeGen/attr-cpuspecific.c
index 1b98b5dc9678..d6c99648cb7d 100644
--- a/test/CodeGen/attr-cpuspecific.c
+++ b/test/CodeGen/attr-cpuspecific.c
@@ -1,100 +1,258 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX
+// RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WINDOWS
+#ifdef _WIN64
+#define ATTR(X) __declspec(X)
+#else
+#define ATTR(X) __attribute__((X))
+#endif // _MSC_VER
// Each called version should have an IFunc.
-// CHECK: @SingleVersion.ifunc = ifunc void (), void ()* ()* @SingleVersion.resolver
-// CHECK: @TwoVersions.ifunc = ifunc void (), void ()* ()* @TwoVersions.resolver
-// CHECK: @TwoVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @TwoVersionsSameAttr.resolver
-// CHECK: @ThreeVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @ThreeVersionsSameAttr.resolver
+// LINUX: @SingleVersion.ifunc = ifunc void (), void ()* ()* @SingleVersion.resolver
+// LINUX: @TwoVersions.ifunc = ifunc void (), void ()* ()* @TwoVersions.resolver
+// LINUX: @TwoVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @TwoVersionsSameAttr.resolver
+// LINUX: @ThreeVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @ThreeVersionsSameAttr.resolver
-__attribute__((cpu_specific(ivybridge)))
+ATTR(cpu_specific(ivybridge))
void SingleVersion(void){}
-// CHECK: define void @SingleVersion.S() #[[S:[0-9]+]]
+// LINUX: define void @SingleVersion.S() #[[S:[0-9]+]]
+// WINDOWS: define dso_local void @SingleVersion.S() #[[S:[0-9]+]]
-__attribute__((cpu_specific(ivybridge)))
+ATTR(cpu_specific(ivybridge))
void NotCalled(void){}
-// CHECK: define void @NotCalled.S() #[[S]]
+// LINUX: define void @NotCalled.S() #[[S]]
+// WINDOWS: define dso_local void @NotCalled.S() #[[S:[0-9]+]]
-// Done before any of the implementations.
-__attribute__((cpu_dispatch(ivybridge, knl)))
+// Done before any of the implementations. Also has an undecorated forward
+// declaration.
void TwoVersions(void);
-// CHECK: define void ()* @TwoVersions.resolver()
-// CHECK: call void @__cpu_indicator_init
-// CHECK: ret void ()* @TwoVersions.Z
-// CHECK: ret void ()* @TwoVersions.S
-// CHECK: call void @llvm.trap
-// CHECK: unreachable
-
-__attribute__((cpu_specific(ivybridge)))
+
+ATTR(cpu_dispatch(ivybridge, knl))
+void TwoVersions(void);
+// LINUX: define void ()* @TwoVersions.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret void ()* @TwoVersions.Z
+// LINUX: ret void ()* @TwoVersions.S
+// LINUX: call void @llvm.trap
+// LINUX: unreachable
+
+// WINDOWS: define dso_local void @TwoVersions()
+// WINDOWS: call void @__cpu_indicator_init()
+// WINDOWS: call void @TwoVersions.Z()
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @TwoVersions.S()
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @llvm.trap
+// WINDOWS: unreachable
+
+ATTR(cpu_specific(ivybridge))
void TwoVersions(void){}
-// CHECK: define void @TwoVersions.S() #[[S]]
+// CHECK: define {{.*}}void @TwoVersions.S() #[[S]]
-__attribute__((cpu_specific(knl)))
+ATTR(cpu_specific(knl))
void TwoVersions(void){}
-// CHECK: define void @TwoVersions.Z() #[[K:[0-9]+]]
+// CHECK: define {{.*}}void @TwoVersions.Z() #[[K:[0-9]+]]
-__attribute__((cpu_specific(ivybridge, knl)))
+ATTR(cpu_specific(ivybridge, knl))
void TwoVersionsSameAttr(void){}
-// CHECK: define void @TwoVersionsSameAttr.S() #[[S]]
-// CHECK: define void @TwoVersionsSameAttr.Z() #[[K]]
+// CHECK: define {{.*}}void @TwoVersionsSameAttr.S() #[[S]]
+// CHECK: define {{.*}}void @TwoVersionsSameAttr.Z() #[[K]]
-__attribute__((cpu_specific(atom, ivybridge, knl)))
+ATTR(cpu_specific(atom, ivybridge, knl))
void ThreeVersionsSameAttr(void){}
-// CHECK: define void @ThreeVersionsSameAttr.O() #[[O:[0-9]+]]
-// CHECK: define void @ThreeVersionsSameAttr.S() #[[S]]
-// CHECK: define void @ThreeVersionsSameAttr.Z() #[[K]]
+// CHECK: define {{.*}}void @ThreeVersionsSameAttr.O() #[[O:[0-9]+]]
+// CHECK: define {{.*}}void @ThreeVersionsSameAttr.S() #[[S]]
+// CHECK: define {{.*}}void @ThreeVersionsSameAttr.Z() #[[K]]
void usages() {
SingleVersion();
- // CHECK: @SingleVersion.ifunc()
+ // LINUX: @SingleVersion.ifunc()
+ // WINDOWS: @SingleVersion()
TwoVersions();
- // CHECK: @TwoVersions.ifunc()
+ // LINUX: @TwoVersions.ifunc()
+ // WINDOWS: @TwoVersions()
TwoVersionsSameAttr();
- // CHECK: @TwoVersionsSameAttr.ifunc()
+ // LINUX: @TwoVersionsSameAttr.ifunc()
+ // WINDOWS: @TwoVersionsSameAttr()
ThreeVersionsSameAttr();
- // CHECK: @ThreeVersionsSameAttr.ifunc()
+ // LINUX: @ThreeVersionsSameAttr.ifunc()
+ // WINDOWS: @ThreeVersionsSameAttr()
}
// has an extra config to emit!
-__attribute__((cpu_dispatch(ivybridge, knl, atom)))
+ATTR(cpu_dispatch(ivybridge, knl, atom))
void TwoVersionsSameAttr(void);
-// CHECK: define void ()* @TwoVersionsSameAttr.resolver()
-// CHECK: ret void ()* @TwoVersionsSameAttr.Z
-// CHECK: ret void ()* @TwoVersionsSameAttr.S
-// CHECK: ret void ()* @TwoVersionsSameAttr.O
-// CHECK: call void @llvm.trap
-// CHECK: unreachable
-
-__attribute__((cpu_dispatch(atom, ivybridge, knl)))
+// LINUX: define void ()* @TwoVersionsSameAttr.resolver()
+// LINUX: ret void ()* @TwoVersionsSameAttr.Z
+// LINUX: ret void ()* @TwoVersionsSameAttr.S
+// LINUX: ret void ()* @TwoVersionsSameAttr.O
+// LINUX: call void @llvm.trap
+// LINUX: unreachable
+
+// WINDOWS: define dso_local void @TwoVersionsSameAttr()
+// WINDOWS: call void @TwoVersionsSameAttr.Z
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @TwoVersionsSameAttr.S
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @TwoVersionsSameAttr.O
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @llvm.trap
+// WINDOWS: unreachable
+
+ATTR(cpu_dispatch(atom, ivybridge, knl))
void ThreeVersionsSameAttr(void){}
-// CHECK: define void ()* @ThreeVersionsSameAttr.resolver()
-// CHECK: call void @__cpu_indicator_init
-// CHECK: ret void ()* @ThreeVersionsSameAttr.Z
-// CHECK: ret void ()* @ThreeVersionsSameAttr.S
-// CHECK: ret void ()* @ThreeVersionsSameAttr.O
-// CHECK: call void @llvm.trap
-// CHECK: unreachable
+// LINUX: define void ()* @ThreeVersionsSameAttr.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret void ()* @ThreeVersionsSameAttr.Z
+// LINUX: ret void ()* @ThreeVersionsSameAttr.S
+// LINUX: ret void ()* @ThreeVersionsSameAttr.O
+// LINUX: call void @llvm.trap
+// LINUX: unreachable
+
+// WINDOWS: define dso_local void @ThreeVersionsSameAttr()
+// WINDOWS: call void @__cpu_indicator_init
+// WINDOWS: call void @ThreeVersionsSameAttr.Z
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @ThreeVersionsSameAttr.S
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @ThreeVersionsSameAttr.O
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @llvm.trap
+// WINDOWS: unreachable
// No Cpu Specific options.
-__attribute__((cpu_dispatch(atom, ivybridge, knl)))
+ATTR(cpu_dispatch(atom, ivybridge, knl))
void NoSpecifics(void);
-// CHECK: define void ()* @NoSpecifics.resolver()
-// CHECK: call void @__cpu_indicator_init
-// CHECK: ret void ()* @NoSpecifics.Z
-// CHECK: ret void ()* @NoSpecifics.S
-// CHECK: ret void ()* @NoSpecifics.O
-// CHECK: call void @llvm.trap
-// CHECK: unreachable
-
-__attribute__((cpu_dispatch(atom, generic, ivybridge, knl)))
+// LINUX: define void ()* @NoSpecifics.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret void ()* @NoSpecifics.Z
+// LINUX: ret void ()* @NoSpecifics.S
+// LINUX: ret void ()* @NoSpecifics.O
+// LINUX: call void @llvm.trap
+// LINUX: unreachable
+
+// WINDOWS: define dso_local void @NoSpecifics()
+// WINDOWS: call void @__cpu_indicator_init
+// WINDOWS: call void @NoSpecifics.Z
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @NoSpecifics.S
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @NoSpecifics.O
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @llvm.trap
+// WINDOWS: unreachable
+
+ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
void HasGeneric(void);
-// CHECK: define void ()* @HasGeneric.resolver()
-// CHECK: call void @__cpu_indicator_init
-// CHECK: ret void ()* @HasGeneric.Z
-// CHECK: ret void ()* @HasGeneric.S
-// CHECK: ret void ()* @HasGeneric.O
-// CHECK: ret void ()* @HasGeneric.A
-// CHECK-NOT: call void @llvm.trap
+// LINUX: define void ()* @HasGeneric.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret void ()* @HasGeneric.Z
+// LINUX: ret void ()* @HasGeneric.S
+// LINUX: ret void ()* @HasGeneric.O
+// LINUX: ret void ()* @HasGeneric.A
+// LINUX-NOT: call void @llvm.trap
+
+// WINDOWS: define dso_local void @HasGeneric()
+// WINDOWS: call void @__cpu_indicator_init
+// WINDOWS: call void @HasGeneric.Z
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @HasGeneric.S
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @HasGeneric.O
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @HasGeneric.A
+// WINDOWS-NEXT: ret void
+// WINDOWS-NOT: call void @llvm.trap
+
+ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
+void HasParams(int i, double d);
+// LINUX: define void (i32, double)* @HasParams.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret void (i32, double)* @HasParams.Z
+// LINUX: ret void (i32, double)* @HasParams.S
+// LINUX: ret void (i32, double)* @HasParams.O
+// LINUX: ret void (i32, double)* @HasParams.A
+// LINUX-NOT: call void @llvm.trap
+
+// WINDOWS: define dso_local void @HasParams(i32, double)
+// WINDOWS: call void @__cpu_indicator_init
+// WINDOWS: call void @HasParams.Z(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @HasParams.S(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @HasParams.O(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @HasParams.A(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+// WINDOWS-NOT: call void @llvm.trap
+
+ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
+int HasParamsAndReturn(int i, double d);
+// LINUX: define i32 (i32, double)* @HasParamsAndReturn.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.Z
+// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.S
+// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.O
+// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.A
+// LINUX-NOT: call void @llvm.trap
+
+// WINDOWS: define dso_local i32 @HasParamsAndReturn(i32, double)
+// WINDOWS: call void @__cpu_indicator_init
+// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.Z(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.S(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.O(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.A(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS-NOT: call void @llvm.trap
+
+ATTR(cpu_dispatch(atom, generic, pentium))
+int GenericAndPentium(int i, double d);
+// LINUX: define i32 (i32, double)* @GenericAndPentium.resolver()
+// LINUX: call void @__cpu_indicator_init
+// LINUX: ret i32 (i32, double)* @GenericAndPentium.O
+// LINUX: ret i32 (i32, double)* @GenericAndPentium.B
+// LINUX-NOT: ret i32 (i32, double)* @GenericAndPentium.A
+// LINUX-NOT: call void @llvm.trap
+
+// WINDOWS: define dso_local i32 @GenericAndPentium(i32, double)
+// WINDOWS: call void @__cpu_indicator_init
+// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.O(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.B(i32 %0, double %1)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS-NOT: call i32 @GenericAndPentium.A
+// WINDOWS-NOT: call void @llvm.trap
+
+ATTR(cpu_dispatch(atom, pentium))
+int DispatchFirst(void);
+// LINUX: define i32 ()* @DispatchFirst.resolver
+// LINUX: ret i32 ()* @DispatchFirst.O
+// LINUX: ret i32 ()* @DispatchFirst.B
+
+// WINDOWS: define dso_local i32 @DispatchFirst()
+// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.O()
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.B()
+// WINDOWS-NEXT: ret i32 %[[RET]]
+
+ATTR(cpu_specific(atom))
+int DispatchFirst(void) {return 0;}
+// LINUX: define i32 @DispatchFirst.O
+// LINUX: ret i32 0
+
+// WINDOWS: define dso_local i32 @DispatchFirst.O()
+// WINDOWS: ret i32 0
+
+ATTR(cpu_specific(pentium))
+int DispatchFirst(void) {return 1;}
+// LINUX: define i32 @DispatchFirst.B
+// LINUX: ret i32 1
+
+// WINDOWS: define dso_local i32 @DispatchFirst.B
+// WINDOWS: ret i32 1
// CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
// CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
diff --git a/test/CodeGen/attr-speculative-load-hardening.c b/test/CodeGen/attr-speculative-load-hardening.c
new file mode 100644
index 000000000000..97bccd03585c
--- /dev/null
+++ b/test/CodeGen/attr-speculative-load-hardening.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -mspeculative-load-hardening -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=SLH
+// RUN: %clang -mno-speculative-load-hardening -S -emit-llvm %s -o - | FileCheck %s -check-prefix=NOSLH
+//
+// Check that we set the attribute on each function.
+
+int test1() {
+ return 42;
+}
+// SLH: @{{.*}}test1{{.*}}[[SLH:#[0-9]+]]
+
+// SLH: attributes [[SLH]] = { {{.*}}speculative_load_hardening{{.*}} }
+
+// NOSLH: @{{.*}}test1{{.*}}[[NOSLH:#[0-9]+]]
+
+// NOSLH-NOT: attributes [[SLH]] = { {{.*}}speculative_load_hardening{{.*}} }
diff --git a/test/CodeGen/attr-speculative-load-hardening.cpp b/test/CodeGen/attr-speculative-load-hardening.cpp
new file mode 100644
index 000000000000..e2eb805cbb85
--- /dev/null
+++ b/test/CodeGen/attr-speculative-load-hardening.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK1
+// RUN: %clang_cc1 -std=c++11 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK2
+//
+// Check that we set the attribute on each function.
+
+[[clang::speculative_load_hardening]]
+int test1() {
+ return 42;
+}
+
+int __attribute__((speculative_load_hardening)) test2() {
+ return 42;
+}
+// CHECK1: @{{.*}}test1{{.*}}[[SLH1:#[0-9]+]]
+// CHECK1: attributes [[SLH1]] = { {{.*}}speculative_load_hardening{{.*}} }
+
+// CHECK2: @{{.*}}test2{{.*}}[[SLH2:#[0-9]+]]
+// CHECK2: attributes [[SLH2]] = { {{.*}}speculative_load_hardening{{.*}} }
diff --git a/test/CodeGen/attr-speculative-load-hardening.m b/test/CodeGen/attr-speculative-load-hardening.m
new file mode 100644
index 000000000000..2de945b974fa
--- /dev/null
+++ b/test/CodeGen/attr-speculative-load-hardening.m
@@ -0,0 +1,9 @@
+// RUN: %clang -emit-llvm %s -o - -S | FileCheck %s -check-prefix=SLH
+
+int main() __attribute__((speculative_load_hardening)) {
+ return 0;
+}
+
+// SLH: @{{.*}}main{{.*}}[[SLH:#[0-9]+]]
+
+// SLH: attributes [[SLH]] = { {{.*}}speculative_load_hardening{{.*}} }
diff --git a/test/CodeGen/attr-target-mv-func-ptrs.c b/test/CodeGen/attr-target-mv-func-ptrs.c
index 5df9a927cf8d..d1ff80050c14 100644
--- a/test/CodeGen/attr-target-mv-func-ptrs.c
+++ b/test/CodeGen/attr-target-mv-func-ptrs.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
int __attribute__((target("sse4.2"))) foo(int i) { return 0; }
int __attribute__((target("arch=sandybridge"))) foo(int);
int __attribute__((target("arch=ivybridge"))) foo(int i) {return 1;}
@@ -16,17 +17,31 @@ int bar() {
return Free(1) + Free(2);
}
-// CHECK: @foo.ifunc = ifunc i32 (i32), i32 (i32)* ()* @foo.resolver
-// CHECK: define i32 @foo.sse4.2(
-// CHECK: ret i32 0
-// CHECK: define i32 @foo.arch_ivybridge(
-// CHECK: ret i32 1
-// CHECK: define i32 @foo(
-// CHECK: ret i32 2
+// LINUX: @foo.ifunc = ifunc i32 (i32), i32 (i32)* ()* @foo.resolver
+// LINUX: define i32 @foo.sse4.2(
+// LINUX: ret i32 0
+// LINUX: define i32 @foo.arch_ivybridge(
+// LINUX: ret i32 1
+// LINUX: define i32 @foo(
+// LINUX: ret i32 2
-// CHECK: define i32 @bar()
-// CHECK: call void @func(i32 (i32)* @foo.ifunc)
-// CHECK: store i32 (i32)* @foo.ifunc
-// CHECK: store i32 (i32)* @foo.ifunc
+// WINDOWS: define dso_local i32 @foo.sse4.2(
+// WINDOWS: ret i32 0
+// WINDOWS: define dso_local i32 @foo.arch_ivybridge(
+// WINDOWS: ret i32 1
+// WINDOWS: define dso_local i32 @foo(
+// WINDOWS: ret i32 2
-// CHECK: declare i32 @foo.arch_sandybridge(
+// LINUX: define i32 @bar()
+// LINUX: call void @func(i32 (i32)* @foo.ifunc)
+// LINUX: store i32 (i32)* @foo.ifunc
+// LINUX: store i32 (i32)* @foo.ifunc
+
+// WINDOWS: define dso_local i32 @bar()
+// WINDOWS: call void @func(i32 (i32)* @foo.resolver)
+// WINDOWS: store i32 (i32)* @foo.resolver
+// WINDOWS: store i32 (i32)* @foo.resolver
+
+// LINUX: declare i32 @foo.arch_sandybridge(
+
+// WINDOWS: declare dso_local i32 @foo.arch_sandybridge(
diff --git a/test/CodeGen/attr-target-mv-va-args.c b/test/CodeGen/attr-target-mv-va-args.c
index b33f841dba5e..356b769140e9 100644
--- a/test/CodeGen/attr-target-mv-va-args.c
+++ b/test/CodeGen/attr-target-mv-va-args.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
int __attribute__((target("sse4.2"))) foo(int i, ...) { return 0; }
int __attribute__((target("arch=sandybridge"))) foo(int i, ...);
int __attribute__((target("arch=ivybridge"))) foo(int i, ...) {return 1;}
@@ -8,19 +9,37 @@ int bar() {
return foo(1, 'a', 1.1) + foo(2, 2.2, "asdf");
}
-// CHECK: @foo.ifunc = ifunc i32 (i32, ...), i32 (i32, ...)* ()* @foo.resolver
-// CHECK: define i32 @foo.sse4.2(i32 %i, ...)
-// CHECK: ret i32 0
-// CHECK: define i32 @foo.arch_ivybridge(i32 %i, ...)
-// CHECK: ret i32 1
-// CHECK: define i32 @foo(i32 %i, ...)
-// CHECK: ret i32 2
-// CHECK: define i32 @bar()
-// CHECK: call i32 (i32, ...) @foo.ifunc(i32 1, i32 97, double
-// CHECK: call i32 (i32, ...) @foo.ifunc(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds
-// CHECK: define i32 (i32, ...)* @foo.resolver() comdat
-// CHECK: ret i32 (i32, ...)* @foo.arch_sandybridge
-// CHECK: ret i32 (i32, ...)* @foo.arch_ivybridge
-// CHECK: ret i32 (i32, ...)* @foo.sse4.2
-// CHECK: ret i32 (i32, ...)* @foo
-// CHECK: declare i32 @foo.arch_sandybridge(i32, ...)
+// LINUX: @foo.ifunc = ifunc i32 (i32, ...), i32 (i32, ...)* ()* @foo.resolver
+// LINUX: define i32 @foo.sse4.2(i32 %i, ...)
+// LINUX: ret i32 0
+// LINUX: define i32 @foo.arch_ivybridge(i32 %i, ...)
+// LINUX: ret i32 1
+// LINUX: define i32 @foo(i32 %i, ...)
+// LINUX: ret i32 2
+// LINUX: define i32 @bar()
+// LINUX: call i32 (i32, ...) @foo.ifunc(i32 1, i32 97, double
+// LINUX: call i32 (i32, ...) @foo.ifunc(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds
+
+// LINUX: define i32 (i32, ...)* @foo.resolver() comdat
+// LINUX: ret i32 (i32, ...)* @foo.arch_sandybridge
+// LINUX: ret i32 (i32, ...)* @foo.arch_ivybridge
+// LINUX: ret i32 (i32, ...)* @foo.sse4.2
+// LINUX: ret i32 (i32, ...)* @foo
+// LINUX: declare i32 @foo.arch_sandybridge(i32, ...)
+
+// WINDOWS: define dso_local i32 @foo.sse4.2(i32 %i, ...)
+// WINDOWS: ret i32 0
+// WINDOWS: define dso_local i32 @foo.arch_ivybridge(i32 %i, ...)
+// WINDOWS: ret i32 1
+// WINDOWS: define dso_local i32 @foo(i32 %i, ...)
+// WINDOWS: ret i32 2
+// WINDOWS: define dso_local i32 @bar()
+// WINDOWS: call i32 (i32, ...) @foo.resolver(i32 1, i32 97, double
+// WINDOWS: call i32 (i32, ...) @foo.resolver(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds
+
+// WINDOWS: define dso_local i32 @foo.resolver(i32, ...) comdat
+// WINDOWS: musttail call i32 (i32, ...) @foo.arch_sandybridge
+// WINDOWS: musttail call i32 (i32, ...) @foo.arch_ivybridge
+// WINDOWS: musttail call i32 (i32, ...) @foo.sse4.2
+// WINDOWS: musttail call i32 (i32, ...) @foo
+// WINDOWS: declare dso_local i32 @foo.arch_sandybridge(i32, ...)
diff --git a/test/CodeGen/attr-target-mv.c b/test/CodeGen/attr-target-mv.c
index 0085a154ced1..363dea6a2fcb 100644
--- a/test/CodeGen/attr-target-mv.c
+++ b/test/CodeGen/attr-target-mv.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
+
int __attribute__((target("sse4.2"))) foo(void) { return 0; }
int __attribute__((target("arch=sandybridge"))) foo(void);
int __attribute__((target("arch=ivybridge"))) foo(void) {return 1;}
@@ -25,67 +27,208 @@ void bar3() {
inline __attribute__((target("default"))) void foo_decls(void) {}
inline __attribute__((target("sse4.2"))) void foo_decls(void) {}
-inline __attribute__((target("default"))) void foo_multi(void) {}
-inline __attribute__((target("avx,sse4.2"))) void foo_multi(void) {}
-inline __attribute__((target("sse4.2,fma4"))) void foo_multi(void) {}
-inline __attribute__((target("arch=ivybridge,fma4,sse4.2"))) void foo_multi(void) {}
+inline __attribute__((target("default"))) void foo_multi(int i, double d) {}
+inline __attribute__((target("avx,sse4.2"))) void foo_multi(int i, double d) {}
+inline __attribute__((target("sse4.2,fma4"))) void foo_multi(int i, double d) {}
+inline __attribute__((target("arch=ivybridge,fma4,sse4.2"))) void foo_multi(int i, double d) {}
void bar4() {
- foo_multi();
+ foo_multi(1, 5.0);
}
-// CHECK: @foo.ifunc = ifunc i32 (), i32 ()* ()* @foo.resolver
-// CHECK: @foo_inline.ifunc = ifunc i32 (), i32 ()* ()* @foo_inline.resolver
-// CHECK: @foo_decls.ifunc = ifunc void (), void ()* ()* @foo_decls.resolver
-
-// CHECK: define i32 @foo.sse4.2()
-// CHECK: ret i32 0
-// CHECK: define i32 @foo.arch_ivybridge()
-// CHECK: ret i32 1
-// CHECK: define i32 @foo()
-// CHECK: ret i32 2
-// CHECK: define i32 @bar()
-// CHECK: call i32 @foo.ifunc()
-
-// CHECK: define i32 ()* @foo.resolver() comdat
-// CHECK: call void @__cpu_indicator_init()
-// CHECK: ret i32 ()* @foo.arch_sandybridge
-// CHECK: ret i32 ()* @foo.arch_ivybridge
-// CHECK: ret i32 ()* @foo.sse4.2
-// CHECK: ret i32 ()* @foo
-
-// CHECK: define i32 @bar2()
-// CHECK: call i32 @foo_inline.ifunc()
-
-// CHECK: define i32 ()* @foo_inline.resolver() comdat
-// CHECK: call void @__cpu_indicator_init()
-// CHECK: ret i32 ()* @foo_inline.arch_sandybridge
-// CHECK: ret i32 ()* @foo_inline.arch_ivybridge
-// CHECK: ret i32 ()* @foo_inline.sse4.2
-// CHECK: ret i32 ()* @foo_inline
-
-// CHECK: define void @bar3()
-// CHECK: call void @foo_decls.ifunc()
-
-// CHECK: define void ()* @foo_decls.resolver() comdat
-// CHECK: ret void ()* @foo_decls.sse4.2
-// CHECK: ret void ()* @foo_decls
-
-// CHECK: declare i32 @foo.arch_sandybridge()
-
-// CHECK: define available_externally i32 @foo_inline.sse4.2()
-// CHECK: ret i32 0
-
-// CHECK: declare i32 @foo_inline.arch_sandybridge()
-//
-// CHECK: define available_externally i32 @foo_inline.arch_ivybridge()
-// CHECK: ret i32 1
-// CHECK: define available_externally i32 @foo_inline()
-// CHECK: ret i32 2
-
-// CHECK: define available_externally void @foo_decls()
-// CHECK: define available_externally void @foo_decls.sse4.2()
-
-// CHECK: define available_externally void @foo_multi.avx_sse4.2()
-// CHECK: define available_externally void @foo_multi.fma4_sse4.2()
-// CHECK: define available_externally void @foo_multi.arch_ivybridge_fma4_sse4.2()
+int fwd_decl_default(void);
+int __attribute__((target("default"))) fwd_decl_default(void) { return 2; }
+
+int fwd_decl_avx(void);
+int __attribute__((target("avx"))) fwd_decl_avx(void) { return 2; }
+int __attribute__((target("default"))) fwd_decl_avx(void) { return 2; }
+
+void bar5() {
+ fwd_decl_default();
+ fwd_decl_avx();
+}
+// LINUX: @foo.ifunc = ifunc i32 (), i32 ()* ()* @foo.resolver
+// LINUX: @foo_inline.ifunc = ifunc i32 (), i32 ()* ()* @foo_inline.resolver
+// LINUX: @foo_decls.ifunc = ifunc void (), void ()* ()* @foo_decls.resolver
+// LINUX: @foo_multi.ifunc = ifunc void (i32, double), void (i32, double)* ()* @foo_multi.resolver
+// LINUX: @fwd_decl_default.ifunc = ifunc i32 (), i32 ()* ()* @fwd_decl_default.resolver
+// LINUX: @fwd_decl_avx.ifunc = ifunc i32 (), i32 ()* ()* @fwd_decl_avx.resolver
+
+// LINUX: define i32 @foo.sse4.2()
+// LINUX: ret i32 0
+// LINUX: define i32 @foo.arch_ivybridge()
+// LINUX: ret i32 1
+// LINUX: define i32 @foo()
+// LINUX: ret i32 2
+// LINUX: define i32 @bar()
+// LINUX: call i32 @foo.ifunc()
+
+// WINDOWS: define dso_local i32 @foo.sse4.2()
+// WINDOWS: ret i32 0
+// WINDOWS: define dso_local i32 @foo.arch_ivybridge()
+// WINDOWS: ret i32 1
+// WINDOWS: define dso_local i32 @foo()
+// WINDOWS: ret i32 2
+// WINDOWS: define dso_local i32 @bar()
+// WINDOWS: call i32 @foo.resolver()
+
+// LINUX: define i32 ()* @foo.resolver() comdat
+// LINUX: call void @__cpu_indicator_init()
+// LINUX: ret i32 ()* @foo.arch_sandybridge
+// LINUX: ret i32 ()* @foo.arch_ivybridge
+// LINUX: ret i32 ()* @foo.sse4.2
+// LINUX: ret i32 ()* @foo
+
+// WINDOWS: define dso_local i32 @foo.resolver() comdat
+// WINDOWS: call void @__cpu_indicator_init()
+// WINDOWS: call i32 @foo.arch_sandybridge
+// WINDOWS: call i32 @foo.arch_ivybridge
+// WINDOWS: call i32 @foo.sse4.2
+// WINDOWS: call i32 @foo
+
+// LINUX: define i32 @bar2()
+// LINUX: call i32 @foo_inline.ifunc()
+
+// WINDOWS: define dso_local i32 @bar2()
+// WINDOWS: call i32 @foo_inline.resolver()
+
+// LINUX: define i32 ()* @foo_inline.resolver() comdat
+// LINUX: call void @__cpu_indicator_init()
+// LINUX: ret i32 ()* @foo_inline.arch_sandybridge
+// LINUX: ret i32 ()* @foo_inline.arch_ivybridge
+// LINUX: ret i32 ()* @foo_inline.sse4.2
+// LINUX: ret i32 ()* @foo_inline
+
+// WINDOWS: define dso_local i32 @foo_inline.resolver() comdat
+// WINDOWS: call void @__cpu_indicator_init()
+// WINDOWS: call i32 @foo_inline.arch_sandybridge
+// WINDOWS: call i32 @foo_inline.arch_ivybridge
+// WINDOWS: call i32 @foo_inline.sse4.2
+// WINDOWS: call i32 @foo_inline
+
+// LINUX: define void @bar3()
+// LINUX: call void @foo_decls.ifunc()
+
+// WINDOWS: define dso_local void @bar3()
+// WINDOWS: call void @foo_decls.resolver()
+
+// LINUX: define void ()* @foo_decls.resolver() comdat
+// LINUX: ret void ()* @foo_decls.sse4.2
+// LINUX: ret void ()* @foo_decls
+
+// WINDOWS: define dso_local void @foo_decls.resolver() comdat
+// WINDOWS: call void @foo_decls.sse4.2
+// WINDOWS: call void @foo_decls
+
+// LINUX: define void @bar4()
+// LINUX: call void @foo_multi.ifunc(i32 1, double 5.{{[0+e]*}})
+
+// WINDOWS: define dso_local void @bar4()
+// WINDOWS: call void @foo_multi.resolver(i32 1, double 5.{{[0+e]*}})
+
+// LINUX: define void (i32, double)* @foo_multi.resolver() comdat
+// LINUX: and i32 %{{.*}}, 4352
+// LINUX: icmp eq i32 %{{.*}}, 4352
+// LINUX: ret void (i32, double)* @foo_multi.fma4_sse4.2
+// LINUX: icmp eq i32 %{{.*}}, 12
+// LINUX: and i32 %{{.*}}, 4352
+// LINUX: icmp eq i32 %{{.*}}, 4352
+// LINUX: ret void (i32, double)* @foo_multi.arch_ivybridge_fma4_sse4.2
+// LINUX: and i32 %{{.*}}, 768
+// LINUX: icmp eq i32 %{{.*}}, 768
+// LINUX: ret void (i32, double)* @foo_multi.avx_sse4.2
+// LINUX: ret void (i32, double)* @foo_multi
+
+// WINDOWS: define dso_local void @foo_multi.resolver(i32, double) comdat
+// WINDOWS: and i32 %{{.*}}, 4352
+// WINDOWS: icmp eq i32 %{{.*}}, 4352
+// WINDOWS: call void @foo_multi.fma4_sse4.2(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+// WINDOWS: icmp eq i32 %{{.*}}, 12
+// WINDOWS: and i32 %{{.*}}, 4352
+// WINDOWS: icmp eq i32 %{{.*}}, 4352
+// WINDOWS: call void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+// WINDOWS: and i32 %{{.*}}, 768
+// WINDOWS: icmp eq i32 %{{.*}}, 768
+// WINDOWS: call void @foo_multi.avx_sse4.2(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+// WINDOWS: call void @foo_multi(i32 %0, double %1)
+// WINDOWS-NEXT: ret void
+
+// LINUX: define i32 @fwd_decl_default()
+// LINUX: ret i32 2
+// LINUX: define i32 @fwd_decl_avx.avx()
+// LINUX: ret i32 2
+// LINUX: define i32 @fwd_decl_avx()
+// LINUX: ret i32 2
+
+// WINDOWS: define dso_local i32 @fwd_decl_default()
+// WINDOWS: ret i32 2
+// WINDOWS: define dso_local i32 @fwd_decl_avx.avx()
+// WINDOWS: ret i32 2
+// WINDOWS: define dso_local i32 @fwd_decl_avx()
+// WINDOWS: ret i32 2
+
+// LINUX: define void @bar5()
+// LINUX: call i32 @fwd_decl_default.ifunc()
+// LINUX: call i32 @fwd_decl_avx.ifunc()
+
+// WINDOWS: define dso_local void @bar5()
+// WINDOWS: call i32 @fwd_decl_default.resolver()
+// WINDOWS: call i32 @fwd_decl_avx.resolver()
+
+// LINUX: define i32 ()* @fwd_decl_default.resolver() comdat
+// LINUX: call void @__cpu_indicator_init()
+// LINUX: ret i32 ()* @fwd_decl_default
+// LINUX: define i32 ()* @fwd_decl_avx.resolver() comdat
+// LINUX: call void @__cpu_indicator_init()
+// LINUX: ret i32 ()* @fwd_decl_avx.avx
+// LINUX: ret i32 ()* @fwd_decl_avx
+
+// WINDOWS: define dso_local i32 @fwd_decl_default.resolver() comdat
+// WINDOWS: call void @__cpu_indicator_init()
+// WINDOWS: call i32 @fwd_decl_default
+// WINDOWS: define dso_local i32 @fwd_decl_avx.resolver() comdat
+// WINDOWS: call void @__cpu_indicator_init()
+// WINDOWS: call i32 @fwd_decl_avx.avx
+// WINDOWS: call i32 @fwd_decl_avx
+
+// LINUX: declare i32 @foo.arch_sandybridge()
+// WINDOWS: declare dso_local i32 @foo.arch_sandybridge()
+
+// LINUX: define linkonce i32 @foo_inline.sse4.2()
+// LINUX: ret i32 0
+
+// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.sse4.2()
+// WINDOWS: ret i32 0
+
+// LINUX: declare i32 @foo_inline.arch_sandybridge()
+
+// WINDOWS: declare dso_local i32 @foo_inline.arch_sandybridge()
+
+// LINUX: define linkonce i32 @foo_inline.arch_ivybridge()
+// LINUX: ret i32 1
+// LINUX: define linkonce i32 @foo_inline()
+// LINUX: ret i32 2
+
+// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.arch_ivybridge()
+// WINDOWS: ret i32 1
+// WINDOWS: define linkonce_odr dso_local i32 @foo_inline()
+// WINDOWS: ret i32 2
+
+// LINUX: define linkonce void @foo_decls()
+// LINUX: define linkonce void @foo_decls.sse4.2()
+
+// WINDOWS: define linkonce_odr dso_local void @foo_decls()
+// WINDOWS: define linkonce_odr dso_local void @foo_decls.sse4.2()
+
+// LINUX: define linkonce void @foo_multi(i32 %{{[^,]+}}, double %{{[^\)]+}})
+// LINUX: define linkonce void @foo_multi.avx_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
+// LINUX: define linkonce void @foo_multi.fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
+// LINUX: define linkonce void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
+
+// WINDOWS: define linkonce_odr dso_local void @foo_multi(i32 %{{[^,]+}}, double %{{[^\)]+}})
+// WINDOWS: define linkonce_odr dso_local void @foo_multi.avx_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
+// WINDOWS: define linkonce_odr dso_local void @foo_multi.fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
+// WINDOWS: define linkonce_odr dso_local void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
diff --git a/test/CodeGen/attr-target-x86.c b/test/CodeGen/attr-target-x86.c
index ca544e4eaefb..153cdb3e94c9 100644
--- a/test/CodeGen/attr-target-x86.c
+++ b/test/CodeGen/attr-target-x86.c
@@ -49,7 +49,7 @@ int __attribute__((target("arch=lakemont,mmx"))) use_before_def(void) {
// CHECK: lake{{.*}} #7
// CHECK: use_before_def{{.*}} #7
// CHECK: #0 = {{.*}}"target-cpu"="i686" "target-features"="+x87"
-// CHECK: #1 = {{.*}}"target-cpu"="ivybridge" "target-features"="+aes,+avx,+cx16,+f16c,+fsgsbase,+fxsr,+mmx,+pclmul,+popcnt,+rdrnd,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"
+// CHECK: #1 = {{.*}}"target-cpu"="ivybridge" "target-features"="+avx,+cx16,+f16c,+fsgsbase,+fxsr,+mmx,+pclmul,+popcnt,+rdrnd,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"
// CHECK: #2 = {{.*}}"target-cpu"="i686" "target-features"="+x87,-aes,-avx,-avx2,-avx512bitalg,-avx512bw,-avx512cd,-avx512dq,-avx512er,-avx512f,-avx512ifma,-avx512pf,-avx512vbmi,-avx512vbmi2,-avx512vl,-avx512vnni,-avx512vpopcntdq,-f16c,-fma,-fma4,-gfni,-pclmul,-sha,-sse2,-sse3,-sse4.1,-sse4.2,-sse4a,-ssse3,-vaes,-vpclmulqdq,-xop,-xsave,-xsaveopt"
// CHECK: #3 = {{.*}}"target-cpu"="i686" "target-features"="+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87"
// CHECK: #4 = {{.*}}"target-cpu"="i686" "target-features"="+x87,-avx,-avx2,-avx512bitalg,-avx512bw,-avx512cd,-avx512dq,-avx512er,-avx512f,-avx512ifma,-avx512pf,-avx512vbmi,-avx512vbmi2,-avx512vl,-avx512vnni,-avx512vpopcntdq,-f16c,-fma,-fma4,-sse4.1,-sse4.2,-vaes,-vpclmulqdq,-xop,-xsave,-xsaveopt"
diff --git a/test/CodeGen/avr-inline-asm-constraints.c b/test/CodeGen/avr-inline-asm-constraints.c
index f1bfbac38978..c659953ca624 100644
--- a/test/CodeGen/avr-inline-asm-constraints.c
+++ b/test/CodeGen/avr-inline-asm-constraints.c
@@ -4,121 +4,121 @@
int data;
void a() {
- // CHECK: call void asm sideeffect "add r5, $0", "a"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "a"(i16 %0)
asm("add r5, %0" :: "a"(data));
}
void b() {
- // CHECK: call void asm sideeffect "add r5, $0", "b"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "b"(i16 %0)
asm("add r5, %0" :: "b"(data));
}
void d() {
- // CHECK: call void asm sideeffect "add r5, $0", "d"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "d"(i16 %0)
asm("add r5, %0" :: "d"(data));
}
void l() {
- // CHECK: call void asm sideeffect "add r5, $0", "l"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "l"(i16 %0)
asm("add r5, %0" :: "l"(data));
}
void e() {
- // CHECK: call void asm sideeffect "add r5, $0", "e"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "e"(i16 %0)
asm("add r5, %0" :: "e"(data));
}
void q() {
- // CHECK: call void asm sideeffect "add r5, $0", "q"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "q"(i16 %0)
asm("add r5, %0" :: "q"(data));
}
void r() {
- // CHECK: call void asm sideeffect "add r5, $0", "r"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "r"(i16 %0)
asm("add r5, %0" :: "r"(data));
}
void w() {
- // CHECK: call void asm sideeffect "add r5, $0", "w"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "w"(i16 %0)
asm("add r5, %0" :: "w"(data));
}
void t() {
- // CHECK: call void asm sideeffect "add r5, $0", "t"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "t"(i16 %0)
asm("add r5, %0" :: "t"(data));
}
void x() {
- // CHECK: call void asm sideeffect "add r5, $0", "x"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "x"(i16 %0)
asm("add r5, %0" :: "x"(data));
}
void y() {
- // CHECK: call void asm sideeffect "add r5, $0", "y"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "y"(i16 %0)
asm("add r5, %0" :: "y"(data));
}
void z() {
- // CHECK: call void asm sideeffect "add r5, $0", "z"(i16 %0)
+ // CHECK: call addrspace(0) void asm sideeffect "add r5, $0", "z"(i16 %0)
asm("add r5, %0" :: "z"(data));
}
void I() {
- // CHECK: call void asm sideeffect "subi r30, $0", "I"(i16 50)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "I"(i16 50)
asm("subi r30, %0" :: "I"(50));
}
void J() {
- // CHECK: call void asm sideeffect "subi r30, $0", "J"(i16 -50)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "J"(i16 -50)
asm("subi r30, %0" :: "J"(-50));
}
void K() {
- // CHECK: call void asm sideeffect "subi r30, $0", "K"(i16 2)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "K"(i16 2)
asm("subi r30, %0" :: "K"(2));
}
void L() {
- // CHECK: call void asm sideeffect "subi r30, $0", "L"(i16 0)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "L"(i16 0)
asm("subi r30, %0" :: "L"(0));
}
void M() {
- // CHECK: call void asm sideeffect "subi r30, $0", "M"(i16 255)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "M"(i16 255)
asm("subi r30, %0" :: "M"(255));
}
void O() {
- // CHECK: call void asm sideeffect "subi r30, $0", "O"(i16 16)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "O"(i16 16)
asm("subi r30, %0" :: "O"(16));
}
void P() {
- // CHECK: call void asm sideeffect "subi r30, $0", "P"(i16 1)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "P"(i16 1)
asm("subi r30, %0" :: "P"(1));
}
void R() {
- // CHECK: call void asm sideeffect "subi r30, $0", "R"(i16 -3)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "R"(i16 -3)
asm("subi r30, %0" :: "R"(-3));
}
void G() {
- // CHECK: call void asm sideeffect "subi r30, $0", "G"(i16 50)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "G"(i16 50)
asm("subi r30, %0" :: "G"(50));
}
void Q() {
- // CHECK: call void asm sideeffect "subi r30, $0", "Q"(i16 50)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "Q"(i16 50)
asm("subi r30, %0" :: "Q"(50));
}
void ra() {
- // CHECK: call void asm sideeffect "subi r30, $0", "ra"(i16 50)
+ // CHECK: call addrspace(0) void asm sideeffect "subi r30, $0", "ra"(i16 50)
asm("subi r30, %0" :: "ra"(50));
}
void ora() {
- // CHECK: call i16 asm "subi r30, $0", "=ra"()
+ // CHECK: call addrspace(0) i16 asm "subi r30, $0", "=ra"()
asm("subi r30, %0" : "=ra"(data));
}
diff --git a/test/CodeGen/avr/attributes/interrupt.c b/test/CodeGen/avr/attributes/interrupt.c
index 31b7ebb4f03d..adea84eb3a37 100644
--- a/test/CodeGen/avr/attributes/interrupt.c
+++ b/test/CodeGen/avr/attributes/interrupt.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm %s -o - | FileCheck %s
-// CHECK: define void @foo() #0
+// CHECK: define void @foo(){{.*}}#0
__attribute__((interrupt)) void foo(void) { }
// CHECK: attributes #0 = {{{.*interrupt.*}}}
diff --git a/test/CodeGen/avr/attributes/signal.c b/test/CodeGen/avr/attributes/signal.c
index 82859000060e..030cdc843fec 100644
--- a/test/CodeGen/avr/attributes/signal.c
+++ b/test/CodeGen/avr/attributes/signal.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm %s -o - | FileCheck %s
-// CHECK: define void @foo() #0
+// CHECK: define void @foo(){{.*}}#0
__attribute__((signal)) void foo(void) { }
// CHECK: attributes #0 = {{{.*signal.*}}}
diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c
index b0f4b5e6b55b..90c07c1d389d 100644
--- a/test/CodeGen/avx2-builtins.c
+++ b/test/CodeGen/avx2-builtins.c
@@ -56,25 +56,27 @@ __m256i test_mm256_add_epi64(__m256i a, __m256i b) {
__m256i test_mm256_adds_epi8(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_adds_epi8
- // CHECK: call <32 x i8> @llvm.x86.avx2.padds.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+ // CHECK: call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
return _mm256_adds_epi8(a, b);
}
__m256i test_mm256_adds_epi16(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_adds_epi16
- // CHECK: call <16 x i16> @llvm.x86.avx2.padds.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_adds_epi16(a, b);
}
__m256i test_mm256_adds_epu8(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_adds_epu8
- // CHECK: call <32 x i8> @llvm.x86.avx2.paddus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+ // CHECK-NOT: call <32 x i8> @llvm.x86.avx2.paddus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+ // CHECK: call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
return _mm256_adds_epu8(a, b);
}
__m256i test_mm256_adds_epu16(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_adds_epu16
- // CHECK: call <16 x i16> @llvm.x86.avx2.paddus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK-NOT: call <16 x i16> @llvm.x86.avx2.paddus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_adds_epu16(a, b);
}
@@ -993,18 +995,36 @@ __m256i test_mm256_slli_epi16(__m256i a) {
return _mm256_slli_epi16(a, 3);
}
+__m256i test_mm256_slli_epi16_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_slli_epi16_2
+ // CHECK: call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm256_slli_epi16(a, b);
+}
+
__m256i test_mm256_slli_epi32(__m256i a) {
// CHECK-LABEL: test_mm256_slli_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %{{.*}}, i32 %{{.*}})
return _mm256_slli_epi32(a, 3);
}
+__m256i test_mm256_slli_epi32_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_slli_epi32_2
+ // CHECK: call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm256_slli_epi32(a, b);
+}
+
__m256i test_mm256_slli_epi64(__m256i a) {
// CHECK-LABEL: test_mm256_slli_epi64
// CHECK: call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %{{.*}}, i32 %{{.*}})
return _mm256_slli_epi64(a, 3);
}
+__m256i test_mm256_slli_epi64_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_slli_epi64_2
+ // CHECK: call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %{{.*}}, i32 %{{.*}})
+ return _mm256_slli_epi64(a, b);
+}
+
__m256i test_mm256_slli_si256(__m256i a) {
// CHECK-LABEL: test_mm256_slli_si256
// CHECK: shufflevector <32 x i8> zeroinitializer, <32 x i8> %{{.*}}, <32 x i32> <i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60>
@@ -1053,12 +1073,24 @@ __m256i test_mm256_srai_epi16(__m256i a) {
return _mm256_srai_epi16(a, 3);
}
+__m256i test_mm256_srai_epi16_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_srai_epi16_2
+ // CHECK: call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm256_srai_epi16(a, b);
+}
+
__m256i test_mm256_srai_epi32(__m256i a) {
// CHECK-LABEL: test_mm256_srai_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %{{.*}}, i32 %{{.*}})
return _mm256_srai_epi32(a, 3);
}
+__m256i test_mm256_srai_epi32_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_srai_epi32_2
+ // CHECK: call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm256_srai_epi32(a, b);
+}
+
__m128i test_mm_srav_epi32(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_srav_epi32
// CHECK: call <4 x i32> @llvm.x86.avx2.psrav.d(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
@@ -1095,18 +1127,36 @@ __m256i test_mm256_srli_epi16(__m256i a) {
return _mm256_srli_epi16(a, 3);
}
+__m256i test_mm256_srli_epi16_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_srli_epi16_2
+ // CHECK: call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm256_srli_epi16(a, b);
+}
+
__m256i test_mm256_srli_epi32(__m256i a) {
// CHECK-LABEL: test_mm256_srli_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %{{.*}}, i32 %{{.*}})
return _mm256_srli_epi32(a, 3);
}
+__m256i test_mm256_srli_epi32_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_srli_epi32_2
+ // CHECK: call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm256_srli_epi32(a, b);
+}
+
__m256i test_mm256_srli_epi64(__m256i a) {
// CHECK-LABEL: test_mm256_srli_epi64
// CHECK: call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %{{.*}}, i32 %{{.*}})
return _mm256_srli_epi64(a, 3);
}
+__m256i test_mm256_srli_epi64_2(__m256i a, int b) {
+ // CHECK-LABEL: test_mm256_srli_epi64_2
+ // CHECK: call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %{{.*}}, i32 %{{.*}})
+ return _mm256_srli_epi64(a, b);
+}
+
__m256i test_mm256_srli_si256(__m256i a) {
// CHECK-LABEL: test_mm256_srli_si256
// CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> zeroinitializer, <32 x i32> <i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50>
@@ -1169,25 +1219,27 @@ __m256i test_mm256_sub_epi64(__m256i a, __m256i b) {
__m256i test_mm256_subs_epi8(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_subs_epi8
- // CHECK: call <32 x i8> @llvm.x86.avx2.psubs.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+ // CHECK: call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
return _mm256_subs_epi8(a, b);
}
__m256i test_mm256_subs_epi16(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_subs_epi16
- // CHECK: call <16 x i16> @llvm.x86.avx2.psubs.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_subs_epi16(a, b);
}
__m256i test_mm256_subs_epu8(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_subs_epu8
- // CHECK: call <32 x i8> @llvm.x86.avx2.psubus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+ // CHECK-NOT: call <32 x i8> @llvm.x86.avx2.psubus.b(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
+ // CHECK: call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
return _mm256_subs_epu8(a, b);
}
__m256i test_mm256_subs_epu16(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_subs_epu16
- // CHECK: call <16 x i16> @llvm.x86.avx2.psubus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK-NOT: call <16 x i16> @llvm.x86.avx2.psubus.w(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_subs_epu16(a, b);
}
diff --git a/test/CodeGen/avx512bitalg-builtins.c b/test/CodeGen/avx512bitalg-builtins.c
index 5770c662f07e..b289c237cfc0 100644
--- a/test/CodeGen/avx512bitalg-builtins.c
+++ b/test/CodeGen/avx512bitalg-builtins.c
@@ -42,13 +42,14 @@ __m512i test_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B) {
__mmask64 test_mm512_mask_bitshuffle_epi64_mask(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_bitshuffle_epi64_mask
- // CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.512
+ // CHECK: @llvm.x86.avx512.vpshufbitqmb.512
+ // CHECK: and <64 x i1> %{{.*}}, %{{.*}}
return _mm512_mask_bitshuffle_epi64_mask(__U, __A, __B);
}
__mmask64 test_mm512_bitshuffle_epi64_mask(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_bitshuffle_epi64_mask
- // CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.512
+ // CHECK: @llvm.x86.avx512.vpshufbitqmb.512
return _mm512_bitshuffle_epi64_mask(__A, __B);
}
diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c
index 7d2e1fadf4ce..9e75baae77f5 100644
--- a/test/CodeGen/avx512bw-builtins.c
+++ b/test/CodeGen/avx512bw-builtins.c
@@ -4,6 +4,404 @@
#include <immintrin.h>
+__mmask32 test_knot_mask32(__mmask32 a) {
+ // CHECK-LABEL: @test_knot_mask32
+ // CHECK: [[IN:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[NOT:%.*]] = xor <32 x i1> [[IN]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: bitcast <32 x i1> [[NOT]] to i32
+ return _knot_mask32(a);
+}
+
+__mmask64 test_knot_mask64(__mmask64 a) {
+ // CHECK-LABEL: @test_knot_mask64
+ // CHECK: [[IN:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[NOT:%.*]] = xor <64 x i1> [[IN]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: bitcast <64 x i1> [[NOT]] to i64
+ return _knot_mask64(a);
+}
+
+__mmask32 test_kand_mask32(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kand_mask32
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = and <32 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kand_mask32(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask64 test_kand_mask64(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kand_mask64
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = and <64 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kand_mask64(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask32 test_kandn_mask32(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kandn_mask32
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[NOT:%.*]] = xor <32 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = and <32 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kandn_mask32(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask64 test_kandn_mask64(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kandn_mask64
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[NOT:%.*]] = xor <64 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = and <64 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kandn_mask64(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask32 test_kor_mask32(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kor_mask32
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = or <32 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kor_mask32(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask64 test_kor_mask64(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kor_mask64
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = or <64 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kor_mask64(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask32 test_kxnor_mask32(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxnor_mask32
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[NOT:%.*]] = xor <32 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = xor <32 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kxnor_mask32(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask64 test_kxnor_mask64(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxnor_mask64
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[NOT:%.*]] = xor <64 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = xor <64 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kxnor_mask64(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask32 test_kxor_mask32(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxor_mask32
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = xor <32 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kxor_mask32(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask64 test_kxor_mask64(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxor_mask64
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = xor <64 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kxor_mask64(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D)),
+ __E, __F);
+}
+
+unsigned char test_kortestz_mask32_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestz_mask32_u8
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[OR:%.*]] = or <32 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <32 x i1> [[OR]] to i32
+ // CHECK: [[CMP:%.*]] = icmp eq i32 [[CAST]], 0
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestz_mask32_u8(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D));
+}
+
+unsigned char test_kortestc_mask32_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestc_mask32_u8
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[OR:%.*]] = or <32 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <32 x i1> [[OR]] to i32
+ // CHECK: [[CMP:%.*]] = icmp eq i32 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestc_mask32_u8(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D));
+}
+
+unsigned char test_kortest_mask32_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_kortest_mask32_u8
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[OR:%.*]] = or <32 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <32 x i1> [[OR]] to i32
+ // CHECK: [[CMP:%.*]] = icmp eq i32 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ // CHECK: [[LHS2:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS2:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[OR2:%.*]] = or <32 x i1> [[LHS2]], [[RHS2]]
+ // CHECK: [[CAST2:%.*]] = bitcast <32 x i1> [[OR2]] to i32
+ // CHECK: [[CMP2:%.*]] = icmp eq i32 [[CAST2]], 0
+ // CHECK: [[ZEXT2:%.*]] = zext i1 [[CMP2]] to i32
+ // CHECK: trunc i32 [[ZEXT2]] to i8
+ return _kortest_mask32_u8(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D), CF);
+}
+
+unsigned char test_kortestz_mask64_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestz_mask64_u8
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[OR:%.*]] = or <64 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <64 x i1> [[OR]] to i64
+ // CHECK: [[CMP:%.*]] = icmp eq i64 [[CAST]], 0
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestz_mask64_u8(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D));
+}
+
+unsigned char test_kortestc_mask64_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestc_mask64_u8
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[OR:%.*]] = or <64 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <64 x i1> [[OR]] to i64
+ // CHECK: [[CMP:%.*]] = icmp eq i64 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestc_mask64_u8(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D));
+}
+
+unsigned char test_kortest_mask64_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_kortest_mask64_u8
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[OR:%.*]] = or <64 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <64 x i1> [[OR]] to i64
+ // CHECK: [[CMP:%.*]] = icmp eq i64 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ // CHECK: [[LHS2:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS2:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[OR2:%.*]] = or <64 x i1> [[LHS2]], [[RHS2]]
+ // CHECK: [[CAST2:%.*]] = bitcast <64 x i1> [[OR2]] to i64
+ // CHECK: [[CMP2:%.*]] = icmp eq i64 [[CAST2]], 0
+ // CHECK: [[ZEXT2:%.*]] = zext i1 [[CMP2]] to i32
+ // CHECK: trunc i32 [[ZEXT2]] to i8
+ return _kortest_mask64_u8(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D), CF);
+}
+
+unsigned char test_ktestz_mask32_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestz_mask32_u8
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.d(<32 x i1> [[LHS]], <32 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestz_mask32_u8(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D));
+}
+
+unsigned char test_ktestc_mask32_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestc_mask32_u8
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.d(<32 x i1> [[LHS]], <32 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestc_mask32_u8(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D));
+}
+
+unsigned char test_ktest_mask32_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_ktest_mask32_u8
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.d(<32 x i1> [[LHS]], <32 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.d(<32 x i1> [[LHS]], <32 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktest_mask32_u8(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D), CF);
+}
+
+unsigned char test_ktestz_mask64_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestz_mask64_u8
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.q(<64 x i1> [[LHS]], <64 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestz_mask64_u8(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D));
+}
+
+unsigned char test_ktestc_mask64_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestc_mask64_u8
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.q(<64 x i1> [[LHS]], <64 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestc_mask64_u8(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D));
+}
+
+unsigned char test_ktest_mask64_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_ktest_mask64_u8
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.q(<64 x i1> [[LHS]], <64 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.q(<64 x i1> [[LHS]], <64 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktest_mask64_u8(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D), CF);
+}
+
+__mmask32 test_kadd_mask32(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kadd_mask32
+ // CHECK: [[LHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = call <32 x i1> @llvm.x86.avx512.kadd.d(<32 x i1> [[LHS]], <32 x i1> [[RHS]])
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kadd_mask32(_mm512_cmpneq_epu16_mask(__A, __B),
+ _mm512_cmpneq_epu16_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask64 test_kadd_mask64(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kadd_mask64
+ // CHECK: [[LHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = call <64 x i1> @llvm.x86.avx512.kadd.q(<64 x i1> [[LHS]], <64 x i1> [[RHS]])
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kadd_mask64(_mm512_cmpneq_epu8_mask(__A, __B),
+ _mm512_cmpneq_epu8_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask32 test_kshiftli_mask32(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftli_mask32
+ // CHECK: [[VAL:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <32 x i1> zeroinitializer, <32 x i1> [[VAL]], <32 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32>
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kshiftli_mask32(_mm512_cmpneq_epu16_mask(A, B), 31), C, D);
+}
+
+__mmask32 test_kshiftri_mask32(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftri_mask32
+ // CHECK: [[VAL:%.*]] = bitcast i32 %{{.*}} to <32 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <32 x i1> [[VAL]], <32 x i1> zeroinitializer, <32 x i32> <i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62>
+ // CHECK: bitcast <32 x i1> [[RES]] to i32
+ return _mm512_mask_cmpneq_epu16_mask(_kshiftri_mask32(_mm512_cmpneq_epu16_mask(A, B), 31), C, D);
+}
+
+__mmask64 test_kshiftli_mask64(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftli_mask64
+ // CHECK: [[VAL:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <64 x i1> zeroinitializer, <64 x i1> [[VAL]], <64 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95>
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kshiftli_mask64(_mm512_cmpneq_epu8_mask(A, B), 32), C, D);
+}
+
+__mmask64 test_kshiftri_mask64(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftri_mask64
+ // CHECK: [[VAL:%.*]] = bitcast i64 %{{.*}} to <64 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <64 x i1> [[VAL]], <64 x i1> zeroinitializer, <64 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95>
+ // CHECK: bitcast <64 x i1> [[RES]] to i64
+ return _mm512_mask_cmpneq_epu8_mask(_kshiftri_mask64(_mm512_cmpneq_epu8_mask(A, B), 32), C, D);
+}
+
+unsigned int test_cvtmask32_u32(__m512i A, __m512i B) {
+ // CHECK-LABEL: @test_cvtmask32_u32
+ // CHECK: bitcast <32 x i1> %{{.*}} to i32
+ // CHECK: bitcast i32 %{{.*}} to <32 x i1>
+ return _cvtmask32_u32(_mm512_cmpneq_epu16_mask(A, B));
+}
+
+unsigned long long test_cvtmask64_u64(__m512i A, __m512i B) {
+ // CHECK-LABEL: @test_cvtmask64_u64
+ // CHECK: bitcast <64 x i1> %{{.*}} to i64
+ // CHECK: bitcast i64 %{{.*}} to <64 x i1>
+ return _cvtmask64_u64(_mm512_cmpneq_epu8_mask(A, B));
+}
+
+__mmask32 test_cvtu32_mask32(__m512i A, __m512i B, unsigned int C) {
+ // CHECK-LABEL: @test_cvtu32_mask32
+ // CHECK: bitcast i32 %{{.*}} to <32 x i1>
+ return _mm512_mask_cmpneq_epu16_mask(_cvtu32_mask32(C), A, B);
+}
+
+__mmask64 test_cvtu64_mask64(__m512i A, __m512i B, unsigned long long C) {
+ // CHECK-LABEL: @test_cvtu64_mask64
+ // CHECK: bitcast i64 %{{.*}} to <64 x i1>
+ return _mm512_mask_cmpneq_epu8_mask(_cvtu64_mask64(C), A, B);
+}
+
+__mmask32 test_load_mask32(__mmask32 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_load_mask32
+ // CHECK: [[LOAD:%.*]] = load i32, i32* %{{.*}}
+ // CHECK: bitcast i32 [[LOAD]] to <32 x i1>
+ return _mm512_mask_cmpneq_epu16_mask(_load_mask32(A), B, C);
+}
+
+__mmask64 test_load_mask64(__mmask64 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_load_mask64
+ // CHECK: [[LOAD:%.*]] = load i64, i64* %{{.*}}
+ // CHECK: bitcast i64 [[LOAD]] to <64 x i1>
+ return _mm512_mask_cmpneq_epu8_mask(_load_mask64(A), B, C);
+}
+
+void test_store_mask32(__mmask32 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_store_mask32
+ // CHECK: bitcast <32 x i1> %{{.*}} to i32
+ // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+ _store_mask32(A, _mm512_cmpneq_epu16_mask(B, C));
+}
+
+void test_store_mask64(__mmask64 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_store_mask64
+ // CHECK: bitcast <64 x i1> %{{.*}} to i64
+ // CHECK: store i64 %{{.*}}, i64* %{{.*}}
+ _store_mask64(A, _mm512_cmpneq_epu8_mask(B, C));
+}
+
__mmask64 test_mm512_cmpeq_epi8_mask(__m512i __a, __m512i __b) {
// CHECK-LABEL: @test_mm512_cmpeq_epi8_mask
// CHECK: icmp eq <64 x i8> %{{.*}}, %{{.*}}
@@ -594,62 +992,76 @@ __m512i test_mm512_maskz_packus_epi16(__mmask64 __M, __m512i __A, __m512i __B) {
}
__m512i test_mm512_adds_epi8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_adds_epi8
- // CHECK: @llvm.x86.avx512.mask.padds.b.512
+ // CHECK: @llvm.sadd.sat.v64i8
return _mm512_adds_epi8(__A,__B);
}
__m512i test_mm512_mask_adds_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_adds_epi8
- // CHECK: @llvm.x86.avx512.mask.padds.b.512
- return _mm512_mask_adds_epi8(__W,__U,__A,__B);
+ // CHECK: @llvm.sadd.sat.v64i8
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
+ return _mm512_mask_adds_epi8(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_adds_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_adds_epi8
- // CHECK: @llvm.x86.avx512.mask.padds.b.512
+ // CHECK: @llvm.sadd.sat.v64i8
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_adds_epi8(__U,__A,__B);
}
__m512i test_mm512_adds_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_adds_epi16
- // CHECK: @llvm.x86.avx512.mask.padds.w.512
- return _mm512_adds_epi16(__A,__B);
+ // CHECK: @llvm.sadd.sat.v32i16
+ return _mm512_adds_epi16(__A,__B);
}
__m512i test_mm512_mask_adds_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_adds_epi16
- // CHECK: @llvm.x86.avx512.mask.padds.w.512
+ // CHECK: @llvm.sadd.sat.v32i16
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_adds_epi16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_adds_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_adds_epi16
- // CHECK: @llvm.x86.avx512.mask.padds.w.512
- return _mm512_maskz_adds_epi16(__U,__A,__B);
+ // CHECK: @llvm.sadd.sat.v32i16
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+return _mm512_maskz_adds_epi16(__U,__A,__B);
}
__m512i test_mm512_adds_epu8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_adds_epu8
- // CHECK: @llvm.x86.avx512.mask.paddus.b.512
+ // CHECK-NOT: @llvm.x86.avx512.mask.paddus.b.512
+ // CHECK: call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{.*}}, <64 x i8> %{{.*}})
return _mm512_adds_epu8(__A,__B);
}
__m512i test_mm512_mask_adds_epu8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_adds_epu8
- // CHECK: @llvm.x86.avx512.mask.paddus.b.512
+ // CHECK-NOT: @llvm.x86.avx512.mask.paddus.b.512
+ // CHECK: call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{.*}}, <64 x i8> %{{.*}})
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_adds_epu8(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_adds_epu8(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_adds_epu8
- // CHECK: @llvm.x86.avx512.mask.paddus.b.512
+ // CHECK-NOT: @llvm.x86.avx512.mask.paddus.b.512
+ // CHECK: call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{.*}}, <64 x i8> %{{.*}})
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_adds_epu8(__U,__A,__B);
}
__m512i test_mm512_adds_epu16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_adds_epu16
- // CHECK: @llvm.x86.avx512.mask.paddus.w.512
+ // CHECK-NOT: @llvm.x86.avx512.mask.paddus.w.512
+ // CHECK: call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
return _mm512_adds_epu16(__A,__B);
}
__m512i test_mm512_mask_adds_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_adds_epu16
- // CHECK: @llvm.x86.avx512.mask.paddus.w.512
+ // CHECK-NOT: @llvm.x86.avx512.mask.paddus.w.512
+ // CHECK: call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_adds_epu16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_adds_epu16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_adds_epu16
- // CHECK: @llvm.x86.avx512.mask.paddus.w.512
+ // CHECK-NOT: @llvm.x86.avx512.mask.paddus.w.512
+ // CHECK: call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_adds_epu16(__U,__A,__B);
}
__m512i test_mm512_avg_epu8(__m512i __A, __m512i __B) {
@@ -903,63 +1315,77 @@ __m512i test_mm512_maskz_shuffle_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
}
__m512i test_mm512_subs_epi8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_subs_epi8
- // CHECK: @llvm.x86.avx512.mask.psubs.b.512
- return _mm512_subs_epi8(__A,__B);
+ // CHECK: @llvm.ssub.sat.v64i8
+return _mm512_subs_epi8(__A,__B);
}
__m512i test_mm512_mask_subs_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_subs_epi8
- // CHECK: @llvm.x86.avx512.mask.psubs.b.512
- return _mm512_mask_subs_epi8(__W,__U,__A,__B);
+ // CHECK: @llvm.ssub.sat.v64i8
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
+return _mm512_mask_subs_epi8(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_subs_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_subs_epi8
- // CHECK: @llvm.x86.avx512.mask.psubs.b.512
- return _mm512_maskz_subs_epi8(__U,__A,__B);
+ // CHECK: @llvm.ssub.sat.v64i8
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
+return _mm512_maskz_subs_epi8(__U,__A,__B);
}
__m512i test_mm512_subs_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_subs_epi16
- // CHECK: @llvm.x86.avx512.mask.psubs.w.512
- return _mm512_subs_epi16(__A,__B);
+ // CHECK: @llvm.ssub.sat.v32i16
+return _mm512_subs_epi16(__A,__B);
}
__m512i test_mm512_mask_subs_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_subs_epi16
- // CHECK: @llvm.x86.avx512.mask.psubs.w.512
- return _mm512_mask_subs_epi16(__W,__U,__A,__B);
+ // CHECK: @llvm.ssub.sat.v32i16
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+return _mm512_mask_subs_epi16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_subs_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_subs_epi16
- // CHECK: @llvm.x86.avx512.mask.psubs.w.512
- return _mm512_maskz_subs_epi16(__U,__A,__B);
+ // CHECK: @llvm.ssub.sat.v32i16
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+return _mm512_maskz_subs_epi16(__U,__A,__B);
}
__m512i test_mm512_subs_epu8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_subs_epu8
- // CHECK: @llvm.x86.avx512.mask.psubus.b.512
- return _mm512_subs_epu8(__A,__B);
+ // CHECK-NOT: @llvm.x86.avx512.mask.psubus.b.512
+ // CHECK: call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{.*}}, <64 x i8> %{{.*}})
+return _mm512_subs_epu8(__A,__B);
}
__m512i test_mm512_mask_subs_epu8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_subs_epu8
- // CHECK: @llvm.x86.avx512.mask.psubus.b.512
- return _mm512_mask_subs_epu8(__W,__U,__A,__B);
+ // CHECK-NOT: @llvm.x86.avx512.mask.psubus.b.512
+ // CHECK: call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{.*}}, <64 x i8> %{{.*}})
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
+return _mm512_mask_subs_epu8(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_subs_epu8(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_subs_epu8
- // CHECK: @llvm.x86.avx512.mask.psubus.b.512
- return _mm512_maskz_subs_epu8(__U,__A,__B);
+ // CHECK-NOT: @llvm.x86.avx512.mask.psubus.b.512
+ // CHECK: call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{.*}}, <64 x i8> %{{.*}})
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
+return _mm512_maskz_subs_epu8(__U,__A,__B);
}
__m512i test_mm512_subs_epu16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_subs_epu16
- // CHECK: @llvm.x86.avx512.mask.psubus.w.512
- return _mm512_subs_epu16(__A,__B);
+ // CHECK-NOT: @llvm.x86.avx512.mask.psubus.w.512
+ // CHECK: call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+return _mm512_subs_epu16(__A,__B);
}
__m512i test_mm512_mask_subs_epu16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_subs_epu16
- // CHECK: @llvm.x86.avx512.mask.psubus.w.512
- return _mm512_mask_subs_epu16(__W,__U,__A,__B);
+ // CHECK-NOT: @llvm.x86.avx512.mask.psubus.w.512
+ // CHECK: call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+return _mm512_mask_subs_epu16(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_subs_epu16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_subs_epu16
- // CHECK: @llvm.x86.avx512.mask.psubus.w.512
- return _mm512_maskz_subs_epu16(__U,__A,__B);
+ // CHECK-NOT: @llvm.x86.avx512.mask.psubus.w.512
+ // CHECK: call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+return _mm512_maskz_subs_epu16(__U,__A,__B);
}
__m512i test_mm512_mask2_permutex2var_epi16(__m512i __A, __m512i __I, __mmask32 __U, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask2_permutex2var_epi16
@@ -1334,6 +1760,12 @@ __m512i test_mm512_slli_epi16(__m512i __A) {
return _mm512_slli_epi16(__A, 5);
}
+__m512i test_mm512_slli_epi16_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_slli_epi16_2
+ // CHECK: @llvm.x86.avx512.pslli.w.512
+ return _mm512_slli_epi16(__A, __B);
+}
+
__m512i test_mm512_mask_slli_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_slli_epi16
// CHECK: @llvm.x86.avx512.pslli.w.512
@@ -1341,6 +1773,13 @@ __m512i test_mm512_mask_slli_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
return _mm512_mask_slli_epi16(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_slli_epi16_2(__m512i __W, __mmask32 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_slli_epi16_2
+ // CHECK: @llvm.x86.avx512.pslli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+ return _mm512_mask_slli_epi16(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_slli_epi16
// CHECK: @llvm.x86.avx512.pslli.w.512
@@ -1348,6 +1787,13 @@ __m512i test_mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A) {
return _mm512_maskz_slli_epi16(__U, __A, 5);
}
+__m512i test_mm512_maskz_slli_epi16_2(__mmask32 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_slli_epi16_2
+ // CHECK: @llvm.x86.avx512.pslli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+ return _mm512_maskz_slli_epi16(__U, __A, __B);
+}
+
__m512i test_mm512_bslli_epi128(__m512i __A) {
// CHECK-LABEL: @test_mm512_bslli_epi128
// CHECK: shufflevector <64 x i8> zeroinitializer, <64 x i8> %{{.*}}, <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
@@ -1420,6 +1866,12 @@ __m512i test_mm512_srai_epi16(__m512i __A) {
return _mm512_srai_epi16(__A, 5);
}
+__m512i test_mm512_srai_epi16_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_srai_epi16_2
+ // CHECK: @llvm.x86.avx512.psrai.w.512
+ return _mm512_srai_epi16(__A, __B);
+}
+
__m512i test_mm512_mask_srai_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srai_epi16
// CHECK: @llvm.x86.avx512.psrai.w.512
@@ -1427,6 +1879,13 @@ __m512i test_mm512_mask_srai_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
return _mm512_mask_srai_epi16(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_srai_epi16_2(__m512i __W, __mmask32 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_srai_epi16_2
+ // CHECK: @llvm.x86.avx512.psrai.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+ return _mm512_mask_srai_epi16(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_srai_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srai_epi16
// CHECK: @llvm.x86.avx512.psrai.w.512
@@ -1434,6 +1893,13 @@ __m512i test_mm512_maskz_srai_epi16(__mmask32 __U, __m512i __A) {
return _mm512_maskz_srai_epi16(__U, __A, 5);
}
+__m512i test_mm512_maskz_srai_epi16_2(__mmask32 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_srai_epi16_2
+ // CHECK: @llvm.x86.avx512.psrai.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+ return _mm512_maskz_srai_epi16(__U, __A, __B);
+}
+
__m512i test_mm512_srl_epi16(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_srl_epi16
// CHECK: @llvm.x86.avx512.psrl.w.512
@@ -1460,6 +1926,12 @@ __m512i test_mm512_srli_epi16(__m512i __A) {
return _mm512_srli_epi16(__A, 5);
}
+__m512i test_mm512_srli_epi16_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_srli_epi16_2
+ // CHECK: @llvm.x86.avx512.psrli.w.512
+ return _mm512_srli_epi16(__A, __B);
+}
+
__m512i test_mm512_mask_srli_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srli_epi16
// CHECK: @llvm.x86.avx512.psrli.w.512
@@ -1467,6 +1939,13 @@ __m512i test_mm512_mask_srli_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
return _mm512_mask_srli_epi16(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_srli_epi16_2(__m512i __W, __mmask32 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_srli_epi16_2
+ // CHECK: @llvm.x86.avx512.psrli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+ return _mm512_mask_srli_epi16(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srli_epi16
// CHECK: @llvm.x86.avx512.psrli.w.512
@@ -1474,6 +1953,13 @@ __m512i test_mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A) {
return _mm512_maskz_srli_epi16(__U, __A, 5);
}
+__m512i test_mm512_maskz_srli_epi16_2(__mmask32 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_srli_epi16_2
+ // CHECK: @llvm.x86.avx512.psrli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
+ return _mm512_maskz_srli_epi16(__U, __A, __B);
+}
+
__m512i test_mm512_bsrli_epi128(__m512i __A) {
// CHECK-LABEL: @test_mm512_bsrli_epi128
// CHECK: shufflevector <64 x i8> %{{.*}}, <64 x i8> zeroinitializer, <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
@@ -1662,6 +2148,13 @@ __mmask32 test_mm512_kunpackw(__m512i __A, __m512i __B, __m512i __C, __m512i __D
return _mm512_mask_cmpneq_epu16_mask(_mm512_kunpackw(_mm512_cmpneq_epu16_mask(__B, __A),_mm512_cmpneq_epu16_mask(__C, __D)), __E, __F);
}
+__m512i test_mm512_loadu_epi16 (void *__P)
+{
+ // CHECK-LABEL: @test_mm512_loadu_epi16
+ // CHECK: load <8 x i64>, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_loadu_epi16 (__P);
+}
+
__m512i test_mm512_mask_loadu_epi16(__m512i __W, __mmask32 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_mask_loadu_epi16
// CHECK: @llvm.masked.load.v32i16.p0v32i16(<32 x i16>* %{{.*}}, i32 1, <32 x i1> %{{.*}}, <32 x i16> %{{.*}})
@@ -1674,6 +2167,13 @@ __m512i test_mm512_maskz_loadu_epi16(__mmask32 __U, void const *__P) {
return _mm512_maskz_loadu_epi16(__U, __P);
}
+__m512i test_mm512_loadu_epi8 (void *__P)
+{
+ // CHECK-LABEL: @test_mm512_loadu_epi8
+ // CHECK: load <8 x i64>, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_loadu_epi8 (__P);
+}
+
__m512i test_mm512_mask_loadu_epi8(__m512i __W, __mmask64 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_mask_loadu_epi8
// CHECK: @llvm.masked.load.v64i8.p0v64i8(<64 x i8>* %{{.*}}, i32 1, <64 x i1> %{{.*}}, <64 x i8> %{{.*}})
@@ -1685,11 +2185,19 @@ __m512i test_mm512_maskz_loadu_epi8(__mmask64 __U, void const *__P) {
// CHECK: @llvm.masked.load.v64i8.p0v64i8(<64 x i8>* %{{.*}}, i32 1, <64 x i1> %{{.*}}, <64 x i8> %{{.*}})
return _mm512_maskz_loadu_epi8(__U, __P);
}
+
+void test_mm512_storeu_epi16(void *__P, __m512i __A) {
+ // CHECK-LABEL: @test_mm512_storeu_epi16
+ // CHECK: store <8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_storeu_epi16(__P, __A);
+}
+
void test_mm512_mask_storeu_epi16(void *__P, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_storeu_epi16
// CHECK: @llvm.masked.store.v32i16.p0v32i16(<32 x i16> %{{.*}}, <32 x i16>* %{{.*}}, i32 1, <32 x i1> %{{.*}})
- return _mm512_mask_storeu_epi16(__P, __U, __A);
+ return _mm512_mask_storeu_epi16(__P, __U, __A);
}
+
__mmask64 test_mm512_test_epi8_mask(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_test_epi8_mask
// CHECK: and <16 x i32> %{{.*}}, %{{.*}}
@@ -1697,6 +2205,12 @@ __mmask64 test_mm512_test_epi8_mask(__m512i __A, __m512i __B) {
return _mm512_test_epi8_mask(__A, __B);
}
+void test_mm512_storeu_epi8(void *__P, __m512i __A) {
+ // CHECK-LABEL: @test_mm512_storeu_epi8
+ // CHECK: store <8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_storeu_epi8(__P, __A);
+}
+
void test_mm512_mask_storeu_epi8(void *__P, __mmask64 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_storeu_epi8
// CHECK: @llvm.masked.store.v64i8.p0v64i8(<64 x i8> %{{.*}}, <64 x i8>* %{{.*}}, i32 1, <64 x i1> %{{.*}})
diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c
index 6ac3aff0aa3c..6227a83b55d4 100644
--- a/test/CodeGen/avx512dq-builtins.c
+++ b/test/CodeGen/avx512dq-builtins.c
@@ -3,6 +3,252 @@
#include <immintrin.h>
+__mmask8 test_knot_mask8(__mmask8 a) {
+ // CHECK-LABEL: @test_knot_mask8
+ // CHECK: [[IN:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[NOT:%.*]] = xor <8 x i1> [[IN]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: bitcast <8 x i1> [[NOT]] to i8
+ return _knot_mask8(a);
+}
+
+__mmask8 test_kand_mask8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kand_mask8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = and <8 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kand_mask8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask8 test_kandn_mask8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kandn_mask8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[NOT:%.*]] = xor <8 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = and <8 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kandn_mask8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask8 test_kor_mask8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kor_mask8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = or <8 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kor_mask8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask8 test_kxnor_mask8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxnor_mask8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[NOT:%.*]] = xor <8 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = xor <8 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kxnor_mask8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask8 test_kxor_mask8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxor_mask8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = xor <8 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kxor_mask8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D)),
+ __E, __F);
+}
+
+unsigned char test_kortestz_mask8_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestz_mask8_u8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[OR:%.*]] = or <8 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <8 x i1> [[OR]] to i8
+ // CHECK: [[CMP:%.*]] = icmp eq i8 [[CAST]], 0
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestz_mask8_u8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D));
+}
+
+unsigned char test_kortestc_mask8_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestc_mask8_u8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[OR:%.*]] = or <8 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <8 x i1> [[OR]] to i8
+ // CHECK: [[CMP:%.*]] = icmp eq i8 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestc_mask8_u8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D));
+}
+
+unsigned char test_kortest_mask8_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_kortest_mask8_u8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[OR:%.*]] = or <8 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <8 x i1> [[OR]] to i8
+ // CHECK: [[CMP:%.*]] = icmp eq i8 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ // CHECK: [[LHS2:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS2:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[OR2:%.*]] = or <8 x i1> [[LHS2]], [[RHS2]]
+ // CHECK: [[CAST2:%.*]] = bitcast <8 x i1> [[OR2]] to i8
+ // CHECK: [[CMP2:%.*]] = icmp eq i8 [[CAST2]], 0
+ // CHECK: [[ZEXT2:%.*]] = zext i1 [[CMP2]] to i32
+ // CHECK: trunc i32 [[ZEXT2]] to i8
+ return _kortest_mask8_u8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D), CF);
+}
+
+unsigned char test_ktestz_mask8_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestz_mask8_u8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.b(<8 x i1> [[LHS]], <8 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestz_mask8_u8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D));
+}
+
+unsigned char test_ktestc_mask8_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestc_mask8_u8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.b(<8 x i1> [[LHS]], <8 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestc_mask8_u8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D));
+}
+
+unsigned char test_ktest_mask8_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_ktest_mask8_u8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.b(<8 x i1> [[LHS]], <8 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.b(<8 x i1> [[LHS]], <8 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktest_mask8_u8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D), CF);
+}
+
+unsigned char test_ktestz_mask16_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestz_mask16_u8
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.w(<16 x i1> [[LHS]], <16 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestz_mask16_u8(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D));
+}
+
+unsigned char test_ktestc_mask16_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_ktestc_mask16_u8
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.w(<16 x i1> [[LHS]], <16 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktestc_mask16_u8(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D));
+}
+
+unsigned char test_ktest_mask16_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_ktest_mask16_u8
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestc.w(<16 x i1> [[LHS]], <16 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = call i32 @llvm.x86.avx512.ktestz.w(<16 x i1> [[LHS]], <16 x i1> [[RHS]])
+ // CHECK: trunc i32 [[RES]] to i8
+ return _ktest_mask16_u8(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D), CF);
+}
+
+__mmask8 test_kadd_mask8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kadd_mask8
+ // CHECK: [[LHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = call <8 x i1> @llvm.x86.avx512.kadd.b(<8 x i1> [[LHS]], <8 x i1> [[RHS]])
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kadd_mask8(_mm512_cmpneq_epu64_mask(__A, __B),
+ _mm512_cmpneq_epu64_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask16 test_kadd_mask16(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kadd_mask16
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = call <16 x i1> @llvm.x86.avx512.kadd.w(<16 x i1> [[LHS]], <16 x i1> [[RHS]])
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kadd_mask16(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask8 test_kshiftli_mask8(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftli_mask8
+ // CHECK: [[VAL:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <8 x i1> zeroinitializer, <8 x i1> [[VAL]], <8 x i32> <i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13>
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kshiftli_mask8(_mm512_cmpneq_epu64_mask(A, B), 2), C, D);
+}
+
+__mmask8 test_kshiftri_mask8(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftri_mask8
+ // CHECK: [[VAL:%.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <8 x i1> [[VAL]], <8 x i1> zeroinitializer, <8 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9>
+ // CHECK: bitcast <8 x i1> [[RES]] to i8
+ return _mm512_mask_cmpneq_epu64_mask(_kshiftri_mask8(_mm512_cmpneq_epu64_mask(A, B), 2), C, D);
+}
+
+unsigned int test_cvtmask8_u32(__m512i A, __m512i B) {
+ // CHECK-LABEL: @test_cvtmask8_u32
+ // CHECK: bitcast <8 x i1> %{{.*}} to i8
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: zext i8 %{{.*}} to i32
+ return _cvtmask8_u32(_mm512_cmpneq_epu64_mask(A, B));
+}
+
+__mmask8 test_cvtu32_mask8(__m512i A, __m512i B, unsigned int C) {
+ // CHECK-LABEL: @test_cvtu32_mask8
+ // CHECK: trunc i32 %{{.*}} to i8
+ // CHECK: bitcast i8 %{{.*}} to <8 x i1>
+ return _mm512_mask_cmpneq_epu64_mask(_cvtu32_mask8(C), A, B);
+}
+
+__mmask8 test_load_mask8(__mmask8 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_load_mask8
+ // CHECK: [[LOAD:%.*]] = load i8, i8* %{{.*}}
+ // CHECK: bitcast i8 [[LOAD]] to <8 x i1>
+ return _mm512_mask_cmpneq_epu64_mask(_load_mask8(A), B, C);
+}
+
+void test_store_mask8(__mmask8 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_store_mask8
+ // CHECK: bitcast <8 x i1> %{{.*}} to i8
+ // CHECK: store i8 %{{.*}}, i8* %{{.*}}
+ _store_mask8(A, _mm512_cmpneq_epu64_mask(B, C));
+}
+
__m512i test_mm512_mullo_epi64 (__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mullo_epi64
// CHECK: mul <8 x i64>
diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c
index 17cbc62d6149..5154e820bd72 100644
--- a/test/CodeGen/avx512f-builtins.c
+++ b/test/CodeGen/avx512f-builtins.c
@@ -254,12 +254,24 @@ void test_mm512_mask_store_pd(void *p, __m512d a, __mmask8 m)
_mm512_mask_store_pd(p, m, a);
}
+void test_mm512_storeu_epi32(void *__P, __m512i __A) {
+ // CHECK-LABEL: @test_mm512_storeu_epi32
+ // CHECK: store <8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_storeu_epi32(__P, __A);
+}
+
void test_mm512_mask_storeu_epi32(void *__P, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_storeu_epi32
// CHECK: @llvm.masked.store.v16i32.p0v16i32(<16 x i32> %{{.*}}, <16 x i32>* %{{.*}}, i32 1, <16 x i1> %{{.*}})
return _mm512_mask_storeu_epi32(__P, __U, __A);
}
+void test_mm512_storeu_epi64(void *__P, __m512i __A) {
+ // CHECK-LABEL: @test_mm512_storeu_epi64
+ // CHECK: store <8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_storeu_epi64(__P, __A);
+}
+
void test_mm512_mask_storeu_epi64(void *__P, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_storeu_epi64
// CHECK: @llvm.masked.store.v8i64.p0v8i64(<8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, i32 1, <8 x i1> %{{.*}})
@@ -273,6 +285,13 @@ __m512i test_mm512_loadu_si512 (void *__P)
return _mm512_loadu_si512 ( __P);
}
+__m512i test_mm512_loadu_epi32 (void *__P)
+{
+ // CHECK-LABEL: @test_mm512_loadu_epi32
+ // CHECK: load <8 x i64>, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_loadu_epi32 (__P);
+}
+
__m512i test_mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void *__P)
{
// CHECK-LABEL: @test_mm512_mask_loadu_epi32
@@ -280,6 +299,20 @@ __m512i test_mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void *__P)
return _mm512_mask_loadu_epi32 (__W,__U, __P);
}
+__m512i test_mm512_maskz_loadu_epi32 (__mmask16 __U, void *__P)
+{
+ // CHECK-LABEL: @test_mm512_maskz_loadu_epi32
+ // CHECK: @llvm.masked.load.v16i32.p0v16i32(<16 x i32>* %{{.*}}, i32 1, <16 x i1> %{{.*}}, <16 x i32> %{{.*}})
+ return _mm512_maskz_loadu_epi32 (__U, __P);
+}
+
+__m512i test_mm512_loadu_epi64 (void *__P)
+{
+ // CHECK-LABEL: @test_mm512_loadu_epi64
+ // CHECK: load <8 x i64>, <8 x i64>* %{{.*}}, align 1{{$}}
+ return _mm512_loadu_epi64 (__P);
+}
+
__m512i test_mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void *__P)
{
// CHECK-LABEL: @test_mm512_mask_loadu_epi64
@@ -287,6 +320,13 @@ __m512i test_mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void *__P)
return _mm512_mask_loadu_epi64 (__W,__U, __P);
}
+__m512i test_mm512_maskz_loadu_epi64 (__mmask16 __U, void *__P)
+{
+ // CHECK-LABEL: @test_mm512_maskz_loadu_epi64
+ // CHECK: @llvm.masked.load.v8i64.p0v8i64(<8 x i64>* %{{.*}}, i32 1, <8 x i1> %{{.*}}, <8 x i64> %{{.*}})
+ return _mm512_maskz_loadu_epi64 (__U, __P);
+}
+
__m512 test_mm512_loadu_ps(void *p)
{
// CHECK-LABEL: @test_mm512_loadu_ps
@@ -3996,120 +4036,120 @@ __m512i test_mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
__m512i test_mm512_rol_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.512
+ // CHECK: @llvm.fshl.v16i32
return _mm512_rol_epi32(__A, 5);
}
__m512i test_mm512_mask_rol_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.512
+ // CHECK: @llvm.fshl.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_rol_epi32(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_rol_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.512
+ // CHECK: @llvm.fshl.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_rol_epi32(__U, __A, 5);
}
__m512i test_mm512_rol_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.512
+ // CHECK: @llvm.fshl.v8i64
return _mm512_rol_epi64(__A, 5);
}
__m512i test_mm512_mask_rol_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.512
+ // CHECK: @llvm.fshl.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_rol_epi64(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_rol_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.512
+ // CHECK: @llvm.fshl.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_rol_epi64(__U, __A, 5);
}
__m512i test_mm512_rolv_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.512
+ // CHECK: @llvm.fshl.v16i32
return _mm512_rolv_epi32(__A, __B);
}
__m512i test_mm512_mask_rolv_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.512
+ // CHECK: @llvm.fshl.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_rolv_epi32(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rolv_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.512
+ // CHECK: @llvm.fshl.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_rolv_epi32(__U, __A, __B);
}
__m512i test_mm512_rolv_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.512
+ // CHECK: @llvm.fshl.v8i64
return _mm512_rolv_epi64(__A, __B);
}
__m512i test_mm512_mask_rolv_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.512
+ // CHECK: @llvm.fshl.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_rolv_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rolv_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.512
+ // CHECK: @llvm.fshl.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_rolv_epi64(__U, __A, __B);
}
__m512i test_mm512_ror_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.512
+ // CHECK: @llvm.fshr.v16i32
return _mm512_ror_epi32(__A, 5);
}
__m512i test_mm512_mask_ror_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.512
+ // CHECK: @llvm.fshr.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_ror_epi32(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_ror_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.512
+ // CHECK: @llvm.fshr.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_ror_epi32(__U, __A, 5);
}
__m512i test_mm512_ror_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.512
+ // CHECK: @llvm.fshr.v8i64
return _mm512_ror_epi64(__A, 5);
}
__m512i test_mm512_mask_ror_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.512
+ // CHECK: @llvm.fshr.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_ror_epi64(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_ror_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.512
+ // CHECK: @llvm.fshr.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_ror_epi64(__U, __A, 5);
}
@@ -4117,40 +4157,40 @@ __m512i test_mm512_maskz_ror_epi64(__mmask8 __U, __m512i __A) {
__m512i test_mm512_rorv_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.512
+ // CHECK: @llvm.fshr.v16i32
return _mm512_rorv_epi32(__A, __B);
}
__m512i test_mm512_mask_rorv_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.512
+ // CHECK: @llvm.fshr.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_rorv_epi32(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rorv_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.512
+ // CHECK: @llvm.fshr.v16i32
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_rorv_epi32(__U, __A, __B);
}
__m512i test_mm512_rorv_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.512
+ // CHECK: @llvm.fshr.v8i64
return _mm512_rorv_epi64(__A, __B);
}
__m512i test_mm512_mask_rorv_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.512
+ // CHECK: @llvm.fshr.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_rorv_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_rorv_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.512
+ // CHECK: @llvm.fshr.v8i64
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_rorv_epi64(__U, __A, __B);
}
@@ -4161,6 +4201,12 @@ __m512i test_mm512_slli_epi32(__m512i __A) {
return _mm512_slli_epi32(__A, 5);
}
+__m512i test_mm512_slli_epi32_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_slli_epi32_2
+ // CHECK: @llvm.x86.avx512.pslli.d.512
+ return _mm512_slli_epi32(__A, __B);
+}
+
__m512i test_mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_slli_epi32
// CHECK: @llvm.x86.avx512.pslli.d.512
@@ -4168,6 +4214,13 @@ __m512i test_mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
return _mm512_mask_slli_epi32(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_slli_epi32_2(__m512i __W, __mmask16 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_slli_epi32_2
+ // CHECK: @llvm.x86.avx512.pslli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+ return _mm512_mask_slli_epi32(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_slli_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_slli_epi32
// CHECK: @llvm.x86.avx512.pslli.d.512
@@ -4175,12 +4228,25 @@ __m512i test_mm512_maskz_slli_epi32(__mmask16 __U, __m512i __A) {
return _mm512_maskz_slli_epi32(__U, __A, 5);
}
+__m512i test_mm512_maskz_slli_epi32_2(__mmask16 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_slli_epi32_2
+ // CHECK: @llvm.x86.avx512.pslli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+ return _mm512_maskz_slli_epi32(__U, __A, __B);
+}
+
__m512i test_mm512_slli_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_slli_epi64
// CHECK: @llvm.x86.avx512.pslli.q.512
return _mm512_slli_epi64(__A, 5);
}
+__m512i test_mm512_slli_epi64_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_slli_epi64_2
+ // CHECK: @llvm.x86.avx512.pslli.q.512
+ return _mm512_slli_epi64(__A, __B);
+}
+
__m512i test_mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_slli_epi64
// CHECK: @llvm.x86.avx512.pslli.q.512
@@ -4188,18 +4254,39 @@ __m512i test_mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
return _mm512_mask_slli_epi64(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_slli_epi64_2(__m512i __W, __mmask8 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_slli_epi64_2
+ // CHECK: @llvm.x86.avx512.pslli.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+ return _mm512_mask_slli_epi64(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_slli_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_slli_epi64
+ // CHECK: @llvm.x86.avx512.pslli.q.512
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_slli_epi64(__U, __A, 5);
}
+__m512i test_mm512_maskz_slli_epi64_2(__mmask8 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_slli_epi64_2
+ // CHECK: @llvm.x86.avx512.pslli.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+ return _mm512_maskz_slli_epi64(__U, __A, __B);
+}
+
__m512i test_mm512_srli_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_srli_epi32
// CHECK: @llvm.x86.avx512.psrli.d.512
return _mm512_srli_epi32(__A, 5);
}
+__m512i test_mm512_srli_epi32_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_srli_epi32_2
+ // CHECK: @llvm.x86.avx512.psrli.d.512
+ return _mm512_srli_epi32(__A, __B);
+}
+
__m512i test_mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srli_epi32
// CHECK: @llvm.x86.avx512.psrli.d.512
@@ -4207,6 +4294,13 @@ __m512i test_mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
return _mm512_mask_srli_epi32(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_srli_epi32_2(__m512i __W, __mmask16 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_srli_epi32_2
+ // CHECK: @llvm.x86.avx512.psrli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+ return _mm512_mask_srli_epi32(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_srli_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srli_epi32
// CHECK: @llvm.x86.avx512.psrli.d.512
@@ -4214,12 +4308,25 @@ __m512i test_mm512_maskz_srli_epi32(__mmask16 __U, __m512i __A) {
return _mm512_maskz_srli_epi32(__U, __A, 5);
}
+__m512i test_mm512_maskz_srli_epi32_2(__mmask16 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_srli_epi32_2
+ // CHECK: @llvm.x86.avx512.psrli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+ return _mm512_maskz_srli_epi32(__U, __A, __B);
+}
+
__m512i test_mm512_srli_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_srli_epi64
// CHECK: @llvm.x86.avx512.psrli.q.512
return _mm512_srli_epi64(__A, 5);
}
+__m512i test_mm512_srli_epi64_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_srli_epi64_2
+ // CHECK: @llvm.x86.avx512.psrli.q.512
+ return _mm512_srli_epi64(__A, __B);
+}
+
__m512i test_mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srli_epi64
// CHECK: @llvm.x86.avx512.psrli.q.512
@@ -4227,6 +4334,13 @@ __m512i test_mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
return _mm512_mask_srli_epi64(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_srli_epi64_2(__m512i __W, __mmask8 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_srli_epi64_2
+ // CHECK: @llvm.x86.avx512.psrli.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+ return _mm512_mask_srli_epi64(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srli_epi64
// CHECK: @llvm.x86.avx512.psrli.q.512
@@ -4234,6 +4348,13 @@ __m512i test_mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A) {
return _mm512_maskz_srli_epi64(__U, __A, 5);
}
+__m512i test_mm512_maskz_srli_epi64_2(__mmask8 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_srli_epi64_2
+ // CHECK: @llvm.x86.avx512.psrli.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+ return _mm512_maskz_srli_epi64(__U, __A, __B);
+}
+
__m512i test_mm512_mask_load_epi32(__m512i __W, __mmask16 __U, void const *__P) {
// CHECK-LABEL: @test_mm512_mask_load_epi32
// CHECK: @llvm.masked.load.v16i32.p0v16i32(<16 x i32>* %{{.*}}, i32 64, <16 x i1> %{{.*}}, <16 x i32> %{{.*}})
@@ -5535,6 +5656,12 @@ __m512i test_mm512_srai_epi32(__m512i __A) {
return _mm512_srai_epi32(__A, 5);
}
+__m512i test_mm512_srai_epi32_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_srai_epi32_2
+ // CHECK: @llvm.x86.avx512.psrai.d.512
+ return _mm512_srai_epi32(__A, __B);
+}
+
__m512i test_mm512_mask_srai_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srai_epi32
// CHECK: @llvm.x86.avx512.psrai.d.512
@@ -5542,6 +5669,13 @@ __m512i test_mm512_mask_srai_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
return _mm512_mask_srai_epi32(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_srai_epi32_2(__m512i __W, __mmask16 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_srai_epi32_2
+ // CHECK: @llvm.x86.avx512.psrai.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+ return _mm512_mask_srai_epi32(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_srai_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srai_epi32
// CHECK: @llvm.x86.avx512.psrai.d.512
@@ -5549,12 +5683,25 @@ __m512i test_mm512_maskz_srai_epi32(__mmask16 __U, __m512i __A) {
return _mm512_maskz_srai_epi32(__U, __A, 5);
}
+__m512i test_mm512_maskz_srai_epi32_2(__mmask16 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_srai_epi32_2
+ // CHECK: @llvm.x86.avx512.psrai.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
+ return _mm512_maskz_srai_epi32(__U, __A, __B);
+}
+
__m512i test_mm512_srai_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.512
return _mm512_srai_epi64(__A, 5);
}
+__m512i test_mm512_srai_epi64_2(__m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.512
+ return _mm512_srai_epi64(__A, __B);
+}
+
__m512i test_mm512_mask_srai_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.512
@@ -5562,6 +5709,13 @@ __m512i test_mm512_mask_srai_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
return _mm512_mask_srai_epi64(__W, __U, __A, 5);
}
+__m512i test_mm512_mask_srai_epi64_2(__m512i __W, __mmask8 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_mask_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+ return _mm512_mask_srai_epi64(__W, __U, __A, __B);
+}
+
__m512i test_mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.512
@@ -5569,6 +5723,13 @@ __m512i test_mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A) {
return _mm512_maskz_srai_epi64(__U, __A, 5);
}
+__m512i test_mm512_maskz_srai_epi64_2(__mmask8 __U, __m512i __A, int __B) {
+ // CHECK-LABEL: @test_mm512_maskz_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
+ return _mm512_maskz_srai_epi64(__U, __A, __B);
+}
+
__m512i test_mm512_sll_epi32(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_sll_epi32
// CHECK: @llvm.x86.avx512.psll.d.512
@@ -8149,6 +8310,52 @@ int test_mm512_kortestz(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
_mm512_cmpneq_epu32_mask(__C, __D));
}
+unsigned char test_kortestz_mask16_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestz_mask16_u8
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[OR:%.*]] = or <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <16 x i1> [[OR]] to i16
+ // CHECK: [[CMP:%.*]] = icmp eq i16 [[CAST]], 0
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestz_mask16_u8(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D));
+}
+
+unsigned char test_kortestc_mask16_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D) {
+ // CHECK-LABEL: @test_kortestc_mask16_u8
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[OR:%.*]] = or <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <16 x i1> [[OR]] to i16
+ // CHECK: [[CMP:%.*]] = icmp eq i16 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ return _kortestc_mask16_u8(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D));
+}
+
+unsigned char test_kortest_mask16_u8(__m512i __A, __m512i __B, __m512i __C, __m512i __D, unsigned char *CF) {
+ // CHECK-LABEL: @test_kortest_mask16_u8
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[OR:%.*]] = or <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: [[CAST:%.*]] = bitcast <16 x i1> [[OR]] to i16
+ // CHECK: [[CMP:%.*]] = icmp eq i16 [[CAST]], -1
+ // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
+ // CHECK: trunc i32 [[ZEXT]] to i8
+ // CHECK: [[LHS2:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS2:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[OR2:%.*]] = or <16 x i1> [[LHS2]], [[RHS2]]
+ // CHECK: [[CAST2:%.*]] = bitcast <16 x i1> [[OR2]] to i16
+ // CHECK: [[CMP2:%.*]] = icmp eq i16 [[CAST2]], 0
+ // CHECK: [[ZEXT2:%.*]] = zext i1 [[CMP2]] to i32
+ // CHECK: trunc i32 [[ZEXT2]] to i8
+ return _kortest_mask16_u8(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D), CF);
+}
+
__mmask16 test_mm512_kunpackb(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
// CHECK-LABEL: @test_mm512_kunpackb
// CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
@@ -8185,6 +8392,116 @@ __mmask16 test_mm512_kxor(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __
__E, __F);
}
+__mmask16 test_knot_mask16(__mmask16 a) {
+ // CHECK-LABEL: @test_knot_mask16
+ // CHECK: [[IN:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[NOT:%.*]] = xor <16 x i1> [[IN]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: bitcast <16 x i1> [[NOT]] to i16
+ return _knot_mask16(a);
+}
+
+__mmask16 test_kand_mask16(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kand_mask16
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = and <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kand_mask16(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask16 test_kandn_mask16(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kandn_mask16
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[NOT:%.*]] = xor <16 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = and <16 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kandn_mask16(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask16 test_kor_mask16(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kor_mask16
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = or <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kor_mask16(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask16 test_kxnor_mask16(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxnor_mask16
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[NOT:%.*]] = xor <16 x i1> [[LHS]], <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>
+ // CHECK: [[RES:%.*]] = xor <16 x i1> [[NOT]], [[RHS]]
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kxnor_mask16(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask16 test_kxor_mask16(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
+ // CHECK-LABEL: @test_kxor_mask16
+ // CHECK: [[LHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RHS:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = xor <16 x i1> [[LHS]], [[RHS]]
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kxor_mask16(_mm512_cmpneq_epu32_mask(__A, __B),
+ _mm512_cmpneq_epu32_mask(__C, __D)),
+ __E, __F);
+}
+
+__mmask16 test_kshiftli_mask16(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftli_mask16
+ // CHECK: [[VAL:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <16 x i1> zeroinitializer, <16 x i1> [[VAL]], <16 x i32> <i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30>
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kshiftli_mask16(_mm512_cmpneq_epu32_mask(A, B), 1), C, D);
+}
+
+__mmask16 test_kshiftri_mask16(__m512i A, __m512i B, __m512i C, __m512i D) {
+ // CHECK-LABEL: @test_kshiftri_mask16
+ // CHECK: [[VAL:%.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: [[RES:%.*]] = shufflevector <16 x i1> [[VAL]], <16 x i1> zeroinitializer, <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>
+ // CHECK: bitcast <16 x i1> [[RES]] to i16
+ return _mm512_mask_cmpneq_epu32_mask(_kshiftri_mask16(_mm512_cmpneq_epu32_mask(A, B), 1), C, D);
+}
+
+unsigned int test_cvtmask16_u32(__m512i A, __m512i B) {
+ // CHECK-LABEL: @test_cvtmask16_u32
+ // CHECK: bitcast <16 x i1> %{{.*}} to i16
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: zext i16 %{{.*}} to i32
+ return _cvtmask16_u32(_mm512_cmpneq_epu32_mask(A, B));
+}
+
+__mmask16 test_cvtu32_mask16(__m512i A, __m512i B, unsigned int C) {
+ // CHECK-LABEL: @test_cvtu32_mask16
+ // CHECK: trunc i32 %{{.*}} to i16
+ // CHECK: bitcast i16 %{{.*}} to <16 x i1>
+ return _mm512_mask_cmpneq_epu32_mask(_cvtu32_mask16(C), A, B);
+}
+
+__mmask16 test_load_mask16(__mmask16 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_load_mask16
+ // CHECK: [[LOAD:%.*]] = load i16, i16* %{{.*}}
+ // CHECK: bitcast i16 [[LOAD]] to <16 x i1>
+ return _mm512_mask_cmpneq_epu32_mask(_load_mask16(A), B, C);
+}
+
+void test_store_mask16(__mmask16 *A, __m512i B, __m512i C) {
+ // CHECK-LABEL: @test_store_mask16
+ // CHECK: bitcast <16 x i1> %{{.*}} to i16
+ // CHECK: store i16 %{{.*}}, i16* %{{.*}}
+ _store_mask16(A, _mm512_cmpneq_epu32_mask(B, C));
+}
+
void test_mm512_stream_si512(__m512i * __P, __m512i __A) {
// CHECK-LABEL: @test_mm512_stream_si512
// CHECK: store <8 x i64> %{{.*}}, <8 x i64>* %{{.*}}, align 64, !nontemporal
diff --git a/test/CodeGen/avx512vbmi-builtins.c b/test/CodeGen/avx512vbmi-builtins.c
index 0347916af09f..80d9a9476a62 100644
--- a/test/CodeGen/avx512vbmi-builtins.c
+++ b/test/CodeGen/avx512vbmi-builtins.c
@@ -52,18 +52,20 @@ __m512i test_mm512_mask_permutexvar_epi8(__m512i __W, __mmask64 __M, __m512i __A
__m512i test_mm512_mask_multishift_epi64_epi8(__m512i __W, __mmask64 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.512
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_multishift_epi64_epi8(__W, __M, __X, __Y);
}
__m512i test_mm512_maskz_multishift_epi64_epi8(__mmask64 __M, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.512
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_multishift_epi64_epi8(__M, __X, __Y);
}
__m512i test_mm512_multishift_epi64_epi8(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.512
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.512
return _mm512_multishift_epi64_epi8(__X, __Y);
}
diff --git a/test/CodeGen/avx512vbmi2-builtins.c b/test/CodeGen/avx512vbmi2-builtins.c
index db4abdba457f..304561d9fa8a 100644
--- a/test/CodeGen/avx512vbmi2-builtins.c
+++ b/test/CodeGen/avx512vbmi2-builtins.c
@@ -88,229 +88,241 @@ __m512i test_mm512_maskz_expandloadu_epi8(__mmask64 __U, void const* __P) {
__m512i test_mm512_mask_shldi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.512
+ // CHECK: @llvm.fshl.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> <i64 47, i64 47, i64 47, i64 47, i64 47, i64 47, i64 47, i64 47>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
- return _mm512_mask_shldi_epi64(__S, __U, __A, __B, 127);
+ return _mm512_mask_shldi_epi64(__S, __U, __A, __B, 47);
}
__m512i test_mm512_maskz_shldi_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.512
+ // CHECK: @llvm.fshl.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> <i64 63, i64 63, i64 63, i64 63, i64 63, i64 63, i64 63, i64 63>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_shldi_epi64(__U, __A, __B, 63);
}
__m512i test_mm512_shldi_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.512
+ // CHECK: @llvm.fshl.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> <i64 31, i64 31, i64 31, i64 31, i64 31, i64 31, i64 31, i64 31>)
return _mm512_shldi_epi64(__A, __B, 31);
}
__m512i test_mm512_mask_shldi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.512
+ // CHECK: @llvm.fshl.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
- return _mm512_mask_shldi_epi32(__S, __U, __A, __B, 127);
+ return _mm512_mask_shldi_epi32(__S, __U, __A, __B, 7);
}
__m512i test_mm512_maskz_shldi_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.512
+ // CHECK: @llvm.fshl.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
- return _mm512_maskz_shldi_epi32(__U, __A, __B, 63);
+ return _mm512_maskz_shldi_epi32(__U, __A, __B, 15);
}
__m512i test_mm512_shldi_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.512
+ // CHECK: @llvm.fshl.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31>)
return _mm512_shldi_epi32(__A, __B, 31);
}
__m512i test_mm512_mask_shldi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.512
+ // CHECK: @llvm.fshl.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>)
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
- return _mm512_mask_shldi_epi16(__S, __U, __A, __B, 127);
+ return _mm512_mask_shldi_epi16(__S, __U, __A, __B, 3);
}
__m512i test_mm512_maskz_shldi_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.512
+ // CHECK: @llvm.fshl.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> <i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7>)
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
- return _mm512_maskz_shldi_epi16(__U, __A, __B, 63);
+ return _mm512_maskz_shldi_epi16(__U, __A, __B, 7);
}
__m512i test_mm512_shldi_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.512
- return _mm512_shldi_epi16(__A, __B, 31);
+ // CHECK: @llvm.fshl.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>)
+ return _mm512_shldi_epi16(__A, __B, 15);
}
__m512i test_mm512_mask_shrdi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.512
+ // CHECK: @llvm.fshr.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> <i64 47, i64 47, i64 47, i64 47, i64 47, i64 47, i64 47, i64 47>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
- return _mm512_mask_shrdi_epi64(__S, __U, __A, __B, 127);
+ return _mm512_mask_shrdi_epi64(__S, __U, __A, __B, 47);
}
__m512i test_mm512_maskz_shrdi_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.512
+ // CHECK: @llvm.fshr.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> <i64 63, i64 63, i64 63, i64 63, i64 63, i64 63, i64 63, i64 63>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_shrdi_epi64(__U, __A, __B, 63);
}
__m512i test_mm512_shrdi_epi64(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.512
+ // CHECK: @llvm.fshr.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> <i64 31, i64 31, i64 31, i64 31, i64 31, i64 31, i64 31, i64 31>)
return _mm512_shrdi_epi64(__A, __B, 31);
}
__m512i test_mm512_mask_shrdi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.512
+ // CHECK: @llvm.fshr.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
- return _mm512_mask_shrdi_epi32(__S, __U, __A, __B, 127);
+ return _mm512_mask_shrdi_epi32(__S, __U, __A, __B, 7);
}
__m512i test_mm512_maskz_shrdi_epi32(__mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.512
+ // CHECK: @llvm.fshr.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
- return _mm512_maskz_shrdi_epi32(__U, __A, __B, 63);
+ return _mm512_maskz_shrdi_epi32(__U, __A, __B, 15);
}
__m512i test_mm512_shrdi_epi32(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.512
+ // CHECK: @llvm.fshr.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31>)
return _mm512_shrdi_epi32(__A, __B, 31);
}
__m512i test_mm512_mask_shrdi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.512
+ // CHECK: @llvm.fshr.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>)
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
- return _mm512_mask_shrdi_epi16(__S, __U, __A, __B, 127);
+ return _mm512_mask_shrdi_epi16(__S, __U, __A, __B, 3);
}
__m512i test_mm512_maskz_shrdi_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.512
+ // CHECK: @llvm.fshr.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>)
// CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
- return _mm512_maskz_shrdi_epi16(__U, __A, __B, 63);
+ return _mm512_maskz_shrdi_epi16(__U, __A, __B, 15);
}
__m512i test_mm512_shrdi_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.512
+ // CHECK: @llvm.fshr.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> <i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31>)
return _mm512_shrdi_epi16(__A, __B, 31);
}
__m512i test_mm512_mask_shldv_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshldv.q.512
+ // CHECK: @llvm.fshl.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_shldv_epi64(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_shldv_epi64(__mmask8 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldv_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.q.512
+ // CHECK: @llvm.fshl.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_shldv_epi64(__U, __S, __A, __B);
}
__m512i test_mm512_shldv_epi64(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshldv.q.512
+ // CHECK: @llvm.fshl.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}})
return _mm512_shldv_epi64(__S, __A, __B);
}
__m512i test_mm512_mask_shldv_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshldv.d.512
+ // CHECK: @llvm.fshl.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_shldv_epi32(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_shldv_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldv_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.d.512
+ // CHECK: @llvm.fshl.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_shldv_epi32(__U, __S, __A, __B);
}
__m512i test_mm512_shldv_epi32(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshldv.d.512
+ // CHECK: @llvm.fshl.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}})
return _mm512_shldv_epi32(__S, __A, __B);
}
__m512i test_mm512_mask_shldv_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shldv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshldv.w.512
+ // CHECK: @llvm.fshl.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_shldv_epi16(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_shldv_epi16(__mmask32 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shldv_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.w.512
+ // CHECK: @llvm.fshl.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_shldv_epi16(__U, __S, __A, __B);
}
__m512i test_mm512_shldv_epi16(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shldv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshldv.w.512
+ // CHECK: @llvm.fshl.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}})
return _mm512_shldv_epi16(__S, __A, __B);
}
__m512i test_mm512_mask_shrdv_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.q.512
+ // CHECK: @llvm.fshr.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_shrdv_epi64(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_shrdv_epi64(__mmask8 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdv_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.q.512
+ // CHECK: @llvm.fshr.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_shrdv_epi64(__U, __S, __A, __B);
}
__m512i test_mm512_shrdv_epi64(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.q.512
+ // CHECK: @llvm.fshr.v8i64(<8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}})
return _mm512_shrdv_epi64(__S, __A, __B);
}
__m512i test_mm512_mask_shrdv_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.d.512
+ // CHECK: @llvm.fshr.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_shrdv_epi32(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_shrdv_epi32(__mmask16 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdv_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.d.512
+ // CHECK: @llvm.fshr.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_shrdv_epi32(__U, __S, __A, __B);
}
__m512i test_mm512_shrdv_epi32(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.d.512
+ // CHECK: @llvm.fshr.v16i32(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}})
return _mm512_shrdv_epi32(__S, __A, __B);
}
__m512i test_mm512_mask_shrdv_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shrdv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.w.512
+ // CHECK: @llvm.fshr.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_shrdv_epi16(__S, __U, __A, __B);
}
__m512i test_mm512_maskz_shrdv_epi16(__mmask32 __U, __m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shrdv_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.w.512
+ // CHECK: @llvm.fshr.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_shrdv_epi16(__U, __S, __A, __B);
}
__m512i test_mm512_shrdv_epi16(__m512i __S, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shrdv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.w.512
+ // CHECK: @llvm.fshr.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}})
return _mm512_shrdv_epi16(__S, __A, __B);
}
diff --git a/test/CodeGen/avx512vbmivl-builtin.c b/test/CodeGen/avx512vbmivl-builtin.c
index da8986f2e7d8..0bf9165f6c6a 100644
--- a/test/CodeGen/avx512vbmivl-builtin.c
+++ b/test/CodeGen/avx512vbmivl-builtin.c
@@ -99,37 +99,41 @@ __m256i test_mm256_maskz_permutex2var_epi8(__mmask32 __U, __m256i __A, __m256i _
__m128i test_mm_mask_multishift_epi64_epi8(__m128i __W, __mmask16 __M, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.128
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.128
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_multishift_epi64_epi8(__W, __M, __X, __Y);
}
__m128i test_mm_maskz_multishift_epi64_epi8(__mmask16 __M, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.128
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.128
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_multishift_epi64_epi8(__M, __X, __Y);
}
__m128i test_mm_multishift_epi64_epi8(__m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.128
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.128
return _mm_multishift_epi64_epi8(__X, __Y);
}
__m256i test_mm256_mask_multishift_epi64_epi8(__m256i __W, __mmask32 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.256
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.256
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_multishift_epi64_epi8(__W, __M, __X, __Y);
}
__m256i test_mm256_maskz_multishift_epi64_epi8(__mmask32 __M, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.256
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.256
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_multishift_epi64_epi8(__M, __X, __Y);
}
__m256i test_mm256_multishift_epi64_epi8(__m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_multishift_epi64_epi8
- // CHECK: @llvm.x86.avx512.mask.pmultishift.qb.256
+ // CHECK: @llvm.x86.avx512.pmultishift.qb.256
return _mm256_multishift_epi64_epi8(__X, __Y);
}
diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c
index 7e4e64381c1d..5547ac9e2f7d 100644
--- a/test/CodeGen/avx512vl-builtins.c
+++ b/test/CodeGen/avx512vl-builtins.c
@@ -839,126 +839,182 @@ __m256i test_mm256_mask_mullo_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
return _mm256_mask_mullo_epi32(__W, __M, __A, __B);
}
-__m256i test_mm256_mask_and_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_and_epi32 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_and_epi32
+ //CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+ return _mm256_and_epi32(__A, __B);
+}
+
+__m256i test_mm256_mask_and_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_and_epi32
- //CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_and_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_and_epi32 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_and_epi32
- //CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: and <8 x i32> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_and_epi32(__U, __A, __B);
}
+__m128i test_mm_and_epi32 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_and_epi32
+ //CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+ return _mm_and_epi32(__A, __B);
+}
+
__m128i test_mm_mask_and_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_and_epi32
- //CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_and_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_and_epi32 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_and_epi32
- //CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: and <4 x i32> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_and_epi32(__U, __A, __B);
}
-__m256i test_mm256_mask_andnot_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_andnot_epi32 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_andnot_epi32
+ //CHECK: xor <8 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
+ //CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+ return _mm256_andnot_epi32(__A, __B);
+}
+
+__m256i test_mm256_mask_andnot_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_andnot_epi32
- //CHECK: xor <4 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1>
- //CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <8 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
+ //CHECK: and <8 x i32> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_andnot_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_andnot_epi32 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_andnot_epi32
- //CHECK: xor <4 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1>
- //CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <8 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
+ //CHECK: and <8 x i32> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_andnot_epi32(__U, __A, __B);
}
-__m128i test_mm_mask_andnot_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B) {
+__m128i test_mm_andnot_epi32 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_andnot_epi32
+ //CHECK: xor <4 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+ //CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+ return _mm_andnot_epi32(__A, __B);
+}
+
+__m128i test_mm_mask_andnot_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_andnot_epi32
- //CHECK: xor <2 x i64> %{{.*}}, <i64 -1, i64 -1>
- //CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <4 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+ //CHECK: and <4 x i32> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_andnot_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_andnot_epi32 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_andnot_epi32
- //CHECK: xor <2 x i64> %{{.*}}, <i64 -1, i64 -1>
- //CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <4 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+ //CHECK: and <4 x i32> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_andnot_epi32(__U, __A, __B);
}
-__m256i test_mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_or_epi32 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_or_epi32
+ //CHECK: or <8 x i32> %{{.*}}, %{{.*}}
+ return _mm256_or_epi32(__A, __B);
+}
+
+__m256i test_mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_or_epi32
- //CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: or <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_or_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_or_epi32 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_or_epi32
- //CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: or <8 x i32> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_or_epi32(__U, __A, __B);
}
- __m128i test_mm_mask_or_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+__m128i test_mm_or_epi32 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_or_epi32
+ //CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+ return _mm_or_epi32(__A, __B);
+}
+
+__m128i test_mm_mask_or_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_or_epi32
- //CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_or_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_or_epi32 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_or_epi32
- //CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: or <4 x i32> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_or_epi32(__U, __A, __B);
}
-__m256i test_mm256_mask_xor_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_xor_epi32 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_xor_epi32
+ //CHECK: or <8 x i32> %{{.*}}, %{{.*}}
+ return _mm256_xor_epi32(__A, __B);
+}
+
+__m256i test_mm256_mask_xor_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_xor_epi32
- //CHECK: xor <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_xor_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_xor_epi32 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_xor_epi32
- //CHECK: xor <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <8 x i32> %{{.*}}, %{{.*}}
//CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_xor_epi32(__U, __A, __B);
}
-__m128i test_mm_mask_xor_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B) {
+__m128i test_mm_xor_epi32 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_xor_epi32
+ //CHECK: xor <4 x i32> %{{.*}}, %{{.*}}
+ return _mm_xor_epi32(__A, __B);
+}
+
+__m128i test_mm_mask_xor_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_xor_epi32
- //CHECK: xor <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_xor_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_xor_epi32 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_xor_epi32
- //CHECK: xor <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: xor <4 x i32> %{{.*}}, %{{.*}}
//CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_xor_epi32(__U, __A, __B);
}
-__m256i test_mm256_mask_and_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_and_epi64 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_and_epi64
+ //CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ return _mm256_and_epi64(__A, __B);
+}
+
+__m256i test_mm256_mask_and_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_and_epi64
//CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_and_epi64(__W, __U, __A, __B);
}
@@ -969,10 +1025,16 @@ __m256i test_mm256_maskz_and_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
return _mm256_maskz_and_epi64(__U, __A, __B);
}
-__m128i test_mm_mask_and_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B) {
+__m128i test_mm_and_epi64 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_and_epi64
+ //CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ return _mm_and_epi64(__A, __B);
+}
+
+__m128i test_mm_mask_and_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_and_epi64
//CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_and_epi64(__W,__U, __A, __B);
}
@@ -983,8 +1045,14 @@ __m128i test_mm_maskz_and_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
return _mm_maskz_and_epi64(__U, __A, __B);
}
-__m256i test_mm256_mask_andnot_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_andnot_epi64 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_andnot_epi64
+ //CHECK: xor <4 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1>
+ //CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ return _mm256_andnot_epi64(__A, __B);
+}
+
+__m256i test_mm256_mask_andnot_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_andnot_epi64
//CHECK: xor <4 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1>
//CHECK: and <4 x i64> %{{.*}}, %{{.*}}
@@ -1000,8 +1068,14 @@ __m256i test_mm256_maskz_andnot_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
return _mm256_maskz_andnot_epi64(__U, __A, __B);
}
-__m128i test_mm_mask_andnot_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B) {
+__m128i test_mm_andnot_epi64 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_andnot_epi64
+ //CHECK: xor <2 x i64> %{{.*}}, <i64 -1, i64 -1>
+ //CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ return _mm_andnot_epi64(__A, __B);
+}
+
+__m128i test_mm_mask_andnot_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_andnot_epi64
//CHECK: xor <2 x i64> %{{.*}}, <i64 -1, i64 -1>
//CHECK: and <2 x i64> %{{.*}}, %{{.*}}
@@ -1017,10 +1091,16 @@ __m128i test_mm_maskz_andnot_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
return _mm_maskz_andnot_epi64(__U, __A, __B);
}
-__m256i test_mm256_mask_or_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_or_epi64 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_or_epi64
+ //CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+ return _mm256_or_epi64(__A, __B);
+}
+
+__m256i test_mm256_mask_or_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_or_epi64
//CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_or_epi64(__W,__U, __A, __B);
}
@@ -1031,9 +1111,16 @@ __m256i test_mm256_maskz_or_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
return _mm256_maskz_or_epi64(__U, __A, __B);
}
+__m128i test_mm_or_epi64 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_or_epi64
+ //CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+ return _mm_or_epi64(__A, __B);
+}
+
__m128i test_mm_mask_or_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_or_epi64
//CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_or_epi64(__W, __U, __A, __B);
}
@@ -1044,10 +1131,16 @@ __m128i test_mm_maskz_or_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
return _mm_maskz_or_epi64( __U, __A, __B);
}
-__m256i test_mm256_mask_xor_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B) {
+__m256i test_mm256_xor_epi64 (__m256i __A, __m256i __B) {
+ //CHECK-LABEL: @test_mm256_xor_epi64
+ //CHECK: xor <4 x i64> %{{.*}}, %{{.*}}
+ return _mm256_xor_epi64(__A, __B);
+}
+
+__m256i test_mm256_mask_xor_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_xor_epi64
//CHECK: xor <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_xor_epi64(__W,__U, __A, __B);
}
@@ -1058,9 +1151,16 @@ __m256i test_mm256_maskz_xor_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
return _mm256_maskz_xor_epi64(__U, __A, __B);
}
+__m128i test_mm_xor_epi64 (__m128i __A, __m128i __B) {
+ //CHECK-LABEL: @test_mm_xor_epi64
+ //CHECK: xor <2 x i64> %{{.*}}, %{{.*}}
+ return _mm_xor_epi64(__A, __B);
+}
+
__m128i test_mm_mask_xor_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_xor_epi64
//CHECK: xor <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_xor_epi64(__W, __U, __A, __B);
}
@@ -5679,240 +5779,240 @@ __m256i test_mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
__m128i test_mm_rol_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.128
+ // CHECK: @llvm.fshl.v4i32
return _mm_rol_epi32(__A, 5);
}
__m128i test_mm_mask_rol_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.128
+ // CHECK: @llvm.fshl.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_rol_epi32(__W, __U, __A, 5);
}
__m128i test_mm_maskz_rol_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.128
+ // CHECK: @llvm.fshl.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_rol_epi32(__U, __A, 5);
}
__m256i test_mm256_rol_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm256_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.256
+ // CHECK: @llvm.fshl.v8i32
return _mm256_rol_epi32(__A, 5);
}
__m256i test_mm256_mask_rol_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.256
+ // CHECK: @llvm.fshl.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_rol_epi32(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_rol_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_rol_epi32
- // CHECK: @llvm.x86.avx512.prol.d.256
+ // CHECK: @llvm.fshl.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_rol_epi32(__U, __A, 5);
}
__m128i test_mm_rol_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.128
+ // CHECK: @llvm.fshl.v2i64
return _mm_rol_epi64(__A, 5);
}
__m128i test_mm_mask_rol_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.128
+ // CHECK: @llvm.fshl.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_rol_epi64(__W, __U, __A, 5);
}
__m128i test_mm_maskz_rol_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.128
+ // CHECK: @llvm.fshl.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_rol_epi64(__U, __A, 5);
}
__m256i test_mm256_rol_epi64(__m256i __A) {
// CHECK-LABEL: @test_mm256_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.256
+ // CHECK: @llvm.fshl.v4i64
return _mm256_rol_epi64(__A, 5);
}
__m256i test_mm256_mask_rol_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.256
+ // CHECK: @llvm.fshl.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_rol_epi64(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_rol_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_rol_epi64
- // CHECK: @llvm.x86.avx512.prol.q.256
+ // CHECK: @llvm.fshl.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_rol_epi64(__U, __A, 5);
}
__m128i test_mm_rolv_epi32(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.128
+ // CHECK: llvm.fshl.v4i32
return _mm_rolv_epi32(__A, __B);
}
__m128i test_mm_mask_rolv_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.128
+ // CHECK: llvm.fshl.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_rolv_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rolv_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.128
+ // CHECK: llvm.fshl.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_rolv_epi32(__U, __A, __B);
}
__m256i test_mm256_rolv_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.256
+ // CHECK: @llvm.fshl.v8i32
return _mm256_rolv_epi32(__A, __B);
}
__m256i test_mm256_mask_rolv_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.256
+ // CHECK: @llvm.fshl.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_rolv_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rolv_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rolv_epi32
- // CHECK: @llvm.x86.avx512.prolv.d.256
+ // CHECK: @llvm.fshl.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_rolv_epi32(__U, __A, __B);
}
__m128i test_mm_rolv_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.128
+ // CHECK: @llvm.fshl.v2i64
return _mm_rolv_epi64(__A, __B);
}
__m128i test_mm_mask_rolv_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.128
+ // CHECK: @llvm.fshl.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_rolv_epi64(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rolv_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.128
+ // CHECK: @llvm.fshl.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_rolv_epi64(__U, __A, __B);
}
__m256i test_mm256_rolv_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.256
+ // CHECK: @llvm.fshl.v4i64
return _mm256_rolv_epi64(__A, __B);
}
__m256i test_mm256_mask_rolv_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.256
+ // CHECK: @llvm.fshl.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_rolv_epi64(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rolv_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rolv_epi64
- // CHECK: @llvm.x86.avx512.prolv.q.256
+ // CHECK: @llvm.fshl.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_rolv_epi64(__U, __A, __B);
}
__m128i test_mm_ror_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.128
+ // CHECK: @llvm.fshr.v4i32
return _mm_ror_epi32(__A, 5);
}
__m128i test_mm_mask_ror_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.128
+ // CHECK: @llvm.fshr.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_ror_epi32(__W, __U, __A, 5);
}
__m128i test_mm_maskz_ror_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.128
+ // CHECK: @llvm.fshr.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_ror_epi32(__U, __A, 5);
}
__m256i test_mm256_ror_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm256_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.256
+ // CHECK: @llvm.fshr.v8i32
return _mm256_ror_epi32(__A, 5);
}
__m256i test_mm256_mask_ror_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.256
+ // CHECK: @llvm.fshr.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_ror_epi32(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_ror_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_ror_epi32
- // CHECK: @llvm.x86.avx512.pror.d.256
+ // CHECK: @llvm.fshr.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_ror_epi32(__U, __A, 5);
}
__m128i test_mm_ror_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.128
+ // CHECK: @llvm.fshr.v2i64
return _mm_ror_epi64(__A, 5);
}
__m128i test_mm_mask_ror_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.128
+ // CHECK: @llvm.fshr.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_ror_epi64(__W, __U, __A, 5);
}
__m128i test_mm_maskz_ror_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.128
+ // CHECK: @llvm.fshr.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_ror_epi64(__U, __A, 5);
}
__m256i test_mm256_ror_epi64(__m256i __A) {
// CHECK-LABEL: @test_mm256_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.256
+ // CHECK: @llvm.fshr.v4i64
return _mm256_ror_epi64(__A, 5);
}
__m256i test_mm256_mask_ror_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.256
+ // CHECK: @llvm.fshr.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_ror_epi64(__W, __U, __A,5);
}
__m256i test_mm256_maskz_ror_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_ror_epi64
- // CHECK: @llvm.x86.avx512.pror.q.256
+ // CHECK: @llvm.fshr.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_ror_epi64(__U, __A, 5);
}
@@ -5920,80 +6020,80 @@ __m256i test_mm256_maskz_ror_epi64(__mmask8 __U, __m256i __A) {
__m128i test_mm_rorv_epi32(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.128
+ // CHECK: @llvm.fshr.v4i32
return _mm_rorv_epi32(__A, __B);
}
__m128i test_mm_mask_rorv_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.128
+ // CHECK: @llvm.fshr.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_rorv_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rorv_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.128
+ // CHECK: @llvm.fshr.v4i32
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_rorv_epi32(__U, __A, __B);
}
__m256i test_mm256_rorv_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.256
+ // CHECK: @llvm.fshr.v8i32
return _mm256_rorv_epi32(__A, __B);
}
__m256i test_mm256_mask_rorv_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.256
+ // CHECK: @llvm.fshr.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_rorv_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rorv_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rorv_epi32
- // CHECK: @llvm.x86.avx512.prorv.d.256
+ // CHECK: @llvm.fshr.v8i32
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_rorv_epi32(__U, __A, __B);
}
__m128i test_mm_rorv_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.128
+ // CHECK: @llvm.fshr.v2i64
return _mm_rorv_epi64(__A, __B);
}
__m128i test_mm_mask_rorv_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.128
+ // CHECK: @llvm.fshr.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_rorv_epi64(__W, __U, __A, __B);
}
__m128i test_mm_maskz_rorv_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.128
+ // CHECK: @llvm.fshr.v2i64
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_rorv_epi64(__U, __A, __B);
}
__m256i test_mm256_rorv_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.256
+ // CHECK: @llvm.fshr.v4i64
return _mm256_rorv_epi64(__A, __B);
}
__m256i test_mm256_mask_rorv_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.256
+ // CHECK: @llvm.fshr.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_rorv_epi64(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_rorv_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_rorv_epi64
- // CHECK: @llvm.x86.avx512.prorv.q.256
+ // CHECK: @llvm.fshr.v4i64
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_rorv_epi64(__U, __A, __B);
}
@@ -6145,6 +6245,13 @@ __m128i test_mm_mask_srli_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_srli_epi32(__W, __U, __A, 5);
}
+__m128i test_mm_mask_srli_epi32_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_srli_epi32_2
+ // CHECK: @llvm.x86.sse2.psrli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_srli_epi32(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_srli_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srli_epi32
// CHECK: @llvm.x86.sse2.psrli.d
@@ -6152,6 +6259,13 @@ __m128i test_mm_maskz_srli_epi32(__mmask8 __U, __m128i __A) {
return _mm_maskz_srli_epi32(__U, __A, 5);
}
+__m128i test_mm_maskz_srli_epi32_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_srli_epi32_2
+ // CHECK: @llvm.x86.sse2.psrli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_srli_epi32(__U, __A, __B);
+}
+
__m256i test_mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srli_epi32
// CHECK: @llvm.x86.avx2.psrli.d
@@ -6159,6 +6273,13 @@ __m256i test_mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
return _mm256_mask_srli_epi32(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_srli_epi32_2(__m256i __W, __mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_srli_epi32_2
+ // CHECK: @llvm.x86.avx2.psrli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_mask_srli_epi32(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srli_epi32
// CHECK: @llvm.x86.avx2.psrli.d
@@ -6166,6 +6287,12 @@ __m256i test_mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A) {
return _mm256_maskz_srli_epi32(__U, __A, 5);
}
+__m256i test_mm256_maskz_srli_epi32_2(__mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srli_epi32_2
+ // CHECK: @llvm.x86.avx2.psrli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_maskz_srli_epi32(__U, __A, __B);
+}
__m128i test_mm_mask_srl_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_srl_epi64
// CHECK: @llvm.x86.sse2.psrl.q
@@ -6201,6 +6328,13 @@ __m128i test_mm_mask_srli_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_srli_epi64(__W, __U, __A, 5);
}
+__m128i test_mm_mask_srli_epi64_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_srli_epi64_2
+ // CHECK: @llvm.x86.sse2.psrli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_mask_srli_epi64(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_srli_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srli_epi64
// CHECK: @llvm.x86.sse2.psrli.q
@@ -6208,6 +6342,13 @@ __m128i test_mm_maskz_srli_epi64(__mmask8 __U, __m128i __A) {
return _mm_maskz_srli_epi64(__U, __A, 5);
}
+__m128i test_mm_maskz_srli_epi64_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_srli_epi64_2
+ // CHECK: @llvm.x86.sse2.psrli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_maskz_srli_epi64(__U, __A, __B);
+}
+
__m256i test_mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srli_epi64
// CHECK: @llvm.x86.avx2.psrli.q
@@ -6215,6 +6356,13 @@ __m256i test_mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
return _mm256_mask_srli_epi64(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_srli_epi64_2(__m256i __W, __mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_srli_epi64_2
+ // CHECK: @llvm.x86.avx2.psrli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_mask_srli_epi64(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srli_epi64
// CHECK: @llvm.x86.avx2.psrli.q
@@ -6222,6 +6370,13 @@ __m256i test_mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A) {
return _mm256_maskz_srli_epi64(__U, __A, 5);
}
+__m256i test_mm256_maskz_srli_epi64_2(__mmask8 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_maskz_srli_epi64_2
+ // CHECK: @llvm.x86.avx2.psrli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_maskz_srli_epi64(__U, __A, 5);
+}
+
__m128i test_mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_sll_epi32
// CHECK: @llvm.x86.sse2.psll.d
@@ -6257,6 +6412,13 @@ __m128i test_mm_mask_slli_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_slli_epi32(__W, __U, __A, 5);
}
+__m128i test_mm_mask_slli_epi32_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_slli_epi32_2
+ // CHECK: @llvm.x86.sse2.pslli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_slli_epi32(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_slli_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_slli_epi32
// CHECK: @llvm.x86.sse2.pslli.d
@@ -6264,6 +6426,13 @@ __m128i test_mm_maskz_slli_epi32(__mmask8 __U, __m128i __A) {
return _mm_maskz_slli_epi32(__U, __A, 5);
}
+__m128i test_mm_maskz_slli_epi32_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_slli_epi32_2
+ // CHECK: @llvm.x86.sse2.pslli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_slli_epi32(__U, __A, __B);
+}
+
__m256i test_mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_slli_epi32
// CHECK: @llvm.x86.avx2.pslli.d
@@ -6271,6 +6440,13 @@ __m256i test_mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
return _mm256_mask_slli_epi32(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_slli_epi32_2(__m256i __W, __mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_slli_epi32_2
+ // CHECK: @llvm.x86.avx2.pslli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_mask_slli_epi32(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_slli_epi32
// CHECK: @llvm.x86.avx2.pslli.d
@@ -6278,6 +6454,13 @@ __m256i test_mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A) {
return _mm256_maskz_slli_epi32(__U, __A, 5);
}
+__m256i test_mm256_maskz_slli_epi32_2(__mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_maskz_slli_epi32_2
+ // CHECK: @llvm.x86.avx2.pslli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_maskz_slli_epi32(__U, __A, __B);
+}
+
__m128i test_mm_mask_sll_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_sll_epi64
// CHECK: @llvm.x86.sse2.psll.q
@@ -6313,6 +6496,13 @@ __m128i test_mm_mask_slli_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_slli_epi64(__W, __U, __A, 5);
}
+__m128i test_mm_mask_slli_epi64_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_slli_epi64_2
+ // CHECK: @llvm.x86.sse2.pslli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_mask_slli_epi64(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_slli_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_slli_epi64
// CHECK: @llvm.x86.sse2.pslli.q
@@ -6320,6 +6510,13 @@ __m128i test_mm_maskz_slli_epi64(__mmask8 __U, __m128i __A) {
return _mm_maskz_slli_epi64(__U, __A, 5);
}
+__m128i test_mm_maskz_slli_epi64_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_slli_epi64_2
+ // CHECK: @llvm.x86.sse2.pslli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_maskz_slli_epi64(__U, __A, __B);
+}
+
__m256i test_mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_slli_epi64
// CHECK: @llvm.x86.avx2.pslli.q
@@ -6327,6 +6524,13 @@ __m256i test_mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
return _mm256_mask_slli_epi64(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_slli_epi64_2(__m256i __W, __mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_slli_epi64_2
+ // CHECK: @llvm.x86.avx2.pslli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_mask_slli_epi64(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_slli_epi64
// CHECK: @llvm.x86.avx2.pslli.q
@@ -6334,6 +6538,13 @@ __m256i test_mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A) {
return _mm256_maskz_slli_epi64(__U, __A, 5);
}
+__m256i test_mm256_maskz_slli_epi64_2(__mmask8 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_maskz_slli_epi64_2
+ // CHECK: @llvm.x86.avx2.pslli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_maskz_slli_epi64(__U, __A, 5);
+}
+
__m128i test_mm_mask_srav_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_srav_epi32
// CHECK: @llvm.x86.avx2.psrav.d
@@ -6402,12 +6613,24 @@ __m256i test_mm256_maskz_srav_epi64(__mmask8 __U, __m256i __X, __m256i __Y) {
return _mm256_maskz_srav_epi64(__U, __X, __Y);
}
+void test_mm_store_epi32(void *__P, __m128i __A) {
+ // CHECK-LABEL: @test_mm_store_epi32
+ // CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}
+ return _mm_store_epi32(__P, __A);
+}
+
void test_mm_mask_store_epi32(void *__P, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_store_epi32
// CHECK: @llvm.masked.store.v4i32.p0v4i32(<4 x i32> %{{.*}}, <4 x i32>* %{{.}}, i32 16, <4 x i1> %{{.*}})
return _mm_mask_store_epi32(__P, __U, __A);
}
+void test_mm256_store_epi32(void *__P, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_store_epi32
+ // CHECK: store <4 x i64> %{{.*}}, <4 x i64>* %{{.*}}
+ return _mm256_store_epi32(__P, __A);
+}
+
void test_mm256_mask_store_epi32(void *__P, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_store_epi32
// CHECK: @llvm.masked.store.v8i32.p0v8i32(<8 x i32> %{{.*}}, <8 x i32>* %{{.}}, i32 32, <8 x i1> %{{.*}})
@@ -6462,6 +6685,12 @@ __m256i test_mm256_maskz_mov_epi64(__mmask8 __U, __m256i __A) {
return _mm256_maskz_mov_epi64(__U, __A);
}
+__m128i test_mm_load_epi32(void const *__P) {
+ // CHECK-LABEL: @test_mm_load_epi32
+ // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}
+ return _mm_load_epi32(__P);
+}
+
__m128i test_mm_mask_load_epi32(__m128i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_load_epi32
// CHECK: @llvm.masked.load.v4i32.p0v4i32(<4 x i32>* %{{.*}}, i32 16, <4 x i1> %{{.*}}, <4 x i32> %{{.*}})
@@ -6474,6 +6703,12 @@ __m128i test_mm_maskz_load_epi32(__mmask8 __U, void const *__P) {
return _mm_maskz_load_epi32(__U, __P);
}
+__m256i test_mm256_load_epi32(void const *__P) {
+ // CHECK-LABEL: @test_mm256_load_epi32
+ // CHECK: load <4 x i64>, <4 x i64>* %{{.*}}
+ return _mm256_load_epi32(__P);
+}
+
__m256i test_mm256_mask_load_epi32(__m256i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_load_epi32
// CHECK: @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %{{.*}}, i32 32, <8 x i1> %{{.*}}, <8 x i32> %{{.*}})
@@ -6486,6 +6721,12 @@ __m256i test_mm256_maskz_load_epi32(__mmask8 __U, void const *__P) {
return _mm256_maskz_load_epi32(__U, __P);
}
+__m128i test_mm_load_epi64(void const *__P) {
+ // CHECK-LABEL: @test_mm_load_epi64
+ // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}
+ return _mm_load_epi64(__P);
+}
+
__m128i test_mm_mask_load_epi64(__m128i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_load_epi64
// CHECK: @llvm.masked.load.v2i64.p0v2i64(<2 x i64>* %{{.*}}, i32 16, <2 x i1> %{{.*}}, <2 x i64> %{{.*}})
@@ -6498,6 +6739,12 @@ __m128i test_mm_maskz_load_epi64(__mmask8 __U, void const *__P) {
return _mm_maskz_load_epi64(__U, __P);
}
+__m256i test_mm256_load_epi64(void const *__P) {
+ // CHECK-LABEL: @test_mm256_load_epi64
+ // CHECK: load <4 x i64>, <4 x i64>* %{{.*}}
+ return _mm256_load_epi64(__P);
+}
+
__m256i test_mm256_mask_load_epi64(__m256i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_load_epi64
// CHECK: @llvm.masked.load.v4i64.p0v4i64(<4 x i64>* %{{.*}}, i32 32, <4 x i1> %{{.*}}, <4 x i64> %{{.*}})
@@ -6510,12 +6757,24 @@ __m256i test_mm256_maskz_load_epi64(__mmask8 __U, void const *__P) {
return _mm256_maskz_load_epi64(__U, __P);
}
+void test_mm_store_epi64(void *__P, __m128i __A) {
+ // CHECK-LABEL: @test_mm_store_epi64
+ // CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}
+ return _mm_store_epi64(__P, __A);
+}
+
void test_mm_mask_store_epi64(void *__P, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_store_epi64
// CHECK: @llvm.masked.store.v2i64.p0v2i64(<2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, i32 16, <2 x i1> %{{.*}})
return _mm_mask_store_epi64(__P, __U, __A);
}
+void test_mm256_store_epi64(void *__P, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_store_epi64
+ // CHECK: store <4 x i64> %{{.*}}, <4 x i64>* %{{.*}}
+ return _mm256_store_epi64(__P, __A);
+}
+
void test_mm256_mask_store_epi64(void *__P, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_store_epi64
// CHECK: @llvm.masked.store.v4i64.p0v4i64(<4 x i64> %{{.*}}, <4 x i64>* %{{.*}}, i32 32, <4 x i1> %{{.*}})
@@ -6760,6 +7019,12 @@ __m256 test_mm256_maskz_load_ps(__mmask8 __U, void const *__P) {
return _mm256_maskz_load_ps(__U, __P);
}
+__m128i test_mm_loadu_epi64(void const *__P) {
+ // CHECK-LABEL: @test_mm_loadu_epi64
+ // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_loadu_epi64(__P);
+}
+
__m128i test_mm_mask_loadu_epi64(__m128i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_loadu_epi64
// CHECK: @llvm.masked.load.v2i64.p0v2i64(<2 x i64>* %{{.*}}, i32 1, <2 x i1> %{{.*}}, <2 x i64> %{{.*}})
@@ -6772,6 +7037,12 @@ __m128i test_mm_maskz_loadu_epi64(__mmask8 __U, void const *__P) {
return _mm_maskz_loadu_epi64(__U, __P);
}
+__m256i test_mm256_loadu_epi64(void const *__P) {
+ // CHECK-LABEL: @test_mm256_loadu_epi64
+ // CHECK: load <4 x i64>, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_loadu_epi64(__P);
+}
+
__m256i test_mm256_mask_loadu_epi64(__m256i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_loadu_epi64
// CHECK: @llvm.masked.load.v4i64.p0v4i64(<4 x i64>* %{{.*}}, i32 1, <4 x i1> %{{.*}}, <4 x i64> %{{.*}})
@@ -6784,6 +7055,12 @@ __m256i test_mm256_maskz_loadu_epi64(__mmask8 __U, void const *__P) {
return _mm256_maskz_loadu_epi64(__U, __P);
}
+__m128i test_mm_loadu_epi32(void const *__P) {
+ // CHECK-LABEL: @test_mm_loadu_epi32
+ // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_loadu_epi32(__P);
+}
+
__m128i test_mm_mask_loadu_epi32(__m128i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_loadu_epi32
// CHECK: @llvm.masked.load.v4i32.p0v4i32(<4 x i32>* %{{.*}}, i32 1, <4 x i1> %{{.*}}, <4 x i32> %{{.*}})
@@ -6796,6 +7073,12 @@ __m128i test_mm_maskz_loadu_epi32(__mmask8 __U, void const *__P) {
return _mm_maskz_loadu_epi32(__U, __P);
}
+__m256i test_mm256_loadu_epi32(void const *__P) {
+ // CHECK-LABEL: @test_mm256_loadu_epi32
+ // CHECK: load <4 x i64>, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_loadu_epi32(__P);
+}
+
__m256i test_mm256_mask_loadu_epi32(__m256i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_loadu_epi32
// CHECK: @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %{{.*}}, i32 1, <8 x i1> %{{.*}}, <8 x i32> %{{.*}})
@@ -6880,24 +7163,48 @@ void test_mm256_mask_store_ps(void *__P, __mmask8 __U, __m256 __A) {
return _mm256_mask_store_ps(__P, __U, __A);
}
+void test_mm_storeu_epi64(void *__p, __m128i __a) {
+ // check-label: @test_mm_storeu_epi64
+ // check: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_storeu_epi64(__p, __a);
+}
+
void test_mm_mask_storeu_epi64(void *__P, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_storeu_epi64
// CHECK: @llvm.masked.store.v2i64.p0v2i64(<2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, i32 1, <2 x i1> %{{.*}})
return _mm_mask_storeu_epi64(__P, __U, __A);
}
+void test_mm256_storeu_epi64(void *__P, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_storeu_epi64
+ // CHECK: store <4 x i64> %{{.*}}, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_storeu_epi64(__P, __A);
+}
+
void test_mm256_mask_storeu_epi64(void *__P, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_storeu_epi64
// CHECK: @llvm.masked.store.v4i64.p0v4i64(<4 x i64> %{{.*}}, <4 x i64>* %{{.*}}, i32 1, <4 x i1> %{{.*}})
return _mm256_mask_storeu_epi64(__P, __U, __A);
}
+void test_mm_storeu_epi32(void *__P, __m128i __A) {
+ // CHECK-LABEL: @test_mm_storeu_epi32
+ // CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_storeu_epi32(__P, __A);
+}
+
void test_mm_mask_storeu_epi32(void *__P, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_storeu_epi32
// CHECK: @llvm.masked.store.v4i32.p0v4i32(<4 x i32> %{{.*}}, <4 x i32>* %{{.*}}, i32 1, <4 x i1> %{{.*}})
return _mm_mask_storeu_epi32(__P, __U, __A);
}
+void test_mm256_storeu_epi32(void *__P, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_storeu_epi32
+ // CHECK: store <4 x i64> %{{.*}}, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_storeu_epi32(__P, __A);
+}
+
void test_mm256_mask_storeu_epi32(void *__P, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_storeu_epi32
// CHECK: @llvm.masked.store.v8i32.p0v8i32(<8 x i32> %{{.*}}, <8 x i32>* %{{.*}}, i32 1, <8 x i1> %{{.*}})
@@ -7491,6 +7798,13 @@ __m128i test_mm_mask_srai_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_srai_epi32(__W, __U, __A, 5);
}
+__m128i test_mm_mask_srai_epi32_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_srai_epi32_2
+ // CHECK: @llvm.x86.sse2.psrai.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_srai_epi32(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_srai_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srai_epi32
// CHECK: @llvm.x86.sse2.psrai.d
@@ -7498,6 +7812,13 @@ __m128i test_mm_maskz_srai_epi32(__mmask8 __U, __m128i __A) {
return _mm_maskz_srai_epi32(__U, __A, 5);
}
+__m128i test_mm_maskz_srai_epi32_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_srai_epi32_2
+ // CHECK: @llvm.x86.sse2.psrai.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_srai_epi32(__U, __A, __B);
+}
+
__m256i test_mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srai_epi32
// CHECK: @llvm.x86.avx2.psrai.d
@@ -7505,6 +7826,13 @@ __m256i test_mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
return _mm256_mask_srai_epi32(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_srai_epi32_2(__m256i __W, __mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_srai_epi32_2
+ // CHECK: @llvm.x86.avx2.psrai.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_mask_srai_epi32(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srai_epi32
// CHECK: @llvm.x86.avx2.psrai.d
@@ -7512,6 +7840,13 @@ __m256i test_mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A) {
return _mm256_maskz_srai_epi32(__U, __A, 5);
}
+__m256i test_mm256_maskz_srai_epi32_2(__mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srai_epi32_2
+ // CHECK: @llvm.x86.avx2.psrai.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_maskz_srai_epi32(__U, __A, __B);
+}
+
__m128i test_mm_sra_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_sra_epi64
// CHECK: @llvm.x86.avx512.psra.q.128
@@ -7558,6 +7893,12 @@ __m128i test_mm_srai_epi64(__m128i __A) {
return _mm_srai_epi64(__A, 5);
}
+__m128i test_mm_srai_epi64_2(__m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.128
+ return _mm_srai_epi64(__A, __B);
+}
+
__m128i test_mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.128
@@ -7565,6 +7906,13 @@ __m128i test_mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_srai_epi64(__W, __U, __A, 5);
}
+__m128i test_mm_mask_srai_epi64_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_mask_srai_epi64(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_srai_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.128
@@ -7572,12 +7920,25 @@ __m128i test_mm_maskz_srai_epi64(__mmask8 __U, __m128i __A) {
return _mm_maskz_srai_epi64(__U, __A, 5);
}
+__m128i test_mm_maskz_srai_epi64_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_maskz_srai_epi64(__U, __A, __B);
+}
+
__m256i test_mm256_srai_epi64(__m256i __A) {
// CHECK-LABEL: @test_mm256_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.256
return _mm256_srai_epi64(__A, 5);
}
+__m256i test_mm256_srai_epi64_2(__m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.256
+ return _mm256_srai_epi64(__A, __B);
+}
+
__m256i test_mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.256
@@ -7585,6 +7946,13 @@ __m256i test_mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
return _mm256_mask_srai_epi64(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_srai_epi64_2(__m256i __W, __mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_mask_srai_epi64(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srai_epi64
// CHECK: @llvm.x86.avx512.psrai.q.256
@@ -7592,6 +7960,13 @@ __m256i test_mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A) {
return _mm256_maskz_srai_epi64(__U, __A, 5);
}
+__m256i test_mm256_maskz_srai_epi64_2(__mmask8 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srai_epi64_2
+ // CHECK: @llvm.x86.avx512.psrai.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_maskz_srai_epi64(__U, __A, __B);
+}
+
__m128i test_mm_ternarylogic_epi32(__m128i __A, __m128i __B, __m128i __C) {
// CHECK-LABEL: @test_mm_ternarylogic_epi32
// CHECK: @llvm.x86.avx512.pternlog.d.128
diff --git a/test/CodeGen/avx512vlbitalg-builtins.c b/test/CodeGen/avx512vlbitalg-builtins.c
index 3dd5b68fd463..d54a607f7178 100644
--- a/test/CodeGen/avx512vlbitalg-builtins.c
+++ b/test/CodeGen/avx512vlbitalg-builtins.c
@@ -80,25 +80,27 @@ __m128i test_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) {
__mmask32 test_mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_bitshuffle_epi64_mask
- // CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.256
+ // CHECK: @llvm.x86.avx512.vpshufbitqmb.256
+ // CHECK: and <32 x i1> %{{.*}}, %{{.*}}
return _mm256_mask_bitshuffle_epi64_mask(__U, __A, __B);
}
__mmask32 test_mm256_bitshuffle_epi64_mask(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_bitshuffle_epi64_mask
- // CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.256
+ // CHECK: @llvm.x86.avx512.vpshufbitqmb.256
return _mm256_bitshuffle_epi64_mask(__A, __B);
}
__mmask16 test_mm_mask_bitshuffle_epi64_mask(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_bitshuffle_epi64_mask
- // CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.128
+ // CHECK: @llvm.x86.avx512.vpshufbitqmb.128
+ // CHECK: and <16 x i1> %{{.*}}, %{{.*}}
return _mm_mask_bitshuffle_epi64_mask(__U, __A, __B);
}
__mmask16 test_mm_bitshuffle_epi64_mask(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_bitshuffle_epi64_mask
- // CHECK: @llvm.x86.avx512.mask.vpshufbitqmb.128
+ // CHECK: @llvm.x86.avx512.vpshufbitqmb.128
return _mm_bitshuffle_epi64_mask(__A, __B);
}
diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c
index c28c3fbd7f81..80efe72787a2 100644
--- a/test/CodeGen/avx512vlbw-builtins.c
+++ b/test/CodeGen/avx512vlbw-builtins.c
@@ -1075,97 +1075,105 @@ __m256i test_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __
__m128i test_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epi8
- // CHECK: @llvm.x86.sse2.padds.b
+ // CHECK: @llvm.sadd.sat.v16i8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_adds_epi8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epi8
- // CHECK: @llvm.x86.sse2.padds.b
+ // CHECK: @llvm.sadd.sat.v16i8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_adds_epi8(__U,__A,__B);
}
__m256i test_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epi8
- // CHECK: @llvm.x86.avx2.padds.b
+ // CHECK: @llvm.sadd.sat.v32i8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_adds_epi8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epi8
- // CHECK: @llvm.x86.avx2.padds.b
+ // CHECK: @llvm.sadd.sat.v32i8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_adds_epi8(__U,__A,__B);
}
__m128i test_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epi16
- // CHECK: @llvm.x86.sse2.padds.w
+ // CHECK: @llvm.sadd.sat.v8i16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_adds_epi16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epi16
- // CHECK: @llvm.x86.sse2.padds.w
+ // CHECK: @llvm.sadd.sat.v8i16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_adds_epi16(__U,__A,__B);
}
__m256i test_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epi16
- // CHECK: @llvm.x86.avx2.padds.w
+ // CHECK: @llvm.sadd.sat.v16i16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_adds_epi16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epi16
- // CHECK: @llvm.x86.avx2.padds.w
+ // CHECK: @llvm.sadd.sat.v16i16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_adds_epi16(__U,__A,__B);
}
__m128i test_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epu8
- // CHECK: @llvm.x86.sse2.paddus.b
+ // CHECK-NOT: @llvm.x86.sse2.paddus.b
+ // CHECK: call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_adds_epu8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epu8
- // CHECK: @llvm.x86.sse2.paddus.b
+ // CHECK-NOT: @llvm.x86.sse2.paddus.b
+ // CHECK: call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_adds_epu8(__U,__A,__B);
}
__m256i test_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epu8
- // CHECK: @llvm.x86.avx2.paddus.b
+ // CHECK-NOT: @llvm.x86.avx2.paddus.b
+ // CHECK: call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_adds_epu8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epu8
- // CHECK: @llvm.x86.avx2.paddus.b
+ // CHECK-NOT: @llvm.x86.avx2.paddus.b
+ // CHECK: call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_adds_epu8(__U,__A,__B);
}
__m128i test_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_adds_epu16
- // CHECK: @llvm.x86.sse2.paddus.w
+ // CHECK-NOT: @llvm.x86.sse2.paddus.w
+ // CHECK: call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_adds_epu16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epu16
- // CHECK: @llvm.x86.sse2.paddus.w
+ // CHECK-NOT: @llvm.x86.sse2.paddus.w
+ // CHECK: call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_adds_epu16(__U,__A,__B);
}
__m256i test_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_adds_epu16
- // CHECK: @llvm.x86.avx2.paddus.w
+ // CHECK-NOT: @llvm.x86.avx2.paddus.w
+ // CHECK: call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_adds_epu16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epu16
- // CHECK: @llvm.x86.avx2.paddus.w
+ // CHECK-NOT: @llvm.x86.avx2.paddus.w
+ // CHECK: call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_adds_epu16(__U,__A,__B);
}
@@ -1519,97 +1527,105 @@ __m256i test_mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
}
__m128i test_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epi8
- // CHECK: @llvm.x86.sse2.psubs.b
+ // CHECK: @llvm.ssub.sat.v16i8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_subs_epi8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epi8
- // CHECK: @llvm.x86.sse2.psubs.b
+ // CHECK: @llvm.ssub.sat.v16i8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_subs_epi8(__U,__A,__B);
}
__m256i test_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epi8
- // CHECK: @llvm.x86.avx2.psubs.b
+ // CHECK: @llvm.ssub.sat.v32i8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_subs_epi8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epi8
- // CHECK: @llvm.x86.avx2.psubs.b
+ // CHECK: @llvm.ssub.sat.v32i8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_subs_epi8(__U,__A,__B);
}
__m128i test_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epi16
- // CHECK: @llvm.x86.sse2.psubs.w
+ // CHECK: @llvm.ssub.sat.v8i16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_subs_epi16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epi16
- // CHECK: @llvm.x86.sse2.psubs.w
+ // CHECK: @llvm.ssub.sat.v8i16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_subs_epi16(__U,__A,__B);
}
__m256i test_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epi16
- // CHECK: @llvm.x86.avx2.psubs.w
+ // CHECK: @llvm.ssub.sat.v16i16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_subs_epi16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epi16
- // CHECK: @llvm.x86.avx2.psubs.w
+ // CHECK: @llvm.ssub.sat.v16i16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_subs_epi16(__U,__A,__B);
}
__m128i test_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epu8
- // CHECK: @llvm.x86.sse2.psubus.b
+ // CHECK-NOT: @llvm.x86.sse2.psubus.b
+ // CHECK: call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_subs_epu8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epu8
- // CHECK: @llvm.x86.sse2.psubus.b
+ // CHECK-NOT: @llvm.x86.sse2.psubus.b
+ // CHECK: call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_subs_epu8(__U,__A,__B);
}
__m256i test_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epu8
- // CHECK: @llvm.x86.avx2.psubus.b
+ // CHECK-NOT: @llvm.x86.avx2.psubus.b
+ // CHECK: call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_subs_epu8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epu8
- // CHECK: @llvm.x86.avx2.psubus.b
+ // CHECK-NOT: @llvm.x86.avx2.psubus.b
+ // CHECK: call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{.*}}, <32 x i8> %{{.*}})
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_subs_epu8(__U,__A,__B);
}
__m128i test_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_subs_epu16
- // CHECK: @llvm.x86.sse2.psubus.w
+ // CHECK-NOT: @llvm.x86.sse2.psubus.w
+ // CHECK: call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_subs_epu16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epu16
- // CHECK: @llvm.x86.sse2.psubus.w
+ // CHECK-NOT: @llvm.x86.sse2.psubus.w
+ // CHECK: call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_subs_epu16(__U,__A,__B);
}
__m256i test_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_subs_epu16
- // CHECK: @llvm.x86.avx2.psubus.w
+ // CHECK-NOT: @llvm.x86.avx2.psubus.w
+ // CHECK: call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_subs_epu16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epu16
- // CHECK: @llvm.x86.avx2.psubus.w
+ // CHECK-NOT: @llvm.x86.avx2.psubus.w
+ // CHECK: call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_subs_epu16(__U,__A,__B);
}
@@ -2156,6 +2172,13 @@ __m128i test_mm_mask_slli_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_slli_epi16(__W, __U, __A, 5);
}
+__m128i test_mm_mask_slli_epi16_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_slli_epi16_2
+ // CHECK: @llvm.x86.sse2.pslli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_slli_epi16(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_slli_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_slli_epi16
// CHECK: @llvm.x86.sse2.pslli.w
@@ -2163,6 +2186,13 @@ __m128i test_mm_maskz_slli_epi16(__mmask8 __U, __m128i __A) {
return _mm_maskz_slli_epi16(__U, __A, 5);
}
+__m128i test_mm_maskz_slli_epi16_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_slli_epi16_2
+ // CHECK: @llvm.x86.sse2.pslli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_slli_epi16(__U, __A, __B);
+}
+
__m256i test_mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_slli_epi16
// CHECK: @llvm.x86.avx2.pslli.w
@@ -2170,6 +2200,13 @@ __m256i test_mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
return _mm256_mask_slli_epi16(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_slli_epi16_2(__m256i __W, __mmask16 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_slli_epi16_2
+ // CHECK: @llvm.x86.avx2.pslli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_slli_epi16(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_slli_epi16
// CHECK: @llvm.x86.avx2.pslli.w
@@ -2177,6 +2214,13 @@ __m256i test_mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A) {
return _mm256_maskz_slli_epi16(__U, __A, 5);
}
+__m256i test_mm256_maskz_slli_epi16_2(__mmask16 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_maskz_slli_epi16_2
+ // CHECK: @llvm.x86.avx2.pslli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_slli_epi16(__U, __A, __B);
+}
+
__m256i test_mm256_srlv_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_srlv_epi16
// CHECK: @llvm.x86.avx512.psrlv.w.256(
@@ -2252,6 +2296,13 @@ __m128i test_mm_mask_srli_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_srli_epi16(__W, __U, __A, 5);
}
+__m128i test_mm_mask_srli_epi16_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_srli_epi16_2
+ // CHECK: @llvm.x86.sse2.psrli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_srli_epi16(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_srli_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srli_epi16
// CHECK: @llvm.x86.sse2.psrli.w
@@ -2259,6 +2310,13 @@ __m128i test_mm_maskz_srli_epi16(__mmask8 __U, __m128i __A) {
return _mm_maskz_srli_epi16(__U, __A, 5);
}
+__m128i test_mm_maskz_srli_epi16_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_srli_epi16_2
+ // CHECK: @llvm.x86.sse2.psrli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_srli_epi16(__U, __A, __B);
+}
+
__m256i test_mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srli_epi16
// CHECK: @llvm.x86.avx2.psrli.w
@@ -2266,6 +2324,13 @@ __m256i test_mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
return _mm256_mask_srli_epi16(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_srli_epi16_2(__m256i __W, __mmask16 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_srli_epi16_2
+ // CHECK: @llvm.x86.avx2.psrli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_srli_epi16(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srli_epi16
// CHECK: @llvm.x86.avx2.psrli.w
@@ -2273,6 +2338,13 @@ __m256i test_mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A) {
return _mm256_maskz_srli_epi16(__U, __A, 5);
}
+__m256i test_mm256_maskz_srli_epi16_2(__mmask16 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srli_epi16_2
+ // CHECK: @llvm.x86.avx2.psrli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_srli_epi16(__U, __A, __B);
+}
+
__m256i test_mm256_srav_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_srav_epi16
// CHECK: @llvm.x86.avx512.psrav.w.256(
@@ -2348,6 +2420,13 @@ __m128i test_mm_mask_srai_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
return _mm_mask_srai_epi16(__W, __U, __A, 5);
}
+__m128i test_mm_mask_srai_epi16_2(__m128i __W, __mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_mask_srai_epi16_2
+ // CHECK: @llvm.x86.sse2.psrai.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_srai_epi16(__W, __U, __A, __B);
+}
+
__m128i test_mm_maskz_srai_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srai_epi16
// CHECK: @llvm.x86.sse2.psrai.w
@@ -2355,6 +2434,13 @@ __m128i test_mm_maskz_srai_epi16(__mmask8 __U, __m128i __A) {
return _mm_maskz_srai_epi16(__U, __A, 5);
}
+__m128i test_mm_maskz_srai_epi16_2(__mmask8 __U, __m128i __A, int __B) {
+ // CHECK-LABEL: @test_mm_maskz_srai_epi16_2
+ // CHECK: @llvm.x86.sse2.psrai.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_srai_epi16(__U, __A, __B);
+}
+
__m256i test_mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srai_epi16
// CHECK: @llvm.x86.avx2.psrai.w
@@ -2362,6 +2448,13 @@ __m256i test_mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
return _mm256_mask_srai_epi16(__W, __U, __A, 5);
}
+__m256i test_mm256_mask_srai_epi16_2(__m256i __W, __mmask16 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_mask_srai_epi16_2
+ // CHECK: @llvm.x86.avx2.psrai.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_srai_epi16(__W, __U, __A, __B);
+}
+
__m256i test_mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srai_epi16
// CHECK: @llvm.x86.avx2.psrai.w
@@ -2369,6 +2462,13 @@ __m256i test_mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A) {
return _mm256_maskz_srai_epi16(__U, __A, 5);
}
+__m256i test_mm256_maskz_srai_epi16_2(__mmask16 __U, __m256i __A, int __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srai_epi16_2
+ // CHECK: @llvm.x86.avx2.psrai.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_srai_epi16(__U, __A, __B);
+}
+
__m128i test_mm_mask_mov_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_mov_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
@@ -2417,6 +2517,12 @@ __m256i test_mm256_maskz_mov_epi8(__mmask32 __U, __m256i __A) {
return _mm256_maskz_mov_epi8(__U, __A);
}
+__m128i test_mm_loadu_epi16(void const *__P) {
+ // CHECK-LABEL: @test_mm_loadu_epi16
+ // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_loadu_epi16(__P);
+}
+
__m128i test_mm_mask_loadu_epi16(__m128i __W, __mmask8 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_loadu_epi16
// CHECK: @llvm.masked.load.v8i16.p0v8i16(<8 x i16>* %{{.*}}, i32 1, <8 x i1> %{{.*}}, <8 x i16> %{{.*}})
@@ -2429,6 +2535,12 @@ __m128i test_mm_maskz_loadu_epi16(__mmask8 __U, void const *__P) {
return _mm_maskz_loadu_epi16(__U, __P);
}
+__m256i test_mm256_loadu_epi16(void const *__P) {
+ // CHECK-LABEL: @test_mm256_loadu_epi16
+ // CHECK: load <4 x i64>, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_loadu_epi16(__P);
+}
+
__m256i test_mm256_mask_loadu_epi16(__m256i __W, __mmask16 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_loadu_epi16
// CHECK: @llvm.masked.load.v16i16.p0v16i16(<16 x i16>* %{{.*}}, i32 1, <16 x i1> %{{.*}}, <16 x i16> %{{.*}})
@@ -2441,6 +2553,12 @@ __m256i test_mm256_maskz_loadu_epi16(__mmask16 __U, void const *__P) {
return _mm256_maskz_loadu_epi16(__U, __P);
}
+__m128i test_mm_loadu_epi8(void const *__P) {
+ // CHECK-LABEL: @test_mm_loadu_epi8
+ // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_loadu_epi8(__P);
+}
+
__m128i test_mm_mask_loadu_epi8(__m128i __W, __mmask16 __U, void const *__P) {
// CHECK-LABEL: @test_mm_mask_loadu_epi8
// CHECK: @llvm.masked.load.v16i8.p0v16i8(<16 x i8>* %{{.*}}, i32 1, <16 x i1> %{{.*}}, <16 x i8> %{{.*}})
@@ -2453,6 +2571,12 @@ __m128i test_mm_maskz_loadu_epi8(__mmask16 __U, void const *__P) {
return _mm_maskz_loadu_epi8(__U, __P);
}
+__m256i test_mm256_loadu_epi8(void const *__P) {
+ // CHECK-LABEL: @test_mm256_loadu_epi8
+ // CHECK: load <4 x i64>, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_loadu_epi8(__P);
+}
+
__m256i test_mm256_mask_loadu_epi8(__m256i __W, __mmask32 __U, void const *__P) {
// CHECK-LABEL: @test_mm256_mask_loadu_epi8
// CHECK: @llvm.masked.load.v32i8.p0v32i8(<32 x i8>* %{{.*}}, i32 1, <32 x i1> %{{.*}}, <32 x i8> %{{.*}})
@@ -2465,24 +2589,48 @@ __m256i test_mm256_maskz_loadu_epi8(__mmask32 __U, void const *__P) {
return _mm256_maskz_loadu_epi8(__U, __P);
}
+void test_mm_storeu_epi16(void *__p, __m128i __a) {
+ // check-label: @test_mm_storeu_epi16
+ // check: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_storeu_epi16(__p, __a);
+}
+
void test_mm_mask_storeu_epi16(void *__P, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_storeu_epi16
// CHECK: @llvm.masked.store.v8i16.p0v8i16(<8 x i16> %{{.*}}, <8 x i16>* %{{.*}}, i32 1, <8 x i1> %{{.*}})
return _mm_mask_storeu_epi16(__P, __U, __A);
}
+void test_mm256_storeu_epi16(void *__P, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_storeu_epi16
+ // CHECK: store <4 x i64> %{{.*}}, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_storeu_epi16(__P, __A);
+}
+
void test_mm256_mask_storeu_epi16(void *__P, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_storeu_epi16
// CHECK: @llvm.masked.store.v16i16.p0v16i16(<16 x i16> %{{.*}}, <16 x i16>* %{{.*}}, i32 1, <16 x i1> %{{.*}})
return _mm256_mask_storeu_epi16(__P, __U, __A);
}
+void test_mm_storeu_epi8(void *__p, __m128i __a) {
+ // check-label: @test_mm_storeu_epi8
+ // check: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}}
+ return _mm_storeu_epi8(__p, __a);
+}
+
void test_mm_mask_storeu_epi8(void *__P, __mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_storeu_epi8
// CHECK: @llvm.masked.store.v16i8.p0v16i8(<16 x i8> %{{.*}}, <16 x i8>* %{{.*}}, i32 1, <16 x i1> %{{.*}})
return _mm_mask_storeu_epi8(__P, __U, __A);
}
+void test_mm256_storeu_epi8(void *__P, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_storeu_epi8
+ // CHECK: store <4 x i64> %{{.*}}, <4 x i64>* %{{.*}}, align 1{{$}}
+ return _mm256_storeu_epi8(__P, __A);
+}
+
void test_mm256_mask_storeu_epi8(void *__P, __mmask32 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_storeu_epi8
// CHECK: @llvm.masked.store.v32i8.p0v32i8(<32 x i8> %{{.*}}, <32 x i8>* %{{.*}}, i32 1, <32 x i1> %{{.*}})
diff --git a/test/CodeGen/avx512vlvbmi2-builtins.c b/test/CodeGen/avx512vlvbmi2-builtins.c
index aceb97616d2b..b512a728a500 100644
--- a/test/CodeGen/avx512vlvbmi2-builtins.c
+++ b/test/CodeGen/avx512vlvbmi2-builtins.c
@@ -172,457 +172,481 @@ __m256i test_mm256_maskz_expandloadu_epi8(__mmask32 __U, void const* __P) {
__m256i test_mm256_mask_shldi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.256
+ // CHECK: @llvm.fshl.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> <i64 47, i64 47, i64 47, i64 47>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
- return _mm256_mask_shldi_epi64(__S, __U, __A, __B, 127);
+ return _mm256_mask_shldi_epi64(__S, __U, __A, __B, 47);
}
__m256i test_mm256_maskz_shldi_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.256
+ // CHECK: @llvm.fshl.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> <i64 63, i64 63, i64 63, i64 63>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_shldi_epi64(__U, __A, __B, 63);
}
__m256i test_mm256_shldi_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.256
+ // CHECK: @llvm.fshl.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> <i64 31, i64 31, i64 31, i64 31>)
return _mm256_shldi_epi64(__A, __B, 31);
}
__m128i test_mm_mask_shldi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.128
+ // CHECK: @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> <i64 47, i64 47>)
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
- return _mm_mask_shldi_epi64(__S, __U, __A, __B, 127);
+ return _mm_mask_shldi_epi64(__S, __U, __A, __B, 47);
}
__m128i test_mm_maskz_shldi_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.128
+ // CHECK: @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> <i64 63, i64 63>)
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_shldi_epi64(__U, __A, __B, 63);
}
__m128i test_mm_shldi_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shldi_epi64
- // CHECK: @llvm.x86.avx512.vpshld.q.128
+ // CHECK: @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> <i64 31, i64 31>)
return _mm_shldi_epi64(__A, __B, 31);
}
__m256i test_mm256_mask_shldi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.256
+ // CHECK: @llvm.fshl.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
- return _mm256_mask_shldi_epi32(__S, __U, __A, __B, 127);
+ return _mm256_mask_shldi_epi32(__S, __U, __A, __B, 7);
}
__m256i test_mm256_maskz_shldi_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.256
+ // CHECK: @llvm.fshl.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
- return _mm256_maskz_shldi_epi32(__U, __A, __B, 63);
+ return _mm256_maskz_shldi_epi32(__U, __A, __B, 15);
}
__m256i test_mm256_shldi_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.256
+ // CHECK: @llvm.fshl.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31>)
return _mm256_shldi_epi32(__A, __B, 31);
}
__m128i test_mm_mask_shldi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.128
+ // CHECK: @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 7, i32 7, i32 7, i32 7>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
- return _mm_mask_shldi_epi32(__S, __U, __A, __B, 127);
+ return _mm_mask_shldi_epi32(__S, __U, __A, __B, 7);
}
__m128i test_mm_maskz_shldi_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.128
+ // CHECK: @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 15, i32 15, i32 15, i32 15>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
- return _mm_maskz_shldi_epi32(__U, __A, __B, 63);
+ return _mm_maskz_shldi_epi32(__U, __A, __B, 15);
}
__m128i test_mm_shldi_epi32(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shldi_epi32
- // CHECK: @llvm.x86.avx512.vpshld.d.128
+ // CHECK: @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 31, i32 31, i32 31, i32 31>)
return _mm_shldi_epi32(__A, __B, 31);
}
__m256i test_mm256_mask_shldi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.256
+ // CHECK: @llvm.fshl.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
- return _mm256_mask_shldi_epi16(__S, __U, __A, __B, 127);
+ return _mm256_mask_shldi_epi16(__S, __U, __A, __B, 3);
}
__m256i test_mm256_maskz_shldi_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.256
+ // CHECK: @llvm.fshl.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> <i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
- return _mm256_maskz_shldi_epi16(__U, __A, __B, 63);
+ return _mm256_maskz_shldi_epi16(__U, __A, __B, 7);
}
__m256i test_mm256_shldi_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.256
+ // CHECK: @llvm.fshl.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> <i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31>)
return _mm256_shldi_epi16(__A, __B, 31);
}
__m128i test_mm_mask_shldi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.128
+ // CHECK: @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
- return _mm_mask_shldi_epi16(__S, __U, __A, __B, 127);
+ return _mm_mask_shldi_epi16(__S, __U, __A, __B, 3);
}
__m128i test_mm_maskz_shldi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.128
+ // CHECK: @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> <i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
- return _mm_maskz_shldi_epi16(__U, __A, __B, 63);
+ return _mm_maskz_shldi_epi16(__U, __A, __B, 7);
}
__m128i test_mm_shldi_epi16(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shldi_epi16
- // CHECK: @llvm.x86.avx512.vpshld.w.128
+ // CHECK: @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> <i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31>)
return _mm_shldi_epi16(__A, __B, 31);
}
__m256i test_mm256_mask_shrdi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.256
+ // CHECK: @llvm.fshr.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> <i64 47, i64 47, i64 47, i64 47>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
- return _mm256_mask_shrdi_epi64(__S, __U, __A, __B, 127);
+ return _mm256_mask_shrdi_epi64(__S, __U, __A, __B, 47);
}
__m256i test_mm256_maskz_shrdi_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.256
+ // CHECK: @llvm.fshr.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> <i64 63, i64 63, i64 63, i64 63>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_shrdi_epi64(__U, __A, __B, 63);
}
__m256i test_mm256_shrdi_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.256
+ // CHECK: @llvm.fshr.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> <i64 31, i64 31, i64 31, i64 31>)
return _mm256_shrdi_epi64(__A, __B, 31);
}
__m128i test_mm_mask_shrdi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.128
+ // CHECK: @llvm.fshr.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> <i64 47, i64 47>)
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
- return _mm_mask_shrdi_epi64(__S, __U, __A, __B, 127);
+ return _mm_mask_shrdi_epi64(__S, __U, __A, __B, 47);
}
__m128i test_mm_maskz_shrdi_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.128
+ // CHECK: @llvm.fshr.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> <i64 63, i64 63>)
// CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_shrdi_epi64(__U, __A, __B, 63);
}
__m128i test_mm_shrdi_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shrdi_epi64
- // CHECK: @llvm.x86.avx512.vpshrd.q.128
+ // CHECK: @llvm.fshr.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> <i64 31, i64 31>)
return _mm_shrdi_epi64(__A, __B, 31);
}
__m256i test_mm256_mask_shrdi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.256
+ // CHECK: @llvm.fshr.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
- return _mm256_mask_shrdi_epi32(__S, __U, __A, __B, 127);
+ return _mm256_mask_shrdi_epi32(__S, __U, __A, __B, 7);
}
__m256i test_mm256_maskz_shrdi_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.256
+ // CHECK: @llvm.fshr.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
- return _mm256_maskz_shrdi_epi32(__U, __A, __B, 63);
+ return _mm256_maskz_shrdi_epi32(__U, __A, __B, 15);
}
__m256i test_mm256_shrdi_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.256
+ // CHECK: @llvm.fshr.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31>)
return _mm256_shrdi_epi32(__A, __B, 31);
}
__m128i test_mm_mask_shrdi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.128
+ // CHECK: @llvm.fshr.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 7, i32 7, i32 7, i32 7>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
- return _mm_mask_shrdi_epi32(__S, __U, __A, __B, 127);
+ return _mm_mask_shrdi_epi32(__S, __U, __A, __B, 7);
}
__m128i test_mm_maskz_shrdi_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.128
+ // CHECK: @llvm.fshr.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 15, i32 15, i32 15, i32 15>)
// CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
- return _mm_maskz_shrdi_epi32(__U, __A, __B, 63);
+ return _mm_maskz_shrdi_epi32(__U, __A, __B, 15);
}
__m128i test_mm_shrdi_epi32(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shrdi_epi32
- // CHECK: @llvm.x86.avx512.vpshrd.d.128
+ // CHECK: @llvm.fshr.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 31, i32 31, i32 31, i32 31>)
return _mm_shrdi_epi32(__A, __B, 31);
}
__m256i test_mm256_mask_shrdi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.256
+ // CHECK: @llvm.fshr.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
- return _mm256_mask_shrdi_epi16(__S, __U, __A, __B, 127);
+ return _mm256_mask_shrdi_epi16(__S, __U, __A, __B, 3);
}
__m256i test_mm256_maskz_shrdi_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.256
+ // CHECK: @llvm.fshr.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> <i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7>)
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
- return _mm256_maskz_shrdi_epi16(__U, __A, __B, 63);
+ return _mm256_maskz_shrdi_epi16(__U, __A, __B, 7);
}
__m256i test_mm256_shrdi_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.256
+ // CHECK: @llvm.fshr.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> <i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31>
return _mm256_shrdi_epi16(__A, __B, 31);
}
__m128i test_mm_mask_shrdi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.128
+ // CHECK: @llvm.fshr.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
- return _mm_mask_shrdi_epi16(__S, __U, __A, __B, 127);
+ return _mm_mask_shrdi_epi16(__S, __U, __A, __B, 3);
}
__m128i test_mm_maskz_shrdi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.128
+ // CHECK: @llvm.fshr.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> <i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7, i16 7>)
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
- return _mm_maskz_shrdi_epi16(__U, __A, __B, 63);
+ return _mm_maskz_shrdi_epi16(__U, __A, __B, 7);
}
__m128i test_mm_shrdi_epi16(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shrdi_epi16
- // CHECK: @llvm.x86.avx512.vpshrd.w.128
+ // CHECK: @llvm.fshr.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> <i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31>)
return _mm_shrdi_epi16(__A, __B, 31);
}
__m256i test_mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshldv.q.256
+ // CHECK: @llvm.fshl.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_shldv_epi64(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_shldv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldv_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.q.256
+ // CHECK: @llvm.fshl.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_shldv_epi64(__U, __S, __A, __B);
}
__m256i test_mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshldv.q.256
+ // CHECK: @llvm.fshl.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_shldv_epi64(__S, __A, __B);
}
__m128i test_mm_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shldv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshldv.q.128
+ // CHECK: @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_shldv_epi64(__S, __U, __A, __B);
}
__m128i test_mm_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shldv_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.q.128
+ // CHECK: @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_shldv_epi64(__U, __S, __A, __B);
}
__m128i test_mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shldv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshldv.q.128
+ // CHECK: @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}})
return _mm_shldv_epi64(__S, __A, __B);
}
__m256i test_mm256_mask_shldv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshldv.d.256
+ // CHECK: @llvm.fshl.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_shldv_epi32(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_shldv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldv_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.d.256
+ // CHECK: @llvm.fshl.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_shldv_epi32(__U, __S, __A, __B);
}
__m256i test_mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshldv.d.256
+ // CHECK: @llvm.fshl.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_shldv_epi32(__S, __A, __B);
}
__m128i test_mm_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shldv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshldv.d.128
+ // CHECK: @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_shldv_epi32(__S, __U, __A, __B);
}
__m128i test_mm_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shldv_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.d.128
+ // CHECK: @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_shldv_epi32(__U, __S, __A, __B);
}
__m128i test_mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shldv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshldv.d.128
+ // CHECK: @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_shldv_epi32(__S, __A, __B);
}
__m256i test_mm256_mask_shldv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shldv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshldv.w.256
+ // CHECK: @llvm.fshl.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_shldv_epi16(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_shldv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shldv_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.w.256
+ // CHECK: @llvm.fshl.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_shldv_epi16(__U, __S, __A, __B);
}
__m256i test_mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shldv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshldv.w.256
+ // CHECK: @llvm.fshl.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_shldv_epi16(__S, __A, __B);
}
__m128i test_mm_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shldv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshldv.w.128
+ // CHECK: @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_shldv_epi16(__S, __U, __A, __B);
}
__m128i test_mm_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shldv_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpshldv.w.128
+ // CHECK: @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_shldv_epi16(__U, __S, __A, __B);
}
__m128i test_mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shldv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshldv.w.128
+ // CHECK: @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
return _mm_shldv_epi16(__S, __A, __B);
}
__m256i test_mm256_mask_shrdv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.q.256
+ // CHECK: @llvm.fshr.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_shrdv_epi64(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_shrdv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdv_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.q.256
+ // CHECK: @llvm.fshr.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_shrdv_epi64(__U, __S, __A, __B);
}
__m256i test_mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.q.256
+ // CHECK: @llvm.fshr.v4i64(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_shrdv_epi64(__S, __A, __B);
}
__m128i test_mm_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shrdv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.q.128
+ // CHECK: @llvm.fshr.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_shrdv_epi64(__S, __U, __A, __B);
}
__m128i test_mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shrdv_epi64
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.q.128
+ // CHECK: @llvm.fshr.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_shrdv_epi64(__U, __S, __A, __B);
}
__m128i test_mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shrdv_epi64
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.q.128
+ // CHECK: @llvm.fshr.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}})
return _mm_shrdv_epi64(__S, __A, __B);
}
__m256i test_mm256_mask_shrdv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.d.256
+ // CHECK: @llvm.fshr.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_shrdv_epi32(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_shrdv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdv_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.d.256
+ // CHECK: @llvm.fshr.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_shrdv_epi32(__U, __S, __A, __B);
}
__m256i test_mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.d.256
+ // CHECK: @llvm.fshr.v8i32(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_shrdv_epi32(__S, __A, __B);
}
__m128i test_mm_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shrdv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.d.128
+ // CHECK: @llvm.fshr.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_shrdv_epi32(__S, __U, __A, __B);
}
__m128i test_mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shrdv_epi32
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.d.128
+ // CHECK: @llvm.fshr.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_shrdv_epi32(__U, __S, __A, __B);
}
__m128i test_mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shrdv_epi32
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.d.128
+ // CHECK: @llvm.fshr.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_shrdv_epi32(__S, __A, __B);
}
__m256i test_mm256_mask_shrdv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_shrdv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.w.256
+ // CHECK: @llvm.fshr.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_shrdv_epi16(__S, __U, __A, __B);
}
__m256i test_mm256_maskz_shrdv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shrdv_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.w.256
+ // CHECK: @llvm.fshr.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_shrdv_epi16(__U, __S, __A, __B);
}
__m256i test_mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_shrdv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.w.256
+ // CHECK: @llvm.fshr.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}})
return _mm256_shrdv_epi16(__S, __A, __B);
}
__m128i test_mm_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_shrdv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.w.128
+ // CHECK: @llvm.fshr.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_shrdv_epi16(__S, __U, __A, __B);
}
__m128i test_mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shrdv_epi16
- // CHECK: @llvm.x86.avx512.maskz.vpshrdv.w.128
+ // CHECK: @llvm.fshr.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_shrdv_epi16(__U, __S, __A, __B);
}
__m128i test_mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_shrdv_epi16
- // CHECK: @llvm.x86.avx512.mask.vpshrdv.w.128
+ // CHECK: @llvm.fshr.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
return _mm_shrdv_epi16(__S, __A, __B);
}
diff --git a/test/CodeGen/block-byref-aggr.c b/test/CodeGen/block-byref-aggr.c
index 962f100638f0..db105768993f 100644
--- a/test/CodeGen/block-byref-aggr.c
+++ b/test/CodeGen/block-byref-aggr.c
@@ -9,11 +9,13 @@ Agg makeAgg(void);
// cause a block copy. rdar://9309454
void test0() {
__block Agg a = {100};
+ ^{ (void)a; };
a = makeAgg();
}
// CHECK-LABEL: define void @test0()
// CHECK: [[A:%.*]] = alloca [[BYREF:%.*]], align 8
+// CHECK-NEXT: alloca <{ i8*, i32, i32, i8*, %{{.*}}*, i8* }>, align 8
// CHECK-NEXT: [[TEMP:%.*]] = alloca [[AGG]], align 4
// CHECK: [[RESULT:%.*]] = call i32 @makeAgg()
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[TEMP]], i32 0, i32 0
@@ -35,11 +37,13 @@ void test0() {
// rdar://11757470
void test1() {
__block Agg a, b;
+ ^{ (void)a; (void)b; };
a = b = makeAgg();
}
// CHECK-LABEL: define void @test1()
// CHECK: [[A:%.*]] = alloca [[A_BYREF:%.*]], align 8
// CHECK-NEXT: [[B:%.*]] = alloca [[B_BYREF:%.*]], align 8
+// CHECK-NEXT: alloca <{ i8*, i32, i32, i8*, %{{.*}}*, i8*, i8* }>, align 8
// CHECK-NEXT: [[TEMP:%.*]] = alloca [[AGG]], align 4
// CHECK: [[RESULT:%.*]] = call i32 @makeAgg()
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[TEMP]], i32 0, i32 0
diff --git a/test/CodeGen/blocks-1.c b/test/CodeGen/blocks-1.c
index 350f7a3bafb8..8589a7bedfff 100644
--- a/test/CodeGen/blocks-1.c
+++ b/test/CodeGen/blocks-1.c
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 %s -emit-llvm -o %t -fblocks
-// RUN: grep "_Block_object_dispose" %t | count 17
-// RUN: grep "__copy_helper_block_" %t | count 14
-// RUN: grep "__destroy_helper_block_" %t | count 14
+// RUN: grep "_Block_object_dispose" %t | count 12
+// RUN: grep "__copy_helper_block_" %t | count 9
+// RUN: grep "__destroy_helper_block_" %t | count 9
// RUN: grep "__Block_byref_object_copy_" %t | count 2
// RUN: grep "__Block_byref_object_dispose_" %t | count 2
// RUN: grep "i32 135)" %t | count 2
-// RUN: grep "_Block_object_assign" %t | count 10
+// RUN: grep "_Block_object_assign" %t | count 5
int printf(const char *, ...);
diff --git a/test/CodeGen/blocks-seq.c b/test/CodeGen/blocks-seq.c
index b3e672976cab..9b47fbf783dd 100644
--- a/test/CodeGen/blocks-seq.c
+++ b/test/CodeGen/blocks-seq.c
@@ -11,6 +11,7 @@ int rhs();
void foo() {
__block int i;
+ ^{ (void)i; };
i = rhs();
i += rhs();
}
diff --git a/test/CodeGen/blocks.c b/test/CodeGen/blocks.c
index 911c63e41d34..6b355b898ed0 100644
--- a/test/CodeGen/blocks.c
+++ b/test/CodeGen/blocks.c
@@ -1,4 +1,10 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - -fblocks | FileCheck %s
+
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i32, i32 }
+
+// CHECK: @{{.*}} = internal constant { i32, i32, i8*, i8*, i8*, i8* } { i32 0, i32 24, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_4_20r to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_4_20r to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* null }, align 4
+// CHECK: @[[BLOCK_DESCRIPTOR_TMP21:.*]] = internal constant { i32, i32, i8*, i8*, i8*, i8* } { i32 0, i32 24, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_4_20r to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_4_20r to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* null }, align 4
+
void (^f)(void) = ^{};
// rdar://6768379
@@ -27,6 +33,32 @@ void (^test1)(void) = ^(void) {
^ { i = 1; }();
};
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_4_20r(i8*, i8*) unnamed_addr
+// CHECK: %[[_ADDR:.*]] = alloca i8*, align 4
+// CHECK-NEXT: %[[_ADDR1:.*]] = alloca i8*, align 4
+// CHECK-NEXT: store i8* %0, i8** %[[_ADDR]], align 4
+// CHECK-NEXT: store i8* %1, i8** %[[_ADDR1]], align 4
+// CHECK-NEXT: %[[V2:.*]] = load i8*, i8** %[[_ADDR1]], align 4
+// CHECK-NEXT: %[[BLOCK_SOURCE:.*]] = bitcast i8* %[[V2]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>*
+// CHECK-NEXT: %[[V3:.*]] = load i8*, i8** %[[_ADDR]], align 4
+// CHECK-NEXT: %[[BLOCK_DEST:.*]] = bitcast i8* %[[V3]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>*
+// CHECK-NEXT: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK_SOURCE]], i32 0, i32 5
+// CHECK-NEXT: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK_DEST]], i32 0, i32 5
+// CHECK-NEXT: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 4
+// CHECK-NEXT: %[[V6:.*]] = bitcast i8** %[[V5]] to i8*
+// CHECK-NEXT: call void @_Block_object_assign(i8* %[[V6]], i8* %[[BLOCKCOPY_SRC]], i32 8)
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_4_20r(i8*) unnamed_addr
+// CHECK: %[[_ADDR:.*]] = alloca i8*, align 4
+// CHECK-NEXT: store i8* %0, i8** %[[_ADDR]], align 4
+// CHECK-NEXT: %[[V1:.*]] = load i8*, i8** %[[_ADDR]], align 4
+// CHECK-NEXT: %[[BLOCK:.*]] = bitcast i8* %[[V1]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>*
+// CHECK-NEXT: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5
+// CHECK-NEXT: %[[V3:.*]] = load i8*, i8** %[[V2]], align 4
+// CHECK-NEXT: call void @_Block_object_dispose(i8* %[[V3]], i32 8)
+// CHECK-NEXT: ret void
+
typedef double ftype(double);
// It's not clear that we *should* support this syntax, but until that decision
// is made, we should support it properly and not crash.
@@ -85,30 +117,8 @@ void testConstCaptureInCopyAndDestroyHelpers() {
__block int i;
(^ { i = x; })();
}
-// CHECK-LABEL: testConstCaptureInCopyAndDestroyHelpers_block_invoke
-
-// CHECK: @__copy_helper_block
-// CHECK: alloca
-// CHECK-NEXT: alloca
-// CHECK-NEXT: store
-// CHECK-NEXT: store
-// CHECK-NEXT: load
-// CHECK-NEXT: bitcast
-// CHECK-NEXT: load
-// CHECK-NEXT: bitcast
-// CHECK-NEXT: getelementptr
-// CHECK-NEXT: getelementptr
-// CHECK-NEXT: load
-// CHECK-NEXT: bitcast
-// CHECK-NEXT: call void @_Block_object_assign
-// CHECK-NEXT: ret
-
-// CHECK: @__destroy_helper_block
-// CHECK: alloca
-// CHECK-NEXT: store
-// CHECK-NEXT: load
-// CHECK-NEXT: bitcast
-// CHECK-NEXT: getelementptr
-// CHECK-NEXT: load
-// CHECK-NEXT: call void @_Block_object_dispose
-// CHECK-NEXT: ret
+// CHECK-LABEL: define void @testConstCaptureInCopyAndDestroyHelpers(
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %{{.*}}, i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i32, i32, i8*, i8*, i8*, i8* }* @[[BLOCK_DESCRIPTOR_TMP21]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 4
+
+// CHECK-LABEL: define internal void @__testConstCaptureInCopyAndDestroyHelpers_block_invoke
diff --git a/test/CodeGen/bmi-builtins.c b/test/CodeGen/bmi-builtins.c
index 91271f0b3599..69eb2bdb807c 100644
--- a/test/CodeGen/bmi-builtins.c
+++ b/test/CodeGen/bmi-builtins.c
@@ -15,9 +15,7 @@
unsigned short test__tzcnt_u16(unsigned short __X) {
// CHECK-LABEL: test__tzcnt_u16
- // CHECK: zext i16 %{{.*}} to i32
- // CHECK: icmp ne i32 %{{.*}}, 0
- // CHECK: i16 @llvm.cttz.i16(i16 %{{.*}}, i1 true)
+ // CHECK: i16 @llvm.cttz.i16(i16 %{{.*}}, i1 false)
return __tzcnt_u16(__X);
}
@@ -57,15 +55,13 @@ unsigned int test__blsr_u32(unsigned int __X) {
unsigned int test__tzcnt_u32(unsigned int __X) {
// CHECK-LABEL: test__tzcnt_u32
- // CHECK: icmp ne i32 %{{.*}}, 0
- // CHECK: i32 @llvm.cttz.i32(i32 %{{.*}}, i1 true)
+ // CHECK: i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
return __tzcnt_u32(__X);
}
int test_mm_tzcnt_32(unsigned int __X) {
// CHECK-LABEL: test_mm_tzcnt_32
- // CHECK: icmp ne i32 %{{.*}}, 0
- // CHECK: i32 @llvm.cttz.i32(i32 %{{.*}}, i1 true)
+ // CHECK: i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
return _mm_tzcnt_32(__X);
}
@@ -105,15 +101,13 @@ unsigned long long test__blsr_u64(unsigned long long __X) {
unsigned long long test__tzcnt_u64(unsigned long long __X) {
// CHECK-LABEL: test__tzcnt_u64
- // CHECK: icmp ne i64 %{{.*}}, 0
- // CHECK: i64 @llvm.cttz.i64(i64 %{{.*}}, i1 true)
+ // CHECK: i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false)
return __tzcnt_u64(__X);
}
long long test_mm_tzcnt_64(unsigned long long __X) {
// CHECK-LABEL: test_mm_tzcnt_64
- // CHECK: icmp ne i64 %{{.*}}, 0
- // CHECK: i64 @llvm.cttz.i64(i64 %{{.*}}, i1 true)
+ // CHECK: i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false)
return _mm_tzcnt_64(__X);
}
@@ -121,9 +115,7 @@ long long test_mm_tzcnt_64(unsigned long long __X) {
unsigned short test_tzcnt_u16(unsigned short __X) {
// CHECK-LABEL: test_tzcnt_u16
- // CHECK: zext i16 %{{.*}} to i32
- // CHECK: icmp ne i32 %{{.*}}, 0
- // CHECK: i16 @llvm.cttz.i16(i16 %{{.*}}, i1 true)
+ // CHECK: i16 @llvm.cttz.i16(i16 %{{.*}}, i1 false)
return _tzcnt_u16(__X);
}
@@ -168,8 +160,7 @@ unsigned int test_blsr_u32(unsigned int __X) {
unsigned int test_tzcnt_u32(unsigned int __X) {
// CHECK-LABEL: test_tzcnt_u32
- // CHECK: icmp ne i32 %{{.*}}, 0
- // CHECK: i32 @llvm.cttz.i32(i32 %{{.*}}, i1 true)
+ // CHECK: i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
return _tzcnt_u32(__X);
}
@@ -215,7 +206,6 @@ unsigned long long test_blsr_u64(unsigned long long __X) {
unsigned long long test_tzcnt_u64(unsigned long long __X) {
// CHECK-LABEL: test_tzcnt_u64
- // CHECK: icmp ne i64 %{{.*}}, 0
- // CHECK: i64 @llvm.cttz.i64(i64 %{{.*}}, i1 true)
+ // CHECK: i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false)
return _tzcnt_u64(__X);
}
diff --git a/test/CodeGen/bool_test.c b/test/CodeGen/bool_test.c
index ead8854e284b..84c775cba4fb 100644
--- a/test/CodeGen/bool_test.c
+++ b/test/CodeGen/bool_test.c
@@ -1,18 +1,18 @@
// REQUIRES: powerpc-registered-target
-// RUN: %clang_cc1 -triple powerpc-apple-macosx10.4.0 -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
int boolsize = sizeof(_Bool);
-// CHECK: boolsize = global i32 4, align 4
+// CHECK: boolsize = global i32 1, align 4
void f(_Bool *x, _Bool *y) {
*x = *y;
}
// CHECK-LABEL: define void @f(
-// CHECK: [[FROMMEM:%.*]] = load i32, i32* %
-// CHECK: [[BOOLVAL:%.*]] = trunc i32 [[FROMMEM]] to i1
-// CHECK: [[TOMEM:%.*]] = zext i1 [[BOOLVAL]] to i32
-// CHECK: store i32 [[TOMEM]]
+// CHECK: [[FROMMEM:%.*]] = load i8, i8* %
+// CHECK: [[BOOLVAL:%.*]] = trunc i8 [[FROMMEM]] to i1
+// CHECK: [[TOMEM:%.*]] = zext i1 [[BOOLVAL]] to i8
+// CHECK: store i8 [[TOMEM]]
// CHECK: ret void
-// CHECK: i32 0, i32 2}
+// CHECK: i8 0, i8 2}
diff --git a/test/CodeGen/builtin-constant-p.c b/test/CodeGen/builtin-constant-p.c
new file mode 100644
index 000000000000..f1cd06ad4aab
--- /dev/null
+++ b/test/CodeGen/builtin-constant-p.c
@@ -0,0 +1,179 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O2 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck --check-prefix=O0 %s
+
+int a = 42;
+
+inline int bcp(int x) {
+ return __builtin_constant_p(x);
+}
+
+/* --- Compound literals */
+
+struct foo { int x, y; };
+
+int y;
+struct foo f = (struct foo){ __builtin_constant_p(y), 42 };
+
+struct foo test0(int expr) {
+ // CHECK: define i64 @test0(i32 %expr)
+ // CHECK: call i1 @llvm.is.constant.i32(i32 %expr)
+ struct foo f = (struct foo){ __builtin_constant_p(expr), 42 };
+ return f;
+}
+
+/* --- Pointer types */
+
+inline int test1_i(int *x) {
+ return *x;
+}
+
+int test1() {
+ // CHECK: define i32 @test1
+ // CHECK: add nsw i32 %0, -13
+ // CHECK-NEXT: call i1 @llvm.is.constant.i32(i32 %sub)
+ return bcp(test1_i(&a) - 13);
+}
+
+int test2() {
+ // CHECK: define i32 @test2
+ // CHECK: ret i32 0
+ return __builtin_constant_p(&a - 13);
+}
+
+inline int test3_i(int *x) {
+ return 42;
+}
+
+int test3() {
+ // CHECK: define i32 @test3
+ // CHECK: ret i32 1
+ return bcp(test3_i(&a) - 13);
+}
+
+/* --- Aggregate types */
+
+int b[] = {1, 2, 3};
+
+int test4() {
+ // CHECK: define i32 @test4
+ // CHECK: ret i32 0
+ return __builtin_constant_p(b);
+}
+
+const char test5_c[] = {1, 2, 3, 0};
+
+int test5() {
+ // CHECK: define i32 @test5
+ // CHECK: ret i32 0
+ return __builtin_constant_p(test5_c);
+}
+
+inline char test6_i(const char *x) {
+ return x[1];
+}
+
+int test6() {
+ // CHECK: define i32 @test6
+ // CHECK: ret i32 0
+ return __builtin_constant_p(test6_i(test5_c));
+}
+
+/* --- Non-constant global variables */
+
+int test7() {
+ // CHECK: define i32 @test7
+ // CHECK: call i1 @llvm.is.constant.i32(i32 %0)
+ return bcp(a);
+}
+
+/* --- Constant global variables */
+
+const int c = 42;
+
+int test8() {
+ // CHECK: define i32 @test8
+ // CHECK: ret i32 1
+ return bcp(c);
+}
+
+/* --- Array types */
+
+int arr[] = { 1, 2, 3 };
+const int c_arr[] = { 1, 2, 3 };
+
+int test9() {
+ // CHECK: define i32 @test9
+ // CHECK: call i1 @llvm.is.constant.i32(i32 %0)
+ return __builtin_constant_p(arr[2]);
+}
+
+int test10() {
+ // CHECK: define i32 @test10
+ // CHECK: ret i32 1
+ return __builtin_constant_p(c_arr[2]);
+}
+
+int test11() {
+ // CHECK: define i32 @test11
+ // CHECK: ret i32 0
+ return __builtin_constant_p(c_arr);
+}
+
+/* --- Function pointers */
+
+int test12() {
+ // CHECK: define i32 @test12
+ // CHECK: ret i32 0
+ return __builtin_constant_p(&test10);
+}
+
+int test13() {
+ // CHECK: define i32 @test13
+ // CHECK: ret i32 1
+ return __builtin_constant_p(&test10 != 0);
+}
+
+typedef unsigned long uintptr_t;
+#define assign(p, v) ({ \
+ uintptr_t _r_a_p__v = (uintptr_t)(v); \
+ if (__builtin_constant_p(v) && _r_a_p__v == (uintptr_t)0) { \
+ union { \
+ uintptr_t __val; \
+ char __c[1]; \
+ } __u = { \
+ .__val = (uintptr_t)_r_a_p__v \
+ }; \
+ *(volatile unsigned int*)&p = *(unsigned int*)(__u.__c); \
+ __u.__val; \
+ } \
+ _r_a_p__v; \
+})
+
+typedef void fn_p(void);
+extern fn_p *dest_p;
+
+static void src_fn(void) {
+}
+
+void test14() {
+ assign(dest_p, src_fn);
+}
+
+extern int test15_v;
+
+struct { const char *t; int a; } test15[] = {
+ { "tag", __builtin_constant_p(test15_v) && !test15_v ? 1 : 0 }
+};
+
+extern char test16_v;
+struct { int a; } test16 = { __builtin_constant_p(test16_v) };
+
+extern unsigned long long test17_v;
+
+void test17() {
+ // O0: define void @test17
+ // O0: call void asm sideeffect "", {{.*}}(i32 -1)
+ // CHECK: define void @test17
+ // CHECK: call void asm sideeffect "", {{.*}}(i32 -1)
+ __asm__ __volatile__("" :: "n"( (__builtin_constant_p(test17_v) || 0) ? 1 : -1));
+}
diff --git a/test/CodeGen/builtin-cpu-is.c b/test/CodeGen/builtin-cpu-is.c
index f2a5f54a0c80..bff3544c1360 100644
--- a/test/CodeGen/builtin-cpu-is.c
+++ b/test/CodeGen/builtin-cpu-is.c
@@ -4,6 +4,8 @@
// global, the bit grab, and the icmp correct.
extern void a(const char *);
+// CHECK: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
+
void intel() {
if (__builtin_cpu_is("intel"))
a("intel");
diff --git a/test/CodeGen/builtin-cpu-supports.c b/test/CodeGen/builtin-cpu-supports.c
index b70f4aca9d43..761f00cf9572 100644
--- a/test/CodeGen/builtin-cpu-supports.c
+++ b/test/CodeGen/builtin-cpu-supports.c
@@ -4,6 +4,9 @@
// global, the bit grab, and the icmp correct.
extern void a(const char *);
+// CHECK: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
+// CHECK: @__cpu_features2 = external dso_local global i32
+
int main() {
__builtin_cpu_init();
@@ -14,7 +17,16 @@ int main() {
// CHECK: [[LOAD:%[^ ]+]] = load i32, i32* getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, { i32, i32, i32, [1 x i32] }* @__cpu_model, i32 0, i32 3, i32 0)
// CHECK: [[AND:%[^ ]+]] = and i32 [[LOAD]], 256
- // CHECK: = icmp ne i32 [[AND]], 0
+ // CHECK: = icmp eq i32 [[AND]], 256
+
+ if (__builtin_cpu_supports("gfni"))
+ a("gfni");
+
+ // CHECK: [[LOAD:%[^ ]+]] = load i32, i32* @__cpu_features2
+ // CHECK: [[AND:%[^ ]+]] = and i32 [[LOAD]], 1
+ // CHECK: = icmp eq i32 [[AND]], 1
return 0;
}
+
+// CHECK: declare dso_local void @__cpu_indicator_init()
diff --git a/test/CodeGen/builtin-memfns.c b/test/CodeGen/builtin-memfns.c
index 48626774531d..27004426819e 100644
--- a/test/CodeGen/builtin-memfns.c
+++ b/test/CodeGen/builtin-memfns.c
@@ -3,6 +3,8 @@
typedef __WCHAR_TYPE__ wchar_t;
typedef __SIZE_TYPE__ size_t;
+void *memcpy(void *, void const *, size_t);
+
// CHECK: @test1
// CHECK: call void @llvm.memset.p0i8.i32
// CHECK: call void @llvm.memset.p0i8.i32
@@ -100,3 +102,19 @@ void test10() {
__builtin_wmemmove(&dest, &src, 4);
}
+// CHECK-LABEL: @test11
+void test11() {
+ typedef struct { int a; } b;
+ int d;
+ b e;
+ // CHECK: call void @llvm.memcpy{{.*}}(
+ memcpy(&d, (char *)&e.a, sizeof(e));
+}
+
+// CHECK-LABEL: @test12
+extern char dest_array[];
+extern char src_array[];
+void test12() {
+ // CHECK: call void @llvm.memcpy{{.*}}(
+ memcpy(&dest_array, &dest_array, 2);
+}
diff --git a/test/CodeGen/builtin-rotate.c b/test/CodeGen/builtin-rotate.c
new file mode 100644
index 000000000000..8fc1701c6c9b
--- /dev/null
+++ b/test/CodeGen/builtin-rotate.c
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+unsigned char rotl8(unsigned char x, unsigned char y) {
+// CHECK-LABEL: rotl8
+// CHECK: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]])
+// CHECK-NEXT: ret i8 [[F]]
+
+ return __builtin_rotateleft8(x, y);
+}
+
+short rotl16(short x, short y) {
+// CHECK-LABEL: rotl16
+// CHECK: [[F:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]])
+// CHECK-NEXT: ret i16 [[F]]
+
+ return __builtin_rotateleft16(x, y);
+}
+
+int rotl32(int x, unsigned int y) {
+// CHECK-LABEL: rotl32
+// CHECK: [[F:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+// CHECK-NEXT: ret i32 [[F]]
+
+ return __builtin_rotateleft32(x, y);
+}
+
+unsigned long long rotl64(unsigned long long x, long long y) {
+// CHECK-LABEL: rotl64
+// CHECK: [[F:%.*]] = call i64 @llvm.fshl.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]])
+// CHECK-NEXT: ret i64 [[F]]
+
+ return __builtin_rotateleft64(x, y);
+}
+
+char rotr8(char x, char y) {
+// CHECK-LABEL: rotr8
+// CHECK: [[F:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]])
+// CHECK-NEXT: ret i8 [[F]]
+
+ return __builtin_rotateright8(x, y);
+}
+
+unsigned short rotr16(unsigned short x, unsigned short y) {
+// CHECK-LABEL: rotr16
+// CHECK: [[F:%.*]] = call i16 @llvm.fshr.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]])
+// CHECK-NEXT: ret i16 [[F]]
+
+ return __builtin_rotateright16(x, y);
+}
+
+unsigned int rotr32(unsigned int x, int y) {
+// CHECK-LABEL: rotr32
+// CHECK: [[F:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+// CHECK-NEXT: ret i32 [[F]]
+
+ return __builtin_rotateright32(x, y);
+}
+
+long long rotr64(long long x, unsigned long long y) {
+// CHECK-LABEL: rotr64
+// CHECK: [[F:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]])
+// CHECK-NEXT: ret i64 [[F]]
+
+ return __builtin_rotateright64(x, y);
+}
+
diff --git a/test/CodeGen/builtin-unpredictable.c b/test/CodeGen/builtin-unpredictable.c
index 30709b0cac68..bdd62e972b05 100644
--- a/test/CodeGen/builtin-unpredictable.c
+++ b/test/CodeGen/builtin-unpredictable.c
@@ -1,10 +1,15 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - %s -O1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - %s -O1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - -x c++ %s -O1 | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck %s --check-prefix=CHECK_O0
// When optimizing, the builtin should be converted to metadata.
// When not optimizing, there should be no metadata created for the builtin.
// In both cases, the builtin should be removed from the code.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void foo();
void branch(int x) {
// CHECK-LABEL: define void @branch(
@@ -42,5 +47,10 @@ int unpredictable_switch(int x) {
return 0;
}
+#ifdef __cplusplus
+}
+#endif
+
+
// CHECK: [[METADATA]] = !{}
diff --git a/test/CodeGen/builtin_clrsb.c b/test/CodeGen/builtin_clrsb.c
new file mode 100644
index 000000000000..c51777ed1222
--- /dev/null
+++ b/test/CodeGen/builtin_clrsb.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+int test__builtin_clrsb(int x) {
+// CHECK-LABEL: test__builtin_clrsb
+// CHECK: [[C:%.*]] = icmp slt i32 [[X:%.*]], 0
+// CHECK-NEXT: [[INV:%.*]] = xor i32 [[X]], -1
+// CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[INV]], i32 [[X]]
+// CHECK-NEXT: [[CTLZ:%.*]] = call i32 @llvm.ctlz.i32(i32 [[SEL]], i1 false)
+// CHECK-NEXT: [[SUB:%.*]] = sub i32 [[CTLZ]], 1
+ return __builtin_clrsb(x);
+}
+
+int test__builtin_clrsbll(long long x) {
+// CHECK-LABEL: test__builtin_clrsbll
+// CHECK: [[C:%.*]] = icmp slt i64 [[X:%.*]], 0
+// CHECK-NEXT: [[INV:%.*]] = xor i64 [[X]], -1
+// CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i64 [[INV]], i64 [[X]]
+// CHECK-NEXT: [[CTLZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[SEL]], i1 false)
+// CHECK-NEXT: [[SUB:%.*]] = sub i64 [[CTLZ]], 1
+// CHECK-NEXT: trunc i64 [[SUB]] to i32
+ return __builtin_clrsbll(x);
+}
diff --git a/test/CodeGen/builtins-hexagon-v66-128B.c b/test/CodeGen/builtins-hexagon-v66-128B.c
new file mode 100644
index 000000000000..a1c4786cf24c
--- /dev/null
+++ b/test/CodeGen/builtins-hexagon-v66-128B.c
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -triple hexagon -target-cpu hexagonv66 -target-feature +hvxv66 -target-feature +hvx-length128b -emit-llvm -o - %s | FileCheck %s
+// REQUIRES: hexagon-registered-target
+
+typedef long HEXAGON_VecPred128 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+typedef long HEXAGON_Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+typedef long HEXAGON_Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(256)));
+
+// CHECK-LABEL: @test1
+// CHECK: call <32 x i32> @llvm.hexagon.V6.vaddcarrysat.128B(<32 x i32> %{{[0-9]+}}, <32 x i32> %{{[0-9]+}}, <1024 x i1> %{{[0-9]+}})
+HEXAGON_Vect1024 test1(void *in, void *out) {
+ HEXAGON_Vect1024 v1, v2;
+ HEXAGON_Vect1024 *p;
+ HEXAGON_VecPred128 q1;
+
+ p = (HEXAGON_Vect1024 *)in;
+ v1 = *p++;
+ v2 = *p++;
+ q1 = *p++;
+
+ return __builtin_HEXAGON_V6_vaddcarrysat_128B(v1, v2, q1);
+}
+
+// CHECK-LABEL: @test26
+// CHECK: call <32 x i32> @llvm.hexagon.V6.vrotr.128B(<32 x i32> %{{[0-9]+}}, <32 x i32> %{{[0-9]+}})
+HEXAGON_Vect1024 test26(void *in, void *out) {
+ HEXAGON_Vect1024 v1, v2;
+ HEXAGON_Vect1024 *p;
+
+ p = (HEXAGON_Vect1024 *)in;
+ v1 = *p++;
+ v2 = *p++;
+
+ return __builtin_HEXAGON_V6_vrotr_128B(v1, v2);
+}
+
+// CHECK-LABEL: @test27
+// CHECK: call <32 x i32> @llvm.hexagon.V6.vsatdw.128B(<32 x i32> %{{[0-9]+}}, <32 x i32> %{{[0-9]+}})
+HEXAGON_Vect1024 test27(void *in, void *out) {
+ HEXAGON_Vect1024 v1, v2;
+ HEXAGON_Vect1024 *p;
+
+ p = (HEXAGON_Vect1024 *)in;
+ v1 = *p++;
+ v2 = *p++;
+
+ return __builtin_HEXAGON_V6_vsatdw_128B(v1, v2);
+}
+
+// CHECK-LABEL: @test28
+// CHECK: call <64 x i32> @llvm.hexagon.V6.vasr.into.128B(<64 x i32> %{{[0-9]+}}, <32 x i32> %{{[0-9]+}}, <32 x i32> %{{[0-9]+}})
+HEXAGON_Vect2048 test28(void *in1, void *in2, void *out) {
+ HEXAGON_Vect1024 v1, v2;
+ HEXAGON_Vect1024 *p1;
+ HEXAGON_Vect2048 *p2;
+ HEXAGON_Vect2048 vr;
+
+ p1 = (HEXAGON_Vect1024 *)in1;
+ v1 = *p1++;
+ v2 = *p1++;
+ p2 = (HEXAGON_Vect2048 *)in2;
+ vr = *p2;
+
+ return __builtin_HEXAGON_V6_vasr_into_128B(vr, v1, v2);
+}
diff --git a/test/CodeGen/builtins-hexagon-v66.c b/test/CodeGen/builtins-hexagon-v66.c
new file mode 100644
index 000000000000..1382f18b4faf
--- /dev/null
+++ b/test/CodeGen/builtins-hexagon-v66.c
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -triple hexagon -target-cpu hexagonv66 -target-feature +hvxv66 -target-feature +hvx-length64b -emit-llvm -o - %s | FileCheck %s
+// REQUIRES: hexagon-registered-target
+
+// CHECK-LABEL: @test1
+// CHECK: call i32 @llvm.hexagon.M2.mnaci(i32 %0, i32 %1, i32 %2)
+int test1(int rx, int rs, int rt) {
+ return __builtin_HEXAGON_M2_mnaci(rx, rs, rt);
+}
+
+// CHECK-LABEL: @test2
+// CHECK: call double @llvm.hexagon.F2.dfadd(double %0, double %1)
+double test2(double rss, double rtt) {
+ return __builtin_HEXAGON_F2_dfadd(rss, rtt);
+}
+
+// CHECK-LABEL: @test3
+// CHECK: call double @llvm.hexagon.F2.dfsub(double %0, double %1)
+double test3(double rss, double rtt) {
+ return __builtin_HEXAGON_F2_dfsub(rss, rtt);
+}
+
+// CHECK-LABEL: @test4
+// CHECK: call i32 @llvm.hexagon.S2.mask(i32 1, i32 2)
+int test4() {
+ return __builtin_HEXAGON_S2_mask(1, 2);
+}
+
+typedef long HEXAGON_VecPred64 __attribute__((__vector_size__(64)))
+ __attribute__((aligned(64)));
+typedef long HEXAGON_Vect512 __attribute__((__vector_size__(64)))
+ __attribute__((aligned(64)));
+typedef long HEXAGON_Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+// CHECK-LABEL: @test5
+// CHECK: call <16 x i32> @llvm.hexagon.V6.vaddcarrysat(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}, <512 x i1> %{{[0-9]+}})
+HEXAGON_Vect512 test5(void *in, void *out) {
+ HEXAGON_Vect512 v1, v2;
+ HEXAGON_Vect512 *p;
+ HEXAGON_VecPred64 q1;
+
+ p = (HEXAGON_Vect512 *)in;
+ v1 = *p++;
+ v2 = *p++;
+ q1 = *p++;
+
+ return __builtin_HEXAGON_V6_vaddcarrysat(v1, v2, q1);
+}
+
+// CHECK-LABEL: @test6
+// CHECK: call <16 x i32> @llvm.hexagon.V6.vrotr(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}})
+HEXAGON_Vect512 test6(void *in, void *out) {
+ HEXAGON_Vect512 v1, v2;
+ HEXAGON_Vect512 *p;
+
+ p = (HEXAGON_Vect512 *)in;
+ v1 = *p++;
+ v2 = *p++;
+
+ return __builtin_HEXAGON_V6_vrotr(v1, v2);
+}
+
+// CHECK-LABEL: @test7
+// CHECK: call <16 x i32> @llvm.hexagon.V6.vsatdw(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}})
+HEXAGON_Vect512 test7(void *in, void *out) {
+ HEXAGON_Vect512 v1, v2;
+ HEXAGON_Vect512 *p;
+
+ p = (HEXAGON_Vect512 *)in;
+ v1 = *p++;
+ v2 = *p++;
+
+ return __builtin_HEXAGON_V6_vsatdw(v1, v2);
+}
+
+// CHECK-LABEL: @test8
+// CHECK: call <32 x i32> @llvm.hexagon.V6.vasr.into(<32 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}})
+HEXAGON_Vect1024 test8(void *in1, void *in2, void *out) {
+ HEXAGON_Vect512 v1, v2;
+ HEXAGON_Vect512 *p1;
+ HEXAGON_Vect1024 *p2;
+ HEXAGON_Vect1024 vr;
+
+ p1 = (HEXAGON_Vect512 *)in1;
+ v1 = *p1++;
+ v2 = *p1++;
+ p2 = (HEXAGON_Vect1024 *)in2;
+ vr = *p2;
+
+ return __builtin_HEXAGON_V6_vasr_into(vr, v1, v2);
+}
diff --git a/test/CodeGen/builtins-hexagon.c b/test/CodeGen/builtins-hexagon.c
index b4c0642ef3c1..9a1b733da5cd 100644
--- a/test/CodeGen/builtins-hexagon.c
+++ b/test/CodeGen/builtins-hexagon.c
@@ -426,8 +426,6 @@ void test() {
__builtin_HEXAGON_A5_vaddhubs(0, 0);
// CHECK: @llvm.hexagon.A6.vcmpbeq.notany
__builtin_HEXAGON_A6_vcmpbeq_notany(0, 0);
- // CHECK: @llvm.hexagon.A6.vcmpbeq.notany.128B
- __builtin_HEXAGON_A6_vcmpbeq_notany_128B(0, 0);
// CHECK: @llvm.hexagon.C2.all8
__builtin_HEXAGON_C2_all8(0);
// CHECK: @llvm.hexagon.C2.and
@@ -1400,8 +1398,6 @@ void test() {
__builtin_HEXAGON_S2_brev(0);
// CHECK: @llvm.hexagon.S2.brevp
__builtin_HEXAGON_S2_brevp(0);
- // CHECK: @llvm.hexagon.S2.cabacencbin
- __builtin_HEXAGON_S2_cabacencbin(0, 0, 0);
// CHECK: @llvm.hexagon.S2.cl0
__builtin_HEXAGON_S2_cl0(0);
// CHECK: @llvm.hexagon.S2.cl0p
diff --git a/test/CodeGen/builtins-mips-msa-error.c b/test/CodeGen/builtins-mips-msa-error.c
index 11750922bb4f..0454a19b1cd2 100644
--- a/test/CodeGen/builtins-mips-msa-error.c
+++ b/test/CodeGen/builtins-mips-msa-error.c
@@ -1,18 +1,22 @@
// REQUIRES: mips-registered-target
-// RUN: not %clang_cc1 -triple mips-unknown-linux-gnu -fsyntax-only %s \
+// RUN: %clang_cc1 -triple mips-unknown-linux-gnu -fsyntax-only %s \
// RUN: -target-feature +msa -target-feature +fp64 \
-// RUN: -mfloat-abi hard -o - 2>&1 | FileCheck %s
+// RUN: -verify -mfloat-abi hard -o - 2>&1
#include <msa.h>
void test(void) {
v16i8 v16i8_a = (v16i8) {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ v16i8 v16i8_b = (v16i8) {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
v16i8 v16i8_r;
v8i16 v8i16_a = (v8i16) {0, 1, 2, 3, 4, 5, 6, 7};
+ v8i16 v8i16_b = (v8i16) {8, 9, 10, 11, 12, 13, 14, 15};
v8i16 v8i16_r;
v4i32 v4i32_a = (v4i32) {0, 1, 2, 3};
+ v4i32 v4i32_b = (v4i32) {4, 5, 6, 7};
v4i32 v4i32_r;
v2i64 v2i64_a = (v2i64) {0, 1};
+ v2i64 v2i64_b = (v2i64) {3, 4};
v2i64 v2i64_r;
v16u8 v16u8_a = (v16u8) {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
@@ -24,388 +28,385 @@ void test(void) {
v2u64 v2u64_a = (v2u64) {0, 1};
v2u64 v2u64_r;
-
int int_r;
long long ll_r;
- v16u8_r = __msa_addvi_b(v16u8_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_addvi_h(v8u16_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_addvi_w(v4u32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_addvi_d(v2u64_a, 32); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_andi_b(v16i8_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v8i16_r = __msa_andi_b(v8i16_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v4i32_r = __msa_andi_b(v4i32_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v2i64_r = __msa_andi_b(v2i64_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bclri_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_bclri_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_bclri_w(v4i32_a, 33); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_bclri_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_binsli_b(v16i8_r, v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_binsli_h(v8i16_r, v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_binsli_w(v4i32_r, v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_binsli_d(v2i64_r, v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_binsri_b(v16i8_r, v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_binsri_h(v8i16_r, v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_binsri_w(v4i32_r, v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_binsri_d(v2i64_r, v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_bmnzi_b(v16i8_r, v16i8_a, 256); // expected-error {{argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bmzi_b(v16i8_r, v16i8_a, 256); // expected-error {{argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bnegi_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_bnegi_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_bnegi_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_bnegi_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_bseli_b(v16i8_r, v16i8_a, 256); // expected-error {{argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bseti_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_bseti_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_bseti_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_bseti_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_ceqi_b(v16i8_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_ceqi_h(v8i16_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_ceqi_w(v4i32_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_ceqi_d(v2i64_a, 16); // expected-error {{argument should be a value from -16 to 15}}
-
- v16i8_r = __msa_clei_s_b(v16i8_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_clei_s_h(v8i16_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_clei_s_w(v4i32_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_clei_s_d(v2i64_a, 16); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_clei_u_b(v16u8_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_clei_u_h(v8u16_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_clei_u_w(v4u32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_clei_u_d(v2u64_a, 32); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_clti_s_b(v16i8_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_clti_s_h(v8i16_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_clti_s_w(v4i32_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_clti_s_d(v2i64_a, 16); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_clti_u_b(v16u8_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_clti_u_h(v8u16_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_clti_u_w(v4u32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_clti_u_d(v2u64_a, 32); // expected-error {{argument should be a value from 0 to 31}}
-
- int_r = __msa_copy_s_b(v16i8_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- int_r = __msa_copy_s_h(v8i16_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- int_r = __msa_copy_s_w(v4i32_a, 4); // expected-error {{argument should be a value from 0 to 3}}
- ll_r = __msa_copy_s_d(v2i64_a, 2); // expected-error {{argument should be a value from 0 to 1}}
-
- int_r = __msa_copy_u_b(v16u8_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- int_r = __msa_copy_u_h(v8u16_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- int_r = __msa_copy_u_w(v4u32_a, 4); // expected-error {{argument should be a value from 0 to 3}}
- ll_r = __msa_copy_u_d(v2i64_a, 2); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_insve_b(v16i8_r, 16, v16i8_a); // expected-error {{argument should be a value from 0 to 15}}
- v8i16_r = __msa_insve_h(v8i16_r, 8, v8i16_a); // expected-error {{argument should be a value from 0 to 7}}
- v4i32_r = __msa_insve_w(v4i32_r, 4, v4i32_a); // expected-error {{argument should be a value from 0 to 3}}
- v2i64_r = __msa_insve_d(v2i64_r, 2, v2i64_a); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_ld_b(&v16i8_a, 23); // expected-error {{argument should be a multiple of 16}}
- v8i16_r = __msa_ld_h(&v8i16_a, 77); // expected-error {{argument should be a multiple of 16}}
- v4i32_r = __msa_ld_w(&v4i32_a, 14); // expected-error {{argument should be a multiple of 16}}
- v2i64_r = __msa_ld_d(&v2i64_a, 23); // expected-error {{argument should be a multiple of 16}}
-
- v16i8_r = __msa_ld_b(&v16i8_a, 512); // expected-error {{argument should be a value from -512 to 511}}
- v8i16_r = __msa_ld_h(&v8i16_a, 512); // expected-error {{argument should be a value from -512 to 511}}
- v4i32_r = __msa_ld_w(&v4i32_a, 512); // expected-error {{argument should be a value from -512 to 511}}
- v2i64_r = __msa_ld_d(&v2i64_a, 512); // expected-error {{argument should be a value from -512 to 511}}
-
- v16i8_r = __msa_ldi_b(256); // expected-error {{argument should be a value from -128 to 255}}
- v8i16_r = __msa_ldi_h(512); // expected-error {{argument should be a value from -512 to 511}}
- v4i32_r = __msa_ldi_w(512); // expected-error {{argument should be a value from -512 to 511}}
- v2i64_r = __msa_ldi_d(512); // expected-error {{argument should be a value from -512 to 511}}
-
- v16i8_r = __msa_maxi_s_b(v16i8_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_maxi_s_h(v8i16_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_maxi_s_w(v4i32_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_maxi_s_d(v2i64_a, 16); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_maxi_u_b(v16u8_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_maxi_u_h(v8u16_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_maxi_u_w(v4u32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_maxi_u_d(v2u64_a, 32); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_mini_s_b(v16i8_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_mini_s_h(v8i16_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_mini_s_w(v4i32_a, 16); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_mini_s_d(v2i64_a, 16); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_mini_u_b(v16u8_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_mini_u_h(v8u16_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_mini_u_w(v4u32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_mini_u_d(v2u64_a, 32); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_nori_b(v16i8_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_ori_b(v16i8_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_sat_s_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_sat_s_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_sat_s_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_sat_s_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_sat_u_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_sat_u_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_sat_u_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_sat_u_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_shf_b(v16i8_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v8i16_r = __msa_shf_h(v8i16_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v4i32_r = __msa_shf_w(v4i32_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_sldi_b(v16i8_r, v16i8_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v8i16_r = __msa_sldi_h(v8i16_r, v8i16_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v4i32_r = __msa_sldi_w(v4i32_r, v4i32_a, 4); // expected-error {{argument should be a value from 0 to 3}}
- v2i64_r = __msa_sldi_d(v2i64_r, v2i64_a, 2); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_slli_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_slli_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_slli_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_slli_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_splati_b(v16i8_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v8i16_r = __msa_splati_h(v8i16_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v4i32_r = __msa_splati_w(v4i32_a, 4); // expected-error {{argument should be a value from 0 to 3}}
- v2i64_r = __msa_splati_d(v2i64_a, 2); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_srai_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srai_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srai_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srai_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_srari_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srari_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srari_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srari_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_srli_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srli_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srli_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srli_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_srlri_b(v16i8_a, 8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srlri_h(v8i16_a, 16); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srlri_w(v4i32_a, 32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srlri_d(v2i64_a, 64); // expected-error {{argument should be a value from 0 to 63}}
-
- __msa_st_b(v16i8_b, &v16i8_a, 52); // expected-error {{argument should be a multiple of 16}}
- __msa_st_h(v8i16_b, &v8i16_a, 51); // expected-error {{argument should be a multiple of 16}}
- __msa_st_w(v4i32_b, &v4i32_a, 51); // expected-error {{argument should be a multiple of 16}}
- __msa_st_d(v2i64_b, &v2i64_a, 12); // expected-error {{argument should be a multiple of 16}}
-
- __msa_st_b(v16i8_b, &v16i8_a, 512); // expected-error {{argument should be a value from -512 to 511}}
- __msa_st_h(v8i16_b, &v8i16_a, 512); // expected-error {{argument should be a value from -512 to 511}}
- __msa_st_w(v4i32_b, &v4i32_a, 512); // expected-error {{argument should be a value from -512 to 511}}
- __msa_st_d(v2i64_b, &v2i64_a, 512); // expected-error {{argument should be a value from -512 to 511}}
-
- v16i8_r = __msa_subvi_b(v16i8_a, 256); // expected-error {{argument should be a value from 0 to 31}}
- v8i16_r = __msa_subvi_h(v8i16_a, 256); // expected-error {{argument should be a value from 0 to 31}}
- v4i32_r = __msa_subvi_w(v4i32_a, 256); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_subvi_d(v2i64_a, 256); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_xori_b(v16i8_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v8i16_r = __msa_xori_b(v8i16_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v4i32_r = __msa_xori_b(v4i32_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v2i64_r = __msa_xori_b(v2i64_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16u8_r = __msa_xori_b(v16u8_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v8u16_r = __msa_xori_b(v8u16_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v4u32_r = __msa_xori_b(v4u32_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
- v2u64_r = __msa_xori_b(v2u64_a, 256); // CHECK: warning: argument should be a value from 0 to 255}}
+ v16u8_r = __msa_addvi_b(v16u8_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_addvi_h(v8u16_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_addvi_w(v4u32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_addvi_d(v2u64_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_andi_b(v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v8i16_r = __msa_andi_b(v8i16_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v4i32_r = __msa_andi_b(v4i32_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v2i64_r = __msa_andi_b(v2i64_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bclri_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_bclri_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_bclri_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_bclri_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_binsli_b(v16i8_r, v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_binsli_h(v8i16_r, v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_binsli_w(v4i32_r, v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_binsli_d(v2i64_r, v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_binsri_b(v16i8_r, v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_binsri_h(v8i16_r, v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_binsri_w(v4i32_r, v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_binsri_d(v2i64_r, v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_bmnzi_b(v16i8_r, v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bmzi_b(v16i8_r, v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bnegi_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_bnegi_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_bnegi_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_bnegi_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_bseli_b(v16i8_r, v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bseti_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_bseti_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_bseti_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_bseti_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_ceqi_b(v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_ceqi_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_ceqi_w(v4i32_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_ceqi_d(v2i64_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+
+ v16i8_r = __msa_clei_s_b(v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_clei_s_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_clei_s_w(v4i32_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_clei_s_d(v2i64_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_clei_u_b(v16u8_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_clei_u_h(v8u16_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_clei_u_w(v4u32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_clei_u_d(v2u64_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_clti_s_b(v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_clti_s_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_clti_s_w(v4i32_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_clti_s_d(v2i64_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_clti_u_b(v16u8_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_clti_u_h(v8u16_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_clti_u_w(v4u32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_clti_u_d(v2u64_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+
+ int_r = __msa_copy_s_b(v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ int_r = __msa_copy_s_h(v8i16_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ int_r = __msa_copy_s_w(v4i32_a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ ll_r = __msa_copy_s_d(v2i64_a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+
+ int_r = __msa_copy_u_b(v16u8_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ int_r = __msa_copy_u_h(v8u16_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ int_r = __msa_copy_u_w(v4u32_a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ ll_r = __msa_copy_u_d(v2i64_a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+
+ v16i8_r = __msa_insve_b(v16i8_r, 16, v16i8_a); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v8i16_r = __msa_insve_h(v8i16_r, 8, v8i16_a); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v4i32_r = __msa_insve_w(v4i32_r, 4, v4i32_a); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ v2i64_r = __msa_insve_d(v2i64_r, 2, v2i64_a); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+
+ v8i16_r = __msa_ld_h(&v8i16_a, 77); // expected-error {{argument should be a multiple of 2}}
+ v4i32_r = __msa_ld_w(&v4i32_a, 14); // expected-error {{argument should be a multiple of 4}}
+ v2i64_r = __msa_ld_d(&v2i64_a, 23); // expected-error {{argument should be a multiple of 8}}
+
+ v16i8_r = __msa_ld_b(&v16i8_a, 512); // expected-error {{argument value 512 is outside the valid range [-512, 511]}}
+ v8i16_r = __msa_ld_h(&v8i16_a, 1024); // expected-error {{argument value 1024 is outside the valid range [-1024, 1022]}}
+ v4i32_r = __msa_ld_w(&v4i32_a, 2048); // expected-error {{argument value 2048 is outside the valid range [-2048, 2044]}}
+ v2i64_r = __msa_ld_d(&v2i64_a, 4096); // expected-error {{argument value 4096 is outside the valid range [-4096, 4088]}}
+
+ v16i8_r = __msa_ldi_b(256); // expected-error {{argument value 256 is outside the valid range [-128, 255]}}
+ v8i16_r = __msa_ldi_h(512); // expected-error {{argument value 512 is outside the valid range [-512, 511]}}
+ v4i32_r = __msa_ldi_w(512); // expected-error {{argument value 512 is outside the valid range [-512, 511]}}
+ v2i64_r = __msa_ldi_d(512); // expected-error {{argument value 512 is outside the valid range [-512, 511]}}
+
+ v16i8_r = __msa_maxi_s_b(v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_maxi_s_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_maxi_s_w(v4i32_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_maxi_s_d(v2i64_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_maxi_u_b(v16u8_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_maxi_u_h(v8u16_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_maxi_u_w(v4u32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_maxi_u_d(v2u64_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_mini_s_b(v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_mini_s_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_mini_s_w(v4i32_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_mini_s_d(v2i64_a, 16); // expected-error {{argument value 16 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_mini_u_b(v16u8_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_mini_u_h(v8u16_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_mini_u_w(v4u32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_mini_u_d(v2u64_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_nori_b(v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_ori_b(v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_sat_s_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_sat_s_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_sat_s_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_sat_s_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_sat_u_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_sat_u_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_sat_u_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_sat_u_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_shf_b(v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v8i16_r = __msa_shf_h(v8i16_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v4i32_r = __msa_shf_w(v4i32_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_sldi_b(v16i8_r, v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v8i16_r = __msa_sldi_h(v8i16_r, v8i16_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v4i32_r = __msa_sldi_w(v4i32_r, v4i32_a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ v2i64_r = __msa_sldi_d(v2i64_r, v2i64_a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+
+ v16i8_r = __msa_slli_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_slli_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_slli_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_slli_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_splati_b(v16i8_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v8i16_r = __msa_splati_h(v8i16_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v4i32_r = __msa_splati_w(v4i32_a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ v2i64_r = __msa_splati_d(v2i64_a, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+
+ v16i8_r = __msa_srai_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srai_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srai_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srai_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_srari_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srari_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srari_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srari_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_srli_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srli_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srli_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srli_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_srlri_b(v16i8_a, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srlri_h(v8i16_a, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srlri_w(v4i32_a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srlri_d(v2i64_a, 64); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
+
+ __msa_st_h(v8i16_b, &v8i16_a, 51); // expected-error {{argument should be a multiple of 2}}
+ __msa_st_w(v4i32_b, &v4i32_a, 51); // expected-error {{argument should be a multiple of 4}}
+ __msa_st_d(v2i64_b, &v2i64_a, 12); // expected-error {{argument should be a multiple of 8}}
+
+ __msa_st_b(v16i8_b, &v16i8_a, 512); // expected-error {{argument value 512 is outside the valid range [-512, 511]}}
+ __msa_st_h(v8i16_b, &v8i16_a, 1024); // expected-error {{argument value 1024 is outside the valid range [-1024, 1022]}}
+ __msa_st_w(v4i32_b, &v4i32_a, 2048); // expected-error {{argument value 2048 is outside the valid range [-2048, 2044]}}
+ __msa_st_d(v2i64_b, &v2i64_a, 4096); // expected-error {{argument value 4096 is outside the valid range [-4096, 4088]}}
+
+ v16i8_r = __msa_subvi_b(v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 31]}}
+ v8i16_r = __msa_subvi_h(v8i16_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 31]}}
+ v4i32_r = __msa_subvi_w(v4i32_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_subvi_d(v2i64_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_xori_b(v16i8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v8i16_r = __msa_xori_b(v8i16_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v4i32_r = __msa_xori_b(v4i32_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v2i64_r = __msa_xori_b(v2i64_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+
+ v16u8_r = __msa_xori_b(v16u8_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v8u16_r = __msa_xori_b(v8u16_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v4u32_r = __msa_xori_b(v4u32_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
+ v2u64_r = __msa_xori_b(v2u64_a, 256); // expected-error {{argument value 256 is outside the valid range [0, 255]}}
// Test the lower bounds
- v16u8_r = __msa_addvi_b(v16u8_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_addvi_h(v8u16_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_addvi_w(v4u32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_addvi_d(v2u64_a, -1); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_andi_b(v16i8_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v8i16_r = __msa_andi_b(v8i16_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v4i32_r = __msa_andi_b(v4i32_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v2i64_r = __msa_andi_b(v2i64_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bclri_b(v16i8_a, -1); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_bclri_h(v8i16_a, -1); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_bclri_w(v4i32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_bclri_d(v2i64_a, -1); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_binsli_b(v16i8_r, v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_binsli_h(v8i16_r, v8i16_a, -1); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_binsli_w(v4i32_r, v4i32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_binsli_d(v2i64_r, v2i64_a, -1); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_binsri_b(v16i8_r, v16i8_a, -1); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_binsri_h(v8i16_r, v8i16_a, -1); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_binsri_w(v4i32_r, v4i32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_binsri_d(v2i64_r, v2i64_a, -1); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_bmnzi_b(v16i8_r, v16i8_a, -1); // expected-error {{argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bmzi_b(v16i8_r, v16i8_a, -1); // expected-error {{argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bnegi_b(v16i8_a, -1); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_bnegi_h(v8i16_a, -1); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_bnegi_w(v4i32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_bnegi_d(v2i64_a, -1); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_bseli_b(v16i8_r, v16i8_a, -1); // expected-error {{argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_bseti_b(v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_bseti_h(v8i16_a, -1); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_bseti_w(v4i32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_bseti_d(v2i64_a, -1); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_ceqi_b(v16i8_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_ceqi_h(v8i16_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_ceqi_w(v4i32_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_ceqi_d(v2i64_a, -17); // expected-error {{argument should be a value from -16 to 15}}
-
- v16i8_r = __msa_clei_s_b(v16i8_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_clei_s_h(v8i16_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_clei_s_w(v4i32_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_clei_s_d(v2i64_a, -17); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_clei_u_b(v16u8_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_clei_u_h(v8u16_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_clei_u_w(v4u32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_clei_u_d(v2u64_a, -1); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_clti_s_b(v16i8_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_clti_s_h(v8i16_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_clti_s_w(v4i32_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_clti_s_d(v2i64_a, -17); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_clti_u_b(v16u8_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_clti_u_h(v8u16_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_clti_u_w(v4u32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_clti_u_d(v2u64_a, -1); // expected-error {{argument should be a value from 0 to 31}}
-
- int_r = __msa_copy_s_b(v16i8_a, -1); // expected-error {{argument should be a value from 0 to 15}}
- int_r = __msa_copy_s_h(v8i16_a, -1); // expected-error {{argument should be a value from 0 to 7}}
- int_r = __msa_copy_s_w(v4i32_a, -1); // expected-error {{argument should be a value from 0 to 3}}
- ll_r = __msa_copy_s_d(v2i64_a, -1); // expected-error {{argument should be a value from 0 to 1}}
-
- int_r = __msa_copy_u_b(v16u8_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- int_r = __msa_copy_u_h(v8u16_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- int_r = __msa_copy_u_w(v4u32_a, -4); // expected-error {{argument should be a value from 0 to 3}}
- ll_r = __msa_copy_u_d(v2i64_a, -2); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_insve_b(v16i8_r, 16, v16i8_a); // expected-error {{argument should be a value from 0 to 15}}
- v8i16_r = __msa_insve_h(v8i16_r, 8, v8i16_a); // expected-error {{argument should be a value from 0 to 7}}
- v4i32_r = __msa_insve_w(v4i32_r, 4, v4i32_a); // expected-error {{argument should be a value from 0 to 3}}
- v2i64_r = __msa_insve_d(v2i64_r, 2, v2i64_a); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_ld_b(&v16i8_a, -513); // expected-error {{argument should be a value from -512 to 511}}
- v8i16_r = __msa_ld_h(&v8i16_a, -513); // expected-error {{argument should be a value from -512 to 511}}
- v4i32_r = __msa_ld_w(&v4i32_a, -513); // expected-error {{argument should be a value from -512 to 511}}
- v2i64_r = __msa_ld_d(&v2i64_a, -513); // expected-error {{argument should be a value from -512 to 511}}
-
- v16i8_r = __msa_ldi_b(-129); // expected-error {{argument should be a value from -128 to 255}}
- v8i16_r = __msa_ldi_h(-513); // expected-error {{argument should be a value from -512 to 511}}
- v4i32_r = __msa_ldi_w(-513); // expected-error {{argument should be a value from -512 to 511}}
- v2i64_r = __msa_ldi_d(-513); // expected-error {{argument should be a value from -512 to 511}}
-
- v16i8_r = __msa_maxi_s_b(v16i8_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_maxi_s_h(v8i16_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_maxi_s_w(v4i32_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_maxi_s_d(v2i64_a, -17); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_maxi_u_b(v16u8_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_maxi_u_h(v8u16_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_maxi_u_w(v4u32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_maxi_u_d(v2u64_a, -1); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_mini_s_b(v16i8_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v8i16_r = __msa_mini_s_h(v8i16_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v4i32_r = __msa_mini_s_w(v4i32_a, -17); // expected-error {{argument should be a value from -16 to 15}}
- v2i64_r = __msa_mini_s_d(v2i64_a, -17); // expected-error {{argument should be a value from -16 to 15}}
-
- v16u8_r = __msa_mini_u_b(v16u8_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v8u16_r = __msa_mini_u_h(v8u16_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v4u32_r = __msa_mini_u_w(v4u32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2u64_r = __msa_mini_u_d(v2u64_a, -1); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_nori_b(v16i8_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_ori_b(v16i8_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_sat_s_b(v16i8_a, -1); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_sat_s_h(v8i16_a, -1); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_sat_s_w(v4i32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_sat_s_d(v2i64_a, -1); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_sat_u_b(v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_sat_u_h(v8i16_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_sat_u_w(v4i32_a, -32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_sat_u_d(v2i64_a, -64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_shf_b(v16i8_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v8i16_r = __msa_shf_h(v8i16_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v4i32_r = __msa_shf_w(v4i32_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16i8_r = __msa_sldi_b(v16i8_r, v16i8_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v8i16_r = __msa_sldi_h(v8i16_r, v8i16_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v4i32_r = __msa_sldi_w(v4i32_r, v4i32_a, -4); // expected-error {{argument should be a value from 0 to 3}}
- v2i64_r = __msa_sldi_d(v2i64_r, v2i64_a, -2); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_slli_b(v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_slli_h(v8i16_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_slli_w(v4i32_a, -32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_slli_d(v2i64_a, -64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_splati_b(v16i8_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v8i16_r = __msa_splati_h(v8i16_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v4i32_r = __msa_splati_w(v4i32_a, -4); // expected-error {{argument should be a value from 0 to 3}}
- v2i64_r = __msa_splati_d(v2i64_a, -2); // expected-error {{argument should be a value from 0 to 1}}
-
- v16i8_r = __msa_srai_b(v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srai_h(v8i16_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srai_w(v4i32_a, -32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srai_d(v2i64_a, -64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_srari_b(v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srari_h(v8i16_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srari_w(v4i32_a, -32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srari_d(v2i64_a, -64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_srli_b(v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srli_h(v8i16_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srli_w(v4i32_a, -32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srli_d(v2i64_a, -64); // expected-error {{argument should be a value from 0 to 63}}
-
- v16i8_r = __msa_srlri_b(v16i8_a, -8); // expected-error {{argument should be a value from 0 to 7}}
- v8i16_r = __msa_srlri_h(v8i16_a, -17); // expected-error {{argument should be a value from 0 to 15}}
- v4i32_r = __msa_srlri_w(v4i32_a, -32); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_srlri_d(v2i64_a, -64); // expected-error {{argument should be a value from 0 to 63}}
-
- __msa_st_b(v16i8_b, &v16i8_a, -513); // expected-error {{argument should be a value from -512 to 511}}
- __msa_st_h(v8i16_b, &v8i16_a, -513); // expected-error {{argument should be a value from -512 to 511}}
- __msa_st_w(v4i32_b, &v4i32_a, -513); // expected-error {{argument should be a value from -512 to 511}}
- __msa_st_d(v2i64_b, &v2i64_a, -513); // expected-error {{argument should be a value from -512 to 511}}
-
- v16i8_r = __msa_subvi_b(v16i8_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v8i16_r = __msa_subvi_h(v8i16_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v4i32_r = __msa_subvi_w(v4i32_a, -1); // expected-error {{argument should be a value from 0 to 31}}
- v2i64_r = __msa_subvi_d(v2i64_a, -1); // expected-error {{argument should be a value from 0 to 31}}
-
- v16i8_r = __msa_xori_b(v16i8_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v8i16_r = __msa_xori_b(v8i16_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v4i32_r = __msa_xori_b(v4i32_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v2i64_r = __msa_xori_b(v2i64_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
-
- v16u8_r = __msa_xori_b(v16u8_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v8u16_r = __msa_xori_b(v8u16_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v4u32_r = __msa_xori_b(v4u32_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
- v2u64_r = __msa_xori_b(v2u64_a, -1); // CHECK: warning: argument should be a value from 0 to 255}}
+ v16u8_r = __msa_addvi_b(v16u8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_addvi_h(v8u16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_addvi_w(v4u32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_addvi_d(v2u64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_andi_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v8i16_r = __msa_andi_b(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v4i32_r = __msa_andi_b(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v2i64_r = __msa_andi_b(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bclri_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_bclri_h(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_bclri_w(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_bclri_d(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_binsli_b(v16i8_r, v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_binsli_h(v8i16_r, v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_binsli_w(v4i32_r, v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_binsli_d(v2i64_r, v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_binsri_b(v16i8_r, v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_binsri_h(v8i16_r, v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_binsri_w(v4i32_r, v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_binsri_d(v2i64_r, v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_bmnzi_b(v16i8_r, v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bmzi_b(v16i8_r, v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bnegi_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_bnegi_h(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_bnegi_w(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_bnegi_d(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_bseli_b(v16i8_r, v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_bseti_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_bseti_h(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_bseti_w(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_bseti_d(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_ceqi_b(v16i8_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_ceqi_h(v8i16_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_ceqi_w(v4i32_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_ceqi_d(v2i64_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+
+ v16i8_r = __msa_clei_s_b(v16i8_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_clei_s_h(v8i16_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_clei_s_w(v4i32_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_clei_s_d(v2i64_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_clei_u_b(v16u8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_clei_u_h(v8u16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_clei_u_w(v4u32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_clei_u_d(v2u64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_clti_s_b(v16i8_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_clti_s_h(v8i16_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_clti_s_w(v4i32_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_clti_s_d(v2i64_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_clti_u_b(v16u8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_clti_u_h(v8u16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_clti_u_w(v4u32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_clti_u_d(v2u64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+
+ int_r = __msa_copy_s_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ int_r = __msa_copy_s_h(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ int_r = __msa_copy_s_w(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 3]}}
+ ll_r = __msa_copy_s_d(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 1]}}
+
+ int_r = __msa_copy_u_b(v16u8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ int_r = __msa_copy_u_h(v8u16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ int_r = __msa_copy_u_w(v4u32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 3]}}
+ ll_r = __msa_copy_u_d(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 1]}}
+
+ v16i8_r = __msa_insve_b(v16i8_r, 16, v16i8_a); // expected-error {{argument value 16 is outside the valid range [0, 15]}}
+ v8i16_r = __msa_insve_h(v8i16_r, 8, v8i16_a); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
+ v4i32_r = __msa_insve_w(v4i32_r, 4, v4i32_a); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+ v2i64_r = __msa_insve_d(v2i64_r, 2, v2i64_a); // expected-error {{argument value 2 is outside the valid range [0, 1]}}
+
+ v16i8_r = __msa_ld_b(&v16i8_a, -513); // expected-error {{argument value -513 is outside the valid range [-512, 511]}}
+ v8i16_r = __msa_ld_h(&v8i16_a, -1028); // expected-error {{argument value -1028 is outside the valid range [-1024, 1022]}}
+ v4i32_r = __msa_ld_w(&v4i32_a, -2052); // expected-error {{argument value -2052 is outside the valid range [-2048, 2044]}}
+ v2i64_r = __msa_ld_d(&v2i64_a, -4104); // expected-error {{argument value -4104 is outside the valid range [-4096, 4088]}}
+
+ v16i8_r = __msa_ldi_b(-129); // expected-error {{argument value -129 is outside the valid range [-128, 255]}}
+ v8i16_r = __msa_ldi_h(-513); // expected-error {{argument value -513 is outside the valid range [-512, 511]}}
+ v4i32_r = __msa_ldi_w(-513); // expected-error {{argument value -513 is outside the valid range [-512, 511]}}
+ v2i64_r = __msa_ldi_d(-513); // expected-error {{argument value -513 is outside the valid range [-512, 511]}}
+
+ v16i8_r = __msa_maxi_s_b(v16i8_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_maxi_s_h(v8i16_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_maxi_s_w(v4i32_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_maxi_s_d(v2i64_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_maxi_u_b(v16u8_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_maxi_u_h(v8u16_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_maxi_u_w(v4u32_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_maxi_u_d(v2u64_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_mini_s_b(v16i8_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v8i16_r = __msa_mini_s_h(v8i16_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v4i32_r = __msa_mini_s_w(v4i32_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+ v2i64_r = __msa_mini_s_d(v2i64_a, -17); // expected-error {{argument value -17 is outside the valid range [-16, 15]}}
+
+ v16u8_r = __msa_mini_u_b(v16u8_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+ v8u16_r = __msa_mini_u_h(v8u16_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+ v4u32_r = __msa_mini_u_w(v4u32_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+ v2u64_r = __msa_mini_u_d(v2u64_a, -1); // expected-error {{argument value -1 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_nori_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_ori_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_sat_s_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_sat_s_h(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_sat_s_w(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_sat_s_d(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_sat_u_b(v16i8_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_sat_u_h(v8i16_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_sat_u_w(v4i32_a, -32); // expected-error {{argument value 4294967264 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_sat_u_d(v2i64_a, -64); // expected-error {{argument value 4294967232 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_shf_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v8i16_r = __msa_shf_h(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v4i32_r = __msa_shf_w(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16i8_r = __msa_sldi_b(v16i8_r, v16i8_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v8i16_r = __msa_sldi_h(v8i16_r, v8i16_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v4i32_r = __msa_sldi_w(v4i32_r, v4i32_a, -4); // expected-error {{argument value 4294967292 is outside the valid range [0, 3]}}
+ v2i64_r = __msa_sldi_d(v2i64_r, v2i64_a, -2); // expected-error {{argument value 4294967294 is outside the valid range [0, 1]}}
+
+ v16i8_r = __msa_slli_b(v16i8_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_slli_h(v8i16_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_slli_w(v4i32_a, -32); // expected-error {{argument value 4294967264 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_slli_d(v2i64_a, -64); // expected-error {{argument value 4294967232 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_splati_b(v16i8_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v8i16_r = __msa_splati_h(v8i16_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v4i32_r = __msa_splati_w(v4i32_a, -4); // expected-error {{argument value 4294967292 is outside the valid range [0, 3]}}
+ v2i64_r = __msa_splati_d(v2i64_a, -2); // expected-error {{argument value 4294967294 is outside the valid range [0, 1]}}
+
+ v16i8_r = __msa_srai_b(v16i8_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srai_h(v8i16_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srai_w(v4i32_a, -32); // expected-error {{argument value 4294967264 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srai_d(v2i64_a, -64); // expected-error {{argument value 4294967232 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_srari_b(v16i8_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srari_h(v8i16_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srari_w(v4i32_a, -32); // expected-error {{argument value 4294967264 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srari_d(v2i64_a, -64); // expected-error {{argument value 4294967232 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_srli_b(v16i8_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srli_h(v8i16_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srli_w(v4i32_a, -32); // expected-error {{argument value 4294967264 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srli_d(v2i64_a, -64); // expected-error {{argument value 4294967232 is outside the valid range [0, 63]}}
+
+ v16i8_r = __msa_srlri_b(v16i8_a, -8); // expected-error {{argument value 4294967288 is outside the valid range [0, 7]}}
+ v8i16_r = __msa_srlri_h(v8i16_a, -17); // expected-error {{argument value 4294967279 is outside the valid range [0, 15]}}
+ v4i32_r = __msa_srlri_w(v4i32_a, -32); // expected-error {{argument value 4294967264 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_srlri_d(v2i64_a, -64); // expected-error {{argument value 4294967232 is outside the valid range [0, 63]}}
+
+ __msa_st_b(v16i8_b, &v16i8_a, -513); // expected-error {{argument value -513 is outside the valid range [-512, 511]}}
+ __msa_st_h(v8i16_b, &v8i16_a, -1025); // expected-error {{argument value -1025 is outside the valid range [-1024, 1022]}}
+ __msa_st_w(v4i32_b, &v4i32_a, -2049); // expected-error {{argument value -2049 is outside the valid range [-2048, 2044]}}
+ __msa_st_d(v2i64_b, &v2i64_a, -4097); // expected-error {{argument value -4097 is outside the valid range [-4096, 4088]}}
+
+ v16i8_r = __msa_subvi_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v8i16_r = __msa_subvi_h(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v4i32_r = __msa_subvi_w(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+ v2i64_r = __msa_subvi_d(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 31]}}
+
+ v16i8_r = __msa_xori_b(v16i8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v8i16_r = __msa_xori_b(v8i16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v4i32_r = __msa_xori_b(v4i32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v2i64_r = __msa_xori_b(v2i64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+
+ v16u8_r = __msa_xori_b(v16u8_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v8u16_r = __msa_xori_b(v8u16_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v4u32_r = __msa_xori_b(v4u32_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
+ v2u64_r = __msa_xori_b(v2u64_a, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 255]}}
}
diff --git a/test/CodeGen/builtins-mips-msa.c b/test/CodeGen/builtins-mips-msa.c
index 9d09a4209056..69c48a107589 100644
--- a/test/CodeGen/builtins-mips-msa.c
+++ b/test/CodeGen/builtins-mips-msa.c
@@ -520,10 +520,10 @@ void test(void) {
v4i32_r = __msa_insve_w(v4i32_r, 1, v4i32_a); // CHECK: call <4 x i32> @llvm.mips.insve.w(
v2i64_r = __msa_insve_d(v2i64_r, 1, v2i64_a); // CHECK: call <2 x i64> @llvm.mips.insve.d(
- v16i8_r = __msa_ld_b(&v16i8_a, 16); // CHECK: call <16 x i8> @llvm.mips.ld.b(
- v8i16_r = __msa_ld_h(&v8i16_a, 32); // CHECK: call <8 x i16> @llvm.mips.ld.h(
- v4i32_r = __msa_ld_w(&v4i32_a, 48); // CHECK: call <4 x i32> @llvm.mips.ld.w(
- v2i64_r = __msa_ld_d(&v2i64_a, 96); // CHECK: call <2 x i64> @llvm.mips.ld.d(
+ v16i8_r = __msa_ld_b(&v16i8_a, 1); // CHECK: call <16 x i8> @llvm.mips.ld.b(
+ v8i16_r = __msa_ld_h(&v8i16_a, 2); // CHECK: call <8 x i16> @llvm.mips.ld.h(
+ v4i32_r = __msa_ld_w(&v4i32_a, 4); // CHECK: call <4 x i32> @llvm.mips.ld.w(
+ v2i64_r = __msa_ld_d(&v2i64_a, 8); // CHECK: call <2 x i64> @llvm.mips.ld.d(
v16i8_r = __msa_ldi_b(3); // CHECK: call <16 x i8> @llvm.mips.ldi.b(
v16i8_r = __msa_ldi_b(-128); // CHECK: call <16 x i8> @llvm.mips.ldi.b(
@@ -771,10 +771,10 @@ void test(void) {
v4i32_r = __msa_srlri_w(v4i32_a, 3); // CHECK: call <4 x i32> @llvm.mips.srlri.w(
v2i64_r = __msa_srlri_d(v2i64_a, 3); // CHECK: call <2 x i64> @llvm.mips.srlri.d(
- __msa_st_b(v16i8_b, &v16i8_a, 16); // CHECK: call void @llvm.mips.st.b(
- __msa_st_h(v8i16_b, &v8i16_a, 32); // CHECK: call void @llvm.mips.st.h(
- __msa_st_w(v4i32_b, &v4i32_a, 48); // CHECK: call void @llvm.mips.st.w(
- __msa_st_d(v2i64_b, &v2i64_a, 96); // CHECK: call void @llvm.mips.st.d(
+ __msa_st_b(v16i8_b, &v16i8_a, 1); // CHECK: call void @llvm.mips.st.b(
+ __msa_st_h(v8i16_b, &v8i16_a, 2); // CHECK: call void @llvm.mips.st.h(
+ __msa_st_w(v4i32_b, &v4i32_a, 4); // CHECK: call void @llvm.mips.st.w(
+ __msa_st_d(v2i64_b, &v2i64_a, 8); // CHECK: call void @llvm.mips.st.d(
v16i8_r = __msa_subs_s_b(v16i8_a, v16i8_b); // CHECK: call <16 x i8> @llvm.mips.subs.s.b(
v8i16_r = __msa_subs_s_h(v8i16_a, v8i16_b); // CHECK: call <8 x i16> @llvm.mips.subs.s.h(
diff --git a/test/CodeGen/builtins-overflow.c b/test/CodeGen/builtins-overflow.c
index 57f90eb66a5f..79a3186b7457 100644
--- a/test/CodeGen/builtins-overflow.c
+++ b/test/CodeGen/builtins-overflow.c
@@ -339,6 +339,27 @@ long long test_smulll_overflow(long long x, long long y) {
return result;
}
+int test_mixed_sign_mul_overflow_sext_signed_op(int x, unsigned long long y) {
+// CHECK: @test_mixed_sign_mul_overflow_sext_signed_op
+// CHECK: [[SignedOp:%.*]] = sext i32 %0 to i64
+// CHECK: [[IsNeg:%.*]] = icmp slt i64 [[SignedOp]], 0
+ int result;
+ if (__builtin_mul_overflow(x, y, &result))
+ return LongErrorCode;
+ return result;
+}
+
+int test_mixed_sign_mul_overflow_zext_unsigned_op(long long x, unsigned y) {
+// CHECK: @test_mixed_sign_mul_overflow_zext_unsigned_op
+// CHECK: [[UnsignedOp:%.*]] = zext i32 %1 to i64
+// CHECK: [[IsNeg:%.*]] = icmp slt i64 %0, 0
+// CHECK: @llvm.umul.with.overflow.i64({{.*}}, i64 [[UnsignedOp]])
+ int result;
+ if (__builtin_mul_overflow(x, y, &result))
+ return LongErrorCode;
+ return result;
+}
+
int test_mixed_sign_mull_overflow(int x, unsigned y) {
// CHECK: @test_mixed_sign_mull_overflow
// CHECK: [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0
diff --git a/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c
index 99cf3c253879..13562354f4e5 100644
--- a/test/CodeGen/builtins-ppc-altivec.c
+++ b/test/CodeGen/builtins-ppc-altivec.c
@@ -4256,52 +4256,76 @@ void test6() {
/* vec_sr */
res_vsc = vec_sr(vsc, vuc);
-// CHECK: lshr <16 x i8>
-// CHECK-LE: lshr <16 x i8>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK-LE: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vuc = vec_sr(vuc, vuc);
-// CHECK: lshr <16 x i8>
-// CHECK-LE: lshr <16 x i8>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK-LE: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vs = vec_sr(vs, vus);
-// CHECK: lshr <8 x i16>
-// CHECK-LE: lshr <8 x i16>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK-LE: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vus = vec_sr(vus, vus);
-// CHECK: lshr <8 x i16>
-// CHECK-LE: lshr <8 x i16>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK-LE: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vi = vec_sr(vi, vui);
-// CHECK: lshr <4 x i32>
-// CHECK-LE: lshr <4 x i32>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK-LE: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vui = vec_sr(vui, vui);
-// CHECK: lshr <4 x i32>
-// CHECK-LE: lshr <4 x i32>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK-LE: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vsc = vec_vsrb(vsc, vuc);
-// CHECK: shr <16 x i8>
-// CHECK-LE: shr <16 x i8>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK-LE: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vuc = vec_vsrb(vuc, vuc);
-// CHECK: shr <16 x i8>
-// CHECK-LE: shr <16 x i8>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, <i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8, i8 8>
+// CHECK-LE: lshr <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vs = vec_vsrh(vs, vus);
-// CHECK: shr <8 x i16>
-// CHECK-LE: shr <8 x i16>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK-LE: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vus = vec_vsrh(vus, vus);
-// CHECK: shr <8 x i16>
-// CHECK-LE: shr <8 x i16>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, <i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16>
+// CHECK-LE: lshr <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vi = vec_vsrw(vi, vui);
-// CHECK: shr <4 x i32>
-// CHECK-LE: shr <4 x i32>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK-LE: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
res_vui = vec_vsrw(vui, vui);
-// CHECK: shr <4 x i32>
-// CHECK-LE: shr <4 x i32>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, <i32 32, i32 32, i32 32, i32 32>
+// CHECK-LE: lshr <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]]
/* vec_sra */
res_vsc = vec_sra(vsc, vuc);
@@ -9338,32 +9362,32 @@ void test9() {
// CHECK-LABEL: define void @test9
// CHECK-LE-LABEL: define void @test9
res_vsc = vec_xl(param_sll, &param_sc);
- // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1
res_vuc = vec_xl(param_sll, &param_uc);
- // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1
res_vs = vec_xl(param_sll, &param_s);
- // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1
res_vus = vec_xl(param_sll, &param_us);
- // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1
res_vi = vec_xl(param_sll, &param_i);
- // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1
res_vui = vec_xl(param_sll, &param_ui);
- // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1
res_vf = vec_xl(param_sll, &param_f);
- // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 1
}
/* ------------------------------ vec_xst ----------------------------------- */
@@ -9371,32 +9395,32 @@ void test10() {
// CHECK-LABEL: define void @test10
// CHECK-LE-LABEL: define void @test10
vec_xst(vsc, param_sll, &param_sc);
- // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1
vec_xst(vuc, param_sll, &param_uc);
- // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1
vec_xst(vs, param_sll, &param_s);
- // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1
vec_xst(vus, param_sll, &param_us);
- // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1
vec_xst(vi, param_sll, &param_i);
- // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1
vec_xst(vui, param_sll, &param_ui);
- // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1
vec_xst(vf, param_sll, &param_f);
- // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 1
}
/* ----------------------------- vec_xl_be ---------------------------------- */
@@ -9404,35 +9428,35 @@ void test11() {
// CHECK-LABEL: define void @test11
// CHECK-LE-LABEL: define void @test11
res_vsc = vec_xl_be(param_sll, &param_sc);
- // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1
// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
// CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
res_vuc = vec_xl_be(param_sll, &param_uc);
- // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1
// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
// CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
res_vs = vec_xl_be(param_sll, &param_s);
- // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1
// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
// CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
res_vus = vec_xl_be(param_sll, &param_us);
- // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1
// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
// CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
res_vi = vec_xl_be(param_sll, &param_i);
- // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1
// CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}})
res_vui = vec_xl_be(param_sll, &param_ui);
- // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1
// CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}})
res_vf = vec_xl_be(param_sll, &param_f);
- // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 1
// CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}})
}
@@ -9441,34 +9465,34 @@ void test12() {
// CHECK-LABEL: define void @test12
// CHECK-LE-LABEL: define void @test12
vec_xst_be(vsc, param_sll, &param_sc);
- // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1
// CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vuc, param_sll, &param_uc);
- // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1
// CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vs, param_sll, &param_s);
- // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1
// CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vus, param_sll, &param_us);
- // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1
// CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vi, param_sll, &param_i);
- // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1
// CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vui, param_sll, &param_ui);
- // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1
// CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vf, param_sll, &param_f);
- // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 1
// CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}})
}
diff --git a/test/CodeGen/builtins-ppc-error.c b/test/CodeGen/builtins-ppc-error.c
index 29eebf286100..a50dc2cba024 100644
--- a/test/CodeGen/builtins-ppc-error.c
+++ b/test/CodeGen/builtins-ppc-error.c
@@ -14,6 +14,7 @@ extern vector signed int vsi;
extern vector signed int vui;
extern vector float vf;
extern vector unsigned char vuc;
+extern vector signed __int128 vsllli;
void testInsertWord(void) {
int index = 5;
@@ -67,3 +68,8 @@ void testCTU(int index) {
void testVCTUXS(int index) {
vec_vctuxs(vf, index); //expected-error {{argument to '__builtin_altivec_vctuxs' must be a constant integer}}
}
+
+void testUnpack128(int index) {
+ __builtin_unpack_vector_int128(vsllli, index); //expected-error {{argument to '__builtin_unpack_vector_int128' must be a constant integer}}
+ __builtin_unpack_vector_int128(vsllli, 5); //expected-error {{argument value 5 is outside the valid range [0, 1]}}
+}
diff --git a/test/CodeGen/builtins-ppc-p7-disabled.c b/test/CodeGen/builtins-ppc-p7-disabled.c
index 9ccedd2ce894..2a6a4f8dbc8e 100644
--- a/test/CodeGen/builtins-ppc-p7-disabled.c
+++ b/test/CodeGen/builtins-ppc-p7-disabled.c
@@ -6,6 +6,8 @@
// RUN: not %clang_cc1 -triple powerpc-unknown-unknown -emit-llvm %s -o - 2>&1 \
// RUN: -target-cpu pwr7 | FileCheck %s -check-prefix=CHECK-32
+vector signed __int128 vslll = {33};
+
void call_p7_builtins(void)
{
int a = __builtin_divwe(33, 11);
@@ -13,6 +15,8 @@ void call_p7_builtins(void)
unsigned long long d = __builtin_divde(33ULL, 11ULL);
unsigned long long e = __builtin_divdeu(33ULL, 11ULL);
unsigned long long f = __builtin_bpermd(33ULL, 11ULL);
+ __builtin_pack_vector_int128(33ULL, 11ULL);
+ __builtin_unpack_vector_int128(vslll, 1);
}
// CHECK: error: this builtin is only valid on POWER7 or later CPUs
@@ -25,6 +29,10 @@ void call_p7_builtins(void)
// CHECK: __builtin_divdeu
// CHECK: error: this builtin is only valid on POWER7 or later CPUs
// CHECK: __builtin_bpermd
+// CHECK: error: this builtin is only valid on POWER7 or later CPUs
+// CHECK: __builtin_pack_vector_int128
+// CHECK: error: this builtin is only valid on POWER7 or later CPUs
+// CHECK: __builtin_unpack_vector_int128
// CHECK-32: error: this builtin is only available on 64-bit targets
// CHECK-32: __builtin_divde
// CHECK-32: error: this builtin is only available on 64-bit targets
diff --git a/test/CodeGen/builtins-ppc-p8vector.c b/test/CodeGen/builtins-ppc-p8vector.c
index 9f2913847e56..a686b0a0796b 100644
--- a/test/CodeGen/builtins-ppc-p8vector.c
+++ b/test/CodeGen/builtins-ppc-p8vector.c
@@ -1066,13 +1066,17 @@ void test1() {
/* vec_sr */
res_vsll = vec_sr(vsll, vull);
-// CHECK: lshr <2 x i64>
-// CHECK-LE: lshr <2 x i64>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <2 x i64> {{[0-9a-zA-Z%.]+}}, <i64 64, i64 64>
+// CHECK: lshr <2 x i64> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <2 x i64> {{[0-9a-zA-Z%.]+}}, <i64 64, i64 64>
+// CHECK-LE: lshr <2 x i64> {{[0-9a-zA-Z%.]+}}, [[UREM]]
// CHECK-PPC: error: call to 'vec_sr' is ambiguous
res_vull = vec_sr(vull, vull);
-// CHECK: lshr <2 x i64>
-// CHECK-LE: lshr <2 x i64>
+// CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <2 x i64> {{[0-9a-zA-Z%.]+}}, <i64 64, i64 64>
+// CHECK: lshr <2 x i64> {{[0-9a-zA-Z%.]+}}, [[UREM]]
+// CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <2 x i64> {{[0-9a-zA-Z%.]+}}, <i64 64, i64 64>
+// CHECK-LE: lshr <2 x i64> {{[0-9a-zA-Z%.]+}}, [[UREM]]
// CHECK-PPC: error: call to 'vec_sr' is ambiguous
/* vec_sra */
diff --git a/test/CodeGen/builtins-ppc-p9-f128.c b/test/CodeGen/builtins-ppc-p9-f128.c
index c43915ad2489..d0c89cea5bd4 100644
--- a/test/CodeGen/builtins-ppc-p9-f128.c
+++ b/test/CodeGen/builtins-ppc-p9-f128.c
@@ -48,3 +48,15 @@ double testTruncOdd() {
// CHECK-NEXT: ret double
}
+__float128 insert_exp_qp(unsigned long long int b) {
+ return __builtin_vsx_scalar_insert_exp_qp(A, b);
+// CHECK: @llvm.ppc.scalar.insert.exp.qp(fp128 %{{.+}}, i64
+// CHECK-NEXT: ret fp128
+}
+
+unsigned long long int extract_exp() {
+ return __builtin_vsx_scalar_extract_expq(A);
+// CHECK: @llvm.ppc.scalar.extract.expq(fp128
+// CHECK-NEXT: ret i64
+}
+
diff --git a/test/CodeGen/builtins-ppc-quadword.c b/test/CodeGen/builtins-ppc-quadword.c
index 7d014db61323..868fb183a623 100644
--- a/test/CodeGen/builtins-ppc-quadword.c
+++ b/test/CodeGen/builtins-ppc-quadword.c
@@ -205,45 +205,45 @@ void test1() {
/* vec_xl */
res_vlll = vec_xl(param_sll, &param_lll);
- // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xl' is ambiguous
res_vulll = vec_xl(param_sll, &param_ulll);
- // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xl' is ambiguous
/* vec_xst */
vec_xst(vlll, param_sll, &param_lll);
- // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xst' is ambiguous
vec_xst(vulll, param_sll, &param_ulll);
- // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xst' is ambiguous
/* vec_xl_be */
res_vlll = vec_xl_be(param_sll, &param_lll);
- // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xl' is ambiguous
res_vulll = vec_xl_be(param_sll, &param_ulll);
- // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xl' is ambiguous
/* vec_xst_be */
vec_xst_be(vlll, param_sll, &param_lll);
- // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xst' is ambiguous
vec_xst_be(vulll, param_sll, &param_ulll);
- // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
- // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1
// CHECK-PPC: error: call to 'vec_xst' is ambiguous
}
diff --git a/test/CodeGen/builtins-ppc-vsx.c b/test/CodeGen/builtins-ppc-vsx.c
index 848d24d4fb10..838d94cf7de9 100644
--- a/test/CodeGen/builtins-ppc-vsx.c
+++ b/test/CodeGen/builtins-ppc-vsx.c
@@ -49,6 +49,7 @@ vector unsigned int res_vui;
vector bool long long res_vbll;
vector signed long long res_vsll;
vector unsigned long long res_vull;
+vector signed __int128 res_vslll;
double res_d;
float res_af[4];
@@ -1637,51 +1638,51 @@ res_vsll = vec_slo(vsll, vsc);
// CHECK-LE: @llvm.ppc.altivec.vsro
res_vsll = vec_xl(sll, asll);
-// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
-// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1
+// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1
res_vull = vec_xl(sll, aull);
-// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
-// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1
+// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1
res_vd = vec_xl(sll, ad);
-// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16
-// CHECK-LE: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 1
+// CHECK-LE: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 1
vec_xst(vsll, sll, asll);
-// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
-// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1
+// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1
vec_xst(vull, sll, aull);
-// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
-// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1
+// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1
vec_xst(vd, sll, ad);
-// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16
-// CHECK-LE: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 1
+// CHECK-LE: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 1
res_vsll = vec_xl_be(sll, asll);
-// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1
// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
res_vull = vec_xl_be(sll, aull);
-// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1
// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
res_vd = vec_xl_be(sll, ad);
-// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 1
// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
vec_xst_be(vsll, sll, asll);
-// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1
// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vull, sll, aull);
-// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1
// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
vec_xst_be(vd, sll, ad);
-// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 1
// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
res_vf = vec_neg(vf);
@@ -1803,3 +1804,31 @@ vector double xxsldwi_should_not_assert(vector double a, vector double b) {
// CHECK-NEXT-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK-NEXT-LE: bitcast <4 x i32> %{{[0-9]+}} to <2 x double>
}
+
+void testVectorInt128Pack(){
+// CHECK-LABEL: testVectorInt128Pack
+// CHECK-LABEL-LE: testVectorInt128Pack
+ res_vslll = __builtin_pack_vector_int128(aull[0], aull[1]);
+// CHECK: %[[V1:[0-9]+]] = insertelement <2 x i64> undef, i64 %{{[0-9]+}}, i64 0
+// CHECK-NEXT: %[[V2:[0-9]+]] = insertelement <2 x i64> %[[V1]], i64 %{{[0-9]+}}, i64 1
+// CHECK-NEXT: bitcast <2 x i64> %[[V2]] to <1 x i128>
+
+// CHECK-LE: %[[V1:[0-9]+]] = insertelement <2 x i64> undef, i64 %{{[0-9]+}}, i64 1
+// CHECK-NEXT-LE: %[[V2:[0-9]+]] = insertelement <2 x i64> %[[V1]], i64 %{{[0-9]+}}, i64 0
+// CHECK-NEXT-LE: bitcast <2 x i64> %[[V2]] to <1 x i128>
+
+ __builtin_unpack_vector_int128(res_vslll, 0);
+// CHECK: %[[V1:[0-9]+]] = bitcast <1 x i128> %{{[0-9]+}} to <2 x i64>
+// CHECK-NEXT: %{{[0-9]+}} = extractelement <2 x i64> %[[V1]], i32 0
+
+// CHECK-LE: %[[V1:[0-9]+]] = bitcast <1 x i128> %{{[0-9]+}} to <2 x i64>
+// CHECK-NEXT-LE: %{{[0-9]+}} = extractelement <2 x i64> %[[V1]], i32 1
+
+ __builtin_unpack_vector_int128(res_vslll, 1);
+// CHECK: %[[V1:[0-9]+]] = bitcast <1 x i128> %{{[0-9]+}} to <2 x i64>
+// CHECK-NEXT: %{{[0-9]+}} = extractelement <2 x i64> %[[V1]], i32 1
+
+// CHECK-LE: %[[V1:[0-9]+]] = bitcast <1 x i128> %{{[0-9]+}} to <2 x i64>
+// CHECK-NEXT-LE: %{{[0-9]+}} = extractelement <2 x i64> %[[V1]], i32 0
+
+}
diff --git a/test/CodeGen/builtins-systemz-zvector.c b/test/CodeGen/builtins-systemz-zvector.c
index a8adbd717ea1..f8e5aa3f40d5 100644
--- a/test/CodeGen/builtins-systemz-zvector.c
+++ b/test/CodeGen/builtins-systemz-zvector.c
@@ -2,6 +2,9 @@
// RUN: %clang_cc1 -target-cpu z13 -triple s390x-linux-gnu \
// RUN: -O -fzvector -fno-lax-vector-conversions \
// RUN: -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -target-cpu z13 -triple s390x-linux-gnu \
+// RUN: -O -fzvector -fno-lax-vector-conversions \
+// RUN: -Wall -Wno-unused -Werror -S %s -o - | FileCheck %s --check-prefix=CHECK-ASM
#include <vecintrin.h>
@@ -58,367 +61,598 @@ volatile int idx;
int cc;
void test_core(void) {
+ // CHECK-ASM-LABEL: test_core
+
len = __lcbb(cptr, 64);
// CHECK: call i32 @llvm.s390.lcbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: lcbb
len = __lcbb(cptr, 128);
// CHECK: call i32 @llvm.s390.lcbb(i8* %{{.*}}, i32 1)
+ // CHECK-ASM: lcbb
len = __lcbb(cptr, 256);
// CHECK: call i32 @llvm.s390.lcbb(i8* %{{.*}}, i32 2)
+ // CHECK-ASM: lcbb
len = __lcbb(cptr, 512);
// CHECK: call i32 @llvm.s390.lcbb(i8* %{{.*}}, i32 3)
+ // CHECK-ASM: lcbb
len = __lcbb(cptr, 1024);
// CHECK: call i32 @llvm.s390.lcbb(i8* %{{.*}}, i32 4)
+ // CHECK-ASM: lcbb
len = __lcbb(cptr, 2048);
// CHECK: call i32 @llvm.s390.lcbb(i8* %{{.*}}, i32 5)
+ // CHECK-ASM: lcbb
len = __lcbb(cptr, 4096);
// CHECK: call i32 @llvm.s390.lcbb(i8* %{{.*}}, i32 6)
+ // CHECK-ASM: lcbb
sc = vec_extract(vsc, idx);
// CHECK: extractelement <16 x i8> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvb
uc = vec_extract(vuc, idx);
// CHECK: extractelement <16 x i8> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvb
uc = vec_extract(vbc, idx);
// CHECK: extractelement <16 x i8> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvb
ss = vec_extract(vss, idx);
// CHECK: extractelement <8 x i16> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvh
us = vec_extract(vus, idx);
// CHECK: extractelement <8 x i16> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvh
us = vec_extract(vbs, idx);
// CHECK: extractelement <8 x i16> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvh
si = vec_extract(vsi, idx);
// CHECK: extractelement <4 x i32> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvf
ui = vec_extract(vui, idx);
// CHECK: extractelement <4 x i32> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvf
ui = vec_extract(vbi, idx);
// CHECK: extractelement <4 x i32> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvf
sl = vec_extract(vsl, idx);
// CHECK: extractelement <2 x i64> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvg
ul = vec_extract(vul, idx);
// CHECK: extractelement <2 x i64> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvg
ul = vec_extract(vbl, idx);
// CHECK: extractelement <2 x i64> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvg
d = vec_extract(vd, idx);
// CHECK: extractelement <2 x double> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvg
vsc = vec_insert(sc, vsc, idx);
// CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgb
vuc = vec_insert(uc, vuc, idx);
// CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgb
vuc = vec_insert(uc, vbc, idx);
// CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgb
vss = vec_insert(ss, vss, idx);
// CHECK: insertelement <8 x i16> %{{.*}}, i16 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgh
vus = vec_insert(us, vus, idx);
// CHECK: insertelement <8 x i16> %{{.*}}, i16 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgh
vus = vec_insert(us, vbs, idx);
// CHECK: insertelement <8 x i16> %{{.*}}, i16 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgh
vsi = vec_insert(si, vsi, idx);
// CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgf
vui = vec_insert(ui, vui, idx);
// CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgf
vui = vec_insert(ui, vbi, idx);
// CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgf
vsl = vec_insert(sl, vsl, idx);
// CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vul = vec_insert(ul, vul, idx);
// CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vul = vec_insert(ul, vbl, idx);
// CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vd = vec_insert(d, vd, idx);
// CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vsc = vec_promote(sc, idx);
// CHECK: insertelement <16 x i8> undef, i8 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgb
vuc = vec_promote(uc, idx);
// CHECK: insertelement <16 x i8> undef, i8 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgb
vss = vec_promote(ss, idx);
// CHECK: insertelement <8 x i16> undef, i16 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgh
vus = vec_promote(us, idx);
// CHECK: insertelement <8 x i16> undef, i16 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgh
vsi = vec_promote(si, idx);
// CHECK: insertelement <4 x i32> undef, i32 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgf
vui = vec_promote(ui, idx);
// CHECK: insertelement <4 x i32> undef, i32 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgf
vsl = vec_promote(sl, idx);
// CHECK: insertelement <2 x i64> undef, i64 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vul = vec_promote(ul, idx);
// CHECK: insertelement <2 x i64> undef, i64 %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vd = vec_promote(d, idx);
// CHECK: insertelement <2 x double> undef, double %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vsc = vec_insert_and_zero(cptrsc);
// CHECK: insertelement <16 x i8> <i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 undef, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>, i8 %{{.*}}, i32 7
+ // CHECK-ASM: vllezb
vuc = vec_insert_and_zero(cptruc);
// CHECK: insertelement <16 x i8> <i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 undef, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>, i8 %{{.*}}, i32 7
+ // CHECK-ASM: vllezb
vss = vec_insert_and_zero(cptrss);
// CHECK: insertelement <8 x i16> <i16 0, i16 0, i16 0, i16 undef, i16 0, i16 0, i16 0, i16 0>, i16 %{{.*}}, i32 3
+ // CHECK-ASM: vllezh
vus = vec_insert_and_zero(cptrus);
// CHECK: insertelement <8 x i16> <i16 0, i16 0, i16 0, i16 undef, i16 0, i16 0, i16 0, i16 0>, i16 %{{.*}}, i32 3
+ // CHECK-ASM: vllezh
vsi = vec_insert_and_zero(cptrsi);
// CHECK: insertelement <4 x i32> <i32 0, i32 undef, i32 0, i32 0>, i32 %{{.*}}, i32 1
+ // CHECK-ASM: vllezf
vui = vec_insert_and_zero(cptrui);
// CHECK: insertelement <4 x i32> <i32 0, i32 undef, i32 0, i32 0>, i32 %{{.*}}, i32 1
+ // CHECK-ASM: vllezf
vsl = vec_insert_and_zero(cptrsl);
// CHECK: insertelement <2 x i64> <i64 undef, i64 0>, i64 %{{.*}}, i32 0
+ // CHECK-ASM: vllezg
vul = vec_insert_and_zero(cptrul);
// CHECK: insertelement <2 x i64> <i64 undef, i64 0>, i64 %{{.*}}, i32 0
+ // CHECK-ASM: vllezg
vd = vec_insert_and_zero(cptrd);
// CHECK: insertelement <2 x double> <double undef, double 0.000000e+00>, double %{{.*}}, i32 0
+ // CHECK-ASM: vllezg
vsc = vec_perm(vsc, vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vuc = vec_perm(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vbc = vec_perm(vbc, vbc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vss = vec_perm(vss, vss, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vus = vec_perm(vus, vus, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vbs = vec_perm(vbs, vbs, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vsi = vec_perm(vsi, vsi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vui = vec_perm(vui, vui, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vbi = vec_perm(vbi, vbi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vsl = vec_perm(vsl, vsl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vul = vec_perm(vul, vul, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vbl = vec_perm(vbl, vbl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vd = vec_perm(vd, vd, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vsl = vec_permi(vsl, vsl, 0);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 0)
+ // CHECK-ASM: vpdi
vsl = vec_permi(vsl, vsl, 1);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 1)
+ // CHECK-ASM: vpdi
vsl = vec_permi(vsl, vsl, 2);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 4)
+ // CHECK-ASM: vpdi
vsl = vec_permi(vsl, vsl, 3);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 5)
+ // CHECK-ASM: vpdi
vul = vec_permi(vul, vul, 0);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 0)
+ // CHECK-ASM: vpdi
vul = vec_permi(vul, vul, 1);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 1)
+ // CHECK-ASM: vpdi
vul = vec_permi(vul, vul, 2);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 4)
+ // CHECK-ASM: vpdi
vul = vec_permi(vul, vul, 3);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 5)
+ // CHECK-ASM: vpdi
vbl = vec_permi(vbl, vbl, 0);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 0)
+ // CHECK-ASM: vpdi
vbl = vec_permi(vbl, vbl, 1);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 1)
+ // CHECK-ASM: vpdi
vbl = vec_permi(vbl, vbl, 2);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 4)
+ // CHECK-ASM: vpdi
vbl = vec_permi(vbl, vbl, 3);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 5)
+ // CHECK-ASM: vpdi
vd = vec_permi(vd, vd, 0);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 0)
+ // CHECK-ASM: vpdi
vd = vec_permi(vd, vd, 1);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 1)
+ // CHECK-ASM: vpdi
vd = vec_permi(vd, vd, 2);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 4)
+ // CHECK-ASM: vpdi
vd = vec_permi(vd, vd, 3);
// CHECK: call <2 x i64> @llvm.s390.vpdi(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 5)
+ // CHECK-ASM: vpdi
vsc = vec_sel(vsc, vsc, vuc);
+ // CHECK-ASM: vsel
vsc = vec_sel(vsc, vsc, vbc);
+ // CHECK-ASM: vsel
vuc = vec_sel(vuc, vuc, vuc);
+ // CHECK-ASM: vsel
vuc = vec_sel(vuc, vuc, vbc);
+ // CHECK-ASM: vsel
vbc = vec_sel(vbc, vbc, vuc);
+ // CHECK-ASM: vsel
vbc = vec_sel(vbc, vbc, vbc);
+ // CHECK-ASM: vsel
vss = vec_sel(vss, vss, vus);
+ // CHECK-ASM: vsel
vss = vec_sel(vss, vss, vbs);
+ // CHECK-ASM: vsel
vus = vec_sel(vus, vus, vus);
+ // CHECK-ASM: vsel
vus = vec_sel(vus, vus, vbs);
+ // CHECK-ASM: vsel
vbs = vec_sel(vbs, vbs, vus);
+ // CHECK-ASM: vsel
vbs = vec_sel(vbs, vbs, vbs);
+ // CHECK-ASM: vsel
vsi = vec_sel(vsi, vsi, vui);
+ // CHECK-ASM: vsel
vsi = vec_sel(vsi, vsi, vbi);
+ // CHECK-ASM: vsel
vui = vec_sel(vui, vui, vui);
+ // CHECK-ASM: vsel
vui = vec_sel(vui, vui, vbi);
+ // CHECK-ASM: vsel
vbi = vec_sel(vbi, vbi, vui);
+ // CHECK-ASM: vsel
vbi = vec_sel(vbi, vbi, vbi);
+ // CHECK-ASM: vsel
vsl = vec_sel(vsl, vsl, vul);
+ // CHECK-ASM: vsel
vsl = vec_sel(vsl, vsl, vbl);
+ // CHECK-ASM: vsel
vul = vec_sel(vul, vul, vul);
+ // CHECK-ASM: vsel
vul = vec_sel(vul, vul, vbl);
+ // CHECK-ASM: vsel
vbl = vec_sel(vbl, vbl, vul);
+ // CHECK-ASM: vsel
vbl = vec_sel(vbl, vbl, vbl);
+ // CHECK-ASM: vsel
vd = vec_sel(vd, vd, vul);
+ // CHECK-ASM: vsel
vd = vec_sel(vd, vd, vbl);
+ // CHECK-ASM: vsel
vsi = vec_gather_element(vsi, vui, cptrsi, 0);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vsi = vec_gather_element(vsi, vui, cptrsi, 1);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vsi = vec_gather_element(vsi, vui, cptrsi, 2);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vsi = vec_gather_element(vsi, vui, cptrsi, 3);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vui = vec_gather_element(vui, vui, cptrui, 0);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vui = vec_gather_element(vui, vui, cptrui, 1);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vui = vec_gather_element(vui, vui, cptrui, 2);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vui = vec_gather_element(vui, vui, cptrui, 3);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vbi = vec_gather_element(vbi, vui, cptrui, 0);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vbi = vec_gather_element(vbi, vui, cptrui, 1);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vbi = vec_gather_element(vbi, vui, cptrui, 2);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vbi = vec_gather_element(vbi, vui, cptrui, 3);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vsl = vec_gather_element(vsl, vul, cptrsl, 0);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vsl = vec_gather_element(vsl, vul, cptrsl, 1);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vul = vec_gather_element(vul, vul, cptrul, 0);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vul = vec_gather_element(vul, vul, cptrul, 1);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vbl = vec_gather_element(vbl, vul, cptrul, 0);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vbl = vec_gather_element(vbl, vul, cptrul, 1);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vd = vec_gather_element(vd, vul, cptrd, 0);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vd = vec_gather_element(vd, vul, cptrd, 1);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vsi, vui, ptrsi, 0);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vsi, vui, ptrsi, 1);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vsi, vui, ptrsi, 2);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vec_scatter_element(vsi, vui, ptrsi, 3);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vec_scatter_element(vui, vui, ptrui, 0);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vui, vui, ptrui, 1);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vui, vui, ptrui, 2);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vec_scatter_element(vui, vui, ptrui, 3);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vec_scatter_element(vbi, vui, ptrui, 0);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vbi, vui, ptrui, 1);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vbi, vui, ptrui, 2);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vec_scatter_element(vbi, vui, ptrui, 3);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vec_scatter_element(vsl, vul, ptrsl, 0);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vsl, vul, ptrsl, 1);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vul, vul, ptrul, 0);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vul, vul, ptrul, 1);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vbl, vul, ptrul, 0);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vbl, vul, ptrul, 1);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vd, vul, ptrd, 0);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vd, vul, ptrd, 1);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vsc = vec_xl(idx, cptrsc);
+ // CHECK-ASM: vl
vuc = vec_xl(idx, cptruc);
+ // CHECK-ASM: vl
vss = vec_xl(idx, cptrss);
+ // CHECK-ASM: vl
vus = vec_xl(idx, cptrus);
+ // CHECK-ASM: vl
vsi = vec_xl(idx, cptrsi);
+ // CHECK-ASM: vl
vui = vec_xl(idx, cptrui);
+ // CHECK-ASM: vl
vsl = vec_xl(idx, cptrsl);
+ // CHECK-ASM: vl
vul = vec_xl(idx, cptrul);
+ // CHECK-ASM: vl
vd = vec_xl(idx, cptrd);
+ // CHECK-ASM: vl
vsc = vec_xld2(idx, cptrsc);
+ // CHECK-ASM: vl
vuc = vec_xld2(idx, cptruc);
+ // CHECK-ASM: vl
vss = vec_xld2(idx, cptrss);
+ // CHECK-ASM: vl
vus = vec_xld2(idx, cptrus);
+ // CHECK-ASM: vl
vsi = vec_xld2(idx, cptrsi);
+ // CHECK-ASM: vl
vui = vec_xld2(idx, cptrui);
+ // CHECK-ASM: vl
vsl = vec_xld2(idx, cptrsl);
+ // CHECK-ASM: vl
vul = vec_xld2(idx, cptrul);
+ // CHECK-ASM: vl
vd = vec_xld2(idx, cptrd);
+ // CHECK-ASM: vl
vsc = vec_xlw4(idx, cptrsc);
+ // CHECK-ASM: vl
vuc = vec_xlw4(idx, cptruc);
+ // CHECK-ASM: vl
vss = vec_xlw4(idx, cptrss);
+ // CHECK-ASM: vl
vus = vec_xlw4(idx, cptrus);
+ // CHECK-ASM: vl
vsi = vec_xlw4(idx, cptrsi);
+ // CHECK-ASM: vl
vui = vec_xlw4(idx, cptrui);
+ // CHECK-ASM: vl
vec_xst(vsc, idx, ptrsc);
+ // CHECK-ASM: vst
vec_xst(vuc, idx, ptruc);
+ // CHECK-ASM: vst
vec_xst(vss, idx, ptrss);
+ // CHECK-ASM: vst
vec_xst(vus, idx, ptrus);
+ // CHECK-ASM: vst
vec_xst(vsi, idx, ptrsi);
+ // CHECK-ASM: vst
vec_xst(vui, idx, ptrui);
+ // CHECK-ASM: vst
vec_xst(vsl, idx, ptrsl);
+ // CHECK-ASM: vst
vec_xst(vul, idx, ptrul);
+ // CHECK-ASM: vst
vec_xst(vd, idx, ptrd);
+ // CHECK-ASM: vst
vec_xstd2(vsc, idx, ptrsc);
+ // CHECK-ASM: vst
vec_xstd2(vuc, idx, ptruc);
+ // CHECK-ASM: vst
vec_xstd2(vss, idx, ptrss);
+ // CHECK-ASM: vst
vec_xstd2(vus, idx, ptrus);
+ // CHECK-ASM: vst
vec_xstd2(vsi, idx, ptrsi);
+ // CHECK-ASM: vst
vec_xstd2(vui, idx, ptrui);
+ // CHECK-ASM: vst
vec_xstd2(vsl, idx, ptrsl);
+ // CHECK-ASM: vst
vec_xstd2(vul, idx, ptrul);
+ // CHECK-ASM: vst
vec_xstd2(vd, idx, ptrd);
+ // CHECK-ASM: vst
vec_xstw4(vsc, idx, ptrsc);
+ // CHECK-ASM: vst
vec_xstw4(vuc, idx, ptruc);
+ // CHECK-ASM: vst
vec_xstw4(vss, idx, ptrss);
+ // CHECK-ASM: vst
vec_xstw4(vus, idx, ptrus);
+ // CHECK-ASM: vst
vec_xstw4(vsi, idx, ptrsi);
+ // CHECK-ASM: vst
vec_xstw4(vui, idx, ptrui);
+ // CHECK-ASM: vst
vsc = vec_load_bndry(cptrsc, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vuc = vec_load_bndry(cptruc, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vss = vec_load_bndry(cptrss, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vus = vec_load_bndry(cptrus, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vsi = vec_load_bndry(cptrsi, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vui = vec_load_bndry(cptrui, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vsl = vec_load_bndry(cptrsl, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vul = vec_load_bndry(cptrul, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vd = vec_load_bndry(cptrd, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vsc = vec_load_bndry(cptrsc, 128);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 1)
+ // CHECK-ASM: vlbb
vsc = vec_load_bndry(cptrsc, 256);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 2)
+ // CHECK-ASM: vlbb
vsc = vec_load_bndry(cptrsc, 512);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 3)
+ // CHECK-ASM: vlbb
vsc = vec_load_bndry(cptrsc, 1024);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 4)
+ // CHECK-ASM: vlbb
vsc = vec_load_bndry(cptrsc, 2048);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 5)
+ // CHECK-ASM: vlbb
vsc = vec_load_bndry(cptrsc, 4096);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 6)
+ // CHECK-ASM: vlbb
vsc = vec_load_len(cptrsc, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vuc = vec_load_len(cptruc, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vss = vec_load_len(cptrss, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vus = vec_load_len(cptrus, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vsi = vec_load_len(cptrsi, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vui = vec_load_len(cptrui, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vsl = vec_load_len(cptrsl, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vul = vec_load_len(cptrul, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vd = vec_load_len(cptrd, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vec_store_len(vsc, ptrsc, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vuc, ptruc, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vss, ptrss, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vus, ptrus, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vsi, ptrsi, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vui, ptrui, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vsl, ptrsl, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vul, ptrul, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vd, ptrd, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
- vsl = vec_load_pair(sl, sl);
- vul = vec_load_pair(ul, ul);
+ vsl = vec_load_pair(sl + 1, sl - 1);
+ // CHECK-ASM: vlvgp
+ vul = vec_load_pair(ul + 1, ul - 1);
+ // CHECK-ASM: vlvgp
vuc = vec_genmask(0);
// CHECK: <16 x i8> zeroinitializer
@@ -454,56 +688,82 @@ void test_core(void) {
vsc = vec_splat(vsc, 0);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> zeroinitializer
+ // CHECK-ASM: vrepb
vsc = vec_splat(vsc, 15);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>
+ // CHECK-ASM: vrepb
vuc = vec_splat(vuc, 0);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> zeroinitializer
+ // CHECK-ASM: vrepb
vuc = vec_splat(vuc, 15);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>
+ // CHECK-ASM: vrepb
vbc = vec_splat(vbc, 0);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> zeroinitializer
+ // CHECK-ASM: vrepb
vbc = vec_splat(vbc, 15);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>
+ // CHECK-ASM: vrepb
vss = vec_splat(vss, 0);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> zeroinitializer
+ // CHECK-ASM: vreph
vss = vec_splat(vss, 7);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+ // CHECK-ASM: vreph
vus = vec_splat(vus, 0);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> zeroinitializer
+ // CHECK-ASM: vreph
vus = vec_splat(vus, 7);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+ // CHECK-ASM: vreph
vbs = vec_splat(vbs, 0);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> zeroinitializer
+ // CHECK-ASM: vreph
vbs = vec_splat(vbs, 7);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
+ // CHECK-ASM: vreph
vsi = vec_splat(vsi, 0);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> zeroinitializer
+ // CHECK-ASM: vrepf
vsi = vec_splat(vsi, 3);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+ // CHECK-ASM: vrepf
vui = vec_splat(vui, 0);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> zeroinitializer
+ // CHECK-ASM: vrepf
vui = vec_splat(vui, 3);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+ // CHECK-ASM: vrepf
vbi = vec_splat(vbi, 0);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> zeroinitializer
+ // CHECK-ASM: vrepf
vbi = vec_splat(vbi, 3);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
+ // CHECK-ASM: vrepf
vsl = vec_splat(vsl, 0);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vrepg
vsl = vec_splat(vsl, 1);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> <i32 1, i32 1>
+ // CHECK-ASM: vrepg
vul = vec_splat(vul, 0);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vrepg
vul = vec_splat(vul, 1);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> <i32 1, i32 1>
+ // CHECK-ASM: vrepg
vbl = vec_splat(vbl, 0);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vrepg
vbl = vec_splat(vbl, 1);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> <i32 1, i32 1>
+ // CHECK-ASM: vrepg
vd = vec_splat(vd, 0);
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vrepg
vd = vec_splat(vd, 1);
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> <i32 1, i32 1>
+ // CHECK-ASM: vrepg
vsc = vec_splat_s8(-128);
// CHECK: <16 x i8> <i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>
@@ -540,2516 +800,3781 @@ void test_core(void) {
vsc = vec_splats(sc);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> zeroinitializer
+ // CHECK-ASM: vlrepb
vuc = vec_splats(uc);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> undef, <16 x i32> zeroinitializer
+ // CHECK-ASM: vlrepb
vss = vec_splats(ss);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> zeroinitializer
+ // CHECK-ASM: vlreph
vus = vec_splats(us);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> zeroinitializer
+ // CHECK-ASM: vlreph
vsi = vec_splats(si);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> zeroinitializer
+ // CHECK-ASM: vlrepf
vui = vec_splats(ui);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> zeroinitializer
+ // CHECK-ASM: vlrepf
vsl = vec_splats(sl);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vlrepg
vul = vec_splats(ul);
// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vlrepg
vd = vec_splats(d);
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vlrepg
vsl = vec_extend_s64(vsc);
+ // CHECK-ASM: vsegb
vsl = vec_extend_s64(vss);
+ // CHECK-ASM: vsegh
vsl = vec_extend_s64(vsi);
+ // CHECK-ASM: vsegf
vsc = vec_mergeh(vsc, vsc);
// shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
+ // CHECK-ASM: vmrhb
vuc = vec_mergeh(vuc, vuc);
// shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
+ // CHECK-ASM: vmrhb
vbc = vec_mergeh(vbc, vbc);
// shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
+ // CHECK-ASM: vmrhb
vss = vec_mergeh(vss, vss);
// shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+ // CHECK-ASM: vmrhh
vus = vec_mergeh(vus, vus);
// shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+ // CHECK-ASM: vmrhh
vbs = vec_mergeh(vbs, vbs);
// shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+ // CHECK-ASM: vmrhh
vsi = vec_mergeh(vsi, vsi);
// shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+ // CHECK-ASM: vmrhf
vui = vec_mergeh(vui, vui);
// shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+ // CHECK-ASM: vmrhf
vbi = vec_mergeh(vbi, vbi);
// shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+ // CHECK-ASM: vmrhf
vsl = vec_mergeh(vsl, vsl);
// shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 0, i32 2>
+ // CHECK-ASM: vmrhg
vul = vec_mergeh(vul, vul);
// shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 0, i32 2>
+ // CHECK-ASM: vmrhg
vbl = vec_mergeh(vbl, vbl);
// shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 0, i32 2>
+ // CHECK-ASM: vmrhg
vd = vec_mergeh(vd, vd);
// shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 0, i32 2>
+ // CHECK-ASM: vmrhg
vsc = vec_mergel(vsc, vsc);
// shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
+ // CHECK-ASM: vmrlb
vuc = vec_mergel(vuc, vuc);
// shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
+ // CHECK-ASM: vmrlb
vbc = vec_mergel(vbc, vbc);
// shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %a, <16 x i8> %b, <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
+ // CHECK-ASM: vmrlb
vss = vec_mergel(vss, vss);
// shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+ // CHECK-ASM: vmrlh
vus = vec_mergel(vus, vus);
// shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+ // CHECK-ASM: vmrlh
vbs = vec_mergel(vbs, vbs);
// shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+ // CHECK-ASM: vmrlh
vsi = vec_mergel(vsi, vsi);
// shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <i32 2, i32 6, i32 3, i32 7>
+ // CHECK-ASM: vmrlf
vui = vec_mergel(vui, vui);
// shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <i32 2, i32 6, i32 3, i32 7>
+ // CHECK-ASM: vmrlf
vbi = vec_mergel(vbi, vbi);
// shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <i32 2, i32 6, i32 3, i32 7>
+ // CHECK-ASM: vmrlf
vsl = vec_mergel(vsl, vsl);
// shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <i32 1, i32 3>
+ // CHECK-ASM: vmrlg
vul = vec_mergel(vul, vul);
// shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <i32 1, i32 3>
+ // CHECK-ASM: vmrlg
vbl = vec_mergel(vbl, vbl);
// shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <i32 1, i32 3>
+ // CHECK-ASM: vmrlg
vd = vec_mergel(vd, vd);
// shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <i32 1, i32 3>
+ // CHECK-ASM: vmrlg
vsc = vec_pack(vss, vss);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
+ // CHECK-ASM: vpkh
vuc = vec_pack(vus, vus);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
+ // CHECK-ASM: vpkh
vbc = vec_pack(vbs, vbs);
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25, i32 27, i32 29, i32 31>
+ // CHECK-ASM: vpkh
vss = vec_pack(vsi, vsi);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+ // CHECK-ASM: vpkf
vus = vec_pack(vui, vui);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+ // CHECK-ASM: vpkf
vbs = vec_pack(vbi, vbi);
// CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+ // CHECK-ASM: vpkf
vsi = vec_pack(vsl, vsl);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ // CHECK-ASM: vpkg
vui = vec_pack(vul, vul);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ // CHECK-ASM: vpkg
vbi = vec_pack(vbl, vbl);
// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ // CHECK-ASM: vpkg
vsc = vec_packs(vss, vss);
// CHECK: call <16 x i8> @llvm.s390.vpksh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vpksh
vuc = vec_packs(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vpklsh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vpklsh
vss = vec_packs(vsi, vsi);
// CHECK: call <8 x i16> @llvm.s390.vpksf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vpksf
vus = vec_packs(vui, vui);
// CHECK: call <8 x i16> @llvm.s390.vpklsf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vpklsf
vsi = vec_packs(vsl, vsl);
// CHECK: call <4 x i32> @llvm.s390.vpksg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vpksg
vui = vec_packs(vul, vul);
// CHECK: call <4 x i32> @llvm.s390.vpklsg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vpklsg
vsc = vec_packs_cc(vss, vss, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vpkshs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vpkshs
vuc = vec_packs_cc(vus, vus, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vpklshs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vpklshs
vss = vec_packs_cc(vsi, vsi, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vpksfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vpksfs
vus = vec_packs_cc(vui, vui, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vpklsfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vpklsfs
vsi = vec_packs_cc(vsl, vsl, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vpksgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vpksgs
vui = vec_packs_cc(vul, vul, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vpklsgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vpklsgs
vuc = vec_packsu(vss, vss);
// CHECK: call <16 x i8> @llvm.s390.vpklsh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vpklsh
vuc = vec_packsu(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vpklsh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vpklsh
vus = vec_packsu(vsi, vsi);
// CHECK: call <8 x i16> @llvm.s390.vpklsf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vpklsf
vus = vec_packsu(vui, vui);
// CHECK: call <8 x i16> @llvm.s390.vpklsf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vpklsf
vui = vec_packsu(vsl, vsl);
// CHECK: call <4 x i32> @llvm.s390.vpklsg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vpklsg
vui = vec_packsu(vul, vul);
// CHECK: call <4 x i32> @llvm.s390.vpklsg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vpklsg
vuc = vec_packsu_cc(vus, vus, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vpklshs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vpklshs
vus = vec_packsu_cc(vui, vui, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vpklsfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vpklsfs
vui = vec_packsu_cc(vul, vul, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vpklsgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vpklsgs
vss = vec_unpackh(vsc);
// CHECK: call <8 x i16> @llvm.s390.vuphb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vuphb
vus = vec_unpackh(vuc);
// CHECK: call <8 x i16> @llvm.s390.vuplhb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vuplhb
vbs = vec_unpackh(vbc);
// CHECK: call <8 x i16> @llvm.s390.vuphb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vuphb
vsi = vec_unpackh(vss);
// CHECK: call <4 x i32> @llvm.s390.vuphh(<8 x i16> %{{.*}})
+ // CHECK-ASM: vuphh
vui = vec_unpackh(vus);
// CHECK: call <4 x i32> @llvm.s390.vuplhh(<8 x i16> %{{.*}})
+ // CHECK-ASM: vuplhh
vbi = vec_unpackh(vbs);
// CHECK: call <4 x i32> @llvm.s390.vuphh(<8 x i16> %{{.*}})
+ // CHECK-ASM: vuphh
vsl = vec_unpackh(vsi);
// CHECK: call <2 x i64> @llvm.s390.vuphf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vuphf
vul = vec_unpackh(vui);
// CHECK: call <2 x i64> @llvm.s390.vuplhf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vuplhf
vbl = vec_unpackh(vbi);
// CHECK: call <2 x i64> @llvm.s390.vuphf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vuphf
vss = vec_unpackl(vsc);
// CHECK: call <8 x i16> @llvm.s390.vuplb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vuplb
vus = vec_unpackl(vuc);
// CHECK: call <8 x i16> @llvm.s390.vupllb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vupllb
vbs = vec_unpackl(vbc);
// CHECK: call <8 x i16> @llvm.s390.vuplb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vuplb
vsi = vec_unpackl(vss);
// CHECK: call <4 x i32> @llvm.s390.vuplhw(<8 x i16> %{{.*}})
+ // CHECK-ASM: vuplhw
vui = vec_unpackl(vus);
// CHECK: call <4 x i32> @llvm.s390.vupllh(<8 x i16> %{{.*}})
+ // CHECK-ASM: vupllh
vbi = vec_unpackl(vbs);
// CHECK: call <4 x i32> @llvm.s390.vuplhw(<8 x i16> %{{.*}})
+ // CHECK-ASM: vuplhw
vsl = vec_unpackl(vsi);
// CHECK: call <2 x i64> @llvm.s390.vuplf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vuplf
vul = vec_unpackl(vui);
// CHECK: call <2 x i64> @llvm.s390.vupllf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vupllf
vbl = vec_unpackl(vbi);
// CHECK: call <2 x i64> @llvm.s390.vuplf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vuplf
}
void test_compare(void) {
+ // CHECK-ASM-LABEL: test_compare
+
vbc = vec_cmpeq(vsc, vsc);
// CHECK: icmp eq <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqb
vbc = vec_cmpeq(vuc, vuc);
// CHECK: icmp eq <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqb
vbc = vec_cmpeq(vbc, vbc);
// CHECK: icmp eq <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqb
vbs = vec_cmpeq(vss, vss);
// CHECK: icmp eq <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqh
vbs = vec_cmpeq(vus, vus);
// CHECK: icmp eq <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqh
vbs = vec_cmpeq(vbs, vbs);
// CHECK: icmp eq <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqh
vbi = vec_cmpeq(vsi, vsi);
// CHECK: icmp eq <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqf
vbi = vec_cmpeq(vui, vui);
// CHECK: icmp eq <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqf
vbi = vec_cmpeq(vbi, vbi);
// CHECK: icmp eq <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqf
vbl = vec_cmpeq(vsl, vsl);
// CHECK: icmp eq <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqg
vbl = vec_cmpeq(vul, vul);
// CHECK: icmp eq <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqg
vbl = vec_cmpeq(vbl, vbl);
// CHECK: icmp eq <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vceqg
vbl = vec_cmpeq(vd, vd);
// CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfcedb
vbc = vec_cmpge(vsc, vsc);
// CHECK: icmp sge <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchb
vbc = vec_cmpge(vuc, vuc);
// CHECK: icmp uge <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlb
vbs = vec_cmpge(vss, vss);
// CHECK: icmp sge <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchh
vbs = vec_cmpge(vus, vus);
// CHECK: icmp uge <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlh
vbi = vec_cmpge(vsi, vsi);
// CHECK: icmp sge <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchf
vbi = vec_cmpge(vui, vui);
// CHECK: icmp uge <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlf
vbl = vec_cmpge(vsl, vsl);
// CHECK: icmp sge <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchg
vbl = vec_cmpge(vul, vul);
// CHECK: icmp uge <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlg
vbl = vec_cmpge(vd, vd);
// CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchedb
vbc = vec_cmpgt(vsc, vsc);
// CHECK: icmp sgt <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchb
vbc = vec_cmpgt(vuc, vuc);
// CHECK: icmp ugt <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlb
vbs = vec_cmpgt(vss, vss);
// CHECK: icmp sgt <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchh
vbs = vec_cmpgt(vus, vus);
// CHECK: icmp ugt <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlh
vbi = vec_cmpgt(vsi, vsi);
// CHECK: icmp sgt <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchf
vbi = vec_cmpgt(vui, vui);
// CHECK: icmp ugt <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlf
vbl = vec_cmpgt(vsl, vsl);
// CHECK: icmp sgt <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchg
vbl = vec_cmpgt(vul, vul);
// CHECK: icmp ugt <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlg
vbl = vec_cmpgt(vd, vd);
// CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchdb
vbc = vec_cmple(vsc, vsc);
// CHECK: icmp sle <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchb
vbc = vec_cmple(vuc, vuc);
// CHECK: icmp ule <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlb
vbs = vec_cmple(vss, vss);
// CHECK: icmp sle <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchh
vbs = vec_cmple(vus, vus);
// CHECK: icmp ule <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlh
vbi = vec_cmple(vsi, vsi);
// CHECK: icmp sle <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchf
vbi = vec_cmple(vui, vui);
// CHECK: icmp ule <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlf
vbl = vec_cmple(vsl, vsl);
// CHECK: icmp sle <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchg
vbl = vec_cmple(vul, vul);
// CHECK: icmp ule <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlg
vbl = vec_cmple(vd, vd);
// CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchedb
vbc = vec_cmplt(vsc, vsc);
// CHECK: icmp slt <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchb
vbc = vec_cmplt(vuc, vuc);
// CHECK: icmp ult <16 x i8> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlb
vbs = vec_cmplt(vss, vss);
// CHECK: icmp slt <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchh
vbs = vec_cmplt(vus, vus);
// CHECK: icmp ult <8 x i16> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlh
vbi = vec_cmplt(vsi, vsi);
// CHECK: icmp slt <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchf
vbi = vec_cmplt(vui, vui);
// CHECK: icmp ult <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlf
vbl = vec_cmplt(vsl, vsl);
// CHECK: icmp slt <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchg
vbl = vec_cmplt(vul, vul);
// CHECK: icmp ult <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vchlg
vbl = vec_cmplt(vd, vd);
// CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchdb
idx = vec_all_eq(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_eq(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_eq(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_eq(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_eq(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_eq(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_eq(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_eq(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_eq(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_eq(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_eq(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_eq(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_eq(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_eq(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_eq(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_eq(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_eq(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_eq(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_eq(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_eq(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_eq(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_eq(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_eq(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_eq(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_eq(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_eq(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_eq(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_eq(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_eq(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_all_ne(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_ne(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_ne(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_ne(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_ne(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_ne(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_ne(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_all_ne(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_ne(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_ne(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_ne(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_ne(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_ne(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_ne(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_all_ne(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_ne(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_ne(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_ne(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_ne(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_ne(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_ne(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_all_ne(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_ne(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_ne(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_ne(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_ne(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_ne(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_ne(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_all_ne(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_all_ge(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_ge(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_ge(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_ge(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_ge(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_ge(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_ge(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_ge(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_ge(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_ge(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_ge(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_ge(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_ge(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_ge(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_ge(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_ge(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_ge(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_ge(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_ge(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_ge(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_ge(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_ge(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_ge(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_ge(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_ge(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_ge(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_ge(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_ge(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_ge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_gt(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_gt(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_gt(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_gt(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_gt(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_gt(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_gt(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_gt(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_gt(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_gt(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_gt(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_gt(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_gt(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_gt(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_gt(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_gt(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_gt(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_gt(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_gt(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_gt(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_gt(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_gt(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_gt(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_gt(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_gt(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_gt(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_gt(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_gt(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_gt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_all_le(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_le(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_le(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_le(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_le(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_le(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_le(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_le(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_le(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_le(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_le(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_le(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_le(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_le(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_le(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_le(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_le(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_le(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_le(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_le(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_le(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_le(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_le(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_le(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_le(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_le(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_le(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_le(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_le(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_lt(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_lt(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_lt(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_all_lt(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_lt(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_lt(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_lt(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_all_lt(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_lt(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_lt(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_all_lt(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_lt(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_lt(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_lt(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_all_lt(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_lt(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_lt(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_all_lt(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_lt(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_lt(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_lt(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_all_lt(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_lt(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_lt(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_all_lt(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_lt(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_lt(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_lt(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_all_lt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_all_nge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_ngt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_all_nle(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_nlt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_all_nan(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
idx = vec_all_numeric(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
idx = vec_any_eq(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_eq(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_eq(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_eq(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_eq(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_eq(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_eq(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_eq(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_eq(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_eq(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_eq(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_eq(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_eq(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_eq(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_eq(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_eq(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_eq(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_eq(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_eq(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_eq(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_eq(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_eq(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_eq(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_eq(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_eq(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_eq(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_eq(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_eq(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_eq(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_any_ne(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_ne(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_ne(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_ne(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_ne(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_ne(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_ne(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vceqbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vceqbs
idx = vec_any_ne(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_ne(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_ne(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_ne(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_ne(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_ne(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_ne(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vceqhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vceqhs
idx = vec_any_ne(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_ne(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_ne(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_ne(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_ne(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_ne(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_ne(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vceqfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vceqfs
idx = vec_any_ne(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_ne(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_ne(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_ne(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_ne(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_ne(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_ne(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vceqgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vceqgs
idx = vec_any_ne(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_any_ge(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_ge(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_ge(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_ge(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_ge(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_ge(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_ge(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_ge(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_ge(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_ge(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_ge(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_ge(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_ge(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_ge(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_ge(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_ge(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_ge(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_ge(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_ge(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_ge(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_ge(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_ge(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_ge(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_ge(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_ge(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_ge(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_ge(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_ge(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_ge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_gt(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_gt(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_gt(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_gt(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_gt(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_gt(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_gt(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_gt(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_gt(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_gt(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_gt(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_gt(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_gt(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_gt(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_gt(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_gt(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_gt(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_gt(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_gt(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_gt(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_gt(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_gt(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_gt(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_gt(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_gt(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_gt(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_gt(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_gt(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_gt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_le(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_le(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_le(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_le(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_le(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_le(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_le(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_le(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_le(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_le(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_le(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_le(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_le(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_le(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_le(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_le(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_le(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_le(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_le(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_le(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_le(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_le(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_le(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_le(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_le(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_le(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_le(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_le(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_le(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_lt(vsc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_lt(vsc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_lt(vbc, vsc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchbs
idx = vec_any_lt(vuc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_lt(vuc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_lt(vbc, vuc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_lt(vbc, vbc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vchlbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vchlbs
idx = vec_any_lt(vss, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_lt(vss, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_lt(vbs, vss);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchhs
idx = vec_any_lt(vus, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_lt(vus, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_lt(vbs, vus);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_lt(vbs, vbs);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vchlhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vchlhs
idx = vec_any_lt(vsi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_lt(vsi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_lt(vbi, vsi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchfs
idx = vec_any_lt(vui, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_lt(vui, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_lt(vbi, vui);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_lt(vbi, vbi);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vchlfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vchlfs
idx = vec_any_lt(vsl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_lt(vsl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_lt(vbl, vsl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchgs
idx = vec_any_lt(vul, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_lt(vul, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_lt(vbl, vul);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_lt(vbl, vbl);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vchlgs(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vchlgs
idx = vec_any_lt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_nge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_ngt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_nle(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_nlt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_nan(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
idx = vec_any_numeric(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
}
void test_integer(void) {
+ // CHECK-ASM-LABEL: test_integer
+
vsc = vec_andc(vsc, vsc);
+ // CHECK-ASM: vnc
vsc = vec_andc(vsc, vbc);
+ // CHECK-ASM: vnc
vsc = vec_andc(vbc, vsc);
+ // CHECK-ASM: vnc
vuc = vec_andc(vuc, vuc);
+ // CHECK-ASM: vnc
vuc = vec_andc(vuc, vbc);
+ // CHECK-ASM: vnc
vuc = vec_andc(vbc, vuc);
+ // CHECK-ASM: vnc
vbc = vec_andc(vbc, vbc);
+ // CHECK-ASM: vnc
vss = vec_andc(vss, vss);
+ // CHECK-ASM: vnc
vss = vec_andc(vss, vbs);
+ // CHECK-ASM: vnc
vss = vec_andc(vbs, vss);
+ // CHECK-ASM: vnc
vus = vec_andc(vus, vus);
+ // CHECK-ASM: vnc
vus = vec_andc(vus, vbs);
+ // CHECK-ASM: vnc
vus = vec_andc(vbs, vus);
+ // CHECK-ASM: vnc
vbs = vec_andc(vbs, vbs);
+ // CHECK-ASM: vnc
vsi = vec_andc(vsi, vsi);
+ // CHECK-ASM: vnc
vsi = vec_andc(vsi, vbi);
+ // CHECK-ASM: vnc
vsi = vec_andc(vbi, vsi);
+ // CHECK-ASM: vnc
vui = vec_andc(vui, vui);
+ // CHECK-ASM: vnc
vui = vec_andc(vui, vbi);
+ // CHECK-ASM: vnc
vui = vec_andc(vbi, vui);
+ // CHECK-ASM: vnc
vbi = vec_andc(vbi, vbi);
+ // CHECK-ASM: vnc
vsl = vec_andc(vsl, vsl);
+ // CHECK-ASM: vnc
vsl = vec_andc(vsl, vbl);
+ // CHECK-ASM: vnc
vsl = vec_andc(vbl, vsl);
+ // CHECK-ASM: vnc
vul = vec_andc(vul, vul);
+ // CHECK-ASM: vnc
vul = vec_andc(vul, vbl);
+ // CHECK-ASM: vnc
vul = vec_andc(vbl, vul);
+ // CHECK-ASM: vnc
vbl = vec_andc(vbl, vbl);
+ // CHECK-ASM: vnc
vd = vec_andc(vd, vd);
+ // CHECK-ASM: vnc
vd = vec_andc(vd, vbl);
+ // CHECK-ASM: vnc
vd = vec_andc(vbl, vd);
+ // CHECK-ASM: vnc
vsc = vec_nor(vsc, vsc);
+ // CHECK-ASM: vno
vsc = vec_nor(vsc, vbc);
+ // CHECK-ASM: vno
vsc = vec_nor(vbc, vsc);
+ // CHECK-ASM: vno
vuc = vec_nor(vuc, vuc);
+ // CHECK-ASM: vno
vuc = vec_nor(vuc, vbc);
+ // CHECK-ASM: vno
vuc = vec_nor(vbc, vuc);
+ // CHECK-ASM: vno
vbc = vec_nor(vbc, vbc);
+ // CHECK-ASM: vno
vss = vec_nor(vss, vss);
+ // CHECK-ASM: vno
vss = vec_nor(vss, vbs);
+ // CHECK-ASM: vno
vss = vec_nor(vbs, vss);
+ // CHECK-ASM: vno
vus = vec_nor(vus, vus);
+ // CHECK-ASM: vno
vus = vec_nor(vus, vbs);
+ // CHECK-ASM: vno
vus = vec_nor(vbs, vus);
+ // CHECK-ASM: vno
vbs = vec_nor(vbs, vbs);
+ // CHECK-ASM: vno
vsi = vec_nor(vsi, vsi);
+ // CHECK-ASM: vno
vsi = vec_nor(vsi, vbi);
+ // CHECK-ASM: vno
vsi = vec_nor(vbi, vsi);
+ // CHECK-ASM: vno
vui = vec_nor(vui, vui);
+ // CHECK-ASM: vno
vui = vec_nor(vui, vbi);
+ // CHECK-ASM: vno
vui = vec_nor(vbi, vui);
+ // CHECK-ASM: vno
vbi = vec_nor(vbi, vbi);
+ // CHECK-ASM: vno
vsl = vec_nor(vsl, vsl);
+ // CHECK-ASM: vno
vsl = vec_nor(vsl, vbl);
+ // CHECK-ASM: vno
vsl = vec_nor(vbl, vsl);
+ // CHECK-ASM: vno
vul = vec_nor(vul, vul);
+ // CHECK-ASM: vno
vul = vec_nor(vul, vbl);
+ // CHECK-ASM: vno
vul = vec_nor(vbl, vul);
+ // CHECK-ASM: vno
vbl = vec_nor(vbl, vbl);
+ // CHECK-ASM: vno
vd = vec_nor(vd, vd);
+ // CHECK-ASM: vno
vd = vec_nor(vd, vbl);
+ // CHECK-ASM: vno
vd = vec_nor(vbl, vd);
+ // CHECK-ASM: vno
vuc = vec_cntlz(vsc);
// CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzb
vuc = vec_cntlz(vuc);
// CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzb
vus = vec_cntlz(vss);
// CHECK: call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzh
vus = vec_cntlz(vus);
// CHECK: call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzh
vui = vec_cntlz(vsi);
// CHECK: call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzf
vui = vec_cntlz(vui);
// CHECK: call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzf
vul = vec_cntlz(vsl);
// CHECK: call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzg
vul = vec_cntlz(vul);
// CHECK: call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
+ // CHECK-ASM: vclzg
vuc = vec_cnttz(vsc);
// CHECK: call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzb
vuc = vec_cnttz(vuc);
// CHECK: call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzb
vus = vec_cnttz(vss);
// CHECK: call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzh
vus = vec_cnttz(vus);
// CHECK: call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzh
vui = vec_cnttz(vsi);
// CHECK: call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzf
vui = vec_cnttz(vui);
// CHECK: call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzf
vul = vec_cnttz(vsl);
// CHECK: call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzg
vul = vec_cnttz(vul);
// CHECK: call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
+ // CHECK-ASM: vctzg
vuc = vec_popcnt(vsc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
+ // CHECK-ASM: vpopct
vuc = vec_popcnt(vuc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
+ // CHECK-ASM: vpopct
vus = vec_popcnt(vss);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
+ // (emulated)
vus = vec_popcnt(vus);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
+ // (emulated)
vui = vec_popcnt(vsi);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
+ // (emulated)
vui = vec_popcnt(vui);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
+ // (emulated)
vul = vec_popcnt(vsl);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
+ // (emulated)
vul = vec_popcnt(vul);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
+ // (emulated)
vsc = vec_rl(vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.verllvb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: verllvb
vuc = vec_rl(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.verllvb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: verllvb
vss = vec_rl(vss, vus);
// CHECK: call <8 x i16> @llvm.s390.verllvh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: verllvh
vus = vec_rl(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.verllvh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: verllvh
vsi = vec_rl(vsi, vui);
// CHECK: call <4 x i32> @llvm.s390.verllvf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: verllvf
vui = vec_rl(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.verllvf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: verllvf
vsl = vec_rl(vsl, vul);
// CHECK: call <2 x i64> @llvm.s390.verllvg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: verllvg
vul = vec_rl(vul, vul);
// CHECK: call <2 x i64> @llvm.s390.verllvg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: verllvg
vsc = vec_rli(vsc, ul);
// CHECK: call <16 x i8> @llvm.s390.verllb(<16 x i8> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllb
vuc = vec_rli(vuc, ul);
// CHECK: call <16 x i8> @llvm.s390.verllb(<16 x i8> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllb
vss = vec_rli(vss, ul);
// CHECK: call <8 x i16> @llvm.s390.verllh(<8 x i16> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllh
vus = vec_rli(vus, ul);
// CHECK: call <8 x i16> @llvm.s390.verllh(<8 x i16> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllh
vsi = vec_rli(vsi, ul);
// CHECK: call <4 x i32> @llvm.s390.verllf(<4 x i32> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllf
vui = vec_rli(vui, ul);
// CHECK: call <4 x i32> @llvm.s390.verllf(<4 x i32> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllf
vsl = vec_rli(vsl, ul);
// CHECK: call <2 x i64> @llvm.s390.verllg(<2 x i64> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllg
vul = vec_rli(vul, ul);
// CHECK: call <2 x i64> @llvm.s390.verllg(<2 x i64> %{{.*}}, i32 %{{.*}})
+ // CHECK-ASM: verllg
vsc = vec_rl_mask(vsc, vuc, 0);
// CHECK: call <16 x i8> @llvm.s390.verimb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: verimb
vsc = vec_rl_mask(vsc, vuc, 255);
// CHECK: call <16 x i8> @llvm.s390.verimb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 255)
+ // CHECK-ASM: verimb
vuc = vec_rl_mask(vuc, vuc, 0);
// CHECK: call <16 x i8> @llvm.s390.verimb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: verimb
vuc = vec_rl_mask(vuc, vuc, 255);
// CHECK: call <16 x i8> @llvm.s390.verimb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 255)
+ // CHECK-ASM: verimb
vss = vec_rl_mask(vss, vus, 0);
// CHECK: call <8 x i16> @llvm.s390.verimh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: verimh
vss = vec_rl_mask(vss, vus, 255);
// CHECK: call <8 x i16> @llvm.s390.verimh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 255)
+ // CHECK-ASM: verimh
vus = vec_rl_mask(vus, vus, 0);
// CHECK: call <8 x i16> @llvm.s390.verimh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: verimh
vus = vec_rl_mask(vus, vus, 255);
// CHECK: call <8 x i16> @llvm.s390.verimh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 255)
+ // CHECK-ASM: verimh
vsi = vec_rl_mask(vsi, vui, 0);
// CHECK: call <4 x i32> @llvm.s390.verimf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: verimf
vsi = vec_rl_mask(vsi, vui, 255);
// CHECK: call <4 x i32> @llvm.s390.verimf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 255)
+ // CHECK-ASM: verimf
vui = vec_rl_mask(vui, vui, 0);
// CHECK: call <4 x i32> @llvm.s390.verimf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: verimf
vui = vec_rl_mask(vui, vui, 255);
// CHECK: call <4 x i32> @llvm.s390.verimf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 255)
+ // CHECK-ASM: verimf
vsl = vec_rl_mask(vsl, vul, 0);
// CHECK: call <2 x i64> @llvm.s390.verimg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 0)
+ // CHECK-ASM: verimg
vsl = vec_rl_mask(vsl, vul, 255);
// CHECK: call <2 x i64> @llvm.s390.verimg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 255)
+ // CHECK-ASM: verimg
vul = vec_rl_mask(vul, vul, 0);
// CHECK: call <2 x i64> @llvm.s390.verimg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 0)
+ // CHECK-ASM: verimg
vul = vec_rl_mask(vul, vul, 255);
// CHECK: call <2 x i64> @llvm.s390.verimg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, i32 255)
+ // CHECK-ASM: verimg
vsc = vec_sll(vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsc = vec_sll(vsc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsc = vec_sll(vsc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vuc = vec_sll(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vuc = vec_sll(vuc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vuc = vec_sll(vuc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbc = vec_sll(vbc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbc = vec_sll(vbc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbc = vec_sll(vbc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vss = vec_sll(vss, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vss = vec_sll(vss, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vss = vec_sll(vss, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vus = vec_sll(vus, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vus = vec_sll(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vus = vec_sll(vus, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbs = vec_sll(vbs, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbs = vec_sll(vbs, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbs = vec_sll(vbs, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsi = vec_sll(vsi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsi = vec_sll(vsi, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsi = vec_sll(vsi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vui = vec_sll(vui, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vui = vec_sll(vui, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vui = vec_sll(vui, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbi = vec_sll(vbi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbi = vec_sll(vbi, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbi = vec_sll(vbi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsl = vec_sll(vsl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsl = vec_sll(vsl, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsl = vec_sll(vsl, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vul = vec_sll(vul, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vul = vec_sll(vul, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vul = vec_sll(vul, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbl = vec_sll(vbl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbl = vec_sll(vbl, vus);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vbl = vec_sll(vbl, vui);
// CHECK: call <16 x i8> @llvm.s390.vsl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsl
vsc = vec_slb(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vsc = vec_slb(vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vuc = vec_slb(vuc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vuc = vec_slb(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vss = vec_slb(vss, vss);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vss = vec_slb(vss, vus);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vus = vec_slb(vus, vss);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vus = vec_slb(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vsi = vec_slb(vsi, vsi);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vsi = vec_slb(vsi, vui);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vui = vec_slb(vui, vsi);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vui = vec_slb(vui, vui);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vsl = vec_slb(vsl, vsl);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vsl = vec_slb(vsl, vul);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vul = vec_slb(vul, vsl);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vul = vec_slb(vul, vul);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vd = vec_slb(vd, vsl);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vd = vec_slb(vd, vul);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vsc = vec_sld(vsc, vsc, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vsc = vec_sld(vsc, vsc, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vuc = vec_sld(vuc, vuc, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vuc = vec_sld(vuc, vuc, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vbc = vec_sld(vbc, vbc, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vbc = vec_sld(vbc, vbc, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vss = vec_sld(vss, vss, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vss = vec_sld(vss, vss, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vus = vec_sld(vus, vus, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vus = vec_sld(vus, vus, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vbs = vec_sld(vbs, vbs, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vbs = vec_sld(vbs, vbs, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vsi = vec_sld(vsi, vsi, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vsi = vec_sld(vsi, vsi, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vui = vec_sld(vui, vui, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vui = vec_sld(vui, vui, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vbi = vec_sld(vbi, vbi, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vbi = vec_sld(vbi, vbi, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vsl = vec_sld(vsl, vsl, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vsl = vec_sld(vsl, vsl, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vul = vec_sld(vul, vul, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vul = vec_sld(vul, vul, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vbl = vec_sld(vbl, vbl, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vbl = vec_sld(vbl, vbl, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vd = vec_sld(vd, vd, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vd = vec_sld(vd, vd, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vsc = vec_sldw(vsc, vsc, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vsc = vec_sldw(vsc, vsc, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vuc = vec_sldw(vuc, vuc, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vuc = vec_sldw(vuc, vuc, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vss = vec_sldw(vss, vss, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vss = vec_sldw(vss, vss, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vus = vec_sldw(vus, vus, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vus = vec_sldw(vus, vus, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vsi = vec_sldw(vsi, vsi, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vsi = vec_sldw(vsi, vsi, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vui = vec_sldw(vui, vui, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vui = vec_sldw(vui, vui, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vsl = vec_sldw(vsl, vsl, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vsl = vec_sldw(vsl, vsl, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vul = vec_sldw(vul, vul, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vul = vec_sldw(vul, vul, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vd = vec_sldw(vd, vd, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vd = vec_sldw(vd, vd, 3);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vsldb
vsc = vec_sral(vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsc = vec_sral(vsc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsc = vec_sral(vsc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vuc = vec_sral(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vuc = vec_sral(vuc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vuc = vec_sral(vuc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbc = vec_sral(vbc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbc = vec_sral(vbc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbc = vec_sral(vbc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vss = vec_sral(vss, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vss = vec_sral(vss, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vss = vec_sral(vss, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vus = vec_sral(vus, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vus = vec_sral(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vus = vec_sral(vus, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbs = vec_sral(vbs, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbs = vec_sral(vbs, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbs = vec_sral(vbs, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsi = vec_sral(vsi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsi = vec_sral(vsi, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsi = vec_sral(vsi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vui = vec_sral(vui, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vui = vec_sral(vui, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vui = vec_sral(vui, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbi = vec_sral(vbi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbi = vec_sral(vbi, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbi = vec_sral(vbi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsl = vec_sral(vsl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsl = vec_sral(vsl, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsl = vec_sral(vsl, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vul = vec_sral(vul, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vul = vec_sral(vul, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vul = vec_sral(vul, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbl = vec_sral(vbl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbl = vec_sral(vbl, vus);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vbl = vec_sral(vbl, vui);
// CHECK: call <16 x i8> @llvm.s390.vsra(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsra
vsc = vec_srab(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vsc = vec_srab(vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vuc = vec_srab(vuc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vuc = vec_srab(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vss = vec_srab(vss, vss);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vss = vec_srab(vss, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vus = vec_srab(vus, vss);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vus = vec_srab(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vsi = vec_srab(vsi, vsi);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vsi = vec_srab(vsi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vui = vec_srab(vui, vsi);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vui = vec_srab(vui, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vsl = vec_srab(vsl, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vsl = vec_srab(vsl, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vul = vec_srab(vul, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vul = vec_srab(vul, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vd = vec_srab(vd, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vd = vec_srab(vd, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vsc = vec_srl(vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsc = vec_srl(vsc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsc = vec_srl(vsc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vuc = vec_srl(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vuc = vec_srl(vuc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vuc = vec_srl(vuc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbc = vec_srl(vbc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbc = vec_srl(vbc, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbc = vec_srl(vbc, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vss = vec_srl(vss, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vss = vec_srl(vss, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vss = vec_srl(vss, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vus = vec_srl(vus, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vus = vec_srl(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vus = vec_srl(vus, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbs = vec_srl(vbs, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbs = vec_srl(vbs, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbs = vec_srl(vbs, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsi = vec_srl(vsi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsi = vec_srl(vsi, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsi = vec_srl(vsi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vui = vec_srl(vui, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vui = vec_srl(vui, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vui = vec_srl(vui, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbi = vec_srl(vbi, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbi = vec_srl(vbi, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbi = vec_srl(vbi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsl = vec_srl(vsl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsl = vec_srl(vsl, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsl = vec_srl(vsl, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vul = vec_srl(vul, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vul = vec_srl(vul, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vul = vec_srl(vul, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbl = vec_srl(vbl, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbl = vec_srl(vbl, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vbl = vec_srl(vbl, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrl(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrl
vsc = vec_srb(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vsc = vec_srb(vsc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vuc = vec_srb(vuc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vuc = vec_srb(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vss = vec_srb(vss, vss);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vss = vec_srb(vss, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vus = vec_srb(vus, vss);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vus = vec_srb(vus, vus);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vsi = vec_srb(vsi, vsi);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vsi = vec_srb(vsi, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vui = vec_srb(vui, vsi);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vui = vec_srb(vui, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vsl = vec_srb(vsl, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vsl = vec_srb(vsl, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vul = vec_srb(vul, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vul = vec_srb(vul, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vd = vec_srb(vd, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vd = vec_srb(vd, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vsc = vec_abs(vsc);
+ // CHECK-ASM: vlpb
vss = vec_abs(vss);
+ // CHECK-ASM: vlph
vsi = vec_abs(vsi);
+ // CHECK-ASM: vlpf
vsl = vec_abs(vsl);
+ // CHECK-ASM: vlpg
vsc = vec_max(vsc, vsc);
+ // CHECK-ASM: vmxb
vsc = vec_max(vsc, vbc);
+ // CHECK-ASM: vmxb
vsc = vec_max(vbc, vsc);
+ // CHECK-ASM: vmxb
vuc = vec_max(vuc, vuc);
+ // CHECK-ASM: vmxlb
vuc = vec_max(vuc, vbc);
+ // CHECK-ASM: vmxlb
vuc = vec_max(vbc, vuc);
+ // CHECK-ASM: vmxlb
vss = vec_max(vss, vss);
+ // CHECK-ASM: vmxh
vss = vec_max(vss, vbs);
+ // CHECK-ASM: vmxh
vss = vec_max(vbs, vss);
+ // CHECK-ASM: vmxh
vus = vec_max(vus, vus);
+ // CHECK-ASM: vmxlh
vus = vec_max(vus, vbs);
+ // CHECK-ASM: vmxlh
vus = vec_max(vbs, vus);
+ // CHECK-ASM: vmxlh
vsi = vec_max(vsi, vsi);
+ // CHECK-ASM: vmxf
vsi = vec_max(vsi, vbi);
+ // CHECK-ASM: vmxf
vsi = vec_max(vbi, vsi);
+ // CHECK-ASM: vmxf
vui = vec_max(vui, vui);
+ // CHECK-ASM: vmxlf
vui = vec_max(vui, vbi);
+ // CHECK-ASM: vmxlf
vui = vec_max(vbi, vui);
+ // CHECK-ASM: vmxlf
vsl = vec_max(vsl, vsl);
+ // CHECK-ASM: vmxg
vsl = vec_max(vsl, vbl);
+ // CHECK-ASM: vmxg
vsl = vec_max(vbl, vsl);
+ // CHECK-ASM: vmxg
vul = vec_max(vul, vul);
+ // CHECK-ASM: vmxlg
vul = vec_max(vul, vbl);
+ // CHECK-ASM: vmxlg
vul = vec_max(vbl, vul);
+ // CHECK-ASM: vmxlg
vd = vec_max(vd, vd);
+ // (emulated)
vsc = vec_min(vsc, vsc);
+ // CHECK-ASM: vmnb
vsc = vec_min(vsc, vbc);
+ // CHECK-ASM: vmnb
vsc = vec_min(vbc, vsc);
+ // CHECK-ASM: vmnb
vuc = vec_min(vuc, vuc);
+ // CHECK-ASM: vmnlb
vuc = vec_min(vuc, vbc);
+ // CHECK-ASM: vmnlb
vuc = vec_min(vbc, vuc);
+ // CHECK-ASM: vmnlb
vss = vec_min(vss, vss);
+ // CHECK-ASM: vmnh
vss = vec_min(vss, vbs);
+ // CHECK-ASM: vmnh
vss = vec_min(vbs, vss);
+ // CHECK-ASM: vmnh
vus = vec_min(vus, vus);
+ // CHECK-ASM: vmnlh
vus = vec_min(vus, vbs);
+ // CHECK-ASM: vmnlh
vus = vec_min(vbs, vus);
+ // CHECK-ASM: vmnlh
vsi = vec_min(vsi, vsi);
+ // CHECK-ASM: vmnf
vsi = vec_min(vsi, vbi);
+ // CHECK-ASM: vmnf
vsi = vec_min(vbi, vsi);
+ // CHECK-ASM: vmnf
vui = vec_min(vui, vui);
+ // CHECK-ASM: vmnlf
vui = vec_min(vui, vbi);
+ // CHECK-ASM: vmnlf
vui = vec_min(vbi, vui);
+ // CHECK-ASM: vmnlf
vsl = vec_min(vsl, vsl);
+ // CHECK-ASM: vmng
vsl = vec_min(vsl, vbl);
+ // CHECK-ASM: vmng
vsl = vec_min(vbl, vsl);
+ // CHECK-ASM: vmng
vul = vec_min(vul, vul);
+ // CHECK-ASM: vmnlg
vul = vec_min(vul, vbl);
+ // CHECK-ASM: vmnlg
vul = vec_min(vbl, vul);
+ // CHECK-ASM: vmnlg
vd = vec_min(vd, vd);
+ // (emulated)
vuc = vec_addc(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vaccb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vaccb
vus = vec_addc(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vacch(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vacch
vui = vec_addc(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vaccf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vaccf
vul = vec_addc(vul, vul);
// CHECK: call <2 x i64> @llvm.s390.vaccg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vaccg
vuc = vec_add_u128(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vaq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vaq
vuc = vec_addc_u128(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vaccq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vaccq
vuc = vec_adde_u128(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vacq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vacq
vuc = vec_addec_u128(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vacccq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vacccq
vsc = vec_avg(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vavgb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vavgb
vuc = vec_avg(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vavglb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vavglb
vss = vec_avg(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vavgh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vavgh
vus = vec_avg(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vavglh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vavglh
vsi = vec_avg(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vavgf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vavgf
vui = vec_avg(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vavglf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vavglf
vsl = vec_avg(vsl, vsl);
// CHECK: call <2 x i64> @llvm.s390.vavgg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vavgg
vul = vec_avg(vul, vul);
// CHECK: call <2 x i64> @llvm.s390.vavglg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vavglg
vui = vec_checksum(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vcksm(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vcksm
vus = vec_gfmsum(vuc, vuc);
// CHECK: call <8 x i16> @llvm.s390.vgfmb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vgfmb
vui = vec_gfmsum(vus, vus);
// CHECK: call <4 x i32> @llvm.s390.vgfmh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vgfmh
vul = vec_gfmsum(vui, vui);
// CHECK: call <2 x i64> @llvm.s390.vgfmf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vgfmf
vuc = vec_gfmsum_128(vul, vul);
// CHECK: call <16 x i8> @llvm.s390.vgfmg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vgfmg
vus = vec_gfmsum_accum(vuc, vuc, vus);
// CHECK: call <8 x i16> @llvm.s390.vgfmab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vgfmab
vui = vec_gfmsum_accum(vus, vus, vui);
// CHECK: call <4 x i32> @llvm.s390.vgfmah(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vgfmah
vul = vec_gfmsum_accum(vui, vui, vul);
// CHECK: call <2 x i64> @llvm.s390.vgfmaf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vgfmaf
vuc = vec_gfmsum_accum_128(vul, vul, vuc);
// CHECK: call <16 x i8> @llvm.s390.vgfmag(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vgfmag
vsc = vec_mladd(vsc, vsc, vsc);
+ // CHECK-ASM: vmalb
vsc = vec_mladd(vuc, vsc, vsc);
+ // CHECK-ASM: vmalb
vsc = vec_mladd(vsc, vuc, vuc);
+ // CHECK-ASM: vmalb
vuc = vec_mladd(vuc, vuc, vuc);
+ // CHECK-ASM: vmalb
vss = vec_mladd(vss, vss, vss);
+ // CHECK-ASM: vmalhw
vss = vec_mladd(vus, vss, vss);
+ // CHECK-ASM: vmalhw
vss = vec_mladd(vss, vus, vus);
+ // CHECK-ASM: vmalhw
vus = vec_mladd(vus, vus, vus);
+ // CHECK-ASM: vmalhw
vsi = vec_mladd(vsi, vsi, vsi);
+ // CHECK-ASM: vmalf
vsi = vec_mladd(vui, vsi, vsi);
+ // CHECK-ASM: vmalf
vsi = vec_mladd(vsi, vui, vui);
+ // CHECK-ASM: vmalf
vui = vec_mladd(vui, vui, vui);
+ // CHECK-ASM: vmalf
vsc = vec_mhadd(vsc, vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vmahb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmahb
vuc = vec_mhadd(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vmalhb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmalhb
vss = vec_mhadd(vss, vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vmahh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmahh
vus = vec_mhadd(vus, vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vmalhh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmalhh
vsi = vec_mhadd(vsi, vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vmahf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmahf
vui = vec_mhadd(vui, vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vmalhf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmalhf
vss = vec_meadd(vsc, vsc, vss);
// CHECK: call <8 x i16> @llvm.s390.vmaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmaeb
vus = vec_meadd(vuc, vuc, vus);
// CHECK: call <8 x i16> @llvm.s390.vmaleb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmaleb
vsi = vec_meadd(vss, vss, vsi);
// CHECK: call <4 x i32> @llvm.s390.vmaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmaeh
vui = vec_meadd(vus, vus, vui);
// CHECK: call <4 x i32> @llvm.s390.vmaleh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmaleh
vsl = vec_meadd(vsi, vsi, vsl);
// CHECK: call <2 x i64> @llvm.s390.vmaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vmaef
vul = vec_meadd(vui, vui, vul);
// CHECK: call <2 x i64> @llvm.s390.vmalef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vmalef
vss = vec_moadd(vsc, vsc, vss);
// CHECK: call <8 x i16> @llvm.s390.vmaob(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmaob
vus = vec_moadd(vuc, vuc, vus);
// CHECK: call <8 x i16> @llvm.s390.vmalob(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmalob
vsi = vec_moadd(vss, vss, vsi);
// CHECK: call <4 x i32> @llvm.s390.vmaoh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmaoh
vui = vec_moadd(vus, vus, vui);
// CHECK: call <4 x i32> @llvm.s390.vmaloh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmaloh
vsl = vec_moadd(vsi, vsi, vsl);
// CHECK: call <2 x i64> @llvm.s390.vmaof(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vmaof
vul = vec_moadd(vui, vui, vul);
// CHECK: call <2 x i64> @llvm.s390.vmalof(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vmalof
vsc = vec_mulh(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vmhb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmhb
vuc = vec_mulh(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vmlhb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmlhb
vss = vec_mulh(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vmhh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmhh
vus = vec_mulh(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vmlhh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmlhh
vsi = vec_mulh(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vmhf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmhf
vui = vec_mulh(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vmlhf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmlhf
vss = vec_mule(vsc, vsc);
// CHECK: call <8 x i16> @llvm.s390.vmeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmeb
vus = vec_mule(vuc, vuc);
// CHECK: call <8 x i16> @llvm.s390.vmleb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmleb
vsi = vec_mule(vss, vss);
// CHECK: call <4 x i32> @llvm.s390.vmeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmeh
vui = vec_mule(vus, vus);
// CHECK: call <4 x i32> @llvm.s390.vmleh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmleh
vsl = vec_mule(vsi, vsi);
// CHECK: call <2 x i64> @llvm.s390.vmef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmef
vul = vec_mule(vui, vui);
// CHECK: call <2 x i64> @llvm.s390.vmlef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmlef
vss = vec_mulo(vsc, vsc);
// CHECK: call <8 x i16> @llvm.s390.vmob(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmob
vus = vec_mulo(vuc, vuc);
// CHECK: call <8 x i16> @llvm.s390.vmlob(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vmlob
vsi = vec_mulo(vss, vss);
// CHECK: call <4 x i32> @llvm.s390.vmoh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmoh
vui = vec_mulo(vus, vus);
// CHECK: call <4 x i32> @llvm.s390.vmloh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vmloh
vsl = vec_mulo(vsi, vsi);
// CHECK: call <2 x i64> @llvm.s390.vmof(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmof
vul = vec_mulo(vui, vui);
// CHECK: call <2 x i64> @llvm.s390.vmlof(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vmlof
vuc = vec_subc(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vscbib(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vscbib
vus = vec_subc(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vscbih(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vscbih
vui = vec_subc(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vscbif(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vscbif
vul = vec_subc(vul, vul);
// CHECK: call <2 x i64> @llvm.s390.vscbig(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vscbig
vuc = vec_sub_u128(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsq
vuc = vec_subc_u128(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vscbiq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vscbiq
vuc = vec_sube_u128(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsbiq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsbiq
vuc = vec_subec_u128(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vsbcbiq(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsbcbiq
vui = vec_sum4(vuc, vuc);
// CHECK: call <4 x i32> @llvm.s390.vsumb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsumb
vui = vec_sum4(vus, vus);
// CHECK: call <4 x i32> @llvm.s390.vsumh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vsumh
vul = vec_sum2(vus, vus);
// CHECK: call <2 x i64> @llvm.s390.vsumgh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vsumgh
vul = vec_sum2(vui, vui);
// CHECK: call <2 x i64> @llvm.s390.vsumgf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vsumgf
vuc = vec_sum_u128(vui, vui);
// CHECK: call <16 x i8> @llvm.s390.vsumqf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vsumqf
vuc = vec_sum_u128(vul, vul);
// CHECK: call <16 x i8> @llvm.s390.vsumqg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK-ASM: vsumqg
idx = vec_test_mask(vsc, vuc);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vuc, vuc);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vss, vus);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vus, vus);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vsi, vui);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vui, vui);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vsl, vul);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vul, vul);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vd, vul);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
}
void test_string(void) {
+ // CHECK-ASM-LABEL: test_string
+
vsc = vec_cp_until_zero(vsc);
// CHECK: call <16 x i8> @llvm.s390.vistrb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vistrb
vuc = vec_cp_until_zero(vuc);
// CHECK: call <16 x i8> @llvm.s390.vistrb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vistrb
vbc = vec_cp_until_zero(vbc);
// CHECK: call <16 x i8> @llvm.s390.vistrb(<16 x i8> %{{.*}})
+ // CHECK-ASM: vistrb
vss = vec_cp_until_zero(vss);
// CHECK: call <8 x i16> @llvm.s390.vistrh(<8 x i16> %{{.*}})
+ // CHECK-ASM: vistrh
vus = vec_cp_until_zero(vus);
// CHECK: call <8 x i16> @llvm.s390.vistrh(<8 x i16> %{{.*}})
+ // CHECK-ASM: vistrh
vbs = vec_cp_until_zero(vbs);
// CHECK: call <8 x i16> @llvm.s390.vistrh(<8 x i16> %{{.*}})
+ // CHECK-ASM: vistrh
vsi = vec_cp_until_zero(vsi);
// CHECK: call <4 x i32> @llvm.s390.vistrf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vistrf
vui = vec_cp_until_zero(vui);
// CHECK: call <4 x i32> @llvm.s390.vistrf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vistrf
vbi = vec_cp_until_zero(vbi);
// CHECK: call <4 x i32> @llvm.s390.vistrf(<4 x i32> %{{.*}})
+ // CHECK-ASM: vistrf
vsc = vec_cp_until_zero_cc(vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vistrbs(<16 x i8> %{{.*}})
+ // CHECK-ASM: vistrbs
vuc = vec_cp_until_zero_cc(vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vistrbs(<16 x i8> %{{.*}})
+ // CHECK-ASM: vistrbs
vbc = vec_cp_until_zero_cc(vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vistrbs(<16 x i8> %{{.*}})
+ // CHECK-ASM: vistrbs
vss = vec_cp_until_zero_cc(vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vistrhs(<8 x i16> %{{.*}})
+ // CHECK-ASM: vistrhs
vus = vec_cp_until_zero_cc(vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vistrhs(<8 x i16> %{{.*}})
+ // CHECK-ASM: vistrhs
vbs = vec_cp_until_zero_cc(vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vistrhs(<8 x i16> %{{.*}})
+ // CHECK-ASM: vistrhs
vsi = vec_cp_until_zero_cc(vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vistrfs(<4 x i32> %{{.*}})
+ // CHECK-ASM: vistrfs
vui = vec_cp_until_zero_cc(vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vistrfs(<4 x i32> %{{.*}})
+ // CHECK-ASM: vistrfs
vbi = vec_cp_until_zero_cc(vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vistrfs(<4 x i32> %{{.*}})
+ // CHECK-ASM: vistrfs
vsc = vec_cmpeq_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfeeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeeb
vuc = vec_cmpeq_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfeeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeeb
vuc = vec_cmpeq_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfeeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeeb
vss = vec_cmpeq_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfeeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeeh
vus = vec_cmpeq_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfeeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeeh
vus = vec_cmpeq_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfeeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeeh
vsi = vec_cmpeq_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfeef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeef
vui = vec_cmpeq_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfeef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeef
vui = vec_cmpeq_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfeef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeef
vsc = vec_cmpeq_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfeebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeebs
vuc = vec_cmpeq_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfeebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeebs
vuc = vec_cmpeq_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfeebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeebs
vss = vec_cmpeq_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfeehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeehs
vus = vec_cmpeq_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfeehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeehs
vus = vec_cmpeq_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfeehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeehs
vsi = vec_cmpeq_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfeefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeefs
vui = vec_cmpeq_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfeefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeefs
vui = vec_cmpeq_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfeefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeefs
vsc = vec_cmpeq_or_0_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfeezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeezb
vuc = vec_cmpeq_or_0_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfeezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeezb
vuc = vec_cmpeq_or_0_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfeezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeezb
vss = vec_cmpeq_or_0_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfeezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeezh
vus = vec_cmpeq_or_0_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfeezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeezh
vus = vec_cmpeq_or_0_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfeezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeezh
vsi = vec_cmpeq_or_0_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfeezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeezf
vui = vec_cmpeq_or_0_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfeezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeezf
vui = vec_cmpeq_or_0_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfeezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeezf
vsc = vec_cmpeq_or_0_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfeezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeezbs
vuc = vec_cmpeq_or_0_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfeezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeezbs
vuc = vec_cmpeq_or_0_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfeezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeezbs
vss = vec_cmpeq_or_0_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfeezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeezhs
vus = vec_cmpeq_or_0_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfeezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeezhs
vus = vec_cmpeq_or_0_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfeezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeezhs
vsi = vec_cmpeq_or_0_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfeezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeezfs
vui = vec_cmpeq_or_0_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfeezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeezfs
vui = vec_cmpeq_or_0_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfeezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfeezfs
vsc = vec_cmpne_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfeneb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeneb
vuc = vec_cmpne_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfeneb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeneb
vuc = vec_cmpne_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfeneb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfeneb
vss = vec_cmpne_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfeneh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeneh
vus = vec_cmpne_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfeneh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeneh
vus = vec_cmpne_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfeneh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfeneh
vsi = vec_cmpne_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfenef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenef
vui = vec_cmpne_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfenef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenef
vui = vec_cmpne_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfenef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenef
vsc = vec_cmpne_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfenebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenebs
vuc = vec_cmpne_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfenebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenebs
vuc = vec_cmpne_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfenebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenebs
vss = vec_cmpne_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfenehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenehs
vus = vec_cmpne_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfenehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenehs
vus = vec_cmpne_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfenehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenehs
vsi = vec_cmpne_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfenefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenefs
vui = vec_cmpne_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfenefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenefs
vui = vec_cmpne_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfenefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenefs
vsc = vec_cmpne_or_0_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfenezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenezb
vuc = vec_cmpne_or_0_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfenezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenezb
vuc = vec_cmpne_or_0_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfenezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenezb
vss = vec_cmpne_or_0_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfenezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenezh
vus = vec_cmpne_or_0_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfenezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenezh
vus = vec_cmpne_or_0_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfenezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenezh
vsi = vec_cmpne_or_0_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfenezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenezf
vui = vec_cmpne_or_0_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfenezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenezf
vui = vec_cmpne_or_0_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfenezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenezf
vsc = vec_cmpne_or_0_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfenezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenezbs
vuc = vec_cmpne_or_0_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfenezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenezbs
vuc = vec_cmpne_or_0_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfenezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vfenezbs
vss = vec_cmpne_or_0_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfenezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenezhs
vus = vec_cmpne_or_0_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfenezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenezhs
vus = vec_cmpne_or_0_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfenezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-ASM: vfenezhs
vsi = vec_cmpne_or_0_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfenezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenezfs
vui = vec_cmpne_or_0_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfenezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenezfs
vui = vec_cmpne_or_0_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfenezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK-ASM: vfenezfs
vbc = vec_cmprg(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vstrcb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vstrcb
vbs = vec_cmprg(vus, vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vstrch(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vstrch
vbi = vec_cmprg(vui, vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vstrcf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vstrcf
vbc = vec_cmprg_cc(vuc, vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vstrcbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vstrcbs
vbs = vec_cmprg_cc(vus, vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vstrchs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vstrchs
vbi = vec_cmprg_cc(vui, vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vstrcfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vstrcfs
vuc = vec_cmprg_idx(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vstrcb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrcb
vus = vec_cmprg_idx(vus, vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vstrch(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrch
vui = vec_cmprg_idx(vui, vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vstrcf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrcf
vuc = vec_cmprg_idx_cc(vuc, vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vstrcbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrcbs
vus = vec_cmprg_idx_cc(vus, vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vstrchs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrchs
vui = vec_cmprg_idx_cc(vui, vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vstrcfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrcfs
vuc = vec_cmprg_or_0_idx(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vstrczb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrczb
vus = vec_cmprg_or_0_idx(vus, vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vstrczh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrczh
vui = vec_cmprg_or_0_idx(vui, vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vstrczf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrczf
vuc = vec_cmprg_or_0_idx_cc(vuc, vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vstrczbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrczbs
vus = vec_cmprg_or_0_idx_cc(vus, vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vstrczhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrczhs
vui = vec_cmprg_or_0_idx_cc(vui, vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vstrczfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vstrczfs
vbc = vec_cmpnrg(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vstrcb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vstrcb
vbs = vec_cmpnrg(vus, vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vstrch(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vstrch
vbi = vec_cmpnrg(vui, vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vstrcf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vstrcf
vbc = vec_cmpnrg_cc(vuc, vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vstrcbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vstrcbs
vbs = vec_cmpnrg_cc(vus, vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vstrchs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vstrchs
vbi = vec_cmpnrg_cc(vui, vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vstrcfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vstrcfs
vuc = vec_cmpnrg_idx(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vstrcb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrcb
vus = vec_cmpnrg_idx(vus, vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vstrch(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrch
vui = vec_cmpnrg_idx(vui, vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vstrcf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrcf
vuc = vec_cmpnrg_idx_cc(vuc, vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vstrcbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrcbs
vus = vec_cmpnrg_idx_cc(vus, vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vstrchs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrchs
vui = vec_cmpnrg_idx_cc(vui, vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vstrcfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrcfs
vuc = vec_cmpnrg_or_0_idx(vuc, vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vstrczb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrczb
vus = vec_cmpnrg_or_0_idx(vus, vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vstrczh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrczh
vui = vec_cmpnrg_or_0_idx(vui, vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vstrczf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrczf
vuc = vec_cmpnrg_or_0_idx_cc(vuc, vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vstrczbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrczbs
vus = vec_cmpnrg_or_0_idx_cc(vus, vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vstrczhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrczhs
vui = vec_cmpnrg_or_0_idx_cc(vui, vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vstrczfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vstrczfs
vbc = vec_find_any_eq(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaeb
vbc = vec_find_any_eq(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaeb
vbc = vec_find_any_eq(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaeb
vbs = vec_find_any_eq(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaeh
vbs = vec_find_any_eq(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaeh
vbs = vec_find_any_eq(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaeh
vbi = vec_find_any_eq(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaef
vbi = vec_find_any_eq(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaef
vbi = vec_find_any_eq(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaef
vbc = vec_find_any_eq_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaebs
vbc = vec_find_any_eq_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaebs
vbc = vec_find_any_eq_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaebs
vbs = vec_find_any_eq_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaehs
vbs = vec_find_any_eq_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaehs
vbs = vec_find_any_eq_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaehs
vbi = vec_find_any_eq_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaefs
vbi = vec_find_any_eq_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaefs
vbi = vec_find_any_eq_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 4)
+ // CHECK-ASM: vfaefs
vsc = vec_find_any_eq_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaeb
vuc = vec_find_any_eq_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaeb
vuc = vec_find_any_eq_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaeb
vss = vec_find_any_eq_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaeh
vus = vec_find_any_eq_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaeh
vus = vec_find_any_eq_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaeh
vsi = vec_find_any_eq_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaef
vui = vec_find_any_eq_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaef
vui = vec_find_any_eq_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaef
vsc = vec_find_any_eq_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaebs
vuc = vec_find_any_eq_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaebs
vuc = vec_find_any_eq_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaebs
vss = vec_find_any_eq_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaehs
vus = vec_find_any_eq_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaehs
vus = vec_find_any_eq_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaehs
vsi = vec_find_any_eq_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaefs
vui = vec_find_any_eq_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaefs
vui = vec_find_any_eq_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaefs
vsc = vec_find_any_eq_or_0_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfaezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezb
vuc = vec_find_any_eq_or_0_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfaezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezb
vuc = vec_find_any_eq_or_0_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfaezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezb
vss = vec_find_any_eq_or_0_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfaezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezh
vus = vec_find_any_eq_or_0_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfaezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezh
vus = vec_find_any_eq_or_0_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfaezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezh
vsi = vec_find_any_eq_or_0_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfaezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezf
vui = vec_find_any_eq_or_0_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfaezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezf
vui = vec_find_any_eq_or_0_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfaezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezf
vsc = vec_find_any_eq_or_0_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezbs
vuc = vec_find_any_eq_or_0_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezbs
vuc = vec_find_any_eq_or_0_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezbs
vss = vec_find_any_eq_or_0_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezhs
vus = vec_find_any_eq_or_0_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezhs
vus = vec_find_any_eq_or_0_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezhs
vsi = vec_find_any_eq_or_0_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezfs
vui = vec_find_any_eq_or_0_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezfs
vui = vec_find_any_eq_or_0_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 0)
+ // CHECK-ASM: vfaezfs
vbc = vec_find_any_ne(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaeb
vbc = vec_find_any_ne(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaeb
vbc = vec_find_any_ne(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaeb
vbs = vec_find_any_ne(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaeh
vbs = vec_find_any_ne(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaeh
vbs = vec_find_any_ne(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaeh
vbi = vec_find_any_ne(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaef
vbi = vec_find_any_ne(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaef
vbi = vec_find_any_ne(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaef
vbc = vec_find_any_ne_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaebs
vbc = vec_find_any_ne_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaebs
vbc = vec_find_any_ne_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaebs
vbs = vec_find_any_ne_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaehs
vbs = vec_find_any_ne_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaehs
vbs = vec_find_any_ne_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaehs
vbi = vec_find_any_ne_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaefs
vbi = vec_find_any_ne_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaefs
vbi = vec_find_any_ne_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 12)
+ // CHECK-ASM: vfaefs
vsc = vec_find_any_ne_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaeb
vuc = vec_find_any_ne_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaeb
vuc = vec_find_any_ne_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfaeb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaeb
vss = vec_find_any_ne_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaeh
vus = vec_find_any_ne_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaeh
vus = vec_find_any_ne_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfaeh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaeh
vsi = vec_find_any_ne_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaef
vui = vec_find_any_ne_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaef
vui = vec_find_any_ne_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfaef(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaef
vsc = vec_find_any_ne_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaebs
vuc = vec_find_any_ne_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaebs
vuc = vec_find_any_ne_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaebs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaebs
vss = vec_find_any_ne_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaehs
vus = vec_find_any_ne_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaehs
vus = vec_find_any_ne_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaehs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaehs
vsi = vec_find_any_ne_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaefs
vui = vec_find_any_ne_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaefs
vui = vec_find_any_ne_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaefs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaefs
vsc = vec_find_any_ne_or_0_idx(vsc, vsc);
// CHECK: call <16 x i8> @llvm.s390.vfaezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezb
vuc = vec_find_any_ne_or_0_idx(vuc, vuc);
// CHECK: call <16 x i8> @llvm.s390.vfaezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezb
vuc = vec_find_any_ne_or_0_idx(vbc, vbc);
// CHECK: call <16 x i8> @llvm.s390.vfaezb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezb
vss = vec_find_any_ne_or_0_idx(vss, vss);
// CHECK: call <8 x i16> @llvm.s390.vfaezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezh
vus = vec_find_any_ne_or_0_idx(vus, vus);
// CHECK: call <8 x i16> @llvm.s390.vfaezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezh
vus = vec_find_any_ne_or_0_idx(vbs, vbs);
// CHECK: call <8 x i16> @llvm.s390.vfaezh(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezh
vsi = vec_find_any_ne_or_0_idx(vsi, vsi);
// CHECK: call <4 x i32> @llvm.s390.vfaezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezf
vui = vec_find_any_ne_or_0_idx(vui, vui);
// CHECK: call <4 x i32> @llvm.s390.vfaezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezf
vui = vec_find_any_ne_or_0_idx(vbi, vbi);
// CHECK: call <4 x i32> @llvm.s390.vfaezf(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezf
vsc = vec_find_any_ne_or_0_idx_cc(vsc, vsc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezbs
vuc = vec_find_any_ne_or_0_idx_cc(vuc, vuc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezbs
vuc = vec_find_any_ne_or_0_idx_cc(vbc, vbc, &cc);
// CHECK: call { <16 x i8>, i32 } @llvm.s390.vfaezbs(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezbs
vss = vec_find_any_ne_or_0_idx_cc(vss, vss, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezhs
vus = vec_find_any_ne_or_0_idx_cc(vus, vus, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezhs
vus = vec_find_any_ne_or_0_idx_cc(vbs, vbs, &cc);
// CHECK: call { <8 x i16>, i32 } @llvm.s390.vfaezhs(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezhs
vsi = vec_find_any_ne_or_0_idx_cc(vsi, vsi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezfs
vui = vec_find_any_ne_or_0_idx_cc(vui, vui, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezfs
vui = vec_find_any_ne_or_0_idx_cc(vbi, vbi, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfaezfs(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, i32 8)
+ // CHECK-ASM: vfaezfs
}
void test_float(void) {
+ // CHECK-ASM-LABEL: test_float
+
vd = vec_abs(vd);
// CHECK: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vflpdb
vd = vec_nabs(vd);
// CHECK: [[ABS:%[^ ]+]] = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{.*}})
// CHECK-NEXT: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[ABS]]
+ // CHECK-ASM: vflndb
vd = vec_madd(vd, vd, vd);
// CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfmadb
vd = vec_msub(vd, vd, vd);
// CHECK: [[NEG:%[^ ]+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
// CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]])
+ // CHECK-ASM: vfmsdb
vd = vec_sqrt(vd);
// CHECK: call <2 x double> @llvm.sqrt.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfsqdb
vd = vec_ld2f(cptrf);
// CHECK: [[VAL:%[^ ]+]] = load <2 x float>, <2 x float>* %{{.*}}
// CHECK: fpext <2 x float> [[VAL]] to <2 x double>
+ // (emulated)
vec_st2f(vd, ptrf);
// CHECK: [[VAL:%[^ ]+]] = fptrunc <2 x double> %{{.*}} to <2 x float>
// CHECK: store <2 x float> [[VAL]], <2 x float>* %{{.*}}
+ // (emulated)
vd = vec_ctd(vsl, 0);
// CHECK: sitofp <2 x i64> %{{.*}} to <2 x double>
+ // (emulated)
vd = vec_ctd(vul, 0);
// CHECK: uitofp <2 x i64> %{{.*}} to <2 x double>
+ // (emulated)
vd = vec_ctd(vsl, 1);
// CHECK: [[VAL:%[^ ]+]] = sitofp <2 x i64> %{{.*}} to <2 x double>
// CHECK: fmul <2 x double> [[VAL]], <double 5.000000e-01, double 5.000000e-01>
+ // (emulated)
vd = vec_ctd(vul, 1);
// CHECK: [[VAL:%[^ ]+]] = uitofp <2 x i64> %{{.*}} to <2 x double>
// CHECK: fmul <2 x double> [[VAL]], <double 5.000000e-01, double 5.000000e-01>
+ // (emulated)
vd = vec_ctd(vsl, 31);
// CHECK: [[VAL:%[^ ]+]] = sitofp <2 x i64> %{{.*}} to <2 x double>
// CHECK: fmul <2 x double> [[VAL]], <double 0x3E00000000000000, double 0x3E00000000000000>
+ // (emulated)
vd = vec_ctd(vul, 31);
// CHECK: [[VAL:%[^ ]+]] = uitofp <2 x i64> %{{.*}} to <2 x double>
// CHECK: fmul <2 x double> [[VAL]], <double 0x3E00000000000000, double 0x3E00000000000000>
+ // (emulated)
vsl = vec_ctsl(vd, 0);
// CHECK: fptosi <2 x double> %{{.*}} to <2 x i64>
+ // (emulated)
vul = vec_ctul(vd, 0);
// CHECK: fptoui <2 x double> %{{.*}} to <2 x i64>
+ // (emulated)
vsl = vec_ctsl(vd, 1);
// CHECK: [[VAL:%[^ ]+]] = fmul <2 x double> %{{.*}}, <double 2.000000e+00, double 2.000000e+00>
// CHECK: fptosi <2 x double> [[VAL]] to <2 x i64>
+ // (emulated)
vul = vec_ctul(vd, 1);
// CHECK: [[VAL:%[^ ]+]] = fmul <2 x double> %{{.*}}, <double 2.000000e+00, double 2.000000e+00>
// CHECK: fptoui <2 x double> [[VAL]] to <2 x i64>
+ // (emulated)
vsl = vec_ctsl(vd, 31);
// CHECK: [[VAL:%[^ ]+]] = fmul <2 x double> %{{.*}}, <double 0x41E0000000000000, double 0x41E0000000000000>
// CHECK: fptosi <2 x double> [[VAL]] to <2 x i64>
+ // (emulated)
vul = vec_ctul(vd, 31);
// CHECK: [[VAL:%[^ ]+]] = fmul <2 x double> %{{.*}}, <double 0x41E0000000000000, double 0x41E0000000000000>
// CHECK: fptoui <2 x double> [[VAL]] to <2 x i64>
+ // (emulated)
vd = vec_double(vsl);
// CHECK: sitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK-ASM: vcdgb
vd = vec_double(vul);
// CHECK: uitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK-ASM: vcdlgb
vsl = vec_signed(vd);
// CHECK: fptosi <2 x double> %{{.*}} to <2 x i64>
+ // CHECK-ASM: vcgdb
vul = vec_unsigned(vd);
// CHECK: fptoui <2 x double> %{{.*}} to <2 x i64>
+ // CHECK-ASM: vclgdb
vd = vec_roundp(vd);
// CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 6
vd = vec_ceil(vd);
// CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 6
vd = vec_roundm(vd);
// CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 7
vd = vec_floor(vd);
// CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 7
vd = vec_roundz(vd);
// CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 5
vd = vec_trunc(vd);
// CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 5
vd = vec_roundc(vd);
// CHECK: call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 0
vd = vec_rint(vd);
// CHECK: call <2 x double> @llvm.rint.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 0, 0
vd = vec_round(vd);
// CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 4)
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 4
vbl = vec_fp_test_data_class(vd, 0, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 0)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, 4095, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 4095)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_ZERO_P, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 2048)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_ZERO_N, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 1024)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_ZERO, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 3072)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_NORMAL_P, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 512)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_NORMAL_N, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 256)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_NORMAL, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 768)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_SUBNORMAL_P, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 128)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_SUBNORMAL_N, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 64)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_SUBNORMAL, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 192)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_INFINITY_P, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 32)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_INFINITY_N, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 16)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_INFINITY, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 48)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_QNAN_P, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 8)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_QNAN_N, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 4)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_QNAN, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 12)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_SNAN_P, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 2)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_SNAN_N, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 1)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_SNAN, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 3)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_NAN, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, __VEC_CLASS_FP_NOT_NORMAL, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 3327)
+ // CHECK-ASM: vftcidb
}
diff --git a/test/CodeGen/builtins-systemz-zvector2.c b/test/CodeGen/builtins-systemz-zvector2.c
index d9607b3a8788..c89cf399a406 100644
--- a/test/CodeGen/builtins-systemz-zvector2.c
+++ b/test/CodeGen/builtins-systemz-zvector2.c
@@ -2,6 +2,9 @@
// RUN: %clang_cc1 -target-cpu z14 -triple s390x-linux-gnu \
// RUN: -O -fzvector -fno-lax-vector-conversions \
// RUN: -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -target-cpu z14 -triple s390x-linux-gnu \
+// RUN: -O -fzvector -fno-lax-vector-conversions \
+// RUN: -Wall -Wno-unused -Werror -S %s -o - | FileCheck %s --check-prefix=CHECK-ASM
#include <vecintrin.h>
@@ -60,486 +63,774 @@ volatile int idx;
int cc;
void test_core(void) {
+ // CHECK-ASM-LABEL: test_core
+ vector float vf2;
+ vector double vd2;
+
+ f = vec_extract(vf, 0);
+ // CHECK: extractelement <4 x float> %{{.*}}, i32 0
+ // CHECK-ASM: vstef
f = vec_extract(vf, idx);
// CHECK: extractelement <4 x float> %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlgvf
+ d = vec_extract(vd, 0);
+ // CHECK: extractelement <2 x double> %{{.*}}, i32 0
+ // CHECK-ASM: vsteg
d = vec_extract(vd, idx);
// CHECK: extractelement <2 x double> %{{.*}}, i32 %{{.*}}
-
- vf = vec_insert(d, vf, idx);
+ // CHECK-ASM: vlgvg
+
+ vf2 = vf;
+ vf = vec_insert(f, vf2, 0);
+ // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
+ // CHECK-ASM: vlef
+ vf = vec_insert(0.0f, vf, 1);
+ // CHECK: insertelement <4 x float> %{{.*}}, float 0.000000e+00, i32 1
+ // CHECK-ASM: vleif %{{.*}}, 0, 1
+ vf = vec_insert(f, vf, idx);
// CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 %{{.*}}
- vd = vec_insert(f, vd, idx);
+ // CHECK-ASM: vlvgf
+ vd2 = vd;
+ vd = vec_insert(d, vd2, 0);
+ // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
+ // CHECK-ASM: vleg
+ vd = vec_insert(0.0, vd, 1);
+ // CHECK: insertelement <2 x double> %{{.*}}, double 0.000000e+00, i32 1
+ // CHECK-ASM: vleig %{{.*}}, 0, 1
+ vd = vec_insert(d, vd, idx);
// CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vf = vec_promote(f, idx);
// CHECK: insertelement <4 x float> undef, float %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgf
vd = vec_promote(d, idx);
// CHECK: insertelement <2 x double> undef, double %{{.*}}, i32 %{{.*}}
+ // CHECK-ASM: vlvgg
vf = vec_insert_and_zero(cptrf);
- // CHECK: insertelement <4 x float> <float undef, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00>, float %{{.*}}, i32 0
+ // CHECK: insertelement <4 x float> <float 0.000000e+00, float undef, float 0.000000e+00, float 0.000000e+00>, float %{{.*}}, i32 1
+ // CHECK-ASM: vllezf
vd = vec_insert_and_zero(cptrd);
// CHECK: insertelement <2 x double> <double undef, double 0.000000e+00>, double %{{.*}}, i32 0
+ // CHECK-ASM: vllezg
vf = vec_perm(vf, vf, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vd = vec_perm(vd, vd, vuc);
// CHECK: call <16 x i8> @llvm.s390.vperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vperm
vul = vec_bperm_u128(vuc, vuc);
// CHECK: call <2 x i64> @llvm.s390.vbperm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vbperm
vf = vec_sel(vf, vf, vui);
+ // CHECK-ASM: vsel
vf = vec_sel(vf, vf, vbi);
+ // CHECK-ASM: vsel
vd = vec_sel(vd, vd, vul);
+ // CHECK-ASM: vsel
vd = vec_sel(vd, vd, vbl);
+ // CHECK-ASM: vsel
vf = vec_gather_element(vf, vui, cptrf, 0);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vf = vec_gather_element(vf, vui, cptrf, 1);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vf = vec_gather_element(vf, vui, cptrf, 2);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vf = vec_gather_element(vf, vui, cptrf, 3);
+ // CHECK-ASM: vgef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vd = vec_gather_element(vd, vul, cptrd, 0);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vd = vec_gather_element(vd, vul, cptrd, 1);
+ // CHECK-ASM: vgeg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vf, vui, ptrf, 0);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vf, vui, ptrf, 1);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vec_scatter_element(vf, vui, ptrf, 2);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 2
vec_scatter_element(vf, vui, ptrf, 3);
+ // CHECK-ASM: vscef %{{.*}}, 0(%{{.*}},%{{.*}}), 3
vec_scatter_element(vd, vul, ptrd, 0);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 0
vec_scatter_element(vd, vul, ptrd, 1);
+ // CHECK-ASM: vsceg %{{.*}}, 0(%{{.*}},%{{.*}}), 1
vf = vec_xl(idx, cptrf);
+ // CHECK-ASM: vl
vd = vec_xl(idx, cptrd);
+ // CHECK-ASM: vl
vec_xst(vf, idx, ptrf);
+ // CHECK-ASM: vst
vec_xst(vd, idx, ptrd);
+ // CHECK-ASM: vst
vd = vec_load_bndry(cptrd, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vf = vec_load_bndry(cptrf, 64);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 0)
+ // CHECK-ASM: vlbb
vf = vec_load_bndry(cptrf, 128);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 1)
+ // CHECK-ASM: vlbb
vf = vec_load_bndry(cptrf, 256);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 2)
+ // CHECK-ASM: vlbb
vf = vec_load_bndry(cptrf, 512);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 3)
+ // CHECK-ASM: vlbb
vf = vec_load_bndry(cptrf, 1024);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 4)
+ // CHECK-ASM: vlbb
vf = vec_load_bndry(cptrf, 2048);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 5)
+ // CHECK-ASM: vlbb
vf = vec_load_bndry(cptrf, 4096);
// CHECK: call <16 x i8> @llvm.s390.vlbb(i8* %{{.*}}, i32 6)
+ // CHECK-ASM: vlbb
vf = vec_load_len(cptrf, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vd = vec_load_len(cptrd, idx);
// CHECK: call <16 x i8> @llvm.s390.vll(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vll
vec_store_len(vf, ptrf, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
vec_store_len(vd, ptrd, idx);
// CHECK: call void @llvm.s390.vstl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstl
+ vuc = vec_load_len_r(cptruc, 0);
+ // CHECK: call <16 x i8> @llvm.s390.vlrl(i32 0, i8* %{{.*}})
+ // CHECK-ASM: vlrl %{{.*}}, 0(%{{.*}}), 0
vuc = vec_load_len_r(cptruc, idx);
// CHECK: call <16 x i8> @llvm.s390.vlrl(i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vlrlr
+ vec_store_len_r(vuc, ptruc, 0);
+ // CHECK: call void @llvm.s390.vstrl(<16 x i8> %{{.*}}, i32 0, i8* %{{.*}})
+ // CHECK-ASM: vstrl %{{.*}}, 0(%{{.*}}), 0
vec_store_len_r(vuc, ptruc, idx);
// CHECK: call void @llvm.s390.vstrl(<16 x i8> %{{.*}}, i32 %{{.*}}, i8* %{{.*}})
+ // CHECK-ASM: vstrlr
vf = vec_splat(vf, 0);
// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> zeroinitializer
+ // CHECK-ASM: vrepf
vf = vec_splat(vf, 1);
// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+ // CHECK-ASM: vrepf
vd = vec_splat(vd, 0);
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vrepg
vd = vec_splat(vd, 1);
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> <i32 1, i32 1>
+ // CHECK-ASM: vrepg
vf = vec_splats(f);
// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> zeroinitializer
+ // CHECK-ASM: vlrepf
vd = vec_splats(d);
// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> zeroinitializer
+ // CHECK-ASM: vlrepg
vf = vec_mergeh(vf, vf);
// shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+ // CHECK-ASM: vmrhf
vd = vec_mergeh(vd, vd);
// shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> <i32 0, i32 2>
+ // CHECK-ASM: vmrhg
vf = vec_mergel(vf, vf);
// shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <i32 2, i32 6, i32 3, i32 7>
+ // CHECK-ASM: vmrlf
vd = vec_mergel(vd, vd);
// shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <i32 1, i32 3>
+ // CHECK-ASM: vmrlg
}
void test_compare(void) {
+ // CHECK-ASM-LABEL: test_compare
+
vbi = vec_cmpeq(vf, vf);
// CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfcesb
vbl = vec_cmpeq(vd, vd);
// CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfcedb
vbi = vec_cmpge(vf, vf);
// CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchesb
vbl = vec_cmpge(vd, vd);
// CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchedb
vbi = vec_cmpgt(vf, vf);
// CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchsb
vbl = vec_cmpgt(vd, vd);
// CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchdb
vbi = vec_cmple(vf, vf);
// CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchesb
vbl = vec_cmple(vd, vd);
// CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchedb
vbi = vec_cmplt(vf, vf);
// CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchsb
vbl = vec_cmplt(vd, vd);
// CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
+ // CHECK-ASM: vfchdb
idx = vec_all_eq(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfcesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfcesbs
idx = vec_all_eq(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_all_ne(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfcesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfcesbs
idx = vec_all_ne(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_all_ge(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_all_ge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_gt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_all_gt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_all_le(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_all_le(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_lt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_all_lt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
+ idx = vec_all_nge(vf, vf);
+ // CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_all_nge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
- idx = vec_all_nge(vd, vd);
- // CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_ngt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_all_ngt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_all_nle(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_all_nle(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_all_nlt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_all_nlt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_all_nan(vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vftcisb(<4 x float> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcisb
idx = vec_all_nan(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
idx = vec_all_numeric(vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vftcisb(<4 x float> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcisb
idx = vec_all_numeric(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
idx = vec_any_eq(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfcesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfcesbs
idx = vec_any_eq(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_any_ne(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfcesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfcesbs
idx = vec_any_ne(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfcedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfcedbs
idx = vec_any_ge(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_any_ge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_gt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_any_gt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_le(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_any_le(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_lt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_any_lt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_nge(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_any_nge(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_ngt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_any_ngt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_nle(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchesbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchesbs
idx = vec_any_nle(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchedbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchedbs
idx = vec_any_nlt(vf, vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vfchsbs(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfchsbs
idx = vec_any_nlt(vd, vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vfchdbs(<2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfchdbs
idx = vec_any_nan(vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vftcisb(<4 x float> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcisb
idx = vec_any_nan(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
idx = vec_any_numeric(vf);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vftcisb(<4 x float> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcisb
idx = vec_any_numeric(vd);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 15)
+ // CHECK-ASM: vftcidb
}
void test_integer(void) {
+ // CHECK-ASM-LABEL: test_integer
+
vf = vec_andc(vf, vf);
+ // CHECK-ASM: vnc
vd = vec_andc(vd, vd);
+ // CHECK-ASM: vnc
vf = vec_nor(vf, vf);
+ // CHECK-ASM: vno
vd = vec_nor(vd, vd);
+ // CHECK-ASM: vno
vsc = vec_nand(vsc, vsc);
+ // CHECK-ASM: vnn
vuc = vec_nand(vuc, vuc);
+ // CHECK-ASM: vnn
vbc = vec_nand(vbc, vbc);
+ // CHECK-ASM: vnn
vss = vec_nand(vss, vss);
+ // CHECK-ASM: vnn
vus = vec_nand(vus, vus);
+ // CHECK-ASM: vnn
vbs = vec_nand(vbs, vbs);
+ // CHECK-ASM: vnn
vsi = vec_nand(vsi, vsi);
+ // CHECK-ASM: vnn
vui = vec_nand(vui, vui);
+ // CHECK-ASM: vnn
vbi = vec_nand(vbi, vbi);
+ // CHECK-ASM: vnn
vsl = vec_nand(vsl, vsl);
+ // CHECK-ASM: vnn
vul = vec_nand(vul, vul);
+ // CHECK-ASM: vnn
vbl = vec_nand(vbl, vbl);
+ // CHECK-ASM: vnn
vf = vec_nand(vf, vf);
+ // CHECK-ASM: vnn
vd = vec_nand(vd, vd);
+ // CHECK-ASM: vnn
vsc = vec_orc(vsc, vsc);
+ // CHECK-ASM: voc
vuc = vec_orc(vuc, vuc);
+ // CHECK-ASM: voc
vbc = vec_orc(vbc, vbc);
+ // CHECK-ASM: voc
vss = vec_orc(vss, vss);
+ // CHECK-ASM: voc
vus = vec_orc(vus, vus);
+ // CHECK-ASM: voc
vbs = vec_orc(vbs, vbs);
+ // CHECK-ASM: voc
vsi = vec_orc(vsi, vsi);
+ // CHECK-ASM: voc
vui = vec_orc(vui, vui);
+ // CHECK-ASM: voc
vbi = vec_orc(vbi, vbi);
+ // CHECK-ASM: voc
vsl = vec_orc(vsl, vsl);
+ // CHECK-ASM: voc
vul = vec_orc(vul, vul);
+ // CHECK-ASM: voc
vbl = vec_orc(vbl, vbl);
+ // CHECK-ASM: voc
vf = vec_orc(vf, vf);
+ // CHECK-ASM: voc
vd = vec_orc(vd, vd);
+ // CHECK-ASM: voc
vsc = vec_eqv(vsc, vsc);
+ // CHECK-ASM: vnx
vuc = vec_eqv(vuc, vuc);
+ // CHECK-ASM: vnx
vbc = vec_eqv(vbc, vbc);
+ // CHECK-ASM: vnx
vss = vec_eqv(vss, vss);
+ // CHECK-ASM: vnx
vus = vec_eqv(vus, vus);
+ // CHECK-ASM: vnx
vbs = vec_eqv(vbs, vbs);
+ // CHECK-ASM: vnx
vsi = vec_eqv(vsi, vsi);
+ // CHECK-ASM: vnx
vui = vec_eqv(vui, vui);
+ // CHECK-ASM: vnx
vbi = vec_eqv(vbi, vbi);
+ // CHECK-ASM: vnx
vsl = vec_eqv(vsl, vsl);
+ // CHECK-ASM: vnx
vul = vec_eqv(vul, vul);
+ // CHECK-ASM: vnx
vbl = vec_eqv(vbl, vbl);
+ // CHECK-ASM: vnx
vf = vec_eqv(vf, vf);
+ // CHECK-ASM: vnx
vd = vec_eqv(vd, vd);
+ // CHECK-ASM: vnx
+
+ vuc = vec_popcnt(vsc);
+ // CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
+ // CHECK-ASM: vpopctb
+ vuc = vec_popcnt(vuc);
+ // CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
+ // CHECK-ASM: vpopctb
+ vus = vec_popcnt(vss);
+ // CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
+ // CHECK-ASM: vpopcth
+ vus = vec_popcnt(vus);
+ // CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
+ // CHECK-ASM: vpopcth
+ vui = vec_popcnt(vsi);
+ // CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
+ // CHECK-ASM: vpopctf
+ vui = vec_popcnt(vui);
+ // CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
+ // CHECK-ASM: vpopctf
+ vul = vec_popcnt(vsl);
+ // CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
+ // CHECK-ASM: vpopctg
+ vul = vec_popcnt(vul);
+ // CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
+ // CHECK-ASM: vpopctg
vf = vec_slb(vf, vsi);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vf = vec_slb(vf, vui);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vd = vec_slb(vd, vsl);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vd = vec_slb(vd, vul);
// CHECK: call <16 x i8> @llvm.s390.vslb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vslb
vf = vec_sld(vf, vf, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vf = vec_sld(vf, vf, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vd = vec_sld(vd, vd, 0);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vsldb
vd = vec_sld(vd, vd, 15);
// CHECK: call <16 x i8> @llvm.s390.vsldb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, i32 15)
+ // CHECK-ASM: vsldb
vf = vec_srab(vf, vsi);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vf = vec_srab(vf, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vd = vec_srab(vd, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vd = vec_srab(vd, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrab(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrab
vf = vec_srb(vf, vsi);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vf = vec_srb(vf, vui);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vd = vec_srb(vd, vsl);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
vd = vec_srb(vd, vul);
// CHECK: call <16 x i8> @llvm.s390.vsrlb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vsrlb
idx = vec_test_mask(vf, vui);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
idx = vec_test_mask(vd, vul);
// CHECK: call i32 @llvm.s390.vtm(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-ASM: vtm
vuc = vec_msum_u128(vul, vul, vuc, 0);
// CHECK: call <16 x i8> @llvm.s390.vmslg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <16 x i8> %{{.*}}, i32 0)
+ // CHECK-ASM: vmslg
vuc = vec_msum_u128(vul, vul, vuc, 4);
// CHECK: call <16 x i8> @llvm.s390.vmslg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <16 x i8> %{{.*}}, i32 4)
+ // CHECK-ASM: vmslg
vuc = vec_msum_u128(vul, vul, vuc, 8);
// CHECK: call <16 x i8> @llvm.s390.vmslg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <16 x i8> %{{.*}}, i32 8)
+ // CHECK-ASM: vmslg
vuc = vec_msum_u128(vul, vul, vuc, 12);
// CHECK: call <16 x i8> @llvm.s390.vmslg(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <16 x i8> %{{.*}}, i32 12)
+ // CHECK-ASM: vmslg
}
void test_float(void) {
+ // CHECK-ASM-LABEL: test_float
+
vf = vec_abs(vf);
// CHECK: call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vflpsb
vd = vec_abs(vd);
// CHECK: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vflpdb
vf = vec_nabs(vf);
// CHECK: [[ABS:%[^ ]+]] = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
// CHECK-NEXT: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[ABS]]
+ // CHECK-ASM: vflnsb
vd = vec_nabs(vd);
// CHECK: [[ABS:%[^ ]+]] = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{.*}})
// CHECK-NEXT: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[ABS]]
+ // CHECK-ASM: vflndb
vf = vec_max(vf, vf);
// CHECK: call <4 x float> @llvm.s390.vfmaxsb(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 0)
+ // CHECK-ASM: vfmaxsb
vd = vec_max(vd, vd);
// CHECK: call <2 x double> @llvm.s390.vfmaxdb(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 0)
+ // CHECK-ASM: vfmaxdb
vf = vec_min(vf, vf);
// CHECK: call <4 x float> @llvm.s390.vfminsb(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 0)
+ // CHECK-ASM: vfminsb
vd = vec_min(vd, vd);
// CHECK: call <2 x double> @llvm.s390.vfmindb(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i32 0)
+ // CHECK-ASM: vfmindb
vf = vec_madd(vf, vf, vf);
// CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ // CHECK-ASM: vfmasb
vd = vec_madd(vd, vd, vd);
// CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
+ // CHECK-ASM: vfmadb
vf = vec_msub(vf, vf, vf);
// CHECK: [[NEG:%[^ ]+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
// CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]])
+ // CHECK-ASM: vfmssb
vd = vec_msub(vd, vd, vd);
// CHECK: [[NEG:%[^ ]+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
// CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]])
+ // CHECK-ASM: vfmsdb
vf = vec_nmadd(vf, vf, vf);
// CHECK: [[RES:%[^ ]+]] = tail call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
// CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[RES]]
+ // CHECK-ASM: vfnmasb
vd = vec_nmadd(vd, vd, vd);
// CHECK: [[RES:%[^ ]+]] = tail call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}})
// CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[RES]]
+ // CHECK-ASM: vfnmadb
vf = vec_nmsub(vf, vf, vf);
// CHECK: [[NEG:%[^ ]+]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %{{.*}}
// CHECK: [[RES:%[^ ]+]] = tail call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]])
// CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[RES]]
+ // CHECK-ASM: vfnmssb
vd = vec_nmsub(vd, vd, vd);
// CHECK: [[NEG:%[^ ]+]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %{{.*}}
// CHECK: [[RES:%[^ ]+]] = tail call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]])
// CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[RES]]
+ // CHECK-ASM: vfnmsdb
vf = vec_sqrt(vf);
// CHECK: call <4 x float> @llvm.sqrt.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfsqsb
vd = vec_sqrt(vd);
// CHECK: call <2 x double> @llvm.sqrt.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfsqdb
vd = vec_doublee(vf);
// CHECK: fpext <2 x float> %{{.*}} to <2 x double>
+ // CHECK-ASM: vldeb
vf = vec_floate(vd);
// CHECK: fptrunc <2 x double> %{{.*}} to <2 x float>
+ // CHECK-ASM: vledb
vd = vec_double(vsl);
// CHECK: sitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK-ASM: vcdgb
vd = vec_double(vul);
// CHECK: uitofp <2 x i64> %{{.*}} to <2 x double>
+ // CHECK-ASM: vcdlgb
vsl = vec_signed(vd);
// CHECK: fptosi <2 x double> %{{.*}} to <2 x i64>
+ // CHECK-ASM: vcgdb
vul = vec_unsigned(vd);
// CHECK: fptoui <2 x double> %{{.*}} to <2 x i64>
+ // CHECK-ASM: vclgdb
vf = vec_roundp(vf);
// CHECK: call <4 x float> @llvm.ceil.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 6
vf = vec_ceil(vf);
// CHECK: call <4 x float> @llvm.ceil.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 6
vd = vec_roundp(vd);
// CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 6
vd = vec_ceil(vd);
// CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 6
vf = vec_roundm(vf);
// CHECK: call <4 x float> @llvm.floor.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 7
vf = vec_floor(vf);
// CHECK: call <4 x float> @llvm.floor.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 7
vd = vec_roundm(vd);
// CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 7
vd = vec_floor(vd);
// CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 7
vf = vec_roundz(vf);
// CHECK: call <4 x float> @llvm.trunc.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 5
vf = vec_trunc(vf);
// CHECK: call <4 x float> @llvm.trunc.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 5
vd = vec_roundz(vd);
// CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 5
vd = vec_trunc(vd);
// CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 5
vf = vec_roundc(vf);
// CHECK: call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 0
vd = vec_roundc(vd);
// CHECK: call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 0
vf = vec_rint(vf);
// CHECK: call <4 x float> @llvm.rint.v4f32(<4 x float> %{{.*}})
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 0, 0
vd = vec_rint(vd);
// CHECK: call <2 x double> @llvm.rint.v2f64(<2 x double> %{{.*}})
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 0, 0
vf = vec_round(vf);
// CHECK: call <4 x float> @llvm.s390.vfisb(<4 x float> %{{.*}}, i32 4, i32 4)
+ // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 4
vd = vec_round(vd);
// CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 4)
+ // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 4
vbi = vec_fp_test_data_class(vf, 0, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vftcisb(<4 x float> %{{.*}}, i32 0)
+ // CHECK-ASM: vftcisb
vbi = vec_fp_test_data_class(vf, 4095, &cc);
// CHECK: call { <4 x i32>, i32 } @llvm.s390.vftcisb(<4 x float> %{{.*}}, i32 4095)
+ // CHECK-ASM: vftcisb
vbl = vec_fp_test_data_class(vd, 0, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 0)
+ // CHECK-ASM: vftcidb
vbl = vec_fp_test_data_class(vd, 4095, &cc);
// CHECK: call { <2 x i64>, i32 } @llvm.s390.vftcidb(<2 x double> %{{.*}}, i32 4095)
+ // CHECK-ASM: vftcidb
}
diff --git a/test/CodeGen/builtins-wasm.c b/test/CodeGen/builtins-wasm.c
index 1b647b56d1a2..4f14e901edf2 100644
--- a/test/CodeGen/builtins-wasm.c
+++ b/test/CodeGen/builtins-wasm.c
@@ -1,52 +1,408 @@
-// RUN: %clang_cc1 -triple wasm32-unknown-unknown -O3 -emit-llvm -o - %s \
-// RUN: | FileCheck %s -check-prefix=WEBASSEMBLY32
-// RUN: %clang_cc1 -triple wasm64-unknown-unknown -O3 -emit-llvm -o - %s \
-// RUN: | FileCheck %s -check-prefix=WEBASSEMBLY64
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +unimplemented-simd128 -target-feature +nontrapping-fptoint -target-feature +exception-handling -fno-lax-vector-conversions -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY32
+// RUN: %clang_cc1 -triple wasm64-unknown-unknown -target-feature +unimplemented-simd128 -target-feature +nontrapping-fptoint -target-feature +exception-handling -fno-lax-vector-conversions -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY64
+// RUN: not %clang_cc1 -triple wasm64-unknown-unknown -target-feature +nontrapping-fptoint -target-feature +exception-handling -fno-lax-vector-conversions -O3 -emit-llvm -o - %s 2>&1 | FileCheck %s -check-prefixes MISSING-SIMD
-__SIZE_TYPE__ f0(void) {
+// SIMD convenience types
+typedef char i8x16 __attribute((vector_size(16)));
+typedef short i16x8 __attribute((vector_size(16)));
+typedef int i32x4 __attribute((vector_size(16)));
+typedef long long i64x2 __attribute((vector_size(16)));
+typedef unsigned char u8x16 __attribute((vector_size(16)));
+typedef unsigned short u16x8 __attribute((vector_size(16)));
+typedef unsigned int u32x4 __attribute((vector_size(16)));
+typedef unsigned long long u64x2 __attribute((vector_size(16)));
+typedef float f32x4 __attribute((vector_size(16)));
+typedef double f64x2 __attribute((vector_size(16)));
+
+__SIZE_TYPE__ memory_size(void) {
return __builtin_wasm_memory_size(0);
-// WEBASSEMBLY32: call {{i.*}} @llvm.wasm.memory.size.i32(i32 0)
-// WEBASSEMBLY64: call {{i.*}} @llvm.wasm.memory.size.i64(i32 0)
+ // WEBASSEMBLY32: call {{i.*}} @llvm.wasm.memory.size.i32(i32 0)
+ // WEBASSEMBLY64: call {{i.*}} @llvm.wasm.memory.size.i64(i32 0)
}
-__SIZE_TYPE__ f1(__SIZE_TYPE__ delta) {
+__SIZE_TYPE__ memory_grow(__SIZE_TYPE__ delta) {
return __builtin_wasm_memory_grow(0, delta);
-// WEBASSEMBLY32: call i32 @llvm.wasm.memory.grow.i32(i32 0, i32 %{{.*}})
-// WEBASSEMBLY64: call i64 @llvm.wasm.memory.grow.i64(i32 0, i64 %{{.*}})
+ // WEBASSEMBLY32: call i32 @llvm.wasm.memory.grow.i32(i32 0, i32 %{{.*}})
+ // WEBASSEMBLY64: call i64 @llvm.wasm.memory.grow.i64(i32 0, i64 %{{.*}})
}
-__SIZE_TYPE__ f2(void) {
- return __builtin_wasm_mem_size(0);
-// WEBASSEMBLY32: call {{i.*}} @llvm.wasm.mem.size.i32(i32 0)
-// WEBASSEMBLY64: call {{i.*}} @llvm.wasm.mem.size.i64(i32 0)
+void throw(unsigned int tag, void *obj) {
+ return __builtin_wasm_throw(tag, obj);
+ // WEBASSEMBLY32: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
+ // WEBASSEMBLY64: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
}
-__SIZE_TYPE__ f3(__SIZE_TYPE__ delta) {
- return __builtin_wasm_mem_grow(0, delta);
-// WEBASSEMBLY32: call i32 @llvm.wasm.mem.grow.i32(i32 0, i32 %{{.*}})
-// WEBASSEMBLY64: call i64 @llvm.wasm.mem.grow.i64(i32 0, i64 %{{.*}})
+void rethrow(void) {
+ return __builtin_wasm_rethrow();
+ // WEBASSEMBLY32: call void @llvm.wasm.rethrow()
+ // WEBASSEMBLY64: call void @llvm.wasm.rethrow()
}
-__SIZE_TYPE__ f4(void) {
- return __builtin_wasm_current_memory();
-// WEBASSEMBLY32: call {{i.*}} @llvm.wasm.current.memory.i32()
-// WEBASSEMBLY64: call {{i.*}} @llvm.wasm.current.memory.i64()
+int atomic_wait_i32(int *addr, int expected, long long timeout) {
+ return __builtin_wasm_atomic_wait_i32(addr, expected, timeout);
+ // WEBASSEMBLY32: call i32 @llvm.wasm.atomic.wait.i32(i32* %{{.*}}, i32 %{{.*}}, i64 %{{.*}})
+ // WEBASSEMBLY64: call i32 @llvm.wasm.atomic.wait.i32(i32* %{{.*}}, i32 %{{.*}}, i64 %{{.*}})
}
-__SIZE_TYPE__ f5(__SIZE_TYPE__ delta) {
- return __builtin_wasm_grow_memory(delta);
-// WEBASSEMBLY32: call i32 @llvm.wasm.grow.memory.i32(i32 %{{.*}})
-// WEBASSEMBLY64: call i64 @llvm.wasm.grow.memory.i64(i64 %{{.*}})
+int atomic_wait_i64(long long *addr, long long expected, long long timeout) {
+ return __builtin_wasm_atomic_wait_i64(addr, expected, timeout);
+ // WEBASSEMBLY32: call i32 @llvm.wasm.atomic.wait.i64(i64* %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
+ // WEBASSEMBLY64: call i32 @llvm.wasm.atomic.wait.i64(i64* %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
}
-void f6(unsigned int tag, void *obj) {
- return __builtin_wasm_throw(tag, obj);
-// WEBASSEMBLY32: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
-// WEBASSEMBLY64: call void @llvm.wasm.throw(i32 %{{.*}}, i8* %{{.*}})
+unsigned int atomic_notify(int *addr, unsigned int count) {
+ return __builtin_wasm_atomic_notify(addr, count);
+ // WEBASSEMBLY32: call i32 @llvm.wasm.atomic.notify(i32* %{{.*}}, i32 %{{.*}})
+ // WEBASSEMBLY64: call i32 @llvm.wasm.atomic.notify(i32* %{{.*}}, i32 %{{.*}})
}
-void f7(void) {
- return __builtin_wasm_rethrow();
-// WEBASSEMBLY32: call void @llvm.wasm.rethrow()
-// WEBASSEMBLY64: call void @llvm.wasm.rethrow()
+int trunc_saturate_s_i32_f32(float f) {
+ return __builtin_wasm_trunc_saturate_s_i32_f32(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int trunc_saturate_u_i32_f32(float f) {
+ return __builtin_wasm_trunc_saturate_u_i32_f32(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int trunc_saturate_s_i32_f64(double f) {
+ return __builtin_wasm_trunc_saturate_s_i32_f64(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int trunc_saturate_u_i32_f64(double f) {
+ return __builtin_wasm_trunc_saturate_u_i32_f64(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_saturate_s_i64_f32(float f) {
+ return __builtin_wasm_trunc_saturate_s_i64_f32(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_saturate_u_i64_f32(float f) {
+ return __builtin_wasm_trunc_saturate_u_i64_f32(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_saturate_s_i64_f64(double f) {
+ return __builtin_wasm_trunc_saturate_s_i64_f64(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_saturate_u_i64_f64(double f) {
+ return __builtin_wasm_trunc_saturate_u_i64_f64(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+float min_f32(float x, float y) {
+ return __builtin_wasm_min_f32(x, y);
+ // WEBASSEMBLY: call float @llvm.minimum.f32(float %x, float %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+float max_f32(float x, float y) {
+ return __builtin_wasm_max_f32(x, y);
+ // WEBASSEMBLY: call float @llvm.maximum.f32(float %x, float %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+double min_f64(double x, double y) {
+ return __builtin_wasm_min_f64(x, y);
+ // WEBASSEMBLY: call double @llvm.minimum.f64(double %x, double %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+double max_f64(double x, double y) {
+ return __builtin_wasm_max_f64(x, y);
+ // WEBASSEMBLY: call double @llvm.maximum.f64(double %x, double %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+
+int extract_lane_s_i8x16(i8x16 v) {
+ return __builtin_wasm_extract_lane_s_i8x16(v, 13);
+ // MISSING-SIMD: error: '__builtin_wasm_extract_lane_s_i8x16' needs target feature simd128
+ // WEBASSEMBLY: extractelement <16 x i8> %v, i32 13
+ // WEBASSEMBLY-NEXT: sext
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int extract_lane_u_i8x16(i8x16 v) {
+ return __builtin_wasm_extract_lane_u_i8x16(v, 13);
+ // WEBASSEMBLY: extractelement <16 x i8> %v, i32 13
+ // WEBASSEMBLY-NEXT: zext
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int extract_lane_s_i16x8(i16x8 v) {
+ return __builtin_wasm_extract_lane_s_i16x8(v, 7);
+ // WEBASSEMBLY: extractelement <8 x i16> %v, i32 7
+ // WEBASSEMBLY-NEXT: sext
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int extract_lane_u_i16x8(i16x8 v) {
+ return __builtin_wasm_extract_lane_u_i16x8(v, 7);
+ // WEBASSEMBLY: extractelement <8 x i16> %v, i32 7
+ // WEBASSEMBLY-NEXT: zext
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int extract_lane_i32x4(i32x4 v) {
+ return __builtin_wasm_extract_lane_i32x4(v, 3);
+ // WEBASSEMBLY: extractelement <4 x i32> %v, i32 3
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long extract_lane_i64x2(i64x2 v) {
+ return __builtin_wasm_extract_lane_i64x2(v, 1);
+ // WEBASSEMBLY: extractelement <2 x i64> %v, i32 1
+ // WEBASSEMBLY-NEXT: ret
+}
+
+float extract_lane_f32x4(f32x4 v) {
+ return __builtin_wasm_extract_lane_f32x4(v, 3);
+ // WEBASSEMBLY: extractelement <4 x float> %v, i32 3
+ // WEBASSEMBLY-NEXT: ret
+}
+
+double extract_lane_f64x2(f64x2 v) {
+ return __builtin_wasm_extract_lane_f64x2(v, 1);
+ // WEBASSEMBLY: extractelement <2 x double> %v, i32 1
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i8x16 replace_lane_i8x16(i8x16 v, int x) {
+ return __builtin_wasm_replace_lane_i8x16(v, 13, x);
+ // WEBASSEMBLY: trunc i32 %x to i8
+ // WEBASSEMBLY-NEXT: insertelement <16 x i8> %v, i8 %{{.*}}, i32 13
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i16x8 replace_lane_i16x8(i16x8 v, int x) {
+ return __builtin_wasm_replace_lane_i16x8(v, 7, x);
+ // WEBASSEMBLY: trunc i32 %x to i16
+ // WEBASSEMBLY-NEXT: insertelement <8 x i16> %v, i16 %{{.*}}, i32 7
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i32x4 replace_lane_i32x4(i32x4 v, int x) {
+ return __builtin_wasm_replace_lane_i32x4(v, 3, x);
+ // WEBASSEMBLY: insertelement <4 x i32> %v, i32 %x, i32 3
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i64x2 replace_lane_i64x2(i64x2 v, long long x) {
+ return __builtin_wasm_replace_lane_i64x2(v, 1, x);
+ // WEBASSEMBLY: insertelement <2 x i64> %v, i64 %x, i32 1
+ // WEBASSEMBLY-NEXT: ret
+}
+
+f32x4 replace_lane_f32x4(f32x4 v, float x) {
+ return __builtin_wasm_replace_lane_f32x4(v, 3, x);
+ // WEBASSEMBLY: insertelement <4 x float> %v, float %x, i32 3
+ // WEBASSEMBLY-NEXT: ret
+}
+
+f64x2 replace_lane_f64x2(f64x2 v, double x) {
+ return __builtin_wasm_replace_lane_f64x2(v, 1, x);
+ // WEBASSEMBLY: insertelement <2 x double> %v, double %x, i32 1
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i8x16 add_saturate_s_i8x16(i8x16 x, i8x16 y) {
+ return __builtin_wasm_add_saturate_s_i8x16(x, y);
+ // WEBASSEMBLY: call <16 x i8> @llvm.sadd.sat.v16i8(
+ // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i8x16 add_saturate_u_i8x16(i8x16 x, i8x16 y) {
+ return __builtin_wasm_add_saturate_u_i8x16(x, y);
+ // WEBASSEMBLY: call <16 x i8> @llvm.uadd.sat.v16i8(
+ // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i16x8 add_saturate_s_i16x8(i16x8 x, i16x8 y) {
+ return __builtin_wasm_add_saturate_s_i16x8(x, y);
+ // WEBASSEMBLY: call <8 x i16> @llvm.sadd.sat.v8i16(
+ // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i16x8 add_saturate_u_i16x8(i16x8 x, i16x8 y) {
+ return __builtin_wasm_add_saturate_u_i16x8(x, y);
+ // WEBASSEMBLY: call <8 x i16> @llvm.uadd.sat.v8i16(
+ // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i8x16 sub_saturate_s_i8x16(i8x16 x, i8x16 y) {
+ return __builtin_wasm_sub_saturate_s_i8x16(x, y);
+ // WEBASSEMBLY: call <16 x i8> @llvm.wasm.sub.saturate.signed.v16i8(
+ // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i8x16 sub_saturate_u_i8x16(i8x16 x, i8x16 y) {
+ return __builtin_wasm_sub_saturate_u_i8x16(x, y);
+ // WEBASSEMBLY: call <16 x i8> @llvm.wasm.sub.saturate.unsigned.v16i8(
+ // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i16x8 sub_saturate_s_i16x8(i16x8 x, i16x8 y) {
+ return __builtin_wasm_sub_saturate_s_i16x8(x, y);
+ // WEBASSEMBLY: call <8 x i16> @llvm.wasm.sub.saturate.signed.v8i16(
+ // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i16x8 sub_saturate_u_i16x8(i16x8 x, i16x8 y) {
+ return __builtin_wasm_sub_saturate_u_i16x8(x, y);
+ // WEBASSEMBLY: call <8 x i16> @llvm.wasm.sub.saturate.unsigned.v8i16(
+ // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i32x4 bitselect(i32x4 x, i32x4 y, i32x4 c) {
+ return __builtin_wasm_bitselect(x, y, c);
+ // WEBASSEMBLY: call <4 x i32> @llvm.wasm.bitselect.v4i32(
+ // WEBASSEMBLY-SAME: <4 x i32> %x, <4 x i32> %y, <4 x i32> %c)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int any_true_i8x16(i8x16 x) {
+ return __builtin_wasm_any_true_i8x16(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> %x)
+ // WEBASSEMBLY: ret
+}
+
+int any_true_i16x8(i16x8 x) {
+ return __builtin_wasm_any_true_i16x8(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v8i16(<8 x i16> %x)
+ // WEBASSEMBLY: ret
+}
+
+int any_true_i32x4(i32x4 x) {
+ return __builtin_wasm_any_true_i32x4(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v4i32(<4 x i32> %x)
+ // WEBASSEMBLY: ret
+}
+
+int any_true_i64x2(i64x2 x) {
+ return __builtin_wasm_any_true_i64x2(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v2i64(<2 x i64> %x)
+ // WEBASSEMBLY: ret
+}
+
+int all_true_i8x16(i8x16 x) {
+ return __builtin_wasm_all_true_i8x16(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v16i8(<16 x i8> %x)
+ // WEBASSEMBLY: ret
+}
+
+int all_true_i16x8(i16x8 x) {
+ return __builtin_wasm_all_true_i16x8(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v8i16(<8 x i16> %x)
+ // WEBASSEMBLY: ret
+}
+
+int all_true_i32x4(i32x4 x) {
+ return __builtin_wasm_all_true_i32x4(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v4i32(<4 x i32> %x)
+ // WEBASSEMBLY: ret
+}
+
+int all_true_i64x2(i64x2 x) {
+ return __builtin_wasm_all_true_i64x2(x);
+ // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v2i64(<2 x i64> %x)
+ // WEBASSEMBLY: ret
+}
+
+f32x4 abs_f32x4(f32x4 x) {
+ return __builtin_wasm_abs_f32x4(x);
+ // WEBASSEMBLY: call <4 x float> @llvm.fabs.v4f32(<4 x float> %x)
+ // WEBASSEMBLY: ret
+}
+
+f64x2 abs_f64x2(f64x2 x) {
+ return __builtin_wasm_abs_f64x2(x);
+ // WEBASSEMBLY: call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
+ // WEBASSEMBLY: ret
+}
+
+f32x4 min_f32x4(f32x4 x, f32x4 y) {
+ return __builtin_wasm_min_f32x4(x, y);
+ // WEBASSEMBLY: call <4 x float> @llvm.minimum.v4f32(
+ // WEBASSEMBLY-SAME: <4 x float> %x, <4 x float> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+f32x4 max_f32x4(f32x4 x, f32x4 y) {
+ return __builtin_wasm_max_f32x4(x, y);
+ // WEBASSEMBLY: call <4 x float> @llvm.maximum.v4f32(
+ // WEBASSEMBLY-SAME: <4 x float> %x, <4 x float> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+f64x2 min_f64x2(f64x2 x, f64x2 y) {
+ return __builtin_wasm_min_f64x2(x, y);
+ // WEBASSEMBLY: call <2 x double> @llvm.minimum.v2f64(
+ // WEBASSEMBLY-SAME: <2 x double> %x, <2 x double> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+f64x2 max_f64x2(f64x2 x, f64x2 y) {
+ return __builtin_wasm_max_f64x2(x, y);
+ // WEBASSEMBLY: call <2 x double> @llvm.maximum.v2f64(
+ // WEBASSEMBLY-SAME: <2 x double> %x, <2 x double> %y)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+f32x4 sqrt_f32x4(f32x4 x) {
+ return __builtin_wasm_sqrt_f32x4(x);
+ // WEBASSEMBLY: call <4 x float> @llvm.sqrt.v4f32(<4 x float> %x)
+ // WEBASSEMBLY: ret
+}
+
+f64x2 sqrt_f64x2(f64x2 x) {
+ return __builtin_wasm_sqrt_f64x2(x);
+ // WEBASSEMBLY: call <2 x double> @llvm.sqrt.v2f64(<2 x double> %x)
+ // WEBASSEMBLY: ret
+}
+
+i32x4 trunc_saturate_s_i32x4_f32x4(f32x4 f) {
+ return __builtin_wasm_trunc_saturate_s_i32x4_f32x4(f);
+ // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i32x4 trunc_saturate_u_i32x4_f32x4(f32x4 f) {
+ return __builtin_wasm_trunc_saturate_u_i32x4_f32x4(f);
+ // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i64x2 trunc_saturate_s_i64x2_f64x2(f64x2 f) {
+ return __builtin_wasm_trunc_saturate_s_i64x2_f64x2(f);
+ // WEBASSEMBLY: call <2 x i64> @llvm.wasm.trunc.saturate.signed.v2i64.v2f64(<2 x double> %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+i64x2 trunc_saturate_u_i64x2_f64x2(f64x2 f) {
+ return __builtin_wasm_trunc_saturate_u_i64x2_f64x2(f);
+ // WEBASSEMBLY: call <2 x i64> @llvm.wasm.trunc.saturate.unsigned.v2i64.v2f64(<2 x double> %f)
+ // WEBASSEMBLY-NEXT: ret
}
diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c
index 77b479e4c112..8e0542a1a839 100644
--- a/test/CodeGen/builtins.c
+++ b/test/CodeGen/builtins.c
@@ -132,6 +132,8 @@ int main() {
R(extract_return_addr, (&N));
P(signbit, (1.0));
+ R(launder, (&N));
+
return 0;
}
@@ -396,6 +398,15 @@ long long test_builtin_readcyclecounter() {
return __builtin_readcyclecounter();
}
+/// __builtin_launder should be a NOP in C since there are no vtables.
+// CHECK-LABEL: define void @test_builtin_launder
+void test_builtin_launder(int *p) {
+ // CHECK: [[TMP:%.*]] = load i32*,
+ // CHECK-NOT: @llvm.launder
+ // CHECK: store i32* [[TMP]],
+ int *d = __builtin_launder(p);
+}
+
// Behavior of __builtin_os_log differs between platforms, so only test on X86
#ifdef __x86_64__
@@ -440,10 +451,36 @@ void test_builtin_os_log(void *buf, int i, const char *data) {
// CHECK: call void @__os_log_helper_1_2_1_8_34(
__builtin_os_log_format(buf, "%{ xyz, public }s", "abc");
- // The last privacy annotation in the string wins.
+ // CHECK: call void @__os_log_helper_1_3_1_8_33(
+ __builtin_os_log_format(buf, "%{ xyz, private }s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_3_1_8_37(
+ __builtin_os_log_format(buf, "%{ xyz, sensitive }s", "abc");
+
+ // The strictest privacy annotation in the string wins.
// CHECK: call void @__os_log_helper_1_3_1_8_33(
__builtin_os_log_format(buf, "%{ private, public, private, public}s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_3_1_8_37(
+ __builtin_os_log_format(buf, "%{ private, sensitive, private, public}s",
+ "abc");
+
+ // CHECK: store volatile i32 22, i32* %[[LEN]], align 4
+ len = __builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_2_2_8_112_8_34(i8* {{.*}}, i64 8026488
+ __builtin_os_log_format(buf, "%{mask.xyz, public}s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_3_2_8_112_4_1(i8* {{.*}}, i64 8026488
+ __builtin_os_log_format(buf, "%{ mask.xyz, private }d", 11);
+
+ // Mask type is silently ignored.
+ // CHECK: call void @__os_log_helper_1_2_1_8_32(
+ __builtin_os_log_format(buf, "%{ mask. xyz }s", "abc");
+
+ // CHECK: call void @__os_log_helper_1_2_1_8_32(
+ __builtin_os_log_format(buf, "%{ mask.xy z }s", "abc");
}
// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49
@@ -729,25 +766,28 @@ void test_builtin_os_log_merge_helper1(void *buf, unsigned u, long long ll) {
// CHECK-LABEL: define void @test_builtin_os_log_errno
void test_builtin_os_log_errno() {
- // CHECK: %[[VLA:.*]] = alloca i8, i64 4, align 16
- // CHECK: call void @__os_log_helper_16_2_1_0_96(i8* %[[VLA]])
+ // CHECK-NOT: @stacksave
+ // CHECK: %[[BUF:.*]] = alloca [4 x i8], align 1
+ // CHECK: %[[DECAY:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUF]], i32 0, i32 0
+ // CHECK: call void @__os_log_helper_1_2_1_0_96(i8* %[[DECAY]])
+ // CHECK-NOT: @stackrestore
char buf[__builtin_os_log_format_buffer_size("%m")];
__builtin_os_log_format(buf, "%m");
}
-// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_16_2_1_0_96
+// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_1_0_96
// CHECK: (i8* %[[BUFFER:.*]])
// CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8
// CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8
// CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8
// CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0
-// CHECK: store i8 2, i8* %[[SUMMARY]], align 16
+// CHECK: store i8 2, i8* %[[SUMMARY]], align 1
// CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1
// CHECK: store i8 1, i8* %[[NUMARGS]], align 1
// CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2
-// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 2
+// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 1
// CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3
// CHECK: store i8 0, i8* %[[ARGSIZE]], align 1
// CHECK-NEXT: ret void
diff --git a/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp b/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp
new file mode 100644
index 000000000000..96d264190bec
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+typedef char **__attribute__((align_value(0x80000000))) aligned_char;
+
+struct ac_struct {
+ // CHECK: %[[STRUCT_AC_STRUCT:.*]] = type { i8** }
+ aligned_char a;
+};
+
+// CHECK-SANITIZE-ANYRECOVER: @[[ALIGNED_CHAR:.*]] = {{.*}} c"'aligned_char' (aka 'char **')\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 13 }, {{.*}}* @[[ALIGNED_CHAR]] }
+
+char **load_from_ac_struct(struct ac_struct *x) {
+ // CHECK: define i8** @{{.*}}(%[[STRUCT_AC_STRUCT]]* %[[X:.*]])
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[STRUCT_AC_STRUCT_ADDR:.*]] = alloca %[[STRUCT_AC_STRUCT]]*, align 8
+ // CHECK-NEXT: store %[[STRUCT_AC_STRUCT]]* %[[X]], %[[STRUCT_AC_STRUCT]]** %[[STRUCT_AC_STRUCT_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load %[[STRUCT_AC_STRUCT]]*, %[[STRUCT_AC_STRUCT]]** %[[STRUCT_AC_STRUCT_ADDR]], align 8
+ // CHECK: %[[A_ADDR:.*]] = getelementptr inbounds %[[STRUCT_AC_STRUCT]], %[[STRUCT_AC_STRUCT]]* %[[X_RELOADED]], i32 0, i32 0
+ // CHECK: %[[A:.*]] = load i8**, i8*** %[[A_ADDR]], align 8
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[A]] to i64
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 2147483647
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[A]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8** %[[A]]
+ // CHECK-NEXT: }
+#line 100
+ return x->a;
+}
diff --git a/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp b/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp
new file mode 100644
index 000000000000..0e3fa750c66c
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[CHAR]] }
+
+char **passthrough(__attribute__((align_value(0x80000000))) char **x) {
+ // CHECK-NOSANITIZE: define i8** @{{.*}}(i8** align 536870912 %[[X:.*]])
+ // CHECK-SANITIZE: define i8** @{{.*}}(i8** %[[X:.*]])
+ // CHECK-NEXT: [[entry:.*]]:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RELOADED]] to i64
+ // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 2147483647
+ // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[X_RELOADED]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8** %[[X_RELOADED]]
+ // CHECK-NEXT: }
+#line 100
+ return x;
+}
diff --git a/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp b/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp
new file mode 100644
index 000000000000..1b5a39227688
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[CHAR]] }
+
+char **__attribute__((alloc_align(2)))
+passthrough(char **x, unsigned long alignment) {
+ // CHECK: define i8** @[[PASSTHROUGH:.*]](i8** %[[X:.*]], i64 %[[ALIGNMENT:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: %[[ALIGNMENT_ADDR:.*]] = alloca i64, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: store i64 %[[ALIGNMENT]], i64* %[[ALIGNMENT_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: ret i8** %[[X_RELOADED]]
+ // CHECK-NEXT: }
+ return x;
+}
+
+char **caller(char **x, unsigned long alignment) {
+ // CHECK: define i8** @{{.*}}(i8** %[[X:.*]], i64 %[[ALIGNMENT:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: %[[ALIGNMENT_ADDR:.*]] = alloca i64, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: store i64 %[[ALIGNMENT]], i64* %[[ALIGNMENT_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[ALIGNMENT_RELOADED:.*]] = load i64, i64* %[[ALIGNMENT_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RETURNED:.*]] = call i8** @[[PASSTHROUGH]](i8** %[[X_RELOADED]], i64 %[[ALIGNMENT_RELOADED]])
+ // CHECK-NEXT: %[[ISPOSITIVE:.*]] = icmp sgt i64 %[[ALIGNMENT_RELOADED]], 0
+ // CHECK-NEXT: %[[POSITIVEMASK:.*]] = sub i64 %[[ALIGNMENT_RELOADED]], 1
+ // CHECK-NEXT: %[[MASK:.*]] = select i1 %[[ISPOSITIVE]], i64 %[[POSITIVEMASK]], i64 0
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], %[[MASK]]
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 %[[ALIGNMENT_RELOADED]], i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 %[[ALIGNMENT_RELOADED]], i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8** %[[X_RETURNED]]
+ // CHECK-NEXT: }
+#line 100
+ return passthrough(x, alignment);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp b/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp
new file mode 100644
index 000000000000..90682638f796
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[CHAR]] }
+
+char **__attribute__((alloc_align(2)))
+passthrough(char **x, unsigned long alignment) {
+ // CHECK: define i8** @[[PASSTHROUGH:.*]](i8** %[[X:.*]], i64 %[[ALIGNMENT:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: %[[ALIGNMENT_ADDR:.*]] = alloca i64, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: store i64 %[[ALIGNMENT]], i64* %[[ALIGNMENT_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: ret i8** %[[X_RELOADED]]
+ // CHECK-NEXT: }
+ return x;
+}
+
+char **caller(char **x) {
+ // CHECK: define i8** @{{.*}}(i8** %[[X:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RETURNED:.*]] = call i8** @[[PASSTHROUGH]](i8** %[[X_RELOADED]], i64 2147483648)
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 2147483647
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8** %[[X_RETURNED]]
+ // CHECK-NEXT: }
+#line 100
+ return passthrough(x, 0x80000000);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp b/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp
new file mode 100644
index 000000000000..e78667ce16e0
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[CHAR]] }
+
+char **__attribute__((assume_aligned(0x80000000, 42))) passthrough(char **x) {
+ // CHECK: define i8** @[[PASSTHROUGH:.*]](i8** %[[X:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: ret i8** %[[X_RELOADED]]
+ // CHECK-NEXT: }
+ return x;
+}
+
+char **caller(char **x) {
+ // CHECK: define i8** @{{.*}}(i8** %[[X:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RETURNED:.*]] = call i8** @[[PASSTHROUGH]](i8** %[[X_RELOADED]])
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64
+ // CHECK-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], 42
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 2147483647
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 42){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 42){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8** %[[X_RETURNED]]
+ // CHECK-NEXT: }
+#line 100
+ return passthrough(x);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp b/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp
new file mode 100644
index 000000000000..0b92ff683abf
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[CHAR]] }
+
+char **__attribute__((assume_aligned(0x80000000))) passthrough(char **x) {
+ // CHECK: define i8** @[[PASSTHROUGH:.*]](i8** %[[X:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: ret i8** %[[X_RELOADED]]
+ // CHECK-NEXT: }
+ return x;
+}
+
+char **caller(char **x) {
+ // CHECK: define i8** @{{.*}}(i8** %[[X]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RETURNED:.*]] = call i8** @[[PASSTHROUGH]](i8** %[[X_RELOADED]])
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 2147483647
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8** %[[X_RETURNED]]
+ // CHECK-NEXT: }
+#line 100
+ return passthrough(x);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-blacklist.c b/test/CodeGen/catch-alignment-assumption-blacklist.c
new file mode 100644
index 000000000000..67da7ff7627b
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-blacklist.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK
+
+// CHECK-LABEL: @baseline
+void *baseline(void *x) {
+ // CHECK: call void @__ubsan_handle_alignment_assumption(
+ return __builtin_assume_aligned(x, 1);
+}
+
+// CHECK-LABEL: blacklist_0
+__attribute__((no_sanitize("undefined"))) void *blacklist_0(void *x) {
+ return __builtin_assume_aligned(x, 1);
+}
+
+// CHECK-LABEL: blacklist_1
+__attribute__((no_sanitize("alignment"))) void *blacklist_1(void *x) {
+ return __builtin_assume_aligned(x, 1);
+}
+
+// CHECK-LABEL: dont_ignore_volatile_ptrs
+void *dont_ignore_volatile_ptrs(void * volatile x) {
+ // CHECK: call void @__ubsan_handle_alignment_assumption(
+ return __builtin_assume_aligned(x, 1);
+}
+
+// CHECK-LABEL: ignore_volatiles
+void *ignore_volatiles(volatile void * x) {
+ return __builtin_assume_aligned(x, 1);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp b/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp
new file mode 100644
index 000000000000..4384b9ce7200
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 35 }, {{.*}}* @[[CHAR]] }
+
+void *caller(char **x, unsigned long offset) {
+ // CHECK: define i8* @{{.*}}(i8** %[[X:.*]], i64 %[[OFFSET:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: store i64 %[[OFFSET]], i64* %[[OFFSET_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[BITCAST:.*]] = bitcast i8** %[[X_RELOADED]] to i8*
+ // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, i64* %[[OFFSET_ADDR]], align 8
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64
+ // CHECK-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], %[[OFFSET_RELOADED]]
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 2147483647
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[BITCAST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 %[[OFFSET_RELOADED]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 %[[OFFSET_RELOADED]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8* %[[BITCAST]]
+ // CHECK-NEXT: }
+#line 100
+ return __builtin_assume_aligned(x, 0x80000000, offset);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp b/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp
new file mode 100644
index 000000000000..18a573429d9f
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 35 }, {{.*}}* @[[CHAR]] }
+
+void *caller(char **x) {
+ // CHECK: define i8* @{{.*}}(i8** %[[X:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[BITCAST:.*]] = bitcast i8** %[[X_RELOADED]] to i8*
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64
+ // CHECK-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], 42
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 2147483647
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[BITCAST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 42){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 42){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8* %[[BITCAST]]
+ // CHECK-NEXT: }
+#line 100
+ return __builtin_assume_aligned(x, 0x80000000, 42);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp b/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp
new file mode 100644
index 000000000000..fe4384752ceb
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char **'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 35 }, {{.*}}* @[[CHAR]] }
+
+void *caller(char **x) {
+ // CHECK: define i8* @{{.*}}(i8** %[[X:.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[X_ADDR:.*]] = alloca i8**, align 8
+ // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8
+ // CHECK-NEXT: %[[BITCAST:.*]] = bitcast i8** %[[X_RELOADED]] to i8*
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 2147483647
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[BITCAST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 2147483648, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+ // CHECK-NEXT: ret i8* %[[BITCAST]]
+ // CHECK-NEXT: }
+#line 100
+ return __builtin_assume_aligned(x, 0x80000000);
+}
diff --git a/test/CodeGen/catch-alignment-assumption-openmp.cpp b/test/CodeGen/catch-alignment-assumption-openmp.cpp
new file mode 100644
index 000000000000..6d75ee0858da
--- /dev/null
+++ b/test/CodeGen/catch-alignment-assumption-openmp.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fopenmp-simd -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE
+// RUN: %clang_cc1 -fopenmp-simd -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fopenmp-simd -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fopenmp-simd -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char *'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 30 }, {{.*}}* @[[CHAR]] }
+
+void func(char *data) {
+ // CHECK: define void @{{.*}}(i8* %[[DATA:.*]])
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[DATA_ADDR:.*]] = alloca i8*, align 8
+ // CHECK: store i8* %[[DATA]], i8** %[[DATA_ADDR]], align 8
+ // CHECK: %[[DATA_RELOADED:.*]] = load i8*, i8** %[[DATA_ADDR]], align 8
+ // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[DATA_RELOADED]] to i64
+ // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 1073741823
+ // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[DATA_RELOADED]] to i64, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 1073741824, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* bitcast ({ {{{.*}}}, {{{.*}}}, {{{.*}}}* }* @[[LINE_100_ALIGNMENT_ASSUMPTION]] to i8*), i64 %[[PTRINT_DUP]], i64 1073741824, i64 0){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]])
+
+#line 100
+#pragma omp for simd aligned(data : 0x40000000)
+ for (int x = 0; x < 1; x++)
+ data[x] = data[x];
+}
diff --git a/test/CodeGen/catch-implicit-conversions-basics.c b/test/CodeGen/catch-implicit-conversions-basics.c
new file mode 100644
index 000000000000..2af16e80c8ff
--- /dev/null
+++ b/test/CodeGen/catch-implicit-conversions-basics.c
@@ -0,0 +1,125 @@
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// Test plan:
+// * Two types - int and char
+// * Two signs - signed and unsigned
+// * Square that - we have input and output types.
+// Thus, there are total of (2*2)^2 == 16 tests.
+// These are all the possible variations/combinations of casts.
+// However, not all of them should result in the check.
+// So here, we *only* check which should and which should not result in checks.
+
+// CHECK-DAG: @[[LINE_500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+// CHECK-DAG: @[[LINE_900_SIGN_CHANGE:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1000_SIGN_CHANGE:.*]] = {{.*}}, i32 1000, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1100, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_1200_SIGN_CHANGE:.*]] = {{.*}}, i32 1200, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1300_SIGN_CHANGE:.*]] = {{.*}}, i32 1300, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1400_SIGN_CHANGE:.*]] = {{.*}}, i32 1400, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}, {{.*}}, i8 4 }
+// CHECK-DAG: @[[LINE_1600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_int
+unsigned int convert_unsigned_int_to_unsigned_int(unsigned int x) {
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_char
+unsigned char convert_unsigned_char_to_unsigned_char(unsigned char x) {
+#line 200
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_int
+signed int convert_signed_int_to_signed_int(signed int x) {
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_char
+signed char convert_signed_char_to_signed_char(signed char x) {
+#line 400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_char
+unsigned char convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_UNSIGNED_TRUNCATION]] to i8*)
+#line 500
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_int
+unsigned int convert_unsigned_char_to_unsigned_int(unsigned char x) {
+#line 600
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_int
+signed int convert_unsigned_char_to_signed_int(unsigned char x) {
+#line 700
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_int
+signed int convert_signed_char_to_signed_int(signed char x) {
+#line 800
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_int
+signed int convert_unsigned_int_to_signed_int(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGN_CHANGE]] to i8*)
+#line 900
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_int
+unsigned int convert_signed_int_to_unsigned_int(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGN_CHANGE]] to i8*)
+#line 1000
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_char
+unsigned char convert_signed_int_to_unsigned_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_SIGNED_TRUNCATION]] to i8*)
+#line 1100
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_char
+unsigned char convert_signed_char_to_unsigned_char(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGN_CHANGE]] to i8*)
+#line 1200
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_char
+signed char convert_unsigned_char_to_signed_char(unsigned char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGN_CHANGE]] to i8*)
+#line 1300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_int
+unsigned int convert_signed_char_to_unsigned_int(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGN_CHANGE]] to i8*)
+#line 1400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_char
+signed char convert_unsigned_int_to_signed_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*)
+#line 1500
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_char
+signed char convert_signed_int_to_signed_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*)
+#line 1600
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-integer-arithmetic-value-change-basics.c b/test/CodeGen/catch-implicit-integer-arithmetic-value-change-basics.c
new file mode 100644
index 000000000000..0ba16eb052a1
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-arithmetic-value-change-basics.c
@@ -0,0 +1,123 @@
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// Test plan:
+// * Two types - int and char
+// * Two signs - signed and unsigned
+// * Square that - we have input and output types.
+// Thus, there are total of (2*2)^2 == 16 tests.
+// These are all the possible variations/combinations of casts.
+// However, not all of them should result in the check.
+// So here, we *only* check which should and which should not result in checks.
+
+// CHECK-DAG: @[[LINE_900_SIGN_CHANGE:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1000_SIGN_CHANGE:.*]] = {{.*}}, i32 1000, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1100, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_1200_SIGN_CHANGE:.*]] = {{.*}}, i32 1200, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1300_SIGN_CHANGE:.*]] = {{.*}}, i32 1300, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1400_SIGN_CHANGE:.*]] = {{.*}}, i32 1400, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}, {{.*}}, i8 4 }
+// CHECK-DAG: @[[LINE_1600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_int
+unsigned int convert_unsigned_int_to_unsigned_int(unsigned int x) {
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_char
+unsigned char convert_unsigned_char_to_unsigned_char(unsigned char x) {
+#line 200
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_int
+signed int convert_signed_int_to_signed_int(signed int x) {
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_char
+signed char convert_signed_char_to_signed_char(signed char x) {
+#line 400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_char
+unsigned char convert_unsigned_int_to_unsigned_char(unsigned int x) {
+#line 500
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_int
+unsigned int convert_unsigned_char_to_unsigned_int(unsigned char x) {
+#line 600
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_int
+signed int convert_unsigned_char_to_signed_int(unsigned char x) {
+#line 700
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_int
+signed int convert_signed_char_to_signed_int(signed char x) {
+#line 800
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_int
+signed int convert_unsigned_int_to_signed_int(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGN_CHANGE]] to i8*)
+#line 900
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_int
+unsigned int convert_signed_int_to_unsigned_int(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGN_CHANGE]] to i8*)
+#line 1000
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_char
+unsigned char convert_signed_int_to_unsigned_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_SIGNED_TRUNCATION]] to i8*)
+#line 1100
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_char
+unsigned char convert_signed_char_to_unsigned_char(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGN_CHANGE]] to i8*)
+#line 1200
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_char
+signed char convert_unsigned_char_to_signed_char(unsigned char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGN_CHANGE]] to i8*)
+#line 1300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_int
+unsigned int convert_signed_char_to_unsigned_int(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGN_CHANGE]] to i8*)
+#line 1400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_char
+signed char convert_unsigned_int_to_signed_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*)
+#line 1500
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_char
+signed char convert_signed_int_to_signed_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*)
+#line 1600
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-integer-conversions-basics.c b/test/CodeGen/catch-implicit-integer-conversions-basics.c
new file mode 100644
index 000000000000..2af16e80c8ff
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-conversions-basics.c
@@ -0,0 +1,125 @@
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// Test plan:
+// * Two types - int and char
+// * Two signs - signed and unsigned
+// * Square that - we have input and output types.
+// Thus, there are total of (2*2)^2 == 16 tests.
+// These are all the possible variations/combinations of casts.
+// However, not all of them should result in the check.
+// So here, we *only* check which should and which should not result in checks.
+
+// CHECK-DAG: @[[LINE_500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+// CHECK-DAG: @[[LINE_900_SIGN_CHANGE:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1000_SIGN_CHANGE:.*]] = {{.*}}, i32 1000, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1100, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_1200_SIGN_CHANGE:.*]] = {{.*}}, i32 1200, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1300_SIGN_CHANGE:.*]] = {{.*}}, i32 1300, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1400_SIGN_CHANGE:.*]] = {{.*}}, i32 1400, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}, {{.*}}, i8 4 }
+// CHECK-DAG: @[[LINE_1600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_int
+unsigned int convert_unsigned_int_to_unsigned_int(unsigned int x) {
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_char
+unsigned char convert_unsigned_char_to_unsigned_char(unsigned char x) {
+#line 200
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_int
+signed int convert_signed_int_to_signed_int(signed int x) {
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_char
+signed char convert_signed_char_to_signed_char(signed char x) {
+#line 400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_char
+unsigned char convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_UNSIGNED_TRUNCATION]] to i8*)
+#line 500
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_int
+unsigned int convert_unsigned_char_to_unsigned_int(unsigned char x) {
+#line 600
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_int
+signed int convert_unsigned_char_to_signed_int(unsigned char x) {
+#line 700
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_int
+signed int convert_signed_char_to_signed_int(signed char x) {
+#line 800
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_int
+signed int convert_unsigned_int_to_signed_int(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGN_CHANGE]] to i8*)
+#line 900
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_int
+unsigned int convert_signed_int_to_unsigned_int(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGN_CHANGE]] to i8*)
+#line 1000
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_char
+unsigned char convert_signed_int_to_unsigned_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_SIGNED_TRUNCATION]] to i8*)
+#line 1100
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_char
+unsigned char convert_signed_char_to_unsigned_char(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGN_CHANGE]] to i8*)
+#line 1200
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_char
+signed char convert_unsigned_char_to_signed_char(unsigned char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGN_CHANGE]] to i8*)
+#line 1300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_int
+unsigned int convert_signed_char_to_unsigned_int(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGN_CHANGE]] to i8*)
+#line 1400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_char
+signed char convert_unsigned_int_to_signed_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*)
+#line 1500
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_char
+signed char convert_signed_int_to_signed_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*)
+#line 1600
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-integer-sign-changes-CompoundAssignOperator.c b/test/CodeGen/catch-implicit-integer-sign-changes-CompoundAssignOperator.c
new file mode 100644
index 000000000000..9a87760896cc
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-sign-changes-CompoundAssignOperator.c
@@ -0,0 +1,2561 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fno-sanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// LHS can be of 2 types: unsigned char and signed char
+// RHS can be of 4 types: unsigned char, signed char, unsigned int, signed int.
+// Therefore there are total of 8 tests per group.
+
+// Also there are total of 10 compound operators (+=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=)
+
+// CHECK-SANITIZE-ANYRECOVER: @[[INT:.*]] = {{.*}} c"'int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_SIGN_CHANGE:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200_SIGN_CHANGE:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400_SIGN_CHANGE:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500_SIGN_CHANGE:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_600_SIGN_CHANGE:.*]] = {{.*}}, i32 600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_700_SIGN_CHANGE:.*]] = {{.*}}, i32 700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_800_SIGN_CHANGE:.*]] = {{.*}}, i32 800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_900_SIGN_CHANGE:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1000_SIGN_CHANGE:.*]] = {{.*}}, i32 1000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1200_SIGN_CHANGE:.*]] = {{.*}}, i32 1200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1300_SIGN_CHANGE:.*]] = {{.*}}, i32 1300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1400_SIGN_CHANGE:.*]] = {{.*}}, i32 1400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1500_SIGN_CHANGE:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1600_SIGN_CHANGE:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1700_SIGN_CHANGE:.*]] = {{.*}}, i32 1700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1800_SIGN_CHANGE:.*]] = {{.*}}, i32 1800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2000_SIGN_CHANGE:.*]] = {{.*}}, i32 2000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2100_SIGN_CHANGE:.*]] = {{.*}}, i32 2100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2200_SIGN_CHANGE:.*]] = {{.*}}, i32 2200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2300_SIGN_CHANGE:.*]] = {{.*}}, i32 2300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2400_SIGN_CHANGE:.*]] = {{.*}}, i32 2400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2500_SIGN_CHANGE:.*]] = {{.*}}, i32 2500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2600_SIGN_CHANGE:.*]] = {{.*}}, i32 2600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2800_SIGN_CHANGE:.*]] = {{.*}}, i32 2800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2900_SIGN_CHANGE:.*]] = {{.*}}, i32 2900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3000_SIGN_CHANGE:.*]] = {{.*}}, i32 3000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3100_SIGN_CHANGE:.*]] = {{.*}}, i32 3100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3200_SIGN_CHANGE:.*]] = {{.*}}, i32 3200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3300_SIGN_CHANGE:.*]] = {{.*}}, i32 3300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3400_SIGN_CHANGE:.*]] = {{.*}}, i32 3400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3600_SIGN_CHANGE:.*]] = {{.*}}, i32 3600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3700_SIGN_CHANGE:.*]] = {{.*}}, i32 3700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3800_SIGN_CHANGE:.*]] = {{.*}}, i32 3800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3900_SIGN_CHANGE:.*]] = {{.*}}, i32 3900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4000_SIGN_CHANGE:.*]] = {{.*}}, i32 4000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4100_SIGN_CHANGE:.*]] = {{.*}}, i32 4100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4200_SIGN_CHANGE:.*]] = {{.*}}, i32 4200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4300_SIGN_CHANGE:.*]] = {{.*}}, i32 4300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4400_SIGN_CHANGE:.*]] = {{.*}}, i32 4400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4500_SIGN_CHANGE:.*]] = {{.*}}, i32 4500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4600_SIGN_CHANGE:.*]] = {{.*}}, i32 4600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4700_SIGN_CHANGE:.*]] = {{.*}}, i32 4700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4800_SIGN_CHANGE:.*]] = {{.*}}, i32 4800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4900_SIGN_CHANGE:.*]] = {{.*}}, i32 4900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5000_SIGN_CHANGE:.*]] = {{.*}}, i32 5000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5100_SIGN_CHANGE:.*]] = {{.*}}, i32 5100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5200_SIGN_CHANGE:.*]] = {{.*}}, i32 5200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5300_SIGN_CHANGE:.*]] = {{.*}}, i32 5300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5400_SIGN_CHANGE:.*]] = {{.*}}, i32 5400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5500_SIGN_CHANGE:.*]] = {{.*}}, i32 5500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5600_SIGN_CHANGE:.*]] = {{.*}}, i32 5600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5700_SIGN_CHANGE:.*]] = {{.*}}, i32 5700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5800_SIGN_CHANGE:.*]] = {{.*}}, i32 5800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6000_SIGN_CHANGE:.*]] = {{.*}}, i32 6000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6100_SIGN_CHANGE:.*]] = {{.*}}, i32 6100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6200_SIGN_CHANGE:.*]] = {{.*}}, i32 6200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6300_SIGN_CHANGE:.*]] = {{.*}}, i32 6300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6400_SIGN_CHANGE:.*]] = {{.*}}, i32 6400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6500_SIGN_CHANGE:.*]] = {{.*}}, i32 6500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6600_SIGN_CHANGE:.*]] = {{.*}}, i32 6600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6800_SIGN_CHANGE:.*]] = {{.*}}, i32 6800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6900_SIGN_CHANGE:.*]] = {{.*}}, i32 6900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7000_SIGN_CHANGE:.*]] = {{.*}}, i32 7000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7100_SIGN_CHANGE:.*]] = {{.*}}, i32 7100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7200_SIGN_CHANGE:.*]] = {{.*}}, i32 7200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7300_SIGN_CHANGE:.*]] = {{.*}}, i32 7300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7400_SIGN_CHANGE:.*]] = {{.*}}, i32 7400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7600_SIGN_CHANGE:.*]] = {{.*}}, i32 7600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7700_SIGN_CHANGE:.*]] = {{.*}}, i32 7700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7800_SIGN_CHANGE:.*]] = {{.*}}, i32 7800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7900_SIGN_CHANGE:.*]] = {{.*}}, i32 7900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_8000_SIGN_CHANGE:.*]] = {{.*}}, i32 8000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+
+//----------------------------------------------------------------------------//
+// Compound add operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_unsigned_char
+void unsigned_char_add_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 100
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_signed_char
+void unsigned_char_add_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 200
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_unsigned_int
+void unsigned_char_add_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 300
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_signed_int
+void unsigned_char_add_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 400
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_unsigned_char
+void signed_char_add_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 500
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char
+void signed_char_add_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 600
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char_unsigned_int
+void signed_char_add_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 700
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char_signed_int
+void signed_char_add_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 800
+ (*LHS) += RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound subtract operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_unsigned_char
+void unsigned_char_sub_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 900
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_signed_char
+void unsigned_char_sub_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1000
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_unsigned_int
+void unsigned_char_sub_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 1100
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_signed_int
+void unsigned_char_sub_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1200
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_unsigned_char
+void signed_char_sub_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1300
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char
+void signed_char_sub_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1400
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char_unsigned_int
+void signed_char_sub_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1500
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char_signed_int
+void signed_char_sub_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1600
+ (*LHS) -= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound multiply operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_unsigned_char
+void unsigned_char_mul_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1700
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_signed_char
+void unsigned_char_mul_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1800
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_unsigned_int
+void unsigned_char_mul_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 1900
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_signed_int
+void unsigned_char_mul_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2000
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_unsigned_char
+void signed_char_mul_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2100
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char
+void signed_char_mul_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2200
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char_unsigned_int
+void signed_char_mul_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2300
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char_signed_int
+void signed_char_mul_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2400
+ (*LHS) *= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound divide operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_unsigned_char
+void unsigned_char_div_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2500
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_signed_char
+void unsigned_char_div_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2600
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_unsigned_int
+void unsigned_char_div_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 2700
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_signed_int
+void unsigned_char_div_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2800
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_unsigned_char
+void signed_char_div_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2900
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char
+void signed_char_div_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3000
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char_unsigned_int
+void signed_char_div_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = udiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3100
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char_signed_int
+void signed_char_div_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3200
+ (*LHS) /= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound remainder operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_unsigned_char
+void unsigned_char_rem_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3300
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_signed_char
+void unsigned_char_rem_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3400
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_unsigned_int
+void unsigned_char_rem_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 3500
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_signed_int
+void unsigned_char_rem_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3600
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_unsigned_char
+void signed_char_rem_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3700
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char
+void signed_char_rem_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3800
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char_unsigned_int
+void signed_char_rem_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = urem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3900
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char_signed_int
+void signed_char_rem_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4000
+ (*LHS) %= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound left-shift operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_unsigned_char
+void unsigned_char_shl_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4100
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_signed_char
+void unsigned_char_shl_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4200
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_unsigned_int
+void unsigned_char_shl_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4300
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_signed_int
+void unsigned_char_shl_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4400
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_unsigned_char
+void signed_char_shl_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4500
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char
+void signed_char_shl_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4600
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char_unsigned_int
+void signed_char_shl_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4700
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char_signed_int
+void signed_char_shl_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4800
+ (*LHS) <<= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound right-shift operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_unsigned_char
+void unsigned_char_shr_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4900
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_signed_char
+void unsigned_char_shr_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5000
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_unsigned_int
+void unsigned_char_shr_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5100
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_signed_int
+void unsigned_char_shr_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5200
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_unsigned_char
+void signed_char_shr_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5300
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char
+void signed_char_shr_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5400
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char_unsigned_int
+void signed_char_shr_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5500
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char_signed_int
+void signed_char_shr_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5600
+ (*LHS) >>= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound and operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_unsigned_char
+void unsigned_char_and_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5700
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_signed_char
+void unsigned_char_and_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5800
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_unsigned_int
+void unsigned_char_and_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 5900
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_signed_int
+void unsigned_char_and_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6000
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_unsigned_char
+void signed_char_and_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6100
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char
+void signed_char_and_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6200
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char_unsigned_int
+void signed_char_and_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6300
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char_signed_int
+void signed_char_and_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6400
+ (*LHS) &= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound xor operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_unsigned_char
+void unsigned_char_or_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6500_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6500
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_signed_char
+void unsigned_char_or_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6600
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_unsigned_int
+void unsigned_char_or_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 6700
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_signed_int
+void unsigned_char_or_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6800
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_unsigned_char
+void signed_char_or_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6900
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char
+void signed_char_or_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7000
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char_unsigned_int
+void signed_char_or_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7100_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7100
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char_signed_int
+void signed_char_or_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7200
+ (*LHS) |= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound or operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_unsigned_char
+void unsigned_char_xor_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7300
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_signed_char
+void unsigned_char_xor_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7400_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7400
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_unsigned_int
+void unsigned_char_xor_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 7500
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_signed_int
+void unsigned_char_xor_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7600_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7600
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_unsigned_char
+void signed_char_xor_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7700_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7700
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char
+void signed_char_xor_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7800_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7800
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char_unsigned_int
+void signed_char_xor_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7900_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7900
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char_signed_int
+void signed_char_xor_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[SRC]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_8000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_8000_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 8000
+ (*LHS) ^= RHS;
+}
diff --git a/test/CodeGen/catch-implicit-integer-sign-changes-basics.c b/test/CodeGen/catch-implicit-integer-sign-changes-basics.c
new file mode 100644
index 000000000000..71533a9b924a
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-sign-changes-basics.c
@@ -0,0 +1,157 @@
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// Test plan:
+// * Two types - int and char
+// * Two signs - signed and unsigned
+// * Square that - we have input and output types.
+// Thus, there are total of (2*2)^2 == 16 tests.
+// These are all the possible variations/combinations of casts.
+// However, not all of them should result in the check.
+// So here, we *only* check which should and which should not result in checks.
+
+// CHECK-DAG: @[[LINE_900_SIGN_CHANGE:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1000_SIGN_CHANGE:.*]] = {{.*}}, i32 1000, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1100_SIGN_CHANGE:.*]] = {{.*}}, i32 1100, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1200_SIGN_CHANGE:.*]] = {{.*}}, i32 1200, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1300_SIGN_CHANGE:.*]] = {{.*}}, i32 1300, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1400_SIGN_CHANGE:.*]] = {{.*}}, i32 1400, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1500_SIGN_CHANGE:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+// CHECK-DAG: @[[LINE_1600_SIGN_CHANGE:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}, {{.*}}, i8 3 }
+
+//============================================================================//
+// Half of the cases do not need the check. //
+//============================================================================//
+
+//----------------------------------------------------------------------------//
+// No cast happens at all. No check needed.
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_int
+unsigned int convert_unsigned_int_to_unsigned_int(unsigned int x) {
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_char
+unsigned char convert_unsigned_char_to_unsigned_char(unsigned char x) {
+#line 200
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_int
+signed int convert_signed_int_to_signed_int(signed int x) {
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_char
+signed char convert_signed_char_to_signed_char(signed char x) {
+#line 400
+ return x;
+}
+
+//----------------------------------------------------------------------------//
+// Both types are unsigned. No check needed.
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_char
+unsigned char convert_unsigned_int_to_unsigned_char(unsigned int x) {
+#line 500
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_int
+unsigned int convert_unsigned_char_to_unsigned_int(unsigned char x) {
+#line 600
+ return x;
+}
+
+//----------------------------------------------------------------------------//
+// Source type was unsigned, destination type is signed, but non-negative.
+// Because zero-extension happens - the sign bit will be 0. No check needed.
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_int
+signed int convert_unsigned_char_to_signed_int(unsigned char x) {
+#line 700
+ return x;
+}
+
+//----------------------------------------------------------------------------//
+// Both types are signed, and have the same sign, since sign-extension happens,
+// i.e. the sign bit will be propagated. No check needed.
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @convert_signed_char_to_signed_int
+signed int convert_signed_char_to_signed_int(signed char x) {
+#line 800
+ return x;
+}
+
+//============================================================================//
+// The remaining 8 cases *do* need the check. //
+//============================================================================//
+
+// These 3 result in simple 'icmp sge i32 %x, 0'
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_int
+signed int convert_unsigned_int_to_signed_int(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGN_CHANGE]] to i8*)
+#line 900
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_int
+unsigned int convert_signed_int_to_unsigned_int(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGN_CHANGE]] to i8*)
+#line 1000
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_char
+unsigned char convert_signed_int_to_unsigned_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_SIGN_CHANGE]] to i8*)
+#line 1100
+ return x;
+}
+
+// These 3 result in simple 'icmp sge i8 %x, 0'
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_char
+unsigned char convert_signed_char_to_unsigned_char(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGN_CHANGE]] to i8*)
+#line 1200
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_char
+signed char convert_unsigned_char_to_signed_char(unsigned char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGN_CHANGE]] to i8*)
+#line 1300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_int
+unsigned int convert_signed_char_to_unsigned_int(signed char x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGN_CHANGE]] to i8*)
+#line 1400
+ return x;
+}
+
+// 'icmp sge i8 (trunc i32 %x), 0'
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_char
+signed char convert_unsigned_int_to_signed_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGN_CHANGE]] to i8*)
+#line 1500
+ return x;
+}
+
+// 'xor i1 (icmp sge i8 (trunc i32 %x), 0), (icmp sge i32 %x, 0)'
+
+// CHECK-LABEL: @convert_signed_int_to_signed_char
+signed char convert_signed_int_to_signed_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGN_CHANGE]] to i8*)
+#line 1600
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-integer-sign-changes-true-negatives.c b/test/CodeGen/catch-implicit-integer-sign-changes-true-negatives.c
new file mode 100644
index 000000000000..b847344818c6
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-sign-changes-true-negatives.c
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefix=CHECK
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fno-sanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
+
+// ========================================================================== //
+// The expected true-negatives.
+// ========================================================================== //
+
+// Sanitization is explicitly disabled.
+// ========================================================================== //
+
+// CHECK-LABEL: @blacklist_0
+__attribute__((no_sanitize("undefined"))) unsigned int blacklist_0(signed int src) {
+ // We are not in "undefined" group, so that doesn't work.
+ // CHECK-SANITIZE: call
+ return src;
+}
+
+// CHECK-LABEL: @blacklist_1
+__attribute__((no_sanitize("integer"))) unsigned int blacklist_1(signed int src) {
+ return src;
+}
+
+// CHECK-LABEL: @blacklist_2
+__attribute__((no_sanitize("implicit-conversion"))) unsigned int blacklist_2(signed int src) {
+ return src;
+}
+
+// CHECK-LABEL: @blacklist_3
+__attribute__((no_sanitize("implicit-integer-sign-change"))) unsigned int blacklist_3(signed int src) {
+ return src;
+}
+
+// Explicit sign-changing conversions.
+// ========================================================================== //
+
+// CHECK-LABEL: explicit_signed_int_to_unsigned_int
+unsigned int explicit_signed_int_to_unsigned_int(signed int src) {
+ return (unsigned int)src;
+}
+
+// CHECK-LABEL: explicit_unsigned_int_to_signed_int
+signed int explicit_unsigned_int_to_signed_int(unsigned int src) {
+ return (signed int)src;
+}
+
+// Explicit NOP conversions.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_ununsigned_int_to_ununsigned_int
+unsigned int explicit_ununsigned_int_to_ununsigned_int(unsigned int src) {
+ return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
+signed int explicit_unsigned_int_to_unsigned_int(signed int src) {
+ return (signed int)src;
+}
+
+// conversions to to boolean type are not counted as sign-change.
+// ========================================================================== //
+
+// CHECK-LABEL: @unsigned_int_to_bool
+_Bool unsigned_int_to_bool(unsigned int src) {
+ return src;
+}
+
+// CHECK-LABEL: @signed_int_to_bool
+_Bool signed_int_to_bool(signed int src) {
+ return src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_int_to_bool
+_Bool explicit_unsigned_int_to_bool(unsigned int src) {
+ return (_Bool)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_bool
+_Bool explicit_signed_int_to_bool(signed int src) {
+ return (_Bool)src;
+}
+
+// Explicit conversions from pointer to an integer.
+// Can not have an implicit conversion from pointer to an integer.
+// Can not have an implicit conversion between two enums.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_voidptr_to_unsigned_int
+unsigned int explicit_voidptr_to_unsigned_int(void *src) {
+ return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_voidptr_to_signed_int
+signed int explicit_voidptr_to_signed_int(void *src) {
+ return (signed int)src;
+}
+
+// Implicit conversions from floating-point.
+// ========================================================================== //
+
+// CHECK-LABEL: @float_to_unsigned_int
+unsigned int float_to_unsigned_int(float src) {
+ return src;
+}
+
+// CHECK-LABEL: @float_to_signed_int
+signed int float_to_signed_int(float src) {
+ return src;
+}
+
+// CHECK-LABEL: @double_to_unsigned_int
+unsigned int double_to_unsigned_int(double src) {
+ return src;
+}
+
+// CHECK-LABEL: @double_to_signed_int
+signed int double_to_signed_int(double src) {
+ return src;
+}
+
+// Sugar.
+// ========================================================================== //
+
+typedef unsigned int uint32_t;
+
+// CHECK-LABEL: @uint32_to_unsigned_int
+unsigned int uint32_to_unsigned_int(uint32_t src) {
+ return src;
+}
+
+// CHECK-LABEL: @unsigned_int_to_uint32
+uint32_t unsigned_int_to_uint32(unsigned int src) {
+ return src;
+}
+
+// CHECK-LABEL: @uint32_to_uint32
+uint32_t uint32_to_uint32(uint32_t src) {
+ return src;
+}
+
+// "Transparent" Enum.
+// ========================================================================== //
+
+enum a { b = ~2147483647 };
+enum a c();
+void d(int);
+void e();
+void e() {
+ enum a f = c();
+ d(f);
+}
diff --git a/test/CodeGen/catch-implicit-integer-sign-changes.c b/test/CodeGen/catch-implicit-integer-sign-changes.c
new file mode 100644
index 000000000000..e1719048f1a7
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-sign-changes.c
@@ -0,0 +1,273 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fno-sanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_INT]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_INT]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_CHAR]], {{.*}}* @[[UNSIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UNSIGNED_CHAR]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 10 }, {{.*}}* @[[SIGNED_CHAR]], {{.*}}* @[[UNSIGNED_INT]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[INT32:.*]] = {{.*}} c"'int32_t' (aka 'int')\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[INT32]], i8 3 }
+
+// ========================================================================== //
+// The expected true-positives.
+// These are implicit, potentially sign-altering, conversions.
+// ========================================================================== //
+
+// These 3 result (after optimizations) in simple 'icmp sge i32 %src, 0'.
+
+// CHECK-LABEL: @unsigned_int_to_signed_int
+// CHECK-SAME: (i32 %[[SRC:.*]])
+signed int unsigned_int_to_signed_int(unsigned int src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i32 %[[DST]]
+ // CHECK-NEXT: }
+#line 100
+ return src;
+}
+
+// CHECK-LABEL: @signed_int_to_unsigned_int
+// CHECK-SAME: (i32 %[[SRC:.*]])
+unsigned int signed_int_to_unsigned_int(signed int src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i32 %[[DST]]
+ // CHECK-NEXT: }
+#line 200
+ return src;
+}
+
+// CHECK-LABEL: @signed_int_to_unsigned_char
+// CHECK-SAME: (i32 %[[SRC:.*]])
+unsigned char signed_int_to_unsigned_char(signed int src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+#line 300
+ return src;
+}
+
+// These 3 result (after optimizations) in simple 'icmp sge i8 %src, 0'
+
+// CHECK-LABEL: @signed_char_to_unsigned_char
+// CHECK-SAME: (i8 signext %[[SRC:.*]])
+unsigned char signed_char_to_unsigned_char(signed char src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i8
+ // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i8, i8* %[[SRC_ADDR]]
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[DST]]
+ // CHECK-NEXT: }
+#line 400
+ return src;
+}
+
+// CHECK-LABEL: @unsigned_char_to_signed_char
+// CHECK-SAME: (i8 zeroext %[[SRC:.*]])
+signed char unsigned_char_to_signed_char(unsigned char src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i8
+ // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i8, i8* %[[SRC_ADDR]]
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[DST]]
+ // CHECK-NEXT: }
+#line 500
+ return src;
+}
+
+// CHECK-LABEL: @signed_char_to_unsigned_int
+// CHECK-SAME: (i8 signext %[[SRC:.*]])
+unsigned int signed_char_to_unsigned_int(signed char src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i8
+ // CHECK-NEXT: store i8 %[[SRC]], i8* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i8, i8* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = sext i8 %[[DST]] to i32
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], false, !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i32 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i32 %[[CONV]]
+ // CHECK-NEXT: }
+#line 600
+ return src;
+}
+
+// This one result (after optimizations) in 'icmp sge i8 (trunc i32 %src), 0'
+
+// CHECK-LABEL: @unsigned_int_to_signed_char
+// CHECK-SAME: (i32 %[[SRC:.*]])
+signed char unsigned_int_to_signed_char(unsigned int src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+#line 700
+ return src;
+}
+
+// The worst one: 'xor i1 (icmp sge i8 (trunc i32 %x), 0), (icmp sge i32 %x, 0)'
+
+// CHECK-LABEL: @signed_int_to_signed_char
+// CHECK-SAME: (i32 %[[SRC:.*]])
+signed char signed_int_to_signed_char(signed int x) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-SANITIZE-NEXT: %[[SRC_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 %[[SRC_NEGATIVITYCHECK]], %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+#line 800
+ return x;
+}
+
+// ========================================================================== //
+// Check canonical type stuff
+// ========================================================================== //
+
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+
+// CHECK-LABEL: @uint32_t_to_int32_t
+// CHECK-SAME: (i32 %[[SRC:.*]])
+int32_t uint32_t_to_int32_t(uint32_t src) {
+ // CHECK: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i32 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i32 %[[DST]]
+ // CHECK-NEXT: }
+#line 900
+ return src;
+}
+
+// ========================================================================== //
+// Check that explicit conversion does not interfere with implicit conversion
+// ========================================================================== //
+// These contain one implicit and one explicit sign-changing conversion.
+// We want to make sure that we still diagnose the implicit conversion.
+
+// Implicit sign-change after explicit sign-change.
+// CHECK-LABEL: @explicit_conversion_interference0
+unsigned int explicit_conversion_interference0(unsigned int c) {
+ // CHECK-SANITIZE: call
+ return (signed int)c;
+}
+
+// Implicit sign-change before explicit sign-change.
+// CHECK-LABEL: @explicit_conversion_interference1
+unsigned int explicit_conversion_interference1(unsigned int c) {
+ // CHECK-SANITIZE: call
+ signed int b;
+ return (unsigned int)(b = c);
+}
diff --git a/test/CodeGen/catch-implicit-integer-truncations-CompoundAssignOperator.c b/test/CodeGen/catch-implicit-integer-truncations-CompoundAssignOperator.c
new file mode 100644
index 000000000000..50e7696032f2
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-truncations-CompoundAssignOperator.c
@@ -0,0 +1,2745 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fno-sanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// LHS can be of 2 types: unsigned char and signed char
+// RHS can be of 4 types: unsigned char, signed char, unsigned int, signed int.
+// Therefore there are total of 8 tests per group.
+
+// Also there are total of 10 compound operators (+=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=)
+
+// CHECK-SANITIZE-ANYRECOVER: @[[INT:.*]] = {{.*}} c"'int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_300_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1100_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 1100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1900_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 1900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2700_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 2700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 3500, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5900_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 5900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6700_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 6700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 7500, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_8000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 8000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+//----------------------------------------------------------------------------//
+// Compound add operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_unsigned_char
+void unsigned_char_add_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 100
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_signed_char
+void unsigned_char_add_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 200
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_unsigned_int
+void unsigned_char_add_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 300
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_signed_int
+void unsigned_char_add_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 400
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_unsigned_char
+void signed_char_add_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 500
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char
+void signed_char_add_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 600
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char_unsigned_int
+void signed_char_add_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 700
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char_signed_int
+void signed_char_add_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 800
+ (*LHS) += RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound subtract operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_unsigned_char
+void unsigned_char_sub_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 900
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_signed_char
+void unsigned_char_sub_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1000
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_unsigned_int
+void unsigned_char_sub_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1100
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_signed_int
+void unsigned_char_sub_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1200
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_unsigned_char
+void signed_char_sub_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1300
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char
+void signed_char_sub_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1400
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char_unsigned_int
+void signed_char_sub_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1500
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char_signed_int
+void signed_char_sub_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1600
+ (*LHS) -= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound multiply operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_unsigned_char
+void unsigned_char_mul_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1700
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_signed_char
+void unsigned_char_mul_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1800
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_unsigned_int
+void unsigned_char_mul_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1900_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1900_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1900
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_signed_int
+void unsigned_char_mul_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2000
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_unsigned_char
+void signed_char_mul_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2100
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char
+void signed_char_mul_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2200
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char_unsigned_int
+void signed_char_mul_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2300
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char_signed_int
+void signed_char_mul_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2400
+ (*LHS) *= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound divide operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_unsigned_char
+void unsigned_char_div_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2500
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_signed_char
+void unsigned_char_div_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2600
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_unsigned_int
+void unsigned_char_div_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = udiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2700_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2700_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2700
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_signed_int
+void unsigned_char_div_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2800
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_unsigned_char
+void signed_char_div_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2900
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char
+void signed_char_div_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3000
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char_unsigned_int
+void signed_char_div_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = udiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3100
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char_signed_int
+void signed_char_div_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3200
+ (*LHS) /= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound remainder operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_unsigned_char
+void unsigned_char_rem_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3300
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_signed_char
+void unsigned_char_rem_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3400
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_unsigned_int
+void unsigned_char_rem_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = urem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3500_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3500_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3500
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_signed_int
+void unsigned_char_rem_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3600
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_unsigned_char
+void signed_char_rem_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3700
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char
+void signed_char_rem_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3800
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char_unsigned_int
+void signed_char_rem_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = urem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3900
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char_signed_int
+void signed_char_rem_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4000
+ (*LHS) %= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound left-shift operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_unsigned_char
+void unsigned_char_shl_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4100
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_signed_char
+void unsigned_char_shl_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4200
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_unsigned_int
+void unsigned_char_shl_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4300
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_signed_int
+void unsigned_char_shl_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4400
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_unsigned_char
+void signed_char_shl_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4500
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char
+void signed_char_shl_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4600
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char_unsigned_int
+void signed_char_shl_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4700
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char_signed_int
+void signed_char_shl_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4800
+ (*LHS) <<= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound right-shift operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_unsigned_char
+void unsigned_char_shr_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4900
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_signed_char
+void unsigned_char_shr_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5000
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_unsigned_int
+void unsigned_char_shr_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5100
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_signed_int
+void unsigned_char_shr_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5200
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_unsigned_char
+void signed_char_shr_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5300
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char
+void signed_char_shr_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5400
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char_unsigned_int
+void signed_char_shr_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5500
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char_signed_int
+void signed_char_shr_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5600
+ (*LHS) >>= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound and operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_unsigned_char
+void unsigned_char_and_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5700
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_signed_char
+void unsigned_char_and_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5800
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_unsigned_int
+void unsigned_char_and_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5900_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5900_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5900
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_signed_int
+void unsigned_char_and_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6000
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_unsigned_char
+void signed_char_and_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6100
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char
+void signed_char_and_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6200
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char_unsigned_int
+void signed_char_and_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6300
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char_signed_int
+void signed_char_and_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6400
+ (*LHS) &= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound xor operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_unsigned_char
+void unsigned_char_or_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6500
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_signed_char
+void unsigned_char_or_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6600
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_unsigned_int
+void unsigned_char_or_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6700_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6700_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6700
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_signed_int
+void unsigned_char_or_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6800
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_unsigned_char
+void signed_char_or_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6900
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char
+void signed_char_or_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7000
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char_unsigned_int
+void signed_char_or_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7100
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char_signed_int
+void signed_char_or_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7200
+ (*LHS) |= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound or operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_unsigned_char
+void unsigned_char_xor_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7300
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_signed_char
+void unsigned_char_xor_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7400
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_unsigned_int
+void unsigned_char_xor_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7500_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7500_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7500
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_signed_int
+void unsigned_char_xor_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7600
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_unsigned_char
+void signed_char_xor_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7700
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char
+void signed_char_xor_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7800
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char_unsigned_int
+void signed_char_xor_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7900
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char_signed_int
+void signed_char_xor_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_8000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_8000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 8000
+ (*LHS) ^= RHS;
+}
diff --git a/test/CodeGen/catch-implicit-integer-truncations-basics-negatives.c b/test/CodeGen/catch-implicit-integer-truncations-basics-negatives.c
new file mode 100644
index 000000000000..1b543a3a7ff0
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-truncations-basics-negatives.c
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// CHECK-DAG: @[[LINE_100_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+// CHECK-DAG: @[[LINE_200_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+// CHECK-DAG: @[[LINE_300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+
+//----------------------------------------------------------------------------//
+// Unsigned case.
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @blacklist_0_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("undefined"))) unsigned char blacklist_0_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // We are not in "undefined" group, so that doesn't work.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_UNSIGNED_TRUNCATION]] to i8*)
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_1_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("integer"))) unsigned char blacklist_1_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_2_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_2_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_3_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_3_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_4_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-unsigned-integer-truncation"))) unsigned char blacklist_4_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_5_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-signed-integer-truncation"))) unsigned char blacklist_5_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // This is an unsigned truncation, not signed-one.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_UNSIGNED_TRUNCATION]] to i8*)
+#line 200
+ return x;
+}
+
+//----------------------------------------------------------------------------//
+// Signed case.
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @blacklist_0_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("undefined"))) signed char blacklist_0_convert_signed_int_to_signed_char(signed int x) {
+ // We are not in "undefined" group, so that doesn't work.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGNED_TRUNCATION]] to i8*)
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_1_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("integer"))) signed char blacklist_1_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_2_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-conversion"))) signed char blacklist_2_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_3_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-integer-truncation"))) signed char blacklist_3_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_4_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-signed-integer-truncation"))) signed char blacklist_4_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_5_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-unsigned-integer-truncation"))) signed char blacklist_5_convert_signed_int_to_signed_char(signed int x) {
+ // This is an signed truncation, not unsigned-one.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*)
+#line 400
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-integer-truncations-basics.c b/test/CodeGen/catch-implicit-integer-truncations-basics.c
new file mode 100644
index 000000000000..1a34246d78bd
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-truncations-basics.c
@@ -0,0 +1,115 @@
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// Test plan:
+// * Two types - int and char
+// * Two signs - signed and unsigned
+// * Square that - we have input and output types.
+// Thus, there are total of (2*2)^2 == 16 tests.
+// These are all the possible variations/combinations of casts.
+// However, not all of them should result in the check.
+// So here, we *only* check which should and which should not result in checks.
+
+// CHECK-DAG: @[[LINE_500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+// CHECK-DAG: @[[LINE_1100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1100, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_1500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_1600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_int
+unsigned int convert_unsigned_int_to_unsigned_int(unsigned int x) {
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_char
+unsigned char convert_unsigned_char_to_unsigned_char(unsigned char x) {
+#line 200
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_int
+signed int convert_signed_int_to_signed_int(signed int x) {
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_char
+signed char convert_signed_char_to_signed_char(signed char x) {
+#line 400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_char
+unsigned char convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_UNSIGNED_TRUNCATION]] to i8*)
+#line 500
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_int
+unsigned int convert_unsigned_char_to_unsigned_int(unsigned char x) {
+#line 600
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_int
+signed int convert_unsigned_char_to_signed_int(unsigned char x) {
+#line 700
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_int
+signed int convert_signed_char_to_signed_int(signed char x) {
+#line 800
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_int
+signed int convert_unsigned_int_to_signed_int(unsigned int x) {
+#line 900
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_int
+unsigned int convert_signed_int_to_unsigned_int(signed int x) {
+#line 1000
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_char
+unsigned char convert_signed_int_to_unsigned_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_SIGNED_TRUNCATION]] to i8*)
+#line 1100
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_char
+unsigned char convert_signed_char_to_unsigned_char(signed char x) {
+#line 1200
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_char
+signed char convert_unsigned_char_to_signed_char(unsigned char x) {
+#line 1300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_int
+unsigned int convert_signed_char_to_unsigned_int(signed char x) {
+#line 1400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_char
+signed char convert_unsigned_int_to_signed_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION]] to i8*)
+#line 1500
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_char
+signed char convert_signed_int_to_signed_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*)
+#line 1600
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-integer-truncations.c b/test/CodeGen/catch-implicit-integer-truncations.c
index b09f7ddfaedf..bcc9273439b9 100644
--- a/test/CodeGen/catch-implicit-integer-truncations.c
+++ b/test/CodeGen/catch-implicit-integer-truncations.c
@@ -1,21 +1,21 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
-// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
-// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fno-sanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
-// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 }
// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" }
-// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
-// CHECK-SANITIZE-ANYRECOVER: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 }
-// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
// CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[UINT8:.*]] = {{.*}} c"'uint8_t' (aka 'unsigned char')\00" }
-// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 0 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 1 }
// ========================================================================== //
// The expected true-positives. These are implicit conversions, and they truncate.
@@ -30,12 +30,13 @@ unsigned char unsigned_int_to_unsigned_char(unsigned int src) {
// CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
- // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
- // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
- // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
// CHECK-SANITIZE: [[CONT]]:
- // CHECK: ret i8 %[[DST]]
+ // CHECK-NEXT: ret i8 %[[DST]]
+ // CHECK-NEXT: }
#line 100
return src;
}
@@ -49,12 +50,13 @@ unsigned char signed_int_to_unsigned_char(signed int src) {
// CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
- // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
- // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
- // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
// CHECK-SANITIZE: [[CONT]]:
- // CHECK: ret i8 %[[DST]]
+ // CHECK-NEXT: ret i8 %[[DST]]
+ // CHECK-NEXT: }
#line 200
return src;
}
@@ -68,12 +70,13 @@ signed char unsigned_int_to_signed_char(unsigned int src) {
// CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
- // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
- // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
- // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
// CHECK-SANITIZE: [[CONT]]:
- // CHECK: ret i8 %[[DST]]
+ // CHECK-NEXT: ret i8 %[[DST]]
+ // CHECK-NEXT: }
#line 300
return src;
}
@@ -87,12 +90,13 @@ signed char signed_int_to_signed_char(signed int src) {
// CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
- // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
- // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
- // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
// CHECK-SANITIZE: [[CONT]]:
- // CHECK: ret i8 %[[DST]]
+ // CHECK-NEXT: ret i8 %[[DST]]
+ // CHECK-NEXT: }
#line 400
return src;
}
@@ -113,12 +117,13 @@ uint8_t uint32_to_uint8(uint32_t src) {
// CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
// CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
- // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
- // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
- // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
// CHECK-SANITIZE: [[CONT]]:
- // CHECK: ret i8 %[[DST]]
+ // CHECK-NEXT: ret i8 %[[DST]]
+ // CHECK-NEXT: }
#line 500
return src;
}
@@ -134,8 +139,6 @@ uint8_t uint32_to_uint8(uint32_t src) {
unsigned char explicit_conversion_interference0(unsigned int c) {
// CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize
// CHECK-SANITIZE: call
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned short)c;
}
@@ -144,8 +147,6 @@ unsigned char explicit_conversion_interference0(unsigned int c) {
unsigned char explicit_conversion_interference1(unsigned int c) {
// CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize
// CHECK-SANITIZE: call
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
unsigned short b;
return (unsigned char)(b = c);
}
@@ -161,21 +162,21 @@ unsigned char explicit_conversion_interference1(unsigned int c) {
__attribute__((no_sanitize("undefined"))) unsigned char blacklist_0(unsigned int src) {
// We are not in "undefined" group, so that doesn't work.
// CHECK-SANITIZE: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @blacklist_1
-__attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_1(unsigned int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
+__attribute__((no_sanitize("integer"))) unsigned char blacklist_1(unsigned int src) {
return src;
}
// CHECK-LABEL: @blacklist_2
-__attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_2(unsigned int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
+__attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_2(unsigned int src) {
+ return src;
+}
+
+// CHECK-LABEL: @blacklist_3
+__attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_3(unsigned int src) {
return src;
}
@@ -184,29 +185,21 @@ __attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blackl
// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char
unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned char)src;
}
// CHECK-LABEL: @explicit_signed_int_to_unsigned_char
unsigned char explicit_signed_int_to_unsigned_char(signed int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned char)src;
}
// CHECK-LABEL: @explicit_unsigned_int_to_signed_char
signed char explicit_unsigned_int_to_signed_char(unsigned int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (signed char)src;
}
// CHECK-LABEL: @explicit_signed_int_to_signed_char
signed char explicit_signed_int_to_signed_char(signed int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (signed char)src;
}
@@ -215,29 +208,21 @@ signed char explicit_signed_int_to_signed_char(signed int src) {
// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned int)src;
}
// CHECK-LABEL: @explicit_signed_int_to_signed_int
signed int explicit_signed_int_to_signed_int(signed int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (signed int)src;
}
// CHECK-LABEL: @explicit_unsigned_char_to_signed_char
unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned char)src;
}
// CHECK-LABEL: @explicit_signed_char_to_signed_char
signed char explicit_signed_char_to_signed_char(signed char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (signed char)src;
}
@@ -246,29 +231,21 @@ signed char explicit_signed_char_to_signed_char(signed char src) {
// CHECK-LABEL: @unsigned_char_to_unsigned_int
unsigned int unsigned_char_to_unsigned_int(unsigned char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @signed_char_to_unsigned_int
unsigned int signed_char_to_unsigned_int(signed char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @unsigned_char_to_signed_int
signed int unsigned_char_to_signed_int(unsigned char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @signed_char_to_signed_int
signed int signed_char_to_signed_int(signed char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
@@ -277,29 +254,21 @@ signed int signed_char_to_signed_int(signed char src) {
// CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int
unsigned int explicit_unsigned_char_to_unsigned_int(unsigned char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned int)src;
}
// CHECK-LABEL: @explicit_signed_char_to_unsigned_int
unsigned int explicit_signed_char_to_unsigned_int(signed char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned int)src;
}
// CHECK-LABEL: @explicit_unsigned_char_to_signed_int
signed int explicit_unsigned_char_to_signed_int(unsigned char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (signed int)src;
}
// CHECK-LABEL: @explicit_signed_char_to_signed_int
signed int explicit_signed_char_to_signed_int(signed char src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (signed int)src;
}
@@ -308,29 +277,21 @@ signed int explicit_signed_char_to_signed_int(signed char src) {
// CHECK-LABEL: @unsigned_int_to_bool
_Bool unsigned_int_to_bool(unsigned int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @signed_int_to_bool
_Bool signed_int_to_bool(signed int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @explicit_unsigned_int_to_bool
_Bool explicit_unsigned_int_to_bool(unsigned int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (_Bool)src;
}
// CHECK-LABEL: @explicit_signed_int_to_bool
_Bool explicit_signed_int_to_bool(signed int src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (_Bool)src;
}
@@ -341,15 +302,11 @@ _Bool explicit_signed_int_to_bool(signed int src) {
// CHECK-LABEL: @explicit_voidptr_to_unsigned_char
unsigned char explicit_voidptr_to_unsigned_char(void *src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (unsigned char)src;
}
// CHECK-LABEL: @explicit_voidptr_to_signed_char
signed char explicit_voidptr_to_signed_char(void *src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return (signed char)src;
}
@@ -358,29 +315,21 @@ signed char explicit_voidptr_to_signed_char(void *src) {
// CHECK-LABEL: @float_to_unsigned_int
unsigned int float_to_unsigned_int(float src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @float_to_signed_int
signed int float_to_signed_int(float src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @double_to_unsigned_int
unsigned int double_to_unsigned_int(double src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
// CHECK-LABEL: @double_to_signed_int
signed int double_to_signed_int(double src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
@@ -389,7 +338,5 @@ signed int double_to_signed_int(double src) {
// CHECK-LABEL: @double_to_float
float double_to_float(double src) {
- // CHECK-SANITIZE-NOT: call
- // CHECK: }
return src;
}
diff --git a/test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change-CompoundAssignOperator.c b/test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change-CompoundAssignOperator.c
new file mode 100644
index 000000000000..3dfa79fc82f1
--- /dev/null
+++ b/test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change-CompoundAssignOperator.c
@@ -0,0 +1,2553 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fno-sanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-trap=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// LHS can be of 2 types: unsigned char and signed char
+// RHS can be of 4 types: unsigned char, signed char, unsigned int, signed int.
+// Therefore there are total of 8 tests per group.
+
+// Also there are total of 10 compound operators (+=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=)
+
+// CHECK-SANITIZE-ANYRECOVER: @[[INT:.*]] = {{.*}} c"'int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_700_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 700, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_1800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2300_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 2300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_2900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 2900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3100_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 3100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 3800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_3900_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 3900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_4900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 4900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_5800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 5800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6100, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6300_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 6300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6500, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_6900_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 6900, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7100_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 7100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7200, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7300, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7400, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7600, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7700_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7700, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7800_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 7800, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_7900_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 7900, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_8000_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 8000, i32 10 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+//----------------------------------------------------------------------------//
+// Compound add operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_unsigned_char
+void unsigned_char_add_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 100
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_signed_char
+void unsigned_char_add_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 200
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_unsigned_int
+void unsigned_char_add_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 300
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_add_signed_char_signed_int
+void unsigned_char_add_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 400
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_unsigned_char
+void signed_char_add_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 500
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char
+void signed_char_add_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 600
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char_unsigned_int
+void signed_char_add_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 700
+ (*LHS) += RHS;
+}
+
+// CHECK-LABEL: @signed_char_add_signed_char_signed_int
+void signed_char_add_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = add nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 800
+ (*LHS) += RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound subtract operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_unsigned_char
+void unsigned_char_sub_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 900
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_signed_char
+void unsigned_char_sub_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1000
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_unsigned_int
+void unsigned_char_sub_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 1100
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_sub_signed_char_signed_int
+void unsigned_char_sub_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1200
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_unsigned_char
+void signed_char_sub_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1300
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char
+void signed_char_sub_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1400
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char_unsigned_int
+void signed_char_sub_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1500
+ (*LHS) -= RHS;
+}
+
+// CHECK-LABEL: @signed_char_sub_signed_char_signed_int
+void signed_char_sub_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sub nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1600
+ (*LHS) -= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound multiply operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_unsigned_char
+void unsigned_char_mul_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1700
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_signed_char
+void unsigned_char_mul_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 1800
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_unsigned_int
+void unsigned_char_mul_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 1900
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_mul_signed_char_signed_int
+void unsigned_char_mul_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2000
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_unsigned_char
+void signed_char_mul_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2100
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char
+void signed_char_mul_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2200
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char_unsigned_int
+void signed_char_mul_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2300_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2300_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2300
+ (*LHS) *= RHS;
+}
+
+// CHECK-LABEL: @signed_char_mul_signed_char_signed_int
+void signed_char_mul_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = mul nsw i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2400
+ (*LHS) *= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound divide operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_unsigned_char
+void unsigned_char_div_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2500
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_signed_char
+void unsigned_char_div_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2600
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_unsigned_int
+void unsigned_char_div_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 2700
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_div_signed_char_signed_int
+void unsigned_char_div_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2800
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_unsigned_char
+void signed_char_div_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_2900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 2900
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char
+void signed_char_div_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3000
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char_unsigned_int
+void signed_char_div_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = udiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3100
+ (*LHS) /= RHS;
+}
+
+// CHECK-LABEL: @signed_char_div_signed_char_signed_int
+void signed_char_div_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = sdiv i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3200
+ (*LHS) /= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound remainder operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_unsigned_char
+void unsigned_char_rem_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3300
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_signed_char
+void unsigned_char_rem_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3400
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_unsigned_int
+void unsigned_char_rem_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 3500
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_rem_signed_char_signed_int
+void unsigned_char_rem_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3600
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_unsigned_char
+void signed_char_rem_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3700
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char
+void signed_char_rem_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3800
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char_unsigned_int
+void signed_char_rem_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = urem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3900_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_3900_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 3900
+ (*LHS) %= RHS;
+}
+
+// CHECK-LABEL: @signed_char_rem_signed_char_signed_int
+void signed_char_rem_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = srem i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4000
+ (*LHS) %= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound left-shift operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_unsigned_char
+void unsigned_char_shl_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4100
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_signed_char
+void unsigned_char_shl_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4200
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_unsigned_int
+void unsigned_char_shl_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4300
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shl_signed_char_signed_int
+void unsigned_char_shl_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4400
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_unsigned_char
+void signed_char_shl_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4500
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char
+void signed_char_shl_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4600
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char_unsigned_int
+void signed_char_shl_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4700
+ (*LHS) <<= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shl_signed_char_signed_int
+void signed_char_shl_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = shl i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4800
+ (*LHS) <<= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound right-shift operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_unsigned_char
+void unsigned_char_shr_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_4900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 4900
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_signed_char
+void unsigned_char_shr_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5000
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_unsigned_int
+void unsigned_char_shr_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5100
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_shr_signed_char_signed_int
+void unsigned_char_shr_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5200
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_unsigned_char
+void signed_char_shr_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5300
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char
+void signed_char_shr_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5400
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char_unsigned_int
+void signed_char_shr_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5500
+ (*LHS) >>= RHS;
+}
+
+// CHECK-LABEL: @signed_char_shr_signed_char_signed_int
+void signed_char_shr_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = ashr i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5600
+ (*LHS) >>= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound and operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_unsigned_char
+void unsigned_char_and_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5700
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_signed_char
+void unsigned_char_and_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_5800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 5800
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_unsigned_int
+void unsigned_char_and_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 5900
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_and_signed_char_signed_int
+void unsigned_char_and_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6000
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_unsigned_char
+void signed_char_and_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6100_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6100
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char
+void signed_char_and_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6200
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char_unsigned_int
+void signed_char_and_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6300_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6300_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6300
+ (*LHS) &= RHS;
+}
+
+// CHECK-LABEL: @signed_char_and_signed_char_signed_int
+void signed_char_and_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = and i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6400
+ (*LHS) &= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound xor operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_unsigned_char
+void unsigned_char_or_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6500_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6500
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_signed_char
+void unsigned_char_or_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6600
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_unsigned_int
+void unsigned_char_or_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 6700
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_or_signed_char_signed_int
+void unsigned_char_or_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6800
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_unsigned_char
+void signed_char_or_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_6900_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 6900
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char
+void signed_char_or_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7000
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char_unsigned_int
+void signed_char_or_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7100
+ (*LHS) |= RHS;
+}
+
+// CHECK-LABEL: @signed_char_or_signed_char_signed_int
+void signed_char_or_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = or i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7200_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7200
+ (*LHS) |= RHS;
+}
+
+//----------------------------------------------------------------------------//
+// Compound or operator. //
+//----------------------------------------------------------------------------//
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_unsigned_char
+void unsigned_char_xor_signed_char_unsigned_char(unsigned char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7300_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7300
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_signed_char
+void unsigned_char_xor_signed_char_signed_char(unsigned char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7400
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_unsigned_int
+void unsigned_char_xor_signed_char_unsigned_int(unsigned char *LHS, unsigned int RHS) {
+#line 7500
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @unsigned_char_xor_signed_char_signed_int
+void unsigned_char_xor_signed_char_signed_int(unsigned char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = zext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7600_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7600
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_unsigned_char
+void signed_char_xor_unsigned_char(signed char *LHS, unsigned char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = zext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7700_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7700
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char
+void signed_char_xor_signed_char(signed char *LHS, signed char RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i8, align 1
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i8 %[[ARG1:.*]], i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHS:.*]] = load i8, i8* %[[RHSADDR]], align 1
+ // CHECK-NEXT: %[[RHSEXT:.*]] = sext i8 %[[RHS]] to i32
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHSEXT]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7800_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7800
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char_unsigned_int
+void signed_char_xor_signed_char_unsigned_int(signed char *LHS, unsigned int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[DST]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7900_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_7900_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 7900
+ (*LHS) ^= RHS;
+}
+
+// CHECK-LABEL: @signed_char_xor_signed_char_signed_int
+void signed_char_xor_signed_char_signed_int(signed char *LHS, signed int RHS) {
+ // CHECK: {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[ADDRESS:.*]] = alloca i8*, align 8
+ // CHECK-NEXT: %[[RHSADDR:.*]] = alloca i32, align 4
+ // CHECK-NEXT: store i8* %[[ARG0:.*]], i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: store i32 %[[ARG1:.*]], i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[RHS:.*]] = load i32, i32* %[[RHSADDR]], align 4
+ // CHECK-NEXT: %[[LHSADDR:.*]] = load i8*, i8** %[[ADDRESS]], align 8
+ // CHECK-NEXT: %[[LHS:.*]] = load i8, i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: %[[LHSEXT:.*]] = sext i8 %[[LHS]] to i32
+ // CHECK-NEXT: %[[SRC:.*]] = xor i32 %[[LHSEXT]], %[[RHS]]
+ // CHECK-NEXT: %[[DST:.*]] = trunc i32 %[[SRC]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_8000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_8000_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: store i8 %[[DST]], i8* %[[LHSADDR]], align 1
+ // CHECK-NEXT: ret void
+ // CHECK-NEXT: }
+#line 8000
+ (*LHS) ^= RHS;
+}
diff --git a/test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change.c b/test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change.c
new file mode 100644
index 000000000000..45171baebaef
--- /dev/null
+++ b/test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change.c
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fno-sanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-trap=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_100_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_200_SIGN_CHANGE:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_300_SIGN_CHANGE:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 }
+// CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
+
+//============================================================================//
+// Both sanitizers are enabled, and not disabled per-function.
+//============================================================================//
+
+// CHECK-LABEL: @unsigned_int_to_signed_char
+// CHECK-SAME: (i32 %[[SRC:.*]])
+signed char unsigned_int_to_signed_char(unsigned int src) {
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[CONV]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[DST]], !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+#line 100
+ return src;
+}
+
+//============================================================================//
+// Truncation sanitizer is disabled per-function.
+//============================================================================//
+
+// CHECK-LABEL: @unsigned_int_to_signed_char__no_truncation_sanitizer
+// CHECK-SAME: (i32 %[[SRC:.*]])
+__attribute__((no_sanitize("implicit-integer-truncation"))) signed char
+unsigned_int_to_signed_char__no_truncation_sanitizer(unsigned int src) {
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+#line 200
+ return src;
+}
+
+//============================================================================//
+// Signed truncation sanitizer is disabled per-function.
+//============================================================================//
+
+// CHECK-LABEL: @unsigned_int_to_signed_char__no_signed_truncation_sanitizer
+// CHECK-SAME: (i32 %[[SRC:.*]])
+__attribute__((no_sanitize("implicit-signed-integer-truncation"))) signed char
+unsigned_int_to_signed_char__no_signed_truncation_sanitizer(unsigned int src) {
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+#line 300
+ return src;
+}
+
+//============================================================================//
+// Sign change sanitizer is disabled per-function
+//============================================================================//
+
+// CHECK-LABEL: @unsigned_int_to_signed_char__no_sign_change_sanitizer
+// CHECK-SAME: (i32 %[[SRC:.*]])
+__attribute__((no_sanitize("implicit-integer-sign-change"))) signed char
+unsigned_int_to_signed_char__no_sign_change_sanitizer(unsigned int src) {
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[CONV]] to i32, !nosanitize
+ // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[DST]], !nosanitize
+ // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+ // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize
+ // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+#line 400
+ return src;
+}
+
+//============================================================================//
+// Both sanitizers are disabled per-function.
+//============================================================================//
+
+// CHECK-LABEL: @unsigned_int_to_signed_char__no_sanitizers
+// CHECK-SAME: (i32 %[[SRC:.*]])
+__attribute__((no_sanitize("implicit-integer-truncation"),
+ no_sanitize("implicit-integer-sign-change"))) signed char
+unsigned_int_to_signed_char__no_sanitizers(unsigned int src) {
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32
+ // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]]
+ // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8
+ // CHECK-NEXT: ret i8 %[[CONV]]
+ // CHECK-NEXT: }
+ return src;
+}
diff --git a/test/CodeGen/catch-implicit-signed-integer-truncations-basics-negatives.c b/test/CodeGen/catch-implicit-signed-integer-truncations-basics-negatives.c
new file mode 100644
index 000000000000..4ec4385c9fbb
--- /dev/null
+++ b/test/CodeGen/catch-implicit-signed-integer-truncations-basics-negatives.c
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation -fsanitize-recover=implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// CHECK-DAG: @[[LINE_100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+
+// CHECK-LABEL: @blacklist_0_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("undefined"))) signed char blacklist_0_convert_signed_int_to_signed_char(signed int x) {
+ // We are not in "undefined" group, so that doesn't work.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION]] to i8*)
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_1_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("integer"))) signed char blacklist_1_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_2_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-conversion"))) signed char blacklist_2_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_3_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-integer-truncation"))) signed char blacklist_3_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_4_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-signed-integer-truncation"))) signed char blacklist_4_convert_signed_int_to_signed_char(signed int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_5_convert_signed_int_to_signed_char
+__attribute__((no_sanitize("implicit-unsigned-integer-truncation"))) signed char blacklist_5_convert_signed_int_to_signed_char(signed int x) {
+ // This is an signed truncation, not unsigned-one.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] to i8*)
+#line 200
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-signed-integer-truncations-basics.c b/test/CodeGen/catch-implicit-signed-integer-truncations-basics.c
new file mode 100644
index 000000000000..a0fa2c3a2265
--- /dev/null
+++ b/test/CodeGen/catch-implicit-signed-integer-truncations-basics.c
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation -fsanitize-recover=implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// Test plan:
+// * Two types - int and char
+// * Two signs - signed and unsigned
+// * Square that - we have input and output types.
+// Thus, there are total of (2*2)^2 == 16 tests.
+// These are all the possible variations/combinations of casts.
+// However, not all of them should result in the check.
+// So here, we *only* check which should and which should not result in checks.
+
+// CHECK-DAG: @[[LINE_1100_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1100, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_1500_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1500, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+// CHECK-DAG: @[[LINE_1600_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 1600, i32 10 }, {{.*}}, {{.*}}, i8 2 }
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_int
+unsigned int convert_unsigned_int_to_unsigned_int(unsigned int x) {
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_char
+unsigned char convert_unsigned_char_to_unsigned_char(unsigned char x) {
+#line 200
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_int
+signed int convert_signed_int_to_signed_int(signed int x) {
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_char
+signed char convert_signed_char_to_signed_char(signed char x) {
+#line 400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_char
+unsigned char convert_unsigned_int_to_unsigned_char(unsigned int x) {
+#line 500
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_int
+unsigned int convert_unsigned_char_to_unsigned_int(unsigned char x) {
+#line 600
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_int
+signed int convert_unsigned_char_to_signed_int(unsigned char x) {
+#line 700
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_int
+signed int convert_signed_char_to_signed_int(signed char x) {
+#line 800
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_int
+signed int convert_unsigned_int_to_signed_int(unsigned int x) {
+#line 900
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_int
+unsigned int convert_signed_int_to_unsigned_int(signed int x) {
+#line 1000
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_char
+unsigned char convert_signed_int_to_unsigned_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100_SIGNED_TRUNCATION]] to i8*)
+#line 1100
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_char
+unsigned char convert_signed_char_to_unsigned_char(signed char x) {
+#line 1200
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_char
+signed char convert_unsigned_char_to_signed_char(unsigned char x) {
+#line 1300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_int
+unsigned int convert_signed_char_to_unsigned_int(signed char x) {
+#line 1400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_char
+signed char convert_unsigned_int_to_signed_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500_SIGNED_TRUNCATION]] to i8*)
+#line 1500
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_char
+signed char convert_signed_int_to_signed_char(signed int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600_SIGNED_TRUNCATION]] to i8*)
+#line 1600
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-unsigned-integer-truncations-basics-negatives.c b/test/CodeGen/catch-implicit-unsigned-integer-truncations-basics-negatives.c
new file mode 100644
index 000000000000..de6c098396df
--- /dev/null
+++ b/test/CodeGen/catch-implicit-unsigned-integer-truncations-basics-negatives.c
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// CHECK-DAG: @[[LINE_100_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+// CHECK-DAG: @[[LINE_200_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+
+// CHECK-LABEL: @blacklist_0_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("undefined"))) unsigned char blacklist_0_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // We are not in "undefined" group, so that doesn't work.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_UNSIGNED_TRUNCATION]] to i8*)
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_1_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("integer"))) unsigned char blacklist_1_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_2_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_2_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_3_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_3_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_4_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-unsigned-integer-truncation"))) unsigned char blacklist_4_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ return x;
+}
+
+// CHECK-LABEL: @blacklist_5_convert_unsigned_int_to_unsigned_char
+__attribute__((no_sanitize("implicit-signed-integer-truncation"))) unsigned char blacklist_5_convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // This is an unsigned truncation, not signed-one.
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_UNSIGNED_TRUNCATION]] to i8*)
+#line 200
+ return x;
+}
diff --git a/test/CodeGen/catch-implicit-unsigned-integer-truncations-basics.c b/test/CodeGen/catch-implicit-unsigned-integer-truncations-basics.c
new file mode 100644
index 000000000000..7eb0f0f8c91d
--- /dev/null
+++ b/test/CodeGen/catch-implicit-unsigned-integer-truncations-basics.c
@@ -0,0 +1,109 @@
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
+
+// Test plan:
+// * Two types - int and char
+// * Two signs - signed and unsigned
+// * Square that - we have input and output types.
+// Thus, there are total of (2*2)^2 == 16 tests.
+// These are all the possible variations/combinations of casts.
+// However, not all of them should result in the check.
+// So here, we *only* check which should and which should not result in checks.
+
+// CHECK-DAG: @[[LINE_500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}, {{.*}}, i8 1 }
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_int
+unsigned int convert_unsigned_int_to_unsigned_int(unsigned int x) {
+#line 100
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_char
+unsigned char convert_unsigned_char_to_unsigned_char(unsigned char x) {
+#line 200
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_int
+signed int convert_signed_int_to_signed_int(signed int x) {
+#line 300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_char
+signed char convert_signed_char_to_signed_char(signed char x) {
+#line 400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_unsigned_char
+unsigned char convert_unsigned_int_to_unsigned_char(unsigned int x) {
+ // CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_UNSIGNED_TRUNCATION]] to i8*)
+#line 500
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_unsigned_int
+unsigned int convert_unsigned_char_to_unsigned_int(unsigned char x) {
+#line 600
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_int
+signed int convert_unsigned_char_to_signed_int(unsigned char x) {
+#line 700
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_signed_int
+signed int convert_signed_char_to_signed_int(signed char x) {
+#line 800
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_int
+signed int convert_unsigned_int_to_signed_int(unsigned int x) {
+#line 900
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_int
+unsigned int convert_signed_int_to_unsigned_int(signed int x) {
+#line 1000
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_unsigned_char
+unsigned char convert_signed_int_to_unsigned_char(signed int x) {
+#line 1100
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_char
+unsigned char convert_signed_char_to_unsigned_char(signed char x) {
+#line 1200
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_char_to_signed_char
+signed char convert_unsigned_char_to_signed_char(unsigned char x) {
+#line 1300
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_char_to_unsigned_int
+unsigned int convert_signed_char_to_unsigned_int(signed char x) {
+#line 1400
+ return x;
+}
+
+// CHECK-LABEL: @convert_unsigned_int_to_signed_char
+signed char convert_unsigned_int_to_signed_char(unsigned int x) {
+#line 1500
+ return x;
+}
+
+// CHECK-LABEL: @convert_signed_int_to_signed_char
+signed char convert_signed_int_to_signed_char(signed int x) {
+#line 1600
+ return x;
+}
diff --git a/test/CodeGen/cf-runtime-abi.c b/test/CodeGen/cf-runtime-abi.c
new file mode 100644
index 000000000000..d4089771a6df
--- /dev/null
+++ b/test/CodeGen/cf-runtime-abi.c
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC-LLP64
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC
+
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fcf-runtime-abi=objc -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fcf-runtime-abi=objc -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC-LLP64
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcf-runtime-abi=objc -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC
+
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fcf-runtime-abi=standalone -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fcf-runtime-abi=standalone -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC-LLP64
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcf-runtime-abi=standalone -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-OBJC
+
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fcf-runtime-abi=swift -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-64
+// RUN: %clang_cc1 -triple aarch64-apple-ios -fcf-runtime-abi=swift -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-64
+// RUN: %clang_cc1 -triple armv7k-apple-watchos -fcf-runtime-abi=swift -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-32
+// RUN: %clang_cc1 -triple armv7-apple-tvos -fcf-runtime-abi=swift -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-32
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fcf-runtime-abi=swift -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-5_0-64
+// RUN: %clang_cc1 -triple armv7-unknown-linux-android -fcf-runtime-abi=swift -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-5_0-32
+
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fcf-runtime-abi=swift-5.0 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-64
+// RUN: %clang_cc1 -triple aarch64-apple-ios -fcf-runtime-abi=swift-5.0 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-64
+// RUN: %clang_cc1 -triple armv7k-apple-watchos -fcf-runtime-abi=swift-5.0 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-32
+// RUN: %clang_cc1 -triple armv7-apple-tvos -fcf-runtime-abi=swift-5.0 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-5_0-32
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fcf-runtime-abi=swift-5.0 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-5_0-64
+// RUN: %clang_cc1 -triple armv7-unknown-linux-android -fcf-runtime-abi=swift-5.0 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-5_0-32
+
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fcf-runtime-abi=swift-4.2 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_2-64
+// RUN: %clang_cc1 -triple aarch64-apple-ios -fcf-runtime-abi=swift-4.2 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_2-64
+// RUN: %clang_cc1 -triple armv7k-apple-watchos -fcf-runtime-abi=swift-4.2 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_2-32
+// RUN: %clang_cc1 -triple armv7-apple-tvos -fcf-runtime-abi=swift-4.2 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_2-32
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fcf-runtime-abi=swift-4.2 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-4_2-64
+// RUN: %clang_cc1 -triple armv7-unknown-linux-android -fcf-runtime-abi=swift-4.2 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-4_2-32
+
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fcf-runtime-abi=swift-4.1 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_1-64
+// RUN: %clang_cc1 -triple aarch64-apple-ios -fcf-runtime-abi=swift-4.1 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_1-64
+// RUN: %clang_cc1 -triple armv7k-apple-watchos -fcf-runtime-abi=swift-4.1 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_1-32
+// RUN: %clang_cc1 -triple armv7-apple-tvos -fcf-runtime-abi=swift-4.1 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-DARWIN-4_1-32
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fcf-runtime-abi=swift-4.1 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-4_1-64
+// RUN: %clang_cc1 -triple armv7-unknown-linux-android -fcf-runtime-abi=swift-4.1 -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-SWIFT-4_1-32
+
+const __NSConstantString *s = __builtin___CFStringMakeConstantString("");
+
+// CHECK-OBJC: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i64 0 }
+// CHECK-OBJC-LLP64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+
+// CHECK-SWIFT-DARWIN-5_0-64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i64 ptrtoint (i64* @"$s15SwiftFoundation19_NSCFConstantStringCN" to i64), i64 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i64 0 }
+// CHECK-SWIFT-DARWIN-5_0-32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32 ptrtoint (i32* @"$s15SwiftFoundation19_NSCFConstantStringCN" to i32), i32 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+// CHECK-SWIFT-5_0-64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i64 ptrtoint (i64* @"$s10Foundation19_NSCFConstantStringCN" to i64), i64 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i64 0 }
+// CHECK-SWIFT-5_0-32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32 ptrtoint (i32* @"$s10Foundation19_NSCFConstantStringCN" to i32), i32 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+
+// CHECK-SWIFT-DARWIN-4_2-64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i64 ptrtoint (i64* @"$S15SwiftFoundation19_NSCFConstantStringCN" to i64), i64 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+// CHECK-SWIFT-DARWIN-4_2-32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32 ptrtoint (i32* @"$S15SwiftFoundation19_NSCFConstantStringCN" to i32), i32 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+// CHECK-SWIFT-4_2-64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i64 ptrtoint (i64* @"$S10Foundation19_NSCFConstantStringCN" to i64), i64 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+// CHECK-SWIFT-4_2-32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32 ptrtoint (i32* @"$S10Foundation19_NSCFConstantStringCN" to i32), i32 1, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+
+// CHECK-SWIFT-DARWIN-4_1-64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i64 ptrtoint (i64* @__T015SwiftFoundation19_NSCFConstantStringCN to i64), i64 5, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+// CHECK-SWIFT-DARWIN-4_1-32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32 ptrtoint (i32* @__T015SwiftFoundation19_NSCFConstantStringCN to i32), i32 5, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+// CHECK-SWIFT-4_1-64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i64 ptrtoint (i64* @__T010Foundation19_NSCFConstantStringCN to i64), i64 5, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+// CHECK-SWIFT-4_1-32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32 ptrtoint (i32* @__T010Foundation19_NSCFConstantStringCN to i32), i32 5, i64 1992, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i32 0 }
+
diff --git a/test/CodeGen/cfguardtable.c b/test/CodeGen/cfguardtable.c
new file mode 100644
index 000000000000..964929261297
--- /dev/null
+++ b/test/CodeGen/cfguardtable.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -cfguard -emit-llvm %s -o - | FileCheck %s
+
+void f() {}
+
+// Check that the cfguardtable metadata flag gets set on the module.
+// CHECK: !"cfguardtable", i32 1}
diff --git a/test/CodeGen/cfstring-elf-cfbuild-x86_64.c b/test/CodeGen/cfstring-elf-cfbuild-x86_64.c
new file mode 100644
index 000000000000..8b90d7c0c1d8
--- /dev/null
+++ b/test/CodeGen/cfstring-elf-cfbuild-x86_64.c
@@ -0,0 +1,36 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -triple x86_64-elf -DCF_BUILDING_CF -DDECL -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DECL
+// RUN: %clang_cc1 -triple x86_64-elf -DCF_BUILDING_CF -DDEFN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DEFN
+// RUN: %clang_cc1 -triple x86_64-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF
+// RUN: %clang_cc1 -triple x86_64-elf -DEXTERN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-EXTERN
+
+// RUN: %clang_cc1 -Os -triple x86_64-elf -DCF_BUILDING_CF -DDECL -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DECL
+// RUN: %clang_cc1 -Os -triple x86_64-elf -DCF_BUILDING_CF -DDEFN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DEFN
+// RUN: %clang_cc1 -Os -triple x86_64-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF
+// RUN: %clang_cc1 -Os -triple x86_64-elf -DEXTERN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-EXTERN
+
+
+#if defined(CF_BUILDING_CF)
+#if defined(DECL)
+extern long __CFConstantStringClassReference[];
+#elif defined(DEFN)
+long __CFConstantStringClassReference[32];
+#endif
+#else
+#if defined(EXTERN)
+extern long __CFConstantStringClassReference[];
+#else
+long __CFConstantStringClassReference[];
+#endif
+#endif
+
+typedef struct __CFString *CFStringRef;
+const CFStringRef string = (CFStringRef)__builtin___CFStringMakeConstantString("string");
+
+
+// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external global [0 x i32]
+// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = common global [32 x i64] zeroinitializer, align 16
+// CHECK-CF: @__CFConstantStringClassReference = common global [1 x i64] zeroinitializer, align 8
+// CHECK-CF-EXTERN: @__CFConstantStringClassReference = external global [0 x i32]
+// CHECK-CF-EXTERN: @.str = private unnamed_addr constant [7 x i8] c"string\00", section ".rodata", align 1
diff --git a/test/CodeGen/cfstring-elf-sections-x86_64.c b/test/CodeGen/cfstring-elf-sections-x86_64.c
new file mode 100644
index 000000000000..439113a4e855
--- /dev/null
+++ b/test/CodeGen/cfstring-elf-sections-x86_64.c
@@ -0,0 +1,23 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -triple x86_64-elf -S %s -o - | FileCheck %s -check-prefix CHECK-ELF-DATA-SECTION
+
+typedef struct __CFString *CFStringRef;
+const CFStringRef one = (CFStringRef)__builtin___CFStringMakeConstantString("one");
+const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xef\xbf\xbd\x74\xef\xbf\xbd\x77\xef\xbf\xbd\x6f");
+
+// CHECK-ELF-DATA-SECTION: .type .L.str,@object
+// CHECK-ELF-DATA-SECTION: .section .rodata,"a",@progbits
+// CHECK-ELF-DATA-SECTION: .L.str:
+// CHECK-ELF-DATA-SECTION: .asciz "one"
+
+// CHECK-ELF-DATA-SECTION: .type .L.str.1,@object
+// CHECK-ELF-DATA-SECTION: .section .rodata,"a",@progbits
+// CHECK-ELF-DATA-SECTION: .L.str.1:
+// CHECK-ELF-DATA-SECTION: .short 65533
+// CHECK-ELF-DATA-SECTION: .short 116
+// CHECK-ELF-DATA-SECTION: .short 65533
+// CHECK-ELF-DATA-SECTION: .short 119
+// CHECK-ELF-DATA-SECTION: .short 65533
+// CHECK-ELF-DATA-SECTION: .short 111
+// CHECK-ELF-DATA-SECTION: .short 0
diff --git a/test/CodeGen/CFStrings.c b/test/CodeGen/cfstring3.c
index 4edb5ff26e60..839ef656935b 100644
--- a/test/CodeGen/CFStrings.c
+++ b/test/CodeGen/cfstring3.c
@@ -7,7 +7,6 @@
// RUN: %clang_cc1 -triple armv7-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-ELF -check-prefix CHECK-ELF32
// RUN: %clang_cc1 -triple i686-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-ELF -check-prefix CHECK-ELF32
// RUN: %clang_cc1 -triple x86_64-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-ELF -check-prefix CHECK-ELF64
-// RUN: %clang_cc1 -triple armv7-elf -S %s -o - | FileCheck %s -check-prefix CHECK-ELF-DATA-SECTION
// RUN: %clang_cc1 -triple armv7-macho -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACHO -check-prefix CHECK-MACHO32
// RUN: %clang_cc1 -triple i386-apple-macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACHO -check-prefix CHECK-MACHO32
@@ -22,7 +21,7 @@ const CFStringRef one = (CFStringRef)__builtin___CFStringMakeConstantString("one
const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xef\xbf\xbd\x74\xef\xbf\xbd\x77\xef\xbf\xbd\x6f");
// CHECK-COFF: @.str = private unnamed_addr constant [4 x i8] c"one\00", align 1
-// CHECK-ELF: @.str = private unnamed_addr constant [4 x i8] c"one\00", align 1
+// CHECK-ELF: @.str = private unnamed_addr constant [4 x i8] c"one\00", section ".rodata", align 1
// CHECK-MACHO: @.str = private unnamed_addr constant [4 x i8] c"one\00", section "__TEXT,__cstring,cstring_literals", align 1
// CHECK-COFF: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "cfstring", align {{[48]}}
@@ -32,7 +31,7 @@ const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xe
// CHECK-MACHO64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8
// CHECK-COFF: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], align 2
-// CHECK-ELF: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], align 2
+// CHECK-ELF: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], section ".rodata", align 2
// CHECK-MACHO: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], section "__TEXT,__ustring", align 2
// CHECK-COFF: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "cfstring", align {{[48]}}
@@ -41,19 +40,6 @@ const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xe
// CHECK-MACHO32: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "__DATA,__cfstring", align 4
// CHECK-MACHO64: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i64 6 }, section "__DATA,__cfstring", align 8
-// CHECK-ELF-DATA-SECTION: .section .rodata.str1.1
-// CHECK-ELF-DATA-SECTION: .asciz "one"
-
-// CHECK-ELF-DATA-SECTION: .section .rodata.str2.2
-// CHECK-ELF-DATA-SECTION: .short 65533
-// CHECK-ELF-DATA-SECTION: .short 116
-// CHECK-ELF-DATA-SECTION: .short 65533
-// CHECK-ELF-DATA-SECTION: .short 119
-// CHECK-ELF-DATA-SECTION: .short 65533
-// CHECK-ELF-DATA-SECTION: .short 111
-// CHECK-ELF-DATA-SECTION: .short 0
-
// CHECK-ASM-COFF: .section cfstring,"dw"
-// CHECK-ASM-ELF: .section cfstring,"aw"
+// CHECK-ASM-ELF: .section cfstring,"aw",{{[@%]}}progbits
// CHECK-ASM-MACHO: .section __DATA,__cfstring
-
diff --git a/test/CodeGen/cleanup-destslot-simple.c b/test/CodeGen/cleanup-destslot-simple.c
index e7067e7b0485..f571c6ab0e9e 100644
--- a/test/CodeGen/cleanup-destslot-simple.c
+++ b/test/CodeGen/cleanup-destslot-simple.c
@@ -3,6 +3,7 @@
// We shouldn't have markers at -O0 or with msan.
// RUN: %clang_cc1 -O0 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - -fsanitize=memory | FileCheck %s
+// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - -fsanitize=kernel-memory | FileCheck %s
// There is no exception to handle here, lifetime.end is not a destructor,
// so there is no need have cleanup dest slot related code
diff --git a/test/CodeGen/code-coverage-filter.c b/test/CodeGen/code-coverage-filter.c
new file mode 100644
index 000000000000..5186dadcd804
--- /dev/null
+++ b/test/CodeGen/code-coverage-filter.c
@@ -0,0 +1,84 @@
+// RUN: %clang -S -emit-llvm --coverage %s -o %t
+// RUN: FileCheck -check-prefix=ALL < %t %s
+// RUN: %clang -S -emit-llvm --coverage -fprofile-exclude-files=".*\.h$" %s -o %t
+// RUN: FileCheck -check-prefix=NO-HEADER < %t %s
+// RUN: %clang -S -emit-llvm --coverage -fprofile-filter-files=".*\.c$" %s -o %t
+// RUN: FileCheck -check-prefix=NO-HEADER < %t %s
+// RUN: %clang -S -emit-llvm --coverage -fprofile-filter-files=".*\.c$;.*1\.h$" %s -o %t
+// RUN: FileCheck -check-prefix=NO-HEADER2 < %t %s
+// RUN: %clang -S -emit-llvm --coverage -fprofile-exclude-files=".*2\.h$;.*1\.h$" %s -o %t
+// RUN: FileCheck -check-prefix=JUST-C < %t %s
+// RUN: %clang -S -emit-llvm --coverage -fprofile-exclude-files=".*code\-coverage\-filter\.c$" %s -o %t
+// RUN: FileCheck -check-prefix=HEADER < %t %s
+// RUN: %clang -S -emit-llvm --coverage -fprofile-filter-files=".*\.c$" -fprofile-exclude-files=".*\.c$" %s -o %t
+// RUN: FileCheck -check-prefix=NONE < %t %s
+// RUN: %clang -S -emit-llvm --coverage -fprofile-filter-files=".*\.c$" -fprofile-exclude-files=".*\.h$" %s -o %t
+// RUN: FileCheck -check-prefix=JUST-C < %t %s
+
+#include "Inputs/code-coverage-filter1.h"
+#include "Inputs/code-coverage-filter2.h"
+
+void test() {
+ test1();
+ test2();
+}
+
+// ALL: void @test1() #0 {{.*}}
+// ALL: {{.*}}__llvm_gcov_ctr{{.*}}
+// ALL: ret void
+// ALL: void @test2() #0 {{.*}}
+// ALL: {{.*}}__llvm_gcov_ctr{{.*}}
+// ALL: ret void
+// ALL: void @test() #0 {{.*}}
+// ALL: {{.*}}__llvm_gcov_ctr{{.*}}
+// ALL: ret void
+
+// NO-HEADER: void @test1() #0 {{.*}}
+// NO-HEADER-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// NO-HEADER: ret void
+// NO-HEADER: void @test2() #0 {{.*}}
+// NO-HEADER-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// NO-HEADER: ret void
+// NO-HEADER: void @test() #0 {{.*}}
+// NO-HEADER: {{.*}}__llvm_gcov_ctr{{.*}}
+// NO-HEADER: ret void
+
+// NO-HEADER2: void @test1() #0 {{.*}}
+// NO-HEADER2: {{.*}}__llvm_gcov_ctr{{.*}}
+// NO-HEADER2: ret void
+// NO-HEADER2: void @test2() #0 {{.*}}
+// NO-HEADER2-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// NO-HEADER2: ret void
+// NO-HEADER2: void @test() #0 {{.*}}
+// NO-HEADER2: {{.*}}__llvm_gcov_ctr{{.*}}
+// NO-HEADER2: ret void
+
+// JUST-C: void @test1() #0 {{.*}}
+// JUST-C-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// JUST-C: ret void
+// JUST-C: void @test2() #0 {{.*}}
+// JUST-C-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// JUST-C: ret void
+// JUST-C: void @test() #0 {{.*}}
+// JUST-C: {{.*}}__llvm_gcov_ctr{{.*}}
+// JUST-C: ret void
+
+// HEADER: void @test1() #0 {{.*}}
+// HEADER: {{.*}}__llvm_gcov_ctr{{.*}}
+// HEADER: ret void
+// HEADER: void @test2() #0 {{.*}}
+// HEADER: {{.*}}__llvm_gcov_ctr{{.*}}
+// HEADER: ret void
+// HEADER: void @test() #0 {{.*}}
+// HEADER-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// HEADER: ret void
+
+// NONE: void @test1() #0 {{.*}}
+// NONE-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// NONE: ret void
+// NONE: void @test2() #0 {{.*}}
+// NONE-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// NONE: ret void
+// NONE: void @test() #0 {{.*}}
+// NONE-NOT: {{.*}}__llvm_gcov_ctr{{.*}}
+// NONE: ret void
diff --git a/test/CodeGen/code-coverage.c b/test/CodeGen/code-coverage.c
index 310d58544e41..98153933c918 100644
--- a/test/CodeGen/code-coverage.c
+++ b/test/CodeGen/code-coverage.c
@@ -40,8 +40,7 @@ int test2(int b) {
// Check that the noredzone flag is set on the generated functions.
-// CHECK: void @__llvm_gcov_indirect_counter_increment(i32* %{{.*}}, i64** %{{.*}}) unnamed_addr [[NRZ:#[0-9]+]]
-// CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ]]
+// CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]]
// CHECK: void @__llvm_gcov_flush() unnamed_addr [[NRZ]]
// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]]
diff --git a/test/CodeGen/codemodels.c b/test/CodeGen/codemodels.c
new file mode 100644
index 000000000000..cc68bf2120c5
--- /dev/null
+++ b/test/CodeGen/codemodels.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-NOMODEL
+// RUN: %clang_cc1 -triple aarch64-unknown-none-eabi -emit-llvm -mcode-model tiny %s -o - | FileCheck %s -check-prefix=CHECK-TINY
+// RUN: %clang_cc1 -emit-llvm -mcode-model small %s -o - | FileCheck %s -check-prefix=CHECK-SMALL
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcode-model kernel %s -o - | FileCheck %s -check-prefix=CHECK-KERNEL
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcode-model medium %s -o - | FileCheck %s -check-prefix=CHECK-MEDIUM
+// RUN: %clang_cc1 -emit-llvm -mcode-model large %s -o - | FileCheck %s -check-prefix=CHECK-LARGE
+
+// CHECK-TINY: !llvm.module.flags = !{{{.*}}}
+// CHECK-TINY: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 0}
+// CHECK-SMALL: !llvm.module.flags = !{{{.*}}}
+// CHECK-SMALL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 1}
+// CHECK-KERNEL: !llvm.module.flags = !{{{.*}}}
+// CHECK-KERNEL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 2}
+// CHECK-MEDIUM: !llvm.module.flags = !{{{.*}}}
+// CHECK-MEDIUM: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 3}
+// CHECK-LARGE: !llvm.module.flags = !{{{.*}}}
+// CHECK-LARGE: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 4}
+// CHECK-NOMODEL-NOT: Code Model
diff --git a/test/CodeGen/coff-aarch64-type-sizes.c b/test/CodeGen/coff-aarch64-type-sizes.c
index 1d8a64520469..20c557c85952 100644
--- a/test/CodeGen/coff-aarch64-type-sizes.c
+++ b/test/CodeGen/coff-aarch64-type-sizes.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple aarch64-windows -emit-llvm -w -o - %s | FileCheck %s
// CHECK: target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"
-// CHECK: target triple = "aarch64--windows-msvc"
+// CHECK: target triple = "aarch64-unknown-windows-msvc"
int check_short() {
return sizeof(short);
diff --git a/test/CodeGen/darwin-ppc-varargs.c b/test/CodeGen/darwin-ppc-varargs.c
deleted file mode 100644
index c2a0d192233c..000000000000
--- a/test/CodeGen/darwin-ppc-varargs.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 -triple powerpc-apple-macosx10.5.0 -target-feature +altivec -Os -emit-llvm -o - %s | FileCheck %s
-
-int f(__builtin_va_list args) { return __builtin_va_arg(args, int); }
-
-// CHECK: @f(i8* {{.*}}[[PARAM:%[a-zA-Z0-9]+]])
-// CHECK: [[BITCAST:%[0-9]+]] = bitcast i8* [[PARAM]] to i32*
-// CHECK: [[VALUE:%[0-9]+]] = load i32, i32* [[BITCAST]], align 4
-// CHECK: ret i32 [[VALUE]]
-
-void h(vector int);
-int g(__builtin_va_list args) {
- int i = __builtin_va_arg(args, int);
- h(__builtin_va_arg(args, vector int));
- int j = __builtin_va_arg(args, int);
- return i + j;
-}
-
-// CHECK: @g(i8* {{.*}}[[PARAM:%[a-zA-Z0-9]+]])
-// CHECK: [[NEXT:%[-_.a-zA-Z0-9]+]] = getelementptr inbounds i8, i8* [[PARAM]], i32 4
-// CHECK: [[BITCAST:%[0-9]+]] = bitcast i8* [[PARAM]] to i32*
-// CHECK: [[LOAD:%[0-9]+]] = load i32, i32* [[BITCAST]], align 4
-// CHECK: [[PTRTOINT:%[0-9]+]] = ptrtoint i8* [[NEXT]] to i32
-// CHECK: [[ADD:%[0-9]+]] = add i32 [[PTRTOINT]], 15
-// CHECK: [[AND:%[0-9]+]] = and i32 [[ADD]], -16
-// CHECK: [[INTTOPTR:%[0-9]+]] = inttoptr i32 [[AND]] to <4 x i32>*
-// CHECK: [[ARG:%[0-9]]] = load <4 x i32>, <4 x i32>* [[INTTOPTR]], align 16
-// CHECK: call void @h(<4 x i32> [[ARG]]
-
diff --git a/test/CodeGen/darwin-sdk-version.c b/test/CodeGen/darwin-sdk-version.c
new file mode 100644
index 000000000000..23c43f5932a4
--- /dev/null
+++ b/test/CodeGen/darwin-sdk-version.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14 -target-sdk-version=10.14.1 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: !llvm.module.flags = !{!0
+// CHECK: !0 = !{i32 2, !"SDK Version", [3 x i32] [i32 10, i32 14, i32 1]}
diff --git a/test/CodeGen/darwin-string-literals.c b/test/CodeGen/darwin-string-literals.c
index 1cebbf6fbdd0..1177b2de401d 100644
--- a/test/CodeGen/darwin-string-literals.c
+++ b/test/CodeGen/darwin-string-literals.c
@@ -5,14 +5,6 @@
// CHECK-LSB: @.str.2 = private unnamed_addr constant [18 x i16] [i16 104, i16 101, i16 108, i16 108, i16 111, i16 32, i16 8594, i16 32, i16 9731, i16 32, i16 8592, i16 32, i16 119, i16 111, i16 114, i16 108, i16 100, i16 0], section "__TEXT,__ustring", align 2
// CHECK-LSB: @.str.4 = private unnamed_addr constant [6 x i16] [i16 116, i16 101, i16 115, i16 116, i16 8482, i16 0], section "__TEXT,__ustring", align 2
-
-// RUN: %clang_cc1 -triple powerpc-apple-darwin9 -emit-llvm %s -o - | FileCheck -check-prefix CHECK-MSB %s
-
-// CHECK-MSB: @.str = private unnamed_addr constant [8 x i8] c"string0\00"
-// CHECK-MSB: @.str.1 = private unnamed_addr constant [8 x i8] c"string1\00"
-// CHECK-MSB: @.str.2 = private unnamed_addr constant [18 x i16] [i16 104, i16 101, i16 108, i16 108, i16 111, i16 32, i16 8594, i16 32, i16 9731, i16 32, i16 8592, i16 32, i16 119, i16 111, i16 114, i16 108, i16 100, i16 0], section "__TEXT,__ustring", align 2
-// CHECK-MSB: @.str.4 = private unnamed_addr constant [6 x i16] [i16 116, i16 101, i16 115, i16 116, i16 8482, i16 0], section "__TEXT,__ustring", align 2
-
const char *g0 = "string0";
const void *g1 = __builtin___CFStringMakeConstantString("string1");
const void *g2 = __builtin___CFStringMakeConstantString("hello \u2192 \u2603 \u2190 world");
diff --git a/test/CodeGen/debug-info-abspath.c b/test/CodeGen/debug-info-abspath.c
new file mode 100644
index 000000000000..b20ed317d7d4
--- /dev/null
+++ b/test/CodeGen/debug-info-abspath.c
@@ -0,0 +1,34 @@
+// RUN: mkdir -p %t/UNIQUEISH_SENTINEL
+// RUN: cp %s %t/UNIQUEISH_SENTINEL/debug-info-abspath.c
+
+// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
+// RUN: %t/UNIQUEISH_SENTINEL/debug-info-abspath.c -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// RUN: cp %s %t.c
+// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
+// RUN: %t.c -emit-llvm -o - | FileCheck %s --check-prefix=INTREE
+
+// RUN: cd %t/UNIQUEISH_SENTINEL
+// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
+// RUN: debug-info-abspath.c -emit-llvm -o - \
+// RUN: | FileCheck %s --check-prefix=CURDIR
+// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
+// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefix=CURDIR
+
+void foo() {}
+
+// Since %s is an absolute path, directory should be the common
+// prefix, but the directory part should be part of the filename.
+
+// CHECK: = distinct !DISubprogram({{.*}}file: ![[SPFILE:[0-9]+]]
+// CHECK: ![[SPFILE]] = !DIFile(filename: "{{.*}}UNIQUEISH_SENTINEL
+// CHECK-SAME: debug-info-abspath.c"
+// CHECK-NOT: directory: "{{.*}}UNIQUEISH_SENTINEL
+
+// INTREE: = distinct !DISubprogram({{.*}}![[SPFILE:[0-9]+]]
+// INTREE: DIFile({{.*}}directory: "{{.+}}CodeGen{{.*}}")
+
+// CURDIR: = distinct !DICompileUnit({{.*}}file: ![[CUFILE:[0-9]+]]
+// CURDIR: ![[CUFILE]] = !DIFile({{.*}}directory: "{{.+}}UNIQUEISH_SENTINEL")
+
diff --git a/test/CodeGen/debug-info-compilation-dir.c b/test/CodeGen/debug-info-compilation-dir.c
index be2cc3542df0..786d23556de9 100644
--- a/test/CodeGen/debug-info-compilation-dir.c
+++ b/test/CodeGen/debug-info-compilation-dir.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fdebug-compilation-dir /nonsense -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-NONSENSE %s
+// RUN: mkdir -p %t.dir && cd %t.dir
+// RUN: cp %s rel.c
+// RUN: %clang_cc1 -fdebug-compilation-dir /nonsense -emit-llvm -debug-info-kind=limited rel.c -o - | FileCheck -check-prefix=CHECK-NONSENSE %s
// CHECK-NONSENSE: nonsense
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-DIR %s
diff --git a/test/CodeGen/debug-info-enum.cpp b/test/CodeGen/debug-info-enum.cpp
index 1237f28b9a55..bbe66bb9fa6a 100644
--- a/test/CodeGen/debug-info-enum.cpp
+++ b/test/CodeGen/debug-info-enum.cpp
@@ -12,7 +12,7 @@ enum class E0 : signed char {
} x0;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E0"
// CHECK-SAME: baseType: ![[SCHAR:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS0:[0-9]+]]
// CHECK: ![[SCHAR]] = !DIBasicType(name: "signed char", size: 8, encoding: DW_ATE_signed_char)
// CHECK: ![[ELTS0]] = !{![[A0:[0-9]+]], ![[B0:[0-9]+]]}
@@ -22,7 +22,7 @@ enum class E0 : signed char {
enum class E1 : unsigned char { A1 = 255 } x1;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E1"
// CHECK-SAME: baseType: ![[UCHAR:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS1:[0-9]+]]
// CHECK: ![[UCHAR]] = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
// CHECK: ![[ELTS1]] = !{![[A1:[0-9]+]]}
@@ -34,7 +34,7 @@ enum class E2 : signed short {
} x2;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E2"
// CHECK-SAME: baseType: ![[SHORT:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS2:[0-9]+]]
// CHECK: ![[SHORT]] = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed)
// CHECK: ![[ELTS2]] = !{![[A2:[0-9]+]], ![[B2:[0-9]+]]}
@@ -44,7 +44,7 @@ enum class E2 : signed short {
enum class E3 : unsigned short { A3 = 65535 } x3;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E3"
// CHECK-SAME: baseType: ![[USHORT:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS3:[0-9]+]]
// CHECK: ![[USHORT]] = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
// CHECK: ![[ELTS3]] = !{![[A3:[0-9]+]]}
@@ -53,7 +53,7 @@ enum class E3 : unsigned short { A3 = 65535 } x3;
enum class E4 : signed int { A4 = -2147483648, B4 = 2147483647 } x4;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E4"
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS4:[0-9]+]]
// CHECK: ![[INT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
// CHECK: ![[ELTS4]] = !{![[A4:[0-9]+]], ![[B4:[0-9]+]]}
@@ -63,7 +63,7 @@ enum class E4 : signed int { A4 = -2147483648, B4 = 2147483647 } x4;
enum class E5 : unsigned int { A5 = 4294967295 } x5;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E5"
// CHECK-SAME: baseType: ![[UINT:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS5:[0-9]+]]
// CHECK: ![[UINT]] = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
// CHECK: ![[ELTS5]] = !{![[A5:[0-9]+]]}
@@ -75,7 +75,7 @@ enum class E6 : signed long long {
} x6;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E6"
// CHECK-SAME: baseType: ![[LONG:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS6:[0-9]+]]
// CHECK: ![[LONG]] = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
// CHECK: ![[ELTS6]] = !{![[A6:[0-9]+]], ![[B6:[0-9]+]]}
@@ -85,7 +85,7 @@ enum class E6 : signed long long {
enum class E7 : unsigned long long { A7 = 18446744073709551615ULL } x7;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E7"
// CHECK-SAME: baseType: ![[ULONG:[0-9]+]]
-// CHECK-SAME: DIFlagFixedEnum
+// CHECK-SAME: DIFlagEnumClass
// CHECK-SAME: elements: ![[ELTS7:[0-9]+]]
// CHECK: ![[ULONG]] = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
// CHECK: ![[ELTS7]] = !{![[A7:[0-9]+]]}
@@ -95,6 +95,6 @@ enum class E7 : unsigned long long { A7 = 18446744073709551615ULL } x7;
enum E8 { A8 = -128, B8 = 127 } x8;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E8"
// CHECK-SAME: baseType: ![[INT]]
-// CHECK-NOT: DIFlagFixedEnum
+// CHECK-NOT: DIFlagEnumClass
// CHECK: !DIEnumerator(name: "A8", value: -128)
diff --git a/test/CodeGen/debug-info-gline-tables-only.c b/test/CodeGen/debug-info-gline-tables-only.c
index e890dbb0da20..6f832be82875 100644
--- a/test/CodeGen/debug-info-gline-tables-only.c
+++ b/test/CodeGen/debug-info-gline-tables-only.c
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -debug-info-kind=line-tables-only -S -emit-llvm -o - | FileCheck %s
-// Checks that clang with "-gline-tables-only" doesn't emit debug info
+// RUN: %clang_cc1 %s -debug-info-kind=line-directives-only -S -emit-llvm -o - | FileCheck %s
+// Checks that clang with "-gline-tables-only" or "-gline-directives-only" doesn't emit debug info
// for variables and types.
// CHECK-NOT: DW_TAG_variable
diff --git a/test/CodeGen/debug-info-gline-tables-only2.c b/test/CodeGen/debug-info-gline-tables-only2.c
index da17d41f3b13..8b8fbc2fe00c 100644
--- a/test/CodeGen/debug-info-gline-tables-only2.c
+++ b/test/CodeGen/debug-info-gline-tables-only2.c
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -debug-info-kind=line-tables-only -S -emit-llvm -o - | FileCheck %s
-// Checks that clang with "-gline-tables-only" emits metadata for
+// RUN: %clang_cc1 %s -debug-info-kind=line-directives-only -S -emit-llvm -o - | FileCheck %s
+// Checks that clang with "-gline-tables-only" or "-gline-directives-only" emits metadata for
// compile unit, subprogram and file.
int main() {
diff --git a/test/CodeGen/debug-info-global-constant.c b/test/CodeGen/debug-info-global-constant.c
index 8cb7f44ff3f0..7da33aedbb51 100644
--- a/test/CodeGen/debug-info-global-constant.c
+++ b/test/CodeGen/debug-info-global-constant.c
@@ -7,7 +7,7 @@
// CHECK: @i = internal constant i32 1, align 4, !dbg ![[I:[0-9]+]]
// CHECK: ![[I]] = !DIGlobalVariableExpression(var: ![[VAR:.*]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
// CHECK: ![[VAR]] = distinct !DIGlobalVariable(name: "i",
-// CHECK: !DICompileUnit({{.*}}globals: ![[GLOBALS:[0-9]+]])
+// CHECK: !DICompileUnit({{.*}}globals: ![[GLOBALS:[0-9]+]]
// CHECK: ![[GLOBALS]] = !{![[I]]}
static const int i = 1;
diff --git a/test/CodeGen/debug-info-line.c b/test/CodeGen/debug-info-line.c
index 24981b54b7e9..39595d148c12 100644
--- a/test/CodeGen/debug-info-line.c
+++ b/test/CodeGen/debug-info-line.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -w -debug-info-kind=line-directives-only -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s
int f1(int a, int b) {
// CHECK: icmp {{.*}}, !dbg [[DBG_F1:!.*]]
diff --git a/test/CodeGen/debug-info-macro.c b/test/CodeGen/debug-info-macro.c
index 889c7ffdbac3..6294d43753f0 100644
--- a/test/CodeGen/debug-info-macro.c
+++ b/test/CodeGen/debug-info-macro.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=line-tables-only -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/Inputs/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,NO_PCH %s
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=line-directives-only -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/Inputs/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,NO_PCH %s
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/Inputs/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,NO_PCH %s
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/Inputs/debug-info-macro.h -UC1 | FileCheck -check-prefixes=CHECK,NO_PCH %s
// RUN: %clang_cc1 -emit-llvm -debug-info-macro %s -o - "-DC1(x)=( x + 5 )" -DA -include %S/Inputs/debug-info-macro.h -UC1 | FileCheck -check-prefixes=NO_MACRO %s
@@ -23,7 +24,7 @@
// NO_MACRO-NOT: DIMacro
// NO_MACRO-NOT: DIMacroFile
-// CHECK: !DICompileUnit({{.*}} macros: [[Macros:![0-9]+]])
+// CHECK: !DICompileUnit({{.*}} macros: [[Macros:![0-9]+]]
// CHECK: [[EmptyMD:![0-9]+]] = !{}
// NO_PCH: [[Macros]] = !{[[MainMacroFile:![0-9]+]], [[BuiltinMacro:![0-9]+]], {{.*}}, [[DefineC1:![0-9]+]], [[DefineA:![0-9]+]], [[UndefC1:![0-9]+]]}
diff --git a/test/CodeGen/debug-info-names.c b/test/CodeGen/debug-info-names.c
new file mode 100644
index 000000000000..bcfc99860988
--- /dev/null
+++ b/test/CodeGen/debug-info-names.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - -gpubnames | FileCheck --check-prefix=DEFAULT %s
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - -ggnu-pubnames | FileCheck --check-prefix=GNU %s
+
+// CHECK: !DICompileUnit({{.*}}, nameTableKind: None
+// DEFAULT-NOT: !DICompileUnit({{.*}}, nameTableKind:
+// GNU: !DICompileUnit({{.*}}, nameTableKind: GNU
+
+void f1() {
+}
diff --git a/test/CodeGen/debug-info-ranges-base-address.c b/test/CodeGen/debug-info-ranges-base-address.c
new file mode 100644
index 000000000000..dee7cc5f898d
--- /dev/null
+++ b/test/CodeGen/debug-info-ranges-base-address.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck --check-prefix=NORNGBSE %s
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - -fdebug-ranges-base-address | FileCheck --check-prefix=RNGBSE %s
+
+// NORNGBSE-NOT: rangesBaseAddress
+// RNGBSE: !DICompileUnit({{.*}}, rangesBaseAddress: true
+
+void f1() {
+}
+
diff --git a/test/CodeGen/debug-info-scope-file.c b/test/CodeGen/debug-info-scope-file.c
index 94123bbc4935..a5af59506592 100644
--- a/test/CodeGen/debug-info-scope-file.c
+++ b/test/CodeGen/debug-info-scope-file.c
@@ -5,9 +5,9 @@
// CHECK: ret void, !dbg [[F1_LINE:![0-9]*]]
// CHECK: ret void, !dbg [[F2_LINE:![0-9]*]]
-// CHECK: [[F1:![0-9]*]] = distinct !DISubprogram(name: "f1",{{.*}} isDefinition: true
+// CHECK: [[F1:![0-9]*]] = distinct !DISubprogram(name: "f1",{{.*}} DISPFlagDefinition
// CHECK: [[F1_LINE]] = !DILocation({{.*}}, scope: [[F1]])
-// CHECK: [[F2:![0-9]*]] = distinct !DISubprogram(name: "f2",{{.*}} isDefinition: true
+// CHECK: [[F2:![0-9]*]] = distinct !DISubprogram(name: "f2",{{.*}} DISPFlagDefinition
// CHECK: [[F2_LINE]] = !DILocation({{.*}}, scope: [[F2]])
void f1() {
diff --git a/test/CodeGen/debug-info-scope.c b/test/CodeGen/debug-info-scope.c
index a25f1177a911..0c12c4d60464 100644
--- a/test/CodeGen/debug-info-scope.c
+++ b/test/CodeGen/debug-info-scope.c
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -dwarf-version=4 -debug-info-kind=limited -disable-llvm-passes -emit-llvm < %s | FileCheck %s
// RUN: %clang_cc1 -dwarf-version=4 -debug-info-kind=line-tables-only -disable-llvm-passes -emit-llvm < %s | FileCheck --check-prefix=GMLT %s
+// RUN: %clang_cc1 -dwarf-version=4 -debug-info-kind=line-directives-only -disable-llvm-passes -emit-llvm < %s | FileCheck --check-prefix=GMLT %s
// Two variables with same name in separate scope.
// Radar 8330217.
int main() {
diff --git a/test/CodeGen/debug-info-vla.c b/test/CodeGen/debug-info-vla.c
index 8bd6a6d0acbe..22b3930dfc88 100644
--- a/test/CodeGen/debug-info-vla.c
+++ b/test/CodeGen/debug-info-vla.c
@@ -2,9 +2,9 @@
void testVLAwithSize(int s)
{
-// CHECK-DAG: dbg.declare({{.*}} %__vla_expr, metadata ![[VLAEXPR:[0-9]+]]
+// CHECK-DAG: dbg.declare({{.*}} %__vla_expr0, metadata ![[VLAEXPR:[0-9]+]]
// CHECK-DAG: dbg.declare({{.*}} %vla, metadata ![[VAR:[0-9]+]]
-// CHECK-DAG: ![[VLAEXPR]] = !DILocalVariable(name: "__vla_expr", {{.*}} flags: DIFlagArtificial
+// CHECK-DAG: ![[VLAEXPR]] = !DILocalVariable(name: "__vla_expr0", {{.*}} flags: DIFlagArtificial
// CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "vla",{{.*}} line: [[@LINE+2]]
// CHECK-DAG: !DISubrange(count: ![[VLAEXPR]])
int vla[s];
diff --git a/test/CodeGen/debug-nvptx.c b/test/CodeGen/debug-nvptx.c
new file mode 100644
index 000000000000..ceff30082960
--- /dev/null
+++ b/test/CodeGen/debug-nvptx.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple nvptx-unknown-unknown -S -o - -debug-info-kind=limited %s -emit-llvm | FileCheck %s
+
+// CHECK: DICompileUnit({{.*}}, nameTableKind: None)
+
+void f1(void) {
+}
diff --git a/test/CodeGen/debug-prefix-map.c b/test/CodeGen/debug-prefix-map.c
index dfb57bbe2e4b..f755ba47a291 100644
--- a/test/CodeGen/debug-prefix-map.c
+++ b/test/CodeGen/debug-prefix-map.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/var/empty %s -emit-llvm -o - | FileCheck %s -check-prefix CHECK-NO-MAIN-FILE-NAME
-// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/var=empty %s -emit-llvm -o - | FileCheck %s -check-prefix CHECK-EVIL
-// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/var/empty %s -emit-llvm -o - -main-file-name debug-prefix-map.c | FileCheck %s
-// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/var/empty %s -emit-llvm -o - -fdebug-compilation-dir %p | FileCheck %s -check-prefix CHECK-COMPILATION-DIR
+// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/UNLIKELY_PATH/empty %s -emit-llvm -o - | FileCheck %s -check-prefix CHECK-NO-MAIN-FILE-NAME
+// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/UNLIKELY_PATH=empty %s -emit-llvm -o - | FileCheck %s -check-prefix CHECK-EVIL
+// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/UNLIKELY_PATH/empty %s -emit-llvm -o - -main-file-name debug-prefix-map.c | FileCheck %s
+// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=/UNLIKELY_PATH/empty %s -emit-llvm -o - -fdebug-compilation-dir %p | FileCheck %s -check-prefix CHECK-COMPILATION-DIR
#include "Inputs/stdio.h"
@@ -16,19 +16,25 @@ void test_rewrite_includes() {
vprintf("string", argp);
}
-// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/var/empty{{/|\\5C}}<stdin>"
-// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/var/empty{{[/\\]}}{{.*}}"
-// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/var/empty{{[/\\]}}Inputs/stdio.h"
+// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/UNLIKELY_PATH/empty{{/|\\5C}}<stdin>"
+// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/UNLIKELY_PATH/empty{{[/\\]}}{{.*}}",
+// On POSIX systems "Dir" should actually be empty, but on Windows we
+// can't recognize "/UNLIKELY_PATH" as being an absolute path.
+// CHECK-NO-MAIN-FILE-NAME-SAME: directory: "{{()|(.*:.*)}}")
+// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "/UNLIKELY_PATH/empty{{[/\\]}}Inputs/stdio.h",
+// CHECK-NO-MAIN-FILE-NAME-SAME: directory: "{{()|(.*:.*)}}")
// CHECK-NO-MAIN-FILE-NAME-NOT: !DIFile(filename:
-// CHECK-EVIL: !DIFile(filename: "/var=empty{{[/\\]}}{{.*}}"
-// CHECK-EVIL: !DIFile(filename: "/var=empty{{[/\\]}}Inputs/stdio.h"
+// CHECK-EVIL: !DIFile(filename: "/UNLIKELY_PATH=empty{{[/\\]}}{{.*}}"
+// CHECK-EVIL: !DIFile(filename: "/UNLIKELY_PATH=empty{{[/\\]}}{{.*}}Inputs/stdio.h",
+// CHECK-EVIL-SAME: directory: "{{()|(.*:.*)}}")
// CHECK-EVIL-NOT: !DIFile(filename:
-// CHECK: !DIFile(filename: "/var/empty{{[/\\]}}{{.*}}"
-// CHECK: !DIFile(filename: "/var/empty{{[/\\]}}Inputs/stdio.h"
+// CHECK: !DIFile(filename: "/UNLIKELY_PATH/empty{{[/\\]}}{{.*}}"
+// CHECK: !DIFile(filename: "/UNLIKELY_PATH/empty{{[/\\]}}{{.*}}Inputs/stdio.h",
+// CHECK-SAME: directory: "{{()|(.*:.*)}}")
// CHECK-NOT: !DIFile(filename:
-// CHECK-COMPILATION-DIR: !DIFile(filename: "/var/empty{{[/\\]}}{{.*}}", directory: "/var/empty")
-// CHECK-COMPILATION-DIR: !DIFile(filename: "/var/empty{{[/\\]}}Inputs/stdio.h", directory: "/var/empty")
+// CHECK-COMPILATION-DIR: !DIFile(filename: "{{.*}}", directory: "/UNLIKELY_PATH/empty")
+// CHECK-COMPILATION-DIR: !DIFile(filename: "{{.*}}Inputs/stdio.h", directory: "/UNLIKELY_PATH/empty")
// CHECK-COMPILATION-DIR-NOT: !DIFile(filename:
diff --git a/test/CodeGen/decl.c b/test/CodeGen/decl.c
index d62629c7fb5c..22c2d034ad61 100644
--- a/test/CodeGen/decl.c
+++ b/test/CodeGen/decl.c
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -w -fmerge-all-constants -emit-llvm < %s | FileCheck %s
// CHECK: @test1.x = internal constant [12 x i32] [i32 1
-// CHECK: @test2.x = private unnamed_addr constant [13 x i32] [i32 1,
+// CHECK: @__const.test2.x = private unnamed_addr constant [13 x i32] [i32 1,
// CHECK: @test5w = {{(dso_local )?}}global { i32, [4 x i8] } { i32 2, [4 x i8] undef }
// CHECK: @test5y = {{(dso_local )?}}global { double } { double 7.300000e+0{{[0]*}}1 }
-// CHECK: @test6.x = private unnamed_addr constant %struct.SelectDest { i8 1, i8 2, i32 3, i32 0 }
+// CHECK: @__const.test6.x = private unnamed_addr constant %struct.SelectDest { i8 1, i8 2, i32 3, i32 0 }
// CHECK: @test7 = {{(dso_local )?}}global [2 x %struct.test7s] [%struct.test7s { i32 1, i32 2 }, %struct.test7s { i32 4, i32 0 }]
diff --git a/test/CodeGen/default-function-attr.c b/test/CodeGen/default-function-attr.c
new file mode 100644
index 000000000000..1c186e8e55b9
--- /dev/null
+++ b/test/CodeGen/default-function-attr.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -default-function-attr foo=bar -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: define void @foo() #[[X:[0-9]+]]
+void foo() {}
+
+// CHECK: attributes #[[X]] = {{.*}} "foo"="bar"
diff --git a/test/CodeGen/designated-initializers.c b/test/CodeGen/designated-initializers.c
index 74532c8fa5b4..b29799dace20 100644
--- a/test/CodeGen/designated-initializers.c
+++ b/test/CodeGen/designated-initializers.c
@@ -142,6 +142,18 @@ union_16644_t union_16644_instance_4[2] =
// CHECK: @lab = global { [4 x i8], i32 } { [4 x i8] undef, i32 123 }
struct leading_anon_bitfield { int : 32; int n; } lab = { .n = 123 };
+// rdar://45691981
+struct Base {
+ struct {
+ int A;
+ };
+};
+struct Derived {
+ struct Base B;
+};
+struct Derived D = {{}, .B.A = 42};
+// CHECK: @D = global %struct.Derived { %struct.Base { %struct.anon.4 { i32 42 } } }, align 4
+
void test1(int argc, char **argv)
{
// CHECK: internal global %struct.foo { i8* null, i32 1024 }
@@ -149,7 +161,7 @@ void test1(int argc, char **argv)
.b = 1024,
};
- // CHECK: bitcast %union.anon.4* %u2
+ // CHECK: bitcast %union.anon.5* %u2
// CHECK: call void @llvm.memset
union { int i; float f; } u2 = { };
diff --git a/test/CodeGen/dllimport.c b/test/CodeGen/dllimport.c
index 61d695705261..c3fd0770ee83 100644
--- a/test/CodeGen/dllimport.c
+++ b/test/CodeGen/dllimport.c
@@ -39,7 +39,8 @@ USEVAR(GlobalRedecl2)
// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
-// CHECK: @GlobalRedecl3 = external dso_local global i32
+// MS: @GlobalRedecl3 = external dso_local global i32
+// GNU: @GlobalRedecl3 = external global i32
__declspec(dllimport) extern int GlobalRedecl3;
extern int GlobalRedecl3; // dllimport ignored
USEVAR(GlobalRedecl3)
diff --git a/test/CodeGen/dso-local-executable.c b/test/CodeGen/dso-local-executable.c
index 6e434a67effb..36fd4d0d0396 100644
--- a/test/CodeGen/dso-local-executable.c
+++ b/test/CodeGen/dso-local-executable.c
@@ -9,6 +9,17 @@
// COFF-DAG: @import_var = external dllimport global i32
// COFF-DAG: declare dllimport void @import_func()
+// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=MINGW %s
+// MINGW-DAG: @bar = external global i32
+// MINGW-DAG: @weak_bar = extern_weak global i32
+// MINGW-DAG: declare dso_local void @foo()
+// MINGW-DAG: @baz = dso_local global i32 42
+// MINGW-DAG: define dso_local i32* @zed()
+// MINGW-DAG: @thread_var = external dso_local thread_local global i32
+// MINGW-DAG: @local_thread_var = dso_local thread_local global i32 42
+// MINGW-DAG: @import_var = external dllimport global i32
+// MINGW-DAG: declare dllimport void @import_func()
+
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=STATIC %s
// STATIC-DAG: @bar = external dso_local global i32
// STATIC-DAG: @weak_bar = extern_weak dso_local global i32
diff --git a/test/CodeGen/dump-struct-builtin.c b/test/CodeGen/dump-struct-builtin.c
index cd8540960205..929c5f71131b 100644
--- a/test/CodeGen/dump-struct-builtin.c
+++ b/test/CodeGen/dump-struct-builtin.c
@@ -3,55 +3,55 @@
#include "Inputs/stdio.h"
#include <stdint.h>
-// CHECK: @unit1.a = private unnamed_addr constant %struct.U1A { i16 12 }, align 2
+// CHECK: @__const.unit1.a = private unnamed_addr constant %struct.U1A { i16 12 }, align 2
// CHECK-NEXT: [[STRUCT_STR_U1:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U1A {\0A\00"
// CHECK-NEXT: [[FIELD_U1:@[0-9]+]] = private unnamed_addr constant [11 x i8] c"short a : \00"
// CHECK-NEXT: [[FORMAT_U1:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%hd\0A\00"
// CHECK-NEXT: [[END_STRUCT_U1:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit2.a = private unnamed_addr constant %struct.U2A { i16 12 }, align 2
+// CHECK: @__const.unit2.a = private unnamed_addr constant %struct.U2A { i16 12 }, align 2
// CHECK-NEXT: [[STRUCT_STR_U2:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U2A {\0A\00"
// CHECK-NEXT: [[FIELD_U2:@[0-9]+]] = private unnamed_addr constant [20 x i8] c"unsigned short a : \00"
// CHECK-NEXT: [[FORMAT_U2:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%hu\0A\00"
// CHECK-NEXT: [[END_STRUCT_U2:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit3.a = private unnamed_addr constant %struct.U3A { i32 12 }, align 4
+// CHECK: @__const.unit3.a = private unnamed_addr constant %struct.U3A { i32 12 }, align 4
// CHECK-NEXT: [[STRUCT_STR_U3:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U3A {\0A\00"
// CHECK-NEXT: [[FIELD_U3:@[0-9]+]] = private unnamed_addr constant [9 x i8] c"int a : \00"
// CHECK-NEXT: [[FORMAT_U3:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%d\0A\00"
// CHECK-NEXT: [[END_STRUCT_U3:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit4.a = private unnamed_addr constant %struct.U4A { i32 12 }, align 4
+// CHECK: @__const.unit4.a = private unnamed_addr constant %struct.U4A { i32 12 }, align 4
// CHECK-NEXT: [[STRUCT_STR_U4:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U4A {\0A\00"
// CHECK-NEXT: [[FIELD_U4:@[0-9]+]] = private unnamed_addr constant [18 x i8] c"unsigned int a : \00"
// CHECK-NEXT: [[FORMAT_U4:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%u\0A\00"
// CHECK-NEXT: [[END_STRUCT_U4:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit5.a = private unnamed_addr constant %struct.U5A { i64 12 }, align 8
+// CHECK: @__const.unit5.a = private unnamed_addr constant %struct.U5A { i64 12 }, align 8
// CHECK-NEXT: [[STRUCT_STR_U5:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U5A {\0A\00"
// CHECK-NEXT: [[FIELD_U5:@[0-9]+]] = private unnamed_addr constant [10 x i8] c"long a : \00"
// CHECK-NEXT: [[FORMAT_U5:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%ld\0A\00"
// CHECK-NEXT: [[END_STRUCT_U5:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit6.a = private unnamed_addr constant %struct.U6A { i64 12 }, align 8
+// CHECK: @__const.unit6.a = private unnamed_addr constant %struct.U6A { i64 12 }, align 8
// CHECK-NEXT: [[STRUCT_STR_U6:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U6A {\0A\00"
// CHECK-NEXT: [[FIELD_U6:@[0-9]+]] = private unnamed_addr constant [19 x i8] c"unsigned long a : \00"
// CHECK-NEXT: [[FORMAT_U6:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%lu\0A\00"
// CHECK-NEXT: [[END_STRUCT_U6:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit7.a = private unnamed_addr constant %struct.U7A { i64 12 }, align 8
+// CHECK: @__const.unit7.a = private unnamed_addr constant %struct.U7A { i64 12 }, align 8
// CHECK-NEXT: [[STRUCT_STR_U7:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U7A {\0A\00"
// CHECK-NEXT: [[FIELD_U7:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"long long a : \00"
// CHECK-NEXT: [[FORMAT_U7:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%lld\0A\00"
// CHECK-NEXT: [[END_STRUCT_U7:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit8.a = private unnamed_addr constant %struct.U8A { i64 12 }, align 8
+// CHECK: @__const.unit8.a = private unnamed_addr constant %struct.U8A { i64 12 }, align 8
// CHECK-NEXT: [[STRUCT_STR_U8:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U8A {\0A\00"
// CHECK-NEXT: [[FIELD_U8:@[0-9]+]] = private unnamed_addr constant [24 x i8] c"unsigned long long a : \00"
// CHECK-NEXT: [[FORMAT_U8:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%llu\0A\00"
// CHECK-NEXT: [[END_STRUCT_U8:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit9.a = private unnamed_addr constant %struct.U9A { i8 97 }, align 1
+// CHECK: @__const.unit9.a = private unnamed_addr constant %struct.U9A { i8 97 }, align 1
// CHECK-NEXT: [[STRUCT_STR_U9:@[0-9]+]] = private unnamed_addr constant [14 x i8] c"struct U9A {\0A\00"
// CHECK-NEXT: [[FIELD_U9:@[0-9]+]] = private unnamed_addr constant [10 x i8] c"char a : \00"
// CHECK-NEXT: [[FORMAT_U9:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%c\0A\00"
@@ -59,55 +59,55 @@
// CHECK: @.str = private unnamed_addr constant [4 x i8] c"LSE\00", align 1
-// CHECK: @unit10.a = private unnamed_addr constant %struct.U10A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
+// CHECK: @__const.unit10.a = private unnamed_addr constant %struct.U10A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
// CHECK-NEXT: [[STRUCT_STR_U10:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U10A {\0A\00"
// CHECK-NEXT: [[FIELD_U10:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"char * a : \00"
// CHECK-NEXT: [[FORMAT_U10:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%s\0A\00"
// CHECK-NEXT: [[END_STRUCT_U10:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit11.a = private unnamed_addr constant %struct.U11A { i8* inttoptr (i64 305419896 to i8*) }, align 8
+// CHECK: @__const.unit11.a = private unnamed_addr constant %struct.U11A { i8* inttoptr (i64 305419896 to i8*) }, align 8
// CHECK-NEXT: [[STRUCT_STR_U11:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U11A {\0A\00"
// CHECK-NEXT: [[FIELD_U11:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"void * a : \00"
// CHECK-NEXT: [[FORMAT_U11:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%p\0A\00"
// CHECK-NEXT: [[END_STRUCT_U11:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit12.a = private unnamed_addr constant %struct.U12A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
+// CHECK: @__const.unit12.a = private unnamed_addr constant %struct.U12A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
// CHECK-NEXT: [[STRUCT_STR_U12:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U12A {\0A\00"
// CHECK-NEXT: [[FIELD_U12:@[0-9]+]] = private unnamed_addr constant [18 x i8] c"const char * a : \00"
// CHECK-NEXT: [[FORMAT_U12:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%s\0A\00"
// CHECK-NEXT: [[END_STRUCT_U12:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit13.a = private unnamed_addr constant %struct.U13A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
+// CHECK: @__const.unit13.a = private unnamed_addr constant %struct.U13A { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0) }, align 8
// CHECK-NEXT: [[STRUCT_STR_U13:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U13A {\0A\00"
// CHECK-NEXT: [[FIELD_U13:@[0-9]+]] = private unnamed_addr constant [20 x i8] c"const charstar a : \00"
// CHECK-NEXT: [[FORMAT_U13:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%s\0A\00"
// CHECK-NEXT: [[END_STRUCT_U13:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit14.a = private unnamed_addr constant %struct.U14A { double 0x3FF1F9ACFFA7EB6C }, align 8
+// CHECK: @__const.unit14.a = private unnamed_addr constant %struct.U14A { double 0x3FF1F9ACFFA7EB6C }, align 8
// CHECK-NEXT: [[STRUCT_STR_U14:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U14A {\0A\00"
// CHECK-NEXT: [[FIELD_U14:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"double a : \00"
// CHECK-NEXT: [[FORMAT_U14:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%f\0A\00"
// CHECK-NEXT: [[END_STRUCT_U14:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit15.a = private unnamed_addr constant %struct.U15A { [3 x i32] [i32 1, i32 2, i32 3] }, align 4
+// CHECK: @__const.unit15.a = private unnamed_addr constant %struct.U15A { [3 x i32] [i32 1, i32 2, i32 3] }, align 4
// CHECK-NEXT: [[STRUCT_STR_U15:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U15A {\0A\00"
// CHECK-NEXT: [[FIELD_U15:@[0-9]+]] = private unnamed_addr constant [13 x i8] c"int [3] a : \00"
// CHECK-NEXT: [[FORMAT_U15:@[0-9]+]] = private unnamed_addr constant [4 x i8] c"%p\0A\00"
// CHECK-NEXT: [[END_STRUCT_U15:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit16.a = private unnamed_addr constant %struct.U16A { i8 12 }, align 1
+// CHECK: @__const.unit16.a = private unnamed_addr constant %struct.U16A { i8 12 }, align 1
// CHECK-NEXT: [[STRUCT_STR_U16:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U16A {\0A\00"
// CHECK-NEXT: [[FIELD_U16:@[0-9]+]] = private unnamed_addr constant [13 x i8] c"uint8_t a : \00"
// CHECK-NEXT: [[FORMAT_U16:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%hhu\0A\00"
// CHECK-NEXT: [[END_STRUCT_U16:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit17.a = private unnamed_addr constant %struct.U17A { i8 12 }, align 1
+// CHECK: @__const.unit17.a = private unnamed_addr constant %struct.U17A { i8 12 }, align 1
// CHECK-NEXT: [[STRUCT_STR_U17:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U17A {\0A\00"
// CHECK-NEXT: [[FIELD_U17:@[0-9]+]] = private unnamed_addr constant [12 x i8] c"int8_t a : \00"
// CHECK-NEXT: [[FORMAT_U17:@[0-9]+]] = private unnamed_addr constant [6 x i8] c"%hhd\0A\00"
// CHECK-NEXT: [[END_STRUCT_U17:@[0-9]+]] = private unnamed_addr constant [3 x i8] c"}\0A\00"
-// CHECK: @unit18.a = private unnamed_addr constant %struct.U18A { x86_fp80 0xK3FFF8FCD67FD3F5B6000 }, align 16
+// CHECK: @__const.unit18.a = private unnamed_addr constant %struct.U18A { x86_fp80 0xK3FFF8FCD67FD3F5B6000 }, align 16
// CHECK-NEXT: [[STRUCT_STR_U18:@[0-9]+]] = private unnamed_addr constant [15 x i8] c"struct U18A {\0A\00"
// CHECK-NEXT: [[FIELD_U18:@[0-9]+]] = private unnamed_addr constant [17 x i8] c"long double a : \00"
// CHECK-NEXT: [[FORMAT_U18:@[0-9]+]] = private unnamed_addr constant [5 x i8] c"%Lf\0A\00"
diff --git a/test/CodeGen/dwarf-version.c b/test/CodeGen/dwarf-version.c
index cee0f031e130..39bcbc209037 100644
--- a/test/CodeGen/dwarf-version.c
+++ b/test/CodeGen/dwarf-version.c
@@ -14,14 +14,29 @@
// RUN: %clang -target powerpc-unknown-openbsd -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2
// RUN: %clang -target powerpc-unknown-freebsd -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2
// RUN: %clang -target i386-pc-solaris -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2
-//
-// Test what -gcodeview and -gdwarf do on Windows.
-// RUN: %clang -target i686-pc-windows-msvc -gcodeview -S -emit-llvm -o - %s | FileCheck %s --check-prefix=NODWARF --check-prefix=CODEVIEW
-// RUN: %clang -target i686-pc-windows-msvc -gdwarf -gcodeview -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER4 --check-prefix=CODEVIEW
+
+// Check which debug info formats we use on Windows. By default, in an MSVC
+// environment, we should use codeview. You can enable dwarf, which implicitly
+// disables codeview, of you can explicitly ask for both if you don't know how
+// the app will be debugged.
+// Default is codeview.
+// RUN: %clang -target i686-pc-windows-msvc -g -S -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefixes=NODWARF,CODEVIEW
+// Explicitly request codeview.
+// RUN: %clang -target i686-pc-windows-msvc -gcodeview -S -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefixes=NODWARF,CODEVIEW
+// Explicitly request DWARF.
+// RUN: %clang -target i686-pc-windows-msvc -gdwarf -S -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefixes=VER4,NOCODEVIEW
+// Explicitly request both.
+// RUN: %clang -target i686-pc-windows-msvc -gdwarf -gcodeview -S -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefixes=VER4,CODEVIEW
int main (void) {
return 0;
}
+// NOCODEVIEW-NOT: !"CodeView"
+
// VER2: !{i32 2, !"Dwarf Version", i32 2}
// VER3: !{i32 2, !"Dwarf Version", i32 3}
// VER4: !{i32 2, !"Dwarf Version", i32 4}
@@ -29,4 +44,5 @@ int main (void) {
// NODWARF-NOT: !"Dwarf Version"
// CODEVIEW: !{i32 2, !"CodeView", i32 1}
+// NOCODEVIEW-NOT: !"CodeView"
// NODWARF-NOT: !"Dwarf Version"
diff --git a/test/CodeGen/exceptions-seh-nested-finally.c b/test/CodeGen/exceptions-seh-nested-finally.c
new file mode 100644
index 000000000000..7385d18f0cd8
--- /dev/null
+++ b/test/CodeGen/exceptions-seh-nested-finally.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 %s -triple aarch64-windows -fms-extensions -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+// Check that the first finally block passes the enclosing function's frame
+// pointer to the second finally block, instead of generating it via localaddr.
+
+// CHECK-LABEL: define internal void @"?fin$0@0@main@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
+// CHECK: call void @"?fin$1@0@main@@"({{i8( zeroext)?}} 0, i8* %frame_pointer)
+int
+main() {
+ int Check = 0;
+ __try {
+ Check = 3;
+ } __finally {
+ __try {
+ Check += 2;
+ } __finally {
+ Check += 4;
+ }
+ }
+ return Check;
+}
diff --git a/test/CodeGen/exceptions-seh.c b/test/CodeGen/exceptions-seh.c
index 1e3e2236ac6d..8c952a04bec7 100644
--- a/test/CodeGen/exceptions-seh.c
+++ b/test/CodeGen/exceptions-seh.c
@@ -52,7 +52,7 @@ int safe_div(int numerator, int denominator, int *res) {
//
// X86-LABEL: define internal i32 @"?filt$0@0@safe_div@@"()
// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
-// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]])
+// X86: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]])
// X86: call i8* @llvm.localrecover(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[fp]], i32 0)
// X86: load i8*, i8**
// X86: load i32*, i32**
@@ -95,16 +95,16 @@ int filter_expr_capture(void) {
// CHECK: ret i32 %[[rv]]
// X64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
-// X64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
+// X64: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
// X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
//
// ARM64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
-// ARM64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
+// ARM64: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
// ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
//
// X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"()
// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
-// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[ebp]])
+// X86: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[ebp]])
// X86: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
//
// CHECK: store i32 -1, i32* %{{.*}}
@@ -166,13 +166,13 @@ int nested_try(void) {
// CHECK: br label %[[inner_try_cont]]
//
// CHECK-LABEL: define internal i32 @"?filt$0@0@nested_try@@"({{.*}})
-// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
+// X86: call i8* @llvm.eh.recoverfp({{.*}})
// CHECK: load i32*, i32**
// CHECK: load i32, i32*
// CHECK: icmp eq i32 %{{.*}}, 456
//
// CHECK-LABEL: define internal i32 @"?filt$1@0@nested_try@@"({{.*}})
-// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
+// X86: call i8* @llvm.eh.recoverfp({{.*}})
// CHECK: load i32*, i32**
// CHECK: load i32, i32*
// CHECK: icmp eq i32 %{{.*}}, 123
diff --git a/test/CodeGen/exceptions.c b/test/CodeGen/exceptions.c
index 039ec84d2e53..57b869196ba9 100644
--- a/test/CodeGen/exceptions.c
+++ b/test/CodeGen/exceptions.c
@@ -23,6 +23,7 @@ void test1() {
void test2_helper();
void test2() {
__block int x = 10;
+ ^{ (void)x; };
test2_helper(5, 6, 7);
}
void test2_helper(int x, int y) {
diff --git a/test/CodeGen/global-blocks-win32.c b/test/CodeGen/global-blocks-win32.c
new file mode 100644
index 000000000000..7a66c924b420
--- /dev/null
+++ b/test/CodeGen/global-blocks-win32.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fblocks -triple i386-pc-windows-msvc %s -emit-llvm -o - -fblocks | FileCheck %s
+
+
+int (^x)(void) = ^() { return 21; };
+
+
+// Check that the block literal is emitted with a null isa pointer
+// CHECK: @__block_literal_global = internal global { i8**, i32, i32, i8*, %struct.__block_descriptor* } { i8** null,
+
+// Check that _NSConcreteGlobalBlock has the correct dllimport specifier.
+// CHECK: @_NSConcreteGlobalBlock = external dllimport global i8*
+// Check that we create an initialiser pointer in the correct section (early library initialisation).
+// CHECK: @.block_isa_init_ptr = internal constant void ()* @.block_isa_init, section ".CRT$XCLa"
+
+// Check that we emit an initialiser for it.
+// CHECK: define internal void @.block_isa_init() {
+// CHECK: store i8** @_NSConcreteGlobalBlock, i8*** getelementptr inbounds ({ i8**, i32, i32, i8*, %struct.__block_descriptor* }, { i8**, i32, i32, i8*, %struct.__block_descriptor* }* @__block_literal_global, i32 0, i32 0), align 4
+
diff --git a/test/CodeGen/indirect-tls-seg-refs.c b/test/CodeGen/indirect-tls-seg-refs.c
new file mode 100644
index 000000000000..de6f3cda7d3c
--- /dev/null
+++ b/test/CodeGen/indirect-tls-seg-refs.c
@@ -0,0 +1,10 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-unknown-linux -o - -mno-tls-direct-seg-refs | FileCheck %s -check-prefix=NO-TLSDIRECT
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-unknown-linux -o - | FileCheck %s -check-prefix=TLSDIRECT
+
+// NO-TLSDIRECT: attributes #{{[0-9]+}} = {{{.*}} "indirect-tls-seg-refs"
+// TLSDIRECT-NOT: attributes #{{[0-9]+}} = {{{.*}} "indirect-tls-seg-refs"
+
+void test1() {
+}
diff --git a/test/CodeGen/inline-asm-matching-ppc-vsx.c b/test/CodeGen/inline-asm-matching-ppc-vsx.c
new file mode 100644
index 000000000000..a4fabd688175
--- /dev/null
+++ b/test/CodeGen/inline-asm-matching-ppc-vsx.c
@@ -0,0 +1,20 @@
+// REQUIRES: powerpc-registered-target
+
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-feature +vsx \
+// RUN: -target-cpu pwr9 -emit-llvm %s -o - | FileCheck %s
+
+// This case is to test VSX register support in the clobbers list for inline asm.
+void testVSX (void) {
+ unsigned int a = 0;
+ unsigned int *dbell=&a;
+ int d;
+ __asm__ __volatile__ (
+ "lxvw4x %%vs32, 0, %2\n\t"
+ "stxvw4x %%vs32, 0, %1"
+ : "=m"(*(volatile unsigned int*)(dbell))
+ : "r" (dbell), "r" (&d)
+ : "vs32"
+ );
+}
+
+// CHECK: call void asm sideeffect "lxvw4x %vs32, 0, $2\0A\09stxvw4x %vs32, 0, $1", "=*m,r,r,~{vs32}"
diff --git a/test/CodeGen/keep-static-consts.cpp b/test/CodeGen/keep-static-consts.cpp
new file mode 100644
index 000000000000..d89f21cf65aa
--- /dev/null
+++ b/test/CodeGen/keep-static-consts.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fkeep-static-consts -emit-llvm %s -o - -triple=x86_64-unknown-linux-gnu | FileCheck %s
+
+// CHECK: @_ZL7srcvers = internal constant [4 x i8] c"xyz\00", align 1
+// CHECK: @_ZL8srcvers2 = internal constant [4 x i8] c"abc\00", align 1
+// CHECK: @_ZL1N = internal constant i32 2, align 4
+// CHECK: @llvm.used = appending global [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_ZL7srcvers, i32 0, i32 0), i8* bitcast (i32* @b to i8*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_ZL8srcvers2, i32 0, i32 0), i8* bitcast (i32* @_ZL1N to i8*)], section "llvm.metadata"
+
+static const char srcvers[] = "xyz";
+extern const int b = 1;
+const char srcvers2[] = "abc";
+constexpr int N = 2;
diff --git a/test/CodeGen/lifetime-debuginfo-1.c b/test/CodeGen/lifetime-debuginfo-1.c
index e2e45cb7f816..10fd2c21644d 100644
--- a/test/CodeGen/lifetime-debuginfo-1.c
+++ b/test/CodeGen/lifetime-debuginfo-1.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s
+// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-directives-only %s -o - | FileCheck %s
// Inserting lifetime markers should not affect debuginfo
diff --git a/test/CodeGen/lifetime-debuginfo-2.c b/test/CodeGen/lifetime-debuginfo-2.c
index 1d2fb5957697..a2e06519358f 100644
--- a/test/CodeGen/lifetime-debuginfo-2.c
+++ b/test/CodeGen/lifetime-debuginfo-2.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s
+// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-directives-only %s -o - | FileCheck %s
// Inserting lifetime markers should not affect debuginfo: lifetime.end is not
// a destructor, but instrumentation for the compiler. Ensure the debug info for
diff --git a/test/CodeGen/lto-newpm-pipeline.c b/test/CodeGen/lto-newpm-pipeline.c
index 137c46c964cc..57391161a6d6 100644
--- a/test/CodeGen/lto-newpm-pipeline.c
+++ b/test/CodeGen/lto-newpm-pipeline.c
@@ -27,12 +27,14 @@
// CHECK-FULL-O0: Starting llvm::Module pass manager run.
// CHECK-FULL-O0: Running pass: AlwaysInlinerPass
+// CHECK-FULL-O0-NEXT: Running pass: CanonicalizeAliasesPass
// CHECK-FULL-O0-NEXT: Running pass: NameAnonGlobalPass
// CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass
// CHECK-FULL-O0: Finished llvm::Module pass manager run.
// CHECK-THIN-O0: Starting llvm::Module pass manager run.
// CHECK-THIN-O0: Running pass: AlwaysInlinerPass
+// CHECK-THIN-O0-NEXT: Running pass: CanonicalizeAliasesPass
// CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass
// CHECK-THIN-O0-NEXT: Running pass: ThinLTOBitcodeWriterPass
// CHECK-THIN-O0: Finished llvm::Module pass manager run.
@@ -48,6 +50,7 @@
// LoopVectorizePass.
// CHECK-THIN-OPTIMIZED: Starting llvm::Function pass manager run.
// CHECK-THIN-OPTIMIZED-NOT: Running pass: LoopVectorizePass
+// CHECK-THIN-OPTIMIZED: Running pass: CanonicalizeAliasesPass
// CHECK-THIN-OPTIMIZED: Running pass: NameAnonGlobalPass
// CHECK-THIN-OPTIMIZED: Running pass: ThinLTOBitcodeWriterPass
diff --git a/test/CodeGen/lzcnt-builtins.c b/test/CodeGen/lzcnt-builtins.c
index b1414a3b56f2..9255207ffaef 100644
--- a/test/CodeGen/lzcnt-builtins.c
+++ b/test/CodeGen/lzcnt-builtins.c
@@ -5,30 +5,30 @@
unsigned short test__lzcnt16(unsigned short __X)
{
- // CHECK: @llvm.ctlz.i16
+ // CHECK: @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
return __lzcnt16(__X);
}
unsigned int test_lzcnt32(unsigned int __X)
{
- // CHECK: @llvm.ctlz.i32
+ // CHECK: @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
return __lzcnt32(__X);
}
unsigned long long test__lzcnt64(unsigned long long __X)
{
- // CHECK: @llvm.ctlz.i64
+ // CHECK: @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
return __lzcnt64(__X);
}
unsigned int test_lzcnt_u32(unsigned int __X)
{
- // CHECK: @llvm.ctlz.i32
+ // CHECK: @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
return _lzcnt_u32(__X);
}
unsigned long long test__lzcnt_u64(unsigned long long __X)
{
- // CHECK: @llvm.ctlz.i64
+ // CHECK: @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
return _lzcnt_u64(__X);
}
diff --git a/test/CodeGen/microsoft-no-common-align.c b/test/CodeGen/microsoft-no-common-align.c
new file mode 100644
index 000000000000..fc46946c00ed
--- /dev/null
+++ b/test/CodeGen/microsoft-no-common-align.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s
+typedef float TooLargeAlignment __attribute__((__vector_size__(64)));
+typedef float NormalAlignment __attribute__((__vector_size__(4)));
+
+TooLargeAlignment TooBig;
+// CHECK: @TooBig = dso_local global <16 x float> zeroinitializer, align 64
+NormalAlignment JustRight;
+// CHECK: @JustRight = common dso_local global <1 x float> zeroinitializer, align 4
diff --git a/test/CodeGen/mips-zero-sized-struct.c b/test/CodeGen/mips-zero-sized-struct.c
index 217bdb92c6f6..08ebf9df3e93 100644
--- a/test/CodeGen/mips-zero-sized-struct.c
+++ b/test/CodeGen/mips-zero-sized-struct.c
@@ -1,9 +1,23 @@
// RUN: %clang_cc1 -triple mips-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=O32 %s
// RUN: %clang_cc1 -triple mipsel-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=O32 %s
+// RUN: %clang_cc1 -triple mipsisa32r6-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=O32 %s
+// RUN: %clang_cc1 -triple mipsisa32r6el-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=O32 %s
// RUN: %clang_cc1 -triple mips64-unknown-linux-gnu -S -emit-llvm -o - %s -target-abi n32 | FileCheck -check-prefix=N32 %s
// RUN: %clang_cc1 -triple mips64el-unknown-linux-gnu -S -emit-llvm -o - %s -target-abi n32 | FileCheck -check-prefix=N32 %s
+// RUN: %clang_cc1 -triple mipsisa64r6-unknown-linux-gnu -S -emit-llvm -o - %s -target-abi n32 | FileCheck -check-prefix=N32 %s
+// RUN: %clang_cc1 -triple mipsisa64r6el-unknown-linux-gnu -S -emit-llvm -o - %s -target-abi n32 | FileCheck -check-prefix=N32 %s
+// RUN: %clang_cc1 -triple mips64-unknown-linux-gnuabin32 -S -emit-llvm -o - %s | FileCheck -check-prefix=N32 %s
+// RUN: %clang_cc1 -triple mips64el-unknown-linux-gnuabin32 -S -emit-llvm -o - %s | FileCheck -check-prefix=N32 %s
+// RUN: %clang_cc1 -triple mipsisa64r6-unknown-linux-gnuabin32 -S -emit-llvm -o - %s | FileCheck -check-prefix=N32 %s
+// RUN: %clang_cc1 -triple mipsisa64r6el-unknown-linux-gnuabin32 -S -emit-llvm -o - %s | FileCheck -check-prefix=N32 %s
// RUN: %clang_cc1 -triple mips64-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
// RUN: %clang_cc1 -triple mips64el-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
+// RUN: %clang_cc1 -triple mipsisa64r6-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
+// RUN: %clang_cc1 -triple mipsisa64r6el-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
+// RUN: %clang_cc1 -triple mips64-unknown-linux-gnuabi64 -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
+// RUN: %clang_cc1 -triple mips64el-unknown-linux-gnuabi64 -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
+// RUN: %clang_cc1 -triple mipsisa64r6-unknown-linux-gnuabi64 -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
+// RUN: %clang_cc1 -triple mipsisa64r6el-unknown-linux-gnuabi64 -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s
// O32: define void @fn28(%struct.T2* noalias sret %agg.result, i8 signext %arg0)
// N32: define void @fn28(i8 signext %arg0)
diff --git a/test/CodeGen/movbe-builtins.c b/test/CodeGen/movbe-builtins.c
new file mode 100644
index 000000000000..342f66391388
--- /dev/null
+++ b/test/CodeGen/movbe-builtins.c
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +movbe -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-X64
+// RUN: %clang_cc1 -ffreestanding %s -triple=i686-apple-darwin -target-feature +movbe -emit-llvm -o - | FileCheck %s
+
+
+#include <immintrin.h>
+
+short test_loadbe_i16(const short *P) {
+ // CHECK-LABEL: @test_loadbe_i16
+ // CHECK: [[LOAD:%.*]] = load i16, i16* %{{.*}}, align 1
+ // CHECK: call i16 @llvm.bswap.i16(i16 [[LOAD]])
+ return _loadbe_i16(P);
+}
+
+void test_storebe_i16(short *P, short D) {
+ // CHECK-LABEL: @test_storebe_i16
+ // CHECK: [[DATA:%.*]] = call i16 @llvm.bswap.i16(i16 %{{.*}})
+ // CHECK: store i16 [[DATA]], i16* %{{.*}}, align 1
+ _storebe_i16(P, D);
+}
+
+int test_loadbe_i32(const int *P) {
+ // CHECK-LABEL: @test_loadbe_i32
+ // CHECK: [[LOAD:%.*]] = load i32, i32* %{{.*}}, align 1
+ // CHECK: call i32 @llvm.bswap.i32(i32 [[LOAD]])
+ return _loadbe_i32(P);
+}
+
+void test_storebe_i32(int *P, int D) {
+ // CHECK-LABEL: @test_storebe_i32
+ // CHECK: [[DATA:%.*]] = call i32 @llvm.bswap.i32(i32 %{{.*}})
+ // CHECK: store i32 [[DATA]], i32* %{{.*}}, align 1
+ _storebe_i32(P, D);
+}
+
+#ifdef __x86_64__
+long long test_loadbe_i64(const long long *P) {
+ // CHECK-X64-LABEL: @test_loadbe_i64
+ // CHECK-X64: [[LOAD:%.*]] = load i64, i64* %{{.*}}, align 1
+ // CHECK-X64: call i64 @llvm.bswap.i64(i64 [[LOAD]])
+ return _loadbe_i64(P);
+}
+
+void test_storebe_i64(long long *P, long long D) {
+ // CHECK-X64-LABEL: @test_storebe_i64
+ // CHECK-X64: [[DATA:%.*]] = call i64 @llvm.bswap.i64(i64 %{{.*}})
+ // CHECK-X64: store i64 [[DATA]], i64* %{{.*}}, align 1
+ _storebe_i64(P, D);
+}
+#endif
diff --git a/test/CodeGen/ms-intrinsics-cpuid.c b/test/CodeGen/ms-intrinsics-cpuid.c
new file mode 100644
index 000000000000..e6666c86e68e
--- /dev/null
+++ b/test/CodeGen/ms-intrinsics-cpuid.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s
+
+// intrin.h needs size_t, but -ffreestanding prevents us from getting it from
+// stddef.h. Work around it with this typedef.
+typedef __SIZE_TYPE__ size_t;
+
+#include <intrin.h>
+
+void test__cpuid(int *info, int level) {
+ __cpuid(info, level);
+}
+// CHECK-LABEL: define {{.*}} @test__cpuid(i32* %{{.*}}, i32 %{{.*}})
+// CHECK: call { i32, i32, i32, i32 } asm "cpuid",
+// CHECK-SAME: "={ax},={bx},={cx},={dx},{ax},{cx},~{dirflag},~{fpsr},~{flags}"
+// CHECK-SAME: (i32 %{{.*}}, i32 0)
diff --git a/test/CodeGen/ms-intrinsics-other.c b/test/CodeGen/ms-intrinsics-other.c
index 65d767058462..adc8ac98e573 100644
--- a/test/CodeGen/ms-intrinsics-other.c
+++ b/test/CodeGen/ms-intrinsics-other.c
@@ -148,3 +148,51 @@ LONG test_InterlockedDecrement(LONG volatile *Addend) {
// CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1
// CHECK: ret i32 [[RESULT]]
// CHECK: }
+
+unsigned short test__lzcnt16(unsigned short x) {
+ return __lzcnt16(x);
+}
+// CHECK: i16 @test__lzcnt16
+// CHECK: [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
+// CHECK: ret i16 [[RESULT]]
+// CHECK: }
+
+unsigned int test__lzcnt(unsigned int x) {
+ return __lzcnt(x);
+}
+// CHECK: i32 @test__lzcnt
+// CHECK: [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
+// CHECK: ret i32 [[RESULT]]
+// CHECK: }
+
+unsigned __int64 test__lzcnt64(unsigned __int64 x) {
+ return __lzcnt64(x);
+}
+// CHECK: i64 @test__lzcnt64
+// CHECK: [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+// CHECK: ret i64 [[RESULT]]
+// CHECK: }
+
+unsigned short test__popcnt16(unsigned short x) {
+ return __popcnt16(x);
+}
+// CHECK: i16 @test__popcnt16
+// CHECK: [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctpop.i16(i16 %x)
+// CHECK: ret i16 [[RESULT]]
+// CHECK: }
+
+unsigned int test__popcnt(unsigned int x) {
+ return __popcnt(x);
+}
+// CHECK: i32 @test__popcnt
+// CHECK: [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctpop.i32(i32 %x)
+// CHECK: ret i32 [[RESULT]]
+// CHECK: }
+
+unsigned __int64 test__popcnt64(unsigned __int64 x) {
+ return __popcnt64(x);
+}
+// CHECK: i64 @test__popcnt64
+// CHECK: [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctpop.i64(i64 %x)
+// CHECK: ret i64 [[RESULT]]
+// CHECK: }
diff --git a/test/CodeGen/ms-intrinsics-rotations.c b/test/CodeGen/ms-intrinsics-rotations.c
index 735de6e41e68..30428b12aa33 100644
--- a/test/CodeGen/ms-intrinsics-rotations.c
+++ b/test/CodeGen/ms-intrinsics-rotations.c
@@ -30,66 +30,36 @@ unsigned char test_rotl8(unsigned char value, unsigned char shift) {
return _rotl8(value, shift);
}
// CHECK: i8 @test_rotl8
-// CHECK: [[LSHIFT:%[0-9]+]] = and i8 [[SHIFT:%[0-9]+]], 7
-// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE:%[0-9]+]], [[LSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i8 0, [[SHIFT]]
-// CHECK: [[RSHIFT:%[0-9]+]] = and i8 [[NEGATE]], 7
-// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE]], [[RSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i8 [[HIGH]], [[LOW]]
-// CHECK: ret i8 [[RESULT]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]])
+// CHECK: ret i8 [[R]]
unsigned short test_rotl16(unsigned short value, unsigned char shift) {
return _rotl16(value, shift);
}
// CHECK: i16 @test_rotl16
-// CHECK: [[LSHIFT:%[0-9]+]] = and i16 [[SHIFT:%[0-9]+]], 15
-// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE:%[0-9]+]], [[LSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i16 0, [[SHIFT]]
-// CHECK: [[RSHIFT:%[0-9]+]] = and i16 [[NEGATE]], 15
-// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE]], [[RSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i16 [[HIGH]], [[LOW]]
-// CHECK: ret i16 [[RESULT]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]])
+// CHECK: ret i16 [[R]]
unsigned int test_rotl(unsigned int value, int shift) {
return _rotl(value, shift);
}
// CHECK: i32 @test_rotl
-// CHECK: [[LSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
-// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[LSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
-// CHECK: [[RSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
-// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[RSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK: ret i32 [[RESULT]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+// CHECK: ret i32 [[R]]
unsigned LONG test_lrotl(unsigned LONG value, int shift) {
return _lrotl(value, shift);
}
// CHECK-32BIT-LONG: i32 @test_lrotl
-// CHECK-32BIT-LONG: [[LSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
-// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[LSHIFT]]
-// CHECK-32BIT-LONG: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
-// CHECK-32BIT-LONG: [[RSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
-// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[RSHIFT]]
-// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK-32BIT-LONG: ret i32 [[RESULT]]
-// CHECK-32BIT-LONG }
+// CHECK-32BIT-LONG: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+// CHECK-32BIT-LONG: ret i32 [[R]]
unsigned __int64 test_rotl64(unsigned __int64 value, int shift) {
return _rotl64(value, shift);
}
// CHECK: i64 @test_rotl64
-// CHECK: [[LSHIFT:%[0-9]+]] = and i64 [[SHIFT:%[0-9]+]], 63
-// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE:%[0-9]+]], [[LSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i64 0, [[SHIFT]]
-// CHECK: [[RSHIFT:%[0-9]+]] = and i64 [[NEGATE]], 63
-// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE]], [[RSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
-// CHECK: ret i64 [[RESULT]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i64 @llvm.fshl.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]])
+// CHECK: ret i64 [[R]]
// rotate right
@@ -97,61 +67,34 @@ unsigned char test_rotr8(unsigned char value, unsigned char shift) {
return _rotr8(value, shift);
}
// CHECK: i8 @test_rotr8
-// CHECK: [[RSHIFT:%[0-9]+]] = and i8 [[SHIFT:%[0-9]+]], 7
-// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE:%[0-9]+]], [[RSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i8 0, [[SHIFT]]
-// CHECK: [[LSHIFT:%[0-9]+]] = and i8 [[NEGATE]], 7
-// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE]], [[LSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i8 [[HIGH]], [[LOW]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]])
+// CHECK: ret i8 [[R]]
unsigned short test_rotr16(unsigned short value, unsigned char shift) {
return _rotr16(value, shift);
}
// CHECK: i16 @test_rotr16
-// CHECK: [[RSHIFT:%[0-9]+]] = and i16 [[SHIFT:%[0-9]+]], 15
-// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE:%[0-9]+]], [[RSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i16 0, [[SHIFT]]
-// CHECK: [[LSHIFT:%[0-9]+]] = and i16 [[NEGATE]], 15
-// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE]], [[LSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i16 [[HIGH]], [[LOW]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i16 @llvm.fshr.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]])
+// CHECK: ret i16 [[R]]
unsigned int test_rotr(unsigned int value, int shift) {
return _rotr(value, shift);
}
// CHECK: i32 @test_rotr
-// CHECK: [[RSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
-// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[RSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
-// CHECK: [[LSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
-// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[LSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK: ret i32 [[RESULT]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+// CHECK: ret i32 [[R]]
unsigned LONG test_lrotr(unsigned LONG value, int shift) {
return _lrotr(value, shift);
}
// CHECK-32BIT-LONG: i32 @test_lrotr
-// CHECK-32BIT-LONG: [[RSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31
-// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[RSHIFT]]
-// CHECK-32BIT-LONG: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]]
-// CHECK-32BIT-LONG: [[LSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31
-// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[LSHIFT]]
-// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]]
-// CHECK-32BIT-LONG: ret i32 [[RESULT]]
-// CHECK-32BIT-LONG }
+// CHECK-32BIT-LONG: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+// CHECK-32BIT-LONG: ret i32 [[R]]
unsigned __int64 test_rotr64(unsigned __int64 value, int shift) {
return _rotr64(value, shift);
}
// CHECK: i64 @test_rotr64
-// CHECK: [[RSHIFT:%[0-9]+]] = and i64 [[SHIFT:%[0-9]+]], 63
-// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE:%[0-9]+]], [[RSHIFT]]
-// CHECK: [[NEGATE:%[0-9]+]] = sub i64 0, [[SHIFT]]
-// CHECK: [[LSHIFT:%[0-9]+]] = and i64 [[NEGATE]], 63
-// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE]], [[LSHIFT]]
-// CHECK: [[RESULT:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
-// CHECK: ret i64 [[RESULT]]
-// CHECK }
+// CHECK: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]])
+// CHECK: ret i64 [[R]]
+
diff --git a/test/CodeGen/ms-intrinsics.c b/test/CodeGen/ms-intrinsics.c
index a8c234123a93..e59b1d36a8e2 100644
--- a/test/CodeGen/ms-intrinsics.c
+++ b/test/CodeGen/ms-intrinsics.c
@@ -3,13 +3,13 @@
// RUN: | FileCheck %s -check-prefixes CHECK,CHECK-I386,CHECK-INTEL
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -triple thumbv7--windows -Oz -emit-llvm %s -o - \
-// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-ARM,CHECK-ARM-X64
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-ARM,CHECK-ARM-ARM64,CHECK-ARM-X64
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -triple x86_64--windows -Oz -emit-llvm -target-feature +cx16 %s -o - \
// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-X64,CHECK-ARM-X64,CHECK-INTEL
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -triple aarch64-windows -Oz -emit-llvm %s -o - \
-// RUN: | FileCheck %s --check-prefix CHECK-ARM-X64
+// RUN: | FileCheck %s --check-prefixes CHECK-ARM-ARM64,CHECK-ARM-X64
// intrin.h needs size_t, but -ffreestanding prevents us from getting it from
// stddef.h. Work around it with this typedef.
@@ -137,7 +137,7 @@ void *test_ReturnAddress() {
// CHECK: = tail call i8* @llvm.returnaddress(i32 0)
// CHECK: ret i8*
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined (__aarch64__)
void *test_AddressOfReturnAddress() {
return _AddressOfReturnAddress();
}
@@ -235,6 +235,21 @@ void *test_InterlockedCompareExchangePointer(void * volatile *Destination,
// CHECK: ret i8* %[[RESULT:[0-9]+]]
// CHECK: }
+void *test_InterlockedCompareExchangePointer_nf(void * volatile *Destination,
+ void *Exchange, void *Comparand) {
+ return _InterlockedCompareExchangePointer_nf(Destination, Exchange, Comparand);
+}
+
+// CHECK: define{{.*}}i8* @test_InterlockedCompareExchangePointer_nf(i8** {{[a-z_ ]*}}%Destination, i8* {{[a-z_ ]*}}%Exchange, i8* {{[a-z_ ]*}}%Comparand){{.*}}{
+// CHECK: %[[DEST:[0-9]+]] = bitcast i8** %Destination to [[iPTR]]*
+// CHECK: %[[EXCHANGE:[0-9]+]] = ptrtoint i8* %Exchange to [[iPTR]]
+// CHECK: %[[COMPARAND:[0-9]+]] = ptrtoint i8* %Comparand to [[iPTR]]
+// CHECK: %[[XCHG:[0-9]+]] = cmpxchg volatile [[iPTR]]* %[[DEST:[0-9]+]], [[iPTR]] %[[COMPARAND:[0-9]+]], [[iPTR]] %[[EXCHANGE:[0-9]+]] monotonic monotonic
+// CHECK: %[[EXTRACT:[0-9]+]] = extractvalue { [[iPTR]], i1 } %[[XCHG]], 0
+// CHECK: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXTRACT]] to i8*
+// CHECK: ret i8* %[[RESULT:[0-9]+]]
+// CHECK: }
+
char test_InterlockedExchange8(char volatile *value, char mask) {
return _InterlockedExchange8(value, mask);
}
@@ -416,14 +431,21 @@ __int64 test_InterlockedCompareExchange64(__int64 volatile *Destination, __int64
// CHECK: }
#if defined(__x86_64__)
-unsigned char test_InterlockedCompareExchange128(__int64 volatile *Destination, __int64 ExchangeHigh, __int64 ExchangeLow, __int64* ComparandResult) {
- return _InterlockedCompareExchange128(Destination, ExchangeHigh, ExchangeLow, ComparandResult);
+unsigned char test_InterlockedCompareExchange128(
+ __int64 volatile *Destination, __int64 ExchangeHigh,
+ __int64 ExchangeLow, __int64 *ComparandResult) {
+ return _InterlockedCompareExchange128(++Destination, ++ExchangeHigh,
+ ++ExchangeLow, ++ComparandResult);
}
// CHECK-X64: define{{.*}}i8 @test_InterlockedCompareExchange128(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%ExchangeHigh, i64{{[a-z_ ]*}}%ExchangeLow, i64*{{[a-z_ ]*}}%ComparandResult){{.*}}{
-// CHECK-X64: [[DST:%[0-9]+]] = bitcast i64* %Destination to i128*
-// CHECK-X64: [[EH:%[0-9]+]] = zext i64 %ExchangeHigh to i128
-// CHECK-X64: [[EL:%[0-9]+]] = zext i64 %ExchangeLow to i128
-// CHECK-X64: [[CNR:%[0-9]+]] = bitcast i64* %ComparandResult to i128*
+// CHECK-X64: %incdec.ptr = getelementptr inbounds i64, i64* %Destination, i64 1
+// CHECK-X64: %inc = add nsw i64 %ExchangeHigh, 1
+// CHECK-X64: %inc1 = add nsw i64 %ExchangeLow, 1
+// CHECK-X64: %incdec.ptr2 = getelementptr inbounds i64, i64* %ComparandResult, i64 1
+// CHECK-X64: [[DST:%[0-9]+]] = bitcast i64* %incdec.ptr to i128*
+// CHECK-X64: [[EH:%[0-9]+]] = zext i64 %inc to i128
+// CHECK-X64: [[EL:%[0-9]+]] = zext i64 %inc1 to i128
+// CHECK-X64: [[CNR:%[0-9]+]] = bitcast i64* %incdec.ptr2 to i128*
// CHECK-X64: [[EHS:%[0-9]+]] = shl nuw i128 [[EH]], 64
// CHECK-X64: [[EXP:%[0-9]+]] = or i128 [[EHS]], [[EL]]
// CHECK-X64: [[ORG:%[0-9]+]] = load i128, i128* [[CNR]], align 16
@@ -590,6 +612,736 @@ __int64 test_InterlockedCompareExchange64_HLERelease(__int64 volatile *Destinati
}
#endif
+#if defined(__arm__) || defined(__aarch64__)
+char test_InterlockedExchangeAdd8_acq(char volatile *value, char mask) {
+ return _InterlockedExchangeAdd8_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedExchangeAdd8_acq(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i8* %value, i8 %mask acquire
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+char test_InterlockedExchangeAdd8_rel(char volatile *value, char mask) {
+ return _InterlockedExchangeAdd8_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedExchangeAdd8_rel(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i8* %value, i8 %mask release
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+char test_InterlockedExchangeAdd8_nf(char volatile *value, char mask) {
+ return _InterlockedExchangeAdd8_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedExchangeAdd8_nf(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i8* %value, i8 %mask monotonic
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+short test_InterlockedExchangeAdd16_acq(short volatile *value, short mask) {
+ return _InterlockedExchangeAdd16_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedExchangeAdd16_acq(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i16* %value, i16 %mask acquire
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+short test_InterlockedExchangeAdd16_rel(short volatile *value, short mask) {
+ return _InterlockedExchangeAdd16_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedExchangeAdd16_rel(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i16* %value, i16 %mask release
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+short test_InterlockedExchangeAdd16_nf(short volatile *value, short mask) {
+ return _InterlockedExchangeAdd16_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedExchangeAdd16_nf(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i16* %value, i16 %mask monotonic
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+long test_InterlockedExchangeAdd_acq(long volatile *value, long mask) {
+ return _InterlockedExchangeAdd_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedExchangeAdd_acq(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i32* %value, i32 %mask acquire
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+long test_InterlockedExchangeAdd_rel(long volatile *value, long mask) {
+ return _InterlockedExchangeAdd_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedExchangeAdd_rel(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i32* %value, i32 %mask release
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+long test_InterlockedExchangeAdd_nf(long volatile *value, long mask) {
+ return _InterlockedExchangeAdd_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedExchangeAdd_nf(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i32* %value, i32 %mask monotonic
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+__int64 test_InterlockedExchangeAdd64_acq(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchangeAdd64_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedExchangeAdd64_acq(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i64* %value, i64 %mask acquire
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+__int64 test_InterlockedExchangeAdd64_rel(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchangeAdd64_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedExchangeAdd64_rel(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i64* %value, i64 %mask release
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+__int64 test_InterlockedExchangeAdd64_nf(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchangeAdd64_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedExchangeAdd64_nf(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw add i64* %value, i64 %mask monotonic
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedExchange8_acq(char volatile *value, char mask) {
+ return _InterlockedExchange8_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedExchange8_acq(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i8* %value, i8 %mask acquire
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+char test_InterlockedExchange8_rel(char volatile *value, char mask) {
+ return _InterlockedExchange8_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedExchange8_rel(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i8* %value, i8 %mask release
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+char test_InterlockedExchange8_nf(char volatile *value, char mask) {
+ return _InterlockedExchange8_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedExchange8_nf(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i8* %value, i8 %mask monotonic
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+short test_InterlockedExchange16_acq(short volatile *value, short mask) {
+ return _InterlockedExchange16_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedExchange16_acq(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i16* %value, i16 %mask acquire
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+short test_InterlockedExchange16_rel(short volatile *value, short mask) {
+ return _InterlockedExchange16_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedExchange16_rel(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i16* %value, i16 %mask release
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+short test_InterlockedExchange16_nf(short volatile *value, short mask) {
+ return _InterlockedExchange16_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedExchange16_nf(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i16* %value, i16 %mask monotonic
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+long test_InterlockedExchange_acq(long volatile *value, long mask) {
+ return _InterlockedExchange_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedExchange_acq(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i32* %value, i32 %mask acquire
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+long test_InterlockedExchange_rel(long volatile *value, long mask) {
+ return _InterlockedExchange_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedExchange_rel(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i32* %value, i32 %mask release
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+long test_InterlockedExchange_nf(long volatile *value, long mask) {
+ return _InterlockedExchange_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedExchange_nf(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i32* %value, i32 %mask monotonic
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+__int64 test_InterlockedExchange64_acq(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchange64_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedExchange64_acq(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i64* %value, i64 %mask acquire
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+__int64 test_InterlockedExchange64_rel(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchange64_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedExchange64_rel(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i64* %value, i64 %mask release
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+__int64 test_InterlockedExchange64_nf(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchange64_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedExchange64_nf(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xchg i64* %value, i64 %mask monotonic
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedCompareExchange8_acq(char volatile *Destination, char Exchange, char Comperand) {
+ return _InterlockedCompareExchange8_acq(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedCompareExchange8_acq(i8*{{[a-z_ ]*}}%Destination, i8{{[a-z_ ]*}}%Exchange, i8{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i8* %Destination, i8 %Comperand, i8 %Exchange acquire acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i8, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i8 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedCompareExchange8_rel(char volatile *Destination, char Exchange, char Comperand) {
+ return _InterlockedCompareExchange8_rel(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedCompareExchange8_rel(i8*{{[a-z_ ]*}}%Destination, i8{{[a-z_ ]*}}%Exchange, i8{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i8* %Destination, i8 %Comperand, i8 %Exchange release monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i8, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i8 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedCompareExchange8_nf(char volatile *Destination, char Exchange, char Comperand) {
+ return _InterlockedCompareExchange8_nf(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedCompareExchange8_nf(i8*{{[a-z_ ]*}}%Destination, i8{{[a-z_ ]*}}%Exchange, i8{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i8* %Destination, i8 %Comperand, i8 %Exchange monotonic monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i8, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i8 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedCompareExchange16_acq(short volatile *Destination, short Exchange, short Comperand) {
+ return _InterlockedCompareExchange16_acq(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedCompareExchange16_acq(i16*{{[a-z_ ]*}}%Destination, i16{{[a-z_ ]*}}%Exchange, i16{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i16* %Destination, i16 %Comperand, i16 %Exchange acquire acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i16, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedCompareExchange16_rel(short volatile *Destination, short Exchange, short Comperand) {
+ return _InterlockedCompareExchange16_rel(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedCompareExchange16_rel(i16*{{[a-z_ ]*}}%Destination, i16{{[a-z_ ]*}}%Exchange, i16{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i16* %Destination, i16 %Comperand, i16 %Exchange release monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i16, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedCompareExchange16_nf(short volatile *Destination, short Exchange, short Comperand) {
+ return _InterlockedCompareExchange16_nf(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedCompareExchange16_nf(i16*{{[a-z_ ]*}}%Destination, i16{{[a-z_ ]*}}%Exchange, i16{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i16* %Destination, i16 %Comperand, i16 %Exchange monotonic monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i16, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedCompareExchange_acq(long volatile *Destination, long Exchange, long Comperand) {
+ return _InterlockedCompareExchange_acq(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedCompareExchange_acq(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i32* %Destination, i32 %Comperand, i32 %Exchange acquire acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i32, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedCompareExchange_rel(long volatile *Destination, long Exchange, long Comperand) {
+ return _InterlockedCompareExchange_rel(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedCompareExchange_rel(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i32* %Destination, i32 %Comperand, i32 %Exchange release monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i32, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedCompareExchange_nf(long volatile *Destination, long Exchange, long Comperand) {
+ return _InterlockedCompareExchange_nf(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedCompareExchange_nf(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i32* %Destination, i32 %Comperand, i32 %Exchange monotonic monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i32, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedCompareExchange64_acq(__int64 volatile *Destination, __int64 Exchange, __int64 Comperand) {
+ return _InterlockedCompareExchange64_acq(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedCompareExchange64_acq(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i64* %Destination, i64 %Comperand, i64 %Exchange acquire acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i64, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedCompareExchange64_rel(__int64 volatile *Destination, __int64 Exchange, __int64 Comperand) {
+ return _InterlockedCompareExchange64_rel(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedCompareExchange64_rel(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i64* %Destination, i64 %Comperand, i64 %Exchange release monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i64, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedCompareExchange64_nf(__int64 volatile *Destination, __int64 Exchange, __int64 Comperand) {
+ return _InterlockedCompareExchange64_nf(Destination, Exchange, Comperand);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedCompareExchange64_nf(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = cmpxchg volatile i64* %Destination, i64 %Comperand, i64 %Exchange monotonic monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = extractvalue { i64, i1 } [[TMP]], 0
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedOr8_acq(char volatile *value, char mask) {
+ return _InterlockedOr8_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedOr8_acq(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i8* %value, i8 %mask acquire
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedOr8_rel(char volatile *value, char mask) {
+ return _InterlockedOr8_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedOr8_rel(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i8* %value, i8 %mask release
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedOr8_nf(char volatile *value, char mask) {
+ return _InterlockedOr8_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedOr8_nf(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i8* %value, i8 %mask monotonic
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedOr16_acq(short volatile *value, short mask) {
+ return _InterlockedOr16_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedOr16_acq(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i16* %value, i16 %mask acquire
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedOr16_rel(short volatile *value, short mask) {
+ return _InterlockedOr16_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedOr16_rel(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i16* %value, i16 %mask release
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedOr16_nf(short volatile *value, short mask) {
+ return _InterlockedOr16_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedOr16_nf(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i16* %value, i16 %mask monotonic
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedOr_acq(long volatile *value, long mask) {
+ return _InterlockedOr_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedOr_acq(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i32* %value, i32 %mask acquire
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedOr_rel(long volatile *value, long mask) {
+ return _InterlockedOr_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedOr_rel(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i32* %value, i32 %mask release
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedOr_nf(long volatile *value, long mask) {
+ return _InterlockedOr_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedOr_nf(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i32* %value, i32 %mask monotonic
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedOr64_acq(__int64 volatile *value, __int64 mask) {
+ return _InterlockedOr64_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedOr64_acq(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i64* %value, i64 %mask acquire
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedOr64_rel(__int64 volatile *value, __int64 mask) {
+ return _InterlockedOr64_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedOr64_rel(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i64* %value, i64 %mask release
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedOr64_nf(__int64 volatile *value, __int64 mask) {
+ return _InterlockedOr64_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedOr64_nf(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw or i64* %value, i64 %mask monotonic
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedXor8_acq(char volatile *value, char mask) {
+ return _InterlockedXor8_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedXor8_acq(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i8* %value, i8 %mask acquire
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedXor8_rel(char volatile *value, char mask) {
+ return _InterlockedXor8_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedXor8_rel(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i8* %value, i8 %mask release
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedXor8_nf(char volatile *value, char mask) {
+ return _InterlockedXor8_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedXor8_nf(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i8* %value, i8 %mask monotonic
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedXor16_acq(short volatile *value, short mask) {
+ return _InterlockedXor16_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedXor16_acq(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i16* %value, i16 %mask acquire
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedXor16_rel(short volatile *value, short mask) {
+ return _InterlockedXor16_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedXor16_rel(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i16* %value, i16 %mask release
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedXor16_nf(short volatile *value, short mask) {
+ return _InterlockedXor16_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedXor16_nf(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i16* %value, i16 %mask monotonic
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedXor_acq(long volatile *value, long mask) {
+ return _InterlockedXor_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedXor_acq(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i32* %value, i32 %mask acquire
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedXor_rel(long volatile *value, long mask) {
+ return _InterlockedXor_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedXor_rel(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i32* %value, i32 %mask release
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedXor_nf(long volatile *value, long mask) {
+ return _InterlockedXor_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedXor_nf(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i32* %value, i32 %mask monotonic
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedXor64_acq(__int64 volatile *value, __int64 mask) {
+ return _InterlockedXor64_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedXor64_acq(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i64* %value, i64 %mask acquire
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedXor64_rel(__int64 volatile *value, __int64 mask) {
+ return _InterlockedXor64_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedXor64_rel(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i64* %value, i64 %mask release
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedXor64_nf(__int64 volatile *value, __int64 mask) {
+ return _InterlockedXor64_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedXor64_nf(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw xor i64* %value, i64 %mask monotonic
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedAnd8_acq(char volatile *value, char mask) {
+ return _InterlockedAnd8_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedAnd8_acq(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i8* %value, i8 %mask acquire
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedAnd8_rel(char volatile *value, char mask) {
+ return _InterlockedAnd8_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedAnd8_rel(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i8* %value, i8 %mask release
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+char test_InterlockedAnd8_nf(char volatile *value, char mask) {
+ return _InterlockedAnd8_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i8 @test_InterlockedAnd8_nf(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i8* %value, i8 %mask monotonic
+// CHECK-ARM-ARM64: ret i8 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedAnd16_acq(short volatile *value, short mask) {
+ return _InterlockedAnd16_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedAnd16_acq(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i16* %value, i16 %mask acquire
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedAnd16_rel(short volatile *value, short mask) {
+ return _InterlockedAnd16_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedAnd16_rel(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i16* %value, i16 %mask release
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedAnd16_nf(short volatile *value, short mask) {
+ return _InterlockedAnd16_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedAnd16_nf(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i16* %value, i16 %mask monotonic
+// CHECK-ARM-ARM64: ret i16 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedAnd_acq(long volatile *value, long mask) {
+ return _InterlockedAnd_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedAnd_acq(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i32* %value, i32 %mask acquire
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedAnd_rel(long volatile *value, long mask) {
+ return _InterlockedAnd_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedAnd_rel(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i32* %value, i32 %mask release
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedAnd_nf(long volatile *value, long mask) {
+ return _InterlockedAnd_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedAnd_nf(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i32* %value, i32 %mask monotonic
+// CHECK-ARM-ARM64: ret i32 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedAnd64_acq(__int64 volatile *value, __int64 mask) {
+ return _InterlockedAnd64_acq(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedAnd64_acq(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i64* %value, i64 %mask acquire
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedAnd64_rel(__int64 volatile *value, __int64 mask) {
+ return _InterlockedAnd64_rel(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedAnd64_rel(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i64* %value, i64 %mask release
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedAnd64_nf(__int64 volatile *value, __int64 mask) {
+ return _InterlockedAnd64_nf(value, mask);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedAnd64_nf(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = atomicrmw and i64* %value, i64 %mask monotonic
+// CHECK-ARM-ARM64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedIncrement16_acq(short volatile *Addend) {
+ return _InterlockedIncrement16_acq(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedIncrement16_acq(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i16* %Addend, i16 1 acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedIncrement16_rel(short volatile *Addend) {
+ return _InterlockedIncrement16_rel(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedIncrement16_rel(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i16* %Addend, i16 1 release
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedIncrement16_nf(short volatile *Addend) {
+ return _InterlockedIncrement16_nf(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedIncrement16_nf(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i16* %Addend, i16 1 monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedIncrement_acq(long volatile *Addend) {
+ return _InterlockedIncrement_acq(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedIncrement_acq(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i32* %Addend, i32 1 acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedIncrement_rel(long volatile *Addend) {
+ return _InterlockedIncrement_rel(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedIncrement_rel(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i32* %Addend, i32 1 release
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedIncrement_nf(long volatile *Addend) {
+ return _InterlockedIncrement_nf(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedIncrement_nf(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i32* %Addend, i32 1 monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedIncrement64_acq(__int64 volatile *Addend) {
+ return _InterlockedIncrement64_acq(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedIncrement64_acq(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i64* %Addend, i64 1 acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedIncrement64_rel(__int64 volatile *Addend) {
+ return _InterlockedIncrement64_rel(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedIncrement64_rel(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i64* %Addend, i64 1 release
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedIncrement64_nf(__int64 volatile *Addend) {
+ return _InterlockedIncrement64_nf(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedIncrement64_nf(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add i64* %Addend, i64 1 monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], 1
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedDecrement16_acq(short volatile *Addend) {
+ return _InterlockedDecrement16_acq(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedDecrement16_acq(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i16* %Addend, i16 1 acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedDecrement16_rel(short volatile *Addend) {
+ return _InterlockedDecrement16_rel(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedDecrement16_rel(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i16* %Addend, i16 1 release
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+short test_InterlockedDecrement16_nf(short volatile *Addend) {
+ return _InterlockedDecrement16_nf(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedDecrement16_nf(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i16* %Addend, i16 1 monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i16 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedDecrement_acq(long volatile *Addend) {
+ return _InterlockedDecrement_acq(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedDecrement_acq(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i32* %Addend, i32 1 acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedDecrement_rel(long volatile *Addend) {
+ return _InterlockedDecrement_rel(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedDecrement_rel(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i32* %Addend, i32 1 release
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+long test_InterlockedDecrement_nf(long volatile *Addend) {
+ return _InterlockedDecrement_nf(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedDecrement_nf(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i32* %Addend, i32 1 monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i32 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedDecrement64_acq(__int64 volatile *Addend) {
+ return _InterlockedDecrement64_acq(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedDecrement64_acq(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i64* %Addend, i64 1 acquire
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedDecrement64_rel(__int64 volatile *Addend) {
+ return _InterlockedDecrement64_rel(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedDecrement64_rel(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i64* %Addend, i64 1 release
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+
+__int64 test_InterlockedDecrement64_nf(__int64 volatile *Addend) {
+ return _InterlockedDecrement64_nf(Addend);
+}
+// CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedDecrement64_nf(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub i64* %Addend, i64 1 monotonic
+// CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1
+// CHECK-ARM-ARM64: ret i64 [[RESULT]]
+// CHECK-ARM-ARM64: }
+#endif
+
#if !defined(__aarch64__)
void test__fastfail() {
__fastfail(42);
diff --git a/test/CodeGen/ms-setjmp.c b/test/CodeGen/ms-setjmp.c
index d92f4d00ff5c..a6e30cb96aa4 100644
--- a/test/CodeGen/ms-setjmp.c
+++ b/test/CodeGen/ms-setjmp.c
@@ -25,7 +25,7 @@ int test_setjmp() {
// X64-NEXT: ret i32 %[[call]]
// AARCH64-LABEL: define dso_local i32 @test_setjmp
- // AARCH64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)
+ // AARCH64: %[[addr:.*]] = call i8* @llvm.sponentry()
// AARCH64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])
// AARCH64-NEXT: ret i32 %[[call]]
}
@@ -38,7 +38,7 @@ int test_setjmpex() {
// X64-NEXT: ret i32 %[[call]]
// AARCH64-LABEL: define dso_local i32 @test_setjmpex
- // AARCH64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)
+ // AARCH64: %[[addr:.*]] = call i8* @llvm.sponentry()
// AARCH64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])
// AARCH64-NEXT: ret i32 %[[call]]
}
diff --git a/test/CodeGen/ms-x86-intrinsics.c b/test/CodeGen/ms-x86-intrinsics.c
index 450a134131be..c231dbd56e39 100644
--- a/test/CodeGen/ms-x86-intrinsics.c
+++ b/test/CodeGen/ms-x86-intrinsics.c
@@ -7,34 +7,38 @@
#if defined(__i386__)
char test__readfsbyte(unsigned long Offset) {
- return __readfsbyte(Offset);
+ return __readfsbyte(++Offset);
}
// CHECK-I386-LABEL: define dso_local signext i8 @test__readfsbyte(i32 %Offset)
-// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i8 addrspace(257)*
+// CHECK-I386: %inc = add i32 %Offset, 1
+// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %inc to i8 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i8, i8 addrspace(257)* [[PTR]], align 1
// CHECK-I386: ret i8 [[VALUE:%[0-9]+]]
short test__readfsword(unsigned long Offset) {
- return __readfsword(Offset);
+ return __readfsword(++Offset);
}
// CHECK-I386-LABEL: define dso_local signext i16 @test__readfsword(i32 %Offset)
-// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i16 addrspace(257)*
+// CHECK-I386: %inc = add i32 %Offset, 1
+// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %inc to i16 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i16, i16 addrspace(257)* [[PTR]], align 2
// CHECK-I386: ret i16 [[VALUE:%[0-9]+]]
long test__readfsdword(unsigned long Offset) {
- return __readfsdword(Offset);
+ return __readfsdword(++Offset);
}
// CHECK-I386-LABEL: define dso_local i32 @test__readfsdword(i32 %Offset)
-// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i32 addrspace(257)*
+// CHECK-I386: %inc = add i32 %Offset, 1
+// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %inc to i32 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(257)* [[PTR]], align 4
// CHECK-I386: ret i32 [[VALUE:%[0-9]+]]
long long test__readfsqword(unsigned long Offset) {
- return __readfsqword(Offset);
+ return __readfsqword(++Offset);
}
// CHECK-I386-LABEL: define dso_local i64 @test__readfsqword(i32 %Offset)
-// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i64 addrspace(257)*
+// CHECK-I386: %inc = add i32 %Offset, 1
+// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %inc to i64 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i64, i64 addrspace(257)* [[PTR]], align 8
// CHECK-I386: ret i64 [[VALUE:%[0-9]+]]
#endif
@@ -60,37 +64,41 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
#if defined(__x86_64__)
char test__readgsbyte(unsigned long Offset) {
- return __readgsbyte(Offset);
+ return __readgsbyte(++Offset);
}
// CHECK-X64-LABEL: define dso_local i8 @test__readgsbyte(i32 %Offset)
-// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
+// CHECK-X64: %inc = add i32 %Offset, 1
+// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %inc to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i8 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i8, i8 addrspace(256)* [[PTR]], align 1
// CHECK-X64: ret i8 [[VALUE:%[0-9]+]]
short test__readgsword(unsigned long Offset) {
- return __readgsword(Offset);
+ return __readgsword(++Offset);
}
// CHECK-X64-LABEL: define dso_local i16 @test__readgsword(i32 %Offset)
-// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
+// CHECK-X64: %inc = add i32 %Offset, 1
+// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %inc to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i16 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i16, i16 addrspace(256)* [[PTR]], align 2
// CHECK-X64: ret i16 [[VALUE:%[0-9]+]]
long test__readgsdword(unsigned long Offset) {
- return __readgsdword(Offset);
+ return __readgsdword(++Offset);
}
// CHECK-X64-LABEL: define dso_local i32 @test__readgsdword(i32 %Offset)
-// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
+// CHECK-X64: %inc = add i32 %Offset, 1
+// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %inc to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i32 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(256)* [[PTR]], align 4
// CHECK-X64: ret i32 [[VALUE:%[0-9]+]]
long long test__readgsqword(unsigned long Offset) {
- return __readgsqword(Offset);
+ return __readgsqword(++Offset);
}
// CHECK-X64-LABEL: define dso_local i64 @test__readgsqword(i32 %Offset)
-// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
+// CHECK-X64: %inc = add i32 %Offset, 1
+// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %inc to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i64 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i64, i64 addrspace(256)* [[PTR]], align 8
// CHECK-X64: ret i64 [[VALUE:%[0-9]+]]
@@ -130,4 +138,34 @@ unsigned __int64 test_umul128(unsigned __int64 Multiplier,
// CHECK-X64: = mul nuw i128 %
// CHECK-X64: store i64 %
// CHECK-X64: ret i64 %
-#endif
+
+unsigned __int64 test__shiftleft128(unsigned __int64 l, unsigned __int64 h,
+ unsigned char d) {
+ return __shiftleft128(l, h, d);
+}
+// CHECK-X64-LABEL: define dso_local i64 @test__shiftleft128(i64 %l, i64 %h, i8 %d)
+// CHECK-X64 = zext i64 %h to i128
+// CHECK-X64 = shl nuw i128 %0, 64
+// CHECK-X64 = zext i64 %l to i128
+// CHECK-X64 = or i128 %1, %2
+// CHECK-X64 = and i8 %d, 63
+// CHECK-X64 = shl i128 %
+// CHECK-X64 = lshr i128 %
+// CHECK-X64 = trunc i128 %
+// CHECK-X64 ret i64 %
+
+unsigned __int64 test__shiftright128(unsigned __int64 l, unsigned __int64 h,
+ unsigned char d) {
+ return __shiftright128(l, h, d);
+}
+// CHECK-X64-LABEL: define dso_local i64 @test__shiftright128(i64 %l, i64 %h, i8 %d)
+// CHECK-X64 = zext i64 %h to i128
+// CHECK-X64 = shl nuw i128 %
+// CHECK-X64 = zext i64 %l to i128
+// CHECK-X64 = or i128 %
+// CHECK-X64 = and i8 %d, 63
+// CHECK-X64 = lshr i128 %
+// CHECK-X64 = trunc i128 %
+// CHECK-X64 ret i64 %
+
+#endif // defined(__x86_64__)
diff --git a/test/CodeGen/pch-dllexport.cpp b/test/CodeGen/pch-dllexport.cpp
index 9c6623be4362..b8db075046de 100644
--- a/test/CodeGen/pch-dllexport.cpp
+++ b/test/CodeGen/pch-dllexport.cpp
@@ -57,6 +57,13 @@ extern template void explicitInstantiationDefAfterDecl<int>(int);
template <typename T> T __declspec(dllexport) variableTemplate;
extern template int variableTemplate<int>;
+namespace pr38934 {
+template <typename T> struct S {};
+extern template struct S<int>;
+// The use here causes the S<int>::operator= decl to go into the PCH.
+inline void use(S<int> *a, S<int> *b) { *a = *b; };
+}
+
#else
void use() {
@@ -81,4 +88,9 @@ template void __declspec(dllexport) explicitInstantiationDefAfterDecl<int>(int);
template int __declspec(dllexport) variableTemplate<int>;
// PCHWITHOBJVARS: @"??$variableTemplate@H@@3HA" = weak_odr dso_local dllexport global
+// PR38934: Make sure S<int>::operator= gets emitted. While it itself isn't a
+// template specialization, its parent is.
+template struct __declspec(dllexport) pr38934::S<int>;
+// PCHWITHOBJ: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %"struct.pr38934::S"* @"??4?$S@H@pr38934@@QAEAAU01@ABU01@@Z"
+
#endif
diff --git a/test/CodeGen/personality.c b/test/CodeGen/personality.c
index 1c533ce786c0..59a6a9ccd696 100644
--- a/test/CodeGen/personality.c
+++ b/test/CodeGen/personality.c
@@ -26,6 +26,7 @@ extern void i(void);
void f(void) {
__block int i;
+ ^{ (void)i; };
g(^ { });
}
diff --git a/test/CodeGen/pr18235.c b/test/CodeGen/pr18235.c
index 49241c822923..bd9261dc7bb5 100644
--- a/test/CodeGen/pr18235.c
+++ b/test/CodeGen/pr18235.c
@@ -1,3 +1,3 @@
// RUN: not %clang_cc1 -triple le32-unknown-nacl %s -S -o - 2>&1 | FileCheck %s
-// CHECK: error: unable to create target: 'No available targets are compatible with this triple.
+// CHECK: error: unable to create target: 'No available targets are compatible with triple "le32-unknown-nacl"'
diff --git a/test/CodeGen/rd-builtins.c b/test/CodeGen/rd-builtins.c
index 0d7cd04d6f26..38e0886f0325 100644
--- a/test/CodeGen/rd-builtins.c
+++ b/test/CodeGen/rd-builtins.c
@@ -14,3 +14,12 @@ int test_rdtsc() {
// CHECK: @test_rdtsc
// CHECK: call i64 @llvm.x86.rdtsc
}
+
+unsigned long long test_rdtscp(unsigned int *a) {
+// CHECK: @test_rdtscp
+// CHECK: [[RDTSCP:%.*]] = call { i64, i32 } @llvm.x86.rdtscp
+// CHECK: [[TSC_AUX:%.*]] = extractvalue { i64, i32 } [[RDTSCP]], 1
+// CHECK: store i32 [[TSC_AUX]], i32* %{{.*}}
+// CHECK: [[TSC:%.*]] = extractvalue { i64, i32 } [[RDTSCP]], 0
+ return __rdtscp(a);
+}
diff --git a/test/CodeGen/sanitize-thread-no-checking-at-run-time.m b/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
index 3d862c0bf7ed..16d3bc931c73 100644
--- a/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
+++ b/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
@@ -35,7 +35,7 @@ public:
void test2(id x) {
extern void test2_helper(id (^)(void));
test2_helper(^{ return x; });
-// TSAN: define internal void @__destroy_helper_block_(i8*) [[ATTR:#[0-9]+]]
+// TSAN: define linkonce_odr hidden void @__destroy_helper_block_8_32o(i8*) unnamed_addr [[ATTR:#[0-9]+]]
}
// TSAN: attributes [[ATTR]] = { noinline nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} }
diff --git a/test/CodeGen/split-debug-single-file.c b/test/CodeGen/split-debug-single-file.c
new file mode 100644
index 000000000000..ffbc127a463c
--- /dev/null
+++ b/test/CodeGen/split-debug-single-file.c
@@ -0,0 +1,17 @@
+// REQUIRES: x86-registered-target
+
+// Testing to ensure -enable-split-dwarf=single allows to place .dwo sections into regular output object.
+// RUN: %clang_cc1 -debug-info-kind=limited -triple x86_64-unknown-linux \
+// RUN: -enable-split-dwarf=single -split-dwarf-file %t.o -emit-obj -o %t.o %s
+// RUN: llvm-objdump -section-headers %t.o | FileCheck --check-prefix=MODE-SINGLE %s
+// MODE-SINGLE: .dwo
+
+// Testing to ensure -enable-split-dwarf=split does not place .dwo sections into regular output object.
+// RUN: %clang_cc1 -debug-info-kind=limited -triple x86_64-unknown-linux \
+// RUN: -enable-split-dwarf=split -split-dwarf-file %t.o -emit-obj -o %t.o %s
+// RUN: llvm-objdump -section-headers %t.o | FileCheck --check-prefix=MODE-SPLIT %s
+// MODE-SPLIT-NOT: .dwo
+
+int main (void) {
+ return 0;
+}
diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c
index fe7f7ccf83ee..28ee523ac840 100644
--- a/test/CodeGen/sse2-builtins.c
+++ b/test/CodeGen/sse2-builtins.c
@@ -47,25 +47,27 @@ __m128d test_mm_add_sd(__m128d A, __m128d B) {
__m128i test_mm_adds_epi8(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_adds_epi8
- // CHECK: call <16 x i8> @llvm.x86.sse2.padds.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK: call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
return _mm_adds_epi8(A, B);
}
__m128i test_mm_adds_epi16(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_adds_epi16
- // CHECK: call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
return _mm_adds_epi16(A, B);
}
__m128i test_mm_adds_epu8(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_adds_epu8
- // CHECK: call <16 x i8> @llvm.x86.sse2.paddus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-NOT: call <16 x i8> @llvm.x86.sse2.paddus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK: call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
return _mm_adds_epu8(A, B);
}
__m128i test_mm_adds_epu16(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_adds_epu16
- // CHECK: call <8 x i16> @llvm.x86.sse2.paddus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-NOT: call <8 x i16> @llvm.x86.sse2.paddus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
return _mm_adds_epu16(A, B);
}
@@ -715,6 +717,30 @@ __m128i test_mm_loadu_si64(void const* A) {
return _mm_loadu_si64(A);
}
+__m128i test_mm_loadu_si32(void const* A) {
+ // CHECK-LABEL: test_mm_loadu_si32
+ // CHECK: load i32, i32* %{{.*}}, align 1{{$}}
+ // CHECK: insertelement <4 x i32> undef, i32 %{{.*}}, i32 0
+ // CHECK: insertelement <4 x i32> %{{.*}}, i32 0, i32 1
+ // CHECK: insertelement <4 x i32> %{{.*}}, i32 0, i32 2
+ // CHECK: insertelement <4 x i32> %{{.*}}, i32 0, i32 3
+ return _mm_loadu_si32(A);
+}
+
+__m128i test_mm_loadu_si16(void const* A) {
+ // CHECK-LABEL: test_mm_loadu_si16
+ // CHECK: load i16, i16* %{{.*}}, align 1{{$}}
+ // CHECK: insertelement <8 x i16> undef, i16 %{{.*}}, i32 0
+ // CHECK: insertelement <8 x i16> %{{.*}}, i16 0, i32 1
+ // CHECK: insertelement <8 x i16> %{{.*}}, i16 0, i32 2
+ // CHECK: insertelement <8 x i16> %{{.*}}, i16 0, i32 3
+ // CHECK: insertelement <8 x i16> %{{.*}}, i16 0, i32 4
+ // CHECK: insertelement <8 x i16> %{{.*}}, i16 0, i32 5
+ // CHECK: insertelement <8 x i16> %{{.*}}, i16 0, i32 6
+ // CHECK: insertelement <8 x i16> %{{.*}}, i16 0, i32 7
+ return _mm_loadu_si16(A);
+}
+
__m128i test_mm_madd_epi16(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_madd_epi16
// CHECK: call <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
@@ -1160,18 +1186,54 @@ __m128i test_mm_slli_epi16(__m128i A) {
return _mm_slli_epi16(A, 1);
}
+__m128i test_mm_slli_epi16_1(__m128i A) {
+ // CHECK-LABEL: test_mm_slli_epi16_1
+ // CHECK: call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm_slli_epi16(A, -1);
+}
+
+__m128i test_mm_slli_epi16_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_slli_epi16_2
+ // CHECK: call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm_slli_epi16(A, B);
+}
+
__m128i test_mm_slli_epi32(__m128i A) {
// CHECK-LABEL: test_mm_slli_epi32
// CHECK: call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %{{.*}}, i32 %{{.*}})
return _mm_slli_epi32(A, 1);
}
+__m128i test_mm_slli_epi32_1(__m128i A) {
+ // CHECK-LABEL: test_mm_slli_epi32_1
+ // CHECK: call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm_slli_epi32(A, -1);
+}
+
+__m128i test_mm_slli_epi32_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_slli_epi32_2
+ // CHECK: call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm_slli_epi32(A, B);
+}
+
__m128i test_mm_slli_epi64(__m128i A) {
// CHECK-LABEL: test_mm_slli_epi64
// CHECK: call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %{{.*}}, i32 %{{.*}})
return _mm_slli_epi64(A, 1);
}
+__m128i test_mm_slli_epi64_1(__m128i A) {
+ // CHECK-LABEL: test_mm_slli_epi64_1
+ // CHECK: call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %{{.*}}, i32 %{{.*}})
+ return _mm_slli_epi64(A, -1);
+}
+
+__m128i test_mm_slli_epi64_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_slli_epi64_2
+ // CHECK: call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %{{.*}}, i32 %{{.*}})
+ return _mm_slli_epi64(A, B);
+}
+
__m128i test_mm_slli_si128(__m128i A) {
// CHECK-LABEL: test_mm_slli_si128
// CHECK: shufflevector <16 x i8> zeroinitializer, <16 x i8> %{{.*}}, <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
@@ -1216,12 +1278,36 @@ __m128i test_mm_srai_epi16(__m128i A) {
return _mm_srai_epi16(A, 1);
}
+__m128i test_mm_srai_epi16_1(__m128i A) {
+ // CHECK-LABEL: test_mm_srai_epi16_1
+ // CHECK: call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm_srai_epi16(A, -1);
+}
+
+__m128i test_mm_srai_epi16_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_srai_epi16_2
+ // CHECK: call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm_srai_epi16(A, B);
+}
+
__m128i test_mm_srai_epi32(__m128i A) {
// CHECK-LABEL: test_mm_srai_epi32
// CHECK: call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %{{.*}}, i32 %{{.*}})
return _mm_srai_epi32(A, 1);
}
+__m128i test_mm_srai_epi32_1(__m128i A) {
+ // CHECK-LABEL: test_mm_srai_epi32_1
+ // CHECK: call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm_srai_epi32(A, -1);
+}
+
+__m128i test_mm_srai_epi32_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_srai_epi32_2
+ // CHECK: call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm_srai_epi32(A, B);
+}
+
__m128i test_mm_srl_epi16(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_srl_epi16
// CHECK: call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
@@ -1246,18 +1332,54 @@ __m128i test_mm_srli_epi16(__m128i A) {
return _mm_srli_epi16(A, 1);
}
+__m128i test_mm_srli_epi16_1(__m128i A) {
+ // CHECK-LABEL: test_mm_srli_epi16_1
+ // CHECK: call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm_srli_epi16(A, -1);
+}
+
+__m128i test_mm_srli_epi16_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_srli_epi16
+ // CHECK: call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %{{.*}}, i32 %{{.*}})
+ return _mm_srli_epi16(A, B);
+}
+
__m128i test_mm_srli_epi32(__m128i A) {
// CHECK-LABEL: test_mm_srli_epi32
// CHECK: call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %{{.*}}, i32 %{{.*}})
return _mm_srli_epi32(A, 1);
}
+__m128i test_mm_srli_epi32_1(__m128i A) {
+ // CHECK-LABEL: test_mm_srli_epi32_1
+ // CHECK: call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm_srli_epi32(A, -1);
+}
+
+__m128i test_mm_srli_epi32_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_srli_epi32_2
+ // CHECK: call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %{{.*}}, i32 %{{.*}})
+ return _mm_srli_epi32(A, B);
+}
+
__m128i test_mm_srli_epi64(__m128i A) {
// CHECK-LABEL: test_mm_srli_epi64
// CHECK: call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %{{.*}}, i32 %{{.*}})
return _mm_srli_epi64(A, 1);
}
+__m128i test_mm_srli_epi64_1(__m128i A) {
+ // CHECK-LABEL: test_mm_srli_epi64_1
+ // CHECK: call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %{{.*}}, i32 %{{.*}})
+ return _mm_srli_epi64(A, -1);
+}
+
+__m128i test_mm_srli_epi64_2(__m128i A, int B) {
+ // CHECK-LABEL: test_mm_srli_epi64_2
+ // CHECK: call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %{{.*}}, i32 %{{.*}})
+ return _mm_srli_epi64(A, B);
+}
+
__m128i test_mm_srli_si128(__m128i A) {
// CHECK-LABEL: test_mm_srli_si128
// CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
@@ -1345,6 +1467,30 @@ void test_mm_storeu_si128(__m128i* A, __m128i B) {
_mm_storeu_si128(A, B);
}
+void test_mm_storeu_si64(void* A, __m128i B) {
+ // CHECK-LABEL: test_mm_storeu_si64
+ // CHECK: [[EXT:%.*]] = extractelement <2 x i64> %{{.*}}, i32 0
+ // CHECK: store i64 [[EXT]], i64* %{{.*}}, align 1{{$}}
+ // CHECK-NEXT: ret void
+ _mm_storeu_si64(A, B);
+}
+
+void test_mm_storeu_si32(void* A, __m128i B) {
+ // CHECK-LABEL: test_mm_storeu_si32
+ // CHECK: [[EXT:%.*]] = extractelement <4 x i32> %{{.*}}, i32 0
+ // CHECK: store i32 [[EXT]], i32* %{{.*}}, align 1{{$}}
+ // CHECK-NEXT: ret void
+ _mm_storeu_si32(A, B);
+}
+
+void test_mm_storeu_si16(void* A, __m128i B) {
+ // CHECK-LABEL: test_mm_storeu_si16
+ // CHECK: [[EXT:%.*]] = extractelement <8 x i16> %{{.*}}, i32 0
+ // CHECK: store i16 [[EXT]], i16* %{{.*}}, align 1{{$}}
+ // CHECK-NEXT: ret void
+ _mm_storeu_si16(A, B);
+}
+
void test_mm_stream_pd(double *A, __m128d B) {
// CHECK-LABEL: test_mm_stream_pd
// CHECK: store <2 x double> %{{.*}}, <2 x double>* %{{.*}}, align 16, !nontemporal
@@ -1410,25 +1556,27 @@ __m128d test_mm_sub_sd(__m128d A, __m128d B) {
__m128i test_mm_subs_epi8(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_subs_epi8
- // CHECK: call <16 x i8> @llvm.x86.sse2.psubs.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK: call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
return _mm_subs_epi8(A, B);
}
__m128i test_mm_subs_epi16(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_subs_epi16
- // CHECK: call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
return _mm_subs_epi16(A, B);
}
__m128i test_mm_subs_epu8(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_subs_epu8
- // CHECK: call <16 x i8> @llvm.x86.sse2.psubus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK-NOT: call <16 x i8> @llvm.x86.sse2.psubus.b(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK: call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
return _mm_subs_epu8(A, B);
}
__m128i test_mm_subs_epu16(__m128i A, __m128i B) {
// CHECK-LABEL: test_mm_subs_epu16
- // CHECK: call <8 x i16> @llvm.x86.sse2.psubus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK-NOT: call <8 x i16> @llvm.x86.sse2.psubus.w(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
return _mm_subs_epu16(A, B);
}
diff --git a/test/CodeGen/stack-arg-probe.c b/test/CodeGen/stack-arg-probe.c
index d806db61c369..2ffe1f2862e3 100644
--- a/test/CodeGen/stack-arg-probe.c
+++ b/test/CodeGen/stack-arg-probe.c
@@ -1,8 +1,15 @@
// RUN: %clang_cc1 %s -triple=i686-windows-msvc -emit-llvm -o - -mno-stack-arg-probe | FileCheck %s -check-prefix=NO-STACKPROBE
+// RUN: %clang_cc1 %s -triple=x86_64-windows-msvc -emit-llvm -o - -mno-stack-arg-probe | FileCheck %s -check-prefix=NO-STACKPROBE
+// RUN: %clang_cc1 %s -triple=armv7-windows-msvc -emit-llvm -o - -mno-stack-arg-probe | FileCheck %s -check-prefix=NO-STACKPROBE
+// RUN: %clang_cc1 %s -triple=aarch64-windows-msvc -emit-llvm -o - -mno-stack-arg-probe | FileCheck %s -check-prefix=NO-STACKPROBE
// RUN: %clang_cc1 %s -triple=i686-windows-msvc -emit-llvm -o - | FileCheck %s -check-prefix=STACKPROBE
+// RUN: %clang_cc1 %s -triple=x86_64-windows-msvc -emit-llvm -o - | FileCheck %s -check-prefix=STACKPROBE
+// RUN: %clang_cc1 %s -triple=armv7-windows-msvc -emit-llvm -o - | FileCheck %s -check-prefix=STACKPROBE
+// RUN: %clang_cc1 %s -triple=aarch64-windows-msvc -emit-llvm -o - | FileCheck %s -check-prefix=STACKPROBE
+
// NO-STACKPROBE: attributes #{{[0-9]+}} = {{{.*}} "no-stack-arg-probe"
-// STACKPROBE-NOT: attributes #{{[0-9]+}} = {{{.*}} "no-stack-arg-probe"
+// STACKPROBE-NOT: "no-stack-arg-probe"
void test1() {
}
diff --git a/test/CodeGen/stackrealign-main.c b/test/CodeGen/stackrealign-main.c
new file mode 100644
index 000000000000..10b21bf548db
--- /dev/null
+++ b/test/CodeGen/stackrealign-main.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - -mstack-alignment=64 %s | FileCheck %s
+
+// CHECK-LABEL: define void @other()
+// CHECK: [[OTHER:#[0-9]+]]
+// CHECK: {
+void other(void) {}
+
+// CHECK-LABEL: define i32 @main(
+// CHECK: [[MAIN:#[0-9]+]]
+// CHECK: {
+int main(int argc, char **argv) {
+ other();
+ return 0;
+}
+
+// CHECK: attributes [[OTHER]] = { noinline nounwind optnone
+// CHECK-NOT: "stackrealign"
+// CHECK: }
+// CHECK: attributes [[MAIN]] = { noinline nounwind optnone {{.*}}"stackrealign"{{.*}} }
diff --git a/test/CodeGen/summary-index-unnamed-global.ll b/test/CodeGen/summary-index-unnamed-global.ll
new file mode 100644
index 000000000000..76485b8ede49
--- /dev/null
+++ b/test/CodeGen/summary-index-unnamed-global.ll
@@ -0,0 +1,11 @@
+; RUN: %clang_cc1 -flto -triple x86_64-pc-linux-gnu -emit-llvm-bc -disable-llvm-passes -x ir < %s -o - | llvm-bcanalyzer -dump | FileCheck %s
+; RUN: %clang_cc1 -flto=thin -triple x86_64-pc-linux-gnu -emit-llvm-bc -disable-llvm-passes -x ir < %s -o - | llvm-bcanalyzer -dump | FileCheck %s
+; RUN: %clang_cc1 -fexperimental-new-pass-manager -flto -triple x86_64-pc-linux-gnu -emit-llvm-bc -disable-llvm-passes -x ir < %s -o - | llvm-bcanalyzer -dump | FileCheck %s
+; RUN: %clang_cc1 -fexperimental-new-pass-manager -flto=thin -triple x86_64-pc-linux-gnu -emit-llvm-bc -disable-llvm-passes -x ir < %s -o - | llvm-bcanalyzer -dump | FileCheck %s
+; REQUIRES: x86-registered-target
+
+; CHECK-NOT:GLOBALVAL_SUMMARY_BLOCK
+
+; Make sure this doesn't crash, and we don't try to emit a module summary.
+; (The command is roughly emulating what -save-temps would do.)
+@0 = global i32 0
diff --git a/test/CodeGen/swift-call-conv.c b/test/CodeGen/swift-call-conv.c
new file mode 100644
index 000000000000..31d70b33a498
--- /dev/null
+++ b/test/CodeGen/swift-call-conv.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
+
+// REQUIRES: aarch64-registered-target,arm-registered-target,x86-registered-target
+
+void __attribute__((__swiftcall__)) f(void) {}
+// CHECK-LABEL: define dso_local swiftcc void @f()
+
diff --git a/test/CodeGen/target-builtin-noerror.c b/test/CodeGen/target-builtin-noerror.c
index 37820b33bada..400c5e696ad8 100644
--- a/test/CodeGen/target-builtin-noerror.c
+++ b/test/CodeGen/target-builtin-noerror.c
@@ -75,6 +75,11 @@ void verifyfeaturestrings() {
(void)__builtin_cpu_supports("avx5124vnniw");
(void)__builtin_cpu_supports("avx5124fmaps");
(void)__builtin_cpu_supports("avx512vpopcntdq");
+ (void)__builtin_cpu_supports("avx512vbmi2");
+ (void)__builtin_cpu_supports("gfni");
+ (void)__builtin_cpu_supports("vpclmulqdq");
+ (void)__builtin_cpu_supports("avx512vnni");
+ (void)__builtin_cpu_supports("avx512bitalg");
}
void verifycpustrings() {
@@ -95,7 +100,11 @@ void verifycpustrings() {
(void)__builtin_cpu_is("cannonlake");
(void)__builtin_cpu_is("core2");
(void)__builtin_cpu_is("corei7");
+ (void)__builtin_cpu_is("goldmont");
+ (void)__builtin_cpu_is("goldmont-plus");
(void)__builtin_cpu_is("haswell");
+ (void)__builtin_cpu_is("icelake-client");
+ (void)__builtin_cpu_is("icelake-server");
(void)__builtin_cpu_is("intel");
(void)__builtin_cpu_is("istanbul");
(void)__builtin_cpu_is("ivybridge");
@@ -108,6 +117,7 @@ void verifycpustrings() {
(void)__builtin_cpu_is("skylake");
(void)__builtin_cpu_is("skylake-avx512");
(void)__builtin_cpu_is("slm");
+ (void)__builtin_cpu_is("tremont");
(void)__builtin_cpu_is("westmere");
(void)__builtin_cpu_is("znver1");
}
diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c
index 2b990910920c..0c2b1e4cfff3 100644
--- a/test/CodeGen/target-data.c
+++ b/test/CodeGen/target-data.c
@@ -32,26 +32,54 @@
// RUN: %clang_cc1 -triple mipsel-linux-gnu -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=MIPS-32EL
+// RUN: %clang_cc1 -triple mipsisa32r6el-linux-gnu -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-32EL
// MIPS-32EL: target datalayout = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
// RUN: %clang_cc1 -triple mips-linux-gnu -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=MIPS-32EB
+// RUN: %clang_cc1 -triple mipsisa32r6-linux-gnu -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-32EB
// MIPS-32EB: target datalayout = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
// RUN: %clang_cc1 -triple mips64el-linux-gnu -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=MIPS-64EL
+// RUN: %clang_cc1 -triple mips64el-linux-gnuabi64 -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-64EL
+// RUN: %clang_cc1 -triple mipsisa64r6el-linux-gnu -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-64EL
+// RUN: %clang_cc1 -triple mipsisa64r6el-linux-gnuabi64 -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-64EL
// MIPS-64EL: target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128"
// RUN: %clang_cc1 -triple mips64el-linux-gnu -o - -emit-llvm -target-abi n32 \
// RUN: %s | FileCheck %s -check-prefix=MIPS-64EL-N32
+// RUN: %clang_cc1 -triple mips64el-linux-gnuabin32 -o - -emit-llvm \
+// RUN: %s | FileCheck %s -check-prefix=MIPS-64EL-N32
+// RUN: %clang_cc1 -triple mipsisa64r6el-linux-gnu -o - -emit-llvm -target-abi n32 \
+// RUN: %s | FileCheck %s -check-prefix=MIPS-64EL-N32
+// RUN: %clang_cc1 -triple mipsisa64r6el-linux-gnuabin32 -o - -emit-llvm \
+// RUN: %s | FileCheck %s -check-prefix=MIPS-64EL-N32
// MIPS-64EL-N32: target datalayout = "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"
// RUN: %clang_cc1 -triple mips64-linux-gnu -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=MIPS-64EB
+// RUN: %clang_cc1 -triple mips64-linux-gnuabi64 -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-64EB
+// RUN: %clang_cc1 -triple mipsisa64r6-linux-gnu -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-64EB
+// RUN: %clang_cc1 -triple mipsisa64r6-linux-gnuabi64 -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=MIPS-64EB
// MIPS-64EB: target datalayout = "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128"
// RUN: %clang_cc1 -triple mips64-linux-gnu -o - -emit-llvm %s -target-abi n32 \
// RUN: | FileCheck %s -check-prefix=MIPS-64EB-N32
+// RUN: %clang_cc1 -triple mips64-linux-gnuabin32 -o - -emit-llvm %s \
+// RUN: | FileCheck %s -check-prefix=MIPS-64EB-N32
+// RUN: %clang_cc1 -triple mipsisa64r6-linux-gnu -o - -emit-llvm %s -target-abi n32 \
+// RUN: | FileCheck %s -check-prefix=MIPS-64EB-N32
+// RUN: %clang_cc1 -triple mipsisa64r6-linux-gnuabin32 -o - -emit-llvm %s \
+// RUN: | FileCheck %s -check-prefix=MIPS-64EB-N32
// MIPS-64EB-N32: target datalayout = "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"
// RUN: %clang_cc1 -triple powerpc64-lv2 -o - -emit-llvm %s | \
@@ -106,14 +134,6 @@
// RUN: FileCheck %s -check-prefix=PPC64LE-LINUX
// PPC64LE-LINUX: target datalayout = "e-m:e-i64:64-n32:64"
-// RUN: %clang_cc1 -triple powerpc-darwin -o - -emit-llvm %s | \
-// RUN: FileCheck %s -check-prefix=PPC32-DARWIN
-// PPC32-DARWIN: target datalayout = "E-m:o-p:32:32-f64:32:64-n32"
-
-// RUN: %clang_cc1 -triple powerpc64-darwin -o - -emit-llvm %s | \
-// RUN: FileCheck %s -check-prefix=PPC64-DARWIN
-// PPC64-DARWIN: target datalayout = "E-m:o-i64:64-n32:64"
-
// RUN: %clang_cc1 -triple nvptx-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=NVPTX
// NVPTX: target datalayout = "e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64"
@@ -159,6 +179,10 @@
// RUN: %s | FileCheck %s -check-prefix=ARM-GNU
// ARM-GNU: target datalayout = "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+// RUN: %clang_cc1 -triple arc-unknown-unknown -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=ARC
+// ARC: target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32"
+
// RUN: %clang_cc1 -triple hexagon-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=HEXAGON
// HEXAGON: target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
diff --git a/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll b/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll
index 09a2ec890ff9..2d25930e508b 100644
--- a/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll
+++ b/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll
@@ -19,9 +19,10 @@
; YAML-NEXT: - Callee: tinkywinky
; YAML-NEXT: - String: ' inlined into '
; YAML-NEXT: - Caller: main
-; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - String: ' with '
+; YAML-NEXT: - String: '(cost='
; YAML-NEXT: - Cost: '0'
-; YAML-NEXT: - String: ' (threshold='
+; YAML-NEXT: - String: ', threshold='
; YAML-NEXT: - Threshold: '337'
; YAML-NEXT: - String: ')'
; YAML-NEXT: ...
@@ -29,7 +30,7 @@
; Next try with pass remarks to stderr
; RUN: %clang -target x86_64-scei-ps4 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -mllvm -pass-remarks=inline -fdiagnostics-show-hotness -o %t2.o -c 2>&1 | FileCheck %s
-; CHECK: tinkywinky inlined into main with cost=0 (threshold=337) (hotness: 300)
+; CHECK: tinkywinky inlined into main with (cost=0, threshold=337) (hotness: 300)
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-scei-ps4"
diff --git a/test/CodeGen/thinlto-distributed-cfi-devirt.ll b/test/CodeGen/thinlto-distributed-cfi-devirt.ll
index ab33a59b6982..2ecf149b061d 100644
--- a/test/CodeGen/thinlto-distributed-cfi-devirt.ll
+++ b/test/CodeGen/thinlto-distributed-cfi-devirt.ll
@@ -4,9 +4,11 @@
; It additionally enables -fwhole-program-vtables to get more information in
; TYPE_IDs of GLOBALVAL_SUMMARY_BLOCK.
-; RUN: opt -thinlto-bc -o %t.o %s
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s
+; FIXME: Fix machine verifier issues and remove -verify-machineinstrs=0. PR39436.
; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
+; RUN: -verify-machineinstrs=0 \
; RUN: -o %t2.index \
; RUN: -r=%t.o,test,px \
; RUN: -r=%t.o,_ZN1A1nEi,p \
diff --git a/test/CodeGen/thinlto-distributed-cfi.ll b/test/CodeGen/thinlto-distributed-cfi.ll
index 055b5971eb23..b2ede5395d1a 100644
--- a/test/CodeGen/thinlto-distributed-cfi.ll
+++ b/test/CodeGen/thinlto-distributed-cfi.ll
@@ -2,7 +2,7 @@
; Backend test for distribute ThinLTO with CFI.
-; RUN: opt -thinlto-bc -o %t.o %s
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s
; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
; RUN: -o %t2.index \
diff --git a/test/CodeGen/thinlto_backend.ll b/test/CodeGen/thinlto_backend.ll
index 5ba846457dfd..2dd919d5f7de 100644
--- a/test/CodeGen/thinlto_backend.ll
+++ b/test/CodeGen/thinlto_backend.ll
@@ -25,7 +25,8 @@
; be empty file.
; RUN: opt -o %t5.o %s
; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t4.o -x ir %t5.o -c -fthinlto-index=%t.thinlto.bc
-; RUN: llvm-nm %t4.o | count 0
+; RUN: llvm-nm %t4.o 2>&1 | FileCheck %s -check-prefix=NO-SYMBOLS
+; NO-SYMBOLS: no symbols
; Ensure f2 was imported. Check for all 3 flavors of -save-temps[=cwd|obj].
; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=%t.thinlto.bc -save-temps=obj
diff --git a/test/CodeGen/thinlto_backend_local_name_conflict.ll b/test/CodeGen/thinlto_backend_local_name_conflict.ll
new file mode 100644
index 000000000000..cefbc51bf05c
--- /dev/null
+++ b/test/CodeGen/thinlto_backend_local_name_conflict.ll
@@ -0,0 +1,36 @@
+; Test handling when two files with the same source file name contain
+; static read only variables with the same name (which will have the same GUID
+; in the combined index).
+
+; REQUIRES: x86-registered-target
+
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary -module-hash %s -o %t.bc
+; RUN: opt -module-summary -module-hash %p/Inputs/thinlto_backend_local_name_conflict1.ll -o %t2.bc
+; RUN: opt -module-summary -module-hash %p/Inputs/thinlto_backend_local_name_conflict2.ll -o %t3.bc
+; RUN: llvm-lto -thinlto-action=thinlink -o %t4.bc %t.bc %t2.bc %t3.bc
+; RUN: llvm-lto -thinlto-action=distributedindexes -exported-symbol=main -thinlto-index=%t4.bc %t.bc
+
+; This module will import a() and b() which should cause the read only copy
+; of baz from each of those modules to be imported. Check that the both are
+; imported as local copies.
+; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t4.o -x ir %t.bc -c -fthinlto-index=%t.bc.thinlto.bc -save-temps=obj
+; RUN: llvm-dis %t.s.3.import.bc -o - | FileCheck --check-prefix=IMPORT %s
+; IMPORT: @baz.llvm.{{.*}} = internal global i32 10
+; IMPORT: @baz.llvm.{{.*}} = internal global i32 10
+
+; ModuleID = 'local_name_conflict_var_main.o'
+source_filename = "local_name_conflict_var_main.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: noinline nounwind uwtable
+define i32 @main() {
+entry:
+ %call1 = call i32 (...) @a()
+ %call2 = call i32 (...) @b()
+ ret i32 0
+}
+
+declare i32 @a(...)
+declare i32 @b(...)
diff --git a/test/CodeGen/tsan-instrprof-atomic.c b/test/CodeGen/tsan-instrprof-atomic.c
new file mode 100644
index 000000000000..9519cb7eb8ed
--- /dev/null
+++ b/test/CodeGen/tsan-instrprof-atomic.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 %s -emit-llvm -fprofile-instrument=clang -fsanitize=thread -o - | FileCheck %s
+
+// CHECK: define {{.*}}@foo
+// CHECK-NOT: load {{.*}}foo
+// CHECK: ret void
+void foo() {}
diff --git a/test/CodeGen/ubsan-debuglog-return.c b/test/CodeGen/ubsan-debuglog-return.c
new file mode 100644
index 000000000000..23a1326934de
--- /dev/null
+++ b/test/CodeGen/ubsan-debuglog-return.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x c -debug-info-kind=line-tables-only -emit-llvm -fsanitize=returns-nonnull-attribute -o - %s | FileCheck %s
+// The UBSAN function call in the epilogue needs to have a debug location.
+
+__attribute__((returns_nonnull)) void *allocate() {}
+
+// CHECK: define {{.*}}nonnull i8* @allocate(){{.*}} !dbg
+// CHECK: call void @__ubsan_handle_nonnull_return_v1_abort
+// CHECK-SAME: !dbg ![[LOC:[0-9]+]]
+// CHECK: ret i8*
+// CHECK-SAME: !dbg ![[LOC]]
diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c
index c79cd84f7e2e..f128c8a321bd 100644
--- a/test/CodeGen/vector.c
+++ b/test/CodeGen/vector.c
@@ -70,7 +70,7 @@ vec_int1 lax_vector_compare1(int x, vec_int1 y) {
}
// CHECK: define i32 @lax_vector_compare1(i32 {{.*}}, i32 {{.*}})
-// CHECK: icmp eq <1 x i32>
+// CHECK: icmp eq i32
typedef int vec_int2 __attribute__((vector_size(8)));
vec_int2 lax_vector_compare2(long long x, vec_int2 y) {
diff --git a/test/CodeGen/wasm-arguments.c b/test/CodeGen/wasm-arguments.c
index 9283dd5d15f9..cd3f45ab1a7e 100644
--- a/test/CodeGen/wasm-arguments.c
+++ b/test/CodeGen/wasm-arguments.c
@@ -54,7 +54,6 @@ void f5(char a, short b) {}
// WEBASSEMBLY64: define void @f6(i8 zeroext %a, i16 zeroext %b)
void f6(unsigned char a, unsigned short b) {}
-
enum my_enum {
ENUM1,
ENUM2,
diff --git a/test/CodeGen/wasm-varargs.c b/test/CodeGen/wasm-varargs.c
index acbd590cc25c..4cb46f1c1908 100644
--- a/test/CodeGen/wasm-varargs.c
+++ b/test/CodeGen/wasm-varargs.c
@@ -65,9 +65,9 @@ long long test_i64(char *fmt, ...) {
// CHECK: }
struct S {
- int x;
- int y;
- int z;
+ int x;
+ int y;
+ int z;
};
struct S test_struct(char *fmt, ...) {
diff --git a/test/CodeGen/win64-i128.c b/test/CodeGen/win64-i128.c
new file mode 100644
index 000000000000..0514c4846c24
--- /dev/null
+++ b/test/CodeGen/win64-i128.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=GNU64
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=MSC64
+
+typedef int int128_t __attribute__((mode(TI)));
+
+int128_t foo() { return 0; }
+
+// GNU64: define dso_local <2 x i64> @foo()
+// MSC64: define dso_local <2 x i64> @foo()
+
+int128_t bar(int128_t a, int128_t b) { return a * b; }
+
+// GNU64: define dso_local <2 x i64> @bar(i128*, i128*)
+// MSC64: define dso_local <2 x i64> @bar(i128*, i128*)
diff --git a/test/CodeGen/windows-swiftcall.c b/test/CodeGen/windows-swiftcall.c
index d8fdec47aa24..98fb3bd4b518 100644
--- a/test/CodeGen/windows-swiftcall.c
+++ b/test/CodeGen/windows-swiftcall.c
@@ -5,7 +5,7 @@
#define ERROR __attribute__((swift_error_result))
#define CONTEXT __attribute__((swift_context))
-// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, float 0.000000e+00, float 0.000000e+00 }
+// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, i32 0, i32 0 }
/*****************************************************************************/
/****************************** PARAMETER ABIS *******************************/
@@ -93,8 +93,8 @@ typedef struct {
int x;
char c0;
char c1;
- float f0;
- float f1;
+ int f0;
+ int f1;
} struct_1;
TEST(struct_1);
// CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_1() {{.*}}{
@@ -141,8 +141,8 @@ typedef struct {
int x;
char c0;
__attribute__((aligned(2))) char c1;
- float f0;
- float f1;
+ int f0;
+ int f1;
} struct_2;
TEST(struct_2);
// CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_2() {{.*}}{
@@ -299,20 +299,30 @@ typedef union {
TEST(union_hom_fp_partial)
// CHECK: define dso_local void @test_union_hom_fp_partial()
// CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_hom_fp_partial()
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
-// CHECK: store i64 [[T1]], i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK: store i64 [[T1]], i64* [[T0]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK: call swiftcc void @take_union_hom_fp_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: [[CALL:%.*]] = call swiftcc { float, float, float, float } @return_union_hom_fp_partial()
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 0
+// CHECK: store float [[T1]], float* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 1
+// CHECK: store float [[T1]], float* [[T0]], align 4
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 2
+// CHECK: store float [[T1]], float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 3
+// CHECK: store float [[T1]], float* [[T0]], align 4
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load float, float* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load float, float* [[T0]], align 4
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[V2:%.*]] = load float, float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK: [[V3:%.*]] = load float, float* [[T0]], align 4
+// CHECK: call swiftcc void @take_union_hom_fp_partial(float [[V0]], float [[V1]], float [[V2]], float [[V3]])
// CHECK: ret void
// CHECK: }
@@ -323,20 +333,25 @@ typedef union {
TEST(union_het_fpv_partial)
// CHECK-LABEL: define dso_local void @test_union_het_fpv_partial()
// CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_het_fpv_partial()
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: [[CALL:%.*]] = call swiftcc { i64, float, float } @return_union_het_fpv_partial()
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 0
// CHECK: store i64 [[T1]], i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK: store i64 [[T1]], i64* [[T0]], align 8
-// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 1
+// CHECK: store float [[T1]], float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 2
+// CHECK: store float [[T1]], float* [[T0]], align 4
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load float, float* [[T0]], align 8
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK: [[V2:%.*]] = load float, float* [[T0]], align 4
+// CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], float [[V1]], float [[V2]])
// CHECK: ret void
// CHECK: }
diff --git a/test/CodeGen/x86-inline-asm-min-vector-width.c b/test/CodeGen/x86-inline-asm-min-vector-width.c
new file mode 100644
index 000000000000..8d08ca0c6f9a
--- /dev/null
+++ b/test/CodeGen/x86-inline-asm-min-vector-width.c
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-feature +avx512f -o - | FileCheck %s
+
+typedef long long __m128i __attribute__ ((vector_size (16)));
+typedef long long __m256i __attribute__ ((vector_size (32)));
+typedef long long __m512i __attribute__ ((vector_size (64)));
+
+// CHECK: define <2 x i64> @testXMMout(<2 x i64>* %p) #0
+__m128i testXMMout(__m128i *p) {
+ __m128i xmm0;
+ __asm__("vmovdqu %1, %0" :"=v"(xmm0) : "m"(*(__m128i*)p));
+ return xmm0;
+}
+
+// CHECK: define <4 x i64> @testYMMout(<4 x i64>* %p) #1
+__m256i testYMMout(__m256i *p) {
+ __m256i ymm0;
+ __asm__("vmovdqu %1, %0" :"=v"(ymm0) : "m"(*(__m256i*)p));
+ return ymm0;
+}
+
+// CHECK: define <8 x i64> @testZMMout(<8 x i64>* %p) #2
+__m512i testZMMout(__m512i *p) {
+ __m512i zmm0;
+ __asm__("vmovdqu64 %1, %0" :"=v"(zmm0) : "m"(*(__m512i*)p));
+ return zmm0;
+}
+
+// CHECK: define void @testXMMin(<2 x i64> %xmm0, <2 x i64>* %p) #0
+void testXMMin(__m128i xmm0, __m128i *p) {
+ __asm__("vmovdqu %0, %1" : : "v"(xmm0), "m"(*(__m128i*)p));
+}
+
+// CHECK: define void @testYMMin(<4 x i64> %ymm0, <4 x i64>* %p) #1
+void testYMMin(__m256i ymm0, __m256i *p) {
+ __asm__("vmovdqu %0, %1" : : "v"(ymm0), "m"(*(__m256i*)p));
+}
+
+// CHECK: define void @testZMMin(<8 x i64> %zmm0, <8 x i64>* %p) #2
+void testZMMin(__m512i zmm0, __m512i *p) {
+ __asm__("vmovdqu64 %0, %1" : : "v"(zmm0), "m"(*(__m512i*)p));
+}
+
+// CHECK: attributes #0 = {{.*}}"min-legal-vector-width"="128"
+// CHECK: attributes #1 = {{.*}}"min-legal-vector-width"="256"
+// CHECK: attributes #2 = {{.*}}"min-legal-vector-width"="512"
diff --git a/test/CodeGen/x86-vector-width.c b/test/CodeGen/x86-vector-width.c
new file mode 100644
index 000000000000..7e03fedb7846
--- /dev/null
+++ b/test/CodeGen/x86-vector-width.c
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu i686 -emit-llvm %s -o - | FileCheck %s
+
+typedef signed long long V2LLi __attribute__((vector_size(16)));
+typedef signed long long V4LLi __attribute__((vector_size(32)));
+
+V2LLi ret_128();
+V4LLi ret_256();
+void arg_128(V2LLi);
+void arg_256(V4LLi);
+
+// Make sure return type forces a min-legal-width
+V2LLi foo(void) {
+ return (V2LLi){ 0, 0 };
+}
+
+V4LLi goo(void) {
+ return (V4LLi){ 0, 0 };
+}
+
+// Make sure return type of called function forces a min-legal-width
+void hoo(void) {
+ V2LLi tmp_V2LLi;
+ tmp_V2LLi = ret_128();
+}
+
+void joo(void) {
+ V4LLi tmp_V4LLi;
+ tmp_V4LLi = ret_256();
+}
+
+// Make sure arg type of called function forces a min-legal-width
+void koo(void) {
+ V2LLi tmp_V2LLi;
+ arg_128(tmp_V2LLi);
+}
+
+void loo(void) {
+ V4LLi tmp_V4LLi;
+ arg_256(tmp_V4LLi);
+}
+
+// Make sure arg type of our function forces a min-legal-width
+void moo(V2LLi x) {
+
+}
+
+void noo(V4LLi x) {
+
+}
+
+// CHECK: {{.*}}@foo{{.*}} #0
+// CHECK: {{.*}}@goo{{.*}} #1
+// CHECK: {{.*}}@hoo{{.*}} #0
+// CHECK: {{.*}}@joo{{.*}} #1
+// CHECK: {{.*}}@koo{{.*}} #0
+// CHECK: {{.*}}@loo{{.*}} #1
+// CHECK: {{.*}}@moo{{.*}} #0
+// CHECK: {{.*}}@noo{{.*}} #1
+
+// CHECK: #0 = {{.*}}"min-legal-vector-width"="128"
+// CHECK: #1 = {{.*}}"min-legal-vector-width"="256"
diff --git a/test/CodeGen/xop-builtins.c b/test/CodeGen/xop-builtins.c
index 5302b9ab8f2f..e6a09007f7b8 100644
--- a/test/CodeGen/xop-builtins.c
+++ b/test/CodeGen/xop-builtins.c
@@ -194,49 +194,49 @@ __m128i test_mm_perm_epi8(__m128i a, __m128i b, __m128i c) {
__m128i test_mm_rot_epi8(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_rot_epi8
- // CHECK: call <16 x i8> @llvm.x86.xop.vprotb(<16 x i8> %{{.*}}, <16 x i8> %{{.*}})
+ // CHECK: call <16 x i8> @llvm.fshl.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}})
return _mm_rot_epi8(a, b);
}
__m128i test_mm_rot_epi16(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_rot_epi16
- // CHECK: call <8 x i16> @llvm.x86.xop.vprotw(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+ // CHECK: call <8 x i16> @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
return _mm_rot_epi16(a, b);
}
__m128i test_mm_rot_epi32(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_rot_epi32
- // CHECK: call <4 x i32> @llvm.x86.xop.vprotd(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
+ // CHECK: call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_rot_epi32(a, b);
}
__m128i test_mm_rot_epi64(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_rot_epi64
- // CHECK: call <2 x i64> @llvm.x86.xop.vprotq(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
+ // CHECK: call <2 x i64> @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}})
return _mm_rot_epi64(a, b);
}
__m128i test_mm_roti_epi8(__m128i a) {
// CHECK-LABEL: test_mm_roti_epi8
- // CHECK: call <16 x i8> @llvm.x86.xop.vprotbi(<16 x i8> %{{.*}}, i8 1)
+ // CHECK: call <16 x i8> @llvm.fshl.v16i8(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
return _mm_roti_epi8(a, 1);
}
__m128i test_mm_roti_epi16(__m128i a) {
// CHECK-LABEL: test_mm_roti_epi16
- // CHECK: call <8 x i16> @llvm.x86.xop.vprotwi(<8 x i16> %{{.*}}, i8 50)
+ // CHECK: call <8 x i16> @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> <i16 50, i16 50, i16 50, i16 50, i16 50, i16 50, i16 50, i16 50>)
return _mm_roti_epi16(a, 50);
}
__m128i test_mm_roti_epi32(__m128i a) {
// CHECK-LABEL: test_mm_roti_epi32
- // CHECK: call <4 x i32> @llvm.x86.xop.vprotdi(<4 x i32> %{{.*}}, i8 -30)
+ // CHECK: call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 226, i32 226, i32 226, i32 226>)
return _mm_roti_epi32(a, -30);
}
__m128i test_mm_roti_epi64(__m128i a) {
// CHECK-LABEL: test_mm_roti_epi64
- // CHECK: call <2 x i64> @llvm.x86.xop.vprotqi(<2 x i64> %{{.*}}, i8 100)
+ // CHECK: call <2 x i64> @llvm.fshl.v2i64(<2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> <i64 100, i64 100>)
return _mm_roti_epi64(a, 100);
}
diff --git a/test/CodeGen/xray-attributes-noxray-supported.cpp b/test/CodeGen/xray-attributes-noxray-supported.cpp
new file mode 100644
index 000000000000..f9c8a2ee6927
--- /dev/null
+++ b/test/CodeGen/xray-attributes-noxray-supported.cpp
@@ -0,0 +1,29 @@
+// We want to ensure that the "never instrument" attributes show up even if we
+// explicitly turn off XRay instrumentation.
+//
+// RUN: %clang_cc1 %s -fno-xray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fno-xray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple arm-unknown-linux-gnu -target-abi apcs-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fno-xray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fno-xray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsel-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fno-xray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fno-xray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64el-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fno-xray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple powerpc64le-unknown-linux-gnu | FileCheck %s
+
+[[clang::xray_always_instrument]] void foo() {
+// CHECK: define void @_Z3foov() #0
+}
+
+[[clang::xray_never_instrument]] void bar() {
+// CHECK: define void @_Z3barv() #1
+}
+
+// CHECK-NOT: #0 = {{.*}}"function-instrument"="xray-always"
+// CHECK: #1 = {{.*}}"function-instrument"="xray-never"
+
diff --git a/test/CodeGen/xray-attributes-supported.cpp b/test/CodeGen/xray-attributes-supported.cpp
index 21a5dde53a05..c2ee70822adb 100644
--- a/test/CodeGen/xray-attributes-supported.cpp
+++ b/test/CodeGen/xray-attributes-supported.cpp
@@ -1,10 +1,41 @@
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple x86_64-unknown-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple arm-unknown-linux-gnu -target-abi apcs-gnu | FileCheck %s
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mips-unknown-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mipsel-unknown-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mips64-unknown-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple mips64el-unknown-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple powerpc64le-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple arm-unknown-linux-gnu -target-abi apcs-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa32r6-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsel-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa32r6el-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa64r6-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64el-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa64r6el-unknown-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64-unknown-linux-gnuabi64 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa64r6-unknown-linux-gnuabi64 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64el-unknown-linux-gnuabi64 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa64r6el-unknown-linux-gnuabi64 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64-unknown-linux-gnuabin32 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa64r6-unknown-linux-gnuabin32 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mips64el-unknown-linux-gnuabin32 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple mipsisa64r6el-unknown-linux-gnuabin32 | FileCheck %s
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - \
+// RUN: -triple powerpc64le-unknown-linux-gnu | FileCheck %s
// Make sure that the LLVM attribute for XRay-annotated functions do show up.
[[clang::xray_always_instrument]] void foo() {
diff --git a/test/CodeGenCUDA/builtins-amdgcn.cu b/test/CodeGenCUDA/builtins-amdgcn.cu
new file mode 100644
index 000000000000..82a666717ac7
--- /dev/null
+++ b/test/CodeGenCUDA/builtins-amdgcn.cu
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple amdgcn -fcuda-is-device -emit-llvm %s -o - | FileCheck %s
+#include "Inputs/cuda.h"
+
+// CHECK-LABEL: @_Z16use_dispatch_ptrPi(
+// CHECK: %2 = call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr()
+// CHECK: %3 = addrspacecast i8 addrspace(4)* %2 to i8 addrspace(4)**
+__global__ void use_dispatch_ptr(int* out) {
+ const int* dispatch_ptr = (const int*)__builtin_amdgcn_dispatch_ptr();
+ *out = *dispatch_ptr;
+}
+
+// CHECK-LABEL: @_Z12test_ds_fmaxf(
+// CHECK: call float @llvm.amdgcn.ds.fmax(float addrspace(3)* @_ZZ12test_ds_fmaxfE6shared, float %2, i32 0, i32 0, i1 false)
+__global__
+void test_ds_fmax(float src) {
+ __shared__ float shared;
+ volatile float x = __builtin_amdgcn_ds_fmaxf(&shared, src, 0, 0, false);
+}
diff --git a/test/CodeGenCUDA/device-stub.cu b/test/CodeGenCUDA/device-stub.cu
index 716381b7a826..ea45c391d20c 100644
--- a/test/CodeGenCUDA/device-stub.cu
+++ b/test/CodeGenCUDA/device-stub.cu
@@ -6,22 +6,22 @@
// RUN: -fcuda-include-gpubinary %t -o - -DNOGLOBALS \
// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=NOGLOBALS,CUDANOGLOBALS
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
-// RUN: -fcuda-rdc -fcuda-include-gpubinary %t -o - \
+// RUN: -fgpu-rdc -fcuda-include-gpubinary %t -o - \
// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,RDC,CUDA,CUDARDC
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - \
// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=NOGPUBIN
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
// RUN: -fcuda-include-gpubinary %t -o - -x hip\
-// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP,HIPEF
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
// RUN: -fcuda-include-gpubinary %t -o - -DNOGLOBALS -x hip \
// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=NOGLOBALS,HIPNOGLOBALS
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \
-// RUN: -fcuda-rdc -fcuda-include-gpubinary %t -o - -x hip \
-// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP
+// RUN: -fgpu-rdc -fcuda-include-gpubinary %t -o - -x hip \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP,HIPEF
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - -x hip\
-// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=NOGPUBIN
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=ALL,NORDC,HIP,HIPNEF
#include "Inputs/cuda.h"
@@ -42,13 +42,20 @@ int host_var;
// ALL-DAG: @ext_host_var = external global i32
extern int ext_host_var;
-// Shadows for external device-side variables are *definitions* of
-// those variables.
-// ALL-DAG: @ext_device_var = internal global i32
+// external device-side variables -> extern references to their shadows.
+// ALL-DAG: @ext_device_var = external global i32
extern __device__ int ext_device_var;
-// ALL-DAG: @ext_device_var = internal global i32
+// ALL-DAG: @ext_device_var = external global i32
extern __constant__ int ext_constant_var;
+// external device-side variables with definitions should generate
+// definitions for the shadows.
+// ALL-DAG: @ext_device_var_def = internal global i32 undef,
+extern __device__ int ext_device_var_def;
+__device__ int ext_device_var_def = 1;
+// ALL-DAG: @ext_device_var_def = internal global i32 undef,
+__constant__ int ext_constant_var_def = 2;
+
void use_pointers() {
int *p;
p = &device_var;
@@ -64,8 +71,9 @@ void use_pointers() {
// * constant unnamed string with the kernel name
// ALL: private unnamed_addr constant{{.*}}kernelfunc{{.*}}\00"
// * constant unnamed string with GPU binary
-// HIP: @[[FATBIN:__hip_fatbin]] = external constant i8, section ".hip_fatbin"
// CUDA: @[[FATBIN:.*]] = private constant{{.*GPU binary would be here.*}}\00",
+// HIPEF: @[[FATBIN:.*]] = private constant{{.*GPU binary would be here.*}}\00",
+// HIPNEF: @[[FATBIN:__hip_fatbin]] = external constant i8, section ".hip_fatbin"
// CUDANORDC-SAME: section ".nv_fatbin", align 8
// CUDARDC-SAME: section "__nv_relfatbin", align 8
// * constant struct that wraps GPU binary
@@ -74,13 +82,14 @@ void use_pointers() {
// CUDA-SAME: { i32 1180844977, i32 1,
// HIP-SAME: { i32 1212764230, i32 1,
// CUDA-SAME: i8* getelementptr inbounds ({{.*}}@[[FATBIN]], i64 0, i64 0),
-// HIP-SAME: i8* @[[FATBIN]],
+// HIPEF-SAME: i8* getelementptr inbounds ({{.*}}@[[FATBIN]], i64 0, i64 0),
+// HIPNEF-SAME: i8* @[[FATBIN]],
// ALL-SAME: i8* null }
// CUDA-SAME: section ".nvFatBinSegment"
// HIP-SAME: section ".hipFatBinSegment"
// * variable to save GPU binary handle after initialization
// CUDANORDC: @__[[PREFIX]]_gpubin_handle = internal global i8** null
-// HIP: @__[[PREFIX]]_gpubin_handle = linkonce global i8** null
+// HIPNEF: @__[[PREFIX]]_gpubin_handle = linkonce hidden global i8** null
// * constant unnamed string with NVModuleID
// RDC: [[MODULE_ID_GLOBAL:@.*]] = private constant
// CUDARDC-SAME: c"[[MODULE_ID:.+]]\00", section "__nv_module_id", align 32
@@ -112,8 +121,8 @@ void hostfunc(void) { kernelfunc<<<1, 1>>>(1, 1, 1); }
// ALL: call{{.*}}[[PREFIX]]RegisterFunction(i8** %0, {{.*}}kernelfunc
// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}device_var{{.*}}i32 0, i32 4, i32 0, i32 0
// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}constant_var{{.*}}i32 0, i32 4, i32 1, i32 0
-// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}ext_device_var{{.*}}i32 1, i32 4, i32 0, i32 0
-// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}ext_constant_var{{.*}}i32 1, i32 4, i32 1, i32 0
+// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}ext_device_var_def{{.*}}i32 0, i32 4, i32 0, i32 0
+// ALL-DAG: call{{.*}}[[PREFIX]]RegisterVar(i8** %0, {{.*}}ext_constant_var_def{{.*}}i32 0, i32 4, i32 1, i32 0
// ALL: ret void
// Test that we've built a constructor.
@@ -157,7 +166,7 @@ void hostfunc(void) { kernelfunc<<<1, 1>>>(1, 1, 1); }
// device-side globals, but we still need to register GPU binary.
// Skip GPU binary string first.
// CUDANOGLOBALS: @{{.*}} = private constant{{.*}}
-// HIPNOGLOBALS: @{{.*}} = external constant{{.*}}
+// HIPNOGLOBALS: @{{.*}} = internal constant{{.*}}
// NOGLOBALS-NOT: define internal void @__{{.*}}_register_globals
// NOGLOBALS: define internal void @__[[PREFIX:cuda|hip]]_module_ctor
// NOGLOBALS: call{{.*}}[[PREFIX]]RegisterFatBinary{{.*}}__[[PREFIX]]_fatbin_wrapper
diff --git a/test/CodeGenCUDA/device-var-init.cu b/test/CodeGenCUDA/device-var-init.cu
index f96e42d9711c..af42e698cfe9 100644
--- a/test/CodeGenCUDA/device-var-init.cu
+++ b/test/CodeGenCUDA/device-var-init.cu
@@ -5,10 +5,12 @@
// variables, but accept empty constructors allowed by CUDA.
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fcuda-is-device -std=c++11 \
-// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,NVPTX %s
+// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck -check-prefixes=DEVICE,NVPTX %s
+// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -std=c++11 \
+// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck -check-prefixes=HOST %s
// RUN: %clang_cc1 -triple amdgcn -fcuda-is-device -std=c++11 \
-// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,AMDGCN %s
+// RUN: -fno-threadsafe-statics -emit-llvm -o - %s | FileCheck -check-prefixes=DEVICE,AMDGCN %s
#ifdef __clang__
#include "Inputs/cuda.h"
@@ -18,105 +20,140 @@
#include "Inputs/cuda-initializers.h"
__device__ int d_v;
-// CHECK: @d_v = addrspace(1) externally_initialized global i32 0,
+// DEVICE: @d_v = addrspace(1) externally_initialized global i32 0,
+// HOST: @d_v = internal global i32 undef,
__shared__ int s_v;
-// CHECK: @s_v = addrspace(3) global i32 undef,
+// DEVICE: @s_v = addrspace(3) global i32 undef,
+// HOST: @s_v = internal global i32 undef,
__constant__ int c_v;
-// CHECK: addrspace(4) externally_initialized global i32 0,
+// DEVICE: addrspace(4) externally_initialized global i32 0,
+// HOST: @c_v = internal global i32 undef,
__device__ int d_v_i = 1;
-// CHECK: @d_v_i = addrspace(1) externally_initialized global i32 1,
+// DEVICE: @d_v_i = addrspace(1) externally_initialized global i32 1,
+// HOST: @d_v_i = internal global i32 undef,
// trivial constructor -- allowed
__device__ T d_t;
-// CHECK: @d_t = addrspace(1) externally_initialized global %struct.T zeroinitializer
+// DEVICE: @d_t = addrspace(1) externally_initialized global %struct.T zeroinitializer
+// HOST: @d_t = internal global %struct.T undef,
__shared__ T s_t;
-// CHECK: @s_t = addrspace(3) global %struct.T undef,
+// DEVICE: @s_t = addrspace(3) global %struct.T undef,
+// HOST: @s_t = internal global %struct.T undef,
__constant__ T c_t;
-// CHECK: @c_t = addrspace(4) externally_initialized global %struct.T zeroinitializer,
+// DEVICE: @c_t = addrspace(4) externally_initialized global %struct.T zeroinitializer,
+// HOST: @c_t = internal global %struct.T undef,
__device__ T d_t_i = {2};
-// CHECK: @d_t_i = addrspace(1) externally_initialized global %struct.T { i32 2 },
+// DEVICE: @d_t_i = addrspace(1) externally_initialized global %struct.T { i32 2 },
+// HOST: @d_t_i = internal global %struct.T undef,
__constant__ T c_t_i = {2};
-// CHECK: @c_t_i = addrspace(4) externally_initialized global %struct.T { i32 2 },
+// DEVICE: @c_t_i = addrspace(4) externally_initialized global %struct.T { i32 2 },
+// HOST: @c_t_i = internal global %struct.T undef,
// empty constructor
__device__ EC d_ec;
-// CHECK: @d_ec = addrspace(1) externally_initialized global %struct.EC zeroinitializer,
+// DEVICE: @d_ec = addrspace(1) externally_initialized global %struct.EC zeroinitializer,
+// HOST: @d_ec = internal global %struct.EC undef,
__shared__ EC s_ec;
-// CHECK: @s_ec = addrspace(3) global %struct.EC undef,
+// DEVICE: @s_ec = addrspace(3) global %struct.EC undef,
+// HOST: @s_ec = internal global %struct.EC undef,
__constant__ EC c_ec;
-// CHECK: @c_ec = addrspace(4) externally_initialized global %struct.EC zeroinitializer,
+// DEVICE: @c_ec = addrspace(4) externally_initialized global %struct.EC zeroinitializer,
+// HOST: @c_ec = internal global %struct.EC undef
// empty destructor
__device__ ED d_ed;
-// CHECK: @d_ed = addrspace(1) externally_initialized global %struct.ED zeroinitializer,
+// DEVICE: @d_ed = addrspace(1) externally_initialized global %struct.ED zeroinitializer,
+// HOST: @d_ed = internal global %struct.ED undef,
__shared__ ED s_ed;
-// CHECK: @s_ed = addrspace(3) global %struct.ED undef,
+// DEVICE: @s_ed = addrspace(3) global %struct.ED undef,
+// HOST: @s_ed = internal global %struct.ED undef,
__constant__ ED c_ed;
-// CHECK: @c_ed = addrspace(4) externally_initialized global %struct.ED zeroinitializer,
+// DEVICE: @c_ed = addrspace(4) externally_initialized global %struct.ED zeroinitializer,
+// HOST: @c_ed = internal global %struct.ED undef,
__device__ ECD d_ecd;
-// CHECK: @d_ecd = addrspace(1) externally_initialized global %struct.ECD zeroinitializer,
+// DEVICE: @d_ecd = addrspace(1) externally_initialized global %struct.ECD zeroinitializer,
+// HOST: @d_ecd = internal global %struct.ECD undef,
__shared__ ECD s_ecd;
-// CHECK: @s_ecd = addrspace(3) global %struct.ECD undef,
+// DEVICE: @s_ecd = addrspace(3) global %struct.ECD undef,
+// HOST: @s_ecd = internal global %struct.ECD undef,
__constant__ ECD c_ecd;
-// CHECK: @c_ecd = addrspace(4) externally_initialized global %struct.ECD zeroinitializer,
+// DEVICE: @c_ecd = addrspace(4) externally_initialized global %struct.ECD zeroinitializer,
+// HOST: @c_ecd = internal global %struct.ECD undef,
// empty templated constructor -- allowed with no arguments
__device__ ETC d_etc;
-// CHECK: @d_etc = addrspace(1) externally_initialized global %struct.ETC zeroinitializer,
+// DEVICE: @d_etc = addrspace(1) externally_initialized global %struct.ETC zeroinitializer,
+// HOST: @d_etc = internal global %struct.ETC undef,
__shared__ ETC s_etc;
-// CHECK: @s_etc = addrspace(3) global %struct.ETC undef,
+// DEVICE: @s_etc = addrspace(3) global %struct.ETC undef,
+// HOST: @s_etc = internal global %struct.ETC undef,
__constant__ ETC c_etc;
-// CHECK: @c_etc = addrspace(4) externally_initialized global %struct.ETC zeroinitializer,
+// DEVICE: @c_etc = addrspace(4) externally_initialized global %struct.ETC zeroinitializer,
+// HOST: @c_etc = internal global %struct.ETC undef,
__device__ NCFS d_ncfs;
-// CHECK: @d_ncfs = addrspace(1) externally_initialized global %struct.NCFS { i32 3 }
+// DEVICE: @d_ncfs = addrspace(1) externally_initialized global %struct.NCFS { i32 3 }
+// HOST: @d_ncfs = internal global %struct.NCFS undef,
__constant__ NCFS c_ncfs;
-// CHECK: @c_ncfs = addrspace(4) externally_initialized global %struct.NCFS { i32 3 }
+// DEVICE: @c_ncfs = addrspace(4) externally_initialized global %struct.NCFS { i32 3 }
+// HOST: @c_ncfs = internal global %struct.NCFS undef,
// Regular base class -- allowed
__device__ T_B_T d_t_b_t;
-// CHECK: @d_t_b_t = addrspace(1) externally_initialized global %struct.T_B_T zeroinitializer,
+// DEVICE: @d_t_b_t = addrspace(1) externally_initialized global %struct.T_B_T zeroinitializer,
+// HOST: @d_t_b_t = internal global %struct.T_B_T undef,
__shared__ T_B_T s_t_b_t;
-// CHECK: @s_t_b_t = addrspace(3) global %struct.T_B_T undef,
+// DEVICE: @s_t_b_t = addrspace(3) global %struct.T_B_T undef,
+// HOST: @s_t_b_t = internal global %struct.T_B_T undef,
__constant__ T_B_T c_t_b_t;
-// CHECK: @c_t_b_t = addrspace(4) externally_initialized global %struct.T_B_T zeroinitializer,
+// DEVICE: @c_t_b_t = addrspace(4) externally_initialized global %struct.T_B_T zeroinitializer,
+// HOST: @c_t_b_t = internal global %struct.T_B_T undef,
// Incapsulated object of allowed class -- allowed
__device__ T_F_T d_t_f_t;
-// CHECK: @d_t_f_t = addrspace(1) externally_initialized global %struct.T_F_T zeroinitializer,
+// DEVICE: @d_t_f_t = addrspace(1) externally_initialized global %struct.T_F_T zeroinitializer,
+// HOST: @d_t_f_t = internal global %struct.T_F_T undef,
__shared__ T_F_T s_t_f_t;
-// CHECK: @s_t_f_t = addrspace(3) global %struct.T_F_T undef,
+// DEVICE: @s_t_f_t = addrspace(3) global %struct.T_F_T undef,
+// HOST: @s_t_f_t = internal global %struct.T_F_T undef,
__constant__ T_F_T c_t_f_t;
-// CHECK: @c_t_f_t = addrspace(4) externally_initialized global %struct.T_F_T zeroinitializer,
+// DEVICE: @c_t_f_t = addrspace(4) externally_initialized global %struct.T_F_T zeroinitializer,
+// HOST: @c_t_f_t = internal global %struct.T_F_T undef,
// array of allowed objects -- allowed
__device__ T_FA_T d_t_fa_t;
-// CHECK: @d_t_fa_t = addrspace(1) externally_initialized global %struct.T_FA_T zeroinitializer,
+// DEVICE: @d_t_fa_t = addrspace(1) externally_initialized global %struct.T_FA_T zeroinitializer,
+// HOST: @d_t_fa_t = internal global %struct.T_FA_T undef,
__shared__ T_FA_T s_t_fa_t;
-// CHECK: @s_t_fa_t = addrspace(3) global %struct.T_FA_T undef,
+// DEVICE: @s_t_fa_t = addrspace(3) global %struct.T_FA_T undef,
+// HOST: @s_t_fa_t = internal global %struct.T_FA_T undef,
__constant__ T_FA_T c_t_fa_t;
-// CHECK: @c_t_fa_t = addrspace(4) externally_initialized global %struct.T_FA_T zeroinitializer,
+// DEVICE: @c_t_fa_t = addrspace(4) externally_initialized global %struct.T_FA_T zeroinitializer,
+// HOST: @c_t_fa_t = internal global %struct.T_FA_T undef,
// Calling empty base class initializer is OK
__device__ EC_I_EC d_ec_i_ec;
-// CHECK: @d_ec_i_ec = addrspace(1) externally_initialized global %struct.EC_I_EC zeroinitializer,
+// DEVICE: @d_ec_i_ec = addrspace(1) externally_initialized global %struct.EC_I_EC zeroinitializer,
+// HOST: @d_ec_i_ec = internal global %struct.EC_I_EC undef,
__shared__ EC_I_EC s_ec_i_ec;
-// CHECK: @s_ec_i_ec = addrspace(3) global %struct.EC_I_EC undef,
+// DEVICE: @s_ec_i_ec = addrspace(3) global %struct.EC_I_EC undef,
+// HOST: @s_ec_i_ec = internal global %struct.EC_I_EC undef,
__constant__ EC_I_EC c_ec_i_ec;
-// CHECK: @c_ec_i_ec = addrspace(4) externally_initialized global %struct.EC_I_EC zeroinitializer,
+// DEVICE: @c_ec_i_ec = addrspace(4) externally_initialized global %struct.EC_I_EC zeroinitializer,
+// HOST: @c_ec_i_ec = internal global %struct.EC_I_EC undef,
-// CHECK: @_ZZ2dfvE4s_ec = internal addrspace(3) global %struct.EC undef
-// CHECK: @_ZZ2dfvE5s_etc = internal addrspace(3) global %struct.ETC undef
+// DEVICE: @_ZZ2dfvE4s_ec = internal addrspace(3) global %struct.EC undef
+// DEVICE: @_ZZ2dfvE5s_etc = internal addrspace(3) global %struct.ETC undef
-// CHECK: @_ZZ2dfvE11const_array = internal addrspace(4) constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5]
-// CHECK: @_ZZ2dfvE9const_int = internal addrspace(4) constant i32 123
+// DEVICE: @_ZZ2dfvE11const_array = internal addrspace(4) constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5]
+// DEVICE: @_ZZ2dfvE9const_int = internal addrspace(4) constant i32 123
// We should not emit global initializers for device-side variables.
-// CHECK-NOT: @__cxx_global_var_init
+// DEVICE-NOT: @__cxx_global_var_init
// Make sure that initialization restrictions do not apply to local
// variables.
@@ -171,90 +208,90 @@ __device__ void df() {
// AMDGCN: %[[t_fa_ned:.*]] = addrspacecast %struct.T_FA_NED addrspace(5)* %t_fa_ned to %struct.T_FA_NED*
T t;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
EC ec;
- // CHECK: call void @_ZN2ECC1Ev(%struct.EC* %[[ec]])
+ // DEVICE: call void @_ZN2ECC1Ev(%struct.EC* %[[ec]])
ED ed;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
ECD ecd;
- // CHECK: call void @_ZN3ECDC1Ev(%struct.ECD* %[[ecd]])
+ // DEVICE: call void @_ZN3ECDC1Ev(%struct.ECD* %[[ecd]])
ETC etc;
- // CHECK: call void @_ZN3ETCC1IJEEEDpT_(%struct.ETC* %[[etc]])
+ // DEVICE: call void @_ZN3ETCC1IJEEEDpT_(%struct.ETC* %[[etc]])
UC uc;
// undefined constructor -- not allowed
- // CHECK: call void @_ZN2UCC1Ev(%struct.UC* %[[uc]])
+ // DEVICE: call void @_ZN2UCC1Ev(%struct.UC* %[[uc]])
UD ud;
// undefined destructor -- not allowed
- // CHECK-NOT: call
+ // DEVICE-NOT: call
ECI eci;
// empty constructor w/ initializer list -- not allowed
- // CHECK: call void @_ZN3ECIC1Ev(%struct.ECI* %[[eci]])
+ // DEVICE: call void @_ZN3ECIC1Ev(%struct.ECI* %[[eci]])
NEC nec;
// non-empty constructor -- not allowed
- // CHECK: call void @_ZN3NECC1Ev(%struct.NEC* %[[nec]])
+ // DEVICE: call void @_ZN3NECC1Ev(%struct.NEC* %[[nec]])
// non-empty destructor -- not allowed
NED ned;
// no-constructor, virtual method -- not allowed
- // CHECK: call void @_ZN3NCVC1Ev(%struct.NCV* %[[ncv]])
+ // DEVICE: call void @_ZN3NCVC1Ev(%struct.NCV* %[[ncv]])
NCV ncv;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
VD vd;
- // CHECK: call void @_ZN2VDC1Ev(%struct.VD* %[[vd]])
+ // DEVICE: call void @_ZN2VDC1Ev(%struct.VD* %[[vd]])
NCF ncf;
- // CHECK: call void @_ZN3NCFC1Ev(%struct.NCF* %[[ncf]])
+ // DEVICE: call void @_ZN3NCFC1Ev(%struct.NCF* %[[ncf]])
NCFS ncfs;
- // CHECK: call void @_ZN4NCFSC1Ev(%struct.NCFS* %[[ncfs]])
+ // DEVICE: call void @_ZN4NCFSC1Ev(%struct.NCFS* %[[ncfs]])
UTC utc;
- // CHECK: call void @_ZN3UTCC1IJEEEDpT_(%struct.UTC* %[[utc]])
+ // DEVICE: call void @_ZN3UTCC1IJEEEDpT_(%struct.UTC* %[[utc]])
NETC netc;
- // CHECK: call void @_ZN4NETCC1IJEEEDpT_(%struct.NETC* %[[netc]])
+ // DEVICE: call void @_ZN4NETCC1IJEEEDpT_(%struct.NETC* %[[netc]])
T_B_T t_b_t;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
T_F_T t_f_t;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
T_FA_T t_fa_t;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
EC_I_EC ec_i_ec;
- // CHECK: call void @_ZN7EC_I_ECC1Ev(%struct.EC_I_EC* %[[ec_i_ec]])
+ // DEVICE: call void @_ZN7EC_I_ECC1Ev(%struct.EC_I_EC* %[[ec_i_ec]])
EC_I_EC1 ec_i_ec1;
- // CHECK: call void @_ZN8EC_I_EC1C1Ev(%struct.EC_I_EC1* %[[ec_i_ec1]])
+ // DEVICE: call void @_ZN8EC_I_EC1C1Ev(%struct.EC_I_EC1* %[[ec_i_ec1]])
T_V_T t_v_t;
- // CHECK: call void @_ZN5T_V_TC1Ev(%struct.T_V_T* %[[t_v_t]])
+ // DEVICE: call void @_ZN5T_V_TC1Ev(%struct.T_V_T* %[[t_v_t]])
T_B_NEC t_b_nec;
- // CHECK: call void @_ZN7T_B_NECC1Ev(%struct.T_B_NEC* %[[t_b_nec]])
+ // DEVICE: call void @_ZN7T_B_NECC1Ev(%struct.T_B_NEC* %[[t_b_nec]])
T_F_NEC t_f_nec;
- // CHECK: call void @_ZN7T_F_NECC1Ev(%struct.T_F_NEC* %[[t_f_nec]])
+ // DEVICE: call void @_ZN7T_F_NECC1Ev(%struct.T_F_NEC* %[[t_f_nec]])
T_FA_NEC t_fa_nec;
- // CHECK: call void @_ZN8T_FA_NECC1Ev(%struct.T_FA_NEC* %[[t_fa_nec]])
+ // DEVICE: call void @_ZN8T_FA_NECC1Ev(%struct.T_FA_NEC* %[[t_fa_nec]])
T_B_NED t_b_ned;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
T_F_NED t_f_ned;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
T_FA_NED t_fa_ned;
- // CHECK-NOT: call
+ // DEVICE-NOT: call
static __shared__ EC s_ec;
- // CHECK-NOT: call void @_ZN2ECC1Ev(%struct.EC* addrspacecast (%struct.EC addrspace(3)* @_ZZ2dfvE4s_ec to %struct.EC*))
+ // DEVICE-NOT: call void @_ZN2ECC1Ev(%struct.EC* addrspacecast (%struct.EC addrspace(3)* @_ZZ2dfvE4s_ec to %struct.EC*))
static __shared__ ETC s_etc;
- // CHECK-NOT: call void @_ZN3ETCC1IJEEEDpT_(%struct.ETC* addrspacecast (%struct.ETC addrspace(3)* @_ZZ2dfvE5s_etc to %struct.ETC*))
+ // DEVICE-NOT: call void @_ZN3ETCC1IJEEEDpT_(%struct.ETC* addrspacecast (%struct.ETC addrspace(3)* @_ZZ2dfvE5s_etc to %struct.ETC*))
static const int const_array[] = {1, 2, 3, 4, 5};
static const int const_int = 123;
// anchor point separating constructors and destructors
- df(); // CHECK: call void @_Z2dfv()
+ df(); // DEVICE: call void @_Z2dfv()
// Verify that we only call non-empty destructors
- // CHECK-NEXT: call void @_ZN8T_FA_NEDD1Ev(%struct.T_FA_NED* %[[t_fa_ned]])
- // CHECK-NEXT: call void @_ZN7T_F_NEDD1Ev(%struct.T_F_NED* %[[t_f_ned]])
- // CHECK-NEXT: call void @_ZN7T_B_NEDD1Ev(%struct.T_B_NED* %[[t_b_ned]])
- // CHECK-NEXT: call void @_ZN2VDD1Ev(%struct.VD* %[[vd]])
- // CHECK-NEXT: call void @_ZN3NEDD1Ev(%struct.NED* %[[ned]])
- // CHECK-NEXT: call void @_ZN2UDD1Ev(%struct.UD* %[[ud]])
- // CHECK-NEXT: call void @_ZN3ECDD1Ev(%struct.ECD* %[[ecd]])
- // CHECK-NEXT: call void @_ZN2EDD1Ev(%struct.ED* %[[ed]])
+ // DEVICE-NEXT: call void @_ZN8T_FA_NEDD1Ev(%struct.T_FA_NED* %[[t_fa_ned]])
+ // DEVICE-NEXT: call void @_ZN7T_F_NEDD1Ev(%struct.T_F_NED* %[[t_f_ned]])
+ // DEVICE-NEXT: call void @_ZN7T_B_NEDD1Ev(%struct.T_B_NED* %[[t_b_ned]])
+ // DEVICE-NEXT: call void @_ZN2VDD1Ev(%struct.VD* %[[vd]])
+ // DEVICE-NEXT: call void @_ZN3NEDD1Ev(%struct.NED* %[[ned]])
+ // DEVICE-NEXT: call void @_ZN2UDD1Ev(%struct.UD* %[[ud]])
+ // DEVICE-NEXT: call void @_ZN3ECDD1Ev(%struct.ECD* %[[ecd]])
+ // DEVICE-NEXT: call void @_ZN2EDD1Ev(%struct.ED* %[[ed]])
- // CHECK-NEXT: ret void
+ // DEVICE-NEXT: ret void
}
// We should not emit global init function.
-// CHECK-NOT: @_GLOBAL__sub_I
+// DEVICE-NOT: @_GLOBAL__sub_I
diff --git a/test/CodeGenCUDA/link-device-bitcode.cu b/test/CodeGenCUDA/link-device-bitcode.cu
index b307838ae82d..69dc051355de 100644
--- a/test/CodeGenCUDA/link-device-bitcode.cu
+++ b/test/CodeGenCUDA/link-device-bitcode.cu
@@ -11,13 +11,19 @@
//
// Make sure function in device-code gets linked in and internalized.
// RUN: %clang_cc1 -triple nvptx-unknown-cuda -fcuda-is-device \
+// RUN: -mlink-builtin-bitcode %t.bc -emit-llvm \
+// RUN: -disable-llvm-passes -o - %s \
+// RUN: | FileCheck %s -check-prefix CHECK-IR
+
+// Make sure legacy flag name works
+// RUN: %clang_cc1 -triple nvptx-unknown-cuda -fcuda-is-device \
// RUN: -mlink-cuda-bitcode %t.bc -emit-llvm \
// RUN: -disable-llvm-passes -o - %s \
// RUN: | FileCheck %s -check-prefix CHECK-IR
//
// Make sure we can link two bitcode files.
// RUN: %clang_cc1 -triple nvptx-unknown-cuda -fcuda-is-device \
-// RUN: -mlink-cuda-bitcode %t.bc -mlink-cuda-bitcode %t-2.bc \
+// RUN: -mlink-builtin-bitcode %t.bc -mlink-builtin-bitcode %t-2.bc \
// RUN: -emit-llvm -disable-llvm-passes -o - %s \
// RUN: | FileCheck %s -check-prefix CHECK-IR -check-prefix CHECK-IR-2
//
@@ -30,7 +36,7 @@
//
// Make sure NVVMReflect pass is enabled in NVPTX back-end.
// RUN: %clang_cc1 -triple nvptx-unknown-cuda -fcuda-is-device \
-// RUN: -mlink-cuda-bitcode %t.bc -S -o /dev/null %s \
+// RUN: -mlink-builtin-bitcode %t.bc -S -o /dev/null %s \
// RUN: -mllvm -debug-pass=Structure 2>&1 \
// RUN: | FileCheck %s -check-prefix CHECK-REFLECT
diff --git a/test/CodeGenCUDA/propagate-metadata.cu b/test/CodeGenCUDA/propagate-metadata.cu
index 1616cb933748..773dd8afba81 100644
--- a/test/CodeGenCUDA/propagate-metadata.cu
+++ b/test/CodeGenCUDA/propagate-metadata.cu
@@ -1,5 +1,5 @@
// Check that when we link a bitcode module into a file using
-// -mlink-cuda-bitcode, we apply the same attributes to the functions in that
+// -mlink-builtin-bitcode, we apply the same attributes to the functions in that
// bitcode module as we apply to functions we generate.
//
// In particular, we check that ftz and unsafe-math are propagated into the
@@ -14,17 +14,17 @@
// RUN: %clang_cc1 -x c++ -emit-llvm-bc -ftrapping-math -DLIB \
// RUN: %s -o %t.bc -triple nvptx-unknown-unknown
-// RUN: %clang_cc1 -x cuda %s -emit-llvm -mlink-cuda-bitcode %t.bc -o - \
+// RUN: %clang_cc1 -x cuda %s -emit-llvm -mlink-builtin-bitcode %t.bc -o - \
// RUN: -fno-trapping-math -fcuda-is-device -triple nvptx-unknown-unknown \
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=NOFTZ --check-prefix=NOFAST
-// RUN: %clang_cc1 -x cuda %s -emit-llvm -mlink-cuda-bitcode %t.bc \
+// RUN: %clang_cc1 -x cuda %s -emit-llvm -mlink-builtin-bitcode %t.bc \
// RUN: -fno-trapping-math -fcuda-flush-denormals-to-zero -o - \
// RUN: -fcuda-is-device -triple nvptx-unknown-unknown \
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=FTZ \
// RUN: --check-prefix=NOFAST
-// RUN: %clang_cc1 -x cuda %s -emit-llvm -mlink-cuda-bitcode %t.bc \
+// RUN: %clang_cc1 -x cuda %s -emit-llvm -mlink-builtin-bitcode %t.bc \
// RUN: -fno-trapping-math -fcuda-flush-denormals-to-zero -o - \
// RUN: -fcuda-is-device -menable-unsafe-fp-math -triple nvptx-unknown-unknown \
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
diff --git a/test/CodeGenCUDA/usual-deallocators.cu b/test/CodeGenCUDA/usual-deallocators.cu
new file mode 100644
index 000000000000..2d97c8c9f7de
--- /dev/null
+++ b/test/CodeGenCUDA/usual-deallocators.cu
@@ -0,0 +1,133 @@
+// RUN: %clang_cc1 %s --std=c++11 -triple nvptx-unknown-unknown -fcuda-is-device \
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=COMMON,DEVICE
+// RUN: %clang_cc1 %s --std=c++11 -triple nvptx-unknown-unknown \
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=COMMON,HOST
+// RUN: %clang_cc1 %s --std=c++17 -triple nvptx-unknown-unknown -fcuda-is-device \
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=COMMON,DEVICE
+// RUN: %clang_cc1 %s --std=c++17 -triple nvptx-unknown-unknown \
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=COMMON,HOST
+
+#include "Inputs/cuda.h"
+extern "C" __host__ void host_fn();
+extern "C" __device__ void dev_fn();
+extern "C" __host__ __device__ void hd_fn();
+
+struct H1D1 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+};
+
+struct H1D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H2D1 {
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+};
+
+struct H2D2 {
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H1D1D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H1H2D1 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+};
+
+struct H1H2D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H1H2D1D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+
+template <typename T>
+__host__ __device__ void test_hd(void *p) {
+ T *t = (T *)p;
+ delete t;
+}
+
+// Make sure we call the right variant of usual deallocator.
+__host__ __device__ void tests_hd(void *t) {
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI4H1D1EvPv
+ // COMMON: call void @_ZN4H1D1dlEPv
+ test_hd<H1D1>(t);
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI4H1D2EvPv
+ // DEVICE: call void @_ZN4H1D2dlEPvj(i8* {{.*}}, i32 1)
+ // HOST: call void @_ZN4H1D2dlEPv(i8* {{.*}})
+ test_hd<H1D2>(t);
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI4H2D1EvPv
+ // DEVICE: call void @_ZN4H2D1dlEPv(i8* {{.*}})
+ // HOST: call void @_ZN4H2D1dlEPvj(i8* %3, i32 1)
+ test_hd<H2D1>(t);
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI4H2D2EvPv
+ // COMMON: call void @_ZN4H2D2dlEPvj(i8* {{.*}}, i32 1)
+ test_hd<H2D2>(t);
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI6H1D1D2EvPv
+ // COMMON: call void @_ZN6H1D1D2dlEPv(i8* %3)
+ test_hd<H1D1D2>(t);
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI6H1H2D1EvPv
+ // COMMON: call void @_ZN6H1H2D1dlEPv(i8* {{.*}})
+ test_hd<H1H2D1>(t);
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI6H1H2D2EvPv
+ // DEVICE: call void @_ZN6H1H2D2dlEPvj(i8* {{.*}}, i32 1)
+ // HOST: call void @_ZN6H1H2D2dlEPv(i8* {{.*}})
+ test_hd<H1H2D2>(t);
+ // COMMON-LABEL: define linkonce_odr void @_Z7test_hdI8H1H2D1D2EvPv
+ // COMMON: call void @_ZN8H1H2D1D2dlEPv(i8* {{.*}})
+ test_hd<H1H2D1D2>(t);
+}
+
+// Make sure we've picked deallocator for the correct side of compilation.
+
+// COMMON-LABEL: define linkonce_odr void @_ZN4H1D1dlEPv(i8*)
+// DEVICE: call void @dev_fn()
+// HOST: call void @host_fn()
+
+// DEVICE-LABEL: define linkonce_odr void @_ZN4H1D2dlEPvj(i8*, i32)
+// DEVICE: call void @dev_fn()
+// HOST-LABEL: define linkonce_odr void @_ZN4H1D2dlEPv(i8*)
+// HOST: call void @host_fn()
+
+// DEVICE-LABEL: define linkonce_odr void @_ZN4H2D1dlEPv(i8*)
+// DEVICE: call void @dev_fn()
+// HOST-LABEL: define linkonce_odr void @_ZN4H2D1dlEPvj(i8*, i32)
+// HOST: call void @host_fn()
+
+// COMMON-LABEL: define linkonce_odr void @_ZN4H2D2dlEPvj(i8*, i32)
+// DEVICE: call void @dev_fn()
+// HOST: call void @host_fn()
+
+// COMMON-LABEL: define linkonce_odr void @_ZN6H1D1D2dlEPv(i8*)
+// DEVICE: call void @dev_fn()
+// HOST: call void @host_fn()
+
+// COMMON-LABEL: define linkonce_odr void @_ZN6H1H2D1dlEPv(i8*)
+// DEVICE: call void @dev_fn()
+// HOST: call void @host_fn()
+
+// DEVICE-LABEL: define linkonce_odr void @_ZN6H1H2D2dlEPvj(i8*, i32)
+// DEVICE: call void @dev_fn()
+// HOST-LABEL: define linkonce_odr void @_ZN6H1H2D2dlEPv(i8*)
+// HOST: call void @host_fn()
+
+// COMMON-LABEL: define linkonce_odr void @_ZN8H1H2D1D2dlEPv(i8*)
+// DEVICE: call void @dev_fn()
+// HOST: call void @host_fn()
diff --git a/test/CodeGenCXX/Inputs/override-layout-packed-base.layout b/test/CodeGenCXX/Inputs/override-layout-packed-base.layout
index 949215ab849d..2ebcb98819b7 100644
--- a/test/CodeGenCXX/Inputs/override-layout-packed-base.layout
+++ b/test/CodeGenCXX/Inputs/override-layout-packed-base.layout
@@ -3,16 +3,26 @@
Type: class B<0>
Layout: <ASTRecordLayout
+ Size:40
FieldOffsets: [0, 32]>
*** Dumping AST Record Layout
Type: class B<1>
Layout: <ASTRecordLayout
+ Size:40
FieldOffsets: [0, 32]>
*** Dumping AST Record Layout
Type: class C
Layout: <ASTRecordLayout
+ Size:88
FieldOffsets: [80]>
+
+*** Dumping AST Record Layout
+Type: class D
+
+Layout: <ASTRecordLayout
+ Size:120
+ FieldOffsets: [32]>
diff --git a/test/CodeGenCXX/Inputs/profile-remap.map b/test/CodeGenCXX/Inputs/profile-remap.map
new file mode 100644
index 000000000000..50b812a9165e
--- /dev/null
+++ b/test/CodeGenCXX/Inputs/profile-remap.map
@@ -0,0 +1,2 @@
+name 3Foo 3Bar
+type N3Foo1XE N3Baz1YE
diff --git a/test/CodeGenCXX/Inputs/profile-remap.proftext b/test/CodeGenCXX/Inputs/profile-remap.proftext
new file mode 100644
index 000000000000..a1f90cfa6e9e
--- /dev/null
+++ b/test/CodeGenCXX/Inputs/profile-remap.proftext
@@ -0,0 +1,7 @@
+:ir
+_ZN3Foo8functionENS_1XE
+29667547796
+2
+10
+90
+
diff --git a/test/CodeGenCXX/Inputs/profile-remap.samples b/test/CodeGenCXX/Inputs/profile-remap.samples
new file mode 100644
index 000000000000..45e599470cc5
--- /dev/null
+++ b/test/CodeGenCXX/Inputs/profile-remap.samples
@@ -0,0 +1,3 @@
+_ZN3Bar8functionEN3Baz1YE:100:0
+ 2: 10
+ 4: 90
diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp
index 095705f389bf..195e4e521240 100644
--- a/test/CodeGenCXX/PR20038.cpp
+++ b/test/CodeGenCXX/PR20038.cpp
@@ -6,9 +6,9 @@ struct C {
extern bool b;
// CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]]
// CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]]
-// CHECK: [[FUN1:.*]] = distinct !DISubprogram(name: "fun1",{{.*}} isDefinition: true
+// CHECK: [[FUN1:.*]] = distinct !DISubprogram(name: "fun1",{{.*}} DISPFlagDefinition
// CHECK: [[DTOR_CALL1_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN1]])
void fun1() { b && (C(), 1); }
-// CHECK: [[FUN2:.*]] = distinct !DISubprogram(name: "fun2",{{.*}} isDefinition: true
+// CHECK: [[FUN2:.*]] = distinct !DISubprogram(name: "fun2",{{.*}} DISPFlagDefinition
// CHECK: [[DTOR_CALL2_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN2]])
bool fun2() { return (C(), b) && 0; }
diff --git a/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp b/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp
new file mode 100644
index 000000000000..3971c22287f9
--- /dev/null
+++ b/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=none %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=non-leaf %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-A-KEY
+
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=none %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=standard %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY --check-prefix=CHECK-BTE
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-A-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-B-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-B-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=bti %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTE
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf+bti %s | \
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-B-KEY --check-prefix=BTE
+
+struct Foo {
+ Foo() {}
+ ~Foo() {}
+};
+
+Foo f;
+
+// CHECK: @llvm.global_ctors {{.*}}i32 65535, void ()* @[[CTOR_FN:.*]], i8* null
+
+// CHECK: @[[CTOR_FN]]() #[[ATTR:[0-9]*]]
+
+// CHECK-NONE-NOT: "sign-return-address"={{.*}}
+// CHECK-PARTIAL: "sign-return-address"="non-leaf"
+// CHECK-ALL: "sign-return-address"="all"
+// CHECK-A-KEY: "sign-return-address-key"="a_key"
+// CHECK-B-KEY: "sign-return-address-key"="b_key"
+// CHECK-BTE: "branch-target-enforcement"
diff --git a/test/CodeGenCXX/address-space-cast-coerce.cpp b/test/CodeGenCXX/address-space-cast-coerce.cpp
new file mode 100644
index 000000000000..940a4f55b47a
--- /dev/null
+++ b/test/CodeGenCXX/address-space-cast-coerce.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s
+
+template<typename T, unsigned int n> struct my_vector_base;
+
+ template<typename T>
+ struct my_vector_base<T, 1> {
+ typedef T Native_vec_ __attribute__((ext_vector_type(1)));
+
+ union {
+ Native_vec_ data;
+ struct {
+ T x;
+ };
+ };
+ };
+
+ template<typename T, unsigned int rank>
+ struct my_vector_type : public my_vector_base<T, rank> {
+ using my_vector_base<T, rank>::data;
+ using typename my_vector_base<T, rank>::Native_vec_;
+
+ template< typename U>
+ my_vector_type(U x) noexcept
+ {
+ for (auto i = 0u; i != rank; ++i) data[i] = x;
+ }
+ my_vector_type& operator+=(const my_vector_type& x) noexcept
+ {
+ data += x.data;
+ return *this;
+ }
+ };
+
+template<typename T, unsigned int n>
+ inline
+ my_vector_type<T, n> operator+(
+ const my_vector_type<T, n>& x, const my_vector_type<T, n>& y) noexcept
+ {
+ return my_vector_type<T, n>{x} += y;
+ }
+
+using char1 = my_vector_type<char, 1>;
+
+int mane() {
+
+ char1 f1{1};
+ char1 f2{1};
+
+// CHECK: %[[a:[^ ]+]] = addrspacecast i16 addrspace(5)* %{{[^ ]+}} to i16*
+// CHECK: %[[a:[^ ]+]] = addrspacecast %{{[^ ]+}} addrspace(5)* %{{[^ ]+}} to %{{[^ ]+}}
+
+ char1 f3 = f1 + f2;
+}
diff --git a/test/CodeGenCXX/address-space-cast.cpp b/test/CodeGenCXX/address-space-cast.cpp
index 334a1a63e627..e0cf3c199b88 100644
--- a/test/CodeGenCXX/address-space-cast.cpp
+++ b/test/CodeGenCXX/address-space-cast.cpp
@@ -3,13 +3,63 @@
#define __private__ __attribute__((address_space(5)))
void func_pchar(__private__ char *x);
+void func_pvoid(__private__ void *x);
+void func_pint(__private__ int *x);
-void test_cast(char *gen_ptr) {
+void test_cast(char *gen_char_ptr, void *gen_void_ptr, int *gen_int_ptr) {
// CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
// CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
- __private__ char *priv_ptr = (__private__ char *)gen_ptr;
+ __private__ char *priv_char_ptr = (__private__ char *)gen_char_ptr;
// CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+ priv_char_ptr = (__private__ char *)gen_void_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+ priv_char_ptr = (__private__ char *)gen_int_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+ __private__ void *priv_void_ptr = (__private__ void *)gen_char_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+ priv_void_ptr = (__private__ void *)gen_void_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]
+ priv_void_ptr = (__private__ void *)gen_int_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i32 addrspace(5)*
+ // CHECK-NEXT: store i32 addrspace(5)* %[[cast]]
+ __private__ int *priv_int_ptr = (__private__ int *)gen_void_ptr;
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
+ func_pchar((__private__ char *)gen_char_ptr);
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
+ func_pchar((__private__ char *)gen_void_ptr);
+
+ // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
// CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]])
- func_pchar((__private__ char *)gen_ptr);
+ func_pchar((__private__ char *)gen_int_ptr);
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]])
+ func_pvoid((__private__ void *)gen_char_ptr);
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]])
+ func_pvoid((__private__ void *)gen_void_ptr);
+
+ // CHECK: %[[cast:.*]] = addrspacecast i32* %{{.*}} to i8 addrspace(5)*
+ // CHECK-NEXT: call void @_Z10func_pvoidPU3AS5v(i8 addrspace(5)* %[[cast]])
+ func_pvoid((__private__ void *)gen_int_ptr);
+
+ // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i32 addrspace(5)*
+ // CHECK-NEXT: call void @_Z9func_pintPU3AS5i(i32 addrspace(5)* %[[cast]])
+ func_pint((__private__ int *)gen_void_ptr);
}
diff --git a/test/CodeGenCXX/always_destroy.cpp b/test/CodeGenCXX/always_destroy.cpp
new file mode 100644
index 000000000000..e84c4cf02c52
--- /dev/null
+++ b/test/CodeGenCXX/always_destroy.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 %s -fno-c++-static-destructors -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | FileCheck %s
+
+struct NonTrivial {
+ ~NonTrivial();
+};
+
+// CHECK-NOT: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev
+NonTrivial nt1;
+// CHECK-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
+thread_local NonTrivial nt2;
+
+struct NonTrivial2 {
+ ~NonTrivial2();
+};
+
+// CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev
+[[clang::always_destroy]] NonTrivial2 nt21;
+// CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev
+[[clang::always_destroy]] thread_local NonTrivial2 nt22;
+
+void f() {
+ // CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev
+ [[clang::always_destroy]] static NonTrivial2 nt21;
+ // CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev
+ [[clang::always_destroy]] thread_local NonTrivial2 nt22;
+}
+
+// CHECK-NOT: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev
+[[clang::no_destroy]] NonTrivial nt3;
+// CHECK-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
+[[clang::no_destroy]] thread_local NonTrivial nt4;
diff --git a/test/CodeGenCXX/amdgcn-string-literal.cpp b/test/CodeGenCXX/amdgcn-string-literal.cpp
index 7fd05351c863..70be249433fb 100644
--- a/test/CodeGenCXX/amdgcn-string-literal.cpp
+++ b/test/CodeGenCXX/amdgcn-string-literal.cpp
@@ -4,7 +4,7 @@
// CHECK: @g_str = addrspace(1) global i8* addrspacecast (i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @.str, i32 0, i32 0) to i8*), align 8
// CHECK: @g_array = addrspace(1) global [8 x i8] c"g_array\00", align 1
// CHECK: @.str.1 = private unnamed_addr addrspace(4) constant [6 x i8] c"l_str\00", align 1
-// CHECK: @_ZZ1fvE7l_array = private unnamed_addr addrspace(4) constant [8 x i8] c"l_array\00", align 1
+// CHECK: @__const._Z1fv.l_array = private unnamed_addr addrspace(4) constant [8 x i8] c"l_array\00", align 1
const char* g_str = "g_str";
char g_array[] = "g_array";
diff --git a/test/CodeGenCXX/atomic-inline.cpp b/test/CodeGenCXX/atomic-inline.cpp
index 327f85d5667f..fe727589d2e2 100644
--- a/test/CodeGenCXX/atomic-inline.cpp
+++ b/test/CodeGenCXX/atomic-inline.cpp
@@ -1,52 +1,6 @@
// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s
// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu -target-cpu core2 | FileCheck %s --check-prefix=CORE2
-// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i386 | FileCheck %s --check-prefix=I386
-// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i486 | FileCheck %s --check-prefix=I486
-// Check the atomic code generation for cpu targets w/wo cx, cx8 and cx16 support.
-
-struct alignas(4) AM4 {
- short f1, f2;
-};
-AM4 m4;
-AM4 load4() {
- AM4 am;
- // CHECK-LABEL: @_Z5load4v
- // CHECK: load atomic i32, {{.*}} monotonic
- // CORE2-LABEL: @_Z5load4v
- // CORE2: load atomic i32, {{.*}} monotonic
- // I386-LABEL: @_Z5load4v
- // I386: call i32 @__atomic_load_4
- // I486-LABEL: @_Z5load4v
- // I486: load atomic i32, {{.*}} monotonic
- __atomic_load(&m4, &am, 0);
- return am;
-}
-
-AM4 s4;
-void store4() {
- // CHECK-LABEL: @_Z6store4v
- // CHECK: store atomic i32 {{.*}} monotonic
- // CORE2-LABEL: @_Z6store4v
- // CORE2: store atomic i32 {{.*}} monotonic
- // I386-LABEL: @_Z6store4v
- // I386: call void @__atomic_store_4
- // I486-LABEL: @_Z6store4v
- // I486: store atomic i32 {{.*}} monotonic
- __atomic_store(&m4, &s4, 0);
-}
-
-bool cmpxchg4() {
- AM4 am;
- // CHECK-LABEL: @_Z8cmpxchg4v
- // CHECK: cmpxchg i32* {{.*}} monotonic
- // CORE2-LABEL: @_Z8cmpxchg4v
- // CORE2: cmpxchg i32* {{.*}} monotonic
- // I386-LABEL: @_Z8cmpxchg4v
- // I386: call zeroext i1 @__atomic_compare_exchange_4
- // I486-LABEL: @_Z8cmpxchg4v
- // I486: cmpxchg i32* {{.*}} monotonic
- return __atomic_compare_exchange(&m4, &s4, &am, 0, 0, 0);
-}
+// Check the atomic code generation for cpu targets w/wo cx16 support.
struct alignas(8) AM8 {
int f1, f2;
@@ -58,10 +12,6 @@ AM8 load8() {
// CHECK: load atomic i64, {{.*}} monotonic
// CORE2-LABEL: @_Z5load8v
// CORE2: load atomic i64, {{.*}} monotonic
- // I386-LABEL: @_Z5load8v
- // I386: call i64 @__atomic_load_8
- // I486-LABEL: @_Z5load8v
- // I486: call i64 @__atomic_load_8
__atomic_load(&m8, &am, 0);
return am;
}
@@ -72,10 +22,6 @@ void store8() {
// CHECK: store atomic i64 {{.*}} monotonic
// CORE2-LABEL: @_Z6store8v
// CORE2: store atomic i64 {{.*}} monotonic
- // I386-LABEL: @_Z6store8v
- // I386: call void @__atomic_store_8
- // I486-LABEL: @_Z6store8v
- // I486: call void @__atomic_store_8
__atomic_store(&m8, &s8, 0);
}
@@ -85,10 +31,6 @@ bool cmpxchg8() {
// CHECK: cmpxchg i64* {{.*}} monotonic
// CORE2-LABEL: @_Z8cmpxchg8v
// CORE2: cmpxchg i64* {{.*}} monotonic
- // I386-LABEL: @_Z8cmpxchg8v
- // I386: call zeroext i1 @__atomic_compare_exchange_8
- // I486-LABEL: @_Z8cmpxchg8v
- // I486: call zeroext i1 @__atomic_compare_exchange_8
return __atomic_compare_exchange(&m8, &s8, &am, 0, 0, 0);
}
@@ -124,3 +66,4 @@ bool cmpxchg16() {
// CORE2: cmpxchg i128* {{.*}} monotonic
return __atomic_compare_exchange(&m16, &s16, &am, 0, 0, 0);
}
+
diff --git a/test/CodeGenCXX/attr-cpuspecific.cpp b/test/CodeGenCXX/attr-cpuspecific.cpp
new file mode 100644
index 000000000000..bfee49ca34bd
--- /dev/null
+++ b/test/CodeGenCXX/attr-cpuspecific.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX
+// RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WINDOWS
+
+struct S {
+ __attribute__((cpu_specific(atom)))
+ void Func(){}
+ __attribute__((cpu_dispatch(ivybridge,atom)))
+ void Func(){}
+};
+
+void foo() {
+ S s;
+ s.Func();
+}
+
+// LINUX: define void (%struct.S*)* @_ZN1S4FuncEv.resolver
+// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.S
+// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.O
+// LINUX: declare void @_ZN1S4FuncEv.S
+// LINUX: define linkonce_odr void @_ZN1S4FuncEv.O
+
+// WINDOWS: define dso_local void @"?Func@S@@QEAAXXZ"(%struct.S*)
+// WINDOWS: musttail call void @"?Func@S@@QEAAXXZ.S"(%struct.S* %0)
+// WINDOWS: musttail call void @"?Func@S@@QEAAXXZ.O"(%struct.S* %0)
+// WINDOWS: declare dso_local void @"?Func@S@@QEAAXXZ.S"
+// WINDOWS: define linkonce_odr dso_local void @"?Func@S@@QEAAXXZ.O"
diff --git a/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp b/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp
new file mode 100644
index 000000000000..efbbb0cd6400
--- /dev/null
+++ b/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -O0 -o - %s | FileCheck %s
+
+// Test that we do not assume that entities marked with the
+// exclude_from_explicit_instantiation attribute are instantiated
+// in another TU when an extern template instantiation declaration
+// is present. We test that by making sure that definitions are
+// generated in this TU despite there being an extern template
+// instantiation declaration, which is normally not the case.
+
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct Foo {
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1();
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member;
+
+ struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {
+ static void static_member_function() { }
+ };
+
+ struct member_class2 {
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() { }
+ };
+};
+
+template <class T> inline void Foo<T>::non_static_member_function1() { }
+template <class T> void Foo<T>::non_static_member_function2() { }
+
+template <class T> inline void Foo<T>::static_member_function1() { }
+template <class T> void Foo<T>::static_member_function2() { }
+
+template <class T> int Foo<T>::static_data_member = 0;
+
+extern template struct Foo<int>;
+
+void use() {
+ Foo<int> f;
+
+ // An inline non-static member function marked with the attribute is not
+ // part of the extern template declaration, so a definition must be emitted
+ // in this TU.
+ // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function1Ev
+ f.non_static_member_function1();
+
+ // A non-inline non-static member function marked with the attribute is
+ // not part of the extern template declaration, so a definition must be
+ // emitted in this TU.
+ // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function2Ev
+ f.non_static_member_function2();
+
+ // An inline static member function marked with the attribute is not
+ // part of the extern template declaration, so a definition must be
+ // emitted in this TU.
+ // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function1Ev
+ Foo<int>::static_member_function1();
+
+ // A non-inline static member function marked with the attribute is not
+ // part of the extern template declaration, so a definition must be
+ // emitted in this TU.
+ // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function2Ev
+ Foo<int>::static_member_function2();
+
+ // A static data member marked with the attribute is not part of the
+ // extern template declaration, so a definition must be emitted in this TU.
+ // CHECK-DAG: @_ZN3FooIiE18static_data_memberE = linkonce_odr global
+ int& odr_use = Foo<int>::static_data_member;
+
+ // A member class marked with the attribute is not part of the extern
+ // template declaration (it is not recursively instantiated), so its member
+ // functions must be emitted in this TU.
+ // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class122static_member_functionEv
+ Foo<int>::member_class1::static_member_function();
+
+ // A member function marked with the attribute in a member class is not
+ // part of the extern template declaration of the parent class template, so
+ // it must be emitted in this TU.
+ // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class222static_member_functionEv
+ Foo<int>::member_class2::static_member_function();
+}
diff --git a/test/CodeGenCXX/attr-no-destroy-d54344.cpp b/test/CodeGenCXX/attr-no-destroy-d54344.cpp
new file mode 100644
index 000000000000..2e004d6426d9
--- /dev/null
+++ b/test/CodeGenCXX/attr-no-destroy-d54344.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK-ATTR
+// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR -fno-c++-static-destructors %s -o - | FileCheck %s --check-prefix=CHECK-FLAG
+
+// Regression test for D54344. Class with no user-defined destructor
+// that has an inherited member that has a non-trivial destructor
+// and a non-default constructor will attempt to emit a destructor
+// despite being marked as __attribute((no_destroy)) in which case
+// it would trigger an assertion due to an incorrect assumption.
+
+// This test is more reliable with asserts to work as without
+// the crash may (unlikely) could generate working but semantically
+// incorrect code.
+
+class a {
+public:
+ ~a();
+};
+class logger_base {
+ a d;
+};
+class e : logger_base {};
+#ifndef NOATTR
+__attribute((no_destroy))
+#endif
+e g;
+
+// In the absence of the attribute and flag, both ctor and dtor should
+// be emitted, check for that.
+// CHECK: @__cxx_global_var_init
+// CHECK: @__cxa_atexit
+
+// When attribute is enabled, the constructor should not be balanced
+// by a destructor. Make sure we have the ctor but not the dtor
+// registration.
+// CHECK-ATTR: @__cxx_global_var_init
+// CHECK-ATTR-NOT: @__cxa_atexit
+
+// Same scenario except with global flag (-fno-c++-static-destructors)
+// supressing it instead of the attribute.
+// CHECK-FLAG: @__cxx_global_var_init
+// CHECK-FLAG-NOT: @__cxa_atexit
diff --git a/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
index 4dc2b67b4644..77e1ad771eca 100644
--- a/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
+++ b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
-// Test ensures that this properly differentiates between types in different
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
+// Test ensures that this properly differentiates between types in different
// namespaces.
int __attribute__((target("sse4.2"))) foo(int) { return 0; }
int __attribute__((target("arch=sandybridge"))) foo(int);
@@ -17,38 +18,71 @@ int bar() {
return foo(1) + ns::foo(2);
}
-// CHECK: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver
-// CHECK: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver
-
-// CHECK: define i32 @_Z3fooi.sse4.2(i32)
-// CHECK: ret i32 0
-// CHECK: define i32 @_Z3fooi.arch_ivybridge(i32)
-// CHECK: ret i32 1
-// CHECK: define i32 @_Z3fooi(i32)
-// CHECK: ret i32 2
-
-// CHECK: define i32 @_ZN2ns3fooEi.sse4.2(i32)
-// CHECK: ret i32 0
-// CHECK: define i32 @_ZN2ns3fooEi.arch_ivybridge(i32)
-// CHECK: ret i32 1
-// CHECK: define i32 @_ZN2ns3fooEi(i32)
-// CHECK: ret i32 2
-
-// CHECK: define i32 @_Z3barv()
-// CHECK: call i32 @_Z3fooi.ifunc(i32 1)
-// CHECK: call i32 @_ZN2ns3fooEi.ifunc(i32 2)
-
-// CHECK: define i32 (i32)* @_Z3fooi.resolver() comdat
-// CHECK: ret i32 (i32)* @_Z3fooi.arch_sandybridge
-// CHECK: ret i32 (i32)* @_Z3fooi.arch_ivybridge
-// CHECK: ret i32 (i32)* @_Z3fooi.sse4.2
-// CHECK: ret i32 (i32)* @_Z3fooi
-//
-// CHECK: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat
-// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge
-// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge
-// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2
-// CHECK: ret i32 (i32)* @_ZN2ns3fooEi
-
-// CHECK: declare i32 @_Z3fooi.arch_sandybridge(i32)
-// CHECK: declare i32 @_ZN2ns3fooEi.arch_sandybridge(i32)
+// LINUX: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver
+// LINUX: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver
+
+// LINUX: define i32 @_Z3fooi.sse4.2(i32)
+// LINUX: ret i32 0
+// LINUX: define i32 @_Z3fooi.arch_ivybridge(i32)
+// LINUX: ret i32 1
+// LINUX: define i32 @_Z3fooi(i32)
+// LINUX: ret i32 2
+
+// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z.sse4.2"(i32)
+// WINDOWS: ret i32 0
+// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z.arch_ivybridge"(i32)
+// WINDOWS: ret i32 1
+// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z"(i32)
+// WINDOWS: ret i32 2
+
+// LINUX: define i32 @_ZN2ns3fooEi.sse4.2(i32)
+// LINUX: ret i32 0
+// LINUX: define i32 @_ZN2ns3fooEi.arch_ivybridge(i32)
+// LINUX: ret i32 1
+// LINUX: define i32 @_ZN2ns3fooEi(i32)
+// LINUX: ret i32 2
+
+// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z.sse4.2"(i32)
+// WINDOWS: ret i32 0
+// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z.arch_ivybridge"(i32)
+// WINDOWS: ret i32 1
+// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z"(i32)
+// WINDOWS: ret i32 2
+
+// LINUX: define i32 @_Z3barv()
+// LINUX: call i32 @_Z3fooi.ifunc(i32 1)
+// LINUX: call i32 @_ZN2ns3fooEi.ifunc(i32 2)
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"()
+// WINDOWS: call i32 @"?foo@@YAHH@Z.resolver"(i32 1)
+// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.resolver"(i32 2)
+
+// LINUX: define i32 (i32)* @_Z3fooi.resolver() comdat
+// LINUX: ret i32 (i32)* @_Z3fooi.arch_sandybridge
+// LINUX: ret i32 (i32)* @_Z3fooi.arch_ivybridge
+// LINUX: ret i32 (i32)* @_Z3fooi.sse4.2
+// LINUX: ret i32 (i32)* @_Z3fooi
+
+// WINDOWS: define dso_local i32 @"?foo@@YAHH@Z.resolver"(i32) comdat
+// WINDOWS: call i32 @"?foo@@YAHH@Z.arch_sandybridge"(i32 %0)
+// WINDOWS: call i32 @"?foo@@YAHH@Z.arch_ivybridge"(i32 %0)
+// WINDOWS: call i32 @"?foo@@YAHH@Z.sse4.2"(i32 %0)
+// WINDOWS: call i32 @"?foo@@YAHH@Z"(i32 %0)
+
+// LINUX: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat
+// LINUX: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge
+// LINUX: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge
+// LINUX: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2
+// LINUX: ret i32 (i32)* @_ZN2ns3fooEi
+
+// WINDOWS: define dso_local i32 @"?foo@ns@@YAHH@Z.resolver"(i32) comdat
+// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.arch_sandybridge"(i32 %0)
+// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.arch_ivybridge"(i32 %0)
+// WINDOWS: call i32 @"?foo@ns@@YAHH@Z.sse4.2"(i32 %0)
+// WINDOWS: call i32 @"?foo@ns@@YAHH@Z"(i32 %0)
+
+// LINUX: declare i32 @_Z3fooi.arch_sandybridge(i32)
+// LINUX: declare i32 @_ZN2ns3fooEi.arch_sandybridge(i32)
+
+// WINDOWS: declare dso_local i32 @"?foo@@YAHH@Z.arch_sandybridge"(i32)
+// WINDOWS: declare dso_local i32 @"?foo@ns@@YAHH@Z.arch_sandybridge"(i32)
diff --git a/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp
index 290d6b5c6489..6336e190426b 100644
--- a/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp
+++ b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
void temp();
void temp(int);
using FP = void(*)(int);
@@ -31,15 +32,23 @@ int bar() {
return Free(1) + (s.*Member)(2);
}
+// LINUX: @_Z3fooi.ifunc
+// LINUX: @_ZN1S3fooEi.ifunc
-// CHECK: @_Z3fooi.ifunc
-// CHECK: @_ZN1S3fooEi.ifunc
-
-// CHECK: define i32 @_Z3barv()
+// LINUX: define i32 @_Z3barv()
// Store to Free of ifunc
-// CHECK: store i32 (i32)* @_Z3fooi.ifunc
+// LINUX: store i32 (i32)* @_Z3fooi.ifunc
// Store to Member of ifunc
-// CHECK: store { i64, i64 } { i64 ptrtoint (i32 (%struct.S*, i32)* @_ZN1S3fooEi.ifunc to i64), i64 0 }, { i64, i64 }* [[MEMBER:%[a-z]+]]
+// LINUX: store { i64, i64 } { i64 ptrtoint (i32 (%struct.S*, i32)* @_ZN1S3fooEi.ifunc to i64), i64 0 }, { i64, i64 }* [[MEMBER:%[a-z]+]]
// Call to 'f' with the ifunc
-// CHECK: call void @_Z1fPFiiEM1SFiiE(i32 (i32)* @_Z3fooi.ifunc
+// LINUX: call void @_Z1fPFiiEM1SFiiE(i32 (i32)* @_Z3fooi.ifunc
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"()
+// Store to Free
+// WINDOWS: store i32 (i32)* @"?foo@@YAHH@Z.resolver", i32 (i32)**
+// Store to Member
+// WINDOWS: store i8* bitcast (i32 (%struct.S*, i32)* @"?foo@S@@QEAAHH@Z.resolver" to i8*), i8**
+
+// Call to 'f'
+// WINDOWS: call void @"?f@@YAXP6AHH@ZP8S@@EAAHH@Z@Z"(i32 (i32)* @"?foo@@YAHH@Z.resolver", i8* bitcast (i32 (%struct.S*, i32)* @"?foo@S@@QEAAHH@Z.resolver" to i8*))
diff --git a/test/CodeGenCXX/attr-target-mv-inalloca.cpp b/test/CodeGenCXX/attr-target-mv-inalloca.cpp
new file mode 100644
index 000000000000..0b656220273f
--- /dev/null
+++ b/test/CodeGenCXX/attr-target-mv-inalloca.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -std=c++11 -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS64
+
+struct Foo {
+ Foo();
+ Foo(const Foo &o);
+ ~Foo();
+ int x;
+};
+int __attribute__((target("default"))) bar(Foo o) { return o.x; }
+int __attribute__((target("sse4.2"))) bar(Foo o) { return o.x + 1; }
+int __attribute__((target("arch=ivybridge"))) bar(Foo o) { return o.x + 2; }
+
+void usage() {
+ Foo f;
+ bar(f);
+}
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* inalloca)
+// WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
+// WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
+// WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
+// WINDOWS: ret i32 %[[LOAD]]
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* inalloca)
+// WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
+// WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
+// WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
+// WINDOWS: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 1
+// WINDOWS: ret i32 %[[ADD]]
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* inalloca)
+// WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
+// WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
+// WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
+// WINDOWS: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 2
+// WINDOWS: ret i32 %[[ADD]]
+
+// WINDOWS: define dso_local void @"?usage@@YAXXZ"()
+// WINDOWS: %[[F:[0-9a-zA-Z]+]] = alloca %struct.Foo
+// WINDOWS: %[[ARGMEM:[0-9a-zA-Z]+]] = alloca inalloca <{ %struct.Foo }>
+// WINDOWS: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* inalloca %[[ARGMEM]])
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>*)
+// WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* %0)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* %0)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+// WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* %0)
+// WINDOWS-NEXT: ret i32 %[[RET]]
+
+
+// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(%struct.Foo* %[[O:[0-9a-zA-Z]+]])
+// WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
+// WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
+// WINDOWS64: ret i32 %[[LOAD]]
+
+// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(%struct.Foo* %[[O:[0-9a-zA-Z]+]])
+// WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
+// WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
+// WINDOWS64: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 1
+// WINDOWS64: ret i32 %[[ADD]]
+
+// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(%struct.Foo* %[[O:[0-9a-zA-Z]+]])
+// WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
+// WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
+// WINDOWS64: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 2
+// WINDOWS64: ret i32 %[[ADD]]
+
+// WINDOWS64: define dso_local void @"?usage@@YAXXZ"()
+// WINDOWS64: %[[F:[0-9a-zA-Z]+]] = alloca %struct.Foo
+// WINDOWS64: %[[ARG:[0-9a-zA-Z.]+]] = alloca %struct.Foo
+// WINDOWS64: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(%struct.Foo* %[[ARG]])
+
+// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(%struct.Foo*)
+// WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(%struct.Foo* %0)
+// WINDOWS64-NEXT: ret i32 %[[RET]]
+// WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(%struct.Foo* %0)
+// WINDOWS64-NEXT: ret i32 %[[RET]]
+// WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z"(%struct.Foo* %0)
+// WINDOWS64-NEXT: ret i32 %[[RET]]
diff --git a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
index 2e5db3b705e4..a63737ed0330 100644
--- a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
+++ b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
struct S {
int __attribute__((target("sse4.2"))) foo(int) { return 0; }
@@ -64,74 +65,156 @@ int templ_use() {
return a.foo(1) + b.foo(2);
}
-// CHECK: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver
-// CHECK: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver
-// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
-// CHECK: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver
+// LINUX: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver
+// LINUX: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver
+// LINUX: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
+// LINUX: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver
// Templates:
-// CHECK: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
-// CHECK: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
-
-// CHECK: define i32 @_Z3barv()
-// CHECK: %s = alloca %struct.S, align 1
-// CHECK: %s2 = alloca %struct.S, align 1
-// CHECK: %C = alloca %struct.ConvertTo, align 1
-// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2
-// CHECK: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* %C)
-// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2
-// CHECK: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0)
-
-// CHECK: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat
-// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge
-// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_
-
-// CHECK: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat
-// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge
-// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv
-
-// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
-
-// CHECK: define i32 @_Z4bar2v()
-// CHECK:call i32 @_ZN2S23fooEi.ifunc
-// define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat
-// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge
-// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge
-// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2
-// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi
-
-// CHECK: define i32 @_ZN2S23fooEi.sse4.2(%struct.S2* %this, i32)
-// CHECK: define i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* %this, i32)
-// CHECK: define i32 @_ZN2S23fooEi(%struct.S2* %this, i32)
-
-// CHECK: define i32 @_Z9templ_usev()
-// CHECK: call i32 @_ZN5templIiE3fooEi.ifunc
-// CHECK: call i32 @_ZN5templIdE3fooEi.ifunc
-
-
-// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat
-// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge
-// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge
-// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2
-// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi
-//
-// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat
-// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge
-// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge
-// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2
-// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi
-
-// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
-// CHECK: ret i32 0
-
-// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
-
-// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
-// CHECK: ret i32 1
-
-// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32)
-// CHECK: ret i32 2
-
+// LINUX: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
+// LINUX: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
+
+// LINUX: define i32 @_Z3barv()
+// LINUX: %s = alloca %struct.S, align 1
+// LINUX: %s2 = alloca %struct.S, align 1
+// LINUX: %C = alloca %struct.ConvertTo, align 1
+// LINUX: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2
+// LINUX: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* %C)
+// LINUX: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2
+// LINUX: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0)
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"()
+// WINDOWS: %s = alloca %struct.S, align 1
+// WINDOWS: %s2 = alloca %struct.S, align 1
+// WINDOWS: %C = alloca %struct.ConvertTo, align 1
+// WINDOWS: call dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* %s2
+// WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo* %C
+// WINDOWS: call dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* %s2
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* %s, i32 0)
+
+// LINUX: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat
+// LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge
+// LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_
+
+// WINDOWS: define dso_local %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S*, %struct.S*)
+// WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.arch_ivybridge"
+// WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z"
+
+// LINUX: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat
+// LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge
+// LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv
+
+// WINDOWS: define dso_local void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo*, %struct.S*)
+// WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ.arch_ivybridge"
+// WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ"
+
+// LINUX: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
+
+// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S*, i32)
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.sse4.2"
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z"
+
+// LINUX: define i32 @_Z4bar2v()
+// LINUX: call i32 @_ZN2S23fooEi.ifunc
+
+// WINDOWS: define dso_local i32 @"?bar2@@YAHXZ"()
+// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.resolver"
+
+// LINUX: define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat
+// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge
+// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge
+// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2
+// LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi
+
+// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.resolver"(%struct.S2*, i32)
+// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_sandybridge"
+// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_ivybridge"
+// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.sse4.2"
+// WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z"
+
+// LINUX: define i32 @_ZN2S23fooEi.sse4.2(%struct.S2* %this, i32)
+// LINUX: define i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* %this, i32)
+// LINUX: define i32 @_ZN2S23fooEi(%struct.S2* %this, i32)
+
+// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.sse4.2"(%struct.S2* %this, i32)
+// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z.arch_ivybridge"(%struct.S2* %this, i32)
+// WINDOWS: define dso_local i32 @"?foo@S2@@QEAAHH@Z"(%struct.S2* %this, i32)
+
+// LINUX: define i32 @_Z9templ_usev()
+// LINUX: call i32 @_ZN5templIiE3fooEi.ifunc
+// LINUX: call i32 @_ZN5templIdE3fooEi.ifunc
+
+// WINDOWS: define dso_local i32 @"?templ_use@@YAHXZ"()
+// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver"
+// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.resolver"
+
+// LINUX: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat
+// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge
+// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge
+// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2
+// LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi
+
+// WINDOWS: define dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver"(%struct.templ*, i32)
+// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_sandybridge"
+// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_ivybridge"
+// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.sse4.2"
+// WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z"
+
+// LINUX: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat
+// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge
+// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge
+// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2
+// LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi
+
+// WINDOWS: define dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.resolver"(%struct.templ.0*, i32) comdat
+// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_sandybridge"
+// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_ivybridge"
+// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.sse4.2"
+// WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z"
+
+// LINUX: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
+// LINUX: ret i32 0
+
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* %this, i32)
+// WINDOWS: ret i32 0
+
+// LINUX: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
+
+// WINDOWS: declare dso_local i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S*, i32)
+
+// LINUX: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
+// LINUX: ret i32 1
+
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* %this, i32)
+// WINDOWS: ret i32 1
+
+// LINUX: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32)
+// LINUX: ret i32 2
+
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@S@@QEAAHH@Z"(%struct.S* %this, i32)
+// WINDOWS: ret i32 2
+
+// LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi.sse4.2
+// LINUX: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge
+// LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi.arch_ivybridge
+// LINUX: define linkonce_odr i32 @_ZN5templIiE3fooEi
+
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.sse4.2"
+// WINDOWS: declare dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_sandybridge"
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_ivybridge"
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z"
+
+// LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi.sse4.2
+// LINUX: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge
+// LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi.arch_ivybridge
+// LINUX: define linkonce_odr i32 @_ZN5templIdE3fooEi
+
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.sse4.2"
+// WINDOWS: declare dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_sandybridge"
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_ivybridge"
+// WINDOWS: define linkonce_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z"
diff --git a/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
index 63353c12d29a..1c051b385384 100644
--- a/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
+++ b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
struct S {
int __attribute__((target("sse4.2"))) foo(int);
int __attribute__((target("arch=sandybridge"))) foo(int);
@@ -15,25 +16,46 @@ int bar() {
return s.foo(0);
}
-// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
+// LINUX: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
-// CHECK: define i32 @_ZN1S3fooEi(%struct.S* %this, i32)
-// CHECK: ret i32 2
+// LINUX: define i32 @_ZN1S3fooEi(%struct.S* %this, i32)
+// LINUX: ret i32 2
-// CHECK: define i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
-// CHECK: ret i32 0
+// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z"(%struct.S* %this, i32)
+// WINDOWS: ret i32 2
-// CHECK: define i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
-// CHECK: ret i32 1
+// LINUX: define i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
+// LINUX: ret i32 0
-// CHECK: define i32 @_Z3barv()
-// CHECK: %s = alloca %struct.S, align 1
-// CHECK: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0)
+// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* %this, i32)
+// WINDOWS: ret i32 0
-// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
-// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
+// LINUX: define i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
+// LINUX: ret i32 1
-// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
+// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* %this, i32)
+// WINDOWS: ret i32 1
+
+// LINUX: define i32 @_Z3barv()
+// LINUX: %s = alloca %struct.S, align 1
+// LINUX: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0)
+
+// WINDOWS: define dso_local i32 @"?bar@@YAHXZ"()
+// WINDOWS: %s = alloca %struct.S, align 1
+// WINDOWS: %call = call i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* %s, i32 0)
+
+// LINUX: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
+// LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
+
+// WINDOWS: define dso_local i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S*, i32) comdat
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S* %0, i32 %1)
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* %0, i32 %1)
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* %0, i32 %1)
+// WINDOWS: call i32 @"?foo@S@@QEAAHH@Z"(%struct.S* %0, i32 %1)
+
+// LINUX: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
+
+// WINDOWS: declare dso_local i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S*, i32)
diff --git a/test/CodeGenCXX/attr-target-mv-overloads.cpp b/test/CodeGenCXX/attr-target-mv-overloads.cpp
index c72ea77fa46f..a213d247cb1f 100644
--- a/test/CodeGenCXX/attr-target-mv-overloads.cpp
+++ b/test/CodeGenCXX/attr-target-mv-overloads.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
int __attribute__((target("sse4.2"))) foo_overload(int) { return 0; }
int __attribute__((target("arch=sandybridge"))) foo_overload(int);
@@ -13,38 +14,69 @@ int bar2() {
return foo_overload() + foo_overload(1);
}
-// CHECK: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver
-// CHECK: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver
-
-
-// CHECK: define i32 @_Z12foo_overloadi.sse4.2(i32)
-// CHECK: ret i32 0
-// CHECK: define i32 @_Z12foo_overloadi.arch_ivybridge(i32)
-// CHECK: ret i32 1
-// CHECK: define i32 @_Z12foo_overloadi(i32)
-// CHECK: ret i32 2
-// CHECK: define i32 @_Z12foo_overloadv.sse4.2()
-// CHECK: ret i32 0
-// CHECK: define i32 @_Z12foo_overloadv.arch_ivybridge()
-// CHECK: ret i32 1
-// CHECK: define i32 @_Z12foo_overloadv()
-// CHECK: ret i32 2
-
-// CHECK: define i32 @_Z4bar2v()
-// CHECK: call i32 @_Z12foo_overloadv.ifunc()
-// CHECK: call i32 @_Z12foo_overloadi.ifunc(i32 1)
-
-// CHECK: define i32 ()* @_Z12foo_overloadv.resolver() comdat
-// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge
-// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge
-// CHECK: ret i32 ()* @_Z12foo_overloadv.sse4.2
-// CHECK: ret i32 ()* @_Z12foo_overloadv
-
-// CHECK: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat
-// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge
-// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge
-// CHECK: ret i32 (i32)* @_Z12foo_overloadi.sse4.2
-// CHECK: ret i32 (i32)* @_Z12foo_overloadi
-
-// CHECK: declare i32 @_Z12foo_overloadv.arch_sandybridge()
-// CHECK: declare i32 @_Z12foo_overloadi.arch_sandybridge(i32)
+// LINUX: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver
+// LINUX: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver
+
+// LINUX: define i32 @_Z12foo_overloadi.sse4.2(i32)
+// LINUX: ret i32 0
+// LINUX: define i32 @_Z12foo_overloadi.arch_ivybridge(i32)
+// LINUX: ret i32 1
+// LINUX: define i32 @_Z12foo_overloadi(i32)
+// LINUX: ret i32 2
+// LINUX: define i32 @_Z12foo_overloadv.sse4.2()
+// LINUX: ret i32 0
+// LINUX: define i32 @_Z12foo_overloadv.arch_ivybridge()
+// LINUX: ret i32 1
+// LINUX: define i32 @_Z12foo_overloadv()
+// LINUX: ret i32 2
+
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z.sse4.2"(i32)
+// WINDOWS: ret i32 0
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z.arch_ivybridge"(i32)
+// WINDOWS: ret i32 1
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z"(i32)
+// WINDOWS: ret i32 2
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ.sse4.2"()
+// WINDOWS: ret i32 0
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ.arch_ivybridge"()
+// WINDOWS: ret i32 1
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ"()
+// WINDOWS: ret i32 2
+
+// LINUX: define i32 @_Z4bar2v()
+// LINUX: call i32 @_Z12foo_overloadv.ifunc()
+// LINUX: call i32 @_Z12foo_overloadi.ifunc(i32 1)
+
+// WINDOWS: define dso_local i32 @"?bar2@@YAHXZ"()
+// WINDOWS: call i32 @"?foo_overload@@YAHXZ.resolver"()
+// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.resolver"(i32 1)
+
+// LINUX: define i32 ()* @_Z12foo_overloadv.resolver() comdat
+// LINUX: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge
+// LINUX: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge
+// LINUX: ret i32 ()* @_Z12foo_overloadv.sse4.2
+// LINUX: ret i32 ()* @_Z12foo_overloadv
+
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHXZ.resolver"() comdat
+// WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_sandybridge"
+// WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_ivybridge"
+// WINDOWS: call i32 @"?foo_overload@@YAHXZ.sse4.2"
+// WINDOWS: call i32 @"?foo_overload@@YAHXZ"
+
+// LINUX: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat
+// LINUX: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge
+// LINUX: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge
+// LINUX: ret i32 (i32)* @_Z12foo_overloadi.sse4.2
+// LINUX: ret i32 (i32)* @_Z12foo_overloadi
+
+// WINDOWS: define dso_local i32 @"?foo_overload@@YAHH@Z.resolver"(i32) comdat
+// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.arch_sandybridge"
+// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.arch_ivybridge"
+// WINDOWS: call i32 @"?foo_overload@@YAHH@Z.sse4.2"
+// WINDOWS: call i32 @"?foo_overload@@YAHH@Z"
+
+// LINUX: declare i32 @_Z12foo_overloadv.arch_sandybridge()
+// LINUX: declare i32 @_Z12foo_overloadi.arch_sandybridge(i32)
+
+// WINDOWS: declare dso_local i32 @"?foo_overload@@YAHXZ.arch_sandybridge"()
+// WINDOWS: declare dso_local i32 @"?foo_overload@@YAHH@Z.arch_sandybridge"(i32)
diff --git a/test/CodeGenCXX/auto-var-init.cpp b/test/CodeGenCXX/auto-var-init.cpp
new file mode 100644
index 000000000000..0d13c0af4e8f
--- /dev/null
+++ b/test/CodeGenCXX/auto-var-init.cpp
@@ -0,0 +1,1350 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO
+
+template<typename T> void used(T &) noexcept;
+
+#define TEST_UNINIT(NAME, TYPE) \
+ using type_##NAME = TYPE; \
+ void test_##NAME##_uninit() { \
+ type_##NAME uninit; \
+ used(uninit); \
+ }
+
+// Value initialization on scalars, aggregate initialization on aggregates.
+#define TEST_BRACES(NAME, TYPE) \
+ using type_##NAME = TYPE; \
+ void test_##NAME##_braces() { \
+ type_##NAME braces = {}; \
+ used(braces); \
+ }
+
+#define TEST_CUSTOM(NAME, TYPE, ...) \
+ using type_##NAME = TYPE; \
+ void test_##NAME##_custom() { \
+ type_##NAME custom __VA_ARGS__; \
+ used(custom); \
+ }
+
+// None of the synthesized globals should contain `undef`.
+// PATTERN-NOT: undef
+// ZERO-NOT: undef
+
+// PATTERN: @__const.test_empty_uninit.uninit = private unnamed_addr constant %struct.empty { i8 -86 }, align 1
+struct empty {};
+// PATTERN: @__const.test_small_uninit.uninit = private unnamed_addr constant %struct.small { i8 -86 }, align 1
+// PATTERN: @__const.test_small_custom.custom = private unnamed_addr constant %struct.small { i8 42 }, align 1
+// ZERO: @__const.test_small_custom.custom = private unnamed_addr constant %struct.small { i8 42 }, align 1
+struct small { char c; };
+// PATTERN: @__const.test_smallinit_uninit.uninit = private unnamed_addr constant %struct.smallinit { i8 -86 }, align 1
+// PATTERN: @__const.test_smallinit_braces.braces = private unnamed_addr constant %struct.smallinit { i8 -86 }, align 1
+// PATTERN: @__const.test_smallinit_custom.custom = private unnamed_addr constant %struct.smallinit { i8 -86 }, align 1
+struct smallinit { char c = 42; };
+// PATTERN: @__const.test_smallpartinit_uninit.uninit = private unnamed_addr constant %struct.smallpartinit { i8 -86, i8 -86 }, align 1
+// PATTERN: @__const.test_smallpartinit_braces.braces = private unnamed_addr constant %struct.smallpartinit { i8 -86, i8 -86 }, align 1
+// PATTERN: @__const.test_smallpartinit_custom.custom = private unnamed_addr constant %struct.smallpartinit { i8 -86, i8 -86 }, align 1
+struct smallpartinit { char c = 42, d; };
+// PATTERN: @__const.test_nullinit_uninit.uninit = private unnamed_addr constant %struct.nullinit { i8* inttoptr (i64 -6148914691236517206 to i8*) }, align 8
+// PATTERN: @__const.test_nullinit_braces.braces = private unnamed_addr constant %struct.nullinit { i8* inttoptr (i64 -6148914691236517206 to i8*) }, align 8
+// PATTERN: @__const.test_nullinit_custom.custom = private unnamed_addr constant %struct.nullinit { i8* inttoptr (i64 -6148914691236517206 to i8*) }, align 8
+struct nullinit { char* null = nullptr; };
+// PATTERN: @__const.test_padded_uninit.uninit = private unnamed_addr constant %struct.padded { i8 -86, i32 -1431655766 }, align 4
+// PATTERN: @__const.test_padded_custom.custom = private unnamed_addr constant %struct.padded { i8 42, i32 13371337 }, align 4
+// ZERO: @__const.test_padded_custom.custom = private unnamed_addr constant %struct.padded { i8 42, i32 13371337 }, align 4
+struct padded { char c; int i; };
+// PATTERN: @__const.test_paddednullinit_uninit.uninit = private unnamed_addr constant %struct.paddednullinit { i8 -86, i32 -1431655766 }, align 4
+// PATTERN: @__const.test_paddednullinit_braces.braces = private unnamed_addr constant %struct.paddednullinit { i8 -86, i32 -1431655766 }, align 4
+// PATTERN: @__const.test_paddednullinit_custom.custom = private unnamed_addr constant %struct.paddednullinit { i8 -86, i32 -1431655766 }, align 4
+struct paddednullinit { char c = 0; int i = 0; };
+// PATTERN: @__const.test_bitfield_uninit.uninit = private unnamed_addr constant %struct.bitfield { i8 -86, [3 x i8] c"\AA\AA\AA" }, align 4
+// PATTERN: @__const.test_bitfield_custom.custom = private unnamed_addr constant %struct.bitfield { i8 20, [3 x i8] zeroinitializer }, align 4
+// ZERO: @__const.test_bitfield_custom.custom = private unnamed_addr constant %struct.bitfield { i8 20, [3 x i8] zeroinitializer }, align 4
+struct bitfield { int i : 4; int j : 2; };
+// PATTERN: @__const.test_bitfieldaligned_uninit.uninit = private unnamed_addr constant %struct.bitfieldaligned { i8 -86, [3 x i8] c"\AA\AA\AA", i8 -86, [3 x i8] c"\AA\AA\AA" }, align 4
+// PATTERN: @__const.test_bitfieldaligned_custom.custom = private unnamed_addr constant %struct.bitfieldaligned { i8 4, [3 x i8] zeroinitializer, i8 1, [3 x i8] zeroinitializer }, align 4
+// ZERO: @__const.test_bitfieldaligned_custom.custom = private unnamed_addr constant %struct.bitfieldaligned { i8 4, [3 x i8] zeroinitializer, i8 1, [3 x i8] zeroinitializer }, align 4
+struct bitfieldaligned { int i : 4; int : 0; int j : 2; };
+struct big { unsigned a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; };
+// PATTERN: @__const.test_arraytail_uninit.uninit = private unnamed_addr constant %struct.arraytail { i32 -1431655766, [0 x i32] zeroinitializer }, align 4
+// PATTERN: @__const.test_arraytail_custom.custom = private unnamed_addr constant %struct.arraytail { i32 57005, [0 x i32] zeroinitializer }, align 4
+// ZERO: @__const.test_arraytail_custom.custom = private unnamed_addr constant %struct.arraytail { i32 57005, [0 x i32] zeroinitializer }, align 4
+struct arraytail { int i; int arr[]; };
+// PATTERN: @__const.test_int1_uninit.uninit = private unnamed_addr constant [1 x i32] [i32 -1431655766], align 4
+// PATTERN: @__const.test_int1_custom.custom = private unnamed_addr constant [1 x i32] [i32 858993459], align 4
+// ZERO: @__const.test_int1_custom.custom = private unnamed_addr constant [1 x i32] [i32 858993459], align 4
+// PATTERN: @__const.test_bool4_uninit.uninit = private unnamed_addr constant [4 x i8] c"\AA\AA\AA\AA", align 1
+// PATTERN: @__const.test_bool4_custom.custom = private unnamed_addr constant [4 x i8] c"\01\01\01\01", align 1
+// ZERO: @__const.test_bool4_custom.custom = private unnamed_addr constant [4 x i8] c"\01\01\01\01", align 1
+// PATTERN: @__const.test_intptr4_uninit.uninit = private unnamed_addr constant [4 x i32*] [i32* inttoptr (i64 -6148914691236517206 to i32*), i32* inttoptr (i64 -6148914691236517206 to i32*), i32* inttoptr (i64 -6148914691236517206 to i32*), i32* inttoptr (i64 -6148914691236517206 to i32*)], align 16
+// PATTERN: @__const.test_intptr4_custom.custom = private unnamed_addr constant [4 x i32*] [i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*)], align 16
+// ZERO: @__const.test_intptr4_custom.custom = private unnamed_addr constant [4 x i32*] [i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*), i32* inttoptr (i64 572662306 to i32*)], align 16
+// PATTERN: @__const.test_tailpad4_uninit.uninit = private unnamed_addr constant [4 x %struct.tailpad] [%struct.tailpad { i16 -21846, i8 -86 }, %struct.tailpad { i16 -21846, i8 -86 }, %struct.tailpad { i16 -21846, i8 -86 }, %struct.tailpad { i16 -21846, i8 -86 }], align 16
+// PATTERN: @__const.test_tailpad4_custom.custom = private unnamed_addr constant [4 x %struct.tailpad] [%struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }], align 16
+// ZERO: @__const.test_tailpad4_custom.custom = private unnamed_addr constant [4 x %struct.tailpad] [%struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }, %struct.tailpad { i16 257, i8 1 }], align 16
+struct tailpad { short s; char c; };
+// PATTERN: @__const.test_atomicnotlockfree_uninit.uninit = private unnamed_addr constant %struct.notlockfree { [4 x i64] [i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206] }, align 8
+struct notlockfree { long long a[4]; };
+// PATTERN: @__const.test_atomicpadded_uninit.uninit = private unnamed_addr constant %struct.padded { i8 -86, i32 -1431655766 }, align 8
+// PATTERN: @__const.test_atomictailpad_uninit.uninit = private unnamed_addr constant %struct.tailpad { i16 -21846, i8 -86 }, align 4
+// PATTERN: @__const.test_complexfloat_uninit.uninit = private unnamed_addr constant { float, float } { float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000 }, align 4
+// PATTERN: @__const.test_complexfloat_braces.braces = private unnamed_addr constant { float, float } { float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000 }, align 4
+// PATTERN: @__const.test_complexfloat_custom.custom = private unnamed_addr constant { float, float } { float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000 }, align 4
+// PATTERN: @__const.test_complexdouble_uninit.uninit = private unnamed_addr constant { double, double } { double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF }, align 8
+// PATTERN: @__const.test_complexdouble_braces.braces = private unnamed_addr constant { double, double } { double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF }, align 8
+// PATTERN: @__const.test_complexdouble_custom.custom = private unnamed_addr constant { double, double } { double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF }, align 8
+// PATTERN: @__const.test_semivolatile_uninit.uninit = private unnamed_addr constant %struct.semivolatile { i32 -1431655766, i32 -1431655766 }, align 4
+// PATTERN: @__const.test_semivolatile_custom.custom = private unnamed_addr constant %struct.semivolatile { i32 1145324612, i32 1145324612 }, align 4
+struct semivolatile { int i; volatile int vi; };
+// PATTERN: @__const.test_semivolatileinit_uninit.uninit = private unnamed_addr constant %struct.semivolatileinit { i32 -1431655766, i32 -1431655766 }, align 4
+// PATTERN: @__const.test_semivolatileinit_braces.braces = private unnamed_addr constant %struct.semivolatileinit { i32 -1431655766, i32 -1431655766 }, align 4
+// PATTERN: @__const.test_semivolatileinit_custom.custom = private unnamed_addr constant %struct.semivolatileinit { i32 -1431655766, i32 -1431655766 }, align 4
+// ZERO: @__const.test_semivolatile_custom.custom = private unnamed_addr constant %struct.semivolatile { i32 1145324612, i32 1145324612 }, align 4
+struct semivolatileinit { int i = 0x11111111; volatile int vi = 0x11111111; };
+// PATTERN: @__const.test_base_uninit.uninit = private unnamed_addr constant %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, align 8
+// PATTERN: @__const.test_base_braces.braces = private unnamed_addr constant %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, align 8
+struct base { virtual ~base(); };
+// PATTERN: @__const.test_derived_uninit.uninit = private unnamed_addr constant %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } }, align 8
+// PATTERN: @__const.test_derived_braces.braces = private unnamed_addr constant %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } }, align 8
+struct derived : public base {};
+// PATTERN: @__const.test_virtualderived_uninit.uninit = private unnamed_addr constant %struct.virtualderived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } } }, align 8
+// PATTERN: @__const.test_virtualderived_braces.braces = private unnamed_addr constant %struct.virtualderived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) }, %struct.derived { %struct.base { i32 (...)** inttoptr (i64 -6148914691236517206 to i32 (...)**) } } }, align 8
+struct virtualderived : public virtual base, public virtual derived {};
+// PATTERN: @__const.test_matching_uninit.uninit = private unnamed_addr constant %union.matching { i32 -1431655766 }, align 4
+// PATTERN: @__const.test_matching_custom.custom = private unnamed_addr constant { float } { float 6.145500e+04 }, align 4
+union matching { int i; float f; };
+// PATTERN: @__const.test_matchingreverse_uninit.uninit = private unnamed_addr constant %union.matchingreverse { float 0xFFFFFFFFE0000000 }, align 4
+// PATTERN: @__const.test_matchingreverse_custom.custom = private unnamed_addr constant { i32 } { i32 61455 }, align 4
+// ZERO: @__const.test_matching_custom.custom = private unnamed_addr constant { float } { float 6.145500e+04 }, align 4
+union matchingreverse { float f; int i; };
+// PATTERN: @__const.test_unmatched_uninit.uninit = private unnamed_addr constant %union.unmatched { i32 -1431655766 }, align 4
+// PATTERN: @__const.test_unmatched_custom.custom = private unnamed_addr constant %union.unmatched { i32 1001242351 }, align 4
+// ZERO: @__const.test_matchingreverse_custom.custom = private unnamed_addr constant { i32 } { i32 61455 }, align 4
+union unmatched { char c; int i; };
+// PATTERN: @__const.test_unmatchedreverse_uninit.uninit = private unnamed_addr constant %union.unmatchedreverse { i32 -1431655766 }, align 4
+// PATTERN: @__const.test_unmatchedreverse_custom.custom = private unnamed_addr constant { i8, [3 x i8] } { i8 42, [3 x i8] zeroinitializer }, align 4
+// ZERO: @__const.test_unmatched_custom.custom = private unnamed_addr constant %union.unmatched { i32 1001242351 }, align 4
+union unmatchedreverse { int i; char c; };
+// PATTERN: @__const.test_unmatchedfp_uninit.uninit = private unnamed_addr constant %union.unmatchedfp { double 0xFFFFFFFFFFFFFFFF }, align 8
+// PATTERN: @__const.test_unmatchedfp_custom.custom = private unnamed_addr constant %union.unmatchedfp { double 0x400921FB54442D18 }, align 8
+// ZERO: @__const.test_unmatchedreverse_custom.custom = private unnamed_addr constant { i8, [3 x i8] } { i8 42, [3 x i8] zeroinitializer }, align 4
+// ZERO: @__const.test_unmatchedfp_custom.custom = private unnamed_addr constant %union.unmatchedfp { double 0x400921FB54442D18 }, align 8
+union unmatchedfp { float f; double d; };
+enum emptyenum {};
+enum smallenum { VALUE };
+
+extern "C" {
+
+TEST_UNINIT(char, char);
+// CHECK-LABEL: @test_char_uninit()
+// CHECK: %uninit = alloca i8, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_char_uninit()
+// PATTERN: store i8 -86, i8* %uninit, align 1
+// ZERO-LABEL: @test_char_uninit()
+// ZERO: store i8 0, i8* %uninit, align 1
+
+TEST_BRACES(char, char);
+// CHECK-LABEL: @test_char_braces()
+// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(uchar, unsigned char);
+// CHECK-LABEL: @test_uchar_uninit()
+// CHECK: %uninit = alloca i8, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_uchar_uninit()
+// PATTERN: store i8 -86, i8* %uninit, align 1
+// ZERO-LABEL: @test_uchar_uninit()
+// ZERO: store i8 0, i8* %uninit, align 1
+
+TEST_BRACES(uchar, unsigned char);
+// CHECK-LABEL: @test_uchar_braces()
+// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(schar, signed char);
+// CHECK-LABEL: @test_schar_uninit()
+// CHECK: %uninit = alloca i8, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_schar_uninit()
+// PATTERN: store i8 -86, i8* %uninit, align 1
+// ZERO-LABEL: @test_schar_uninit()
+// ZERO: store i8 0, i8* %uninit, align 1
+
+TEST_BRACES(schar, signed char);
+// CHECK-LABEL: @test_schar_braces()
+// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(wchar_t, wchar_t);
+// CHECK-LABEL: @test_wchar_t_uninit()
+// CHECK: %uninit = alloca i32, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_wchar_t_uninit()
+// PATTERN: store i32 -1431655766, i32* %uninit, align
+// ZERO-LABEL: @test_wchar_t_uninit()
+// ZERO: store i32 0, i32* %uninit, align
+
+TEST_BRACES(wchar_t, wchar_t);
+// CHECK-LABEL: @test_wchar_t_braces()
+// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(short, short);
+// CHECK-LABEL: @test_short_uninit()
+// CHECK: %uninit = alloca i16, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_short_uninit()
+// PATTERN: store i16 -21846, i16* %uninit, align
+// ZERO-LABEL: @test_short_uninit()
+// ZERO: store i16 0, i16* %uninit, align
+
+TEST_BRACES(short, short);
+// CHECK-LABEL: @test_short_braces()
+// CHECK: %braces = alloca i16, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i16 0, i16* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(ushort, unsigned short);
+// CHECK-LABEL: @test_ushort_uninit()
+// CHECK: %uninit = alloca i16, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_ushort_uninit()
+// PATTERN: store i16 -21846, i16* %uninit, align
+// ZERO-LABEL: @test_ushort_uninit()
+// ZERO: store i16 0, i16* %uninit, align
+
+TEST_BRACES(ushort, unsigned short);
+// CHECK-LABEL: @test_ushort_braces()
+// CHECK: %braces = alloca i16, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i16 0, i16* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(int, int);
+// CHECK-LABEL: @test_int_uninit()
+// CHECK: %uninit = alloca i32, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_int_uninit()
+// PATTERN: store i32 -1431655766, i32* %uninit, align
+// ZERO-LABEL: @test_int_uninit()
+// ZERO: store i32 0, i32* %uninit, align
+
+TEST_BRACES(int, int);
+// CHECK-LABEL: @test_int_braces()
+// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(unsigned, unsigned);
+// CHECK-LABEL: @test_unsigned_uninit()
+// CHECK: %uninit = alloca i32, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_unsigned_uninit()
+// PATTERN: store i32 -1431655766, i32* %uninit, align
+// ZERO-LABEL: @test_unsigned_uninit()
+// ZERO: store i32 0, i32* %uninit, align
+
+TEST_BRACES(unsigned, unsigned);
+// CHECK-LABEL: @test_unsigned_braces()
+// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(long, long);
+// CHECK-LABEL: @test_long_uninit()
+// CHECK: %uninit = alloca i64, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_long_uninit()
+// PATTERN: store i64 -6148914691236517206, i64* %uninit, align
+// ZERO-LABEL: @test_long_uninit()
+// ZERO: store i64 0, i64* %uninit, align
+
+TEST_BRACES(long, long);
+// CHECK-LABEL: @test_long_braces()
+// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(ulong, unsigned long);
+// CHECK-LABEL: @test_ulong_uninit()
+// CHECK: %uninit = alloca i64, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_ulong_uninit()
+// PATTERN: store i64 -6148914691236517206, i64* %uninit, align
+// ZERO-LABEL: @test_ulong_uninit()
+// ZERO: store i64 0, i64* %uninit, align
+
+TEST_BRACES(ulong, unsigned long);
+// CHECK-LABEL: @test_ulong_braces()
+// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(longlong, long long);
+// CHECK-LABEL: @test_longlong_uninit()
+// CHECK: %uninit = alloca i64, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_longlong_uninit()
+// PATTERN: store i64 -6148914691236517206, i64* %uninit, align
+// ZERO-LABEL: @test_longlong_uninit()
+// ZERO: store i64 0, i64* %uninit, align
+
+TEST_BRACES(longlong, long long);
+// CHECK-LABEL: @test_longlong_braces()
+// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(ulonglong, unsigned long long);
+// CHECK-LABEL: @test_ulonglong_uninit()
+// CHECK: %uninit = alloca i64, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_ulonglong_uninit()
+// PATTERN: store i64 -6148914691236517206, i64* %uninit, align
+// ZERO-LABEL: @test_ulonglong_uninit()
+// ZERO: store i64 0, i64* %uninit, align
+
+TEST_BRACES(ulonglong, unsigned long long);
+// CHECK-LABEL: @test_ulonglong_braces()
+// CHECK: %braces = alloca i64, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i64 0, i64* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(int128, __int128);
+// CHECK-LABEL: @test_int128_uninit()
+// CHECK: %uninit = alloca i128, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_int128_uninit()
+// PATTERN: store i128 -113427455640312821154458202477256070486, i128* %uninit, align
+// ZERO-LABEL: @test_int128_uninit()
+// ZERO: store i128 0, i128* %uninit, align
+
+TEST_BRACES(int128, __int128);
+// CHECK-LABEL: @test_int128_braces()
+// CHECK: %braces = alloca i128, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i128 0, i128* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(uint128, unsigned __int128);
+// CHECK-LABEL: @test_uint128_uninit()
+// CHECK: %uninit = alloca i128, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_uint128_uninit()
+// PATTERN: store i128 -113427455640312821154458202477256070486, i128* %uninit, align
+// ZERO-LABEL: @test_uint128_uninit()
+// ZERO: store i128 0, i128* %uninit, align
+
+TEST_BRACES(uint128, unsigned __int128);
+// CHECK-LABEL: @test_uint128_braces()
+// CHECK: %braces = alloca i128, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i128 0, i128* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+
+TEST_UNINIT(fp16, __fp16);
+// CHECK-LABEL: @test_fp16_uninit()
+// CHECK: %uninit = alloca half, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_fp16_uninit()
+// PATTERN: store half 0xHFFFF, half* %uninit, align
+// ZERO-LABEL: @test_fp16_uninit()
+// ZERO: store half 0xH0000, half* %uninit, align
+
+TEST_BRACES(fp16, __fp16);
+// CHECK-LABEL: @test_fp16_braces()
+// CHECK: %braces = alloca half, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store half 0xH0000, half* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(float, float);
+// CHECK-LABEL: @test_float_uninit()
+// CHECK: %uninit = alloca float, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_float_uninit()
+// PATTERN: store float 0xFFFFFFFFE0000000, float* %uninit, align
+// ZERO-LABEL: @test_float_uninit()
+// ZERO: store float 0.000000e+00, float* %uninit, align
+
+TEST_BRACES(float, float);
+// CHECK-LABEL: @test_float_braces()
+// CHECK: %braces = alloca float, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store float 0.000000e+00, float* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(double, double);
+// CHECK-LABEL: @test_double_uninit()
+// CHECK: %uninit = alloca double, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_double_uninit()
+// PATTERN: store double 0xFFFFFFFFFFFFFFFF, double* %uninit, align
+// ZERO-LABEL: @test_double_uninit()
+// ZERO: store double 0.000000e+00, double* %uninit, align
+
+TEST_BRACES(double, double);
+// CHECK-LABEL: @test_double_braces()
+// CHECK: %braces = alloca double, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store double 0.000000e+00, double* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(longdouble, long double);
+// CHECK-LABEL: @test_longdouble_uninit()
+// CHECK: %uninit = alloca x86_fp80, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_longdouble_uninit()
+// PATTERN: store x86_fp80 0xKFFFFFFFFFFFFFFFFFFFF, x86_fp80* %uninit, align
+// ZERO-LABEL: @test_longdouble_uninit()
+// ZERO: store x86_fp80 0xK00000000000000000000, x86_fp80* %uninit, align
+
+TEST_BRACES(longdouble, long double);
+// CHECK-LABEL: @test_longdouble_braces()
+// CHECK: %braces = alloca x86_fp80, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store x86_fp80 0xK00000000000000000000, x86_fp80* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+
+TEST_UNINIT(intptr, int*);
+// CHECK-LABEL: @test_intptr_uninit()
+// CHECK: %uninit = alloca i32*, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_intptr_uninit()
+// PATTERN: store i32* inttoptr (i64 -6148914691236517206 to i32*), i32** %uninit, align
+// ZERO-LABEL: @test_intptr_uninit()
+// ZERO: store i32* null, i32** %uninit, align
+
+TEST_BRACES(intptr, int*);
+// CHECK-LABEL: @test_intptr_braces()
+// CHECK: %braces = alloca i32*, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32* null, i32** %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(intptrptr, int**);
+// CHECK-LABEL: @test_intptrptr_uninit()
+// CHECK: %uninit = alloca i32**, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_intptrptr_uninit()
+// PATTERN: store i32** inttoptr (i64 -6148914691236517206 to i32**), i32*** %uninit, align
+// ZERO-LABEL: @test_intptrptr_uninit()
+// ZERO: store i32** null, i32*** %uninit, align
+
+TEST_BRACES(intptrptr, int**);
+// CHECK-LABEL: @test_intptrptr_braces()
+// CHECK: %braces = alloca i32**, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32** null, i32*** %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(function, void(*)());
+// CHECK-LABEL: @test_function_uninit()
+// CHECK: %uninit = alloca void ()*, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_function_uninit()
+// PATTERN: store void ()* inttoptr (i64 -6148914691236517206 to void ()*), void ()** %uninit, align
+// ZERO-LABEL: @test_function_uninit()
+// ZERO: store void ()* null, void ()** %uninit, align
+
+TEST_BRACES(function, void(*)());
+// CHECK-LABEL: @test_function_braces()
+// CHECK: %braces = alloca void ()*, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store void ()* null, void ()** %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(bool, bool);
+// CHECK-LABEL: @test_bool_uninit()
+// CHECK: %uninit = alloca i8, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_bool_uninit()
+// PATTERN: store i8 -86, i8* %uninit, align 1
+// ZERO-LABEL: @test_bool_uninit()
+// ZERO: store i8 0, i8* %uninit, align 1
+
+TEST_BRACES(bool, bool);
+// CHECK-LABEL: @test_bool_braces()
+// CHECK: %braces = alloca i8, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i8 0, i8* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+
+TEST_UNINIT(empty, empty);
+// CHECK-LABEL: @test_empty_uninit()
+// CHECK: %uninit = alloca %struct.empty, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_empty_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_empty_uninit.uninit
+// ZERO-LABEL: @test_empty_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(empty, empty);
+// CHECK-LABEL: @test_empty_braces()
+// CHECK: %braces = alloca %struct.empty, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(small, small);
+// CHECK-LABEL: @test_small_uninit()
+// CHECK: %uninit = alloca %struct.small, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_small_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_small_uninit.uninit
+// ZERO-LABEL: @test_small_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(small, small);
+// CHECK-LABEL: @test_small_braces()
+// CHECK: %braces = alloca %struct.small, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 1, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(small, small, { 42 });
+// CHECK-LABEL: @test_small_custom()
+// CHECK: %custom = alloca %struct.small, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(smallinit, smallinit);
+// CHECK-LABEL: @test_smallinit_uninit()
+// CHECK: %uninit = alloca %struct.smallinit, align
+// CHECK-NEXT: call void @{{.*}}smallinit{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+
+TEST_BRACES(smallinit, smallinit);
+// CHECK-LABEL: @test_smallinit_braces()
+// CHECK: %braces = alloca %struct.smallinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallinit, %struct.smallinit* %braces, i32 0, i32 0
+// CHECK-NEXT: store i8 42, i8* %[[C]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(smallinit, smallinit, { 100 });
+// CHECK-LABEL: @test_smallinit_custom()
+// CHECK: %custom = alloca %struct.smallinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallinit, %struct.smallinit* %custom, i32 0, i32 0
+// CHECK-NEXT: store i8 100, i8* %[[C]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(smallpartinit, smallpartinit);
+// CHECK-LABEL: @test_smallpartinit_uninit()
+// CHECK: %uninit = alloca %struct.smallpartinit, align
+// CHECK-NEXT: call void @{{.*}}smallpartinit{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_smallpartinit_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_smallpartinit_uninit.uninit
+// ZERO-LABEL: @test_smallpartinit_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(smallpartinit, smallpartinit);
+// CHECK-LABEL: @test_smallpartinit_braces()
+// CHECK: %braces = alloca %struct.smallpartinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %braces, i32 0, i32 0
+// CHECK-NEXT: store i8 42, i8* %[[C]], align [[ALIGN]]
+// CHECK-NEXT: %[[D:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %braces, i32 0, i32 1
+// CHECK-NEXT: store i8 0, i8* %[[D]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(smallpartinit, smallpartinit, { 100, 42 });
+// CHECK-LABEL: @test_smallpartinit_custom()
+// CHECK: %custom = alloca %struct.smallpartinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %custom, i32 0, i32 0
+// CHECK-NEXT: store i8 100, i8* %[[C]], align [[ALIGN]]
+// CHECK-NEXT: %[[D:[^ ]*]] = getelementptr inbounds %struct.smallpartinit, %struct.smallpartinit* %custom, i32 0, i32 1
+// CHECK-NEXT: store i8 42, i8* %[[D]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(nullinit, nullinit);
+// CHECK-LABEL: @test_nullinit_uninit()
+// CHECK: %uninit = alloca %struct.nullinit, align
+// CHECK-NEXT: call void @{{.*}}nullinit{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+
+TEST_BRACES(nullinit, nullinit);
+// CHECK-LABEL: @test_nullinit_braces()
+// CHECK: %braces = alloca %struct.nullinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[N:[^ ]*]] = getelementptr inbounds %struct.nullinit, %struct.nullinit* %braces, i32 0, i32 0
+// CHECK-NEXT: store i8* null, i8** %[[N]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(nullinit, nullinit, { (char*)"derp" });
+// CHECK-LABEL: @test_nullinit_custom()
+// CHECK: %custom = alloca %struct.nullinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[N:[^ ]*]] = getelementptr inbounds %struct.nullinit, %struct.nullinit* %custom, i32 0, i32 0
+// CHECK-NEXT: store i8* getelementptr inbounds {{.*}}, i8** %[[N]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(padded, padded);
+// CHECK-LABEL: @test_padded_uninit()
+// CHECK: %uninit = alloca %struct.padded, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_padded_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_padded_uninit.uninit
+// ZERO-LABEL: @test_padded_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(padded, padded);
+// CHECK-LABEL: @test_padded_braces()
+// CHECK: %braces = alloca %struct.padded, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(padded, padded, { 42, 13371337 });
+// CHECK-LABEL: @test_padded_custom()
+// CHECK: %custom = alloca %struct.padded, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(paddednullinit, paddednullinit);
+// CHECK-LABEL: @test_paddednullinit_uninit()
+// CHECK: %uninit = alloca %struct.paddednullinit, align
+// CHECK-NEXT: call void @{{.*}}paddednullinit{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_paddednullinit_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_paddednullinit_uninit.uninit
+// ZERO-LABEL: @test_paddednullinit_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(paddednullinit, paddednullinit);
+// CHECK-LABEL: @test_paddednullinit_braces()
+// CHECK: %braces = alloca %struct.paddednullinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %braces, i32 0, i32 0
+// CHECK-NEXT: store i8 0, i8* %[[C]], align [[ALIGN]]
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %braces, i32 0, i32 1
+// CHECK-NEXT: store i32 0, i32* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(paddednullinit, paddednullinit, { 42, 13371337 });
+// CHECK-LABEL: @test_paddednullinit_custom()
+// CHECK: %custom = alloca %struct.paddednullinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[C:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %custom, i32 0, i32 0
+// CHECK-NEXT: store i8 42, i8* %[[C]], align [[ALIGN]]
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.paddednullinit, %struct.paddednullinit* %custom, i32 0, i32 1
+// CHECK-NEXT: store i32 13371337, i32* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(bitfield, bitfield);
+// CHECK-LABEL: @test_bitfield_uninit()
+// CHECK: %uninit = alloca %struct.bitfield, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_bitfield_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_bitfield_uninit.uninit
+// ZERO-LABEL: @test_bitfield_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(bitfield, bitfield);
+// CHECK-LABEL: @test_bitfield_braces()
+// CHECK: %braces = alloca %struct.bitfield, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(bitfield, bitfield, { 4, 1 });
+// CHECK-LABEL: @test_bitfield_custom()
+// CHECK: %custom = alloca %struct.bitfield, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(bitfieldaligned, bitfieldaligned);
+// CHECK-LABEL: @test_bitfieldaligned_uninit()
+// CHECK: %uninit = alloca %struct.bitfieldaligned, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_bitfieldaligned_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_bitfieldaligned_uninit.uninit
+// ZERO-LABEL: @test_bitfieldaligned_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(bitfieldaligned, bitfieldaligned);
+// CHECK-LABEL: @test_bitfieldaligned_braces()
+// CHECK: %braces = alloca %struct.bitfieldaligned, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(bitfieldaligned, bitfieldaligned, { 4, 1 });
+// CHECK-LABEL: @test_bitfieldaligned_custom()
+// CHECK: %custom = alloca %struct.bitfieldaligned, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(big, big);
+// CHECK-LABEL: @test_big_uninit()
+// CHECK: %uninit = alloca %struct.big, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_big_uninit()
+// PATTERN: call void @llvm.memset{{.*}}, i8 -86,
+// ZERO-LABEL: @test_big_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(big, big);
+// CHECK-LABEL: @test_big_braces()
+// CHECK: %braces = alloca %struct.big, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 104, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(big, big, { 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA });
+// CHECK-LABEL: @test_big_custom()
+// CHECK: %custom = alloca %struct.big, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 -86, i64 104, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(arraytail, arraytail);
+// CHECK-LABEL: @test_arraytail_uninit()
+// CHECK: %uninit = alloca %struct.arraytail, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_arraytail_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_arraytail_uninit.uninit
+// ZERO-LABEL: @test_arraytail_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(arraytail, arraytail);
+// CHECK-LABEL: @test_arraytail_braces()
+// CHECK: %braces = alloca %struct.arraytail, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(arraytail, arraytail, { 0xdead });
+// CHECK-LABEL: @test_arraytail_custom()
+// CHECK: %custom = alloca %struct.arraytail, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+
+TEST_UNINIT(int0, int[0]);
+// CHECK-LABEL: @test_int0_uninit()
+// CHECK: %uninit = alloca [0 x i32], align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_int0_uninit()
+// PATTERN: %uninit = alloca [0 x i32], align
+// PATTERN-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// ZERO-LABEL: @test_int0_uninit()
+// ZERO: %uninit = alloca [0 x i32], align
+// ZERO-NEXT: call void @{{.*}}used{{.*}}%uninit)
+
+TEST_BRACES(int0, int[0]);
+// CHECK-LABEL: @test_int0_braces()
+// CHECK: %braces = alloca [0 x i32], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 0, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(int1, int[1]);
+// CHECK-LABEL: @test_int1_uninit()
+// CHECK: %uninit = alloca [1 x i32], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_int1_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_int1_uninit.uninit
+// ZERO-LABEL: @test_int1_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(int1, int[1]);
+// CHECK-LABEL: @test_int1_braces()
+// CHECK: %braces = alloca [1 x i32], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(int1, int[1], { 0x33333333 });
+// CHECK-LABEL: @test_int1_custom()
+// CHECK: %custom = alloca [1 x i32], align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(int64, int[64]);
+// CHECK-LABEL: @test_int64_uninit()
+// CHECK: %uninit = alloca [64 x i32], align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_int64_uninit()
+// PATTERN: call void @llvm.memset{{.*}}, i8 -86,
+// ZERO-LABEL: @test_int64_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(int64, int[64]);
+// CHECK-LABEL: @test_int64_braces()
+// CHECK: %braces = alloca [64 x i32], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 256, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(int64, int[64], = { 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111 });
+// CHECK-LABEL: @test_int64_custom()
+// CHECK: %custom = alloca [64 x i32], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 17, i64 256, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(bool4, bool[4]);
+// CHECK-LABEL: @test_bool4_uninit()
+// CHECK: %uninit = alloca [4 x i8], align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_bool4_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_bool4_uninit.uninit
+// ZERO-LABEL: @test_bool4_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(bool4, bool[4]);
+// CHECK-LABEL: @test_bool4_braces()
+// CHECK: %braces = alloca [4 x i8], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(bool4, bool[4], { true, true, true, true });
+// CHECK-LABEL: @test_bool4_custom()
+// CHECK: %custom = alloca [4 x i8], align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(intptr4, int*[4]);
+// CHECK-LABEL: @test_intptr4_uninit()
+// CHECK: %uninit = alloca [4 x i32*], align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_intptr4_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_intptr4_uninit.uninit
+// ZERO-LABEL: @test_intptr4_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(intptr4, int*[4]);
+// CHECK-LABEL: @test_intptr4_braces()
+// CHECK: %braces = alloca [4 x i32*], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 32, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+ TEST_CUSTOM(intptr4, int*[4], = { (int*)0x22222222, (int*)0x22222222, (int*)0x22222222, (int*)0x22222222 });
+// CHECK-LABEL: @test_intptr4_custom()
+// CHECK: %custom = alloca [4 x i32*], align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(tailpad4, tailpad[4]);
+// CHECK-LABEL: @test_tailpad4_uninit()
+// CHECK: %uninit = alloca [4 x %struct.tailpad], align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_tailpad4_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_tailpad4_uninit.uninit
+// ZERO-LABEL: @test_tailpad4_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(tailpad4, tailpad[4]);
+// CHECK-LABEL: @test_tailpad4_braces()
+// CHECK: %braces = alloca [4 x %struct.tailpad], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 16, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(tailpad4, tailpad[4], { {257, 1}, {257, 1}, {257, 1}, {257, 1} });
+// CHECK-LABEL: @test_tailpad4_custom()
+// CHECK: %custom = alloca [4 x %struct.tailpad], align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(tailpad9, tailpad[9]);
+// CHECK-LABEL: @test_tailpad9_uninit()
+// CHECK: %uninit = alloca [9 x %struct.tailpad], align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_tailpad9_uninit()
+// PATTERN: call void @llvm.memset{{.*}}, i8 -86,
+// ZERO-LABEL: @test_tailpad9_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(tailpad9, tailpad[9]);
+// CHECK-LABEL: @test_tailpad9_braces()
+// CHECK: %braces = alloca [9 x %struct.tailpad], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 36, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(tailpad9, tailpad[9], { {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1}, {257, 1} });
+// CHECK-LABEL: @test_tailpad9_custom()
+// CHECK: %custom = alloca [9 x %struct.tailpad], align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 1, i64 36, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+
+TEST_UNINIT(atomicbool, _Atomic(bool));
+// CHECK-LABEL: @test_atomicbool_uninit()
+// CHECK: %uninit = alloca i8, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_atomicbool_uninit()
+// PATTERN: store i8 -86, i8* %uninit, align 1
+// ZERO-LABEL: @test_atomicbool_uninit()
+// ZERO: store i8 0, i8* %uninit, align 1
+
+TEST_UNINIT(atomicint, _Atomic(int));
+// CHECK-LABEL: @test_atomicint_uninit()
+// CHECK: %uninit = alloca i32, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_atomicint_uninit()
+// PATTERN: store i32 -1431655766, i32* %uninit, align 4
+// ZERO-LABEL: @test_atomicint_uninit()
+// ZERO: store i32 0, i32* %uninit, align 4
+
+TEST_UNINIT(atomicdouble, _Atomic(double));
+// CHECK-LABEL: @test_atomicdouble_uninit()
+// CHECK: %uninit = alloca double, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_atomicdouble_uninit()
+// PATTERN: store double 0xFFFFFFFFFFFFFFFF, double* %uninit, align 8
+// ZERO-LABEL: @test_atomicdouble_uninit()
+// ZERO: store double 0.000000e+00, double* %uninit, align 8
+
+TEST_UNINIT(atomicnotlockfree, _Atomic(notlockfree));
+// CHECK-LABEL: @test_atomicnotlockfree_uninit()
+// CHECK: %uninit = alloca %struct.notlockfree, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_atomicnotlockfree_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_atomicnotlockfree_uninit.uninit
+// ZERO-LABEL: @test_atomicnotlockfree_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_UNINIT(atomicpadded, _Atomic(padded));
+// CHECK-LABEL: @test_atomicpadded_uninit()
+// CHECK: %uninit = alloca %struct.padded, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_atomicpadded_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_atomicpadded_uninit.uninit
+// ZERO-LABEL: @test_atomicpadded_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_UNINIT(atomictailpad, _Atomic(tailpad));
+// CHECK-LABEL: @test_atomictailpad_uninit()
+// CHECK: %uninit = alloca %struct.tailpad, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_atomictailpad_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_atomictailpad_uninit.uninit
+// ZERO-LABEL: @test_atomictailpad_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+
+TEST_UNINIT(complexfloat, _Complex float);
+// CHECK-LABEL: @test_complexfloat_uninit()
+// CHECK: %uninit = alloca { float, float }, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_complexfloat_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_complexfloat_uninit.uninit
+// ZERO-LABEL: @test_complexfloat_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(complexfloat, _Complex float);
+// CHECK-LABEL: @test_complexfloat_braces()
+// CHECK: %braces = alloca { float, float }, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %braces, i32 0, i32 0
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %braces, i32 0, i32 1
+// CHECK-NEXT: store float 0.000000e+00, float* %[[R]], align [[ALIGN]]
+// CHECK-NEXT: store float 0.000000e+00, float* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(complexfloat, _Complex float, { 3.1415926535897932384626433, 3.1415926535897932384626433 });
+// CHECK-LABEL: @test_complexfloat_custom()
+// CHECK: %custom = alloca { float, float }, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %custom, i32 0, i32 0
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { float, float }, { float, float }* %custom, i32 0, i32 1
+// CHECK-NEXT: store float 0x400921FB60000000, float* %[[R]], align [[ALIGN]]
+// CHECK-NEXT: store float 0x400921FB60000000, float* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(complexdouble, _Complex double);
+// CHECK-LABEL: @test_complexdouble_uninit()
+// CHECK: %uninit = alloca { double, double }, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_complexdouble_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_complexdouble_uninit.uninit
+// ZERO-LABEL: @test_complexdouble_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(complexdouble, _Complex double);
+// CHECK-LABEL: @test_complexdouble_braces()
+// CHECK: %braces = alloca { double, double }, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %braces, i32 0, i32 0
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %braces, i32 0, i32 1
+// CHECK-NEXT: store double 0.000000e+00, double* %[[R]], align [[ALIGN]]
+// CHECK-NEXT: store double 0.000000e+00, double* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(complexdouble, _Complex double, { 3.1415926535897932384626433, 3.1415926535897932384626433 });
+// CHECK-LABEL: @test_complexdouble_custom()
+// CHECK: %custom = alloca { double, double }, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[R:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %custom, i32 0, i32 0
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds { double, double }, { double, double }* %custom, i32 0, i32 1
+// CHECK-NEXT: store double 0x400921FB54442D18, double* %[[R]], align [[ALIGN]]
+// CHECK-NEXT: store double 0x400921FB54442D18, double* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+
+TEST_UNINIT(volatileint, volatile int);
+// CHECK-LABEL: @test_volatileint_uninit()
+// CHECK: %uninit = alloca i32, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_volatileint_uninit()
+// PATTERN: store volatile i32 -1431655766, i32* %uninit, align 4
+// ZERO-LABEL: @test_volatileint_uninit()
+// ZERO: store volatile i32 0, i32* %uninit, align 4
+
+TEST_BRACES(volatileint, volatile int);
+// CHECK-LABEL: @test_volatileint_braces()
+// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store volatile i32 0, i32* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(semivolatile, semivolatile);
+// CHECK-LABEL: @test_semivolatile_uninit()
+// CHECK: %uninit = alloca %struct.semivolatile, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_semivolatile_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_semivolatile_uninit.uninit
+// ZERO-LABEL: @test_semivolatile_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(semivolatile, semivolatile);
+// CHECK-LABEL: @test_semivolatile_braces()
+// CHECK: %braces = alloca %struct.semivolatile, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(semivolatile, semivolatile, { 0x44444444, 0x44444444 });
+// CHECK-LABEL: @test_semivolatile_custom()
+// CHECK: %custom = alloca %struct.semivolatile, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(semivolatileinit, semivolatileinit);
+// CHECK-LABEL: @test_semivolatileinit_uninit()
+// CHECK: %uninit = alloca %struct.semivolatileinit, align
+// CHECK-NEXT: call void @{{.*}}semivolatileinit{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+
+TEST_BRACES(semivolatileinit, semivolatileinit);
+// CHECK-LABEL: @test_semivolatileinit_braces()
+// CHECK: %braces = alloca %struct.semivolatileinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %braces, i32 0, i32 0
+// CHECK-NEXT: store i32 286331153, i32* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: %[[VI:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %braces, i32 0, i32 1
+// CHECK-NEXT: store volatile i32 286331153, i32* %[[VI]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(semivolatileinit, semivolatileinit, { 0x44444444, 0x44444444 });
+// CHECK-LABEL: @test_semivolatileinit_custom()
+// CHECK: %custom = alloca %struct.semivolatileinit, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: %[[I:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %custom, i32 0, i32 0
+// CHECK-NEXT: store i32 1145324612, i32* %[[I]], align [[ALIGN]]
+// CHECK-NEXT: %[[VI:[^ ]*]] = getelementptr inbounds %struct.semivolatileinit, %struct.semivolatileinit* %custom, i32 0, i32 1
+// CHECK-NEXT: store volatile i32 1145324612, i32* %[[VI]], align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+
+TEST_UNINIT(base, base);
+// CHECK-LABEL: @test_base_uninit()
+// CHECK: %uninit = alloca %struct.base, align
+// CHECK-NEXT: call void @{{.*}}base{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_base_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_base_uninit.uninit
+// ZERO-LABEL: @test_base_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(base, base);
+// CHECK-LABEL: @test_base_braces()
+// CHECK: %braces = alloca %struct.base, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false)
+// CHECK-NEXT: call void @{{.*}}base{{.*}}%braces)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(derived, derived);
+// CHECK-LABEL: @test_derived_uninit()
+// CHECK: %uninit = alloca %struct.derived, align
+// CHECK-NEXT: call void @{{.*}}derived{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_derived_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_derived_uninit.uninit
+// ZERO-LABEL: @test_derived_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(derived, derived);
+// CHECK-LABEL: @test_derived_braces()
+// CHECK: %braces = alloca %struct.derived, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 8, i1 false)
+// CHECK-NEXT: call void @{{.*}}derived{{.*}}%braces)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_UNINIT(virtualderived, virtualderived);
+// CHECK-LABEL: @test_virtualderived_uninit()
+// CHECK: %uninit = alloca %struct.virtualderived, align
+// CHECK-NEXT: call void @{{.*}}virtualderived{{.*}}%uninit)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_virtualderived_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_virtualderived_uninit.uninit
+// ZERO-LABEL: @test_virtualderived_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(virtualderived, virtualderived);
+// CHECK-LABEL: @test_virtualderived_braces()
+// CHECK: %braces = alloca %struct.virtualderived, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 16, i1 false)
+// CHECK-NEXT: call void @{{.*}}virtualderived{{.*}}%braces)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+
+TEST_UNINIT(matching, matching);
+// CHECK-LABEL: @test_matching_uninit()
+// CHECK: %uninit = alloca %union.matching, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_matching_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_matching_uninit.uninit
+// ZERO-LABEL: @test_matching_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(matching, matching);
+// CHECK-LABEL: @test_matching_braces()
+// CHECK: %braces = alloca %union.matching, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(matching, matching, { .f = 0xf00f });
+// CHECK-LABEL: @test_matching_custom()
+// CHECK: %custom = alloca %union.matching, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(matchingreverse, matchingreverse);
+// CHECK-LABEL: @test_matchingreverse_uninit()
+// CHECK: %uninit = alloca %union.matchingreverse, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_matchingreverse_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_matchingreverse_uninit.uninit
+// ZERO-LABEL: @test_matchingreverse_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(matchingreverse, matchingreverse);
+// CHECK-LABEL: @test_matchingreverse_braces()
+// CHECK: %braces = alloca %union.matchingreverse, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(matchingreverse, matchingreverse, { .i = 0xf00f });
+// CHECK-LABEL: @test_matchingreverse_custom()
+// CHECK: %custom = alloca %union.matchingreverse, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(unmatched, unmatched);
+// CHECK-LABEL: @test_unmatched_uninit()
+// CHECK: %uninit = alloca %union.unmatched, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_unmatched_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_unmatched_uninit.uninit
+// ZERO-LABEL: @test_unmatched_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(unmatched, unmatched);
+// CHECK-LABEL: @test_unmatched_braces()
+// CHECK: %braces = alloca %union.unmatched, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(unmatched, unmatched, { .i = 0x3badbeef });
+// CHECK-LABEL: @test_unmatched_custom()
+// CHECK: %custom = alloca %union.unmatched, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(unmatchedreverse, unmatchedreverse);
+// CHECK-LABEL: @test_unmatchedreverse_uninit()
+// CHECK: %uninit = alloca %union.unmatchedreverse, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_unmatchedreverse_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_unmatchedreverse_uninit.uninit
+// ZERO-LABEL: @test_unmatchedreverse_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(unmatchedreverse, unmatchedreverse);
+// CHECK-LABEL: @test_unmatchedreverse_braces()
+// CHECK: %braces = alloca %union.unmatchedreverse, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %{{.*}}, i8 0, i64 4, i1 false)
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(unmatchedreverse, unmatchedreverse, { .c = 42 });
+// CHECK-LABEL: @test_unmatchedreverse_custom()
+// CHECK: %custom = alloca %union.unmatchedreverse, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(unmatchedfp, unmatchedfp);
+// CHECK-LABEL: @test_unmatchedfp_uninit()
+// CHECK: %uninit = alloca %union.unmatchedfp, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_unmatchedfp_uninit()
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_unmatchedfp_uninit.uninit
+// ZERO-LABEL: @test_unmatchedfp_uninit()
+// ZERO: call void @llvm.memset{{.*}}, i8 0,
+
+TEST_BRACES(unmatchedfp, unmatchedfp);
+// CHECK-LABEL: @test_unmatchedfp_braces()
+// CHECK: %braces = alloca %union.unmatchedfp, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(unmatchedfp, unmatchedfp, { .d = 3.1415926535897932384626433 });
+// CHECK-LABEL: @test_unmatchedfp_custom()
+// CHECK: %custom = alloca %union.unmatchedfp, align
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @llvm.memcpy
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+
+TEST_UNINIT(emptyenum, emptyenum);
+// CHECK-LABEL: @test_emptyenum_uninit()
+// CHECK: %uninit = alloca i32, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_emptyenum_uninit()
+// PATTERN: store i32 -1431655766, i32* %braces, align 4
+// ZERO-LABEL: @test_emptyenum_uninit()
+// ZERO: store i32 0, i32* %braces, align 4
+
+TEST_BRACES(emptyenum, emptyenum);
+// CHECK-LABEL: @test_emptyenum_braces()
+// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(emptyenum, emptyenum, { (emptyenum)42 });
+// CHECK-LABEL: @test_emptyenum_custom()
+// CHECK: %custom = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32 42, i32* %custom, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(smallenum, smallenum);
+// CHECK-LABEL: @test_smallenum_uninit()
+// CHECK: %uninit = alloca i32, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_smallenum_uninit()
+// PATTERN: store i32 -1431655766, i32* %braces, align 4
+// ZERO-LABEL: @test_smallenum_uninit()
+// ZERO: store i32 0, i32* %braces, align 4
+
+TEST_BRACES(smallenum, smallenum);
+// CHECK-LABEL: @test_smallenum_braces()
+// CHECK: %braces = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32 0, i32* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(smallenum, smallenum, { (smallenum)42 });
+// CHECK-LABEL: @test_smallenum_custom()
+// CHECK: %custom = alloca i32, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store i32 42, i32* %custom, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+
+TEST_UNINIT(intvec16, int __attribute__((vector_size(16))));
+// CHECK-LABEL: @test_intvec16_uninit()
+// CHECK: %uninit = alloca <4 x i32>, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_intvec16_uninit()
+// PATTERN: store <4 x i32> <i32 -1431655766, i32 -1431655766, i32 -1431655766, i32 -1431655766>, <4 x i32>* %uninit, align 16
+// ZERO-LABEL: @test_intvec16_uninit()
+// ZERO: store <4 x i32> zeroinitializer, <4 x i32>* %uninit, align 16
+
+TEST_BRACES(intvec16, int __attribute__((vector_size(16))));
+// CHECK-LABEL: @test_intvec16_braces()
+// CHECK: %braces = alloca <4 x i32>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x i32> zeroinitializer, <4 x i32>* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(intvec16, int __attribute__((vector_size(16))), { 0x44444444, 0x44444444, 0x44444444, 0x44444444 });
+// CHECK-LABEL: @test_intvec16_custom()
+// CHECK: %custom = alloca <4 x i32>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x i32> <i32 1145324612, i32 1145324612, i32 1145324612, i32 1145324612>, <4 x i32>* %custom, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(longlongvec32, long long __attribute__((vector_size(32))));
+// CHECK-LABEL: @test_longlongvec32_uninit()
+// CHECK: %uninit = alloca <4 x i64>, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_longlongvec32_uninit()
+// PATTERN: store <4 x i64> <i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206, i64 -6148914691236517206>, <4 x i64>* %uninit, align 32
+// ZERO-LABEL: @test_longlongvec32_uninit()
+// ZERO: store <4 x i64> zeroinitializer, <4 x i64>* %uninit, align 32
+
+TEST_BRACES(longlongvec32, long long __attribute__((vector_size(32))));
+// CHECK-LABEL: @test_longlongvec32_braces()
+// CHECK: %braces = alloca <4 x i64>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x i64> zeroinitializer, <4 x i64>* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(longlongvec32, long long __attribute__((vector_size(32))), { 0x3333333333333333, 0x3333333333333333, 0x3333333333333333, 0x3333333333333333 });
+// CHECK-LABEL: @test_longlongvec32_custom()
+// CHECK: %custom = alloca <4 x i64>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x i64> <i64 3689348814741910323, i64 3689348814741910323, i64 3689348814741910323, i64 3689348814741910323>, <4 x i64>* %custom, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(floatvec16, float __attribute__((vector_size(16))));
+// CHECK-LABEL: @test_floatvec16_uninit()
+// CHECK: %uninit = alloca <4 x float>, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_floatvec16_uninit()
+// PATTERN: store <4 x float> <float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000>, <4 x float>* %uninit, align 16
+// ZERO-LABEL: @test_floatvec16_uninit()
+// ZERO: store <4 x float> zeroinitializer, <4 x float>* %uninit, align 16
+
+TEST_BRACES(floatvec16, float __attribute__((vector_size(16))));
+// CHECK-LABEL: @test_floatvec16_braces()
+// CHECK: %braces = alloca <4 x float>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x float> zeroinitializer, <4 x float>* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(floatvec16, float __attribute__((vector_size(16))), { 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433 });
+// CHECK-LABEL: @test_floatvec16_custom()
+// CHECK: %custom = alloca <4 x float>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x float> <float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000>, <4 x float>* %custom, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+TEST_UNINIT(doublevec32, double __attribute__((vector_size(32))));
+// CHECK-LABEL: @test_doublevec32_uninit()
+// CHECK: %uninit = alloca <4 x double>, align
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
+// PATTERN-LABEL: @test_doublevec32_uninit()
+// PATTERN: store <4 x double> <double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF>, <4 x double>* %uninit, align 32
+// ZERO-LABEL: @test_doublevec32_uninit()
+// ZERO: store <4 x double> zeroinitializer, <4 x double>* %uninit, align 32
+
+TEST_BRACES(doublevec32, double __attribute__((vector_size(32))));
+// CHECK-LABEL: @test_doublevec32_braces()
+// CHECK: %braces = alloca <4 x double>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x double> zeroinitializer, <4 x double>* %braces, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%braces)
+
+TEST_CUSTOM(doublevec32, double __attribute__((vector_size(32))), { 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433, 3.1415926535897932384626433 });
+// CHECK-LABEL: @test_doublevec32_custom()
+// CHECK: %custom = alloca <4 x double>, align [[ALIGN:[0-9]*]]
+// CHECK-NEXT: store <4 x double> <double 0x400921FB54442D18, double 0x400921FB54442D18, double 0x400921FB54442D18, double 0x400921FB54442D18>, <4 x double>* %custom, align [[ALIGN]]
+// CHECK-NEXT: call void @{{.*}}used{{.*}}%custom)
+
+
+} // extern "C"
diff --git a/test/CodeGenCXX/block-byref-cxx-objc.cpp b/test/CodeGenCXX/block-byref-cxx-objc.cpp
index ce1ebd615ef8..6aca809c2c72 100644
--- a/test/CodeGenCXX/block-byref-cxx-objc.cpp
+++ b/test/CodeGenCXX/block-byref-cxx-objc.cpp
@@ -1,17 +1,23 @@
-// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -fblocks | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -triple %itanium_abi_triple -o - -fblocks -fexceptions | FileCheck %s
// rdar://8594790
struct A {
int x;
A(const A &);
A();
- ~A();
+ ~A() noexcept(false);
};
-int main()
-{
- __block A BYREF_VAR;
- ^{ BYREF_VAR.x = 1234; };
+struct B {
+ int x;
+ B(const B &);
+ B();
+ ~B();
+};
+
+int testA() {
+ __block A a0, a1;
+ ^{ a0.x = 1234; a1.x = 5678; };
return 0;
}
@@ -19,10 +25,32 @@ int main()
// CHECK: call {{.*}} @_ZN1AC1ERKS_
// CHECK-LABEL: define internal void @__Block_byref_object_dispose_
// CHECK: call {{.*}} @_ZN1AD1Ev
-// CHECK-LABEL: define internal void @__copy_helper_block_
-// CHECK: call {{.*}}void @_Block_object_assign
-// CHECK-LABEL: define internal void @__destroy_helper_block_
-// CHECK: call {{.*}}void @_Block_object_dispose
+
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_e{{4|8}}_{{20|32}}rc{{24|40}}rc(
+// CHECK: call void @_Block_object_assign(
+// CHECK: invoke void @_Block_object_assign(
+// CHECK: call void @_Block_object_dispose({{.*}}) #[[NOUNWIND_ATTR:[0-9]+]]
+
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_e{{4|8}}_{{20|32}}rd{{24|40}}rd(
+// CHECK: invoke void @_Block_object_dispose(
+// CHECK: call void @_Block_object_dispose(
+// CHECK: invoke void @_Block_object_dispose(
+
+int testB() {
+ __block B b0, b1;
+ ^{ b0.x = 1234; b1.x = 5678; };
+ return 0;
+}
+
+// CHECK-LABEL: define internal void @__Block_byref_object_copy_
+// CHECK: call {{.*}} @_ZN1BC1ERKS_
+// CHECK-LABEL: define internal void @__Block_byref_object_dispose_
+// CHECK: call {{.*}} @_ZN1BD1Ev
+
+// CHECK-NOT: define{{.*}}@__copy_helper_block
+// CHECK: define linkonce_odr hidden void @__destroy_helper_block_e{{4|8}}_{{20|32}}r{{24|40}}r(
+
+// CHECK: attributes #[[NOUNWIND_ATTR]] = {{{.*}}nounwind{{.*}}}
// rdar://problem/11135650
namespace test1 {
diff --git a/test/CodeGenCXX/block-byref.cpp b/test/CodeGenCXX/block-byref.cpp
new file mode 100644
index 000000000000..1cb86a547573
--- /dev/null
+++ b/test/CodeGenCXX/block-byref.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - | FileCheck %s
+// REQUIRES: x86-registered-target
+
+// CHECK: @b = global i32 0,
+
+// CHECK: define {{.*}}void @{{.*}}test{{.*}}_block_invoke(
+// CHECK: store i32 2, i32* @b,
+// CHECK: ret void
+
+int b;
+
+void test() {
+ int &a = b;
+ ^{ a = 2; };
+}
diff --git a/test/CodeGenCXX/block-capture.cpp b/test/CodeGenCXX/block-capture.cpp
index 623838357a38..515d64d35dad 100644
--- a/test/CodeGenCXX/block-capture.cpp
+++ b/test/CodeGenCXX/block-capture.cpp
@@ -4,10 +4,12 @@
// CHECK: [[baz:%[0-9a-z_]*]] = alloca %struct.__block_byref_baz
// CHECK: [[bazref:%[0-9a-z_\.]*]] = getelementptr inbounds %struct.__block_byref_baz, %struct.__block_byref_baz* [[baz]], i32 0, i32 1
// CHECK: store %struct.__block_byref_baz* [[baz]], %struct.__block_byref_baz** [[bazref]]
+// CHECK: bitcast %struct.__block_byref_baz* [[baz]] to i8*
// CHECK: [[disposable:%[0-9a-z_]*]] = bitcast %struct.__block_byref_baz* [[baz]] to i8*
// CHECK: call void @_Block_object_dispose(i8* [[disposable]]
int main() {
__block int baz = [&]() { return 0; }();
+ ^{ (void)baz; };
return 0;
}
diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp
index 37219d3f7abd..3b3363dc4175 100644
--- a/test/CodeGenCXX/blocks.cpp
+++ b/test/CodeGenCXX/blocks.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+// CHECK: @[[BLOCK_DESCRIPTOR22:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 36, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* null }, align 8
+
namespace test0 {
// CHECK-LABEL: define void @_ZN5test04testEi(
// CHECK: define internal void @___ZN5test04testEi_block_invoke{{.*}}(
@@ -73,6 +76,7 @@ namespace test2 {
void test() {
__block A a;
__block B b;
+ ^{ (void)a; (void)b; };
}
// CHECK-LABEL: define internal void @__Block_byref_object_copy
@@ -122,7 +126,7 @@ namespace test4 {
// CHECK-LABEL: define internal void @___ZN5test44testEv_block_invoke
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
// CHECK-NEXT: store i8* [[BLOCKDESC:%.*]], i8** {{.*}}, align 8
- // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %struct.__block_descriptor* }>*
+ // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]* }>*
// CHECK: call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
// CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]])
// CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]])
@@ -252,3 +256,54 @@ namespace test9 {
});
}
}
+
+namespace test10 {
+ // Check that 'v' is included in the copy helper function name to indicate
+ // the constructor taking a volatile parameter is called to copy the captured
+ // object.
+
+ // CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32c16_ZTSVN6test101BE(
+ // CHECK: call void @_ZN6test101BC1ERVKS0_(
+ // CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_8_32c16_ZTSVN6test101BE(
+ // CHECK: call void @_ZN6test101BD1Ev(
+
+ struct B {
+ int a;
+ B();
+ B(const B &);
+ B(const volatile B &);
+ ~B();
+ };
+
+ void test() {
+ volatile B x;
+ ^{ (void)x; };
+ }
+}
+
+// Copy/dispose helper functions and block descriptors of blocks that capture
+// objects that are non-external and non-trivial have internal linkage.
+
+// CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_14testEv(
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESCRIPTOR22]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %{{.*}}, align 8
+
+// CHECK-LABEL: define internal void @__copy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE(
+// CHECK-LABEL: define internal void @__destroy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE(
+
+namespace {
+ struct B {
+ int a;
+ B();
+ B(const B &);
+ ~B();
+ };
+
+ void test() {
+ B x;
+ ^{ (void)x; };
+ }
+}
+
+void callTest() {
+ test();
+}
diff --git a/test/CodeGenCXX/builtin-constant-p.cpp b/test/CodeGenCXX/builtin-constant-p.cpp
new file mode 100644
index 000000000000..6d853e8a6828
--- /dev/null
+++ b/test/CodeGenCXX/builtin-constant-p.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s
+
+// Don't crash if the argument to __builtin_constant_p isn't scalar.
+template <typename T>
+constexpr bool is_constant(const T v) {
+ return __builtin_constant_p(v);
+}
+
+template <typename T>
+class numeric {
+ public:
+ using type = T;
+
+ template <typename S>
+ constexpr numeric(S value)
+ : value_(static_cast<T>(value)) {}
+
+ private:
+ const T value_;
+};
+
+bool bcp() {
+ return is_constant(numeric<int>(1));
+}
diff --git a/test/CodeGenCXX/builtin-launder.cpp b/test/CodeGenCXX/builtin-launder.cpp
new file mode 100644
index 000000000000..b3d849c8aec9
--- /dev/null
+++ b/test/CodeGenCXX/builtin-launder.cpp
@@ -0,0 +1,321 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fstrict-vtable-pointers -o - %s \
+// RUN: | FileCheck --check-prefixes=CHECK,CHECK-STRICT %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes=CHECK,CHECK-NONSTRICT %s
+
+//===----------------------------------------------------------------------===//
+// Positive Cases
+//===----------------------------------------------------------------------===//
+
+struct TestVirtualFn {
+ virtual void foo() {}
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_virtual_fn
+extern "C" void test_builtin_launder_virtual_fn(TestVirtualFn *p) {
+ // CHECK: store [[TYPE:%[^ ]+]] %p, [[TYPE]]* %p.addr
+ // CHECK-NEXT: [[TMP0:%.*]] = load [[TYPE]], [[TYPE]]* %p.addr
+
+ // CHECK-NONSTRICT-NEXT: store [[TYPE]] [[TMP0]], [[TYPE]]* %d
+
+ // CHECK-STRICT-NEXT: [[TMP1:%.*]] = bitcast [[TYPE]] [[TMP0]] to i8*
+ // CHECK-STRICT-NEXT: [[TMP2:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* [[TMP1]])
+ // CHECK-STRICT-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to [[TYPE]]
+ // CHECK-STRICT-NEXT: store [[TYPE]] [[TMP3]], [[TYPE]]* %d
+
+ // CHECK-NEXT: ret void
+ TestVirtualFn *d = __builtin_launder(p);
+}
+
+struct TestPolyBase : TestVirtualFn {
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_poly_base
+extern "C" void test_builtin_launder_poly_base(TestPolyBase *p) {
+ // CHECK-STRICT-NOT: ret void
+ // CHECK-STRICT: @llvm.launder.invariant.group
+
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+
+ // CHECK: ret void
+ TestPolyBase *d = __builtin_launder(p);
+}
+
+struct TestBase {};
+struct TestVirtualBase : virtual TestBase {};
+
+// CHECK-LABEL: define void @test_builtin_launder_virtual_base
+extern "C" void test_builtin_launder_virtual_base(TestVirtualBase *p) {
+ // CHECK-STRICT-NOT: ret void
+ // CHECK-STRICT: @llvm.launder.invariant.group
+
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+
+ // CHECK: ret void
+ TestVirtualBase *d = __builtin_launder(p);
+}
+
+//===----------------------------------------------------------------------===//
+// Negative Cases
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: define void @test_builtin_launder_ommitted_one
+extern "C" void test_builtin_launder_ommitted_one(int *p) {
+ // CHECK: entry
+ // CHECK-NEXT: %p.addr = alloca i32*
+ // CHECK-NEXT: %d = alloca i32*
+ // CHECK-NEXT: store i32* %p, i32** %p.addr, align 8
+ // CHECK-NEXT: [[TMP:%.*]] = load i32*, i32** %p.addr
+ // CHECK-NEXT: store i32* [[TMP]], i32** %d
+ // CHECK-NEXT: ret void
+ int *d = __builtin_launder(p);
+}
+
+struct TestNoInvariant {
+ int x;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_ommitted_two
+extern "C" void test_builtin_launder_ommitted_two(TestNoInvariant *p) {
+ // CHECK: entry
+ // CHECK-NOT: llvm.launder.invariant.group
+ // CHECK-NEXT: %p.addr = alloca [[TYPE:%.*]], align 8
+ // CHECK-NEXT: %d = alloca [[TYPE]]
+ // CHECK-NEXT: store [[TYPE]] %p, [[TYPE]]* %p.addr
+ // CHECK-NEXT: [[TMP:%.*]] = load [[TYPE]], [[TYPE]]* %p.addr
+ // CHECK-NEXT: store [[TYPE]] [[TMP]], [[TYPE]]* %d
+ // CHECK-NEXT: ret void
+ TestNoInvariant *d = __builtin_launder(p);
+}
+
+struct TestVirtualMember {
+ TestVirtualFn member;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_virtual_member
+extern "C" void test_builtin_launder_virtual_member(TestVirtualMember *p) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestVirtualMember *d = __builtin_launder(p);
+}
+
+struct TestVirtualMemberDepth2 {
+ TestVirtualMember member;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_virtual_member_depth_2
+extern "C" void test_builtin_launder_virtual_member_depth_2(TestVirtualMemberDepth2 *p) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestVirtualMemberDepth2 *d = __builtin_launder(p);
+}
+
+struct TestVirtualReferenceMember {
+ TestVirtualFn &member;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_virtual_reference_member
+extern "C" void test_builtin_launder_virtual_reference_member(TestVirtualReferenceMember *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestVirtualReferenceMember *d = __builtin_launder(p);
+}
+
+struct TestRecursiveMember {
+ TestRecursiveMember() : member(*this) {}
+ TestRecursiveMember &member;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_recursive_member
+extern "C" void test_builtin_launder_recursive_member(TestRecursiveMember *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestRecursiveMember *d = __builtin_launder(p);
+}
+
+struct TestVirtualRecursiveMember {
+ TestVirtualRecursiveMember() : member(*this) {}
+ TestVirtualRecursiveMember &member;
+ virtual void foo();
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_virtual_recursive_member
+extern "C" void test_builtin_launder_virtual_recursive_member(TestVirtualRecursiveMember *p) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestVirtualRecursiveMember *d = __builtin_launder(p);
+}
+
+// CHECK-LABEL: define void @test_builtin_launder_array(
+extern "C" void test_builtin_launder_array(TestVirtualFn (&Arr)[5]) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestVirtualFn *d = __builtin_launder(Arr);
+}
+
+// CHECK-LABEL: define void @test_builtin_launder_array_nested(
+extern "C" void test_builtin_launder_array_nested(TestVirtualFn (&Arr)[5][2]) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ using RetTy = TestVirtualFn(*)[2];
+ RetTy d = __builtin_launder(Arr);
+}
+
+// CHECK-LABEL: define void @test_builtin_launder_array_no_invariant(
+extern "C" void test_builtin_launder_array_no_invariant(TestNoInvariant (&Arr)[5]) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestNoInvariant *d = __builtin_launder(Arr);
+}
+
+// CHECK-LABEL: define void @test_builtin_launder_array_nested_no_invariant(
+extern "C" void test_builtin_launder_array_nested_no_invariant(TestNoInvariant (&Arr)[5][2]) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ using RetTy = TestNoInvariant(*)[2];
+ RetTy d = __builtin_launder(Arr);
+}
+
+template <class Member>
+struct WithMember {
+ Member mem;
+};
+
+template struct WithMember<TestVirtualFn[5]>;
+
+// CHECK-LABEL: define void @test_builtin_launder_member_array(
+extern "C" void test_builtin_launder_member_array(WithMember<TestVirtualFn[5]> *p) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ auto *d = __builtin_launder(p);
+}
+
+template struct WithMember<TestVirtualFn[5][2]>;
+
+// CHECK-LABEL: define void @test_builtin_launder_member_array_nested(
+extern "C" void test_builtin_launder_member_array_nested(WithMember<TestVirtualFn[5][2]> *p) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ auto *d = __builtin_launder(p);
+}
+
+template struct WithMember<TestNoInvariant[5]>;
+
+// CHECK-LABEL: define void @test_builtin_launder_member_array_no_invariant(
+extern "C" void test_builtin_launder_member_array_no_invariant(WithMember<TestNoInvariant[5]> *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ auto *d = __builtin_launder(p);
+}
+
+template struct WithMember<TestNoInvariant[5][2]>;
+
+// CHECK-LABEL: define void @test_builtin_launder_member_array_nested_no_invariant(
+extern "C" void test_builtin_launder_member_array_nested_no_invariant(WithMember<TestNoInvariant[5][2]> *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ auto *d = __builtin_launder(p);
+}
+
+template <class T>
+struct WithBase : T {};
+
+template struct WithBase<TestNoInvariant>;
+
+// CHECK-LABEL: define void @test_builtin_launder_base_no_invariant(
+extern "C" void test_builtin_launder_base_no_invariant(WithBase<TestNoInvariant> *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ auto *d = __builtin_launder(p);
+}
+
+template struct WithBase<TestVirtualFn>;
+
+// CHECK-LABEL: define void @test_builtin_launder_base(
+extern "C" void test_builtin_launder_base(WithBase<TestVirtualFn> *p) {
+ // CHECK: entry
+ // CHECK-NONSTRICT-NOT: @llvm.launder.invariant.group
+ // CHECK-STRICT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ auto *d = __builtin_launder(p);
+}
+
+/// The test cases in this namespace technically need to be laundered according
+/// to the language in the standard (ie they have const or reference subobjects)
+/// but LLVM doesn't currently optimize on these cases -- so Clang emits
+/// __builtin_launder as a nop.
+///
+/// NOTE: Adding optimizations for these cases later is an LTO ABI break. That's
+/// probably OK for now -- but is something to keep in mind.
+namespace pessimizing_cases {
+
+struct TestConstMember {
+ const int x;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_const_member
+extern "C" void test_builtin_launder_const_member(TestConstMember *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestConstMember *d = __builtin_launder(p);
+}
+
+struct TestConstSubobject {
+ TestConstMember x;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_const_subobject
+extern "C" void test_builtin_launder_const_subobject(TestConstSubobject *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestConstSubobject *d = __builtin_launder(p);
+}
+
+struct TestConstObject {
+ const struct TestConstMember x;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_const_object
+extern "C" void test_builtin_launder_const_object(TestConstObject *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestConstObject *d = __builtin_launder(p);
+}
+
+struct TestReferenceMember {
+ int &x;
+};
+
+// CHECK-LABEL: define void @test_builtin_launder_reference_member
+extern "C" void test_builtin_launder_reference_member(TestReferenceMember *p) {
+ // CHECK: entry
+ // CHECK-NOT: @llvm.launder.invariant.group
+ // CHECK: ret void
+ TestReferenceMember *d = __builtin_launder(p);
+}
+
+} // namespace pessimizing_cases
diff --git a/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp b/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp
index d5c1f603ff3f..61272b1ceea2 100644
--- a/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp
+++ b/test/CodeGenCXX/castexpr-basepathsize-threshold.cpp
@@ -1,8 +1,12 @@
-// RUN: %clang_cc1 %s -emit-llvm -o -
+// RUN: %clang_cc1 %s -emit-llvm-only -o -
// https://bugs.llvm.org/show_bug.cgi?id=38356
// We only check that we do not crash.
+// ASAN increases stack usage, so we are hitting stack overflow before reaching
+// recursive template instantiation limit.
+// XFAIL: darwin && asan
+
template <typename a, a b(unsigned), int c, unsigned...>
struct d : d<a, b, c - 1> {};
template <typename a, a b(unsigned), unsigned... e>
diff --git a/test/CodeGenCXX/catch-implicit-integer-sign-changes-true-negatives.cpp b/test/CodeGenCXX/catch-implicit-integer-sign-changes-true-negatives.cpp
new file mode 100644
index 000000000000..95349387b3b4
--- /dev/null
+++ b/test/CodeGenCXX/catch-implicit-integer-sign-changes-true-negatives.cpp
@@ -0,0 +1,149 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fno-sanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-recover=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-sign-change -fsanitize-trap=implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
+
+extern "C" { // Disable name mangling.
+
+// ========================================================================== //
+// The expected true-negatives.
+// ========================================================================== //
+
+// Sanitization is explicitly disabled.
+// ========================================================================== //
+
+// CHECK-LABEL: @blacklist_0
+__attribute__((no_sanitize("undefined"))) unsigned int blacklist_0(signed int src) {
+ // We are not in "undefined" group, so that doesn't work.
+ // CHECK-SANITIZE: call
+ // CHECK: }
+ return src;
+}
+
+// CHECK-LABEL: @blacklist_1
+__attribute__((no_sanitize("integer"))) unsigned int blacklist_1(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return src;
+}
+
+// CHECK-LABEL: @blacklist_2
+__attribute__((no_sanitize("implicit-conversion"))) unsigned int blacklist_2(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return src;
+}
+
+// CHECK-LABEL: @blacklist_3
+__attribute__((no_sanitize("implicit-integer-sign-change"))) unsigned int blacklist_3(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return src;
+}
+
+// Explicit sign-changing conversions.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_signed_int_to_unsigned_int
+unsigned int explicit_signed_int_to_unsigned_int(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_int_to_signed_int
+signed int explicit_unsigned_int_to_signed_int(unsigned int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return (signed int)src;
+}
+
+// Explicit NOP conversions.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
+unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_signed_int
+signed int explicit_signed_int_to_signed_int(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return (signed int)src;
+}
+
+// Explicit functional sign-changing casts.
+// ========================================================================== //
+
+using UnsignedInt = unsigned int;
+using SignedInt = signed int;
+
+// CHECK-LABEL: explicit_functional_unsigned_int_to_signed_int
+signed int explicit_functional_unsigned_int_to_signed_int(unsigned int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return SignedInt(src);
+}
+
+// CHECK-LABEL: @explicit_functional_signed_int_to_unsigned_int
+unsigned int explicit_functional_signed_int_to_unsigned_int(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return UnsignedInt(src);
+}
+
+// Explicit functional NOP casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_int
+unsigned int explicit_functional_unsigned_int_to_unsigned_int(unsigned int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return UnsignedInt(src);
+}
+
+// CHECK-LABEL: @explicit_functional_signed_int_to_signed_int
+signed int explicit_functional_signed_int_to_signed_int(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return SignedInt(src);
+}
+
+// Explicit C++-style sign-changing casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_cppstyle_unsigned_int_to_signed_int
+signed int explicit_cppstyle_unsigned_int_to_signed_int(unsigned int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return static_cast<signed int>(src);
+}
+
+// CHECK-LABEL: @explicit_cppstyle_signed_int_to_unsigned_int
+unsigned int explicit_cppstyle_signed_int_to_unsigned_int(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return static_cast<unsigned int>(src);
+}
+
+// Explicit C++-style casts NOP casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_cppstyle_unsigned_int_to_unsigned_int
+unsigned int explicit_cppstyle_unsigned_int_to_unsigned_int(unsigned int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return static_cast<unsigned int>(src);
+}
+
+// CHECK-LABEL: @explicit_cppstyle_signed_int_to_signed_int
+signed int explicit_cppstyle_signed_int_to_signed_int(signed int src) {
+ // CHECK-SANITIZE-NOT: call
+ // CHECK: }
+ return static_cast<signed int>(src);
+}
+
+} // extern "C"
diff --git a/test/CodeGenCXX/catch-implicit-integer-truncations.cpp b/test/CodeGenCXX/catch-implicit-integer-truncations.cpp
index ba7676a3504a..2902fe1e884d 100644
--- a/test/CodeGenCXX/catch-implicit-integer-truncations.cpp
+++ b/test/CodeGenCXX/catch-implicit-integer-truncations.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
-// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
-// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fno-sanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
extern "C" { // Disable name mangling.
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index 4513936e49a3..0e8d4fa51a0c 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -72,7 +72,7 @@ void member_access(S *p) {
// The two hash values are for 64- and 32-bit Clang binaries, respectively.
// FIXME: We should produce a 64-bit value either way.
//
- // CHECK-NEXT: xor i64 {{-4030275160588942838|2562089159}}, %[[VPTR]]
+ // CHECK-NEXT: xor i64 {{-4030275160588942838|1107558922}}, %[[VPTR]]
// CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023
// CHECK-NEXT: lshr i64 {{.*}}, 47
// CHECK-NEXT: xor i64
@@ -121,7 +121,7 @@ void member_access(S *p) {
// (3b) Check that 'p' actually points to an 'S'
// CHECK: load i64, i64*
- // CHECK-NEXT: xor i64 {{-4030275160588942838|2562089159}},
+ // CHECK-NEXT: xor i64 {{-4030275160588942838|1107558922}},
// [...]
// CHECK: getelementptr inbounds [128 x i64], [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 %
// CHECK: br i1
@@ -520,6 +520,49 @@ void upcast_to_vbase() {
}
}
+struct nothrow {};
+void *operator new[](__SIZE_TYPE__, nothrow) noexcept;
+
+namespace NothrowNew {
+ struct X { X(); };
+
+ // CHECK-LABEL: define{{.*}}nothrow_new_trivial
+ void *nothrow_new_trivial() {
+ // CHECK: %[[is_null:.*]] = icmp eq i8*{{.*}}, null
+ // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]]
+
+ // CHECK: [[nonnull]]:
+ // CHECK: llvm.objectsize
+ // CHECK: br i1
+ //
+ // CHECK: call {{.*}}__ubsan_handle_type_mismatch
+ //
+ // CHECK: [[null]]:
+ // CHECK-NOT: {{ }}br{{ }}
+ // CHECK: ret
+ return new (nothrow{}) char[123456];
+ }
+
+ // CHECK-LABEL: define{{.*}}nothrow_new_nontrivial
+ void *nothrow_new_nontrivial() {
+ // CHECK: %[[is_null:.*]] = icmp eq i8*{{.*}}, null
+ // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]]
+
+ // CHECK: [[nonnull]]:
+ // CHECK: llvm.objectsize
+ // CHECK: br i1
+ //
+ // CHECK: call {{.*}}__ubsan_handle_type_mismatch
+ //
+ // CHECK: call {{.*}}_ZN10NothrowNew1XC1Ev
+ //
+ // CHECK: [[null]]:
+ // CHECK-NOT: {{ }}br{{ }}
+ // CHECK: ret
+ return new (nothrow{}) X[123456];
+ }
+}
+
struct ThisAlign {
void this_align_lambda();
void this_align_lambda_2();
diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp
index 6d5e0591191c..4b7b3d70f098 100644
--- a/test/CodeGenCXX/cfi-cross-dso.cpp
+++ b/test/CodeGenCXX/cfi-cross-dso.cpp
@@ -26,7 +26,7 @@ void g() {
b.f();
}
-// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A@@6B@"{{.*}}@"?f@B@?A@@UEAAXXZ"
+// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A0x{{[^@]*}}@@6B@"{{.*}}@"?f@B@?A0x{{[^@]*}}@@UEAAXXZ"
// CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)***
// CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize
diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp
index e53aeefd8a9b..00c9f59700ac 100644
--- a/test/CodeGenCXX/cfi-icall.cpp
+++ b/test/CodeGenCXX/cfi-icall.cpp
@@ -21,7 +21,7 @@ void g() {
}
// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fENS_1SE({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
-// MS: define internal void @"?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
+// MS: define internal void @"?f@?A0x{{[^@]*}}@@YAXUS@?A0x{{[^@]*}}@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]]
// CHECK: [[VOIDS1]] = distinct !{}
// CHECK: [[TS1]] = !{i64 0, [[VOIDS1]]}
diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp
index e08de61f9d41..48c911788265 100644
--- a/test/CodeGenCXX/conditional-temporaries.cpp
+++ b/test/CodeGenCXX/conditional-temporaries.cpp
@@ -1,6 +1,7 @@
// REQUIRES: amdgpu-registered-target
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O3 | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O3 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 | FileCheck %s --check-prefixes=CHECK,CHECK-OPT
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 | FileCheck %s --check-prefixes=CHECK,CHECK-OPT
namespace {
@@ -38,20 +39,167 @@ Checker c;
}
-// CHECK-LABEL: define i32 @_Z12getCtorCallsv()
+// CHECK-OPT-LABEL: define i32 @_Z12getCtorCallsv()
int getCtorCalls() {
- // CHECK: ret i32 5
+ // CHECK-OPT: ret i32 5
return ctorcalls;
}
-// CHECK-LABEL: define i32 @_Z12getDtorCallsv()
+// CHECK-OPT-LABEL: define i32 @_Z12getDtorCallsv()
int getDtorCalls() {
- // CHECK: ret i32 5
+ // CHECK-OPT: ret i32 5
return dtorcalls;
}
-// CHECK-LABEL: define zeroext i1 @_Z7successv()
+// CHECK-OPT-LABEL: define zeroext i1 @_Z7successv()
bool success() {
- // CHECK: ret i1 true
+ // CHECK-OPT: ret i1 true
return ctorcalls == dtorcalls;
}
+
+struct X { ~X(); int f(); };
+int g(int, int, int);
+// CHECK-LABEL: @_Z16lifetime_nontriv
+int lifetime_nontriv(bool cond) {
+ // CHECK-NOOPT: store i1 false,
+ // CHECK-NOOPT: store i1 false,
+ // CHECK-NOOPT: store i1 false,
+ // CHECK-NOOPT: store i1 false,
+ // CHECK-NOOPT: store i1 false,
+ // CHECK-NOOPT: store i1 false,
+ // CHECK-NOOPT: br i1
+ //
+ // CHECK-NOOPT: call void @llvm.lifetime.start
+ // CHECK-NOOPT: store i1 true,
+ // CHECK-NOOPT: store i1 true,
+ // CHECK-NOOPT: call i32 @_ZN1X1fEv(
+ // CHECK-NOOPT: call void @llvm.lifetime.start
+ // CHECK-NOOPT: store i1 true,
+ // CHECK-NOOPT: store i1 true,
+ // CHECK-NOOPT: call i32 @_ZN1X1fEv(
+ // CHECK-NOOPT: call void @llvm.lifetime.start
+ // CHECK-NOOPT: store i1 true,
+ // CHECK-NOOPT: store i1 true,
+ // CHECK-NOOPT: call i32 @_ZN1X1fEv(
+ // CHECK-NOOPT: call i32 @_Z1giii(
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3)
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: load i1,
+ // CHECK-NOOPT: br i1
+ // CHECK-NOOPT: call void @_ZN1XD1Ev(
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: load i1,
+ // CHECK-NOOPT: br i1
+ // CHECK-NOOPT: call void @llvm.lifetime.end
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: load i1,
+ // CHECK-NOOPT: br i1
+ // CHECK-NOOPT: call void @_ZN1XD1Ev(
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: load i1,
+ // CHECK-NOOPT: br i1
+ // CHECK-NOOPT: call void @llvm.lifetime.end
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: load i1,
+ // CHECK-NOOPT: br i1
+ // CHECK-NOOPT: call void @_ZN1XD1Ev(
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: load i1,
+ // CHECK-NOOPT: br i1
+ // CHECK-NOOPT: call void @llvm.lifetime.end
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: ret
+
+ // CHECK-OPT: br i1
+ //
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call i32 @_ZN1X1fEv(
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call i32 @_ZN1X1fEv(
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call i32 @_ZN1X1fEv(
+ // CHECK-OPT: call i32 @_Z1giii(
+ // CHECK-OPT: call void @_ZN1XD1Ev(
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: call void @_ZN1XD1Ev(
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: call void @_ZN1XD1Ev(
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: br label
+ return cond ? g(X().f(), X().f(), X().f()) : g(1, 2, 3);
+}
+
+struct Y { int f(); };
+int g(int, int, int);
+// CHECK-LABEL: @_Z13lifetime_triv
+int lifetime_triv(bool cond) {
+ // CHECK-NOOPT: call void @llvm.lifetime.start
+ // CHECK-NOOPT: call void @llvm.lifetime.start
+ // CHECK-NOOPT: call void @llvm.lifetime.start
+ // CHECK-NOOPT: br i1
+ //
+ // CHECK-NOOPT: call i32 @_ZN1Y1fEv(
+ // CHECK-NOOPT: call i32 @_ZN1Y1fEv(
+ // CHECK-NOOPT: call i32 @_ZN1Y1fEv(
+ // CHECK-NOOPT: call i32 @_Z1giii(
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: call i32 @_Z1giii(i32 1, i32 2, i32 3)
+ // CHECK-NOOPT: br label
+ //
+ // CHECK-NOOPT: call void @llvm.lifetime.end
+ // CHECK-NOOPT-NOT: br
+ // CHECK-NOOPT: call void @llvm.lifetime.end
+ // CHECK-NOOPT-NOT: br
+ // CHECK-NOOPT: call void @llvm.lifetime.end
+ //
+ // CHECK-NOOPT: ret
+
+ // FIXME: LLVM isn't smart enough to remove the lifetime markers from the
+ // g(1, 2, 3) path here.
+
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: br i1
+ //
+ // CHECK-OPT: call i32 @_ZN1Y1fEv(
+ // CHECK-OPT: call i32 @_ZN1Y1fEv(
+ // CHECK-OPT: call i32 @_ZN1Y1fEv(
+ // CHECK-OPT: call i32 @_Z1giii(
+ // CHECK-OPT: br label
+ //
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: call void @llvm.lifetime.end
+ return cond ? g(Y().f(), Y().f(), Y().f()) : g(1, 2, 3);
+}
+
+struct Z { ~Z() {} int f(); };
+int g(int, int, int);
+// CHECK-LABEL: @_Z22lifetime_nontriv_empty
+int lifetime_nontriv_empty(bool cond) {
+ // CHECK-OPT: br i1
+ //
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call i32 @_ZN1Z1fEv(
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call i32 @_ZN1Z1fEv(
+ // CHECK-OPT: call void @llvm.lifetime.start
+ // CHECK-OPT: call i32 @_ZN1Z1fEv(
+ // CHECK-OPT: call i32 @_Z1giii(
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: call void @llvm.lifetime.end
+ // CHECK-OPT: br label
+ return cond ? g(Z().f(), Z().f(), Z().f()) : g(1, 2, 3);
+}
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index 801d7b1e19cc..9fb4ba5fe178 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -402,7 +402,7 @@ namespace UnemittedTemporaryDecl {
// CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101
// CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102
-// CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant {{.*}} i32 103
+// CHECK: @__const._ZN12LocalVarInit8mutable_Ev.a = private unnamed_addr constant {{.*}} i32 103
// CHECK: @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_ = linkonce_odr constant i32 5, comdat
// CHECK: @_ZN33ClassTemplateWithStaticDataMember3useE = constant i32* @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_
// CHECK: @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_ = linkonce_odr hidden constant i32 5, comdat
@@ -461,7 +461,7 @@ namespace LocalVarInit {
// CHECK: define {{.*}} @_ZN12LocalVarInit8mutable_Ev
// CHECK-NOT: call
- // CHECK: call {{.*}}memcpy{{.*}} @_ZZN12LocalVarInit8mutable_EvE1a
+ // CHECK: call {{.*}}memcpy{{.*}} @__const._ZN12LocalVarInit8mutable_Ev.a
// CHECK-NOT: call
// Can't fold return value due to 'mutable'.
// CHECK-NOT: ret i32 103
diff --git a/test/CodeGenCXX/crash.cpp b/test/CodeGenCXX/crash.cpp
index d12c021a6dcc..63bca484b5dd 100644
--- a/test/CodeGenCXX/crash.cpp
+++ b/test/CodeGenCXX/crash.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -std=c++11 -emit-llvm-only
// RUN: %clang_cc1 -emit-obj -o %t -debug-info-kind=line-tables-only -std=c++11 %s
+// RUN: %clang_cc1 -emit-obj -o %t -debug-info-kind=line-directives-only -std=c++11 %s
// CHECK that we don't crash.
// PR11676's example is ill-formed:
diff --git a/test/CodeGenCXX/cxx-block-objects.cpp b/test/CodeGenCXX/cxx-block-objects.cpp
index ff868fcdd06f..d28bcb670fd2 100644
--- a/test/CodeGenCXX/cxx-block-objects.cpp
+++ b/test/CodeGenCXX/cxx-block-objects.cpp
@@ -25,9 +25,9 @@ main()
return 0;
}
-// CHECK-LABEL: define internal void @__copy_helper_block_
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_
// CHECK: call void @_ZN1AC1ERKS_
-// CHECK-LABEL:define internal void @__destroy_helper_block_
+// CHECK-LABEL:define linkonce_odr hidden void @__destroy_helper_block_
// CHECK: call void @_ZN1AD1Ev
diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp
index 70f5a47fd3b8..156c4f591908 100644
--- a/test/CodeGenCXX/cxx11-thread-local.cpp
+++ b/test/CodeGenCXX/cxx11-thread-local.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -O2 -disable-llvm-passes -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX --check-prefix=CHECK-OPT %s
// RUN: %clang_cc1 -std=c++11 -femulated-tls -emit-llvm %s -o - \
// RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s
@@ -307,6 +308,7 @@ void set_anon_i() {
// CHECK: br i1 %[[NEED_TLS_INIT]],
// init:
// CHECK: store i8 1, i8* @__tls_guard
+// CHECK-OPT: call {}* @llvm.invariant.start.p0i8(i64 1, i8* @__tls_guard)
// CHECK-NOT: call void @[[V_M_INIT]]()
// CHECK: call void @[[A_INIT]]()
// CHECK-NOT: call void @[[V_M_INIT]]()
diff --git a/test/CodeGenCXX/cxx1y-init-captures.cpp b/test/CodeGenCXX/cxx1y-init-captures.cpp
index dcfe4d47292d..c76180c5bf43 100644
--- a/test/CodeGenCXX/cxx1y-init-captures.cpp
+++ b/test/CodeGenCXX/cxx1y-init-captures.cpp
@@ -38,6 +38,19 @@ void g() {
// CHECK: add nsw i32
+// CHECK-LABEL: define void @_Z18init_capture_dtorsv
+void init_capture_dtors() {
+ // Ensure that init-captures are not treated as separate full-expressions.
+ struct HasDtor { ~HasDtor() {} };
+ void some_function_call();
+ void other_function_call();
+ // CHECK: call {{.*}}some_function_call
+ // CHECK: call {{.*}}HasDtorD
+ ([x = (HasDtor(), 0)]{}, some_function_call());
+ // CHECK: call {{.*}}other_function_call
+ other_function_call();
+}
+
int h(int a) {
// CHECK-LABEL: define i32 @_Z1hi(
// CHECK: %[[A_ADDR:.*]] = alloca i32,
diff --git a/test/CodeGenCXX/cxx2a-init-statement.cpp b/test/CodeGenCXX/cxx2a-init-statement.cpp
new file mode 100644
index 000000000000..2d45c8554451
--- /dev/null
+++ b/test/CodeGenCXX/cxx2a-init-statement.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++2a -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s -w | FileCheck %s
+
+// CHECK: @__const._Z1fv.arr = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4
+
+void f() {
+ // CHECK: %[[ARR:.*]] = alloca [3 x i32], align 4
+ // CHECK: call void @llvm.memcpy{{.*}}({{.*}} @__const._Z1fv.arr
+ for (int arr[3] = {1, 2, 3}; int a : arr)
+ ;
+}
diff --git a/test/CodeGenCXX/dbg-info-all-calls-described.cpp b/test/CodeGenCXX/dbg-info-all-calls-described.cpp
new file mode 100644
index 000000000000..547c2707226d
--- /dev/null
+++ b/test/CodeGenCXX/dbg-info-all-calls-described.cpp
@@ -0,0 +1,61 @@
+// Test that call site debug info is (un)supported in various configurations.
+
+// Supported: DWARF5, -O1, standalone DI
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \
+// RUN: -O1 -disable-llvm-passes \
+// RUN: -debug-info-kind=standalone -dwarf-version=5 \
+// RUN: | FileCheck %s -check-prefix=HAS-ATTR \
+// RUN: -implicit-check-not=DISubprogram -implicit-check-not=DIFlagAllCallsDescribed
+
+// Supported: DWARF4 + LLDB tuning, -O1, limited DI
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \
+// RUN: -O1 -disable-llvm-passes \
+// RUN: -debugger-tuning=lldb \
+// RUN: -debug-info-kind=standalone -dwarf-version=4 \
+// RUN: | FileCheck %s -check-prefix=HAS-ATTR \
+// RUN: -implicit-check-not=DISubprogram -implicit-check-not=DIFlagAllCallsDescribed
+
+// Supported: DWARF4 + LLDB tuning, -O1, line-tables only DI
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \
+// RUN: -O1 -disable-llvm-passes \
+// RUN: -debugger-tuning=lldb \
+// RUN: -debug-info-kind=line-tables-only -dwarf-version=4 \
+// RUN: | FileCheck %s -check-prefix=LINE-TABLES-ONLY
+
+// Unsupported: -O0
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \
+// RUN: -O0 \
+// RUN: -debug-info-kind=standalone -dwarf-version=5 \
+// RUN: | FileCheck %s -check-prefix=NO-ATTR
+
+// Unsupported: DWARF4
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - \
+// RUN: -O1 -disable-llvm-passes \
+// RUN: -debug-info-kind=standalone -dwarf-version=4 \
+// RUN: | FileCheck %s -check-prefix=NO-ATTR
+
+// NO-ATTR-NOT: FlagAllCallsDescribed
+
+// HAS-ATTR-DAG: DISubprogram(name: "declaration2", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition
+// HAS-ATTR-DAG: DISubprogram(name: "struct1", {{.*}}, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+// HAS-ATTR-DAG: DISubprogram(name: "struct1", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition
+// HAS-ATTR-DAG: DISubprogram(name: "method1", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition
+// HAS-ATTR-DAG: DISubprogram(name: "force_irgen", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition
+
+// LINE-TABLES-ONLY: DISubprogram(name: "force_irgen", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition
+
+void declaration1();
+
+void declaration2();
+
+void declaration2() {}
+
+struct struct1 {
+ struct1() {}
+ void method1() {}
+};
+
+void __attribute__((optnone)) force_irgen() {
+ declaration1();
+ struct1().method1();
+}
diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp
index 44d6b4da17a3..0759ee1d13bd 100644
--- a/test/CodeGenCXX/debug-info-access.cpp
+++ b/test/CodeGenCXX/debug-info-access.cpp
@@ -35,8 +35,8 @@ private:
// CHECK: !DISubprogram(name: "free",
-// CHECK-SAME: isDefinition: true
// CHECK-SAME: flags: DIFlagPrototyped,
+// CHECK-SAME: spFlags: DISPFlagDefinition
void free() {}
U u;
diff --git a/test/CodeGenCXX/debug-info-blocks.cpp b/test/CodeGenCXX/debug-info-blocks.cpp
index ed0d659eeae1..7eea3ce09649 100644
--- a/test/CodeGenCXX/debug-info-blocks.cpp
+++ b/test/CodeGenCXX/debug-info-blocks.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -debug-info-kind=line-tables-only -fblocks -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -debug-info-kind=line-directives-only -fblocks -S -emit-llvm -o - | FileCheck %s
struct A {
A();
@@ -8,11 +9,12 @@ struct A {
void test() {
__block A a;
+ ^{ (void)a; };
}
// CHECK: !DISubprogram(name: "__Block_byref_object_copy_",
-// CHECK-SAME: line: 10,
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: line: 11,
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK: !DISubprogram(name: "__Block_byref_object_dispose_",
-// CHECK-SAME: line: 10,
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: line: 11,
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
diff --git a/test/CodeGenCXX/debug-info-byval.cpp b/test/CodeGenCXX/debug-info-byval.cpp
index 5b0850b9643c..38f803d6d9bb 100644
--- a/test/CodeGenCXX/debug-info-byval.cpp
+++ b/test/CodeGenCXX/debug-info-byval.cpp
@@ -1,5 +1,5 @@
// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang -Xclang -triple=%itanium_abi_triple -g -S %s -o - | FileCheck %s
+// RUN: %clang --target=%itanium_abi_triple -g -S %s -o - | FileCheck %s
// Test to check presence of debug info for byval parameter.
// Radar 8350436.
class DAG {
diff --git a/test/CodeGenCXX/debug-info-class-limited-plugin.test b/test/CodeGenCXX/debug-info-class-limited-plugin.test
index 533c2f6b16c5..17248d5743da 100644
--- a/test/CodeGenCXX/debug-info-class-limited-plugin.test
+++ b/test/CodeGenCXX/debug-info-class-limited-plugin.test
@@ -1,2 +1,2 @@
-RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-function-names %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp
+RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-fns %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp
REQUIRES: plugins, examples
diff --git a/test/CodeGenCXX/debug-info-ctor2.cpp b/test/CodeGenCXX/debug-info-ctor2.cpp
index 3bc931e98448..95b0608dadc8 100644
--- a/test/CodeGenCXX/debug-info-ctor2.cpp
+++ b/test/CodeGenCXX/debug-info-ctor2.cpp
@@ -1,5 +1,5 @@
// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep AT_explicit
+// RUN: %clang --target=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep AT_explicit
class MyClass
diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp
index 403424e2d6a8..f1298b1d858c 100644
--- a/test/CodeGenCXX/debug-info-cxx1y.cpp
+++ b/test/CodeGenCXX/debug-info-cxx1y.cpp
@@ -18,12 +18,12 @@
// FIXME: The context of this definition should be the CU/file scope, not the class.
// CHECK: !DISubprogram(name: "func", {{.*}} scope: [[FOO]]
// CHECK-SAME: type: [[SUBROUTINE_TYPE]]
-// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DISPFlagDefinition
// CHECK-SAME: declaration: [[FUNC_DECL:![0-9]*]]
// CHECK: [[FUNC_DECL]] = !DISubprogram(name: "func",
// CHECK-SAME: scope: [[FOO]]
// CHECK-SAME: type: [[SUBROUTINE_TYPE]]
-// CHECK-SAME: isDefinition: false
+// CHECK-SAME: spFlags: 0
struct foo {
static auto func();
diff --git a/test/CodeGenCXX/debug-info-decl-nested.cpp b/test/CodeGenCXX/debug-info-decl-nested.cpp
index feab1d709094..5345ff2dff94 100644
--- a/test/CodeGenCXX/debug-info-decl-nested.cpp
+++ b/test/CodeGenCXX/debug-info-decl-nested.cpp
@@ -19,13 +19,13 @@ class OuterClass
} theInnerClass;
// CHECK0: ![[DECL:[0-9]+]] = !DISubprogram(name: "OuterClass"
// CHECK0-SAME: line: [[@LINE+2]]
-// CHECK0-SAME: isDefinition: false
+// CHECK0-SAME: spFlags: 0
OuterClass(const Foo *); // line 10
};
OuterClass::InnerClass OuterClass::theInnerClass; // This toplevel decl causes InnerClass to be generated.
// CHECK0: !DISubprogram(name: "OuterClass"
// CHECK0-SAME: line: [[@LINE+3]]
-// CHECK0-SAME: isDefinition: true
+// CHECK0-SAME: DISPFlagDefinition
// CHECK0-SAME: declaration: ![[DECL]]
OuterClass::OuterClass(const Foo *meta) { } // line 13
@@ -43,13 +43,13 @@ class OuterClass1
} theInnerClass1;
// CHECK1: ![[DECL:[0-9]+]] = !DISubprogram(name: "Bar"
// CHECK1-SAME: line: [[@LINE+2]]
-// CHECK1-SAME: isDefinition: false
+// CHECK1-SAME: spFlags: 0
void Bar(const Foo1 *);
};
OuterClass1::InnerClass1 OuterClass1::theInnerClass1;
// CHECK1: !DISubprogram(name: "Bar"
// CHECK1-SAME: line: [[@LINE+3]]
-// CHECK1-SAME: isDefinition: true
+// CHECK1-SAME: DISPFlagDefinition
// CHECK1-SAME: declaration: ![[DECL]]
void OuterClass1::Bar(const Foo1 *meta) { }
@@ -66,12 +66,12 @@ class OuterClass2
} theInnerClass2;
// CHECK2: ![[DECL:[0-9]+]] = !DISubprogram(name: "~OuterClass2"
// CHECK2-SAME: line: [[@LINE+2]]
-// CHECK2-SAME: isDefinition: false
+// CHECK2-SAME: spFlags: 0
~OuterClass2(); // line 10
};
OuterClass2::InnerClass2 OuterClass2::theInnerClass2;
// CHECK4: !DISubprogram(name: "~OuterClass2"
// CHECK4-SAME: line: [[@LINE+3]]
-// CHECK4-SAME: isDefinition: true
+// CHECK4-SAME: DISPFlagDefinition
// CHECK4-SAME: declaration: ![[DECL]]
OuterClass2::~OuterClass2() { }
diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp
index e857bb195913..3664c67bf360 100644
--- a/test/CodeGenCXX/debug-info-enum-class.cpp
+++ b/test/CodeGenCXX/debug-info-enum-class.cpp
@@ -15,7 +15,7 @@ D d;
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
// CHECK-SAME: size: 32
// CHECK-NOT: offset:
-// CHECK-SAME: flags: DIFlagFixedEnum
+// CHECK-SAME: flags: DIFlagEnumClass
// CHECK-SAME: ){{$}}
// CHECK: ![[INT]] = !DIBasicType(name: "int"
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "B"
@@ -23,7 +23,7 @@ D d;
// CHECK-SAME: baseType: ![[ULONG:[0-9]+]]
// CHECK-SAME: size: 64
// CHECK-NOT: offset:
-// CHECK-SAME: flags: DIFlagFixedEnum
+// CHECK-SAME: flags: DIFlagEnumClass
// CHECK-SAME: ){{$}}
// CHECK: ![[ULONG]] = !DIBasicType(name: "long unsigned int"
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "C"
@@ -52,6 +52,7 @@ namespace test2 {
// FIXME: this should just be a declaration under -fno-standalone-debug
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E"
// CHECK-SAME: scope: [[TEST2:![0-9]+]]
+// CHECK-NOT: DIFlagEnumClass
// CHECK-SAME: elements: [[TEST_ENUMS:![0-9]+]]
// CHECK-SAME: identifier: "_ZTSN5test21EE"
// CHECK: [[TEST2]] = !DINamespace(name: "test2"
@@ -67,6 +68,7 @@ namespace test3 {
// FIXME: this should just be a declaration under -fno-standalone-debug
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E"
// CHECK-SAME: scope: [[TEST3:![0-9]+]]
+// CHECK-NOT: DIFlagEnumClass
// CHECK-SAME: elements: [[TEST_ENUMS]]
// CHECK-SAME: identifier: "_ZTSN5test31EE"
// CHECK: [[TEST3]] = !DINamespace(name: "test3"
@@ -78,6 +80,7 @@ void func(E *) {
namespace test4 {
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E"
// CHECK-SAME: scope: [[TEST4:![0-9]+]]
+// CHECK-NOT: DIFlagEnumClass
// CHECK-SAME: elements: [[TEST_ENUMS]]
// CHECK-SAME: identifier: "_ZTSN5test41EE"
// CHECK: [[TEST4]] = !DINamespace(name: "test4"
diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp
index 1db62d96d5b6..40a6643e71f9 100644
--- a/test/CodeGenCXX/debug-info-function-context.cpp
+++ b/test/CodeGenCXX/debug-info-function-context.cpp
@@ -28,10 +28,10 @@ int global_namespace_variable = 1;
// CHECK: ![[FILE:[0-9]+]] = !DIFile(filename: "{{.*}}context.cpp",
// CHECK: ![[C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C",
// CHECK: ![[NS:.*]] = !DINamespace(name: "ns"
-// CHECK: !DISubprogram(name: "member_function",{{.*}} scope: ![[C]],{{.*}} isDefinition: true
+// CHECK: !DISubprogram(name: "member_function",{{.*}} scope: ![[C]],{{.*}} DISPFlagDefinition
-// CHECK: !DISubprogram(name: "static_member_function",{{.*}} scope: ![[C]],{{.*}} isDefinition: true
+// CHECK: !DISubprogram(name: "static_member_function",{{.*}} scope: ![[C]],{{.*}} DISPFlagDefinition
-// CHECK: !DISubprogram(name: "global_function",{{.*}} scope: ![[FILE]],{{.*}} isDefinition: true
+// CHECK: !DISubprogram(name: "global_function",{{.*}} scope: ![[FILE]],{{.*}} DISPFlagDefinition
-// CHECK: !DISubprogram(name: "global_namespace_function",{{.*}} scope: ![[NS]],{{.*}} isDefinition: true
+// CHECK: !DISubprogram(name: "global_namespace_function",{{.*}} scope: ![[NS]],{{.*}} DISPFlagDefinition
diff --git a/test/CodeGenCXX/debug-info-gline-tables-only.cpp b/test/CodeGenCXX/debug-info-gline-tables-only.cpp
index d98b27872d62..ceb7856addc6 100644
--- a/test/CodeGenCXX/debug-info-gline-tables-only.cpp
+++ b/test/CodeGenCXX/debug-info-gline-tables-only.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -fno-rtti -debug-info-kind=line-tables-only -S -emit-llvm -o - | FileCheck %s
-// Checks that clang with "-gline-tables-only" doesn't emit debug info
+// RUN: %clang_cc1 %s -fno-rtti -debug-info-kind=line-directives-only -S -emit-llvm -o - | FileCheck %s
+// Checks that clang with "-gline-tables-only" or "-gline-directives-only" doesn't emit debug info
// for variables and types.
// CHECK-NOT: DW_TAG_namespace
diff --git a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
index 7b57c08a1097..0ede3c6e48b7 100644
--- a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
+++ b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
@@ -16,12 +16,12 @@ void foo() {
static A stat;
}
-// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} line: 12,{{.*}} isLocal: true, isDefinition: true
-// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} line: 12,{{.*}} isLocal: true, isDefinition: true
-// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} line: 13,{{.*}} isLocal: true, isDefinition: true
-// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 13,{{.*}} isLocal: true, isDefinition: true
-// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} line: 13,{{.*}} isLocal: true, isDefinition: true
-// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} line: 16,{{.*}} isLocal: true, isDefinition: true
-// CHECK-NOKEXT: !DISubprogram({{.*}} isLocal: true, isDefinition: true
+// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} line: 12,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
+// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} line: 12,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
+// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} line: 13,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
+// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 13,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
+// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} line: 13,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
+// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
+// CHECK-NOKEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
-// CHECK-KEXT: !DISubprogram({{.*}} isLocal: true, isDefinition: true
+// CHECK-KEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
diff --git a/test/CodeGenCXX/debug-info-inlined.cpp b/test/CodeGenCXX/debug-info-inlined.cpp
index 53e2cc9289c2..d36715bcfcb6 100644
--- a/test/CodeGenCXX/debug-info-inlined.cpp
+++ b/test/CodeGenCXX/debug-info-inlined.cpp
@@ -26,4 +26,4 @@ B::B() : Forward(WithDtor()) {}
// CHECK-SAME: !dbg ![[INL:[0-9]+]]
// CHECK: ![[INL]] = !DILocation(line: 10, scope: ![[SP:[0-9]+]], inlinedAt:
-// CHECK: ![[SP]] = distinct !DISubprogram(name: "Base", {{.*}}isDefinition: true
+// CHECK: ![[SP]] = distinct !DISubprogram(name: "Base", {{.*}} DISPFlagDefinition
diff --git a/test/CodeGenCXX/debug-info-lambda.cpp b/test/CodeGenCXX/debug-info-lambda.cpp
new file mode 100644
index 000000000000..a10765de3777
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-lambda.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm \
+// RUN: -debug-info-kind=line-tables-only -dwarf-column-info -std=c++11 %s -o - | FileCheck %s
+
+// CHECK-LABEL: define{{.*}}lambda_in_func
+void lambda_in_func(int &ref) {
+ // CHECK: [[ref_slot:%.*]] = getelementptr inbounds %class.anon, %class.anon* {{.*}}, i32 0, i32 0, !dbg [[lambda_decl_loc:![0-9]+]]
+ // CHECK-NEXT: %1 = load i32*, i32** %ref.addr, align {{.*}}, !dbg [[capture_init_loc:![0-9]+]]
+ // CHECK-NEXT: store i32* %1, i32** %0, align {{.*}}, !dbg [[lambda_decl_loc]]
+ // CHECK-NEXT: call {{.*}}void {{.*}}, !dbg [[lambda_call_loc:![0-9]+]]
+
+ auto helper = [ // CHECK: [[lambda_decl_loc]] = !DILocation(line: [[@LINE]], column: 17
+ &]() { // CHECK: [[capture_init_loc]] = !DILocation(line: [[@LINE]], column: 18
+ ++ref;
+ };
+ helper(); // CHECK: [[lambda_call_loc]] = !DILocation(line: [[@LINE]]
+}
diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp
index a1c4ef9eea25..100cfa6e5e9a 100644
--- a/test/CodeGenCXX/debug-info-line.cpp
+++ b/test/CodeGenCXX/debug-info-line.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s
// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -w -debug-info-kind=line-directives-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s
+// RUN: %clang_cc1 -w -debug-info-kind=line-directives-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s
int &src();
int *sink();
diff --git a/test/CodeGenCXX/debug-info-member.cpp b/test/CodeGenCXX/debug-info-member.cpp
index 7ba97b5b54e7..68d02526131b 100644
--- a/test/CodeGenCXX/debug-info-member.cpp
+++ b/test/CodeGenCXX/debug-info-member.cpp
@@ -1,5 +1,5 @@
// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public
+// RUN: %clang --target=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public
class A {
public:
int x;
diff --git a/test/CodeGenCXX/debug-info-method-spec.cpp b/test/CodeGenCXX/debug-info-method-spec.cpp
index c00da004f456..0c803fdf6bf5 100644
--- a/test/CodeGenCXX/debug-info-method-spec.cpp
+++ b/test/CodeGenCXX/debug-info-method-spec.cpp
@@ -1,5 +1,5 @@
// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_AT_specification
+// RUN: %clang --target=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_AT_specification
// Radar 9254491
class A {
public:
diff --git a/test/CodeGenCXX/debug-info-ms-abi.cpp b/test/CodeGenCXX/debug-info-ms-abi.cpp
index e83d7e94230d..0ce13a02e319 100644
--- a/test/CodeGenCXX/debug-info-ms-abi.cpp
+++ b/test/CodeGenCXX/debug-info-ms-abi.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -gcodeview-ghash -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,GHASH
// Tests that certain miscellaneous features work in the MS ABI.
@@ -29,19 +30,25 @@ Foo::Nested n;
// CHECK: ![[vptr_ty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[vshape]], size: 32
// CHECK: ![[f]] = !DISubprogram(name: "f",
-// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0,
+// CHECK-SAME: containingType: ![[Foo]], virtualIndex: 0,
// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual,
+// CHECK-SAME: spFlags: DISPFlagVirtual
// CHECK: ![[g]] = !DISubprogram(name: "g",
-// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 1,
+// CHECK-SAME: containingType: ![[Foo]], virtualIndex: 1,
// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual,
+// CHECK-SAME: spFlags: DISPFlagVirtual
// CHECK: ![[h]] = !DISubprogram(name: "h",
-// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2,
+// CHECK-SAME: containingType: ![[Foo]], virtualIndex: 2,
// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual,
+// CHECK-SAME: spFlags: DISPFlagVirtual
// CHECK: ![[i]] = !DISubprogram(name: "i",
// CHECK-SAME: flags: DIFlagPrototyped | DIFlagStaticMember
// CHECK-NEXT: ![[dummy:[0-9]+]] = !DISubroutineType(types: ![[Signature:[0-9]+]])
// CHECK: ![[Signature]] = !{null, ![[BasicInt:[0-9]+]], ![[BasicInt]]}
// CHECK: ![[BasicInt]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+// CHECK: !{{[0-9]+}} = !{i32 2, !"CodeView", i32 1}
+// GHASH: !{{[0-9]+}} = !{i32 2, !"CodeViewGHash", i32 1}
diff --git a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
index d6fdee62d677..88449c8d6b75 100644
--- a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
+++ b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple i686--windows -emit-llvm -debug-info-kind=line-tables-only -x c++ %s -fms-extensions -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i686--windows -emit-llvm -debug-info-kind=line-directives-only -x c++ %s -fms-extensions -o - | FileCheck %s
struct __declspec(dllexport) S { virtual ~S(); };
struct __declspec(dllexport) T { virtual ~T(); };
diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp
index 296c99efc8eb..be88feda1112 100644
--- a/test/CodeGenCXX/debug-info-namespace.cpp
+++ b/test/CodeGenCXX/debug-info-namespace.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -std=c++11 -debug-info-kind=line-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s
+// RUN: %clang_cc1 -std=c++11 -debug-info-kind=line-directives-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLI %s
// RUN: %clang_cc1 -std=c++11 -debug-info-kind=standalone -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
namespace A {
@@ -89,7 +90,7 @@ void C::c() {}
// CHECK: [[LEX2]] = distinct !DILexicalBlock(scope: [[LEX1:![0-9]+]], file: [[FOOCPP]],
// CHECK: [[LEX1]] = distinct !DILexicalBlock(scope: [[FUNC:![0-9]+]], file: [[FOOCPP]],
-// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} isDefinition: true
+// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} DISPFlagDefinition
// CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT:![0-9]+]],
// CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:![0-9]+]], file: [[FOOCPP]], line: 27)
// CHECK: [[FOO]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo",
@@ -102,7 +103,7 @@ void C::c() {}
// CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1:![0-9]+]]
// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4
-// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DISPFlagDefinition
// CHECK: [[M9]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[I]]
// CHECK: [[M10]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAZ:![0-9]+]]
// CHECK: [[BAZ]] = !DIDerivedType(tag: DW_TAG_typedef, name: "baz", scope: [[NS]], file: [[FOOCPP]],
@@ -116,15 +117,19 @@ void C::c() {}
// CHECK-SAME: scope: [[NS]], file: [[FOOCPP]], line: 9
// CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]]
// CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]]
-// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 53,{{.*}} isDefinition: true
+// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 53,{{.*}} DISPFlagDefinition
// CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]]
-// CHECK: distinct !DISubprogram(name: "c",{{.*}}, scope: ![[C:[0-9]+]],{{.*}}, line: 60,{{.*}} isDefinition: true
+// CHECK: distinct !DISubprogram(name: "c",{{.*}}, scope: ![[C:[0-9]+]],{{.*}}, line: 60,{{.*}} DISPFlagDefinition
// CHECK: ![[C]] = !DINamespace(name: "C",
// CHECK-GMLT: [[CU:![0-9]+]] = distinct !DICompileUnit(
// CHECK-GMLT-SAME: emissionKind: LineTablesOnly,
// CHECK-GMLT-NOT: imports:
+// CHECK-GMLI: [[CU:![0-9]+]] = distinct !DICompileUnit(
+// CHECK-GMLI-SAME: emissionKind: DebugDirectivesOnly,
+// CHECK-GMLI-NOT: imports:
+
// CHECK-NOLIMIT: !DICompositeType(tag: DW_TAG_structure_type, name: "bar",{{.*}} line: 6,
// CHECK-NOLIMIT-NOT: DIFlagFwdDecl
// CHECK-NOLIMIT-SAME: ){{$}}
diff --git a/test/CodeGenCXX/debug-info-static-fns.cpp b/test/CodeGenCXX/debug-info-static-fns.cpp
index 59c7471f7ca6..2c8ed8f26c56 100644
--- a/test/CodeGenCXX/debug-info-static-fns.cpp
+++ b/test/CodeGenCXX/debug-info-static-fns.cpp
@@ -10,4 +10,4 @@ namespace A {
// CHECK: define internal i32 @_ZN1AL1aEi({{.*}} !dbg [[DBG:![0-9]+]]
// CHECK: [[DBG]] = distinct !DISubprogram(name: "a", linkageName: "_ZN1AL1aEi",
// CHECK-SAME: line: 4
-// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DISPFlagDefinition
diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
index c8d8a1de855d..cd51b522505d 100644
--- a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
+++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
@@ -1,8 +1,9 @@
// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=limited %s -o - | FileCheck %s
-// Run again with -gline-tables-only and verify we don't crash. We won't output
+// Run again with -gline-tables-only or -gline-directives-only and verify we don't crash. We won't output
// type info at all.
// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=line-tables-only %s -o - | FileCheck %s -check-prefix LINES-ONLY
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=line-directives-only %s -o - | FileCheck %s -check-prefix LINES-ONLY
// LINES-ONLY-NOT: !DICompositeType(tag: DW_TAG_structure_type
diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp
index a6aa1a05a256..db6006cab820 100644
--- a/test/CodeGenCXX/debug-info-template-member.cpp
+++ b/test/CodeGenCXX/debug-info-template-member.cpp
@@ -22,6 +22,19 @@ inline int add3(int x) {
// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]], expr: !DIExpression())
// CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x",
// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]]
+//
+// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
+// CHECK-SAME: name: "var"
+// CHECK-SAME: templateParams: {{![0-9]+}}
+// CHECK: !DITemplateTypeParameter(name: "T", type: [[TY:![0-9]+]])
+// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
+// CHECK-SAME: name: "var"
+// CHECK-SAME: templateParams: {{![0-9]+}}
+// CHECK: !DITemplateTypeParameter(name: "P", type: {{![0-9]+}})
+// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
+// CHECK-SAME: name: "varray"
+// CHECK-SAME: templateParams: {{![0-9]+}}
+// CHECK: !DITemplateValueParameter(name: "N", type: [[TY]], value: i32 1)
// CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier:
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
@@ -103,3 +116,15 @@ void f2() {
// declaration/reference in the compile unit.
// CHECK: !DISubprogram(name: "MyClass"
// CHECK-SAME: scope: [[C]]
+
+template <typename T>
+T var = T();
+template <typename P>
+P var<P *> = P();
+template <typename T, int N>
+T varray[N];
+void f3() {
+ var<int> = 1;
+ var<int *> = 1;
+ varray<int, 1>[0] = 1;
+}
diff --git a/test/CodeGenCXX/debug-info-thunk-msabi.cpp b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
index 565992ad2a3d..3dbabafdd87d 100644
--- a/test/CodeGenCXX/debug-info-thunk-msabi.cpp
+++ b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
@@ -12,8 +12,8 @@ class __declspec(dllexport) A {
//
// CHECK: ![[SP]] = distinct !DISubprogram(
// CHECK-SAME: line: 4
-// CHECK-SAME: isDefinition: true
// CHECK-SAME: DIFlagArtificial
+// CHECK-SAME: DISPFlagDefinition
// CHECK-SAME: ){{$}}
//
// CHECK: ![[DBG]] = !DILocation(line: 0
diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp
index 56dec93f6b39..f6130cc28ced 100644
--- a/test/CodeGenCXX/debug-info-thunk.cpp
+++ b/test/CodeGenCXX/debug-info-thunk.cpp
@@ -86,7 +86,7 @@ namespace Test4 {
};
}
void C::c() {}
-// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
+// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A0x{{[^@]*}}@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk
void C::f() {}
// Force C::f to be used.
@@ -268,9 +268,9 @@ namespace Test12 {
//
// ITANIUM: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N6Test121C1fEv"
// ITANIUM-SAME: line: 261
- // ITANIUM-SAME: isDefinition: true
// ITANIUM-SAME: DIFlagArtificial
// ITANIUM-SAME: DIFlagThunk
+ // ITANIUM-SAME: DISPFlagDefinition
// ITANIUM-SAME: ){{$}}
//
// ITANIUM: ![[DBG]] = !DILocation(line: 0
diff --git a/test/CodeGenCXX/debug-info-vla.cpp b/test/CodeGenCXX/debug-info-vla.cpp
index 6c35f301f968..73bdaf0abc53 100644
--- a/test/CodeGenCXX/debug-info-vla.cpp
+++ b/test/CodeGenCXX/debug-info-vla.cpp
@@ -13,7 +13,7 @@ int (*fp)(int[][*]) = nullptr;
// CHECK: [[ELEM_TYPE]] = !{[[NOCOUNT:.*]]}
// CHECK: [[NOCOUNT]] = !DISubrange(count: -1)
//
-// CHECK: [[VAR:![0-9]+]] = !DILocalVariable(name: "__vla_expr", {{.*}}flags: DIFlagArtificial
+// CHECK: [[VAR:![0-9]+]] = !DILocalVariable(name: "__vla_expr0", {{.*}}flags: DIFlagArtificial
// CHECK: !DICompositeType(tag: DW_TAG_array_type,
// CHECK-NOT: size:
// CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]]
diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp
index 0b3d7e17e3fa..beea56ce7368 100644
--- a/test/CodeGenCXX/debug-info-windows-dtor.cpp
+++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple i386-unknown-windows-msvc -std=c++11 -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-windows-msvc -std=c++11 -emit-llvm -debug-info-kind=line-directives-only %s -o - | FileCheck %s
struct A {
virtual ~A() {}
diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp
index 6d6d0c7d19cf..8ac4016493c5 100644
--- a/test/CodeGenCXX/debug-info.cpp
+++ b/test/CodeGenCXX/debug-info.cpp
@@ -103,7 +103,7 @@ Cls obj;
// CHECK: [[FUNC:[0-9]+]] = distinct !DISubprogram(name: "func", linkageName: "_ZN7pr147634funcENS_3fooE"
// CHECK-SAME: type: {{![0-9]+}}
-// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DISPFlagDefinition
// CHECK: [[PR14763:![0-9]+]] = !DINamespace(name: "pr14763"
namespace pr14763 {
diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp
index 1717fc468656..324c0926fb9f 100644
--- a/test/CodeGenCXX/debug-lambda-expressions.cpp
+++ b/test/CodeGenCXX/debug-lambda-expressions.cpp
@@ -40,7 +40,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
// A: 10
-// CHECK: ![[A_FUNC:.*]] = distinct !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}}, isDefinition: true
+// CHECK: ![[A_FUNC:.*]] = distinct !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}} DISPFlagDefinition
// Back to A. -- 78
// CHECK: ![[LAM_A:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[A_FUNC]]{{.*}}, line: [[A_LINE]],
@@ -52,7 +52,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// CHECK-SAME: DIFlagPublic
// B: 14
-// CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}}, isDefinition: true
+// CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}} DISPFlagDefinition
// Back to B. -- 67
// CHECK: ![[LAM_B:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[B_FUNC]]{{.*}}, line: [[B_LINE]],
@@ -68,7 +68,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// CHECK-SAME: DIFlagPublic
// C: 17
-// CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}}, isDefinition: true
+// CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}} DISPFlagDefinition
// Back to C. -- 55
// CHECK: ![[LAM_C:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[C_FUNC]]{{.*}}, line: [[C_LINE]],
@@ -85,7 +85,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// CHECK-SAME: DIFlagPublic
// D: 18
-// CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}}, isDefinition: true
+// CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}} DISPFlagDefinition
// Back to D. -- 24
// CHECK: ![[LAM_D:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[D_FUNC]]{{.*}}, line: [[D_LINE]],
diff --git a/test/CodeGenCXX/debug-prefix-map-lambda.cpp b/test/CodeGenCXX/debug-prefix-map-lambda.cpp
new file mode 100644
index 000000000000..f0fb1a312c8b
--- /dev/null
+++ b/test/CodeGenCXX/debug-prefix-map-lambda.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
+// RUN: -fdebug-prefix-map=%S=/SOURCE_ROOT %s -emit-llvm -o - | FileCheck %s
+
+template <typename T> void b(T) {}
+void c() {
+ // CHECK: !DISubprogram(name: "b<(lambda at
+ // CHECK-SAME: SOURCE_ROOT
+ // CHECK-SAME: [[@LINE+1]]:{{[0-9]+}})>"
+ b([]{});
+}
diff --git a/test/CodeGenCXX/dllexport-missing-key.cpp b/test/CodeGenCXX/dllexport-missing-key.cpp
new file mode 100644
index 000000000000..90e736f6fad3
--- /dev/null
+++ b/test/CodeGenCXX/dllexport-missing-key.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix=GNU %s
+
+class __declspec(dllexport) QAbstractLayoutStyleInfo {
+public:
+ QAbstractLayoutStyleInfo() : m_isWindow(false) {}
+ virtual ~QAbstractLayoutStyleInfo() {}
+
+ virtual bool hasChangedCore() const { return false; }
+
+ virtual void invalidate() {}
+
+ virtual double windowMargin(bool orientation) const = 0;
+
+ bool isWindow() const { return m_isWindow; }
+
+protected:
+ bool m_isWindow;
+};
+
+// GNU-DAG: @_ZTV24QAbstractLayoutStyleInfo = weak_odr dso_local dllexport
+// GNU-DAG: @_ZTS24QAbstractLayoutStyleInfo = linkonce_odr
+// GNU-DAG: @_ZTI24QAbstractLayoutStyleInfo = linkonce_odr
diff --git a/test/CodeGenCXX/dllexport-no-dllexport-inlines.cpp b/test/CodeGenCXX/dllexport-no-dllexport-inlines.cpp
new file mode 100644
index 000000000000..3866731a3cd9
--- /dev/null
+++ b/test/CodeGenCXX/dllexport-no-dllexport-inlines.cpp
@@ -0,0 +1,133 @@
+// RUN: %clang_cc1 %s -fms-extensions -triple x86_64-windows-msvc \
+// RUN: -disable-llvm-passes \
+// RUN: -fno-dllexport-inlines -emit-llvm -O1 -o - | \
+// RUN: FileCheck --check-prefix=CHECK --check-prefix=NOEXPORTINLINE %s
+
+// RUN: %clang_cc1 %s -fms-extensions -triple x86_64-windows-msvc \
+// RUN: -disable-llvm-passes \
+// RUN: -emit-llvm -O1 -o - | \
+// RUN: FileCheck --check-prefix=CHECK --check-prefix=EXPORTINLINE %s
+
+
+struct __declspec(dllexport) ExportedClass {
+
+ // NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InclassDefFunc@ExportedClass@@
+ // EXPORTINLINE-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@ExportedClass@@
+ void InclassDefFunc() {}
+
+ // CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticVariable@ExportedClass@@QEAAHXZ"
+ int InclassDefFuncWithStaticVariable() {
+ // CHECK-DAG: @"?static_variable@?1??InclassDefFuncWithStaticVariable@ExportedClass@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+ static int static_variable = 0;
+ ++static_variable;
+ return static_variable;
+ }
+
+ // CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFunctWithLambdaStaticVariable@ExportedClass@@QEAAHXZ"
+ int InclassDefFunctWithLambdaStaticVariable() {
+ // CHECK-DAG: @"?static_x@?2???R<lambda_1>@?0??InclassDefFunctWithLambdaStaticVariable@ExportedClass@@QEAAHXZ@QEBA?A?<auto>@@XZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+ return ([]() { static int static_x; return ++static_x; })();
+ }
+
+ // NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InlineOutclassDefFunc@ExportedClass@@QEAAXXZ
+ // EXPORTINLINE-DAG: define weak_odr dso_local dllexport void @"?InlineOutclassDefFunc@ExportedClass@@QEAAXXZ
+ inline void InlineOutclassDefFunc();
+
+ // CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InlineOutclassDefFuncWithStaticVariable@ExportedClass@@QEAAHXZ"
+ inline int InlineOutclassDefFuncWithStaticVariable();
+
+ // CHECK-DAG: define dso_local dllexport void @"?OutoflineDefFunc@ExportedClass@@QEAAXXZ"
+ void OutoflineDefFunc();
+};
+
+void ExportedClass::OutoflineDefFunc() {}
+
+inline void ExportedClass::InlineOutclassDefFunc() {}
+
+inline int ExportedClass::InlineOutclassDefFuncWithStaticVariable() {
+ static int static_variable = 0;
+ return ++static_variable;
+}
+
+void ExportedClassUser() {
+ ExportedClass a;
+ a.InclassDefFunc();
+ a.InlineOutclassDefFunc();
+}
+
+template<typename T>
+struct __declspec(dllexport) TemplateExportedClass {
+ void InclassDefFunc() {}
+
+ int InclassDefFuncWithStaticVariable() {
+ static int static_x = 0;
+ return ++static_x;
+ }
+};
+
+class A11{};
+class B22{};
+
+// CHECK-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@?$TemplateExportedClass@VA11@@@@QEAAXXZ"
+// CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VA11@@@@QEAAHXZ"
+// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VA11@@@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+template class TemplateExportedClass<A11>;
+
+// NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InclassDefFunc@?$TemplateExportedClass@VB22@@@@QEAAXXZ"
+// EXPORTINLINE-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@?$TemplateExportedClass@VB22@@@@QEAAXXZ
+// CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VB22@@@@QEAAHXZ"
+// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticVariable@?$TemplateExportedClass@VB22@@@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+TemplateExportedClass<B22> b22;
+
+void TemplateExportedClassUser() {
+ b22.InclassDefFunc();
+ b22.InclassDefFuncWithStaticVariable();
+}
+
+
+template<typename T>
+struct TemplateNoAttributeClass {
+ void InclassDefFunc() {}
+ int InclassDefFuncWithStaticLocal() {
+ static int static_x;
+ return ++static_x;
+ }
+};
+
+// CHECK-DAG: define weak_odr dso_local dllexport void @"?InclassDefFunc@?$TemplateNoAttributeClass@VA11@@@@QEAAXXZ"
+// CHECK-DAG: define weak_odr dso_local dllexport i32 @"?InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VA11
+// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VA11@@@@QEAAHXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+template class __declspec(dllexport) TemplateNoAttributeClass<A11>;
+
+// CHECK-DAG: define available_externally dllimport void @"?InclassDefFunc@?$TemplateNoAttributeClass@VB22@@@@QEAAXXZ"
+// CHECK-DAG: define available_externally dllimport i32 @"?InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VB22@@@@QEAAHXZ"
+// CHECK-DAG: @"?static_x@?2??InclassDefFuncWithStaticLocal@?$TemplateNoAttributeClass@VB22@@@@QEAAHXZ@4HA" = available_externally dllimport global i32 0, align 4
+extern template class __declspec(dllimport) TemplateNoAttributeClass<B22>;
+
+void TemplateNoAttributeClassUser() {
+ TemplateNoAttributeClass<B22> b22;
+ b22.InclassDefFunc();
+ b22.InclassDefFuncWithStaticLocal();
+}
+
+struct __declspec(dllimport) ImportedClass {
+ // NOEXPORTINLINE-DAG: define linkonce_odr dso_local void @"?InClassDefFunc@ImportedClass@@QEAAXXZ"
+ // EXPORTINLINE-DAG: define available_externally dllimport void @"?InClassDefFunc@ImportedClass@@QEAAXXZ"
+ void InClassDefFunc() {}
+
+ // EXPORTINLINE-DAG: define available_externally dllimport i32 @"?InClassDefFuncWithStaticVariable@ImportedClass@@QEAAHXZ"
+ // NOEXPORTINLINE-DAG: define linkonce_odr dso_local i32 @"?InClassDefFuncWithStaticVariable@ImportedClass@@QEAAHXZ"
+ int InClassDefFuncWithStaticVariable() {
+ // CHECK-DAG: @"?static_variable@?1??InClassDefFuncWithStaticVariable@ImportedClass@@QEAAHXZ@4HA" = available_externally dllimport global i32 0, align 4
+ static int static_variable = 0;
+ ++static_variable;
+ return static_variable;
+ }
+};
+
+int InClassDefFuncUser() {
+ // This is necessary for declare statement of ImportedClass::InClassDefFunc().
+ ImportedClass c;
+ c.InClassDefFunc();
+ return c.InClassDefFuncWithStaticVariable();
+}
diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp
index a7b6aad357e5..16cfb8465845 100644
--- a/test/CodeGenCXX/dllexport.cpp
+++ b/test/CodeGenCXX/dllexport.cpp
@@ -43,7 +43,7 @@ __declspec(dllexport) extern int ExternGlobalDecl;
// M64-DAG: @__ImageBase = external dso_local constant i8
-// GNU-DAG: @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global
+// GNU-DAG: @_ZTVN10__cxxabiv117__class_type_infoE = external global
// dllexport implies a definition.
// MSC-DAG: @"?GlobalDef@@3HA" = dso_local dllexport global i32 0, align 4
@@ -137,7 +137,7 @@ class __declspec(dllexport) i : h<> {};
// Declarations are not exported.
// MSC-DAG: @"??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external dso_local global
-// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external dso_local global
+// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external global
template<typename T> __declspec(dllexport) extern int VarTmplImplicitDef;
USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>)
@@ -797,7 +797,7 @@ struct __declspec(dllexport) PR23308 {
};
void PR23308::f(InternalLinkageType*) {}
long use(PR23308* p) { p->f(nullptr); }
-// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z"
+// M32-DAG: define internal x86_thiscallcc void @"?f@PR23308@@QAEXPAUInternalLinkageType@?A0x{{[^@]*}}@@@Z"
template <typename T> struct PR23770BaseTemplate { void f() {} };
template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
@@ -1012,6 +1012,18 @@ struct __declspec(dllexport) LayerTreeImpl {
// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QAE@XZ"
// M64-DAG: define weak_odr dso_local dllexport %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QEAA@XZ"
+namespace pr39496 {
+// Make sure dll attribute are inherited by static locals also in template
+// specializations.
+template <typename> struct __declspec(dllexport) S { int foo() { static int x; return x++; } };
+int foo() { S<int> s; return s.foo(); }
+// MSC-DAG: @"?x@?{{1|2}}??foo@?$S@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+
+template <typename> struct T { int foo() { static int x; return x++; } };
+template struct __declspec(dllexport) T<int>;
+// MSC-DAG: @"?x@?{{1|2}}??foo@?$T@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
+}
+
class __declspec(dllexport) ACE_Shared_Object {
public:
virtual ~ACE_Shared_Object();
diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp
index 7a7519f66831..f8034cfb47c1 100644
--- a/test/CodeGenCXX/dllimport-members.cpp
+++ b/test/CodeGenCXX/dllimport-members.cpp
@@ -854,7 +854,7 @@ USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_Imported>)
// Not importing specialization of a member variable template without explicit
// dllimport.
// MSC-DAG: @"??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external dso_local constant i32
-// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external dso_local constant i32
+// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external constant i32
template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>;
USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_NotImported>)
diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp
index 74f58cc3b171..e9f0e4795f79 100644
--- a/test/CodeGenCXX/dllimport.cpp
+++ b/test/CodeGenCXX/dllimport.cpp
@@ -78,7 +78,7 @@ USEVAR(GlobalRedecl2c)
// NB: MSC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
// MSC-DAG: @"?GlobalRedecl3@@3HA" = external dso_local global i32
-// GNU-DAG: @GlobalRedecl3 = external dso_local global i32
+// GNU-DAG: @GlobalRedecl3 = external global i32
__declspec(dllimport) extern int GlobalRedecl3;
extern int GlobalRedecl3; // dllimport ignored
USEVAR(GlobalRedecl3)
@@ -137,7 +137,7 @@ template<typename T> __declspec(dllimport) int VarTmplRedecl2;
USEVAR(VarTmplRedecl2<ImplicitInst_Imported>)
// MSC-DAG: @"??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external dso_local global i32
-// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external dso_local global i32
+// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external global i32
template<typename T> __declspec(dllimport) extern int VarTmplRedecl3;
template<typename T> extern int VarTmplRedecl3; // dllimport ignored
USEVAR(VarTmplRedecl3<ImplicitInst_Imported>)
@@ -996,3 +996,26 @@ template struct __declspec(dllexport) ExplicitInstantiationDeclTemplateBase2<int
USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func)
// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv
+
+namespace pr39496 {
+// Make sure dll attribute are inherited by static locals also in template
+// specializations.
+template <typename> struct __declspec(dllimport) S { int foo() { static int x; return x++; } };
+int foo() { S<int> s; return s.foo(); }
+// MO1-DAG: @"?x@?{{1|2}}??foo@?$S@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = available_externally dllimport global i32 0, align 4
+
+template <typename> struct T { int foo() { static int x; return x++; } };
+extern template struct __declspec(dllimport) T<int>;
+int bar() { T<int> t; return t.foo(); }
+// MO1-DAG: @"?x@?{{1|2}}??foo@?$T@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = available_externally dllimport global i32 0, align 4
+
+template <typename T> struct __declspec(dllimport) U {
+ void foo() {
+ // Don't inherit dllimport to src before attaching the initializer.
+ static constexpr char src[] = {"hello"};
+ T arr[sizeof(src)];
+ }
+};
+void baz() { U<int> u; u.foo(); } // No diagnostic.
+
+}
diff --git a/test/CodeGenCXX/dso-local-executable.cpp b/test/CodeGenCXX/dso-local-executable.cpp
index cc8d50f09c9e..ceb649e074a3 100644
--- a/test/CodeGenCXX/dso-local-executable.cpp
+++ b/test/CodeGenCXX/dso-local-executable.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -O1 -emit-llvm %s -o - | FileCheck --check-prefix=STATIC %s
// RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -fno-plt -O1 -emit-llvm %s -o - | FileCheck --check-prefix=NOPLT %s
+// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -O1 -emit-llvm %s -o - | FileCheck --check-prefix=MINGW %s
// STATIC-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant
// STATIC-DAG: @_ZTS1C = linkonce_odr dso_local constant
@@ -19,6 +20,15 @@
// NOPLT-DAG: define dso_local void @_ZN1CC1Ev(
// NOPLT-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv(
+// MINGW-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant
+// MINGW-DAG: @_ZTS1C = linkonce_odr dso_local constant
+// MINGW-DAG: @_ZTI1C = linkonce_odr dso_local constant
+// MINGW-DAG: @_ZZ14useStaticLocalvE3obj = linkonce_odr dso_local global
+// MINGW-DAG: @_ZGVZN5guard1gEvE1a = linkonce_odr dso_local global
+// MINGW-DAG: define dso_local void @_ZN1CC2Ev(
+// MINGW-DAG: define dso_local void @_ZN1CC1Ev(
+// MINGW-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv(
+
struct C {
C();
virtual void foo() {}
@@ -48,15 +58,23 @@ int h() {
} // namespace guard
+// STATIC-DAG: @_ZN5test23barIiE1xE = available_externally dso_local constant i32
// STATIC-DAG: define available_externally dso_local void @_ZN5test23barIcEC1Ev(
+// NOPLT-DAG: @_ZN5test23barIiE1xE = available_externally dso_local constant i32
// NOPLT-DAG: define available_externally void @_ZN5test23barIcEC1Ev(
+// MINGW-DAG: @_ZN5test23barIiE1xE = available_externally constant i32
+// MINGW-DAG: define available_externally dso_local void @_ZN5test23barIcEC1Ev(
namespace test2 {
void foo();
template <typename T>
struct bar {
virtual void zed();
+ static const int x = 42;
bar() { foo(); }
};
extern template class bar<char>;
bar<char> abc;
+const int *getX() {
+ return &bar<int>::x;
+}
} // namespace test2
diff --git a/test/CodeGenCXX/empty-struct-init-list.cpp b/test/CodeGenCXX/empty-struct-init-list.cpp
new file mode 100644
index 000000000000..33f52ba7032d
--- /dev/null
+++ b/test/CodeGenCXX/empty-struct-init-list.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++14 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++17 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: struct.a
+typedef struct { } a;
+typedef struct {
+ a b[];
+} c;
+
+// CHECK: {{(dso_local )?}}global %struct.c{{.*}}zeroinitializer
+c d{ };
diff --git a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
index 0e9766220828..79fba7537146 100644
--- a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
+++ b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
@@ -21,7 +21,7 @@ extern "C" void test_freefunc(int p1) {
// CHECK: invoke void @might_crash()
// CHECK-LABEL: define internal i32 @"?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer)
// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1)
@@ -51,7 +51,7 @@ void S::test_method() {
// CHECK: invoke void @might_crash()
// CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
@@ -76,7 +76,7 @@ void test_lambda() {
// CHECK: invoke void @might_crash()
// CHECK-LABEL: define internal i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0)
// CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
// CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
diff --git a/test/CodeGenCXX/float128-declarations.cpp b/test/CodeGenCXX/float128-declarations.cpp
index 07e73b281728..18a25d9faba8 100644
--- a/test/CodeGenCXX/float128-declarations.cpp
+++ b/test/CodeGenCXX/float128-declarations.cpp
@@ -6,8 +6,6 @@
// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -std=c++11 \
// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
-// RUN: %clang_cc1 -emit-llvm -triple systemz-unknown-linux-gnu -std=c++11 \
-// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-SYSZ
// RUN: %clang_cc1 -emit-llvm -triple i686-pc-openbsd -std=c++11 \
// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
// RUN: %clang_cc1 -emit-llvm -triple amd64-pc-openbsd -std=c++11 \
@@ -16,10 +14,13 @@
// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
// RUN: %clang_cc1 -emit-llvm -triple x86_64-pc-solaris2.11 -std=c++11 \
// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
+// RUN: %clang_cc1 -emit-llvm -triple i586-pc-haiku -std=c++11 \
+// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-haiku -std=c++11 \
+// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86
//
/* Various contexts where type __float128 can appear. The different check
- prefixes are due to different mangling on X86 and different calling
- convention on SystemZ. */
+ prefixes are due to different mangling on X86. */
/* Namespace */
namespace {
@@ -92,7 +93,7 @@ int main(void) {
// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128 %arg)
// CHECK-DAG: define linkonce_odr fp128 @_ZN2C16func2cEU10__float128(fp128 %arg)
// CHECK-DAG: define linkonce_odr fp128 @_Z6func1tIU10__float128ET_S0_(fp128 %arg)
-// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 }
+// CHECK-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 }
// CHECK-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16
// CHECK-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16
// CHECK-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16
@@ -114,7 +115,7 @@ int main(void) {
// CHECK-X86-DAG: define linkonce_odr void @_ZN2C1C2Eg(%class.C1* %this, fp128 %arg)
// CHECK-X86-DAG: define linkonce_odr fp128 @_ZN2C16func2cEg(fp128 %arg)
// CHECK-X86-DAG: define linkonce_odr fp128 @_Z6func1tIgET_S0_(fp128 %arg)
-// CHECK-X86-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 }
+// CHECK-X86-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 }
// CHECK-X86-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16
// CHECK-X86-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16
// CHECK-X86-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16
@@ -122,25 +123,3 @@ int main(void) {
// CHECK-X86-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l
// CHECK-X86-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000
// CHECK-X86-DAG: store fp128 [[INC]], fp128* %f4l
-
-// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000
-// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000
-// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128]
-// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000]
-// CHECK-SYSZ-DAG: define internal void @_ZN12_GLOBAL__N_16func1nERKU10__float128(fp128*
-// CHECK-SYSZ-DAG: @f1f = global fp128 0xL00000000000000000000000000000000
-// CHECK-SYSZ-DAG: @f2f = global fp128 0xL33333333333333334004033333333333
-// CHECK-SYSZ-DAG: @arr1f = global [10 x fp128]
-// CHECK-SYSZ-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000]
-// CHECK-SYSZ-DAG: declare void @_Z6func1fU10__float128(fp128*
-// CHECK-SYSZ-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128*
-// CHECK-SYSZ-DAG: define linkonce_odr void @_ZN2C16func2cEU10__float128(fp128*
-// CHECK-SYSZ-DAG: define linkonce_odr void @_Z6func1tIU10__float128ET_S0_(fp128*
-// CHECK-SYSZ-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 }
-// CHECK-SYSZ-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16
-// CHECK-SYSZ-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16
-// CHECK-SYSZ-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16
-// CHECK-SYSZ-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16
-// CHECK-SYSZ-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l
-// CHECK-SYSZ-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000
-// CHECK-SYSZ-DAG: store fp128 [[INC]], fp128* %f4l
diff --git a/test/CodeGenCXX/float16-declarations.cpp b/test/CodeGenCXX/float16-declarations.cpp
index e82c05ec8c81..7e1c1e8db93c 100644
--- a/test/CodeGenCXX/float16-declarations.cpp
+++ b/test/CodeGenCXX/float16-declarations.cpp
@@ -106,9 +106,9 @@ int main(void) {
// CHECK-DAG: call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}})
S1<_Float16> s1 = { 132.f16 };
-// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2
+// CHECK-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2
// CHECK-DAG: [[S1:%[0-9]+]] = bitcast %struct.S1* %{{.*}} to i8*
-// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[S1]], i8* align 2 bitcast (%struct.S1* @_ZZ4mainE2s1 to i8*), i64 2, i1 false)
+// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[S1]], i8* align 2 bitcast (%struct.S1* @__const.main.s1 to i8*), i64 2, i1 false)
_Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
func1t(f1l) + s1.mem2 - f1n + f2n;
@@ -123,7 +123,7 @@ int main(void) {
// CHECK-DAG: store half [[INC]], half* %{{.*}}, align 2
_Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 };
-// CHECK-DAG: @_ZZ4mainE5arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2
+// CHECK-DAG: @__const.main.arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2
float cvtf = f2n;
//CHECK-DAG: [[H2F:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to float
diff --git a/test/CodeGenCXX/globalinit-loc.cpp b/test/CodeGenCXX/globalinit-loc.cpp
index 203eb2142667..e9715a651f40 100644
--- a/test/CodeGenCXX/globalinit-loc.cpp
+++ b/test/CodeGenCXX/globalinit-loc.cpp
@@ -8,8 +8,8 @@
// CHECK: !dbg ![[DBG:.*]]
// CHECK: !DISubprogram(linkageName: "_GLOBAL__sub_I_globalinit_loc.cpp"
// CHECK-NOT: line:
-// CHECK-SAME: isLocal: true
-// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DISPFlagLocalToUnit
+// CHECK-SAME: DISPFlagDefinition
// CHECK: ![[DBG]] = !DILocation(line: 0,
# 99 "someheader.h"
class A {
diff --git a/test/CodeGenCXX/inalloca-lambda.cpp b/test/CodeGenCXX/inalloca-lambda.cpp
new file mode 100644
index 000000000000..ac85ee175268
--- /dev/null
+++ b/test/CodeGenCXX/inalloca-lambda.cpp
@@ -0,0 +1,11 @@
+// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s 2>&1 | FileCheck %s
+
+// PR28299
+// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+
+class A {
+ A(const A &);
+};
+typedef void (*fptr_t)(A);
+fptr_t fn1() { return [](A) {}; }
+
diff --git a/test/CodeGenCXX/inheriting-constructor-cleanup.cpp b/test/CodeGenCXX/inheriting-constructor-cleanup.cpp
new file mode 100644
index 000000000000..3aac9ac9f78e
--- /dev/null
+++ b/test/CodeGenCXX/inheriting-constructor-cleanup.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s --check-prefix=EXCEPTIONS
+
+// PR36748
+// rdar://problem/45805151
+
+// Classes to verify order of destroying function parameters.
+struct S1 {
+ ~S1();
+};
+struct S2 {
+ ~S2();
+};
+
+struct Base {
+ // Use variadic args to cause inlining the inherited constructor.
+ Base(const S1&, const S2&, const char *fmt, ...) {}
+};
+
+struct NonTrivialDtor {
+ ~NonTrivialDtor() {}
+};
+struct Inheritor : public NonTrivialDtor, public Base {
+ using Base::Base;
+};
+
+void f() {
+ Inheritor(S1(), S2(), "foo");
+ // CHECK-LABEL: define void @_Z1fv
+ // CHECK: %[[TMP1:.*]] = alloca %struct.S1
+ // CHECK: %[[TMP2:.*]] = alloca %struct.S2
+ // CHECK: call void (%struct.Base*, %struct.S1*, %struct.S2*, i8*, ...) @_ZN4BaseC2ERK2S1RK2S2PKcz(%struct.Base* {{.*}}, %struct.S1* dereferenceable(1) %[[TMP1]], %struct.S2* dereferenceable(1) %[[TMP2]], i8* {{.*}})
+ // CHECK-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}})
+ // CHECK-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]])
+ // CHECK-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]])
+
+ // EXCEPTIONS-LABEL: define void @_Z1fv
+ // EXCEPTIONS: %[[TMP1:.*]] = alloca %struct.S1
+ // EXCEPTIONS: %[[TMP2:.*]] = alloca %struct.S2
+ // EXCEPTIONS: invoke void (%struct.Base*, %struct.S1*, %struct.S2*, i8*, ...) @_ZN4BaseC2ERK2S1RK2S2PKcz(%struct.Base* {{.*}}, %struct.S1* dereferenceable(1) %[[TMP1]], %struct.S2* dereferenceable(1) %[[TMP2]], i8* {{.*}})
+ // EXCEPTIONS-NEXT: to label %[[CONT:.*]] unwind label %[[LPAD:.*]]
+
+ // EXCEPTIONS: [[CONT]]:
+ // EXCEPTIONS-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}})
+ // EXCEPTIONS-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]])
+ // EXCEPTIONS-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]])
+
+ // EXCEPTIONS: [[LPAD]]:
+ // EXCEPTIONS: call void @_ZN14NonTrivialDtorD2Ev(%struct.NonTrivialDtor* {{.*}})
+ // EXCEPTIONS-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]])
+ // EXCEPTIONS-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]])
+}
diff --git a/test/CodeGenCXX/inline-template-hint.cpp b/test/CodeGenCXX/inline-template-hint.cpp
new file mode 100644
index 000000000000..3e64b1f74932
--- /dev/null
+++ b/test/CodeGenCXX/inline-template-hint.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 \
+// RUN: -finline-functions -emit-llvm -disable-llvm-passes -o - \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s \
+// RUN: --check-prefix=CHECK --check-prefix=SUITABLE
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 \
+// RUN: -finline-hint-functions -emit-llvm -disable-llvm-passes -o - \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s \
+// RUN: --check-prefix=CHECK --check-prefix=HINTED
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 \
+// RUN: -fno-inline -emit-llvm -disable-llvm-passes -o - \
+// RUN: | FileCheck -allow-deprecated-dag-overlap %s \
+// RUN: --check-prefix=CHECK --check-prefix=NOINLINE
+
+struct A {
+ inline void int_run(int);
+
+ template <class T>
+ inline void template_run(T);
+};
+
+// CHECK: @_ZN1A7int_runEi({{.*}}) [[ATTR:#[0-9]+]]
+void A::int_run(int) {}
+// CHECK: @_ZN1A12template_runIiEEvT_({{.*}}) [[ATTR]]
+template <typename T>
+void A::template_run(T) {}
+
+void bar() {
+ A().int_run(1);
+ A().template_run(1);
+}
+
+// SUITABLE: attributes [[ATTR]] = { {{.*}}inlinehint{{.*}} }
+// HINTED: attributes [[ATTR]] = { {{.*}}inlinehint{{.*}} }
+// NOINLINE: attributes [[ATTR]] = { {{.*}}noinline{{.*}} }
diff --git a/test/CodeGenCXX/lifetime-asan.cpp b/test/CodeGenCXX/lifetime-asan.cpp
new file mode 100644
index 000000000000..9ccb28c876a1
--- /dev/null
+++ b/test/CodeGenCXX/lifetime-asan.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - -fno-exceptions -O0 %s | FileCheck %s -check-prefixes=CHECK,CHECK-O0 --implicit-check-not=llvm.lifetime
+// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - -fno-exceptions -O0 \
+// RUN: -fsanitize=address -fsanitize-address-use-after-scope %s | \
+// RUN: FileCheck %s -check-prefixes=CHECK,CHECK-ASAN-USE-AFTER-SCOPE
+
+extern int bar(char *A, int n);
+
+struct X { X(); ~X(); int *p; };
+struct Y { Y(); int *p; };
+
+extern "C" void a(), b(), c(), d();
+
+// CHECK-LABEL: @_Z3foo
+void foo(int n) {
+ // CHECK: call void @a()
+ a();
+
+ // CHECK: call void @b()
+ // CHECK-ASAN-USE-AFTER-SCOPE: store i1 false
+ // CHECK-ASAN-USE-AFTER-SCOPE: store i1 false
+ // CHECK: br i1
+ //
+ // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.start
+ // CHECK-ASAN-USE-AFTER-SCOPE: store i1 true
+ // CHECK: call void @_ZN1XC
+ // CHECK: br label
+ //
+ // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.start
+ // CHECK-ASAN-USE-AFTER-SCOPE: store i1 true
+ // CHECK: call void @_ZN1YC
+ // CHECK: br label
+ //
+ // CHECK: call void @c()
+ // CHECK-ASAN-USE-AFTER-SCOPE: br i1
+ // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.end
+ // CHECK-ASAN-USE-AFTER-SCOPE: br i1
+ // CHECK-ASAN-USE-AFTER-SCOPE: @llvm.lifetime.end
+ b(), (n ? X().p : Y().p), c();
+
+ // CHECK: call void @d()
+ d();
+}
diff --git a/test/CodeGenCXX/linetable-fnbegin.cpp b/test/CodeGenCXX/linetable-fnbegin.cpp
index f4cf53b0c5f5..3b93d70bd705 100644
--- a/test/CodeGenCXX/linetable-fnbegin.cpp
+++ b/test/CodeGenCXX/linetable-fnbegin.cpp
@@ -7,7 +7,7 @@
// CHECK: [[HPP:.*]] = !DIFile(filename: "./template.hpp",
// CHECK: [[SP:.*]] = distinct !DISubprogram(name: "bar",
// CHECK-SAME: file: [[HPP]], line: 22
-// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DISPFlagDefinition
// We shouldn't need a lexical block for this function.
// CHECK: [[DBG]] = !DILocation(line: 23, scope: [[SP]])
diff --git a/test/CodeGenCXX/linetable-virtual-variadic.cpp b/test/CodeGenCXX/linetable-virtual-variadic.cpp
index cd746cdfdfe2..60dee5fe61b4 100644
--- a/test/CodeGenCXX/linetable-virtual-variadic.cpp
+++ b/test/CodeGenCXX/linetable-virtual-variadic.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -debug-info-kind=line-directives-only %s -o - | FileCheck %s
// Crasher for PR22929.
class Base {
virtual void VariadicFunction(...);
diff --git a/test/CodeGenCXX/mangle-address-space.cpp b/test/CodeGenCXX/mangle-address-space.cpp
index cd10384594ea..549ae54dfbe4 100644
--- a/test/CodeGenCXX/mangle-address-space.cpp
+++ b/test/CodeGenCXX/mangle-address-space.cpp
@@ -1,15 +1,64 @@
-// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKNOOCL
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN,WINNOOCL
+// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKOCL
+// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN,WINOCL
-// CHECK-LABEL: define {{.*}}void @_Z2f0Pc
+// CHECKNOOCL-LABEL: define {{.*}}void @_Z2f0Pc
+// WINNOOCL-LABEL: define {{.*}}void @"?f0@@YAXPEAD@Z"
+// CHECKOCL-LABEL: define {{.*}}void @_Z2f0PU9CLgenericc
+// WINOCL-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$_ASCLgeneric@$$CAD@__clang@@@Z"
void f0(char *p) { }
// CHECK-LABEL: define {{.*}}void @_Z2f0PU3AS1c
+// WIN-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$_AS@$00$$CAD@__clang@@@Z"
void f0(char __attribute__((address_space(1))) *p) { }
struct OpaqueType;
typedef OpaqueType __attribute__((address_space(100))) * OpaqueTypePtr;
// CHECK-LABEL: define {{.*}}void @_Z2f0PU5AS10010OpaqueType
+// WIN-LABEL: define {{.*}}void @"?f0@@YAXPEAU?$_AS@$0GE@$$CAUOpaqueType@@@__clang@@@Z"
void f0(OpaqueTypePtr) { }
// CHECK-LABEL: define {{.*}}void @_Z2f1PU3AS1Kc
-void f1(char __attribute__((address_space(1))) const *p) {} \ No newline at end of file
+// WIN-LABEL: define {{.*}}void @"?f1@@YAXPEAU?$_AS@$00$$CBD@__clang@@@Z"
+void f1(char __attribute__((address_space(1))) const *p) {}
+
+// Ensure we can do return values, which change in MS mode.
+// CHECK-LABEL: define {{.*}}float addrspace(1)* @_Z2f1PU3AS2Kc
+// WIN-LABEL: define {{.*}}float addrspace(1)* @"?f1@@YAPEAU?$_AS@$00$$CAM@__clang@@PEAU?$_AS@$01$$CBD@2@@Z"
+__attribute__((address_space(1))) float *f1(char __attribute__((address_space(2))) const *p) { return 0;}
+
+#if !defined(__OPENCL_CPP_VERSION__)
+// Return value of address space without a pointer is invalid in opencl.
+// Ensure we skip return values, since non-pointers aren't supposed to have an AS.
+// CHECKNOOCL-LABEL: define {{.*}}float @_Z2f2PU3AS2Kc
+// WINNOOCL-LABEL: define {{.*}}float @"?f2@@YA?AMQEAU?$_AS@$01$$CBD@__clang@@@Z"
+__attribute__((address_space(1))) float f2(char __attribute__((address_space(2))) const * const p) { return 0;}
+#endif
+
+#ifdef __OPENCL_CPP_VERSION__
+// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f0PU9CLprivatec
+// WINOCL-LABEL: define {{.*}}void @"?ocl_f0@@YAXPEAU?$_ASCLprivate@$$CAD@__clang@@@Z"
+void ocl_f0(char __private *p) { }
+
+struct ocl_OpaqueType;
+typedef ocl_OpaqueType __global * ocl_OpaqueTypePtr;
+
+// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f0PU8CLglobal14ocl_OpaqueType
+// WINOCL-LABEL: define {{.*}}void @"?ocl_f0@@YAXPEAU?$_ASCLglobal@$$CAUocl_OpaqueType@@@__clang@@@Z"
+void ocl_f0(ocl_OpaqueTypePtr) { }
+
+// CHECKOCL-LABEL: define {{.*}}void @_Z6ocl_f1PU10CLconstantKc
+// WINOCL-LABEL: define {{.*}}void @"?ocl_f1@@YAXPEAU?$_ASCLconstant@$$CBD@__clang@@@Z"
+void ocl_f1(char __constant const *p) {}
+
+// Ensure we can do return values, which change in MS mode.
+// CHECKOCL-LABEL: define {{.*}}float* @_Z6ocl_f1PU9CLgenericKc
+// WINOCL-LABEL: define {{.*}}float* @"?ocl_f1@@YAPEAU?$_ASCLconstant@$$CAM@__clang@@PEAU?$_ASCLgeneric@$$CBD@2@@Z"
+__constant float *ocl_f1(char __generic const *p) { return 0;}
+
+// Ensure we skip return values, since non-pointers aren't supposed to have an AS.
+// CHECKOCL-LABEL: define {{.*}}float* @_Z6ocl_f2PU9CLgenericKc
+// WINOCL-LABEL: define {{.*}}float* @"?ocl_f2@@YAPEAU?$_ASCLgeneric@$$CAM@__clang@@QEAU?$_ASCLgeneric@$$CBD@2@@Z"
+__generic float *ocl_f2(__generic char const * const p) { return 0;}
+#endif
diff --git a/test/CodeGenCXX/mangle-long-double.cpp b/test/CodeGenCXX/mangle-long-double.cpp
index e248c474a2e7..177982b8f1aa 100644
--- a/test/CodeGenCXX/mangle-long-double.cpp
+++ b/test/CodeGenCXX/mangle-long-double.cpp
@@ -1,12 +1,8 @@
// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER64-LINUX
// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER-LINUX
-// RUN: %clang_cc1 -triple powerpc64-apple-darwin9 %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER64-DARWIN
-// RUN: %clang_cc1 -triple powerpc-apple-darwin9 %s -emit-llvm -o - | FileCheck %s --check-prefix=POWER-DARWIN
// RUN: %clang_cc1 -triple s390x-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=S390X-LINUX
void f(long double) {}
// POWER64-LINUX: _Z1fg
// POWER-LINUX: _Z1fg
-// POWER64-DARWIN: _Z1fe
-// POWER-DARWIN: _Z1fe
// S390X-LINUX: _Z1fg
diff --git a/test/CodeGenCXX/mangle-ms-exception-spec.cpp b/test/CodeGenCXX/mangle-ms-exception-spec.cpp
new file mode 100644
index 000000000000..1aaf2486ea14
--- /dev/null
+++ b/test/CodeGenCXX/mangle-ms-exception-spec.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 -Wno-noexcept-type -fms-compatibility-version=19.12 | FileCheck %s --check-prefix=CHECK --check-prefix=CXX11
+// RUN: %clang_cc1 -std=c++17 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=CHECK --check-prefix=NOCOMPAT
+// RUN: %clang_cc1 -std=c++17 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-compatibility-version=19.12 | FileCheck %s --check-prefix=CHECK --check-prefix=CXX17
+
+// Prove that mangling only changed for noexcept types under /std:C++17, not all noexcept functions
+// CHECK-DAG: @"?nochange@@YAXXZ"
+void nochange() noexcept {}
+
+// CXX11-DAG: @"?a@@YAXP6AHXZ@Z"
+// NOCOMPAT-DAG: @"?a@@YAXP6AHXZ@Z"
+// CXX17-DAG: @"?a@@YAXP6AHX_E@Z"
+void a(int() noexcept) {}
+// CHECK-DAG: @"?b@@YAXP6AHXZ@Z"
+void b(int() noexcept(false)) {}
+// CXX11-DAG: @"?c@@YAXP6AHXZ@Z"
+// NOCOMPAT-DAG: @"?c@@YAXP6AHXZ@Z"
+// CXX17-DAG: @"?c@@YAXP6AHX_E@Z"
+void c(int() noexcept(true)) {}
+// CHECK-DAG: @"?d@@YAXP6AHXZ@Z"
+void d(int()) {}
+
+template <typename T>
+class e;
+template <typename T, typename... U>
+class e<T(U...) noexcept> {
+ // CXX11-DAG: @"?ee@?$e@$$A6AXXZ@@EEAAXXZ"
+ // NOCOMPAT-DAG: @"?ee@?$e@$$A6AXXZ@@EEAAXXZ"
+ // CXX17-DAG: @"?ee@?$e@$$A6AXX_E@@EEAAXXZ"
+ virtual T ee(U &&...) noexcept {};
+};
+
+e<void() noexcept> e1;
+
+template <typename T>
+class f;
+template <typename T, typename... U>
+class f<T(U...)> {
+ // CHECK-DAG: @"?ff@?$f@$$A6AXXZ@@EEAAXXZ"
+ virtual T ff(U &&...) noexcept {};
+};
+
+f<void()> f1;
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index 8c6062b6d5ee..469a23afc8e1 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
-// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
+// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
+// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
template<typename T>
class Class {
@@ -185,13 +187,35 @@ void spam() {
// Unlike Itanium, there is no character code to indicate an argument pack.
// Tested with MSVC 2013, the first version which supports variadic templates.
-template <typename ...Ts> void variadic_fn_template(const Ts &...args) { }
+template <typename ...Ts> void variadic_fn_template(const Ts &...args);
+template <typename... Ts, typename... Us>
+void multi_variadic_fn(Ts... ts, Us... us);
+template <typename... Ts, typename C, typename... Us>
+void multi_variadic_mixed(Ts... ts, C c, Us... us);
void variadic_fn_instantiate() {
variadic_fn_template(0, 1, 3, 4);
variadic_fn_template(0, 1, 'a', "b");
+
+ // Directlly consecutive packs are separated by $$Z...
+ multi_variadic_fn<int, int>(1, 2, 3, 4, 5);
+ multi_variadic_fn<int, int, int>(1, 2, 3, 4, 5);
+
+ // ...but not if another template parameter is between them.
+ multi_variadic_mixed<int, int>(1, 2, 3);
+ multi_variadic_mixed<int, int>(1, 2, 3, 4);
}
// CHECK: "??$variadic_fn_template@HHHH@@YAXABH000@Z"
+// X64: "??$variadic_fn_template@HHHH@@YAXAEBH000@Z"
// CHECK: "??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
+// X64: "??$variadic_fn_template@HHD$$BY01D@@YAXAEBH0AEBDAEAY01$$CBD@Z"
+// CHECK: "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z"
+// X64: "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z"
+// CHECK: "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z"
+// X64: "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z"
+// CHECK: "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z"
+// X64: "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z"
+// CHECK: "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z"
+// X64: "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z"
template <typename ...Ts>
struct VariadicClass {
diff --git a/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp b/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp
new file mode 100644
index 000000000000..47b1a38ffe18
--- /dev/null
+++ b/test/CodeGenCXX/mangle-ms-thunks-covariant.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fno-rtti-data -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK
+
+namespace t1 {
+struct A {
+public:
+ virtual ~A();
+ virtual A *f();
+};
+struct B {
+public:
+ virtual ~B();
+
+private:
+ virtual B *f();
+};
+struct C : A, B {
+ virtual ~C();
+
+protected:
+ virtual C *f();
+};
+C c;
+}
+// Main external C::f impl:
+// CHECK-DAG: "?f@C@t1@@MEAAPEAU12@XZ"
+// New slot in C's vftable for B, returns C* directly:
+// CHECK-DAG: "?f@C@t1@@O7EAAPEAU12@XZ"
+// Return-adjusting thunk in C's vftable for B:
+// CHECK-DAG: "?f@C@t1@@W7EAAPEAUB@2@XZ"
diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp
index f55713e6c0c8..c2461a30700f 100644
--- a/test/CodeGenCXX/mangle-ms-vector-types.cpp
+++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp
@@ -94,5 +94,9 @@ typedef __attribute__((ext_vector_type(4))) int vi4b;
void foovi4b(vi4b) {}
// CHECK: define dso_local void @"?foovi4b@@YAXT?$__vector@H$03@__clang@@@Z"
+typedef float __attribute__((__ext_vector_type__(3))) vf3;
+void foovf3(vf3) {}
+// CHECK: define dso_local void @"?foovf3@@YAXT?$__vector@M$02@__clang@@@Z"
+
// Clang does not support vectors of complex types, so we can't test the
// mangling of them.
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 3cc1b1645e9c..e128c9443153 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -15,7 +15,7 @@ namespace N {
namespace {
int anonymous;
-// CHECK-DAG: @"?anonymous@?A@N@@3HA"
+// CHECK-DAG: @"?anonymous@?A0x{{[^@]*}}@N@@3HA"
}
}
diff --git a/test/CodeGenCXX/mangle-win-ccs.cpp b/test/CodeGenCXX/mangle-win-ccs.cpp
new file mode 100644
index 000000000000..f5ddf974cf8f
--- /dev/null
+++ b/test/CodeGenCXX/mangle-win-ccs.cpp
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-gnu -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-itanium -o - | FileCheck %s
+
+// GCC 5.1 began mangling these Windows calling conventions into function
+// types, since they can be used for overloading. They've always been mangled
+// in the MS ABI, but they are new to the Itanium mangler. Note that the main
+// function definition does not use a calling convention. Only function types
+// that appear later use it.
+
+template <typename Fn> static int func_as_ptr(Fn fn) { return int(fn); }
+
+void f_cdecl(int, int);
+void __attribute__((stdcall)) f_stdcall(int, int);
+void __attribute__((fastcall)) f_fastcall(int, int);
+void __attribute__((thiscall)) f_thiscall(int, int);
+
+int as_cdecl() { return func_as_ptr(f_cdecl); }
+int as_stdcall() { return func_as_ptr(f_stdcall); }
+int as_fastcall() { return func_as_ptr(f_fastcall); }
+
+// CHECK: define dso_local i32 @_Z8as_cdeclv()
+// CHECK: call i32 @_ZL11func_as_ptrIPFviiEEiT_(void (i32, i32)* @_Z7f_cdeclii)
+
+// CHECK: define dso_local i32 @_Z10as_stdcallv()
+// CHECK: call i32 @_ZL11func_as_ptrIPU7stdcallFviiEEiT_(void (i32, i32)* @"\01__Z9f_stdcallii@8")
+
+// CHECK: define dso_local i32 @_Z11as_fastcallv()
+// CHECK: call i32 @_ZL11func_as_ptrIPU8fastcallFviiEEiT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8")
+
+// PR40107: We should mangle thiscall here but we don't because we can't
+// disambiguate it from the member pointer case below where it shouldn't be
+// mangled.
+//int as_thiscall() { return func_as_ptr(f_thiscall); }
+// CHECKX: define dso_local i32 @_Z11as_thiscallv()
+// CHECKX: call i32 @_ZL11func_as_ptrIPU8thiscallFviiEEiT_(void (i32, i32)* @_Z10f_thiscallii)
+
+// CHECK: define dso_local void @_Z11funcRefTypeRU8fastcallFviiE(void (i32, i32)* %fr)
+void funcRefType(void(__attribute__((fastcall)) & fr)(int, int)) {
+ fr(1, 2);
+}
+
+struct Foo { void bar(int, int); };
+
+// PR40107: In this case, the member function pointer uses the thiscall
+// convention, but GCC doesn't mangle it, so we don't either.
+// CHECK: define dso_local void @_Z15memptr_thiscallP3FooMS_FvvE(%struct.Foo* {{.*}})
+void memptr_thiscall(Foo *o, void (Foo::*mp)()) { (o->*mp)(); }
+
+// CHECK: define dso_local void @_Z12memptrCCTypeR3FooMS_U8fastcallFviiE(%struct.Foo* {{.*}}, { i32, i32 }* byval{{.*}})
+void memptrCCType(Foo &o, void (__attribute__((fastcall)) Foo::*mp)(int, int)) {
+ (o.*mp)(1, 2);
+}
+
+// CHECK: define dso_local i32 @_Z17useTemplateFnTypev()
+// CHECK: call i32 @_ZL14templateFnTypeIU8fastcallFviiEElPT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8")
+template <typename Fn> static long templateFnType(Fn *fn) { return long(fn); }
+long useTemplateFnType() { return templateFnType(f_fastcall); }
+
+// CHECK: define weak_odr dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIsEvv@0"()
+// CHECK: define dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIiEvv@0"()
+template <typename T> void __attribute__((fastcall)) fnTemplate() {}
+template void __attribute__((fastcall)) fnTemplate<short>();
+template <> void __attribute__((fastcall)) fnTemplate<int>() {}
+
+// CHECK: define weak_odr dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIsEPU8fastcallFviiEv@0"()
+// CHECK: define dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIiEPU8fastcallFviiEv@0"()
+typedef void (__attribute__((fastcall)) *fp_cc_t)(int, int);
+template <typename T> fp_cc_t __attribute__((fastcall)) fnTempReturn() { return nullptr; }
+template fp_cc_t __attribute__((fastcall)) fnTempReturn<short>();
+template <> fp_cc_t __attribute__((fastcall)) fnTempReturn<int>() { return nullptr; }
diff --git a/test/CodeGenCXX/mangle-win64-ccs.cpp b/test/CodeGenCXX/mangle-win64-ccs.cpp
new file mode 100644
index 000000000000..10c0430117c5
--- /dev/null
+++ b/test/CodeGenCXX/mangle-win64-ccs.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-WIN
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-LIN
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+template <typename FTy> ptrdiff_t func_as_int(FTy *fp) { return ptrdiff_t(fp); }
+
+int f_plain(int);
+int __attribute__((sysv_abi)) f_sysvabi(int);
+int __attribute__((ms_abi)) f_msabi(int);
+ptrdiff_t useThem() {
+ ptrdiff_t rv = 0;
+ rv += func_as_int(f_plain);
+ rv += func_as_int(f_sysvabi);
+ rv += func_as_int(f_msabi);
+ return rv;
+}
+
+// CHECK-WIN: define dso_local i64 @_Z7useThemv()
+// CHECK-WIN: call i64 @_Z11func_as_intIFiiEExPT_(i32 (i32)* @_Z7f_plaini)
+// CHECK-WIN: call i64 @_Z11func_as_intIU8sysv_abiFiiEExPT_(i32 (i32)* @_Z9f_sysvabii)
+// CHECK-WIN: call i64 @_Z11func_as_intIFiiEExPT_(i32 (i32)* @_Z7f_msabii)
+
+// CHECK-LIN: define i64 @_Z7useThemv()
+// CHECK-LIN: call i64 @_Z11func_as_intIFiiEElPT_(i32 (i32)* @_Z7f_plaini)
+// CHECK-LIN: call i64 @_Z11func_as_intIFiiEElPT_(i32 (i32)* @_Z9f_sysvabii)
+// CHECK-LIN: call i64 @_Z11func_as_intIU6ms_abiFiiEElPT_(i32 (i32)* @_Z7f_msabii)
diff --git a/test/CodeGenCXX/merge-functions.cpp b/test/CodeGenCXX/merge-functions.cpp
index 2137f19c409c..20a286e02203 100644
--- a/test/CodeGenCXX/merge-functions.cpp
+++ b/test/CodeGenCXX/merge-functions.cpp
@@ -1,5 +1,5 @@
// REQUIRES: x86-registered-target
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O1 -fmerge-functions -emit-llvm -o - -x c++ < %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O1 -fmerge-functions -emit-llvm -o - -x c++ < %s | FileCheck %s -implicit-check-not=_ZN1A1gEiPi
// Basic functionality test. Function merging doesn't kick in on functions that
// are too simple.
@@ -9,6 +9,4 @@ struct A {
virtual int g(int x, int *p) { return x ? *p : 1; }
} a;
-// CHECK: define {{.*}} @_ZN1A1gEiPi
-// CHECK-NEXT: tail call i32 @_ZN1A1fEiPi
-// CHECK-NEXT: ret
+// CHECK: define {{.*}} @_ZN1A1fEiPi
diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
index db9526633ff1..e6a0891cfc65 100644
--- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -3,8 +3,8 @@
// CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()*, i8* }] [
// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany1@@3US@@A", i32 0, i32 0) },
// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany2@@3US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
-// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"?foo@?$B@H@@2VA@@A" to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?s@?$ExportedTemplate@H@@2US@@A@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ", i8* bitcast (%class.A* @"?foo@?$B@H@@2VA@@A" to i8*) },
// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }
// CHECK: ]
@@ -231,18 +231,18 @@ void force_usage() {
DynamicDLLImportInitVSMangling::switch_test3();
}
-// CHECK: define linkonce_odr dso_local void @"??__Efoo@?$B@H@@2VA@@A@YAXXZ"() {{.*}} comdat
+// CHECK: define linkonce_odr dso_local void @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ"() {{.*}} comdat
// CHECK-NOT: and
// CHECK-NOT: ?_Bfoo@
// CHECK: call x86_thiscallcc %class.A* @"??0A@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ")
+// CHECK: call i32 @atexit(void ()* @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ")
// CHECK: ret void
// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.A* @"??0A@@QAE@XZ"({{.*}}) {{.*}} comdat
// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) {{.*}} comdat
-// CHECK: define internal void @"??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
+// CHECK: define internal void @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ"
// CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"{{.*}}foo
// CHECK: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index 97b90ce6b9eb..b0d2b5654030 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -467,9 +467,9 @@ struct A {
void *getA() {
return (void*)new A();
}
-// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A@@UAEPAXI@Z"
+// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A0x{{[^@]*}}@@UAEPAXI@Z"
// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
-// CHECK: define internal x86_thiscallcc void @"??1A@?A@@UAE@XZ"
+// CHECK: define internal x86_thiscallcc void @"??1A@?A0x{{[^@]*}}@@UAE@XZ"
// CHECK: (%"struct.(anonymous namespace)::A"* %this)
// Check that we correctly transform __stdcall to __thiscall for ctors and
diff --git a/test/CodeGenCXX/microsoft-abi-throw.cpp b/test/CodeGenCXX/microsoft-abi-throw.cpp
index cbbce2daaad8..f55b94acf1d7 100644
--- a/test/CodeGenCXX/microsoft-abi-throw.cpp
+++ b/test/CodeGenCXX/microsoft-abi-throw.cpp
@@ -22,7 +22,7 @@
// CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1P6AXXZ to i8*) }, section ".xdata", comdat
// CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.2* @_CTA2PAPFAH to i8*) }, section ".xdata", comdat
// CHECK-DAG: @_CTA2PAPFAH = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0PAPFAH@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat
-// CHECK-DAG: @"_TI1?AUFoo@?A@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A@@" to i8*) }, section ".xdata"
+// CHECK-DAG: @"_TI1?AUFoo@?A0x{{[^@]*}}@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A0x{{[^@]*}}@@" to i8*) }, section ".xdata"
struct N { ~N(); };
@@ -135,6 +135,6 @@ namespace { struct Foo { } foo_exc; }
void *GetExceptionInfo_test2() {
// CHECK-LABEL: @"?GetExceptionInfo_test2@@YAPAXXZ"
-// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A@@" to i8*)
+// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A0x{{[^@]*}}@@" to i8*)
return __GetExceptionInfo(foo_exc);
}
diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp
index c2f64f38417c..2b0231ffe74e 100644
--- a/test/CodeGenCXX/microsoft-abi-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -160,5 +160,5 @@ struct E : D {
E::E() {}
E e;
// Class with internal linkage has internal linkage thunks.
-// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A@@QAEPAUB@@XZ"
+// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A0x{{[^@]*}}@@QAEPAUB@@XZ"
}
diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
index 46e159c628f0..ae6602053b8c 100644
--- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
@@ -19,7 +19,7 @@ D d; // Force vbtable emission.
// C: vbptr C
// int c
-// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20]
+// CHECK-DAG: @"??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20], comdat, align 4
// CHECK-DAG: @"??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
// CHECK-DAG: @"??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12]
// CHECK-DAG: @"??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp
index 65370ab1ece5..f8d26f14f91d 100644
--- a/test/CodeGenCXX/microsoft-abi-vftables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp
@@ -36,10 +36,10 @@ struct W {
virtual ~W() {}
} w;
}
-// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
-// RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
+// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"??_R4W@?A0x{{[^@]*}}@@6B@" to i8*), i8* bitcast ({{.*}} @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z" to i8*)] }
+// RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A@@UAEPAXI@Z" to i8*)] }
+// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z" to i8*)] }
struct X {};
template <class> struct Y : virtual X {
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
index ef8a5e486825..5ebe612e00ac 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
@@ -57,14 +57,14 @@ void f() {
// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AE" to i8*), i8** %ptr
// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B3AE" to i8*), i8** %ptr2
// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AE" to i8*), i8** %ptr3
-// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
+// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AE" to i8*), i8** %ptr4
// CHECK32: }
//
// CHECK64-LABEL: define dso_local void @"?f@@YAXXZ"()
// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AA" to i8*), i8** %ptr
// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AA" to i8*), i8** %ptr2
// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BBA@AA" to i8*), i8** %ptr3
-// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A@@$BA@AA" to i8*), i8** %ptr
+// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AA" to i8*), i8** %ptr
// CHECK64: }
}
@@ -125,7 +125,7 @@ void f() {
// CHECK64: }
// Thunk for calling the virtual function in internal class D.
-// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A0x{{[^@]*}}@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK32: #[[ATTR]]
// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
@@ -133,7 +133,7 @@ void f() {
// CHECK32-NEXT: ret void
// CHECK32: }
//
-// CHECK64-LABEL: define internal void @"??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
+// CHECK64-LABEL: define internal void @"??_9D@?A0x{{[^@]*}}@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...)
// CHECK64: #[[ATTR]]
// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0
// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]]
diff --git a/test/CodeGenCXX/msabi-swiftcall-cc.cpp b/test/CodeGenCXX/msabi-swiftcall-cc.cpp
index d8205ed192a5..3cc90a83fbd1 100644
--- a/test/CodeGenCXX/msabi-swiftcall-cc.cpp
+++ b/test/CodeGenCXX/msabi-swiftcall-cc.cpp
@@ -12,8 +12,8 @@ void (__attribute__((__swiftcall__)) *p)();
namespace {
void __attribute__((__swiftcall__)) __attribute__((__used__)) f() { }
}
-// CHECK-DAG: @"?f@?A@@YSXXZ"
-// CHECK-64-DAG: @"?f@?A@@YSXXZ"
+// CHECK-DAG: @"?f@?A0x{{[^@]*}}@@YSXXZ"
+// CHECK-64-DAG: @"?f@?A0x{{[^@]*}}@@YSXXZ"
namespace n {
void __attribute__((__swiftcall__)) f() {}
@@ -44,8 +44,8 @@ void (__attribute__((__preserve_most__)) *q)();
namespace {
void __attribute__((__preserve_most__)) __attribute__((__used__)) g() {}
}
-// CHECK-DAG: @"?g@?A@@YUXXZ"
-// CHECK-64-DAG: @"?g@?A@@YUXXZ"
+// CHECK-DAG: @"?g@?A0x{{[^@]*}}@@YUXXZ"
+// CHECK-64-DAG: @"?g@?A0x{{[^@]*}}@@YUXXZ"
namespace n {
void __attribute__((__preserve_most__)) g() {}
diff --git a/test/CodeGenCXX/no-lto-unit.cpp b/test/CodeGenCXX/no-lto-unit.cpp
index 24b8fd01546a..3797f0742efb 100644
--- a/test/CodeGenCXX/no-lto-unit.cpp
+++ b/test/CodeGenCXX/no-lto-unit.cpp
@@ -2,6 +2,8 @@
// RUN: llvm-dis -o - %t | FileCheck %s
// RUN: %clang_cc1 -flto=thin -flto-unit -fno-lto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s
// RUN: llvm-dis -o - %t | FileCheck %s
+// RUN: llvm-bcanalyzer -dump %t | FileCheck %s --check-prefix=NOLTOUNIT
+// NOLTOUNIT: <FLAGS op0=0/>
// CHECK-NOT: !type
class A {
diff --git a/test/CodeGenCXX/no_destroy.cpp b/test/CodeGenCXX/no_destroy.cpp
new file mode 100644
index 000000000000..93e6ce17bb69
--- /dev/null
+++ b/test/CodeGenCXX/no_destroy.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | FileCheck %s
+
+struct NonTrivial {
+ ~NonTrivial();
+};
+
+// CHECK-NOT: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev
+[[clang::no_destroy]] NonTrivial nt1;
+// CHECK-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
+[[clang::no_destroy]] thread_local NonTrivial nt2;
+
+struct NonTrivial2 {
+ ~NonTrivial2();
+};
+
+// CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev
+NonTrivial2 nt21;
+// CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev
+thread_local NonTrivial2 nt22;
+
+void f() {
+ // CHECK: __cxa_atexit{{.*}}_ZN11NonTrivial2D1Ev
+ static NonTrivial2 nt21;
+ // CHECK: _tlv_atexit{{.*}}_ZN11NonTrivial2D1Ev
+ thread_local NonTrivial2 nt22;
+}
+
+// CHECK: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev
+[[clang::always_destroy]] NonTrivial nt3;
+// CHECK: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
+[[clang::always_destroy]] thread_local NonTrivial nt4;
diff --git a/test/CodeGenCXX/noescape.cpp b/test/CodeGenCXX/noescape.cpp
index 90d24de3da29..40bc839788ac 100644
--- a/test/CodeGenCXX/noescape.cpp
+++ b/test/CodeGenCXX/noescape.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -fblocks -o - %s | FileCheck %s
struct S {
int a[4];
@@ -65,3 +65,32 @@ typedef void (*NoEscapeFunc)(__attribute__((noescape)) int *);
void test3(NoEscapeFunc f, int *p) {
f(p);
}
+
+namespace TestByref {
+
+struct S {
+ S();
+ ~S();
+ S(const S &);
+ int a;
+};
+
+typedef void (^BlockTy)(void);
+S &getS();
+void noescapefunc(__attribute__((noescape)) BlockTy);
+
+// Check that __block variables with reference types are handled correctly.
+
+// CHECK: define void @_ZN9TestByref4testEv(
+// CHECK: %[[X:.*]] = alloca %[[STRUCT_TESTBYREF:.*]]*, align 8
+// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>, align 8
+// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>, <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>* %[[BLOCK]], i32 0, i32 5
+// CHECK: %[[V0:.*]] = load %[[STRUCT_TESTBYREF]]*, %[[STRUCT_TESTBYREF]]** %[[X]], align 8
+// CHECK: store %[[STRUCT_TESTBYREF]]* %[[V0]], %[[STRUCT_TESTBYREF]]** %[[BLOCK_CAPTURED]], align 8
+
+void test() {
+ __block S &x = getS();
+ noescapefunc(^{ (void)x; });
+}
+
+}
diff --git a/test/CodeGenCXX/override-layout-packed-base.cpp b/test/CodeGenCXX/override-layout-packed-base.cpp
index 26ed4b5d815a..03255f2f6ebf 100644
--- a/test/CodeGenCXX/override-layout-packed-base.cpp
+++ b/test/CodeGenCXX/override-layout-packed-base.cpp
@@ -1,26 +1,40 @@
-// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | FileCheck %s
+
+//#pragma pack(push, 1)
// CHECK: Type: class B<0>
+// CHECK: Size:40
// CHECK: FieldOffsets: [0, 32]
// CHECK: Type: class B<1>
+// CHECK: Size:40
// CHECK: FieldOffsets: [0, 32]
-//#pragma pack(push, 1)
template<int I>
class B {
int _b1;
char _b2;
};
-//#pragma pack(pop)
// CHECK: Type: class C
+// CHECK: Size:88
// CHECK: FieldOffsets: [80]
class C : B<0>, B<1> {
char _c;
};
+// CHECK: Type: class D
+// CHECK: Size:120
+// CHECK: FieldOffsets: [32]
+
+class D : virtual B<0>, virtual B<1> {
+ char _d;
+};
+
+//#pragma pack(pop)
+
void use_structs() {
C cs[sizeof(C)];
+ D ds[sizeof(D)];
}
diff --git a/test/CodeGenCXX/pragma-init_seg.cpp b/test/CodeGenCXX/pragma-init_seg.cpp
index 8b33b854fd21..f0b15598c472 100644
--- a/test/CodeGenCXX/pragma-init_seg.cpp
+++ b/test/CodeGenCXX/pragma-init_seg.cpp
@@ -28,8 +28,8 @@ int z = f();
namespace internal_init {
namespace {
int x = f();
-// CHECK: @"?x@?A@internal_init@@3HA" = internal global i32 0, align 4
-// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A@internal_init@@YAXXZ", section ".asdf"
+// CHECK: @"?x@?A0x{{[^@]*}}@internal_init@@3HA" = internal global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr.2 = private constant void ()* @"??__Ex@?A0x{{[^@]*}}@internal_init@@YAXXZ", section ".asdf"
}
}
@@ -44,7 +44,7 @@ template <typename T> struct A { static const int x; };
template <typename T> const int A<T>::x = f();
template struct A<int>;
// CHECK: @"?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr dso_local global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@explicit_template_instantiation@@2HB")
+// CHECK: @__cxx_init_fn_ptr.4 = private constant void ()* @"??__E?x@?$A@H@explicit_template_instantiation@@2HB@@YAXXZ", section ".asdf", comdat($"?x@?$A@H@explicit_template_instantiation@@2HB")
}
namespace implicit_template_instantiation {
@@ -52,7 +52,7 @@ template <typename T> struct A { static const int x; };
template <typename T> const int A<T>::x = f();
int g() { return A<int>::x; }
// CHECK: @"?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr dso_local global i32 0, comdat, align 4
-// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"?x@?$A@H@implicit_template_instantiation@@2HB")
+// CHECK: @__cxx_init_fn_ptr.5 = private constant void ()* @"??__E?x@?$A@H@implicit_template_instantiation@@2HB@@YAXXZ", section ".asdf", comdat($"?x@?$A@H@implicit_template_instantiation@@2HB")
}
// ... and here's where we emitted user level ctors.
diff --git a/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp b/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp
new file mode 100644
index 000000000000..da060f7902ef
--- /dev/null
+++ b/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+// Verify that the outer loop has the llvm.access.group property for the
+// accesses outside and inside the inner loop, even when the inner loop
+// is not perfectly nested.
+void vectorize_imperfectly_nested_test(int *List, int Length) {
+#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable)
+ for (int i = 0; i < Length; ++i) {
+ List[i * Length] = 42;
+#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable)
+ for (int j = 1; j < Length - 1; ++j)
+ List[i * Length + j] = (i + j) * 2;
+ List[(i + 1) * Length - 1] = 21;
+ }
+}
+
+
+// CHECK: load i32, i32* %Length.addr, align 4, !llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]]
+
+// CHECK: %[[MUL:.+]] = mul nsw i32 %add, 2
+// CHECK: store i32 %[[MUL]], i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_3:[0-9]+]]
+// CHECK: br label %{{.+}}, !llvm.loop ![[INNER_LOOPID:[0-9]+]]
+// CHECK: store i32 21, i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_2]]
+// CHECK: br label %{{.+}}, !llvm.loop ![[OUTER_LOOPID:[0-9]+]]
+
+// CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
+// CHECK: ![[ACCESS_GROUP_LIST_3:[0-9]+]] = !{![[ACCESS_GROUP_2]], ![[ACCESS_GROUP_4:[0-9]+]]}
+// CHECK: ![[ACCESS_GROUP_4]] = distinct !{}
+// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_8:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_8]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_4]]}
+// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_10:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_10]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
diff --git a/test/CodeGenCXX/pragma-loop-safety-nested.cpp b/test/CodeGenCXX/pragma-loop-safety-nested.cpp
new file mode 100644
index 000000000000..deec06bbc827
--- /dev/null
+++ b/test/CodeGenCXX/pragma-loop-safety-nested.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+// Verify that the outer loop has the llvm.access.group property for the
+// accesses outside and inside the inner loop.
+void vectorize_nested_test(int *List, int Length) {
+#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable)
+ for (int i = 0; i < Length; ++i) {
+#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable)
+ for (int j = 0; j < Length; ++j)
+ List[i * Length + j] = (i + j) * 2;
+ }
+}
+
+
+// CHECK: load i32, i32* %Length.addr, align 4, !llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]]
+// CHECK: %[[MUL:.+]] = mul
+// CHECK: store i32 %[[MUL]], i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_LIST_3:[0-9]+]]
+// CHECK: br label %{{.+}}, !llvm.loop ![[INNER_LOOPID:[0-9]+]]
+// CHECK: br label %{{.+}}, !llvm.loop ![[OUTER_LOOPID:[0-9]+]]
+
+// CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
+// CHECK: ![[ACCESS_GROUP_LIST_3]] = !{![[ACCESS_GROUP_2]], ![[ACCESS_GROUP_4:[0-9]+]]}
+// CHECK: ![[ACCESS_GROUP_4]] = distinct !{}
+// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_8:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_8]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_4]]}
+// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_10:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_10]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
diff --git a/test/CodeGenCXX/pragma-loop-safety-outer.cpp b/test/CodeGenCXX/pragma-loop-safety-outer.cpp
new file mode 100644
index 000000000000..d99b86ffe23a
--- /dev/null
+++ b/test/CodeGenCXX/pragma-loop-safety-outer.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+// Verify that the outer loop has the inner loop's access in its
+// llvm.loop.parallel_accesses property.
+void vectorize_outer_test(int *List, int Length) {
+#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable)
+ for (int i = 0; i < Length; i += 2) {
+#pragma clang loop unroll(full)
+ for (int j = 0; j < 2; j += 1)
+ List[i + j] = (i + j) * 2;
+ }
+}
+
+// CHECK: %[[MUL:.+]] = mul
+// CHECK: store i32 %[[MUL]], i32* %{{.+}}, !llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]]
+// CHECK: br label %{{.+}}, !llvm.loop ![[INNER_LOOPID:[0-9]+]]
+// CHECK: br label %{{.+}}, !llvm.loop ![[OUTER_LOOPID:[0-9]+]]
+
+// CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
+// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]],
+// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], {{.*}} ![[PARALLEL_ACCESSES_9:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_9]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
diff --git a/test/CodeGenCXX/pragma-loop-safety.cpp b/test/CodeGenCXX/pragma-loop-safety.cpp
index c6ce82737d0b..c0b10b0a6bd1 100644
--- a/test/CodeGenCXX/pragma-loop-safety.cpp
+++ b/test/CodeGenCXX/pragma-loop-safety.cpp
@@ -3,19 +3,19 @@
// Verify assume_safety vectorization is recognized.
void vectorize_test(int *List, int Length) {
// CHECK: define {{.*}} @_Z14vectorize_test
-// CHECK: [[LOAD1_IV:.+]] = load i32, i32* [[IV1:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID:[0-9]+]]
-// CHECK-NEXT: [[LOAD1_LEN:.+]] = load i32, i32* [[LEN1:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+// CHECK: [[LOAD1_IV:.+]] = load i32, i32* [[IV1:[^,]+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2:[0-9]+]]
+// CHECK-NEXT: [[LOAD1_LEN:.+]] = load i32, i32* [[LEN1:.+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]]
// CHECK-NEXT: [[CMP1:.+]] = icmp slt i32[[LOAD1_IV]],[[LOAD1_LEN]]
// CHECK-NEXT: br i1[[CMP1]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]]
#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable)
for (int i = 0; i < Length; i++) {
- // CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+ // CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]]
// CHECK-DAG: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2
- // CHECK-DAG: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+ // CHECK-DAG: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.access.group ![[ACCESS_GROUP_2]]
// CHECK-DAG: [[INDEX1:.+]] = sext i32[[SIV1]] to i64
- // CHECK-DAG: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+ // CHECK-DAG: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]]
// CHECK-DAG: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]]
- // CHECK: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+ // CHECK: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_2]]
// CHECK-NEXT: br label [[LOOP1_INC:[^,]+]]
List[i] = i * 2;
@@ -26,19 +26,19 @@ void vectorize_test(int *List, int Length) {
// Verify assume_safety interleaving is recognized.
void interleave_test(int *List, int Length) {
// CHECK: define {{.*}} @_Z15interleave_test
-// CHECK: [[LOAD2_IV:.+]] = load i32, i32* [[IV2:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID:[0-9]+]]
-// CHECK-NEXT: [[LOAD2_LEN:.+]] = load i32, i32* [[LEN2:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+// CHECK: [[LOAD2_IV:.+]] = load i32, i32* [[IV2:[^,]+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8:[0-9]+]]
+// CHECK-NEXT: [[LOAD2_LEN:.+]] = load i32, i32* [[LEN2:.+]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]]
// CHECK-NEXT: [[CMP2:.+]] = icmp slt i32[[LOAD2_IV]],[[LOAD2_LEN]]
// CHECK-NEXT: br i1[[CMP2]], label %[[LOOP2_BODY:[^,]+]], label %[[LOOP2_END:[^,]+]]
#pragma clang loop interleave(assume_safety) vectorize(disable) unroll(disable)
for (int i = 0; i < Length; i++) {
- // CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+ // CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]]
// CHECK-DAG: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2
- // CHECK-DAG: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+ // CHECK-DAG: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.access.group ![[ACCESS_GROUP_8]]
// CHECK-DAG: [[INDEX2:.+]] = sext i32[[SIV2]] to i64
- // CHECK-DAG: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+ // CHECK-DAG: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]]
// CHECK-DAG: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]]
- // CHECK: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+ // CHECK: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.access.group ![[ACCESS_GROUP_8]]
// CHECK-NEXT: br label [[LOOP2_INC:[^,]+]]
List[i] = i * 2;
@@ -46,9 +46,13 @@ void interleave_test(int *List, int Length) {
}
}
-// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]]}
+// CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
+// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]], ![[PARALLEL_ACCESSES_7:[0-9]+]]}
// CHECK: ![[INTERLEAVE_1]] = !{!"llvm.loop.interleave.count", i32 1}
// CHCCK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true}
// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
-// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]], ![[UNROLL_DISABLE]]}
+// CHECK: ![[PARALLEL_ACCESSES_7]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
+// CHECK: ![[ACCESS_GROUP_8]] = distinct !{}
+// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]], ![[UNROLL_DISABLE]], ![[PARALLEL_ACCESSES_11:[0-9]+]]}
// CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1}
+// CHECK: ![[PARALLEL_ACCESSES_11]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_8]]}
diff --git a/test/CodeGenCXX/pragma-pipeline.cpp b/test/CodeGenCXX/pragma-pipeline.cpp
new file mode 100644
index 000000000000..6846f1544365
--- /dev/null
+++ b/test/CodeGenCXX/pragma-pipeline.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple hexagon -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+void pipeline_disabled(int *List, int Length, int Value) {
+// CHECK-LABEL: define {{.*}} @_Z17pipeline_disabled
+#pragma clang loop pipeline(disable)
+ for (int i = 0; i < Length; i++) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
+ List[i] = Value;
+ }
+}
+
+void pipeline_not_disabled(int *List, int Length, int Value) {
+ // CHECK-LABEL: define {{.*}} @_Z21pipeline_not_disabled
+ for (int i = 0; i < Length; i++) {
+ List[i] = Value;
+ }
+}
+
+void pipeline_initiation_interval(int *List, int Length, int Value) {
+// CHECK-LABEL: define {{.*}} @_Z28pipeline_initiation_interval
+#pragma clang loop pipeline_initiation_interval(10)
+ for (int i = 0; i < Length; i++) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
+ List[i] = Value;
+ }
+}
+
+void pipeline_disabled_on_nested_loop(int *List, int Length, int Value) {
+ // CHECK-LABEL: define {{.*}} @_Z32pipeline_disabled_on_nested_loop
+ for (int i = 0; i < Length; i++) {
+#pragma clang loop pipeline(disable)
+ for (int j = 0; j < Length; j++) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]]
+ List[i * Length + j] = Value;
+ }
+ }
+}
+
+// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[PIPELINE_DISABLE:.*]]}
+// CHECK: ![[PIPELINE_DISABLE]] = !{!"llvm.loop.pipeline.disable", i1 true}
+
+// CHECK-NOT:llvm.loop.pipeline
+
+// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[PIPELINE_II_10:.*]]}
+// CHECK: ![[PIPELINE_II_10]] = !{!"llvm.loop.pipeline.initiationinterval", i32 10}
+
+// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[PIPELINE_DISABLE]]}
diff --git a/test/CodeGenCXX/pragma-unroll-and-jam.cpp b/test/CodeGenCXX/pragma-unroll-and-jam.cpp
new file mode 100644
index 000000000000..984212603450
--- /dev/null
+++ b/test/CodeGenCXX/pragma-unroll-and-jam.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -triple arm-none-eabi -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+void unroll_and_jam(int *List, int Length, int Value) {
+ // CHECK-LABEL: define {{.*}} @_Z14unroll_and_jam
+#pragma unroll_and_jam
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
+ List[i * Length + j] = Value;
+ }
+ }
+}
+
+void unroll_and_jam_count(int *List, int Length, int Value) {
+ // CHECK-LABEL: define {{.*}} @_Z20unroll_and_jam_count
+#pragma unroll_and_jam(4)
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
+ List[i * Length + j] = Value;
+ }
+ }
+}
+
+void nounroll_and_jam(int *List, int Length, int Value) {
+ // CHECK-LABEL: define {{.*}} @_Z16nounroll_and_jam
+#pragma nounroll_and_jam
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
+ List[i * Length + j] = Value;
+ }
+ }
+}
+
+void clang_unroll_plus_nounroll_and_jam(int *List, int Length, int Value) {
+ // CHECK-LABEL: define {{.*}} @_Z34clang_unroll_plus_nounroll_and_jam
+#pragma nounroll_and_jam
+#pragma unroll(4)
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]]
+ List[i * Length + j] = Value;
+ }
+ }
+}
+
+// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNJ_ENABLE:.*]]}
+// CHECK: ![[UNJ_ENABLE]] = !{!"llvm.loop.unroll_and_jam.enable"}
+// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[UNJ_4:.*]]}
+// CHECK: ![[UNJ_4]] = !{!"llvm.loop.unroll_and_jam.count", i32 4}
+// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNJ_DISABLE:.*]]}
+// CHECK: ![[UNJ_DISABLE]] = !{!"llvm.loop.unroll_and_jam.disable"}
+// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_4:.*]], ![[UNJ_DISABLE:.*]]}
+// CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4}
diff --git a/test/CodeGenCXX/profile-remap.cpp b/test/CodeGenCXX/profile-remap.cpp
new file mode 100644
index 000000000000..0fc7c7b40033
--- /dev/null
+++ b/test/CodeGenCXX/profile-remap.cpp
@@ -0,0 +1,29 @@
+// REQUIRES: x86-registered-target
+//
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fprofile-sample-use=%S/Inputs/profile-remap.samples -fprofile-remapping-file=%S/Inputs/profile-remap.map -fexperimental-new-pass-manager -O2 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SAMPLES
+// RUN: llvm-profdata merge -output %T.profdata %S/Inputs/profile-remap.proftext
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fprofile-instrument-use-path=%T.profdata -fprofile-remapping-file=%S/Inputs/profile-remap.map -fexperimental-new-pass-manager -O2 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-INSTR
+
+namespace Foo {
+ struct X {};
+ bool cond();
+ void bar();
+ void baz();
+ void function(X x) {
+ if (cond())
+ bar();
+ else
+ baz();
+ }
+}
+
+// CHECK: define {{.*}} @_ZN3Foo8functionENS_1XE() {{.*}} !prof [[FUNC_ENTRY:![0-9]*]]
+// CHECK: br i1 {{.*}} !prof [[BR_WEIGHTS:![0-9]*]]
+//
+// FIXME: Laplace's rule of succession is applied to sample profiles...
+// CHECK-SAMPLES-DAG: [[FUNC_ENTRY]] = !{!"function_entry_count", i64 1}
+// CHECK-SAMPLES-DAG: [[BR_WEIGHTS]] = !{!"branch_weights", i32 11, i32 91}
+//
+// ... but not to instruction profiles.
+// CHECK-INSTR-DAG: [[FUNC_ENTRY]] = !{!"function_entry_count", i64 100}
+// CHECK-INSTR-DAG: [[BR_WEIGHTS]] = !{!"branch_weights", i32 10, i32 90}
diff --git a/test/CodeGenCXX/speculative-vtt.cpp b/test/CodeGenCXX/speculative-vtt.cpp
new file mode 100644
index 000000000000..120d95d4d482
--- /dev/null
+++ b/test/CodeGenCXX/speculative-vtt.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -O2 -disable-llvm-passes -emit-llvm -o - | FileCheck %s
+struct A { virtual ~A(); };
+template<typename T> struct B : virtual A {
+ ~B() override {}
+};
+struct C : B<int>, B<float> { C(); ~C() override; };
+struct D : C { ~D() override; };
+
+// We must not create a reference to B<int>::~B() here, because we're not going to emit it.
+// CHECK-NOT: @_ZN1BIiED1Ev
+// CHECK-NOT: @_ZTC1D0_1BIiE =
+// CHECK-NOT: @_ZTT1D = available_externally
+D *p = new D;
diff --git a/test/CodeGenCXX/static-init-wasm.cpp b/test/CodeGenCXX/static-init-wasm.cpp
index 68d139157e2d..579818ce5a20 100644
--- a/test/CodeGenCXX/static-init-wasm.cpp
+++ b/test/CodeGenCXX/static-init-wasm.cpp
@@ -38,7 +38,7 @@ void g() {
// Test various aspects of static constructor calls.
struct A {
- A();
+ A();
};
A theA;
diff --git a/test/CodeGenCXX/thunk-returning-memptr.cpp b/test/CodeGenCXX/thunk-returning-memptr.cpp
new file mode 100644
index 000000000000..0b7870c6d658
--- /dev/null
+++ b/test/CodeGenCXX/thunk-returning-memptr.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple=i686 -emit-llvm -o - %s | FileCheck %s
+
+
+struct X;
+typedef void (X::*memptr)();
+
+struct A {
+ virtual memptr f();
+};
+
+struct B {
+ virtual memptr f();
+};
+
+struct C : A, B {
+ C();
+ memptr f() override __attribute__((noinline)) { return nullptr; };
+};
+
+C::C() {}
+
+// Make sure the member pointer is returned from the thunk via the return slot.
+// Because of the tail call, the return value cannot be copied into a local
+// alloca. (PR39901)
+
+// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret %agg.result, %struct.C* %this)
+// CHECK: tail call void @_ZN1C1fEv({ i32, i32 }* sret %agg.result
diff --git a/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp b/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp
new file mode 100644
index 000000000000..e7c9e9ac2a5a
--- /dev/null
+++ b/test/CodeGenCXX/trivial-auto-var-init-attribute.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO
+
+template<typename T> void used(T &) noexcept;
+
+extern "C" {
+
+// UNINIT-LABEL: test_attribute_uninitialized(
+// UNINIT: alloca
+// UNINIT-NEXT: call void
+// ZERO-LABEL: test_attribute_uninitialized(
+// ZERO: alloca
+// ZERO-NEXT: call void
+// PATTERN-LABEL: test_attribute_uninitialized(
+// PATTERN: alloca
+// PATTERN-NEXT: call void
+void test_attribute_uninitialized() {
+ [[clang::uninitialized]] int i;
+ used(i);
+}
+
+} // extern "C"
diff --git a/test/CodeGenCXX/trivial-auto-var-init.cpp b/test/CodeGenCXX/trivial-auto-var-init.cpp
new file mode 100644
index 000000000000..b795c0755bd4
--- /dev/null
+++ b/test/CodeGenCXX/trivial-auto-var-init.cpp
@@ -0,0 +1,216 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO
+
+// None of the synthesized globals should contain `undef`.
+// PATTERN-NOT: undef
+// ZERO-NOT: undef
+
+template<typename T> void used(T &) noexcept;
+
+extern "C" {
+
+// UNINIT-LABEL: test_selfinit(
+// ZERO-LABEL: test_selfinit(
+// ZERO: store i32 0, i32* %self, align 4
+// PATTERN-LABEL: test_selfinit(
+// PATTERN: store i32 -1431655766, i32* %self, align 4
+void test_selfinit() {
+ int self = self + 1;
+ used(self);
+}
+
+// UNINIT-LABEL: test_block(
+// ZERO-LABEL: test_block(
+// ZERO: store i32 0, i32* %block
+// PATTERN-LABEL: test_block(
+// PATTERN: store i32 -1431655766, i32* %block
+void test_block() {
+ __block int block;
+ used(block);
+}
+
+// This type of code is currently not handled by zero / pattern initialization.
+// The test will break when that is fixed.
+// UNINIT-LABEL: test_goto_unreachable_value(
+// ZERO-LABEL: test_goto_unreachable_value(
+// ZERO-NOT: store {{.*}}%oops
+// PATTERN-LABEL: test_goto_unreachable_value(
+// PATTERN-NOT: store {{.*}}%oops
+void test_goto_unreachable_value() {
+ goto jump;
+ int oops;
+ jump:
+ used(oops);
+}
+
+// This type of code is currently not handled by zero / pattern initialization.
+// The test will break when that is fixed.
+// UNINIT-LABEL: test_goto(
+// ZERO-LABEL: test_goto(
+// ZERO: if.then:
+// ZERO: br label %jump
+// ZERO: store i32 0, i32* %oops, align 4
+// ZERO: br label %jump
+// ZERO: jump:
+// PATTERN-LABEL: test_goto(
+// PATTERN: if.then:
+// PATTERN: br label %jump
+// PATTERN: store i32 -1431655766, i32* %oops, align 4
+// PATTERN: br label %jump
+// PATTERN: jump:
+void test_goto(int i) {
+ if (i)
+ goto jump;
+ int oops;
+ jump:
+ used(oops);
+}
+
+// This type of code is currently not handled by zero / pattern initialization.
+// The test will break when that is fixed.
+// UNINIT-LABEL: test_switch(
+// ZERO-LABEL: test_switch(
+// ZERO: sw.bb:
+// ZERO-NEXT: store i32 0, i32* %oops, align 4
+// ZERO: sw.bb1:
+// ZERO-NEXT: call void @{{.*}}used
+// PATTERN-LABEL: test_switch(
+// PATTERN: sw.bb:
+// PATTERN-NEXT: store i32 -1431655766, i32* %oops, align 4
+// PATTERN: sw.bb1:
+// PATTERN-NEXT: call void @{{.*}}used
+void test_switch(int i) {
+ switch (i) {
+ case 0:
+ int oops;
+ break;
+ case 1:
+ used(oops);
+ }
+}
+
+// UNINIT-LABEL: test_vla(
+// ZERO-LABEL: test_vla(
+// ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4
+// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false)
+// PATTERN-LABEL: test_vla(
+// PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0
+// PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
+// PATTERN: vla-setup.loop:
+// PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4
+// PATTERN: %vla.begin = bitcast i32* %vla to i8*
+// PATTERN: %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]]
+// PATTERN: br label %vla-init.loop
+// PATTERN: vla-init.loop:
+// PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
+// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla
+// PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 4
+// PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
+// PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
+// PATTERN: vla-init.cont:
+// PATTERN: call void @{{.*}}used
+void test_vla(int size) {
+ // Variable-length arrays can't have a zero size according to C11 6.7.6.2/5.
+ // Neither can they be negative-sized.
+ //
+ // We don't use the former fact because some code creates zero-sized VLAs and
+ // doesn't use them. clang makes these share locations with other stack
+ // values, which leads to initialization of the wrong values.
+ //
+ // We rely on the later fact because it generates better code.
+ //
+ // Both cases are caught by UBSan.
+ int vla[size];
+ int *ptr = vla;
+ used(ptr);
+}
+
+// UNINIT-LABEL: test_struct_vla(
+// ZERO-LABEL: test_struct_vla(
+// ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16
+// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false)
+// PATTERN-LABEL: test_struct_vla(
+// PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0
+// PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
+// PATTERN: vla-setup.loop:
+// PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16
+// PATTERN: %vla.begin = bitcast %struct.anon* %vla to i8*
+// PATTERN: %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]]
+// PATTERN: br label %vla-init.loop
+// PATTERN: vla-init.loop:
+// PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
+// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla
+// PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 16
+// PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
+// PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
+// PATTERN: vla-init.cont:
+// PATTERN: call void @{{.*}}used
+void test_struct_vla(int size) {
+ // Same as above, but with a struct that doesn't just memcpy.
+ struct {
+ float f;
+ char c;
+ void *ptr;
+ } vla[size];
+ void *ptr = static_cast<void*>(vla);
+ used(ptr);
+}
+
+// UNINIT-LABEL: test_zsa(
+// ZERO-LABEL: test_zsa(
+// ZERO: %zsa = alloca [0 x i32], align 4
+// ZERO-NOT: %zsa
+// ZERO: call void @{{.*}}used
+// PATTERN-LABEL: test_zsa(
+// PATTERN: %zsa = alloca [0 x i32], align 4
+// PATTERN-NOT: %zsa
+// PATTERN: call void @{{.*}}used
+void test_zsa(int size) {
+ // Technically not valid, but as long as clang accepts them we should do
+ // something sensible (i.e. not store to the zero-size array).
+ int zsa[0];
+ used(zsa);
+}
+
+// UNINIT-LABEL: test_huge_uninit(
+// ZERO-LABEL: test_huge_uninit(
+// ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536,
+// PATTERN-LABEL: test_huge_uninit(
+// PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536,
+void test_huge_uninit() {
+ // We can't emit this as an inline constant to a store instruction because
+ // SDNode hits an internal size limit.
+ char big[65536];
+ used(big);
+}
+
+// UNINIT-LABEL: test_huge_small_init(
+// ZERO-LABEL: test_huge_small_init(
+// ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536,
+// ZERO: store i8 97,
+// ZERO: store i8 98,
+// ZERO: store i8 99,
+// ZERO: store i8 100,
+// PATTERN-LABEL: test_huge_small_init(
+// PATTERN: call void @llvm.memset{{.*}}, i8 0, i64 65536,
+// PATTERN: store i8 97,
+// PATTERN: store i8 98,
+// PATTERN: store i8 99,
+// PATTERN: store i8 100,
+void test_huge_small_init() {
+ char big[65536] = { 'a', 'b', 'c', 'd' };
+ used(big);
+}
+
+// UNINIT-LABEL: test_huge_larger_init(
+// ZERO-LABEL: test_huge_larger_init(
+// ZERO: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
+// PATTERN-LABEL: test_huge_larger_init(
+// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
+void test_huge_larger_init() {
+ char big[65536] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
+ used(big);
+}
+
+} // extern "C"
diff --git a/test/CodeGenCXX/trivial_abi.cpp b/test/CodeGenCXX/trivial_abi.cpp
index 2cf07b22581a..e37c8ff615a2 100644
--- a/test/CodeGenCXX/trivial_abi.cpp
+++ b/test/CodeGenCXX/trivial_abi.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
// CHECK: %[[STRUCT_SMALL:.*]] = type { i32* }
// CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] }
@@ -43,6 +43,13 @@ struct HasNonTrivial {
NonTrivial m;
};
+struct __attribute__((trivial_abi)) CopyMoveDeleted {
+ CopyMoveDeleted(int);
+ CopyMoveDeleted(const CopyMoveDeleted &) = delete;
+ CopyMoveDeleted(CopyMoveDeleted &&) = delete;
+ int a;
+};
+
// CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]])
// CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0
@@ -237,3 +244,11 @@ void calleeExceptionLarge(Large, Large);
void testExceptionLarge() {
calleeExceptionLarge(Large(), Large());
}
+
+// A class with deleted copy and move constructors can still be passed or
+// returned in registers if the class is annotated with trivial_abi.
+
+// CHECK: define i64 @_Z19testCopyMoveDeletedi(i32 %
+CopyMoveDeleted testCopyMoveDeleted(int a) {
+ return a;
+}
diff --git a/test/CodeGenCXX/type-metadata-thinlto.cpp b/test/CodeGenCXX/type-metadata-thinlto.cpp
index 2a586fc4c37c..8bf39f129c40 100644
--- a/test/CodeGenCXX/type-metadata-thinlto.cpp
+++ b/test/CodeGenCXX/type-metadata-thinlto.cpp
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -flto=thin -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s
+// RUN: %clang_cc1 -flto=thin -flto-unit -fsplit-lto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s
// RUN: llvm-modextract -o - -n 1 %t | llvm-dis | FileCheck %s
+// RUN: llvm-modextract -b -o - -n 1 %t | llvm-bcanalyzer -dump | FileCheck %s --check-prefix=LTOUNIT
+// LTOUNIT: <FLAGS op0=8/>
// CHECK: @_ZTV1A = linkonce_odr
class A {
diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp
index 8e3e4bd182fe..a7a34673cdfc 100644
--- a/test/CodeGenCXX/type-metadata.cpp
+++ b/test/CodeGenCXX/type-metadata.cpp
@@ -82,8 +82,8 @@
// MS: comdat($"??_7B@@6B0@@"), !type [[B8:![0-9]+]]
// MS: comdat($"??_7B@@6BA@@@"), !type [[A8]]
// MS: comdat($"??_7C@@6B@"), !type [[A8]]
-// MS: comdat($"??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
-// MS: comdat($"??_7D@?A@@6BA@@@"), !type [[A8]]
+// MS: comdat($"??_7D@?A0x{{[^@]*}}@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
+// MS: comdat($"??_7D@?A0x{{[^@]*}}@@6BA@@@"), !type [[A8]]
// MS: comdat($"??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]]
struct A {
@@ -161,7 +161,7 @@ void af(A *a) {
}
// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE
-// MS: define internal void @"?df1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
void df1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@@")
@@ -171,7 +171,7 @@ void df1(D *d) {
}
// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE
-// MS: define internal void @"?dg1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dg1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
void dg1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUB@@")
@@ -181,7 +181,7 @@ void dg1(D *d) {
}
// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE
-// MS: define internal void @"?dh1@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?dh1@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
void dh1(D *d) {
// TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]])
// TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
@@ -191,7 +191,7 @@ void dh1(D *d) {
}
// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE
-// MS: define internal void @"?df2@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df2@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
__attribute__((no_sanitize("cfi")))
void df2(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test
@@ -201,7 +201,7 @@ void df2(D *d) {
}
// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE
-// MS: define internal void @"?df3@@YAXPEAUD@?A@@@Z"
+// MS: define internal void @"?df3@@YAXPEAUD@?A0x{{[^@]*}}@@@Z"
__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall")))
void df3(D *d) {
// CFI-NVT-NOT: call i1 @llvm.type.test
diff --git a/test/CodeGenCXX/ubsan-check-debuglocs.cpp b/test/CodeGenCXX/ubsan-check-debuglocs.cpp
new file mode 100644
index 000000000000..96a697aca5eb
--- /dev/null
+++ b/test/CodeGenCXX/ubsan-check-debuglocs.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited \
+// RUN: -fsanitize=null %s -o - | FileCheck %s
+
+// Check that santizer check calls have a !dbg location.
+// CHECK: define {{.*}}acquire{{.*}} !dbg
+// CHECK-NOT: define
+// CHECK: call void {{.*}}@__ubsan_handle_type_mismatch_v1
+// CHECK-SAME: !dbg
+
+struct SourceLocation {
+ SourceLocation acquire() {};
+};
+extern "C" void __ubsan_handle_type_mismatch_v1(SourceLocation *Loc);
+static void handleTypeMismatchImpl(SourceLocation *Loc) { Loc->acquire(); }
+void __ubsan_handle_type_mismatch_v1(SourceLocation *Loc) {
+ handleTypeMismatchImpl(Loc);
+}
diff --git a/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp b/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp
new file mode 100644
index 000000000000..c0fa57d859c7
--- /dev/null
+++ b/test/CodeGenCXX/visibility-inlines-hidden-staticvar.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck -check-prefixes=CHECK-NO-VIH %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility hidden -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-HIDDEN
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility protected -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-PROTECTED
+
+// When a function is hidden due to -fvisibility-inlines-hidden option, static local variables of the function should not be hidden by the option.
+
+// CHECK-DAG: @_ZZ4funcvE3var = internal global i32 0
+// CHECK-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
+// CHECK-DAG: @_ZZ12default_funcvE3var = internal global i32 0
+// CHECK-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
+// CHECK-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
+// CHECK-DAG: define i32 @_Z4funcv()
+// CHECK-DAG: define hidden i32 @_Z11hidden_funcv()
+// CHECK-DAG: define i32 @_Z12default_funcv()
+// CHECK-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
+// CHECK-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
+// CHECK-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
+// CHECK-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
+// CHECK-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
+
+// CHECK-NO-VIH-DAG: @_ZZ4funcvE3var = internal global i32 0
+// CHECK-NO-VIH-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
+// CHECK-NO-VIH-DAG: @_ZZ12default_funcvE3var = internal global i32 0
+// CHECK-NO-VIH-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-NO-VIH-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
+// CHECK-NO-VIH-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-NO-VIH-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
+// CHECK-NO-VIH-DAG: define i32 @_Z4funcv()
+// CHECK-NO-VIH-DAG: define hidden i32 @_Z11hidden_funcv()
+// CHECK-NO-VIH-DAG: define i32 @_Z12default_funcv()
+// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z11inline_funcv()
+// CHECK-NO-VIH-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
+// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
+// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
+// CHECK-NO-VIH-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
+
+// CHECK-VIS-HIDDEN-DAG: @_ZZ4funcvE3var = internal global i32 0
+// CHECK-VIS-HIDDEN-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
+// CHECK-VIS-HIDDEN-DAG: @_ZZ12default_funcvE3var = internal global i32 0
+// CHECK-VIS-HIDDEN-DAG: @_ZZ11inline_funcvE3var = linkonce_odr hidden global i32 0, comdat
+// CHECK-VIS-HIDDEN-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
+// CHECK-VIS-HIDDEN-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-VIS-HIDDEN-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
+// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z4funcv()
+// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z11hidden_funcv()
+// CHECK-VIS-HIDDEN-DAG: define i32 @_Z12default_funcv()
+// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
+// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
+// CHECK-VIS-HIDDEN-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
+// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
+// CHECK-VIS-HIDDEN-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
+
+// CHECK-VIS-PROTECTED-DAG: @_ZZ4funcvE3var = internal global i32 0
+// CHECK-VIS-PROTECTED-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
+// CHECK-VIS-PROTECTED-DAG: @_ZZ12default_funcvE3var = internal global i32 0
+// CHECK-VIS-PROTECTED-DAG: @_ZZ11inline_funcvE3var = linkonce_odr protected global i32 0, comdat
+// CHECK-VIS-PROTECTED-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
+// CHECK-VIS-PROTECTED-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
+// CHECK-VIS-PROTECTED-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
+// CHECK-VIS-PROTECTED-DAG: define protected i32 @_Z4funcv()
+// CHECK-VIS-PROTECTED-DAG: define hidden i32 @_Z11hidden_funcv()
+// CHECK-VIS-PROTECTED-DAG: define i32 @_Z12default_funcv()
+// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
+// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
+// CHECK-VIS-PROTECTED-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
+// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
+// CHECK-VIS-PROTECTED-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
+
+int func(void) {
+ static int var = 0;
+ return var++;
+}
+inline int inline_func(void) {
+ static int var = 0;
+ return var++;
+}
+int __attribute__((visibility("hidden"))) hidden_func(void) {
+ static int var = 0;
+ return var++;
+}
+inline int __attribute__((visibility("hidden"))) inline_hidden_func(void) {
+ static int var = 0;
+ return var++;
+}
+int __attribute__((visibility("default"))) default_func(void) {
+ static int var = 0;
+ return var++;
+}
+inline int __attribute__((visibility("default"))) inline_default_func(void) {
+ static int var = 0;
+ return var++;
+}
+struct __attribute__((visibility("default"))) ExportedClass {
+ int inl_method() {
+ static int var = 0;
+ return var++;
+ }
+ int ext_method();
+};
+int ExportedClass::ext_method() { return inl_method(); }
+void bar(void) {
+ func();
+ inline_func();
+ hidden_func();
+ inline_hidden_func();
+ default_func();
+ inline_default_func();
+}
diff --git a/test/CodeGenCXX/vtable-align.cpp b/test/CodeGenCXX/vtable-align.cpp
index 1b82cbc085c9..bd0494fe5dd5 100644
--- a/test/CodeGenCXX/vtable-align.cpp
+++ b/test/CodeGenCXX/vtable-align.cpp
@@ -10,5 +10,8 @@ struct A {
void A::f() {}
// CHECK-32: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 4
-
+// CHECK-32: @_ZTS1A = constant [3 x i8] c"1A\00", align 1
+// CHECK-32: @_ZTI1A = constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i32 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) }, align 4
// CHECK-64: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 8
+// CHECK-64: @_ZTS1A = constant [3 x i8] c"1A\00", align 1
+// CHECK-64: @_ZTI1A = constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) }, align 8
diff --git a/test/CodeGenCXX/vtable-debug-info.cpp b/test/CodeGenCXX/vtable-debug-info.cpp
index 8710c76e0bfa..0ac90b3ec1d3 100644
--- a/test/CodeGenCXX/vtable-debug-info.cpp
+++ b/test/CodeGenCXX/vtable-debug-info.cpp
@@ -1,6 +1,6 @@
// RUN: %clang -emit-llvm -S -g %s -o /dev/null
// Radar 8730409
-// XFAIL: win32
+// XFAIL: windows-msvc
// FIXME: This test crashes on *-pc-win32
// for lack of debugging support on -integrated-as (MCCOFF).
diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp
index 0c55eb26f7f1..d4f06ce6ce03 100644
--- a/test/CodeGenCXX/vtable-linkage.cpp
+++ b/test/CodeGenCXX/vtable-linkage.cpp
@@ -98,10 +98,10 @@ void use_F() {
// C has no key function, so its vtable should have weak_odr linkage
// and hidden visibility (rdar://problem/7523229).
-// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant {{.*}}, comdat,
-// CHECK-DAG: @_ZTS1C = linkonce_odr constant {{.*}}, comdat{{$}}
-// CHECK-DAG: @_ZTI1C = linkonce_odr constant {{.*}}, comdat{{$}}
-// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant {{.*}}, comdat{{$}}
+// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, align 8{{$}}
+// CHECK-DAG: @_ZTS1C = linkonce_odr constant {{.*}}, comdat, align 1{{$}}
+// CHECK-DAG: @_ZTI1C = linkonce_odr constant {{.*}}, comdat, align 8{{$}}
+// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, align 8{{$}}
// D has a key function that is defined in this translation unit so its vtable is
// defined in the translation unit.
@@ -120,27 +120,27 @@ void use_F() {
// defined in this translation unit, so its vtable should have
// weak_odr linkage.
// CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant {{.*}}, comdat,
-// CHECK-DAG: @_ZTS1EIsE = weak_odr constant {{.*}}, comdat{{$}}
-// CHECK-DAG: @_ZTI1EIsE = weak_odr constant {{.*}}, comdat{{$}}
+// CHECK-DAG: @_ZTS1EIsE = weak_odr constant {{.*}}, comdat, align 1{{$}}
+// CHECK-DAG: @_ZTI1EIsE = weak_odr constant {{.*}}, comdat, align 8{{$}}
// F<short> is an explicit template instantiation without a key
// function, so its vtable should have weak_odr linkage
// CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant {{.*}}, comdat,
-// CHECK-DAG: @_ZTS1FIsE = weak_odr constant {{.*}}, comdat{{$}}
-// CHECK-DAG: @_ZTI1FIsE = weak_odr constant {{.*}}, comdat{{$}}
+// CHECK-DAG: @_ZTS1FIsE = weak_odr constant {{.*}}, comdat, align 1{{$}}
+// CHECK-DAG: @_ZTI1FIsE = weak_odr constant {{.*}}, comdat, align 8{{$}}
// E<long> is an implicit template instantiation with a key function
// defined in this translation unit, so its vtable should have
// linkonce_odr linkage.
// CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat,
-// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant {{.*}}, comdat{{$}}
-// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant {{.*}}, comdat{{$}}
+// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant {{.*}}, comdat, align 1{{$}}
+// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant {{.*}}, comdat, align 8{{$}}
// F<long> is an implicit template instantiation with no key function,
// so its vtable should have linkonce_odr linkage.
// CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat,
-// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant {{.*}}, comdat{{$}}
-// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant {{.*}}, comdat{{$}}
+// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant {{.*}}, comdat, align 1{{$}}
+// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant {{.*}}, comdat, align 8{{$}}
// F<int> is an explicit template instantiation declaration without a
// key function, so its vtable should have external linkage.
@@ -171,8 +171,8 @@ void use_F() {
// F<char> is an explicit specialization without a key function, so
// its vtable should have linkonce_odr linkage.
// CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant {{.*}}, comdat,
-// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant {{.*}}, comdat{{$}}
-// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant {{.*}}, comdat{{$}}
+// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant {{.*}}, comdat, align 1{{$}}
+// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant {{.*}}, comdat, align 8{{$}}
// CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant {{.*}}, comdat,
template <typename T>
diff --git a/test/CodeGenCXX/wasm-args-returns.cpp b/test/CodeGenCXX/wasm-args-returns.cpp
index 24adc8e08761..a7c4e1e282a1 100644
--- a/test/CodeGenCXX/wasm-args-returns.cpp
+++ b/test/CodeGenCXX/wasm-args-returns.cpp
@@ -3,16 +3,18 @@
// RUN: %clang_cc1 -O1 -triple wasm64-unknown-unknown -emit-llvm -o - %s \
// RUN: | FileCheck %s
-#define concat_(x, y) x ## y
+#define concat_(x, y) x##y
#define concat(x, y) concat_(x, y)
-#define test(T) \
+#define test(T) \
T forward(T x) { return x; } \
- void use(T x); \
- T concat(def_, T)(void); \
+ void use(T x); \
+ T concat(def_, T)(void); \
void concat(test_, T)(void) { use(concat(def_, T)()); }
-struct one_field { double d; };
+struct one_field {
+ double d;
+};
test(one_field);
// CHECK: define double @_Z7forward9one_field(double returned %{{.*}})
//
@@ -24,7 +26,9 @@ test(one_field);
// CHECK: declare void @_Z3use9one_field(double)
// CHECK: declare double @_Z13def_one_fieldv()
-struct two_fields { double d, e; };
+struct two_fields {
+ double d, e;
+};
test(two_fields);
// CHECK: define void @_Z7forward10two_fields(%struct.two_fields* noalias nocapture sret %{{.*}}, %struct.two_fields* byval nocapture readonly align 8 %{{.*}})
//
@@ -38,8 +42,8 @@ test(two_fields);
// CHECK: declare void @_Z14def_two_fieldsv(%struct.two_fields* sret)
struct copy_ctor {
- double d;
- copy_ctor(copy_ctor const&);
+ double d;
+ copy_ctor(copy_ctor const &);
};
test(copy_ctor);
// CHECK: define void @_Z7forward9copy_ctor(%struct.copy_ctor* noalias sret %{{.*}}, %struct.copy_ctor* %{{.*}})
@@ -56,8 +60,8 @@ test(copy_ctor);
// CHECK: declare void @_Z13def_copy_ctorv(%struct.copy_ctor* sret)
struct __attribute__((aligned(16))) aligned_copy_ctor {
- double d, e;
- aligned_copy_ctor(aligned_copy_ctor const&);
+ double d, e;
+ aligned_copy_ctor(aligned_copy_ctor const &);
};
test(aligned_copy_ctor);
// CHECK: define void @_Z7forward17aligned_copy_ctor(%struct.aligned_copy_ctor* noalias sret %{{.*}}, %struct.aligned_copy_ctor* %{{.*}})
@@ -86,7 +90,7 @@ test(empty);
// CHECK: declare void @_Z9def_emptyv()
struct one_bitfield {
- int d:3;
+ int d : 3;
};
test(one_bitfield);
// CHECK: define i32 @_Z7forward12one_bitfield(i32 returned %{{.*}})
diff --git a/test/CodeGenObjC/arc-arm.m b/test/CodeGenObjC/arc-arm.m
index 63c861f28951..b46f956bc62b 100644
--- a/test/CodeGenObjC/arc-arm.m
+++ b/test/CodeGenObjC/arc-arm.m
@@ -14,9 +14,9 @@ void test1(void) {
extern id test1_helper(void);
// CHECK: [[T0:%.*]] = call [[CC]]i8* @test1_helper()
// CHECK-NEXT: call void asm sideeffect "mov\09{{fp, fp|r7, r7}}\09\09// marker for objc_retainAutoreleaseReturnValue"
- // CHECK-NEXT: [[T1:%.*]] = call [[CC]]i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call [[CC]]i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]],
- // CHECK-NEXT: call [[CC]]void @objc_storeStrong(
+ // CHECK-NEXT: call [[CC]]void @llvm.objc.storeStrong(
// CHECK-NEXT: ret void
id x = test1_helper();
}
diff --git a/test/CodeGenObjC/arc-block-copy-escape.m b/test/CodeGenObjC/arc-block-copy-escape.m
index 16a75a0d3118..3823a95d6a85 100644
--- a/test/CodeGenObjC/arc-block-copy-escape.m
+++ b/test/CodeGenObjC/arc-block-copy-escape.m
@@ -9,14 +9,14 @@ void use_int(int);
void test0(int i) {
block_t block = ^{ use_int(i); };
// CHECK-LABEL: define {{.*}}void @test0(
- // CHECK: call {{.*}}i8* @objc_retainBlock(i8* {{%.*}}) [[NUW:#[0-9]+]], !clang.arc.copy_on_escape
+ // CHECK: call {{.*}}i8* @llvm.objc.retainBlock(i8* {{%.*}}) [[NUW:#[0-9]+]], !clang.arc.copy_on_escape
// CHECK: ret void
}
void test1(int i) {
id block = ^{ use_int(i); };
// CHECK-LABEL: define {{.*}}void @test1(
- // CHECK: call {{.*}}i8* @objc_retainBlock(i8* {{%.*}}) [[NUW]]
+ // CHECK: call {{.*}}i8* @llvm.objc.retainBlock(i8* {{%.*}}) [[NUW]]
// CHECK-NOT: !clang.arc.copy_on_escape
// CHECK: ret void
}
diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m
index b84d141037e0..49da992f95f5 100644
--- a/test/CodeGenObjC/arc-blocks.m
+++ b/test/CodeGenObjC/arc-blocks.m
@@ -1,5 +1,11 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-COMMON %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT -check-prefix=CHECK-COMMON %s
+
+// CHECK-COMMON: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+// CHECK-COMMON: @[[BLOCK_DESCRIPTOR_TMP44:.*]] = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i8*, i8*, i64 } { i64 0, i64 40, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_8_32s to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_8_32s to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8
+// CHECK-COMMON: @[[BLOCK_DESCRIPTOR_TMP9:.*]] = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i8*, i8*, i64 } { i64 0, i64 40, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_8_32r to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_8_32r to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 16 }, align 8
+// CHECK-COMMON: @[[BLOCK_DESCRIPTOR_TMP46:.*]] = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 48, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_8_32s to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_8_32s to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @{{.*}}, i32 0, i32 0) }, align 8
+// CHECK-COMMON: @[[BLOCK_DESCRIPTOR_TMP48:.*]] = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i8*, i8*, i64 } { i64 0, i64 40, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_8_32b to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_8_32s to i8*), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8
// This shouldn't crash.
void test0(id (^maker)(void)) {
@@ -13,10 +19,10 @@ int (^test1(int x))(void) {
// CHECK-NEXT: store i32 {{%.*}}, i32* [[X]]
// CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to i32 ()*
// CHECK-NEXT: [[T1:%.*]] = bitcast i32 ()* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) [[NUW:#[0-9]+]]
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T1]]) [[NUW:#[0-9]+]]
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()*
// CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8*
- // CHECK-NEXT: [[T5:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) [[NUW]]
+ // CHECK-NEXT: [[T5:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T4]]) [[NUW]]
// CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()*
// CHECK-NEXT: ret i32 ()* [[T6]]
return ^{ return x; };
@@ -26,39 +32,40 @@ void test2(id x) {
// CHECK-LABEL: define void @test2(
// CHECK: [[X:%.*]] = alloca i8*,
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
-// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+// CHECK-NEXT: [[PARM:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]],
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]],
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @test2_helper(
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOTREL]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: ret void
extern void test2_helper(id (^)(void));
test2_helper(^{ return x; });
-// CHECK-LABEL: define internal void @__copy_helper_block_(i8*, i8*) #{{[0-9]+}} {
+// CHECK: define linkonce_odr hidden void @__copy_helper_block_8_32s(i8*, i8*) unnamed_addr #{{[0-9]+}} {
// CHECK: [[T0:%.*]] = load i8*, i8**
// CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8**
// CHECK-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[SRC]], i32 0, i32 5
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) [[NUW]]
// CHECK-NEXT: ret void
-// CHECK-LABEL: define internal void @__destroy_helper_block_(i8*) #{{[0-9]+}} {
+
+// CHECK: define linkonce_odr hidden void @__destroy_helper_block_8_32s(i8*) unnamed_addr #{{[0-9]+}} {
// CHECK: [[T0:%.*]] = load i8*, i8**
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[T1]], i32 0, i32 5
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[T2]]
-// CHECK-NEXT: call void @objc_release(i8* [[T3]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T3]])
// CHECK-NEXT: ret void
}
@@ -71,7 +78,7 @@ void test3(void (^sink)(id*)) {
// CHECK-NEXT: [[STRONG:%.*]] = alloca i8*
// CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
// CHECK-NEXT: bitcast void (i8**)* {{%.*}} to i8*
- // CHECK-NEXT: call i8* @objc_retain(
+ // CHECK-NEXT: call i8* @llvm.objc.retain(
// CHECK-NEXT: bitcast i8*
// CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
// CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
@@ -88,20 +95,20 @@ void test3(void (^sink)(id*)) {
// CHECK-NEXT: [[F1:%.*]] = bitcast i8* [[F0]] to void (i8*, i8**)*
// CHECK-NEXT: call void [[F1]](i8* [[BLOCK]], i8** [[TEMP]])
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
- // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[V]]) [[NUW]]
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[V]]) [[NUW]]
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[STRONG]]
// CHECK-NEXT: store i8* [[T1]], i8** [[STRONG]]
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[STRONG]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[STRONGPTR2]])
// CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
// CHECK-NEXT: bitcast
- // CHECK-NEXT: call void @objc_release
+ // CHECK-NEXT: call void @llvm.objc.release
// CHECK-NEXT: ret void
}
@@ -120,7 +127,7 @@ void test4(void) {
// CHECK-NEXT: store i32 838860800, i32* [[T0]]
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
// CHECK-NEXT: [[T0:%.*]] = call i8* @test4_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]]
// CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
// 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
@@ -131,7 +138,7 @@ void test4(void) {
// CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK: ret void
// CHECK-LABEL: define internal void @__Block_byref_object_copy_(i8*, i8*) #{{[0-9]+}} {
@@ -146,19 +153,19 @@ void test4(void) {
// CHECK-LABEL: define internal void @__Block_byref_object_dispose_(i8*) #{{[0-9]+}} {
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-LABEL: define internal void @__test4_block_invoke
// CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align 8
// CHECK-NEXT: store i8* null, i8** [[SLOT]],
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: ret void
- // CHECK-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
+ // CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32r(i8*, i8*) unnamed_addr #{{[0-9]+}} {
// CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
- // CHECK-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
+ // CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_8_32r(i8*) unnamed_addr #{{[0-9]+}} {
// CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
}
@@ -174,9 +181,9 @@ void test5(void) {
// CHECK-NEXT: [[VARPTR1:%.*]] = bitcast i8** [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[VARPTR1]])
// CHECK: [[T0:%.*]] = call i8* @test5_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// 0x40800000 - has signature but no copy/dispose, as well as BLOCK_HAS_EXTENDED_LAYOUT
// CHECK: store i32 -1073741824, i32*
// CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
@@ -205,18 +212,20 @@ void test6(void) {
// CHECK-NEXT: store i32 1107296256, i32* [[T0]]
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
// CHECK-NEXT: [[T0:%.*]] = call i8* @test6_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T1]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[SLOT]], i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
// 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
// CHECK: store i32 -1040187392,
+ // CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %{{.*}}, i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i64 }* @[[BLOCK_DESCRIPTOR_TMP9]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
// CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
// CHECK-NEXT: store i8* [[T0]], i8**
// CHECK: call void @test6_helper(
// CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[SLOT]])
// CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 48, i8* [[VARPTR2]])
// CHECK-NEXT: ret void
@@ -226,24 +235,16 @@ void test6(void) {
// CHECK-NEXT: load i8*, i8**
// CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.moveWeak(i8** [[T0]], i8** [[T1]])
// CHECK-LABEL: define internal void @__Block_byref_object_dispose_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[T0]])
// CHECK-LABEL: define internal void @__test6_block_invoke
// CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
- // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[SLOT]], i8* null)
+ // CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[SLOT]], i8* null)
// CHECK-NEXT: ret void
-
- // CHECK-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
- // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
- // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
-
- // CHECK-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
- // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
- // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
}
void test7(void) {
@@ -257,33 +258,33 @@ void test7(void) {
// CHECK: [[VAR:%.*]] = alloca i8*,
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK: [[T0:%.*]] = call i8* @test7_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[VAR]], i8* [[T1]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[VAR]], i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
// CHECK: store i32 -1040187392,
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
- // CHECK-NEXT: call void @objc_copyWeak(i8** [[SLOT]], i8** [[VAR]])
+ // CHECK-NEXT: call void @llvm.objc.copyWeak(i8** [[SLOT]], i8** [[VAR]])
// CHECK: call void @test7_helper(
- // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}})
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** {{%.*}})
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[VAR]])
// CHECK: ret void
// CHECK-LABEL: define internal void @__test7_block_invoke
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* {{%.*}}, i32 0, i32 5
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[SLOT]])
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[SLOT]])
// CHECK-NEXT: call void @test7_consume(i8* [[T0]])
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK: ret void
- // CHECK-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
+ // CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32w(i8*, i8*) unnamed_addr #{{[0-9]+}} {
// CHECK: getelementptr
// CHECK-NEXT: getelementptr
- // CHECK-NEXT: call void @objc_copyWeak(
+ // CHECK-NEXT: call void @llvm.objc.copyWeak(
- // CHECK-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
+ // CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_8_32w(i8*) unnamed_addr #{{[0-9]+}} {
// CHECK: getelementptr
- // CHECK-NEXT: call void @objc_destroyWeak(
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(
}
@interface Test8 @end
@@ -302,7 +303,7 @@ void test7(void) {
// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK: call void @test8_helper(
// CHECK-NEXT: [[T2:%.*]] = load [[TEST8]]*, [[TEST8]]** [[D0]]
-// CHECK-NEXT: call void (...) @clang.arc.use([[TEST8]]* [[T2]])
+// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use([[TEST8]]* [[T2]])
// CHECK: ret void
extern void test8_helper(void (^)(void));
@@ -322,11 +323,11 @@ id test9(void) {
// CHECK: load i8*, i8** getelementptr
// CHECK-NEXT: bitcast i8*
// CHECK-NEXT: call i8*
-// CHECK-NEXT: tail call i8* @objc_autoreleaseReturnValue
+// CHECK-NEXT: tail call i8* @llvm.objc.autoreleaseReturnValue
// CHECK-NEXT: ret i8*
// CHECK: call i8* @test9_produce()
-// CHECK-NEXT: call i8* @objc_retain
+// CHECK-NEXT: call i8* @llvm.objc.retain
// CHECK-NEXT: ret i8*
}
@@ -344,7 +345,7 @@ void test10a(void) {
// Run the initializer as an assignment.
// CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
// CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
@@ -352,7 +353,7 @@ void test10a(void) {
// CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
// CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
// CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T7]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T7]])
// Destroy at end of function.
// CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 6
@@ -360,7 +361,7 @@ void test10a(void) {
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
// CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
// CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
// CHECK: ret void
}
@@ -378,7 +379,7 @@ void test10a(void) {
// CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[S1]], i32 0, i32 6
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[S2]], align 8
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
// CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8
// CHECK: ret void
@@ -389,7 +390,7 @@ void test10a(void) {
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T1]], i32 0, i32 6
// CHECK-NEXT: [[T3:%.*]] = load void ()*, void ()** [[T2]]
// CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T4]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T4]])
// CHECK-NEXT: ret void
// Test that we correctly assign to __block variables when the
@@ -409,7 +410,7 @@ void test10b(void) {
// The assignment.
// CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[BYREF]], i32 0, i32 1
// CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]*, [[BYREF_T]]** [[T3]]
@@ -417,14 +418,14 @@ void test10b(void) {
// CHECK-NEXT: [[T6:%.*]] = load void ()*, void ()** [[T5]], align 8
// CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
// CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T7]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T7]])
// Destroy at end of function.
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
// CHECK-NEXT: [[T1:%.*]] = load void ()*, void ()** [[SLOT]]
// CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
// CHECK: ret void
}
@@ -439,12 +440,12 @@ void test11a(void) {
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
// CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
// CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
// CHECK-NEXT: call void @test11_helper(i8* [[T4]])
// CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]])
// CHECK: ret void
}
void test11b(void) {
@@ -457,12 +458,12 @@ void test11b(void) {
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
// CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
// CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8
// CHECK-NEXT: [[T5:%.*]] = load i8*, i8** [[B]]
- // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]])
// CHECK: ret void
}
@@ -499,7 +500,7 @@ void test13(id x) {
// CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8
// CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
// CHECK-NEXT: [[BPTR1:%.*]] = bitcast void ()** [[B]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[BPTR1]])
@@ -512,7 +513,7 @@ void test13(id x) {
// CHECK-NOT: br
// CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[CAPTURE]], align 8
// CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
@@ -520,25 +521,25 @@ void test13(id x) {
// CHECK: br label
// CHECK: [[T0:%.*]] = phi void ()*
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
// CHECK-NEXT: store void ()* [[T3]], void ()** [[B]], align 8
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]], align 8
// CHECK-NEXT: call void @test13_use(void ()* [[T0]])
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]]
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]]
// CHECK-NEXT: br i1 [[T0]]
// CHECK: [[T0:%.*]] = load i8*, i8** [[CLEANUP_ADDR]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: br label
// CHECK: [[BPTR2:%.*]] = bitcast void ()** [[B]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[BPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: ret void
}
@@ -585,7 +586,7 @@ id (^test17(id self, int which))(void) {
// CHECK-NEXT: [[SELF:%.*]] = alloca i8*,
// CHECK: [[B0:%.*]] = alloca [[BLOCK:<.*>]], align
// CHECK: [[B1:%.*]] = alloca [[BLOCK]], align
-// CHECK: [[T0:%.*]] = call i8* @objc_retain(i8*
+// CHECK: [[T0:%.*]] = call i8* @llvm.objc.retain(i8*
// CHECK-NEXT: store i8* [[T0]], i8** [[SELF]], align
// CHECK-NOT: objc_retain
// CHECK-NOT: objc_release
@@ -594,15 +595,15 @@ id (^test17(id self, int which))(void) {
// CHECK-NOT: objc_release
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B0]], i32 0, i32 5
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[SELF]], align
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: store i8* [[T2]], i8** [[T0]],
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B0]] to i8* ()*
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()*
// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[DESTROY]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: store i32
// CHECK-NEXT: br label
// CHECK-NOT: objc_retain
@@ -612,15 +613,15 @@ id (^test17(id self, int which))(void) {
// CHECK-NOT: objc_release
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]], [[BLOCK]]* [[B1]], i32 0, i32 5
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[SELF]], align
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: store i8* [[T2]], i8** [[T0]],
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B1]] to i8* ()*
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()*
// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[DESTROY]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: store i32
// CHECK-NEXT: br label
@@ -629,38 +630,21 @@ void test18(id x) {
// CHECK-UNOPT: [[X:%.*]] = alloca i8*,
// CHECK-UNOPT-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-UNOPT-NEXT: store i8* null, i8** [[X]]
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]],
+// CHECK-UNOPT-NEXT: call void @llvm.objc.storeStrong(i8** [[X]],
// CHECK-UNOPT-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-UNOPT: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 4
+// CHECK-UNOPT: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i64 }* @[[BLOCK_DESCRIPTOR_TMP44]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
// CHECK-UNOPT: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8*, i8** [[X]],
-// CHECK-UNOPT-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-UNOPT-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-UNOPT-NEXT: store i8* [[T1]], i8** [[SLOT]],
// CHECK-UNOPT-NEXT: bitcast
// CHECK-UNOPT-NEXT: call void @test18_helper(
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[SLOTREL]], i8* null) [[NUW:#[0-9]+]]
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) [[NUW]]
+// CHECK-UNOPT-NEXT: call void @llvm.objc.storeStrong(i8** [[SLOTREL]], i8* null) [[NUW:#[0-9]+]]
+// CHECK-UNOPT-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null) [[NUW]]
// CHECK-UNOPT-NEXT: ret void
extern void test18_helper(id (^)(void));
test18_helper(^{ return x; });
-
-// CHECK-UNOPT-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
-// CHECK-UNOPT: [[T0:%.*]] = load i8*, i8**
-// CHECK-UNOPT-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
-// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8*, i8**
-// CHECK-UNOPT-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
-// CHECK-UNOPT-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[SRC]], i32 0, i32 5
-// CHECK-UNOPT-NEXT: [[T1:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[DST]], i32 0, i32 5
-// CHECK-UNOPT-NEXT: [[T2:%.*]] = load i8*, i8** [[T0]]
-// CHECK-UNOPT-NEXT: store i8* null, i8** [[T1]]
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) [[NUW]]
-// CHECK-UNOPT-NEXT: ret void
-
-// CHECK-UNOPT-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} {
-// CHECK-UNOPT: [[T0:%.*]] = load i8*, i8**
-// CHECK-UNOPT-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
-// CHECK-UNOPT-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[T1]], i32 0, i32 5
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null)
-// CHECK-UNOPT-NEXT: ret void
}
// Ensure that we don't emit helper code in copy/dispose routines for variables
@@ -670,33 +654,12 @@ void testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers(id x, id y) {
(^ { testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers(x, unsafeObject); })();
}
-// CHECK-LABEL: testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers_block_invoke
-// CHECK-UNOPT-LABEL: testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers_block_invoke
+// CHECK-LABEL: define void @testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers
+// %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>* %{{.*}}, i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESCRIPTOR_TMP46]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
-// CHECK-UNOPT: @__copy_helper_block
-// CHECK-UNOPT: alloca
-// CHECK-UNOPT-NEXT: alloca
-// CHECK-UNOPT-NEXT: store
-// CHECK-UNOPT-NEXT: store
-// CHECK-UNOPT-NEXT: load
-// CHECK-UNOPT-NEXT: bitcast
-// CHECK-UNOPT-NEXT: load
-// CHECK-UNOPT-NEXT: bitcast
-// CHECK-UNOPT-NEXT: getelementptr
-// CHECK-UNOPT-NEXT: getelementptr
-// CHECK-UNOPT-NEXT: load
-// CHECK-UNOPT-NEXT: store
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong
-// CHECK-UNOPT-NEXT: ret
-
-// CHECK-UNOPT: @__destroy_helper_block
-// CHECK-UNOPT: alloca
-// CHECK-UNOPT-NEXT: store
-// CHECK-UNOPT-NEXT: load
-// CHECK-UNOPT-NEXT: bitcast
-// CHECK-UNOPT-NEXT: getelementptr
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong
-// CHECK-UNOPT-NEXT: ret
+// CHECK-LABEL: define internal void @__testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers_block_invoke
+// CHECK-UNOPT-LABEL: define internal void @__testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers_block_invoke
// rdar://13588325
void test19_sink(void (^)(int));
@@ -706,16 +669,18 @@ void test19(void (^b)(void)) {
// CHECK: [[B:%.*]] = alloca void ()*,
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
// CHECK-NEXT: store void ()* [[T2]], void ()** [[B]]
// Block setup. We skip most of this. Note the bare retain.
// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i64 }* @[[BLOCK_DESCRIPTOR_TMP48]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]],
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
// CHECK-NEXT: store void ()* [[T3]], void ()** [[SLOT]],
// Call.
@@ -727,12 +692,12 @@ void test19(void (^b)(void)) {
// Block teardown.
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[SLOTREL]]
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// Local cleanup.
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]]
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: ret void
}
@@ -740,16 +705,16 @@ void test19(void (^b)(void)) {
// CHECK-LABEL: define void @test20(
// CHECK: [[XADDR:%.*]] = alloca i8*
// CHECK-NEXT: [[BLOCK:%.*]] = alloca <[[BLOCKTY:.*]]>
-// CHECK-NEXT: [[RETAINEDX:%.*]] = call i8* @objc_retain(i8* %{{.*}})
+// CHECK-NEXT: [[RETAINEDX:%.*]] = call i8* @llvm.objc.retain(i8* %{{.*}})
// CHECK-NEXT: store i8* [[RETAINEDX]], i8** [[XADDR]]
// CHECK-NEXT: [[CAPTUREFIELD:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5
// CHECK: [[BLOCKCAPTURED:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5
// CHECK: [[CAPTURED:%.*]] = load i8*, i8** [[XADDR]]
// CHECK: store i8* [[CAPTURED]], i8** [[BLOCKCAPTURED]]
// CHECK: [[CAPTURE:%.*]] = load i8*, i8** [[CAPTUREFIELD]]
-// CHECK-NEXT: call void (...) @clang.arc.use(i8* [[CAPTURE]])
+// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[CAPTURE]])
// CHECK-NEXT: [[X:%.*]] = load i8*, i8** [[XADDR]]
-// CHECK-NEXT: call void @objc_release(i8* [[X]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[X]])
// CHECK-NEXT: ret void
// CHECK-UNOPT-LABEL: define void @test20(
@@ -758,15 +723,9 @@ void test19(void (^b)(void)) {
// CHECK-UNOPT: [[CAPTUREFIELD:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5
// CHECK-UNOPT: [[BLOCKCAPTURED:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5
// CHECK-UNOPT: [[CAPTURED:%.*]] = load i8*, i8** [[XADDR]]
-// CHECK-UNOPT: [[RETAINED:%.*]] = call i8* @objc_retain(i8* [[CAPTURED]])
+// CHECK-UNOPT: [[RETAINED:%.*]] = call i8* @llvm.objc.retain(i8* [[CAPTURED]])
// CHECK-UNOPT: store i8* [[RETAINED]], i8** [[BLOCKCAPTURED]]
-// CHECK-UNOPT: call void @objc_storeStrong(i8** [[CAPTUREFIELD]], i8* null)
-
-// CHECK-LABEL: define internal void @__copy_helper_block
-// CHECK: [[BLOCKSOURCE:%.*]] = bitcast i8* %{{.*}} to <[[BLOCKTY]]>*
-// CHECK: [[CAPTUREFIELD:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCKSOURCE]], i32 0, i32 5
-// CHECK: [[BLOCKCOPYSRC:%.*]] = load i8*, i8** [[CAPTUREFIELD]]
-// CHECK: call i8* @objc_retain(i8* [[BLOCKCOPYSRC]])
+// CHECK-UNOPT: call void @llvm.objc.storeStrong(i8** [[CAPTUREFIELD]], i8* null)
void test20_callee(void (^)());
void test20(const id x) {
diff --git a/test/CodeGenObjC/arc-bridged-cast.m b/test/CodeGenObjC/arc-bridged-cast.m
index 42795d5d8009..db018944964e 100644
--- a/test/CodeGenObjC/arc-bridged-cast.m
+++ b/test/CodeGenObjC/arc-bridged-cast.m
@@ -27,10 +27,10 @@ void bridge_transfer_from_cf(int *i) {
// CHECK-NOT: retain
// CHECK: store i32 13
(void)(__bridge_transfer id)CFCreateSomething(), *i = 13;
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: store i32 17
*i = 17;
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
@@ -42,7 +42,7 @@ void bridge_from_cf(int *i) {
*i = 7;
// CHECK: call i8* @CFCreateSomething()
id obj1 = (__bridge id)CFCreateSomething();
- // CHECK: objc_retainAutoreleasedReturnValue
+ // CHECK: llvm.objc.retainAutoreleasedReturnValue
// CHECK: store i32 11
*i = 11;
// CHECK: call i8* @CFCreateSomething()
@@ -51,7 +51,7 @@ void bridge_from_cf(int *i) {
(void)(__bridge id)CFCreateSomething(), *i = 13;
// CHECK: store i32 17
*i = 17;
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
@@ -62,12 +62,12 @@ void bridge_retained_of_cf(int *i) {
*i = 7;
// CHECK: call i8* @CreateSomething()
CFTypeRef cf1 = (__bridge_retained CFTypeRef)CreateSomething();
- // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
// CHECK: store i32 11
*i = 11;
// CHECK: call i8* @CreateSomething()
(__bridge_retained CFTypeRef)CreateSomething(), *i = 13;
- // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
// CHECK: store i32 13
// CHECK: store i32 17
*i = 17;
@@ -99,8 +99,8 @@ void bridge_of_cf(int *i) {
// CHECK-LABEL: define %struct.__CFString* @bridge_of_paren_expr()
CFStringRef bridge_of_paren_expr() {
- // CHECK-NOT: call i8* @objc_retainAutoreleasedReturnValue(
- // CHECK-NOT: call void @objc_release(
+ // CHECK-NOT: call i8* @llvm.objc.retainAutoreleasedReturnValue(
+ // CHECK-NOT: call void @llvm.objc.release(
CFStringRef r = (__bridge CFStringRef)(CreateNSString());
r = (__bridge CFStringRef)((NSString *)(CreateNSString()));
return r;
diff --git a/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m b/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m
index 10feda938d08..e944e35ed107 100644
--- a/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m
+++ b/test/CodeGenObjC/arc-captured-32bit-block-var-layout-2.m
@@ -30,7 +30,8 @@ int main() {
void (^block4)() = ^{ printf("%c %#lx", ch, fourByte); NSLog(@"%@", strong); };
// Test5
- // CHECK: Inline block variable layout: 0x0100, BL_STRONG:1, BL_OPERATOR:0
+ // Nothing gets printed here since the descriptor of this block is merged with
+ // the descriptor of Test3's block.
void (^block5)() = ^{ NSLog(@"%@", strong); printf("%c %#llx", ch, eightByte); };
// Test6
diff --git a/test/CodeGenObjC/arc-exceptions.m b/test/CodeGenObjC/arc-exceptions.m
index dafffd81f506..b8fb47057ee1 100644
--- a/test/CodeGenObjC/arc-exceptions.m
+++ b/test/CodeGenObjC/arc-exceptions.m
@@ -17,11 +17,11 @@ void test0(void) {
// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch(
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW:#[0-9]+]]
+// CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retain(i8* [[T2]]) [[NUW:#[0-9]+]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null) [[NUW]]
// CHECK-NEXT: call void @objc_end_catch() [[NUW]]
void test1_helper(void);
@@ -38,9 +38,9 @@ void test1(void) {
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[T0]]) [[NUW]]
// CHECK-NEXT: call void @objc_end_catch() [[NUW]]
// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m
index ffeb37247b1b..c8c7120bae7a 100644
--- a/test/CodeGenObjC/arc-foreach.m
+++ b/test/CodeGenObjC/arc-foreach.m
@@ -38,7 +38,7 @@ void test0(NSArray *array) {
// CHECK-LP64-NEXT: store [[ARRAY_T]]* null, [[ARRAY_T]]** [[ARRAY]]
// CHECK-LP64-NEXT: [[ZERO:%.*]] = bitcast [[ARRAY_T]]** [[ARRAY]] to i8**
// CHECK-LP64-NEXT: [[ONE:%.*]] = bitcast [[ARRAY_T]]* {{%.*}} to i8*
-// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[ZERO]], i8* [[ONE]]) [[NUW:#[0-9]+]]
+// CHECK-LP64-NEXT: call void @llvm.objc.storeStrong(i8** [[ZERO]], i8* [[ONE]]) [[NUW:#[0-9]+]]
// Initialize the fast enumaration state.
// CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[STATE_T]]* [[STATE]] to i8*
@@ -47,7 +47,7 @@ void test0(NSArray *array) {
// Evaluate the collection expression and retain.
// CHECK-LP64-NEXT: [[T0:%.*]] = load [[ARRAY_T]]*, [[ARRAY_T]]** [[ARRAY]], align 8
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8*
-// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-LP64-NEXT: [[SAVED_ARRAY:%.*]] = bitcast i8* [[T2]] to [[ARRAY_T]]*
// Call the enumeration method.
@@ -68,16 +68,16 @@ void test0(NSArray *array) {
// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
-// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]]
// CHECK-LP64-NEXT: [[BLOCK1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]]
// CHECK-LP64-NEXT: call void @use_block(void ()* [[BLOCK1]])
-// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[D0]], i8* null)
-// CHECK-LP64-NOT: call void (...) @clang.arc.use(i8* [[CAPTURE]])
+// CHECK-LP64-NEXT: call void @llvm.objc.storeStrong(i8** [[D0]], i8* null)
+// CHECK-LP64-NOT: call void (...) @llvm.objc.clang.arc.use(i8* [[CAPTURE]])
// CHECK-LP64-OPT: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i64 0, i32 5
// CHECK-LP64-OPT: [[CAPTURE:%.*]] = load i8*, i8** [[D0]]
-// CHECK-LP64-OPT: call void (...) @clang.arc.use(i8* [[CAPTURE]])
+// CHECK-LP64-OPT: call void (...) @llvm.objc.clang.arc.use(i8* [[CAPTURE]])
// CHECK-LP64: [[T0:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8*
@@ -85,11 +85,11 @@ void test0(NSArray *array) {
// Release the array.
// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8*
-// CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-LP64-NEXT: call void @llvm.objc.release(i8* [[T0]])
// Destroy 'array'.
// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]** [[ARRAY]] to i8**
-// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-LP64-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK-LP64-NEXT: ret void
// CHECK-LP64-LABEL: define internal void @__test0_block_invoke
@@ -116,15 +116,15 @@ void test1(NSArray *array) {
// CHECK-LP64-NEXT: [[T1:%.*]] = load i8**, i8*** [[T0]]
// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr i8*, i8** [[T1]], i64
// CHECK-LP64-NEXT: [[T3:%.*]] = load i8*, i8** [[T2]]
-// CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T3]])
+// CHECK-LP64-NEXT: call i8* @llvm.objc.initWeak(i8** [[X]], i8* [[T3]])
// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
-// CHECK-LP64-NEXT: call void @objc_copyWeak(i8** [[T0]], i8** [[X]])
+// CHECK-LP64-NEXT: call void @llvm.objc.copyWeak(i8** [[T0]], i8** [[X]])
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK-LP64: call void @use_block
-// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[D0]])
-// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[X]])
+// CHECK-LP64-NEXT: call void @llvm.objc.destroyWeak(i8** [[D0]])
+// CHECK-LP64-NEXT: call void @llvm.objc.destroyWeak(i8** [[X]])
// rdar://problem/9817306
@interface Test2
@@ -139,7 +139,7 @@ void test2(Test2 *a) {
// CHECK-LP64-LABEL: define void @test2(
// CHECK-LP64: [[T0:%.*]] = call [[ARRAY_T]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[ARRAY_T]]* (i8*, i8*)*)(
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8*
-// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-LP64-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[ARRAY_T]]*
// Make sure it's not immediately released before starting the iteration.
@@ -157,7 +157,7 @@ void test2(Test2 *a) {
// This bitcast is for the final release.
// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]* [[COLL]] to i8*
-// CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-LP64-NEXT: call void @llvm.objc.release(i8* [[T0]])
// Check that the 'continue' label is positioned appropriately
@@ -211,7 +211,7 @@ NSArray *array4;
// CHECK-LP64: [[BC:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[T1:%.*]] = load [[TY]]*, [[TY]]** [[SELF_ADDR]]
// CHECK-LP64: [[T2:%.*]] = bitcast [[TY]]* [[T1]] to i8*
-// CHECK-LP64: call i8* @objc_retain(i8* [[T2]])
+// CHECK-LP64: call i8* @llvm.objc.retain(i8* [[T2]])
// CHECK-LP64-OPT-LABEL: define internal void @"\01-[I1 foo2]"(
// CHECK-LP64-OPT: [[TY:%.*]]* %self
@@ -219,15 +219,15 @@ NSArray *array4;
// CHECK-LP64-OPT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i64 0, i32 5
// CHECK-LP64: [[T5:%.*]] = bitcast [[TY]]** [[T0]] to i8**
-// CHECK-LP64: call void @objc_storeStrong(i8** [[T5]], i8* null)
-// CHECK-LP64-NOT: call void (...) @clang.arc.use([[TY]]* [[T5]])
+// CHECK-LP64: call void @llvm.objc.storeStrong(i8** [[T5]], i8* null)
+// CHECK-LP64-NOT: call void (...) @llvm.objc.clang.arc.use([[TY]]* [[T5]])
// CHECK-LP64: switch i32 {{%.*}}, label %[[UNREACHABLE:.*]] [
// CHECK-LP64-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
// CHECK-LP64-NEXT: i32 2, label %[[FORCOLL_END:.*]]
// CHECK-LP64-NEXT: ]
// CHECK-LP64-OPT: [[T5:%.*]] = load [[TY]]*, [[TY]]** [[T0]]
-// CHECK-LP64-OPT: call void (...) @clang.arc.use([[TY]]* [[T5]])
+// CHECK-LP64-OPT: call void (...) @llvm.objc.clang.arc.use([[TY]]* [[T5]])
// CHECK-LP64: {{^|:}}[[CLEANUP_CONT]]
// CHECK-LP64-NEXT: br label %[[FORCOLL_END]]
diff --git a/test/CodeGenObjC/arc-i386.m b/test/CodeGenObjC/arc-i386.m
index 7693a8f2b6ff..66b6ea85017e 100644
--- a/test/CodeGenObjC/arc-i386.m
+++ b/test/CodeGenObjC/arc-i386.m
@@ -16,9 +16,9 @@ void test1(void) {
extern id test1_helper(void);
// CHECK: [[T0:%.*]] = call i8* @test1_helper()
// CHECK-NEXT: call void asm sideeffect "mov
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]],
- // CHECK-NEXT: call void @objc_storeStrong(
+ // CHECK-NEXT: call void @llvm.objc.storeStrong(
// CHECK-NEXT: ret void
id x = test1_helper();
}
diff --git a/test/CodeGenObjC/arc-linetable-autorelease.m b/test/CodeGenObjC/arc-linetable-autorelease.m
index 6812e8a6de83..0804b0700a08 100644
--- a/test/CodeGenObjC/arc-linetable-autorelease.m
+++ b/test/CodeGenObjC/arc-linetable-autorelease.m
@@ -29,8 +29,8 @@ NSRect NSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h);
CGFloat pattern[2];
// CHECK: define {{.*}}_createBezierPathWithWidth
// CHECK: load {{.*}} %path, align {{.*}}, !dbg ![[RET:[0-9]+]]
- // CHECK: call void @objc_storeStrong{{.*}} !dbg ![[ARC:[0-9]+]]
- // CHECK: call {{.*}} @objc_autoreleaseReturnValue{{.*}} !dbg ![[ARC]]
+ // CHECK: call void @llvm.objc.storeStrong{{.*}} !dbg ![[ARC:[0-9]+]]
+ // CHECK: call {{.*}} @llvm.objc.autoreleaseReturnValue{{.*}} !dbg ![[ARC]]
// CHECK: ret {{.*}} !dbg ![[ARC]]
// CHECK: ![[RET]] = !DILocation(line: [[@LINE+1]], scope: !{{.*}})
return path;
diff --git a/test/CodeGenObjC/arc-linetable.m b/test/CodeGenObjC/arc-linetable.m
index 877dfdc12211..3883e0a3a93f 100644
--- a/test/CodeGenObjC/arc-linetable.m
+++ b/test/CodeGenObjC/arc-linetable.m
@@ -3,8 +3,8 @@
// Legend: EXP = Return expression, RET = ret instruction
// CHECK: define {{.*}}testNoSideEffect
-// CHECK: call void @objc_storeStrong{{.*}}
-// CHECK: call void @objc_storeStrong{{.*}} !dbg ![[RET1:[0-9]+]]
+// CHECK: call void @llvm.objc.storeStrong{{.*}}
+// CHECK: call void @llvm.objc.storeStrong{{.*}} !dbg ![[RET1:[0-9]+]]
// CHECK: ret {{.*}} !dbg ![[RET1]]
// CHECK: define {{.*}}testNoCleanup
@@ -20,8 +20,8 @@
// CHECK: ret {{.*}} !dbg ![[RET4:[0-9]+]]
// CHECK: define {{.*}}testVoid
-// CHECK: call void @objc_storeStrong{{.*}}
-// CHECK: call void @objc_storeStrong{{.*}} !dbg ![[RET5:[0-9]+]]
+// CHECK: call void @llvm.objc.storeStrong{{.*}}
+// CHECK: call void @llvm.objc.storeStrong{{.*}} !dbg ![[RET5:[0-9]+]]
// CHECK: ret {{.*}} !dbg ![[RET5]]
// CHECK: define {{.*}}testVoidNoReturn
@@ -35,7 +35,7 @@
// CHECK: define {{.*}}testCleanupVoid
// CHECK: icmp ne {{.*}}!dbg ![[SKIP1:[0-9]+]]
// CHECK: store i32 0, i32* {{.*}}, !dbg ![[RET8:[0-9]+]]
-// CHECK: @objc_storeStrong{{.*}}, !dbg ![[RET8]]
+// CHECK: @llvm.objc.storeStrong{{.*}}, !dbg ![[RET8]]
// CHECK: ret {{.*}} !dbg ![[RET8]]
typedef signed char BOOL;
@@ -56,7 +56,7 @@ typedef signed char BOOL;
// CHECK: ![[TESTNOSIDEEFFECT:.*]] = distinct !DISubprogram(name: "-[AppDelegate testNoSideEffect:]"
// CHECK-SAME: line: [[@LINE+2]]
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
- (int)testNoSideEffect:(NSString *)foo {
int x = 1;
return 1; // Return expression
diff --git a/test/CodeGenObjC/arc-literals.m b/test/CodeGenObjC/arc-literals.m
index 74e231c765bf..a9cb7691380d 100644
--- a/test/CodeGenObjC/arc-literals.m
+++ b/test/CodeGenObjC/arc-literals.m
@@ -15,24 +15,24 @@
// CHECK-LABEL: define void @test_numeric()
void test_numeric() {
// CHECK: {{call.*objc_msgSend.*i32 17}}
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
id ilit = @17;
// CHECK: {{call.*objc_msgSend.*i32 25}}
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
id ulit = @25u;
// CHECK: {{call.*objc_msgSend.*i64 42}}
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
id ulllit = @42ull;
// CHECK: {{call.*objc_msgSend.*i8 signext 97}}
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
id charlit = @'a';
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}
@@ -43,8 +43,8 @@ void test_array(id a, id b) {
// CHECK: [[B:%.*]] = alloca i8*,
// Retaining parameters
- // CHECK: call i8* @objc_retain(i8*
- // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @llvm.objc.retain(i8*
+ // CHECK: call i8* @llvm.objc.retain(i8*
// Constructing the array
// CHECK: [[T0:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i64 0, i64 0
@@ -59,13 +59,13 @@ void test_array(id a, id b) {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8**
// CHECK-NEXT: [[T3:%.*]] = call i8* bitcast ({{.*@objc_msgSend.*}})(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i64 2)
- // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]])
- // CHECK: call void (...) @clang.arc.use(i8* [[V0]], i8* [[V1]])
+ // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T3]])
+ // CHECK: call void (...) @llvm.objc.clang.arc.use(i8* [[V0]], i8* [[V1]])
id arr = @[a, b];
- // CHECK: call void @objc_release
- // CHECK: call void @objc_release
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
+ // CHECK: call void @llvm.objc.release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: ret void
}
@@ -77,10 +77,10 @@ void test_dictionary(id k1, id o1, id k2, id o2) {
// CHECK: [[O2:%.*]] = alloca i8*,
// Retaining parameters
- // CHECK: call i8* @objc_retain(i8*
- // CHECK: call i8* @objc_retain(i8*
- // CHECK: call i8* @objc_retain(i8*
- // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @llvm.objc.retain(i8*
+ // CHECK: call i8* @llvm.objc.retain(i8*
+ // CHECK: call i8* @llvm.objc.retain(i8*
+ // CHECK: call i8* @llvm.objc.retain(i8*
// Constructing the arrays
// CHECK: [[T0:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[KEYS:%[A-Za-z0-9]+]], i64 0, i64 0
@@ -103,16 +103,16 @@ void test_dictionary(id k1, id o1, id k2, id o2) {
// CHECK-NEXT: [[T2:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [2 x i8*]* [[KEYS]] to i8**
// CHECK-NEXT: [[T4:%.*]] = call i8* bitcast ({{.*@objc_msgSend.*}})(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i8** [[T3]], i64 2)
- // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]])
- // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[V0]], i8* [[V1]], i8* [[V2]], i8* [[V3]])
+ // CHECK-NEXT: [[T5:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T4]])
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[V0]], i8* [[V1]], i8* [[V2]], i8* [[V3]])
id dict = @{ k1 : o1, k2 : o2 };
- // CHECK: call void @objc_release
- // CHECK: call void @objc_release
- // CHECK: call void @objc_release
- // CHECK: call void @objc_release
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
+ // CHECK: call void @llvm.objc.release
+ // CHECK: call void @llvm.objc.release
+ // CHECK: call void @llvm.objc.release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: ret void
}
@@ -126,7 +126,7 @@ void test_dictionary(id k1, id o1, id k2, id o2) {
// CHECK-LABEL: define void @test_property
void test_property(B *b) {
// Retain parameter
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
// CHECK: [[T0:%.*]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[OBJECTS:%.*]], i64 0, i64 0
@@ -135,7 +135,7 @@ void test_property(B *b) {
// CHECK-NEXT: [[T1:%.*]] = bitcast
// CHECK-NEXT: [[T2:%.*]] = call [[B:%.*]]* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]])
// CHECK-NEXT: [[T3:%.*]] = bitcast [[B]]* [[T2]] to i8*
- // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]])
+ // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T3]])
// CHECK-NEXT: [[V0:%.*]] = bitcast i8* [[T4]] to [[B]]*
// CHECK-NEXT: [[V1:%.*]] = bitcast [[B]]* [[V0]] to i8*
@@ -148,8 +148,8 @@ void test_property(B *b) {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast [1 x i8*]* [[OBJECTS]] to i8**
// CHECK-NEXT: [[T3:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}}(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i64 1)
- // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]])
- // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[V1]])
+ // CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T3]])
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[V1]])
// CHECK-NEXT: bitcast
// CHECK-NEXT: bitcast
// CHECK-NEXT: store
@@ -157,12 +157,12 @@ void test_property(B *b) {
// Release b.prop
// CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[V0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// Destroy arr
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// Destroy b
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenObjC/arc-loadweakretained-release.m b/test/CodeGenObjC/arc-loadweakretained-release.m
index 5392abdf8c5f..a35ee0187c67 100644
--- a/test/CodeGenObjC/arc-loadweakretained-release.m
+++ b/test/CodeGenObjC/arc-loadweakretained-release.m
@@ -28,13 +28,13 @@ int main (int argc, const char * argv[]) {
}
}
-// CHECK: [[SIXTEEN:%.*]] = call i8* @objc_loadWeakRetained(i8** {{%.*}})
+// CHECK: [[SIXTEEN:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** {{%.*}})
// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast i8* [[SIXTEEN]] to {{%.*}}
// CHECK-NEXT: [[EIGHTEEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.6
// CHECK-NEXT: [[NINETEEN:%.*]] = bitcast %0* [[SEVENTEEN]] to i8*
// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
// CHECK-NEXT: [[TWENTY:%.*]] = bitcast %0* [[SEVENTEEN]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[TWENTY]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[TWENTY]])
void test1(int cond) {
extern void test34_sink(id *);
@@ -55,7 +55,7 @@ void test1(int cond) {
// CHECK-NEXT: [[ICRARGUMENT:%.*]] = select i1 [[ICRISNULL]], i8** null, i8** [[INCRTEMP]]
// CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]]
// CHECK-NEXT: br i1 [[ICRISNULL]], label [[ICRCONT:%.*]], label [[ICRCOPY:%.*]]
-// CHECK: [[ONE:%.*]] = call i8* @objc_loadWeakRetained(
+// CHECK: [[ONE:%.*]] = call i8* @llvm.objc.loadWeakRetained(
// CHECK-NEXT: store i8* [[ONE]], i8** [[CONDCLEANUPSAVE]]
// CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]]
// CHECK-NEXT: store i8* [[ONE]], i8** [[INCRTEMP]]
@@ -65,13 +65,13 @@ void test1(int cond) {
// CHECK-NEXT: [[ICRISNULL1:%.*]] = icmp eq i8** [[COND1]], null
// CHECK-NEXT: br i1 [[ICRISNULL1]], label [[ICRDONE:%.*]], label [[ICRWRITEBACK:%.*]]
// CHECK: [[TWO:%.*]] = load i8*, i8** [[INCRTEMP]]
-// CHECK-NEXT: [[THREE:%.*]] = call i8* @objc_storeWeak(
+// CHECK-NEXT: [[THREE:%.*]] = call i8* @llvm.objc.storeWeak(
// CHECK-NEXT: br label [[ICRDONE]]
// CHECK: [[CLEANUPISACTIVE:%.*]] = load i1, i1* [[CONDCLEANUP]]
// CHECK-NEXT: br i1 [[CLEANUPISACTIVE]], label [[CLEASNUPACTION:%.*]], label [[CLEANUPDONE:%.*]]
// CHECK: [[FOUR:%.*]] = load i8*, i8** [[CONDCLEANUPSAVE]]
-// CHECK-NEXT: call void @objc_release(i8* [[FOUR]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[FOUR]])
// CHECK-NEXT: br label
-// CHECK: call void @objc_destroyWeak(i8** [[WEAK]])
+// CHECK: call void @llvm.objc.destroyWeak(i8** [[WEAK]])
// CHECK-NEXT: ret void
diff --git a/test/CodeGenObjC/arc-no-arc-exceptions.m b/test/CodeGenObjC/arc-no-arc-exceptions.m
index 3338ad8477bc..31d1dd537635 100644
--- a/test/CodeGenObjC/arc-no-arc-exceptions.m
+++ b/test/CodeGenObjC/arc-no-arc-exceptions.m
@@ -42,6 +42,7 @@ void NSLog(id, ...);
void test2(void) {
@autoreleasepool {
__attribute__((__blocks__(byref))) int x;
+ ^{ (void)x; };
NSLog(@"Address of x outside of block: %p", &x);
}
}
diff --git a/test/CodeGenObjC/arc-no-runtime.m b/test/CodeGenObjC/arc-no-runtime.m
index f5f5b90ea52b..31f0ed8714ce 100644
--- a/test/CodeGenObjC/arc-no-runtime.m
+++ b/test/CodeGenObjC/arc-no-runtime.m
@@ -5,9 +5,9 @@ id make(void) __attribute__((ns_returns_retained));
void test0() {
make();
id x = 0;
- // CHECK: call void @objc_release(
- // CHECK: call void @objc_storeStrong(
+ // CHECK: call void @llvm.objc.release(
+ // CHECK: call void @llvm.objc.storeStrong(
}
-// CHECK: declare extern_weak void @objc_release(
-// CHECK: declare extern_weak void @objc_storeStrong(
+// CHECK: declare extern_weak void @llvm.objc.release(
+// CHECK: declare extern_weak void @llvm.objc.storeStrong(
diff --git a/test/CodeGenObjC/arc-precise-lifetime.m b/test/CodeGenObjC/arc-precise-lifetime.m
index a366c08bbbf6..4c563c5b8448 100644
--- a/test/CodeGenObjC/arc-precise-lifetime.m
+++ b/test/CodeGenObjC/arc-precise-lifetime.m
@@ -14,11 +14,11 @@ void test0() {
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* null, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW:#[0-9]+]]
// CHECK-NOT: clang.imprecise_release
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW:#[0-9]+]]
// CHECK-NOT: clang.imprecise_release
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
@@ -43,14 +43,14 @@ void test1a_message(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
@@ -60,7 +60,7 @@ void test1a_message(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
@@ -77,14 +77,14 @@ void test1a_property(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
@@ -94,7 +94,7 @@ void test1a_property(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
@@ -111,7 +111,7 @@ void test1b_message(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
@@ -125,7 +125,7 @@ void test1b_message(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]]
// CHECK-NOT: clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
@@ -142,7 +142,7 @@ void test1b_property(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
@@ -156,7 +156,7 @@ void test1b_property(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]]
// CHECK-NOT: clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
@@ -173,14 +173,14 @@ void test1c_message(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
@@ -190,7 +190,7 @@ void test1c_message(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
@@ -206,14 +206,14 @@ void test1c_property(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
@@ -223,7 +223,7 @@ void test1c_property(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
@@ -239,7 +239,7 @@ void test1d_message(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
@@ -253,7 +253,7 @@ void test1d_message(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[TEN]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TEN]])
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
@@ -269,7 +269,7 @@ void test1d_property(void) {
// CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
@@ -283,7 +283,7 @@ void test1d_property(void) {
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[TEN]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TEN]])
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
@@ -301,7 +301,7 @@ void test2(Test2 *x) {
x->ivar = 0;
// CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]*
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8*
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]]
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]*
// CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]],
@@ -312,12 +312,12 @@ void test2(Test2 *x) {
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8**
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]],
// CHECK-NEXT: store i8* null, i8** [[T3]],
- // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T4]]) [[NUW]]
// CHECK-NOT: imprecise
// CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]*, [[TEST2]]** [[X]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: ret void
}
@@ -325,11 +325,11 @@ void test2(Test2 *x) {
// CHECK-LABEL: define void @test3(i8*
void test3(PRECISE_LIFETIME id x) {
// CHECK: [[X:%.*]] = alloca i8*,
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) [[NUW]]
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}}) [[NUW]]
// CHECK-NEXT: store i8* [[T0]], i8** [[X]],
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]]
// CHECK-NOT: imprecise_release
// CHECK-NEXT: ret void
diff --git a/test/CodeGenObjC/arc-property.m b/test/CodeGenObjC/arc-property.m
index edc4d1e85383..b417f9505e12 100644
--- a/test/CodeGenObjC/arc-property.m
+++ b/test/CodeGenObjC/arc-property.m
@@ -8,11 +8,11 @@ void test0(Test0 *t0, id value) {
t0.value = value;
}
// CHECK-LABEL: define void @test0(
-// CHECK: call void @objc_storeStrong
-// CHECK: call void @objc_storeStrong
+// CHECK: call void @llvm.objc.storeStrong
+// CHECK: call void @llvm.objc.storeStrong
// CHECK: @objc_msgSend
-// CHECK: call void @objc_storeStrong(
-// CHECK: call void @objc_storeStrong(
+// CHECK: call void @llvm.objc.storeStrong(
+// CHECK: call void @llvm.objc.storeStrong(
struct S1 { Class isa; };
@interface Test1
@@ -62,7 +62,7 @@ static Class theGlobalClass;
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST2]]* [[T1]] to i8*
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[OFFSET]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T4]], i8* [[T0]]) [[NUW:#[0-9]+]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T4]], i8* [[T0]]) [[NUW:#[0-9]+]]
// CHECK-NEXT: ret void
// CHECK: define internal i8* @"\01-[Test2 theClass]"(
@@ -83,7 +83,7 @@ static Class theGlobalClass;
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, i8* [[T1]], i64 [[OFFSET]]
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T3]], i8* null) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T3]], i8* null) [[NUW]]
// CHECK-NEXT: ret void
// rdar://13115896
@@ -112,11 +112,11 @@ void test3(Test3 *t) {
// CHECK-NEXT: [[T2:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]])
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[X]],
// CHECK-NEXT: store i8* [[T2]], i8** [[X]],
-// CHECK-NEXT: call void @objc_release(i8* [[T3]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T3]])
// Epilogue.
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST3]]** [[T]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK-NEXT: ret void
@implementation Test3
@@ -126,7 +126,7 @@ void test3(Test3 *t) {
}
// CHECK: define internal i8* @"\01-[Test3 copyMachine]"(
// CHECK: [[T0:%.*]] = call i8* @test3_helper()
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: ret i8* [[T1]]
- (void) setCopyMachine: (id) x {}
@end
diff --git a/test/CodeGenObjC/arc-related-result-type.m b/test/CodeGenObjC/arc-related-result-type.m
index 02d380368b00..ac69e0d9f646 100644
--- a/test/CodeGenObjC/arc-related-result-type.m
+++ b/test/CodeGenObjC/arc-related-result-type.m
@@ -12,17 +12,17 @@ void test0(Test0 *val) {
// CHECK-NEXT: store [[TEST0]]* null
// CHECK-NEXT: bitcast
// CHECK-NEXT: bitcast
-// CHECK-NEXT: call void @objc_storeStrong(
+// CHECK-NEXT: call void @llvm.objc.storeStrong(
// CHECK-NEXT: load [[TEST0]]*, [[TEST0]]** [[VAL]],
// CHECK-NEXT: load
// CHECK-NEXT: bitcast
// CHECK-NEXT: [[T0:%.*]] = call i8* bitcast (
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]*
// CHECK-NEXT: store [[TEST0]]* [[T2]], [[TEST0]]** [[X]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]** [[X]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]** [[VAL]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenObjC/arc-ternary-op.m b/test/CodeGenObjC/arc-ternary-op.m
index 3488d2c5387a..2be046284641 100644
--- a/test/CodeGenObjC/arc-ternary-op.m
+++ b/test/CodeGenObjC/arc-ternary-op.m
@@ -22,15 +22,15 @@ void test0(_Bool cond) {
// CHECK-NEXT: store i1 true, i1* [[RELCOND]]
// CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = phi i8* [ null, {{%.*}} ], [ [[CALL]], {{%.*}} ]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW:#[0-9]+]]
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) [[NUW:#[0-9]+]]
// CHECK-NEXT: store i8* [[T1]], i8** [[X]],
// CHECK-NEXT: [[REL:%.*]] = load i1, i1* [[RELCOND]]
// CHECK-NEXT: br i1 [[REL]],
// CHECK: [[T0:%.*]] = load i8*, i8** [[RELVAL]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -58,7 +58,7 @@ void test1(int cond) {
// CHECK-NEXT: store i8* null, i8** [[STRONG]]
// CHECK-NEXT: [[WEAKPTR1:%.*]] = bitcast i8** [[WEAK]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[WEAKPTR1]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)
+ // CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[WEAK]], i8* null)
// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
// CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0
@@ -74,11 +74,11 @@ void test1(int cond) {
// CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
// CHECK-NEXT: br i1 [[T0]],
// CHECK: [[T0:%.*]] = load i8*, i8** [[TEMP1]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
- // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[W]]) [[NUW]]
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[W]]) [[NUW]]
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[ARG]]
// CHECK-NEXT: store i8* [[T1]], i8** [[ARG]]
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
// CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = load i32, i32* [[COND]]
@@ -88,7 +88,7 @@ void test1(int cond) {
// CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]]
// CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]]
// CHECK-NEXT: br i1 [[T0]],
- // CHECK: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[ARG]])
+ // CHECK: [[T0:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[ARG]])
// CHECK-NEXT: store i8* [[T0]], i8** [[CONDCLEANUPSAVE]]
// CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]]
// CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]]
@@ -97,10 +97,10 @@ void test1(int cond) {
// CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
// CHECK-NEXT: br i1 [[T0]],
// CHECK: [[T0:%.*]] = load i8*, i8** [[TEMP2]]
- // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]])
+ // CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[ARG]], i8* [[T0]])
// CHECK-NEXT: br label
- // CHECK: call void @objc_destroyWeak(i8** [[WEAK]])
+ // CHECK: call void @llvm.objc.destroyWeak(i8** [[WEAK]])
// CHECK: [[WEAKPTR2:%.*]] = bitcast i8** [[WEAK]] to i8*
// CHECK: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[WEAKPTR2]])
// CHECK: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*
@@ -130,21 +130,21 @@ void test2(int cond) {
// CHECK-NEXT: br i1
// Within true branch, cleanup enabled.
// CHECK: [[T0:%.*]] = call i8* @test2_producer()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[CLEANUP_SAVE]]
// CHECK-NEXT: store i1 true, i1* [[RUN_CLEANUP]]
// CHECK-NEXT: br label
// Join point for conditional operator; retain immediately.
// CHECK: [[T0:%.*]] = phi i8* [ [[T1]], {{%.*}} ], [ null, {{%.*}} ]
- // CHECK-NEXT: [[RESULT:%.*]] = call i8* @objc_retain(i8* [[T0]])
+ // CHECK-NEXT: [[RESULT:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// Leaving full-expression; run conditional cleanup.
// CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[RUN_CLEANUP]]
// CHECK-NEXT: br i1 [[T0]]
// CHECK: [[T0:%.*]] = load i8*, i8** [[CLEANUP_SAVE]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: br label
// And way down at the end of the loop:
- // CHECK: call void @objc_release(i8* [[RESULT]])
+ // CHECK: call void @llvm.objc.release(i8* [[RESULT]])
}
// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenObjC/arc-unbridged-cast.m b/test/CodeGenObjC/arc-unbridged-cast.m
index 5ab5d02fffee..72b7b01bb7ed 100644
--- a/test/CodeGenObjC/arc-unbridged-cast.m
+++ b/test/CodeGenObjC/arc-unbridged-cast.m
@@ -32,4 +32,4 @@ id MMM()
return 0;
}
-// CHECK-NOT: call i8* @objc_retainAutoreleasedReturnValue
+// CHECK-NOT: call i8* @llvm.objc.retainAutoreleasedReturnValue
diff --git a/test/CodeGenObjC/arc-unopt.m b/test/CodeGenObjC/arc-unopt.m
index f80514d6e4b5..4354cb61c44c 100644
--- a/test/CodeGenObjC/arc-unopt.m
+++ b/test/CodeGenObjC/arc-unopt.m
@@ -9,7 +9,7 @@ Test0 *test0(void) {
// CHECK: [[LD:%.*]] = load [[TEST0:%.*]]*, [[TEST0:%.*]]** @test0_helper
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]* [[LD]] to i8*
- // CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_retainAutoreleaseReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = tail call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]*
// CHECK-NEXT: ret [[TEST0]]* [[T2]]
}
@@ -19,14 +19,14 @@ id test1(void) {
return test1_helper;
// CHECK: [[LD:%.*]] = load i8*, i8** @test1_helper
- // CHECK-NEXT: [[T0:%.*]] = tail call i8* @objc_retainAutoreleaseReturnValue(i8* [[LD]])
+ // CHECK-NEXT: [[T0:%.*]] = tail call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* [[LD]])
// CHECK-NEXT: ret i8* [[T0]]
}
void test2(void) {
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: store i8* null, i8** [[X]]
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[X]])
// CHECK-NEXT: ret void
__weak id x;
}
@@ -63,7 +63,7 @@ void test5(void) {
// CHECK-NEXT: [[T0:%.*]] = load [[TEST5]]*, [[TEST5]]** [[Y]],
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST5]]** [[X]] to i8**
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST5]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]])
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T1]], i8* [[T2]])
// CHECK-NEXT: [[T3:%.*]] = icmp ne [[TEST5]]* [[T0]], null
// CHECK-NEXT: br i1 [[T3]],
}
diff --git a/test/CodeGenObjC/arc-unoptimized-byref-var.m b/test/CodeGenObjC/arc-unoptimized-byref-var.m
index 9d856d659afe..bd57335d6e55 100644
--- a/test/CodeGenObjC/arc-unoptimized-byref-var.m
+++ b/test/CodeGenObjC/arc-unoptimized-byref-var.m
@@ -3,13 +3,14 @@
void test19() {
__block id x;
+ ^{ (void)x; };
// CHECK-UNOPT-LABEL: define internal void @__Block_byref_object_copy
// CHECK-UNOPT: [[X:%.*]] = getelementptr inbounds [[BYREF_T:%.*]], [[BYREF_T:%.*]]* [[VAR:%.*]], i32 0, i32 6
// CHECK-UNOPT: [[X2:%.*]] = getelementptr inbounds [[BYREF_T:%.*]], [[BYREF_T:%.*]]* [[VAR1:%.*]], i32 0, i32 6
// CHECK-UNOPT-NEXT: [[SIX:%.*]] = load i8*, i8** [[X2]], align 8
// CHECK-UNOPT-NEXT: store i8* null, i8** [[X]], align 8
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* [[SIX]]) [[NUW:#[0-9]+]]
-// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X2]], i8* null) [[NUW]]
+// CHECK-UNOPT-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* [[SIX]]) [[NUW:#[0-9]+]]
+// CHECK-UNOPT-NEXT: call void @llvm.objc.storeStrong(i8** [[X2]], i8* null) [[NUW]]
// CHECK-UNOPT-NEXT: ret void
}
diff --git a/test/CodeGenObjC/arc-unsafeclaim.m b/test/CodeGenObjC/arc-unsafeclaim.m
index 01329df0f791..fd063bfccf9a 100644
--- a/test/CodeGenObjC/arc-unsafeclaim.m
+++ b/test/CodeGenObjC/arc-unsafeclaim.m
@@ -29,7 +29,7 @@ void test_assign() {
// CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[X]]
@@ -41,7 +41,7 @@ void test_assign() {
// DISABLED: [[T0:%.*]] = call [[A:.*]]* @makeA()
// DISABLED-MARKED-NEXT: call void asm sideeffect
// DISABLED-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// DISABLED-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// DISABLED-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
void test_assign_assign() {
__unsafe_unretained id x, y;
@@ -53,7 +53,7 @@ void test_assign_assign() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
@@ -75,18 +75,18 @@ void test_strong_assign_assign() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* [[T4]], i8** [[X]]
-// CHECK-NEXT: call void @objc_release(i8* [[OLD]]
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]]
// CHECK-OPTIMIZED-NEXT: bitcast
// CHECK-OPTIMIZED-NEXT: lifetime.end
-// CHECK-UNOPTIMIZED-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
-// CHECK-OPTIMIZED-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-OPTIMIZED-NEXT: bitcast
// CHECK-OPTIMIZED-NEXT: lifetime.end
// CHECK-NEXT: ret void
@@ -102,16 +102,16 @@ void test_assign_strong_assign() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[Y]]
// CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
-// CHECK-NEXT: call void @objc_release(i8* [[OLD]]
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]]
// CHECK-NEXT: store i8* [[T4]], i8** [[X]]
-// CHECK-UNOPTIMIZED-NEXT: call void @objc_storeStrong(i8** [[Y]], i8* null)
+// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[Y]], i8* null)
// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
-// CHECK-OPTIMIZED-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-OPTIMIZED-NEXT: bitcast
// CHECK-OPTIMIZED-NEXT: lifetime.end
// CHECK-OPTIMIZED-NEXT: bitcast
@@ -126,7 +126,7 @@ void test_init() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[X]]
@@ -144,7 +144,7 @@ void test_init_assignment() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[X]]
@@ -165,14 +165,14 @@ void test_strong_init_assignment() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[X]]
// CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
-// CHECK-UNOPTIMIZED-NEXT: call void @objc_storeStrong(i8** [[Y]], i8* null)
+// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[Y]], i8* null)
// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
-// CHECK-OPTIMIZED-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-OPTIMIZED-NEXT: bitcast
// CHECK-OPTIMIZED-NEXT: lifetime.end
// CHECK-OPTIMIZED-NEXT: bitcast
@@ -189,18 +189,18 @@ void test_init_strong_assignment() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8*
// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* [[T4]], i8** [[X]]
-// CHECK-NEXT: call void @objc_release(i8* [[OLD]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]])
// CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
// CHECK-OPTIMIZED-NEXT: bitcast
// CHECK-OPTIMIZED-NEXT: lifetime.end
-// CHECK-UNOPTIMIZED-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
-// CHECK-OPTIMIZED-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-OPTIMIZED-NEXT: bitcast
// CHECK-OPTIMIZED-NEXT: lifetime.end
// CHECK-NEXT: ret void
@@ -212,7 +212,7 @@ void test_ignored() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: ret void
@@ -223,7 +223,7 @@ void test_cast_to_void() {
// CHECK: [[T0:%.*]] = call [[A]]* @makeA()
// CHECK-MARKED-NEXT: call void asm sideeffect
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: bitcast i8* [[T2]] to [[A]]*
// CHECK-NEXT: ret void
diff --git a/test/CodeGenObjC/arc-weak-property.m b/test/CodeGenObjC/arc-weak-property.m
index d04032bc0d46..8b50a0c2090c 100644
--- a/test/CodeGenObjC/arc-weak-property.m
+++ b/test/CodeGenObjC/arc-weak-property.m
@@ -21,8 +21,8 @@
// CHECK-NEXT: [[T2:%.*]] = bitcast [[WPT]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[T1]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
-// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T4]])
-// CHECK-NEXT: [[T6:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T5]])
+// CHECK-NEXT: [[T5:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T4]])
+// CHECK-NEXT: [[T6:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T5]])
// CHECK-NEXT: ret i8* [[T6]]
// CHECK: define internal void @"\01-[WeakPropertyTest setPROP:]"
@@ -38,7 +38,7 @@
// CHECK-NEXT: [[T2:%.*]] = bitcast [[WPT]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[T1]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
-// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[T4]], i8* [[V]])
+// CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[T4]], i8* [[V]])
// CHECK-NEXT: ret void
// CHECK: define internal void @"\01-[WeakPropertyTest .cxx_destruct]"
@@ -51,5 +51,5 @@
// CHECK-NEXT: [[T2:%.*]] = bitcast [[WPT]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[T1]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T4]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[T4]])
// CHECK-NEXT: ret void
diff --git a/test/CodeGenObjC/arc-weak.m b/test/CodeGenObjC/arc-weak.m
index 59f8d1d69300..a976402f54a9 100644
--- a/test/CodeGenObjC/arc-weak.m
+++ b/test/CodeGenObjC/arc-weak.m
@@ -15,6 +15,6 @@ void test0(__weak B **src) {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]**
// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8**
-// CHECK-NEXT: call void @objc_copyWeak(i8** [[T2]], i8** [[T3]])
+// CHECK-NEXT: call void @llvm.objc.copyWeak(i8** [[T2]], i8** [[T3]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8**
-// CHECK: call void @objc_destroyWeak(i8** [[T0]])
+// CHECK: call void @llvm.objc.destroyWeak(i8** [[T0]])
diff --git a/test/CodeGenObjC/arc-with-atthrow.m b/test/CodeGenObjC/arc-with-atthrow.m
index e5295159ce5e..93fa228c8b06 100644
--- a/test/CodeGenObjC/arc-with-atthrow.m
+++ b/test/CodeGenObjC/arc-with-atthrow.m
@@ -11,8 +11,8 @@ void test() {
// CHECK-LABEL: define void @test()
// CHECK: [[T0:%.*]] = call i8* @make()
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_autorelease(i8* [[T1]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.autorelease(i8* [[T1]])
// CHECK-NEXT: call void @objc_exception_throw(i8* [[T2]]) [[NR:#[0-9]+]]
// CHECK-NEXT: unreachable
diff --git a/test/CodeGenObjC/arc.ll b/test/CodeGenObjC/arc.ll
index caafcff05246..f23c656c3498 100644
--- a/test/CodeGenObjC/arc.ll
+++ b/test/CodeGenObjC/arc.ll
@@ -2,8 +2,8 @@
target triple = "x86_64-apple-darwin10"
-declare i8* @objc_retain(i8*)
-declare void @objc_release(i8*)
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.release(i8*)
; CHECK-LABEL: define void @test(
; CHECK-NOT: @objc_
@@ -13,15 +13,15 @@ entry:
br label %loop
loop:
- call i8* @objc_retain(i8* %x)
+ call i8* @llvm.objc.retain(i8* %x)
%q = load i1, i1* %p
br i1 %q, label %loop.more, label %exit
loop.more:
- call void @objc_release(i8* %x)
+ call void @llvm.objc.release(i8* %x)
br label %loop
exit:
- call void @objc_release(i8* %x)
+ call void @llvm.objc.release(i8* %x)
ret void
}
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index 3243952a36b3..cbdb03205a66 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -6,39 +6,39 @@
// RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s
// RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s
-// ARC-ALIEN: declare extern_weak void @objc_storeStrong(i8**, i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8*)
+// ARC-ALIEN: declare extern_weak void @llvm.objc.storeStrong(i8**, i8*)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.retain(i8*)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.autoreleaseReturnValue(i8*)
// ARC-ALIEN: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]]
-// ARC-ALIEN: declare extern_weak void @objc_release(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_initWeak(i8**, i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_storeWeak(i8**, i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_loadWeakRetained(i8**)
-// ARC-ALIEN: declare extern_weak void @objc_destroyWeak(i8**)
-// ARC-ALIEN: declare extern_weak i8* @objc_autorelease(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8*)
-
-// ARC-NATIVE: declare void @objc_storeStrong(i8**, i8*)
-// ARC-NATIVE: declare i8* @objc_retain(i8*) [[NLB:#[0-9]+]]
-// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8*)
-// ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB]]
-// ARC-NATIVE: declare void @objc_release(i8*) [[NLB]]
-// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8*)
-// ARC-NATIVE: declare i8* @objc_initWeak(i8**, i8*)
-// ARC-NATIVE: declare i8* @objc_storeWeak(i8**, i8*)
-// ARC-NATIVE: declare i8* @objc_loadWeakRetained(i8**)
-// ARC-NATIVE: declare void @objc_destroyWeak(i8**)
-// ARC-NATIVE: declare i8* @objc_autorelease(i8*)
-// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8*)
+// ARC-ALIEN: declare extern_weak void @llvm.objc.release(i8*)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.initWeak(i8**, i8*)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.storeWeak(i8**, i8*)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.loadWeakRetained(i8**)
+// ARC-ALIEN: declare extern_weak void @llvm.objc.destroyWeak(i8**)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.autorelease(i8*)
+// ARC-ALIEN: declare extern_weak i8* @llvm.objc.retainAutorelease(i8*)
+
+// ARC-NATIVE: declare void @llvm.objc.storeStrong(i8**, i8*)
+// ARC-NATIVE: declare i8* @llvm.objc.retain(i8*)
+// ARC-NATIVE: declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+// ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]]
+// ARC-NATIVE: declare void @llvm.objc.release(i8*)
+// ARC-NATIVE: declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+// ARC-NATIVE: declare i8* @llvm.objc.initWeak(i8**, i8*)
+// ARC-NATIVE: declare i8* @llvm.objc.storeWeak(i8**, i8*)
+// ARC-NATIVE: declare i8* @llvm.objc.loadWeakRetained(i8**)
+// ARC-NATIVE: declare void @llvm.objc.destroyWeak(i8**)
+// ARC-NATIVE: declare i8* @llvm.objc.autorelease(i8*)
+// ARC-NATIVE: declare i8* @llvm.objc.retainAutorelease(i8*)
// CHECK-LABEL: define void @test0
void test0(id x) {
// CHECK: [[X:%.*]] = alloca i8*
- // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{.*}})
+ // CHECK-NEXT: [[PARM:%.*]] = call i8* @llvm.objc.retain(i8* {{.*}})
// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
// CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[TMP]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]])
// CHECK-NEXT: ret void
}
@@ -46,20 +46,20 @@ void test0(id x) {
id test1(id x) {
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[Y:%.*]] = alloca i8*
- // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+ // CHECK-NEXT: [[PARM:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: store i8* null, i8** [[Y]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
- // CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T0]])
+ // CHECK-NEXT: [[RET:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
- // CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RET]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
+ // CHECK-NEXT: [[T1:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[RET]])
// CHECK-NEXT: ret i8* [[T1]]
id y;
return y;
@@ -113,19 +113,19 @@ void test3_unelided() {
// CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
// CHECK-NEXT: bitcast
// CHECK-NEXT: bitcast
- // CHECK-NEXT: call void @objc_release(i8*
+ // CHECK-NEXT: call void @llvm.objc.release(i8*
[Test3 alloc];
// CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]*, [[TEST3]]** [[X]]
// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8*
// CHECK-NEXT: [[COPY:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend {{.*}})(i8* [[T1]],
- // CHECK-NEXT: call void @objc_release(i8* [[COPY]]) [[NUW:#[0-9]+]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[COPY]]) [[NUW:#[0-9]+]]
[x copy];
// CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]*, [[TEST3]]** [[X]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST3]]** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -163,13 +163,13 @@ void test3() {
// Assignment to x.
// CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* [[COPY]], i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]]
x = [x copy];
// Cleanup for x.
// CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -193,7 +193,7 @@ id test4() {
// Retain/release elided.
// CHECK-NEXT: bitcast
// CHECK-NEXT: [[INIT:%.*]] = bitcast
- // CHECK-NEXT: [[RET:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[INIT]])
+ // CHECK-NEXT: [[RET:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[INIT]])
// CHECK-NEXT: ret i8* [[RET]]
@@ -212,10 +212,10 @@ void test5(Test5 *x, id y) {
// CHECK: [[X:%.*]] = alloca [[TEST5:%.*]]*,
// CHECK-NEXT: [[Y:%.*]] = alloca i8*
// CHECK-NEXT: bitcast [[TEST5]]* {{%.*}} to i8*
- // CHECK-NEXT: call i8* @objc_retain
+ // CHECK-NEXT: call i8* @llvm.objc.retain
// CHECK-NEXT: [[PARMX:%.*]] = bitcast i8* {{%.*}} to [[TEST5]]*
// CHECK-NEXT: store [[TEST5]]* [[PARMX]], [[TEST5]]** [[X]]
- // CHECK-NEXT: call i8* @objc_retain
+ // CHECK-NEXT: call i8* @llvm.objc.retain
// CHECK-NEXT: store
// CHECK-NEXT: load [[TEST5]]*, [[TEST5]]** [[X]]
@@ -225,7 +225,7 @@ void test5(Test5 *x, id y) {
// CHECK-NEXT: [[VAR:%.*]] = bitcast
// CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[VAR]]
// CHECK-NEXT: store i8* null, i8** [[VAR]]
- // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]]
x->var = 0;
// CHECK-NEXT: [[YVAL:%.*]] = load i8*, i8** [[Y]]
@@ -234,18 +234,18 @@ void test5(Test5 *x, id y) {
// CHECK-NEXT: bitcast
// CHECK-NEXT: getelementptr
// CHECK-NEXT: [[VAR:%.*]] = bitcast
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[YVAL]]) [[NUW]]
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[YVAL]]) [[NUW]]
// CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[VAR]]
// CHECK-NEXT: store i8* [[T0]], i8** [[VAR]]
- // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]]
x->var = y;
// Epilogue.
// CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[Y]]
- // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[TMP]]) [[NUW]]
// CHECK-NEXT: [[T0:%.*]] = load [[TEST5]]*, [[TEST5]]** [[X]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST5]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]]
// CHECK-NEXT: ret void
}
@@ -258,7 +258,7 @@ void test6() {
// CHECK-NEXT: [[CALL:%.*]] = call i8* @test6_helper()
// CHECK-NEXT: store i8* [[CALL]], i8** [[X]]
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -273,10 +273,10 @@ void test7() {
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]])
// CHECK-NEXT: store i8* null, i8** [[X]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]]
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: call void @test7_helper(i8* [[T1]])
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -292,7 +292,7 @@ void test8() {
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test8_helper()
// CHECK-NEXT: store i8* [[T0]], i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -318,25 +318,25 @@ void test10() {
// CHECK-NEXT: bitcast
// CHECK-NEXT: [[T0:%.*]] = call [[TEST10]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[V:%.*]] = bitcast i8* [[T2]] to [[TEST10]]*
// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}
// CHECK-NEXT: bitcast
// CHECK-NEXT: [[T0:%.*]] = call [[TEST10]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST10]]*
// CHECK-NEXT: [[T4:%.*]] = bitcast [[TEST10]]* [[T3]] to i8*
// CHECK-NEXT: store i8* [[T4]], i8** [[Y]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST10]]* [[V]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST10]]*, [[TEST10]]** [[X]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST10]]** [[X]] to i8*
// CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -353,7 +353,7 @@ void test11(id (*f)(void) __attribute__((ns_returns_retained))) {
// CHECK-NEXT: [[T1:%.*]] = call i8* [[T0]]()
// CHECK-NEXT: store i8* [[T1]], i8** [[X]], align
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T3]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T3]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -371,27 +371,27 @@ void test12(void) {
// CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T1]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[X]], i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
x = test12_helper();
// CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[X]], i8* [[T1]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[X]], i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
id y = x;
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[X]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[X]])
// CHECK-NEXT: store i8* [[T2]], i8** [[Y]], align
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[Y]]
- // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T4]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[X]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK: ret void
@@ -410,7 +410,7 @@ void test13(void) {
extern fnty *test13_func;
// CHECK-NEXT: [[FN:%.*]] = load void (i8*)*, void (i8*)** @test13_func, align
// CHECK-NEXT: [[X_VAL:%.*]] = load i8*, i8** [[X]], align
- // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) [[NUW]]
+ // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @llvm.objc.retain(i8* [[X_VAL]]) [[NUW]]
// CHECK-NEXT: call void [[FN]](i8* [[X_TMP]])
test13_func(x);
@@ -420,14 +420,14 @@ void test13(void) {
// CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds [[BLOCKTY]], [[BLOCKTY]]* [[BLOCK]], i32 0, i32 3
// CHECK-NEXT: [[BLOCK_OPAQUE:%.*]] = bitcast [[BLOCKTY]]* [[BLOCK]] to i8*
// CHECK-NEXT: [[X_VAL:%.*]] = load i8*, i8** [[X]], align
- // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) [[NUW]]
+ // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @llvm.objc.retain(i8* [[X_VAL]]) [[NUW]]
// CHECK-NEXT: [[BLOCK_FN_TMP:%.*]] = load i8*, i8** [[BLOCK_FN_PTR]]
// CHECK-NEXT: [[BLOCK_FN:%.*]] = bitcast i8* [[BLOCK_FN_TMP]] to void (i8*, i8*)*
// CHECK-NEXT: call void [[BLOCK_FN]](i8* [[BLOCK_OPAQUE]], i8* [[X_TMP]])
test13_block(x);
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -479,14 +479,14 @@ void test13(void) {
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8*
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[Y_OFF]]
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8**
- // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T2]], i8* null) [[NUW]]
// Destroy z.
// CHECK-NEXT: [[Z_OFF:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test16.z"
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8*
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[Z_OFF]]
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8**
- // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T2]], i8* null) [[NUW]]
// CHECK-NEXT: ret void
@@ -514,11 +514,11 @@ void test19() {
x[2] = test19_helper();
// CHECK-NEXT: [[CALL:%.*]] = call i8* @test19_helper()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]]) [[NUW]]
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]]) [[NUW]]
// CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[X]], i64 0, i64 2
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]]
// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[X]], i32 0, i32 0
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8*, i8** [[BEGIN]], i64 5
@@ -527,7 +527,7 @@ void test19() {
// CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
// CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK-NEXT: br i1 [[EQ]],
@@ -570,7 +570,7 @@ void test20(unsigned n) {
// CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[VLA]]
// CHECK-NEXT: br i1 [[EQ]],
@@ -620,7 +620,7 @@ void test21(unsigned n) {
// CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK-NEXT: br i1 [[EQ]],
@@ -656,7 +656,7 @@ void test21(unsigned n) {
// CHECK-NEXT: br label
// CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8*, i8** [[PAST]], i64 -1
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[CUR]], i8* null)
// CHECK-NEXT: [[ISDONE:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK-NEXT: br i1 [[ISDONE]],
// CHECK: ret void
@@ -674,12 +674,12 @@ void test21(unsigned n) {
// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]]
// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]*, [[TEST27]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST27]]*
// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST27]]* [[T3]] to i8*
// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]*, [[TEST27]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: ret i8* [[RET]]
@end
@@ -697,7 +697,7 @@ void test21(unsigned n) {
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST28]]* [[SELF]] to i8*
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]]
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T2]], i8* null)
// CHECK-NEXT: ret void
@interface Test29_super
@@ -738,14 +738,14 @@ static id _test29_allocator = 0;
// Return statement.
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[CALL]]
// CHECK-NEXT: [[CALL:%.*]] = bitcast
-// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[CALL]]) [[NUW]]
+// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[CALL]]) [[NUW]]
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]*
// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8*
// Cleanup.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// Return.
// CHECK-NEXT: ret i8* [[RET]]
@@ -759,7 +759,7 @@ static id _test29_allocator = 0;
// CHECK-NEXT: alloca
// CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]]
// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]]
-// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[T0]], i8** [[ALLOCATOR]]
// Evaluate arguments. Note that the send argument is evaluated
@@ -782,27 +782,27 @@ static id _test29_allocator = 0;
// Assignment.
// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]*
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) [[NUW]]
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST29]]*
// CHECK-NEXT: [[T4:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]], align
// CHECK-NEXT: store [[TEST29]]* [[T3]], [[TEST29]]** [[SELF]], align
// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST29]]* [[T4]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T5]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]])
// Return statement.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8*
-// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]
+// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]]) [[NUW]]
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]*
// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8*
// Cleanup.
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[ALLOCATOR]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]*, [[TEST29]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// Return.
// CHECK-NEXT: ret i8* [[RET]]
@@ -840,21 +840,21 @@ char *helper;
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[IVAR]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
// CHECK-NEXT#: [[T5:%.*]] = load i8*, i8** [[T4]]
-// CHECK-NEXT#: [[T6:%.*]] = call i8* @objc_retain(i8* [[T0]])
-// CHECK-NEXT#: call void @objc_release(i8* [[T5]])
+// CHECK-NEXT#: [[T6:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
+// CHECK-NEXT#: call void @llvm.objc.release(i8* [[T5]])
// CHECK-NEXT: store i8* [[T0]], i8** [[T4]]
// Return.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]*, [[TEST30]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8*
-// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST30]]*
// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST30]]* [[T1]] to i8*
// Cleanup.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]*, [[TEST30]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// Epilogue.
// CHECK-NEXT: ret i8* [[RET]]
@@ -876,7 +876,7 @@ char *helper;
__attribute__((ns_returns_retained)) id test32(void) {
// CHECK-LABEL: define i8* @test32()
// CHECK: [[CALL:%.*]] = call i8* @test32_helper()
-// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]])
+// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]])
// CHECK-NEXT: ret i8* [[T0]]
extern id test32_helper(void);
return test32_helper();
@@ -905,7 +905,7 @@ void test33(Test33 *ptr) {
// CHECK-NEXT: [[TEMP1:%.*]] = alloca [[A_T]]*
// CHECK-NEXT: [[TEMP2:%.*]] = alloca [[A_T]]*
// CHECK-NEXT: bitcast
- // CHECK-NEXT: objc_retain
+ // CHECK-NEXT: llvm.objc.retain
// CHECK-NEXT: bitcast
// CHECK-NEXT: store
// CHECK-NEXT: bitcast
@@ -920,13 +920,13 @@ void test33(Test33 *ptr) {
// CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP0]])
// CHECK-NEXT: [[T0:%.*]] = load [[A_T]]*, [[A_T]]** [[TEMP0]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]*
- // CHECK-NEXT: call void (...) @clang.arc.use([[A_T]]* [[W0]]) [[NUW]]
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use([[A_T]]* [[W0]]) [[NUW]]
// CHECK-NEXT: [[T4:%.*]] = load [[A_T]]*, [[A_T]]** [[A]]
// CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]]
// CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]])
// CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]]
// CHECK-NEXT: [[W0:%.*]] = load [[A_T]]*, [[A_T]]** [[A]]
@@ -936,13 +936,13 @@ void test33(Test33 *ptr) {
// CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP1]])
// CHECK-NEXT: [[T0:%.*]] = load [[A_T]]*, [[A_T]]** [[TEMP1]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]*
- // CHECK-NEXT: call void (...) @clang.arc.use([[A_T]]* [[W0]]) [[NUW]]
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use([[A_T]]* [[W0]]) [[NUW]]
// CHECK-NEXT: [[T4:%.*]] = load [[A_T]]*, [[A_T]]** [[A]]
// CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]]
// CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]])
// CHECK-NEXT: load [[TEST33]]*, [[TEST33]]** [[PTR]]
// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_
@@ -962,21 +962,21 @@ void test33(Test33 *ptr) {
// CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP2]])
// CHECK-NEXT: [[T0:%.*]] = load [[A_T]]*, [[A_T]]** [[TEMP2]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]*
// CHECK-NEXT: [[T4:%.*]] = load [[A_T]]*, [[A_T]]** [[A]]
// CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]]
// CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T5]])
// CHECK-NEXT: load
// CHECK-NEXT: bitcast
- // CHECK-NEXT: objc_release
+ // CHECK-NEXT: llvm.objc.release
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: load
// CHECK-NEXT: bitcast
- // CHECK-NEXT: objc_release
+ // CHECK-NEXT: llvm.objc.release
// CHECK-NEXT: ret void
}
@@ -985,21 +985,21 @@ void test33(Test33 *ptr) {
void test36(id x) {
// CHECK: [[X:%.*]] = alloca i8*
- // CHECK: call i8* @objc_retain
- // CHECK: call i8* @objc_retain
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
+ // CHECK: call i8* @llvm.objc.retain
+ // CHECK: call i8* @llvm.objc.retain
id array[3] = { @"A", x, @"y" };
// CHECK: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* null, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
x = 0;
// CHECK: br label
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: br i1
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: ret void
}
@@ -1023,17 +1023,17 @@ void test37(void) {
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]]
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST37]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST37]]* [[T1]] to i8*
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
+ // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retain(i8* [[T2]])
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST37]]*
- // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[W1]]) [[NUW]]
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[W1]]) [[NUW]]
// CHECK-NEXT: [[T5:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]]
// CHECK-NEXT: store [[TEST37]]* [[T4]], [[TEST37]]** [[VAR]]
// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST37]]* [[T5]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T6]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T6]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST37]]* [[T0]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[TEST37]]** [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[VARPTR2]])
// CHECK-NEXT: ret void
@@ -1045,7 +1045,7 @@ void test37(void) {
extern id test43_produce(void);
return test43_produce();
// CHECK: call i8* @test43_produce()
- // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue(
+ // CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue(
// CHECK-NEXT: ret
}
@end
@@ -1067,21 +1067,21 @@ void test46(__weak id *wp, __weak volatile id *wvp) {
// TODO: this is sub-optimal, we should retain at the actual call site.
// CHECK: [[T0:%.*]] = call i8* @test46_helper()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
- // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retain(i8* [[T3]])
+ // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]])
+ // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retain(i8* [[T3]])
// CHECK-NEXT: store i8* [[T4]], i8**
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
id x = *wp = test46_helper();
// CHECK: [[T0:%.*]] = call i8* @test46_helper()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
- // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retain(i8* [[T3]])
+ // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]])
+ // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retain(i8* [[T3]])
// CHECK-NEXT: store i8* [[T4]], i8**
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
id y = *wvp = test46_helper();
}
@@ -1096,16 +1096,16 @@ void test47(void) {
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]])
// CHECK-NEXT: store i8* null, i8** [[X]]
// CHECK-NEXT: [[CALL:%.*]] = call i8* @test47_helper()
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]])
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]])
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* [[T0]], i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* [[T2]], i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T3]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T3]])
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T4]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T4]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -1118,13 +1118,13 @@ void test48(void) {
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]])
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_initWeak(i8** [[X]], i8* null)
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.initWeak(i8** [[X]], i8* null)
// CHECK-NEXT: [[T1:%.*]] = call i8* @test48_helper()
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[X]], i8* [[T2]])
- // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_storeWeak(i8** [[X]], i8* [[T3]])
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[X]], i8* [[T2]])
+ // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[X]], i8* [[T3]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[X]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -1139,10 +1139,10 @@ void test49(void) {
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]])
// CHECK-NEXT: store i8* null, i8** [[X]]
// CHECK-NEXT: [[CALL:%.*]] = call i8* @test49_helper()
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]])
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_autorelease(i8* [[T0]])
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[CALL]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.autorelease(i8* [[T0]])
// CHECK-NEXT: store i8* [[T2]], i8** [[X]]
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retainAutorelease(i8* [[T1]])
// CHECK-NEXT: store i8* [[T3]], i8** [[X]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
@@ -1153,8 +1153,8 @@ void test49(void) {
id x();
void test50(id y) {
({x();});
-// CHECK: [[T0:%.*]] = call i8* @objc_retain
-// CHECK: call void @objc_release
+// CHECK: [[T0:%.*]] = call i8* @llvm.objc.retain
+// CHECK: call void @llvm.objc.release
}
@@ -1190,7 +1190,7 @@ id test52(void) {
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i32* [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[XPTR2]])
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[TMPALLOCA]]
-// CHECK-NEXT: [[T3:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T2]])
+// CHECK-NEXT: [[T3:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T2]])
// CHECK-NEXT: ret i8* [[T3]]
}
@@ -1208,20 +1208,20 @@ void test53(void) {
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test53_helper()
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]],
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]],
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[Y]]
-// CHECK-NEXT: call void @objc_release(i8* [[T2]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[TMPALLOCA]]
// CHECK-NEXT: store i8* [[T3]], i8** [[X]],
// CHECK-NEXT: load i8*, i8** [[X]],
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -1233,11 +1233,11 @@ void test54(int first, ...) {
__builtin_va_list arglist;
// CHECK: call void @llvm.va_start
__builtin_va_start(arglist, first);
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
id obj = __builtin_va_arg(arglist, id);
// CHECK: call void @llvm.va_end
__builtin_va_end(arglist);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -1261,7 +1261,7 @@ void test54(int first, ...) {
+ (id) make {
extern id test56_helper(void);
// CHECK: [[T0:%.*]] = call i8* @test56_helper()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: ret i8* [[T1]]
return test56_helper();
}
@@ -1275,7 +1275,7 @@ void test56_test(void) {
// CHECK: [[T0:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(
// CHECK-NEXT: store i8* [[T0]], i8** [[X]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -1305,8 +1305,8 @@ void test56_test(void) {
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 [[T1]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
-// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T4]])
-// CHECK-NEXT: [[T6:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T5]])
+// CHECK-NEXT: [[T5:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T4]])
+// CHECK-NEXT: [[T6:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T5]])
// CHECK-NEXT: ret i8* [[T6]]
// CHECK: define internal i8* @"\01-[Test57 unsafe]"(
@@ -1328,11 +1328,11 @@ void test59(void) {
// CHECK-LABEL: define void @test59()
// CHECK: [[T0:%.*]] = call i8* @test59_getlock()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: call i32 @objc_sync_enter(i8* [[T1]])
// CHECK-NEXT: call void @test59_body()
// CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T1]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: ret void
}
@@ -1350,27 +1350,27 @@ void test61(void) {
extern id test61_make(void);
// CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T4:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T1]], i8* [[T3]], i8* [[T2]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
[test61_make() performSelector: @selector(test61_void)];
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T4:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T1]], i8* [[T3]], i8* [[T2]])
- // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]])
+ // CHECK-NEXT: [[T5:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T4]])
// CHECK-NEXT: store i8* [[T5]], i8** [[Y]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
id y = [test61_make() performSelector: @selector(test61_id)];
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: ret void
@@ -1400,7 +1400,7 @@ void test62(void) {
// CHECK-NEXT: store i1 false, i1* [[CLEANUP_REQUIRED]]
// CHECK-NEXT: br i1 [[T1]],
// CHECK: [[T0:%.*]] = call i8* @test62_make()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[CLEANUP_VALUE]]
// CHECK-NEXT: store i1 true, i1* [[CLEANUP_REQUIRED]]
// CHECK-NEXT: [[T2:%.*]] = icmp ne i8* [[T1]], null
@@ -1409,7 +1409,7 @@ void test62(void) {
// CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_REQUIRED]]
// CHECK-NEXT: br i1 [[T0]],
// CHECK: [[T0:%.*]] = load i8*, i8** [[CLEANUP_VALUE]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: br label
// CHECK: br i1 [[COND]]
// CHECK: call void @test62_body()
@@ -1455,20 +1455,20 @@ void test66(void) {
// CHECK-LABEL: define void @test66()
// CHECK: [[T0:%.*]] = call [[TEST66:%.*]]* @test66_receiver()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST66]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST66]]*
// CHECK-NEXT: [[T4:%.*]] = call i8* @test66_arg()
-// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]])
+// CHECK-NEXT: [[T5:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T4]])
// CHECK-NEXT: [[T6:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES
// CHECK-NEXT: [[T7:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
// CHECK-NEXT: [[SIX:%.*]] = icmp eq i8* [[T7]], null
// CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label [[CALL:%.*]]
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]])
// CHECK-NEXT: br label [[CONT:%.*]]
-// CHECK: call void @objc_release(i8* [[T5]]) [[NUW]]
+// CHECK: call void @llvm.objc.release(i8* [[T5]]) [[NUW]]
// CHECK-NEXT: br label [[CONT:%.*]]
// CHECK: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T8]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T8]])
// CHECK-NEXT: ret void
// rdar://problem/9953540
@@ -1495,10 +1495,10 @@ void test68(void) {
// CHECK-NEXT: [[CLPTR1:%.*]] = bitcast i8** [[CL]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CLPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper()
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[CL]], align 8
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[CL]]
-// CHECK-NEXT: call void @objc_release(i8* [[T2]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
// CHECK-NEXT: [[CLPTR2:%.*]] = bitcast i8** [[CL]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CLPTR2]])
// CHECK-NEXT: ret void
@@ -1519,7 +1519,7 @@ void test70(id i) {
// CHECK-LABEL: define void @test70
// CHECK: store i8* null, i8**
// CHECK: store i8* null, i8**
- // CHECK: [[ID:%.*]] = call i8* @objc_retain(i8*
+ // CHECK: [[ID:%.*]] = call i8* @llvm.objc.retain(i8*
// CHECK: store i8* [[ID]], i8**
id x[3] = {
[2] = i
diff --git a/test/CodeGenObjC/autorelease.m b/test/CodeGenObjC/autorelease.m
index ab65f8088d1f..0677340eae92 100644
--- a/test/CodeGenObjC/autorelease.m
+++ b/test/CodeGenObjC/autorelease.m
@@ -25,9 +25,9 @@
}
@end
-// CHECK: call i8* @objc_autoreleasePoolPush
+// CHECK: call i8* @llvm.objc.autoreleasePoolPush
// CHECK: [[T:%.*]] = load i8*, i8** [[A:%.*]]
-// CHECK: call void @objc_autoreleasePoolPop
+// CHECK: call void @llvm.objc.autoreleasePoolPop
// rdar://13660038
int tryTo(int (*f)(void)) {
@@ -41,7 +41,7 @@ int tryTo(int (*f)(void)) {
}
// CHECK-LABEL: define i32 @tryTo(i32 ()*
// CHECK: [[RET:%.*]] = alloca i32,
-// CHECK: [[T0:%.*]] = call i8* @objc_autoreleasePoolPush()
+// CHECK: [[T0:%.*]] = call i8* @llvm.objc.autoreleasePoolPush()
// CHECK-NEXT: [[T1:%.*]] = load i32 ()*, i32 ()** {{%.*}},
// CHECK-NEXT: [[T2:%.*]] = invoke i32 [[T1]]()
// CHECK: store i32 [[T2]], i32* [[RET]]
diff --git a/test/CodeGenObjC/block-byref-debuginfo.m b/test/CodeGenObjC/block-byref-debuginfo.m
index 3ddb376dde65..a145b28bb49f 100644
--- a/test/CodeGenObjC/block-byref-debuginfo.m
+++ b/test/CodeGenObjC/block-byref-debuginfo.m
@@ -1,16 +1,35 @@
// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -debug-info-kind=limited -triple x86_64-apple-darwin -emit-llvm %s -o - | FileCheck %s
-// rdar://problem/14386148
+// CHECK: !DILocalVariable(name: "foo", {{.*}}type: ![[FOOTY:[0-9]+]])
+// CHECK: ![[FOOTY]] = {{.*}}!DICompositeType({{.*}}, name: "Foo"
+
+// CHECK-NOT: DIFlagBlockByrefStruct
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "__block_literal_1",
+// CHECK-SAME: size: 320, elements: ![[BL_ELTS:[0-9]+]])
+// CHECK: ![[BL_ELTS]] = !{{.*}}![[WFOO:[0-9]+]]}
+
// Test that the foo is aligned at an 8 byte boundary in the DWARF
// expression (256) that locates it inside of the byref descriptor:
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "foo",
-// CHECK-NOT: line:
-// CHECK-SAME: offset: 256
+// CHECK: ![[WFOO]] = !DIDerivedType(tag: DW_TAG_member, name: "foo",
+// CHECK-SAME: baseType: ![[PTR:[0-9]+]]
+// CHECK-SAME: offset: 256)
+
+// CHECK: ![[PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,
+// CHECK-SAME: baseType: ![[WRAPPER:[0-9]+]]
+// CHECK: ![[WRAPPER]] = !DICompositeType(tag: DW_TAG_structure_type, scope:
+// CHECK: elements: ![[WR_ELTS:[0-9]+]])
+// CHECK: ![[WR_ELTS]] = !{{.*}}![[WFOO:[0-9]+]]}
+// CHECK: ![[WFOO]] = !DIDerivedType(tag: DW_TAG_member, name: "foo",
+// CHECK-SAME: baseType: ![[FOOTY]]
+
+// CHECK: !DILocalVariable(name: "foo", {{.*}}type: ![[FOOTY]])
+
struct Foo {
unsigned char *data;
};
int func() {
__attribute__((__blocks__(byref))) struct Foo foo;
+ ^{ foo.data = 0; }();
return 0;
}
diff --git a/test/CodeGenObjC/block-desc-str.m b/test/CodeGenObjC/block-desc-str.m
new file mode 100644
index 000000000000..44d2f214330a
--- /dev/null
+++ b/test/CodeGenObjC/block-desc-str.m
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -emit-llvm -fobjc-runtime=gnustep-1.7 -fblocks -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fobjc-runtime=gcc -fblocks -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -fblocks -o - %s | FileCheck %s
+
+// Test that descriptor symbol names don't include '@'.
+
+// CHECK: @[[STR:.*]] = private unnamed_addr constant [6 x i8] c"v8@?0\00"
+// CHECK: @"__block_descriptor_40_8_32o_e5_v8\01?0l" = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i8*, i8*, {{.*}} } { i64 0, i64 40, i8* bitcast ({{.*}} to i8*), i8* bitcast ({{.*}} to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @[[STR]], i32 0, i32 0), {{.*}} }, align 8
+
+typedef void (^BlockTy)(void);
+
+void test(id a) {
+ BlockTy b = ^{ (void)a; };
+}
diff --git a/test/CodeGenObjC/blocks-1.m b/test/CodeGenObjC/blocks-1.m
index 0d2c35096ae4..cecb55d17a84 100644
--- a/test/CodeGenObjC/blocks-1.m
+++ b/test/CodeGenObjC/blocks-1.m
@@ -1,23 +1,31 @@
-// RUN: %clang_cc1 %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5
-// RUN: grep "_Block_object_dispose" %t | count 6
-// RUN: grep "__copy_helper_block_" %t | count 4
-// RUN: grep "__destroy_helper_block_" %t | count 4
-// RUN: grep "__Block_byref_object_copy_" %t | count 2
-// RUN: grep "__Block_byref_object_dispose_" %t | count 2
-// RUN: not grep "i32 135)" %t
-// RUN: grep "_Block_object_assign" %t | count 4
-// RUN: grep "objc_read_weak" %t | count 2
-// RUN: grep "objc_assign_weak" %t | count 3
-// RUN: %clang_cc1 -x objective-c++ %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5
-// RUN: grep "_Block_object_dispose" %t | count 6
-// RUN: grep "__copy_helper_block_" %t | count 4
-// RUN: grep "__destroy_helper_block_" %t | count 4
-// RUN: grep "__Block_byref_object_copy_" %t | count 2
-// RUN: grep "__Block_byref_object_dispose_" %t | count 2
-// RUN: not grep "i32 135)" %t
-// RUN: grep "_Block_object_assign" %t | count 4
-// RUN: grep "objc_read_weak" %t | count 2
-// RUN: grep "objc_assign_weak" %t | count 3
+// RUN: %clang_cc1 %s -emit-llvm -o - -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 | FileCheck %s --check-prefix=CHECK --check-prefix=OBJC
+// RUN: %clang_cc1 -x objective-c++ %s -emit-llvm -o - -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 | FileCheck %s --check-prefix=CHECK --check-prefix=OBJCXX
+
+// OBJC-LABEL: define void @test1(
+// OBJCXX-LABEL: define void @_Z5test1P12NSDictionary(
+
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_
+// CHECK: call void @_Block_object_assign(
+
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_
+// CHECK: call void @_Block_object_dispose(
+
+// OBJC-LABEL: define void @foo(
+// OBJCXX-LABEL: define void @_Z3foov(
+// CHECK: call i8* @objc_read_weak(
+// CHECK: call i8* @objc_assign_weak(
+// CHECK: call void @_Block_object_dispose(
+
+// OBJC-LABEL: define void @test2(
+// OBJCXX-LABEL: define void @_Z5test2v(
+// CHECK: call i8* @objc_assign_weak(
+// CHECK: call void @_Block_object_dispose(
+
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_
+// CHECK: call void @_Block_object_assign(
+
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_
+// CHECK: call void @_Block_object_dispose(
@interface NSDictionary @end
@@ -30,6 +38,7 @@ void test1(NSDictionary * dict) {
void foo() {
__block __weak D *weakSelf;
+ ^{ (void)weakSelf; };
D *l;
l = weakSelf;
weakSelf = l;
diff --git a/test/CodeGenObjC/convert-messages-to-runtime-calls.m b/test/CodeGenObjC/convert-messages-to-runtime-calls.m
new file mode 100644
index 000000000000..8ce024fe8094
--- /dev/null
+++ b/test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -0,0 +1,164 @@
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime.
+// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+
+#define nil (id)0
+
+@interface NSObject
++ (id)alloc;
++ (id)allocWithZone:(void*)zone;
++ (id)alloc2;
+- (id)retain;
+- (void)release;
+- (id)autorelease;
+@end
+
+// CHECK-LABEL: define {{.*}}void @test1
+void test1(id x) {
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_alloc}}
+ // CALLS: {{call.*@objc_allocWithZone}}
+ // CALLS: {{call.*@objc_retain}}
+ // CALLS: {{call.*@objc_release}}
+ // CALLS: {{call.*@objc_autorelease}}
+ [NSObject alloc];
+ [NSObject allocWithZone:nil];
+ [x retain];
+ [x release];
+ [x autorelease];
+}
+
+// CHECK-LABEL: define {{.*}}void @test2
+void test2(void* x) {
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ [NSObject alloc2];
+ [NSObject allocWithZone:(void*)-1];
+ [NSObject allocWithZone:x];
+}
+
+@class A;
+@interface B
++ (A*) alloc;
++ (A*) allocWithZone:(void*)zone;
+- (A*) alloc;
+- (A*) allocWithZone:(void*)zone;
+- (A*) retain;
+- (A*) autorelease;
+@end
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_alloc_class_ptr() {
+ // CALLS: {{call.*@objc_alloc}}
+ // CALLS-NEXT: bitcast i8*
+ // CALLS-NEXT: ret
+ return [B alloc];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_allocWithZone_class_ptr() {
+ // CALLS: {{call.*@objc_allocWithZone}}
+ // CALLS-NEXT: bitcast i8*
+ // CALLS-NEXT: ret
+ return [B allocWithZone:nil];
+}
+
+// Only call objc_alloc on a Class, not an instance
+// CHECK-LABEL: define {{.*}}void @test_alloc_instance
+void test_alloc_instance(A *a) {
+ // CALLS: {{call.*@objc_alloc}}
+ // CALLS: {{call.*@objc_allocWithZone}}
+ // CALLS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ [A alloc];
+ [A allocWithZone:nil];
+ [a alloc];
+ [a allocWithZone:nil];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_retain_class_ptr
+A* test_retain_class_ptr(B *b) {
+ // CALLS: {{call.*@objc_retain}}
+ // CALLS-NEXT: bitcast i8*
+ // CALLS-NEXT: ret
+ return [b retain];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_autorelease_class_ptr
+A* test_autorelease_class_ptr(B *b) {
+ // CALLS: {{call.*@objc_autorelease}}
+ // CALLS-NEXT: bitcast i8*
+ // CALLS-NEXT: ret
+ return [b autorelease];
+}
+
+
+@interface C
++ (id)allocWithZone:(int)intArg;
+- (float) retain;
+@end
+
+// Make sure we only accept pointer types
+// CHECK-LABEL: define {{.*}}void @test_allocWithZone_int
+C* test_allocWithZone_int() {
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ return [C allocWithZone:3];
+}
+
+// Make sure we use a message and not a call as the return type is
+// not a pointer type.
+// CHECK-LABEL: define {{.*}}void @test_cannot_message_return_float
+float test_cannot_message_return_float(C *c) {
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ return [c retain];
+}
+
+@interface NSString : NSObject
++ (void)retain_self;
+- (void)retain_super;
+@end
+
+@implementation NSString
+
+// Make sure we can convert a message to a dynamic receiver to a call
+// CHECK-LABEL: define {{.*}}void @retain_self
++ (void)retain_self {
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_retain}}
+ [self retain];
+}
+
+// Make sure we never convert a message to super to a call
+// CHECK-LABEL: define {{.*}}void @retain_super
+- (void)retain_super {
+ // MSGS: {{call.*@objc_msgSend}}
+ // CALLS: {{call.*@objc_msgSend}}
+ [super retain];
+}
+
+@end
+
diff --git a/test/CodeGenObjC/debug-info-block-helper.m b/test/CodeGenObjC/debug-info-block-helper.m
index 107830782c3c..1d37ea44ec6f 100644
--- a/test/CodeGenObjC/debug-info-block-helper.m
+++ b/test/CodeGenObjC/debug-info-block-helper.m
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -emit-llvm -fblocks -debug-info-kind=limited -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 %s -o - | FileCheck %s
extern void foo(void(^)(void));
-// CHECK: !DISubprogram(name: "__destroy_helper_block_"
+// CHECK: !DISubprogram(name: "__destroy_helper_block_8_32o40r48r"
@interface NSObject {
struct objc_object *isa;
diff --git a/test/CodeGenObjC/debug-info-block-line.m b/test/CodeGenObjC/debug-info-block-line.m
index d4c409411c6a..863912e5df4e 100644
--- a/test/CodeGenObjC/debug-info-block-line.m
+++ b/test/CodeGenObjC/debug-info-block-line.m
@@ -62,16 +62,16 @@ typedef enum : NSUInteger {
TMap *map = [TMap mapForID:mapID];
// Make sure we do not map code generated for the block to the above line.
// CHECK: define internal void @"__39-[TServer serverConnection:getCommand:]_block_invoke"
-// CHECK: call void @objc_storeStrong(i8** [[ZERO:%.*]], i8* [[ONE:%.*]]) [[NUW:#[0-9]+]]
-// CHECK: call void @objc_storeStrong(i8** [[TWO:%.*]], i8* [[THREE:%.*]]) [[NUW]]
+// CHECK: call void @llvm.objc.storeStrong(i8** [[ZERO:%.*]], i8* [[ONE:%.*]]) [[NUW:#[0-9]+]]
+// CHECK: call void @llvm.objc.storeStrong(i8** [[TWO:%.*]], i8* [[THREE:%.*]]) [[NUW]]
// CHECK: call {{.*}}@objc_msgSend{{.*}}, !dbg ![[LINE_ABOVE:[0-9]+]]
// CHECK: getelementptr
// CHECK-NOT: !dbg, ![[LINE_ABOVE]]
// CHECK: bitcast %5** [[TMP:%.*]] to i8**
// CHECK-NOT: !dbg, ![[LINE_ABOVE]]
-// CHECK: call void @objc_storeStrong(i8** [[VAL1:%.*]], i8* null) [[NUW]]
+// CHECK: call void @llvm.objc.storeStrong(i8** [[VAL1:%.*]], i8* null) [[NUW]]
// CHECK-NEXT: bitcast %4** [[TMP:%.*]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[VAL2:%.*]], i8* null) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[VAL2:%.*]], i8* null) [[NUW]]
// CHECK-NEXT: ret
// CHECK: attributes [[NUW]] = { nounwind }
[map dataWithCompletionBlock:^(NSData *data, NSError *error) {
diff --git a/test/CodeGenObjC/debug-info-blocks.m b/test/CodeGenObjC/debug-info-blocks.m
index 848e389f701b..b6e5b42ec671 100644
--- a/test/CodeGenObjC/debug-info-blocks.m
+++ b/test/CodeGenObjC/debug-info-blocks.m
@@ -59,9 +59,9 @@ static void run(void (^block)(void))
if ((self = [super init])) {
// CHECK-DAG: [[DBG_LINE]] = !DILocation(line: 0, scope: ![[COPY_SP:[0-9]+]])
// CHECK-DAG: [[COPY_LINE]] = !DILocation(line: [[@LINE+7]], scope: ![[COPY_SP:[0-9]+]])
- // CHECK-DAG: [[COPY_SP]] = distinct !DISubprogram(name: "__copy_helper_block_"
+ // CHECK-DAG: [[COPY_SP]] = distinct !DISubprogram(name: "__copy_helper_block_8_32o"
// CHECK-DAG: [[DESTROY_LINE]] = !DILocation(line: [[@LINE+5]], scope: ![[DESTROY_SP:[0-9]+]])
- // CHECK-DAG: [[DESTROY_SP]] = distinct !DISubprogram(name: "__destroy_helper_block_"
+ // CHECK-DAG: [[DESTROY_SP]] = distinct !DISubprogram(name: "__destroy_helper_block_8_32o"
// CHECK-DAG: !DILocalVariable(arg: 1, scope: ![[COPY_SP]], {{.*}}, flags: DIFlagArtificial)
// CHECK-DAG: !DILocalVariable(arg: 2, scope: ![[COPY_SP]], {{.*}}, flags: DIFlagArtificial)
// CHECK-DAG: !DILocalVariable(arg: 1, scope: ![[DESTROY_SP]], {{.*}}, flags: DIFlagArtificial)
diff --git a/test/CodeGenObjC/debug-info-category.m b/test/CodeGenObjC/debug-info-category.m
index faca3a49c23e..5ff2365722f3 100644
--- a/test/CodeGenObjC/debug-info-category.m
+++ b/test/CodeGenObjC/debug-info-category.m
@@ -36,17 +36,18 @@
// CHECK: ![[STRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo"
-// DWARF5: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-// DWARF5: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-// DWARF5: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-// DWARF5: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-
-// DWARF4-NOT: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-// DWARF4-NOT: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-// DWARF4-NOT: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-// DWARF4-NOT: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}}isDefinition: false
-
-// CHECK: = distinct !DISubprogram(name: "-[Foo integer]"{{.*}}isDefinition: true
-// CHECK: = distinct !DISubprogram(name: "-[Foo integer:]"{{.*}}isDefinition: true
-// CHECK: = distinct !DISubprogram(name: "+[Foo(Bar) zero:]"{{.*}}isDefinition: true
-// CHECK: = distinct !DISubprogram(name: "-[Foo(Bar) add:]"{{.*}}isDefinition: true
+// Verify "not a definition" by showing spFlags doesn't have DISPFlagDefinition.
+// DWARF5: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+// DWARF5: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+// DWARF5: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+// DWARF5: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+
+// DWARF4-NOT: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+// DWARF4-NOT: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+// DWARF4-NOT: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+// DWARF4-NOT: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit,
+
+// CHECK: = distinct !DISubprogram(name: "-[Foo integer]"{{.*}} DISPFlagDefinition
+// CHECK: = distinct !DISubprogram(name: "-[Foo integer:]"{{.*}} DISPFlagDefinition
+// CHECK: = distinct !DISubprogram(name: "+[Foo(Bar) zero:]"{{.*}} DISPFlagDefinition
+// CHECK: = distinct !DISubprogram(name: "-[Foo(Bar) add:]"{{.*}} DISPFlagDefinition
diff --git a/test/CodeGenObjC/debug-info-synthesis.m b/test/CodeGenObjC/debug-info-synthesis.m
index 8d2846e7312b..f95425628281 100644
--- a/test/CodeGenObjC/debug-info-synthesis.m
+++ b/test/CodeGenObjC/debug-info-synthesis.m
@@ -34,4 +34,4 @@ int main(int argc, char *argv[]) {
// CHECK: !DISubprogram(name: "-[Foo setDict:]"
// CHECK-SAME: file: ![[FILE]],
// CHECK-SAME: line: 8,
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
diff --git a/test/CodeGenObjC/debug-property-synth.m b/test/CodeGenObjC/debug-property-synth.m
index 45bf77067c86..124c61ea88cd 100644
--- a/test/CodeGenObjC/debug-property-synth.m
+++ b/test/CodeGenObjC/debug-property-synth.m
@@ -18,9 +18,9 @@
// CHECK-NOT: ret
// CHECK: load {{.*}}, !dbg ![[DBG2:[0-9]+]]
//
-// CHECK: !DISubprogram(name: "-[I p1]",{{.*}} line: [[@LINE+4]],{{.*}} isLocal: true, isDefinition: true
+// CHECK: !DISubprogram(name: "-[I p1]",{{.*}} line: [[@LINE+4]],{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+3]],
-// CHECK: !DISubprogram(name: "-[I setP1:]",{{.*}} line: [[@LINE+2]],{{.*}} isLocal: true, isDefinition: true
+// CHECK: !DISubprogram(name: "-[I setP1:]",{{.*}} line: [[@LINE+2]],{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK: ![[DBG2]] = !DILocation(line: [[@LINE+1]],
@property int p1;
@end
diff --git a/test/CodeGenObjC/debuginfo-properties.m b/test/CodeGenObjC/debuginfo-properties.m
index 5593b0d87f6a..c0de620abd96 100644
--- a/test/CodeGenObjC/debuginfo-properties.m
+++ b/test/CodeGenObjC/debuginfo-properties.m
@@ -13,16 +13,16 @@
@property (nonatomic, retain) Selection* selection;
// CHECK: !DISubprogram(name: "-[MyClass selection]"
// CHECK-SAME: line: [[@LINE-2]]
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK: !DISubprogram(name: "-[MyClass setSelection:]"
// CHECK-SAME: line: [[@LINE-5]]
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK: !DISubprogram(name: "-[OtherClass selection]"
// CHECK-SAME: line: [[@LINE-8]]
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK: !DISubprogram(name: "-[OtherClass setSelection:]"
// CHECK-SAME: line: [[@LINE-11]]
-// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
@end
diff --git a/test/CodeGenObjC/empty-collection-literals.m b/test/CodeGenObjC/empty-collection-literals.m
index 4b1d7f6ebe46..313c8c86c151 100644
--- a/test/CodeGenObjC/empty-collection-literals.m
+++ b/test/CodeGenObjC/empty-collection-literals.m
@@ -17,16 +17,16 @@ void test_empty_array() {
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
// CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
- // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*llvm.objc.retainAutoreleasedReturnValue}}
// CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
// CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_array
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
// CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSArray0__
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
- // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
+ // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*llvm.objc.retain\(}}
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
- // CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
+ // CHECK-WITH-EMPTY-COLLECTIONS: call void @llvm.objc.storeStrong
// CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
NSArray *arr = @[];
}
@@ -36,16 +36,16 @@ void test_empty_dictionary() {
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
// CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
- // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*llvm.objc.retainAutoreleasedReturnValue}}
// CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
// CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_dictionary
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
// CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSDictionary0__{{.*}}!invariant.load
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
- // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
+ // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*llvm.objc.retain\(}}
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
- // CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
+ // CHECK-WITH-EMPTY-COLLECTIONS: call void @llvm.objc.storeStrong
// CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
NSDictionary *dict = @{};
}
diff --git a/test/CodeGenObjC/extern-void-class-decl.m b/test/CodeGenObjC/extern-void-class-decl.m
new file mode 100644
index 000000000000..c673b005cd5c
--- /dev/null
+++ b/test/CodeGenObjC/extern-void-class-decl.m
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -emit-llvm -o - | FileCheck %s
+
+// rdar://45077269
+
+extern void OBJC_CLASS_$_f;
+Class c = (Class)&OBJC_CLASS_$_f;
+
+@implementation f @end
+
+// Check that we override the initializer for c, and that OBJC_CLASS_$_f gets
+// the right definition.
+
+// CHECK: @c = global i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_f" to i8*)
+// CHECK: @"OBJC_CLASS_$_f" = global %struct._class_t
diff --git a/test/CodeGenObjC/externally-retained.m b/test/CodeGenObjC/externally-retained.m
new file mode 100644
index 000000000000..0b4d0d648b44
--- /dev/null
+++ b/test/CodeGenObjC/externally-retained.m
@@ -0,0 +1,115 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-arc -fblocks -Wno-objc-root-class -O0 %s -S -emit-llvm -o - | FileCheck %s --dump-input-on-failure
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-arc -fblocks -Wno-objc-root-class -O0 -xobjective-c++ -std=c++11 %s -S -emit-llvm -o - | FileCheck %s --check-prefix CHECKXX --dump-input-on-failure
+
+#define EXT_RET __attribute__((objc_externally_retained))
+
+@interface ObjTy @end
+
+ObjTy *global;
+
+#if __cplusplus
+// Suppress name mangling in C++ mode for the sake of check lines.
+extern "C" void param(ObjTy *p);
+extern "C" void local();
+extern "C" void in_init();
+extern "C" void anchor();
+extern "C" void block_capture(ObjTy *);
+extern "C" void esc(void (^)());
+extern "C" void escp(void (^)(ObjTy *));
+extern "C" void block_param();
+#endif
+
+void param(ObjTy *p) EXT_RET {
+ // CHECK-LABEL: define void @param
+ // CHECK-NOT: llvm.objc.
+ // CHECK ret
+}
+
+void local() {
+ EXT_RET ObjTy *local = global;
+ // CHECK-LABEL: define void @local
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+}
+
+void in_init() {
+ // Test that we do the right thing when a variable appears in it's own
+ // initializer. Here, we release the value stored in 'wat' after overwriting
+ // it, in case it was somehow set to point to a non-null object while it's
+ // initializer is being evaluated.
+ EXT_RET ObjTy *wat = 0 ? wat : global;
+
+ // CHECK-LABEL: define void @in_init
+ // CHECK: [[WAT:%.*]] = alloca
+ // CHECK-NEXT: store {{.*}} null, {{.*}} [[WAT]]
+ // CHECK-NEXT: [[GLOBAL:%.*]] = load {{.*}} @global
+ // CHECK-NEXT: [[WAT_LOAD:%.*]] = load {{.*}} [[WAT]]
+ // CHECK-NEXT: store {{.*}} [[GLOBAL]], {{.*}} [[WAT]]
+ // CHECK-NEXT: [[CASTED:%.*]] = bitcast {{.*}} [[WAT_LOAD]] to
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[CASTED]])
+
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+}
+
+void esc(void (^)());
+
+void block_capture(ObjTy *obj) EXT_RET {
+ esc(^{ (void)obj; });
+
+ // CHECK-LABEL: define void @block_capture
+ // CHECK-NOT: llvm.objc.
+ // CHECK: call i8* @llvm.objc.retain
+ // CHECK-NOT: llvm.objc.
+ // CHECK: call void @esc
+ // CHECK-NOT: llvm.objc.
+ // CHECK: call void @llvm.objc.storeStrong({{.*}} null)
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+
+ // CHECK-LABEL: define {{.*}} void @__copy_helper_block_
+ // CHECK-NOT: llvm.objc.
+ // CHECK: llvm.objc.storeStrong
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+
+ // CHECK-LABEL: define {{.*}} void @__destroy_helper_block_
+ // CHECK-NOT: llvm.objc.
+ // CHECK: llvm.objc.storeStrong({{.*}} null)
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+}
+
+void escp(void (^)(ObjTy *));
+
+void block_param() {
+ escp(^(ObjTy *p) EXT_RET {});
+
+ // CHECK-LABEL: define internal void @__block_param_block_invoke
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+}
+
+@interface Inter
+-(void)m1: (ObjTy *)w;
+@end
+
+@implementation Inter
+-(void)m1: (ObjTy *) w EXT_RET {
+ // CHECK-LABEL: define internal void @"\01-[Inter m1:]"
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+}
+-(void)m2: (ObjTy *) w EXT_RET {
+ // CHECK-LABEL: define internal void @"\01-[Inter m2:]"
+ // CHECK-NOT: llvm.objc.
+ // CHECK: ret
+}
+@end
+
+#if __cplusplus
+// Verify that the decltype(p) is resolved before 'p' is made implicitly const.
+__attribute__((objc_externally_retained))
+void foo(ObjTy *p, decltype(p) *) {}
+// CHECKXX: _Z3fooP5ObjTyPU8__strongS0_
+#endif
diff --git a/test/CodeGenObjC/forward-declare-protocol-gnu.m b/test/CodeGenObjC/forward-declare-protocol-gnu.m
index b57a4a48d4a0..3731fb078eea 100644
--- a/test/CodeGenObjC/forward-declare-protocol-gnu.m
+++ b/test/CodeGenObjC/forward-declare-protocol-gnu.m
@@ -3,9 +3,11 @@
// Regression test: check that we don't crash when referencing a forward-declared protocol.
@protocol P;
-Protocol *getProtocol(void)
-{
- return @protocol(P);
-}
+@interface I <P>
+@end
+
+@implementation I
+
+@end
// CHECK: @.objc_protocol
diff --git a/test/CodeGenObjC/forward-protocol-metadata-symbols.m b/test/CodeGenObjC/forward-protocol-metadata-symbols.m
index 16d33ec15d82..76afc9c6c760 100644
--- a/test/CodeGenObjC/forward-protocol-metadata-symbols.m
+++ b/test/CodeGenObjC/forward-protocol-metadata-symbols.m
@@ -3,7 +3,7 @@
@interface NSObject @end
-@protocol P0;
+@protocol P0 @end
@interface A : NSObject <P0>
+(Class) getClass;
@@ -19,8 +19,8 @@ int main() {
}
// CHECK: @"\01l_OBJC_PROTOCOL_$_P0" = weak hidden global
-// CHECK: @"\01l_OBJC_CLASS_PROTOCOLS_$_A" = private global
// CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_P0" = weak hidden global
+// CHECK: @"\01l_OBJC_CLASS_PROTOCOLS_$_A" = private global
// CHECK: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P0" = weak hidden global
// CHECK: llvm.used = appending global [3 x i8*]
@@ -33,7 +33,7 @@ int main() {
// CHECK-SAME: OBJC_METH_VAR_NAME_
// CHECK-SAME: OBJC_METH_VAR_TYPE_
// CHECK-SAME: "\01l_OBJC_$_CLASS_METHODS_A"
-// CHECK-SAME: "\01l_OBJC_CLASS_PROTOCOLS_$_A"
// CHECK-SAME: OBJC_CLASS_NAME_.1
+// CHECK-SAME: "\01l_OBJC_CLASS_PROTOCOLS_$_A"
// CHECK-SAME: "OBJC_LABEL_CLASS_$"
// CHECK-SAME: section "llvm.metadata"
diff --git a/test/CodeGenObjC/fragile-arc.m b/test/CodeGenObjC/fragile-arc.m
index 2bf813d4615b..1320a147bbca 100644
--- a/test/CodeGenObjC/fragile-arc.m
+++ b/test/CodeGenObjC/fragile-arc.m
@@ -37,7 +37,7 @@
// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]**
// CHECK-NEXT: [[T0:%.*]] = load [[OPAQUE]]*, [[OPAQUE]]** [[IVAR]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[OPAQUE]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[OPAQUE]]*
// CHECK-NEXT: store [[OPAQUE]]* [[T3]], [[OPAQUE]]** [[X]]
Opaque *x = strong;
@@ -48,10 +48,10 @@
// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]**
// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[OPAQUE]]* [[VALUE]] to i8*
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* [[T1]])
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* [[T1]])
strong = x;
// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[X]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK-NEXT: ret void
}
@@ -64,7 +64,7 @@
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 8
// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]**
// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8**
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T0]])
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]*
// CHECK-NEXT: store [[OPAQUE]]* [[T2]], [[OPAQUE]]** [[X]]
Opaque *x = weak;
@@ -75,10 +75,10 @@
// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]**
// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[OPAQUE]]* [[VALUE]] to i8*
-// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[T0]], i8* [[T1]])
+// CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[T0]], i8* [[T1]])
weak = x;
// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[X]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK-NEXT: ret void
}
@@ -89,12 +89,12 @@
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 8
// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]**
// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8**
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[T0]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[SELF]] to i8*
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 4
// CHECK-NEXT: [[IVAR:%.*]] = bitcast i8* [[T1]] to [[OPAQUE]]**
// CHECK-NEXT: [[T0:%.*]] = bitcast [[OPAQUE]]** [[IVAR]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK-NEXT: ret void
@end
@@ -126,13 +126,13 @@
extern void useBlock(void (^block)(void));
// 256 == 0x100 == starts with 1 strong
-// GLOBALS: @__block_descriptor_tmp{{.*}} = internal constant {{.*}}, i32 256 }
+// GLOBALS: @"__block_descriptor{{.*}} = linkonce_odr hidden {{.*}}, i32 256 }
void testBlockLayoutStrong(id x) {
useBlock(^{ (void) x; });
}
// 1 == 0x001 == starts with 1 weak
-// GLOBALS: @__block_descriptor_tmp{{.*}} = internal constant {{.*}}, i32 1 }
+// GLOBALS: @"__block_descriptor{{.*}} = linkonce_odr hidden {{.*}}, i32 1 }
void testBlockLayoutWeak(__weak id x) {
useBlock(^{ (void) x; });
}
@@ -151,17 +151,17 @@ void testBlockLayoutWeak(__weak id x) {
// CHECK: br i1
// CHECK: [[T0:%.*]] = bitcast i8* [[EXN]] to [[A]]*
// CHECK: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
-// CHECK: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK: [[T2:%.*]] = call i8* @llvm.objc.retain(i8* [[T1]])
// CHECK: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
// CHECK: store [[A]]* [[T3]], [[A]]** [[X]]
// CHECK: call void @checkpoint(i32 1)
// CHECK: [[T0:%.*]] = bitcast [[A]]** [[X]] to i8**
-// CHECK: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null)
// CHECK: br label
-// CHECK: [[T0:%.*]] = call i8* @objc_retain(i8* [[EXN]])
+// CHECK: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[EXN]])
// CHECK: store i8* [[T0]], i8** [[Y]]
// CHECK: call void @checkpoint(i32 2)
-// CHECK: call void @objc_storeStrong(i8** [[Y]], i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** [[Y]], i8* null)
extern void checkpoint(int n);
void testCatch() {
@try {
diff --git a/test/CodeGenObjC/gnu-deterministic-selectors.m b/test/CodeGenObjC/gnu-deterministic-selectors.m
new file mode 100644
index 000000000000..5f8d2e5378a5
--- /dev/null
+++ b/test/CodeGenObjC/gnu-deterministic-selectors.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -fobjc-runtime=gnustep-1.5 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -fobjc-runtime=gcc %s -emit-llvm -o - | FileCheck %s
+
+// Check that these selectors are emitted in alphabetical order.
+// The order doesn't actually matter, only that it doesn't vary across runs.
+// Clang sorts them when targeting a GCC-like ABI to guarantee determinism.
+// CHECK: @.objc_selector_list = internal global [6 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.objc_sel_namea, i64 0, i64 0), i8* null }, { i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.objc_sel_nameg, i64 0, i64 0), i8* null }, { i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.objc_sel_namej, i64 0, i64 0), i8* null }, { i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.objc_sel_namel, i64 0, i64 0), i8* null }, { i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.objc_sel_namez, i64 0, i64 0), i8* null }, { i8*, i8* } zeroinitializer], align 8
+
+
+void f() {
+ SEL a = @selector(z);
+ SEL b = @selector(a);
+ SEL c = @selector(g);
+ SEL d = @selector(l);
+ SEL e = @selector(j);
+}
diff --git a/test/CodeGenObjC/gnu-init.m b/test/CodeGenObjC/gnu-init.m
index beb06bbe0df4..2188165ff177 100644
--- a/test/CodeGenObjC/gnu-init.m
+++ b/test/CodeGenObjC/gnu-init.m
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-WIN
// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-1.8 -o - %s | FileCheck %s -check-prefix=CHECK-OLD
// Almost minimal Objective-C file, check that it emits calls to the correct
@@ -49,9 +50,9 @@
// CHECK-NEW: @.objc_null_class_alias = linkonce_odr hidden global { i8*, i8* } zeroinitializer, section "__objc_class_aliases", comdat, align 8
// CHECK-NEW: @.objc_null_constant_string = linkonce_odr hidden global { i8*, i32, i32, i32, i32, i8* } zeroinitializer, section "__objc_constant_string", comdat, align 8
// Make sure that the null symbols are not going to be removed, even by linking.
-// CHECK-NEW: @llvm.used = appending global [7 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata"
+// CHECK-NEW: @llvm.used = appending global [8 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast (void ()** @.objc_ctor to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata"
// Make sure that the load function and the reference to it are marked as used.
-// CHECK-NEW: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata"
+// CHECK-NEW: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*)], section "llvm.metadata"
// Check that we emit the load function in a comdat and that it does the right thing.
// CHECK-NEW: define linkonce_odr hidden void @.objcv2_load_function() comdat {
@@ -67,3 +68,37 @@
// CHECK-OLD-NEXT: entry:
// CHECK-OLD-NEXT: call void ({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }*, ...) @__objc_exec_class({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }* @4)
+
+
+// Make sure all of our section boundary variables are emitted correctly.
+// CHECK-WIN-DAG: @__start___objc_selectors = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_selectors$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_selectors = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_selectors$z", comdat, align 1
+// CHECK-WIN-DAG: @__start___objc_classes = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_classes$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_classes = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_classes$z", comdat, align 1
+// CHECK-WIN-DAG: @__start___objc_class_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_refs$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_class_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_refs$z", comdat, align 1
+// CHECK-WIN-DAG: @__start___objc_cats = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_cats$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_cats = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_cats$z", comdat, align 1
+// CHECK-WIN-DAG: @__start___objc_protocols = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocols$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_protocols = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocols$z", comdat, align 1
+// CHECK-WIN-DAG: @__start___objc_protocol_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocol_refs$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_protocol_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocol_refs$z", comdat, align 1
+// CHECK-WIN-DAG: @__start___objc_class_aliases = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_aliases$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_class_aliases = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_aliases$z", comdat, align 1
+// CHECK-WIN-DAG: @__start___objc_constant_string = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_constant_string$a", comdat, align 1
+// CHECK-WIN-DAG: @__stop__objc_constant_string = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_constant_string$z", comdat, align 1
+// CHECK-WIN: @.objc_init = linkonce_odr hidden global { i64, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel* } { i64 0, %.objc_section_sentinel* @__start___objc_selectors, %.objc_section_sentinel* @__stop__objc_selectors, %.objc_section_sentinel* @__start___objc_classes, %.objc_section_sentinel* @__stop__objc_classes, %.objc_section_sentinel* @__start___objc_class_refs, %.objc_section_sentinel* @__stop__objc_class_refs, %.objc_section_sentinel* @__start___objc_cats, %.objc_section_sentinel* @__stop__objc_cats, %.objc_section_sentinel* @__start___objc_protocols, %.objc_section_sentinel* @__stop__objc_protocols, %.objc_section_sentinel* @__start___objc_protocol_refs, %.objc_section_sentinel* @__stop__objc_protocol_refs, %.objc_section_sentinel* @__start___objc_class_aliases, %.objc_section_sentinel* @__stop__objc_class_aliases, %.objc_section_sentinel* @__start___objc_constant_string, %.objc_section_sentinel* @__stop__objc_constant_string }, comdat, align 8
+
+// Make sure our init variable is in the correct section for late library init.
+// CHECK-WIN: @.objc_ctor = linkonce hidden constant void ()* @.objcv2_load_function, section ".CRT$XCLz", comdat
+
+// We shouldn't have emitted any null placeholders on Windows.
+// CHECK-WIN: @llvm.used = appending global [2 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8* }*, i8*, i8*, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata"
+// CHECK-WIN: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*)], section "llvm.metadata"
+
+// Check our load function is in a comdat.
+// CHECK-WIN: define linkonce_odr hidden void @.objcv2_load_function() comdat {
+
+// Make sure we have dllimport on the load function
+// CHECK-WIN: declare dllimport void @__objc_load
+
diff --git a/test/CodeGenObjC/gnustep2-category-protocol.m b/test/CodeGenObjC/gnustep2-category-protocol.m
new file mode 100644
index 000000000000..646347450763
--- /dev/null
+++ b/test/CodeGenObjC/gnustep2-category-protocol.m
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
+
+// Regression test. We weren't emitting definitions for protocols used in
+// categories, causing linker errors when the category was the only reference
+// to a protocol in a binary.
+
+// CHECK: @._OBJC_PROTOCOL_Y = global
+// CHEKC-SAME: section "__objc_protocols", comdat, align 8
+
+
+@interface X
+{
+id isa;
+}
+@end
+@implementation X
+@end
+
+@protocol Y @end
+
+@interface X (y) <Y>
+@end
+@implementation X (y) @end
+
+
diff --git a/test/CodeGenObjC/gnustep2-proto.m b/test/CodeGenObjC/gnustep2-proto.m
index 536714f03a99..8550b0fb2d92 100644
--- a/test/CodeGenObjC/gnustep2-proto.m
+++ b/test/CodeGenObjC/gnustep2-proto.m
@@ -22,11 +22,11 @@
// Check that we're emitting the protocol and a correctly initialised
// indirection variable.
-// CHECK: @._OBJC_PROTOCOL_X = global
+// CHECK: @._OBJC_PROTOCOL_X = global
// CHECK-SAME: , section "__objc_protocols", comdat, align 8
-// CHECK: @._OBJC_REF_PROTOCOL_X = global
+// CHECK: @._OBJC_REF_PROTOCOL_X = linkonce_odr global
// CHECK-SAME: @._OBJC_PROTOCOL_X
-// CHECK-SAME: , section "__objc_protocol_refs", align 8
+// CHECK-SAME: , section "__objc_protocol_refs", comdat, align 8
// Check that we load from the indirection variable on protocol references.
diff --git a/test/CodeGenObjC/hidden-visibility.m b/test/CodeGenObjC/hidden-visibility.m
index cb23ca18f81f..03290c29bbdb 100644
--- a/test/CodeGenObjC/hidden-visibility.m
+++ b/test/CodeGenObjC/hidden-visibility.m
@@ -16,7 +16,7 @@
@end
-@protocol Prot0;
+@protocol Prot0 @end
id f0() {
return @protocol(Prot0);
diff --git a/test/CodeGenObjC/link-errors.m b/test/CodeGenObjC/link-errors.m
index f2d9ddba883b..44797d9e8d1d 100644
--- a/test/CodeGenObjC/link-errors.m
+++ b/test/CodeGenObjC/link-errors.m
@@ -10,7 +10,7 @@
-(id) init;
@end
-@protocol P;
+@protocol P @end
@interface A : Root
@end
diff --git a/test/CodeGenObjC/mrc-weak.m b/test/CodeGenObjC/mrc-weak.m
index e2c78f073367..3a8cd2fd75e6 100644
--- a/test/CodeGenObjC/mrc-weak.m
+++ b/test/CodeGenObjC/mrc-weak.m
@@ -46,15 +46,15 @@
@implementation Foo
// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
@end
void test1(__weak id x) {}
// CHECK-LABEL: define void @test1
// CHECK: [[X:%.*]] = alloca i8*,
-// CHECK-NEXT: objc_initWeak
-// CHECK-NEXT: objc_destroyWeak
+// CHECK-NEXT: @llvm.objc.initWeak
+// CHECK-NEXT: @llvm.objc.destroyWeak
// CHECK-NEXT: ret void
void test2(id y) {
@@ -65,8 +65,8 @@ void test2(id y) {
// CHECK-NEXT: [[Z:%.*]] = alloca i8*,
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]])
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[Z]], i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]])
// CHECK-NEXT: ret void
void test3(id y) {
@@ -79,8 +79,8 @@ void test3(id y) {
// CHECK-NEXT: store
// CHECK-NEXT: store i8* null, i8** [[Z]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
-// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]])
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
+// CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[Z]], i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]])
// CHECK-NEXT: ret void
void test4(__weak id *p) {
@@ -91,7 +91,7 @@ void test4(__weak id *p) {
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeak(i8** [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
// CHECK-NEXT: ret void
@@ -103,7 +103,7 @@ void test5(__weak id *p) {
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
// CHECK-NEXT: ret void
@@ -116,7 +116,7 @@ void test6(__weak Foo **p) {
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8**
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]*
// CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]]
// CHECK-NEXT: ret void
@@ -134,44 +134,44 @@ void test7(void) {
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8*
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]])
-// CHECK: call void @objc_copyWeak
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[T2]], i8* [[T3]])
+// CHECK: call void @llvm.objc.copyWeak
// CHECK: call void @use_block
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
-// CHECK-LABEL: define internal void @__copy_helper_block
-// CHECK: @objc_copyWeak
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block
+// CHECK: @llvm.objc.copyWeak
-// CHECK-LABEL: define internal void @__destroy_helper_block
-// CHECK: @objc_destroyWeak
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block
+// CHECK: @llvm.objc.destroyWeak
void test8(void) {
__block __weak Foo *p = get_object();
use_block(^{ [p run ]; });
}
// CHECK-LABEL: define void @test8
-// CHECK: call i8* @objc_initWeak
-// CHECK-NOT: call void @objc_copyWeak
+// CHECK: call i8* @llvm.objc.initWeak
+// CHECK-NOT: call void @llvm.objc.copyWeak
// CHECK: call void @use_block
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
// CHECK-LABEL: define internal void @__Block_byref_object_copy
-// CHECK: call void @objc_moveWeak
+// CHECK: call void @llvm.objc.moveWeak
// CHECK-LABEL: define internal void @__Block_byref_object_dispose
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
// CHECK-LABEL: define void @test9_baseline()
-// CHECK: define internal void @__copy_helper
-// CHECK: define internal void @__destroy_helper
+// CHECK: define linkonce_odr hidden void @__copy_helper
+// CHECK: define linkonce_odr hidden void @__destroy_helper
void test9_baseline(void) {
Foo *p = get_object();
use_block(^{ [p run]; });
}
// CHECK-LABEL: define void @test9()
-// CHECK-NOT: define internal void @__copy_helper
-// CHECK-NOT: define internal void @__destroy_helper
+// CHECK-NOT: define linkonce_odr hidden void @__copy_helper
+// CHECK-NOT: define linkonce_odr hidden void @__destroy_helper
// CHECK: define void @test9_fin()
void test9(void) {
__unsafe_unretained Foo *p = get_object();
@@ -180,8 +180,8 @@ void test9(void) {
void test9_fin() {}
// CHECK-LABEL: define void @test10()
-// CHECK-NOT: define internal void @__copy_helper
-// CHECK-NOT: define internal void @__destroy_helper
+// CHECK-NOT: define linkonce_odr hidden void @__copy_helper
+// CHECK-NOT: define linkonce_odr hidden void @__destroy_helper
// CHECK: define void @test10_fin()
void test10(void) {
typedef __unsafe_unretained Foo *UnsafeFooPtr;
diff --git a/test/CodeGenObjC/noescape.m b/test/CodeGenObjC/noescape.m
index 56e1e51e5d3f..0c4f3ddddf83 100644
--- a/test/CodeGenObjC/noescape.m
+++ b/test/CodeGenObjC/noescape.m
@@ -8,6 +8,7 @@ union U {
long long *ll;
} __attribute__((transparent_union));
+void escapingFunc0(BlockTy);
void noescapeFunc0(id, __attribute__((noescape)) BlockTy);
void noescapeFunc1(__attribute__((noescape)) int *);
void noescapeFunc2(__attribute__((noescape)) id);
@@ -17,7 +18,14 @@ void noescapeFunc3(__attribute__((noescape)) union U);
// helper functions.
// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
-// CHECK: @[[BLOCK_DESCIPTOR_TMP_2:.*]] = internal constant { i64, i64, i8*, i64 } { i64 0, i64 40, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8
+
+// When the block is non-escaping, copy/dispose helpers aren't generated, so the
+// block layout string must include information about __strong captures.
+
+// CHECK-NOARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_B0]]*, i32, i32, i8*, %[[STRUCT_S0:.*]] }
+// CHECK-ARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_B0]]*, i32, i32, i8*, i8*, i8*, %[[STRUCT_S0:.*]] }
+// CHECK: %[[STRUCT_S0]] = type { i8*, i8* }
+// CHECK: @[[BLOCK_DESCIPTOR_TMP_2:.*ls32l8"]] = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i64 } { i64 0, i64 40, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8
// CHECK-LABEL: define void @test0(
// CHECK: call void @noescapeFunc0({{.*}}, {{.*}} nocapture {{.*}})
@@ -86,7 +94,7 @@ void test5(BlockTy2 b, int *p) {
// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
// CHECK-NOARC: store i8* %[[B]], i8** %[[B_ADDR]], align 8
// CHECK-ARC: store i8* null, i8** %[[B_ADDR]], align 8
-// CHECK-ARC: call void @objc_storeStrong(i8** %[[B_ADDR]], i8* %[[B]])
+// CHECK-ARC: call void @llvm.objc.storeStrong(i8** %[[B_ADDR]], i8* %[[B]])
// CHECK-ARC: %[[V0:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5
// CHECK: %[[BLOCK_ISA:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 0
// CHECK: store i8* bitcast (i8** @_NSConcreteGlobalBlock to i8*), i8** %[[BLOCK_ISA]], align 8
@@ -98,11 +106,11 @@ void test5(BlockTy2 b, int *p) {
// CHECK-NOARC: %[[V1:.*]] = load i8*, i8** %[[B_ADDR]], align 8
// CHECK-NOARC: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8
// CHECK-ARC: %[[V2:.*]] = load i8*, i8** %[[B_ADDR]], align 8
-// CHECK-ARC: %[[V3:.*]] = call i8* @objc_retain(i8* %[[V2]]) #3
+// CHECK-ARC: %[[V3:.*]] = call i8* @llvm.objc.retain(i8* %[[V2]])
// CHECK-ARC: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED]], align 8
// CHECK: call void @noescapeFunc0(
-// CHECK-ARC: call void @objc_storeStrong(i8** %[[V0]], i8* null)
-// CHECK-ARC: call void @objc_storeStrong(i8** %[[B_ADDR]], i8* null)
+// CHECK-ARC: call void @llvm.objc.storeStrong(i8** %[[V0]], i8* null)
+// CHECK-ARC: call void @llvm.objc.storeStrong(i8** %[[B_ADDR]], i8* null)
// Non-escaping blocks don't need copy/dispose helper functions.
@@ -114,3 +122,49 @@ void func(id);
void test6(id a, id b) {
noescapeFunc0(a, ^{ func(b); });
}
+
+// We don't need either the byref helper functions or the byref structs for
+// __block variables that are not captured by escaping blocks.
+
+// CHECK: define void @test7(
+// CHECK: alloca i8*, align 8
+// CHECK: %[[B0:.*]] = alloca i8*, align 8
+// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, align 8
+// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>* %[[BLOCK]], i32 0, i32 5
+// CHECK: store i8** %[[B0]], i8*** %[[BLOCK_CAPTURED]], align 8
+
+// CHECK-ARC-NOT: define internal void @__Block_byref_object_copy_
+// CHECK-ARC-NOT: define internal void @__Block_byref_object_dispose_
+
+void test7() {
+ id a;
+ __block id b0;
+ noescapeFunc0(a, ^{ (void)b0; });
+}
+
+// __block variables captured by escaping blocks need byref helper functions.
+
+// CHECK: define void @test8(
+// CHECK: %[[A:.*]] = alloca i8*, align 8
+// CHECK: %[[B0:.*]] = alloca %[[STRUCT_BLOCK_BYREF_B0]], align 8
+// CHECK: alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
+// CHECK: %[[BLOCK1:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
+// CHECK: %[[BLOCK_CAPTURED7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK1]], i32 0, i32 5
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_BLOCK_BYREF_B0]]* %[[B0]] to i8*
+// CHECK: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED7]], align 8
+
+// CHECK-ARC: define internal void @__Block_byref_object_copy_
+// CHECK-ARC: define internal void @__Block_byref_object_dispose_
+// CHECK: define linkonce_odr hidden void @__copy_helper_block_
+// CHECK: define linkonce_odr hidden void @__destroy_helper_block_
+
+struct S0 {
+ id a, b;
+};
+
+void test8() {
+ id a;
+ __block struct S0 b0;
+ noescapeFunc0(a, ^{ (void)b0; });
+ escapingFunc0(^{ (void)b0; });
+}
diff --git a/test/CodeGenObjC/ns_consume_null_check.m b/test/CodeGenObjC/ns_consume_null_check.m
index 777659f2686e..292dfeedb9b6 100644
--- a/test/CodeGenObjC/ns_consume_null_check.m
+++ b/test/CodeGenObjC/ns_consume_null_check.m
@@ -17,7 +17,7 @@ void test0(void) {
[x isEqual : obj];
}
// CHECK-LABEL: define void @test0()
-// CHECK: [[FIVE:%.*]] = call i8* @objc_retain
+// CHECK: [[FIVE:%.*]] = call i8* @llvm.objc.retain
// CHECK-NEXT: [[SIX:%.*]] = bitcast
// CHECK-NEXT: [[SEVEN:%.*]] = icmp eq i8* [[SIX]], null
// CHECK-NEXT: br i1 [[SEVEN]], label [[NULLINIT:%.*]], label [[CALL_LABEL:%.*]]
@@ -25,7 +25,7 @@ void test0(void) {
// CHECK-NEXT: [[EIGHT:%.*]] = bitcast i8* [[FN]]
// CHECK-NEXT: [[CALL:%.*]] = call signext i8 [[EIGHT]]
// CHECK-NEXT: br label [[CONT:%.*]]
-// CHECK: call void @objc_release(i8* [[FIVE]]) [[NUW:#[0-9]+]]
+// CHECK: call void @llvm.objc.release(i8* [[FIVE]]) [[NUW:#[0-9]+]]
// CHECK-NEXT: br label [[CONT]]
// CHECK: phi i8 [ [[CALL]], {{%.*}} ], [ 0, {{%.*}} ]
@@ -44,11 +44,11 @@ void test1(void) {
// CHECK: [[T0:%.*]] = call i8* bitcast (
// CHECK-NEXT: store i8* [[T0]], i8** [[OBJ]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[OBJ]]
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAKOBJ]], i8* [[T0]]) [[NUW]]
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[WEAKOBJ]], i8* [[T0]]) [[NUW]]
// Okay, start the message-send.
// CHECK-NEXT: [[T0:%.*]] = load [[MYOBJECT:%.*]]*, [[MYOBJECT:%.*]]** @x
// CHECK-NEXT: [[ARG:%.*]] = load i8*, i8** [[OBJ]]
-// CHECK-NEXT: [[ARG_RETAINED:%.*]] = call i8* @objc_retain(i8* [[ARG]])
+// CHECK-NEXT: [[ARG_RETAINED:%.*]] = call i8* @llvm.objc.retain(i8* [[ARG]])
// CHECK-NEXT: load i8*, i8** @
// CHECK-NEXT: [[SELF:%.*]] = bitcast [[MYOBJECT]]* [[T0]] to i8*
// Null check.
@@ -65,7 +65,7 @@ void test1(void) {
// CHECK-NEXT: [[IMAGCALL:%.*]] = load float, float* [[T0]]
// CHECK-NEXT: br label [[CONT:%.*]]{{$}}
// Null path.
-// CHECK: call void @objc_release(i8* [[ARG_RETAINED]]) [[NUW]]
+// CHECK: call void @llvm.objc.release(i8* [[ARG_RETAINED]]) [[NUW]]
// CHECK-NEXT: br label [[CONT]]
// Join point.
// CHECK: [[REAL:%.*]] = phi float [ [[REALCALL]], [[INVOKE_CONT]] ], [ 0.000000e+00, [[FORNULL]] ]
@@ -75,11 +75,11 @@ void test1(void) {
// CHECK-NEXT: store float [[REAL]], float* [[T0]]
// CHECK-NEXT: store float [[IMAG]], float* [[T1]]
// Epilogue.
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[WEAKOBJ]]) [[NUW]]
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[OBJ]], i8* null) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[WEAKOBJ]]) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[OBJ]], i8* null) [[NUW]]
// CHECK-NEXT: ret void
// Cleanup.
// CHECK: landingpad
-// CHECK: call void @objc_destroyWeak(i8** [[WEAKOBJ]]) [[NUW]]
+// CHECK: call void @llvm.objc.destroyWeak(i8** [[WEAKOBJ]]) [[NUW]]
// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m b/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m
index bab6e27bb345..4ca5adf1ca6f 100644
--- a/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m
+++ b/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m
@@ -25,9 +25,9 @@ void doRange() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
NSRange ns_range = { .location = 0, .length = 42 };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8* {{.*}}[[RANGE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *range = @(ns_range);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -44,9 +44,9 @@ void doPoint() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
CGPoint cg_point = { .x = 42, .y = 24 };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8* {{.*}}[[POINT_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *point = @(cg_point);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -63,9 +63,9 @@ void doSize() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
CGSize cg_size = { .width = 42, .height = 24 };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8* {{.*}}[[SIZE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *size = @(cg_size);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -84,9 +84,9 @@ void doRect() {
CGSize cg_size = { .width = 42, .height = 24 };
CGRect cg_rect = { .origin = cg_point, .size = cg_size };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8*{{.*}}[[RECT_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *rect = @(cg_rect);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -103,9 +103,9 @@ void doNSEdgeInsets() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
NSEdgeInsets ns_edge_insets;
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8*{{.*}}[[EDGE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *edge_insets = @(ns_edge_insets);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -118,9 +118,9 @@ void doRangeRValue() {
// CHECK: [[SEL:%.*]] = load i8*, i8** [[VALUE_SEL]]
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[COERCE_CAST]], i8* {{.*}}[[RANGE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *range_rvalue = @(getRange());
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
diff --git a/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m b/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m
index a2b4dfd6d9d2..041f03873bbc 100644
--- a/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m
+++ b/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m
@@ -25,9 +25,9 @@ void doRange() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
NSRange ns_range = { .location = 0, .length = 42 };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8* {{.*}}[[RANGE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *range = @(ns_range);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -44,9 +44,9 @@ void doPoint() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
NSPoint ns_point = { .x = 42, .y = 24 };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8* {{.*}}[[POINT_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *point = @(ns_point);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -63,9 +63,9 @@ void doSize() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
NSSize ns_size = { .width = 42, .height = 24 };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8* {{.*}}[[SIZE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *size = @(ns_size);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -84,9 +84,9 @@ void doRect() {
NSSize ns_size = { .width = 42, .height = 24 };
NSRect ns_rect = { .origin = ns_point, .size = ns_size };
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8*{{.*}}[[RECT_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *rect = @(ns_rect);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -103,9 +103,9 @@ void doNSEdgeInsets() {
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
NSEdgeInsets ns_edge_insets;
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[PARAM_CAST]], i8*{{.*}}[[EDGE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *edge_insets = @(ns_edge_insets);
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
@@ -122,9 +122,9 @@ void doRangeRValue() {
// CHECK: [[SEL:%.*]] = load i8*, i8** [[VALUE_SEL]]
// CHECK: [[RECV:%.*]] = bitcast %struct._class_t* [[RECV_PTR]] to i8*
// CHECK: call {{.*objc_msgSend.*}}(i8* [[RECV]], i8* [[SEL]], i8* [[COERCE_CAST]], i8* {{.*}}[[RANGE_STR]]{{.*}})
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
NSValue *range_rvalue = @(getRange());
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret void
}
diff --git a/test/CodeGenObjC/objc-arc-container-subscripting.m b/test/CodeGenObjC/objc-arc-container-subscripting.m
index 182456221c3c..339415e3c05d 100644
--- a/test/CodeGenObjC/objc-arc-container-subscripting.m
+++ b/test/CodeGenObjC/objc-arc-container-subscripting.m
@@ -12,10 +12,10 @@ id func() {
}
// CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
-// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) [[NUW:#[0-9]+]]
+// CHECK: [[SIX:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[call]]) [[NUW:#[0-9]+]]
// CHECK: [[ARRAY_CASTED:%.*]] = bitcast %0** {{%.*}} to i8**
-// CHECK: call void @objc_storeStrong(i8** [[ARRAY_CASTED]], i8* null)
-// CHECK: [[EIGHT:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) [[NUW]]
+// CHECK: call void @llvm.objc.storeStrong(i8** [[ARRAY_CASTED]], i8* null)
+// CHECK: [[EIGHT:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[SIX]]) [[NUW]]
// CHECK: ret i8* [[EIGHT]]
// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenObjC/os_log.m b/test/CodeGenObjC/os_log.m
index 1cf0c9f1f35c..6acd58304aab 100644
--- a/test/CodeGenObjC/os_log.m
+++ b/test/CodeGenObjC/os_log.m
@@ -21,7 +21,7 @@ void *test_builtin_os_log(void *buf) {
// CHECK: %[[CALL:.*]] = tail call %[[TY0:.*]]* (...) @GenString()
// CHECK: %[[V0:.*]] = bitcast %[[TY0]]* %[[CALL]] to i8*
- // CHECK: %[[V1:.*]] = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %[[V0]])
+ // CHECK: %[[V1:.*]] = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[V0]])
// CHECK: %[[V2:.*]] = ptrtoint %[[TY0]]* %[[CALL]] to i64
// CHECK: store i8 2, i8* %[[BUF]], align 1
// CHECK: %[[NUMARGS_I:.*]] = getelementptr i8, i8* %[[BUF]], i64 1
@@ -33,8 +33,8 @@ void *test_builtin_os_log(void *buf) {
// CHECK: %[[ARGDATA_I:.*]] = getelementptr i8, i8* %[[BUF]], i64 4
// CHECK: %[[ARGDATACAST_I:.*]] = bitcast i8* %[[ARGDATA_I]] to i64*
// CHECK: store i64 %[[V2]], i64* %[[ARGDATACAST_I]], align 1
- // CHECK: tail call void (...) @clang.arc.use(%[[TY0]]* %[[CALL]])
- // CHECK: tail call void @objc_release(i8* %[[V0]])
+ // CHECK: tail call void (...) @llvm.objc.clang.arc.use(%[[TY0]]* %[[CALL]])
+ // CHECK: tail call void @llvm.objc.release(i8* %[[V0]])
// CHECK: ret i8* %[[BUF]]
// clang.arc.use is used and removed in IR optimizations. At O0, we should not
@@ -45,13 +45,13 @@ void *test_builtin_os_log(void *buf) {
// CHECK-O0: %[[V0:.*]] = load i8*, i8** %[[BUF_ADDR]], align 8
// CHECK-O0: %[[CALL:.*]] = call %[[TY0:.*]]* (...) @GenString()
// CHECK-O0: %[[V1:.*]] = bitcast %[[TY0]]* %[[CALL]] to i8*
- // CHECK-O0: %[[V2:.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* %[[V1]])
+ // CHECK-O0: %[[V2:.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[V1]])
// CHECK-O0: %[[V3:.*]] = bitcast i8* %[[V2]] to %[[TY0]]*
// CHECK-O0: %[[V4:.*]] = ptrtoint %[[TY0]]* %[[V3]] to i64
// CHECK-O0: call void @__os_log_helper_1_2_1_8_64(i8* %[[V0]], i64 %[[V4]])
// CHECK-O0: %[[V5:.*]] = bitcast %[[TY0]]* %[[V3]] to i8*
- // CHECK-O0-NOT call void (...) @clang.arc.use({{.*}}
- // CHECK-O0: call void @objc_release(i8* %[[V5]])
+ // CHECK-O0-NOT call void (...) @llvm.objc.clang.arc.use({{.*}}
+ // CHECK-O0: call void @llvm.objc.release(i8* %[[V5]])
// CHECK-O0: ret i8* %[[V0]]
}
diff --git a/test/CodeGenObjC/parameterized_classes.m b/test/CodeGenObjC/parameterized_classes.m
index 34aca35af313..c2ddb5b551a9 100644
--- a/test/CodeGenObjC/parameterized_classes.m
+++ b/test/CodeGenObjC/parameterized_classes.m
@@ -61,11 +61,11 @@ void printMe(NSString *name) { }
// CHECK-LABEL: define void @blockTest
void blockTest(NSMutableArray<void (^)(void)> *array, NSString *name) {
// CHECK-NOT: ret void
- // CHECK: call i8* @objc_retainBlock
+ // CHECK: call i8* @llvm.objc.retainBlock
[array addObject: ^ { printMe(name); }];
// CHECK-NOT: ret void
array[0] = ^ { printMe(name); };
- // CHECK: call i8* @objc_retainBlock
+ // CHECK: call i8* @llvm.objc.retainBlock
// CHECK: ret void
}
@@ -80,7 +80,7 @@ void blockTest(NSMutableArray<void (^)(void)> *array, NSString *name) {
// CHECK: %[[V5:.*]] = bitcast i8* %[[ADDPTR]] to %[[IVARTY]]**
// CHECK: %[[V6:.*]] = bitcast %[[IVARTY]]** %[[V5]] to i8**
// CHECK: %[[V7:.*]] = bitcast %[[IVARTY]]* %[[V2]] to i8*
-// CHECK: call void @objc_storeStrong(i8** %[[V6]], i8* %[[V7]])
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V6]], i8* %[[V7]])
@interface Base<DestType> : NSObject {
DestType _destination;
diff --git a/test/CodeGenObjC/protocol-comdat.m b/test/CodeGenObjC/protocol-comdat.m
index a19ba8cf35dc..ddf8e5a77d4c 100644
--- a/test/CodeGenObjC/protocol-comdat.m
+++ b/test/CodeGenObjC/protocol-comdat.m
@@ -4,8 +4,8 @@
- (void) method;
@end
-@protocol Q;
-@protocol R;
+@protocol Q @end
+@protocol R @end
@interface I<P>
@end
diff --git a/test/CodeGenObjC/protocols-lazy.m b/test/CodeGenObjC/protocols-lazy.m
index fba7454b9549..a2dfc106d643 100644
--- a/test/CodeGenObjC/protocols-lazy.m
+++ b/test/CodeGenObjC/protocols-lazy.m
@@ -18,7 +18,10 @@ void f0() { id x = @protocol(P2); }
// RUN: grep OBJC_PROTOCOL_P3 %t | count 3
// RUN: not grep OBJC_PROTOCOL_INSTANCE_METHODS_P3 %t
@protocol P3;
-void f1() { id x = @protocol(P3); }
+@interface UserP3<P3>
+@end
+@implementation UserP3
+@end
// Definition triggered by class reference.
// RUN: grep OBJC_PROTOCOL_P4 %t | count 3
@@ -31,10 +34,16 @@ void f1() { id x = @protocol(P3); }
// RUN: grep OBJC_PROTOCOL_P5 %t | count 3
// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P5 %t | count 3
@protocol P5;
-void f2() { id x = @protocol(P5); } // This generates a forward
- // reference, which has to be
- // updated on the next line.
-@protocol P5 -im1; @end
+@interface UserP5<P5> // This generates a forward
+ // reference, which has to be
+ // updated on the next line.
+@end
+@protocol P5 -im1; @end
+@implementation UserP5
+
+- im1 { }
+
+@end
// Protocol reference following definition.
// RUN: grep OBJC_PROTOCOL_P6 %t | count 4
diff --git a/test/CodeGenObjC/protocols.m b/test/CodeGenObjC/protocols.m
index 6dadb11273dc..31965e171189 100644
--- a/test/CodeGenObjC/protocols.m
+++ b/test/CodeGenObjC/protocols.m
@@ -7,7 +7,8 @@ void p(const char*, ...);
-(int) conformsTo: (id) x;
@end
-@protocol P0;
+@protocol P0
+@end
@protocol P1
+(void) classMethodReq0;
diff --git a/test/CodeGenObjC/stret-lifetime.m b/test/CodeGenObjC/stret-lifetime.m
index d81ef34aeed4..837014d4e6ba 100644
--- a/test/CodeGenObjC/stret-lifetime.m
+++ b/test/CodeGenObjC/stret-lifetime.m
@@ -27,7 +27,7 @@ void foo(id o, id p) {
// CHECK: @llvm.lifetime.end
// ARC: br label
- // ARC: call void @objc_release
+ // ARC: call void @llvm.objc.release
// ARC: br label
// CHECK-NOT: call void @llvm.memset
diff --git a/test/CodeGenObjC/strong-in-c-struct.m b/test/CodeGenObjC/strong-in-c-struct.m
index 36e9049635f2..999b89dd60f5 100644
--- a/test/CodeGenObjC/strong-in-c-struct.m
+++ b/test/CodeGenObjC/strong-in-c-struct.m
@@ -125,7 +125,7 @@ void func(Strong *);
// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 24
// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
-// CHECK: call void @objc_storeStrong(i8** %[[V3]], i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V3]], i8* null)
// CHECK: ret void
// CHECK: define linkonce_odr hidden void @__destructor_8_s16(i8** %[[DST:.*]])
@@ -135,7 +135,7 @@ void func(Strong *);
// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 16
// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
-// CHECK: call void @objc_storeStrong(i8** %[[V3]], i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V3]], i8* null)
// CHECK: ret void
void test_constructor_destructor_StrongOuter(void) {
@@ -169,7 +169,7 @@ void test_constructor_destructor_StrongOuter(void) {
// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
-// CHECK: %[[V9:.*]] = call i8* @objc_retain(i8* %[[V8]])
+// CHECK: %[[V9:.*]] = call i8* @llvm.objc.retain(i8* %[[V8]])
// CHECK: store i8* %[[V9]], i8** %[[V4]], align 8
// CHECK: %[[V10:.*]] = bitcast i8** %[[V0]] to i8*
// CHECK: %[[V11:.*]] = getelementptr inbounds i8, i8* %[[V10]], i64 32
@@ -200,7 +200,7 @@ void test_constructor_destructor_StrongOuter(void) {
// CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 16
// CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8**
// CHECK: %[[V10:.*]] = load i8*, i8** %[[V9]], align 8
-// CHECK: %[[V11:.*]] = call i8* @objc_retain(i8* %[[V10]])
+// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retain(i8* %[[V10]])
// CHECK: store i8* %[[V11]], i8** %[[V6]], align 8
// CHECK: ret void
@@ -222,7 +222,7 @@ void test_copy_constructor_StrongOuter(StrongOuter *s) {
// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
-// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* %[[V8]])
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* %[[V8]])
void test_copy_assignment_StrongOuter(StrongOuter *d, StrongOuter *s) {
*d = *s;
@@ -283,7 +283,7 @@ void test_move_constructor_StrongOuter(void) {
// CHECK: store i8* null, i8** %[[V7]], align 8
// CHECK: %[[V9:.*]] = load i8*, i8** %[[V4]], align 8
// CHECK: store i8* %[[V8]], i8** %[[V4]], align 8
-// CHECK: call void @objc_release(i8* %[[V9]])
+// CHECK: call void @llvm.objc.release(i8* %[[V9]])
void test_move_assignment_StrongOuter(StrongOuter *p) {
*p = getStrongOuter();
@@ -363,7 +363,7 @@ void test_destructor_ignored_result(void) {
// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
// CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8
-// CHECK: %[[V3:.*]] = call i8* @objc_retainBlock(i8* %[[V2]])
+// CHECK: %[[V3:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V2]])
// CHECK: store i8* %[[V3]], i8** %[[V0]], align 8
// CHECK: ret void
@@ -382,10 +382,10 @@ void test_copy_constructor_StrongBlock(StrongBlock *s) {
// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
// CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8
-// CHECK: %[[V3:.*]] = call i8* @objc_retainBlock(i8* %[[V2]])
+// CHECK: %[[V3:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V2]])
// CHECK: %[[V4:.*]] = load i8*, i8** %[[V0]], align 8
// CHECK: store i8* %[[V3]], i8** %[[V0]], align 8
-// CHECK: call void @objc_release(i8* %[[V4]])
+// CHECK: call void @llvm.objc.release(i8* %[[V4]])
// CHECK: ret void
void test_copy_assignment_StrongBlock(StrongBlock *d, StrongBlock *s) {
@@ -398,7 +398,7 @@ void test_copy_assignment_StrongBlock(StrongBlock *d, StrongBlock *s) {
// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_sv8(
// CHECK: %[[V8:.*]] = load volatile i8*, i8** %{{.*}}, align 8
-// CHECK: %[[V9:.*]] = call i8* @objc_retain(i8* %[[V8]])
+// CHECK: %[[V9:.*]] = call i8* @llvm.objc.retain(i8* %[[V8]])
// CHECK: store volatile i8* %[[V9]], i8** %{{.*}}, align 8
void test_copy_constructor_StrongVolatile0(StrongVolatile *s) {
@@ -419,11 +419,11 @@ void test_copy_constructor_StrongVolatile1(Strong *s) {
// CHECK: call void @__destructor_8_s16(
// CHECK: ret void
-// CHECK: define internal void @__copy_helper_block_.1(i8*, i8*)
+// CHECK: define linkonce_odr hidden void @__copy_helper_block_8_32n13_8_8_t0w16_s16(i8*, i8*)
// CHECK: call void @__copy_constructor_8_8_t0w16_s16(
// CHECK: ret void
-// CHECK: define internal void @__destroy_helper_block_.2(
+// CHECK: define linkonce_odr hidden void @__destroy_helper_block_8_32n5_8_s16(
// CHECK: call void @__destructor_8_s16(
// CHECK: ret void
@@ -485,8 +485,39 @@ void test_constructor_destructor_StructArray(void) {
StructArray t;
}
+// Test that StructArray's field 'd' is copied before entering the loop.
+
+// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w8_AB8s24n4_t8w16_s24_AE(i8** %[[DST:.*]], i8** %[[SRC:.*]])
+// CHECK: entry:
+// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
+// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
+// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
+// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
+// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
+// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i64*
+// CHECK: %[[V3:.*]] = bitcast i8** %[[V1]] to i64*
+// CHECK: %[[V4:.*]] = load i64, i64* %[[V3]], align 8
+// CHECK: store i64 %[[V4]], i64* %[[V2]], align 8
+
+// CHECK: phi i8**
+// CHECK: phi i8**
+
+// CHECK: phi i8**
+// CHECK: phi i8**
+
+// CHECK-NOT: load i64, i64* %
+// CHECK-NOT: store i64 %
+// CHECK: call void @__copy_constructor_8_8_t0w16_s16(
+
+void test_copy_constructor_StructArray(StructArray a) {
+ StructArray t = a;
+}
+
// Check that IRGen copies the 9-bit bitfield emitting i16 load and store.
+// CHECK: define void @test_copy_constructor_Bitfield0(
+
// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_t8w2(
// CHECK: %[[V4:.*]] = bitcast i8** %{{.*}} to i8*
// CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8
diff --git a/test/CodeGenObjC/ubsan-check-debuglocs.m b/test/CodeGenObjC/ubsan-check-debuglocs.m
new file mode 100644
index 000000000000..d85c8e83e11a
--- /dev/null
+++ b/test/CodeGenObjC/ubsan-check-debuglocs.m
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -emit-llvm -fblocks -debug-info-kind=limited \
+// RUN: -fsanitize=nullability-return %s -o - | FileCheck %s
+
+// Check that santizer check calls have a !dbg location.
+// CHECK: call void {{.*}}@__ubsan_handle_nullability_return_v1_abort
+// CHECK-SAME: !dbg
+
+@protocol NSObject
+@end
+
+@interface NSObject<NSObject> {}
+@end
+
+#pragma clang assume_nonnull begin
+@interface NSString : NSObject
++ (instancetype)stringWithFormat:(NSString *)format, ...;
+@end
+
+@interface NSIndexPath : NSObject {}
+@end
+#pragma clang assume_nonnull end
+
+@interface B : NSObject
+@end
+id foo(NSIndexPath *indexPath) {
+ return [B withBlock:^{
+ return [NSString stringWithFormat:@"%ld",
+ (long)[indexPath indexAtPosition:1]];
+ }];
+}
diff --git a/test/CodeGenObjC/weak-in-c-struct.m b/test/CodeGenObjC/weak-in-c-struct.m
index b0f4c0851021..1b2d860fc3b5 100644
--- a/test/CodeGenObjC/weak-in-c-struct.m
+++ b/test/CodeGenObjC/weak-in-c-struct.m
@@ -40,7 +40,7 @@ void calleeWeak(Weak);
// ARM64: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8
// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
-// ARM64: call void @objc_destroyWeak(i8** %[[V3]])
+// ARM64: call void @llvm.objc.destroyWeak(i8** %[[V3]])
void test_constructor_destructor_Weak(void) {
Weak t;
@@ -67,7 +67,7 @@ void test_constructor_destructor_Weak(void) {
// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
-// ARM64: call void @objc_copyWeak(i8** %[[V7]], i8** %[[V10]])
+// ARM64: call void @llvm.objc.copyWeak(i8** %[[V7]], i8** %[[V10]])
void test_copy_constructor_Weak(Weak *s) {
Weak t = *s;
@@ -93,9 +93,9 @@ void test_copy_constructor_Weak(Weak *s) {
// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
-// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])
-// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])
-// ARM64: call void @objc_release(i8* %[[V11]])
+// ARM64: %[[V11:.*]] = call i8* @llvm.objc.loadWeakRetained(i8** %[[V10]])
+// ARM64: %[[V12:.*]] = call i8* @llvm.objc.storeWeak(i8** %[[V7]], i8* %[[V11]])
+// ARM64: call void @llvm.objc.release(i8* %[[V11]])
void test_copy_assignment_Weak(Weak *d, Weak *s) {
*d = *s;
@@ -121,7 +121,7 @@ void test_copy_assignment_Weak(Weak *d, Weak *s) {
// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
-// ARM64: call void @objc_moveWeak(i8** %[[V7]], i8** %[[V10]])
+// ARM64: call void @llvm.objc.moveWeak(i8** %[[V7]], i8** %[[V10]])
void test_move_constructor_Weak(void) {
__block Weak t;
@@ -148,10 +148,10 @@ void test_move_constructor_Weak(void) {
// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*
// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8
// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**
-// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])
-// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])
-// ARM64: call void @objc_destroyWeak(i8** %[[V10]])
-// ARM64: call void @objc_release(i8* %[[V11]])
+// ARM64: %[[V11:.*]] = call i8* @llvm.objc.loadWeakRetained(i8** %[[V10]])
+// ARM64: %[[V12:.*]] = call i8* @llvm.objc.storeWeak(i8** %[[V7]], i8* %[[V11]])
+// ARM64: call void @llvm.objc.destroyWeak(i8** %[[V10]])
+// ARM64: call void @llvm.objc.release(i8* %[[V11]])
void test_move_assignment_Weak(Weak *p) {
*p = getWeak();
diff --git a/test/CodeGenObjCXX/arc-attrs.mm b/test/CodeGenObjCXX/arc-attrs.mm
index 0b64d775660a..5ab7a69de215 100644
--- a/test/CodeGenObjCXX/arc-attrs.mm
+++ b/test/CodeGenObjCXX/arc-attrs.mm
@@ -15,7 +15,7 @@ void sanityTest() {
// CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]])
releaseObject(makeObject2());
- // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+ // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
// CHECK-NEXT: ret void
}
@@ -43,7 +43,7 @@ void templateTest() {
// CHECK-NEXT: call void @_Z14releaseObjectTIU8__strongP11objc_objectEvT_(i8* [[OBJ3]])
releaseObjectT(makeObject1());
- // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+ // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
// CHECK-NEXT: ret void
}
@@ -58,7 +58,7 @@ ForwardConsumed::ForwardConsumed(__attribute__((ns_consumed)) id x) {}
// CHECK-NOT: objc_retain
// CHECK: store i8* {{.*}}, i8** [[X:%.*]],
// CHECK-NOT: [[X]]
-// CHECK: call void @objc_storeStrong(i8** [[X]], i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
// CHECK: define void @_ZN15ForwardConsumedC1EP11objc_object(
// CHECK-NOT: objc_retain
@@ -66,4 +66,4 @@ ForwardConsumed::ForwardConsumed(__attribute__((ns_consumed)) id x) {}
// CHECK: [[T0:%.*]] = load i8*, i8** [[X]],
// CHECK-NEXT: store i8* null, i8** [[X]],
// CHECK-NEXT: call void @_ZN15ForwardConsumedC2EP11objc_object({{.*}}, i8* [[T0]])
-// CHECK: call void @objc_storeStrong(i8** [[X]], i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** [[X]], i8* null)
diff --git a/test/CodeGenObjCXX/arc-blocks.mm b/test/CodeGenObjCXX/arc-blocks.mm
index 3a75576681d8..ec0c12456aa1 100644
--- a/test/CodeGenObjCXX/arc-blocks.mm
+++ b/test/CodeGenObjCXX/arc-blocks.mm
@@ -1,9 +1,11 @@
// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -o - %s | FileCheck -check-prefix CHECK %s
// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -O1 -o - %s | FileCheck -check-prefix CHECK-O1 %s
+// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck -check-prefix CHECK-NOEXCP %s
// CHECK: [[A:.*]] = type { i64, [10 x i8*] }
-// CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 }
// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+// CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 }
+// CHECK: %[[STRUCT_TRIVIAL_INTERNAL:.*]] = type { i32 }
// CHECK: [[LAYOUT0:@.*]] = private unnamed_addr constant [3 x i8] c" 9\00"
@@ -18,6 +20,7 @@ namespace test0 {
void foo() {
__block A v;
+ ^{ (void)v; };
}
// CHECK-LABEL: define void @_ZN5test03fooEv()
// CHECK: [[V:%.*]] = alloca [[BYREF_A:%.*]], align 8
@@ -30,7 +33,8 @@ namespace test0 {
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7
// CHECK-NEXT: call void @_ZN5test01AC1Ev([[A]]* [[T0]])
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7
- // CHECK-NEXT: [[T1:%.*]] = bitcast [[BYREF_A]]* [[V]] to i8*
+ // CHECK: bitcast [[BYREF_A]]* [[V]] to i8*
+ // CHECK: [[T1:%.*]] = bitcast [[BYREF_A]]* [[V]] to i8*
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8)
// CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[T0]])
// CHECK-NEXT: ret void
@@ -51,38 +55,43 @@ namespace test0 {
// CHECK-NEXT: ret void
}
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_
+// CHECK-LABEL-O1: define linkonce_odr hidden void @__copy_helper_block_
+// CHECK-LABEL-O1: define linkonce_odr hidden void @__destroy_helper_block_
+
namespace test1 {
// Check that copy/dispose helper functions are exception safe.
-// CHECK-LABEL: define internal void @__copy_helper_block_(
-// CHECK: %[[BLOCK_SOURCE:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
-// CHECK: %[[BLOCK_DEST:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
+// CHECK: %[[BLOCK_SOURCE:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>*
+// CHECK: %[[BLOCK_DEST:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>*
-// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 6
-// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 6
+// CHECK: %[[V9:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 5
+// CHECK: %[[V10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 5
+// CHECK: %[[BLOCKCOPY_SRC2:.*]] = load i8*, i8** %[[V9]], align 8
+// CHECK: store i8* null, i8** %[[V10]], align 8
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V10]], i8* %[[BLOCKCOPY_SRC2]])
+
+// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 6
+// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 6
// CHECK: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 8
// CHECK: %[[V6:.*]] = bitcast i8** %[[V5]] to i8*
// CHECK: call void @_Block_object_assign(i8* %[[V6]], i8* %[[BLOCKCOPY_SRC]], i32 8)
-// CHECK: %[[V7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 7
-// CHECK: %[[V8:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 7
-// CHECK: call void @objc_copyWeak(i8** %[[V8]], i8** %[[V7]])
-
-// CHECK: %[[V9:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 5
-// CHECK: %[[V10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 5
-// CHECK: %[[BLOCKCOPY_SRC2:.*]] = load i8*, i8** %[[V9]], align 8
-// CHECK: store i8* null, i8** %[[V10]], align 8
-// CHECK: call void @objc_storeStrong(i8** %[[V10]], i8* %[[BLOCKCOPY_SRC2]])
+// CHECK: %[[V7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 7
+// CHECK: %[[V8:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 7
+// CHECK: call void @llvm.objc.copyWeak(i8** %[[V8]], i8** %[[V7]])
-// CHECK: %[[V11:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 8
-// CHECK: %[[V12:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 8
+// CHECK: %[[V11:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 8
+// CHECK: %[[V12:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 8
// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* %[[V12]], %[[STRUCT_TEST1_S0]]* dereferenceable(4) %[[V11]])
// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
// CHECK: [[INVOKE_CONT]]:
-// CHECK: %[[V13:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 9
-// CHECK: %[[V14:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 9
+// CHECK: %[[V13:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 9
+// CHECK: %[[V14:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 9
// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* %[[V14]], %[[STRUCT_TEST1_S0]]* dereferenceable(4) %[[V13]])
// CHECK: to label %[[INVOKE_CONT4:.*]] unwind label %[[LPAD3:.*]]
@@ -100,10 +109,10 @@ namespace test1 {
// CHECK: br label %[[EHCLEANUP]]
// CHECK: [[EHCLEANUP]]:
-// CHECK: call void @objc_storeStrong(i8** %[[V10]], i8* null)
-// CHECK: call void @objc_destroyWeak(i8** %[[V8]])
+// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V8]])
// CHECK: %[[V21:.*]] = load i8*, i8** %[[V5]], align 8
// CHECK: call void @_Block_object_dispose(i8* %[[V21]], i32 8)
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V10]], i8* null)
// CHECK: br label %[[EH_RESUME:.*]]
// CHECK: [[EH_RESUME]]:
@@ -112,16 +121,17 @@ namespace test1 {
// CHECK: [[TERMINATE_LPAD]]:
// CHECK: call void @__clang_call_terminate(
-// CHECK-O1-LABEL: define internal void @__copy_helper_block_(
-// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
-
-// CHECK: define internal void @__destroy_helper_block_(
-// CHECK: %[[BLOCK:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
-// CHECK: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 6
-// CHECK: %[[V3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 7
-// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 5
-// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 8
-// CHECK: %[[V6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 9
+// CHECK-O1-LABEL: define linkonce_odr hidden void @__copy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
+// CHECK-O1: tail call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release
+// CHECK-NOEXCP: define linkonce_odr hidden void @__copy_helper_block_8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
+
+// CHECK: define linkonce_odr hidden void @__destroy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
+// CHECK: %[[BLOCK:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>*
+// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 5
+// CHECK: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 6
+// CHECK: %[[V3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 7
+// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 8
+// CHECK: %[[V6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 9
// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V6]])
// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
@@ -130,15 +140,15 @@ namespace test1 {
// CHECK: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD1:.*]]
// CHECK: [[INVOKE_CONT2]]:
-// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* null)
-// CHECK: call void @objc_destroyWeak(i8** %[[V3]])
+// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V3]])
// CHECK: %[[V7:.*]] = load i8*, i8** %[[V2]], align 8
// CHECK: call void @_Block_object_dispose(i8* %[[V7]], i32 8)
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* null)
// CHECK: ret void
// CHECK: [[LPAD]]:
// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V5]])
-// CHECK: to label %[[INVOKE_CONT3:.*]] unwind label %[[TERMINATE_LPAD]]
+// CHECK: to label %[[INVOKE_CONT3:.*]] unwind label %[[TERMINATE_LPAD:.*]]
// CHECK: [[LPAD1]]
// CHECK: br label %[[EHCLEANUP:.*]]
@@ -147,11 +157,11 @@ namespace test1 {
// CHECK: br label %[[EHCLEANUP]]
// CHECK: [[EHCLEANUP]]:
-// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* null)
-// CHECK: call void @objc_destroyWeak(i8** %[[V3]])
+// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V3]])
// CHECK: %[[V14:.*]] = load i8*, i8** %[[V2]], align 8
// CHECK: call void @_Block_object_dispose(i8* %[[V14]], i32 8)
-// CHECK: br label %[[EH_RESUME]]
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* null)
+// CHECK: br label %[[EH_RESUME:.*]]
// CHECK: [[EH_RESUME]]:
// CHECK: resume { i8*, i32 }
@@ -159,9 +169,16 @@ namespace test1 {
// CHECK: [[TERMINATE_LPAD]]:
// CHECK: call void @__clang_call_terminate(
-// CHECK-O1-LABEL: define internal void @__destroy_helper_block_(
-// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
-// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
+// CHECK-O1-LABEL: define linkonce_odr hidden void @__destroy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
+// CHECK-O1: tail call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release
+// CHECK-O1: tail call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release
+// CHECK-NOEXCP: define linkonce_odr hidden void @__destroy_helper_block_8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
+
+namespace {
+struct TrivialInternal {
+ int a;
+};
+}
struct S0 {
S0();
@@ -177,6 +194,10 @@ void foo1() {
__weak id t1 = getObj();
id t2 = getObj();
S0 t3, t4;
- ^{ (void)t0; (void)t1; (void)t2; (void)t3; (void)t4; };
+ // Capturing a non-external type doesn't cause the copy/dispose helpers to be
+ // internal unless the captured type has a non-trivial copy constructor or
+ // destructor.
+ TrivialInternal t5;
+ ^{ (void)t0; (void)t1; (void)t2; (void)t3; (void)t4; (void)t5; };
}
}
diff --git a/test/CodeGenObjCXX/arc-constexpr.mm b/test/CodeGenObjCXX/arc-constexpr.mm
index 786e2cb8f2cc..42fafcf2a4a4 100644
--- a/test/CodeGenObjCXX/arc-constexpr.mm
+++ b/test/CodeGenObjCXX/arc-constexpr.mm
@@ -1,18 +1,51 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - -std=c++11 %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-runtime-has-weak -o - -std=c++11 %s | FileCheck %s
// CHECK: %[[TYPE:[a-z0-9]+]] = type opaque
// CHECK: @[[CFSTRING:[a-z0-9_]+]] = private global %struct.__NSConstantString_tag
+@class NSString;
-// CHECK: define void @_Z5test1v
+// CHECK-LABEL: define void @_Z5test1v
// CHECK: %[[ALLOCA:[A-Z]+]] = alloca %[[TYPE]]*
-// CHECK: %[[V0:[0-9]+]] = call i8* @objc_retain(i8* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]]
+// CHECK: %[[V0:[0-9]+]] = call i8* @llvm.objc.retain(i8* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]]
// CHECK: %[[V1:[0-9]+]] = bitcast i8* %[[V0]] to %[[TYPE]]*
// CHECK: store %[[TYPE]]* %[[V1]], %[[TYPE]]** %[[ALLOCA]]
// CHECK: %[[V2:[0-9]+]] = bitcast %[[TYPE]]** %[[ALLOCA]]
-// CHECK: call void @objc_storeStrong(i8** %[[V2]], i8* null)
-
-@class NSString;
-
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V2]], i8* null)
void test1() {
constexpr NSString *S = @"abc";
}
+
+// CHECK-LABEL: define void @_Z5test2v
+// CHECK: %[[CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[REF_CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[V0:[0-9]+]] = call i8* @llvm.objc.retain(i8* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]]
+// CHECK-NEXT: %[[V1:[0-9]+]] = bitcast i8* %[[V0]] to %[[TYPE]]*
+// CHECK-NEXT: store %[[TYPE]]* %[[V1]], %[[TYPE]]** %[[CONST]]
+// CHECK: %[[V2:[0-9]+]] = call i8* @llvm.objc.retain(i8* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]]
+// CHECK-NEXT: %[[V3:[0-9]+]] = bitcast i8* %[[V2]] to %[[TYPE]]*
+// CHECK-NEXT: store %[[TYPE]]* %[[V3]], %[[TYPE]]** %[[REF_CONST]]
+// CHECK: %[[V4:[0-9]+]] = bitcast %[[TYPE]]** %[[REF_CONST]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* null)
+// CHECK: %[[V5:[0-9]+]] = bitcast %[[TYPE]]** %[[CONST]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** %[[V5]], i8* null)
+void test2() {
+ constexpr NSString *Const = @"abc";
+ // In IR RefConst should be initialized with Const initializer instead of
+ // reading from variable.
+ NSString* RefConst = Const;
+}
+
+// CHECK-LABEL: define void @_Z5test3v
+// CHECK: %[[WEAK_CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[REF_WEAK_CONST:[a-zA-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[V0:[0-9]+]] = bitcast %[[TYPE]]** %[[WEAK_CONST]]
+// CHECK-NEXT: %[[V1:[0-9]+]] = call i8* @llvm.objc.initWeak(i8** %[[V0]], i8* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]]
+// CHECK: store %[[TYPE]]* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]] to %[[TYPE]]*), %[[TYPE]]** %[[REF_WEAK_CONST]]
+// CHECK: %[[V2:[0-9]+]] = bitcast %[[TYPE]]** %[[REF_WEAK_CONST]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** %[[V2]], i8* null)
+// CHECK: %[[V3:[0-9]+]] = bitcast %[[TYPE]]** %[[WEAK_CONST]]
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** %[[V3]])
+void test3() {
+ __weak constexpr NSString *WeakConst = @"abc";
+ NSString* RefWeakConst = WeakConst;
+}
diff --git a/test/CodeGenObjCXX/arc-cxx11-init-list.mm b/test/CodeGenObjCXX/arc-cxx11-init-list.mm
index af607654e159..2c70f64d2043 100644
--- a/test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ b/test/CodeGenObjCXX/arc-cxx11-init-list.mm
@@ -29,14 +29,14 @@ extern "C" void single() { function({ [I new] }); }
// CHECK: [[INSTANCE:%.*]] = {{.*}} call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
// CHECK-NEXT: [[CAST:%.*]] = bitcast [{{[0-9]+}} x %0*]* %{{.*}} to i8**
// CHECK-NEXT: store i8* [[INSTANCE]], i8** [[CAST]],
-// CHECK: call void @objc_release(i8* {{.*}})
+// CHECK: call void @llvm.objc.release(i8* {{.*}})
extern "C" void multiple() { function({ [I new], [I new] }); }
// CHECK: [[INSTANCE:%.*]] = {{.*}} call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
// CHECK-NEXT: [[CAST:%.*]] = bitcast [{{[0-9]+}} x %0*]* %{{.*}} to i8**
// CHECK-NEXT: store i8* [[INSTANCE]], i8** [[CAST]],
-// CHECK: call void @objc_release(i8* {{.*}})
+// CHECK: call void @llvm.objc.release(i8* {{.*}})
std::initializer_list<id> foo1() {
return {@"str0", @"str1"};
@@ -58,11 +58,11 @@ extern "C" void extended() {
// CHECK: [[INSTANCE:%.*]] = {{.*}} call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
// CHECK: {{.*}} call void @_Z8externalv()
-// CHECK: {{.*}} call void @objc_release(i8* {{.*}})
+// CHECK: {{.*}} call void @llvm.objc.release(i8* {{.*}})
std::initializer_list<I *> il = { [I new] };
-// CHECK: [[POOL:%.*]] = {{.*}} call i8* @objc_autoreleasePoolPush()
+// CHECK: [[POOL:%.*]] = {{.*}} call i8* @llvm.objc.autoreleasePoolPush()
// CHECK: [[INSTANCE:%.*]] = {{.*}} call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}})
// CHECK-NEXT: store i8* [[INSTANCE]], i8** bitcast ([1 x %0*]* @_ZGR2il_ to i8**)
-// CHECK: {{.*}} call void @objc_autoreleasePoolPop(i8* [[POOL]])
+// CHECK: {{.*}} call void @llvm.objc.autoreleasePoolPop(i8* [[POOL]])
diff --git a/test/CodeGenObjCXX/arc-exceptions.mm b/test/CodeGenObjCXX/arc-exceptions.mm
index 3d5046135078..94e1374c838f 100644
--- a/test/CodeGenObjCXX/arc-exceptions.mm
+++ b/test/CodeGenObjCXX/arc-exceptions.mm
@@ -17,11 +17,11 @@ void test0(void) {
// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch(
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW:#[0-9]+]]
+// CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retain(i8* [[T2]]) [[NUW:#[0-9]+]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null) [[NUW]]
// CHECK-NEXT: call void @objc_end_catch() [[NUW]]
void test1_helper(void);
@@ -38,9 +38,9 @@ void test1(void) {
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[T0]]) [[NUW]]
// CHECK-NEXT: call void @objc_end_catch() [[NUW]]
void test2_helper(void);
@@ -56,11 +56,11 @@ void test2(void) {
// CHECK: [[T0:%.*]] = call i8* @__cxa_begin_catch(
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW]]
+// CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retain(i8* [[T2]]) [[NUW]]
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[T0]], i8* null) [[NUW]]
// CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
void test3_helper(void);
@@ -77,9 +77,9 @@ void test3(void) {
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]]
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[T0]]) [[NUW]]
// CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
namespace test4 {
@@ -112,11 +112,11 @@ namespace test4 {
// CHECK-NEXT: br label
// CHECK: [[AFTER:%.*]] = phi i8** [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
// CHECK-NEXT: [[ELT]] = getelementptr inbounds i8*, i8** [[AFTER]], i64 -1
- // CHECK-NEXT: call void @objc_storeStrong(i8** [[ELT]], i8* null) [[NUW]]
+ // CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[ELT]], i8* null) [[NUW]]
// CHECK-NEXT: [[DONE:%.*]] = icmp eq i8** [[ELT]], [[ARRAYBEGIN]]
// CHECK-NEXT: br i1 [[DONE]],
// - Next, destroy single.
- // CHECK: call void @objc_storeStrong(i8** [[SINGLE]], i8* null) [[NUW]]
+ // CHECK: call void @llvm.objc.storeStrong(i8** [[SINGLE]], i8* null) [[NUW]]
// CHECK: br label
// CHECK: resume
}
diff --git a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm
index 0a575c7697cb..5a5cb42067d9 100644
--- a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm
+++ b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm
@@ -5,8 +5,8 @@ void test0(id x) {
test0_helper([=]() { return x; });
// CHECK-LABEL: define internal i8* @___Z5test0P11objc_object_block_invoke
// CHECK: [[T0:%.*]] = call i8* @"_ZZ5test0P11objc_objectENK3$_0clEv"
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T2:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T1]])
// CHECK-NEXT: ret i8* [[T2]]
}
@@ -28,8 +28,8 @@ void test1() {
test1_helper([](){ return test1_rv; });
// CHECK-LABEL: define internal i8* @"_ZZ5test1vEN3$_18__invokeEv"
// CHECK: [[T0:%.*]] = call i8* @"_ZZ5test1vENK3$_1clEv"
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T2:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T1]])
// CHECK-NEXT: ret i8* [[T2]]
}
diff --git a/test/CodeGenObjCXX/arc-globals.mm b/test/CodeGenObjCXX/arc-globals.mm
index a03ac9948bd3..d5116ee96c93 100644
--- a/test/CodeGenObjCXX/arc-globals.mm
+++ b/test/CodeGenObjCXX/arc-globals.mm
@@ -7,21 +7,21 @@ id getObject();
// CHECK-LABEL: define internal void @__cxx_global_var_init
// CHECK: call i8* @_Z9getObjectv
-// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+// CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
// CHECK-NEXT: {{store i8*.*@global_obj}}
// CHECK-NEXT: ret void
id global_obj = getObject();
// CHECK-LABEL: define internal void @__cxx_global_var_init
// CHECK: call i8* @_Z9getObjectv
-// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+// CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
// CHECK-NEXT: {{store i8*.*@global_obj2}}
// CHECK-NEXT: ret void
id global_obj2 = getObject();
// CHECK-LABEL: define internal void @_GLOBAL__sub_I_arc_globals.mm
-// CHECK: call i8* @objc_autoreleasePoolPush()
+// CHECK: call i8* @llvm.objc.autoreleasePoolPush()
// CHECK-NEXT: call void @__cxx_global_var_init
// CHECK-NEXT: call void @__cxx_global_var_init.1
-// CHECK-NEXT: call void @objc_autoreleasePoolPop(
+// CHECK-NEXT: call void @llvm.objc.autoreleasePoolPop(
// CHECK-NEXT: ret void
diff --git a/test/CodeGenObjCXX/arc-indirect.mm b/test/CodeGenObjCXX/arc-indirect.mm
index 6982bac04118..49fdc51e4669 100644
--- a/test/CodeGenObjCXX/arc-indirect.mm
+++ b/test/CodeGenObjCXX/arc-indirect.mm
@@ -19,4 +19,4 @@ struct S {
// CHECK-DARWIN: define internal void @"\01-[C object:struct:]"(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca)
// CHECK: %obj = getelementptr inbounds <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>, <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* %0, i32 0, i32 2
// CHECK: %[[INSTANCE:[0-9]+]] = load i8*, i8** %obj, align 4
-// CHECK: call void @objc_storeStrong(i8** %obj, i8* %[[INSTANCE]])
+// CHECK: call void @llvm.objc.storeStrong(i8** %obj, i8* %[[INSTANCE]])
diff --git a/test/CodeGenObjCXX/arc-list-init-destruct.mm b/test/CodeGenObjCXX/arc-list-init-destruct.mm
new file mode 100644
index 000000000000..09a66458c260
--- /dev/null
+++ b/test/CodeGenObjCXX/arc-list-init-destruct.mm
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -std=c++1z -fobjc-arc -fobjc-exceptions -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: %[[V0:.*]] = type opaque
+// CHECK: %[[STRUCT_CLASS1:.*]] = type { %[[V0]]* }
+
+@interface Class0;
+@end
+
+struct Class1 {
+ Class0 *f;
+};
+
+struct Container {
+ Class1 a;
+ bool b;
+};
+
+bool getBool() {
+ return false;
+}
+
+Class0 *g;
+
+// CHECK: define {{.*}} @_Z4testv()
+// CHECK: invoke zeroext i1 @_Z7getBoolv()
+// CHECK: landingpad { i8*, i32 }
+// CHECK: call void @_ZN6Class1D1Ev(%[[STRUCT_CLASS1]]* %{{.*}})
+// CHECK: br label
+
+// CHECK: define linkonce_odr void @_ZN6Class1D1Ev(
+
+Container test() {
+ return {{g}, getBool()};
+}
diff --git a/test/CodeGenObjCXX/arc-move.mm b/test/CodeGenObjCXX/arc-move.mm
index def2cea95647..a43b9bc60440 100644
--- a/test/CodeGenObjCXX/arc-move.mm
+++ b/test/CodeGenObjCXX/arc-move.mm
@@ -6,7 +6,7 @@ void simple_move(__strong id &x, __strong id &y) {
// CHECK: store i8* null
// CHECK: = load i8*, i8**
// CHECK: store i8*
- // CHECK-NEXT: call void @objc_release
+ // CHECK-NEXT: call void @llvm.objc.release
x = static_cast<__strong id&&>(y);
// CHECK-NEXT: ret void
}
@@ -39,7 +39,7 @@ void library_move(__strong id &x, __strong id &y) {
// CHECK: load i8**, i8***
// CHECK-NEXT: load i8*, i8**
// CHECK-NEXT: store i8*
- // CHECK-NEXT: call void @objc_release
+ // CHECK-NEXT: call void @llvm.objc.release
// CHECK-NEXT: ret void
x = move(y);
}
@@ -66,7 +66,7 @@ void library_move(__strong id &y) {
// CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[IPTR2]])
// CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[X]]
- // CHECK-NEXT: call void @objc_release(i8* [[OBJ]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[OBJ]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
@@ -77,9 +77,9 @@ void const_move(const __strong id &x) {
// CHECK: [[Y:%.*]] = alloca i8*,
// CHECK: [[X:%.*]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongKP11objc_objectEON16remove_referenceIT_E4typeEOS5_(
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
id y = move(x);
}
diff --git a/test/CodeGenObjCXX/arc-new-delete.mm b/test/CodeGenObjCXX/arc-new-delete.mm
index 9fb57819901f..0f66056be646 100644
--- a/test/CodeGenObjCXX/arc-new-delete.mm
+++ b/test/CodeGenObjCXX/arc-new-delete.mm
@@ -8,8 +8,8 @@ typedef __weak id weak_id;
void test_new(id invalue) {
// CHECK: [[INVALUEADDR:%.*]] = alloca i8*
// UNOPT-NEXT: store i8* null, i8** [[INVALUEADDR]]
- // UNOPT-NEXT: call void @objc_storeStrong(i8** [[INVALUEADDR]], i8* [[INVALUE:%.*]])
- // OPT-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[INVALUE:%.*]])
+ // UNOPT-NEXT: call void @llvm.objc.storeStrong(i8** [[INVALUEADDR]], i8* [[INVALUE:%.*]])
+ // OPT-NEXT: [[T0:%.*]] = call i8* @llvm.objc.retain(i8* [[INVALUE:%.*]])
// OPT-NEXT: store i8* [[T0]], i8** [[INVALUEADDR]]
// CHECK: call i8* @_Znwm
@@ -19,7 +19,7 @@ void test_new(id invalue) {
// CHECK: call i8* @_Znwm
// CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}}
// UNOPT-NEXT: store i8* null, i8**
- // OPT-NEXT: call i8* @objc_initWeak(i8** {{.*}}, i8* null)
+ // OPT-NEXT: call i8* @llvm.objc.initWeak(i8** {{.*}}, i8* null)
new weak_id;
// CHECK: call i8* @_Znwm
@@ -29,20 +29,20 @@ void test_new(id invalue) {
// CHECK: call i8* @_Znwm
// CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}}
// UNOPT-NEXT: store i8* null, i8**
- // OPT-NEXT: call i8* @objc_initWeak(i8** {{.*}}, i8* null)
+ // OPT-NEXT: call i8* @llvm.objc.initWeak(i8** {{.*}}, i8* null)
new __weak id;
// CHECK: call i8* @_Znwm
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
// CHECK: store i8*
new __strong id(invalue);
// CHECK: call i8* @_Znwm
- // CHECK: call i8* @objc_initWeak
+ // CHECK: call i8* @llvm.objc.initWeak
new __weak id(invalue);
- // UNOPT: call void @objc_storeStrong
- // OPT: call void @objc_release
+ // UNOPT: call void @llvm.objc.storeStrong
+ // OPT: call void @llvm.objc.release
// CHECK: ret void
}
@@ -63,13 +63,13 @@ void test_array_new() {
// CHECK-LABEL: define void @_Z11test_deletePU8__strongP11objc_objectPU6__weakS0_
void test_delete(__strong id *sptr, __weak id *wptr) {
// CHECK: br i1
- // UNOPT: call void @objc_storeStrong(i8** {{.*}}, i8* null)
+ // UNOPT: call void @llvm.objc.storeStrong(i8** {{.*}}, i8* null)
// OPT: load i8*, i8**
- // OPT-NEXT: call void @objc_release
+ // OPT-NEXT: call void @llvm.objc.release
// CHECK: call void @_ZdlPv
delete sptr;
- // CHECK: call void @objc_destroyWeak
+ // CHECK: call void @llvm.objc.destroyWeak
// CHECK: call void @_ZdlPv
delete wptr;
@@ -84,9 +84,9 @@ void test_array_delete(__strong id *sptr, __weak id *wptr) {
// CHECK-NEXT: icmp eq i8** [[BEGIN]], [[END]]
// CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]],
// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8*, i8** [[PAST]], i64 -1
- // UNOPT-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null)
+ // UNOPT-NEXT: call void @llvm.objc.storeStrong(i8** [[CUR]], i8* null)
// OPT-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]]
- // OPT-NEXT: objc_release(i8* [[T0]])
+ // OPT-NEXT: llvm.objc.release(i8* [[T0]])
// CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK: call void @_ZdaPv
delete [] sptr;
@@ -97,7 +97,7 @@ void test_array_delete(__strong id *sptr, __weak id *wptr) {
// CHECK-NEXT: icmp eq i8** [[BEGIN]], [[END]]
// CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]],
// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8*, i8** [[PAST]], i64 -1
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[CUR]])
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[CUR]])
// CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK: call void @_ZdaPv
delete [] wptr;
diff --git a/test/CodeGenObjCXX/arc-pseudo-destructors.mm b/test/CodeGenObjCXX/arc-pseudo-destructors.mm
index b79d9a3447b0..191712d79c11 100644
--- a/test/CodeGenObjCXX/arc-pseudo-destructors.mm
+++ b/test/CodeGenObjCXX/arc-pseudo-destructors.mm
@@ -4,18 +4,18 @@
void test_objc_object_pseudo_dtor(__strong id *ptr, __weak id *wptr) {
// CHECK: load i8**, i8***
// CHECK-NEXT: load i8*, i8**
- // CHECK-NEXT: call void @objc_release
+ // CHECK-NEXT: call void @llvm.objc.release
ptr->~id();
- // CHECK: call void @objc_destroyWeak(i8** {{%.*}})
+ // CHECK: call void @llvm.objc.destroyWeak(i8** {{%.*}})
wptr->~id();
// CHECK: load i8**, i8***
// CHECK-NEXT: load i8*, i8**
- // CHECK-NEXT: call void @objc_release
+ // CHECK-NEXT: call void @llvm.objc.release
(*ptr).~id();
- // CHECK: call void @objc_destroyWeak(i8** {{%.*}})
+ // CHECK: call void @llvm.objc.destroyWeak(i8** {{%.*}})
(*wptr).~id();
// CHECK: ret void
}
diff --git a/test/CodeGenObjCXX/arc-references.mm b/test/CodeGenObjCXX/arc-references.mm
index 983b211dfbfa..aa0b85f2a050 100644
--- a/test/CodeGenObjCXX/arc-references.mm
+++ b/test/CodeGenObjCXX/arc-references.mm
@@ -10,17 +10,17 @@ void callee();
// CHECK-LABEL: define void @_Z5test0v()
void test0() {
// CHECK: call i8* @_Z9getObjectv
- // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
const __strong id &ref1 = getObject();
// CHECK: call void @_Z6calleev
callee();
// CHECK: call i8* @_Z9getObjectv
- // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
- // CHECK-NEXT: call i8* @objc_autorelease
+ // CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
+ // CHECK-NEXT: call i8* @llvm.objc.autorelease
const __autoreleasing id &ref2 = getObject();
// CHECK: call void @_Z6calleev
callee();
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: ret
}
@@ -39,12 +39,12 @@ typedef __strong id strong_id;
//CHECK: define void @_Z5test3v
void test3() {
// CHECK: [[REF:%.*]] = alloca i8**, align 8
- // CHECK: call i8* @objc_initWeak
+ // CHECK: call i8* @llvm.objc.initWeak
// CHECK-NEXT: store i8**
const __weak id &ref = strong_id();
// CHECK-NEXT: call void @_Z6calleev()
callee();
- // CHECK-NEXT: call void @objc_destroyWeak
+ // CHECK-NEXT: call void @llvm.objc.destroyWeak
// CHECK-NEXT: [[PTR:%.*]] = bitcast i8*** [[REF]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTR]])
// CHECK-NEXT: ret void
@@ -52,11 +52,11 @@ void test3() {
// CHECK-LABEL: define void @_Z5test4RU8__strongP11objc_object
void test4(__strong id &x) {
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
__strong A* const &ar = x;
// CHECK: store i32 17, i32*
int i = 17;
- // CHECK: call void @objc_release(
+ // CHECK: call void @llvm.objc.release(
// CHECK: ret void
}
@@ -66,14 +66,14 @@ void sink(__strong A* &&);
void test5(__strong id &x) {
// CHECK: [[REFTMP:%.*]] = alloca {{%.*}}*, align 8
// CHECK: [[I:%.*]] = alloca i32, align 4
- // CHECK: [[OBJ_ID:%.*]] = call i8* @objc_retain(
+ // CHECK: [[OBJ_ID:%.*]] = call i8* @llvm.objc.retain(
// CHECK-NEXT: [[OBJ_A:%.*]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]*
// CHECK-NEXT: store [[A]]* [[OBJ_A]], [[A]]** [[REFTMP:%[a-zA-Z0-9]+]]
// CHECK-NEXT: call void @_Z4sinkOU8__strongP1A
sink(x);
// CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = load [[A]]*, [[A]]** [[REFTMP]]
// CHECK-NEXT: [[OBJ_ID:%[a-zA-Z0-9]+]] = bitcast [[A]]* [[OBJ_A]] to i8*
- // CHECK-NEXT: call void @objc_release
+ // CHECK-NEXT: call void @llvm.objc.release
// CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[IPTR1]])
// CHECK-NEXT: store i32 17, i32
@@ -85,7 +85,7 @@ void test5(__strong id &x) {
// CHECK-LABEL: define internal void @__cxx_global_var_init(
// CHECK: call i8* @_Z9getObjectv
-// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+// CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
const __strong id &global_ref = getObject();
// Note: we intentionally don't release the object.
diff --git a/test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm b/test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm
index c4ab34ea0e8b..fa9b4219f54a 100644
--- a/test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm
+++ b/test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm
@@ -15,8 +15,8 @@ void foo() {
// CHECK: [[T0:%.*]] = load {{%.*}} {{%.*}}, align 8
// CHECK: [[T1:%.*]] = bitcast {{%.*}} [[T0]] to i8*
-// call i8* @objc_retainAutorelease(i8* [[T1]]) nounwind
+// call i8* @llvm.objc.retainAutorelease(i8* [[T1]]) nounwind
// CHECK: [[T2:%.*]] = load {{%.*}} {{%.*}}, align 8
// CHECK: [[T3:%.*]] = bitcast {{%.*}} [[T2]] to i8*
-// call i8* @objc_retainAutorelease(i8* [[T3]]) nounwind
+// call i8* @llvm.objc.retainAutorelease(i8* [[T3]]) nounwind
diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm
index d620187d7017..04ffbbe02152 100644
--- a/test/CodeGenObjCXX/arc-special-member-functions.mm
+++ b/test/CodeGenObjCXX/arc-special-member-functions.mm
@@ -91,7 +91,7 @@ void test_ObjCMember_copy_assign(ObjCMember m1, ObjCMember m2) {
// Implicitly-generated copy assignment operator for ObjCMember
// CHECK: {{define linkonce_odr.*@_ZN10ObjCMemberaSERKS_}}
-// CHECK: call void @objc_storeStrong
+// CHECK: call void @llvm.objc.storeStrong
// CHECK: ret
// CHECK-LABEL: define void @_Z47test_ObjCArrayMember_default_construct_destructv
@@ -120,7 +120,7 @@ void test_ObjCArrayMember_copy_assign(ObjCArrayMember m1, ObjCArrayMember m2) {
// Implicitly-generated copy assignment operator for ObjCArrayMember
// CHECK: {{define linkonce_odr.*@_ZN15ObjCArrayMemberaSERKS_}}
-// CHECK: call void @objc_storeStrong
+// CHECK: call void @llvm.objc.storeStrong
// CHECK-NEXT: br label
// CHECK: ret
@@ -155,13 +155,13 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// CHECK: [[T0:%.*]] = getelementptr inbounds [[T:%.*]], [[T:%.*]]* {{%.*}}, i32 0, i32 0
// CHECK-NEXT: [[T1:%.*]] = load i32 (i32)*, i32 (i32)** [[T0]], align 8
// CHECK-NEXT: [[T2:%.*]] = bitcast i32 (i32)* [[T1]] to i8*
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainBlock(i8* [[T2]])
+// CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T2]])
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i32 (i32)*
// CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[T]], [[T]]* {{%.*}}, i32 0, i32 0
// CHECK-NEXT: [[T6:%.*]] = load i32 (i32)*, i32 (i32)** [[T5]], align 8
// CHECK-NEXT: store i32 (i32)* [[T4]], i32 (i32)** [[T5]]
// CHECK-NEXT: [[T7:%.*]] = bitcast i32 (i32)* [[T6]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T7]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T7]])
// CHECK-NEXT: ret
// Check that the Weak object passed to this constructor is not destructed after
@@ -179,13 +179,13 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// Implicitly-generated destructor for ObjCMember
// CHECK-LABEL: define linkonce_odr void @_ZN10ObjCMemberD2Ev
-// CHECK: call void @objc_storeStrong
+// CHECK: call void @llvm.objc.storeStrong
// CHECK: ret void
// Implicitly-generated copy constructor for ObjCMember
// CHECK-LABEL: define linkonce_odr void @_ZN10ObjCMemberC2ERKS_
// CHECK-NOT: objc_release
-// CHECK: call i8* @objc_retain
+// CHECK: call i8* @llvm.objc.retain
// CHECK-NEXT: store i8*
// CHECK-NEXT: ret void
@@ -201,14 +201,14 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// CHECK-NEXT: br label
// CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8*, i8** [[PAST]], i64 -1
-// CHECK-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null)
+// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[CUR]], i8* null)
// CHECK-NEXT: [[T1:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
// CHECK-NEXT: br i1 [[T1]],
// CHECK: ret void
// Implicitly-generated copy constructor for ObjCArrayMember
// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCArrayMemberC2ERKS_
-// CHECK: call i8* @objc_retain
+// CHECK: call i8* @llvm.objc.retain
// CHECK-NEXT: store i8*
// CHECK: br i1
// CHECK: ret
@@ -220,11 +220,11 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// Implicitly-generated destructor for ObjCBlockMember
// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCBlockMemberD2Ev
-// CHECK: call void @objc_storeStrong(i8*
+// CHECK: call void @llvm.objc.storeStrong(i8*
// CHECK: ret
// Implicitly-generated copy constructor for ObjCBlockMember
// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCBlockMemberC2ERKS_
-// CHECK: call i8* @objc_retainBlock
+// CHECK: call i8* @llvm.objc.retainBlock
// CHECK: ret
diff --git a/test/CodeGenObjCXX/arc-weak.mm b/test/CodeGenObjCXX/arc-weak.mm
index 8fd03379aa69..cb1bc95c93bd 100644
--- a/test/CodeGenObjCXX/arc-weak.mm
+++ b/test/CodeGenObjCXX/arc-weak.mm
@@ -15,9 +15,9 @@ void test0(__weak B **src) {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]**
// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8**
-// CHECK-NEXT: call void @objc_copyWeak(i8** [[T2]], i8** [[T3]])
+// CHECK-NEXT: call void @llvm.objc.copyWeak(i8** [[T2]], i8** [[T3]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8**
-// CHECK: call void @objc_destroyWeak(i8** [[T0]])
+// CHECK: call void @llvm.objc.destroyWeak(i8** [[T0]])
void test1(__weak B **src) {
__weak A *dest = static_cast<__weak B*&&>(*src);
@@ -29,6 +29,6 @@ void test1(__weak B **src) {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]**
// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8**
-// CHECK-NEXT: call void @objc_moveWeak(i8** [[T2]], i8** [[T3]])
+// CHECK-NEXT: call void @llvm.objc.moveWeak(i8** [[T2]], i8** [[T3]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8**
-// CHECK: call void @objc_destroyWeak(i8** [[T0]])
+// CHECK: call void @llvm.objc.destroyWeak(i8** [[T0]])
diff --git a/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm
index 5e66206ad547..e32c1f89215f 100644
--- a/test/CodeGenObjCXX/arc.mm
+++ b/test/CodeGenObjCXX/arc.mm
@@ -20,21 +20,21 @@ void test0(__weak id *wp, __weak volatile id *wvp) {
// TODO: in the non-volatile case, we do not need to be reloading.
// CHECK: [[T0:%.*]] = call i8* @_Z12test0_helperv()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
- // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retain(i8* [[T3]])
+ // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]])
+ // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retain(i8* [[T3]])
// CHECK-NEXT: store i8* [[T4]], i8**
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
id x = *wp = test0_helper();
// CHECK: [[T0:%.*]] = call i8* @_Z12test0_helperv()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
- // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T2]])
+ // CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]])
+ // CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T2]])
// CHECK-NEXT: store i8* [[T4]], i8**
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
id y = *wvp = test0_helper();
}
@@ -69,7 +69,7 @@ void test34(int cond) {
// CHECK-NEXT: store i8* null, i8** [[STRONG]]
// CHECK-NEXT: [[WEAKP:%.*]] = bitcast i8** [[WEAK]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[WEAKP]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)
+ // CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[WEAK]], i8* null)
// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
// CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0
@@ -85,11 +85,11 @@ void test34(int cond) {
// CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
// CHECK-NEXT: br i1 [[T0]],
// CHECK: [[T0:%.*]] = load i8*, i8** [[TEMP1]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
- // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[W0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retain(i8* [[T0]])
+ // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[W0]])
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[ARG]]
// CHECK-NEXT: store i8* [[T1]], i8** [[ARG]]
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+ // CHECK-NEXT: call void @llvm.objc.release(i8* [[T2]])
// CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = load i32, i32* [[COND]]
@@ -99,7 +99,7 @@ void test34(int cond) {
// CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]]
// CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]]
// CHECK-NEXT: br i1 [[T0]],
- // CHECK: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[ARG]])
+ // CHECK: [[T0:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[ARG]])
// CHECK-NEXT: store i8* [[T0]], i8** [[CONDCLEANUPSAVE]]
// CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]]
// CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]]
@@ -108,10 +108,10 @@ void test34(int cond) {
// CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
// CHECK-NEXT: br i1 [[T0]],
// CHECK: [[T0:%.*]] = load i8*, i8** [[TEMP2]]
- // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]])
+ // CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[ARG]], i8* [[T0]])
// CHECK-NEXT: br label
- // CHECK: call void @objc_destroyWeak(i8** [[WEAK]])
+ // CHECK: call void @llvm.objc.destroyWeak(i8** [[WEAK]])
// CHECK: ret void
}
@@ -126,36 +126,36 @@ struct Test35_Helper {
void test35(Test35_Helper x0, Test35_Helper *x0p) {
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject1Ev
- // CHECK-NOT: call i8* @objc_retain
+ // CHECK-NOT: call i8* @llvm.objc.retain
id obj1 = Test35_Helper::makeObject1();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev
- // CHECK-NOT: call i8* @objc_retain
+ // CHECK-NOT: call i8* @llvm.objc.retain
id obj2 = x0.makeObject2();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev
- // CHECK-NOT: call i8* @objc_retain
+ // CHECK-NOT: call i8* @llvm.objc.retain
id obj3 = x0p->makeObject2();
id (Test35_Helper::*pmf)() __attribute__((ns_returns_retained))
= &Test35_Helper::makeObject2;
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
- // CHECK-NOT: call i8* @objc_retain
+ // CHECK-NOT: call i8* @llvm.objc.retain
id obj4 = (x0.*pmf)();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
- // CHECK-NOT: call i8* @objc_retain
+ // CHECK-NOT: call i8* @llvm.objc.retain
id obj5 = (x0p->*pmf)();
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}
@@ -164,36 +164,36 @@ void test35(Test35_Helper x0, Test35_Helper *x0p) {
void test35b(Test35_Helper x0, Test35_Helper *x0p) {
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject3Ev
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
id obj1 = Test35_Helper::makeObject3();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
id obj2 = x0.makeObject4();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
id obj3 = x0p->makeObject4();
id (Test35_Helper::*pmf)() = &Test35_Helper::makeObject4;
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
id obj4 = (x0.*pmf)();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
- // CHECK: call i8* @objc_retain
+ // CHECK: call i8* @llvm.objc.retain
id obj5 = (x0p->*pmf)();
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}
@@ -201,10 +201,10 @@ void test35b(Test35_Helper x0, Test35_Helper *x0p) {
// rdar://problem/9603128
// CHECK-LABEL: define i8* @_Z6test36P11objc_object(
id test36(id z) {
- // CHECK: objc_retain
- // CHECK: objc_retain
- // CHECK: objc_release
- // CHECK: objc_autoreleaseReturnValue
+ // CHECK: llvm.objc.retain
+ // CHECK: llvm.objc.retain
+ // CHECK: llvm.objc.release
+ // CHECK: llvm.objc.autoreleaseReturnValue
return z;
}
@@ -224,7 +224,7 @@ template void test37<Test37>(Test37 *a);
// CHECK-LABEL: define weak_odr void @_Z6test37I6Test37EvPT_(
// CHECK: [[T0:%.*]] = call [[NSARRAY]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[NSARRAY]]* (i8*, i8*)*)(
// CHECK-NEXT: [[T1:%.*]] = bitcast [[NSARRAY]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[NSARRAY]]*
// Make sure it's not immediately released before starting the iteration.
@@ -242,7 +242,7 @@ template void test37<Test37>(Test37 *a);
// This bitcast is for the final release.
// CHECK: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.release(i8* [[T0]])
template<typename T>
void send_release() {
@@ -252,10 +252,10 @@ void send_release() {
// CHECK-LABEL: define weak_odr void @_Z12send_releaseIiEvv(
// CHECK: call %0* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
// CHECK-NEXT: bitcast
-// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
+// CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue
// CHECK-NEXT: bitcast
// CHECK-NEXT: bitcast
-// CHECK-NEXT: call void @objc_release
+// CHECK-NEXT: call void @llvm.objc.release
// CHECK-NEXT: ret void
template void send_release<int>();
@@ -268,9 +268,9 @@ Test37 *instantiate_init() {
// CHECK-LABEL: define weak_odr %2* @_Z16instantiate_initIiEP6Test37v
// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
-// CHECK: call i8* @objc_retain
-// CHECK: call void @objc_release
-// CHECK: call i8* @objc_autoreleaseReturnValue
+// CHECK: call i8* @llvm.objc.retain
+// CHECK: call void @llvm.objc.release
+// CHECK: call i8* @llvm.objc.autoreleaseReturnValue
template Test37* instantiate_init<int>();
// Just make sure that the AST invariants hold properly here,
@@ -322,7 +322,7 @@ template void test40_helper<int>();
// CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]]
// CHECK: @objc_msgSend
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]]
-// CHECK-NEXT: call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: call i8* @llvm.objc.retain(i8* [[T0]])
// Check that moves out of __weak variables are compiled to use objc_moveWeak.
void test41(__weak id &&x) {
@@ -332,5 +332,5 @@ void test41(__weak id &&x) {
// CHECK: [[X:%.*]] = alloca i8**
// CHECK: [[Y:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = load i8**, i8*** [[X]]
-// CHECK-NEXT: call void @objc_moveWeak(i8** [[Y]], i8** [[T0]])
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Y]])
+// CHECK-NEXT: call void @llvm.objc.moveWeak(i8** [[Y]], i8** [[T0]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Y]])
diff --git a/test/CodeGenObjCXX/block-nested-in-lambda.cpp b/test/CodeGenObjCXX/block-nested-in-lambda.cpp
deleted file mode 100644
index 51b7abf034e5..000000000000
--- a/test/CodeGenObjCXX/block-nested-in-lambda.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -std=c++11 -fblocks -o - %s | FileCheck %s
-
-// CHECK: %[[BLOCK_CAPTURED0:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>* %[[BLOCK:.*]], i32 0, i32 5
-// CHECK: %[[V0:.*]] = getelementptr inbounds %[[LAMBDA_CLASS:.*]], %[[LAMBDA_CLASS]]* %[[THIS:.*]], i32 0, i32 0
-// CHECK: %[[V1:.*]] = load i32*, i32** %[[V0]], align 8
-// CHECK: store i32* %[[V1]], i32** %[[BLOCK_CAPTURED0]], align 8
-// CHECK: %[[BLOCK_CAPTURED1:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>* %[[BLOCK]], i32 0, i32 6
-// CHECK: %[[V2:.*]] = getelementptr inbounds %[[LAMBDA_CLASS]], %[[LAMBDA_CLASS]]* %[[THIS]], i32 0, i32 1
-// CHECK: %[[V3:.*]] = load i32*, i32** %[[V2]], align 8
-// CHECK: store i32* %[[V3]], i32** %[[BLOCK_CAPTURED1]], align 8
-
-void foo1(int &, int &);
-
-void block_in_lambda(int &s1, int &s2) {
- auto lambda = [&s1, &s2]() {
- auto block = ^{
- foo1(s1, s2);
- };
- block();
- };
-
- lambda();
-}
diff --git a/test/CodeGenObjCXX/block-nested-in-lambda.mm b/test/CodeGenObjCXX/block-nested-in-lambda.mm
new file mode 100644
index 000000000000..be1ad8117cd2
--- /dev/null
+++ b/test/CodeGenObjCXX/block-nested-in-lambda.mm
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -std=c++11 -fblocks -fobjc-arc -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+
+// CHECK: %[[BLOCK_CAPTURED0:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>* %[[BLOCK:.*]], i32 0, i32 5
+// CHECK: %[[V0:.*]] = getelementptr inbounds %[[LAMBDA_CLASS:.*]], %[[LAMBDA_CLASS]]* %[[THIS:.*]], i32 0, i32 0
+// CHECK: %[[V1:.*]] = load i32*, i32** %[[V0]], align 8
+// CHECK: store i32* %[[V1]], i32** %[[BLOCK_CAPTURED0]], align 8
+// CHECK: %[[BLOCK_CAPTURED1:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>* %[[BLOCK]], i32 0, i32 6
+// CHECK: %[[V2:.*]] = getelementptr inbounds %[[LAMBDA_CLASS]], %[[LAMBDA_CLASS]]* %[[THIS]], i32 0, i32 1
+// CHECK: %[[V3:.*]] = load i32*, i32** %[[V2]], align 8
+// CHECK: store i32* %[[V3]], i32** %[[BLOCK_CAPTURED1]], align 8
+
+void foo1(int &, int &);
+
+void block_in_lambda(int &s1, int &s2) {
+ auto lambda = [&s1, &s2]() {
+ auto block = ^{
+ foo1(s1, s2);
+ };
+ block();
+ };
+
+ lambda();
+}
+
+namespace CaptureByReference {
+
+id getObj();
+void use(id);
+
+// Block copy/dispose helpers aren't needed because 'a' is captured by
+// reference.
+
+// CHECK-LABEL: define void @_ZN18CaptureByReference5test0Ev(
+// CHECK-LABEL: define internal void @"_ZZN18CaptureByReference5test0EvENK3$_1clEv"(
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>* %{{.*}}, i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i64 }* @"__block_descriptor_40_e5_v8\01?0ls32l8" to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
+
+void test0() {
+ id a = getObj();
+ [&]{ ^{ a = 0; }(); }();
+}
+
+// Block copy/dispose helpers shouldn't have to retain/release 'a' because it
+// is captured by reference.
+
+// CHECK-LABEL: define void @_ZN18CaptureByReference5test1Ev(
+// CHECK-LABEL: define internal void @"_ZZN18CaptureByReference5test1EvENK3$_2clEv"(
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i64 }* @"__block_descriptor_56_8_32s40s_e5_v8\01?0l" to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
+
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32s40s(
+// CHECK-NOT: call void @llvm.objc.storeStrong(
+// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 5
+// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 5
+// CHECK: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 8
+// CHECK: store i8* null, i8** %[[V5]], align 8
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V5]], i8* %[[BLOCKCOPY_SRC]])
+// CHECK: %[[V6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 6
+// CHECK: %[[V7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 6
+// CHECK: %[[BLOCKCOPY_SRC2:.*]] = load i8*, i8** %[[V6]], align 8
+// CHECK: store i8* null, i8** %[[V7]], align 8
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V7]], i8* %[[BLOCKCOPY_SRC2]])
+// CHECK-NOT: call void @llvm.objc.storeStrong(
+// CHECK: ret void
+
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_8_32s40s(
+// CHECK: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 5
+// CHECK: %[[V3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 6
+// CHECK-NOT: call void @llvm.objc.storeStrong(
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V3]], i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** %[[V2]], i8* null)
+// CHECK-NOT: call void @llvm.objc.storeStrong(
+// CHECK: ret void
+
+void test1() {
+ id a = getObj(), b = getObj(), c = getObj();
+ [&a, b, c]{ ^{ a = 0; use(b); use(c); }(); }();
+}
+
+}
diff --git a/test/CodeGenObjCXX/crash-function-type.mm b/test/CodeGenObjCXX/crash-function-type.mm
new file mode 100644
index 000000000000..53acc58dfc44
--- /dev/null
+++ b/test/CodeGenObjCXX/crash-function-type.mm
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fblocks -fsanitize=function -emit-llvm %s -o %t
+
+void g(void (^)());
+void f() {
+ __block int a = 0;
+ g(^() {
+ a++;
+ });
+}
diff --git a/test/CodeGenObjCXX/debug-info-line.mm b/test/CodeGenObjCXX/debug-info-line.mm
index 7cdb4d20fba0..d1cfc5b00303 100644
--- a/test/CodeGenObjCXX/debug-info-line.mm
+++ b/test/CodeGenObjCXX/debug-info-line.mm
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-unknown-windows-gnu -fcxx-exceptions -fexceptions -debug-info-kind=line-tables-only -fblocks -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-gnu -fcxx-exceptions -fexceptions -debug-info-kind=line-directives-only -fblocks -emit-llvm %s -o - | FileCheck %s
void fn();
diff --git a/test/CodeGenObjCXX/destroy.mm b/test/CodeGenObjCXX/destroy.mm
index 371f729afad2..4a0451ec947b 100644
--- a/test/CodeGenObjCXX/destroy.mm
+++ b/test/CodeGenObjCXX/destroy.mm
@@ -44,7 +44,7 @@ void test4() {
// CHECK: call void @_ZN8tderivedIiED1Ev
// CHECK-LABEL: define linkonce_odr void @_ZN7derivedD2Ev
-// CHECK: call void @objc_storeStrong(i8** {{.*}}, i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** {{.*}}, i8* null)
// CHECK-LABEL: define linkonce_odr void @_ZN8tderivedIiED2Ev
-// CHECK: call void @objc_storeStrong(i8** {{.*}}, i8* null)
+// CHECK: call void @llvm.objc.storeStrong(i8** {{.*}}, i8* null)
diff --git a/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm b/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm
new file mode 100644
index 000000000000..229e84a0f56a
--- /dev/null
+++ b/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call\ "
+// rdar://problem/45805151
+
+struct Strong {
+ __strong id x;
+};
+
+struct Base {
+ // Use variadic args to cause inlining the inherited constructor.
+ Base(Strong s, ...) {}
+};
+
+struct NonTrivialDtor {
+ ~NonTrivialDtor() {}
+};
+struct Inheritor : public NonTrivialDtor, public Base {
+ using Base::Base;
+};
+
+id g(void);
+void f() {
+ Inheritor({g()});
+}
+// CHECK-LABEL: define void @_Z1fv
+// CHECK: %[[TMP:.*]] = call i8* @_Z1gv()
+// CHECK: {{.*}} = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[TMP]])
+// CHECK: call void (%struct.Base*, i8*, ...) @_ZN4BaseC2E6Strongz(%struct.Base* {{.*}}, i8* {{.*}})
+// CHECK-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}})
+
+// CHECK-LABEL: define linkonce_odr void @_ZN4BaseC2E6Strongz(%struct.Base* {{.*}}, i8* {{.*}}, ...)
+// CHECK: call void @_ZN6StrongD1Ev(%struct.Strong* {{.*}})
+
+// CHECK-LABEL: define linkonce_odr void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}})
+// CHECK: call void @_ZN9InheritorD2Ev(%struct.Inheritor* {{.*}})
+
+// CHECK-LABEL: define linkonce_odr void @_ZN6StrongD1Ev(%struct.Strong* {{.*}})
+// CHECK: call void @_ZN6StrongD2Ev(%struct.Strong* {{.*}})
+
+// CHECK-LABEL: define linkonce_odr void @_ZN6StrongD2Ev(%struct.Strong* {{.*}})
+// CHECK: call void @llvm.objc.storeStrong(i8** {{.*}}, i8* null)
+
+// CHECK-LABEL: define linkonce_odr void @_ZN9InheritorD2Ev(%struct.Inheritor* {{.*}})
+// CHECK: call void @_ZN14NonTrivialDtorD2Ev(%struct.NonTrivialDtor* {{.*}})
diff --git a/test/CodeGenObjCXX/lambda-expressions.mm b/test/CodeGenObjCXX/lambda-expressions.mm
index f60655c61b18..ff7450f20671 100644
--- a/test/CodeGenObjCXX/lambda-expressions.mm
+++ b/test/CodeGenObjCXX/lambda-expressions.mm
@@ -20,8 +20,8 @@ fp f() { auto x = []{ return 3; }; return x; }
// ARC-LABEL: define internal i32 ()* @"_ZZ1fvENK3$_0cvU13block_pointerFivEEv"
// ARC: store i8* bitcast (i8** @_NSConcreteStackBlock to i8*)
// ARC: store i8* bitcast (i32 (i8*)* @"___ZZ1fvENK3$_0cvU13block_pointerFivEEv_block_invoke" to i8*)
-// ARC: call i8* @objc_retainBlock
-// ARC: call i8* @objc_autoreleaseReturnValue
+// ARC: call i8* @llvm.objc.retainBlock
+// ARC: call i8* @llvm.objc.autoreleaseReturnValue
typedef int (^fp)();
fp global;
@@ -35,8 +35,8 @@ void f2() { global = []{ return 3; }; }
// ARC: define void @_Z2f2v() [[NUW:#[0-9]+]] {
// ARC: store i8* bitcast (i32 (i8*)* @___Z2f2v_block_invoke to i8*),
-// ARC: call i8* @objc_retainBlock
-// ARC: call void @objc_release
+// ARC: call i8* @llvm.objc.retainBlock
+// ARC: call void @llvm.objc.release
// ARC-LABEL: define internal i32 @___Z2f2v_block_invoke
// ARC: call i32 @"_ZZ2f2vENK3$_1clEv
@@ -72,7 +72,7 @@ void take_block(void (^block)()) { block(); }
// ARC: store i32 %{{.*}}, i32* %[[CAPTURE1]]
// ARC-LABEL: define internal void @"_ZZ10-[Foo foo]ENK3$_4clEv"(
-// ARC-NOT: @objc_storeStrong(
+// ARC-NOT: @llvm.objc.storeStrong(
// ARC: ret void
// ARC: define internal void @"___ZZN13LambdaCapture4foo1ERiENK3$_3clEv_block_invoke"
diff --git a/test/CodeGenObjCXX/lambda-to-block.mm b/test/CodeGenObjCXX/lambda-to-block.mm
index a8d0718b1244..a21c8232f084 100644
--- a/test/CodeGenObjCXX/lambda-to-block.mm
+++ b/test/CodeGenObjCXX/lambda-to-block.mm
@@ -3,16 +3,74 @@
// rdar://31385153
// Shouldn't crash!
+// CHECK: %[[STRUCT_COPYABLE:.*]] = type { i8 }
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+// CHECK: %[[CLASS_ANON:.*]] = type { %[[STRUCT_COPYABLE]] }
+// CHECK: %[[CLASS_ANON_0:.*]] = type { %[[STRUCT_COPYABLE]] }
+// CHECK: %[[CLASS_ANON_1:.*]] = type { %[[STRUCT_COPYABLE]] }
+// CHECK: %[[CLASS_ANON_2:.*]] = type { %[[STRUCT_COPYABLE]] }
+
+// CHECK: @[[BLOCK_DESC0:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER0:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8
+// CHECK: @[[BLOCK_DESC1:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER1:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8
+// CHECK: @[[BLOCK_DESC2:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER2:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8
+// CHECK: @[[BLOCK_DESC3:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER3:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8
+
+// CHECK: define void @_Z9hasLambda8Copyable(
+// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON]] }>, align 8
+// CHECK: %[[BLOCK1:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_0]] }>, align 8
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON]] }>* %[[BLOCK]], i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC0]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
+// CHECK: %[[BLOCK_DESCRIPTOR6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_0]] }>* %[[BLOCK1]], i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC1]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR6]], align 8
+
void takesBlock(void (^)(void));
struct Copyable {
Copyable(const Copyable &x);
};
+// Check that each block has its block descriptor and helper function.
+
void hasLambda(Copyable x) {
takesBlock([x] () { });
+ takesBlock([x] () { });
}
-// CHECK-LABEL: define internal void @__copy_helper_block_
+// CHECK: define internal void @[[COPY_HELPER0]]
// CHECK: call void @"_ZZ9hasLambda8CopyableEN3$_0C1ERKS0_"
+// CHECK: define internal void @[[COPY_HELPER1]]
+
+// CHECK: define void @_Z17testHelperMerging8Copyable(
+// CHECK: %[[CALL:.*]] = call void ()* @[[CONV_FUNC0:.*]](%[[CLASS_ANON_1]]*
+// CHECK: call void @_Z10takesBlockU13block_pointerFvvE(void ()* %[[CALL]])
+// CHECK: %[[CALL1:.*]] = call void ()* @[[CONV_FUNC0]](%[[CLASS_ANON_1]]*
+// CHECK: call void @_Z10takesBlockU13block_pointerFvvE(void ()* %[[CALL1]])
+// CHECK: %[[CALL2:.*]] = call void ()* @[[CONV_FUNC1:.*]](%[[CLASS_ANON_2]]*
+// CHECK: call void @_Z10takesBlockU13block_pointerFvvE(void ()* %[[CALL2]])
+
+// CHECK: define internal void ()* @[[CONV_FUNC0]](
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_1]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_1]] }>* %{{.*}}, i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC2]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
+
+// CHECK: define internal void ()* @[[CONV_FUNC1]](
+// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_2]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_2]] }>* %{{.*}}, i32 0, i32 4
+// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC3]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
+
// CHECK-LABEL: define internal void @"_ZZ9hasLambda8CopyableEN3$_0C2ERKS0_"
// CHECK: call void @_ZN8CopyableC1ERKS_
+
+// CHECK: define internal void @[[COPY_HELPER2]]
+// CHECK: define internal void @[[COPY_HELPER3]]
+
+void testHelperMerging(Copyable x) {
+ auto lambda0 = [x]{};
+ auto lambda1 = [x]{};
+ takesBlock(lambda0);
+
+ // This block has the same helper functions and a descriptor as the block
+ // created above.
+ takesBlock(lambda0);
+
+ // This block has different helper functions and a descriptor as the blocks
+ // created above.
+ takesBlock(lambda1);
+}
diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm
index a42070b00c30..0a14d330bdb6 100644
--- a/test/CodeGenObjCXX/literals.mm
+++ b/test/CodeGenObjCXX/literals.mm
@@ -29,7 +29,7 @@ void test_array() {
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]])
// CHECK-NEXT: call void @_ZN1XC1Ev({{.*}} [[TMPX]])
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
- // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]])
+ // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT0]])
// CHECK: store i8* [[RET0]], i8** [[ELEMENT0]]
// Initializing the second element
@@ -38,36 +38,36 @@ void test_array() {
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]])
// CHECK-NEXT: invoke void @_ZN1YC1Ev({{.*}} [[TMPY]])
// CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv
- // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]])
+ // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT1]])
// CHECK: store i8* [[RET1]], i8** [[ELEMENT1]]
// Build the array
// CHECK: {{invoke.*@objc_msgSend}}
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
id arr = @[ X(), Y() ];
// Destroy temporaries
// CHECK-NOT: ret void
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NOT: ret void
// CHECK: invoke void @_ZN1YD1Ev
// CHECK-NOT: ret void
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: call void @_ZN1XD1Ev
// CHECK-NOT: ret void
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: [[PTR2:%.*]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTR2]])
// CHECK-NEXT: ret void
// Check cleanups
- // CHECK: call void @objc_release
- // CHECK-NOT: call void @objc_release
+ // CHECK: call void @llvm.objc.release
+ // CHECK-NOT: call void @llvm.objc.release
// CHECK: invoke void @_ZN1YD1Ev
- // CHECK: call void @objc_release
- // CHECK-NOT: call void @objc_release
+ // CHECK: call void @llvm.objc.release
+ // CHECK-NOT: call void @llvm.objc.release
// CHECK: invoke void @_ZN1XD1Ev
- // CHECK-NOT: call void @objc_release
+ // CHECK-NOT: call void @llvm.objc.release
// CHECK: unreachable
}
@@ -83,43 +83,43 @@ void test_array_instantiation() {
// CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0
// CHECK: call void @_ZN1XC1Ev
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
- // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]])
+ // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT0]])
// CHECK: store i8* [[RET0]], i8** [[ELEMENT0]]
// Initializing the second element
// CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1
// CHECK: invoke void @_ZN1YC1Ev
// CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv
- // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]])
+ // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OBJECT1]])
// CHECK: store i8* [[RET1]], i8** [[ELEMENT1]]
// Build the array
// CHECK: {{invoke.*@objc_msgSend}}
- // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ // CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
id arr = @[ X(), Y() ];
// Destroy temporaries
// CHECK-NOT: ret void
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NOT: ret void
// CHECK: invoke void @_ZN1YD1Ev
// CHECK-NOT: ret void
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: call void @_ZN1XD1Ev
// CHECK-NOT: ret void
- // CHECK: call void @objc_release
+ // CHECK: call void @llvm.objc.release
// CHECK-NEXT: [[PTR2]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTR2]])
// CHECK-NEXT: ret void
// Check cleanups
- // CHECK: call void @objc_release
- // CHECK-NOT: call void @objc_release
+ // CHECK: call void @llvm.objc.release
+ // CHECK-NOT: call void @llvm.objc.release
// CHECK: invoke void @_ZN1YD1Ev
- // CHECK: call void @objc_release
- // CHECK-NOT: call void @objc_release
+ // CHECK: call void @llvm.objc.release
+ // CHECK-NOT: call void @llvm.objc.release
// CHECK: invoke void @_ZN1XD1Ev
- // CHECK-NOT: call void @objc_release
+ // CHECK-NOT: call void @llvm.objc.release
// CHECK: unreachable
}
diff --git a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
index 910a7db73404..50c2e4aa41e1 100644
--- a/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
+++ b/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
@@ -13,8 +13,8 @@ struct A {
// CHECK: (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca)
void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) {
// CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}})
- // CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
+ // CHECK: call void @llvm.objc.storeStrong(i8** %{{.*}}, i8* null)
// CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}})
- // CHECK: call void @objc_storeStrong(i8** %{{.*}}, i8* null)
+ // CHECK: call void @llvm.objc.storeStrong(i8** %{{.*}}, i8* null)
// CHECK: ret void
}
diff --git a/test/CodeGenObjCXX/mrc-weak.mm b/test/CodeGenObjCXX/mrc-weak.mm
index 17ceb31231a3..b89d76cf4712 100644
--- a/test/CodeGenObjCXX/mrc-weak.mm
+++ b/test/CodeGenObjCXX/mrc-weak.mm
@@ -26,15 +26,15 @@
@implementation Foo
// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
@end
void test1(__weak id x) {}
// CHECK-LABEL: define void @_Z5test1P11objc_object(
// CHECK: [[X:%.*]] = alloca i8*,
-// CHECK-NEXT: objc_initWeak
-// CHECK-NEXT: objc_destroyWeak
+// CHECK-NEXT: llvm.objc.initWeak
+// CHECK-NEXT: llvm.objc.destroyWeak
// CHECK-NEXT: ret void
void test2(id y) {
@@ -45,8 +45,8 @@ void test2(id y) {
// CHECK-NEXT: [[Z:%.*]] = alloca i8*,
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]])
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[Z]], i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]])
// CHECK-NEXT: ret void
void test3(id y) {
@@ -59,8 +59,8 @@ void test3(id y) {
// CHECK-NEXT: store
// CHECK-NEXT: store i8* null, i8** [[Z]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
-// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]])
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
+// CHECK-NEXT: call i8* @llvm.objc.storeWeak(i8** [[Z]], i8* [[T0]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Z]])
// CHECK-NEXT: ret void
void test4(__weak id *p) {
@@ -71,7 +71,7 @@ void test4(__weak id *p) {
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeak(i8** [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
// CHECK-NEXT: ret void
@@ -83,7 +83,7 @@ void test5(__weak id *p) {
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
// CHECK-NEXT: ret void
@@ -96,7 +96,7 @@ void test6(__weak Foo **p) {
// CHECK-NEXT: store
// CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8**
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.loadWeakRetained(i8** [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]*
// CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]]
// CHECK-NEXT: ret void
@@ -114,36 +114,36 @@ void test7(void) {
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]*
// CHECK-NEXT: [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8*
-// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]])
-// CHECK: call void @objc_copyWeak
+// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[T2]], i8* [[T3]])
+// CHECK: call void @llvm.objc.copyWeak
// CHECK: call void @use_block
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
-// CHECK-LABEL: define internal void @__copy_helper_block
-// CHECK: @objc_copyWeak
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block
+// CHECK: @llvm.objc.copyWeak
-// CHECK-LABEL: define internal void @__destroy_helper_block
-// CHECK: @objc_destroyWeak
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block
+// CHECK: @llvm.objc.destroyWeak
void test8(void) {
__block __weak Foo *p = get_object();
use_block(^{ [p run ]; });
}
// CHECK-LABEL: define void @_Z5test8v
-// CHECK: call i8* @objc_initWeak
-// CHECK-NOT: call void @objc_copyWeak
+// CHECK: call i8* @llvm.objc.initWeak
+// CHECK-NOT: call void @llvm.objc.copyWeak
// CHECK: call void @use_block
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
// CHECK-LABEL: define internal void @__Block_byref_object_copy
-// CHECK: call void @objc_moveWeak
+// CHECK: call void @llvm.objc.moveWeak
// CHECK-LABEL: define internal void @__Block_byref_object_dispose
-// CHECK: call void @objc_destroyWeak
+// CHECK: call void @llvm.objc.destroyWeak
// CHECK-LABEL: define void @_Z14test9_baselinev()
-// CHECK: define internal void @__copy_helper
-// CHECK: define internal void @__destroy_helper
+// CHECK: define linkonce_odr hidden void @__copy_helper
+// CHECK: define linkonce_odr hidden void @__destroy_helper
void test9_baseline(void) {
Foo *p = get_object();
use_block(^{ [p run]; });
diff --git a/test/CodeGenObjCXX/msabi-objc-extensions.mm b/test/CodeGenObjCXX/msabi-objc-extensions.mm
index 2f724a985f33..7ac3910ba471 100644
--- a/test/CodeGenObjCXX/msabi-objc-extensions.mm
+++ b/test/CodeGenObjCXX/msabi-objc-extensions.mm
@@ -4,6 +4,7 @@
@protocol Q;
@class I;
+@class J<T>;
void f(id<P>, id, id<P>, id) {}
// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@PAUobjc_object@@01@Z"
@@ -64,3 +65,33 @@ S<__autoreleasing id> g() { return S<__autoreleasing id>(); }
__autoreleasing id h() { return nullptr; }
// CHECK-LABEL: "?h@@YAPAUobjc_object@@XZ"
+
+void f(I *) {}
+// CHECK-LABEL: "?f@@YAXPAUI@@@Z"
+
+void f(__kindof I *) {}
+// CHECK-LABEL: "?f@@YAXPAU?$KindOf@UI@@@__ObjC@@@Z"
+
+void f(__kindof I<P> *) {}
+// CHECK-LABEL: "?f@@YAXPAU?$KindOf@U?$I@U?$Protocol@UP@@@__ObjC@@@@@__ObjC@@@Z"
+
+void f(S<I *>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAUI@@@__ObjC@@@@@Z"
+
+void f(S<__kindof I *>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAU?$KindOf@UI@@@__ObjC@@@__ObjC@@@@@Z"
+
+void f(S<__kindof I<P> *>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAU?$KindOf@U?$I@U?$Protocol@UP@@@__ObjC@@@@@__ObjC@@@__ObjC@@@@@Z"
+
+void f(S<__weak __kindof I *>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAU?$KindOf@UI@@@__ObjC@@@__ObjC@@@@@Z"
+
+void f(S<__weak __kindof I<P> *>) {}
+// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAU?$KindOf@U?$I@U?$Protocol@UP@@@__ObjC@@@@@__ObjC@@@__ObjC@@@@@Z"
+
+void f(J<I *> *) {}
+// CHECK-LABEL: "?f@@YAXPAU?$J@PAUI@@@@@Z"
+
+void f(J<__kindof I *> *) {}
+// CHECK-LABEL: "?f@@YAXPAU?$J@PAU?$KindOf@UI@@@__ObjC@@@@@Z"
diff --git a/test/CodeGenObjCXX/objc-weak.mm b/test/CodeGenObjCXX/objc-weak.mm
index 68c2d4611146..afccc81106fe 100644
--- a/test/CodeGenObjCXX/objc-weak.mm
+++ b/test/CodeGenObjCXX/objc-weak.mm
@@ -18,9 +18,9 @@ id test0() {
// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
// CHECK: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeak(i8** [[T0]])
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
+// CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]])
// Move Assignment Operator
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.A* @_ZN1AaSEOS_(
@@ -29,9 +29,9 @@ id test0() {
// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
// CHECK: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.loadWeak(i8** [[T0]])
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
+// CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.storeWeak(i8** [[T2]], i8* [[T1]])
// Default Constructor
// CHECK-LABEL: define linkonce_odr void @_ZN1AC2Ev(
@@ -48,7 +48,7 @@ id test0() {
// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
// CHECK-NEXT: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
-// CHECK-NEXT: call void @objc_copyWeak(i8** [[T0]], i8** [[T1]])
+// CHECK-NEXT: call void @llvm.objc.copyWeak(i8** [[T0]], i8** [[T1]])
// Move Constructor
// CHECK-LABEL: define linkonce_odr void @_ZN1AC2EOS_(
@@ -58,12 +58,12 @@ id test0() {
// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
// CHECK-NEXT: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
-// CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
+// CHECK-NEXT: call void @llvm.objc.moveWeak(i8** [[T0]], i8** [[T1]])
// Destructor
// CHECK-LABEL: define linkonce_odr void @_ZN1AD2Ev(
// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
-// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
+// CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[T0]])
diff --git a/test/CodeGenObjCXX/pr14474-gline-tables-only.mm b/test/CodeGenObjCXX/pr14474-gline-tables-only.mm
index 6c74ce80db0f..cfc6d78b6b88 100644
--- a/test/CodeGenObjCXX/pr14474-gline-tables-only.mm
+++ b/test/CodeGenObjCXX/pr14474-gline-tables-only.mm
@@ -1,6 +1,8 @@
// PR 14474
// RUN: %clang_cc1 -triple i386-apple-macosx10.6.0 -emit-llvm \
// RUN: -debug-info-kind=line-tables-only -x objective-c++ -o /dev/null %s
+// RUN: %clang_cc1 -triple i386-apple-macosx10.6.0 -emit-llvm \
+// RUN: -debug-info-kind=line-directives-only -x objective-c++ -o /dev/null %s
typedef signed char BOOL;
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
diff --git a/test/CodeGenOpenCL/addr-space-struct-arg.cl b/test/CodeGenOpenCL/addr-space-struct-arg.cl
index f8d7073f92ee..6f923b7fd403 100644
--- a/test/CodeGenOpenCL/addr-space-struct-arg.cl
+++ b/test/CodeGenOpenCL/addr-space-struct-arg.cl
@@ -1,6 +1,9 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -ffake-address-space-map -triple i686-pc-darwin | FileCheck -enable-var-scope -check-prefixes=COM,X86 %s
-// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -finclude-default-header -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN %s
-// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL2.0 -O0 -finclude-default-header -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN,AMDGCN20 %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -ffake-address-space-map -triple i686-pc-darwin | FileCheck -enable-var-scope -check-prefixes=COM,X86 %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL2.0 -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=COM,AMDGCN,AMDGCN20 %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL1.2 -O0 -triple spir-unknown-unknown-unknown | FileCheck -enable-var-scope -check-prefixes=SPIR %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
typedef struct {
int cells[9];
@@ -130,6 +133,12 @@ kernel void KernelOneMember(struct StructOneMember u) {
FuncOneMember(u);
}
+// SPIR: call void @llvm.memcpy.p0i8.p1i8.i32
+// SPIR-NOT: addrspacecast
+kernel void KernelOneMemberSpir(global struct StructOneMember* u) {
+ FuncOneMember(*u);
+}
+
// AMDGCN-LABEL: define amdgpu_kernel void @KernelLargeOneMember(
// AMDGCN: %[[U:.*]] = alloca %struct.LargeStructOneMember, align 8, addrspace(5)
// AMDGCN: store %struct.LargeStructOneMember %u.coerce, %struct.LargeStructOneMember addrspace(5)* %[[U]], align 8
diff --git a/test/CodeGenOpenCL/address-spaces.cl b/test/CodeGenOpenCL/address-spaces.cl
index 60f5e30d328b..3c8fea2a80bc 100644
--- a/test/CodeGenOpenCL/address-spaces.cl
+++ b/test/CodeGenOpenCL/address-spaces.cl
@@ -19,7 +19,7 @@ struct S {
// CL20-DAG: @g_static_var = internal addrspace(1) global float 0.000000e+00
#ifdef CL20
-// CL20-DAG: @g_s = common {{(dso_local )?}}addrspace(1) global %struct.S zeroinitializer
+// CL20-DAG: @g_s = {{(common )?}}{{(dso_local )?}}addrspace(1) global %struct.S zeroinitializer
struct S g_s;
#endif
@@ -55,7 +55,7 @@ void fc(constant int *arg) {}
int i;
// CL20-DAG: @i = common {{(dso_local )?}}addrspace(1) global i32 0
int *ptr;
-// CL20SPIR-DAG: @ptr = common {{(dso_local )?}}addrspace(1) global i32 addrspace(4)* null
+// CL20SPIR-DAG: @ptr = {{(common )?}}{{(dso_local )?}}addrspace(1) global i32 addrspace(4)* null
// CL20AMDGCN-DAG: @ptr = common {{(dso_local )?}}addrspace(1) global i32* null
#endif
diff --git a/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl b/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
index 75fceccb2a45..875c35c048dd 100644
--- a/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
+++ b/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn | FileCheck %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn | FileCheck %s --check-prefix=CHECK
typedef struct {int a;} ndrange_t;
@@ -36,23 +36,23 @@ kernel void test(global char *a, char b, global long *c, long d) {
enqueue_kernel(default_queue, flags, ndrange, block);
}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_kernel(<{ i32, i32, i8 addrspace(1)*, i8 }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_kernel(<{ i32, i32, i8*, i8 addrspace(1)*, i8 }>)
// CHECK-SAME: #[[ATTR:[0-9]+]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
// CHECK: entry:
-// CHECK: %1 = alloca <{ i32, i32, i8 addrspace(1)*, i8 }>, align 8, addrspace(5)
-// CHECK: store <{ i32, i32, i8 addrspace(1)*, i8 }> %0, <{ i32, i32, i8 addrspace(1)*, i8 }> addrspace(5)* %1, align 8
-// CHECK: %2 = addrspacecast <{ i32, i32, i8 addrspace(1)*, i8 }> addrspace(5)* %1 to i8*
+// CHECK: %1 = alloca <{ i32, i32, i8*, i8 addrspace(1)*, i8 }>, align 8, addrspace(5)
+// CHECK: store <{ i32, i32, i8*, i8 addrspace(1)*, i8 }> %0, <{ i32, i32, i8*, i8 addrspace(1)*, i8 }> addrspace(5)* %1, align 8
+// CHECK: %2 = addrspacecast <{ i32, i32, i8*, i8 addrspace(1)*, i8 }> addrspace(5)* %1 to i8*
// CHECK: call void @__test_block_invoke(i8* %2)
// CHECK: ret void
// CHECK:}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_2_kernel(<{ i32, i32, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_2_kernel(<{ i32, i32, i8*, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_3_kernel(<{ i32, i32, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>, i8 addrspace(3)*)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_3_kernel(<{ i32, i32, i8*, i8 addrspace(1)*, i64 addrspace(1)*, i64, i8 }>, i8 addrspace(3)*)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
-// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_4_kernel(<{ i32, i32, i64, i64 addrspace(1)* }>)
+// CHECK-LABEL: define internal amdgpu_kernel void @__test_block_invoke_4_kernel(<{ i32, i32, i8*, i64, i64 addrspace(1)* }>)
// CHECK-SAME: #[[ATTR]] !kernel_arg_addr_space !{{.*}} !kernel_arg_access_qual !{{.*}} !kernel_arg_type !{{.*}} !kernel_arg_base_type !{{.*}} !kernel_arg_type_qual !{{.*}}
// CHECK: attributes #[[ATTR]] = { nounwind "enqueued-block" }
diff --git a/test/CodeGenOpenCL/amdgpu-features.cl b/test/CodeGenOpenCL/amdgpu-features.cl
index a1815cedcd49..7aac4d3a3685 100644
--- a/test/CodeGenOpenCL/amdgpu-features.cl
+++ b/test/CodeGenOpenCL/amdgpu-features.cl
@@ -5,8 +5,16 @@
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx904 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX904 %s
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx906 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX906 %s
+// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx801 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX801 %s
+// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx700 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX700 %s
+// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx600 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX600 %s
+// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx601 -S -emit-llvm -o - %s | FileCheck --check-prefix=GFX601 %s
-// GFX904: "target-features"="+16-bit-insts,+dpp,+fp32-denormals,+fp64-fp16-denormals,+gfx9-insts,+s-memrealtime"
-// GFX906: "target-features"="+16-bit-insts,+dl-insts,+dpp,+fp32-denormals,+fp64-fp16-denormals,+gfx9-insts,+s-memrealtime"
+// GFX904: "target-features"="+16-bit-insts,+ci-insts,+dpp,+fp32-denormals,+fp64-fp16-denormals,+gfx9-insts,+s-memrealtime,+vi-insts"
+// GFX906: "target-features"="+16-bit-insts,+ci-insts,+dl-insts,+dot-insts,+dpp,+fp32-denormals,+fp64-fp16-denormals,+gfx9-insts,+s-memrealtime,+vi-insts"
+// GFX801: "target-features"="+16-bit-insts,+ci-insts,+dpp,+fp32-denormals,+fp64-fp16-denormals,+s-memrealtime,+vi-insts"
+// GFX700: "target-features"="+ci-insts,+fp64-fp16-denormals,-fp32-denormals"
+// GFX600: "target-features"="+fp64-fp16-denormals,-fp32-denormals"
+// GFX601: "target-features"="+fp64-fp16-denormals,-fp32-denormals"
kernel void test() {}
diff --git a/test/CodeGenOpenCL/amdgpu-nullptr.cl b/test/CodeGenOpenCL/amdgpu-nullptr.cl
index 688d3a58e90b..c7c77920b775 100644
--- a/test/CodeGenOpenCL/amdgpu-nullptr.cl
+++ b/test/CodeGenOpenCL/amdgpu-nullptr.cl
@@ -143,7 +143,7 @@ void test_static_var_local(void) {
// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp3, align 4
// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp4, align 4
// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1 addrspace(5)* %SS1 to i8 addrspace(5)*
-// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @test_func_scope_var_private.SS1 to i8 addrspace(4)*), i64 32, i1 false)
+// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @__const.test_func_scope_var_private.SS1 to i8 addrspace(4)*), i64 32, i1 false)
// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2 addrspace(5)* %SS2 to i8 addrspace(5)*
// NOOPT: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 8 %[[SS2]], i8 0, i64 24, i1 false)
void test_func_scope_var_private(void) {
@@ -163,7 +163,7 @@ void test_func_scope_var_private(void) {
// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)* addrspace(5)* %sp3, align 4
// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)* addrspace(5)* %sp4, align 4
// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1 addrspace(5)* %SS1 to i8 addrspace(5)*
-// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @test_func_scope_var_local.SS1 to i8 addrspace(4)*), i64 32, i1 false)
+// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @__const.test_func_scope_var_local.SS1 to i8 addrspace(4)*), i64 32, i1 false)
// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2 addrspace(5)* %SS2 to i8 addrspace(5)*
// NOOPT: call void @llvm.memset.p5i8.i64(i8 addrspace(5)* align 8 %[[SS2]], i8 0, i64 24, i1 false)
void test_func_scope_var_local(void) {
diff --git a/test/CodeGenOpenCL/blocks.cl b/test/CodeGenOpenCL/blocks.cl
index 80ac5727b094..675240c6f05d 100644
--- a/test/CodeGenOpenCL/blocks.cl
+++ b/test/CodeGenOpenCL/blocks.cl
@@ -1,7 +1,12 @@
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple spir-unknown-unknown | FileCheck -check-prefixes=COMMON,SPIR %s
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=COMMON,SPIR %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple spir-unknown-unknown | FileCheck -check-prefixes=CHECK-DEBUG %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=CHECK-DEBUG %s
-// COMMON: @__block_literal_global = internal addrspace(1) constant { i32, i32 } { i32 8, i32 4 }
+// SPIR: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* }
+// AMDGCN: %struct.__opencl_block_literal_generic = type { i32, i32, i8* }
+// SPIR: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 12, i32 4, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) }
+// AMDGCN: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8* } { i32 16, i32 8, i8* bitcast (void (i8*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) }
// COMMON-NOT: .str
// SPIR-LABEL: define internal {{.*}}void @block_A_block_invoke(i8 addrspace(4)* %.block_descriptor, i8 addrspace(3)* %a)
@@ -17,32 +22,44 @@ void foo(){
// COMMON-NOT: %block.flags
// COMMON-NOT: %block.reserved
// COMMON-NOT: %block.descriptor
- // SPIR: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block:.*]], i32 0, i32 0
- // AMDGCN: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block:.*]], i32 0, i32 0
- // SPIR: store i32 12, i32* %[[block_size]]
- // AMDGCN: store i32 12, i32 addrspace(5)* %[[block_size]]
- // SPIR: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 1
- // AMDGCN: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block]], i32 0, i32 1
+ // SPIR: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 0
+ // AMDGCN: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %block, i32 0, i32 0
+ // SPIR: store i32 16, i32* %[[block_size]]
+ // AMDGCN: store i32 20, i32 addrspace(5)* %[[block_size]]
+ // SPIR: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %block, i32 0, i32 1
+ // AMDGCN: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %block, i32 0, i32 1
// SPIR: store i32 4, i32* %[[block_align]]
- // AMDGCN: store i32 4, i32 addrspace(5)* %[[block_align]]
- // SPIR: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 2
+ // AMDGCN: store i32 8, i32 addrspace(5)* %[[block_align]]
+ // SPIR: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block:.*]], i32 0, i32 2
+ // SPIR: store i8 addrspace(4)* addrspacecast (i8* bitcast (i32 (i8 addrspace(4)*)* @__foo_block_invoke to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %[[block_invoke]]
+ // SPIR: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]], i32 0, i32 3
// SPIR: %[[i_value:.*]] = load i32, i32* %i
// SPIR: store i32 %[[i_value]], i32* %[[block_captured]],
- // SPIR: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i32 }>* %[[block]] to i32 ()*
+ // SPIR: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 }>* %[[block]] to i32 ()*
// SPIR: %[[blk_gen_ptr:.*]] = addrspacecast i32 ()* %[[blk_ptr]] to i32 () addrspace(4)*
// SPIR: store i32 () addrspace(4)* %[[blk_gen_ptr]], i32 () addrspace(4)** %[[block_B:.*]],
- // SPIR: %[[block_literal:.*]] = load i32 () addrspace(4)*, i32 () addrspace(4)** %[[block_B]]
- // SPIR: %[[blk_gen_ptr:.*]] = bitcast i32 () addrspace(4)* %[[block_literal]] to i8 addrspace(4)*
- // SPIR: call {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %[[blk_gen_ptr]])
- // AMDGCN: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(5)* %[[block]], i32 0, i32 2
+ // SPIR: %[[blk_gen_ptr:.*]] = load i32 () addrspace(4)*, i32 () addrspace(4)** %[[block_B]]
+ // SPIR: %[[block_literal:.*]] = bitcast i32 () addrspace(4)* %[[blk_gen_ptr]] to %struct.__opencl_block_literal_generic addrspace(4)*
+ // SPIR: %[[invoke_addr:.*]] = getelementptr inbounds %struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]], i32 0, i32 2
+ // SPIR: %[[blk_gen_ptr:.*]] = bitcast %struct.__opencl_block_literal_generic addrspace(4)* %[[block_literal]] to i8 addrspace(4)*
+ // SPIR: %[[invoke_func_ptr:.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %[[invoke_addr]]
+ // SPIR: %[[invoke_func:.*]] = addrspacecast i8 addrspace(4)* %[[invoke_func_ptr]] to i32 (i8 addrspace(4)*)*
+ // SPIR: call {{.*}}i32 %[[invoke_func]](i8 addrspace(4)* %[[blk_gen_ptr]])
+ // AMDGCN: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %[[block:.*]], i32 0, i32 2
+ // AMDGCN: store i8* bitcast (i32 (i8*)* @__foo_block_invoke to i8*), i8* addrspace(5)* %[[block_invoke]]
+ // AMDGCN: %[[block_captured:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }> addrspace(5)* %[[block]], i32 0, i32 3
// AMDGCN: %[[i_value:.*]] = load i32, i32 addrspace(5)* %i
// AMDGCN: store i32 %[[i_value]], i32 addrspace(5)* %[[block_captured]],
- // AMDGCN: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i32 }> addrspace(5)* %[[block]] to i32 () addrspace(5)*
+ // AMDGCN: %[[blk_ptr:.*]] = bitcast <{ i32, i32, i8*, i32 }> addrspace(5)* %[[block]] to i32 () addrspace(5)*
// AMDGCN: %[[blk_gen_ptr:.*]] = addrspacecast i32 () addrspace(5)* %[[blk_ptr]] to i32 ()*
// AMDGCN: store i32 ()* %[[blk_gen_ptr]], i32 ()* addrspace(5)* %[[block_B:.*]],
- // AMDGCN: %[[block_literal:.*]] = load i32 ()*, i32 ()* addrspace(5)* %[[block_B]]
- // AMDGCN: %[[blk_gen_ptr:.*]] = bitcast i32 ()* %[[block_literal]] to i8*
- // AMDGCN: call {{.*}}i32 @__foo_block_invoke(i8* %[[blk_gen_ptr]])
+ // AMDGCN: %[[blk_gen_ptr:.*]] = load i32 ()*, i32 ()* addrspace(5)* %[[block_B]]
+ // AMDGCN: %[[block_literal:.*]] = bitcast i32 ()* %[[blk_gen_ptr]] to %struct.__opencl_block_literal_generic*
+ // AMDGCN: %[[invoke_addr:.*]] = getelementptr inbounds %struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic* %[[block_literal]], i32 0, i32 2
+ // AMDGCN: %[[blk_gen_ptr:.*]] = bitcast %struct.__opencl_block_literal_generic* %[[block_literal]] to i8*
+ // AMDGCN: %[[invoke_func_ptr:.*]] = load i8*, i8** %[[invoke_addr]]
+ // AMDGCN: %[[invoke_func:.*]] = bitcast i8* %[[invoke_func_ptr]] to i32 (i8*)*
+ // AMDGCN: call {{.*}}i32 %[[invoke_func]](i8* %[[blk_gen_ptr]])
int (^ block_B)(void) = ^{
return i;
@@ -51,20 +68,40 @@ void foo(){
}
// SPIR-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor)
-// SPIR: %[[block:.*]] = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i32 }> addrspace(4)*
-// SPIR: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }> addrspace(4)* %[[block]], i32 0, i32 2
+// SPIR: %[[block:.*]] = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)*
+// SPIR: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)*, i32 }>, <{ i32, i32, i8 addrspace(4)*, i32 }> addrspace(4)* %[[block]], i32 0, i32 3
// SPIR: %[[block_capture:.*]] = load i32, i32 addrspace(4)* %[[block_capture_addr]]
// AMDGCN-LABEL: define internal {{.*}}i32 @__foo_block_invoke(i8* %.block_descriptor)
-// AMDGCN: %[[block:.*]] = bitcast i8* %.block_descriptor to <{ i32, i32, i32 }>*
-// AMDGCN: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i32 }>, <{ i32, i32, i32 }>* %[[block]], i32 0, i32 2
+// AMDGCN: %[[block:.*]] = bitcast i8* %.block_descriptor to <{ i32, i32, i8*, i32 }>*
+// AMDGCN: %[[block_capture_addr:.*]] = getelementptr inbounds <{ i32, i32, i8*, i32 }>, <{ i32, i32, i8*, i32 }>* %[[block]], i32 0, i32 3
// AMDGCN: %[[block_capture:.*]] = load i32, i32* %[[block_capture_addr]]
// COMMON-NOT: define{{.*}}@__foo_block_invoke_kernel
-// COMMON: !DIDerivedType(tag: DW_TAG_member, name: "__size"
-// COMMON: !DIDerivedType(tag: DW_TAG_member, name: "__align"
+// Test that we support block arguments.
+// COMMON-LABEL: define {{.*}} @blockArgFunc
+int blockArgFunc(int (^ bl)(void)) {
+ return bl();
+}
+
+// COMMON-LABEL: define {{.*}} @get21
+// COMMON: define {{.*}} @__get21_block_invoke
+// COMMON: ret i32 21
+int get21() {
+ return blockArgFunc(^{return 21;});
+}
+
+// COMMON-LABEL: define {{.*}} @get42
+// COMMON: define {{.*}} @__get42_block_invoke
+// COMMON: ret i32 42
+int get42() {
+ return blockArgFunc(^{return 42;});
+}
+
+// CHECK-DEBUG: !DIDerivedType(tag: DW_TAG_member, name: "__size"
+// CHECK-DEBUG: !DIDerivedType(tag: DW_TAG_member, name: "__align"
-// COMMON-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__isa"
-// COMMON-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__flags"
-// COMMON-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__reserved"
-// COMMON-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__FuncPtr"
+// CHECK-DEBUG-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__isa"
+// CHECK-DEBUG-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__flags"
+// CHECK-DEBUG-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__reserved"
+// CHECK-DEBUG-NOT: !DIDerivedType(tag: DW_TAG_member, name: "__FuncPtr"
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-ci.cl b/test/CodeGenOpenCL/builtins-amdgcn-ci.cl
new file mode 100644
index 000000000000..41275268dbb4
--- /dev/null
+++ b/test/CodeGenOpenCL/builtins-amdgcn-ci.cl
@@ -0,0 +1,19 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu hawaii -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu fiji -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx906 -S -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: @test_s_dcache_inv_vol
+// CHECK: call void @llvm.amdgcn.s.dcache.inv.vol(
+void test_s_dcache_inv_vol()
+{
+ __builtin_amdgcn_s_dcache_inv_vol();
+}
+
+// CHECK-LABEL: @test_buffer_wbinvl1_vol
+// CHECK: call void @llvm.amdgcn.buffer.wbinvl1.vol()
+void test_buffer_wbinvl1_vol()
+{
+ __builtin_amdgcn_buffer_wbinvl1_vol();
+}
+
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl b/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
index ca3f4006e300..e2c03a471baa 100644
--- a/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
+++ b/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
@@ -12,24 +12,24 @@ kernel void builtins_amdgcn_dl_insts_err(
half2 v2hA, half2 v2hB, float fC,
short2 v2ssA, short2 v2ssB, int siA, int siB, int siC,
ushort2 v2usA, ushort2 v2usB, uint uiA, uint uiB, uint uiC) {
- fOut[0] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC, false); // expected-error {{'__builtin_amdgcn_fdot2' needs target feature dl-insts}}
- fOut[1] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC, true); // expected-error {{'__builtin_amdgcn_fdot2' needs target feature dl-insts}}
+ fOut[0] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC, false); // expected-error {{'__builtin_amdgcn_fdot2' needs target feature dot-insts}}
+ fOut[1] = __builtin_amdgcn_fdot2(v2hA, v2hB, fC, true); // expected-error {{'__builtin_amdgcn_fdot2' needs target feature dot-insts}}
- siOut[0] = __builtin_amdgcn_sdot2(v2ssA, v2ssB, siC, false); // expected-error {{'__builtin_amdgcn_sdot2' needs target feature dl-insts}}
- siOut[1] = __builtin_amdgcn_sdot2(v2ssA, v2ssB, siC, true); // expected-error {{'__builtin_amdgcn_sdot2' needs target feature dl-insts}}
+ siOut[0] = __builtin_amdgcn_sdot2(v2ssA, v2ssB, siC, false); // expected-error {{'__builtin_amdgcn_sdot2' needs target feature dot-insts}}
+ siOut[1] = __builtin_amdgcn_sdot2(v2ssA, v2ssB, siC, true); // expected-error {{'__builtin_amdgcn_sdot2' needs target feature dot-insts}}
- uiOut[0] = __builtin_amdgcn_udot2(v2usA, v2usB, uiC, false); // expected-error {{'__builtin_amdgcn_udot2' needs target feature dl-insts}}
- uiOut[1] = __builtin_amdgcn_udot2(v2usA, v2usB, uiC, true); // expected-error {{'__builtin_amdgcn_udot2' needs target feature dl-insts}}
+ uiOut[0] = __builtin_amdgcn_udot2(v2usA, v2usB, uiC, false); // expected-error {{'__builtin_amdgcn_udot2' needs target feature dot-insts}}
+ uiOut[1] = __builtin_amdgcn_udot2(v2usA, v2usB, uiC, true); // expected-error {{'__builtin_amdgcn_udot2' needs target feature dot-insts}}
- siOut[2] = __builtin_amdgcn_sdot4(siA, siB, siC, false); // expected-error {{'__builtin_amdgcn_sdot4' needs target feature dl-insts}}
- siOut[3] = __builtin_amdgcn_sdot4(siA, siB, siC, true); // expected-error {{'__builtin_amdgcn_sdot4' needs target feature dl-insts}}
+ siOut[2] = __builtin_amdgcn_sdot4(siA, siB, siC, false); // expected-error {{'__builtin_amdgcn_sdot4' needs target feature dot-insts}}
+ siOut[3] = __builtin_amdgcn_sdot4(siA, siB, siC, true); // expected-error {{'__builtin_amdgcn_sdot4' needs target feature dot-insts}}
- uiOut[2] = __builtin_amdgcn_udot4(uiA, uiB, uiC, false); // expected-error {{'__builtin_amdgcn_udot4' needs target feature dl-insts}}
- uiOut[3] = __builtin_amdgcn_udot4(uiA, uiB, uiC, true); // expected-error {{'__builtin_amdgcn_udot4' needs target feature dl-insts}}
+ uiOut[2] = __builtin_amdgcn_udot4(uiA, uiB, uiC, false); // expected-error {{'__builtin_amdgcn_udot4' needs target feature dot-insts}}
+ uiOut[3] = __builtin_amdgcn_udot4(uiA, uiB, uiC, true); // expected-error {{'__builtin_amdgcn_udot4' needs target feature dot-insts}}
- siOut[4] = __builtin_amdgcn_sdot8(siA, siB, siC, false); // expected-error {{'__builtin_amdgcn_sdot8' needs target feature dl-insts}}
- siOut[5] = __builtin_amdgcn_sdot8(siA, siB, siC, true); // expected-error {{'__builtin_amdgcn_sdot8' needs target feature dl-insts}}
+ siOut[4] = __builtin_amdgcn_sdot8(siA, siB, siC, false); // expected-error {{'__builtin_amdgcn_sdot8' needs target feature dot-insts}}
+ siOut[5] = __builtin_amdgcn_sdot8(siA, siB, siC, true); // expected-error {{'__builtin_amdgcn_sdot8' needs target feature dot-insts}}
- uiOut[4] = __builtin_amdgcn_udot8(uiA, uiB, uiC, false); // expected-error {{'__builtin_amdgcn_udot8' needs target feature dl-insts}}
- uiOut[5] = __builtin_amdgcn_udot8(uiA, uiB, uiC, true); // expected-error {{'__builtin_amdgcn_udot8' needs target feature dl-insts}}
+ uiOut[4] = __builtin_amdgcn_udot8(uiA, uiB, uiC, false); // expected-error {{'__builtin_amdgcn_udot8' needs target feature dot-insts}}
+ uiOut[5] = __builtin_amdgcn_udot8(uiA, uiB, uiC, true); // expected-error {{'__builtin_amdgcn_udot8' needs target feature dot-insts}}
}
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-vi.cl b/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
index afa312cfcb12..220142122435 100644
--- a/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
+++ b/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
@@ -82,13 +82,27 @@ void test_s_memrealtime(global ulong* out)
*out = __builtin_amdgcn_s_memrealtime();
}
+// CHECK-LABEL: @test_s_dcache_wb()
+// CHECK: call void @llvm.amdgcn.s.dcache.wb()
+void test_s_dcache_wb()
+{
+ __builtin_amdgcn_s_dcache_wb();
+}
+
// CHECK-LABEL: @test_mov_dpp
-// CHECK: call i32 @llvm.amdgcn.mov.dpp.i32(i32 %src, i32 0, i32 0, i32 0, i1 false)
+// CHECK: call i32 @llvm.amdgcn.update.dpp.i32(i32 undef, i32 %src, i32 0, i32 0, i32 0, i1 false)
void test_mov_dpp(global int* out, int src)
{
*out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0, false);
}
+// CHECK-LABEL: @test_update_dpp
+// CHECK: call i32 @llvm.amdgcn.update.dpp.i32(i32 %arg1, i32 %arg2, i32 0, i32 0, i32 0, i1 false)
+void test_update_dpp(global int* out, int arg1, int arg2)
+{
+ *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0, false);
+}
+
// CHECK-LABEL: @test_ds_fadd
// CHECK: call float @llvm.amdgcn.ds.fadd(float addrspace(3)* %out, float %src, i32 0, i32 0, i1 false)
void test_ds_faddf(local float *out, float src) {
diff --git a/test/CodeGenOpenCL/builtins-amdgcn.cl b/test/CodeGenOpenCL/builtins-amdgcn.cl
index 2015f36e93dc..dc7f480209af 100644
--- a/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -1,6 +1,5 @@
// REQUIRES: amdgpu-registered-target
-// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple amdgcn-unknown-unknown-opencl -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck -enable-var-scope %s
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
@@ -20,19 +19,42 @@ void test_div_scale_f64(global double* out, global int* flagout, double a, doubl
*flagout = flag;
}
-// CHECK-LABEL: @test_div_scale_f32
+// CHECK-LABEL: @test_div_scale_f32(
// CHECK: call { float, i1 } @llvm.amdgcn.div.scale.f32(float %a, float %b, i1 true)
// CHECK-DAG: [[FLAG:%.+]] = extractvalue { float, i1 } %{{.+}}, 1
// CHECK-DAG: [[VAL:%.+]] = extractvalue { float, i1 } %{{.+}}, 0
-// CHECK: [[FLAGEXT:%.+]] = zext i1 [[FLAG]] to i32
-// CHECK: store i32 [[FLAGEXT]]
-void test_div_scale_f32(global float* out, global int* flagout, float a, float b)
+// CHECK: [[FLAGEXT:%.+]] = zext i1 [[FLAG]] to i8
+// CHECK: store i8 [[FLAGEXT]]
+void test_div_scale_f32(global float* out, global bool* flagout, float a, float b)
{
bool flag;
*out = __builtin_amdgcn_div_scalef(a, b, true, &flag);
*flagout = flag;
}
+// CHECK-LABEL: @test_div_scale_f32_global_ptr(
+// CHECK: call { float, i1 } @llvm.amdgcn.div.scale.f32(float %a, float %b, i1 true)
+// CHECK-DAG: [[FLAG:%.+]] = extractvalue { float, i1 } %{{.+}}, 1
+// CHECK-DAG: [[VAL:%.+]] = extractvalue { float, i1 } %{{.+}}, 0
+// CHECK: [[FLAGEXT:%.+]] = zext i1 [[FLAG]] to i8
+// CHECK: store i8 [[FLAGEXT]]
+void test_div_scale_f32_global_ptr(global float* out, global int* flagout, float a, float b, global bool* flag)
+{
+ *out = __builtin_amdgcn_div_scalef(a, b, true, flag);
+}
+
+// CHECK-LABEL: @test_div_scale_f32_generic_ptr(
+// CHECK: call { float, i1 } @llvm.amdgcn.div.scale.f32(float %a, float %b, i1 true)
+// CHECK-DAG: [[FLAG:%.+]] = extractvalue { float, i1 } %{{.+}}, 1
+// CHECK-DAG: [[VAL:%.+]] = extractvalue { float, i1 } %{{.+}}, 0
+// CHECK: [[FLAGEXT:%.+]] = zext i1 [[FLAG]] to i8
+// CHECK: store i8 [[FLAGEXT]]
+void test_div_scale_f32_generic_ptr(global float* out, global int* flagout, float a, float b, global bool* flag_arg)
+{
+ generic bool* flag = flag_arg;
+ *out = __builtin_amdgcn_div_scalef(a, b, true, flag);
+}
+
// CHECK-LABEL: @test_div_fmas_f32
// CHECK: call float @llvm.amdgcn.div.fmas.f32
void test_div_fmas_f32(global float* out, float a, float b, float c, int d)
@@ -414,42 +436,49 @@ void test_cubema(global float* out, float a, float b, float c) {
}
// CHECK-LABEL: @test_read_exec(
-// CHECK: call i64 @llvm.read_register.i64(metadata ![[EXEC:[0-9]+]]) #[[READ_EXEC_ATTRS:[0-9]+]]
+// CHECK: call i64 @llvm.read_register.i64(metadata ![[$EXEC:[0-9]+]]) #[[$READ_EXEC_ATTRS:[0-9]+]]
void test_read_exec(global ulong* out) {
*out = __builtin_amdgcn_read_exec();
}
-// CHECK: declare i64 @llvm.read_register.i64(metadata) #[[NOUNWIND_READONLY:[0-9]+]]
+// CHECK: declare i64 @llvm.read_register.i64(metadata) #[[$NOUNWIND_READONLY:[0-9]+]]
// CHECK-LABEL: @test_read_exec_lo(
-// CHECK: call i32 @llvm.read_register.i32(metadata ![[EXEC_LO:[0-9]+]]) #[[READ_EXEC_ATTRS]]
+// CHECK: call i32 @llvm.read_register.i32(metadata ![[$EXEC_LO:[0-9]+]]) #[[$READ_EXEC_ATTRS]]
void test_read_exec_lo(global uint* out) {
*out = __builtin_amdgcn_read_exec_lo();
}
// CHECK-LABEL: @test_read_exec_hi(
-// CHECK: call i32 @llvm.read_register.i32(metadata ![[EXEC_HI:[0-9]+]]) #[[READ_EXEC_ATTRS]]
+// CHECK: call i32 @llvm.read_register.i32(metadata ![[$EXEC_HI:[0-9]+]]) #[[$READ_EXEC_ATTRS]]
void test_read_exec_hi(global uint* out) {
*out = __builtin_amdgcn_read_exec_hi();
}
// CHECK-LABEL: @test_dispatch_ptr
// CHECK: call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr()
-void test_dispatch_ptr(__attribute__((address_space(4))) unsigned char ** out)
+void test_dispatch_ptr(__constant unsigned char ** out)
{
*out = __builtin_amdgcn_dispatch_ptr();
}
+// CHECK-LABEL: @test_queue_ptr
+// CHECK: call i8 addrspace(4)* @llvm.amdgcn.queue.ptr()
+void test_queue_ptr(__constant unsigned char ** out)
+{
+ *out = __builtin_amdgcn_queue_ptr();
+}
+
// CHECK-LABEL: @test_kernarg_segment_ptr
// CHECK: call i8 addrspace(4)* @llvm.amdgcn.kernarg.segment.ptr()
-void test_kernarg_segment_ptr(__attribute__((address_space(4))) unsigned char ** out)
+void test_kernarg_segment_ptr(__constant unsigned char ** out)
{
*out = __builtin_amdgcn_kernarg_segment_ptr();
}
// CHECK-LABEL: @test_implicitarg_ptr
// CHECK: call i8 addrspace(4)* @llvm.amdgcn.implicitarg.ptr()
-void test_implicitarg_ptr(__attribute__((address_space(4))) unsigned char ** out)
+void test_implicitarg_ptr(__constant unsigned char ** out)
{
*out = __builtin_amdgcn_implicitarg_ptr();
}
@@ -480,9 +509,9 @@ void test_s_getreg(volatile global uint *out)
}
// CHECK-LABEL: @test_get_local_id(
-// CHECK: tail call i32 @llvm.amdgcn.workitem.id.x(), !range [[WI_RANGE:![0-9]*]]
-// CHECK: tail call i32 @llvm.amdgcn.workitem.id.y(), !range [[WI_RANGE]]
-// CHECK: tail call i32 @llvm.amdgcn.workitem.id.z(), !range [[WI_RANGE]]
+// CHECK: tail call i32 @llvm.amdgcn.workitem.id.x(), !range [[$WI_RANGE:![0-9]*]]
+// CHECK: tail call i32 @llvm.amdgcn.workitem.id.y(), !range [[$WI_RANGE]]
+// CHECK: tail call i32 @llvm.amdgcn.workitem.id.z(), !range [[$WI_RANGE]]
void test_get_local_id(int d, global int *out)
{
switch (d) {
@@ -507,9 +536,9 @@ void test_s_getpc(global ulong* out)
*out = __builtin_amdgcn_s_getpc();
}
-// CHECK-DAG: [[WI_RANGE]] = !{i32 0, i32 1024}
-// CHECK-DAG: attributes #[[NOUNWIND_READONLY:[0-9]+]] = { nounwind readonly }
-// CHECK-DAG: attributes #[[READ_EXEC_ATTRS]] = { convergent }
-// CHECK-DAG: ![[EXEC]] = !{!"exec"}
-// CHECK-DAG: ![[EXEC_LO]] = !{!"exec_lo"}
-// CHECK-DAG: ![[EXEC_HI]] = !{!"exec_hi"}
+// CHECK-DAG: [[$WI_RANGE]] = !{i32 0, i32 1024}
+// CHECK-DAG: attributes #[[$NOUNWIND_READONLY:[0-9]+]] = { nounwind readonly }
+// CHECK-DAG: attributes #[[$READ_EXEC_ATTRS]] = { convergent }
+// CHECK-DAG: ![[$EXEC]] = !{!"exec"}
+// CHECK-DAG: ![[$EXEC_LO]] = !{!"exec_lo"}
+// CHECK-DAG: ![[$EXEC_HI]] = !{!"exec_hi"}
diff --git a/test/CodeGenOpenCL/builtins.cl b/test/CodeGenOpenCL/builtins.cl
new file mode 100644
index 000000000000..3fba83dcf5dc
--- /dev/null
+++ b/test/CodeGenOpenCL/builtins.cl
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 %s -finclude-default-header -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir-unknown-unknown" | FileCheck %s
+
+void testBranchingOnEnqueueKernel(queue_t default_queue, unsigned flags, ndrange_t ndrange) {
+ // Ensure `enqueue_kernel` can be branched upon.
+
+ if (enqueue_kernel(default_queue, flags, ndrange, ^(void) {}))
+ (void)0;
+ // CHECK: [[P:%[0-9]+]] = call i32 @__enqueue_kernel
+ // CHECK-NEXT: [[Q:%[a-z0-9]+]] = icmp ne i32 [[P]], 0
+ // CHECK-NEXT: br i1 [[Q]]
+
+ if (get_kernel_work_group_size(^(void) {}))
+ (void)0;
+ // CHECK: [[P:%[0-9]+]] = call i32 @__get_kernel_work_group_size
+ // CHECK-NEXT: [[Q:%[a-z0-9]+]] = icmp ne i32 [[P]], 0
+ // CHECK-NEXT: br i1 [[Q]]
+
+ if (get_kernel_preferred_work_group_size_multiple(^(void) {}))
+ (void)0;
+ // CHECK: [[P:%[0-9]+]] = call i32 @__get_kernel_preferred_work_group_size_multiple_impl
+ // CHECK-NEXT: [[Q:%[a-z0-9]+]] = icmp ne i32 [[P]], 0
+ // CHECK-NEXT: br i1 [[Q]]
+}
+
+void testBranchinOnPipeOperations(read_only pipe int r, write_only pipe int w, global int* ptr) {
+ // Verify that return type is correctly casted to i1 value.
+
+ if (read_pipe(r, ptr))
+ (void)0;
+ // CHECK: [[R:%[0-9]+]] = call i32 @__read_pipe_2
+ // CHECK-NEXT: icmp ne i32 [[R]], 0
+
+ if (write_pipe(w, ptr))
+ (void)0;
+ // CHECK: [[R:%[0-9]+]] = call i32 @__write_pipe_2
+ // CHECK-NEXT: icmp ne i32 [[R]], 0
+
+ if (get_pipe_num_packets(r))
+ (void)0;
+ // CHECK: [[R:%[0-9]+]] = call i32 @__get_pipe_num_packets_ro
+ // CHECK-NEXT: icmp ne i32 [[R]], 0
+
+ if (get_pipe_num_packets(w))
+ (void)0;
+ // CHECK: [[R:%[0-9]+]] = call i32 @__get_pipe_num_packets_wo
+ // CHECK-NEXT: icmp ne i32 [[R]], 0
+
+ if (get_pipe_max_packets(r))
+ (void)0;
+ // CHECK: [[R:%[0-9]+]] = call i32 @__get_pipe_max_packets_ro
+ // CHECK-NEXT: icmp ne i32 [[R]], 0
+
+ if (get_pipe_max_packets(w))
+ (void)0;
+ // CHECK: [[R:%[0-9]+]] = call i32 @__get_pipe_max_packets_wo
+ // CHECK-NEXT: icmp ne i32 [[R]], 0
+}
+
+void testBranchingOnAddressSpaceCast(generic long* ptr) {
+ // Verify that pointer types are properly casted, respecting address spaces.
+
+ if (to_global(ptr))
+ (void)0;
+ // CHECK: [[P:%[0-9]+]] = call [[GLOBAL_VOID:i8 addrspace\(1\)\*]] @__to_global([[GENERIC_VOID:i8 addrspace\(4\)\*]] {{%[0-9]+}})
+ // CHECK-NEXT: [[Q:%[0-9]+]] = bitcast [[GLOBAL_VOID]] [[P]] to [[GLOBAL_i64:i64 addrspace\(1\)\*]]
+ // CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne [[GLOBAL_i64]] [[Q]], null
+ // CHECK-NEXT: br i1 [[BOOL]]
+
+ if (to_local(ptr))
+ (void)0;
+ // CHECK: [[P:%[0-9]+]] = call [[LOCAL_VOID:i8 addrspace\(3\)\*]] @__to_local([[GENERIC_VOID]] {{%[0-9]+}})
+ // CHECK-NEXT: [[Q:%[0-9]+]] = bitcast [[LOCAL_VOID]] [[P]] to [[LOCAL_i64:i64 addrspace\(3\)\*]]
+ // CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne [[LOCAL_i64]] [[Q]], null
+ // CHECK-NEXT: br i1 [[BOOL]]
+
+ if (to_private(ptr))
+ (void)0;
+ // CHECK: [[P:%[0-9]+]] = call [[PRIVATE_VOID:i8\*]] @__to_private([[GENERIC_VOID]] {{%[0-9]+}})
+ // CHECK-NEXT: [[Q:%[0-9]+]] = bitcast [[PRIVATE_VOID]] [[P]] to [[PRIVATE_i64:i64\*]]
+ // CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne [[PRIVATE_i64]] [[Q]], null
+ // CHECK-NEXT: br i1 [[BOOL]]
+}
+
diff --git a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
index d74a1dfbd484..473219478a2f 100644
--- a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
+++ b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
@@ -1,30 +1,33 @@
// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O0 -emit-llvm -o - -triple "spir-unknown-unknown" | FileCheck %s --check-prefix=COMMON --check-prefix=B32
// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" | FileCheck %s --check-prefix=COMMON --check-prefix=B64
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O1 -emit-llvm -o - -triple "spir64-unknown-unknown" | FileCheck %s --check-prefix=CHECK-LIFETIMES
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
typedef void (^bl_t)(local void *);
typedef struct {int a;} ndrange_t;
+// COMMON: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* }
+
// For a block global variable, first emit the block literal as a global variable, then emit the block variable itself.
-// COMMON: [[BL_GLOBAL:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BL_GLOBAL]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*)
+// COMMON: [[BL_GLOBAL:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INV_G:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
+// COMMON: @block_G = addrspace(1) constant void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*)
// For anonymous blocks without captures, emit block literals as global variable.
-// COMMON: [[BLG1:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG2:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG3:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG4:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG5:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG6:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG7:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG8:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG9:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG10:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
-// COMMON: [[BLG11:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32 } { i32 {{[0-9]+}}, i32 {{[0-9]+}} }
+// COMMON: [[BLG1:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG2:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG3:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG4:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG5:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG6:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*, i8 addrspace(3)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG7:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG8:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVG8:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG9:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* [[INVG9:@[^ ]+]] to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG10:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
+// COMMON: [[BLG11:@__block_literal_global[^ ]*]] = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 {{[0-9]+}}, i32 {{[0-9]+}}, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* {{@[^ ]+}} to i8*) to i8 addrspace(4)*) }
// Emits block literal [[BL_GLOBAL]], invoke function [[INV_G]] and global block variable @block_G
-// COMMON: define internal spir_func void [[INV_G:.*]](i8 addrspace(4)* %{{.*}}, i8 addrspace(3)* %{{.*}})
+// COMMON: define internal spir_func void [[INV_G]](i8 addrspace(4)* %{{.*}}, i8 addrspace(3)* %{{.*}})
const bl_t block_G = (bl_t) ^ (local void *a) {};
void callee(int id, __global int *out) {
@@ -46,12 +49,36 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: %event_wait_list2 = alloca [1 x %opencl.clk_event_t*]
clk_event_t event_wait_list2[] = {clk_event};
- // Emits block literal on stack and block kernel [[INVLK1]].
// COMMON: [[NDR:%[a-z0-9]+]] = alloca %struct.ndrange_t, align 4
+
+ // B32: %[[BLOCK_SIZES1:.*]] = alloca [1 x i32]
+ // B64: %[[BLOCK_SIZES1:.*]] = alloca [1 x i64]
+ // CHECK-LIFETIMES: %[[BLOCK_SIZES1:.*]] = alloca [1 x i64]
+ // B32: %[[BLOCK_SIZES2:.*]] = alloca [1 x i32]
+ // B64: %[[BLOCK_SIZES2:.*]] = alloca [1 x i64]
+ // CHECK-LIFETIMES: %[[BLOCK_SIZES2:.*]] = alloca [1 x i64]
+ // B32: %[[BLOCK_SIZES3:.*]] = alloca [1 x i32]
+ // B64: %[[BLOCK_SIZES3:.*]] = alloca [1 x i64]
+ // CHECK-LIFETIMES: %[[BLOCK_SIZES3:.*]] = alloca [1 x i64]
+ // B32: %[[BLOCK_SIZES4:.*]] = alloca [1 x i32]
+ // B64: %[[BLOCK_SIZES4:.*]] = alloca [1 x i64]
+ // CHECK-LIFETIMES: %[[BLOCK_SIZES4:.*]] = alloca [1 x i64]
+ // B32: %[[BLOCK_SIZES5:.*]] = alloca [1 x i32]
+ // B64: %[[BLOCK_SIZES5:.*]] = alloca [1 x i64]
+ // CHECK-LIFETIMES: %[[BLOCK_SIZES5:.*]] = alloca [1 x i64]
+ // B32: %[[BLOCK_SIZES6:.*]] = alloca [3 x i32]
+ // B64: %[[BLOCK_SIZES6:.*]] = alloca [3 x i64]
+ // CHECK-LIFETIMES: %[[BLOCK_SIZES6:.*]] = alloca [3 x i64]
+ // B32: %[[BLOCK_SIZES7:.*]] = alloca [1 x i32]
+ // B64: %[[BLOCK_SIZES7:.*]] = alloca [1 x i64]
+ // CHECK-LIFETIMES: %[[BLOCK_SIZES7:.*]] = alloca [1 x i64]
+
+ // Emits block literal on stack and block kernel [[INVLK1]].
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // B32: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32 addrspace(1)*, i32, i32 addrspace(1)* }>* %block to void ()*
- // B64: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32 addrspace(1)*, i32 addrspace(1)*, i32 }>* %block to void ()*
+ // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL1:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
+ // B32: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }>* %block to void ()*
+ // B64: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 }>* %block to void ()*
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)*
// COMMON-LABEL: call i32 @__enqueue_kernel_basic(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}},
@@ -67,54 +94,68 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
// COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %event_wait_list to %opencl.clk_event_t{{.*}}* addrspace(4)*
// COMMON: [[EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %clk_event to %opencl.clk_event_t{{.*}}* addrspace(4)*
- // COMMON: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
+ // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL2:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
+ // COMMON: [[BL:%[0-9]+]] = bitcast <{ i32, i32, i8 addrspace(4)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* [[BL]] to i8 addrspace(4)*
// COMMON-LABEL: call i32 @__enqueue_kernel_basic_events
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]],
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVLK2:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
// COMMON-SAME: i8 addrspace(4)* [[BL_I8]])
-
enqueue_kernel(default_queue, flags, ndrange, 2, &event_wait_list, &clk_event,
^(void) {
a[i] = b[i];
});
+ // COMMON-LABEL: call i32 @__enqueue_kernel_basic_events
+ // COMMON-SAME: (%opencl.queue_t{{.*}}* {{%[0-9]+}}, i32 {{%[0-9]+}}, %struct.ndrange_t* {{.*}}, i32 1, %opencl.clk_event_t{{.*}}* addrspace(4)* {{%[0-9]+}}, %opencl.clk_event_t{{.*}}* addrspace(4)* null,
+ enqueue_kernel(default_queue, flags, ndrange, 1, &event_wait_list, 0,
+ ^(void) {
+ return;
+ });
+
// Emits global block literal [[BLG1]] and block kernel [[INVGK1]].
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // B32: %[[TMP:.*]] = alloca [1 x i32]
- // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0
- // B32: store i32 256, i32* %[[TMP1]], align 4
- // B64: %[[TMP:.*]] = alloca [1 x i64]
- // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
- // B64: store i64 256, i64* %[[TMP1]], align 8
+ // CHECK-LIFETIMES: [[LIFETIME_PTR:%[0-9]+]] = bitcast [1 x i64]* %[[BLOCK_SIZES1]] to i8*
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // CHECK-LIFETIMES-NEXT: getelementptr inbounds [1 x i64], [1 x i64]* %[[BLOCK_SIZES1]], i64 0, i64 0
+ // CHECK-LIFETIMES-LABEL: call i32 @__enqueue_kernel_varargs(
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // B32: %[[TMP:.*]] = getelementptr [1 x i32], [1 x i32]* %[[BLOCK_SIZES1]], i32 0, i32 0
+ // B32: store i32 256, i32* %[[TMP]], align 4
+ // B64: %[[TMP:.*]] = getelementptr [1 x i64], [1 x i64]* %[[BLOCK_SIZES1]], i32 0, i32 0
+ // B64: store i64 256, i64* %[[TMP]], align 8
// COMMON-LABEL: call i32 @__enqueue_kernel_varargs(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK1:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG1]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
- // B32-SAME: i32* %[[TMP1]])
- // B64-SAME: i64* %[[TMP1]])
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG1]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // B32-SAME: i32* %[[TMP]])
+ // B64-SAME: i64* %[[TMP]])
enqueue_kernel(default_queue, flags, ndrange,
^(local void *p) {
return;
},
256);
+
char c;
// Emits global block literal [[BLG2]] and block kernel [[INVGK2]].
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // B32: %[[TMP:.*]] = alloca [1 x i32]
- // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0
- // B32: store i32 %{{.*}}, i32* %[[TMP1]], align 4
- // B64: %[[TMP:.*]] = alloca [1 x i64]
- // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
- // B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8
+ // CHECK-LIFETIMES: [[LIFETIME_PTR:%[0-9]+]] = bitcast [1 x i64]* %[[BLOCK_SIZES2]] to i8*
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // CHECK-LIFETIMES-NEXT: getelementptr inbounds [1 x i64], [1 x i64]* %[[BLOCK_SIZES2]], i64 0, i64 0
+ // CHECK-LIFETIMES-LABEL: call i32 @__enqueue_kernel_varargs(
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // B32: %[[TMP:.*]] = getelementptr [1 x i32], [1 x i32]* %[[BLOCK_SIZES2]], i32 0, i32 0
+ // B32: store i32 %{{.*}}, i32* %[[TMP]], align 4
+ // B64: %[[TMP:.*]] = getelementptr [1 x i64], [1 x i64]* %[[BLOCK_SIZES2]], i32 0, i32 0
+ // B64: store i64 %{{.*}}, i64* %[[TMP]], align 8
// COMMON-LABEL: call i32 @__enqueue_kernel_varargs(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK2:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG2]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
- // B32-SAME: i32* %[[TMP1]])
- // B64-SAME: i64* %[[TMP1]])
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG2]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // B32-SAME: i32* %[[TMP]])
+ // B64-SAME: i64* %[[TMP]])
enqueue_kernel(default_queue, flags, ndrange,
^(local void *p) {
return;
@@ -127,18 +168,21 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0
// COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** [[AD]] to %opencl.clk_event_t{{.*}}* addrspace(4)*
// COMMON: [[EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %clk_event to %opencl.clk_event_t{{.*}}* addrspace(4)*
- // B32: %[[TMP:.*]] = alloca [1 x i32]
- // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0
- // B32: store i32 256, i32* %[[TMP1]], align 4
- // B64: %[[TMP:.*]] = alloca [1 x i64]
- // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
- // B64: store i64 256, i64* %[[TMP1]], align 8
+ // CHECK-LIFETIMES: [[LIFETIME_PTR:%[0-9]+]] = bitcast [1 x i64]* %[[BLOCK_SIZES3]] to i8*
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // CHECK-LIFETIMES-NEXT: getelementptr inbounds [1 x i64], [1 x i64]* %[[BLOCK_SIZES3]], i64 0, i64 0
+ // CHECK-LIFETIMES-LABEL: call i32 @__enqueue_kernel_events_varargs(
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // B32: %[[TMP:.*]] = getelementptr [1 x i32], [1 x i32]* %[[BLOCK_SIZES3]], i32 0, i32 0
+ // B32: store i32 256, i32* %[[TMP]], align 4
+ // B64: %[[TMP:.*]] = getelementptr [1 x i64], [1 x i64]* %[[BLOCK_SIZES3]], i32 0, i32 0
+ // B64: store i64 256, i64* %[[TMP]], align 8
// COMMON-LABEL: call i32 @__enqueue_kernel_events_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]],
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK3:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG3]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
- // B32-SAME: i32* %[[TMP1]])
- // B64-SAME: i64* %[[TMP1]])
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG3]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // B32-SAME: i32* %[[TMP]])
+ // B64-SAME: i64* %[[TMP]])
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
^(local void *p) {
return;
@@ -151,18 +195,21 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0
// COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** [[AD]] to %opencl.clk_event_t{{.*}}* addrspace(4)*
// COMMON: [[EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** %clk_event to %opencl.clk_event_t{{.*}}* addrspace(4)*
- // B32: %[[TMP:.*]] = alloca [1 x i32]
- // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0
- // B32: store i32 %{{.*}}, i32* %[[TMP1]], align 4
- // B64: %[[TMP:.*]] = alloca [1 x i64]
- // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
- // B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8
+ // CHECK-LIFETIMES: [[LIFETIME_PTR:%[0-9]+]] = bitcast [1 x i64]* %[[BLOCK_SIZES4]] to i8*
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // CHECK-LIFETIMES-NEXT: getelementptr inbounds [1 x i64], [1 x i64]* %[[BLOCK_SIZES4]], i64 0, i64 0
+ // CHECK-LIFETIMES-LABEL: call i32 @__enqueue_kernel_events_varargs(
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // B32: %[[TMP:.*]] = getelementptr [1 x i32], [1 x i32]* %[[BLOCK_SIZES4]], i32 0, i32 0
+ // B32: store i32 %{{.*}}, i32* %[[TMP]], align 4
+ // B64: %[[TMP:.*]] = getelementptr [1 x i64], [1 x i64]* %[[BLOCK_SIZES4]], i32 0, i32 0
+ // B64: store i64 %{{.*}}, i64* %[[TMP]], align 8
// COMMON-LABEL: call i32 @__enqueue_kernel_events_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]],
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK4:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG4]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
- // B32-SAME: i32* %[[TMP1]])
- // B64-SAME: i64* %[[TMP1]])
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG4]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // B32-SAME: i32* %[[TMP]])
+ // B64-SAME: i64* %[[TMP]])
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
^(local void *p) {
return;
@@ -173,18 +220,21 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// Emits global block literal [[BLG5]] and block kernel [[INVGK5]].
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // B32: %[[TMP:.*]] = alloca [1 x i32]
- // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0
- // B32: store i32 %{{.*}}, i32* %[[TMP1]], align 4
- // B64: %[[TMP:.*]] = alloca [1 x i64]
- // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
- // B64: store i64 %{{.*}}, i64* %[[TMP1]], align 8
+ // CHECK-LIFETIMES: [[LIFETIME_PTR:%[0-9]+]] = bitcast [1 x i64]* %[[BLOCK_SIZES5]] to i8*
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // CHECK-LIFETIMES-NEXT: getelementptr inbounds [1 x i64], [1 x i64]* %[[BLOCK_SIZES5]], i64 0, i64 0
+ // CHECK-LIFETIMES-LABEL: call i32 @__enqueue_kernel_varargs(
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // B32: %[[TMP:.*]] = getelementptr [1 x i32], [1 x i32]* %[[BLOCK_SIZES5]], i32 0, i32 0
+ // B32: store i32 %{{.*}}, i32* %[[TMP]], align 4
+ // B64: %[[TMP:.*]] = getelementptr [1 x i64], [1 x i64]* %[[BLOCK_SIZES5]], i32 0, i32 0
+ // B64: store i64 %{{.*}}, i64* %[[TMP]], align 8
// COMMON-LABEL: call i32 @__enqueue_kernel_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK5:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG5]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
- // B32-SAME: i32* %[[TMP1]])
- // B64-SAME: i64* %[[TMP1]])
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG5]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // B32-SAME: i32* %[[TMP]])
+ // B64-SAME: i64* %[[TMP]])
enqueue_kernel(default_queue, flags, ndrange,
^(local void *p) {
return;
@@ -194,26 +244,29 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// Emits global block literal [[BLG6]] and block kernel [[INVGK6]].
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // B32: %[[TMP:.*]] = alloca [3 x i32]
- // B32: %[[TMP1:.*]] = getelementptr [3 x i32], [3 x i32]* %[[TMP]], i32 0, i32 0
- // B32: store i32 1, i32* %[[TMP1]], align 4
- // B32: %[[TMP2:.*]] = getelementptr [3 x i32], [3 x i32]* %[[TMP]], i32 0, i32 1
- // B32: store i32 2, i32* %[[TMP2]], align 4
- // B32: %[[TMP3:.*]] = getelementptr [3 x i32], [3 x i32]* %[[TMP]], i32 0, i32 2
- // B32: store i32 4, i32* %[[TMP3]], align 4
- // B64: %[[TMP:.*]] = alloca [3 x i64]
- // B64: %[[TMP1:.*]] = getelementptr [3 x i64], [3 x i64]* %[[TMP]], i32 0, i32 0
- // B64: store i64 1, i64* %[[TMP1]], align 8
- // B64: %[[TMP2:.*]] = getelementptr [3 x i64], [3 x i64]* %[[TMP]], i32 0, i32 1
- // B64: store i64 2, i64* %[[TMP2]], align 8
- // B64: %[[TMP3:.*]] = getelementptr [3 x i64], [3 x i64]* %[[TMP]], i32 0, i32 2
- // B64: store i64 4, i64* %[[TMP3]], align 8
+ // CHECK-LIFETIMES: [[LIFETIME_PTR:%[0-9]+]] = bitcast [3 x i64]* %[[BLOCK_SIZES6]] to i8*
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.start.p0i8(i64 24, i8* nonnull [[LIFETIME_PTR]])
+ // CHECK-LIFETIMES-NEXT: getelementptr inbounds [3 x i64], [3 x i64]* %[[BLOCK_SIZES6]], i64 0, i64 0
+ // CHECK-LIFETIMES-LABEL: call i32 @__enqueue_kernel_varargs(
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.end.p0i8(i64 24, i8* nonnull [[LIFETIME_PTR]])
+ // B32: %[[TMP:.*]] = getelementptr [3 x i32], [3 x i32]* %[[BLOCK_SIZES6]], i32 0, i32 0
+ // B32: store i32 1, i32* %[[TMP]], align 4
+ // B32: %[[BLOCK_SIZES62:.*]] = getelementptr [3 x i32], [3 x i32]* %[[BLOCK_SIZES6]], i32 0, i32 1
+ // B32: store i32 2, i32* %[[BLOCK_SIZES62]], align 4
+ // B32: %[[BLOCK_SIZES63:.*]] = getelementptr [3 x i32], [3 x i32]* %[[BLOCK_SIZES6]], i32 0, i32 2
+ // B32: store i32 4, i32* %[[BLOCK_SIZES63]], align 4
+ // B64: %[[TMP:.*]] = getelementptr [3 x i64], [3 x i64]* %[[BLOCK_SIZES6]], i32 0, i32 0
+ // B64: store i64 1, i64* %[[TMP]], align 8
+ // B64: %[[BLOCK_SIZES62:.*]] = getelementptr [3 x i64], [3 x i64]* %[[BLOCK_SIZES6]], i32 0, i32 1
+ // B64: store i64 2, i64* %[[BLOCK_SIZES62]], align 8
+ // B64: %[[BLOCK_SIZES63:.*]] = getelementptr [3 x i64], [3 x i64]* %[[BLOCK_SIZES6]], i32 0, i32 2
+ // B64: store i64 4, i64* %[[BLOCK_SIZES63]], align 8
// COMMON-LABEL: call i32 @__enqueue_kernel_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK6:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG6]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3,
- // B32-SAME: i32* %[[TMP1]])
- // B64-SAME: i64* %[[TMP1]])
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG6]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 3,
+ // B32-SAME: i32* %[[TMP]])
+ // B64-SAME: i64* %[[TMP]])
enqueue_kernel(default_queue, flags, ndrange,
^(local void *p1, local void *p2, local void *p3) {
return;
@@ -223,18 +276,21 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// Emits global block literal [[BLG7]] and block kernel [[INVGK7]].
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // B32: %[[TMP:.*]] = alloca [1 x i32]
- // B32: %[[TMP1:.*]] = getelementptr [1 x i32], [1 x i32]* %[[TMP]], i32 0, i32 0
- // B32: store i32 0, i32* %[[TMP1]], align 4
- // B64: %[[TMP:.*]] = alloca [1 x i64]
- // B64: %[[TMP1:.*]] = getelementptr [1 x i64], [1 x i64]* %[[TMP]], i32 0, i32 0
- // B64: store i64 4294967296, i64* %[[TMP1]], align 8
+ // CHECK-LIFETIMES: [[LIFETIME_PTR:%[0-9]+]] = bitcast [1 x i64]* %[[BLOCK_SIZES7]] to i8*
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // CHECK-LIFETIMES-NEXT: getelementptr inbounds [1 x i64], [1 x i64]* %[[BLOCK_SIZES7]], i64 0, i64 0
+ // CHECK-LIFETIMES-LABEL: call i32 @__enqueue_kernel_varargs(
+ // CHECK-LIFETIMES-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull [[LIFETIME_PTR]])
+ // B32: %[[TMP:.*]] = getelementptr [1 x i32], [1 x i32]* %[[BLOCK_SIZES7]], i32 0, i32 0
+ // B32: store i32 0, i32* %[[TMP]], align 4
+ // B64: %[[TMP:.*]] = getelementptr [1 x i64], [1 x i64]* %[[BLOCK_SIZES7]], i32 0, i32 0
+ // B64: store i64 4294967296, i64* %[[TMP]], align 8
// COMMON-LABEL: call i32 @__enqueue_kernel_varargs
// COMMON-SAME: (%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK7:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG7]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
- // B32-SAME: i32* %[[TMP1]])
- // B64-SAME: i64* %[[TMP1]])
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG7]] to i8 addrspace(1)*) to i8 addrspace(4)*), i32 1,
+ // B32-SAME: i32* %[[TMP]])
+ // B64-SAME: i64* %[[TMP]])
enqueue_kernel(default_queue, flags, ndrange,
^(local void *p) {
return;
@@ -244,19 +300,21 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// Emits global block literal [[BLG8]] and invoke function [[INVG8]].
// The full type of these expressions are long (and repeated elsewhere), so we
// capture it as part of the regex for convenience and clarity.
- // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A
+ // COMMON: store void () addrspace(4)* addrspacecast (void () addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to void () addrspace(1)*) to void () addrspace(4)*), void () addrspace(4)** %block_A
void (^const block_A)(void) = ^{
return;
};
// Emits global block literal [[BLG9]] and invoke function [[INVG9]].
- // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG9]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B
+ // COMMON: store void (i8 addrspace(3)*) addrspace(4)* addrspacecast (void (i8 addrspace(3)*) addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to void (i8 addrspace(3)*) addrspace(1)*) to void (i8 addrspace(3)*) addrspace(4)*), void (i8 addrspace(3)*) addrspace(4)** %block_B
void (^const block_B)(local void *) = ^(local void *a) {
return;
};
// Uses global block literal [[BLG8]] and invoke function [[INVG8]].
- // COMMON: call spir_func void [[INVG8:.*]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2)
+ // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)*
+ // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
block_A();
// Emits global block literal [[BLG8]] and block kernel [[INVGK8]]. [[INVGK8]] calls [[INVG8]].
@@ -265,17 +323,19 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON-LABEL: call i32 @__enqueue_kernel_basic(
// COMMON-SAME: %opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %struct.ndrange_t* byval [[NDR]]{{([0-9]+)?}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
enqueue_kernel(default_queue, flags, ndrange, block_A);
// Uses block kernel [[INVGK8]] and global block literal [[BLG8]].
// COMMON: call i32 @__get_kernel_work_group_size_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
unsigned size = get_kernel_work_group_size(block_A);
// Uses global block literal [[BLG8]] and invoke function [[INVG8]]. Make sure no redundant block literal and invoke functions are emitted.
- // COMMON: call spir_func void [[INVG8]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON: [[r1:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* getelementptr inbounds (%struct.__opencl_block_literal_generic, %struct.__opencl_block_literal_generic addrspace(4)* addrspacecast (%struct.__opencl_block_literal_generic addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to %struct.__opencl_block_literal_generic addrspace(1)*) to %struct.__opencl_block_literal_generic addrspace(4)*), i32 0, i32 2)
+ // COMMON: [[r2:%.*]] = addrspacecast i8 addrspace(4)* [[r1]] to void (i8 addrspace(4)*)*
+ // COMMON: call spir_func void [[r2]](i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
block_A();
void (^block_C)(void) = ^{
@@ -283,6 +343,7 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
};
// Emits block literal on stack and block kernel [[INVLK3]].
+ // COMMON: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* [[INVL3:@__device_side_enqueue_block_invoke[^ ]*]] to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %block.invoke
// COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
// COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
// COMMON: [[BL_I8:%[0-9]+]] = addrspacecast void ()* {{.*}} to i8 addrspace(4)*
@@ -292,34 +353,34 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON-SAME: i8 addrspace(4)* [[BL_I8]])
enqueue_kernel(default_queue, flags, ndrange, block_C);
- // Emits global block literal [[BLG9]] and block kernel [[INVGK9]]. [[INVGK9]] calls [[INVG9]].
+ // Emits global block literal [[BLG9]] and block kernel [[INVGK9]]. [[INVGK9]] calls [[INV9]].
// COMMON: call i32 @__get_kernel_work_group_size_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK9:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG9]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG9]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_work_group_size(block_B);
// Uses global block literal [[BLG8]] and block kernel [[INVGK8]]. Make sure no redundant block literal ind invoke functions are emitted.
// COMMON: call i32 @__get_kernel_preferred_work_group_size_multiple_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK8]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG8]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_preferred_work_group_size_multiple(block_A);
// Uses global block literal [[BL_GLOBAL]] and block kernel [[INV_G_K]]. [[INV_G_K]] calls [[INV_G]].
// COMMON: call i32 @__get_kernel_preferred_work_group_size_multiple_impl(
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INV_G_K:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BL_GLOBAL]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_preferred_work_group_size_multiple(block_G);
// Emits global block literal [[BLG10]] and block kernel [[INVGK10]].
// COMMON: call i32 @__get_kernel_max_sub_group_size_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK10:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG10]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG10]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_max_sub_group_size_for_ndrange(ndrange, ^(){});
// Emits global block literal [[BLG11]] and block kernel [[INVGK11]].
// COMMON: call i32 @__get_kernel_sub_group_count_for_ndrange_impl(%struct.ndrange_t* {{[^,]+}},
// COMMON-SAME: i8 addrspace(4)* addrspacecast (i8* bitcast ({{.*}} [[INVGK11:[^ ]+_kernel]] to i8*) to i8 addrspace(4)*),
- // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32 } addrspace(1)* [[BLG11]] to i8 addrspace(1)*) to i8 addrspace(4)*))
+ // COMMON-SAME: i8 addrspace(4)* addrspacecast (i8 addrspace(1)* bitcast ({ i32, i32, i8 addrspace(4)* } addrspace(1)* [[BLG11]] to i8 addrspace(1)*) to i8 addrspace(4)*))
size = get_kernel_sub_group_count_for_ndrange(ndrange, ^(){});
}
@@ -336,12 +397,12 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
// COMMON: define internal spir_kernel void [[INVGK5]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
// COMMON: define internal spir_kernel void [[INVGK6]](i8 addrspace(4)*, i8 addrspace(3)*, i8 addrspace(3)*, i8 addrspace(3)*) #{{[0-9]+}} {
// COMMON: entry:
-// COMMON: call void @__device_side_enqueue_block_invoke_8(i8 addrspace(4)* %0, i8 addrspace(3)* %1, i8 addrspace(3)* %2, i8 addrspace(3)* %3)
+// COMMON: call void @__device_side_enqueue_block_invoke_9(i8 addrspace(4)* %0, i8 addrspace(3)* %1, i8 addrspace(3)* %2, i8 addrspace(3)* %3)
// COMMON: ret void
// COMMON: }
// COMMON: define internal spir_kernel void [[INVGK7]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
// COMMON: define internal spir_func void [[INVG8]](i8 addrspace(4)*{{.*}})
-// COMMON: define internal spir_func void [[INVG9:.*]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)* %{{.*}})
+// COMMON: define internal spir_func void [[INVG9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)* %{{.*}})
// COMMON: define internal spir_kernel void [[INVGK8]](i8 addrspace(4)*{{.*}})
// COMMON: define internal spir_kernel void [[INVLK3]](i8 addrspace(4)*{{.*}})
// COMMON: define internal spir_kernel void [[INVGK9]](i8 addrspace(4)*{{.*}}, i8 addrspace(3)*{{.*}})
diff --git a/test/CodeGenOpenCL/constant-addr-space-globals.cl b/test/CodeGenOpenCL/constant-addr-space-globals.cl
index 7bb970527c26..5fcf117dde33 100644
--- a/test/CodeGenOpenCL/constant-addr-space-globals.cl
+++ b/test/CodeGenOpenCL/constant-addr-space-globals.cl
@@ -13,8 +13,8 @@ kernel void test(global float *out) {
void foo(constant int* p, constant const int *p1, const int *p2, const int *p3);
// CHECK: @k.arr1 = internal addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3]
-// CHECK: @k.arr2 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 4, i32 5, i32 6]
-// CHECK: @k.arr3 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 7, i32 8, i32 9]
+// CHECK: @__const.k.arr2 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 4, i32 5, i32 6]
+// CHECK: @__const.k.arr3 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 7, i32 8, i32 9]
// CHECK: @k.var1 = internal addrspace(2) constant i32 1
kernel void k(void) {
// CHECK-NOT: %arr1 = alloca [3 x i32]
diff --git a/test/CodeGenOpenCL/denorms-are-zero.cl b/test/CodeGenOpenCL/denorms-are-zero.cl
index ab8bf7641c87..d572b1321124 100644
--- a/test/CodeGenOpenCL/denorms-are-zero.cl
+++ b/test/CodeGenOpenCL/denorms-are-zero.cl
@@ -1,8 +1,26 @@
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - %s | FileCheck %s --check-prefix=DENORM-ZERO
-// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck %s --check-prefix=AMDGCN
-// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck %s --check-prefix=AMDGCN-DENORM
-// RUN: %clang_cc1 -emit-llvm -target-feature +fp32-denormals -target-feature -fp64-fp16-denormals -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck --check-prefix=AMDGCN-FEATURE %s
+// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - %s | FileCheck -check-prefix=DENORM-ZERO %s
+
+// Slow FMAF and slow f32 denormals
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa -target-cpu pitcairn %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FLUSH %s
+// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu pitcairn %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FLUSH-OPT %s
+
+// Fast FMAF, but slow f32 denormals
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa -target-cpu tahiti %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FLUSH %s
+// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu tahiti %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FLUSH-OPT %s
+
+// Fast F32 denormals, but slow FMAF
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FLUSH %s
+// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FLUSH-OPT %s
+
+// Fast F32 denormals and fast FMAF
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa -target-cpu gfx900 %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-DENORM %s
+// RUN: %clang_cc1 -emit-llvm -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu gfx900 %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FLUSH-OPT %s
+
+// RUN: %clang_cc1 -emit-llvm -target-feature +fp32-denormals -target-feature -fp64-fp16-denormals -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FEATURE %s
+// RUN: %clang_cc1 -emit-llvm -target-feature +fp32-denormals -target-feature -fp64-fp16-denormals -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu pitcairn %s | FileCheck -check-prefixes=AMDGCN,AMDGCN-FEATURE %s
+
+
// For all targets 'denorms-are-zero' attribute is set to 'true'
// if '-cl-denorms-are-zero' was specified and to 'false' otherwise.
@@ -17,9 +35,11 @@
// explicitly set. amdgcn target always do not flush fp64 denormals. The control for fp64 and fp16 denormals is the same.
// AMDGCN-LABEL: define void @f()
-// AMDGCN: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="true" {{.*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
-// AMDGCN-DENORM-LABEL: define void @f()
-// AMDGCN-DENORM: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="false" {{.*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
-// AMDGCN-FEATURE-LABEL: define void @f()
+
+// AMDGCN-FLUSH: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="false" {{.*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
+// AMDGCN-FLUSH-OPT: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="true" {{.*}} "target-features"="{{[^"]*}}+fp64-fp16-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
+
+// AMDGCN-DENORM: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="false" {{.*}} "target-features"="{{[^"]*}}+fp32-denormals,{{[^"]*}}+fp64-fp16-denormals{{[^"]*}}"
+
// AMDGCN-FEATURE: attributes #{{[0-9]*}} = {{{[^}]*}} "denorms-are-zero"="true" {{.*}} "target-features"="{{[^"]*}}+fp32-denormals,{{[^"]*}}-fp64-fp16-denormals{{[^"]*}}"
void f() {}
diff --git a/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl b/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl
new file mode 100644
index 000000000000..8b5c5df2e4ba
--- /dev/null
+++ b/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=COMMON,AMDGPU
+// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR32
+// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR64
+// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -debug-info-kind=limited -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=CHECK-DEBUG
+
+// Check that the enqueue_kernel array temporary is in the entry block to avoid
+// a dynamic alloca
+
+typedef struct {int a;} ndrange_t;
+
+kernel void test(int i) {
+// COMMON-LABEL: define {{.*}} void @test
+// COMMON-LABEL: entry:
+// AMDGPU: %block_sizes = alloca [1 x i64]
+// SPIR32: %block_sizes = alloca [1 x i32]
+// SPIR64: %block_sizes = alloca [1 x i64]
+// COMMON-LABEL: if.then:
+// COMMON-NOT: alloca
+// CHECK-DEBUG: getelementptr {{.*}} %block_sizes, {{.*}} !dbg ![[TEMPLOCATION:[0-9]+]]
+// COMMON-LABEL: if.end
+ queue_t default_queue;
+ unsigned flags = 0;
+ ndrange_t ndrange;
+ if (i)
+ enqueue_kernel(default_queue, flags, ndrange, ^(local void *a) { }, 32);
+}
+
+// Check that the temporary is scoped to the `if`
+
+// CHECK-DEBUG: ![[TESTFILE:[0-9]+]] = !DIFile(filename: "<stdin>"
+// CHECK-DEBUG: ![[TESTSCOPE:[0-9]+]] = distinct !DISubprogram(name: "test", {{.*}} file: ![[TESTFILE]]
+// CHECK-DEBUG: ![[IFSCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[TESTSCOPE]], file: ![[TESTFILE]], line: 24)
+// CHECK-DEBUG: ![[TEMPLOCATION]] = !DILocation(line: 25, scope: ![[IFSCOPE]])
diff --git a/test/CodeGenOpenCL/fpmath.cl b/test/CodeGenOpenCL/fpmath.cl
index 8908861ace8e..0108d909c94e 100644
--- a/test/CodeGenOpenCL/fpmath.cl
+++ b/test/CodeGenOpenCL/fpmath.cl
@@ -16,7 +16,7 @@ float spscalardiv(float a, float b) {
float4 spvectordiv(float4 a, float4 b) {
// CHECK: @spvectordiv
- // CHECK: #[[ATTR]]
+ // CHECK: #[[ATTR2:[0-9]+]]
// CHECK: fdiv{{.*}},
// NODIVOPT: !fpmath ![[MD]]
// DIVOPT-NOT: !fpmath ![[MD]]
@@ -45,7 +45,11 @@ double dpscalardiv(double a, double b) {
#endif
// CHECK: attributes #[[ATTR]] = {
-// NODIVOPT: "correctly-rounded-divide-sqrt-fp-math"="false"
-// DIVOPT: "correctly-rounded-divide-sqrt-fp-math"="true"
-// CHECK: }
+// NODIVOPT-SAME: "correctly-rounded-divide-sqrt-fp-math"="false"
+// DIVOPT-SAME: "correctly-rounded-divide-sqrt-fp-math"="true"
+// CHECK-SAME: }
+// CHECK: attributes #[[ATTR2]] = {
+// NODIVOPT-SAME: "correctly-rounded-divide-sqrt-fp-math"="false"
+// DIVOPT-SAME: "correctly-rounded-divide-sqrt-fp-math"="true"
+// CHECK-SAME: }
// NODIVOPT: ![[MD]] = !{float 2.500000e+00}
diff --git a/test/CodeGenOpenCL/intel-subgroups-avc-ext-types.cl b/test/CodeGenOpenCL/intel-subgroups-avc-ext-types.cl
new file mode 100644
index 000000000000..515f13f6e768
--- /dev/null
+++ b/test/CodeGenOpenCL/intel-subgroups-avc-ext-types.cl
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL1.2 -cl-ext=+cl_intel_device_side_avc_motion_estimation -emit-llvm -o - -O0 | FileCheck %s
+
+// CHECK: %opencl.intel_sub_group_avc_mce_payload_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_ime_payload_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_ref_payload_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_sic_payload_t = type opaque
+
+// CHECK: %opencl.intel_sub_group_avc_mce_result_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_ime_result_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_ref_result_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_sic_result_t = type opaque
+
+// CHECK: %opencl.intel_sub_group_avc_ime_result_single_reference_streamout_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_ime_result_dual_reference_streamout_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_ime_single_reference_streamin_t = type opaque
+// CHECK: %opencl.intel_sub_group_avc_ime_dual_reference_streamin_t = type opaque
+
+// CHECK: store %opencl.intel_sub_group_avc_ime_payload_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ref_payload_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_sic_payload_t* null,
+
+// CHECK: store %opencl.intel_sub_group_avc_ime_result_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ref_result_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_sic_result_t* null,
+
+// CHECK: store %opencl.intel_sub_group_avc_ime_result_single_reference_streamout_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ime_result_dual_reference_streamout_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ime_single_reference_streamin_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ime_dual_reference_streamin_t* null,
+//
+// CHECK: store %opencl.intel_sub_group_avc_ime_payload_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ref_payload_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_sic_payload_t* null,
+
+// CHECK: store %opencl.intel_sub_group_avc_ime_result_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ref_result_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_sic_result_t* null,
+
+// CHECK: store %opencl.intel_sub_group_avc_ime_result_single_reference_streamout_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ime_result_dual_reference_streamout_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ime_single_reference_streamin_t* null,
+// CHECK: store %opencl.intel_sub_group_avc_ime_dual_reference_streamin_t* null,
+
+#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : enable
+
+// Using 0x0 directly allows us not to include opencl-c.h header and not to
+// redefine all of these CLK_AVC_*_INTITIALIZE_INTEL macro. '0x0' value must
+// be in sync with ones defined in opencl-c.h
+
+void foo() {
+ intel_sub_group_avc_mce_payload_t payload_mce; // No literal initializer for mce types
+ intel_sub_group_avc_ime_payload_t payload_ime = 0x0;
+ intel_sub_group_avc_ref_payload_t payload_ref = 0x0;
+ intel_sub_group_avc_sic_payload_t payload_sic = 0x0;
+
+ intel_sub_group_avc_mce_result_t result_mce; // No literal initializer for mce types
+ intel_sub_group_avc_ime_result_t result_ime = 0x0;
+ intel_sub_group_avc_ref_result_t result_ref = 0x0;
+ intel_sub_group_avc_sic_result_t result_sic = 0x0;
+
+ intel_sub_group_avc_ime_result_single_reference_streamout_t sstreamout = 0x0;
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t dstreamout = 0x0;
+ intel_sub_group_avc_ime_single_reference_streamin_t sstreamin = 0x0;
+ intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin = 0x0;
+
+ // Initialization with initializer list was supported in the first version
+ // of the extension. So we check for backward compatibility here.
+ intel_sub_group_avc_ime_payload_t payload_ime_list = {0};
+ intel_sub_group_avc_ref_payload_t payload_ref_list = {0};
+ intel_sub_group_avc_sic_payload_t payload_sic_list = {0};
+
+ intel_sub_group_avc_ime_result_t result_ime_list = {0};
+ intel_sub_group_avc_ref_result_t result_ref_list = {0};
+ intel_sub_group_avc_sic_result_t result_sic_list = {0};
+
+ intel_sub_group_avc_ime_result_single_reference_streamout_t sstreamout_list = {0};
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t dstreamout_list = {0};
+ intel_sub_group_avc_ime_single_reference_streamin_t sstreamin_list = {0};
+ intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin_list = {0};
+}
+
diff --git a/test/CodeGenOpenCL/numbered-address-space.cl b/test/CodeGenOpenCL/numbered-address-space.cl
new file mode 100644
index 000000000000..dbaba8747678
--- /dev/null
+++ b/test/CodeGenOpenCL/numbered-address-space.cl
@@ -0,0 +1,34 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-unknown-unknown -target-cpu tonga -S -emit-llvm -O0 -o - %s | FileCheck %s
+
+// Make sure using numbered address spaces doesn't trigger crashes when a
+// builtin has an address space parameter.
+
+// CHECK-LABEL: @test_numbered_as_to_generic(
+// CHECK: addrspacecast i32 addrspace(42)* %0 to i32*
+void test_numbered_as_to_generic(__attribute__((address_space(42))) int *arbitary_numbered_ptr) {
+ generic int* generic_ptr = arbitary_numbered_ptr;
+ *generic_ptr = 4;
+}
+
+// CHECK-LABEL: @test_numbered_as_to_builtin(
+// CHECK: addrspacecast i32 addrspace(42)* %0 to float addrspace(3)*
+void test_numbered_as_to_builtin(__attribute__((address_space(42))) int *arbitary_numbered_ptr, float src) {
+ volatile float result = __builtin_amdgcn_ds_fmaxf(arbitary_numbered_ptr, src, 0, 0, false);
+}
+
+// CHECK-LABEL: @test_generic_as_to_builtin_parameter_explicit_cast(
+// CHECK: addrspacecast i32 addrspace(3)* %0 to i32*
+void test_generic_as_to_builtin_parameter_explicit_cast(__local int *local_ptr, float src) {
+ generic int* generic_ptr = local_ptr;
+ volatile float result = __builtin_amdgcn_ds_fmaxf((__local float*) generic_ptr, src, 0, 0, false);
+}
+
+// CHECK-LABEL: @test_generic_as_to_builtin_parameter_implicit_cast(
+// CHECK: addrspacecast i32* %2 to float addrspace(3)*
+void test_generic_as_to_builtin_parameter_implicit_cast(__local int *local_ptr, float src) {
+ generic int* generic_ptr = local_ptr;
+
+ volatile float result = __builtin_amdgcn_ds_fmaxf(generic_ptr, src, 0, 0, false);
+}
+
diff --git a/test/CodeGenOpenCL/partial_initializer.cl b/test/CodeGenOpenCL/partial_initializer.cl
index ee6be919a7fa..4e8299584135 100644
--- a/test/CodeGenOpenCL/partial_initializer.cl
+++ b/test/CodeGenOpenCL/partial_initializer.cl
@@ -24,7 +24,7 @@ int4 GV1 = (int4)((int2)(1,2),3,4);
// CHECK: @GV2 = addrspace(1) global <4 x i32> <i32 1, i32 1, i32 1, i32 1>, align 16
int4 GV2 = (int4)(1);
-// CHECK: @f.S = private unnamed_addr addrspace(2) constant %struct.StrucTy { i32 1, i32 2, i32 0 }, align 4
+// CHECK: @__const.f.S = private unnamed_addr addrspace(2) constant %struct.StrucTy { i32 1, i32 2, i32 0 }, align 4
// CHECK-LABEL: define spir_func void @f()
void f(void) {
@@ -46,7 +46,7 @@ void f(void) {
float A[6][6] = {1.0f, 2.0f};
// CHECK: %[[v5:.*]] = bitcast %struct.StrucTy* %S to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %[[v5]], i8 addrspace(2)* align 4 bitcast (%struct.StrucTy addrspace(2)* @f.S to i8 addrspace(2)*), i32 12, i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %[[v5]], i8 addrspace(2)* align 4 bitcast (%struct.StrucTy addrspace(2)* @__const.f.S to i8 addrspace(2)*), i32 12, i1 false)
StrucTy S = {1, 2};
// CHECK: store <2 x i32> <i32 1, i32 2>, <2 x i32>* %[[compoundliteral1]], align 8
diff --git a/test/CodeGenOpenCL/pipe_builtin.cl b/test/CodeGenOpenCL/pipe_builtin.cl
index d912fce5e95d..2a533c54c13c 100644
--- a/test/CodeGenOpenCL/pipe_builtin.cl
+++ b/test/CodeGenOpenCL/pipe_builtin.cl
@@ -69,25 +69,3 @@ void test8(write_only pipe int p, global int *ptr) {
// CHECK: call i32 @__get_pipe_max_packets_wo(%opencl.pipe_wo_t* %{{.*}}, i32 4, i32 4)
*ptr = get_pipe_max_packets(p);
}
-
-void test9(read_only pipe int r, write_only pipe int w, global int *ptr) {
- // verify that return type is correctly casted to i1 value
- // CHECK: %[[R:[0-9]+]] = call i32 @__read_pipe_2
- // CHECK: icmp ne i32 %[[R]], 0
- if (read_pipe(r, ptr)) *ptr = -1;
- // CHECK: %[[W:[0-9]+]] = call i32 @__write_pipe_2
- // CHECK: icmp ne i32 %[[W]], 0
- if (write_pipe(w, ptr)) *ptr = -1;
- // CHECK: %[[NR:[0-9]+]] = call i32 @__get_pipe_num_packets_ro
- // CHECK: icmp ne i32 %[[NR]], 0
- if (get_pipe_num_packets(r)) *ptr = -1;
- // CHECK: %[[NW:[0-9]+]] = call i32 @__get_pipe_num_packets_wo
- // CHECK: icmp ne i32 %[[NW]], 0
- if (get_pipe_num_packets(w)) *ptr = -1;
- // CHECK: %[[MR:[0-9]+]] = call i32 @__get_pipe_max_packets_ro
- // CHECK: icmp ne i32 %[[MR]], 0
- if (get_pipe_max_packets(r)) *ptr = -1;
- // CHECK: %[[MW:[0-9]+]] = call i32 @__get_pipe_max_packets_wo
- // CHECK: icmp ne i32 %[[MW]], 0
- if (get_pipe_max_packets(w)) *ptr = -1;
-}
diff --git a/test/CodeGenOpenCL/printf.cl b/test/CodeGenOpenCL/printf.cl
new file mode 100644
index 000000000000..346f6c35bae4
--- /dev/null
+++ b/test/CodeGenOpenCL/printf.cl
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-+cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=FP64,ALL %s
+// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=NOFP64,ALL %s
+
+typedef __attribute__((ext_vector_type(2))) float float2;
+typedef __attribute__((ext_vector_type(2))) half half2;
+
+#ifdef cl_khr_fp64
+typedef __attribute__((ext_vector_type(2))) double double2;
+#endif
+
+int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
+
+
+// ALL-LABEL: @test_printf_float2(
+// FP64: %conv = fpext <2 x float> %0 to <2 x double>
+// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %conv)
+
+// NOFP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0)
+kernel void test_printf_float2(float2 arg) {
+ printf("%v2f", arg);
+}
+
+// ALL-LABEL: @test_printf_half2(
+// FP64: %conv = fpext <2 x half> %0 to <2 x double>
+// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %conv) #2
+
+// NOFP64: %conv = fpext <2 x half> %0 to <2 x float>
+// NOFP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %conv) #2
+kernel void test_printf_half2(half2 arg) {
+ printf("%v2f", arg);
+}
+
+#ifdef cl_khr_fp64
+// FP64-LABEL: @test_printf_double2(
+// FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %0) #2
+kernel void test_printf_double2(double2 arg) {
+ printf("%v2f", arg);
+}
+#endif
diff --git a/test/CodeGenOpenCL/private-array-initialization.cl b/test/CodeGenOpenCL/private-array-initialization.cl
index 9aa058dcfacf..420270de1933 100644
--- a/test/CodeGenOpenCL/private-array-initialization.cl
+++ b/test/CodeGenOpenCL/private-array-initialization.cl
@@ -6,11 +6,11 @@
void test() {
__private int arr[] = {1, 2, 3};
// PRIVATE0: %[[arr_i8_ptr:[0-9]+]] = bitcast [3 x i32]* %arr to i8*
-// PRIVATE0: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %[[arr_i8_ptr]], i8 addrspace(2)* align 4 bitcast ([3 x i32] addrspace(2)* @test.arr to i8 addrspace(2)*), i32 12, i1 false)
+// PRIVATE0: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %[[arr_i8_ptr]], i8 addrspace(2)* align 4 bitcast ([3 x i32] addrspace(2)* @__const.test.arr to i8 addrspace(2)*), i32 12, i1 false)
// PRIVATE5: %arr = alloca [3 x i32], align 4, addrspace(5)
// PRIVATE5: %0 = bitcast [3 x i32] addrspace(5)* %arr to i8 addrspace(5)*
-// PRIVATE5: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 4 %0, i8 addrspace(4)* align 4 bitcast ([3 x i32] addrspace(4)* @test.arr to i8 addrspace(4)*), i64 12, i1 false)
+// PRIVATE5: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 4 %0, i8 addrspace(4)* align 4 bitcast ([3 x i32] addrspace(4)* @__const.test.arr to i8 addrspace(4)*), i64 12, i1 false)
}
__kernel void initializer_cast_is_valid_crash() {
diff --git a/test/CodeGenOpenCLCXX/address-space-deduction.cl b/test/CodeGenOpenCLCXX/address-space-deduction.cl
new file mode 100644
index 000000000000..ecc0066d45ae
--- /dev/null
+++ b/test/CodeGenOpenCLCXX/address-space-deduction.cl
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - | FileCheck %s -check-prefixes=COMMON,PTR
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - -DREF | FileCheck %s -check-prefixes=COMMON,REF
+
+#ifdef REF
+#define PTR &
+#define ADR(x) x
+#else
+#define PTR *
+#define ADR(x) &x
+#endif
+
+//COMMON: @glob = addrspace(1) global i32
+int glob;
+//PTR: @glob_p = addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*)
+//REF: @glob_p = addrspace(1) global i32 addrspace(4)* null
+int PTR glob_p = ADR(glob);
+
+//COMMON: @_ZZ3fooi{{P|R}}U3AS4iE6loc_st = internal addrspace(1) global i32
+//PTR: @_ZZ3fooiPU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiPU3AS4iE6loc_st to i32 addrspace(4)*)
+//REF: @_ZZ3fooiRU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* null
+//COMMON: @loc_ext_p = external addrspace(1) {{global|constant}} i32 addrspace(4)*
+//COMMON: @loc_ext = external addrspace(1) global i32
+
+//REF: store i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*), i32 addrspace(4)* addrspace(1)* @glob_p
+
+//COMMON: define spir_func i32 @_Z3fooi{{P|R}}U3AS4i(i32 %par, i32 addrspace(4)*{{.*}} %par_p)
+int foo(int par, int PTR par_p){
+ //COMMON: %loc = alloca i32
+ int loc;
+ //COMMON: %loc_p = alloca i32 addrspace(4)*
+ //COMMON: %loc_p_const = alloca i32*
+ //COMMON: [[GAS:%[0-9]+]] = addrspacecast i32* %loc to i32 addrspace(4)*
+ //COMMON: store i32 addrspace(4)* [[GAS]], i32 addrspace(4)** %loc_p
+ int PTR loc_p = ADR(loc);
+ //COMMON: store i32* %loc, i32** %loc_p_const
+ const __private int PTR loc_p_const = ADR(loc);
+
+ // CHECK directives for the following code are located above.
+ static int loc_st;
+ //REF: store i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiRU3AS4iE6loc_st to i32 addrspace(4)*), i32 addrspace(4)* addrspace(1)* @_ZZ3fooiRU3AS4iE8loc_st_p
+ static int PTR loc_st_p = ADR(loc_st);
+ extern int loc_ext;
+ extern int PTR loc_ext_p;
+ (void)loc_ext_p;
+ return loc_ext;
+}
diff --git a/test/CodeGenOpenCLCXX/address-space-deduction2.cl b/test/CodeGenOpenCLCXX/address-space-deduction2.cl
new file mode 100644
index 000000000000..6772cdcb11d0
--- /dev/null
+++ b/test/CodeGenOpenCLCXX/address-space-deduction2.cl
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - | FileCheck %s
+
+class P {
+public:
+ P(const P &Rhs) = default;
+
+ long A;
+ long B;
+};
+
+void foo(__global P *GPtr) {
+// CHECK: call void @llvm.memcpy{{.*}}, {{.*}}, i32 16
+ P Val = GPtr[0];
+}
+
+struct __attribute__((packed)) A { int X; };
+int test(__global A *GPtr) {
+// CHECK: {{.*}} = load i32, {{.*}}, align 1
+ return static_cast<__generic A &>(*GPtr).X;
+}
diff --git a/test/CodeGenOpenCLCXX/addrspace-of-this.cl b/test/CodeGenOpenCLCXX/addrspace-of-this.cl
new file mode 100644
index 000000000000..83af3fbcb3b6
--- /dev/null
+++ b/test/CodeGenOpenCLCXX/addrspace-of-this.cl
@@ -0,0 +1,188 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -pedantic -verify -O0 -o - | FileCheck %s
+// expected-no-diagnostics
+
+// Test that the 'this' pointer is in the __generic address space.
+
+// FIXME: Add support for __constant address space.
+
+class C {
+public:
+ int v;
+ C() { v = 2; }
+ C(C &&c) { v = c.v; }
+ C(const C &c) { v = c.v; }
+ C &operator=(const C &c) {
+ v = c.v;
+ return *this;
+ }
+ C &operator=(C &&c) & {
+ v = c.v;
+ return *this;
+ }
+
+ C operator+(const C& c) {
+ v += c.v;
+ return *this;
+ }
+
+ int get() { return v; }
+
+ int outside();
+};
+
+int C::outside() {
+ return v;
+}
+
+extern C&& foo();
+
+__global C c;
+
+__kernel void test__global() {
+ int i = c.get();
+ int i2 = c.outside();
+ C c1(c);
+ C c2;
+ c2 = c1;
+ C c3 = c1 + c2;
+ C c4(foo());
+ C c5 = foo();
+}
+
+// CHECK-LABEL: @__cxx_global_var_init()
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*))
+
+// Test that the address space is __generic for the constructor
+// CHECK-LABEL: @_ZNU3AS41CC1Ev(%class.C addrspace(4)* %this)
+// CHECK: entry:
+// CHECK: %this.addr = alloca %class.C addrspace(4)*, align 4
+// CHECK: store %class.C addrspace(4)* %this, %class.C addrspace(4)** %this.addr, align 4
+// CHECK: %this1 = load %class.C addrspace(4)*, %class.C addrspace(4)** %this.addr, align 4
+// CHECK: call void @_ZNU3AS41CC2Ev(%class.C addrspace(4)* %this1)
+// CHECK: ret void
+
+// CHECK-LABEL: @_Z12test__globalv()
+
+// Test the address space of 'this' when invoking a method.
+// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*))
+
+// Test the address space of 'this' when invoking a method that is declared in the file contex.
+// CHECK: %call1 = call i32 @_ZNU3AS41C7outsideEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*))
+
+// Test the address space of 'this' when invoking copy-constructor.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*))
+
+// Test the address space of 'this' when invoking a constructor.
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]])
+
+// Test the address space of 'this' when invoking assignment operator.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: %call2 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]])
+
+// Test the address space of 'this' when invoking the operator+
+// CHECK: [[C3GEN:%[0-9]+]] = addrspacecast %class.C* %c3 to %class.C addrspace(4)*
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CplERU3AS4KS_(%class.C* sret %ref.tmp, %class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) [[C2GEN]])
+// CHECK: [[REFGEN:%[0-9]+]] = addrspacecast %class.C* %ref.tmp to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1EOU3AS4S_(%class.C addrspace(4)* [[C3GEN]], %class.C addrspace(4)* dereferenceable(4) [[REFGEN]])
+
+// Test the address space of 'this' when invoking the move constructor
+// CHECK: [[C4GEN:%[0-9]+]] = addrspacecast %class.C* %c4 to %class.C addrspace(4)*
+// CHECK: %call3 = call spir_func dereferenceable(4) %class.C addrspace(4)* @_Z3foov()
+// CHECK: call void @_ZNU3AS41CC1EOU3AS4S_(%class.C addrspace(4)* [[C4GEN]], %class.C addrspace(4)* dereferenceable(4) %call3)
+
+// Test the address space of 'this' when invoking the move assignment
+// CHECK: [[C5GEN:%[0-9]+]] = addrspacecast %class.C* %c5 to %class.C addrspace(4)*
+// CHECK: %call4 = call spir_func dereferenceable(4) %class.C addrspace(4)* @_Z3foov() #5
+// CHECK: call void @_ZNU3AS41CC1EOU3AS4S_(%class.C addrspace(4)* [[C5GEN:%[0-9]+]], %class.C addrspace(4)* dereferenceable(4) %call4)
+
+
+#define TEST(AS) \
+ __kernel void test##AS() { \
+ AS C c; \
+ int i = c.get(); \
+ C c1(c); \
+ C c2; \
+ c2 = c1; \
+ }
+
+TEST(__local)
+
+// CHECK-LABEL: _Z11test__localv
+// CHECK: @__cxa_guard_acquire
+
+// Test the address space of 'this' when invoking a constructor for an object in non-default address space
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*))
+
+// Test the address space of 'this' when invoking a method.
+// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*))
+
+
+// Test the address space of 'this' when invoking copy-constructor.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*))
+
+// Test the address space of 'this' when invoking a constructor.
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]])
+
+// Test the address space of 'this' when invoking assignment operator.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: %call1 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]])
+
+TEST(__private)
+
+// CHECK-LABEL: @_Z13test__privatev
+
+// Test the address space of 'this' when invoking a constructor for an object in non-default address space
+// CHECK: [[CGEN:%[0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[CGEN]])
+
+// Test the address space of 'this' when invoking a method.
+// CHECK: [[CGEN:%[0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)*
+// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* [[CGEN]])
+
+// Test the address space of 'this' when invoking a copy-constructor.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: [[CGEN:%[0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) [[CGEN]])
+
+// Test the address space of 'this' when invoking a constructor.
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]])
+
+// Test the address space of 'this' when invoking a copy-assignment.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: %call1 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]])
+
+TEST()
+
+// CHECK-LABEL: @_Z4testv()
+
+// Test the address space of 'this' when invoking a constructor for an object in non-default address space
+// CHECK: [[CGEN:%[0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[CGEN]])
+
+// Test the address space of 'this' when invoking a method.
+// CHECK: [[CGEN:%[0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)*
+// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* [[CGEN]])
+
+// Test the address space of 'this' when invoking a copy-constructor.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: [[CGEN:%[0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) [[CGEN]])
+
+// Test the address space of 'this' when invoking a constructor.
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]])
+
+// Test the address space of 'this' when invoking a copy-assignment.
+// CHECK: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
+// CHECK: [[C2GEN:%[0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
+// CHECK: %call1 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]])
diff --git a/test/CodeGenOpenCLCXX/template-address-spaces.cl b/test/CodeGenOpenCLCXX/template-address-spaces.cl
new file mode 100644
index 000000000000..7c722537fca3
--- /dev/null
+++ b/test/CodeGenOpenCLCXX/template-address-spaces.cl
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -cl-std=c++ %s -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck %s
+
+template <typename T>
+struct S{
+ T a;
+ T foo();
+};
+
+template<typename T>
+T S<T>::foo() { return a;}
+
+// CHECK: %struct.S = type { i32 }
+// CHECK: %struct.S.0 = type { i32 addrspace(4)* }
+// CHECK: %struct.S.1 = type { i32 addrspace(1)* }
+
+// CHECK: %0 = addrspacecast %struct.S* %sint to %struct.S addrspace(4)*
+// CHECK: %call = call i32 @_ZNU3AS41SIiE3fooEv(%struct.S addrspace(4)* %0) #1
+// CHECK: %1 = addrspacecast %struct.S.0* %sintptr to %struct.S.0 addrspace(4)*
+// CHECK: %call1 = call i32 addrspace(4)* @_ZNU3AS41SIPU3AS4iE3fooEv(%struct.S.0 addrspace(4)* %1) #1
+// CHECK: %2 = addrspacecast %struct.S.1* %sintptrgl to %struct.S.1 addrspace(4)*
+// CHECK: %call2 = call i32 addrspace(1)* @_ZNU3AS41SIPU3AS1iE3fooEv(%struct.S.1 addrspace(4)* %2) #1
+
+void bar(){
+ S<int> sint;
+ S<int*> sintptr;
+ S<__global int*> sintptrgl;
+
+ sint.foo();
+ sintptr.foo();
+ sintptrgl.foo();
+}
diff --git a/test/Coverage/ast-printing.c b/test/Coverage/ast-printing.c
index dfda6c676f6f..0cdc6e588e71 100644
--- a/test/Coverage/ast-printing.c
+++ b/test/Coverage/ast-printing.c
@@ -4,6 +4,5 @@
// RUN: diff %t.1.c %t.2.c
// RUN: %clang_cc1 -ast-dump %s
// RUN: %clang_cc1 -ast-dump-all %s
-// RUN: %clang_cc1 -print-decl-contexts %s
#include "c-language-features.inc"
diff --git a/test/Coverage/ast-printing.cpp b/test/Coverage/ast-printing.cpp
index bcd78be7d05b..948b67eec6b0 100644
--- a/test/Coverage/ast-printing.cpp
+++ b/test/Coverage/ast-printing.cpp
@@ -4,7 +4,6 @@
// RUN: diff %t.1.cpp %t.2.cpp
// RUN: %clang_cc1 -std=c++14 -ast-dump %s
// RUN: %clang_cc1 -std=c++14 -ast-dump-all %s
-// RUN: %clang_cc1 -std=c++14 -print-decl-contexts %s
// RUN: %clang_cc1 -std=c++14 -fdump-record-layouts %s
#include "cxx-language-features.inc"
diff --git a/test/Coverage/targets.c b/test/Coverage/targets.c
index 58c635ae74e1..b95ecd9b9021 100644
--- a/test/Coverage/targets.c
+++ b/test/Coverage/targets.c
@@ -5,9 +5,7 @@
// RUN: %clang_cc1 -debug-info-kind=limited -triple i686-unknown-dragonfly -emit-llvm -o %t %s
// RUN: %clang_cc1 -debug-info-kind=limited -triple i686-unknown-unknown -emit-llvm -o %t %s
// RUN: %clang_cc1 -debug-info-kind=limited -triple i686-unknown-win32 -emit-llvm -o %t %s
-// RUN: %clang_cc1 -debug-info-kind=limited -triple powerpc-apple-darwin9 -emit-llvm -o %t %s
// RUN: %clang_cc1 -debug-info-kind=limited -triple powerpc-unknown-unknown -emit-llvm -o %t %s
-// RUN: %clang_cc1 -debug-info-kind=limited -triple powerpc64-apple-darwin9 -emit-llvm -o %t %s
// RUN: %clang_cc1 -debug-info-kind=limited -triple powerpc64-unknown-unknown -emit-llvm -o %t %s
// RUN: %clang_cc1 -debug-info-kind=limited -triple sparc-unknown-solaris -emit-llvm -o %t %s
// RUN: %clang_cc1 -debug-info-kind=limited -triple sparc-unknown-unknown -emit-llvm -o %t %s
diff --git a/test/CoverageMapping/default-method.cpp b/test/CoverageMapping/default-method.cpp
new file mode 100644
index 000000000000..6b5428306b71
--- /dev/null
+++ b/test/CoverageMapping/default-method.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name default-method.cpp -w %s | FileCheck %s -implicit-check-not="->"
+
+namespace PR39822 {
+ struct unique_ptr {
+ unique_ptr &operator=(unique_ptr &);
+ };
+
+ class foo {
+ foo &operator=(foo &);
+ unique_ptr convertable_values_[2];
+ };
+
+ // CHECK: _ZN7PR398223fooaSERS0_:
+ // CHECK-NEXT: File 0, [[@LINE+1]]:28 -> [[@LINE+1]]:29 = #0
+ foo &foo::operator=(foo &) = default;
+} // namespace PR39822
+
diff --git a/test/CoverageMapping/macros.c b/test/CoverageMapping/macros.c
index 95fe37ed7e8d..39cd190b2a88 100644
--- a/test/CoverageMapping/macros.c
+++ b/test/CoverageMapping/macros.c
@@ -4,6 +4,7 @@
#define MACRO_2 bar()
#define MACRO_1 return; MACRO_2
#define MACRO_3 MACRO_2
+#define GOTO goto
void bar() {}
@@ -56,6 +57,15 @@ void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+4]]:2 = #0
// CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1
// CHECK-NEXT: File 2, 4:17 -> 4:22 = #1
+// CHECK-NEXT: func6
+void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+4]]:2 = #0
+begin: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #1
+ if (count--) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:16 = #1
+ GOTO begin; // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:19 = #2
+}
+// CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = #2
+// CHECK-NEXT: File 1, 7:14 -> 7:18 = #2
+
int main(int argc, const char *argv[]) {
func();
func2();
diff --git a/test/Driver/Inputs/MacOSX10.14.sdk/SDKSettings.json b/test/Driver/Inputs/MacOSX10.14.sdk/SDKSettings.json
new file mode 100644
index 000000000000..bca56e4f1ee3
--- /dev/null
+++ b/test/Driver/Inputs/MacOSX10.14.sdk/SDKSettings.json
@@ -0,0 +1 @@
+{"Version":"10.14"}
diff --git a/test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/c++/v1/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/include/c++/v1/.keep
diff --git a/test/Driver/Inputs/basic_hurd_tree/include/.keep b/test/Driver/Inputs/basic_hurd_tree/include/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_hurd_tree/include/.keep
diff --git a/test/Driver/Inputs/basic_hurd_tree/lib/i386-gnu/.keep b/test/Driver/Inputs/basic_hurd_tree/lib/i386-gnu/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_hurd_tree/lib/i386-gnu/.keep
diff --git a/test/Driver/Inputs/basic_hurd_tree/lib32/.keep b/test/Driver/Inputs/basic_hurd_tree/lib32/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_hurd_tree/lib32/.keep
diff --git a/test/Driver/Inputs/basic_hurd_tree/usr/include/i386-gnu/.keep b/test/Driver/Inputs/basic_hurd_tree/usr/include/i386-gnu/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_hurd_tree/usr/include/i386-gnu/.keep
diff --git a/test/Driver/Inputs/basic_hurd_tree/usr/lib/i386-gnu/.keep b/test/Driver/Inputs/basic_hurd_tree/usr/lib/i386-gnu/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_hurd_tree/usr/lib/i386-gnu/.keep
diff --git a/test/Driver/Inputs/basic_hurd_tree/usr/lib32/.keep b/test/Driver/Inputs/basic_hurd_tree/usr/lib32/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_hurd_tree/usr/lib32/.keep
diff --git a/test/Driver/Inputs/basic_msp430_tree/bin/msp430-elf-ld b/test/Driver/Inputs/basic_msp430_tree/bin/msp430-elf-ld
new file mode 100755
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_msp430_tree/bin/msp430-elf-ld
diff --git a/test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o b/test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o
diff --git a/test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o b/test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o
diff --git a/test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crt0.o b/test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crt0.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crt0.o
diff --git a/test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crtn.o b/test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crtn.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_msp430_tree/msp430-elf/lib/430/crtn.o
diff --git a/test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/include/g++/backward/.keep b/test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/include/g++/backward/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/include/g++/backward/.keep
diff --git a/test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o b/test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o
diff --git a/test/Driver/Inputs/cray_suse_gcc_tree/usr/include/c++/4.8/.keep b/test/Driver/Inputs/cray_suse_gcc_tree/usr/include/c++/4.8/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/cray_suse_gcc_tree/usr/include/c++/4.8/.keep
diff --git a/test/Driver/Inputs/cray_suse_gcc_tree/usr/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o b/test/Driver/Inputs/cray_suse_gcc_tree/usr/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/cray_suse_gcc_tree/usr/lib/gcc/x86_64-suse-linux/8.2.0/crtbegin.o
diff --git a/test/Driver/Inputs/hip_dev_lib/hip.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/hip.amdgcn.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hip_dev_lib/hip.amdgcn.bc
diff --git a/test/Driver/Inputs/in.so b/test/Driver/Inputs/in.so
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/test/Driver/Inputs/in.so
@@ -0,0 +1 @@
+
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_tvos.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_tvos.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_tvos.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_watchos.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_watchos.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.cc_kext_watchos.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.ios.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.ios.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.ios.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.osx.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.osx.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.osx.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_tvos.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_tvos.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_tvos.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_watchos.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_watchos.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.profile_watchos.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tvos.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tvos.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tvos.a
diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.watchos.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.watchos.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.watchos.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/asan/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/asan/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/asan/.keep
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan-preinit.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan-preinit.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan-preinit.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan.so b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.asan.so
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.builtins.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.builtins.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.builtins.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.fuzzer.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.fuzzer.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.fuzzer.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.scudo.so b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.scudo.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.scudo.so
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray-basic.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray-basic.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray-basic.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/libclang_rt.xray.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/libclang_rt.builtins.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/libclang_rt.builtins.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/libclang_rt.builtins.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/asan/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/asan/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/asan/.keep
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan-preinit.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan-preinit.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan-preinit.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan.so b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.asan.so
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.builtins.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.builtins.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.builtins.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.fuzzer.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.fuzzer.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.fuzzer.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.scudo.so b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.scudo.so
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.scudo.so
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray-basic.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray-basic.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray-basic.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/libclang_rt.xray.a
diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/libclang_rt.builtins.a b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/libclang_rt.builtins.a
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/libclang_rt.builtins.a
diff --git a/test/Driver/XRay/lit.local.cfg b/test/Driver/XRay/lit.local.cfg
index 41bd41395f7b..70f9792ba3db 100644
--- a/test/Driver/XRay/lit.local.cfg
+++ b/test/Driver/XRay/lit.local.cfg
@@ -10,7 +10,7 @@ supported_targets = [
# Only on platforms we support.
supported_oses = [
- 'Linux', 'FreeBSD'
+ 'Linux', 'FreeBSD', 'Darwin'
]
triple_set = set(target_triple_components)
diff --git a/test/Driver/XRay/xray-instrument-os.c b/test/Driver/XRay/xray-instrument-os.c
index 7e221365d611..1008d0aff6f8 100644
--- a/test/Driver/XRay/xray-instrument-os.c
+++ b/test/Driver/XRay/xray-instrument-os.c
@@ -1,4 +1,4 @@
// RUN: not %clang -o /dev/null -v -fxray-instrument -c %s
-// XFAIL: -linux-, -freebsd
+// XFAIL: -linux-, -freebsd, -darwin
// REQUIRES-ANY: amd64, x86_64, x86_64h, arm, aarch64, arm64
typedef int a;
diff --git a/test/Driver/XRay/xray-instrumentation-bundles-flags.cpp b/test/Driver/XRay/xray-instrumentation-bundles-flags.cpp
new file mode 100644
index 000000000000..da2535509b99
--- /dev/null
+++ b/test/Driver/XRay/xray-instrumentation-bundles-flags.cpp
@@ -0,0 +1,11 @@
+// This test ensures that when we invoke the clang compiler, that the -cc1
+// options include the -fxray-instrumentation-bundle= flag we provide in the
+// invocation.
+//
+// RUN: %clang -fxray-instrument -fxray-instrumentation-bundle=function -### \
+// RUN: -x c++ -std=c++11 -emit-llvm -c -o - %s 2>&1 \
+// RUN: | FileCheck %s
+// CHECK: -fxray-instrumentation-bundle=function
+//
+// REQUIRES-ANY: linux, freebsd
+// REQUIRES-ANY: amd64, x86_64, x86_64h, arm, aarch64, arm64
diff --git a/test/Driver/XRay/xray-mode-flags.cpp b/test/Driver/XRay/xray-mode-flags.cpp
index 0a040881d332..281cf0b547fa 100644
--- a/test/Driver/XRay/xray-mode-flags.cpp
+++ b/test/Driver/XRay/xray-mode-flags.cpp
@@ -26,6 +26,20 @@
// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=none,all \
// RUN: -### %s \
// RUN: 2>&1 | FileCheck --check-prefixes FDR,BASIC %s
+//
+// We also should support having the individual modes be concatenated.
+//
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=none \
+// RUN: -fxray-modes=xray-fdr \
+// RUN: -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes FDR %s
+//
+// Order also matters.
+//
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=xray-fdr \
+// RUN: -fxray-modes=none \
+// RUN: -### %s \
+// RUN: 2>&1 | FileCheck --check-prefixes NONE %s
// BASIC: libclang_rt.xray-basic
// FDR: libclang_rt.xray-fdr
diff --git a/test/Driver/Xarch.c b/test/Driver/Xarch.c
index 34f9340dd68f..ae0816f2c8f4 100644
--- a/test/Driver/Xarch.c
+++ b/test/Driver/Xarch.c
@@ -1,9 +1,12 @@
-// RUN: %clang -target i386-apple-darwin9 -m32 -Xarch_i386 -O2 %s -S -### 2> %t.log
-// RUN: grep ' "-O2" ' %t.log | count 1
-// RUN: %clang -target i386-apple-darwin9 -m64 -Xarch_i386 -O2 %s -S -### 2> %t.log
-// RUN: not grep ' "-O2" ' %t.log
-// RUN: grep "argument unused during compilation: '-Xarch_i386 -O2'" %t.log
-// RUN: not %clang -target i386-apple-darwin9 -m32 -Xarch_i386 -o -Xarch_i386 -S %s -S -Xarch_i386 -o 2> %t.log
-// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -o'" %t.log | count 2
-// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -S'" %t.log
+// RUN: %clang -target i386-apple-darwin9 -m32 -Xarch_i386 -O3 %s -S -### 2>&1 | FileCheck -check-prefix=O3ONCE %s
+// O3ONCE: "-O3"
+// O3ONCE-NOT: "-O3"
+// RUN: %clang -target i386-apple-darwin9 -m64 -Xarch_i386 -O3 %s -S -### 2>&1 | FileCheck -check-prefix=O3NONE %s
+// O3NONE-NOT: "-O3"
+// O3NONE: argument unused during compilation: '-Xarch_i386 -O3'
+
+// RUN: not %clang -target i386-apple-darwin9 -m32 -Xarch_i386 -o -Xarch_i386 -S %s -S -Xarch_i386 -o 2>&1 | FileCheck -check-prefix=INVALID %s
+// INVALID: error: invalid Xarch argument: '-Xarch_i386 -o'
+// INVALID: error: invalid Xarch argument: '-Xarch_i386 -S'
+// INVALID: error: invalid Xarch argument: '-Xarch_i386 -o'
diff --git a/test/Driver/aarch64-call-saved-x-register.c b/test/Driver/aarch64-call-saved-x-register.c
new file mode 100644
index 000000000000..6a3ee6322578
--- /dev/null
+++ b/test/Driver/aarch64-call-saved-x-register.c
@@ -0,0 +1,58 @@
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x8 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X8 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x9 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X9 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x10 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X10 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x11 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X11 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x12 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X12 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x13 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X13 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x14 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X14 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x15 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X15 %s
+
+// RUN: %clang -target aarch64-none-gnu -fcall-saved-x18 -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CALL-SAVED-X18 %s
+
+// Test all call-saved-x# options together.
+// RUN: %clang -target aarch64-none-gnu \
+// RUN: -fcall-saved-x8 \
+// RUN: -fcall-saved-x9 \
+// RUN: -fcall-saved-x10 \
+// RUN: -fcall-saved-x11 \
+// RUN: -fcall-saved-x12 \
+// RUN: -fcall-saved-x13 \
+// RUN: -fcall-saved-x14 \
+// RUN: -fcall-saved-x15 \
+// RUN: -fcall-saved-x18 \
+// RUN: -### %s 2>&1 | FileCheck %s \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X8 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X9 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X10 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X11 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X12 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X13 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X14 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X15 \
+// RUN: --check-prefix=CHECK-CALL-SAVED-X18
+
+// CHECK-CALL-SAVED-X8: "-target-feature" "+call-saved-x8"
+// CHECK-CALL-SAVED-X9: "-target-feature" "+call-saved-x9"
+// CHECK-CALL-SAVED-X10: "-target-feature" "+call-saved-x10"
+// CHECK-CALL-SAVED-X11: "-target-feature" "+call-saved-x11"
+// CHECK-CALL-SAVED-X12: "-target-feature" "+call-saved-x12"
+// CHECK-CALL-SAVED-X13: "-target-feature" "+call-saved-x13"
+// CHECK-CALL-SAVED-X14: "-target-feature" "+call-saved-x14"
+// CHECK-CALL-SAVED-X15: "-target-feature" "+call-saved-x15"
+// CHECK-CALL-SAVED-X18: "-target-feature" "+call-saved-x18"
diff --git a/test/Driver/aarch64-cpus.c b/test/Driver/aarch64-cpus.c
index d3cb35fa1030..900162f95403 100644
--- a/test/Driver/aarch64-cpus.c
+++ b/test/Driver/aarch64-cpus.c
@@ -6,7 +6,7 @@
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=generic -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC %s
// RUN: %clang -target aarch64_be -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC %s
// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=generic -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC %s
-// GENERIC: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// GENERIC: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERIC %s
// RUN: %clang -target arm64 -mcpu=generic -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERIC %s
@@ -21,7 +21,10 @@
// ARM64-NATIVE-NOT: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "native"
// RUN: %clang -target arm64-apple-darwin -arch arm64 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-DARWIN %s
+// RUN: %clang -target arm64-apple-darwin -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-DARWIN %s
+// RUN: %clang -target arm64-apple-ios12.0 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-DARWIN %s
// ARM64-DARWIN: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "cyclone"
+// ARM64-DARWIN-SAME: "-target-feature" "+aes"
// RUN: %clang -target aarch64 -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35 %s
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35 %s
@@ -29,8 +32,8 @@
// RUN: %clang -target aarch64 -mtune=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CA35-TUNE %s
-// CA35: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a35"
-// CA35-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// CA35: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "cortex-a35"
+// CA35-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA35 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA35 %s
@@ -44,8 +47,8 @@
// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53 %s
// RUN: %clang -target aarch64 -mtune=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CA53-TUNE %s
-// CA53: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a53"
-// CA53-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// CA53: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "cortex-a53"
+// CA53-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA53 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA53 %s
@@ -59,8 +62,8 @@
// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CA55 %s
// RUN: %clang -target aarch64 -mtune=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CA55-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CA55-TUNE %s
-// CA55: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a55"
-// CA55-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// CA55: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "cortex-a55"
+// CA55-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA55 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA55 %s
@@ -75,8 +78,8 @@
// RUN: %clang -target aarch64 -mtune=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CA57-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CA57-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CA57-TUNE %s
-// CA57: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a57"
-// CA57-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// CA57: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "cortex-a57"
+// CA57-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA57 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA57 %s
@@ -91,8 +94,8 @@
// RUN: %clang -target aarch64 -mtune=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CA72-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CA72-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CA72-TUNE %s
-// CA72: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a72"
-// CA72-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// CA72: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "cortex-a72"
+// CA72-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA72 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CA72 %s
@@ -107,8 +110,8 @@
// RUN: %clang -target aarch64 -mtune=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A73-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A73-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A73-TUNE %s
-// CORTEX-A73: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a73"
-// CORTEX-A73-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// CORTEX-A73: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "cortex-a73"
+// CORTEX-A73-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CORTEX-A73 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CORTEX-A73 %s
@@ -123,8 +126,8 @@
// RUN: %clang -target aarch64 -mtune=cortex-a75 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A75-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=cortex-a75 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A75-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=cortex-a75 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A75-TUNE %s
-// CORTEX-A75: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a75"
-// CORTEX-A75-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// CORTEX-A75: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "cortex-a75"
+// CORTEX-A75-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target arm64 -mcpu=cortex-a75 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CORTEX-A75 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=cortex-a75 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-CORTEX-A75 %s
@@ -139,8 +142,8 @@
// RUN: %clang -target aarch64 -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-TUNE %s
-// M1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "exynos-m1"
-// M1-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// M1: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "exynos-m1"
+// M1-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// RUN: %clang -target aarch64 -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
@@ -166,8 +169,9 @@
// RUN: %clang -target aarch64_be -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s
// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s
// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s
-// M4: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4"
+// M4: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4" "-target-feature" "+v8.2a"
// M4-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// M4-TUNE-NOT: "+v8.2a"
// RUN: %clang -target arm64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s
@@ -194,8 +198,9 @@
// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4 %s
// RUN: %clang -target arm64 -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4-TUNE %s
// RUN: %clang -target arm64 -mlittle-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4-TUNE %s
-// ARM64-M4: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m4"
+// ARM64-M4: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m4" "-target-feature" "+v8.2a"
// ARM64-M4-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic"
+// ARM64-M4-TUNE-NOT: "+v8.2a"
// RUN: %clang -target aarch64 -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR %s
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR %s
@@ -231,8 +236,8 @@
// RUN: %clang -target aarch64 -mtune=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-TUNE %s
-// THUNDERX2T99: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "thunderx2t99" "-target-feature" "+v8.1a"
-// THUNDERX2T99-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic"
+// THUNDERX2T99: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "thunderx2t99" "-target-feature" "+v8.1a"
+// THUNDERX2T99-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"
// THUNDERX2T99-TUNE-NOT: +v8.1a
// RUN: %clang -target arm64 -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-THUNDERX2T99 %s
@@ -335,8 +340,9 @@
// RUN: %clang -target aarch64_be -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s
// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s
// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s
-// M4-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4"
+// M4-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4" "-target-feature" "+v8.2a"
// M4-BE-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic"
+// M4-BE-TUNE-NOT: "+v8.2a"
// RUN: %clang -target aarch64_be -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s
// RUN: %clang -target aarch64 -mbig-endian -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s
@@ -365,7 +371,7 @@
// RUN: %clang -target aarch64 -mlittle-endian -march=armv8.1-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV81A %s
// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.1a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV81A %s
// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.1-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV81A %s
-// GENERICV81A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.1a"
+// GENERICV81A: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.1a"
// RUN: %clang -target arm64 -march=armv8.1a -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERICV81A %s
// RUN: %clang -target arm64 -march=armv8.1-a -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERICV81A %s
@@ -396,14 +402,61 @@
// RUN: %clang -target aarch64_be -mbig-endian -march=armv8.2-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-BE %s
// GENERICV82A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.2a"
+// RUN: %clang -target aarch64 -march=armv8.2a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-NO-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.2-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-NO-FP16FML %s
+// GENERICV82A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV82A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.2a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16 %s
// RUN: %clang -target aarch64 -march=armv8.2-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16 %s
// GENERICV82A-FP16: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.2a" "-target-feature" "+fullfp16"
+// GENERICV82A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV82A-FP16-SAME: {{$}}
// RUN: %clang -target aarch64 -march=armv8.2-a+profile -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-SPE %s
// GENERICV82A-SPE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.2a" "-target-feature" "+spe"
-//
+
+// RUN: %clang -target aarch64 -march=armv8a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-NO-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-NO-FP16FML %s
+// GENERICV8A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV8A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-FP16 %s
+// GENERICV8A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV8A-FP16: "-target-feature" "+fullfp16"
+// GENERICV8A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV8A-FP16-SAME: {{$}}
+
+// RUN: %clang -target aarch64 -march=armv8a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-FP16FML %s
+// GENERICV8A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.2a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.2-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16FML %s
+// GENERICV82A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.2a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16-NO-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.2-a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16-NO-FP16FML %s
+// GENERICV82A-FP16-NO-FP16FML: "-target-feature" "+fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.2a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-NO-FP16FML-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8.2-a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-NO-FP16FML-FP16 %s
+// GENERICV82A-NO-FP16FML-FP16: "-target-feature" "-fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.2a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16FML-NO-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8.2-a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16FML-NO-FP16 %s
+// GENERICV82A-FP16FML-NO-FP16: "-target-feature" "-fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.2a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-NO-FP16-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.2-a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-NO-FP16-FP16FML %s
+// GENERICV82A-NO-FP16-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.2a+fp16+profile -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16-SPE %s
// RUN: %clang -target aarch64 -march=armv8.2-a+fp16+profile -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV82A-FP16-SPE %s
// GENERICV82A-FP16-SPE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.2a" "-target-feature" "+fullfp16" "-target-feature" "+spe"
+// GENERICV82A-FP16-SPE-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV82A-FP16-SPE-SAME: {{$}}
// RUN: %clang -target aarch64 -march=armv8.3a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A %s
// RUN: %clang -target aarch64 -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A %s
@@ -411,7 +464,7 @@
// RUN: %clang -target aarch64 -mlittle-endian -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A %s
// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.3a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A %s
// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A %s
-// GENERICV83A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.3a"
+// GENERICV83A: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.3a"
// RUN: %clang -target aarch64_be -march=armv8.3a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-BE %s
// RUN: %clang -target aarch64_be -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-BE %s
@@ -421,16 +474,42 @@
// RUN: %clang -target aarch64_be -mbig-endian -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-BE %s
// GENERICV83A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.3a"
+// RUN: %clang -target aarch64 -march=armv8.3a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-NO-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-NO-FP16FML %s
+// GENERICV83A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV83A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.3a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16 %s
// RUN: %clang -target aarch64 -march=armv8.3-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16 %s
// GENERICV83A-FP16: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.3a" "-target-feature" "+fullfp16"
+// RUN: %clang -target aarch64 -march=armv8.3a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.3-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16FML %s
+// GENERICV83A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.3a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16-NO-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.3-a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16-NO-FP16FML %s
+// GENERICV83A-FP16-NO-FP16FML: "-target-feature" "+fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.3a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-NO-FP16FML-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8.3-a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-NO-FP16FML-FP16 %s
+// GENERICV83A-NO-FP16FML-FP16: "-target-feature" "-fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.3a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16FML-NO-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8.3-a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-FP16FML-NO-FP16 %s
+// GENERICV83A-FP16FML-NO-FP16: "-target-feature" "-fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.3a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-NO-FP16-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.3-a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV83A-NO-FP16-FP16FML %s
+// GENERICV83A-NO-FP16-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
// RUN: %clang -target aarch64 -march=armv8.4a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A %s
// RUN: %clang -target aarch64 -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A %s
// RUN: %clang -target aarch64 -mlittle-endian -march=armv8.4a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A %s
// RUN: %clang -target aarch64 -mlittle-endian -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A %s
// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.4a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A %s
// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A %s
-// GENERICV84A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.4a"
+// GENERICV84A: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.4a"
// RUN: %clang -target aarch64_be -march=armv8.4a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-BE %s
// RUN: %clang -target aarch64_be -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-BE %s
@@ -440,21 +519,59 @@
// RUN: %clang -target aarch64_be -mbig-endian -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-BE %s
// GENERICV84A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.4a"
-// RUN: %clang -target aarch64 -march=armv8.4-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16 %s
-// GENERICV84A-FP16: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.4a" "-target-feature" "+fullfp16"
+// RUN: %clang -target aarch64 -march=armv8.4a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-NO-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-NO-FP16FML %s
+// GENERICV84A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// GENERICV84A-NO-FP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
-// fullfp16 is not specified by default for v8.2a, and can be enabled by +fp16
-// RUN: %clang -target aarch64 -march=armv8.2a -### -c %s 2>&1 | FileCheck -check-prefix=V82ANOFP16 -check-prefix=GENERICV82A %s
-// RUN: %clang -target aarch64 -march=armv8.2-a -### -c %s 2>&1 | FileCheck -check-prefix=V82ANOFP16 -check-prefix=GENERICV82A %s
-// V82ANOFP16-NOT: "-target-feature" "-fullfp16"
-// V82ANOFP16-NOT: "-target-feature" "+fullfp16"
-// RUN: %clang -target aarch64 -march=armv8.2a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=V82AFP16 -check-prefix=GENERICV82A %s
-// RUN: %clang -target aarch64 -march=armv8.2-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=V82AFP16 -check-prefix=GENERICV82A %s
-// V82AFP16: "-target-feature" "+fullfp16"
+// RUN: %clang -target aarch64 -march=armv8.4a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8.4-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16 %s
+// GENERICV84A-FP16: "-target-feature" "+fullfp16" "-target-feature" "+fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.4a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.4-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16FML %s
+// GENERICV84A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.4a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16-NO-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.4-a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16-NO-FP16FML %s
+// GENERICV84A-FP16-NO-FP16FML: "-target-feature" "+fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.4a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-NO-FP16FML-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8.4-a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-NO-FP16FML-FP16 %s
+// GENERICV84A-NO-FP16FML-FP16: "-target-feature" "+fullfp16" "-target-feature" "+fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.4a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16FML-NO-FP16 %s
+// RUN: %clang -target aarch64 -march=armv8.4-a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-FP16FML-NO-FP16 %s
+// GENERICV84A-FP16FML-NO-FP16: "-target-feature" "-fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target aarch64 -march=armv8.4a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-NO-FP16-FP16FML %s
+// RUN: %clang -target aarch64 -march=armv8.4-a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV84A-NO-FP16-FP16FML %s
+// GENERICV84A-NO-FP16-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target aarch64 -march=armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A %s
+// RUN: %clang -target aarch64 -march=armv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A %s
+// RUN: %clang -target aarch64 -mlittle-endian -march=armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A %s
+// RUN: %clang -target aarch64 -mlittle-endian -march=armv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A %s
+// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A %s
+// RUN: %clang -target aarch64_be -mlittle-endian -march=armv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A %s
+// GENERICV85A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.5a"
+
+// RUN: %clang -target aarch64_be -march=armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A-BE %s
+// RUN: %clang -target aarch64_be -march=armv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A-BE %s
+// RUN: %clang -target aarch64 -mbig-endian -march=armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A-BE %s
+// RUN: %clang -target aarch64 -mbig-endian -march=armv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A-BE %s
+// RUN: %clang -target aarch64_be -mbig-endian -march=armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A-BE %s
+// RUN: %clang -target aarch64_be -mbig-endian -march=armv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A-BE %s
+// GENERICV85A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.5a"
+
+// RUN: %clang -target aarch64 -march=armv8.5-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV85A-FP16 %s
+// GENERICV85A-FP16: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v8.5a" "-target-feature" "+fullfp16"
// fullfp16 is off by default for v8a, feature must not be mentioned
// RUN: %clang -target aarch64 -march=armv8a -### -c %s 2>&1 | FileCheck -check-prefix=V82ANOFP16 -check-prefix=GENERIC %s
// RUN: %clang -target aarch64 -march=armv8-a -### -c %s 2>&1 | FileCheck -check-prefix=V82ANOFP16 -check-prefix=GENERIC %s
+// V82ANOFP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// V82ANOFP16-NOT: "-target-feature" "{{[+-]}}fullfp16"
// RAS is on by default for v8.2a, but can be disabled by +noras
// RUN: %clang -target aarch64 -march=armv8.2a -### -c %s 2>&1 | FileCheck -check-prefix=V82ARAS -check-prefix=GENERICV82A %s
diff --git a/test/Driver/aarch64-fixed-call-saved-x-register.c b/test/Driver/aarch64-fixed-call-saved-x-register.c
new file mode 100644
index 000000000000..aa781fda91e8
--- /dev/null
+++ b/test/Driver/aarch64-fixed-call-saved-x-register.c
@@ -0,0 +1,8 @@
+// Check that -ffixed and -fcall-saved flags work correctly together.
+// RUN: %clang -target aarch64-none-gnu \
+// RUN: -ffixed-x18 \
+// RUN: -fcall-saved-x18 \
+// RUN: -### %s 2>&1 | FileCheck %s
+
+// CHECK: "-target-feature" "+reserve-x18"
+// CHECK: "-target-feature" "+call-saved-x18"
diff --git a/test/Driver/aarch64-fixed-x-register.c b/test/Driver/aarch64-fixed-x-register.c
new file mode 100644
index 000000000000..bc7d993ed9ab
--- /dev/null
+++ b/test/Driver/aarch64-fixed-x-register.c
@@ -0,0 +1,71 @@
+// RUN: %clang -target aarch64-none-gnu -ffixed-x1 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X1 < %t %s
+// CHECK-FIXED-X1: "-target-feature" "+reserve-x1"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x2 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X2 < %t %s
+// CHECK-FIXED-X2: "-target-feature" "+reserve-x2"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x3 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X3 < %t %s
+// CHECK-FIXED-X3: "-target-feature" "+reserve-x3"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x4 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X4 < %t %s
+// CHECK-FIXED-X4: "-target-feature" "+reserve-x4"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x5 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X5 < %t %s
+// CHECK-FIXED-X5: "-target-feature" "+reserve-x5"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x6 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X6 < %t %s
+// CHECK-FIXED-X6: "-target-feature" "+reserve-x6"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x7 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X7 < %t %s
+// CHECK-FIXED-X7: "-target-feature" "+reserve-x7"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x18 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X18 < %t %s
+// CHECK-FIXED-X18: "-target-feature" "+reserve-x18"
+
+// RUN: %clang -target aarch64-none-gnu -ffixed-x20 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-X20 < %t %s
+// CHECK-FIXED-X20: "-target-feature" "+reserve-x20"
+
+// Test multiple of reserve-x# options together.
+// RUN: %clang -target aarch64-none-gnu \
+// RUN: -ffixed-x1 \
+// RUN: -ffixed-x2 \
+// RUN: -ffixed-x18 \
+// RUN: -### %s 2> %t
+// RUN: FileCheck \
+// RUN: --check-prefix=CHECK-FIXED-X1 \
+// RUN: --check-prefix=CHECK-FIXED-X2 \
+// RUN: --check-prefix=CHECK-FIXED-X18 \
+// RUN: < %t %s
+
+// Test all reserve-x# options together.
+// RUN: %clang -target aarch64-none-gnu \
+// RUN: -ffixed-x1 \
+// RUN: -ffixed-x2 \
+// RUN: -ffixed-x3 \
+// RUN: -ffixed-x4 \
+// RUN: -ffixed-x5 \
+// RUN: -ffixed-x6 \
+// RUN: -ffixed-x7 \
+// RUN: -ffixed-x18 \
+// RUN: -ffixed-x20 \
+// RUN: -### %s 2> %t
+// RUN: FileCheck \
+// RUN: --check-prefix=CHECK-FIXED-X1 \
+// RUN: --check-prefix=CHECK-FIXED-X2 \
+// RUN: --check-prefix=CHECK-FIXED-X3 \
+// RUN: --check-prefix=CHECK-FIXED-X4 \
+// RUN: --check-prefix=CHECK-FIXED-X5 \
+// RUN: --check-prefix=CHECK-FIXED-X6 \
+// RUN: --check-prefix=CHECK-FIXED-X7 \
+// RUN: --check-prefix=CHECK-FIXED-X18 \
+// RUN: --check-prefix=CHECK-FIXED-X20 \
+// RUN: < %t %s
diff --git a/test/Driver/aarch64-fixed-x18.c b/test/Driver/aarch64-fixed-x18.c
deleted file mode 100644
index 631865f9aa4a..000000000000
--- a/test/Driver/aarch64-fixed-x18.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang -target aarch64-none-gnu -ffixed-x18 -### %s 2> %t
-// RUN: FileCheck --check-prefix=CHECK-FIXED-X18 < %t %s
-
-// CHECK-FIXED-X18: "-target-feature" "+reserve-x18"
diff --git a/test/Driver/aarch64-fixed-x20.c b/test/Driver/aarch64-fixed-x20.c
deleted file mode 100644
index 0be63971a441..000000000000
--- a/test/Driver/aarch64-fixed-x20.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang -target aarch64-none-gnu -ffixed-x20 -### %s 2> %t
-// RUN: FileCheck --check-prefix=CHECK-FIXED-X20 < %t %s
-
-// CHECK-FIXED-X20: "-target-feature" "+reserve-x20"
diff --git a/test/Driver/aarch64-mte.c b/test/Driver/aarch64-mte.c
new file mode 100644
index 000000000000..89c9da9e70ac
--- /dev/null
+++ b/test/Driver/aarch64-mte.c
@@ -0,0 +1,13 @@
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.4a+memtag %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.5a+memtag %s 2>&1 | FileCheck %s
+// CHECK: "-target-feature" "+mte"
+
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.4a+nomemtag %s 2>&1 | FileCheck %s --check-prefix=NOMTE
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.5a+nomemtag %s 2>&1 | FileCheck %s --check-prefix=NOMTE
+// NOMTE: "-target-feature" "-mte"
+
+// RUN: %clang -### -target aarch64-none-none-eabi %s 2>&1 | FileCheck %s --check-prefix=ABSENTMTE
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.4a %s 2>&1 | FileCheck %s --check-prefix=ABSENTMTE
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.5a %s 2>&1 | FileCheck %s --check-prefix=ABSENTMTE
+// ABSENTMTE-NOT: "-target-feature" "+mte"
+// ABSENTMTE-NOT: "-target-feature" "-mte"
diff --git a/test/Driver/aarch64-rand.c b/test/Driver/aarch64-rand.c
new file mode 100644
index 000000000000..e6f566eeb0b9
--- /dev/null
+++ b/test/Driver/aarch64-rand.c
@@ -0,0 +1,13 @@
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.4a+rng %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.5a+rng %s 2>&1 | FileCheck %s
+// CHECK: "-target-feature" "+rand"
+
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.4a+norng %s 2>&1 | FileCheck %s --check-prefix=NORAND
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.5a+norng %s 2>&1 | FileCheck %s --check-prefix=NORAND
+// NORAND: "-target-feature" "-rand"
+
+// RUN: %clang -### -target aarch64-none-none-eabi %s 2>&1 | FileCheck %s --check-prefix=ABSENTRAND
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.4a %s 2>&1 | FileCheck %s --check-prefix=ABSENTRAND
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8.5a %s 2>&1 | FileCheck %s --check-prefix=ABSENTRAND
+// ABSENTRAND-NOT: "-target-feature" "+rand"
+// ABSENTRAND-NOT: "-target-feature" "-rand"
diff --git a/test/Driver/aarch64-security-options.c b/test/Driver/aarch64-security-options.c
new file mode 100644
index 000000000000..9ba5067cc3cf
--- /dev/null
+++ b/test/Driver/aarch64-security-options.c
@@ -0,0 +1,54 @@
+// Check the -msign-return-address= option, which has a required argument to
+// select scope.
+// RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=none 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=non-leaf 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=all 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// Check that the -msign-return-address= option can also accept the signing key
+// to use.
+
+// RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=non-leaf 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-B --check-prefix=BTE-OFF
+
+// RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=all 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-B --check-prefix=BTE-OFF
+
+// -mbranch-protection with standard
+// RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=standard 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON
+
+// If the -msign-return-address and -mbranch-protection are both used, the
+// right-most one controls return address signing.
+// RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=non-leaf -mbranch-protection=none 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CONFLICT
+
+// RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=pac-ret -msign-return-address=none 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CONFLICT
+
+// RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=foo 2>&1 | \
+// RUN: FileCheck %s --check-prefix=BAD-RA-PROTECTION
+
+// RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=bar 2>&1 | \
+// RUN: FileCheck %s --check-prefix=BAD-BP-PROTECTION
+
+// RA-OFF: "-msign-return-address=none"
+// RA-NON-LEAF: "-msign-return-address=non-leaf"
+// RA-ALL: "-msign-return-address=all"
+
+// KEY-A: "-msign-return-address-key=a_key"
+
+// BTE-OFF-NOT: "-mbranch-target-enforce"
+// BTE-ON: "-mbranch-target-enforce"
+
+// CONFLICT: "-msign-return-address=none"
+
+// BAD-RA-PROTECTION: invalid branch protection option 'foo' in '-msign-return-address={{.*}}'
+// BAD-BP-PROTECTION: invalid branch protection option 'bar' in '-mbranch-protection={{.*}}'
+
+// BAD-B-KEY-COMBINATION: invalid branch protection option 'b-key' in '-mbranch-protection={{.*}}'
+// BAD-LEAF-COMBINATION: invalid branch protection option 'leaf' in '-mbranch-protection={{.*}}'
diff --git a/test/Driver/aarch64-ssbs.c b/test/Driver/aarch64-ssbs.c
new file mode 100644
index 000000000000..86c93ae92640
--- /dev/null
+++ b/test/Driver/aarch64-ssbs.c
@@ -0,0 +1,9 @@
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8a+ssbs %s 2>&1 | FileCheck %s
+// CHECK: "-target-feature" "+ssbs"
+
+// RUN: %clang -### -target aarch64-none-none-eabi -march=armv8a+nossbs %s 2>&1 | FileCheck %s --check-prefix=NOSSBS
+// NOSSBS: "-target-feature" "-ssbs"
+
+// RUN: %clang -### -target aarch64-none-none-eabi %s 2>&1 | FileCheck %s --check-prefix=ABSENTSSBS
+// ABSENTSSBS-NOT: "-target-feature" "+ssbs"
+// ABSENTSSBS-NOT: "-target-feature" "-ssbs"
diff --git a/test/Driver/addrsig.c b/test/Driver/addrsig.c
index fd5598c472e9..684e351298dc 100644
--- a/test/Driver/addrsig.c
+++ b/test/Driver/addrsig.c
@@ -1,8 +1,14 @@
+// Gentoo disables -faddrsig by default
+// XFAIL: gentoo
+
// RUN: %clang -### -target x86_64-unknown-linux -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
+// RUN: %clang -### -target x86_64-pc-win32 -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -faddrsig -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
// RUN: %clang -### -target x86_64-unknown-linux -fno-addrsig -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
// RUN: %clang -### -target x86_64-apple-darwin -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-scei-ps4 -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-linux-android21 -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
// ADDRSIG: -faddrsig
// NO-ADDRSIG-NOT: -faddrsig
diff --git a/test/Driver/amdgpu-features.c b/test/Driver/amdgpu-features.c
index 0e54a5e2512f..15bcfed1550d 100644
--- a/test/Driver/amdgpu-features.c
+++ b/test/Driver/amdgpu-features.c
@@ -6,8 +6,20 @@
// RUN: | FileCheck --check-prefix=CHECK-MAMDGPU-DEBUGGER-ABI-1-0 %s
// CHECK-MAMDGPU-DEBUGGER-ABI-1-0: "-target-feature" "+amdgpu-debugger-insert-nops" "-target-feature" "+amdgpu-debugger-emit-prologue"
+// RUN: %clang -### -target amdgcn -mcpu=gfx700 -mcode-object-v3 %s 2>&1 | FileCheck --check-prefix=CODE-OBJECT-V3 %s
+// CODE-OBJECT-V3: "-target-feature" "+code-object-v3"
+
+// RUN: %clang -### -target amdgcn -mcpu=gfx700 -mno-code-object-v3 %s 2>&1 | FileCheck --check-prefix=NO-CODE-OBJECT-V3 %s
+// NO-CODE-OBJECT-V3: "-target-feature" "-code-object-v3"
+
// RUN: %clang -### -target amdgcn -mcpu=gfx700 -mxnack %s 2>&1 | FileCheck --check-prefix=XNACK %s
// XNACK: "-target-feature" "+xnack"
// RUN: %clang -### -target amdgcn -mcpu=gfx700 -mno-xnack %s 2>&1 | FileCheck --check-prefix=NO-XNACK %s
// NO-XNACK: "-target-feature" "-xnack"
+
+// RUN: %clang -### -target amdgcn -mcpu=gfx700 -msram-ecc %s 2>&1 | FileCheck --check-prefix=SRAM-ECC %s
+// SRAM-ECC: "-target-feature" "+sram-ecc"
+
+// RUN: %clang -### -target amdgcn -mcpu=gfx700 -mno-sram-ecc %s 2>&1 | FileCheck --check-prefix=NO-SRAM-ECC %s
+// NO-SRAM-ECC: "-target-feature" "-sram-ecc"
diff --git a/test/Driver/amdgpu-macros.cl b/test/Driver/amdgpu-macros.cl
index c57d3805be7a..09f28123b15e 100644
--- a/test/Driver/amdgpu-macros.cl
+++ b/test/Driver/amdgpu-macros.cl
@@ -175,6 +175,7 @@
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx902 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX902 %s
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx904 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX904 %s
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx906 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX906 %s
+// RUN: %clang -E -dM -target amdgcn -mcpu=gfx909 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,GFX909 %s
// GFX600-DAG: #define FP_FAST_FMA 1
// GFX601-DAG: #define FP_FAST_FMA 1
@@ -191,6 +192,7 @@
// GFX902-DAG: #define FP_FAST_FMA 1
// GFX904-DAG: #define FP_FAST_FMA 1
// GFX906-DAG: #define FP_FAST_FMA 1
+// GFX909-DAG: #define FP_FAST_FMA 1
// GFX600-DAG: #define FP_FAST_FMAF 1
// GFX601-NOT: #define FP_FAST_FMAF 1
@@ -207,6 +209,7 @@
// GFX902-DAG: #define FP_FAST_FMAF 1
// GFX904-DAG: #define FP_FAST_FMAF 1
// GFX906-DAG: #define FP_FAST_FMAF 1
+// GFX909-DAG: #define FP_FAST_FMAF 1
// ARCH-GCN-DAG: #define __AMDGCN__ 1
// ARCH-GCN-DAG: #define __AMDGPU__ 1
@@ -227,6 +230,7 @@
// GFX902-DAG: #define __HAS_FMAF__ 1
// GFX904-DAG: #define __HAS_FMAF__ 1
// GFX906-DAG: #define __HAS_FMAF__ 1
+// GFX909-DAG: #define __HAS_FMAF__ 1
// GFX600-DAG: #define __HAS_FP64__ 1
// GFX601-DAG: #define __HAS_FP64__ 1
@@ -243,6 +247,7 @@
// GFX902-DAG: #define __HAS_FP64__ 1
// GFX904-DAG: #define __HAS_FP64__ 1
// GFX906-DAG: #define __HAS_FP64__ 1
+// GFX909-DAG: #define __HAS_FP64__ 1
// GFX600-DAG: #define __HAS_LDEXPF__ 1
// GFX601-DAG: #define __HAS_LDEXPF__ 1
@@ -259,6 +264,7 @@
// GFX902-DAG: #define __HAS_LDEXPF__ 1
// GFX904-DAG: #define __HAS_LDEXPF__ 1
// GFX906-DAG: #define __HAS_LDEXPF__ 1
+// GFX909-DAG: #define __HAS_LDEXPF__ 1
// GFX600-DAG: #define __gfx600__ 1
// GFX601-DAG: #define __gfx601__ 1
@@ -275,3 +281,4 @@
// GFX902-DAG: #define __gfx902__ 1
// GFX904-DAG: #define __gfx904__ 1
// GFX906-DAG: #define __gfx906__ 1
+// GFX909-DAG: #define __gfx909__ 1
diff --git a/test/Driver/amdgpu-mcpu.cl b/test/Driver/amdgpu-mcpu.cl
index c036e2ef093a..4191d1884cf4 100644
--- a/test/Driver/amdgpu-mcpu.cl
+++ b/test/Driver/amdgpu-mcpu.cl
@@ -84,6 +84,7 @@
// RUN: %clang -### -target amdgcn -mcpu=gfx902 %s 2>&1 | FileCheck --check-prefix=GFX902 %s
// RUN: %clang -### -target amdgcn -mcpu=gfx904 %s 2>&1 | FileCheck --check-prefix=GFX904 %s
// RUN: %clang -### -target amdgcn -mcpu=gfx906 %s 2>&1 | FileCheck --check-prefix=GFX906 %s
+// RUN: %clang -### -target amdgcn -mcpu=gfx909 %s 2>&1 | FileCheck --check-prefix=GFX909 %s
// GFX600: "-target-cpu" "gfx600"
// TAHITI: "-target-cpu" "tahiti"
@@ -117,3 +118,4 @@
// GFX902: "-target-cpu" "gfx902"
// GFX904: "-target-cpu" "gfx904"
// GFX906: "-target-cpu" "gfx906"
+// GFX909: "-target-cpu" "gfx909"
diff --git a/test/Driver/amdgpu-visibility.cl b/test/Driver/amdgpu-visibility.cl
new file mode 100644
index 000000000000..35969db0340e
--- /dev/null
+++ b/test/Driver/amdgpu-visibility.cl
@@ -0,0 +1,7 @@
+// RUN: %clang -### -target amdgcn-amd-amdhsa -x cl -c -emit-llvm %s 2>&1 | FileCheck -check-prefix=DEFAULT %s
+// RUN: %clang -### -target amdgcn-amd-amdhsa -x cl -c -emit-llvm -fvisibility=protected %s 2>&1 | FileCheck -check-prefix=OVERRIDE-PROTECTED %s
+// RUN: %clang -### -target amdgcn-amd-amdhsa -x cl -c -emit-llvm -fvisibility-ms-compat %s 2>&1 | FileCheck -check-prefix=OVERRIDE-MS %s
+
+// DEFAULT: "-fvisibility" "hidden"
+// OVERRIDE-PROTECTED: "-fvisibility" "protected"
+// OVERRIDE-MS: "-fvisibility" "hidden" "-ftype-visibility" "default"
diff --git a/test/Driver/android-aarch64-link.cpp b/test/Driver/android-aarch64-link.cpp
index 2c4cfb9898eb..051bcd57b17b 100644
--- a/test/Driver/android-aarch64-link.cpp
+++ b/test/Driver/android-aarch64-link.cpp
@@ -12,6 +12,11 @@
// RUN: -mcpu=cortex-a57 -### -v %s 2> %t
// RUN: FileCheck -check-prefix=CORTEX-A57 < %t %s
//
+// RUN: %clang -target aarch64-none-linux-android \
+// RUN: -### -v %s 2> %t
+// RUN: FileCheck -check-prefix=MAX-PAGE-SIZE < %t %s
+//
// GENERIC-ARM: --fix-cortex-a53-843419
// CORTEX-A53: --fix-cortex-a53-843419
// CORTEX-A57-NOT: --fix-cortex-a53-843419
+// MAX-PAGE-SIZE: max-page-size=4096
diff --git a/test/Driver/android-gcc-toolchain.c b/test/Driver/android-gcc-toolchain.c
new file mode 100644
index 000000000000..17834132ad4c
--- /dev/null
+++ b/test/Driver/android-gcc-toolchain.c
@@ -0,0 +1,8 @@
+// Test that gcc-toolchain option works correctly with a aarch64-linux-gnu
+// triple.
+//
+// RUN: %clang %s -### -v --target=aarch64-linux-gnu \
+// RUN: --gcc-toolchain=%S/Inputs/basic_android_ndk_tree/ 2>&1 \
+// RUN: | FileCheck %s
+//
+// CHECK: Selected GCC installation: {{.*}}/Inputs/basic_android_ndk_tree/lib/gcc/aarch64-linux-android/4.9
diff --git a/test/Driver/android-ndk-standalone.cpp b/test/Driver/android-ndk-standalone.cpp
index dd5ebe9754af..c4d939934782 100644
--- a/test/Driver/android-ndk-standalone.cpp
+++ b/test/Driver/android-ndk-standalone.cpp
@@ -2,21 +2,13 @@
// toolchain.
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck %s
// CHECK: {{.*}}clang{{.*}}" "-cc1"
// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
-// CHECK: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb"
-// CHECK-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a"
-// CHECK-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
-// CHECK: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
-// CHECK-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb"
-// CHECK-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a"
-// CHECK-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
-// CHECK: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
// CHECK: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
@@ -49,21 +41,47 @@
// CHECK-14: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target armv7a-none-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -B%S/Inputs/basic_android_ndk_tree \
+// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
+// RUN: | FileCheck --check-prefix=CHECK-STDCXX %s
+// CHECK-STDCXX: {{.*}}clang{{.*}}" "-cc1"
+// CHECK-STDCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-STDCXX: "-internal-isystem" "{{.*}}/include/c++/4.9"
+// CHECK-STDCXX-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb"
+// CHECK-STDCXX-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a"
+// CHECK-STDCXX-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
+// CHECK-STDCXX: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
+// CHECK-STDCXX-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb"
+// CHECK-STDCXX-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a"
+// CHECK-STDCXX-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
+// CHECK-STDCXX: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-STDCXX: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/armv7-a/thumb"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/armv7-a"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/thumb"
+// CHECK-STDCXX: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/armv7-a/thumb"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/armv7-a"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/thumb"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a/thumb"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
+// CHECK-STDCXX: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi/21"
+// CHECK-STDCXX: "-L{{.*}}/sysroot/usr/lib/arm-linux-androideabi"
+// CHECK-STDCXX: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/arm-linux-androideabi/lib"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a/thumb"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/armv7-a"
+// CHECK-STDCXX-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib/thumb"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target armv7a-none-linux-androideabi21 \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s
// CHECK-ARMV7: {{.*}}clang{{.*}}" "-cc1"
// CHECK-ARMV7: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
-// CHECK-ARMV7: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-ARMV7-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb"
-// CHECK-ARMV7-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
-// CHECK-ARMV7-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
-// CHECK-ARMV7: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a"
-// CHECK-ARMV7-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb"
-// CHECK-ARMV7-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
-// CHECK-ARMV7-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
-// CHECK-ARMV7: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-ARMV7: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-ARMV7: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK-ARMV7: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
// CHECK-ARMV7: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
@@ -89,19 +107,19 @@
//
// Other flags that can trigger armv7 mode.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 \
// RUN: -march=armv7 \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 \
// RUN: -march=armv7a \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7 %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 \
// RUN: -march=armv7-a \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -109,22 +127,14 @@
//
// ARM thumb mode.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 \
// RUN: -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-THUMB %s
// CHECK-THUMB: {{.*}}clang{{.*}}" "-cc1"
// CHECK-THUMB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
-// CHECK-THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7/thumb"
-// CHECK-THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7"
-// CHECK-THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
-// CHECK-THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
-// CHECK-THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7/thumb"
-// CHECK-THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7"
-// CHECK-THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
-// CHECK-THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-THUMB: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-THUMB: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK-THUMB: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
// CHECK-THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
@@ -151,22 +161,14 @@
//
// ARM V7 thumb mode.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 \
// RUN: -march=armv7-a -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7THUMB %s
// CHECK-ARMV7THUMB: {{.*}}clang{{.*}}" "-cc1"
// CHECK-ARMV7THUMB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
-// CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-ARMV7THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a"
-// CHECK-ARMV7THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
-// CHECK-ARMV7THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
-// CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a/thumb"
-// CHECK-ARMV7THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/armv7-a"
-// CHECK-ARMV7THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi/thumb"
-// CHECK-ARMV7THUMB-NOT: "-internal-isystem" "{{.*}}/include/c++/4.9/arm-linux-androideabi"
-// CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-ARMV7THUMB: "-internal-isystem" "{{.*}}/sysroot/usr/local/include"
// CHECK-ARMV7THUMB: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
// CHECK-ARMV7THUMB: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/arm-linux-androideabi"
@@ -191,7 +193,7 @@
// CHECK-ARMV7THUMB-NOT: "-L{{.*}}/lib/gcc/arm-linux-androideabi/4.9/../{{[^ ]*}}/lib"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target arm-linux-androideabi21 \
// RUN: -march=armv7-a -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
@@ -205,21 +207,19 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target armv7a-none-linux-androideabi21 -stdlib=libstdc++ \
+// RUN: -target armv7a-none-linux-androideabi21 \
// RUN: -mthumb \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARMV7THUMB %s
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target aarch64-linux-android21 -stdlib=libstdc++ \
+// RUN: -target aarch64-linux-android21 \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-AARCH64 %s
// CHECK-AARCH64: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/4.9/aarch64-linux-android"
-// CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-AARCH64: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/aarch64-linux-android"
// CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-AARCH64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
@@ -230,14 +230,12 @@
// CHECK-AARCH64: "-L{{.*}}/lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/lib"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -target arm64-linux-android21 -stdlib=libstdc++ \
+// RUN: -target arm64-linux-android21 \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ARM64 %s
// CHECK-ARM64: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/4.9/aarch64-linux-android"
-// CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-ARM64: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/aarch64-linux-android"
// CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-ARM64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
@@ -249,14 +247,12 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target mipsel-linux-android21 \
-// RUN: -mips32 -stdlib=libstdc++ \
+// RUN: -mips32 \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-MIPS %s
// CHECK-MIPS: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-MIPS: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-MIPS: "-internal-isystem" "{{.*}}/include/c++/4.9/mipsel-linux-android"
-// CHECK-MIPS: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-MIPS: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-MIPS: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-MIPS: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
// CHECK-MIPS: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
@@ -267,14 +263,11 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target i686-linux-android21 \
-// RUN: -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-I686 %s
// CHECK-I686: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/4.9/i686-linux-android"
-// CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-I686: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/i686-linux-android"
// CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-I686: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
@@ -286,14 +279,11 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-linux-android21 \
-// RUN: -stdlib=libstdc++ \
// RUN: -B%S/Inputs/basic_android_ndk_tree \
// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-X86_64 %s
// CHECK-X86_64: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/4.9/x86_64-linux-android"
-// CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/4.9/backward"
+// CHECK-X86_64: "-internal-isystem" "{{.*}}/include/c++/v1"
// CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include/x86_64-linux-android"
// CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/include"
// CHECK-X86_64: "-internal-externc-isystem" "{{.*}}/sysroot/usr/include"
diff --git a/test/Driver/arm-cortex-cpus.c b/test/Driver/arm-cortex-cpus.c
index 541a1e4e4e58..04554ee3bd99 100644
--- a/test/Driver/arm-cortex-cpus.c
+++ b/test/Driver/arm-cortex-cpus.c
@@ -73,11 +73,11 @@
// RUN: %clang -target armv6k -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V6K %s
// RUN: %clang -target arm -march=armv6k -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V6K %s
-// CHECK-V6K: "-cc1"{{.*}} "-triple" "armv6k-{{.*}} "-target-cpu" "arm1176j-s"
+// CHECK-V6K: "-cc1"{{.*}} "-triple" "armv6k-{{.*}} "-target-cpu" "mpcore"
// RUN: %clang -target armv6k -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V6K-THUMB %s
// RUN: %clang -target arm -march=armv6k -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V6K-THUMB %s
-// CHECK-V6K-THUMB: "-cc1"{{.*}} "-triple" "thumbv6k-{{.*}} "-target-cpu" "arm1176j-s"
+// CHECK-V6K-THUMB: "-cc1"{{.*}} "-triple" "thumbv6k-{{.*}} "-target-cpu" "mpcore"
// RUN: %clang -target armv6t2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V6T2 %s
// RUN: %clang -target arm -march=armv6t2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V6T2 %s
@@ -284,9 +284,6 @@
// RUN: %clang -target arm -march=armebv8.2-a -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V82A-THUMB %s
// CHECK-BE-V82A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8.2a-{{.*}}" "-target-cpu" "generic"
-// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-V82A-FP16 %s
-// CHECK-V82A-FP16: "-cc1"{{.*}} "-triple" "armv8.2{{.*}}" "-target-cpu" "generic" {{.*}}"-target-feature" "+fullfp16"
-
// RUN: %clang -target armv8.3a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A %s
// RUN: %clang -target arm -march=armv8.3a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A %s
// RUN: %clang -target arm -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A %s
@@ -304,9 +301,6 @@
// RUN: %clang -target arm -march=armebv8.3-a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V83A %s
// CHECK-BE-V83A: "-cc1"{{.*}} "-triple" "armebv8.3{{.*}}" "-target-cpu" "generic"
-// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-V83A-FP16 %s
-// CHECK-V83A-FP16: "-cc1"{{.*}} "-triple" "armv8.3{{.*}}" "-target-cpu" "generic" {{.*}}"-target-feature" "+fullfp16"
-
// RUN: %clang -target armv8.4a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A %s
// RUN: %clang -target arm -march=armv8.4a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A %s
// RUN: %clang -target arm -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A %s
@@ -324,15 +318,129 @@
// RUN: %clang -target arm -march=armebv8.4-a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V84A %s
// CHECK-BE-V84A: "-cc1"{{.*}} "-triple" "armebv8.4{{.*}}" "-target-cpu" "generic"
-// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-V84A-FP16 %s
-// CHECK-V84A-FP16: "-cc1"{{.*}} "-triple" "armv8.4{{.*}}" "-target-cpu" "generic" {{.*}}"-target-feature" "+fullfp16"
+// RUN: %clang -target armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V85A %s
+// RUN: %clang -target arm -march=armv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V85A %s
+// RUN: %clang -target arm -march=armv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V85A %s
+// RUN: %clang -target arm -march=armv8.5a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V85A %s
+// RUN: %clang -target armv8.5a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V85A %s
+// RUN: %clang -target arm -march=armv8.5a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V85A %s
+// RUN: %clang -target arm -mlittle-endian -march=armv8.5-a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V85A %s
+// CHECK-V85A: "-cc1"{{.*}} "-triple" "armv8.5{{.*}}" "-target-cpu" "generic"
+
+// RUN: %clang -target armebv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V85A %s
+// RUN: %clang -target armv8.5a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V85A %s
+// RUN: %clang -target armeb -march=armebv8.5a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V85A %s
+// RUN: %clang -target armeb -march=armebv8.5-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V85A %s
+// RUN: %clang -target arm -march=armebv8.5a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V85A %s
+// RUN: %clang -target arm -march=armebv8.5-a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V85A %s
+// CHECK-BE-V85A: "-cc1"{{.*}} "-triple" "armebv8.5{{.*}}" "-target-cpu" "generic"
// Once we have CPUs with optional v8.2-A FP16, we will need a way to turn it
// on and off. Cortex-A53 is a placeholder for now.
// RUN: %clang -target armv8a-linux-eabi -mcpu=cortex-a53+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-CORTEX-A53-FP16 %s
// RUN: %clang -target armv8a-linux-eabi -mcpu=cortex-a53+nofp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-CORTEX-A53-NOFP16 %s
// CHECK-CORTEX-A53-FP16: "-cc1" {{.*}}"-target-cpu" "cortex-a53" {{.*}}"-target-feature" "+fullfp16"
-// CHECK-CORTEX-A53-NOFP16: "-cc1" {{.*}}"-target-cpu" "cortex-a53" {{.*}}"-target-feature" "-fullfp16"
+// CHECK-CORTEX-A53-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-CORTEX-A53-NOFP16: "-cc1" {{.*}}"-target-cpu" "cortex-a53" {{.*}}"-target-feature" "-fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-NOFP16FML %s
+// CHECK-V8A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V8A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-FP16 %s
+// CHECK-V8A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V8A-FP16: "-target-feature" "+fullfp16"
+// CHECK-V8A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V8A-FP16-SAME: {{$}}
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-FP16FML %s
+// CHECK-V8A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V82A-NOFP16FML %s
+// CHECK-V82A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V82A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V82A-FP16 %s
+// CHECK-V82A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V82A-FP16: "-target-feature" "+fullfp16"
+// CHECK-V82A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V82A-FP16-SAME: {{$}}
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V82A-FP16FML %s
+// CHECK-V82A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V82A-FP16-NOFP16FML %s
+// CHECK-V82A-FP16-NOFP16FML: "-target-feature" "+fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V82A-NOFP16FML-FP16 %s
+// CHECK-V82A-NOFP16FML-FP16: "-target-feature" "-fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V82A-FP16FML-NOFP16 %s
+// CHECK-V82A-FP16FML-NOFP16: "-target-feature" "-fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.2-a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V82A-NOFP16-FP16FML %s
+// CHECK-V82A-NOFP16-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A-NOFP16FML %s
+// CHECK-V83A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V83A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A-FP16 %s
+// CHECK-V83A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V83A-FP16: "-target-feature" "+fullfp16"
+// CHECK-V83A-FP16-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V83A-FP16-SAME: {{$}}
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A-FP16FML %s
+// CHECK-V83A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A-FP16-NOFP16FML %s
+// CHECK-V83A-FP16-NOFP16FML: "-target-feature" "+fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A-NOFP16FML-FP16 %s
+// CHECK-V83A-NOFP16FML-FP16: "-target-feature" "-fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A-FP16FML-NOFP16 %s
+// CHECK-V83A-FP16FML-NOFP16: "-target-feature" "-fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.3-a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V83A-NOFP16-FP16FML %s
+// CHECK-V83A-NOFP16-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A-NOFP16FML %s
+// CHECK-V84A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fp16fml"
+// CHECK-V84A-NOFP16FML-NOT: "-target-feature" "{{[+-]}}fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A-FP16 %s
+// CHECK-V84A-FP16: "-target-feature" "+fullfp16" "-target-feature" "+fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A-FP16FML %s
+// CHECK-V84A-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a+fp16+nofp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A-FP16-NOFP16FML %s
+// CHECK-V84A-FP16-NOFP16FML: "-target-feature" "+fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a+nofp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A-NOFP16FML-FP16 %s
+// CHECK-V84A-NOFP16FML-FP16: "-target-feature" "+fullfp16" "-target-feature" "+fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a+fp16fml+nofp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A-FP16FML-NOFP16 %s
+// CHECK-V84A-FP16FML-NOFP16: "-target-feature" "-fullfp16" "-target-feature" "-fp16fml"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.4-a+nofp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V84A-NOFP16-FP16FML %s
+// CHECK-V84A-NOFP16-FP16FML: "-target-feature" "+fp16fml" "-target-feature" "+fullfp16"
+
+// RUN: %clang -target armv8a-linux-eabi -march=armv8.5-a+fp16 -### -c %s 2>&1 | FileCheck --check-prefix CHECK-V85A-FP16 %s
+// CHECK-V85A-FP16: "-cc1"{{.*}} "-triple" "armv8.5{{.*}}" "-target-cpu" "generic" {{.*}}"-target-feature" "+fullfp16"
+
+// RUN: %clang -target arm -march=armv8.2-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.2-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.2-a+fp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.2-a+fp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16+fp16fml -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16fml+fp16 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FULLFP16-SOFT %s
+// CHECK-FULLFP16-SOFT-NOT: "-target-feature" "+fullfp16"
+// CHECK-FULLFP16-SOFT-NOT: "-target-feature" "+fp16fml"
// RAS is on by default for v8.2-a (this is handled in the backend), but can be
// optionally enabled for v8.0-a and v8.1-a. Cortex-A53 does not have RAS, but
@@ -552,17 +660,18 @@
// RUN: %clang -target arm -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
-// RUN: %clang -target arm -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
-// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s
// CHECK-CPUV8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}
// RUN: %clang -target arm -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s
// RUN: %clang -target arm -mcpu=cortex-a75 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s
// RUN: %clang -target arm -mcpu=cortex-a55 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s
// RUN: %clang -target arm -mcpu=cortex-a75 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s
+//
+// RUN: %clang -target arm -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s
// CHECK-CPUV82A: "-cc1"{{.*}} "-triple" "armv8.2a-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a32 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
@@ -581,17 +690,18 @@
// RUN: %clang -target armeb -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target armeb -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target armeb -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
-// RUN: %clang -target armeb -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
-// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
// CHECK-BE-CPUV8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s
// RUN: %clang -target armeb -mcpu=cortex-a75 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s
// RUN: %clang -target arm -mcpu=cortex-a55 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s
// RUN: %clang -target arm -mcpu=cortex-a75 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s
+//
+// RUN: %clang -target armeb -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s
// CHECK-BE-CPUV82A: "-cc1"{{.*}} "-triple" "armebv8.2a-{{.*}}
// RUN: %clang -target arm-linux-gnueabi -mcpu=cortex-r52 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8R %s
@@ -613,18 +723,19 @@
// RUN: %clang -target arm -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
-// RUN: %clang -target arm -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
-// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// CHECK-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}}
-// RUN: %clang -target arm -mcpu=cortex-a55 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECKCPUV82A-THUMB %s
-// RUN: %clang -target arm -mcpu=cortex-a75 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECKCPUV82A-THUMB %s
-// RUN: %clang -target arm -mcpu=cortex-a55 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECKCPUV82A-THUMB %s
-// RUN: %clang -target arm -mcpu=cortex-a75 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECKCPUV82A-THUMB %s
-// CHECKCPUV82A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8.2a-{{.*}}
+// RUN: %clang -target arm -mcpu=cortex-a55 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A-THUMB %s
+// RUN: %clang -target arm -mcpu=cortex-a75 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A-THUMB %s
+// RUN: %clang -target arm -mcpu=cortex-a55 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A-THUMB %s
+// RUN: %clang -target arm -mcpu=cortex-a75 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A-THUMB %s
+//
+// RUN: %clang -target arm -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A-THUMB %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A-THUMB %s
+// CHECK-CPUV82A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8.2a-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a32 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target armeb -mcpu=cortex-a35 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
@@ -642,17 +753,18 @@
// RUN: %clang -target armeb -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target armeb -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target armeb -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
-// RUN: %clang -target armeb -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m2 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=exynos-m3 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
-// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
// CHECK-BE-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a55 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s
// RUN: %clang -target armeb -mcpu=cortex-a75 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a55 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a75 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s
+//
+// RUN: %clang -target armeb -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s
+// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s
// CHECK-BE-CPUV82A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8.2a-{{.*}}
// RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A73 %s
diff --git a/test/Driver/arm-features.c b/test/Driver/arm-features.c
index 74cedf3bd83b..b278af15fa4f 100644
--- a/test/Driver/arm-features.c
+++ b/test/Driver/arm-features.c
@@ -17,3 +17,42 @@
// RUN: %clang -target arm-none-none-eabi -mcpu=generic+nodsp -march=armv8m.main -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NODSP %s
// RUN: %clang -target arm-none-none-eabi -mcpu=generic -march=armv8m.main+nodsp -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NODSP %s
// CHECK-NODSP: "-cc1"{{.*}} "-triple" "thumbv8m.main-{{.*}} "-target-cpu" "generic"{{.*}} "-target-feature" "-dsp"
+
+// Check that crypto means sha2 + aes:
+//
+// Check +sha2 +aes:
+//
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.2a+sha2+aes -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-SHA2-AES %s
+// CHECK-SHA2-AES: "-cc1"{{.*}} "-triple" "armv8.2a-{{.*}} "-target-cpu" "generic"{{.*}} "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check -sha2 -aes:
+//
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.2a+sha2+nosha2+aes+noaes -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SHA2-AES %s
+// CHECK-NO-SHA2-AES: "-cc1"{{.*}} "-triple" "armv8.2a-{{.*}} "-target-cpu" "generic"{{.*}} "-target-feature" "-sha2" "-target-feature" "-aes"
+//
+// Check +crypto:
+//
+// RUN: %clang -target arm-arm-none-eabi -march=armv8a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO2 %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO2 %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.2a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO2 %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.3a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO2 %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.4a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO2 %s
+// CHECK-CRYPTO2: "-cc1"{{.*}} "-target-cpu" "generic"{{.*}} "-target-feature" "+crypto" "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check -crypto:
+//
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO2 %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.2a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO2 %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.3a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO2 %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.4a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO2 %s
+// CHECK-NOCRYPTO2-NOT: "-target-feature" "+crypto" "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check +crypto -sha2 -aes:
+//
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1a+crypto+nosha2+noaes -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO3 %s
+// CHECK-CRYPTO3-NOT: "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check -crypto +sha2 +aes:
+//
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1a+nocrypto+sha2+aes -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO4 %s
+// CHECK-CRYPTO4: "-target-feature" "+sha2" "-target-feature" "+aes"
diff --git a/test/Driver/arm-ias-Wa.s b/test/Driver/arm-ias-Wa.s
index 1483f902ff1d..fd2f157c88b2 100644
--- a/test/Driver/arm-ias-Wa.s
+++ b/test/Driver/arm-ias-Wa.s
@@ -71,7 +71,7 @@
// RUN: %clang -target armv7r-none-eabi -c %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-R-PROFILE %s
-// CHECK-R-PROFILE: "-triple" "armv7r-none--eabi"
+// CHECK-R-PROFILE: "-triple" "armv7r-none-unknown-eabi"
// RUN: %clang -target armv7m-none-eabi -c %s -### 2>&1 \
// RUN: %clang -target thumbv7m-none-eabi -c %s -### 2>&1 \
diff --git a/test/Driver/arm-mfpu.c b/test/Driver/arm-mfpu.c
index 2f8d64f02392..c3a644f2412d 100644
--- a/test/Driver/arm-mfpu.c
+++ b/test/Driver/arm-mfpu.c
@@ -364,3 +364,67 @@
// CHECK-SOFT-ABI-FP: "-target-feature" "-fp-armv8"
// CHECK-SOFT-ABI-FP: "-target-feature" "-neon"
// CHECK-SOFT-ABI-FP: "-target-feature" "-crypto"
+
+// RUN: %clang -target arm-linux-androideabi21 %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-ARM5-ANDROID-FP-DEFAULT %s
+// CHECK-ARM5-ANDROID-FP-DEFAULT: "-target-feature" "+soft-float"
+// CHECK-ARM5-ANDROID-FP-DEFAULT: "-target-feature" "+soft-float-abi"
+// CHECK-ARM5-ANDROID-FP-DEFAULT-NOT: "-target-feature" "+d16"
+// CHECK-ARM5-ANDROID-FP-DEFAULT-NOT: "-target-feature" "+vfp3"
+// CHECK-ARM5-ANDROID-FP-DEFAULT-NOT: "-target-feature" "+vfp4"
+// CHECK-ARM5-ANDROID-FP-DEFAULT-NOT: "-target-feature" "+fp-armv8"
+// CHECK-ARM5-ANDROID-FP-DEFAULT-NOT: "-target-feature" "+neon"
+// CHECK-ARM5-ANDROID-FP-DEFAULT-NOT: "-target-feature" "+crypto"
+
+// RUN: %clang -target arm-linux-androideabi21 -march=armv7-a %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-MARCH-ARM7-ANDROID-FP %s
+// CHECK-MARCH-ARM7-ANDROID-FP-NOT: "-target-feature" "+soft-float"
+// CHECK-MARCH-ARM7-ANDROID-FP: "-target-feature" "+soft-float-abi"
+// CHECK-MARCH-ARM7-ANDROID-FP: "-target-feature" "+d16"
+// CHECK-MARCH-ARM7-ANDROID-FP: "-target-feature" "+vfp3"
+// CHECK-MARCH-ARM7-ANDROID-FP-NOT: "-target-feature" "+vfp4"
+// CHECK-MARCH-ARM7-ANDROID-FP-NOT: "-target-feature" "+fp-armv8"
+// CHECK-MARCH-ARM7-ANDROID-FP-NOT: "-target-feature" "+neon"
+// CHECK-MARCH-ARM7-ANDROID-FP-NOT: "-target-feature" "+crypto"
+
+// RUN: %clang -target armv7-linux-androideabi21 %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-ARM-ANDROID-L-FP-DEFAULT %s
+// CHECK-ARM-ANDROID-L-FP-DEFAULT-NOT: "-target-feature" "+soft-float"
+// CHECK-ARM-ANDROID-L-FP-DEFAULT: "-target-feature" "+soft-float-abi"
+// CHECK-ARM-ANDROID-L-FP-DEFAULT: "-target-feature" "+d16"
+// CHECK-ARM-ANDROID-L-FP-DEFAULT: "-target-feature" "+vfp3"
+// CHECK-ARM-ANDROID-L-FP-DEFAULT-NOT: "-target-feature" "+vfp4"
+// CHECK-ARM-ANDROID-L-FP-DEFAULT-NOT: "-target-feature" "+fp-armv8"
+// CHECK-ARM-ANDROID-L-FP-DEFAULT-NOT: "-target-feature" "+neon"
+// CHECK-ARM-ANDROID-L-FP-DEFAULT-NOT: "-target-feature" "+crypto"
+
+// RUN: %clang -target armv7-linux-androideabi21 -mfpu=neon %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-ARM-ANDROID-L-FP-NEON %s
+// CHECK-ARM-ANDROID-L-FP-NEON-NOT: "-target-feature" "+soft-float"
+// CHECK-ARM-ANDROID-L-FP-NEON: "-target-feature" "+soft-float-abi"
+// CHECK-ARM-ANDROID-L-FP-NEON: "-target-feature" "+vfp3"
+// CHECK-ARM-ANDROID-L-FP-NEON-NOT: "-target-feature" "+vfp4"
+// CHECK-ARM-ANDROID-L-FP-NEON-NOT: "-target-feature" "+fp-armv8"
+// CHECK-ARM-ANDROID-L-FP-NEON: "-target-feature" "+neon"
+// CHECK-ARM-ANDROID-L-FP-NEON-NOT: "-target-feature" "+crypto"
+
+// RUN: %clang -target armv7-linux-androideabi23 %s -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-ARM-ANDROID-M-FP-DEFAULT %s
+// CHECK-ARM-ANDROID-M-FP-DEFAULT-NOT: "-target-feature" "+soft-float"
+// CHECK-ARM-ANDROID-M-FP-DEFAULT: "-target-feature" "+soft-float-abi"
+// CHECK-ARM-ANDROID-M-FP-DEFAULT: "-target-feature" "+vfp3"
+// CHECK-ARM-ANDROID-M-FP-DEFAULT-NOT: "-target-feature" "+vfp4"
+// CHECK-ARM-ANDROID-M-FP-DEFAULT-NOT: "-target-feature" "+fp-armv8"
+// CHECK-ARM-ANDROID-M-FP-DEFAULT: "-target-feature" "+neon"
+// CHECK-ARM-ANDROID-M-FP-DEFAULT-NOT: "-target-feature" "+crypto"
+
+// RUN: %clang -target armv7-linux-androideabi23 %s -mfpu=vfp3-d16 -### -c 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-ARM-ANDROID-M-FP-D16 %s
+// CHECK-ARM-ANDROID-M-FP-D16-NOT: "-target-feature" "+soft-float"
+// CHECK-ARM-ANDROID-M-FP-D16: "-target-feature" "+soft-float-abi"
+// CHECK-ARM-ANDROID-M-FP-D16: "-target-feature" "+d16"
+// CHECK-ARM-ANDROID-M-FP-D16: "-target-feature" "+vfp3"
+// CHECK-ARM-ANDROID-M-FP-D16-NOT: "-target-feature" "+vfp4"
+// CHECK-ARM-ANDROID-M-FP-D16-NOT: "-target-feature" "+fp-armv8"
+// CHECK-ARM-ANDROID-M-FP-D16-NOT: "-target-feature" "+neon"
+// CHECK-ARM-ANDROID-M-FP-D16-NOT: "-target-feature" "+crypto"
diff --git a/test/Driver/arm-target-as-mthumb.s b/test/Driver/arm-target-as-mthumb.s
index c2c0fd0a653c..7e014bb9d43f 100644
--- a/test/Driver/arm-target-as-mthumb.s
+++ b/test/Driver/arm-target-as-mthumb.s
@@ -7,11 +7,11 @@
// RUN: %clang -target armv7a-linux-gnueabi -### -c -Wa,-mthumb \
// RUN: %S/Inputs/wildcard1.c 2>&1 | FileCheck -check-prefix=TRIPLE-ARM %s
-// TRIPLE-ARM: "-triple" "armv7--linux-gnueabi"
+// TRIPLE-ARM: "-triple" "armv7-unknown-linux-gnueabi"
// RUN: %clang -target armv7a-linux-gnueabi -### -c -Wa,-mthumb %s 2>&1 | \
// RUN: FileCheck -check-prefix=TRIPLE-THUMB %s
// RUN: %clang -target armv7a-linux-gnueabi -### -c -Xassembler -mthumb %s \
// RUN: 2>&1 | FileCheck -check-prefix=TRIPLE-THUMB %s
-// TRIPLE-THUMB: "-triple" "thumbv7--linux-gnueabi"
+// TRIPLE-THUMB: "-triple" "thumbv7-unknown-linux-gnueabi"
diff --git a/test/Driver/autocomplete.c b/test/Driver/autocomplete.c
index 16f2edf03452..f8271770d063 100644
--- a/test/Driver/autocomplete.c
+++ b/test/Driver/autocomplete.c
@@ -25,6 +25,7 @@
// STDLIBALL-NEXT: platform
// RUN: %clang --autocomplete=-meabi,d | FileCheck %s -check-prefix=MEABI
// MEABI: default
+// RUN: %clang --autocomplete=-meabi, | FileCheck %s -check-prefix=MEABIALL
// RUN: %clang --autocomplete=-meabi | FileCheck %s -check-prefix=MEABIALL
// MEABIALL: 4
// MEABIALL-NEXT: 5
@@ -115,3 +116,14 @@
// Check if they can autocomplete values with coron
// RUN: %clang --autocomplete=foo,bar,,,-fno-sanitize-coverage=,f | FileCheck %s -check-prefix=FNOSANICOVER-CORON
// FNOSANICOVER-CORON: func
+
+// Clang should return empty string when no value completion was found, which will fall back to file autocompletion
+// RUN: %clang --autocomplete=-fmodule-file= | FileCheck %s -check-prefix=MODULE_FILE_EQUAL
+// MODULE_FILE_EQUAL-NOT: -fmodule-file=
+// RUN: %clang --autocomplete=-fmodule-file | FileCheck %s -check-prefix=MODULE_FILE
+// MODULE_FILE: -fmodule-file=
+
+// RUN: %clang --autocomplete=-Qunused-arguments, | FileCheck %s -check-prefix=QUNUSED_COMMA
+// QUNUSED_COMMA-NOT: -Qunused-arguments
+// RUN: %clang --autocomplete=-Qunused-arguments | FileCheck %s -check-prefix=QUNUSED
+// QUNUSED: -Qunused-arguments
diff --git a/test/Driver/baremetal.cpp b/test/Driver/baremetal.cpp
index 2e93734651e8..68031fede72c 100644
--- a/test/Driver/baremetal.cpp
+++ b/test/Driver/baremetal.cpp
@@ -4,7 +4,7 @@
// RUN: -L some/directory/user/asked/for \
// RUN: --sysroot=%S/Inputs/baremetal_arm \
// RUN: | FileCheck --check-prefix=CHECK-V6M-C %s
-// CHECK-V6M-C: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "thumbv6m-none--eabi"
+// CHECK-V6M-C: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "thumbv6m-none-unknown-eabi"
// CHECK-V6M-C-SAME: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-V6M-C-SAME: "-isysroot" "[[SYSROOT:[^"]*]]"
// CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
diff --git a/test/Driver/biarch.c b/test/Driver/biarch.c
index c2b2e4eef847..51e173faa7e6 100644
--- a/test/Driver/biarch.c
+++ b/test/Driver/biarch.c
@@ -1,33 +1,33 @@
// RUN: %clang -target i386--netbsd -m32 %s -### 2>&1 | FileCheck -check-prefix=I386 %s
// RUN: %clang -target x86_64--netbsd -m32 %s -### 2>&1 | FileCheck -check-prefix=I386 %s
-// I386: "-cc1" "-triple" "i386--netbsd"
+// I386: "-cc1" "-triple" "i386-unknown-netbsd"
// RUN: %clang -target i386--netbsd -m64 %s -### 2>&1 | FileCheck -check-prefix=X86_64 %s
// RUN: %clang -target x86_64--netbsd -m64 %s -### 2>&1 | FileCheck -check-prefix=X86_64 %s
-// X86_64: "-cc1" "-triple" "x86_64--netbsd"
+// X86_64: "-cc1" "-triple" "x86_64-unknown-netbsd"
// r196538 set arm1176jzf-s as default CPU for ARMv6 on NetBSD
// RUN: %clang -target armv6--netbsd-eabihf -m32 %s -### 2>&1 | FileCheck -check-prefix=ARMV6 %s
-// ARMV6: "-cc1" "-triple" "armv6kz--netbsd-eabihf"
+// ARMV6: "-cc1" "-triple" "armv6kz-unknown-netbsd-eabihf"
// RUN: %clang -target sparcv9--netbsd -m32 %s -### 2>&1 | FileCheck -check-prefix=SPARC %s
// RUN: %clang -target sparc--netbsd -m32 %s -### 2>&1 | FileCheck -check-prefix=SPARC %s
-// SPARC: "-cc1" "-triple" "sparc--netbsd"
+// SPARC: "-cc1" "-triple" "sparc-unknown-netbsd"
// RUN: %clang -target sparcv9--netbsd -m64 %s -### 2>&1 | FileCheck -check-prefix=SPARCV9 %s
// RUN: %clang -target sparc--netbsd -m64 %s -### 2>&1 | FileCheck -check-prefix=SPARCV9 %s
-// SPARCV9: "-cc1" "-triple" "sparcv9--netbsd"
+// SPARCV9: "-cc1" "-triple" "sparcv9-unknown-netbsd"
// RUN: %clang -target sparc64--netbsd -m64 %s -### 2>&1 | FileCheck -check-prefix=SPARC64 %s
-// SPARC64: "-cc1" "-triple" "sparc64--netbsd"
+// SPARC64: "-cc1" "-triple" "sparc64-unknown-netbsd"
// RUN: %clang -target sparcel -o foo %s -### 2>&1 | FileCheck -check-prefix=SPARCEL %s
// SPARCEL: gcc{{(\.exe)?}}" "-EL" "-o" "foo"
// RUN: %clang -target mips64--netbsd -m32 %s -### 2>&1 | FileCheck -check-prefix=MIPS %s
// RUN: %clang -target mips--netbsd -m32 %s -### 2>&1 | FileCheck -check-prefix=MIPS %s
-// MIPS: "-cc1" "-triple" "mips--netbsd"
+// MIPS: "-cc1" "-triple" "mips-unknown-netbsd"
// RUN: %clang -target mips64--netbsd -m64 %s -### 2>&1 | FileCheck -check-prefix=MIPS64 %s
// RUN: %clang -target mips--netbsd -m64 %s -### 2>&1 | FileCheck -check-prefix=MIPS64 %s
-// MIPS64: "-cc1" "-triple" "mips64--netbsd"
+// MIPS64: "-cc1" "-triple" "mips64-unknown-netbsd"
diff --git a/test/Driver/cf-runtime-abi.c b/test/Driver/cf-runtime-abi.c
new file mode 100644
index 000000000000..1d4b9702ef5e
--- /dev/null
+++ b/test/Driver/cf-runtime-abi.c
@@ -0,0 +1,22 @@
+// RUN: %clang -### -target aarch64-unknown-windows-msvc -c %s 2>&1 | FileCheck -check-prefix CHECK-UNSPECIFIED %s
+// RUN: %clang -### -target thumbv7-unknown-linux-android -c %s 2>&1 | FileCheck -check-prefix CHECK-UNSPECIFIED %s
+// RUN: %clang -### -target x86_64-apple-macosx -c %s 2>&1 | FileCheck -check-prefix CHECK-UNSPECIFIED %s
+
+// RUN: %clang -### -target aarch64-unknown-windows-msvc -fcf-runtime-abi=objc -c %s 2>&1 | FileCheck -check-prefix CHECK-OBJC %s
+// RUN: %clang -### -target thumbv7-unknown-linux-android -fcf-runtime-abi=swift-5.0 -c %s 2>&1 | FileCheck -check-prefix CHECK-SWIFT-5_0 %s
+// RUN: %clang -### -target i386-unknown-freebsd -fcf-runtime-abi=swift-4.2 -c %s 2>&1 | FileCheck -check-prefix CHECK-SWIFT-4_2 %s
+// RUN: %clang -### -target s390x-unknown-linux-gnu -fcf-runtime-abi=swift-4.1 -c %s 2>&1 | FileCheck -check-prefix CHECK-SWIFT-4_1 %s
+// RUN: %clang -### -target x86_64-apple-macosx -fcf-runtime-abi=swift -c %s 2>&1 | FileCheck -check-prefix CHECK-SWIFT %s
+
+// RUN: %clang -### -target arm7k-apple-watchos -fcf-runtime-abi=invalid -c %s 2>&1 | FileCheck -check-prefix CHECK-INVALID %s
+
+// CHECK-UNSPECIFIED-NOT: "-fcf-runtime-abi=
+
+// CHECK-OBJC: "-fcf-runtime-abi=objc"
+// CHECK-SWIFT-5_0: "-fcf-runtime-abi=swift-5.0"
+// CHECK-SWIFT-4_2: "-fcf-runtime-abi=swift-4.2"
+// CHECK-SWIFT-4_1: "-fcf-runtime-abi=swift-4.1"
+// CHECK-SWIFT: "-fcf-runtime-abi=swift"
+
+// CHECK-INVALID: error: invalid CoreFoundation Runtime ABI 'invalid'; must be one of 'objc', 'standalone', 'swift', 'swift-5.0', 'swift-4.2', 'swift-4.1'
+
diff --git a/test/Driver/cl-idl.cpp b/test/Driver/cl-idl.cpp
new file mode 100644
index 000000000000..7843ab31334a
--- /dev/null
+++ b/test/Driver/cl-idl.cpp
@@ -0,0 +1,18 @@
+// Note: %s must be preceded by --, otherwise it may be interpreted as a
+// command-line option, e.g. on Mac where %s is commonly under /Users.
+
+// Test that 'clang-cl /E' treats inputs as C++ if the extension is
+// unrecognized. midl relies on this. See PR40140.
+
+// Use a plain .cpp extension first.
+// RUN: %clang_cl /E -- %s | FileCheck %s
+
+// Copy to use .idl as the extension.
+// RUN: cp %s %t.idl
+// RUN: %clang_cl /E -- %t.idl | FileCheck %s
+
+#ifdef __cplusplus
+struct IsCPlusPlus {};
+#endif
+
+// CHECK: struct IsCPlusPlus {};
diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c
index 9aa6ced34994..f5171d5c040c 100644
--- a/test/Driver/cl-options.c
+++ b/test/Driver/cl-options.c
@@ -101,7 +101,7 @@
// Gy_-NOT: -ffunction-sections
// RUN: %clang_cl /Gs -### -- %s 2>&1 | FileCheck -check-prefix=Gs %s
-// Gs: "-mstack-probe-size=0"
+// Gs: "-mstack-probe-size=4096"
// RUN: %clang_cl /Gs0 -### -- %s 2>&1 | FileCheck -check-prefix=Gs0 %s
// Gs0: "-mstack-probe-size=0"
// RUN: %clang_cl /Gs4096 -### -- %s 2>&1 | FileCheck -check-prefix=Gs4096 %s
@@ -420,8 +420,6 @@
// RUN: /Gr \
// RUN: /GS \
// RUN: /GT \
-// RUN: /guard:cf \
-// RUN: /guard:cf- \
// RUN: /GX \
// RUN: /Gv \
// RUN: /Gz \
@@ -429,6 +427,7 @@
// RUN: /H \
// RUN: /homeparams \
// RUN: /hotpatch \
+// RUN: /JMC \
// RUN: /kernel \
// RUN: /LN \
// RUN: /MP \
@@ -491,6 +490,13 @@
// RUN: %clang_cl /Zc:threadSafeInit /c -### -- %s 2>&1 | FileCheck -check-prefix=ThreadSafeStatics %s
// ThreadSafeStatics-NOT: "-fno-threadsafe-statics"
+// RUN: %clang_cl /Zc:dllexportInlines- /c -### -- %s 2>&1 | FileCheck -check-prefix=NoDllExportInlines %s
+// NoDllExportInlines: "-fno-dllexport-inlines"
+// RUN: %clang_cl /Zc:dllexportInlines /c -### -- %s 2>&1 | FileCheck -check-prefix=DllExportInlines %s
+// DllExportInlines-NOT: "-fno-dllexport-inlines"
+// RUN: %clang_cl /fallback /Zc:dllexportInlines- /c -### -- %s 2>&1 | FileCheck -check-prefix=DllExportInlinesFallback %s
+// DllExportInlinesFallback: error: option '/Zc:dllexportInlines-' is ABI-changing and not compatible with '/fallback'
+
// RUN: %clang_cl /Zi /c -### -- %s 2>&1 | FileCheck -check-prefix=Zi %s
// Zi: "-gcodeview"
// Zi: "-debug-info-kind=limited"
@@ -561,11 +567,25 @@
// RUN: %clang_cl -### -Fe%t.exe -entry:main -flto -- %s 2>&1 | FileCheck -check-prefix=LTO-WITHOUT-LLD %s
// LTO-WITHOUT-LLD: LTO requires -fuse-ld=lld
+// RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=NOCFGUARD %s
+// RUN: %clang_cl /guard:cf- -### -- %s 2>&1 | FileCheck -check-prefix=NOCFGUARD %s
+// NOCFGUARD-NOT: -cfguard
+
+// RUN: %clang_cl /guard:cf -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARD %s
+// RUN: %clang_cl /guard:cf,nochecks -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARD %s
+// RUN: %clang_cl /guard:nochecks -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARD %s
+// CFGUARD: -cfguard
+
+// RUN: %clang_cl /guard:foo -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARDINVALID %s
+// CFGUARDINVALID: invalid value 'foo' in '/guard:'
+
// Accept "core" clang options.
// (/Zs is for syntax-only, -Werror makes it fail hard on unknown options)
// RUN: %clang_cl \
// RUN: --driver-mode=cl \
// RUN: -fblocks \
+// RUN: -fcrash-diagnostics-dir=/foo \
+// RUN: -fno-crash-diagnostics \
// RUN: -fno-blocks \
// RUN: -fbuiltin \
// RUN: -fno-builtin \
@@ -597,8 +617,23 @@
// RUN: -flto \
// RUN: -fmerge-all-constants \
// RUN: -no-canonical-prefixes \
+// RUN: -march=skylake \
// RUN: --version \
// RUN: -Werror /Zs -- %s 2>&1
+// Accept clang options under the /clang: flag.
+// The first test case ensures that the SLP vectorizer is on by default and that
+// it's being turned off by the /clang:-fno-slp-vectorize flag.
+
+// RUN: %clang_cl -O2 -### -- %s 2>&1 | FileCheck -check-prefix=NOCLANG %s
+// NOCLANG: "--dependent-lib=libcmt"
+// NOCLANG-SAME: "-vectorize-slp"
+// NOCLANG-NOT: "--dependent-lib=msvcrt"
+
+// RUN: %clang_cl -O2 -MD /clang:-fno-slp-vectorize /clang:-MD /clang:-MF /clang:my_dependency_file.dep -### -- %s 2>&1 | FileCheck -check-prefix=CLANG %s
+// CLANG: "--dependent-lib=msvcrt"
+// CLANG-SAME: "-dependency-file" "my_dependency_file.dep"
+// CLANG-NOT: "--dependent-lib=libcmt"
+// CLANG-NOT: "-vectorize-slp"
void f() { }
diff --git a/test/Driver/cl-pch.cpp b/test/Driver/cl-pch.cpp
index 8521d3576a7b..0d18171d94e6 100644
--- a/test/Driver/cl-pch.cpp
+++ b/test/Driver/cl-pch.cpp
@@ -264,6 +264,71 @@
// CHECK-YU-SLASH: -include
// CHECK-YU-SLASH: ".{{[/\\]+}}pchfile.h"
+// /Yc without an argument creates a PCH from the code before #pragma hdrstop.
+// /Yu without an argument uses a PCH and starts compiling after the
+// #pragma hdrstop.
+// RUN: %clang_cl -Werror /Yc /Fpycnoarg.pch /c -### -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-YC-NOARG %s
+// 1. Create .pch file
+// CHECK-YC-NOARG: cc1
+// CHECK-YC-NOARG: -emit-pch
+// CHECK-YC-NOARG: -pch-through-hdrstop-create
+// CHECK-YC-NOARG: -o
+// CHECK-YC-NOARG: ycnoarg.pch
+// CHECK-YC-NOARG: -x
+// CHECK-YC-NOARG: "c++-header"
+// CHECK-YC-NOARG: cl-pch.cpp
+// 2. Use .pch file: Includes ycnoarg.pch
+// CHECK-YC-NOARG: cc1
+// CHECK-YC-NOARG: -emit-obj
+// CHECK-YC-NOARG: -include-pch
+// CHECK-YC-NOARG: ycnoarg.pch
+// CHECK-YC-NOARG: -pch-through-hdrstop-create
+// CHECK-YC-NOARG: -o
+// CHECK-YC-NOARG: cl-pch.obj
+// CHECK-YC-NOARG: -x
+// CHECK-YC-NOARG: "c++"
+// CHECK-YC-NOARG: cl-pch.cpp
+
+// RUN: %clang_cl -Werror /Yu /Fpycnoarg.pch /c -### -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-YU-NOARG %s
+// Use .pch file, but don't build it.
+// CHECK-YU-NOARG-NOT: -emit-pch
+// CHECK-YU-NOARG: cc1
+// CHECK-YU-NOARG: -emit-obj
+// CHECK-YU-NOARG: -include-pch
+// CHECK-YU-NOARG: ycnoarg.pch
+// CHECK-YU-NOARG: -pch-through-hdrstop-use
+// CHECK-YU-NOARG: -o
+// CHECK-YU-NOARG: cl-pch.obj
+// CHECK-YU-NOARG: -x
+// CHECK-YU-NOARG: "c++"
+// CHECK-YU-NOARG: cl-pch.cpp
+
+// /Yc with no argument and no /FP
+// RUN: %clang_cl -Werror /Yc /c -### -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-YC-NOARG-NOFP %s
+// 1. Create .pch file
+// CHECK-YC-NOARG-NOFP: cc1
+// CHECK-YC-NOARG-NOFP: -emit-pch
+// CHECK-YC-NOARG-NOFP: -pch-through-hdrstop-create
+// CHECK-YC-NOARG-NOFP: -o
+// CHECK-YC-NOARG-NOFP: cl-pch.pch
+// CHECK-YC-NOARG-NOFP: -x
+// CHECK-YC-NOARG-NOFP: "c++-header"
+// CHECK-YC-NOARG-NOFP: cl-pch.cpp
+// 2. Use .pch file: Includes cl-pch.pch
+// CHECK-YC-NOARG-NOFP: cc1
+// CHECK-YC-NOARG-NOFP: -emit-obj
+// CHECK-YC-NOARG-NOFP: -include-pch
+// CHECK-YC-NOARG-NOFP: cl-pch.pch
+// CHECK-YC-NOARG-NOFP: -pch-through-hdrstop-create
+// CHECK-YC-NOARG-NOFP: -o
+// CHECK-YC-NOARG-NOFP: cl-pch.obj
+// CHECK-YC-NOARG-NOFP: -x
+// CHECK-YC-NOARG-NOFP: "c++"
+// CHECK-YC-NOARG-NOFP: cl-pch.cpp
+
// cl.exe warns on multiple /Yc, /Yu, /Fp arguments, but clang-cl silently just
// uses the last one. This is true for e.g. /Fo too, so not warning on this
// is self-consistent with clang-cl's flag handling.
@@ -345,3 +410,24 @@
// CHECK-NoSourceTP: pchfile.pch
// CHECK-NoSourceTP: -x
// CHECK-NoSourceTP: "c++"
+
+// If only preprocessing, PCH options are ignored.
+// RUN: %clang_cl /P /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-YC-P %s
+// CHECK-YC-P-NOT: -emit-pch
+// CHECK-YC-P-NOT: -include-pch
+
+// RUN: %clang_cl /E /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-YC-E %s
+// CHECK-YC-E-NOT: -emit-pch
+// CHECK-YC-E-NOT: -include-pch
+
+// RUN: %clang_cl /P /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-YU-P %s
+// CHECK-YU-P-NOT: -emit-pch
+// CHECK-YU-P-NOT: -include-pch
+
+// RUN: %clang_cl /E /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-YU-E %s
+// CHECK-YU-E-NOT: -emit-pch
+// CHECK-YU-E-NOT: -include-pch
diff --git a/test/Driver/cl-showfilenames.c b/test/Driver/cl-showfilenames.c
new file mode 100644
index 000000000000..b2932f1a01ac
--- /dev/null
+++ b/test/Driver/cl-showfilenames.c
@@ -0,0 +1,23 @@
+// We have to run the compilation step to see the output, so we must be able to
+// target Windows.
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cl --target=i686-pc-win32 /c /Fo%T/ /showFilenames -- %s 2>&1 | FileCheck -check-prefix=show %s
+// RUN: %clang_cl --target=i686-pc-win32 /c /Fo%T/ /showFilenames -- %s %S/Inputs/wildcard*.c 2>&1 | FileCheck -check-prefix=multiple %s
+
+// RUN: %clang_cl --target=i686-pc-win32 /c /Fo%T/ -- %s 2>&1 | FileCheck -check-prefix=noshow %s
+// RUN: %clang_cl --target=i686-pc-win32 /c /Fo%T/ /showFilenames /showFilenames- -- %s 2>&1 | FileCheck -check-prefix=noshow %s
+
+
+#pragma message "Hello"
+
+// show: cl-showfilenames.c
+// show-NEXT: warning: Hello
+
+// multiple: cl-showfilenames.c
+// multiple-NEXT: warning: Hello
+// multiple: wildcard1.c
+// multiple-NEXT: wildcard2.c
+
+// noshow: warning: Hello
+// noshow-NOT: cl-showfilenames.c
diff --git a/test/Driver/cl-zc.cpp b/test/Driver/cl-zc.cpp
index 4414eb6ebba2..cf7734875e1f 100644
--- a/test/Driver/cl-zc.cpp
+++ b/test/Driver/cl-zc.cpp
@@ -18,6 +18,12 @@
// RUN: %clang_cl /c -### /Zc:sizedDealloc- -- %s 2>&1 | FileCheck -check-prefix=SIZED-DEALLOC-OFF %s
// SIZED-DEALLOC-OFF-NOT: "-fsized-deallocation"
+// RUN: %clang_cl /c /std:c++17 -### /Zc:alignedNew -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-ON %s
+// ALIGNED-NEW-ON: "-faligned-allocation"
+
+// RUN: %clang_cl /c /std:c++17 -### /Zc:alignedNew- -- %s 2>&1 | FileCheck -check-prefix=ALIGNED-NEW-OFF %s
+// ALIGNED-NEW-OFF-NOT: "-faligned-allocation"
+
// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=STRICTSTRINGS-DEFAULT %s
// STRICTSTRINGS-DEFAULT-NOT: -Werror=c++11-compat-deprecated-writable-strings
// RUN: %clang_cl /c -### /Zc:strictStrings -- %s 2>&1 | FileCheck -check-prefix=STRICTSTRINGS-ON %s
diff --git a/test/Driver/clang-offload-bundler.c b/test/Driver/clang-offload-bundler.c
index adf13f59d46f..15092dd12778 100644
--- a/test/Driver/clang-offload-bundler.c
+++ b/test/Driver/clang-offload-bundler.c
@@ -115,7 +115,7 @@
// CK-TEXTI: // __CLANG_OFFLOAD_BUNDLE____END__ openmp-x86_64-pc-linux-gnu
// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____START__ host-powerpc64le-ibm-linux-gnu
-// CK-TEXTLL: @A = global i32 0
+// CK-TEXTLL: @A = dso_local global i32 0
// CK-TEXTLL: define {{.*}}@test_func()
// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____END__ host-powerpc64le-ibm-linux-gnu
// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____START__ openmp-powerpc64le-ibm-linux-gnu
diff --git a/test/Driver/clang-translation.c b/test/Driver/clang-translation.c
index a09a60c9f33e..4360ea44aeb2 100644
--- a/test/Driver/clang-translation.c
+++ b/test/Driver/clang-translation.c
@@ -33,6 +33,11 @@
// AVX2: "-target-cpu"
// AVX2: "core-avx2"
+// RUN: %clang -target x86_64h-apple-darwin -march=skx -### %s -o /dev/null 2>&1 | \
+// RUN: FileCheck -check-prefix=X8664HSKX %s
+// X8664HSKX: "-target-cpu"
+// X8664HSKX: "skx"
+
// RUN: %clang -target i386-apple-macosx10.12 -### -S %s -o %t.s 2>&1 | \
// RUN: FileCheck -check-prefix=PENRYN %s
// RUN: %clang -target x86_64-apple-macosx10.12 -### -S %s -o %t.s 2>&1 | \
@@ -266,7 +271,7 @@
// AMD64-MINGW: clang
// AMD64-MINGW: "-cc1"
// AMD64-MINGW: "-triple"
-// AMD64-MINGW: "amd64--windows-gnu"
+// AMD64-MINGW: "amd64-unknown-windows-gnu"
// AMD64-MINGW: "-munwind-tables"
// RUN: %clang -target i686-linux-android -### -S %s 2>&1 \
@@ -291,6 +296,13 @@
// MIPS: "-target-cpu" "mips32r2"
// MIPS: "-mfloat-abi" "hard"
+// RUN: %clang -target mipsisa32r6-linux-gnu -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPSR6 %s
+// MIPSR6: clang
+// MIPSR6: "-cc1"
+// MIPSR6: "-target-cpu" "mips32r6"
+// MIPSR6: "-mfloat-abi" "hard"
+
// RUN: %clang -target mipsel-linux-gnu -### -S %s 2>&1 | \
// RUN: FileCheck -check-prefix=MIPSEL %s
// MIPSEL: clang
@@ -298,6 +310,13 @@
// MIPSEL: "-target-cpu" "mips32r2"
// MIPSEL: "-mfloat-abi" "hard"
+// RUN: %clang -target mipsisa32r6el-linux-gnu -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPSR6EL %s
+// MIPSR6EL: clang
+// MIPSR6EL: "-cc1"
+// MIPSR6EL: "-target-cpu" "mips32r6"
+// MIPSR6EL: "-mfloat-abi" "hard"
+
// RUN: %clang -target mipsel-linux-android -### -S %s 2>&1 | \
// RUN: FileCheck -check-prefix=MIPSEL-ANDROID %s
// MIPSEL-ANDROID: clang
@@ -323,6 +342,13 @@
// MIPS64: "-target-cpu" "mips64r2"
// MIPS64: "-mfloat-abi" "hard"
+// RUN: %clang -target mipsisa64r6-linux-gnu -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPS64R6 %s
+// MIPS64R6: clang
+// MIPS64R6: "-cc1"
+// MIPS64R6: "-target-cpu" "mips64r6"
+// MIPS64R6: "-mfloat-abi" "hard"
+
// RUN: %clang -target mips64el-linux-gnu -### -S %s 2>&1 | \
// RUN: FileCheck -check-prefix=MIPS64EL %s
// MIPS64EL: clang
@@ -330,6 +356,77 @@
// MIPS64EL: "-target-cpu" "mips64r2"
// MIPS64EL: "-mfloat-abi" "hard"
+// RUN: %clang -target mipsisa64r6el-linux-gnu -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPS64R6EL %s
+// MIPS64R6EL: clang
+// MIPS64R6EL: "-cc1"
+// MIPS64R6EL: "-target-cpu" "mips64r6"
+// MIPS64R6EL: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mips64-linux-gnuabi64 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPS64-GNUABI64 %s
+// MIPS64-GNUABI64: clang
+// MIPS64-GNUABI64: "-cc1"
+// MIPS64-GNUABI64: "-target-cpu" "mips64r2"
+// MIPS64-GNUABI64: "-target-abi" "n64"
+// MIPS64-GNUABI64: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mipsisa64r6-linux-gnuabi64 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPS64R6-GNUABI64 %s
+// MIPS64R6-GNUABI64: clang
+// MIPS64R6-GNUABI64: "-cc1"
+// MIPS64R6-GNUABI64: "-target-cpu" "mips64r6"
+// MIPS64R6-GNUABI64: "-target-abi" "n64"
+// MIPS64R6-GNUABI64: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mips64el-linux-gnuabi64 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPS64EL-GNUABI64 %s
+// MIPS64EL-GNUABI64: clang
+// MIPS64EL-GNUABI64: "-cc1"
+// MIPS64EL-GNUABI64: "-target-cpu" "mips64r2"
+// MIPS64EL-GNUABI64: "-target-abi" "n64"
+// MIPS64EL-GNUABI64: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mipsisa64r6el-linux-gnuabi64 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPS64R6EL-GNUABI64 %s
+// MIPS64R6EL-GNUABI64: clang
+// MIPS64R6EL-GNUABI64: "-cc1"
+// MIPS64R6EL-GNUABI64: "-target-cpu" "mips64r6"
+// MIPS64R6EL-GNUABI64: "-target-abi" "n64"
+// MIPS64R6EL-GNUABI64: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mips64-linux-gnuabin32 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPSN32 %s
+// MIPSN32: clang
+// MIPSN32: "-cc1"
+// MIPSN32: "-target-cpu" "mips64r2"
+// MIPSN32: "-target-abi" "n32"
+// MIPSN32: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mipsisa64r6-linux-gnuabin32 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPSN32R6 %s
+// MIPSN32R6: clang
+// MIPSN32R6: "-cc1"
+// MIPSN32R6: "-target-cpu" "mips64r6"
+// MIPSN32R6: "-target-abi" "n32"
+// MIPSN32R6: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mips64el-linux-gnuabin32 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPSN32EL %s
+// MIPSN32EL: clang
+// MIPSN32EL: "-cc1"
+// MIPSN32EL: "-target-cpu" "mips64r2"
+// MIPSN32EL: "-target-abi" "n32"
+// MIPSN32EL: "-mfloat-abi" "hard"
+
+// RUN: %clang -target mipsisa64r6el-linux-gnuabin32 -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=MIPSN32R6EL %s
+// MIPSN32R6EL: clang
+// MIPSN32R6EL: "-cc1"
+// MIPSN32R6EL: "-target-cpu" "mips64r6"
+// MIPSN32R6EL: "-target-abi" "n32"
+// MIPSN32R6EL: "-mfloat-abi" "hard"
+
// RUN: %clang -target mips64el-linux-android -### -S %s 2>&1 | \
// RUN: FileCheck -check-prefix=MIPS64EL-ANDROID %s
// MIPS64EL-ANDROID: clang
diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c
index 9208d6b71bb5..866b368beacc 100644
--- a/test/Driver/clang_f_opts.c
+++ b/test/Driver/clang_f_opts.c
@@ -85,6 +85,10 @@
// CHECK-PROFILE-DIR-UNUSED-NOT: "-coverage-data-file" "abc
// CHECK-PROFILE-DIR-NEITHER-NOT: argument unused
+// RUN: %clang -### -fprofile-arcs -ftest-coverage %s 2>&1 | FileCheck -check-prefix=CHECK-u %s
+// RUN: %clang -### --coverage %s 2>&1 | FileCheck -check-prefix=CHECK-u %s
+// CHECK-u-NOT: "-u{{.*}}"
+
// RUN: %clang -### -S -fprofile-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-LLVM %s
// RUN: %clang -### -S -fprofile-instr-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s
// RUN: %clang -### -S -fprofile-generate=/some/dir %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-DIR %s
@@ -116,6 +120,7 @@
// RUN: %clang -### -S -fcoverage-mapping %s 2>&1 | FileCheck -check-prefix=CHECK-COVERAGE-AND-GEN %s
// RUN: %clang -### -S -fcoverage-mapping -fno-coverage-mapping %s 2>&1 | FileCheck -check-prefix=CHECK-DISABLE-COVERAGE %s
// RUN: %clang -### -S -fprofile-instr-generate -fcoverage-mapping -fno-coverage-mapping %s 2>&1 | FileCheck -check-prefix=CHECK-DISABLE-COVERAGE %s
+// RUN: %clang -### -S -fprofile-remapping-file foo/bar.txt %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-REMAP %s
// CHECK-PROFILE-GENERATE: "-fprofile-instrument=clang"
// CHECK-PROFILE-GENERATE-LLVM: "-fprofile-instrument=llvm"
// CHECK-PROFILE-GENERATE-DIR: "-fprofile-instrument-path=/some/dir{{/|\\\\}}{{.*}}"
@@ -126,6 +131,7 @@
// CHECK-DISABLE-USE-NOT: "-fprofile-instr-use"
// CHECK-COVERAGE-AND-GEN: '-fcoverage-mapping' only allowed with '-fprofile-instr-generate'
// CHECK-DISABLE-COVERAGE-NOT: "-fcoverage-mapping"
+// CHECK-PROFILE-REMAP: "-fprofile-remapping-file=foo/bar.txt"
// RUN: %clang -### -S -fprofile-use %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE %s
// RUN: %clang -### -S -fprofile-instr-use %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE %s
@@ -531,3 +537,32 @@
// RUN: %clang -### -S -fno-delete-null-pointer-checks -fdelete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NULL-POINTER-CHECKS %s
// CHECK-NO-NULL-POINTER-CHECKS: "-fno-delete-null-pointer-checks"
// CHECK-NULL-POINTER-CHECKS-NOT: "-fno-delete-null-pointer-checks"
+
+// RUN: %clang -### -S -fomit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-OMIT-FP-PG %s
+// RUN: %clang -### -S -fomit-frame-pointer -fno-omit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-MIX-NO-OMIT-FP-PG %s
+// CHECK-NO-MIX-OMIT-FP-PG: '-fomit-frame-pointer' not allowed with '-pg'
+// CHECK-MIX-NO-OMIT-FP-PG-NOT: '-fomit-frame-pointer' not allowed with '-pg'
+
+// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
+// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
+// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
+// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-gcc-switches -fno-record-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
+// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
+// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
+// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
+// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line -fno-record-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
+// Test with a couple examples of non-ELF object file formats
+// RUN: %clang -### -S -target x86_64-unknown-macosx -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
+// RUN: %clang -### -S -target x86_64-unknown-windows -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
+// CHECK-RECORD-GCC-SWITCHES: "-record-command-line"
+// CHECK-NO-RECORD-GCC-SWITCHES-NOT: "-record-command-line"
+// CHECK-RECORD-GCC-SWITCHES-ERROR: error: unsupported option '-frecord-command-line' for target
+
+// RUN: %clang -### -S -ftrivial-auto-var-init=uninitialized %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-UNINIT %s
+// RUN: %clang -### -S -ftrivial-auto-var-init=pattern %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-PATTERN %s
+// RUN: %clang -### -S -ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-ZERO-GOOD %s
+// RUN: %clang -### -S -ftrivial-auto-var-init=zero %s 2>&1 | FileCheck -check-prefix=CHECK-TRIVIAL-ZERO-BAD %s
+// CHECK-TRIVIAL-UNINIT-NOT: hasn't been enabled
+// CHECK-TRIVIAL-PATTERN-NOT: hasn't been enabled
+// CHECK-TRIVIAL-ZERO-GOOD-NOT: hasn't been enabled
+// CHECK-TRIVIAL-ZERO-BAD: hasn't been enabled
diff --git a/test/Driver/code-model.c b/test/Driver/code-model.c
index 001ca606cde7..dcb54e972a50 100644
--- a/test/Driver/code-model.c
+++ b/test/Driver/code-model.c
@@ -1,9 +1,11 @@
+// RUN: %clang -### -c -mcmodel=tiny %s 2>&1 | FileCheck -check-prefix CHECK-TINY %s
// RUN: %clang -### -c -mcmodel=small %s 2>&1 | FileCheck -check-prefix CHECK-SMALL %s
// RUN: %clang -### -S -mcmodel=kernel %s 2>&1 | FileCheck -check-prefix CHECK-KERNEL %s
// RUN: %clang -### -c -mcmodel=medium %s 2>&1 | FileCheck -check-prefix CHECK-MEDIUM %s
// RUN: %clang -### -S -mcmodel=large %s 2>&1 | FileCheck -check-prefix CHECK-LARGE %s
// RUN: not %clang -c -mcmodel=lager %s 2>&1 | FileCheck -check-prefix CHECK-INVALID %s
+// CHECK-TINY: "-mcode-model" "tiny"
// CHECK-SMALL: "-mcode-model" "small"
// CHECK-KERNEL: "-mcode-model" "kernel"
// CHECK-MEDIUM: "-mcode-model" "medium"
diff --git a/test/Driver/coverage_no_integrated_as.c b/test/Driver/coverage_no_integrated_as.c
index 9acab9bbd172..d7689e591ff0 100644
--- a/test/Driver/coverage_no_integrated_as.c
+++ b/test/Driver/coverage_no_integrated_as.c
@@ -1,5 +1,5 @@
// REQUIRES: clang-driver
-// XFAIL: win32,win64
+// XFAIL: windows-msvc
// RUN: %clang -### -S -fprofile-arcs %s 2>&1 | FileCheck -check-prefix=CHECK-GCNO-DEFAULT-LOCATION %s
// RUN: %clang -### -S -fprofile-arcs -no-integrated-as %s 2>&1 | FileCheck -check-prefix=CHECK-GCNO-DEFAULT-LOCATION %s
diff --git a/test/Driver/crash-report-null.test b/test/Driver/crash-report-null.test
index 477dd28df3ed..22c211ee987d 100644
--- a/test/Driver/crash-report-null.test
+++ b/test/Driver/crash-report-null.test
@@ -1,7 +1,7 @@
// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH=1 %clang -fsyntax-only -x c /dev/null -lstdc++ 2>&1 | FileCheck %s
// FIXME: Investigating. "fatal error: file 'nul' modified since it was first processed"
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK-NEXT: note: diagnostic msg: {{.*}}null-{{.*}}.c
diff --git a/test/Driver/cuda-detect.cu b/test/Driver/cuda-detect.cu
index f086ba4c42e3..e5dfe36571a7 100644
--- a/test/Driver/cuda-detect.cu
+++ b/test/Driver/cuda-detect.cu
@@ -14,9 +14,9 @@
// RUN: %clang -v --target=i386-unknown-linux \
-// RUN: --sysroot=%S/Inputs/CUDA 2>&1 | FileCheck %s
+// RUN: --sysroot=%S/Inputs/CUDA --cuda-path-ignore-env 2>&1 | FileCheck %s
// RUN: %clang -v --target=i386-apple-macosx \
-// RUN: --sysroot=%S/Inputs/CUDA 2>&1 | FileCheck %s
+// RUN: --sysroot=%S/Inputs/CUDA --cuda-path-ignore-env 2>&1 | FileCheck %s
// RUN: %clang -v --target=i386-unknown-linux \
// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 | FileCheck %s
@@ -145,8 +145,8 @@
// COMMON: "-triple" "nvptx-nvidia-cuda"
// COMMON-SAME: "-fcuda-is-device"
-// LIBDEVICE-SAME: "-mlink-cuda-bitcode"
-// NOLIBDEVICE-NOT: "-mlink-cuda-bitcode"
+// LIBDEVICE-SAME: "-mlink-builtin-bitcode"
+// NOLIBDEVICE-NOT: "-mlink-builtin-bitcode"
// LIBDEVICE20-SAME: libdevice.compute_20.10.bc
// LIBDEVICE30-SAME: libdevice.compute_30.10.bc
// LIBDEVICE35-SAME: libdevice.compute_35.10.bc
@@ -164,6 +164,6 @@
// COMMON-SAME: "-x" "cuda"
// CHECK-CXXINCLUDE: clang{{.*}} "-cc1" "-triple" "nvptx64-nvidia-cuda"
// CHECK-CXXINCLUDE-SAME: {{.*}}"-internal-isystem" "{{.+}}/include/c++/4.8"
-// CHECK-CXXINCLUDE: clang{{.*}} "-cc1" "-triple" "x86_64--linux-gnu"
+// CHECK-CXXINCLUDE: clang{{.*}} "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// CHECK-CXXINCLUDE-SAME: {{.*}}"-internal-isystem" "{{.+}}/include/c++/4.8"
// CHECK-CXXINCLUDE: ld{{.*}}"
diff --git a/test/Driver/cuda-dwarf-2.cu b/test/Driver/cuda-dwarf-2.cu
index 7956e6ddbe23..bcfb2444bc51 100644
--- a/test/Driver/cuda-dwarf-2.cu
+++ b/test/Driver/cuda-dwarf-2.cu
@@ -1,25 +1,28 @@
// REQUIRES: clang-driver
//
-// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O0 --no-cuda-noopt-device-debug 2>&1 | \
-// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O1 --no-cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix DEBUG_DIRECTIVES
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O3 2>&1 | \
-// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: FileCheck %s -check-prefix DEBUG_DIRECTIVES
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O3 --no-cuda-noopt-device-debug 2>&1 | \
-// RUN: FileCheck %s -check-prefix NO_DEBUG
+// RUN: FileCheck %s -check-prefix DEBUG_DIRECTIVES
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g0 2>&1 | \
// RUN: FileCheck %s -check-prefix NO_DEBUG
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb0 -O3 --cuda-noopt-device-debug 2>&1 | \
// RUN: FileCheck %s -check-prefix NO_DEBUG
-// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb1 2>&1 | \
-// RUN: FileCheck %s -check-prefix NO_DEBUG -check-prefix LINE_TABLE
-// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -gline-tables-only -O2 --cuda-noopt-device-debug 2>&1 | \
-// RUN: FileCheck %s -check-prefix NO_DEBUG -check-prefix LINE_TABLE
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -gline-directives-only -O2 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix DEBUG_DIRECTIVES
// NO_DEBUG-NOT: warning: debug
-// LINE_TABLE-NOT: warning: debug
+// DEBUG_DIRECTIVES-NOT: warning: debug
+// NO_DEBUG: "-fcuda-is-device"
+// NO_DEBUG-NOT: "-debug-info-kind=
// NO_DEBUG: ptxas
// NO_DEBUG-NOT: "-g"
-// LINE_TABLE: "-lineinfo"
+// DEBUG_DIRECTIVES: "-fcuda-is-device"
+// DEBUG_DIRECTIVES-SAME: "-debug-info-kind=line-directives-only"
+// DEBUG_DIRECTIVES: ptxas
+// DEBUG_DIRECTIVES-SAME: "-lineinfo"
// NO_DEBUG: fatbinary
// NO_DEBUG-NOT: "-g"
@@ -27,6 +30,8 @@
// RUN: FileCheck %s -check-prefix HAS_DEBUG
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O0 --cuda-noopt-device-debug 2>&1 | \
// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O0 --no-cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g -O3 --cuda-noopt-device-debug 2>&1 | \
// RUN: FileCheck %s -check-prefix HAS_DEBUG
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -g2 2>&1 | \
@@ -37,9 +42,14 @@
// RUN: FileCheck %s -check-prefix HAS_DEBUG
// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb3 -O3 --cuda-noopt-device-debug 2>&1 | \
// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb1 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -gline-tables-only -O2 --cuda-noopt-device-debug 2>&1 | \
+// RUN: FileCheck %s -check-prefix HAS_DEBUG
// HAS_DEBUG-NOT: warning: debug
// HAS_DEBUG: "-fcuda-is-device"
+// HAS_DEBUG-SAME: "-debug-info-kind={{limited|line-tables-only}}"
// HAS_DEBUG-SAME: "-dwarf-version=2"
// HAS_DEBUG: ptxas
// HAS_DEBUG-SAME: "-g"
diff --git a/test/Driver/cuda-external-tools.cu b/test/Driver/cuda-external-tools.cu
index 367c6997ea87..5da6ffe0262e 100644
--- a/test/Driver/cuda-external-tools.cu
+++ b/test/Driver/cuda-external-tools.cu
@@ -19,7 +19,7 @@
// RUN: %clang -### -target x86_64-linux-gnu -Ofast -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT3 %s
// Generating relocatable device code
-// RUN: %clang -### -target x86_64-linux-gnu -fcuda-rdc -c %s 2>&1 \
+// RUN: %clang -### -target x86_64-linux-gnu -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,RDC %s
// With debugging enabled, ptxas should be run with with no ptxas optimizations.
@@ -46,21 +46,21 @@
// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_35 -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35 %s
// Separate compilation targeting sm_35.
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_35 -fcuda-rdc -c %s 2>&1 \
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_35 -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
// 32-bit compile.
// RUN: %clang -### -target i386-linux-gnu -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20 %s
// 32-bit compile when generating relocatable device code.
-// RUN: %clang -### -target i386-linux-gnu -fcuda-rdc -c %s 2>&1 \
+// RUN: %clang -### -target i386-linux-gnu -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20,RDC %s
// Compile with -fintegrated-as. This should still cause us to invoke ptxas.
// RUN: %clang -### -target x86_64-linux-gnu -fintegrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,OPT0 %s
// Check that we still pass -c when generating relocatable device code.
-// RUN: %clang -### -target x86_64-linux-gnu -fintegrated-as -fcuda-rdc -c %s 2>&1 \
+// RUN: %clang -### -target x86_64-linux-gnu -fintegrated-as -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,RDC %s
// Check -Xcuda-ptxas and -Xcuda-fatbinary
@@ -77,11 +77,11 @@
// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20 %s
// Check relocatable device code generation on MacOS.
-// RUN: %clang -### -target x86_64-apple-macosx -O0 -fcuda-rdc -c %s 2>&1 \
+// RUN: %clang -### -target x86_64-apple-macosx -O0 -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM20,RDC %s
-// RUN: %clang -### -target x86_64-apple-macosx --cuda-gpu-arch=sm_35 -fcuda-rdc -c %s 2>&1 \
+// RUN: %clang -### -target x86_64-apple-macosx --cuda-gpu-arch=sm_35 -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
-// RUN: %clang -### -target i386-apple-macosx -fcuda-rdc -c %s 2>&1 \
+// RUN: %clang -### -target i386-apple-macosx -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM20,RDC %s
// Check that CLANG forwards the -v flag to PTXAS.
@@ -92,12 +92,12 @@
// CHECK: "-cc1"
// ARCH64-SAME: "-triple" "nvptx64-nvidia-cuda"
// ARCH32-SAME: "-triple" "nvptx-nvidia-cuda"
+// RDC-SAME: "-fgpu-rdc"
+// CHECK-NOT: "-fgpu-rdc"
// SM20-SAME: "-target-cpu" "sm_20"
// SM35-SAME: "-target-cpu" "sm_35"
// SM20-SAME: "-o" "[[PTXFILE:[^"]*]]"
// SM35-SAME: "-o" "[[PTXFILE:[^"]*]]"
-// RDC-SAME: "-fcuda-rdc"
-// CHECK-NOT: "-fcuda-rdc"
// Match the call to ptxas (which assembles PTX to SASS).
// CHECK: ptxas
@@ -141,7 +141,7 @@
// ARCH64-SAME: "-triple" "x86_64-
// ARCH32-SAME: "-triple" "i386-
// CHECK-SAME: "-fcuda-include-gpubinary" "[[FATBINARY]]"
-// RDC-SAME: "-fcuda-rdc"
-// CHECK-NOT: "-fcuda-rdc"
+// RDC-SAME: "-fgpu-rdc"
+// CHECK-NOT: "-fgpu-rdc"
// CHK-PTXAS-VERBOSE: ptxas{{.*}}" "-v"
diff --git a/test/Driver/cuda-macosx.cu b/test/Driver/cuda-macosx.cu
index ad0bcf756e31..a4700a3b81d8 100644
--- a/test/Driver/cuda-macosx.cu
+++ b/test/Driver/cuda-macosx.cu
@@ -3,6 +3,6 @@
// REQUIRES: nvptx-registered-target
//
// RUN: %clang -v --target=i386-apple-macosx \
-// RUN: --sysroot=%S/Inputs/CUDA-macosx 2>&1 | FileCheck %s
+// RUN: --sysroot=%S/Inputs/CUDA-macosx --cuda-path-ignore-env 2>&1 | FileCheck %s
// CHECK: Found CUDA installation: {{.*}}/Inputs/CUDA-macosx/usr/local/cuda
diff --git a/test/Driver/cuda-no-pgo-or-coverage.cu b/test/Driver/cuda-no-pgo-or-coverage.cu
index 1bfd8f432593..952838a98d9d 100644
--- a/test/Driver/cuda-no-pgo-or-coverage.cu
+++ b/test/Driver/cuda-no-pgo-or-coverage.cu
@@ -29,6 +29,6 @@
// CHECK-DAG: "-fcuda-is-device"
// CHECK-NOT: "-f{{[^"]*coverage.*}}"
// CHECK-NOT: "-fprofile{{[^"]*}}"
-// CHECK: "-triple" "x86_64--linux-gnu"
+// CHECK: "-triple" "x86_64-unknown-linux-gnu"
// PROF-DAG: "-fprofile{{.*}}"
// GCOV-DAG: "-f{{(coverage|emit-coverage).*}}"
diff --git a/test/Driver/cuda-no-sanitizers.cu b/test/Driver/cuda-no-sanitizers.cu
index a466b42d8c42..0573c483cd03 100644
--- a/test/Driver/cuda-no-sanitizers.cu
+++ b/test/Driver/cuda-no-sanitizers.cu
@@ -9,5 +9,5 @@
// CHECK-NOT: error: unsupported option '-fsanitize=address'
// CHECK-DAG: "-fcuda-is-device"
// CHECK-NOT: "-fsanitize=address"
-// CHECK-DAG: "-triple" "x86_64--linux-gnu"
+// CHECK-DAG: "-triple" "x86_64-unknown-linux-gnu"
// CHECK: "-fsanitize=address"
diff --git a/test/Driver/cuda-no-stack-protector.cu b/test/Driver/cuda-no-stack-protector.cu
index f94cc188fac0..890a6d6b9d8b 100644
--- a/test/Driver/cuda-no-stack-protector.cu
+++ b/test/Driver/cuda-no-stack-protector.cu
@@ -19,5 +19,5 @@
// CHECK-DAG: "-fcuda-is-device"
// CHECK-NOT: "-stack-protector"
// CHECK-NOT: "-stack-protector-buffer-size"
-// CHECK-DAG: "-triple" "x86_64--linux-gnu"
+// CHECK-DAG: "-triple" "x86_64-unknown-linux-gnu"
// CHECK: "-stack-protector"
diff --git a/test/Driver/cuda-options.cu b/test/Driver/cuda-options.cu
index 4ffab317d16a..73190fd5741a 100644
--- a/test/Driver/cuda-options.cu
+++ b/test/Driver/cuda-options.cu
@@ -194,18 +194,18 @@
// Match device-side preprocessor and compiler phases with -save-temps.
// DEVICE-SAVE: "-cc1" "-triple" "nvptx64-nvidia-cuda"
-// DEVICE-SAVE-SAME: "-aux-triple" "x86_64--linux-gnu"
+// DEVICE-SAVE-SAME: "-aux-triple" "x86_64-unknown-linux-gnu"
// DEVICE-SAVE-SAME: "-fcuda-is-device"
// DEVICE-SAVE-SAME: "-x" "cuda"
// DEVICE-SAVE: "-cc1" "-triple" "nvptx64-nvidia-cuda"
-// DEVICE-SAVE-SAME: "-aux-triple" "x86_64--linux-gnu"
+// DEVICE-SAVE-SAME: "-aux-triple" "x86_64-unknown-linux-gnu"
// DEVICE-SAVE-SAME: "-fcuda-is-device"
// DEVICE-SAVE-SAME: "-x" "cuda-cpp-output"
// Match the job that produces PTX assembly.
// DEVICE: "-cc1" "-triple" "nvptx64-nvidia-cuda"
-// DEVICE-NOSAVE-SAME: "-aux-triple" "x86_64--linux-gnu"
+// DEVICE-NOSAVE-SAME: "-aux-triple" "x86_64-unknown-linux-gnu"
// DEVICE-SAME: "-fcuda-is-device"
// DEVICE-SM30-SAME: "-target-cpu" "sm_30"
// DEVICE-SAME: "-o" "[[PTXFILE:[^"]*]]"
@@ -220,7 +220,7 @@
// Match another device-side compilation.
// DEVICE2: "-cc1" "-triple" "nvptx64-nvidia-cuda"
-// DEVICE2-SAME: "-aux-triple" "x86_64--linux-gnu"
+// DEVICE2-SAME: "-aux-triple" "x86_64-unknown-linux-gnu"
// DEVICE2-SAME: "-fcuda-is-device"
// DEVICE2-SM35-SAME: "-target-cpu" "sm_35"
// DEVICE2-SAME: "-o" "[[PTXFILE2:[^"]*]]"
@@ -244,13 +244,13 @@
// INCLUDES-DEVICE2-DAG: "--image=profile=compute_{{[0-9]+}},file=[[PTXFILE2]]"
// Match host-side preprocessor job with -save-temps.
-// HOST-SAVE: "-cc1" "-triple" "x86_64--linux-gnu"
+// HOST-SAVE: "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// HOST-SAVE-SAME: "-aux-triple" "nvptx64-nvidia-cuda"
// HOST-SAVE-NOT: "-fcuda-is-device"
// HOST-SAVE-SAME: "-x" "cuda"
// Match host-side compilation.
-// HOST: "-cc1" "-triple" "x86_64--linux-gnu"
+// HOST: "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// HOST-SAME: "-aux-triple" "nvptx64-nvidia-cuda"
// HOST-NOT: "-fcuda-is-device"
// HOST-SAME: "-o" "[[HOSTOUTPUT:[^"]*]]"
diff --git a/test/Driver/cuda-output-asm.cu b/test/Driver/cuda-output-asm.cu
index 8ca87a5caa5c..ac9435489182 100644
--- a/test/Driver/cuda-output-asm.cu
+++ b/test/Driver/cuda-output-asm.cu
@@ -15,7 +15,7 @@
// RUN: --cuda-gpu-arch=sm_30 --cuda-device-only %s 2>&1 \
// RUN: | FileCheck -check-prefix SM20 -check-prefix SM30 %s
-// HOST-DAG: "-cc1" "-triple" "x86_64--linux-gnu"
+// HOST-DAG: "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// SM20-DAG: "-cc1" "-triple" "nvptx64-nvidia-cuda"
// SM20-same: "-target-cpu" "sm_20"
// SM30-DAG: "-cc1" "-triple" "nvptx64-nvidia-cuda"
diff --git a/test/Driver/cuda-phases.cu b/test/Driver/cuda-phases.cu
index e34ffa802d97..58be50ae2e12 100644
--- a/test/Driver/cuda-phases.cu
+++ b/test/Driver/cuda-phases.cu
@@ -11,12 +11,21 @@
//
// Test single gpu architecture with complete compilation.
//
+// Test CUDA NVPTX phases.
// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
// RUN: --cuda-gpu-arch=sm_30 %s 2>&1 \
// RUN: | FileCheck -check-prefixes=BIN,BIN_NV %s
+//
+// Test HIP AMDGPU -fgpu-rdc phases.
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 -fgpu-rdc %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=BIN,BIN_AMD,BIN_AMD_RDC %s
+//
+// Test HIP AMDGPU -fno-gpu-rdc phases (default).
// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
// RUN: --cuda-gpu-arch=gfx803 %s 2>&1 \
-// RUN: | FileCheck -check-prefixes=BIN,BIN_AMD %s
+// RUN: | FileCheck -check-prefixes=BIN,BIN_AMD,BIN_AMD_NRDC %s
+//
// BIN_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
// BIN_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
// BIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -32,12 +41,17 @@
// BIN_NV-DAG: [[P10:[0-9]+]]: linker, {[[P8]], [[P9]]}, cuda-fatbin, (device-[[T]])
// BIN_NV-DAG: [[P11:[0-9]+]]: offload, "host-[[T]] (powerpc64le-ibm-linux-gnu)" {[[P2]]}, "device-[[T]] ([[TRIPLE]])" {[[P10]]}, ir
// BIN_NV-DAG: [[P12:[0-9]+]]: backend, {[[P11]]}, assembler, (host-[[T]])
-// BIN_AMD-DAG: [[P12:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// BIN_AMD_RDC-DAG: [[P12:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// BIN_AMD_NRDC-DAG: [[P6:[0-9]+]]: linker, {[[P5]]}, image, (device-hip, [[ARCH]])
+// BIN_AMD_NRDC-DAG: [[P7:[0-9]+]]: offload, "device-hip (amdgcn-amd-amdhsa:[[ARCH]])" {[[P6]]}, image
+// BIN_AMD_NRDC-DAG: [[P8:[0-9]+]]: linker, {[[P7]]}, hip-fatbin, (device-hip)
+// BIN_AMD_NRDC-DAG: [[P11:[0-9]+]]: offload, "host-hip (powerpc64le-ibm-linux-gnu)" {[[P2]]}, "device-hip (amdgcn-amd-amdhsa)" {[[P8]]}, ir
+// BIN_AMD_NRDC-DAG: [[P12:[0-9]+]]: backend, {[[P11]]}, assembler, (host-[[T]])
// BIN-DAG: [[P13:[0-9]+]]: assembler, {[[P12]]}, object, (host-[[T]])
// BIN-DAG: [[P14:[0-9]+]]: linker, {[[P13]]}, image, (host-[[T]])
-// BIN_AMD-DAG: [[P15:[0-9]+]]: linker, {[[P5]]}, image, (device-[[T]], [[ARCH]])
-// BIN_AMD-DAG: [[P16:[0-9]+]]: offload, "host-[[T]] (powerpc64le-ibm-linux-gnu)" {[[P14]]},
-// BIN_AMD-DAG-SAME: "device-[[T]] ([[TRIPLE:amdgcn-amd-amdhsa]]:[[ARCH]])" {[[P15]]}, object
+// BIN_AMD_RDC-DAG: [[P15:[0-9]+]]: linker, {[[P5]]}, image, (device-[[T]], [[ARCH]])
+// BIN_AMD_RDC-DAG: [[P16:[0-9]+]]: offload, "host-[[T]] (powerpc64le-ibm-linux-gnu)" {[[P14]]},
+// BIN_AMD_RDC-DAG-SAME: "device-[[T]] ([[TRIPLE:amdgcn-amd-amdhsa]]:[[ARCH]])" {[[P15]]}, object
//
// Test single gpu architecture up to the assemble phase.
@@ -46,7 +60,10 @@
// RUN: --cuda-gpu-arch=sm_30 %s -S 2>&1 \
// RUN: | FileCheck -check-prefixes=ASM,ASM_NV %s
// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 %s -S 2>&1 \
+// RUN: --cuda-gpu-arch=gfx803 -fgpu-rdc %s -S 2>&1 \
+// RUN: | FileCheck -check-prefixes=ASM,ASM_AMD %s
+// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
+// RUN: --cuda-gpu-arch=gfx803 -fcuda-rdc %s -S 2>&1 \
// RUN: | FileCheck -check-prefixes=ASM,ASM_AMD %s
// ASM_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
// ASM_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
@@ -66,7 +83,7 @@
// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s 2>&1 \
// RUN: | FileCheck -check-prefixes=BIN2,BIN2_NV %s
// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s 2>&1 \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 -fgpu-rdc %s 2>&1 \
// RUN: | FileCheck -check-prefixes=BIN2,BIN2_AMD %s
// BIN2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
// BIN2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (host-[[T]])
@@ -105,7 +122,7 @@
// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s -S 2>&1 \
// RUN: | FileCheck -check-prefixes=ASM2,ASM2_NV %s
// RUN: %clang -x hip -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -S 2>&1 \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 -fgpu-rdc %s -S 2>&1 \
// RUN: | FileCheck -check-prefixes=ASM2,ASM2_AMD %s
// ASM2_NV-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH1:sm_30]])
// ASM2_AMD-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:hip]], (device-[[T]], [[ARCH1:gfx803]])
@@ -140,6 +157,7 @@
// HBIN-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
// HBIN-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (host-[[T]])
// HBIN-DAG: [[P5:[0-9]+]]: linker, {[[P4]]}, image, (host-[[T]])
+// HBIN-NOT: device
//
// Test single gpu architecture up to the assemble phase in host-only
// compilation mode.
@@ -155,6 +173,7 @@
// HASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
// HASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
// HASM-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// HASM-NOT: device
//
// Test two gpu architectures with complete compilation in host-only
@@ -173,6 +192,7 @@
// HBIN2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
// HBIN2-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (host-[[T]])
// HBIN2-DAG: [[P5:[0-9]+]]: linker, {[[P4]]}, image, (host-[[T]])
+// HBIN2-NOT: device
//
// Test two gpu architectures up to the assemble phase in host-only
@@ -189,6 +209,7 @@
// HASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
// HASM2-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (host-[[T]])
// HASM2-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (host-[[T]])
+// HASM2-NOT: device
//
// Test single gpu architecture with complete compilation in device-only
@@ -207,7 +228,7 @@
// DBIN_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]])
// DBIN_NV-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (device-[[T]], [[ARCH]])
// DBIN_NV-DAG: [[P5:[0-9]+]]: offload, "device-[[T]] (nvptx64-nvidia-cuda:[[ARCH]])" {[[P4]]}, object
-
+// DBIN-NOT: host
//
// Test single gpu architecture up to the assemble phase in device-only
// compilation mode.
@@ -224,6 +245,7 @@
// DASM-DAG: [[P2:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH]])
// DASM_NV-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]])
// DASM_NV-DAG: [[P4:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE:nvptx64-nvidia-cuda|amdgcn-amd-amdhsa]]:[[ARCH]])" {[[P3]]}, assembler
+// DASM-NOT: host
//
// Test two gpu architectures with complete compilation in device-only
@@ -248,7 +270,7 @@
// DBIN2_NV-DAG: [[P9:[0-9]+]]: backend, {[[P8]]}, assembler, (device-[[T]], [[ARCH2]])
// DBIN2_NV-DAG: [[P10:[0-9]+]]: assembler, {[[P9]]}, object, (device-[[T]], [[ARCH2]])
// DBIN2_NV-DAG: [[P11:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH2]])" {[[P10]]}, object
-
+// DBIN2-NOT: host
//
// Test two gpu architectures up to the assemble phase in device-only
// compilation mode.
@@ -271,3 +293,4 @@
// DASM2-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (device-[[T]], [[ARCH2]])
// DASM2_NV-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (device-[[T]], [[ARCH2]])
// DASM2_NV-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] ([[TRIPLE]]:[[ARCH2]])" {[[P8]]}, assembler
+// DASM2-NOT: host
diff --git a/test/Driver/cxa-atexit.cpp b/test/Driver/cxa-atexit.cpp
index cc5f68b9a474..ae955ea5a7df 100644
--- a/test/Driver/cxa-atexit.cpp
+++ b/test/Driver/cxa-atexit.cpp
@@ -20,7 +20,7 @@
// CHECK-WINDOWS: "-fno-use-cxa-atexit"
// CHECK-SOLARIS: "-fno-use-cxa-atexit"
-// CHECK-HEXAGON: "-fno-use-cxa-atexit"
+// CHECK-HEXAGON-NOT: "-fno-use-cxa-atexit"
// CHECK-XCORE: "-fno-use-cxa-atexit"
// CHECK-MTI: "-fno-use-cxa-atexit"
// CHECK-MIPS-NOT: "-fno-use-cxa-atexit"
diff --git a/test/Driver/darwin-infer-simulator-sdkroot.c b/test/Driver/darwin-infer-simulator-sdkroot.c
index 1b1f1739d64c..3fda5998addb 100644
--- a/test/Driver/darwin-infer-simulator-sdkroot.c
+++ b/test/Driver/darwin-infer-simulator-sdkroot.c
@@ -1,6 +1,6 @@
// Check that SDKROOT does not infer simulator on when it points to a regular
// SDK.
-// REQUIRES: system-darwin
+// REQUIRES: system-darwin && native
//
// RUN: rm -rf %t/SDKs/iPhoneOS8.0.0.sdk
// RUN: mkdir -p %t/SDKs/iPhoneOS8.0.0.sdk
diff --git a/test/Driver/darwin-ld-lto.c b/test/Driver/darwin-ld-lto.c
index 2725df4f5f5b..80b23b9b2c79 100644
--- a/test/Driver/darwin-ld-lto.c
+++ b/test/Driver/darwin-ld-lto.c
@@ -17,3 +17,14 @@
// RUN: %clang -target x86_64-apple-darwin10 -### %s \
// RUN: -ccc-install-dir %S/dummytestdir -mlinker-version=133 2> %t.log
// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH %s -input-file %t.log
+
+
+// Check that -object_lto_path is passed correctly to ld64
+// RUN: %clang -target x86_64-apple-darwin10 %s -flto=full -### 2>&1 | \
+// RUN: FileCheck -check-prefix=FULL_LTO_OBJECT_PATH %s
+// FULL_LTO_OBJECT_PATH: /usr/bin/ld
+// FULL_LTO_OBJECT_PATH-SAME: "-object_path_lto" "{{[a-zA-Z0-9_\/]+\/cc\-[a-zA-Z0-9_]+.o}}"
+// RUN: %clang -target x86_64-apple-darwin10 %s -flto=thin -### 2>&1 | \
+// RUN: FileCheck -check-prefix=THIN_LTO_OBJECT_PATH %s
+// THIN_LTO_OBJECT_PATH: /usr/bin/ld
+// THIN_LTO_OBJECT_PATH-SAME: "-object_path_lto" "{{[a-zA-Z0-9_\/]+\/thinlto\-[a-zA-Z0-9_]+}}"
diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c
index c98d1abcab29..5198ef057b94 100644
--- a/test/Driver/darwin-ld.c
+++ b/test/Driver/darwin-ld.c
@@ -152,78 +152,51 @@
// RUN: FileCheck -check-prefix=LINK_NO_IOS_ARM64_CRT1 %s < %t.log
// LINK_NO_IOS_ARM64_CRT1-NOT: crt
-// RUN: %clang -target x86_64-apple-ios6.0 -miphoneos-version-min=6.0 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: %clang -target x86_64-apple-ios6.0 -miphoneos-version-min=6.0 -fprofile-instr-generate -resource-dir=%S/Inputs/resource_dir -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=LINK_IOSSIM_PROFILE %s < %t.log
// LINK_IOSSIM_PROFILE: {{ld(.exe)?"}}
// LINK_IOSSIM_PROFILE: libclang_rt.profile_iossim.a
+// LINK_IOSSIM_PROFILE: libclang_rt.ios.a
-// FIXME: Currently the builtin library is only added to the command line if it,
-// so we can't check for it here
-// FIXME_LINK_IOSSIM_PROFILE: libclang_rt.ios.a
-
-// RUN: %clang -target arm64-apple-tvos8.3 -mtvos-version-min=8.3 -### %t.o 2> %t.log
+// RUN: %clang -target arm64-apple-tvos8.3 -mtvos-version-min=8.3 -resource-dir=%S/Inputs/resource_dir -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=LINK_TVOS_ARM64 %s < %t.log
// LINK_TVOS_ARM64: {{ld(.exe)?"}}
// LINK_TVOS_ARM64: -tvos_version_min
// LINK_TVOS_ARM64-NOT: crt
// LINK_TVOS_ARM64-NOT: lgcc_s.1
-// FIXME: This library does not get built unless the tvOS SDK is
-// installed, and the driver will not try to link it if it does not exist.
-// This should be reenabled when the tvOS SDK becomes a standard part
-// of Xcode.
-// FIXME_LINK_TVOS_ARM64: libclang_rt.tvos.a
+// LINK_TVOS_ARM64: libclang_rt.tvos.a
-// RUN: %clang -target arm64-apple-tvos8.3 -mtvos-version-min=8.3 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: %clang -target arm64-apple-tvos8.3 -mtvos-version-min=8.3 -fprofile-instr-generate -resource-dir=%S/Inputs/resource_dir -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=LINK_TVOS_PROFILE %s < %t.log
// LINK_TVOS_PROFILE: {{ld(.exe)?"}}
-// FIXME: These libraries do not get built unless the tvOS SDK is
-// installed, and the driver will not try to link them if they do not exist.
-// This should be reenabled when the tvOS SDK becomes a standard part
-// of Xcode.
-// FIXME_LINK_TVOS_PROFILE: libclang_rt.profile_tvos.a
-// FIXME_LINK_TVOS_PROFILE: libclang_rt.tvos.a
-
-// RUN: %clang -target arm64-apple-tvos8.3 -mtvos-version-min=8.3 -### %t.o -lcc_kext 2> %t.log
+// LINK_TVOS_PROFILE: libclang_rt.profile_tvos.a
+// LINK_TVOS_PROFILE: libclang_rt.tvos.a
+
+// RUN: %clang -target arm64-apple-tvos8.3 -mtvos-version-min=8.3 -resource-dir=%S/Inputs/resource_dir -### %t.o -lcc_kext 2> %t.log
// RUN: FileCheck -check-prefix=LINK_TVOS_KEXT %s < %t.log
// LINK_TVOS_KEXT: {{ld(.exe)?"}}
-// FIXME: These libraries do not get built unless the tvOS SDK is
-// installed, and the driver will not try to link them if they do not exist.
-// This should be reenabled when the tvOS SDK becomes a standard part
-// of Xcode.
-// FIXME_LINK_TVOS_KEXT: libclang_rt.cc_kext_tvos.a
-// FIXME_LINK_TVOS_KEXT: libclang_rt.tvos.a
-
-// RUN: %clang -target armv7k-apple-watchos2.0 -mwatchos-version-min=2.0 -### %t.o 2> %t.log
+// LINK_TVOS_KEXT: libclang_rt.cc_kext_tvos.a
+// LINK_TVOS_KEXT: libclang_rt.tvos.a
+
+// RUN: %clang -target armv7k-apple-watchos2.0 -mwatchos-version-min=2.0 -resource-dir=%S/Inputs/resource_dir -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=LINK_WATCHOS_ARM %s < %t.log
// LINK_WATCHOS_ARM: {{ld(.exe)?"}}
// LINK_WATCHOS_ARM: -watchos_version_min
// LINK_WATCHOS_ARM-NOT: crt
// LINK_WATCHOS_ARM-NOT: lgcc_s.1
-// FIXME: This library does not get built unless the watchOS SDK is
-// installed, and the driver will not try to link it if it does not exist.
-// This should be reenabled when the watchOS SDK becomes a standard part
-// of Xcode.
-// FIXME_LINK_WATCHOS_ARM: libclang_rt.watchos.a
+// LINK_WATCHOS_ARM: libclang_rt.watchos.a
-// RUN: %clang -target armv7k-apple-watchos2.0 -mwatchos-version-min=2.0 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: %clang -target armv7k-apple-watchos2.0 -mwatchos-version-min=2.0 -resource-dir=%S/Inputs/resource_dir -fprofile-instr-generate -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=LINK_WATCHOS_PROFILE %s < %t.log
// LINK_WATCHOS_PROFILE: {{ld(.exe)?"}}
-// FIXME: These libraries do not get built unless the watchOS SDK is
-// installed, and the driver will not try to link them if they do not exist.
-// This should be reenabled when the watchOS SDK becomes a standard part
-// of Xcode.
-// FIXME_LINK_WATCHOS_PROFILE: libclang_rt.profile_watchos.a
-// FIXME_LINK_WATCHOS_PROFILE: libclang_rt.watchos.a
-
-// RUN: %clang -target armv7k-apple-watchos2.0 -mwatchos-version-min=2.0 -### %t.o -lcc_kext 2> %t.log
+// LINK_WATCHOS_PROFILE: libclang_rt.profile_watchos.a
+// LINK_WATCHOS_PROFILE: libclang_rt.watchos.a
+
+// RUN: %clang -target armv7k-apple-watchos2.0 -mwatchos-version-min=2.0 -resource-dir=%S/Inputs/resource_dir -### %t.o -lcc_kext 2> %t.log
// RUN: FileCheck -check-prefix=LINK_WATCHOS_KEXT %s < %t.log
// LINK_WATCHOS_KEXT: {{ld(.exe)?"}}
-// FIXME: These libraries do not get built unless the watchOS SDK is
-// installed, and the driver will not try to link them if they do not exist.
-// This should be reenabled when the watchOS SDK becomes a standard part
-// of Xcode.
-// FIXME_LINK_WATCHOS_KEXT: libclang_rt.cc_kext_watchos.a
-// FIXME_LINK_WATCHOS_KEXT: libclang_rt.watchos.a
+// LINK_WATCHOS_KEXT: libclang_rt.cc_kext_watchos.a
+// LINK_WATCHOS_KEXT: libclang_rt.watchos.a
// RUN: %clang -target i386-apple-darwin12 -pg -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=LINK_PG %s < %t.log
@@ -368,10 +341,22 @@
// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
// PROFILE_EXPORT: "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version" "-exported_symbol" "_lprofCurFilename"
//
-// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log
+// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate --coverage -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=NO_PROFILE_EXPORT %s < %t.log
// NO_PROFILE_EXPORT-NOT: "-exported_symbol"
//
+// RUN: %clang -target x86_64-apple-darwin12 --coverage -exported_symbols_list /dev/null -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log
+// RUN: %clang -target x86_64-apple-darwin12 -fprofile-arcs -Wl,-exported_symbols_list,/dev/null -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log
+// RUN: %clang -target x86_64-apple-darwin12 -fprofile-arcs -Wl,-exported_symbol,foo -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log
+// RUN: %clang -target x86_64-apple-darwin12 -fprofile-arcs -Xlinker -exported_symbol -Xlinker foo -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log
+// RUN: %clang -target x86_64-apple-darwin12 -fprofile-arcs -Xlinker -exported_symbols_list -Xlinker /dev/null -### %t.o 2> %t.log
+// RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log
+// GCOV_EXPORT: "-exported_symbol" "___gcov_flush"
+//
// Check that we can pass the outliner down to the linker.
// RUN: env IPHONEOS_DEPLOYMENT_TARGET=7.0 \
// RUN: %clang -target arm64-apple-darwin -moutline -### %t.o 2> %t.log
diff --git a/test/Driver/darwin-sdk-version.c b/test/Driver/darwin-sdk-version.c
new file mode 100644
index 000000000000..9c1eec0ee43f
--- /dev/null
+++ b/test/Driver/darwin-sdk-version.c
@@ -0,0 +1,37 @@
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %S/Inputs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck %s
+// RUN: env SDKROOT=%S/Inputs/MacOSX10.14.sdk %clang -target x86_64-apple-macosx10.13 -c -### %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.10.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.10.sdk
+// RUN: %clang -m64 -isysroot %t/SDKs/MacOSX10.10.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=INFER_SDK_VERSION %s
+// RUN: sed -e 's/10\.14/10\.8/g' %S/Inputs/MacOSX10.14.sdk/SDKSettings.json > %t/SDKs/MacOSX10.10.sdk/SDKSettings.json
+// RUN: %clang -m64 -isysroot %t/SDKs/MacOSX10.10.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=INFER_DEPLOYMENT_TARGET_VERSION %s
+// REQUIRES: system-darwin && native
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.14.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.14.sdk
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %t/SDKs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=NO_VERSION %s
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.14.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.14.sdk
+// RUN: echo '{broken json' > %t/SDKs/MacOSX10.14.sdk/SDKSettings.json
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %t/SDKs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=NO_VERSION,ERROR %s
+//
+// RUN: rm -rf %t/SDKs/MacOSX10.14.sdk
+// RUN: mkdir -p %t/SDKs/MacOSX10.14.sdk
+// RUN: echo '{"Version":1}' > %t/SDKs/MacOSX10.14.sdk/SDKSettings.json
+// RUN: %clang -target x86_64-apple-macosx10.13 -isysroot %t/SDKs/MacOSX10.14.sdk -c -### %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=NO_VERSION,ERROR %s
+
+// CHECK: -target-sdk-version=10.14
+// INFER_SDK_VERSION: "-triple" "x86_64-apple-macosx10.10.0"
+// INFER_SDK_VERSION-SAME: -target-sdk-version=10.10
+// INFER_DEPLOYMENT_TARGET_VERSION: "-triple" "x86_64-apple-macosx10.8.0"
+// NO_VERSION-NOT: target-sdk-version
+// ERROR: warning: SDK settings were ignored as 'SDKSettings.json' could not be parsed
diff --git a/test/Driver/darwin-stdlib.cpp b/test/Driver/darwin-stdlib.cpp
index 26cbf2bde346..3e89bd1ec99f 100644
--- a/test/Driver/darwin-stdlib.cpp
+++ b/test/Driver/darwin-stdlib.cpp
@@ -2,19 +2,20 @@
// than the platform default. (see https://llvm.org/bugs/show_bug.cgi?id=30548)
// XFAIL: default-cxx-stdlib-set
-// RUN: %clang -target x86_64-apple-darwin -arch arm64 -miphoneos-version-min=7.0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
-// RUN: %clang -target x86_64-apple-darwin -mmacosx-version-min=10.8 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBSTDCXX
-// RUN: %clang -target x86_64-apple-darwin -mmacosx-version-min=10.9 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
-// RUN: %clang -target x86_64-apple-darwin -arch armv7s -miphoneos-version-min=6.1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBSTDCXX
-// RUN: %clang -target x86_64-apple-darwin -arch armv7s -miphoneos-version-min=7.0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
-// RUN: %clang -target x86_64-apple-darwin -arch armv7k %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
+// RUN: %clang -target x86_64-apple-darwin -ccc-install-dir %S/Inputs/darwin_toolchain_tree/bin/ -arch arm64 -miphoneos-version-min=7.0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
+// RUN: %clang -target x86_64-apple-darwin -ccc-install-dir %S/Inputs/darwin_toolchain_tree/bin/ -mmacosx-version-min=10.8 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBSTDCXX
+// RUN: %clang -target x86_64-apple-darwin -ccc-install-dir %S/Inputs/darwin_toolchain_tree/bin/ -mmacosx-version-min=10.9 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
+// RUN: %clang -target x86_64-apple-darwin -ccc-install-dir %S/Inputs/darwin_toolchain_tree/bin/ -arch armv7s -miphoneos-version-min=6.1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBSTDCXX
+// RUN: %clang -target x86_64-apple-darwin -ccc-install-dir %S/Inputs/darwin_toolchain_tree/bin/ -arch armv7s -miphoneos-version-min=7.0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
+// RUN: %clang -target x86_64-apple-darwin -ccc-install-dir %S/Inputs/darwin_toolchain_tree/bin/ -arch armv7k %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
// The purpose of this test is that the libc++ headers should be found
-// properly. At the moment this is done by passing -stdlib=libc++ down to the
-// cc1 invocation. If and when we change to finding them in the driver this test
-// should reflect that.
+// properly. We also pass -stdlib=libc++ to make sure the logic to add the
+// optional absolute include for libc++ from InitHeaderSearch.cpp also fires.
-// CHECK-LIBCXX: -stdlib=libc++
+// CHECK-LIBCXX: "-stdlib=libc++"
+// CHECK-LIBCXX: "-internal-isystem" "{{[^"]*}}{{/|\\\\}}Inputs{{/|\\\\}}darwin_toolchain_tree{{/|\\\\}}bin{{/|\\\\}}..{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1"
// CHECK-LIBSTDCXX-NOT: -stdlib=libc++
// CHECK-LIBSTDCXX-NOT: -stdlib=libstdc++
+// CHECK-LIBSTDCXX-NOT: -internal-isystem
diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c
index 0dd32e983ad8..58269cbb29bf 100644
--- a/test/Driver/debug-options.c
+++ b/test/Driver/debug-options.c
@@ -64,6 +64,14 @@
// RUN: %clang -### -c -g %s -target x86_64-pc-freebsd10.0 2>&1 \
// RUN: | FileCheck -check-prefix=G_GDB %s
+// Windows.
+// RUN: %clang -### -c -g %s -target x86_64-w64-windows-gnu 2>&1 \
+// RUN: | FileCheck -check-prefix=G_GDB %s
+// RUN: %clang -### -c -g %s -target x86_64-windows-msvc 2>&1 \
+// RUN: | FileCheck -check-prefix=G_NOTUNING %s
+// RUN: %clang_cl -### -c -Z7 -target x86_64-windows-msvc -- %s 2>&1 \
+// RUN: | FileCheck -check-prefix=G_NOTUNING %s
+
// On the PS4, -g defaults to -gno-column-info, and we always generate the
// arange section.
// RUN: %clang -### -c %s -target x86_64-scei-ps4 2>&1 \
@@ -119,6 +127,25 @@
// RUN: %clang -### -c -gline-tables-only -g0 %s 2>&1 \
// RUN: | FileCheck -check-prefix=GLTO_NO %s
//
+// RUN: %clang -### -c -gline-directives-only %s -target x86_64-apple-darwin 2>&1 \
+// RUN: | FileCheck -check-prefix=GLIO_ONLY %s
+// RUN: %clang -### -c -gline-directives-only %s -target i686-pc-openbsd 2>&1 \
+// RUN: | FileCheck -check-prefix=GLIO_ONLY_DWARF2 %s
+// RUN: %clang -### -c -gline-directives-only %s -target x86_64-pc-freebsd10.0 2>&1 \
+// RUN: | FileCheck -check-prefix=GLIO_ONLY_DWARF2 %s
+// RUN: %clang -### -c -gline-directives-only -g %s -target x86_64-linux-gnu 2>&1 \
+// RUN: | FileCheck -check-prefix=G_ONLY %s
+// RUN: %clang -### -c -gline-directives-only -g %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE -check-prefix=G_DWARF4 %s
+// RUN: %clang -### -c -gline-directives-only -g %s -target i686-pc-openbsd 2>&1 \
+// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
+// RUN: %clang -### -c -gline-directives-only -g %s -target x86_64-pc-freebsd10.0 2>&1 \
+// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
+// RUN: %clang -### -c -gline-directives-only -g %s -target i386-pc-solaris 2>&1 \
+// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
+// RUN: %clang -### -c -gline-directives-only -g0 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=GLIO_NO %s
+//
// RUN: %clang -### -c -grecord-gcc-switches %s 2>&1 \
// | FileCheck -check-prefix=GRECORD %s
// RUN: %clang -### -c -gno-record-gcc-switches %s 2>&1 \
@@ -130,12 +157,39 @@
// RUN: %clang -### -c -O3 -ffunction-sections -grecord-gcc-switches %s 2>&1 \
// | FileCheck -check-prefix=GRECORD_OPT %s
//
+// RUN: %clang -### -c -grecord-command-line %s 2>&1 \
+// | FileCheck -check-prefix=GRECORD %s
+// RUN: %clang -### -c -gno-record-command-line %s 2>&1 \
+// | FileCheck -check-prefix=GNO_RECORD %s
+// RUN: %clang -### -c -grecord-command-line -gno-record-command-line %s 2>&1 \
+// | FileCheck -check-prefix=GNO_RECORD %s/
+// RUN: %clang -### -c -grecord-command-line -o - %s 2>&1 \
+// | FileCheck -check-prefix=GRECORD_O %s
+// RUN: %clang -### -c -O3 -ffunction-sections -grecord-command-line %s 2>&1 \
+// | FileCheck -check-prefix=GRECORD_OPT %s
+//
// RUN: %clang -### -c -gstrict-dwarf -gno-strict-dwarf %s 2>&1 \
// RUN: | FileCheck -check-prefix=GIGNORE %s
//
-// RUN: %clang -### -c -ggnu-pubnames %s 2>&1 | FileCheck -check-prefix=GOPT %s
-// RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NOGOPT %s
-// RUN: %clang -### -c -ggnu-pubnames -gno-gnu-pubnames %s 2>&1 | FileCheck -check-prefix=NOGOPT %s
+// RUN: %clang -### -c -ggnu-pubnames %s 2>&1 | FileCheck -check-prefix=GPUB %s
+// RUN: %clang -### -c -ggdb %s 2>&1 | FileCheck -check-prefix=NOPUB %s
+// RUN: %clang -### -c -ggnu-pubnames -gno-gnu-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s
+// RUN: %clang -### -c -ggnu-pubnames -gno-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s
+//
+// RUN: %clang -### -c -gpubnames %s 2>&1 | FileCheck -check-prefix=PUB %s
+// RUN: %clang -### -c -ggdb %s 2>&1 | FileCheck -check-prefix=NOPUB %s
+// RUN: %clang -### -c -gpubnames -gno-gnu-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s
+// RUN: %clang -### -c -gpubnames -gno-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s
+//
+// RUN: %clang -### -c -gsplit-dwarf %s 2>&1 | FileCheck -check-prefix=GPUB %s
+// RUN: %clang -### -c -gsplit-dwarf -gno-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s
+//
+// RUN: %clang -### -c -fdebug-ranges-base-address %s 2>&1 | FileCheck -check-prefix=RNGBSE %s
+// RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s
+// RUN: %clang -### -c -fdebug-ranges-base-address -fno-debug-ranges-base-address %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s
+//
+// RUN: %clang -### -c -glldb %s 2>&1 | FileCheck -check-prefix=GPUB %s
+// RUN: %clang -### -c -glldb -gno-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s
//
// RUN: %clang -### -c -gdwarf-aranges %s 2>&1 | FileCheck -check-prefix=GARANGE %s
//
@@ -169,6 +223,9 @@
// RUN: %clang -### -gmodules -gline-tables-only %s 2>&1 \
// RUN: | FileCheck -check-prefix=GLTO_ONLY %s
//
+// RUN: %clang -### -target %itanium_abi_triple -gmodules -gline-directives-only %s 2>&1 \
+// RUN: | FileCheck -check-prefix=GLIO_ONLY %s
+//
// G: "-cc1"
// G: "-debug-info-kind=limited"
//
@@ -195,6 +252,15 @@
// GLTO_ONLY_DWARF2: "-debug-info-kind=line-tables-only"
// GLTO_ONLY_DWARF2: "-dwarf-version=2"
//
+// GLIO_ONLY: "-cc1"
+// GLIO_ONLY-NOT: "-dwarf-ext-refs"
+// GLIO_ONLY: "-debug-info-kind=line-directives-only"
+// GLIO_ONLY-NOT: "-dwarf-ext-refs"
+//
+// GLIO_ONLY_DWARF2: "-cc1"
+// GLIO_ONLY_DWARF2: "-debug-info-kind=line-directives-only"
+// GLIO_ONLY_DWARF2: "-dwarf-version=2"
+//
// G_ONLY: "-cc1"
// G_ONLY: "-debug-info-kind=limited"
//
@@ -212,10 +278,17 @@
// G_LLDB: "-debugger-tuning=lldb"
// G_SCE: "-debugger-tuning=sce"
//
+// G_NOTUNING: "-cc1"
+// G_NOTUNING-NOT: "-debugger-tuning="
+//
// This tests asserts that "-gline-tables-only" "-g0" disables debug info.
// GLTO_NO: "-cc1"
// GLTO_NO-NOT: -debug-info-kind=
//
+// This tests asserts that "-gline-directives-only" "-g0" disables debug info.
+// GLIO_NO: "-cc1"
+// GLIO_NO-NOT: -debug-info-kind=
+//
// GRECORD: "-dwarf-debug-flags"
// GRECORD: -### -c -grecord-gcc-switches
//
@@ -229,8 +302,14 @@
//
// GIGNORE-NOT: "argument unused during compilation"
//
-// GOPT: -ggnu-pubnames
-// NOGOPT-NOT: -ggnu-pubnames
+// GPUB: -ggnu-pubnames
+// NOPUB-NOT: -ggnu-pubnames
+// NOPUB-NOT: -gpubnames
+//
+// PUB: -gpubnames
+//
+// RNGBSE: -fdebug-ranges-base-address
+// NORNGBSE-NOT: -fdebug-ranges-base-address
//
// GARANGE: -generate-arange-section
//
@@ -244,7 +323,8 @@
//
// NOCI-NOT: "-dwarf-column-info"
//
-// GEXTREFS: "-dwarf-ext-refs" "-fmodule-format=obj" "-debug-info-kind={{standalone|limited}}"
+// GEXTREFS: "-dwarf-ext-refs" "-fmodule-format=obj"
+// GEXTREFS: "-debug-info-kind={{standalone|limited}}"
// RUN: not %clang -cc1 -debug-info-kind=watkind 2>&1 | FileCheck -check-prefix=BADSTRING1 %s
// BADSTRING1: error: invalid value 'watkind' in '-debug-info-kind=watkind'
diff --git a/test/Driver/embed-bitcode.s b/test/Driver/embed-bitcode.s
new file mode 100644
index 000000000000..71a3e9c2fb1d
--- /dev/null
+++ b/test/Driver/embed-bitcode.s
@@ -0,0 +1,12 @@
+// REQUIRES: arm-registered-target
+
+// RUN: %clang -c -target armv7-apple-ios10 %s -fembed-bitcode -### 2>&1 | FileCheck %s -check-prefix=CHECK-AS
+// RUN: %clang -c -target armv7-apple-ios10 %s -fembed-bitcode-marker -### 2>&1 | FileCheck %s -check-prefix=CHECK-AS-MARKER
+// CHECK-AS: -cc1as
+// CHECK-AS: -fembed-bitcode=all
+// CHECK-AS-MARKER: -fembed-bitcode=marker
+
+// RUN: %clang -c -target armv7-apple-ios10 %s -fembed-bitcode -o %t.o
+// RUN: llvm-readobj -section-headers %t.o | FileCheck --check-prefix=CHECK-SECTION %s
+// CHECK-SECTION: Name: __asm
+// CHECK-SECTION-NEXT: Segment: __LLVM
diff --git a/test/Driver/fast-math.c b/test/Driver/fast-math.c
index 57e5d2c71575..470e5a8104b4 100644
--- a/test/Driver/fast-math.c
+++ b/test/Driver/fast-math.c
@@ -95,6 +95,8 @@
// RUN: | FileCheck --check-prefix=CHECK-NO-MATH-ERRNO %s
// RUN: %clang -### -target x86_64-fuchsia -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-MATH-ERRNO %s
+// RUN: %clang -### -target x86_64-linux-android -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-MATH-ERRNO %s
//
// Check that -ffast-math disables -fmath-errno, and -fno-fast-math merely
// preserves the target default. Also check various flag set operations between
diff --git a/test/Driver/fembed-bitcode.c b/test/Driver/fembed-bitcode.c
new file mode 100644
index 000000000000..b0ec63f13ff3
--- /dev/null
+++ b/test/Driver/fembed-bitcode.c
@@ -0,0 +1,28 @@
+// RUN: %clang -target x86_64-apple-macosx -fembed-bitcode=all -c %s -o /dev/null -### 2>&1 \
+// RUN: | FileCheck -check-prefix CHECK-X64 %s
+
+// CHECK-X64: "-cc1"
+
+// CHECK-X64: "-cc1"
+// CHECK-X64-NOT: "-fdebug-compilation-dir"
+
+// RUN: %clang -target armv7-apple-ios -fembed-bitcode=all -c %s -o /dev/null -### 2>&1 \
+// RUN: | FileCheck -check-prefix CHECK-ARM %s
+
+// CHECK-ARM: "-cc1"
+
+// CHECK-ARM: "-cc1"
+// CHECK-ARM: "-target-abi"
+// CHECK-ARM: "apcs-gnu"
+// CHECK-ARM-NOT: "-fdebug-compilation-dir"
+
+// RUN: %clang -target arm64-apple-ios -fembed-bitcode=all -c %s -o /dev/null -### 2>&1 \
+// RUN: | FileCheck -check-prefix CHECK-AARCH64 %s
+
+// CHECK-AARCH64: "-cc1"
+
+// CHECK-AARCH64: "-cc1"
+// CHECK-AARCH64: "-target-abi"
+// CHECK-AARCH64: "darwinpcs"
+// CHECK-AARCH64-NOT: "-fdebug-compilation-dir"
+
diff --git a/test/Driver/fopenmp.c b/test/Driver/fopenmp.c
index ac0f1b44cba3..63334ba49a1d 100644
--- a/test/Driver/fopenmp.c
+++ b/test/Driver/fopenmp.c
@@ -10,6 +10,9 @@
// RUN: %clang -target x86_64-netbsd -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
// RUN: %clang -target x86_64-netbsd -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
// RUN: %clang -target x86_64-netbsd -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-windows-gnu -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-windows-gnu -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
+// RUN: %clang -target x86_64-windows-gnu -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
//
// CHECK-CC1-OPENMP: "-cc1"
// CHECK-CC1-OPENMP: "-fopenmp"
@@ -49,6 +52,14 @@
// RUN: %clang -nostdlib -target x86_64-netbsd -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-GOMP
// RUN: %clang -nostdlib -target x86_64-netbsd -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-IOMP5
//
+// RUN: %clang -target x86_64-windows-gnu -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-OMP
+// RUN: %clang -target x86_64-windows-gnu -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP --check-prefix=CHECK-LD-GOMP-NO-RT
+// RUN: %clang -target x86_64-windows-gnu -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-IOMP5MD
+//
+// RUN: %clang -nostdlib -target x86_64-windows-gnu -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OMP
+// RUN: %clang -nostdlib -target x86_64-windows-gnu -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-GOMP
+// RUN: %clang -nostdlib -target x86_64-windows-gnu -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-IOMP5MD
+//
// CHECK-LD-OMP: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-OMP: "-lomp"
//
@@ -60,6 +71,9 @@
// CHECK-LD-IOMP5: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-IOMP5: "-liomp5"
//
+// CHECK-LD-IOMP5MD: "{{.*}}ld{{(.exe)?}}"
+// CHECK-LD-IOMP5MD: "-liomp5md"
+//
// CHECK-NO-OMP: "{{.*}}ld{{(.exe)?}}"
// CHECK-NO-OMP-NOT: "-lomp"
//
@@ -69,6 +83,9 @@
// CHECK-NO-IOMP5: "{{.*}}ld{{(.exe)?}}"
// CHECK-NO-IOMP5-NOT: "-liomp5"
//
+// CHECK-NO-IOMP5MD: "{{.*}}ld{{(.exe)?}}"
+// CHECK-NO-IOMP5MD-NOT: "-liomp5md"
+//
// We'd like to check that the default is sane, but until we have the ability
// to *always* semantically analyze OpenMP without always generating runtime
// calls (in the event of an unsupported runtime), we don't have a good way to
@@ -79,6 +96,10 @@
// RUN: %clang -target x86_64-darwin -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY
// RUN: %clang -target x86_64-freebsd -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY
// RUN: %clang -target x86_64-netbsd -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY
+// RUN: %clang -target x86_64-windows-gnu -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANYMD
//
// CHECK-LD-ANY: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-ANY: "-l{{(omp|gomp|iomp5)}}"
+//
+// CHECK-LD-ANYMD: "{{.*}}ld{{(.exe)?}}"
+// CHECK-LD-ANYMD: "-l{{(omp|gomp|iomp5md)}}"
diff --git a/test/Driver/fsanitize-coverage.c b/test/Driver/fsanitize-coverage.c
index ab8b1c65d81e..acc712c001ba 100644
--- a/test/Driver/fsanitize-coverage.c
+++ b/test/Driver/fsanitize-coverage.c
@@ -9,6 +9,7 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=leak -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
// RUN: %clang -target x86_64-linux-gnu -fsanitize=bool -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c
index 304e75930245..db8887239926 100644
--- a/test/Driver/fsanitize.c
+++ b/test/Driver/fsanitize.c
@@ -17,9 +17,11 @@
// RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32
// RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 --check-prefix=CHECK-UNDEFINED-WIN-CXX
// RUN: %clang -target x86_64-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN64
+// RUN: %clang -target x86_64-w64-mingw32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN64-MINGW
// RUN: %clang -target x86_64-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN64 --check-prefix=CHECK-UNDEFINED-WIN-CXX
// CHECK-UNDEFINED-WIN32: "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib"
// CHECK-UNDEFINED-WIN64: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib"
+// CHECK-UNDEFINED-WIN64-MINGW: "--dependent-lib={{[^"]*}}libclang_rt.ubsan_standalone-x86_64.a"
// CHECK-UNDEFINED-WIN-CXX: "--dependent-lib={{[^"]*}}ubsan_standalone_cxx{{[^"]*}}.lib"
// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){18}"}}
@@ -29,22 +31,52 @@
// CHECK-COVERAGE-WIN64: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib"
// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER -implicit-check-not="-fsanitize-address-use-after-scope"
-// CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|implicit-integer-truncation),?){6}"}}
+// CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){8}"}}
// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-RECOVER
// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion -fsanitize-recover=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-RECOVER
// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion -fno-sanitize-recover=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-NORECOVER
// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion -fsanitize-trap=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-TRAP
-// CHECK-implicit-conversion: "-fsanitize={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-RECOVER: "-fsanitize-recover={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-RECOVER-NOT: "-fno-sanitize-recover={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-RECOVER-NOT: "-fsanitize-trap={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-NORECOVER-NOT: "-fno-sanitize-recover={{((implicit-integer-truncation),?){1}"}} // ???
-// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-recover={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-trap={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-TRAP: "-fsanitize-trap={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-TRAP-NOT: "-fsanitize-recover={{((implicit-integer-truncation),?){1}"}}
-// CHECK-implicit-conversion-TRAP-NOT: "-fno-sanitize-recover={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion: "-fsanitize={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-RECOVER: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-RECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-RECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-NORECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}} // ???
+// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-TRAP: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-TRAP-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+// CHECK-implicit-conversion-TRAP-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-arithmetic-value-change %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-arithmetic-value-change,CHECK-implicit-integer-arithmetic-value-change-RECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-arithmetic-value-change -fsanitize-recover=implicit-integer-arithmetic-value-change %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-arithmetic-value-change,CHECK-implicit-integer-arithmetic-value-change-RECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-arithmetic-value-change -fno-sanitize-recover=implicit-integer-arithmetic-value-change %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-arithmetic-value-change,CHECK-implicit-integer-arithmetic-value-change-NORECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-arithmetic-value-change -fsanitize-trap=implicit-integer-arithmetic-value-change %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-arithmetic-value-change,CHECK-implicit-integer-arithmetic-value-change-TRAP
+// CHECK-implicit-integer-arithmetic-value-change: "-fsanitize={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-RECOVER: "-fsanitize-recover={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-RECOVER-NOT: "-fno-sanitize-recover={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-RECOVER-NOT: "-fsanitize-trap={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-NORECOVER-NOT: "-fno-sanitize-recover={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}} // ???
+// CHECK-implicit-integer-arithmetic-value-change-NORECOVER-NOT: "-fsanitize-recover={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-NORECOVER-NOT: "-fsanitize-trap={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-TRAP: "-fsanitize-trap={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-TRAP-NOT: "-fsanitize-recover={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+// CHECK-implicit-integer-arithmetic-value-change-TRAP-NOT: "-fno-sanitize-recover={{((implicit-signed-integer-truncation|implicit-integer-sign-change),?){2}"}}
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-truncation %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-truncation,CHECK-implicit-integer-truncation-RECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-truncation,CHECK-implicit-integer-truncation-RECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-truncation,CHECK-implicit-integer-truncation-NORECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-truncation,CHECK-implicit-integer-truncation-TRAP
+// CHECK-implicit-integer-truncation: "-fsanitize={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-RECOVER: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-RECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-RECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-NORECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}} // ???
+// CHECK-implicit-integer-truncation-NORECOVER-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-NORECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-TRAP: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-TRAP-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
+// CHECK-implicit-integer-truncation-TRAP-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation),?){2}"}}
// RUN: %clang -fsanitize=bounds -### -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-BOUNDS
// CHECK-BOUNDS: "-fsanitize={{((array-bounds|local-bounds),?){2}"}}
@@ -89,6 +121,27 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=leak,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-SANM
// CHECK-SANL-SANM: '-fsanitize=leak' not allowed with '-fsanitize=memory'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-ASAN
+// CHECK-KMSAN-ASAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=address'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,hwaddress -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-HWASAN
+// CHECK-KMSAN-HWASAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=hwaddress'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-LSAN
+// CHECK-KMSAN-LSAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=leak'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,thread -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-TSAN
+// CHECK-KMSAN-TSAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=thread'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-KASAN
+// CHECK-KMSAN-KASAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=kernel-address'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-MSAN
+// CHECK-KMSAN-MSAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=memory'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,safe-stack -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-SAFESTACK
+// CHECK-KMSAN-SAFESTACK: '-fsanitize=kernel-memory' not allowed with '-fsanitize=safe-stack'
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANT
// CHECK-SANKA-SANT: '-fsanitize=kernel-address' not allowed with '-fsanitize=thread'
@@ -144,6 +197,10 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANM
// CHECK-SANE-SANM: '-fsanitize=efficiency-{{.*}}' not allowed with '-fsanitize=memory'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,kernel-memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKM
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,kernel-memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKM
+// CHECK-SANE-SANKM: '-fsanitize=kernel-memory' not allowed with '-fsanitize=efficiency-{{.*}}'
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKA
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKA
// CHECK-SANE-SANKA: '-fsanitize=efficiency-{{.*}}' not allowed with '-fsanitize=kernel-address'
@@ -166,6 +223,24 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-WITHOUT-USE-AFTER-SCOPE
// CHECK-ASAN-WITHOUT-USE-AFTER-SCOPE: -cc1{{.*}}address-use-after-scope
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-poison-custom-array-cookie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE
+// RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fsanitize-address-poison-custom-array-cookie -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE
+// CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE: -cc1{{.*}}-fsanitize-address-poison-custom-array-cookie
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-poison-custom-array-cookie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-OFF
+// RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fno-sanitize-address-poison-custom-array-cookie -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-OFF
+// CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-OFF-NOT: -cc1{{.*}}address-poison-custom-array-cookie
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-poison-custom-array-cookie -fsanitize-address-poison-custom-array-cookie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-BOTH
+// RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fno-sanitize-address-poison-custom-array-cookie -fsanitize-address-poison-custom-array-cookie -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-BOTH
+// CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-BOTH: -cc1{{.*}}-fsanitize-address-poison-custom-array-cookie
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-poison-custom-array-cookie -fno-sanitize-address-poison-custom-array-cookie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-BOTH-OFF
+// CHECK-POISON-CUSTOM-ARRAY-NEW-COOKIE-BOTH-OFF-NOT: -cc1{{.*}}address-poison-custom-array-cookie
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-WITHOUT-POISON-CUSTOM-ARRAY-NEW-COOKIE
+// CHECK-ASAN-WITHOUT-POISON-CUSTOM-ARRAY-NEW-COOKIE-NOT: -cc1{{.*}}address-poison-custom-array-cookie
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-globals-dead-stripping %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-GLOBALS
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ASAN-GLOBALS
// RUN: %clang_cl --target=x86_64-windows-msvc -fsanitize=address -fsanitize-address-globals-dead-stripping -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-GLOBALS
@@ -173,6 +248,24 @@
// CHECK-ASAN-GLOBALS: -cc1{{.*}}-fsanitize-address-globals-dead-stripping
// CHECK-NO-ASAN-GLOBALS-NOT: -cc1{{.*}}-fsanitize-address-globals-dead-stripping
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-odr-indicator %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR
+// RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fsanitize-address-use-odr-indicator -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR
+// CHECK-ASAN-ODR-INDICATOR: -cc1{{.*}}-fsanitize-address-use-odr-indicator
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-use-odr-indicator %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR-OFF
+// RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fno-sanitize-address-use-odr-indicator -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR-OFF
+// CHECK-ASAN-ODR-INDICATOR-OFF-NOT: -cc1{{.*}}address-generate-odr-globals
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-use-odr-indicator -fsanitize-address-use-odr-indicator %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR-BOTH
+// RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fno-sanitize-address-use-odr-indicator -fsanitize-address-use-odr-indicator -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR-BOTH
+// CHECK-ASAN-ODR-INDICATOR-BOTH: -cc1{{.*}}-fsanitize-address-use-odr-indicator
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-odr-indicator -fno-sanitize-address-use-odr-indicator %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR-BOTH-OFF
+// CHECK-ASAN-ODR-INDICATOR-BOTH-OFF-NOT: -cc1{{.*}}address-generate-odr-globals
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-WITHOUT-ODR-INDICATOR
+// CHECK-ASAN-WITHOUT-ODR-INDICATOR-NOT: -cc1{{.*}}address-generate-odr-globals
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize-memory-track-origins -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-TRACK-ORIGINS
// CHECK-ONLY-TRACK-ORIGINS: warning: argument unused during compilation: '-fsanitize-memory-track-origins'
@@ -423,6 +516,15 @@
// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.8 -fsanitize=vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-DARWIN-OLD
// CHECK-VPTR-DARWIN-OLD: unsupported option '-fsanitize=vptr' for target 'x86_64-apple-darwin10'
+// RUN: %clang -target arm-apple-ios4 -fsanitize=vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-IOS-OLD
+// CHECK-VPTR-IOS-OLD: unsupported option '-fsanitize=vptr' for target 'arm-apple-ios4'
+
+// RUN: %clang -target aarch64-apple-darwin15.0.0 -fsanitize=vptr %s -### 2>&1
+// OK
+
+// RUN: %clang -target x86_64-apple-darwin15.0.0-simulator -fsanitize=vptr %s -### 2>&1
+// OK
+
// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.9 -fsanitize=alignment,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-DARWIN-NEW
// CHECK-VPTR-DARWIN-NEW: -fsanitize=alignment,vptr
@@ -471,7 +573,7 @@
// RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86
// RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86
-// CHECK-ESAN-X86: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i686--linux-gnu'
+// CHECK-ESAN-X86: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i686-unknown-linux-gnu'
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-DARWIN
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-DARWIN
@@ -607,28 +709,67 @@
// RUN: %clang -target x86_64-unknown-cloudabi -fsanitize=safe-stack %s -### 2>&1 | FileCheck %s -check-prefix=SAFESTACK-CLOUDABI
// SAFESTACK-CLOUDABI: "-fsanitize=safe-stack"
+
+
+// * NetBSD; please keep ordered as in Sanitizers.def *
+
// RUN: %clang -target i386--netbsd -fsanitize=address %s -### 2>&1 | FileCheck %s -check-prefix=ADDRESS-NETBSD
// RUN: %clang -target x86_64--netbsd -fsanitize=address %s -### 2>&1 | FileCheck %s -check-prefix=ADDRESS-NETBSD
// ADDRESS-NETBSD: "-fsanitize=address"
+// RUN: %clang -target x86_64--netbsd -fsanitize=kernel-address %s -### 2>&1 | FileCheck %s -check-prefix=KERNEL-ADDRESS-NETBSD
+// KERNEL-ADDRESS-NETBSD: "-fsanitize=kernel-address"
+
+// RUN: %clang -target x86_64--netbsd -fsanitize=hwaddress %s -### 2>&1 | FileCheck %s -check-prefix=HWADDRESS-NETBSD
+// HWADDRESS-NETBSD: "-fsanitize=hwaddress"
+
+// RUN: %clang -target x86_64--netbsd -fsanitize=kernel-hwaddress %s -### 2>&1 | FileCheck %s -check-prefix=KERNEL-HWADDRESS-NETBSD
+// KERNEL-HWADDRESS-NETBSD: "-fsanitize=kernel-hwaddress"
+
+// RUN: %clang -target x86_64--netbsd -fsanitize=memory %s -### 2>&1 | FileCheck %s -check-prefix=MEMORY-NETBSD
+// MEMORY-NETBSD: "-fsanitize=memory"
+
+// RUN: %clang -target x86_64--netbsd -fsanitize=kernel-memory %s -### 2>&1 | FileCheck %s -check-prefix=KERNEL-MEMORY-NETBSD
+// KERNEL-MEMORY-NETBSD: "-fsanitize=kernel-memory"
+
+// RUN: %clang -target x86_64--netbsd -fsanitize=thread %s -### 2>&1 | FileCheck %s -check-prefix=THREAD-NETBSD
+// THREAD-NETBSD: "-fsanitize=thread"
+
+// RUN: %clang -target i386--netbsd -fsanitize=leak %s -### 2>&1 | FileCheck %s -check-prefix=LEAK-NETBSD
+// RUN: %clang -target x86_64--netbsd -fsanitize=leak %s -### 2>&1 | FileCheck %s -check-prefix=LEAK-NETBSD
+// LEAK-NETBSD: "-fsanitize=leak"
+
+// RUN: %clang -target i386--netbsd -fsanitize=function %s -### 2>&1 | FileCheck %s -check-prefix=FUNCTION-NETBSD
+// RUN: %clang -target x86_64--netbsd -fsanitize=function %s -### 2>&1 | FileCheck %s -check-prefix=FUNCTION-NETBSD
+// FUNCTION-NETBSD: "-fsanitize=function"
+
// RUN: %clang -target i386--netbsd -fsanitize=vptr %s -### 2>&1 | FileCheck %s -check-prefix=VPTR-NETBSD
// RUN: %clang -target x86_64--netbsd -fsanitize=vptr %s -### 2>&1 | FileCheck %s -check-prefix=VPTR-NETBSD
// VPTR-NETBSD: "-fsanitize=vptr"
+// RUN: %clang -target x86_64--netbsd -fsanitize=dataflow %s -### 2>&1 | FileCheck %s -check-prefix=DATAFLOW-NETBSD
+// DATAFLOW-NETBSD: "-fsanitize=dataflow"
+
+// RUN: %clang -target i386--netbsd -fsanitize=cfi %s -### 2>&1 | FileCheck %s -check-prefix=CFI-NETBSD
+// RUN: %clang -target x86_64--netbsd -fsanitize=cfi %s -### 2>&1 | FileCheck %s -check-prefix=CFI-NETBSD
+// CFI-NETBSD: "-fsanitize=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
+
// RUN: %clang -target i386--netbsd -fsanitize=safe-stack %s -### 2>&1 | FileCheck %s -check-prefix=SAFESTACK-NETBSD
// RUN: %clang -target x86_64--netbsd -fsanitize=safe-stack %s -### 2>&1 | FileCheck %s -check-prefix=SAFESTACK-NETBSD
// SAFESTACK-NETBSD: "-fsanitize=safe-stack"
-// RUN: %clang -target i386--netbsd -fsanitize=function %s -### 2>&1 | FileCheck %s -check-prefix=FUNCTION-NETBSD
-// RUN: %clang -target x86_64--netbsd -fsanitize=function %s -### 2>&1 | FileCheck %s -check-prefix=FUNCTION-NETBSD
-// FUNCTION-NETBSD: "-fsanitize=function"
+// RUN: %clang -target x86_64--netbsd -fsanitize=shadow-call-stack %s -### 2>&1 | FileCheck %s -check-prefix=SHADOW-CALL-STACK-NETBSD
+// SHADOW-CALL-STACK-NETBSD: "-fsanitize=shadow-call-stack"
+
+// RUN: %clang -target i386--netbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s -check-prefix=UNDEFINED-NETBSD
+// RUN: %clang -target x86_64--netbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s -check-prefix=UNDEFINED-NETBSD
+// UNDEFINED-NETBSD: "-fsanitize={{.*}}
+
+// RUN: %clang -target i386--netbsd -fsanitize=scudo %s -### 2>&1 | FileCheck %s -check-prefix=SCUDO-NETBSD
+// RUN: %clang -target x86_64--netbsd -fsanitize=scudo %s -### 2>&1 | FileCheck %s -check-prefix=SCUDO-NETBSD
+// SCUDO-NETBSD: "-fsanitize=scudo"
-// RUN: %clang -target i386--netbsd -fsanitize=leak %s -### 2>&1 | FileCheck %s -check-prefix=LEAK-NETBSD
-// RUN: %clang -target x86_64--netbsd -fsanitize=leak %s -### 2>&1 | FileCheck %s -check-prefix=LEAK-NETBSD
-// LEAK-NETBSD: "-fsanitize=leak"
-// RUN: %clang -target x86_64--netbsd -fsanitize=thread %s -### 2>&1 | FileCheck %s -check-prefix=THREAD-NETBSD
-// THREAD-NETBSD: "-fsanitize=thread"
// RUN: %clang -target x86_64-scei-ps4 -fsanitize=function -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSAN-UBSAN-PS4
// CHECK-FSAN-UBSAN-PS4: unsupported option '-fsanitize=function' for target 'x86_64-scei-ps4'
@@ -651,6 +792,10 @@
// CHECK-ASAN-PS4: --dependent-lib=libSceDbgAddressSanitizer_stub_weak.a
// CHECK-ASAN-PS4-NOT: {{(\.(o|bc)"? |-l).*-lSceDbgAddressSanitizer_stub_weak}}
// CHECK-ASAN-PS4: -lSceDbgAddressSanitizer_stub_weak
+// RUN: %clang -target x86_64-scei-ps4 -fsanitize=address -nostdlib %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-NOLIB-PS4
+// RUN: %clang -target x86_64-scei-ps4 -fsanitize=address -nodefaultlibs %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-NOLIB-PS4
+// RUN: %clang -target x86_64-scei-ps4 -fsanitize=address -nodefaultlibs -nostdlib %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-NOLIB-PS4
+// CHECK-ASAN-NOLIB-PS4-NOT: SceDbgAddressSanitizer_stub_weak
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-MINIMAL
// CHECK-ASAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=address'
@@ -683,6 +828,10 @@
// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall"
// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-minimal-runtime"
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=shadow-call-stack -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCS-MINIMAL
+// CHECK-SCS-MINIMAL: "-fsanitize=shadow-call-stack"
+// CHECK-SCS-MINIMAL: "-fsanitize-minimal-runtime"
+
// RUN: %clang -target aarch64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
// RUN: %clang -target arm-linux-androideabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO
@@ -724,3 +873,14 @@
// CHECK-SCUDO-TSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=thread'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-HWASAN
// CHECK-SCUDO-HWASAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=hwaddress'
+//
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,kernel-memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-KMSAN
+// CHECK-SCUDO-KMSAN: error: invalid argument '-fsanitize=kernel-memory' not allowed with '-fsanitize=scudo'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-INTERCEPTOR-ABI
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-hwaddress-abi=interceptor %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-INTERCEPTOR-ABI
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-hwaddress-abi=platform %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-PLATFORM-ABI
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-hwaddress-abi=foo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-FOO-ABI
+// CHECK-HWASAN-INTERCEPTOR-ABI: "-default-function-attr" "hwasan-abi=interceptor"
+// CHECK-HWASAN-PLATFORM-ABI: "-default-function-attr" "hwasan-abi=platform"
+// CHECK-HWASAN-FOO-ABI: error: invalid value 'foo' in '-fsanitize-hwaddress-abi=foo'
diff --git a/test/Driver/fuchsia.c b/test/Driver/fuchsia.c
index fa5459962370..9c3ea53009bc 100644
--- a/test/Driver/fuchsia.c
+++ b/test/Driver/fuchsia.c
@@ -1,15 +1,16 @@
// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-fuchsia \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
-// RUN: --sysroot=%S/platform 2>&1 \
+// RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,CHECK-X86_64 %s
// RUN: %clang %s -### -no-canonical-prefixes --target=aarch64-fuchsia \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
-// RUN: --sysroot=%S/platform 2>&1 \
+// RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK,CHECK-AARCH64 %s
// CHECK: {{.*}}clang{{.*}}" "-cc1"
// CHECK: "--mrelax-relocations"
// CHECK: "-munwind-tables"
// CHECK: "-fuse-init-array"
+// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
// CHECK: "-fsanitize=safe-stack"
@@ -25,28 +26,28 @@
// CHECK-NOT: crti.o
// CHECK-NOT: crtbegin.o
// CHECK: "-L[[SYSROOT]]{{/|\\\\}}lib"
-// CHECK-X86_64: "{{.*[/\\]}}libclang_rt.builtins.a"
-// CHECK-AARCH64: "{{.*[/\\]}}libclang_rt.builtins.a"
+// CHECK-X86_64: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.builtins.a"
+// CHECK-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.builtins.a"
// CHECK: "-lc"
// CHECK-NOT: crtend.o
// CHECK-NOT: crtn.o
-// RUN: %clang %s -### --target=x86_64-fuchsia -rtlib=libgcc 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -rtlib=libgcc -fuse-ld=lld 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-RTLIB
// CHECK-RTLIB: error: invalid runtime library name in argument '-rtlib=libgcc'
-// RUN: %clang %s -### --target=x86_64-fuchsia -static 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -static -fuse-ld=lld 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
// CHECK-STATIC: "-Bstatic"
// CHECK-STATIC: "-Bdynamic"
// CHECK-STATIC: "-lc"
-// RUN: %clang %s -### --target=x86_64-fuchsia -shared 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -shared -fuse-ld=lld 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-SHARED
// CHECK-SHARED-NOT: "-pie"
// CHECK-SHARED: "-shared"
-// RUN: %clang %s -### --target=x86_64-fuchsia -r 2>&1 \
+// RUN: %clang %s -### --target=x86_64-fuchsia -r -fuse-ld=lld 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE
// CHECK-RELOCATABLE-NOT: "-pie"
// CHECK-RELOCATABLE-NOT: "--build-id"
@@ -55,86 +56,135 @@
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=safe-stack 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-SAFESTACK
+// CHECK-SAFESTACK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-SAFESTACK: "-fsanitize=safe-stack"
-// CHECK-SAFESTACK-NOT: "{{.*[/\\]}}libclang_rt.safestack.a"
+// CHECK-SAFESTACK-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.safestack.a"
// CHECK-SAFESTACK-NOT: "__safestack_init"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=address 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-X86
+// CHECK-ASAN-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-ASAN-X86: "-fsanitize=address"
// CHECK-ASAN-X86: "-fsanitize-address-globals-dead-stripping"
// CHECK-ASAN-X86: "-dynamic-linker" "asan/ld.so.1"
-// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan.so"
-// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan-preinit.a"
+// CHECK-ASAN-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}asan"
+// CHECK-ASAN-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib"
+// CHECK-ASAN-X86: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.asan.so"
+// CHECK-ASAN-X86: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.asan-preinit.a"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -fsanitize=address 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-AARCH64
+// CHECK-ASAN-AARCH64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-ASAN-AARCH64: "-fsanitize=address"
// CHECK-ASAN-AARCH64: "-fsanitize-address-globals-dead-stripping"
// CHECK-ASAN-AARCH64: "-dynamic-linker" "asan/ld.so.1"
-// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan.so"
-// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan-preinit.a"
+// CHECK-ASAN-AARCH64: "-L[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}asan"
+// CHECK-ASAN-AARCH64: "-L[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib"
+// CHECK-ASAN-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.asan.so"
+// CHECK-ASAN-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.asan-preinit.a"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=address -fPIC -shared 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-SHARED
+// CHECK-ASAN-SHARED: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-ASAN-SHARED: "-fsanitize=address"
// CHECK-ASAN-SHARED: "-fsanitize-address-globals-dead-stripping"
-// CHECK-ASAN-SHARED: "{{.*[/\\]}}libclang_rt.asan.so"
-// CHECK-ASAN-SHARED-NOT: "{{.*[/\\]}}libclang_rt.asan-preinit.a"
+// CHECK-ASAN-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.asan.so"
+// CHECK-ASAN-SHARED-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.asan-preinit.a"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=fuzzer 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-X86
+// CHECK-FUZZER-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-FUZZER-X86: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack"
-// CHECK-FUZZER-X86: "{{.*[/\\]}}libclang_rt.fuzzer.a"
+// CHECK-FUZZER-X86: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.fuzzer.a"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -fsanitize=fuzzer 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-AARCH64
+// CHECK-FUZZER-AARCH64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-FUZZER-AARCH64: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack"
-// CHECK-FUZZER-AARCH64: "{{.*[/\\]}}libclang_rt.fuzzer.a"
+// CHECK-FUZZER-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.fuzzer.a"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=scudo 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-X86
+// CHECK-SCUDO-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-SCUDO-X86: "-fsanitize=safe-stack,scudo"
// CHECK-SCUDO-X86: "-pie"
-// CHECK-SCUDO-X86: "{{.*[/\\]}}libclang_rt.scudo.so"
+// CHECK-SCUDO-X86: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.scudo.so"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -fsanitize=scudo 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-AARCH64
+// CHECK-SCUDO-AARCH64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-SCUDO-AARCH64: "-fsanitize=safe-stack,scudo"
// CHECK-SCUDO-AARCH64: "-pie"
-// CHECK-SCUDO-AARCH64: "{{.*[/\\]}}libclang_rt.scudo.so"
+// CHECK-SCUDO-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.scudo.so"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -fsanitize=scudo -fPIC -shared 2>&1 \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED
+// CHECK-SCUDO-SHARED: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-SCUDO-SHARED: "-fsanitize=safe-stack,scudo"
-// CHECK-SCUDO-SHARED: "{{.*[/\\]}}libclang_rt.scudo.so"
+// CHECK-SCUDO-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.scudo.so"
+
+// RUN: %clang %s -### --target=x86_64-fuchsia \
+// RUN: -fxray-instrument -fxray-modes=xray-basic \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-XRAY-X86
+// CHECK-XRAY-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-XRAY-X86: "-fxray-instrument"
+// CHECK-XRAY-X86: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.xray.a"
+// CHECK-XRAY-X86: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.xray-basic.a"
+
+// RUN: %clang %s -### --target=aarch64-fuchsia \
+// RUN: -fxray-instrument -fxray-modes=xray-basic \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -fuse-ld=lld 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-XRAY-AARCH64
+// CHECK-XRAY-AARCH64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-XRAY-AARCH64: "-fxray-instrument"
+// CHECK-XRAY-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.xray.a"
+// CHECK-XRAY-AARCH64: "[[RESOURCE_DIR]]{{/|\\\\}}aarch64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.xray-basic.a"
// RUN: %clang %s -### --target=aarch64-fuchsia \
// RUN: -O3 -flto -mcpu=cortex-a53 2>&1 \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-LTO
// CHECK-LTO: "-plugin-opt=mcpu=cortex-a53"
// CHECK-LTO: "-plugin-opt=O3"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -flto=thin -flto-jobs=8 2>&1 \
+// RUN: -fuse-ld=lld \
// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO
// CHECK-THINLTO: "-plugin-opt=mcpu=x86-64"
// CHECK-THINLTO: "-plugin-opt=thinlto"
// CHECK-THINLTO: "-plugin-opt=jobs=8"
+
+// RUN: %clang %s -### --target=x86_64-fuchsia \
+// RUN: -gsplit-dwarf -c %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-SPLIT-DWARF
+// CHECK-SPLIT-DWARF: "-split-dwarf-file" "fuchsia.dwo"
diff --git a/test/Driver/fuchsia.cpp b/test/Driver/fuchsia.cpp
index 83b18752260c..2c80ad070378 100644
--- a/test/Driver/fuchsia.cpp
+++ b/test/Driver/fuchsia.cpp
@@ -1,8 +1,10 @@
-// RUN: %clangxx %s -### -no-canonical-prefixes --target=x86_64-unknown-fuchsia \
-// RUN: --sysroot=%S/platform 2>&1 | FileCheck %s
+// RUN: %clangxx %s -### -no-canonical-prefixes --target=x86_64-fuchsia \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 | FileCheck %s
// CHECK: {{.*}}clang{{.*}}" "-cc1"
// CHECK: "-triple" "x86_64-fuchsia"
// CHECK: "-fuse-init-array"
+// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK: "-internal-isystem" "{{.*[/\\]}}include{{/|\\\\}}c++{{/|\\\\}}v1"
// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
@@ -15,20 +17,29 @@
// CHECK-NOT: crti.o
// CHECK-NOT: crtbegin.o
// CHECK: "-L[[SYSROOT]]{{/|\\\\}}lib"
-// CHECK: "-lc++" "-lm"
-// CHECK: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a"
+// CHECK: "--push-state"
+// CHECK: "--as-needed"
+// CHECK: "-lc++"
+// CHECK: "-lm"
+// CHECK: "--pop-state"
+// CHECK: "[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}libclang_rt.builtins.a"
// CHECK: "-lc"
// CHECK-NOT: crtend.o
// CHECK-NOT: crtn.o
-// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -stdlib=libstdc++ 2>&1 \
+// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -stdlib=libstdc++ \
+// RUN: -fuse-ld=lld 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STDLIB
// CHECK-STDLIB: error: invalid library name in argument '-stdlib=libstdc++'
-// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -static-libstdc++ 2>&1 \
+// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -static-libstdc++ \
+// RUN: -fuse-ld=lld 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
+// CHECK-STATIC: "--push-state"
+// CHECK-STATIC: "--as-needed"
// CHECK-STATIC: "-Bstatic"
// CHECK-STATIC: "-lc++"
// CHECK-STATIC: "-Bdynamic"
// CHECK-STATIC: "-lm"
+// CHECK-STATIC: "--pop-state"
// CHECK-STATIC: "-lc"
diff --git a/test/Driver/gcodeview-ghash.c b/test/Driver/gcodeview-ghash.c
new file mode 100644
index 000000000000..c45c8296604e
--- /dev/null
+++ b/test/Driver/gcodeview-ghash.c
@@ -0,0 +1,19 @@
+// Note: %s must be preceded by --, otherwise it may be interpreted as a
+// command-line option, e.g. on Mac where %s is commonly under /Users.
+
+// GHASH: "-gcodeview-ghash"
+// NO_GHASH-NOT: "-gcodeview-ghash"
+
+// default
+// RUN: %clang_cl /Z7 -### -- %s 2>&1 | FileCheck -check-prefix=NO_GHASH %s
+// enabled
+// RUN: %clang_cl /Z7 -gcodeview-ghash -### -- %s 2>&1 | FileCheck -check-prefix=GHASH %s
+// disabled
+// RUN: %clang_cl /Z7 -gcodeview-ghash -gno-codeview-ghash -### -- %s 2>&1 | FileCheck -check-prefix=NO_GHASH %s
+
+// enabled, no /Z7
+// RUN: %clang_cl -gcodeview-ghash -### -- %s 2>&1 | FileCheck -check-prefix=NO_GHASH %s
+
+// GCC-style driver
+// RUN: %clang -g -gcodeview -gcodeview-ghash -### -- %s 2>&1 | FileCheck -check-prefix=GHASH %s
+// RUN: %clang -g -gcodeview -gcodeview-ghash -gno-codeview-ghash -### -- %s 2>&1 | FileCheck -check-prefix=NO_GHASH %s
diff --git a/test/Driver/header-module.cpp b/test/Driver/header-module.cpp
new file mode 100644
index 000000000000..9a6ba5b108fc
--- /dev/null
+++ b/test/Driver/header-module.cpp
@@ -0,0 +1,24 @@
+// Check compiling a header module to a .pcm file.
+//
+// RUN: %clang -fmodules-ts -fmodule-name=foobar -x c++-header --precompile %S/Inputs/header1.h %S/Inputs/header2.h %S/Inputs/header3.h -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
+//
+// CHECK-PRECOMPILE: -cc1 {{.*}} -emit-header-module
+// CHECK-PRECOMPILE-SAME: -fmodules-ts
+// CHECK-PRECOMPILE-SAME: -fno-implicit-modules
+// CHECK-PRECOMPILE-SAME: -fmodule-name=foobar
+// CHECK-PRECOMPILE-SAME: -o {{.*}}.pcm
+// CHECK-PRECOMPILE-SAME: -x c++-header
+// CHECK-PRECOMPILE-SAME: header1.h
+// CHECK-PRECOMPILE-SAME: header2.h
+// CHECK-PRECOMPILE-SAME: header3.h
+//
+// RUN: %clang -fmodules-ts -fmodule-name=foobar -x c++-header -fsyntax-only %S/Inputs/header1.h %S/Inputs/header2.h %S/Inputs/header3.h -v 2>&1 | FileCheck %s --check-prefix=CHECK-SYNTAX-ONLY
+// CHECK-SYNTAX-ONLY: -cc1 {{.*}} -fsyntax-only
+// CHECK-SYNTAX-ONLY-SAME: -fmodules-ts
+// CHECK-SYNTAX-ONLY-SAME: -fno-implicit-modules
+// CHECK-SYNTAX-ONLY-SAME: -fmodule-name=foobar
+// CHECK-SYNTAX-ONLY-NOT: -o{{ }}
+// CHECK-SYNTAX-ONLY-SAME: -x c++-header
+// CHECK-SYNTAX-ONLY-SAME: header1.h
+// CHECK-SYNTAX-ONLY-SAME: header2.h
+// CHECK-SYNTAX-ONLY-SAME: header3.h
diff --git a/test/Driver/hexagon-hvx.c b/test/Driver/hexagon-hvx.c
index 70699ce3df52..4642aef81a31 100644
--- a/test/Driver/hexagon-hvx.c
+++ b/test/Driver/hexagon-hvx.c
@@ -2,6 +2,10 @@
// Tests for the hvx features and warnings.
// -----------------------------------------------------------------------------
+// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv66 -mhvx \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECKHVX166 %s
+// CHECKHVX166: "-target-feature" "+hvxv66"
+
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv65 -mhvx \
// RUN: 2>&1 | FileCheck -check-prefix=CHECKHVX165 %s
// CHECKHVX165: "-target-feature" "+hvxv65"
@@ -69,6 +73,9 @@
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv60 -mhvx \
// RUN: -mhvx-length=64B 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-64B %s
// CHECK-HVXLENGTH-64B: "-target-feature" "+hvx{{.*}}" "-target-feature" "+hvx-length64b"
+// The default mode on v66 and future archs is 128B.
+// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv66 -mhvx \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-128B %s
// RUN: %clang -c %s -### -target hexagon-unknown-elf -mv62 -mhvx -mhvx-length=128B\
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-HVXLENGTH-128B %s
// CHECK-HVXLENGTH-128B: "-target-feature" "+hvx{{.*}}" "-target-feature" "+hvx-length128b"
diff --git a/test/Driver/hexagon-toolchain-elf.c b/test/Driver/hexagon-toolchain-elf.c
index 8f4c320ce45b..a7eeca0fdb12 100644
--- a/test/Driver/hexagon-toolchain-elf.c
+++ b/test/Driver/hexagon-toolchain-elf.c
@@ -59,19 +59,11 @@
// -----------------------------------------------------------------------------
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
-// RUN: -mcpu=hexagonv4 \
-// RUN: %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK020 %s
-// CHECK020: "-cc1" {{.*}} "-target-cpu" "hexagonv4"
-// CHECK020: hexagon-link{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v4/crt0
-
-// RUN: %clang -### -target hexagon-unknown-elf \
-// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
// RUN: -mcpu=hexagonv5 \
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK021 %s
// CHECK021: "-cc1" {{.*}} "-target-cpu" "hexagonv5"
-// CHECK021: hexagon-link{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v5/crt0
+// CHECK021: {{hexagon-link|ld}}{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v5/crt0
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
@@ -79,7 +71,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK022 %s
// CHECK022: "-cc1" {{.*}} "-target-cpu" "hexagonv55"
-// CHECK022: hexagon-link{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v55/crt0
+// CHECK022: {{hexagon-link|ld}}{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v55/crt0
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
@@ -87,7 +79,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK023 %s
// CHECK023: "-cc1" {{.*}} "-target-cpu" "hexagonv60"
-// CHECK023: hexagon-link{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0
+// CHECK023: {{hexagon-link|ld}}{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
@@ -95,7 +87,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK024 %s
// CHECK024: "-cc1" {{.*}} "-target-cpu" "hexagonv62"
-// CHECK024: hexagon-link{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v62/crt0
+// CHECK024: {{hexagon-link|ld}}{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v62/crt0
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
@@ -103,23 +95,31 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK025 %s
// CHECK025: "-cc1" {{.*}} "-target-cpu" "hexagonv65"
-// CHECK025: hexagon-link{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v65/crt0
+// CHECK025: {{hexagon-link|ld}}{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v65/crt0
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
-// RUN: -O3 \
+// RUN: -mcpu=hexagonv66 \
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK026 %s
-// CHECK026: "-ffp-contract=fast"
-// CHECK026: hexagon-link
+// CHECK026: "-cc1" {{.*}} "-target-cpu" "hexagonv66"
+// CHECK026: {{hexagon-link|ld}}{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v66/crt0
// RUN: %clang -### -target hexagon-unknown-elf \
// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
-// RUN: -O3 -ffp-contract=off \
+// RUN: -O3 \
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK027 %s
// CHECK027-NOT: "-ffp-contract=fast"
-// CHECK027: hexagon-link
+// CHECK027: {{hexagon-link|ld}}
+
+// RUN: %clang -### -target hexagon-unknown-elf \
+// RUN: -ccc-install-dir %S/Inputs/hexagon_tree/Tools/bin \
+// RUN: -O3 -ffp-contract=off \
+// RUN: %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK028 %s
+// CHECK028-NOT: "-ffp-contract=fast"
+// CHECK028: {{hexagon-link|ld}}
// -----------------------------------------------------------------------------
// Test Linker related args
@@ -134,7 +134,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK030 %s
// CHECK030: "-cc1"
-// CHECK030-NEXT: hexagon-link
+// CHECK030: {{hexagon-link|ld}}
// CHECK030-NOT: "-static"
// CHECK030-NOT: "-shared"
// CHECK030: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0_standalone.o"
@@ -155,7 +155,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK031 %s
// CHECK031: "-cc1"
-// CHECK031-NEXT: hexagon-link
+// CHECK031: {{hexagon-link|ld}}
// CHECK031-NOT: "-static"
// CHECK031-NOT: "-shared"
// CHECK031: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0_standalone.o"
@@ -178,7 +178,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK032 %s
// CHECK032: "-cc1"
-// CHECK032-NEXT: hexagon-link
+// CHECK032: {{hexagon-link|ld}}
// CHECK032-NOT: "-static"
// CHECK032-NOT: "-shared"
// CHECK032: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0_standalone.o"
@@ -201,7 +201,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK033 %s
// CHECK033: "-cc1"
-// CHECK033-NEXT: hexagon-link
+// CHECK033: {{hexagon-link|ld}}
// CHECK033: "-static"
// CHECK033: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0_standalone.o"
// CHECK033: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0.o"
@@ -219,7 +219,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK034 %s
// CHECK034: "-cc1"
-// CHECK034-NEXT: hexagon-link
+// CHECK034: {{hexagon-link|ld}}
// CHECK034: "-shared" "-call_shared"
// CHECK034-NOT: crt0_standalone.o
// CHECK034-NOT: crt0.o
@@ -243,7 +243,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK035 %s
// CHECK035: "-cc1"
-// CHECK035-NEXT: hexagon-link
+// CHECK035: {{hexagon-link|ld}}
// CHECK035: "-shared" "-call_shared" "-static"
// CHECK035-NOT: crt0_standalone.o
// CHECK035-NOT: crt0.o
@@ -269,7 +269,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK036 %s
// CHECK036: "-cc1"
-// CHECK036-NEXT: hexagon-link
+// CHECK036: {{hexagon-link|ld}}
// CHECK036-NOT: crt0_standalone.o
// CHECK036-NOT: crt0.o
// CHECK036-NOT: init.o
@@ -292,7 +292,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK037 %s
// CHECK037: "-cc1"
-// CHECK037-NEXT: hexagon-link
+// CHECK037: {{hexagon-link|ld}}
// CHECK037-NOT: crt0_standalone.o
// CHECK037-NOT: crt0.o
// CHECK037-NOT: init.o
@@ -315,7 +315,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK038 %s
// CHECK038: "-cc1"
-// CHECK038-NEXT: hexagon-link
+// CHECK038: {{hexagon-link|ld}}
// CHECK038: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0_standalone.o"
// CHECK038: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0.o"
// CHECK038: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/init.o"
@@ -341,7 +341,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK039 %s
// CHECK039: "-cc1"
-// CHECK039-NEXT: hexagon-link
+// CHECK039: {{hexagon-link|ld}}
// CHECK039-NOT: "-static"
// CHECK039-NOT: "-shared"
// CHECK039-NOT: crt0_standalone.o
@@ -363,7 +363,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK03A %s
// CHECK03A: "-cc1"
-// CHECK03A-NEXT: hexagon-link
+// CHECK03A: {{hexagon-link|ld}}
// CHECK03A-NOT: "-static"
// CHECK03A-NOT: "-shared"
// CHECK03A: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0_standalone.o"
@@ -392,7 +392,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK03B %s
// CHECK03B: "-cc1"
-// CHECK03B-NEXT: hexagon-link
+// CHECK03B: {{hexagon-link|ld}}
// CHECK03B: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0_standalone.o"
// CHECK03B: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/crt0.o"
// CHECK03B: "{{.*}}/Inputs/hexagon_tree/Tools/bin/../target/hexagon/lib/v60/init.o"
@@ -416,7 +416,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK040 %s
// CHECK040: "-cc1"
-// CHECK040-NEXT: hexagon-link
+// CHECK040: {{hexagon-link|ld}}
// CHECK040-NOT: "-G{{[0-9]+}}"
// RUN: %clang -### -target hexagon-unknown-elf \
@@ -435,7 +435,7 @@
// CHECK041-NOT: "-mrelocation-model" "static"
// CHECK041: "-pic-level" "{{[12]}}"
// CHECK041: "-mllvm" "-hexagon-small-data-threshold=0"
-// CHECK041-NEXT: hexagon-link
+// CHECK041: {{hexagon-link|ld}}
// CHECK041: "-G0"
// RUN: %clang -### -target hexagon-unknown-elf -fno-integrated-as \
@@ -461,7 +461,7 @@
// CHECK042: "-mllvm" "-hexagon-small-data-threshold=8"
// CHECK042-NEXT: llvm-mc
// CHECK042: "-gpsize=8"
-// CHECK042-NEXT: hexagon-link
+// CHECK042: {{hexagon-link|ld}}
// CHECK042: "-G8"
// -----------------------------------------------------------------------------
@@ -474,7 +474,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK050 %s
// CHECK050: "-cc1"
-// CHECK050-NEXT: hexagon-link
+// CHECK050: {{hexagon-link|ld}}
// CHECK050: "-pie"
// RUN: %clang -### -target hexagon-unknown-elf \
@@ -484,7 +484,7 @@
// RUN: %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK051 %s
// CHECK051: "-cc1"
-// CHECK051-NEXT: hexagon-link
+// CHECK051 {{hexagon-link|ld}}
// CHECK051-NOT: "-pie"
// -----------------------------------------------------------------------------
@@ -501,7 +501,7 @@
// CHECK060: "-cc1"
// CHECK060-NEXT: llvm-mc
// CHECK060: "--noexecstack" "--trap" "--keep-locals"
-// CHECK060-NEXT: hexagon-link
+// CHECK060 {{hexagon-link|ld}}
// -----------------------------------------------------------------------------
// ffixed-r19
diff --git a/test/Driver/hip-binding.hip b/test/Driver/hip-binding.hip
index c08cc6736211..5425bf651a7e 100644
--- a/test/Driver/hip-binding.hip
+++ b/test/Driver/hip-binding.hip
@@ -12,4 +12,4 @@
// CHECK-NOT: offload bundler
// CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ3]]"], output: "[[IMG3:.*out]]"
// CHECK-NOT: offload bundler
-// CHECK: # "x86_64--linux-gnu" - "GNU::Linker", inputs: ["[[OBJ1]]", "[[IMG2]]", "[[IMG3]]"], output: "a.out"
+// CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[OBJ1]]", "[[IMG2]]", "[[IMG3]]"], output: "a.out"
diff --git a/test/Driver/hip-device-libs.hip b/test/Driver/hip-device-libs.hip
index 04afab1b73ad..3a7e7fd7dfc5 100644
--- a/test/Driver/hip-device-libs.hip
+++ b/test/Driver/hip-device-libs.hip
@@ -21,7 +21,8 @@
// COM: [[LLVM_LINK:"*.llvm-link"]]
-// COM-SAME: {{.*}} "{{.*}}ocml.amdgcn.bc" "{{.*}}ockl.amdgcn.bc" "{{.*}}irif.amdgcn.bc"
+// COM-SAME: "{{.*}}hip.amdgcn.bc" "{{.*}}opencl.amdgcn.bc"
+// COM-SAME: "{{.*}}ocml.amdgcn.bc" "{{.*}}ockl.amdgcn.bc"
// FLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_on.amdgcn.bc"
// NOFLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_off.amdgcn.bc"
// COM-SAME: {{.*}} "-o" "{{.*}}-gfx900-linked-{{.*bc}}"
diff --git a/test/Driver/hip-link-shared-library.hip b/test/Driver/hip-link-shared-library.hip
new file mode 100644
index 000000000000..b7b301a9e391
--- /dev/null
+++ b/test/Driver/hip-link-shared-library.hip
@@ -0,0 +1,12 @@
+// RUN: touch %t.o
+// RUN: %clang --hip-link -ccc-print-bindings -target x86_64-linux-gnu \
+// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o %S/Inputs/in.so \
+// RUN: 2>&1 | FileCheck %s
+
+// CHECK: # "amdgcn-amd-amdhsa" - "offload bundler", inputs: ["[[IN:.*o]]"], outputs: ["[[OBJ1:.*o]]", "[[OBJ2:.*o]]", "[[OBJ3:.*o]]"]
+// CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ2]]"], output: "[[IMG2:.*out]]"
+// CHECK-NOT: offload bundler
+// CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ3]]"], output: "[[IMG3:.*out]]"
+// CHECK-NOT: offload bundler
+// CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[OBJ1]]", "{{.*}}/Inputs/in.so", "[[IMG2]]", "[[IMG3]]"], output: "a.out"
+
diff --git a/test/Driver/hip-output-file-name.hip b/test/Driver/hip-output-file-name.hip
new file mode 100644
index 000000000000..cce9f76406ee
--- /dev/null
+++ b/test/Driver/hip-output-file-name.hip
@@ -0,0 +1,9 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: amdgpu-registered-target
+
+// RUN: %clang -### -c -target x86_64-linux-gnu -fgpu-rdc \
+// RUN: -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
+// RUN: 2>&1 | FileCheck %s
+
+// CHECK: {{.*}}clang-offload-bundler{{.*}}"-outputs=hip-output-file-name.o"
diff --git a/test/Driver/hip-toolchain-no-rdc.hip b/test/Driver/hip-toolchain-no-rdc.hip
new file mode 100644
index 000000000000..4f31a39a72b9
--- /dev/null
+++ b/test/Driver/hip-toolchain-no-rdc.hip
@@ -0,0 +1,158 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: amdgpu-registered-target
+
+// RUN: %clang -### -target x86_64-linux-gnu -fno-gpu-rdc \
+// RUN: -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
+// RUN: --hip-device-lib=lib1.bc --hip-device-lib=lib2.bc \
+// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
+// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib2 \
+// RUN: -fuse-ld=lld \
+// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
+// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
+// RUN: 2>&1 | FileCheck -check-prefixes=CHECK %s
+
+//
+// Compile device code in a.cu to code object for gfx803.
+//
+
+// CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx803"
+// CHECK-SAME: "-fcuda-is-device" "-fvisibility" "hidden"
+// CHECK-SAME: {{.*}} "-o" [[A_BC_803:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[A_SRC:".*a.cu"]]
+
+// CHECK: [[LLVM_LINK:"*.llvm-link"]] [[A_BC_803]]
+// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
+// CHECK-SAME: "-o" [[LINKED_BC_DEV_A_803:".*-gfx803-linked-.*bc"]]
+
+// CHECK: [[OPT:".*opt"]] [[LINKED_BC_DEV_A_803]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-mcpu=gfx803"
+// CHECK-SAME: "-o" [[OPT_BC_DEV_A_803:".*-gfx803-optimized.*bc"]]
+
+// CHECK: [[LLC: ".*llc"]] [[OPT_BC_DEV_A_803]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-filetype=obj"
+// CHECK-SAME: "-mattr=-code-object-v3"
+// CHECK-SAME: "-mcpu=gfx803" "-o" [[OBJ_DEV_A_803:".*-gfx803-.*o"]]
+
+// CHECK: [[LLD: ".*lld"]] "-flavor" "gnu" "--no-undefined" "-shared"
+// CHECK-SAME: "-o" "[[IMG_DEV_A_803:.*out]]" [[OBJ_DEV_A_803]]
+
+//
+// Compile device code in a.cu to code object for gfx900.
+//
+
+// CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx900"
+// CHECK-SAME: "-fcuda-is-device" "-fvisibility" "hidden"
+// CHECK-SAME: {{.*}} "-o" [[A_BC_900:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[A_SRC]]
+
+// CHECK: [[LLVM_LINK:"*.llvm-link"]] [[A_BC_900]]
+// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
+// CHECK-SAME: "-o" [[LINKED_BC_DEV_A_900:".*-gfx900-linked-.*bc"]]
+
+// CHECK: [[OPT:".*opt"]] [[LINKED_BC_DEV_A_900]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-mcpu=gfx900"
+// CHECK-SAME: "-o" [[OPT_BC_DEV_A_900:".*-gfx900-optimized.*bc"]]
+
+// CHECK: [[LLC: ".*llc"]] [[OPT_BC_DEV_A_900]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-filetype=obj"
+// CHECK-SAME: "-mattr=-code-object-v3"
+// CHECK-SAME: "-mcpu=gfx900" "-o" [[OBJ_DEV_A_900:".*-gfx900-.*o"]]
+
+// CHECK: [[LLD: ".*lld"]] "-flavor" "gnu" "--no-undefined" "-shared"
+// CHECK-SAME: "-o" "[[IMG_DEV_A_900:.*out]]" [[OBJ_DEV_A_900]]
+
+//
+// Bundle and embed device code in host object for a.cu.
+//
+
+// CHECK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
+// CHECK-SAME: "-targets={{.*}},hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
+// CHECK-SAME: "-inputs={{.*}},[[IMG_DEV_A_803]],[[IMG_DEV_A_900]]" "-outputs=[[BUNDLE_A:.*hipfb]]"
+
+// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64-unknown-linux-gnu"
+// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
+// CHECK-SAME: {{.*}} "-main-file-name" "a.cu"
+// CHECK-SAME: {{.*}} "-o" [[A_OBJ_HOST:".*o"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[A_SRC]]
+// CHECK-SAME: {{.*}} "-fcuda-include-gpubinary" "[[BUNDLE_A]]"
+
+//
+// Compile device code in b.hip to code object for gfx803.
+//
+
+// CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx803"
+// CHECK-SAME: "-fcuda-is-device" "-fvisibility" "hidden"
+// CHECK-SAME: {{.*}} "-o" [[B_BC_803:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[B_SRC:".*b.hip"]]
+
+// CHECK: [[LLVM_LINK:"*.llvm-link"]] [[B_BC_803]]
+// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
+// CHECK-SAME: "-o" [[LINKED_BC_DEV_B_803:".*-gfx803-linked-.*bc"]]
+
+// CHECK: [[OPT:".*opt"]] [[LINKED_BC_DEV_B_803]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-mcpu=gfx803"
+// CHECK-SAME: "-o" [[OPT_BC_DEV_B_803:".*-gfx803-optimized.*bc"]]
+
+// CHECK: [[LLC: ".*llc"]] [[OPT_BC_DEV_B_803]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-filetype=obj"
+// CHECK-SAME: "-mattr=-code-object-v3"
+// CHECK-SAME: "-mcpu=gfx803" "-o" [[OBJ_DEV_B_803:".*-gfx803-.*o"]]
+
+// CHECK: [[LLD: ".*lld"]] "-flavor" "gnu" "--no-undefined" "-shared"
+// CHECK-SAME: "-o" "[[IMG_DEV_B_803:.*out]]" [[OBJ_DEV_B_803]]
+
+//
+// Compile device code in b.hip to code object for gfx900.
+//
+
+// CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx900"
+// CHECK-SAME: "-fcuda-is-device" "-fvisibility" "hidden"
+// CHECK-SAME: {{.*}} "-o" [[B_BC_900:".*bc"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[B_SRC]]
+
+// CHECK: [[LLVM_LINK:"*.llvm-link"]] [[B_BC_900]]
+// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
+// CHECK-SAME: "-o" [[LINKED_BC_DEV_B_900:".*-gfx900-linked-.*bc"]]
+
+// CHECK: [[OPT:".*opt"]] [[LINKED_BC_DEV_B_900]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-mcpu=gfx900"
+// CHECK-SAME: "-o" [[OPT_BC_DEV_B_900:".*-gfx900-optimized.*bc"]]
+
+// CHECK: [[LLC: ".*llc"]] [[OPT_BC_DEV_B_900]] "-mtriple=amdgcn-amd-amdhsa"
+// CHECK-SAME: "-filetype=obj"
+// CHECK-SAME: "-mattr=-code-object-v3"
+// CHECK-SAME: "-mcpu=gfx900" "-o" [[OBJ_DEV_B_900:".*-gfx900-.*o"]]
+
+// CHECK: [[LLD: ".*lld"]] "-flavor" "gnu" "--no-undefined" "-shared"
+// CHECK-SAME: "-o" "[[IMG_DEV_B_900:.*out]]" [[OBJ_DEV_B_900]]
+
+//
+// Bundle and embed device code in host object for b.hip.
+//
+
+// CHECK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
+// CHECK-SAME: "-targets={{.*}},hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
+// CHECK-SAME: "-inputs={{.*}},[[IMG_DEV_B_803]],[[IMG_DEV_B_900]]" "-outputs=[[BUNDLE_A:.*hipfb]]"
+
+// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64-unknown-linux-gnu"
+// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
+// CHECK-SAME: {{.*}} "-main-file-name" "b.hip"
+// CHECK-SAME: {{.*}} "-o" [[B_OBJ_HOST:".*o"]] "-x" "hip"
+// CHECK-SAME: {{.*}} [[B_SRC]]
+// CHECK-SAME: {{.*}} "-fcuda-include-gpubinary" "[[BUNDLE_A]]"
+
+//
+// Link host objects.
+//
+
+// CHECK: [[LD:".*ld.*"]] {{.*}} [[A_OBJ_HOST]] [[B_OBJ_HOST]]
+// CHECK-NOT: "-T" "{{.*}}.lk"
diff --git a/test/Driver/hip-toolchain.hip b/test/Driver/hip-toolchain-rdc.hip
index ce24e0b4bee8..5f3fd9250b6c 100644
--- a/test/Driver/hip-toolchain.hip
+++ b/test/Driver/hip-toolchain-rdc.hip
@@ -7,21 +7,23 @@
// RUN: --hip-device-lib=lib1.bc --hip-device-lib=lib2.bc \
// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib2 \
-// RUN: -fuse-ld=lld \
+// RUN: -fuse-ld=lld -fgpu-rdc \
// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
// RUN: 2>&1 | FileCheck %s
// CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
-// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx803"
-// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip"
+// CHECK-SAME: "-fcuda-is-device" "-fgpu-rdc" "-fvisibility" "hidden"
+// CHECK-SAME: {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip"
// CHECK-SAME: {{.*}} [[A_SRC:".*a.cu"]]
// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
-// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx803"
-// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip"
+// CHECK-SAME: "-fcuda-is-device" "-fgpu-rdc" "-fvisibility" "hidden"
+// CHECK-SAME: {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip"
// CHECK-SAME: {{.*}} [[B_SRC:".*b.hip"]]
// CHECK: [[LLVM_LINK:"*.llvm-link"]] [[A_BC]] [[B_BC]]
@@ -33,19 +35,21 @@
// CHECK-SAME: "-o" [[OPT_BC_DEV1:".*-gfx803-optimized.*bc"]]
// CHECK: [[LLC: ".*llc"]] [[OPT_BC_DEV1]] "-mtriple=amdgcn-amd-amdhsa"
-// CHECK-SAME: "-filetype=obj" "-mcpu=gfx803" "-o" [[OBJ_DEV1:".*-gfx803-.*o"]]
+// CHECK-SAME: "-filetype=obj"
+// CHECK-SAME: "-mattr=-code-object-v3"
+// CHECK-SAME: "-mcpu=gfx803" "-o" [[OBJ_DEV1:".*-gfx803-.*o"]]
// CHECK: [[LLD: ".*lld"]] "-flavor" "gnu" "--no-undefined" "-shared"
// CHECK-SAME: "-o" "[[IMG_DEV1:.*out]]" [[OBJ_DEV1]]
// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
-// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx900"
// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip"
// CHECK-SAME: {{.*}} [[A_SRC]]
// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
-// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
+// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" "-emit-llvm-bc"
// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx900"
// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip"
// CHECK-SAME: {{.*}} [[B_SRC]]
@@ -59,18 +63,20 @@
// CHECK-SAME: "-o" [[OPT_BC_DEV2:".*-gfx900-optimized.*bc"]]
// CHECK: [[LLC]] [[OPT_BC_DEV2]] "-mtriple=amdgcn-amd-amdhsa"
-// CHECK-SAME: "-filetype=obj" "-mcpu=gfx900" "-o" [[OBJ_DEV2:".*-gfx900-.*o"]]
+// CHECK-SAME: "-filetype=obj"
+// CHECK-SAME: "-mattr=-code-object-v3"
+// CHECK-SAME: "-mcpu=gfx900" "-o" [[OBJ_DEV2:".*-gfx900-.*o"]]
// CHECK: [[LLD]] "-flavor" "gnu" "--no-undefined" "-shared"
// CHECK-SAME: "-o" "[[IMG_DEV2:.*out]]" [[OBJ_DEV2]]
-// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64--linux-gnu"
+// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
// CHECK-SAME: {{.*}} "-main-file-name" "a.cu"
// CHECK-SAME: {{.*}} "-o" [[A_OBJ_HOST:".*o"]] "-x" "hip"
// CHECK-SAME: {{.*}} [[A_SRC]]
-// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64--linux-gnu"
+// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
// CHECK-SAME: {{.*}} "-main-file-name" "b.hip"
// CHECK-SAME: {{.*}} "-o" [[B_OBJ_HOST:".*o"]] "-x" "hip"
@@ -78,7 +84,7 @@
// CHECK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
// CHECK-SAME: "-targets={{.*}},hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
-// CHECK-SAME: "-inputs={{.*}},[[IMG_DEV1]],[[IMG_DEV2]]" "-outputs=[[BUNDLE:.*o]]"
+// CHECK-SAME: "-inputs={{.*}},[[IMG_DEV1]],[[IMG_DEV2]]" "-outputs=[[BUNDLE:.*hipfb]]"
// CHECK: [[LD:".*ld.*"]] {{.*}} [[A_OBJ_HOST]] [[B_OBJ_HOST]]
// CHECK-SAME: {{.*}} "-T" "{{.*}}.lk"
diff --git a/test/Driver/hurd.c b/test/Driver/hurd.c
new file mode 100644
index 000000000000..a6ca8ea3379f
--- /dev/null
+++ b/test/Driver/hurd.c
@@ -0,0 +1,62 @@
+// RUN: %clang -no-canonical-prefixes %s -### 2>&1 \
+// RUN: --target=i386-pc-gnu \
+// RUN: --sysroot=%S/Inputs/basic_hurd_tree \
+// RUN: | FileCheck --check-prefix=CHECK %s
+// CHECK-NOT: warning:
+// CHECK: "-cc1"
+// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK: "-internal-externc-isystem" "[[SYSROOT]]/usr/include/i386-gnu"
+// CHECK: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
+// CHECK: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK: "-dynamic-linker" "/lib/ld.so"
+// CHECK: "crtbegin.o"
+// CHECK: "-L[[SYSROOT]]/lib/i386-gnu"
+// CHECK: "-L[[SYSROOT]]/lib/../lib32"
+// CHECK: "-L[[SYSROOT]]/usr/lib/i386-gnu"
+// CHECK: "-L[[SYSROOT]]/usr/lib/../lib32"
+// CHECK: "-L[[SYSROOT]]/lib"
+// CHECK: "-L[[SYSROOT]]/usr/lib"
+
+// RUN: %clang -no-canonical-prefixes %s -### 2>&1 \
+// RUN: --target=i386-pc-gnu -static \
+// RUN: --sysroot=%S/Inputs/basic_hurd_tree \
+// RUN: | FileCheck --check-prefix=CHECK-STATIC %s
+// CHECK-STATIC-NOT: warning:
+// CHECK-STATIC: "-cc1"
+// CHECK-STATIC: "-static-define"
+// CHECK-STATIC: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-STATIC: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-STATIC: "-internal-externc-isystem" "[[SYSROOT]]/usr/include/i386-gnu"
+// CHECK-STATIC: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK-STATIC: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
+// CHECK-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-STATIC: "-static"
+// CHECK-STATIC: "crtbeginT.o"
+// CHECK-STATIC: "-L[[SYSROOT]]/lib/i386-gnu"
+// CHECK-STATIC: "-L[[SYSROOT]]/lib/../lib32"
+// CHECK-STATIC: "-L[[SYSROOT]]/usr/lib/i386-gnu"
+// CHECK-STATIC: "-L[[SYSROOT]]/usr/lib/../lib32"
+// CHECK-STATIC: "-L[[SYSROOT]]/lib"
+// CHECK-STATIC: "-L[[SYSROOT]]/usr/lib"
+
+// RUN: %clang -no-canonical-prefixes %s -### 2>&1 \
+// RUN: --target=i386-pc-gnu -shared \
+// RUN: --sysroot=%S/Inputs/basic_hurd_tree \
+// RUN: | FileCheck --check-prefix=CHECK-SHARED %s
+// CHECK-SHARED-NOT: warning:
+// CHECK-SHARED: "-cc1"
+// CHECK-SHARED: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-SHARED: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-SHARED: "-internal-externc-isystem" "[[SYSROOT]]/usr/include/i386-gnu"
+// CHECK-SHARED: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK-SHARED: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
+// CHECK-SHARED: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-SHARED: "crtbeginS.o"
+// CHECK-SHARED: "-L[[SYSROOT]]/lib/i386-gnu"
+// CHECK-SHARED: "-L[[SYSROOT]]/lib/../lib32"
+// CHECK-SHARED: "-L[[SYSROOT]]/usr/lib/i386-gnu"
+// CHECK-SHARED: "-L[[SYSROOT]]/usr/lib/../lib32"
+// CHECK-SHARED: "-L[[SYSROOT]]/lib"
+// CHECK-SHARED: "-L[[SYSROOT]]/usr/lib"
diff --git a/test/Driver/indirect-tls-seg-refs.c b/test/Driver/indirect-tls-seg-refs.c
new file mode 100644
index 000000000000..b3f69329854e
--- /dev/null
+++ b/test/Driver/indirect-tls-seg-refs.c
@@ -0,0 +1,8 @@
+// REQUIRES: clang-driver, x86-registered-target
+
+// RUN: %clang -### -target x86_64-unknown-linux %s 2>&1 | FileCheck %s -check-prefix=TLSDIRECT
+// RUN: %clang -### -target x86_64-unknown-linux -mno-tls-direct-seg-refs -mtls-direct-seg-refs %s 2>&1 | FileCheck %s -check-prefix=TLSDIRECT
+// RUN: %clang -### -target x86_64-unknown-linux -mtls-direct-seg-refs -mno-tls-direct-seg-refs %s 2>&1 | FileCheck %s -check-prefix=NO-TLSDIRECT
+
+// NO-TLSDIRECT: -mno-tls-direct-seg-refs
+// TLSDIRECT-NOT: -mno-tls-direct-seg-refs
diff --git a/test/Driver/inhibit-downstream-commands.c b/test/Driver/inhibit-downstream-commands.c
index ceb245e4f1c9..43f4480a801a 100644
--- a/test/Driver/inhibit-downstream-commands.c
+++ b/test/Driver/inhibit-downstream-commands.c
@@ -2,5 +2,5 @@
// CHECK: error: unknown type name 'invalid'
// CHECK-NOT: clang: error: assembler command failed
// CHECK-NOT: clang: error: linker command failed
-// XFAIL: win32
+// XFAIL: windows-msvc
invalid C code!
diff --git a/test/Driver/integrated-as.c b/test/Driver/integrated-as.c
index c65973ca5f32..55334ed71e59 100644
--- a/test/Driver/integrated-as.c
+++ b/test/Driver/integrated-as.c
@@ -7,7 +7,7 @@
// FIAS: cc1as
-// RUN: %clang -### -fno-integrated-as -S %s 2>&1 \
+// RUN: %clang -target none -### -fno-integrated-as -S %s 2>&1 \
// RUN: | FileCheck %s -check-prefix NOFIAS
// NOFIAS-NOT: cc1as
diff --git a/test/Driver/integrated-as.s b/test/Driver/integrated-as.s
index 1dcd4f611a3a..3ad0860b9020 100644
--- a/test/Driver/integrated-as.s
+++ b/test/Driver/integrated-as.s
@@ -50,3 +50,9 @@
// RUN: %clang -### -target x86_64--- -x assembler -c -fPIC -integrated-as %s 2>&1 | FileCheck --check-prefix=PIC %s
// PIC: "-mrelocation-model" "pic"
+
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Wa,-fdebug-compilation-dir,. 2>&1 | FileCheck --check-prefix=WA_DEBUGDIR %s
+// WA_DEBUGDIR: "-fdebug-compilation-dir" "."
+
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Xassembler -fdebug-compilation-dir -Xassembler . 2>&1 | FileCheck --check-prefix=XA_DEBUGDIR %s
+// XA_DEBUGDIR: "-fdebug-compilation-dir" "."
diff --git a/test/Driver/linker-opts.c b/test/Driver/linker-opts.c
index 5fe29d7a13a6..68b1e9fbe513 100644
--- a/test/Driver/linker-opts.c
+++ b/test/Driver/linker-opts.c
@@ -5,7 +5,7 @@
// CHECK: "-L{{.*}}/test1"
// GCC driver is used as linker on cygming. It should be aware of LIBRARY_PATH.
-// XFAIL: win32
+// XFAIL: windows-msvc
// REQUIRES: clang-driver
// REQUIRES: native
diff --git a/test/Driver/linux-as.c b/test/Driver/linux-as.c
index 68cf403d9789..a9335ebf713f 100644
--- a/test/Driver/linux-as.c
+++ b/test/Driver/linux-as.c
@@ -3,129 +3,160 @@
// RUN: %clang -target arm-linux -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM %s
-// CHECK-ARM: as{{(.exe)?}}" "-mfloat-abi=soft"
+// CHECK-ARM: as{{(.exe)?}}" "-EL" "-mfloat-abi=soft"
//
// RUN: %clang -target arm-linux -mcpu=cortex-a8 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-MCPU %s
-// CHECK-ARM-MCPU: as{{(.exe)?}}" "-mfloat-abi=soft" "-mcpu=cortex-a8"
+// CHECK-ARM-MCPU: as{{(.exe)?}}" "-EL" "-mfloat-abi=soft" "-mcpu=cortex-a8"
//
// RUN: %clang -target arm-linux -mfpu=neon -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-MFPU %s
-// CHECK-ARM-MFPU: as{{(.exe)?}}" "-mfloat-abi=soft" "-mfpu=neon"
+// CHECK-ARM-MFPU: as{{(.exe)?}}" "-EL" "-mfloat-abi=soft" "-mfpu=neon"
//
// RUN: %clang -target arm-linux -march=armv7-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-MARCH %s
-// CHECK-ARM-MARCH: as{{(.exe)?}}" "-mfloat-abi=soft" "-march=armv7-a"
+// CHECK-ARM-MARCH: as{{(.exe)?}}" "-EL" "-mfloat-abi=soft" "-march=armv7-a"
+//
+// RUN: %clang -target armeb-linux -mlittle-endian -mcpu=cortex-a8 -mfpu=neon -march=armv7-a -### \
+// RUN: -no-integrated-as -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ARM-ALL %s
+// CHECK-ARM-ALL: as{{(.exe)?}}" "-EL" "-mfloat-abi=soft" "-march=armv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
//
// RUN: %clang -target arm-linux -mcpu=cortex-a8 -mfpu=neon -march=armv7-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-ALL %s
-// CHECK-ARM-ALL: as{{(.exe)?}}" "-mfloat-abi=soft" "-march=armv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
//
-// RUN: %clang -target arm-linux -mcpu=cortex-a8 -mfpu=neon -march=armebv7-a -### \
+// RUN: %clang -target armeb-linux -mlittle-endian -mcpu=cortex-a8 -mfpu=neon -march=armv7-a -### \
+// RUN: -no-integrated-as -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ARM-ALL %s
+//
+// RUN: %clang -target armeb-linux -mcpu=cortex-a8 -mfpu=neon -march=armebv7-a -### \
+// RUN: -no-integrated-as -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ARMEB-ALL %s
+// CHECK-ARMEB-ALL: as{{(.exe)?}}" "-EB" "-mfloat-abi=soft" "-march=armebv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
+//
+// RUN: %clang -target arm-linux -mcpu=cortex-a8 -mfpu=neon -march=armebv7-a -mbig-endian -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARMEB-ALL %s
-// CHECK-ARMEB-ALL: as{{(.exe)?}}" "-mfloat-abi=soft" "-march=armebv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
//
// RUN: %clang -target thumb-linux -mcpu=cortex-a8 -mfpu=neon -march=thumbv7-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-THUMB-ALL %s
-// CHECK-THUMB-ALL: as{{(.exe)?}}" "-mfloat-abi=soft" "-march=thumbv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
+// CHECK-THUMB-ALL: as{{(.exe)?}}" "-EL" "-mfloat-abi=soft" "-march=thumbv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
+//
+// RUN: %clang -target thumbeb-linux -mcpu=cortex-a8 -mfpu=neon -march=thumbv7-a -mlittle-endian -### \
+// RUN: -no-integrated-as -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-THUMB-ALL %s
//
-// RUN: %clang -target thumb-linux -mcpu=cortex-a8 -mfpu=neon -march=thumbebv7-a -### \
+// RUN: %clang -target thumbeb-linux -mcpu=cortex-a8 -mfpu=neon -march=thumbebv7-a -### \
+// RUN: -no-integrated-as -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-THUMBEB-ALL %s
+// CHECK-THUMBEB-ALL: as{{(.exe)?}}" "-EB" "-mfloat-abi=soft" "-march=thumbebv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
+//
+// RUN: %clang -target thumb-linux -mcpu=cortex-a8 -mfpu=neon -march=thumbebv7-a -mbig-endian -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-THUMBEB-ALL %s
-// CHECK-THUMBEB-ALL: as{{(.exe)?}}" "-mfloat-abi=soft" "-march=thumbebv7-a" "-mcpu=cortex-a8" "-mfpu=neon"
//
// RUN: %clang -target armv7-linux -mcpu=cortex-a8 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-TARGET %s
-// CHECK-ARM-TARGET: as{{(.exe)?}}" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
+// CHECK-ARM-TARGET: as{{(.exe)?}}" "-EL" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
//
// RUN: %clang -target armebv7-linux -mcpu=cortex-a8 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARMEB-TARGET %s
-// CHECK-ARMEB-TARGET: as{{(.exe)?}}" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
+// CHECK-ARMEB-TARGET: as{{(.exe)?}}" "-EB" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
//
// RUN: %clang -target thumbv7-linux -mcpu=cortex-a8 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-THUMB-TARGET %s
-// CHECK-THUMB-TARGET: as{{(.exe)?}}" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
+// CHECK-THUMB-TARGET: as{{(.exe)?}}" "-EL" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
//
// RUN: %clang -target thumbebv7-linux -mcpu=cortex-a8 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-THUMBEB-TARGET %s
-// CHECK-THUMBEB-TARGET: as{{(.exe)?}}" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
+// CHECK-THUMBEB-TARGET: as{{(.exe)?}}" "-EB" "-mfpu=neon" "-mfloat-abi=soft" "-mcpu=cortex-a8"
//
// RUN: %clang -target armv8-linux -mcpu=cortex-a53 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-TARGET-V8 %s
-// CHECK-ARM-TARGET-V8: as{{(.exe)?}}" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
+// CHECK-ARM-TARGET-V8: as{{(.exe)?}}" "-EL" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
//
// RUN: %clang -target armebv8-linux -mcpu=cortex-a53 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARMEB-TARGET-V8 %s
-// CHECK-ARMEB-TARGET-V8: as{{(.exe)?}}" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
+// CHECK-ARMEB-TARGET-V8: as{{(.exe)?}}" "-EB" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
//
// RUN: %clang -target thumbv8-linux -mcpu=cortex-a53 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-THUMB-TARGET-V8 %s
-// CHECK-THUMB-TARGET-V8: as{{(.exe)?}}" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
+// CHECK-THUMB-TARGET-V8: as{{(.exe)?}}" "-EL" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
//
// RUN: %clang -target thumbebv8-linux -mcpu=cortex-a53 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-THUMBEB-TARGET-V8 %s
-// CHECK-THUMBEB-TARGET-V8: as{{(.exe)?}}" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
+// CHECK-THUMBEB-TARGET-V8: as{{(.exe)?}}" "-EB" "-mfpu=crypto-neon-fp-armv8" "-mfloat-abi=soft" "-mcpu=cortex-a53"
//
// RUN: %clang -target arm-linux -mfloat-abi=hard -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-MFLOAT-ABI %s
-// CHECK-ARM-MFLOAT-ABI: as{{(.exe)?}}" "-mfloat-abi=hard"
+// CHECK-ARM-MFLOAT-ABI: as{{(.exe)?}}" "-EL" "-mfloat-abi=hard"
//
// RUN: %clang -target arm-linux-androideabi -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-ANDROID %s
-// CHECK-ARM-ANDROID: as{{(.exe)?}}" "-mfloat-abi=soft"
+// CHECK-ARM-ANDROID: as{{(.exe)?}}" "-EL" "-mfloat-abi=soft"
//
// RUN: %clang -target arm-linux-androideabi -march=armv7-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-ANDROID-SOFTFP %s
-// CHECK-ARM-ANDROID-SOFTFP: as{{(.exe)?}}" "-mfloat-abi=softfp" "-march=armv7-a"
+// CHECK-ARM-ANDROID-SOFTFP: as{{(.exe)?}}" "-EL" "-mfloat-abi=softfp" "-march=armv7-a"
//
// RUN: %clang -target arm-linux-eabi -mhard-float -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM-HARDFP %s
-// CHECK-ARM-HARDFP: as{{(.exe)?}}" "-mfloat-abi=hard"
+// CHECK-ARM-HARDFP: as{{(.exe)?}}" "-EL" "-mfloat-abi=hard"
//
// RUN: %clang -target aarch64-linux-gnu -mcpu=cortex-a53 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM64-MCPU %s
-// CHECK-ARM64-MCPU: as{{(.exe)?}}" "-mcpu=cortex-a53"
+// CHECK-ARM64-MCPU: as{{(.exe)?}}" "-EL" "-mcpu=cortex-a53"
//
// RUN: %clang -target aarch64-linux-gnu -march=armv8-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM64-MARCH %s
-// CHECK-ARM64-MARCH: as{{(.exe)?}}" "-march=armv8-a"
+// CHECK-ARM64-MARCH: as{{(.exe)?}}" "-EL" "-march=armv8-a"
//
// RUN: %clang -target aarch64-linux-gnu -mcpu=cortex-a53 -march=armv8-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ARM64-ALL %s
-// CHECK-ARM64-ALL: as{{(.exe)?}}" "-march=armv8-a" "-mcpu=cortex-a53"
+// CHECK-ARM64-ALL: as{{(.exe)?}}" "-EL" "-march=armv8-a" "-mcpu=cortex-a53"
+//
+// RUN: %clang -target aarch64_be-linux-gnu -mcpu=cortex-a53 -march=armv8-a -mlittle-endian -### \
+// RUN: -no-integrated-as -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ARM64-ALL %s
//
// RUN: %clang -target aarch64_be-linux-gnu -mcpu=cortex-a53 -### \
// RUN: -no-integrated-as -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-ARM64-MCPU %s
+// RUN: | FileCheck -check-prefix=CHECK-ARM64BE-MCPU %s
+// CHECK-ARM64BE-MCPU: as{{(.exe)?}}" "-EB" "-mcpu=cortex-a53"
//
// RUN: %clang -target aarch64_be-linux-gnu -march=armv8-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-ARM64-MARCH %s
+// RUN: | FileCheck -check-prefix=CHECK-ARM64BE-MARCH %s
+// CHECK-ARM64BE-MARCH: as{{(.exe)?}}" "-EB" "-march=armv8-a"
//
// RUN: %clang -target aarch64_be-linux-gnu -mcpu=cortex-a53 -march=armv8-a -### \
// RUN: -no-integrated-as -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-ARM64-ALL %s
+// RUN: | FileCheck -check-prefix=CHECK-ARM64BE-ALL %s
+// CHECK-ARM64BE-ALL: as{{(.exe)?}}" "-EB" "-march=armv8-a" "-mcpu=cortex-a53"
+//
+// RUN: %clang -target aarch64-linux-gnu -mcpu=cortex-a53 -march=armv8-a -mbig-endian -### \
+// RUN: -no-integrated-as -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ARM64BE-ALL %s
//
// RUN: %clang -target ppc-linux -mcpu=invalid-cpu -### \
// RUN: -no-integrated-as -c %s 2>&1 \
diff --git a/test/Driver/linux-header-search.cpp b/test/Driver/linux-header-search.cpp
index f545b439b4ab..03502423c15a 100644
--- a/test/Driver/linux-header-search.cpp
+++ b/test/Driver/linux-header-search.cpp
@@ -498,6 +498,7 @@
// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
// RUN: -target arm-oe-linux-gnueabi -stdlib=libstdc++ \
// RUN: --sysroot=%S/Inputs/openembedded_arm_linux_tree \
+// RUN: --gcc-toolchain="" \
// RUN: | FileCheck --check-prefix=CHECK-OE-ARM %s
// CHECK-OE-ARM: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
@@ -509,9 +510,22 @@
// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
// RUN: -target aarch64-oe-linux -stdlib=libstdc++ \
// RUN: --sysroot=%S/Inputs/openembedded_aarch64_linux_tree \
+// RUN: --gcc-toolchain="" \
// RUN: | FileCheck --check-prefix=CHECK-OE-AARCH64 %s
// CHECK-OE-AARCH64: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
// CHECK-OE-AARCH64: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK-OE-AARCH64: "-internal-isystem" "[[SYSROOT]]/usr/lib64/aarch64-oe-linux/6.3.0/../../../include/c++/6.3.0"
// CHECK-OE-AARCH64: "-internal-isystem" "[[SYSROOT]]/usr/lib64/aarch64-oe-linux/6.3.0/../../../include/c++/6.3.0/backward"
+
+// Check header search with Cray's gcc package.
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN: -target x86_64-unknown-linux-gnu -stdlib=libstdc++ \
+// RUN: --sysroot=%S/Inputs/cray_suse_gcc_tree \
+// RUN: --gcc-toolchain="%S/Inputs/cray_suse_gcc_tree/opt/gcc/8.2.0/snos" \
+// RUN: | FileCheck --check-prefix=CHECK-CRAY-X86 %s
+
+// CHECK-CRAY-X86: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK-CRAY-X86: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-CRAY-X86: "-internal-isystem" "[[SYSROOT]]/opt/gcc/8.2.0/snos/lib/gcc/x86_64-suse-linux/8.2.0/../../../../include/g++"
+// CHECK-CRAY-X86: "-internal-isystem" "[[SYSROOT]]/opt/gcc/8.2.0/snos/lib/gcc/x86_64-suse-linux/8.2.0/../../../../include/g++/backward"
diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c
index 787013931a48..3ab81be4906a 100644
--- a/test/Driver/linux-ld.c
+++ b/test/Driver/linux-ld.c
@@ -150,6 +150,107 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC %s
+// CHECK-CLANG-NO-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-NO-LIBGCC: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+// CHECK-CLANG-NO-LIBGCC: "-lc"
+// CHECK-CLANG-NO-LIBGCC: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+//
+// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANGXX-NO-LIBGCC %s
+// CHECK-CLANGXX-NO-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANGXX-NO-LIBGCC: "-lgcc_s" "-lgcc"
+// CHECK-CLANGXX-NO-LIBGCC: "-lc"
+// CHECK-CLANGXX-NO-LIBGCC: "-lgcc_s" "-lgcc"
+//
+// RUN: %clang -static -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-STATIC %s
+// CHECK-CLANG-NO-LIBGCC-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-NO-LIBGCC-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
+//
+// RUN: %clang -dynamic -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-DYNAMIC %s
+// CHECK-CLANG-NO-LIBGCC-DYNAMIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-NO-LIBGCC-DYNAMIC: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+// CHECK-CLANG-NO-LIBGCC-DYNAMIC: "-lc"
+// CHECK-CLANG-NO-LIBGCC-DYNAMIC: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+//
+// RUN: %clang -static-libgcc -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-STATIC-LIBGCC %s
+// CHECK-CLANG-STATIC-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-STATIC-LIBGCC: "-lgcc" "-lgcc_eh"
+// CHECK-CLANG-STATIC-LIBGCC: "-lc"
+// CHECK-CLANG-STATIC-LIBGCC: "-lgcc" "-lgcc_eh"
+//
+// RUN: %clang -static-libgcc -dynamic -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-STATIC-LIBGCC-DYNAMIC %s
+// CHECK-CLANG-STATIC-LIBGCC-DYNAMIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-STATIC-LIBGCC-DYNAMIC: "-lgcc" "-lgcc_eh"
+// CHECK-CLANG-STATIC-LIBGCC-DYNAMIC: "-lc"
+// CHECK-CLANG-STATIC-LIBGCC-DYNAMIC: "-lgcc" "-lgcc_eh"
+//
+// RUN: %clang -shared-libgcc -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-SHARED-LIBGCC %s
+// CHECK-CLANG-SHARED-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-SHARED-LIBGCC: "-lgcc_s" "-lgcc"
+// CHECK-CLANG-SHARED-LIBGCC: "-lc"
+// CHECK-CLANG-SHARED-LIBGCC: "-lgcc_s" "-lgcc"
+//
+// RUN: %clang -shared-libgcc -dynamic -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-SHARED-LIBGCC-DYNAMIC %s
+// CHECK-CLANG-SHARED-LIBGCC-DYNAMIC: "-lgcc_s" "-lgcc"
+// CHECK-CLANG-SHARED-LIBGCC-DYNAMIC: "-lc"
+// CHECK-CLANG-SHARED-LIBGCC-DYNAMIC: "-lgcc_s" "-lgcc"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64-linux-android -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-NONE %s
+// CHECK-CLANG-ANDROID-NONE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-ANDROID-NONE: "-lgcc" "-ldl" "-lc"
+//
+// RUN: %clang -shared -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64-linux-android -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-SHARED %s
+// CHECK-CLANG-ANDROID-SHARED: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-ANDROID-SHARED: "-lgcc" "-ldl" "-lc"
+//
+// RUN: %clang -static -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64-linux-android -rtlib=platform \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-STATIC %s
+// CHECK-CLANG-ANDROID-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-CLANG-ANDROID-STATIC: "--start-group" "-lgcc" "-lc" "--end-group"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
// RUN: -static \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
@@ -773,7 +874,7 @@
// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=hexagon-linux-gnu \
// RUN: | FileCheck --check-prefix=CHECK-HEXAGON %s
-// CHECK-HEXAGON: "{{.*}}hexagon-link{{(.exe)?}}"
+// CHECK-HEXAGON: "{{.*}}{{hexagon-link|ld}}{{(.exe)?}}"
// CHECK-HEXAGON-NOT: "--hash-style={{gnu|both}}"
//
// Check that we do not pass --hash-style=gnu and --hash-style=both to linker
@@ -869,6 +970,34 @@
// CHECK-MIPS64EL-REDHAT: "-dynamic-linker" "{{.*}}/lib{{(64)?}}/ld.so.1"
// CHECK-MIPS64EL-REDHAT-NOT: "-dynamic-linker" "{{.*}}/lib{{(64)?}}/ld-musl-mipsel.so.1"
// CHECK-MIPS64EL-REDHAT-NOT: "--hash-style={{gnu|both}}"
+
+// Check that we pass --hash-style=both for pre-M Android versions and
+// --hash-style=gnu for newer Android versions.
+// RUN: %clang %s -### -o %t.o 2>&1 \
+// RUN: --target=armv7-linux-android21 \
+// RUN: | FileCheck --check-prefix=CHECK-ANDROID-HASH-STYLE-L %s
+// CHECK-ANDROID-HASH-STYLE-L: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ANDROID-HASH-STYLE-L: "--hash-style=both"
+//
+// RUN: %clang %s -### -o %t.o 2>&1 \
+// RUN: --target=armv7-linux-android23 \
+// RUN: | FileCheck --check-prefix=CHECK-ANDROID-HASH-STYLE-M %s
+// CHECK-ANDROID-HASH-STYLE-M: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ANDROID-HASH-STYLE-M: "--hash-style=gnu"
+//
+// RUN: %clang %s -### -o %t.o 2>&1 --target=mips64-linux-gnuabin32 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-GNUABIN32 %s
+// CHECK-MIPS64EL-GNUABIN32: "{{.*}}ld{{(.exe)?}}"
+// CHECK-MIPS64EL-GNUABIN32: "-m" "elf32btsmipn32"
+// CHECK-MIPS64EL-GNUABIN32: "-dynamic-linker" "{{.*}}/lib{{(32)?}}/ld.so.1"
+// CHECK-MIPS64EL-GNUABIN32-NOT: "--hash-style={{gnu|both}}"
+//
+// RUN: %clang %s -### -o %t.o 2>&1 --target=mips64-linux-gnuabi64 \
+// RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-GNUABI64 %s
+// CHECK-MIPS64EL-GNUABI64: "{{.*}}ld{{(.exe)?}}"
+// CHECK-MIPS64EL-GNUABI64: "-m" "elf64btsmip"
+// CHECK-MIPS64EL-GNUABI64: "-dynamic-linker" "{{.*}}/lib{{(64)?}}/ld.so.1"
+// CHECK-MIPS64EL-GNUABI64-NOT: "--hash-style={{gnu|both}}"
//
// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=sparc-unknown-linux-gnu \
@@ -1135,6 +1264,8 @@
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-ANDROID: "-z" "now"
+// CHECK-ANDROID: "-z" "relro"
// CHECK-ANDROID: "--enable-new-dtags"
// CHECK-ANDROID: "{{.*}}{{/|\\\\}}crtbegin_dynamic.o"
// CHECK-ANDROID: "-L[[SYSROOT]]/usr/lib"
@@ -1637,6 +1768,7 @@
// RUN: | FileCheck --check-prefix=CHECK-ARMEB %s
// CHECK-ARMEB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-ARMEB-NOT: "--be8"
+// CHECK-ARMEB: "-EB"
// CHECK-ARMEB: "-m" "armelfb_linux_eabi"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
@@ -1646,8 +1778,88 @@
// RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s
// CHECK-ARMV7EB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-ARMV7EB: "--be8"
+// CHECK-ARMV7EB: "-EB"
// CHECK-ARMV7EB: "-m" "armelfb_linux_eabi"
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=armv7-unknown-linux \
+// RUN: -mbig-endian \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=armebv7-unknown-linux \
+// RUN: -mbig-endian \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=armv7-unknown-linux \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s
+// CHECK-ARMV7EL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-ARMV7EL-NOT: "--be8"
+// CHECK-ARMV7EL: "-EL"
+// CHECK-ARMV7EL: "-m" "armelf_linux_eabi"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=armebv7-unknown-linux \
+// RUN: -mlittle-endian \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=armv7-unknown-linux \
+// RUN: -mlittle-endian \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64_be-unknown-linux \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s
+// CHECK-AARCH64BE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-AARCH64BE-NOT: "--be8"
+// CHECK-AARCH64BE: "-EB"
+// CHECK-AARCH64BE: "-m" "aarch64linuxb"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64-unknown-linux \
+// RUN: -mbig-endian \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64_be-unknown-linux \
+// RUN: -mbig-endian \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64-unknown-linux \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s
+// CHECK-AARCH64LE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-AARCH64LE-NOT: "--be8"
+// CHECK-AARCH64LE: "-EL"
+// CHECK-AARCH64LE: "-m" "aarch64linux"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=aarch64_be-unknown-linux \
+// RUN: -mlittle-endian \
+// RUN: --gcc-toolchain="" \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s
+
// Check dynamic-linker for musl-libc
// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=i386-pc-linux-musl \
@@ -1817,6 +2029,7 @@
// Check whether the OpenEmbedded ARM libs are added correctly.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: --target=arm-oe-linux-gnueabi -rtlib=libgcc \
+// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/openembedded_arm_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-OE-ARM %s
@@ -1836,6 +2049,7 @@
// Check whether the OpenEmbedded AArch64 libs are added correctly.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: --target=aarch64-oe-linux -rtlib=libgcc \
+// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/openembedded_aarch64_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-OE-AARCH64 %s
diff --git a/test/Driver/linux-per-target-runtime-dir.c b/test/Driver/linux-per-target-runtime-dir.c
index aa9c1017f6ad..bbd11570f522 100644
--- a/test/Driver/linux-per-target-runtime-dir.c
+++ b/test/Driver/linux-per-target-runtime-dir.c
@@ -19,3 +19,9 @@
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s
// CHECK-CLANGRT-X8664: x86_64-linux-gnu{{/|\\}}lib{{/|\\}}libclang_rt.builtins.a
+
+// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \
+// RUN: --target=x86_64-linux-gnu \
+// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-X8664 %s
+// CHECK-FILE-NAME-X8664: x86_64-linux-gnu{{/|\\}}lib{{/|\\}}libclang_rt.builtins.a
diff --git a/test/Driver/miamcu-opt.c b/test/Driver/miamcu-opt.c
index 577bd3772d47..d89c2c3b1758 100644
--- a/test/Driver/miamcu-opt.c
+++ b/test/Driver/miamcu-opt.c
@@ -14,7 +14,7 @@
// DYNAMIC: error: invalid argument '-dynamic' not allowed with '-static'
-// NOT-X86: error: unsupported option '-miamcu' for target 'armv8---eabi'
+// NOT-X86: error: unsupported option '-miamcu' for target 'armv8-unknown-unknown-eabi'
// MNOIAMCU-NOT: "-triple" "i586-intel-elfiamcu"
diff --git a/test/Driver/mingw-lto.c b/test/Driver/mingw-lto.c
new file mode 100644
index 000000000000..8bb4aedefd66
--- /dev/null
+++ b/test/Driver/mingw-lto.c
@@ -0,0 +1,4 @@
+// The default linker doesn't support LLVM bitcode
+// RUN: not %clang -target i686-pc-windows-gnu %s -flto -fuse-ld=bfd
+// When using lld, this is allowed though.
+// RUN: %clang -target i686-pc-windows-gnu -### %s -flto -fuse-ld=lld
diff --git a/test/Driver/mingw-sanitizers.c b/test/Driver/mingw-sanitizers.c
new file mode 100644
index 000000000000..09f28fea8abf
--- /dev/null
+++ b/test/Driver/mingw-sanitizers.c
@@ -0,0 +1,11 @@
+// RUN: %clang -target i686-windows-gnu %s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-I686 %s
+// ASAN-I686: "{{.*}}libclang_rt.asan_dynamic-i386.dll.a"
+// ASAN-I686: "{{[^"]*}}libclang_rt.asan_dynamic_runtime_thunk-i386.a"
+// ASAN-I686: "--require-defined" "___asan_seh_interceptor"
+// ASAN-I686: "--whole-archive" "{{.*}}libclang_rt.asan_dynamic_runtime_thunk-i386.a" "--no-whole-archive"
+
+// RUN: %clang -target x86_64-windows-gnu %s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-X86_64 %s
+// ASAN-X86_64: "{{.*}}libclang_rt.asan_dynamic-x86_64.dll.a"
+// ASAN-X86_64: "{{[^"]*}}libclang_rt.asan_dynamic_runtime_thunk-x86_64.a"
+// ASAN-X86_64: "--require-defined" "__asan_seh_interceptor"
+// ASAN-X86_64: "--whole-archive" "{{.*}}libclang_rt.asan_dynamic_runtime_thunk-x86_64.a" "--no-whole-archive"
diff --git a/test/Driver/mingw.cpp b/test/Driver/mingw.cpp
index 967574ffe161..166a79af7b35 100644
--- a/test/Driver/mingw.cpp
+++ b/test/Driver/mingw.cpp
@@ -56,3 +56,8 @@
// CHECK_MINGW_UBUNTU_POSIX_TREE: "{{.*}}/Inputs/mingw_ubuntu_posix_tree/usr{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}x86_64-w64-mingw32"
// CHECK_MINGW_UBUNTU_POSIX_TREE: "{{.*}}/Inputs/mingw_ubuntu_posix_tree/usr{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.3-posix{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}backward"
// CHECK_MINGW_UBUNTU_POSIX_TREE: "{{.*}}/Inputs/mingw_ubuntu_posix_tree/usr{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
+
+// RUN: %clang -target i686-windows-gnu -E -### %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_NO_UNICODE %s
+// RUN: %clang -target i686-windows-gnu -E -### %s -municode 2>&1 | FileCheck -check-prefix=CHECK_MINGW_UNICODE %s
+// CHECK_MINGW_NO_UNICODE-NOT: "-DUNICODE"
+// CHECK_MINGW_UNICODE: "-DUNICODE"
diff --git a/test/Driver/mips-abi.c b/test/Driver/mips-abi.c
index 8591a45d3eed..63ffd99b5226 100644
--- a/test/Driver/mips-abi.c
+++ b/test/Driver/mips-abi.c
@@ -162,3 +162,28 @@
// RUN: -march=unknown 2>&1 \
// RUN: | FileCheck -check-prefix=MIPS-ARCH-UNKNOWN %s
// MIPS-ARCH-UNKNOWN: error: unknown target CPU 'unknown'
+
+// Check adjusting of target triple accordingly to `-mabi` option.
+// RUN: %clang -target mips64-linux-gnuabi64 -mabi=32 -### %s 2>&1 \
+// RUN: | FileCheck -check-prefix=TARGET-O32 %s
+// TARGET-O32: "-triple" "mips-unknown-linux-gnu"
+// TARGET-O32: "-target-cpu" "mips32r2"
+// TARGET-O32: "-target-abi" "o32"
+// TARGET-O32: ld{{(.exe)?}}"
+// TARGET-O32: "-m" "elf32btsmip"
+
+// RUN: %clang -target mips-linux-gnu -mabi=n32 -### %s 2>&1 \
+// RUN: | FileCheck -check-prefix=TARGET-N32 %s
+// TARGET-N32: "-triple" "mips64-unknown-linux-gnuabin32"
+// TARGET-N32: "-target-cpu" "mips64r2"
+// TARGET-N32: "-target-abi" "n32"
+// TARGET-N32: ld{{(.exe)?}}"
+// TARGET-N32: "-m" "elf32btsmipn32"
+
+// RUN: %clang -target mips-linux-gnu -mabi=64 -### %s 2>&1 \
+// RUN: | FileCheck -check-prefix=TARGET-N64 %s
+// TARGET-N64: "-triple" "mips64-unknown-linux-gnuabi64"
+// TARGET-N64: "-target-cpu" "mips64r2"
+// TARGET-N64: "-target-abi" "n64"
+// TARGET-N64: ld{{(.exe)?}}"
+// TARGET-N64: "-m" "elf64btsmip"
diff --git a/test/Driver/mips-abicalls-error.c b/test/Driver/mips-abicalls-error.c
index 10f7201bdb07..03ef68b02de6 100644
--- a/test/Driver/mips-abicalls-error.c
+++ b/test/Driver/mips-abicalls-error.c
@@ -1,2 +1,2 @@
// RUN: not %clang -c -target mips64-linux-gnu -fPIC -mno-abicalls %s 2>&1 | FileCheck %s
-// CHECK: error: position-independent code requires ‘-mabicalls’
+// CHECK: error: position-independent code requires '-mabicalls'
diff --git a/test/Driver/mips-mti-linux.c b/test/Driver/mips-mti-linux.c
index 91a63e2f23cf..ddc84986ee86 100644
--- a/test/Driver/mips-mti-linux.c
+++ b/test/Driver/mips-mti-linux.c
@@ -15,7 +15,7 @@
// CHECK-BE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mips-mti-linux"
// CHECK-BE-HF-32R2-SAME: "-fuse-init-array" "-target-cpu" "mips32r2"
// CHECK-BE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot"
-// CHECK-BE-HF-32R2: "{{[^"]*}}lld{{[^"]*}}" "-flavor" "old-gnu" "-target" "mips-mti-linux"
+// CHECK-BE-HF-32R2: "{{[^"]*}}ld.lld{{[^"]*}}"
// CHECK-BE-HF-32R2-SAME: "--sysroot=[[SYSROOT:[^"]+]]" {{.*}} "-dynamic-linker" "/lib/ld-musl-mips.so.1"
// CHECK-BE-HF-32R2-SAME: "[[SYSROOT]]/mips-r2-hard-musl/usr/lib{{/|\\\\}}crt1.o"
// CHECK-BE-HF-32R2-SAME: "[[SYSROOT]]/mips-r2-hard-musl/usr/lib{{/|\\\\}}crti.o"
@@ -33,7 +33,7 @@
// CHECK-LE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mipsel-mti-linux"
// CHECK-LE-HF-32R2-SAME: "-fuse-init-array" "-target-cpu" "mips32r2"
// CHECK-LE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot"
-// CHECK-LE-HF-32R2: "{{[^"]*}}lld{{[^"]*}}" "-flavor" "old-gnu" "-target" "mipsel-mti-linux"
+// CHECK-LE-HF-32R2: "{{[^"]*}}ld.lld{{[^"]*}}"
// CHECK-LE-HF-32R2-SAME: "--sysroot=[[SYSROOT:[^"]+]]" {{.*}} "-dynamic-linker" "/lib/ld-musl-mipsel.so.1"
// CHECK-LE-HF-32R2-SAME: "[[SYSROOT]]/mipsel-r2-hard-musl/usr/lib{{/|\\\\}}crt1.o"
// CHECK-LE-HF-32R2-SAME: "[[SYSROOT]]/mipsel-r2-hard-musl/usr/lib{{/|\\\\}}crti.o"
diff --git a/test/Driver/msan.c b/test/Driver/msan.c
index 22f7471510ad..d810f4ca14d8 100644
--- a/test/Driver/msan.c
+++ b/test/Driver/msan.c
@@ -1,12 +1,20 @@
-// RUN: %clang -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -target mips64-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -target mips64el-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -target powerpc64-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
-// Verify that -fsanitize=memory invokes msan instrumentation.
+// RUN: %clang -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+
+// RUN: %clang -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
+// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
+// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
+// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
+
+// RUN: %clang -target mips64-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+// RUN: %clang -target mips64el-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+// RUN: %clang -target powerpc64-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
+
+// Verify that -fsanitize=memory and -fsanitize=kernel-memory invoke MSan/KMSAN instrumentation.
int foo(int *a) { return *a; }
-// CHECK: __msan_init
+// CHECK-MSAN: __msan_init
+// CHECK-KMSAN: __msan_get_context_state
diff --git a/test/Driver/msp430-hwmult.c b/test/Driver/msp430-hwmult.c
new file mode 100644
index 000000000000..d292d9330edf
--- /dev/null
+++ b/test/Driver/msp430-hwmult.c
@@ -0,0 +1,42 @@
+// Test that different values of -mhwmult pick correct
+// MSP430 hwmult target-feature(s).
+
+// RUN: %clang -### -target msp430 %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target msp430 %s -mhwmult=auto 2>&1 | FileCheck %s
+// CHECK-NOT: "-target-feature" "+hwmult16"
+// CHECK-NOT: "-target-feature" "+hwmult32"
+// CHECK-NOT: "-target-feature" "+hwmultf5"
+
+// RUN: %clang -### -target msp430 %s -mhwmult=none 2>&1 | FileCheck --check-prefix=CHECK-NONE %s
+// RUN: %clang -### -target msp430 %s -mhwmult=none -mmcu=msp430f147 2>&1 | FileCheck --check-prefix=CHECK-NONE %s
+// RUN: %clang -### -target msp430 %s -mhwmult=none -mmcu=msp430f4783 2>&1 | FileCheck --check-prefix=CHECK-NONE %s
+// CHECK-NONE: "-target-feature" "-hwmult16"
+// CHECK-NONE: "-target-feature" "-hwmult32"
+// CHECK-NONE: "-target-feature" "-hwmultf5"
+
+// RUN: %clang -### -target msp430 %s -mhwmult=16bit 2>&1 | FileCheck --check-prefix=CHECK-16 %s
+// CHECK-16: "-target-feature" "+hwmult16"
+
+// RUN: %clang -### -target msp430 %s -mhwmult=32bit 2>&1 | FileCheck --check-prefix=CHECK-32 %s
+// CHECK-32: "-target-feature" "+hwmult32"
+
+// RUN: %clang -### -target msp430 %s -mhwmult=f5series 2>&1 | FileCheck --check-prefix=CHECK-F5 %s
+// CHECK-F5: "-target-feature" "+hwmultf5"
+
+// RUN: %clang -### -target msp430 %s -mhwmult=rrr 2>&1 | FileCheck --check-prefix=INVL-ARG %s
+// INVL-ARG: error: unsupported argument 'rrr' to option '-mhwmult=rrr'
+
+// RUN: %clang -### -target msp430 %s -mhwmult=auto 2>&1 | FileCheck --check-prefix=WRN-NODEV %s
+// WRN-NODEV: warning: no MCU device specified, but '-mhwmult' is set to 'auto',
+// assuming no hardware multiply. Use -mmcu to specify a MSP430 device,
+// or -mhwmult to set hardware multiply type explicitly.
+
+// RUN: %clang -### -target msp430 %s -mhwmult=16bit -mmcu=msp430c111 2>&1 | FileCheck --check-prefix=WRN-UNSUP %s
+// RUN: %clang -### -target msp430 %s -mhwmult=32bit -mmcu=msp430c111 2>&1 | FileCheck --check-prefix=WRN-UNSUP %s
+// RUN: %clang -### -target msp430 %s -mhwmult=f5series -mmcu=msp430c111 2>&1 | FileCheck --check-prefix=WRN-UNSUP %s
+// WRN-UNSUP: warning: the given MCU does not support hardware multiply, but -mhwmult is set to
+
+// RUN: %clang -### -target msp430 %s -mhwmult=16bit -mmcu=msp430f4783 2>&1 | FileCheck --check-prefix=WRN-MISMCH %s
+// RUN: %clang -### -target msp430 %s -mhwmult=32bit -mmcu=msp430f147 2>&1 | FileCheck --check-prefix=WRN-MISMCH %s
+// RUN: %clang -### -target msp430 %s -mhwmult=f5series -mmcu=msp430f4783 2>&1 | FileCheck --check-prefix=WRN-MISMCH %s
+// WRN-MISMCH: warning: the given MCU supports {{.*}} hardware multiply, but -mhwmult is set to {{.*}}
diff --git a/test/Driver/msp430-mmcu.c b/test/Driver/msp430-mmcu.c
new file mode 100644
index 000000000000..42caacb97fad
--- /dev/null
+++ b/test/Driver/msp430-mmcu.c
@@ -0,0 +1,16 @@
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430c111 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-C111 %s
+
+// MSP430-C111: clang{{.*}} "-cc1" {{.*}} "-D__MSP430C111__"
+// MSP430-C111: msp430-elf-ld{{.*}} "-Tmsp430c111.ld"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430i2020 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-I2020 %s
+
+// MSP430-I2020: clang{{.*}} "-cc1" {{.*}} "-D__MSP430i2020__"
+// MSP430-I2020: msp430-elf-ld{{.*}} "-Tmsp430i2020.ld"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=not-a-mcu 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-UNSUP %s
+
+// MSP430-UNSUP: error: the clang compiler does not support 'not-a-mcu'
diff --git a/test/Driver/msp430-toolchain.c b/test/Driver/msp430-toolchain.c
new file mode 100644
index 000000000000..ae5ed9189c82
--- /dev/null
+++ b/test/Driver/msp430-toolchain.c
@@ -0,0 +1,78 @@
+// A basic clang -cc1 command-line, and simple environment check.
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 2>&1 \
+// RUN: | FileCheck -check-prefix=CC1 %s
+// CC1: clang{{.*}} "-cc1" "-triple" "msp430"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 \
+// RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430 %s
+
+// MSP430: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld"
+// MSP430: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430"
+// MSP430: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430"
+// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crt0.o"
+// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o"
+// MSP430: "--start-group" "-lmul_none" "-lgcc" "-lc" "-lcrt" "-lnosys" "--end-group"
+// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o"
+// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crtn.o"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -nodefaultlibs \
+// RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-NO-DFT-LIB %s
+
+// MSP430-NO-DFT-LIB: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld"
+// MSP430-NO-DFT-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430"
+// MSP430-NO-DFT-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430"
+// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crt0.o"
+// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o"
+// MSP430-NO-DFT-LIB: "--start-group" "-lmul_none" "-lgcc" "--end-group"
+// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o"
+// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crtn.o"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -nostartfiles \
+// RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-NO-START %s
+
+// MSP430-NO-START: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld"
+// MSP430-NO-START: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430"
+// MSP430-NO-START: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430"
+// MSP430-NO-START: "--start-group" "-lmul_none" "-lgcc" "-lc" "-lcrt" "-lnosys" "--end-group"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -nostdlib \
+// RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-NO-STD-LIB %s
+
+// MSP430-NO-STD-LIB: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld"
+// MSP430-NO-STD-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430"
+// MSP430-NO-STD-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430"
+// MSP430-NO-STD-LIB: "--start-group" "-lmul_none" "-lgcc" "--end-group"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f147 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-16BIT %s
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f147 -mhwmult=auto 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-16BIT %s
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=16bit 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-16BIT %s
+
+// MSP430-HWMult-16BIT: "--start-group" "-lmul_16"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f4783 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-32BIT %s
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f4783 -mhwmult=auto 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-32BIT %s
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=32bit 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-32BIT %s
+
+// MSP430-HWMult-32BIT: "--start-group" "-lmul_32"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=f5series 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-F5 %s
+// MSP430-HWMult-F5: "--start-group" "-lmul_f5"
+
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=none 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-NONE %s
+// RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mhwmult=none -mmcu=msp430f4783 2>&1 \
+// RUN: | FileCheck -check-prefix=MSP430-HWMult-NONE %s
+
+// MSP430-HWMult-NONE: "--start-group" "-lmul_none"
diff --git a/test/Driver/msvc-link.c b/test/Driver/msvc-link.c
index 8fe57331ee47..e3829e6651e3 100644
--- a/test/Driver/msvc-link.c
+++ b/test/Driver/msvc-link.c
@@ -3,6 +3,7 @@
// BASIC: "-out:a.exe"
// BASIC: "-defaultlib:libcmt"
// BASIC: "-nologo"
+// BASIC-NOT: "-Brepro"
// RUN: %clang -target i686-pc-windows-msvc -shared -o a.dll -### %s 2>&1 | FileCheck --check-prefix=DLL %s
// DLL: link.exe"
@@ -16,3 +17,14 @@
// LIBPATH: "-libpath:/usr/lib"
// LIBPATH: "-nologo"
+// RUN: %clang_cl /Brepro -### -- %s 2>&1 | FileCheck --check-prefix=REPRO %s
+// REPRO: link.exe"
+// REPRO: "-out:msvc-link.exe"
+// REPRO: "-nologo"
+// REPRO: "-Brepro"
+
+// RUN: %clang_cl /Brepro- -### -- %s 2>&1 | FileCheck --check-prefix=NOREPRO %s
+// NOREPRO: link.exe"
+// NOREPRO: "-out:msvc-link.exe"
+// NOREPRO: "-nologo"
+// NOREPRO-NOT: "-Brepro"
diff --git a/test/Driver/nacl-direct.c b/test/Driver/nacl-direct.c
index 3c8e33b180b0..194c2f858ddf 100644
--- a/test/Driver/nacl-direct.c
+++ b/test/Driver/nacl-direct.c
@@ -92,7 +92,7 @@
// RUN: %clang -no-canonical-prefixes -### -o %t.o %s 2>&1 \
// RUN: -target arm-nacl \
// RUN: | FileCheck --check-prefix=CHECK-ARM-NOV7 %s
-// CHECK-ARM-NOV7: "-triple" "armv7--nacl-gnueabihf"
+// CHECK-ARM-NOV7: "-triple" "armv7-unknown-nacl-gnueabihf"
// CHECK-ARM-NOV7: "-target-abi" "aapcs-linux"
// CHECK-ARM-NOV7: "-mfloat-abi" "hard"
// CHECK-ARM-NOV7: as{{(.exe)?}}"
diff --git a/test/Driver/netbsd.c b/test/Driver/netbsd.c
index 34ad6e41579f..f5352e2486f0 100644
--- a/test/Driver/netbsd.c
+++ b/test/Driver/netbsd.c
@@ -1,135 +1,135 @@
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=STATIC %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \
// RUN: -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=PIE %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \
// RUN: -static -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=STATIC-PIE %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \
// RUN: -shared --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SHARED %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=X86_64 %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd7.0.0 \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=X86_64-7 %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd6.0.0 \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=X86_64-6 %s
-// RUN: %clang -no-canonical-prefixes -target aarch64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64 %s
-// RUN: %clang -no-canonical-prefixes -target aarch64--netbsd7.0.0 \
+// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64-7 %s
-// RUN: %clang -no-canonical-prefixes -target aarch64_be--netbsd \
+// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64_BE %s
-// RUN: %clang -no-canonical-prefixes -target aarch64_be--netbsd7.0.0 \
+// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64_BE-7 %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd-eabi \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd-eabi \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARM %s
-// RUN: %clang -no-canonical-prefixes -target armeb--netbsd-eabi \
+// RUN: %clang -no-canonical-prefixes -target armeb-unknown-netbsd-eabi \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARMEB %s
-// RUN: %clang -no-canonical-prefixes -target armeb--netbsd-eabi -march=armv7 \
+// RUN: %clang -no-canonical-prefixes -target armeb-unknown-netbsd-eabi -march=armv7 \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARMV7EB %s
-// RUN: %clang -no-canonical-prefixes -target armv7eb--netbsd-eabi \
+// RUN: %clang -no-canonical-prefixes -target armv7eb-unknown-netbsd-eabi \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARMV7EB %s
-// RUN: %clang -r -no-canonical-prefixes -target armeb--netbsd-eabi \
+// RUN: %clang -r -no-canonical-prefixes -target armeb-unknown-netbsd-eabi \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARMEB-R %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARM-APCS %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd-eabihf \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd-eabihf \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARM-HF %s
-// RUN: %clang -no-canonical-prefixes -target thumb--netbsd-eabi \
+// RUN: %clang -no-canonical-prefixes -target thumb-unknown-netbsd-eabi \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=THUMB %s
-// RUN: %clang -no-canonical-prefixes -target thumbeb--netbsd-eabi \
+// RUN: %clang -no-canonical-prefixes -target thumbeb-unknown-netbsd-eabi \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=THUMBEB %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd7.0.0-eabi \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARM-7 %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd6.0.0-eabi \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARM-6 %s
-// RUN: %clang -no-canonical-prefixes -target sparc--netbsd \
+// RUN: %clang -no-canonical-prefixes -target sparc-unknown-netbsd \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC %s
-// RUN: %clang -no-canonical-prefixes -target sparc64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target sparc64-unknown-netbsd \
// RUN: -no-integrated-as --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC64 %s
-// RUN: %clang -no-canonical-prefixes -target powerpc--netbsd \
+// RUN: %clang -no-canonical-prefixes -target powerpc-unknown-netbsd \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=POWERPC %s
-// RUN: %clang -no-canonical-prefixes -target powerpc64--netbsd \
+// RUN: %clang -no-canonical-prefixes -target powerpc64-unknown-netbsd \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=POWERPC64 %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd -static \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-X86_64 %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd7.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-X86_64-7 %s
-// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd6.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-X86_64-6 %s
-// RUN: %clang -no-canonical-prefixes -target aarch64--netbsd -static \
+// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64 %s
-// RUN: %clang -no-canonical-prefixes -target aarch64--netbsd7.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64-7 %s
-// RUN: %clang -no-canonical-prefixes -target aarch64_be--netbsd -static \
+// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64_BE %s
-// RUN: %clang -no-canonical-prefixes -target aarch64_be--netbsd7.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64_BE-7 %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd-eabi -static \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd-eabi -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-ARM %s
-// RUN: %clang -no-canonical-prefixes -target armeb--netbsd-eabi -static \
+// RUN: %clang -no-canonical-prefixes -target armeb-unknown-netbsd-eabi -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-ARMEB %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd7.0.0-eabi -static \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-ARM-7 %s
-// RUN: %clang -no-canonical-prefixes -target arm--netbsd6.0.0-eabi -static \
+// RUN: %clang -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-ARM-6 %s
-// RUN: %clang -no-canonical-prefixes -target sparc--netbsd7.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target sparc-unknown-netbsd7.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC-7 %s
-// RUN: %clang -no-canonical-prefixes -target sparc--netbsd6.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target sparc-unknown-netbsd6.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC-6 %s
-// RUN: %clang -no-canonical-prefixes -target sparc64--netbsd7.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target sparc64-unknown-netbsd7.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC64-7 %s
-// RUN: %clang -no-canonical-prefixes -target sparc64--netbsd6.0.0 -static \
+// RUN: %clang -no-canonical-prefixes -target sparc64-unknown-netbsd6.0.0 -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC64-6 %s
-// RUN: %clang -no-canonical-prefixes -target powerpc--netbsd -static \
+// RUN: %clang -no-canonical-prefixes -target powerpc-unknown-netbsd -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-POWERPC %s
-// RUN: %clang -no-canonical-prefixes -target powerpc64--netbsd -static \
+// RUN: %clang -no-canonical-prefixes -target powerpc64-unknown-netbsd -static \
// RUN: --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-POWERPC64 %s
-// RUN: %clang -target x86_64--netbsd -pthread -dM -E %s \
+// RUN: %clang -target x86_64-unknown-netbsd -pthread -dM -E %s \
// RUN: | FileCheck -check-prefix=PTHREAD %s
// STATIC: ld{{.*}}" "--eh-frame-hdr"
@@ -168,49 +168,49 @@
// PIE: "{{.*}}/usr/lib{{/|\\\\}}crtendS.o"
// PIE: "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd"
+// X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd"
// X86_64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd7.0.0"
+// X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0"
// X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd6.0.0"
+// X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0"
// X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd"
+// AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd"
// AARCH64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd7.0.0"
+// AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0"
// AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd"
+// AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd"
// AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd7.0.0"
+// AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0"
// AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// ARM: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd-eabi"
+// ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabi"
// ARM: as{{.*}}" "-mcpu=arm926ej-s" "-o"
// ARM: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARM: "-m" "armelf_nbsd_eabi"
@@ -219,7 +219,7 @@
// ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// ARMEB: clang{{.*}}" "-cc1" "-triple" "armebv5e--netbsd-eabi"
+// ARMEB: clang{{.*}}" "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi"
// ARMEB: as{{.*}}" "-mcpu=arm926ej-s" "-o"
// ARMEB: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARMEB-NOT: "--be8"
@@ -234,7 +234,7 @@
// ARMEB-R: ld{{.*}}"
// ARMEB-R-NOT: "--be8"
-// ARM-APCS: clang{{.*}}" "-cc1" "-triple" "armv4--netbsd"
+// ARM-APCS: clang{{.*}}" "-cc1" "-triple" "armv4-unknown-netbsd"
// ARM-APCS: as{{.*}}" "-mcpu=strongarm" "-o"
// ARM-APCS: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARM-APCS: "-m" "armelf_nbsd"
@@ -243,7 +243,7 @@
// ARM-APCS: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// ARM-APCS: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// ARM-HF: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd-eabihf"
+// ARM-HF: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabihf"
// ARM-HF: as{{.*}}" "-mcpu=arm926ej-s" "-o"
// ARM-HF: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARM-HF: "-m" "armelf_nbsd_eabihf"
@@ -252,7 +252,7 @@
// ARM-HF: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// ARM-HF: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// THUMB: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd-eabi"
+// THUMB: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabi"
// THUMB: as{{.*}}" "-mcpu=arm926ej-s" "-o"
// THUMB: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// THUMB: "-m" "armelf_nbsd_eabi"
@@ -261,7 +261,7 @@
// THUMB: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// THUMB: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// THUMBEB: clang{{.*}}" "-cc1" "-triple" "armebv5e--netbsd-eabi"
+// THUMBEB: clang{{.*}}" "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi"
// THUMBEB: as{{.*}}" "-mcpu=arm926ej-s" "-o"
// THUMBEB: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// THUMBEB: "-m" "armelfb_nbsd_eabi"
@@ -270,7 +270,7 @@
// THUMBEB: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// THUMBEB: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd7.0.0-eabi"
+// ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi"
// ARM-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARM-7: "-m" "armelf_nbsd_eabi"
// ARM-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -278,7 +278,7 @@
// ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// ARM-6: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd6.0.0-eabi"
+// ARM-6: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi"
// ARM-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARM-6: "-m" "armelf_nbsd_eabi"
// ARM-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -286,7 +286,7 @@
// ARM-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// ARM-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd"
+// SPARC: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd"
// SPARC: as{{.*}}" "-32" "-Av8" "-o"
// SPARC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC: "-m" "elf32_sparc"
@@ -295,7 +295,7 @@
// SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd"
+// SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd"
// SPARC64: as{{.*}}" "-64" "-Av9" "-o"
// SPARC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC64: "-m" "elf64_sparc"
@@ -303,7 +303,7 @@
// SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc--netbsd"
+// POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd"
// POWERPC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// POWERPC: "-m" "elf32ppc_nbsd"
// POWERPC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -311,7 +311,7 @@
// POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64--netbsd"
+// POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd"
// POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// POWERPC64: "-m" "elf64ppc"
// POWERPC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -319,50 +319,50 @@
// POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd"
+// S-X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd"
// S-X86_64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd7.0.0"
+// S-X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0"
// S-X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd6.0.0"
+// S-X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0"
// S-X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-X86_64-6: "-lgcc_eh" "-lc" "-lgcc"
// S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd"
+// S-AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd"
// S-AARCH64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd7.0.0"
+// S-AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0"
// S-AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd"
+// S-AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd"
// S-AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd7.0.0"
+// S-AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0"
// S-AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-ARM: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd-eabi"
+// S-ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd-eabi"
// S-ARM: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-ARM: "-m" "armelf_nbsd_eabi"
// S-ARM: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -370,7 +370,7 @@
// S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-ARMEB: clang{{.*}}" "-cc1" "-triple" "armebv5e--netbsd-eabi"
+// S-ARMEB: clang{{.*}}" "-cc1" "-triple" "armebv5e-unknown-netbsd-eabi"
// S-ARMEB: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-ARMEB: "-m" "armelfb_nbsd_eabi"
// S-ARMEB: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -378,7 +378,7 @@
// S-ARMEB: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-ARMEB: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd7.0.0-eabi"
+// S-ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi"
// S-ARM-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-ARM-7: "-m" "armelf_nbsd_eabi"
// S-ARM-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -386,7 +386,7 @@
// S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-ARM-6: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd6.0.0-eabi"
+// S-ARM-6: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi"
// S-ARM-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-ARM-6: "-m" "armelf_nbsd_eabi"
// S-ARM-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -395,7 +395,7 @@
// S-ARM-6: "-lgcc_eh" "-lc" "-lgcc"
// S-ARM-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd6.0.0"
+// S-SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd6.0.0"
// S-SPARC-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC-6: "-m" "elf32_sparc"
// S-SPARC-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -404,7 +404,7 @@
// S-SPARC-6: "-lgcc_eh" "-lc" "-lgcc"
// S-SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd7.0.0"
+// S-SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd7.0.0"
// S-SPARC-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC-7: "-m" "elf32_sparc"
// S-SPARC-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -412,7 +412,7 @@
// S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd6.0.0"
+// S-SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0"
// S-SPARC64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC64-6: "-m" "elf64_sparc"
// S-SPARC64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
@@ -420,14 +420,14 @@
// S-SPARC64-6: "-lgcc_eh" "-lc" "-lgcc"
// S-SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd7.0.0"
+// S-SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0"
// S-SPARC64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC64-7: "-m" "elf64_sparc"
// S-SPARC64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc--netbsd"
+// S-POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd"
// S-POWERPC: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-POWERPC: "-m" "elf32ppc_nbsd"
// S-POWERPC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
@@ -435,7 +435,7 @@
// S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc"
// S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64--netbsd"
+// S-POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd"
// S-POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-POWERPC64: "-m" "elf64ppc"
// S-POWERPC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
diff --git a/test/Driver/netbsd.cpp b/test/Driver/netbsd.cpp
index e9b1759831b2..4af7d8373d67 100644
--- a/test/Driver/netbsd.cpp
+++ b/test/Driver/netbsd.cpp
@@ -1,168 +1,168 @@
-// RUN: %clangxx -no-canonical-prefixes -target x86_64--netbsd \
+// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=X86_64 %s
-// RUN: %clangxx -no-canonical-prefixes -target x86_64--netbsd7.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=X86_64-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target x86_64--netbsd6.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=X86_64-6 %s
-// RUN: %clangxx -no-canonical-prefixes -target arm--netbsd6.0.0-eabi \
+// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARM %s
-// RUN: %clangxx -no-canonical-prefixes -target arm--netbsd7.0.0-eabi \
+// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=ARM-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64--netbsd \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64 %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64--netbsd7.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64_be--netbsd \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64_BE %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64_be--netbsd7.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=AARCH64_BE-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc--netbsd \
+// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc--netbsd6.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd6.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC-6 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc--netbsd7.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd7.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc64--netbsd \
+// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC64 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc64--netbsd6.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd6.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC64-6 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc64--netbsd7.0.0 \
+// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd7.0.0 \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=SPARC64-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target powerpc--netbsd \
+// RUN: %clangxx -no-canonical-prefixes -target powerpc-unknown-netbsd \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=POWERPC %s
-// RUN: %clangxx -no-canonical-prefixes -target powerpc64--netbsd \
+// RUN: %clangxx -no-canonical-prefixes -target powerpc64-unknown-netbsd \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=POWERPC64 %s
-// RUN: %clangxx -no-canonical-prefixes -target x86_64--netbsd -static \
+// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-X86_64 %s
-// RUN: %clangxx -no-canonical-prefixes -target x86_64--netbsd7.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd7.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-X86_64-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target x86_64--netbsd6.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target x86_64-unknown-netbsd6.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-X86_64-6 %s
-// RUN: %clangxx -no-canonical-prefixes -target arm--netbsd6.0.0-eabi -static \
+// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd6.0.0-eabi -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-ARM %s
-// RUN: %clangxx -no-canonical-prefixes -target arm--netbsd7.0.0-eabi -static \
+// RUN: %clangxx -no-canonical-prefixes -target arm-unknown-netbsd7.0.0-eabi -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-ARM-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64--netbsd -static \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64 %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64--netbsd7.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64-unknown-netbsd7.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64_be--netbsd -static \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64_BE %s
-// RUN: %clangxx -no-canonical-prefixes -target aarch64_be--netbsd7.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target aarch64_be-unknown-netbsd7.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-AARCH64_BE-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc--netbsd -static \
+// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc--netbsd6.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd6.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC-6 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc--netbsd7.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target sparc-unknown-netbsd7.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc64--netbsd -static \
+// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC64 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc64--netbsd6.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd6.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC64-6 %s
-// RUN: %clangxx -no-canonical-prefixes -target sparc64--netbsd7.0.0 -static \
+// RUN: %clangxx -no-canonical-prefixes -target sparc64-unknown-netbsd7.0.0 -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-SPARC64-7 %s
-// RUN: %clangxx -no-canonical-prefixes -target powerpc--netbsd -static \
+// RUN: %clangxx -no-canonical-prefixes -target powerpc-unknown-netbsd -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-POWERPC %s
-// RUN: %clangxx -no-canonical-prefixes -target powerpc64--netbsd -static \
+// RUN: %clangxx -no-canonical-prefixes -target powerpc64-unknown-netbsd -static \
// RUN: -stdlib=platform --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \
// RUN: | FileCheck -check-prefix=S-POWERPC64 %s
-// X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd"
+// X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd"
// X86_64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// X86_64: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd7.0.0"
+// X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0"
// X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// X86_64-7: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd6.0.0"
+// X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0"
// X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++"
// X86_64-6: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
// X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// ARM: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd6.0.0-eabi"
+// ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi"
// ARM: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARM: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o"
// ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++"
// ARM: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
// ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd7.0.0-eabi"
+// ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi"
// ARM-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// ARM-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o"
// ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" "-lm" "-lc"
// ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd"
+// AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd"
// AARCH64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// AARCH64: "-lm" "-lc"
// AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd7.0.0"
+// AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0"
// AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// AARCH64-7: "-lm" "-lc"
// AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd"
+// AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd"
// AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// AARCH64_BE: "-lm" "-lc"
// AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd7.0.0"
+// AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0"
// AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// AARCH64_BE-7: "-lm" "-lc"
// AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd"
+// SPARC: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd"
// SPARC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// SPARC: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o"
@@ -170,7 +170,7 @@
// SPARC: "-lm" "-lc"
// SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd7.0.0"
+// SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd7.0.0"
// SPARC-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o"
@@ -178,7 +178,7 @@
// SPARC-7: "-lm" "-lc"
// SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd6.0.0"
+// SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd6.0.0"
// SPARC-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o"
@@ -186,102 +186,102 @@
// SPARC-6: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
// SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd"
+// SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd"
// SPARC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// SPARC64: "-lm" "-lc"
// SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd7.0.0"
+// SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0"
// SPARC64-7: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// SPARC64-7: "-lm" "-lc"
// SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd6.0.0"
+// SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0"
// SPARC64-6: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// SPARC64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++"
// SPARC64-6: "-lm" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
// SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc--netbsd"
+// POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd"
// POWERPC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// POWERPC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// POWERPC: "{{.*}}/usr/lib{{/|\\\\}}powerpc{{/|\\\\}}crti.o"
// POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// POWERPC: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64--netbsd"
+// POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd"
// POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "/libexec/ld.elf_so"
// POWERPC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// POWERPC64: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd"
+// S-X86_64: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd"
// S-X86_64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-X86_64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-X86_64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-X86_64: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd7.0.0"
+// S-X86_64-7: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd7.0.0"
// S-X86_64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-X86_64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-X86_64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-X86_64-7: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64--netbsd6.0.0"
+// S-X86_64-6: clang{{.*}}" "-cc1" "-triple" "x86_64-unknown-netbsd6.0.0"
// S-X86_64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-X86_64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++"
// S-X86_64-6: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc"
// S-X86_64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-ARM: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd6.0.0-eabi"
+// S-ARM: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd6.0.0-eabi"
// S-ARM: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-ARM: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o"
// S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++"
// S-ARM: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc"
// S-ARM: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e--netbsd7.0.0-eabi"
+// S-ARM-7: clang{{.*}}" "-cc1" "-triple" "armv5e-unknown-netbsd7.0.0-eabi"
// S-ARM-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-ARM-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}eabi{{/|\\\\}}crti.o"
// S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++" "-lm" "-lc"
// S-ARM-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd"
+// S-AARCH64: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd"
// S-AARCH64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-AARCH64: "-lm" "-lc"
// S-AARCH64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64--netbsd7.0.0"
+// S-AARCH64-7: clang{{.*}}" "-cc1" "-triple" "aarch64-unknown-netbsd7.0.0"
// S-AARCH64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-AARCH64-7: "-lm" "-lc"
// S-AARCH64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd"
+// S-AARCH64_BE: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd"
// S-AARCH64_BE: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64_BE: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-AARCH64_BE: "-lm" "-lc"
// S-AARCH64_BE: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be--netbsd7.0.0"
+// S-AARCH64_BE-7: clang{{.*}}" "-cc1" "-triple" "aarch64_be-unknown-netbsd7.0.0"
// S-AARCH64_BE-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-AARCH64_BE-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-AARCH64_BE-7: "-lm" "-lc"
// S-AARCH64_BE-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd"
+// S-SPARC: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd"
// S-SPARC: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// S-SPARC: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o"
@@ -289,7 +289,7 @@
// S-SPARC: "-lm" "-lc"
// S-SPARC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd7.0.0"
+// S-SPARC-7: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd7.0.0"
// S-SPARC-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o"
@@ -297,7 +297,7 @@
// S-SPARC-7: "-lm" "-lc"
// S-SPARC-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc--netbsd6.0.0"
+// S-SPARC-6: clang{{.*}}" "-cc1" "-triple" "sparc-unknown-netbsd6.0.0"
// S-SPARC-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// S-SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}sparc{{/|\\\\}}crti.o"
@@ -305,35 +305,35 @@
// S-SPARC-6: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc"
// S-SPARC-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd"
+// S-SPARC64: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd"
// S-SPARC64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-SPARC64: "-lm" "-lc"
// S-SPARC64: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd7.0.0"
+// S-SPARC64-7: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd7.0.0"
// S-SPARC64-7: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC64-7: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-SPARC64-7: "-lm" "-lc"
// S-SPARC64-7: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64--netbsd6.0.0"
+// S-SPARC64-6: clang{{.*}}" "-cc1" "-triple" "sparc64-unknown-netbsd6.0.0"
// S-SPARC64-6: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-SPARC64-6: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o" "{{.*}}/usr/lib{{/|\\\\}}crti.o"
// S-SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lstdc++"
// S-SPARC64-6: "-lm" "-lc" "-lgcc_eh" "-lc" "-lgcc"
// S-SPARC64-6: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc--netbsd"
+// S-POWERPC: clang{{.*}}" "-cc1" "-triple" "powerpc-unknown-netbsd"
// S-POWERPC: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-POWERPC: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}powerpc{{/|\\\\}}crti.o"
// S-POWERPC: "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" "{{.*}}.o" "-lc++"
// S-POWERPC: "-lm" "-lc" "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o"
-// S-POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64--netbsd"
+// S-POWERPC64: clang{{.*}}" "-cc1" "-triple" "powerpc64-unknown-netbsd"
// S-POWERPC64: ld{{.*}}" "--eh-frame-hdr" "-Bstatic"
// S-POWERPC64: "-o" "a.out" "{{.*}}/usr/lib{{/|\\\\}}crt0.o"
// S-POWERPC64: "{{.*}}/usr/lib{{/|\\\\}}crti.o"
diff --git a/test/Driver/nios2-cpu.c b/test/Driver/nios2-cpu.c
deleted file mode 100644
index d98f0384a66d..000000000000
--- a/test/Driver/nios2-cpu.c
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: %clang -target nios2--- %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck %s
-
-// RUN: %clang -target nios2--- -mcpu=r1 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R1 %s
-// RUN: %clang -target nios2--- -mcpu=nios2r1 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R1 %s
-// RUN: %clang -target nios2--- -march=r1 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R1 %s
-// RUN: %clang -target nios2--- -march=nios2r1 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R1 %s
-
-// RUN: %clang -target nios2--- -mcpu=r2 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R2 %s
-// RUN: %clang -target nios2--- -mcpu=nios2r2 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R2 %s
-// RUN: %clang -target nios2--- -march=r2 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R2 %s
-// RUN: %clang -target nios2--- -march=nios2r2 %s -### -o %t.o 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-R2 %s
-
-// CHECK: "-triple" "nios2---"
-// CHECK-R1: "-triple" "nios2---"
-// CHECK-R1: "-target-cpu" "nios2r1"
-// CHECK-R2: "-triple" "nios2---"
-// CHECK-R2: "-target-cpu" "nios2r2"
diff --git a/test/Driver/no-integrated-as.c b/test/Driver/no-integrated-as.c
index 812ab1e6463f..12717158a5cc 100644
--- a/test/Driver/no-integrated-as.c
+++ b/test/Driver/no-integrated-as.c
@@ -9,11 +9,6 @@
// IAS-NOT: -no-integrated-as
// RUN: %clang -target i386 -### -c %s 2>&1 | FileCheck %s -check-prefix DEFAULT
+// RUN: %clang -target msp430 -### -c %s 2>&1 | FileCheck %s -check-prefix DEFAULT
// DEFAULT-NOT: -no-integrated-as
-
-// RUN: %clang -target msp430 -### -c %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix NO-IAS-DEFAULT
-
-// NO-IAS-DEFAULT: -no-integrated-as
-
diff --git a/test/Driver/no-integrated-as.s b/test/Driver/no-integrated-as.s
index cd6f5e2867a4..bf6e69dd8196 100644
--- a/test/Driver/no-integrated-as.s
+++ b/test/Driver/no-integrated-as.s
@@ -1,6 +1,6 @@
; RUN: %clang -### -no-integrated-as -c %s 2>&1 | FileCheck %s -check-prefix IAS
; Windows doesn't support no-integrated-as
-; XFAIL: win32,win64
+; XFAIL: windows-msvc
;
; Make sure the current file's filename appears in the output.
; We can't generically match on the assembler name, so we just make sure
diff --git a/test/Driver/nostdlibxx.cpp b/test/Driver/nostdlibxx.cpp
index 02bd62d96af5..48d14e15a61f 100644
--- a/test/Driver/nostdlibxx.cpp
+++ b/test/Driver/nostdlibxx.cpp
@@ -6,3 +6,12 @@
// CHECK-NOT: -lstdc++
// CHECK-NOT: -lc++
// CHECK: -lm
+
+// Make sure -lstdc++ isn't rewritten to the default stdlib when -nostdlib++ is
+// used.
+//
+// RUN: %clangxx -target i686-pc-linux-gnu -### \
+// RUN: -nostdlib++ -stdlib=libc++ -lstdc++ %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-RESERVED-LIB-REWRITE < %t %s
+// CHECK-RESERVED-LIB-REWRITE: -lstdc++
+// CHECK-RESERVED-LIB-REWRITE-NOT: -lc++
diff --git a/test/Driver/objc-convert-messages-to-runtime-calls.m b/test/Driver/objc-convert-messages-to-runtime-calls.m
new file mode 100644
index 000000000000..ed7be571eb57
--- /dev/null
+++ b/test/Driver/objc-convert-messages-to-runtime-calls.m
@@ -0,0 +1,7 @@
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fobjc-convert-messages-to-runtime-calls -fno-objc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck %s --check-prefix=DISABLE
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fno-objc-convert-messages-to-runtime-calls -fobjc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck %s --check-prefix=ENABLE
+
+// Check that we pass fobjc-convert-messages-to-runtime-calls only when supported, and not explicitly disabled.
+
+// DISABLE: "-fno-objc-convert-messages-to-runtime-calls"
+// ENABLE-NOT: "-fno-objc-convert-messages-to-runtime-calls"
diff --git a/test/Driver/offloading-interoperability.c b/test/Driver/offloading-interoperability.c
index ab5132297aab..75d2ce9239dd 100644
--- a/test/Driver/offloading-interoperability.c
+++ b/test/Driver/offloading-interoperability.c
@@ -12,6 +12,6 @@
// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NOT: -fopenmp
// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: ptxas" "-m64"
// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: fatbinary" "--cuda" "-64"
-// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux-gnu"
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux-gnu"
// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE: -fopenmp
// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: {{ld(.exe)?"}} {{.*}}"-m" "elf64lppc"
diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c
index d3846b7acf66..59ec8833719a 100644
--- a/test/Driver/openbsd.c
+++ b/test/Driver/openbsd.c
@@ -1,18 +1,18 @@
// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-LD %s
// CHECK-LD: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
-// CHECK-LD: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-LD: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// Check for --eh-frame-hdr being passed with static linking
// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -static %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-LD-STATIC-EH %s
// CHECK-LD-STATIC-EH: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
-// CHECK-LD-STATIC-EH: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bstatic" "-o" "a.out" "{{.*}}rcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-LD-STATIC-EH: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bstatic" "-o" "a.out" "{{.*}}rcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -pg -pthread %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-PG %s
// CHECK-PG: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
-// CHECK-PG: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}gcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lpthread_p" "-lc_p" "-lgcc" "{{.*}}crtend.o"
+// CHECK-PG: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-nopie" "-o" "a.out" "{{.*}}gcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lcompiler_rt" "-lpthread_p" "-lc_p" "-lcompiler_rt" "{{.*}}crtend.o"
// Check CPU type for MIPS64
// RUN: %clang -target mips64-unknown-openbsd -### -c %s 2>&1 \
@@ -36,17 +36,17 @@
// RUN: %clang -no-canonical-prefixes -target mips64el-unknown-openbsd %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-LD %s
// CHECK-LD-R: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
-// CHECK-LD-R: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-r" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-LD-R: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-r" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// CHECK-LD-S: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
-// CHECK-LD-S: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-s" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-LD-S: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-s" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// CHECK-LD-T: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
-// CHECK-LD-T: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-t" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-LD-T: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-t" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// CHECK-LD-Z: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
-// CHECK-LD-Z: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-Z" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-LD-Z: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-Z" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// CHECK-MIPS64-LD: clang{{.*}}" "-cc1" "-triple" "mips64-unknown-openbsd"
-// CHECK-MIPS64-LD: ld{{.*}}" "-EB" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-MIPS64-LD: ld{{.*}}" "-EB" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// CHECK-MIPS64EL-LD: clang{{.*}}" "-cc1" "-triple" "mips64el-unknown-openbsd"
-// CHECK-MIPS64EL-LD: ld{{.*}}" "-EL" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o"
+// CHECK-MIPS64EL-LD: ld{{.*}}" "-EL" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "{{.*}}.o" "-lcompiler_rt" "-lc" "-lcompiler_rt" "{{.*}}crtend.o"
// Check passing options to the assembler for various OpenBSD targets
// RUN: %clang -target amd64-pc-openbsd -m32 -### -no-integrated-as -c %s 2>&1 \
@@ -74,12 +74,16 @@
// CHECK-MIPS64EL: as{{.*}}" "-mabi" "64" "-EL"
// CHECK-MIPS64EL-PIC: as{{.*}}" "-mabi" "64" "-EL" "-KPIC"
-// Check that the integrated assembler is enabled for MIPS64
+// Check that the integrated assembler is enabled for MIPS64/SPARC
// RUN: %clang -target mips64-unknown-openbsd -### -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s
+// RUN: | FileCheck -check-prefix=CHECK-IAS %s
// RUN: %clang -target mips64el-unknown-openbsd -### -c %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s
-// CHECK-MIPS64-AS-NOT: "-no-integrated-as"
+// RUN: | FileCheck -check-prefix=CHECK-IAS %s
+// RUN: %clang -target sparc-unknown-openbsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-IAS %s
+// RUN: %clang -target sparc64-unknown-openbsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-IAS %s
+// CHECK-IAS-NOT: "-no-integrated-as"
// Check linking against correct startup code when (not) using PIE
// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -### 2>&1 \
@@ -112,3 +116,8 @@
// RUN: | FileCheck -check-prefix=CHECK-ARM-FLOAT-ABI %s
// CHECK-ARM-FLOAT-ABI-NOT: "-target-feature" "+soft-float"
// CHECK-ARM-FLOAT-ABI: "-target-feature" "+soft-float-abi"
+
+// Check PowerPC for Secure PLT
+// RUN: %clang -target powerpc-unknown-openbsd -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-POWERPC-SECUREPLT %s
+// CHECK-POWERPC-SECUREPLT: "-target-feature" "+secure-plt"
diff --git a/test/Driver/openbsd.cpp b/test/Driver/openbsd.cpp
new file mode 100644
index 000000000000..9293148680c8
--- /dev/null
+++ b/test/Driver/openbsd.cpp
@@ -0,0 +1,19 @@
+// RUN: %clangxx %s -### -o %t.o -target amd64-pc-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CXX %s
+// RUN: %clangxx %s -### -o %t.o -target i686-pc-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CXX %s
+// RUN: %clangxx %s -### -o %t.o -target aarch64-unknown-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CXX %s
+// RUN: %clangxx %s -### -o %t.o -target arm-unknown-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-CXX %s
+// CHECK-CXX: "-lc++" "-lc++abi" "-lm"
+
+// RUN: %clangxx %s -### -pg -o %t.o -target amd64-pc-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s
+// RUN: %clangxx %s -### -pg -o %t.o -target i686-pc-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s
+// RUN: %clangxx %s -### -pg -o %t.o -target aarch64-unknown-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s
+// RUN: %clangxx %s -### -pg -o %t.o -target arm-unknown-openbsd 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s
+// CHECK-PG-CXX: "-lc++_p" "-lc++abi_p" "-lm_p"
diff --git a/test/Driver/openmp-offload-gpu.c b/test/Driver/openmp-offload-gpu.c
index ca3d9445443d..dfdc79b5f70c 100644
--- a/test/Driver/openmp-offload-gpu.c
+++ b/test/Driver/openmp-offload-gpu.c
@@ -30,6 +30,22 @@
/// ###########################################################################
+/// Check that -lomptarget-nvptx is passed to nvlink.
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp \
+// RUN: -fopenmp-targets=nvptx64-nvidia-cuda %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-NVLINK %s
+/// Check that the value of --libomptarget-nvptx-path is forwarded to nvlink.
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp \
+// RUN: --libomptarget-nvptx-path=/path/to/libomptarget/ \
+// RUN: -fopenmp-targets=nvptx64-nvidia-cuda %s 2>&1 \
+// RUN: | FileCheck -check-prefixes=CHK-NVLINK,CHK-LIBOMPTARGET-NVPTX-PATH %s
+
+// CHK-NVLINK: nvlink
+// CHK-LIBOMPTARGET-NVPTX-PATH-SAME: "-L/path/to/libomptarget/"
+// CHK-NVLINK-SAME: "-lomptarget-nvptx"
+
+/// ###########################################################################
+
/// Check cubin file generation and usage by nvlink
// RUN: %clang -### -no-canonical-prefixes -target powerpc64le-unknown-linux-gnu -fopenmp=libomp \
// RUN: -fopenmp-targets=nvptx64-nvidia-cuda -save-temps %s 2>&1 \
@@ -73,13 +89,15 @@
/// Check cubin file unbundling and usage by nvlink
// RUN: touch %t.o
// RUN: %clang -### -target powerpc64le-unknown-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
-// RUN: -no-canonical-prefixes -save-temps %t.o 2>&1 \
+// RUN: -no-canonical-prefixes -save-temps %t.o %S/Inputs/in.so 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-CUBIN-UNBUNDLING-NVLINK %s
/// Use DAG to ensure that cubin file has been unbundled.
+// CHK-CUBIN-UNBUNDLING-NVLINK-NOT: clang-offload-bundler{{.*}}" "-type=o"{{.*}}in.so
// CHK-CUBIN-UNBUNDLING-NVLINK-DAG: nvlink{{.*}}" {{.*}}"[[CUBIN:.*\.cubin]]"
// CHK-CUBIN-UNBUNDLING-NVLINK-DAG: clang-offload-bundler{{.*}}" "-type=o" {{.*}}"-outputs={{.*}}[[CUBIN]]
// CHK-CUBIN-UNBUNDLING-NVLINK-DAG-SAME: "-unbundle"
+// CHK-CUBIN-UNBUNDLING-NVLINK-NOT: clang-offload-bundler{{.*}}" "-type=o"{{.*}}in.so
/// ###########################################################################
@@ -151,8 +169,13 @@
// RUN: -Xopenmp-target -march=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda \
// RUN: -fopenmp-relocatable-target -save-temps -no-canonical-prefixes %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-BCLIB %s
+/// The user can override default detection using --libomptarget-nvptx-path=.
+// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda --libomptarget-nvptx-path=%S/Inputs/libomptarget \
+// RUN: -Xopenmp-target -march=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda \
+// RUN: -fopenmp-relocatable-target -save-temps -no-canonical-prefixes %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BCLIB %s
-// CHK-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-cuda-bitcode{{.*}}libomptarget-nvptx-sm_20.bc
+// CHK-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget-nvptx-sm_20.bc
// CHK-BCLIB-NOT: {{error:|warning:}}
/// ###########################################################################
@@ -167,29 +190,35 @@
// CHK-BCLIB-WARN: No library 'libomptarget-nvptx-sm_20.bc' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.
/// Check that debug info is emitted in dwarf-2
-// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O0 --no-cuda-noopt-device-debug 2>&1 \
-// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O1 --no-cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=DEBUG_DIRECTIVES %s
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O3 2>&1 \
-// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: | FileCheck -check-prefix=DEBUG_DIRECTIVES %s
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O3 --no-cuda-noopt-device-debug 2>&1 \
-// RUN: | FileCheck -check-prefix=NO_DEBUG %s
+// RUN: | FileCheck -check-prefix=DEBUG_DIRECTIVES %s
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g0 2>&1 \
// RUN: | FileCheck -check-prefix=NO_DEBUG %s
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb0 -O3 --cuda-noopt-device-debug 2>&1 \
// RUN: | FileCheck -check-prefix=NO_DEBUG %s
-// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -gline-tables-only 2>&1 \
-// RUN: | FileCheck -check-prefix=NO_DEBUG -check-prefix=LINE_TABLE %s
-// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb1 -O2 --cuda-noopt-device-debug 2>&1 \
-// RUN: | FileCheck -check-prefix=NO_DEBUG -check-prefix=LINE_TABLE %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -gline-directives-only 2>&1 \
+// RUN: | FileCheck -check-prefix=DEBUG_DIRECTIVES %s
-// LINE_TABLE-NOT: warning: debug
+// DEBUG_DIRECTIVES-NOT: warning: debug
// NO_DEBUG-NOT: warning: debug
+// NO_DEBUG: "-fopenmp-is-device"
+// NO_DEBUG-NOT: "-debug-info-kind=
// NO_DEBUG: ptxas
-// LINE_TABLE: "-lineinfo"
+// DEBUG_DIRECTIVES: "-triple" "nvptx64-nvidia-cuda"
+// DEBUG_DIRECTIVES-SAME: "-debug-info-kind=line-directives-only"
+// DEBUG_DIRECTIVES-SAME: "-fopenmp-is-device"
+// DEBUG_DIRECTIVES: ptxas
+// DEBUG_DIRECTIVES: "-lineinfo"
// NO_DEBUG-NOT: "-g"
// NO_DEBUG: nvlink
// NO_DEBUG-NOT: "-g"
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O0 --no-cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g 2>&1 \
// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -g -O0 --cuda-noopt-device-debug 2>&1 \
@@ -204,9 +233,14 @@
// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb3 -O2 --cuda-noopt-device-debug 2>&1 \
// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -gline-tables-only 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb1 -O2 --cuda-noopt-device-debug 2>&1 \
+// RUN: | FileCheck -check-prefix=HAS_DEBUG %s
// HAS_DEBUG-NOT: warning: debug
// HAS_DEBUG: "-triple" "nvptx64-nvidia-cuda"
+// HAS_DEBUG-SAME: "-debug-info-kind={{limited|line-tables-only}}"
// HAS_DEBUG-SAME: "-dwarf-version=2"
// HAS_DEBUG-SAME: "-fopenmp-is-device"
// HAS_DEBUG: ptxas
@@ -216,3 +250,26 @@
// HAS_DEBUG: nvlink
// HAS_DEBUG-SAME: "-g"
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fopenmp-cuda-mode 2>&1 \
+// RUN: | FileCheck -check-prefix=CUDA_MODE %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fno-openmp-cuda-mode -fopenmp-cuda-mode 2>&1 \
+// RUN: | FileCheck -check-prefix=CUDA_MODE %s
+// CUDA_MODE: clang{{.*}}"-cc1"{{.*}}"-triple" "nvptx64-nvidia-cuda"
+// CUDA_MODE-SAME: "-fopenmp-cuda-mode"
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fno-openmp-cuda-mode 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_CUDA_MODE %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fopenmp-cuda-mode -fno-openmp-cuda-mode 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_CUDA_MODE %s
+// NO_CUDA_MODE-NOT: "-{{fno-|f}}openmp-cuda-mode"
+
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fopenmp-cuda-force-full-runtime 2>&1 \
+// RUN: | FileCheck -check-prefix=FULL_RUNTIME %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fno-openmp-cuda-force-full-runtime -fopenmp-cuda-force-full-runtime 2>&1 \
+// RUN: | FileCheck -check-prefix=FULL_RUNTIME %s
+// FULL_RUNTIME: clang{{.*}}"-cc1"{{.*}}"-triple" "nvptx64-nvidia-cuda"
+// FULL_RUNTIME-SAME: "-fopenmp-cuda-force-full-runtime"
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fno-openmp-cuda-force-full-runtime 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_FULL_RUNTIME %s
+// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -fopenmp-cuda-force-full-runtime -fno-openmp-cuda-force-full-runtime 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_FULL_RUNTIME %s
+// NO_FULL_RUNTIME-NOT: "-{{fno-|f}}openmp-cuda-force-full-runtime"
diff --git a/test/Driver/openmp-offload.c b/test/Driver/openmp-offload.c
index 67098c902238..ac0190af876e 100644
--- a/test/Driver/openmp-offload.c
+++ b/test/Driver/openmp-offload.c
@@ -294,27 +294,27 @@
//
// Generate host BC file.
//
-// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-o" "
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" "
// CHK-COMMANDS-SAME: [[INPUT:[^\\/]+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" "
// CHK-COMMANDS-ST-SAME: [[INPUT:[^\\/]+\.c]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
//
// Compile for the powerpc device.
//
-// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
@@ -323,15 +323,15 @@
//
// Compile for the x86 device.
//
-// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
@@ -341,14 +341,14 @@
//
// Generate host object from the BC file and link using the linker script.
//
-// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-COMMANDS-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"-lomptarget" {{.*}}"-T" "
// CHK-COMMANDS-SAME: [[HOSTLK:[^\\/]+\.lk]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
-// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
// CHK-COMMANDS-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-COMMANDS-ST-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"-lomptarget" {{.*}}"-T" "
@@ -358,7 +358,7 @@
/// ###########################################################################
/// Check separate compilation with offloading - bundling actions
-// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \
+// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -c -o %t.o %S/Input/in.so -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-BUACTIONS %s
// CHK-BUACTIONS: 0: input, "[[INPUT:.+\.c]]", c, (host-openmp)
@@ -367,14 +367,14 @@
// CHK-BUACTIONS: 3: input, "[[INPUT]]", c, (device-openmp)
// CHK-BUACTIONS: 4: preprocessor, {3}, cpp-output, (device-openmp)
// CHK-BUACTIONS: 5: compiler, {4}, ir, (device-openmp)
-// CHK-BUACTIONS: 6: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (powerpc64le-ibm-linux-gnu)" {5}, ir
+// CHK-BUACTIONS: 6: offload, "host-openmp (powerpc64le-unknown-linux)" {2}, "device-openmp (powerpc64le-ibm-linux-gnu)" {5}, ir
// CHK-BUACTIONS: 7: backend, {6}, assembler, (device-openmp)
// CHK-BUACTIONS: 8: assembler, {7}, object, (device-openmp)
// CHK-BUACTIONS: 9: offload, "device-openmp (powerpc64le-ibm-linux-gnu)" {8}, object
// CHK-BUACTIONS: 10: input, "[[INPUT]]", c, (device-openmp)
// CHK-BUACTIONS: 11: preprocessor, {10}, cpp-output, (device-openmp)
// CHK-BUACTIONS: 12: compiler, {11}, ir, (device-openmp)
-// CHK-BUACTIONS: 13: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (x86_64-pc-linux-gnu)" {12}, ir
+// CHK-BUACTIONS: 13: offload, "host-openmp (powerpc64le-unknown-linux)" {2}, "device-openmp (x86_64-pc-linux-gnu)" {12}, ir
// CHK-BUACTIONS: 14: backend, {13}, assembler, (device-openmp)
// CHK-BUACTIONS: 15: assembler, {14}, object, (device-openmp)
// CHK-BUACTIONS: 16: offload, "device-openmp (x86_64-pc-linux-gnu)" {15}, object
@@ -398,17 +398,17 @@
// CHK-UBACTIONS: 6: linker, {0, 5}, image, (host-openmp)
// CHK-UBACTIONS: 7: input, "somelib", object, (device-openmp)
// CHK-UBACTIONS: 8: compiler, {2}, ir, (device-openmp)
-// CHK-UBACTIONS: 9: offload, "host-openmp (powerpc64le--linux)" {3}, "device-openmp (powerpc64le-ibm-linux-gnu)" {8}, ir
+// CHK-UBACTIONS: 9: offload, "host-openmp (powerpc64le-unknown-linux)" {3}, "device-openmp (powerpc64le-ibm-linux-gnu)" {8}, ir
// CHK-UBACTIONS: 10: backend, {9}, assembler, (device-openmp)
// CHK-UBACTIONS: 11: assembler, {10}, object, (device-openmp)
// CHK-UBACTIONS: 12: linker, {7, 11}, image, (device-openmp)
// CHK-UBACTIONS: 13: input, "somelib", object, (device-openmp)
// CHK-UBACTIONS: 14: compiler, {2}, ir, (device-openmp)
-// CHK-UBACTIONS: 15: offload, "host-openmp (powerpc64le--linux)" {3}, "device-openmp (x86_64-pc-linux-gnu)" {14}, ir
+// CHK-UBACTIONS: 15: offload, "host-openmp (powerpc64le-unknown-linux)" {3}, "device-openmp (x86_64-pc-linux-gnu)" {14}, ir
// CHK-UBACTIONS: 16: backend, {15}, assembler, (device-openmp)
// CHK-UBACTIONS: 17: assembler, {16}, object, (device-openmp)
// CHK-UBACTIONS: 18: linker, {13, 17}, image, (device-openmp)
-// CHK-UBACTIONS: 19: offload, "host-openmp (powerpc64le--linux)" {6}, "device-openmp (powerpc64le-ibm-linux-gnu)" {12}, "device-openmp (x86_64-pc-linux-gnu)" {18}, image
+// CHK-UBACTIONS: 19: offload, "host-openmp (powerpc64le-unknown-linux)" {6}, "device-openmp (powerpc64le-ibm-linux-gnu)" {12}, "device-openmp (x86_64-pc-linux-gnu)" {18}, image
/// ###########################################################################
@@ -421,12 +421,12 @@
// CHK-UBUACTIONS: 1: clang-offload-unbundler, {0}, cpp-output, (host-openmp)
// CHK-UBUACTIONS: 2: compiler, {1}, ir, (host-openmp)
// CHK-UBUACTIONS: 3: compiler, {1}, ir, (device-openmp)
-// CHK-UBUACTIONS: 4: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (powerpc64le-ibm-linux-gnu)" {3}, ir
+// CHK-UBUACTIONS: 4: offload, "host-openmp (powerpc64le-unknown-linux)" {2}, "device-openmp (powerpc64le-ibm-linux-gnu)" {3}, ir
// CHK-UBUACTIONS: 5: backend, {4}, assembler, (device-openmp)
// CHK-UBUACTIONS: 6: assembler, {5}, object, (device-openmp)
// CHK-UBUACTIONS: 7: offload, "device-openmp (powerpc64le-ibm-linux-gnu)" {6}, object
// CHK-UBUACTIONS: 8: compiler, {1}, ir, (device-openmp)
-// CHK-UBUACTIONS: 9: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (x86_64-pc-linux-gnu)" {8}, ir
+// CHK-UBUACTIONS: 9: offload, "host-openmp (powerpc64le-unknown-linux)" {2}, "device-openmp (x86_64-pc-linux-gnu)" {8}, ir
// CHK-UBUACTIONS: 10: backend, {9}, assembler, (device-openmp)
// CHK-UBUACTIONS: 11: assembler, {10}, object, (device-openmp)
// CHK-UBUACTIONS: 12: offload, "device-openmp (x86_64-pc-linux-gnu)" {11}, object
@@ -443,50 +443,50 @@
// RUN: | FileCheck -check-prefix=CHK-BUJOBS-ST %s
// Create host BC.
-// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" "
// CHK-BUJOBS-SAME: [[INPUT:[^\\/]+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" "
// CHK-BUJOBS-ST-SAME: [[INPUT:[^\\/]+\.c]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
// Create target 1 object.
-// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
// Create target 2 object.
-// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
// Create host object and bundle.
-// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-BUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-outputs=
// CHK-BUJOBS-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
-// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" "
// CHK-BUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
-// CHK-BUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-BUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-outputs=
// CHK-BUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
/// ###########################################################################
@@ -500,33 +500,33 @@
// RUN: touch %t.o
// RUN: %clang -### -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o -no-canonical-prefixes 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-UBJOBS2 %s
-// RUN: %clang -### -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o -save-temps -no-canonical-prefixes 2>&1 \
+// RUN: %clang -### -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o %S/Inputs/in.so -save-temps -no-canonical-prefixes 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-UBJOBS2-ST %s
// Unbundle and create host BC.
-// CHK-UBJOBS: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
// CHK-UBJOBS-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
// CHK-UBJOBS-SAME: [[HOSTPP:[^\\/]+\.i]],
// CHK-UBJOBS-SAME: [[T1PP:[^\\/]+\.i]],
// CHK-UBJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle"
-// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
-// CHK-UBJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
// CHK-UBJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
// CHK-UBJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]],
// CHK-UBJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]],
// CHK-UBJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
// Create target 1 object.
-// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
@@ -534,13 +534,13 @@
// CHK-UBJOBS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]"
// Create target 2 object.
-// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
@@ -548,21 +548,21 @@
// CHK-UBJOBS-ST-SAME: [[T2BIN:[^\\/]+\.out-openmp-x86_64-pc-linux-gnu]]" {{.*}}"{{.*}}[[T2OBJ]]"
// Create binary.
-// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" {{.*}}"-T" "
// CHK-UBJOBS-SAME: [[LKS:[^\\/]+\.lk]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
-// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
// CHK-UBJOBS-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS-ST-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" {{.*}}"-T" "
// CHK-UBJOBS-ST-SAME: [[LKS:[^\\/]+\.lk]]"
// Unbundle object file.
-// CHK-UBJOBS2: clang-offload-bundler{{.*}}" "-type=o" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS2: clang-offload-bundler{{.*}}" "-type=o" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
// CHK-UBJOBS2-SAME: [[INPUT:[^\\/]+\.o]]" "-outputs=
// CHK-UBJOBS2-SAME: [[HOSTOBJ:[^\\/]+\.o]],
// CHK-UBJOBS2-SAME: [[T1OBJ:[^\\/]+\.o]],
@@ -574,11 +574,13 @@
// CHK-UBJOBS2: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS2-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" {{.*}}"-T" "
// CHK-UBJOBS2-SAME: [[LKS:[^\\/]+\.lk]]"
-// CHK-UBJOBS2-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS2-ST-NOT: clang-offload-bundler{{.*}}in.so
+// CHK-UBJOBS2-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
// CHK-UBJOBS2-ST-SAME: [[INPUT:[^\\/]+\.o]]" "-outputs=
// CHK-UBJOBS2-ST-SAME: [[HOSTOBJ:[^\\/,]+\.o]],
// CHK-UBJOBS2-ST-SAME: [[T1OBJ:[^\\/,]+\.o]],
// CHK-UBJOBS2-ST-SAME: [[T2OBJ:[^\\/,]+\.o]]" "-unbundle"
+// CHK-UBJOBS2-ST-NOT: clang-offload-bundler{{.*}}in.so
// CHK-UBJOBS2-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
// CHK-UBJOBS2-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]"
// CHK-UBJOBS2-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
@@ -598,52 +600,52 @@
// RUN: | FileCheck -check-prefix=CHK-UBUJOBS-ST %s
// Unbundle and create host BC.
-// CHK-UBUJOBS: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBUJOBS: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
// CHK-UBUJOBS-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
// CHK-UBUJOBS-SAME: [[HOSTPP:[^\\/]+\.i]],
// CHK-UBUJOBS-SAME: [[T1PP:[^\\/]+\.i]],
// CHK-UBUJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle"
-// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
-// CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
// CHK-UBUJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
// CHK-UBUJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]],
// CHK-UBUJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]],
// CHK-UBUJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
// Create target 1 object.
-// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
// Create target 2 object.
-// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
// Create binary.
-// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-UBUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-outputs=
// CHK-UBUJOBS-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
-// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-unknown-linux" "-filetype" "obj" {{.*}}"-o" "
// CHK-UBUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
-// CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le-unknown-linux" "-outputs=
// CHK-UBUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
/// ###########################################################################
@@ -652,4 +654,4 @@
// RUN: %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-IS-DEVICE %s
-// CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le--linux" {{.*}}.c" "-fopenmp-is-device" "-fopenmp-host-ir-file-path"
+// CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le-unknown-linux" {{.*}}.c" "-fopenmp-is-device" "-fopenmp-host-ir-file-path"
diff --git a/test/Driver/output-file-cleanup.c b/test/Driver/output-file-cleanup.c
index e3f2bdbb2fb8..a5ca3e546f53 100644
--- a/test/Driver/output-file-cleanup.c
+++ b/test/Driver/output-file-cleanup.c
@@ -41,3 +41,4 @@ invalid C code
// RUN: not %clang -S %t-dir/1.c %t-dir/2.c
// RUN: test -f %t-dir/1.s
// RUN: test ! -f %t-dir/2.s
+// RUN: rm -f %t-dir/2.c
diff --git a/test/Driver/parse-progname.c b/test/Driver/parse-progname.c
index c432b10e31b2..ed907ea12e00 100644
--- a/test/Driver/parse-progname.c
+++ b/test/Driver/parse-progname.c
@@ -55,4 +55,4 @@
// RUN: ln -fs %clang %t/arm-linux-gnueabi-clang
// RUN: %t/arm-linux-gnueabi-clang -### %s 2>&1 | FileCheck -check-prefix=TARGET %s
-// TARGET: Target: arm--linux-gnueabi
+// TARGET: Target: arm-unknown-linux-gnueabi
diff --git a/test/Driver/ppc-abi.c b/test/Driver/ppc-abi.c
index cebc90d3f99a..a82a01de2781 100644
--- a/test/Driver/ppc-abi.c
+++ b/test/Driver/ppc-abi.c
@@ -13,12 +13,12 @@
// RUN: %clang -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
// RUN: -mcpu=a2q -mno-qpx | FileCheck -check-prefix=CHECK-ELFv1 %s
// RUN: %clang -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
-// RUN: -mabi=elfv2 | FileCheck -check-prefix=CHECK-ELFv2 %s
+// RUN: -mabi=elfv2 | FileCheck -check-prefix=CHECK-ELFv2-BE %s
// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-ELFv2 %s
// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
-// RUN: -mabi=elfv1 | FileCheck -check-prefix=CHECK-ELFv1 %s
+// RUN: -mabi=elfv1 | FileCheck -check-prefix=CHECK-ELFv1-LE %s
// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
// RUN: -mabi=elfv2 | FileCheck -check-prefix=CHECK-ELFv2 %s
// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
@@ -26,8 +26,44 @@
// CHECK-ELFv1: "-mrelocation-model" "pic" "-pic-level" "2"
// CHECK-ELFv1: "-target-abi" "elfv1"
+// CHECK-ELFv1-LE: "-mrelocation-model" "static"
+// CHECK-ELFv1-LE: "-target-abi" "elfv1"
// CHECK-ELFv1-QPX: "-mrelocation-model" "pic" "-pic-level" "2"
// CHECK-ELFv1-QPX: "-target-abi" "elfv1-qpx"
-// CHECK-ELFv2: "-mrelocation-model" "pic" "-pic-level" "2"
+// CHECK-ELFv2: "-mrelocation-model" "static"
// CHECK-ELFv2: "-target-abi" "elfv2"
+// CHECK-ELFv2-BE: "-mrelocation-model" "pic" "-pic-level" "2"
+// CHECK-ELFv2-BE: "-target-abi" "elfv2"
+
+// RUN: %clang -fPIC -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ELFv1-PIC %s
+// RUN: %clang -fPIC -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mabi=elfv1 | FileCheck -check-prefix=CHECK-ELFv1-PIC %s
+// RUN: %clang -fPIC -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mabi=elfv1-qpx | FileCheck -check-prefix=CHECK-ELFv1-QPX-PIC %s
+// RUN: %clang -fPIC -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mcpu=a2q | FileCheck -check-prefix=CHECK-ELFv1-QPX-PIC %s
+// RUN: %clang -fPIC -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mcpu=a2 -mqpx | FileCheck -check-prefix=CHECK-ELFv1-QPX-PIC %s
+// RUN: %clang -fPIC -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mcpu=a2q -mno-qpx | FileCheck -check-prefix=CHECK-ELFv1-PIC %s
+// RUN: %clang -fPIC -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mabi=elfv2 | FileCheck -check-prefix=CHECK-ELFv2-PIC %s
+
+// RUN: %clang -fPIC -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK-ELFv2-PIC %s
+// RUN: %clang -fPIC -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mabi=elfv1 | FileCheck -check-prefix=CHECK-ELFv1-PIC %s
+// RUN: %clang -fPIC -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mabi=elfv2 | FileCheck -check-prefix=CHECK-ELFv2-PIC %s
+// RUN: %clang -fPIC -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN: -mabi=altivec | FileCheck -check-prefix=CHECK-ELFv2-PIC %s
+
+// CHECK-ELFv1-PIC: "-mrelocation-model" "pic" "-pic-level" "2"
+// CHECK-ELFv1-PIC: "-target-abi" "elfv1"
+// CHECK-ELFv1-QPX-PIC: "-mrelocation-model" "pic" "-pic-level" "2"
+// CHECK-ELFv1-QPX-PIC: "-target-abi" "elfv1-qpx"
+// CHECK-ELFv2-PIC: "-mrelocation-model" "pic" "-pic-level" "2"
+// CHECK-ELFv2-PIC: "-target-abi" "elfv2"
+
diff --git a/test/Driver/print-effective-triple.c b/test/Driver/print-effective-triple.c
new file mode 100644
index 000000000000..65b38748d6a3
--- /dev/null
+++ b/test/Driver/print-effective-triple.c
@@ -0,0 +1,6 @@
+// Test that -print-target-triple prints correct triple.
+
+// RUN: %clang -print-effective-triple 2>&1 \
+// RUN: --target=thumb-linux-gnu \
+// RUN: | FileCheck %s
+// CHECK: armv4t-unknown-linux-gnu
diff --git a/test/Driver/print-multi-directory.c b/test/Driver/print-multi-directory.c
new file mode 100644
index 000000000000..5fb6a118e115
--- /dev/null
+++ b/test/Driver/print-multi-directory.c
@@ -0,0 +1,28 @@
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>/dev/null \
+// RUN: -target i386-none-linux \
+// RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree/usr \
+// RUN: -print-multi-directory \
+// RUN: | FileCheck --match-full-lines --check-prefix=CHECK-X86-MULTILIBS %s
+
+// CHECK-X86-MULTILIBS: 32
+// CHECK-X86-MULTILIBS-NOT: {{^.+$}}
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>/dev/null \
+// RUN: -target i386-none-linux -m64 \
+// RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree/usr \
+// RUN: -print-multi-directory \
+// RUN: | FileCheck --match-full-lines --check-prefix=CHECK-X86_64-MULTILIBS %s
+
+// CHECK-X86_64-MULTILIBS: .
+// CHECK-X86_64-MULTILIBS-NOT: {{^.+$}}
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>/dev/null \
+// RUN: -target arm-linux-androideabi21 \
+// RUN: -mthumb \
+// RUN: -B%S/Inputs/basic_android_ndk_tree \
+// RUN: --sysroot=%S/Inputs/basic_android_ndk_tree/sysroot \
+// RUN: -print-multi-directory \
+// RUN: | FileCheck --match-full-lines --check-prefix=CHECK-ARM-MULTILIBS %s
+
+// CHECK-ARM-MULTILIBS: thumb
+// CHECK-ARM-MULTILIBS-NOT: {{^.+$}}
diff --git a/test/Driver/print-target-triple.c b/test/Driver/print-target-triple.c
new file mode 100644
index 000000000000..70b2493a6fae
--- /dev/null
+++ b/test/Driver/print-target-triple.c
@@ -0,0 +1,6 @@
+// Test that -print-target-triple prints correct triple.
+
+// RUN: %clang -print-target-triple 2>&1 \
+// RUN: --target=x86_64-linux-gnu \
+// RUN: | FileCheck %s
+// CHECK: x86_64-unknown-linux-gnu
diff --git a/test/Driver/pth.c b/test/Driver/pth.c
deleted file mode 100644
index e56c34c93bb0..000000000000
--- a/test/Driver/pth.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// Test transparent PTH support.
-
-// RUN: %clang -no-canonical-prefixes -ccc-pch-is-pth -x c-header %s -o %t.h.pth -### 2> %t.log
-// RUN: FileCheck -check-prefix CHECK1 -input-file %t.log %s
-
-// CHECK1: "{{.*[/\\]}}clang{{.*}}" "-cc1" {{.*}} "-o" "{{.*}}.h.pth" "-x" "c-header" "{{.*}}pth.c"
-
-// RUN: touch %t.h.pth
-// RUN: %clang -no-canonical-prefixes -ccc-pch-is-pth -E -include %t.h %s -### 2> %t.log
-// RUN: FileCheck -check-prefix CHECK2 -input-file %t.log %s
-
-// CHECK2: "{{.*[/\\]}}clang{{.*}}" "-cc1" {{.*}}"-include-pth" "{{.*}}.h.pth" {{.*}}"-x" "c" "{{.*}}pth.c"
diff --git a/test/Driver/rewrite-legacy-objc.m b/test/Driver/rewrite-legacy-objc.m
index 37b829e5e5a2..6461aecfe5d9 100644
--- a/test/Driver/rewrite-legacy-objc.m
+++ b/test/Driver/rewrite-legacy-objc.m
@@ -10,4 +10,4 @@
// RUN: %clang -no-canonical-prefixes -target i386-apple-macosx10.6.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \
// RUN: FileCheck -check-prefix=TEST2 %s
// TEST1: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
-// TEST2: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fobjc-runtime=macosx-fragile" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
+// TEST2: "-fmessage-length" "0" "-stack-protector" "1" "-fblocks" "-fencode-extended-block-signature" "-fregister-global-dtors-with-atexit" "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option"
diff --git a/test/Driver/riscv32-toolchain.c b/test/Driver/riscv32-toolchain.c
index 1e0c750a3fa4..9e8af3a8ff45 100644
--- a/test/Driver/riscv32-toolchain.c
+++ b/test/Driver/riscv32-toolchain.c
@@ -9,6 +9,7 @@
// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf 2>&1 \
// RUN: | FileCheck -check-prefix=C-RV32-BAREMETAL-ILP32 %s
+// C-RV32-BAREMETAL-ILP32: "-fuse-init-array"
// C-RV32-BAREMETAL-ILP32: "{{.*}}Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../bin{{/|\\\\}}riscv32-unknown-elf-ld"
// C-RV32-BAREMETAL-ILP32: "--sysroot={{.*}}/Inputs/basic_riscv32_tree/riscv32-unknown-elf"
// C-RV32-BAREMETAL-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/riscv32-unknown-elf/lib{{/|\\\\}}crt0.o"
@@ -18,13 +19,29 @@
// C-RV32-BAREMETAL-ILP32: "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc"
// C-RV32-BAREMETAL-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1{{/|\\\\}}crtend.o"
+// RUN: %clang %s -### -no-canonical-prefixes \
+// RUN: -target riscv32-unknown-elf \
+// RUN: --sysroot= \
+// RUN: --gcc-toolchain=%S/Inputs/basic_riscv32_tree 2>&1 \
+// RUN: | FileCheck -check-prefix=C-RV32-BAREMETAL-NOSYSROOT-ILP32 %s
+
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "-fuse-init-array"
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../bin{{/|\\\\}}riscv32-unknown-elf-ld"
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../riscv32-unknown-elf/lib{{/|\\\\}}crt0.o"
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1{{/|\\\\}}crtbegin.o"
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "-L{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../riscv32-unknown-elf{{/|\\\\}}lib"
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "-L{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1"
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc"
+// C-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1{{/|\\\\}}crtend.o"
+
// RUN: %clangxx %s -### -no-canonical-prefixes \
// RUN: -target riscv32-unknown-elf -stdlib=libstdc++ \
// RUN: --gcc-toolchain=%S/Inputs/basic_riscv32_tree \
// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf 2>&1 \
// RUN: | FileCheck -check-prefix=CXX-RV32-BAREMETAL-ILP32 %s
-// CXX-RV32-BAREMETAL-ILP32: "-internal-isystem" "{{.*}}Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../riscv32-unknown-elf/include/c++{{/|\\\\}}8.0.1"
+// CXX-RV32-BAREMETAL-ILP32: "-fuse-init-array"
+// CXX-RV32-BAREMETAL-ILP32: "-internal-isystem" "{{.*}}Inputs/basic_riscv32_tree/riscv32-unknown-elf/include/c++{{/|\\\\}}8.0.1"
// CXX-RV32-BAREMETAL-ILP32: "{{.*}}Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../bin{{/|\\\\}}riscv32-unknown-elf-ld"
// CXX-RV32-BAREMETAL-ILP32: "--sysroot={{.*}}/Inputs/basic_riscv32_tree/riscv32-unknown-elf"
// CXX-RV32-BAREMETAL-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/riscv32-unknown-elf/lib{{/|\\\\}}crt0.o"
@@ -34,12 +51,29 @@
// CXX-RV32-BAREMETAL-ILP32: "-lstdc++" "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc"
// CXX-RV32-BAREMETAL-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1{{/|\\\\}}crtend.o"
+// RUN: %clangxx %s -### -no-canonical-prefixes \
+// RUN: -target riscv32-unknown-elf -stdlib=libstdc++ \
+// RUN: --sysroot= \
+// RUN: --gcc-toolchain=%S/Inputs/basic_riscv32_tree 2>&1 \
+// RUN: | FileCheck -check-prefix=CXX-RV32-BAREMETAL-NOSYSROOT-ILP32 %s
+
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "-fuse-init-array"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "-internal-isystem" "{{.*}}Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../riscv32-unknown-elf/include/c++{{/|\\\\}}8.0.1"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../bin{{/|\\\\}}riscv32-unknown-elf-ld"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../riscv32-unknown-elf/lib{{/|\\\\}}crt0.o"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1{{/|\\\\}}crtbegin.o"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "-L{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1/../../../../riscv32-unknown-elf/lib"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "-L{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "-lstdc++" "--start-group" "-lc" "-lgloss" "--end-group" "-lgcc"
+// CXX-RV32-BAREMETAL-NOSYSROOT-ILP32: "{{.*}}/Inputs/basic_riscv32_tree/lib/gcc/riscv32-unknown-elf/8.0.1{{/|\\\\}}crtend.o"
+
// RUN: %clang %s -### -no-canonical-prefixes -fuse-ld=ld \
// RUN: -target riscv32-linux-unknown-elf \
// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_linux_sdk \
// RUN: --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
// RUN: | FileCheck -check-prefix=C-RV32-LINUX-MULTI-ILP32 %s
+// C-RV32-LINUX-MULTI-ILP32: "-fuse-init-array"
// C-RV32-LINUX-MULTI-ILP32: "{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/../../../../riscv64-unknown-linux-gnu/bin{{/|\\\\}}ld"
// C-RV32-LINUX-MULTI-ILP32: "--sysroot={{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot"
// C-RV32-LINUX-MULTI-ILP32: "-m" "elf32lriscv"
@@ -55,6 +89,7 @@
// RUN: --sysroot=%S/Inputs/multilib_riscv_linux_sdk/sysroot 2>&1 \
// RUN: | FileCheck -check-prefix=C-RV32-LINUX-MULTI-ILP32D %s
+// C-RV32-LINUX-MULTI-ILP32D: "-fuse-init-array"
// C-RV32-LINUX-MULTI-ILP32D: "{{.*}}/Inputs/multilib_riscv_linux_sdk/lib/gcc/riscv64-unknown-linux-gnu/7.2.0/../../../../riscv64-unknown-linux-gnu/bin{{/|\\\\}}ld"
// C-RV32-LINUX-MULTI-ILP32D: "--sysroot={{.*}}/Inputs/multilib_riscv_linux_sdk/sysroot"
// C-RV32-LINUX-MULTI-ILP32D: "-m" "elf32lriscv"
diff --git a/test/Driver/ropi-rwpi.c b/test/Driver/ropi-rwpi.c
index 61fb8beff126..f22c8d004891 100644
--- a/test/Driver/ropi-rwpi.c
+++ b/test/Driver/ropi-rwpi.c
@@ -30,8 +30,8 @@
// ROPI-RWPI: "-mrelocation-model" "ropi-rwpi"
-// ROPI-NON-ARM: error: unsupported option '-fropi' for target 'x86_64--linux-gnu'
-// RWPI-NON-ARM: error: unsupported option '-frwpi' for target 'x86_64--linux-gnu'
+// ROPI-NON-ARM: error: unsupported option '-fropi' for target 'x86_64-unknown-linux-gnu'
+// RWPI-NON-ARM: error: unsupported option '-frwpi' for target 'x86_64-unknown-linux-gnu'
// PIC: error: embedded and GOT-based position independence are incompatible
diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c
index 483c87a6242f..db699410f7e2 100644
--- a/test/Driver/sanitizer-ld.c
+++ b/test/Driver/sanitizer-ld.c
@@ -575,6 +575,9 @@
// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
// RUN: -target arm64-unknown-ios -fuse-ld=ld \
// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-AARCH64-X18 %s
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target aarch64-unknown-linux-android -fuse-ld=ld \
+// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-AARCH64-X18 %s
// CHECK-SHADOWCALLSTACK-LINUX-AARCH64-X18-NOT: error:
// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
@@ -585,7 +588,7 @@
// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
// RUN: -fsanitize=safe-stack -target x86_64-unknown-linux -fuse-ld=ld \
// RUN: | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-SAFESTACK %s
-// CHECK-SHADOWCALLSTACK-SAFESTACK: error: invalid argument '-fsanitize=shadow-call-stack' not allowed with '-fsanitize=safe-stack'
+// CHECK-SHADOWCALLSTACK-SAFESTACK-NOT: error:
// RUN: %clang -fsanitize=cfi -fsanitize-stats %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux -fuse-ld=ld \
@@ -670,6 +673,13 @@
// CHECK-AUBSAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}"
// CHECK-AUBSAN-PS4: -lSceDbgAddressSanitizer_stub_weak
+// RUN: %clang -fsanitize=address,undefined %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-scei-ps4 -fuse-ld=ld \
+// RUN: -shared \
+// RUN: -nostdlib \
+// RUN: | FileCheck --check-prefix=CHECK-NOLIB-PS4 %s
+// CHECK-NOLIB-PS4-NOT: SceDbgAddressSanitizer_stub_weak
+
// RUN: %clang -fsanitize=efficiency-cache-frag %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux -fuse-ld=ld \
// RUN: | FileCheck --check-prefix=CHECK-ESAN-LINUX %s
diff --git a/test/Driver/split-debug.c b/test/Driver/split-debug.c
index 212c12f5395f..0ac206395e70 100644
--- a/test/Driver/split-debug.c
+++ b/test/Driver/split-debug.c
@@ -5,6 +5,21 @@
//
// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=split -c -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=single -c -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-ACTIONS-SINGLE-SPLIT < %t %s
+//
+// CHECK-ACTIONS-SINGLE-SPLIT: "-enable-split-dwarf=single"
+// CHECK-ACTIONS-SINGLE-SPLIT: "-split-dwarf-file" "split-debug.o"
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=single -c -### -o %tfoo.o %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-SINGLE-SPLIT-FILENAME < %t %s
+//
+// CHECK-SINGLE-SPLIT-FILENAME: "-split-dwarf-file" "{{.*}}foo.o"
// RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s
diff --git a/test/Driver/split-debug.s b/test/Driver/split-debug.s
index 6e6f8c5b8043..ece64cc0ad14 100644
--- a/test/Driver/split-debug.s
+++ b/test/Driver/split-debug.s
@@ -5,6 +5,13 @@
//
// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"
+// Check we pass -split-dwarf-file to `as` if -gsplit-dwarf=split.
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=split -c -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
+
+// Check we do not pass any -split-dwarf* commands to `as` if -gsplit-dwarf=single.
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=single -c -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s
// RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s
diff --git a/test/Driver/split-lto-unit.c b/test/Driver/split-lto-unit.c
new file mode 100644
index 000000000000..fab5790c26b9
--- /dev/null
+++ b/test/Driver/split-lto-unit.c
@@ -0,0 +1,10 @@
+// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin 2>&1 | FileCheck --check-prefix=NOUNIT %s
+// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fsplit-lto-unit 2>&1 | FileCheck --check-prefix=UNIT %s
+// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fno-split-lto-unit 2>&1 | FileCheck --check-prefix=NOUNIT %s
+// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fno-split-lto-unit -fwhole-program-vtables 2>&1 | FileCheck --check-prefix=ERROR1 %s
+// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fno-split-lto-unit -fsanitize=cfi 2>&1 | FileCheck --check-prefix=ERROR2 %s
+
+// UNIT: "-fsplit-lto-unit"
+// NOUNIT-NOT: "-fsplit-lto-unit"
+// ERROR1: error: invalid argument '-fno-split-lto-unit' not allowed with '-fwhole-program-vtables'
+// ERROR2: error: invalid argument '-fno-split-lto-unit' not allowed with '-fsanitize=cfi'
diff --git a/test/Driver/unavailable_aligned_allocation.cpp b/test/Driver/unavailable_aligned_allocation.cpp
index d5820b0665c1..131bc116be10 100644
--- a/test/Driver/unavailable_aligned_allocation.cpp
+++ b/test/Driver/unavailable_aligned_allocation.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -target x86_64-apple-macosx10.12 -c -### %s 2>&1 \
+// RUN: %clang -target x86_64-apple-macosx10.13 -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=UNAVAILABLE
//
// RUN: %clang -target arm64-apple-ios10 -c -### %s 2>&1 \
@@ -24,7 +24,7 @@
//
// UNAVAILABLE: "-faligned-alloc-unavailable"
-// RUN: %clang -target x86_64-apple-macosx10.13 -c -### %s 2>&1 \
+// RUN: %clang -target x86_64-apple-macosx10.14 -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AVAILABLE
//
// RUN: %clang -target arm64-apple-ios11 -c -### %s 2>&1 \
@@ -51,4 +51,13 @@
// RUN: -c -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AVAILABLE
//
+// Check that passing -faligned-allocation or -fno-aligned-allocation stops the
+// driver from passing -faligned-alloc-unavailable to cc1.
+//
+// RUN: %clang -target x86_64-apple-macosx10.13 -faligned-allocation -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+//
+// RUN: %clang -target x86_64-apple-macosx10.13 -fno-aligned-allocation -c -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix=AVAILABLE
+
// AVAILABLE-NOT: "-faligned-alloc-unavailable"
diff --git a/test/Driver/unknown-arg.c b/test/Driver/unknown-arg.c
index 36f5c6aabbb0..4ea43278b7ea 100644
--- a/test/Driver/unknown-arg.c
+++ b/test/Driver/unknown-arg.c
@@ -14,7 +14,7 @@
// RUN: FileCheck %s --check-prefix=CL-ERROR-DID-YOU-MEAN
// RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Wno-unknown-argument -### -- %s 2>&1 | \
// RUN: FileCheck %s --check-prefix=SILENT
-// RUN: not %clang -cc1as -hell --version -debug-info-macros 2>&1 | \
+// RUN: not %clang -cc1as -hell --version 2>&1 | \
// RUN: FileCheck %s --check-prefix=CC1AS-DID-YOU-MEAN
// RUN: not %clang -cc1asphalt -help 2>&1 | \
// RUN: FileCheck %s --check-prefix=UNKNOWN-INTEGRATED
diff --git a/test/Driver/unknown-std.c b/test/Driver/unknown-std.c
index 9ef70a4227a6..86515506511a 100644
--- a/test/Driver/unknown-std.c
+++ b/test/Driver/unknown-std.c
@@ -14,8 +14,8 @@
// CHECK-NEXT: note: use 'gnu99' for 'ISO C 1999 with GNU extensions' standard
// CHECK-NEXT: note: use 'c11' or 'iso9899:2011' for 'ISO C 2011' standard
// CHECK-NEXT: note: use 'gnu11' for 'ISO C 2011 with GNU extensions' standard
-// CHECK-NEXT: note: use 'c17' or 'iso9899:2017' for 'ISO C 2017' standard
-// CHECK-NEXT: note: use 'gnu17' for 'ISO C 2017 with GNU extensions' standard
+// CHECK-NEXT: note: use 'c17', 'iso9899:2017', 'c18', or 'iso9899:2018' for 'ISO C 2017' standard
+// CHECK-NEXT: note: use 'gnu17' or 'gnu18' for 'ISO C 2017 with GNU extensions' standard
// Make sure that no other output is present.
// CHECK-NOT: {{^.+$}}
diff --git a/test/Driver/wasm-toolchain.c b/test/Driver/wasm-toolchain.c
index b1f5f48f874d..39024d11ef6f 100644
--- a/test/Driver/wasm-toolchain.c
+++ b/test/Driver/wasm-toolchain.c
@@ -10,14 +10,31 @@
// RUN: %clang %s -### -target wasm32-unknown-unknown -fvisibility=default 2>&1 | FileCheck -check-prefix=FVISIBILITY_DEFAULT %s
// FVISIBILITY_DEFAULT-NOT: hidden
-// A basic C link command-line.
+// A basic C link command-line with unknown OS.
-// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=LINK %s
+// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK %s
// LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
-// LINK: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+// LINK: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
-// A basic C link command-line with optimization.
+// A basic C link command-line with optimization with unknown OS.
-// RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=LINK_OPT %s
+// RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK_OPT %s
// LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
-// LINK_OPT: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+// LINK_OPT: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+
+// A basic C link command-line with known OS.
+
+// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-wasi-musl --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK_KNOWN %s
+// LINK_KNOWN: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
+// LINK_KNOWN: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi-musl" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+
+// A basic C link command-line with optimization with known OS.
+
+// RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-wasi-musl --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK_OPT_KNOWN %s
+// LINK_OPT_KNOWN: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
+// LINK_OPT_KNOWN: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi-musl" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+
+// A basic C compile command-line with known OS.
+
+// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-wasi-musl --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=COMPILE %s
+// COMPILE: clang{{.*}}" "-cc1" {{.*}} "-internal-isystem" "/foo/include/wasm32-wasi-musl" "-internal-isystem" "/foo/include"
diff --git a/test/Driver/wasm-toolchain.cpp b/test/Driver/wasm-toolchain.cpp
index ea3aa313985c..447b1a0a560c 100644
--- a/test/Driver/wasm-toolchain.cpp
+++ b/test/Driver/wasm-toolchain.cpp
@@ -10,14 +10,31 @@
// RUN: %clangxx %s -### -target wasm32-unknown-unknown -fvisibility=default 2>&1 | FileCheck -check-prefix=FVISIBILITY_DEFAULT %s
// FVISIBILITY_DEFAULT-NOT: hidden
-// A basic C++ link command-line.
+// A basic C++ link command-line with unknown OS.
-// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=LINK %s
+// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo -fuse-ld=wasm-ld --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=LINK %s
// LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
-// LINK: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+// LINK: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
-// A basic C++ link command-line with optimization.
+// A basic C++ link command-line with optimization with unknown OS.
-// RUN: %clangxx -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s --stdlib=c++ 2>&1 | FileCheck -check-prefix=LINK_OPT %s
+// RUN: %clangxx -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s --stdlib=c++ -fuse-ld=wasm-ld 2>&1 | FileCheck -check-prefix=LINK_OPT %s
// LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
-// LINK_OPT: lld{{.*}}" "-flavor" "wasm" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+// LINK_OPT: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+
+// A basic C++ link command-line with known OS.
+
+// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-wasi-musl --sysroot=/foo -fuse-ld=wasm-ld --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=LINK_KNOWN %s
+// LINK_KNOWN: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
+// LINK_KNOWN: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi-musl" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+
+// A basic C++ link command-line with optimization with known OS.
+
+// RUN: %clangxx -### -O2 -no-canonical-prefixes -target wasm32-unknown-wasi-musl --sysroot=/foo %s --stdlib=c++ -fuse-ld=wasm-ld 2>&1 | FileCheck -check-prefix=LINK_OPT_KNOWN %s
+// LINK_OPT_KNOWN: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
+// LINK_OPT_KNOWN: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi-musl" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
+
+// A basic C++ compile command-line with known OS.
+
+// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-wasi-musl --sysroot=/foo --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=COMPILE %s
+// COMPILE: clang{{.*}}" "-cc1" {{.*}} "-internal-isystem" "/foo/include/wasm32-wasi-musl/c++/v1" "-internal-isystem" "/foo/include/c++/v1" "-internal-isystem" "/foo/include/wasm32-wasi-musl" "-internal-isystem" "/foo/include"
diff --git a/test/Driver/wasm32-unknown-unknown.cpp b/test/Driver/wasm32-unknown-unknown.cpp
index 3f44d93df570..90b58503faf9 100644
--- a/test/Driver/wasm32-unknown-unknown.cpp
+++ b/test/Driver/wasm32-unknown-unknown.cpp
@@ -29,7 +29,7 @@ int align_l = __alignof(long);
int align_ll = __alignof(long long);
// CHECK: @align_p = hidden global i32 4
-int align_p = __alignof(void*);
+int align_p = __alignof(void *);
// CHECK: @align_f = hidden global i32 4
int align_f = __alignof(float);
@@ -99,17 +99,20 @@ double check_double() { return 0; }
// CHECK: fp128 @check_longdouble()
long double check_longdouble() { return 0; }
-
}
-template<int> void Switch();
-template<> void Switch<4>();
-template<> void Switch<8>();
-template<> void Switch<16>();
+template <int>
+void Switch();
+template <>
+void Switch<4>();
+template <>
+void Switch<8>();
+template <>
+void Switch<16>();
void check_pointer_size() {
// CHECK: SwitchILi4
- Switch<sizeof(void*)>();
+ Switch<sizeof(void *)>();
// CHECK: SwitchILi8
Switch<sizeof(long long)>();
diff --git a/test/Driver/wasm64-unknown-unknown.cpp b/test/Driver/wasm64-unknown-unknown.cpp
index 6162759884a8..9ee4a1b566d0 100644
--- a/test/Driver/wasm64-unknown-unknown.cpp
+++ b/test/Driver/wasm64-unknown-unknown.cpp
@@ -29,7 +29,7 @@ int align_l = __alignof(long);
int align_ll = __alignof(long long);
// CHECK: @align_p = hidden global i32 8
-int align_p = __alignof(void*);
+int align_p = __alignof(void *);
// CHECK: @align_f = hidden global i32 4
int align_f = __alignof(float);
@@ -99,17 +99,20 @@ double check_double() { return 0; }
// CHECK: fp128 @check_longdouble()
long double check_longdouble() { return 0; }
-
}
-template<int> void Switch();
-template<> void Switch<4>();
-template<> void Switch<8>();
-template<> void Switch<16>();
+template <int>
+void Switch();
+template <>
+void Switch<4>();
+template <>
+void Switch<8>();
+template <>
+void Switch<16>();
void check_pointer_size() {
// CHECK: SwitchILi8
- Switch<sizeof(void*)>();
+ Switch<sizeof(void *)>();
// CHECK: SwitchILi8
Switch<sizeof(long long)>();
diff --git a/test/Driver/windows-arm-minimal-arch.c b/test/Driver/windows-arm-minimal-arch.c
index 43d6ad8602a6..4344336ea767 100644
--- a/test/Driver/windows-arm-minimal-arch.c
+++ b/test/Driver/windows-arm-minimal-arch.c
@@ -1,5 +1,5 @@
// RUN: not %clang -target thumbv5-windows -mcpu=arm10tdmi %s -o /dev/null 2>&1 \
// RUN: | FileCheck %s
-// CHECK: error: the target architecture 'thumbv5' is not supported by the target 'thumbv5--windows-msvc
+// CHECK: error: the target architecture 'thumbv5' is not supported by the target 'thumbv5-unknown-windows-msvc
diff --git a/test/Driver/windows-exceptions.cpp b/test/Driver/windows-exceptions.cpp
index 8bce3b8dd82f..2eefe22bcdbf 100644
--- a/test/Driver/windows-exceptions.cpp
+++ b/test/Driver/windows-exceptions.cpp
@@ -2,8 +2,11 @@
// RUN: %clang -target x86_64-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC %s
// RUN: %clang -target i686-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-DWARF %s
// RUN: %clang -target x86_64-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-SEH %s
+// RUN: %clang -target aarch64-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-DWARF %s
+// RUN: %clang -target aarch64-windows-gnu -fseh-exceptions -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-SEH %s
MSVC-NOT: -fdwarf-exceptions
MSVC-NOT: -fseh-exceptions
MINGW-DWARF: -fdwarf-exceptions
+MINGW-SEH: -munwind-tables
MINGW-SEH: -fseh-exceptions
diff --git a/test/Driver/x86-march.c b/test/Driver/x86-march.c
index d0cd5b61d9bf..bc1194ff73b4 100644
--- a/test/Driver/x86-march.c
+++ b/test/Driver/x86-march.c
@@ -48,6 +48,10 @@
// RUN: | FileCheck %s -check-prefix=skx
// skx: "-target-cpu" "skx"
//
+// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=cascadelake 2>&1 \
+// RUN: | FileCheck %s -check-prefix=cascadelake
+// cascadelake: "-target-cpu" "cascadelake"
+//
// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=knl 2>&1 \
// RUN: | FileCheck %s -check-prefix=knl
// knl: "-target-cpu" "knl"
diff --git a/test/Driver/x86-target-features.c b/test/Driver/x86-target-features.c
index 515ca425c2b5..ee2e6afd615d 100644
--- a/test/Driver/x86-target-features.c
+++ b/test/Driver/x86-target-features.c
@@ -132,14 +132,23 @@
// RUN: %clang -target i386-linux-gnu -mretpoline %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RETPOLINE %s
// RUN: %clang -target i386-linux-gnu -mno-retpoline %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-RETPOLINE %s
-// RETPOLINE: "-target-feature" "+retpoline"
-// NO-RETPOLINE: "-target-feature" "-retpoline"
+// RETPOLINE: "-target-feature" "+retpoline-indirect-calls" "-target-feature" "+retpoline-indirect-branches"
+// NO-RETPOLINE-NOT: retpoline
// RUN: %clang -target i386-linux-gnu -mretpoline -mretpoline-external-thunk %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RETPOLINE-EXTERNAL-THUNK %s
// RUN: %clang -target i386-linux-gnu -mretpoline -mno-retpoline-external-thunk %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-RETPOLINE-EXTERNAL-THUNK %s
// RETPOLINE-EXTERNAL-THUNK: "-target-feature" "+retpoline-external-thunk"
// NO-RETPOLINE-EXTERNAL-THUNK: "-target-feature" "-retpoline-external-thunk"
+// RUN: %clang -target i386-linux-gnu -mspeculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=SLH %s
+// RUN: %clang -target i386-linux-gnu -mretpoline -mspeculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RETPOLINE %s
+// RUN: %clang -target i386-linux-gnu -mno-speculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-SLH %s
+// SLH-NOT: retpoline
+// SLH: "-target-feature" "+retpoline-indirect-calls"
+// SLH-NOT: retpoline
+// SLH: "-mspeculative-load-hardening"
+// NO-SLH-NOT: retpoline
+
// RUN: %clang -target i386-linux-gnu -mwaitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=WAITPKG %s
// RUN: %clang -target i386-linux-gnu -mno-waitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-WAITPKG %s
// WAITPKG: "-target-feature" "+waitpkg"
diff --git a/test/FixIt/fixit-cxx11-attributes.cpp b/test/FixIt/fixit-cxx11-attributes.cpp
index 30697a900026..996fd185c37d 100644
--- a/test/FixIt/fixit-cxx11-attributes.cpp
+++ b/test/FixIt/fixit-cxx11-attributes.cpp
@@ -49,3 +49,6 @@ namespace BaseSpecifier {
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:26}:"[{{\[}}d]]"
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:33-[[@LINE-2]]:39}:""
}
+
+[[__clang__::annotate("test")]] void annotate3(); // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}}
+// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"_Clang"
diff --git a/test/Frontend/ast-main.c b/test/Frontend/ast-main.c
index 43237a12ef59..74e8bcf6db66 100644
--- a/test/Frontend/ast-main.c
+++ b/test/Frontend/ast-main.c
@@ -1,6 +1,6 @@
-// RUN: %clang -emit-llvm -S -o %t1.ll -x c - < %s
-// RUN: %clang -emit-ast -o %t.ast %s
-// RUN: %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t1.ll -x c - < %s
+// RUN: env SDKROOT="/" %clang -emit-ast -o %t.ast %s
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
// RUN: diff %t1.ll %t2.ll
int main() {
diff --git a/test/Frontend/ast-main.cpp b/test/Frontend/ast-main.cpp
index 4bddbe1372a0..89fd5e5a6389 100644
--- a/test/Frontend/ast-main.cpp
+++ b/test/Frontend/ast-main.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang -emit-llvm -S -o %t1.ll -x c++ - < %s
-// RUN: %clang -fno-delayed-template-parsing -emit-ast -o %t.ast %s
-// RUN: %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t1.ll -x c++ - < %s
+// RUN: env SDKROOT="/" %clang -fno-delayed-template-parsing -emit-ast -o %t.ast %s
+// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
// RUN: diff %t1.ll %t2.ll
// http://llvm.org/bugs/show_bug.cgi?id=15377
diff --git a/test/Frontend/dependency-gen-escaping.c b/test/Frontend/dependency-gen-escaping.c
index c8d1191674c8..deca57e4172c 100644
--- a/test/Frontend/dependency-gen-escaping.c
+++ b/test/Frontend/dependency-gen-escaping.c
@@ -21,7 +21,7 @@
// Backslash followed by # or space should escape both characters, because
// that's what GNU Make wants. GCC does the right thing with space, but not
// #, so Clang does too. (There should be 3 backslashes before the #.)
-// SEP2F: a\b\\#c\\\ d.h
+// SEP2F: a{{[/\\]}}b{{[/\\]}}\#c{{/|\\\\}}\ d.h
// With -fms-compatibility, Backslashes in #include are treated as path separators.
// Backslashes are given in the emission for special characters, like 0x20 or 0x23.
// SEP5C: a{{[/\\]}}b{{[/\\]}}\#c{{/|\\\\}}\ d.h
diff --git a/test/Frontend/dependency-gen-has-include.c b/test/Frontend/dependency-gen-has-include.c
new file mode 100644
index 000000000000..e8abb2c9c163
--- /dev/null
+++ b/test/Frontend/dependency-gen-has-include.c
@@ -0,0 +1,40 @@
+// REQUIRES: shell
+
+// Basic test
+// RUN: rm -rf %t.dir
+// RUN: mkdir %t.dir
+// RUN: mkdir %t.dir/a
+// RUN: echo "#ifndef HEADER_A" > %t.dir/a/header.h
+// RUN: echo "#define HEADER_A" >> %t.dir/a/header.h
+// RUN: echo "#endif" >> %t.dir/a/header.h
+// RUN: mkdir %t.dir/system
+// RUN: echo "#define SYSTEM_HEADER" > %t.dir/system/system-header.h
+// RUN: mkdir %t.dir/next-a
+// RUN: echo "#if __has_include_next(<next-header.h>)" > %t.dir/next-a/next-header.h
+// RUN: echo "#endif" >> %t.dir/next-a/next-header.h
+// RUN: mkdir %t.dir/next-b
+// RUN: echo "#define NEXT_HEADER" > %t.dir/next-b/next-header.h
+
+// RUN: %clang -MD -MF %t.dir/file.deps %s -fsyntax-only -I %t.dir -isystem %t.dir/system -I %t.dir/next-a -I %t.dir/next-b
+// RUN: FileCheck -input-file=%t.dir/file.deps %s
+// CHECK: dependency-gen-has-include.o
+// CHECK: dependency-gen-has-include.c
+// CHECK: a/header.h
+// CHECK-NOT: missing/file.h
+// CHECK: system/system-header.h
+// CHECK: next-a/next-header.h
+// CHECK: next-b/next-header.h
+
+// Verify that we ignore system headers in user-only headers mode.
+// RUN: %clang -MMD -MF %t.dir/user-headers.deps %s -fsyntax-only -I %t.dir -isystem %t.dir/system -I %t.dir/next-a -I %t.dir/next-b
+// RUN: FileCheck -input-file=%t.dir/user-headers.deps --check-prefix CHECK-USER-HEADER %s
+// CHECK-USER-HEADER-NOT: system/system-header.h
+
+#if __has_include("a/header.h")
+#endif
+#if __has_include("missing/file.h")
+#endif
+#if __has_include(<system-header.h>)
+#endif
+
+#include <next-header.h>
diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c
index cd222c5dfd9a..963419cb1188 100644
--- a/test/Frontend/dependency-gen.c
+++ b/test/Frontend/dependency-gen.c
@@ -4,19 +4,19 @@
// RUN: echo > %t.dir/a/b/x.h
// RUN: cd %t.dir
// RUN: %clang -MD -MF - %s -fsyntax-only -I a/b | FileCheck -check-prefix=CHECK-ONE %s
-// CHECK-ONE: {{ }}a/b{{[/\\]}}x.h
+// CHECK-ONE: {{ }}a{{[/\\]}}b{{[/\\]}}x.h
// PR8974 (-include flag)
// RUN: %clang -MD -MF - %s -fsyntax-only -include a/b/x.h -DINCLUDE_FLAG_TEST | FileCheck -check-prefix=CHECK-TWO %s
-// CHECK-TWO: {{ }}a/b/x.h
+// CHECK-TWO: {{ }}a{{[/\\]}}b{{[/\\]}}x.h
// rdar://problem/9734352 (paths involving ".")
// RUN: %clang -MD -MF - %s -fsyntax-only -I ./a/b | FileCheck -check-prefix=CHECK-THREE %s
-// CHECK-THREE: {{ }}a/b{{[/\\]}}x.h
+// CHECK-THREE: {{ }}a{{[/\\]}}b{{[/\\]}}x.h
// RUN: %clang -MD -MF - %s -fsyntax-only -I .//./a/b/ | FileCheck -check-prefix=CHECK-FOUR %s
-// CHECK-FOUR: {{ }}a/b{{[/\\]}}x.h
+// CHECK-FOUR: {{ }}a{{[/\\]}}b{{[/\\]}}x.h
// RUN: %clang -MD -MF - %s -fsyntax-only -I a/b/. | FileCheck -check-prefix=CHECK-FIVE %s
-// CHECK-FIVE: {{ }}a/b/.{{[/\\]}}x.h
+// CHECK-FIVE: {{ }}a{{[/\\]}}b{{[/\\]}}.{{[/\\]}}x.h
// RUN: cd a/b
// RUN: %clang -MD -MF - %s -fsyntax-only -I ./ | FileCheck -check-prefix=CHECK-SIX %s
// CHECK-SIX: {{ }}x.h
diff --git a/test/Frontend/fixed_point_conversions.c b/test/Frontend/fixed_point_conversions.c
new file mode 100644
index 000000000000..7e98fb1e130c
--- /dev/null
+++ b/test/Frontend/fixed_point_conversions.c
@@ -0,0 +1,283 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
+
+void TestFixedPointCastSameType() {
+ _Accum a = 2.5k;
+ _Accum a2 = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+
+ a2 = (_Accum)a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+}
+
+void TestFixedPointCastDown() {
+ long _Accum la = 2.5lk;
+ _Accum a = la;
+ // DEFAULT: [[LACCUM:%[0-9a-z]+]] = load i64, i64* %la, align 8
+ // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9a-z]+]] = ashr i64 [[LACCUM]], 16
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ a = (_Accum)la;
+ // DEFAULT: [[LACCUM:%[0-9a-z]+]] = load i64, i64* %la, align 8
+ // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9a-z]+]] = ashr i64 [[LACCUM]], 16
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ short _Accum sa = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
+ // DEFAULT-NEXT: [[SACCUM:%[0-9a-z]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
+ // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
+
+ sa = (short _Accum)a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
+ // DEFAULT-NEXT: [[SACCUM:%[0-9a-z]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
+ // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
+}
+
+void TestFixedPointCastUp() {
+ short _Accum sa = 2.5hk;
+ _Accum a = sa;
+ // DEFAULT: [[SACCUM:%[0-9a-z]+]] = load i16, i16* %sa, align 2
+ // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9a-z]+]] = sext i16 [[SACCUM]] to i32
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[SACCUM_BUFF]], 8
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ long _Accum la = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // DEFAULT-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_BUFF]], 16
+ // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %la, align 8
+
+ a = (_Accum)sa;
+ // DEFAULT: [[SACCUM:%[0-9a-z]+]] = load i16, i16* %sa, align 2
+ // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9a-z]+]] = sext i16 [[SACCUM]] to i32
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[SACCUM_BUFF]], 8
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ la = (long _Accum)a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // DEFAULT-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_BUFF]], 16
+ // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %la, align 8
+}
+
+void TestFixedPointCastSignedness() {
+ _Accum a = 2.5k;
+ unsigned _Accum ua = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[UACCUM:%[0-9a-z]+]] = shl i32 [[ACCUM]], 1
+ // DEFAULT-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
+ // SAME: TestFixedPointCastSignedness
+ // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // SAME-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
+
+ a = ua;
+ // DEFAULT: [[UACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = lshr i32 [[UACCUM]], 1
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // SAME-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ ua = (unsigned _Accum)a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[UACCUM:%[0-9a-z]+]] = shl i32 [[ACCUM]], 1
+ // DEFAULT-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
+
+ a = (_Accum)ua;
+ // DEFAULT: [[UACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = lshr i32 [[UACCUM]], 1
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ _Accum a2;
+ unsigned long _Accum ula = a2;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a2, align 4
+ // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // DEFAULT-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_EXT]], 17
+ // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
+ // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a2, align 4
+ // SAME-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // SAME-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_EXT]], 16
+ // SAME-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
+}
+
+void TestFixedPointCastSaturation() {
+ _Accum a;
+ _Sat short _Accum sat_sa;
+ _Sat _Accum sat_a;
+ _Sat long _Accum sat_la;
+ _Sat unsigned short _Accum sat_usa;
+ _Sat unsigned _Accum sat_ua;
+ _Sat unsigned long _Accum sat_ula;
+ _Sat short _Fract sat_sf;
+ _Sat _Fract sat_f;
+ _Sat long _Fract sat_lf;
+
+ // Casting down between types
+ sat_sa = sat_a;
+ // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
+ // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
+ // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
+ // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -32768
+ // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
+ // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_sa, align 2
+
+ // Accum to Fract, decreasing scale
+ sat_sf = sat_a;
+ // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
+ // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[FRACT]], 127
+ // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 127, i32 [[FRACT]]
+ // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -128
+ // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -128, i32 [[RESULT]]
+ // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i8
+ // DEFAULT-NEXT: store i8 [[RESULT_TRUNC]], i8* %sat_sf, align 1
+
+ // Accum to Fract, same scale
+ sat_f = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
+ // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
+ // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -32768
+ // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
+ // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_f, align 2
+
+ // Accum to Fract, increasing scale
+ sat_lf = sat_a;
+ // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i48
+ // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = shl i48 [[ACCUM]], 16
+ // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i48 [[FRACT]], 2147483647
+ // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i48 2147483647, i48 [[FRACT]]
+ // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i48 [[RESULT]], -2147483648
+ // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i48 -2147483648, i48 [[RESULT]]
+ // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i48 [[RESULT2]] to i32
+ // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_lf, align 4
+
+ // Signed to unsigned, decreasing scale
+ _Sat _Accum sat_a2;
+ sat_usa = sat_a2;
+ // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a2, align 4
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 7
+ // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 65535
+ // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 65535, i32 [[ACCUM]]
+ // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], 0
+ // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
+ // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
+ // SAME: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a2, align 4
+ // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
+ // SAME-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
+ // SAME-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
+ // SAME-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], 0
+ // SAME-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
+ // SAME-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // SAME-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
+
+ // Signed to unsigned, increasing scale
+ sat_ua = sat_a;
+ // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i33
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i33 [[ACCUM_EXT]], 1
+ // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i33 [[ACCUM]], 0
+ // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i33 0, i33 [[ACCUM]]
+ // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i33 [[RESULT2]] to i32
+ // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_ua, align 4
+ // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // SAME-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[ACCUM]], 0
+ // SAME-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[ACCUM]]
+ // SAME-NEXT: store i32 [[RESULT]], i32* %sat_ua, align 4
+
+ // Nothing when saturating to the same type and size
+ sat_a = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %sat_a, align 4
+
+ // Nothing when assigning back
+ a = sat_a;
+ // DEFAULT: [[SAT_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // DEFAULT-NEXT: store i32 [[SAT_ACCUM]], i32* %a, align 4
+
+ // No overflow when casting from fract to signed accum
+ sat_a = sat_f;
+ // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i16, i16* %sat_f, align 2
+ // DEFAULT-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i16 [[FRACT]] to i32
+ // DEFAULT-NEXT: store i32 [[FRACT_EXT]], i32* %sat_a, align 4
+
+ // Only get overflow checking if signed fract to unsigned accum
+ sat_ua = sat_sf;
+ // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sat_sf, align 1
+ // DEFAULT-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i17
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i17 [[FRACT_EXT]], 9
+ // DEFAULT-NEXT: [[IS_NEG:%[0-9a-z]+]] = icmp slt i17 [[ACCUM]], 0
+ // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[IS_NEG]], i17 0, i17 [[ACCUM]]
+ // DEFAULT-NEXT: [[RESULT_EXT:%[0-9a-z]+]] = sext i17 [[RESULT]] to i32
+ // DEFAULT-NEXT: store i32 [[RESULT_EXT]], i32* %sat_ua, align 4
+ // SAME: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sat_sf, align 1
+ // SAME-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i16
+ // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i16 [[FRACT_EXT]], 8
+ // SAME-NEXT: [[IS_NEG:%[0-9a-z]+]] = icmp slt i16 [[ACCUM]], 0
+ // SAME-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[IS_NEG]], i16 0, i16 [[ACCUM]]
+ // SAME-NEXT: [[RESULT_EXT:%[0-9a-z]+]] = sext i16 [[RESULT]] to i32
+ // SAME-NEXT: store i32 [[RESULT_EXT]], i32* %sat_ua, align 4
+}
+
+void TestFixedPointCastBetFractAccum() {
+ short _Accum sa;
+ _Accum a;
+ long _Accum la;
+ short _Fract sf;
+ _Fract f;
+ long _Fract lf;
+ unsigned _Accum ua;
+ unsigned _Fract uf;
+
+ // To lower scale
+ sf = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
+ // DEFAULT-NEXT: [[FRACT_TRUNC:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i8
+ // DEFAULT-NEXT: store i8 [[FRACT_TRUNC]], i8* %sf, align 1
+
+ // To higher scale
+ a = sf;
+ // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sf, align 1
+ // DEFAULT-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i32
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[FRACT_EXT]], 8
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ // To same scale
+ f = a;
+ // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = trunc i32 [[ACCUM]] to i16
+ // DEFAULT-NEXT: store i16 [[FRACT]], i16* %f, align 2
+
+ a = f;
+ // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i16, i16* %f, align 2
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = sext i16 [[FRACT]] to i32
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+ // To unsigned
+ ua = uf;
+ // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i16, i16* %uf, align 2
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = zext i16 [[FRACT]] to i32
+ // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
+ // SAME: [[FRACT:%[0-9a-z]+]] = load i16, i16* %uf, align 2
+ // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = zext i16 [[FRACT]] to i32
+ // SAME-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
+
+ uf = ua;
+ // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i16
+ // DEFAULT-NEXT: store i16 [[ACCUM]], i16* %uf, align 2
+ // SAME: [[FRACT:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i16
+ // SAME-NEXT: store i16 [[ACCUM]], i16* %uf, align 2
+}
diff --git a/test/Frontend/fixed_point_declarations.c b/test/Frontend/fixed_point_declarations.c
index 5df54f38d7f6..04ed25d227ca 100644
--- a/test/Frontend/fixed_point_declarations.c
+++ b/test/Frontend/fixed_point_declarations.c
@@ -1,5 +1,4 @@
// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-linux | FileCheck %s
-// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-scei-ps4-ubuntu-fast | FileCheck %s
// Primary fixed point types
signed short _Accum s_short_accum; // CHECK-DAG: @s_short_accum = {{.*}}global i16 0, align 2
@@ -111,3 +110,18 @@ long _Fract long_fract_eps = 0x1p-31lr; // CHECK-DAG: @long_
unsigned short _Fract u_short_fract_eps = 0x1p-8uhr; // CHECK-DAG: @u_short_fract_eps = {{.*}}global i8 1, align 1
unsigned _Fract u_fract_eps = 0x1p-16ur; // CHECK-DAG: @u_fract_eps = {{.*}}global i16 1, align 2
unsigned long _Fract u_long_fract_eps = 0x1p-32ulr; // CHECK-DAG: @u_long_fract_eps = {{.*}}global i32 1, align 4
+
+// Zero
+short _Accum short_accum_zero = 0.0hk; // CHECK-DAG: @short_accum_zero = {{.*}}global i16 0, align 2
+ _Accum accum_zero = 0.0k; // CHECK-DAG: @accum_zero = {{.*}}global i32 0, align 4
+long _Accum long_accum_zero = 0.0lk; // CHECK-DAG: @long_accum_zero = {{.*}}global i64 0, align 8
+unsigned short _Accum u_short_accum_zero = 0.0uhk; // CHECK-DAG: @u_short_accum_zero = {{.*}}global i16 0, align 2
+unsigned _Accum u_accum_zero = 0.0uk; // CHECK-DAG: @u_accum_zero = {{.*}}global i32 0, align 4
+unsigned long _Accum u_long_accum_zero = 0.0ulk; // CHECK-DAG: @u_long_accum_zero = {{.*}}global i64 0, align 8
+
+short _Fract short_fract_zero = 0.0hr; // CHECK-DAG: @short_fract_zero = {{.*}}global i8 0, align 1
+ _Fract fract_zero = 0.0r; // CHECK-DAG: @fract_zero = {{.*}}global i16 0, align 2
+long _Fract long_fract_zero = 0.0lr; // CHECK-DAG: @long_fract_zero = {{.*}}global i32 0, align 4
+unsigned short _Fract u_short_fract_zero = 0.0uhr; // CHECK-DAG: @u_short_fract_zero = {{.*}}global i8 0, align 1
+unsigned _Fract u_fract_zero = 0.0ur; // CHECK-DAG: @u_fract_zero = {{.*}}global i16 0, align 2
+unsigned long _Fract u_long_fract_zero = 0.0ulr; // CHECK-DAG: @u_long_fract_zero = {{.*}}global i32 0, align 4
diff --git a/test/Frontend/fixed_point_to_bool.c b/test/Frontend/fixed_point_to_bool.c
new file mode 100644
index 000000000000..13b39b8e7ac4
--- /dev/null
+++ b/test/Frontend/fixed_point_to_bool.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s
+
+_Bool global_b = 1.0k; // @global_b = {{*.}}global i8 1, align 1
+_Bool global_b2 = 0.0k; // @global_b2 = {{*.}}global i8 0, align 1
+
+void func() {
+ _Accum a = 0.5k;
+ unsigned _Accum ua = 0.5uk;
+ _Bool b;
+
+ // CHECK: store i8 1, i8* %b, align 1
+ // CHECK-NEXT: store i8 0, i8* %b, align 1
+ // CHECK: store i8 1, i8* %b, align 1
+ // CHECK-NEXT: store i8 0, i8* %b, align 1
+ b = 0.5k;
+ b = 0.0k;
+ b = 0.5uk;
+ b = 0.0uk;
+
+ // CHECK-NEXT: store i8 1, i8* %b, align 1
+ // CHECK-NEXT: store i8 0, i8* %b, align 1
+ // CHECK-NEXT: store i8 1, i8* %b, align 1
+ // CHECK-NEXT: store i8 0, i8* %b, align 1
+ b = (_Bool)0.5r;
+ b = (_Bool)0.0r;
+ b = (_Bool)0.5ur;
+ b = (_Bool)0.0ur;
+
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[NOTZERO:%[0-9a-z]+]] = icmp ne i32 [[ACCUM]], 0
+ // CHECK-NEXT: [[FROMBOOL:%[0-9a-z]+]] = zext i1 [[NOTZERO]] to i8
+ // CHECK-NEXT: store i8 [[FROMBOOL]], i8* %b, align 1
+ b = a;
+
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[NOTZERO:%[0-9a-z]+]] = icmp ne i32 [[ACCUM]], 0
+ // CHECK-NEXT: [[FROMBOOL:%[0-9a-z]+]] = zext i1 [[NOTZERO]] to i8
+ // CHECK-NEXT: store i8 [[FROMBOOL]], i8* %b, align 1
+ b = ua;
+
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[NOTZERO:%[0-9a-z]+]] = icmp ne i32 [[ACCUM]], 0
+ // CHECK-NEXT: br i1 [[NOTZERO]], label %if.then, label %if.end
+ if (a) {
+ }
+
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[NOTZERO:%[0-9a-z]+]] = icmp ne i32 [[ACCUM]], 0
+ // CHECK-NEXT: br i1 [[NOTZERO]], label %if.then{{[0-9]+}}, label %if.end{{[0-9]+}}
+ if (ua) {
+ }
+}
diff --git a/test/Frontend/fixed_point_unknown_conversions.c b/test/Frontend/fixed_point_unknown_conversions.c
new file mode 100644
index 000000000000..0cd3d046ca0d
--- /dev/null
+++ b/test/Frontend/fixed_point_unknown_conversions.c
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -verify -ffixed-point %s
+
+void func() {
+ _Bool b;
+ char c;
+ int i;
+ float f;
+ double d;
+ double _Complex dc;
+ int _Complex ic;
+ struct S {
+ int i;
+ } s;
+ enum E {
+ A
+ } e;
+ int *ptr;
+ typedef int int_t;
+ int_t i2;
+
+ _Accum accum;
+ _Fract fract = accum; // ok
+ _Accum *accum_ptr;
+
+ accum = b; // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+ accum = i; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+ accum = i; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+ accum = f; // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+ accum = d; // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+ accum = dc; // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+ accum = ic; // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+ accum = s; // expected-error{{assigning to '_Accum' from incompatible type 'struct S'}}
+ accum = e; // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+ accum = ptr; // expected-error{{assigning to '_Accum' from incompatible type 'int *'}}
+ accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}}
+ accum = i2; // expected-error{{conversion between fixed point and 'int_t' (aka 'int') is not yet supported}}
+
+ c = accum; // expected-error{{conversion between fixed point and 'char' is not yet supported}}
+ i = accum; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+ f = accum; // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+ d = accum; // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+ dc = accum; // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+ ic = accum; // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+ s = accum; // expected-error{{assigning to 'struct S' from incompatible type '_Accum'}}
+ e = accum; // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+ ptr = accum; // expected-error{{assigning to 'int *' from incompatible type '_Accum'}}
+ ptr = accum_ptr; // expected-warning{{incompatible pointer types assigning to 'int *' from '_Accum *'}}
+ i2 = accum; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+}
diff --git a/test/Frontend/noderef.c b/test/Frontend/noderef.c
new file mode 100644
index 000000000000..b072b995fcf6
--- /dev/null
+++ b/test/Frontend/noderef.c
@@ -0,0 +1,209 @@
+// RUN: %clang_cc1 -Wno-unused-value -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+struct S {
+ int a;
+ int b;
+};
+
+struct S2 {
+ int a[2];
+ int NODEREF a2[2];
+ int *b;
+ int NODEREF *b2;
+ struct S *s;
+ struct S NODEREF *s2;
+};
+
+int NODEREF *func(int NODEREF *arg) { // expected-note{{arg declared here}}
+ int y = *arg; // expected-warning{{dereferencing arg; was declared with a 'noderef' type}}
+ return arg;
+}
+
+void func2(int x) {}
+
+int test() {
+ int NODEREF *p; // expected-note 34 {{p declared here}}
+ int *p2;
+
+ int x = *p; // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ x = *((int NODEREF *)p2); // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ int NODEREF **q;
+ int *NODEREF *q2; // expected-note 4 {{q2 declared here}}
+
+ // Indirection
+ x = **q; // expected-warning{{dereferencing expression marked as 'noderef'}}
+ p2 = *q2; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
+
+ **q; // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ p = *&*q;
+ p = **&q;
+ q = &**&q;
+ p = &*p;
+ p = *&p;
+ p = &(*p);
+ p = *(&p);
+ x = **&p; // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ *p = 2; // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ *q = p; // ok
+ **q = 2; // expected-warning{{dereferencing expression marked as 'noderef'}}
+ *q2 = p2; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
+
+ p = p + 1;
+ p = &*(p + 1);
+
+ // Struct member access
+ struct S NODEREF *s; // expected-note 2 {{s declared here}}
+ x = s->a; // expected-warning{{dereferencing s; was declared with a 'noderef' type}}
+ x = (*s).b; // expected-warning{{dereferencing s; was declared with a 'noderef' type}}
+ p = &s->a;
+ p = &(*s).b;
+
+ // Nested struct access
+ struct S2 NODEREF *s2_noderef; // expected-note 5 {{s2_noderef declared here}}
+ p = s2_noderef->a; // ok since result is an array in a struct
+ p = s2_noderef->a2; // ok
+ p = s2_noderef->b; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
+ p = s2_noderef->b2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
+ s = s2_noderef->s; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
+ s = s2_noderef->s2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
+ p = s2_noderef->a + 1;
+
+ struct S2 *s2;
+ p = s2->a;
+ p = s2->a2;
+ p = s2->b;
+ p = s2->b2;
+ s = s2->s;
+ s = s2->s2;
+ &(*(*s2).s2).b;
+
+ // Subscript access
+ x = p[1]; // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ x = q[0][0]; // expected-warning{{dereferencing expression marked as 'noderef'}}
+ p2 = q2[0]; // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
+ p = q[*p]; // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ x = p[*p]; // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
+
+ int NODEREF arr[10]; // expected-note 1 {{arr declared here}}
+ x = arr[1]; // expected-warning{{dereferencing arr; was declared with a 'noderef' type}}
+
+ int NODEREF *(arr2[10]);
+ int NODEREF *elem = *arr2;
+
+ int NODEREF(*arr3)[10];
+ elem = *arr3;
+
+ // Combinations between indirection, subscript, and member access
+ struct S2 NODEREF *s2_arr[10];
+ struct S2 NODEREF *s2_arr2[10][10];
+
+ p = s2_arr[1]->a;
+ p = s2_arr[1]->b; // expected-warning{{dereferencing expression marked as 'noderef'}}
+ int **bptr = &s2_arr[1]->b;
+
+ x = s2->s2->a; // expected-warning{{dereferencing expression marked as 'noderef'}}
+ x = s2_noderef->a[1]; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
+ p = &s2_noderef->a[1];
+
+ // Casting to dereferenceable pointer
+ p2 = p; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
+ p2 = *q; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
+ p2 = q[0]; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
+ s2 = s2_arr[1]; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
+ s2 = s2_arr2[1][1]; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
+ p2 = p, p2 = *q; // expected-warning 2 {{casting to dereferenceable pointer removes 'noderef' attribute}}
+
+ // typedefs
+ typedef int NODEREF *ptr_t;
+ ptr_t ptr; // expected-note 2 {{ptr declared here}}
+ ptr_t *ptr2;
+ *ptr; // expected-warning{{dereferencing ptr; was declared with a 'noderef' type}}
+ *ptr2;
+ **ptr2; // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ typedef struct S2 NODEREF *s2_ptr_t;
+ s2_ptr_t s2_ptr; // expected-note 4 {{s2_ptr declared here}}
+ s2_ptr->a; // ok since result is an array in a struct
+ s2_ptr->a2; // ok
+ s2_ptr->b; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
+ s2_ptr->b2; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
+ s2_ptr->s; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
+ s2_ptr->s2; // expected-warning{{dereferencing s2_ptr; was declared with a 'noderef' type}}
+ s2_ptr->a + 1;
+
+ typedef int(int_t);
+ typedef int_t NODEREF *(noderef_int_t);
+ typedef noderef_int_t *noderef_int_nested_t;
+ noderef_int_nested_t noderef_int_nested_ptr;
+ *noderef_int_nested_ptr;
+ **noderef_int_nested_ptr; // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ typedef int_t *(NODEREF noderef_int2_t);
+ typedef noderef_int2_t *noderef_int2_nested_t;
+ noderef_int2_nested_t noderef_int2_nested_ptr; // expected-note{{noderef_int2_nested_ptr declared here}}
+ *noderef_int2_nested_ptr; // expected-warning{{dereferencing noderef_int2_nested_ptr; was declared with a 'noderef' type}}
+
+ typedef int_t *(noderef_int3_t);
+ typedef noderef_int3_t(NODEREF(*(noderef_int3_nested_t)));
+ noderef_int3_nested_t noderef_int3_nested_ptr; // expected-note{{noderef_int3_nested_ptr declared here}}
+ *noderef_int3_nested_ptr; // expected-warning{{dereferencing noderef_int3_nested_ptr; was declared with a 'noderef' type}}
+
+ // Parentheses
+ (((*((p))))); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ (*(*(&(p)))); // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ (p[1]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ (q[0]); // ok
+ (q[0][0]); // expected-warning{{dereferencing expression marked as 'noderef'}}
+ (q2[0]); // expected-warning{{dereferencing q2; was declared with a 'noderef' type}}
+ (q[(*(p))]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ (p[(*(p))]); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
+
+ (*(ptr)); // expected-warning{{dereferencing ptr; was declared with a 'noderef' type}}
+ (*(ptr2));
+ (*(*(ptr2))); // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ // Functions
+ x = *(func(p)); // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ // Casting is ok
+ q = (int NODEREF **)&p;
+ q = (int NODEREF **)&p2;
+ q = &p;
+ q = &p2;
+ x = s2->s2->a; // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+ // Other expressions
+ func2(*p); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ func2(*p + 1); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ func2(!*p); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ func2((x = *p)); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ func2((char)(*p)); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+
+ // Other statements
+ if (*p) {} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ else if (*p) {} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ switch (*p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ for (*p; *p; *p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
+ // expected-warning@-2{{dereferencing p; was declared with a 'noderef' type}}
+ for (*p; *p;){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
+ for (*p;; *p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
+ for (; *p; *p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ // expected-warning@-1{{dereferencing p; was declared with a 'noderef' type}}
+ for (*p;;){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ for (;*p;){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ for (;;*p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ while (*p){} // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ do {} while (*p); // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+ return *p; // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+}
diff --git a/test/Frontend/noderef.cpp b/test/Frontend/noderef.cpp
new file mode 100644
index 000000000000..15eb4e457c20
--- /dev/null
+++ b/test/Frontend/noderef.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -fblocks -verify %s
+
+/**
+ * Test 'noderef' attribute with c++ constructs.
+ */
+
+#define NODEREF __attribute__((noderef))
+
+void Normal() {
+ int NODEREF i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+ int NODEREF *i_ptr; // expected-note 2 {{i_ptr declared here}}
+ int NODEREF **i_ptr2; // ok
+ int *NODEREF i_ptr3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+ int *NODEREF *i_ptr4; // ok
+
+ auto NODEREF *auto_i_ptr = i_ptr;
+ auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+
+ struct {
+ int x;
+ int y;
+ } NODEREF *s;
+
+ int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}}
+
+ int i2 = *i_ptr; // expected-warning{{dereferencing i_ptr; was declared with a 'noderef' type}}
+ int &i3 = *i_ptr; // expected-warning{{dereferencing i_ptr; was declared with a 'noderef' type}}
+ int *i_ptr5 = i_ptr; // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
+ int *i_ptr6(i_ptr); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}}
+}
+
+const int NODEREF *const_i_ptr;
+static int NODEREF *static_i_ptr;
+
+void ParenTypes() {
+ int NODEREF(*i_ptr); // ok (same as `int NODEREF *`)
+ int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`)
+}
+
+// Function declarations
+int NODEREF func(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+int NODEREF *func2(); // ok (returning pointer)
+
+typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+typedef int NODEREF *(*func4)(int);
+
+void Arrays() {
+ int NODEREF i_arr[10]; // ok
+ int NODEREF i_arr2[10][10]; // ok
+ int NODEREF *i_arr3[10]; // ok
+ int NODEREF i_arr4[] = {1, 2};
+}
+
+void ParenArrays() {
+ int NODEREF(i_ptr[10]);
+ int NODEREF(i_ptr2[10])[10];
+}
+
+typedef int NODEREF *(*func5[10])(int);
+
+// Arguments
+void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+void func7(int NODEREF *x);
+void func8() NODEREF;
+
+void References() {
+ int x = 2;
+ int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+ int *xp = &x;
+ int NODEREF *&a = xp; // ok (reference to a NODEREF *)
+ int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+void BlockPointers() {
+ typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+class A {
+public:
+ int member;
+ int NODEREF *member2;
+ int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void MemberPointer() {
+ int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+template <class Ty>
+class B {
+ Ty NODEREF *member;
+ Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void test_lambdas() {
+ auto l = [](int NODEREF *x){ // expected-note{{x declared here}}
+ return *x; // expected-warning{{dereferencing x; was declared with a 'noderef' type}}
+ };
+}
+
+int NODEREF *glob_ptr; // expected-note{{glob_ptr declared here}}
+int glob_int = *glob_ptr; // expected-warning{{dereferencing glob_ptr; was declared with a 'noderef' type}}
diff --git a/test/Frontend/noderef_on_non_pointers.m b/test/Frontend/noderef_on_non_pointers.m
new file mode 100644
index 000000000000..ced7627bb5e8
--- /dev/null
+++ b/test/Frontend/noderef_on_non_pointers.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+@interface NSObject
++ (id)new;
+@end
+
+void func() {
+ id NODEREF obj = [NSObject new]; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
diff --git a/test/Frontend/noderef_templates.cpp b/test/Frontend/noderef_templates.cpp
new file mode 100644
index 000000000000..5fde6efd87c7
--- /dev/null
+++ b/test/Frontend/noderef_templates.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+template <typename T>
+int func(T NODEREF *a) { // expected-note 2 {{a declared here}}
+ return *a + 1; // expected-warning 2 {{dereferencing a; was declared with a 'noderef' type}}
+}
+
+void func() {
+ float NODEREF *f;
+ int NODEREF *i;
+ func(f); // expected-note{{in instantiation of function template specialization 'func<float>' requested here}}
+ func(i); // expected-note{{in instantiation of function template specialization 'func<int>' requested here}}
+}
diff --git a/test/Frontend/optimization-remark-with-hotness.c b/test/Frontend/optimization-remark-with-hotness.c
index 6d3ab0697a21..150b7324da5e 100644
--- a/test/Frontend/optimization-remark-with-hotness.c
+++ b/test/Frontend/optimization-remark-with-hotness.c
@@ -60,13 +60,13 @@ void bar(int x) {
// THRESHOLD-NOT: hotness
// NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
// NO_PGO: '-fdiagnostics-hotness-threshold=' requires profile-guided optimization information
- // expected-remark@+1 {{foo inlined into bar with cost=always (hotness:}}
+ // expected-remark@+1 {{foo inlined into bar with (cost=always): always inliner (hotness:}}
sum += foo(x, x - 2);
}
int main(int argc, const char *argv[]) {
for (int i = 0; i < 30; i++)
- // expected-remark@+1 {{bar not inlined into main because it should never be inlined (cost=never) (hotness:}}
+ // expected-remark@+1 {{bar not inlined into main because it should never be inlined (cost=never): always inliner (hotness:}}
bar(argc);
return sum;
}
diff --git a/test/Frontend/plugin-unknown.c b/test/Frontend/plugin-unknown.c
new file mode 100644
index 000000000000..5b225ae6639e
--- /dev/null
+++ b/test/Frontend/plugin-unknown.c
@@ -0,0 +1,5 @@
+// RUN: not %clang_cc1 -plugin asdf %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -add-plugin asdf %s 2>&1 | FileCheck --check-prefix=ADD %s
+
+// CHECK: unable to find plugin 'asdf'
+// ADD: unable to find plugin 'asdf'
diff --git a/test/Frontend/warning-stdlibcxx-darwin.cpp b/test/Frontend/warning-stdlibcxx-darwin.cpp
index 3c132b6a833b..697fe27c730d 100644
--- a/test/Frontend/warning-stdlibcxx-darwin.cpp
+++ b/test/Frontend/warning-stdlibcxx-darwin.cpp
@@ -1,5 +1,6 @@
// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist %s 2>&1 | FileCheck %s
// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -stdlib=libc++ %s -verify
-// CHECK: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead
+// RUN: %clang -cc1 -x c++-cpp-output -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist %s -verify
+// CHECK: include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead
// expected-no-diagnostics
diff --git a/test/Frontend/windows-exceptions.cpp b/test/Frontend/windows-exceptions.cpp
index 56316872be48..5aac32857c93 100644
--- a/test/Frontend/windows-exceptions.cpp
+++ b/test/Frontend/windows-exceptions.cpp
@@ -18,10 +18,10 @@
// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fseh-exceptions %s
// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fsjlj-exceptions %s
-// MSVC-X86-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'i686--windows-msvc'
-// MSVC-X86-SEH: error: invalid exception model 'fseh-exceptions' for target 'i686--windows-msvc'
-// MSVC-X86-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'i686--windows-msvc'
+// MSVC-X86-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'i686-unknown-windows-msvc'
+// MSVC-X86-SEH: error: invalid exception model 'fseh-exceptions' for target 'i686-unknown-windows-msvc'
+// MSVC-X86-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'i686-unknown-windows-msvc'
-// MSVC-X64-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'x86_64--windows-msvc'
-// MSVC-X64-SEH: error: invalid exception model 'fseh-exceptions' for target 'x86_64--windows-msvc'
-// MSVC-X64-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'x86_64--windows-msvc'
+// MSVC-X64-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'x86_64-unknown-windows-msvc'
+// MSVC-X64-SEH: error: invalid exception model 'fseh-exceptions' for target 'x86_64-unknown-windows-msvc'
+// MSVC-X64-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'x86_64-unknown-windows-msvc'
diff --git a/test/Headers/arm-fp16-header.c b/test/Headers/arm-fp16-header.c
new file mode 100644
index 000000000000..781113debda0
--- /dev/null
+++ b/test/Headers/arm-fp16-header.c
@@ -0,0 +1,19 @@
+// RUN: %clang -fsyntax-only -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c89 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c99 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c11 -xc %s
+
+// RUN: %clang -fsyntax-only -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c89 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c99 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c11 -xc %s
+
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++98 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++11 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++14 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++17 -xc++ %s
+
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++98 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++11 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++14 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++17 -xc++ %s
+
+#include <arm_fp16.h>
diff --git a/test/Headers/arm-neon-header.c b/test/Headers/arm-neon-header.c
index 90ea22bc96fe..06b99a4560a5 100644
--- a/test/Headers/arm-neon-header.c
+++ b/test/Headers/arm-neon-header.c
@@ -2,4 +2,22 @@
// RUN: %clang_cc1 -triple thumbv7-apple-darwin10 -target-cpu cortex-a8 -fsyntax-only -fno-lax-vector-conversions -ffreestanding %s
// RUN: %clang_cc1 -x c++ -triple thumbv7-apple-darwin10 -target-cpu cortex-a8 -fsyntax-only -Wvector-conversions -ffreestanding %s
+// RUN: %clang -fsyntax-only -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c89 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c99 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c11 -xc %s
+
+// RUN: %clang -fsyntax-only -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c89 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c99 -xc %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c11 -xc %s
+
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++98 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++11 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++14 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-eabi -march=armv8.2-a+fp16 -std=c++17 -xc++ %s
+
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++98 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++11 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++14 -xc++ %s
+// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-eabi -march=armv8.2-a+fp16 -std=c++17 -xc++ %s
+
#include <arm_neon.h>
diff --git a/test/Headers/float.c b/test/Headers/float.c
index 46e9cc3fd9b0..74ebb8437f11 100644
--- a/test/Headers/float.c
+++ b/test/Headers/float.c
@@ -61,6 +61,21 @@
#if ((FLT_DECIMAL_DIG > DBL_DECIMAL_DIG) || (DBL_DECIMAL_DIG > LDBL_DECIMAL_DIG))
#error "Mandatory macros {FLT,DBL,LDBL}_DECIMAL_DIG are invalid."
#endif
+ #ifndef FLT_HAS_SUBNORM
+ #error "Mandatory macro FLT_HAS_SUBNORM is missing."
+ #elif FLT_HAS_SUBNORM != __FLT_HAS_DENORM__
+ #error "Mandatory macro FLT_HAS_SUBNORM is invalid."
+ #endif
+ #ifndef LDBL_HAS_SUBNORM
+ #error "Mandatory macro LDBL_HAS_SUBNORM is missing."
+ #elif LDBL_HAS_SUBNORM != __LDBL_HAS_DENORM__
+ #error "Mandatory macro LDBL_HAS_SUBNORM is invalid."
+ #endif
+ #ifndef DBL_HAS_SUBNORM
+ #error "Mandatory macro DBL_HAS_SUBNORM is missing."
+ #elif DBL_HAS_SUBNORM != __DBL_HAS_DENORM__
+ #error "Mandatory macro DBL_HAS_SUBNORM is invalid."
+ #endif
#else
#ifdef FLT_DECIMAL_DIG
#error "Macro FLT_DECIMAL_DIG should not be defined."
@@ -71,6 +86,15 @@
#ifdef LDBL_DECIMAL_DIG
#error "Macro LDBL_DECIMAL_DIG should not be defined."
#endif
+ #ifdef FLT_HAS_SUBNORM
+ #error "Macro FLT_HAS_SUBNORM should not be defined."
+ #endif
+ #ifdef DBL_HAS_SUBNORM
+ #error "Macro DBL_HAS_SUBNORM should not be defined."
+ #endif
+ #ifdef LDBL_HAS_SUBNORM
+ #error "Macro LDBL_HAS_SUBNORM should not be defined."
+ #endif
#endif
diff --git a/test/Headers/ms-arm64-intrin.cpp b/test/Headers/ms-arm64-intrin.cpp
new file mode 100644
index 000000000000..729ca5e7f2d2
--- /dev/null
+++ b/test/Headers/ms-arm64-intrin.cpp
@@ -0,0 +1,29 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple arm64-windows -O1 \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 \
+// RUN: | FileCheck %s
+
+#include <intrin.h>
+
+void check_nop() {
+// CHECK: "nop"
+ __nop();
+}
+
+unsigned short check_byteswap_ushort(unsigned short val) {
+// CHECK: call i16 @llvm.bswap.i16(i16 %val)
+ return _byteswap_ushort(val);
+}
+
+unsigned long check_byteswap_ulong(unsigned long val) {
+// CHECK: call i32 @llvm.bswap.i32(i32 %val)
+ return _byteswap_ulong(val);
+}
+
+unsigned __int64 check_byteswap_uint64(unsigned __int64 val) {
+// CHECK: call i64 @llvm.bswap.i64(i64 %val)
+ return _byteswap_uint64(val);
+}
diff --git a/test/Headers/ms-intrin.cpp b/test/Headers/ms-intrin.cpp
index d8a4d382eb37..b0fef9cc06a7 100644
--- a/test/Headers/ms-intrin.cpp
+++ b/test/Headers/ms-intrin.cpp
@@ -42,8 +42,6 @@ void f() {
__stosw(0, 0, 0);
#ifdef _M_X64
- __shiftleft128(1, 2, 3);
- __shiftright128(1, 2, 3);
__movsq(0, 0, 0);
__stosq(0, 0, 0);
#endif
diff --git a/test/Headers/opencl-c-header.cl b/test/Headers/opencl-c-header.cl
index 2c28be19fa67..b26e61bf1a65 100644
--- a/test/Headers/opencl-c-header.cl
+++ b/test/Headers/opencl-c-header.cl
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s| FileCheck %s
-// RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
+// RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify | FileCheck %s
+// RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify -cl-std=CL1.1| FileCheck %s
+// RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify -cl-std=CL1.2| FileCheck %s
// Test including the default header as a module.
// The module should be compiled only once and loaded from cache afterwards.
@@ -45,6 +46,7 @@
// Verify that called builtins occur in the generated IR.
+// CHECK-NOT: intel_sub_group_avc_mce_get_default_inter_base_multi_reference_penalty
// CHECK-NOT: ndrange_t
// CHECK20: ndrange_t
// CHECK: _Z16convert_char_rtec
@@ -71,4 +73,16 @@ void test_image3dwo(write_only image3d_t img) {
}
#endif //__OPENCL_C_VERSION__
+// Verify that non-builtin cl_intel_planar_yuv extension is defined from
+// OpenCL 1.2 onwards.
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
+// expected-no-diagnostics
+#ifndef cl_intel_planar_yuv
+#error "Missing cl_intel_planar_yuv define"
+#endif
+#else //__OPENCL_C_VERSION__
+// expected-warning@+2{{unknown OpenCL extension 'cl_intel_planar_yuv' - ignoring}}
+#endif //__OPENCL_C_VERSION__
+#pragma OPENCL EXTENSION cl_intel_planar_yuv : enable
+
// CHECK-MOD: Reading modules
diff --git a/test/Headers/thumbv7-apple-ios-types.cpp b/test/Headers/thumbv7-apple-ios-types.cpp
index e0f77c3309f7..6f8a3652bf3a 100644
--- a/test/Headers/thumbv7-apple-ios-types.cpp
+++ b/test/Headers/thumbv7-apple-ios-types.cpp
@@ -45,11 +45,11 @@ static_assert(check_type<unsigned int, 4, 4>::value, "unsigned int is wrong");
static_assert(check_type<long, 4, 4>::value, "long is wrong");
static_assert(check_type<unsigned long, 4, 4>::value, "unsigned long is wrong");
-static_assert(check_type<long long, 8, 8>::value, "long long is wrong");
-static_assert(check_type<unsigned long long, 8, 8>::value, "unsigned long long is wrong");
+static_assert(check_type<long long, 4, 8>::value, "long long is wrong");
+static_assert(check_type<unsigned long long, 4, 8>::value, "unsigned long long is wrong");
static_assert(check_type<float, 4, 4>::value, "float is wrong");
-static_assert(check_type<double, 8, 8>::value, "double is wrong");
+static_assert(check_type<double, 4, 8>::value, "double is wrong");
static_assert(check_type<long double, 4, 8>::value, "long double is wrong");
static_assert(check_type<void *, 4, 4>::value, "'void *' is wrong");
diff --git a/test/Import/array-init-loop-expr/Inputs/S.cpp b/test/Import/array-init-loop-expr/Inputs/S.cpp
new file mode 100644
index 000000000000..5ca3ad47b278
--- /dev/null
+++ b/test/Import/array-init-loop-expr/Inputs/S.cpp
@@ -0,0 +1,8 @@
+class S {
+ int a[10];
+};
+
+void f() {
+ S s;
+ S copy = s;
+}
diff --git a/test/Import/array-init-loop-expr/test.cpp b/test/Import/array-init-loop-expr/test.cpp
new file mode 100644
index 000000000000..7fe109c305dd
--- /dev/null
+++ b/test/Import/array-init-loop-expr/test.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s
+// CHECK: CXXCtorInitializer
+// CHECK-NEXT: ArrayInitLoopExpr
+// CHECK-SAME: 'int [10]'
+
+// CHECK: ArrayInitIndexExpr
+
+void expr() {
+ f();
+}
diff --git a/test/Import/call-expr/Inputs/F.cpp b/test/Import/call-expr/Inputs/F.cpp
new file mode 100644
index 000000000000..bd88df99ba41
--- /dev/null
+++ b/test/Import/call-expr/Inputs/F.cpp
@@ -0,0 +1,10 @@
+namespace NS {
+struct X {};
+void f(X) {}
+void operator+(X, X) {}
+} // namespace NS
+void f() {
+ NS::X x;
+ f(x);
+ x + x;
+}
diff --git a/test/Import/call-expr/test.cpp b/test/Import/call-expr/test.cpp
new file mode 100644
index 000000000000..86c1b50c47d6
--- /dev/null
+++ b/test/Import/call-expr/test.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+void expr() {
+ f();
+}
+
+// CHECK: FunctionDecl 0x{{[^ ]*}} <{{[^>]*}}> line:{{.*}}:{{[^ ]*}} used f 'void ()'
+// CHECK: -CallExpr 0x{{[^ ]*}} <{{[^>]*}}> 'void' adl
+// CHECK: -CXXOperatorCallExpr 0x{{[^ ]*}} <{{[^>]*}}> 'void' adl
diff --git a/test/Import/compound-assign-op/Inputs/F.cpp b/test/Import/compound-assign-op/Inputs/F.cpp
new file mode 100644
index 000000000000..f925ae5ef6ed
--- /dev/null
+++ b/test/Import/compound-assign-op/Inputs/F.cpp
@@ -0,0 +1,18 @@
+void f() {
+ unsigned iadd_eq = 0U;
+ iadd_eq += 1U;
+ unsigned isub_eq = 0U;
+ isub_eq -= 1U;
+ unsigned imul_eq = 0U;
+ imul_eq *= 1U;
+ unsigned idiv_eq = 0U;
+ idiv_eq /= 1U;
+ unsigned iand_eq = 0U;
+ iand_eq &= 1U;
+ unsigned ixor_eq = 0U;
+ ixor_eq ^= 1U;
+ unsigned ilsh_eq = 0U;
+ ilsh_eq <<= 1U;
+ unsigned irsh_eq = 0U;
+ irsh_eq >>= 1U;
+}
diff --git a/test/Import/compound-assign-op/test.cpp b/test/Import/compound-assign-op/test.cpp
new file mode 100644
index 000000000000..415358ddbf99
--- /dev/null
+++ b/test/Import/compound-assign-op/test.cpp
@@ -0,0 +1,45 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '+='
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '-='
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '*='
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '/='
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '&='
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '^='
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '<<='
+
+// CHECK: VarDecl
+// CHECK-NEXT: Integer
+// CHECK-NEXT: CompoundAssignOperator
+// CHECK-SAME: '>>='
+
+void expr() {
+ f();
+}
diff --git a/test/Import/conversion-decl/Inputs/F.cpp b/test/Import/conversion-decl/Inputs/F.cpp
new file mode 100644
index 000000000000..b1776b0b26a5
--- /dev/null
+++ b/test/Import/conversion-decl/Inputs/F.cpp
@@ -0,0 +1,10 @@
+class Y {
+ int M;
+};
+
+class X {
+ int N, M;
+
+public:
+ operator Y();
+};
diff --git a/test/Import/conversion-decl/test.cpp b/test/Import/conversion-decl/test.cpp
new file mode 100644
index 000000000000..dc9e6d85dd34
--- /dev/null
+++ b/test/Import/conversion-decl/test.cpp
@@ -0,0 +1,5 @@
+// RUN: clang-import-test -import %S/Inputs/F.cpp -expression %s
+void expr() {
+ X X1;
+ Y Y1 = X1;
+}
diff --git a/test/Import/cxx-casts/Inputs/F.cpp b/test/Import/cxx-casts/Inputs/F.cpp
new file mode 100644
index 000000000000..79326a7e4b28
--- /dev/null
+++ b/test/Import/cxx-casts/Inputs/F.cpp
@@ -0,0 +1,12 @@
+struct A {
+ virtual ~A() {}
+};
+struct B : public A {};
+
+void f() {
+ const A *b = new B();
+ const B *c1 = dynamic_cast<const B *>(b);
+ const B *c2 = static_cast<const B *>(b);
+ const B *c3 = reinterpret_cast<const B *>(b);
+ A *c4 = const_cast<A *>(b);
+}
diff --git a/test/Import/cxx-casts/test.cpp b/test/Import/cxx-casts/test.cpp
new file mode 100644
index 000000000000..49215ce81c7b
--- /dev/null
+++ b/test/Import/cxx-casts/test.cpp
@@ -0,0 +1,21 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: CXXDynamicCastExpr
+// CHECK-SAME: dynamic_cast
+// CHECK-SAME: <Dynamic>
+
+// CHECK: CXXStaticCastExpr
+// CHECK-SAME: static_cast
+// CHECK-SAME: <BaseToDerived (A)>
+
+// CHECK: CXXReinterpretCastExpr
+// CHECK-SAME: reinterpret_cast
+// CHECK-SAME: <BitCast>
+
+// CHECK: CXXConstCastExpr
+// CHECK-SAME: const_cast
+// CHECK-SAME: <NoOp>
+
+void expr() {
+ f();
+}
diff --git a/test/Import/cxx-default-init-expr/Inputs/S.cpp b/test/Import/cxx-default-init-expr/Inputs/S.cpp
new file mode 100644
index 000000000000..2b83b5d2eedc
--- /dev/null
+++ b/test/Import/cxx-default-init-expr/Inputs/S.cpp
@@ -0,0 +1,9 @@
+struct Foo {
+ int i;
+};
+
+struct S {
+ int int_member = 3;
+ float float_member = 3.0f;
+ Foo class_member = Foo();
+};
diff --git a/test/Import/cxx-default-init-expr/test.cpp b/test/Import/cxx-default-init-expr/test.cpp
new file mode 100644
index 000000000000..a50b12b83e0d
--- /dev/null
+++ b/test/Import/cxx-default-init-expr/test.cpp
@@ -0,0 +1,22 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s
+// CHECK: CXXCtorInitializer
+// CHECK-SAME: 'int_member'
+// CHECK-SAME: 'int'
+// CHECK-NEXT: CXXDefaultInitExpr
+// CHECK-SAME: 'int'
+
+// CHECK-NEXT: CXXCtorInitializer
+// CHECK-SAME: 'float_member'
+// CHECK-SAME: 'float'
+// CHECK-NEXT: CXXDefaultInitExpr
+// CHECK-SAME: 'float'
+
+// CHECK-NEXT: CXXCtorInitializer
+// CHECK-SAME: 'class_member'
+// CHECK-SAME: 'Foo'
+// CHECK-NEXT: CXXDefaultInitExpr
+// CHECK-SAME: 'Foo'
+
+void expr() {
+ struct S s;
+}
diff --git a/test/Import/cxx-for-range/Inputs/F.cpp b/test/Import/cxx-for-range/Inputs/F.cpp
new file mode 100644
index 000000000000..26a3a4e1d3fa
--- /dev/null
+++ b/test/Import/cxx-for-range/Inputs/F.cpp
@@ -0,0 +1,10 @@
+struct Container {
+ int *begin();
+ int *end();
+};
+
+void f() {
+ for (Container c; int varname : c) {
+ return;
+ }
+}
diff --git a/test/Import/cxx-for-range/test.cpp b/test/Import/cxx-for-range/test.cpp
new file mode 100644
index 000000000000..019fc20bee1e
--- /dev/null
+++ b/test/Import/cxx-for-range/test.cpp
@@ -0,0 +1,58 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: CXXForRangeStmt
+
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: c 'Container'
+// CHECK-NEXT: CXXConstructExpr
+
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: 'c'
+// CHECK-SAME: Container
+
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: CXXMemberCallExpr
+// CHECK-SAME: 'int *'
+// CHECK-NEXT: MemberExpr
+// CHECK-SAME: .begin
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: '__range1'
+// CHECK-SAME: Container
+
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: CXXMemberCallExpr
+// CHECK-SAME: 'int *'
+// CHECK-NEXT: MemberExpr
+// CHECK-SAME: .end
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: '__range1'
+// CHECK-SAME: Container
+
+// CHECK-NEXT: BinaryOperator
+// CHECK-SAME: '!='
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: '__begin1'
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: '__end1'
+
+// CHECK-NEXT: UnaryOperator
+// CHECK-SAME: '++'
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: '__begin1'
+
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname
+
+// CHECK: ReturnStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Import/cxx-member-pointers/Inputs/S.cpp b/test/Import/cxx-member-pointers/Inputs/S.cpp
new file mode 100644
index 000000000000..afee60de3268
--- /dev/null
+++ b/test/Import/cxx-member-pointers/Inputs/S.cpp
@@ -0,0 +1,7 @@
+struct S {
+ int i;
+};
+
+int S::*iptr() {
+ return &S::i;
+}
diff --git a/test/Import/cxx-member-pointers/test.cpp b/test/Import/cxx-member-pointers/test.cpp
new file mode 100644
index 000000000000..253c90bdcf7e
--- /dev/null
+++ b/test/Import/cxx-member-pointers/test.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s
+
+// CHECK: VarDecl
+// CHECK-SAME: int S::*
+// CHECK-NEXT: CallExpr
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-SAME: int S::*(*)()
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: int S::*()
+
+void expr() {
+ int S::*p = iptr();
+ S s;
+ s.i = 3;
+ int i = s.*p;
+}
diff --git a/test/Import/cxx-noexcept-expr/Inputs/F.cpp b/test/Import/cxx-noexcept-expr/Inputs/F.cpp
new file mode 100644
index 000000000000..2c48ad652a6e
--- /dev/null
+++ b/test/Import/cxx-noexcept-expr/Inputs/F.cpp
@@ -0,0 +1 @@
+bool f() { return noexcept(1); }
diff --git a/test/Import/cxx-noexcept-expr/test.cpp b/test/Import/cxx-noexcept-expr/test.cpp
new file mode 100644
index 000000000000..090a4eb7e647
--- /dev/null
+++ b/test/Import/cxx-noexcept-expr/test.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: CXXNoexceptExpr
+// CHECK-NEXT: IntegerLiteral
+
+void expr() {
+ f();
+}
diff --git a/test/Import/cxx-scalar-value-init/Inputs/S.cpp b/test/Import/cxx-scalar-value-init/Inputs/S.cpp
new file mode 100644
index 000000000000..153d960699b0
--- /dev/null
+++ b/test/Import/cxx-scalar-value-init/Inputs/S.cpp
@@ -0,0 +1,2 @@
+int si() { return int(); }
+float sf() { return float(); }
diff --git a/test/Import/cxx-scalar-value-init/test.cpp b/test/Import/cxx-scalar-value-init/test.cpp
new file mode 100644
index 000000000000..596710911cc8
--- /dev/null
+++ b/test/Import/cxx-scalar-value-init/test.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s
+// CHECK: CXXScalarValueInitExpr
+// CHECK-SAME: 'int'
+
+// CHECK: CXXScalarValueInitExpr
+// CHECK-SAME: 'float'
+
+void expr() {
+ int i = si();
+ float f = sf();
+}
diff --git a/test/Import/cxx-try-catch/Inputs/F.cpp b/test/Import/cxx-try-catch/Inputs/F.cpp
new file mode 100644
index 000000000000..4e06f3599bb4
--- /dev/null
+++ b/test/Import/cxx-try-catch/Inputs/F.cpp
@@ -0,0 +1,18 @@
+void f() {
+ try {
+ } catch (...) {
+ }
+
+ try {
+ } catch (int) {
+ }
+
+ try {
+ } catch (int varname) {
+ }
+
+ try {
+ } catch (int varname1) {
+ } catch (long varname2) {
+ }
+}
diff --git a/test/Import/cxx-try-catch/test.cpp b/test/Import/cxx-try-catch/test.cpp
new file mode 100644
index 000000000000..079e35b3e7d3
--- /dev/null
+++ b/test/Import/cxx-try-catch/test.cpp
@@ -0,0 +1,39 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: CXXTryStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXCatchStmt
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: CompoundStmt
+
+// CHECK: CXXTryStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXCatchStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: 'int'
+// CHECK-NEXT: CompoundStmt
+
+// CHECK: CXXTryStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXCatchStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname
+// CHECK-SAME: 'int'
+// CHECK-NEXT: CompoundStmt
+
+// CHECK: CXXTryStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXCatchStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname1
+// CHECK-SAME: 'int'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXCatchStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname2
+// CHECK-SAME: 'long'
+// CHECK-NEXT: CompoundStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Import/do-stmt/Inputs/F.cpp b/test/Import/do-stmt/Inputs/F.cpp
new file mode 100644
index 000000000000..a58efb3a25ca
--- /dev/null
+++ b/test/Import/do-stmt/Inputs/F.cpp
@@ -0,0 +1,7 @@
+void f() {
+ do
+ ;
+ while (true);
+ do {
+ } while (false);
+}
diff --git a/test/Import/do-stmt/test.cpp b/test/Import/do-stmt/test.cpp
new file mode 100644
index 000000000000..8b1057dae65b
--- /dev/null
+++ b/test/Import/do-stmt/test.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: DoStmt
+// CHECK-NEXT: NullStmt
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-SAME: true
+
+// CHECK: DoStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-SAME: false
+
+void expr() {
+ f();
+}
diff --git a/test/Import/enum/Inputs/S.cpp b/test/Import/enum/Inputs/S.cpp
index 8506c68512db..3179da1daacc 100644
--- a/test/Import/enum/Inputs/S.cpp
+++ b/test/Import/enum/Inputs/S.cpp
@@ -2,3 +2,5 @@ enum E {
a = 1,
b = 2
};
+
+enum OpaqueWithType : long;
diff --git a/test/Import/enum/test.cpp b/test/Import/enum/test.cpp
index aa68063cb207..491c3b7cb60d 100644
--- a/test/Import/enum/test.cpp
+++ b/test/Import/enum/test.cpp
@@ -1,4 +1,8 @@
-// RUN: clang-import-test -import %S/Inputs/S.cpp -expression %s
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s
+
+// CHECK: OpaqueWithType 'long'
+
void expr() {
static_assert(E::a + E::b == 3);
+ static_assert(sizeof(OpaqueWithType) == sizeof(long));
}
diff --git a/test/Import/expr-with-cleanups/Inputs/S.cpp b/test/Import/expr-with-cleanups/Inputs/S.cpp
new file mode 100644
index 000000000000..7b69f48f681e
--- /dev/null
+++ b/test/Import/expr-with-cleanups/Inputs/S.cpp
@@ -0,0 +1,8 @@
+struct RAII {
+ int i = 0;
+ RAII() { i++; }
+ ~RAII() { i--; }
+};
+void f() {
+ RAII();
+}
diff --git a/test/Import/expr-with-cleanups/test.cpp b/test/Import/expr-with-cleanups/test.cpp
new file mode 100644
index 000000000000..79b76f414ecf
--- /dev/null
+++ b/test/Import/expr-with-cleanups/test.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s
+// CHECK: ExprWithCleanups
+// CHECK-SAME: 'RAII'
+// CHECK-NEXT: CXXBindTemporaryExpr
+
+void expr() {
+ f();
+}
diff --git a/test/Import/for-stmt/Inputs/F.cpp b/test/Import/for-stmt/Inputs/F.cpp
new file mode 100644
index 000000000000..e93e35dd6b79
--- /dev/null
+++ b/test/Import/for-stmt/Inputs/F.cpp
@@ -0,0 +1,11 @@
+void f() {
+ for (;;)
+ ;
+ for (int i = 0;;)
+ continue;
+ for (; bool j = false;)
+ continue;
+ for (int i = 0; i != 0; ++i) {
+ i++;
+ }
+}
diff --git a/test/Import/for-stmt/test.cpp b/test/Import/for-stmt/test.cpp
new file mode 100644
index 000000000000..95895ce6c1db
--- /dev/null
+++ b/test/Import/for-stmt/test.cpp
@@ -0,0 +1,50 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: ForStmt
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: NullStmt
+
+// CHECK: ForStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: ContinueStmt
+
+// CHECK: ForStmt
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: 'j'
+// CHECK-SAME: 'bool'
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: ContinueStmt
+
+// CHECK: ForStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: <<NULL>>
+
+// CHECK-NEXT: BinaryOperator
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-NEXT: IntegerLiteral
+
+// CHECK-NEXT: UnaryOperator
+// CHECK-SAME: '++'
+// CHECK-NEXT: DeclRefExpr
+
+// CHECK-NEXT: CompoundStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Import/if-stmt/Inputs/F.cpp b/test/Import/if-stmt/Inputs/F.cpp
new file mode 100644
index 000000000000..a7062c94ea76
--- /dev/null
+++ b/test/Import/if-stmt/Inputs/F.cpp
@@ -0,0 +1,21 @@
+void f() {
+ if (true)
+ return;
+
+ if (int j = 3)
+ return;
+
+ if (int j; true)
+ return;
+
+ if (true)
+ return;
+ else
+ return;
+
+ if (true) {
+ return;
+ } else {
+ return;
+ }
+}
diff --git a/test/Import/if-stmt/test.cpp b/test/Import/if-stmt/test.cpp
new file mode 100644
index 000000000000..8c92a72c0129
--- /dev/null
+++ b/test/Import/if-stmt/test.cpp
@@ -0,0 +1,36 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: IfStmt
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: ReturnStmt
+
+// CHECK: IfStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-NEXT: ReturnStmt
+
+// CHECK: IfStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: ReturnStmt
+
+// CHECK: IfStmt
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: ReturnStmt
+
+// CHECK: IfStmt
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Import/indirect-goto/Inputs/F.cpp b/test/Import/indirect-goto/Inputs/F.cpp
new file mode 100644
index 000000000000..368b6db40da5
--- /dev/null
+++ b/test/Import/indirect-goto/Inputs/F.cpp
@@ -0,0 +1,6 @@
+void f() {
+ void const *l1_ptr = &&l1;
+ goto *l1_ptr;
+l1:
+ return;
+}
diff --git a/test/Import/indirect-goto/test.cpp b/test/Import/indirect-goto/test.cpp
new file mode 100644
index 000000000000..62be49eea6bc
--- /dev/null
+++ b/test/Import/indirect-goto/test.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: IndirectGotoStmt
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: 'l1_ptr'
+
+void expr() {
+ f();
+}
diff --git a/test/Import/objc-autoreleasepool/Inputs/F.m b/test/Import/objc-autoreleasepool/Inputs/F.m
new file mode 100644
index 000000000000..0236cdf8f632
--- /dev/null
+++ b/test/Import/objc-autoreleasepool/Inputs/F.m
@@ -0,0 +1,5 @@
+void f() {
+ @autoreleasepool {
+ return;
+ }
+}
diff --git a/test/Import/objc-autoreleasepool/test.m b/test/Import/objc-autoreleasepool/test.m
new file mode 100644
index 000000000000..f09e7ef4dddf
--- /dev/null
+++ b/test/Import/objc-autoreleasepool/test.m
@@ -0,0 +1,9 @@
+// RUN: clang-import-test -dump-ast -x objective-c++ -import %S/Inputs/F.m -expression %s | FileCheck %s
+
+// CHECK: ObjCAutoreleasePoolStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Import/objc-param-decl/Inputs/S.m b/test/Import/objc-param-decl/Inputs/S.m
new file mode 100644
index 000000000000..6364cfa43381
--- /dev/null
+++ b/test/Import/objc-param-decl/Inputs/S.m
@@ -0,0 +1,5 @@
+@protocol NSString
+@end
+
+@interface Dictionary <FirstParam : id <NSString>, NSString>
+@end
diff --git a/test/Import/objc-param-decl/test.m b/test/Import/objc-param-decl/test.m
new file mode 100644
index 000000000000..ce05b01b0f83
--- /dev/null
+++ b/test/Import/objc-param-decl/test.m
@@ -0,0 +1,11 @@
+// RUN: clang-import-test -dump-ast -x objective-c++ -import %S/Inputs/S.m -expression %s | FileCheck %s
+
+// CHECK: ObjCTypeParamDecl
+// CHECK-SAME: FirstParam
+// CHECK-SAME: 'id<NSString>'
+// CHECK-NEXT: ObjCTypeParamDecl
+// CHECK-SAME: 'id':'id'
+
+void expr() {
+ Dictionary *d;
+}
diff --git a/test/Import/objc-try-catch/Inputs/F.m b/test/Import/objc-try-catch/Inputs/F.m
new file mode 100644
index 000000000000..5b8b67549b33
--- /dev/null
+++ b/test/Import/objc-try-catch/Inputs/F.m
@@ -0,0 +1,28 @@
+@interface Exception
+@end
+@interface OtherException
+@end
+
+void f() {
+ @try {
+ Exception *e;
+ @throw e;
+ }
+ @catch (Exception *varname) {
+ }
+ @finally {
+ }
+
+ @try {
+ }
+ @catch (Exception *varname1) {
+ @throw;
+ }
+ @catch (OtherException *varname2) {
+ }
+
+ @try {
+ }
+ @finally {
+ }
+}
diff --git a/test/Import/objc-try-catch/test.m b/test/Import/objc-try-catch/test.m
new file mode 100644
index 000000000000..216beba4f7fa
--- /dev/null
+++ b/test/Import/objc-try-catch/test.m
@@ -0,0 +1,43 @@
+// RUN: clang-import-test -x objective-c++ -Xcc -fobjc-exceptions -dump-ast -import %S/Inputs/F.m -expression %s | FileCheck %s
+
+// FIXME: Seems that Objective-C try/catch crash codegen on Windows. Reenable once this is fixed.
+// UNSUPPORTED: system-windows
+
+// CHECK: ObjCAtTryStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: ObjCAtThrowStmt
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-NEXT: ObjCAtCatchStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname
+// CHECK-SAME: 'Exception *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ObjCAtFinallyStmt
+// CHECK-NEXT: CompoundStmt
+
+// CHECK-NEXT: ObjCAtTryStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ObjCAtCatchStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname1
+// CHECK-SAME: 'Exception *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ObjCAtThrowStmt
+// CHECK-NEXT: <<NULL>>
+// CHECK-NEXT: ObjCAtCatchStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname2
+// CHECK-SAME: 'OtherException *'
+// CHECK-NEXT: CompoundStmt
+
+// CHECK-NEXT: ObjCAtTryStmt
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ObjCAtFinallyStmt
+// CHECK-NEXT: CompoundStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Import/pack-expansion-expr/Inputs/F.cpp b/test/Import/pack-expansion-expr/Inputs/F.cpp
new file mode 100644
index 000000000000..528451c855d8
--- /dev/null
+++ b/test/Import/pack-expansion-expr/Inputs/F.cpp
@@ -0,0 +1,11 @@
+template <typename... T>
+void sink(T... a);
+
+template <typename... T>
+void packfuncT(T... a) {
+ sink(a...);
+}
+
+void f() {
+ packfuncT(1, 2, 3);
+}
diff --git a/test/Import/pack-expansion-expr/test.cpp b/test/Import/pack-expansion-expr/test.cpp
new file mode 100644
index 000000000000..3e9867b1a736
--- /dev/null
+++ b/test/Import/pack-expansion-expr/test.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: PackExpansionExpr
+// CHECK-SAME: '<dependent type>'
+// CHECK-NEXT: DeclRefExpr
+// CHECK-SAME: 'T...'
+// CHECK-SAME: ParmVar
+// CHECK-SAME: 'a'
+
+void expr() {
+ f();
+}
diff --git a/test/Import/switch-stmt/Inputs/F.cpp b/test/Import/switch-stmt/Inputs/F.cpp
new file mode 100644
index 000000000000..5d0d8376d462
--- /dev/null
+++ b/test/Import/switch-stmt/Inputs/F.cpp
@@ -0,0 +1,23 @@
+void f() {
+ switch (1) {
+ case 1:
+ case 2:
+ break;
+ case 3 ... 4:
+ case 5 ... 5:
+ break;
+ }
+ switch (int varname; 1) {
+ case 1:
+ break;
+ case 2:
+ break;
+ case 3 ... 5:
+ break;
+ }
+ switch (1)
+ default:
+ break;
+ switch (0)
+ ;
+}
diff --git a/test/Import/switch-stmt/test.cpp b/test/Import/switch-stmt/test.cpp
new file mode 100644
index 000000000000..e274e895c444
--- /dev/null
+++ b/test/Import/switch-stmt/test.cpp
@@ -0,0 +1,57 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: SwitchStmt
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CaseStmt
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: CaseStmt
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: BreakStmt
+// CHECK-NEXT: CaseStmt
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: CaseStmt
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: BreakStmt
+
+// CHECK: SwitchStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-SAME: varname
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CaseStmt
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: BreakStmt
+// CHECK-NEXT: CaseStmt
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: BreakStmt
+// CHECK-NEXT: CaseStmt
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: BreakStmt
+
+// CHECK: SwitchStmt
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: DefaultStmt
+// CHECK-NEXT: BreakStmt
+
+// CHECK: SwitchStmt
+// CHECK-NEXT: IntegerLiteral
+// CHECK-NEXT: NullStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Import/while-stmt/Inputs/F.cpp b/test/Import/while-stmt/Inputs/F.cpp
new file mode 100644
index 000000000000..6fd2d8753b04
--- /dev/null
+++ b/test/Import/while-stmt/Inputs/F.cpp
@@ -0,0 +1,8 @@
+void f() {
+ while (false)
+ ;
+ while (false) {
+ }
+ while (bool ini = true)
+ ;
+}
diff --git a/test/Import/while-stmt/test.cpp b/test/Import/while-stmt/test.cpp
new file mode 100644
index 000000000000..a0309d431240
--- /dev/null
+++ b/test/Import/while-stmt/test.cpp
@@ -0,0 +1,21 @@
+// RUN: clang-import-test -dump-ast -import %S/Inputs/F.cpp -expression %s | FileCheck %s
+
+// CHECK: WhileStmt
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: NullStmt
+
+// CHECK: WhileStmt
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: CompoundStmt
+
+// CHECK: WhileStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl
+// CHECK-NEXT: CXXBoolLiteralExpr
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: DeclRefExpr
+// CHECK-NEXT: NullStmt
+
+void expr() {
+ f();
+}
diff --git a/test/Index/Core/Inputs/module/SubModA.h b/test/Index/Core/Inputs/module/SubModA.h
new file mode 100644
index 000000000000..59d243ecfa64
--- /dev/null
+++ b/test/Index/Core/Inputs/module/SubModA.h
@@ -0,0 +1,2 @@
+
+void SubModA_func(void);
diff --git a/test/Index/Core/Inputs/module/SubSubModA.h b/test/Index/Core/Inputs/module/SubSubModA.h
new file mode 100644
index 000000000000..51ffa910f7a3
--- /dev/null
+++ b/test/Index/Core/Inputs/module/SubSubModA.h
@@ -0,0 +1,2 @@
+
+void SubSubModA_func(void);
diff --git a/test/Index/Core/Inputs/module/module.modulemap b/test/Index/Core/Inputs/module/module.modulemap
index a132562eafd8..180a4aad36dc 100644
--- a/test/Index/Core/Inputs/module/module.modulemap
+++ b/test/Index/Core/Inputs/module/module.modulemap
@@ -1 +1,11 @@
-module ModA { header "ModA.h" export * }
+module ModA {
+ header "ModA.h" export *
+
+ module SubModA {
+ header "SubModA.h"
+
+ module SubSubModA {
+ header "SubSubModA.h"
+ }
+ }
+}
diff --git a/test/Index/Core/external-source-symbol-attr.m b/test/Index/Core/external-source-symbol-attr.m
index cdc52966977d..41bb7a264ab3 100644
--- a/test/Index/Core/external-source-symbol-attr.m
+++ b/test/Index/Core/external-source-symbol-attr.m
@@ -87,7 +87,7 @@ void test2(I3 *i3, id<ExtProt2> prot2, SomeEnum some) {
[i3 meth2];
// CHECK: [[@LINE-1]]:7 | instance-method/Swift | meth2 | c:@CM@modname@objc(cs)I3(im)meth2 |
[prot2 meth];
- // CHECK: [[@LINE-1]]:10 | instance-method/Swift | meth | c:@M@modname@objc(pl)ExtProt2(im)meth |
+ // CHECK: [[@LINE-1]]:10 | instance-method(protocol)/Swift | meth | c:@M@modname@objc(pl)ExtProt2(im)meth |
some = SomeEnumFirst;
// CHECK: [[@LINE-1]]:10 | enumerator/Swift | SomeEnumFirst | c:@M@modname@E@SomeEnum@SomeEnumFirst |
}
diff --git a/test/Index/Core/index-source.cpp b/test/Index/Core/index-source.cpp
index 6f485feb47c5..0bf663e30be3 100644
--- a/test/Index/Core/index-source.cpp
+++ b/test/Index/Core/index-source.cpp
@@ -1,4 +1,5 @@
// RUN: c-index-test core -print-source-symbols -- %s -std=c++1z -target x86_64-apple-macosx10.7 | FileCheck %s
+// RUN: c-index-test core -print-source-symbols -include-locals -- %s -std=c++1z -target x86_64-apple-macosx10.7 | FileCheck -check-prefix=LOCAL %s
// CHECK: [[@LINE+1]]:7 | class/C++ | Cls | [[Cls_USR:.*]] | <no-cgname> | Def | rel: 0
class Cls { public:
@@ -493,6 +494,7 @@ void localStructuredBindingAndRef() {
// CHECK: [[@LINE-1]]:69 | variable/C++ | structuredBinding2 | c:@N@cpp17structuredBinding@structuredBinding2 | <no-cgname> | Ref,Read,RelCont | rel: 1
// CHECK-NEXT: RelCont | localStructuredBindingAndRef | c:@N@cpp17structuredBinding@F@localStructuredBindingAndRef#
// CHECK-NOT: localBinding
+// LOCAL: [[@LINE-4]]:9 | variable(local)/C++ | localBinding1 | c:index-source.cpp@25382@N@cpp17structuredBinding@F@localStructuredBindingAndRef#@localBinding1
}
}
diff --git a/test/Index/Core/index-source.m b/test/Index/Core/index-source.m
index 2931e664eac6..ed616dbc9ae6 100644
--- a/test/Index/Core/index-source.m
+++ b/test/Index/Core/index-source.m
@@ -2,7 +2,7 @@
// RUN: c-index-test core -print-source-symbols -include-locals -- %s -target x86_64-apple-macosx10.7 | FileCheck -check-prefix=LOCAL %s
@interface Base
-// CHECK: [[@LINE-1]]:12 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Decl | rel: 0
+// CHECK: [[@LINE-1]]:12 | class/ObjC | Base | [[BASE_USR:.*]] | _OBJC_CLASS_$_Base | Decl | rel: 0
-(void)meth;
// CHECK: [[@LINE-1]]:8 | instance-method/ObjC | meth | c:objc(cs)Base(im)meth | -[Base meth] | Decl,Dyn,RelChild | rel: 1
// CHECK-NEXT: RelChild | Base | c:objc(cs)Base
@@ -60,7 +60,7 @@ void goo(Base *b) {
Base *f = (Base *) 2;
}
-// CHECK: [[@LINE+1]]:11 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Decl | rel: 0
+// CHECK: [[@LINE+1]]:11 | protocol/ObjC | Prot1 | [[PROT1_USR:.*]] | <no-cgname> | Decl | rel: 0
@protocol Prot1
@end
@@ -472,3 +472,21 @@ void testImplicitProperties(ImplicitProperties *c) {
}
@end
+
+@protocol Prot3 // CHECK: [[@LINE]]:11 | protocol/ObjC | Prot3 | [[PROT3_USR:.*]] | <no-cgname> | Decl |
+-(void)meth; // CHECK: [[@LINE]]:8 | instance-method(protocol)/ObjC | meth | [[PROT3_meth_USR:.*]] | -[Prot3 meth] | Decl,Dyn,RelChild |
+@end
+
+void test_rec1() {
+ id<Prot3, Prot1> o1;
+ [o1 meth]; // CHECK: [[@LINE]]:7 | instance-method(protocol)/ObjC | meth | [[PROT3_meth_USR]] | {{.*}} | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 3
+ // CHECK-NEXT: RelCall,RelCont | test_rec1 |
+ // CHECK-NEXT: RelRec | Prot3 | [[PROT3_USR]]
+ // CHECK-NEXT: RelRec | Prot1 | [[PROT1_USR]]
+ Base<Prot3, Prot1> *o2;
+ [o2 meth]; // CHECK: [[@LINE]]:7 | instance-method/ObjC | meth | {{.*}} | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 4
+ // CHECK-NEXT: RelCall,RelCont | test_rec1 |
+ // CHECK-NEXT: RelRec | Base | [[BASE_USR]]
+ // CHECK-NEXT: RelRec | Prot3 | [[PROT3_USR]]
+ // CHECK-NEXT: RelRec | Prot1 | [[PROT1_USR]]
+}
diff --git a/test/Index/Core/index-with-module.m b/test/Index/Core/index-with-module.m
index c83de63701e1..ca89c2e1de38 100644
--- a/test/Index/Core/index-with-module.m
+++ b/test/Index/Core/index-with-module.m
@@ -1,11 +1,17 @@
// RUN: rm -rf %t.mcp
// RUN: c-index-test core -print-source-symbols -dump-imported-module-files -- %s -I %S/Inputs/module -fmodules -fmodules-cache-path=%t.mcp | FileCheck %s
-// CHECK: [[@LINE+1]]:9 | module/C | ModA | Decl |
+// CHECK: [[@LINE+1]]:9 | module/C | ModA | [[ModA_USR:c:@M@ModA]] | Decl |
@import ModA;
-// CHECK: [[@LINE+1]]:1 | module/C | ModA | Decl,Impl |
+// CHECK: [[@LINE+1]]:1 | module/C | ModA | [[ModA_USR]] | Decl,Impl |
#include "ModA.h"
+@import ModA.SubModA.SubSubModA;
+// CHECK: [[@LINE-1]]:9 | module/C | ModA | [[ModA_USR]] | Ref |
+// CHECK: [[@LINE-2]]:14 | module/C | ModA.SubModA | c:@M@ModA@M@SubModA | Ref |
+// CHECK: [[@LINE-3]]:22 | module/C | ModA.SubModA.SubSubModA | [[SubSubModA_USR:c:@M@ModA@M@SubModA@M@SubSubModA]] | Decl |
+#include "SubSubModA.h" // CHECK: [[@LINE]]:1 | module/C | ModA.SubModA.SubSubModA | [[SubSubModA_USR]] | Decl,Impl |
+
void foo() {
// CHECK: [[@LINE+1]]:3 | function/C | ModA_func | c:@F@ModA_func | {{.*}} | Ref,Call,RelCall,RelCont | rel: 1
ModA_func();
diff --git a/test/Index/Inputs/cycle.h b/test/Index/Inputs/cycle.h
new file mode 100644
index 000000000000..5dc8890f1463
--- /dev/null
+++ b/test/Index/Inputs/cycle.h
@@ -0,0 +1 @@
+#include "cycle.h"
diff --git a/test/Index/annotate-comments-availability-attrs.cpp b/test/Index/annotate-comments-availability-attrs.cpp
index f31c4e16ccd6..2722c06fc8d9 100644
--- a/test/Index/annotate-comments-availability-attrs.cpp
+++ b/test/Index/annotate-comments-availability-attrs.cpp
@@ -13,7 +13,7 @@
void attr_availability_1() __attribute__((availability(macosx,obsoleted=10.0,introduced=8.0,deprecated=9.0, message="use availability_test in <foo.h>")))
__attribute__((availability(ios,unavailable, message="not for iOS")));
-// CHECK: FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments-availability-attrs.cpp" line="[[@LINE-3]]" column="6"><Name>attr_availability_1</Name><USR>c:@F@attr_availability_1#</USR><Declaration>void attr_availability_1()</Declaration><Abstract><Para> Aaa.</Para></Abstract><Availability distribution="iOS"><DeprecationSummary>not for iOS</DeprecationSummary><Unavailable/></Availability><Availability distribution="macOS"><IntroducedInVersion>8.0</IntroducedInVersion><DeprecatedInVersion>9.0</DeprecatedInVersion><RemovedAfterVersion>10.0</RemovedAfterVersion><DeprecationSummary>use availability_test in &lt;foo.h&gt;</DeprecationSummary></Availability></Function>]
+// CHECK: FullCommentAsXML=[<Function file="{{[^"]+}}annotate-comments-availability-attrs.cpp" line="[[@LINE-3]]" column="6"><Name>attr_availability_1</Name><USR>c:@F@attr_availability_1#</USR><Declaration>void attr_availability_1()</Declaration><Abstract><Para> Aaa.</Para></Abstract><Availability distribution="macOS"><IntroducedInVersion>8.0</IntroducedInVersion><DeprecatedInVersion>9.0</DeprecatedInVersion><RemovedAfterVersion>10.0</RemovedAfterVersion><DeprecationSummary>use availability_test in &lt;foo.h&gt;</DeprecationSummary></Availability><Availability distribution="iOS"><DeprecationSummary>not for iOS</DeprecationSummary><Unavailable/></Availability></Function>]
/// Aaa.
void attr_availability_2() __attribute__((availability(macosx,obsoleted=10.0.1,introduced=8.0.1,deprecated=9.0.1)));
diff --git a/test/Index/annotate-operator-call-expr.cpp b/test/Index/annotate-operator-call-expr.cpp
new file mode 100644
index 000000000000..facb841ce33f
--- /dev/null
+++ b/test/Index/annotate-operator-call-expr.cpp
@@ -0,0 +1,84 @@
+struct Foo {
+ int operator[](int key);
+ int operator()(int key = 2);
+};
+
+void testFoo(Foo foo, int index) {
+ foo();
+ foo(index);
+
+ foo[index];
+ foo[index + index];
+
+ foo[foo[index]];
+ foo[foo() + foo[index]];
+ foo[foo(index) + foo[index]];
+}
+
+// RUN: c-index-test -test-annotate-tokens=%s:7:1:7:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK1
+// CHECK1: Identifier: "foo" [7:3 - 7:6] DeclRefExpr=foo:6:18
+// CHECK1: Punctuation: "(" [7:6 - 7:7] DeclRefExpr=operator():3:7 RefName=[7:6 - 7:7] RefName=[7:7 - 7:8]
+// CHECK1: Punctuation: ")" [7:7 - 7:8] DeclRefExpr=operator():3:7 RefName=[7:6 - 7:7] RefName=[7:7 - 7:8]
+// CHECK1: Punctuation: ";" [7:8 - 7:9] CompoundStmt=
+
+// RUN: c-index-test -test-annotate-tokens=%s:8:1:8:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK2
+// CHECK2: Punctuation: "(" [8:6 - 8:7] DeclRefExpr=operator():3:7 RefName=[8:6 - 8:7] RefName=[8:12 - 8:13]
+// CHECK2: Identifier: "index" [8:7 - 8:12] DeclRefExpr=index:6:27
+// CHECK2: Punctuation: ")" [8:12 - 8:13] DeclRefExpr=operator():3:7 RefName=[8:6 - 8:7] RefName=[8:12 - 8:13]
+// CHECK2: Punctuation: ";" [8:13 - 8:14] CompoundStmt=
+
+// RUN: c-index-test -test-annotate-tokens=%s:10:1:10:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK3
+// CHECK3: Identifier: "foo" [10:3 - 10:6] DeclRefExpr=foo:6:18
+// CHECK3: Punctuation: "[" [10:6 - 10:7] DeclRefExpr=operator[]:2:7 RefName=[10:6 - 10:7] RefName=[10:12 - 10:13]
+// CHECK3: Identifier: "index" [10:7 - 10:12] DeclRefExpr=index:6:27
+// CHECK3: Punctuation: "]" [10:12 - 10:13] DeclRefExpr=operator[]:2:7 RefName=[10:6 - 10:7] RefName=[10:12 - 10:13]
+// CHECK3: Punctuation: ";" [10:13 - 10:14] CompoundStmt=
+
+// RUN: c-index-test -test-annotate-tokens=%s:11:1:11:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK4
+// CHECK4: Identifier: "foo" [11:3 - 11:6] DeclRefExpr=foo:6:18
+// CHECK4: Punctuation: "[" [11:6 - 11:7] DeclRefExpr=operator[]:2:7 RefName=[11:6 - 11:7] RefName=[11:20 - 11:21]
+// CHECK4: Identifier: "index" [11:7 - 11:12] DeclRefExpr=index:6:27
+// CHECK4: Punctuation: "+" [11:13 - 11:14] BinaryOperator=
+// CHECK4: Identifier: "index" [11:15 - 11:20] DeclRefExpr=index:6:27
+// CHECK4: Punctuation: "]" [11:20 - 11:21] DeclRefExpr=operator[]:2:7 RefName=[11:6 - 11:7] RefName=[11:20 - 11:21]
+// CHECK4: Punctuation: ";" [11:21 - 11:22] CompoundStmt=
+
+// RUN: c-index-test -test-annotate-tokens=%s:13:1:13:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK5
+// CHECK5: Identifier: "foo" [13:3 - 13:6] DeclRefExpr=foo:6:18
+// CHECK5: Punctuation: "[" [13:6 - 13:7] DeclRefExpr=operator[]:2:7 RefName=[13:6 - 13:7] RefName=[13:17 - 13:18]
+// CHECK5: Identifier: "foo" [13:7 - 13:10] DeclRefExpr=foo:6:18
+// CHECK5: Punctuation: "[" [13:10 - 13:11] DeclRefExpr=operator[]:2:7 RefName=[13:10 - 13:11] RefName=[13:16 - 13:17]
+// CHECK5: Identifier: "index" [13:11 - 13:16] DeclRefExpr=index:6:27
+// CHECK5: Punctuation: "]" [13:16 - 13:17] DeclRefExpr=operator[]:2:7 RefName=[13:10 - 13:11] RefName=[13:16 - 13:17]
+// CHECK5: Punctuation: "]" [13:17 - 13:18] DeclRefExpr=operator[]:2:7 RefName=[13:6 - 13:7] RefName=[13:17 - 13:18]
+// CHECK5: Punctuation: ";" [13:18 - 13:19] CompoundStmt=
+
+// RUN: c-index-test -test-annotate-tokens=%s:14:1:14:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK6
+// CHECK6: Identifier: "foo" [14:3 - 14:6] DeclRefExpr=foo:6:18
+// CHECK6: Punctuation: "[" [14:6 - 14:7] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26]
+// CHECK6: Identifier: "foo" [14:7 - 14:10] DeclRefExpr=foo:6:18
+// CHECK6: Punctuation: "(" [14:10 - 14:11] DeclRefExpr=operator():3:7 RefName=[14:10 - 14:11] RefName=[14:11 - 14:12]
+// CHECK6: Punctuation: ")" [14:11 - 14:12] DeclRefExpr=operator():3:7 RefName=[14:10 - 14:11] RefName=[14:11 - 14:12]
+// CHECK6: Punctuation: "+" [14:13 - 14:14] BinaryOperator=
+// CHECK6: Identifier: "foo" [14:15 - 14:18] DeclRefExpr=foo:6:18
+// CHECK6: Punctuation: "[" [14:18 - 14:19] DeclRefExpr=operator[]:2:7 RefName=[14:18 - 14:19] RefName=[14:24 - 14:25]
+// CHECK6: Identifier: "index" [14:19 - 14:24] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26]
+// CHECK6: Punctuation: "]" [14:24 - 14:25] DeclRefExpr=operator[]:2:7 RefName=[14:18 - 14:19] RefName=[14:24 - 14:25]
+// CHECK6: Punctuation: "]" [14:25 - 14:26] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26]
+// CHECK6: Punctuation: ";" [14:26 - 14:27] CompoundStmt=
+
+// RUN: c-index-test -test-annotate-tokens=%s:15:1:15:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK7
+// CHECK7: Identifier: "foo" [15:3 - 15:6] DeclRefExpr=foo:6:18
+// CHECK7: Punctuation: "[" [15:6 - 15:7] DeclRefExpr=operator[]:2:7 RefName=[15:6 - 15:7] RefName=[15:30 - 15:31]
+// CHECK7: Identifier: "foo" [15:7 - 15:10] DeclRefExpr=foo:6:18
+// CHECK7: Punctuation: "(" [15:10 - 15:11] DeclRefExpr=operator():3:7 RefName=[15:10 - 15:11] RefName=[15:16 - 15:17]
+// CHECK7: Identifier: "index" [15:11 - 15:16] DeclRefExpr=index:6:27
+// CHECK7: Punctuation: ")" [15:16 - 15:17] DeclRefExpr=operator():3:7 RefName=[15:10 - 15:11] RefName=[15:16 - 15:17]
+// CHECK7: Punctuation: "+" [15:18 - 15:19] BinaryOperator=
+// CHECK7: Identifier: "foo" [15:20 - 15:23] DeclRefExpr=foo:6:18
+// CHECK7: Punctuation: "[" [15:23 - 15:24] DeclRefExpr=operator[]:2:7 RefName=[15:23 - 15:24] RefName=[15:29 - 15:30]
+// CHECK7: Identifier: "index" [15:24 - 15:29] DeclRefExpr=index:6:27
+// CHECK7: Punctuation: "]" [15:29 - 15:30] DeclRefExpr=operator[]:2:7 RefName=[15:23 - 15:24] RefName=[15:29 - 15:30]
+// CHECK7: Punctuation: "]" [15:30 - 15:31] DeclRefExpr=operator[]:2:7 RefName=[15:6 - 15:7] RefName=[15:30 - 15:31]
+// CHECK7: Punctuation: ";" [15:31 - 15:32] CompoundStmt=
+
diff --git a/test/Index/attributes.c b/test/Index/attributes.c
index 95d9c7548bd7..e3b2c1ab7a7d 100644
--- a/test/Index/attributes.c
+++ b/test/Index/attributes.c
@@ -8,6 +8,10 @@ void pure_fn() __attribute__((pure));
void const_fn() __attribute__((const));
void noduplicate_fn() __attribute__((noduplicate));
+enum __attribute((flag_enum)) FlagEnum {
+ Foo
+};
+
// CHECK: attributes.c:3:32: StructDecl=Test2:3:32 (Definition) Extent=[3:1 - 5:2]
// CHECK: attributes.c:3:23: attribute(packed)=packed Extent=[3:23 - 3:29]
// CHECK: attributes.c:4:8: FieldDecl=a:4:8 (Definition) Extent=[4:3 - 4:9] [access=public]
@@ -18,3 +22,5 @@ void noduplicate_fn() __attribute__((noduplicate));
// CHECK: attributes.c:8:32: attribute(const)= Extent=[8:32 - 8:37]
// CHECK: attributes.c:9:6: FunctionDecl=noduplicate_fn:9:6 Extent=[9:1 - 9:51]
// CHECK: attributes.c:9:38: attribute(noduplicate)= Extent=[9:38 - 9:49]
+// CHECK: attributes.c:11:31: EnumDecl=FlagEnum:11:31 (Definition) Extent=[11:1 - 13:2]
+// CHECK: attributes.c:11:19: attribute(flag_enum)= Extent=[11:19 - 11:28]
diff --git a/test/Index/availability.c b/test/Index/availability.c
index 206b8a2a7105..9f3c995ffad3 100644
--- a/test/Index/availability.c
+++ b/test/Index/availability.c
@@ -14,9 +14,14 @@ void bar(void) __attribute__((availability(macosx,introduced=10.4))) __attribute
void bar2(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7))) __attribute__((availability(ios,introduced=3.2,deprecated=10.0))) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7))) __attribute__((availability(ios,introduced=3.2,deprecated=10.0)));
+void foo2(void) __attribute__((availability(swift,unavailable)));
+void foo3(void) __attribute__((availability(swift,deprecated)));
+
// RUN: c-index-test -test-load-source all %s | FileCheck %s
// CHECK: FunctionDecl=foo:3:6{{.*}}(ios, introduced=3.2, deprecated=4.1) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
// CHECK: EnumConstantDecl=old_enum:6:3 (Definition) (deprecated)
// CHECK: EnumConstantDecl=old_enum_plat:10:3 {{.*}} (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
// CHECK: FunctionDecl=bar:13:6{{.*}}(ios, introduced=3.2) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.6, message="use foobar")
// CHECK: FunctionDecl=bar2:15:6{{.*}}(ios, introduced=3.2, deprecated=10.0) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
+// CHECK: FunctionDecl=foo2:17:6{{.*}}(swift, unavailable)
+// CHECK: FunctionDecl=foo3:18:6{{.*}}(swift, deprecated=1)
diff --git a/test/Index/complete-access-checks.cpp b/test/Index/complete-access-checks.cpp
index 54d9640f6f59..bac63279c093 100644
--- a/test/Index/complete-access-checks.cpp
+++ b/test/Index/complete-access-checks.cpp
@@ -29,17 +29,20 @@ void Y::doSomething() {
// RUN: c-index-test -code-completion-at=%s:30:9 %s | FileCheck -check-prefix=CHECK-SUPER-ACCESS %s
this->;
+ // RUN: c-index-test -code-completion-at=%s:33:3 %s | FileCheck -check-prefix=CHECK-SUPER-ACCESS-IMPLICIT %s
+
+
Z that;
- // RUN: c-index-test -code-completion-at=%s:34:8 %s | FileCheck -check-prefix=CHECK-ACCESS %s
+ // RUN: c-index-test -code-completion-at=%s:37:8 %s | FileCheck -check-prefix=CHECK-ACCESS %s
that.
}
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func1}{LeftParen (}{RightParen )} (36)
-// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36)
+// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36){{$}}
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func3}{LeftParen (}{RightParen )} (36) (inaccessible)
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member1} (37)
-// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37)
+// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37){{$}}
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member3} (37) (inaccessible)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType Y &}{TypedText operator=}{LeftParen (}{Placeholder const Y &}{RightParen )} (79)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (81)
@@ -48,6 +51,14 @@ void Y::doSomething() {
// CHECK-SUPER-ACCESS: CXXDestructor:{ResultType void}{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )} (81)
// CHECK-SUPER-ACCESS: CXXDestructor:{ResultType void}{TypedText ~Y}{LeftParen (}{RightParen )} (79)
+// CHECK-SUPER-ACCESS-IMPLICIT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
+// CHECK-SUPER-ACCESS-IMPLICIT: CXXMethod:{ResultType void}{TypedText func1}{LeftParen (}{RightParen )} (36)
+// CHECK-SUPER-ACCESS-IMPLICIT: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (36){{$}}
+// CHECK-SUPER-ACCESS-IMPLICIT: CXXMethod:{ResultType void}{TypedText func3}{LeftParen (}{RightParen )} (36) (inaccessible)
+// CHECK-SUPER-ACCESS-IMPLICIT: FieldDecl:{ResultType int}{TypedText member1} (37)
+// CHECK-SUPER-ACCESS-IMPLICIT: FieldDecl:{ResultType int}{TypedText member2} (37){{$}}
+// CHECK-SUPER-ACCESS-IMPLICIT: FieldDecl:{ResultType int}{TypedText member3} (37) (inaccessible)
+
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func1}{LeftParen (}{RightParen )} (34)
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) (inaccessible)
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func3}{LeftParen (}{RightParen )} (34) (inaccessible)
@@ -69,9 +80,9 @@ public:
};
void f(P x, Q y) {
- // RUN: c-index-test -code-completion-at=%s:73:5 %s | FileCheck -check-prefix=CHECK-USING-INACCESSIBLE %s
+ // RUN: c-index-test -code-completion-at=%s:84:5 %s | FileCheck -check-prefix=CHECK-USING-INACCESSIBLE %s
x.; // member is inaccessible
- // RUN: c-index-test -code-completion-at=%s:75:5 %s | FileCheck -check-prefix=CHECK-USING-ACCESSIBLE %s
+ // RUN: c-index-test -code-completion-at=%s:86:5 %s | FileCheck -check-prefix=CHECK-USING-ACCESSIBLE %s
y.; // member is accessible
}
@@ -102,11 +113,11 @@ class D : public C {
};
void D::f(::B *that) {
- // RUN: c-index-test -code-completion-at=%s:106:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THIS %s
+ // RUN: c-index-test -code-completion-at=%s:117:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THIS %s
this->;
// CHECK-PRIVATE-SUPER-THIS: FieldDecl:{ResultType int}{Informative B::}{TypedText member} (37) (inaccessible)
- // RUN: c-index-test -code-completion-at=%s:110:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THAT %s
+ // RUN: c-index-test -code-completion-at=%s:121:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THAT %s
that->;
// CHECK-PRIVATE-SUPER-THAT: FieldDecl:{ResultType int}{TypedText member} (35) (inaccessible)
}
diff --git a/test/Index/complete-block-properties.m b/test/Index/complete-block-properties.m
index a754712e4c99..0e8872dece23 100644
--- a/test/Index/complete-block-properties.m
+++ b/test/Index/complete-block-properties.m
@@ -40,15 +40,15 @@ typedef int (^BarBlock)(int *);
// RUN: c-index-test -code-completion-at=%s:35:33 %s | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: c-index-test -code-completion-at=%s:36:21 %s | FileCheck -check-prefix=CHECK-CC1 %s
//CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText barBlock}{LeftParen (}{Placeholder int *}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText block}{LeftParen (}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)()}{TypedText block}{Equal = }{Placeholder ^(void)} (38)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo}{TypedText blocker}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder Foo y}{Comma , }{Placeholder ^(Foo *someParameter)foo}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo (^)(int, Foo, FooBlock)}{TypedText blocker}{Equal = }{Placeholder ^Foo(int x, Foo y, FooBlock foo)} (32)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText block}{LeftParen (}{RightParen )} (37)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)()}{TypedText block}{Equal = }{Placeholder ^(void)} (40)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo}{TypedText blocker}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder Foo y}{Comma , }{Placeholder ^(Foo *someParameter)foo}{RightParen )} (37)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo (^)(int, Foo, FooBlock)}{TypedText blocker}{Equal = }{Placeholder ^Foo(int x, Foo y, FooBlock foo)} (34)
//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText fooBlock}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Test *}{TypedText getObject}{LeftParen (}{Placeholder int index}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performA}{LeftParen (}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performB}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder int y}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performA}{LeftParen (}{RightParen )} (37)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performB}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder int y}{RightParen )} (37)
@end
diff --git a/test/Index/complete-block-property-assignment.m b/test/Index/complete-block-property-assignment.m
index 908e18629528..c1abc03ad06d 100644
--- a/test/Index/complete-block-property-assignment.m
+++ b/test/Index/complete-block-property-assignment.m
@@ -34,10 +34,10 @@ typedef void (^FooBlock)(Foo *someParameter);
// RUN: c-index-test -code-completion-at=%s:28:27 %s | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: c-index-test -code-completion-at=%s:29:22 %s | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: c-index-test -code-completion-at=%s:30:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (37)
// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
-// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onAction}{LeftParen (}{Placeholder Obj *object}{RightParen )} (35)
-// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction}{Equal = }{Placeholder ^(Obj *object)} (38)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onAction}{LeftParen (}{Placeholder Obj *object}{RightParen )} (37)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction}{Equal = }{Placeholder ^(Obj *object)} (40)
// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onEventHandler}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler}{Equal = }{Placeholder ^(Foo *someParameter)} (38)
// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onReadonly}{LeftParen (}{Placeholder int *someParameter}{RightParen )} (35)
@@ -60,13 +60,20 @@ typedef void (^FooBlock)(Foo *someParameter);
// RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
// RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
// RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
// RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
-// CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (37)
// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
-// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (37)
// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (37)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (37)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
@end
diff --git a/test/Index/complete-ctor-inits.cpp b/test/Index/complete-ctor-inits.cpp
index 96f36b65e3d0..46793bda9ffd 100644
--- a/test/Index/complete-ctor-inits.cpp
+++ b/test/Index/complete-ctor-inits.cpp
@@ -30,27 +30,33 @@ struct PR23948 {
};
// RUN: c-index-test -code-completion-at=%s:18:10 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: NotImplemented:{TypedText X<int>}{LeftParen (}{Placeholder args}{RightParen )} (7)
-// CHECK-CC1: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (35)
+// CHECK-CC1: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC1: MemberRef:{TypedText b}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC1: MemberRef:{TypedText c}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder const Virt &}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder Virt &&}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText X<int>}{LeftParen (}{Placeholder int}{RightParen )} (7)
+// CHECK-CC1: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder const Y &}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder Y &&}{RightParen )} (35)
// RUN: c-index-test -code-completion-at=%s:18:23 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// CHECK-CC2: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC2: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC2: MemberRef:{TypedText b}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC2: MemberRef:{TypedText c}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC2: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder const Virt &}{RightParen )} (35)
+// CHECK-CC2: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder Virt &&}{RightParen )} (35)
+// CHECK-CC2: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder const Y &}{RightParen )} (7)
+// CHECK-CC2: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder Y &&}{RightParen )} (7)
// RUN: c-index-test -code-completion-at=%s:18:36 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC3-NOT: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CC3: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7)
-// CHECK-CC3-NOT: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CC3: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (35)
+// CHECK-CC3: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC3-NOT: MemberRef:{TypedText b}{LeftParen (}{Placeholder int}{RightParen )}
+// CHECK-CC3: MemberRef:{TypedText c}{LeftParen (}{Placeholder int}{RightParen )} (7)
+// CHECK-CC3-NOT: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder const Virt &}{RightParen )} (35)
+// CHECK-CC3-NOT: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder Virt &&}{RightParen )} (35)
+// CHECK-CC3: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder const Y &}{RightParen )} (35)
+// CHECK-CC3: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder Y &&}{RightParen )} (35)
// RUN: c-index-test -code-completion-at=%s:22:10 -target i386-apple-darwin %s | FileCheck -check-prefix=CHECK-CC4 %s
-// CHECK-CC4: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC4: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (7)
// RUN: c-index-test -code-completion-at=%s:26:10 %s
diff --git a/test/Index/complete-cxx-inline-methods.cpp b/test/Index/complete-cxx-inline-methods.cpp
index 0f78e8caa748..aefc16f53f8f 100644
--- a/test/Index/complete-cxx-inline-methods.cpp
+++ b/test/Index/complete-cxx-inline-methods.cpp
@@ -21,6 +21,13 @@ private:
int value;
MyCls *object;
};
+
+template <typename T>
+class X {};
+
+class Y : public X<int> {
+ Y() : X<int>() {}
+};
}
// RUN: c-index-test -code-completion-at=%s:4:9 -std=c++98 %s | FileCheck %s
@@ -35,10 +42,12 @@ private:
// CHECK-NEXT: Container Kind: StructDecl
// RUN: c-index-test -code-completion-at=%s:18:41 %s | FileCheck -check-prefix=CHECK-CTOR-INIT %s
-// CHECK-CTOR-INIT: NotImplemented:{TypedText MyCls}{LeftParen (}{Placeholder args}{RightParen )} (7)
-// CHECK-CTOR-INIT: MemberRef:{TypedText object}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CTOR-INIT: MemberRef:{TypedText value}{LeftParen (}{Placeholder args}{RightParen )} (35)
+// CHECK-CTOR-INIT: ClassDecl:{TypedText MyCls}{LeftParen (}{Placeholder MyCls}{RightParen )} (7)
+// CHECK-CTOR-INIT: MemberRef:{TypedText object}{LeftParen (}{Placeholder MyCls *}{RightParen )} (35)
+// CHECK-CTOR-INIT: MemberRef:{TypedText value}{LeftParen (}{Placeholder int}{RightParen )} (35)
// RUN: c-index-test -code-completion-at=%s:18:55 %s | FileCheck -check-prefix=CHECK-CTOR-INIT-2 %s
-// CHECK-CTOR-INIT-2-NOT: NotImplemented:{TypedText MyCls}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CTOR-INIT-2: MemberRef:{TypedText object}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CTOR-INIT-2: MemberRef:{TypedText value}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CTOR-INIT-2-NOT: ClassDecl:{TypedText MyCls}{LeftParen (}{Placeholder MyCls}{RightParen )} (7)
+// CHECK-CTOR-INIT-2: MemberRef:{TypedText object}{LeftParen (}{Placeholder MyCls *}{RightParen )} (35)
+// CHECK-CTOR-INIT-2: MemberRef:{TypedText value}{LeftParen (}{Placeholder int}{RightParen )} (7)
+// RUN: c-index-test -code-completion-at=%s:29:9 %s | FileCheck -check-prefix=CHECK-CTOR-INIT-3 %s
+// CHECK-CTOR-INIT-3: ClassDecl:{TypedText X<int>}{LeftParen (}{Placeholder X<int>}{RightParen )} (7)
diff --git a/test/Index/complete-exprs.c b/test/Index/complete-exprs.c
index dbb6019d82ce..9beb16deef99 100644
--- a/test/Index/complete-exprs.c
+++ b/test/Index/complete-exprs.c
@@ -33,16 +33,11 @@ void f5(float f) {
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (8)
// CHECK-CC1: NotImplemented:{ResultType size_t}{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (40)
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
-// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
-// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: macro definition:{TypedText __VERSION__} (70)
-// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
-// CHECK-CC3-NOT: NotImplemented:{TypedText float}
-// CHECK-CC3: ParmDecl:{ResultType int}{TypedText j} (34)
-// CHECK-CC3: NotImplemented:{ResultType size_t}{TypedText sizeof}{LeftParen (}{Placeholder expressio
+// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
-// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
-// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: c-index-test -code-completion-at=%s:7:2 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: macro definition:{TypedText __VERSION__} (70)
// CHECK-CC2: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
diff --git a/test/Index/complete-member-access.m b/test/Index/complete-member-access.m
index 5e40be1eac01..0248cd1fabc1 100644
--- a/test/Index/complete-member-access.m
+++ b/test/Index/complete-member-access.m
@@ -61,8 +61,8 @@ int test_two_levels(Other *other) {
// RUN: c-index-test -code-completion-at=%s:34:12 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: ObjCInstanceMethodDecl:{ResultType int}{TypedText myOtherPropLikeThing} (37)
// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText myProp} (35)
-// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (35)
-// CHECK-CC3: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (35)
+// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (37)
+// CHECK-CC3: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (37)
// CHECK-CC3: Completion contexts:
// CHECK-CC3-NEXT: Objective-C property access
// CHECK-CC3-NEXT: Container Kind: ObjCInterfaceDecl
@@ -72,6 +72,6 @@ int test_two_levels(Other *other) {
// RUN: c-index-test -code-completion-at=%s:42:20 %s | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText myOtherPropLikeThing} (37)
// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText myProp} (35)
-// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (35)
-// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (35)
+// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (37)
+// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (37)
diff --git a/test/Index/complete-pch-skip.cpp b/test/Index/complete-pch-skip.cpp
index 6abf40df36c1..38ba228ba29d 100644
--- a/test/Index/complete-pch-skip.cpp
+++ b/test/Index/complete-pch-skip.cpp
@@ -4,19 +4,26 @@ int bar;
int main() { return ns:: }
int main2() { return ns::foo(). }
+int main3() { PREAMBLE_ }
-// RUN: echo "namespace ns { struct foo { int baz }; }" > %t.h
+// RUN: printf "namespace ns { struct foo { int baz }; }\n#define PREAMBLE_MAC" > %t.h
// RUN: c-index-test -write-pch %t.h.pch -x c++-header %t.h
//
// RUN: c-index-test -code-completion-at=%s:5:26 -include %t.h %s | FileCheck -check-prefix=WITH-PCH %s
// WITH-PCH: {TypedText bar}
// WITH-PCH: {TypedText foo}
+// RUN: c-index-test -code-completion-at=%s:7:24 -include %t.h %s | FileCheck -check-prefix=WITH-PCH-MACRO %s
+// WITH-PCH-MACRO: {TypedText PREAMBLE_MAC}
+
// RUN: env CINDEXTEST_COMPLETION_SKIP_PREAMBLE=1 c-index-test -code-completion-at=%s:5:26 -include %t.h %s | FileCheck -check-prefix=SKIP-PCH %s
// SKIP-PCH-NOT: foo
// SKIP-PCH: {TypedText bar}
// SKIP-PCH-NOT: foo
+// RUN: env CINDEXTEST_COMPLETION_SKIP_PREAMBLE=1 c-index-test -code-completion-at=%s:7:24 -include %t.h %s | FileCheck -check-prefix=SKIP-PCH-MACRO %s
+// SKIP-PCH-MACRO-NOT: {TypedText PREAMBLE_MAC}
+
// Verify that with *no* preamble (no -include flag) we still get local results.
// SkipPreamble used to break this, by making lookup *too* lazy.
// RUN: env CINDEXTEST_COMPLETION_SKIP_PREAMBLE=1 c-index-test -code-completion-at=%s:5:26 %s | FileCheck -check-prefix=NO-PCH %s
diff --git a/test/Index/complete-properties.m b/test/Index/complete-properties.m
index 0c49819ac2a7..7dd4f1c9afb0 100644
--- a/test/Index/complete-properties.m
+++ b/test/Index/complete-properties.m
@@ -77,11 +77,11 @@ id test(I3 *i3) {
// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop4}
// RUN: c-index-test -code-completion-at=%s:29:13 %s | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5: ObjCPropertyDecl:{ResultType int}{TypedText Prop0} (35)
-// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText Prop1} (35)
-// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText Prop2} (35)
+// CHECK-CC5: ObjCPropertyDecl:{ResultType int}{TypedText Prop0} (37)
+// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText Prop1} (37)
+// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText Prop2} (37)
// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop3} (35)
-// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop4} (35)
+// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop4} (37)
// RUN: c-index-test -code-completion-at=%s:9:11 %s | FileCheck -check-prefix=CHECK-CC6 %s
// CHECK-CC6: ObjCInterfaceDecl:{TypedText MyClass} (50)
@@ -93,7 +93,7 @@ id test(I3 *i3) {
// CHECK-CC7: ObjCIvarDecl:{ResultType id}{TypedText Prop2_} (7)
// RUN: c-index-test -code-completion-at=%s:57:13 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC8 %s
-// CHECK-CC8: ObjCPropertyDecl:{ResultType int}{TypedText Prop5} (35)
+// CHECK-CC8: ObjCPropertyDecl:{ResultType int}{TypedText Prop5} (37)
@interface ClassProperties
@@ -157,12 +157,12 @@ void classProperties() {
// CHECK-CC9-NOT: instanceProperty
// RUN: c-index-test -code-completion-at=%s:145:28 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC10 %s
-// CHECK-CC10: ObjCPropertyDecl:{ResultType int}{TypedText explicit} (35)
-// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitInProtocol} (35)
-// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitReadonly} (35)
-// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicit} (37)
-// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitInCategory} (37)
-// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitReadonly} (37)
+// CHECK-CC10: ObjCPropertyDecl:{ResultType int}{TypedText explicit} (37)
+// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitInProtocol} (37)
+// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitReadonly} (37)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicit} (39)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitInCategory} (39)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitReadonly} (39)
// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType ClassProperties *}{TypedText shadowedImplicit} (35)
// CHECK-CC10-NOT: implicitInstance
// CHECK-CC10-NOT: noProperty
diff --git a/test/Index/complete-switch.c b/test/Index/complete-switch.c
new file mode 100644
index 000000000000..9a9438c28d31
--- /dev/null
+++ b/test/Index/complete-switch.c
@@ -0,0 +1,10 @@
+void f() {
+ auto foo = bar;
+ switch(foo) {
+ case x:
+ break;
+ }
+}
+
+// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:4:10 %s | FileCheck %s -allow-empty
+// CHECK-NOT: COMPLETION: foo
diff --git a/test/Index/complete-template-keywords.cpp b/test/Index/complete-template-keywords.cpp
new file mode 100644
index 000000000000..1e593330eb73
--- /dev/null
+++ b/test/Index/complete-template-keywords.cpp
@@ -0,0 +1,5 @@
+templ
+// RUN: env c-index-test -code-completion-at=%s:1:5 %s | FileCheck -check-prefix=CHECK-NO-PATTERN %s
+// CHECK-NO-PATTERN: {TypedText template} (1)
+// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:1:5 %s | FileCheck -check-prefix=CHECK-PATTERN %s
+// CHECK-PATTERN: {TypedText template}{LeftAngle <}
diff --git a/test/Index/complete-type-factors.m b/test/Index/complete-type-factors.m
index f2588e6fe65e..fcd51284bf0b 100644
--- a/test/Index/complete-type-factors.m
+++ b/test/Index/complete-type-factors.m
@@ -39,7 +39,6 @@ void test2(A *a) {
// CHECK-CC1: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (25)
// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (32)
// CHECK-CC1: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (32)
-// CHECK-CC1: VarDecl:{ResultType int}{TypedText i} (8)
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText integer} (8)
// CHECK-CC1: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (32)
// CHECK-CC1: ParmDecl:{ResultType enum Priority}{TypedText priority} (17)
@@ -48,7 +47,6 @@ void test2(A *a) {
// CHECK-CC1: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (25)
// RUN: c-index-test -code-completion-at=%s:17:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (16)
-// CHECK-CC2: VarDecl:{ResultType enum Color}{TypedText c} (8)
// CHECK-CC2: ParmDecl:{ResultType enum Color}{TypedText color} (8)
// CHECK-CC2: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25)
// CHECK-CC2: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50)
diff --git a/test/Index/complete-with-annotations.cpp b/test/Index/complete-with-annotations.cpp
index 7bad8f1b7cbe..459bd9f57316 100644
--- a/test/Index/complete-with-annotations.cpp
+++ b/test/Index/complete-with-annotations.cpp
@@ -14,7 +14,7 @@ void X::doSomething() {
}
// CHECK: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
-// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("three", "two", "one")
+// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("one", "two", "three")
// CHECK: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) ("some annotation")
// CHECK: FieldDecl:{ResultType int}{TypedText member2} (35) ("another annotation", "some annotation")
// CHECK: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79)
diff --git a/test/Index/coroutines.cpp b/test/Index/coroutines.cpp
new file mode 100644
index 000000000000..5853437926c6
--- /dev/null
+++ b/test/Index/coroutines.cpp
@@ -0,0 +1,24 @@
+// RUN: c-index-test -test-load-source all -c %s -fsyntax-only -target x86_64-apple-darwin9 -fcoroutines-ts -std=c++1z -I%S/../SemaCXX/Inputs | FileCheck %s
+#include "std-coroutine.h"
+
+using std::experimental::suspend_always;
+using std::experimental::suspend_never;
+
+struct promise_void {
+ void get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void unhandled_exception();
+};
+
+template <>
+struct std::experimental::coroutine_traits<void> { using promise_type = promise_void; };
+
+void CoroutineTestRet() {
+ co_return;
+}
+// CHECK: [[@LINE-3]]:25: UnexposedStmt=
+// CHECK-SAME: [[@LINE-4]]:25 - [[@LINE-2]]:2]
+// CHECK: [[@LINE-4]]:3: UnexposedStmt=
+// CHECK-SAME: [[@LINE-5]]:3 - [[@LINE-5]]:12]
diff --git a/test/Index/cxx11-lambdas.cpp b/test/Index/cxx11-lambdas.cpp
index d0ee908059fa..6d6cbb631285 100644
--- a/test/Index/cxx11-lambdas.cpp
+++ b/test/Index/cxx11-lambdas.cpp
@@ -7,6 +7,7 @@ struct X {
auto lambda = [&localA, localB] (Integer x) -> Integer {
return localA + localB + x;
};
+ auto lambda2 = [](Integer y) {};
}
};
@@ -14,9 +15,9 @@ struct X {
// CHECK-LOAD: cxx11-lambdas.cpp:7:19: LambdaExpr= Extent=[7:19 - 9:6]
// CHECK-LOAD: cxx11-lambdas.cpp:7:21: VariableRef=localA:6:9 Extent=[7:21 - 7:27]
// CHECK-LOAD: cxx11-lambdas.cpp:7:29: VariableRef=localB:6:17 Extent=[7:29 - 7:35]
-// CHECK-LOAD: cxx11-lambdas.cpp:7:52: TypeRef=Integer:3:13 Extent=[7:52 - 7:59]
// CHECK-LOAD: cxx11-lambdas.cpp:7:46: ParmDecl=x:7:46 (Definition) Extent=[7:38 - 7:47]
// CHECK-LOAD: cxx11-lambdas.cpp:7:38: TypeRef=Integer:3:13 Extent=[7:38 - 7:45]
+// CHECK-LOAD: cxx11-lambdas.cpp:7:52: TypeRef=Integer:3:13 Extent=[7:52 - 7:59]
// CHECK-LOAD: cxx11-lambdas.cpp:7:60: CompoundStmt= Extent=[7:60 - 9:6]
// CHECK-LOAD: cxx11-lambdas.cpp:8:7: ReturnStmt= Extent=[8:7 - 8:33]
// CHECK-LOAD: cxx11-lambdas.cpp:8:14: DeclRefExpr=localA:6:9 Extent=[8:14 - 8:20]
@@ -26,8 +27,10 @@ struct X {
// RUN: env CINDEXTEST_INDEXLOCALSYMBOLS=1 c-index-test -index-file -std=c++11 %s | FileCheck -check-prefix=CHECK-INDEX %s
// CHECK-INDEX: [indexEntityReference]: kind: variable | name: localA | USR: c:cxx11-lambdas.cpp@100@S@X@F@f#@localA | lang: C | cursor: VariableRef=localA:6:9 | loc: 7:21
// CHECK-INDEX: [indexEntityReference]: kind: variable | name: localB | USR: c:cxx11-lambdas.cpp@100@S@X@F@f#@localB | lang: C | cursor: VariableRef=localB:6:17 | loc: 7:29
+// CHECK-INDEX: [indexDeclaration]: kind: variable | name: x | USR: c:cxx11-lambdas.cpp@157@S@X@F@f#@Sa@F@operator()#I#1@x | lang: C | cursor: ParmDecl=x:7:46 (Definition) | loc: 7:46
// CHECK-INDEX: [indexEntityReference]: kind: typedef | name: Integer | USR: c:cxx11-lambdas.cpp@T@Integer | lang: C | cursor: TypeRef=Integer:3:13 | loc: 7:52
// CHECK-INDEX: [indexEntityReference]: kind: typedef | name: Integer | USR: c:cxx11-lambdas.cpp@T@Integer | lang: C | cursor: TypeRef=Integer:3:13 | loc: 7:38
// CHECK-INDEX: [indexEntityReference]: kind: variable | name: localA | USR: c:cxx11-lambdas.cpp@100@S@X@F@f#@localA | lang: C | cursor: DeclRefExpr=localA:6:9 | loc: 8:14
// CHECK-INDEX: [indexEntityReference]: kind: variable | name: localB | USR: c:cxx11-lambdas.cpp@100@S@X@F@f#@localB | lang: C | cursor: DeclRefExpr=localB:6:17 | loc: 8:23
// CHECK-INDEX: [indexEntityReference]: kind: variable | name: x | USR: c:cxx11-lambdas.cpp@157@S@X@F@f#@Sa@F@operator()#I#1@x | lang: C | cursor: DeclRefExpr=x:7:46 | loc: 8:32
+// CHECK-INDEX: [indexDeclaration]: kind: variable | name: y | USR: c:cxx11-lambdas.cpp@244@S@X@F@f#@Sa@F@operator()#I#1@y | lang: C | cursor: ParmDecl=y:10:31 (Definition) | loc: 10:31 \ No newline at end of file
diff --git a/test/Index/implicit-attrs.m b/test/Index/implicit-attrs.m
new file mode 100644
index 000000000000..ca651cdb791f
--- /dev/null
+++ b/test/Index/implicit-attrs.m
@@ -0,0 +1,6 @@
+@interface Foo
+-(instancetype)init;
+@end
+
+// RUN: env CINDEXTEST_VISIT_IMPLICIT_ATTRIBUTES=1 c-index-test -test-print-decl-attributes %s -fobjc-arc | FileCheck %s
+// CHECK: ObjCInstanceMethodDecl=init:2:16 attribute(ns_consumes_self)= attribute(ns_returns_retained)=
diff --git a/test/Index/index-attrs.m b/test/Index/index-attrs.m
index 09c52ba3dcfe..574725562e40 100644
--- a/test/Index/index-attrs.m
+++ b/test/Index/index-attrs.m
@@ -9,9 +9,48 @@
@property (assign) id prop __attribute__((annotate("anno")));
@end
+__attribute__((objc_protocol_requires_explicit_implementation))
+@protocol P
+@end
+
+typedef id __attribute__((objc_independent_class)) T2;
+id __attribute__((objc_precise_lifetime)) x;
+struct __attribute__((objc_boxable)) S {
+ int x;
+};
+
+__attribute__((objc_exception))
+__attribute__((objc_root_class))
+__attribute__((objc_subclassing_restricted))
+__attribute__((objc_runtime_visible))
+@interface J
+-(id)a __attribute__((ns_returns_retained));
+-(id)b __attribute__((ns_returns_not_retained));
+-(id)c __attribute__((ns_returns_autoreleased));
+-(id)d __attribute__((ns_consumes_self));
+-(id)e __attribute__((objc_requires_super));
+-(int *)f __attribute__((objc_returns_inner_pointer));
+-(id)init __attribute__((objc_designated_initializer));
+@end
+
// RUN: c-index-test -index-file %s | FileCheck %s
// CHECK: <attribute>: attribute(iboutletcollection)= [IBOutletCollection=ObjCInterface]
// CHECK: <attribute>: attribute(annotate)=anno
// CHECK: <getter>: kind: objc-instance-method | name: prop | {{.*}} <attribute>: attribute(annotate)=anno
// CHECK: <setter>: kind: objc-instance-method | name: setProp: | {{.*}} <attribute>: attribute(annotate)=anno
+// CHECK: <attribute>: attribute(objc_protocol_requires_explicit_implementation)=
+// CHECK: <attribute>: attribute(objc_independent_class)=
+// CHECK: <attribute>: attribute(objc_precise_lifetime)=
+// CHECK: <attribute>: attribute(objc_boxable)=
+// CHECK: <attribute>: attribute(objc_exception)=
+// CHECK: <attribute>: attribute(objc_root_class)=
+// CHECK: <attribute>: attribute(objc_subclassing_restricted)=
+// CHECK: <attribute>: attribute(objc_runtime_visible)=
+// CHECK: <attribute>: attribute(ns_returns_retained)=
+// CHECK: <attribute>: attribute(ns_returns_not_retained)=
+// CHECK: <attribute>: attribute(ns_returns_autoreleased)=
+// CHECK: <attribute>: attribute(ns_consumes_self)=
+// CHECK: <attribute>: attribute(objc_requires_super)=
+// CHECK: <attribute>: attribute(objc_returns_inner_pointer)=
+// CHECK: <attribute>: attribute(objc_designated_initializer)=
diff --git a/test/Index/index-local-symbol.cpp b/test/Index/index-local-symbol.cpp
new file mode 100644
index 000000000000..1ffc4ec89ed8
--- /dev/null
+++ b/test/Index/index-local-symbol.cpp
@@ -0,0 +1,6 @@
+void ff() {
+ struct Foo {};
+}
+
+// RUN: env CINDEXTEST_INDEXLOCALSYMBOLS=1 c-index-test -index-file %s | FileCheck %s
+// CHECK: [indexDeclaration]: kind: struct | name: Foo | {{.*}} | loc: 2:10 \ No newline at end of file
diff --git a/test/Index/index-template-specialization.cpp b/test/Index/index-template-specialization.cpp
index d11754113c46..d50da0f2d63d 100644
--- a/test/Index/index-template-specialization.cpp
+++ b/test/Index/index-template-specialization.cpp
@@ -9,6 +9,12 @@ void g() {
foo.f(0);
}
+template <typename T>
+struct B {};
+
+template <typename T>
+struct D : B<T> {};
+
// FIXME: if c-index-test uses OrigD for symbol info, refererences below should
// refer to template specialization decls.
// RUN: env CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS=1 c-index-test -index-file %s | FileCheck %s
@@ -17,3 +23,7 @@ void g() {
// CHECK-NEXT: [indexDeclaration]: kind: function | name: g
// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: Foo | USR: c:@ST>1#T@Foo
// CHECK-NEXT: [indexEntityReference]: kind: c++-instance-method | name: f | USR: c:@ST>1#T@Foo@F@f#t0.0#
+
+// CHECK: [indexDeclaration]: kind: c++-class-template | name: D
+// CHECK-NEXT: <base>: kind: c++-class-template | name: B
+// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: B
diff --git a/test/Index/keep-going-include-cycle.c b/test/Index/keep-going-include-cycle.c
new file mode 100644
index 000000000000..b0fe24fa25df
--- /dev/null
+++ b/test/Index/keep-going-include-cycle.c
@@ -0,0 +1,10 @@
+#include "cycle.h"
+#include "foo.h"
+
+// RUN: env CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type -I%S/Inputs %s 2> %t.stderr.txt | FileCheck %s
+// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
+
+// Verify that we don't stop preprocessing after an include cycle.
+// CHECK: VarDecl=global_var:1:12 [type=int] [typekind=Int] [isPOD=1]
+
+// CHECK-DIAG: cycle.h:1:10: error: #include nested too deeply
diff --git a/test/Index/keep-going.cpp b/test/Index/keep-going.cpp
index dbfcad32d3d2..b3f29c5d3dae 100644
--- a/test/Index/keep-going.cpp
+++ b/test/Index/keep-going.cpp
@@ -9,11 +9,18 @@ class B : public A<int> { };
class C : public A<float> { };
-// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type %s -std=c++03 2> %t.stderr.txt | FileCheck %s
+// Not found includes shouldn't affect subsequent correct includes.
+#include "foo.h"
+
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type -I%S/Inputs %s -std=c++03 2> %t.stderr.txt | FileCheck %s
// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
+// Verify that even without CINDEXTEST_EDITING we don't stop processing after a fatal error.
+// RUN: env CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type -I%S/Inputs %s -std=c++03 2> %t.stderr.txt | FileCheck -check-prefix CHECK-KEEP-GOING-ONLY %s
+
// CHECK: inclusion directive=missing1.h ((null)) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: inclusion directive=missing2.h ((null)) [type=] [typekind=Invalid] [isPOD=0]
+// CHECK: inclusion directive=foo.h ({{.*[/\\]}}test{{[/\\]}}Index{{[/\\]}}Inputs{{[/\\]}}foo.h) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: ClassTemplate=A:4:7 (Definition) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: TemplateTypeParameter=T:3:16 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
// CHECK: FieldDecl=a:4:13 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
@@ -25,5 +32,7 @@ class C : public A<float> { };
// CHECK: C++ base class specifier=A<float>:4:7 [access=public isVirtual=false] [type=A<float>] [typekind=Unexposed] [templateargs/1= [type=float] [typekind=Float]] [canonicaltype=A<float>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1]
// CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0]
+// CHECK-KEEP-GOING-ONLY: VarDecl=global_var:1:12 [type=int] [typekind=Int] [isPOD=1]
+
// CHECK-DIAG: keep-going.cpp:1:10: fatal error: 'missing1.h' file not found
// CHECK-DIAG: keep-going.cpp:8:10: fatal error: 'missing2.h' file not found
diff --git a/test/Index/nullability.c b/test/Index/nullability.c
new file mode 100644
index 000000000000..26e55cb65f47
--- /dev/null
+++ b/test/Index/nullability.c
@@ -0,0 +1,10 @@
+int *a;
+int * _Nonnull b;
+int * _Nullable c;
+int * _Null_unspecified d;
+
+// RUN: env CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES=1 c-index-test -test-print-type %s | FileCheck %s
+// CHECK: VarDecl=a:1:6 [type=int *] [typekind=Pointer] [isPOD=1] [pointeetype=int] [pointeekind=Int]
+// CHECK: VarDecl=b:2:16 [type=int * _Nonnull] [typekind=Attributed] [nullability=nonnull] [canonicaltype=int *] [canonicaltypekind=Pointer] [modifiedtype=int *] [modifiedtypekind=Pointer] [isPOD=1]
+// CHECK: VarDecl=c:3:17 [type=int * _Nullable] [typekind=Attributed] [nullability=nullable] [canonicaltype=int *] [canonicaltypekind=Pointer] [modifiedtype=int *] [modifiedtypekind=Pointer] [isPOD=1]
+// CHECK: VarDecl=d:4:25 [type=int * _Null_unspecified] [typekind=Attributed] [nullability=unspecified] [canonicaltype=int *] [canonicaltypekind=Pointer] [modifiedtype=int *] [modifiedtypekind=Pointer] [isPOD=1]
diff --git a/test/Index/objc-typeargs-protocols.m b/test/Index/objc-typeargs-protocols.m
new file mode 100644
index 000000000000..780f7b2c7444
--- /dev/null
+++ b/test/Index/objc-typeargs-protocols.m
@@ -0,0 +1,28 @@
+
+@interface TestA
+@end
+
+@interface TestB
+@end
+
+@protocol Bar
+@end
+
+@interface Base
+@end
+
+@interface Foo<FirstType, SecondType> : Base
+@end
+
+Foo *a;
+Foo<TestA *, TestB *> *b;
+Foo<Bar> *c;
+Foo<TestA *, TestB *><Bar> *d;
+id<Bar> e;
+
+// RUN: c-index-test -test-print-type %s | FileCheck %s
+// CHECK: VarDecl=a:17:6 [type=Foo *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface]
+// CHECK: VarDecl=b:18:24 [type=Foo<TestA *,TestB *> *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [typeargs= [TestA *] [ObjCObjectPointer] [TestB *] [ObjCObjectPointer]] [isPOD=1] [pointeetype=Foo<TestA *,TestB *>] [pointeekind=ObjCObject]
+// CHECK: VarDecl=c:19:11 [type=Foo<Bar> *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [protocols=ObjCProtocolDecl=Bar:8:11 (Definition)] [isPOD=1] [pointeetype=Foo<Bar>] [pointeekind=ObjCObject]
+// CHECK: VarDecl=d:20:29 [type=Foo<TestA *,TestB *><Bar> *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [typeargs= [TestA *] [ObjCObjectPointer] [TestB *] [ObjCObjectPointer]] [protocols=ObjCProtocolDecl=Bar:8:11 (Definition)] [isPOD=1] [pointeetype=Foo<TestA *,TestB *><Bar>] [pointeekind=ObjCObject]
+// CHECK: VarDecl=e:21:9 [type=id<Bar>] [typekind=ObjCObjectPointer] [basetype=id] [basekind=ObjCId] [protocols=ObjCProtocolDecl=Bar:8:11 (Definition)] [isPOD=1] [pointeetype=id<Bar>] [pointeekind=ObjCObject]
diff --git a/test/Index/opencl-types.cl b/test/Index/opencl-types.cl
index d71893a22085..9eb680843ac7 100644
--- a/test/Index/opencl-types.cl
+++ b/test/Index/opencl-types.cl
@@ -21,7 +21,7 @@ void kernel testFloatTypes() {
// CHECK: VarDecl=scalarFloat:13:9 (Definition) [type=float] [typekind=Float] [isPOD=1]
// CHECK: VarDecl=vectorFloat:14:10 (Definition) [type=float4] [typekind=Typedef] [canonicaltype=float __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
// CHECK: VarDecl=scalarDouble:15:10 (Definition){{( \(invalid\))?}} [type=double] [typekind=Double] [isPOD=1]
-// CHECK: VarDecl=vectorDouble:16:11 (Definition) [type=double4] [typekind=Typedef] [canonicaltype=double __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
+// CHECK: VarDecl=vectorDouble:16:11 (Definition){{( \(invalid\))?}} [type=double4] [typekind=Typedef] [canonicaltype=double __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
@@ -124,3 +124,11 @@ void kernel testMiscOpenCLTypes() {
// CHECK: VarDecl=scalarOCLEvent:118:15 (Definition) [type=clk_event_t] [typekind=Typedef] [canonicaltype=clk_event_t] [canonicaltypekind=Unexposed] [isPOD=1]
// CHECK: VarDecl=scalarOCLQueue:119:11 (Definition) [type=queue_t] [typekind=Typedef] [canonicaltype=queue_t] [canonicaltypekind=OCLQueue] [isPOD=1]
// CHECK: VarDecl=scalarOCLReserveID:120:16 (Definition) [type=reserve_id_t] [typekind=Typedef] [canonicaltype=reserve_id_t] [canonicaltypekind=OCLReserveID] [isPOD=1]
+
+#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : enable
+
+void kernel testExtOpenCLTypes() {
+ intel_sub_group_avc_mce_payload_t mce_payload;
+}
+
+// CHECK: VarDecl=mce_payload:131:37 (Definition){{( \(invalid\))?}} [type=intel_sub_group_avc_mce_payload_t] [typekind=Typedef] [canonicaltype=intel_sub_group_avc_mce_payload_t] [canonicaltypekind=OCLIntelSubgroupAVCMcePayload] [isPOD=1]
diff --git a/test/Index/print-type.cpp b/test/Index/print-type.cpp
index e152a7ed3dd1..17bae2e9c307 100644
--- a/test/Index/print-type.cpp
+++ b/test/Index/print-type.cpp
@@ -75,6 +75,21 @@ template<typename T> struct A {};
template<typename T> using C = T;
using baz = C<A<void>>;
+auto autoTemplPointer = &autoTemplRefParam;
+
+outer::Foo<bool> parameter;
+outer::inner::Bar construct(&parameter);
+
+class X {
+ struct { int a; };
+ class { public: int b; };
+ union { int c; int d;};
+ enum { Test };
+};
+
+namespace {
+ int a;
+}
// RUN: c-index-test -test-print-type %s -std=c++14 | FileCheck %s
// CHECK: Namespace=outer:1:11 (Definition) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: ClassTemplate=Foo:4:8 (Definition) [type=] [typekind=Invalid] [isPOD=0]
@@ -182,3 +197,10 @@ using baz = C<A<void>>;
// CHECK: UnexposedExpr=templRefParam:71:40 [type=const Specialization<Specialization<bool> &>] [typekind=Unexposed] const [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=const Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
// CHECK: DeclRefExpr=templRefParam:71:40 [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
// CHECK: TypeAliasDecl=baz:76:7 (Definition) [type=baz] [typekind=Typedef] [templateargs/1= [type=A<void>] [typekind=Unexposed]] [canonicaltype=A<void>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=void] [typekind=Void]] [isPOD=0]
+// CHECK: VarDecl=autoTemplPointer:78:6 (Definition) [type=Specialization<Specialization<bool> &> *] [typekind=Auto] [canonicaltype=Specialization<Specialization<bool> &> *] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=Specialization<Specialization<bool> &>] [pointeekind=Record]
+// CHECK: CallExpr=Bar:17:3 [type=outer::inner::Bar] [typekind=Elaborated] [canonicaltype=outer::inner::Bar] [canonicaltypekind=Record] [args= [outer::Foo<bool> *] [Pointer]] [isPOD=0] [nbFields=3]
+// CHECK: StructDecl=:84:3 (Definition) [type=X::(anonymous struct at {{.*}}print-type.cpp:84:3)] [typekind=Record] [isPOD=1] [nbFields=1] [isAnon=1]
+// CHECK: ClassDecl=:85:3 (Definition) [type=X::(anonymous class at {{.*}}print-type.cpp:85:3)] [typekind=Record] [isPOD=1] [nbFields=1] [isAnon=1]
+// CHECK: UnionDecl=:86:3 (Definition) [type=X::(anonymous union at {{.*}}print-type.cpp:86:3)] [typekind=Record] [isPOD=1] [nbFields=2] [isAnon=1]
+// CHECK: EnumDecl=:87:3 (Definition) [type=X::(anonymous enum at {{.*}}print-type.cpp:87:3)] [typekind=Enum] [isPOD=1] [isAnon=1]
+// CHECK: Namespace=:90:11 (Definition) [type=] [typekind=Invalid] [isPOD=0] [isAnon=1]
diff --git a/test/Index/print-type.m b/test/Index/print-type.m
index 392399a573f1..2afdfc0ff842 100644
--- a/test/Index/print-type.m
+++ b/test/Index/print-type.m
@@ -7,6 +7,10 @@
@property (class) int classProp;
@end
+@interface Bar<SomeType> : Foo
+-(SomeType)generic;
+@end
+
// RUN: c-index-test -test-print-type %s | FileCheck %s
// CHECK: ObjCPropertyDecl=x:2:25 [readonly,] [type=id] [typekind=ObjCId] [canonicaltype=id] [canonicaltypekind=ObjCObjectPointer] [isPOD=1]
// CHECK: ObjCInstanceMethodDecl=mymethod:3:8 [type=] [typekind=Invalid] [resulttype=int] [resulttypekind=Int] [isPOD=0]
@@ -15,5 +19,6 @@
// CHECK: ObjCInstanceMethodDecl=methodIn:andOut::5:10 (variadic) [Bycopy,] [type=] [typekind=Invalid] [resulttype=id] [resulttypekind=ObjCId] [args= [int] [Int] [short *] [Pointer]] [isPOD=0]
// CHECK: ParmDecl=i:5:27 (Definition) [In,] [type=int] [typekind=Int] [isPOD=1]
// CHECK: ParmDecl=j:5:49 (Definition) [Out,] [type=short *] [typekind=Pointer] [isPOD=1] [pointeetype=short] [pointeekind=Short]
-// CHECK: ParmDecl=p:6:36 (Definition) [type=__kindof Foo *] [typekind=ObjCObjectPointer] [canonicaltype=__kindof Foo *] [canonicaltypekind=ObjCObjectPointer] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface]
+// CHECK: ParmDecl=p:6:36 (Definition) [type=__kindof Foo *] [typekind=ObjCObjectPointer] [canonicaltype=__kindof Foo *] [canonicaltypekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface]
// CHECK: ObjCPropertyDecl=classProp:7:23 [class,] [type=int] [typekind=Int] [isPOD=1]
+// CHECK: ObjCInstanceMethodDecl=generic:11:12 [type=] [typekind=Invalid] [resulttype=SomeType] [resulttypekind=ObjCTypeParam] [isPOD=0]
diff --git a/test/Index/property-getter-setter.m b/test/Index/property-getter-setter.m
new file mode 100644
index 000000000000..d77775ac149f
--- /dev/null
+++ b/test/Index/property-getter-setter.m
@@ -0,0 +1,10 @@
+@interface Foo
+@property (assign,readwrite,getter=b,setter=c:) id a;
+@property (assign,readonly,getter=e) id d;
+@property (assign,readwrite) id f;
+@end
+
+// RUN: c-index-test -test-print-type-declaration %s | FileCheck %s
+// CHECK: ObjCPropertyDecl=a:2:52 [getter,assign,readwrite,setter,] (getter=b) (setter=c:) [typedeclaration=id] [typekind=ObjCId]
+// CHECK: ObjCPropertyDecl=d:3:41 [readonly,getter,assign,] (getter=e) [typedeclaration=id] [typekind=ObjCId]
+// CHECK: ObjCPropertyDecl=f:4:33 [assign,readwrite,] [typedeclaration=id] [typekind=ObjCId]
diff --git a/test/Index/skipped-bodies-unused.cpp b/test/Index/skipped-bodies-unused.cpp
new file mode 100644
index 000000000000..fc1ebc8efd83
--- /dev/null
+++ b/test/Index/skipped-bodies-unused.cpp
@@ -0,0 +1,8 @@
+// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s -Wunused-parameter 2>&1 \
+// RUN: | FileCheck %s
+
+// No 'unused parameter' warnings should be shown when skipping the function bodies.
+inline int foo(int used, int unused) {
+ used = 100;
+}
+// CHECK-NOT: warning: unused parameter
diff --git a/test/Lexer/aligned-allocation.cpp b/test/Lexer/aligned-allocation.cpp
new file mode 100644
index 000000000000..eef5d980a37b
--- /dev/null
+++ b/test/Lexer/aligned-allocation.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \
+// RUN: -DEXPECT_DEFINED
+//
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \
+// RUN: -faligned-alloc-unavailable
+//
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \
+// RUN: -faligned-allocation -faligned-alloc-unavailable
+
+// Test that __cpp_aligned_new is not defined when CC1 is passed
+// -faligned-alloc-unavailable by the Darwin driver, even when aligned
+// allocation is actually enabled.
+
+// expected-no-diagnostics
+#ifdef EXPECT_DEFINED
+# ifndef __cpp_aligned_new
+# error "__cpp_aligned_new" should be defined
+# endif
+#else
+# ifdef __cpp_aligned_new
+# error "__cpp_aligned_new" should not be defined
+# endif
+#endif
diff --git a/test/Lexer/cross-windows-on-linux.cpp b/test/Lexer/cross-windows-on-linux.cpp
index 810e1d6ea966..c6dcbca54056 100644
--- a/test/Lexer/cross-windows-on-linux.cpp
+++ b/test/Lexer/cross-windows-on-linux.cpp
@@ -8,7 +8,7 @@
// expected to fail on windows as the inclusion would succeed and the
// compilation will fail due to the '#error success'.
-// XFAIL: win32
+// XFAIL: windows-msvc
// This test may or may not fail since 'Inputs\success.h' is passed
// to Win32 APIs on Windows.
diff --git a/test/Lexer/cxx-features.cpp b/test/Lexer/cxx-features.cpp
index 772fa26e96fc..09b82b7c47ef 100644
--- a/test/Lexer/cxx-features.cpp
+++ b/test/Lexer/cxx-features.cpp
@@ -9,53 +9,68 @@
// RUN: %clang_cc1 -fno-rtti -fno-threadsafe-statics -verify %s -DNO_EXCEPTIONS -DNO_RTTI -DNO_THREADSAFE_STATICS -fsized-deallocation
// RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify -fsized-deallocation %s
// RUN: %clang_cc1 -fchar8_t -DNO_EXCEPTIONS -DCHAR8_T -verify -fsized-deallocation %s
+// RUN: %clang_cc1 -std=c++2a -fno-char8_t -DNO_EXCEPTIONS -DNO_CHAR8_T -verify -fsized-deallocation %s
// expected-no-diagnostics
// FIXME using `defined` in a macro has undefined behavior.
#if __cplusplus < 201103L
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98)
#elif __cplusplus < 201402L
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
-#elif __cplusplus < 201406L
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11)
+#elif __cplusplus < 201703L
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14)
+#elif __cplusplus <= 201703L
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx17 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx17)
#else
-#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx17 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx17
+#define check(macro, cxx98, cxx11, cxx14, cxx17, cxx20) (cxx20 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx20)
+#endif
+
+// --- C++20 features ---
+
+#if defined(CHAR8_T) ? check(char8_t, 201811, 201811, 201811, 201811, 201811) : \
+ defined(NO_CHAR8_T) ? check(char8_t, 0, 0, 0, 0, 0) : \
+ check(char8_t, 0, 0, 0, 0, 201811)
+#error "wrong value for __cpp_char8_t"
+#endif
+
+#if check(impl_destroying_delete, 201806, 201806, 201806, 201806, 201806)
+#error "wrong value for __cpp_impl_destroying_delete"
#endif
// --- C++17 features ---
-#if check(hex_float, 0, 0, 0, 201603)
+#if check(hex_float, 0, 0, 0, 201603, 201603)
#error "wrong value for __cpp_hex_float"
#endif
-#if check(inline_variables, 0, 0, 0, 201606)
+#if check(inline_variables, 0, 0, 0, 201606, 201606)
#error "wrong value for __cpp_inline_variables"
#endif
-#if check(aligned_new, 0, 0, 0, 201606)
+#if check(aligned_new, 0, 0, 0, 201606, 201606)
#error "wrong value for __cpp_aligned_new"
#endif
-#if check(guaranteed_copy_elision, 0, 0, 0, 201606)
+#if check(guaranteed_copy_elision, 0, 0, 0, 201606, 201606)
#error "wrong value for __cpp_guaranteed_copy_elision"
#endif
-#if check(noexcept_function_type, 0, 0, 0, 201510)
+#if check(noexcept_function_type, 0, 0, 0, 201510, 201510)
#error "wrong value for __cpp_noexcept_function_type"
#endif
-#if check(fold_expressions, 0, 0, 0, 201603)
+#if check(fold_expressions, 0, 0, 0, 201603, 201603)
#error "wrong value for __cpp_fold_expressions"
#endif
-#if check(capture_star_this, 0, 0, 0, 201603)
+#if check(capture_star_this, 0, 0, 0, 201603, 201603)
#error "wrong value for __cpp_capture_star_this"
#endif
// constexpr checked below
-#if check(if_constexpr, 0, 0, 0, 201606)
+#if check(if_constexpr, 0, 0, 0, 201606, 201606)
#error "wrong value for __cpp_if_constexpr"
#endif
@@ -63,204 +78,199 @@
// static_assert checked below
-#if check(deduction_guides, 0, 0, 0, 201703)
+#if check(deduction_guides, 0, 0, 0, 201703, 201703)
#error "wrong value for __cpp_deduction_guides"
#endif
-#if check(nontype_template_parameter_auto, 0, 0, 0, 201606)
+#if check(nontype_template_parameter_auto, 0, 0, 0, 201606, 201606)
#error "wrong value for __cpp_nontype_template_parameter_auto"
#endif
// This is the old name (from P0096R4) for
// __cpp_nontype_template_parameter_auto
-#if check(template_auto, 0, 0, 0, 201606)
+#if check(template_auto, 0, 0, 0, 201606, 201606)
#error "wrong value for __cpp_template_auto"
#endif
-#if check(namespace_attributes, 0, 0, 0, 201411)
+#if check(namespace_attributes, 0, 0, 0, 201411, 201411)
// FIXME: allowed without warning in C++14 and C++11
#error "wrong value for __cpp_namespace_attributes"
#endif
-#if check(enumerator_attributes, 0, 0, 0, 201411)
+#if check(enumerator_attributes, 0, 0, 0, 201411, 201411)
// FIXME: allowed without warning in C++14 and C++11
#error "wrong value for __cpp_enumerator_attributes"
#endif
// This is an old name (from P0096R4), now removed from SD-6.
-#if check(nested_namespace_definitions, 0, 0, 0, 201411)
+#if check(nested_namespace_definitions, 0, 0, 0, 201411, 201411)
#error "wrong value for __cpp_nested_namespace_definitions"
#endif
// inheriting_constructors checked below
-#if check(variadic_using, 0, 0, 0, 201611)
+#if check(variadic_using, 0, 0, 0, 201611, 201611)
#error "wrong value for __cpp_variadic_using"
#endif
-#if check(aggregate_bases, 0, 0, 0, 201603)
+#if check(aggregate_bases, 0, 0, 0, 201603, 201603)
#error "wrong value for __cpp_aggregate_bases"
#endif
-#if check(structured_bindings, 0, 0, 0, 201606)
+#if check(structured_bindings, 0, 0, 0, 201606, 201606)
#error "wrong value for __cpp_structured_bindings"
#endif
-#if check(nontype_template_args, 0, 0, 0, 201411)
+#if check(nontype_template_args, 0, 0, 0, 201411, 201411)
#error "wrong value for __cpp_nontype_template_args"
#endif
#if defined(RELAXED_TEMPLATE_TEMPLATE_ARGS) \
- ? check(template_template_args, 0, 0, 0, 201611) \
- : check(template_template_args, 0, 0, 0, 0)
+ ? check(template_template_args, 0, 0, 0, 201611, 201611) \
+ : check(template_template_args, 0, 0, 0, 0, 0)
#error "wrong value for __cpp_template_template_args"
#endif
// --- C++14 features ---
-#if check(binary_literals, 0, 0, 201304, 201304)
+#if check(binary_literals, 0, 0, 201304, 201304, 201304)
#error "wrong value for __cpp_binary_literals"
#endif
// (Removed from SD-6.)
-#if check(digit_separators, 0, 0, 201309, 201309)
+#if check(digit_separators, 0, 0, 201309, 201309, 201309)
#error "wrong value for __cpp_digit_separators"
#endif
-#if check(init_captures, 0, 0, 201304, 201304)
+#if check(init_captures, 0, 0, 201304, 201304, 201304)
#error "wrong value for __cpp_init_captures"
#endif
-#if check(generic_lambdas, 0, 0, 201304, 201304)
+#if check(generic_lambdas, 0, 0, 201304, 201304, 201304)
#error "wrong value for __cpp_generic_lambdas"
#endif
-#if check(sized_deallocation, 0, 0, 201309, 201309)
+#if check(sized_deallocation, 0, 0, 201309, 201309, 201309)
#error "wrong value for __cpp_sized_deallocation"
#endif
// constexpr checked below
-#if check(decltype_auto, 0, 0, 201304, 201304)
+#if check(decltype_auto, 0, 0, 201304, 201304, 201304)
#error "wrong value for __cpp_decltype_auto"
#endif
-#if check(return_type_deduction, 0, 0, 201304, 201304)
+#if check(return_type_deduction, 0, 0, 201304, 201304, 201304)
#error "wrong value for __cpp_return_type_deduction"
#endif
-#if check(runtime_arrays, 0, 0, 0, 0)
+#if check(runtime_arrays, 0, 0, 0, 0, 0)
#error "wrong value for __cpp_runtime_arrays"
#endif
-#if check(aggregate_nsdmi, 0, 0, 201304, 201304)
+#if check(aggregate_nsdmi, 0, 0, 201304, 201304, 201304)
#error "wrong value for __cpp_aggregate_nsdmi"
#endif
-#if check(variable_templates, 0, 0, 201304, 201304)
+#if check(variable_templates, 0, 0, 201304, 201304, 201304)
#error "wrong value for __cpp_variable_templates"
#endif
// --- C++11 features ---
-#if check(unicode_characters, 0, 200704, 200704, 200704)
+#if check(unicode_characters, 0, 200704, 200704, 200704, 200704)
#error "wrong value for __cpp_unicode_characters"
#endif
-#if check(raw_strings, 0, 200710, 200710, 200710)
+#if check(raw_strings, 0, 200710, 200710, 200710, 200710)
#error "wrong value for __cpp_raw_strings"
#endif
-#if check(unicode_literals, 0, 200710, 200710, 200710)
+#if check(unicode_literals, 0, 200710, 200710, 200710, 200710)
#error "wrong value for __cpp_unicode_literals"
#endif
-#if check(user_defined_literals, 0, 200809, 200809, 200809)
+#if check(user_defined_literals, 0, 200809, 200809, 200809, 200809)
#error "wrong value for __cpp_user_defined_literals"
#endif
-#if defined(NO_THREADSAFE_STATICS) ? check(threadsafe_static_init, 0, 0, 0, 0) : check(threadsafe_static_init, 200806, 200806, 200806, 200806)
+#if defined(NO_THREADSAFE_STATICS) ? check(threadsafe_static_init, 0, 0, 0, 0, 0) : \
+ check(threadsafe_static_init, 200806, 200806, 200806, 200806, 200806)
#error "wrong value for __cpp_threadsafe_static_init"
#endif
-#if check(lambdas, 0, 200907, 200907, 200907)
+#if check(lambdas, 0, 200907, 200907, 200907, 200907)
#error "wrong value for __cpp_lambdas"
#endif
-#if check(constexpr, 0, 200704, 201304, 201603)
+#if check(constexpr, 0, 200704, 201304, 201603, 201603)
#error "wrong value for __cpp_constexpr"
#endif
-#if check(range_based_for, 0, 200907, 200907, 201603)
+#if check(range_based_for, 0, 200907, 200907, 201603, 201603)
#error "wrong value for __cpp_range_based_for"
#endif
-#if check(static_assert, 0, 200410, 200410, 201411)
+#if check(static_assert, 0, 200410, 200410, 201411, 201411)
#error "wrong value for __cpp_static_assert"
#endif
-#if check(decltype, 0, 200707, 200707, 200707)
+#if check(decltype, 0, 200707, 200707, 200707, 200707)
#error "wrong value for __cpp_decltype"
#endif
-#if check(attributes, 0, 200809, 200809, 200809)
+#if check(attributes, 0, 200809, 200809, 200809, 200809)
#error "wrong value for __cpp_attributes"
#endif
-#if check(rvalue_references, 0, 200610, 200610, 200610)
+#if check(rvalue_references, 0, 200610, 200610, 200610, 200610)
#error "wrong value for __cpp_rvalue_references"
#endif
-#if check(variadic_templates, 0, 200704, 200704, 200704)
+#if check(variadic_templates, 0, 200704, 200704, 200704, 200704)
#error "wrong value for __cpp_variadic_templates"
#endif
-#if check(initializer_lists, 0, 200806, 200806, 200806)
+#if check(initializer_lists, 0, 200806, 200806, 200806, 200806)
#error "wrong value for __cpp_initializer_lists"
#endif
-#if check(delegating_constructors, 0, 200604, 200604, 200604)
+#if check(delegating_constructors, 0, 200604, 200604, 200604, 200604)
#error "wrong value for __cpp_delegating_constructors"
#endif
-#if check(nsdmi, 0, 200809, 200809, 200809)
+#if check(nsdmi, 0, 200809, 200809, 200809, 200809)
#error "wrong value for __cpp_nsdmi"
#endif
-#if check(inheriting_constructors, 0, 201511, 201511, 201511)
+#if check(inheriting_constructors, 0, 201511, 201511, 201511, 201511)
#error "wrong value for __cpp_inheriting_constructors"
#endif
-#if check(ref_qualifiers, 0, 200710, 200710, 200710)
+#if check(ref_qualifiers, 0, 200710, 200710, 200710, 200710)
#error "wrong value for __cpp_ref_qualifiers"
#endif
-#if check(alias_templates, 0, 200704, 200704, 200704)
+#if check(alias_templates, 0, 200704, 200704, 200704, 200704)
#error "wrong value for __cpp_alias_templates"
#endif
// --- C++98 features ---
-#if defined(NO_RTTI) ? check(rtti, 0, 0, 0, 0) : check(rtti, 199711, 199711, 199711, 199711)
+#if defined(NO_RTTI) ? check(rtti, 0, 0, 0, 0, 0) : check(rtti, 199711, 199711, 199711, 199711, 199711)
#error "wrong value for __cpp_rtti"
#endif
-#if defined(NO_EXCEPTIONS) ? check(exceptions, 0, 0, 0, 0) : check(exceptions, 199711, 199711, 199711, 199711)
+#if defined(NO_EXCEPTIONS) ? check(exceptions, 0, 0, 0, 0, 0) : check(exceptions, 199711, 199711, 199711, 199711, 199711)
#error "wrong value for __cpp_exceptions"
#endif
// --- TS features --
-#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS)
+#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS, CONCEPTS_TS)
#error "wrong value for __cpp_experimental_concepts"
#endif
-#if defined(COROUTINES) ? check(coroutines, 201703L, 201703L, 201703L, 201703L) : check(coroutines, 0, 0, 0, 0)
+#if defined(COROUTINES) ? check(coroutines, 201703L, 201703L, 201703L, 201703L, 201703L) : check(coroutines, 0, 0, 0, 0, 0)
#error "wrong value for __cpp_coroutines"
#endif
-
-// --- not-yet-standard features --
-
-#if defined(CHAR8_T) ? check(char8_t, 201803, 201803, 201803, 201803) : check(char8_t, 0, 0, 0, 0)
-#error "wrong value for __cpp_char8_t"
-#endif
diff --git a/test/Lexer/has_feature_memory_sanitizer.cpp b/test/Lexer/has_feature_memory_sanitizer.cpp
index 3ebb9e13682a..ca9a39cccdae 100644
--- a/test/Lexer/has_feature_memory_sanitizer.cpp
+++ b/test/Lexer/has_feature_memory_sanitizer.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -E -fsanitize=memory %s -o - | FileCheck --check-prefix=CHECK-MSAN %s
+// RUN: %clang_cc1 -E -fsanitize=kernel-memory %s -o - | FileCheck --check-prefix=CHECK-MSAN %s
// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-MSAN %s
#if __has_feature(memory_sanitizer)
diff --git a/test/Lexer/has_feature_undefined_behavior_sanitizer.cpp b/test/Lexer/has_feature_undefined_behavior_sanitizer.cpp
new file mode 100644
index 000000000000..62e5316dde58
--- /dev/null
+++ b/test/Lexer/has_feature_undefined_behavior_sanitizer.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang -E -fsanitize=undefined %s -o - | FileCheck --check-prefix=CHECK-UBSAN %s
+// RUN: %clang -E -fsanitize=alignment %s -o - | FileCheck --check-prefix=CHECK-ALIGNMENT %s
+// RUN: %clang -E %s -o - | FileCheck --check-prefix=CHECK-NO-UBSAN %s
+
+#if __has_feature(undefined_behavior_sanitizer)
+int UBSanEnabled();
+#else
+int UBSanDisabled();
+#endif
+
+// CHECK-UBSAN: UBSanEnabled
+// CHECK-ALIGNMENT: UBSanEnabled
+// CHECK-NO-UBSAN: UBSanDisabled
diff --git a/test/Lexer/has_feature_xray_instrument.cpp b/test/Lexer/has_feature_xray_instrument.cpp
new file mode 100644
index 000000000000..cd2750d77f9b
--- /dev/null
+++ b/test/Lexer/has_feature_xray_instrument.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -E -fxray-instrument %s -o - | FileCheck --check-prefix=CHECK-XRAY %s
+// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-XRAY %s
+
+#if __has_feature(xray_instrument)
+int XRayInstrumentEnabled();
+#else
+int XRayInstrumentDisabled();
+#endif
+
+// CHECK-XRAY: XRayInstrumentEnabled
+// CHECK-NO-XRAY: XRayInstrumentDisabled
diff --git a/test/Lexer/unicode.c b/test/Lexer/unicode.c
index 30e353fa797e..01285fbc2138 100644
--- a/test/Lexer/unicode.c
+++ b/test/Lexer/unicode.c
@@ -38,3 +38,15 @@ int n; = 3; // expected-warning {{treating Unicode character <U+037E> as identi
int *n꞉꞉v = &n;; // expected-warning 2{{treating Unicode character <U+A789> as identifier character rather than as ':' symbol}}
// expected-warning@-1 {{treating Unicode character <U+037E> as identifier character rather than as ';' symbol}}
int v=[=](auto){return~x;}(); // expected-warning 12{{treating Unicode character}}
+
+int ⁠xx‍;
+// expected-warning@-1 {{identifier contains Unicode character <U+2060> that is invisible in some environments}}
+// expected-warning@-2 {{identifier contains Unicode character <U+FEFF> that is invisible in some environments}}
+// expected-warning@-3 {{identifier contains Unicode character <U+200D> that is invisible in some environments}}
+int foo​bar = 0; // expected-warning {{identifier contains Unicode character <U+200B> that is invisible in some environments}}
+int x = foobar; // expected-error {{undeclared identifier}}
+
+int ∣foo; // expected-error {{non-ASCII character}}
+#ifndef PP_ONLY
+#define ∶ x // expected-error {{macro name must be an identifier}}
+#endif
diff --git a/test/Misc/ast-dump-stmt.c b/test/Misc/ast-dump-stmt.c
deleted file mode 100644
index 461893188a16..000000000000
--- a/test/Misc/ast-dump-stmt.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// RUN: %clang_cc1 -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s
-
-int TestLocation = 0;
-// CHECK: VarDecl{{.*}}TestLocation
-// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:20> 'int' 0
-
-int TestIndent = 1 + (1);
-// CHECK: VarDecl{{.*}}TestIndent
-// CHECK-NEXT: {{^}}`-BinaryOperator{{[^()]*$}}
-// CHECK-NEXT: {{^}} |-IntegerLiteral{{.*0[^()]*$}}
-// CHECK-NEXT: {{^}} `-ParenExpr{{.*0[^()]*$}}
-// CHECK-NEXT: {{^}} `-IntegerLiteral{{.*0[^()]*$}}
-
-void TestDeclStmt() {
- int x = 0;
- int y, z;
-}
-// CHECK: FunctionDecl{{.*}}TestDeclStmt
-// CHECK-NEXT: CompoundStmt
-// CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl{{.*}}x
-// CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl{{.*}}y
-// CHECK-NEXT: VarDecl{{.*}}z
-
-int TestOpaqueValueExpr = 0 ?: 1;
-// CHECK: VarDecl{{.*}}TestOpaqueValueExpr
-// CHECK-NEXT: BinaryConditionalOperator
-// CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: OpaqueValueExpr
-// CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: OpaqueValueExpr
-// CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: IntegerLiteral
-
-void TestUnaryOperatorExpr(void) {
- char T1 = 1;
- int T2 = 1;
-
- T1++;
- T2++;
- // CHECK: UnaryOperator{{.*}}postfix '++' cannot overflow
- // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
- // CHECK-NOT: UnaryOperator{{.*}}postfix '++' cannot overflow
- // CHECK: DeclRefExpr{{.*}}'T2' 'int'
-
- -T1;
- -T2;
- // CHECK: UnaryOperator{{.*}}prefix '-' cannot overflow
- // CHECK-NEXT: ImplicitCastExpr
- // CHECK-NEXT: ImplicitCastExpr
- // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
- // CHECK-NOT: UnaryOperator{{.*}}prefix '-' cannot overflow
- // CHECK: ImplicitCastExpr
- // CHECK: DeclRefExpr{{.*}}'T2' 'int'
-
- ~T1;
- ~T2;
- // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow
- // CHECK-NEXT: ImplicitCastExpr
- // CHECK-NEXT: ImplicitCastExpr
- // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char'
- // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow
- // CHECK-NEXT: ImplicitCastExpr
- // CHECK-NEXT: DeclRefExpr{{.*}}'T2' 'int'
-}
diff --git a/test/Misc/ast-dump-stmt.cpp b/test/Misc/ast-dump-stmt.cpp
deleted file mode 100644
index 55b9b5fa9531..000000000000
--- a/test/Misc/ast-dump-stmt.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// RUN: %clang_cc1 -fcxx-exceptions -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s
-
-namespace n {
-void function() {}
-int Variable;
-}
-using n::function;
-using n::Variable;
-void TestFunction() {
- void (*f)() = &function;
-// CHECK: DeclRefExpr{{.*}} (UsingShadow{{.*}}function
- Variable = 4;
-// CHECK: DeclRefExpr{{.*}} (UsingShadow{{.*}}Variable
-}
-
-// CHECK: FunctionDecl {{.*}} TestCatch1
-void TestCatch1() {
-// CHECK: CXXTryStmt
-// CHECK-NEXT: CompoundStmt
- try {
- }
-// CHECK-NEXT: CXXCatchStmt
-// CHECK-NEXT: VarDecl {{.*}} x
-// CHECK-NEXT: CompoundStmt
- catch (int x) {
- }
-}
-
-// CHECK: FunctionDecl {{.*}} TestCatch2
-void TestCatch2() {
-// CHECK: CXXTryStmt
-// CHECK-NEXT: CompoundStmt
- try {
- }
-// CHECK-NEXT: CXXCatchStmt
-// CHECK-NEXT: NULL
-// CHECK-NEXT: CompoundStmt
- catch (...) {
- }
-}
-
-void TestAllocationExprs() {
- int *p;
- p = new int;
- delete p;
- p = new int[2];
- delete[] p;
- p = ::new int;
- ::delete p;
-}
-// CHECK: FunctionDecl {{.*}} TestAllocationExprs
-// CHECK: CXXNewExpr {{.*}} 'int *' Function {{.*}} 'operator new'
-// CHECK: CXXDeleteExpr {{.*}} 'void' Function {{.*}} 'operator delete'
-// CHECK: CXXNewExpr {{.*}} 'int *' array Function {{.*}} 'operator new[]'
-// CHECK: CXXDeleteExpr {{.*}} 'void' array Function {{.*}} 'operator delete[]'
-// CHECK: CXXNewExpr {{.*}} 'int *' global Function {{.*}} 'operator new'
-// CHECK: CXXDeleteExpr {{.*}} 'void' global Function {{.*}} 'operator delete'
-
-// Don't crash on dependent exprs that haven't been resolved yet.
-template <typename T>
-void TestDependentAllocationExpr() {
- T *p = new T;
- delete p;
-}
-// CHECK: FunctionTemplateDecl {{.*}} TestDependentAllocationExpr
-// CHECK: CXXNewExpr {{.*'T \*'$}}
-// CHECK: CXXDeleteExpr {{.*'void'$}}
-
-template <typename T>
-class DependentScopeMemberExprWrapper {
- T member;
-};
-
-template <typename T>
-void TestDependentScopeMemberExpr() {
- DependentScopeMemberExprWrapper<T> obj;
- obj.member = T();
- (&obj)->member = T();
-}
-
-// CHECK: FunctionTemplateDecl {{.*}} TestDependentScopeMemberExpr
-// CHECK: CXXDependentScopeMemberExpr {{.*}} lvalue .member
-// CHECK: CXXDependentScopeMemberExpr {{.*}} lvalue ->member
diff --git a/test/Misc/backend-optimization-failure-nodbg.cpp b/test/Misc/backend-optimization-failure-nodbg.cpp
index aba37de231af..02b0889d0208 100644
--- a/test/Misc/backend-optimization-failure-nodbg.cpp
+++ b/test/Misc/backend-optimization-failure-nodbg.cpp
@@ -4,7 +4,7 @@
// Test verifies optimization failures generated by the backend are handled
// correctly by clang. LLVM tests verify all of the failure conditions.
-void test_switch(int *A, int *B, int Length, int J) { /* expected-warning {{loop not vectorized: failed explicitly specified loop vectorization}} */
+void test_switch(int *A, int *B, int Length, int J) { /* expected-warning {{loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering}} */
#pragma clang loop vectorize(enable) unroll(disable)
for (int i = 0; i < Length; i++) {
switch (A[i]) {
diff --git a/test/Misc/backend-optimization-failure.cpp b/test/Misc/backend-optimization-failure.cpp
index 1657c0cb91d5..18b0ccb74e8c 100644
--- a/test/Misc/backend-optimization-failure.cpp
+++ b/test/Misc/backend-optimization-failure.cpp
@@ -7,7 +7,7 @@
void test_switch(int *A, int *B, int Length,int J) {
#pragma clang loop vectorize(enable) unroll(disable)
for (int i = 0; i < Length; i++) {
-/* expected-warning@-1 {{loop not vectorized: failed explicitly specified loop vectorization}} */ switch (A[i]) {
+/* expected-warning@-1 {{loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering}} */ switch (A[i]) {
case 0:
B[i] = 1;
break;
diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test
index 4a3846be8d9b..9a6bcca1bd36 100644
--- a/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -2,54 +2,107 @@
// The number of supported attributes should never go down!
-// CHECK: #pragma clang attribute supports 72 attributes:
+// CHECK: #pragma clang attribute supports the following attributes:
// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUWavesPerEU (SubjectMatchRule_function)
// CHECK-NEXT: AVRSignal (SubjectMatchRule_function)
// CHECK-NEXT: AbiTag (SubjectMatchRule_record_not_is_union, SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_namespace)
+// CHECK-NEXT: Alias (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
// CHECK-NEXT: AlignValue (SubjectMatchRule_variable, SubjectMatchRule_type_alias)
// CHECK-NEXT: AllocSize (SubjectMatchRule_function)
+// CHECK-NEXT: AlwaysDestroy (SubjectMatchRule_variable)
+// CHECK-NEXT: AlwaysInline (SubjectMatchRule_function)
// CHECK-NEXT: Annotate ()
// CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType)
+// CHECK-NEXT: ArcWeakrefUnavailable (SubjectMatchRule_objc_interface)
// CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
+// CHECK-NEXT: CFAuditedTransfer (SubjectMatchRule_function)
+// CHECK-NEXT: CFConsumed (SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: CFUnknownTransfer (SubjectMatchRule_function)
// CHECK-NEXT: CPUDispatch (SubjectMatchRule_function)
// CHECK-NEXT: CPUSpecific (SubjectMatchRule_function)
+// CHECK-NEXT: CUDAConstant (SubjectMatchRule_variable)
+// CHECK-NEXT: CUDADevice (SubjectMatchRule_function, SubjectMatchRule_variable)
+// CHECK-NEXT: CUDAGlobal (SubjectMatchRule_function)
+// CHECK-NEXT: CUDAHost (SubjectMatchRule_function)
+// CHECK-NEXT: CUDALaunchBounds (SubjectMatchRule_objc_method, SubjectMatchRule_hasType_functionType)
+// CHECK-NEXT: CUDAShared (SubjectMatchRule_variable)
// CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function)
// CHECK-NEXT: CallableWhen (SubjectMatchRule_function_is_member)
+// CHECK-NEXT: Capability (SubjectMatchRule_record, SubjectMatchRule_type_alias)
// CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function)
+// CHECK-NEXT: Cold (SubjectMatchRule_function)
+// CHECK-NEXT: Common (SubjectMatchRule_variable)
+// CHECK-NEXT: Constructor (SubjectMatchRule_function)
// CHECK-NEXT: Consumable (SubjectMatchRule_record)
+// CHECK-NEXT: ConsumableAutoCast (SubjectMatchRule_record)
+// CHECK-NEXT: ConsumableSetOnRead (SubjectMatchRule_record)
// CHECK-NEXT: Convergent (SubjectMatchRule_function)
// CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface)
// CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface)
+// CHECK-NEXT: Destructor (SubjectMatchRule_function)
// CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: EnableIf (SubjectMatchRule_function)
// CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum)
+// CHECK-NEXT: ExcludeFromExplicitInstantiation (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
// CHECK-NEXT: ExternalSourceSymbol ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
// CHECK-NEXT: FlagEnum (SubjectMatchRule_enum)
// CHECK-NEXT: Flatten (SubjectMatchRule_function)
+// CHECK-NEXT: GNUInline (SubjectMatchRule_function)
+// CHECK-NEXT: Hot (SubjectMatchRule_function)
+// CHECK-NEXT: IBAction (SubjectMatchRule_objc_method_is_instance)
// CHECK-NEXT: IFunc (SubjectMatchRule_function)
+// CHECK-NEXT: InitPriority (SubjectMatchRule_variable)
// CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
// CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record)
+// CHECK-NEXT: Lockable (SubjectMatchRule_record)
+// CHECK-NEXT: MSStruct (SubjectMatchRule_record)
// CHECK-NEXT: MicroMips (SubjectMatchRule_function)
+// CHECK-NEXT: MinSize (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: MinVectorWidth (SubjectMatchRule_function)
+// CHECK-NEXT: Mips16 (SubjectMatchRule_function)
// CHECK-NEXT: MipsLongCall (SubjectMatchRule_function)
// CHECK-NEXT: MipsShortCall (SubjectMatchRule_function)
+// CHECK-NEXT: NSConsumed (SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: NSConsumesSelf (SubjectMatchRule_objc_method)
+// CHECK-NEXT: Naked (SubjectMatchRule_function)
+// CHECK-NEXT: NoCommon (SubjectMatchRule_variable)
// CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter)
+// CHECK-NEXT: NoDestroy (SubjectMatchRule_variable)
// CHECK-NEXT: NoDuplicate (SubjectMatchRule_function)
// CHECK-NEXT: NoEscape (SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: NoInline (SubjectMatchRule_function)
+// CHECK-NEXT: NoInstrumentFunction (SubjectMatchRule_function)
// CHECK-NEXT: NoMicroMips (SubjectMatchRule_function)
+// CHECK-NEXT: NoMips16 (SubjectMatchRule_function)
// CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
// CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
// CHECK-NEXT: NoSplitStack (SubjectMatchRule_function)
// CHECK-NEXT: NoStackProtector (SubjectMatchRule_function)
+// CHECK-NEXT: NoThreadSafetyAnalysis (SubjectMatchRule_function)
// CHECK-NEXT: NoThrow (SubjectMatchRule_function)
// CHECK-NEXT: NotTailCalled (SubjectMatchRule_function)
+// CHECK-NEXT: OSConsumed (SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: OSReturnsRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: OSReturnsRetainedOnNonZero (SubjectMatchRule_variable_is_parameter)
+// CHECK-NEXT: OSReturnsRetainedOnZero (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: ObjCBoxable (SubjectMatchRule_record)
+// CHECK-NEXT: ObjCBridge (SubjectMatchRule_record, SubjectMatchRule_type_alias)
+// CHECK-NEXT: ObjCBridgeMutable (SubjectMatchRule_record)
+// CHECK-NEXT: ObjCBridgeRelated (SubjectMatchRule_record)
+// CHECK-NEXT: ObjCException (SubjectMatchRule_objc_interface)
+// CHECK-NEXT: ObjCExplicitProtocolImpl (SubjectMatchRule_objc_protocol)
+// CHECK-NEXT: ObjCExternallyRetained (SubjectMatchRule_variable_not_is_parameter, SubjectMatchRule_function, SubjectMatchRule_block, SubjectMatchRule_objc_method)
// CHECK-NEXT: ObjCMethodFamily (SubjectMatchRule_objc_method)
+// CHECK-NEXT: ObjCPreciseLifetime (SubjectMatchRule_variable)
+// CHECK-NEXT: ObjCRequiresPropertyDefs (SubjectMatchRule_objc_interface)
// CHECK-NEXT: ObjCRequiresSuper (SubjectMatchRule_objc_method)
+// CHECK-NEXT: ObjCReturnsInnerPointer (SubjectMatchRule_objc_method, SubjectMatchRule_objc_property)
+// CHECK-NEXT: ObjCRootClass (SubjectMatchRule_objc_interface)
// CHECK-NEXT: ObjCRuntimeName (SubjectMatchRule_objc_interface, SubjectMatchRule_objc_protocol)
// CHECK-NEXT: ObjCRuntimeVisible (SubjectMatchRule_objc_interface)
// CHECK-NEXT: ObjCSubclassingRestricted (SubjectMatchRule_objc_interface)
@@ -60,11 +113,16 @@
// CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function)
+// CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function)
// CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global)
+// CHECK-NEXT: Restrict (SubjectMatchRule_function)
// CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function)
+// CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function)
+// CHECK-NEXT: ScopedLockable (SubjectMatchRule_record)
// CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property)
// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member)
+// CHECK-NEXT: SpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: SwiftContext (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter)
@@ -72,6 +130,13 @@
// CHECK-NEXT: Target (SubjectMatchRule_function)
// CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member)
// CHECK-NEXT: TrivialABI (SubjectMatchRule_record)
+// CHECK-NEXT: VecReturn (SubjectMatchRule_record)
+// CHECK-NEXT: VecTypeHint (SubjectMatchRule_function)
+// CHECK-NEXT: WarnUnused (SubjectMatchRule_record)
// CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType)
+// CHECK-NEXT: Weak (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
+// CHECK-NEXT: WeakRef (SubjectMatchRule_variable, SubjectMatchRule_function)
+// CHECK-NEXT: WorkGroupSizeHint (SubjectMatchRule_function)
// CHECK-NEXT: XRayInstrument (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: XRayLogArgs (SubjectMatchRule_function, SubjectMatchRule_objc_method)
+// CHECK-NEXT: End of supported attributes.
diff --git a/test/Misc/target-invalid-cpu-note.c b/test/Misc/target-invalid-cpu-note.c
index f2b36d44b9f4..babfaa9ffcb4 100644
--- a/test/Misc/target-invalid-cpu-note.c
+++ b/test/Misc/target-invalid-cpu-note.c
@@ -16,7 +16,7 @@
// X86-SAME: nocona, core2, penryn, bonnell, atom, silvermont, slm, goldmont, goldmont-plus, tremont,
// X86-SAME: nehalem, corei7, westmere, sandybridge, corei7-avx, ivybridge,
// X86-SAME: core-avx-i, haswell, core-avx2, broadwell, skylake, skylake-avx512,
-// X86-SAME: skx, cannonlake, icelake-client, icelake-server, knl, knm, lakemont, k6, k6-2, k6-3,
+// X86-SAME: skx, cascadelake, cannonlake, icelake-client, icelake-server, knl, knm, lakemont, k6, k6-2, k6-3,
// X86-SAME: athlon, athlon-tbird, athlon-xp, athlon-mp, athlon-4, k8, athlon64,
// X86-SAME: athlon-fx, opteron, k8-sse3, athlon64-sse3, opteron-sse3, amdfam10,
// X86-SAME: barcelona, btver1, btver2, bdver1, bdver2, bdver3, bdver4, znver1,
@@ -27,7 +27,7 @@
// X86_64: note: valid target CPU values are: nocona, core2, penryn, bonnell,
// X86_64-SAME: atom, silvermont, slm, goldmont, goldmont-plus, tremont, nehalem, corei7, westmere,
// X86_64-SAME: sandybridge, corei7-avx, ivybridge, core-avx-i, haswell,
-// X86_64-SAME: core-avx2, broadwell, skylake, skylake-avx512, skx, cannonlake,
+// X86_64-SAME: core-avx2, broadwell, skylake, skylake-avx512, skx, cascadelake, cannonlake,
// X86_64-SAME: icelake-client, icelake-server, knl, knm, k8, athlon64, athlon-fx, opteron, k8-sse3,
// X86_64-SAME: athlon64-sse3, opteron-sse3, amdfam10, barcelona, btver1,
// X86_64-SAME: btver2, bdver1, bdver2, bdver3, bdver4, znver1, x86-64
@@ -84,10 +84,6 @@
// PPC-SAME: pwr7, power8, pwr8, power9, pwr9, powerpc, ppc, powerpc64, ppc64,
// PPC-SAME: powerpc64le, ppc64le
-// RUN: not %clang_cc1 -triple nios2--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix NIOS
-// NIOS: error: unknown target CPU 'not-a-cpu'
-// NIOS: note: valid target CPU values are: nios2r1, nios2r2
-
// RUN: not %clang_cc1 -triple mips--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix MIPS
// MIPS: error: unknown target CPU 'not-a-cpu'
// MIPS: note: valid target CPU values are: mips1, mips2, mips3, mips4, mips5,
@@ -100,7 +96,7 @@
// RUN: not %clang_cc1 -triple hexagon--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix HEXAGON
// HEXAGON: error: unknown target CPU 'not-a-cpu'
-// HEXAGON: note: valid target CPU values are: hexagonv4, hexagonv5, hexagonv55,
+// HEXAGON: note: valid target CPU values are: hexagonv5, hexagonv55,
// HEXAGON-SAME: hexagonv60, hexagonv62, hexagonv65
// RUN: not %clang_cc1 -triple bpf--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix BPF
diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c
index 4f9469f8e582..05172b220859 100644
--- a/test/Misc/warning-flags.c
+++ b/test/Misc/warning-flags.c
@@ -18,7 +18,7 @@ This test serves two purposes:
The list of warnings below should NEVER grow. It should gradually shrink to 0.
-CHECK: Warnings without flags (76):
+CHECK: Warnings without flags (74):
CHECK-NEXT: ext_excess_initializers
CHECK-NEXT: ext_excess_initializers_in_char_array_initializer
CHECK-NEXT: ext_expected_semi_decl_list
@@ -29,7 +29,6 @@ CHECK-NEXT: ext_missing_whitespace_after_macro_name
CHECK-NEXT: ext_new_paren_array_nonconst
CHECK-NEXT: ext_plain_complex
CHECK-NEXT: ext_template_arg_extra_parens
-CHECK-NEXT: ext_typecheck_comparison_of_pointer_integer
CHECK-NEXT: ext_typecheck_cond_incompatible_operands
CHECK-NEXT: ext_typecheck_ordered_comparison_of_pointer_integer
CHECK-NEXT: ext_using_undefined_std
@@ -40,7 +39,6 @@ CHECK-NEXT: warn_accessor_property_type_mismatch
CHECK-NEXT: warn_arcmt_nsalloc_realloc
CHECK-NEXT: warn_asm_label_on_auto_decl
CHECK-NEXT: warn_c_kext
-CHECK-NEXT: warn_call_to_pure_virtual_member_function_from_ctor_dtor
CHECK-NEXT: warn_call_wrong_number_of_arguments
CHECK-NEXT: warn_case_empty_range
CHECK-NEXT: warn_char_constant_too_large
diff --git a/test/Modules/ExtDebugInfo.cpp b/test/Modules/ExtDebugInfo.cpp
index c57f1f034eb2..592612b9a5db 100644
--- a/test/Modules/ExtDebugInfo.cpp
+++ b/test/Modules/ExtDebugInfo.cpp
@@ -83,11 +83,11 @@ void foo() {
// CHECK: ![[NS]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]])
// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX
-// This type is anchored in the module by an explicit template instantiation.
+// This type is not anchored in the module by an explicit template instantiation.
// CHECK: !DICompositeType(tag: DW_TAG_class_type,
// CHECK-SAME: name: "Template<long, DebugCXX::traits<long> >",
// CHECK-SAME: scope: ![[NS]],
-// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: elements:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE")
// This type is anchored in the module by an explicit template instantiation.
diff --git a/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h
new file mode 100644
index 000000000000..96212a03a113
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h
@@ -0,0 +1 @@
+#include "Thing2.h"
diff --git a/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h
new file mode 100644
index 000000000000..7d1fe26edb09
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h
@@ -0,0 +1 @@
+// Empty file!
diff --git a/test/Modules/Inputs/lsv-debuginfo/A/ADT.h b/test/Modules/Inputs/lsv-debuginfo/A/ADT.h
new file mode 100644
index 000000000000..f48d4f7820a8
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/A/ADT.h
@@ -0,0 +1,45 @@
+#ifndef ADT
+#define ADT
+
+#ifdef WITH_NAMESPACE
+namespace llvm {
+#endif
+template <unsigned Alignment, unsigned Size>
+struct AlignedCharArray {
+ alignas(Alignment) char buffer[Size];
+};
+
+template <typename T1>
+class AlignerImpl {
+ T1 t1;
+};
+
+template <typename T1>
+union SizerImpl {
+ char arr1[sizeof(T1)];
+};
+
+template <typename T1>
+struct AlignedCharArrayUnion
+ : AlignedCharArray<alignof(AlignerImpl<T1>), sizeof(SizerImpl<T1>)> {};
+
+template <typename T, unsigned N>
+struct SmallVectorStorage {
+ AlignedCharArrayUnion<T> InlineElts[N];
+};
+template <typename T, unsigned N>
+class SmallVector : SmallVectorStorage<T, N> {};
+
+template <typename T>
+struct OptionalStorage {
+ AlignedCharArrayUnion<T> storage;
+};
+template <typename T>
+class Optional {
+ OptionalStorage<T> Storage;
+};
+
+#ifdef WITH_NAMESPACE
+} // namespace llvm
+#endif
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/B/B.h b/test/Modules/Inputs/lsv-debuginfo/B/B.h
new file mode 100644
index 000000000000..c00bc3cddbf5
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/B/B.h
@@ -0,0 +1,14 @@
+#ifndef B_H
+#define B_H
+#include <A/ADT.h>
+#include <C/C.h>
+
+namespace llvm {
+struct S {
+ unsigned a, b, c, d;
+};
+class C {
+ Optional<S> S;
+};
+}
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/C/C.h b/test/Modules/Inputs/lsv-debuginfo/C/C.h
new file mode 100644
index 000000000000..52c6e4dbac94
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/C/C.h
@@ -0,0 +1,13 @@
+#ifndef C_H
+#define C_H
+#include <A/ADT.h>
+
+namespace llvm {
+class D {
+ struct Q {
+ unsigned a, b, c, d;
+ };
+ SmallVector<Q, 4> q;
+};
+} // namespace llvm
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/module.modulemap b/test/Modules/Inputs/lsv-debuginfo/module.modulemap
new file mode 100644
index 000000000000..5bb044908dc7
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/module.modulemap
@@ -0,0 +1,9 @@
+module A {
+ umbrella "A" module * { export * }
+}
+module B {
+ umbrella "B" module * { export * }
+}
+module C {
+ umbrella "C" module * { export * }
+}
diff --git a/test/Modules/Inputs/no-module-map/a.h b/test/Modules/Inputs/no-module-map/a.h
new file mode 100644
index 000000000000..546714f4ca3e
--- /dev/null
+++ b/test/Modules/Inputs/no-module-map/a.h
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+void a();
+#endif
diff --git a/test/Modules/Inputs/no-module-map/b.h b/test/Modules/Inputs/no-module-map/b.h
new file mode 100644
index 000000000000..d3fbc8b3ad59
--- /dev/null
+++ b/test/Modules/Inputs/no-module-map/b.h
@@ -0,0 +1,5 @@
+#ifndef B_H
+#define B_H
+#include "a.h"
+void b();
+#endif
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/class.h b/test/Modules/Inputs/odr_hash-Unresolved/class.h
index fe3a7116f9bf..8a3c9f941f7e 100644
--- a/test/Modules/Inputs/odr_hash-Unresolved/class.h
+++ b/test/Modules/Inputs/odr_hash-Unresolved/class.h
@@ -6,6 +6,7 @@ class S {
void run() {
int x;
A::Check(&Field, 1);
+ A::Check(&Field, 1);
}
};
#endif
diff --git a/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h
new file mode 100644
index 000000000000..c362dd03f048
--- /dev/null
+++ b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h
@@ -0,0 +1 @@
+int bar();
diff --git a/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map
new file mode 100644
index 000000000000..dc51f5d03aca
--- /dev/null
+++ b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map
@@ -0,0 +1,5 @@
+module ModuleInSubdir {
+header "h1.h"
+ export *
+}
+
diff --git a/test/Modules/Inputs/unavailable-local-visibility/a.h b/test/Modules/Inputs/unavailable-local-visibility/a.h
new file mode 100644
index 000000000000..865bb65f4d28
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/a.h
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+#include "x.h"
+#endif
diff --git a/test/Modules/Inputs/unavailable-local-visibility/b.h b/test/Modules/Inputs/unavailable-local-visibility/b.h
new file mode 100644
index 000000000000..71360e38b7b1
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/b.h
@@ -0,0 +1,13 @@
+#ifndef B_H
+#define B_H
+#include "a.h"
+
+#ifndef A_H
+#error where is a?
+#endif
+
+#ifndef X_H
+#error where is x?
+#endif
+X f();
+#endif
diff --git a/test/Modules/Inputs/unavailable-local-visibility/module.modulemap b/test/Modules/Inputs/unavailable-local-visibility/module.modulemap
new file mode 100644
index 000000000000..8da3d3c1ab0e
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/module.modulemap
@@ -0,0 +1,9 @@
+module M {
+ module a { header "a.h" export * }
+ module b { header "b.h" export * }
+ module doesnotexist { header "doesnotexist.h" }
+}
+module X {
+ header "x.h"
+ export *
+}
diff --git a/test/Modules/Inputs/unavailable-local-visibility/x.h b/test/Modules/Inputs/unavailable-local-visibility/x.h
new file mode 100644
index 000000000000..0498c5d2aabc
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/x.h
@@ -0,0 +1,4 @@
+#ifndef X_H
+#define X_H
+struct X {};
+#endif
diff --git a/test/Modules/autolink.m b/test/Modules/autolink.m
index 6aee0e11b120..f15472692dd9 100644
--- a/test/Modules/autolink.m
+++ b/test/Modules/autolink.m
@@ -37,9 +37,9 @@ int use_autolink_sub3() {
// NOTE: "autolink_sub" is intentionally not linked.
// CHECK: !llvm.linker.options = !{![[AUTOLINK_PCH:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[AUTOLINK:[0-9]+]], ![[DEPENDSONMODULE:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]}
-// CHECK: ![[AUTOLINK_PCH]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink_from_pch{{(\.lib)?}}"}
+// CHECK: ![[AUTOLINK_PCH]] = !{!"{{(\\01|-l|/DEFAULTLIB:|lib", !")}}autolink_from_pch{{(\.lib)?}}"}
// CHECK: ![[AUTOLINK_FRAMEWORK]] = !{!"-framework", !"autolink_framework"}
-// CHECK: ![[AUTOLINK]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink{{(\.lib)?}}"}
+// CHECK: ![[AUTOLINK]] = !{!"{{(\\01|-l|/DEFAULTLIB:|lib", !")}}autolink{{(\.lib)?}}"}
// CHECK: ![[DEPENDSONMODULE]] = !{!"-framework", !"DependsOnModule"}
// CHECK: ![[MODULE]] = !{!"-framework", !"Module"}
// CHECK: ![[NOUMBRELLA]] = !{!"-framework", !"NoUmbrella"}
diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m
index 118537ba2a4f..f4c101cd0c6d 100644
--- a/test/Modules/crash-vfs-headermaps.m
+++ b/test/Modules/crash-vfs-headermaps.m
@@ -32,7 +32,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/Foo.framework/Headers",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-include-pch.m b/test/Modules/crash-vfs-include-pch.m
index 78a8e149a41b..f4ae00e3bb59 100644
--- a/test/Modules/crash-vfs-include-pch.m
+++ b/test/Modules/crash-vfs-include-pch.m
@@ -33,7 +33,6 @@ void g() { double x = DBL_MAX; }
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/out",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-ivfsoverlay.m b/test/Modules/crash-vfs-ivfsoverlay.m
index 85aaeaef67a5..3cb0f1d0321d 100644
--- a/test/Modules/crash-vfs-ivfsoverlay.m
+++ b/test/Modules/crash-vfs-ivfsoverlay.m
@@ -36,7 +36,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/example"
// CHECKYAML: 'contents': [
diff --git a/test/Modules/crash-vfs-path-emptydir-entries.m b/test/Modules/crash-vfs-path-emptydir-entries.m
index a50ea869f476..0c7286d248dc 100644
--- a/test/Modules/crash-vfs-path-emptydir-entries.m
+++ b/test/Modules/crash-vfs-path-emptydir-entries.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// Test clang can collect symbolic link headers used in modules.
// crash reproducer if there's a symbolic link header file used in a module.
diff --git a/test/Modules/crash-vfs-path-symlink-component.m b/test/Modules/crash-vfs-path-symlink-component.m
index 565a64fb5c23..b868625aa6a4 100644
--- a/test/Modules/crash-vfs-path-symlink-component.m
+++ b/test/Modules/crash-vfs-path-symlink-component.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// Test that clang is capable of collecting the right header files in the
// crash reproducer if there's a symbolic link component in the path.
diff --git a/test/Modules/crash-vfs-path-symlink-topheader.m b/test/Modules/crash-vfs-path-symlink-topheader.m
index fea1f01c02ae..6582243d62c9 100644
--- a/test/Modules/crash-vfs-path-symlink-topheader.m
+++ b/test/Modules/crash-vfs-path-symlink-topheader.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// Test clang can collect symbolic link headers used in modules.
// crash reproducer if there's a symbolic link header file used in a module.
diff --git a/test/Modules/crash-vfs-path-traversal.m b/test/Modules/crash-vfs-path-traversal.m
index cd12cadcf18e..b924d81d0467 100644
--- a/test/Modules/crash-vfs-path-traversal.m
+++ b/test/Modules/crash-vfs-path-traversal.m
@@ -3,7 +3,7 @@
// FIXME: Canonicalizing paths to remove relative traversal components
// currenty fails a unittest on windows and is disable by default.
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t
diff --git a/test/Modules/crash-vfs-relative-incdir.m b/test/Modules/crash-vfs-relative-incdir.m
index ed02de8d7e1e..d019c01e2f0f 100644
--- a/test/Modules/crash-vfs-relative-incdir.m
+++ b/test/Modules/crash-vfs-relative-incdir.m
@@ -36,7 +36,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/Inputs/crash-recovery/usr/include",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-relative-overlay.m b/test/Modules/crash-vfs-relative-overlay.m
index e55f4c8f272e..9eeed011fc78 100644
--- a/test/Modules/crash-vfs-relative-overlay.m
+++ b/test/Modules/crash-vfs-relative-overlay.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t
diff --git a/test/Modules/crash-vfs-run-reproducer.m b/test/Modules/crash-vfs-run-reproducer.m
index eba56c53f6fa..d15b52d40b97 100644
--- a/test/Modules/crash-vfs-run-reproducer.m
+++ b/test/Modules/crash-vfs-run-reproducer.m
@@ -36,7 +36,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/Inputs/crash-recovery/usr/include",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-umbrella-frameworks.m b/test/Modules/crash-vfs-umbrella-frameworks.m
index a18acf576ea3..e311c608549a 100644
--- a/test/Modules/crash-vfs-umbrella-frameworks.m
+++ b/test/Modules/crash-vfs-umbrella-frameworks.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t
diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp
index 25f8a9992585..c085eb5f676c 100644
--- a/test/Modules/cxx-templates.cpp
+++ b/test/Modules/cxx-templates.cpp
@@ -199,6 +199,8 @@ namespace hidden_specializations {
cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls_t<int> unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
+ // expected-error@cxx-templates-unimported.h:29 {{explicit specialization of 'nested_cls_t' must be imported}}
+ // expected-note@-2 {{in evaluation of exception specification}}
cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}}
// For enums, uses that would trigger instantiations of definitions are not
diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m
index a21f12fa5e5a..8eec36574762 100644
--- a/test/Modules/double-quotes.m
+++ b/test/Modules/double-quotes.m
@@ -32,6 +32,9 @@
#import "A.h"
#import <Z/Z.h>
+// Make sure we correctly handle paths that resemble frameworks, but aren't.
+#import "NotAFramework/Headers/Headers/Thing1.h"
+
int bar() { return foo(); }
// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}}
diff --git a/test/Modules/exception-spec.cpp b/test/Modules/exception-spec.cpp
new file mode 100644
index 000000000000..083cd950f7c5
--- /dev/null
+++ b/test/Modules/exception-spec.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -x c++ -std=c++17 -fmodules -fmodules-local-submodule-visibility -fmodules-cache-path=%t %s -verify
+
+// expected-no-diagnostics
+
+#pragma clang module build PR38627
+module PR38627 {}
+#pragma clang module contents
+#pragma clang module begin PR38627
+namespace PR38627 {
+struct X {
+ virtual ~X() {}
+ struct C {
+ friend X::~X();
+ } c;
+};
+}
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import PR38627
+
+namespace PR38627 {
+struct Y {
+ virtual ~Y() {}
+ struct C {
+ friend Y::~Y();
+ } c;
+};
+static_assert(noexcept(X().~X()));
+static_assert(noexcept(Y().~Y()));
+
+struct A { virtual ~A() = default; };
+struct B : public A, public X {
+ virtual ~B() override = default;
+};
+} // PR38627
diff --git a/test/Modules/friend-definition.cpp b/test/Modules/friend-definition.cpp
index 8588cbd9c6f4..32329d0e3e1c 100644
--- a/test/Modules/friend-definition.cpp
+++ b/test/Modules/friend-definition.cpp
@@ -7,6 +7,7 @@ module A {}
#pragma clang module begin A
template<typename T> struct A {
friend A operator+(const A&, const A&) { return {}; }
+ template<typename T2> friend void func_1(const A&, const T2 &) {}
};
#pragma clang module end
#pragma clang module endbuild
@@ -36,4 +37,5 @@ inline void g() { A<int> a; }
void h() {
A<int> a;
a + a;
+ func_1(a, 0);
}
diff --git a/test/Modules/lsv-debuginfo.cpp b/test/Modules/lsv-debuginfo.cpp
new file mode 100755
index 000000000000..30d3c2583fbd
--- /dev/null
+++ b/test/Modules/lsv-debuginfo.cpp
@@ -0,0 +1,39 @@
+// Test C++ -gmodules debug info in the PCMs with local submodule visibility.
+// REQUIRES: asserts
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 \
+// RUN: -fmodules-local-submodule-visibility %s \
+// RUN: -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone \
+// RUN: -dwarf-version=4 -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path="%t" -o %t.ll -I%S/Inputs/lsv-debuginfo \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 \
+// RUN: -fmodules-local-submodule-visibility %s \
+// RUN: -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone \
+// RUN: -dwarf-version=4 -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path="%t" -o %t.ll -I%S/Inputs/lsv-debuginfo \
+// RUN: -DWITH_NAMESPACE \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// ADT
+// CHECK: @__clang_ast =
+
+// B
+// CHECK: @__clang_ast =
+
+// This type isn't anchored anywhere, expect a full definition.
+// CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4, 16>",
+// CHECK-SAME: elements:
+
+// C
+// CHECK: @__clang_ast =
+
+// Here, too.
+// CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4, 16>",
+// CHECK-SAME: elements:
+
+#include <B/B.h>
diff --git a/test/Modules/merge-deduced-return.cpp b/test/Modules/merge-deduced-return.cpp
index 0a4de7b97554..71dc29b633b6 100644
--- a/test/Modules/merge-deduced-return.cpp
+++ b/test/Modules/merge-deduced-return.cpp
@@ -8,6 +8,8 @@ module A {}
#pragma clang module begin A
inline auto f() { struct X {}; return X(); }
inline auto a = f();
+auto g(int);
+template<typename T> auto h(T t) { return g(t); }
#pragma clang module end
#pragma clang module endbuild
@@ -17,12 +19,14 @@ module B {}
#pragma clang module begin B
inline auto f() { struct X {}; return X(); }
inline auto b = f();
+auto g(int) { return 0; }
#pragma clang module end
#pragma clang module endbuild
#ifdef LOCAL
inline auto f() { struct X {}; return X(); }
inline auto b = f();
+auto g(int) { return 0; }
#else
#pragma clang module import B
#endif
@@ -31,3 +35,5 @@ inline auto b = f();
using T = decltype(a);
using T = decltype(b);
+
+int test_g = h(0);
diff --git a/test/Modules/merge-lambdas.cpp b/test/Modules/merge-lambdas.cpp
index d14483aa3aa7..463a4c9b2fc6 100644
--- a/test/Modules/merge-lambdas.cpp
+++ b/test/Modules/merge-lambdas.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fmodules -verify %s
+// RUN: %clang_cc1 -fmodules -verify %s -emit-llvm-only
// expected-no-diagnostics
#pragma clang module build A
@@ -46,3 +46,6 @@ using U = decltype(y2);
using V = decltype(x3);
using V = decltype(y3);
+
+#pragma clang module import A
+void (*p)() = f<int>();
diff --git a/test/Modules/merge-template-pattern-visibility-2.cpp b/test/Modules/merge-template-pattern-visibility-2.cpp
new file mode 100644
index 000000000000..14577f146e94
--- /dev/null
+++ b/test/Modules/merge-template-pattern-visibility-2.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility %s -verify -Werror=undefined-inline
+
+#pragma clang module build A1
+module A1 { export * }
+#pragma clang module contents
+#pragma clang module begin A1
+template<typename T> class A {};
+template<typename T> inline bool f(const A<T>&) { return T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build A2
+module A2 { export * }
+#pragma clang module contents
+#pragma clang module begin A2
+#pragma clang module load A1
+template<typename T> class A {};
+template<typename T> inline bool f(const A<T>&) { return T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build A3
+module A3 { export * }
+#pragma clang module contents
+#pragma clang module begin A3
+template<typename T> class A {};
+template<typename T> inline bool f(const A<T>&) { return T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module load A3
+#pragma clang module import A2
+// expected-error@* {{cannot be used prior to}}
+bool y(A<int> o) { return f(o); } // expected-note {{instantiation of}}
diff --git a/test/Modules/merge-template-pattern-visibility-3.cpp b/test/Modules/merge-template-pattern-visibility-3.cpp
new file mode 100644
index 000000000000..9ac1b6699da3
--- /dev/null
+++ b/test/Modules/merge-template-pattern-visibility-3.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fmodules -emit-llvm-only %s -verify
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+template<typename T> void f(const T&) { T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+template<typename T> void f(const T&) { T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build C
+module C {}
+#pragma clang module contents
+#pragma clang module begin C
+#pragma clang module load B
+template<typename T> void f(const T&) { T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module load A
+inline void f() {}
+void x() { f(); }
+
+#pragma clang module import C
+// expected-error@* {{cannot be used prior to}}
+void y(int n) { f(n); } // expected-note {{instantiation of}}
diff --git a/test/Modules/mismatch-diagnostics.cpp b/test/Modules/mismatch-diagnostics.cpp
new file mode 100644
index 000000000000..038e367e3973
--- /dev/null
+++ b/test/Modules/mismatch-diagnostics.cpp
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/prebuilt_modules
+//
+// RUN: %clang_cc1 -triple %itanium_abi_triple \
+// RUN: -fmodules-ts -fprebuilt-module-path=%t/prebuilt-modules \
+// RUN: -emit-module-interface -pthread -DBUILD_MODULE \
+// RUN: %s -o %t/prebuilt_modules/mismatching_module.pcm
+//
+// RUN: not %clang_cc1 -triple %itanium_abi_triple -fmodules-ts \
+// RUN: -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \
+// RUN: %s 2>&1 | FileCheck %s
+
+#ifdef BUILD_MODULE
+export module mismatching_module;
+#endif
+
+#ifdef CHECK_MISMATCH
+import mismatching_module;
+// CHECK: error: POSIX thread support was enabled in PCH file but is currently disabled
+// CHECK-NEXT: module file {{.*[/|\\\\]}}mismatching_module.pcm cannot be loaded due to a configuration mismatch with the current compilation
+#endif
+
diff --git a/test/Modules/module-debuginfo-prefix.m b/test/Modules/module-debuginfo-prefix.m
new file mode 100644
index 000000000000..da5d86abefd0
--- /dev/null
+++ b/test/Modules/module-debuginfo-prefix.m
@@ -0,0 +1,25 @@
+// REQUIRES: asserts
+
+// Modules:
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c -fmodules -fmodule-format=obj \
+// RUN: -fdebug-prefix-map=%S/Inputs=/OVERRIDE \
+// RUN: -fimplicit-module-maps -DMODULES -fmodules-cache-path=%t %s \
+// RUN: -I %S/Inputs -I %t -emit-llvm -o %t.ll \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// PCH:
+// RUN: %clang_cc1 -x objective-c -emit-pch -fmodule-format=obj -I %S/Inputs \
+// RUN: -fdebug-prefix-map=%S/Inputs=/OVERRIDE \
+// RUN: -o %t.pch %S/Inputs/DebugObjC.h \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-pch.ll
+// RUN: cat %t-pch.ll | FileCheck %s
+
+#ifdef MODULES
+@import DebugObjC;
+#endif
+
+// Dir should always be empty, but on Windows we can't recognize /var
+// as being an absolute path.
+// CHECK: !DIFile(filename: "/OVERRIDE/DebugObjC.h", directory: "{{()|(.*:.*)}}")
diff --git a/test/Modules/module_file_info.m b/test/Modules/module_file_info.m
index 05d401b9450a..0e3138935008 100644
--- a/test/Modules/module_file_info.m
+++ b/test/Modules/module_file_info.m
@@ -16,10 +16,11 @@
// CHECK: Module name: DependsOnModule
// CHECK: Module map file: {{.*}}DependsOnModule.framework{{[/\\]}}module.map
+// CHECK: Imports module 'Module': {{.*}}Module.pcm
// CHECK: Language options:
// CHECK: C99: Yes
-// CHECK: Objective-C 1: Yes
+// CHECK: Objective-C: Yes
// CHECK: modules extension to C: Yes
// CHECK: Module features:
// CHECK: myfeature
diff --git a/test/Modules/no-module-map.cpp b/test/Modules/no-module-map.cpp
new file mode 100644
index 000000000000..46ca38af7eed
--- /dev/null
+++ b/test/Modules/no-module-map.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -fmodules-ts -fmodule-name=ab -x c++-header %S/Inputs/no-module-map/a.h %S/Inputs/no-module-map/b.h -emit-header-module -o %t.pcm
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DB
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA -DB
+
+// RUN: %clang_cc1 -E %t.pcm -o - | FileCheck %s
+// RUN: %clang_cc1 -frewrite-imports -E %t.pcm -o - | FileCheck %s
+// CHECK: # {{.*}}a.h
+// CHECK: # {{.*}}b.h
+
+#ifdef B
+// expected-no-diagnostics
+#endif
+
+#ifdef A
+#include "a.h"
+#endif
+
+#ifdef B
+#include "b.h"
+#endif
+
+#if defined(A) || defined(B)
+#ifndef A_H
+#error A_H should be defined
+#endif
+#else
+#ifdef A_H
+#error A_H should not be defined
+#endif
+// expected-error@+3 {{must be imported from}}
+// expected-note@* {{previous declaration}}
+#endif
+void use_a() { a(); }
+
+#if defined(B)
+#ifndef B_H
+#error B_H should be defined
+#endif
+#else
+#ifdef B_H
+#error B_H should not be defined
+#endif
+// expected-error@+3 {{must be imported from}}
+// expected-note@* {{previous declaration}}
+#endif
+void use_b() { b(); }
diff --git a/test/Modules/odr_hash-Friend.cpp b/test/Modules/odr_hash-Friend.cpp
index 8a2513e2f9cd..e55d9e8fd45a 100644
--- a/test/Modules/odr_hash-Friend.cpp
+++ b/test/Modules/odr_hash-Friend.cpp
@@ -9,7 +9,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST1 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST1
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -17,7 +17,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST2 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST2
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -25,7 +25,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -33,7 +33,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -41,7 +41,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3
#if defined(TEST1)
#include "Box.h"
diff --git a/test/Modules/odr_hash-blocks.cpp b/test/Modules/odr_hash-blocks.cpp
index 07dfa4ce2ac8..512c659f841e 100644
--- a/test/Modules/odr_hash-blocks.cpp
+++ b/test/Modules/odr_hash-blocks.cpp
@@ -41,7 +41,7 @@
#define ACCESS private:
#endif
-// TODO: S1, S2, and S3 should generate errors.
+// TODO: S1 and S2 should generate errors.
namespace Blocks {
#if defined(FIRST)
struct S1 {
@@ -77,6 +77,8 @@ struct S3 {
};
#else
S3 s3;
+// expected-error@first.h:* {{'Blocks::S3::run' from module 'FirstModule' is not present in definition of 'Blocks::S3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'run' does not match}}
#endif
#define DECLS \
diff --git a/test/Modules/odr_hash-gnu.cpp b/test/Modules/odr_hash-gnu.cpp
new file mode 100644
index 000000000000..7091bb559848
--- /dev/null
+++ b/test/Modules/odr_hash-gnu.cpp
@@ -0,0 +1,130 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=gnu++11 %t/Inputs/first.h
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=gnu++11 %t/Inputs/second.h
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=gnu++11
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+namespace Types {
+namespace TypeOfExpr {
+#if defined(FIRST)
+struct Invalid1 {
+ typeof(1 + 2) x;
+};
+double global;
+struct Invalid2 {
+ typeof(global) x;
+};
+struct Valid {
+ typeof(3) x;
+ typeof(x) y;
+ typeof(Valid*) self;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ typeof(3) x;
+};
+int global;
+struct Invalid2 {
+ typeof(global) x;
+};
+struct Valid {
+ typeof(3) x;
+ typeof(x) y;
+ typeof(Valid*) self;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::TypeOfExpr::Invalid1' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof (1 + 2)' (aka 'int')}}
+// expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof (3)' (aka 'int')}}
+Invalid2 i2;
+// expected-error@second.h:* {{'Types::TypeOfExpr::Invalid2::x' from module 'SecondModule' is not present in definition of 'Types::TypeOfExpr::Invalid2' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Valid v;
+#endif
+} // namespace TypeOfExpr
+
+namespace TypeOf {
+#if defined(FIRST)
+struct Invalid1 {
+ typeof(int) x;
+};
+struct Invalid2 {
+ typeof(int) x;
+};
+using T = int;
+struct Invalid3 {
+ typeof(T) x;
+};
+struct Valid {
+ typeof(int) x;
+ using T = typeof(double);
+ typeof(T) y;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ typeof(double) x;
+};
+using I = int;
+struct Invalid2 {
+ typeof(I) x;
+};
+using T = short;
+struct Invalid3 {
+ typeof(T) x;
+};
+struct Valid {
+ typeof(int) x;
+ using T = typeof(double);
+ typeof(T) y;
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'Types::TypeOf::Invalid1::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid1' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@first.h:* {{'Types::TypeOf::Invalid2' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof(int)' (aka 'int')}}
+// expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof(Types::TypeOf::I)' (aka 'int')}}
+Invalid3 i3;
+// expected-error@second.h:* {{'Types::TypeOf::Invalid3::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid3' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Valid v;
+#endif
+} // namespace TypeOf
+} // namespace Types
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
diff --git a/test/Modules/odr_hash-vector.cpp b/test/Modules/odr_hash-vector.cpp
new file mode 100644
index 000000000000..ee59cb617c1a
--- /dev/null
+++ b/test/Modules/odr_hash-vector.cpp
@@ -0,0 +1,128 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 %t/Inputs/first.h -fzvector
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 %t/Inputs/second.h -fzvector
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++11 -fzvector
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+namespace Types {
+namespace Vector {
+#if defined(FIRST)
+struct Invalid1 {
+ __attribute((vector_size(8))) int x;
+};
+struct Invalid2 {
+ __attribute((vector_size(8))) int x;
+};
+struct Invalid3 {
+ __attribute((vector_size(16))) int x;
+};
+struct Valid {
+ __attribute((vector_size(8))) int x1;
+ __attribute((vector_size(16))) int x2;
+ __attribute((vector_size(8))) unsigned x3;
+ __attribute((vector_size(16))) long x4;
+ vector unsigned x5;
+ vector int x6;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ __attribute((vector_size(16))) int x;
+};
+struct Invalid2 {
+ __attribute((vector_size(8))) unsigned x;
+};
+struct Invalid3 {
+ vector unsigned x;
+};
+struct Valid {
+ __attribute((vector_size(8))) int x1;
+ __attribute((vector_size(16))) int x2;
+ __attribute((vector_size(8))) unsigned x3;
+ __attribute((vector_size(16))) long x4;
+ vector unsigned x5;
+ vector int x6;
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'Types::Vector::Invalid1::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid1' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@second.h:* {{'Types::Vector::Invalid2::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid2' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Invalid3 i3;
+// expected-error@second.h:* {{'Types::Vector::Invalid3::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid3' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+
+Valid v;
+#endif
+} // namespace Vector
+
+
+
+namespace ExtVector {
+} // namespace ExtVector
+#if defined(FIRST)
+struct Invalid {
+ using f = __attribute__((ext_vector_type(4))) float;
+};
+struct Valid {
+ using f = __attribute__((ext_vector_type(8))) float;
+};
+#elif defined(SECOND)
+struct Invalid {
+ using f = __attribute__((ext_vector_type(8))) float;
+};
+struct Valid {
+ using f = __attribute__((ext_vector_type(8))) float;
+};
+#else
+Invalid i;
+// expected-error@first.h:* {{'Types::Invalid::f' from module 'FirstModule' is not present in definition of 'Types::Invalid' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'f' does not match}}
+
+Valid v;
+#endif
+
+} // namespace Types
+
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
+
+#ifdef ACCESS
+#undef ACCESS
+#endif
diff --git a/test/Modules/odr_hash.cl b/test/Modules/odr_hash.cl
new file mode 100644
index 000000000000..d4af1cea6e26
--- /dev/null
+++ b/test/Modules/odr_hash.cl
@@ -0,0 +1,80 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c++ %t/Inputs/first.h -cl-std=CL2.0
+// RUN: %clang_cc1 -fsyntax-only -x c++ %t/Inputs/second.h -cl-std=CL2.0
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -cl-std=CL2.0
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+
+#if defined(FIRST)
+void invalid1() {
+ typedef read_only pipe int x;
+}
+void invalid2() {
+ typedef read_only pipe int x;
+}
+void valid() {
+ typedef read_only pipe int x;
+ typedef write_only pipe int y;
+ typedef read_write pipe int z;
+}
+#elif defined(SECOND)
+void invalid1() {
+ typedef write_only pipe int x;
+}
+void invalid2() {
+ typedef read_only pipe float x;
+}
+void valid() {
+ typedef read_only pipe int x;
+ typedef write_only pipe int y;
+ typedef read_write pipe int z;
+}
+#else
+void run() {
+ invalid1();
+// expected-error@second.h:* {{'invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+ invalid2();
+// expected-error@second.h:* {{'invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+ valid();
+}
+#endif
+
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index 16ddfefa53c7..e4c5ba6f82a8 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -25,7 +25,9 @@
// RUN: echo "}" >> %t/Inputs/module.map
// Run test
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++1z
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++1z \
+// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
+// RUN: -I%t/Inputs -verify %s
#if !defined(FIRST) && !defined(SECOND)
#include "first.h"
@@ -2244,22 +2246,6 @@ S2 s2;
#endif
#if defined(FIRST)
-struct T3 {};
-struct S3 {
- friend const T3;
-};
-#elif defined(SECOND)
-struct T3 {};
-struct S3 {
- friend T3;
-};
-#else
-S3 s3;
-// expected-error@second.h:* {{'Friend::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T3'}}
-// expected-note@first.h:* {{but in 'FirstModule' found friend 'const Friend::T3'}}
-#endif
-
-#if defined(FIRST)
struct T4 {};
struct S4 {
friend T4;
@@ -2292,14 +2278,12 @@ S5 s5;
friend class FriendA; \
friend struct FriendB; \
friend FriendC; \
- friend const FriendD; \
friend void Function();
#if defined(FIRST) || defined(SECOND)
class FriendA {};
class FriendB {};
class FriendC {};
-class FriendD {};
#endif
#if defined(FIRST) || defined(SECOND)
@@ -3317,6 +3301,568 @@ Valid V;
#endif
} // namespace Enums
+namespace Types {
+namespace Complex {
+#if defined(FIRST)
+void invalid() {
+ _Complex float x;
+}
+void valid() {
+ _Complex float x;
+}
+#elif defined(SECOND)
+void invalid() {
+ _Complex double x;
+}
+void valid() {
+ _Complex float x;
+}
+#else
+auto function1 = invalid;
+// expected-error@second.h:* {{'Types::Complex::invalid' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = valid;
+#endif
+} // namespace Complex
+
+namespace Decltype {
+#if defined(FIRST)
+void invalid1() {
+ decltype(1 + 1) x;
+}
+int global;
+void invalid2() {
+ decltype(global) x;
+}
+void valid() {
+ decltype(1.5) x;
+ decltype(x) y;
+}
+#elif defined(SECOND)
+void invalid1() {
+ decltype(2) x;
+}
+float global;
+void invalid2() {
+ decltype(global) x;
+}
+void valid() {
+ decltype(1.5) x;
+ decltype(x) y;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::Decltype::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::Decltype::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = valid;
+#endif
+} // namespace Decltype
+
+namespace Auto {
+#if defined(FIRST)
+void invalid1() {
+ decltype(auto) x = 1;
+}
+void invalid2() {
+ auto x = 1;
+}
+void invalid3() {
+ __auto_type x = 1;
+}
+void valid() {
+ decltype(auto) x = 1;
+ auto y = 1;
+ __auto_type z = 1;
+}
+#elif defined(SECOND)
+void invalid1() {
+ auto x = 1;
+}
+void invalid2() {
+ __auto_type x = 1;
+}
+void invalid3() {
+ decltype(auto) x = 1;
+}
+void valid() {
+ decltype(auto) x = 1;
+ auto y = 1;
+ __auto_type z = 1;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::Auto::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid3;
+// expected-error@second.h:* {{'Types::Auto::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = invalid2;
+// expected-error@second.h:* {{'Types::Auto::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function4 = valid;
+#endif
+} // namespace Auto
+
+namespace DeducedTemplateSpecialization {
+#if defined(FIRST)
+template<typename T> struct A {};
+A() -> A<int>;
+template<typename T> struct B {};
+B() -> B<int>;
+
+void invalid1() {
+ A a{};
+}
+void invalid2() {
+ A a{};
+}
+void valid() {
+ B b{};
+}
+#elif defined(SECOND)
+template<typename T> struct A {};
+A() -> A<float>;
+template<typename T> struct B {};
+B() -> B<int>;
+
+void invalid1() {
+ A a{};
+}
+void invalid2() {
+ B a{};
+}
+void valid() {
+ B b{};
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = valid;
+#endif
+} // namespace DeducedTemplateSpecialization
+
+namespace DependentAddressSpace {
+#if defined(FIRST)
+template <int A1, int A2>
+void invalid1() {
+ using type = int __attribute__((address_space(A1)));
+}
+template <int A1>
+void invalid2() {
+ using type = float __attribute__((address_space(A1)));
+}
+template <int A1, int A2>
+void valid() {
+ using type1 = float __attribute__((address_space(A1)));
+ using type2 = int __attribute__((address_space(A2)));
+ using type3 = int __attribute__((address_space(A1 + A2)));
+}
+#elif defined(SECOND)
+template <int A1, int A2>
+void invalid1() {
+ using type = int __attribute__((address_space(A2)));
+}
+template <int A1>
+void invalid2() {
+ using type = int __attribute__((address_space(A1)));
+}
+template <int A1, int A2>
+void valid() {
+ using type1 = float __attribute__((address_space(A1)));
+ using type2 = int __attribute__((address_space(A2)));
+ using type3 = int __attribute__((address_space(A1 + A2)));
+}
+#else
+template <int A, int B>
+class S {
+ static auto function1 = invalid1<A, B>;
+ // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto function2 = invalid2<B>;
+ // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto function3 = valid<A, B>;
+};
+#endif
+} // namespace DependentAddressSpace
+
+namespace DependentSizedExtVector {
+#if defined(FIRST)
+template<int Size>
+void invalid1() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+template<int Size>
+void invalid2() {
+ typedef int __attribute__((ext_vector_type(Size + 0))) type;
+}
+template<int Size>
+void valid() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+#elif defined(SECOND)
+template<int Size>
+void invalid1() {
+ typedef float __attribute__((ext_vector_type(Size))) type;
+}
+template<int Size>
+void invalid2() {
+ typedef int __attribute__((ext_vector_type(Size + 1))) type;
+}
+template<int Size>
+void valid() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+#else
+template <int Num>
+class S {
+ static auto Function1 = invalid1<Num>;
+ // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto Function2 = invalid2<Num>;
+ // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto Function3 = valid<Num>;
+};
+#endif
+} // namespace DependentSizedExtVector
+
+namespace InjectedClassName {
+#if defined(FIRST)
+struct Invalid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L3 *x;
+ };
+ };
+};
+struct Valid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ L3 *y;
+ };
+ };
+};
+#elif defined(SECOND)
+struct Invalid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ };
+ };
+};
+struct Valid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ L3 *y;
+ };
+ };
+};
+#else
+Invalid::L2<1>::L3<1> invalid;
+// expected-error@second.h:* {{'Types::InjectedClassName::Invalid::L2::L3::x' from module 'SecondModule' is not present in definition of 'L3<>' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Valid::L2<1>::L3<1> valid;
+#endif
+} // namespace InjectedClassName
+
+namespace MemberPointer {
+#if defined(FIRST)
+struct A {};
+struct B {};
+
+void Invalid1() {
+ int A::*x;
+};
+void Invalid2() {
+ int A::*x;
+}
+void Invalid3() {
+ int (A::*x)(int);
+}
+void Valid() {
+ int A::*x;
+ float A::*y;
+ bool B::*z;
+ void (A::*fun1)();
+ int (A::*fun2)();
+ void (B::*fun3)(int);
+ void (B::*fun4)(bool*, int);
+}
+#elif defined(SECOND)
+struct A {};
+struct B {};
+
+void Invalid1() {
+ float A::*x;
+};
+void Invalid2() {
+ int B::*x;
+}
+void Invalid3() {
+ int (A::*x)(int, int);
+}
+void Valid() {
+ int A::*x;
+ float A::*y;
+ bool B::*z;
+ void (A::*fun1)();
+ int (A::*fun2)();
+ void (B::*fun3)(int);
+ void (B::*fun4)(bool*, int);
+}
+#else
+auto function1 = Invalid1;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = Invalid2;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = Invalid3;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function4 = Valid;
+#endif
+
+} // namespace MemberPointer
+
+namespace PackExpansion {
+#if defined(FIRST)
+struct Invalid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+struct Valid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+#elif defined(SECOND)
+struct Invalid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(B...);
+ void run(A...);
+ };
+ };
+};
+struct Valid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+#else
+Invalid::L2<int>::L3<short, bool> invalid;
+// expected-error@first.h:* {{'Types::PackExpansion::Invalid::L2::L3' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'run' with 1st parameter of type 'A...'}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'run' with 1st parameter of type 'B...'}}
+Valid::L2<int>::L3<short, bool> valid;
+#endif
+
+} // namespace PackExpansion
+
+namespace Paren {
+#if defined(FIRST)
+void invalid() {
+ int (*x);
+}
+void valid() {
+ int (*x);
+}
+#elif defined(SECOND)
+void invalid() {
+ float (*x);
+}
+void valid() {
+ int (*x);
+}
+#else
+auto function1 = invalid;
+// expected-error@second.h:* {{'Types::Paren::invalid' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = valid;
+#endif
+} // namespace Paren
+
+namespace SubstTemplateTypeParm {
+#if defined(FIRST)
+template <class> struct wrapper {};
+template <class, class, class> struct triple {};
+struct Valid {
+ template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+ struct L2 {
+ A<T, T> x;
+ };
+};
+#elif defined(SECOND)
+template <class> struct wrapper {};
+template <class, class, class> struct triple {};
+struct Valid {
+ template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+ struct L2 {
+ A<T, T> x;
+ };
+};
+#else
+template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+using V = Valid::L2<T, A>;
+#endif
+} // namespace SubstTemplateTypeParm
+
+namespace SubstTemplateTypeParmPack {
+} // namespace SubstTemplateTypeParmPack
+
+namespace UnaryTransform {
+#if defined(FIRST)
+enum class E1a : unsigned {};
+struct Invalid1 {
+ __underlying_type(E1a) x;
+};
+enum E2a : unsigned {};
+struct Invalid2 {
+ __underlying_type(E2a) x;
+};
+enum E3a {};
+struct Invalid3 {
+ __underlying_type(E3a) x;
+};
+enum E4a {};
+struct Invalid4 {
+ __underlying_type(E4a) x;
+};
+enum E1 {};
+struct Valid1 {
+ __underlying_type(E1) x;
+};
+enum E2 : unsigned {};
+struct Valid2 {
+ __underlying_type(E2) x;
+};
+enum class E3 {};
+struct Valid3 {
+ __underlying_type(E3) x;
+};
+#elif defined(SECOND)
+enum class E1b : signed {};
+struct Invalid1 {
+ __underlying_type(E1b) x;
+};
+enum class E2b : unsigned {};
+struct Invalid2 {
+ __underlying_type(E2b) x;
+};
+enum E3b : int {};
+struct Invalid3 {
+ __underlying_type(E3b) x;
+};
+enum E4b {};
+struct Invalid4 {
+ __underlying_type(E4b) x;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2b)' (aka 'unsigned int')}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2a)' (aka 'unsigned int')}}
+Invalid3 i3;
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid4 i4;
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4b)' (aka 'unsigned int')}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4a)' (aka 'unsigned int')}}
+Valid1 v1;
+Valid2 v2;
+Valid3 v3;
+#endif
+} // namespace UnaryTransform
+
+namespace UnresolvedUsing {
+#if defined(FIRST)
+template <class T> struct wrapper {};
+template <class T>
+struct Invalid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+};
+template <class T>
+struct Valid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+ T2 y;
+};
+#elif defined(SECOND)
+template <class T> struct wrapper {};
+template <class T>
+struct Invalid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T2 x;
+};
+template <class T>
+struct Valid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+ T2 y;
+};
+#else
+template <class T> using I = Invalid<T>;
+// expected-error@first.h:* {{'Types::UnresolvedUsing::Invalid::x' from module 'FirstModule' is not present in definition of 'Invalid<T>' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+
+template <class T> using V = Valid<T>;
+#endif
+
+} // namespace UnresolvedUsing
+
+// Vector
+// void invalid1() {
+// __attribute((vector_size(8))) int *x1;
+//}
+
+} // namespace Types
+
// Collection of interesting cases below.
// Naive parsing of AST can lead to cycles in processing. Ensure
diff --git a/test/Modules/odr_hash.mm b/test/Modules/odr_hash.mm
new file mode 100644
index 000000000000..f04fb7eb5e8e
--- /dev/null
+++ b/test/Modules/odr_hash.mm
@@ -0,0 +1,299 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/first.h -fblocks -fobjc-arc
+// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/second.h -fblocks -fobjc-arc
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c++ -I%t/Inputs -verify %s -fblocks -fobjc-arc
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+@protocol P1
+@end
+
+@protocol P2
+@end
+
+@interface I1
+@end
+
+@interface I2 : I1
+@end
+
+@interface Interface1 <T : I1 *> {
+@public
+ T<P1> x;
+}
+@end
+
+@interface Interface2 <T : I1 *>
+@end
+
+@interface Interface3 <T : I1 *>
+@end
+
+#endif
+
+#if defined(FIRST)
+struct S {
+ Interface1 *I;
+ decltype(I->x) x;
+ int y;
+};
+#elif defined(SECOND)
+struct S {
+ Interface1 *I;
+ decltype(I->x) x;
+ bool y;
+};
+#else
+S s;
+// expected-error@second.h:* {{'S::y' from module 'SecondModule' is not present in definition of 'S' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'y' does not match}}
+#endif
+
+namespace Types {
+namespace Attributed {
+#if defined(FIRST)
+void invalid1() {
+ static double __attribute((objc_gc(strong))) *x;
+}
+void invalid2() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+void valid() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+#elif defined(SECOND)
+void invalid1() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+void invalid2() {
+ static int __attribute((objc_gc(weak))) *x;
+}
+void valid() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{Types::Attributed::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::Attributed::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = valid;
+#endif
+} // namespace Attributed
+
+namespace BlockPointer {
+#if defined(FIRST)
+void invalid1() {
+ void (^x)(int);
+}
+void invalid2() {
+ void (^x)(int);
+}
+void invalid3() {
+ void (^x)(int);
+}
+void invalid4() {
+ void (^x)(int);
+}
+void valid() {
+ void (^x1)(int);
+ int (^x2)(int);
+ void (^x3)(int, int);
+ void (^x4)(short);
+}
+#elif defined(SECOND)
+void invalid1() {
+ void (^x)();
+}
+void invalid2() {
+ void (^x)(int, int);
+}
+void invalid3() {
+ int (^x)(int);
+}
+void invalid4() {
+ void (^x)(float);
+}
+void valid() {
+ void (^x1)(int);
+ int (^x2)(int);
+ void (^x3)(int, int);
+ void (^x4)(short);
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = invalid3;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function4 = invalid4;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid4' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function5 = valid;
+#endif
+} // namespace BlockPointer
+
+namespace ObjCObject {
+#if defined(FIRST)
+struct Invalid1 {
+ using T = Interface2<I1*>;
+};
+struct Invalid2 {
+ using T = Interface2<I1*>;
+};
+struct Invalid3 {
+ using T = Interface2<P1, P1>;
+};
+struct Invalid4 {
+ using T = Interface2<P1>;
+};
+struct Valid {
+ using T1 = Interface2<I1*>;
+ using T2 = Interface3<I1*>;
+ using T3 = Interface2<P1>;
+ using T4 = Interface3<P1, P2>;
+ using T5 = __kindof Interface2;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ using T = Interface3<I1*>;
+};
+struct Invalid2 {
+ using T = Interface2<I2*>;
+};
+struct Invalid3 {
+ using T = Interface2<P1>;
+};
+struct Invalid4 {
+ using T = Interface2<P2>;
+};
+struct Valid {
+ using T1 = Interface2<I1*>;
+ using T2 = Interface3<I1*>;
+ using T3 = Interface2<P1>;
+ using T4 = Interface3<P1, P2>;
+ using T5 = __kindof Interface2;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid1::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'T' does not match}}
+Invalid2 i2;
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid2::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid2' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'T' does not match}}
+Invalid3 i3;
+// expected-error@second.h:* {{'Types::ObjCObject::Invalid3' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'Interface2<P1>'}}
+// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'Interface2<P1,P1>'}}
+Invalid4 i4;
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid4::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid4' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'T' does not match}}
+Valid v;
+#endif
+} // namespace VisitObjCObject
+} // namespace Types
+
+#if defined(FIRST)
+@interface Interface4 <T : I1 *> {
+@public
+ T<P1> x;
+}
+@end
+@interface Interface5 <T : I1 *> {
+@public
+ T<P1> x;
+}
+@end
+@interface Interface6 <T1 : I1 *, T2 : I2 *> {
+@public
+ T1 x;
+}
+@end
+#elif defined(SECOND)
+@interface Interface4 <T : I1 *> {
+@public
+ T<P2> x;
+}
+@end
+@interface Interface5 <T : I1 *> {
+@public
+ T<P1, P2> x;
+}
+@end
+@interface Interface6 <T1 : I1 *, T2 : I2 *> {
+@public
+ T2 x;
+}
+@end
+#endif
+
+namespace Types {
+namespace ObjCTypeParam {
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+ Interface4 *I;
+ decltype(I->x) x;
+};
+struct Invalid2 {
+ Interface5 *I;
+ decltype(I->x) x;
+};
+struct Invalid3 {
+ Interface6 *I;
+ decltype(I->x) x;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid2::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid3 i3;
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+} // namespace ObjCTypeParam
+} // namespace Types
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
diff --git a/test/Modules/prune.m b/test/Modules/prune.m
index 97a2fd7d0dcc..7c462e20fcef 100644
--- a/test/Modules/prune.m
+++ b/test/Modules/prune.m
@@ -1,3 +1,6 @@
+// NetBSD: noatime mounts currently inhibit 'touch -a' updates
+// UNSUPPORTED: system-netbsd
+
// Test the automatic pruning of module cache entries.
#ifdef IMPORT_DEPENDS_ON_MODULE
@import DependsOnModule;
diff --git a/test/Modules/relative-dep-gen.cpp b/test/Modules/relative-dep-gen.cpp
index bfa9471859b8..e1db618c3622 100644
--- a/test/Modules/relative-dep-gen.cpp
+++ b/test/Modules/relative-dep-gen.cpp
@@ -30,9 +30,9 @@
#include "Inputs/relative-dep-gen-1.h"
// CHECK-BUILD: mod.pcm:
-// CHECK-BUILD: {{[ \t]}}Inputs/relative-dep-gen{{(-cwd)?}}.modulemap
-// CHECK-BUILD: {{[ \t]}}Inputs/relative-dep-gen-1.h
-// CHECK-BUILD: {{[ \t]}}Inputs/relative-dep-gen-2.h
+// CHECK-BUILD: {{[ \t]}}Inputs{{[/\\]}}relative-dep-gen{{(-cwd)?}}.modulemap
+// CHECK-BUILD: {{[ \t]}}Inputs{{[/\\]}}relative-dep-gen-1.h
+// CHECK-BUILD: {{[ \t]}}Inputs{{[/\\]}}relative-dep-gen-2.h
// CHECK-USE: use.o:
// CHECK-USE-DAG: {{[ \t]}}relative-dep-gen.cpp
// CHECK-EXPLICIT-DAG: mod.pcm
diff --git a/test/Modules/strict-decluse-headers.cpp b/test/Modules/strict-decluse-headers.cpp
new file mode 100644
index 000000000000..deeda2fe7f4d
--- /dev/null
+++ b/test/Modules/strict-decluse-headers.cpp
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: touch %t/foo.h
+// RUN: echo '#include "foo.h"' > %t/bar.h
+// RUN: touch %t/baz.h
+// RUN: echo 'module X { header "bar.h" header "baz.h" }' > %t/map
+//
+// RUN: not %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/bar.h %t/baz.h 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/baz.h %t/bar.h 2>&1 | FileCheck %s
+//
+// Don't crash on this: (FIXME: we should produce an error that the specified module name is not known)
+// RUN: %clang_cc1 -fsyntax-only -fmodules -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/baz.h %t/bar.h
+//
+// Don't crash on this: (FIXME: we should produce an error that the specified file is not part of the specified module)
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/foo.h
+//
+// CHECK: module X does not depend on a module exporting 'foo.h'
diff --git a/test/Modules/subdirectory-module-maps-working-dir.m b/test/Modules/subdirectory-module-maps-working-dir.m
new file mode 100644
index 000000000000..c106dd453e04
--- /dev/null
+++ b/test/Modules/subdirectory-module-maps-working-dir.m
@@ -0,0 +1,13 @@
+// RUN: rm -rf %t
+// RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t \
+// RUN: -working-directory %S/Inputs \
+// RUN: -I subdirectory-module-maps-working-dir \
+// RUN: %s -Werror=implicit-function-declaration -Xclang -verify
+
+@import ModuleInSubdir;
+
+void foo() {
+ int x = bar();
+}
+
+// expected-no-diagnostics
diff --git a/test/Modules/submodules-merge-defs.cpp b/test/Modules/submodules-merge-defs.cpp
index 4ab822a022bd..795150208c95 100644
--- a/test/Modules/submodules-merge-defs.cpp
+++ b/test/Modules/submodules-merge-defs.cpp
@@ -65,7 +65,7 @@ using pre_i = I<>; // expected-error +{{must be imported}}
J<> pre_j; // expected-error {{declaration of 'J' must be imported}}
#ifdef IMPORT_USE_2
-// expected-error-re@-2 {{default argument of 'J' must be imported from one of {{.*}}stuff.use{{.*}}stuff.use-2}}
+// expected-error-re@-2 {{default argument of 'J' must be imported from one of {{.*}}stuff.use-2{{.*}}stuff.use}}
#elif EARLY_INDIRECT_INCLUDE
// expected-error@-4 {{default argument of 'J' must be imported from module 'merged-defs'}}
#else
diff --git a/test/Modules/target-platform-features.m b/test/Modules/target-platform-features.m
new file mode 100644
index 000000000000..875c83a2a545
--- /dev/null
+++ b/test/Modules/target-platform-features.m
@@ -0,0 +1,79 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/InputsA
+
+// RUN: echo "module RequiresMacOS {" >> %t/InputsA/module.map
+// RUN: echo " requires macos" >> %t/InputsA/module.map
+// RUN: echo "}" >> %t/InputsA/module.map
+// RUN: echo "module RequiresNotiOS {" >> %t/InputsA/module.map
+// RUN: echo " requires !ios" >> %t/InputsA/module.map
+// RUN: echo "}" >> %t/InputsA/module.map
+// RUN: echo "module RequiresMain {" >> %t/InputsA/module.map
+// RUN: echo " module SubRequiresNotiOS {" >> %t/InputsA/module.map
+// RUN: echo " requires !ios" >> %t/InputsA/module.map
+// RUN: echo " }" >> %t/InputsA/module.map
+// RUN: echo "}" >> %t/InputsA/module.map
+
+// RUN: %clang_cc1 -triple=x86_64-apple-macosx10.6 -DENABLE_DARWIN -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsA -verify %s
+// expected-no-diagnostics
+
+// RUN: not %clang_cc1 -triple=arm64-apple-ios -DENABLE_DARWIN -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsA %s 2> %t/notios
+// RUN: FileCheck %s -check-prefix=CHECK-IOS < %t/notios
+#ifdef ENABLE_DARWIN
+// CHECK-IOS: module 'RequiresMacOS' requires feature 'macos'
+@import RequiresMacOS;
+// CHECK-IOS: module 'RequiresNotiOS' is incompatible with feature 'ios'
+@import RequiresNotiOS;
+// We should never get errors for submodules that don't match
+// CHECK-IOS-NOT: module 'RequiresMain'
+@import RequiresMain;
+#endif
+
+// RUN: mkdir %t/InputsB
+// RUN: echo "module RequiresiOSSim {" >> %t/InputsB/module.map
+// RUN: echo " requires iossimulator" >> %t/InputsB/module.map
+// RUN: echo "}" >> %t/InputsB/module.map
+// RUN: %clang_cc1 -triple=x86_64-apple-iossimulator -DENABLE_IOSSIM -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsB %s -verify
+// RUN: %clang_cc1 -triple=x86_64-apple-ios-simulator -DENABLE_IOSSIM -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsB %s -verify
+
+#ifdef ENABLE_IOSSIM
+@import RequiresiOSSim;
+#endif
+
+// RUN: mkdir %t/InputsC
+// RUN: echo "module RequiresLinuxEABIA {" >> %t/InputsC/module.map
+// RUN: echo " requires linux, gnueabi" >> %t/InputsC/module.map
+// RUN: echo "}" >> %t/InputsC/module.map
+// RUN: echo "module RequiresLinuxEABIB {" >> %t/InputsC/module.map
+// RUN: echo " requires gnueabi" >> %t/InputsC/module.map
+// RUN: echo "}" >> %t/InputsC/module.map
+// RUN: echo "module RequiresLinuxEABIC {" >> %t/InputsC/module.map
+// RUN: echo " requires linux" >> %t/InputsC/module.map
+// RUN: echo "}" >> %t/InputsC/module.map
+// RUN: %clang_cc1 -triple=armv8r-none-linux-gnueabi -DENABLE_LINUXEABI -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsC %s -verify
+
+#ifdef ENABLE_LINUXEABI
+@import RequiresLinuxEABIA;
+@import RequiresLinuxEABIB;
+@import RequiresLinuxEABIC;
+#endif
+
+// RUN: mkdir %t/InputsD
+// RUN: echo "module RequiresWinMSVCA {" >> %t/InputsD/module.map
+// RUN: echo " requires windows" >> %t/InputsD/module.map
+// RUN: echo "}" >> %t/InputsD/module.map
+// RUN: echo "module RequiresWinMSVCB {" >> %t/InputsD/module.map
+// RUN: echo " requires windows, msvc" >> %t/InputsD/module.map
+// RUN: echo "}" >> %t/InputsD/module.map
+// RUN: echo "module RequiresWinMSVCC {" >> %t/InputsD/module.map
+// RUN: echo " requires msvc" >> %t/InputsD/module.map
+// RUN: echo "}" >> %t/InputsD/module.map
+// RUN: %clang_cc1 -triple=thumbv7-unknown-windows-msvc -DENABLE_WINMSVC -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsD %s -verify
+
+#ifdef ENABLE_WINMSVC
+@import RequiresWinMSVCA;
+@import RequiresWinMSVCB;
+@import RequiresWinMSVCC;
+#endif
diff --git a/test/Modules/templates.mm b/test/Modules/templates.mm
index 95e7a9caea55..6639775986d0 100644
--- a/test/Modules/templates.mm
+++ b/test/Modules/templates.mm
@@ -14,8 +14,8 @@ void testInlineRedeclEarly() {
// CHECK-DAG: @list_left = global %[[LIST:.*]] { %[[LISTNODE:.*]]* null, i32 8 }, align 8
// CHECK-DAG: @list_right = global %[[LIST]] { %[[LISTNODE]]* null, i32 12 }, align 8
-// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 1 }, align 8
-// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 2 }, align 8
+// CHECK-DAG: @__const._Z15testMixedStructv.l = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 1 }, align 8
+// CHECK-DAG: @__const._Z15testMixedStructv.r = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 2 }, align 8
// CHECK-DAG: @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE = external global
void testTemplateClasses() {
@@ -77,10 +77,10 @@ unsigned testMixedStruct() {
// CHECK: %[[l:.*]] = alloca %[[ListInt:[^ ]*]], align 8
// CHECK: %[[r:.*]] = alloca %[[ListInt]], align 8
- // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @_ZZ15testMixedStructvE1l to i8*), i64 16,
+ // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @__const._Z15testMixedStructv.l to i8*), i64 16,
ListInt_left l{0, 1};
- // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @_ZZ15testMixedStructvE1r to i8*), i64 16,
+ // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @__const._Z15testMixedStructv.r to i8*), i64 16,
ListInt_right r{0, 2};
// CHECK: call void @_Z10useListIntR4ListIiE(%[[ListInt]]* dereferenceable({{[0-9]+}}) %[[l]])
diff --git a/test/Modules/unavailable-local-visibility.test b/test/Modules/unavailable-local-visibility.test
new file mode 100644
index 000000000000..10b316a50ec0
--- /dev/null
+++ b/test/Modules/unavailable-local-visibility.test
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fmodules -I%S/Inputs/unavailable-local-visibility -fmodule-name=X -emit-module -x c++-module-map %S/Inputs/unavailable-local-visibility/module.modulemap -o %t/x.pcm
+// RUN: %clang_cc1 -fmodules -I%S/Inputs/unavailable-local-visibility -fmodule-name=M -fmodule-map-file=%S/Inputs/unavailable-local-visibility/module.modulemap -fmodules-local-submodule-visibility -fmodule-file=%t/x.pcm -fsyntax-only -x c++-header %S/Inputs/unavailable-local-visibility/b.h
diff --git a/test/OpenMP/Inputs/declare_target_include.h b/test/OpenMP/Inputs/declare_target_include.h
new file mode 100644
index 000000000000..b74cd00819db
--- /dev/null
+++ b/test/OpenMP/Inputs/declare_target_include.h
@@ -0,0 +1,3 @@
+#pragma omp declare target
+ void zyx();
+#pragma omp end declare target
diff --git a/test/OpenMP/cancel_messages.cpp b/test/OpenMP/cancel_messages.cpp
index 28f22d17eaf5..b14c42f3959f 100644
--- a/test/OpenMP/cancel_messages.cpp
+++ b/test/OpenMP/cancel_messages.cpp
@@ -10,18 +10,18 @@ int main(int argc, char **argv) {
{
#pragma omp cancel // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
}
-#pragma omp cancel parallel untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp cancel'}}
+#pragma omp cancel parallel untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp cancel'}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
#pragma omp cancel unknown // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
#pragma omp parallel
{
#pragma omp cancel unknown // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
}
-#pragma omp cancel sections( // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}}
-#pragma omp cancel for, ) // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}}
-#pragma omp cancel taskgroup() // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}}
-#pragma omp cancel parallel, if // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}}
+#pragma omp cancel sections( // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancel for, ) // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancel taskgroup() // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancel parallel, if // expected-warning {{extra tokens at the end of '#pragma omp cancel' are ignored}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
if (argc)
-#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
if (argc) {
#pragma omp taskgroup
#pragma omp task
@@ -48,44 +48,44 @@ int main(int argc, char **argv) {
#pragma omp cancel parallel // expected-error {{region cannot be closely nested inside 'sections' region}}
}
while (argc)
-#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
while (argc) {
-#pragma omp cancel sections
+#pragma omp cancel sections // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
do
-#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
while (argc)
;
do {
-#pragma omp cancel taskgroup
+#pragma omp cancel taskgroup // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
} while (argc);
switch (argc)
-#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
switch (argc)
case 1:
-#pragma omp cancel sections
+#pragma omp cancel sections // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
switch (argc)
case 1: {
-#pragma omp cancel for
+#pragma omp cancel for // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
switch (argc) {
-#pragma omp cancel taskgroup
+#pragma omp cancel taskgroup // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
case 1:
-#pragma omp cancel parallel
+#pragma omp cancel parallel // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
break;
default: {
-#pragma omp cancel sections
+#pragma omp cancel sections // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
} break;
}
for (;;)
-#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel for // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
for (;;) {
-#pragma omp cancel taskgroup
+#pragma omp cancel taskgroup // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
label:
-#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
+#pragma omp cancel parallel // expected-error {{'#pragma omp cancel' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
label1 : {
-#pragma omp cancel sections
+#pragma omp cancel sections // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
return 0;
diff --git a/test/OpenMP/cancellation_point_messages.cpp b/test/OpenMP/cancellation_point_messages.cpp
index 8bf5b3d55fdd..2bf667c40788 100644
--- a/test/OpenMP/cancellation_point_messages.cpp
+++ b/test/OpenMP/cancellation_point_messages.cpp
@@ -10,18 +10,18 @@ int main(int argc, char **argv) {
{
#pragma omp cancellation point // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
}
-#pragma omp cancellation point parallel untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp cancellation point'}}
+#pragma omp cancellation point parallel untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp cancellation point'}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
#pragma omp cancellation point unknown // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
#pragma omp parallel
{
#pragma omp cancellation point unknown // expected-error {{one of 'for', 'parallel', 'sections' or 'taskgroup' is expected}}
}
-#pragma omp cancellation point sections( // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}}
-#pragma omp cancellation point for, ) // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}}
-#pragma omp cancellation point taskgroup() // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}}
-#pragma omp cancellation point parallel, if // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}}
+#pragma omp cancellation point sections( // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancellation point for, ) // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancellation point taskgroup() // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancellation point parallel, if // expected-warning {{extra tokens at the end of '#pragma omp cancellation point' are ignored}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
if (argc)
-#pragma omp cancellation point for // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point for // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
if (argc) {
#pragma omp taskgroup
#pragma omp task
@@ -48,44 +48,44 @@ int main(int argc, char **argv) {
#pragma omp cancellation point parallel // expected-error {{region cannot be closely nested inside 'sections' region}}
}
while (argc)
-#pragma omp cancellation point for // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point for // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
while (argc) {
-#pragma omp cancellation point sections
+#pragma omp cancellation point sections // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
do
-#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
while (argc)
;
do {
-#pragma omp cancellation point taskgroup
+#pragma omp cancellation point taskgroup // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
} while (argc);
switch (argc)
-#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
switch (argc)
case 1:
-#pragma omp cancellation point sections
+#pragma omp cancellation point sections // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
switch (argc)
case 1: {
-#pragma omp cancellation point for
+#pragma omp cancellation point for // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
switch (argc) {
-#pragma omp cancellation point taskgroup
+#pragma omp cancellation point taskgroup // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
case 1:
-#pragma omp cancellation point parallel
+#pragma omp cancellation point parallel // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
break;
default: {
-#pragma omp cancellation point sections
+#pragma omp cancellation point sections // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
} break;
}
for (;;)
-#pragma omp cancellation point for // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point for // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
for (;;) {
-#pragma omp cancellation point taskgroup
+#pragma omp cancellation point taskgroup // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
label:
-#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
+#pragma omp cancellation point parallel // expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}} expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
label1 : {
-#pragma omp cancellation point sections
+#pragma omp cancellation point sections // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
}
return 0;
diff --git a/test/OpenMP/debug-info-openmp-array.cpp b/test/OpenMP/debug-info-openmp-array.cpp
index e6de4763fbbc..1db79e6cc5ae 100644
--- a/test/OpenMP/debug-info-openmp-array.cpp
+++ b/test/OpenMP/debug-info-openmp-array.cpp
@@ -13,4 +13,4 @@ void f(int m) {
}
}
-// CHECK: !DILocalVariable(name: "cen", arg: 6
+// CHECK: !DILocalVariable(name: "cen", arg: 5
diff --git a/test/OpenMP/declare_reduction_ast_print.cpp b/test/OpenMP/declare_reduction_ast_print.cpp
index a8ca529c456b..6344394cfdbf 100644
--- a/test/OpenMP/declare_reduction_ast_print.cpp
+++ b/test/OpenMP/declare_reduction_ast_print.cpp
@@ -10,6 +10,15 @@
#ifndef HEADER
#define HEADER
+template <typename T>
+void bar(T &x, T &y) { x.a += y.a; }
+
+namespace N1
+{
+ struct A { int a; A() : a(0) {} };
+ #pragma omp declare reduction(+: A : bar(omp_out, omp_in))
+};
+
#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
// CHECK: #pragma omp declare reduction (+ : int : omp_out *= omp_in){{$}}
// CHECK-NEXT: #pragma omp declare reduction (+ : char : omp_out *= omp_in)
@@ -66,6 +75,11 @@ int main() {
// TODO-CHECK: #pragma omp parallel reduction(::fun: sss)
{
}
+ N1::A a;
+ // CHECK: #pragma omp parallel reduction(+: a)
+ #pragma omp parallel reduction(+: a)
+ {
+ }
return foo(15);
}
diff --git a/test/OpenMP/declare_reduction_codegen.cpp b/test/OpenMP/declare_reduction_codegen.cpp
index 90dbd47214df..d0e355cac0e0 100644
--- a/test/OpenMP/declare_reduction_codegen.cpp
+++ b/test/OpenMP/declare_reduction_codegen.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
-// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix=CHECK-LOAD %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple x86_64-linux -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-linux -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-linux -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix=CHECK-LOAD %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -triple x86_64-linux -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-linux -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-linux -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
diff --git a/test/OpenMP/declare_reduction_messages.cpp b/test/OpenMP/declare_reduction_messages.cpp
index f22f92485a57..21c03fac228d 100644
--- a/test/OpenMP/declare_reduction_messages.cpp
+++ b/test/OpenMP/declare_reduction_messages.cpp
@@ -142,17 +142,33 @@ int main() {
#if __cplusplus == 201103L
struct A {
A() {}
- // expected-note@+1 {{copy constructor is implicitly deleted because 'A' has a user-declared move assignment operator}}
A& operator=(A&&) = default;
};
int A_TEST() {
A test;
-// expected-error@+1 {{call to implicitly-deleted copy constructor of 'A'}}
#pragma omp declare reduction(+ : A : omp_out) initializer(omp_priv = A())
-// expected-error@+1 {{invalid operands to binary expression ('A' and 'A')}}
#pragma omp parallel reduction(+ : test)
{}
return 0;
}
+
+struct U
+{
+ void foo(U&, bool);
+ U();
+};
+template <int N>
+struct S
+{
+ int s;
+ // expected-note@+1 {{'foo' declared here}}
+ void foo(S &x) {};
+ // expected-error@+1 {{too many arguments to function call, expected single argument 'x', have 2 arguments}}
+ #pragma omp declare reduction (foo : U, S : omp_out.foo(omp_in, false))
+};
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp declare reduction' are ignored}}
+// expected-note@+1 {{in instantiation of template class 'S<1>' requested here}}
+#pragma omp declare reduction (bar : S<1> : omp_out.foo(omp_in))
+
#endif
diff --git a/test/OpenMP/declare_target_ast_print.cpp b/test/OpenMP/declare_target_ast_print.cpp
index bd1acc28dc6c..613926d5f614 100644
--- a/test/OpenMP/declare_target_ast_print.cpp
+++ b/test/OpenMP/declare_target_ast_print.cpp
@@ -1,15 +1,34 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -I %S/Inputs -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
+int out_decl_target = 0;
+// CHECK: #pragma omp declare target{{$}}
+// CHECK: int out_decl_target = 0;
+// CHECK: #pragma omp end declare target{{$}}
+// CHECK: #pragma omp declare target{{$}}
+// CHECK: void lambda()
+// CHECK: #pragma omp end declare target{{$}}
+
+#pragma omp declare target
+void lambda () {
+#ifdef __cpp_lambdas
+ (void)[&] { ++out_decl_target; };
+#else
+ #pragma clang __debug captured
+ (void)out_decl_target;
+#endif
+};
+#pragma omp end declare target
+
#pragma omp declare target
// CHECK: #pragma omp declare target{{$}}
void foo() {}
@@ -150,11 +169,61 @@ struct SSSTt {
// CHECK: #pragma omp end declare target
// CHECK: int b;
+#pragma omp declare target
+template <typename T>
+T baz() { return T(); }
+#pragma omp end declare target
+
+template <>
+int baz() { return 1; }
+
+// CHECK: #pragma omp declare target
+// CHECK: template <typename T> T baz() {
+// CHECK: return T();
+// CHECK: }
+// CHECK: #pragma omp end declare target
+// CHECK: #pragma omp declare target
+// CHECK: template<> float baz<float>() {
+// CHECK: return float();
+// CHECK: }
+// CHECK: template<> int baz<int>() {
+// CHECK: return 1;
+// CHECK: }
+// CHECK: #pragma omp end declare target
+
+#pragma omp declare target
+ #include "declare_target_include.h"
+ void xyz();
+#pragma omp end declare target
+
+// CHECK: #pragma omp declare target
+// CHECK: void zyx();
+// CHECK: #pragma omp end declare target
+// CHECK: #pragma omp declare target
+// CHECK: void xyz();
+// CHECK: #pragma omp end declare target
+
+#pragma omp declare target
+ #pragma omp declare target
+ void abc();
+ #pragma omp end declare target
+ void cba();
+#pragma omp end declare target
+
+// CHECK: #pragma omp declare target
+// CHECK: void abc();
+// CHECK: #pragma omp end declare target
+// CHECK: #pragma omp declare target
+// CHECK: void cba();
+// CHECK: #pragma omp end declare target
+
int main (int argc, char **argv) {
foo();
foo_c();
foo_cpp();
test1();
+ baz<float>();
+ baz<int>();
return (0);
}
diff --git a/test/OpenMP/declare_target_codegen.cpp b/test/OpenMP/declare_target_codegen.cpp
index 96bdc874ece2..cc7525a44b20 100644
--- a/test/OpenMP/declare_target_codegen.cpp
+++ b/test/OpenMP/declare_target_codegen.cpp
@@ -12,7 +12,17 @@
// SIMD-ONLY-NOT: {{__kmpc|__tgt}}
-// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1}}
+// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1|Base|virtual_}}
+// CHECK-DAG: Bake
+// CHECK-NOT: @{{hhh|ggg|fff|eee}} =
+// CHECK-DAG: @aaa = external global i32,
+// CHECK-DAG: @bbb = global i32 0,
+// CHECK-DAG: @ccc = external global i32,
+// CHECK-DAG: @ddd = global i32 0,
+// CHECK-DAG: @hhh_decl_tgt_link_ptr = common global i32* null
+// CHECK-DAG: @ggg_decl_tgt_link_ptr = common global i32* null
+// CHECK-DAG: @fff_decl_tgt_link_ptr = common global i32* null
+// CHECK-DAG: @eee_decl_tgt_link_ptr = common global i32* null
// CHECK-DAG: @{{.*}}maini1{{.*}}aaa = internal global i64 23,
// CHECK-DAG: @b = global i32 15,
// CHECK-DAG: @d = global i32 0,
@@ -20,17 +30,45 @@
// CHECK-DAG: @globals = global %struct.S zeroinitializer,
// CHECK-DAG: [[STAT:@.+stat]] = internal global %struct.S zeroinitializer,
// CHECK-DAG: [[STAT_REF:@.+]] = internal constant %struct.S* [[STAT]]
-// CHECK-DAG: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @__omp_offloading__{{.+}}_globals_l[[@LINE+42]]_ctor to i8*), i8* bitcast (void ()* @__omp_offloading__{{.+}}_stat_l[[@LINE+43]]_ctor to i8*)],
+// CHECK-DAG: @out_decl_target = global i32 0,
+// CHECK-DAG: @llvm.used = appending global [6 x i8*] [i8* bitcast (void ()* @__omp_offloading__{{.+}}_globals_l[[@LINE+69]]_ctor to i8*), i8* bitcast (void ()* @__omp_offloading__{{.+}}_stat_l[[@LINE+70]]_ctor to i8*),
// CHECK-DAG: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (%struct.S** [[STAT_REF]] to i8*)],
// CHECK-DAG: define {{.*}}i32 @{{.*}}{{foo|bar|baz2|baz3|FA|f_method}}{{.*}}()
// CHECK-DAG: define {{.*}}void @{{.*}}TemplateClass{{.*}}(%class.TemplateClass* %{{.*}})
// CHECK-DAG: define {{.*}}i32 @{{.*}}TemplateClass{{.*}}f_method{{.*}}(%class.TemplateClass* %{{.*}})
-// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_globals_l[[@LINE+36]]_ctor()
+// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_globals_l[[@LINE+63]]_ctor()
#ifndef HEADER
#define HEADER
+#pragma omp declare target
+extern int aaa;
+int bbb = 0;
+extern int ccc;
+int ddd = 0;
+#pragma omp end declare target
+
+extern int eee;
+int fff = 0;
+extern int ggg;
+int hhh = 0;
+#pragma omp declare target link(eee, fff, ggg, hhh)
+
+int out_decl_target = 0;
+#pragma omp declare target
+void lambda () {
+#ifdef __cpp_lambdas
+ (void)[&] { (void)out_decl_target; };
+#else
+#pragma clang __debug captured
+ {
+ (void)out_decl_target;
+ }
+#endif
+};
+#pragma omp end declare target
+
template <typename T>
class TemplateClass {
T a;
@@ -41,7 +79,7 @@ public:
int foo();
-int baz1();
+static int baz1() { return 0; }
int baz2();
@@ -71,7 +109,7 @@ int bar() { return 1 + foo() + bar() + baz1() + baz2(); }
int maini1() {
int a;
- static long aa = 32;
+ static long aa = 32 + bbb + ccc + fff + ggg;
// CHECK-DAG: define weak void @__omp_offloading_{{.*}}maini1{{.*}}_l[[@LINE+1]](i32* dereferenceable{{.*}}, i64 {{.*}}, i64 {{.*}})
#pragma omp target map(tofrom \
: a, b)
@@ -91,5 +129,87 @@ int baz2() {
return 2 + baz3();
}
-// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1}}
+extern int create() throw();
+
+static __typeof(create) __t_create __attribute__((__weakref__("__create")));
+
+int baz5() {
+ bool a;
+// CHECK-DAG: define weak void @__omp_offloading_{{.*}}baz5{{.*}}_l[[@LINE+1]](i64 {{.*}})
+#pragma omp target
+ a = __extension__(void *) & __t_create != 0;
+ return a;
+}
+
+template <typename T>
+struct Base {
+ virtual ~Base() {}
+};
+
+template class Base<int>;
+
+template <typename T>
+struct Bake {
+ virtual ~Bake() {}
+};
+
+#pragma omp declare target
+template class Bake<int>;
+#pragma omp end declare target
+
+struct BaseNonT {
+ virtual ~BaseNonT() {}
+};
+
+#pragma omp declare target
+struct BakeNonT {
+ virtual ~BakeNonT() {}
+};
+#pragma omp end declare target
+
+template <typename T>
+struct B {
+ virtual void virtual_foo();
+};
+
+void new_bar() { new B<int>(); }
+
+template <typename T>
+void B<T>::virtual_foo() {
+#pragma omp target
+ {}
+}
+
+struct A {
+ virtual void emitted() {}
+};
+
+template <typename T>
+struct C : public A {
+ virtual void emitted();
+};
+
+template <typename T>
+void C<T>::emitted() {
+#pragma omp target
+ {}
+}
+
+int main() {
+ A *X = new C<int>();
+ X->emitted();
+ return 0;
+}
+
+// CHECK-DAG: define {{.*}}void @__omp_offloading_{{.*}}virtual_foo{{.*}}_l[[@LINE-25]]()
+// CHECK-DAG: define {{.*}}void @__omp_offloading_{{.*}}emitted{{.*}}_l[[@LINE-11]]()
+
+// CHECK-DAG: declare extern_weak signext i32 @__create()
+
+// CHECK-NOT: define {{.*}}{{baz1|baz4|maini1|Base|virtual_}}
+
+// CHECK-DAG: !{i32 1, !"aaa", i32 0, i32 {{[0-9]+}}}
+// CHECK-DAG: !{i32 1, !"ccc", i32 0, i32 {{[0-9]+}}}
+// CHECK-DAG: !{{{.+}}virtual_foo
+
#endif // HEADER
diff --git a/test/OpenMP/declare_target_codegen_globalization.cpp b/test/OpenMP/declare_target_codegen_globalization.cpp
index 7ef4f8af3dec..06d7e5ce6456 100644
--- a/test/OpenMP/declare_target_codegen_globalization.cpp
+++ b/test/OpenMP/declare_target_codegen_globalization.cpp
@@ -10,7 +10,7 @@ int bar() {
}
// CHECK: define weak void @__omp_offloading_{{.*}}maini1{{.*}}_l[[@LINE+5]](i32* dereferenceable{{.*}})
-// CHECK-NOT: @__kmpc_data_sharing_push_stack
+// CHECK-NOT: @__kmpc_data_sharing_coalesced_push_stack
int maini1() {
int a;
@@ -24,7 +24,7 @@ int maini1() {
// parallel region
// CHECK: define {{.*}}void @{{.*}}(i32* noalias {{.*}}, i32* noalias {{.*}}, i32* dereferenceable{{.*}})
-// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack(
+// CHECK-NOT: call i8* @__kmpc_data_sharing_coalesced_push_stack(
// CHECK: [[B_ADDR:%.+]] = alloca i32,
// CHECK: call {{.*}}[[FOO:@.*foo.*]](i32* dereferenceable{{.*}} [[B_ADDR]])
// CHECK: call {{.*}}[[BAR:@.*bar.*]]()
@@ -32,12 +32,27 @@ int maini1() {
// CHECK: ret void
// CHECK: define {{.*}}[[FOO]](i32* dereferenceable{{.*}})
-// CHECK-NOT: @__kmpc_data_sharing_push_stack
+// CHECK-NOT: @__kmpc_data_sharing_coalesced_push_stack
// CHECK: define {{.*}}[[BAR]]()
-// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 4, i16 0)
-// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_ST:%struct[.].*]]*
-// CHECK: [[A_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_ST]], [[GLOBAL_ST]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: alloca i32,
+// CHECK: [[A_LOCAL_ADDR:%.+]] = alloca i32,
+// CHECK: [[RES:%.+]] = call i8 @__kmpc_is_spmd_exec_mode()
+// CHECK: [[IS_SPMD:%.+]] = icmp ne i8 [[RES]], 0
+// CHECK: br i1 [[IS_SPMD]], label
+// CHECK: br label
+// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_coalesced_push_stack(i64 128, i16 0)
+// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_ST:%.+]]*
+// CHECK: br label
+// CHECK: [[ITEMS:%.+]] = phi [[GLOBAL_ST]]* [ null, {{.+}} ], [ [[GLOBALS]], {{.+}} ]
+// CHECK: [[A_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_ST]], [[GLOBAL_ST]]* [[ITEMS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+// CHECK: [[LID:%.+]] = and i32 [[TID]], 31
+// CHECK: [[A_GLOBAL_ADDR:%.+]] = getelementptr inbounds [32 x i32], [32 x i32]* [[A_ADDR]], i32 0, i32 [[LID]]
+// CHECK: [[A_ADDR:%.+]] = select i1 [[IS_SPMD]], i32* [[A_LOCAL_ADDR]], i32* [[A_GLOBAL_ADDR]]
// CHECK: call {{.*}}[[FOO]](i32* dereferenceable{{.*}} [[A_ADDR]])
-// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]])
+// CHECK: br i1 [[IS_SPMD]], label
+// CHECK: [[BC:%.+]] = bitcast [[GLOBAL_ST]]* [[ITEMS]] to i8*
+// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[BC]])
+// CHECK: br label
// CHECK: ret i32
diff --git a/test/OpenMP/declare_target_link_codegen.cpp b/test/OpenMP/declare_target_link_codegen.cpp
index fdecd728ce68..564581c2592a 100644
--- a/test/OpenMP/declare_target_link_codegen.cpp
+++ b/test/OpenMP/declare_target_link_codegen.cpp
@@ -17,10 +17,10 @@
#ifndef HEADER
#define HEADER
-// HOST: @c = external global i32,
+// HOST-DAG: @c = external global i32,
+// HOST-DAG: @c_decl_tgt_link_ptr = global i32* @c
// DEVICE-NOT: @c =
// DEVICE: @c_decl_tgt_link_ptr = common global i32* null
-// HOST: @c_decl_tgt_link_ptr = global i32* @c
// HOST: [[SIZES:@.+]] = private unnamed_addr constant [2 x i64] [i64 4, i64 4]
// HOST: [[MAPTYPES:@.+]] = private unnamed_addr constant [2 x i64] [i64 35, i64 531]
// HOST: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_link_ptr\00"
diff --git a/test/OpenMP/declare_target_messages.cpp b/test/OpenMP/declare_target_messages.cpp
index c8e73f6efbd7..0c001d265f9f 100644
--- a/test/OpenMP/declare_target_messages.cpp
+++ b/test/OpenMP/declare_target_messages.cpp
@@ -4,7 +4,7 @@
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
-int a, b; // expected-warning {{declaration is not declared in any declare target region}}
+int a, b;
__thread int t; // expected-note {{defined as threadprivate or thread local}}
#pragma omp declare target . // expected-error {{expected '(' after 'declare target'}}
@@ -59,8 +59,19 @@ void t2() {
}
}
+#pragma omp declare target
+ void abc();
+#pragma omp end declare target
+void cba();
+#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
-#pragma omp declare target // expected-note {{to match this '#pragma omp declare target'}}
+#pragma omp declare target
+ #pragma omp declare target
+ void def();
+ #pragma omp end declare target
+ void fed();
+
+#pragma omp declare target
#pragma omp threadprivate(a) // expected-note {{defined as threadprivate or thread local}}
extern int b;
int g;
@@ -90,7 +101,7 @@ int C::method1() {
void foo(int p) {
a = 0; // expected-error {{threadprivate variables cannot be used in target constructs}}
- b = 0; // expected-note {{used here}}
+ b = 0;
t = 1; // expected-error {{threadprivate variables cannot be used in target constructs}}
C object;
VC object1;
@@ -100,9 +111,12 @@ void foo(int p) {
f();
c();
}
-#pragma omp declare target // expected-error {{expected '#pragma omp end declare target'}}
+#pragma omp declare target
void foo1() {}
#pragma omp end declare target
+
+#pragma omp end declare target
+#pragma omp end declare target
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
int C::method() {
diff --git a/test/OpenMP/distribute_ast_print.cpp b/test/OpenMP/distribute_ast_print.cpp
index f675814e57a5..1bd0a41662fe 100644
--- a/test/OpenMP/distribute_ast_print.cpp
+++ b/test/OpenMP/distribute_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_codegen.cpp b/test/OpenMP/distribute_codegen.cpp
index fe89ee0c1bdb..9641b8a1359b 100644
--- a/test/OpenMP/distribute_codegen.cpp
+++ b/test/OpenMP/distribute_codegen.cpp
@@ -40,8 +40,8 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
-// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-LABEL: define {{.*void}} @{{.*}}without_schedule_clause{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
void without_schedule_clause(float *a, float *b, float *c, float *d) {
diff --git a/test/OpenMP/distribute_firstprivate_codegen.cpp b/test/OpenMP/distribute_firstprivate_codegen.cpp
index 29d44fde92f2..d7fdd1c0acd4 100644
--- a/test/OpenMP/distribute_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_firstprivate_codegen.cpp
@@ -1,31 +1,31 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_firstprivate_messages.cpp b/test/OpenMP/distribute_firstprivate_messages.cpp
index ea0e7b4a2314..8acc6b643f09 100644
--- a/test/OpenMP/distribute_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_firstprivate_messages.cpp
@@ -93,7 +93,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
- #pragma omp distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ #pragma omp distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'const S3' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
@@ -101,11 +101,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
- #pragma omp distribute firstprivate(ba)
+ #pragma omp distribute firstprivate(ba) // expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
- #pragma omp distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
+ #pragma omp distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}} expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
diff --git a/test/OpenMP/distribute_lastprivate_codegen.cpp b/test/OpenMP/distribute_lastprivate_codegen.cpp
index 66a860b7152e..175f3c8bde26 100644
--- a/test/OpenMP/distribute_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_lastprivate_codegen.cpp
@@ -1,31 +1,31 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_parallel_for_ast_print.cpp b/test/OpenMP/distribute_parallel_for_ast_print.cpp
index 58e6eb8aa77a..5cfc08173752 100644
--- a/test/OpenMP/distribute_parallel_for_ast_print.cpp
+++ b/test/OpenMP/distribute_parallel_for_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -std=c++11 -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -std=c++11 -fopenmp -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -std=c++11 -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -std=c++11 -fopenmp-simd -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_parallel_for_codegen.cpp b/test/OpenMP/distribute_parallel_for_codegen.cpp
index a7700a3421ac..6b57290f32ef 100644
--- a/test/OpenMP/distribute_parallel_for_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_codegen.cpp
@@ -406,19 +406,27 @@ int main() {
for (int i = 0; i < n; ++i) {
a[i] = b[i] + c[i];
// LAMBDA: define{{.+}} void [[OMP_OUTLINED_3]](
- // LAMBDA-DAG: [[OMP_IV:%.omp.iv]] = alloca
- // LAMBDA-DAG: [[OMP_LB:%.omp.comb.lb]] = alloca
- // LAMBDA-DAG: [[OMP_UB:%.omp.comb.ub]] = alloca
- // LAMBDA-DAG: [[OMP_ST:%.omp.stride]] = alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[OMP_IV:%.+]] = alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[OMP_LB:%.+]] = alloca
+ // LAMBDA: [[OMP_UB:%.+]] = alloca
+ // LAMBDA: [[OMP_ST:%.+]] = alloca
- // unlike the previous tests, in this one we have a outer and inner loop for 'distribute'
// LAMBDA: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91,
- // LAMBDA: br label %[[DIST_OUTER_LOOP_HEADER:.+]]
- // LAMBDA: [[DIST_OUTER_LOOP_HEADER]]:
// check EUB for distribute
// LAMBDA-DAG: [[OMP_UB_VAL_1:%.+]] = load{{.+}} [[OMP_UB]],
- // LAMBDA: [[NUM_IT_1:%.+]] = load{{.+}},
+ // LAMBDA: [[NUM_IT_1:%.+]] = load{{.+}}
// LAMBDA-DAG: [[CMP_UB_NUM_IT:%.+]] = icmp sgt {{.+}} [[OMP_UB_VAL_1]], [[NUM_IT_1]]
// LAMBDA: br {{.+}} [[CMP_UB_NUM_IT]], label %[[EUB_TRUE:.+]], label %[[EUB_FALSE:.+]]
// LAMBDA-DAG: [[EUB_TRUE]]:
@@ -437,18 +445,10 @@ int main() {
// check exit condition
// LAMBDA-DAG: [[OMP_IV_VAL_1:%.+]] = load {{.+}} [[OMP_IV]],
- // LAMBDA-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}} [[OMP_UB]],
- // LAMBDA: [[CMP_IV_UB:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3]]
- // LAMBDA: br {{.+}} [[CMP_IV_UB]], label %[[DIST_OUTER_LOOP_BODY:.+]], label %[[DIST_OUTER_LOOP_END:.+]]
-
- // LAMBDA: [[DIST_OUTER_LOOP_BODY]]:
- // LAMBDA: br label %[[DIST_INNER_LOOP_HEADER:.+]]
-
- // LAMBDA: [[DIST_INNER_LOOP_HEADER]]:
- // LAMBDA-DAG: [[OMP_IV_VAL_2:%.+]] = load {{.+}} [[OMP_IV]],
- // LAMBDA-DAG: [[OMP_UB_VAL_4:%.+]] = load {{.+}} [[OMP_UB]],
- // LAMBDA: [[CMP_IV_UB_2:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_2]], [[OMP_UB_VAL_4]]
- // LAMBDA: br{{.+}} [[CMP_IV_UB_2]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
+ // LAMBDA-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}}
+ // LAMBDA-DAG: [[OMP_UB_VAL_3_PLUS_ONE:%.+]] = add {{.+}} [[OMP_UB_VAL_3]], 1
+ // LAMBDA: [[CMP_IV_UB:%.+]] = icmp slt {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3_PLUS_ONE]]
+ // LAMBDA: br {{.+}} [[CMP_IV_UB]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
// check that PrevLB and PrevUB are passed to the 'for'
// LAMBDA: [[DIST_INNER_LOOP_BODY]]:
@@ -467,13 +467,6 @@ int main() {
// LAMBDA-DAG: [[OMP_ST_VAL_1:%.+]] = load {{.+}}, {{.+}}* [[OMP_ST]],
// LAMBDA: [[OMP_IV_INC:%.+]] = add{{.+}} [[OMP_IV_VAL_3]], [[OMP_ST_VAL_1]]
// LAMBDA: store{{.+}} [[OMP_IV_INC]], {{.+}}* [[OMP_IV]],
- // LAMBDA: br label %[[DIST_INNER_LOOP_HEADER]]
-
- // LAMBDA: [[DIST_INNER_LOOP_END]]:
- // LAMBDA: br label %[[DIST_OUTER_LOOP_INC:.+]]
-
- // LAMBDA: [[DIST_OUTER_LOOP_INC]]:
- // check NextLB and NextUB
// LAMBDA-DAG: [[OMP_LB_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
// LAMBDA-DAG: [[OMP_ST_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// LAMBDA-DAG: [[OMP_LB_NEXT:%.+]] = add{{.+}} [[OMP_LB_VAL_2]], [[OMP_ST_VAL_2]]
@@ -482,10 +475,31 @@ int main() {
// LAMBDA-DAG: [[OMP_ST_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// LAMBDA-DAG: [[OMP_UB_NEXT:%.+]] = add{{.+}} [[OMP_UB_VAL_5]], [[OMP_ST_VAL_3]]
// LAMBDA: store{{.+}} [[OMP_UB_NEXT]], {{.+}}* [[OMP_UB]],
- // LAMBDA: br label %[[DIST_OUTER_LOOP_HEADER]]
- // outer loop exit
- // LAMBDA: [[DIST_OUTER_LOOP_END]]:
+ // Update UB
+ // LAMBDA-DAG: [[OMP_UB_VAL_6:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+ // LAMBDA: [[OMP_EXPR_VAL:%.+]] = load{{.+}}, {{.+}}
+ // LAMBDA-DAG: [[CMP_UB_NUM_IT_1:%.+]] = icmp sgt {{.+}}[[OMP_UB_VAL_6]], [[OMP_EXPR_VAL]]
+ // LAMBDA: br {{.+}} [[CMP_UB_NUM_IT_1]], label %[[EUB_TRUE_1:.+]], label %[[EUB_FALSE_1:.+]]
+ // LAMBDA-DAG: [[EUB_TRUE_1]]:
+ // LAMBDA: [[NUM_IT_3:%.+]] = load{{.+}}
+ // LAMBDA: br label %[[EUB_END_1:.+]]
+ // LAMBDA-DAG: [[EUB_FALSE_1]]:
+ // LAMBDA: [[OMP_UB_VAL3:%.+]] = load{{.+}} [[OMP_UB]],
+ // LAMBDA: br label %[[EUB_END_1]]
+ // LAMBDA-DAG: [[EUB_END_1]]:
+ // LAMBDA-DAG: [[EUB_RES_1:%.+]] = phi{{.+}} [ [[NUM_IT_3]], %[[EUB_TRUE_1]] ], [ [[OMP_UB_VAL3]], %[[EUB_FALSE_1]] ]
+ // LAMBDA: store{{.+}} [[EUB_RES_1]], {{.+}}* [[OMP_UB]],
+
+ // Store LB in IV
+ // LAMBDA-DAG: [[OMP_LB_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+ // LAMBDA: store{{.+}} [[OMP_LB_VAL_3]], {{.+}}* [[OMP_IV]],
+
+ // LAMBDA: [[DIST_INNER_LOOP_END]]:
+ // LAMBDA: br label %[[LOOP_EXIT:.+]]
+
+ // loop exit
+ // LAMBDA: [[LOOP_EXIT]]:
// LAMBDA-DAG: call void @__kmpc_for_static_fini(
// LAMBDA: ret
@@ -1154,19 +1168,28 @@ int main() {
for (int i = 0; i < n; ++i) {
a[i] = b[i] + c[i];
// CHECK: define{{.+}} void [[OMP_OUTLINED_3]](
- // CHECK-DAG: [[OMP_IV:%.omp.iv]] = alloca
- // CHECK-DAG: [[OMP_LB:%.omp.comb.lb]] = alloca
- // CHECK-DAG: [[OMP_UB:%.omp.comb.ub]] = alloca
- // CHECK-DAG: [[OMP_ST:%.omp.stride]] = alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: [[OMP_IV:%.+]] = alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: [[OMP_LB:%.+]] = alloca
+ // CHECK: [[OMP_UB:%.+]] = alloca
+ // CHECK: [[OMP_ST:%.+]] = alloca
// unlike the previous tests, in this one we have a outer and inner loop for 'distribute'
// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91,
- // CHECK: br label %[[DIST_OUTER_LOOP_HEADER:.+]]
- // CHECK: [[DIST_OUTER_LOOP_HEADER]]:
// check EUB for distribute
// CHECK-DAG: [[OMP_UB_VAL_1:%.+]] = load{{.+}} [[OMP_UB]],
- // CHECK: [[NUM_IT_1:%.+]] = load{{.+}},
+ // CHECK: [[NUM_IT_1:%.+]] = load{{.+}}
// CHECK-DAG: [[CMP_UB_NUM_IT:%.+]] = icmp sgt {{.+}} [[OMP_UB_VAL_1]], [[NUM_IT_1]]
// CHECK: br {{.+}} [[CMP_UB_NUM_IT]], label %[[EUB_TRUE:.+]], label %[[EUB_FALSE:.+]]
// CHECK-DAG: [[EUB_TRUE]]:
@@ -1185,18 +1208,10 @@ int main() {
// check exit condition
// CHECK-DAG: [[OMP_IV_VAL_1:%.+]] = load {{.+}} [[OMP_IV]],
- // CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}} [[OMP_UB]],
- // CHECK: [[CMP_IV_UB:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3]]
- // CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_OUTER_LOOP_BODY:.+]], label %[[DIST_OUTER_LOOP_END:.+]]
-
- // CHECK: [[DIST_OUTER_LOOP_BODY]]:
- // CHECK: br label %[[DIST_INNER_LOOP_HEADER:.+]]
-
- // CHECK: [[DIST_INNER_LOOP_HEADER]]:
- // CHECK-DAG: [[OMP_IV_VAL_2:%.+]] = load {{.+}} [[OMP_IV]],
- // CHECK-DAG: [[OMP_UB_VAL_4:%.+]] = load {{.+}} [[OMP_UB]],
- // CHECK: [[CMP_IV_UB_2:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_2]], [[OMP_UB_VAL_4]]
- // CHECK: br{{.+}} [[CMP_IV_UB_2]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
+ // CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}}
+ // CHECK-DAG: [[OMP_UB_VAL_3_PLUS_ONE:%.+]] = add {{.+}} [[OMP_UB_VAL_3]], 1
+ // CHECK: [[CMP_IV_UB:%.+]] = icmp slt {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3_PLUS_ONE]]
+ // CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
// check that PrevLB and PrevUB are passed to the 'for'
// CHECK: [[DIST_INNER_LOOP_BODY]]:
@@ -1215,13 +1230,6 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_1:%.+]] = load {{.+}}, {{.+}}* [[OMP_ST]],
// CHECK: [[OMP_IV_INC:%.+]] = add{{.+}} [[OMP_IV_VAL_3]], [[OMP_ST_VAL_1]]
// CHECK: store{{.+}} [[OMP_IV_INC]], {{.+}}* [[OMP_IV]],
- // CHECK: br label %[[DIST_INNER_LOOP_HEADER]]
-
- // CHECK: [[DIST_INNER_LOOP_END]]:
- // CHECK: br label %[[DIST_OUTER_LOOP_INC:.+]]
-
- // CHECK: [[DIST_OUTER_LOOP_INC]]:
- // check NextLB and NextUB
// CHECK-DAG: [[OMP_LB_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
// CHECK-DAG: [[OMP_ST_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_LB_NEXT:%.+]] = add{{.+}} [[OMP_LB_VAL_2]], [[OMP_ST_VAL_2]]
@@ -1230,10 +1238,31 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_UB_NEXT:%.+]] = add{{.+}} [[OMP_UB_VAL_5]], [[OMP_ST_VAL_3]]
// CHECK: store{{.+}} [[OMP_UB_NEXT]], {{.+}}* [[OMP_UB]],
- // CHECK: br label %[[DIST_OUTER_LOOP_HEADER]]
- // outer loop exit
- // CHECK: [[DIST_OUTER_LOOP_END]]:
+ // Update UB
+ // CHECK-DAG: [[OMP_UB_VAL_6:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+ // CHECK: [[OMP_EXPR_VAL:%.+]] = load{{.+}}, {{.+}}
+ // CHECK-DAG: [[CMP_UB_NUM_IT_1:%.+]] = icmp sgt {{.+}}[[OMP_UB_VAL_6]], [[OMP_EXPR_VAL]]
+ // CHECK: br {{.+}} [[CMP_UB_NUM_IT_1]], label %[[EUB_TRUE_1:.+]], label %[[EUB_FALSE_1:.+]]
+ // CHECK-DAG: [[EUB_TRUE_1]]:
+ // CHECK: [[NUM_IT_3:%.+]] = load{{.+}}
+ // CHECK: br label %[[EUB_END_1:.+]]
+ // CHECK-DAG: [[EUB_FALSE_1]]:
+ // CHECK: [[OMP_UB_VAL3:%.+]] = load{{.+}} [[OMP_UB]],
+ // CHECK: br label %[[EUB_END_1]]
+ // CHECK-DAG: [[EUB_END_1]]:
+ // CHECK-DAG: [[EUB_RES_1:%.+]] = phi{{.+}} [ [[NUM_IT_3]], %[[EUB_TRUE_1]] ], [ [[OMP_UB_VAL3]], %[[EUB_FALSE_1]] ]
+ // CHECK: store{{.+}} [[EUB_RES_1]], {{.+}}* [[OMP_UB]],
+
+ // Store LB in IV
+ // CHECK-DAG: [[OMP_LB_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+ // CHECK: store{{.+}} [[OMP_LB_VAL_3]], {{.+}}* [[OMP_IV]],
+
+ // CHECK: [[DIST_INNER_LOOP_END]]:
+ // CHECK: br label %[[LOOP_EXIT:.+]]
+
+ // loop exit
+ // CHECK: [[LOOP_EXIT]]:
// CHECK-DAG: call void @__kmpc_for_static_fini(
// CHECK: ret
@@ -1867,19 +1896,28 @@ int main() {
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 5, {{.+}}* [[OMP_OUTLINED_3:@.+]] to {{.+}})
// CHECK: define{{.+}} void [[OMP_OUTLINED_3]](
-// CHECK-DAG: [[OMP_IV:%.omp.iv]] = alloca
-// CHECK-DAG: [[OMP_LB:%.omp.comb.lb]] = alloca
-// CHECK-DAG: [[OMP_UB:%.omp.comb.ub]] = alloca
-// CHECK-DAG: [[OMP_ST:%.omp.stride]] = alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: [[OMP_IV:%.+]] = alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: [[OMP_LB:%.+]] = alloca
+// CHECK: [[OMP_UB:%.+]] = alloca
+// CHECK: [[OMP_ST:%.+]] = alloca
// unlike the previous tests, in this one we have a outer and inner loop for 'distribute'
// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91,
-// CHECK: br label %[[DIST_OUTER_LOOP_HEADER:.+]]
-// CHECK: [[DIST_OUTER_LOOP_HEADER]]:
// check EUB for distribute
// CHECK-DAG: [[OMP_UB_VAL_1:%.+]] = load{{.+}} [[OMP_UB]],
-// CHECK: [[NUM_IT_1:%.+]] = load{{.+}},
+// CHECK: [[NUM_IT_1:%.+]] = load{{.+}}
// CHECK-DAG: [[CMP_UB_NUM_IT:%.+]] = icmp sgt {{.+}} [[OMP_UB_VAL_1]], [[NUM_IT_1]]
// CHECK: br {{.+}} [[CMP_UB_NUM_IT]], label %[[EUB_TRUE:.+]], label %[[EUB_FALSE:.+]]
// CHECK-DAG: [[EUB_TRUE]]:
@@ -1898,18 +1936,10 @@ int main() {
// check exit condition
// CHECK-DAG: [[OMP_IV_VAL_1:%.+]] = load {{.+}} [[OMP_IV]],
-// CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}} [[OMP_UB]],
-// CHECK: [[CMP_IV_UB:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3]]
-// CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_OUTER_LOOP_BODY:.+]], label %[[DIST_OUTER_LOOP_END:.+]]
-
-// CHECK: [[DIST_OUTER_LOOP_BODY]]:
-// CHECK: br label %[[DIST_INNER_LOOP_HEADER:.+]]
-
-// CHECK: [[DIST_INNER_LOOP_HEADER]]:
-// CHECK-DAG: [[OMP_IV_VAL_2:%.+]] = load {{.+}} [[OMP_IV]],
-// CHECK-DAG: [[OMP_UB_VAL_4:%.+]] = load {{.+}} [[OMP_UB]],
-// CHECK: [[CMP_IV_UB_2:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_2]], [[OMP_UB_VAL_4]]
-// CHECK: br{{.+}} [[CMP_IV_UB_2]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
+// CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}}
+// CHECK-DAG: [[OMP_UB_VAL_3_PLUS_ONE:%.+]] = add {{.+}} [[OMP_UB_VAL_3]], 1
+// CHECK: [[CMP_IV_UB:%.+]] = icmp slt {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3_PLUS_ONE]]
+// CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
// check that PrevLB and PrevUB are passed to the 'for'
// CHECK: [[DIST_INNER_LOOP_BODY]]:
@@ -1928,13 +1958,6 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_1:%.+]] = load {{.+}}, {{.+}}* [[OMP_ST]],
// CHECK: [[OMP_IV_INC:%.+]] = add{{.+}} [[OMP_IV_VAL_3]], [[OMP_ST_VAL_1]]
// CHECK: store{{.+}} [[OMP_IV_INC]], {{.+}}* [[OMP_IV]],
-// CHECK: br label %[[DIST_INNER_LOOP_HEADER]]
-
-// CHECK: [[DIST_INNER_LOOP_END]]:
-// CHECK: br label %[[DIST_OUTER_LOOP_INC:.+]]
-
-// CHECK: [[DIST_OUTER_LOOP_INC]]:
-// check NextLB and NextUB
// CHECK-DAG: [[OMP_LB_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
// CHECK-DAG: [[OMP_ST_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_LB_NEXT:%.+]] = add{{.+}} [[OMP_LB_VAL_2]], [[OMP_ST_VAL_2]]
@@ -1943,10 +1966,31 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_UB_NEXT:%.+]] = add{{.+}} [[OMP_UB_VAL_5]], [[OMP_ST_VAL_3]]
// CHECK: store{{.+}} [[OMP_UB_NEXT]], {{.+}}* [[OMP_UB]],
-// CHECK: br label %[[DIST_OUTER_LOOP_HEADER]]
-// outer loop exit
-// CHECK: [[DIST_OUTER_LOOP_END]]:
+// Update UB
+// CHECK-DAG: [[OMP_UB_VAL_6:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+// CHECK: [[OMP_EXPR_VAL:%.+]] = load{{.+}}, {{.+}}
+// CHECK-DAG: [[CMP_UB_NUM_IT_1:%.+]] = icmp sgt {{.+}}[[OMP_UB_VAL_6]], [[OMP_EXPR_VAL]]
+// CHECK: br {{.+}} [[CMP_UB_NUM_IT_1]], label %[[EUB_TRUE_1:.+]], label %[[EUB_FALSE_1:.+]]
+// CHECK-DAG: [[EUB_TRUE_1]]:
+// CHECK: [[NUM_IT_3:%.+]] = load{{.+}}
+// CHECK: br label %[[EUB_END_1:.+]]
+// CHECK-DAG: [[EUB_FALSE_1]]:
+// CHECK: [[OMP_UB_VAL3:%.+]] = load{{.+}} [[OMP_UB]],
+// CHECK: br label %[[EUB_END_1]]
+// CHECK-DAG: [[EUB_END_1]]:
+// CHECK-DAG: [[EUB_RES_1:%.+]] = phi{{.+}} [ [[NUM_IT_3]], %[[EUB_TRUE_1]] ], [ [[OMP_UB_VAL3]], %[[EUB_FALSE_1]] ]
+// CHECK: store{{.+}} [[EUB_RES_1]], {{.+}}* [[OMP_UB]],
+
+// Store LB in IV
+// CHECK-DAG: [[OMP_LB_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+// CHECK: store{{.+}} [[OMP_LB_VAL_3]], {{.+}}* [[OMP_IV]],
+
+// CHECK: [[DIST_INNER_LOOP_END]]:
+// CHECK: br label %[[LOOP_EXIT:.+]]
+
+// loop exit
+// CHECK: [[LOOP_EXIT]]:
// CHECK-DAG: call void @__kmpc_for_static_fini(
// CHECK: ret
diff --git a/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
index e4915acf69b6..705418276856 100644
--- a/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
@@ -1,30 +1,30 @@
-// RxUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp
index 63f4dbec1786..35579d35377e 100644
--- a/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp
@@ -110,7 +110,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+#pragma omp distribute parallel for firstprivate(a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -120,7 +120,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -232,7 +232,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+#pragma omp distribute parallel for firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'const S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -247,12 +247,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(ba) // OK
+#pragma omp distribute parallel for firstprivate(ba) // expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(ca) // OK
+#pragma omp distribute parallel for firstprivate(ca) // expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -283,12 +283,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(m) // OK
+#pragma omp distribute parallel for firstprivate(m) // expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -320,13 +320,13 @@ int main(int argc, char **argv) {
// expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(g) firstprivate(g)
+#pragma omp distribute parallel for lastprivate(g) firstprivate(g) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
// expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}}
+#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Non-trivial type 'S6' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
diff --git a/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
index dda8c932908e..b10c02ba7964 100644
--- a/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
@@ -1,31 +1,31 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp
index c8eaad8cf147..8d93fbbee6d2 100644
--- a/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -112,7 +112,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+#pragma omp distribute parallel for lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -122,7 +122,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+#pragma omp distribute parallel for lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} expected-warning 2 {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -171,8 +171,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -221,7 +221,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'const S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -236,17 +236,17 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(ba)
+#pragma omp distribute parallel for lastprivate(ba) // expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}} expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -262,7 +262,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -272,12 +272,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+#pragma omp distribute parallel for lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+#pragma omp distribute parallel for lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -318,13 +318,13 @@ int main(int argc, char **argv) {
// expected-error@+3 {{firstprivate variable cannot be lastprivate}} expected-note@+3 {{defined as firstprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for firstprivate(m) lastprivate(m)
+#pragma omp distribute parallel for firstprivate(m) lastprivate(m) // expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
// expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}}
+#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Non-trivial type 'S6' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
static int si;
diff --git a/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp b/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
index 21d094945427..8d941391c75b 100644
--- a/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
@@ -15,7 +15,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[S_TY:%.+]] = type { [[INTPTR_T_TY:i[0-9]+]], [[INTPTR_T_TY]], [[INTPTR_T_TY]] }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/distribute_parallel_for_private_messages.cpp b/test/OpenMP/distribute_parallel_for_private_messages.cpp
index 75fe47ae8204..63d89a8c7c0b 100644
--- a/test/OpenMP/distribute_parallel_for_private_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_private_messages.cpp
@@ -49,7 +49,7 @@ public:
#pragma omp target
#pragma omp teams
#pragma omp distribute parallel for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp b/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
index fce005be80fb..3e2a65e47f0e 100644
--- a/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
@@ -16,7 +16,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/distribute_parallel_for_reduction_messages.cpp
index 21a1eb40608d..e6be867f151a 100644
--- a/test/OpenMP/distribute_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_reduction_messages.cpp
@@ -160,12 +160,12 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-warning 2 {{Non-trivial type 'S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning 2 {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -175,17 +175,17 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -200,12 +200,12 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+#pragma omp distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}} expected-warning 2 {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -231,7 +231,7 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -344,12 +344,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -359,17 +359,17 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctl}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -384,22 +384,22 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+#pragma omp distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+#pragma omp distribute parallel for reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : o) // expected-error {{no viable overloaded '='}}
+#pragma omp distribute parallel for reduction(+ : o) // expected-error {{no viable overloaded '='}} expected-warning {{Non-trivial type 'class S6' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -410,17 +410,17 @@ int main(int argc, char **argv) {
#pragma omp parallel private(k)
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/distribute_parallel_for_shared_messages.cpp b/test/OpenMP/distribute_parallel_for_shared_messages.cpp
index 01c582cdbd44..6700b80cad3d 100644
--- a/test/OpenMP/distribute_parallel_for_shared_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_shared_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wno-openmp-target
-// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wno-openmp-target
struct S1; // expected-note 2 {{declared here}}
@@ -117,7 +117,7 @@ T tmain(T argc, S **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for shared (a, b, c, d, f)
+#pragma omp distribute parallel for shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
@@ -291,7 +291,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for shared (a, b, c, d, f)
+#pragma omp distribute parallel for shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
index 0c94f5b12d0c..40d72418c721 100644
--- a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
@@ -287,7 +287,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd aligned (a, b) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}}
+#pragma omp distribute parallel for simd aligned (a, b) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp b/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
index fff6f965b4c2..4ff0a4929066 100644
--- a/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
index 129d90b746c4..66576e1e8e24 100644
--- a/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
@@ -405,19 +405,27 @@ int main() {
for (int i = 0; i < n; ++i) {
a[i] = b[i] + c[i];
// LAMBDA: define{{.+}} void [[OMP_OUTLINED_3]](
- // LAMBDA-DAG: [[OMP_IV:%.omp.iv]] = alloca
- // LAMBDA-DAG: [[OMP_LB:%.omp.comb.lb]] = alloca
- // LAMBDA-DAG: [[OMP_UB:%.omp.comb.ub]] = alloca
- // LAMBDA-DAG: [[OMP_ST:%.omp.stride]] = alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[OMP_IV:%.+]] = alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: alloca
+ // LAMBDA: [[OMP_LB:%.+]] = alloca
+ // LAMBDA: [[OMP_UB:%.+]] = alloca
+ // LAMBDA: [[OMP_ST:%.+]] = alloca
- // unlike the previous tests, in this one we have a outer and inner loop for 'distribute'
// LAMBDA: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91,
- // LAMBDA: br label %[[DIST_OUTER_LOOP_HEADER:.+]]
- // LAMBDA: [[DIST_OUTER_LOOP_HEADER]]:
// check EUB for distribute
// LAMBDA-DAG: [[OMP_UB_VAL_1:%.+]] = load{{.+}} [[OMP_UB]],
- // LAMBDA: [[NUM_IT_1:%.+]] = load{{.+}},
+ // LAMBDA: [[NUM_IT_1:%.+]] = load{{.+}}
// LAMBDA-DAG: [[CMP_UB_NUM_IT:%.+]] = icmp sgt {{.+}} [[OMP_UB_VAL_1]], [[NUM_IT_1]]
// LAMBDA: br {{.+}} [[CMP_UB_NUM_IT]], label %[[EUB_TRUE:.+]], label %[[EUB_FALSE:.+]]
// LAMBDA-DAG: [[EUB_TRUE]]:
@@ -436,18 +444,10 @@ int main() {
// check exit condition
// LAMBDA-DAG: [[OMP_IV_VAL_1:%.+]] = load {{.+}} [[OMP_IV]],
- // LAMBDA-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}} [[OMP_UB]],
- // LAMBDA: [[CMP_IV_UB:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3]]
- // LAMBDA: br {{.+}} [[CMP_IV_UB]], label %[[DIST_OUTER_LOOP_BODY:.+]], label %[[DIST_OUTER_LOOP_END:.+]]
-
- // LAMBDA: [[DIST_OUTER_LOOP_BODY]]:
- // LAMBDA: br label %[[DIST_INNER_LOOP_HEADER:.+]]
-
- // LAMBDA: [[DIST_INNER_LOOP_HEADER]]:
- // LAMBDA-DAG: [[OMP_IV_VAL_2:%.+]] = load {{.+}} [[OMP_IV]],
- // LAMBDA-DAG: [[OMP_UB_VAL_4:%.+]] = load {{.+}} [[OMP_UB]],
- // LAMBDA: [[CMP_IV_UB_2:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_2]], [[OMP_UB_VAL_4]]
- // LAMBDA: br{{.+}} [[CMP_IV_UB_2]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
+ // LAMBDA-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}}
+ // LAMBDA-DAG: [[OMP_UB_VAL_3_PLUS_ONE:%.+]] = add {{.+}} [[OMP_UB_VAL_3]], 1
+ // LAMBDA: [[CMP_IV_UB:%.+]] = icmp slt {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3_PLUS_ONE]]
+ // LAMBDA: br {{.+}} [[CMP_IV_UB]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
// check that PrevLB and PrevUB are passed to the 'for'
// LAMBDA: [[DIST_INNER_LOOP_BODY]]:
@@ -466,13 +466,6 @@ int main() {
// LAMBDA-DAG: [[OMP_ST_VAL_1:%.+]] = load {{.+}}, {{.+}}* [[OMP_ST]],
// LAMBDA: [[OMP_IV_INC:%.+]] = add{{.+}} [[OMP_IV_VAL_3]], [[OMP_ST_VAL_1]]
// LAMBDA: store{{.+}} [[OMP_IV_INC]], {{.+}}* [[OMP_IV]],
- // LAMBDA: br label %[[DIST_INNER_LOOP_HEADER]]
-
- // LAMBDA: [[DIST_INNER_LOOP_END]]:
- // LAMBDA: br label %[[DIST_OUTER_LOOP_INC:.+]]
-
- // LAMBDA: [[DIST_OUTER_LOOP_INC]]:
- // check NextLB and NextUB
// LAMBDA-DAG: [[OMP_LB_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
// LAMBDA-DAG: [[OMP_ST_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// LAMBDA-DAG: [[OMP_LB_NEXT:%.+]] = add{{.+}} [[OMP_LB_VAL_2]], [[OMP_ST_VAL_2]]
@@ -481,10 +474,31 @@ int main() {
// LAMBDA-DAG: [[OMP_ST_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// LAMBDA-DAG: [[OMP_UB_NEXT:%.+]] = add{{.+}} [[OMP_UB_VAL_5]], [[OMP_ST_VAL_3]]
// LAMBDA: store{{.+}} [[OMP_UB_NEXT]], {{.+}}* [[OMP_UB]],
- // LAMBDA: br label %[[DIST_OUTER_LOOP_HEADER]]
- // outer loop exit
- // LAMBDA: [[DIST_OUTER_LOOP_END]]:
+ // Update UB
+ // LAMBDA-DAG: [[OMP_UB_VAL_6:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+ // LAMBDA: [[OMP_EXPR_VAL:%.+]] = load{{.+}}, {{.+}}
+ // LAMBDA-DAG: [[CMP_UB_NUM_IT_1:%.+]] = icmp sgt {{.+}}[[OMP_UB_VAL_6]], [[OMP_EXPR_VAL]]
+ // LAMBDA: br {{.+}} [[CMP_UB_NUM_IT_1]], label %[[EUB_TRUE_1:.+]], label %[[EUB_FALSE_1:.+]]
+ // LAMBDA-DAG: [[EUB_TRUE_1]]:
+ // LAMBDA: [[NUM_IT_3:%.+]] = load{{.+}}
+ // LAMBDA: br label %[[EUB_END_1:.+]]
+ // LAMBDA-DAG: [[EUB_FALSE_1]]:
+ // LAMBDA: [[OMP_UB_VAL3:%.+]] = load{{.+}} [[OMP_UB]],
+ // LAMBDA: br label %[[EUB_END_1]]
+ // LAMBDA-DAG: [[EUB_END_1]]:
+ // LAMBDA-DAG: [[EUB_RES_1:%.+]] = phi{{.+}} [ [[NUM_IT_3]], %[[EUB_TRUE_1]] ], [ [[OMP_UB_VAL3]], %[[EUB_FALSE_1]] ]
+ // LAMBDA: store{{.+}} [[EUB_RES_1]], {{.+}}* [[OMP_UB]],
+
+ // Store LB in IV
+ // LAMBDA-DAG: [[OMP_LB_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+ // LAMBDA: store{{.+}} [[OMP_LB_VAL_3]], {{.+}}* [[OMP_IV]],
+
+ // LAMBDA: [[DIST_INNER_LOOP_END]]:
+ // LAMBDA: br label %[[LOOP_EXIT:.+]]
+
+ // loop exit
+ // LAMBDA: [[LOOP_EXIT]]:
// LAMBDA-DAG: call void @__kmpc_for_static_fini(
// LAMBDA: ret
@@ -1153,19 +1167,28 @@ int main() {
for (int i = 0; i < n; ++i) {
a[i] = b[i] + c[i];
// CHECK: define{{.+}} void [[OMP_OUTLINED_3]](
- // CHECK-DAG: [[OMP_IV:%.omp.iv]] = alloca
- // CHECK-DAG: [[OMP_LB:%.omp.comb.lb]] = alloca
- // CHECK-DAG: [[OMP_UB:%.omp.comb.ub]] = alloca
- // CHECK-DAG: [[OMP_ST:%.omp.stride]] = alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: [[OMP_IV:%.+]] = alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: alloca
+ // CHECK: [[OMP_LB:%.+]] = alloca
+ // CHECK: [[OMP_UB:%.+]] = alloca
+ // CHECK: [[OMP_ST:%.+]] = alloca
// unlike the previous tests, in this one we have a outer and inner loop for 'distribute'
// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91,
- // CHECK: br label %[[DIST_OUTER_LOOP_HEADER:.+]]
- // CHECK: [[DIST_OUTER_LOOP_HEADER]]:
// check EUB for distribute
// CHECK-DAG: [[OMP_UB_VAL_1:%.+]] = load{{.+}} [[OMP_UB]],
- // CHECK: [[NUM_IT_1:%.+]] = load{{.+}},
+ // CHECK: [[NUM_IT_1:%.+]] = load{{.+}}
// CHECK-DAG: [[CMP_UB_NUM_IT:%.+]] = icmp sgt {{.+}} [[OMP_UB_VAL_1]], [[NUM_IT_1]]
// CHECK: br {{.+}} [[CMP_UB_NUM_IT]], label %[[EUB_TRUE:.+]], label %[[EUB_FALSE:.+]]
// CHECK-DAG: [[EUB_TRUE]]:
@@ -1184,18 +1207,10 @@ int main() {
// check exit condition
// CHECK-DAG: [[OMP_IV_VAL_1:%.+]] = load {{.+}} [[OMP_IV]],
- // CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}} [[OMP_UB]],
- // CHECK: [[CMP_IV_UB:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3]]
- // CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_OUTER_LOOP_BODY:.+]], label %[[DIST_OUTER_LOOP_END:.+]]
-
- // CHECK: [[DIST_OUTER_LOOP_BODY]]:
- // CHECK: br label %[[DIST_INNER_LOOP_HEADER:.+]]
-
- // CHECK: [[DIST_INNER_LOOP_HEADER]]:
- // CHECK-DAG: [[OMP_IV_VAL_2:%.+]] = load {{.+}} [[OMP_IV]],
- // CHECK-DAG: [[OMP_UB_VAL_4:%.+]] = load {{.+}} [[OMP_UB]],
- // CHECK: [[CMP_IV_UB_2:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_2]], [[OMP_UB_VAL_4]]
- // CHECK: br{{.+}} [[CMP_IV_UB_2]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
+ // CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}}
+ // CHECK-DAG: [[OMP_UB_VAL_3_PLUS_ONE:%.+]] = add {{.+}} [[OMP_UB_VAL_3]], 1
+ // CHECK: [[CMP_IV_UB:%.+]] = icmp slt {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3_PLUS_ONE]]
+ // CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
// check that PrevLB and PrevUB are passed to the 'for'
// CHECK: [[DIST_INNER_LOOP_BODY]]:
@@ -1214,13 +1229,6 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_1:%.+]] = load {{.+}}, {{.+}}* [[OMP_ST]],
// CHECK: [[OMP_IV_INC:%.+]] = add{{.+}} [[OMP_IV_VAL_3]], [[OMP_ST_VAL_1]]
// CHECK: store{{.+}} [[OMP_IV_INC]], {{.+}}* [[OMP_IV]],
- // CHECK: br label %[[DIST_INNER_LOOP_HEADER]]
-
- // CHECK: [[DIST_INNER_LOOP_END]]:
- // CHECK: br label %[[DIST_OUTER_LOOP_INC:.+]]
-
- // CHECK: [[DIST_OUTER_LOOP_INC]]:
- // check NextLB and NextUB
// CHECK-DAG: [[OMP_LB_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
// CHECK-DAG: [[OMP_ST_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_LB_NEXT:%.+]] = add{{.+}} [[OMP_LB_VAL_2]], [[OMP_ST_VAL_2]]
@@ -1229,10 +1237,31 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_UB_NEXT:%.+]] = add{{.+}} [[OMP_UB_VAL_5]], [[OMP_ST_VAL_3]]
// CHECK: store{{.+}} [[OMP_UB_NEXT]], {{.+}}* [[OMP_UB]],
- // CHECK: br label %[[DIST_OUTER_LOOP_HEADER]]
- // outer loop exit
- // CHECK: [[DIST_OUTER_LOOP_END]]:
+ // Update UB
+ // CHECK-DAG: [[OMP_UB_VAL_6:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+ // CHECK: [[OMP_EXPR_VAL:%.+]] = load{{.+}}, {{.+}}
+ // CHECK-DAG: [[CMP_UB_NUM_IT_1:%.+]] = icmp sgt {{.+}}[[OMP_UB_VAL_6]], [[OMP_EXPR_VAL]]
+ // CHECK: br {{.+}} [[CMP_UB_NUM_IT_1]], label %[[EUB_TRUE_1:.+]], label %[[EUB_FALSE_1:.+]]
+ // CHECK-DAG: [[EUB_TRUE_1]]:
+ // CHECK: [[NUM_IT_3:%.+]] = load{{.+}}
+ // CHECK: br label %[[EUB_END_1:.+]]
+ // CHECK-DAG: [[EUB_FALSE_1]]:
+ // CHECK: [[OMP_UB_VAL3:%.+]] = load{{.+}} [[OMP_UB]],
+ // CHECK: br label %[[EUB_END_1]]
+ // CHECK-DAG: [[EUB_END_1]]:
+ // CHECK-DAG: [[EUB_RES_1:%.+]] = phi{{.+}} [ [[NUM_IT_3]], %[[EUB_TRUE_1]] ], [ [[OMP_UB_VAL3]], %[[EUB_FALSE_1]] ]
+ // CHECK: store{{.+}} [[EUB_RES_1]], {{.+}}* [[OMP_UB]],
+
+ // Store LB in IV
+ // CHECK-DAG: [[OMP_LB_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+ // CHECK: store{{.+}} [[OMP_LB_VAL_3]], {{.+}}* [[OMP_IV]],
+
+ // CHECK: [[DIST_INNER_LOOP_END]]:
+ // CHECK: br label %[[LOOP_EXIT:.+]]
+
+ // loop exit
+ // CHECK: [[LOOP_EXIT]]:
// CHECK-DAG: call void @__kmpc_for_static_fini(
// CHECK: ret
@@ -1866,19 +1895,28 @@ int main() {
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_teams({{.+}}, i32 5, {{.+}}* [[OMP_OUTLINED_3:@.+]] to {{.+}})
// CHECK: define{{.+}} void [[OMP_OUTLINED_3]](
-// CHECK-DAG: [[OMP_IV:%.omp.iv]] = alloca
-// CHECK-DAG: [[OMP_LB:%.omp.comb.lb]] = alloca
-// CHECK-DAG: [[OMP_UB:%.omp.comb.ub]] = alloca
-// CHECK-DAG: [[OMP_ST:%.omp.stride]] = alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: [[OMP_IV:%.+]] = alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: [[OMP_LB:%.+]] = alloca
+// CHECK: [[OMP_UB:%.+]] = alloca
+// CHECK: [[OMP_ST:%.+]] = alloca
// unlike the previous tests, in this one we have a outer and inner loop for 'distribute'
// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, i32 91,
-// CHECK: br label %[[DIST_OUTER_LOOP_HEADER:.+]]
-// CHECK: [[DIST_OUTER_LOOP_HEADER]]:
// check EUB for distribute
// CHECK-DAG: [[OMP_UB_VAL_1:%.+]] = load{{.+}} [[OMP_UB]],
-// CHECK: [[NUM_IT_1:%.+]] = load{{.+}},
+// CHECK: [[NUM_IT_1:%.+]] = load{{.+}}
// CHECK-DAG: [[CMP_UB_NUM_IT:%.+]] = icmp sgt {{.+}} [[OMP_UB_VAL_1]], [[NUM_IT_1]]
// CHECK: br {{.+}} [[CMP_UB_NUM_IT]], label %[[EUB_TRUE:.+]], label %[[EUB_FALSE:.+]]
// CHECK-DAG: [[EUB_TRUE]]:
@@ -1897,18 +1935,10 @@ int main() {
// check exit condition
// CHECK-DAG: [[OMP_IV_VAL_1:%.+]] = load {{.+}} [[OMP_IV]],
-// CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}} [[OMP_UB]],
-// CHECK: [[CMP_IV_UB:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3]]
-// CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_OUTER_LOOP_BODY:.+]], label %[[DIST_OUTER_LOOP_END:.+]]
-
-// CHECK: [[DIST_OUTER_LOOP_BODY]]:
-// CHECK: br label %[[DIST_INNER_LOOP_HEADER:.+]]
-
-// CHECK: [[DIST_INNER_LOOP_HEADER]]:
-// CHECK-DAG: [[OMP_IV_VAL_2:%.+]] = load {{.+}} [[OMP_IV]],
-// CHECK-DAG: [[OMP_UB_VAL_4:%.+]] = load {{.+}} [[OMP_UB]],
-// CHECK: [[CMP_IV_UB_2:%.+]] = icmp sle {{.+}} [[OMP_IV_VAL_2]], [[OMP_UB_VAL_4]]
-// CHECK: br{{.+}} [[CMP_IV_UB_2]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
+// CHECK-DAG: [[OMP_UB_VAL_3:%.+]] = load {{.+}}
+// CHECK-DAG: [[OMP_UB_VAL_3_PLUS_ONE:%.+]] = add {{.+}} [[OMP_UB_VAL_3]], 1
+// CHECK: [[CMP_IV_UB:%.+]] = icmp slt {{.+}} [[OMP_IV_VAL_1]], [[OMP_UB_VAL_3_PLUS_ONE]]
+// CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
// check that PrevLB and PrevUB are passed to the 'for'
// CHECK: [[DIST_INNER_LOOP_BODY]]:
@@ -1927,13 +1957,6 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_1:%.+]] = load {{.+}}, {{.+}}* [[OMP_ST]],
// CHECK: [[OMP_IV_INC:%.+]] = add{{.+}} [[OMP_IV_VAL_3]], [[OMP_ST_VAL_1]]
// CHECK: store{{.+}} [[OMP_IV_INC]], {{.+}}* [[OMP_IV]],
-// CHECK: br label %[[DIST_INNER_LOOP_HEADER]]
-
-// CHECK: [[DIST_INNER_LOOP_END]]:
-// CHECK: br label %[[DIST_OUTER_LOOP_INC:.+]]
-
-// CHECK: [[DIST_OUTER_LOOP_INC]]:
-// check NextLB and NextUB
// CHECK-DAG: [[OMP_LB_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
// CHECK-DAG: [[OMP_ST_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_LB_NEXT:%.+]] = add{{.+}} [[OMP_LB_VAL_2]], [[OMP_ST_VAL_2]]
@@ -1942,10 +1965,31 @@ int main() {
// CHECK-DAG: [[OMP_ST_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
// CHECK-DAG: [[OMP_UB_NEXT:%.+]] = add{{.+}} [[OMP_UB_VAL_5]], [[OMP_ST_VAL_3]]
// CHECK: store{{.+}} [[OMP_UB_NEXT]], {{.+}}* [[OMP_UB]],
-// CHECK: br label %[[DIST_OUTER_LOOP_HEADER]]
-// outer loop exit
-// CHECK: [[DIST_OUTER_LOOP_END]]:
+// Update UB
+// CHECK-DAG: [[OMP_UB_VAL_6:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+// CHECK: [[OMP_EXPR_VAL:%.+]] = load{{.+}}, {{.+}}
+// CHECK-DAG: [[CMP_UB_NUM_IT_1:%.+]] = icmp sgt {{.+}}[[OMP_UB_VAL_6]], [[OMP_EXPR_VAL]]
+// CHECK: br {{.+}} [[CMP_UB_NUM_IT_1]], label %[[EUB_TRUE_1:.+]], label %[[EUB_FALSE_1:.+]]
+// CHECK-DAG: [[EUB_TRUE_1]]:
+// CHECK: [[NUM_IT_3:%.+]] = load{{.+}}
+// CHECK: br label %[[EUB_END_1:.+]]
+// CHECK-DAG: [[EUB_FALSE_1]]:
+// CHECK: [[OMP_UB_VAL3:%.+]] = load{{.+}} [[OMP_UB]],
+// CHECK: br label %[[EUB_END_1]]
+// CHECK-DAG: [[EUB_END_1]]:
+// CHECK-DAG: [[EUB_RES_1:%.+]] = phi{{.+}} [ [[NUM_IT_3]], %[[EUB_TRUE_1]] ], [ [[OMP_UB_VAL3]], %[[EUB_FALSE_1]] ]
+// CHECK: store{{.+}} [[EUB_RES_1]], {{.+}}* [[OMP_UB]],
+
+// Store LB in IV
+// CHECK-DAG: [[OMP_LB_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+// CHECK: store{{.+}} [[OMP_LB_VAL_3]], {{.+}}* [[OMP_IV]],
+
+// CHECK: [[DIST_INNER_LOOP_END]]:
+// CHECK: br label %[[LOOP_EXIT:.+]]
+
+// loop exit
+// CHECK: [[LOOP_EXIT]]:
// CHECK-DAG: call void @__kmpc_for_static_fini(
// CHECK: ret
diff --git a/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
index 1447b5ff2ee2..50e45be0ee28 100644
--- a/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
@@ -1,30 +1,30 @@
-// RxUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp
index d6f56d5b2169..e1b0f1466cd9 100644
--- a/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
-// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
@@ -232,7 +232,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+#pragma omp distribute parallel for simd firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
diff --git a/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
index af74ab7b72a5..c79bceef455f 100644
--- a/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
@@ -1,31 +1,31 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp
index 45e0d44322a5..e7f2b7da3feb 100644
--- a/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
-// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
void foo() {
}
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -171,8 +171,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -221,7 +221,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -241,12 +241,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -262,7 +262,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute parallel for simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
diff --git a/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp
index 788bace434f9..6fb5944d2c15 100644
--- a/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_linear_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -Wno-openmp-target
-// RUN: %clang_cc1 -verify -fopenmp-simd %s
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wno-openmp-target
namespace X {
int x;
@@ -189,7 +189,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp distribute parallel for simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -294,7 +294,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp distribute parallel for simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
index 20ee49a6fcc4..2c0d7ab74285 100644
--- a/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
-// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s -Wno-openmp-target
class S {
int a;
@@ -144,9 +144,9 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target
#pragma omp teams
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
#pragma omp distribute parallel for simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
index 014fb9523fe5..318fc1401963 100644
--- a/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -15,7 +15,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[S_TY:%.+]] = type { [[INTPTR_T_TY:i[0-9]+]], [[INTPTR_T_TY]], [[INTPTR_T_TY]] }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp
index d23d9176ed2e..419e735f4529 100644
--- a/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp
@@ -49,7 +49,7 @@ public:
#pragma omp target
#pragma omp teams
#pragma omp distribute parallel for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp b/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
index 4fb1f5b0274d..716d7d7fa2e9 100644
--- a/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -16,7 +16,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp
index 348e664b782a..046cce59dd2c 100644
--- a/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_reduction_messages.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
-// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s -Wno-openmp-target
-// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s -Wno-openmp-target
+// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s -Wno-openmp-target
void foo() {
}
@@ -160,12 +160,12 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -175,17 +175,17 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -200,7 +200,7 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -231,7 +231,7 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -344,12 +344,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -359,17 +359,17 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -384,7 +384,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -420,7 +420,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute parallel for simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp
index fd694b7ba488..d037e4cd93b0 100644
--- a/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp
@@ -117,7 +117,7 @@ T tmain(T argc, S **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared (a, b, c, d, f)
+#pragma omp distribute parallel for simd shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'const S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
@@ -131,14 +131,14 @@ T tmain(T argc, S **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared(ba)
+#pragma omp distribute parallel for simd shared(ba) // expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared(ca)
+#pragma omp distribute parallel for simd shared(ca) // expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
@@ -152,7 +152,7 @@ T tmain(T argc, S **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared(e, g)
+#pragma omp distribute parallel for simd shared(e, g) // expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
@@ -291,7 +291,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared (a, b, c, d, f)
+#pragma omp distribute parallel for simd shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'const S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
@@ -305,14 +305,14 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared(ba)
+#pragma omp distribute parallel for simd shared(ba) // expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared(ca)
+#pragma omp distribute parallel for simd shared(ca) // expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
@@ -326,7 +326,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd shared(e, g)
+#pragma omp distribute parallel for simd shared(e, g) // expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for(int k = 0 ; k < n ; k++) {
acc++;
}
diff --git a/test/OpenMP/distribute_private_messages.cpp b/test/OpenMP/distribute_private_messages.cpp
index 3cf2fdc228b5..55c13a00bbc3 100644
--- a/test/OpenMP/distribute_private_messages.cpp
+++ b/test/OpenMP/distribute_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -67,15 +67,15 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp distribute private (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
- #pragma omp distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp distribute private (argv[1]) // expected-error {{expected variable name}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp distribute private(ba)
for (int k = 0; k < argc; ++k) ++k;
- #pragma omp distribute private(ca) // expected-error {{shared variable cannot be private}}
+ #pragma omp distribute private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
- #pragma omp distribute private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp distribute private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp distribute private(S2::S2s) // expected-error {{shared variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/distribute_simd_aligned_messages.cpp b/test/OpenMP/distribute_simd_aligned_messages.cpp
index 51421d6cbdd2..8c4a8d956995 100644
--- a/test/OpenMP/distribute_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_simd_aligned_messages.cpp
@@ -287,7 +287,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd aligned (a, b) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}}
+#pragma omp distribute simd aligned (a, b) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/distribute_simd_ast_print.cpp b/test/OpenMP/distribute_simd_ast_print.cpp
index 5133db695b3b..092c5cfd78eb 100644
--- a/test/OpenMP/distribute_simd_ast_print.cpp
+++ b/test/OpenMP/distribute_simd_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_simd_codegen.cpp b/test/OpenMP/distribute_simd_codegen.cpp
index 662d66af1107..55e24c03ffcc 100644
--- a/test/OpenMP/distribute_simd_codegen.cpp
+++ b/test/OpenMP/distribute_simd_codegen.cpp
@@ -40,8 +40,8 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
-// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_DISTRIBUTE_0:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2050, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-LABEL: define {{.*void}} @{{.*}}without_schedule_clause{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
void without_schedule_clause(float *a, float *b, float *c, float *d) {
diff --git a/test/OpenMP/distribute_simd_firstprivate_codegen.cpp b/test/OpenMP/distribute_simd_firstprivate_codegen.cpp
index 919a12284131..36bd1456af5b 100644
--- a/test/OpenMP/distribute_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/distribute_simd_firstprivate_codegen.cpp
@@ -1,31 +1,31 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_simd_firstprivate_messages.cpp b/test/OpenMP/distribute_simd_firstprivate_messages.cpp
index e0f3ddeeeba1..1cfc273256a3 100644
--- a/test/OpenMP/distribute_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/distribute_simd_firstprivate_messages.cpp
@@ -110,7 +110,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+#pragma omp distribute simd firstprivate(a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -120,7 +120,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -232,7 +232,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+#pragma omp distribute simd firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'const S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -247,12 +247,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(ba) // OK
+#pragma omp distribute simd firstprivate(ba) // expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(ca) // OK
+#pragma omp distribute simd firstprivate(ca) // expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctl}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -283,12 +283,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(m) // OK
+#pragma omp distribute simd firstprivate(m) // expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -320,13 +320,13 @@ int main(int argc, char **argv) {
// expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(g) firstprivate(g)
+#pragma omp distribute simd lastprivate(g) firstprivate(g) //expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
// expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}}
+#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Non-trivial type 'S6' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
diff --git a/test/OpenMP/distribute_simd_lastprivate_codegen.cpp b/test/OpenMP/distribute_simd_lastprivate_codegen.cpp
index cde7c81d50f9..22a24a66495a 100644
--- a/test/OpenMP/distribute_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/distribute_simd_lastprivate_codegen.cpp
@@ -1,31 +1,31 @@
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
+// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-32
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/distribute_simd_lastprivate_messages.cpp b/test/OpenMP/distribute_simd_lastprivate_messages.cpp
index e47ad7ec1eef..875210ed49f9 100644
--- a/test/OpenMP/distribute_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/distribute_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -112,7 +112,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+#pragma omp distribute simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -122,7 +122,7 @@ int foomain(int argc, char **argv) {
++k;
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+#pragma omp distribute simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} expected-warning 2 {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k)
++k;
#pragma omp target
@@ -171,8 +171,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -221,7 +221,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'const S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -236,17 +236,17 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(ba)
+#pragma omp distribute simd lastprivate(ba) // expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}} expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -262,7 +262,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp distribute simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -272,12 +272,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+#pragma omp distribute simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+#pragma omp distribute simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target
@@ -318,13 +318,13 @@ int main(int argc, char **argv) {
// expected-error@+3 {{firstprivate variable cannot be lastprivate}} expected-note@+3 {{defined as firstprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd firstprivate(m) lastprivate(m)
+#pragma omp distribute simd firstprivate(m) lastprivate(m) // expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
// expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}}
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}}
+#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Non-trivial type 'S6' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (i = 0; i < argc; ++i)
foo();
static int si;
diff --git a/test/OpenMP/distribute_simd_linear_messages.cpp b/test/OpenMP/distribute_simd_linear_messages.cpp
index 06d85d13501e..631b43a12096 100644
--- a/test/OpenMP/distribute_simd_linear_messages.cpp
+++ b/test/OpenMP/distribute_simd_linear_messages.cpp
@@ -189,7 +189,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -283,7 +283,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}} expected-warning {{Non-trivial type 'const S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -293,7 +293,7 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd linear(e, g) // expected-error {{argument of a linear clause should be of integral or pointer type, not 'S4'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+#pragma omp distribute simd linear(e, g) // expected-error {{argument of a linear clause should be of integral or pointer type, not 'S4'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S5'}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/distribute_simd_loop_messages.cpp b/test/OpenMP/distribute_simd_loop_messages.cpp
index 1977ca789dcf..b46bdad0b641 100644
--- a/test/OpenMP/distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/distribute_simd_loop_messages.cpp
@@ -135,9 +135,9 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+ // Ok
#pragma omp target
#pragma omp teams
- // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
#pragma omp distribute simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
@@ -472,7 +472,7 @@ int test_with_random_access_iterator() {
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (GoodIter I = begin; I < end; ++I)
+ for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams
@@ -483,41 +483,41 @@ int test_with_random_access_iterator() {
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (GoodIter I = begin; I >= end; --I)
+ for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams
// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
#pragma omp distribute simd
- for (GoodIter I(begin); I < end; ++I)
+ for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams
// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
#pragma omp distribute simd
- for (GoodIter I(nullptr); I < end; ++I)
+ for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams
// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
#pragma omp distribute simd
- for (GoodIter I(0); I < end; ++I)
+ for (GoodIter I(0); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams
// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
#pragma omp distribute simd
- for (GoodIter I(1,2); I < end; ++I)
+ for (GoodIter I(1,2); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (begin = GoodIter(0); begin < end; ++begin)
+ for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (begin = GoodIter(1,2); begin < end; ++begin)
+ for (begin = GoodIter(1,2); begin < end; ++begin) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams
@@ -528,7 +528,7 @@ int test_with_random_access_iterator() {
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (begin = end; begin < end; ++begin)
+ for (begin = end; begin < end; ++begin) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams
@@ -558,7 +558,7 @@ int test_with_random_access_iterator() {
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (GoodIter I = begin; I >= end; I = I - 1)
+ for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams
@@ -582,7 +582,7 @@ int test_with_random_access_iterator() {
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (Iter0 I = begin0; I < end0; ++I)
+ for (Iter0 I = begin0; I < end0; ++I) // expected-warning 2 {{Non-trivial type 'Iter0' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
@@ -590,7 +590,7 @@ int test_with_random_access_iterator() {
// Initializer is constructor without params.
// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
#pragma omp distribute simd
- for (Iter0 I; I < end0; ++I)
+ for (Iter0 I; I < end0; ++I) // expected-warning {{Non-trivial type 'Iter0' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
Iter1 begin1, end1;
@@ -636,7 +636,7 @@ template <typename IT, int ST> class TC {
// expected-note@+3 {{loop step is expected to be positive due to this condition}}
// expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
#pragma omp distribute simd
- for (IT I = begin; I <= end; I += ST) {
+ for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp distribute simd
@@ -679,7 +679,7 @@ template <typename IT, int ST=0> int dotest_gt(IT begin, IT end) {
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
- for (IT I = begin; I < end; I+=TC<int,ST>::step()) {
+ for (IT I = begin; I < end; I+=TC<int,ST>::step()) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -688,7 +688,7 @@ void test_with_template() {
GoodIter begin, end;
TC<GoodIter, 100> t1;
TC<GoodIter, -100> t2;
- t1.dotest_lt(begin, end);
+ t1.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, 100>::dotest_lt' requested here}}
t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
dotest_gt<unsigned, 10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, 10>' requested here}}
diff --git a/test/OpenMP/distribute_simd_private_messages.cpp b/test/OpenMP/distribute_simd_private_messages.cpp
index 8d82cc816649..1fdb97dceb4e 100644
--- a/test/OpenMP/distribute_simd_private_messages.cpp
+++ b/test/OpenMP/distribute_simd_private_messages.cpp
@@ -49,7 +49,7 @@ public:
#pragma omp target
#pragma omp teams
#pragma omp distribute simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
- for (int k = 0; k < s.a; ++k)
+ for (int k = 0; k < s.a; ++k) // expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}
++s.a;
return *this;
}
diff --git a/test/OpenMP/distribute_simd_reduction_messages.cpp b/test/OpenMP/distribute_simd_reduction_messages.cpp
index 7bb5bdea5b46..f960b1831917 100644
--- a/test/OpenMP/distribute_simd_reduction_messages.cpp
+++ b/test/OpenMP/distribute_simd_reduction_messages.cpp
@@ -160,12 +160,12 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-warning 2 {{Non-trivial type 'S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning 2 {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -175,17 +175,17 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -200,12 +200,12 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+#pragma omp distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}} expected-warning 2 {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -231,7 +231,7 @@ T tmain(T argc) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -344,12 +344,12 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-warning {{Non-trivial type 'S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-warning {{Non-trivial type 'S2' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -359,17 +359,17 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Non-trivial type 'const S2 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Non-trivial type 'const S3 [5]' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -384,22 +384,22 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+#pragma omp distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} expected-warning {{Non-trivial type 'S4' is mapped, only trivial types are guaranteed to be mapped correctly}} expected-warning {{Non-trivial type 'S5' is mapped, only trivial types are guaranteed to be mapped correctly}}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+#pragma omp distribute simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} expected-warning {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
+#pragma omp distribute simd reduction(+ : o) // expected-error {{no viable overloaded '='}} expected-warning {{Non-trivial type 'class S6' is mapped, only trivial types are guaranteed to be mapped correctly}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target
@@ -407,12 +407,18 @@ int main(int argc, char **argv) {
#pragma omp distribute simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
for (int i = 0; i < 10; ++i)
foo();
+#if __cplusplus < 201103L // < C++11
+// expected-warning@+5 {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
+#endif
#pragma omp parallel private(k)
#pragma omp target
#pragma omp teams
#pragma omp distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
for (int i = 0; i < 10; ++i)
foo();
+#if __cplusplus < 201103L // < C++11
+// expected-warning@+4 {{Non-trivial type 'S3' is mapped, only trivial types are guaranteed to be mapped correctly}}
+#endif
#pragma omp target
#pragma omp teams
#pragma omp distribute simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
@@ -420,7 +426,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp distribute simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/for_ast_print.cpp b/test/OpenMP/for_ast_print.cpp
index 82318ff800aa..760d44c1cf51 100644
--- a/test/OpenMP/for_ast_print.cpp
+++ b/test/OpenMP/for_ast_print.cpp
@@ -145,8 +145,8 @@ int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
// CHECK: static int a;
-#pragma omp for schedule(guided, argc)
- // CHECK-NEXT: #pragma omp for schedule(guided, argc)
+#pragma omp for schedule(guided, argc) reduction(+:argv[0][:1])
+ // CHECK-NEXT: #pragma omp for schedule(guided, argc) reduction(+: argv[0][:1])
for (int i = 0; i < 2; ++i)
a = 2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
diff --git a/test/OpenMP/for_codegen.cpp b/test/OpenMP/for_codegen.cpp
index ad8674fdde7e..2e44478b632f 100644
--- a/test/OpenMP/for_codegen.cpp
+++ b/test/OpenMP/for_codegen.cpp
@@ -1,14 +1,14 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=LIFETIME
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s --check-prefix=CHECK --check-prefix=LIFETIME
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s
-// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=TERM_DEBUG
-// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=PROF-INSTR-PATH
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck %s --check-prefix=PROF-INSTR-PATH
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
//
// expected-no-diagnostics
@@ -17,8 +17,8 @@
// PROF-INSTR-PATH: constant [25 x i8] c"for_codegen-test.profraw\00"
// CHECK: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
-// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
-// CHECK-DAG: [[LOOP_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 514, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[LOOP_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 514, i32 0, i32 0, i8*
// CHECK-DAG: [[I:@.+]] = global i8 1,
// CHECK-DAG: [[J:@.+]] = global i8 2,
// CHECK-DAG: [[K:@.+]] = global i8 3,
@@ -38,7 +38,6 @@ void loop_with_counter_collapse() {
// LIFETIME: call void @llvm.lifetime.end
// LIFETIME: call void @llvm.lifetime.end
// LIFETIME: call void @llvm.lifetime.end
- // LIFETIME: call void @llvm.lifetime.end
#pragma omp for collapse(2)
for (int i = 0; i < 4; i++) {
for (int j = i; j < 4; j++) {
@@ -73,7 +72,7 @@ void without_schedule_clause(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
a[i] = b[i] * c[i] * d[i];
// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}
// CHECK-NEXT: [[ADD1_2:%.+]] = add nsw i32 [[IV1_2]], 1
@@ -114,7 +113,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
a[i] = b[i] * c[i] * d[i];
// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}
// CHECK-NEXT: [[ADD1_2:%.+]] = add nsw i32 [[IV1_2]], 1
@@ -163,7 +162,7 @@ void static_chunked(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
a[i] = b[i] * c[i] * d[i];
// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}
// CHECK-NEXT: [[ADD1_2:%.+]] = add i32 [[IV1_2]], 1
@@ -215,7 +214,7 @@ void dynamic1(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[CALC_I_2]], i64* [[LC_I:.+]]
// ... loop body ...
// End of body: store into a[i]:
-// CHECK: store float [[RESULT:%.+]], float* {{%.+}}!llvm.mem.parallel_loop_access
+// CHECK: store float [[RESULT:%.+]], float* {{%.+}}!llvm.access.group
a[i] = b[i] * c[i] * d[i];
// CHECK: [[IV1_2:%.+]] = load i64, i64* [[OMP_IV]]{{.*}}
// CHECK-NEXT: [[ADD1_2:%.+]] = add i64 [[IV1_2]], 1
@@ -256,7 +255,7 @@ void guided7(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[CALC_I_2]], i64* [[LC_I:.+]]
// ... loop body ...
// End of body: store into a[i]:
-// CHECK: store float [[RESULT:%.+]], float* {{%.+}}!llvm.mem.parallel_loop_access
+// CHECK: store float [[RESULT:%.+]], float* {{%.+}}!llvm.access.group
a[i] = b[i] * c[i] * d[i];
// CHECK: [[IV1_2:%.+]] = load i64, i64* [[OMP_IV]]{{.*}}
// CHECK-NEXT: [[ADD1_2:%.+]] = add i64 [[IV1_2]], 1
@@ -301,7 +300,7 @@ void test_auto(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
a[i] = b[i] * c[i] * d[i];
// CHECK: [[IV1_2:%.+]] = load i64, i64* [[OMP_IV]]{{.*}}
// CHECK-NEXT: [[ADD1_2:%.+]] = add nsw i64 [[IV1_2]], 1
@@ -343,7 +342,7 @@ void runtime(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
a[i] = b[i] * c[i] * d[i];
// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}
// CHECK-NEXT: [[ADD1_2:%.+]] = add nsw i32 [[IV1_2]], 1
@@ -385,12 +384,12 @@ void parallel_for(float *a) {
#pragma omp parallel
#pragma omp for schedule(static, 5)
// TERM_DEBUG-NOT: __kmpc_global_thread_num
- // TERM_DEBUG: call void @__kmpc_for_static_init_4u({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]]
+ // TERM_DEBUG: call void @__kmpc_for_static_init_4u({{.+}}), !dbg [[DBG_LOC:![0-9]+]]
// TERM_DEBUG: invoke i32 {{.*}}foo{{.*}}()
// TERM_DEBUG: unwind label %[[TERM_LPAD:.+]],
// TERM_DEBUG-NOT: __kmpc_global_thread_num
- // TERM_DEBUG: call void @__kmpc_for_static_fini({{.+}}), !dbg [[DBG_LOC_END:![0-9]+]]
- // TERM_DEBUG: call {{.+}} @__kmpc_barrier({{.+}}), !dbg [[DBG_LOC_CANCEL:![0-9]+]]
+ // TERM_DEBUG: call void @__kmpc_for_static_fini({{.+}}), !dbg [[DBG_LOC]]
+ // TERM_DEBUG: call {{.+}} @__kmpc_barrier({{.+}}), !dbg [[DBG_LOC]]
// TERM_DEBUG: [[TERM_LPAD]]
// TERM_DEBUG: call void @__clang_call_terminate
// TERM_DEBUG: unreachable
@@ -398,9 +397,7 @@ void parallel_for(float *a) {
a[i] += foo();
}
// Check source line corresponds to "#pragma omp for schedule(static, 5)" above:
-// TERM_DEBUG-DAG: [[DBG_LOC_START]] = !DILocation(line: [[@LINE-15]],
-// TERM_DEBUG-DAG: [[DBG_LOC_END]] = !DILocation(line: [[@LINE-16]],
-// TERM_DEBUG-DAG: [[DBG_LOC_CANCEL]] = !DILocation(line: [[@LINE-17]],
+// TERM_DEBUG: [[DBG_LOC]] = !DILocation(line: [[@LINE-15]],
char i = 1, j = 2, k = 3;
// CHECK-LABEL: for_with_global_lcv
diff --git a/test/OpenMP/for_firstprivate_codegen.cpp b/test/OpenMP/for_firstprivate_codegen.cpp
index fc3caa9a2603..14f1f7a08420 100644
--- a/test/OpenMP/for_firstprivate_codegen.cpp
+++ b/test/OpenMP/for_firstprivate_codegen.cpp
@@ -65,7 +65,7 @@ S<float> s_arr[] = {1, 2};
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
S<float> var(3);
// CHECK: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
-// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
// CHECK: ([[S_FLOAT_TY]]*)* [[S_FLOAT_TY_DESTR:@[^ ]+]] {{[^,]+}}, {{.+}}([[S_FLOAT_TY]]* [[TEST]]
diff --git a/test/OpenMP/for_lastprivate_codegen.cpp b/test/OpenMP/for_lastprivate_codegen.cpp
index 0061de632380..f0eeb63128e8 100644
--- a/test/OpenMP/for_lastprivate_codegen.cpp
+++ b/test/OpenMP/for_lastprivate_codegen.cpp
@@ -143,7 +143,7 @@ char cnt;
// BLOCKS: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK: [[S_INT_TY:%.+]] = type { i32 }
-// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK-DAG: [[X:@.+]] = global double 0.0
// CHECK-DAG: [[F:@.+]] = global float 0.0
// CHECK-DAG: [[CNT:@.+]] = global i8 0
diff --git a/test/OpenMP/for_lastprivate_messages.cpp b/test/OpenMP/for_lastprivate_messages.cpp
index 7787ab12d481..1777335c9a91 100644
--- a/test/OpenMP/for_lastprivate_messages.cpp
+++ b/test/OpenMP/for_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -156,8 +156,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -197,7 +197,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
@@ -213,11 +213,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp for lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -230,7 +230,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp for lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
diff --git a/test/OpenMP/for_linear_codegen.cpp b/test/OpenMP/for_linear_codegen.cpp
index 34e8c6a09aff..a9bc6210059c 100644
--- a/test/OpenMP/for_linear_codegen.cpp
+++ b/test/OpenMP/for_linear_codegen.cpp
@@ -99,7 +99,7 @@ struct SST {
// BLOCKS: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK: [[S_INT_TY:%.+]] = type { i32 }
-// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK-DAG: [[F:@.+]] = global float 0.0
// CHECK-DAG: [[CNT:@.+]] = global i8 0
template <typename T>
diff --git a/test/OpenMP/for_linear_messages.cpp b/test/OpenMP/for_linear_messages.cpp
index 622cd4a8a3af..f35e5343c34a 100644
--- a/test/OpenMP/for_linear_messages.cpp
+++ b/test/OpenMP/for_linear_messages.cpp
@@ -122,7 +122,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp for linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp for linear (a, b:B::ib)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp for linear (argv[1]) // expected-error {{expected variable name}}
@@ -188,7 +188,7 @@ int main(int argc, char **argv) {
#pragma omp for linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp for linear(a, b)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp for linear (argv[1]) // expected-error {{expected variable name}}
diff --git a/test/OpenMP/for_loop_messages.cpp b/test/OpenMP/for_loop_messages.cpp
index 37ff0fc0ca2d..8817c77acf15 100644
--- a/test/OpenMP/for_loop_messages.cpp
+++ b/test/OpenMP/for_loop_messages.cpp
@@ -131,8 +131,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp parallel
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
#pragma omp for
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/for_reduction_codegen.cpp b/test/OpenMP/for_reduction_codegen.cpp
index 55323122f3fc..68946a8b4f79 100644
--- a/test/OpenMP/for_reduction_codegen.cpp
+++ b/test/OpenMP/for_reduction_codegen.cpp
@@ -29,9 +29,9 @@ struct S {
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
-// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
-// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
-// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
+// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
// CHECK-DAG: [[REDUCTION_LOCK:@.+]] = common global [8 x i32] zeroinitializer
template <typename T, int length>
diff --git a/test/OpenMP/for_reduction_codegen_UDR.cpp b/test/OpenMP/for_reduction_codegen_UDR.cpp
index 0a6ba1d61008..7adca3eb8047 100644
--- a/test/OpenMP/for_reduction_codegen_UDR.cpp
+++ b/test/OpenMP/for_reduction_codegen_UDR.cpp
@@ -39,9 +39,9 @@ void init_plus(BaseS1&, const BaseS1&);
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { %{{[^,]+}}, %{{[^,]+}}, float }
// CHECK-DAG: [[S_INT_TY:%.+]] = type { %{{[^,]+}}, %{{[^,]+}}, i{{[0-9]+}} }
-// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
-// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
-// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
+// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
// CHECK-DAG: [[REDUCTION_LOCK:@.+]] = common global [8 x i32] zeroinitializer
#pragma omp declare reduction(operator&& : int : omp_out = 111 & omp_in)
diff --git a/test/OpenMP/for_reduction_messages.cpp b/test/OpenMP/for_reduction_messages.cpp
index a4f15aa6193e..f575ee463d3b 100644
--- a/test/OpenMP/for_reduction_messages.cpp
+++ b/test/OpenMP/for_reduction_messages.cpp
@@ -146,11 +146,11 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -158,15 +158,15 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -178,7 +178,7 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -202,7 +202,7 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -214,12 +214,12 @@ T tmain(T argc) {
#pragma omp for reduction(+ : fl) // expected-error 2 {{reduction variable must be shared}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel private(qa) // expected-note 2 {{defined as private}}
-#pragma omp for reduction(+ : qa[1], get()[0]) // expected-error 2 {{reduction variable must be shared}} expected-error {{expected variable name as a base of the array subscript}}
+#pragma omp parallel private(qa)
+#pragma omp for reduction(+ : qa[1], get()[0]) // expected-error {{expected variable name as a base of the array subscript}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(qa)
-#pragma omp for reduction(+ : qa[1], qa[0]) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+#pragma omp for reduction(+ : qa[1], qa[0])
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel reduction(* : fl) // expected-note 2 {{defined as reduction}}
@@ -303,11 +303,11 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -315,15 +315,15 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -335,7 +335,7 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -367,7 +367,7 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -379,12 +379,12 @@ int main(int argc, char **argv) {
#pragma omp for reduction(+ : fl) // expected-error {{reduction variable must be shared}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel private(argv) // expected-note {{defined as private}}
-#pragma omp for reduction(+ : argv[1], get()[0]) // expected-error {{reduction variable must be shared}} expected-error {{expected variable name as a base of the array subscript}}
+#pragma omp parallel private(argv)
+#pragma omp for reduction(+ : argv[1], get()[0]) // expected-error {{expected variable name as a base of the array subscript}} expected-error {{invalid operands to binary expression ('char *' and 'char *')}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(qa)
-#pragma omp for reduction(+ : qa[1], qa[0]) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+#pragma omp for reduction(+ : qa[1], qa[0])
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel reduction(* : fl) // expected-note {{defined as reduction}}
diff --git a/test/OpenMP/for_simd_codegen.cpp b/test/OpenMP/for_simd_codegen.cpp
index 7e540e263b14..c36f52704b7c 100644
--- a/test/OpenMP/for_simd_codegen.cpp
+++ b/test/OpenMP/for_simd_codegen.cpp
@@ -73,21 +73,21 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
// CHECK: store i32 [[LB_VAL]], i32* [[OMP_IV2:%[^,]+]],
-// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID:[0-9]+]]
-// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
+// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP2:%.+]] = icmp sle i32 [[IV2]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP2_BODY:.+]], label %[[SIMPLE_LOOP2_END:[^,]+]]
for (int i = 10; i > 1; i--) {
// CHECK: [[SIMPLE_LOOP2_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
// CHECK-NEXT: [[IV2_1:%.+]] = mul nsw i32 [[IV2_0]], 1
// CHECK-NEXT: [[LC_I_1:%.+]] = sub nsw i32 10, [[IV2_1]]
-// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.access.group
//
-// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
-// CHECK-NEXT: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LIN_MUL1:%.+]] = mul nsw i32 [[IV2_2]], 3
// CHECK-NEXT: [[LIN_EXT1:%.+]] = sext i32 [[LIN_MUL1]] to i64
// CHECK-NEXT: [[LIN_ADD1:%.+]] = add nsw i64 [[LIN0_1]], [[LIN_EXT1]]
@@ -95,9 +95,9 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[LIN_ADD1]], i64* [[K_PRIVATIZED:%[^,]+]]
a[k]++;
k = k + 3;
-// CHECK: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2_2:%.+]] = add nsw i32 [[IV2_2]], 1
-// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP2_ID]]
}
// CHECK: [[SIMPLE_LOOP2_END]]:
@@ -408,7 +408,10 @@ int templ1(T a, T *z) {
// CHECK-NEXT: [[I_2:%.+]] = trunc i64 [[I_1_ADD0]] to i32
// CHECK-NEXT: store i32 [[I_2]], i32*
// CHECK: [[IV2:%.+]] = load i64, i64* [[T1_OMP_IV]]
-// CHECK-NEXT: [[J_1:%.+]] = srem i64 [[IV2]], 4
+// CHECK-NEXT: [[IV2_1:%.+]] = load i64, i64* [[T1_OMP_IV]]
+// CHECK-NEXT: [[DIV_2:%.+]] = sdiv i64 [[IV2_1]], 4
+// CHECK-NEXT: [[MUL_2:%.+]] = mul nsw i64 [[DIV_2]], 4
+// CHECK-NEXT: [[J_1:%.+]] = sub nsw i64 [[IV2]], [[MUL_2]]
// CHECK-NEXT: [[J_2:%.+]] = mul nsw i64 [[J_1]], 2
// CHECK-NEXT: [[J_2_ADD0:%.+]] = add nsw i64 0, [[J_2]]
// CHECK-NEXT: store i64 [[J_2_ADD0]], i64*
@@ -556,22 +559,70 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CALC_I_1_MUL1:%.+]] = mul i32 [[CALC_I_1]], 1
// CHECK-NEXT: [[CALC_I_2:%.+]] = add i32 1, [[CALC_I_1_MUL1]]
// CHECK-NEXT: store i32 [[CALC_I_2]], i32* [[LC_I:.+]]
+
// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]
-// CHECK-NEXT: [[CALC_J_1:%.+]] = udiv i32 [[IV1_2]], 20
-// CHECK-NEXT: [[CALC_J_2:%.+]] = urem i32 [[CALC_J_1]], 3
+// CHECK: [[IV1_2_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[CALC_J_1:%.+]] = udiv i32 [[IV1_2_1]], 60
+// CHECK-NEXT: [[MUL_1:%.+]] = mul i32 [[CALC_J_1]], 60
+// CHECK-NEXT: [[SUB_3:%.+]] = sub i32 [[IV1_2]], [[MUL_1]]
+// CHECK-NEXT: [[CALC_J_2:%.+]] = udiv i32 [[SUB_3]], 20
// CHECK-NEXT: [[CALC_J_2_MUL1:%.+]] = mul i32 [[CALC_J_2]], 1
// CHECK-NEXT: [[CALC_J_3:%.+]] = add i32 2, [[CALC_J_2_MUL1]]
// CHECK-NEXT: store i32 [[CALC_J_3]], i32* [[LC_J:.+]]
+
// CHECK: [[IV1_3:%.+]] = load i32, i32* [[OMP_IV]]
-// CHECK-NEXT: [[CALC_K_1:%.+]] = udiv i32 [[IV1_3]], 5
-// CHECK-NEXT: [[CALC_K_2:%.+]] = urem i32 [[CALC_K_1]], 4
-// CHECK-NEXT: [[CALC_K_2_MUL1:%.+]] = mul i32 [[CALC_K_2]], 1
-// CHECK-NEXT: [[CALC_K_3:%.+]] = add i32 3, [[CALC_K_2_MUL1]]
-// CHECK-NEXT: store i32 [[CALC_K_3]], i32* [[LC_K:.+]]
+// CHECK: [[IV1_3_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_1:%.+]] = udiv i32 [[IV1_3_1]], 60
+// CHECK-NEXT: [[MUL_2:%.+]] = mul i32 [[DIV_1]], 60
+// CHECK-NEXT: [[ADD_3:%.+]] = sub i32 [[IV1_3]], [[MUL_2]]
+
// CHECK: [[IV1_4:%.+]] = load i32, i32* [[OMP_IV]]
-// CHECK-NEXT: [[CALC_L_1:%.+]] = urem i32 [[IV1_4]], 5
-// CHECK-NEXT: [[CALC_L_1_MUL1:%.+]] = mul i32 [[CALC_L_1]], 1
-// CHECK-NEXT: [[CALC_L_2:%.+]] = add i32 4, [[CALC_L_1_MUL1]]
+// CHECK: [[IV1_4_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_2:%.+]] = udiv i32 [[IV1_4_1]], 60
+// CHECK-NEXT: [[MUL_3:%.+]] = mul i32 [[DIV_2]], 60
+// CHECK-NEXT: [[SUB_6:%.+]] = sub i32 [[IV1_4]], [[MUL_3]]
+// CHECK-NEXT: [[DIV_3:%.+]] = udiv i32 [[SUB_6]], 20
+// CHECK-NEXT: [[MUL_4:%.+]] = mul i32 [[DIV_3]], 20
+// CHECK-NEXT: [[SUB_7:%.+]] = sub i32 [[ADD_3]], [[MUL_4]]
+// CHECK-NEXT: [[DIV_4:%.+]] = udiv i32 [[SUB_7]], 5
+// CHECK-NEXT: [[MUL_5:%.+]] = mul i32 [[DIV_4]], 1
+// CHECK-NEXT: [[ADD_6:%.+]] = add i32 3, [[MUL_5]]
+// CHECK-NEXT: store i32 [[ADD_6]], i32* [[LC_K:.+]]
+
+// CHECK: [[IV1_5:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_5_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_5:%.+]] = udiv i32 [[IV1_5_1]], 60
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[DIV_5]], 60
+// CHECK-NEXT: [[ADD_7:%.+]] = sub i32 [[IV1_5]], [[MUL_6]]
+
+// CHECK: [[IV1_6:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_6_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_6:%.+]] = udiv i32 [[IV1_6_1]], 60
+// CHECK-NEXT: [[MUL_7:%.+]] = mul i32 [[DIV_6]], 60
+// CHECK-NEXT: [[SUB_10:%.+]] = sub i32 [[IV1_6]], [[MUL_7]]
+// CHECK-NEXT: [[DIV_7:%.+]] = udiv i32 [[SUB_10]], 20
+// CHECK-NEXT: [[MUL_8:%.+]] = mul i32 [[DIV_7]], 20
+// CHECK-NEXT: [[ADD_9:%.+]] = sub i32 [[ADD_7]], [[MUL_8]]
+
+// CHECK: [[IV1_7:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_7_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_8:%.+]] = udiv i32 [[IV1_7_1]], 60
+// CHECK-NEXT: [[MUL_9:%.+]] = mul i32 [[DIV_8]], 60
+// CHECK-NEXT: [[ADD_10:%.+]] = sub i32 [[IV1_7]], [[MUL_9]]
+
+// CHECK: [[IV1_8:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_8_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_3:%.+]] = udiv i32 [[IV1_8_1]], 60
+// CHECK-NEXT: [[MUL_4:%.+]] = mul i32 [[DIV_3]], 60
+// CHECK-NEXT: [[SUB_7:%.+]] = sub i32 [[IV1_8]], [[MUL_4]]
+// CHECK-NEXT: [[DIV_4:%.+]] = udiv i32 [[SUB_7]], 20
+// CHECK-NEXT: [[MUL_5:%.+]] = mul i32 [[DIV_4]], 20
+// CHECK-NEXT: [[SUB_8:%.+]] = sub i32 [[ADD_10]], [[MUL_5]]
+// CHECK-NEXT: [[DIV_5:%.+]] = udiv i32 [[SUB_8]], 5
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[DIV_5]], 5
+// CHECK-NEXT: [[SUB_9:%.+]] = sub i32 [[ADD_9]], [[MUL_6]]
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[SUB_9]], 1
+// CHECK-NEXT: [[CALC_L_2:%.+]] = add i32 4, [[MUL_6]]
// CHECK-NEXT: [[CALC_L_3:%.+]] = trunc i32 [[CALC_L_2]] to i16
// CHECK-NEXT: store i16 [[CALC_L_3]], i16* [[LC_L:.+]]
// ... loop body ...
diff --git a/test/OpenMP/for_simd_lastprivate_messages.cpp b/test/OpenMP/for_simd_lastprivate_messages.cpp
index 9ed2232d6a37..a4bed93365ed 100644
--- a/test/OpenMP/for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/for_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
S2 &operator =(const S2&);
const S2 &operator =(const S2&) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -153,8 +153,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -194,7 +194,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
@@ -210,11 +210,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp for simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp for simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -227,7 +227,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp for simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
diff --git a/test/OpenMP/for_simd_linear_messages.cpp b/test/OpenMP/for_simd_linear_messages.cpp
index ff522e7b7ece..a87b1ab115b3 100644
--- a/test/OpenMP/for_simd_linear_messages.cpp
+++ b/test/OpenMP/for_simd_linear_messages.cpp
@@ -122,7 +122,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp for simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp for simd linear (a, b:B::ib)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp for simd linear (argv[1]) // expected-error {{expected variable name}}
@@ -186,7 +186,7 @@ int main(int argc, char **argv) {
#pragma omp for simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp for simd linear (a, b)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp for simd linear (argv[1]) // expected-error {{expected variable name}}
diff --git a/test/OpenMP/for_simd_loop_messages.cpp b/test/OpenMP/for_simd_loop_messages.cpp
index a3ae84efd4ae..29ab738dd149 100644
--- a/test/OpenMP/for_simd_loop_messages.cpp
+++ b/test/OpenMP/for_simd_loop_messages.cpp
@@ -126,8 +126,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp parallel
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
#pragma omp for simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/for_simd_reduction_messages.cpp b/test/OpenMP/for_simd_reduction_messages.cpp
index 1f5578e611ee..12368efccf23 100644
--- a/test/OpenMP/for_simd_reduction_messages.cpp
+++ b/test/OpenMP/for_simd_reduction_messages.cpp
@@ -145,11 +145,11 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -157,15 +157,15 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -177,7 +177,7 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -201,7 +201,7 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -294,11 +294,11 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -306,15 +306,15 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -326,7 +326,7 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
@@ -354,7 +354,7 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel
-#pragma omp for simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp for simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/loops_explicit_clauses_codegen.cpp b/test/OpenMP/loops_explicit_clauses_codegen.cpp
index 43fbd56b592d..5cc69b9df39d 100644
--- a/test/OpenMP/loops_explicit_clauses_codegen.cpp
+++ b/test/OpenMP/loops_explicit_clauses_codegen.cpp
@@ -39,18 +39,18 @@ int main(int argc, char **argv) {
;
foo();
// CHECK: @{{.+}}foo
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
+// CHECK-NOT: @k{{.+}}!llvm.access.group
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
+// CHECK-NOT: @k{{.+}}!llvm.access.group
// CHECK: sdiv i32
// CHECK: store i32 %{{.+}}, i32* @k,
#pragma omp simd linear(k : 2)
for (k = 0; k < argc; k++)
bar();
// CHECK: @{{.+}}foo
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
+// CHECK-NOT: @k{{.+}}!llvm.access.group
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
+// CHECK-NOT: @k{{.+}}!llvm.access.group
// CHECK: sdiv i32
// CHECK: store i32 %{{.+}}, i32* @k,
foo();
@@ -60,9 +60,9 @@ int main(int argc, char **argv) {
bar() ;
foo();
// CHECK: @{{.+}}foo
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
+// CHECK-NOT: @k{{.+}}!llvm.access.group
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
+// CHECK-NOT: @k{{.+}}!llvm.access.group
// CHECK: sdiv i32
// CHECK: store i32 %{{.+}}, i32* @k,
#pragma omp simd
@@ -70,9 +70,9 @@ int main(int argc, char **argv) {
bar();
foo();
// CHECK: @{{.+}}foo
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
-// CHECK-NOT: @k{{.+}}!llvm.mem.parallel_loop_access
+// CHECK-NOT: @k{{.+}}!llvm.access.group
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
+// CHECK-NOT: @k{{.+}}!llvm.access.group
// CHECK: sdiv i32
// CHECK: store i32 %{{.+}}, i32* @k,
#pragma omp simd collapse(2)
@@ -110,7 +110,7 @@ struct S {
// CHECK: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: br i1
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: add nsw i32 %{{.+}}, 1
// CHECK: br label {{.+}}, !llvm.loop
@@ -123,7 +123,7 @@ struct S {
// CHECK: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: br i1
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: add nsw i64 %{{.+}}, 1
// CHECK: br label {{.+}}, !llvm.loop
@@ -137,7 +137,7 @@ struct S {
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: br i1
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: add nsw i32 %{{.+}}, 1
// CHECK: br label {{.+}}, !llvm.loop
@@ -150,7 +150,7 @@ struct S {
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: br i1
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
-// CHECK: i32 @{{.+}}bar{{.+}}!llvm.mem.parallel_loop_access
+// CHECK: i32 @{{.+}}bar{{.+}}!llvm.access.group
// CHECK-NOT: getelementptr inbounds %struct.S, %struct.S* %{{.+}}, i32 0, i32 0
// CHECK: add nsw i64 %{{.+}}, 1
// CHECK: br label {{.+}}, !llvm.loop
diff --git a/test/OpenMP/nvptx_SPMD_codegen.cpp b/test/OpenMP/nvptx_SPMD_codegen.cpp
new file mode 100644
index 000000000000..738bbf34f725
--- /dev/null
+++ b/test/OpenMP/nvptx_SPMD_codegen.cpp
@@ -0,0 +1,483 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-NOT: @__omp_offloading_{{.+}}_exec_mode = weak constant i8 1
+// CHECK-DAG: [[DISTR_LIGHT:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2050, i32 3, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: [[FOR_LIGHT:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 514, i32 3, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: [[LIGHT:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 3, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: [[DISTR_FULL:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2050, i32 1, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: [[FULL:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 1, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: [[BAR_LIGHT:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 66, i32 3, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: [[BAR_FULL:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 66, i32 1, i32 0, i8* getelementptr inbounds
+// CHECK-NOT: @__omp_offloading_{{.+}}_exec_mode = weak constant i8 1
+
+void foo() {
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+#pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+int a;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+#pragma omp target teams distribute parallel for lastprivate(a)
+ for (int i = 0; i < 10; ++i)
+ a = i;
+#pragma omp target teams distribute parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+#pragma omp target teams
+ {
+ int b;
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+ ;
+ }
+#pragma omp target teams
+ {
+ int b[] = {2, 3, sizeof(int)};
+#pragma omp distribute parallel for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+ int b;
+#pragma omp distribute parallel for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+ int &c = b;
+ }
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+#pragma omp target teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[DISTR_LIGHT]]
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[DISTR_FULL]]
+// CHECK-DAG: [[FULL]]
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK-DAG: [[BAR_LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK-DAG: [[BAR_LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK-DAG: [[BAR_LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+#pragma omp target parallel
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK-DAG: [[BAR_LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK-DAG: [[BAR_LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK-DAG: [[BAR_FULL]]
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd ordered
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 0, i16 0)
+// CHECK-DAG: [[FOR_LIGHT]]
+// CHECK-DAG: [[LIGHT]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK-DAG: [[FULL]]
+#pragma omp target
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+}
+
+#endif
+
diff --git a/test/OpenMP/nvptx_data_sharing.cpp b/test/OpenMP/nvptx_data_sharing.cpp
index 0acb11991527..7b21d827941c 100644
--- a/test/OpenMP/nvptx_data_sharing.cpp
+++ b/test/OpenMP/nvptx_data_sharing.cpp
@@ -26,10 +26,15 @@ void test_ds(){
}
}
}
+// CK1: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CK1-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CK1-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CK1-DAG: [[KERNEL_SIZE:@.+]] = internal unnamed_addr constant i64 8
+// CK1-DAG: [[KERNEL_SHARED:@.+]] = internal unnamed_addr constant i16 1
/// ========= In the worker function ========= ///
// CK1: {{.*}}define internal void @__omp_offloading{{.*}}test_ds{{.*}}_worker()
-// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CK1-NOT: call void @__kmpc_data_sharing_init_stack
/// ========= In the kernel function ========= ///
@@ -39,7 +44,11 @@ void test_ds(){
// CK1: [[SHAREDARGS2:%.+]] = alloca i8**
// CK1: call void @__kmpc_kernel_init
// CK1: call void @__kmpc_data_sharing_init_stack
-// CK1: [[GLOBALSTACK:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 8, i16 0)
+// CK1: [[SHARED_MEM_FLAG:%.+]] = load i16, i16* [[KERNEL_SHARED]],
+// CK1: [[SIZE:%.+]] = load i64, i64* [[KERNEL_SIZE]],
+// CK1: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i64 [[SIZE]], i16 [[SHARED_MEM_FLAG]], i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CK1: [[KERNEL_RD:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CK1: [[GLOBALSTACK:%.+]] = getelementptr inbounds i8, i8* [[KERNEL_RD]], i64 0
// CK1: [[GLOBALSTACK2:%.+]] = bitcast i8* [[GLOBALSTACK]] to %struct._globalized_locals_ty*
// CK1: [[A:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 0
// CK1: [[B:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 1
@@ -50,8 +59,8 @@ void test_ds(){
// CK1: [[SHARGSTMP2:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP1]], i64 0
// CK1: [[SHAREDVAR:%.+]] = bitcast i32* [[A]] to i8*
// CK1: store i8* [[SHAREDVAR]], i8** [[SHARGSTMP2]]
-// CK1: call void @llvm.nvvm.barrier0()
-// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CK1: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CK1: call void @__kmpc_end_sharing_variables()
// CK1: store i32 100, i32* [[B]]
// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i16 1)
@@ -63,10 +72,11 @@ void test_ds(){
// CK1: [[SHARGSTMP12:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]], i64 1
// CK1: [[SHAREDVAR2:%.+]] = bitcast i32* [[A]] to i8*
// CK1: store i8* [[SHAREDVAR2]], i8** [[SHARGSTMP12]]
-// CK1: call void @llvm.nvvm.barrier0()
-// CK1: call void @llvm.nvvm.barrier0()
+// CK1: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CK1: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CK1: call void @__kmpc_end_sharing_variables()
-// CK1: call void @__kmpc_data_sharing_pop_stack(i8* [[GLOBALSTACK]])
+// CK1: [[SHARED_MEM_FLAG:%.+]] = load i16, i16* [[KERNEL_SHARED]],
+// CK1: call void @__kmpc_restore_team_static_memory(i16 0, i16 [[SHARED_MEM_FLAG]])
// CK1: call void @__kmpc_kernel_deinit(i16 1)
/// ========= In the data sharing wrapper function ========= ///
diff --git a/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
index 2b18f6d3f9bd..d9056eeff5c2 100644
--- a/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
+++ b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
@@ -21,12 +21,17 @@ int main(int argc, char **argv) {
return 0;
}
-// CHECK: @__omp_offloading_{{.*}}_main_l17_exec_mode = weak constant i8 1
+// CHECK: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CHECK-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CHECK-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CHECK-DAG: [[KERNEL_SIZE:@.+]] = internal unnamed_addr constant i{{64|32}} 84
+// CHECK-DAG: @__omp_offloading_{{.*}}_main_l17_exec_mode = weak constant i8 1
// CHECK-LABEL: define internal void @__omp_offloading_{{.*}}_main_l17_worker(
// CHECK: define weak void @__omp_offloading_{{.*}}_main_l17([10 x i32]* dereferenceable(40) %{{.+}}, [10 x i32]* dereferenceable(40) %{{.+}}, i32* dereferenceable(4) %{{.+}}, i{{64|32}} %{{.+}}, [10 x i32]* dereferenceable(40) %{{.+}})
-// CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 84, i16 0)
+// CHECK: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} 84, i16 1, i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CHECK: [[PTR:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
// CHECK: [[STACK:%.+]] = bitcast i8* [[PTR]] to %struct._globalized_locals_ty*
// CHECK: [[ARGC:%.+]] = load i32, i32* %{{.+}}, align
// CHECK: [[ARGC_ADDR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[STACK]], i{{32|64}} 0, i{{32|64}} 0
@@ -41,7 +46,7 @@ int main(int argc, char **argv) {
// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @
-// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]])
+// CHECK: call void @__kmpc_restore_team_static_memory(i16 0, i16 1)
// CHECK: define internal void [[PARALLEL]](
// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack(
diff --git a/test/OpenMP/nvptx_force_full_runtime_SPMD_codegen.cpp b/test/OpenMP/nvptx_force_full_runtime_SPMD_codegen.cpp
new file mode 100644
index 000000000000..395a2d48ff0f
--- /dev/null
+++ b/test/OpenMP/nvptx_force_full_runtime_SPMD_codegen.cpp
@@ -0,0 +1,326 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-cuda-force-full-runtime | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - -fopenmp-cuda-force-full-runtime | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - -fopenmp-cuda-force-full-runtime | FileCheck %s
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-NOT: @__omp_offloading_{{.+}}_exec_mode = weak constant i8 1
+
+void foo() {
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+int a;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target teams distribute parallel for lastprivate(a)
+ for (int i = 0; i < 10; ++i)
+ a = i;
+#pragma omp target teams distribute parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp distribute parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target parallel
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target parallel
+#pragma omp for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd ordered
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel
+#pragma omp for simd schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 {{.+}})
+#pragma omp target
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(static)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(static, 1)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(auto)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(runtime)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(dynamic)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp parallel for schedule(guided)
+ for (int i = 0; i < 10; ++i)
+ ;
+}
+
+#endif
+
diff --git a/test/OpenMP/nvptx_lambda_capturing.cpp b/test/OpenMP/nvptx_lambda_capturing.cpp
new file mode 100644
index 000000000000..f57fef638f43
--- /dev/null
+++ b/test/OpenMP/nvptx_lambda_capturing.cpp
@@ -0,0 +1,156 @@
+// REQUIRES: powerpc-registered-target
+// REQUIRES: nvptx-registered-target
+
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -o - | FileCheck %s --check-prefix HOST
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefixes=CLASS,FUN,CHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefixes=CLASS,CHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s --check-prefixes=FUN,CHECK
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// HOST-DAG: = private unnamed_addr constant [11 x i64] [i64 4, i64 4, i64 0, i64 4, i64 40, i64 4, i64 4, i64 4, i64 8, i64 4, i64 4]
+// HOST-DAG: = private unnamed_addr constant [11 x i64] [i64 547, i64 547, i64 544, i64 33, i64 673, i64 1407374883554064, i64 1407374883554064, i64 1407374883554064, i64 1407374883554064, i64 1407374883554064, i64 800]
+// HOST-DAG: = private unnamed_addr constant [11 x i64] [i64 4, i64 4, i64 4, i64 0, i64 4, i64 40, i64 4, i64 4, i64 4, i64 8, i64 4]
+// HOST-DAG: = private unnamed_addr constant [11 x i64] [i64 547, i64 547, i64 547, i64 544, i64 547, i64 673, i64 1688849860264720, i64 1688849860264720, i64 1688849860264720, i64 1688849860264720, i64 1688849860264720]
+// HOST-DAG: = private unnamed_addr constant [3 x i64] [i64 4, i64 8, i64 8]
+// HOST-DAG: = private unnamed_addr constant [3 x i64] [i64 547, i64 673, i64 562949953422096]
+// HOST-DAG: = private unnamed_addr constant [3 x i64] [i64 4, i64 8, i64 8]
+// HOST-DAG: = private unnamed_addr constant [3 x i64] [i64 547, i64 673, i64 562949953422096]
+// HOST-DAG: = private unnamed_addr constant [2 x i64] [i64 8, i64 8]
+// HOST-DAG: = private unnamed_addr constant [2 x i64] [i64 673, i64 281474976711440]
+// CHECK-DAG: [[S:%.+]] = type { i32 }
+// CHECK-DAG: [[CAP1:%.+]] = type { [[S]]* }
+// CHECK-DAG: [[CAP2:%.+]] = type { i32*, i32*, i32*, i32**, i32* }
+
+// CLASS: define internal void @__omp_offloading_{{.*}}_{{.*}}foo{{.*}}_l72_worker()
+// CLASS: define weak void @__omp_offloading_{{.*}}_{{.*}}foo{{.*}}_l72([[S]]* {{%.+}}, [[CAP1]]* dereferenceable(8) {{%.+}})
+// CLASS-NOT: getelementptr
+// CLASS: br i1 %
+// CLASS: call void @__omp_offloading_{{.*}}_{{.*}}foo{{.*}}_l72_worker()
+// CLASS: br label %
+// CLASS: br i1 %
+// CLASS: call void @__kmpc_kernel_init(
+// CLASS: call void @__kmpc_data_sharing_init_stack()
+// CLASS: call void @llvm.memcpy.
+// CLASS: [[L:%.+]] = load [[CAP1]]*, [[CAP1]]** [[L_ADDR:%.+]],
+// CLASS: [[THIS_REF:%.+]] = getelementptr inbounds [[CAP1]], [[CAP1]]* [[L]], i32 0, i32 0
+// CLASS: store [[S]]* [[S_:%.+]], [[S]]** [[THIS_REF]],
+// CLASS: [[L:%.+]] = load [[CAP1]]*, [[CAP1]]** [[L_ADDR]],
+// CLASS: call i32 [[LAMBDA1:@.+foo.+]]([[CAP1]]* [[L]])
+// CLASS: ret void
+
+// CLASS: define weak void @__omp_offloading_{{.+}}foo{{.+}}_l74([[S]]* %{{.+}}, [[CAP1]]* dereferenceable(8) %{{.+}})
+// CLASS-NOT: getelementptr
+// CLASS: call void [[PARALLEL:@.+]](i32* %{{.+}}, i32* %{{.+}}, [[S]]* %{{.+}}, [[CAP1]]* %{{.+}})
+// CLASS: ret void
+
+// CLASS: define internal void [[PARALLEL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, [[S]]* %{{.+}}, [[CAP1]]* dereferenceable(8) %{{.+}})
+// CLASS-NOT: getelementptr
+// CLASS: call void @llvm.memcpy.
+// CLASS: [[L:%.+]] = load [[CAP1]]*, [[CAP1]]** [[L_ADDR:%.+]],
+// CLASS: [[THIS_REF:%.+]] = getelementptr inbounds [[CAP1]], [[CAP1]]* [[L]], i32 0, i32 0
+// CLASS: store [[S]]* %{{.+}}, [[S]]** [[THIS_REF]],
+// CLASS: [[L:%.+]] = load [[CAP1]]*, [[CAP1]]** [[L_ADDR]],
+// CLASS: call i32 [[LAMBDA1]]([[CAP1]]* [[L]])
+// CLASS: ret void
+
+template <typename T>
+int foo(const T &t) {
+ #pragma omp target parallel
+ t();
+ return 0;
+}
+
+struct S {
+ int a = 15;
+ int foo() {
+ auto &&L = [&]() { return a; };
+#pragma omp target
+ L();
+#pragma omp target parallel
+ L();
+ return a + ::foo(L);
+ }
+} s;
+
+// FUN: define internal void @__omp_offloading_{{.+}}_main_l134_worker()
+// FUN: define weak void @__omp_offloading_{{.+}}_main_l134(i32* dereferenceable(4) %{{.+}}, i32* dereferenceable(4) %{{.+}}, i32* %{{.+}}, i32* dereferenceable(4) %{{.+}}, [[CAP2]]* dereferenceable(40) %{{.+}}, i64 %{{.+}})
+// FUN-NOT: getelementptr
+// FUN: br i1 %
+// FUN: call void @__omp_offloading_{{.*}}_{{.*}}main{{.*}}_l134_worker()
+// FUN: br label %
+// FUN: br i1 %
+// FUN: call void @__kmpc_kernel_init(
+// FUN: call void @__kmpc_data_sharing_init_stack()
+// FUN: call void @llvm.memcpy.
+// FUN: [[L:%.+]] = load [[CAP2]]*, [[CAP2]]** [[L_ADDR:%.+]],
+// FUN: [[ARGC_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 0
+// FUN: store i32* %{{.+}}, i32** [[ARGC_CAP]],
+// FUN: [[B_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 1
+// FUN: store i32* %{{.+}}, i32** [[B_CAP]],
+// FUN: [[C_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 2
+// FUN: store i32* %{{.+}}, i32** [[C_CAP]],
+// FUN: [[D_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 3
+// FUN: store i32** %{{.+}}, i32*** [[D_CAP]],
+// FUN: [[A_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 4
+// FUN: store i32* %{{.+}}, i32** [[A_CAP]],
+// FUN: [[L:%.+]] = load [[CAP2]]*, [[CAP2]]** [[L_ADDR:%.+]],
+// FUN: call i64 [[LAMBDA2:@.+main.+]]([[CAP2]]* [[L]])
+// FUN: ret void
+
+// FUN: define weak void @__omp_offloading_{{.+}}_main_l136(i32* dereferenceable(4) %{{.+}}, i32* dereferenceable(4) %{{.+}} i32* dereferenceable(4) %{{.+}}, i32* %{{.+}}, i32* dereferenceable(4) %{{.+}}, [[CAP2]]* dereferenceable(40) %{{.+}})
+// FUN-NOT: getelementptr
+// FUN: call void [[PARALLEL:@.+]](i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, [[CAP2]]* %{{.+}})
+// FUN: ret void
+
+// FUN: define internal void [[PARALLEL:@.+]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}}, i32* dereferenceable(4) %{{.+}}, i32* dereferenceable(4) %{{.+}}, i32* %{{.+}}, i32* dereferenceable(4) %{{.+}}, [[CAP2]]* dereferenceable(40) %{{.+}})
+// FUN-NOT: getelementptr
+// FUN: call void @llvm.memcpy.
+// FUN: [[L:%.+]] = load [[CAP2]]*, [[CAP2]]** [[L_ADDR]],
+// FUN: [[ARGC_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 0
+// FUN: store i32* %{{.+}}, i32** [[ARGC_CAP]],
+// FUN: [[B_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 1
+// FUN: store i32* %{{.+}}, i32** [[B_CAP]],
+// FUN: [[C_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 2
+// FUN: store i32* %{{.+}}, i32** [[C_CAP]],
+// FUN: [[D_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 3
+// FUN: store i32** %{{.+}}, i32*** [[D_CAP]],
+// FUN: [[A_CAP:%.+]] = getelementptr inbounds [[CAP2]], [[CAP2]]* [[L]], i32 0, i32 4
+// FUN: store i32* %{{.+}}, i32** [[A_CAP]],
+// FUN: [[L:%.+]] = load [[CAP2]]*, [[CAP2]]** [[L_ADDR]],
+// FUN: call i64 [[LAMBDA2]]([[CAP2]]* [[L]])
+// FUN: ret void
+
+int main(int argc, char **argv) {
+ int &b = argc;
+ int &&c = 1;
+ int *d = &argc;
+ int a;
+ auto &&L = [&]() { return argc + b + c + reinterpret_cast<long int>(d) + a; };
+#pragma omp target firstprivate(argc) map(to : a)
+ L();
+#pragma omp target parallel
+ L();
+ return argc + s.foo();
+}
+
+
+// HOST-LABEL: @main
+
+// HOST-DAG: call i32 @__tgt_target(i64 -1, i8* @{{.+}}, i32 11, i8** [[BASES:%.+]], i8** [[PTRS:%.+]],
+// HOST-DAG: [[BASES:%.+]] = getelementptr inbounds [11 x i8*], [11 x i8*]* [[BASE_PTR:%.+]], i32 0, i32 0
+// HOST-DAG: [[PTRS:%.+]] = getelementptr inbounds [11 x i8*], [11 x i8*]* [[PTR_PTR:%.+]], i32 0, i32 0
+// HOST-DAG: [[BASE_REF:%.+]] = getelementptr inbounds [11 x i8*], [11 x i8*]* [[BASE_PTR]], i32 0, i32 5
+// HOST-DAG: [[BASE_REF_CAST:%.+]] = bitcast i8** [[BASE_REF]] to i32***
+// HOST-DAG: store i32** [[BASE:%.+]], i32*** [[BASE_REF_CAST]],
+// HOST-DAG: [[BASE]] = getelementptr inbounds [[LAMBDA:%.+]], [[LAMBDA]]* [[LAMBDA_ADDR:%.+]], i32 0, i32 0
+// HOST-DAG: [[PTR_REF:%.+]] = getelementptr inbounds [11 x i8*], [11 x i8*]* [[PTR_PTR]], i32 0, i32 5
+// HOST-DAG: [[PTR_REF_CAST:%.+]] = bitcast i8** [[PTR_REF]] to i32**
+// HOST-DAG: store i32* [[PTR:%.+]], i32** [[PTR_REF_CAST]],
+// HOST-DAG: [[PTR]] = load i32*, i32** [[PTR_REF:%.+]],
+// HOST-DAG: [[PTR_REF]] = getelementptr inbounds [[LAMBDA]], [[LAMBDA]]* [[LAMBDA_ADDR]], i32 0, i32 0
+#endif // HEADER
diff --git a/test/OpenMP/nvptx_parallel_codegen.cpp b/test/OpenMP/nvptx_parallel_codegen.cpp
index d1a3104407d0..04089ce3f5b6 100644
--- a/test/OpenMP/nvptx_parallel_codegen.cpp
+++ b/test/OpenMP/nvptx_parallel_codegen.cpp
@@ -45,6 +45,7 @@ tx ftemplate(int n) {
#pragma omp parallel if(n>1000)
{
int a = 45;
+#pragma omp barrier
}
a += 1;
aa += 1;
@@ -71,6 +72,12 @@ int bar(int n){
return a;
}
+// CHECK: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CHECK-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CHECK-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CHECK-DAG: [[KERNEL_SIZE:@.+]] = internal unnamed_addr constant i{{64|32}} 4
+// CHECK-DAG: [[KERNEL_SHARED:@.+]] = internal unnamed_addr constant i16 1
+
// CHECK-NOT: define {{.*}}void {{@__omp_offloading_.+template.+l17}}_worker()
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}_worker()
@@ -81,7 +88,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
@@ -120,7 +127,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
@@ -157,21 +164,21 @@ int bar(int n){
// CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
// CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN1]]_wrapper to i8*),
-// CHECK: call void @llvm.nvvm.barrier0()
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: call void @__kmpc_serialized_parallel(
// CHECK: {{call|invoke}} void [[PARALLEL_FN3:@.+]](
// CHECK: call void @__kmpc_end_serialized_parallel(
// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN2]]_wrapper to i8*),
-// CHECK: call void @llvm.nvvm.barrier0()
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK-64-DAG: load i32, i32* [[REF_A]]
// CHECK-32-DAG: load i32, i32* [[LOCAL_A]]
// CHECK: br label {{%?}}[[TERMINATE:.+]]
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
@@ -200,7 +207,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]],
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
@@ -230,7 +237,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
@@ -282,8 +289,8 @@ int bar(int n){
//
// CHECK: [[IF_THEN]]
// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN4]]_wrapper to i8*),
-// CHECK: call void @llvm.nvvm.barrier0()
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[IF_END:.+]]
//
// CHECK: [[IF_ELSE]]
@@ -302,7 +309,7 @@ int bar(int n){
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
@@ -311,19 +318,28 @@ int bar(int n){
// CHECK: define internal void [[PARALLEL_FN4]](
// CHECK: [[A:%.+]] = alloca i[[SZ:32|64]],
// CHECK: store i[[SZ]] 45, i[[SZ]]* %a,
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* @{{.+}}, i32 %{{.+}})
// CHECK: ret void
-// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l54}}_worker()
-// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l54}}(
+// CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32) #[[BARRIER_ATTRS:.+]]
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l55}}_worker()
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l55}}(
// CHECK-32: [[A_ADDR:%.+]] = alloca i32,
// CHECK-64: [[A_ADDR:%.+]] = alloca i64,
// CHECK-64: [[CONV:%.+]] = bitcast i64* [[A_ADDR]] to i32*
-// CHECK: [[STACK:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 4, i16 0)
+// CHECK: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED]],
+// CHECK: [[SIZE:%.+]] = load i{{64|32}}, i{{64|32}}* [[KERNEL_SIZE]],
+// CHECK: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} [[SIZE]], i16 [[IS_SHARED]], i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CHECK: [[KERNEL_RD:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CHECK: [[STACK:%.+]] = getelementptr inbounds i8, i8* [[KERNEL_RD]], i{{64|32}} 0
// CHECK: [[BC:%.+]] = bitcast i8* [[STACK]] to %struct._globalized_locals_ty*
// CHECK-32: [[A:%.+]] = load i32, i32* [[A_ADDR]],
// CHECK-64: [[A:%.+]] = load i32, i32* [[CONV]],
// CHECK: [[GLOBAL_A_ADDR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[BC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: store i32 [[A]], i32* [[GLOBAL_A_ADDR]],
+// CHECK: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED]],
+// CHECK: call void @__kmpc_restore_team_static_memory(i16 0, i16 [[IS_SHARED]])
// CHECK-LABEL: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable{{.*}})
// CHECK: [[CC:%.+]] = alloca i32,
@@ -340,9 +356,17 @@ int bar(int n){
// CHECK: [[RES:%.+]] = icmp eq i32 [[TID]], [[CC_VAL]]
// CHECK: br i1 [[RES]], label
-// CHECK: call void @llvm.nvvm.barrier0()
+// CHECK: call void @__kmpc_critical(
+// CHECK: load i32, i32*
+// CHECK: add nsw i32
+// CHECK: store i32
+// CHECK: call void @__kmpc_end_critical(
+
+// CHECK: call void @__kmpc_barrier(%struct.ident_t* @{{.+}}, i32 %{{.+}})
// CHECK: [[NEW_CC_VAL:%.+]] = add nsw i32 [[CC_VAL]], 1
// CHECK: store i32 [[NEW_CC_VAL]], i32* [[CC]],
// CHECK: br label
+// CHECK: attributes #[[BARRIER_ATTRS]] = {{.*}} convergent {{.*}}
+
#endif
diff --git a/test/OpenMP/nvptx_parallel_for_codegen.cpp b/test/OpenMP/nvptx_parallel_for_codegen.cpp
new file mode 100644
index 000000000000..1446ba50cea8
--- /dev/null
+++ b/test/OpenMP/nvptx_parallel_for_codegen.cpp
@@ -0,0 +1,134 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+template<typename tx>
+tx ftemplate(int n) {
+ tx b[10];
+
+ #pragma omp target
+ {
+ tx d = n;
+ #pragma omp parallel for
+ for(int i=0; i<10; i++) {
+ b[i] += d;
+ }
+ b[3] += 1;
+ }
+
+ return b[3];
+}
+
+int bar(int n){
+ int a = 0;
+
+ a += ftemplate<int>(n);
+
+ return a;
+}
+
+// CHECK: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CHECK-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CHECK-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CHECK-DAG: [[KERNEL_SIZE:@.+]] = internal unnamed_addr constant i{{64|32}} 4
+// CHECK-DAG: [[KERNEL_SHARED:@.+]] = internal unnamed_addr constant i16 1
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l12}}_worker()
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call i1 @__kmpc_kernel_parallel(
+// CHECK: call void @__omp_outlined___wrapper(
+
+// CHECK: define weak void @__omp_offloading_{{.*}}l12(
+// CHECK: call void @__omp_offloading_{{.*}}l12_worker()
+// CHECK: call void @__kmpc_kernel_init(
+// CHECK: call void @__kmpc_data_sharing_init_stack()
+// CHECK: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED]],
+// CHECK: [[SIZE:%.+]] = load i{{64|32}}, i{{64|32}}* [[KERNEL_SIZE]],
+// CHECK: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i64 %7, i16 %6, i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CHECK: [[KERNEL_RD:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CHECK: [[STACK:%.+]] = getelementptr inbounds i8, i8* [[KERNEL_RD]], i{{64|32}} 0
+// CHECK: call void @__kmpc_kernel_prepare_parallel(
+// CHECK: call void @__kmpc_begin_sharing_variables({{.*}}, i64 2)
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call void @__kmpc_end_sharing_variables()
+// CHECK: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED]],
+// CHECK: call void @__kmpc_restore_team_static_memory(i16 0, i16 [[IS_SHARED]])
+// CHECK: call void @__kmpc_kernel_deinit(i16 1)
+
+// CHECK: define internal void @__omp_outlined__(
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: [[OMP_IV:%.*]] = alloca i32
+// CHECK: store i32 0, {{.*}} [[OMP_LB:%.+]],
+// CHECK: store i32 9, {{.*}} [[OMP_UB:%.+]],
+// CHECK: store i32 1, {{.*}} [[OMP_ST:%.+]],
+// CHECK: call void @__kmpc_for_static_init_4({{.*}} i32 33, {{.*}} [[OMP_LB]], {{.*}} [[OMP_UB]], {{.*}} [[OMP_ST]], i32 1, i32 1)
+// CHECK: br label %[[OMP_DISPATCH_COND:.+]]
+
+// CHECK: [[OMP_DISPATCH_COND]]
+// CHECK: [[OMP_UB_1:%.+]] = load {{.*}} [[OMP_UB]]
+// CHECK: [[COMP_1:%.+]] = icmp sgt {{.*}} [[OMP_UB_1]]
+// CHECK: br i1 [[COMP_1]], label %[[COND_TRUE:.+]], label %[[COND_FALSE:.+]]
+
+// CHECK: [[COND_TRUE]]
+// CHECK: br label %[[COND_END:.+]]
+
+// CHECK: [[COND_FALSE]]
+// CHECK: [[OMP_UB_2:%.+]] = load {{.*}}* [[OMP_UB]]
+// CHECK: br label %[[COND_END]]
+
+// CHECK: [[COND_END]]
+// CHECK: [[COND_RES:%.+]] = phi i32 [ 9, %[[COND_TRUE]] ], [ [[OMP_UB_2]], %[[COND_FALSE]] ]
+// CHECK: store i32 [[COND_RES]], i32* [[OMP_UB]]
+// CHECK: [[OMP_LB_1:%.+]] = load i32, i32* [[OMP_LB]]
+// CHECK: store i32 [[OMP_LB_1]], i32* [[OMP_IV]]
+// CHECK: [[OMP_IV_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[OMP_UB_3:%.+]] = load i32, i32* [[OMP_UB]]
+// CHECK: [[COMP_2:%.+]] = icmp sle i32 [[OMP_IV_1]], [[OMP_UB_3]]
+// CHECK: br i1 [[COMP_2]], label %[[DISPATCH_BODY:.+]], label %[[DISPATCH_END:.+]]
+
+// CHECK: [[DISPATCH_BODY]]
+// CHECK: br label %[[OMP_INNER_FOR_COND:.+]]
+
+// CHECK: [[OMP_INNER_FOR_COND]]
+// CHECK: [[OMP_IV_2:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[OMP_UB_4:%.+]] = load i32, i32* [[OMP_UB]]
+// CHECK: [[COMP_3:%.+]] = icmp sle i32 [[OMP_IV_2]], [[OMP_UB_4]]
+// CHECK: br i1 [[COMP_3]], label %[[OMP_INNER_FOR_BODY:.+]], label %[[OMP_INNER_FOR_END:.+]]
+
+// CHECK: [[OMP_INNER_FOR_BODY]]
+// CHECK: br label %[[OMP_BODY_CONTINUE:.+]]
+
+// CHECK: [[OMP_BODY_CONTINUE]]
+// CHECK: br label %[[OMP_INNER_FOR_INC:.+]]
+
+// CHECK: [[OMP_INNER_FOR_INC]]
+// CHECK: [[OMP_IV_3:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[ADD_1:%.+]] = add nsw i32 [[OMP_IV_3]], 1
+// CHECK: store i32 [[ADD_1]], i32* [[OMP_IV]]
+// CHECK: br label %[[OMP_INNER_FOR_COND]]
+
+// CHECK: [[OMP_INNER_FOR_COND]]
+// CHECK: br label %[[OMP_DISPATCH_INC:.+]]
+
+// CHECK: [[OMP_DISPATCH_INC]]
+// CHECK: [[OMP_LB_2:%.+]] = load i32, i32* [[OMP_LB]]
+// CHECK: [[OMP_ST_1:%.+]] = load i32, i32* [[OMP_ST]]
+// CHECK: [[ADD_2:%.+]] = add nsw i32 [[OMP_LB_2]], [[OMP_ST_1]]
+// CHECK: store i32 [[ADD_2]], i32* [[OMP_LB]]
+// CHECK: [[OMP_UB_5:%.+]] = load i32, i32* [[OMP_UB]]
+// CHECK: [[OMP_ST_2:%.+]] = load i32, i32* [[OMP_ST]]
+// CHECK: [[ADD_3:%.+]] = add nsw i32 [[OMP_UB_5]], [[OMP_ST_2]]
+// CHECK: store i32 [[ADD_3]], i32* [[OMP_UB]]
+
+// CHECK: [[DISPATCH_END]]
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/nvptx_target_codegen.cpp b/test/OpenMP/nvptx_target_codegen.cpp
index 5f9b3bd32808..b05ee9dee6e6 100644
--- a/test/OpenMP/nvptx_target_codegen.cpp
+++ b/test/OpenMP/nvptx_target_codegen.cpp
@@ -8,13 +8,18 @@
#ifndef HEADER
#define HEADER
-// Check that the execution mode of all 6 target regions is set to Generic Mode.
-// CHECK-DAG: {{@__omp_offloading_.+l103}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l180}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l290}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l328}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l346}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l311}}_exec_mode = weak constant i8 1
+// Check that the execution mode of all 7 target regions is set to Generic Mode.
+// CHECK-DAG: [[NONSPMD:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: [[UNKNOWN:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 2, i32 0, i8* getelementptr inbounds
+// CHECK-DAG: {{@__omp_offloading_.+l59}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l137}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l214}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l324}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l362}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l380}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l345}}_exec_mode = weak constant i8 1
+// CHECK-DAG: [[MAP_TY:%.+]] = type { [128 x i8] }
+// CHECK-DAG: [[GLOB_TY:%.+]] = type { i32* }
__thread int id;
@@ -27,6 +32,35 @@ struct TT{
tx &operator[](int i) { return X; }
};
+// CHECK: define weak void @__omp_offloading_{{.+}}_{{.+}}targetBar{{.+}}_l59(i32* [[PTR1:%.+]], i32** dereferenceable{{.*}} [[PTR2_REF:%.+]])
+// CHECK: store i32* [[PTR1]], i32** [[PTR1_ADDR:%.+]],
+// CHECK: store i32** [[PTR2_REF]], i32*** [[PTR2_REF_PTR:%.+]],
+// CHECK: [[PTR2_REF:%.+]] = load i32**, i32*** [[PTR2_REF_PTR]],
+// CHECK: call void @__kmpc_kernel_init(
+// CHECK: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MAP_TY]], [[MAP_TY]] addrspace(3)* @{{.+}}, i32 0, i32 0, i32 0) to i8*), i{{64|32}} %{{.+}}, i16 %{{.+}}, i8** addrspacecast (i8* addrspace(3)* [[BUF_PTR:@.+]] to i8**))
+// CHECK: [[BUF:%.+]] = load i8*, i8* addrspace(3)* [[BUF_PTR]],
+// CHECK: [[BUF_OFFS:%.+]] = getelementptr inbounds i8, i8* [[BUF]], i{{[0-9]+}} 0
+// CHECK: [[BUF:%.+]] = bitcast i8* [[BUF_OFFS]] to [[GLOB_TY]]*
+// CHECK: [[PTR1:%.+]] = load i32*, i32** [[PTR1_ADDR]],
+// CHECK: [[PTR1_GLOB_REF:%.+]] = getelementptr inbounds [[GLOB_TY]], [[GLOB_TY]]* [[BUF]], i32 0, i32 0
+// CHECK: store i32* [[PTR1]], i32** [[PTR1_GLOB_REF]],
+// CHECK: call void @__kmpc_begin_sharing_variables(i8*** [[ARG_PTRS_REF:%.+]], i{{64|32}} 2)
+// CHECK: [[ARG_PTRS:%.+]] = load i8**, i8*** [[ARG_PTRS_REF]],
+// CHECK: [[ARG_PTR1:%.+]] = getelementptr inbounds i8*, i8** [[ARG_PTRS]], i{{[0-9]+}} 0
+// CHECK: [[BC:%.+]] = bitcast i32** [[PTR1_GLOB_REF]] to i8*
+// CHECK: store i8* [[BC]], i8** [[ARG_PTR1]],
+// CHECK: [[ARG_PTR2:%.+]] = getelementptr inbounds i8*, i8** [[ARG_PTRS]], i{{[0-9]+}} 1
+// CHECK: [[BC:%.+]] = bitcast i32** [[PTR2_REF]] to i8*
+// CHECK: store i8* [[BC]], i8** [[ARG_PTR2]],
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+// CHECK: call void @__kmpc_end_sharing_variables()
+void targetBar(int *Ptr1, int *Ptr2) {
+#pragma omp target map(Ptr1[:0], Ptr2)
+#pragma omp parallel num_threads(2)
+ *Ptr1 = *Ptr2;
+}
+
int foo(int n) {
int a = 0;
short aa = 0;
@@ -36,7 +70,7 @@ int foo(int n) {
double cn[5][n];
TT<long long, char> d;
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l103}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l137}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -44,7 +78,7 @@ int foo(int n) {
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
@@ -61,13 +95,13 @@ int foo(int n) {
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l103]]()
+ // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l137]]()
// CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
// CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
@@ -95,7 +129,7 @@ int foo(int n) {
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
@@ -109,7 +143,7 @@ int foo(int n) {
{
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l180}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l214}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -117,7 +151,7 @@ int foo(int n) {
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
@@ -134,13 +168,13 @@ int foo(int n) {
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+foo.+l180]](i[[SZ:32|64]] [[ARG1:%[a-zA-Z_]+]], i[[SZ:32|64]] [[ID:%[a-zA-Z_]+]])
+ // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+foo.+l214]](i[[SZ:32|64]] [[ARG1:%[a-zA-Z_]+]], i[[SZ:32|64]] [[ID:%[a-zA-Z_]+]])
// CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]],
// CHECK: store i[[SZ]] [[ARG1]], i[[SZ]]* [[AA_ADDR]],
// CHECK: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i16*
@@ -172,7 +206,7 @@ int foo(int n) {
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
@@ -183,7 +217,7 @@ int foo(int n) {
id = aa;
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l290}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l324}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -191,7 +225,7 @@ int foo(int n) {
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
@@ -208,13 +242,13 @@ int foo(int n) {
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l290]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l324]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_B:%.+]] = alloca [10 x float]*
@@ -282,7 +316,7 @@ int foo(int n) {
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
@@ -375,7 +409,7 @@ int baz(int f, double &a) {
return f;
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+328}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+362}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -383,7 +417,7 @@ int baz(int f, double &a) {
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
@@ -400,13 +434,13 @@ int baz(int f, double &a) {
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+static.+l328]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+static.+l362]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]]
@@ -453,7 +487,7 @@ int baz(int f, double &a) {
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
@@ -461,16 +495,15 @@ int baz(int f, double &a) {
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l346}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l380}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
- // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
// CHECK: store i8 0, i8* [[OMP_EXEC_STATUS]],
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
@@ -481,6 +514,7 @@ int baz(int f, double &a) {
// CHECK: br i1 [[IS_ACTIVE]], label {{%?}}[[EXEC_PARALLEL:.+]], label {{%?}}[[BAR_PARALLEL:.+]]
//
// CHECK: [[EXEC_PARALLEL]]
+ // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[NONSPMD]]
// CHECK: [[WORK_FN:%.+]] = bitcast i8* [[WORK]] to void (i16, i32)*
// CHECK: call void [[WORK_FN]](i16 0, i32 [[GTID]])
// CHECK: br label {{%?}}[[TERM_PARALLEL:.+]]
@@ -489,13 +523,13 @@ int baz(int f, double &a) {
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+S1.+l346]](
+ // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+S1.+l380]](
// Create local storage for each capture.
// CHECK: [[LOCAL_THIS:%.+]] = alloca [[S1:%struct.*]]*
// CHECK: [[LOCAL_B:%.+]] = alloca i[[SZ]]
@@ -547,59 +581,74 @@ int baz(int f, double &a) {
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
// CHECK: define i32 [[BAZ]](i32 [[F:%.*]], double* dereferenceable{{.*}})
+ // CHECK: alloca i32,
+ // CHECK: [[LOCAL_F_PTR:%.+]] = alloca i32,
// CHECK: [[ZERO_ADDR:%.+]] = alloca i32,
- // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
- // CHECK: [[GTID_ADDR:%.+]] = alloca i32,
// CHECK: store i32 0, i32* [[ZERO_ADDR]]
- // CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 4, i16 0)
- // CHECK: [[REC_ADDR:%.+]] = bitcast i8* [[PTR]] to %struct._globalized_locals_ty*
- // CHECK: [[F_PTR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[REC_ADDR]], i32 0, i32 0
+ // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[UNKNOWN]]
+ // CHECK: [[PAR_LEVEL:%.+]] = call i16 @__kmpc_parallel_level(%struct.ident_t* [[UNKNOWN]], i32 [[GTID]])
+ // CHECK: [[IS_TTD:%.+]] = icmp eq i16 %1, 0
+ // CHECK: [[RES:%.+]] = call i8 @__kmpc_is_spmd_exec_mode()
+ // CHECK: [[IS_SPMD:%.+]] = icmp ne i8 [[RES]], 0
+ // CHECK: br i1 [[IS_SPMD]], label
+ // CHECK: br label
+ // CHECK: [[SIZE:%.+]] = select i1 [[IS_TTD]], i{{64|32}} 4, i{{64|32}} 128
+ // CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_coalesced_push_stack(i{{64|32}} [[SIZE]], i16 0)
+ // CHECK: [[REC_ADDR:%.+]] = bitcast i8* [[PTR]] to [[GLOBAL_ST:%.+]]*
+ // CHECK: br label
+ // CHECK: [[ITEMS:%.+]] = phi [[GLOBAL_ST]]* [ null, {{.+}} ], [ [[REC_ADDR]], {{.+}} ]
+ // CHECK: [[TTD_ITEMS:%.+]] = bitcast [[GLOBAL_ST]]* [[ITEMS]] to [[SEC_GLOBAL_ST:%.+]]*
+ // CHECK: [[F_PTR_ARR:%.+]] = getelementptr inbounds [[GLOBAL_ST]], [[GLOBAL_ST]]* [[ITEMS]], i32 0, i32 0
+ // CHECK: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+ // CHECK: [[LID:%.+]] = and i32 [[TID]], 31
+ // CHECK: [[GLOBAL_F_PTR_PAR:%.+]] = getelementptr inbounds [32 x i32], [32 x i32]* [[F_PTR_ARR]], i32 0, i32 [[LID]]
+ // CHECK: [[GLOBAL_F_PTR_TTD:%.+]] = getelementptr inbounds [[SEC_GLOBAL_ST]], [[SEC_GLOBAL_ST]]* [[TTD_ITEMS]], i32 0, i32 0
+ // CHECK: [[GLOBAL_F_PTR:%.+]] = select i1 [[IS_TTD]], i32* [[GLOBAL_F_PTR_TTD]], i32* [[GLOBAL_F_PTR_PAR]]
+ // CHECK: [[F_PTR:%.+]] = select i1 [[IS_SPMD]], i32* [[LOCAL_F_PTR]], i32* [[GLOBAL_F_PTR]]
// CHECK: store i32 %{{.+}}, i32* [[F_PTR]],
// CHECK: [[RES:%.+]] = call i8 @__kmpc_is_spmd_exec_mode()
// CHECK: icmp ne i8 [[RES]], 0
// CHECK: br i1
- // CHECK: [[RES:%.+]] = call i16 @__kmpc_parallel_level(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+ // CHECK: [[RES:%.+]] = call i16 @__kmpc_parallel_level(%struct.ident_t* [[UNKNOWN]], i32 [[GTID]])
// CHECK: icmp ne i16 [[RES]], 0
// CHECK: br i1
- // CHECK: call void @__kmpc_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+ // CHECK: call void @__kmpc_serialized_parallel(%struct.ident_t* [[UNKNOWN]], i32 [[GTID]])
// CHECK: call void [[OUTLINED:@.+]](i32* [[ZERO_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}})
- // CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+ // CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* [[UNKNOWN]], i32 [[GTID]])
// CHECK: br label
- // CHECK: icmp eq i32
- // CHECK: br i1
-
// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* @{{.+}} to i8*), i16 1)
// CHECK: call void @__kmpc_begin_sharing_variables(i8*** [[SHARED_PTR:%.+]], i{{64|32}} 2)
// CHECK: [[SHARED:%.+]] = load i8**, i8*** [[SHARED_PTR]],
// CHECK: [[REF:%.+]] = getelementptr inbounds i8*, i8** [[SHARED]], i{{64|32}} 0
// CHECK: [[F_REF:%.+]] = bitcast i32* [[F_PTR]] to i8*
// CHECK: store i8* [[F_REF]], i8** [[REF]],
- // CHECK: call void @llvm.nvvm.barrier0()
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: call void @__kmpc_end_sharing_variables()
// CHECK: br label
- // CHECK: store i32 [[GTID]], i32* [[GTID_ADDR]],
- // CHECK: call void [[OUTLINED]](i32* [[GTID_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}})
- // CHECK: br label
-
// CHECK: [[RES:%.+]] = load i32, i32* [[F_PTR]],
- // CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]])
+ // CHECK: store i32 [[RES]], i32* [[RET:%.+]],
+ // CHECK: br i1 [[IS_SPMD]], label
+ // CHECK: [[BC:%.+]] = bitcast [[GLOBAL_ST]]* [[ITEMS]] to i8*
+ // CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[BC]])
+ // CHECK: br label
+ // CHECK: [[RES:%.+]] = load i32, i32* [[RET]],
// CHECK: ret i32 [[RES]]
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l311}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l345}}_worker()
// CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8,
// CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*,
// CHECK: store i8* null, i8** [[OMP_WORK_FN]],
@@ -607,7 +656,7 @@ int baz(int f, double &a) {
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]],
// CHECK: [[SHOULD_EXIT:%.+]] = icmp eq i8* [[WORK]], null
// CHECK: br i1 [[SHOULD_EXIT]], label {{%?}}[[EXIT:.+]], label {{%?}}[[SEL_WORKERS:.+]]
@@ -624,13 +673,13 @@ int baz(int f, double &a) {
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l311]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l345]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]]
@@ -676,9 +725,10 @@ int baz(int f, double &a) {
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
+
#endif
diff --git a/test/OpenMP/nvptx_target_parallel_codegen.cpp b/test/OpenMP/nvptx_target_parallel_codegen.cpp
index 15611f647588..7964d768d799 100644
--- a/test/OpenMP/nvptx_target_parallel_codegen.cpp
+++ b/test/OpenMP/nvptx_target_parallel_codegen.cpp
@@ -59,7 +59,7 @@ int bar(int n){
// CHECK: store i16* {{%.+}}, i16** [[AA_ADDR]], align
// CHECK: [[AA:%.+]] = load i16*, i16** [[AA_ADDR]], align
// CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
@@ -68,7 +68,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
// CHECK: br label {{%?}}[[EXIT:.+]]
//
// CHECK: [[EXIT]]
@@ -102,7 +102,7 @@ int bar(int n){
// CHECK: [[AA:%.+]] = load i16*, i16** [[AA_ADDR]], align
// CHECK: [[B:%.+]] = load [10 x i32]*, [10 x i32]** [[B_ADDR]], align
// CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
- // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
@@ -111,7 +111,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
// CHECK: br label {{%?}}[[EXIT:.+]]
//
// CHECK: [[EXIT]]
diff --git a/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp b/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp
index 1cdcb70417b8..4b32f9d87bcd 100644
--- a/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp
+++ b/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp
@@ -47,7 +47,7 @@ int bar(int n){
}
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l22}}(
- // CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
@@ -57,7 +57,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
// CHECK: br label {{%?}}[[EXIT:.+]]
//
// CHECK: [[EXIT]]
@@ -69,7 +69,7 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}(
- // CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
@@ -79,7 +79,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
// CHECK: br label {{%?}}[[EXIT:.+]]
//
// CHECK: [[EXIT]]
@@ -90,7 +90,7 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l31}}(
- // CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXEC:.+]]
//
@@ -100,7 +100,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[DONE:.+]]
//
// CHECK: [[DONE]]
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
// CHECK: br label {{%?}}[[EXIT:.+]]
//
// CHECK: [[EXIT]]
diff --git a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp
index 02676272b0fe..c23f275bd1a4 100644
--- a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp
+++ b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp
@@ -9,7 +9,7 @@
#define HEADER
// Check for the data transfer medium in shared memory to transfer the reduction list to the first warp.
-// CHECK-DAG: [[TRANSFER_STORAGE:@.+]] = common addrspace([[SHARED_ADDRSPACE:[0-9]+]]) global [32 x i64]
+// CHECK-DAG: [[TRANSFER_STORAGE:@.+]] = common addrspace([[SHARED_ADDRSPACE:[0-9]+]]) global [32 x i32]
// Check that the execution mode of all 3 target regions is set to Spmd Mode.
// CHECK-DAG: {{@__omp_offloading_.+l27}}_exec_mode = weak constant i8 0
@@ -54,13 +54,13 @@ int bar(int n){
// CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l27}}(
//
- // CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXECUTE:.+]]
//
// CHECK: [[EXECUTE]]
// CHECK: {{call|invoke}} void [[PFN:@.+]](i32*
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
//
//
// define internal void [[PFN]](
@@ -72,19 +72,17 @@ int bar(int n){
// CHECK: [[E_CAST:%.+]] = bitcast double* [[E]] to i8*
// CHECK: store i8* [[E_CAST]], i8** [[PTR1]], align
// CHECK: [[ARG_RL:%.+]] = bitcast [[RLT]]* [[RL]] to i8*
- // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_parallel_reduce_nowait(i32 {{.+}}, i32 1, i{{32|64}} {{4|8}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]])
- // CHECK: switch i32 [[RET]], label {{%?}}[[DEFAULTLABEL:.+]] [
- // CHECK: i32 1, label {{%?}}[[REDLABEL:.+]]
+ // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_parallel_reduce_nowait_v2(%struct.ident_t* @{{.+}}, i32 {{.+}}, i32 1, i{{32|64}} {{4|8}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]])
+ // CHECK: [[CMP:%.+]] = icmp eq i32 [[RET]], 1
+ // CHECK: br i1 [[CMP]], label
- // CHECK: [[REDLABEL]]
// CHECK: [[E_INV:%.+]] = load double, double* [[E_IN:%.+]], align
// CHECK: [[EV:%.+]] = load double, double* [[E]], align
// CHECK: [[ADD:%.+]] = fadd double [[E_INV]], [[EV]]
// CHECK: store double [[ADD]], double* [[E_IN]], align
// CHECK: call void @__kmpc_nvptx_end_reduce_nowait(
- // CHECK: br label %[[DEFAULTLABEL]]
+ // CHECK: br label
//
- // CHECK: [[DEFAULTLABEL]]
// CHECK: ret
//
@@ -187,18 +185,24 @@ int bar(int n){
// CHECK-DAG: [[LANEID:%.+]] = and i32 {{.+}}, 31
// CHECK-DAG: [[WARPID:%.+]] = ashr i32 {{.+}}, 5
// CHECK-DAG: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
+ // CHECK: store i32 0, i32* [[CNT_ADDR:%.+]],
+ // CHECK: br label
+ // CHECK: [[CNT:%.+]] = load i32, i32* [[CNT_ADDR]],
+ // CHECK: [[DONE_COPY:%.+]] = icmp ult i32 [[CNT]], 2
+ // CHECK: br i1 [[DONE_COPY]], label
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
// CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
// CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
//
// [[DO_COPY]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
+ // CHECK: [[BASE_ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
+ // CHECK: [[ELT:%.+]] = getelementptr i32, i32* [[BASE_ELT]], i32 [[CNT]]
//
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
- // CHECK: store double [[ELT_VAL]], double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
+ // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]],
+ // CHECK: store volatile i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]],
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
// CHECK: [[COPY_ELSE]]
@@ -206,29 +210,30 @@ int bar(int n){
//
// Barrier after copy to shared memory storage medium.
// CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
+ // CHECK: [[ACTIVE_WARPS:%.+]] = load i32, i32*
//
// Read into warp 0.
// CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
// CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
//
// CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: store double [[MEDIUM_ELT_VAL]], double* [[ELT]], align
+ // CHECK: [[ELT_BASE:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
+ // CHECK: [[ELT:%.+]] = getelementptr i32, i32* [[ELT_BASE]], i32 [[CNT]]
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load volatile i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]],
+ // CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]],
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
// CHECK: [[READ_ELSE]]
// CHECK: br label {{%?}}[[READ_CONT]]
//
// CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: [[NEXT:%.+]] = add nsw i32 [[CNT]], 1
+ // CHECK: store i32 [[NEXT]], i32* [[CNT_ADDR]],
+ // CHECK: br label
// CHECK: ret
@@ -242,13 +247,13 @@ int bar(int n){
// CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l32}}(
//
- // CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXECUTE:.+]]
//
// CHECK: [[EXECUTE]]
// CHECK: {{call|invoke}} void [[PFN1:@.+]](i32*
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
//
//
// define internal void [[PFN1]](
@@ -267,11 +272,9 @@ int bar(int n){
// CHECK: [[D_CAST:%.+]] = bitcast float* [[D]] to i8*
// CHECK: store i8* [[D_CAST]], i8** [[PTR2]], align
// CHECK: [[ARG_RL:%.+]] = bitcast [[RLT]]* [[RL]] to i8*
- // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_parallel_reduce_nowait(i32 {{.+}}, i32 2, i{{32|64}} {{8|16}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]])
- // CHECK: switch i32 [[RET]], label {{%?}}[[DEFAULTLABEL:.+]] [
- // CHECK: i32 1, label {{%?}}[[REDLABEL:.+]]
-
- // CHECK: [[REDLABEL]]
+ // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_parallel_reduce_nowait_v2(%struct.ident_t* @{{.+}}, i32 {{.+}}, i32 2, i{{32|64}} {{8|16}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]])
+ // CHECK: [[CMP:%.+]] = icmp eq i32 [[RET]], 1
+ // CHECK: br i1 [[CMP]], label
// CHECK: [[C_INV8:%.+]] = load i8, i8* [[C_IN:%.+]], align
// CHECK: [[C_INV:%.+]] = sext i8 [[C_INV8]] to i32
// CHECK: [[CV8:%.+]] = load i8, i8* [[C]], align
@@ -284,9 +287,8 @@ int bar(int n){
// CHECK: [[MUL:%.+]] = fmul float [[D_INV]], [[DV]]
// CHECK: store float [[MUL]], float* [[D_IN]], align
// CHECK: call void @__kmpc_nvptx_end_reduce_nowait(
- // CHECK: br label %[[DEFAULTLABEL]]
+ // CHECK: br label
//
- // CHECK: [[DEFAULTLABEL]]
// CHECK: ret
//
@@ -425,6 +427,7 @@ int bar(int n){
// CHECK-DAG: [[LANEID:%.+]] = and i32 {{.+}}, 31
// CHECK-DAG: [[WARPID:%.+]] = ashr i32 {{.+}}, 5
// CHECK-DAG: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
// CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
// CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
//
@@ -432,10 +435,10 @@ int bar(int n){
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
//
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
+ // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
// CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
- // CHECK: store i8 [[ELT_VAL]], i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: store volatile i8 [[ELT_VAL]], i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
// CHECK: [[COPY_ELSE]]
@@ -443,20 +446,19 @@ int bar(int n){
//
// Barrier after copy to shared memory storage medium.
// CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
+ // CHECK: [[ACTIVE_WARPS:%.+]] = load i32, i32*
//
// Read into warp 0.
// CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
// CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
//
// CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT32:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
+ // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT32]] to i8 addrspace([[SHARED_ADDRSPACE]])*
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load volatile i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i8 [[MEDIUM_ELT_VAL]], i8* [[ELT_VOID]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -464,19 +466,18 @@ int bar(int n){
// CHECK: br label {{%?}}[[READ_CONT]]
//
// CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
// CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
// CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
//
// [[DO_COPY]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
//
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
- // CHECK: store float [[ELT_VAL]], float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
+ // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
+ // CHECK: store volatile i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
// CHECK: [[COPY_ELSE]]
@@ -484,29 +485,26 @@ int bar(int n){
//
// Barrier after copy to shared memory storage medium.
// CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
+ // CHECK: [[ACTIVE_WARPS:%.+]] = load i32, i32*
//
// Read into warp 0.
// CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
// CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
//
// CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: store float [[MEDIUM_ELT_VAL]], float* [[ELT]], align
+ // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load volatile i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
// CHECK: [[READ_ELSE]]
// CHECK: br label {{%?}}[[READ_CONT]]
//
// CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
// CHECK: ret
@@ -520,13 +518,13 @@ int bar(int n){
// CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l38}}(
//
- // CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
// CHECK: br label {{%?}}[[EXECUTE:.+]]
//
// CHECK: [[EXECUTE]]
// CHECK: {{call|invoke}} void [[PFN2:@.+]](i32*
- // CHECK: call void @__kmpc_spmd_kernel_deinit()
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
//
//
// define internal void [[PFN2]](
@@ -559,11 +557,10 @@ int bar(int n){
// CHECK: [[B_CAST:%.+]] = bitcast i16* [[B]] to i8*
// CHECK: store i8* [[B_CAST]], i8** [[PTR2]], align
// CHECK: [[ARG_RL:%.+]] = bitcast [[RLT]]* [[RL]] to i8*
- // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_parallel_reduce_nowait(i32 {{.+}}, i32 2, i{{32|64}} {{8|16}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]])
- // CHECK: switch i32 [[RET]], label {{%?}}[[DEFAULTLABEL:.+]] [
- // CHECK: i32 1, label {{%?}}[[REDLABEL:.+]]
+ // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_parallel_reduce_nowait_v2(%struct.ident_t* @{{.+}}, i32 {{.+}}, i32 2, i{{32|64}} {{8|16}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]])
+ // CHECK: [[CMP:%.+]] = icmp eq i32 [[RET]], 1
+ // CHECK: br i1 [[CMP]], label
- // CHECK: [[REDLABEL]]
// CHECK: [[A_INV:%.+]] = load i32, i32* [[A_IN:%.+]], align
// CHECK: [[AV:%.+]] = load i32, i32* [[A]], align
// CHECK: [[OR:%.+]] = or i32 [[A_INV]], [[AV]]
@@ -587,9 +584,8 @@ int bar(int n){
// CHECK: [[B_MAX:%.+]] = phi i16 [ [[MAX1]], %[[DO_MAX]] ], [ [[MAX2]], %[[MAX_ELSE]] ]
// CHECK: store i16 [[B_MAX]], i16* [[B_IN]], align
// CHECK: call void @__kmpc_nvptx_end_reduce_nowait(
- // CHECK: br label %[[DEFAULTLABEL]]
+ // CHECK: br label
//
- // CHECK: [[DEFAULTLABEL]]
// CHECK: ret
//
@@ -744,6 +740,7 @@ int bar(int n){
// CHECK-DAG: [[LANEID:%.+]] = and i32 {{.+}}, 31
// CHECK-DAG: [[WARPID:%.+]] = ashr i32 {{.+}}, 5
// CHECK-DAG: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
// CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
// CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
//
@@ -752,10 +749,9 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
//
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
- // CHECK: store i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: store volatile i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
// CHECK: [[COPY_ELSE]]
@@ -763,21 +759,19 @@ int bar(int n){
//
// Barrier after copy to shared memory storage medium.
// CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
+ // CHECK: [[ACTIVE_WARPS:%.+]] = load i32, i32*
//
// Read into warp 0.
// CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
// CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
//
// CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load volatile i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -785,7 +779,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[READ_CONT]]
//
// CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
// CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
// CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
//
@@ -794,10 +788,10 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
//
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT32:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
+ // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT32]] to i16 addrspace([[SHARED_ADDRSPACE]])*
// CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
- // CHECK: store i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: store volatile i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
// CHECK: [[COPY_ELSE]]
@@ -805,21 +799,20 @@ int bar(int n){
//
// Barrier after copy to shared memory storage medium.
// CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
+ // CHECK: [[ACTIVE_WARPS:%.+]] = load i32, i32*
//
// Read into warp 0.
// CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
// CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
//
// CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT32:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
+ // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT32]] to i16 addrspace([[SHARED_ADDRSPACE]])*
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load volatile i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i16 [[MEDIUM_ELT_VAL]], i16* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -827,7 +820,6 @@ int bar(int n){
// CHECK: br label {{%?}}[[READ_CONT]]
//
// CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
// CHECK: ret
#endif
diff --git a/test/OpenMP/nvptx_target_printf_codegen.c b/test/OpenMP/nvptx_target_printf_codegen.c
index e7bfb874f4ef..a68a9fc8cd9d 100644
--- a/test/OpenMP/nvptx_target_printf_codegen.c
+++ b/test/OpenMP/nvptx_target_printf_codegen.c
@@ -6,8 +6,11 @@
// expected-no-diagnostics
extern int printf(const char *, ...);
+// CHECK-DAG: private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds
+
// Check a simple call to printf end-to-end.
-// CHECK: [[SIMPLE_PRINTF_TY:%[a-zA-Z0-9_]+]] = type { i32, i64, double }
+// CHECK-DAG: [[SIMPLE_PRINTF_TY:%[a-zA-Z0-9_]+]] = type { i32, i64, double }
+// CHECK-NOT: private unnamed_addr constant %struct.ident_t { i32 0, i32 2, {{1|2|3}}
int CheckSimple() {
// CHECK: define {{.*}}void [[T1:@__omp_offloading_.+CheckSimple.+]]_worker()
#pragma omp target
diff --git a/test/OpenMP/nvptx_target_teams_codegen.cpp b/test/OpenMP/nvptx_target_teams_codegen.cpp
index c7667d83b9aa..069eecb6079e 100644
--- a/test/OpenMP/nvptx_target_teams_codegen.cpp
+++ b/test/OpenMP/nvptx_target_teams_codegen.cpp
@@ -67,7 +67,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1)
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
@@ -88,7 +88,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
@@ -134,7 +134,7 @@ int bar(int n){
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
@@ -153,7 +153,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1)
// CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8
// store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1
@@ -174,7 +174,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[BAR_PARALLEL]]
//
// CHECK: [[BAR_PARALLEL]]
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[AWAIT_WORK]]
//
// CHECK: [[EXIT]]
@@ -220,21 +220,21 @@ int bar(int n){
//
// CHECK: [[TERMINATE]]
// CHECK: call void @__kmpc_kernel_deinit(
- // CHECK: call void @llvm.nvvm.barrier0()
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[EXIT]]
// CHECK: ret void
// CHECK: define weak void @__omp_offloading_{{.*}}ftemplate{{.*}}_l37(
-// CHECK: call void @__kmpc_spmd_kernel_init(
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 {{.+}}, i16 1, i16 0)
// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
-// CHECK: call i8* @__kmpc_data_sharing_push_stack(
+// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack(
// CHECK-NOT: call void @__kmpc_serialized_parallel(
// CHECK: call void [[L0:@.+]](i32* %{{.+}}, i32* %{{.+}}, i16* %{{.*}})
// CHECK-NOT: call void @__kmpc_end_serialized_parallel(
-// CHECK: call void @__kmpc_data_sharing_pop_stack(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK-NOT: call void @__kmpc_data_sharing_pop_stack(
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
// CHECK: ret
// CHECK: define internal void [[L0]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i16* dereferenceable
diff --git a/test/OpenMP/nvptx_target_teams_distribute_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_codegen.cpp
new file mode 100644
index 000000000000..3a0e5138277e
--- /dev/null
+++ b/test/OpenMP/nvptx_target_teams_distribute_codegen.cpp
@@ -0,0 +1,90 @@
+// Test target codegen - host bc file has to be created first.
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CHECK-DAG: {{@__omp_offloading_.+}}_l19_exec_mode = weak constant i8 1
+// CHECK-DAG: internal unnamed_addr constant i{{64|32}} 4
+
+template<typename tx>
+tx ftemplate(int n) {
+ int i;
+
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; ++i)
+ {
+#pragma omp parallel
+ ++i;
+ }
+
+ return i;
+}
+
+int bar(int n){
+ int a = 0;
+
+ a += ftemplate<char>(n);
+
+ return a;
+}
+
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l19}}_worker()
+ // CHECK: ret void
+
+ // CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l19}}()
+
+ // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+ // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+ // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+ // CHECK-DAG: [[TH_LIMIT:%.+]] = sub nuw i32 [[NTH]], [[WS]]
+ // CHECK: [[IS_WORKER:%.+]] = icmp ult i32 [[TID]], [[TH_LIMIT]]
+ // CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[CHECK_MASTER:.+]]
+ //
+ // CHECK: [[WORKER]]
+ // CHECK: {{call|invoke}} void {{@__omp_offloading_.+template.+l19}}_worker()
+ // CHECK: br label {{%?}}[[EXIT:.+]]
+ //
+ // CHECK: [[CHECK_MASTER]]
+ // CHECK-DAG: [[CMTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+ // CHECK-DAG: [[CMNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+ // CHECK-DAG: [[CMWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+ // CHECK: [[IS_MASTER:%.+]] = icmp eq i32 [[CMTID]],
+ // CHECK: br i1 [[IS_MASTER]], label {{%?}}[[MASTER:.+]], label {{%?}}[[EXIT]]
+ //
+ // CHECK: [[MASTER]]
+ // CHECK-DAG: [[MNTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
+ // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
+ // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]]
+ // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]]
+ // CHECK: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* @{{.+}}, i32 0, i32 0, i32 0) to i8*), i{{64|32}} 4, i16 1, i8** addrspacecast (i8* addrspace(3)* [[BUF:@.+]] to i8**))
+ // CHECK: [[PTR:%.+]] = load i8*, i8* addrspace(3)* [[BUF]],
+ // CHECK: [[RD:%.+]] = bitcast i8* [[PTR]] to [[GLOB_TY:%.+]]*
+ // CHECK: [[I_ADDR:%.+]] = getelementptr inbounds [[GLOB_TY]], [[GLOB_TY]]* [[RD]], i32 0, i32 0
+ //
+ // CHECK: call void @__kmpc_for_static_init_4(
+ // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* @{{.+}} to i8*), i16 1)
+ // CHECK: call void @__kmpc_begin_sharing_variables(i8*** [[SHARED_VARS_PTR:%.+]], i{{64|32}} 1)
+ // CHECK: [[SHARED_VARS_BUF:%.+]] = load i8**, i8*** [[SHARED_VARS_PTR]],
+ // CHECK: [[I_ADDR_BC:%.+]] = bitcast i32* [[I_ADDR]] to i8*
+ // CHECK: store i8* [[I_ADDR_BC]], i8** [[SHARED_VARS_BUF]],
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+ // CHECK: call void @__kmpc_end_sharing_variables()
+ // CHECK: call void @__kmpc_for_static_fini(
+ // CHECK: br label {{%?}}[[TERMINATE:.+]]
+ //
+ // CHECK: [[TERMINATE]]
+ // CHECK: call void @__kmpc_kernel_deinit(
+ // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0)
+ // CHECK: br label {{%?}}[[EXIT]]
+ //
+ // CHECK: [[EXIT]]
+ // CHECK: ret void
+
+#endif
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
index f74919fc828d..fe0c8dfb63fd 100644
--- a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
@@ -1,6 +1,7 @@
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix CHECK-DIV64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -fopenmp-optimistic-collapse -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-DIV32
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fopenmp-cuda-mode -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
@@ -8,12 +9,13 @@
#ifndef HEADER
#define HEADER
-// Check that the execution mode of all 2 target regions on the gpu is set to SPMD Mode.
-// CHECK-DAG: {{@__omp_offloading_.+l32}}_exec_mode = weak constant i8 0
-// CHECK-DAG: {{@__omp_offloading_.+l38}}_exec_mode = weak constant i8 0
-// CHECK-DAG: {{@__omp_offloading_.+l43}}_exec_mode = weak constant i8 0
-// CHECK-DAG: {{@__omp_offloading_.+l48}}_exec_mode = weak constant i8 0
-// CHECK-DAG: {{@__omp_offloading_.+l56}}_exec_mode = weak constant i8 0
+// Check that the execution mode of all 5 target regions on the gpu is set to SPMD Mode.
+// CHECK-DAG: {{@__omp_offloading_.+l34}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l40}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l45}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l50}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l58}}_exec_mode = weak constant i8 0
+// CHECK-DAG: {{@__omp_offloading_.+l65}}_exec_mode = weak constant i8 0
#define N 1000
#define M 10
@@ -35,7 +37,7 @@ tx ftemplate(int n) {
l = i;
}
- #pragma omp target teams distribute parallel for map(tofrom: aa) num_teams(M) thread_limit(64)
+#pragma omp target teams distribute parallel for map(tofrom: aa) num_teams(M) thread_limit(64)
for(int i = 0; i < n; i++) {
aa[i] += 1;
}
@@ -53,6 +55,13 @@ tx ftemplate(int n) {
}
}
+#pragma omp target teams distribute parallel for collapse(2)
+ for(int i = 0; i < n; i++) {
+ for(int j = 0; j < n; j++) {
+ c[i][j] = i + j;
+ }
+ }
+
#pragma omp target teams distribute parallel for map(a, v[:N])
for(int i = 0; i < n; i++)
a[i] = v[i];
@@ -67,14 +76,24 @@ int bar(int n){
return a;
}
-// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CHECK-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CHECK-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CHECK-DAG: [[KERNEL_SIZE:@.+]] = internal unnamed_addr constant i{{64|32}} 4
+// CHECK-DAG: [[KERNEL_SHARED:@.+]] = internal unnamed_addr constant i16 1
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}_l34(
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
+// CHECK: call void @__kmpc_get_team_static_memory(i16 1, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} 4, i16 1, i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CHECK: [[TEAM_ALLOC:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CHECK: [[BC:%.+]] = bitcast i8* [[TEAM_ALLOC]] to [[REC:%.+]]*
+// CHECK: getelementptr inbounds [[REC]], [[REC]]* [[BC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
// CHECK: {{call|invoke}} void [[OUTL1:@.+]](
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_restore_team_static_memory(i16 1, i16 1)
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
// CHECK: define internal void [[OUTL1]](
@@ -84,52 +103,132 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
// CHECK: {{call|invoke}} void [[OUTL2:@.+]](
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
// CHECK: define internal void [[OUTL2]](
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
// CHECK: {{call|invoke}} void [[OUTL3:@.+]](
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
// CHECK: define internal void [[OUTL3]](
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
+// Distribute with collapse(2)
// CHECK: define {{.*}}void {{@__omp_offloading_.+}}({{.+}}, i{{32|64}} [[F_IN:%.+]])
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: [[OMP_IV:%.+]] = alloca
+// CHECK: alloca
+// CHECK: alloca
+// CHECK: [[OMP_LB:%.+]] = alloca
+// CHECK: [[OMP_UB:%.+]] = alloca
+// CHECK: [[OMP_ST:%.+]] = alloca
// CHECK: store {{.+}} [[F_IN]], {{.+}}* {{.+}},
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
// CHECK: store {{.+}} 99, {{.+}}* [[COMB_UB:%.+]], align
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]],
-// CHECK: {{call|invoke}} void [[OUTL4:@.+]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]],
+
+// check EUB for distribute
+// CHECK-DAG: [[OMP_UB_VAL_1:%.+]] = load{{.+}} [[OMP_UB]],
+// CHECK-DAG: [[CMP_UB_NUM_IT:%.+]] = icmp sgt {{.+}} [[OMP_UB_VAL_1]], 99
+// CHECK: br {{.+}} [[CMP_UB_NUM_IT]], label %[[EUB_TRUE:.+]], label %[[EUB_FALSE:.+]]
+// CHECK-DAG: [[EUB_TRUE]]:
+// CHECK: br label %[[EUB_END:.+]]
+// CHECK-DAG: [[EUB_FALSE]]:
+// CHECK: [[OMP_UB_VAL2:%.+]] = load{{.+}} [[OMP_UB]],
+// CHECK: br label %[[EUB_END]]
+// CHECK-DAG: [[EUB_END]]:
+// CHECK-DAG: [[EUB_RES:%.+]] = phi{{.+}} [ 99, %[[EUB_TRUE]] ], [ [[OMP_UB_VAL2]], %[[EUB_FALSE]] ]
+// CHECK: store{{.+}} [[EUB_RES]], {{.+}}* [[OMP_UB]],
+
+// initialize omp.iv
+// CHECK: [[OMP_LB_VAL_1:%.+]] = load{{.+}}, {{.+}}* [[OMP_LB]],
+// CHECK: store {{.+}} [[OMP_LB_VAL_1]], {{.+}}* [[OMP_IV]],
+
+// check exit condition
+// CHECK-DAG: [[OMP_IV_VAL_1:%.+]] = load {{.+}} [[OMP_IV]],
+// CHECK: [[CMP_IV_UB:%.+]] = icmp slt {{.+}} [[OMP_IV_VAL_1]], 100
+// CHECK: br {{.+}} [[CMP_IV_UB]], label %[[DIST_INNER_LOOP_BODY:.+]], label %[[DIST_INNER_LOOP_END:.+]]
+
+// check that PrevLB and PrevUB are passed to the 'for'
+// CHECK: [[DIST_INNER_LOOP_BODY]]:
+// CHECK-DAG: [[OMP_PREV_LB:%.+]] = load {{.+}}, {{.+}} [[OMP_LB]],
+// CHECK-64-DAG: [[OMP_PREV_LB_EXT:%.+]] = zext {{.+}} [[OMP_PREV_LB]] to {{.+}}
+// CHECK-DAG: [[OMP_PREV_UB:%.+]] = load {{.+}}, {{.+}} [[OMP_UB]],
+// CHECK-64-DAG: [[OMP_PREV_UB_EXT:%.+]] = zext {{.+}} [[OMP_PREV_UB]] to {{.+}}
+
+// check that distlb and distub are properly passed to the outlined function
+// CHECK-32: {{call|invoke}} void [[OUTL4:@.+]]({{.*}} i32 [[OMP_PREV_LB]], i32 [[OMP_PREV_UB]]
+// CHECK-64: {{call|invoke}} void [[OUTL4:@.+]]({{.*}} i64 [[OMP_PREV_LB_EXT]], i64 [[OMP_PREV_UB_EXT]]
+
+// check DistInc
+// CHECK-DAG: [[OMP_IV_VAL_3:%.+]] = load {{.+}}, {{.+}}* [[OMP_IV]],
+// CHECK-DAG: [[OMP_ST_VAL_1:%.+]] = load {{.+}}, {{.+}}* [[OMP_ST]],
+// CHECK: [[OMP_IV_INC:%.+]] = add{{.+}} [[OMP_IV_VAL_3]], [[OMP_ST_VAL_1]]
+// CHECK: store{{.+}} [[OMP_IV_INC]], {{.+}}* [[OMP_IV]],
+// CHECK-DAG: [[OMP_LB_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+// CHECK-DAG: [[OMP_ST_VAL_2:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
+// CHECK-DAG: [[OMP_LB_NEXT:%.+]] = add{{.+}} [[OMP_LB_VAL_2]], [[OMP_ST_VAL_2]]
+// CHECK: store{{.+}} [[OMP_LB_NEXT]], {{.+}}* [[OMP_LB]],
+// CHECK-DAG: [[OMP_UB_VAL_5:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+// CHECK-DAG: [[OMP_ST_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_ST]],
+// CHECK-DAG: [[OMP_UB_NEXT:%.+]] = add{{.+}} [[OMP_UB_VAL_5]], [[OMP_ST_VAL_3]]
+// CHECK: store{{.+}} [[OMP_UB_NEXT]], {{.+}}* [[OMP_UB]],
+
+// Update UB
+// CHECK-DAG: [[OMP_UB_VAL_6:%.+]] = load{{.+}}, {{.+}} [[OMP_UB]],
+// CHECK-DAG: [[CMP_UB_NUM_IT_1:%.+]] = icmp sgt {{.+}}[[OMP_UB_VAL_6]], 99
+// CHECK: br {{.+}} [[CMP_UB_NUM_IT_1]], label %[[EUB_TRUE_1:.+]], label %[[EUB_FALSE_1:.+]]
+// CHECK-DAG: [[EUB_TRUE_1]]:
+// CHECK: br label %[[EUB_END_1:.+]]
+// CHECK-DAG: [[EUB_FALSE_1]]:
+// CHECK: [[OMP_UB_VAL3:%.+]] = load{{.+}} [[OMP_UB]],
+// CHECK: br label %[[EUB_END_1]]
+// CHECK-DAG: [[EUB_END_1]]:
+// CHECK-DAG: [[EUB_RES_1:%.+]] = phi{{.+}} [ 99, %[[EUB_TRUE_1]] ], [ [[OMP_UB_VAL3]], %[[EUB_FALSE_1]] ]
+// CHECK: store{{.+}} [[EUB_RES_1]], {{.+}}* [[OMP_UB]],
+
+// Store LB in IV
+// CHECK-DAG: [[OMP_LB_VAL_3:%.+]] = load{{.+}}, {{.+}} [[OMP_LB]],
+// CHECK: store{{.+}} [[OMP_LB_VAL_3]], {{.+}}* [[OMP_IV]],
+
+// CHECK: [[DIST_INNER_LOOP_END]]:
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
-// CHECK: define internal void [[OUTL4]](
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK-32: define internal void [[OUTL4]](
+// CHECK-64: define internal void [[OUTL4]](
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
-// CHECK: define weak void @__omp_offloading_{{.*}}_l56(i[[SZ:64|32]] %{{[^,]+}}, [1000 x i32]* dereferenceable{{.*}}, i32* %{{[^)]+}})
+// CHECK: define weak void @__omp_offloading_{{.*}}_l58(i[[SZ:64|32]] %{{[^,]+}}, [10 x [10 x i32]]* dereferenceable{{.*}})
+// CHECK: call void [[OUTLINED:@__omp_outlined.*]](i32* %{{.+}}, i32* %{{.+}}, i[[SZ]] %{{.*}}, i[[SZ]] %{{.*}}, i[[SZ]] %{{.*}}, [10 x [10 x i32]]* %{{.*}})
+// CHECK: define internal void [[OUTLINED]](i32* noalias %{{.*}}, i32* noalias %{{.*}} i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x [10 x i32]]* dereferenceable{{.*}})
+// CHECK-DIV64: div i64
+// CHECK-DIV32-NO: div i64
+
+// CHECK: define weak void @__omp_offloading_{{.*}}_l65(i[[SZ:64|32]] %{{[^,]+}}, [1000 x i32]* dereferenceable{{.*}}, i32* %{{[^)]+}})
// CHECK: call void [[OUTLINED:@__omp_outlined.*]](i32* %{{.+}}, i32* %{{.+}}, i[[SZ]] %{{.*}}, i[[SZ]] %{{.*}}, i[[SZ]] %{{.*}}, [1000 x i32]* %{{.*}}, i32* %{{.*}})
// CHECK: define internal void [[OUTLINED]](i32* noalias %{{.*}}, i32* noalias %{{.*}} i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [1000 x i32]* dereferenceable{{.*}}, i32* %{{.*}})
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
index d75a10210905..f7ce26296139 100644
--- a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
@@ -22,8 +22,8 @@ int main(int argc, char **argv) {
// CHECK: @__omp_offloading_{{.*}}_main_l16_exec_mode = weak constant i8 0
// CHECK: define weak void @__omp_offloading_{{.*}}_main_l16(i{{64|32}} %{{[^,].*}}, i32* dereferenceable{{[^,]*}}, i{{64|32}} %{{[^,)]*}})
-// CHECK: [[TID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @
// CHECK: call void @__kmpc_spmd_kernel_init(
+// CHECK: [[TID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void [[PARALLEL:@.+]](i32* %{{.*}}, i32* %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.*}}, i{{64|32}} %{{.*}}, i32* %{{.*}})
@@ -32,7 +32,7 @@ int main(int argc, char **argv) {
// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: define internal void [[PARALLEL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} [[ARGC:%.+]], i32* dereferenceable{{.*}})
// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack(
diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
index 0b945a69b054..21fb46fc51d3 100644
--- a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
@@ -8,7 +8,7 @@
#ifndef HEADER
#define HEADER
-// Check that the execution mode of all 2 target regions on the gpu is set to SPMD Mode.
+// Check that the execution mode of all 4 target regions on the gpu is set to SPMD Mode.
// CHECK-DAG: {{@__omp_offloading_.+l30}}_exec_mode = weak constant i8 0
// CHECK-DAG: {{@__omp_offloading_.+l36}}_exec_mode = weak constant i8 0
// CHECK-DAG: {{@__omp_offloading_.+l41}}_exec_mode = weak constant i8 0
@@ -33,7 +33,7 @@ tx ftemplate(int n) {
l = i;
}
- #pragma omp target teams distribute parallel for simd map(tofrom: aa) num_teams(M) thread_limit(64)
+ #pragma omp target teams distribute parallel for simd map(tofrom: aa) num_teams(M) thread_limit(64)
for(int i = 0; i < n; i++) {
aa[i] += 1;
}
@@ -62,14 +62,24 @@ int bar(int n){
return a;
}
-// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
+// CHECK-DAG: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CHECK-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CHECK-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CHECK-DAG: [[KERNEL_SIZE:@.+]] = internal unnamed_addr constant i{{64|32}} 4
+// CHECK-DAG: [[KERNEL_SHARED:@.+]] = internal unnamed_addr constant i16 1
+
+// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}_l30(
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
+// CHECK: call void @__kmpc_get_team_static_memory(i16 1, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} 4, i16 1, i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CHECK: [[TEAM_ALLOC:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CHECK: [[BC:%.+]] = bitcast i8* [[TEAM_ALLOC]] to [[REC:%.+]]*
+// CHECK: getelementptr inbounds [[REC]], [[REC]]* [[BC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
// CHECK: {{call|invoke}} void [[OUTL1:@.+]](
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_restore_team_static_memory(i16 1, i16 1)
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
// CHECK: define internal void [[OUTL1]](
@@ -79,48 +89,45 @@ int bar(int n){
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
// CHECK: {{call|invoke}} void [[OUTL2:@.+]](
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
// CHECK: define internal void [[OUTL2]](
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
// CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}(
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92,
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91,
// CHECK: {{call|invoke}} void [[OUTL3:@.+]](
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
// CHECK: define internal void [[OUTL3]](
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
// CHECK: define {{.*}}void {{@__omp_offloading_.+}}({{.+}}, i{{32|64}} [[F_IN:%.+]])
// CHECK: store {{.+}} [[F_IN]], {{.+}}* {{.+}},
// CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
-// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]],
-// CHECK: call void @__kmpc_data_sharing_init_stack_spmd
+// CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], i16 0, i16 0)
// CHECK: store {{.+}} 99, {{.+}}* [[COMB_UB:%.+]], align
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]],
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]],
// CHECK: {{call|invoke}} void [[OUTL4:@.+]](
// CHECK: call void @__kmpc_for_static_fini(
-// CHECK: call void @__kmpc_spmd_kernel_deinit()
+// CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 0)
// CHECK: ret void
// CHECK: define internal void [[OUTL4]](
-// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 34,
+// CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 33,
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void
diff --git a/test/OpenMP/nvptx_teams_codegen.cpp b/test/OpenMP/nvptx_teams_codegen.cpp
index 2c50f037b228..2d1ab9f06362 100644
--- a/test/OpenMP/nvptx_teams_codegen.cpp
+++ b/test/OpenMP/nvptx_teams_codegen.cpp
@@ -27,6 +27,14 @@ int main (int argc, char **argv) {
return tmain(argv);
}
+// CK1: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CK1-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CK1-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CK1-DAG: [[KERNEL_SIZE1:@.+]] = internal unnamed_addr constant i{{64|32}} 4
+// CK1-DAG: [[KERNEL_SIZE2:@.+]] = internal unnamed_addr constant i{{64|32}} {{8|4}}
+// CK1-DAG: [[KERNEL_SHARED1:@.+]] = internal unnamed_addr constant i16 1
+// CK1-DAG: [[KERNEL_SHARED2:@.+]] = internal unnamed_addr constant i16 1
+
// only nvptx side: do not outline teams region and do not call fork_teams
// CK1: define {{.*}}void @{{[^,]+}}(i{{[0-9]+}} [[ARGC:%.+]])
// CK1: {{.+}} = alloca i{{[0-9]+}}*,
@@ -36,7 +44,11 @@ int main (int argc, char **argv) {
// CK1: store {{.+}} 0, {{.+}},
// CK1: store i{{[0-9]+}} [[ARGC]], i{{[0-9]+}}* [[ARGCADDR]],
// CK1-64: [[CONV:%.+]] = bitcast i{{[0-9]+}}* [[ARGCADDR]] to i{{[0-9]+}}*
-// CK1: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} 4, i16 0)
+// CK1: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED1]],
+// CK1: [[SIZE:%.+]] = load i{{64|32}}, i{{64|32}}* [[KERNEL_SIZE1]],
+// CK1: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} [[SIZE]], i16 [[IS_SHARED]], i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CK1: [[KERNEL_RD:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CK1: [[GLOBALSTACK:%.+]] = getelementptr inbounds i8, i8* [[KERNEL_RD]], i{{64|32}} 0
// CK1-64: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[CONV]]
// CK1-32: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ARGCADDR]]
// CK1: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
@@ -53,7 +65,11 @@ int main (int argc, char **argv) {
// CK1: [[ARGCADDR_PTR:%.+]] = alloca i{{.+}}***,
// CK1: [[ARGCADDR:%.+]] = alloca i{{.+}}**,
// CK1: store i{{.+}}** [[ARGC]], i{{.+}}*** [[ARGCADDR]]
-// CK1: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} {{4|8}}, i16 0)
+// CK1: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED2]],
+// CK1: [[SIZE:%.+]] = load i{{64|32}}, i{{64|32}}* [[KERNEL_SIZE2]],
+// CK1: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} [[SIZE]], i16 [[IS_SHARED]], i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CK1: [[KERNEL_RD:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CK1: [[GLOBALSTACK:%.+]] = getelementptr inbounds i8, i8* [[KERNEL_RD]], i{{64|32}} 0
// CK1: [[ARG:%.+]] = load i{{[0-9]+}}**, i{{[0-9]+}}*** [[ARGCADDR]]
// CK1: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CK1: store i{{[0-9]+}}** [[ARG]], i{{[0-9]+}}*** [[ARGCADDR]],
@@ -98,6 +114,14 @@ int main (int argc, char **argv) {
return tmain(argv);
}
+// CK2: [[MEM_TY:%.+]] = type { [128 x i8] }
+// CK2-DAG: [[SHARED_GLOBAL_RD:@.+]] = common addrspace(3) global [[MEM_TY]] zeroinitializer
+// CK2-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CK2-DAG: [[KERNEL_SIZE1:@.+]] = internal unnamed_addr constant i{{64|32}} 4
+// CK2-DAG: [[KERNEL_SIZE2:@.+]] = internal unnamed_addr constant i{{64|32}} {{8|4}}
+// CK2-DAG: [[KERNEL_SHARED1:@.+]] = internal unnamed_addr constant i16 1
+// CK2-DAG: [[KERNEL_SHARED2:@.+]] = internal unnamed_addr constant i16 1
+
// CK2: define {{.*}}void @{{[^,]+}}(i{{[0-9]+}} [[A_IN:%.+]], i{{[0-9]+}} [[B_IN:%.+]], i{{[0-9]+}} [[ARGC_IN:.+]])
// CK2: {{.}} = alloca i{{[0-9]+}}*,
// CK2: {{.}} = alloca i{{[0-9]+}}*,
@@ -105,18 +129,22 @@ int main (int argc, char **argv) {
// CK2: [[AADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[BADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[ARGCADDR:%.+]] = alloca i{{[0-9]+}},
-// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}} [[A_IN]], i{{[0-9]+}}* [[AADDR]],
// CK2: store i{{[0-9]+}} [[B_IN]], i{{[0-9]+}}* [[BADDR]],
// CK2: store i{{[0-9]+}} [[ARGC_IN]], i{{[0-9]+}}* [[ARGCADDR]],
// CK2-64: [[ACONV:%.+]] = bitcast i64* [[AADDR]] to i32*
// CK2-64: [[BCONV:%.+]] = bitcast i64* [[BADDR]] to i32*
// CK2-64: [[CONV:%.+]] = bitcast i64* [[ARGCADDR]] to i32*
-// CK2: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} 4, i16 0)
+// CK2: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED1]],
+// CK2: [[SIZE:%.+]] = load i{{64|32}}, i{{64|32}}* [[KERNEL_SIZE1]],
+// CK2: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} [[SIZE]], i16 [[IS_SHARED]], i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CK2: [[KERNEL_RD:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CK2: [[GLOBALSTACK:%.+]] = getelementptr inbounds i8, i8* [[KERNEL_RD]], i{{64|32}} 0
// CK2-64: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[CONV]]
// CK2-32: [[ARG:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[ARGCADDR]]
// CK2: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CK2: store i{{[0-9]+}} [[ARG]], i{{[0-9]+}}* [[ARGCADDR]],
+// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}}* [[ARGCADDR]], i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK2: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[ARGCADDR_PTR]],
// CK2: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[ARGCADDR_PTR_REF]],
@@ -129,14 +157,18 @@ int main (int argc, char **argv) {
// CK2: [[AADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[BADDR:%.+]] = alloca i{{[0-9]+}},
// CK2: [[ARGCADDR:%.+]] = alloca i{{[0-9]+}}**,
-// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}} [[A_IN]], i{{[0-9]+}}* [[AADDR]],
// CK2: store i{{[0-9]+}} [[B_IN]], i{{[0-9]+}}* [[BADDR]],
// CK2: store i{{[0-9]+}}** [[ARGC]], i{{[0-9]+}}*** [[ARGCADDR]],
-// CK2: call i8* @__kmpc_data_sharing_push_stack(i{{[0-9]+}} {{4|8}}, i16 0)
+// CK2: [[IS_SHARED:%.+]] = load i16, i16* [[KERNEL_SHARED2]],
+// CK2: [[SIZE:%.+]] = load i{{64|32}}, i{{64|32}}* [[KERNEL_SIZE2]],
+// CK2: call void @__kmpc_get_team_static_memory(i16 0, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY]], [[MEM_TY]] addrspace(3)* [[SHARED_GLOBAL_RD]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} [[SIZE]], i16 [[IS_SHARED]], i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR]] to i8**))
+// CK2: [[KERNEL_RD:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+// CK2: [[GLOBALSTACK:%.+]] = getelementptr inbounds i8, i8* [[KERNEL_RD]], i{{64|32}} 0
// CK2: [[ARG:%.+]] = load i{{[0-9]+}}**, i{{[0-9]+}}*** [[ARGCADDR]]
// CK2: [[ARGCADDR:%.+]] = getelementptr inbounds %struct.{{.*}}, %struct.{{.*}}* %{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CK2: store i{{[0-9]+}}** [[ARG]], i{{[0-9]+}}*** [[ARGCADDR]],
+// CK2: {{%.+}} = call i32 @__kmpc_global_thread_num(
// CK2: store i{{[0-9]+}}*** [[ARGCADDR]], i{{[0-9]+}}**** [[ARGCADDR_PTR]],
// CK2: [[ARGCADDR_PTR_REF:%.+]] = load i{{[0-9]+}}***, i{{[0-9]+}}**** [[ARGCADDR_PTR]],
// CK2: store i{{[0-9]+}}** null, i{{[0-9]+}}*** [[ARGCADDR_PTR_REF]],
diff --git a/test/OpenMP/nvptx_teams_reduction_codegen.cpp b/test/OpenMP/nvptx_teams_reduction_codegen.cpp
index 6925b17163af..0de25295a7a9 100644
--- a/test/OpenMP/nvptx_teams_reduction_codegen.cpp
+++ b/test/OpenMP/nvptx_teams_reduction_codegen.cpp
@@ -8,13 +8,23 @@
#ifndef HEADER
#define HEADER
+// CHECK: [[MAP_TY:%.+]] = type { [128 x i8] }
+
+// CHECK-DAG: [[KERNEL_PTR:@.+]] = internal addrspace(3) global i8* null
+// CHECK-DAG: [[KERNEL_SHARED1:@.+]] = internal unnamed_addr constant i16 1
+// CHECK-DAG: [[KERNEL_SHARED2:@.+]] = internal unnamed_addr constant i16 1
+// CHECK-DAG: [[KERNEL_SHARED3:@.+]] = internal unnamed_addr constant i16 1
+// CHECK-DAG: [[KERNEL_SIZE1:@.+]] = internal unnamed_addr constant i{{64|32}} {{16|8}}
+// CHECK-DAG: [[KERNEL_SIZE2:@.+]] = internal unnamed_addr constant i{{64|32}} 16
+// CHECK-DAG: [[KERNEL_SIZE3:@.+]] = internal unnamed_addr constant i{{64|32}} 8
+
// Check for the data transfer medium in shared memory to transfer the reduction list to the first warp.
-// CHECK-DAG: [[TRANSFER_STORAGE:@.+]] = common addrspace([[SHARED_ADDRSPACE:[0-9]+]]) global [32 x i64]
+// CHECK-DAG: [[TRANSFER_STORAGE:@.+]] = common addrspace([[SHARED_ADDRSPACE:[0-9]+]]) global [32 x i32]
-// Check that the execution mode of all 3 target regions is set to Generic Mode.
-// CHECK-DAG: {{@__omp_offloading_.+l27}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l33}}_exec_mode = weak constant i8 1
-// CHECK-DAG: {{@__omp_offloading_.+l40}}_exec_mode = weak constant i8 1
+// Check that the execution mode of 2 target regions is set to Non-SPMD and the 3rd is in SPMD.
+// CHECK-DAG: {{@__omp_offloading_.+l37}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l43}}_exec_mode = weak constant i8 1
+// CHECK-DAG: {{@__omp_offloading_.+l50}}_exec_mode = weak constant i8 0
template<typename tx>
tx ftemplate(int n) {
@@ -39,6 +49,7 @@ tx ftemplate(int n) {
#pragma omp target
#pragma omp teams reduction(|: a) reduction(max: b)
+ #pragma omp parallel reduction(|: a) reduction(max: b)
{
a |= 1;
b = 99 > b ? 99 : b;
@@ -55,9 +66,9 @@ int bar(int n){
return a;
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l27}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l37}}_worker()
- // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+template.+l27]](
+ // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+template.+l37]](
//
// CHECK: {{call|invoke}} void [[T1]]_worker()
//
@@ -67,11 +78,7 @@ int bar(int n){
// CHECK: [[EV:%.+]] = load double, double* [[E]], align
// CHECK: [[ADD:%.+]] = fadd double [[EV]], 5
// CHECK: store double [[ADD]], double* [[E]], align
- // CHECK: [[PTR1:%.+]] = getelementptr inbounds [[RLT:.+]], [1 x i8*]* [[RL:%.+]], i[[SZ:32|64]] 0, i{{32|64}} 0
- // CHECK: [[E_CAST:%.+]] = bitcast double* [[E]] to i8*
- // CHECK: store i8* [[E_CAST]], i8** [[PTR1]], align
- // CHECK: [[ARG_RL:%.+]] = bitcast [[RLT]]* [[RL]] to i8*
- // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_teams_reduce_nowait(i32 {{.+}}, i32 1, i[[SZ]] {{4|8}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]], void (i8*, i8*, i32, i32)* [[SCRATCH_COPY_FN:@.+]], void (i8*, i8*, i32, i32, i32)* [[LOAD_REDUCE_FN:@.+]])
+ // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_teams_reduce_nowait_simple(%struct.ident_t* [[LOC:@.+]], i32 [[GTID:%.+]], [8 x i32]* [[LOCK:@.+]])
// CHECK: [[COND:%.+]] = icmp eq i32 [[RET]], 1
// CHECK: br i1 [[COND]], label {{%?}}[[IFLABEL:.+]], label {{%?}}[[EXIT:.+]]
//
@@ -80,238 +87,18 @@ int bar(int n){
// CHECK: [[EV:%.+]] = load double, double* [[E]], align
// CHECK: [[ADD:%.+]] = fadd double [[E_INV]], [[EV]]
// CHECK: store double [[ADD]], double* [[E_IN]], align
- // CHECK: call void @__kmpc_nvptx_end_reduce_nowait(
+ // CHECK: call void @__kmpc_nvptx_teams_end_reduce_nowait_simple(%struct.ident_t* [[LOC]], i32 [[GTID]], [8 x i32]* [[LOCK]])
// CHECK: br label %[[EXIT]]
//
// CHECK: [[EXIT]]
// CHECK: call void @__kmpc_kernel_deinit(
- //
- // Reduction function
- // CHECK: define internal void [[REDUCTION_FUNC:@.+]](i8*, i8*)
- // CHECK: [[VAR_RHS_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST_RHS:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[VAR_RHS_VOID:%.+]] = load i8*, i8** [[VAR_RHS_REF]],
- // CHECK: [[VAR_RHS:%.+]] = bitcast i8* [[VAR_RHS_VOID]] to double*
- //
- // CHECK: [[VAR_LHS_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST_LHS:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[VAR_LHS_VOID:%.+]] = load i8*, i8** [[VAR_LHS_REF]],
- // CHECK: [[VAR_LHS:%.+]] = bitcast i8* [[VAR_LHS_VOID]] to double*
- //
- // CHECK: [[VAR_LHS_VAL:%.+]] = load double, double* [[VAR_LHS]],
- // CHECK: [[VAR_RHS_VAL:%.+]] = load double, double* [[VAR_RHS]],
- // CHECK: [[RES:%.+]] = fadd double [[VAR_LHS_VAL]], [[VAR_RHS_VAL]]
- // CHECK: store double [[RES]], double* [[VAR_LHS]],
- // CHECK: ret void
-
- //
- // Shuffle and reduce function
- // CHECK: define internal void [[SHUFFLE_REDUCE_FN]](i8*, i16 {{.*}}, i16 {{.*}}, i16 {{.*}})
- // CHECK: [[REMOTE_RED_LIST:%.+]] = alloca [[RLT]], align
- // CHECK: [[REMOTE_ELT:%.+]] = alloca double
- //
- // CHECK: [[LANEID:%.+]] = load i16, i16* {{.+}}, align
- // CHECK: [[LANEOFFSET:%.+]] = load i16, i16* {{.+}}, align
- // CHECK: [[ALGVER:%.+]] = load i16, i16* {{.+}}, align
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- //
- // CHECK: [[ELT_CAST:%.+]] = bitcast double* [[ELT]] to i64*
- // CHECK: [[REMOTE_ELT_CAST:%.+]] = bitcast double* [[REMOTE_ELT]] to i64*
- // CHECK: [[ELT_VAL:%.+]] = load i64, i64* [[ELT_CAST]], align
- // CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16
- // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]])
- //
- // CHECK: store i64 [[REMOTE_ELT_VAL64]], i64* [[REMOTE_ELT_CAST]], align
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = bitcast double* [[REMOTE_ELT]] to i8*
- // CHECK: store i8* [[REMOTE_ELT_VOID]], i8** [[REMOTE_ELT_REF]], align
- //
- // Condition to reduce
- // CHECK: [[CONDALG0:%.+]] = icmp eq i16 [[ALGVER]], 0
- //
- // CHECK: [[COND1:%.+]] = icmp eq i16 [[ALGVER]], 1
- // CHECK: [[COND2:%.+]] = icmp ult i16 [[LANEID]], [[LANEOFFSET]]
- // CHECK: [[CONDALG1:%.+]] = and i1 [[COND1]], [[COND2]]
- //
- // CHECK: [[COND3:%.+]] = icmp eq i16 [[ALGVER]], 2
- // CHECK: [[COND4:%.+]] = and i16 [[LANEID]], 1
- // CHECK: [[COND5:%.+]] = icmp eq i16 [[COND4]], 0
- // CHECK: [[COND6:%.+]] = and i1 [[COND3]], [[COND5]]
- // CHECK: [[COND7:%.+]] = icmp sgt i16 [[LANEOFFSET]], 0
- // CHECK: [[CONDALG2:%.+]] = and i1 [[COND6]], [[COND7]]
- //
- // CHECK: [[COND8:%.+]] = or i1 [[CONDALG0]], [[CONDALG1]]
- // CHECK: [[SHOULD_REDUCE:%.+]] = or i1 [[COND8]], [[CONDALG2]]
- // CHECK: br i1 [[SHOULD_REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
- //
- // CHECK: [[DO_REDUCE]]
- // CHECK: [[RED_LIST1_VOID:%.+]] = bitcast [[RLT]]* [[RED_LIST]] to i8*
- // CHECK: [[RED_LIST2_VOID:%.+]] = bitcast [[RLT]]* [[REMOTE_RED_LIST]] to i8*
- // CHECK: call void [[REDUCTION_FUNC]](i8* [[RED_LIST1_VOID]], i8* [[RED_LIST2_VOID]])
- // CHECK: br label {{%?}}[[REDUCE_CONT:.+]]
- //
- // CHECK: [[REDUCE_ELSE]]
- // CHECK: br label {{%?}}[[REDUCE_CONT]]
- //
- // CHECK: [[REDUCE_CONT]]
- // Now check if we should just copy over the remote reduction list
- // CHECK: [[COND1:%.+]] = icmp eq i16 [[ALGVER]], 1
- // CHECK: [[COND2:%.+]] = icmp uge i16 [[LANEID]], [[LANEOFFSET]]
- // CHECK: [[SHOULD_COPY:%.+]] = and i1 [[COND1]], [[COND2]]
- // CHECK: br i1 [[SHOULD_COPY]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
- //
- // CHECK: [[DO_COPY]]
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align
- // CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align
- // CHECK: br label {{%?}}[[COPY_CONT:.+]]
- //
- // CHECK: [[COPY_ELSE]]
- // CHECK: br label {{%?}}[[COPY_CONT]]
- //
- // CHECK: [[COPY_CONT]]
- // CHECK: void
-
- //
- // Inter warp copy function
- // CHECK: define internal void [[WARP_COPY_FN]](i8*, i32)
- // CHECK-DAG: [[LANEID:%.+]] = and i32 {{.+}}, 31
- // CHECK-DAG: [[WARPID:%.+]] = ashr i32 {{.+}}, 5
- // CHECK-DAG: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
- // CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
- //
- // [[DO_COPY]]
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- //
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
- // CHECK: store double [[ELT_VAL]], double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: br label {{%?}}[[COPY_CONT:.+]]
- //
- // CHECK: [[COPY_ELSE]]
- // CHECK: br label {{%?}}[[COPY_CONT]]
- //
- // Barrier after copy to shared memory storage medium.
- // CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
- //
- // Read into warp 0.
- // CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
- // CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
- //
- // CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: store double [[MEDIUM_ELT_VAL]], double* [[ELT]], align
- // CHECK: br label {{%?}}[[READ_CONT:.+]]
- //
- // CHECK: [[READ_ELSE]]
- // CHECK: br label {{%?}}[[READ_CONT]]
- //
- // CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
- // CHECK: ret
-
- //
- // Copy to scratchpad function
- // CHECK: define internal void [[SCRATCH_COPY_FN]](i8*, i8*, i32, i32)
- // CHECK: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[SCRATCHPAD_PTR:%.+]] = load i8*, i8** {{.+}}, align
- // CHECK-64: [[TEAM32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[TEAM:%.+]] = sext i32 [[TEAM32]] to i64
- // CHECK-32: [[TEAM:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS:%.+]] = sext i32 [[NUM_TEAMS32]] to i64
- // CHECK-32: [[NUM_TEAMS:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 8, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to double*
- // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align
- // CHECK: store double [[ELT_VAL]], double* [[SCRATCHPAD_ELT_PTR]], align
- //
- // CHECK: ret
-
- //
- // Load and reduce function
- // CHECK: define internal void [[LOAD_REDUCE_FN]](i8*, i8*, i32, i32, i32)
- // CHECK: [[REMOTE_RED_LIST:%.+]] = alloca [[RLT]], align
- // CHECK: [[REMOTE_ELT:%.+]] = alloca double
- // CHECK: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[SCRATCHPAD_PTR:%.+]] = load i8*, i8** {{.+}}, align
- // CHECK-64: [[TEAM32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[TEAM:%.+]] = sext i32 [[TEAM32]] to i64
- // CHECK-32: [[TEAM:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS:%.+]] = sext i32 [[NUM_TEAMS32]] to i64
- // CHECK-32: [[NUM_TEAMS:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SHOULD_REDUCE:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 8, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l43}}_worker()
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to double*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[SCRATCHPAD_ELT_PTR]], align
- // CHECK: store double [[REMOTE_ELT_VAL]], double* [[REMOTE_ELT]], align
- // CHECK: [[REMOTE_ELT_PTR:%.+]] = bitcast double* [[REMOTE_ELT]] to i8*
- // CHECK: store i8* [[REMOTE_ELT_PTR]], i8** [[REMOTE_ELT_REF]], align
- //
- // CHECK: [[REDUCE:%.+]] = icmp ne i32 [[SHOULD_REDUCE]], 0
- // CHECK: br i1 [[REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
- //
- // CHECK: [[DO_REDUCE]]
- // CHECK: [[RED_LIST1_VOID:%.+]] = bitcast [[RLT]]* [[RED_LIST]] to i8*
- // CHECK: [[RED_LIST2_VOID:%.+]] = bitcast [[RLT]]* [[REMOTE_RED_LIST]] to i8*
- // CHECK: call void [[REDUCTION_FUNC]](i8* [[RED_LIST1_VOID]], i8* [[RED_LIST2_VOID]])
- // CHECK: br label {{%?}}[[REDUCE_CONT:.+]]
- //
- // Copy element from remote reduce list
- // CHECK: [[REDUCE_ELSE]]
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align
- // CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align
- // CHECK: br label {{%?}}[[REDUCE_CONT]]
- //
- // CHECK: [[REDUCE_CONT]]
- // CHECK: ret
-
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l33}}_worker()
-
- // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+template.+l33]](
+ // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+template.+l43]](
//
// CHECK: {{call|invoke}} void [[T2]]_worker()
+
//
// CHECK: call void @__kmpc_kernel_init(
//
@@ -324,13 +111,7 @@ int bar(int n){
// CHECK: [[DV:%.+]] = load float, float* [[D]], align
// CHECK: [[MUL:%.+]] = fmul float [[DV]], {{[0-9e\.\+]+}}
// CHECK: store float [[MUL]], float* [[D]], align
- // CHECK: [[PTR1:%.+]] = getelementptr inbounds [[RLT:.+]], [2 x i8*]* [[RL:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: store i8* [[C]], i8** [[PTR1]], align
- // CHECK: [[PTR2:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RL]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[D_CAST:%.+]] = bitcast float* [[D]] to i8*
- // CHECK: store i8* [[D_CAST]], i8** [[PTR2]], align
- // CHECK: [[ARG_RL:%.+]] = bitcast [[RLT]]* [[RL]] to i8*
- // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_teams_reduce_nowait(i32 {{.+}}, i32 2, i[[SZ]] {{8|16}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]], void (i8*, i8*, i32, i32)* [[SCRATCH_COPY_FN:@.+]], void (i8*, i8*, i32, i32, i32)* [[LOAD_REDUCE_FN:@.+]])
+ // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_teams_reduce_nowait_simple(%struct.ident_t* [[LOC:@.+]], i32 [[GTID:%.+]], [8 x i32]* [[LOCK:@.+]])
// CHECK: [[COND:%.+]] = icmp eq i32 [[RET]], 1
// CHECK: br i1 [[COND]], label {{%?}}[[IFLABEL:.+]], label {{%?}}[[EXIT:.+]]
//
@@ -346,356 +127,59 @@ int bar(int n){
// CHECK: [[DV:%.+]] = load float, float* [[D]], align
// CHECK: [[MUL:%.+]] = fmul float [[D_INV]], [[DV]]
// CHECK: store float [[MUL]], float* [[D_IN]], align
- // CHECK: call void @__kmpc_nvptx_end_reduce_nowait(
+ // CHECK: call void @__kmpc_nvptx_teams_end_reduce_nowait_simple(%struct.ident_t* [[LOC]], i32 [[GTID]], [8 x i32]* [[LOCK]])
// CHECK: br label %[[EXIT]]
//
// CHECK: [[EXIT]]
// CHECK: call void @__kmpc_kernel_deinit(
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l50}}(
+ //
+ // CHECK: call void @__kmpc_spmd_kernel_init(
+ // CHECK: call void @__kmpc_data_sharing_init_stack_spmd()
+ // CHECK: call void @__kmpc_get_team_static_memory(i16 1, i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([[MEM_TY:%.+]], %{{.+}} addrspace(3)* [[KERNEL_RD:@.+]], i32 0, i32 0, i32 0) to i8*), i{{64|32}} {{8|16}}, i16 1, i8** addrspacecast (i8* addrspace(3)* [[KERNEL_PTR:@.+]] to i8**))
+ // CHECK: [[PTR:%.+]] = load i8*, i8* addrspace(3)* [[KERNEL_PTR]],
+ // CHECK: [[GLOBAL_REC:%.+]] = bitcast i8* [[PTR]] to [[GLOB_REC_TY:%.+]]*
+ // CHECK-DAG: [[A_ADDR:%.+]] = getelementptr inbounds [[GLOB_REC_TY]], [[GLOB_REC_TY]]* [[GLOBAL_REC]], i32 0, i32 0
+ // CHECK-DAG: [[B_ADDR:%.+]] = getelementptr inbounds [[GLOB_REC_TY]], [[GLOB_REC_TY]]* [[GLOBAL_REC]], i32 0, i32 1
+ // CHECK: store i32 0, i32* [[A_ADDR]],
+ // CHECK: store i16 -32768, i16* [[B_ADDR]],
+ // CHECK: call void [[OUTLINED:@.+]](i32* {{.+}}, i32* {{.+}}, i32* [[A_ADDR]], i16* [[B_ADDR]])
+ // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_teams_reduce_nowait_simple(%struct.ident_t* [[LOC:@.+]], i32 [[GTID:%.+]], [8 x i32]* [[LOCK:@.+]])
+ // CHECK: [[COND:%.+]] = icmp eq i32 [[RET]], 1
+ // CHECK: br i1 [[COND]], label {{%?}}[[IFLABEL:.+]], label {{%?}}[[EXIT:.+]]
//
- // Reduction function
- // CHECK: define internal void [[REDUCTION_FUNC:@.+]](i8*, i8*)
- // CHECK: [[VAR1_RHS_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST_RHS:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[VAR1_RHS:%.+]] = load i8*, i8** [[VAR1_RHS_REF]],
- //
- // CHECK: [[VAR1_LHS_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST_LHS:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[VAR1_LHS:%.+]] = load i8*, i8** [[VAR1_LHS_REF]],
- //
- // CHECK: [[VAR2_RHS_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST_RHS]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[VAR2_RHS_VOID:%.+]] = load i8*, i8** [[VAR2_RHS_REF]],
- // CHECK: [[VAR2_RHS:%.+]] = bitcast i8* [[VAR2_RHS_VOID]] to float*
- //
- // CHECK: [[VAR2_LHS_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST_LHS]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[VAR2_LHS_VOID:%.+]] = load i8*, i8** [[VAR2_LHS_REF]],
- // CHECK: [[VAR2_LHS:%.+]] = bitcast i8* [[VAR2_LHS_VOID]] to float*
- //
- // CHECK: [[VAR1_LHS_VAL8:%.+]] = load i8, i8* [[VAR1_LHS]],
- // CHECK: [[VAR1_LHS_VAL:%.+]] = sext i8 [[VAR1_LHS_VAL8]] to i32
- // CHECK: [[VAR1_RHS_VAL8:%.+]] = load i8, i8* [[VAR1_RHS]],
- // CHECK: [[VAR1_RHS_VAL:%.+]] = sext i8 [[VAR1_RHS_VAL8]] to i32
- // CHECK: [[XOR:%.+]] = xor i32 [[VAR1_LHS_VAL]], [[VAR1_RHS_VAL]]
- // CHECK: [[RES:%.+]] = trunc i32 [[XOR]] to i8
- // CHECK: store i8 [[RES]], i8* [[VAR1_LHS]],
- //
- // CHECK: [[VAR2_LHS_VAL:%.+]] = load float, float* [[VAR2_LHS]],
- // CHECK: [[VAR2_RHS_VAL:%.+]] = load float, float* [[VAR2_RHS]],
- // CHECK: [[RES:%.+]] = fmul float [[VAR2_LHS_VAL]], [[VAR2_RHS_VAL]]
- // CHECK: store float [[RES]], float* [[VAR2_LHS]],
- // CHECK: ret void
-
- //
- // Shuffle and reduce function
- // CHECK: define internal void [[SHUFFLE_REDUCE_FN]](i8*, i16 {{.*}}, i16 {{.*}}, i16 {{.*}})
- // CHECK: [[REMOTE_RED_LIST:%.+]] = alloca [[RLT]], align
- // CHECK: [[REMOTE_ELT1:%.+]] = alloca i8
- // CHECK: [[REMOTE_ELT2:%.+]] = alloca float
- //
- // CHECK: [[LANEID:%.+]] = load i16, i16* {{.+}}, align
- // CHECK: [[LANEOFFSET:%.+]] = load i16, i16* {{.+}}, align
- // CHECK: [[ALGVER:%.+]] = load i16, i16* {{.+}}, align
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
- //
- // CHECK: [[ELT_CAST:%.+]] = sext i8 [[ELT_VAL]] to i32
- // CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16
- // CHECK: [[REMOTE_ELT1_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]])
- // CHECK: [[REMOTE_ELT1_VAL:%.+]] = trunc i32 [[REMOTE_ELT1_VAL32]] to i8
- //
- // CHECK: store i8 [[REMOTE_ELT1_VAL]], i8* [[REMOTE_ELT1]], align
- // CHECK: store i8* [[REMOTE_ELT1]], i8** [[REMOTE_ELT_REF]], align
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- //
- // CHECK: [[ELT_CAST:%.+]] = bitcast float* [[ELT]] to i32*
- // CHECK: [[REMOTE_ELT2_CAST:%.+]] = bitcast float* [[REMOTE_ELT2]] to i32*
- // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT_CAST]], align
- // CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16
- // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]])
- //
- // CHECK: store i32 [[REMOTE_ELT2_VAL32]], i32* [[REMOTE_ELT2_CAST]], align
- // CHECK: [[REMOTE_ELT2C:%.+]] = bitcast float* [[REMOTE_ELT2]] to i8*
- // CHECK: store i8* [[REMOTE_ELT2C]], i8** [[REMOTE_ELT_REF]], align
- //
- // Condition to reduce
- // CHECK: [[CONDALG0:%.+]] = icmp eq i16 [[ALGVER]], 0
- //
- // CHECK: [[COND1:%.+]] = icmp eq i16 [[ALGVER]], 1
- // CHECK: [[COND2:%.+]] = icmp ult i16 [[LANEID]], [[LANEOFFSET]]
- // CHECK: [[CONDALG1:%.+]] = and i1 [[COND1]], [[COND2]]
- //
- // CHECK: [[COND3:%.+]] = icmp eq i16 [[ALGVER]], 2
- // CHECK: [[COND4:%.+]] = and i16 [[LANEID]], 1
- // CHECK: [[COND5:%.+]] = icmp eq i16 [[COND4]], 0
- // CHECK: [[COND6:%.+]] = and i1 [[COND3]], [[COND5]]
- // CHECK: [[COND7:%.+]] = icmp sgt i16 [[LANEOFFSET]], 0
- // CHECK: [[CONDALG2:%.+]] = and i1 [[COND6]], [[COND7]]
- //
- // CHECK: [[COND8:%.+]] = or i1 [[CONDALG0]], [[CONDALG1]]
- // CHECK: [[SHOULD_REDUCE:%.+]] = or i1 [[COND8]], [[CONDALG2]]
- // CHECK: br i1 [[SHOULD_REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
- //
- // CHECK: [[DO_REDUCE]]
- // CHECK: [[RED_LIST1_VOID:%.+]] = bitcast [[RLT]]* [[RED_LIST]] to i8*
- // CHECK: [[RED_LIST2_VOID:%.+]] = bitcast [[RLT]]* [[REMOTE_RED_LIST]] to i8*
- // CHECK: call void [[REDUCTION_FUNC]](i8* [[RED_LIST1_VOID]], i8* [[RED_LIST2_VOID]])
- // CHECK: br label {{%?}}[[REDUCE_CONT:.+]]
- //
- // CHECK: [[REDUCE_ELSE]]
- // CHECK: br label {{%?}}[[REDUCE_CONT]]
- //
- // CHECK: [[REDUCE_CONT]]
- // Now check if we should just copy over the remote reduction list
- // CHECK: [[COND1:%.+]] = icmp eq i16 [[ALGVER]], 1
- // CHECK: [[COND2:%.+]] = icmp uge i16 [[LANEID]], [[LANEOFFSET]]
- // CHECK: [[SHOULD_COPY:%.+]] = and i1 [[COND1]], [[COND2]]
- // CHECK: br i1 [[SHOULD_COPY]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
- //
- // CHECK: [[DO_COPY]]
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i8, i8* [[REMOTE_ELT_VOID]], align
- // CHECK: store i8 [[REMOTE_ELT_VAL]], i8* [[ELT_VOID]], align
- //
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align
- // CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align
- // CHECK: br label {{%?}}[[COPY_CONT:.+]]
- //
- // CHECK: [[COPY_ELSE]]
- // CHECK: br label {{%?}}[[COPY_CONT]]
- //
- // CHECK: [[COPY_CONT]]
- // CHECK: void
-
- //
- // Inter warp copy function
- // CHECK: define internal void [[WARP_COPY_FN]](i8*, i32)
- // CHECK-DAG: [[LANEID:%.+]] = and i32 {{.+}}, 31
- // CHECK-DAG: [[WARPID:%.+]] = ashr i32 {{.+}}, 5
- // CHECK-DAG: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
- // CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
- //
- // [[DO_COPY]]
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- //
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
- // CHECK: store i8 [[ELT_VAL]], i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: br label {{%?}}[[COPY_CONT:.+]]
- //
- // CHECK: [[COPY_ELSE]]
- // CHECK: br label {{%?}}[[COPY_CONT]]
- //
- // Barrier after copy to shared memory storage medium.
- // CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
- //
- // Read into warp 0.
- // CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
- // CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
- //
- // CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: store i8 [[MEDIUM_ELT_VAL]], i8* [[ELT_VOID]], align
- // CHECK: br label {{%?}}[[READ_CONT:.+]]
- //
- // CHECK: [[READ_ELSE]]
- // CHECK: br label {{%?}}[[READ_CONT]]
- //
- // CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
- // CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
- // CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
- //
- // [[DO_COPY]]
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- //
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
- // CHECK: store float [[ELT_VAL]], float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: br label {{%?}}[[COPY_CONT:.+]]
- //
- // CHECK: [[COPY_ELSE]]
- // CHECK: br label {{%?}}[[COPY_CONT]]
- //
- // Barrier after copy to shared memory storage medium.
- // CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
- //
- // Read into warp 0.
- // CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
- // CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
- //
- // CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])*
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
- // CHECK: store float [[MEDIUM_ELT_VAL]], float* [[ELT]], align
- // CHECK: br label {{%?}}[[READ_CONT:.+]]
- //
- // CHECK: [[READ_ELSE]]
- // CHECK: br label {{%?}}[[READ_CONT]]
- //
- // CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
- // CHECK: ret
-
- //
- // Copy to scratchpad function
- // CHECK: define internal void [[SCRATCH_COPY_FN]](i8*, i8*, i32, i32)
- // CHECK: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[SCRATCHPAD_PTR:%.+]] = load i8*, i8** {{.+}}, align
- // CHECK-64: [[TEAM32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[TEAM:%.+]] = sext i32 [[TEAM32]] to i64
- // CHECK-32: [[TEAM:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS:%.+]] = sext i32 [[NUM_TEAMS32]] to i64
- // CHECK-32: [[NUM_TEAMS:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 1, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align
- // CHECK: store i8 [[ELT_VAL]], i8* [[SCRATCHPAD_ELT_PTR]], align
- //
- // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 1
- // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to float*
- // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align
- // CHECK: store float [[ELT_VAL]], float* [[SCRATCHPAD_ELT_PTR]], align
- //
- // CHECK: ret
-
- //
- // Load and reduce function
- // CHECK: define internal void [[LOAD_REDUCE_FN]](i8*, i8*, i32, i32, i32)
- // CHECK: [[REMOTE_RED_LIST:%.+]] = alloca [[RLT]], align
- // CHECK: [[REMOTE_ELT1:%.+]] = alloca i8
- // CHECK: [[REMOTE_ELT2:%.+]] = alloca float
- // CHECK: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[SCRATCHPAD_PTR:%.+]] = load i8*, i8** {{.+}}, align
- // CHECK-64: [[TEAM32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[TEAM:%.+]] = sext i32 [[TEAM32]] to i64
- // CHECK-32: [[TEAM:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS:%.+]] = sext i32 [[NUM_TEAMS32]] to i64
- // CHECK-32: [[NUM_TEAMS:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SHOULD_REDUCE:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 1, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
-
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i8, i8* [[SCRATCHPAD_ELT_PTR_VOID]], align
- // CHECK: store i8 [[REMOTE_ELT_VAL]], i8* [[REMOTE_ELT1]], align
- // CHECK: store i8* [[REMOTE_ELT1]], i8** [[REMOTE_ELT_REF]], align
- //
- // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 1
- // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
-
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to float*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[SCRATCHPAD_ELT_PTR]], align
- // CHECK: store float [[REMOTE_ELT_VAL]], float* [[REMOTE_ELT2]], align
- // CHECK: [[REMOTE_ELT_PTR:%.+]] = bitcast float* [[REMOTE_ELT2]] to i8*
- // CHECK: store i8* [[REMOTE_ELT_PTR]], i8** [[REMOTE_ELT_REF]], align
- //
- // CHECK: [[REDUCE:%.+]] = icmp ne i32 [[SHOULD_REDUCE]], 0
- // CHECK: br i1 [[REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
+ // CHECK: [[IFLABEL]]
+ // CHECK: [[A_INV:%.+]] = load i32, i32* [[A_IN:%.+]], align
+ // CHECK: [[AV:%.+]] = load i32, i32* [[A_ADDR]], align
+ // CHECK: [[OR:%.+]] = or i32 [[A_INV]], [[AV]]
+ // CHECK: store i32 [[OR]], i32* [[A_IN]], align
+ // CHECK: [[B_INV16:%.+]] = load i16, i16* [[B_IN:%.+]], align
+ // CHECK: [[B_INV:%.+]] = sext i16 [[B_INV16]] to i32
+ // CHECK: [[BV16:%.+]] = load i16, i16* [[B_ADDR]], align
+ // CHECK: [[BV:%.+]] = sext i16 [[BV16]] to i32
+ // CHECK: [[CMP:%.+]] = icmp sgt i32 [[B_INV]], [[BV]]
+ // CHECK: br i1 [[CMP]], label {{%?}}[[DO_MAX:.+]], label {{%?}}[[MAX_ELSE:.+]]
//
- // CHECK: [[DO_REDUCE]]
- // CHECK: [[RED_LIST1_VOID:%.+]] = bitcast [[RLT]]* [[RED_LIST]] to i8*
- // CHECK: [[RED_LIST2_VOID:%.+]] = bitcast [[RLT]]* [[REMOTE_RED_LIST]] to i8*
- // CHECK: call void [[REDUCTION_FUNC]](i8* [[RED_LIST1_VOID]], i8* [[RED_LIST2_VOID]])
- // CHECK: br label {{%?}}[[REDUCE_CONT:.+]]
+ // CHECK: [[DO_MAX]]
+ // CHECK: [[MAX1:%.+]] = load i16, i16* [[B_IN]], align
+ // CHECK: br label {{%?}}[[MAX_CONT:.+]]
//
- // Copy element from remote reduce list
- // CHECK: [[REDUCE_ELSE]]
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i8, i8* [[REMOTE_ELT_VOID]], align
- // CHECK: store i8 [[REMOTE_ELT_VAL]], i8* [[ELT_VOID]], align
+ // CHECK: [[MAX_ELSE]]
+ // CHECK: [[MAX2:%.+]] = load i16, i16* [[B_ADDR]], align
+ // CHECK: br label {{%?}}[[MAX_CONT]]
//
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align
- // CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align
- // CHECK: br label {{%?}}[[REDUCE_CONT]]
+ // CHECK: [[MAX_CONT]]
+ // CHECK: [[B_MAX:%.+]] = phi i16 [ [[MAX1]], %[[DO_MAX]] ], [ [[MAX2]], %[[MAX_ELSE]] ]
+ // CHECK: store i16 [[B_MAX]], i16* [[B_IN]], align
+ // CHECK: call void @__kmpc_nvptx_teams_end_reduce_nowait_simple(%struct.ident_t* [[LOC]], i32 [[GTID]], [8 x i32]* [[LOCK]])
+ // CHECK: br label %[[EXIT]]
//
- // CHECK: [[REDUCE_CONT]]
- // CHECK: ret
-
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l40}}_worker()
+ // CHECK: [[EXIT]]
+ // CHECK: call void @__kmpc_restore_team_static_memory(i16 1, i16 1)
+ // CHECK: call void @__kmpc_spmd_kernel_deinit_v2(i16 1)
- // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+template.+l40]](
- //
- // CHECK: {{call|invoke}} void [[T3]]_worker()
- //
- // CHECK: call void @__kmpc_kernel_init(
+ // CHECK: define internal void [[OUTLINED]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable{{.+}}, i16* dereferenceable{{.+}})
//
// CHECK: store i32 0, i32* [[A:%.+]], align
// CHECK: store i16 -32768, i16* [[B:%.+]], align
@@ -719,14 +203,14 @@ int bar(int n){
// CHECK: [[B_LVALUE:%.+]] = phi i32 [ 99, %[[DO_MAX]] ], [ [[MAX]], %[[MAX_ELSE]] ]
// CHECK: [[TRUNC:%.+]] = trunc i32 [[B_LVALUE]] to i16
// CHECK: store i16 [[TRUNC]], i16* [[B]], align
- // CHECK: [[PTR1:%.+]] = getelementptr inbounds [[RLT:.+]], [2 x i8*]* [[RL:%.+]], i[[SZ]] 0, i[[SZ]] 0
+ // CHECK: [[PTR1:%.+]] = getelementptr inbounds [[RLT:.+]], [2 x i8*]* [[RL:%.+]], i{{.+}} 0, i[[SZ:.+]] 0
// CHECK: [[A_CAST:%.+]] = bitcast i32* [[A]] to i8*
// CHECK: store i8* [[A_CAST]], i8** [[PTR1]], align
// CHECK: [[PTR2:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RL]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[B_CAST:%.+]] = bitcast i16* [[B]] to i8*
// CHECK: store i8* [[B_CAST]], i8** [[PTR2]], align
// CHECK: [[ARG_RL:%.+]] = bitcast [[RLT]]* [[RL]] to i8*
- // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_teams_reduce_nowait(i32 {{.+}}, i32 2, i[[SZ]] {{8|16}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[WARP_COPY_FN:@.+]], void (i8*, i8*, i32, i32)* [[SCRATCH_COPY_FN:@.+]], void (i8*, i8*, i32, i32, i32)* [[LOAD_REDUCE_FN:@.+]])
+ // CHECK: [[RET:%.+]] = call i32 @__kmpc_nvptx_parallel_reduce_nowait_v2(%struct.ident_t* [[LOC]], i32 {{.+}}, i32 2, i[[SZ]] {{8|16}}, i8* [[ARG_RL]], void (i8*, i16, i16, i16)* [[PAR_SHUFFLE_REDUCE_FN:@.+]], void (i8*, i32)* [[PAR_WARP_COPY_FN:@.+]])
// CHECK: [[COND:%.+]] = icmp eq i32 [[RET]], 1
// CHECK: br i1 [[COND]], label {{%?}}[[IFLABEL:.+]], label {{%?}}[[EXIT:.+]]
//
@@ -757,11 +241,11 @@ int bar(int n){
// CHECK: br label %[[EXIT]]
//
// CHECK: [[EXIT]]
- // CHECK: call void @__kmpc_kernel_deinit(
+ // CHECK: ret void
//
// Reduction function
- // CHECK: define internal void [[REDUCTION_FUNC:@.+]](i8*, i8*)
+ // CHECK: define internal void [[PAR_REDUCTION_FUNC:@.+]](i8*, i8*)
// CHECK: [[VAR1_RHS_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST_RHS:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[VAR1_RHS_VOID:%.+]] = load i8*, i8** [[VAR1_RHS_REF]],
// CHECK: [[VAR1_RHS:%.+]] = bitcast i8* [[VAR1_RHS_VOID]] to i32*
@@ -803,10 +287,9 @@ int bar(int n){
// CHECK: [[MAXV:%.+]] = phi i16 [ [[MAX1]], %[[DO_MAX]] ], [ [[MAX2]], %[[MAX_ELSE]] ]
// CHECK: store i16 [[MAXV]], i16* [[VAR2_LHS]],
// CHECK: ret void
-
//
// Shuffle and reduce function
- // CHECK: define internal void [[SHUFFLE_REDUCE_FN]](i8*, i16 {{.*}}, i16 {{.*}}, i16 {{.*}})
+ // CHECK: define internal void [[PAR_SHUFFLE_REDUCE_FN]](i8*, i16 {{.*}}, i16 {{.*}}, i16 {{.*}})
// CHECK: [[REMOTE_RED_LIST:%.+]] = alloca [[RLT]], align
// CHECK: [[REMOTE_ELT1:%.+]] = alloca i32
// CHECK: [[REMOTE_ELT2:%.+]] = alloca i16
@@ -866,7 +349,7 @@ int bar(int n){
// CHECK: [[DO_REDUCE]]
// CHECK: [[RED_LIST1_VOID:%.+]] = bitcast [[RLT]]* [[RED_LIST]] to i8*
// CHECK: [[RED_LIST2_VOID:%.+]] = bitcast [[RLT]]* [[REMOTE_RED_LIST]] to i8*
- // CHECK: call void [[REDUCTION_FUNC]](i8* [[RED_LIST1_VOID]], i8* [[RED_LIST2_VOID]])
+ // CHECK: call void [[PAR_REDUCTION_FUNC]](i8* [[RED_LIST1_VOID]], i8* [[RED_LIST2_VOID]])
// CHECK: br label {{%?}}[[REDUCE_CONT:.+]]
//
// CHECK: [[REDUCE_ELSE]]
@@ -907,7 +390,7 @@ int bar(int n){
//
// Inter warp copy function
- // CHECK: define internal void [[WARP_COPY_FN]](i8*, i32)
+ // CHECK: define internal void [[PAR_WARP_COPY_FN]](i8*, i32)
// CHECK-DAG: [[LANEID:%.+]] = and i32 {{.+}}, 31
// CHECK-DAG: [[WARPID:%.+]] = ashr i32 {{.+}}, 5
// CHECK-DAG: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
@@ -919,10 +402,9 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
//
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
// CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
- // CHECK: store i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: store volatile i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
// CHECK: [[COPY_ELSE]]
@@ -930,21 +412,19 @@ int bar(int n){
//
// Barrier after copy to shared memory storage medium.
// CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
+ // CHECK: [[ACTIVE_WARPS:%.+]] = load i32, i32*
//
// Read into warp 0.
// CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
// CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
//
// CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load volatile i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -952,7 +432,7 @@ int bar(int n){
// CHECK: br label {{%?}}[[READ_CONT]]
//
// CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
// CHECK: [[IS_WARP_MASTER:%.+]] = icmp eq i32 [[LANEID]], 0
// CHECK: br i1 [[IS_WARP_MASTER]], label {{%?}}[[DO_COPY:.+]], label {{%?}}[[COPY_ELSE:.+]]
//
@@ -961,10 +441,10 @@ int bar(int n){
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
//
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT32:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]]
+ // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT32]] to i16 addrspace([[SHARED_ADDRSPACE]])*
// CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
- // CHECK: store i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: store volatile i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: br label {{%?}}[[COPY_CONT:.+]]
//
// CHECK: [[COPY_ELSE]]
@@ -972,21 +452,20 @@ int bar(int n){
//
// Barrier after copy to shared memory storage medium.
// CHECK: [[COPY_CONT]]
- // CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
- // CHECK: [[ACTIVE_THREADS:%.+]] = mul nsw i32 [[ACTIVE_WARPS:%.+]], [[WS]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
+ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @
+ // CHECK: [[ACTIVE_WARPS:%.+]] = load i32, i32*
//
// Read into warp 0.
// CHECK: [[IS_W0_ACTIVE_THREAD:%.+]] = icmp ult i32 [[TID:%.+]], [[ACTIVE_WARPS]]
// CHECK: br i1 [[IS_W0_ACTIVE_THREAD]], label {{%?}}[[DO_READ:.+]], label {{%?}}[[READ_ELSE:.+]]
//
// CHECK: [[DO_READ]]
- // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
- // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])*
+ // CHECK: [[MEDIUM_ELT32:%.+]] = getelementptr inbounds [32 x i32], [32 x i32] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]]
+ // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT32]] to i16 addrspace([[SHARED_ADDRSPACE]])*
// CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
// CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
// CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
- // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
+ // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load volatile i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align
// CHECK: store i16 [[MEDIUM_ELT_VAL]], i16* [[ELT]], align
// CHECK: br label {{%?}}[[READ_CONT:.+]]
//
@@ -994,131 +473,6 @@ int bar(int n){
// CHECK: br label {{%?}}[[READ_CONT]]
//
// CHECK: [[READ_CONT]]
- // CHECK: call void @llvm.nvvm.barrier(i32 1, i32 [[ACTIVE_THREADS]])
// CHECK: ret
- //
- // Copy to scratchpad function
- // CHECK: define internal void [[SCRATCH_COPY_FN]](i8*, i8*, i32, i32)
- // CHECK: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[SCRATCHPAD_PTR:%.+]] = load i8*, i8** {{.+}}, align
- // CHECK-64: [[TEAM32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[TEAM:%.+]] = sext i32 [[TEAM32]] to i64
- // CHECK-32: [[TEAM:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS:%.+]] = sext i32 [[NUM_TEAMS32]] to i64
- // CHECK-32: [[NUM_TEAMS:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i32*
- // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align
- // CHECK: store i32 [[ELT_VAL]], i32* [[SCRATCHPAD_ELT_PTR]], align
- //
- // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 4
- // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
- //
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 2, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i16*
- // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align
- // CHECK: store i16 [[ELT_VAL]], i16* [[SCRATCHPAD_ELT_PTR]], align
- //
- // CHECK: ret
-
- //
- // Load and reduce function
- // CHECK: define internal void [[LOAD_REDUCE_FN]](i8*, i8*, i32, i32, i32)
- // CHECK: [[REMOTE_RED_LIST:%.+]] = alloca [[RLT]], align
- // CHECK: [[REMOTE_ELT1:%.+]] = alloca i32
- // CHECK: [[REMOTE_ELT2:%.+]] = alloca i16
- // CHECK: [[RED_LIST:%.+]] = bitcast i8* {{.+}} to [[RLT]]*
- // CHECK: [[SCRATCHPAD_PTR:%.+]] = load i8*, i8** {{.+}}, align
- // CHECK-64: [[TEAM32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[TEAM:%.+]] = sext i32 [[TEAM32]] to i64
- // CHECK-32: [[TEAM:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS32:%.+]] = load i32, i32* {{.+}}, align
- // CHECK-64: [[NUM_TEAMS:%.+]] = sext i32 [[NUM_TEAMS32]] to i64
- // CHECK-32: [[NUM_TEAMS:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SHOULD_REDUCE:%.+]] = load i32, i32* {{.+}}, align
- // CHECK: [[SCRATCHPAD:%.+]] = ptrtoint i8* [[SCRATCHPAD_PTR]] to i[[SZ]]
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 4, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
-
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i32*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[SCRATCHPAD_ELT_PTR]], align
- // CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[REMOTE_ELT1]], align
- // CHECK: [[REMOTE_ELT1_PTR:%.+]] = bitcast i32* [[REMOTE_ELT1]] to i8*
- // CHECK: store i8* [[REMOTE_ELT1_PTR]], i8** [[REMOTE_ELT_REF]], align
- //
- // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 4
- // CHECK: [[POS1:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[OF]]
- // CHECK: [[POS2:%.+]] = sub nuw i[[SZ]] [[POS1]], 1
- // CHECK: [[POS3:%.+]] = udiv i[[SZ]] [[POS2]], 256
- // CHECK: [[POS4:%.+]] = add nuw i[[SZ]] [[POS3]], 1
- // CHECK: [[SCRATCHPAD_NEXT:%.+]] = mul nuw i[[SZ]] [[POS4]], 256
- //
- // CHECK: [[P:%.+]] = mul nuw i[[SZ]] 2, [[TEAM]]
- // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]]
- // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8*
-
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i16*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[SCRATCHPAD_ELT_PTR]], align
- // CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[REMOTE_ELT2]], align
- // CHECK: [[REMOTE_ELT_PTR:%.+]] = bitcast i16* [[REMOTE_ELT2]] to i8*
- // CHECK: store i8* [[REMOTE_ELT_PTR]], i8** [[REMOTE_ELT_REF]], align
- //
- // CHECK: [[REDUCE:%.+]] = icmp ne i32 [[SHOULD_REDUCE]], 0
- // CHECK: br i1 [[REDUCE]], label {{%?}}[[DO_REDUCE:.+]], label {{%?}}[[REDUCE_ELSE:.+]]
- //
- // CHECK: [[DO_REDUCE]]
- // CHECK: [[RED_LIST1_VOID:%.+]] = bitcast [[RLT]]* [[RED_LIST]] to i8*
- // CHECK: [[RED_LIST2_VOID:%.+]] = bitcast [[RLT]]* [[REMOTE_RED_LIST]] to i8*
- // CHECK: call void [[REDUCTION_FUNC]](i8* [[RED_LIST1_VOID]], i8* [[RED_LIST2_VOID]])
- // CHECK: br label {{%?}}[[REDUCE_CONT:.+]]
- //
- // Copy element from remote reduce list
- // CHECK: [[REDUCE_ELSE]]
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i32*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align
- // CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[ELT]], align
- //
- // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[REMOTE_ELT_VOID:%.+]] = load i8*, i8** [[REMOTE_ELT_REF]],
- // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1
- // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]],
- // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i16*
- // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16*
- // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align
- // CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[ELT]], align
- // CHECK: br label {{%?}}[[REDUCE_CONT]]
- //
- // CHECK: [[REDUCE_CONT]]
- // CHECK: ret
-
-
#endif
diff --git a/test/OpenMP/openmp_offload_registration.cpp b/test/OpenMP/openmp_offload_registration.cpp
new file mode 100644
index 000000000000..d13ffed96be6
--- /dev/null
+++ b/test/OpenMP/openmp_offload_registration.cpp
@@ -0,0 +1,49 @@
+// Test for offload registration code for two targets
+// RUN: %clang_cc1 -verify -fopenmp -x c -triple x86_64-unknown-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu,powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+void foo() {
+#pragma omp target
+ {}
+}
+
+// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
+// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
+// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
+
+// Comdat key for the offload registration code. Should have sorted offload
+// target triples encoded into the name.
+// CHECK-DAG: $[[REGFN:\.omp_offloading\..+\.powerpc64le-ibm-linux-gnu\.x86_64-pc-linux-gnu+]] = comdat any
+
+// Check if offloading descriptor is created.
+// CHECK: [[ENTBEGIN:@.+]] = external constant [[ENTTY]]
+// CHECK: [[ENTEND:@.+]] = external constant [[ENTTY]]
+// CHECK: [[DEV1BEGIN:@.+]] = extern_weak constant i8
+// CHECK: [[DEV1END:@.+]] = extern_weak constant i8
+// CHECK: [[DEV2BEGIN:@.+]] = extern_weak constant i8
+// CHECK: [[DEV2END:@.+]] = extern_weak constant i8
+// CHECK: [[IMAGES:@.+]] = internal unnamed_addr constant [2 x [[DEVTY]]] [{{.+}} { i8* [[DEV1BEGIN]], i8* [[DEV1END]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, {{.+}} { i8* [[DEV2BEGIN]], i8* [[DEV2END]], [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }], comdat($[[REGFN]])
+// CHECK: [[DESC:@.+]] = internal constant [[DSCTY]] { i32 2, [[DEVTY]]* getelementptr inbounds ([2 x [[DEVTY]]], [2 x [[DEVTY]]]* [[IMAGES]], i32 0, i32 0), [[ENTTY]]* [[ENTBEGIN]], [[ENTTY]]* [[ENTEND]] }, comdat($[[REGFN]])
+
+// Check target registration is registered as a Ctor.
+// CHECK: appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @[[REGFN]], i8* bitcast (void ()* @[[REGFN]] to i8*) }]
+
+// Check presence of foo() and the outlined target region
+// CHECK: define void [[FOO:@.+]]()
+// CHECK: define internal void [[OUTLINEDTARGET:@.+]]()
+
+// Check registration and unregistration code.
+
+// CHECK: define internal void @[[UNREGFN:.+]](i8*)
+// CHECK-SAME: comdat($[[REGFN]]) {
+// CHECK: call i32 @__tgt_unregister_lib([[DSCTY]]* [[DESC]])
+// CHECK: ret void
+// CHECK: declare i32 @__tgt_unregister_lib([[DSCTY]]*)
+
+// CHECK: define linkonce hidden void @[[REGFN]]()
+// CHECK-SAME: comdat {
+// CHECK: call i32 @__tgt_register_lib([[DSCTY]]* [[DESC]])
+// CHECK: call i32 @__cxa_atexit(void (i8*)* @[[UNREGFN]], i8* bitcast ([[DSCTY]]* [[DESC]] to i8*),
+// CHECK: ret void
+// CHECK: declare i32 @__tgt_register_lib([[DSCTY]]*)
+
diff --git a/test/OpenMP/ordered_codegen.cpp b/test/OpenMP/ordered_codegen.cpp
index 977aba9d4555..ef7d39dfd0aa 100644
--- a/test/OpenMP/ordered_codegen.cpp
+++ b/test/OpenMP/ordered_codegen.cpp
@@ -11,7 +11,7 @@
#define HEADER
// CHECK: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
-// CHECK: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK-LABEL: define {{.*void}} @{{.*}}static_not_chunked{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
void static_not_chunked(float *a, float *b, float *c, float *d) {
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:[@%].+]])
@@ -44,7 +44,7 @@ void static_not_chunked(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK-NEXT: call void @__kmpc_end_ordered([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// ... end of ordered region ...
#pragma omp ordered
@@ -93,7 +93,7 @@ void dynamic1(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK-NEXT: call void @__kmpc_end_ordered([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// ... end of ordered region ...
#pragma omp ordered threads
@@ -147,7 +147,7 @@ void test_auto(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK-NEXT: call void @__kmpc_end_ordered([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// ... end of ordered region ...
#pragma omp ordered
@@ -198,7 +198,7 @@ void runtime(float *a, float *b, float *c, float *d) {
// ... loop body ...
// End of body: store into a[i]:
// CHECK: store float [[RESULT:%.+]], float* {{%.+}}
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK-NEXT: call void @__kmpc_end_ordered([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// ... end of ordered region ...
#pragma omp ordered threads
@@ -220,8 +220,8 @@ void runtime(float *a, float *b, float *c, float *d) {
float f[10];
// CHECK-LABEL: foo_simd
void foo_simd(int low, int up) {
- // CHECK: store float 0.000000e+00, float* %{{.+}}, align {{[0-9]+}}, !llvm.mem.parallel_loop_access !
- // CHECK-NEXT: call void [[CAP_FUNC:@.+]](i32* %{{.+}}), !llvm.mem.parallel_loop_access !
+ // CHECK: store float 0.000000e+00, float* %{{.+}}, align {{[0-9]+}}, !llvm.access.group !
+ // CHECK-NEXT: call void [[CAP_FUNC:@.+]](i32* %{{.+}}), !llvm.access.group !
#pragma omp simd
for (int i = low; i < up; ++i) {
f[i] = 0.0;
diff --git a/test/OpenMP/ordered_doacross_codegen.c b/test/OpenMP/ordered_doacross_codegen.c
index c12df2638f8f..a6cd4fe48b3f 100644
--- a/test/OpenMP/ordered_doacross_codegen.c
+++ b/test/OpenMP/ordered_doacross_codegen.c
@@ -19,17 +19,19 @@ void foo();
// CHECK-LABEL: @main()
int main() {
int i;
-// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]],
+// CHECK: [[DIMS:%.+]] = alloca [1 x [[KMP_DIM]]],
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
// CHECK: icmp
// CHECK-NEXT: br i1 %
-// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
+// CHECK: [[CAST:%.+]] = bitcast [1 x [[KMP_DIM]]]* [[DIMS]] to i8*
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
-// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
+// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
// CHECK: store i64 %{{.+}}, i64* %
-// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
// CHECK: store i64 1, i64* %
-// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
+// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
+// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
// CHECK: call void @__kmpc_for_static_init_4(
#pragma omp for ordered(1)
@@ -37,18 +39,26 @@ int main() {
a[i] = b[i] + 1;
foo();
// CHECK: call void [[FOO:.+]](
-// CHECK: load i32, i32* [[CNT:%.+]],
+// CHECK: load i32, i32* [[I:%.+]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
// CHECK-NEXT: sext i32 %{{.+}} to i64
-// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
#pragma omp ordered depend(source)
c[i] = c[i] + 1;
foo();
// CHECK: call void [[FOO]]
-// CHECK: load i32, i32* [[CNT]],
+// CHECK: load i32, i32* [[I]],
// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
// CHECK-NEXT: sext i32 %{{.+}} to i64
-// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
#pragma omp ordered depend(sink : i - 2)
d[i] = a[i - 2];
diff --git a/test/OpenMP/ordered_doacross_codegen.cpp b/test/OpenMP/ordered_doacross_codegen.cpp
index 60b0353b711e..2f19e9c2d5ef 100644
--- a/test/OpenMP/ordered_doacross_codegen.cpp
+++ b/test/OpenMP/ordered_doacross_codegen.cpp
@@ -19,17 +19,19 @@ void foo();
// CHECK-LABEL: @main()
int main() {
int i;
-// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]],
+// CHECK: [[DIMS:%.+]] = alloca [1 x [[KMP_DIM]]],
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
// CHECK: icmp
// CHECK-NEXT: br i1 %
-// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
+// CHECK: [[CAST:%.+]] = bitcast [1 x [[KMP_DIM]]]* [[DIMS]] to i8*
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
-// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
+// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
// CHECK: store i64 %{{.+}}, i64* %
-// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
// CHECK: store i64 1, i64* %
-// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
+// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
+// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
// CHECK: call void @__kmpc_for_static_init_4(
#pragma omp for ordered(1)
@@ -37,18 +39,26 @@ int main() {
a[i] = b[i] + 1;
foo();
// CHECK: invoke void [[FOO:.+]](
-// CHECK: load i32, i32* [[CNT:%.+]],
+// CHECK: load i32, i32* [[I:%.+]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
// CHECK-NEXT: sext i32 %{{.+}} to i64
-// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
#pragma omp ordered depend(source)
c[i] = c[i] + 1;
foo();
// CHECK: invoke void [[FOO]]
-// CHECK: load i32, i32* [[CNT]],
+// CHECK: load i32, i32* [[I]],
// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
// CHECK-NEXT: sext i32 %{{.+}} to i64
-// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
#pragma omp ordered depend(sink : i - 2)
d[i] = a[i - 2];
@@ -75,41 +85,84 @@ struct TestStruct {
T bar(T, T, T);
void baz(T, T);
TestStruct() {
-// CHECK: [[CNT:%.+]] = alloca i64,
-// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]],
+// CHECK: [[DIMS:%.+]] = alloca [2 x [[KMP_DIM]]],
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
-// CHECK: icmp
-// CHECK-NEXT: br i1 %
-// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
-// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
-// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
+// CHECK: [[CAST:%.+]] = bitcast [2 x [[KMP_DIM]]]* [[DIMS]] to i8*
+// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 48, i1 false)
+// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
+// CHECK: store i64 10, i64* %
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
+// CHECK: store i64 1, i64* %
+// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 1
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
// CHECK: store i64 %{{.+}}, i64* %
-// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
+// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
// CHECK: store i64 1, i64* %
-// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
-// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
-// CHECK: call void @__kmpc_for_static_init_8(
+// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
+// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
+// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 2, i8* [[CAST]])
+// CHECK: call void @__kmpc_for_static_init_4(
#pragma omp for ordered(2)
for (T j = 0; j < M; j++)
for (i = 0; i < n; i += 2) {
a[i][j] = foo(i, j);
// CHECK: invoke {{.+TestStruct.+foo}}
-// CHECK: load i64, i64* [[CNT]],
-// CHECK-NEXT: sub nsw i64 %{{.+}}, 1
+// CHECK: load i32*, i32** %
+// CHECK: load i32, i32* %
+// CHECK: load i32, i32* %
+// CHECK: load i32, i32* [[J:%.+]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
+// CHECK-NEXT: sext i32 %{{.+}} to i64
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF:%.+]],
+// CHECK-NEXT: load i32, i32* [[I]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 2
+// CHECK-NEXT: sext i32 %{{.+}} to i64
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
-// CHECK-NEXT: load i64, i64* [[CNT]],
-// CHECK-NEXT: load i32, i32* %
-// CHECK-NEXT: mul nsw i32 1, %
+// CHECK-NEXT: load i32, i32* [[J:%.+]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 1
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
// CHECK-NEXT: sext i32 %{{.+}} to i64
-// CHECK-NEXT: sub nsw i64 %
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]],
+// CHECK-NEXT: load i32, i32* [[I]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 2
+// CHECK-NEXT: sext i32 %{{.+}} to i64
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
#pragma omp ordered depend(sink : j, i - 2) depend(sink : j - 1, i)
b[i][j] = bar(a[i][j], b[i - 1][j], b[i][j - 1]);
// CHECK: invoke {{.+TestStruct.+bar}}
-// CHECK: load i64, i64* [[CNT]],
+// CHECK: load i32*, i32** %
+// CHECK: load i32, i32* %
+// CHECK: load i32, i32* %
+// CHECK: load i32, i32* [[J]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
+// CHECK-NEXT: sext i32 %{{.+}} to i64
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
+// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]],
+// CHECK-NEXT: load i32, i32* [[I]],
+// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
+// CHECK-NEXT: sdiv i32 %{{.+}}, 2
+// CHECK-NEXT: sext i32 %{{.+}} to i64
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
+// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
+// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
#pragma omp ordered depend(source)
baz(a[i][j], b[i][j]);
diff --git a/test/OpenMP/parallel_codegen.cpp b/test/OpenMP/parallel_codegen.cpp
index 0ecca8de64fe..19eebc8289ac 100644
--- a/test/OpenMP/parallel_codegen.cpp
+++ b/test/OpenMP/parallel_codegen.cpp
@@ -11,10 +11,10 @@
#define HEADER
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DEBUG-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DEBUG-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DEBUG-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DEBUG-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;main;[[@LINE+15]];9;;\00"
// CHECK-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}parallel_codegen.cpp;tmain;[[@LINE+7]];9;;\00"
diff --git a/test/OpenMP/parallel_copyin_codegen.cpp b/test/OpenMP/parallel_copyin_codegen.cpp
index 3d33aa2cfe0a..5e056b9ccb0c 100644
--- a/test/OpenMP/parallel_copyin_codegen.cpp
+++ b/test/OpenMP/parallel_copyin_codegen.cpp
@@ -1,30 +1,30 @@
-// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
-// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -triple x86_64-linux -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-linux -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -x c++ -triple x86_64-linux -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -DLAMBDA -triple x86_64-linux -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
+// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -fblocks -DBLOCKS -triple x86_64-linux -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -triple x86_64-linux -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-linux -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -x c++ -triple x86_64-linux -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -DLAMBDA -triple x86_64-linux -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -fblocks -DBLOCKS -triple x86_64-linux -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -verify -fopenmp-simd -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s -check-prefix=TLS-CHECK
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TLS-CHECK
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=TLS-LAMBDA %s
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=TLS-BLOCKS %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-linux -emit-llvm %s -o - | FileCheck %s -check-prefix=TLS-CHECK
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-linux -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-linux -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -check-prefix=TLS-CHECK
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-linux -emit-llvm %s -o - | FileCheck -check-prefix=TLS-LAMBDA %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-linux -emit-llvm %s -o - | FileCheck -check-prefix=TLS-BLOCKS %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=TLS-ARRAY %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-linux -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-linux -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-linux -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-linux -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-linux -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
@@ -47,10 +47,10 @@ struct S {
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
-// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// TLS-CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
// TLS-CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
-// TLS-CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// TLS-CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK-DAG: [[T_VAR:@.+]] = internal global i{{[0-9]+}} 1122,
// CHECK-DAG: [[VEC:@.+]] = internal global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
diff --git a/test/OpenMP/parallel_default_messages.cpp b/test/OpenMP/parallel_default_messages.cpp
index 4b698bccb0fb..eb4b378f0dab 100644
--- a/test/OpenMP/parallel_default_messages.cpp
+++ b/test/OpenMP/parallel_default_messages.cpp
@@ -1,10 +1,15 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
-
-// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-simd -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-version=50 -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-version=40 -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-version=31 -fopenmp -ferror-limit 100 -o - %s
+// RUN: %clang_cc1 -verify -fopenmp-version=30 -fopenmp -ferror-limit 100 -o - %s
void foo();
int main(int argc, char **argv) {
+ const int c = 0;
+
#pragma omp parallel default // expected-error {{expected '(' after 'default'}}
#pragma omp parallel default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
@@ -18,6 +23,9 @@ int main(int argc, char **argv) {
#pragma omp parallel default(none)
#pragma omp parallel default(shared)
- ++argc;
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ #pragma omp parallel default(none)
+ (void)c; // ge40-error {{variable 'c' must have explicitly specified data sharing attributes}}
return 0;
}
diff --git a/test/OpenMP/parallel_for_ast_print.cpp b/test/OpenMP/parallel_for_ast_print.cpp
index 1e77bc855a22..036279030c1d 100644
--- a/test/OpenMP/parallel_for_ast_print.cpp
+++ b/test/OpenMP/parallel_for_ast_print.cpp
@@ -103,6 +103,29 @@ T tmain(T argc) {
return T();
}
+int increment () {
+ #pragma omp for
+ for (int i = 5 ; i != 0; ++i)
+ ;
+ // CHECK: int increment() {
+ // CHECK-NEXT: #pragma omp for
+ // CHECK-NEXT: for (int i = 5; i != 0; ++i)
+ // CHECK-NEXT: ;
+ return 0;
+}
+
+int decrement_nowait () {
+ #pragma omp for nowait
+ for (int j = 5 ; j != 0; --j)
+ ;
+ // CHECK: int decrement_nowait() {
+ // CHECK-NEXT: #pragma omp for nowait
+ // CHECK-NEXT: for (int j = 5; j != 0; --j)
+ // CHECK-NEXT: ;
+ return 0;
+}
+
+
int main(int argc, char **argv) {
int b = argc, c, d, e, f, h;
static int a;
diff --git a/test/OpenMP/parallel_for_codegen.cpp b/test/OpenMP/parallel_for_codegen.cpp
index e6199f00eabd..a3d307afac97 100644
--- a/test/OpenMP/parallel_for_codegen.cpp
+++ b/test/OpenMP/parallel_for_codegen.cpp
@@ -15,7 +15,7 @@
#define HEADER
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
-// CHECK-DAG: [[LOOP_LOC:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 514, i32 0, i32 0, i8*
+// CHECK-DAG: [[LOOP_LOC:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 514, i32 0, i32 0, i8*
// CHECK-LABEL: with_var_schedule
void with_var_schedule() {
@@ -267,8 +267,8 @@ void test_auto(float *a, float *b, float *c, float *d) {
unsigned int x = 0;
unsigned int y = 0;
#pragma omp parallel for schedule(auto) collapse(2)
-// CHECK: call void ([[IDENT_T_TY]]*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call([[IDENT_T_TY]]* [[DEFAULT_LOC:[@%].+]], i32 6, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i32*, float**, float**, float**, float**)* [[OMP_PARALLEL_FUNC:@.+]] to void (i32*, i32*, ...)*),
-// CHECK: define internal void [[OMP_PARALLEL_FUNC]](i32* noalias [[GTID_PARAM_ADDR:%.+]], i32* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}}, i32* dereferenceable(4) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}})
+// CHECK: call void ([[IDENT_T_TY]]*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call([[IDENT_T_TY]]* [[DEFAULT_LOC:[@%].+]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float**, float**, float**, float**)* [[OMP_PARALLEL_FUNC:@.+]] to void (i32*, i32*, ...)*),
+// CHECK: define internal void [[OMP_PARALLEL_FUNC]](i32* noalias [[GTID_PARAM_ADDR:%.+]], i32* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}})
// CHECK: store i32* [[GTID_PARAM_ADDR]], i32** [[GTID_REF_ADDR:%.+]],
// CHECK: call void @__kmpc_dispatch_init_8([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID:%.+]], i32 38, i64 0, i64 [[LAST_ITER:%[^,]+]], i64 1, i64 1)
//
@@ -311,8 +311,8 @@ void test_auto(float *a, float *b, float *c, float *d) {
void runtime(float *a, float *b, float *c, float *d) {
int x = 0;
#pragma omp parallel for collapse(2) schedule(runtime)
-// CHECK: call void ([[IDENT_T_TY]]*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call([[IDENT_T_TY]]* [[DEFAULT_LOC:[@%].+]], i32 5, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float**, float**, float**, float**)* [[OMP_PARALLEL_FUNC:@.+]] to void (i32*, i32*, ...)*),
-// CHECK: define internal void [[OMP_PARALLEL_FUNC]](i32* noalias [[GTID_PARAM_ADDR:%.+]], i32* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}})
+// CHECK: call void ([[IDENT_T_TY]]*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call([[IDENT_T_TY]]* [[DEFAULT_LOC:[@%].+]], i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, float**, float**, float**, float**)* [[OMP_PARALLEL_FUNC:@.+]] to void (i32*, i32*, ...)*),
+// CHECK: define internal void [[OMP_PARALLEL_FUNC]](i32* noalias [[GTID_PARAM_ADDR:%.+]], i32* noalias %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}}, float** dereferenceable(8) %{{.+}})
// CHECK: store i32* [[GTID_PARAM_ADDR]], i32** [[GTID_REF_ADDR:%.+]],
// CHECK: call void @__kmpc_dispatch_init_4([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID:%.+]], i32 37, i32 0, i32 199, i32 1, i32 1)
//
@@ -376,5 +376,85 @@ void parallel_for(float *a, const int n) {
// TERM_DEBUG-DAG: [[DBG_LOC_START]] = !DILocation(line: [[@LINE-4]],
// TERM_DEBUG-DAG: [[DBG_LOC_END]] = !DILocation(line: [[@LINE-18]],
+// CHECK-LABEL: increment
+int increment () {
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:[@%].+]])
+ #pragma omp for
+// Determine UB = min(UB, GlobalUB)
+// CHECK: call void @__kmpc_for_static_init_4([[IDENT_T_TY]]* [[LOOP_LOC]], i32 [[GTID]], i32 34, i32* [[IS_LAST:%[^,]+]], i32* [[OMP_LB:%[^,]+]], i32* [[OMP_UB:%[^,]+]], i32* [[OMP_ST:%[^,]+]], i32 1, i32 1)
+// CHECK-NEXT: [[UB:%.+]] = load i32, i32* [[OMP_UB]]
+// CHECK-NEXT: [[UBCMP:%.+]] = icmp sgt i32 [[UB]], 4
+// CHECK-NEXT: br i1 [[UBCMP]], label [[UB_TRUE:%[^,]+]], label [[UB_FALSE:%[^,]+]]
+// CHECK: [[UBRESULT:%.+]] = phi i32 [ 4, [[UB_TRUE]] ], [ [[UBVAL:%[^,]+]], [[UB_FALSE]] ]
+// CHECK-NEXT: store i32 [[UBRESULT]], i32* [[OMP_UB]]
+// CHECK-NEXT: [[LB:%.+]] = load i32, i32* [[OMP_LB]]
+// CHECK-NEXT: store i32 [[LB]], i32* [[OMP_IV:[^,]+]]
+// CHECK-NEXT: br label %[[LOOP1_HEAD:.+]]
+
+// Loop header
+// CHECK: [[LOOP1_HEAD]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[UB:%.+]] = load i32, i32* [[OMP_UB]]
+// CHECK-NEXT: [[CMP:%.+]] = icmp sle i32 [[IV]], [[UB]]
+// CHECK-NEXT: br i1 [[CMP]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]]
+
+ for (int i = 0 ; i != 5; ++i)
+// Start of body: calculate i from IV:
+// CHECK: [[LOOP1_BODY]]
+// CHECK: [[IV1_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[CALC_I_1:%.+]] = mul nsw i32 [[IV1_1]], 1
+// CHECK-NEXT: [[CALC_I_2:%.+]] = add nsw i32 0, [[CALC_I_1]]
+// CHECK-NEXT: store i32 [[CALC_I_2]], i32* [[LC_I:.+]]
+// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}
+// CHECK-NEXT: [[ADD1_2:%.+]] = add nsw i32 [[IV1_2]], 1
+// CHECK-NEXT: store i32 [[ADD1_2]], i32* [[OMP_IV]]
+// CHECK-NEXT: br label %[[LOOP1_HEAD]]
+ ;
+// CHECK: [[LOOP1_END]]
+// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[LOOP_LOC]], i32 [[GTID]])
+// CHECK: __kmpc_barrier
+ return 0;
+// CHECK: ret i32 0
+}
+
+// CHECK-LABEL: decrement_nowait
+int decrement_nowait () {
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:[@%].+]])
+ #pragma omp for nowait
+// Determine UB = min(UB, GlobalUB)
+// CHECK: call void @__kmpc_for_static_init_4([[IDENT_T_TY]]* [[LOOP_LOC]], i32 [[GTID]], i32 34, i32* [[IS_LAST:%[^,]+]], i32* [[OMP_LB:%[^,]+]], i32* [[OMP_UB:%[^,]+]], i32* [[OMP_ST:%[^,]+]], i32 1, i32 1)
+// CHECK-NEXT: [[UB:%.+]] = load i32, i32* [[OMP_UB]]
+// CHECK-NEXT: [[UBCMP:%.+]] = icmp sgt i32 [[UB]], 4
+// CHECK-NEXT: br i1 [[UBCMP]], label [[UB_TRUE:%[^,]+]], label [[UB_FALSE:%[^,]+]]
+// CHECK: [[UBRESULT:%.+]] = phi i32 [ 4, [[UB_TRUE]] ], [ [[UBVAL:%[^,]+]], [[UB_FALSE]] ]
+// CHECK-NEXT: store i32 [[UBRESULT]], i32* [[OMP_UB]]
+// CHECK-NEXT: [[LB:%.+]] = load i32, i32* [[OMP_LB]]
+// CHECK-NEXT: store i32 [[LB]], i32* [[OMP_IV:[^,]+]]
+// CHECK-NEXT: br label %[[LOOP1_HEAD:.+]]
+
+// Loop header
+// CHECK: [[LOOP1_HEAD]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[UB:%.+]] = load i32, i32* [[OMP_UB]]
+// CHECK-NEXT: [[CMP:%.+]] = icmp sle i32 [[IV]], [[UB]]
+// CHECK-NEXT: br i1 [[CMP]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]]
+ for (int j = 5 ; j != 0; --j)
+// Start of body: calculate i from IV:
+// CHECK: [[LOOP1_BODY]]
+// CHECK: [[IV2_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[CALC_II_1:%.+]] = mul nsw i32 [[IV2_1]], 1
+// CHECK-NEXT: [[CALC_II_2:%.+]] = sub nsw i32 5, [[CALC_II_1]]
+// CHECK-NEXT: store i32 [[CALC_II_2]], i32* [[LC_I:.+]]
+// CHECK: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}
+// CHECK-NEXT: [[ADD2_2:%.+]] = add nsw i32 [[IV2_2]], 1
+// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]
+// CHECK-NEXT: br label %[[LOOP1_HEAD]]
+ ;
+// CHECK: [[LOOP1_END]]
+// CHECK: call void @__kmpc_for_static_fini([[IDENT_T_TY]]* [[LOOP_LOC]], i32 [[GTID]])
+// CHECK-NOT: __kmpc_barrier
+ return 0;
+// CHECK: ret i32 0
+}
#endif // HEADER
diff --git a/test/OpenMP/parallel_for_default_messages.cpp b/test/OpenMP/parallel_for_default_messages.cpp
index 743383640f3b..95f6c9193e9e 100644
--- a/test/OpenMP/parallel_for_default_messages.cpp
+++ b/test/OpenMP/parallel_for_default_messages.cpp
@@ -31,7 +31,7 @@ int main(int argc, char **argv) {
#pragma omp parallel default(none)
#pragma omp parallel for default(shared)
- for (i = 0; i < argc; ++i)
+ for (i = 0; i < argc; ++i) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
foo();
return 0;
diff --git a/test/OpenMP/parallel_for_lastprivate_messages.cpp b/test/OpenMP/parallel_for_lastprivate_messages.cpp
index 8d2f4b5886fc..ae635f342179 100644
--- a/test/OpenMP/parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/parallel_for_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
S2 &operator=(const S2 &);
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -168,7 +168,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel for lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -180,10 +180,10 @@ int main(int argc, char **argv) {
#pragma omp parallel for lastprivate(ba)
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel for lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel for lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel for safelen(5) // expected-error {{unexpected OpenMP clause 'safelen' in directive '#pragma omp parallel for'}}
diff --git a/test/OpenMP/parallel_for_linear_messages.cpp b/test/OpenMP/parallel_for_linear_messages.cpp
index 080add692cab..6596814de646 100644
--- a/test/OpenMP/parallel_for_linear_messages.cpp
+++ b/test/OpenMP/parallel_for_linear_messages.cpp
@@ -146,7 +146,7 @@ int foomain(I argc, C **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp parallel for linear(a, b : B::ib)
for (int k = 0; k < argc; ++k)
++k;
@@ -231,7 +231,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp parallel for linear(a, b)
for (int k = 0; k < argc; ++k)
++k;
diff --git a/test/OpenMP/parallel_for_loop_messages.cpp b/test/OpenMP/parallel_for_loop_messages.cpp
index 193c84e27fa5..12020c37a575 100644
--- a/test/OpenMP/parallel_for_loop_messages.cpp
+++ b/test/OpenMP/parallel_for_loop_messages.cpp
@@ -108,7 +108,7 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// Ok
#pragma omp parallel for
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/parallel_for_reduction_messages.cpp b/test/OpenMP/parallel_for_reduction_messages.cpp
index 5cfc2b9041ab..c44ee676d6a6 100644
--- a/test/OpenMP/parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/parallel_for_reduction_messages.cpp
@@ -136,22 +136,22 @@ T tmain(T argc) {
#pragma omp parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -160,7 +160,7 @@ T tmain(T argc) {
#pragma omp parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -179,7 +179,7 @@ T tmain(T argc) {
#pragma omp parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -258,22 +258,22 @@ int main(int argc, char **argv) {
#pragma omp parallel for reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -282,7 +282,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -304,7 +304,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/parallel_for_simd_ast_print.cpp b/test/OpenMP/parallel_for_simd_ast_print.cpp
index fd4153752af3..597e66d22e3f 100644
--- a/test/OpenMP/parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/parallel_for_simd_ast_print.cpp
@@ -48,7 +48,7 @@ class S8 : public S7<S1> {
public:
S8(int v) : S7<S1>(v){
-#pragma omp parallel for simd private(a) private(this->a) private(S7<S1>::a)
+#pragma omp parallel for simd private(a) private(this->a) private(S7 <S1>::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
diff --git a/test/OpenMP/parallel_for_simd_codegen.cpp b/test/OpenMP/parallel_for_simd_codegen.cpp
index e8cb651e2bc5..9585bf293695 100644
--- a/test/OpenMP/parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/parallel_for_simd_codegen.cpp
@@ -83,21 +83,21 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
// CHECK: store i32 [[LB_VAL]], i32* [[OMP_IV2:%[^,]+]],
-// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID:[0-9]+]]
-// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
+// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP2:%.+]] = icmp sle i32 [[IV2]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP2_BODY:.+]], label %[[SIMPLE_LOOP2_END:[^,]+]]
for (int i = 10; i > 1; i--) {
// CHECK: [[SIMPLE_LOOP2_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
// CHECK-NEXT: [[IV2_1:%.+]] = mul nsw i32 [[IV2_0]], 1
// CHECK-NEXT: [[LC_I_1:%.+]] = sub nsw i32 10, [[IV2_1]]
-// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.access.group
//
-// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
-// CHECK-NEXT: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LIN_MUL1:%.+]] = mul nsw i32 [[IV2_2]], 3
// CHECK-NEXT: [[LIN_EXT1:%.+]] = sext i32 [[LIN_MUL1]] to i64
// CHECK-NEXT: [[LIN_ADD1:%.+]] = add nsw i64 [[LIN0_1]], [[LIN_EXT1]]
@@ -105,9 +105,9 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[LIN_ADD1]], i64* [[K_PRIVATIZED:%[^,]+]]
a[k]++;
k = k + 3;
-// CHECK: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2_2:%.+]] = add nsw i32 [[IV2_2]], 1
-// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP2_ID]]
}
// CHECK: [[SIMPLE_LOOP2_END]]:
@@ -513,22 +513,70 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CALC_I_1_MUL1:%.+]] = mul i32 [[CALC_I_1]], 1
// CHECK-NEXT: [[CALC_I_2:%.+]] = add i32 1, [[CALC_I_1_MUL1]]
// CHECK-NEXT: store i32 [[CALC_I_2]], i32* [[LC_I:.+]]
+
// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]
-// CHECK-NEXT: [[CALC_J_1:%.+]] = udiv i32 [[IV1_2]], 20
-// CHECK-NEXT: [[CALC_J_2:%.+]] = urem i32 [[CALC_J_1]], 3
+// CHECK: [[IV1_2_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[CALC_J_1:%.+]] = udiv i32 [[IV1_2_1]], 60
+// CHECK-NEXT: [[MUL_1:%.+]] = mul i32 [[CALC_J_1]], 60
+// CHECK-NEXT: [[SUB_3:%.+]] = sub i32 [[IV1_2]], [[MUL_1]]
+// CHECK-NEXT: [[CALC_J_2:%.+]] = udiv i32 [[SUB_3]], 20
// CHECK-NEXT: [[CALC_J_2_MUL1:%.+]] = mul i32 [[CALC_J_2]], 1
// CHECK-NEXT: [[CALC_J_3:%.+]] = add i32 2, [[CALC_J_2_MUL1]]
// CHECK-NEXT: store i32 [[CALC_J_3]], i32* [[LC_J:.+]]
+
// CHECK: [[IV1_3:%.+]] = load i32, i32* [[OMP_IV]]
-// CHECK-NEXT: [[CALC_K_1:%.+]] = udiv i32 [[IV1_3]], 5
-// CHECK-NEXT: [[CALC_K_2:%.+]] = urem i32 [[CALC_K_1]], 4
-// CHECK-NEXT: [[CALC_K_2_MUL1:%.+]] = mul i32 [[CALC_K_2]], 1
-// CHECK-NEXT: [[CALC_K_3:%.+]] = add i32 3, [[CALC_K_2_MUL1]]
-// CHECK-NEXT: store i32 [[CALC_K_3]], i32* [[LC_K:.+]]
+// CHECK: [[IV1_3_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_1:%.+]] = udiv i32 [[IV1_3_1]], 60
+// CHECK-NEXT: [[MUL_2:%.+]] = mul i32 [[DIV_1]], 60
+// CHECK-NEXT: [[ADD_3:%.+]] = sub i32 [[IV1_3]], [[MUL_2]]
+
// CHECK: [[IV1_4:%.+]] = load i32, i32* [[OMP_IV]]
-// CHECK-NEXT: [[CALC_L_1:%.+]] = urem i32 [[IV1_4]], 5
-// CHECK-NEXT: [[CALC_L_1_MUL1:%.+]] = mul i32 [[CALC_L_1]], 1
-// CHECK-NEXT: [[CALC_L_2:%.+]] = add i32 4, [[CALC_L_1_MUL1]]
+// CHECK: [[IV1_4_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_2:%.+]] = udiv i32 [[IV1_4_1]], 60
+// CHECK-NEXT: [[MUL_3:%.+]] = mul i32 [[DIV_2]], 60
+// CHECK-NEXT: [[SUB_6:%.+]] = sub i32 [[IV1_4]], [[MUL_3]]
+// CHECK-NEXT: [[DIV_3:%.+]] = udiv i32 [[SUB_6]], 20
+// CHECK-NEXT: [[MUL_4:%.+]] = mul i32 [[DIV_3]], 20
+// CHECK-NEXT: [[SUB_7:%.+]] = sub i32 [[ADD_3]], [[MUL_4]]
+// CHECK-NEXT: [[DIV_4:%.+]] = udiv i32 [[SUB_7]], 5
+// CHECK-NEXT: [[MUL_5:%.+]] = mul i32 [[DIV_4]], 1
+// CHECK-NEXT: [[ADD_6:%.+]] = add i32 3, [[MUL_5]]
+// CHECK-NEXT: store i32 [[ADD_6]], i32* [[LC_K:.+]]
+
+// CHECK: [[IV1_5:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_5_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_5:%.+]] = udiv i32 [[IV1_5_1]], 60
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[DIV_5]], 60
+// CHECK-NEXT: [[ADD_7:%.+]] = sub i32 [[IV1_5]], [[MUL_6]]
+
+// CHECK: [[IV1_6:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_6_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_6:%.+]] = udiv i32 [[IV1_6_1]], 60
+// CHECK-NEXT: [[MUL_7:%.+]] = mul i32 [[DIV_6]], 60
+// CHECK-NEXT: [[SUB_10:%.+]] = sub i32 [[IV1_6]], [[MUL_7]]
+// CHECK-NEXT: [[DIV_7:%.+]] = udiv i32 [[SUB_10]], 20
+// CHECK-NEXT: [[MUL_8:%.+]] = mul i32 [[DIV_7]], 20
+// CHECK-NEXT: [[ADD_9:%.+]] = sub i32 [[ADD_7]], [[MUL_8]]
+
+// CHECK: [[IV1_7:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_7_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_8:%.+]] = udiv i32 [[IV1_7_1]], 60
+// CHECK-NEXT: [[MUL_9:%.+]] = mul i32 [[DIV_8]], 60
+// CHECK-NEXT: [[ADD_10:%.+]] = sub i32 [[IV1_7]], [[MUL_9]]
+
+// CHECK: [[IV1_8:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_8_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_3:%.+]] = udiv i32 [[IV1_8_1]], 60
+// CHECK-NEXT: [[MUL_4:%.+]] = mul i32 [[DIV_3]], 60
+// CHECK-NEXT: [[SUB_7:%.+]] = sub i32 [[IV1_8]], [[MUL_4]]
+// CHECK-NEXT: [[DIV_4:%.+]] = udiv i32 [[SUB_7]], 20
+// CHECK-NEXT: [[MUL_5:%.+]] = mul i32 [[DIV_4]], 20
+// CHECK-NEXT: [[SUB_8:%.+]] = sub i32 [[ADD_10]], [[MUL_5]]
+// CHECK-NEXT: [[DIV_5:%.+]] = udiv i32 [[SUB_8]], 5
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[DIV_5]], 5
+// CHECK-NEXT: [[SUB_9:%.+]] = sub i32 [[ADD_9]], [[MUL_6]]
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[SUB_9]], 1
+// CHECK-NEXT: [[CALC_L_2:%.+]] = add i32 4, [[MUL_6]]
// CHECK-NEXT: [[CALC_L_3:%.+]] = trunc i32 [[CALC_L_2]] to i16
// CHECK-NEXT: store i16 [[CALC_L_3]], i16* [[LC_L:.+]]
// ... loop body ...
@@ -655,7 +703,10 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[I_2:%.+]] = trunc i64 [[I_1_ADD0]] to i32
// CHECK-NEXT: store i32 [[I_2]], i32*
// CHECK: [[IV2:%.+]] = load i64, i64* [[T1_OMP_IV]]
-// CHECK-NEXT: [[J_1:%.+]] = srem i64 [[IV2]], 4
+// CHECK: [[IV2_1:%.+]] = load i64, i64* [[T1_OMP_IV]]
+// CHECK-NEXT: [[DIV_1:%.+]] = sdiv i64 [[IV2_1]], 4
+// CHECK-NEXT: [[MUL_1:%.+]] = mul nsw i64 [[DIV_1]], 4
+// CHECK-NEXT: [[J_1:%.+]] = sub nsw i64 [[IV2]], [[MUL_1]]
// CHECK-NEXT: [[J_2:%.+]] = mul nsw i64 [[J_1]], 2
// CHECK-NEXT: [[J_2_ADD0:%.+]] = add nsw i64 0, [[J_2]]
// CHECK-NEXT: store i64 [[J_2_ADD0]], i64*
diff --git a/test/OpenMP/parallel_for_simd_default_messages.cpp b/test/OpenMP/parallel_for_simd_default_messages.cpp
index 2fccb5634b44..6d751449bc3c 100644
--- a/test/OpenMP/parallel_for_simd_default_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_default_messages.cpp
@@ -31,7 +31,7 @@ int main(int argc, char **argv) {
#pragma omp parallel default(none)
#pragma omp parallel for simd default(shared)
- for (i = 0; i < argc; ++i)
+ for (i = 0; i < argc; ++i) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}} expected-error {{variable 'i' must have explicitly specified data sharing attributes}}
foo();
return 0;
diff --git a/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp
index 84e0896f1ff2..5759e835b2fa 100644
--- a/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_lastprivate_messages.cpp
@@ -19,7 +19,7 @@ public:
S2(S2 &s2) : a(s2.a) {}
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -32,9 +32,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -138,8 +138,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -170,7 +170,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel for simd lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -182,10 +182,10 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd lastprivate(ba)
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel for simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel for simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -195,7 +195,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp parallel for simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel for simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel for simd safelen(5)
diff --git a/test/OpenMP/parallel_for_simd_linear_messages.cpp b/test/OpenMP/parallel_for_simd_linear_messages.cpp
index a6bcf64806f6..792978e63103 100644
--- a/test/OpenMP/parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_linear_messages.cpp
@@ -122,7 +122,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp parallel for simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp parallel for simd linear (a, b:B::ib)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp parallel for simd linear (argv[1]) // expected-error {{expected variable name}}
@@ -186,7 +186,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp parallel for simd linear (a, b)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp parallel for simd linear (argv[1]) // expected-error {{expected variable name}}
diff --git a/test/OpenMP/parallel_for_simd_loop_messages.cpp b/test/OpenMP/parallel_for_simd_loop_messages.cpp
index d9d05cccc54c..ba54cb2c09ac 100644
--- a/test/OpenMP/parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_loop_messages.cpp
@@ -108,7 +108,7 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// Ok
#pragma omp parallel for simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/parallel_for_simd_reduction_messages.cpp b/test/OpenMP/parallel_for_simd_reduction_messages.cpp
index 32222ac5a53f..5be42461f02d 100644
--- a/test/OpenMP/parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_reduction_messages.cpp
@@ -130,22 +130,22 @@ T tmain(T argc) {
#pragma omp parallel for simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -154,7 +154,7 @@ T tmain(T argc) {
#pragma omp parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -173,7 +173,7 @@ T tmain(T argc) {
#pragma omp parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -252,22 +252,22 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -276,7 +276,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel for simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -298,7 +298,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp parallel for simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel for simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/parallel_if_codegen.cpp b/test/OpenMP/parallel_if_codegen.cpp
index 49e4bd402ce8..ec9fc01561bd 100644
--- a/test/OpenMP/parallel_if_codegen.cpp
+++ b/test/OpenMP/parallel_if_codegen.cpp
@@ -55,9 +55,9 @@ int tmain(T Arg) {
// CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main()
int main() {
-// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
// CHECK: store i32 0, i32* [[ZERO_ADDR2:%.+]],
// CHECK: store i32 0, i32* [[ZERO_ADDR1:%.+]],
+// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN4:@.+]] to void
#pragma omp parallel if (true)
fn4();
@@ -96,9 +96,9 @@ int main() {
// CHECK: ret void
// CHECK-LABEL: define {{.+}} @{{.+}}tmain
-// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
// CHECK: store i32 0, i32* [[ZERO_ADDR2:%.+]],
// CHECK: store i32 0, i32* [[ZERO_ADDR1:%.+]],
+// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN1:@.+]] to void
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
// CHECK: call void [[CAP_FN2:@.+]](i32* [[ZERO_ADDR1]], i32* [[ZERO_ADDR1]])
diff --git a/test/OpenMP/parallel_num_threads_codegen.cpp b/test/OpenMP/parallel_num_threads_codegen.cpp
index 9ec712f83c53..79615b934168 100644
--- a/test/OpenMP/parallel_num_threads_codegen.cpp
+++ b/test/OpenMP/parallel_num_threads_codegen.cpp
@@ -15,7 +15,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[S_TY:%.+]] = type { [[INTPTR_T_TY:i[0-9]+]], [[INTPTR_T_TY]], [[INTPTR_T_TY]] }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/parallel_private_messages.cpp b/test/OpenMP/parallel_private_messages.cpp
index 4adee55e341c..e8fd70d2ff1d 100644
--- a/test/OpenMP/parallel_private_messages.cpp
+++ b/test/OpenMP/parallel_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -52,8 +52,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g[] = {5, 6};
int i;
@@ -66,11 +66,11 @@ int main(int argc, char **argv) {
#pragma omp parallel private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
#pragma omp parallel private (argc argv) // expected-error {{expected ',' or ')' in 'private' clause}}
#pragma omp parallel private (S1) // expected-error {{'S1' does not refer to a value}}
- #pragma omp parallel private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp parallel private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
#pragma omp parallel private (argv[1]) // expected-error {{expected variable name}}
#pragma omp parallel private(ba)
- #pragma omp parallel private(ca) // expected-error {{shared variable cannot be private}}
- #pragma omp parallel private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp parallel private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
+ #pragma omp parallel private(da) // expected-error {{const-qualified variable cannot be private}}
#pragma omp parallel private(S2::S2s) // expected-error {{shared variable cannot be private}}
#pragma omp parallel private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
#pragma omp parallel private(threadvar, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be private}}
diff --git a/test/OpenMP/parallel_proc_bind_codegen.cpp b/test/OpenMP/parallel_proc_bind_codegen.cpp
index 8b9e09191b24..4747a8182e58 100644
--- a/test/OpenMP/parallel_proc_bind_codegen.cpp
+++ b/test/OpenMP/parallel_proc_bind_codegen.cpp
@@ -14,7 +14,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/parallel_reduction_codegen.cpp b/test/OpenMP/parallel_reduction_codegen.cpp
index c064ed071210..bd43a9328af7 100644
--- a/test/OpenMP/parallel_reduction_codegen.cpp
+++ b/test/OpenMP/parallel_reduction_codegen.cpp
@@ -84,7 +84,7 @@ struct SST {
// BLOCKS: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
-// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
+// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
// CHECK-DAG: [[REDUCTION_LOCK:@.+]] = common global [8 x i32] zeroinitializer
//CHECK: foo_array_sect
diff --git a/test/OpenMP/parallel_reduction_messages.cpp b/test/OpenMP/parallel_reduction_messages.cpp
index b3619bb9ad4d..f520d4a0fa92 100644
--- a/test/OpenMP/parallel_reduction_messages.cpp
+++ b/test/OpenMP/parallel_reduction_messages.cpp
@@ -116,23 +116,23 @@ T tmain(T argc) {
foo();
#pragma omp parallel reduction(^ : T) // expected-error {{'T' does not refer to a value}}
foo();
-#pragma omp parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp parallel reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp parallel reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp parallel reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp parallel reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
foo();
@@ -145,7 +145,7 @@ T tmain(T argc) {
foo();
#pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
foo();
-#pragma omp parallel reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -211,23 +211,23 @@ int main(int argc, char **argv) {
foo();
#pragma omp parallel reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
foo();
-#pragma omp parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp parallel reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp parallel reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp parallel reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp parallel reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
foo();
@@ -242,7 +242,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp parallel reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
foo();
-#pragma omp parallel reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/parallel_sections_default_messages.cpp b/test/OpenMP/parallel_sections_default_messages.cpp
index a62b86ff34a8..b16e5f73695e 100644
--- a/test/OpenMP/parallel_sections_default_messages.cpp
+++ b/test/OpenMP/parallel_sections_default_messages.cpp
@@ -34,7 +34,7 @@ int main(int argc, char **argv) {
{
#pragma omp parallel sections default(shared)
{
- ++argc;
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
}
}
return 0;
diff --git a/test/OpenMP/parallel_sections_lastprivate_messages.cpp b/test/OpenMP/parallel_sections_lastprivate_messages.cpp
index 865dda01a330..25ea4a51dd99 100644
--- a/test/OpenMP/parallel_sections_lastprivate_messages.cpp
+++ b/test/OpenMP/parallel_sections_lastprivate_messages.cpp
@@ -19,7 +19,7 @@ public:
S2(S2 &s2) : a(s2.a) {}
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -32,9 +32,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -153,8 +153,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp parallel sections lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
{
foo();
}
@@ -209,11 +209,11 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel sections lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
{
foo();
}
-#pragma omp parallel sections lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel sections lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
{
foo();
}
@@ -226,7 +226,7 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp parallel sections lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
{
foo();
}
diff --git a/test/OpenMP/parallel_sections_reduction_messages.cpp b/test/OpenMP/parallel_sections_reduction_messages.cpp
index bbd3737de5c1..ae8384adf041 100644
--- a/test/OpenMP/parallel_sections_reduction_messages.cpp
+++ b/test/OpenMP/parallel_sections_reduction_messages.cpp
@@ -144,11 +144,11 @@ T tmain(T argc) {
{
foo();
}
-#pragma omp parallel sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
{
foo();
}
-#pragma omp parallel sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -156,15 +156,15 @@ T tmain(T argc) {
{
foo();
}
-#pragma omp parallel sections reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
-#pragma omp parallel sections reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
-#pragma omp parallel sections reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -176,7 +176,7 @@ T tmain(T argc) {
{
foo();
}
-#pragma omp parallel sections reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -201,7 +201,7 @@ T tmain(T argc) {
{
foo();
}
-#pragma omp parallel sections reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -297,11 +297,11 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp parallel sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
{
foo();
}
-#pragma omp parallel sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -309,15 +309,15 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
-#pragma omp parallel sections reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
-#pragma omp parallel sections reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -329,7 +329,7 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -358,7 +358,7 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp parallel sections reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
diff --git a/test/OpenMP/requires_acq_rel_print.cpp b/test/OpenMP/requires_acq_rel_print.cpp
new file mode 100644
index 000000000000..f4102416f084
--- /dev/null
+++ b/test/OpenMP/requires_acq_rel_print.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+#pragma omp requires atomic_default_mem_order(acq_rel)
+// CHECK:#pragma omp requires atomic_default_mem_order(acq_rel)
+
+#endif
diff --git a/test/OpenMP/requires_ast_print.cpp b/test/OpenMP/requires_ast_print.cpp
new file mode 100644
index 000000000000..e884c71c8663
--- /dev/null
+++ b/test/OpenMP/requires_ast_print.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+#pragma omp requires unified_address
+// CHECK:#pragma omp requires unified_address
+
+#pragma omp requires unified_shared_memory
+// CHECK:#pragma omp requires unified_shared_memory
+
+#pragma omp requires reverse_offload
+// CHECK:#pragma omp requires reverse_offload
+
+#pragma omp requires dynamic_allocators
+// CHECK:#pragma omp requires dynamic_allocators
+
+#pragma omp requires atomic_default_mem_order(seq_cst)
+// CHECK:#pragma omp requires atomic_default_mem_order(seq_cst)
+
+#endif
diff --git a/test/OpenMP/requires_codegen.cpp b/test/OpenMP/requires_codegen.cpp
new file mode 100644
index 000000000000..e94fd28b419e
--- /dev/null
+++ b/test/OpenMP/requires_codegen.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -DREGION_HOST
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_20 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_21 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_30 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_32 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_35 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_37 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_50 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_52 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_53 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_60 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_61 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_62 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_70 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE_NO_ERR
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_72 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE_NO_ERR
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-nvidia-cuda -fopenmp-targets=nvptx64-nvidia-cuda -target-cpu sm_75 -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t-out.ll -DREGION_DEVICE_NO_ERR
+
+#if defined(REGION_HOST) || defined(REGION_DEVICE_NO_ERR)
+// expected-no-diagnostics
+#pragma omp requires unified_shared_memory
+#endif
+
+#ifdef REGION_DEVICE
+#pragma omp requires unified_shared_memory // expected-error {{Target architecture does not support unified addressing}}
+#endif
diff --git a/test/OpenMP/requires_messages.cpp b/test/OpenMP/requires_messages.cpp
new file mode 100644
index 000000000000..7404d3ea5f32
--- /dev/null
+++ b/test/OpenMP/requires_messages.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+#pragma omp requires unified_address // expected-note {{unified_address clause previously used here}} expected-note {{unified_address clause previously used here}} expected-note {{unified_address clause previously used here}} expected-note {{unified_address clause previously used here}} expected-note {{unified_address clause previously used here}} expected-note{{unified_address clause previously used here}}
+
+#pragma omp requires unified_shared_memory // expected-note {{unified_shared_memory clause previously used here}} expected-note{{unified_shared_memory clause previously used here}}
+
+#pragma omp requires unified_shared_memory, unified_shared_memory // expected-error {{Only one unified_shared_memory clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_shared_memory' clause}}
+
+#pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}}
+
+#pragma omp requires unified_address, unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_address' clause}}
+
+#pragma omp requires reverse_offload // expected-note {{reverse_offload clause previously used here}} expected-note {{reverse_offload clause previously used here}}
+
+#pragma omp requires reverse_offload, reverse_offload // expected-error {{Only one reverse_offload clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'reverse_offload' clause}}
+
+#pragma omp requires dynamic_allocators // expected-note {{dynamic_allocators clause previously used here}} expected-note {{dynamic_allocators clause previously used here}}
+
+#pragma omp requires dynamic_allocators, dynamic_allocators // expected-error {{Only one dynamic_allocators clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'dynamic_allocators' clause}}
+
+#pragma omp requires atomic_default_mem_order(seq_cst) // expected-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}}
+
+#pragma omp requires atomic_default_mem_order(acq_rel) // expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
+
+#pragma omp requires atomic_default_mem_order(relaxed) // expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
+
+#pragma omp requires atomic_default_mem_order // expected-error {{expected '(' after 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires atomic_default_mem_order( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires atomic_default_mem_order(seq_cst // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
+
+#pragma omp requires atomic_default_mem_order(invalid_modifier) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires atomic_default_mem_order(shared) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires atomic_default_mem_order(acq_rel), atomic_default_mem_order(relaxed) // expected-error {{directive '#pragma omp requires' cannot contain more than one 'atomic_default_mem_order' claus}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
+
+#pragma omp requires // expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires invalid_clause // expected-warning {{extra tokens at the end of '#pragma omp requires' are ignored}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires nowait // expected-error {{unexpected OpenMP clause 'nowait' in directive '#pragma omp requires'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires unified_address, invalid_clause // expected-warning {{extra tokens at the end of '#pragma omp requires' are ignored}} expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}}
+
+#pragma omp requires invalid_clause unified_address // expected-warning {{extra tokens at the end of '#pragma omp requires' are ignored}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+
+#pragma omp requires unified_shared_memory, unified_address, reverse_offload, dynamic_allocators, atomic_default_mem_order(seq_cst) // expected-error {{Only one unified_shared_memory clause can appear on a requires directive in a single translation unit}} expected-error{{Only one unified_address clause can appear on a requires directive in a single translation unit}} expected-error{{Only one reverse_offload clause can appear on a requires directive in a single translation unit}} expected-error{{Only one dynamic_allocators clause can appear on a requires directive in a single translation unit}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
+
+namespace A {
+ #pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}}
+ namespace B {
+ #pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}}
+ }
+}
+
+template <typename T> T foo() {
+ #pragma omp requires unified_address // expected-error {{unexpected OpenMP directive '#pragma omp requires'}}
+}
+
+class C {
+ #pragma omp requires unified_address // expected-error {{'#pragma omp requires' directive must appear only in file scope}}
+};
+
+int main() {
+ #pragma omp requires unified_address // expected-error {{unexpected OpenMP directive '#pragma omp requires'}}
+}
diff --git a/test/OpenMP/requires_relaxed_print.cpp b/test/OpenMP/requires_relaxed_print.cpp
new file mode 100644
index 000000000000..98786e56605f
--- /dev/null
+++ b/test/OpenMP/requires_relaxed_print.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+#pragma omp requires atomic_default_mem_order(relaxed)
+// CHECK:#pragma omp requires atomic_default_mem_order(relaxed)
+
+#endif
diff --git a/test/OpenMP/schedule_codegen.cpp b/test/OpenMP/schedule_codegen.cpp
index 394eae4a55e6..f1f40cb1fa25 100644
--- a/test/OpenMP/schedule_codegen.cpp
+++ b/test/OpenMP/schedule_codegen.cpp
@@ -5,191 +5,191 @@
int main() {
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for simd
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for schedule(static)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for simd schedule(static)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for schedule(static, 2)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for simd schedule(static, 2)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for schedule(auto)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for simd schedule(auto)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for schedule(runtime)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for simd schedule(runtime)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for schedule(guided)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for simd schedule(guided)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for schedule(dynamic)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for simd schedule(dynamic)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for schedule(monotonic: static)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for simd schedule(monotonic: static)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for schedule(monotonic: static, 2)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_for_static_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_for_static_fini
#pragma omp for simd schedule(monotonic: static, 2)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for schedule(monotonic: auto)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for simd schedule(monotonic: auto)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for schedule(monotonic: runtime)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for simd schedule(monotonic: runtime)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for schedule(monotonic: guided)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for simd schedule(monotonic: guided)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for schedule(monotonic: dynamic)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for simd schedule(monotonic: dynamic)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for schedule(nonmonotonic: guided)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for simd schedule(nonmonotonic: guided)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for schedule(nonmonotonic: dynamic)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
#pragma omp for simd schedule(nonmonotonic: dynamic)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for schedule(static) ordered
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for simd schedule(static) ordered
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for schedule(static, 2) ordered(1)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for simd schedule(static, 2) ordered
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for schedule(auto) ordered(1)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
#pragma omp for simd schedule(auto) ordered
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for schedule(runtime) ordered
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for simd schedule(runtime) ordered
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for schedule(guided) ordered(1)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for simd schedule(guided) ordered
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for schedule(dynamic) ordered(1)
for(int i = 0; i < 10; ++i);
// CHECK: @__kmpc_dispatch_init
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: @__kmpc_dispatch_next
#pragma omp for simd schedule(dynamic)
for(int i = 0; i < 10; ++i);
diff --git a/test/OpenMP/sections_codegen.cpp b/test/OpenMP/sections_codegen.cpp
index ba918c385fc3..68fd38f7d0bb 100644
--- a/test/OpenMP/sections_codegen.cpp
+++ b/test/OpenMP/sections_codegen.cpp
@@ -9,8 +9,8 @@
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
-// CHECK-DAG: [[IMPLICIT_BARRIER_SECTIONS_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
-// CHECK-DAG: [[SECTIONS_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 1026, i32 0, i32 0, i8*
+// CHECK-DAG: [[IMPLICIT_BARRIER_SECTIONS_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
+// CHECK-DAG: [[SECTIONS_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 1026, i32 0, i32 0, i8*
// CHECK-LABEL: foo
void foo() {};
// CHECK-LABEL: bar
diff --git a/test/OpenMP/sections_firstprivate_codegen.cpp b/test/OpenMP/sections_firstprivate_codegen.cpp
index 467c10f242c6..a8d83ec7a0a0 100644
--- a/test/OpenMP/sections_firstprivate_codegen.cpp
+++ b/test/OpenMP/sections_firstprivate_codegen.cpp
@@ -65,7 +65,7 @@ S<float> s_arr[] = {1, 2};
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
S<float> var(3);
// CHECK-DAG: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
-// CHECK-DAG: [[SECTIONS_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
+// CHECK-DAG: [[SECTIONS_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
// CHECK: ([[S_FLOAT_TY]]*)* [[S_FLOAT_TY_DESTR:@[^ ]+]] {{[^,]+}}, {{.+}}([[S_FLOAT_TY]]* [[TEST]]
diff --git a/test/OpenMP/sections_lastprivate_codegen.cpp b/test/OpenMP/sections_lastprivate_codegen.cpp
index bb6a54f00aef..3c8fb2c8f8e1 100644
--- a/test/OpenMP/sections_lastprivate_codegen.cpp
+++ b/test/OpenMP/sections_lastprivate_codegen.cpp
@@ -29,7 +29,7 @@ volatile int g = 1212;
// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK [[CAP_MAIN_TY:%.+]] = type { i{{[0-9]+}}*, [2 x i{{[0-9]+}}]*, [2 x [[S_FLOAT_TY]]]*, [[S_FLOAT_TY]]*, i{{[0-9]+}}* }
// CHECK: [[S_INT_TY:%.+]] = type { i32 }
-// CHECK-DAG: [[SECTIONS_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
+// CHECK-DAG: [[SECTIONS_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
// CHECK-DAG: [[X:@.+]] = global double 0.0
template <typename T>
T tmain() {
diff --git a/test/OpenMP/sections_lastprivate_messages.cpp b/test/OpenMP/sections_lastprivate_messages.cpp
index e24b58fa29bc..1f73260541fe 100644
--- a/test/OpenMP/sections_lastprivate_messages.cpp
+++ b/test/OpenMP/sections_lastprivate_messages.cpp
@@ -19,7 +19,7 @@ public:
S2(S2 &s2) : a(s2.a) {}
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -32,9 +32,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -167,8 +167,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -216,7 +216,7 @@ int main(int argc, char **argv) {
foo();
}
#pragma omp parallel
-#pragma omp sections lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp sections lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
{
foo();
}
@@ -236,12 +236,12 @@ int main(int argc, char **argv) {
foo();
}
#pragma omp parallel
-#pragma omp sections lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp sections lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
{
foo();
}
#pragma omp parallel
-#pragma omp sections lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp sections lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
{
foo();
}
@@ -257,7 +257,7 @@ int main(int argc, char **argv) {
foo();
}
#pragma omp parallel
-#pragma omp sections lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp sections lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
{
foo();
}
diff --git a/test/OpenMP/sections_reduction_codegen.cpp b/test/OpenMP/sections_reduction_codegen.cpp
index 43b08b1160d3..29d72262a49b 100644
--- a/test/OpenMP/sections_reduction_codegen.cpp
+++ b/test/OpenMP/sections_reduction_codegen.cpp
@@ -28,8 +28,8 @@ struct S {
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
-// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
-// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
+// CHECK-DAG: [[ATOMIC_REDUCE_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
+// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
// CHECK-DAG: [[REDUCTION_LOCK:@.+]] = common global [8 x i32] zeroinitializer
template <typename T>
diff --git a/test/OpenMP/sections_reduction_messages.cpp b/test/OpenMP/sections_reduction_messages.cpp
index bf302cf7b335..72a48c9c4309 100644
--- a/test/OpenMP/sections_reduction_messages.cpp
+++ b/test/OpenMP/sections_reduction_messages.cpp
@@ -159,12 +159,12 @@ T tmain(T argc) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
{
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -174,17 +174,17 @@ T tmain(T argc) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -199,7 +199,7 @@ T tmain(T argc) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -229,7 +229,7 @@ T tmain(T argc) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -339,12 +339,12 @@ int main(int argc, char **argv) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp sections reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
{
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -354,17 +354,17 @@ int main(int argc, char **argv) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -379,7 +379,7 @@ int main(int argc, char **argv) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
@@ -414,7 +414,7 @@ int main(int argc, char **argv) {
foo();
}
#pragma omp parallel
-#pragma omp sections reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp sections reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
{
foo();
}
diff --git a/test/OpenMP/simd_codegen.cpp b/test/OpenMP/simd_codegen.cpp
index 883273099ad8..8a636fba231f 100644
--- a/test/OpenMP/simd_codegen.cpp
+++ b/test/OpenMP/simd_codegen.cpp
@@ -21,23 +21,23 @@ void simple(float *a, float *b, float *c, float *d) {
#pragma omp simd
// CHECK: store i32 0, i32* [[OMP_IV:%[^,]+]]
-// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID:[0-9]+]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP:%.+]] = icmp slt i32 [[IV]], 6
// CHECK-NEXT: br i1 [[CMP]], label %[[SIMPLE_LOOP1_BODY:.+]], label %[[SIMPLE_LOOP1_END:[^,]+]]
for (int i = 3; i < 32; i += 5) {
// CHECK: [[SIMPLE_LOOP1_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV1_1:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID]]
+// CHECK: [[IV1_1:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK: [[CALC_I_1:%.+]] = mul nsw i32 [[IV1_1]], 5
// CHECK-NEXT: [[CALC_I_2:%.+]] = add nsw i32 3, [[CALC_I_1]]
-// CHECK-NEXT: store i32 [[CALC_I_2]], i32* [[LC_I:.+]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID]]
+// CHECK-NEXT: store i32 [[CALC_I_2]], i32* [[LC_I:.+]]{{.*}}!llvm.access.group
// ... loop body ...
// End of body: store into a[i]:
-// CHECK: store float [[RESULT:%.+]], float* {{%.+}}{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID]]
+// CHECK: store float [[RESULT:%.+]], float* {{%.+}}{{.*}}!llvm.access.group
a[i] = b[i] * c[i] * d[i];
-// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID]]
+// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD1_2:%.+]] = add nsw i32 [[IV1_2]], 1
-// CHECK-NEXT: store i32 [[ADD1_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID]]
+// CHECK-NEXT: store i32 [[ADD1_2]], i32* [[OMP_IV]]{{.*}}!llvm.access.group
// br label %{{.+}}, !llvm.loop !{{.+}}
}
// CHECK: [[SIMPLE_LOOP1_END]]:
@@ -51,20 +51,20 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[K_VAR]]
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
-// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID:[0-9]+]]
+// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV2]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP2_BODY:.+]], label %[[SIMPLE_LOOP2_END:[^,]+]]
for (int i = 10; i > 1; i--) {
// CHECK: [[SIMPLE_LOOP2_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
// CHECK-NEXT: [[IV2_1:%.+]] = mul nsw i32 [[IV2_0]], 1
// CHECK-NEXT: [[LC_I_1:%.+]] = sub nsw i32 10, [[IV2_1]]
-// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.access.group
//
-// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
-// CHECK-NEXT: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LIN_MUL1:%.+]] = mul nsw i32 [[IV2_2]], 3
// CHECK-NEXT: [[LIN_EXT1:%.+]] = sext i32 [[LIN_MUL1]] to i64
// CHECK-NEXT: [[LIN_ADD1:%.+]] = add nsw i64 [[LIN0_1]], [[LIN_EXT1]]
@@ -72,9 +72,9 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[LIN_ADD1]], i64* [[K_PRIVATIZED:%[^,]+]]
a[k]++;
k = k + 3;
-// CHECK: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK: [[IV2_2:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2_2:%.+]] = add nsw i32 [[IV2_2]], 1
-// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
+// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.access.group
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP2_ID]]
}
// CHECK: [[SIMPLE_LOOP2_END]]:
@@ -101,35 +101,35 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[GLIN_LOAD:%.+]] = load double*, double** [[GLIN_VAR:@[^,]+]]
// CHECK-NEXT: store double* [[GLIN_LOAD]], double** [[GLIN_START:%[^,]+]]
-// CHECK: [[IV3:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID:[0-9]+]]
+// CHECK: [[IV3:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP3:%.+]] = icmp ult i64 [[IV3]], 4
// CHECK-NEXT: br i1 [[CMP3]], label %[[SIMPLE_LOOP3_BODY:.+]], label %[[SIMPLE_LOOP3_END:[^,]+]]
for (unsigned long long it = 2000; it >= 600; it-=400) {
// CHECK: [[SIMPLE_LOOP3_BODY]]:
// Start of body: calculate it from IV:
-// CHECK: [[IV3_0:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
+// CHECK: [[IV3_0:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul i64 [[IV3_0]], 400
// CHECK-NEXT: [[LC_IT_2:%.+]] = sub i64 2000, [[LC_IT_1]]
-// CHECK-NEXT: store i64 [[LC_IT_2]], i64* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
+// CHECK-NEXT: store i64 [[LC_IT_2]], i64* {{.+}}, !llvm.access.group
//
// Linear start and step are used to calculate current value of the linear variable.
-// CHECK: [[LINSTART:.+]] = load i32, i32* [[LIN_START]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
-// CHECK: [[LINSTEP:.+]] = load i64, i64* [[LIN_STEP]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
-// CHECK-NOT: store i32 {{.+}}, i32* [[LIN_VAR]],{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
-// CHECK: [[GLINSTART:.+]] = load double*, double** [[GLIN_START]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
-// CHECK-NEXT: [[IV3_1:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
+// CHECK: [[LINSTART:.+]] = load i32, i32* [[LIN_START]]{{.*}}!llvm.access.group
+// CHECK: [[LINSTEP:.+]] = load i64, i64* [[LIN_STEP]]{{.*}}!llvm.access.group
+// CHECK-NOT: store i32 {{.+}}, i32* [[LIN_VAR]],{{.*}}!llvm.access.group
+// CHECK: [[GLINSTART:.+]] = load double*, double** [[GLIN_START]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[IV3_1:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[MUL:%.+]] = mul i64 [[IV3_1]], 1
// CHECK: [[GEP:%.+]] = getelementptr{{.*}}[[GLINSTART]]
-// CHECK-NEXT: store double* [[GEP]], double** [[G_PTR_CUR:%[^,]+]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
+// CHECK-NEXT: store double* [[GEP]], double** [[G_PTR_CUR:%[^,]+]]{{.*}}!llvm.access.group
*g_ptr++ = 0.0;
-// CHECK: [[GEP_VAL:%.+]] = load double{{.*}}[[G_PTR_CUR]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
-// CHECK: store double{{.*}}[[GEP_VAL]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
+// CHECK: [[GEP_VAL:%.+]] = load double{{.*}}[[G_PTR_CUR]]{{.*}}!llvm.access.group
+// CHECK: store double{{.*}}[[GEP_VAL]]{{.*}}!llvm.access.group
a[it + lin]++;
// CHECK: [[FLT_INC:%.+]] = fadd float
-// CHECK-NEXT: store float [[FLT_INC]],{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
-// CHECK: [[IV3_2:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
+// CHECK-NEXT: store float [[FLT_INC]],{{.*}}!llvm.access.group
+// CHECK: [[IV3_2:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD3_2:%.+]] = add i64 [[IV3_2]], 1
-// CHECK-NEXT: store i64 [[ADD3_2]], i64* [[OMP_IV3]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
+// CHECK-NEXT: store i64 [[ADD3_2]], i64* [[OMP_IV3]]{{.*}}!llvm.access.group
}
// CHECK: [[SIMPLE_LOOP3_END]]:
//
@@ -143,42 +143,42 @@ void simple(float *a, float *b, float *c, float *d) {
#pragma omp simd
// CHECK: store i32 0, i32* [[OMP_IV4:%[^,]+]]
-// CHECK: [[IV4:%.+]] = load i32, i32* [[OMP_IV4]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP4_ID:[0-9]+]]
+// CHECK: [[IV4:%.+]] = load i32, i32* [[OMP_IV4]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP4:%.+]] = icmp slt i32 [[IV4]], 4
// CHECK-NEXT: br i1 [[CMP4]], label %[[SIMPLE_LOOP4_BODY:.+]], label %[[SIMPLE_LOOP4_END:[^,]+]]
for (short it = 6; it <= 20; it-=-4) {
// CHECK: [[SIMPLE_LOOP4_BODY]]:
// Start of body: calculate it from IV:
-// CHECK: [[IV4_0:%.+]] = load i32, i32* [[OMP_IV4]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP4_ID]]
+// CHECK: [[IV4_0:%.+]] = load i32, i32* [[OMP_IV4]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i32 [[IV4_0]], 4
// CHECK-NEXT: [[LC_IT_2:%.+]] = add nsw i32 6, [[LC_IT_1]]
// CHECK-NEXT: [[LC_IT_3:%.+]] = trunc i32 [[LC_IT_2]] to i16
-// CHECK-NEXT: store i16 [[LC_IT_3]], i16* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP4_ID]]
+// CHECK-NEXT: store i16 [[LC_IT_3]], i16* {{.+}}, !llvm.access.group
-// CHECK: [[IV4_2:%.+]] = load i32, i32* [[OMP_IV4]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP4_ID]]
+// CHECK: [[IV4_2:%.+]] = load i32, i32* [[OMP_IV4]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD4_2:%.+]] = add nsw i32 [[IV4_2]], 1
-// CHECK-NEXT: store i32 [[ADD4_2]], i32* [[OMP_IV4]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP4_ID]]
+// CHECK-NEXT: store i32 [[ADD4_2]], i32* [[OMP_IV4]]{{.*}}!llvm.access.group
}
// CHECK: [[SIMPLE_LOOP4_END]]:
#pragma omp simd
// CHECK: store i32 0, i32* [[OMP_IV5:%[^,]+]]
-// CHECK: [[IV5:%.+]] = load i32, i32* [[OMP_IV5]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP5_ID:[0-9]+]]
+// CHECK: [[IV5:%.+]] = load i32, i32* [[OMP_IV5]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP5:%.+]] = icmp slt i32 [[IV5]], 26
// CHECK-NEXT: br i1 [[CMP5]], label %[[SIMPLE_LOOP5_BODY:.+]], label %[[SIMPLE_LOOP5_END:[^,]+]]
for (unsigned char it = 'z'; it >= 'a'; it+=-1) {
// CHECK: [[SIMPLE_LOOP5_BODY]]:
// Start of body: calculate it from IV:
-// CHECK: [[IV5_0:%.+]] = load i32, i32* [[OMP_IV5]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP5_ID]]
+// CHECK: [[IV5_0:%.+]] = load i32, i32* [[OMP_IV5]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[IV5_1:%.+]] = mul nsw i32 [[IV5_0]], 1
// CHECK-NEXT: [[LC_IT_1:%.+]] = sub nsw i32 122, [[IV5_1]]
// CHECK-NEXT: [[LC_IT_2:%.+]] = trunc i32 [[LC_IT_1]] to i8
-// CHECK-NEXT: store i8 [[LC_IT_2]], i8* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP5_ID]]
+// CHECK-NEXT: store i8 [[LC_IT_2]], i8* {{.+}}, !llvm.access.group
-// CHECK: [[IV5_2:%.+]] = load i32, i32* [[OMP_IV5]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP5_ID]]
+// CHECK: [[IV5_2:%.+]] = load i32, i32* [[OMP_IV5]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD5_2:%.+]] = add nsw i32 [[IV5_2]], 1
-// CHECK-NEXT: store i32 [[ADD5_2]], i32* [[OMP_IV5]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP5_ID]]
+// CHECK-NEXT: store i32 [[ADD5_2]], i32* [[OMP_IV5]]{{.*}}!llvm.access.group
}
// CHECK: [[SIMPLE_LOOP5_END]]:
@@ -194,23 +194,23 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: store i64 0, i64* [[OMP_IV7:%[^,]+]]
// CHECK: br label %[[SIMD_LOOP7_COND:[^,]+]]
// CHECK: [[SIMD_LOOP7_COND]]:
-// CHECK-NEXT: [[IV7:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID:[0-9]+]]
+// CHECK-NEXT: [[IV7:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP7:%.+]] = icmp slt i64 [[IV7]], 7
// CHECK-NEXT: br i1 [[CMP7]], label %[[SIMPLE_LOOP7_BODY:.+]], label %[[SIMPLE_LOOP7_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
// CHECK: [[SIMPLE_LOOP7_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV7_0:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
+// CHECK: [[IV7_0:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV7_0]], 3
// CHECK-NEXT: [[LC_IT_2:%.+]] = add nsw i64 -10, [[LC_IT_1]]
-// CHECK-NEXT: store i64 [[LC_IT_2]], i64* [[LC:%[^,]+]],{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
-// CHECK-NEXT: [[LC_VAL:%.+]] = load i64, i64* [[LC]]{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
+// CHECK-NEXT: store i64 [[LC_IT_2]], i64* [[LC:%[^,]+]],{{.+}}!llvm.access.group
+// CHECK-NEXT: [[LC_VAL:%.+]] = load i64, i64* [[LC]]{{.+}}!llvm.access.group
// CHECK-NEXT: [[CONV:%.+]] = trunc i64 [[LC_VAL]] to i32
-// CHECK-NEXT: store i32 [[CONV]], i32* [[A_PRIV:%[^,]+]],{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
+// CHECK-NEXT: store i32 [[CONV]], i32* [[A_PRIV:%[^,]+]],{{.+}}!llvm.access.group
A = i;
-// CHECK: [[IV7_2:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
+// CHECK: [[IV7_2:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD7_2:%.+]] = add nsw i64 [[IV7_2]], 1
-// CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
+// CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]{{.*}}!llvm.access.group
}
// CHECK: [[SIMPLE_LOOP7_END]]:
// CHECK-NEXT: store i64 11, i64*
@@ -224,22 +224,22 @@ void simple(float *a, float *b, float *c, float *d) {
#pragma omp simd reduction(*:R)
// CHECK: br label %[[SIMD_LOOP8_COND:[^,]+]]
// CHECK: [[SIMD_LOOP8_COND]]:
-// CHECK-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID:[0-9]+]]
+// CHECK-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP8:%.+]] = icmp slt i64 [[IV8]], 7
// CHECK-NEXT: br i1 [[CMP8]], label %[[SIMPLE_LOOP8_BODY:.+]], label %[[SIMPLE_LOOP8_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
// CHECK: [[SIMPLE_LOOP8_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV8_0:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
+// CHECK: [[IV8_0:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV8_0]], 3
// CHECK-NEXT: [[LC_IT_2:%.+]] = add nsw i64 -10, [[LC_IT_1]]
-// CHECK-NEXT: store i64 [[LC_IT_2]], i64* [[LC:%[^,]+]],{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
-// CHECK-NEXT: [[LC_VAL:%.+]] = load i64, i64* [[LC]]{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
-// CHECK: store i32 %{{.+}}, i32* [[R_PRIV]],{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
+// CHECK-NEXT: store i64 [[LC_IT_2]], i64* [[LC:%[^,]+]],{{.+}}!llvm.access.group
+// CHECK-NEXT: [[LC_VAL:%.+]] = load i64, i64* [[LC]]{{.+}}!llvm.access.group
+// CHECK: store i32 %{{.+}}, i32* [[R_PRIV]],{{.+}}!llvm.access.group
R *= i;
-// CHECK: [[IV8_2:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
+// CHECK: [[IV8_2:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD8_2:%.+]] = add nsw i64 [[IV8_2]], 1
-// CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
+// CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]{{.*}}!llvm.access.group
}
// CHECK: [[SIMPLE_LOOP8_END]]:
// CHECK-DAG: [[R_VAL:%.+]] = load i32, i32* [[R]],
@@ -266,26 +266,29 @@ int templ1(T a, T *z) {
// CHECK-LABEL: define {{.*i32}} @{{.*}}templ1{{.*}}(float {{.+}}, float* {{.+}})
// CHECK: store i64 0, i64* [[T1_OMP_IV:[^,]+]]
// ...
-// CHECK: [[IV:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID:[0-9]+]]
+// CHECK: [[IV:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP1:%.+]] = icmp slt i64 [[IV]], 16
// CHECK-NEXT: br i1 [[CMP1]], label %[[T1_BODY:.+]], label %[[T1_END:[^,]+]]
// CHECK: [[T1_BODY]]:
// Loop counters i and j updates:
-// CHECK: [[IV1:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
+// CHECK: [[IV1:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[I_1:%.+]] = sdiv i64 [[IV1]], 4
// CHECK-NEXT: [[I_1_MUL1:%.+]] = mul nsw i64 [[I_1]], 1
// CHECK-NEXT: [[I_1_ADD0:%.+]] = add nsw i64 0, [[I_1_MUL1]]
// CHECK-NEXT: [[I_2:%.+]] = trunc i64 [[I_1_ADD0]] to i32
-// CHECK-NEXT: store i32 [[I_2]], i32* {{%.+}}{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
-// CHECK: [[IV2:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
-// CHECK-NEXT: [[J_1:%.+]] = srem i64 [[IV2]], 4
-// CHECK-NEXT: [[J_2:%.+]] = mul nsw i64 [[J_1]], 2
+// CHECK-NEXT: store i32 [[I_2]], i32* {{%.+}}{{.*}}!llvm.access.group
+// CHECK: [[IV2:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.access.group
+// CHECK: [[IV2_1:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[J_1_DIV1:%.+]] = sdiv i64 [[IV2_1]], 4
+// CHECK-NEXT: [[J_1_MUL1:%.+]] = mul nsw i64 [[J_1_DIV1]], 4
+// CHECK-NEXT: [[J_1_SUB0:%.+]] = sub nsw i64 [[IV2]], [[J_1_MUL1]]
+// CHECK-NEXT: [[J_2:%.+]] = mul nsw i64 [[J_1_SUB0]], 2
// CHECK-NEXT: [[J_2_ADD0:%.+]] = add nsw i64 0, [[J_2]]
-// CHECK-NEXT: store i64 [[J_2_ADD0]], i64* {{%.+}}{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
+// CHECK-NEXT: store i64 [[J_2_ADD0]], i64* {{%.+}}{{.*}}!llvm.access.group
// simd.for.inc:
-// CHECK: [[IV3:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
+// CHECK: [[IV3:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[INC:%.+]] = add nsw i64 [[IV3]], 1
-// CHECK-NEXT: store i64 [[INC]], i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
+// CHECK-NEXT: store i64 [[INC]], i64* [[T1_OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: br label {{%.+}}
// CHECK: [[T1_END]]:
// CHECK: ret i32 0
@@ -338,15 +341,15 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK: store i32 0, i32* [[IT_OMP_IV:%[^,]+]]
#pragma omp simd
-// CHECK: [[IV:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}} !llvm.mem.parallel_loop_access ![[ITER_LOOP_ID:[0-9]+]]
-// CHECK-NEXT: [[LAST_IT:%.+]] = load i32, i32* [[OMP_LAST_IT]]{{.+}}!llvm.mem.parallel_loop_access ![[ITER_LOOP_ID]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}} !llvm.access.group
+// CHECK-NEXT: [[LAST_IT:%.+]] = load i32, i32* [[OMP_LAST_IT]]{{.+}}!llvm.access.group
// CHECK-NEXT: [[NUM_IT:%.+]] = add nsw i32 [[LAST_IT]], 1
// CHECK-NEXT: [[CMP:%.+]] = icmp slt i32 [[IV]], [[NUM_IT]]
// CHECK-NEXT: br i1 [[CMP]], label %[[IT_BODY:[^,]+]], label %[[IT_END:[^,]+]]
for (IterDouble i = ia; i < ib; ++i) {
// CHECK: [[IT_BODY]]:
// Start of body: calculate i from index:
-// CHECK: [[IV1:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[ITER_LOOP_ID]]
+// CHECK: [[IV1:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}}!llvm.access.group
// Call of operator+ (i, IV).
// CHECK: {{%.+}} = invoke {{.+}} @{{.*}}IterDouble{{.*}}
// ... loop body ...
@@ -354,12 +357,12 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// Float multiply and save result.
// CHECK: [[MULR:%.+]] = fmul double {{%.+}}, 5.000000e-01
// CHECK-NEXT: invoke {{.+}} @{{.*}}IterDouble{{.*}}
-// CHECK: store double [[MULR:%.+]], double* [[RESULT_ADDR:%.+]], !llvm.mem.parallel_loop_access ![[ITER_LOOP_ID]]
+// CHECK: store double [[MULR:%.+]], double* [[RESULT_ADDR:%.+]], !llvm.access.group
++ic;
//
-// CHECK: [[IV2:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[ITER_LOOP_ID]]
+// CHECK: [[IV2:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}}!llvm.access.group
// CHECK-NEXT: [[ADD2:%.+]] = add nsw i32 [[IV2]], 1
-// CHECK-NEXT: store i32 [[ADD2]], i32* [[IT_OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[ITER_LOOP_ID]]
+// CHECK-NEXT: store i32 [[ADD2]], i32* [[IT_OMP_IV]]{{.+}}!llvm.access.group
// br label %{{.*}}, !llvm.loop ![[ITER_LOOP_ID]]
}
// CHECK: [[IT_END]]:
@@ -377,7 +380,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
//
#pragma omp simd collapse(4)
-// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID:[0-9]+]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
// CHECK-NEXT: [[CMP:%.+]] = icmp ult i32 [[IV]], 120
// CHECK-NEXT: br i1 [[CMP]], label %[[COLL1_BODY:[^,]+]], label %[[COLL1_END:[^,]+]]
for (i = 1; i < 3; i++) // 2 iterations
@@ -387,38 +390,86 @@ void collapsed(float *a, float *b, float *c, float *d) {
{
// CHECK: [[COLL1_BODY]]:
// Start of body: calculate i from index:
-// CHECK: [[IV1:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
+// CHECK: [[IV1:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
// Calculation of the loop counters values.
// CHECK: [[CALC_I_1:%.+]] = udiv i32 [[IV1]], 60
// CHECK-NEXT: [[CALC_I_1_MUL1:%.+]] = mul i32 [[CALC_I_1]], 1
// CHECK-NEXT: [[CALC_I_2:%.+]] = add i32 1, [[CALC_I_1_MUL1]]
// CHECK-NEXT: store i32 [[CALC_I_2]], i32* [[LC_I:.+]]
-// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
-// CHECK-NEXT: [[CALC_J_1:%.+]] = udiv i32 [[IV1_2]], 20
-// CHECK-NEXT: [[CALC_J_2:%.+]] = urem i32 [[CALC_J_1]], 3
+
+// CHECK: [[IV1_2:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
+// CHECK: [[IV1_2_1:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
+// CHECK-NEXT: [[CALC_J_1:%.+]] = udiv i32 [[IV1_2_1]], 60
+// CHECK-NEXT: [[MUL_1:%.+]] = mul i32 [[CALC_J_1]], 60
+// CHECK-NEXT: [[SUB_3:%.+]] = sub i32 [[IV1_2]], [[MUL_1]]
+// CHECK-NEXT: [[CALC_J_2:%.+]] = udiv i32 [[SUB_3]], 20
// CHECK-NEXT: [[CALC_J_2_MUL1:%.+]] = mul i32 [[CALC_J_2]], 1
// CHECK-NEXT: [[CALC_J_3:%.+]] = add i32 2, [[CALC_J_2_MUL1]]
// CHECK-NEXT: store i32 [[CALC_J_3]], i32* [[LC_J:.+]]
-// CHECK: [[IV1_3:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
-// CHECK-NEXT: [[CALC_K_1:%.+]] = udiv i32 [[IV1_3]], 5
-// CHECK-NEXT: [[CALC_K_2:%.+]] = urem i32 [[CALC_K_1]], 4
-// CHECK-NEXT: [[CALC_K_2_MUL1:%.+]] = mul i32 [[CALC_K_2]], 1
-// CHECK-NEXT: [[CALC_K_3:%.+]] = add i32 3, [[CALC_K_2_MUL1]]
-// CHECK-NEXT: store i32 [[CALC_K_3]], i32* [[LC_K:.+]]
-// CHECK: [[IV1_4:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
-// CHECK-NEXT: [[CALC_L_1:%.+]] = urem i32 [[IV1_4]], 5
-// CHECK-NEXT: [[CALC_L_1_MUL1:%.+]] = mul i32 [[CALC_L_1]], 1
-// CHECK-NEXT: [[CALC_L_2:%.+]] = add i32 4, [[CALC_L_1_MUL1]]
+
+// CHECK: [[IV1_3:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
+// CHECK: [[IV1_3_1:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
+// CHECK-NEXT: [[DIV_1:%.+]] = udiv i32 [[IV1_3_1]], 60
+// CHECK-NEXT: [[MUL_2:%.+]] = mul i32 [[DIV_1]], 60
+// CHECK-NEXT: [[ADD_3:%.+]] = sub i32 [[IV1_3]], [[MUL_2]]
+
+// CHECK: [[IV1_4:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_4_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_2:%.+]] = udiv i32 [[IV1_4_1]], 60
+// CHECK-NEXT: [[MUL_3:%.+]] = mul i32 [[DIV_2]], 60
+// CHECK-NEXT: [[SUB_6:%.+]] = sub i32 [[IV1_4]], [[MUL_3]]
+// CHECK-NEXT: [[DIV_3:%.+]] = udiv i32 [[SUB_6]], 20
+// CHECK-NEXT: [[MUL_4:%.+]] = mul i32 [[DIV_3]], 20
+// CHECK-NEXT: [[ADD_5:%.+]] = sub i32 [[ADD_3]], [[MUL_4]]
+// CHECK-NEXT: [[DIV_4:%.+]] = udiv i32 [[ADD_5]], 5
+// CHECK-NEXT: [[MUL_5:%.+]] = mul i32 [[DIV_4]], 1
+// CHECK-NEXT: [[ADD_6:%.+]] = add i32 3, [[MUL_5]]
+// CHECK-NEXT: store i32 [[ADD_6]], i32* [[LC_K:.+]]
+
+// CHECK: [[IV1_5:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
+// CHECK: [[IV1_5_1:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.access.group
+// CHECK-NEXT: [[DIV_5:%.+]] = udiv i32 [[IV1_5_1]], 60
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[DIV_5]], 60
+// CHECK-NEXT: [[SUB_7:%.+]] = sub i32 [[IV1_5]], [[MUL_6]]
+
+// CHECK: [[IV1_6:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_6_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_6:%.+]] = udiv i32 [[IV1_6_1]], 60
+// CHECK-NEXT: [[MUL_7:%.+]] = mul i32 [[DIV_6]], 60
+// CHECK-NEXT: [[SUB_10:%.+]] = sub i32 [[IV1_6]], [[MUL_7]]
+// CHECK-NEXT: [[DIV_7:%.+]] = udiv i32 [[SUB_10]], 20
+// CHECK-NEXT: [[MUL_8:%.+]] = mul i32 [[DIV_7]], 20
+// CHECK-NEXT: [[SUB_11:%.+]] = sub i32 [[SUB_7]], [[MUL_8]]
+
+// CHECK: [[IV1_7:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_7_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_8:%.+]] = udiv i32 [[IV1_7_1]], 60
+// CHECK-NEXT: [[MUL_9:%.+]] = mul i32 [[DIV_8]], 60
+// CHECK-NEXT: [[SUB_12:%.+]] = sub i32 [[IV1_7]], [[MUL_9]]
+
+// CHECK: [[IV1_8:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK: [[IV1_8_1:%.+]] = load i32, i32* [[OMP_IV]]
+// CHECK-NEXT: [[DIV_3:%.+]] = udiv i32 [[IV1_8_1]], 60
+// CHECK-NEXT: [[MUL_4:%.+]] = mul i32 [[DIV_3]], 60
+// CHECK-NEXT: [[SUB_7:%.+]] = sub i32 [[IV1_8]], [[MUL_4]]
+// CHECK-NEXT: [[DIV_4:%.+]] = udiv i32 [[SUB_7]], 20
+// CHECK-NEXT: [[MUL_5:%.+]] = mul i32 [[DIV_4]], 20
+// CHECK-NEXT: [[SUB_8:%.+]] = sub i32 [[SUB_12]], [[MUL_5]]
+// CHECK-NEXT: [[DIV_5:%.+]] = udiv i32 [[SUB_8]], 5
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[DIV_5]], 5
+// CHECK-NEXT: [[SUB_9:%.+]] = sub i32 [[SUB_11]], [[MUL_6]]
+// CHECK-NEXT: [[MUL_6:%.+]] = mul i32 [[SUB_9]], 1
+// CHECK-NEXT: [[CALC_L_2:%.+]] = add i32 4, [[MUL_6]]
// CHECK-NEXT: [[CALC_L_3:%.+]] = trunc i32 [[CALC_L_2]] to i16
// CHECK-NEXT: store i16 [[CALC_L_3]], i16* [[LC_L:.+]]
// ... loop body ...
// End of body: store into a[i]:
-// CHECK: store float [[RESULT:%.+]], float* [[RESULT_ADDR:%.+]]{{.+}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
+// CHECK: store float [[RESULT:%.+]], float* [[RESULT_ADDR:%.+]]{{.+}}!llvm.access.group
float res = b[j] * c[k];
a[i] = res * d[l];
-// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
+// CHECK: [[IV2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2:%.+]] = add i32 [[IV2]], 1
-// CHECK-NEXT: store i32 [[ADD2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
+// CHECK-NEXT: store i32 [[ADD2]], i32* [[OMP_IV]]{{.*}}!llvm.access.group
// br label %{{[^,]+}}, !llvm.loop ![[COLL1_LOOP_ID]]
// CHECK: [[COLL1_END]]:
}
@@ -445,8 +496,8 @@ void widened(float *a, float *b, float *c, float *d) {
//
#pragma omp simd collapse(2) private(globalfloat, localint)
-// CHECK: [[IV:%.+]] = load i64, i64* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID:[0-9]+]]
-// CHECK-NEXT: [[LI:%.+]] = load i64, i64* [[OMP_LI:%[^,]+]]{{.+}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
+// CHECK: [[IV:%.+]] = load i64, i64* [[OMP_IV]]{{.+}}!llvm.access.group
+// CHECK-NEXT: [[LI:%.+]] = load i64, i64* [[OMP_LI:%[^,]+]]{{.+}}!llvm.access.group
// CHECK-NEXT: [[NUMIT:%.+]] = add nsw i64 [[LI]], 1
// CHECK-NEXT: [[CMP:%.+]] = icmp slt i64 [[IV]], [[NUMIT]]
// CHECK-NEXT: br i1 [[CMP]], label %[[WIDE1_BODY:[^,]+]], label %[[WIDE1_END:[^,]+]]
@@ -455,10 +506,10 @@ void widened(float *a, float *b, float *c, float *d) {
{
// CHECK: [[WIDE1_BODY]]:
// Start of body: calculate i from index:
-// CHECK: [[IV1:%.+]] = load i64, i64* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
+// CHECK: [[IV1:%.+]] = load i64, i64* [[OMP_IV]]{{.+}}!llvm.access.group
// Calculation of the loop counters values...
// CHECK: store i32 {{[^,]+}}, i32* [[LC_I:.+]]
-// CHECK: [[IV1_2:%.+]] = load i64, i64* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
+// CHECK: [[IV1_2:%.+]] = load i64, i64* [[OMP_IV]]{{.+}}!llvm.access.group
// CHECK: store i16 {{[^,]+}}, i16* [[LC_J:.+]]
// ... loop body ...
//
@@ -467,14 +518,14 @@ void widened(float *a, float *b, float *c, float *d) {
globalfloat = (float)j/i;
float res = b[j] * c[j];
// Store into a[i]:
-// CHECK: store float [[RESULT:%.+]], float* [[RESULT_ADDR:%.+]]{{.+}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
+// CHECK: store float [[RESULT:%.+]], float* [[RESULT_ADDR:%.+]]{{.+}}!llvm.access.group
a[i] = res * d[i];
// Then there's a store into private var localint:
-// CHECK: store i32 {{.+}}, i32* [[LOCALINT:%[^,]+]]{{.+}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
+// CHECK: store i32 {{.+}}, i32* [[LOCALINT:%[^,]+]]{{.+}}!llvm.access.group
localint = (int)j;
-// CHECK: [[IV2:%.+]] = load i64, i64* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
+// CHECK: [[IV2:%.+]] = load i64, i64* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2:%.+]] = add nsw i64 [[IV2]], 1
-// CHECK-NEXT: store i64 [[ADD2]], i64* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
+// CHECK-NEXT: store i64 [[ADD2]], i64* [[OMP_IV]]{{.*}}!llvm.access.group
//
// br label %{{[^,]+}}, !llvm.loop ![[WIDE1_LOOP_ID]]
// CHECK: [[WIDE1_END]]:
@@ -505,20 +556,20 @@ void linear(float *a) {
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[K_REF]]
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
-// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID:[0-9]+]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP_BODY:.+]], label %[[SIMPLE_LOOP_END:[^,]+]]
for (int i = 10; i > 1; i--) {
// CHECK: [[SIMPLE_LOOP_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
// CHECK-NEXT: [[IV_1:%.+]] = mul nsw i32 [[IV_0]], 1
// CHECK-NEXT: [[LC_I_1:%.+]] = sub nsw i32 10, [[IV_1]]
-// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.access.group
//
-// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
-// CHECK-NEXT: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LIN_MUL1:%.+]] = mul nsw i32 [[IV_2]], 3
// CHECK-NEXT: [[LIN_EXT1:%.+]] = sext i32 [[LIN_MUL1]] to i64
// CHECK-NEXT: [[LIN_ADD1:%.+]] = add nsw i64 [[LIN0_1]], [[LIN_EXT1]]
@@ -526,9 +577,9 @@ void linear(float *a) {
// CHECK-NEXT: store i64 [[LIN_ADD1]], i64* [[K_PRIVATIZED:%[^,]+]]
a[k]++;
k = k + 3;
-// CHECK: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2_2:%.+]] = add nsw i32 [[IV_2]], 1
-// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.access.group
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP_ID]]
}
// CHECK: [[SIMPLE_LOOP_END]]:
@@ -550,20 +601,20 @@ void linear(float *a) {
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[K_REF]]
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
-// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID:[0-9]+]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP_BODY:.+]], label %[[SIMPLE_LOOP_END:[^,]+]]
for (int i = 10; i > 1; i--) {
// CHECK: [[SIMPLE_LOOP_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
// CHECK-NEXT: [[IV_1:%.+]] = mul nsw i32 [[IV_0]], 1
// CHECK-NEXT: [[LC_I_1:%.+]] = sub nsw i32 10, [[IV_1]]
-// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.access.group
//
-// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
-// CHECK-NEXT: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LIN_MUL1:%.+]] = mul nsw i32 [[IV_2]], 3
// CHECK-NEXT: [[LIN_EXT1:%.+]] = sext i32 [[LIN_MUL1]] to i64
// CHECK-NEXT: [[LIN_ADD1:%.+]] = add nsw i64 [[LIN0_1]], [[LIN_EXT1]]
@@ -571,9 +622,9 @@ void linear(float *a) {
// CHECK-NEXT: store i64 [[LIN_ADD1]], i64* [[K_PRIVATIZED:%[^,]+]]
a[k]++;
k = k + 3;
-// CHECK: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2_2:%.+]] = add nsw i32 [[IV_2]], 1
-// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.access.group
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP_ID]]
}
// CHECK: [[SIMPLE_LOOP_END]]:
@@ -591,20 +642,20 @@ void linear(float *a) {
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[VAL_ADDR]]
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
-// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID:[0-9]+]]
+// CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP_BODY:.+]], label %[[SIMPLE_LOOP_END:[^,]+]]
for (int i = 10; i > 1; i--) {
// CHECK: [[SIMPLE_LOOP_BODY]]:
// Start of body: calculate i from IV:
-// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
// CHECK-NEXT: [[IV_1:%.+]] = mul nsw i32 [[IV_0]], 1
// CHECK-NEXT: [[LC_I_1:%.+]] = sub nsw i32 10, [[IV_1]]
-// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: store i32 [[LC_I_1]], i32* {{.+}}, !llvm.access.group
//
-// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
-// CHECK-NEXT: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: [[LIN0_1:%.+]] = load i64, i64* [[LIN0]]{{.*}}!llvm.access.group
+// CHECK-NEXT: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[LIN_MUL1:%.+]] = mul nsw i32 [[IV_2]], 3
// CHECK-NEXT: [[LIN_EXT1:%.+]] = sext i32 [[LIN_MUL1]] to i64
// CHECK-NEXT: [[LIN_ADD1:%.+]] = add nsw i64 [[LIN0_1]], [[LIN_EXT1]]
@@ -612,9 +663,9 @@ void linear(float *a) {
// CHECK-NEXT: store i64 [[LIN_ADD1]], i64* [[K_PRIVATIZED:%[^,]+]]
a[k]++;
k = k + 3;
-// CHECK: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK: [[IV_2:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group
// CHECK-NEXT: [[ADD2_2:%.+]] = add nsw i32 [[IV_2]], 1
-// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
+// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.access.group
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP_ID]]
}
// CHECK: [[SIMPLE_LOOP_END]]:
@@ -635,7 +686,7 @@ void parallel_simd(float *a) {
#pragma omp simd
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: invoke i32 {{.*}}bar{{.*}}()
- // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]],
+ // TERM_DEBUG: unwind label %[[TERM_LPAD:[^,]+]],
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: [[TERM_LPAD]]
// TERM_DEBUG: call void @__clang_call_terminate
diff --git a/test/OpenMP/simd_lastprivate_messages.cpp b/test/OpenMP/simd_lastprivate_messages.cpp
index 0af812889cf1..bd5a237a6027 100644
--- a/test/OpenMP/simd_lastprivate_messages.cpp
+++ b/test/OpenMP/simd_lastprivate_messages.cpp
@@ -19,7 +19,7 @@ public:
S2(S2 &s2) : a(s2.a) {}
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -32,9 +32,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -130,8 +130,8 @@ int foomain(I argc, C **argv) {
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -161,7 +161,7 @@ int main(int argc, char **argv) {
#pragma omp simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp simd lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -173,10 +173,10 @@ int main(int argc, char **argv) {
#pragma omp simd lastprivate(ba)
for (i = 0; i < argc; ++i)
foo();
-#pragma omp simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -186,7 +186,7 @@ int main(int argc, char **argv) {
#pragma omp simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp simd firstprivate(g) // expected-error {{unexpected OpenMP clause 'firstprivate' in directive '#pragma omp simd'}}
diff --git a/test/OpenMP/simd_linear_messages.cpp b/test/OpenMP/simd_linear_messages.cpp
index aad0d18d4281..3a72ed26fc5c 100644
--- a/test/OpenMP/simd_linear_messages.cpp
+++ b/test/OpenMP/simd_linear_messages.cpp
@@ -132,7 +132,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp simd linear (val(a, b):B::ib)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp simd linear (argv[1]) // expected-error {{expected variable name}}
@@ -221,7 +221,7 @@ int main(int argc, char **argv) {
#pragma omp simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp simd linear(a, b)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp simd linear (argv[1]) // expected-error {{expected variable name}}
diff --git a/test/OpenMP/simd_loop_messages.cpp b/test/OpenMP/simd_loop_messages.cpp
index b9d146c2150a..80f3cb14b76e 100644
--- a/test/OpenMP/simd_loop_messages.cpp
+++ b/test/OpenMP/simd_loop_messages.cpp
@@ -99,7 +99,7 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
- // expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ // Ok
#pragma omp simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/simd_metadata.c b/test/OpenMP/simd_metadata.c
index 8fdc306930c5..44a7e901a0af 100644
--- a/test/OpenMP/simd_metadata.c
+++ b/test/OpenMP/simd_metadata.c
@@ -49,8 +49,8 @@ void h1(float *c, float *a, double b[], int size)
c[i] = a[i] * a[i] + b[i] * b[t];
++t;
}
-// do not emit parallel_loop_access metadata due to usage of safelen clause.
-// CHECK-NOT: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.mem.parallel_loop_access {{![0-9]+}}
+// do not emit llvm.access.group metadata due to usage of safelen clause.
+// CHECK-NOT: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group {{![0-9]+}}
#pragma omp simd safelen(16) linear(t) aligned(c:32) aligned(a,b) simdlen(8)
// CHECK: [[C_PTRINT:%.+]] = ptrtoint
// CHECK-NEXT: [[C_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[C_PTRINT]], 31
@@ -80,8 +80,8 @@ void h1(float *c, float *a, double b[], int size)
c[i] = a[i] * a[i] + b[i] * b[t];
++t;
}
-// do not emit parallel_loop_access metadata due to usage of safelen clause.
-// CHECK-NOT: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.mem.parallel_loop_access {{![0-9]+}}
+// do not emit llvm.access.group metadata due to usage of safelen clause.
+// CHECK-NOT: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group {{![0-9]+}}
#pragma omp simd linear(t) aligned(c:32) aligned(a,b) simdlen(8)
// CHECK: [[C_PTRINT:%.+]] = ptrtoint
// CHECK-NEXT: [[C_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[C_PTRINT]], 31
@@ -110,7 +110,7 @@ void h1(float *c, float *a, double b[], int size)
for (int i = 0; i < size; ++i) {
c[i] = a[i] * a[i] + b[i] * b[t];
++t;
-// CHECK: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.mem.parallel_loop_access {{![0-9]+}}
+// CHECK: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group ![[ACCESS_GROUP_7:[0-9]+]]
}
}
@@ -122,8 +122,9 @@ void h2(float *c, float *a, float *b, int size)
for (int i = 0; i < size; ++i) {
c[i] = a[i] * a[i] + b[i] * b[t];
++t;
-// CHECK: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.mem.parallel_loop_access [[LOOP_H2_HEADER:![0-9]+]]
+// CHECK: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group ![[ACCESS_GROUP_10:[0-9]+]]
}
+// CHECK: br label %{{.+}}, !llvm.loop [[LOOP_H2_HEADER:![0-9]+]]
}
void h3(float *c, float *a, float *b, int size)
@@ -134,9 +135,9 @@ void h3(float *c, float *a, float *b, int size)
for (int j = 0; j < size; ++j) {
c[j*i] = a[i] * b[j];
}
+// CHECK: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group ![[ACCESS_GROUP_13:[0-9]+]]
}
-// do not emit parallel_loop_access for nested loop.
-// CHECK-NOT: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.mem.parallel_loop_access {{![0-9]+}}
+// CHECK: br label %{{.+}}, !llvm.loop [[LOOP_H3_HEADER:![0-9]+]]
}
// Metadata for h1:
@@ -145,11 +146,17 @@ void h3(float *c, float *a, float *b, int size)
// CHECK: [[LOOP_VEC_ENABLE]] = !{!"llvm.loop.vectorize.enable", i1 true}
// CHECK: [[LOOP_H1_HEADER:![0-9]+]] = distinct !{[[LOOP_H1_HEADER]], [[LOOP_WIDTH_8:![0-9]+]], [[LOOP_VEC_ENABLE]]}
// CHECK: [[LOOP_WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8}
-// CHECK: [[LOOP_H1_HEADER:![0-9]+]] = distinct !{[[LOOP_H1_HEADER]], [[LOOP_WIDTH_8]], [[LOOP_VEC_ENABLE]]}
+// CHECK: ![[ACCESS_GROUP_7]] = distinct !{}
+// CHECK: [[LOOP_H1_HEADER:![0-9]+]] = distinct !{[[LOOP_H1_HEADER]], [[LOOP_WIDTH_8]], [[LOOP_VEC_ENABLE]], ![[PARALLEL_ACCESSES_9:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_9]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_7]]}
//
// Metadata for h2:
-// CHECK: [[LOOP_H2_HEADER]] = distinct !{[[LOOP_H2_HEADER]], [[LOOP_VEC_ENABLE]]}
+// CHECK: ![[ACCESS_GROUP_10]] = distinct !{}
+// CHECK: [[LOOP_H2_HEADER]] = distinct !{[[LOOP_H2_HEADER]], [[LOOP_VEC_ENABLE]], ![[PARALLEL_ACCESSES_12:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_12]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_10]]}
//
// Metadata for h3:
-// CHECK: [[LOOP_H3_HEADER:![0-9]+]] = distinct !{[[LOOP_H3_HEADER]], [[LOOP_VEC_ENABLE]]}
+// CHECK: ![[ACCESS_GROUP_13]] = distinct !{}
+// CHECK: [[LOOP_H3_HEADER]] = distinct !{[[LOOP_H3_HEADER]], [[LOOP_VEC_ENABLE]], ![[PARALLEL_ACCESSES_15:[0-9]+]]}
+// CHECK: ![[PARALLEL_ACCESSES_15]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_13]]}
//
diff --git a/test/OpenMP/simd_reduction_messages.cpp b/test/OpenMP/simd_reduction_messages.cpp
index 135a3ca71f6e..1602aeb40fa5 100644
--- a/test/OpenMP/simd_reduction_messages.cpp
+++ b/test/OpenMP/simd_reduction_messages.cpp
@@ -130,22 +130,22 @@ T tmain(T argc) {
#pragma omp simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -154,7 +154,7 @@ T tmain(T argc) {
#pragma omp simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -176,7 +176,7 @@ T tmain(T argc) {
#pragma omp simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -255,22 +255,22 @@ int main(int argc, char **argv) {
#pragma omp simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -279,7 +279,7 @@ int main(int argc, char **argv) {
#pragma omp simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -301,7 +301,7 @@ int main(int argc, char **argv) {
#pragma omp simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/single_codegen.cpp b/test/OpenMP/single_codegen.cpp
index b6ecac72d4f5..df5b2ca0e67a 100644
--- a/test/OpenMP/single_codegen.cpp
+++ b/test/OpenMP/single_codegen.cpp
@@ -28,7 +28,7 @@ public:
// CHECK-DAG: [[SST_TY:%.+]] = type { double }
// CHECK-DAG: [[SS_TY:%.+]] = type { i32, i8, i32* }
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
-// CHECK: [[IMPLICIT_BARRIER_SINGLE_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
+// CHECK: [[IMPLICIT_BARRIER_SINGLE_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
// CHECK: define void [[FOO:@.+]]()
@@ -74,9 +74,12 @@ struct SST {
// CHECK-LABEL: @main
// TERM_DEBUG-LABEL: @main
int main() {
+ // CHECK: alloca i32
// CHECK-DAG: [[A_ADDR:%.+]] = alloca i8
// CHECK-DAG: [[A2_ADDR:%.+]] = alloca [2 x i8]
// CHECK-DAG: [[C_ADDR:%.+]] = alloca [[TEST_CLASS_TY]]
+ // CHECK-DAG: [[DID_IT:%.+]] = alloca i32,
+ // CHECK-DAG: [[COPY_LIST:%.+]] = alloca [5 x i8*],
char a;
char a2[2];
TestClass &c = tc;
@@ -84,9 +87,6 @@ int main() {
SS ss(c.a);
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]])
-// CHECK-DAG: [[DID_IT:%.+]] = alloca i32,
-// CHECK-DAG: [[COPY_LIST:%.+]] = alloca [5 x i8*],
-
// CHECK: [[RES:%.+]] = call i32 @__kmpc_single([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]])
// CHECK-NEXT: [[IS_SINGLE:%.+]] = icmp ne i32 [[RES]], 0
// CHECK-NEXT: br i1 [[IS_SINGLE]], label {{%?}}[[THEN:.+]], label {{%?}}[[EXIT:.+]]
diff --git a/test/OpenMP/single_firstprivate_codegen.cpp b/test/OpenMP/single_firstprivate_codegen.cpp
index 23b543511b0f..3b738253904e 100644
--- a/test/OpenMP/single_firstprivate_codegen.cpp
+++ b/test/OpenMP/single_firstprivate_codegen.cpp
@@ -63,7 +63,7 @@ int vec[] = {1, 2};
S<float> s_arr[] = {1, 2};
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
S<float> var(3);
-// CHECK-DAG: [[SINGLE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
+// CHECK-DAG: [[SINGLE_BARRIER_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
// CHECK: ([[S_FLOAT_TY]]*)* [[S_FLOAT_TY_DESTR:@[^ ]+]] {{[^,]+}}, {{.+}}([[S_FLOAT_TY]]* [[TEST]]
@@ -178,13 +178,13 @@ int main() {
// CHECK: define {{.*}}i{{[0-9]+}} @main()
// CHECK: alloca i{{[0-9]+}},
-// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
// CHECK: [[SIVAR_PRIV:%.+]] = alloca i{{[0-9]+}},
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
// CHECK: call i32 @__kmpc_single(
// firstprivate t_var(t_var)
// CHECK: [[T_VAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR]],
diff --git a/test/OpenMP/target_ast_print.cpp b/test/OpenMP/target_ast_print.cpp
index 827d6a4e3deb..9b866b789a75 100644
--- a/test/OpenMP/target_ast_print.cpp
+++ b/test/OpenMP/target_ast_print.cpp
@@ -14,7 +14,7 @@ void foo() {}
template <typename T, int C>
T tmain(T argc, T *argv) {
- T i, j, a[20], always;
+ T i, j, a[20], always, close;
#pragma omp target
foo();
#pragma omp target if (target:argc > 0)
@@ -35,6 +35,14 @@ T tmain(T argc, T *argv) {
{always++;}
#pragma omp target map(always,i)
{always++;i++;}
+#pragma omp target map(close,alloc: i)
+ foo();
+#pragma omp target map(close from: i)
+ foo();
+#pragma omp target map(close)
+ {close++;}
+#pragma omp target map(close,i)
+ {close++;i++;}
#pragma omp target nowait
foo();
#pragma omp target depend(in : argc, argv[i:argc], a[:])
@@ -71,6 +79,19 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: always++;
// CHECK-NEXT: i++;
// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target map(close,alloc: i)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target map(close,from: i)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target map(tofrom: close)
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target map(tofrom: close,i)
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: i++;
+// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target nowait
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target depend(in : argc,argv[i:argc],a[:])
@@ -104,6 +125,19 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: always++;
// CHECK-NEXT: i++;
// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target map(close,alloc: i)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target map(close,from: i)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target map(tofrom: close)
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target map(tofrom: close,i)
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: i++;
+// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target nowait
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target depend(in : argc,argv[i:argc],a[:])
@@ -137,6 +171,19 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: always++;
// CHECK-NEXT: i++;
// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target map(close,alloc: i)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target map(close,from: i)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target map(tofrom: close)
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target map(tofrom: close,i)
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: i++;
+// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target nowait
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target depend(in : argc,argv[i:argc],a[:])
@@ -144,9 +191,44 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: #pragma omp target defaultmap(tofrom: scalar)
// CHECK-NEXT: foo()
+// CHECK-LABEL: class S {
+class S {
+ void foo() {
+// CHECK-NEXT: void foo() {
+ int a = 0;
+// CHECK-NEXT: int a = 0;
+ #pragma omp target map(this[0])
+// CHECK-NEXT: #pragma omp target map(tofrom: this[0])
+ a++;
+// CHECK-NEXT: a++;
+ #pragma omp target map(this[:1])
+// CHECK-NEXT: #pragma omp target map(tofrom: this[:1])
+ a++;
+// CHECK-NEXT: a++;
+ #pragma omp target map((this)[0])
+// CHECK-NEXT: #pragma omp target map(tofrom: (this)[0])
+ a++;
+// CHECK-NEXT: a++;
+ #pragma omp target map(this[:a])
+// CHECK-NEXT: #pragma omp target map(tofrom: this[:a])
+ a++;
+// CHECK-NEXT: a++;
+ #pragma omp target map(this[a:1])
+// CHECK-NEXT: #pragma omp target map(tofrom: this[a:1])
+ a++;
+// CHECK-NEXT: a++;
+ #pragma omp target map(this[a])
+// CHECK-NEXT: #pragma omp target map(tofrom: this[a])
+ a++;
+// CHECK-NEXT: a++;
+ }
+// CHECK-NEXT: }
+};
+// CHECK-NEXT: };
+
// CHECK-LABEL: int main(int argc, char **argv) {
int main (int argc, char **argv) {
- int i, j, a[20], always;
+ int i, j, a[20], always, close;
// CHECK-NEXT: int i, j, a[20]
#pragma omp target
// CHECK-NEXT: #pragma omp target
@@ -202,6 +284,31 @@ int main (int argc, char **argv) {
// CHECK-NEXT: i++;
// CHECK-NEXT: }
+#pragma omp target map(close,alloc: i)
+// CHECK-NEXT: #pragma omp target map(close,alloc: i)
+ foo();
+// CHECK-NEXT: foo();
+
+#pragma omp target map(close from: i)
+// CHECK-NEXT: #pragma omp target map(close,from: i)
+ foo();
+// CHECK-NEXT: foo();
+
+#pragma omp target map(close)
+// CHECK-NEXT: #pragma omp target map(tofrom: close)
+ {close++;}
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: }
+
+#pragma omp target map(close,i)
+// CHECK-NEXT: #pragma omp target map(tofrom: close,i)
+ {close++;i++;}
+// CHECK-NEXT: {
+// CHECK-NEXT: close++;
+// CHECK-NEXT: i++;
+// CHECK-NEXT: }
+
#pragma omp target nowait
// CHECK-NEXT: #pragma omp target nowait
foo();
diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp
index 6395dd354fa2..a5026cf660b4 100644
--- a/test/OpenMP/target_codegen.cpp
+++ b/test/OpenMP/target_codegen.cpp
@@ -40,6 +40,7 @@
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
+// CHECK-DAG: [[S2:%.+]] = type { i32, i32, i32 }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
// CHECK-DAG: [[DEVTY:%.+]] = type { i8*, i8*, [[ENTTY]]*, [[ENTTY]]* }
// CHECK-DAG: [[DSCTY:%.+]] = type { i32, [[DEVTY]]*, [[ENTTY]]*, [[ENTTY]]* }
@@ -48,8 +49,8 @@
// CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat
-// We have 8 target regions, but only 7 that actually will generate offloading
-// code and have mapped arguments, and only 5 have all-constant map sizes.
+// We have 9 target regions, but only 8 that actually will generate offloading
+// code and have mapped arguments, and only 6 have all-constant map sizes.
// CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4]
// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
@@ -63,6 +64,9 @@
// CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40]
// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547]
// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547]
+// CHECK-DAG: [[SIZET9:@.+]] = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 12]
+// CHECK-DAG: [[MAPT10:@.+]] = private unnamed_addr constant [1 x i64] [i64 35]
+// CHECK-DAG: @{{.*}} = weak constant i8 0
// CHECK-DAG: @{{.*}} = weak constant i8 0
// CHECK-DAG: @{{.*}} = weak constant i8 0
// CHECK-DAG: @{{.*}} = weak constant i8 0
@@ -80,6 +84,7 @@
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
@@ -691,6 +696,31 @@ int bar(int n){
// CHECK: [[IFEND]]
+// CHECK: define {{.*}}@{{.*}}zee{{.*}}
+
+// CHECK: [[LOCAL_THIS:%.+]] = alloca [[S2]]*
+// CHECK: [[BP:%.+]] = alloca [1 x i8*]
+// CHECK: [[P:%.+]] = alloca [1 x i8*]
+// CHECK: [[LOCAL_THIS1:%.+]] = load [[S2]]*, [[S2]]** [[LOCAL_THIS]]
+// CHECK: [[ARR_IDX:%.+]] = getelementptr inbounds [[S2]], [[S2]]* [[LOCAL_THIS1]], i[[SZ]] 0
+// CHECK: [[ARR_IDX2:%.+]] = getelementptr inbounds [[S2]], [[S2]]* [[LOCAL_THIS1]], i[[SZ]] 0
+
+// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BP]], i32 0, i32 0
+// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[P]], i32 0, i32 0
+// CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to [[S2]]**
+// CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to [[S2]]**
+// CHECK-DAG: store [[S2]]* [[ARR_IDX]], [[S2]]** [[CBPADDR0]]
+// CHECK-DAG: store [[S2]]* [[ARR_IDX2]], [[S2]]** [[CPADDR0]]
+
+// CHECK: [[BPR:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BP]], i32 0, i32 0
+// CHECK: [[PR:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[P]], i32 0, i32 0
+// CHECK: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 1, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* getelementptr inbounds ([1 x i[[SZ]]], [1 x i[[SZ]]]* [[SIZET9]], i32 0, i32 0), i64* getelementptr inbounds ([1 x i64], [1 x i64]* [[MAPT10]], i32 0, i32 0))
+// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
+// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
+// CHECK: [[FAIL]]
+// CHECK: call void [[HVT0:@.+]]([[S2]]* [[LOCAL_THIS1]])
+// CHECK-NEXT: br label %[[END]]
+// CHECK: [[END]]
// Check that the offloading functions are emitted and that the arguments are
// correct and loaded correctly for the target regions of the callees of bar().
@@ -765,4 +795,20 @@ void bar () {
pragma_target
{}
}
+
+class S2 {
+ int a, b, c;
+
+public:
+ void zee() {
+ #pragma omp target map(this[0])
+ a++;
+ }
+};
+
+int main () {
+ S2 bar;
+ bar.zee();
+}
+
#endif
diff --git a/test/OpenMP/target_data_ast_print.cpp b/test/OpenMP/target_data_ast_print.cpp
index 17dace8bfac8..fa67c1834aa4 100644
--- a/test/OpenMP/target_data_ast_print.cpp
+++ b/test/OpenMP/target_data_ast_print.cpp
@@ -40,11 +40,16 @@ T tmain(T argc, T *argv) {
#pragma omp target data map(always,alloc: e)
foo();
+#pragma omp target data map(close,alloc: e)
+ foo();
+
// nesting a target region
#pragma omp target data map(e)
{
#pragma omp target map(always, alloc: e)
foo();
+ #pragma omp target map(close, alloc: e)
+ foo();
}
return 0;
@@ -68,10 +73,14 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target data map(always,alloc: e)
// CHECK-NEXT: foo();
+// CHECK-NEXT: #pragma omp target data map(close,alloc: e)
+// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target data map(tofrom: e)
// CHECK-NEXT: {
// CHECK-NEXT: #pragma omp target map(always,alloc: e)
// CHECK-NEXT: foo();
+// CHECK-NEXT: #pragma omp target map(close,alloc: e)
+// CHECK-NEXT: foo();
// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
// CHECK-NEXT: int i, j, b, c, d, e, x[20];
// CHECK-NEXT: #pragma omp target data map(to: c)
@@ -90,10 +99,14 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target data map(always,alloc: e)
// CHECK-NEXT: foo();
+// CHECK-NEXT: #pragma omp target data map(close,alloc: e)
+// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target data map(tofrom: e)
// CHECK-NEXT: {
// CHECK-NEXT: #pragma omp target map(always,alloc: e)
// CHECK-NEXT: foo();
+// CHECK-NEXT: #pragma omp target map(close,alloc: e)
+// CHECK-NEXT: foo();
// CHECK: template<> char tmain<char, 1>(char argc, char *argv) {
// CHECK-NEXT: char i, j, b, c, d, e, x[20];
// CHECK-NEXT: #pragma omp target data map(to: c)
@@ -112,10 +125,14 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target data map(always,alloc: e)
// CHECK-NEXT: foo();
+// CHECK-NEXT: #pragma omp target data map(close,alloc: e)
+// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target data map(tofrom: e)
// CHECK-NEXT: {
// CHECK-NEXT: #pragma omp target map(always,alloc: e)
// CHECK-NEXT: foo();
+// CHECK-NEXT: #pragma omp target map(close,alloc: e)
+// CHECK-NEXT: foo();
int main (int argc, char **argv) {
int b = argc, c, d, e, f, g, x[20];
@@ -161,6 +178,11 @@ int main (int argc, char **argv) {
foo();
// CHECK-NEXT: foo();
+#pragma omp target data map(close,alloc: e)
+// CHECK-NEXT: #pragma omp target data map(close,alloc: e)
+ foo();
+// CHECK-NEXT: foo();
+
// nesting a target region
#pragma omp target data map(e)
// CHECK-NEXT: #pragma omp target data map(tofrom: e)
@@ -170,7 +192,11 @@ int main (int argc, char **argv) {
// CHECK-NEXT: #pragma omp target map(always,alloc: e)
foo();
// CHECK-NEXT: foo();
+#pragma omp target map(close, alloc: e)
+// CHECK-NEXT: #pragma omp target map(close,alloc: e)
+ foo();
}
+
return tmain<int, 5>(argc, &argc) + tmain<char, 1>(argv[0][0], argv[0]);
}
diff --git a/test/OpenMP/target_map_codegen.cpp b/test/OpenMP/target_map_codegen.cpp
index ec99e8ed396d..b267a72b4ce6 100644
--- a/test/OpenMP/target_map_codegen.cpp
+++ b/test/OpenMP/target_map_codegen.cpp
@@ -5101,4 +5101,161 @@ void explicit_maps_member_pointer_references(SSA *sap) {
sb.foo();
}
#endif
+///==========================================================================///
+// RUN: %clang_cc1 -DCK30 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK30 --check-prefix CK30-64
+// RUN: %clang_cc1 -DCK30 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK30 --check-prefix CK30-64
+// RUN: %clang_cc1 -DCK30 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK30 --check-prefix CK30-32
+// RUN: %clang_cc1 -DCK30 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK30 --check-prefix CK30-32
+
+// RUN: %clang_cc1 -DCK30 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY30 %s
+// RUN: %clang_cc1 -DCK30 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY30 %s
+// RUN: %clang_cc1 -DCK30 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY30 %s
+// RUN: %clang_cc1 -DCK30 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY30 %s
+// SIMD-ONLY30-NOT: {{__kmpc|__tgt}}
+#ifdef CK30
+
+// CK30-DAG: [[BASE:%.+]] = type { i32*, i32, i32* }
+// CK30-DAG: [[STRUCT:%.+]] = type { [[BASE]], i32*, i32*, i32, i32* }
+
+// CK30-LABEL: @.__omp_offloading_{{.*}}map_with_deep_copy{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
+// The first element: 0x20 - OMP_MAP_TARGET_PARAM
+// 2-4: 0x1000000000003 - OMP_MAP_MEMBER_OF(0) | OMP_MAP_TO | OMP_MAP_FROM - copies all the data in structs excluding deep-copied elements (from &s to &s.ptrBase1, from &s.ptr to &s.ptr1, from &s.ptr1 to end of s).
+// 5-6: 0x1000000000013 - OMP_MAP_MEMBER_OF(0) | OMP_MAP_PTR_AND_OBJ | OMP_MAP_TO | OMP_MAP_FROM - deep copy of the pointers + pointee.
+// CK30: [[MTYPE00:@.+]] = private {{.*}}constant [6 x i64] [i64 32, i64 281474976710659, i64 281474976710659, i64 281474976710659, i64 281474976710675, i64 281474976710675]
+
+typedef struct {
+ int *ptrBase;
+ int valBase;
+ int *ptrBase1;
+} Base;
+
+typedef struct : public Base {
+ int *ptr;
+ int *ptr2;
+ int val;
+ int *ptr1;
+} StructWithPtr;
+
+// CK30-DAG: call i32 @__tgt_target(i64 -1, i8* @.__omp_offloading_{{.*}}map_with_deep_copy{{.*}}_l{{[0-9]+}}.region_id, i32 6, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i{{64|32}}* [[GEPS:%.+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MTYPE00]], i32 0, i32 0))
+// CK30-DAG: [[GEPS]] = getelementptr inbounds [6 x i{{64|32}}], [6 x i{{64|32}}]* [[SIZES:%.+]], i32 0, i32 0
+// CK30-DAG: [[GEPP]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS:%.+]], i32 0, i32 0
+// CK30-DAG: [[GEPBP]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASES:%.+]], i32 0, i32 0
+
+// CK30-DAG: [[BASE_PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASES]], i32 0, i32 0
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[BASE_PTR]] to [[STRUCT]]**
+// CK30-DAG: store [[STRUCT]]* [[S:%.+]], [[STRUCT]]** [[BC]],
+// CK30-DAG: [[PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS]], i32 0, i32 0
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[PTR]] to [[STRUCT]]**
+// CK30-DAG: store [[STRUCT]]* [[S]], [[STRUCT]]** [[BC]],
+// CK30-DAG: [[SIZE:%.+]] = getelementptr inbounds [6 x i{{64|32}}], [6 x i{{64|32}}]* [[SIZES]], i32 0, i32 0
+// CK30-64-DAG: store i64 [[S_ALLOC_SIZE:%.+]], i64* [[SIZE]],
+// CK30-32-DAG: store i32 [[S_ALLOC_SIZE32:%.+]], i32* [[SIZE]],
+// CK30-32-DAG: [[S_ALLOC_SIZE32]] = trunc i64 [[S_ALLOC_SIZE:%.+]] to i32
+// CK30-DAG: [[S_ALLOC_SIZE]] = sdiv exact i64 [[DIFF:%.+]], ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+// CK30-DAG: [[DIFF]] = sub i64 [[S_END_BC:%.+]], [[S_BEGIN_BC:%.+]]
+// CK30-DAG: [[S_BEGIN_BC]] = ptrtoint i8* [[S_BEGIN:%.+]] to i64
+// CK30-DAG: [[S_END_BC]] = ptrtoint i8* [[S_END:%.+]] to i64
+// CK30-DAG: [[S_BEGIN]] = bitcast [[STRUCT]]* [[S]] to i8*
+// CK30-DAG: [[S_END]] = getelementptr i8, i8* [[S_LAST:%.+]], i32 1
+// CK30-DAG: [[S_LAST]] = getelementptr i8, i8* [[S_BC:%.+]], i{{64|32}} {{55|27}}
+// CK30-DAG: [[S_BC]] = bitcast [[STRUCT]]* [[S]] to i8*
+
+// CK30-DAG: [[BASE_PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASES]], i32 0, i32 1
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[BASE_PTR]] to [[STRUCT]]**
+// CK30-DAG: store [[STRUCT]]* [[S]], [[STRUCT]]** [[BC]],
+// CK30-DAG: [[PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS]], i32 0, i32 1
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[PTR]] to [[STRUCT]]**
+// CK30-DAG: store [[STRUCT]]* [[S]], [[STRUCT]]** [[BC]],
+// CK30-DAG: [[SIZE:%.+]] = getelementptr inbounds [6 x i{{64|32}}], [6 x i{{64|32}}]* [[SIZES]], i32 0, i32 1
+// CK30-64-DAG: store i64 [[SIZE1:%.+]], i64* [[SIZE]],
+// CK30-32-DAG: store i32 [[SIZE1_32:%.+]], i32* [[SIZE]],
+// CK30-32-DAG: [[SIZE1_32]] = trunc i64 [[SIZE1:%.+]] to i32
+// CK30-DAG: [[SIZE1]] = sdiv exact i64 [[DIFF:%.+]], ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+// CK30-DAG: [[DIFF]] = sub i64 [[S_PTRBASE1_BC:%.+]], [[S_BEGIN_BC:%.+]]
+// CK30-DAG: [[S_BEGIN_BC]] = ptrtoint i8* [[S_BEGIN:%.+]] to i64
+// CK30-DAG: [[S_PTRBASE1_BC]] = ptrtoint i8* [[S_PTRBASE1:%.+]] to i64
+// CK30-DAG: [[S_PTRBASE1]] = bitcast i32** [[S_PTRBASE1_REF:%.+]] to i8*
+// CK30-DAG: [[S_BEGIN]] = bitcast [[STRUCT]]* [[S]] to i8*
+// CK30-DAG: [[S_PTRBASE1_REF]] = getelementptr inbounds [[BASE]], [[BASE]]* [[BASE_ADDR:%.+]], i32 0, i32 2
+// CK30-DAG: [[BASE_ADDR]] = bitcast [[STRUCT]]* [[S]] to [[BASE]]*
+
+// CK30-DAG: [[BASE_PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASES]], i32 0, i32 2
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[BASE_PTR]] to [[STRUCT]]**
+// CK30-DAG: store [[STRUCT]]* [[S]], [[STRUCT]]** [[BC]],
+// CK30-DAG: [[PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS]], i32 0, i32 2
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[PTR]] to i32***
+// CK30-DAG: store i32** [[PTR1:%.+]], i32*** [[BC]],
+// CK30-DAG: [[SIZE:%.+]] = getelementptr inbounds [6 x i{{64|32}}], [6 x i{{64|32}}]* [[SIZES]], i32 0, i32 2
+// CK30-64-DAG: store i64 [[SIZE2:%.+]], i64* [[SIZE]],
+// CK30-32-DAG: store i32 [[SIZE2_32:%.+]], i32* [[SIZE]],
+// CK30-32-DAG: [[SIZE2_32]] = trunc i64 [[SIZE2:%.+]] to i32
+// CK30-DAG: [[PTR1]] = getelementptr i32*, i32** [[S_PTRBASE1_REF]], i{{64|32}} 1
+// CK30-DAG: [[SIZE2]] = sdiv exact i64 [[DIFF:%.+]], ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+// CK30-DAG: [[DIFF]] = sub i64 [[S_PTR1_BC:%.+]], [[S_PTRBASE1_BC:%.+]]
+// CK30-DAG: [[S_PTR1_BC]] = ptrtoint i8* [[S_PTR1:%.+]] to i64
+// CK30-DAG: [[S_PTRBASE1_BC]] = ptrtoint i8* [[S_PTRBASE1:%.+]] to i64
+// CK30-DAG: [[S_PTR1]] = bitcast i32** [[S_PTR1_REF:%.+]] to i8*
+// CK30-DAG: [[S_PTRBASE1]] = bitcast i32** [[PTR1]] to i8*
+// CK30-DAG: [[S_PTR1_REF]] = getelementptr inbounds [[STRUCT]], [[STRUCT]]* [[S]], i32 0, i32 4
+
+// CK30-DAG: [[BASE_PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASES]], i32 0, i32 3
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[BASE_PTR]] to [[STRUCT]]**
+// CK30-DAG: store [[STRUCT]]* [[S]], [[STRUCT]]** [[BC]],
+// CK30-DAG: [[PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS]], i32 0, i32 3
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[PTR]] to i32***
+// CK30-DAG: store i32** [[PTR2:%.+]], i32*** [[BC]],
+// CK30-DAG: [[SIZE:%.+]] = getelementptr inbounds [6 x i{{64|32}}], [6 x i{{64|32}}]* [[SIZES]], i32 0, i32 3
+// CK30-64-DAG: store i64 [[SIZE3:%.+]], i64* [[SIZE]],
+// CK30-32-DAG: store i32 [[SIZE3_32:%.+]], i32* [[SIZE]],
+// CK30-32-DAG: [[SIZE3_32]] = trunc i64 [[SIZE3:%.+]] to i32
+// CK30-DAG: [[PTR2]] = getelementptr i32*, i32** [[S_PTR1_REF]], i{{64|32}} 1
+// CK30-DAG: [[SIZE3]] = sdiv exact i64 [[DIFF:%.+]], ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+// CK30-DAG: [[DIFF]] = sub i64 [[S_END_BC:%.+]], [[S_PTR1_BC:%.+]]
+// CK30-DAG: [[S_PTR1_BC]] = ptrtoint i8* [[S_PTR1:%.+]] to i64
+// CK30-DAG: [[S_END_BC]] = ptrtoint i8* [[S_END:%.+]] to i64
+// CK30-DAG: [[S_PTR1]] = bitcast i32** [[PTR2]] to i8*
+// CK30-DAG: [[S_END]] = getelementptr i8, i8* [[S_LAST]], i{{64|32}} 1
+
+// CK30-DAG: [[BASE_PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASES]], i32 0, i32 4
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[BASE_PTR]] to i32***
+// CK30-DAG: store i32** [[S_PTR1:%.+]], i32*** [[BC]],
+// CK30-DAG: [[PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS]], i32 0, i32 4
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[PTR]] to i32**
+// CK30-DAG: store i32* [[S_PTR1_BEGIN:%.+]], i32** [[BC]],
+// CK30-DAG: [[SIZE:%.+]] = getelementptr inbounds [6 x i{{64|32}}], [6 x i{{64|32}}]* [[SIZES]], i32 0, i32 4
+// CK30-DAG: store i{{64|32}} 4, i{{64|32}}* [[SIZE]],
+// CK30-DAG: [[S_PTR1]] = getelementptr inbounds [[STRUCT]], [[STRUCT]]* [[S]], i32 0, i32 4
+// CK30-DAG: [[S_PTR1_BEGIN]] = getelementptr inbounds i32, i32* [[S_PTR1_BEGIN_REF:%.+]], i{{64|32}} 0
+// CK30-DAG: [[S_PTR1_BEGIN_REF]] = load i32*, i32** [[S_PTR1:%.+]],
+// CK30-DAG: [[S_PTR1]] = getelementptr inbounds [[STRUCT]], [[STRUCT]]* [[S]], i32 0, i32 4
+
+// CK30-DAG: [[BASE_PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASES]], i32 0, i32 5
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[BASE_PTR]] to i32***
+// CK30-DAG: store i32** [[S_PTRBASE1:%.+]], i32*** [[BC]],
+// CK30-DAG: [[PTR:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS]], i32 0, i32 5
+// CK30-DAG: [[BC:%.+]] = bitcast i8** [[PTR]] to i32**
+// CK30-DAG: store i32* [[S_PTRBASE1_BEGIN:%.+]], i32** [[BC]],
+// CK30-DAG: [[SIZE:%.+]] = getelementptr inbounds [6 x i{{64|32}}], [6 x i{{64|32}}]* [[SIZES]], i32 0, i32 5
+// CK30-DAG: store i{{64|32}} 4, i{{64|32}}* [[SIZE]],
+// CK30-DAG: [[S_PTRBASE1]] = getelementptr inbounds [[BASE]], [[BASE]]* [[S_BASE:%.+]], i32 0, i32 2
+// CK30-DAG: [[S_BASE]] = bitcast [[STRUCT]]* [[S]] to [[BASE]]*
+// CK30-DAG: [[S_PTRBASE1_BEGIN]] = getelementptr inbounds i32, i32* [[S_PTRBASE1_BEGIN_REF:%.+]], i{{64|32}} 0
+// CK30-DAG: [[S_PTRBASE1_BEGIN_REF]] = load i32*, i32** [[S_PTRBASE1:%.+]],
+// CK30-DAG: [[S_PTRBASE1]] = getelementptr inbounds [[BASE]], [[BASE]]* [[S_BASE:%.+]], i32 0, i32 2
+// CK30-DAG: [[S_BASE]] = bitcast [[STRUCT]]* [[S]] to [[BASE]]*
+void map_with_deep_copy() {
+ StructWithPtr s;
+#pragma omp target map(s, s.ptr1 [0:1], s.ptrBase1 [0:1])
+ {
+ s.val++;
+ s.ptr1[0]++;
+ s.ptrBase1[0] = 10001;
+ }
+}
+
+#endif
#endif
diff --git a/test/OpenMP/target_map_messages.cpp b/test/OpenMP/target_map_messages.cpp
index 03a81ee575b6..e81e61eaab5b 100644
--- a/test/OpenMP/target_map_messages.cpp
+++ b/test/OpenMP/target_map_messages.cpp
@@ -74,6 +74,8 @@ struct SA {
#pragma omp target map(b[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
{}
+ #pragma omp target map(: c,f) // expected-error {{missing map type}}
+ {}
#pragma omp target map(always, tofrom: c,f)
{}
#pragma omp target map(always, tofrom: c[1:2],f)
@@ -86,6 +88,42 @@ struct SA {
{}
#pragma omp target map(always) // expected-error {{use of undeclared identifier 'always'}}
{}
+ #pragma omp target map(close, tofrom: c,f)
+ {}
+ #pragma omp target map(close, tofrom: c[1:2],f)
+ {}
+ #pragma omp target map(close, tofrom: c,f[1:2])
+ {}
+ #pragma omp target map(close, tofrom: c[:],f) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ {}
+ #pragma omp target map(close, tofrom: c,f[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ {}
+ #pragma omp target map(close) // expected-error {{use of undeclared identifier 'close'}}
+ {}
+ #pragma omp target map(close, close, tofrom: a) // expected-error {{same map type modifier has been specified more than once}}
+ {}
+ #pragma omp target map(always, close, always, close, tofrom: a) // expected-error {{same map type modifier has been specified more than once}} expected-error {{same map type modifier has been specified more than once}}
+ {}
+ #pragma omp target map( , tofrom: a) // expected-error {{missing map type modifier}}
+ {}
+ #pragma omp target map( , , tofrom: a) // expected-error {{missing map type modifier}} expected-error {{missing map type modifier}}
+ {}
+ #pragma omp target map( , , : a) // expected-error {{missing map type modifier}} expected-error {{missing map type modifier}} expected-error {{missing map type}}
+ {}
+ #pragma omp target map( d, f, bf: a) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ {}
+ #pragma omp target map( , f, : a) // expected-error {{missing map type modifier}} expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
+ {}
+ #pragma omp target map(always close: a) // expected-error {{missing map type}}
+ {}
+ #pragma omp target map(always close bf: a) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ {}
+ #pragma omp target map(always tofrom close: a) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
+ {}
+ #pragma omp target map(tofrom from: a) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}}
+ {}
+ #pragma omp target map(close bf: a) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ {}
return;
}
};
@@ -405,7 +443,7 @@ T tmain(T argc) {
T *k = &j;
T x;
T y;
- T to, tofrom, always;
+ T to, tofrom, always, close;
const T (&l)[5] = da;
#pragma omp target map // expected-error {{expected '(' after 'map'}}
{}
@@ -478,10 +516,16 @@ T tmain(T argc) {
#pragma omp target data map(always, tofrom: x)
#pragma omp target data map(always: x) // expected-error {{missing map type}}
-#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
#pragma omp target data map(always, tofrom: always, tofrom, x)
#pragma omp target map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
foo();
+
+#pragma omp target data map(close, tofrom: x)
+#pragma omp target data map(close: x) // expected-error {{missing map type}}
+#pragma omp target data map(tofrom, close: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
+#pragma omp target data map(close, tofrom: close, tofrom, x)
+ foo();
return 0;
}
@@ -515,7 +559,7 @@ int main(int argc, char **argv) {
S6<int> m;
int x;
int y;
- int to, tofrom, always;
+ int to, tofrom, always, close;
const int (&l)[5] = da;
SC1 s;
SC1 *p;
@@ -569,10 +613,14 @@ int main(int argc, char **argv) {
#pragma omp target data map(always, tofrom: x)
#pragma omp target data map(always: x) // expected-error {{missing map type}}
-#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
#pragma omp target data map(always, tofrom: always, tofrom, x)
#pragma omp target map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
foo();
+#pragma omp target data map(close, tofrom: x)
+#pragma omp target data map(close: x) // expected-error {{missing map type}}
+#pragma omp target data map(tofrom, close: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
+ foo();
#pragma omp target private(j) map(j) // expected-error {{private variable cannot be in a map clause in '#pragma omp target' directive}} expected-note {{defined as private}}
{}
#pragma omp target firstprivate(j) map(j) // expected-error {{firstprivate variable cannot be in a map clause in '#pragma omp target' directive}} expected-note {{defined as firstprivate}}
@@ -591,9 +639,7 @@ int main(int argc, char **argv) {
#pragma omp target map(s.b[:5])
// expected-error@+1 {{variable already marked as mapped in current construct}}
{ s.a++; }
-// expected-note@+1 {{used here}}
#pragma omp target map(s.p[:5])
-// expected-error@+1 {{variable already marked as mapped in current construct}}
{ s.a++; }
// expected-note@+1 {{used here}}
#pragma omp target map(s.s.sa[3].a)
diff --git a/test/OpenMP/target_messages.cpp b/test/OpenMP/target_messages.cpp
index c9dc80aca44c..9bd8b3749e05 100644
--- a/test/OpenMP/target_messages.cpp
+++ b/test/OpenMP/target_messages.cpp
@@ -15,6 +15,7 @@
// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -DREGION_HOST
// RUN: not %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -DREGION_DEVICE 2>&1 | FileCheck %s --check-prefix NO-REGION
// NO-REGION: Offloading entry for target region is incorrect: either the address or the ID is invalid.
+// NO-REGION-NOT: Offloading entry for target region is incorrect: either the address or the ID is invalid.
#if defined(REGION_HOST) || defined(REGION_DEVICE)
void foo() {
@@ -27,10 +28,33 @@ void foo() {
;
#endif
}
+#pragma omp declare target to(foo)
+void bar() {
+#ifdef REGION_HOST
+#pragma omp target
+ ;
+#endif
+#ifdef REGION_DEVICE
+#pragma omp target
+ ;
+#endif
+}
#else
void foo() {
}
+class S {
+ public:
+ void zee() {
+ #pragma omp target map(this[:2]) // expected-note {{expected length on mapping of 'this' array section expression to be '1'}} // expected-error {{invalid 'this' expression on 'map' clause}}
+ int a;
+ #pragma omp target map(this[1:1]) // expected-note {{expected lower bound on mapping of 'this' array section expression to be '0' or not specified}} // expected-error {{invalid 'this' expression on 'map' clause}}
+ int b;
+ #pragma omp target map(this[1]) // expected-note {{expected 'this' subscript expression on map clause to be 'this[0]'}} // expected-error {{invalid 'this' expression on 'map' clause}}
+ int c;
+ }
+};
+
#pragma omp target // expected-error {{unexpected OpenMP directive '#pragma omp target'}}
int main(int argc, char **argv) {
diff --git a/test/OpenMP/target_parallel_codegen.cpp b/test/OpenMP/target_parallel_codegen.cpp
index bebde4edf722..3fada3164798 100644
--- a/test/OpenMP/target_parallel_codegen.cpp
+++ b/test/OpenMP/target_parallel_codegen.cpp
@@ -1,37 +1,37 @@
// Test host codegen.
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32
-// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// Test target codegen - host bc file has to be created first.
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc
-// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc
-// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s
// SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -242,54 +242,55 @@ int foo(int n) {
// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR0:%.+]],
// CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
// CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
- // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CBPADDR1:%.+]],
// CHECK-DAG: store i[[SZ]] [[VLA1]], i[[SZ]]* [[CPADDR1:%.+]],
// CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
// CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
- // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CBPADDR2:%.+]],
// CHECK-DAG: store i[[SZ]] 5, i[[SZ]]* [[CPADDR2:%.+]],
// CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
// CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
- // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CBPADDR3:%.+]],
// CHECK-DAG: store i[[SZ]] [[A_CVAL]], i[[SZ]]* [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
- // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CBPADDR4:%.+]],
// CHECK-DAG: store [10 x float]* %{{.+}}, [10 x float]** [[CPADDR4:%.+]],
// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [10 x float]**
// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [10 x float]**
- // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store float* %{{.+}}, float** [[CBPADDR5:%.+]],
// CHECK-DAG: store float* %{{.+}}, float** [[CPADDR5:%.+]],
// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to float**
// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to float**
- // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CBPADDR6:%.+]],
// CHECK-DAG: store [5 x [10 x double]]* %{{.+}}, [5 x [10 x double]]** [[CPADDR6:%.+]],
// CHECK-DAG: [[CBPADDR6]] = bitcast i8** {{%[^,]+}} to [5 x [10 x double]]**
// CHECK-DAG: [[CPADDR6]] = bitcast i8** {{%[^,]+}} to [5 x [10 x double]]**
- // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store double* %{{.+}}, double** [[CBPADDR7:%.+]],
// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR7:%.+]],
// CHECK-DAG: [[CBPADDR7]] = bitcast i8** {{%[^,]+}} to double**
// CHECK-DAG: [[CPADDR7]] = bitcast i8** {{%[^,]+}} to double**
- // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CBPADDR8:%.+]],
// CHECK-DAG: store [[TT]]* %{{.+}}, [[TT]]** [[CPADDR8:%.+]],
// CHECK-DAG: [[CBPADDR8]] = bitcast i8** {{%[^,]+}} to [[TT]]**
// CHECK-DAG: [[CPADDR8]] = bitcast i8** {{%[^,]+}} to [[TT]]**
+
+ // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] [[CNSIZE]], i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] [[BNSIZE]], i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] 40, i[[SZ]]* {{%[^,]+}}
+ // CHECK-DAG: store i[[SZ]] 400, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store i[[SZ]] {{12|16}}, i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
@@ -564,37 +565,32 @@ int bar(int n){
// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR0:%.+]],
// CHECK-DAG: [[CBPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
// CHECK-DAG: [[CPADDR0]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
-// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR1:%.+]],
// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR1:%.+]],
// CHECK-DAG: [[CBPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
// CHECK-DAG: [[CPADDR1]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
-// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR2:%.+]],
// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR2:%.+]],
// CHECK-DAG: [[CBPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
// CHECK-DAG: [[CPADDR2]] = bitcast i8** {{%[^,]+}} to i[[SZ]]*
-// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]],
// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]],
// CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* {{%[^,]+}}
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]],
-// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR4:%.+]],
-// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]**
-// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}}
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]],
+// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]],
+// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]],
-// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]],
-// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
-// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16**
+// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}}
// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}}
+// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
+// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* {{%[^,]+}}
+// CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* {{%[^,]+}}
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
diff --git a/test/OpenMP/target_parallel_debug_codegen.cpp b/test/OpenMP/target_parallel_debug_codegen.cpp
index ebd761fb9699..06515f6b309b 100644
--- a/test/OpenMP/target_parallel_debug_codegen.cpp
+++ b/test/OpenMP/target_parallel_debug_codegen.cpp
@@ -2,6 +2,17 @@
// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -fopenmp-cuda-mode -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -debug-info-kind=limited -fopenmp-version=45 | FileCheck %s
// expected-no-diagnostics
+template <unsigned *ddd>
+struct S {
+ static int a;
+};
+
+extern unsigned aaa;
+template<> int S<&aaa>::a;
+
+template struct S<&aaa>;
+// CHECK-NOT: @aaa
+
int main() {
/* int(*b)[a]; */
/* int *(**c)[a]; */
@@ -116,11 +127,11 @@ int main() {
// CHECK: !DILocalVariable(name: ".bound_tid.",
// CHECK-SAME: DIFlagArtificial
// CHECK: !DILocalVariable(name: "c",
-// CHECK-SAME: line: 11
+// CHECK-SAME: line: 22
// CHECK: !DILocalVariable(name: "a",
-// CHECK-SAME: line: 9
+// CHECK-SAME: line: 20
// CHECK: !DILocalVariable(name: "b",
-// CHECK-SAME: line: 10
+// CHECK-SAME: line: 21
// CHECK-DAG: distinct !DISubprogram(name: "[[NONDEBUG_WRAPPER]]",
// CHECK-DAG: distinct !DISubprogram(name: "[[DEBUG_PARALLEL]]",
diff --git a/test/OpenMP/target_parallel_default_messages.cpp b/test/OpenMP/target_parallel_default_messages.cpp
index 143a94c55326..9fb3fac69743 100644
--- a/test/OpenMP/target_parallel_default_messages.cpp
+++ b/test/OpenMP/target_parallel_default_messages.cpp
@@ -27,6 +27,6 @@ int main(int argc, char **argv) {
++argc;
#pragma omp target parallel default(none)
#pragma omp parallel default(shared)
- ++argc;
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
return 0;
}
diff --git a/test/OpenMP/target_parallel_for_codegen.cpp b/test/OpenMP/target_parallel_for_codegen.cpp
index dc6243c9df3c..eac2bd451f92 100644
--- a/test/OpenMP/target_parallel_for_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
diff --git a/test/OpenMP/target_parallel_for_lastprivate_messages.cpp b/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
index 0ff2c722f7de..7aff164b50bf 100644
--- a/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/target_parallel_for_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
S2 &operator=(const S2 &);
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -168,7 +168,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target parallel for lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -180,10 +180,10 @@ int main(int argc, char **argv) {
#pragma omp target parallel for lastprivate(ba)
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target parallel for safelen(5) // expected-error {{unexpected OpenMP clause 'safelen' in directive '#pragma omp target parallel for'}}
diff --git a/test/OpenMP/target_parallel_for_linear_messages.cpp b/test/OpenMP/target_parallel_for_linear_messages.cpp
index b7224b538f4c..79890c414ab3 100644
--- a/test/OpenMP/target_parallel_for_linear_messages.cpp
+++ b/test/OpenMP/target_parallel_for_linear_messages.cpp
@@ -146,7 +146,7 @@ int foomain(I argc, C **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp target parallel for linear(a, b : B::ib)
for (int k = 0; k < argc; ++k)
++k;
@@ -231,7 +231,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp target parallel for linear(a, b)
for (int k = 0; k < argc; ++k)
++k;
diff --git a/test/OpenMP/target_parallel_for_loop_messages.cpp b/test/OpenMP/target_parallel_for_loop_messages.cpp
index 416cbfa1f3c3..6cc1f80887d6 100644
--- a/test/OpenMP/target_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/target_parallel_for_loop_messages.cpp
@@ -108,7 +108,7 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// Ok
#pragma omp target parallel for
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/target_parallel_for_map_messages.cpp b/test/OpenMP/target_parallel_for_map_messages.cpp
index f4f98dfc4915..6d8292160354 100644
--- a/test/OpenMP/target_parallel_for_map_messages.cpp
+++ b/test/OpenMP/target_parallel_for_map_messages.cpp
@@ -163,7 +163,7 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
@@ -271,7 +271,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_parallel_for_reduction_messages.cpp b/test/OpenMP/target_parallel_for_reduction_messages.cpp
index 5cc40e9b9924..7cb55129e231 100644
--- a/test/OpenMP/target_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/target_parallel_for_reduction_messages.cpp
@@ -130,22 +130,22 @@ T tmain(T argc) {
#pragma omp target parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -154,7 +154,7 @@ T tmain(T argc) {
#pragma omp target parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -173,7 +173,7 @@ T tmain(T argc) {
#pragma omp target parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -252,22 +252,22 @@ int main(int argc, char **argv) {
#pragma omp target parallel for reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -276,7 +276,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -298,7 +298,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/target_parallel_for_simd_codegen.cpp b/test/OpenMP/target_parallel_for_simd_codegen.cpp
index 75bf2d17afd6..ce0851c65a77 100644
--- a/test/OpenMP/target_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/target_parallel_for_simd_codegen.cpp
@@ -39,7 +39,7 @@
#define HEADER
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -367,7 +367,7 @@ int foo(int n) {
// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
// CHECK-64: [[AA:%.+]] = load i32, i32* [[AA_CADDR]], align
// CHECK-32: [[AA:%.+]] = load i32, i32* [[AA_ADDR]], align
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
// CHECK: !llvm.loop
// CHECK: ret void
// CHECK-NEXT: }
diff --git a/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
index 7c2c23f9d70d..1c4d853431ae 100644
--- a/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
S2 &operator=(const S2 &);
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -168,7 +168,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target parallel for simd lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -180,10 +180,10 @@ int main(int argc, char **argv) {
#pragma omp target parallel for simd lastprivate(ba)
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target parallel for simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target parallel for simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target parallel for simd safelen(5) // OK
diff --git a/test/OpenMP/target_parallel_for_simd_linear_messages.cpp b/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
index 40fd052df2e3..166cd2bc0bea 100644
--- a/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_linear_messages.cpp
@@ -146,7 +146,7 @@ int foomain(I argc, C **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp target parallel for simd linear(a, b : B::ib)
for (int k = 0; k < argc; ++k)
++k;
@@ -231,7 +231,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp target parallel for simd linear(a, b)
for (int k = 0; k < argc; ++k)
++k;
diff --git a/test/OpenMP/target_parallel_for_simd_loop_messages.cpp b/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
index fabf389150d0..e2e80186cd88 100644
--- a/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
@@ -108,7 +108,7 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// Ok
#pragma omp target parallel for simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/target_parallel_for_simd_map_messages.cpp b/test/OpenMP/target_parallel_for_simd_map_messages.cpp
index 1cab5988396f..a5135559cc33 100644
--- a/test/OpenMP/target_parallel_for_simd_map_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_map_messages.cpp
@@ -163,7 +163,7 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
@@ -271,7 +271,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
index 30aaf832d6fe..eb3d756dce4b 100644
--- a/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_reduction_messages.cpp
@@ -130,22 +130,22 @@ T tmain(T argc) {
#pragma omp target parallel for simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -154,7 +154,7 @@ T tmain(T argc) {
#pragma omp target parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -173,7 +173,7 @@ T tmain(T argc) {
#pragma omp target parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -252,22 +252,22 @@ int main(int argc, char **argv) {
#pragma omp target parallel for simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -276,7 +276,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target parallel for simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -298,7 +298,7 @@ int main(int argc, char **argv) {
#pragma omp target parallel for simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target parallel for simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel for simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/target_parallel_if_codegen.cpp b/test/OpenMP/target_parallel_if_codegen.cpp
index 264017f7c523..03e8c344450b 100644
--- a/test/OpenMP/target_parallel_if_codegen.cpp
+++ b/test/OpenMP/target_parallel_if_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
diff --git a/test/OpenMP/target_parallel_map_messages.cpp b/test/OpenMP/target_parallel_map_messages.cpp
index 4bb14ea52f03..056fd501ac84 100644
--- a/test/OpenMP/target_parallel_map_messages.cpp
+++ b/test/OpenMP/target_parallel_map_messages.cpp
@@ -163,7 +163,7 @@ T tmain(T argc) {
foo();
#pragma omp target parallel map(always: x) // expected-error {{missing map type}}
foo();
-#pragma omp target parallel map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target parallel map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
foo();
#pragma omp target parallel map(always, tofrom: always, tofrom, x)
foo();
@@ -270,7 +270,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target parallel map(always: x) // expected-error {{missing map type}}
foo();
-#pragma omp target parallel map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target parallel map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
foo();
#pragma omp target parallel map(always, tofrom: always, tofrom, x)
foo();
diff --git a/test/OpenMP/target_parallel_num_threads_codegen.cpp b/test/OpenMP/target_parallel_num_threads_codegen.cpp
index e271811a4911..7a39a3fd1c01 100644
--- a/test/OpenMP/target_parallel_num_threads_codegen.cpp
+++ b/test/OpenMP/target_parallel_num_threads_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
diff --git a/test/OpenMP/target_parallel_private_messages.cpp b/test/OpenMP/target_parallel_private_messages.cpp
index 34652d6cb3ce..de71c03ad4b6 100644
--- a/test/OpenMP/target_parallel_private_messages.cpp
+++ b/test/OpenMP/target_parallel_private_messages.cpp
@@ -22,9 +22,9 @@ class S3 {
public:
S3() : a(0) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}} expected-note 1 {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}} expected-note 1 {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}} expected-note 1 {{global variable is predetermined as shared}}
+const S3 c; // expected-note 2 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 2 {{'f' declared here}}
int threadvar;
#pragma omp threadprivate(threadvar) // expected-note {{defined as threadprivate or thread local}} expected-note 1 {{defined as threadprivate or thread local}}
@@ -56,8 +56,8 @@ S3 h;
template <class I, class C, class D, class E>
int foomain(I argc, C **argv) {
- const I d = 5; // expected-note {{constant variable is predetermined as shared}}
- const I da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}}
+ const I d = 5; // expected-note {{'d' defined here}}
+ const I da[5] = { 0 }; // expected-note {{'da' defined here}}
D e(4);
E g[] = {5, 6};
I i;
@@ -82,15 +82,15 @@ int foomain(I argc, C **argv) {
{}
#pragma omp target parallel private(a, b) // expected-error {{private variable with incomplete type 'S1'}}
{}
-#pragma omp target parallel private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp target parallel private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
{}
#pragma omp target parallel private(argv[1]) // expected-error {{expected variable name}}
{}
#pragma omp target parallel private(ba)
{}
-#pragma omp target parallel private(ca) // expected-error {{shared variable cannot be private}}
+#pragma omp target parallel private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
{}
-#pragma omp target parallel private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp target parallel private(da) // expected-error {{const-qualified variable cannot be private}}
{}
#pragma omp target parallel private(S2::S2s) // expected-error {{shared variable cannot be private}}
{}
@@ -143,8 +143,8 @@ void bar(S4 a[2]) {
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g[] = {5, 6};
int i;
@@ -169,15 +169,15 @@ int main(int argc, char **argv) {
{}
#pragma omp target parallel private(a, b) // expected-error {{private variable with incomplete type 'S1'}}
{}
-#pragma omp target parallel private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp target parallel private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
{}
#pragma omp target parallel private(argv[1]) // expected-error {{expected variable name}}
{}
#pragma omp target parallel private(ba)
{}
-#pragma omp target parallel private(ca) // expected-error {{shared variable cannot be private}}
+#pragma omp target parallel private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
{}
-#pragma omp target parallel private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp target parallel private(da) // expected-error {{const-qualified variable cannot be private}}
{}
#pragma omp target parallel private(S2::S2s) // expected-error {{shared variable cannot be private}}
{}
diff --git a/test/OpenMP/target_parallel_reduction_messages.cpp b/test/OpenMP/target_parallel_reduction_messages.cpp
index 6ea08848d513..63a00caf9273 100644
--- a/test/OpenMP/target_parallel_reduction_messages.cpp
+++ b/test/OpenMP/target_parallel_reduction_messages.cpp
@@ -116,23 +116,23 @@ T tmain(T argc) {
foo();
#pragma omp target parallel reduction(^ : T) // expected-error {{'T' does not refer to a value}}
foo();
-#pragma omp target parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp target parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp target parallel reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target parallel reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target parallel reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp target parallel reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp target parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
foo();
@@ -145,7 +145,7 @@ T tmain(T argc) {
foo();
#pragma omp target parallel reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
foo();
-#pragma omp target parallel reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel shared(i)
foo();
@@ -214,23 +214,23 @@ int main(int argc, char **argv) {
foo();
#pragma omp target parallel reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
foo();
-#pragma omp target parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target parallel reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp target parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp target parallel reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target parallel reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target parallel reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp target parallel reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp target parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
foo();
@@ -245,7 +245,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target parallel reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
foo();
-#pragma omp target parallel reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target parallel reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target parallel shared(i)
foo();
diff --git a/test/OpenMP/target_reduction_messages.cpp b/test/OpenMP/target_reduction_messages.cpp
index ff936b8c1950..29a12aba857c 100644
--- a/test/OpenMP/target_reduction_messages.cpp
+++ b/test/OpenMP/target_reduction_messages.cpp
@@ -116,23 +116,23 @@ T tmain(T argc) {
foo();
#pragma omp target reduction(^ : T) // expected-error {{'T' does not refer to a value}}
foo();
-#pragma omp target reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp target reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp target reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp target reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp target reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
foo();
@@ -145,7 +145,7 @@ T tmain(T argc) {
foo();
#pragma omp target reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
foo();
-#pragma omp target reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp target reduction(min : i)
@@ -211,23 +211,23 @@ int main(int argc, char **argv) {
foo();
#pragma omp target reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
foo();
-#pragma omp target reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp target reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp target reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp target reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp target reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
foo();
@@ -242,7 +242,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
foo();
-#pragma omp target reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp target reduction(min : i)
diff --git a/test/OpenMP/target_simd_codegen.cpp b/test/OpenMP/target_simd_codegen.cpp
index 81ad4038044c..13504213c531 100644
--- a/test/OpenMP/target_simd_codegen.cpp
+++ b/test/OpenMP/target_simd_codegen.cpp
@@ -342,7 +342,7 @@ int foo(int n) {
// CHECK-64: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i32*
// CHECK-64: [[AA:%.+]] = load i32, i32* [[AA_CADDR]], align
// CHECK-32: [[AA:%.+]] = load i32, i32* [[AA_ADDR]], align
-// CHECK: !llvm.mem.parallel_loop_access
+// CHECK: !llvm.access.group
// CHECK: !llvm.loop
// CHECK: ret void
// CHECK-NEXT: }
diff --git a/test/OpenMP/target_simd_lastprivate_messages.cpp b/test/OpenMP/target_simd_lastprivate_messages.cpp
index ae8bd0af7b5f..70a452f6a50e 100644
--- a/test/OpenMP/target_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
S2 &operator=(const S2 &);
const S2 &operator=(const S2 &) const;
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -168,7 +168,7 @@ int main(int argc, char **argv) {
#pragma omp target simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp target simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target simd lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -180,10 +180,10 @@ int main(int argc, char **argv) {
#pragma omp target simd lastprivate(ba)
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
#pragma omp target simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
-#pragma omp target simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp target simd safelen(5) // OK
diff --git a/test/OpenMP/target_simd_linear_messages.cpp b/test/OpenMP/target_simd_linear_messages.cpp
index 6a094b865185..d19409f280d7 100644
--- a/test/OpenMP/target_simd_linear_messages.cpp
+++ b/test/OpenMP/target_simd_linear_messages.cpp
@@ -146,7 +146,7 @@ int foomain(I argc, C **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp target simd linear(a, b : B::ib)
for (int k = 0; k < argc; ++k)
++k;
@@ -231,7 +231,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k)
++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
-// expected-error@+1 {{const-qualified variable cannot be linear}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp target simd linear(a, b)
for (int k = 0; k < argc; ++k)
++k;
diff --git a/test/OpenMP/target_simd_loop_messages.cpp b/test/OpenMP/target_simd_loop_messages.cpp
index 760bfe0496c2..4ab02e755058 100644
--- a/test/OpenMP/target_simd_loop_messages.cpp
+++ b/test/OpenMP/target_simd_loop_messages.cpp
@@ -108,7 +108,7 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// Ok
#pragma omp target simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/target_simd_map_messages.cpp b/test/OpenMP/target_simd_map_messages.cpp
index 3722ecb95ad1..acd629880874 100644
--- a/test/OpenMP/target_simd_map_messages.cpp
+++ b/test/OpenMP/target_simd_map_messages.cpp
@@ -159,7 +159,7 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
@@ -263,7 +263,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_simd_reduction_messages.cpp b/test/OpenMP/target_simd_reduction_messages.cpp
index 299c81315abe..cf6c9f6295cf 100644
--- a/test/OpenMP/target_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_simd_reduction_messages.cpp
@@ -130,22 +130,22 @@ T tmain(T argc) {
#pragma omp target simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -154,7 +154,7 @@ T tmain(T argc) {
#pragma omp target simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -173,7 +173,7 @@ T tmain(T argc) {
#pragma omp target simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -252,22 +252,22 @@ int main(int argc, char **argv) {
#pragma omp target simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -276,7 +276,7 @@ int main(int argc, char **argv) {
#pragma omp target simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp target simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -298,7 +298,7 @@ int main(int argc, char **argv) {
#pragma omp target simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp target simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/target_teams_codegen.cpp b/test/OpenMP/target_teams_codegen.cpp
index 43391fc641a6..044893311186 100644
--- a/test/OpenMP/target_teams_codegen.cpp
+++ b/test/OpenMP/target_teams_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
@@ -74,6 +74,8 @@
// CHECK-DAG: @{{.*}} = weak constant i8 0
// CHECK-DAG: @{{.*}} = weak constant i8 0
// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
+// CHECK-DAG: @{{.*}} = weak constant i8 0
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
@@ -82,6 +84,8 @@
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
+// TCHECK: @{{.+}} = weak constant [[ENTTY]]
// TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]]
// Check if offloading descriptor is created.
@@ -836,4 +840,21 @@ int bar(int n){
// CHECK: define internal {{.*}}void [[OMP_OUTLINED7]](i32* noalias %.global_tid., i32* noalias %.bound_tid., i[[SZ]] %{{.+}}, i[[SZ]] %{{.+}}, [10 x i32]* {{.+}})
// To reduce complexity, we're only going as far as validating the signature of the outlined parallel function.
+void foo1() {
+ const int n = 0;
+ #pragma omp target teams shared(n)
+ #pragma omp parallel firstprivate(n)
+ (void)n;
+}
+void foo() {
+ const int n = 0;
+ #pragma omp target teams firstprivate(n)
+ #pragma omp parallel shared(n)
+ (void)n;
+}
+
+// define {{.*}}void @__omp_offloading_{{.*}}foo1{{.*}}_l841(i[[SZ]] %{{.+}})
+// define internal void {{@.+}}(i32* {{.+}}, i32* {{.+}}, i[[SZ]] %{{.+}})
+// define {{.*}}void @__omp_offloading_{{.*}}foo1{{.*}}_l847(i[[SZ]] %{{.+}})
+// define internal void {{@.+}}(i32* {{.+}}, i32* {{.+}}, i32* dereferenceable{{.+}})
#endif
diff --git a/test/OpenMP/target_teams_default_messages.cpp b/test/OpenMP/target_teams_default_messages.cpp
index fa54416e6774..18520d9e8df8 100644
--- a/test/OpenMP/target_teams_default_messages.cpp
+++ b/test/OpenMP/target_teams_default_messages.cpp
@@ -23,6 +23,6 @@ int main(int argc, char **argv) {
#pragma omp target teams default(none)
#pragma omp parallel default(shared)
- ++argc;
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
return 0;
}
diff --git a/test/OpenMP/target_teams_distribute_codegen.cpp b/test/OpenMP/target_teams_distribute_codegen.cpp
index aa1bc016da0d..8c82362228e5 100644
--- a/test/OpenMP/target_teams_distribute_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
diff --git a/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
index 0739846cee0a..0a2f5448ba02 100644
--- a/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -168,7 +168,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -180,10 +180,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute lastprivate(ba)
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
diff --git a/test/OpenMP/target_teams_distribute_loop_messages.cpp b/test/OpenMP/target_teams_distribute_loop_messages.cpp
index b090c288a201..0ce8cbf71baa 100644
--- a/test/OpenMP/target_teams_distribute_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_loop_messages.cpp
@@ -108,8 +108,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target teams distribute
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/target_teams_distribute_map_messages.cpp b/test/OpenMP/target_teams_distribute_map_messages.cpp
index 826a09dd76d5..bbfa7cde9aac 100644
--- a/test/OpenMP/target_teams_distribute_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_map_messages.cpp
@@ -163,7 +163,7 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
@@ -271,7 +271,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
index 4d263cf69f02..e439431a0518 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
@@ -51,9 +51,13 @@ int target_teams_fun(int *g){
// discard capture expressions for te and th
// HCK1: = alloca i32,
// HCK1: = alloca i32,
+ // HCK1: = alloca i32,
+ // HCK1: = alloca i32,
+ // HCK1: = alloca i32,
// HCK1: [[N_CAST:%.+]] = alloca i{{32|64}},
// HCK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
// HCK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+ // HCK1: call void @__kmpc_push_target_tripcount(i64 -1, i64 %{{.+}})
// HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]],
// HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
// HCK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]],
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
index 8cd90a610b5c..af6ed9744a2c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
@@ -22,8 +22,10 @@ int Arg;
// CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test
void gtid_test() {
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
#pragma omp target teams distribute parallel for
@@ -78,9 +80,12 @@ int tmain(T Arg) {
// CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main()
int main() {
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_2:@.+]](
// CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
index b21b9118f913..3c5e81521778 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -169,7 +169,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -181,10 +181,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for lastprivate(ba)
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -194,7 +194,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
index 01bf38deb97c..ca537dd976dd 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
@@ -108,8 +108,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target teams distribute parallel for
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
index 5cba1e732d3f..f585d0a1eed0 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
@@ -163,7 +163,7 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
@@ -271,7 +271,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
index 7750238e70b5..43b0304bb90c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for private (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute parallel for private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp target teams distribute parallel for private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute parallel for private (argv[1]) // expected-error {{expected variable name}}
@@ -85,10 +85,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for private(ba)
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute parallel for private(ca) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams distribute parallel for private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute parallel for private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams distribute parallel for private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute parallel for private(S2::S2s) // expected-error {{shared variable cannot be private}}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
index 9107c218a436..a7242c911245 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
@@ -17,7 +17,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
index 53c41b6bb062..33a0e37b869c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
@@ -111,23 +111,23 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
@@ -140,7 +140,7 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -198,23 +198,23 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
for (int j=0; j<100; j++) foo();
@@ -229,7 +229,7 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
index 0329d7e2789e..7a1ea810911e 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
@@ -52,10 +52,14 @@ int target_teams_fun(int *g){
// discard capture expressions for te and th
// HCK1: = alloca i32,
// HCK1: = alloca i32,
+// HCK1: = alloca i32,
+// HCK1: = alloca i32,
+// HCK1: = alloca i32,
// HCK1: [[I_CAST:%.+]] = alloca i{{32|64}},
// HCK1: [[N_CAST:%.+]] = alloca i{{32|64}},
// HCK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
// HCK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+// HCK1: call void @__kmpc_push_target_tripcount(i64 -1, i64 %{{.+}})
// HCK1: [[I_PAR:%.+]] = load{{.+}}, {{.+}} [[I_CAST]],
// HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]],
// HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
@@ -73,7 +77,8 @@ int target_teams_fun(int *g){
// HCK1: call void @[[OFFL2:.+]](i{{64|32}} %{{.+}})
{{{
#pragma omp target teams distribute parallel for simd is_device_ptr(g) simdlen(8)
- for(int i = 0; i < n; i++) {
+ for(
+ int i = 0; i < n; i++) {
a[i] = g[0];
}
}}}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
index a3a14fbf1e68..b6778417be67 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
@@ -22,8 +22,10 @@ int Arg;
// CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test
void gtid_test() {
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
#pragma omp target teams distribute parallel for simd
@@ -78,9 +80,12 @@ int tmain(T Arg) {
// CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main()
int main() {
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_0:@.+]](
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call void [[OFFLOADING_FUN_1:@.+]](
+// CHECK: call void @__kmpc_push_target_tripcount(i64 -1, i64 100)
// CHECK: call i{{[0-9]+}} @__tgt_target_teams(
// CHECK: call void [[OFFLOADING_FUN_2:@.+]](
// CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
index b65c22ba8a40..d1adbd0d3916 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -169,7 +169,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -181,10 +181,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for simd lastprivate(ba)
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -194,7 +194,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute parallel for simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp
index 3013480d6ea9..372a976087ee 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_linear_messages.cpp
@@ -148,7 +148,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target teams distribute parallel for simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute parallel for simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp target teams distribute parallel for simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute parallel for simd linear (argv[1]) // expected-error {{expected variable name}}
@@ -216,7 +216,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute parallel for simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp target teams distribute parallel for simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute parallel for simd linear (argv[1]) // expected-error {{expected variable name}}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
index 1378ea4eb65c..6c7cb795059f 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
@@ -108,8 +108,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target teams distribute parallel for simd
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
index 63d85ebc37b9..5cf03278959b 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_map_messages.cpp
@@ -163,7 +163,7 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
@@ -271,7 +271,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute parallel for simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
index f1a8e0bfc7c3..9cf810a9e959 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for simd private (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
- #pragma omp target teams distribute parallel for simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp target teams distribute parallel for simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute parallel for simd private (argv[1]) // expected-error {{expected variable name}}
@@ -85,10 +85,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for simd private(ba)
for (int k = 0; k < argc; ++k) ++k;
- #pragma omp target teams distribute parallel for simd private(ca) // expected-error {{shared variable cannot be private}}
+ #pragma omp target teams distribute parallel for simd private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
- #pragma omp target teams distribute parallel for simd private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp target teams distribute parallel for simd private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute parallel for simd private(S2::S2s) // expected-error {{shared variable cannot be private}}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
index 40bf51f34028..9d10c2e3dc7c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -17,7 +17,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
index 8cd4acd878d0..d3d9c6009116 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_messages.cpp
@@ -111,23 +111,23 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
@@ -140,7 +140,7 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -198,23 +198,23 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
for (int j=0; j<100; j++) foo();
@@ -229,7 +229,7 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute parallel for simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute parallel for simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/target_teams_distribute_private_messages.cpp b/test/OpenMP/target_teams_distribute_private_messages.cpp
index df7b68919ca5..3d692a3f2629 100644
--- a/test/OpenMP/target_teams_distribute_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute private (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp target teams distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute private (argv[1]) // expected-error {{expected variable name}}
@@ -85,10 +85,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute private(ba)
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute private(ca) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams distribute private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams distribute private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute private(S2::S2s) // expected-error {{shared variable cannot be private}}
diff --git a/test/OpenMP/target_teams_distribute_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_reduction_messages.cpp
index 38878fc74c74..6a9e6782f6c4 100644
--- a/test/OpenMP/target_teams_distribute_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_reduction_messages.cpp
@@ -116,23 +116,23 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
@@ -145,7 +145,7 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -203,23 +203,23 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
for (int j=0; j<100; j++) foo();
@@ -234,7 +234,7 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/target_teams_distribute_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_codegen.cpp
index 425afd262256..0a5482e9b1c6 100644
--- a/test/OpenMP/target_teams_distribute_simd_codegen.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[TT:%.+]] = type { i64, i8 }
// CHECK-DAG: [[S1:%.+]] = type { double }
diff --git a/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
index 3a9abfb24a1a..4dcc9ea7549f 100644
--- a/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -136,8 +136,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -169,7 +169,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd lastprivate(argv[1]) // expected-error {{expected variable name}}
@@ -181,10 +181,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute simd lastprivate(ba)
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -194,7 +194,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp target teams distribute simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
diff --git a/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp b/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp
index 5bcd77da9e58..c353242bc130 100644
--- a/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_linear_messages.cpp
@@ -148,7 +148,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target teams distribute simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp target teams distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute simd linear (argv[1]) // expected-error {{expected variable name}}
@@ -216,7 +216,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp target teams distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute simd linear (argv[1]) // expected-error {{expected variable name}}
diff --git a/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp b/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp
index 463c88df2c3e..cba8e8205611 100644
--- a/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_loop_messages.cpp
@@ -108,8 +108,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target teams distribute simd
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/target_teams_distribute_simd_map_messages.cpp b/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
index 73671d728443..99c633a45dd9 100644
--- a/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_map_messages.cpp
@@ -163,7 +163,7 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
@@ -271,7 +271,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd map(always: x) // expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams distribute simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd map(always, tofrom: always, tofrom, x)
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_teams_distribute_simd_private_messages.cpp b/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
index 743ac160ce5d..eef86d229d33 100644
--- a/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute simd private (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp target teams distribute simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute simd private (argv[1]) // expected-error {{expected variable name}}
@@ -85,10 +85,10 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute simd private(ba)
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute simd private(ca) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams distribute simd private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
-#pragma omp target teams distribute simd private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams distribute simd private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target teams distribute simd private(S2::S2s) // expected-error {{shared variable cannot be private}}
diff --git a/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
index b77082b44a9e..1b4b3ed88cde 100644
--- a/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_simd_reduction_messages.cpp
@@ -111,23 +111,23 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
@@ -140,7 +140,7 @@ T tmain(T argc) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -198,23 +198,23 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
for (int j=0; j<100; j++) foo();
@@ -229,7 +229,7 @@ int main(int argc, char **argv) {
for (int j=0; j<100; j++) foo();
#pragma omp target teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
-#pragma omp target teams distribute simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams distribute simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/target_teams_map_messages.cpp b/test/OpenMP/target_teams_map_messages.cpp
index 57d9396394c7..4b2629ee3345 100644
--- a/test/OpenMP/target_teams_map_messages.cpp
+++ b/test/OpenMP/target_teams_map_messages.cpp
@@ -454,7 +454,7 @@ T tmain(T argc) {
#pragma omp target data map(always, tofrom: x)
#pragma omp target data map(always: x) // expected-error {{missing map type}}
-#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
#pragma omp target data map(always, tofrom: always, tofrom, x)
#pragma omp target teams map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
foo();
@@ -529,7 +529,7 @@ int main(int argc, char **argv) {
#pragma omp target data map(always, tofrom: x)
#pragma omp target data map(always: x) // expected-error {{missing map type}}
-#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always' or 'close'}} expected-error {{missing map type}}
#pragma omp target data map(always, tofrom: always, tofrom, x)
#pragma omp target teams map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
foo();
diff --git a/test/OpenMP/target_teams_messages.cpp b/test/OpenMP/target_teams_messages.cpp
index 3a367bfc7e4e..bc068f87b619 100644
--- a/test/OpenMP/target_teams_messages.cpp
+++ b/test/OpenMP/target_teams_messages.cpp
@@ -50,6 +50,16 @@ int main(int argc, char **argv) {
#pragma omp target teams default(none)
++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+#pragma omp target teams default(none)
+#pragma omp parallel num_threads(argc) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+ ;
+
+#pragma omp target teams default(none)
+ {
+#pragma omp parallel num_threads(argc) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+ ;
+ }
+
goto L2; // expected-error {{use of undeclared label 'L2'}}
#pragma omp target teams
L2:
diff --git a/test/OpenMP/target_teams_num_teams_codegen.cpp b/test/OpenMP/target_teams_num_teams_codegen.cpp
index 6edde0042edd..36c4ac2814a9 100644
--- a/test/OpenMP/target_teams_num_teams_codegen.cpp
+++ b/test/OpenMP/target_teams_num_teams_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
diff --git a/test/OpenMP/target_teams_private_messages.cpp b/test/OpenMP/target_teams_private_messages.cpp
index 7ee509c8acaa..ceb268f40a70 100644
--- a/test/OpenMP/target_teams_private_messages.cpp
+++ b/test/OpenMP/target_teams_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -52,8 +52,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -74,15 +74,15 @@ int main(int argc, char **argv) {
foo();
#pragma omp target teams private (S1) // expected-error {{'S1' does not refer to a value}}
foo();
-#pragma omp target teams private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp target teams private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
foo();
#pragma omp target teams private (argv[1]) // expected-error {{expected variable name}}
foo();
#pragma omp target teams private(ba)
foo();
-#pragma omp target teams private(ca) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
foo();
-#pragma omp target teams private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp target teams private(da) // expected-error {{const-qualified variable cannot be private}}
foo();
#pragma omp target teams private(S2::S2s) // expected-error {{shared variable cannot be private}}
foo();
diff --git a/test/OpenMP/target_teams_reduction_messages.cpp b/test/OpenMP/target_teams_reduction_messages.cpp
index c62f2c58440b..1c3eacfef4a7 100644
--- a/test/OpenMP/target_teams_reduction_messages.cpp
+++ b/test/OpenMP/target_teams_reduction_messages.cpp
@@ -116,23 +116,23 @@ T tmain(T argc) {
foo();
#pragma omp target teams reduction(^ : T) // expected-error {{'T' does not refer to a value}}
foo();
-#pragma omp target teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp target teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target teams reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp target teams reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target teams reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target teams reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target teams reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp target teams reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp target teams reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target teams reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
foo();
@@ -145,7 +145,7 @@ T tmain(T argc) {
foo();
#pragma omp target teams reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
foo();
-#pragma omp target teams reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -213,23 +213,23 @@ int main(int argc, char **argv) {
foo();
#pragma omp target teams reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
foo();
-#pragma omp target teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp target teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp target teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target teams reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp target teams reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target teams reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
-#pragma omp target teams reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target teams reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp target teams reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp target teams reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target teams reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
foo();
@@ -244,7 +244,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target teams reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
foo();
-#pragma omp target teams reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp target teams reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/target_teams_thread_limit_codegen.cpp b/test/OpenMP/target_teams_thread_limit_codegen.cpp
index 3baa81cc9ecb..c322e258d853 100644
--- a/test/OpenMP/target_teams_thread_limit_codegen.cpp
+++ b/test/OpenMP/target_teams_thread_limit_codegen.cpp
@@ -40,7 +40,7 @@
// CHECK-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CHECK-DAG: [[S1:%.+]] = type { double }
// CHECK-DAG: [[ENTTY:%.+]] = type { i8*, i8*, i[[SZ:32|64]], i32, i32 }
diff --git a/test/OpenMP/task_codegen.cpp b/test/OpenMP/task_codegen.cpp
index fefe8b4329c2..b034bb29c887 100644
--- a/test/OpenMP/task_codegen.cpp
+++ b/test/OpenMP/task_codegen.cpp
@@ -107,6 +107,7 @@ int main() {
// CHECK: call i32 @__kmpc_omp_task([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]])
#pragma omp task untied
{
+#pragma omp critical
a = 1;
}
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i32 0, i64 40, i64 1,
@@ -278,5 +279,18 @@ int main() {
// CHECK: load i32*, i32** %
// CHECK: store i32 4, i32* %
// CHECK: call i32 @__kmpc_omp_task(%
+
+struct S1 {
+ int a;
+ S1() { taskinit(); }
+ void taskinit() {
+#pragma omp task
+ a = 0;
+ }
+} s1;
+
+// CHECK-LABEL: taskinit
+// CHECK: call i8* @__kmpc_omp_task_alloc(
+
#endif
diff --git a/test/OpenMP/task_default_messages.cpp b/test/OpenMP/task_default_messages.cpp
index 45bd8df82151..046e388c1469 100644
--- a/test/OpenMP/task_default_messages.cpp
+++ b/test/OpenMP/task_default_messages.cpp
@@ -18,6 +18,6 @@ int main(int argc, char **argv) {
#pragma omp task default(none)
#pragma omp task default(shared)
- ++argc;
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
return 0;
}
diff --git a/test/OpenMP/task_firstprivate_messages.cpp b/test/OpenMP/task_firstprivate_messages.cpp
index 1a64f2abf3c6..d970f097a580 100644
--- a/test/OpenMP/task_firstprivate_messages.cpp
+++ b/test/OpenMP/task_firstprivate_messages.cpp
@@ -47,7 +47,7 @@ extern const int f;
class S4 {
int a;
S4();
- S4(const S4 &s4); // expected-note 2 {{implicitly declared private here}}
+ S4(const S4 &s4); // expected-note 16 {{implicitly declared private here}}
public:
S4(int v) : a(v) {}
@@ -55,7 +55,7 @@ public:
class S5 {
int a;
S5() : a(0) {}
- S5(const S5 &s5) : a(s5.a) {} // expected-note 2 {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {} // expected-note 16 {{implicitly declared private here}}
public:
S5(int v) : a(v) {}
@@ -100,7 +100,7 @@ int main(int argc, char **argv) {
#pragma omp task firstprivate(da)
#pragma omp task firstprivate(S2::S2s)
#pragma omp task firstprivate(S2::S2sc)
-#pragma omp task firstprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} expected-error 2 {{calling a private constructor of class 'S5'}}
+#pragma omp task firstprivate(e, g) // expected-error 16 {{calling a private constructor of class 'S4'}} expected-error 16 {{calling a private constructor of class 'S5'}}
#pragma omp task firstprivate(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be firstprivate}}
#pragma omp task private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note{{defined as private}}
foo();
diff --git a/test/OpenMP/task_in_reduction_message.cpp b/test/OpenMP/task_in_reduction_message.cpp
index d99d2e42d762..e9bde31ec975 100644
--- a/test/OpenMP/task_in_reduction_message.cpp
+++ b/test/OpenMP/task_in_reduction_message.cpp
@@ -154,23 +154,23 @@ T tmain(T argc) {
#pragma omp task in_reduction(^ : T) // expected-error {{'T' does not refer to a value}}
foo();
#pragma omp taskgroup task_reduction(+:c)
-#pragma omp task in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
+#pragma omp task in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be in_reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
foo();
-#pragma omp task in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp task in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp task in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(+ : ba) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
-#pragma omp task in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(* : ca) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
-#pragma omp task in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(- : da) // expected-error {{const-qualified variable cannot be in_reduction}} expected-error {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp task in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
foo();
#pragma omp task in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp task in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp taskgroup task_reduction(+:k)
#pragma omp task in_reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -183,7 +183,7 @@ T tmain(T argc) {
#pragma omp taskgroup task_reduction(+:p)
#pragma omp task in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note 2 {{previously referenced here}}
foo();
-#pragma omp task in_reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -258,23 +258,23 @@ int main(int argc, char **argv) {
#pragma omp task in_reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
foo();
#pragma omp taskgroup task_reduction(+:c)
-#pragma omp task in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
+#pragma omp task in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be in_reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
foo();
-#pragma omp task in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp task in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp task in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(+ : ba) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
-#pragma omp task in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(* : ca) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
-#pragma omp task in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(- : da) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp task in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp task in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp task in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp task in_reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
foo();
@@ -289,7 +289,7 @@ int main(int argc, char **argv) {
#pragma omp taskgroup task_reduction(+:p)
#pragma omp task in_reduction(+ : p), in_reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note {{previously referenced here}}
foo();
-#pragma omp task in_reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp task in_reduction(+ : r) // expected-error {{const-qualified variable cannot be in_reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/task_messages.cpp b/test/OpenMP/task_messages.cpp
index 832d8fa57d67..d490c7f8ea48 100644
--- a/test/OpenMP/task_messages.cpp
+++ b/test/OpenMP/task_messages.cpp
@@ -8,7 +8,7 @@ void foo() {
#pragma omp task // expected-error {{unexpected OpenMP directive '#pragma omp task'}}
class S {
- S(const S &s) { a = s.a + 12; } // expected-note 10 {{implicitly declared private here}}
+ S(const S &s) { a = s.a + 12; } // expected-note 16 {{implicitly declared private here}}
int a;
public:
@@ -40,21 +40,30 @@ int foo() {
++s1;
#pragma omp task default(none)
#pragma omp task default(shared)
- ++a;
+ ++a; // expected-error 2 {{variable 'a' must have explicitly specified data sharing attributes}}
#pragma omp task default(none)
#pragma omp task
// expected-error@+1 {{calling a private constructor of class 'S'}}
- ++a;
+ ++a; // expected-error 2 {{variable 'a' must have explicitly specified data sharing attributes}}
+#pragma omp task
#pragma omp task
+ // expected-error@+1 {{calling a private constructor of class 'S'}}
+ ++a; // expected-error {{calling a private constructor of class 'S'}}
+#pragma omp task default(shared)
#pragma omp task
// expected-error@+1 {{calling a private constructor of class 'S'}}
++a;
+#pragma omp parallel shared(a)
+#pragma omp task
+#pragma omp task
+ ++a;
+#pragma omp parallel shared(a)
#pragma omp task default(shared)
#pragma omp task
++a;
#pragma omp task
#pragma omp parallel
- ++a;
+ ++a; // expected-error {{calling a private constructor of class 'S'}}
// expected-error@+2 {{calling a private constructor of class 'S'}}
#pragma omp task
++b;
@@ -177,10 +186,10 @@ L2:
#pragma omp task default(none)
#pragma omp task default(shared)
- ++a;
+ ++a; // expected-error {{variable 'a' must have explicitly specified data sharing attributes}}
#pragma omp task default(none)
#pragma omp task
- ++a;
+ ++a; // expected-error {{variable 'a' must have explicitly specified data sharing attributes}}
#pragma omp task default(shared)
#pragma omp task
++a;
@@ -194,21 +203,30 @@ L2:
++a, ++b;
#pragma omp task default(none)
#pragma omp task default(shared)
- ++sa;
+ ++sa; // expected-error {{variable 'sa' must have explicitly specified data sharing attributes}}
#pragma omp task default(none)
#pragma omp task
// expected-error@+1 {{calling a private constructor of class 'S'}}
- ++sa;
+ ++sa; // expected-error {{variable 'sa' must have explicitly specified data sharing attributes}}
#pragma omp task
#pragma omp task
// expected-error@+1 {{calling a private constructor of class 'S'}}
+ ++sa; // expected-error {{calling a private constructor of class 'S'}}
+#pragma omp task default(shared)
+#pragma omp task
+ // expected-error@+1 {{calling a private constructor of class 'S'}}
++sa;
+#pragma omp parallel shared(sa)
+#pragma omp task
+#pragma omp task
+ ++sa;
+#pragma omp parallel shared(sa)
#pragma omp task default(shared)
#pragma omp task
++sa;
#pragma omp task
#pragma omp parallel
- ++sa;
+ ++sa; // expected-error {{calling a private constructor of class 'S'}}
// expected-error@+2 {{calling a private constructor of class 'S'}}
#pragma omp task
++sb;
diff --git a/test/OpenMP/task_private_messages.cpp b/test/OpenMP/task_private_messages.cpp
index 5663a436e43f..2a3df509c250 100644
--- a/test/OpenMP/task_private_messages.cpp
+++ b/test/OpenMP/task_private_messages.cpp
@@ -26,9 +26,9 @@ class S3 {
public:
S3() : a(0) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -61,8 +61,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -75,11 +75,11 @@ int main(int argc, char **argv) {
#pragma omp task private(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
#pragma omp task private(argc argv) // expected-error {{expected ',' or ')' in 'private' clause}}
#pragma omp task private(S1) // expected-error {{'S1' does not refer to a value}}
-#pragma omp task private(a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp task private(a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
#pragma omp task private(argv[1]) // expected-error {{expected variable name}}
#pragma omp task private(ba)
-#pragma omp task private(ca) // expected-error {{shared variable cannot be private}}
-#pragma omp task private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp task private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
+#pragma omp task private(da) // expected-error {{const-qualified variable cannot be private}}
#pragma omp task private(S2::S2s) // expected-error {{shared variable cannot be private}}
#pragma omp task private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
#pragma omp task private(threadvar, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be private}}
diff --git a/test/OpenMP/taskgroup_task_reduction_codegen.cpp b/test/OpenMP/taskgroup_task_reduction_codegen.cpp
index 90b03c653ef0..02a5ba664e5e 100644
--- a/test/OpenMP/taskgroup_task_reduction_codegen.cpp
+++ b/test/OpenMP/taskgroup_task_reduction_codegen.cpp
@@ -43,12 +43,12 @@ int main(int argc, char **argv) {
// CHECK: [[A:%.+]] = alloca i32,
// CHECK: [[B:%.+]] = alloca float,
// CHECK: [[C:%.+]] = alloca [5 x %struct.S],
-// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: [[RD_IN1:%.+]] = alloca [3 x [[T1:%[^,]+]]],
// CHECK: [[TD1:%.+]] = alloca i8*,
// CHECK: [[RD_IN2:%.+]] = alloca [2 x [[T2:%[^,]+]]],
// CHECK: [[TD2:%.+]] = alloca i8*,
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: [[VLA:%.+]] = alloca i16, i64 [[VLA_SIZE:%[^,]+]],
// CHECK: call void @__kmpc_taskgroup(%struct.ident_t* {{[^,]+}}, i32 [[GTID]])
diff --git a/test/OpenMP/taskgroup_task_reduction_messages.cpp b/test/OpenMP/taskgroup_task_reduction_messages.cpp
index 59ff2190bb9e..56abe2abe667 100644
--- a/test/OpenMP/taskgroup_task_reduction_messages.cpp
+++ b/test/OpenMP/taskgroup_task_reduction_messages.cpp
@@ -116,23 +116,23 @@ T tmain(T argc) {
foo();
#pragma omp taskgroup task_reduction(^ : T) // expected-error {{'T' does not refer to a value}}
foo();
-#pragma omp taskgroup task_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp taskgroup task_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be task_reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp taskgroup task_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'task_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'task_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp taskgroup task_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp taskgroup task_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(+ : ba) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
-#pragma omp taskgroup task_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(* : ca) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
-#pragma omp taskgroup task_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(- : da) // expected-error {{const-qualified variable cannot be task_reduction}} expected-error {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp taskgroup task_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp taskgroup task_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp taskgroup task_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp taskgroup task_reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
foo();
@@ -143,7 +143,7 @@ T tmain(T argc) {
foo();
#pragma omp taskgroup task_reduction(+ : p), task_reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'task_reduction' clause}} expected-note 2 {{previously referenced here}}
foo();
-#pragma omp taskgroup task_reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -209,23 +209,23 @@ int main(int argc, char **argv) {
foo();
#pragma omp taskgroup task_reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
foo();
-#pragma omp taskgroup task_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp taskgroup task_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be task_reduction}} expected-error {{'operator+' is a private member of 'S2'}}
foo();
-#pragma omp taskgroup task_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'task_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'task_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp taskgroup task_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
-#pragma omp taskgroup task_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(+ : ba) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
-#pragma omp taskgroup task_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(* : ca) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
-#pragma omp taskgroup task_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(- : da) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp taskgroup task_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
foo();
#pragma omp taskgroup task_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
-#pragma omp taskgroup task_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp taskgroup task_reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
foo();
@@ -238,7 +238,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp taskgroup task_reduction(+ : p), task_reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'task_reduction' clause}} expected-note {{previously referenced here}}
foo();
-#pragma omp taskgroup task_reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskgroup task_reduction(+ : r) // expected-error {{const-qualified variable cannot be task_reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/taskloop_codegen.cpp b/test/OpenMP/taskloop_codegen.cpp
index 82b8e1b292bd..6471f5741f66 100644
--- a/test/OpenMP/taskloop_codegen.cpp
+++ b/test/OpenMP/taskloop_codegen.cpp
@@ -28,7 +28,7 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 0, i64 0, i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 0, i64 0, i8* null)
// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
#pragma omp taskloop priority(argc)
for (int i = 0; i < 10; ++i)
@@ -44,12 +44,12 @@ int main(int argc, char **argv) {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[GRAINSIZE:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 1, i64 [[GRAINSIZE]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 1, i64 [[GRAINSIZE]], i8* null)
#pragma omp taskloop nogroup grainsize(argc)
for (int i = 0; i < 10; ++i)
;
// CHECK: call void @__kmpc_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
-// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 24, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK3:@.+]] to i32 (i32, i8*)*))
+// CHECK: [[TASKV:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i32 1, i64 80, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, [[TDP_TY:%.+]]*)* [[TASK3:@.+]] to i32 (i32, i8*)*))
// CHECK: [[TASK:%.+]] = bitcast i8* [[TASKV]] to [[TDP_TY]]*
// CHECK: [[TASK_DATA:%.+]] = getelementptr inbounds [[TDP_TY]], [[TDP_TY]]* [[TASK]], i32 0, i32 0
// CHECK: [[IF:%.+]] = icmp ne i32 %{{.+}}, 0
@@ -61,7 +61,7 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 4, i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 2, i64 4, i8* null)
// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
int i;
#pragma omp taskloop if(argc) shared(argc, argv) collapse(2) num_tasks(4)
@@ -164,7 +164,7 @@ struct S {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[NUM_TASKS:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 [[NUM_TASKS]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 2, i64 [[NUM_TASKS]], i8* null)
#pragma omp taskloop shared(c) num_tasks(a)
for (a = 0; a < c; ++a)
;
diff --git a/test/OpenMP/taskloop_firstprivate_codegen.cpp b/test/OpenMP/taskloop_firstprivate_codegen.cpp
index d617835299cc..8f3b2468ffef 100644
--- a/test/OpenMP/taskloop_firstprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_firstprivate_codegen.cpp
@@ -77,7 +77,7 @@ int main() {
// LAMBDA: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_ADDR_REF]]
// LAMBDA: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
-// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// LAMBDA: ret
#pragma omp taskloop firstprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -120,7 +120,7 @@ int main() {
// BLOCKS: [[SIVAR_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
// BLOCKS: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_ADDR_REF]]
// BLOCKS: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
- // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+ // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// BLOCKS: ret
#pragma omp taskloop firstprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -253,7 +253,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// CHECK: = call i{{.+}} [[TMAIN_INT:@.+]]()
@@ -416,7 +416,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
// No destructors must be called for private copies of s_arr and var.
// CHECK-NOT: getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
diff --git a/test/OpenMP/taskloop_firstprivate_messages.cpp b/test/OpenMP/taskloop_firstprivate_messages.cpp
index 7e1b818800da..a34d9bcd82b2 100644
--- a/test/OpenMP/taskloop_firstprivate_messages.cpp
+++ b/test/OpenMP/taskloop_firstprivate_messages.cpp
@@ -297,9 +297,12 @@ int main(int argc, char **argv) {
#pragma omp taskloop firstprivate(i) // expected-note {{defined as firstprivate}}
for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop' directive may not be firstprivate, predetermined as private}}
foo();
-#pragma omp parallel reduction(+ : i) // expected-note 2 {{defined as reduction}}
+#pragma omp parallel reduction(+ : i) // expected-note {{defined as reduction}}
#pragma omp taskloop firstprivate(i) //expected-error {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
- for (i = 0; i < argc; ++i) // expected-error {{reduction variables may not be accessed in an explicit task}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp taskloop firstprivate(i) //expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop' directive may not be firstprivate, predetermined as private}}
foo();
#pragma omp parallel
#pragma omp taskloop firstprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
diff --git a/test/OpenMP/taskloop_in_reduction_messages.cpp b/test/OpenMP/taskloop_in_reduction_messages.cpp
index dc19bac907d5..177217888e0b 100644
--- a/test/OpenMP/taskloop_in_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_in_reduction_messages.cpp
@@ -171,22 +171,22 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskgroup task_reduction(+:c)
-#pragma omp taskloop in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
+#pragma omp taskloop in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be in_reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(+ : ba) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(* : ca) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(- : da) // expected-error {{const-qualified variable cannot be in_reduction}} expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
@@ -195,7 +195,7 @@ T tmain(T argc) {
#pragma omp taskloop in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskgroup task_reduction(+:k)
@@ -213,7 +213,7 @@ T tmain(T argc) {
#pragma omp taskloop in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -306,22 +306,22 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskgroup task_reduction(+:c)
-#pragma omp taskloop in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
+#pragma omp taskloop in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be in_reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(+ : ba) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(* : ca) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(- : da) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -330,7 +330,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop in_reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -351,7 +351,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop in_reduction(+ : p), in_reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop in_reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop in_reduction(+ : r) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/taskloop_lastprivate_codegen.cpp b/test/OpenMP/taskloop_lastprivate_codegen.cpp
index a6f7abcc338b..fa1549d7fcb0 100644
--- a/test/OpenMP/taskloop_lastprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_lastprivate_codegen.cpp
@@ -68,7 +68,7 @@ int main() {
// LAMBDA: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
-// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// LAMBDA: ret
#pragma omp taskloop lastprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -108,7 +108,7 @@ int main() {
// BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
// BLOCKS: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
- // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+ // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// BLOCKS: ret
#pragma omp taskloop lastprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -226,7 +226,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// CHECK: = call i{{.+}} [[TMAIN_INT:@.+]]()
@@ -400,7 +400,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
// No destructors must be called for private copies of s_arr and var.
// CHECK-NOT: getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
diff --git a/test/OpenMP/taskloop_lastprivate_messages.cpp b/test/OpenMP/taskloop_lastprivate_messages.cpp
index 85aaa00c8189..c46a1f0c4c1c 100644
--- a/test/OpenMP/taskloop_lastprivate_messages.cpp
+++ b/test/OpenMP/taskloop_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -156,8 +156,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -197,7 +197,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp taskloop lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
@@ -213,11 +213,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp taskloop lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp taskloop lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -230,7 +230,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp taskloop lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
diff --git a/test/OpenMP/taskloop_loop_messages.cpp b/test/OpenMP/taskloop_loop_messages.cpp
index 4ce83b4ae1ae..324114d6d745 100644
--- a/test/OpenMP/taskloop_loop_messages.cpp
+++ b/test/OpenMP/taskloop_loop_messages.cpp
@@ -131,8 +131,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp parallel
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
#pragma omp taskloop
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/taskloop_private_codegen.cpp b/test/OpenMP/taskloop_private_codegen.cpp
index 21ffcba97d9e..8e2c13c40d94 100644
--- a/test/OpenMP/taskloop_private_codegen.cpp
+++ b/test/OpenMP/taskloop_private_codegen.cpp
@@ -65,7 +65,7 @@ int main() {
// LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
// LAMBDA: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
-// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// LAMBDA: ret
#pragma omp taskloop private(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -101,7 +101,7 @@ int main() {
// BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
// BLOCKS: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
- // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+ // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// BLOCKS: ret
#pragma omp taskloop private(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -193,7 +193,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// CHECK: call i32 @__kmpc_omp_task([[LOC]], i32 [[GTID]], i8*
// CHECK: = call i{{.+}} [[TMAIN_INT:@.+]]()
@@ -324,7 +324,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
// No destructors must be called for private copies of s_arr and var.
// CHECK-NOT: getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
diff --git a/test/OpenMP/taskloop_reduction_codegen.cpp b/test/OpenMP/taskloop_reduction_codegen.cpp
index 65bc50a4d255..0eff06d88678 100644
--- a/test/OpenMP/taskloop_reduction_codegen.cpp
+++ b/test/OpenMP/taskloop_reduction_codegen.cpp
@@ -52,11 +52,11 @@ sum = 0.0;
// CHECK: [[C:%.*]] = alloca [100 x %struct.S],
// CHECK: [[D:%.*]] = alloca float*,
// CHECK: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]],
-// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: [[DOTRD_INPUT_:%.*]] = alloca [4 x %struct.kmp_task_red_input_t],
// CHECK: alloca i32,
// CHECK: [[DOTCAPTURE_EXPR_:%.*]] = alloca i32,
// CHECK: [[DOTCAPTURE_EXPR_9:%.*]] = alloca i32,
+// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: store i32 0, i32* [[RETVAL]],
// CHECK: store i32 [[ARGC:%.*]], i32* [[ARGC_ADDR]],
// CHECK: store i8** [[ARGV:%.*]], i8*** [[ARGV_ADDR]],
@@ -147,8 +147,8 @@ sum = 0.0;
// CHECK: [[DIV:%.*]] = sdiv i32 [[ADD11]], 1
// CHECK: [[SUB12:%.*]] = sub nsw i32 [[DIV]], 1
// CHECK: store i32 [[SUB12]], i32* [[DOTCAPTURE_EXPR_9]],
-// CHECK: [[TMP65:%.*]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i32 1, i64 888, i64 72, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* @[[TASK:.+]] to i32 (i32, i8*)*))
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// CHECK: [[TMP65:%.*]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i32 1, i64 888, i64 64, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* @[[TASK:.+]] to i32 (i32, i8*)*))
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t*
// CHECK: ret i32
diff --git a/test/OpenMP/taskloop_reduction_messages.cpp b/test/OpenMP/taskloop_reduction_messages.cpp
index c83a8b30c52c..4794c7a2d005 100644
--- a/test/OpenMP/taskloop_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_reduction_messages.cpp
@@ -139,22 +139,22 @@ T tmain(T argc) {
#pragma omp taskloop reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp taskloop reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -163,7 +163,7 @@ T tmain(T argc) {
#pragma omp taskloop reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -182,7 +182,7 @@ T tmain(T argc) {
#pragma omp taskloop reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -261,22 +261,22 @@ int main(int argc, char **argv) {
#pragma omp taskloop reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp taskloop reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -285,7 +285,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -307,7 +307,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/taskloop_simd_codegen.cpp b/test/OpenMP/taskloop_simd_codegen.cpp
index d3efec5ee441..4c84eccb4f85 100644
--- a/test/OpenMP/taskloop_simd_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_codegen.cpp
@@ -24,7 +24,7 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 0, i64 0, i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 0, i64 0, i8* null)
// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
#pragma omp taskloop simd priority(argc)
for (int i = 0; i < 10; ++i)
@@ -40,7 +40,7 @@ int main(int argc, char **argv) {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[GRAINSIZE:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 1, i64 [[GRAINSIZE]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 1, i64 [[GRAINSIZE]], i8* null)
#pragma omp taskloop simd nogroup grainsize(argc) simdlen(4)
for (int i = 0; i < 10; ++i)
;
@@ -57,7 +57,7 @@ int main(int argc, char **argv) {
// CHECK: [[ST:%.+]] = getelementptr inbounds [[TD_TY]], [[TD_TY]]* [[TASK_DATA]], i32 0, i32 7
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 4, i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 [[IF_INT]], i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 2, i64 4, i8* null)
// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t* [[DEFLOC]], i32 [[GTID]])
int i;
#pragma omp taskloop simd if(argc) shared(argc, argv) collapse(2) num_tasks(4) safelen(32)
@@ -83,17 +83,17 @@ int main(int argc, char **argv) {
// CHECK: [[LB_I32:%.+]] = trunc i64 [[LB_VAL]] to i32
// CHECK: store i32 [[LB_I32]], i32* [[CNT:%.+]],
// CHECK: br label
-// CHECK: [[VAL:%.+]] = load i32, i32* [[CNT]],{{.*}}!llvm.mem.parallel_loop_access [[LOOP1:!.+]]
+// CHECK: [[VAL:%.+]] = load i32, i32* [[CNT]],{{.*}}!llvm.access.group
// CHECK: [[VAL_I64:%.+]] = sext i32 [[VAL]] to i64
-// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],{{.*}}!llvm.mem.parallel_loop_access [[LOOP1]]
+// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],{{.*}}!llvm.access.group
// CHECK: [[CMP:%.+]] = icmp ule i64 [[VAL_I64]], [[UB_VAL]]
// CHECK: br i1 [[CMP]], label %{{.+}}, label %{{.+}}
-// CHECK: load i32, i32* %{{.*}}!llvm.mem.parallel_loop_access [[LOOP1]]
-// CHECK: store i32 %{{.*}}!llvm.mem.parallel_loop_access [[LOOP1]]
-// CHECK: load i32, i32* %{{.*}}!llvm.mem.parallel_loop_access [[LOOP1]]
+// CHECK: load i32, i32* %{{.*}}!llvm.access.group
+// CHECK: store i32 %{{.*}}!llvm.access.group
+// CHECK: load i32, i32* %{{.*}}!llvm.access.group
// CHECK: add nsw i32 %{{.+}}, 1
-// CHECK: store i32 %{{.+}}, i32* %{{.*}}!llvm.mem.parallel_loop_access [[LOOP1]]
-// CHECK: br label %{{.*}}!llvm.loop [[LOOP1]]
+// CHECK: store i32 %{{.+}}, i32* %{{.*}}!llvm.access.group
+// CHECK: br label %{{.*}}!llvm.loop
// CHECK: ret i32 0
// CHECK: define internal i32 [[TASK2]](
@@ -113,17 +113,17 @@ int main(int argc, char **argv) {
// CHECK: [[LB_I32:%.+]] = trunc i64 [[LB_VAL]] to i32
// CHECK: store i32 [[LB_I32]], i32* [[CNT:%.+]],
// CHECK: br label
-// CHECK: [[VAL:%.+]] = load i32, i32* [[CNT]],{{.*}}!llvm.mem.parallel_loop_access [[LOOP2:!.+]]
+// CHECK: [[VAL:%.+]] = load i32, i32* [[CNT]],{{.*}}!llvm.access.group
// CHECK: [[VAL_I64:%.+]] = sext i32 [[VAL]] to i64
-// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],{{.*}}!llvm.mem.parallel_loop_access [[LOOP2]]
+// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],{{.*}}!llvm.access.group
// CHECK: [[CMP:%.+]] = icmp ule i64 [[VAL_I64]], [[UB_VAL]]
// CHECK: br i1 [[CMP]], label %{{.+}}, label %{{.+}}
-// CHECK: load i32, i32* %{{.*}}!llvm.mem.parallel_loop_access [[LOOP2]]
-// CHECK: store i32 %{{.*}}!llvm.mem.parallel_loop_access [[LOOP2]]
-// CHECK: load i32, i32* %{{.*}}!llvm.mem.parallel_loop_access [[LOOP2]]
+// CHECK: load i32, i32* %{{.*}}!llvm.access.group
+// CHECK: store i32 %{{.*}}!llvm.access.group
+// CHECK: load i32, i32* %{{.*}}!llvm.access.group
// CHECK: add nsw i32 %{{.+}}, 1
-// CHECK: store i32 %{{.+}}, i32* %{{.*}}!llvm.mem.parallel_loop_access [[LOOP2]]
-// CHECK: br label %{{.*}}!llvm.loop [[LOOP2]]
+// CHECK: store i32 %{{.+}}, i32* %{{.*}}!llvm.access.group
+// CHECK: br label %{{.*}}!llvm.loop
// CHECK: ret i32 0
// CHECK: define internal i32 [[TASK3]](
@@ -142,7 +142,7 @@ int main(int argc, char **argv) {
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
// CHECK: store i64 [[LB_VAL]], i64* [[CNT:%.+]],
// CHECK: br label
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: br label %{{.*}}!llvm.loop
// CHECK: ret i32 0
@@ -162,7 +162,7 @@ struct S {
// CHECK: store i64 1, i64* [[ST]],
// CHECK: [[ST_VAL:%.+]] = load i64, i64* [[ST]],
// CHECK: [[NUM_TASKS:%.+]] = zext i32 %{{.+}} to i64
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 0, i32 2, i64 [[NUM_TASKS]], i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* [[DEFLOC]], i32 [[GTID]], i8* [[TASKV]], i32 1, i64* [[DOWN]], i64* [[UP]], i64 [[ST_VAL]], i32 1, i32 2, i64 [[NUM_TASKS]], i8* null)
#pragma omp taskloop simd shared(c) num_tasks(a) simdlen(8) safelen(64)
for (a = 0; a < c; ++a)
;
@@ -192,14 +192,14 @@ struct S {
// CHECK: [[CMP:%.+]] = icmp ule i64 [[VAL_I64]], [[UB_VAL]]
// CHECK: br i1 [[CMP]], label %{{.+}}, label %{{.+}}
// CHECK: load i32, i32* %
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: store i32 %
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: load i32, i32* %
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: add nsw i32 %{{.+}}, 1
// CHECK: store i32 %{{.+}}, i32* %
-// CHECK-NOT: !llvm.mem.parallel_loop_access
+// CHECK-NOT: !llvm.access.group
// CHECK: br label %{{.*}}!llvm.loop
// CHECK: ret i32 0
diff --git a/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp b/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
index 4f406b2a583a..b7e8ba987403 100644
--- a/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
@@ -77,7 +77,7 @@ int main() {
// LAMBDA: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_ADDR_REF]]
// LAMBDA: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
-// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// LAMBDA: ret
#pragma omp taskloop simd firstprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -120,7 +120,7 @@ int main() {
// BLOCKS: [[SIVAR_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
// BLOCKS: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_ADDR_REF]]
// BLOCKS: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
- // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+ // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// BLOCKS: ret
#pragma omp taskloop simd firstprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -253,7 +253,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// CHECK: = call i{{.+}} [[TMAIN_INT:@.+]]()
@@ -416,7 +416,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
// No destructors must be called for private copies of s_arr and var.
// CHECK-NOT: getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
diff --git a/test/OpenMP/taskloop_simd_firstprivate_messages.cpp b/test/OpenMP/taskloop_simd_firstprivate_messages.cpp
index 66c9e7a2f8ff..3fb5ad17064d 100644
--- a/test/OpenMP/taskloop_simd_firstprivate_messages.cpp
+++ b/test/OpenMP/taskloop_simd_firstprivate_messages.cpp
@@ -301,6 +301,9 @@ int main(int argc, char **argv) {
#pragma omp taskloop simd firstprivate(i) // expected-error {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
for (i = 0; i < argc; ++i) // expected-error {{reduction variables may not be accessed in an explicit task}}
foo();
+#pragma omp taskloop simd firstprivate(i) //expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop simd' directive may not be firstprivate, predetermined as linear}}
+ foo();
#pragma omp parallel
#pragma omp taskloop simd firstprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
for (i = 0; i < argc; ++i)
diff --git a/test/OpenMP/taskloop_simd_in_reduction_messages.cpp b/test/OpenMP/taskloop_simd_in_reduction_messages.cpp
index ee3d09376610..5fa976b22952 100644
--- a/test/OpenMP/taskloop_simd_in_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_simd_in_reduction_messages.cpp
@@ -171,22 +171,22 @@ T tmain(T argc) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskgroup task_reduction(+:c)
-#pragma omp taskloop simd in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
+#pragma omp taskloop simd in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be in_reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(+ : ba) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(* : ca) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(- : da) // expected-error {{const-qualified variable cannot be in_reduction}} expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
@@ -195,7 +195,7 @@ T tmain(T argc) {
#pragma omp taskloop simd in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskgroup task_reduction(+:k)
@@ -213,7 +213,7 @@ T tmain(T argc) {
#pragma omp taskloop simd in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -306,22 +306,22 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskgroup task_reduction(+:c)
-#pragma omp taskloop simd in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
+#pragma omp taskloop simd in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be in_reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(+ : ba) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(* : ca) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(- : da) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -330,7 +330,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop simd in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd in_reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -351,7 +351,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop simd in_reduction(+ : p), in_reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd in_reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd in_reduction(+ : r) // expected-error {{const-qualified variable cannot be in_reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp b/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
index be484465e3ae..750bf97885af 100644
--- a/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
@@ -68,7 +68,7 @@ int main() {
// LAMBDA: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
-// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// LAMBDA: ret
#pragma omp taskloop simd lastprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -108,7 +108,7 @@ int main() {
// BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
// BLOCKS: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
- // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+ // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY:%[^*]+]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// BLOCKS: ret
#pragma omp taskloop simd lastprivate(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -226,7 +226,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// CHECK: = call i{{.+}} [[TMAIN_INT:@.+]]()
@@ -400,7 +400,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
// No destructors must be called for private copies of s_arr and var.
// CHECK-NOT: getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
diff --git a/test/OpenMP/taskloop_simd_lastprivate_messages.cpp b/test/OpenMP/taskloop_simd_lastprivate_messages.cpp
index 8f418ff3b883..3ed65de247e1 100644
--- a/test/OpenMP/taskloop_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/taskloop_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -156,8 +156,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -197,7 +197,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp taskloop simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
@@ -213,11 +213,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp taskloop simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp taskloop simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
int xa;
@@ -230,7 +230,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
-#pragma omp taskloop simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp taskloop simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i)
foo();
#pragma omp parallel
diff --git a/test/OpenMP/taskloop_simd_linear_messages.cpp b/test/OpenMP/taskloop_simd_linear_messages.cpp
index 2aea6a041fce..645026c9facc 100644
--- a/test/OpenMP/taskloop_simd_linear_messages.cpp
+++ b/test/OpenMP/taskloop_simd_linear_messages.cpp
@@ -132,7 +132,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp taskloop simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp taskloop simd linear (val(a, b):B::ib)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp taskloop simd linear (argv[1]) // expected-error {{expected variable name}}
@@ -221,7 +221,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop simd linear (S1) // expected-error {{'S1' does not refer to a value}}
for (int k = 0; k < argc; ++k) ++k;
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
- // expected-error@+1 {{const-qualified variable cannot be linear}}
+ // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
#pragma omp taskloop simd linear(a, b)
for (int k = 0; k < argc; ++k) ++k;
#pragma omp taskloop simd linear (argv[1]) // expected-error {{expected variable name}}
diff --git a/test/OpenMP/taskloop_simd_loop_messages.cpp b/test/OpenMP/taskloop_simd_loop_messages.cpp
index 71aa9dfe1143..fcae0130d96c 100644
--- a/test/OpenMP/taskloop_simd_loop_messages.cpp
+++ b/test/OpenMP/taskloop_simd_loop_messages.cpp
@@ -131,8 +131,8 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp parallel
-// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
#pragma omp taskloop simd
for (int i = 0; i != 1; i++)
c[i] = a[i];
diff --git a/test/OpenMP/taskloop_simd_private_codegen.cpp b/test/OpenMP/taskloop_simd_private_codegen.cpp
index fd0820ad84a6..c6e1df9cc0a7 100644
--- a/test/OpenMP/taskloop_simd_private_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_private_codegen.cpp
@@ -65,7 +65,7 @@ int main() {
// LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
// LAMBDA: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
-// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// LAMBDA: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// LAMBDA: ret
#pragma omp taskloop simd private(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -101,7 +101,7 @@ int main() {
// BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
// BLOCKS: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 96, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
- // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+ // BLOCKS: call void @__kmpc_taskloop(%{{.+}}* @{{.+}}, i32 %{{.+}}, i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// BLOCKS: ret
#pragma omp taskloop simd private(g, sivar)
for (int i = 0; i < 10; ++i) {
@@ -193,7 +193,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_MAIN_TY]]*, [[KMP_TASK_MAIN_TY]]*, i32)* [[MAIN_DUP:@.+]] to i8*))
// CHECK: call i32 @__kmpc_omp_task([[LOC]], i32 [[GTID]], i8*
// CHECK: = call i{{.+}} [[TMAIN_INT:@.+]]()
@@ -324,7 +324,7 @@ int main() {
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_PTR]],
// Start task.
-// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
+// CHECK: call void @__kmpc_taskloop([[LOC]], i32 [[GTID]], i8* [[RES]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* bitcast (void ([[KMP_TASK_TMAIN_TY]]*, [[KMP_TASK_TMAIN_TY]]*, i32)* [[TMAIN_DUP:@.+]] to i8*))
// No destructors must be called for private copies of s_arr and var.
// CHECK-NOT: getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
diff --git a/test/OpenMP/taskloop_simd_reduction_codegen.cpp b/test/OpenMP/taskloop_simd_reduction_codegen.cpp
index 6c34e34ca584..37a60c8b6755 100644
--- a/test/OpenMP/taskloop_simd_reduction_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_reduction_codegen.cpp
@@ -52,11 +52,11 @@ sum = 0.0;
// CHECK: [[C:%.*]] = alloca [100 x %struct.S],
// CHECK: [[D:%.*]] = alloca float*,
// CHECK: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]],
-// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: [[DOTRD_INPUT_:%.*]] = alloca [4 x %struct.kmp_task_red_input_t],
// CHECK: alloca i32,
// CHECK: [[DOTCAPTURE_EXPR_:%.*]] = alloca i32,
// CHECK: [[DOTCAPTURE_EXPR_9:%.*]] = alloca i32,
+// CHECK: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t*
// CHECK: store i32 0, i32* [[RETVAL]],
// CHECK: store i32 [[ARGC:%.*]], i32* [[ARGC_ADDR]],
// CHECK: store i8** [[ARGV:%.*]], i8*** [[ARGV_ADDR]],
@@ -148,7 +148,7 @@ sum = 0.0;
// CHECK: [[SUB12:%.*]] = sub nsw i32 [[DIV]], 1
// CHECK: store i32 [[SUB12]], i32* [[DOTCAPTURE_EXPR_9]],
// CHECK: [[TMP65:%.*]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i32 1, i64 888, i64 72, i32 (i32, i8*)* bitcast (i32 (i32, %struct.kmp_task_t_with_privates*)* @{{.+}} to i32 (i32, i8*)*))
-// CHECK: call void @__kmpc_taskloop(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 0, i32 0, i64 0, i8* null)
+// CHECK: call void @__kmpc_taskloop(%struct.ident_t* %{{.+}}, i32 [[TMP0]], i8* [[TMP65]], i32 1, i64* %{{.+}}, i64* %{{.+}}, i64 %{{.+}}, i32 1, i32 0, i64 0, i8* null)
// CHECK: call void @__kmpc_end_taskgroup(%struct.ident_t*
// CHECK: ret i32
diff --git a/test/OpenMP/taskloop_simd_reduction_messages.cpp b/test/OpenMP/taskloop_simd_reduction_messages.cpp
index 10ee5ce8c83c..fb279e28b84f 100644
--- a/test/OpenMP/taskloop_simd_reduction_messages.cpp
+++ b/test/OpenMP/taskloop_simd_reduction_messages.cpp
@@ -139,22 +139,22 @@ T tmain(T argc) {
#pragma omp taskloop simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp taskloop simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -163,7 +163,7 @@ T tmain(T argc) {
#pragma omp taskloop simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -182,7 +182,7 @@ T tmain(T argc) {
#pragma omp taskloop simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
@@ -261,22 +261,22 @@ int main(int argc, char **argv) {
#pragma omp taskloop simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp taskloop simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -285,7 +285,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp taskloop simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -307,7 +307,7 @@ int main(int argc, char **argv) {
#pragma omp taskloop simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int i = 0; i < 10; ++i)
foo();
-#pragma omp taskloop simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp taskloop simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int i = 0; i < 10; ++i)
foo();
#pragma omp parallel shared(i)
diff --git a/test/OpenMP/teams_codegen.cpp b/test/OpenMP/teams_codegen.cpp
index 057c55788319..681777717126 100644
--- a/test/OpenMP/teams_codegen.cpp
+++ b/test/OpenMP/teams_codegen.cpp
@@ -266,7 +266,7 @@ int teams_template_struct(void) {
// CK4-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CK4-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CK4-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CK4-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CK4-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;main;[[@LINE+14]];9;;\00"
// CK4-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;tmain;[[@LINE+7]];9;;\00"
@@ -327,7 +327,7 @@ int main (int argc, char **argv) {
// CK5-DAG: %struct.ident_t = type { i32, i32, i32, i32, i8* }
// CK5-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CK5-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CK5-DAG: [[DEF_LOC_0:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CK5-DEBUG-DAG: [[LOC1:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;main;[[@LINE+14]];9;;\00"
// CK5-DEBUG-DAG: [[LOC2:@.+]] = private unnamed_addr constant [{{.+}} x i8] c";{{.*}}teams_codegen.cpp;tmain;[[@LINE+7]];9;;\00"
diff --git a/test/OpenMP/teams_default_messages.cpp b/test/OpenMP/teams_default_messages.cpp
index daf48ae56204..c032f5e482cd 100644
--- a/test/OpenMP/teams_default_messages.cpp
+++ b/test/OpenMP/teams_default_messages.cpp
@@ -31,6 +31,6 @@ int main(int argc, char **argv) {
#pragma omp target
#pragma omp teams default(none)
#pragma omp parallel default(shared)
- ++argc;
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
return 0;
}
diff --git a/test/OpenMP/teams_distribute_ast_print.cpp b/test/OpenMP/teams_distribute_ast_print.cpp
index ef07d51b5a9d..8868802bbcdf 100644
--- a/test/OpenMP/teams_distribute_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/teams_distribute_codegen.cpp b/test/OpenMP/teams_distribute_codegen.cpp
index 0f6b5f2f25e1..ea299bc346a6 100644
--- a/test/OpenMP/teams_distribute_codegen.cpp
+++ b/test/OpenMP/teams_distribute_codegen.cpp
@@ -21,15 +21,19 @@
int a[100];
// CK1: define {{.*}}i32 @{{.+}}teams_argument_globali(
-int teams_argument_global(int n){
+int teams_argument_global(int n){
int te = n / 128;
int th = 128;
// discard n_addr
// CK1: alloca i32,
// CK1: [[TE:%.+]] = alloca i32,
// CK1: [[TH:%.+]] = alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
// CK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
// CK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+ // CK1: call void @__kmpc_push_target_tripcount(i64 -1, i64 %{{.+}})
// CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
// CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]],
diff --git a/test/OpenMP/teams_distribute_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_lastprivate_messages.cpp
index d5e1a1c94cd0..a6440b7b6d94 100644
--- a/test/OpenMP/teams_distribute_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -152,8 +152,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
@@ -209,11 +209,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -226,7 +226,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_loop_messages.cpp b/test/OpenMP/teams_distribute_loop_messages.cpp
index 13f39d100aa5..a96d86d7d6af 100644
--- a/test/OpenMP/teams_distribute_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_loop_messages.cpp
@@ -126,9 +126,9 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target
#pragma omp teams distribute
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
for (int i = 0; i != 1; i++)
c[i] = a[i];
@@ -414,7 +414,7 @@ int test_with_random_access_iterator() {
Iter0 begin0, end0;
#pragma omp target
#pragma omp teams distribute
- for (GoodIter I = begin; I < end; ++I)
+ for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute
@@ -423,31 +423,31 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute
- for (GoodIter I = begin; I >= end; --I)
+ for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(begin); I < end; ++I)
+ for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(nullptr); I < end; ++I)
+ for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(0); I < end; ++I)
+ for (GoodIter I(0); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(1, 2); I < end; ++I)
+ for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute
- for (begin = GoodIter(0); begin < end; ++begin)
+ for (begin = GoodIter(0); begin < end; ++begin) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute
@@ -462,7 +462,7 @@ int test_with_random_access_iterator() {
++begin;
#pragma omp target
#pragma omp teams distribute
- for (begin = end; begin < end; ++begin)
+ for (begin = end; begin < end; ++begin) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute
@@ -487,7 +487,7 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute
- for (GoodIter I = begin; I >= end; I = I - 1)
+ for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute
@@ -549,19 +549,19 @@ public:
#pragma omp teams distribute
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I < end; I = I + ST) {
+ for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I <= end; I += ST) {
+ for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute
- for (IT I = begin; I < end; ++I) {
+ for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -597,7 +597,7 @@ int dotest_gt(IT begin, IT end) {
#pragma omp target
#pragma omp teams distribute
- for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -606,7 +606,7 @@ void test_with_template() {
GoodIter begin, end;
TC<GoodIter, 100> t1;
TC<GoodIter, -100> t2;
- t1.dotest_lt(begin, end);
+ t1.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, 100>::dotest_lt' requested here}}
t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
dotest_gt<unsigned, 10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, 10>' requested here}}
diff --git a/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp b/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
index 246382daff4f..50d7b59fd906 100644
--- a/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
index 865ea129f979..fa425b3ecab0 100644
--- a/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
@@ -28,8 +28,12 @@ int teams_argument_global(int n){
// CK1: alloca i32,
// CK1: [[TE:%.+]] = alloca i32,
// CK1: [[TH:%.+]] = alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
// CK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
// CK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+ // CK1: call void @__kmpc_push_target_tripcount(i64 -1, i64 %{{.+}})
// CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
// CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]],
// CK1: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 {{.+}}, i32 {{.+}})
diff --git a/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
index 97e9e4f822f0..14b7e8be2a2c 100644
--- a/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -152,8 +152,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
@@ -209,11 +209,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -226,7 +226,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
index 0fd3fa263ad2..42dc92e3ceca 100644
--- a/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
@@ -126,9 +126,9 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target
#pragma omp teams distribute parallel for
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
for (int i = 0; i != 1; i++)
c[i] = a[i];
@@ -412,7 +412,7 @@ int test_with_random_access_iterator() {
Iter0 begin0, end0;
#pragma omp target
#pragma omp teams distribute parallel for
- for (GoodIter I = begin; I < end; ++I)
+ for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for
@@ -421,31 +421,31 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute parallel for
- for (GoodIter I = begin; I >= end; --I)
+ for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(begin); I < end; ++I)
+ for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(nullptr); I < end; ++I)
+ for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(0); I < end; ++I)
+ for (GoodIter I(0); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(1, 2); I < end; ++I)
+ for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for
- for (begin = GoodIter(0); begin < end; ++begin)
+ for (begin = GoodIter(0); begin < end; ++begin) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute parallel for
@@ -460,7 +460,7 @@ int test_with_random_access_iterator() {
++begin;
#pragma omp target
#pragma omp teams distribute parallel for
- for (begin = end; begin < end; ++begin)
+ for (begin = end; begin < end; ++begin) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute parallel for
@@ -485,7 +485,7 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute parallel for
- for (GoodIter I = begin; I >= end; I = I - 1)
+ for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for
@@ -547,19 +547,19 @@ public:
#pragma omp teams distribute parallel for
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I < end; I = I + ST) {
+ for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute parallel for
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I <= end; I += ST) {
+ for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute parallel for
- for (IT I = begin; I < end; ++I) {
+ for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -595,7 +595,7 @@ int dotest_gt(IT begin, IT end) {
#pragma omp target
#pragma omp teams distribute parallel for
- for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -604,7 +604,7 @@ void test_with_template() {
GoodIter begin, end;
TC<GoodIter, 100> t1;
TC<GoodIter, -100> t2;
- t1.dotest_lt(begin, end);
+ t1.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, 100>::dotest_lt' requested here}}
t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
dotest_gt<unsigned, 10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, 10>' requested here}}
diff --git a/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
index ea4afa1418cb..0f93fe219aae 100644
--- a/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
@@ -15,7 +15,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[S_TY:%.+]] = type { [[INTPTR_T_TY:i[0-9]+]], [[INTPTR_T_TY]], [[INTPTR_T_TY]] }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
index 5fda1a96e41e..ba9e0774371e 100644
--- a/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -85,7 +85,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute parallel for private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp teams distribute parallel for private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -97,11 +97,11 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute parallel for private(ca) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute parallel for private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute parallel for private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute parallel for private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
index 0c242f851b7d..0b7f3b2d8c62 100644
--- a/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
@@ -16,7 +16,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
index 31a91a862f69..5eb69fd00b80 100644
--- a/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
@@ -125,22 +125,22 @@ T tmain(T argc) {
#pragma omp teams distribute parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -149,7 +149,7 @@ T tmain(T argc) {
#pragma omp teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -168,7 +168,7 @@ T tmain(T argc) {
#pragma omp teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -242,22 +242,22 @@ int main(int argc, char **argv) {
#pragma omp teams distribute parallel for reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -266,7 +266,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -288,7 +288,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
index c7a0a358f60d..bce89b7498dc 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
index 784deeef7cd2..45793419d7c4 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
@@ -28,8 +28,12 @@ int teams_argument_global(int n){
// CK1: alloca i32,
// CK1: [[TE:%.+]] = alloca i32,
// CK1: [[TH:%.+]] = alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
// CK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
// CK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+ // CK1: call void @__kmpc_push_target_tripcount(i64 -1, i64 %{{.+}})
// CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
// CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]],
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
index 416d409acc13..7e78d06e937a 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -152,8 +152,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
@@ -209,11 +209,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -226,7 +226,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute parallel for simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
index e60f2c9dbc68..c6fb77b496d1 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
@@ -169,7 +169,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
-#pragma omp teams distribute parallel for simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp teams distribute parallel for simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -250,7 +250,7 @@ int main(int argc, char **argv) {
#pragma omp target
-#pragma omp teams distribute parallel for simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp teams distribute parallel for simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
index 9980a1d11a7e..a1c928073697 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
@@ -126,9 +126,9 @@ int test_iteration_spaces() {
for (int i = 0; !!i; i++)
c[i] = a[i];
+// Ok
#pragma omp target
#pragma omp teams distribute parallel for simd
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
for (int i = 0; i != 1; i++)
c[i] = a[i];
@@ -414,7 +414,7 @@ int test_with_random_access_iterator() {
Iter0 begin0, end0;
#pragma omp target
#pragma omp teams distribute parallel for simd
- for (GoodIter I = begin; I < end; ++I)
+ for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
@@ -423,31 +423,31 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
- for (GoodIter I = begin; I >= end; --I)
+ for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(begin); I < end; ++I)
+ for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(nullptr); I < end; ++I)
+ for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(0); I < end; ++I)
+ for (GoodIter I(0); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(1, 2); I < end; ++I)
+ for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
- for (begin = GoodIter(0); begin < end; ++begin)
+ for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute parallel for simd
@@ -462,7 +462,7 @@ int test_with_random_access_iterator() {
++begin;
#pragma omp target
#pragma omp teams distribute parallel for simd
- for (begin = end; begin < end; ++begin)
+ for (begin = end; begin < end; ++begin) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute parallel for simd
@@ -487,7 +487,7 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
- for (GoodIter I = begin; I >= end; I = I - 1)
+ for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute parallel for simd
@@ -549,19 +549,19 @@ public:
#pragma omp teams distribute parallel for simd
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I < end; I = I + ST) {
+ for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute parallel for simd
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I <= end; I += ST) {
+ for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute parallel for simd
- for (IT I = begin; I < end; ++I) {
+ for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -597,7 +597,7 @@ int dotest_gt(IT begin, IT end) {
#pragma omp target
#pragma omp teams distribute parallel for simd
- for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -606,7 +606,7 @@ void test_with_template() {
GoodIter begin, end;
TC<GoodIter, 100> t1;
TC<GoodIter, -100> t2;
- t1.dotest_lt(begin, end);
+ t1.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, 100>::dotest_lt' requested here}}
t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
dotest_gt<unsigned, 10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, 10>' requested here}}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
index 8c0c8208ab80..4faa99e2ee36 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -15,7 +15,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[S_TY:%.+]] = type { [[INTPTR_T_TY:i[0-9]+]], [[INTPTR_T_TY]], [[INTPTR_T_TY]] }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
index 50bf034891d9..7bbe4c2f235b 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -85,7 +85,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute parallel for simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp teams distribute parallel for simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -97,11 +97,11 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute parallel for simd private(ca) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute parallel for simd private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute parallel for simd private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute parallel for simd private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
index 08b3cd3a47ba..447a1a60109c 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -16,7 +16,7 @@ typedef __INTPTR_TYPE__ intptr_t;
// CHECK-DAG: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
-// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr constant [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
+// CHECK-DAG: [[DEF_LOC_2:@.+]] = private unnamed_addr global [[IDENT_T_TY]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
void foo();
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
index a17ffe392b87..9f203063f1d5 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
@@ -125,22 +125,22 @@ T tmain(T argc) {
#pragma omp teams distribute parallel for simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -149,7 +149,7 @@ T tmain(T argc) {
#pragma omp teams distribute parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -168,7 +168,7 @@ T tmain(T argc) {
#pragma omp teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -242,22 +242,22 @@ int main(int argc, char **argv) {
#pragma omp teams distribute parallel for simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -266,7 +266,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute parallel for simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -288,7 +288,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute parallel for simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute parallel for simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/teams_distribute_private_messages.cpp b/test/OpenMP/teams_distribute_private_messages.cpp
index 5fa002aadaaa..c24504460ef1 100644
--- a/test/OpenMP/teams_distribute_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -85,7 +85,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp teams distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -97,11 +97,11 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute private(ca) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_reduction_messages.cpp b/test/OpenMP/teams_distribute_reduction_messages.cpp
index 4b9d6e51b2cc..f83dda6809f7 100644
--- a/test/OpenMP/teams_distribute_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_reduction_messages.cpp
@@ -131,22 +131,22 @@ T tmain(T argc) {
#pragma omp teams distribute reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -155,7 +155,7 @@ T tmain(T argc) {
#pragma omp teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -174,7 +174,7 @@ T tmain(T argc) {
#pragma omp teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -248,22 +248,22 @@ int main(int argc, char **argv) {
#pragma omp teams distribute reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -272,7 +272,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -294,7 +294,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/teams_distribute_simd_ast_print.cpp b/test/OpenMP/teams_distribute_simd_ast_print.cpp
index b3d8ce436d4a..f811b0b7ace3 100644
--- a/test/OpenMP/teams_distribute_simd_ast_print.cpp
+++ b/test/OpenMP/teams_distribute_simd_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -Wno-openmp-target | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -Wno-openmp-target | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -75,7 +75,7 @@ class S8 : public S7<S> {
public:
S8(int v) : S7<S>(v){
#pragma omp target
-#pragma omp teams distribute simd private(a) private(this->a) private(S7<S>::a)
+#pragma omp teams distribute simd private(a) private(this->a) private(S7 <S>::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
diff --git a/test/OpenMP/teams_distribute_simd_codegen.cpp b/test/OpenMP/teams_distribute_simd_codegen.cpp
index 813d3912c398..c89a936b64f6 100644
--- a/test/OpenMP/teams_distribute_simd_codegen.cpp
+++ b/test/OpenMP/teams_distribute_simd_codegen.cpp
@@ -30,8 +30,12 @@ int teams_argument_global(int n) {
// CK1: alloca i32,
// CK1: [[TE:%.+]] = alloca i32,
// CK1: [[TH:%.+]] = alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
+ // CK1: alloca i32,
// CK1: [[TE_CAST:%.+]] = alloca i{{32|64}},
// CK1: [[TH_CAST:%.+]] = alloca i{{32|64}},
+ // CK1: call void @__kmpc_push_target_tripcount(i64 -1, i64 %{{.+}})
// CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]],
// CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]],
diff --git a/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
index 08605912d8e4..5e0806b68706 100644
--- a/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
@@ -20,7 +20,7 @@ public:
const S2 &operator =(const S2&) const;
S2 &operator =(const S2&);
static float S2s; // expected-note {{static data member is predetermined as shared}}
- static const float S2sc; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc; // expected-note {{'S2sc' declared here}}
};
const float S2::S2sc = 0;
const S2 b;
@@ -33,9 +33,9 @@ public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note 3 {{implicitly declared private here}}
@@ -152,8 +152,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
S3 m;
@@ -193,7 +193,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
@@ -209,11 +209,11 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute simd lastprivate(da) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
int xa;
@@ -226,7 +226,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
-#pragma omp teams distribute simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+#pragma omp teams distribute simd lastprivate(S2::S2sc) // expected-error {{const-qualified variable cannot be lastprivate}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_simd_linear_messages.cpp b/test/OpenMP/teams_distribute_simd_linear_messages.cpp
index a3984b98da82..8548e3dcc0cc 100644
--- a/test/OpenMP/teams_distribute_simd_linear_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_linear_messages.cpp
@@ -169,7 +169,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
-#pragma omp teams distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp teams distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -250,7 +250,7 @@ int main(int argc, char **argv) {
#pragma omp target
-#pragma omp teams distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+#pragma omp teams distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S2'}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
index 8721dc50795f..777f0812ce43 100644
--- a/test/OpenMP/teams_distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
@@ -128,7 +128,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams distribute simd
-// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// Ok
for (int i = 0; i != 1; i++)
c[i] = a[i];
@@ -414,7 +414,7 @@ int test_with_random_access_iterator() {
Iter0 begin0, end0;
#pragma omp target
#pragma omp teams distribute simd
- for (GoodIter I = begin; I < end; ++I)
+ for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute simd
@@ -423,31 +423,31 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute simd
- for (GoodIter I = begin; I >= end; --I)
+ for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(begin); I < end; ++I)
+ for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(nullptr); I < end; ++I)
+ for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(0); I < end; ++I)
+ for (GoodIter I(0); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute simd
// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
- for (GoodIter I(1, 2); I < end; ++I)
+ for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute simd
- for (begin = GoodIter(0); begin < end; ++begin)
+ for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute simd
@@ -462,7 +462,7 @@ int test_with_random_access_iterator() {
++begin;
#pragma omp target
#pragma omp teams distribute simd
- for (begin = end; begin < end; ++begin)
+ for (begin = end; begin < end; ++begin) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++begin;
#pragma omp target
#pragma omp teams distribute simd
@@ -487,7 +487,7 @@ int test_with_random_access_iterator() {
++I;
#pragma omp target
#pragma omp teams distribute simd
- for (GoodIter I = begin; I >= end; I = I - 1)
+ for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
#pragma omp target
#pragma omp teams distribute simd
@@ -549,19 +549,19 @@ public:
#pragma omp teams distribute simd
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I < end; I = I + ST) {
+ for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute simd
// expected-note@+2 {{loop step is expected to be positive due to this condition}}
// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
- for (IT I = begin; I <= end; I += ST) {
+ for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
#pragma omp target
#pragma omp teams distribute simd
- for (IT I = begin; I < end; ++I) {
+ for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -597,7 +597,7 @@ int dotest_gt(IT begin, IT end) {
#pragma omp target
#pragma omp teams distribute simd
- for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) { // expected-warning 2 {{Non-trivial type 'GoodIter' is mapped, only trivial types are guaranteed to be mapped correctly}}
++I;
}
}
@@ -606,7 +606,7 @@ void test_with_template() {
GoodIter begin, end;
TC<GoodIter, 100> t1;
TC<GoodIter, -100> t2;
- t1.dotest_lt(begin, end);
+ t1.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, 100>::dotest_lt' requested here}}
t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
dotest_gt<unsigned, 10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, 10>' requested here}}
diff --git a/test/OpenMP/teams_distribute_simd_private_messages.cpp b/test/OpenMP/teams_distribute_simd_private_messages.cpp
index 94fb9098a7d1..f2485b36a0ca 100644
--- a/test/OpenMP/teams_distribute_simd_private_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{predetermined as shared}}
-const S3 ca[5]; // expected-note {{predetermined as shared}}
-extern const int f; // expected-note {{predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -45,8 +45,8 @@ S3 h;
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -85,7 +85,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp teams distribute simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
@@ -97,11 +97,11 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute simd private(ca) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute simd private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
- #pragma omp teams distribute simd private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams distribute simd private(da) // expected-error {{const-qualified variable cannot be private}}
for (int k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/teams_distribute_simd_reduction_messages.cpp b/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
index 49b45b7bc6fb..e590d3616d0b 100644
--- a/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
@@ -125,22 +125,22 @@ T tmain(T argc) {
#pragma omp teams distribute simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -149,7 +149,7 @@ T tmain(T argc) {
#pragma omp teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -168,7 +168,7 @@ T tmain(T argc) {
#pragma omp teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -242,22 +242,22 @@ int main(int argc, char **argv) {
#pragma omp teams distribute simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -266,7 +266,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp target
#pragma omp teams distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -288,7 +288,7 @@ int main(int argc, char **argv) {
#pragma omp teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
for (int j=0; j<100; j++) foo();
#pragma omp target
-#pragma omp teams distribute simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams distribute simd reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
for (int j=0; j<100; j++) foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/teams_private_messages.cpp b/test/OpenMP/teams_private_messages.cpp
index 30c7a0abd68f..4ad7a0de29db 100644
--- a/test/OpenMP/teams_private_messages.cpp
+++ b/test/OpenMP/teams_private_messages.cpp
@@ -24,9 +24,9 @@ class S3 {
public:
S3():a(0) { }
};
-const S3 c; // expected-note {{global variable is predetermined as shared}}
-const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
-extern const int f; // expected-note {{global variable is predetermined as shared}}
+const S3 c; // expected-note {{'c' defined here}}
+const S3 ca[5]; // expected-note {{'ca' defined here}}
+extern const int f; // expected-note {{'f' declared here}}
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}
@@ -52,8 +52,8 @@ using A::x;
}
int main(int argc, char **argv) {
- const int d = 5; // expected-note {{constant variable is predetermined as shared}}
- const int da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}}
+ const int d = 5; // expected-note {{'d' defined here}}
+ const int da[5] = { 0 }; // expected-note {{'da' defined here}}
S4 e(4);
S5 g(5);
int i;
@@ -83,7 +83,7 @@ int main(int argc, char **argv) {
#pragma omp teams private (S1) // expected-error {{'S1' does not refer to a value}}
foo();
#pragma omp target
- #pragma omp teams private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ #pragma omp teams private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be private}} expected-error 2 {{const-qualified variable cannot be private}}
foo();
#pragma omp target
#pragma omp teams private (argv[1]) // expected-error {{expected variable name}}
@@ -92,10 +92,10 @@ int main(int argc, char **argv) {
#pragma omp teams private(ba)
foo();
#pragma omp target
- #pragma omp teams private(ca) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams private(ca) // expected-error {{const-qualified variable without mutable fields cannot be private}}
foo();
#pragma omp target
- #pragma omp teams private(da) // expected-error {{shared variable cannot be private}}
+ #pragma omp teams private(da) // expected-error {{const-qualified variable cannot be private}}
foo();
#pragma omp target
#pragma omp teams private(S2::S2s) // expected-error {{shared variable cannot be private}}
diff --git a/test/OpenMP/teams_reduction_messages.cpp b/test/OpenMP/teams_reduction_messages.cpp
index 94a47436c123..37f58f8b171e 100644
--- a/test/OpenMP/teams_reduction_messages.cpp
+++ b/test/OpenMP/teams_reduction_messages.cpp
@@ -131,22 +131,22 @@ T tmain(T argc) {
#pragma omp teams reduction(^ : T) // expected-error {{'T' does not refer to a value}}
foo();
#pragma omp target
-#pragma omp teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+#pragma omp teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
foo();
#pragma omp target
-#pragma omp teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
#pragma omp teams reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
#pragma omp target
-#pragma omp teams reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
-#pragma omp teams reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
-#pragma omp teams reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
#pragma omp teams reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -155,7 +155,7 @@ T tmain(T argc) {
#pragma omp teams reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
#pragma omp target
-#pragma omp teams reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
#pragma omp teams reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
@@ -174,7 +174,7 @@ T tmain(T argc) {
#pragma omp teams reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
foo();
#pragma omp target
-#pragma omp teams reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(+ : r) // expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
@@ -261,22 +261,22 @@ int main(int argc, char **argv) {
#pragma omp teams reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
foo();
#pragma omp target
-#pragma omp teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+#pragma omp teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
foo();
#pragma omp target
-#pragma omp teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
#pragma omp teams reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
foo();
#pragma omp target
-#pragma omp teams reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
-#pragma omp teams reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
-#pragma omp teams reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(- : da) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
#pragma omp teams reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
@@ -285,7 +285,7 @@ int main(int argc, char **argv) {
#pragma omp teams reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
foo();
#pragma omp target
-#pragma omp teams reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp target
#pragma omp teams reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
@@ -307,7 +307,7 @@ int main(int argc, char **argv) {
#pragma omp teams reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
foo();
#pragma omp target
-#pragma omp teams reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+#pragma omp teams reduction(+ : r) // expected-error {{const-qualified variable cannot be reduction}}
foo();
#pragma omp parallel shared(i)
#pragma omp parallel reduction(min : i)
diff --git a/test/OpenMP/threadprivate_codegen.cpp b/test/OpenMP/threadprivate_codegen.cpp
index 1f403111e7e2..405b9f16f7d7 100644
--- a/test/OpenMP/threadprivate_codegen.cpp
+++ b/test/OpenMP/threadprivate_codegen.cpp
@@ -125,7 +125,7 @@ struct S5 {
// CHECK-DAG: [[GS1:@.+]] = internal global [[S1]] zeroinitializer
// CHECK-DAG: [[GS1]].cache. = common global i8** null
-// CHECK-DAG: [[DEFAULT_LOC:@.+]] = private unnamed_addr constant [[IDENT]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* {{@.+}}, i32 0, i32 0) }
+// CHECK-DAG: [[DEFAULT_LOC:@.+]] = private unnamed_addr global [[IDENT]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* {{@.+}}, i32 0, i32 0) }
// CHECK-DAG: [[GS2:@.+]] = internal global [[S2]] zeroinitializer
// CHECK-DAG: [[ARR_X:@.+]] = global [2 x [3 x [[S1]]]] zeroinitializer
// CHECK-DAG: [[ARR_X]].cache. = common global i8** null
diff --git a/test/PCH/Inputs/pch-hdrstop-use.cpp b/test/PCH/Inputs/pch-hdrstop-use.cpp
new file mode 100644
index 000000000000..5cbb7a73755d
--- /dev/null
+++ b/test/PCH/Inputs/pch-hdrstop-use.cpp
@@ -0,0 +1,13 @@
+#include "Inputs/pch-through1.h"
+static int bar() { return 42; }
+#include "Inputs/pch-through2.h"
+int pch();
+#pragma hdrstop
+
+//expected-no-diagnostics
+//CHECK-NOT: FunctionDecl{{.*}}other
+//CHECK: FunctionDecl{{.*}}main
+int main()
+{
+ return pch() - 42*42 + bar() - 42 + through1(0) + through2(33);
+}
diff --git a/test/PCH/Inputs/pch-no-hdrstop-use.cpp b/test/PCH/Inputs/pch-no-hdrstop-use.cpp
new file mode 100644
index 000000000000..ec4f96257064
--- /dev/null
+++ b/test/PCH/Inputs/pch-no-hdrstop-use.cpp
@@ -0,0 +1,11 @@
+#include "Inputs/pch-through1.h"
+static int bar() { return 42; }
+#include "Inputs/pch-through2.h"
+int pch();
+#pragma hdrstop
+
+//expected-no-diagnostics
+int main()
+{
+ return pch() + through1(0) + through2(-1) + bar() - 42;
+}
diff --git a/test/PCH/Inputs/pch-through-use3c.cpp b/test/PCH/Inputs/pch-through-use3c.cpp
new file mode 100644
index 000000000000..6102c514fba3
--- /dev/null
+++ b/test/PCH/Inputs/pch-through-use3c.cpp
@@ -0,0 +1,2 @@
+int a = A;
+// expected-no-diagnostics
diff --git a/test/PCH/Inputs/pch-through3c.h b/test/PCH/Inputs/pch-through3c.h
new file mode 100644
index 000000000000..ab2a05dbbf84
--- /dev/null
+++ b/test/PCH/Inputs/pch-through3c.h
@@ -0,0 +1 @@
+#define A 1
diff --git a/test/PCH/block-helpers.cpp b/test/PCH/block-helpers.cpp
new file mode 100644
index 000000000000..02d4ceecf359
--- /dev/null
+++ b/test/PCH/block-helpers.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -x c++-header -triple x86_64-apple-darwin11 -emit-pch -fblocks -fexceptions -o %t %S/block-helpers.h
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -include-pch %t -emit-llvm -fblocks -fexceptions -o - %s | FileCheck %s
+
+// CHECK: %[[STRUCT_BLOCK_BYREF_X:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_X]]*, i32, i32, i8*, i8*, %[[STRUCT_S0:.*]] }
+// CHECK: %[[STRUCT_S0]] = type { i32 }
+// CHECK: %[[STRUCT_BLOCK_BYREF_Y:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_Y]]*, i32, i32, i8*, i8*, %[[STRUCT_S0]] }
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
+
+// Check that byref structs are allocated for x and y.
+
+// CHECK-LABEL: define linkonce_odr void @_ZN1S1mEv(
+// CHECK: %[[X:.*]] = alloca %[[STRUCT_BLOCK_BYREF_X]], align 8
+// CHECK: %[[Y:.*]] = alloca %[[STRUCT_BLOCK_BYREF_Y]], align 8
+// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>, align 8
+// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>* %[[BLOCK]], i32 0, i32 5
+// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_BLOCK_BYREF_X]]* %[[X]] to i8*
+// CHECK: store i8* %[[V0]], i8** %[[BLOCK_CAPTURED]], align 8
+// CHECK: %[[BLOCK_CAPTURED10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>* %[[BLOCK]], i32 0, i32 6
+// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_BLOCK_BYREF_Y]]* %[[Y]] to i8*
+// CHECK: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED10]], align 8
+
+// CHECK-LABEL: define internal void @___ZN1S1mEv_block_invoke(
+
+// The second call to block_object_assign should be an invoke.
+
+// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_e8_32rc40rc(
+// CHECK: call void @_Block_object_assign(
+// CHECK: invoke void @_Block_object_assign(
+// CHECK: call void @_Block_object_dispose(
+
+// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_e8_32r40r(
+void test() {
+ S s;
+ s.m();
+}
diff --git a/test/PCH/block-helpers.h b/test/PCH/block-helpers.h
new file mode 100644
index 000000000000..3614cc7be93a
--- /dev/null
+++ b/test/PCH/block-helpers.h
@@ -0,0 +1,12 @@
+struct S0 {
+ S0();
+ S0(const S0 &) noexcept(false);
+ int a;
+};
+
+struct S {
+ void m() {
+ __block S0 x, y;
+ ^{ (void)x; (void)y; };
+ }
+};
diff --git a/test/PCH/case-insensitive-include.c b/test/PCH/case-insensitive-include.c
index c721225397ce..c40b0ada9856 100644
--- a/test/PCH/case-insensitive-include.c
+++ b/test/PCH/case-insensitive-include.c
@@ -13,7 +13,7 @@
// RUN: touch -r %t-dir/case-insensitive-include.h %t.copy
// RUN: mv %t.copy %t-dir/case-insensitive-include.h
-// RUN: %clang_cc1 -fsyntax-only %s -include-pch %t.pch -I %t-dir -verify
+// RUN: %clang_cc1 -Wno-nonportable-include-path -fsyntax-only %s -include-pch %t.pch -I %t-dir -verify
// expected-no-diagnostics
diff --git a/test/PCH/cxx-static_assert.cpp b/test/PCH/cxx-static_assert.cpp
index 8049525fb598..be6c0ab2a76b 100644
--- a/test/PCH/cxx-static_assert.cpp
+++ b/test/PCH/cxx-static_assert.cpp
@@ -3,7 +3,7 @@
// Test with pch.
// RUN: %clang_cc1 -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -include-pch %t -verify -std=c++11 %s
+// RUN: %clang_cc1 -include-pch %t -verify -std=c++11 %s
#ifndef HEADER
#define HEADER
@@ -14,7 +14,7 @@ template<int N> struct T {
#else
-// expected-error@12 {{static_assert failed "N is not 2!"}}
+// expected-error@12 {{static_assert failed due to requirement '1 == 2' "N is not 2!"}}
T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}}
T<2> t2;
diff --git a/test/PCH/cxx2a-for-init-statement.cpp b/test/PCH/cxx2a-for-init-statement.cpp
new file mode 100644
index 000000000000..2147c0f8a2a1
--- /dev/null
+++ b/test/PCH/cxx2a-for-init-statement.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -emit-pch -std=c++2a -o %t %s
+// RUN: %clang_cc1 -std=c++2a -x ast -ast-print %t | FileCheck %s
+
+void f() {
+ // CHECK: for (int arr[3]; int n : arr) {
+ // CHECK-NEXT: }
+ for (int arr[3]; int n : arr) {}
+}
diff --git a/test/PCH/debug-info-pch-path.c b/test/PCH/debug-info-pch-path.c
index 015086f726e8..dcf7ed41f50e 100644
--- a/test/PCH/debug-info-pch-path.c
+++ b/test/PCH/debug-info-pch-path.c
@@ -24,7 +24,7 @@
// CHECK-REL-NODIR: !DICompileUnit(
// CHECK-REL-NODIR-SAME: file: ![[PCH:[0-9]+]]
// CHECK-REL-NODIR-SAME: splitDebugFilename: "prefix.pch"
-// CHECK-REL-NODIR: ![[PCH]] = !DIFile({{.*}}directory: "[[DIR]]"
+// CHECK-REL-NODIR: ![[PCH]] = !DIFile({{.*}}directory: "[[DIR]]
// ---------------------------------------------------------------------
// Relative PCH in a subdirectory.
@@ -71,4 +71,4 @@
// CHECK-ABS: !DICompileUnit(
// CHECK-ABS-SAME: file: ![[PCH:[0-9]+]]
// CHECK-ABS-SAME: splitDebugFilename: "prefix.pch"
-// CHECK-ABS: ![[PCH]] = !DIFile({{.*}}directory: "[[DIR]]"
+// CHECK-ABS: ![[PCH]] = !DIFile({{.*}}directory: "[[DIR]]
diff --git a/test/PCH/emit-pth.c b/test/PCH/emit-pth.c
deleted file mode 100644
index 2c0fba7f0932..000000000000
--- a/test/PCH/emit-pth.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o %t1 %s
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o - %s > %t2
-// RUN: cmp %t1 %t2
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o - %s | \
-// RUN: FileCheck %s
-
-// CHECK: cfe-pth
diff --git a/test/PCH/no-escaping-block-tail-calls.cpp b/test/PCH/no-escaping-block-tail-calls.cpp
new file mode 100644
index 000000000000..5ae8108f387d
--- /dev/null
+++ b/test/PCH/no-escaping-block-tail-calls.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++-header -triple x86_64-apple-darwin11 -emit-pch -O1 -fblocks -fno-escaping-block-tail-calls -o %t %S/no-escaping-block-tail-calls.h
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -include-pch %t -emit-llvm -O1 -fblocks -fno-escaping-block-tail-calls -o - %s | FileCheck %s
+
+// Check that -fno-escaping-block-tail-calls doesn't disable tail-call
+// optimization if the block is non-escaping.
+
+// CHECK-LABEL: define internal i32 @___ZN1S1mEv_block_invoke(
+// CHECK: %[[CALL:.*]] = tail call i32 @_ZN1S3fooER2S0(
+// CHECK-NEXT: ret i32 %[[CALL]]
+
+void test() {
+ S s;
+ s.m();
+}
diff --git a/test/PCH/no-escaping-block-tail-calls.h b/test/PCH/no-escaping-block-tail-calls.h
new file mode 100644
index 000000000000..5d37d904795e
--- /dev/null
+++ b/test/PCH/no-escaping-block-tail-calls.h
@@ -0,0 +1,16 @@
+typedef int (^BlockTy)(void);
+
+struct S0 {
+ int a;
+};
+
+struct S {
+ int i;
+ void func(BlockTy __attribute__((noescape)));
+ int foo(S0 &);
+
+ void m() {
+ __block S0 x;
+ func(^{ return foo(x); });
+ }
+};
diff --git a/test/PCH/objc_exprs.h b/test/PCH/objc_exprs.h
index 807304c20f86..e4952f5929bf 100644
--- a/test/PCH/objc_exprs.h
+++ b/test/PCH/objc_exprs.h
@@ -1,11 +1,13 @@
@protocol foo;
+@protocol foo2
+@end
@class itf;
// Expressions
typedef typeof(@"foo" "bar") objc_string;
typedef typeof(@encode(int)) objc_encode;
-typedef typeof(@protocol(foo)) objc_protocol;
+typedef typeof(@protocol(foo2)) objc_protocol;
typedef typeof(@selector(noArgs)) objc_selector_noArgs;
typedef typeof(@selector(oneArg:)) objc_selector_oneArg;
typedef typeof(@selector(foo:bar:)) objc_selector_twoArg;
diff --git a/test/PCH/pch-hdrstop-err.cpp b/test/PCH/pch-hdrstop-err.cpp
new file mode 100644
index 000000000000..7e66c96eeca6
--- /dev/null
+++ b/test/PCH/pch-hdrstop-err.cpp
@@ -0,0 +1,14 @@
+// Create PCH with #pragma hdrstop
+// RUN: %clang_cc1 -I %S -emit-pch -pch-through-hdrstop-create \
+// RUN: -fms-extensions -o %t.pch -x c++-header %s
+
+// Use PCH with no #pragma hdrstop
+// RUN: not %clang_cc1 -I %S -emit-obj -include-pch %t.pch \
+// RUN: -pch-through-hdrstop-use -fms-extensions -o %t.obj -x c++ %s 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-U %s
+
+#include "Inputs/pch-through1.h"
+static int bar() { return 42; }
+#include "Inputs/pch-through2.h"
+int pch();
+//CHECK-U: hdrstop not seen while attempting to use precompiled header
diff --git a/test/PCH/pch-hdrstop-warn.cpp b/test/PCH/pch-hdrstop-warn.cpp
new file mode 100644
index 000000000000..dbd592fb788f
--- /dev/null
+++ b/test/PCH/pch-hdrstop-warn.cpp
@@ -0,0 +1,10 @@
+// Create PCH with #pragma hdrstop
+// RUN: %clang_cc1 -verify -I %S -emit-pch -pch-through-hdrstop-create \
+// RUN: -fms-extensions -o %t.pch -x c++-header %s
+
+// Create PCH object with #pragma hdrstop
+// RUN: %clang_cc1 -verify -I %S -emit-obj -include-pch %t.pch \
+// RUN: -pch-through-hdrstop-create -fms-extensions -o %t.obj -x c++ %s
+
+//expected-warning@+1{{hdrstop filename not supported}}
+#pragma hdrstop("name.pch")
diff --git a/test/PCH/pch-hdrstop.cpp b/test/PCH/pch-hdrstop.cpp
new file mode 100644
index 000000000000..5fe83a603e31
--- /dev/null
+++ b/test/PCH/pch-hdrstop.cpp
@@ -0,0 +1,28 @@
+// expected-no-diagnostics
+// Create PCH with #pragma hdrstop
+// RUN: %clang_cc1 -verify -I %S -emit-pch -pch-through-hdrstop-create \
+// RUN: -fms-extensions -o %t.pch -x c++-header %s
+
+// Create PCH object with #pragma hdrstop
+// RUN: %clang_cc1 -verify -I %S -emit-obj -include-pch %t.pch \
+// RUN: -pch-through-hdrstop-create -fms-extensions -o %t.obj -x c++ %s
+
+// Use PCH with #pragma hdrstop
+// RUN: %clang_cc1 -verify -I %S -emit-obj -include-pch %t.pch \
+// RUN: -pch-through-hdrstop-use -fms-extensions -o %t.obj \
+// RUN: -x c++ %S/Inputs/pch-hdrstop-use.cpp
+
+// Ensure the PCH stops at the hdrstop
+// RUN: %clang_cc1 -ast-dump -I %S -include-pch %t.pch \
+// RUN: -pch-through-hdrstop-use -fms-extensions -o %t.obj \
+// RUN: -x c++ %S/Inputs/pch-hdrstop-use.cpp 2>&1 \
+// RUN: | FileCheck %S/Inputs/pch-hdrstop-use.cpp
+
+#include "Inputs/pch-through1.h"
+static int bar() { return 42; }
+#include "Inputs/pch-through2.h"
+int pch();
+#pragma hdrstop
+
+int pch() { return 42*42; }
+int other() { return 42; }
diff --git a/test/PCH/pch-no-hdrstop.cpp b/test/PCH/pch-no-hdrstop.cpp
new file mode 100644
index 000000000000..3eb4c78ca91c
--- /dev/null
+++ b/test/PCH/pch-no-hdrstop.cpp
@@ -0,0 +1,18 @@
+// expected-no-diagnostics
+// Create PCH with #pragma hdrstop processing with no #pragma hdrstop
+// RUN: %clang_cc1 -verify -I %S -emit-pch -pch-through-hdrstop-create \
+// RUN: -fms-extensions -o %t.pch -x c++-header %s
+
+// Create the PCH object
+// RUN: %clang_cc1 -verify -I %S -emit-obj -include-pch %t.pch \
+// RUN: -pch-through-hdrstop-create -fms-extensions -o %t.obj -x c++ %s
+
+// The use must still have a #pragma hdrstop
+// RUN: %clang_cc1 -verify -I %S -emit-obj -include-pch %t.pch \
+// RUN: -pch-through-hdrstop-use -fms-extensions -o %t.obj \
+// RUN: -x c++ %S/Inputs/pch-no-hdrstop-use.cpp
+
+#include "Inputs/pch-through1.h"
+static int bar() { return 42; }
+#include "Inputs/pch-through2.h"
+int pch();
diff --git a/test/PCH/pch-through3c.cpp b/test/PCH/pch-through3c.cpp
new file mode 100644
index 000000000000..41894c99731d
--- /dev/null
+++ b/test/PCH/pch-through3c.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -I %S -emit-pch \
+// RUN: -include Inputs/pch-through3c.h \
+// RUN: -pch-through-header=Inputs/pch-through3c.h -o %t.3c %s
+
+// Checks that no warnings appear for this successful use.
+// RUN: %clang_cc1 -verify -I %S -include-pch %t.3c \
+// RUN: -include Inputs/pch-through3c.h \
+// RUN: -pch-through-header=Inputs/pch-through3c.h \
+// RUN: %S/Inputs/pch-through-use3c.cpp 2>&1
diff --git a/test/PCH/pragma-loop.cpp b/test/PCH/pragma-loop.cpp
index 7f443ddb034e..b8079ff608e4 100644
--- a/test/PCH/pragma-loop.cpp
+++ b/test/PCH/pragma-loop.cpp
@@ -1,26 +1,23 @@
// RUN: %clang_cc1 -emit-pch -o %t.a %s
// RUN: %clang_cc1 -include-pch %t.a %s -ast-print -o - | FileCheck %s
-// FIXME: A bug in ParsedAttributes causes the order of the attributes to be
-// reversed. The checks are consequently in the reverse order below.
-
-// CHECK: #pragma clang loop unroll_count(16){{$}}
-// CHECK: #pragma clang loop interleave_count(8)
// CHECK: #pragma clang loop vectorize_width(4)
-// CHECK: #pragma clang loop distribute(enable)
-// CHECK: #pragma clang loop unroll(disable)
-// CHECK: #pragma clang loop interleave(disable)
+// CHECK: #pragma clang loop interleave_count(8)
+// CHECK: #pragma clang loop unroll_count(16){{$}}
// CHECK: #pragma clang loop vectorize(enable)
-// CHECK: #pragma clang loop distribute(disable)
-// CHECK: #pragma clang loop unroll(full)
-// CHECK: #pragma clang loop interleave(enable)
+// CHECK: #pragma clang loop interleave(disable)
+// CHECK: #pragma clang loop unroll(disable)
+// CHECK: #pragma clang loop distribute(enable)
// CHECK: #pragma clang loop vectorize(disable)
+// CHECK: #pragma clang loop interleave(enable)
+// CHECK: #pragma clang loop unroll(full)
+// CHECK: #pragma clang loop distribute(disable)
// FIXME: "#pragma unroll (enable)" is invalid and is not the input source.
// CHECK: #pragma unroll (enable){{$}}
// CHECK: #pragma unroll (32){{$}}
// CHECK: #pragma nounroll{{$}}
-// CHECK: #pragma clang loop interleave_count(I)
// CHECK: #pragma clang loop vectorize_width(V)
+// CHECK: #pragma clang loop interleave_count(I)
#ifndef HEADER
#define HEADER
diff --git a/test/PCH/pth.c b/test/PCH/pth.c
deleted file mode 100644
index 6f2e4fc7b53c..000000000000
--- a/test/PCH/pth.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o %t %S/pth.h
-// RUN: not %clang_cc1 -triple i386-unknown-unknown -include-pth %t -fsyntax-only %s 2>&1 | FileCheck %s
-
-#error This is the only diagnostic
-
-// CHECK: This is the only diagnostic
-// CHECK: 1 error generated.
diff --git a/test/Parser/DelayedTemplateParsing.cpp b/test/Parser/DelayedTemplateParsing.cpp
index 6ea245c2d4e4..c65e80b1f732 100644
--- a/test/Parser/DelayedTemplateParsing.cpp
+++ b/test/Parser/DelayedTemplateParsing.cpp
@@ -181,3 +181,33 @@ static void h() {
}
}
+
+struct PR38460 {
+ template <typename>
+ struct T {
+ static void foo() {
+ struct U {
+ void dummy() {
+ use_delayed_identifier();
+ }
+ };
+ }
+ };
+};
+void use_delayed_identifier();
+void trigger_PR38460() {
+ PR38460::T<int>::foo();
+}
+
+template <typename> struct PR38460_2 {
+ struct p {
+ struct G {
+ bool operator()(int) {}
+ };
+ };
+ static void as() {
+ typename p::G g;
+ g(0);
+ }
+};
+template struct PR38460_2<int>;
diff --git a/test/Parser/cuda-kernel-call-c++11.cu b/test/Parser/cuda-kernel-call-c++11.cu
index 8f833f79af50..1870b201ad91 100644
--- a/test/Parser/cuda-kernel-call-c++11.cu
+++ b/test/Parser/cuda-kernel-call-c++11.cu
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
-template<typename> struct S {};
+template<typename T=int> struct S {};
template<typename> void f();
@@ -11,10 +11,14 @@ void foo(void) {
// expected-no-diagnostics
S<S<S<int>>> s3;
+ S<S<S<>>> s30;
S<S<S<S<int>>>> s4;
+ S<S<S<S<>>>> s40;
S<S<S<S<S<int>>>>> s5;
+ S<S<S<S<S<>>>>> s50;
(void)(&f<S<S<int>>>==0);
+ (void)(&f<S<S<>>>==0);
}
diff --git a/test/Parser/cuda-kernel-call.cu b/test/Parser/cuda-kernel-call.cu
index 1970c558c506..2a409aa3777e 100644
--- a/test/Parser/cuda-kernel-call.cu
+++ b/test/Parser/cuda-kernel-call.cu
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-template<typename> struct S {};
+template<typename T=int> struct S {};
template<typename> void f();
void foo(void) {
@@ -13,5 +13,7 @@ void foo(void) {
// The following two are parse errors because -std=c++11 is not enabled.
S<S<S<int>>> s; // expected-error 2{{use '> >'}}
+ S<S<S<>>> s1; // expected-error 2{{use '> >'}}
(void)(&f<S<S<int>>>==0); // expected-error 2{{use '> >'}}
+ (void)(&f<S<S<>>>==0); // expected-error 2{{use '> >'}}
}
diff --git a/test/Parser/cxx0x-attributes.cpp b/test/Parser/cxx0x-attributes.cpp
index e01491db4133..101e03845b8f 100644
--- a/test/Parser/cxx0x-attributes.cpp
+++ b/test/Parser/cxx0x-attributes.cpp
@@ -373,3 +373,11 @@ int fallthru(int n) {
[[attr_name, attr_name_2(bitor), attr_name_3(com, pl)]] int macro_attrs; // expected-warning {{unknown attribute 'compl' ignored}} \
expected-warning {{unknown attribute 'bitor' ignored}} \
expected-warning {{unknown attribute 'bitand' ignored}}
+
+// Check that we can parse an attribute in our vendor namespace.
+[[clang::annotate("test")]] void annotate1();
+[[_Clang::annotate("test")]] void annotate2();
+// Note: __clang__ is a predefined macro, which is why _Clang is the
+// prefered "protected" vendor namespace. We support __clang__ only for
+// people expecting it to behave the same as __gnu__.
+[[__clang__::annotate("test")]] void annotate3(); // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}}
diff --git a/test/Parser/cxx1z-decomposition.cpp b/test/Parser/cxx1z-decomposition.cpp
index cf4ba77723ad..1e184a7fac54 100644
--- a/test/Parser/cxx1z-decomposition.cpp
+++ b/test/Parser/cxx1z-decomposition.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++1z %s -verify -fcxx-exceptions
+// RUN: not %clang_cc1 -std=c++1z %s -emit-llvm-only -fcxx-exceptions
struct S { int a, b, c; };
diff --git a/test/Parser/cxx1z-init-statement.cpp b/test/Parser/cxx1z-init-statement.cpp
index 3d119ef8e709..ade60dc762d5 100644
--- a/test/Parser/cxx1z-init-statement.cpp
+++ b/test/Parser/cxx1z-init-statement.cpp
@@ -13,9 +13,9 @@ int f() {
if (T(n) = 0; n) {}
// init-statement expressions
- if (T{f()}; f()) {}
- if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}}
- if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}}
+ if (T{f()}; f()) {} // expected-warning {{expression result unused}}
+ if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}}
+ if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}}
// condition declarations
if (T(n){g}) {}
@@ -35,7 +35,7 @@ int f() {
// Likewise for 'switch'
switch (int n; n) {}
- switch (g; int g = 5) {}
+ switch (g; int g = 5) {} // expected-warning {{expression result unused}}
if (int a, b; int c = a) { // expected-note 6{{previous}}
int a; // expected-error {{redefinition}}
diff --git a/test/Parser/cxx2a-init-statement.cpp b/test/Parser/cxx2a-init-statement.cpp
new file mode 100644
index 000000000000..3b1862f1d3c5
--- /dev/null
+++ b/test/Parser/cxx2a-init-statement.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template<int N> struct A {};
+
+using F = bool(*)(int);
+extern F *p;
+extern int m;
+
+struct Convertible { template<typename T> operator T(); };
+
+void f() {
+ int arr1[3];
+ for (int n = 5; int x : arr1) {}
+
+ int A<0>::*arr2[3];
+ for (int n = 5; int A<true ? 0 : 1>::*x : arr2) {}
+
+ F (*arr3[3])(int);
+ for (int n = 5; F (*p)(int n) : arr3) {}
+ for (int n = 5; F (*p)(int (n)) : arr3) {}
+
+ // Here, we have a declaration rather than an expression.
+ for (int n = 5; F (*p)(int (n)); ++n) {}
+
+ // We detect whether we have a for-range-declaration before parsing so that
+ // we can give different diagnostics for for-range-declarations versus
+ // conditions (even though the rules are currently identical).
+ Convertible arr4[3];
+ for (int n = 0; struct { operator bool(); } x = {}; ++n) {} // expected-error {{cannot be defined in a condition}}
+ for (int n = 0; struct { operator bool(); } x : arr4) {} // expected-error {{may not be defined in a for range declaration}}
+
+ for (int n = 0; static int m = 0; ++n) {} // expected-error {{type name does not allow storage class}}
+ for (int n = 0; static int m : arr1) {} // expected-error {{loop variable 'm' may not be declared 'static'}}
+}
diff --git a/test/Parser/cxx2a-inline-nested-namespace-definition.cpp b/test/Parser/cxx2a-inline-nested-namespace-definition.cpp
new file mode 100644
index 000000000000..660287c83fca
--- /dev/null
+++ b/test/Parser/cxx2a-inline-nested-namespace-definition.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++17
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2a -Wc++17-compat
+
+namespace inline foo1::foo2::foo3 { // expected-error {{expected identifier or '{'}} expected-error {{use of undeclared identifier 'foo1'}}
+}
+
+inline namespace foo4::foo5::foo6 { // expected-error {{nested namespace definition cannot be 'inline'}}}
+}
+
+#if __cplusplus <= 201402L
+// expected-warning@+7 {{nested namespace definition is a C++17 extension; define each namespace separately}}
+// expected-warning@+6 {{inline nested namespace definition is a C++2a extension}}
+#elif __cplusplus <= 201703L
+// expected-warning@+4 {{inline nested namespace definition is a C++2a extension}}
+#else
+// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}}
+#endif
+namespace valid1::valid2::inline valid3::inline valid4::valid5 {}
+// expected-note@-1 2 {{previous definition is here}}
+
+#if __cplusplus <= 201402L
+// expected-warning@+3 {{nested namespace definition is a C++17 extension; define each namespace separately}}
+#endif
+//expected-warning@+1 2 {{inline namespace reopened as a non-inline namespace}}
+namespace valid1::valid2::valid3::valid4::valid5 {}
+
+#if __cplusplus <= 201402L
+// expected-warning@+7 {{nested namespace definition is a C++17 extension; define each namespace separately}}
+// expected-warning@+6 {{inline nested namespace definition is a C++2a extension}}
+#elif __cplusplus <= 201703L
+// expected-warning@+4 {{inline nested namespace definition is a C++2a extension}}
+#else
+// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}}
+#endif
+namespace valid1::valid2::inline valid3::inline valid4::valid5 {}
+// expected-note@-1 2 {{previous definition is here}}
+
+namespace valid1 {
+namespace valid2 {
+//expected-warning@+1 {{inline namespace reopened as a non-inline namespace}}
+namespace valid3 {
+//expected-warning@+1 {{inline namespace reopened as a non-inline namespace}}
+namespace valid4 {
+namespace valid5 {
+}
+} // namespace valid4
+} // namespace valid3
+} // namespace valid2
+} // namespace valid1
+
diff --git a/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp b/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp
new file mode 100644
index 000000000000..7737eb02947f
--- /dev/null
+++ b/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -fsyntax-only -Wextra -std=c++2a -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wextra-semi-stmt -std=c++2a -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wempty-init-stmt -std=c++2a -verify %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -x c++ -Wempty-init-stmt -std=c++2a -fixit %t
+// RUN: %clang_cc1 -x c++ -Wempty-init-stmt -std=c++2a -Werror %t
+
+struct S {
+ int *begin();
+ int *end();
+};
+
+void naive(int x) {
+ if (; true) // expected-warning {{empty initialization statement of 'if' has no effect}}
+ ;
+
+ switch (; x) { // expected-warning {{empty initialization statement of 'switch' has no effect}}
+ }
+
+ for (; int y : S()) // expected-warning {{empty initialization statement of 'range-based for' has no effect}}
+ ;
+
+ for (;;) // OK
+ ;
+}
+
+#define NULLMACRO
+
+void with_null_macro(int x) {
+ if (NULLMACRO; true)
+ ;
+
+ switch (NULLMACRO; x) {
+ }
+
+ for (NULLMACRO; int y : S())
+ ;
+}
+
+#define SEMIMACRO ;
+
+void with_semi_macro(int x) {
+ if (SEMIMACRO true)
+ ;
+
+ switch (SEMIMACRO x) {
+ }
+
+ for (SEMIMACRO int y : S())
+ ;
+}
+
+#define PASSTHROUGHMACRO(x) x
+
+void with_passthrough_macro(int x) {
+ if (PASSTHROUGHMACRO(;) true)
+ ;
+
+ switch (PASSTHROUGHMACRO(;) x) {
+ }
+
+ for (PASSTHROUGHMACRO(;) int y : S())
+ ;
+}
diff --git a/test/Parser/extra-semi-resulting-in-nullstmt.cpp b/test/Parser/extra-semi-resulting-in-nullstmt.cpp
new file mode 100644
index 000000000000..a09d942c5892
--- /dev/null
+++ b/test/Parser/extra-semi-resulting-in-nullstmt.cpp
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -fsyntax-only -Wextra-semi-stmt -verify %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -x c++ -Wextra-semi-stmt -fixit %t
+// RUN: %clang_cc1 -x c++ -Wextra-semi-stmt -Werror %t
+
+#define GOODMACRO(varname) int varname
+#define BETTERMACRO(varname) GOODMACRO(varname);
+#define NULLMACRO(varname)
+
+enum MyEnum {
+ E1,
+ E2
+};
+
+void test() {
+ ; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}
+ ;
+
+ // This removal of extra semi also consumes all the comments.
+ // clang-format: off
+ ;;;
+ // clang-format: on
+
+ // clang-format: off
+ ;NULLMACRO(ZZ);
+ // clang-format: on
+
+ {}; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}
+
+ {
+ ; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}
+ }
+
+ if (true) {
+ ; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}
+ }
+
+ GOODMACRO(v0); // OK
+
+ GOODMACRO(v1;) // OK
+
+ BETTERMACRO(v2) // OK
+
+ BETTERMACRO(v3;) // Extra ';', but within macro expansion, so ignored.
+
+ BETTERMACRO(v4); // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}
+
+ BETTERMACRO(v5;); // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}
+
+ NULLMACRO(v6) // OK
+
+ NULLMACRO(v7); // OK. This could be either GOODMACRO() or BETTERMACRO() situation, so we can't know we can drop it.
+
+ if (true)
+ ; // OK
+
+ while (true)
+ ; // OK
+
+ do
+ ; // OK
+ while (true);
+
+ for (;;) // OK
+ ; // OK
+
+ MyEnum my_enum;
+ switch (my_enum) {
+ case E1:
+ // stuff
+ break;
+ case E2:; // OK
+ }
+
+ for (;;) {
+ for (;;) {
+ goto contin_outer;
+ }
+ contin_outer:; // OK
+ }
+}
+
+;
+
+namespace NS {};
+
+void foo(int x) {
+ switch (x) {
+ case 0:
+ [[fallthrough]];
+ case 1:
+ return;
+ }
+}
+
+[[]];
diff --git a/test/Parser/message-expr-alt-op.mm b/test/Parser/message-expr-alt-op.mm
new file mode 100644
index 000000000000..4fbea5753709
--- /dev/null
+++ b/test/Parser/message-expr-alt-op.mm
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@interface WeirdInterface
+-(void)allOfThem:(int)a
+ and:(int)b
+ and_eq:(int)c
+ bitand:(int)d
+ bitor:(int)e
+ compl:(int)f
+ not:(int)g
+ not_eq:(int)h
+ or:(int)i
+ or_eq:(int)j
+ xor:(int)k
+ xor_eq:(int)l;
+
+-(void)justAnd:(int)x and:(int)y;
+-(void)and;
+-(void)and:(int)x;
+@end
+
+void call_it(WeirdInterface *x) {
+ [x allOfThem:0
+ and:0
+ and_eq:0
+ bitand:0
+ bitor:0
+ compl:0
+ not:0
+ not_eq:0
+ or:0
+ or_eq:0
+ xor:0
+ xor_eq:0];
+
+ [x and];
+ [x and:0];
+ [x &&:0]; // expected-error{{expected expression}};
+ [x justAnd:0 and:1];
+ [x and: 0 ? : 1];
+}
diff --git a/test/Parser/objc-cxx-keyword-identifiers.mm b/test/Parser/objc-cxx-keyword-identifiers.mm
index 6791f0d3732a..cff38c554371 100644
--- a/test/Parser/objc-cxx-keyword-identifiers.mm
+++ b/test/Parser/objc-cxx-keyword-identifiers.mm
@@ -18,7 +18,9 @@ struct S {
@protocol new // expected-error {{expected identifier; 'new' is a keyword in Objective-C++}}
@end
-@protocol P2, delete; // expected-error {{expected identifier; 'delete' is a keyword in Objective-C++}}
+@protocol P2;
+@protocol delete // expected-error {{expected identifier; 'delete' is a keyword in Objective-C++}}
+@end
@class Foo, try; // expected-error {{expected identifier; 'try' is a keyword in Objective-C++}}
diff --git a/test/Parser/pragma-attribute.cpp b/test/Parser/pragma-attribute.cpp
index f0ebca2c5313..4e860b6d5833 100644
--- a/test/Parser/pragma-attribute.cpp
+++ b/test/Parser/pragma-attribute.cpp
@@ -100,11 +100,12 @@ void function();
#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)) )) // expected-error {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}}
#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)), enum, variable(unless(is_parameter)) )) // expected-error 2 {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}}
-#pragma clang attribute // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}}
-#pragma clang attribute 42 // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}}
-#pragma clang attribute pushpop // expected-error {{unexpected argument 'pushpop' to '#pragma clang attribute'; expected 'push' or 'pop'}}
+#pragma clang attribute // expected-error {{expected 'push', 'pop', or '(' after '#pragma clang attribute'}}
+#pragma clang attribute 42 // expected-error {{expected 'push', 'pop', or '(' after '#pragma clang attribute'}}
+#pragma clang attribute pushpop // expected-error {{expected '.' after pragma attribute namespace 'pushpop'}}
-#pragma clang attribute push // expected-error {{expected '('}}
+#pragma clang attribute push
+#pragma clang attribute pop
#pragma clang attribute push ( // expected-error {{expected an attribute after '('}}
#pragma clang attribute push (__attribute__((annotate)) // expected-error {{expected ')'}}
#pragma clang attribute push () // expected-error {{expected an attribute after '('}}
@@ -123,7 +124,9 @@ void function();
#pragma clang attribute push (__attribute__((annotate)), apply_to=function foo) // expected-error {{extra tokens after attribute in a '#pragma clang attribute push'}}
#pragma clang attribute push (__attribute__((objc_bridge_related)), apply_to=function)
-// expected-error@-1 {{attribute 'objc_bridge_related' is not supported by '#pragma clang attribute'}}
+// expected-error@-1 {{attribute 'objc_bridge_related' can't be applied to 'function'}}
+#pragma clang attribute pop
+
#pragma clang attribute push (__attribute__((objc_bridge_related(1))), apply_to=function) // expected-error {{expected a related ObjectiveC class name, e.g., 'NSColor'}}
#pragma clang attribute push (__attribute__((used)), apply_to=function) // expected-error {{attribute 'used' is not supported by '#pragma clang attribute'}}
diff --git a/test/Parser/pragma-loop-safety.cpp b/test/Parser/pragma-loop-safety.cpp
index ab87dcdcb63e..1393cf747498 100644
--- a/test/Parser/pragma-loop-safety.cpp
+++ b/test/Parser/pragma-loop-safety.cpp
@@ -25,10 +25,10 @@ void test(int *List, int Length) {
List[i] = i;
}
-/* expected-error {{duplicate directives 'vectorize(assume_safety)' and 'vectorize(enable)'}} */ #pragma clang loop vectorize(enable)
-#pragma clang loop vectorize(assume_safety)
-/* expected-error {{duplicate directives 'interleave(assume_safety)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable)
-#pragma clang loop interleave(assume_safety)
+#pragma clang loop vectorize(enable)
+/* expected-error {{duplicate directives 'vectorize(enable)' and 'vectorize(assume_safety)'}} */ #pragma clang loop vectorize(assume_safety)
+#pragma clang loop interleave(enable)
+/* expected-error {{duplicate directives 'interleave(enable)' and 'interleave(assume_safety)'}} */ #pragma clang loop interleave(assume_safety)
while (i-9 < Length) {
List[i] = i;
}
diff --git a/test/Parser/pragma-loop.cpp b/test/Parser/pragma-loop.cpp
index f42d196ce8bd..be765170f85b 100644
--- a/test/Parser/pragma-loop.cpp
+++ b/test/Parser/pragma-loop.cpp
@@ -147,7 +147,7 @@ void test(int *List, int Length) {
/* expected-error {{missing argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll()
/* expected-error {{missing argument; expected 'enable' or 'disable'}} */ #pragma clang loop distribute()
-/* expected-error {{missing option; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute}} */ #pragma clang loop
+/* expected-error {{missing option; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, pipeline, pipeline_initiation_interval, or distribute}} */ #pragma clang loop
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword(enable)
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop vectorize(enable) badkeyword(4)
@@ -231,51 +231,50 @@ const int VV = 4;
// of the next three tests rather than the last, and the order of the kinds
// is also reversed.
-/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4)
-#pragma clang loop vectorize(disable)
-/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4)
-#pragma clang loop interleave(disable)
-/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4)
-#pragma clang loop unroll(disable)
+#pragma clang loop vectorize_width(4)
+/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable)
+#pragma clang loop interleave_count(4)
+/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable)
+#pragma clang loop unroll_count(4)
+/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable)
while (i-8 < Length) {
List[i] = i;
}
-/* expected-error {{duplicate directives 'vectorize(disable)' and 'vectorize(enable)'}} */ #pragma clang loop vectorize(enable)
-#pragma clang loop vectorize(disable)
-/* expected-error {{duplicate directives 'interleave(disable)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable)
-#pragma clang loop interleave(disable)
-/* expected-error {{duplicate directives 'unroll(disable)' and 'unroll(full)'}} */ #pragma clang loop unroll(full)
-#pragma clang loop unroll(disable)
-/* expected-error {{duplicate directives 'distribute(disable)' and 'distribute(enable)'}} */ #pragma clang loop distribute(enable)
-#pragma clang loop distribute(disable)
+#pragma clang loop vectorize(enable)
+/* expected-error {{duplicate directives 'vectorize(enable)' and 'vectorize(disable)'}} */ #pragma clang loop vectorize(disable)
+#pragma clang loop interleave(enable)
+/* expected-error {{duplicate directives 'interleave(enable)' and 'interleave(disable)'}} */ #pragma clang loop interleave(disable)
+#pragma clang loop unroll(full)
+/* expected-error {{duplicate directives 'unroll(full)' and 'unroll(disable)'}} */ #pragma clang loop unroll(disable)
+#pragma clang loop distribute(enable)
+/* expected-error {{duplicate directives 'distribute(enable)' and 'distribute(disable)'}} */ #pragma clang loop distribute(disable)
while (i-9 < Length) {
List[i] = i;
}
-/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable)
-#pragma clang loop vectorize_width(4)
-/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable)
-#pragma clang loop interleave_count(4)
-/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable)
-#pragma clang loop unroll_count(4)
+#pragma clang loop vectorize(disable)
+/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4)
+#pragma clang loop interleave(disable)
+/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4)
+#pragma clang loop unroll(disable)
+/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4)
while (i-10 < Length) {
List[i] = i;
}
-/* expected-error {{duplicate directives 'vectorize_width(4)' and 'vectorize_width(8)'}} */ #pragma clang loop vectorize_width(8)
-#pragma clang loop vectorize_width(4)
-/* expected-error {{duplicate directives 'interleave_count(4)' and 'interleave_count(8)'}} */ #pragma clang loop interleave_count(8)
-#pragma clang loop interleave_count(4)
-/* expected-error {{duplicate directives 'unroll_count(4)' and 'unroll_count(8)'}} */ #pragma clang loop unroll_count(8)
-#pragma clang loop unroll_count(4)
+#pragma clang loop vectorize_width(8)
+/* expected-error {{duplicate directives 'vectorize_width(8)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4)
+#pragma clang loop interleave_count(8)
+/* expected-error {{duplicate directives 'interleave_count(8)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4)
+#pragma clang loop unroll_count(8)
+/* expected-error {{duplicate directives 'unroll_count(8)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4)
while (i-11 < Length) {
List[i] = i;
}
-
-/* expected-error {{incompatible directives 'unroll(full)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(full)
-#pragma clang loop unroll_count(4)
+#pragma clang loop unroll(full)
+/* expected-error {{incompatible directives 'unroll(full)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4)
while (i-11 < Length) {
List[i] = i;
}
diff --git a/test/Parser/pragma-pipeline.cpp b/test/Parser/pragma-pipeline.cpp
new file mode 100644
index 000000000000..e500d4d2d5fb
--- /dev/null
+++ b/test/Parser/pragma-pipeline.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+// Note that this puts the expected lines before the directives to work around
+// limitations in the -verify mode.
+
+void test(int *List, int Length, int Value) {
+ int i = 0;
+
+#pragma clang loop pipeline(disable)
+ for (int i = 0; i < Length; i++) {
+ List[i] = Value;
+ }
+
+#pragma clang loop pipeline_initiation_interval(10)
+ for (int i = 0; i < Length; i++) {
+ List[i] = Value;
+ }
+
+/* expected-error {{expected ')'}} */ #pragma clang loop pipeline(disable
+/* expected-error {{invalid argument; expected 'disable'}} */ #pragma clang loop pipeline(enable)
+/* expected-error {{invalid argument; expected 'disable'}} */ #pragma clang loop pipeline(error)
+/* expected-error {{expected '('}} */ #pragma clang loop pipeline disable
+/* expected-error {{missing argument; expected an integer value}} */ #pragma clang loop pipeline_initiation_interval()
+/* expected-error {{use of undeclared identifier 'error'}} */ #pragma clang loop pipeline_initiation_interval(error)
+/* expected-error {{expected '('}} */ #pragma clang loop pipeline_initiation_interval 1 2
+/* expected-error {{expected ')'}} */ #pragma clang loop pipeline_initiation_interval(1
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+}
diff --git a/test/Parser/pragma-unroll-and-jam.cpp b/test/Parser/pragma-unroll-and-jam.cpp
new file mode 100644
index 000000000000..ef1867aa1955
--- /dev/null
+++ b/test/Parser/pragma-unroll-and-jam.cpp
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+// Note that this puts the expected lines before the directives to work around
+// limitations in the -verify mode.
+
+void test(int *List, int Length, int Value) {
+ int i = 0;
+
+#pragma unroll_and_jam
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+#pragma nounroll_and_jam
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+#pragma unroll_and_jam 4
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+/* expected-error {{expected ')'}} */ #pragma unroll_and_jam(4
+/* expected-error {{missing argument; expected an integer value}} */ #pragma unroll_and_jam()
+/* expected-warning {{extra tokens at end of '#pragma unroll_and_jam'}} */ #pragma unroll_and_jam 1 2
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+/* expected-warning {{extra tokens at end of '#pragma nounroll_and_jam'}} */ #pragma nounroll_and_jam 1
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+#pragma unroll_and_jam
+/* expected-error {{expected a for, while, or do-while loop to follow '#pragma unroll_and_jam'}} */ int j = Length;
+#pragma unroll_and_jam 4
+/* expected-error {{expected a for, while, or do-while loop to follow '#pragma unroll_and_jam'}} */ int k = Length;
+#pragma nounroll_and_jam
+/* expected-error {{expected a for, while, or do-while loop to follow '#pragma nounroll_and_jam'}} */ int l = Length;
+
+#pragma unroll_and_jam 4
+/* expected-error {{incompatible directives '#pragma nounroll_and_jam' and '#pragma unroll_and_jam(4)'}} */ #pragma nounroll_and_jam
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+#pragma nounroll_and_jam
+#pragma unroll(4)
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+// pragma clang unroll_and_jam is disabled for the moment
+/* expected-error {{invalid option 'unroll_and_jam'; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, pipeline, pipeline_initiation_interval, or distribute}} */ #pragma clang loop unroll_and_jam(4)
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+#pragma unroll_and_jam
+/* expected-error {{expected statement}} */ }
diff --git a/test/Parser/pragma-unroll.cpp b/test/Parser/pragma-unroll.cpp
index b1d779879831..fb713812877e 100644
--- a/test/Parser/pragma-unroll.cpp
+++ b/test/Parser/pragma-unroll.cpp
@@ -55,56 +55,56 @@ void test(int *List, int Length) {
#pragma nounroll
/* expected-error {{expected a for, while, or do-while loop to follow '#pragma nounroll'}} */ int l = Length;
-/* expected-error {{incompatible directives 'unroll(disable)' and '#pragma unroll(4)'}} */ #pragma unroll 4
-#pragma clang loop unroll(disable)
+#pragma unroll 4
+/* expected-error {{incompatible directives 'unroll(disable)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(disable)
while (i-10 < Length) {
List[i] = i;
}
-/* expected-error {{incompatible directives 'unroll(full)' and '#pragma unroll(4)'}} */ #pragma unroll(4)
-#pragma clang loop unroll(full)
+#pragma unroll(4)
+/* expected-error {{incompatible directives 'unroll(full)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(full)
while (i-11 < Length) {
List[i] = i;
}
-/* expected-error {{incompatible directives 'unroll(enable)' and '#pragma unroll(4)'}} */ #pragma unroll(4)
-#pragma clang loop unroll(enable)
+#pragma unroll(4)
+/* expected-error {{incompatible directives 'unroll(enable)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(enable)
while (i-11 < Length) {
List[i] = i;
}
-/* expected-error {{incompatible directives '#pragma unroll' and '#pragma unroll(4)'}} */ #pragma unroll(4)
-#pragma unroll
+#pragma unroll(4)
+/* expected-error {{incompatible directives '#pragma unroll' and '#pragma unroll(4)'}} */ #pragma unroll
while (i-11 < Length) {
List[i] = i;
}
-/* expected-error {{incompatible directives '#pragma nounroll' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4)
-#pragma nounroll
+#pragma clang loop unroll_count(4)
+/* expected-error {{incompatible directives '#pragma nounroll' and 'unroll_count(4)'}} */ #pragma nounroll
while (i-12 < Length) {
List[i] = i;
}
-/* expected-error {{duplicate directives '#pragma nounroll' and '#pragma nounroll'}} */ #pragma nounroll
#pragma nounroll
+/* expected-error {{duplicate directives '#pragma nounroll' and '#pragma nounroll'}} */ #pragma nounroll
while (i-13 < Length) {
List[i] = i;
}
-/* expected-error {{duplicate directives '#pragma unroll' and '#pragma unroll'}} */ #pragma unroll
#pragma unroll
+/* expected-error {{duplicate directives '#pragma unroll' and '#pragma unroll'}} */ #pragma unroll
while (i-14 < Length) {
List[i] = i;
}
-/* expected-error {{duplicate directives 'unroll(full)' and '#pragma unroll'}} */ #pragma unroll
-#pragma clang loop unroll(full)
+#pragma unroll
+/* expected-error {{duplicate directives '#pragma unroll' and 'unroll(full)'}} */ #pragma clang loop unroll(full)
while (i-15 < Length) {
List[i] = i;
}
-/* expected-error {{duplicate directives '#pragma unroll(4)' and '#pragma unroll(4)'}} */ #pragma unroll 4
-#pragma unroll(4)
+#pragma unroll 4
+/* expected-error {{duplicate directives '#pragma unroll(4)' and '#pragma unroll(4)'}} */ #pragma unroll(4)
while (i-16 < Length) {
List[i] = i;
}
diff --git a/test/Parser/switch-recovery.cpp b/test/Parser/switch-recovery.cpp
index a3a0178cd10b..eacd017ab236 100644
--- a/test/Parser/switch-recovery.cpp
+++ b/test/Parser/switch-recovery.cpp
@@ -105,7 +105,7 @@ void test9(int x) { // expected-note {{'x' declared here}}
expected-error {{expected expression}}
8:: x; // expected-error {{expected ';' after expression}} \
expected-error {{no member named 'x' in the global namespace; did you mean simply 'x'?}} \
- expected-warning 2 {{expression result unused}}
+ expected-warning {{expression result unused}}
9:: :y; // expected-error {{expected ';' after expression}} \
expected-error {{expected unqualified-id}} \
expected-warning {{expression result unused}}
diff --git a/test/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c
index 92df0004e906..5ab43313468e 100644
--- a/test/Preprocessor/aarch64-target-features.c
+++ b/test/Preprocessor/aarch64-target-features.c
@@ -93,18 +93,51 @@
// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.2a+dotprod -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-DOTPROD %s
// CHECK-DOTPROD: __ARM_FEATURE_DOTPROD 1
-// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// On ARMv8.2-A and above, +fp16fml implies +fp16.
+// On ARMv8.4-A and above, +fp16 implies +fp16fml.
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-FML --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// CHECK-FULLFP16-FML: #define __ARM_FEATURE_FP16FML 1
+// CHECK-FULLFP16-NOFML-NOT: #define __ARM_FEATURE_FP16FML 1
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP 0xE
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
-// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// +fp16fml+nosimd doesn't make sense as the fp16fml instructions all require SIMD.
+// However, as +fp16fml implies +fp16 there is a set of defines that we would expect.
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16fml+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8-a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16fml+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16+nosimd -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16FML 1
// CHECK-FULLFP16-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
// CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
// CHECK-FULLFP16-SCALAR: #define __ARM_FP 0xE
// CHECK-FULLFP16-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.2-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target aarch64-none-linux-gnueabi -march=armv8.4-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16FML 1
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR: #define __ARM_FP 0xE
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
// ================== Check whether -mtune accepts mixed-case features.
// RUN: %clang -target aarch64 -mtune=CYCLONE -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MTUNE-CYCLONE %s
// CHECK-MTUNE-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+zcm" "-target-feature" "+zcz"
@@ -118,7 +151,7 @@
// RUN: %clang -target aarch64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
// RUN: %clang -target aarch64 -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
// RUN: %clang -target aarch64 -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
-// RUN: %clang -target aarch64 -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s
+// RUN: %clang -target aarch64 -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M4 %s
// RUN: %clang -target aarch64 -mcpu=kryo -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-KRYO %s
// RUN: %clang -target aarch64 -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-THUNDERX2T99 %s
// CHECK-MCPU-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz"
@@ -128,6 +161,7 @@
// CHECK-MCPU-A72: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto"
// CHECK-MCPU-CORTEX-A73: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto"
// CHECK-MCPU-M1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto"
+// CHECK-MCPU-M4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fullfp16"
// CHECK-MCPU-KRYO: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto"
// CHECK-MCPU-THUNDERX2T99: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto"
@@ -143,6 +177,101 @@
// CHECK-MARCH-2: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "-fp-armv8" "-target-feature" "-neon" "-target-feature" "-crc" "-target-feature" "-crypto"
// CHECK-MARCH-3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "-neon"
+// Check +sm4:
+//
+// RUN: %clang -target aarch64 -march=armv8.2a+sm4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-SM4 %s
+// CHECK-SM4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+sm4"
+//
+// Check +sha3:
+//
+// RUN: %clang -target aarch64 -march=armv8.2a+sha3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-SHA3 %s
+// CHECK-SHA3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+sha3"
+//
+// Check +sha2:
+//
+// RUN: %clang -target aarch64 -march=armv8.3a+sha2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-SHA2 %s
+// CHECK-SHA2: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.{{.}}a" "-target-feature" "+sha2"
+//
+// Check +aes:
+//
+// RUN: %clang -target aarch64 -march=armv8.3a+aes -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-AES %s
+// CHECK-AES: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.{{.}}a" "-target-feature" "+aes"
+//
+// Check -sm4:
+//
+// RUN: %clang -target aarch64 -march=armv8.2a+noSM4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SM4 %s
+// CHECK-NO-SM4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "-sm4"
+//
+// Check -sha3:
+//
+// RUN: %clang -target aarch64 -march=armv8.2a+noSHA3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SHA3 %s
+// CHECK-NO-SHA3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "-sha3"
+//
+// Check -sha2:
+//
+// RUN: %clang -target aarch64 -march=armv8.2a+noSHA2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NO-SHA2 %s
+// CHECK-NO-SHA2: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "-sha2"
+//
+// Check -aes:
+//
+// RUN: %clang -target aarch64 -march=armv8.2a+noAES -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NO-AES %s
+// CHECK-NO-AES: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "-aes"
+//
+//
+// Arch <= ARMv8.3: crypto = sha2 + aes
+// -------------------------------------
+//
+// Check +crypto:
+//
+// RUN: %clang -target aarch64 -march=armv8a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO83 %s
+// RUN: %clang -target aarch64 -march=armv8.1a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO83 %s
+// RUN: %clang -target aarch64 -march=armv8.2a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO83 %s
+// RUN: %clang -target aarch64 -march=armv8.3a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO83 %s
+// RUN: %clang -target aarch64 -march=armv8a+crypto+nocrypto+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO83 %s
+// CHECK-CRYPTO83: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+crypto" "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check -crypto:
+//
+// RUN: %clang -target aarch64 -march=armv8a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO8A %s
+// RUN: %clang -target aarch64 -march=armv8.1a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO81 %s
+// RUN: %clang -target aarch64 -march=armv8.2a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO82 %s
+// RUN: %clang -target aarch64 -march=armv8.3a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO82 %s
+// RUN: %clang -target aarch64 -march=armv8.3a+nocrypto+crypto+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO82 %s
+
+// CHECK-NOCRYPTO8A: "-target-feature" "+neon" "-target-feature" "-crypto" "-target-feature" "-sha2" "-target-feature" "-aes" "-target-abi" "aapcs"
+// CHECK-NOCRYPTO81: "-target-feature" "+neon" "-target-feature" "+v8.1a" "-target-feature" "-crypto" "-target-feature" "-sha2" "-target-feature" "-aes" "-target-abi" "aapcs"
+// CHECK-NOCRYPTO82: "-target-feature" "+neon" "-target-feature" "+v8.{{.}}a" "-target-feature" "-crypto" "-target-feature" "-sha2" "-target-feature" "-aes" "-target-feature" "-sm4" "-target-feature" "-sha3" "-target-abi" "aapcs"
+//
+// Check +crypto -sha2 -aes:
+//
+// RUN: %clang -target aarch64 -march=armv8.1a+crypto+nosha2+noaes -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO83-NOSHA2-NOAES %s
+// CHECK-CRYPTO83-NOSHA2-NOAES-NOT: "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check -crypto +sha2 +aes:
+//
+// RUN: %clang -target aarch64 -march=armv8.1a+nocrypto+sha2+aes -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO83-SHA2-AES %s
+// CHECK-NOCRYPTO83-SHA2-AES: "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+//
+// Arch >= ARMv8.4: crypto = sm4 + sha3 + sha2 + aes
+// --------------------------------------------------
+//
+// Check +crypto:
+//
+// RUN: %clang -target aarch64 -march=armv8.4a+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO84 %s
+// CHECK-CRYPTO84: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.4a" "-target-feature" "+crypto" "-target-feature" "+sm4" "-target-feature" "+sha3" "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check -crypto:
+//
+// RUN: %clang -target aarch64 -march=armv8.4a+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRYPTO84 %s
+// CHECK-NOCRYPTO84-NOT: "-target-feature" "+crypto" "-target-feature" "+sm4" "-target-feature" "+sha3" "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+// Check +crypto -sm4 -sha3:
+//
+// RUN: %clang -target aarch64 -march=armv8.4a+crypto+sm4+nosm4+sha3+nosha3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRYPTO84-NOSMSHA %s
+// CHECK-CRYPTO84-NOSMSHA: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.4a" "-target-feature" "+crypto" "-target-feature" "-sm4" "-target-feature" "-sha3" "-target-feature" "+sha2" "-target-feature" "+aes"
+//
+//
// RUN: %clang -target aarch64 -mcpu=cyclone+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-1 %s
// RUN: %clang -target aarch64 -mcpu=cyclone+crypto+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-1 %s
// RUN: %clang -target aarch64 -mcpu=generic+crc -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-2 %s
diff --git a/test/Preprocessor/arm-acle-6.4.c b/test/Preprocessor/arm-acle-6.4.c
index 9e4253a3596c..fcabe028b955 100644
--- a/test/Preprocessor/arm-acle-6.4.c
+++ b/test/Preprocessor/arm-acle-6.4.c
@@ -174,10 +174,21 @@
// CHECK-V7M: __ARM_FEATURE_SAT 1
// CHECK-V7M: __ARM_FEATURE_UNALIGNED 1
-// RUN: %clang -target arm-none-linux-eabi -march=armv7e-m -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V7EM
-
-// CHECK-V7EM: __ARM_FEATURE_DSP 1
-// CHECK-V7EM: __ARM_FEATURE_SIMD32 1
+// RUN: %clang -target arm-none-linux-eabi -march=armv7-m -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-NODSP
+// RUN: %clang -target arm-none-linux-eabi -march=armv7e-m -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP
+// RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m3 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-NODSP
+// RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m4 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP
+// RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m7 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP
+// RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m0plus -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-NODSP
+// RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m23 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-NODSP
+// RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m33 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP
+// RUN: %clang --target=arm-arm-none-eabi -march=armv8m.main+dsp -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP
+
+// CHECK-M-DSP: __ARM_FEATURE_DSP 1
+// CHECK-M-DSP: __ARM_FEATURE_SIMD32 1
+
+// CHECK-M-NODSP-NOT: __ARM_FEATURE_DSP 1
+// CHECK-M-NODSP-NOT: __ARM_FEATURE_SIMD32 1
// RUN: %clang -target arm-none-linux-eabi -march=armv8-a -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V8A
diff --git a/test/Preprocessor/arm-target-features.c b/test/Preprocessor/arm-target-features.c
index a982d8085028..004aaac5c3c3 100644
--- a/test/Preprocessor/arm-target-features.c
+++ b/test/Preprocessor/arm-target-features.c
@@ -21,18 +21,58 @@
// CHECK-V8A-ALLOW-FP-INSTR: #define __ARM_FP16_FORMAT_IEEE 1
// CHECK-V8A-ALLOW-FP-INSTR-V8A-NOT: #define __ARM_FEATURE_DOTPROD
-// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+nofp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+nofp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+fp16+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-VECTOR-SCALAR %s
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP 0xe
// CHECK-FULLFP16-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
-// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+fp16 -mfpu=vfp4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// +fp16fml without neon doesn't make sense as the fp16fml instructions all require SIMD.
+// However, as +fp16fml implies +fp16 there is a set of defines that we would expect.
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8-a+fp16fml -mfpu=vfp4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8-a+fp16 -mfpu=vfp4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+fp16fml -mfpu=vfp4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+fp16 -mfpu=vfp4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SCALAR %s
// CHECK-FULLFP16-SCALAR: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
// CHECK-FULLFP16-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
// CHECK-FULLFP16-SCALAR: #define __ARM_FP 0xe
// CHECK-FULLFP16-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
-//
+
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+nofp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.4-a+fp16fml+nofp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-NOFML-VECTOR-SCALAR %s
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC 1
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR: #define __ARM_FP 0xe
+// CHECK-FULLFP16-NOFML-VECTOR-SCALAR: #define __ARM_FP16_FORMAT_IEEE 1
+
+// RUN: %clang -target arm -march=armv8-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8-a+fp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8-a+fp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16+fp16fml -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// RUN: %clang -target arm -march=armv8.4-a+fp16fml+fp16 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-FULLFP16-SOFT %s
+// CHECK-FULLFP16-SOFT-NOT: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC
+// CHECK-FULLFP16-SOFT-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
+// CHECK-FULLFP16-SOFT-NOT: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC
+// CHECK-FULLFP16-SOFT-NOT: #define __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
+
// RUN: %clang -target arm-none-linux-gnueabi -march=armv8.2a+dotprod -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-DOTPROD %s
// CHECK-DOTPROD: #define __ARM_FEATURE_DOTPROD 1
@@ -697,3 +737,18 @@
// CHECK-V82A: #define __ARM_ARCH_PROFILE 'A'
// CHECK-V82A: #define __ARM_FEATURE_QRDMX 1
// CHECK-V82A: #define __ARM_FP 0xe
+
+// RUN: %clang -target armv8.3a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V83A %s
+// CHECK-V83A: #define __ARM_ARCH 8
+// CHECK-V83A: #define __ARM_ARCH_8_3A__ 1
+// CHECK-V83A: #define __ARM_ARCH_PROFILE 'A'
+
+// RUN: %clang -target armv8.4a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V84A %s
+// CHECK-V84A: #define __ARM_ARCH 8
+// CHECK-V84A: #define __ARM_ARCH_8_4A__ 1
+// CHECK-V84A: #define __ARM_ARCH_PROFILE 'A'
+
+// RUN: %clang -target armv8.5a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V85A %s
+// CHECK-V85A: #define __ARM_ARCH 8
+// CHECK-V85A: #define __ARM_ARCH_8_5A__ 1
+// CHECK-V85A: #define __ARM_ARCH_PROFILE 'A'
diff --git a/test/Preprocessor/c17.c b/test/Preprocessor/c17.c
index c610e84f9830..7031eec11ed5 100644
--- a/test/Preprocessor/c17.c
+++ b/test/Preprocessor/c17.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c17 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c18 %s
// expected-no-diagnostics
_Static_assert(__STDC_VERSION__ == 201710L, "Incorrect __STDC_VERSION__");
diff --git a/test/Preprocessor/empty_file_to_include.h b/test/Preprocessor/empty_file_to_include.h
new file mode 100644
index 000000000000..48ffc7515386
--- /dev/null
+++ b/test/Preprocessor/empty_file_to_include.h
@@ -0,0 +1,7 @@
+
+#ifndef EMPTY_FILE_TO_INCLUDE_H
+#define EMPTY_FILE_TO_INCLUDE_H
+
+// empty file
+
+#endif
diff --git a/test/Preprocessor/feature_tests.c b/test/Preprocessor/feature_tests.c
index 52a1f17cdd4f..c2fbd11c97cd 100644
--- a/test/Preprocessor/feature_tests.c
+++ b/test/Preprocessor/feature_tests.c
@@ -14,6 +14,7 @@
!__has_builtin(__builtin_convertvector) || \
!__has_builtin(__builtin_trap) || \
!__has_builtin(__c11_atomic_init) || \
+ !__has_builtin(__builtin_launder) || \
!__has_feature(attribute_analyzer_noreturn) || \
!__has_feature(attribute_overloadable)
#error Clang should have these
diff --git a/test/Preprocessor/has_attribute.cpp b/test/Preprocessor/has_attribute.cpp
index 2cfa005fb09f..91f3501666fc 100644
--- a/test/Preprocessor/has_attribute.cpp
+++ b/test/Preprocessor/has_attribute.cpp
@@ -21,14 +21,34 @@
int has_clang_fallthrough_2();
#endif
-// The scope cannot be bracketed with double underscores.
+// The scope cannot be bracketed with double underscores unless it is
+// for gnu or clang.
+// CHECK: does_not_have___gsl___suppress
+#if !__has_cpp_attribute(__gsl__::suppress)
+ int does_not_have___gsl___suppress();
+#endif
+
+// We do somewhat support the __clang__ vendor namespace, but it is a
+// predefined macro and thus we encourage users to use _Clang instead.
+// Because of this, we do not support __has_cpp_attribute for that
+// vendor namespace.
// CHECK: does_not_have___clang___fallthrough
#if !__has_cpp_attribute(__clang__::fallthrough)
int does_not_have___clang___fallthrough();
#endif
-// Test that C++11, target-specific attributes behave properly.
+// CHECK: does_have_Clang_fallthrough
+#if __has_cpp_attribute(_Clang::fallthrough)
+ int does_have_Clang_fallthrough();
+#endif
+// CHECK: has_gnu_const
+#if __has_cpp_attribute(__gnu__::__const__)
+ int has_gnu_const();
+#endif
+
+// Test that C++11, target-specific attributes behave properly.
+
// CHECK: does_not_have_mips16
#if !__has_cpp_attribute(gnu::mips16)
int does_not_have_mips16();
diff --git a/test/Preprocessor/hexagon-predefines.c b/test/Preprocessor/hexagon-predefines.c
index fe87262ae635..1d122c0e8275 100644
--- a/test/Preprocessor/hexagon-predefines.c
+++ b/test/Preprocessor/hexagon-predefines.c
@@ -34,6 +34,8 @@
// CHECK-V65: #define __hexagon__ 1
// The HVX flags are explicitly defined by the driver.
+// For v60,v62,v65 - 64B mode is default
+// For v66 and future archs - 128B is default
// RUN: %clang_cc1 -E -dM -triple hexagon-unknown-elf -target-cpu hexagonv60 \
// RUN: -target-feature +hvxv60 -target-feature +hvx-length64b %s | FileCheck \
// RUN: %s -check-prefix CHECK-V60HVX-64B
@@ -55,3 +57,25 @@
// CHECK-V60HVX-128B: #define __HVX_LENGTH__ 128
// CHECK-V60HVX-128B: #define __HVX__ 1
// CHECK-V60HVX-128B: #define __hexagon__ 1
+
+// RUN: %clang_cc1 -E -dM -triple hexagon-unknown-elf -target-cpu hexagonv66 \
+// RUN: -target-feature +hvxv66 -target-feature +hvx-length64b %s | FileCheck \
+// RUN: %s -check-prefix CHECK-V66HVX-64B
+// CHECK-V66HVX-64B: #define __HEXAGON_ARCH__ 66
+// CHECK-V66HVX-64B: #define __HEXAGON_V66__ 1
+// CHECK-V66HVX-64B-NOT: #define __HVXDBL__ 1
+// CHECK-V66HVX-64B: #define __HVX_ARCH__ 66
+// CHECK-V66HVX-64B: #define __HVX_LENGTH__ 64
+// CHECK-V66HVX-64B: #define __HVX__ 1
+// CHECK-V66HVX-64B: #define __hexagon__ 1
+
+// RUN: %clang_cc1 -E -dM -triple hexagon-unknown-elf -target-cpu hexagonv66 \
+// RUN: -target-feature +hvxv66 -target-feature +hvx-length128b %s | FileCheck \
+// RUN: %s -check-prefix CHECK-V66HVX-128B
+// CHECK-V66HVX-128B: #define __HEXAGON_ARCH__ 66
+// CHECK-V66HVX-128B: #define __HEXAGON_V66__ 1
+// CHECK-V66HVX-128B: #define __HVXDBL__ 1
+// CHECK-V66HVX-128B: #define __HVX_ARCH__ 66
+// CHECK-V66HVX-128B: #define __HVX_LENGTH__ 128
+// CHECK-V66HVX-128B: #define __HVX__ 1
+// CHECK-V66HVX-128B: #define __hexagon__ 1
diff --git a/test/Preprocessor/include-leading-nonalpha-no-suggest.c b/test/Preprocessor/include-leading-nonalpha-no-suggest.c
new file mode 100644
index 000000000000..0d7dd1aea307
--- /dev/null
+++ b/test/Preprocessor/include-leading-nonalpha-no-suggest.c
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 %s -verify
+
+#include "/non_existing_file_to_include.h" // expected-error {{'/non_existing_file_to_include.h' file not found}}
diff --git a/test/Preprocessor/include-likely-typo.c b/test/Preprocessor/include-likely-typo.c
new file mode 100644
index 000000000000..89abe2a6e87b
--- /dev/null
+++ b/test/Preprocessor/include-likely-typo.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 %s -verify
+// RUN: %clang_cc1 -fms-compatibility %s -verify
+
+#include "<empty_file_to_include.h>" // expected-error {{'<empty_file_to_include.h>' file not found, did you mean 'empty_file_to_include.h'?}}
diff --git a/test/Preprocessor/include-nonalpha-no-crash.c b/test/Preprocessor/include-nonalpha-no-crash.c
new file mode 100644
index 000000000000..31c1348f021d
--- /dev/null
+++ b/test/Preprocessor/include-nonalpha-no-crash.c
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 %s -verify
+
+#include "./" // expected-error {{'./' file not found}}
diff --git a/test/Preprocessor/include-pth.c b/test/Preprocessor/include-pth.c
deleted file mode 100644
index e1d6685d1fa5..000000000000
--- a/test/Preprocessor/include-pth.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %clang_cc1 -emit-pth %s -o %t
-// RUN: %clang_cc1 -include-pth %t %s -E | grep 'file_to_include' | count 2
-#include "file_to_include.h"
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index 68d057d87b08..940dddade337 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -47,21 +47,21 @@
// CXX11:#define __cplusplus 201103L
// CXX11:#define __private_extern__ extern
//
-//
+//
// RUN: %clang_cc1 -x c++ -std=c++98 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX98 %s
-//
+//
// CXX98:#define __GNUG__ {{.*}}
// CXX98:#define __GXX_RTTI 1
// CXX98:#define __GXX_WEAK__ 1
// CXX98:#define __cplusplus 199711L
// CXX98:#define __private_extern__ extern
//
-//
+//
// RUN: %clang_cc1 -fdeprecated-macro -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix DEPRECATED %s
//
// DEPRECATED:#define __DEPRECATED 1
//
-//
+//
// RUN: %clang_cc1 -std=c99 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C99 %s
//
// C99:#define __STDC_VERSION__ 199901L
@@ -71,7 +71,7 @@
// C99-NOT: __GXX_WEAK__
// C99-NOT: __cplusplus
//
-//
+//
// RUN: %clang_cc1 -std=c11 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
// RUN: %clang_cc1 -std=c1x -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
// RUN: %clang_cc1 -std=iso9899:2011 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
@@ -86,7 +86,7 @@
// C11-NOT: __GXX_WEAK__
// C11-NOT: __cplusplus
//
-//
+//
// RUN: %clang_cc1 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix COMMON %s
//
// COMMON:#define __CONSTANT_CFSTRINGS__ 1
@@ -113,7 +113,7 @@
// RUN: %clang_cc1 -E -dM -triple=x86_64-pc-linux-gnu < /dev/null | FileCheck -match-full-lines -check-prefix C-DEFAULT %s
// RUN: %clang_cc1 -E -dM -triple=x86_64-apple-darwin < /dev/null | FileCheck -match-full-lines -check-prefix C-DEFAULT %s
// RUN: %clang_cc1 -E -dM -triple=armv7a-apple-darwin < /dev/null | FileCheck -match-full-lines -check-prefix C-DEFAULT %s
-//
+//
// C-DEFAULT:#define __STDC_VERSION__ 201112L
//
// RUN: %clang_cc1 -ffreestanding -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix FREESTANDING %s
@@ -158,12 +158,12 @@
// GXX98:#define __cplusplus 199711L
// GXX98:#define __private_extern__ extern
//
-//
+//
// RUN: %clang_cc1 -std=iso9899:199409 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C94 %s
//
// C94:#define __STDC_VERSION__ 199409L
//
-//
+//
// RUN: %clang_cc1 -fms-extensions -triple i686-pc-win32 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MSEXT %s
//
// MSEXT-NOT:#define __STDC__
@@ -185,7 +185,7 @@
// MSEXT-CXX-NOWCHAR-NOT:#define _WCHAR_T_DEFINED 1
// MSEXT-CXX-NOWCHAR:#define __BOOL_DEFINED 1
//
-//
+//
// RUN: %clang_cc1 -x objective-c -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix OBJC %s
//
// OBJC:#define OBJC_NEW_PROPERTIES 1
@@ -197,7 +197,7 @@
//
// OBJCGC:#define __OBJC_GC__ 1
//
-//
+//
// RUN: %clang_cc1 -x objective-c -fobjc-exceptions -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix NONFRAGILE %s
//
// NONFRAGILE:#define OBJC_ZEROCOST_EXCEPTIONS 1
@@ -246,9 +246,9 @@
//
// PASCAL:#define __PASCAL_STRINGS__ 1
//
-//
+//
// RUN: %clang_cc1 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix SCHAR %s
-//
+//
// SCHAR:#define __STDC__ 1
// SCHAR-NOT:#define __UNSIGNED_CHAR__
// SCHAR:#define __clang__ 1
@@ -1331,10 +1331,10 @@
// AARCH64-DARWIN: #define __INT_FAST32_FMTi__ "i"
// AARCH64-DARWIN: #define __INT_FAST32_MAX__ 2147483647
// AARCH64-DARWIN: #define __INT_FAST32_TYPE__ int
-// AARCH64-DARWIN: #define __INT_FAST64_FMTd__ "ld"
-// AARCH64-DARWIN: #define __INT_FAST64_FMTi__ "li"
-// AARCH64-DARWIN: #define __INT_FAST64_MAX__ 9223372036854775807L
-// AARCH64-DARWIN: #define __INT_FAST64_TYPE__ long int
+// AARCH64-DARWIN: #define __INT_FAST64_FMTd__ "lld"
+// AARCH64-DARWIN: #define __INT_FAST64_FMTi__ "lli"
+// AARCH64-DARWIN: #define __INT_FAST64_MAX__ 9223372036854775807LL
+// AARCH64-DARWIN: #define __INT_FAST64_TYPE__ long long int
// AARCH64-DARWIN: #define __INT_FAST8_FMTd__ "hhd"
// AARCH64-DARWIN: #define __INT_FAST8_FMTi__ "hhi"
// AARCH64-DARWIN: #define __INT_FAST8_MAX__ 127
@@ -1347,10 +1347,10 @@
// AARCH64-DARWIN: #define __INT_LEAST32_FMTi__ "i"
// AARCH64-DARWIN: #define __INT_LEAST32_MAX__ 2147483647
// AARCH64-DARWIN: #define __INT_LEAST32_TYPE__ int
-// AARCH64-DARWIN: #define __INT_LEAST64_FMTd__ "ld"
-// AARCH64-DARWIN: #define __INT_LEAST64_FMTi__ "li"
-// AARCH64-DARWIN: #define __INT_LEAST64_MAX__ 9223372036854775807L
-// AARCH64-DARWIN: #define __INT_LEAST64_TYPE__ long int
+// AARCH64-DARWIN: #define __INT_LEAST64_FMTd__ "lld"
+// AARCH64-DARWIN: #define __INT_LEAST64_FMTi__ "lli"
+// AARCH64-DARWIN: #define __INT_LEAST64_MAX__ 9223372036854775807LL
+// AARCH64-DARWIN: #define __INT_LEAST64_TYPE__ long long int
// AARCH64-DARWIN: #define __INT_LEAST8_FMTd__ "hhd"
// AARCH64-DARWIN: #define __INT_LEAST8_FMTi__ "hhi"
// AARCH64-DARWIN: #define __INT_LEAST8_MAX__ 127
@@ -1418,16 +1418,16 @@
// AARCH64-DARWIN: #define __UINT_FAST16_TYPE__ unsigned short
// AARCH64-DARWIN: #define __UINT_FAST32_MAX__ 4294967295U
// AARCH64-DARWIN: #define __UINT_FAST32_TYPE__ unsigned int
-// AARCH64-DARWIN: #define __UINT_FAST64_MAX__ 18446744073709551615UL
-// AARCH64-DARWIN: #define __UINT_FAST64_TYPE__ long unsigned int
+// AARCH64-DARWIN: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
+// AARCH64-DARWIN: #define __UINT_FAST64_TYPE__ long long unsigned int
// AARCH64-DARWIN: #define __UINT_FAST8_MAX__ 255
// AARCH64-DARWIN: #define __UINT_FAST8_TYPE__ unsigned char
// AARCH64-DARWIN: #define __UINT_LEAST16_MAX__ 65535
// AARCH64-DARWIN: #define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64-DARWIN: #define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64-DARWIN: #define __UINT_LEAST32_TYPE__ unsigned int
-// AARCH64-DARWIN: #define __UINT_LEAST64_MAX__ 18446744073709551615UL
-// AARCH64-DARWIN: #define __UINT_LEAST64_TYPE__ long unsigned int
+// AARCH64-DARWIN: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+// AARCH64-DARWIN: #define __UINT_LEAST64_TYPE__ long long unsigned int
// AARCH64-DARWIN: #define __UINT_LEAST8_MAX__ 255
// AARCH64-DARWIN: #define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64-DARWIN: #define __USER_LABEL_PREFIX__ _
@@ -1553,7 +1553,7 @@
// AARCH64-MSVC: #define __SIZEOF_SHORT__ 2
// AARCH64-MSVC: #define __SIZEOF_SIZE_T__ 8
// AARCH64-MSVC: #define __SIZEOF_WCHAR_T__ 2
-// AARCH64-MSVC: #define __SIZEOF_WINT_T__ 4
+// AARCH64-MSVC: #define __SIZEOF_WINT_T__ 2
// AARCH64-MSVC: #define __SIZE_MAX__ 18446744073709551615ULL
// AARCH64-MSVC: #define __SIZE_TYPE__ long long unsigned int
// AARCH64-MSVC: #define __SIZE_WIDTH__ 64
@@ -1602,8 +1602,8 @@
// AARCH64-MSVC: #define __WCHAR_TYPE__ unsigned short
// AARCH64-MSVC: #define __WCHAR_UNSIGNED__ 1
// AARCH64-MSVC: #define __WCHAR_WIDTH__ 16
-// AARCH64-MSVC: #define __WINT_TYPE__ int
-// AARCH64-MSVC: #define __WINT_WIDTH__ 32
+// AARCH64-MSVC: #define __WINT_TYPE__ unsigned short
+// AARCH64-MSVC: #define __WINT_WIDTH__ 16
// AARCH64-MSVC: #define __aarch64__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM %s
@@ -2590,6 +2590,7 @@
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-eabihf < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-eabi < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-eabihf < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-elf < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// ARM-NONE-EABI: #define __ELF__ 1
// No MachO targets use the full EABI, even if AAPCS is used.
@@ -3442,7 +3443,7 @@
// MIPS32BE:#define __mips 32
// MIPS32BE:#define __mips__ 1
// MIPS32BE:#define __mips_abicalls 1
-// MIPS32BE:#define __mips_fpr 32
+// MIPS32BE:#define __mips_fpr 0
// MIPS32BE:#define __mips_hard_float 1
// MIPS32BE:#define __mips_o32 1
// MIPS32BE:#define _mips 1
@@ -3649,7 +3650,7 @@
// MIPS32EL:#define __mips 32
// MIPS32EL:#define __mips__ 1
// MIPS32EL:#define __mips_abicalls 1
-// MIPS32EL:#define __mips_fpr 32
+// MIPS32EL:#define __mips_fpr 0
// MIPS32EL:#define __mips_hard_float 1
// MIPS32EL:#define __mips_o32 1
// MIPS32EL:#define _mips 1
@@ -4900,6 +4901,41 @@
// RUN: | FileCheck -match-full-lines -check-prefix NOMIPS-ABS2008 %s
// NOMIPS-ABS2008-NOT:#define __mips_abs2008 1
//
+// RUN: %clang_cc1 \
+// RUN: -E -dM -triple=mips-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-NOFP %s
+// MIPS32-NOFP:#define __mips_fpr 0
+//
+// RUN: %clang_cc1 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFPXX %s
+// MIPS32-MFPXX:#define __mips_fpr 0
+//
+// RUN: %clang_cc1 -target-cpu mips32r6 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS32R6-MFPXX %s
+// MIPS32R6-MFPXX:#define __mips_fpr 0
+//
+// RUN: %clang_cc1 \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-NOFP %s
+// MIPS64-NOFP:#define __mips_fpr 64
+//
+// RUN: not %clang_cc1 -target-feature -fp64 \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-MFP32 %s
+// MIPS64-MFP32:error: option '-mfpxx' cannot be specified with 'mips64r2'
+//
+// RUN: not %clang_cc1 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-MFPXX %s
+// MIPS64-MFPXX:error: '-mfpxx' can only be used with the 'o32' ABI
+//
+// RUN: not %clang_cc1 -target-cpu mips64r6 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64R6-MFPXX %s
+// MIPS64R6-MFPXX:error: '-mfpxx' can only be used with the 'o32' ABI
+//
// RUN: %clang_cc1 -target-feature -fp64 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFP32 %s
@@ -4916,7 +4952,7 @@
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFP32SF %s
// MIPS32-MFP32SF:#define _MIPS_FPSET 32
-// MIPS32-MFP32SF:#define __mips_fpr 32
+// MIPS32-MFP32SF:#define __mips_fpr 0
//
// RUN: %clang_cc1 -target-feature +fp64 \
// RUN: -E -dM -triple=mips64-none-none < /dev/null \
@@ -7943,6 +7979,7 @@
// X86_64:#define __WINT_WIDTH__ 32
// X86_64:#define __amd64 1
// X86_64:#define __amd64__ 1
+// X86_64:#define __code_model_small_ 1
// X86_64:#define __x86_64 1
// X86_64:#define __x86_64__ 1
//
@@ -7952,7 +7989,10 @@
// X86_64H:#define __x86_64__ 1
// X86_64H:#define __x86_64h 1
// X86_64H:#define __x86_64h__ 1
-
+//
+// RUN: %clang -xc - -E -dM -mcmodel=medium --target=i386-unknown-linux < /dev/null | FileCheck -match-full-lines -check-prefix X86_MEDIUM %s
+// X86_MEDIUM:#define __code_model_medium_ 1
+//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 -check-prefix X32-CXX %s
//
@@ -9017,9 +9057,10 @@
// RUN: %clang_cc1 -triple arm-linux-androideabi -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix ANDROID %s
// ANDROID-NOT:#define __ANDROID_API__
// ANDROID:#define __ANDROID__ 1
+// ANDROID-NOT:#define __gnu_linux__
//
// RUN: %clang_cc1 -x c++ -triple i686-linux-android -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix I386-ANDROID-CXX %s
-// I386-ANDROID-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 4U
+// I386-ANDROID-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
//
// RUN: %clang_cc1 -x c++ -triple x86_64-linux-android -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix X86_64-ANDROID-CXX %s
// X86_64-ANDROID-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
@@ -9027,6 +9068,7 @@
// RUN: %clang_cc1 -triple arm-linux-androideabi20 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix ANDROID20 %s
// ANDROID20:#define __ANDROID_API__ 20
// ANDROID20:#define __ANDROID__ 1
+// ANDROID-NOT:#define __gnu_linux__
//
// RUN: %clang_cc1 -triple lanai-unknown-unknown -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix LANAI %s
// LANAI: #define __lanai__ 1
@@ -9795,7 +9837,7 @@
// AVR:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
// AVR:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
// AVR:#define __GXX_ABI_VERSION 1002
-// AVR:#define __INT16_C_SUFFIX__
+// AVR:#define __INT16_C_SUFFIX__
// AVR:#define __INT16_MAX__ 32767
// AVR:#define __INT16_TYPE__ short
// AVR:#define __INT32_C_SUFFIX__ L
@@ -9804,7 +9846,7 @@
// AVR:#define __INT64_C_SUFFIX__ LL
// AVR:#define __INT64_MAX__ 9223372036854775807LL
// AVR:#define __INT64_TYPE__ long long int
-// AVR:#define __INT8_C_SUFFIX__
+// AVR:#define __INT8_C_SUFFIX__
// AVR:#define __INT8_MAX__ 127
// AVR:#define __INT8_TYPE__ signed char
// AVR:#define __INTMAX_C_SUFFIX__ LL
@@ -9879,7 +9921,7 @@
// AVR:#define __UINT64_C_SUFFIX__ ULL
// AVR:#define __UINT64_MAX__ 18446744073709551615ULL
// AVR:#define __UINT64_TYPE__ long long unsigned int
-// AVR:#define __UINT8_C_SUFFIX__
+// AVR:#define __UINT8_C_SUFFIX__
// AVR:#define __UINT8_MAX__ 255
// AVR:#define __UINT8_TYPE__ unsigned char
// AVR:#define __UINTMAX_C_SUFFIX__ ULL
@@ -9903,7 +9945,7 @@
// AVR:#define __UINT_LEAST64_TYPE__ long long unsigned int
// AVR:#define __UINT_LEAST8_MAX__ 255
// AVR:#define __UINT_LEAST8_TYPE__ unsigned char
-// AVR:#define __USER_LABEL_PREFIX__
+// AVR:#define __USER_LABEL_PREFIX__
// AVR:#define __WCHAR_MAX__ 32767
// AVR:#define __WCHAR_TYPE__ int
// AVR:#define __WINT_TYPE__ int
diff --git a/test/Preprocessor/pragma.c b/test/Preprocessor/pragma.c
new file mode 100644
index 000000000000..b491632403aa
--- /dev/null
+++ b/test/Preprocessor/pragma.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -E %s | FileCheck %s
+
+#pragma clang __debug parser_crash
+#pragma clang __debug dump Test
+
+// CHECK: #pragma clang __debug parser_crash
+// FIXME: The dump parameter is dropped.
+// CHECK: #pragma clang __debug dump{{$}}
diff --git a/test/Preprocessor/predefined-arch-macros.c b/test/Preprocessor/predefined-arch-macros.c
index 281e6780cbf5..65d3a3ec319c 100644
--- a/test/Preprocessor/predefined-arch-macros.c
+++ b/test/Preprocessor/predefined-arch-macros.c
@@ -417,7 +417,6 @@
// RUN: %clang -march=corei7-avx -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_COREI7_AVX_M32
-// CHECK_COREI7_AVX_M32: #define __AES__ 1
// CHECK_COREI7_AVX_M32: #define __AVX__ 1
// CHECK_COREI7_AVX_M32: #define __MMX__ 1
// CHECK_COREI7_AVX_M32: #define __PCLMUL__ 1
@@ -441,7 +440,6 @@
// RUN: %clang -march=corei7-avx -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_COREI7_AVX_M64
-// CHECK_COREI7_AVX_M64: #define __AES__ 1
// CHECK_COREI7_AVX_M64: #define __AVX__ 1
// CHECK_COREI7_AVX_M64: #define __MMX__ 1
// CHECK_COREI7_AVX_M64: #define __PCLMUL__ 1
@@ -468,7 +466,6 @@
// RUN: %clang -march=core-avx-i -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX_I_M32
-// CHECK_CORE_AVX_I_M32: #define __AES__ 1
// CHECK_CORE_AVX_I_M32: #define __AVX__ 1
// CHECK_CORE_AVX_I_M32: #define __F16C__ 1
// CHECK_CORE_AVX_I_M32: #define __MMX__ 1
@@ -492,7 +489,6 @@
// RUN: %clang -march=core-avx-i -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX_I_M64
-// CHECK_CORE_AVX_I_M64: #define __AES__ 1
// CHECK_CORE_AVX_I_M64: #define __AVX__ 1
// CHECK_CORE_AVX_I_M64: #define __F16C__ 1
// CHECK_CORE_AVX_I_M64: #define __MMX__ 1
@@ -519,7 +515,6 @@
// RUN: %clang -march=core-avx2 -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX2_M32
-// CHECK_CORE_AVX2_M32: #define __AES__ 1
// CHECK_CORE_AVX2_M32: #define __AVX2__ 1
// CHECK_CORE_AVX2_M32: #define __AVX__ 1
// CHECK_CORE_AVX2_M32: #define __BMI2__ 1
@@ -529,6 +524,7 @@
// CHECK_CORE_AVX2_M32: #define __INVPCID__ 1
// CHECK_CORE_AVX2_M32: #define __LZCNT__ 1
// CHECK_CORE_AVX2_M32: #define __MMX__ 1
+// CHECK_CORE_AVX2_M32: #define __MOVBE__ 1
// CHECK_CORE_AVX2_M32: #define __PCLMUL__ 1
// CHECK_CORE_AVX2_M32: #define __POPCNT__ 1
// CHECK_CORE_AVX2_M32: #define __RDRND__ 1
@@ -550,7 +546,6 @@
// RUN: %clang -march=core-avx2 -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CORE_AVX2_M64
-// CHECK_CORE_AVX2_M64: #define __AES__ 1
// CHECK_CORE_AVX2_M64: #define __AVX2__ 1
// CHECK_CORE_AVX2_M64: #define __AVX__ 1
// CHECK_CORE_AVX2_M64: #define __BMI2__ 1
@@ -560,6 +555,7 @@
// CHECK_CORE_AVX2_M64: #define __INVPCID__ 1
// CHECK_CORE_AVX2_M64: #define __LZCNT__ 1
// CHECK_CORE_AVX2_M64: #define __MMX__ 1
+// CHECK_CORE_AVX2_M64: #define __MOVBE__ 1
// CHECK_CORE_AVX2_M64: #define __PCLMUL__ 1
// CHECK_CORE_AVX2_M64: #define __POPCNT__ 1
// CHECK_CORE_AVX2_M64: #define __RDRND__ 1
@@ -585,7 +581,6 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BROADWELL_M32
// CHECK_BROADWELL_M32: #define __ADX__ 1
-// CHECK_BROADWELL_M32: #define __AES__ 1
// CHECK_BROADWELL_M32: #define __AVX2__ 1
// CHECK_BROADWELL_M32: #define __AVX__ 1
// CHECK_BROADWELL_M32: #define __BMI2__ 1
@@ -595,6 +590,7 @@
// CHECK_BROADWELL_M32: #define __INVPCID__ 1
// CHECK_BROADWELL_M32: #define __LZCNT__ 1
// CHECK_BROADWELL_M32: #define __MMX__ 1
+// CHECK_BROADWELL_M32: #define __MOVBE__ 1
// CHECK_BROADWELL_M32: #define __PCLMUL__ 1
// CHECK_BROADWELL_M32: #define __POPCNT__ 1
// CHECK_BROADWELL_M32: #define __PRFCHW__ 1
@@ -619,7 +615,6 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_BROADWELL_M64
// CHECK_BROADWELL_M64: #define __ADX__ 1
-// CHECK_BROADWELL_M64: #define __AES__ 1
// CHECK_BROADWELL_M64: #define __AVX2__ 1
// CHECK_BROADWELL_M64: #define __AVX__ 1
// CHECK_BROADWELL_M64: #define __BMI2__ 1
@@ -629,6 +624,7 @@
// CHECK_BROADWELL_M64: #define __INVPCID__ 1
// CHECK_BROADWELL_M64: #define __LZCNT__ 1
// CHECK_BROADWELL_M64: #define __MMX__ 1
+// CHECK_BROADWELL_M64: #define __MOVBE__ 1
// CHECK_BROADWELL_M64: #define __PCLMUL__ 1
// CHECK_BROADWELL_M64: #define __POPCNT__ 1
// CHECK_BROADWELL_M64: #define __PRFCHW__ 1
@@ -667,13 +663,13 @@
// CHECK_SKL_M32: #define __INVPCID__ 1
// CHECK_SKL_M32: #define __LZCNT__ 1
// CHECK_SKL_M32: #define __MMX__ 1
+// CHECK_SKL_M32: #define __MOVBE__ 1
// CHECK_SKL_M32: #define __MPX__ 1
// CHECK_SKL_M32: #define __PCLMUL__ 1
// CHECK_SKL_M32: #define __POPCNT__ 1
// CHECK_SKL_M32: #define __PRFCHW__ 1
// CHECK_SKL_M32: #define __RDRND__ 1
// CHECK_SKL_M32: #define __RDSEED__ 1
-// CHECK_SKL_M32: #define __RTM__ 1
// CHECK_SKL_M32: #define __SGX__ 1
// CHECK_SKL_M32: #define __SSE2__ 1
// CHECK_SKL_M32: #define __SSE3__ 1
@@ -702,13 +698,13 @@
// CHECK_SKL_M64: #define __INVPCID__ 1
// CHECK_SKL_M64: #define __LZCNT__ 1
// CHECK_SKL_M64: #define __MMX__ 1
+// CHECK_SKL_M64: #define __MOVBE__ 1
// CHECK_SKL_M64: #define __MPX__ 1
// CHECK_SKL_M64: #define __PCLMUL__ 1
// CHECK_SKL_M64: #define __POPCNT__ 1
// CHECK_SKL_M64: #define __PRFCHW__ 1
// CHECK_SKL_M64: #define __RDRND__ 1
// CHECK_SKL_M64: #define __RDSEED__ 1
-// CHECK_SKL_M64: #define __RTM__ 1
// CHECK_SKL_M64: #define __SGX__ 1
// CHECK_SKL_M64: #define __SSE2_MATH__ 1
// CHECK_SKL_M64: #define __SSE2__ 1
@@ -743,12 +739,12 @@
// CHECK_KNL_M32: #define __FMA__ 1
// CHECK_KNL_M32: #define __LZCNT__ 1
// CHECK_KNL_M32: #define __MMX__ 1
+// CHECK_KNL_M32: #define __MOVBE__ 1
// CHECK_KNL_M32: #define __PCLMUL__ 1
// CHECK_KNL_M32: #define __POPCNT__ 1
// CHECK_KNL_M32: #define __PREFETCHWT1__ 1
// CHECK_KNL_M32: #define __PRFCHW__ 1
// CHECK_KNL_M32: #define __RDRND__ 1
-// CHECK_KNL_M32: #define __RTM__ 1
// CHECK_KNL_M32: #define __SSE2__ 1
// CHECK_KNL_M32: #define __SSE3__ 1
// CHECK_KNL_M32: #define __SSE4_1__ 1
@@ -780,12 +776,12 @@
// CHECK_KNL_M64: #define __FMA__ 1
// CHECK_KNL_M64: #define __LZCNT__ 1
// CHECK_KNL_M64: #define __MMX__ 1
+// CHECK_KNL_M64: #define __MOVBE__ 1
// CHECK_KNL_M64: #define __PCLMUL__ 1
// CHECK_KNL_M64: #define __POPCNT__ 1
// CHECK_KNL_M64: #define __PREFETCHWT1__ 1
// CHECK_KNL_M64: #define __PRFCHW__ 1
// CHECK_KNL_M64: #define __RDRND__ 1
-// CHECK_KNL_M64: #define __RTM__ 1
// CHECK_KNL_M64: #define __SSE2_MATH__ 1
// CHECK_KNL_M64: #define __SSE2__ 1
// CHECK_KNL_M64: #define __SSE3__ 1
@@ -821,12 +817,12 @@
// CHECK_KNM_M32: #define __FMA__ 1
// CHECK_KNM_M32: #define __LZCNT__ 1
// CHECK_KNM_M32: #define __MMX__ 1
+// CHECK_KNM_M32: #define __MOVBE__ 1
// CHECK_KNM_M32: #define __PCLMUL__ 1
// CHECK_KNM_M32: #define __POPCNT__ 1
// CHECK_KNM_M32: #define __PREFETCHWT1__ 1
// CHECK_KNM_M32: #define __PRFCHW__ 1
// CHECK_KNM_M32: #define __RDRND__ 1
-// CHECK_KNM_M32: #define __RTM__ 1
// CHECK_KNM_M32: #define __SSE2__ 1
// CHECK_KNM_M32: #define __SSE3__ 1
// CHECK_KNM_M32: #define __SSE4_1__ 1
@@ -856,12 +852,12 @@
// CHECK_KNM_M64: #define __FMA__ 1
// CHECK_KNM_M64: #define __LZCNT__ 1
// CHECK_KNM_M64: #define __MMX__ 1
+// CHECK_KNM_M64: #define __MOVBE__ 1
// CHECK_KNM_M64: #define __PCLMUL__ 1
// CHECK_KNM_M64: #define __POPCNT__ 1
// CHECK_KNM_M64: #define __PREFETCHWT1__ 1
// CHECK_KNM_M64: #define __PRFCHW__ 1
// CHECK_KNM_M64: #define __RDRND__ 1
-// CHECK_KNM_M64: #define __RTM__ 1
// CHECK_KNM_M64: #define __SSE2_MATH__ 1
// CHECK_KNM_M64: #define __SSE2__ 1
// CHECK_KNM_M64: #define __SSE3__ 1
@@ -897,6 +893,7 @@
// CHECK_SKX_M32: #define __INVPCID__ 1
// CHECK_SKX_M32: #define __LZCNT__ 1
// CHECK_SKX_M32: #define __MMX__ 1
+// CHECK_SKX_M32: #define __MOVBE__ 1
// CHECK_SKX_M32: #define __MPX__ 1
// CHECK_SKX_M32: #define __PCLMUL__ 1
// CHECK_SKX_M32: #define __PKU__ 1
@@ -904,7 +901,6 @@
// CHECK_SKX_M32: #define __PRFCHW__ 1
// CHECK_SKX_M32: #define __RDRND__ 1
// CHECK_SKX_M32: #define __RDSEED__ 1
-// CHECK_SKX_M32: #define __RTM__ 1
// CHECK_SKX_M32-NOT: #define __SGX__ 1
// CHECK_SKX_M32: #define __SSE2__ 1
// CHECK_SKX_M32: #define __SSE3__ 1
@@ -943,6 +939,7 @@
// CHECK_SKX_M64: #define __INVPCID__ 1
// CHECK_SKX_M64: #define __LZCNT__ 1
// CHECK_SKX_M64: #define __MMX__ 1
+// CHECK_SKX_M64: #define __MOVBE__ 1
// CHECK_SKX_M64: #define __MPX__ 1
// CHECK_SKX_M64: #define __PCLMUL__ 1
// CHECK_SKX_M64: #define __PKU__ 1
@@ -950,7 +947,6 @@
// CHECK_SKX_M64: #define __PRFCHW__ 1
// CHECK_SKX_M64: #define __RDRND__ 1
// CHECK_SKX_M64: #define __RDSEED__ 1
-// CHECK_SKX_M64: #define __RTM__ 1
// CHECK_SKX_M64-NOT: #define __SGX__ 1
// CHECK_SKX_M64: #define __SSE2_MATH__ 1
// CHECK_SKX_M64: #define __SSE2__ 1
@@ -972,6 +968,103 @@
// CHECK_SKX_M64: #define __x86_64 1
// CHECK_SKX_M64: #define __x86_64__ 1
+// RUN: %clang -march=cascadelake -m32 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CLX_M32
+// CHECK_CLX_M32: #define __AES__ 1
+// CHECK_CLX_M32: #define __AVX2__ 1
+// CHECK_CLX_M32: #define __AVX512BW__ 1
+// CHECK_CLX_M32: #define __AVX512CD__ 1
+// CHECK_CLX_M32: #define __AVX512DQ__ 1
+// CHECK_CLX_M32: #define __AVX512F__ 1
+// CHECK_CLX_M32: #define __AVX512VL__ 1
+// CHECK_CLX_M32: #define __AVX512VNNI__ 1
+// CHECK_CLX_M32: #define __AVX__ 1
+// CHECK_CLX_M32: #define __BMI2__ 1
+// CHECK_CLX_M32: #define __BMI__ 1
+// CHECK_CLX_M32: #define __CLFLUSHOPT__ 1
+// CHECK_CLX_M32: #define __CLWB__ 1
+// CHECK_CLX_M32: #define __F16C__ 1
+// CHECK_CLX_M32: #define __FMA__ 1
+// CHECK_CLX_M32: #define __INVPCID__ 1
+// CHECK_CLX_M32: #define __LZCNT__ 1
+// CHECK_CLX_M32: #define __MMX__ 1
+// CHECK_CLX_M32: #define __MOVBE__ 1
+// CHECK_CLX_M32: #define __MPX__ 1
+// CHECK_CLX_M32: #define __PCLMUL__ 1
+// CHECK_CLX_M32: #define __PKU__ 1
+// CHECK_CLX_M32: #define __POPCNT__ 1
+// CHECK_CLX_M32: #define __PRFCHW__ 1
+// CHECK_CLX_M32: #define __RDRND__ 1
+// CHECK_CLX_M32: #define __RDSEED__ 1
+// CHECK_CLX_M32-NOT: #define __SGX__ 1
+// CHECK_CLX_M32: #define __SSE2__ 1
+// CHECK_CLX_M32: #define __SSE3__ 1
+// CHECK_CLX_M32: #define __SSE4_1__ 1
+// CHECK_CLX_M32: #define __SSE4_2__ 1
+// CHECK_CLX_M32: #define __SSE__ 1
+// CHECK_CLX_M32: #define __SSSE3__ 1
+// CHECK_CLX_M32: #define __XSAVEC__ 1
+// CHECK_CLX_M32: #define __XSAVEOPT__ 1
+// CHECK_CLX_M32: #define __XSAVES__ 1
+// CHECK_CLX_M32: #define __XSAVE__ 1
+// CHECK_CLX_M32: #define __corei7 1
+// CHECK_CLX_M32: #define __corei7__ 1
+// CHECK_CLX_M32: #define __i386 1
+// CHECK_CLX_M32: #define __i386__ 1
+// CHECK_CLX_M32: #define __tune_corei7__ 1
+// CHECK_CLX_M32: #define i386 1
+
+// RUN: %clang -march=cascadelake -m64 -E -dM %s -o - 2>&1 \
+// RUN: -target i386-unknown-linux \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CLX_M64
+// CHECK_CLX_M64: #define __AES__ 1
+// CHECK_CLX_M64: #define __AVX2__ 1
+// CHECK_CLX_M64: #define __AVX512BW__ 1
+// CHECK_CLX_M64: #define __AVX512CD__ 1
+// CHECK_CLX_M64: #define __AVX512DQ__ 1
+// CHECK_CLX_M64: #define __AVX512F__ 1
+// CHECK_CLX_M64: #define __AVX512VL__ 1
+// CHECK_CLX_M64: #define __AVX512VNNI__ 1
+// CHECK_CLX_M64: #define __AVX__ 1
+// CHECK_CLX_M64: #define __BMI2__ 1
+// CHECK_CLX_M64: #define __BMI__ 1
+// CHECK_CLX_M64: #define __CLFLUSHOPT__ 1
+// CHECK_CLX_M64: #define __CLWB__ 1
+// CHECK_CLX_M64: #define __F16C__ 1
+// CHECK_CLX_M64: #define __FMA__ 1
+// CHECK_CLX_M64: #define __INVPCID__ 1
+// CHECK_CLX_M64: #define __LZCNT__ 1
+// CHECK_CLX_M64: #define __MMX__ 1
+// CHECK_CLX_M64: #define __MOVBE__ 1
+// CHECK_CLX_M64: #define __MPX__ 1
+// CHECK_CLX_M64: #define __PCLMUL__ 1
+// CHECK_CLX_M64: #define __PKU__ 1
+// CHECK_CLX_M64: #define __POPCNT__ 1
+// CHECK_CLX_M64: #define __PRFCHW__ 1
+// CHECK_CLX_M64: #define __RDRND__ 1
+// CHECK_CLX_M64: #define __RDSEED__ 1
+// CHECK_CLX_M64-NOT: #define __SGX__ 1
+// CHECK_CLX_M64: #define __SSE2_MATH__ 1
+// CHECK_CLX_M64: #define __SSE2__ 1
+// CHECK_CLX_M64: #define __SSE3__ 1
+// CHECK_CLX_M64: #define __SSE4_1__ 1
+// CHECK_CLX_M64: #define __SSE4_2__ 1
+// CHECK_CLX_M64: #define __SSE_MATH__ 1
+// CHECK_CLX_M64: #define __SSE__ 1
+// CHECK_CLX_M64: #define __SSSE3__ 1
+// CHECK_CLX_M64: #define __XSAVEC__ 1
+// CHECK_CLX_M64: #define __XSAVEOPT__ 1
+// CHECK_CLX_M64: #define __XSAVES__ 1
+// CHECK_CLX_M64: #define __XSAVE__ 1
+// CHECK_CLX_M64: #define __amd64 1
+// CHECK_CLX_M64: #define __amd64__ 1
+// CHECK_CLX_M64: #define __corei7 1
+// CHECK_CLX_M64: #define __corei7__ 1
+// CHECK_CLX_M64: #define __tune_corei7__ 1
+// CHECK_CLX_M64: #define __x86_64 1
+// CHECK_CLX_M64: #define __x86_64__ 1
+
// RUN: %clang -march=cannonlake -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_CNL_M32
@@ -994,6 +1087,7 @@
// CHECK_CNL_M32: #define __INVPCID__ 1
// CHECK_CNL_M32: #define __LZCNT__ 1
// CHECK_CNL_M32: #define __MMX__ 1
+// CHECK_CNL_M32: #define __MOVBE__ 1
// CHECK_CNL_M32: #define __MPX__ 1
// CHECK_CNL_M32: #define __PCLMUL__ 1
// CHECK_CNL_M32: #define __PKU__ 1
@@ -1001,7 +1095,6 @@
// CHECK_CNL_M32: #define __PRFCHW__ 1
// CHECK_CNL_M32: #define __RDRND__ 1
// CHECK_CNL_M32: #define __RDSEED__ 1
-// CHECK_CNL_M32: #define __RTM__ 1
// CHECK_CNL_M32: #define __SGX__ 1
// CHECK_CNL_M32: #define __SHA__ 1
// CHECK_CNL_M32: #define __SSE2__ 1
@@ -1043,6 +1136,7 @@
// CHECK_CNL_M64: #define __INVPCID__ 1
// CHECK_CNL_M64: #define __LZCNT__ 1
// CHECK_CNL_M64: #define __MMX__ 1
+// CHECK_CNL_M64: #define __MOVBE__ 1
// CHECK_CNL_M64: #define __MPX__ 1
// CHECK_CNL_M64: #define __PCLMUL__ 1
// CHECK_CNL_M64: #define __PKU__ 1
@@ -1050,7 +1144,6 @@
// CHECK_CNL_M64: #define __PRFCHW__ 1
// CHECK_CNL_M64: #define __RDRND__ 1
// CHECK_CNL_M64: #define __RDSEED__ 1
-// CHECK_CNL_M64: #define __RTM__ 1
// CHECK_CNL_M64: #define __SGX__ 1
// CHECK_CNL_M64: #define __SHA__ 1
// CHECK_CNL_M64: #define __SSE2__ 1
@@ -1098,6 +1191,7 @@
// CHECK_ICL_M32: #define __INVPCID__ 1
// CHECK_ICL_M32: #define __LZCNT__ 1
// CHECK_ICL_M32: #define __MMX__ 1
+// CHECK_ICL_M32: #define __MOVBE__ 1
// CHECK_ICL_M32: #define __MPX__ 1
// CHECK_ICL_M32: #define __PCLMUL__ 1
// CHECK_ICL_M32: #define __PKU__ 1
@@ -1106,7 +1200,6 @@
// CHECK_ICL_M32: #define __RDPID__ 1
// CHECK_ICL_M32: #define __RDRND__ 1
// CHECK_ICL_M32: #define __RDSEED__ 1
-// CHECK_ICL_M32: #define __RTM__ 1
// CHECK_ICL_M32: #define __SGX__ 1
// CHECK_ICL_M32: #define __SHA__ 1
// CHECK_ICL_M32: #define __SSE2__ 1
@@ -1156,6 +1249,7 @@
// CHECK_ICL_M64: #define __INVPCID__ 1
// CHECK_ICL_M64: #define __LZCNT__ 1
// CHECK_ICL_M64: #define __MMX__ 1
+// CHECK_ICL_M64: #define __MOVBE__ 1
// CHECK_ICL_M64: #define __MPX__ 1
// CHECK_ICL_M64: #define __PCLMUL__ 1
// CHECK_ICL_M64: #define __PKU__ 1
@@ -1164,7 +1258,6 @@
// CHECK_ICL_M64: #define __RDPID__ 1
// CHECK_ICL_M64: #define __RDRND__ 1
// CHECK_ICL_M64: #define __RDSEED__ 1
-// CHECK_ICL_M64: #define __RTM__ 1
// CHECK_ICL_M64: #define __SGX__ 1
// CHECK_ICL_M64: #define __SHA__ 1
// CHECK_ICL_M64: #define __SSE2__ 1
@@ -1215,6 +1308,7 @@
// CHECK_ICX_M32: #define __INVPCID__ 1
// CHECK_ICX_M32: #define __LZCNT__ 1
// CHECK_ICX_M32: #define __MMX__ 1
+// CHECK_ICX_M32: #define __MOVBE__ 1
// CHECK_ICX_M32: #define __MPX__ 1
// CHECK_ICX_M32: #define __PCLMUL__ 1
// CHECK_ICX_M32: #define __PCONFIG__ 1
@@ -1224,7 +1318,6 @@
// CHECK_ICX_M32: #define __RDPID__ 1
// CHECK_ICX_M32: #define __RDRND__ 1
// CHECK_ICX_M32: #define __RDSEED__ 1
-// CHECK_ICX_M32: #define __RTM__ 1
// CHECK_ICX_M32: #define __SGX__ 1
// CHECK_ICX_M32: #define __SHA__ 1
// CHECK_ICX_M32: #define __SSE2__ 1
@@ -1274,6 +1367,7 @@
// CHECK_ICX_M64: #define __INVPCID__ 1
// CHECK_ICX_M64: #define __LZCNT__ 1
// CHECK_ICX_M64: #define __MMX__ 1
+// CHECK_ICX_M64: #define __MOVBE__ 1
// CHECK_ICX_M64: #define __MPX__ 1
// CHECK_ICX_M64: #define __PCLMUL__ 1
// CHECK_ICX_M64: #define __PCONFIG__ 1
@@ -1283,7 +1377,6 @@
// CHECK_ICX_M64: #define __RDPID__ 1
// CHECK_ICX_M64: #define __RDRND__ 1
// CHECK_ICX_M64: #define __RDSEED__ 1
-// CHECK_ICX_M64: #define __RTM__ 1
// CHECK_ICX_M64: #define __SGX__ 1
// CHECK_ICX_M64: #define __SHA__ 1
// CHECK_ICX_M64: #define __SSE2__ 1
@@ -1311,6 +1404,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATOM_M32
// CHECK_ATOM_M32: #define __MMX__ 1
+// CHECK_ATOM_M32: #define __MOVBE__ 1
// CHECK_ATOM_M32: #define __SSE2__ 1
// CHECK_ATOM_M32: #define __SSE3__ 1
// CHECK_ATOM_M32: #define __SSE__ 1
@@ -1326,6 +1420,7 @@
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_ATOM_M64
// CHECK_ATOM_M64: #define __MMX__ 1
+// CHECK_ATOM_M64: #define __MOVBE__ 1
// CHECK_ATOM_M64: #define __SSE2_MATH__ 1
// CHECK_ATOM_M64: #define __SSE2__ 1
// CHECK_ATOM_M64: #define __SSE3__ 1
@@ -1348,6 +1443,7 @@
// CHECK_GLM_M32: #define __FSGSBASE__ 1
// CHECK_GLM_M32: #define __FXSR__ 1
// CHECK_GLM_M32: #define __MMX__ 1
+// CHECK_GLM_M32: #define __MOVBE__ 1
// CHECK_GLM_M32: #define __MPX__ 1
// CHECK_GLM_M32: #define __PCLMUL__ 1
// CHECK_GLM_M32: #define __POPCNT__ 1
@@ -1381,6 +1477,7 @@
// CHECK_GLM_M64: #define __FSGSBASE__ 1
// CHECK_GLM_M64: #define __FXSR__ 1
// CHECK_GLM_M64: #define __MMX__ 1
+// CHECK_GLM_M64: #define __MOVBE__ 1
// CHECK_GLM_M64: #define __MPX__ 1
// CHECK_GLM_M64: #define __PCLMUL__ 1
// CHECK_GLM_M64: #define __POPCNT__ 1
@@ -1412,6 +1509,7 @@
// CHECK_GLMP_M32: #define __FSGSBASE__ 1
// CHECK_GLMP_M32: #define __FXSR__ 1
// CHECK_GLMP_M32: #define __MMX__ 1
+// CHECK_GLMP_M32: #define __MOVBE__ 1
// CHECK_GLMP_M32: #define __MPX__ 1
// CHECK_GLMP_M32: #define __PCLMUL__ 1
// CHECK_GLMP_M32: #define __POPCNT__ 1
@@ -1448,6 +1546,7 @@
// CHECK_GLMP_M64: #define __FSGSBASE__ 1
// CHECK_GLMP_M64: #define __FXSR__ 1
// CHECK_GLMP_M64: #define __MMX__ 1
+// CHECK_GLMP_M64: #define __MOVBE__ 1
// CHECK_GLMP_M64: #define __MPX__ 1
// CHECK_GLMP_M64: #define __PCLMUL__ 1
// CHECK_GLMP_M64: #define __POPCNT__ 1
@@ -1484,6 +1583,7 @@
// CHECK_TRM_M32: #define __FXSR__ 1
// CHECK_TRM_M32: #define __GFNI__ 1
// CHECK_TRM_M32: #define __MMX__ 1
+// CHECK_TRM_M32: #define __MOVBE__ 1
// CHECK_TRM_M32: #define __MOVDIR64B__ 1
// CHECK_TRM_M32: #define __MOVDIRI__ 1
// CHECK_TRM_M32: #define __MPX__ 1
@@ -1525,6 +1625,7 @@
// CHECK_TRM_M64: #define __FXSR__ 1
// CHECK_TRM_M64: #define __GFNI__ 1
// CHECK_TRM_M64: #define __MMX__ 1
+// CHECK_TRM_M64: #define __MOVBE__ 1
// CHECK_TRM_M64: #define __MOVDIR64B__ 1
// CHECK_TRM_M64: #define __MOVDIRI__ 1
// CHECK_TRM_M64: #define __MPX__ 1
@@ -1557,9 +1658,9 @@
// RUN: %clang -march=slm -m32 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SLM_M32
-// CHECK_SLM_M32: #define __AES__ 1
// CHECK_SLM_M32: #define __FXSR__ 1
// CHECK_SLM_M32: #define __MMX__ 1
+// CHECK_SLM_M32: #define __MOVBE__ 1
// CHECK_SLM_M32: #define __PCLMUL__ 1
// CHECK_SLM_M32: #define __POPCNT__ 1
// CHECK_SLM_M32: #define __PRFCHW__ 1
@@ -1580,9 +1681,9 @@
// RUN: %clang -march=slm -m64 -E -dM %s -o - 2>&1 \
// RUN: -target i386-unknown-linux \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SLM_M64
-// CHECK_SLM_M64: #define __AES__ 1
// CHECK_SLM_M64: #define __FXSR__ 1
// CHECK_SLM_M64: #define __MMX__ 1
+// CHECK_SLM_M64: #define __MOVBE__ 1
// CHECK_SLM_M64: #define __PCLMUL__ 1
// CHECK_SLM_M64: #define __POPCNT__ 1
// CHECK_SLM_M64: #define __PRFCHW__ 1
@@ -2144,6 +2245,7 @@
// CHECK_BTVER2_M32: #define __F16C__ 1
// CHECK_BTVER2_M32: #define __LZCNT__ 1
// CHECK_BTVER2_M32: #define __MMX__ 1
+// CHECK_BTVER2_M32: #define __MOVBE__ 1
// CHECK_BTVER2_M32: #define __PCLMUL__ 1
// CHECK_BTVER2_M32: #define __POPCNT__ 1
// CHECK_BTVER2_M32: #define __PRFCHW__ 1
@@ -2173,6 +2275,7 @@
// CHECK_BTVER2_M64: #define __F16C__ 1
// CHECK_BTVER2_M64: #define __LZCNT__ 1
// CHECK_BTVER2_M64: #define __MMX__ 1
+// CHECK_BTVER2_M64: #define __MOVBE__ 1
// CHECK_BTVER2_M64: #define __PCLMUL__ 1
// CHECK_BTVER2_M64: #define __POPCNT__ 1
// CHECK_BTVER2_M64: #define __PRFCHW__ 1
@@ -2501,6 +2604,7 @@
// CHECK_ZNVER1_M32: #define __FSGSBASE__ 1
// CHECK_ZNVER1_M32: #define __LZCNT__ 1
// CHECK_ZNVER1_M32: #define __MMX__ 1
+// CHECK_ZNVER1_M32: #define __MOVBE__ 1
// CHECK_ZNVER1_M32: #define __PCLMUL__ 1
// CHECK_ZNVER1_M32: #define __POPCNT__ 1
// CHECK_ZNVER1_M32: #define __PRFCHW__ 1
@@ -2544,6 +2648,7 @@
// CHECK_ZNVER1_M64: #define __FSGSBASE__ 1
// CHECK_ZNVER1_M64: #define __LZCNT__ 1
// CHECK_ZNVER1_M64: #define __MMX__ 1
+// CHECK_ZNVER1_M64: #define __MOVBE__ 1
// CHECK_ZNVER1_M64: #define __PCLMUL__ 1
// CHECK_ZNVER1_M64: #define __POPCNT__ 1
// CHECK_ZNVER1_M64: #define __PRFCHW__ 1
diff --git a/test/Preprocessor/wasm-target-features.c b/test/Preprocessor/wasm-target-features.c
index f4d40b1774a2..92aaefd73c08 100644
--- a/test/Preprocessor/wasm-target-features.c
+++ b/test/Preprocessor/wasm-target-features.c
@@ -8,6 +8,15 @@
// SIMD128:#define __wasm_simd128__ 1{{$}}
//
// RUN: %clang -E -dM %s -o - 2>&1 \
+// RUN: -target wasm32-unknown-unknown -munimplemented-simd128 \
+// RUN: | FileCheck %s -check-prefix=SIMD128-UNIMPLEMENTED
+// RUN: %clang -E -dM %s -o - 2>&1 \
+// RUN: -target wasm64-unknown-unknown -munimplemented-simd128 \
+// RUN: | FileCheck %s -check-prefix=SIMD128-UNIMPLEMENTED
+//
+// SIMD128-UNIMPLEMENTED:#define __wasm_unimplemented_simd128__ 1{{$}}
+//
+// RUN: %clang -E -dM %s -o - 2>&1 \
// RUN: -target wasm32-unknown-unknown -mcpu=mvp \
// RUN: | FileCheck %s -check-prefix=MVP
// RUN: %clang -E -dM %s -o - 2>&1 \
diff --git a/test/Preprocessor/woa-defaults.c b/test/Preprocessor/woa-defaults.c
index 4eef863b23a1..97578239396a 100644
--- a/test/Preprocessor/woa-defaults.c
+++ b/test/Preprocessor/woa-defaults.c
@@ -27,7 +27,7 @@
// CHECK: #define __SIZEOF_SHORT__ 2
// CHECK: #define __SIZEOF_SIZE_T__ 4
// CHECK: #define __SIZEOF_WCHAR_T__ 2
-// CHECK: #define __SIZEOF_WINT_T__ 4
+// CHECK: #define __SIZEOF_WINT_T__ 2
// CHECK: #define __SIZE_TYPE__ unsigned int
// CHECK: #define __UINTPTR_TYPE__ unsigned int
diff --git a/test/Sema/Inputs/pragma-pack1.h b/test/Sema/Inputs/pragma-pack1.h
index abbf8a8609f1..3fd299e642a1 100644
--- a/test/Sema/Inputs/pragma-pack1.h
+++ b/test/Sema/Inputs/pragma-pack1.h
@@ -16,7 +16,7 @@ struct ReceivesPragma { };
#include "pragma-pack2.h"
#ifdef SET_SECOND_HEADER
-// expected-warning@-3 {{the current #pragma pack aligment value is modified in the included file}}
+// expected-warning@-3 {{the current #pragma pack alignment value is modified in the included file}}
#endif
#ifdef PUSH_POP_FIRST_HEADER
diff --git a/test/Sema/aarch64-vpcs.c b/test/Sema/aarch64-vpcs.c
new file mode 100644
index 000000000000..93ad00324177
--- /dev/null
+++ b/test/Sema/aarch64-vpcs.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -verify %s
+
+typedef __attribute__((aarch64_vector_pcs)) int invalid_typedef; // expected-warning {{'aarch64_vector_pcs' only applies to function types; type here is 'int'}}
+
+void __attribute__((aarch64_vector_pcs(0))) foo0(void); // expected-error {{'aarch64_vector_pcs' attribute takes no arguments}}
+
+void __attribute__((aarch64_vector_pcs, preserve_all)) foo1(void); // expected-error {{not compatible}}
+
+void __attribute__((cdecl)) foo2(void); // expected-note {{previous declaration is here}}
+void __attribute__((aarch64_vector_pcs)) foo2(void) {} // expected-error {{function declared 'aarch64_vector_pcs' here was previously declared 'cdecl'}}
+
+void foo3(void); // expected-note {{previous declaration is here}}
+void __attribute__((aarch64_vector_pcs)) foo3(void) {} // expected-error {{function declared 'aarch64_vector_pcs' here was previously declared without calling convention}}
+
+typedef int (*fn_ty)(void);
+typedef int __attribute__((aarch64_vector_pcs)) (*aavpcs_fn_ty)(void);
+void foo4(fn_ty ptr1, aavpcs_fn_ty ptr2) {
+ ptr1 = ptr2; // expected-warning {{incompatible function pointer types}}
+}
diff --git a/test/Sema/address_spaces.c b/test/Sema/address_spaces.c
index 87707d7deb0d..a9046d86f18c 100644
--- a/test/Sema/address_spaces.c
+++ b/test/Sema/address_spaces.c
@@ -71,5 +71,19 @@ __attribute__((address_space("12"))) int *i; // expected-error {{'address_space'
// Clang extension doesn't forbid operations on pointers to different address spaces.
char* cmp(_AS1 char *x, _AS2 char *y) {
- return x < y ? x : y; // expected-warning {{pointer type mismatch ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}}
+ return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *') which are pointers to non-overlapping address spaces}}
+}
+
+struct SomeStruct {
+ int a;
+ long b;
+ int c;
+};
+
+// Compound literals in function scope are lvalues with automatic storage duration,
+// so they cannot realistically be qualified with an address space.
+void as_compound_literal() {
+ (_AS1 struct SomeStruct){1, 2, 3}; // expected-error {{compound literal in function scope may not be qualified with an address space}}
+ (_AS1 char[]){"test"}; // expected-error {{compound literal in function scope may not be qualified with an address space}}
+ (_AS1 char[]){'a', 'b', 'c'}; // expected-error {{compound literal in function scope may not be qualified with an address space}}
}
diff --git a/test/Sema/alias-unused.c b/test/Sema/alias-unused.c
new file mode 100644
index 000000000000..5cedc93c2974
--- /dev/null
+++ b/test/Sema/alias-unused.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -Wunneeded-internal-declaration -x c -verify %s
+// expected-no-diagnostics
+static int f() { return 42; }
+int g() __attribute__((alias("f")));
+
+static int foo [] = { 42, 0xDEAD };
+extern typeof(foo) bar __attribute__((unused, alias("foo")));
diff --git a/test/Sema/align-x86-abi7.c b/test/Sema/align-x86-abi7.c
new file mode 100644
index 000000000000..49ca66f69251
--- /dev/null
+++ b/test/Sema/align-x86-abi7.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c11 -triple i386-apple-darwin9 -fsyntax-only -verify -fclang-abi-compat=7 %s
+// expected-no-diagnostics
+
+#define STATIC_ASSERT(cond) _Static_assert(cond, #cond)
+
+// PR3433
+#define CHECK_ALIGNMENT(type, name, pref) \
+ type name; \
+ STATIC_ASSERT(__alignof__(name) == pref); \
+ STATIC_ASSERT(__alignof__(type) == pref); \
+ STATIC_ASSERT(_Alignof(type) == pref)
+
+CHECK_ALIGNMENT(double, g_double, 8);
+CHECK_ALIGNMENT(long long, g_longlong, 8);
+CHECK_ALIGNMENT(unsigned long long, g_ulonglong, 8);
+
+typedef double arr3double[3];
+CHECK_ALIGNMENT(arr3double, g_arr3double, 8);
+
+enum big_enum { x = 18446744073709551615ULL };
+CHECK_ALIGNMENT(enum big_enum, g_bigenum, 8); \ No newline at end of file
diff --git a/test/Sema/align-x86.c b/test/Sema/align-x86.c
index e3b8c704b858..519cbe66f181 100644
--- a/test/Sema/align-x86.c
+++ b/test/Sema/align-x86.c
@@ -1,34 +1,33 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c11 -triple i386-apple-darwin9 -fsyntax-only -verify %s
// expected-no-diagnostics
-// PR3433
-double g1;
-short chk1[__alignof__(g1) == 8 ? 1 : -1];
-short chk2[__alignof__(double) == 8 ? 1 : -1];
-
-long long g2;
-short chk1[__alignof__(g2) == 8 ? 1 : -1];
-short chk2[__alignof__(long long) == 8 ? 1 : -1];
+#define STATIC_ASSERT(cond) _Static_assert(cond, #cond)
-unsigned long long g5;
-short chk1[__alignof__(g5) == 8 ? 1 : -1];
-short chk2[__alignof__(unsigned long long) == 8 ? 1 : -1];
+// PR3433
+#define CHECK_ALIGNMENT(type, name, abi, pref) \
+ type name; \
+ STATIC_ASSERT(__alignof__(name) == pref); \
+ STATIC_ASSERT(__alignof__(type) == pref); \
+ STATIC_ASSERT(_Alignof(type) == abi)
-_Complex double g3;
-short chk1[__alignof__(g3) == 8 ? 1 : -1];
-short chk2[__alignof__(_Complex double) == 8 ? 1 : -1];
+CHECK_ALIGNMENT(double, g_double, 4, 8);
+CHECK_ALIGNMENT(long long, g_longlong, 4, 8);
+CHECK_ALIGNMENT(unsigned long long, g_ulonglong, 4, 8);
+CHECK_ALIGNMENT(_Complex double, g_complexdouble, 4, 8);
// PR6362
-struct __attribute__((packed)) {unsigned int a;} g4;
-short chk1[__alignof__(g4) == 1 ? 1 : -1];
-short chk2[__alignof__(g4.a) == 1 ? 1 : -1];
+struct __attribute__((packed))
+packed_struct {
+ unsigned int a;
+};
+CHECK_ALIGNMENT(struct packed_struct, g_packedstruct, 1, 1);
+STATIC_ASSERT(__alignof__(g_packedstruct.a) == 1);
-double g6[3];
-short chk1[__alignof__(g6) == 8 ? 1 : -1];
-short chk2[__alignof__(double[3]) == 8 ? 1 : -1];
+typedef double arr3double[3];
+CHECK_ALIGNMENT(arr3double, g_arr3double, 4, 8);
-enum { x = 18446744073709551615ULL } g7;
-short chk1[__alignof__(g7) == 8 ? 1 : -1];
+enum big_enum { x = 18446744073709551615ULL };
+CHECK_ALIGNMENT(enum big_enum, g_bigenum, 4, 8);
// PR5637
@@ -36,20 +35,20 @@ short chk1[__alignof__(g7) == 8 ? 1 : -1];
typedef ALIGNED(2) struct {
char a[3];
-} T;
+} aligned_before_struct;
-short chk1[sizeof(T) == 3 ? 1 : -1];
-short chk2[sizeof(T[1]) == 4 ? 1 : -1];
-short chk3[sizeof(T[2]) == 6 ? 1 : -1];
-short chk4[sizeof(T[2][1]) == 8 ? 1 : -1];
-short chk5[sizeof(T[1][2]) == 6 ? 1 : -1];
+STATIC_ASSERT(sizeof(aligned_before_struct) == 3);
+STATIC_ASSERT(sizeof(aligned_before_struct[1]) == 4);
+STATIC_ASSERT(sizeof(aligned_before_struct[2]) == 6);
+STATIC_ASSERT(sizeof(aligned_before_struct[2][1]) == 8);
+STATIC_ASSERT(sizeof(aligned_before_struct[1][2]) == 6);
typedef struct ALIGNED(2) {
char a[3];
-} T2;
+} aligned_after_struct;
-short chk1[sizeof(T2) == 4 ? 1 : -1];
-short chk2[sizeof(T2[1]) == 4 ? 1 : -1];
-short chk3[sizeof(T2[2]) == 8 ? 1 : -1];
-short chk4[sizeof(T2[2][1]) == 8 ? 1 : -1];
-short chk5[sizeof(T2[1][2]) == 8 ? 1 : -1];
+STATIC_ASSERT(sizeof(aligned_after_struct) == 4);
+STATIC_ASSERT(sizeof(aligned_after_struct[1]) == 4);
+STATIC_ASSERT(sizeof(aligned_after_struct[2]) == 8);
+STATIC_ASSERT(sizeof(aligned_after_struct[2][1]) == 8);
+STATIC_ASSERT(sizeof(aligned_after_struct[1][2]) == 8);
diff --git a/test/Sema/altivec-generic-overload.c b/test/Sema/altivec-generic-overload.c
new file mode 100644
index 000000000000..7e0679c68794
--- /dev/null
+++ b/test/Sema/altivec-generic-overload.c
@@ -0,0 +1,100 @@
+// RUN: %clang_cc1 %s -triple=powerpc64le-unknown-linux -target-feature +altivec -target-feature +vsx -verify -verify-ignore-unexpected=note -pedantic -fsyntax-only
+
+typedef signed char __v16sc __attribute__((__vector_size__(16)));
+typedef unsigned char __v16uc __attribute__((__vector_size__(16)));
+typedef signed short __v8ss __attribute__((__vector_size__(16)));
+typedef unsigned short __v8us __attribute__((__vector_size__(16)));
+typedef signed int __v4si __attribute__((__vector_size__(16)));
+typedef unsigned int __v4ui __attribute__((__vector_size__(16)));
+typedef signed long long __v2sll __attribute__((__vector_size__(16)));
+typedef unsigned long long __v2ull __attribute__((__vector_size__(16)));
+typedef signed __int128 __v1slll __attribute__((__vector_size__(16)));
+typedef unsigned __int128 __v1ulll __attribute__((__vector_size__(16)));
+typedef float __v4f __attribute__((__vector_size__(16)));
+typedef double __v2d __attribute__((__vector_size__(16)));
+
+__v16sc *__attribute__((__overloadable__)) convert1(vector signed char);
+__v16uc *__attribute__((__overloadable__)) convert1(vector unsigned char);
+__v8ss *__attribute__((__overloadable__)) convert1(vector signed short);
+__v8us *__attribute__((__overloadable__)) convert1(vector unsigned short);
+__v4si *__attribute__((__overloadable__)) convert1(vector signed int);
+__v4ui *__attribute__((__overloadable__)) convert1(vector unsigned int);
+__v2sll *__attribute__((__overloadable__)) convert1(vector signed long long);
+__v2ull *__attribute__((__overloadable__)) convert1(vector unsigned long long);
+__v1slll *__attribute__((__overloadable__)) convert1(vector signed __int128);
+__v1ulll *__attribute__((__overloadable__)) convert1(vector unsigned __int128);
+__v4f *__attribute__((__overloadable__)) convert1(vector float);
+__v2d *__attribute__((__overloadable__)) convert1(vector double);
+void __attribute__((__overloadable__)) convert1(vector bool int);
+void __attribute__((__overloadable__)) convert1(vector pixel short);
+
+vector signed char *__attribute__((__overloadable__)) convert2(__v16sc);
+vector unsigned char *__attribute__((__overloadable__)) convert2(__v16uc);
+vector signed short *__attribute__((__overloadable__)) convert2(__v8ss);
+vector unsigned short *__attribute__((__overloadable__)) convert2(__v8us);
+vector signed int *__attribute__((__overloadable__)) convert2(__v4si);
+vector unsigned int *__attribute__((__overloadable__)) convert2(__v4ui);
+vector signed long long *__attribute__((__overloadable__)) convert2(__v2sll);
+vector unsigned long long *__attribute__((__overloadable__)) convert2(__v2ull);
+vector signed __int128 *__attribute__((__overloadable__)) convert2(__v1slll);
+vector unsigned __int128 *__attribute__((__overloadable__)) convert2(__v1ulll);
+vector float *__attribute__((__overloadable__)) convert2(__v4f);
+vector double *__attribute__((__overloadable__)) convert2(__v2d);
+
+void test() {
+ __v16sc gv1;
+ __v16uc gv2;
+ __v8ss gv3;
+ __v8us gv4;
+ __v4si gv5;
+ __v4ui gv6;
+ __v2sll gv7;
+ __v2ull gv8;
+ __v1slll gv9;
+ __v1ulll gv10;
+ __v4f gv11;
+ __v2d gv12;
+
+ vector signed char av1;
+ vector unsigned char av2;
+ vector signed short av3;
+ vector unsigned short av4;
+ vector signed int av5;
+ vector unsigned int av6;
+ vector signed long long av7;
+ vector unsigned long long av8;
+ vector signed __int128 av9;
+ vector unsigned __int128 av10;
+ vector float av11;
+ vector double av12;
+ vector bool int av13;
+ vector pixel short av14;
+
+ __v16sc *gv1_p = convert1(gv1);
+ __v16uc *gv2_p = convert1(gv2);
+ __v8ss *gv3_p = convert1(gv3);
+ __v8us *gv4_p = convert1(gv4);
+ __v4si *gv5_p = convert1(gv5);
+ __v4ui *gv6_p = convert1(gv6);
+ __v2sll *gv7_p = convert1(gv7);
+ __v2ull *gv8_p = convert1(gv8);
+ __v1slll *gv9_p = convert1(gv9);
+ __v1ulll *gv10_p = convert1(gv10);
+ __v4f *gv11_p = convert1(gv11);
+ __v2d *gv12_p = convert1(gv12);
+
+ vector signed char *av1_p = convert2(av1);
+ vector unsigned char *av2_p = convert2(av2);
+ vector signed short *av3_p = convert2(av3);
+ vector unsigned short *av4_p = convert2(av4);
+ vector signed int *av5_p = convert2(av5);
+ vector unsigned int *av6_p = convert2(av6);
+ vector signed long long *av7_p = convert2(av7);
+ vector unsigned long long *av8_p = convert2(av8);
+ vector signed __int128 *av9_p = convert2(av9);
+ vector unsigned __int128 *av10_p = convert2(av10);
+ vector float *av11_p = convert2(av11);
+ vector double *av12_p = convert2(av12);
+ convert2(av13); // expected-error {{call to 'convert2' is ambiguous}}
+ convert2(av14); // expected-error {{call to 'convert2' is ambiguous}}
+}
diff --git a/test/Sema/arm-no-fp16.c b/test/Sema/arm-no-fp16.c
index 2a23270e92d8..91c48483f295 100644
--- a/test/Sema/arm-no-fp16.c
+++ b/test/Sema/arm-no-fp16.c
@@ -83,3 +83,213 @@ float16x4_t test_vminnm_f16(float16x4_t a, float16x4_t b) {
float16x8_t test_vminnmq_f16(float16x8_t a, float16x8_t b) {
return vminnmq_f16(a, b); // expected-warning{{implicit declaration of function 'vminnmq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
}
+
+float16x4_t test_vld1_f16(const float16_t *a) {
+ return vld1_f16(a); // expected-warning{{implicit declaration of function 'vld1_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vld1q_f16(const float16_t *a) {
+ return vld1q_f16(a); // expected-warning{{implicit declaration of function 'vld1q_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vld1_dup_f16(const float16_t *a) {
+ return vld1_dup_f16(a); // expected-warning{{implicit declaration of function 'vld1_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vld1q_dup_f16(const float16_t *a) {
+ return vld1q_dup_f16(a); // expected-warning{{implicit declaration of function 'vld1q_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4_t test_vld1_lane_f16(const float16_t *a, float16x4_t b) {
+ return vld1_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vld1_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}}
+}
+
+float16x8_t test_vld1q_lane_f16(const float16_t *a, float16x8_t b) {
+ return vld1q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vld1q_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}}
+}
+
+float16x4x2_t test_vld1_f16_x2(const float16_t *a) {
+ return vld1_f16_x2(a); // expected-warning{{implicit declaration of function 'vld1_f16_x2'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x2_t'}}
+}
+
+float16x8x2_t test_vld1q_f16_x2(const float16_t *a) {
+ return vld1q_f16_x2(a); // expected-warning{{implicit declaration of function 'vld1q_f16_x2'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x2_t'}}
+}
+
+float16x4x3_t test_vld1_f16_x3(const float16_t *a) {
+ return vld1_f16_x3(a); // expected-warning{{implicit declaration of function 'vld1_f16_x3'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x3_t'}}
+}
+
+float16x8x3_t test_vld1q_f16_x3(const float16_t *a) {
+ return vld1q_f16_x3(a); // expected-warning{{implicit declaration of function 'vld1q_f16_x3'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x3_t'}}
+}
+
+float16x4x4_t test_vld1_f16_x4(const float16_t *a) {
+ return vld1_f16_x4(a); // expected-warning{{implicit declaration of function 'vld1_f16_x4'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x4_t'}}
+}
+
+float16x8x4_t test_vld1q_f16_x4(const float16_t *a) {
+ return vld1q_f16_x4(a); // expected-warning{{implicit declaration of function 'vld1q_f16_x4'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x4_t'}}
+}
+
+float16x4x2_t test_vld2_f16(const float16_t *a) {
+ return vld2_f16(a); // expected-warning{{implicit declaration of function 'vld2_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x2_t'}}
+}
+
+float16x8x2_t test_vld2q_f16(const float16_t *a) {
+ return vld2q_f16(a); // expected-warning{{implicit declaration of function 'vld2q_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x2_t'}}
+}
+
+float16x4x2_t test_vld2_lane_f16(const float16_t *a, float16x4x2_t b) {
+ return vld2_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vld2_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x2_t'}}
+}
+
+float16x8x2_t test_vld2q_lane_f16(const float16_t *a, float16x8x2_t b) {
+ return vld2q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vld2q_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x2_t'}}
+}
+
+float16x4x2_t test_vld2_dup_f16(const float16_t *src) {
+ return vld2_dup_f16(src); // expected-warning{{implicit declaration of function 'vld2_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x2_t'}}
+}
+
+float16x8x2_t test_vld2q_dup_f16(const float16_t *src) {
+ return vld2q_dup_f16(src); // expected-warning{{implicit declaration of function 'vld2q_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x2_t'}}
+}
+
+float16x4x3_t test_vld3_f16(const float16_t *a) {
+ return vld3_f16(a); // expected-warning{{implicit declaration of function 'vld3_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x3_t'}}
+}
+
+float16x8x3_t test_vld3q_f16(const float16_t *a) {
+ return vld3q_f16(a); // expected-warning{{implicit declaration of function 'vld3q_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x3_t'}}
+}
+
+float16x4x3_t test_vld3_lane_f16(const float16_t *a, float16x4x3_t b) {
+ return vld3_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vld3_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x3_t'}}
+}
+
+float16x8x3_t test_vld3q_lane_f16(const float16_t *a, float16x8x3_t b) {
+ return vld3q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vld3q_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x3_t'}}
+}
+
+float16x4x3_t test_vld3_dup_f16(const float16_t *src) {
+ return vld3_dup_f16(src); // expected-warning{{implicit declaration of function 'vld3_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x3_t'}}
+}
+
+float16x8x3_t test_vld3q_dup_f16(const float16_t *src) {
+ return vld3q_dup_f16(src); // expected-warning{{implicit declaration of function 'vld3q_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x3_t'}}
+}
+
+float16x4x4_t test_vld4_f16(const float16_t *a) {
+ return vld4_f16(a); // expected-warning{{implicit declaration of function 'vld4_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x4_t'}}
+}
+
+float16x8x4_t test_vld4q_f16(const float16_t *a) {
+ return vld4q_f16(a); // expected-warning{{implicit declaration of function 'vld4q_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x4_t'}}
+}
+
+float16x4x4_t test_vld4_lane_f16(const float16_t *a, float16x4x4_t b) {
+ return vld4_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vld4_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x4_t'}}
+}
+
+float16x8x4_t test_vld4q_lane_f16(const float16_t *a, float16x8x4_t b) {
+ return vld4q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vld4q_lane_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x4_t'}}
+}
+
+float16x4x4_t test_vld4_dup_f16(const float16_t *src) {
+ return vld4_dup_f16(src); // expected-warning{{implicit declaration of function 'vld4_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4x4_t'}}
+}
+
+float16x8x4_t test_vld4q_dup_f16(const float16_t *src) {
+ return vld4q_dup_f16(src); // expected-warning{{implicit declaration of function 'vld4q_dup_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8x4_t'}}
+}
+
+void test_vst1_f16(float16_t *a, float16x4_t b) {
+ vst1_f16(a, b); // expected-warning{{implicit declaration of function 'vst1_f16'}}
+}
+
+// aarch64-neon-intrinsics.c:void test_vst1q_f16(float16_t *a, float16x8_t b) {
+void test_vst1q_f16(float16_t *a, float16x8_t b) {
+ vst1q_f16(a, b); // expected-warning{{implicit declaration of function 'vst1q_f16'}}
+}
+
+// aarch64-neon-ldst-one.c:void test_vst1_lane_f16(float16_t *a, float16x4_t b) {
+void test_vst1_lane_f16(float16_t *a, float16x4_t b) {
+ vst1_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vst1_lane_f16'}}
+}
+
+void test_vst1q_lane_f16(float16_t *a, float16x8_t b) {
+ vst1q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vst1q_lane_f16'}}
+}
+
+void test_vst1_f16_x2(float16_t *a, float16x4x2_t b) {
+ vst1_f16_x2(a, b); // expected-warning{{implicit declaration of function 'vst1_f16_x2'}}
+}
+
+void test_vst1q_f16_x2(float16_t *a, float16x8x2_t b) {
+ vst1q_f16_x2(a, b); // expected-warning{{implicit declaration of function 'vst1q_f16_x2'}}
+}
+
+void test_vst1_f16_x3(float16_t *a, float16x4x3_t b) {
+ vst1_f16_x3(a, b); // expected-warning{{implicit declaration of function 'vst1_f16_x3'}}
+}
+
+void test_vst1q_f16_x3(float16_t *a, float16x8x3_t b) {
+ vst1q_f16_x3(a, b); // expected-warning{{implicit declaration of function 'vst1q_f16_x3'}}
+}
+
+void test_vst1_f16_x4(float16_t *a, float16x4x4_t b) {
+ vst1_f16_x4(a, b); // expected-warning{{implicit declaration of function 'vst1_f16_x4'}}
+}
+
+void test_vst1q_f16_x4(float16_t *a, float16x8x4_t b) {
+ vst1q_f16_x4(a, b); // expected-warning{{implicit declaration of function 'vst1q_f16_x4'}}
+}
+
+void test_vst2_f16(float16_t *a, float16x4x2_t b) {
+ vst2_f16(a, b); // expected-warning{{implicit declaration of function 'vst2_f16'}}
+}
+
+void test_vst2q_f16(float16_t *a, float16x8x2_t b) {
+ vst2q_f16(a, b); // expected-warning{{implicit declaration of function 'vst2q_f16'}}
+}
+
+void test_vst2_lane_f16(float16_t *a, float16x4x2_t b) {
+ vst2_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vst2_lane_f16'}}
+}
+
+void test_vst2q_lane_f16(float16_t *a, float16x8x2_t b) {
+ vst2q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vst2q_lane_f16'}}
+}
+
+void test_vst3_f16(float16_t *a, float16x4x3_t b) {
+ vst3_f16(a, b); // expected-warning{{implicit declaration of function 'vst3_f16'}}
+}
+
+void test_vst3q_f16(float16_t *a, float16x8x3_t b) {
+ vst3q_f16(a, b); // expected-warning{{implicit declaration of function 'vst3q_f16'}}
+}
+
+void test_vst3_lane_f16(float16_t *a, float16x4x3_t b) {
+ vst3_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vst3_lane_f16'}}
+}
+
+void test_vst3q_lane_f16(float16_t *a, float16x8x3_t b) {
+ vst3q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vst3q_lane_f16'}}
+}
+
+void test_vst4_f16(float16_t *a, float16x4x4_t b) {
+ vst4_f16(a, b); // expected-warning{{implicit declaration of function 'vst4_f16'}}
+}
+
+void test_vst4q_f16(float16_t *a, float16x8x4_t b) {
+ vst4q_f16(a, b); // expected-warning{{implicit declaration of function 'vst4q_f16'}}
+}
+
+void test_vst4_lane_f16(float16_t *a, float16x4x4_t b) {
+ vst4_lane_f16(a, b, 3); // expected-warning{{implicit declaration of function 'vst4_lane_f16'}}
+}
+
+void test_vst4q_lane_f16(float16_t *a, float16x8x4_t b) {
+ vst4q_lane_f16(a, b, 7); // expected-warning{{implicit declaration of function 'vst4q_lane_f16'}}
+}
diff --git a/test/Sema/assign.c b/test/Sema/assign.c
index 28d7b9f3bbdf..4d305aca4b5a 100644
--- a/test/Sema/assign.c
+++ b/test/Sema/assign.c
@@ -59,3 +59,37 @@ void testK1_(K k, J j) {
void testK2_(K k, I i) {
k.j->i = i; // expected-error {{cannot assign to non-static data member 'i' with const-qualified data member 'a'}}
}
+
+// PR39946: Recursive checking of hasConstFields caused stack overflow.
+struct L { // expected-note {{definition of 'struct L' is not complete until the closing '}'}}
+ struct L field; // expected-error {{field has incomplete type 'struct L'}}
+};
+void testL(struct L *l) {
+ *l = 0; // expected-error {{assigning to 'struct L' from incompatible type 'int'}}
+}
+
+// Additionally, this example overflowed the stack when figuring out the field.
+struct M1; // expected-note {{forward declaration of 'struct M1'}}
+struct M2 {
+ //expected-note@+1 {{nested data member 'field' declared const here}}
+ const struct M1 field; // expected-error {{field has incomplete type 'const struct M1'}}
+};
+struct M1 {
+ struct M2 field;
+};
+
+void testM(struct M1 *l) {
+ *l = 0; // expected-error {{cannot assign to lvalue with nested const-qualified data member 'field'}}
+}
+
+struct N1; // expected-note {{forward declaration of 'struct N1'}}
+struct N2 {
+ struct N1 field; // expected-error {{field has incomplete type 'struct N1'}}
+};
+struct N1 {
+ struct N2 field;
+};
+
+void testN(struct N1 *l) {
+ *l = 0; // expected-error {{assigning to 'struct N1' from incompatible type 'int'}}
+}
diff --git a/test/Sema/atomic-implicit-seq_cst.c b/test/Sema/atomic-implicit-seq_cst.c
new file mode 100644
index 000000000000..fff7b2444906
--- /dev/null
+++ b/test/Sema/atomic-implicit-seq_cst.c
@@ -0,0 +1,325 @@
+// RUN: %clang_cc1 %s -verify -ffreestanding -fsyntax-only -triple=i686-linux-gnu -std=c11 -Watomic-implicit-seq-cst
+
+// _Atomic operations are implicitly sequentially-consistent. Some codebases
+// want to force explicit usage of memory order instead.
+
+_Atomic(int) atom;
+void gimme_int(int);
+
+void bad_pre_inc(void) {
+ ++atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_pre_dec(void) {
+ --atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_post_inc(void) {
+ atom++; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_post_dec(void) {
+ atom--; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_call(void) {
+ gimme_int(atom); // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_unary_plus(void) {
+ return +atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_unary_minus(void) {
+ return -atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_unary_logical_not(void) {
+ return !atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_unary_bitwise_not(void) {
+ return ~atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_explicit_cast(void) {
+ return (int)atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_implicit_cast(void) {
+ return atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_mul_1(int i) {
+ return atom * i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_mul_2(int i) {
+ return i * atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_div_1(int i) {
+ return atom / i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_div_2(int i) {
+ return i / atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_mod_1(int i) {
+ return atom % i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_mod_2(int i) {
+ return i % atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_add_1(int i) {
+ return atom + i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_add_2(int i) {
+ return i + atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_sub_1(int i) {
+ return atom - i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_sub_2(int i) {
+ return i - atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_shl_1(int i) {
+ return atom << i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_shl_2(int i) {
+ return i << atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_shr_1(int i) {
+ return atom >> i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_shr_2(int i) {
+ return i >> atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_lt_1(int i) {
+ return atom < i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_lt_2(int i) {
+ return i < atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_le_1(int i) {
+ return atom <= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_le_2(int i) {
+ return i <= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_gt_1(int i) {
+ return atom > i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_gt_2(int i) {
+ return i > atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_ge_1(int i) {
+ return atom >= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_ge_2(int i) {
+ return i >= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_eq_1(int i) {
+ return atom == i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_eq_2(int i) {
+ return i == atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_ne_1(int i) {
+ return atom != i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_ne_2(int i) {
+ return i != atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_bitand_1(int i) {
+ return atom & i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_bitand_2(int i) {
+ return i & atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_bitxor_1(int i) {
+ return atom ^ i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_bitxor_2(int i) {
+ return i ^ atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_bitor_1(int i) {
+ return atom | i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_bitor_2(int i) {
+ return i | atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_and_1(int i) {
+ return atom && i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_and_2(int i) {
+ return i && atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_or_1(int i) {
+ return atom || i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_or_2(int i) {
+ return i || atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+int bad_ternary_1(int i, int j) {
+ return i ? atom : j; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_ternary_2(int i, int j) {
+ return atom ? i : j; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_ternary_3(int i, int j) {
+ return i ? j : atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_assign_1(int i) {
+ atom = i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_assign_2(int *i) {
+ *i = atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_assign_3() {
+ atom = atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_add_1(int i) {
+ atom += i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_add_2(int *i) {
+ *i += atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_sub_1(int i) {
+ atom -= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_sub_2(int *i) {
+ *i -= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_mul_1(int i) {
+ atom *= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_mul_2(int *i) {
+ *i *= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_div_1(int i) {
+ atom /= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_div_2(int *i) {
+ *i /= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_mod_1(int i) {
+ atom %= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_mod_2(int *i) {
+ *i %= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_shl_1(int i) {
+ atom <<= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_shl_2(int *i) {
+ *i <<= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_shr_1(int i) {
+ atom >>= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_shr_2(int *i) {
+ *i >>= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_bitand_1(int i) {
+ atom &= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_bitand_2(int *i) {
+ *i &= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_bitxor_1(int i) {
+ atom ^= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_bitxor_2(int *i) {
+ *i ^= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_bitor_1(int i) {
+ atom |= i; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void bad_compound_bitor_2(int *i) {
+ *i |= atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+int bad_comma(int i) {
+ return (void)i, atom; // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+}
+
+void good_c11_atomic_init(int i) { __c11_atomic_init(&atom, i); }
+void good_c11_atomic_thread_fence(void) { __c11_atomic_thread_fence(__ATOMIC_RELAXED); }
+void good_c11_atomic_signal_fence(void) { __c11_atomic_signal_fence(__ATOMIC_RELAXED); }
+void good_c11_atomic_is_lock_free(void) { __c11_atomic_is_lock_free(sizeof(int)); }
+void good_c11_atomic_store(int i) { __c11_atomic_store(&atom, i, __ATOMIC_RELAXED); }
+int good_c11_atomic_load(void) { return __c11_atomic_load(&atom, __ATOMIC_RELAXED); }
+int good_c11_atomic_exchange(int i) { return __c11_atomic_exchange(&atom, i, __ATOMIC_RELAXED); }
+int good_c11_atomic_compare_exchange_strong(int *e, int i) { return __c11_atomic_compare_exchange_strong(&atom, e, i, __ATOMIC_RELAXED, __ATOMIC_RELAXED); }
+int good_c11_atomic_compare_exchange_weak(int *e, int i) { return __c11_atomic_compare_exchange_weak(&atom, e, i, __ATOMIC_RELAXED, __ATOMIC_RELAXED); }
+int good_c11_atomic_fetch_add(int i) { return __c11_atomic_fetch_add(&atom, i, __ATOMIC_RELAXED); }
+int good_c11_atomic_fetch_sub(int i) { return __c11_atomic_fetch_sub(&atom, i, __ATOMIC_RELAXED); }
+int good_c11_atomic_fetch_and(int i) { return __c11_atomic_fetch_and(&atom, i, __ATOMIC_RELAXED); }
+int good_c11_atomic_fetch_or(int i) { return __c11_atomic_fetch_or(&atom, i, __ATOMIC_RELAXED); }
+int good_c11_atomic_fetch_xor(int i) { return __c11_atomic_fetch_xor(&atom, i, __ATOMIC_RELAXED); }
+
+void good_cast_to_void(void) { (void)atom; }
+_Atomic(int) * good_address_of(void) { return &atom; }
+int good_sizeof(void) { return sizeof(atom); }
+_Atomic(int) * good_pointer_arith(_Atomic(int) * p) { return p + 10; }
+_Bool good_pointer_to_bool(_Atomic(int) * p) { return p; }
+void good_no_init(void) { _Atomic(int) no_init; }
+void good_init(void) { _Atomic(int) init = 42; }
diff --git a/test/Sema/atomic-ops.c b/test/Sema/atomic-ops.c
index 49310bf45b68..638c30f278ce 100644
--- a/test/Sema/atomic-ops.c
+++ b/test/Sema/atomic-ops.c
@@ -115,7 +115,7 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__c11_atomic_load(i, memory_order_seq_cst);
__c11_atomic_load(p, memory_order_seq_cst);
__c11_atomic_load(d, memory_order_seq_cst);
- __c11_atomic_load(ci, memory_order_seq_cst); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
+ __c11_atomic_load(ci, memory_order_seq_cst);
int load_n_1 = __atomic_load_n(I, memory_order_relaxed);
int *load_n_2 = __atomic_load_n(P, memory_order_relaxed);
@@ -222,7 +222,7 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__c11_atomic_init(ci, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
__c11_atomic_store(ci, 0, memory_order_release); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
- __c11_atomic_load(ci, memory_order_acquire); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
+ __c11_atomic_load(ci, memory_order_acquire);
// Ensure the <stdatomic.h> macros behave appropriately.
atomic_int n = ATOMIC_VAR_INIT(123);
diff --git a/test/Sema/attr-availability-ios.c b/test/Sema/attr-availability-ios.c
index 3f901bb33cb5..f418c7dcfd5f 100644
--- a/test/Sema/attr-availability-ios.c
+++ b/test/Sema/attr-availability-ios.c
@@ -7,8 +7,8 @@ void f3(int) __attribute__((availability(ios,introduced=3.0)));
void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(ios,introduced=2.0,deprecated=2.1,obsoleted=3.0))); // expected-note{{explicitly marked unavailable}}
void f5(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5' has been explicitly marked deprecated here}}
-void f6(int) __attribute__((availability(ios,deprecated=3.0)));
-void f6(int) __attribute__((availability(iOS,introduced=2.0))); // expected-note {{'f6' has been explicitly marked deprecated here}}
+void f6(int) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f6' has been explicitly marked deprecated here}}
+void f6(int) __attribute__((availability(iOS,introduced=2.0)));
void test() {
f0(0); // expected-warning{{'f0' is deprecated: first deprecated in iOS 2.1}}
diff --git a/test/Sema/attr-availability-swift.c b/test/Sema/attr-availability-swift.c
new file mode 100644
index 000000000000..d77094cb2163
--- /dev/null
+++ b/test/Sema/attr-availability-swift.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -ast-dump %s | FileCheck %s
+//
+
+#if !__has_feature(attribute_availability_with_message)
+# error "Missing __has_feature"
+#endif
+
+#if __has_feature(attribute_availability_swift)
+# warning "okay"
+// expected-warning@-1{{okay}}
+#else
+# error "Missing __has_feature"
+#endif
+
+extern int noSwiftGlobal1 __attribute__((availability(swift, unavailable)));
+// CHECK: AvailabilityAttr {{.*}}swift 0 0 0 Unavailable "" ""
+extern int noSwiftGlobal1 __attribute__((availability(macosx, introduced=10.1))); // okay
+// CHECK: AvailabilityAttr {{.*}}Inherited swift 0 0 0 Unavailable "" ""
+// CHECK: AvailabilityAttr {{.*}}macos 10.1 0 0 "" ""
+extern int noSwiftGlobal1 __attribute__((availability(swift, unavailable, message="and this one has a message"))); // okay
+// CHECK: AvailabilityAttr {{.*}}Inherited macos 10.1 0 0 "" ""
+// CHECK: AvailabilityAttr {{.*}}swift 0 0 0 Unavailable "and this one has a message" ""
+extern int noSwiftGlobal2 __attribute__((availability(swift, introduced=5))); // expected-warning{{only 'unavailable' and 'deprecated' are supported for Swift availability}}
+// CHECK: VarDecl
+// CHECK-NOT: AvailabilityAttr
+extern int noSwiftGlobal3 __attribute__((availability(swift, deprecated, message="t")));
+// CHECK: VarDecl
+// CHECK: AvailabilityAttr {{.*}}swift 0 1 0 "t" ""
diff --git a/test/Sema/attr-availability-tvos.c b/test/Sema/attr-availability-tvos.c
index 68337e49ce44..b940a9ad3a99 100644
--- a/test/Sema/attr-availability-tvos.c
+++ b/test/Sema/attr-availability-tvos.c
@@ -7,8 +7,8 @@ void f3(int) __attribute__((availability(tvos,introduced=3.0)));
void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(tvos,introduced=2.0,deprecated=2.1,obsoleted=3.0))); // expected-note{{explicitly marked unavailable}}
void f5(int) __attribute__((availability(tvos,introduced=2.0))) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f5' has been explicitly marked deprecated here}}
-void f6(int) __attribute__((availability(tvos,deprecated=3.0)));
-void f6(int) __attribute__((availability(tvos,introduced=2.0))); // expected-note {{'f6' has been explicitly marked deprecated here}}
+void f6(int) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f6' has been explicitly marked deprecated here}}
+void f6(int) __attribute__((availability(tvos,introduced=2.0)));
void test() {
f0(0); // expected-warning{{'f0' is deprecated: first deprecated in tvOS 2.1}}
@@ -27,10 +27,8 @@ void test_transcribed_availability() {
f9(0);
}
-__attribute__((availability(ios,introduced=9_0,deprecated=9_0,message="" ))) // expected-note{{previous attribute is here}} \
- // expected-note{{previous attribute is here}}
-__attribute__((availability(ios,introduced=7_0))) // expected-warning{{availability does not match previous declaration}} \
- // expected-warning{{availability does not match previous declaration}}
+__attribute__((availability(ios,introduced=9_0,deprecated=9_0,message="" ))) // expected-warning 2{{availability does not match previous declaration}}
+__attribute__((availability(ios,introduced=7_0))) // expected-note 2{{previous attribute is here}}
void f10(int);
// Test tvOS specific attributes.
@@ -43,8 +41,8 @@ void f5_tvos(int) __attribute__((availability(tvos,introduced=2.0))) __attribute
void f5_attr_reversed_tvos(int) __attribute__((availability(ios, deprecated=3.0))) __attribute__((availability(tvos,introduced=2.0)));
void f5b_tvos(int) __attribute__((availability(tvos,introduced=2.0))) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f5b_tvos' has been explicitly marked deprecated here}}
void f5c_tvos(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5c_tvos' has been explicitly marked deprecated here}}
-void f6_tvos(int) __attribute__((availability(tvos,deprecated=3.0)));
-void f6_tvos(int) __attribute__((availability(tvOS,introduced=2.0))); // expected-note {{'f6_tvos' has been explicitly marked deprecated here}}
+void f6_tvos(int) __attribute__((availability(tvos,deprecated=3.0))); // expected-note {{'f6_tvos' has been explicitly marked deprecated here}}
+void f6_tvos(int) __attribute__((availability(tvOS,introduced=2.0)));
void test_tvos() {
f0_tvos(0); // expected-warning{{'f0_tvos' is deprecated: first deprecated in tvOS 2.1}}
diff --git a/test/Sema/attr-availability-watchos.c b/test/Sema/attr-availability-watchos.c
index 59233986ee46..866efac6a04f 100644
--- a/test/Sema/attr-availability-watchos.c
+++ b/test/Sema/attr-availability-watchos.c
@@ -32,8 +32,8 @@ void f5_watchos(int) __attribute__((availability(watchos,introduced=2.0))) __att
void f5_attr_reversed_watchos(int) __attribute__((availability(ios, deprecated=3.0))) __attribute__((availability(watchos,introduced=2.0)));
void f5b_watchos(int) __attribute__((availability(watchos,introduced=2.0))) __attribute__((availability(watchos,deprecated=3.0))); // expected-note {{'f5b_watchos' has been explicitly marked deprecated here}}
void f5c_watchos(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5c_watchos' has been explicitly marked deprecated here}}
-void f6_watchos(int) __attribute__((availability(watchos,deprecated=3.0)));
-void f6_watchos(int) __attribute__((availability(watchOS,introduced=2.0))); // expected-note {{'f6_watchos' has been explicitly marked deprecated here}}
+void f6_watchos(int) __attribute__((availability(watchos,deprecated=3.0))); // expected-note {{'f6_watchos' has been explicitly marked deprecated here}}
+void f6_watchos(int) __attribute__((availability(watchOS,introduced=2.0)));
void test_watchos() {
f0_watchos(0); // expected-warning{{'f0_watchos' is deprecated: first deprecated in watchOS 2.1}}
diff --git a/test/Sema/attr-availability.c b/test/Sema/attr-availability.c
index 1b8cbd256ce9..dbdf6593c3f7 100644
--- a/test/Sema/attr-availability.c
+++ b/test/Sema/attr-availability.c
@@ -16,13 +16,13 @@ extern void
ATSFontGetPostScriptName(int flags) __attribute__((availability(macosx,introduced=8.0,obsoleted=9.0, message="use ATSFontGetFullPostScriptName"))); // expected-note {{'ATSFontGetPostScriptName' has been explicitly marked unavailable here}}
#if defined(WARN_PARTIAL)
-// expected-note@+3 {{has been explicitly marked partial here}}
+// expected-note@+3 {{'PartiallyAvailable' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
extern void
PartiallyAvailable() __attribute__((availability(macosx,introduced=10.8)));
#ifdef WARN_PARTIAL
-// expected-note@+2 2 {{marked partial here}}
+// expected-note@+2 2 {{'PartialEnum' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
enum __attribute__((availability(macosx,introduced=10.8))) PartialEnum {
kPartialEnumConstant,
@@ -41,7 +41,7 @@ void test_10095131() {
#ifdef WARN_PARTIAL
// FIXME: This note should point to the declaration with the availability
// attribute.
-// expected-note@+2 {{marked partial here}}
+// expected-note@+2 {{'PartiallyAvailable' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
extern void PartiallyAvailable() ;
void with_redeclaration() {
@@ -64,8 +64,8 @@ enum {
void f4(int) __attribute__((availability(ios,deprecated=3.0)));
void f4(int) __attribute__((availability(ios,introduced=4.0))); // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}}
-void f5(int) __attribute__((availability(ios,deprecated=3.0),
- availability(ios,introduced=4.0))); // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}}
+void f5(int) __attribute__((availability(ios,deprecated=3.0), // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}}
+ availability(ios,introduced=4.0)));
void f6(int) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{previous attribute is here}}
void f6(int) __attribute__((availability(ios,deprecated=4.0))); // expected-warning {{availability does not match previous declaration}}
diff --git a/test/Sema/attr-capabilities.c b/test/Sema/attr-capabilities.c
index 21cbae9e6090..8bfc4a506543 100644
--- a/test/Sema/attr-capabilities.c
+++ b/test/Sema/attr-capabilities.c
@@ -37,15 +37,25 @@ void Func6(void) __attribute__((requires_shared_capability(BadCapability))) {}
void Func7(void) __attribute__((assert_capability(GUI))) {}
void Func8(void) __attribute__((assert_shared_capability(GUI))) {}
+void Func9(void) __attribute__((assert_capability())) {} // expected-warning {{'assert_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+void Func10(void) __attribute__((assert_shared_capability())) {} // expected-warning {{'assert_shared_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+
void Func11(void) __attribute__((acquire_capability(GUI))) {}
void Func12(void) __attribute__((acquire_shared_capability(GUI))) {}
+void Func13(void) __attribute__((acquire_capability())) {} // expected-warning {{'acquire_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+void Func14(void) __attribute__((acquire_shared_capability())) {} // expected-warning {{'acquire_shared_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+
void Func15(void) __attribute__((release_capability(GUI))) {}
void Func16(void) __attribute__((release_shared_capability(GUI))) {}
void Func17(void) __attribute__((release_generic_capability(GUI))) {}
-void Func21(void) __attribute__((try_acquire_capability(1))) {}
-void Func22(void) __attribute__((try_acquire_shared_capability(1))) {}
+void Func18(void) __attribute__((release_capability())) {} // expected-warning {{'release_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+void Func19(void) __attribute__((release_shared_capability())) {} // expected-warning {{'release_shared_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+void Func20(void) __attribute__((release_generic_capability())) {} // expected-warning {{'release_generic_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+
+void Func21(void) __attribute__((try_acquire_capability(1))) {} // expected-warning {{'try_acquire_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
+void Func22(void) __attribute__((try_acquire_shared_capability(1))) {} // expected-warning {{'try_acquire_shared_capability' attribute without capability arguments can only be applied to non-static methods of a class}}
void Func23(void) __attribute__((try_acquire_capability(1, GUI))) {}
void Func24(void) __attribute__((try_acquire_shared_capability(1, GUI))) {}
diff --git a/test/Sema/attr-coldhot.c b/test/Sema/attr-coldhot.c
index 972f5a5266aa..a4b15822065c 100644
--- a/test/Sema/attr-coldhot.c
+++ b/test/Sema/attr-coldhot.c
@@ -6,7 +6,7 @@ int bar() __attribute__((__cold__));
int var1 __attribute__((__cold__)); // expected-warning{{'__cold__' attribute only applies to functions}}
int var2 __attribute__((__hot__)); // expected-warning{{'__hot__' attribute only applies to functions}}
-int qux() __attribute__((__hot__)) __attribute__((__cold__)); // expected-error{{'__hot__' and 'cold' attributes are not compatible}} \
+int qux() __attribute__((__hot__)) __attribute__((__cold__)); // expected-error{{'__cold__' and 'hot' attributes are not compatible}} \
// expected-note{{conflicting attribute is here}}
-int baz() __attribute__((__cold__)) __attribute__((__hot__)); // expected-error{{'__cold__' and 'hot' attributes are not compatible}} \
+int baz() __attribute__((__cold__)) __attribute__((__hot__)); // expected-error{{'__hot__' and 'cold' attributes are not compatible}} \
// expected-note{{conflicting attribute is here}}
diff --git a/test/Sema/attr-cpuspecific.c b/test/Sema/attr-cpuspecific.c
index 91063c1c5b8a..e87ad4de7525 100644
--- a/test/Sema/attr-cpuspecific.c
+++ b/test/Sema/attr-cpuspecific.c
@@ -37,10 +37,16 @@ int __attribute__((cpu_dispatch(atom))) redecl2(void) { }
// expected-note@-2 {{previous definition is here}}
int __attribute__((cpu_dispatch(atom))) redecl2(void) { }
-int redecl3(void);
-// expected-error@-1 {{function declaration is missing 'cpu_specific' or 'cpu_dispatch' attribute in a multiversioned function}}
-// expected-note@+1 {{function multiversioning caused by this declaration}}
-int __attribute__((cpu_dispatch(atom))) redecl3(void) {}
+int allow_fwd_decl(void);
+int __attribute__((cpu_dispatch(atom))) allow_fwd_decl(void) {}
+
+int allow_fwd_decl2(void);
+void use_fwd_decl(void) {
+ allow_fwd_decl2();
+}
+// expected-error@+1 {{function declaration cannot become a multiversioned function after first usage}}
+int __attribute__((cpu_dispatch(atom))) allow_fwd_decl2(void) {}
+
int __attribute__((cpu_specific(atom))) redecl4(void);
// expected-error@+1 {{function declaration is missing 'cpu_specific' or 'cpu_dispatch' attribute in a multiversioned function}}
@@ -94,3 +100,15 @@ __vectorcall int __attribute__((cpu_specific(sandybridge))) diff_cc(void);
int __attribute__((cpu_dispatch(atom))) disp_with_body(void) {
return 5;
}
+
+// expected-error@+1 {{invalid option 'INVALID'}}
+int __attribute__((cpu_specific(INVALID))) called_invalid_value(void){ return 1;}
+// expected-warning@+3 {{attribute declaration must precede definition}}
+// expected-note@-2 2 {{previous definition is here}}
+// expected-error@+1 {{redefinition of}}
+int __attribute__((cpu_specific(pentium_iii))) called_invalid_value(void){ return 2;}
+int __attribute__((cpu_specific(pentium_4))) called_invalid_value(void){ return 3;}
+
+int use3(void) {
+ return called_invalid_value();
+}
diff --git a/test/Sema/attr-disable-tail-calls.c b/test/Sema/attr-disable-tail-calls.c
index e8f5bcc73ee8..0545e951e60e 100644
--- a/test/Sema/attr-disable-tail-calls.c
+++ b/test/Sema/attr-disable-tail-calls.c
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} expected-note {{conflicting attribute is here}}
+void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'naked' and 'disable_tail_calls' attributes are not compatible}} expected-note {{conflicting attribute is here}}
__asm__("");
}
-void __attribute__((naked,disable_tail_calls)) foo2(int a) { // expected-error {{'naked' and 'disable_tail_calls' attributes are not compatible}} expected-note {{conflicting attribute is here}}
+void __attribute__((naked,disable_tail_calls)) foo2(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} expected-note {{conflicting attribute is here}}
__asm__("");
}
diff --git a/test/Sema/attr-ifunc.c b/test/Sema/attr-ifunc.c
index af7a7e33da09..907b61c4451e 100644
--- a/test/Sema/attr-ifunc.c
+++ b/test/Sema/attr-ifunc.c
@@ -27,10 +27,6 @@ void f4_ifunc() {}
void f4() __attribute__((ifunc("f4_ifunc")));
//expected-error@-1 {{ifunc resolver function must return a pointer}}
-void* f5_ifunc(int i) { return 0; }
-void f5() __attribute__((ifunc("f5_ifunc")));
-//expected-error@-1 {{ifunc resolver function must have no parameters}}
-
#else
void f1a() __asm("f1");
void f1a() {}
diff --git a/test/Sema/attr-long-call.c b/test/Sema/attr-long-call.c
index cd3de1bf9e41..e80f8fdd52a7 100644
--- a/test/Sema/attr-long-call.c
+++ b/test/Sema/attr-long-call.c
@@ -19,8 +19,8 @@ __attribute((near)) void foo6();
__attribute((long_call, far)) void foo7();
__attribute((short_call, near)) void foo11();
-__attribute((far, near)) void foo8(); // expected-error {{'far' and 'near' attributes are not compatible}} \
+__attribute((far, near)) void foo8(); // expected-error {{'near' and 'far' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
-__attribute((short_call, long_call)) void foo12(); // expected-error {{'short_call' and 'long_call' attributes are not compatible}} \
+__attribute((short_call, long_call)) void foo12(); // expected-error {{'long_call' and 'short_call' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
diff --git a/test/Sema/attr-micromips.c b/test/Sema/attr-micromips.c
index fe587fa3db07..27c9d3b54f6a 100644
--- a/test/Sema/attr-micromips.c
+++ b/test/Sema/attr-micromips.c
@@ -6,9 +6,9 @@ __attribute__((micromips(1))) void foo2(); // expected-error {{'micromips' at
__attribute((nomicromips)) int a; // expected-error {{attribute only applies to functions}}
__attribute((micromips)) int b; // expected-error {{attribute only applies to functions}}
-__attribute__((micromips,mips16)) void foo5(); // expected-error {{'micromips' and 'mips16' attributes are not compatible}} \
+__attribute__((micromips,mips16)) void foo5(); // expected-error {{'mips16' and 'micromips' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
-__attribute__((mips16,micromips)) void foo6(); // expected-error {{'mips16' and 'micromips' attributes are not compatible}} \
+__attribute__((mips16,micromips)) void foo6(); // expected-error {{'micromips' and 'mips16' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
__attribute((micromips)) void foo7();
diff --git a/test/Sema/attr-notail.c b/test/Sema/attr-notail.c
index 4d05fcf6f2c0..f65af47518d1 100644
--- a/test/Sema/attr-notail.c
+++ b/test/Sema/attr-notail.c
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-int callee0() __attribute__((not_tail_called,always_inline)); // expected-error{{'not_tail_called' and 'always_inline' attributes are not compatible}} \
+int callee0() __attribute__((not_tail_called,always_inline)); // expected-error{{'always_inline' and 'not_tail_called' attributes are not compatible}} \
// expected-note{{conflicting attribute is here}}
-int callee1() __attribute__((always_inline,not_tail_called)); // expected-error{{'always_inline' and 'not_tail_called' attributes are not compatible}} \
+int callee1() __attribute__((always_inline,not_tail_called)); // expected-error{{'not_tail_called' and 'always_inline' attributes are not compatible}} \
// expected-note{{conflicting attribute is here}}
int foo(int a) {
diff --git a/test/Sema/attr-osobject.cpp b/test/Sema/attr-osobject.cpp
new file mode 100644
index 000000000000..1659a82533be
--- /dev/null
+++ b/test/Sema/attr-osobject.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct S {
+ __attribute__((os_returns_retained)) S* method_returns_retained() {
+ return nullptr;
+ }
+
+ __attribute__((os_consumes_this)) void method_consumes_this();
+
+ __attribute__((os_consumes_this)) static void rejected_on_static(); // expected-warning{{'os_consumes_this' attribute only applies to non-static member functions}}
+};
+__attribute__((os_returns_retained)) S *ret_retained() {
+ return nullptr;
+}
+
+__attribute__((os_returns_retained)) S ret_retained_value() { // expected-warning{{'os_returns_retained' attribute only applies to functions that return a pointer}}
+ return {};
+}
+
+__attribute__((os_returns_not_retained)) S *ret_not_retained() {
+ return nullptr;
+}
+
+__attribute__((os_returns_not_retained)) S ret_not_retained_value() { // expected-warning{{'os_returns_not_retained' attribute only applies to functions that return a pointer}}
+ return {};
+}
+
+void accept_consumed_arg(__attribute__((os_consumed)) S *arg) {}
+
+void accept_consumed_arg_by_value(__attribute__((os_consumed)) S arg) {} // expected-warning{{os_consumed attribute only applies to pointer parameters}}
+
+void accept_consumed_arg_no_extra_arg(__attribute__((os_consumed(10))) S *arg) {} // expected-error{{'os_consumed' attribute takes no arguments}}
+
+struct __attribute__((os_consumed)) NoAttrOnStruct {}; // expected-warning{{'os_consumed' attribute only applies to parameters}}
+
+__attribute__((os_returns_retained(10))) S* returns_retained_no_extra_arg() { // expected-error{{'os_returns_retained' attribute takes no arguments}}
+ return nullptr;
+}
+
+struct __attribute__((os_returns_retained)) NoRetainAttrOnStruct {}; // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}}
+
+__attribute__((os_returns_not_retained(10))) S* os_returns_no_retained_no_extra_args( S *arg) { // expected-error{{'os_returns_not_retained' attribute takes no arguments}}
+ return nullptr;
+}
+
+struct __attribute__((os_returns_not_retained)) NoNotRetainedAttrOnStruct {}; // expected-warning{{'os_returns_not_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}}
+
+__attribute__((os_consumes_this)) void no_consumes_this_on_function() {} // expected-warning{{'os_consumes_this' attribute only applies to non-static member functions}}
+
+void write_into_out_parameter(__attribute__((os_returns_retained)) S** out) {}
+
+bool write_into_out_parameter_on_nonzero(__attribute__((os_returns_retained_on_non_zero)) S** out) {}
+
+bool write_into_out_parameter_on_nonzero_invalid(__attribute__((os_returns_retained_on_non_zero)) S* out) {} // expected-warning{{'os_returns_retained_on_non_zero' attribute only applies to pointer/reference-to-OSObject-pointer parameters}}
+
+bool write_into_out_parameter_on_zero(__attribute__((os_returns_retained_on_zero)) S** out) {}
+
+bool write_into_out_parameter_on_zero_invalid(__attribute__((os_returns_retained_on_zero)) S* out) {} // expected-warning{{'os_returns_retained_on_zero' attribute only applies to pointer/reference-to-OSObject-pointer parameters}}
+
+void write_into_out_parameter_ref(__attribute__((os_returns_retained)) S*& out) {}
+
+typedef S* SPtr;
+
+void write_into_out_parameter_typedef(__attribute__((os_returns_retained)) SPtr* out) {}
+
+void write_into_out_parameter_invalid(__attribute__((os_returns_retained)) S* out) {} // expected-warning{{'os_returns_retained' attribute only applies to pointer/reference-to-OSObject-pointer parameters}}
+
+void write_into_out_parameter_not_retained(__attribute__((os_returns_not_retained)) S **out) {}
+
+void write_into_out_parameter_not_retained(__attribute__((os_returns_not_retained)) S volatile * const * const out) {}
+
+void write_into_not_retainedout_parameter_invalid(__attribute__((os_returns_not_retained)) S* out) {} // expected-warning{{'os_returns_not_retained' attribute only applies to pointer/reference-to-OSObject-pointer parameters}}
+
+void write_into_not_retainedout_parameter_too_many_pointers(__attribute__((os_returns_not_retained)) S*** out) {} // expected-warning{{'os_returns_not_retained' attribute only applies to pointer/reference-to-OSObject-pointer parameters}}
diff --git a/test/Sema/attr-osobject.mm b/test/Sema/attr-osobject.mm
new file mode 100644
index 000000000000..8b3aadff801c
--- /dev/null
+++ b/test/Sema/attr-osobject.mm
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
+
+struct S {};
+
+@interface I
+ @property (readonly) S* prop __attribute__((os_returns_retained));
+ - (S*) generateS __attribute__((os_returns_retained));
+ - (void) takeS:(S*) __attribute__((os_consumed)) s;
+@end
+
+typedef __attribute__((os_returns_retained)) id (^blockType)(); // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}}
+
+__auto_type b = ^ id (id filter) __attribute__((os_returns_retained)) { // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}}
+ return filter;
+};
diff --git a/test/Sema/attr-ownership.c b/test/Sema/attr-ownership.c
index ff6c7197df8d..5ce758d9f4ad 100644
--- a/test/Sema/attr-ownership.c
+++ b/test/Sema/attr-ownership.c
@@ -16,11 +16,11 @@ void *f11(float i) __attribute__((ownership_returns(foo, 1))); // expected-erro
void *f12(float i, int k, int f, int *j) __attribute__((ownership_returns(foo, 4))); // expected-error {{'ownership_returns' attribute only applies to integer arguments}}
void f13(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_takes(foo, 2)));
-void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_holds' and 'ownership_takes' attributes are not compatible}}
+void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_takes' and 'ownership_holds' attributes are not compatible}}
void f15(int, int)
- __attribute__((ownership_returns(foo, 1))) // expected-note {{declared with index 1 here}}
- __attribute__((ownership_returns(foo, 2))); // expected-error {{'ownership_returns' attribute index does not match; here it is 2}}
+ __attribute__((ownership_returns(foo, 1))) // expected-error {{'ownership_returns' attribute index does not match; here it is 1}}
+ __attribute__((ownership_returns(foo, 2))); // expected-note {{declared with index 2 here}}
void f16(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_holds(foo, 1))); // OK, same index
void f17(void*) __attribute__((ownership_takes(__, 1)));
void f18() __attribute__((ownership_takes(foo, 1))); // expected-warning {{'ownership_takes' attribute only applies to non-K&R-style functions}}
diff --git a/test/Sema/attr-ownership.cpp b/test/Sema/attr-ownership.cpp
index cde195ff0aa8..7381285e2da4 100644
--- a/test/Sema/attr-ownership.cpp
+++ b/test/Sema/attr-ownership.cpp
@@ -2,6 +2,6 @@
class C {
void f(int, int)
- __attribute__((ownership_returns(foo, 2))) // expected-note {{declared with index 2 here}}
- __attribute__((ownership_returns(foo, 3))); // expected-error {{'ownership_returns' attribute index does not match; here it is 3}}
+ __attribute__((ownership_returns(foo, 2))) // expected-error {{'ownership_returns' attribute index does not match; here it is 2}}
+ __attribute__((ownership_returns(foo, 3))); // expected-note {{declared with index 3 here}}
};
diff --git a/test/Sema/attr-print.c b/test/Sema/attr-print.c
index 16b440d5d73a..a326e1c58f48 100644
--- a/test/Sema/attr-print.c
+++ b/test/Sema/attr-print.c
@@ -22,15 +22,13 @@ int * __ptr32 p32;
// CHECK: int * __ptr64 p64;
int * __ptr64 p64;
-// TODO: the Type Printer has no way to specify the order to print attributes
-// in, and so it currently always prints them in reverse order. Fix this.
-// CHECK: int * __ptr32 __uptr p32_2;
+// CHECK: int * __uptr __ptr32 p32_2;
int * __uptr __ptr32 p32_2;
-// CHECK: int * __ptr64 __sptr p64_2;
+// CHECK: int * __sptr __ptr64 p64_2;
int * __sptr __ptr64 p64_2;
-// CHECK: int * __ptr32 __uptr p32_3;
+// CHECK: int * __uptr __ptr32 p32_3;
int * __uptr __ptr32 p32_3;
// CHECK: int * __sptr * __ptr32 ppsp32;
diff --git a/test/Sema/attr-target-mv-bad-target.c b/test/Sema/attr-target-mv-bad-target.c
index 9cf3c5e10a6b..4d61872b9075 100644
--- a/test/Sema/attr-target-mv-bad-target.c
+++ b/test/Sema/attr-target-mv-bad-target.c
@@ -1,4 +1,3 @@
-// RUN: %clang_cc1 -triple x86_64-windows-pc -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple arm-none-eabi -fsyntax-only -verify %s
int __attribute__((target("sse4.2"))) redecl1(void) { return 1; }
diff --git a/test/Sema/attr-target-mv.c b/test/Sema/attr-target-mv.c
index 671adff5b042..664ade1c0fa5 100644
--- a/test/Sema/attr-target-mv.c
+++ b/test/Sema/attr-target-mv.c
@@ -65,10 +65,9 @@ int __attribute__((target("sse4.2,arch=sandybridge"))) mangle(void) { return 1;
//expected-note@-2 {{previous declaration is here}}
int __attribute__((target("arch=sandybridge,sse4.2"))) mangle(void) { return 2; }
+// allow this, since we want to treat the 1st one as fwd-decl of the sandybridge version.
int prev_no_target(void);
int __attribute__((target("arch=sandybridge"))) prev_no_target(void) { return 2; }
-// expected-error@-2 {{function declaration is missing 'target' attribute in a multiversioned function}}
-// expected-note@+1 {{function multiversioning caused by this declaration}}
int __attribute__((target("arch=ivybridge"))) prev_no_target(void) { return 2; }
int __attribute__((target("arch=sandybridge"))) prev_no_target2(void);
diff --git a/test/Sema/attr-uninitialized.c b/test/Sema/attr-uninitialized.c
new file mode 100644
index 000000000000..44c7b4a54efc
--- /dev/null
+++ b/test/Sema/attr-uninitialized.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+void good() {
+ int dont_initialize_me __attribute((uninitialized));
+}
+
+void bad() {
+ int im_bad __attribute((uninitialized("zero"))); // expected-error {{'uninitialized' attribute takes no arguments}}
+ static int im_baaad __attribute((uninitialized)); // expected-warning {{'uninitialized' attribute only applies to local variables}}
+}
+
+extern int come_on __attribute((uninitialized)); // expected-warning {{'uninitialized' attribute only applies to local variables}}
+int you_know __attribute((uninitialized)); // expected-warning {{'uninitialized' attribute only applies to local variables}}
+static int and_the_whole_world_has_to __attribute((uninitialized)); // expected-warning {{'uninitialized' attribute only applies to local variables}}
+
+void answer_right_now() __attribute((uninitialized)) {} // expected-warning {{'uninitialized' attribute only applies to local variables}}
+void just_to_tell_you_once_again(__attribute((uninitialized)) int whos_bad) {} // expected-warning {{'uninitialized' attribute only applies to local variables}}
+
+struct TheWordIsOut {
+ __attribute((uninitialized)) int youre_doin_wrong; // expected-warning {{'uninitialized' attribute only applies to local variables}}
+} __attribute((uninitialized)); // expected-warning {{'uninitialized' attribute only applies to local variables}}
diff --git a/test/Sema/attr-visibility.c b/test/Sema/attr-visibility.c
index ed52ec2743f9..798d6dcd78fc 100644
--- a/test/Sema/attr-visibility.c
+++ b/test/Sema/attr-visibility.c
@@ -15,8 +15,8 @@ struct test5;
struct __attribute__((visibility("hidden"))) test5; // expected-note {{previous attribute is here}}
struct __attribute__((visibility("default"))) test5; // expected-error {{visibility does not match previous declaration}}
-void test6() __attribute__((visibility("hidden"), // expected-note {{previous attribute is here}}
- visibility("default"))); // expected-error {{visibility does not match previous declaration}}
+void test6() __attribute__((visibility("default"), // expected-error {{visibility does not match previous declaration}}
+ visibility("hidden"))); // expected-note {{previous attribute is here}}
extern int test7 __attribute__((visibility("default"))); // expected-note {{previous attribute is here}}
extern int test7 __attribute__((visibility("hidden"))); // expected-error {{visibility does not match previous declaration}}
diff --git a/test/Sema/availability-guard-format.mm b/test/Sema/availability-guard-format.mm
index 910de49ffc81..0e158c4173c2 100644
--- a/test/Sema/availability-guard-format.mm
+++ b/test/Sema/availability-guard-format.mm
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx-10.11 -Wunguarded-availability -fdiagnostics-parseable-fixits -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11 -Wunguarded-availability -fdiagnostics-parseable-fixits -fsyntax-only -verify %s
// Testing that even for source code using '_' as a delimiter in availability version tuple '.' is actually used in diagnostic output as a delimiter.
@interface foo
-- (void) method_bar __attribute__((availability(macosx, introduced = 10_12))); // expected-note {{'method_bar' has been explicitly marked partial here}}
+- (void) method_bar __attribute__((availability(macosx, introduced = 10_12))); // expected-note {{'method_bar' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.11.0}}
@end
int main() {
diff --git a/test/Sema/builtin-object-size.c b/test/Sema/builtin-object-size.c
index 436e99d9ab88..fcf86f3e344a 100644
--- a/test/Sema/builtin-object-size.c
+++ b/test/Sema/builtin-object-size.c
@@ -23,7 +23,7 @@ int f3() {
// rdar://6252231 - cannot call vsnprintf with va_list on x86_64
void f4(const char *fmt, ...) {
__builtin_va_list args;
- __builtin___vsnprintf_chk (0, 42, 0, 11, fmt, args); // expected-warning {{'__builtin___vsnprintf_chk' will always overflow destination buffer}}
+ __builtin___vsnprintf_chk (0, 42, 0, 11, fmt, args); // expected-warning {{'__builtin___vsnprintf_chk' will always overflow; destination buffer has size 11, but size argument is 42}}
}
// rdar://18334276
@@ -50,7 +50,7 @@ void f6(void)
char b[5];
char buf[10];
__builtin___memccpy_chk (buf, b, '\0', sizeof(b), __builtin_object_size (buf, 0));
- __builtin___memccpy_chk (b, buf, '\0', sizeof(buf), __builtin_object_size (b, 0)); // expected-warning {{'__builtin___memccpy_chk' will always overflow destination buffer}}
+ __builtin___memccpy_chk (b, buf, '\0', sizeof(buf), __builtin_object_size (b, 0)); // expected-warning {{'__builtin___memccpy_chk' will always overflow; destination buffer has size 5, but size argument is 10}}
}
int pr28314(void) {
diff --git a/test/Sema/builtins-microsoft-arm64.c b/test/Sema/builtins-microsoft-arm64.c
new file mode 100644
index 000000000000..b72e7038954c
--- /dev/null
+++ b/test/Sema/builtins-microsoft-arm64.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple arm64-windows -fsyntax-only -verify \
+// RUN: -fms-compatibility -ffreestanding -fms-compatibility-version=17.00 %s
+
+#include <intrin.h>
+
+void check__getReg() {
+ __getReg(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+ __getReg(32); // expected-error-re {{argument value {{.*}} is outside the valid range}}
+}
+
+void check_ReadWriteStatusReg(int v) {
+ int x;
+ _ReadStatusReg(x); // expected-error {{argument to '_ReadStatusReg' must be a constant integer}}
+ _WriteStatusReg(x, v); // expected-error {{argument to '_WriteStatusReg' must be a constant integer}}
+}
diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c
index a831d030ef11..62992c0a47eb 100644
--- a/test/Sema/builtins.c
+++ b/test/Sema/builtins.c
@@ -122,6 +122,14 @@ int test16() {
__builtin_constant_p(1, 2); // expected-error {{too many arguments}}
}
+// __builtin_constant_p cannot resolve non-constants as a file scoped array.
+int expr;
+char y[__builtin_constant_p(expr) ? -1 : 1]; // no warning, the builtin is false.
+
+// no warning, the builtin is false.
+struct foo { int a; };
+struct foo x = (struct foo) { __builtin_constant_p(42) ? 37 : 927 };
+
const int test17_n = 0;
const char test17_c[] = {1, 2, 3, 0};
const char test17_d[] = {1, 2, 3, 4};
@@ -161,6 +169,7 @@ void test17() {
F(&test17_d);
F((struct Aggregate){0, 1});
F((IntVector){0, 1, 2, 3});
+ F(test17);
// Ensure that a technique used in glibc is handled correctly.
#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4)
@@ -221,14 +230,14 @@ void Test19(void)
// expected-note {{change size argument to be the size of the destination}}
__builtin___strlcpy_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcpy_chk' call appears to be size of the source; expected the size of the destination}} \
// expected-note {{change size argument to be the size of the destination}} \
- // expected-warning {{'__builtin___strlcpy_chk' will always overflow destination buffer}}
+ // expected-warning {{'__builtin___strlcpy_chk' will always overflow; destination buffer has size 20, but size argument is 40}}
strlcat(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcat' call appears to be size of the source; expected the size of the destination}} \
// expected-note {{change size argument to be the size of the destination}}
__builtin___strlcat_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcat_chk' call appears to be size of the source; expected the size of the destination}} \
// expected-note {{change size argument to be the size of the destination}} \
- // expected-warning {{'__builtin___strlcat_chk' will always overflow destination buffer}}
+ // expected-warning {{'__builtin___strlcat_chk' will always overflow; destination buffer has size 20, but size argument is 40}}
}
// rdar://11076881
@@ -236,7 +245,7 @@ char * Test20(char *p, const char *in, unsigned n)
{
static char buf[10];
- __builtin___memcpy_chk (&buf[6], in, 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}}
+ __builtin___memcpy_chk (&buf[6], in, 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow; destination buffer has size 4, but size argument is 5}}
__builtin___memcpy_chk (p, "abcde", n, __builtin_object_size (p, 0));
@@ -244,11 +253,29 @@ char * Test20(char *p, const char *in, unsigned n)
__builtin___memcpy_chk (&buf[5], "abcde", n, __builtin_object_size (&buf[5], 0));
- __builtin___memcpy_chk (&buf[6], "abcde", 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}}
+ __builtin___memcpy_chk (&buf[6], "abcde", 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow; destination buffer has size 4, but size argument is 5}}
return buf;
}
+typedef void (fn_t)(int);
+
+void test_builtin_launder(char *p, void *vp, const void *cvp,
+ const volatile int *ip, float *restrict fp,
+ fn_t *fn) {
+ __builtin_launder(); // expected-error {{too few arguments to function call, expected 1, have 0}}
+ __builtin_launder(p, p); // expected-error {{too many arguments to function call, expected 1, have 2}}
+ int x;
+ __builtin_launder(x); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ char *d = __builtin_launder(p);
+ __builtin_launder(vp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(cvp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}}
+ const volatile int *id = __builtin_launder(ip);
+ int *id2 = __builtin_launder(ip); // expected-warning {{discards qualifiers}}
+ float *fd = __builtin_launder(fp);
+ __builtin_launder(fn); // expected-error {{function pointer argument to '__builtin_launder' is not allowed}}
+}
+
void test21(const int *ptr) {
__sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}}
__atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}}
@@ -276,3 +303,14 @@ void test22(void) {
(void)__builtin_signbitl(1.0f);
(void)__builtin_signbitl(1.0L);
}
+
+// rdar://43909200
+#define memcpy(x,y,z) __builtin___memcpy_chk(x,y,z, __builtin_object_size(x,0))
+#define my_memcpy(x,y,z) __builtin___memcpy_chk(x,y,z, __builtin_object_size(x,0))
+
+void test23() {
+ char src[1024];
+ char buf[10];
+ memcpy(buf, src, 11); // expected-warning{{'memcpy' will always overflow; destination buffer has size 10, but size argument is 11}}
+ my_memcpy(buf, src, 11); // expected-warning{{'__builtin___memcpy_chk' will always overflow; destination buffer has size 10, but size argument is 11}}
+}
diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c
index c7a4821412cd..8b64bee0474f 100644
--- a/test/Sema/callingconv.c
+++ b/test/Sema/callingconv.c
@@ -51,6 +51,8 @@ int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{calling conv
int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{calling convention 'pcs' ignored for this target}}
int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{invalid PCS type}}
+int __attribute__((aarch64_vector_pcs)) aavpcs(void); // expected-warning {{calling convention 'aarch64_vector_pcs' ignored for this target}}
+
// PR6361
void ctest3();
void __attribute__((cdecl)) ctest3() {}
diff --git a/test/Sema/conditional-expr.c b/test/Sema/conditional-expr.c
index 5ff58a2ec476..6b24ef49b3e6 100644
--- a/test/Sema/conditional-expr.c
+++ b/test/Sema/conditional-expr.c
@@ -73,10 +73,10 @@ void foo() {
int __attribute__((address_space(2))) *adr2;
int __attribute__((address_space(3))) *adr3;
- test0 ? adr2 : adr3; // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+ test0 ? adr2 : adr3; // expected-error{{conditional operator with the second and third operands of type ('__attribute__((address_space(2))) int *' and '__attribute__((address_space(3))) int *') which are pointers to non-overlapping address spaces}}
// Make sure address-space mask ends up in the result type
- (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+ (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-error{{conditional operator with the second and third operands of type ('__attribute__((address_space(2))) int *' and 'int *') which are pointers to non-overlapping address spaces}}
}
int Postgresql() {
diff --git a/test/Sema/conditional.c b/test/Sema/conditional.c
index 3d7bccaf9758..1f3a6d04f14d 100644
--- a/test/Sema/conditional.c
+++ b/test/Sema/conditional.c
@@ -12,3 +12,10 @@ int _php_stream_free1() {
int _php_stream_free2() {
return (1 ? _efree(0) : free(0)); // expected-error {{returning 'void' from a function with incompatible result type 'int'}}
}
+
+void pr39809() {
+ _Generic(0 ? (int const *)0 : (void *)0, int const *: (void)0);
+ _Generic(0 ? (int const *)0 : (void *)1, void const *: (void)0);
+ _Generic(0 ? (int volatile*)0 : (void const*)1, void volatile const*: (void)0);
+ _Generic(0 ? (int volatile*)0 : (void const*)0, void volatile const*: (void)0);
+}
diff --git a/test/Sema/constant-builtins-2.c b/test/Sema/constant-builtins-2.c
index 40cfce1f4a00..9bb5215b8dbd 100644
--- a/test/Sema/constant-builtins-2.c
+++ b/test/Sema/constant-builtins-2.c
@@ -176,6 +176,19 @@ char ffs4[__builtin_ffs(0xfbe70) == 5 ? 1 : -1];
char ffs5[__builtin_ffs(1U << (BITSIZE(int) - 1)) == BITSIZE(int) ? 1 : -1];
char ffs6[__builtin_ffsl(0x10L) == 5 ? 1 : -1];
char ffs7[__builtin_ffsll(0x100LL) == 9 ? 1 : -1];
+
+char clrsb1[__builtin_clrsb(0) == BITSIZE(int) - 1 ? 1 : -1];
+char clrsb2[__builtin_clrsbl(0L) == BITSIZE(long) - 1 ? 1 : -1];
+char clrsb3[__builtin_clrsbll(0LL) == BITSIZE(long long) - 1 ? 1 : -1];
+char clrsb4[__builtin_clrsb(~0) == BITSIZE(int) - 1 ? 1 : -1];
+char clrsb5[__builtin_clrsbl(~0L) == BITSIZE(long) - 1 ? 1 : -1];
+char clrsb6[__builtin_clrsbll(~0LL) == BITSIZE(long long) - 1 ? 1 : -1];
+char clrsb7[__builtin_clrsb(1) == BITSIZE(int) - 2 ? 1 : -1];
+char clrsb8[__builtin_clrsb(~1) == BITSIZE(int) - 2 ? 1 : -1];
+char clrsb9[__builtin_clrsb(1 << (BITSIZE(int) - 1)) == 0 ? 1 : -1];
+char clrsb10[__builtin_clrsb(~(1 << (BITSIZE(int) - 1))) == 0 ? 1 : -1];
+char clrsb11[__builtin_clrsb(0xf) == BITSIZE(int) - 5 ? 1 : -1];
+char clrsb12[__builtin_clrsb(~0x1f) == BITSIZE(int) - 6 ? 1 : -1];
#undef BITSIZE
// GCC misc stuff
diff --git a/test/Sema/conversion.c b/test/Sema/conversion.c
index aa591c9fa60d..07b22a8a6489 100644
--- a/test/Sema/conversion.c
+++ b/test/Sema/conversion.c
@@ -359,7 +359,7 @@ void f7676608(int);
void test_7676608(void) {
float q = 0.7f;
char c = 5;
- f7676608(c *= q);
+ f7676608(c *= q); // expected-warning {{conversion}}
}
// <rdar://problem/7904686>
diff --git a/test/Sema/div-sizeof-ptr.cpp b/test/Sema/div-sizeof-ptr.cpp
new file mode 100644
index 000000000000..4a411ff6bb09
--- /dev/null
+++ b/test/Sema/div-sizeof-ptr.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 %s -verify -Wsizeof-pointer-div -fsyntax-only
+
+template <typename Ty, int N>
+int f(Ty (&Array)[N]) {
+ return sizeof(Array) / sizeof(Ty); // Should not warn
+}
+
+void test(int *p, int **q) {
+ int a1 = sizeof(p) / sizeof(*p); // expected-warning {{'sizeof (p)' will return the size of the pointer, not the array itself}}
+ int a2 = sizeof p / sizeof *p; // expected-warning {{'sizeof p' will return the size of the pointer, not the array itself}}
+ int a3 = sizeof(*q) / sizeof(**q); // expected-warning {{'sizeof (*q)' will return the size of the pointer, not the array itself}}
+ int a4 = sizeof(p) / sizeof(int); // expected-warning {{'sizeof (p)' will return the size of the pointer, not the array itself}}
+ int a5 = sizeof(p) / sizeof(p[0]); // expected-warning {{'sizeof (p)' will return the size of the pointer, not the array itself}}
+
+ // Should not warn
+ int b1 = sizeof(int *) / sizeof(int);
+ int b2 = sizeof(p) / sizeof(p);
+ int b3 = sizeof(*q) / sizeof(q);
+ int b4 = sizeof(p) / sizeof(char);
+
+ int arr[10];
+ int b5 = sizeof(arr) / sizeof(*arr);
+ int b6 = sizeof(arr) / sizeof(arr[0]);
+ int b7 = sizeof(arr) / sizeof(int);
+
+ int arr2[10][12];
+ int b8 = sizeof(arr2) / sizeof(*arr2);
+}
diff --git a/test/Sema/enum.c b/test/Sema/enum.c
index f9e40690c6a6..7681ebccd4fa 100644
--- a/test/Sema/enum.c
+++ b/test/Sema/enum.c
@@ -135,3 +135,26 @@ struct PR28903 {
};
int makeStructNonEmpty;
};
+
+static int EnumRedecl; // expected-note 2 {{previous definition is here}}
+struct S {
+ enum {
+ EnumRedecl = 4 // expected-error {{redefinition of 'EnumRedecl'}}
+ } e;
+};
+
+union U {
+ enum {
+ EnumRedecl = 5 // expected-error {{redefinition of 'EnumRedecl'}}
+ } e;
+};
+
+enum PR15071 {
+ PR15071_One // expected-note {{previous definition is here}}
+};
+
+struct EnumRedeclStruct {
+ enum {
+ PR15071_One // expected-error {{redefinition of enumerator 'PR15071_One'}}
+ } e;
+};
diff --git a/test/Sema/ext-typecheck-comparison-of-pointer-integer.c b/test/Sema/ext-typecheck-comparison-of-pointer-integer.c
new file mode 100644
index 000000000000..b928156aff28
--- /dev/null
+++ b/test/Sema/ext-typecheck-comparison-of-pointer-integer.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -DEXPECTWARNING %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -Wno-pointer-integer-compare %s
+
+#ifdef EXPECTWARNING
+// expected-warning@+6 {{comparison between pointer and integer ('int' and 'int *')}}
+#else
+// expected-no-diagnostics
+#endif
+
+int test_ext_typecheck_comparison_of_pointer_integer(int integer, int * pointer) {
+ return integer != pointer;
+}
diff --git a/test/Sema/fixed-enum.c b/test/Sema/fixed-enum.c
new file mode 100644
index 000000000000..60a4bc474f71
--- /dev/null
+++ b/test/Sema/fixed-enum.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -Weverything -xc++ -std=c++11 -DCXX11 -verify %s
+// RUN: %clang_cc1 -Weverything -xc++ -std=c++03 -DCXX03 -verify %s
+// RUN: %clang_cc1 -Weverything -xobjective-c -DOBJC -verify %s
+// RUN: %clang_cc1 -Weverything -std=c11 -xc -DC11 -verify %s
+// RUN: %clang_cc1 -Weverything -std=c11 -xc -fms-extensions -DMS -verify %s
+
+enum X : int {e};
+#if defined(CXX11)
+// expected-warning@-2{{enumeration types with a fixed underlying type are incompatible with C++98}}
+#elif defined(CXX03)
+// expected-warning@-4{{enumeration types with a fixed underlying type are a C++11 extension}}
+#elif defined(OBJC)
+// expected-no-diagnostics
+#elif defined(C11)
+// expected-warning@-8{{enumeration types with a fixed underlying type are a Clang extension}}
+#elif defined(MS)
+// expected-warning@-10{{enumeration types with a fixed underlying type are a Microsoft extension}}
+#endif
diff --git a/test/Sema/format-strings-bitfield-promotion.c b/test/Sema/format-strings-bitfield-promotion.c
new file mode 100644
index 000000000000..cbe00e7510dd
--- /dev/null
+++ b/test/Sema/format-strings-bitfield-promotion.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fsyntax-only -verify %s
+
+int printf(const char *restrict, ...);
+
+struct bitfields {
+ long a : 2;
+ unsigned long b : 2;
+ long c : 32; // assumes that int is 32 bits
+ unsigned long d : 32; // assumes that int is 32 bits
+} bf;
+
+void bitfield_promotion() {
+ printf("%ld", bf.a); // expected-warning {{format specifies type 'long' but the argument has type 'int'}}
+ printf("%lu", bf.b); // expected-warning {{format specifies type 'unsigned long' but the argument has type 'int'}}
+ printf("%ld", bf.c); // expected-warning {{format specifies type 'long' but the argument has type 'int'}}
+ printf("%lu", bf.d); // expected-warning {{format specifies type 'unsigned long' but the argument has type 'unsigned int'}}
+}
diff --git a/test/Sema/format-strings-bitfield-promotion.cxx b/test/Sema/format-strings-bitfield-promotion.cxx
new file mode 100644
index 000000000000..2309e98066c6
--- /dev/null
+++ b/test/Sema/format-strings-bitfield-promotion.cxx
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fsyntax-only -verify %s
+
+// In C++, the bitfield promotion from long to int does not occur, unlike C.
+// expected-no-diagnostics
+
+int printf(const char *restrict, ...);
+
+struct bitfields {
+ long a : 2;
+ unsigned long b : 2;
+ long c : 32; // assumes that int is 32 bits
+ unsigned long d : 32; // assumes that int is 32 bits
+} bf;
+
+void bitfield_promotion() {
+ printf("%ld", bf.a);
+ printf("%lu", bf.b);
+ printf("%ld", bf.c);
+ printf("%lu", bf.d);
+}
diff --git a/test/Sema/format-strings-ms.c b/test/Sema/format-strings-ms.c
index 42676e7a4e06..56a349051d42 100644
--- a/test/Sema/format-strings-ms.c
+++ b/test/Sema/format-strings-ms.c
@@ -49,7 +49,7 @@ void w_test(wchar_t c, wchar_t *s) {
scanf("%S", s);
double bad;
- printf("%wc", bad); // expected-warning{{format specifies type 'wint_t' (aka 'int') but the argument has type 'double'}}
+ printf("%wc", bad); // expected-warning{{format specifies type 'wint_t' (aka 'unsigned short') but the argument has type 'double'}}
printf("%wC", bad); // expected-warning{{format specifies type 'wchar_t' (aka 'unsigned short') but the argument has type 'double'}}
printf("%C", bad); // expected-warning{{format specifies type 'wchar_t' (aka 'unsigned short') but the argument has type 'double'}}
printf("%ws", bad); // expected-warning{{format specifies type 'wchar_t *' (aka 'unsigned short *') but the argument has type 'double'}}
diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c
index 54651226adc5..a9af8ce5dee9 100644
--- a/test/Sema/format-strings.c
+++ b/test/Sema/format-strings.c
@@ -401,7 +401,11 @@ void bug7377_bad_length_mod_usage() {
void pr7981(wint_t c, wchar_t c2) {
printf("%lc", c); // no-warning
printf("%lc", 1.0); // expected-warning{{the argument has type 'double'}}
+#if __WINT_WIDTH__ == 32
printf("%lc", (char) 1); // no-warning
+#else
+ printf("%lc", (char) 1); // expected-warning{{the argument has type 'char'}}
+#endif
printf("%lc", &c); // expected-warning{{the argument has type 'wint_t *'}}
// If wint_t and wchar_t are the same width and wint_t is signed where
// wchar_t is unsigned, an implicit conversion isn't possible.
@@ -609,6 +613,11 @@ void pr12761(char c) {
printf("%hhx", c);
}
+void test_opencl_vector_format(int x) {
+ printf("%v4d", x); // expected-warning{{invalid conversion specifier 'v'}}
+ printf("%vd", x); // expected-warning{{invalid conversion specifier 'v'}}
+ printf("%0vd", x); // expected-warning{{invalid conversion specifier 'v'}}
+}
// Test that we correctly merge the format in both orders.
extern void test14_foo(const char *, const char *, ...)
diff --git a/test/Sema/implicit-int-conversion.c b/test/Sema/implicit-int-conversion.c
new file mode 100644
index 000000000000..6d07d385e0bd
--- /dev/null
+++ b/test/Sema/implicit-int-conversion.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -verify -Wconversion -Wno-implicit-int-conversion -DSMALL=char -DBIG=int -DNO_DIAG
+// RUN: %clang_cc1 %s -verify -Wno-conversion -Wimplicit-int-conversion -DSMALL=char -DBIG=int
+// RUN: %clang_cc1 %s -verify -Wconversion -Wno-implicit-float-conversion -DSMALL=float -DBIG=double -DNO_DIAG
+// RUN: %clang_cc1 %s -verify -Wno-conversion -Wimplicit-float-conversion -DSMALL=float -DBIG=double
+
+void f() {
+ SMALL a;
+ BIG b = 0;
+ a = b;
+#ifndef NO_DIAG
+ // expected-warning@-2 {{implicit conversion}}
+#else
+ // expected-no-diagnostics
+#endif
+}
diff --git a/test/Sema/integer-overflow.c b/test/Sema/integer-overflow.c
index d66ce7ff1647..39395d9bc1fd 100644
--- a/test/Sema/integer-overflow.c
+++ b/test/Sema/integer-overflow.c
@@ -172,6 +172,9 @@ void check_integer_overflows_in_function_calls() {
// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
(void)f2(0, f0(4608 * 1024 * 1024));
}
+void check_integer_overflows_in_array_size() {
+ int arr[4608 * 1024 * 1024]; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}}
+}
struct s {
unsigned x;
diff --git a/test/Sema/internal_linkage.c b/test/Sema/internal_linkage.c
index 57315d826e24..cc8039acd275 100644
--- a/test/Sema/internal_linkage.c
+++ b/test/Sema/internal_linkage.c
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fdouble-square-bracket-attributes %s
int var __attribute__((internal_linkage));
-int var2 __attribute__((internal_linkage,common)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \
+int var2 __attribute__((internal_linkage,common)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \
// expected-note{{conflicting attribute is here}}
-int var3 __attribute__((common,internal_linkage)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \
+int var3 __attribute__((common,internal_linkage)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \
// expected-note{{conflicting attribute is here}}
int var4 __attribute__((common)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \
diff --git a/test/Sema/mips-interrupt-attr.c b/test/Sema/mips-interrupt-attr.c
index 17344b6edcf0..7c5c9ddab5d6 100644
--- a/test/Sema/mips-interrupt-attr.c
+++ b/test/Sema/mips-interrupt-attr.c
@@ -19,11 +19,11 @@ __attribute__((interrupt(""))) void food() {}
__attribute__((interrupt)) int foob() {return 0;} // expected-warning {{MIPS 'interrupt' attribute only applies to functions that have a 'void' return type}}
__attribute__((interrupt())) void fooc(int a) {} // expected-warning {{MIPS 'interrupt' attribute only applies to functions that have no parameters}}
-__attribute__((interrupt,mips16)) void fooe() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \
+__attribute__((interrupt,mips16)) void fooe() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
-__attribute__((mips16,interrupt)) void foof() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \
+__attribute__((mips16,interrupt)) void foof() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
-__attribute__((interrupt)) __attribute__ ((mips16)) void foo10() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \
+__attribute__((interrupt)) __attribute__ ((mips16)) void foo10() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
-__attribute__((mips16)) __attribute ((interrupt)) void foo11() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \
+__attribute__((mips16)) __attribute ((interrupt)) void foo11() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \
// expected-note {{conflicting attribute is here}}
diff --git a/test/Sema/nullability.c b/test/Sema/nullability.c
index a0247e5af8b3..a5cb4b9a031e 100644
--- a/test/Sema/nullability.c
+++ b/test/Sema/nullability.c
@@ -20,8 +20,8 @@ typedef int * _Null_unspecified null_unspecified_int_ptr;
typedef int * _Nonnull _Nonnull redundant_1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
// Conflicting nullability type specifiers.
-typedef int * _Nonnull _Nullable conflicting_1; // expected-error{{nullability specifier '_Nonnull' conflicts with existing specifier '_Nullable'}}
-typedef int * _Null_unspecified _Nonnull conflicting_2; // expected-error{{nullability specifier '_Null_unspecified' conflicts with existing specifier '_Nonnull'}}
+typedef int * _Nonnull _Nullable conflicting_1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
+typedef int * _Null_unspecified _Nonnull conflicting_2; // expected-error{{nullability specifier '_Nonnull' conflicts with existing specifier '_Null_unspecified'}}
// Redundant nullability specifiers via a typedef are okay.
typedef nonnull_int_ptr _Nonnull redundant_okay_1;
diff --git a/test/Sema/pr32985.c b/test/Sema/pr32985.c
new file mode 100644
index 000000000000..f61cea4e7314
--- /dev/null
+++ b/test/Sema/pr32985.c
@@ -0,0 +1,20 @@
+/*
+RUN: %clang_cc1 %s -std=gnu89 -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU89 %s -allow-empty
+RUN: %clang_cc1 %s -std=gnu89 -pedantic -fsyntax-only 2>&1 | FileCheck -check-prefix=CHECK-GNU89-PEDANTIC %s
+*/
+
+typedef const int t;
+const t c_i;
+/*
+CHECK-GNU89-NOT: 7:1: warning: duplicate 'const' declaration specifier
+CHECK-GNU89-PEDANTIC: 7:1: warning: duplicate 'const' declaration specifier
+*/
+
+const int c_i2;
+const typeof(c_i2) c_i3;
+/*
+CHECK-GNU89-NOT: 14:7: warning: extension used
+CHECK-GNU89-NOT: 14:1: warning: duplicate 'const' declaration specifier
+CHECK-GNU89-PEDANTIC: 14:7: warning: extension used
+CHECK-GNU89-PEDANTIC: 14:1: warning: duplicate 'const' declaration specifier
+*/
diff --git a/test/Sema/pragma-attribute-namespace.c b/test/Sema/pragma-attribute-namespace.c
new file mode 100644
index 000000000000..e7a36afcdc23
--- /dev/null
+++ b/test/Sema/pragma-attribute-namespace.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#if !__has_extension(pragma_clang_attribute_namespaces)
+#error
+#endif
+
+#pragma clang attribute MyNamespace.push (__attribute__((annotate)), apply_to=function) // expected-error 2 {{'annotate' attribute}}
+
+int some_func(); // expected-note{{when applied to this declaration}}
+
+#pragma clang attribute pop // expected-error{{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}}
+#pragma clang attribute NotMyNamespace.pop // expected-error{{'#pragma clang attribute NotMyNamespace.pop' with no matching '#pragma clang attribute NotMyNamespace.push'}}
+
+#pragma clang attribute MyOtherNamespace.push (__attribute__((annotate)), apply_to=function) // expected-error 2 {{'annotate' attribute}}
+
+int some_other_func(); // expected-note 2 {{when applied to this declaration}}
+
+// Out of order!
+#pragma clang attribute MyNamespace.pop
+
+int some_other_other_func(); // expected-note 1 {{when applied to this declaration}}
+
+#pragma clang attribute MyOtherNamespace.pop
+
+#pragma clang attribute Misc. () // expected-error{{namespace can only apply to 'push' or 'pop' directives}} expected-note {{omit the namespace to add attributes to the most-recently pushed attribute group}}
+
+#pragma clang attribute Misc push // expected-error{{expected '.' after pragma attribute namespace 'Misc'}}
+
+// Test how pushes with namespaces interact with pushes without namespaces.
+
+#pragma clang attribute Merp.push (__attribute__((annotate)), apply_to=function) // expected-error{{'annotate' attribute}}
+#pragma clang attribute push (__attribute__((annotate)), apply_to=function) // expected-warning {{unused attribute}}
+#pragma clang attribute pop // expected-note{{ends here}}
+int test(); // expected-note{{when applied to this declaration}}
+#pragma clang attribute Merp.pop
+
+#pragma clang attribute push (__attribute__((annotate)), apply_to=function) // expected-warning {{unused attribute}}
+#pragma clang attribute Merp.push (__attribute__((annotate)), apply_to=function) // expected-error{{'annotate' attribute}}
+#pragma clang attribute pop // expected-note{{ends here}}
+int test2(); // expected-note{{when applied to this declaration}}
+#pragma clang attribute Merp.pop
diff --git a/test/Sema/pragma-attribute.c b/test/Sema/pragma-attribute.c
index d321f2ce4be7..202b3f75faa6 100644
--- a/test/Sema/pragma-attribute.c
+++ b/test/Sema/pragma-attribute.c
@@ -38,6 +38,29 @@ __attribute__((always_inline)) void optnone3() { } // expected-warning {{'always
#pragma clang attribute pop
+#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
+#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
+
+void fun(); // expected-note 2 {{when applied to this declaration}}
+
+#pragma clang attribute pop
+#pragma clang attribute pop // expected-error{{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}}
+
+
+#pragma clang attribute push
+#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes one argument}}
+
+void fun2(); // expected-note {{when applied to this declaration}}
+
+#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
+void fun3(); // expected-note 2 {{when applied to this declaration}}
+#pragma clang attribute pop
+
+#pragma clang attribute pop
+#pragma clang attribute pop // expected-error{{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}}
+
+#pragma clang attribute (__attribute__((annotate)), apply_to = function) // expected-error{{'#pragma clang attribute' attribute with no matching '#pragma clang attribute push}}
+
#pragma clang attribute push ([[]], apply_to = function) // A noop
#pragma clang attribute pop // expected-error {{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}}
diff --git a/test/Sema/pragma-pipeline.cpp b/test/Sema/pragma-pipeline.cpp
new file mode 100644
index 000000000000..7b277601d063
--- /dev/null
+++ b/test/Sema/pragma-pipeline.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+#pragma clang loop pipeline(disable) /* expected-error {{expected unqualified-id}} */
+int main() {
+ for (int i = 0; i < 10; ++i)
+ ;
+}
+
+void test(int *List, int Length, int Value) {
+ int i = 0;
+
+/* expected-error {{invalid argument of type 'double'; expected an integer type}} */ #pragma clang loop pipeline_initiation_interval(1.0)
+/* expected-error {{invalid value '0'; must be positive}} */ #pragma clang loop pipeline_initiation_interval(0)
+/* expected-error {{invalid value '-1'; must be positive}} */ #pragma clang loop pipeline_initiation_interval(-1)
+ for (int i = 0; i < Length; i++) {
+ for (int j = 0; j < Length; j++) {
+ List[i * Length + j] = Value;
+ }
+ }
+
+#pragma clang loop pipeline(disable)
+/* expected-error {{expected a for, while, or do-while loop to follow '#pragma clang loop'}} */ int j = Length;
+#pragma clang loop pipeline_initiation_interval(4)
+/* expected-error {{expected a for, while, or do-while loop to follow '#pragma clang loop'}} */ int k = Length;
+
+#pragma clang loop pipeline(disable)
+#pragma clang loop pipeline_initiation_interval(4) /* expected-error {{incompatible directives 'pipeline(disable)' and 'pipeline_initiation_interval(4)'}} */
+ for (int i = 0; i < Length; i++) {
+ List[i] = Value;
+ }
+
+#pragma clang loop pipeline(disable)
+/* expected-error {{expected statement}} */ }
+
diff --git a/test/Sema/statements.c b/test/Sema/statements.c
index dbb4d56ee1d1..ddaec8d433ef 100644
--- a/test/Sema/statements.c
+++ b/test/Sema/statements.c
@@ -34,6 +34,15 @@ bar:
return &&bar; // expected-warning {{returning address of label, which is local}}
}
+// PR38569: Don't warn when returning a label from a statement expression.
+void test10_logpc(void*);
+void test10a() {
+ test10_logpc(({
+ my_pc:
+ &&my_pc;
+ }));
+}
+
// PR6034
void test11(int bit) {
switch (bit)
diff --git a/test/Sema/static-assert.c b/test/Sema/static-assert.c
index 87fa0504b200..e8cfb1fa58d7 100644
--- a/test/Sema/static-assert.c
+++ b/test/Sema/static-assert.c
@@ -38,5 +38,5 @@ struct A {
typedef UNION(unsigned, struct A) U1;
UNION(char[2], short) u2 = { .one = { 'a', 'b' } };
-typedef UNION(char, short) U3; // expected-error {{static_assert failed "type size mismatch"}}
+typedef UNION(char, short) U3; // expected-error {{static_assert failed due to requirement 'sizeof(char) == sizeof(short)' "type size mismatch"}}
typedef UNION(float, 0.5f) U4; // expected-error {{expected a type}}
diff --git a/test/Sema/suspicious-pragma-pack.c b/test/Sema/suspicious-pragma-pack.c
index d7c5faf06910..1acf63b46892 100644
--- a/test/Sema/suspicious-pragma-pack.c
+++ b/test/Sema/suspicious-pragma-pack.c
@@ -38,7 +38,7 @@
#include "pragma-pack1.h"
#ifdef WARN_MODIFIED_HEADER
-// expected-warning@-3 {{the current #pragma pack aligment value is modified in the included file}}
+// expected-warning@-3 {{the current #pragma pack alignment value is modified in the included file}}
#endif
#ifdef PUSH_SET_HERE
diff --git a/test/Sema/swift-call-conv.c b/test/Sema/swift-call-conv.c
new file mode 100644
index 000000000000..755c18f5183f
--- /dev/null
+++ b/test/Sema/swift-call-conv.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fsyntax-only %s -verify
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fsyntax-only %s -verify
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fsyntax-only %s -verify
+
+// expected-no-diagnostics
+
+void __attribute__((__swiftcall__)) f(void) {}
diff --git a/test/Sema/switch-availability.c b/test/Sema/switch-availability.c
new file mode 100644
index 000000000000..888edddac463
--- /dev/null
+++ b/test/Sema/switch-availability.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -verify -Wswitch -triple x86_64-apple-macosx10.12 %s
+
+enum SwitchOne {
+ Unavail __attribute__((availability(macos, unavailable))),
+};
+
+void testSwitchOne(enum SwitchOne so) {
+ switch (so) {} // no warning
+}
+
+enum SwitchTwo {
+ Ed __attribute__((availability(macos, deprecated=10.12))),
+ Vim __attribute__((availability(macos, deprecated=10.13))),
+ Emacs,
+};
+
+void testSwitchTwo(enum SwitchTwo st) {
+ switch (st) {} // expected-warning{{enumeration values 'Vim' and 'Emacs' not handled in switch}}
+}
+
+enum SwitchThree {
+ New __attribute__((availability(macos, introduced=1000))),
+};
+
+void testSwitchThree(enum SwitchThree st) {
+ switch (st) {} // expected-warning{{enumeration value 'New' not handled in switch}}
+}
diff --git a/test/Sema/sync-implicit-seq_cst.c b/test/Sema/sync-implicit-seq_cst.c
new file mode 100644
index 000000000000..1d9869b2022a
--- /dev/null
+++ b/test/Sema/sync-implicit-seq_cst.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -verify -ffreestanding -fsyntax-only -triple=i686-linux-gnu -std=c11 -Watomic-implicit-seq-cst -Wno-sync-fetch-and-nand-semantics-changed
+
+// __sync_* operations are implicitly sequentially-consistent. Some codebases
+// want to force explicit usage of memory order instead.
+
+void fetch_and_add(int *ptr, int val) { __sync_fetch_and_add(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void fetch_and_sub(int *ptr, int val) { __sync_fetch_and_sub(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void fetch_and_or(int *ptr, int val) { __sync_fetch_and_or(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void fetch_and_and(int *ptr, int val) { __sync_fetch_and_and(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void fetch_and_xor(int *ptr, int val) { __sync_fetch_and_xor(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void fetch_and_nand(int *ptr, int val) { __sync_fetch_and_nand(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+
+void add_and_fetch(int *ptr, int val) { __sync_add_and_fetch(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void sub_and_fetch(int *ptr, int val) { __sync_sub_and_fetch(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void or_and_fetch(int *ptr, int val) { __sync_or_and_fetch(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void and_and_fetch(int *ptr, int val) { __sync_and_and_fetch(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void xor_and_fetch(int *ptr, int val) { __sync_xor_and_fetch(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void nand_and_fetch(int *ptr, int val) { __sync_nand_and_fetch(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+
+void bool_compare_and_swap(int *ptr, int oldval, int newval) { __sync_bool_compare_and_swap(ptr, oldval, newval); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void val_compare_and_swap(int *ptr, int oldval, int newval) { __sync_val_compare_and_swap(ptr, oldval, newval); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+
+void synchronize(void) { __sync_synchronize(); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+
+void lock_test_and_set(int *ptr, int val) { __sync_lock_test_and_set(ptr, val); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
+void lock_release(int *ptr) { __sync_lock_release(ptr); } // expected-warning {{implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary}}
diff --git a/test/Sema/unary-minus-integer-impcast.c b/test/Sema/unary-minus-integer-impcast.c
new file mode 100644
index 000000000000..0eb440175881
--- /dev/null
+++ b/test/Sema/unary-minus-integer-impcast.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -verify -Wconversion -fsyntax-only -triple x86_64-pc-linux-gnu
+// RUN: %clang_cc1 %s -verify -Wconversion -fsyntax-only -triple i386-pc-linux-gnu
+
+void test(void) {
+ unsigned int a = 1;
+
+ unsigned long long b = -a; // expected-warning {{higher order bits are zeroes after implicit conversion}}
+ long long c = -a; // expected-warning {{the resulting value is always non-negative after implicit conversion}}
+
+ unsigned long b2 = -a;
+#ifdef __x86_64__
+// expected-warning@-2 {{higher order bits are zeroes after implicit conversion}}
+#endif
+ long c2 = -a;
+#ifdef __x86_64__
+// expected-warning@-2 {{the resulting value is always non-negative after implicit conversion}}
+#else
+// expected-warning@-4 {{implicit conversion changes signedness: 'unsigned int' to 'long'}}
+#endif
+}
diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c
index 89ea190cbc61..e2d98354932b 100644
--- a/test/Sema/uninit-variables.c
+++ b/test/Sema/uninit-variables.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wconditional-uninitialized -fsyntax-only -fblocks %s -verify
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wconditional-uninitialized -ftrivial-auto-var-init=pattern -fsyntax-only -fblocks %s -verify
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp
index 7ffaffc07849..5083f686338c 100644
--- a/test/Sema/warn-documentation.cpp
+++ b/test/Sema/warn-documentation.cpp
@@ -1304,3 +1304,12 @@ typedef void (*VariadicFnType)(int a, ...);
* now should work too.
*/
using VariadicFnType2 = void (*)(int a, ...);
+
+// expected-warning@+2 {{empty paragraph passed to '@note' command}}
+/**
+@note
+\f$\texttt{mu}_{00}=\texttt{m}_{00}\f$, \f$\texttt{nu}_{00}=1\f$
+\f$\texttt{nu}_{10}=\texttt{mu}_{10}=\texttt{mu}_{01}=\texttt{mu}_{10}=0\f$
+ */
+class EmptyNoteNoCrash {
+};
diff --git a/test/Sema/warn-duplicate-enum.c b/test/Sema/warn-duplicate-enum.c
index 84fdeb4f8fd4..4d51d055f5e9 100644
--- a/test/Sema/warn-duplicate-enum.c
+++ b/test/Sema/warn-duplicate-enum.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify -Wduplicate-enum
-// RUN: %clang_cc1 %s -x c++ -fsyntax-only -verify -Wduplicate-enum
+// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -x c++ -DCPP -fsyntax-only -verify -Wduplicate-enum
enum A {
A1 = 0, // expected-note {{element 'A1' also has value 0}}
A2 = -1,
@@ -99,3 +99,11 @@ enum enum1 {
enum enum2 {
VALUE // expected-error{{redefinition of enumerator 'VALUE'}}
};
+
+// rdar://44774672
+#ifdef CPP
+enum BigEnumerators : long {
+ e1,
+ e2 = __LONG_MAX__,
+};
+#endif
diff --git a/test/Sema/warn-shadow.c b/test/Sema/warn-shadow.c
index 32aca8d612b2..aa8505b0c917 100644
--- a/test/Sema/warn-shadow.c
+++ b/test/Sema/warn-shadow.c
@@ -59,3 +59,15 @@ void rdar8883302() {
void test8() {
int bob; // expected-warning {{declaration shadows a variable in the global scope}}
}
+
+enum PR24718_1{pr24718}; // expected-note {{previous declaration is here}}
+void PR24718(void) {
+ enum PR24718_2{pr24718}; // expected-warning {{declaration shadows a variable in the global scope}}
+}
+
+struct PR24718_3;
+struct PR24718_4 {
+ enum {
+ PR24718_3 // Does not shadow a type.
+ };
+};
diff --git a/test/Sema/zvector.c b/test/Sema/zvector.c
index 740163fcd9d5..858e10d661f8 100644
--- a/test/Sema/zvector.c
+++ b/test/Sema/zvector.c
@@ -37,6 +37,49 @@ unsigned long ul_scalar;
double fd_scalar;
+// Verify that __vector is also recognized
+__vector signed char sc3;
+__vector unsigned char uc3;
+__vector bool char bc3;
+__vector signed short ss3;
+__vector unsigned short us3;
+__vector bool short bs3;
+__vector signed int si3;
+__vector unsigned int ui3;
+__vector bool int bi3;
+__vector signed long long sl3;
+__vector unsigned long long ul3;
+__vector bool long long bl3;
+__vector double fd3;
+__vector long ll3; // expected-error {{cannot use 'long' with '__vector'}}
+__vector float ff3; // expected-error {{cannot use 'float' with '__vector'}}
+
+// Likewise for __bool
+vector __bool char bc4;
+vector __bool short bs4;
+vector __bool int bi4;
+vector __bool long long bl4;
+__vector __bool char bc5;
+__vector __bool short bs5;
+__vector __bool int bi5;
+__vector __bool long long bl5;
+
+// Verify operation of vec_step
+int res_sc[vec_step(sc) == 16 ? 1 : -1];
+int res_uc[vec_step(uc) == 16 ? 1 : -1];
+int res_bc[vec_step(bc) == 16 ? 1 : -1];
+int res_ss[vec_step(ss) == 8 ? 1 : -1];
+int res_us[vec_step(us) == 8 ? 1 : -1];
+int res_bs[vec_step(bs) == 8 ? 1 : -1];
+int res_si[vec_step(si) == 4 ? 1 : -1];
+int res_ui[vec_step(ui) == 4 ? 1 : -1];
+int res_bi[vec_step(bi) == 4 ? 1 : -1];
+int res_sl[vec_step(sl) == 2 ? 1 : -1];
+int res_ul[vec_step(ul) == 2 ? 1 : -1];
+int res_bl[vec_step(bl) == 2 ? 1 : -1];
+int res_fd[vec_step(fd) == 2 ? 1 : -1];
+
+
void foo(void)
{
// -------------------------------------------------------------------------
diff --git a/test/Sema/zvector2.c b/test/Sema/zvector2.c
index 0adc0315f0b8..08ec9dfc661f 100644
--- a/test/Sema/zvector2.c
+++ b/test/Sema/zvector2.c
@@ -22,6 +22,13 @@ vector double fd, fd2;
vector float ff, ff2;
+// Verify that __vector is also recognized
+__vector float ff3;
+
+// Verify operation of vec_step
+int res_ff[vec_step(ff) == 4 ? 1 : -1];
+
+
void foo(void)
{
// -------------------------------------------------------------------------
diff --git a/test/SemaCUDA/call-host-fn-from-device.cu b/test/SemaCUDA/call-host-fn-from-device.cu
index c727dc8cbeb7..acdd291b6645 100644
--- a/test/SemaCUDA/call-host-fn-from-device.cu
+++ b/test/SemaCUDA/call-host-fn-from-device.cu
@@ -41,12 +41,12 @@ struct T {
operator Dummy() { return Dummy(); }
// expected-note@-1 {{'operator Dummy' declared here}}
- __host__ void operator delete(void*);
- __device__ void operator delete(void*, size_t);
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void*, __SIZE_TYPE__);
};
struct U {
- __device__ void operator delete(void*, size_t) = delete;
+ __device__ void operator delete(void*, __SIZE_TYPE__) = delete;
__host__ __device__ void operator delete(void*);
};
diff --git a/test/SemaCUDA/extern-shared.cu b/test/SemaCUDA/extern-shared.cu
index ec6f31695052..bc4f10d3082c 100644
--- a/test/SemaCUDA/extern-shared.cu
+++ b/test/SemaCUDA/extern-shared.cu
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -verify %s
// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fcuda-is-device -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fcuda-rdc -verify=rdc %s
-// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fcuda-is-device -fcuda-rdc -verify=rdc %s
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fgpu-rdc -verify=rdc %s
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-internal -fcuda-is-device -fgpu-rdc -verify=rdc %s
// Most of these declarations are fine in separate compilation mode.
diff --git a/test/SemaCUDA/implicit-member-target-inherited.cu b/test/SemaCUDA/implicit-member-target-inherited.cu
new file mode 100644
index 000000000000..2178172ed019
--- /dev/null
+++ b/test/SemaCUDA/implicit-member-target-inherited.cu
@@ -0,0 +1,205 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -Wno-defaulted-function-deleted
+
+#include "Inputs/cuda.h"
+
+//------------------------------------------------------------------------------
+// Test 1: infer inherited default ctor to be host.
+
+struct A1_with_host_ctor {
+ A1_with_host_ctor() {}
+};
+// expected-note@-3 {{candidate constructor (the implicit copy constructor) not viable}}
+// expected-note@-4 {{candidate constructor (the implicit move constructor) not viable}}
+
+// The inherited default constructor is inferred to be host, so we'll encounter
+// an error when calling it from a __device__ function, but not from a __host__
+// function.
+struct B1_with_implicit_default_ctor : A1_with_host_ctor {
+ using A1_with_host_ctor::A1_with_host_ctor;
+};
+
+// expected-note@-4 {{call to __host__ function from __device__}}
+// expected-note@-5 {{candidate constructor (the implicit copy constructor) not viable}}
+// expected-note@-6 {{candidate constructor (the implicit move constructor) not viable}}
+// expected-note@-6 2{{constructor from base class 'A1_with_host_ctor' inherited here}}
+
+void hostfoo() {
+ B1_with_implicit_default_ctor b;
+}
+
+__device__ void devicefoo() {
+ B1_with_implicit_default_ctor b; // expected-error {{no matching constructor}}
+}
+
+//------------------------------------------------------------------------------
+// Test 2: infer inherited default ctor to be device.
+
+struct A2_with_device_ctor {
+ __device__ A2_with_device_ctor() {}
+};
+// expected-note@-3 {{candidate constructor (the implicit copy constructor) not viable}}
+// expected-note@-4 {{candidate constructor (the implicit move constructor) not viable}}
+
+struct B2_with_implicit_default_ctor : A2_with_device_ctor {
+ using A2_with_device_ctor::A2_with_device_ctor;
+};
+
+// expected-note@-4 {{call to __device__ function from __host__}}
+// expected-note@-5 {{candidate constructor (the implicit copy constructor) not viable}}
+// expected-note@-6 {{candidate constructor (the implicit move constructor) not viable}}
+// expected-note@-6 2{{constructor from base class 'A2_with_device_ctor' inherited here}}
+
+void hostfoo2() {
+ B2_with_implicit_default_ctor b; // expected-error {{no matching constructor}}
+}
+
+__device__ void devicefoo2() {
+ B2_with_implicit_default_ctor b;
+}
+
+//------------------------------------------------------------------------------
+// Test 3: infer inherited copy ctor
+
+struct A3_with_device_ctors {
+ __host__ A3_with_device_ctors() {}
+ __device__ A3_with_device_ctors(const A3_with_device_ctors&) {}
+};
+
+struct B3_with_implicit_ctors : A3_with_device_ctors {
+ using A3_with_device_ctors::A3_with_device_ctors;
+};
+// expected-note@-3 2{{call to __device__ function from __host__ function}}
+// expected-note@-4 {{default constructor}}
+
+
+void hostfoo3() {
+ B3_with_implicit_ctors b; // this is OK because the inferred inherited default ctor
+ // here is __host__
+ B3_with_implicit_ctors b2 = b; // expected-error {{no matching constructor}}
+
+}
+
+//------------------------------------------------------------------------------
+// Test 4: infer inherited default ctor from a field, not a base
+
+struct A4_with_host_ctor {
+ A4_with_host_ctor() {}
+};
+
+struct B4_with_inherited_host_ctor : A4_with_host_ctor{
+ using A4_with_host_ctor::A4_with_host_ctor;
+};
+
+struct C4_with_implicit_default_ctor {
+ B4_with_inherited_host_ctor field;
+};
+
+// expected-note@-4 {{call to __host__ function from __device__}}
+// expected-note@-5 {{candidate constructor (the implicit copy constructor) not viable}}
+// expected-note@-6 {{candidate constructor (the implicit move constructor) not viable}}
+
+void hostfoo4() {
+ C4_with_implicit_default_ctor b;
+}
+
+__device__ void devicefoo4() {
+ C4_with_implicit_default_ctor b; // expected-error {{no matching constructor}}
+}
+
+//------------------------------------------------------------------------------
+// Test 5: inherited copy ctor with non-const param
+
+struct A5_copy_ctor_constness {
+ __host__ A5_copy_ctor_constness() {}
+ __host__ A5_copy_ctor_constness(A5_copy_ctor_constness&) {}
+};
+
+struct B5_copy_ctor_constness : A5_copy_ctor_constness {
+ using A5_copy_ctor_constness::A5_copy_ctor_constness;
+};
+
+// expected-note@-4 {{candidate constructor (the implicit copy constructor) not viable: call to __host__ function from __device__ function}}
+// expected-note@-5 {{candidate constructor (the implicit default constructor) not viable}}
+
+void hostfoo5(B5_copy_ctor_constness& b_arg) {
+ B5_copy_ctor_constness b = b_arg;
+}
+
+__device__ void devicefoo5(B5_copy_ctor_constness& b_arg) {
+ B5_copy_ctor_constness b = b_arg; // expected-error {{no matching constructor}}
+}
+
+//------------------------------------------------------------------------------
+// Test 6: explicitly defaulted ctor
+
+struct A6_with_device_ctor {
+ __device__ A6_with_device_ctor() {}
+};
+
+struct B6_with_defaulted_ctor : A6_with_device_ctor {
+ using A6_with_device_ctor::A6_with_device_ctor;
+ __host__ B6_with_defaulted_ctor() = default;
+};
+
+// expected-note@-3 {{explicitly defaulted function was implicitly deleted here}}
+// expected-note@-6 {{default constructor of 'B6_with_defaulted_ctor' is implicitly deleted because base class 'A6_with_device_ctor' has no default constructor}}
+
+void hostfoo6() {
+ B6_with_defaulted_ctor b; // expected-error {{call to implicitly-deleted default constructor}}
+}
+
+__device__ void devicefoo6() {
+ B6_with_defaulted_ctor b;
+}
+
+//------------------------------------------------------------------------------
+// Test 7: inherited copy assignment operator
+
+struct A7_with_copy_assign {
+ A7_with_copy_assign() {}
+ __device__ A7_with_copy_assign& operator=(const A7_with_copy_assign&) {}
+};
+
+struct B7_with_copy_assign : A7_with_copy_assign {
+ using A7_with_copy_assign::A7_with_copy_assign;
+};
+
+// expected-note@-4 {{candidate function (the implicit copy assignment operator) not viable: call to __device__ function from __host__ function}}
+// expected-note@-5 {{candidate function (the implicit move assignment operator) not viable: call to __device__ function from __host__ function}}
+
+void hostfoo7() {
+ B7_with_copy_assign b1, b2;
+ b1 = b2; // expected-error {{no viable overloaded '='}}
+}
+
+//------------------------------------------------------------------------------
+// Test 8: inherited move assignment operator
+
+// definitions for std::move
+namespace std {
+inline namespace foo {
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T&> { typedef T type; };
+template <class T> struct remove_reference<T&&> { typedef T type; };
+
+template <class T> typename remove_reference<T>::type&& move(T&& t);
+}
+}
+
+struct A8_with_move_assign {
+ A8_with_move_assign() {}
+ __device__ A8_with_move_assign& operator=(A8_with_move_assign&&) {}
+ __device__ A8_with_move_assign& operator=(const A8_with_move_assign&) {}
+};
+
+struct B8_with_move_assign : A8_with_move_assign {
+ using A8_with_move_assign::A8_with_move_assign;
+};
+
+// expected-note@-4 {{candidate function (the implicit copy assignment operator) not viable: call to __device__ function from __host__ function}}
+// expected-note@-5 {{candidate function (the implicit move assignment operator) not viable: call to __device__ function from __host__ function}}
+
+void hostfoo8() {
+ B8_with_move_assign b1, b2;
+ b1 = std::move(b2); // expected-error {{no viable overloaded '='}}
+}
diff --git a/test/SemaCUDA/implicit-member-target.cu b/test/SemaCUDA/implicit-member-target.cu
index 242d345fb93e..d87e69624043 100644
--- a/test/SemaCUDA/implicit-member-target.cu
+++ b/test/SemaCUDA/implicit-member-target.cu
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -verify %s -Wno-defaulted-function-deleted
#include "Inputs/cuda.h"
diff --git a/test/SemaCUDA/inherited-ctor.cu b/test/SemaCUDA/inherited-ctor.cu
new file mode 100644
index 000000000000..8ac59e7b539f
--- /dev/null
+++ b/test/SemaCUDA/inherited-ctor.cu
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+// Inherit a valid non-default ctor.
+namespace NonDefaultCtorValid {
+ struct A {
+ A(const int &x) {}
+ };
+
+ struct B : A {
+ using A::A;
+ };
+
+ struct C {
+ struct B b;
+ C() : b(0) {}
+ };
+
+ void test() {
+ B b(0);
+ C c;
+ }
+}
+
+// Inherit an invalid non-default ctor.
+// The inherited ctor is invalid because it is unable to initialize s.
+namespace NonDefaultCtorInvalid {
+ struct S {
+ S() = delete;
+ };
+ struct A {
+ A(const int &x) {}
+ };
+
+ struct B : A {
+ using A::A;
+ S s;
+ };
+
+ struct C {
+ struct B b;
+ C() : b(0) {} // expected-error{{constructor inherited by 'B' from base class 'A' is implicitly deleted}}
+ // expected-note@-6{{constructor inherited by 'B' is implicitly deleted because field 's' has a deleted corresponding constructor}}
+ // expected-note@-15{{'S' has been explicitly marked deleted here}}
+ };
+}
+
+// Inherit a valid default ctor.
+namespace DefaultCtorValid {
+ struct A {
+ A() {}
+ };
+
+ struct B : A {
+ using A::A;
+ };
+
+ struct C {
+ struct B b;
+ C() {}
+ };
+
+ void test() {
+ B b;
+ C c;
+ }
+}
+
+// Inherit an invalid default ctor.
+// The inherited ctor is invalid because it is unable to initialize s.
+namespace DefaultCtorInvalid {
+ struct S {
+ S() = delete;
+ };
+ struct A {
+ A() {}
+ };
+
+ struct B : A {
+ using A::A;
+ S s;
+ };
+
+ struct C {
+ struct B b;
+ C() {} // expected-error{{call to implicitly-deleted default constructor of 'struct B'}}
+ // expected-note@-6{{default constructor of 'B' is implicitly deleted because field 's' has a deleted default constructor}}
+ // expected-note@-15{{'S' has been explicitly marked deleted here}}
+ };
+}
diff --git a/test/SemaCUDA/usual-deallocators.cu b/test/SemaCUDA/usual-deallocators.cu
new file mode 100644
index 000000000000..a0238649c6dc
--- /dev/null
+++ b/test/SemaCUDA/usual-deallocators.cu
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 %s --std=c++11 -triple nvptx-unknown-unknown -fcuda-is-device \
+// RUN: -emit-llvm -o /dev/null -verify=device
+// RUN: %clang_cc1 %s --std=c++11 -triple nvptx-unknown-unknown \
+// RUN: -emit-llvm -o /dev/null -verify=host
+// RUN: %clang_cc1 %s --std=c++17 -triple nvptx-unknown-unknown -fcuda-is-device \
+// RUN: -emit-llvm -o /dev/null -verify=device
+// RUN: %clang_cc1 %s --std=c++17 -triple nvptx-unknown-unknown \
+// RUN: -emit-llvm -o /dev/null -verify=host
+
+#include "Inputs/cuda.h"
+extern __host__ void host_fn();
+extern __device__ void dev_fn();
+extern __host__ __device__ void hd_fn();
+
+struct H1D1 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+};
+
+struct h1D1 {
+ __host__ void operator delete(void *) = delete;
+ // host-note@-1 {{'operator delete' has been explicitly marked deleted here}}
+ __device__ void operator delete(void *) { dev_fn(); };
+};
+
+struct H1d1 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void *) = delete;
+ // device-note@-1 {{'operator delete' has been explicitly marked deleted here}}
+};
+
+struct H1D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H2D1 {
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+};
+
+struct H2D2 {
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H1D1D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H1H2D1 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+};
+
+struct H1H2D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+struct H1H2D1D2 {
+ __host__ void operator delete(void *) { host_fn(); };
+ __host__ void operator delete(void *, __SIZE_TYPE__) { host_fn(); };
+ __device__ void operator delete(void *) { dev_fn(); };
+ __device__ void operator delete(void *, __SIZE_TYPE__) { dev_fn(); };
+};
+
+
+template <typename T>
+__host__ __device__ void test_hd(void *p) {
+ T *t = (T *)p;
+ delete t;
+ // host-error@-1 {{attempt to use a deleted function}}
+ // device-error@-2 {{attempt to use a deleted function}}
+}
+
+__host__ __device__ void tests_hd(void *t) {
+ test_hd<H1D1>(t);
+ test_hd<h1D1>(t);
+ // host-note@-1 {{in instantiation of function template specialization 'test_hd<h1D1>' requested here}}
+ test_hd<H1d1>(t);
+ // device-note@-1 {{in instantiation of function template specialization 'test_hd<H1d1>' requested here}}
+ test_hd<H1D2>(t);
+ test_hd<H2D1>(t);
+ test_hd<H2D2>(t);
+ test_hd<H1D1D2>(t);
+ test_hd<H1H2D1>(t);
+ test_hd<H1H2D1>(t);
+ test_hd<H1H2D2>(t);
+ test_hd<H1H2D1D2>(t);
+}
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp
index 203a81011142..727e67528fa0 100644
--- a/test/SemaCXX/MicrosoftCompatibility.cpp
+++ b/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -302,3 +302,23 @@ void function_to_voidptr_conv() {
void *a2 = &function_prototype; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}}
void *a3 = function_ptr; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}}
}
+
+namespace member_lookup {
+
+template<typename T>
+struct ConfuseLookup {
+ T* m_val;
+ struct m_val {
+ static size_t ms_test;
+ };
+};
+
+// Microsoft mode allows explicit constructor calls
+// This could confuse name lookup in cases such as this
+template<typename T>
+size_t ConfuseLookup<T>::m_val::ms_test
+ = size_t(&(char&)(reinterpret_cast<ConfuseLookup<T>*>(0)->m_val));
+
+void instantiate() { ConfuseLookup<int>::m_val::ms_test = 1; }
+}
+
diff --git a/test/SemaCXX/PR38913.cpp b/test/SemaCXX/PR38913.cpp
new file mode 100644
index 000000000000..698de8c84411
--- /dev/null
+++ b/test/SemaCXX/PR38913.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+
+// PR38913
+// Check that we instantiate attributes on declarations for...
+
+// ...a member class of a class template specialization
+template<class T> struct A { struct __attribute__((abi_tag("ATAG"))) X { }; };
+A<int>::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv
+
+// ...a member class template
+template<class T> struct B { template<class U> struct __attribute__((abi_tag("BTAG"))) X { }; };
+B<int>::X<int>* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv
diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp
index cca847b4d2c3..6b6734bae17d 100644
--- a/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -221,13 +221,13 @@ namespace test1 {
void QualifierTest() {
void (Qualifiers::*X)();
- X = &Qualifiers::C; // expected-error-re {{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (none vs const)}}
- X = &Qualifiers::V; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (none vs volatile)}}
- X = &Qualifiers::R; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (none vs restrict)}}
- X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (none vs const and volatile)}}
- X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (none vs const and restrict)}}
- X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (none vs volatile and restrict)}}
- X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (none vs const, volatile, and restrict)}}
+ X = &Qualifiers::C; // expected-error-re {{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (unqualified vs 'const')}}
+ X = &Qualifiers::V; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (unqualified vs 'volatile')}}
+ X = &Qualifiers::R; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (unqualified vs '__restrict')}}
+ X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (unqualified vs 'const volatile')}}
+ X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (unqualified vs 'const __restrict')}}
+ X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (unqualified vs 'volatile __restrict')}}
+ X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (unqualified vs 'const volatile __restrict')}}
}
struct Dummy {
diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp
index 0dfb61333ec2..bb03c6fb5cf1 100644
--- a/test/SemaCXX/aggregate-initialization.cpp
+++ b/test/SemaCXX/aggregate-initialization.cpp
@@ -186,3 +186,51 @@ namespace HugeArraysUseArrayFiller {
// amount of time.
struct A { int n; int arr[1000 * 1000 * 1000]; } a = {1, {2}};
}
+
+namespace ElementDestructor {
+ // The destructor for each element of class type is potentially invoked
+ // (15.4 [class.dtor]) from the context where the aggregate initialization
+ // occurs. Produce a diagnostic if an element's destructor isn't accessible.
+
+ class X { int f; ~X(); }; // expected-note {{implicitly declared private here}}
+ struct Y { X x; };
+
+ void test0() {
+ auto *y = new Y {}; // expected-error {{temporary of type 'ElementDestructor::X' has private destructor}}
+ }
+
+ struct S0 { int f; ~S0() = delete; }; // expected-note 3 {{'~S0' has been explicitly marked deleted here}}
+ struct S1 { S0 s0; int f; };
+
+ S1 test1() {
+ auto *t = new S1 { .f = 1 }; // expected-error {{attempt to use a deleted function}}
+ return {2}; // expected-error {{attempt to use a deleted function}}
+ }
+
+ // Check if the type of an array element has a destructor.
+ struct S2 { S0 a[4]; };
+
+ void test2() {
+ auto *t = new S2 {1,2,3,4}; // expected-error {{attempt to use a deleted function}}
+ }
+
+#if __cplusplus >= 201703L
+ namespace BaseDestructor {
+ struct S0 { int f; ~S0() = delete; }; // expected-note {{'~S0' has been explicitly marked deleted here}}
+
+ // Check destructor of base class.
+ struct S3 : S0 {};
+
+ void test3() {
+ S3 s3 = {1}; // expected-error {{attempt to use a deleted function}}
+ }
+ }
+#endif
+
+ // A's destructor doesn't have to be accessible from the context of C's
+ // initialization.
+ struct A { friend struct B; private: ~A(); };
+ struct B { B(); A a; };
+ struct C { B b; };
+ C c = { B() };
+}
diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp
index b6256103ef8d..0a92b9dd9639 100644
--- a/test/SemaCXX/alias-template.cpp
+++ b/test/SemaCXX/alias-template.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -std=c++11 %s
+// RUN: %clang_cc1 -verify -std=c++14 -fcxx-exceptions %s
namespace RedeclAliasTypedef {
template<typename U> using T = int;
@@ -179,3 +179,17 @@ struct S {
};
static_assert(__is_same(S<3>::U, X[2]), ""); // expected-error {{static_assert failed}}
}
+
+namespace PR39623 {
+template <class T>
+using void_t = void;
+
+template <class T, class = void_t<typename T::wait_what>>
+int sfinae_me() { return 0; } // expected-note{{candidate template ignored: substitution failure}}
+
+int g = sfinae_me<int>(); // expected-error{{no matching function for call to 'sfinae_me'}}
+}
+
+namespace NullExceptionDecl {
+template<int... I> auto get = []() { try { } catch(...) {}; return I; }; // expected-error{{initializer contains unexpanded parameter pack 'I'}}
+}
diff --git a/test/SemaCXX/align-x86-abi7.cpp b/test/SemaCXX/align-x86-abi7.cpp
new file mode 100644
index 000000000000..3088a13f7857
--- /dev/null
+++ b/test/SemaCXX/align-x86-abi7.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++11 -triple i386-apple-darwin9 -fsyntax-only -verify -fclang-abi-compat=7 %s
+// expected-no-diagnostics
+
+using size_t = decltype(sizeof(0));
+
+template <typename T, size_t Preferred>
+struct check_alignment {
+ using type = T;
+ static type value;
+
+ static_assert(__alignof__(value) == Preferred, "__alignof__(value) != Preferred");
+ static_assert(__alignof__(type) == Preferred, "__alignof__(type) != Preferred");
+ static_assert(alignof(type) == Preferred, "alignof(type) != Preferred");
+};
+
+// PR3433
+template struct check_alignment<double, 8>;
+template struct check_alignment<long long, 8>;
+template struct check_alignment<unsigned long long, 8>;
+
+// PR6362
+template struct check_alignment<double[3], 8>;
+
+enum big_enum { x = 18446744073709551615ULL };
+template struct check_alignment<big_enum, 8>;
diff --git a/test/SemaCXX/align-x86.cpp b/test/SemaCXX/align-x86.cpp
new file mode 100644
index 000000000000..0c97fc28fe5f
--- /dev/null
+++ b/test/SemaCXX/align-x86.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++11 -triple i386-apple-darwin9 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+using size_t = decltype(sizeof(0));
+
+struct complex_double {
+ double real;
+ double imag;
+};
+
+template <typename T, size_t ABI, size_t Preferred>
+struct check_alignment {
+ using type = T;
+ static type value;
+
+ static_assert(__alignof__(value) == Preferred, "__alignof__(value) != Preferred");
+ static_assert(__alignof__(type) == Preferred, "__alignof__(type) != Preferred");
+ static_assert(alignof(type) == ABI, "alignof(type) != ABI");
+};
+
+// PR3433
+template struct check_alignment<double, 4, 8>;
+template struct check_alignment<long long, 4, 8>;
+template struct check_alignment<unsigned long long, 4, 8>;
+template struct check_alignment<complex_double, 4, 4>;
+
+// PR6362
+struct __attribute__((packed))
+packed_struct {
+ unsigned int a;
+} g_packedstruct;
+template struct check_alignment<packed_struct, 1, 1>;
+static_assert(__alignof__(g_packedstruct.a) == 1, "__alignof__(packed_struct.member) != 1");
+
+template struct check_alignment<double[3], 4, 8>;
+
+enum big_enum { x = 18446744073709551615ULL };
+template struct check_alignment<big_enum, 4, 8>;
+
+// PR5637
+
+#define ALIGNED(x) __attribute__((aligned(x)))
+
+typedef ALIGNED(2) struct {
+ char a[3];
+} aligned_before_struct;
+
+static_assert(sizeof(aligned_before_struct) == 3, "");
+static_assert(sizeof(aligned_before_struct[1]) == 4, "");
+static_assert(sizeof(aligned_before_struct[2]) == 6, "");
+static_assert(sizeof(aligned_before_struct[2][1]) == 8, "");
+static_assert(sizeof(aligned_before_struct[1][2]) == 6, "");
+
+typedef struct ALIGNED(2) {
+ char a[3];
+} aligned_after_struct;
+
+static_assert(sizeof(aligned_after_struct) == 4, "");
+static_assert(sizeof(aligned_after_struct[1]) == 4, "");
+static_assert(sizeof(aligned_after_struct[2]) == 8, "");
+static_assert(sizeof(aligned_after_struct[2][1]) == 8, "");
+static_assert(sizeof(aligned_after_struct[1][2]) == 8, "");
diff --git a/test/SemaCXX/alignof.cpp b/test/SemaCXX/alignof.cpp
index e3690ea926a2..f2854024da1a 100644
--- a/test/SemaCXX/alignof.cpp
+++ b/test/SemaCXX/alignof.cpp
@@ -11,7 +11,7 @@ struct S0 {
struct S1; // expected-note 6 {{forward declaration}}
extern S1 s1;
-const int test3 = __alignof__(s1); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+const int test3 = __alignof__(s1); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
struct S2 {
S2();
@@ -19,11 +19,11 @@ struct S2 {
int x;
int test4 = __alignof__(x); // ok
- int test5 = __alignof__(s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+ int test5 = __alignof__(s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
};
const int test6 = __alignof__(S2::x);
-const int test7 = __alignof__(S2::s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+const int test7 = __alignof__(S2::s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
// Arguably, these should fail like the S1 cases do: the alignment of
// 's2.x' should depend on the alignment of both x-within-S2 and
@@ -34,10 +34,10 @@ struct S3 {
S2 s2;
static const int test8 = __alignof__(s2.x);
- static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+ static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
auto test10() -> char(&)[__alignof__(s2.x)];
static const int test11 = __alignof__(S3::s2.x);
- static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+ static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}}
auto test13() -> char(&)[__alignof__(s2.x)];
};
@@ -59,9 +59,9 @@ struct S5 {
};
const int test8 = __alignof__(S5::x);
-long long int test14[2];
+int test14[2];
-static_assert(alignof(test14) == 8, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}}
+static_assert(alignof(test14) == 4, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}}
// PR19992
static_assert(alignof(int[]) == alignof(int), ""); // ok
@@ -97,3 +97,8 @@ struct S {
typedef __attribute__((aligned(N))) int Field[sizeof(N)]; // expected-error {{requested alignment is dependent but declaration is not dependent}}
};
}
+
+typedef int __attribute__((aligned(16))) aligned_int;
+template <typename>
+using template_alias = aligned_int;
+static_assert(alignof(template_alias<void>) == 16, "Expected alignment of 16" );
diff --git a/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp
index a97f8e312a05..6ebff8c99206 100644
--- a/test/SemaCXX/array-bounds.cpp
+++ b/test/SemaCXX/array-bounds.cpp
@@ -284,3 +284,15 @@ struct multi_s multi2[4]; // expected-note {{array 'multi2' declared here}}
int test_struct_multiarray() {
return multi2[4].arr[0]; // expected-warning {{array index 4 is past the end of the array (which contains 4 elements)}}
}
+
+namespace PR39746 {
+ struct S;
+ extern S xxx[2]; // expected-note {{array 'xxx' declared here}}
+ class C {};
+
+ C &f() { return reinterpret_cast<C *>(xxx)[1]; } // no-warning
+ // We have no info on whether this is out-of-bounds.
+ C &g() { return reinterpret_cast<C *>(xxx)[2]; } // no-warning
+ // We can still diagnose this.
+ C &h() { return reinterpret_cast<C *>(xxx)[-1]; } // expected-warning {{array index -1 is before the beginning of the array}}
+}
diff --git a/test/SemaCXX/attr-cpuspecific.cpp b/test/SemaCXX/attr-cpuspecific.cpp
index a881b6c4e2ba..7ec8c6cd0ce2 100644
--- a/test/SemaCXX/attr-cpuspecific.cpp
+++ b/test/SemaCXX/attr-cpuspecific.cpp
@@ -109,3 +109,6 @@ int __attribute__((cpu_specific(sandybridge))) BadOutOfLine::foo(int) { return 1
// Ensure Cpp Spelling works.
[[clang::cpu_specific(ivybridge,atom)]] int CppSpelling(){}
+
+// expected-error@+1 {{lambda cannot be declared 'cpu_dispatch'}}
+auto x = []() __attribute__((cpu_dispatch(atom))) {};
diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
new file mode 100644
index 000000000000..24e24221939f
--- /dev/null
+++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-func-template -Wundefined-var-template -verify %s
+
+// Test that a diagnostic is emitted when an entity marked with the
+// exclude_from_explicit_instantiation attribute is not defined in
+// the current TU but it is used (and it is hence implicitly
+// instantiated).
+
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct Foo {
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function(); // expected-note{{forward declaration of template entity is here}}
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function(); // expected-note{{forward declaration of template entity is here}}
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member; // expected-note{{forward declaration of template entity is here}}
+ struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION nested {
+ static int static_member_function(); // expected-note{{forward declaration of template entity is here}}
+ };
+};
+
+extern template struct Foo<int>;
+
+void use() {
+ Foo<int> foo;
+
+ foo.non_static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::non_static_member_function' required here, but no definition is available}}
+ // expected-note@-1 {{add an explicit instantiation}}
+
+ Foo<int>::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::static_member_function' required here, but no definition is available}}
+ // expected-note@-1 {{add an explicit instantiation}}
+
+ (void)Foo<int>::static_data_member; // expected-warning{{instantiation of variable 'Foo<int>::static_data_member' required here, but no definition is available}}
+ // expected-note@-1 {{add an explicit instantiation}}
+
+ Foo<int>::nested::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::nested::static_member_function' required here, but no definition is available}}
+ // expected-note@-1 {{add an explicit instantiation}}
+}
diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp
new file mode 100644
index 000000000000..379ab0a3eb00
--- /dev/null
+++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Test that explicit instantiations do not instantiate entities
+// marked with the exclude_from_explicit_instantiation attribute.
+
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct Foo {
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member;
+
+ struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {
+ static void non_static_member_function() { using Fail = typename T::fail; }
+ };
+
+ struct member_class2 {
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void non_static_member_function() { using Fail = typename T::fail; }
+ };
+};
+
+template <class T>
+inline void Foo<T>::non_static_member_function1() { using Fail = typename T::fail; }
+
+template <class T>
+void Foo<T>::non_static_member_function2() { using Fail = typename T::fail; }
+
+template <class T>
+inline void Foo<T>::static_member_function1() { using Fail = typename T::fail; }
+
+template <class T>
+void Foo<T>::static_member_function2() { using Fail = typename T::fail; }
+
+template <class T>
+int Foo<T>::static_data_member = T::fail;
+
+// expected-no-diagnostics
+template struct Foo<int>;
diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp
new file mode 100644
index 000000000000..4cb02252ba35
--- /dev/null
+++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -Wno-unused-local-typedef -fsyntax-only -verify %s
+
+// Test that extern instantiation declarations cause members marked with
+// the exclude_from_explicit_instantiation attribute to be instantiated in
+// the current TU.
+
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct Foo {
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2();
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member;
+
+ struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {
+ static void static_member_function() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+ }
+ };
+
+ struct member_class2 {
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+ }
+ };
+};
+
+template <class T>
+inline void Foo<T>::non_static_member_function1() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template <class T>
+void Foo<T>::non_static_member_function2() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template <class T>
+inline void Foo<T>::static_member_function1() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template <class T>
+void Foo<T>::static_member_function2() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template <class T>
+int Foo<T>::static_data_member = T::invalid; // expected-error{{no member named 'invalid' in 'Empty'}}
+
+struct Empty { };
+extern template struct Foo<Empty>;
+
+int main() {
+ Foo<Empty> foo;
+ foo.non_static_member_function1(); // expected-note{{in instantiation of}}
+ foo.non_static_member_function2(); // expected-note{{in instantiation of}}
+ Foo<Empty>::static_member_function1(); // expected-note{{in instantiation of}}
+ Foo<Empty>::static_member_function2(); // expected-note{{in instantiation of}}
+ (void)foo.static_data_member; // expected-note{{in instantiation of}}
+ Foo<Empty>::member_class1::static_member_function(); // expected-note{{in instantiation of}}
+ Foo<Empty>::member_class2::static_member_function(); // expected-note{{in instantiation of}}
+}
diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp
new file mode 100644
index 000000000000..da861ab97235
--- /dev/null
+++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Test that we properly merge the exclude_from_explicit_instantiation
+// attribute on redeclarations.
+
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct Foo {
+ // Declaration without the attribute, definition with the attribute.
+ void func1();
+
+ // Declaration with the attribute, definition without the attribute.
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func2();
+
+ // Declaration with the attribute, definition with the attribute.
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func3();
+};
+
+template <class T>
+EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func1() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template <class T>
+void Foo<T>::func2() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template <class T>
+EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func3() {
+ using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+struct Empty { };
+extern template struct Foo<Empty>;
+
+int main() {
+ Foo<Empty> foo;
+ foo.func1(); // expected-note{{in instantiation of}}
+ foo.func2(); // expected-note{{in instantiation of}}
+ foo.func3(); // expected-note{{in instantiation of}}
+}
diff --git a/test/SemaCXX/attr-gnu.cpp b/test/SemaCXX/attr-gnu.cpp
index a553f0d21000..9eb42342df31 100644
--- a/test/SemaCXX/attr-gnu.cpp
+++ b/test/SemaCXX/attr-gnu.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -fms-compatibility -verify %s
-
-void f() {
- // GNU-style attributes are prohibited in this position.
+// RUN: %clang_cc1 -std=gnu++17 -fsyntax-only -fms-compatibility -verify %s
+
+void f() {
+ // GNU-style attributes are prohibited in this position.
auto P = new int * __attribute__((vector_size(8))); // expected-error {{an attribute list cannot appear here}} \
// expected-error {{invalid vector element type 'int *'}}
@@ -40,6 +40,13 @@ void tuTest1(Tu<int> u); // expected-note {{candidate function not viable: no kn
void tuTest2(Tu3 u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu3' for 1st argument}}
void tu() {
int x = 2;
- tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
- tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
-}
+ tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
+ tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
+}
+
+[[gnu::__const__]] int f2() { return 12; }
+[[__gnu__::__const__]] int f3() { return 12; }
+[[using __gnu__ : __const__]] int f4() { return 12; }
+
+static_assert(__has_cpp_attribute(gnu::__const__));
+static_assert(__has_cpp_attribute(__gnu__::__const__));
diff --git a/test/SemaCXX/attr-on-explicit-template-instantiation.cpp b/test/SemaCXX/attr-on-explicit-template-instantiation.cpp
new file mode 100644
index 000000000000..ddb9c8e2e4a5
--- /dev/null
+++ b/test/SemaCXX/attr-on-explicit-template-instantiation.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+// PR39118
+// Make sure that attributes are properly applied to explicit template
+// instantiations.
+
+#define HIDDEN __attribute__((__visibility__("hidden")))
+#define VISIBLE __attribute__((__visibility__("default")))
+
+namespace ns HIDDEN {
+ struct A { };
+ template <typename T> struct B { static A a; };
+ template <typename T> A B<T>::a;
+
+ // CHECK: @_ZN2ns1BIiE1aE = weak_odr global
+ // CHECK-NOT: hidden
+ template VISIBLE A B<int>::a;
+}
+
+struct C { };
+template <typename T> struct D { static C c; };
+template <typename T> C D<T>::c;
+
+// CHECK-DAG: @_ZN1DIiE1cB3TAGE
+template __attribute__((abi_tag("TAG"))) C D<int>::c;
diff --git a/test/SemaCXX/attr-optnone.cpp b/test/SemaCXX/attr-optnone.cpp
index 58776caf7ae6..c8e85eec3711 100644
--- a/test/SemaCXX/attr-optnone.cpp
+++ b/test/SemaCXX/attr-optnone.cpp
@@ -71,3 +71,11 @@ struct B2 {
static void bar();
};
+// Verify that we can handle the [[_Clang::optnone]] and
+// [[__clang__::optnone]] spellings, as well as [[clang::__optnone__]].
+[[_Clang::optnone]] int foo3();
+[[__clang__::optnone]] int foo4(); // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}}
+[[clang::__optnone__]] int foo5();
+[[_Clang::__optnone__]] int foo6();
+
+[[_Clang::optnone]] int foo7; // expected-warning {{'optnone' attribute only applies to functions}}
diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp
index 960050bc7106..d7ef42306bd3 100644
--- a/test/SemaCXX/attr-print.cpp
+++ b/test/SemaCXX/attr-print.cpp
@@ -13,8 +13,8 @@ void foo() __attribute__((const));
// CHECK: void bar() __attribute__((__const));
void bar() __attribute__((__const));
-// FIXME: Print this with correct format and order.
-// CHECK: void foo1() __attribute__((pure)) __attribute__((noinline));
+// FIXME: Print this with correct format.
+// CHECK: void foo1() __attribute__((noinline)) __attribute__((pure));
void foo1() __attribute__((noinline, pure));
// CHECK: typedef int Small1 __attribute__((mode(byte)));
diff --git a/test/SemaCXX/attr-reinitializes.cpp b/test/SemaCXX/attr-reinitializes.cpp
new file mode 100644
index 000000000000..129d359b8b74
--- /dev/null
+++ b/test/SemaCXX/attr-reinitializes.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+[[clang::reinitializes]] int a; // expected-error {{'reinitializes' attribute only applies to non-static non-const member functions}}
+
+[[clang::reinitializes]] void f(); // expected-error {{only applies to}}
+
+struct A {
+ [[clang::reinitializes]] void foo();
+ __attribute__((reinitializes)) void gnu_foo();
+ [[clang::reinitializes]] void bar() const; // expected-error {{only applies to}}
+ [[clang::reinitializes]] static void baz(); // expected-error {{only applies to}}
+ [[clang::reinitializes]] int a; // expected-error {{only applies to}}
+
+ [[clang::reinitializes("arg")]] void qux(); // expected-error {{'reinitializes' attribute takes no arguments}}
+};
diff --git a/test/SemaCXX/attr-speculative-load-hardening.cpp b/test/SemaCXX/attr-speculative-load-hardening.cpp
new file mode 100644
index 000000000000..bba3b6921e8d
--- /dev/null
+++ b/test/SemaCXX/attr-speculative-load-hardening.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+int i __attribute__((speculative_load_hardening)); // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
+
+void f1() __attribute__((speculative_load_hardening));
+void f2() __attribute__((speculative_load_hardening(1))); // expected-error {{'speculative_load_hardening' attribute takes no arguments}}
+
+template <typename T>
+void tf1() __attribute__((speculative_load_hardening));
+
+int f3(int __attribute__((speculative_load_hardening)), int); // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
+
+struct A {
+ int f __attribute__((speculative_load_hardening)); // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
+ void mf1() __attribute__((speculative_load_hardening));
+ static void mf2() __attribute__((speculative_load_hardening));
+};
+
+int ci [[clang::speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
+
+[[clang::speculative_load_hardening]] void cf1();
+[[clang::speculative_load_hardening(1)]] void cf2(); // expected-error {{'speculative_load_hardening' attribute takes no arguments}}
+
+template <typename T>
+[[clang::speculative_load_hardening]]
+void ctf1();
+
+int cf3(int c[[clang::speculative_load_hardening]], int); // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
+
+struct CA {
+ int f [[clang::speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}}
+ [[clang::speculative_load_hardening]] void mf1();
+ [[clang::speculative_load_hardening]] static void mf2();
+};
diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp
index f26931b55bdb..fbe2c457dad9 100644
--- a/test/SemaCXX/builtins.cpp
+++ b/test/SemaCXX/builtins.cpp
@@ -53,3 +53,95 @@ extern "C" int vfprintf(FILE *__restrict, const char *__restrict,
void synchronize_args() {
__sync_synchronize(0); // expected-error {{too many arguments}}
}
+
+namespace test_launder {
+#define TEST_TYPE(Ptr, Type) \
+ static_assert(__is_same(decltype(__builtin_launder(Ptr)), Type), "expected same type")
+
+struct Dummy {};
+
+using FnType = int(char);
+using MemFnType = int (Dummy::*)(char);
+using ConstMemFnType = int (Dummy::*)() const;
+
+void foo() {}
+
+void test_builtin_launder_diags(void *vp, const void *cvp, FnType *fnp,
+ MemFnType mfp, ConstMemFnType cmfp, int (&Arr)[5]) {
+ __builtin_launder(vp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(cvp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(fnp); // expected-error {{function pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(mfp); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(cmfp); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ (void)__builtin_launder(&fnp);
+ __builtin_launder(42); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(nullptr); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(foo); // expected-error {{function pointer argument to '__builtin_launder' is not allowed}}
+ (void)__builtin_launder(Arr);
+}
+
+void test_builtin_launder(char *p, const volatile int *ip, const float *&fp,
+ double *__restrict dp) {
+ int x;
+ __builtin_launder(x); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+
+ TEST_TYPE(p, char*);
+ TEST_TYPE(ip, const volatile int*);
+ TEST_TYPE(fp, const float*);
+ TEST_TYPE(dp, double *__restrict);
+
+ char *d = __builtin_launder(p);
+ const volatile int *id = __builtin_launder(ip);
+ int *id2 = __builtin_launder(ip); // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const volatile int *'}}
+ const float* fd = __builtin_launder(fp);
+}
+
+void test_launder_return_type(const int (&ArrayRef)[101], int (&MArrRef)[42][13],
+ void (**&FuncPtrRef)()) {
+ TEST_TYPE(ArrayRef, const int *);
+ TEST_TYPE(MArrRef, int(*)[13]);
+ TEST_TYPE(FuncPtrRef, void (**)());
+}
+
+template <class Tp>
+constexpr Tp *test_constexpr_launder(Tp *tp) {
+ return __builtin_launder(tp);
+}
+constexpr int const_int = 42;
+constexpr int const_int2 = 101;
+constexpr const int *const_ptr = test_constexpr_launder(&const_int);
+static_assert(&const_int == const_ptr, "");
+static_assert(const_ptr != test_constexpr_launder(&const_int2), "");
+
+void test_non_constexpr() {
+ constexpr int i = 42; // expected-note {{declared here}}
+ constexpr const int *ip = __builtin_launder(&i); // expected-error {{constexpr variable 'ip' must be initialized by a constant expression}}
+ // expected-note@-1 {{pointer to 'i' is not a constant expression}}
+}
+
+constexpr bool test_in_constexpr(const int &i) {
+ return (__builtin_launder(&i) == &i);
+}
+
+static_assert(test_in_constexpr(const_int), "");
+void f() {
+ constexpr int i = 42;
+ static_assert(test_in_constexpr(i), "");
+}
+
+struct Incomplete; // expected-note {{forward declaration}}
+struct IncompleteMember {
+ Incomplete &i;
+};
+void test_incomplete(Incomplete *i, IncompleteMember *im) {
+ // expected-error@+1 {{incomplete type 'test_launder::Incomplete' where a complete type is required}}
+ __builtin_launder(i);
+ __builtin_launder(&i); // OK
+ __builtin_launder(im); // OK
+}
+
+void test_noexcept(int *i) {
+ static_assert(noexcept(__builtin_launder(i)), "");
+}
+#undef TEST_TYPE
+} // end namespace test_launder
diff --git a/test/SemaCXX/calling-conv-compat.cpp b/test/SemaCXX/calling-conv-compat.cpp
index 4c4cc15f165a..a268d9da07ee 100644
--- a/test/SemaCXX/calling-conv-compat.cpp
+++ b/test/SemaCXX/calling-conv-compat.cpp
@@ -1,4 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify -triple i686-pc-win32 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify -triple x86_64-pc-win32 %s
+
+// FIXME: Extend this portion of the test to cover the 64-bit case.
+#if !_M_X64
// Pointers to free functions
void free_func_default();
@@ -244,11 +248,16 @@ void call_member_inheritance() {
}
} // end namespace NonVariadic
+#endif // !_M_X64
+
namespace Variadic {
struct A {
void member_default(int, ...);
void __cdecl member_cdecl(int, ...);
- void __thiscall member_thiscall(int, ...); // expected-error {{variadic function cannot use thiscall calling convention}}
+ void __thiscall member_thiscall(int, ...);
+#if !_M_X64
+ // expected-error@-2 {{variadic function cannot use thiscall calling convention}}
+#endif
};
struct B : public A {
@@ -319,7 +328,10 @@ mptr_t __stdcall return_mptr_std(short) {
}
void (A::*(*return_fptr_std_mptr(char))(short))(int) {
- return return_mptr_std; // expected-error {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}}
+ return return_mptr_std;
+#if !_M_X64
+ // expected-error@-2 {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}}
+#endif
}
void call_return() {
@@ -387,15 +399,32 @@ Y<decltype(&A::method_thiscall)>::p tmpl9 = &f_cdecl;
// Test that lambdas that capture nothing convert to cdecl function pointers.
namespace Lambdas {
-
void pass_fptr_cdecl (void (__cdecl *fp)());
-void pass_fptr_stdcall (void (__stdcall *fp)()); // expected-note {{candidate function not viable}}
-void pass_fptr_fastcall(void (__fastcall *fp)()); // expected-note {{candidate function not viable}}
+void pass_fptr_stdcall (void (__stdcall *fp)());
+void pass_fptr_fastcall(void (__fastcall *fp)());
void conversion_to_fptr() {
pass_fptr_cdecl ([]() { } );
- pass_fptr_stdcall ([]() { } ); // expected-error {{no matching function for call}}
- pass_fptr_fastcall([]() { } ); // expected-error {{no matching function for call}}
+
+ pass_fptr_stdcall ([]() { } );
+#if !_M_X64
+ // expected-error@-2 {{no matching function for call}}
+ // expected-note@-9 {{candidate function not viable}}
+#endif
+
+ pass_fptr_fastcall([]() { } );
+#if !_M_X64
+ // expected-error@-2 {{no matching function for call}}
+ // expected-note@-14 {{candidate function not viable}}
+#endif
+}
}
+namespace D50526 {
+ template<typename T, T (__stdcall f)()> void g();
+ void h() { g<void, h>(); }
+#if !_M_X64
+ // expected-error@-2 {{no matching function for call to}}
+ // expected-note@-4 {{invalid explicitly-specified argument}}
+#endif
}
diff --git a/test/SemaCXX/char8_t.cpp b/test/SemaCXX/char8_t.cpp
index 5eb3d7062d2c..f60a66dbe84d 100644
--- a/test/SemaCXX/char8_t.cpp
+++ b/test/SemaCXX/char8_t.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fchar8_t -std=c++2a -verify %s
+// RUN: %clang_cc1 -fchar8_t -std=c++17 -verify %s
+// RUN: %clang_cc1 -std=c++2a -verify %s
char8_t a = u8'a';
char8_t b[] = u8"foo";
@@ -6,7 +7,12 @@ char8_t c = 'a';
char8_t d[] = "foo"; // expected-error {{initializing 'char8_t' array with plain string literal}} expected-note {{add 'u8' prefix}}
char e = u8'a';
-char f[] = u8"foo"; // expected-error {{initialization of char array with UTF-8 string literal is not permitted by '-fchar8_t'}}
+char f[] = u8"foo";
+#if __cplusplus <= 201703L
+// expected-error@-2 {{initialization of char array with UTF-8 string literal is not permitted by '-fchar8_t'}}
+#else
+// expected-error@-4 {{ISO C++20 does not permit initialization of char array with UTF-8 string literal}}
+#endif
char g = 'a';
char h[] = "foo";
diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp
index be9ebee00c2f..353be2cf48e4 100644
--- a/test/SemaCXX/compound-literal.cpp
+++ b/test/SemaCXX/compound-literal.cpp
@@ -34,9 +34,19 @@ namespace brace_initializers {
~HasCtorDtor();
};
+ POD p = (POD){1, 2};
+ // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'
+ // CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NEXT: ConstantExpr {{.*}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: ConstantExpr {{.*}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
void test() {
(void)(POD){1, 2};
// CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NOT: ConstantExpr {{.*}} 'brace_initializers::POD'
// CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
// CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'
// CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
@@ -52,6 +62,7 @@ namespace brace_initializers {
#if __cplusplus >= 201103L
(void)(HasCtor){1, 2};
// CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtor'
+ // CHECK-CXX11-NOT: ConstantExpr {{.*}} 'brace_initializers::HasCtor'
// CHECK-CXX11: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtor'
// CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtor'
// CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
@@ -59,7 +70,8 @@ namespace brace_initializers {
(void)(HasCtorDtor){1, 2};
// CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtorDtor'
- // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NOT: ConstantExpr {{.*}} 'brace_initializers::HasCtorDtor'
+ // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtorDtor'
// CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtorDtor'
// CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
// CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index a64207583dd5..578a057104a3 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -253,7 +253,7 @@ namespace FunctionPointers {
static_assert(1 + Apply(Select(4), 5) + Apply(Select(3), 7) == 42, "");
- constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Apply(0, 0)'}}
+ constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Apply(nullptr, 0)'}}
}
@@ -1972,9 +1972,9 @@ namespace ZeroSizeTypes {
namespace BadDefaultInit {
template<int N> struct X { static const int n = N; };
- struct A {
+ struct A { // expected-error {{default member initializer for 'k' needed within definition of enclosing class}}
int k = // expected-note {{default member initializer declared here}}
- X<A().k>::n; // expected-error {{default member initializer for 'k' needed within definition of enclosing class}}
+ X<A().k>::n; // expected-note {{in evaluation of exception specification for 'BadDefaultInit::A::A' needed here}}
};
// FIXME: The "constexpr constructor must initialize all members" diagnostic
diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp
index 00df2e5c77a4..3c57ac573f2c 100644
--- a/test/SemaCXX/constant-expression-cxx1y.cpp
+++ b/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -356,6 +356,14 @@ namespace compound_assign {
if (a != 13) return false;
a &= 14;
if (a != 12) return false;
+ a += -1.2;
+ if (a != 10) return false;
+ a -= 3.1;
+ if (a != 6) return false;
+ a *= 2.2;
+ if (a != 13) return false;
+ if (&(a /= 1.5) != &a) return false;
+ if (a != 8) return false;
return true;
}
static_assert(test_int(), "");
@@ -374,6 +382,30 @@ namespace compound_assign {
}
static_assert(test_float(), "");
+ constexpr bool test_bool() {
+ bool b = false;
+ b |= 2;
+ if (b != true) return false;
+ b <<= 1;
+ if (b != true) return false;
+ b *= 2;
+ if (b != true) return false;
+ b -= 1;
+ if (b != false) return false;
+ b -= 1;
+ if (b != true) return false;
+ b += -1;
+ if (b != false) return false;
+ b += 1;
+ if (b != true) return false;
+ b += 1;
+ if (b != true) return false;
+ b ^= b;
+ if (b != false) return false;
+ return true;
+ }
+ static_assert(test_bool(), "");
+
constexpr bool test_ptr() {
int arr[123] = {};
int *p = arr;
@@ -420,7 +452,7 @@ namespace compound_assign {
static_assert(test_bounds("foo", 0)[0] == 'f', "");
static_assert(test_bounds("foo", 3)[0] == 0, "");
static_assert(test_bounds("foo", 4)[-3] == 'o', "");
- static_assert(test_bounds("foo" + 4, -4)[0] == 'f', "");
+ static_assert(test_bounds(&"foo"[4], -4)[0] == 'f', "");
static_assert(test_bounds("foo", 5) != 0, ""); // expected-error {{constant}} expected-note {{call}}
static_assert(test_bounds("foo", -1) != 0, ""); // expected-error {{constant}} expected-note {{call}}
static_assert(test_bounds("foo", 1000) != 0, ""); // expected-error {{constant}} expected-note {{call}}
@@ -879,7 +911,7 @@ namespace Bitfields {
--a.n;
--a.u;
a.n = -a.n * 3;
- return a.b == false && a.n == 3 && a.u == 31;
+ return a.b == true && a.n == 3 && a.u == 31;
}
static_assert(test(), "");
}
@@ -1098,3 +1130,8 @@ constexpr E e2 = E{0};
static_assert(e2.x != e2.y, "");
} // namespace IndirectFields
+
+constexpr bool indirect_builtin_constant_p(const char *__s) {
+ return __builtin_constant_p(*__s);
+}
+constexpr bool n = indirect_builtin_constant_p("a");
diff --git a/test/SemaCXX/constant-expression-cxx2a.cpp b/test/SemaCXX/constant-expression-cxx2a.cpp
index 18c4a726fd00..bb2a4a07dd8f 100644
--- a/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -204,3 +204,10 @@ static_assert(complex_test(makeComplex<_Complex int>(0, 0),
std::strong_equality::nonequal));
// TODO: defaulted operator <=>
} // namespace ThreeWayComparison
+
+constexpr bool for_range_init() {
+ int k = 0;
+ for (int arr[3] = {1, 2, 3}; int n : arr) k += n;
+ return k == 6;
+}
+static_assert(for_range_init());
diff --git a/test/SemaCXX/constexpr-string.cpp b/test/SemaCXX/constexpr-string.cpp
index 1145a2081cba..c348c0ff747d 100644
--- a/test/SemaCXX/constexpr-string.cpp
+++ b/test/SemaCXX/constexpr-string.cpp
@@ -1,8 +1,11 @@
-// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++1z -fsyntax-only -verify -pedantic
-// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++1z -fsyntax-only -verify -pedantic -fno-signed-char
-// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++1z -fsyntax-only -verify -pedantic -fno-wchar -Dwchar_t=__WCHAR_TYPE__
-
-# 6 "/usr/include/string.h" 1 3 4
+// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension
+// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-signed-char
+// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-wchar -DNO_PREDEFINED_WCHAR_T
+// RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension
+// RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-signed-char
+// RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-wchar -DNO_PREDEFINED_WCHAR_T
+
+# 9 "/usr/include/string.h" 1 3 4
extern "C" {
typedef decltype(sizeof(int)) size_t;
@@ -18,10 +21,13 @@ extern "C" {
extern void *memcpy(void *d, const void *s, size_t n);
extern void *memmove(void *d, const void *s, size_t n);
}
-# 22 "SemaCXX/constexpr-string.cpp" 2
+# 25 "SemaCXX/constexpr-string.cpp" 2
-# 24 "/usr/include/wchar.h" 1 3 4
+# 27 "/usr/include/wchar.h" 1 3 4
extern "C" {
+#if NO_PREDEFINED_WCHAR_T
+ typedef decltype(L'0') wchar_t;
+#endif
extern size_t wcslen(const wchar_t *p);
extern int wcscmp(const wchar_t *s1, const wchar_t *s2);
@@ -35,7 +41,7 @@ extern "C" {
extern wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n);
}
-# 39 "SemaCXX/constexpr-string.cpp" 2
+# 45 "SemaCXX/constexpr-string.cpp" 2
namespace Strlen {
constexpr int n = __builtin_strlen("hello"); // ok
static_assert(n == 5);
@@ -95,11 +101,142 @@ namespace StrcmpEtc {
static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 6) == -1);
static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 5) == 0);
+ extern struct Incomplete incomplete;
+ static_assert(__builtin_memcmp(&incomplete, "", 0u) == 0);
+ static_assert(__builtin_memcmp("", &incomplete, 0u) == 0);
+ static_assert(__builtin_memcmp(&incomplete, "", 1u) == 42); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}}
+ static_assert(__builtin_memcmp("", &incomplete, 1u) == 42); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}}
+
+ constexpr unsigned char ku00fe00[] = {0x00, 0xfe, 0x00};
+ constexpr unsigned char ku00feff[] = {0x00, 0xfe, 0xff};
+ constexpr signed char ks00fe00[] = {0, -2, 0};
+ constexpr signed char ks00feff[] = {0, -2, -1};
+ static_assert(__builtin_memcmp(ku00feff, ks00fe00, 2) == 0);
+ static_assert(__builtin_memcmp(ku00feff, ks00fe00, 99) == 1);
+ static_assert(__builtin_memcmp(ku00fe00, ks00feff, 99) == -1);
+ static_assert(__builtin_memcmp(ks00feff, ku00fe00, 2) == 0);
+ static_assert(__builtin_memcmp(ks00feff, ku00fe00, 99) == 1);
+ static_assert(__builtin_memcmp(ks00fe00, ku00feff, 99) == -1);
+ static_assert(__builtin_memcmp(ks00fe00, ks00feff, 2) == 0);
+ static_assert(__builtin_memcmp(ks00feff, ks00fe00, 99) == 1);
+ static_assert(__builtin_memcmp(ks00fe00, ks00feff, 99) == -1);
+
+ struct Bool3Tuple { bool bb[3]; };
+ constexpr Bool3Tuple kb000100 = {{false, true, false}};
+ static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, kb000100.bb, 1) == 0);
+ static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, kb000100.bb, 2) == 1);
+
+ constexpr long ksl[] = {0, -1};
+ constexpr unsigned int kui[] = {0, 0u - 1};
+ constexpr unsigned long long kull[] = {0, 0ull - 1};
+ constexpr const auto *kuSizeofLong(void) {
+ if constexpr(sizeof(long) == sizeof(int)) {
+ return kui;
+ } else if constexpr(sizeof(long) == sizeof(long long)) {
+ return kull;
+ } else {
+ return nullptr;
+ }
+ }
+ static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) - 1) == 0);
+ static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + 0) == 0);
+ static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + 1) == 0);
+ static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) - 1) == 0);
+ static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 0) == 0);
+ static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 1) == 42); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) - 1) == 0);
+ static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 0) == 0);
+ static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 1) == 42); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+
constexpr int a = strcmp("hello", "world"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strcmp' cannot be used in a constant expression}}
constexpr int b = strncmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strncmp' cannot be used in a constant expression}}
constexpr int c = memcmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memcmp' cannot be used in a constant expression}}
}
+namespace MultibyteElementTests {
+inline namespace Util {
+#define STR2(X) #X
+#define STR(X) STR2(X)
+constexpr const char ByteOrderString[] = STR(__BYTE_ORDER__);
+#undef STR
+#undef STR2
+constexpr bool LittleEndian{*ByteOrderString == '1'};
+
+constexpr size_t GoodFoldArraySize = 42, BadFoldArraySize = 43;
+struct NotBadFoldResult {};
+template <size_t> struct FoldResult;
+template <> struct FoldResult<GoodFoldArraySize> : NotBadFoldResult {};
+template <typename T, size_t N>
+FoldResult<N> *foldResultImpl(T (*ptrToConstantSizeArray)[N]);
+struct NotFolded : NotBadFoldResult {};
+NotFolded *foldResultImpl(bool anyPtr);
+template <auto Value> struct MetaValue;
+template <typename Callable, size_t N, auto ExpectedFoldResult>
+auto foldResult(const Callable &, MetaValue<N> *,
+ MetaValue<ExpectedFoldResult> *) {
+ int (*maybeVLAPtr)[Callable{}(N) == ExpectedFoldResult
+ ? GoodFoldArraySize
+ : BadFoldArraySize] = 0;
+ return foldResultImpl(maybeVLAPtr);
+}
+template <typename FoldResultKind, typename Callable, typename NWrap,
+ typename ExpectedWrap>
+constexpr bool checkFoldResult(const Callable &c, NWrap *n, ExpectedWrap *e) {
+ decltype(static_cast<FoldResultKind *>(foldResult(c, n, e))) *chk{};
+ return true;
+}
+template <size_t N> constexpr MetaValue<N> *withN() { return nullptr; }
+template <auto Expected> constexpr MetaValue<Expected> *withExpected() {
+ return nullptr;
+}
+} // namespace Util
+} // namespace MultibyteElementTests
+
+namespace MultibyteElementTests::Memcmp {
+#ifdef __SIZEOF_INT128__
+constexpr __int128 i128_ff_8_00_8 = -(__int128)1 - -1ull;
+constexpr __int128 i128_00_16 = 0;
+static_assert(checkFoldResult<NotBadFoldResult>(
+ [](size_t n) constexpr {
+ return __builtin_memcmp(&i128_ff_8_00_8, &i128_00_16, n);
+ },
+ withN<1u>(), withExpected<LittleEndian ? 0 : 1>()));
+#endif
+
+constexpr const signed char ByteOrderStringReduced[] = {
+ ByteOrderString[0] - '0', ByteOrderString[1] - '0',
+ ByteOrderString[2] - '0', ByteOrderString[3] - '0',
+};
+constexpr signed int i04030201 = 0x04030201;
+constexpr unsigned int u04030201 = 0x04030201u;
+static_assert(checkFoldResult<NotBadFoldResult>(
+ [](size_t n) constexpr {
+ return __builtin_memcmp(ByteOrderStringReduced, &i04030201, n);
+ },
+ withN<sizeof(int)>(), withExpected<0>()));
+static_assert(checkFoldResult<NotBadFoldResult>(
+ [](size_t n) constexpr {
+ return __builtin_memcmp(&u04030201, ByteOrderStringReduced, n);
+ },
+ withN<sizeof(int)>(), withExpected<0>()));
+
+constexpr unsigned int ui0000FEFF = 0x0000feffU;
+constexpr unsigned short usFEFF = 0xfeffU;
+static_assert(checkFoldResult<NotBadFoldResult>(
+ [](size_t n) constexpr {
+ return __builtin_memcmp(&ui0000FEFF, &usFEFF, n);
+ },
+ withN<1u>(), withExpected<LittleEndian ? 0 : -1>()));
+
+constexpr unsigned int ui08038700 = 0x08038700u;
+constexpr unsigned int ui08048600 = 0x08048600u;
+static_assert(checkFoldResult<NotBadFoldResult>(
+ [](size_t n) constexpr {
+ return __builtin_memcmp(&ui08038700, &ui08048600, n);
+ },
+ withN<sizeof(int)>(), withExpected<LittleEndian ? 1 : -1>()));
+}
+
namespace WcscmpEtc {
constexpr wchar_t kFoobar[6] = {L'f',L'o',L'o',L'b',L'a',L'r'};
constexpr wchar_t kFoobazfoobar[12] = {L'f',L'o',L'o',L'b',L'a',L'z',L'f',L'o',L'o',L'b',L'a',L'r'};
@@ -187,6 +324,27 @@ namespace StrchrEtc {
static_assert(__builtin_memchr(nullptr, 'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
static_assert(__builtin_memchr(nullptr, 'x', 0) == nullptr); // FIXME: Should we reject this?
+ extern struct Incomplete incomplete;
+ static_assert(__builtin_memchr(&incomplete, 0, 0u) == nullptr);
+ static_assert(__builtin_memchr(&incomplete, 0, 1u) == nullptr); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}}
+
+ const unsigned char &u1 = 0xf0;
+ auto &&i1 = (const signed char []){-128}; // expected-warning {{compound literals are a C99-specific feature}}
+ static_assert(__builtin_memchr(&u1, -(0x0f + 1), 1) == &u1);
+ static_assert(__builtin_memchr(i1, 0x80, 1) == i1);
+
+ enum class E : unsigned char {};
+ struct EPair { E e, f; };
+ constexpr EPair ee{E{240}};
+ static_assert(__builtin_memchr(&ee.e, 240, 1) == &ee.e);
+
+ constexpr bool kBool[] = {false, true, false};
+ constexpr const bool *const kBoolPastTheEndPtr = kBool + 3;
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, 1, 99) == kBool + 1);
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBool + 1, 0, 99) == kBoolPastTheEndPtr - 1);
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, -1, 3) == nullptr);
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr, 0, 1) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+
static_assert(__builtin_char_memchr(kStr, 'a', 0) == nullptr);
static_assert(__builtin_char_memchr(kStr, 'a', 1) == kStr);
static_assert(__builtin_char_memchr(kStr, '\0', 5) == nullptr);
@@ -212,6 +370,22 @@ namespace StrchrEtc {
constexpr bool b = !memchr("hello", 'h', 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memchr' cannot be used in a constant expression}}
}
+namespace MultibyteElementTests::Memchr {
+constexpr unsigned int u04030201 = 0x04030201;
+static_assert(checkFoldResult<NotBadFoldResult>(
+ [](size_t n) constexpr {
+ return __builtin_memchr(&u04030201, *ByteOrderString - '0', n);
+ },
+ withN<1u>(), withExpected<&u04030201>()));
+
+constexpr unsigned int uED = 0xEDU;
+static_assert(checkFoldResult<NotBadFoldResult>(
+ [](size_t n) constexpr {
+ return __builtin_memchr(&uED, 0xED, n);
+ },
+ withN<1u>(), withExpected<LittleEndian ? &uED : nullptr>()));
+}
+
namespace WcschrEtc {
constexpr const wchar_t *kStr = L"abca\xffff\0dL";
constexpr wchar_t kFoo[] = {L'f', L'o', L'o'};
@@ -269,15 +443,15 @@ namespace MemcpyEtc {
wchar_t arr[4] = {1, 2, 3, 4};
__builtin_wmemcpy(arr + a, arr + b, n);
// expected-note@-1 2{{overlapping memory regions}}
- // expected-note-re@-2 {{source is not a contiguous array of at least 2 elements of type '{{wchar_t|int}}'}}
- // expected-note-re@-3 {{destination is not a contiguous array of at least 3 elements of type '{{wchar_t|int}}'}}
+ // expected-note@-2 {{source is not a contiguous array of at least 2 elements of type 'wchar_t'}}
+ // expected-note@-3 {{destination is not a contiguous array of at least 3 elements of type 'wchar_t'}}
return result(arr);
}
constexpr int test_wmemmove(int a, int b, int n) {
wchar_t arr[4] = {1, 2, 3, 4};
__builtin_wmemmove(arr + a, arr + b, n);
- // expected-note-re@-1 {{source is not a contiguous array of at least 2 elements of type '{{wchar_t|int}}'}}
- // expected-note-re@-2 {{destination is not a contiguous array of at least 3 elements of type '{{wchar_t|int}}'}}
+ // expected-note@-1 {{source is not a contiguous array of at least 2 elements of type 'wchar_t'}}
+ // expected-note@-2 {{destination is not a contiguous array of at least 3 elements of type 'wchar_t'}}
return result(arr);
}
@@ -317,6 +491,23 @@ namespace MemcpyEtc {
static_assert(test_wmemmove(0, 3, 2) == 4234); // expected-error {{constant}} expected-note {{in call}}
static_assert(test_wmemmove(2, 0, 3) == 4234); // expected-error {{constant}} expected-note {{in call}}
+#define fold(x) (__builtin_constant_p(0) ? (x) : (x))
+
+ wchar_t global;
+ constexpr wchar_t *null = 0;
+ static_assert(__builtin_memcpy(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memcpy' is nullptr}}
+ static_assert(__builtin_memmove(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memmove' is nullptr}}
+ static_assert(__builtin_wmemcpy(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'wmemcpy' is nullptr}}
+ static_assert(__builtin_wmemmove(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'wmemmove' is nullptr}}
+ static_assert(__builtin_memcpy(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'memcpy' is nullptr}}
+ static_assert(__builtin_memmove(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'memmove' is nullptr}}
+ static_assert(__builtin_wmemcpy(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'wmemcpy' is nullptr}}
+ static_assert(__builtin_wmemmove(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'wmemmove' is nullptr}}
+ static_assert(__builtin_memcpy(&global, fold((wchar_t*)123), sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memcpy' is (void *)123}}
+ static_assert(__builtin_memcpy(fold(reinterpret_cast<wchar_t*>(123)), &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'memcpy' is (void *)123}}
+ constexpr struct Incomplete *null_incomplete = 0;
+ static_assert(__builtin_memcpy(null_incomplete, null_incomplete, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memcpy' is nullptr}}
+
// Copying is permitted for any trivially-copyable type.
struct Trivial { char k; short s; constexpr bool ok() { return k == 3 && s == 4; } };
constexpr bool test_trivial() {
@@ -370,4 +561,41 @@ namespace MemcpyEtc {
// designators until we have a long enough matching size, if both designators
// point to the start of their respective final elements.
static_assert(test_derived_to_base(2) == 3434); // expected-error {{constant}} expected-note {{in call}}
+
+ // Check that when address-of an array is passed to a tested function the
+ // array can be fully copied.
+ constexpr int test_address_of_const_array_type() {
+ int arr[4] = {1, 2, 3, 4};
+ __builtin_memmove(&arr, &arr, sizeof(arr));
+ return arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3];
+ }
+ static_assert(test_address_of_const_array_type() == 1234);
+
+ // Check that an incomplete array is rejected.
+ constexpr int test_incomplete_array_type() { // expected-error {{never produces a constant}}
+ extern int arr[];
+ __builtin_memmove(arr, arr, 4 * sizeof(arr[0]));
+ // expected-note@-1 2{{'memmove' not supported: source is not a contiguous array of at least 4 elements of type 'int'}}
+ return arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3];
+ }
+ static_assert(test_incomplete_array_type() == 1234); // expected-error {{constant}} expected-note {{in call}}
+
+ // Check that a pointer to an incomplete array is rejected.
+ constexpr int test_address_of_incomplete_array_type() { // expected-error {{never produces a constant}}
+ extern int arr[];
+ __builtin_memmove(&arr, &arr, 4 * sizeof(arr[0]));
+ // expected-note@-1 2{{cannot constant evaluate 'memmove' between objects of incomplete type 'int []'}}
+ return arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3];
+ }
+ static_assert(test_address_of_incomplete_array_type() == 1234); // expected-error {{constant}} expected-note {{in call}}
+
+ // Check that a pointer to an incomplete struct is rejected.
+ constexpr bool test_address_of_incomplete_struct_type() { // expected-error {{never produces a constant}}
+ struct Incomplete;
+ extern Incomplete x, y;
+ __builtin_memcpy(&x, &x, 4);
+ // expected-note@-1 2{{cannot constant evaluate 'memcpy' between objects of incomplete type 'Incomplete'}}
+ return true;
+ }
+ static_assert(test_address_of_incomplete_struct_type()); // expected-error {{constant}} expected-note {{in call}}
}
diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp
index 105605c6e37b..33ea49663491 100644
--- a/test/SemaCXX/constructor.cpp
+++ b/test/SemaCXX/constructor.cpp
@@ -86,3 +86,14 @@ A::S::operator int() { return 1; }
A::S::~S() {}
+namespace PR38286 {
+ // FIXME: It'd be nice to give more consistent diagnostics for these cases
+ // (but they're all failing for somewhat different reasons...).
+ template<typename> struct A;
+ template<typename T> A<T>::A() {} // expected-error {{incomplete type 'A' named in nested name specifier}}
+ /*FIXME: needed to recover properly from previous error*/;
+ template<typename> struct B;
+ template<typename T> void B<T>::f() {} // expected-error {{out-of-line definition of 'f' from class 'B<type-parameter-0-0>'}}
+ template<typename> struct C;
+ template<typename T> C<T>::~C() {} // expected-error {{no type named 'C' in 'C<type-parameter-0-0>'}}
+}
diff --git a/test/SemaCXX/coreturn-eh.cpp b/test/SemaCXX/coreturn-eh.cpp
new file mode 100644
index 000000000000..79065736c0a4
--- /dev/null
+++ b/test/SemaCXX/coreturn-eh.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fcxx-exceptions -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wall -Wextra -Wno-error=unreachable-code
+// expected-no-diagnostics
+
+#include "Inputs/std-coroutine.h"
+
+using std::experimental::suspend_always;
+using std::experimental::suspend_never;
+
+struct awaitable {
+ bool await_ready();
+ void await_suspend(std::experimental::coroutine_handle<>); // FIXME: coroutine_handle
+ void await_resume();
+} a;
+
+struct object { ~object() {} };
+
+struct promise_void_return_value {
+ void get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void unhandled_exception();
+ void return_value(object);
+};
+
+struct VoidTagReturnValue {
+ struct promise_type {
+ VoidTagReturnValue get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void unhandled_exception();
+ void return_value(object);
+ };
+};
+
+template <typename T1>
+struct std::experimental::coroutine_traits<void, T1> { using promise_type = promise_void_return_value; };
+
+VoidTagReturnValue test() {
+ object x = {};
+ try {
+ co_return {};
+ } catch (...) {
+ throw;
+ }
+}
diff --git a/test/SemaCXX/coroutine-rvo.cpp b/test/SemaCXX/coroutine-rvo.cpp
new file mode 100644
index 000000000000..8521b8506fd0
--- /dev/null
+++ b/test/SemaCXX/coroutine-rvo.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only
+
+namespace std::experimental {
+template <class Promise = void> struct coroutine_handle {
+ coroutine_handle() = default;
+ static coroutine_handle from_address(void *) noexcept;
+};
+
+template <> struct coroutine_handle<void> {
+ static coroutine_handle from_address(void *) noexcept;
+ coroutine_handle() = default;
+ template <class PromiseType>
+ coroutine_handle(coroutine_handle<PromiseType>) noexcept;
+};
+
+template <class... Args>
+struct void_t_imp {
+ using type = void;
+};
+template <class... Args>
+using void_t = typename void_t_imp<Args...>::type;
+
+template <class T, class = void>
+struct traits_sfinae_base {};
+
+template <class T>
+struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
+ using promise_type = typename T::promise_type;
+};
+
+template <class Ret, class... Args>
+struct coroutine_traits : public traits_sfinae_base<Ret> {};
+}
+
+struct suspend_never {
+ bool await_ready() noexcept;
+ void await_suspend(std::experimental::coroutine_handle<>) noexcept;
+ void await_resume() noexcept;
+};
+
+struct MoveOnly {
+ MoveOnly() {};
+ MoveOnly(const MoveOnly&) = delete;
+ MoveOnly(MoveOnly&&) noexcept {};
+ ~MoveOnly() {};
+};
+
+template <typename T>
+struct task {
+ struct promise_type {
+ auto initial_suspend() { return suspend_never{}; }
+ auto final_suspend() { return suspend_never{}; }
+ auto get_return_object() { return task{}; }
+ static void unhandled_exception() {}
+ void return_value(T&& value) {}
+ };
+};
+
+task<MoveOnly> f() {
+ MoveOnly value;
+ co_return value;
+}
+
+int main() {
+ f();
+ return 0;
+}
+
+// expected-no-diagnostics
diff --git a/test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp b/test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp
new file mode 100644
index 000000000000..7237fbf9db7f
--- /dev/null
+++ b/test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++03 -triple x86_64-pc-linux-gnu %s \
+// RUN: -faligned-allocation -emit-llvm -o - -Wno-c++11-extensions | FileCheck %s
+
+// Ensure Clang doesn't confuse std::align_val_t with the sized deallocation
+// parameter when the enum type is unscoped. Libc++ does this in C++03 in order
+// to support aligned allocation in that dialect.
+
+using size_t = __decltype(sizeof(0));
+
+namespace std {
+enum align_val_t : size_t {};
+}
+_Static_assert(__is_same(__underlying_type(std::align_val_t), size_t), "");
+
+// CHECK-LABEL: define void @_Z1fPi(
+void f(int *p) {
+ // CHECK-NOT: call void @_ZdlPvSt11align_val_t(
+ // CHECK: call void @_ZdlPv(
+ // CHECK: ret void
+ delete p;
+}
diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp
index f623dc765f88..6346e1c23538 100644
--- a/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -99,8 +99,6 @@ namespace DefaultedFnExceptionSpec {
Error<char> c; // expected-note 2{{instantiation of}}
struct DelayImplicit {
- // FIXME: The location of this note is terrible. The instantiation was
- // triggered by the uses of the functions in the decltype expressions below.
Error<int> e; // expected-note 6{{instantiation of}}
};
Error<float> *e;
@@ -109,9 +107,9 @@ namespace DefaultedFnExceptionSpec {
// a defaulted special member function that calls the function is needed.
// Use in an unevaluated operand still results in the exception spec being
// needed.
- void test1(decltype(declval<DelayImplicit>() = DelayImplicit(DelayImplicit())));
- void test2(decltype(declval<DelayImplicit>() = declval<const DelayImplicit>()));
- void test3(decltype(DelayImplicit(declval<const DelayImplicit>())));
+ void test1(decltype(declval<DelayImplicit>() = DelayImplicit(DelayImplicit()))); // expected-note 4{{in evaluation of exception specification}}
+ void test2(decltype(declval<DelayImplicit>() = declval<const DelayImplicit>())); // expected-note {{in evaluation of exception specification}}
+ void test3(decltype(DelayImplicit(declval<const DelayImplicit>()))); // expected-note {{in evaluation of exception specification}}
// Any odr-use needs the exception specification.
void f(Error<double> *p) {
diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
index b9af67948bfc..80efd810f098 100644
--- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
+++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
@@ -59,7 +59,7 @@ struct good_const {
good_const gc;
struct no_default {
- no_default() = delete; // expected-note 4{{deleted here}}
+ no_default() = delete; // expected-note 5{{deleted here}}
};
struct no_dtor {
~no_dtor() = delete; // expected-note 2{{deleted here}}
@@ -108,8 +108,8 @@ struct has_friend {
has_friend hf;
struct defaulted_delete {
- no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}}
- defaulted_delete() = default; // expected-note{{implicitly deleted here}}
+ no_default nd; // expected-note 2{{because field 'nd' has a deleted default constructor}}
+ defaulted_delete() = default; // expected-note{{implicitly deleted here}} expected-warning {{implicitly deleted}}
};
defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}}
diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp
index 90b11f3a9e23..a13aa238de66 100644
--- a/test/SemaCXX/cxx0x-initializer-scalars.cpp
+++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp
@@ -127,3 +127,26 @@ namespace PR12118 {
static_assert(sizeof(f({0})) == sizeof(one), "bad overload");
}
}
+
+namespace excess_braces_sfinae {
+ using valid = int&;
+ using invalid = float&;
+
+ template<typename T> valid braces1(decltype(T{0})*);
+ template<typename T> invalid braces1(...);
+
+ template<typename T> valid braces2(decltype(T{{0}})*);
+ template<typename T> invalid braces2(...);
+
+ template<typename T> valid braces3(decltype(T{{{0}}})*);
+ template<typename T> invalid braces3(...);
+
+ valid a = braces1<int>(0);
+ invalid b = braces2<int>(0);
+ invalid c = braces3<int>(0);
+
+ struct X { int n; };
+ valid d = braces1<X>(0);
+ valid e = braces2<X>(0);
+ invalid f = braces3<X>(0);
+}
diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx11-compat.cpp
index b9ccadd85c2d..07cd6b1fcf93 100644
--- a/test/SemaCXX/cxx0x-compat.cpp
+++ b/test/SemaCXX/cxx11-compat.cpp
@@ -47,12 +47,30 @@ template<int ...N> int f() { // expected-warning {{C++11 extension}}
#else
+decltype(auto) x = 0; // expected-warning {{'decltype(auto)' type specifier is incompatible}}
+
auto init_capture = [a(0)] {}; // expected-warning {{initialized lambda captures are incompatible with C++ standards before C++14}}
-static_assert(true); // expected-warning {{incompatible with C++ standards before C++17}}
-template<int ...N> int f() { return (N + ...); } // expected-warning {{incompatible with C++ standards before C++17}}
+auto generic_lambda =
+ [](
+ auto // expected-warning {{generic lambdas are incompatible}}
+ *a) {};
+
+auto deduced_return_type(); // expected-warning {{incompatible with C++ standards before C++14}}
+auto *another_deduced_return_type(); // expected-warning {{incompatible with C++ standards before C++14}}
+decltype(auto) also_deduced_return_type(); // expected-warning {{return type deduction}} expected-warning {{'decltype(auto)' type specifier is incompatible}}
+int f();
+auto (*not_deduced_return_type)() = f;
+
+auto deduced_lambda_return_type = []() ->
+ auto // expected-warning {{return type deduction is incompatible}}
+{};
+
+auto trailing_non_deduced_return_type() -> int;
+auto trailing_deduced_return_type() -> auto; // expected-warning {{incompatible with C++ standards before C++14}}
-namespace [[]] NS_with_attr {} // expected-warning {{incompatible with C++ standards before C++17}}
-enum { e [[]] }; // expected-warning {{incompatible with C++ standards before C++17}}
+struct A {
+ operator auto(); // expected-warning {{return type deduction is incompatible}}
+};
#endif
diff --git a/test/SemaCXX/cxx14-compat.cpp b/test/SemaCXX/cxx14-compat.cpp
new file mode 100644
index 000000000000..d70f477cd09a
--- /dev/null
+++ b/test/SemaCXX/cxx14-compat.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++14-compat-pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++14-compat-pedantic -verify %s
+
+#if __cplusplus < 201402L
+
+// expected-no-diagnostics
+// FIXME: C++11 features removed or changed in C++14?
+
+#else
+
+static_assert(true); // expected-warning {{incompatible with C++ standards before C++17}}
+
+template<int ...N> int f() { return (N + ...); } // expected-warning {{incompatible with C++ standards before C++17}}
+
+namespace [[]] NS_with_attr {} // expected-warning {{incompatible with C++ standards before C++17}}
+enum { e [[]] }; // expected-warning {{incompatible with C++ standards before C++17}}
+
+template<typename T = int> struct X {};
+X x; // expected-warning {{class template argument deduction is incompatible with C++ standards before C++17; for compatibility, use explicit type name 'X<int>'}}
+
+template<template<typename> class> struct Y {};
+Y<X> yx; // ok, not class template argument deduction
+
+template<typename T> void f(T t) {
+ X x = t; // expected-warning {{incompatible}}
+}
+
+template<typename T> void g(T t) {
+ typename T::X x = t; // expected-warning {{incompatible}}
+}
+struct A { template<typename T> struct X { X(T); }; };
+void h(A a) { g(a); } // expected-note {{in instantiation of}}
+
+#endif
diff --git a/test/SemaCXX/cxx17-compat.cpp b/test/SemaCXX/cxx17-compat.cpp
index 3b814340c6da..eee9c239d188 100644
--- a/test/SemaCXX/cxx17-compat.cpp
+++ b/test/SemaCXX/cxx17-compat.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -pedantic -verify %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++2a -Wc++17-compat-pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++2a -Wc++17-compat-pedantic -verify %s -Wno-defaulted-function-deleted
struct A {};
int (A::*pa)() const&;
@@ -27,3 +27,39 @@ struct B {
// expected-warning@-4 {{default member initializer for bit-field is incompatible with C++ standards before C++2a}}
#endif
};
+
+auto Lambda = []{};
+decltype(Lambda) AnotherLambda;
+#if __cplusplus <= 201703L
+ // expected-error@-2 {{no matching constructor}} expected-note@-3 2{{candidate}}
+#else
+ // expected-warning@-4 {{default construction of lambda is incompatible with C++ standards before C++2a}}
+#endif
+
+void copy_lambda() { Lambda = Lambda; }
+#if __cplusplus <= 201703L
+ // expected-error@-2 {{deleted}} expected-note@-10 {{lambda}}
+#else
+ // expected-warning@-4 {{assignment of lambda is incompatible with C++ standards before C++2a}}
+#endif
+
+struct DefaultDeleteWrongTypeBase {
+ DefaultDeleteWrongTypeBase(DefaultDeleteWrongTypeBase&);
+};
+struct DefaultDeleteWrongType : DefaultDeleteWrongTypeBase {
+ DefaultDeleteWrongType(const DefaultDeleteWrongType&) = default;
+#if __cplusplus <= 201703L
+ // expected-error@-2 {{a member or base requires it to be non-const}}
+#else
+ // expected-warning@-4 {{explicitly defaulting this copy constructor with a type different from the implicit type is incompatible with C++ standards before C++2a}}
+#endif
+};
+
+void ForRangeInit() {
+ for (int arr[3] = {1, 2, 3}; int n : arr) {}
+#if __cplusplus <= 201703L
+ // expected-warning@-2 {{range-based for loop initialization statements are a C++2a extension}}
+#else
+ // expected-warning@-4 {{range-based for loop initialization statements are incompatible with C++ standards before C++2a}}
+#endif
+}
diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp
index 13ff751acae4..fafc6ead73c4 100644
--- a/test/SemaCXX/cxx1y-deduced-return-type.cpp
+++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp
@@ -552,3 +552,71 @@ namespace PR24989 {
void forinit_decltypeauto() {
for (decltype(auto) forinit_decltypeauto_inner();;) {} // expected-warning {{interpreted as a function}} expected-note {{replace}}
}
+
+namespace PR33222 {
+ auto f1();
+ auto f2();
+
+ template<typename T> decltype(auto) g0(T x) { return x.n; }
+ template<typename T> decltype(auto) g1(T);
+ template<typename T> decltype(auto) g2(T);
+
+ struct X {
+ static auto f1();
+ static auto f2();
+
+ template<typename T> static decltype(auto) g0(T x) { return x.n; }
+ template<typename T> static decltype(auto) g1(T);
+ template<typename T> static decltype(auto) g2(T);
+ };
+
+ template<typename U> class A {
+ friend auto f1();
+ friend auto f2();
+
+ friend decltype(auto) g0<>(A);
+ template<typename T> friend decltype(auto) g1(T);
+ template<typename T> friend decltype(auto) g2(T);
+
+ friend auto X::f1();
+ friend auto X::f2();
+
+ // FIXME (PR38882): 'A' names the class template not the injected-class-name here!
+ friend decltype(auto) X::g0<>(A<U>);
+ // FIXME (PR38882): ::T hides the template parameter if both are named T here!
+ template<typename T_> friend decltype(auto) X::g1(T_);
+ template<typename T_> friend decltype(auto) X::g2(T_);
+
+ int n;
+ };
+
+ auto f1() { return A<int>().n; }
+ template<typename T> decltype(auto) g1(T x) { return A<int>().n; }
+
+ auto X::f1() { return A<int>().n; }
+ template<typename T> decltype(auto) X::g1(T x) { return A<int>().n; }
+
+ A<int> ai;
+ int k1 = g0(ai);
+ int k2 = X::g0(ai);
+
+ int k3 = g1(ai);
+ int k4 = X::g1(ai);
+
+ auto f2() { return A<int>().n; }
+ template<typename T> decltype(auto) g2(T x) { return A<int>().n; }
+
+ auto X::f2() { return A<int>().n; }
+ template<typename T> decltype(auto) X::g2(T x) { return A<int>().n; }
+
+ int k5 = g2(ai);
+ int k6 = X::g2(ai);
+
+ template<typename> struct B {
+ auto *q() { return (float*)0; } // expected-note 2{{previous}}
+ };
+ template<> auto *B<char[1]>::q() { return (int*)0; }
+ template<> auto B<char[2]>::q() { return (int*)0; } // expected-error {{return type}}
+ // FIXME: suppress this follow-on error: expected-error@-1 {{cannot initialize}}
+ template<> int B<char[3]>::q() { return 0; } // expected-error {{return type}}
+}
diff --git a/test/SemaCXX/cxx1y-init-captures.cpp b/test/SemaCXX/cxx1y-init-captures.cpp
index 4b82452ed592..16cffb2a914b 100644
--- a/test/SemaCXX/cxx1y-init-captures.cpp
+++ b/test/SemaCXX/cxx1y-init-captures.cpp
@@ -144,13 +144,13 @@ int test(T t = T{}) {
};
}
{ // will need to capture x in outer lambda
- const int x = 10; //expected-note 2{{declared}}
- auto L = [z = x](char a) { //expected-note 2{{begins}}
- auto M = [&y = x](T b) { //expected-error 2{{cannot be implicitly captured}}
+ const int x = 10; //expected-note {{declared}}
+ auto L = [z = x](char a) { //expected-note {{begins}}
+ auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}}
return y;
};
return M;
- };
+ };
}
{
// no captures
diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index cbf7c2eee51c..c310c651408d 100644
--- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -307,6 +307,13 @@ namespace dependent {
template int Var(int);
template int Cast(int);
template int New(int);
+
+ template<template<typename> typename Y> void test() {
+ Y(0);
+ new Y(0);
+ Y y(0);
+ }
+ template void test<X>();
}
namespace injected_class_name {
diff --git a/test/SemaCXX/cxx1z-init-statement.cpp b/test/SemaCXX/cxx1z-init-statement.cpp
index d37acd08ce77..eea2589ab7c6 100644
--- a/test/SemaCXX/cxx1z-init-statement.cpp
+++ b/test/SemaCXX/cxx1z-init-statement.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++1z -verify %s
-// RUN: %clang_cc1 -std=c++17 -verify %s
+// RUN: %clang_cc1 -std=c++1z -Wno-unused-value -verify %s
+// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify %s
void testIf() {
int x = 0;
@@ -12,7 +12,7 @@ void testIf() {
int x = 0; // expected-error {{redefinition of 'x'}}
if (x; int a = 0) ++a;
- if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}}
+ if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}}
int a = 0; // expected-error {{redefinition of 'a'}}
else
int a = 0; // expected-error {{redefinition of 'a'}}
@@ -48,7 +48,7 @@ void testSwitch() {
++a;
}
- switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}}
+ switch (x, +x; int a = 0) { // expected-note {{previous definition is here}}
case 0:
int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}}
case 1:
diff --git a/test/SemaCXX/cxx2a-compat.cpp b/test/SemaCXX/cxx2a-compat.cpp
new file mode 100644
index 000000000000..d51f1e6aab13
--- /dev/null
+++ b/test/SemaCXX/cxx2a-compat.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++2a-compat-pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++2a -pedantic -verify %s
+
+struct A { // expected-note 0+{{candidate}}
+ A() = default; // expected-note 0+{{candidate}}
+ int x, y;
+};
+A a1 = {1, 2};
+#if __cplusplus <= 201703L
+ // expected-warning@-2 {{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}}
+#else
+ // expected-error@-4 {{no matching constructor}}
+#endif
+A a2 = {};
+
+struct B : A { A a; };
+B b1 = {{}, {}}; // ok
+B b2 = {1, 2, 3, 4};
+#if __cplusplus <= 201703L
+ // expected-warning@-2 2{{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}}
+#else
+ // expected-error@-4 2{{no viable conversion from 'int' to 'A'}}
+#endif
+
+// Essentially any use of a u8 string literal in C++<=17 is broken by C++20.
+// Just warn on all such string literals.
+struct string { string(const char*); }; // expected-note 0+{{candidate}}
+char u8arr[] = u8"hello";
+const char *u8ptr = "wo" u8"rld";
+string u8str = u8"test" u8"test";
+#if __cplusplus <= 201703L
+// expected-warning@-4 {{type of UTF-8 string literal will change}} expected-note@-4 {{remove 'u8' prefix}}
+// expected-warning@-4 {{type of UTF-8 string literal will change}} expected-note@-4 {{remove 'u8' prefix}}
+// expected-warning@-4 {{type of UTF-8 string literal will change}} expected-note@-4 {{remove 'u8' prefix}}
+#else
+// expected-error@-8 {{ISO C++20 does not permit initialization of char array with UTF-8 string literal}}
+// expected-error@-8 {{cannot initialize a variable of type 'const char *' with an lvalue of type 'const char8_t [6]'}}
+// expected-error@-8 {{no viable conversion from 'const char8_t [9]' to 'string'}}
+#endif
diff --git a/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/test/SemaCXX/cxx2a-initializer-aggregates.cpp
new file mode 100644
index 000000000000..9c438d399b34
--- /dev/null
+++ b/test/SemaCXX/cxx2a-initializer-aggregates.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+namespace class_with_ctor {
+ struct A { // expected-note 6{{candidate}}
+ A() = default; // expected-note 3{{candidate}}
+ int x;
+ int y;
+ };
+ A a = {1, 2}; // expected-error {{no matching constructor}}
+
+ struct B {
+ int x;
+ int y;
+ };
+ B b1 = B(); // trigger declaration of implicit ctors
+ B b2 = {1, 2}; // ok
+
+ struct C : A {
+ A a;
+ };
+ C c1 = {{}, {}}; // ok, call default ctor twice
+ C c2 = {{1, 2}, {3, 4}}; // expected-error 2{{no matching constructor}}
+}
diff --git a/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp b/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp
new file mode 100644
index 000000000000..e555f16ecc1e
--- /dev/null
+++ b/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+auto a = []{};
+decltype(a) a2;
+void f(decltype(a) x, decltype(a) y) {
+ x = y;
+ x = static_cast<decltype(a)&&>(y);
+}
+
+template<typename T>
+struct X {
+ constexpr X() { T::error; } // expected-error {{'::'}}
+ X(const X&);
+ constexpr X &operator=(const X&) { T::error; } // expected-error {{'::'}}
+ constexpr X &operator=(X&&) { T::error; } // expected-error {{'::'}}
+};
+extern X<int> x;
+auto b = [x = x]{}; // expected-note 3{{in instantiation of}}
+decltype(b) b2; // expected-note {{in implicit default constructor}}
+void f(decltype(b) x, decltype(b) y) {
+ x = y; // expected-note {{in implicit copy assignment}}
+ x = static_cast<decltype(b)&&>(y); // expected-note {{in implicit move assignment}}
+}
+
+struct Y {
+ Y() = delete; // expected-note {{deleted}}
+ Y(const Y&);
+ Y &operator=(const Y&) = delete; // expected-note 2{{deleted}}
+ Y &operator=(Y&&) = delete;
+};
+extern Y y;
+auto c = [y = y]{}; // expected-note 3{{deleted because}}
+decltype(c) c2; // expected-error {{deleted}}
+void f(decltype(c) x, decltype(c) y) {
+ x = y; // expected-error {{deleted}}
+ x = static_cast<decltype(c)&&>(y); // expected-error {{deleted}}
+}
diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp
index f814a06f13be..885ab110ab1f 100644
--- a/test/SemaCXX/cxx98-compat.cpp
+++ b/test/SemaCXX/cxx98-compat.cpp
@@ -103,7 +103,8 @@ struct RefQualifier {
auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}}
#ifdef CXX14COMPAT
-auto ff() { return 5; } // expected-warning {{'auto' type specifier is incompatible with C++98}}
+auto ff() { return 5; } // expected-warning {{'auto' type specifier is incompatible with C++98}}
+// expected-warning@-1 {{return type deduction is incompatible with C++ standards before C++14}}
#endif
void RangeFor() {
diff --git a/test/SemaCXX/delete-non-virtual-dtor.cpp b/test/SemaCXX/delete-non-virtual-dtor.cpp
new file mode 100644
index 000000000000..b64eca3527f3
--- /dev/null
+++ b/test/SemaCXX/delete-non-virtual-dtor.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 %s -verify -DDIAG1
+// RUN: %clang_cc1 %s -verify -DDIAG1 -DDIAG2 -Wdelete-non-virtual-dtor
+// RUN: %clang_cc1 %s -verify -DDIAG1 -Wmost -Wno-delete-non-abstract-non-virtual-dtor
+// RUN: %clang_cc1 %s -verify -DDIAG2 -Wmost -Wno-delete-abstract-non-virtual-dtor
+// RUN: %clang_cc1 %s -verify -Wmost -Wno-delete-non-virtual-dtor
+
+#ifndef DIAG1
+#ifndef DIAG2
+// expected-no-diagnostics
+#endif
+#endif
+
+struct S1 {
+ ~S1() {}
+ virtual void abs() = 0;
+};
+
+void f1(S1 *s1) { delete s1; }
+#ifdef DIAG1
+// expected-warning@-2 {{delete called on 'S1' that is abstract but has non-virtual destructor}}
+#endif
+
+struct S2 {
+ ~S2() {}
+ virtual void real() {}
+};
+void f2(S2 *s2) { delete s2; }
+#ifdef DIAG2
+// expected-warning@-2 {{delete called on non-final 'S2' that has virtual functions but non-virtual destructor}}
+#endif
diff --git a/test/SemaCXX/designated-initializers.cpp b/test/SemaCXX/designated-initializers.cpp
index e5b5f3c9cce2..04002c0b6c11 100644
--- a/test/SemaCXX/designated-initializers.cpp
+++ b/test/SemaCXX/designated-initializers.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Winitializer-overrides %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Woverride-init %s
template <typename T> struct Foo {
struct SubFoo {
diff --git a/test/SemaCXX/dr1301.cpp b/test/SemaCXX/dr1301.cpp
index ec0db74554a8..b7dc91d56330 100644
--- a/test/SemaCXX/dr1301.cpp
+++ b/test/SemaCXX/dr1301.cpp
@@ -6,7 +6,7 @@ struct A { // expected-note 2{{candidate}}
int a = A().n; // expected-error {{no matching constructor}}
struct B {
- B() = delete; // expected-note 3{{here}}
+ B() = delete; // expected-note 4{{here}}
int n;
};
int b = B().n; // expected-error {{call to deleted}}
@@ -17,8 +17,8 @@ struct C {
int c = C().b.n; // expected-error {{call to implicitly-deleted default}}
struct D {
- D() = default; // expected-note {{here}}
- B b; // expected-note {{'b' has a deleted default constructor}}
+ D() = default; // expected-note {{here}} expected-warning {{implicitly deleted}}
+ B b; // expected-note 2{{'b' has a deleted default constructor}}
};
int d = D().b.n; // expected-error {{call to implicitly-deleted default}}
diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp
index 93014f50d508..ba520b047a32 100644
--- a/test/SemaCXX/enable_if.cpp
+++ b/test/SemaCXX/enable_if.cpp
@@ -414,7 +414,8 @@ static_assert(templated<1>() == 1, "");
template <int N> constexpr int callTemplated() { return templated<N>(); }
-constexpr int B = callTemplated<0>(); // expected-error{{initialized by a constant expression}} expected-error@-2{{no matching function for call to 'templated'}} expected-note{{in instantiation of function template}} expected-note@-9{{candidate disabled}}
+constexpr int B = 10 + // the carat for the error should be pointing to the problematic call (on the next line), not here.
+ callTemplated<0>(); // expected-error{{initialized by a constant expression}} expected-error@-3{{no matching function for call to 'templated'}} expected-note{{in instantiation of function template}} expected-note@-10{{candidate disabled}}
static_assert(callTemplated<1>() == 1, "");
}
diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp
index cfe5760112f6..16ebebe31b6d 100644
--- a/test/SemaCXX/enum.cpp
+++ b/test/SemaCXX/enum.cpp
@@ -109,6 +109,8 @@ enum { overflow = 123456 * 234567 };
#if __cplusplus >= 201103L
// expected-warning@-2 {{not an integral constant expression}}
// expected-note@-3 {{value 28958703552 is outside the range of representable values}}
+#else
+// expected-warning@-5 {{overflow in expression; result is -1106067520 with type 'int'}}
#endif
// PR28903
diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp
index f301a63503dd..6ad19aab397b 100644
--- a/test/SemaCXX/exception-spec.cpp
+++ b/test/SemaCXX/exception-spec.cpp
@@ -5,3 +5,50 @@ namespace MissingOnTemplate {
template<typename T> void foo(T); // expected-error {{missing exception specification 'noexcept(true)'}}
void test() { foo(0); }
}
+
+struct UseBeforeComplete1 {
+ ~UseBeforeComplete1(); // expected-note {{previous}}
+ struct X {
+ friend UseBeforeComplete1::~UseBeforeComplete1() noexcept; // expected-warning {{previously declared with an implicit}}
+ };
+};
+
+struct ThrowingDtor { ~ThrowingDtor() noexcept(false); };
+struct UseBeforeComplete2 {
+ ~UseBeforeComplete2(); // expected-note {{previous}}
+ struct X {
+ friend UseBeforeComplete2::~UseBeforeComplete2() noexcept; // expected-error {{does not match previous}}
+ };
+ ThrowingDtor td;
+};
+
+struct UseBeforeComplete3 {
+ ~UseBeforeComplete3();
+ struct X {
+ friend UseBeforeComplete3::~UseBeforeComplete3(); // ok, implicitly noexcept(true)
+ };
+};
+static_assert(noexcept(UseBeforeComplete3()), "");
+
+struct UseBeforeComplete4 {
+ ~UseBeforeComplete4();
+ struct X {
+ friend UseBeforeComplete4::~UseBeforeComplete4(); // ok, implicitly noexcept(false)
+ };
+ ThrowingDtor td;
+};
+static_assert(!noexcept(UseBeforeComplete4()), "");
+
+namespace AssignmentOp {
+ struct D1;
+ struct D2;
+ struct B {
+ B &operator=(const B&);
+ virtual D1 &operator=(const D1&) noexcept; // expected-note {{overridden}}
+ virtual D2 &operator=(const D2&) noexcept; // expected-note {{overridden}}
+ };
+ struct D1 : B {}; // expected-error {{more lax}}
+ struct D2 : B {
+ D2 &operator=(const D2&); // expected-error {{more lax}}
+ };
+}
diff --git a/test/SemaCXX/for-range-dereference.cpp b/test/SemaCXX/for-range-dereference.cpp
index 7377199024e5..de4958c31bce 100644
--- a/test/SemaCXX/for-range-dereference.cpp
+++ b/test/SemaCXX/for-range-dereference.cpp
@@ -17,7 +17,7 @@ struct DeletedEnd : public T {
struct DeletedADLBegin { };
int* begin(DeletedADLBegin) = delete; //expected-note {{candidate function has been explicitly deleted}} \
- expected-note 5 {{candidate function not viable: no known conversion}}
+ expected-note 6 {{candidate function not viable: no known conversion}}
struct PrivateEnd {
Data *begin();
@@ -27,7 +27,7 @@ struct PrivateEnd {
};
struct ADLNoEnd { };
-Data * begin(ADLNoEnd); // expected-note 6 {{candidate function not viable: no known conversion}}
+Data * begin(ADLNoEnd); // expected-note 7 {{candidate function not viable: no known conversion}}
struct OverloadedStar {
T operator*();
@@ -45,7 +45,7 @@ void f() {
for (auto i : parr) { }// expected-error{{invalid range expression of type 'int (*)[10]'; did you mean to dereference it with '*'?}}
NoBegin NB;
- for (auto i : NB) { }// expected-error{{range type 'NoBegin' has 'end' member but no 'begin' member}}
+ for (auto i : NB) { }// expected-error{{invalid range expression of type 'NoBegin'; no viable 'begin' function available}}
NoBegin *pNB;
for (auto i : pNB) { }// expected-error{{invalid range expression of type 'NoBegin *'; no viable 'begin' function available}}
NoBegin **ppNB;
diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp
index 477789b56c14..5424b7a8ee79 100644
--- a/test/SemaCXX/for-range-examples.cpp
+++ b/test/SemaCXX/for-range-examples.cpp
@@ -244,7 +244,7 @@ void foo ()
{
int b = 1, a[b];
a[0] = 0;
- [&] { for (int c : a) 0; } ();
+ [&] { for (int c : a) 0; } (); // expected-warning {{expression result unused}}
}
diff --git a/test/SemaCXX/friend-template-redecl.cpp b/test/SemaCXX/friend-template-redecl.cpp
new file mode 100644
index 000000000000..3e05964fb288
--- /dev/null
+++ b/test/SemaCXX/friend-template-redecl.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++17 -verify -emit-llvm-only %s
+
+// expected-no-diagnostics
+
+template <class T> void bar(const T &t) { foo(t); }
+
+template <class>
+struct HasFriend {
+ template <class T>
+ friend void foo(const HasFriend<T> &m) noexcept(false);
+};
+
+template <class T>
+void foo(const HasFriend<T> &m) noexcept(false) {}
+
+void f() {
+ HasFriend<int> x;
+ foo(x);
+ bar(x);
+}
diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp
index 1f64ba609b16..822b1de39a1e 100644
--- a/test/SemaCXX/friend.cpp
+++ b/test/SemaCXX/friend.cpp
@@ -162,7 +162,7 @@ namespace test9 {
class C {
};
struct A {
- friend void C::f(int, int, int) {} // expected-error {{no function named 'f' with type 'void (int, int, int)' was found in the specified scope}}
+ friend void C::f(int, int, int) {} // expected-error {{friend function definition cannot be qualified with 'C::'}}
};
}
@@ -230,6 +230,10 @@ namespace test10 {
friend void f10_d(X);
};
+ struct W {
+ friend void f10_d(W);
+ };
+
void g(X x, Y y, Z z) {
f10_d(); // expected-error {{undeclared identifier}}
::test10::f10_d(); // expected-error {{no member named 'f10_d'}}
@@ -245,14 +249,13 @@ namespace test10 {
::test10::f10_d(z); // expected-error {{no type named 'f10_d'}}
}
- void local_externs(X x, Y y) {
- extern void f10_d();
- extern void f10_d(X);
+ void local_externs(W w, X x, Y y) {
+ extern void f10_d(); // expected-note {{candidate}}
+ extern void f10_d(X); // expected-note {{candidate}}
f10_d();
f10_d(x);
- // FIXME: This lookup should fail, because the local extern declaration
- // should suppress ADL.
f10_d(y);
+ f10_d(w); // expected-error {{no matching}}
{
int f10_d;
f10_d(); // expected-error {{not a function}}
@@ -388,3 +391,41 @@ namespace default_arg {
friend void f(void *p = 0) {} // expected-error {{must be the only}}
};
}
+
+namespace PR33222 {
+ int f();
+ template<typename T> struct X {
+ friend T f();
+ };
+ X<int> xi;
+
+ int g(); // expected-note {{previous}}
+ template<typename T> struct Y {
+ friend T g(); // expected-error {{return type}}
+ };
+ Y<float> yf; // expected-note {{instantiation}}
+
+ int h(); // expected-note {{previous}}
+ template<typename T> struct Z {
+ friend T h(); // expected-error {{return type}}
+ };
+ Z<int> zi;
+ Z<float> zf; // expected-note {{instantiation}}
+}
+
+namespace qualified_friend_no_match {
+ void f(int); // expected-note {{type mismatch at 1st parameter}}
+ template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}}
+ struct X {
+ friend void qualified_friend_no_match::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend_no_match'}}
+ friend void qualified_friend_no_match::g(); // expected-error {{friend declaration of 'g' does not match any declaration in namespace 'qualified_friend_no_match'}}
+ };
+
+ struct Y {
+ void f(int); // expected-note {{type mismatch at 1st parameter}}
+ template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}}
+ };
+ struct Z {
+ friend void Y::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend_no_match::Y'}}
+ };
+}
diff --git a/test/SemaCXX/friend2.cpp b/test/SemaCXX/friend2.cpp
index 8eacdeb19c62..6d3b545904e4 100644
--- a/test/SemaCXX/friend2.cpp
+++ b/test/SemaCXX/friend2.cpp
@@ -129,6 +129,83 @@ C22b<int> c22bi;
void func_22() {} // expected-error{{redefinition of 'func_22'}}
+// Case of template friend functions.
+
+template<typename T> void func_31(T *x);
+template<typename T1>
+struct C31a {
+ template<typename T> friend void func_31(T *x) {}
+};
+template<typename T1>
+struct C31b {
+ template<typename T> friend void func_31(T *x) {}
+};
+
+
+template<typename T> inline void func_32(T *x) {}
+template<typename T1>
+struct C32a {
+ template<typename T> friend void func_32(T *x) {}
+};
+template<typename T1>
+struct C32b {
+ template<typename T> friend void func_32(T *x) {}
+};
+
+
+template<typename T1>
+struct C33a {
+ template<typename T> friend void func_33(T *x) {}
+};
+template<typename T1>
+struct C33b {
+ template<typename T> friend void func_33(T *x) {}
+};
+
+
+template<typename T> inline void func_34(T *x) {} // expected-note{{previous definition is here}}
+template<typename T1>
+struct C34 {
+ template<typename T> friend void func_34(T *x) {} // expected-error{{redefinition of 'func_34'}}
+};
+
+C34<int> v34; // expected-note{{in instantiation of template class 'C34<int>' requested here}}
+
+
+template<typename T> inline void func_35(T *x);
+template<typename T1>
+struct C35a {
+ template<typename T> friend void func_35(T *x) {} // expected-note{{previous definition is here}}
+};
+template<typename T1>
+struct C35b {
+ template<typename T> friend void func_35(T *x) {} // expected-error{{redefinition of 'func_35'}}
+};
+
+C35a<int> v35a;
+C35b<int> v35b; // expected-note{{in instantiation of template class 'C35b<int>' requested here}}
+
+
+template<typename T> void func_36(T *x);
+template<typename T1>
+struct C36 {
+ template<typename T> friend void func_36(T *x) {} // expected-error{{redefinition of 'func_36'}}
+ // expected-note@-1{{previous definition is here}}
+};
+
+C36<int> v36a;
+C36<long> v36b; //expected-note{{in instantiation of template class 'C36<long>' requested here}}
+
+
+template<typename T> void func_37(T *x);
+template<typename T1>
+struct C37 {
+ template<typename T> friend void func_37(T *x) {} // expected-note{{previous definition is here}}
+};
+
+C37<int> v37;
+template<typename T> void func_37(T *x) {} // expected-error{{redefinition of 'func_37'}}
+
namespace pr22307 {
@@ -235,3 +312,15 @@ void func() {
cache.insert();
}
}
+
+namespace PR39742 {
+template<typename>
+struct wrapper {
+ template<typename>
+ friend void friend_function_template() {} // expected-error{{redefinition of 'friend_function_template'}}
+ // expected-note@-1{{previous definition is here}}
+};
+
+wrapper<bool> x;
+wrapper<int> y; // expected-note{{in instantiation of template class 'PR39742::wrapper<int>' requested here}}
+}
diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp
index c21f773e94c6..19d645d6d3d1 100644
--- a/test/SemaCXX/implicit-exception-spec.cpp
+++ b/test/SemaCXX/implicit-exception-spec.cpp
@@ -16,41 +16,39 @@ namespace InClassInitializers {
// Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept())
// is false.
bool ThrowSomething() noexcept(false);
- struct ConstExpr {
+ struct ConstExpr { // expected-error {{default member initializer for 'b' needed}}
bool b = // expected-note {{declared here}}
- noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{default member initializer for 'b' needed}}
+ noexcept(ConstExpr()) && ThrowSomething(); // expected-note {{in evaluation of exception spec}}
};
// Much more obviously broken: we can't parse the initializer without already
// knowing whether it produces a noexcept expression.
- struct TemplateArg {
+ struct TemplateArg { // expected-error {{default member initializer for 'n' needed}}
int n = // expected-note {{declared here}}
- ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{default member initializer for 'n' needed}}
+ ExceptionIf<noexcept(TemplateArg())>::f(); // expected-note {{in evaluation of exception spec}}
};
// And within a nested class.
struct Nested {
- struct Inner {
+ struct Inner { // expected-error {{default member initializer for 'n' needed}}
int n = // expected-note {{declared here}}
- ExceptionIf<noexcept(Nested())>::f();
- } inner; // expected-error {{default member initializer for 'n' needed}}
+ ExceptionIf<noexcept(Nested())>::f(); // expected-note {{in evaluation of exception spec}}
+ } inner; // expected-note {{in evaluation of exception spec}}
};
struct Nested2 {
struct Inner;
- int n = Inner().n; // expected-error {{initializer for 'n' needed}}
- struct Inner {
+ int n = Inner().n; // expected-note {{in evaluation of exception spec}}
+ struct Inner { // expected-error {{initializer for 'n' needed}}
int n = ExceptionIf<noexcept(Nested2())>::f(); // expected-note {{declared here}}
} inner;
};
}
namespace ExceptionSpecification {
- // FIXME: This diagnostic is quite useless; we should indicate whose
- // exception specification we were looking for and why.
struct Nested {
struct T {
- T() noexcept(!noexcept(Nested()));
+ T() noexcept(!noexcept(Nested())); // expected-note {{in evaluation of exception spec}}
} t; // expected-error{{exception specification is not available until end of class definition}}
};
}
diff --git a/test/SemaCXX/lambda-invalid-capture.cpp b/test/SemaCXX/lambda-invalid-capture.cpp
new file mode 100644
index 000000000000..32349704caa2
--- /dev/null
+++ b/test/SemaCXX/lambda-invalid-capture.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// Don't crash.
+
+struct g {
+ j; // expected-error {{C++ requires a type specifier for all declarations}}
+};
+
+void captures_invalid_type() {
+ g child;
+ auto q = [child]{};
+ const int n = sizeof(q);
+}
+
+void captures_invalid_array_type() {
+ g child[100];
+ auto q = [child]{};
+ const int n = sizeof(q);
+}
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index 8a13eca2f177..2c4659afa3e7 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -13,10 +13,10 @@ public:
bool b();
int k;
-struct Recurse {
+struct Recurse { // expected-error {{initializer for 'n' needed}}
int &n = // expected-note {{declared here}}
b() ?
- Recurse().n : // expected-error {{initializer for 'n' needed}}
+ Recurse().n : // expected-note {{in evaluation of exception spec}}
k;
};
@@ -127,19 +127,19 @@ A::A() {}
namespace template_default_ctor {
struct A {
template <typename T>
- struct B {
+ struct B { // expected-error {{initializer for 'm1' needed}}
int m1 = 0; // expected-note {{declared here}}
};
- enum { NOE = noexcept(B<int>()) }; // expected-error {{initializer for 'm1' needed}}
+ enum { NOE = noexcept(B<int>()) }; // expected-note {{in evaluation of exception spec}}
};
}
namespace default_ctor {
struct A {
- struct B {
+ struct B { // expected-error {{initializer for 'm1' needed}}
int m1 = 0; // expected-note {{declared here}}
};
- enum { NOE = noexcept(B()) }; // expected-error {{initializer for 'm1' needed}}
+ enum { NOE = noexcept(B()) }; // expected-note {{in evaluation of exception spec}}
};
}
@@ -147,17 +147,17 @@ namespace member_template {
struct A {
template <typename T>
struct B {
- struct C {
+ struct C { // expected-error {{initializer for 'm1' needed}}
int m1 = 0; // expected-note {{declared here}}
};
template <typename U>
- struct D {
+ struct D { // expected-error {{initializer for 'm1' needed}}
int m1 = 0; // expected-note {{declared here}}
};
};
enum {
- NOE1 = noexcept(B<int>::C()), // expected-error {{initializer for 'm1' needed}}
- NOE2 = noexcept(B<int>::D<int>()) // expected-error {{initializer for 'm1' needed}}
+ NOE1 = noexcept(B<int>::C()), // expected-note {{in evaluation of exception spec}}
+ NOE2 = noexcept(B<int>::D<int>()) // expected-note {{in evaluation of exception spec}}
};
};
}
diff --git a/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp b/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
index 5a399aa7eac2..000492e0edf1 100644
--- a/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
+++ b/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp
@@ -6,8 +6,8 @@ struct S {
void operator delete(void*, double);
} s; // expected-error {{attempt to use a deleted function}}
-struct T { // expected-note{{virtual destructor requires an unambiguous, accessible 'operator delete'}}
- virtual ~T() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}}
+struct T { // expected-note 2{{virtual destructor requires an unambiguous, accessible 'operator delete'}}
+ virtual ~T() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} expected-warning {{implicitly deleted}}
void operator delete(void*, int);
void operator delete(void*, double);
} t; // expected-error {{attempt to use a deleted function}}
diff --git a/test/SemaCXX/microsoft-varargs.cpp b/test/SemaCXX/microsoft-varargs.cpp
index 5b0f90eb5ca0..311ce4a54f1f 100644
--- a/test/SemaCXX/microsoft-varargs.cpp
+++ b/test/SemaCXX/microsoft-varargs.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -fsyntax-only %s -verify
+// RUN: %clang_cc1 -triple aarch64-windows -fms-compatibility -fsyntax-only %s -verify
// expected-no-diagnostics
extern "C" {
diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp
index 624ac0541db4..c177570682f6 100644
--- a/test/SemaCXX/ms-uuid.cpp
+++ b/test/SemaCXX/ms-uuid.cpp
@@ -62,14 +62,14 @@ class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2;
[uuid("220000A0-0000-0000-C000-000000000049")] class C4 {};
// Both cl and clang-cl error out on this:
-// expected-note@+1 {{previous uuid specified here}}
-class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
// expected-error@+1 {{uuid does not match previous declaration}}
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
+// expected-note@+1 {{previous uuid specified here}}
__declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5;
-// expected-note@+1 {{previous uuid specified here}}
-[uuid("000000A0-0000-0000-C000-000000000049"),
// expected-error@+1 {{uuid does not match previous declaration}}
+[uuid("000000A0-0000-0000-C000-000000000049"),
+// expected-note@+1 {{previous uuid specified here}}
uuid("110000A0-0000-0000-C000-000000000049")] class C6;
// cl doesn't diagnose having one uuid each as []-style attributes and as
diff --git a/test/SemaCXX/no_destroy.cpp b/test/SemaCXX/no_destroy.cpp
new file mode 100644
index 000000000000..7afbf9998253
--- /dev/null
+++ b/test/SemaCXX/no_destroy.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -DNO_DTORS -fno-c++-static-destructors -verify %s
+// RUN: %clang_cc1 -verify %s
+
+struct SecretDestructor {
+#ifndef NO_DTORS
+ // expected-note@+2 4 {{private}}
+#endif
+private: ~SecretDestructor(); // expected-note 2 {{private}}
+};
+
+SecretDestructor sd1;
+thread_local SecretDestructor sd2;
+void locals() {
+ static SecretDestructor sd3;
+ thread_local SecretDestructor sd4;
+}
+
+#ifndef NO_DTORS
+// SecretDestructor sd1; // expected-error@-8 {{private}}
+// thread_local SecretDestructor sd2; // expected-error@-8 {{private}}
+// void locals() {
+// static SecretDestructor sd3; // expected-error@-8 {{private}}
+// thread_local SecretDestructor sd4; // expected-error@-8 {{private}}
+// }
+#endif
+
+[[clang::always_destroy]] SecretDestructor sd6; // expected-error{{private}}
+[[clang::always_destroy]] thread_local SecretDestructor sd7; // expected-error{{private}}
+
+[[clang::no_destroy]] SecretDestructor sd8;
+
+int main() {
+ [[clang::no_destroy]] int p; // expected-error{{no_destroy attribute can only be applied to a variable with static or thread storage duration}}
+ [[clang::always_destroy]] int p2; // expected-error{{always_destroy attribute can only be applied to a variable with static or thread storage duration}}
+ [[clang::no_destroy]] static int p3;
+ [[clang::always_destroy]] static int p4;
+}
+
+[[clang::always_destroy]] [[clang::no_destroy]] int p; // expected-error{{'no_destroy' and 'always_destroy' attributes are not compatible}} // expected-note{{here}}
+[[clang::no_destroy]] [[clang::always_destroy]] int p2; // expected-error{{'always_destroy' and 'no_destroy' attributes are not compatible}} // expected-note{{here}}
+
+[[clang::always_destroy]] void f() {} // expected-warning{{'always_destroy' attribute only applies to variables}}
+struct [[clang::no_destroy]] DoesntApply {}; // expected-warning{{'no_destroy' attribute only applies to variables}}
+
+[[clang::no_destroy(0)]] int no_args; // expected-error{{'no_destroy' attribute takes no arguments}}
+[[clang::always_destroy(0)]] int no_args2; // expected-error{{'always_destroy' attribute takes no arguments}}
diff --git a/test/SemaCXX/rdar42746401.cpp b/test/SemaCXX/rdar42746401.cpp
new file mode 100644
index 000000000000..ff9dff456ce4
--- /dev/null
+++ b/test/SemaCXX/rdar42746401.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template <int>
+class b;
+class c; // expected-note{{forward declaration}}
+
+::b<0> struct c::d // expected-error{{incomplete type}} expected-error{{cannot combine}} expected-error{{expected unqualified-id}}
diff --git a/test/SemaCXX/static-assert-cxx17.cpp b/test/SemaCXX/static-assert-cxx17.cpp
new file mode 100644
index 000000000000..fe02f8f29965
--- /dev/null
+++ b/test/SemaCXX/static-assert-cxx17.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z -triple=x86_64-linux-gnu
+
+template <typename U, typename V>
+struct S1 {
+ static constexpr const bool value = false;
+};
+
+template <typename U, typename V>
+inline constexpr bool global_inline_var = S1<U, V>::value;
+
+template <typename T>
+struct S2 {
+ template <typename U, typename V>
+ static inline constexpr bool var = global_inline_var<U, V>;
+};
+
+template <typename U, typename V>
+inline constexpr bool constexpr_return_false() {
+ return false;
+}
+
+template <typename U, typename V>
+void foo() {
+ static_assert(S1<U, V>::value);
+ // expected-error@-1{{static_assert failed due to requirement 'S1<int, float>::value'}}
+}
+template void foo<int, float>();
+// expected-note@-1{{in instantiation of function template specialization 'foo<int, float>' requested here}}
+
+template <typename U, typename V>
+void foo2() {
+ static_assert(global_inline_var<U, V>);
+ // expected-error@-1{{static_assert failed due to requirement 'global_inline_var<int, float>'}}
+}
+template void foo2<int, float>();
+// expected-note@-1{{in instantiation of function template specialization 'foo2<int, float>' requested here}}
+
+template <typename T, typename U, typename V>
+void foo3() {
+ static_assert(T::template var<U, V>);
+ // expected-error@-1{{static_assert failed due to requirement 'S2<long>::var<int, float>'}}
+}
+template void foo3<S2<long>, int, float>();
+// expected-note@-1{{in instantiation of function template specialization 'foo3<S2<long>, int, float>' requested here}}
+
+template <typename T>
+void foo4() {
+ static_assert(S1<T[sizeof(T)], int[4]>::value, "");
+ // expected-error@-1{{static_assert failed due to requirement 'S1<float [4], int [4]>::value'}}
+};
+template void foo4<float>();
+// expected-note@-1{{in instantiation of function template specialization 'foo4<float>' requested here}}
+
+
+template <typename U, typename V>
+void foo5() {
+ static_assert(!!(global_inline_var<U, V>));
+ // expected-error@-1{{static_assert failed due to requirement '!!(global_inline_var<int, float>)'}}
+}
+template void foo5<int, float>();
+// expected-note@-1{{in instantiation of function template specialization 'foo5<int, float>' requested here}}
+
+struct ExampleTypes {
+ explicit ExampleTypes(int);
+ using T = int;
+ using U = float;
+};
+
+template <class T>
+struct X {
+ int i = 0;
+ int j = 0;
+ constexpr operator bool() const { return false; }
+};
+
+template <class T>
+void foo6() {
+ static_assert(X<typename T::T>());
+ // expected-error@-1{{static_assert failed due to requirement 'X<int>()'}}
+ static_assert(X<typename T::T>{});
+ // expected-error@-1{{static_assert failed due to requirement 'X<int>{}'}}
+ static_assert(X<typename T::T>{1, 2});
+ // expected-error@-1{{static_assert failed due to requirement 'X<int>{1, 2}'}}
+ static_assert(X<typename T::T>({1, 2}));
+ // expected-error@-1{{static_assert failed due to requirement 'X<int>({1, 2})'}}
+ static_assert(typename T::T{0});
+ // expected-error@-1{{static_assert failed due to requirement 'int{0}'}}
+ static_assert(typename T::T(0));
+ // expected-error@-1{{static_assert failed due to requirement 'int(0)'}}
+ static_assert(sizeof(X<typename T::T>) == 0);
+ // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<int>) == 0'}}
+ static_assert((const X<typename T::T> *)nullptr);
+ // expected-error@-1{{static_assert failed due to requirement '(const X<int> *)nullptr'}}
+ static_assert(static_cast<const X<typename T::T> *>(nullptr));
+ // expected-error@-1{{static_assert failed due to requirement 'static_cast<const X<int> *>(nullptr)'}}
+ static_assert((const X<typename T::T>[]){} == nullptr);
+ // expected-error@-1{{static_assert failed due to requirement '(X<int> const[0]){} == nullptr'}}
+ static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0);
+ // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<void>) == 0'}}
+ static_assert(constexpr_return_false<typename T::T, typename T::U>());
+ // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false<int, float>()'}}
+}
+template void foo6<ExampleTypes>();
+// expected-note@-1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}}
diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp
index 846303807a02..a21cc874b566 100644
--- a/test/SemaCXX/static-assert.cpp
+++ b/test/SemaCXX/static-assert.cpp
@@ -15,14 +15,14 @@ class C {
};
template<int N> struct T {
- static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}}
+ static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed due to requirement '1 == 2' "N is not 2!"}}
};
T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}}
T<2> t2;
template<typename T> struct S {
- static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}}
+ static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed due to requirement 'sizeof(char) > sizeof(char)' "Type not big enough!"}}
};
S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}}
@@ -68,3 +68,123 @@ template<typename T> struct second_trait {
};
static_assert(first_trait<X>::value && second_trait<X>::value, "message"); // expected-error{{static_assert failed due to requirement 'second_trait<X>::value' "message"}}
+
+namespace std {
+
+template <class Tp, Tp v>
+struct integral_constant {
+ static const Tp value = v;
+ typedef Tp value_type;
+ typedef integral_constant type;
+ constexpr operator value_type() const noexcept { return value; }
+ constexpr value_type operator()() const noexcept { return value; }
+};
+
+template <class Tp, Tp v>
+const Tp integral_constant<Tp, v>::value;
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template <class Tp>
+struct is_const : public false_type {};
+template <class Tp>
+struct is_const<Tp const> : public true_type {};
+
+// We do not define is_same in terms of integral_constant to check that both implementations are supported.
+template <typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template <typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+} // namespace std
+
+struct ExampleTypes {
+ explicit ExampleTypes(int);
+ using T = int;
+ using U = float;
+};
+
+static_assert(std::is_same<ExampleTypes::T, ExampleTypes::U>::value, "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_same<int, float>::value' "message"}}
+static_assert(std::is_const<ExampleTypes::T>::value, "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}}
+static_assert(!std::is_const<const ExampleTypes::T>::value, "message");
+// expected-error@-1{{static_assert failed due to requirement '!std::is_const<const int>::value' "message"}}
+static_assert(!(std::is_const<const ExampleTypes::T>::value), "message");
+// expected-error@-1{{static_assert failed due to requirement '!(std::is_const<const int>::value)' "message"}}
+static_assert(std::is_const<const ExampleTypes::T>::value == false, "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_const<const int>::value == false' "message"}}
+static_assert(!(std::is_const<const ExampleTypes::T>::value == true), "message");
+// expected-error@-1{{static_assert failed due to requirement '!(std::is_const<const int>::value == true)' "message"}}
+static_assert(std::is_const<ExampleTypes::T>(), "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>()' "message"}}
+static_assert(!(std::is_const<const ExampleTypes::T>()()), "message");
+// expected-error@-1{{static_assert failed due to requirement '!(std::is_const<const int>()())' "message"}}
+static_assert(std::is_same<decltype(std::is_const<const ExampleTypes::T>()), int>::value, "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_same<std::is_const<const int>, int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes::T(3))>::value, "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes::T())>::value, "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes(3))>::value, "message");
+// expected-error@-1{{static_assert failed due to requirement 'std::is_const<ExampleTypes>::value' "message"}}
+
+struct BI_tag {};
+struct RAI_tag : BI_tag {};
+struct MyIterator {
+ using tag = BI_tag;
+};
+struct MyContainer {
+ using iterator = MyIterator;
+};
+template <class Container>
+void foo() {
+ static_assert(std::is_same<RAI_tag, typename Container::iterator::tag>::value, "message");
+ // expected-error@-1{{static_assert failed due to requirement 'std::is_same<RAI_tag, BI_tag>::value' "message"}}
+}
+template void foo<MyContainer>();
+// expected-note@-1{{in instantiation of function template specialization 'foo<MyContainer>' requested here}}
+
+namespace ns {
+template <typename T, int v>
+struct NestedTemplates1 {
+ struct NestedTemplates2 {
+ template <typename U>
+ struct NestedTemplates3 : public std::is_same<T, U> {};
+ };
+};
+} // namespace ns
+
+template <typename T, typename U, int a>
+void foo2() {
+ static_assert(::ns::NestedTemplates1<T, a>::NestedTemplates2::template NestedTemplates3<U>::value, "message");
+ // expected-error@-1{{static_assert failed due to requirement '::ns::NestedTemplates1<int, 3>::NestedTemplates2::NestedTemplates3<float>::value' "message"}}
+}
+template void foo2<int, float, 3>();
+// expected-note@-1{{in instantiation of function template specialization 'foo2<int, float, 3>' requested here}}
+
+template <class T>
+void foo3(T t) {
+ static_assert(std::is_const<T>::value, "message");
+ // expected-error-re@-1{{static_assert failed due to requirement 'std::is_const<(lambda at {{.*}}static-assert.cpp:{{[0-9]*}}:{{[0-9]*}})>::value' "message"}}
+ static_assert(std::is_const<decltype(t)>::value, "message");
+ // expected-error-re@-1{{static_assert failed due to requirement 'std::is_const<(lambda at {{.*}}static-assert.cpp:{{[0-9]*}}:{{[0-9]*}})>::value' "message"}}
+}
+void callFoo3() {
+ foo3([]() {});
+ // expected-note@-1{{in instantiation of function template specialization 'foo3<(lambda at }}
+}
+
+template <class T>
+void foo4(T t) {
+ static_assert(std::is_const<typename T::iterator>::value, "message");
+ // expected-error@-1{{type 'int' cannot be used prior to '::' because it has no members}}
+}
+void callFoo4() { foo4(42); }
+// expected-note@-1{{in instantiation of function template specialization 'foo4<int>' requested here}}
diff --git a/test/SemaCXX/string-plus-int.cpp b/test/SemaCXX/string-plus-int.cpp
index fe9c71949698..448fb49fb49f 100644
--- a/test/SemaCXX/string-plus-int.cpp
+++ b/test/SemaCXX/string-plus-int.cpp
@@ -31,37 +31,36 @@ void f(int index) {
consume("foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
consume("foo" + index); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
consume("foo" + kMyEnum); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume("foo" + kMySmallEnum); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
consume(5 + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
consume(index + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
consume(kMyEnum + "foo"); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume(kMySmallEnum + "foo"); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
// FIXME: suggest replacing with "foo"[5]
consumeChar(*("foo" + 5)); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
consumeChar(*(5 + "foo")); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
consume(L"foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume(L"foo" + 2); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ consume("foo" + 3); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume("foo" + 4); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume("\pfoo" + 4); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ #define A "foo"
+ #define B "bar"
+ consume(A B + sizeof(A) - 1); // expected-warning {{to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
// Should not warn.
consume(&("foo"[3]));
consume(&("foo"[index]));
consume(&("foo"[kMyEnum]));
- consume("foo" + kMySmallEnum);
- consume(kMySmallEnum + "foo");
- consume(L"foo" + 2);
-
- consume("foo" + 3); // Points at the \0
- consume("foo" + 4); // Points 1 past the \0, which is legal too.
- consume("\pfoo" + 4); // Pascal strings don't have a trailing \0, but they
- // have a leading length byte, so this is fine too.
consume("foo" + kMyOperatorOverloadedEnum);
consume(kMyOperatorOverloadedEnum + "foo");
-
- #define A "foo"
- #define B "bar"
- consume(A B + sizeof(A) - 1);
}
template <typename T>
diff --git a/test/SemaCXX/struct-class-redecl.cpp b/test/SemaCXX/struct-class-redecl.cpp
index 7375319186a1..622d5a0b652a 100644
--- a/test/SemaCXX/struct-class-redecl.cpp
+++ b/test/SemaCXX/struct-class-redecl.cpp
@@ -47,14 +47,43 @@ class E;
struct F;
struct F;
-struct F {};
+struct F {}; // expected-note {{previous use}}
struct F;
+class F; // expected-warning {{previously declared as a struct}} expected-note {{did you mean struct}}
template<class U> class G; // expected-note{{previous use is here}}\
// expected-note{{did you mean struct here?}}
template<class U> struct G; // expected-warning{{struct template 'G' was previously declared as a class template}}
template<class U> struct G {}; // expected-warning{{'G' defined as a struct template here but previously declared as a class template}}
+// Declarations from contexts where the warning is disabled are entirely
+// ignored for the purpose of this warning.
+struct J;
+struct K; // expected-note {{previous use}}
+struct L;
+struct M; // expected-note {{previous use}}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmismatched-tags"
+struct H;
+class I {};
+class J;
+class K;
+class L;
+class M {};
+#pragma clang diagnostic pop
+
+class H; // expected-note {{previous use}}
+struct H; // expected-warning {{previously declared as a class}}
+
+struct I; // expected-note {{previous use}}
+class I; // expected-warning {{previously declared as a struct}}
+
+struct J;
+class K; // expected-warning {{previously declared as a struct}}
+struct L;
+class M; // expected-warning {{previously declared as a struct}}
+
/*
*** 'X' messages ***
CHECK: warning: struct 'X' was previously declared as a class
diff --git a/test/SemaCXX/subst-restrict.cpp b/test/SemaCXX/subst-restrict.cpp
new file mode 100644
index 000000000000..aab6872d8de8
--- /dev/null
+++ b/test/SemaCXX/subst-restrict.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++17 -verify %s
+
+// expected-no-diagnostics
+
+template <class T> struct add_restrict {
+ typedef T __restrict type;
+};
+
+template <class T, class V> struct is_same {
+ static constexpr bool value = false;
+};
+
+template <class T> struct is_same<T, T> {
+ static constexpr bool value = true;
+};
+
+static_assert(is_same<int & __restrict, add_restrict<int &>::type>::value, "");
+static_assert(is_same<int(), add_restrict<int()>::type>::value, "");
diff --git a/test/SemaCXX/switch-implicit-fallthrough.cpp b/test/SemaCXX/switch-implicit-fallthrough.cpp
index 9540b1ff2880..6ccac122cff7 100644
--- a/test/SemaCXX/switch-implicit-fallthrough.cpp
+++ b/test/SemaCXX/switch-implicit-fallthrough.cpp
@@ -314,3 +314,18 @@ int fallthrough_targets(int n) {
}
return n;
}
+
+int fallthrough_alt_spelling(int n) {
+ switch (n) {
+ case 0:
+ n++;
+ [[clang::fallthrough]];
+ case 1:
+ n++;
+ [[clang::__fallthrough__]];
+ case 2:
+ n++;
+ break;
+ }
+ return n;
+}
diff --git a/test/SemaCXX/thread-safety-annotations.h b/test/SemaCXX/thread-safety-annotations.h
new file mode 100644
index 000000000000..7755a1b328e7
--- /dev/null
+++ b/test/SemaCXX/thread-safety-annotations.h
@@ -0,0 +1,42 @@
+// Macros to enable testing of both variants of the thread safety analysis.
+
+#if USE_CAPABILITY
+#define LOCKABLE __attribute__((capability("mutex")))
+#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__)))
+#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
+#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__)))
+#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
+#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
+#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__)))
+#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__)))
+#else
+#define LOCKABLE __attribute__((lockable))
+#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))
+#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__)))
+#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
+#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
+#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__)))
+#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
+#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__)))
+#endif
+
+// Lock semantics only
+#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
+#define GUARDED_VAR __attribute__((guarded_var))
+#define PT_GUARDED_VAR __attribute__((pt_guarded_var))
+
+// Capabilities only
+#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__)))
+#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__)))
+#define GUARDED_BY(x) __attribute__((guarded_by(x)))
+#define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
+
+// Common
+#define SCOPED_LOCKABLE __attribute__((scoped_lockable))
+#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
+#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
+#define LOCK_RETURNED(x) __attribute__((lock_returned(x)))
+#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
+#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
diff --git a/test/SemaCXX/unavailable_aligned_allocation.cpp b/test/SemaCXX/unavailable_aligned_allocation.cpp
index 2000e0b6a319..2f0f8fe7a4b5 100644
--- a/test/SemaCXX/unavailable_aligned_allocation.cpp
+++ b/test/SemaCXX/unavailable_aligned_allocation.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify %s
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++1z -verify -DNO_ERRORS %s
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -faligned-allocation -faligned-alloc-unavailable -std=c++14 -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fexceptions -std=c++1z -verify -DNO_ERRORS %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fexceptions -faligned-allocation -faligned-alloc-unavailable -std=c++14 -verify %s
// RUN: %clang_cc1 -triple arm64-apple-ios10.0.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify -DIOS %s
// RUN: %clang_cc1 -triple arm64-apple-ios10.0.0 -fexceptions -std=c++1z -verify -DNO_ERRORS %s
// RUN: %clang_cc1 -triple arm64-apple-tvos10.0.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify -DTVOS %s
@@ -117,13 +117,80 @@ void testOveralignedCheckOS() {
// expected-error@-13 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on watchOS 4 or newer}}}
// expected-error@-14 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on watchOS 4 or newer}}}
#else
-// expected-error@-16 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on macOS 10.13 or newer}}}
-// expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.13 or newer}}}
+// expected-error@-16 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on macOS 10.14 or newer}}}
+// expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.14 or newer}}}
#endif
// expected-note@-20 2 {{if you supply your own aligned allocation functions}}
#endif
+// Test that diagnostics are produced when an unavailable aligned deallocation
+// function is called from a deleting destructor.
+struct alignas(256) OveralignedS2 {
+ int a[4];
+ virtual ~OveralignedS2();
+};
+
+OveralignedS2::~OveralignedS2() {}
+
+#ifdef NO_ERRORS
+// expected-no-diagnostics
+#else
+#if defined(IOS)
+// expected-error@-6 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on iOS 11 or newer}}}
+// expected-note@-7 {{if you supply your own aligned allocation functions}}
+#elif defined(TVOS)
+// expected-error@-9 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on tvOS 11 or newer}}}
+// expected-note@-10 {{if you supply your own aligned allocation functions}}
+#elif defined(WATCHOS)
+// expected-error@-12 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on watchOS 4 or newer}}}
+// expected-note@-13 {{if you supply your own aligned allocation functions}}
+#else
+// expected-error@-15 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.14 or newer}}}
+// expected-note@-16 {{if you supply your own aligned allocation functions}}
+#endif
+#endif
+
+void testExplicitOperatorNewDelete() {
+ void *p = operator new(128);
+ operator delete(p);
+ p = operator new[](128);
+ operator delete[](p);
+ p = __builtin_operator_new(128);
+ __builtin_operator_delete(p);
+}
+
+void testExplicitOperatorNewDeleteOveraligned() {
+ void *p = operator new(128, (std::align_val_t)64);
+ operator delete(p, (std::align_val_t)64);
+ p = operator new[](128, (std::align_val_t)64);
+ operator delete[](p, (std::align_val_t)64);
+ p = __builtin_operator_new(128, (std::align_val_t)64);
+ __builtin_operator_delete(p, (std::align_val_t)64);
+}
+
+#ifdef NO_ERRORS
+// expected-no-diagnostics
+#else
+// expected-error@-11 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}}
+// expected-note@-12 {{if you supply your own aligned allocation functions}}
+
+// expected-error@-13 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}}
+// expected-note@-14 {{if you supply your own aligned allocation functions}}
+
+// expected-error@-15 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}}
+// expected-note@-16 {{if you supply your own aligned allocation functions}}
+
+// expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}}
+// expected-note@-18 {{if you supply your own aligned allocation functions}}
+
+// expected-error@-19 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}}
+// expected-note@-20 {{if you supply your own aligned allocation functions}}
+
+// expected-error@-21 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}}
+// expected-note@-22 {{if you supply your own aligned allocation functions}}
+#endif
+
// No errors if user-defined aligned allocation functions are available.
void *operator new(std::size_t __sz, std::align_val_t) {
static char array[256];
diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp
index f620e1014c34..331a948eb6f1 100644
--- a/test/SemaCXX/uninitialized.cpp
+++ b/test/SemaCXX/uninitialized.cpp
@@ -884,8 +884,10 @@ namespace lambdas {
int x;
};
A a0([] { return a0.x; }); // ok
- void f() {
- A a1([=] { return a1.x; }); // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}}
+ void f() {
+ A a1([=] { // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}}
+ return a1.x;
+ });
A a2([&] { return a2.x; }); // ok
}
}
diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp
index 56a8a6db5b68..a6a4ceb0e535 100644
--- a/test/SemaCXX/vector.cpp
+++ b/test/SemaCXX/vector.cpp
@@ -17,14 +17,14 @@ void f0_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) {
f0(ll16e);
}
-int &f1(char16); // expected-note 2{{candidate function}}
-float &f1(longlong16); // expected-note 2{{candidate function}}
+int &f1(char16);
+float &f1(longlong16);
void f1_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) {
int &ir1 = f1(c16);
float &fr1 = f1(ll16);
- f1(c16e); // expected-error{{call to 'f1' is ambiguous}}
- f1(ll16e); // expected-error{{call to 'f1' is ambiguous}}
+ int &ir2 = f1(c16e);
+ float &fr2 = f1(ll16e);
}
void f2(char16_e); // expected-note{{no known conversion from 'longlong16_e' (vector of 2 'long long' values) to 'char16_e' (vector of 16 'char' values) for 1st argument}} \
diff --git a/test/SemaCXX/warn-comma-operator.cpp b/test/SemaCXX/warn-comma-operator.cpp
index 3192f688f1ba..0ed127b943f3 100644
--- a/test/SemaCXX/warn-comma-operator.cpp
+++ b/test/SemaCXX/warn-comma-operator.cpp
@@ -1,8 +1,16 @@
// RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -verify %s
// RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c89 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c99 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c17 -verify %s
+
+// int returning function
+int return_four() { return 5; }
+
// Test builtin operators
-void test1() {
+void test_builtin() {
int x = 0, y = 0;
for (; y < 10; x++, y++) {}
for (; y < 10; ++x, y++) {}
@@ -23,6 +31,116 @@ void test1() {
for (; y < 10; x ^= 5, ++y) {}
}
+// Test nested comma operators
+void test_nested() {
+ int x1, x2, x3;
+ int y1, *y2 = 0, y3 = 5;
+
+#if __STDC_VERSION >= 199901L
+ for (int z1 = 5, z2 = 4, z3 = 3; x1 <4; ++x1) {}
+#endif
+}
+
+// Confusing "," for "=="
+void test_compare() {
+ if (return_four(), 5) {}
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")"
+
+ if (return_four() == 5) {}
+}
+
+// Confusing "," for "+"
+int test_plus() {
+ return return_four(), return_four();
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
+
+ return return_four() + return_four();
+}
+
+// Be sure to look through parentheses
+void test_parentheses() {
+ int x, y;
+ for (x = 0; return_four(), x;) {}
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:28-[[@LINE-4]]:28}:")"
+
+ for (x = 0; (return_four()), (x) ;) {}
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")"
+}
+
+void test_increment() {
+ int x, y;
+ ++x, ++y;
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:6-[[@LINE-4]]:6}:")"
+}
+
+// Check for comma operator in conditions.
+void test_conditions(int x) {
+ x = (return_four(), x);
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:8-[[@LINE-3]]:8}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:21-[[@LINE-4]]:21}:")"
+
+ int y = (return_four(), x);
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")"
+
+ for (; return_four(), x;) {}
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
+
+ while (return_four(), x) {}
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
+
+ if (return_four(), x) {}
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")"
+
+ do { } while (return_four(), x);
+ // expected-warning@-1{{comma operator}}
+ // expected-note@-2{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")"
+}
+
+// Nested comma operator with fix-its.
+void test_nested_fixits() {
+ return_four(), return_four(), return_four(), return_four();
+ // expected-warning@-1 3{{comma operator}}
+ // expected-note@-2 3{{cast expression to void}}
+ // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:16-[[@LINE-4]]:16}:")"
+ // CHECK: fix-it:{{.*}}:{[[@LINE-5]]:18-[[@LINE-5]]:18}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-6]]:31-[[@LINE-6]]:31}:")"
+ // CHECK: fix-it:{{.*}}:{[[@LINE-7]]:33-[[@LINE-7]]:33}:"static_cast<void>("
+ // CHECK: fix-it:{{.*}}:{[[@LINE-8]]:46-[[@LINE-8]]:46}:")"
+}
+
+#ifdef __cplusplus
class S2 {
public:
void advance();
@@ -45,7 +163,7 @@ public:
};
// Test overloaded operators
-void test2() {
+void test_overloaded_operator() {
S2 x;
int y;
for (; y < 10; x++, y++) {}
@@ -67,22 +185,13 @@ void test2() {
for (; y < 10; x ^= 5, ++y) {}
}
-// Test nested comma operators
-void test3() {
- int x1, x2, x3;
- int y1, *y2 = 0, y3 = 5;
- for (int z1 = 5, z2 = 4, z3 = 3; x1 <4; ++x1) {}
-}
-
class Stream {
public:
Stream& operator<<(int);
} cout;
-int return_four() { return 5; }
-
// Confusing "," for "<<"
-void test4() {
+void test_stream() {
cout << 5 << return_four();
cout << 5, return_four();
// expected-warning@-1{{comma operator}}
@@ -91,33 +200,11 @@ void test4() {
// CHECK: fix-it:{{.*}}:{[[@LINE-4]]:12-[[@LINE-4]]:12}:")"
}
-// Confusing "," for "=="
-void test5() {
- if (return_four(), 5) {}
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")"
-
- if (return_four() == 5) {}
-}
-
-// Confusing "," for "+"
-int test6() {
- return return_four(), return_four();
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
-
- return return_four() + return_four();
-}
-
void Concat(int);
void Concat(int, int);
// Testing extra parentheses in function call
-void test7() {
+void test_overloaded_function() {
Concat((return_four() , 5));
// expected-warning@-1{{comma operator}}
// expected-note@-2{{cast expression to void}}
@@ -127,22 +214,6 @@ void test7() {
Concat(return_four() , 5);
}
-// Be sure to look through parentheses
-void test8() {
- int x, y;
- for (x = 0; return_four(), x;) {}
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:28-[[@LINE-4]]:28}:")"
-
- for (x = 0; (return_four()), (x) ;) {}
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")"
-}
-
bool DoStuff();
class S9 {
public:
@@ -151,24 +222,15 @@ public:
};
// Ignore comma operator in for-loop initializations and increments.
-void test9() {
+void test_for_loop() {
int x, y;
for (x = 0, y = 5; x < y; ++x) {}
for (x = 0; x < 10; DoStuff(), ++x) {}
for (S9 s; s.More(); s.Advance(), ++x) {}
}
-void test10() {
- int x, y;
- ++x, ++y;
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:6-[[@LINE-4]]:6}:")"
-}
-
// Ignore comma operator in templates.
-namespace test11 {
+namespace test_template {
template <bool T>
struct B { static const bool value = T; };
@@ -188,7 +250,7 @@ class Foo {
const auto X = Foo<true_type>();
}
-namespace test12 {
+namespace test_mutex {
class Mutex {
public:
Mutex();
@@ -225,54 +287,13 @@ bool get_status() {
}
}
-// Check for comma operator in conditions.
-void test13(int x) {
- x = (return_four(), x);
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:8-[[@LINE-3]]:8}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:21-[[@LINE-4]]:21}:")"
-
- int y = (return_four(), x);
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")"
-
- for (; return_four(), x;) {}
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
-
- while (return_four(), x) {}
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
-
- if (return_four(), x) {}
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")"
+// PR39375 - test cast to void to silence warnings
+template <typename T>
+void test_dependent_cast() {
+ (void)42, 0;
+ static_cast<void>(42), 0;
- do { } while (return_four(), x);
- // expected-warning@-1{{comma operator}}
- // expected-note@-2{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")"
-}
-
-// Nested comma operator with fix-its.
-void test14() {
- return_four(), return_four(), return_four(), return_four();
- // expected-warning@-1 3{{comma operator}}
- // expected-note@-2 3{{cast expression to void}}
- // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:16-[[@LINE-4]]:16}:")"
- // CHECK: fix-it:{{.*}}:{[[@LINE-5]]:18-[[@LINE-5]]:18}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-6]]:31-[[@LINE-6]]:31}:")"
- // CHECK: fix-it:{{.*}}:{[[@LINE-7]]:33-[[@LINE-7]]:33}:"static_cast<void>("
- // CHECK: fix-it:{{.*}}:{[[@LINE-8]]:46-[[@LINE-8]]:46}:")"
+ (void)T{}, 0;
+ static_cast<void>(T{}), 0;
}
+#endif // ifdef __cplusplus
diff --git a/test/SemaCXX/warn-exit-time-destructors.cpp b/test/SemaCXX/warn-exit-time-destructors.cpp
index 124576aa95b6..17b3a9406369 100644
--- a/test/SemaCXX/warn-exit-time-destructors.cpp
+++ b/test/SemaCXX/warn-exit-time-destructors.cpp
@@ -43,3 +43,8 @@ namespace test3 {
};
E e;
}
+
+namespace test4 {
+struct A { ~A(); };
+[[clang::no_destroy]] A a; // no warning
+}
diff --git a/test/SemaCXX/warn-float-conversion.cpp b/test/SemaCXX/warn-float-conversion.cpp
index a3d178622c7d..7dec4844b062 100644
--- a/test/SemaCXX/warn-float-conversion.cpp
+++ b/test/SemaCXX/warn-float-conversion.cpp
@@ -41,6 +41,32 @@ void Convert(float f, double d, long double ld) {
l = ld; //expected-warning{{conversion}}
}
+void CompoundAssignment() {
+ int x = 3;
+
+ x += 1.234; //expected-warning{{conversion}}
+ x -= -0.0; //expected-warning{{conversion}}
+ x *= 1.1f; //expected-warning{{conversion}}
+ x /= -2.2f; //expected-warning{{conversion}}
+
+ int y = x += 1.4f; //expected-warning{{conversion}}
+
+ float z = 1.1f;
+ double w = -2.2;
+
+ y += z + w; //expected-warning{{conversion}}
+}
+
+# 1 "foo.h" 3
+// ^ the following text comes from a system header file.
+#define SYSTEM_MACRO_FLOAT(x) do { (x) += 1.1; } while(0)
+# 1 "warn-float-conversion.cpp" 1
+// ^ start of a new file.
+void SystemMacro() {
+ float x = 0.0f;
+ SYSTEM_MACRO_FLOAT(x);
+}
+
void Test() {
int a1 = 10.0/2.0; //expected-warning{{conversion}}
int a2 = 1.0/2.0; //expected-warning{{conversion}}
diff --git a/test/SemaCXX/warn-loop-analysis.cpp b/test/SemaCXX/warn-loop-analysis.cpp
index 2934003848a2..324dd386292a 100644
--- a/test/SemaCXX/warn-loop-analysis.cpp
+++ b/test/SemaCXX/warn-loop-analysis.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify -std=c++17 %s
struct S {
bool stop() { return false; }
@@ -278,3 +278,24 @@ void test9() {
// Don't warn when variable is defined by the loop condition.
for (int i = 0; int x = f(i); ++i) {}
}
+
+// Don't warn when decomposition variables are in the loop condition.
+// TODO: BindingDecl's which make a copy should warn.
+void test10() {
+ int arr[] = {1, 2, 3};
+ for (auto[i, j, k] = arr;;) { }
+ for (auto[i, j, k] = arr; i < j; ++i, ++j) { }
+
+ for (auto[i, j, k] = arr; i;) { }
+ for (auto[i, j, k] = arr; i < j;) { }
+ for (auto[i, j, k] = arr; i < j; ++arr[0]) { }
+
+ int a = 1, b = 2;
+ for (auto[i, j, k] = arr; a < b;) { } // expected-warning{{variables 'a' and 'b' used in loop condition not modified in loop body}}
+ for (auto[i, j, k] = arr; a < b; ++a) { }
+
+ for (auto [i, j, k] = arr; i < a;) { }
+ for (auto[i, j, k] = arr; i < a; ++a) { }
+ for (auto[i, j, k] = arr; i < a; ++i) { }
+ for (auto[i, j, k] = arr; i < a; ++arr[0]) { }
+};
diff --git a/test/SemaCXX/warn-overloaded-virtual.cpp b/test/SemaCXX/warn-overloaded-virtual.cpp
index 6204826192d7..271416d04d55 100644
--- a/test/SemaCXX/warn-overloaded-virtual.cpp
+++ b/test/SemaCXX/warn-overloaded-virtual.cpp
@@ -130,7 +130,7 @@ namespace {
virtual int foo(int*) const;
// expected-note@-1{{type mismatch at 1st parameter ('int *' vs 'int')}}
virtual int foo(int) volatile;
- // expected-note@-1{{different qualifiers (volatile vs const)}}
+ // expected-note@-1{{different qualifiers ('volatile' vs 'const')}}
};
class B : public A {
diff --git a/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp
index e69a81b77f70..3312b5635f06 100644
--- a/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp
+++ b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -verify -Wcall-to-pure-virtual-from-ctor-dtor
struct A {
A() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'A'}}
~A() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the destructor of 'A'}}
diff --git a/test/SemaCXX/warn-shadow-in-lambdas.cpp b/test/SemaCXX/warn-shadow-in-lambdas.cpp
index b0dcd122a540..a772af049ab4 100644
--- a/test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ b/test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
+// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
void foo(int param) { // expected-note 1+ {{previous declaration is here}}
int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -79,7 +80,7 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}}
int var = 1; // expected-warning {{declaration shadows a local variable}}
};
auto f2 = [param] // expected-note {{variable 'param' is explicitly captured here}}
- (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
}
// Warn for variables defined in the capture list.
@@ -135,7 +136,7 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}}
auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
#endif
auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
- (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
}
void avoidWarningWhenRedefining() {
diff --git a/test/SemaCXX/warn-shadow.cpp b/test/SemaCXX/warn-shadow.cpp
index 3d09c786285a..f4a904b7ed37 100644
--- a/test/SemaCXX/warn-shadow.cpp
+++ b/test/SemaCXX/warn-shadow.cpp
@@ -59,13 +59,13 @@ class A {
// expected-warning-re@+1 4 {{constructor parameter 'f{{[0-4]}}' shadows the field 'f{{[0-9]}}' of 'A'}}
A(int f1, int f2, int f3, int f4, double overload_dummy) {}
- void test() {
- char *field; // expected-warning {{declaration shadows a field of 'A'}}
- char *data; // expected-warning {{declaration shadows a static data member of 'A'}}
+ void test() {
+ char *field; // expected-warning {{declaration shadows a field of 'A'}}
+ char *data; // expected-warning {{declaration shadows a static data member of 'A'}}
char *a1; // no warning
- char *a2; // no warning
- char *jj; // no warning
- char *jjj; // no warning
+ char *a2; // no warning
+ char *jj; // no warning
+ char *jjj; // no warning
}
void test2() {
@@ -196,14 +196,14 @@ void avoidWarningWhenRedefining(int b) { // expected-note {{previous definition
int k; // expected-note {{previous definition is here}}
typedef int k; // expected-error {{redefinition of 'k'}}
- using l=char; // no warning or error.
- using l=char; // no warning or error.
- typedef char l; // no warning or error.
+ using l=char; // no warning or error.
+ using l=char; // no warning or error.
+ typedef char l; // no warning or error.
typedef char n; // no warning or error.
typedef char n; // no warning or error.
- using n=char; // no warning or error.
-}
+ using n=char; // no warning or error.
+}
}
@@ -219,6 +219,49 @@ void f(int a) {
struct A {
void g(int a) {}
A() { int a; }
+ };
+}
+}
+
+namespace PR34120 {
+struct A {
+ int B; // expected-note 2 {{declared here}}
+};
+
+class C : public A {
+ void D(int B) {} // expected-warning {{parameter 'B' shadows member inherited from type 'A'}}
+ void E() {
+ extern void f(int B); // Ok
+ }
+ void F(int B); // Ok, declaration; not definition.
+ void G(int B);
+};
+
+void C::G(int B) { // expected-warning {{parameter 'B' shadows member inherited from type 'A'}}
+}
+
+class Private {
+ int B;
+};
+class Derived : Private {
+ void D(int B) {} // Ok
+};
+
+struct Static {
+ static int B;
+};
+
+struct Derived2 : Static {
+ void D(int B) {}
+};
+}
+
+int PR24718;
+enum class X { PR24718 }; // Ok, not shadowing
+
+struct PR24718_1;
+struct PR24718_2 {
+ enum {
+ PR24718_1 // Does not shadow a type.
};
-}
-}
+};
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 51535be97d97..f959beb6221e 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -6,42 +6,7 @@
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
-#define SCOPED_LOCKABLE __attribute__((scoped_lockable))
-#define GUARDED_BY(x) __attribute__((guarded_by(x)))
-#define GUARDED_VAR __attribute__((guarded_var))
-#define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
-#define PT_GUARDED_VAR __attribute__((pt_guarded_var))
-#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
-#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
-
-#if USE_CAPABILITY
-#define LOCKABLE __attribute__((capability("mutex")))
-#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__)))
-#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
-#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__)))
-#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
-#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
-#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
-#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__)))
-#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__)))
-#else
-#define LOCKABLE __attribute__((lockable))
-#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))
-#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__)))
-#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
-#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
-#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
-#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__)))
-#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
-#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__)))
-#endif
-#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__)))
-#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__)))
-#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
-#define LOCK_RETURNED(x) __attribute__((lock_returned(x)))
-#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
-#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
-
+#include "thread-safety-annotations.h"
class LOCKABLE Mutex {
public:
@@ -1789,6 +1754,13 @@ struct TestTryLock {
mu.Unlock();
}
+ void foo2_builtin_expect() {
+ if (__builtin_expect(!mu.TryLock(), false))
+ return;
+ a = 2;
+ mu.Unlock();
+ }
+
void foo3() {
bool b = mu.TryLock();
if (b) {
@@ -1797,6 +1769,14 @@ struct TestTryLock {
}
}
+ void foo3_builtin_expect() {
+ bool b = mu.TryLock();
+ if (__builtin_expect(b, true)) {
+ a = 3;
+ mu.Unlock();
+ }
+ }
+
void foo4() {
bool b = mu.TryLock();
if (!b) return;
@@ -1893,6 +1873,23 @@ struct TestTryLock {
int i = a;
mu.Unlock();
}
+
+ // Test with conditional operator
+ void foo13() {
+ if (mu.TryLock() ? 1 : 0)
+ mu.Unlock();
+ }
+
+ void foo14() {
+ if (mu.TryLock() ? 0 : 1)
+ return;
+ mu.Unlock();
+ }
+
+ void foo15() {
+ if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}}
+ mu.Unlock(); // expected-warning{{releasing mutex 'mu' that was not held}}
+ } // expected-warning{{mutex 'mu' is not held on every path through here}}
}; // end TestTrylock
} // end namespace TrylockTest
@@ -2358,6 +2355,7 @@ Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
void test() {
Foo foo;
Foo *fooArray;
+ Foo &(*fooFuncPtr)();
Bar bar;
int a;
int b;
@@ -2394,6 +2392,10 @@ void test() {
(a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
(a > 0 ? fooArray[1] : fooArray[b]).a = 0;
(a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
+
+ fooFuncPtr().mu_.Lock();
+ fooFuncPtr().a = 0;
+ fooFuncPtr().mu_.Unlock();
}
@@ -2621,6 +2623,274 @@ void Foo::test5() {
} // end namespace ReleasableScopedLock
+namespace RelockableScopedLock {
+
+class SCOPED_LOCKABLE RelockableExclusiveMutexLock {
+public:
+ RelockableExclusiveMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
+ ~RelockableExclusiveMutexLock() EXCLUSIVE_UNLOCK_FUNCTION();
+
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+};
+
+struct SharedTraits {};
+struct ExclusiveTraits {};
+
+class SCOPED_LOCKABLE RelockableMutexLock {
+public:
+ RelockableMutexLock(Mutex *mu, SharedTraits) SHARED_LOCK_FUNCTION(mu);
+ RelockableMutexLock(Mutex *mu, ExclusiveTraits) EXCLUSIVE_LOCK_FUNCTION(mu);
+ ~RelockableMutexLock() UNLOCK_FUNCTION();
+
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+
+ void ReaderLock() SHARED_LOCK_FUNCTION();
+ void ReaderUnlock() UNLOCK_FUNCTION();
+
+ void PromoteShared() UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
+ void DemoteExclusive() UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
+};
+
+Mutex mu;
+int x GUARDED_BY(mu);
+
+void print(int);
+
+void relock() {
+ RelockableExclusiveMutexLock scope(&mu);
+ x = 2;
+ scope.Unlock();
+
+ x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+
+ scope.Lock();
+ x = 4;
+}
+
+void relockExclusive() {
+ RelockableMutexLock scope(&mu, SharedTraits{});
+ print(x);
+ x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+ scope.ReaderUnlock();
+
+ print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
+
+ scope.Lock();
+ print(x);
+ x = 4;
+
+ scope.DemoteExclusive();
+ print(x);
+ x = 5; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+}
+
+void relockShared() {
+ RelockableMutexLock scope(&mu, ExclusiveTraits{});
+ print(x);
+ x = 2;
+ scope.Unlock();
+
+ print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
+
+ scope.ReaderLock();
+ print(x);
+ x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+
+ scope.PromoteShared();
+ print(x);
+ x = 5;
+}
+
+void doubleUnlock() {
+ RelockableExclusiveMutexLock scope(&mu);
+ scope.Unlock();
+ scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
+}
+
+void doubleLock1() {
+ RelockableExclusiveMutexLock scope(&mu);
+ scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
+}
+
+void doubleLock2() {
+ RelockableExclusiveMutexLock scope(&mu);
+ scope.Unlock();
+ scope.Lock();
+ scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
+}
+
+void directUnlock() {
+ RelockableExclusiveMutexLock scope(&mu);
+ mu.Unlock();
+ // Debatable that there is no warning. Currently we don't track in the scoped
+ // object whether it is active, but just check if the contained locks can be
+ // reacquired. Here they can, because mu has been unlocked manually.
+ scope.Lock();
+}
+
+void directRelock() {
+ RelockableExclusiveMutexLock scope(&mu);
+ scope.Unlock();
+ mu.Lock();
+ // Similarly debatable that there is no warning.
+ scope.Unlock();
+}
+
+// Doesn't make a lot of sense, just making sure there is no crash.
+void destructLock() {
+ RelockableExclusiveMutexLock scope(&mu);
+ scope.~RelockableExclusiveMutexLock();
+ scope.Lock(); // Should be UB, so we don't really care.
+}
+
+class SCOPED_LOCKABLE MemberLock {
+public:
+ MemberLock() EXCLUSIVE_LOCK_FUNCTION(mutex);
+ ~MemberLock() UNLOCK_FUNCTION(mutex);
+ void Lock() EXCLUSIVE_LOCK_FUNCTION(mutex);
+ Mutex mutex;
+};
+
+void relockShared2() {
+ MemberLock lock;
+ lock.Lock(); // expected-warning {{acquiring mutex 'lock.mutex' that is already held}}
+}
+
+class SCOPED_LOCKABLE WeirdScope {
+private:
+ Mutex *other;
+
+public:
+ WeirdScope(Mutex *mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
+ void unlock() EXCLUSIVE_UNLOCK_FUNCTION() EXCLUSIVE_UNLOCK_FUNCTION(other);
+ void lock() EXCLUSIVE_LOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(other);
+ ~WeirdScope() EXCLUSIVE_UNLOCK_FUNCTION();
+
+ void requireOther() EXCLUSIVE_LOCKS_REQUIRED(other);
+};
+
+void relockWeird() {
+ WeirdScope scope(&mu);
+ x = 1;
+ scope.unlock(); // expected-warning {{releasing mutex 'scope.other' that was not held}}
+ x = 2; // \
+ // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+ scope.requireOther(); // \
+ // expected-warning {{calling function 'requireOther' requires holding mutex 'scope.other' exclusively}}
+ scope.lock(); // expected-note {{mutex acquired here}}
+ x = 3;
+ scope.requireOther();
+} // expected-warning {{mutex 'scope.other' is still held at the end of function}}
+
+} // end namespace RelockableScopedLock
+
+
+namespace ScopedUnlock {
+
+class SCOPED_LOCKABLE MutexUnlock {
+public:
+ MutexUnlock(Mutex *mu) EXCLUSIVE_UNLOCK_FUNCTION(mu);
+ ~MutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
+
+ void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
+ void Unlock() EXCLUSIVE_LOCK_FUNCTION();
+};
+
+class SCOPED_LOCKABLE ReaderMutexUnlock {
+public:
+ ReaderMutexUnlock(Mutex *mu) SHARED_UNLOCK_FUNCTION(mu);
+ ~ReaderMutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
+
+ void Lock() EXCLUSIVE_UNLOCK_FUNCTION();
+ void Unlock() EXCLUSIVE_LOCK_FUNCTION();
+};
+
+Mutex mu;
+int x GUARDED_BY(mu);
+bool c;
+void print(int);
+
+void simple() EXCLUSIVE_LOCKS_REQUIRED(mu) {
+ x = 1;
+ MutexUnlock scope(&mu);
+ x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+}
+
+void simpleShared() SHARED_LOCKS_REQUIRED(mu) {
+ print(x);
+ ReaderMutexUnlock scope(&mu);
+ print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
+}
+
+void innerUnlock() {
+ MutexLock outer(&mu);
+ if (x == 0) {
+ MutexUnlock inner(&mu);
+ x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+ }
+ x = 2;
+}
+
+void innerUnlockShared() {
+ ReaderMutexLock outer(&mu);
+ if (x == 0) {
+ ReaderMutexUnlock inner(&mu);
+ print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}}
+ }
+ print(x);
+}
+
+void manual() EXCLUSIVE_LOCKS_REQUIRED(mu) {
+ MutexUnlock scope(&mu);
+ scope.Lock();
+ x = 2;
+ scope.Unlock();
+ x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+}
+
+void join() EXCLUSIVE_LOCKS_REQUIRED(mu) {
+ MutexUnlock scope(&mu);
+ if (c) {
+ scope.Lock(); // expected-note{{mutex acquired here}}
+ }
+ // expected-warning@+1{{mutex 'mu' is not held on every path through here}}
+ scope.Lock();
+}
+
+void doubleLock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
+ MutexUnlock scope(&mu);
+ scope.Lock();
+ scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}}
+}
+
+void doubleUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
+ MutexUnlock scope(&mu);
+ scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}}
+}
+
+class SCOPED_LOCKABLE MutexLockUnlock {
+public:
+ MutexLockUnlock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_UNLOCK_FUNCTION(mu1) EXCLUSIVE_LOCK_FUNCTION(mu2);
+ ~MutexLockUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
+
+ void Release() EXCLUSIVE_UNLOCK_FUNCTION();
+ void Acquire() EXCLUSIVE_LOCK_FUNCTION();
+};
+
+Mutex other;
+void fn() EXCLUSIVE_LOCKS_REQUIRED(other);
+
+void lockUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) {
+ MutexLockUnlock scope(&mu, &other);
+ fn();
+ x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}}
+}
+
+} // end namespace ScopedUnlock
+
+
namespace TrylockFunctionTest {
class Foo {
@@ -4078,6 +4348,14 @@ public:
mu_.Unlock();
}
+ void unlockExclusive() EXCLUSIVE_UNLOCK_FUNCTION(mu_) {
+ mu_.Unlock();
+ }
+
+ void unlockShared() SHARED_UNLOCK_FUNCTION(mu_) {
+ mu_.ReaderUnlock();
+ }
+
// Check failure to lock.
void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
mu2_.Lock();
@@ -4840,6 +5118,8 @@ public:
void operator+(const Foo& f);
void operator[](const Foo& g);
+
+ void operator()();
};
template<class T>
@@ -4857,8 +5137,23 @@ void destroy(Foo&& f);
void operator/(const Foo& f, const Foo& g);
void operator*(const Foo& f, const Foo& g);
+// Test constructors.
+struct FooRead {
+ FooRead(const Foo &);
+};
+struct FooWrite {
+ FooWrite(Foo &);
+};
+// Test variadic functions
+template<typename... T>
+void copyVariadic(T...) {}
+template<typename... T>
+void writeVariadic(T&...) {}
+template<typename... T>
+void readVariadic(const T&...) {}
+void copyVariadicC(int, ...);
class Bar {
public:
@@ -4890,6 +5185,14 @@ public:
read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ copyVariadic(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
+ readVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ writeVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ copyVariadicC(1, foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
+
+ FooRead reader(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ FooWrite writer(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+
mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
@@ -4908,6 +5211,7 @@ public:
// expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
// expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
+ foo(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
(*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}
@@ -5331,3 +5635,106 @@ namespace ReturnScopedLockable {
return ptr->f();
}
}
+
+namespace PR38640 {
+void f() {
+ // Self-referencing assignment previously caused an infinite loop when thread
+ // safety analysis was enabled.
+ int &i = i; // expected-warning {{reference 'i' is not yet bound to a value when used within its own initialization}}
+}
+}
+
+namespace Derived_Smart_Pointer {
+template <class T>
+class SmartPtr_Derived : public SmartPtr<T> {};
+
+class Foo {
+public:
+ SmartPtr_Derived<Mutex> mu_;
+ int a GUARDED_BY(mu_);
+ int b GUARDED_BY(mu_.get());
+ int c GUARDED_BY(*mu_);
+
+ void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
+ void Unlock() UNLOCK_FUNCTION(mu_);
+
+ void test0() {
+ a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
+ b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
+ c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
+ }
+
+ void test1() {
+ Lock();
+ a = 1;
+ b = 1;
+ c = 1;
+ Unlock();
+ }
+};
+
+class Bar {
+ SmartPtr_Derived<Foo> foo;
+
+ void test0() {
+ foo->a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
+ (*foo).b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
+ foo.get()->c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
+ }
+
+ void test1() {
+ foo->Lock();
+ foo->a = 1;
+ foo->Unlock();
+
+ foo->mu_->Lock();
+ foo->b = 1;
+ foo->mu_->Unlock();
+
+ MutexLock lock(foo->mu_.get());
+ foo->c = 1;
+ }
+};
+
+class PointerGuard {
+ Mutex mu1;
+ Mutex mu2;
+ SmartPtr_Derived<int> i GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
+
+ void test0() {
+ i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
+ *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} \
+ // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
+
+ }
+
+ void test1() {
+ mu1.Lock();
+
+ i.get();
+ *i = 2; // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}}
+
+ mu1.Unlock();
+ }
+
+ void test2() {
+ mu2.Lock();
+
+ i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
+ *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}}
+
+ mu2.Unlock();
+ }
+
+ void test3() {
+ mu1.Lock();
+ mu2.Lock();
+
+ i.get();
+ *i = 2;
+
+ mu2.Unlock();
+ mu1.Unlock();
+ }
+};
+}
diff --git a/test/SemaCXX/warn-thread-safety-negative.cpp b/test/SemaCXX/warn-thread-safety-negative.cpp
index f831010293b6..9a495fa6cff9 100644
--- a/test/SemaCXX/warn-thread-safety-negative.cpp
+++ b/test/SemaCXX/warn-thread-safety-negative.cpp
@@ -1,40 +1,18 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
-#define LOCKABLE __attribute__ ((lockable))
-#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
-#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
-#define GUARDED_VAR __attribute__ ((guarded_var))
-#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
-#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
-#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
-#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
-#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
-#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
-#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))
-#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__)))
-#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
-#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
-#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
-#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
-#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
-#define EXCLUSIVE_LOCKS_REQUIRED(...) \
- __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
-#define SHARED_LOCKS_REQUIRED(...) \
- __attribute__ ((shared_locks_required(__VA_ARGS__)))
-#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
-
-
-class __attribute__((lockable)) Mutex {
+#include "thread-safety-annotations.h"
+
+class LOCKABLE Mutex {
public:
- void Lock() __attribute__((exclusive_lock_function));
- void ReaderLock() __attribute__((shared_lock_function));
- void Unlock() __attribute__((unlock_function));
- bool TryLock() __attribute__((exclusive_trylock_function(true)));
- bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
- void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void ReaderLock() SHARED_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+ bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
+ bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
// for negative capabilities
const Mutex& operator!() const { return *this; }
diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp
index ac357e8dae37..198d02e1f076 100644
--- a/test/SemaCXX/warn-thread-safety-parsing.cpp
+++ b/test/SemaCXX/warn-thread-safety-parsing.cpp
@@ -572,11 +572,11 @@ UnlockableMu ab_var_arg_bad_5 ACQUIRED_BEFORE(mu_ab); // \
// takes zero or more arguments, all locks (vars/fields)
-void elf_function() EXCLUSIVE_LOCK_FUNCTION();
+void elf_function() EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
void elf_function_args() EXCLUSIVE_LOCK_FUNCTION(mu1, mu2);
-int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION();
+int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
int elf_testfn(int y) {
int x EXCLUSIVE_LOCK_FUNCTION() = y; // \
@@ -591,7 +591,8 @@ class ElfFoo {
private:
int test_field EXCLUSIVE_LOCK_FUNCTION(); // \
// expected-warning {{'exclusive_lock_function' attribute only applies to functions}}
- void test_method() EXCLUSIVE_LOCK_FUNCTION();
+ void test_method() EXCLUSIVE_LOCK_FUNCTION(); // \
+ // expected-warning {{'exclusive_lock_function' attribute without capability arguments refers to 'this', but 'ElfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}}
};
class EXCLUSIVE_LOCK_FUNCTION() ElfTestClass { // \
@@ -644,11 +645,11 @@ int elf_function_bad_7() EXCLUSIVE_LOCK_FUNCTION(0); // \
// takes zero or more arguments, all locks (vars/fields)
-void slf_function() SHARED_LOCK_FUNCTION();
+void slf_function() SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
void slf_function_args() SHARED_LOCK_FUNCTION(mu1, mu2);
-int slf_testfn(int y) SHARED_LOCK_FUNCTION();
+int slf_testfn(int y) SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
int slf_testfn(int y) {
int x SHARED_LOCK_FUNCTION() = y; // \
@@ -666,7 +667,8 @@ class SlfFoo {
private:
int test_field SHARED_LOCK_FUNCTION(); // \
// expected-warning {{'shared_lock_function' attribute only applies to functions}}
- void test_method() SHARED_LOCK_FUNCTION();
+ void test_method() SHARED_LOCK_FUNCTION(); // \
+ // expected-warning {{'shared_lock_function' attribute without capability arguments refers to 'this', but 'SlfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}}
};
class SHARED_LOCK_FUNCTION() SlfTestClass { // \
@@ -717,14 +719,16 @@ int slf_function_bad_7() SHARED_LOCK_FUNCTION(0); // \
// takes a mandatory boolean or integer argument specifying the retval
// plus an optional list of locks (vars/fields)
-void etf_function() __attribute__((exclusive_trylock_function)); // \
+void etf_function() __attribute__((exclusive_trylock_function)); // \
// expected-error {{'exclusive_trylock_function' attribute takes at least 1 argument}}
void etf_function_args() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu2);
-void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1);
+void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \
+ // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
-int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1);
+int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); // \
+ // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
int etf_testfn(int y) {
int x EXCLUSIVE_TRYLOCK_FUNCTION(1) = y; // \
@@ -739,7 +743,8 @@ class EtfFoo {
private:
int test_field EXCLUSIVE_TRYLOCK_FUNCTION(1); // \
// expected-warning {{'exclusive_trylock_function' attribute only applies to functions}}
- void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1);
+ void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \
+ // expected-warning {{'exclusive_trylock_function' attribute without capability arguments refers to 'this', but 'EtfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}}
};
class EXCLUSIVE_TRYLOCK_FUNCTION(1) EtfTestClass { // \
@@ -760,7 +765,8 @@ int etf_function_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, &mu1);
int etf_function_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, muRef);
int etf_function_7() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu());
int etf_functetfn_8() EXCLUSIVE_TRYLOCK_FUNCTION(1, muPointer);
-int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true);
+int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true); // \
+ // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
// illegal attribute arguments
@@ -795,9 +801,11 @@ void stf_function() __attribute__((shared_trylock_function)); // \
void stf_function_args() SHARED_TRYLOCK_FUNCTION(1, mu2);
-void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1);
+void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1); // \
+ // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
-int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1);
+int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); // \
+ // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
int stf_testfn(int y) {
int x SHARED_TRYLOCK_FUNCTION(1) = y; // \
@@ -816,7 +824,8 @@ class StfFoo {
private:
int test_field SHARED_TRYLOCK_FUNCTION(1); // \
// expected-warning {{'shared_trylock_function' attribute only applies to functions}}
- void test_method() SHARED_TRYLOCK_FUNCTION(1);
+ void test_method() SHARED_TRYLOCK_FUNCTION(1); // \
+ // expected-warning {{'shared_trylock_function' attribute without capability arguments refers to 'this', but 'StfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}}
};
class SHARED_TRYLOCK_FUNCTION(1) StfTestClass { // \
@@ -834,7 +843,8 @@ int stf_function_5() SHARED_TRYLOCK_FUNCTION(1, &mu1);
int stf_function_6() SHARED_TRYLOCK_FUNCTION(1, muRef);
int stf_function_7() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu());
int stf_function_8() SHARED_TRYLOCK_FUNCTION(1, muPointer);
-int stf_function_9() SHARED_TRYLOCK_FUNCTION(true);
+int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); // \
+ // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
// illegal attribute arguments
@@ -863,11 +873,14 @@ int stf_function_bad_6() SHARED_TRYLOCK_FUNCTION(1, umu); // \
// takes zero or more arguments, all locks (vars/fields)
-void uf_function() UNLOCK_FUNCTION();
+void uf_function() UNLOCK_FUNCTION(); // \
+ // expected-warning {{'unlock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
+
void uf_function_args() UNLOCK_FUNCTION(mu1, mu2);
-int uf_testfn(int y) UNLOCK_FUNCTION();
+int uf_testfn(int y) UNLOCK_FUNCTION(); //\
+ // expected-warning {{'unlock_function' attribute without capability arguments can only be applied to non-static methods of a class}}
int uf_testfn(int y) {
int x UNLOCK_FUNCTION() = y; // \
@@ -882,7 +895,8 @@ class UfFoo {
private:
int test_field UNLOCK_FUNCTION(); // \
// expected-warning {{'unlock_function' attribute only applies to functions}}
- void test_method() UNLOCK_FUNCTION();
+ void test_method() UNLOCK_FUNCTION(); // \
+ // expected-warning {{'unlock_function' attribute without capability arguments refers to 'this', but 'UfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}}
};
class NO_THREAD_SAFETY_ANALYSIS UfTestClass { // \
@@ -1250,6 +1264,36 @@ struct Foomgoper {
}
};
+template <typename Mutex>
+struct SCOPED_LOCKABLE SLTemplateClass {
+ ~SLTemplateClass() UNLOCK_FUNCTION();
+};
+
+template <typename Mutex>
+struct NonSLTemplateClass {
+ ~NonSLTemplateClass() UNLOCK_FUNCTION(); // \
+ // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'NonSLTemplateClass' isn't annotated with 'capability' or 'scoped_lockable' attribute}}
+};
+
+template <>
+struct SLTemplateClass<int> {};
+
+template <typename Mutex>
+struct SLTemplateDerived : public SLTemplateClass<Mutex> {
+ ~SLTemplateDerived() UNLOCK_FUNCTION();
+};
+
+// FIXME: warn on template instantiation.
+template struct SLTemplateDerived<int>;
+
+struct SLDerived1 : public SLTemplateClass<double> {
+ ~SLDerived1() UNLOCK_FUNCTION();
+};
+
+struct SLDerived2 : public SLTemplateClass<int> {
+ ~SLDerived2() UNLOCK_FUNCTION(); // \
+ // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'SLDerived2' isn't annotated with 'capability' or 'scoped_lockable' attribute}}
+};
//-----------------------------------------------------
// Parsing of member variables and function parameters
@@ -1525,4 +1569,4 @@ namespace CRASH_POST_R301735 {
Mutex mu_;
};
}
-#endif \ No newline at end of file
+#endif
diff --git a/test/SemaCXX/warn-thread-safety-verbose.cpp b/test/SemaCXX/warn-thread-safety-verbose.cpp
index 4e19f30bf2c3..2f892cd1e175 100644
--- a/test/SemaCXX/warn-thread-safety-verbose.cpp
+++ b/test/SemaCXX/warn-thread-safety-verbose.cpp
@@ -1,37 +1,15 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-verbose -Wno-thread-safety-negative -fcxx-exceptions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-verbose -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-verbose -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s
-#define LOCKABLE __attribute__ ((lockable))
-#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
-#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
-#define GUARDED_VAR __attribute__ ((guarded_var))
-#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
-#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
-#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
-#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
-#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
-#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
-#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))
-#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__)))
-#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
-#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
-#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
-#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
-#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
-#define EXCLUSIVE_LOCKS_REQUIRED(...) \
- __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
-#define SHARED_LOCKS_REQUIRED(...) \
- __attribute__ ((shared_locks_required(__VA_ARGS__)))
-#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
+#include "thread-safety-annotations.h"
-
-class __attribute__((lockable)) Mutex {
+class LOCKABLE Mutex {
public:
- void Lock() __attribute__((exclusive_lock_function));
- void ReaderLock() __attribute__((shared_lock_function));
- void Unlock() __attribute__((unlock_function));
- bool TryLock() __attribute__((exclusive_trylock_function(true)));
- bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
- void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void ReaderLock() SHARED_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+ bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
+ bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
// for negative capabilities
const Mutex& operator!() const { return *this; }
diff --git a/test/SemaCXX/warn-unsequenced-cxx17.cpp b/test/SemaCXX/warn-unsequenced-cxx17.cpp
new file mode 100644
index 000000000000..3c221fb8d656
--- /dev/null
+++ b/test/SemaCXX/warn-unsequenced-cxx17.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wno-unused %s
+
+void test() {
+ int xs[10];
+ int *p = xs;
+ // expected-no-diagnostics
+ p[(long long unsigned)(p = 0)]; // ok
+}
diff --git a/test/SemaCXX/warn-unsequenced.cpp b/test/SemaCXX/warn-unsequenced.cpp
index 9e8a5b46c218..6d4468cabfe5 100644
--- a/test/SemaCXX/warn-unsequenced.cpp
+++ b/test/SemaCXX/warn-unsequenced.cpp
@@ -81,6 +81,7 @@ void test() {
int *p = xs;
a = *(a++, p); // ok
a = a++ && a; // ok
+ p[(long long unsigned)(p = 0)]; // expected-warning {{unsequenced modification and access to 'p'}}
A *q = &agg1;
(q = &agg2)->y = q->x; // expected-warning {{unsequenced modification and access to 'q'}}
diff --git a/test/SemaCXX/warn-unused-result.cpp b/test/SemaCXX/warn-unused-result.cpp
index 88f5ab1e85c0..f1de4618a741 100644
--- a/test/SemaCXX/warn-unused-result.cpp
+++ b/test/SemaCXX/warn-unused-result.cpp
@@ -33,6 +33,36 @@ void test() {
const S &s4 = g1();
}
+void testSubstmts(int i) {
+ switch (i) {
+ case 0:
+ f(); // expected-warning {{ignoring return value}}
+ default:
+ f(); // expected-warning {{ignoring return value}}
+ }
+
+ if (i)
+ f(); // expected-warning {{ignoring return value}}
+ else
+ f(); // expected-warning {{ignoring return value}}
+
+ while (i)
+ f(); // expected-warning {{ignoring return value}}
+
+ do
+ f(); // expected-warning {{ignoring return value}}
+ while (i);
+
+ for (f(); // expected-warning {{ignoring return value}}
+ ;
+ f() // expected-warning {{ignoring return value}}
+ )
+ f(); // expected-warning {{ignoring return value}}
+
+ f(), // expected-warning {{ignoring return value}}
+ (void)f();
+}
+
struct X {
int foo() __attribute__((warn_unused_result));
};
@@ -206,3 +236,13 @@ void f() {
(void)++p;
}
} // namespace
+
+namespace PR39837 {
+[[clang::warn_unused_result]] int f(int);
+
+void g() {
+ int a[2];
+ for (int b : a)
+ f(b); // expected-warning {{ignoring return value}}
+}
+} // namespace PR39837
diff --git a/test/SemaObjC/arc-objc-lifetime-conflict.m b/test/SemaObjC/arc-objc-lifetime-conflict.m
index 218950ca7b50..e8064b110ce0 100644
--- a/test/SemaObjC/arc-objc-lifetime-conflict.m
+++ b/test/SemaObjC/arc-objc-lifetime-conflict.m
@@ -1,19 +1,19 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-arc -fobjc-runtime-has-weak %s -emit-llvm -o - | FileCheck %s
// CHECK: bitcast {{.*}} %self_weak_s_w_s
-// CHECK-NEXT: objc_destroyWeak
+// CHECK-NEXT: llvm.objc.destroyWeak
// CHECK-NEXT: bitcast {{.*}} %self_strong_w_s
-// CHECK-NEXT: objc_storeStrong
+// CHECK-NEXT: llvm.objc.storeStrong
// CHECK-NEXT: bitcast {{.*}} %self_weak_s
-// CHECK-NEXT: objc_destroyWeak
+// CHECK-NEXT: llvm.objc.destroyWeak
// CHECK-NEXT: bitcast {{.*}} %self_weak_s3
-// CHECK-NEXT: objc_destroyWeak
+// CHECK-NEXT: llvm.objc.destroyWeak
// CHECK-NEXT: bitcast {{.*}} %self_strong3
-// CHECK-NEXT: objc_storeStrong
+// CHECK-NEXT: llvm.objc.storeStrong
// CHECK-NEXT: bitcast {{.*}} %self_strong2
-// CHECK-NEXT: objc_storeStrong
+// CHECK-NEXT: llvm.objc.storeStrong
// CHECK-NEXT: bitcast {{.*}} %self_strong
-// CHECK-NEXT: objc_storeStrong
+// CHECK-NEXT: llvm.objc.storeStrong
@interface NSObject
@end
@interface A : NSObject
diff --git a/test/SemaObjC/arc-repeated-weak.mm b/test/SemaObjC/arc-repeated-weak.mm
index d153eb9a52eb..6c7a6292f992 100644
--- a/test/SemaObjC/arc-repeated-weak.mm
+++ b/test/SemaObjC/arc-repeated-weak.mm
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
-// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++14 -Warc-repeated-use-of-weak -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++14 -Warc-repeated-use-of-weak -verify %s
@interface Test {
@public
@@ -462,6 +462,21 @@ void foo() {
NSString * t2 = NSBundle.foo2.prop;
use(NSBundle.foo2.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}}
+ decltype([NSBundle2.foo2 weakProp]) t3;
+ decltype(NSBundle2.foo2.weakProp) t4;
+ __typeof__(NSBundle2.foo2.weakProp) t5;
+}
+
+void testAuto() {
+ auto __weak wp = NSBundle2.foo2.weakProp;
+}
+
+void testLambdaCaptureInit() {
+ [capture(NSBundle2.foo2.weakProp)] {} ();
+}
+
+void testAutoNew() {
+ auto p = new auto(NSBundle2.foo2.weakProp);
}
// This used to crash in the constructor of WeakObjectProfileTy when a
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index fcac798ff2d1..b87f294eef53 100644
--- a/test/SemaObjC/arc.m
+++ b/test/SemaObjC/arc.m
@@ -410,7 +410,7 @@ void test16(void) {
[v test16_6: 0];
}
-@class Test17; // expected-note 2{{forward declaration of class here}}
+@class Test17; // expected-note 3{{forward declaration of class here}}
@protocol Test17p
- (void) test17;
+ (void) test17;
diff --git a/test/SemaObjC/attr-availability.m b/test/SemaObjC/attr-availability.m
index da1a664e9122..eb25175c5a4a 100644
--- a/test/SemaObjC/attr-availability.m
+++ b/test/SemaObjC/attr-availability.m
@@ -5,7 +5,7 @@
- (void)proto_method __attribute__((availability(macosx,introduced=10.1,deprecated=10.2))); // expected-note 2 {{'proto_method' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
- // expected-note@+2 2 {{'partial_proto_method' has been explicitly marked partial here}}
+// expected-note@+2 2 {{'partial_proto_method' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
- (void)partial_proto_method __attribute__((availability(macosx,introduced=10.8)));
@end
@@ -13,7 +13,7 @@
@interface A <P>
- (void)method __attribute__((availability(macosx,introduced=10.1,deprecated=10.2))); // expected-note {{'method' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
- // expected-note@+2 2 {{'partialMethod' has been explicitly marked partial here}}
+// expected-note@+2 2 {{'partialMethod' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
- (void)partialMethod __attribute__((availability(macosx,introduced=10.8)));
@@ -137,8 +137,8 @@ id NSNibOwner, topNibObjects;
@interface PartialI <PartialProt>
#ifdef WARN_PARTIAL
-// expected-note@+3{{marked partial here}}
-// expected-note@+3{{marked partial here}}
+// expected-note@+3{{'partialMethod' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
+// expected-note@+3{{'partialMethod' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
- (void)partialMethod __attribute__((availability(macosx,introduced=10.8)));
+ (void)partialMethod __attribute__((availability(macosx,introduced=10.8)));
@@ -147,12 +147,12 @@ id NSNibOwner, topNibObjects;
@interface PartialI ()
- (void)ipartialMethod1 __attribute__((availability(macosx,introduced=10.8)));
#if defined(WARN_PARTIAL)
- // expected-note@+2 {{'ipartialMethod2' has been explicitly marked partial here}}
+// expected-note@+2 {{'ipartialMethod2' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
- (void)ipartialMethod2 __attribute__((availability(macosx,introduced=10.8)));
+ (void)ipartialMethod1 __attribute__((availability(macosx,introduced=10.8)));
#if defined(WARN_PARTIAL)
- // expected-note@+2 {{'ipartialMethod2' has been explicitly marked partial here}}
+// expected-note@+2 {{'ipartialMethod2' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
+ (void)ipartialMethod2 __attribute__((availability(macosx,introduced=10.8)));
@end
@@ -190,7 +190,7 @@ void partialfun(PartialI* a) {
}
#if defined(WARN_PARTIAL)
- // expected-note@+2 2 {{'PartialI2' has been explicitly marked partial here}}
+// expected-note@+2 2 {{'PartialI2' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
#endif
__attribute__((availability(macosx, introduced = 10.8))) @interface PartialI2
@end
@@ -314,8 +314,8 @@ __attribute__((objc_root_class))
#if defined(WARN_PARTIAL)
int fn_10_5() __attribute__((availability(macosx, introduced=10.5)));
-int fn_10_7() __attribute__((availability(macosx, introduced=10.7))); // expected-note{{marked partial here}}
-int fn_10_8() __attribute__((availability(macosx, introduced=10.8))) { // expected-note{{marked partial here}}
+int fn_10_7() __attribute__((availability(macosx, introduced=10.7))); // expected-note{{'fn_10_7' has been marked as being introduced in macOS 10.7 here, but the deployment target is macOS 10.5.0}}
+int fn_10_8() __attribute__((availability(macosx, introduced=10.8))) { // expected-note{{'fn_10_8' has been marked as being introduced in macOS 10.8 here, but the deployment target is macOS 10.5.0}}
return fn_10_7();
}
diff --git a/test/SemaObjC/call-unavailable-init-in-self.m b/test/SemaObjC/call-unavailable-init-in-self.m
new file mode 100644
index 000000000000..fa6f670cc997
--- /dev/null
+++ b/test/SemaObjC/call-unavailable-init-in-self.m
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -x objective-c -verify -fobjc-arc %s
+
+@interface NSObject
+
++ (instancetype)new;
++ (instancetype)alloc;
+
+@end
+
+@interface Sub: NSObject
+
+- (instancetype)init __attribute__((unavailable)); // expected-note 4 {{'init' has been explicitly marked unavailable here}}
+
+- (void)notImplemented __attribute__((unavailable)); // expected-note {{'notImplemented' has been explicitly marked unavailable here}}
+
+@end
+
+@implementation Sub
+
++ (Sub *)create {
+ return [[self alloc] init];
+}
+
++ (Sub *)create2 {
+ return [self new];
+}
+
++ (Sub *)create3 {
+ return [Sub new];
+}
+
+- (instancetype) init {
+ return self;
+}
+
+- (void)reportUseOfUnimplemented {
+ [self notImplemented]; // expected-error {{'notImplemented' is unavailable}}
+}
+
+@end
+
+@interface SubClassContext: Sub
+@end
+
+@implementation SubClassContext
+
+- (void)subClassContext {
+ (void)[[Sub alloc] init]; // expected-error {{'init' is unavailable}}
+ (void)[Sub new]; // expected-error {{'new' is unavailable}}
+}
+
+@end
+
+void unrelatedContext() {
+ (void)[[Sub alloc] init]; // expected-error {{'init' is unavailable}}
+ (void)[Sub new]; // expected-error {{'new' is unavailable}}
+}
+
+@interface X @end
+
+@interface X (Foo)
+-(void)meth __attribute__((unavailable));
+@end
+
+@implementation X (Foo)
+-(void)meth {}
+-(void)call_it { [self meth]; }
+@end
diff --git a/test/SemaObjC/enum-fixed-type.m b/test/SemaObjC/enum-fixed-type.m
index 37d2810a504b..88c895a33982 100644
--- a/test/SemaObjC/enum-fixed-type.m
+++ b/test/SemaObjC/enum-fixed-type.m
@@ -1,9 +1,14 @@
// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -xc %s
#if !__has_feature(objc_fixed_enum)
# error Enumerations with a fixed underlying type are not supported
#endif
+#if !__has_extension(cxx_fixed_enum)
+# error Enumerations with a fixed underlying type are not supported
+#endif
+
typedef long Integer;
typedef enum : Integer { Enumerator1, Enumerator2 } Enumeration;
diff --git a/test/SemaObjC/externally-retained-no-arc.m b/test/SemaObjC/externally-retained-no-arc.m
new file mode 100644
index 000000000000..a548d6b88ddb
--- /dev/null
+++ b/test/SemaObjC/externally-retained-no-arc.m
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -verify
+
+@interface NSWidget @end
+
+__attribute__((objc_externally_retained)) void f(NSWidget *p) { // expected-warning{{'objc_externally_retained' attribute ignored}}
+ __attribute__((objc_externally_retained)) NSWidget *w; // expected-warning{{'objc_externally_retained' attribute ignored}}
+}
diff --git a/test/SemaObjC/externally-retained.m b/test/SemaObjC/externally-retained.m
new file mode 100644
index 000000000000..2708fc8eefe1
--- /dev/null
+++ b/test/SemaObjC/externally-retained.m
@@ -0,0 +1,114 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-runtime=macosx-10.13.0 -fblocks -fobjc-arc %s -verify
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fobjc-runtime=macosx-10.13.0 -fblocks -fobjc-arc -xobjective-c++ %s -verify
+
+#define EXT_RET __attribute__((objc_externally_retained))
+
+@interface ObjCTy
+@end
+
+void test1() {
+ EXT_RET int a; // expected-warning{{'objc_externally_retained' can only be applied to}}
+ EXT_RET __weak ObjCTy *b; // expected-warning{{'objc_externally_retained' can only be applied to}}
+ EXT_RET __weak int (^c)(); // expected-warning{{'objc_externally_retained' can only be applied to}}
+
+ EXT_RET int (^d)() = ^{return 0;};
+ EXT_RET ObjCTy *e = 0;
+ EXT_RET __strong ObjCTy *f = 0;
+
+ e = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ f = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ d = ^{ return 0; }; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+}
+
+void test2(ObjCTy *a);
+
+void test2(ObjCTy *a) EXT_RET {
+ a = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+}
+
+EXT_RET ObjCTy *test3; // expected-warning{{'objc_externally_retained' can only be applied to}}
+
+@interface X // expected-warning{{defined without specifying a base class}} expected-note{{add a super class}}
+-(void)m: (ObjCTy *) p;
+@end
+@implementation X
+-(void)m: (ObjCTy *) p EXT_RET {
+ p = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+}
+@end
+
+void test4() {
+ __attribute__((objc_externally_retained(0))) ObjCTy *a; // expected-error{{'objc_externally_retained' attribute takes no arguments}}
+}
+
+void test5(ObjCTy *first, __strong ObjCTy *second) EXT_RET {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0; // fine
+}
+
+void test6(ObjCTy *first,
+ __strong ObjCTy *second) EXT_RET {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+}
+
+__attribute__((objc_root_class)) @interface Y @end
+
+@implementation Y
+- (void)test7:(__strong ObjCTy *)first
+ withThird:(ObjCTy *)second EXT_RET {
+ first = 0;
+ second = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+}
+@end
+
+void (^blk)(ObjCTy *, ObjCTy *) =
+ ^(__strong ObjCTy *first, ObjCTy *second) EXT_RET {
+ first = 0;
+ second = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+};
+
+void test8(EXT_RET ObjCTy *x) {} // expected-warning{{'objc_externally_retained' attribute only applies to variables}}
+
+#pragma clang attribute ext_ret.push(__attribute__((objc_externally_retained)), apply_to=any(function, block, objc_method))
+void test9(ObjCTy *first, __strong ObjCTy *second) {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+}
+void (^test10)(ObjCTy *first, ObjCTy *second) = ^(ObjCTy *first, __strong ObjCTy *second) {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+};
+__attribute__((objc_root_class)) @interface Test11 @end
+@implementation Test11
+-(void)meth: (ObjCTy *)first withSecond:(__strong ObjCTy *)second {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+}
++(void)othermeth: (ObjCTy *)first withSecond:(__strong ObjCTy *)second {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+}
+@end
+
+#if __cplusplus
+class Test12 {
+ void inline_member(ObjCTy *first, __strong ObjCTy *second) {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+ }
+ static void static_inline_member(ObjCTy *first, __strong ObjCTy *second) {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+ }
+};
+#endif
+
+void test13(ObjCTy *first, __weak ObjCTy *second, __unsafe_unretained ObjCTy *third, __strong ObjCTy *fourth) {
+ first = 0; // expected-error{{variable declared with 'objc_externally_retained' cannot be modified in ARC}}
+ second = 0;
+ third = 0;
+ fourth = 0;
+}
+
+#pragma clang attribute ext_ret.pop
diff --git a/test/SemaObjC/format-strings-oslog.m b/test/SemaObjC/format-strings-oslog.m
index 15c88e1b3792..e8b1d64f07c1 100644
--- a/test/SemaObjC/format-strings-oslog.m
+++ b/test/SemaObjC/format-strings-oslog.m
@@ -39,6 +39,10 @@ void test_os_log_format(const char *pc, int i, void *p, void *buf) {
struct { char data[0x100]; } toobig;
__builtin_os_log_format(buf, "%s", toobig); // expected-error {{os_log() argument 2 is too big (256 bytes, max 255)}}
+
+ __builtin_os_log_format(buf, "%{mask.xyz}s", "abc");
+ __builtin_os_log_format(buf, "%{mask.}s", "abc"); // expected-error {{mask type size must be between 1-byte and 8-bytes}}
+ __builtin_os_log_format(buf, "%{mask.abcdefghi}s", "abc"); // expected-error {{mask type size must be between 1-byte and 8-bytes}}
}
// Test os_log_format primitive with ObjC string literal format argument.
diff --git a/test/SemaObjC/infer-availability-from-init.m b/test/SemaObjC/infer-availability-from-init.m
new file mode 100644
index 000000000000..f9996ec70877
--- /dev/null
+++ b/test/SemaObjC/infer-availability-from-init.m
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx-10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
+
+__attribute__((objc_root_class))
+@interface NSObject
++(instancetype)new;
+-(instancetype)init;
+@end
+
+@interface MyObject : NSObject
+-(instancetype)init __attribute__((unavailable)); // expected-note{{'init' has been explicitly marked unavailable here}}
+@end
+
+void usemyobject() {
+ [MyObject new]; // expected-error{{'new' is unavailable}}
+}
+
+@interface MyOtherObject : NSObject
++(instancetype)init __attribute__((unavailable));
++(instancetype)new;
+@end
+
+void usemyotherobject() {
+ [MyOtherObject new]; // no error; new is overrideen.
+}
+
+@interface NotGoodOverride : NSObject
++(instancetype)init __attribute__((unavailable));
+-(instancetype)new;
++(instancetype)new: (int)x;
+@end
+
+void usenotgoodoverride() {
+ [NotGoodOverride new]; // no error
+}
+
+@interface NotNSObject
++(instancetype)new;
+-(instancetype)init;
+@end
+
+@interface NotMyObject : NotNSObject
+-(instancetype)init __attribute__((unavailable));
+@end
+
+void usenotmyobject() {
+ [NotMyObject new]; // no error; this isn't NSObject
+}
+
+@interface FromSelf : NSObject
+-(instancetype)init __attribute__((unavailable)); // expected-note {{'init' has been explicitly marked unavailable here}}
++(FromSelf*)another_one;
+@end
+
+@implementation FromSelf
++(FromSelf*)another_one {
+ [self new]; // expected-error{{'new' is unavailable}}
+}
+@end
diff --git a/test/SemaObjC/multiple-method-names-in-class-self.m b/test/SemaObjC/multiple-method-names-in-class-self.m
new file mode 100644
index 000000000000..47e1306d3837
--- /dev/null
+++ b/test/SemaObjC/multiple-method-names-in-class-self.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -Wobjc-multiple-method-names -x objective-c -verify %s
+// RUN: %clang_cc1 -Wobjc-multiple-method-names -x objective-c -verify -fobjc-arc %s
+// expected-no-diagnostics
+
+@interface NSObj
+
++ (instancetype) alloc;
+
++ (_Nonnull instancetype) globalObject;
+
+@end
+
+@interface SelfAllocReturn: NSObj
+
+- (instancetype)initWithFoo:(int)x;
+
+@end
+
+@interface SelfAllocReturn2: NSObj
+
+- (instancetype)initWithFoo:(SelfAllocReturn *)x;
+
+@end
+
+@implementation SelfAllocReturn
+
+- (instancetype)initWithFoo:(int)x {
+ return self;
+}
+
++ (instancetype) thingWithFoo:(int)x {
+ return [[self alloc] initWithFoo: x];
+}
+
++ (void) initGlobal {
+ (void)[[self globalObject] initWithFoo: 20];
+}
+
+@end
diff --git a/test/SemaObjC/nullability.m b/test/SemaObjC/nullability.m
index 93f4d1d4994a..885ced692ebc 100644
--- a/test/SemaObjC/nullability.m
+++ b/test/SemaObjC/nullability.m
@@ -36,14 +36,14 @@ __attribute__((objc_root_class))
- (nonnull NSFoo **)invalidMethod1; // expected-error{{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'NSFoo **'}}
// expected-note@-1{{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'NSFoo **'}}
-- (nonnull NSFoo * _Nullable)conflictingMethod1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
-- (nonnull NSFoo * _Nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
+- (nonnull NSFoo * _Nullable)conflictingMethod1; // expected-error{{nullability specifier 'nonnull' conflicts with existing specifier '_Nullable'}}
+- (nonnull NSFoo * _Nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier 'nonnull'}}
@property(nonnull,retain) NSFoo *property1;
@property(nullable,assign) NSFoo ** invalidProperty1; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}
// expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}}
-@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}}
-@property(retain,nonnull) NSFoo * _Nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
+@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty1; // expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier '_Nullable'}}
+@property(retain,nonnull) NSFoo * _Nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier 'nonnull'}}
@property(null_unspecified,retain,nullable) NSFoo *conflictingProperty3; // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'null_unspecified'}}
@property(nullable,retain,nullable) NSFoo *redundantProperty3; // expected-warning{{duplicate nullability specifier 'nullable'}}
@@ -53,8 +53,8 @@ __attribute__((objc_root_class))
@property(nonnull,retain) NSFoo *property2;
@property(nullable,assign) NSFoo ** invalidProperty2; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}
// expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}}
-@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty2; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}}
-@property(retain,nonnull) NSFoo * _Nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
+@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty2; // expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier '_Nullable'}}
+@property(retain,nonnull) NSFoo * _Nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier 'nonnull'}}
@end
void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, _Nonnull NSBar *bar) {
@@ -157,7 +157,7 @@ __attribute__((objc_root_class))
- (nullable instancetype)returnMe;
+ (nullable instancetype)returnInstanceOfMe;
-- (nonnull instancetype _Nullable)initWithBlah2:(nonnull id)blah; // expected-error {{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
+- (nonnull instancetype _Nullable)initWithBlah2:(nonnull id)blah; // expected-error {{nullability specifier 'nonnull' conflicts with existing specifier '_Nullable'}}
- (instancetype _Nullable)returnMe2;
+ (_Nonnull instancetype)returnInstanceOfMe2;
@end
diff --git a/test/SemaObjC/property-assign-on-object-type.m b/test/SemaObjC/property-assign-on-object-type.m
new file mode 100644
index 000000000000..6125bb21ed3c
--- /dev/null
+++ b/test/SemaObjC/property-assign-on-object-type.m
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wobjc-property-assign-on-object-type %s
+
+@interface Foo @end
+@protocol Prot @end
+
+@interface Bar
+@property(assign, readonly) Foo* o1; // expected-warning {{'assign' property of object type may become a dangling reference; consider using 'unsafe_unretained'}}
+@property(unsafe_unretained, readonly) Foo* o2;
+
+@property(assign) Class classProperty;
+@property(assign) Class<Prot> classWithProtocolProperty;
+@property(assign) int s1;
+@property(assign) int* s2;
+@end
+
+@interface Bar ()
+@property(readwrite) Foo* o1;
+@property(readwrite) Foo* o2;
+@end
diff --git a/test/SemaObjC/property-deprecated-warning.m b/test/SemaObjC/property-deprecated-warning.m
index 0591c78fba4a..a1e971118b2c 100644
--- a/test/SemaObjC/property-deprecated-warning.m
+++ b/test/SemaObjC/property-deprecated-warning.m
@@ -9,7 +9,7 @@ typedef signed char BOOL;
@property(nonatomic,assign) id ptarget __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{property 'ptarget' is declared deprecated here}} expected-note {{'ptarget' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{'partialPtarget' has been explicitly marked partial here}}
+// expected-note@+2 {{'partialPtarget' has been marked as being introduced in iOS 5.0 here, but the deployment target is iOS 3.0.0}}
#endif
@property(nonatomic,assign) id partialPtarget __attribute__((availability(ios,introduced=5.0)));
@end
@@ -24,7 +24,7 @@ typedef signed char BOOL;
@property(nonatomic,assign) id target __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{property 'target' is declared deprecated here}} expected-note {{'setTarget:' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{'setPartialTarget:' has been explicitly marked partial here}}
+// expected-note@+2 {{'setPartialTarget:' has been marked as being introduced in iOS 5.0 here, but the deployment target is iOS 3.0.0}}
#endif
@property(nonatomic,assign) id partialTarget __attribute__((availability(ios,introduced=5.0)));
@end
@@ -40,7 +40,8 @@ typedef signed char BOOL;
// expected-note 2 {{'setDep_target:' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 2 {{'partial_dep_target' has been explicitly marked partial here}} expected-note@+2 2 {{'setPartial_dep_target:' has been explicitly marked partial here}}
+// expected-note@+3 2 {{'partial_dep_target' has been marked as being introduced in iOS 5.0 here, but the deployment target is iOS 3.0.0}}
+// expected-note@+2 2 {{'setPartial_dep_target:' has been marked as being introduced in iOS 5.0 here, but the deployment target is iOS 3.0.0}}
#endif
@property(nonatomic,assign) id partial_dep_target __attribute__((availability(ios,introduced=5.0)));
@end
@@ -100,12 +101,12 @@ typedef signed char BOOL;
@property(setter=setNewDelegate:,assign) id delegate __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{'setNewDelegate:' has been explicitly marked deprecated here}} expected-note {{property 'delegate' is declared deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{'partialIsEnabled' has been explicitly marked partial here}}
+// expected-note@+2 {{'partialIsEnabled' has been marked as being introduced in iOS 5.0 here, but the deployment target is iOS 3.0.0}}
#endif
@property(getter=partialIsEnabled,assign) BOOL partialEnabled __attribute__((availability(ios,introduced=5.0)));
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{'partialSetNewDelegate:' has been explicitly marked partial here}}
+// expected-note@+2 {{'partialSetNewDelegate:' has been marked as being introduced in iOS 5.0 here, but the deployment target is iOS 3.0.0}}
#endif
@property(setter=partialSetNewDelegate:,assign) id partialDelegate __attribute__((availability(ios,introduced=5.0)));
@end
diff --git a/test/SemaObjC/property-in-class-extension-1.m b/test/SemaObjC/property-in-class-extension-1.m
index 67b57e5faec5..6215f70abc10 100644
--- a/test/SemaObjC/property-in-class-extension-1.m
+++ b/test/SemaObjC/property-in-class-extension-1.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-weak -verify -Weverything %s
-// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-weak -fsyntax-only -verify -Weverything %s
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-weak -verify -Wproperty-attribute-mismatch %s
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-weak -fsyntax-only -verify -Wproperty-attribute-mismatch %s
// rdar://12103400
@class NSString;
diff --git a/test/SemaObjC/protocol-expr-neg-1.m b/test/SemaObjC/protocol-expr-neg-1.m
index 26cdac70ae8d..f659b30046e1 100644
--- a/test/SemaObjC/protocol-expr-neg-1.m
+++ b/test/SemaObjC/protocol-expr-neg-1.m
@@ -12,7 +12,7 @@
int main()
{
Protocol *proto = @protocol(p1);
- Protocol *fproto = @protocol(fproto); // expected-warning {{@protocol is using a forward protocol declaration of 'fproto'}}
+ Protocol *fproto = @protocol(fproto); // expected-error {{@protocol is using a forward protocol declaration of 'fproto'}}
Protocol *pp = @protocol(i); // expected-error {{cannot find protocol declaration for 'i'}}
Protocol *p1p = @protocol(cl); // expected-error {{cannot find protocol declaration for 'cl'}}
}
@@ -26,9 +26,9 @@ int main()
@end
int doesConform(id foo) {
- return [foo conformsToProtocol:@protocol(TestProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of 'TestProtocol'}}
+ return [foo conformsToProtocol:@protocol(TestProtocol)]; // expected-error {{@protocol is using a forward protocol declaration of 'TestProtocol'}}
}
int doesConformSuper(id foo) {
- return [foo conformsToProtocol:@protocol(SuperProtocol)]; // expected-warning {{@protocol is using a forward protocol declaration of 'SuperProtocol'}}
+ return [foo conformsToProtocol:@protocol(SuperProtocol)]; // expected-error {{@protocol is using a forward protocol declaration of 'SuperProtocol'}}
}
diff --git a/test/SemaObjC/unguarded-availability-new.m b/test/SemaObjC/unguarded-availability-new.m
index 474730f0d362..ed61bf977958 100644
--- a/test/SemaObjC/unguarded-availability-new.m
+++ b/test/SemaObjC/unguarded-availability-new.m
@@ -68,15 +68,15 @@
void previouslyAvailable() AVAILABLE_PREV;
#ifdef WARN_PREV
- // expected-note@-2 {{'previouslyAvailable' has been explicitly marked partial here}}
+// expected-note@-2 {{'previouslyAvailable' has been marked as being introduced}}
#endif
void currentlyAvailable() AVAILABLE_CURRENT;
#ifdef WARN_CURRENT
- // expected-note@-2 {{'currentlyAvailable' has been explicitly marked partial here}}
+// expected-note@-2 {{'currentlyAvailable' has been marked as being introduced}}
#endif
void willBeAvailabile() AVAILABLE_NEXT;
#ifndef NO_WARNING
- // expected-note@-2 {{'willBeAvailabile' has been explicitly marked partial here}}
+// expected-note@-2 {{'willBeAvailabile' has been marked as being introduced in}}
#endif
#ifdef TEST_FUNC_CURRENT
@@ -91,7 +91,7 @@ void willBeAvailabile() AVAILABLE_NEXT;
typedef int AVAILABLE_NEXT new_int;
#ifndef NO_WARNING
- // expected-note@-2 {{'new_int' has been explicitly marked partial here}}
+// expected-note@-2 {{'new_int' has been marked as being introduced in}}
#endif
FUNC_AVAILABLE new_int x;
#ifndef NO_WARNING
diff --git a/test/SemaObjC/unguarded-availability.m b/test/SemaObjC/unguarded-availability.m
index 39c631097985..c185a363cd68 100644
--- a/test/SemaObjC/unguarded-availability.m
+++ b/test/SemaObjC/unguarded-availability.m
@@ -1,18 +1,18 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx-10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
-// RUN: %clang_cc1 -xobjective-c++ -std=c++11 -DOBJCPP -triple x86_64-apple-macosx-10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
+// RUN: %clang_cc1 -xobjective-c++ -std=c++11 -DOBJCPP -triple x86_64-apple-macosx10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
#define AVAILABLE_10_0 __attribute__((availability(macos, introduced = 10.0)))
#define AVAILABLE_10_11 __attribute__((availability(macos, introduced = 10.11)))
#define AVAILABLE_10_12 __attribute__((availability(macos, introduced = 10.12)))
-typedef int AVAILABLE_10_12 new_int; // expected-note + {{marked partial here}}
+typedef int AVAILABLE_10_12 new_int; // expected-note + {{'new_int' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
-int func_10_11() AVAILABLE_10_11; // expected-note 8 {{'func_10_11' has been explicitly marked partial here}}
+int func_10_11() AVAILABLE_10_11; // expected-note 8 {{'func_10_11' has been marked as being introduced in macOS 10.11 here, but the deployment target is macOS 10.9.0}}
#ifdef OBJCPP
-// expected-note@+2 6 {{marked partial here}}
+// expected-note@+2 6 {{'func_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
#endif
-int func_10_12() AVAILABLE_10_12; // expected-note 7 {{'func_10_12' has been explicitly marked partial here}}
+int func_10_12() AVAILABLE_10_12; // expected-note 7 {{'func_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
int func_10_0() AVAILABLE_10_0;
@@ -61,11 +61,11 @@ void star_case() {
}
}
-typedef int int_10_11 AVAILABLE_10_11; // expected-note {{'int_10_11' has been explicitly marked partial here}}
+typedef int int_10_11 AVAILABLE_10_11; // expected-note {{'int_10_11' has been marked as being introduced in macOS 10.11 here, but the deployment target is macOS 10.9.0}}
#ifdef OBJCPP
-// expected-note@+2 {{marked partial here}}
+// expected-note@+2 {{'int_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
#endif
-typedef int int_10_12 AVAILABLE_10_12; // expected-note 2 {{'int_10_12' has been explicitly marked partial here}}
+typedef int int_10_12 AVAILABLE_10_12; // expected-note 2 {{'int_10_12' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
void use_typedef() {
int_10_11 x; // expected-warning{{'int_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'int_10_11' in an @available check to silence this warning}}
@@ -106,10 +106,10 @@ int protected_scope() {
struct S {
int m1;
- int m2 __attribute__((availability(macos, introduced = 10.12))); // expected-note{{marked partial here}}
+ int m2 __attribute__((availability(macos, introduced = 10.12))); // expected-note{{has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
struct Nested {
- int nested_member __attribute__((availability(macos, introduced = 10.12))); // expected-note{{marked partial here}}
+ int nested_member __attribute__((availability(macos, introduced = 10.12))); // expected-note{{'nested_member' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
} n;
};
@@ -139,9 +139,9 @@ void (^topLevelBlockDecl)() = ^ {
AVAILABLE_10_12
__attribute__((objc_root_class))
-@interface InterWithProp // expected-note 2 {{marked partial here}}
+@interface InterWithProp // expected-note 2 {{'InterWithProp' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
@property(class) int x;
-+ (void) setX: (int)newX AVAILABLE_10_12; // expected-note{{marked partial here}}
++ (void) setX: (int)newX AVAILABLE_10_12; // expected-note{{'setX:' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
@end
void test_property(void) {
int y = InterWithProp.x; // expected-warning{{'InterWithProp' is only available on macOS 10.12 or newer}} expected-note{{@available}}
@@ -150,7 +150,7 @@ void test_property(void) {
__attribute__((objc_root_class))
@interface Subscriptable
-- (id)objectAtIndexedSubscript:(int)sub AVAILABLE_10_12; // expected-note{{marked partial here}}
+- (id)objectAtIndexedSubscript:(int)sub AVAILABLE_10_12; // expected-note{{'objectAtIndexedSubscript:' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
@end
void test_at(Subscriptable *x) {
@@ -196,7 +196,7 @@ int instantiate_template() {
}
template <class>
-int with_availability_attr() AVAILABLE_10_11 { // expected-note 2 {{marked partial here}}
+int with_availability_attr() AVAILABLE_10_11 { // expected-note 2 {{'with_availability_attr<int>' has been marked as being introduced in macOS 10.11 here, but the deployment target is macOS 10.9.0}}
return 0;
}
@@ -244,7 +244,7 @@ struct InStruct { // expected-note{{annotate 'InStruct' with an availability att
};
#ifdef OBJCPP
-static constexpr int AVAILABLE_10_12 SomeConstexprValue = 2; // expected-note{{marked partial here}}
+static constexpr int AVAILABLE_10_12 SomeConstexprValue = 2; // expected-note{{'SomeConstexprValue' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
typedef enum { // expected-note{{annotate anonymous enum with an availability attribute}}
SomeValue = SomeConstexprValue // expected-warning{{'SomeConstexprValue' is only available on macOS 10.12 or newer}}
} SomeEnum;
@@ -268,7 +268,7 @@ void with_local_struct() {
// Avoid the warning on protocol requirements.
AVAILABLE_10_12
-@protocol NewProtocol // expected-note {{'NewProtocol' has been explicitly marked partial here}}
+@protocol NewProtocol // expected-note {{'NewProtocol' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
@end
@protocol ProtocolWithNewProtocolRequirement <NewProtocol> // expected-note {{annotate 'ProtocolWithNewProtocolRequirement' with an availability attribute to silence}}
@@ -291,7 +291,7 @@ AVAILABLE_10_12
typedef enum {
AK_Dodo __attribute__((availability(macos, deprecated=10.3))), // expected-note 3 {{marked deprecated here}}
AK_Cat __attribute__((availability(macos, introduced=10.4))),
- AK_CyborgCat __attribute__((availability(macos, introduced=10.12))), // expected-note {{marked partial here}}
+ AK_CyborgCat __attribute__((availability(macos, introduced=10.12))), // expected-note {{'AK_CyborgCat' has been marked as being introduced in macOS 10.12 here, but the deployment target is macOS 10.9.0}}
} Animals;
void switchAnimals(Animals a) {
diff --git a/test/SemaObjCXX/blocks.mm b/test/SemaObjCXX/blocks.mm
index bdd5538e92be..5f7352417201 100644
--- a/test/SemaObjCXX/blocks.mm
+++ b/test/SemaObjCXX/blocks.mm
@@ -76,21 +76,27 @@ namespace N1 {
}
// Make sure we successfully instantiate the copy constructor of a
-// __block variable's type.
+// __block variable's type when the variable is captured by an escaping block.
namespace N2 {
template <int n> struct A {
A() {}
A(const A &other) {
int invalid[-n]; // expected-error 2 {{array with a negative size}}
}
+ void m() {}
};
+ typedef void (^BlockFnTy)();
+ void func(BlockFnTy);
+
void test1() {
__block A<1> x; // expected-note {{requested here}}
+ func(^{ x.m(); });
}
template <int n> void test2() {
__block A<n> x; // expected-note {{requested here}}
+ func(^{ x.m(); });
}
template void test2<2>();
}
diff --git a/test/SemaObjCXX/foreach.mm b/test/SemaObjCXX/foreach.mm
index 99f5d0ce55ee..e39815d3e9cd 100644
--- a/test/SemaObjCXX/foreach.mm
+++ b/test/SemaObjCXX/foreach.mm
@@ -14,6 +14,14 @@ void f(NSArray *a) {
for (auto thisKey : keys) { } // expected-warning{{'auto' deduced as 'id' in declaration of 'thisKey'}}
}
+void for_init_stmt() {
+ for (id keys; id key : keys) {} // expected-warning{{extension}} expected-error{{not supported}}
+}
+template<typename T> void for_init_stmt_tmpl() {
+ for (T keys; id key : keys) {} // expected-warning{{extension}} expected-error{{not supported}}
+}
+template void for_init_stmt_tmpl<id>(); // expected-note {{in instantiation of}}
+
template<typename Collection>
void ft(Collection col) {
for (id x : col) { }
diff --git a/test/SemaObjCXX/noescape.mm b/test/SemaObjCXX/noescape.mm
index 9432a3a48a0b..efa2a76d668a 100644
--- a/test/SemaObjCXX/noescape.mm
+++ b/test/SemaObjCXX/noescape.mm
@@ -8,6 +8,7 @@ struct S {
void m();
};
+void escapingFunc0(BlockTy);
void noescapeFunc0(id, __attribute__((noescape)) BlockTy);
void noescapeFunc1(id, [[clang::noescape]] BlockTy);
void noescapeFunc2(__attribute__((noescape)) int *); // expected-note {{previous declaration is here}}
@@ -127,3 +128,27 @@ __attribute__((objc_root_class))
-(void) m1:(int*) p {
}
@end
+
+struct S6 {
+ S6();
+ S6(const S6 &) = delete; // expected-note 3 {{'S6' has been explicitly marked deleted here}}
+ int f;
+};
+
+void test1() {
+ id a;
+ // __block variables that are not captured by escaping blocks don't
+ // necessitate having accessible copy constructors.
+ __block S6 b0;
+ __block S6 b1; // expected-error {{call to deleted constructor of 'S6'}}
+ __block S6 b2; // expected-error {{call to deleted constructor of 'S6'}}
+ __block S6 b3; // expected-error {{call to deleted constructor of 'S6'}}
+
+ noescapeFunc0(a, ^{ (void)b0; });
+ escapingFunc0(^{ (void)b1; });
+ {
+ noescapeFunc0(a, ^{ (void)b0; (void)b1; });
+ }
+ noescapeFunc0(a, ^{ escapingFunc0(^{ (void)b2; }); });
+ escapingFunc0(^{ noescapeFunc0(a, ^{ (void)b3; }); });
+}
diff --git a/test/SemaObjCXX/warn-thread-safety-analysis.mm b/test/SemaObjCXX/warn-thread-safety-analysis.mm
new file mode 100644
index 000000000000..262ab7d108a2
--- /dev/null
+++ b/test/SemaObjCXX/warn-thread-safety-analysis.mm
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta -Wno-objc-root-class %s
+
+class __attribute__((lockable)) Lock {
+public:
+ void Acquire() __attribute__((exclusive_lock_function())) {}
+ void Release() __attribute__((unlock_function())) {}
+};
+
+class __attribute__((scoped_lockable)) AutoLock {
+public:
+ AutoLock(Lock &lock) __attribute__((exclusive_lock_function(lock)))
+ : lock_(lock) {
+ lock.Acquire();
+ }
+ ~AutoLock() __attribute__((unlock_function())) { lock_.Release(); }
+
+private:
+ Lock &lock_;
+};
+
+@interface MyInterface {
+@private
+ Lock lock_;
+ int value_;
+}
+
+- (void)incrementValue;
+- (void)decrementValue;
+
+@end
+
+@implementation MyInterface
+
+- (void)incrementValue {
+ AutoLock lock(lock_);
+ value_ += 1;
+}
+
+- (void)decrementValue {
+ lock_.Acquire(); // expected-note{{mutex acquired here}}
+ value_ -= 1;
+} // expected-warning{{mutex 'self->lock_' is still held at the end of function}}
+
+@end
diff --git a/test/SemaOpenCL/access-qualifier.cl b/test/SemaOpenCL/access-qualifier.cl
index 35e838b1bf83..1753a1dbefdd 100644
--- a/test/SemaOpenCL/access-qualifier.cl
+++ b/test/SemaOpenCL/access-qualifier.cl
@@ -60,7 +60,7 @@ kernel void k10(read_only Int img){} // expected-error {{access qualifier can on
kernel void k11(read_only write_only image1d_t i){} // expected-error{{multiple access qualifiers}}
-kernel void k12(read_only read_only image1d_t i){} // expected-error{{multiple access qualifiers}}
+kernel void k12(read_only read_only image1d_t i){} // expected-warning {{duplicate 'read_only' declaration specifier}}
#if __OPENCL_C_VERSION__ >= 200
kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}}
@@ -78,3 +78,33 @@ kernel void k14(read_only pipe int p) {
#if __OPENCL_C_VERSION__ < 200
kernel void test_image3d_wo(write_only image3d_t img) {} // expected-error {{use of type '__write_only image3d_t' requires cl_khr_3d_image_writes extension to be enabled}}
#endif
+
+#if __OPENCL_C_VERSION__ >= 200
+kernel void read_write_twice_typedef(read_write img1d_rw i){} // expected-warning {{duplicate 'read_write' declaration specifier}}
+// expected-note@-74 {{previously declared 'read_write' here}}
+
+kernel void pipe_ro_twice(read_only read_only pipe int i){} // expected-warning{{duplicate 'read_only' declaration specifier}}
+// Conflicting access qualifiers
+kernel void pipe_ro_twice_tw(read_write read_only read_only pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}}
+kernel void pipe_ro_wo(read_only write_only pipe int i){} // expected-error{{multiple access qualifiers}}
+
+typedef read_only pipe int ROPipeInt;
+kernel void pipe_ro_twice_typedef(read_only ROPipeInt i){} // expected-warning{{duplicate 'read_only' declaration specifier}}
+// expected-note@-2 {{previously declared 'read_only' here}}
+
+kernel void pass_ro_typedef_to_wo(ROPipeInt p) {
+ myPipeWrite(p); // expected-error {{passing 'ROPipeInt' (aka 'read_only pipe int') to parameter of incompatible type 'write_only pipe int'}}
+ // expected-note@-25 {{passing argument to parameter here}}
+}
+#endif
+
+kernel void read_only_twice_typedef(__read_only img1d_ro i){} // expected-warning {{duplicate '__read_only' declaration specifier}}
+// expected-note@-95 {{previously declared 'read_only' here}}
+
+kernel void read_only_twice_default(read_only img1d_ro_default img){} // expected-warning {{duplicate 'read_only' declaration specifier}}
+// expected-note@-101 {{previously declared 'read_only' here}}
+
+kernel void image_wo_twice(write_only __write_only image1d_t i){} // expected-warning {{duplicate '__write_only' declaration specifier}}
+kernel void image_wo_twice_typedef(write_only img1d_wo i){} // expected-warning {{duplicate 'write_only' declaration specifier}}
+// expected-note@-103 {{previously declared 'write_only' here}}
+
diff --git a/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl b/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
index 73e29e7879d5..619ecc4e4771 100644
--- a/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
+++ b/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DCONSTANT -cl-std=CL2.0
// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGLOBAL -cl-std=CL2.0
// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGENERIC -cl-std=CL2.0
+// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DCONSTANT -cl-std=c++
+// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGLOBAL -cl-std=c++
+// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGENERIC -cl-std=c++
/* OpenCLC v2.0 adds a set of restrictions for conversions between pointers to
* different address spaces, mainly described in Sections 6.5.5 and 6.5.6.
@@ -17,71 +20,111 @@
*/
#ifdef GENERIC
-#define AS generic
-#define AS_COMP local
-#define AS_INCOMP constant
+#define AS __generic
+#define AS_COMP __local
+#define AS_INCOMP __constant
#endif
#ifdef GLOBAL
-#define AS global
-#define AS_COMP global
-#define AS_INCOMP local
+#define AS __global
+#define AS_COMP __global
+#define AS_INCOMP __local
#endif
#ifdef CONSTANT
-#define AS constant
-#define AS_COMP constant
-#define AS_INCOMP global
+#define AS __constant
+#define AS_COMP __constant
+#define AS_INCOMP __global
#endif
-void f_glob(global int *arg_glob) {}
+void f_glob(__global int *arg_glob) {}
#ifndef GLOBAL
-// expected-note@-2{{passing argument to parameter 'arg_glob' here}}
+#if !__OPENCL_CPP_VERSION__
+// expected-note@-3{{passing argument to parameter 'arg_glob' here}}
+#else
+// expected-note-re@-5{{candidate function not viable: address space mismatch in 1st argument ('__{{generic|constant}} int *'), parameter type must be '__global int *'}}
+#endif
#endif
-void f_loc(local int *arg_loc) {
-} // expected-note@-1{{passing argument to parameter 'arg_loc' here}}
+void f_loc(__local int *arg_loc) {}
+#if !__OPENCL_CPP_VERSION__
+// expected-note@-2{{passing argument to parameter 'arg_loc' here}}
+#else
+// expected-note-re@-4{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic|constant}} int *'), parameter type must be '__local int *'}}
+#endif
-void f_const(constant int *arg_const) {}
+void f_const(__constant int *arg_const) {}
#ifndef CONSTANT
-// expected-note@-2{{passing argument to parameter 'arg_const' here}}
+#if !__OPENCL_CPP_VERSION__
+// expected-note@-3{{passing argument to parameter 'arg_const' here}}
+#else
+// expected-note-re@-5{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic}} int *'), parameter type must be '__constant int *'}}
+#endif
#endif
-void f_priv(private int *arg_priv) {
-} // expected-note@-1{{passing argument to parameter 'arg_priv' here}}
+void f_priv(__private int *arg_priv) {}
+#if !__OPENCL_CPP_VERSION__
+// expected-note@-2{{passing argument to parameter 'arg_priv' here}}
+#else
+// expected-note-re@-4{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic|constant}} int *'), parameter type must be 'int *'}}
+#endif
-void f_gen(generic int *arg_gen) {}
+void f_gen(__generic int *arg_gen) {}
#ifdef CONSTANT
-// expected-note@-2{{passing argument to parameter 'arg_gen' here}}
+#if !__OPENCL_CPP_VERSION__
+// expected-note@-3{{passing argument to parameter 'arg_gen' here}}
+#else
+// expected-note@-5{{candidate function not viable: address space mismatch in 1st argument ('__constant int *'), parameter type must be '__generic int *'}}
+#endif
#endif
-void test_conversion(global int *arg_glob, local int *arg_loc,
- constant int *arg_const, private int *arg_priv,
- generic int *arg_gen) {
+void test_conversion(__global int *arg_glob, __local int *arg_loc,
+ __constant int *arg_const, __private int *arg_priv,
+ __generic int *arg_gen) {
AS int *var_init1 = arg_glob;
#ifdef CONSTANT
-// expected-error@-2{{initializing '__constant int *' with an expression of type '__global int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-3{{initializing '__constant int *' with an expression of type '__global int *' changes address space of pointer}}
+#else
+// expected-error@-5{{cannot initialize a variable of type '__constant int *' with an lvalue of type '__global int *'}}
+#endif
#endif
AS int *var_init2 = arg_loc;
#ifndef GENERIC
-// expected-error-re@-2{{initializing '__{{global|constant}} int *' with an expression of type '__local int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{initializing '__{{global|constant}} int *' with an expression of type '__local int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{cannot initialize a variable of type '__{{global|constant}} int *' with an lvalue of type '__local int *'}}
+#endif
#endif
AS int *var_init3 = arg_const;
#ifndef CONSTANT
-// expected-error-re@-2{{initializing '__{{global|generic}} int *' with an expression of type '__constant int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{initializing '__{{global|generic}} int *' with an expression of type '__constant int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{cannot initialize a variable of type '__{{global|generic}} int *' with an lvalue of type '__constant int *'}}
+#endif
#endif
AS int *var_init4 = arg_priv;
#ifndef GENERIC
-// expected-error-re@-2{{initializing '__{{global|constant}} int *' with an expression of type 'int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{initializing '__{{global|constant}} int *' with an expression of type 'int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{cannot initialize a variable of type '__{{global|constant}} int *' with an lvalue of type 'int *'}}
+#endif
#endif
AS int *var_init5 = arg_gen;
#ifndef GENERIC
-// expected-error-re@-2{{initializing '__{{global|constant}} int *' with an expression of type '__generic int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{initializing '__{{global|constant}} int *' with an expression of type '__generic int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{cannot initialize a variable of type '__{{global|constant}} int *' with an lvalue of type '__generic int *'}}
+#endif
#endif
AS int *var_cast1 = (AS int *)arg_glob;
@@ -112,27 +155,47 @@ void test_conversion(global int *arg_glob, local int *arg_loc,
AS int *var_impl;
var_impl = arg_glob;
#ifdef CONSTANT
-// expected-error@-2{{assigning '__global int *' to '__constant int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-3{{assigning '__global int *' to '__constant int *' changes address space of pointer}}
+#else
+// expected-error@-5{{assigning to '__constant int *' from incompatible type '__global int *'}}
+#endif
#endif
var_impl = arg_loc;
#ifndef GENERIC
-// expected-error-re@-2{{assigning '__local int *' to '__{{global|constant}} int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{assigning '__local int *' to '__{{global|constant}} int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__local int *'}}
+#endif
#endif
var_impl = arg_const;
#ifndef CONSTANT
-// expected-error-re@-2{{assigning '__constant int *' to '__{{global|generic}} int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{assigning '__constant int *' to '__{{global|generic}} int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{assigning to '__{{global|generic}} int *' from incompatible type '__constant int *'}}
+#endif
#endif
var_impl = arg_priv;
#ifndef GENERIC
-// expected-error-re@-2{{assigning 'int *' to '__{{global|constant}} int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{assigning 'int *' to '__{{global|constant}} int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type 'int *'}}
+#endif
#endif
var_impl = arg_gen;
#ifndef GENERIC
-// expected-error-re@-2{{assigning '__generic int *' to '__{{global|constant}} int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{assigning '__generic int *' to '__{{global|constant}} int *' changes address space of pointer}}
+#else
+// expected-error-re@-5{{assigning to '__{{global|constant}} int *' from incompatible type '__generic int *'}}
+#endif
#endif
var_cast1 = (AS int *)arg_glob;
@@ -163,27 +226,47 @@ void test_conversion(global int *arg_glob, local int *arg_loc,
AS int *var_cmp;
int b = var_cmp != arg_glob;
#ifdef CONSTANT
-// expected-error@-2{{comparison between ('__constant int *' and '__global int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-3{{comparison between ('__constant int *' and '__global int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error@-5{{comparison of distinct pointer types ('__constant int *' and '__global int *')}}
+#endif
#endif
b = var_cmp != arg_loc;
#ifndef GENERIC
-// expected-error-re@-2{{comparison between ('__{{global|constant}} int *' and '__local int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{comparison between ('__{{global|constant}} int *' and '__local int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error-re@-5{{comparison of distinct pointer types ('__{{global|constant}} int *' and '__local int *')}}
+#endif
#endif
b = var_cmp == arg_const;
#ifndef CONSTANT
-// expected-error-re@-2{{comparison between ('__{{global|generic}} int *' and '__constant int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{comparison between ('__{{global|generic}} int *' and '__constant int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error-re@-5{{comparison of distinct pointer types ('__{{global|generic}} int *' and '__constant int *')}}
+#endif
#endif
b = var_cmp <= arg_priv;
#ifndef GENERIC
-// expected-error-re@-2{{comparison between ('__{{global|constant}} int *' and 'int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{comparison between ('__{{global|constant}} int *' and 'int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error-re@-5{{comparison of distinct pointer types ('__{{global|constant}} int *' and 'int *')}}
+#endif
#endif
b = var_cmp >= arg_gen;
#ifdef CONSTANT
-// expected-error@-2{{comparison between ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-3{{comparison between ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error@-5{{comparison of distinct pointer types ('__constant int *' and '__generic int *')}}
+#endif
#endif
AS int *var_sub;
@@ -214,96 +297,158 @@ void test_conversion(global int *arg_glob, local int *arg_loc,
f_glob(var_sub);
#ifndef GLOBAL
-// expected-error-re@-2{{passing '__{{constant|generic}} int *' to parameter of type '__global int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{passing '__{{constant|generic}} int *' to parameter of type '__global int *' changes address space of pointer}}
+#else
+// expected-error@-5{{no matching function for call to 'f_glob'}}
+#endif
#endif
- f_loc(var_sub); // expected-error-re{{passing '__{{global|constant|generic}} int *' to parameter of type '__local int *' changes address space of pointer}}
+ f_loc(var_sub);
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-2{{passing '__{{global|constant|generic}} int *' to parameter of type '__local int *' changes address space of pointer}}
+#else
+// expected-error@-4{{no matching function for call to 'f_loc'}}
+#endif
f_const(var_sub);
#ifndef CONSTANT
-// expected-error-re@-2{{passing '__{{global|generic}} int *' to parameter of type '__constant int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{passing '__{{global|generic}} int *' to parameter of type '__constant int *' changes address space of pointer}}
+#else
+// expected-error@-5{{no matching function for call to 'f_const'}}
+#endif
#endif
- f_priv(var_sub); // expected-error-re{{passing '__{{global|constant|generic}} int *' to parameter of type 'int *' changes address space of pointer}}
+ f_priv(var_sub);
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-2{{passing '__{{global|constant|generic}} int *' to parameter of type 'int *' changes address space of pointer}}
+#else
+// expected-error@-4{{no matching function for call to 'f_priv'}}
+#endif
f_gen(var_sub);
#ifdef CONSTANT
-// expected-error@-2{{passing '__constant int *' to parameter of type '__generic int *' changes address space of pointer}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-3{{passing '__constant int *' to parameter of type '__generic int *' changes address space of pointer}}
+#else
+// expected-error@-5{{no matching function for call to 'f_gen'}}
+#endif
#endif
}
void test_ternary() {
AS int *var_cond;
- generic int *var_gen;
- global int *var_glob;
+ __generic int *var_gen;
+ __global int *var_glob;
var_gen = 0 ? var_cond : var_glob;
#ifdef CONSTANT
-// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__global int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-3{{conditional operator with the second and third operands of type ('__constant int *' and '__global int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error@-5{{incompatible operand types ('__constant int *' and '__global int *')}}
+#endif
#endif
- local int *var_loc;
+ __local int *var_loc;
var_gen = 0 ? var_cond : var_loc;
#ifndef GENERIC
-// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and '__local int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and '__local int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error-re@-5{{incompatible operand types ('__{{global|constant}} int *' and '__local int *')}}
+#endif
#endif
- constant int *var_const;
+ __constant int *var_const;
var_cond = 0 ? var_cond : var_const;
#ifndef CONSTANT
-// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|generic}} int *' and '__constant int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{conditional operator with the second and third operands of type ('__{{global|generic}} int *' and '__constant int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error-re@-5{{incompatible operand types ('__{{global|generic}} int *' and '__constant int *')}}
+#endif
#endif
- private int *var_priv;
+ __private int *var_priv;
var_gen = 0 ? var_cond : var_priv;
#ifndef GENERIC
-// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and 'int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error-re@-3{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and 'int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error-re@-5{{incompatible operand types ('__{{global|constant}} int *' and 'int *')}}
+#endif
#endif
var_gen = 0 ? var_cond : var_gen;
#ifdef CONSTANT
-// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}}
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-3{{conditional operator with the second and third operands of type ('__constant int *' and '__generic int *') which are pointers to non-overlapping address spaces}}
+#else
+// expected-error@-5{{incompatible operand types ('__constant int *' and '__generic int *')}}
+#endif
#endif
void *var_void_gen;
- global char *var_glob_ch;
+ __global char *var_glob_ch;
var_void_gen = 0 ? var_cond : var_glob_ch;
+#if __OPENCL_CPP_VERSION__
+// expected-error-re@-2{{incompatible operand types ('__{{constant|global|generic}} int *' and '__global char *')}}
+#else
#ifdef CONSTANT
-// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__global char *') which are pointers to non-overlapping address spaces}}
+// expected-error@-5{{conditional operator with the second and third operands of type ('__constant int *' and '__global char *') which are pointers to non-overlapping address spaces}}
#else
-// expected-warning-re@-4{{pointer type mismatch ('__{{global|generic}} int *' and '__global char *')}}
+// expected-warning-re@-7{{pointer type mismatch ('__{{global|generic}} int *' and '__global char *')}}
+#endif
#endif
- local char *var_loc_ch;
+ __local char *var_loc_ch;
var_void_gen = 0 ? var_cond : var_loc_ch;
+#if __OPENCL_CPP_VERSION__
+// expected-error-re@-2{{incompatible operand types ('__{{constant|global|generic}} int *' and '__local char *')}}
+#else
#ifndef GENERIC
-// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and '__local char *') which are pointers to non-overlapping address spaces}}
+// expected-error-re@-5{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and '__local char *') which are pointers to non-overlapping address spaces}}
#else
-// expected-warning@-4{{pointer type mismatch ('__generic int *' and '__local char *')}}
+// expected-warning@-7{{pointer type mismatch ('__generic int *' and '__local char *')}}
+#endif
#endif
- constant void *var_void_const;
- constant char *var_const_ch;
+ __constant void *var_void_const;
+ __constant char *var_const_ch;
var_void_const = 0 ? var_cond : var_const_ch;
+#if __OPENCL_CPP_VERSION__
+// expected-error-re@-2{{incompatible operand types ('__{{constant|global|generic}} int *' and '__constant char *')}}
+#else
#ifndef CONSTANT
-// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|generic}} int *' and '__constant char *') which are pointers to non-overlapping address spaces}}
+// expected-error-re@-5{{conditional operator with the second and third operands of type ('__{{global|generic}} int *' and '__constant char *') which are pointers to non-overlapping address spaces}}
#else
-// expected-warning@-4{{pointer type mismatch ('__constant int *' and '__constant char *')}}
+// expected-warning@-7{{pointer type mismatch ('__constant int *' and '__constant char *')}}
+#endif
#endif
- private char *var_priv_ch;
+ __private char *var_priv_ch;
var_void_gen = 0 ? var_cond : var_priv_ch;
+#if __OPENCL_CPP_VERSION__
+// expected-error-re@-2{{incompatible operand types ('__{{constant|global|generic}} int *' and 'char *')}}
+#else
#ifndef GENERIC
-// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and 'char *') which are pointers to non-overlapping address spaces}}
+// expected-error-re@-5{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and 'char *') which are pointers to non-overlapping address spaces}}
#else
-// expected-warning@-4{{pointer type mismatch ('__generic int *' and 'char *')}}
+// expected-warning@-7{{pointer type mismatch ('__generic int *' and 'char *')}}
+#endif
#endif
- generic char *var_gen_ch;
+ __generic char *var_gen_ch;
var_void_gen = 0 ? var_cond : var_gen_ch;
+#if __OPENCL_CPP_VERSION__
+// expected-error-re@-2{{incompatible operand types ('__{{constant|global|generic}} int *' and '__generic char *')}}
+#else
#ifdef CONSTANT
-// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__generic char *') which are pointers to non-overlapping address spaces}}
+// expected-error@-5{{conditional operator with the second and third operands of type ('__constant int *' and '__generic char *') which are pointers to non-overlapping address spaces}}
#else
-// expected-warning-re@-4{{pointer type mismatch ('__{{global|generic}} int *' and '__generic char *')}}
+// expected-warning-re@-7{{pointer type mismatch ('__{{global|generic}} int *' and '__generic char *')}}
+#endif
#endif
}
@@ -317,14 +462,26 @@ void test_pointer_chains() {
// * address spaces of corresponded most outer pointees overlaps, their canonical types are equal
// * CVR, address spaces and canonical types of the rest of pointees are equivalent.
var_as_as_int = 0 ? var_as_as_int : var_asc_as_int;
-
+#if __OPENCL_CPP_VERSION__
+#ifdef GENERIC
+// expected-error@-3{{incompatible operand types ('__generic int *__generic *' and '__generic int *__local *')}}
+#endif
+#endif
// Case 2: Corresponded inner pointees has non-overlapping address spaces.
var_as_as_int = 0 ? var_as_as_int : var_asc_asn_int;
-// expected-warning-re@-1{{pointer type mismatch ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(constant|local|global)}} *')}}
+#if !__OPENCL_CPP_VERSION__
+// expected-warning-re@-2{{pointer type mismatch ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(constant|local|global)}} *')}}
+#else
+// expected-error-re@-4{{incompatible operand types ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(constant|local|global)}} *')}}
+#endif
// Case 3: Corresponded inner pointees has overlapping but not equivalent address spaces.
#ifdef GENERIC
var_as_as_int = 0 ? var_as_as_int : var_asc_asc_int;
-// expected-warning-re@-1{{pointer type mismatch ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(local|global|constant)}} *')}}
+#if !__OPENCL_CPP_VERSION__
+// expected-warning-re@-2{{pointer type mismatch ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(local|global|constant)}} *')}}
+#else
+// expected-error-re@-4{{incompatible operand types ('__{{generic|global|constant}} int *__{{generic|global|constant}} *' and '__{{local|global|constant}} int *__{{local|global|constant}} *')}}
+#endif
#endif
}
diff --git a/test/SemaOpenCL/address-spaces.cl b/test/SemaOpenCL/address-spaces.cl
index 52c891e16b73..30f311d6ef15 100644
--- a/test/SemaOpenCL/address-spaces.cl
+++ b/test/SemaOpenCL/address-spaces.cl
@@ -9,46 +9,47 @@ __kernel void foo(__global int *gip) {
__local int lj = 2; // expected-error {{'__local' variable cannot have an initializer}}
int *ip;
-// FIXME: Temporarily disable part of the test that doesn't work for C++ yet.
-#if !__OPENCL_CPP_VERSION__
-#if __OPENCL_C_VERSION__ < 200
+#if ((!__OPENCL_CPP_VERSION__) && (__OPENCL_C_VERSION__ < 200))
ip = gip; // expected-error {{assigning '__global int *' to 'int *' changes address space of pointer}}
ip = &li; // expected-error {{assigning '__local int *' to 'int *' changes address space of pointer}}
ip = &ci; // expected-error {{assigning '__constant int *' to 'int *' changes address space of pointer}}
#else
ip = gip;
ip = &li;
- ip = &ci; // expected-error {{assigning '__constant int *' to '__generic int *' changes address space of pointer}}
+ ip = &ci;
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-2 {{assigning '__constant int *' to '__generic int *' changes address space of pointer}}
+#else
+// expected-error@-4 {{assigning to '__generic int *' from incompatible type '__constant int *'}}
+#endif
#endif
}
-void explicit_cast(global int* g, local int* l, constant int* c, private int* p, const constant int *cc)
-{
- g = (global int*) l; // expected-error {{casting '__local int *' to type '__global int *' changes address space of pointer}}
- g = (global int*) c; // expected-error {{casting '__constant int *' to type '__global int *' changes address space of pointer}}
- g = (global int*) cc; // expected-error {{casting 'const __constant int *' to type '__global int *' changes address space of pointer}}
- g = (global int*) p; // expected-error {{casting 'int *' to type '__global int *' changes address space of pointer}}
+void explicit_cast(__global int *g, __local int *l, __constant int *c, __private int *p, const __constant int *cc) {
+ g = (__global int *)l; // expected-error {{casting '__local int *' to type '__global int *' changes address space of pointer}}
+ g = (__global int *)c; // expected-error {{casting '__constant int *' to type '__global int *' changes address space of pointer}}
+ g = (__global int *)cc; // expected-error {{casting 'const __constant int *' to type '__global int *' changes address space of pointer}}
+ g = (__global int *)p; // expected-error {{casting 'int *' to type '__global int *' changes address space of pointer}}
- l = (local int*) g; // expected-error {{casting '__global int *' to type '__local int *' changes address space of pointer}}
- l = (local int*) c; // expected-error {{casting '__constant int *' to type '__local int *' changes address space of pointer}}
- l = (local int*) cc; // expected-error {{casting 'const __constant int *' to type '__local int *' changes address space of pointer}}
- l = (local int*) p; // expected-error {{casting 'int *' to type '__local int *' changes address space of pointer}}
+ l = (__local int *)g; // expected-error {{casting '__global int *' to type '__local int *' changes address space of pointer}}
+ l = (__local int *)c; // expected-error {{casting '__constant int *' to type '__local int *' changes address space of pointer}}
+ l = (__local int *)cc; // expected-error {{casting 'const __constant int *' to type '__local int *' changes address space of pointer}}
+ l = (__local int *)p; // expected-error {{casting 'int *' to type '__local int *' changes address space of pointer}}
- c = (constant int*) g; // expected-error {{casting '__global int *' to type '__constant int *' changes address space of pointer}}
- c = (constant int*) l; // expected-error {{casting '__local int *' to type '__constant int *' changes address space of pointer}}
- c = (constant int*) p; // expected-error {{casting 'int *' to type '__constant int *' changes address space of pointer}}
+ c = (__constant int *)g; // expected-error {{casting '__global int *' to type '__constant int *' changes address space of pointer}}
+ c = (__constant int *)l; // expected-error {{casting '__local int *' to type '__constant int *' changes address space of pointer}}
+ c = (__constant int *)p; // expected-error {{casting 'int *' to type '__constant int *' changes address space of pointer}}
- p = (private int*) g; // expected-error {{casting '__global int *' to type 'int *' changes address space of pointer}}
- p = (private int*) l; // expected-error {{casting '__local int *' to type 'int *' changes address space of pointer}}
- p = (private int*) c; // expected-error {{casting '__constant int *' to type 'int *' changes address space of pointer}}
- p = (private int*) cc; // expected-error {{casting 'const __constant int *' to type 'int *' changes address space of pointer}}
+ p = (__private int *)g; // expected-error {{casting '__global int *' to type 'int *' changes address space of pointer}}
+ p = (__private int *)l; // expected-error {{casting '__local int *' to type 'int *' changes address space of pointer}}
+ p = (__private int *)c; // expected-error {{casting '__constant int *' to type 'int *' changes address space of pointer}}
+ p = (__private int *)cc; // expected-error {{casting 'const __constant int *' to type 'int *' changes address space of pointer}}
}
-void ok_explicit_casts(global int *g, global int* g2, local int* l, local int* l2, private int* p, private int* p2)
-{
- g = (global int*) g2;
- l = (local int*) l2;
- p = (private int*) p2;
+void ok_explicit_casts(__global int *g, __global int *g2, __local int *l, __local int *l2, __private int *p, __private int *p2) {
+ g = (__global int *)g2;
+ l = (__local int *)l2;
+ p = (__private int *)p2;
}
__private int func_return_priv(void); //expected-error {{return value cannot be qualified with address space}}
@@ -61,11 +62,10 @@ __generic int func_return_generic(void); //expected-error {{return value cann
void func_multiple_addr(void) {
typedef __private int private_int_t;
- __local __private int var1; // expected-error {{multiple address spaces specified for type}}
- __local __private int *var2; // expected-error {{multiple address spaces specified for type}}
+ __private __local int var1; // expected-error {{multiple address spaces specified for type}}
+ __private __local int *var2; // expected-error {{multiple address spaces specified for type}}
__local private_int_t var3; // expected-error {{multiple address spaces specified for type}}
__local private_int_t *var4; // expected-error {{multiple address spaces specified for type}}
__private private_int_t var5; // expected-warning {{multiple identical address spaces specified for type}}
__private private_int_t *var6;// expected-warning {{multiple identical address spaces specified for type}}
-#endif // !__OPENCL_CXX_VERSION__
}
diff --git a/test/SemaOpenCL/atomic-ops.cl b/test/SemaOpenCL/atomic-ops.cl
index 2ec6cde21176..540520d4e325 100644
--- a/test/SemaOpenCL/atomic-ops.cl
+++ b/test/SemaOpenCL/atomic-ops.cl
@@ -58,7 +58,8 @@ void f(atomic_int *i, const atomic_int *ci,
__opencl_atomic_load(i, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_load(p, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_load(d, memory_order_seq_cst, memory_scope_work_group);
- __opencl_atomic_load(ci, memory_order_seq_cst, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
+ __opencl_atomic_load(ci, memory_order_seq_cst, memory_scope_work_group);
+ __opencl_atomic_load(i_c, memory_order_seq_cst, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-constant _Atomic type ('__constant atomic_int *' (aka '__constant _Atomic(int) *') invalid)}}
__opencl_atomic_store(i, 1, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_store(p, 1, memory_order_seq_cst, memory_scope_work_group);
@@ -94,7 +95,7 @@ void f(atomic_int *i, const atomic_int *ci,
__opencl_atomic_init(ci, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
__opencl_atomic_store(ci, 0, memory_order_release, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
- __opencl_atomic_load(ci, memory_order_acquire, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
+ __opencl_atomic_load(ci, memory_order_acquire, memory_scope_work_group);
__opencl_atomic_init(&gn, 456);
__opencl_atomic_init(&gn, (void*)0); // expected-warning{{incompatible pointer to integer conversion passing '__generic void *' to parameter of type 'int'}}
diff --git a/test/SemaOpenCL/block-array-capturing.cl b/test/SemaOpenCL/block-array-capturing.cl
new file mode 100644
index 000000000000..e8073fce11e8
--- /dev/null
+++ b/test/SemaOpenCL/block-array-capturing.cl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple spir64-unkown-unkown -emit-llvm %s -o -| FileCheck %s
+// expected-no-diagnostics
+
+typedef int (^block_t)();
+
+int block_typedef_kernel(global int* res) {
+ // CHECK: %{{.*}} = alloca <{ i32, i32, i8 addrspace(4)*, [3 x i32] }>
+ int a[3] = {1, 2, 3};
+ // CHECK: call void @llvm.memcpy{{.*}}
+ block_t b = ^() { return a[0]; };
+ return b();
+}
+
+// CHECK: define {{.*}} @__block_typedef_kernel_block_invoke
+// CHECK: %{{.*}} = getelementptr inbounds [3 x i32], [3 x i32] addrspace(4)* %{{.*}}, i64 0, i64 0
+// CHECK-NOT: call void @llvm.memcpy{{.*}}
diff --git a/test/SemaOpenCL/builtins-amdgcn-error-ci.cl b/test/SemaOpenCL/builtins-amdgcn-error-ci.cl
new file mode 100644
index 000000000000..2f656582bee9
--- /dev/null
+++ b/test/SemaOpenCL/builtins-amdgcn-error-ci.cl
@@ -0,0 +1,8 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -verify -S -o - %s
+
+void test_ci_biltins()
+{
+ __builtin_amdgcn_s_dcache_inv_vol(); // expected-error {{'__builtin_amdgcn_s_dcache_inv_vol' needs target feature ci-insts}}
+ __builtin_amdgcn_buffer_wbinvl1_vol(); // expected-error {{'__builtin_amdgcn_buffer_wbinvl1_vol' needs target feature ci-insts}}
+}
diff --git a/test/SemaOpenCL/builtins-amdgcn-error-vi.cl b/test/SemaOpenCL/builtins-amdgcn-error-vi.cl
new file mode 100644
index 000000000000..877a04015e56
--- /dev/null
+++ b/test/SemaOpenCL/builtins-amdgcn-error-vi.cl
@@ -0,0 +1,8 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -verify -S -o - %s
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu hawaii -verify -S -o - %s
+
+void test_vi_s_dcache_wb()
+{
+ __builtin_amdgcn_s_dcache_wb(); // expected-error {{'__builtin_amdgcn_s_dcache_wb' needs target feature vi-insts}}
+}
diff --git a/test/SemaOpenCL/builtins-amdgcn-error.cl b/test/SemaOpenCL/builtins-amdgcn-error.cl
index 67c416feacf7..77b9f573adc9 100644
--- a/test/SemaOpenCL/builtins-amdgcn-error.cl
+++ b/test/SemaOpenCL/builtins-amdgcn-error.cl
@@ -102,6 +102,15 @@ void test_mov_dpp2(global int* out, int a, int b, int c, int d, bool e)
*out = __builtin_amdgcn_mov_dpp(a, 0, 0, 0, e); // expected-error {{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}}
}
+void test_update_dpp2(global int* out, int a, int b, int c, int d, int e, bool f)
+{
+ *out = __builtin_amdgcn_update_dpp(a, b, 0, 0, 0, false);
+ *out = __builtin_amdgcn_update_dpp(a, 0, c, 0, 0, false); // expected-error {{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}}
+ *out = __builtin_amdgcn_update_dpp(a, 0, 0, d, 0, false); // expected-error {{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}}
+ *out = __builtin_amdgcn_update_dpp(a, 0, 0, 0, e, false); // expected-error {{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}}
+ *out = __builtin_amdgcn_update_dpp(a, 0, 0, 0, 0, f); // expected-error {{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}}
+}
+
void test_ds_faddf(local float *out, float src, int a) {
*out = __builtin_amdgcn_ds_faddf(out, src, a, 0, false); // expected-error {{argument to '__builtin_amdgcn_ds_faddf' must be a constant integer}}
*out = __builtin_amdgcn_ds_faddf(out, src, 0, a, false); // expected-error {{argument to '__builtin_amdgcn_ds_faddf' must be a constant integer}}
diff --git a/test/SemaOpenCL/cl20-device-side-enqueue.cl b/test/SemaOpenCL/cl20-device-side-enqueue.cl
index 207fe7d340ab..8946911c093c 100644
--- a/test/SemaOpenCL/cl20-device-side-enqueue.cl
+++ b/test/SemaOpenCL/cl20-device-side-enqueue.cl
@@ -212,7 +212,7 @@ kernel void work_group_size_tests() {
#pragma OPENCL EXTENSION cl_khr_subgroups : enable
-kernel void foo(global int *buf)
+kernel void foo(global unsigned int *buf)
{
ndrange_t n;
buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){});
@@ -220,7 +220,7 @@ kernel void foo(global int *buf)
buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, 1); // expected-error{{illegal call to 'get_kernel_max_sub_group_size_for_ndrange', expected block argument type}}
}
-kernel void bar(global int *buf)
+kernel void bar(global unsigned int *buf)
{
__private ndrange_t n;
buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){});
@@ -230,13 +230,13 @@ kernel void bar(global int *buf)
#pragma OPENCL EXTENSION cl_khr_subgroups : disable
-kernel void foo1(global int *buf)
+kernel void foo1(global unsigned int *buf)
{
ndrange_t n;
buf[0] = get_kernel_max_sub_group_size_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_max_sub_group_size_for_ndrange' requires cl_khr_subgroups extension to be enabled}}
}
-kernel void bar1(global int *buf)
+kernel void bar1(global unsigned int *buf)
{
ndrange_t n;
buf[0] = get_kernel_sub_group_count_for_ndrange(n, ^(){}); // expected-error {{use of declaration 'get_kernel_sub_group_count_for_ndrange' requires cl_khr_subgroups extension to be enabled}}
diff --git a/test/SemaOpenCL/clang-builtin-version.cl b/test/SemaOpenCL/clang-builtin-version.cl
index 270345d86a61..3e270e64c69d 100644
--- a/test/SemaOpenCL/clang-builtin-version.cl
+++ b/test/SemaOpenCL/clang-builtin-version.cl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fblocks -verify -pedantic-errors -fsyntax-only -ferror-limit 100
+// RUN: %clang_cc1 %s -fblocks -verify -pedantic -fsyntax-only -ferror-limit 100
// Confirm CL2.0 Clang builtins are not available in earlier versions
diff --git a/test/SemaOpenCL/clk_event_t.cl b/test/SemaOpenCL/clk_event_t.cl
new file mode 100644
index 000000000000..b73daf92fa00
--- /dev/null
+++ b/test/SemaOpenCL/clk_event_t.cl
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
+
+// Taken from opencl-c.h
+#define CLK_NULL_EVENT (__builtin_astype(((void*)(__SIZE_MAX__)), clk_event_t))
+
+global clk_event_t ce; // expected-error {{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+int clk_event_tests() {
+ event_t e;
+ clk_event_t ce1;
+ clk_event_t ce2;
+
+ if (e == ce1) { // expected-error {{invalid operands to binary expression ('event_t' and 'clk_event_t')}}
+ return 9;
+ }
+
+ if (ce1 != ce2) {
+ return 1;
+ }
+ else if (ce1 == CLK_NULL_EVENT || ce2 != CLK_NULL_EVENT) {
+ return 0;
+ }
+
+ return 2;
+}
diff --git a/test/SemaOpenCL/extension-begin.cl b/test/SemaOpenCL/extension-begin.cl
index 92ea88143233..276e6d7f10b0 100644
--- a/test/SemaOpenCL/extension-begin.cl
+++ b/test/SemaOpenCL/extension-begin.cl
@@ -1,37 +1,29 @@
// Test this without pch.
-// RUN: %clang_cc1 %s -DHEADER -DHEADER_USER -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
// Test with pch.
-// RUN: %clang_cc1 %s -DHEADER -triple spir-unknown-unknown -emit-pch -o %t -verify -pedantic
-// RUN: %clang_cc1 %s -DHEADER_USER -triple spir-unknown-unknown -include-pch %t -fsyntax-only -verify -pedantic
-
-#if defined(HEADER) && !defined(INCLUDED)
-#define INCLUDED
-
-#pragma OPENCL EXTENSION all : begin // expected-warning {{expected 'disable' - ignoring}}
-#pragma OPENCL EXTENSION all : end // expected-warning {{expected 'disable' - ignoring}}
-
-#pragma OPENCL EXTENSION my_ext : begin
-
-struct A {
- int a;
-};
-
-typedef struct A TypedefOfA;
-typedef const TypedefOfA* PointerOfA;
-
-void f(void);
-
-__attribute__((overloadable)) void g(long x);
-
-#pragma OPENCL EXTENSION my_ext : end
-#pragma OPENCL EXTENSION my_ext : end // expected-warning {{OpenCL extension end directive mismatches begin directive - ignoring}}
-
-__attribute__((overloadable)) void g(void);
-
-#endif // defined(HEADER) && !defined(INCLUDED)
-
-#ifdef HEADER_USER
+// RUN: %clang_cc1 -x cl %S/extension-begin.h -triple spir-unknown-unknown -emit-pch -o %t.pch -pedantic
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -include-pch %t.pch -DIMPLICIT_INCLUDE -DUSE_PCH -fsyntax-only -verify -pedantic
+
+// Test with modules
+// RUN: rm -rf %t.modules
+// RUN: mkdir -p %t.modules
+//
+// RUN: %clang_cc1 -cl-std=CL1.2 -DIMPLICIT_INCLUDE -include %S/extension-begin.h -triple spir-unknown-unknown -O0 -emit-llvm -o - -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.modules %s -verify -pedantic
+//
+// RUN: rm -rf %t.modules
+// RUN: mkdir -p %t.modules
+//
+// RUN: %clang_cc1 -cl-std=CL2.0 -DIMPLICIT_INCLUDE -include %S/extension-begin.h -triple spir-unknown-unknown -O0 -emit-llvm -o - -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.modules %s -verify -pedantic
+
+#ifndef IMPLICIT_INCLUDE
+#include "extension-begin.h"
+#endif // IMPLICIT_INCLUDE
+#ifndef USE_PCH
+// expected-warning@extension-begin.h:4 {{expected 'disable' - ignoring}}
+// expected-warning@extension-begin.h:5 {{expected 'disable' - ignoring}}
+// expected-warning@extension-begin.h:21 {{OpenCL extension end directive mismatches begin directive - ignoring}}
+#endif // USE_PCH
#pragma OPENCL EXTENSION my_ext : enable
void test_f1(void) {
@@ -48,9 +40,7 @@ void test_f2(void) {
PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}}
f(); // expected-error {{use of declaration 'f' requires my_ext extension to be enabled}}
g(0); // expected-error {{no matching function for call to 'g'}}
- // expected-note@-26 {{candidate disabled due to OpenCL extension}}
- // expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
+ // expected-note@extension-begin.h:18 {{candidate unavailable as it requires OpenCL extension 'my_ext' to be enabled}}
+ // expected-note@extension-begin.h:23 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
}
-#endif // HEADER_USER
-
diff --git a/test/SemaOpenCL/extension-begin.h b/test/SemaOpenCL/extension-begin.h
new file mode 100644
index 000000000000..d9865ba0b33a
--- /dev/null
+++ b/test/SemaOpenCL/extension-begin.h
@@ -0,0 +1,26 @@
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma OPENCL EXTENSION all : begin
+#pragma OPENCL EXTENSION all : end
+
+#pragma OPENCL EXTENSION my_ext : begin
+
+struct A {
+ int a;
+};
+
+typedef struct A TypedefOfA;
+typedef const __private TypedefOfA* PointerOfA;
+
+void f(void);
+
+__attribute__((overloadable)) void g(long x);
+
+#pragma OPENCL EXTENSION my_ext : end
+#pragma OPENCL EXTENSION my_ext : end
+
+__attribute__((overloadable)) void g(void);
+
+#endif // INCLUDED
+
diff --git a/test/SemaOpenCL/extension-version.cl b/test/SemaOpenCL/extension-version.cl
index 714e4c210861..a587f1db99af 100644
--- a/test/SemaOpenCL/extension-version.cl
+++ b/test/SemaOpenCL/extension-version.cl
@@ -283,6 +283,18 @@
#pragma OPENCL EXTENSION cl_amd_media_ops2: enable
#if (__OPENCL_C_VERSION__ >= 120)
+#ifndef cl_khr_depth_images
+#error "Missing cl_khr_depth_images define"
+#endif
+#else
+#ifdef cl_khr_depth_images
+#error "Incorrect cl_khr_depth_images define"
+#endif
+// expected-warning@+2{{unsupported OpenCL extension 'cl_khr_depth_images' - ignoring}}
+#endif
+#pragma OPENCL EXTENSION cl_khr_depth_images: enable
+
+#if (__OPENCL_C_VERSION__ >= 120)
#ifndef cl_intel_subgroups
#error "Missing cl_intel_subgroups define"
#endif
@@ -300,3 +312,12 @@
#endif
#pragma OPENCL EXTENSION cl_intel_subgroups_short : enable
+#if (__OPENCL_C_VERSION__ >= 120)
+#ifndef cl_intel_device_side_avc_motion_estimation
+#error "Missing cl_intel_device_side_avc_motion_estimation define"
+#endif
+#else
+// expected-warning@+2{{unsupported OpenCL extension 'cl_intel_device_side_avc_motion_estimation' - ignoring}}
+#endif
+#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : enable
+
diff --git a/test/SemaOpenCL/extensions.cl b/test/SemaOpenCL/extensions.cl
index 6afb11e42a6a..5f95e32d4a54 100644
--- a/test/SemaOpenCL/extensions.cl
+++ b/test/SemaOpenCL/extensions.cl
@@ -70,6 +70,13 @@ void f2(void) {
// expected-error@-2{{use of type 'double' requires cl_khr_fp64 extension to be enabled}}
#endif
+ typedef double double4 __attribute__((ext_vector_type(4)));
+ double4 d4 = {0.0f, 2.0f, 3.0f, 1.0f};
+#ifdef NOFP64
+// expected-error@-3 {{use of type 'double' requires cl_khr_fp64 extension to be enabled}}
+// expected-error@-3 {{use of type 'double4' (vector of 4 'double' values) requires cl_khr_fp64 extension to be enabled}}
+#endif
+
(void) 1.0;
#ifdef NOFP64
diff --git a/test/SemaOpenCL/format-strings-fixit.cl b/test/SemaOpenCL/format-strings-fixit.cl
new file mode 100644
index 000000000000..b9f949ffe2fc
--- /dev/null
+++ b/test/SemaOpenCL/format-strings-fixit.cl
@@ -0,0 +1,24 @@
+// RUN: cp %s %t
+// RUN: %clang_cc1 -cl-std=CL1.2 -pedantic -Wall -fixit %t
+// RUN: %clang_cc1 -cl-std=CL1.2 -fsyntax-only -pedantic -Wall -Werror %t
+// RUN: %clang_cc1 -cl-std=CL1.2 -E -o - %t | FileCheck %s
+
+typedef __attribute__((ext_vector_type(4))) int int4;
+typedef __attribute__((ext_vector_type(8))) int int8;
+
+int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
+
+
+void vector_fixits() {
+ printf("%v4f", (int4) 123);
+ // CHECK: printf("%v4d", (int4) 123);
+
+ printf("%v8d", (int4) 123);
+ // CHECK: printf("%v4d", (int4) 123);
+
+ printf("%v4d", (int8) 123);
+ // CHECK: printf("%v8d", (int8) 123);
+
+ printf("%v4f", (int8) 123);
+ // CHECK: printf("%v8d", (int8) 123);
+}
diff --git a/test/SemaOpenCL/intel-subgroup-avc-ext-types.cl b/test/SemaOpenCL/intel-subgroup-avc-ext-types.cl
new file mode 100644
index 000000000000..3392e80565f1
--- /dev/null
+++ b/test/SemaOpenCL/intel-subgroup-avc-ext-types.cl
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL1.2 -cl-ext=+cl_intel_device_side_avc_motion_estimation -fsyntax-only -verify %s
+
+#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : enable
+
+// All intel_sub_group_avc_* types can only be used as argument or return value
+// of built-in functions defined in the extension.
+// But there are also additional initialization rules:
+// * All types except intel_sub_group_avc_mce_* types can be initialized with
+// the corresponding initializer macro defined in opencl-c.h
+// Currently all these macroses are defined as 0x0
+// * In previous versions of the extension these macroses was defined as {0},
+// so initialization with initializer list containing one integer equal to
+// zero should also work
+
+struct st{};
+// negative test cases for initializers
+void foo(char c, float f, void* v, struct st ss) {
+ intel_sub_group_avc_mce_payload_t payload_mce = 0; // No zero initializer for mce types
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_mce_payload_t' with an expression of incompatible type 'int'}}
+ intel_sub_group_avc_ime_payload_t payload_ime = 1; // No literal initializer for *payload_t types
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ime_payload_t' with an expression of incompatible type 'int'}}
+ intel_sub_group_avc_ref_payload_t payload_ref = f;
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ref_payload_t' with an expression of incompatible type 'float'}}
+ intel_sub_group_avc_sic_payload_t payload_sic = ss;
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_sic_payload_t' with an expression of incompatible type 'struct st'}}
+
+ intel_sub_group_avc_mce_result_t result_mce = 0; // No zero initializer for mce types
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_mce_result_t' with an expression of incompatible type 'int'}}
+ intel_sub_group_avc_ime_result_t result_ime = 1; // No literal initializer for *result_t types
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ime_result_t' with an expression of incompatible type 'int'}}
+ intel_sub_group_avc_ref_result_t result_ref = f;
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ref_result_t' with an expression of incompatible type 'float'}}
+ intel_sub_group_avc_sic_result_t result_sic = ss;
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_sic_result_t' with an expression of incompatible type 'struct st'}}
+
+ intel_sub_group_avc_ime_result_single_reference_streamout_t sstreamout = v;
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ime_result_single_reference_streamout_t' with an expression of incompatible type 'void *'}}
+
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t dstreamin_list = {0x0, 0x1};
+ // expected-warning@-1 {{excess elements in struct initializer}}
+ intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin_list2 = {};
+ // expected-error@-1 {{scalar initializer cannot be empty}}
+ intel_sub_group_avc_ime_single_reference_streamin_t dstreamin_list3 = {c};
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ime_single_reference_streamin_t' with an expression of incompatible type 'char'}}
+ intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin_list4 = {1};
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ime_dual_reference_streamin_t' with an expression of incompatible type 'int'}}
+}
+
+// negative tests for initializers and assignment
+void far() {
+ intel_sub_group_avc_mce_payload_t payload_mce;
+ intel_sub_group_avc_mce_payload_t payload_mce2 = payload_mce;
+
+ intel_sub_group_avc_ime_payload_t payload_ime;
+ intel_sub_group_avc_ref_payload_t payload_ref = payload_ime;
+ // expected-error@-1 {{initializing 'intel_sub_group_avc_ref_payload_t' with an expression of incompatible type 'intel_sub_group_avc_ime_payload_t'}}
+
+ intel_sub_group_avc_sic_result_t result_sic;
+ intel_sub_group_avc_ime_result_t result_ime;
+ result_sic = result_ime;
+ // expected-error@-1 {{assigning to 'intel_sub_group_avc_sic_result_t' from incompatible type 'intel_sub_group_avc_ime_result_t'}}
+}
+
+// Using 0x0 directly allows us not to include opencl-c.h header and not to
+// redefine all of these CLK_AVC_*_INTITIALIZE_INTEL macro. '0x0' value must
+// be in sync with ones defined in opencl-c.h
+
+// positive test cases
+void bar() {
+ const sampler_t vme_sampler = 0x0;
+
+ intel_sub_group_avc_mce_payload_t payload_mce; // No literal initializer for mce types
+ intel_sub_group_avc_ime_payload_t payload_ime = 0x0;
+ intel_sub_group_avc_ref_payload_t payload_ref = 0x0;
+ intel_sub_group_avc_sic_payload_t payload_sic = 0x0;
+
+ intel_sub_group_avc_mce_result_t result_mce; // No literal initializer for mce types
+ intel_sub_group_avc_ime_result_t result_ime = 0x0;
+ intel_sub_group_avc_ref_result_t result_ref = 0x0;
+ intel_sub_group_avc_sic_result_t result_sic = 0x0;
+
+ intel_sub_group_avc_ime_result_single_reference_streamout_t sstreamout = 0x0;
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t dstreamout = 0x0;
+ intel_sub_group_avc_ime_single_reference_streamin_t sstreamin = 0x0;
+ intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin = 0x0;
+
+ // It is allowed to assign variables of the same types
+ intel_sub_group_avc_mce_payload_t pauload_mce2 = payload_mce;
+
+ // Initialization with initializer list was supported in the first version
+ // of the extension. So we check for backward compatibility here.
+ intel_sub_group_avc_ime_payload_t payload_ime_list = {0};
+ intel_sub_group_avc_ref_payload_t payload_ref_list = {0};
+ intel_sub_group_avc_sic_payload_t payload_sic_list = {0};
+
+ intel_sub_group_avc_ime_result_t result_ime_list = {0};
+ intel_sub_group_avc_ref_result_t result_ref_list = {0};
+ intel_sub_group_avc_sic_result_t result_sic_list = {0};
+
+ intel_sub_group_avc_ime_result_single_reference_streamout_t sstreamout_list = {0};
+ intel_sub_group_avc_ime_result_dual_reference_streamout_t dstreamout_list = {0};
+ intel_sub_group_avc_ime_single_reference_streamin_t sstreamin_list = {0};
+ intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin_list = {0};
+}
+
diff --git a/test/SemaOpenCL/invalid-clk-events-cl2.0.cl b/test/SemaOpenCL/invalid-clk-events-cl2.0.cl
deleted file mode 100644
index 8c8e1c617611..000000000000
--- a/test/SemaOpenCL/invalid-clk-events-cl2.0.cl
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
-
-global clk_event_t ce; // expected-error {{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
diff --git a/test/SemaOpenCL/invalid-kernel-attrs.cl b/test/SemaOpenCL/invalid-kernel-attrs.cl
index a19a989f41bb..a96e85c9ee24 100644
--- a/test/SemaOpenCL/invalid-kernel-attrs.cl
+++ b/test/SemaOpenCL/invalid-kernel-attrs.cl
@@ -37,3 +37,10 @@ kernel __attribute__((reqd_work_group_size(0,1,2))) void kernel13(){} // expecte
__attribute__((intel_reqd_sub_group_size(8))) void kernel14(){} // expected-error {{attribute 'intel_reqd_sub_group_size' can only be applied to an OpenCL kernel}}
kernel __attribute__((intel_reqd_sub_group_size(0))) void kernel15(){} // expected-error {{'intel_reqd_sub_group_size' attribute must be greater than 0}}
kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel16() {} //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}}
+
+__kernel __attribute__((work_group_size_hint(8,-16,32))) void neg1() {} //expected-error{{'work_group_size_hint' attribute requires a non-negative integral compile time constant expression}}
+__kernel __attribute__((reqd_work_group_size(8,16,-32))) void neg2(){} // expected-error{{'reqd_work_group_size' attribute requires a non-negative integral compile time constant expression}}
+
+// 4294967294 is a negative integer if treated as signed.
+// Should compile successfully, since we expect an unsigned.
+__kernel __attribute__((reqd_work_group_size(8,16,4294967294))) void ok1(){}
diff --git a/test/SemaOpenCL/null_queue.cl b/test/SemaOpenCL/null_queue.cl
index 518f7138de6c..34d1a621f4a8 100644
--- a/test/SemaOpenCL/null_queue.cl
+++ b/test/SemaOpenCL/null_queue.cl
@@ -1,12 +1,30 @@
// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
extern queue_t get_default_queue();
-bool compare() {
- return 1 == get_default_queue() && // expected-error{{invalid operands to binary expression ('int' and 'queue_t')}}
- get_default_queue() == 1; // expected-error{{invalid operands to binary expression ('queue_t' and 'int')}}
-}
+void queue_arg(queue_t); // expected-note {{passing argument to parameter here}}
void init() {
queue_t q1 = 1; // expected-error{{initializing 'queue_t' with an expression of incompatible type 'int'}}
queue_t q = 0;
}
+
+void assign() {
+ queue_t q2, q3;
+ q2 = 5; // expected-error{{assigning to 'queue_t' from incompatible type 'int'}}
+ q3 = 0;
+ q2 = q3 = 0;
+}
+
+bool compare() {
+ queue_t q4, q5;
+ return 1 == get_default_queue() && // expected-error{{invalid operands to binary expression ('int' and 'queue_t')}}
+ get_default_queue() == 1 && // expected-error{{invalid operands to binary expression ('queue_t' and 'int')}}
+ q4 == q5 &&
+ q4 != 0 &&
+ q4 != 0.0f; // expected-error{{invalid operands to binary expression ('queue_t' and 'float')}}
+}
+
+void call() {
+ queue_arg(5); // expected-error {{passing 'int' to parameter of incompatible type 'queue_t'}}
+ queue_arg(0);
+}
diff --git a/test/SemaOpenCL/numbered-address-space.cl b/test/SemaOpenCL/numbered-address-space.cl
new file mode 100644
index 000000000000..423d03274cef
--- /dev/null
+++ b/test/SemaOpenCL/numbered-address-space.cl
@@ -0,0 +1,31 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-amd-amdhsa -verify -pedantic -fsyntax-only %s
+
+void test_numeric_as_to_generic_implicit_cast(__attribute__((address_space(3))) int *as3_ptr, float src) {
+ generic int* generic_ptr = as3_ptr; // FIXME: This should error
+}
+
+void test_numeric_as_to_generic_explicit_cast(__attribute__((address_space(3))) int *as3_ptr, float src) {
+ generic int* generic_ptr = (generic int*) as3_ptr; // Should maybe be valid?
+}
+
+void test_generic_to_numeric_as_implicit_cast() {
+ generic int* generic_ptr = 0;
+ __attribute__((address_space(3))) int *as3_ptr = generic_ptr; // expected-error{{initializing '__attribute__((address_space(3))) int *' with an expression of type '__generic int *' changes address space of pointer}}
+}
+
+void test_generic_to_numeric_as_explicit_cast() {
+ generic int* generic_ptr = 0;
+ __attribute__((address_space(3))) int *as3_ptr = (__attribute__((address_space(3))) int *)generic_ptr;
+}
+
+void test_generic_as_to_builtin_parameter_explicit_cast_numeric(__attribute__((address_space(3))) int *as3_ptr, float src) {
+ generic int* generic_ptr = as3_ptr; // FIXME: This should error
+ volatile float result = __builtin_amdgcn_ds_fmaxf((__attribute__((address_space(3))) float*) generic_ptr, src, 0, 0, false); // expected-error {{passing '__attribute__((address_space(3))) float *' to parameter of type '__local float *' changes address space of pointer}}
+}
+
+void test_generic_as_to_builtin_parameterimplicit_cast_numeric(__attribute__((address_space(3))) int *as3_ptr, float src) {
+ generic int* generic_ptr = as3_ptr;
+ volatile float result = __builtin_amdgcn_ds_fmaxf(generic_ptr, src, 0, 0, false); // expected-warning {{incompatible pointer types passing '__generic int *' to parameter of type '__local float *'}}
+}
+
diff --git a/test/SemaOpenCL/printf-format-string-warnings.cl b/test/SemaOpenCL/printf-format-string-warnings.cl
new file mode 100644
index 000000000000..2b9c5cc3f319
--- /dev/null
+++ b/test/SemaOpenCL/printf-format-string-warnings.cl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 -finclude-default-header
+
+// Make sure warnings are produced based on printf format strings.
+
+
+kernel void format_string_warnings(__constant char* arg) {
+
+ printf("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type '__constant char *'}}
+
+ printf("not enough arguments %d %d", 4); // expected-warning {{more '%' conversions than data arguments}}
+
+ printf("too many arguments", 4); // expected-warning {{data argument not used by format string}}
+}
diff --git a/test/SemaOpenCL/printf-format-strings.cl b/test/SemaOpenCL/printf-format-strings.cl
new file mode 100644
index 000000000000..079a83495685
--- /dev/null
+++ b/test/SemaOpenCL/printf-format-strings.cl
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=+cl_khr_fp64 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -fsyntax-only -verify %s
+
+typedef __attribute__((ext_vector_type(2))) float float2;
+typedef __attribute__((ext_vector_type(4))) float float4;
+
+typedef __attribute__((ext_vector_type(2))) int int2;
+typedef __attribute__((ext_vector_type(4))) int int4;
+typedef __attribute__((ext_vector_type(16))) int int16;
+
+int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
+
+kernel void format_v4f32(float4 arg)
+{
+#ifdef cl_khr_fp64
+ printf("%v4f\n", arg);
+
+ // Precision modifier
+ printf("%.2v4f\n", arg);
+#else
+ // FIXME: These should not warn, and the type should be expected to be float.
+ printf("%v4f\n", arg); // expected-warning {{double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
+
+ // Precision modifier
+ printf("%.2v4f\n", arg); // expected-warning {{double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
+#endif
+}
+
+kernel void format_only_v(int arg)
+{
+ printf("%v", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void format_missing_num(int arg)
+{
+ printf("%v4", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void format_not_num(int arg)
+{
+ printf("%vNd", arg); // expected-warning {{incomplete format specifier}}
+ printf("%v*d", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void format_v16i32(int16 arg)
+{
+ printf("%v16d\n", arg);
+}
+
+kernel void format_v4i32_scalar(int arg)
+{
+ printf("%v4d\n", arg); // expected-warning {{format specifies type 'int __attribute__((ext_vector_type(4)))' but the argument has type 'int'}}
+}
+
+kernel void format_v4i32_wrong_num_elts_2_to_4(int2 arg)
+{
+ printf("%v4d\n", arg); // expected-warning {{format specifies type 'int __attribute__((ext_vector_type(4)))' but the argument has type 'int2' (vector of 2 'int' values)}}
+}
+
+kernel void format_missing_num_elts_format(int4 arg)
+{
+ printf("%vd\n", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void format_v4f32_scalar(float arg)
+{
+ printf("%v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float'}}
+}
+
+kernel void format_v4f32_wrong_num_elts(float2 arg)
+{
+ printf("%v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float2' (vector of 2 'float' values)}}
+}
+
+kernel void format_missing_num_elts(float4 arg)
+{
+ printf("%vf\n", arg); // expected-warning {{incomplete format specifier}}
+}
+
+kernel void vector_precision_modifier_v4i32_to_v4f32(int4 arg)
+{
+ printf("%.2v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'int4' (vector of 4 'int' values)}}
+}
+
+kernel void invalid_Y(int4 arg)
+{
+ printf("%v4Y\n", arg); // expected-warning {{invalid conversion specifier 'Y'}}
+}
+
+// FIXME: This should warn
+kernel void crash_on_s(int4 arg)
+{
+ printf("%v4s\n", arg);
+}
diff --git a/test/SemaOpenCL/sampler_t.cl b/test/SemaOpenCL/sampler_t.cl
index 5a1850b02cbd..8473fa33631a 100644
--- a/test/SemaOpenCL/sampler_t.cl
+++ b/test/SemaOpenCL/sampler_t.cl
@@ -33,6 +33,8 @@ constant sampler_t glb_smp9 = 0x100000000LL; // expected-error{{sampler_t initia
void foo(sampler_t); // expected-note{{passing argument to parameter here}}
+void constant_sampler(constant sampler_t s); // expected-error{{parameter may not be qualified with an address space}}
+
constant struct sampler_s {
sampler_t smp; // expected-error{{the 'sampler_t' type cannot be used to declare a structure or union field}}
} sampler_str = {0};
diff --git a/test/SemaOpenCL/to_addr_builtin.cl b/test/SemaOpenCL/to_addr_builtin.cl
index 70956f007a5f..26389d24fce8 100644
--- a/test/SemaOpenCL/to_addr_builtin.cl
+++ b/test/SemaOpenCL/to_addr_builtin.cl
@@ -1,16 +1,18 @@
// RUN: %clang_cc1 -verify -fsyntax-only %s
-// RUN: %clang_cc1 -verify -fsyntax-only -cl-std=CL2.0 %s
+// RUN: %clang_cc1 -Wconversion -verify -fsyntax-only -cl-std=CL2.0 %s
void test(void) {
global int *glob;
local int *loc;
constant int *con;
+ private int *priv;
+ global float *glob_wrong_ty;
typedef constant int const_int_ty;
const_int_ty *con_typedef;
glob = to_global(glob, loc);
#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
- // expected-warning@-2{{implicit declaration of function 'to_global' is invalid in OpenCL}}
+ // expected-error@-2{{implicit declaration of function 'to_global' is invalid in OpenCL}}
// expected-warning@-3{{incompatible integer to pointer conversion assigning to '__global int *' from 'int'}}
#else
// expected-error@-5{{invalid number of arguments to function: 'to_global'}}
@@ -43,6 +45,73 @@ void test(void) {
// expected-warning@-2{{incompatible integer to pointer conversion assigning to '__local int *' from 'int'}}
#else
// expected-error@-4{{assigning '__global int *' to '__local int *' changes address space of pointer}}
+ // expected-warning@-5{{passing non-generic address space pointer to to_global may cause dynamic conversion affecting performance}}
+#endif
+
+ loc = to_private(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-error@-2{{implicit declaration of function 'to_private' is invalid in OpenCL}}
+ // expected-warning@-3{{incompatible integer to pointer conversion assigning to '__local int *' from 'int'}}
+#else
+ // expected-error@-5{{assigning 'int *' to '__local int *' changes address space of pointer}}
+ // expected-warning@-6{{passing non-generic address space pointer to to_private may cause dynamic conversion affecting performance}}
+#endif
+
+ loc = to_local(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-error@-2{{implicit declaration of function 'to_local' is invalid in OpenCL}}
+ // expected-warning@-3{{incompatible integer to pointer conversion assigning to '__local int *' from 'int'}}
+ // expected-note@-4{{did you mean 'to_global'}}
+ // expected-note@13{{'to_global' declared here}}
+#else
+ // expected-warning@-7{{passing non-generic address space pointer to to_local may cause dynamic conversion affecting performance}}
+#endif
+
+ priv = to_global(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-warning@-2{{incompatible integer to pointer conversion assigning to 'int *' from 'int'}}
+#else
+ // expected-error@-4{{assigning '__global int *' to 'int *' changes address space of pointer}}
+ // expected-warning@-5{{passing non-generic address space pointer to to_global may cause dynamic conversion affecting performance}}
+#endif
+
+ priv = to_private(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-warning@-2{{incompatible integer to pointer conversion assigning to 'int *' from 'int'}}
+#else
+ // expected-warning@-4{{passing non-generic address space pointer to to_private may cause dynamic conversion affecting performance}}
+#endif
+
+
+ priv = to_local(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-warning@-2{{incompatible integer to pointer conversion assigning to 'int *' from 'int'}}
+#else
+ // expected-error@-4{{assigning '__local int *' to 'int *' changes address space of pointer}}
+ // expected-warning@-5{{passing non-generic address space pointer to to_local may cause dynamic conversion affecting performance}}
+#endif
+
+ glob = to_global(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-warning@-2{{incompatible integer to pointer conversion assigning to '__global int *' from 'int'}}
+#else
+ // expected-warning@-4{{passing non-generic address space pointer to to_global may cause dynamic conversion affecting performance}}
+#endif
+
+ glob = to_private(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-warning@-2{{incompatible integer to pointer conversion assigning to '__global int *' from 'int'}}
+#else
+ // expected-error@-4{{assigning 'int *' to '__global int *' changes address space of pointer}}
+ // expected-warning@-5{{passing non-generic address space pointer to to_private may cause dynamic conversion affecting performance}}
+#endif
+
+ glob = to_local(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-warning@-2{{incompatible integer to pointer conversion assigning to '__global int *' from 'int'}}
+#else
+ // expected-error@-4{{assigning '__local int *' to '__global int *' changes address space of pointer}}
+ // expected-warning@-5{{passing non-generic address space pointer to to_local may cause dynamic conversion affecting performance}}
#endif
global char *glob_c = to_global(loc);
@@ -50,6 +119,15 @@ void test(void) {
// expected-warning@-2{{incompatible integer to pointer conversion initializing '__global char *' with an expression of type 'int'}}
#else
// expected-warning@-4{{incompatible pointer types initializing '__global char *' with an expression of type '__global int *'}}
+ // expected-warning@-5{{passing non-generic address space pointer to to_global may cause dynamic conversion affecting performance}}
+#endif
+
+ glob_wrong_ty = to_global(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+ // expected-warning@-2{{incompatible integer to pointer conversion assigning to '__global float *' from 'int'}}
+#else
+ // expected-warning@-4{{incompatible pointer types assigning to '__global float *' from '__global int *'}}
+ // expected-warning@-5{{passing non-generic address space pointer to to_global may cause dynamic conversion affecting performance}}
#endif
}
diff --git a/test/SemaOpenCLCXX/address-space-templates.cl b/test/SemaOpenCLCXX/address-space-templates.cl
new file mode 100644
index 000000000000..48fbdc7642d6
--- /dev/null
+++ b/test/SemaOpenCLCXX/address-space-templates.cl
@@ -0,0 +1,31 @@
+//RUN: %clang_cc1 %s -cl-std=c++ -pedantic -verify -fsyntax-only
+
+template <typename T>
+struct S {
+ T a; // expected-error{{field may not be qualified with an address space}}
+ T f1(); // expected-error{{function type may not be qualified with an address space}}
+ void f2(T); // expected-error{{parameter may not be qualified with an address space}}
+};
+
+template <typename T>
+T foo1(__global T *i) { // expected-note{{candidate template ignored: substitution failure [with T = __local int]: conflicting address space qualifiers are provided between types '__global T' and '__local int'}}
+ return *i;
+}
+
+template <typename T>
+T *foo2(T *i) {
+ return i;
+}
+
+template <typename T>
+void foo3() {
+ __private T ii; // expected-error{{conflicting address space qualifiers are provided between types 'T' and '__global int'}}
+}
+
+void bar() {
+ S<const __global int> sintgl; // expected-note{{in instantiation of template class 'S<const __global int>' requested here}}
+
+ foo1<__local int>(1); // expected-error{{no matching function for call to 'foo1'}}
+ foo2<__global int>(0);
+ foo3<__global int>(); // expected-note{{in instantiation of function template specialization 'foo3<__global int>' requested here}}
+}
diff --git a/test/SemaTemplate/attributes.cpp b/test/SemaTemplate/attributes.cpp
index 7634b937c906..7a04c4705bf2 100644
--- a/test/SemaTemplate/attributes.cpp
+++ b/test/SemaTemplate/attributes.cpp
@@ -55,11 +55,11 @@ namespace PR9049 {
}
// CHECK: FunctionTemplateDecl {{.*}} HasAnnotations
-// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR"
// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO"
+// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR"
// CHECK: FunctionDecl {{.*}} HasAnnotations
// CHECK: TemplateArgument type 'int'
-// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR"
// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO"
+// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR"
template<typename T> [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
void UseAnnotations() { HasAnnotations<int>(); }
diff --git a/test/SemaTemplate/exception-spec-crash.cpp b/test/SemaTemplate/exception-spec-crash.cpp
index 4d9355974c9e..ebbb30a2c23b 100644
--- a/test/SemaTemplate/exception-spec-crash.cpp
+++ b/test/SemaTemplate/exception-spec-crash.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -DCXX_EXCEPTIONS -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -Wno-defaulted-function-deleted
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -DCXX_EXCEPTIONS -fsyntax-only -verify %s -Wno-defaulted-function-deleted
template <class _Tp> struct is_nothrow_move_constructible {
static const bool value = false;
diff --git a/test/SemaTemplate/friend.cpp b/test/SemaTemplate/friend.cpp
index ef1aed50e626..777682be3f1b 100644
--- a/test/SemaTemplate/friend.cpp
+++ b/test/SemaTemplate/friend.cpp
@@ -47,3 +47,78 @@ inline void foo() {}
inline void bar() {}
C<int> c;
}
+
+namespace qualified_friend {
+ void f(int); // expected-note 2{{type mismatch at 1st parameter}}
+ template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
+ template<typename T> void nondep();
+
+ template<typename> struct X1 {
+ friend void qualified_friend::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend'}}
+ friend void qualified_friend::g(); // expected-error {{friend declaration of 'g' does not match any declaration in namespace 'qualified_friend'}}
+ };
+ template<typename T> struct X2 {
+ friend void qualified_friend::f(T); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend'}}
+ };
+ X1<int> xi;
+ X2<double> xd; // expected-note {{in instantiation of}}
+ X2<int> x2i;
+
+ struct Y {
+ void f(int); // expected-note 2{{type mismatch at 1st parameter}}
+ template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
+ template<typename T> void nondep();
+ };
+
+ template<typename> struct Z1 {
+ friend void Y::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend::Y'}}
+ friend void Y::g(); // expected-error {{friend declaration of 'g' does not match any declaration in 'qualified_friend::Y'}}
+ };
+ template<typename T> struct Z2 {
+ friend void Y::f(T); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend::Y'}}
+ };
+ Z1<int> zi;
+ Z2<double> zd; // expected-note {{in instantiation of}}
+ Z2<int> z2i;
+
+ template<typename T>
+ struct OK {
+ friend void qualified_friend::f(int);
+ friend void qualified_friend::f(int*);
+ friend void qualified_friend::f(T*);
+ friend void qualified_friend::f<T>(T*);
+ friend void qualified_friend::nondep<int>();
+ friend void qualified_friend::nondep<T>();
+
+ friend void Y::f(int);
+ friend void Y::f(int*);
+ friend void Y::f(T*);
+ friend void Y::f<T>(T*);
+ friend void Y::nondep<int>();
+ friend void Y::nondep<T>();
+ };
+ OK<float> ok;
+}
+
+namespace qualified_friend_finds_nothing {
+ // FIXME: The status of this example is unclear. For now, we diagnose if the
+ // qualified declaration has nothing it can redeclare, but allow qualified
+ // lookup to find later-declared function templates during instantiation.
+ //
+ // This matches the behavior of GCC, EDG, ICC, and MSVC (except that GCC and
+ // ICC bizarrely accept the instantiation of B<float>).
+ namespace N {}
+
+ template<typename T> struct A {
+ friend void N::f(T); // expected-error {{friend declaration of 'f' does not match}}
+ };
+ namespace N { void f(); } // expected-note {{different number of parameters}}
+
+ template<typename T> struct B {
+ friend void N::f(T); // expected-error {{friend declaration of 'f' does not match}}
+ };
+ B<float> bf; // expected-note {{in instantiation of}}
+
+ namespace N { void f(int); }
+ B<int> bi; // ok?!
+}
diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp
index 51fa6955d0c0..b58ad3a15763 100644
--- a/test/SemaTemplate/instantiate-init.cpp
+++ b/test/SemaTemplate/instantiate-init.cpp
@@ -115,8 +115,10 @@ namespace PR13064 {
struct A { explicit A(int); }; // expected-note{{here}}
template<typename T> struct B { T a { 0 }; };
B<A> b;
- template<typename T> struct C { T a = { 0 }; }; // expected-error{{explicit}}
- C<A> c; // expected-note {{in instantiation of default member initializer}}
+ template <typename T> struct C { // expected-note {{in instantiation of default member initializer}}
+ T a = {0}; // expected-error{{explicit}}
+ };
+ C<A> c; // expected-note {{in evaluation of exception spec}}
}
namespace PR16903 {
diff --git a/test/SemaTemplate/instantiation-depth-default.cpp b/test/SemaTemplate/instantiation-depth-default.cpp
index 3d89aa18ca43..69efa253e3fe 100644
--- a/test/SemaTemplate/instantiation-depth-default.cpp
+++ b/test/SemaTemplate/instantiation-depth-default.cpp
@@ -14,4 +14,4 @@ template<int N, typename T> struct X : X<N+1, T*> {};
X<0, int> x; // expected-note {{in instantiation of}}
// FIXME: It crashes. Investigating.
-// UNSUPPORTED: mingw32
+// UNSUPPORTED: windows-gnu
diff --git a/test/SemaTemplate/member-specialization.cpp b/test/SemaTemplate/member-specialization.cpp
new file mode 100644
index 000000000000..ea30a7a0cd74
--- /dev/null
+++ b/test/SemaTemplate/member-specialization.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=c++17 -verify %s
+// expected-no-diagnostics
+
+template<typename T, typename U> struct X {
+ template<typename V> const V &as() { return V::error; }
+ template<> const U &as<U>() { return u; }
+ U u;
+};
+int f(X<int, int> x) {
+ return x.as<int>();
+}
diff --git a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index 1a84d545c647..b887c7f47d3c 100644
--- a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
+++ b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
@@ -335,3 +335,46 @@ namespace Nested {
void g(int, int);
using Int = A<int>::B<&g>::param2;
}
+
+namespace rdar41852459 {
+template <auto V> struct G {};
+
+template <class T> struct S {
+ template <auto V> void f() {
+ G<V> x;
+ }
+ template <auto *PV> void f2() {
+ G<PV> x;
+ }
+ template <decltype(auto) V> void f3() {
+ G<V> x;
+ }
+};
+
+template <auto *PV> struct I {};
+
+template <class T> struct K {
+ template <auto *PV> void f() {
+ I<PV> x;
+ }
+ template <auto V> void f2() {
+ I<V> x;
+ }
+ template <decltype(auto) V> void f3() {
+ I<V> x;
+ }
+};
+
+template <decltype(auto)> struct L {};
+template <class T> struct M {
+ template <auto *PV> void f() {
+ L<PV> x;
+ }
+ template <auto V> void f() {
+ L<V> x;
+ }
+ template <decltype(auto) V> void f() {
+ L<V> x;
+ }
+};
+}
diff --git a/test/SemaTemplate/temp_arg_pack.cpp b/test/SemaTemplate/temp_arg_pack.cpp
index b79dca78bced..26e3f6ba5e5e 100644
--- a/test/SemaTemplate/temp_arg_pack.cpp
+++ b/test/SemaTemplate/temp_arg_pack.cpp
@@ -6,3 +6,19 @@ namespace deduce_pack_non_pack {
template <typename T> void g(C<A<T>>); // expected-note {{candidate template ignored: deduced type 'C<A<[...], (no argument)>>' of 1st parameter does not match adjusted type 'C<A<[...], int>>' of argument [with T = bool]}}
void h(C<A<bool, int>> &x) { g(x); } // expected-error {{no matching function}}
}
+
+namespace pr39231 {
+ template<typename T, T ...V> struct integer_sequence {};
+
+ template <typename T, T... A, T... B>
+ int operator^(integer_sequence<T, A...> a, // expected-note {{deduced conflicting values for parameter 'A' (<1, 2, 3> vs. <4, 5, 6>)}}
+ integer_sequence<T, A...> b);
+
+ int v = integer_sequence<int, 1, 2, 3>{} ^ integer_sequence<int, 4, 5, 6>{}; // expected-error {{invalid operands}}
+
+ template <typename T, T... A, T... B>
+ integer_sequence<T, A + B...> operator+(integer_sequence<T, A...> a,
+ integer_sequence<T, B...> b);
+ integer_sequence<int, 5, 7, 9> w =
+ integer_sequence<int, 1, 2, 3>{} + integer_sequence<int, 4, 5, 6>{};
+}
diff --git a/test/SemaTemplate/typename-specifier-3.cpp b/test/SemaTemplate/typename-specifier-3.cpp
index dfab5a0130f8..dc9d00601d48 100644
--- a/test/SemaTemplate/typename-specifier-3.cpp
+++ b/test/SemaTemplate/typename-specifier-3.cpp
@@ -18,3 +18,59 @@ B c() {
template<class T> struct test2 { T b() { return typename T::a; } }; // expected-error{{expected '(' for function-style cast or type construction}}
template<class T> struct test3 { T b() { return typename a; } }; // expected-error{{expected a qualified name after 'typename'}}
template<class T> struct test4 { T b() { return typename ::a; } }; // expected-error{{refers to non-type member}} expected-error{{expected '(' for function-style cast or type construction}}
+
+// PR12884
+namespace PR12884_original {
+ template <typename T> struct A {
+ struct B {
+ template <typename U> struct X {};
+ typedef int arg;
+ };
+ struct C {
+ typedef B::X<typename B::arg> x; // expected-error {{missing 'typename'}}
+ };
+ };
+
+ template <> struct A<int>::B {
+ template <int N> struct X {};
+ static const int arg = 0;
+ };
+
+ A<int>::C::x a;
+}
+namespace PR12884_half_fixed {
+ template <typename T> struct A {
+ struct B {
+ template <typename U> struct X {};
+ typedef int arg;
+ };
+ struct C {
+ typedef typename B::X<typename B::arg> x; // expected-error {{use 'template'}} expected-error {{refers to non-type}}
+ };
+ };
+
+ template <> struct A<int>::B {
+ template <int N> struct X {};
+ static const int arg = 0; // expected-note {{here}}
+ };
+
+ A<int>::C::x a; // expected-note {{here}}
+}
+namespace PR12884_fixed {
+ template <typename T> struct A {
+ struct B {
+ template <typename U> struct X {};
+ typedef int arg;
+ };
+ struct C {
+ typedef typename B::template X<B::arg> x;
+ };
+ };
+
+ template <> struct A<int>::B {
+ template <int N> struct X {};
+ static const int arg = 0;
+ };
+
+ A<int>::C::x a; // ok
+}
diff --git a/test/Tooling/Inputs/mock-libcxx/bin/clang b/test/Tooling/Inputs/mock-libcxx/bin/clang
new file mode 100644
index 000000000000..ed34c1f81868
--- /dev/null
+++ b/test/Tooling/Inputs/mock-libcxx/bin/clang
@@ -0,0 +1 @@
+This file is a placeholder to keep its parent directory in git.
diff --git a/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector b/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector
new file mode 100644
index 000000000000..8512477b5d8e
--- /dev/null
+++ b/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector
@@ -0,0 +1 @@
+class vector {};
diff --git a/test/Tooling/auto-detect-from-source.cpp b/test/Tooling/auto-detect-from-source.cpp
index 12a660d585a9..e6241a9ec3e5 100644
--- a/test/Tooling/auto-detect-from-source.cpp
+++ b/test/Tooling/auto-detect-from-source.cpp
@@ -1,8 +1,12 @@
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
+// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -DSECRET=XYZZY -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
// RUN: cp "%s" "%t/test.cpp"
// RUN: not clang-check "%t/test.cpp" 2>&1 | FileCheck %s
-// CHECK: C++ requires
-invalid;
+// CHECK: XYZZY
+SECRET;
+
+// Copy to a different file, and rely on the command being inferred.
+// RUN: cp "%s" "%t/other.cpp"
+// RUN: not clang-check "%t/other.cpp" 2>&1 | FileCheck %s
diff --git a/test/Tooling/clang-check-analyzer.cpp b/test/Tooling/clang-check-analyzer.cpp
index ee0a6dc369ca..72e1a20e5ff0 100644
--- a/test/Tooling/clang-check-analyzer.cpp
+++ b/test/Tooling/clang-check-analyzer.cpp
@@ -1,4 +1,7 @@
// RUN: clang-check -analyze "%s" -- -c 2>&1 | FileCheck %s
+// RUN: clang-check -analyze "%s" -- -c -flto -Wa,--noexecstack 2>&1 | FileCheck %s
+// RUN: clang-check -analyze "%s" -- -c -no-integrated-as -flto=thin 2>&1 | FileCheck %s
+// RUN: clang-check -analyze "%s" -- -c -flto=full 2>&1 | FileCheck %s
// CHECK: Dereference of null pointer
void a(int *x) { if(x){} *x = 47; }
diff --git a/test/Tooling/clang-check-ast-dump.cpp b/test/Tooling/clang-check-ast-dump.cpp
index d8643c79428e..496d489fd609 100644
--- a/test/Tooling/clang-check-ast-dump.cpp
+++ b/test/Tooling/clang-check-ast-dump.cpp
@@ -32,7 +32,8 @@
// CHECK-ATTR: test_namespace
// CHECK-ATTR-NEXT: FieldDecl{{.*}}n
// CHECK-ATTR-NEXT: AlignedAttr
-// CHECK-ATTR-NEXT: BinaryOperator
+// CHECK-ATTR-NEXT: ConstantExpr
+// CHECK-ATTR-NEXT: BinaryOperator
//
// RUN: clang-check -ast-dump -ast-dump-filter test_namespace::AfterNullNode "%s" -- 2>&1 | FileCheck -check-prefix CHECK-AFTER-NULL %s
// CHECK-AFTER-NULL: class AfterNullNode
diff --git a/test/Tooling/clang-check-extra-arg.cpp b/test/Tooling/clang-check-extra-arg.cpp
index a5d00bc8e892..df5fb930eedc 100644
--- a/test/Tooling/clang-check-extra-arg.cpp
+++ b/test/Tooling/clang-check-extra-arg.cpp
@@ -2,4 +2,8 @@
// CHECK: unknown warning option '-Wunimplemented-warning-before'
// CHECK: unknown warning option '-Wunimplemented-warning'
+
+// Check we do not crash with -extra-arg=-gsplit-dwarf (we did, under linux).
+// RUN: clang-check "%s" -extra-arg=-gsplit-dwarf -- -c
+
void a(){}
diff --git a/test/Tooling/clang-check-mac-libcxx-abspath.cpp b/test/Tooling/clang-check-mac-libcxx-abspath.cpp
new file mode 100644
index 000000000000..476ba3ce0849
--- /dev/null
+++ b/test/Tooling/clang-check-mac-libcxx-abspath.cpp
@@ -0,0 +1,17 @@
+// Clang on MacOS can find libc++ living beside the installed compiler.
+// This test makes sure our libTooling-based tools emulate this properly.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
+// Install the mock libc++ (simulates the libc++ directory structure).
+// RUN: cp -r %S/Inputs/mock-libcxx %t/
+//
+// Pretend clang is installed beside the mock library that we provided.
+// RUN: echo '[{"directory":"%t","command":"%t/mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json
+// RUN: cp "%s" "%t/test.cpp"
+// clang-check will produce an error code if the mock library is not found.
+// RUN: clang-check -p "%t" "%t/test.cpp"
+
+#include <mock_vector>
+vector v;
diff --git a/test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp b/test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp
new file mode 100644
index 000000000000..035155c96c92
--- /dev/null
+++ b/test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp
@@ -0,0 +1,16 @@
+// Clang on MacOS can find libc++ living beside the installed compiler.
+// This test makes sure our libTooling-based tools emulate this properly with
+// fixed compilation database.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
+// Install the mock libc++ (simulates the libc++ directory structure).
+// RUN: cp -r %S/Inputs/mock-libcxx %t/
+//
+// RUN: cp $(which clang-check) %t/mock-libcxx/bin/
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: %t/mock-libcxx/bin/clang-check -p "%t" "%t/test.cpp" -- -stdlib=libc++
+
+#include <mock_vector>
+vector v;
diff --git a/test/Tooling/clang-check-mac-libcxx-relpath.cpp b/test/Tooling/clang-check-mac-libcxx-relpath.cpp
new file mode 100644
index 000000000000..099be5ecd498
--- /dev/null
+++ b/test/Tooling/clang-check-mac-libcxx-relpath.cpp
@@ -0,0 +1,17 @@
+// Clang on MacOS can find libc++ living beside the installed compiler.
+// This test makes sure our libTooling-based tools emulate this properly.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
+// Install the mock libc++ (simulates the libc++ directory structure).
+// RUN: cp -r %S/Inputs/mock-libcxx %t/
+//
+// Pretend clang is installed beside the mock library that we provided.
+// RUN: echo '[{"directory":"%t","command":"mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json
+// RUN: cp "%s" "%t/test.cpp"
+// clang-check will produce an error code if the mock library is not found.
+// RUN: clang-check -p "%t" "%t/test.cpp"
+
+#include <mock_vector>
+vector v;
diff --git a/test/Tooling/clang-diff-json.cpp b/test/Tooling/clang-diff-json.cpp
index 20c808cb0f19..cc2bb0805e53 100644
--- a/test/Tooling/clang-diff-json.cpp
+++ b/test/Tooling/clang-diff-json.cpp
@@ -1,10 +1,10 @@
// RUN: clang-diff -ast-dump-json %s -- \
-// RUN: | '%python' -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
+// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s
-// CHECK: "begin": 301,
+// CHECK: "begin": 311,
// CHECK: "type": "FieldDecl",
-// CHECK: "end": 321,
+// CHECK: "end": 319,
// CHECK: "type": "CXXRecordDecl",
class A {
int x;
diff --git a/test/VFS/Inputs/Broken.framework/Headers/Error.h b/test/VFS/Inputs/Broken.framework/Headers/Error.h
new file mode 100644
index 000000000000..12352dd19a54
--- /dev/null
+++ b/test/VFS/Inputs/Broken.framework/Headers/Error.h
@@ -0,0 +1,3 @@
+// Error.h
+
+#error Should not include this header in a module
diff --git a/test/VFS/Inputs/Broken.framework/Modules/module.modulemap b/test/VFS/Inputs/Broken.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..5d033c635a5e
--- /dev/null
+++ b/test/VFS/Inputs/Broken.framework/Modules/module.modulemap
@@ -0,0 +1,6 @@
+framework module Broken [extern_c] {
+ umbrella "Headers"
+ export *
+ module * { export * }
+}
+
diff --git a/test/VFS/Inputs/Broken.framework/VFSHeaders/A.h b/test/VFS/Inputs/Broken.framework/VFSHeaders/A.h
new file mode 100644
index 000000000000..975f1f0437bb
--- /dev/null
+++ b/test/VFS/Inputs/Broken.framework/VFSHeaders/A.h
@@ -0,0 +1 @@
+// A.h
diff --git a/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml b/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml
index 49517a159080..cb74879bafa2 100644
--- a/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml
+++ b/test/VFS/Inputs/MissingVFS/vfsoverlay.yaml
@@ -1,6 +1,5 @@
{
'version': 0,
- 'ignore-non-existent-contents': false,
'roots': [
{ 'name': 'INPUT_DIR', 'type': 'directory',
'contents': [
diff --git a/test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml b/test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml
index a04172875228..7ccddd2d2f82 100644
--- a/test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml
+++ b/test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml
@@ -1,7 +1,6 @@
{
'version': 0,
'case-sensitive': 'false',
- 'ignore-non-existent-contents': 'true',
'roots': [
{
'type': 'directory',
diff --git a/test/VFS/Inputs/bar-headers.yaml b/test/VFS/Inputs/bar-headers.yaml
index 846d55cc9ece..710e6cb06007 100644
--- a/test/VFS/Inputs/bar-headers.yaml
+++ b/test/VFS/Inputs/bar-headers.yaml
@@ -1,7 +1,6 @@
{
'version': 0,
'case-sensitive': 'false',
- 'ignore-non-existent-contents': 'true',
'roots': [
{
'type': 'directory',
diff --git a/test/VFS/Inputs/vfsoverlay2.yaml b/test/VFS/Inputs/vfsoverlay2.yaml
index 688ae643df03..ae2a0ce4ec98 100644
--- a/test/VFS/Inputs/vfsoverlay2.yaml
+++ b/test/VFS/Inputs/vfsoverlay2.yaml
@@ -1,6 +1,5 @@
{
'version': 0,
- 'ignore-non-existent-contents': false,
'roots': [
{ 'name': 'OUT_DIR', 'type': 'directory',
'contents': [
diff --git a/test/VFS/Inputs/vfsroot.yaml b/test/VFS/Inputs/vfsroot.yaml
new file mode 100644
index 000000000000..0b00692b6451
--- /dev/null
+++ b/test/VFS/Inputs/vfsroot.yaml
@@ -0,0 +1,55 @@
+{
+ 'version': 0,
+ 'use-external-names': false,
+ 'fallthrough': false,
+ 'roots': [
+ { 'name': '/tests', 'type': 'directory',
+ 'contents': [
+ { 'name': 'vfsroot-include.c', 'type': 'file',
+ 'external-contents': 'TEST_DIR/vfsroot-include.c'
+ },
+ { 'name': 'vfsroot-with-overlay.c', 'type': 'file',
+ 'external-contents': 'TEST_DIR/vfsroot-with-overlay.c'
+ },
+ { 'name': 'vfsroot-module.m', 'type': 'file',
+ 'external-contents': 'TEST_DIR/vfsroot-module.m'
+ }
+ ]
+ },
+ { 'name': '/direct-vfs-root-files', 'type': 'directory',
+ 'contents': [
+ { 'name': 'not_real.h', 'type': 'file',
+ 'external-contents': 'TEST_DIR/Inputs/actual_header.h'
+ },
+ { 'name': 'vfsoverlay.yaml', 'type': 'file',
+ 'external-contents': 'OUT_DIR/vfsoverlay.yaml'
+ }
+ ]
+ },
+ { 'name': '/indirect-vfs-root-files', 'type': 'directory',
+ 'contents': [
+ { 'name': 'actual_header.h', 'type': 'file',
+ 'external-contents': 'TEST_DIR/Inputs/actual_header.h'
+ }
+ ]
+ },
+ { 'name': 'TEST_DIR/Inputs/Broken.framework', 'type': 'directory',
+ 'contents': [
+ { 'name': 'Headers/A.h', 'type': 'file',
+ 'external-contents': 'TEST_DIR/Inputs/Broken.framework/VFSHeaders/A.h'
+ },
+ { 'name': 'Modules/module.modulemap', 'type': 'file',
+ 'external-contents': 'TEST_DIR/Inputs/Broken.framework/Modules/module.modulemap'
+ }
+ ]
+ },
+ # Locations for modules.
+ { 'name': 'OUT_DIR/cache', 'type': 'directory',
+ 'contents': [
+ { 'name': 'Broken.pcm', 'type': 'file',
+ 'external-contents': 'OUT_DIR/cache/Broken.pcm'
+ }
+ ]
+ }
+ ]
+}
diff --git a/test/VFS/subframework-symlink.m b/test/VFS/subframework-symlink.m
new file mode 100644
index 000000000000..1c6fd0640938
--- /dev/null
+++ b/test/VFS/subframework-symlink.m
@@ -0,0 +1,23 @@
+// REQUIRES: shell
+
+// Test that when a subframework is a symlink to another framework, we don't
+// add it as a submodule to the enclosing framework. We also need to make clang
+// to infer module for the enclosing framework. For this we don't have
+// a module map for the framework itself but have it in a parent directory.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo 'framework module * {}' > %t/module.modulemap
+// RUN: mkdir -p %t/WithSubframework.framework/Headers
+// RUN: echo '#include <Foo/Foo.h>' > %t/WithSubframework.framework/Headers/WithSubframework.h
+// RUN: cp -R %S/Inputs/Foo.framework %t
+// RUN: mkdir -p %t/WithSubframework.framework/Frameworks
+// RUN: ln -s %t/Foo.framework %t/WithSubframework.framework/Frameworks
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache1 -F %t -fsyntax-only %s
+
+// Adding VFS overlay shouldn't change this behavior.
+//
+// RUN: sed -e "s:INPUT_DIR:/InvalidPath:g" -e "s:OUT_DIR:/InvalidPath:g" %S/Inputs/vfsoverlay.yaml > %t/overlay.yaml
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache2 -F %t -fsyntax-only %s -ivfsoverlay %t/overlay.yaml
+
+#import <WithSubframework/WithSubframework.h>
diff --git a/test/VFS/umbrella-framework-import-skipnonexist.m b/test/VFS/umbrella-framework-import-skipnonexist.m
index 129f475fe774..2f148cee7e2d 100644
--- a/test/VFS/umbrella-framework-import-skipnonexist.m
+++ b/test/VFS/umbrella-framework-import-skipnonexist.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// RUN: rm -rf %t
// RUN: mkdir -p %t/vdir %t/outdir %t/cache
diff --git a/test/VFS/vfsroot-include.c b/test/VFS/vfsroot-include.c
new file mode 100644
index 000000000000..7ccd9d705ec3
--- /dev/null
+++ b/test/VFS/vfsroot-include.c
@@ -0,0 +1,17 @@
+// REQUIRES: shell
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: sed -e "s:TEST_DIR:%S:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsroot.yaml > %t.yaml
+// RUN: not %clang_cc1 -Werror -ivfsoverlay %t.yaml -I %S/Inputs -I /direct-vfs-root-files -fsyntax-only /tests/vfsroot-include.c 2>&1 | FileCheck %s
+// The line above tests that the compiler input file is looked up through VFS.
+
+// Test successful include through the VFS.
+#include "not_real.h"
+
+// Test that a file missing from the VFS root is not found, even if it is
+// discoverable through the real file system. Fatal error should be the last
+// in the file as it hides other errors.
+#include "actual_header.h"
+// CHECK: fatal error: 'actual_header.h' file not found
+// CHECK: 1 error generated.
+// CHECK-NOT: error
diff --git a/test/VFS/vfsroot-module.m b/test/VFS/vfsroot-module.m
new file mode 100644
index 000000000000..22822cf5a5e6
--- /dev/null
+++ b/test/VFS/vfsroot-module.m
@@ -0,0 +1,10 @@
+// REQUIRES: shell
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: sed -e "s:TEST_DIR:%S:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsroot.yaml > %t.yaml
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/cache -ivfsoverlay %t.yaml -F %S/Inputs -fsyntax-only /tests/vfsroot-module.m
+
+// Test that a file missing from the VFS root is not found, even if it is
+// discoverable through the real file system at location that is a part of
+// the framework.
+@import Broken;
diff --git a/test/VFS/vfsroot-with-overlay.c b/test/VFS/vfsroot-with-overlay.c
new file mode 100644
index 000000000000..6becb6abce1e
--- /dev/null
+++ b/test/VFS/vfsroot-with-overlay.c
@@ -0,0 +1,12 @@
+// REQUIRES: shell
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: sed -e "s:TEST_DIR:%S:g" -e "s:OUT_DIR:%t:g" %S/Inputs/vfsroot.yaml > %t.yaml
+// RUN: sed -e "s:INPUT_DIR:/indirect-vfs-root-files:g" -e "s:OUT_DIR:/overlay-dir:g" %S/Inputs/vfsoverlay.yaml > %t/vfsoverlay.yaml
+// RUN: %clang_cc1 -Werror -ivfsoverlay %t.yaml -ivfsoverlay /direct-vfs-root-files/vfsoverlay.yaml -I /overlay-dir -fsyntax-only /tests/vfsroot-with-overlay.c
+
+#include "not_real.h"
+
+void foo() {
+ bar();
+}
diff --git a/test/lit.cfg.py b/test/lit.cfg.py
index ad30988c1796..ace0b81081d3 100644
--- a/test/lit.cfg.py
+++ b/test/lit.cfg.py
@@ -43,6 +43,10 @@ llvm_config.use_default_substitutions()
llvm_config.use_clang()
+config.substitutions.append(
+ ('%src_include_dir', config.clang_src_dir + '/include'))
+
+
# Propagate path to symbolizer for ASan/MSan.
llvm_config.with_system_environment(
['ASAN_SYMBOLIZER_PATH', 'MSAN_SYMBOLIZER_PATH'])
@@ -59,8 +63,8 @@ tool_dirs = [config.clang_tools_dir, config.llvm_tools_dir]
tools = [
'c-index-test', 'clang-check', 'clang-diff', 'clang-format', 'clang-tblgen',
'opt',
- ToolSubst('%clang_func_map', command=FindTool(
- 'clang-func-mapping'), unresolved='ignore'),
+ ToolSubst('%clang_extdef_map', command=FindTool(
+ 'clang-extdef-mapping'), unresolved='ignore'),
]
if config.clang_examples:
@@ -71,7 +75,7 @@ llvm_config.add_tool_substitutions(tools, tool_dirs)
config.substitutions.append(
('%hmaptool', "'%s' %s" % (config.python_executable,
- os.path.join(config.llvm_tools_dir, 'hmaptool'))))
+ os.path.join(config.clang_tools_dir, 'hmaptool'))))
# Plugins (loadable modules)
# TODO: This should be supplied by Makefile or autoconf.
@@ -137,7 +141,7 @@ if os.path.exists('/dev/fd/0') and sys.platform not in ['cygwin']:
config.available_features.add('dev-fd-fs')
# Not set on native MS environment.
-if not re.match(r'.*-win32$', config.target_triple):
+if not re.match(r'.*-(windows-msvc)$', config.target_triple):
config.available_features.add('non-ms-sdk')
# Not set on native PS4 environment.
@@ -145,7 +149,7 @@ if not re.match(r'.*-scei-ps4', config.target_triple):
config.available_features.add('non-ps4-sdk')
# [PR8833] LLP64-incompatible tests
-if not re.match(r'^x86_64.*-(win32|mingw32|windows-gnu)$', config.target_triple):
+if not re.match(r'^x86_64.*-(windows-msvc|windows-gnu)$', config.target_triple):
config.available_features.add('LP64')
# [PR12920] "clang-driver" -- set if gcc driver is not used.
@@ -186,3 +190,6 @@ lit.util.usePlatformSdkOnDarwin(config, lit_config)
macOSSDKVersion = lit.util.findPlatformSdkVersionOnMacOS(config, lit_config)
if macOSSDKVersion is not None:
config.available_features.add('macos-sdk-' + macOSSDKVersion)
+
+if os.path.exists('/etc/gentoo-release'):
+ config.available_features.add('gentoo')
diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in
index 361d4e44d679..fd89fd13a691 100644
--- a/test/lit.site.cfg.py.in
+++ b/test/lit.site.cfg.py.in
@@ -26,6 +26,7 @@ config.enable_shared = @ENABLE_SHARED@
config.enable_backtrace = @ENABLE_BACKTRACES@
config.host_arch = "@HOST_ARCH@"
config.python_executable = "@PYTHON_EXECUTABLE@"
+config.use_z3_solver = lit_config.params.get('USE_Z3_SOLVER', "@USE_Z3_SOLVER@")
# 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.
@@ -39,7 +40,8 @@ except KeyError:
key, = e.args
lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
-@LIT_SITE_CFG_IN_FOOTER@
+import lit.llvm
+lit.llvm.initialize(lit_config, config)
# Let the main config do the real work.
lit_config.load_config(config, "@CLANG_SOURCE_DIR@/test/lit.cfg.py")
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 9f76d36dba0e..43dfffe1492e 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -21,7 +21,7 @@ endif()
if(CLANG_ENABLE_STATIC_ANALYZER)
add_clang_subdirectory(clang-check)
- add_clang_subdirectory(clang-func-mapping)
+ add_clang_subdirectory(clang-extdef-mapping)
add_clang_subdirectory(scan-build)
add_clang_subdirectory(scan-view)
endif()
diff --git a/tools/arcmt-test/CMakeLists.txt b/tools/arcmt-test/CMakeLists.txt
index 2b456be2fcdd..c4c1463241b4 100644
--- a/tools/arcmt-test/CMakeLists.txt
+++ b/tools/arcmt-test/CMakeLists.txt
@@ -12,4 +12,5 @@ target_link_libraries(arcmt-test
clangBasic
clangFrontend
clangLex
+ clangSerialization
)
diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp
index e57d69fddbe2..80354788a30c 100644
--- a/tools/arcmt-test/arcmt-test.cpp
+++ b/tools/arcmt-test/arcmt-test.cpp
@@ -130,7 +130,7 @@ static bool checkForMigration(StringRef resourcesPath,
return true;
}
- if (!CI.getLangOpts()->ObjC1)
+ if (!CI.getLangOpts()->ObjC)
return false;
arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0],
@@ -170,7 +170,7 @@ static bool performTransformations(StringRef resourcesPath,
return true;
}
- if (!origCI.getLangOpts()->ObjC1)
+ if (!origCI.getLangOpts()->ObjC)
return false;
MigrationProcess migration(origCI, std::make_shared<PCHContainerOperations>(),
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 70ab11866edd..fc6ba46fd6f2 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -84,6 +84,10 @@ static unsigned getDefaultParsingOptions() {
options |= CXTranslationUnit_KeepGoing;
if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE"))
options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble;
+ if (getenv("CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES"))
+ options |= CXTranslationUnit_IncludeAttributedTypes;
+ if (getenv("CINDEXTEST_VISIT_IMPLICIT_ATTRIBUTES"))
+ options |= CXTranslationUnit_VisitImplicitAttributes;
return options;
}
@@ -1099,6 +1103,34 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
}
}
+ if (Cursor.kind == CXCursor_ObjCPropertyDecl) {
+ CXString Name = clang_Cursor_getObjCPropertyGetterName(Cursor);
+ CXString Spelling = clang_getCursorSpelling(Cursor);
+ const char *CName = clang_getCString(Name);
+ const char *CSpelling = clang_getCString(Spelling);
+ if (CName && strcmp(CName, CSpelling)) {
+ printf(" (getter=%s)", CName);
+ }
+ clang_disposeString(Spelling);
+ clang_disposeString(Name);
+ }
+
+ if (Cursor.kind == CXCursor_ObjCPropertyDecl) {
+ CXString Name = clang_Cursor_getObjCPropertySetterName(Cursor);
+ CXString Spelling = clang_getCursorSpelling(Cursor);
+ const char *CName = clang_getCString(Name);
+ const char *CSpelling = clang_getCString(Spelling);
+ char *DefaultSetter = malloc(strlen(CSpelling) + 5);
+ sprintf(DefaultSetter, "set%s:", CSpelling);
+ DefaultSetter[3] &= ~(1 << 5); /* Make uppercase */
+ if (CName && strcmp(CName, DefaultSetter)) {
+ printf(" (setter=%s)", CName);
+ }
+ free(DefaultSetter);
+ clang_disposeString(Spelling);
+ clang_disposeString(Name);
+ }
+
{
unsigned QT = clang_Cursor_getObjCDeclQualifiers(Cursor);
if (QT != CXObjCDeclQualifier_None) {
@@ -1496,13 +1528,31 @@ static void PrintTypeTemplateArgs(CXType T, const char *Format) {
}
}
+static void PrintNullabilityKind(CXType T, const char *Format) {
+ enum CXTypeNullabilityKind N = clang_Type_getNullability(T);
+
+ const char *nullability = 0;
+ switch (N) {
+ case CXTypeNullability_NonNull: nullability = "nonnull"; break;
+ case CXTypeNullability_Nullable: nullability = "nullable"; break;
+ case CXTypeNullability_Unspecified: nullability = "unspecified"; break;
+ case CXTypeNullability_Invalid: break;
+ }
+
+ if (nullability) {
+ printf(Format, nullability);
+ }
+}
+
static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
CXClientData d) {
if (!clang_isInvalid(clang_getCursorKind(cursor))) {
CXType T = clang_getCursorType(cursor);
+ CXType PT = clang_getPointeeType(T);
enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T);
PrintCursor(cursor, NULL);
PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]");
+ PrintNullabilityKind(T, " [nullability=%s]");
if (clang_isConstQualifiedType(T))
printf(" const");
if (clang_isVolatileQualifiedType(T))
@@ -1523,12 +1573,20 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
PrintTypeTemplateArgs(CT, " [canonicaltemplateargs/%d=");
}
}
+ /* Print the modified type if it exists. */
+ {
+ CXType MT = clang_Type_getModifiedType(T);
+ if (MT.kind != CXType_Invalid) {
+ PrintTypeAndTypeKind(MT, " [modifiedtype=%s] [modifiedtypekind=%s]");
+ }
+ }
/* Print the return type if it exists. */
{
CXType RT = clang_getCursorResultType(cursor);
if (RT.kind != CXType_Invalid) {
PrintTypeAndTypeKind(RT, " [resulttype=%s] [resulttypekind=%s]");
}
+ PrintNullabilityKind(RT, " [resultnullability=%s]");
}
/* Print the argument types if they exist. */
{
@@ -1540,6 +1598,42 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i));
if (T.kind != CXType_Invalid) {
PrintTypeAndTypeKind(T, " [%s] [%s]");
+ PrintNullabilityKind(T, " [%s]");
+ }
+ }
+ printf("]");
+ }
+ }
+ /* Print ObjC base types, type arguments, and protocol list if available. */
+ {
+ CXType BT = clang_Type_getObjCObjectBaseType(PT);
+ if (BT.kind != CXType_Invalid) {
+ PrintTypeAndTypeKind(BT, " [basetype=%s] [basekind=%s]");
+ }
+ }
+ {
+ unsigned NumTypeArgs = clang_Type_getNumObjCTypeArgs(PT);
+ if (NumTypeArgs > 0) {
+ unsigned i;
+ printf(" [typeargs=");
+ for (i = 0; i < NumTypeArgs; ++i) {
+ CXType TA = clang_Type_getObjCTypeArg(PT, i);
+ if (TA.kind != CXType_Invalid) {
+ PrintTypeAndTypeKind(TA, " [%s] [%s]");
+ }
+ }
+ printf("]");
+ }
+ }
+ {
+ unsigned NumProtocols = clang_Type_getNumObjCProtocolRefs(PT);
+ if (NumProtocols > 0) {
+ unsigned i;
+ printf(" [protocols=");
+ for (i = 0; i < NumProtocols; ++i) {
+ CXCursor P = clang_Type_getObjCProtocolDecl(PT, i);
+ if (!clang_isInvalid(clang_getCursorKind(P))) {
+ PrintCursor(P, NULL);
}
}
printf("]");
@@ -1549,7 +1643,6 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
printf(" [isPOD=%d]", clang_isPODType(T));
/* Print the pointee type. */
{
- CXType PT = clang_getPointeeType(T);
if (PT.kind != CXType_Invalid) {
PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]");
}
@@ -1561,13 +1654,14 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
if (numFields != 0) {
printf(" [nbFields=%d]", numFields);
}
- /* Print if it is an anonymous record. */
- {
- unsigned isAnon = clang_Cursor_isAnonymous(cursor);
- if (isAnon != 0) {
- printf(" [isAnon=%d]", isAnon);
- }
- }
+ }
+ }
+
+ /* Print if it is an anonymous record or namespace. */
+ {
+ unsigned isAnon = clang_Cursor_isAnonymous(cursor);
+ if (isAnon != 0) {
+ printf(" [isAnon=%d]", isAnon);
}
}
@@ -1720,6 +1814,23 @@ static enum CXChildVisitResult PrintTypeDeclaration(CXCursor cursor, CXCursor p,
}
/******************************************************************************/
+/* Declaration attributes testing */
+/******************************************************************************/
+
+static enum CXChildVisitResult PrintDeclAttributes(CXCursor cursor, CXCursor p,
+ CXClientData d) {
+ if (clang_isDeclaration(cursor.kind)) {
+ printf("\n");
+ PrintCursor(cursor, NULL);
+ return CXChildVisit_Recurse;
+ } else if (clang_isAttribute(cursor.kind)) {
+ printf(" ");
+ PrintCursor(cursor, NULL);
+ }
+ return CXChildVisit_Continue;
+}
+
+/******************************************************************************/
/* Target information testing. */
/******************************************************************************/
@@ -4730,6 +4841,9 @@ int cindextest_main(int argc, const char **argv) {
else if (argc > 2 && strcmp(argv[1], "-test-print-type-declaration") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all",
PrintTypeDeclaration, 0);
+ else if (argc > 2 && strcmp(argv[1], "-test-print-decl-attributes") == 0)
+ return perform_test_load_source(argc - 2, argv + 2, "all",
+ PrintDeclAttributes, 0);
else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all",
PrintBitWidth, 0);
diff --git a/tools/c-index-test/core_main.cpp b/tools/c-index-test/core_main.cpp
index a7732c09d5b0..b9c0f19a7fcc 100644
--- a/tools/c-index-test/core_main.cpp
+++ b/tools/c-index-test/core_main.cpp
@@ -20,6 +20,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -73,6 +74,7 @@ static cl::opt<std::string>
static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);
static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
raw_ostream &OS);
+static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS);
namespace {
@@ -131,8 +133,9 @@ public:
return true;
}
- bool handleModuleOccurence(const ImportDecl *ImportD, SymbolRoleSet Roles,
- SourceLocation Loc) override {
+ bool handleModuleOccurence(const ImportDecl *ImportD,
+ const clang::Module *Mod,
+ SymbolRoleSet Roles, SourceLocation Loc) override {
ASTContext &Ctx = ImportD->getASTContext();
SourceManager &SM = Ctx.getSourceManager();
@@ -145,7 +148,8 @@ public:
printSymbolInfo(getSymbolInfo(ImportD), OS);
OS << " | ";
- OS << ImportD->getImportedModule()->getFullModuleName() << " | ";
+ printSymbolNameAndUSR(Mod, OS);
+ OS << " | ";
printSymbolRoles(Roles, OS);
OS << " |\n";
@@ -202,11 +206,11 @@ static void dumpModuleFileInputs(serialization::ModuleFile &Mod,
});
}
-static bool printSourceSymbols(ArrayRef<const char *> Args,
- bool dumpModuleImports,
- bool indexLocals) {
+static bool printSourceSymbols(const char *Executable,
+ ArrayRef<const char *> Args,
+ bool dumpModuleImports, bool indexLocals) {
SmallVector<const char *, 4> ArgsWithProgName;
- ArgsWithProgName.push_back("clang");
+ ArgsWithProgName.push_back(Executable);
ArgsWithProgName.append(Args.begin(), Args.end());
IntrusiveRefCntPtr<DiagnosticsEngine>
Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
@@ -307,6 +311,12 @@ static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
}
}
+static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS) {
+ assert(Mod);
+ OS << Mod->getFullModuleName() << " | ";
+ generateFullUSRForModule(Mod, OS);
+}
+
//===----------------------------------------------------------------------===//
// Command line processing.
//===----------------------------------------------------------------------===//
@@ -314,6 +324,8 @@ static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
int indextest_core_main(int argc, const char **argv) {
sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
+ void *MainAddr = (void*) (intptr_t) indextest_core_main;
+ std::string Executable = llvm::sys::fs::getMainExecutable(argv[0], MainAddr);
assert(argv[1] == StringRef("core"));
++argv;
@@ -343,7 +355,9 @@ int indextest_core_main(int argc, const char **argv) {
errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n";
return 1;
}
- return printSourceSymbols(CompArgs, options::DumpModuleImports, options::IncludeLocals);
+ return printSourceSymbols(Executable.c_str(), CompArgs,
+ options::DumpModuleImports,
+ options::IncludeLocals);
}
return 0;
diff --git a/tools/clang-check/CMakeLists.txt b/tools/clang-check/CMakeLists.txt
index c5ace26c2914..b837b0a0a5d9 100644
--- a/tools/clang-check/CMakeLists.txt
+++ b/tools/clang-check/CMakeLists.txt
@@ -15,6 +15,7 @@ target_link_libraries(clang-check
clangDriver
clangFrontend
clangRewriteFrontend
+ clangSerialization
clangStaticAnalyzerFrontend
clangTooling
)
diff --git a/tools/clang-check/ClangCheck.cpp b/tools/clang-check/ClangCheck.cpp
index f00e9a3df0ad..66d865b749a1 100644
--- a/tools/clang-check/ClangCheck.cpp
+++ b/tools/clang-check/ClangCheck.cpp
@@ -122,7 +122,7 @@ public:
/// Subclasses \c clang::FixItAction so that we can install the custom
/// \c FixItRewriter.
-class FixItAction : public clang::FixItAction {
+class ClangCheckFixItAction : public clang::FixItAction {
public:
bool BeginSourceFileAction(clang::CompilerInstance& CI) override {
FixItOpts.reset(new FixItOptions);
@@ -167,6 +167,7 @@ int main(int argc, const char **argv) {
// Clear adjusters because -fsyntax-only is inserted by the default chain.
Tool.clearArgumentsAdjusters();
Tool.appendArgumentsAdjuster(getClangStripOutputAdjuster());
+ Tool.appendArgumentsAdjuster(getClangStripDependencyFileAdjuster());
// Running the analyzer requires --analyze. Other modes can work with the
// -fsyntax-only option.
@@ -180,7 +181,7 @@ int main(int argc, const char **argv) {
if (Analyze)
FrontendFactory = newFrontendActionFactory<clang::ento::AnalysisAction>();
else if (Fixit)
- FrontendFactory = newFrontendActionFactory<FixItAction>();
+ FrontendFactory = newFrontendActionFactory<ClangCheckFixItAction>();
else
FrontendFactory = newFrontendActionFactory(&CheckFactory);
diff --git a/tools/clang-diff/CMakeLists.txt b/tools/clang-diff/CMakeLists.txt
index 09bebf2cb6e5..ab9a5bbbe916 100644
--- a/tools/clang-diff/CMakeLists.txt
+++ b/tools/clang-diff/CMakeLists.txt
@@ -10,6 +10,7 @@ target_link_libraries(clang-diff
PRIVATE
clangBasic
clangFrontend
+ clangSerialization
clangTooling
clangToolingASTDiff
)
diff --git a/tools/clang-func-mapping/CMakeLists.txt b/tools/clang-extdef-mapping/CMakeLists.txt
index ae28e28d532d..6c81689a831a 100644
--- a/tools/clang-func-mapping/CMakeLists.txt
+++ b/tools/clang-extdef-mapping/CMakeLists.txt
@@ -1,23 +1,21 @@
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
- asmparser
support
- mc
)
-add_clang_executable(clang-func-mapping
- ClangFnMapGen.cpp
+add_clang_executable(clang-extdef-mapping
+ ClangExtDefMapGen.cpp
)
-target_link_libraries(clang-func-mapping
+target_link_libraries(clang-extdef-mapping
PRIVATE
clangAST
clangBasic
clangCrossTU
clangFrontend
- clangIndex
+ clangSerialization
clangTooling
)
-install(TARGETS clang-func-mapping
+install(TARGETS clang-extdef-mapping
RUNTIME DESTINATION bin)
diff --git a/tools/clang-func-mapping/ClangFnMapGen.cpp b/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
index 4bf812fffe34..7885f3901897 100644
--- a/tools/clang-func-mapping/ClangFnMapGen.cpp
+++ b/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
@@ -14,61 +14,53 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/GlobalDecl.h"
-#include "clang/AST/Mangle.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
#include "clang/CrossTU/CrossTranslationUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
-#include "clang/Index/USRGeneration.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
#include <sstream>
#include <string>
-#include <vector>
using namespace llvm;
using namespace clang;
using namespace clang::cross_tu;
using namespace clang::tooling;
-static cl::OptionCategory ClangFnMapGenCategory("clang-fnmapgen options");
+static cl::OptionCategory ClangExtDefMapGenCategory("clang-extdefmapgen options");
-class MapFunctionNamesConsumer : public ASTConsumer {
+class MapExtDefNamesConsumer : public ASTConsumer {
public:
- MapFunctionNamesConsumer(ASTContext &Context) : Ctx(Context) {}
+ MapExtDefNamesConsumer(ASTContext &Context)
+ : SM(Context.getSourceManager()) {}
- ~MapFunctionNamesConsumer() {
+ ~MapExtDefNamesConsumer() {
// Flush results to standard output.
llvm::outs() << createCrossTUIndexString(Index);
}
- virtual void HandleTranslationUnit(ASTContext &Ctx) {
+ void HandleTranslationUnit(ASTContext &Ctx) override {
handleDecl(Ctx.getTranslationUnitDecl());
}
private:
void handleDecl(const Decl *D);
- ASTContext &Ctx;
+ SourceManager &SM;
llvm::StringMap<std::string> Index;
std::string CurrentFileName;
};
-void MapFunctionNamesConsumer::handleDecl(const Decl *D) {
+void MapExtDefNamesConsumer::handleDecl(const Decl *D) {
if (!D)
return;
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isThisDeclarationADefinition()) {
if (const Stmt *Body = FD->getBody()) {
- std::string LookupName = CrossTranslationUnitContext::getLookupName(FD);
- const SourceManager &SM = Ctx.getSourceManager();
if (CurrentFileName.empty()) {
CurrentFileName =
SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName();
@@ -80,8 +72,12 @@ void MapFunctionNamesConsumer::handleDecl(const Decl *D) {
case ExternalLinkage:
case VisibleNoLinkage:
case UniqueExternalLinkage:
- if (SM.isInMainFile(Body->getLocStart()))
+ if (SM.isInMainFile(Body->getBeginLoc())) {
+ std::string LookupName =
+ CrossTranslationUnitContext::getLookupName(FD);
Index[LookupName] = CurrentFileName;
+ }
+ break;
default:
break;
}
@@ -94,13 +90,11 @@ void MapFunctionNamesConsumer::handleDecl(const Decl *D) {
handleDecl(D);
}
-class MapFunctionNamesAction : public ASTFrontendAction {
+class MapExtDefNamesAction : public ASTFrontendAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef) {
- std::unique_ptr<ASTConsumer> PFC(
- new MapFunctionNamesConsumer(CI.getASTContext()));
- return PFC;
+ return llvm::make_unique<MapExtDefNamesConsumer>(CI.getASTContext());
}
};
@@ -112,13 +106,13 @@ int main(int argc, const char **argv) {
PrettyStackTraceProgram X(argc, argv);
const char *Overview = "\nThis tool collects the USR name and location "
- "of all functions definitions in the source files "
+ "of external definitions in the source files "
"(excluding headers).\n";
- CommonOptionsParser OptionsParser(argc, argv, ClangFnMapGenCategory,
+ CommonOptionsParser OptionsParser(argc, argv, ClangExtDefMapGenCategory,
cl::ZeroOrMore, Overview);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
- Tool.run(newFrontendActionFactory<MapFunctionNamesAction>().get());
- return 0;
+
+ return Tool.run(newFrontendActionFactory<MapExtDefNamesAction>().get());
}
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index de2f9d7fe76e..49162d0d910e 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/tools/clang-format/ClangFormat.cpp
@@ -116,7 +116,7 @@ namespace format {
static FileID createInMemoryFile(StringRef FileName, MemoryBuffer *Source,
SourceManager &Sources, FileManager &Files,
- vfs::InMemoryFileSystem *MemFS) {
+ llvm::vfs::InMemoryFileSystem *MemFS) {
MemFS->addFileNoOwn(FileName, 0, Source);
return Sources.createFileID(Files.getFile(FileName), SourceLocation(),
SrcMgr::C_User);
@@ -133,8 +133,8 @@ static bool parseLineRange(StringRef Input, unsigned &FromLine,
static bool fillRanges(MemoryBuffer *Code,
std::vector<tooling::Range> &Ranges) {
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
@@ -301,8 +301,8 @@ static bool format(StringRef FileName) {
outputReplacementsXML(Replaces);
outs() << "</replacements>\n";
} else {
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
diff --git a/tools/clang-format/clang-format-diff.py b/tools/clang-format/clang-format-diff.py
index ffa30e70ddc3..d6d351041611 100755
--- a/tools/clang-format/clang-format-diff.py
+++ b/tools/clang-format/clang-format-diff.py
@@ -21,15 +21,19 @@ Example usage for git/svn users:
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
+from __future__ import absolute_import, division, print_function
import argparse
import difflib
import re
-import string
import subprocess
-import StringIO
import sys
+if sys.version_info.major >= 3:
+ from io import StringIO
+else:
+ from io import BytesIO as StringIO
+
def main():
parser = argparse.ArgumentParser(description=
@@ -84,14 +88,14 @@ def main():
line_count = int(match.group(3))
if line_count == 0:
continue
- end_line = start_line + line_count - 1;
+ end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).extend(
['-lines', str(start_line) + ':' + str(end_line)])
# Reformat files containing changes in place.
- for filename, lines in lines_by_file.iteritems():
+ for filename, lines in lines_by_file.items():
if args.i and args.verbose:
- print 'Formatting', filename
+ print('Formatting {}'.format(filename))
command = [args.binary, filename]
if args.i:
command.append('-i')
@@ -100,20 +104,23 @@ def main():
command.extend(lines)
if args.style:
command.extend(['-style', args.style])
- p = subprocess.Popen(command, stdout=subprocess.PIPE,
- stderr=None, stdin=subprocess.PIPE)
+ p = subprocess.Popen(command,
+ stdout=subprocess.PIPE,
+ stderr=None,
+ stdin=subprocess.PIPE,
+ universal_newlines=True)
stdout, stderr = p.communicate()
if p.returncode != 0:
- sys.exit(p.returncode);
+ sys.exit(p.returncode)
if not args.i:
with open(filename) as f:
code = f.readlines()
- formatted_code = StringIO.StringIO(stdout).readlines()
+ formatted_code = StringIO(stdout).readlines()
diff = difflib.unified_diff(code, formatted_code,
filename, filename,
'(before formatting)', '(after formatting)')
- diff_string = string.join(diff, '')
+ diff_string = ''.join(diff)
if len(diff_string) > 0:
sys.stdout.write(diff_string)
diff --git a/tools/clang-format/clang-format-sublime.py b/tools/clang-format/clang-format-sublime.py
index 16ff56e502c6..5ea9a27825cb 100644
--- a/tools/clang-format/clang-format-sublime.py
+++ b/tools/clang-format/clang-format-sublime.py
@@ -12,7 +12,7 @@
# It operates on the current, potentially unsaved buffer and does not create
# or save any files. To revert a formatting, just undo.
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import sublime
import sublime_plugin
import subprocess
diff --git a/tools/clang-format/clang-format.py b/tools/clang-format/clang-format.py
index 5fe592a9202b..fe068bd41c18 100644
--- a/tools/clang-format/clang-format.py
+++ b/tools/clang-format/clang-format.py
@@ -25,7 +25,7 @@
#
# It operates on the current, potentially unsaved buffer and does not create
# or save any files. To revert a formatting, just undo.
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import difflib
import json
diff --git a/tools/clang-format/git-clang-format b/tools/clang-format/git-clang-format
index 0b2103962a31..96e3b4e8a2c1 100755
--- a/tools/clang-format/git-clang-format
+++ b/tools/clang-format/git-clang-format
@@ -23,7 +23,7 @@ git clang-format -h
Requires Python 2.7 or Python 3
"""
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import argparse
import collections
import contextlib
diff --git a/tools/clang-fuzzer/Dockerfile b/tools/clang-fuzzer/Dockerfile
index 1946b8bf88da..9f6336c4798b 100644
--- a/tools/clang-fuzzer/Dockerfile
+++ b/tools/clang-fuzzer/Dockerfile
@@ -35,3 +35,7 @@ RUN mkdir build1 && cd build1 && cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../llv
RUN cd build1 && ninja clang-fuzzer
RUN cd build1 && ninja clang-proto-fuzzer
RUN cd build1 && ninja clang-proto-to-cxx
+RUN cd build1 && ninja clang-loop-proto-to-cxx
+RUN cd build1 && ninja clang-loop-proto-to-llvm
+RUN cd build1 && ninja clang-loop-proto-fuzzer
+RUN cd build1 && ninja clang-llvm-proto-fuzzer
diff --git a/tools/clang-fuzzer/README.txt b/tools/clang-fuzzer/README.txt
index 66a6a6332cd7..9c25afdb22ae 100644
--- a/tools/clang-fuzzer/README.txt
+++ b/tools/clang-fuzzer/README.txt
@@ -80,3 +80,37 @@ custom optimization level and target triple:
To translate a clang-proto-fuzzer corpus output to C++:
bin/clang-proto-to-cxx CORPUS_OUTPUT_FILE
+
+===================
+ llvm-proto-fuzzer
+===================
+Like, clang-proto-fuzzer, llvm-proto-fuzzer is also a protobuf-mutator based
+fuzzer. It receives as input a cxx_loop_proto which it then converts into a
+string of valid LLVM IR: a function with either a single loop or two nested
+loops. It then creates a new string of IR by running optimization passes over
+the original IR. Currently, it only runs a loop-vectorize pass but more passes
+can easily be added to the fuzzer. Once there are two versions of the input
+function (optimized and not), llvm-proto-fuzzer uses LLVM's JIT Engine to
+compile both functions. Lastly, it runs both functions on a suite of inputs and
+checks that both functions behave the same on all inputs. In this way,
+llvm-proto-fuzzer can find not only compiler crashes, but also miscompiles
+originating from LLVM's optimization passes.
+
+llvm-proto-fuzzer is built very similarly to clang-proto-fuzzer. You can run the
+fuzzer with the following command:
+ bin/clang-llvm-proto-fuzzer CORPUS_DIR
+
+To translate a cxx_loop_proto file into LLVM IR do:
+ bin/clang-loop-proto-to-llvm CORPUS_OUTPUT_FILE
+To translate a cxx_loop_proto file into C++ do:
+ bin/clang-loop-proto-to-cxx CORPUS_OUTPUT_FILE
+
+Note: To get a higher number of executions per second with llvm-proto-fuzzer it
+helps to build it without ASan instrumentation and with the -O2 flag. Because
+the fuzzer is not only compiling code, but also running it, as the inputs get
+large, the time necessary to fuzz one input can get very high.
+Example:
+ cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
+ -DCLANG_ENABLE_PROTO_FUZZER=ON -DLLVM_USE_SANITIZE_COVERAGE=YES \
+ -DCMAKE_CXX_FLAGS="-O2"
+ ninja clang-llvm-proto-fuzzer clang-loop-proto-to-llvm
diff --git a/tools/clang-fuzzer/cxx_loop_proto.proto b/tools/clang-fuzzer/cxx_loop_proto.proto
index f2b47ed43d89..760904b579a8 100644
--- a/tools/clang-fuzzer/cxx_loop_proto.proto
+++ b/tools/clang-fuzzer/cxx_loop_proto.proto
@@ -9,10 +9,11 @@
///
/// \file
/// This file describes a subset of C++ as a protobuf. It is used to
-/// more easily find interesting inputs for fuzzing Clang. This subset
-/// differs from the one defined in cxx_proto.proto by eliminating while
-/// loops and conditionals. The goal is that the C++ code generated will be
-/// more likely to stress the LLVM loop vectorizer.
+/// more easily find interesting inputs for fuzzing LLVM's vectorizer.
+/// This subset differs from the one defined in cxx_proto.proto by eliminating
+/// while loops and conditionals. The goal is that the C++ code generated will
+/// be more likely to stress the LLVM loop vectorizer. The code generated will
+/// contain either a single loop or two nested loops.
///
//===----------------------------------------------------------------------===//
@@ -74,7 +75,8 @@ message StatementSeq {
}
message LoopFunction {
- required StatementSeq statements = 1;
+ optional StatementSeq inner_statements = 1;
+ required StatementSeq outer_statements = 2;
}
package clang_fuzzer;
diff --git a/tools/clang-fuzzer/handle-cxx/CMakeLists.txt b/tools/clang-fuzzer/handle-cxx/CMakeLists.txt
index caf1dba7af67..6d62421d9a69 100644
--- a/tools/clang-fuzzer/handle-cxx/CMakeLists.txt
+++ b/tools/clang-fuzzer/handle-cxx/CMakeLists.txt
@@ -8,5 +8,6 @@ add_clang_library(clangHandleCXX
clangCodeGen
clangFrontend
clangLex
+ clangSerialization
clangTooling
)
diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
index ef544ae711ab..86df06ab8b4b 100644
--- a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
+++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include "handle_llvm.h"
+#include "input_arrays.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
@@ -48,6 +49,9 @@
using namespace llvm;
+// Define a type for the functions that are compiled and executed
+typedef void (*LLVMFunc)(int*, int*, int*, int);
+
// Helper function to parse command line args and find the optimization level
static void getOptLevel(const std::vector<const char *> &ExtraArgs,
CodeGenOpt::Level &OLvl) {
@@ -68,7 +72,7 @@ static void getOptLevel(const std::vector<const char *> &ExtraArgs,
}
}
-void ErrorAndExit(std::string message) {
+static void ErrorAndExit(std::string message) {
errs()<< "ERROR: " << message << "\n";
std::exit(1);
}
@@ -88,7 +92,7 @@ static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
}
// Mimics the opt tool to run an optimization pass over the provided IR
-std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) {
+static std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) {
// Create a module that will run the optimization passes
SMDiagnostic Err;
LLVMContext Context;
@@ -96,17 +100,29 @@ std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) {
if (!M || verifyModule(*M, &errs()))
ErrorAndExit("Could not parse IR");
+ Triple ModuleTriple(M->getTargetTriple());
+ const TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+ std::string E;
+ const Target *TheTarget = TargetRegistry::lookupTarget(MArch, ModuleTriple, E);
+ TargetMachine *Machine =
+ TheTarget->createTargetMachine(M->getTargetTriple(), getCPUStr(),
+ getFeaturesStr(), Options, getRelocModel(),
+ getCodeModel(), OLvl);
+ std::unique_ptr<TargetMachine> TM(Machine);
setFunctionAttributes(getCPUStr(), getFeaturesStr(), *M);
-
+
legacy::PassManager Passes;
- Triple ModuleTriple(M->getTargetTriple());
Passes.add(new TargetLibraryInfoWrapperPass(ModuleTriple));
- Passes.add(createTargetTransformInfoWrapperPass(TargetIRAnalysis()));
+ Passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
+
+ LLVMTargetMachine &LTM = static_cast<LLVMTargetMachine &>(*TM);
+ Passes.add(LTM.createPassConfig(Passes));
+
Passes.add(createVerifierPass());
AddOptimizationPasses(Passes, OLvl, 0);
-
+
// Add a pass that writes the optimized IR to an output stream
std::string outString;
raw_string_ostream OS(outString);
@@ -117,11 +133,19 @@ std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) {
return OS.str();
}
-void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) {
+// Takes a function and runs it on a set of inputs
+// First determines whether f is the optimized or unoptimized function
+static void RunFuncOnInputs(LLVMFunc f, int Arr[kNumArrays][kArraySize]) {
+ for (int i = 0; i < kNumArrays / 3; i++)
+ f(Arr[i], Arr[i + (kNumArrays / 3)], Arr[i + (2 * kNumArrays / 3)],
+ kArraySize);
+}
+
+// Takes a string of IR and compiles it using LLVM's JIT Engine
+static void CreateAndRunJITFunc(const std::string &IR, CodeGenOpt::Level OLvl) {
SMDiagnostic Err;
LLVMContext Context;
- std::unique_ptr<Module> M = parseIR(MemoryBufferRef(IR, "IR"), Err,
- Context);
+ std::unique_ptr<Module> M = parseIR(MemoryBufferRef(IR, "IR"), Err, Context);
if (!M)
ErrorAndExit("Could not parse IR");
@@ -148,14 +172,26 @@ void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) {
EE->finalizeObject();
EE->runStaticConstructorsDestructors(false);
- typedef void (*func)(int*, int*, int*, int);
- func f = reinterpret_cast<func>(EE->getPointerToFunction(EntryFunc));
-
- // Define some dummy arrays to use an input for now
- int a[] = {1};
- int b[] = {1};
- int c[] = {1};
- f(a, b, c, 1);
+#if defined(__GNUC__) && !defined(__clang) && \
+ ((__GNUC__ == 4) && (__GNUC_MINOR__ < 9))
+// Silence
+//
+// warning: ISO C++ forbids casting between pointer-to-function and
+// pointer-to-object [-Wpedantic]
+//
+// Since C++11 this casting is conditionally supported and GCC versions
+// starting from 4.9.0 don't warn about the cast.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+ LLVMFunc f = reinterpret_cast<LLVMFunc>(EE->getPointerToFunction(EntryFunc));
+#if defined(__GNUC__) && !defined(__clang) && \
+ ((__GNUC__ == 4) && (__GNUC_MINOR__ < 9))
+#pragma GCC diagnostic pop
+#endif
+
+ // Figure out if we are running the optimized func or the unoptimized func
+ RunFuncOnInputs(f, (OLvl == CodeGenOpt::None) ? UnoptArrays : OptArrays);
EE->runStaticConstructorsDestructors(true);
}
@@ -164,6 +200,10 @@ void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) {
// Mimics the lli tool to JIT the LLVM IR code and execute it
void clang_fuzzer::HandleLLVM(const std::string &IR,
const std::vector<const char *> &ExtraArgs) {
+ // Populate OptArrays and UnoptArrays with the arrays from InputArrays
+ memcpy(OptArrays, InputArrays, kTotalSize);
+ memcpy(UnoptArrays, InputArrays, kTotalSize);
+
// Parse ExtraArgs to set the optimization level
CodeGenOpt::Level OLvl;
getOptLevel(ExtraArgs, OLvl);
@@ -171,8 +211,11 @@ void clang_fuzzer::HandleLLVM(const std::string &IR,
// First we optimize the IR by running a loop vectorizer pass
std::string OptIR = OptLLVM(IR, OLvl);
- CreateAndRunJITFun(OptIR, OLvl);
- CreateAndRunJITFun(IR, CodeGenOpt::None);
-
+ CreateAndRunJITFunc(OptIR, OLvl);
+ CreateAndRunJITFunc(IR, CodeGenOpt::None);
+
+ if (memcmp(OptArrays, UnoptArrays, kTotalSize))
+ ErrorAndExit("!!!BUG!!!");
+
return;
}
diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.h b/tools/clang-fuzzer/handle-llvm/handle_llvm.h
index 38aec6799490..1149c29cef32 100644
--- a/tools/clang-fuzzer/handle-llvm/handle_llvm.h
+++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.h
@@ -19,7 +19,7 @@
namespace clang_fuzzer {
void HandleLLVM(const std::string &S,
- const std::vector<const char *> &ExtraArgs);
+ const std::vector<const char *> &ExtraArgs);
} // namespace clang_fuzzer
#endif
diff --git a/tools/clang-fuzzer/handle-llvm/input_arrays.h b/tools/clang-fuzzer/handle-llvm/input_arrays.h
new file mode 100644
index 000000000000..b60e3e1b2e7d
--- /dev/null
+++ b/tools/clang-fuzzer/handle-llvm/input_arrays.h
@@ -0,0 +1,118 @@
+//==-- input_arrays.h - Helper function for LLVM fuzzer inputs -------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Define a few static variables used by the LLVM Proto Fuzzer
+//
+//===----------------------------------------------------------------------===//
+
+#include <climits>
+
+static const int kArraySize = 64;
+static const int kNumArrays = 93;
+static const int kTotalSize = sizeof(int) * kArraySize * kNumArrays;
+
+// Define two arrays that will hold the input and output for the two functions
+static int OptArrays[kNumArrays][kArraySize];
+static int UnoptArrays[kNumArrays][kArraySize];
+
+// Define a corpus of possible inputs
+static int InputArrays[kNumArrays][kArraySize] =
+{ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX},
+ {INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024},
+ {65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535},
+ {-1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023},
+ {INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX},
+ {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, },
+ {1, 1, 0, 3, 2, 5, 6, 2, 6, 3, 0, 19, 18, 17, 16, 0, 13, 11, 9, 7, 5, 3, 1, -3000, -3000, -3000, -3000, -3000, -3000, -3000, 0, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000},
+ {1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824},
+ {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0},
+ {0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, },
+ {-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0},
+ {1, 1, 2, 1, 6, 9, 10, 7, 2, 10, 4, 11, 10, 11, 0, 19, 26, 18, 10, 2, 14, 7, 0, 39, 34, 29, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91},
+ {0, 0, 2, 0, 0, 1, 6, 9, 4, 12, 6, 13, 12, 0, 2, 21, 28, 20, 12, 4, 16, 9, 2, 41, 36, 31, 26, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93},
+ {1, 1, 0, 2, 2, 3, 8, 11, 6, 14, 8, 15, 14, 2, 4, 23, 30, 22, 14, 6, 18, 11, 4, 43, 38, 33, 28, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95},
+ {0, 0, 0, 4, 0, 0, 10, 13, 0, 16, 0, 17, 16, 4, 6, 25, 16, 24, 16, 8, 0, 13, 6, 45, 40, 35, 30, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97},
+ {1, 1, 2, 3, 2, 2, 0, 1, 2, 9, 2, 19, 18, 6, 8, 27, 18, 26, 18, 10, 2, 15, 8, 1, 42, 37, 32, 27, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 107, 106, 105, 104, 103, 102, 101, 100, 99},
+ {0, 0, 2, 5, 4, 4, 2, 3, 4, 11, 4, 21, 20, 8, 10, 29, 20, 28, 20, 12, 4, 17, 10, 3, 44, 39, 34, 29, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 109, 108, 107, 106, 105, 104, 103, 102, 101},
+ {1, 1, 0, 1, 6, 6, 4, 5, 6, 13, 6, 1, 22, 10, 12, 1, 22, 30, 22, 14, 6, 19, 12, 5, 46, 41, 36, 31, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 110, 109, 108, 107, 106, 105, 104, 103},
+ {0, 0, 0, 0, 4, 8, 0, 0, 8, 15, 8, 3, 12, 12, 0, 3, 24, 32, 24, 16, 8, 0, 14, 7, 0, 43, 38, 33, 28, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 111, 110, 109, 108, 107, 106, 105},
+ {1, 1, 2, 2, 6, 5, 2, 2, 10, 17, 10, 5, 14, 14, 2, 5, 26, 17, 26, 18, 10, 2, 16, 9, 2, 45, 40, 35, 30, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 41, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 113, 112, 111, 110, 109, 108, 107},
+ {0, 0, 2, 4, 0, 7, 4, 4, 12, 1, 12, 7, 16, 16, 4, 7, 28, 19, 28, 20, 12, 4, 18, 11, 4, 47, 42, 37, 32, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 114, 113, 112, 111, 110, 109},
+ {1, 1, 0, 3, 2, 9, 6, 6, 14, 3, 14, 9, 18, 18, 6, 9, 30, 21, 30, 22, 14, 6, 20, 13, 6, 49, 44, 39, 34, 29, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 115, 114, 113, 112, 111},
+ {1, 1, 0, 3, 2, 5, 6, 2, 6, 3, 0, 19, 18, 17, 16, 0, 13, 11, 9, 7, 5, 3, 1, -3000, -3000, -3000, -3000, -3000, -3000, -3000, 0, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000},
+ {1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824},
+ {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0},
+ {0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, },
+ {-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0},
+ {1, 1, 2, 1, 6, 9, 10, 7, 2, 10, 4, 11, 10, 11, 0, 19, 26, 18, 10, 2, 14, 7, 0, 39, 34, 29, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91},
+ {0, 0, 2, 0, 0, 1, 6, 9, 4, 12, 6, 13, 12, 0, 2, 21, 28, 20, 12, 4, 16, 9, 2, 41, 36, 31, 26, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93},
+ {1, 1, 0, 2, 2, 3, 8, 11, 6, 14, 8, 15, 14, 2, 4, 23, 30, 22, 14, 6, 18, 11, 4, 43, 38, 33, 28, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95},
+ {0, 0, 0, 4, 0, 0, 10, 13, 0, 16, 0, 17, 16, 4, 6, 25, 16, 24, 16, 8, 0, 13, 6, 45, 40, 35, 30, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97},
+ {1, 1, 2, 3, 2, 2, 0, 1, 2, 9, 2, 19, 18, 6, 8, 27, 18, 26, 18, 10, 2, 15, 8, 1, 42, 37, 32, 27, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 107, 106, 105, 104, 103, 102, 101, 100, 99},
+ {0, 0, 2, 5, 4, 4, 2, 3, 4, 11, 4, 21, 20, 8, 10, 29, 20, 28, 20, 12, 4, 17, 10, 3, 44, 39, 34, 29, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 109, 108, 107, 106, 105, 104, 103, 102, 101},
+ {1, 1, 0, 1, 6, 6, 4, 5, 6, 13, 6, 1, 22, 10, 12, 1, 22, 30, 22, 14, 6, 19, 12, 5, 46, 41, 36, 31, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 110, 109, 108, 107, 106, 105, 104, 103},
+ {0, 0, 0, 0, 4, 8, 0, 0, 8, 15, 8, 3, 12, 12, 0, 3, 24, 32, 24, 16, 8, 0, 14, 7, 0, 43, 38, 33, 28, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 111, 110, 109, 108, 107, 106, 105},
+ {1, 1, 2, 2, 6, 5, 2, 2, 10, 17, 10, 5, 14, 14, 2, 5, 26, 17, 26, 18, 10, 2, 16, 9, 2, 45, 40, 35, 30, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 41, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 113, 112, 111, 110, 109, 108, 107},
+ {0, 0, 2, 4, 0, 7, 4, 4, 12, 1, 12, 7, 16, 16, 4, 7, 28, 19, 28, 20, 12, 4, 18, 11, 4, 47, 42, 37, 32, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 114, 113, 112, 111, 110, 109},
+ {1, 1, 0, 3, 2, 9, 6, 6, 14, 3, 14, 9, 18, 18, 6, 9, 30, 21, 30, 22, 14, 6, 20, 13, 6, 49, 44, 39, 34, 29, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 115, 114, 113, 112, 111},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX},
+ {INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024},
+ {65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535},
+ {-1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023},
+ {INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX},
+ {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, },
+ {0, 0, 2, 0, 0, 1, 6, 9, 4, 12, 6, 13, 12, 0, 2, 21, 28, 20, 12, 4, 16, 9, 2, 41, 36, 31, 26, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535},
+ {INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX},
+ {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, 0, -1, -2, -4, -8, -16, -32, -64, -128, -256, -512, -1024, -2048, -4096, -8192, -16384, },
+ {1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, },
+ {1, 1, 0, 3, 2, 5, 6, 2, 6, 3, 0, 19, 18, 17, 16, 0, 13, 11, 9, 7, 5, 3, 1, -3000, -3000, -3000, -3000, -3000, -3000, -3000, 0, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000},
+ {0, 0, 2, 5, 4, 4, 2, 3, 4, 11, 4, 21, 20, 8, 10, 29, 20, 28, 20, 12, 4, 17, 10, 3, 44, 39, 34, 29, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 109, 108, 107, 106, 105, 104, 103, 102, 101},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0},
+ {-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0},
+ {1, 1, 2, 1, 6, 9, 10, 7, 2, 10, 4, 11, 10, 11, 0, 19, 26, 18, 10, 2, 14, 7, 0, 39, 34, 29, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91},
+ {0, 0, 2, 4, 0, 7, 4, 4, 12, 1, 12, 7, 16, 16, 4, 7, 28, 19, 28, 20, 12, 4, 18, 11, 4, 47, 42, 37, 32, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 114, 113, 112, 111, 110, 109},
+ {1, 1, 0, 2, 2, 3, 8, 11, 6, 14, 8, 15, 14, 2, 4, 23, 30, 22, 14, 6, 18, 11, 4, 43, 38, 33, 28, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN},
+ {0, 0, 0, 4, 0, 0, 10, 13, 0, 16, 0, 17, 16, 4, 6, 25, 16, 24, 16, 8, 0, 13, 6, 45, 40, 35, 30, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97},
+ {1, 1, 2, 3, 2, 2, 0, 1, 2, 9, 2, 19, 18, 6, 8, 27, 18, 26, 18, 10, 2, 15, 8, 1, 42, 37, 32, 27, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 107, 106, 105, 104, 103, 102, 101, 100, 99},
+ {1, 1, 0, 1, 6, 6, 4, 5, 6, 13, 6, 1, 22, 10, 12, 1, 22, 30, 22, 14, 6, 19, 12, 5, 46, 41, 36, 31, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 40, 37, 34, 31, 28, 25, 22, 19, 16, 13, 10, 7, 4, 1, 110, 109, 108, 107, 106, 105, 104, 103},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {-1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023, -1023},
+ {0, 0, 0, 0, 4, 8, 0, 0, 8, 15, 8, 3, 12, 12, 0, 3, 24, 32, 24, 16, 8, 0, 14, 7, 0, 43, 38, 33, 28, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 111, 110, 109, 108, 107, 106, 105},
+ {1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824, 1073741824},
+ {1, 1, 2, 2, 6, 5, 2, 2, 10, 17, 10, 5, 14, 14, 2, 5, 26, 17, 26, 18, 10, 2, 16, 9, 2, 45, 40, 35, 30, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 41, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 113, 112, 111, 110, 109, 108, 107},
+ {1, 1, 0, 3, 2, 9, 6, 6, 14, 3, 14, 9, 18, 18, 6, 9, 30, 21, 30, 22, 14, 6, 20, 13, 6, 49, 44, 39, 34, 29, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 115, 114, 113, 112, 111},
+ {INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MAX, INT_MAX, INT_MAX} };
diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp
index 7d8f6650aadb..698e0fed8ba1 100644
--- a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp
+++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp
@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
//
// Implements functions for converting between protobufs and C++. Differs from
-// proto_to_cxx.cpp by wrapping all the generated C++ code in a single for
-// loop. Also coutputs a different function signature that includes a
-// size_t parameter for the loop to use. The C++ code generated is meant to
-// stress the LLVM loop vectorizer.
+// proto_to_cxx.cpp by wrapping all the generated C++ code in either a single
+// for loop or two nested loops. Also outputs a different function signature
+// that includes a size_t parameter for the loop to use. The C++ code generated
+// is meant to stress the LLVM loop vectorizer.
//
// Still a work in progress.
//
@@ -28,6 +28,17 @@
namespace clang_fuzzer {
+static bool inner_loop = false;
+class InnerLoop {
+ public:
+ InnerLoop() {
+ inner_loop = true;
+ }
+ ~InnerLoop() {
+ inner_loop = false;
+ }
+};
+
// Forward decls.
std::ostream &operator<<(std::ostream &os, const BinaryOp &x);
std::ostream &operator<<(std::ostream &os, const StatementSeq &x);
@@ -37,13 +48,14 @@ std::ostream &operator<<(std::ostream &os, const Const &x) {
return os << "(" << x.val() << ")";
}
std::ostream &operator<<(std::ostream &os, const VarRef &x) {
+ std::string which_loop = inner_loop ? "j" : "i";
switch (x.arr()) {
case VarRef::ARR_A:
- return os << "a[i]";
+ return os << "a[" << which_loop << "]";
case VarRef::ARR_B:
- return os << "b[i]";
+ return os << "b[" << which_loop << "]";
case VarRef::ARR_C:
- return os << "c[i]";
+ return os << "c[" << which_loop << "]";
}
}
std::ostream &operator<<(std::ostream &os, const Rvalue &x) {
@@ -108,10 +120,27 @@ std::ostream &operator<<(std::ostream &os, const StatementSeq &x) {
os << st;
return os;
}
+void NestedLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
+ << "for (int i=0; i<s; i++){\n"
+ << "for (int j=0; j<s; j++){\n";
+ {
+ InnerLoop IL;
+ os << x.inner_statements() << "}\n";
+ }
+ os << x.outer_statements() << "}\n}\n";
+}
+void SingleLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
+ << "for (int i=0; i<s; i++){\n"
+ << x.outer_statements() << "}\n}\n";
+}
std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
- return os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
- << "for (int i=0; i<s; i++){\n"
- << x.statements() << "}\n}\n";
+ if (x.has_inner_statements())
+ NestedLoopToString(os, x);
+ else
+ SingleLoopToString(os, x);
+ return os;
}
// ---------------------------------
diff --git a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp
index 16dbcb7b49b2..ffbb1c9f0d1f 100644
--- a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp
+++ b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp
@@ -15,6 +15,7 @@
#include "loop_proto_to_llvm.h"
#include "cxx_loop_proto.pb.h"
+#include "../handle-llvm/input_arrays.h"
// The following is needed to convert protos in human-readable form
#include <google/protobuf/text_format.h>
@@ -29,17 +30,30 @@ std::string BinopToString(std::ostream &os, const BinaryOp &x);
std::string StateSeqToString(std::ostream &os, const StatementSeq &x);
// Counter variable to generate new LLVM IR variable names and wrapper function
-std::string get_var() {
+static std::string get_var() {
static int ctr = 0;
return "%var" + std::to_string(ctr++);
}
+static bool inner_loop = false;
+class InnerLoop {
+ public:
+ InnerLoop() {
+ inner_loop = true;
+ }
+ ~InnerLoop() {
+ inner_loop = false;
+ }
+};
+
+
// Proto to LLVM.
std::string ConstToString(const Const &x) {
return std::to_string(x.val());
}
std::string VarRefToString(std::ostream &os, const VarRef &x) {
+ std::string which_loop = inner_loop ? "inner" : "outer";
std::string arr;
switch(x.arr()) {
case VarRef::ARR_A:
@@ -53,7 +67,8 @@ std::string VarRefToString(std::ostream &os, const VarRef &x) {
break;
}
std::string ptr_var = get_var();
- os << ptr_var << " = getelementptr i32, i32* " << arr << ", i64 %ct\n";
+ os << ptr_var << " = getelementptr inbounds i32, i32* " << arr
+ << ", i64 %" << which_loop << "_ct\n";
return ptr_var;
}
std::string RvalueToString(std::ostream &os, const Rvalue &x) {
@@ -121,22 +136,61 @@ std::ostream &operator<<(std::ostream &os, const StatementSeq &x) {
}
return os;
}
+void NestedLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "target triple = \"x86_64-unknown-linux-gnu\"\n"
+ << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
+ << "outer_loop_start:\n"
+ << "%cmp = icmp sgt i64 %s, 0\n"
+ << "br i1 %cmp, label %inner_loop_start, label %end\n"
+ << "outer_loop:\n"
+ << x.outer_statements()
+ << "%o_ct_new = add i64 %outer_ct, 1\n"
+ << "%jmp_outer = icmp eq i64 %o_ct_new, %s\n"
+ << "br i1 %jmp_outer, label %end, label %inner_loop_start\n"
+ << "inner_loop_start:\n"
+ << "%outer_ct = phi i64 [%o_ct_new, %outer_loop], [0, %outer_loop_start]\n"
+ << "br label %inner_loop\n"
+ << "inner_loop:\n"
+ << "%inner_ct = phi i64 [0, %inner_loop_start], [%i_ct_new, %inner_loop]\n";
+ {
+ InnerLoop IL;
+ os << x.inner_statements();
+ }
+ os << "%i_ct_new = add i64 %inner_ct, 1\n"
+ << "%jmp_inner = icmp eq i64 %i_ct_new, %s\n"
+ << "br i1 %jmp_inner, label %outer_loop, label %inner_loop, !llvm.loop !0\n"
+ << "end:\n"
+ << "ret void\n"
+ << "}\n"
+ << "!0 = distinct !{!0, !1, !2}\n"
+ << "!1 = !{!\"llvm.loop.vectorize.enable\", i1 true}\n"
+ << "!2 = !{!\"llvm.loop.vectorize.width\", i32 " << kArraySize << "}\n";
+}
+void SingleLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "target triple = \"x86_64-unknown-linux-gnu\"\n"
+ << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
+ << "%cmp = icmp sgt i64 %s, 0\n"
+ << "br i1 %cmp, label %start, label %end\n"
+ << "start:\n"
+ << "br label %loop\n"
+ << "end:\n"
+ << "ret void\n"
+ << "loop:\n"
+ << "%outer_ct = phi i64 [ %ctnew, %loop ], [ 0, %start ]\n"
+ << x.outer_statements()
+ << "%ctnew = add i64 %outer_ct, 1\n"
+ << "%j = icmp eq i64 %ctnew, %s\n"
+ << "br i1 %j, label %end, label %loop, !llvm.loop !0\n}\n"
+ << "!0 = distinct !{!0, !1, !2}\n"
+ << "!1 = !{!\"llvm.loop.vectorize.enable\", i1 true}\n"
+ << "!2 = !{!\"llvm.loop.vectorize.width\", i32 " << kArraySize << "}\n";
+}
std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
- return os << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
- << "%i = alloca i64\n"
- << "store i64 0, i64* %i\n"
- << "br label %loop\n\n"
- << "loop:\n"
- << "%ct = load i64, i64* %i\n"
- << "%comp = icmp eq i64 %ct, %s\n"
- << "br i1 %comp, label %endloop, label %body\n\n"
- << "body:\n"
- << x.statements()
- << "%z = add i64 1, %ct\n"
- << "store i64 %z, i64* %i\n"
- << "br label %loop\n\n"
- << "endloop:\n"
- << "ret void\n}\n";
+ if (x.has_inner_statements())
+ NestedLoopToString(os, x);
+ else
+ SingleLoopToString(os, x);
+ return os;
}
// ---------------------------------
diff --git a/tools/clang-import-test/CMakeLists.txt b/tools/clang-import-test/CMakeLists.txt
index dfccfe2304bd..ee1bdab64a5d 100644
--- a/tools/clang-import-test/CMakeLists.txt
+++ b/tools/clang-import-test/CMakeLists.txt
@@ -21,6 +21,7 @@ set(CLANG_IMPORT_TEST_LIB_DEPS
clangFrontend
clangLex
clangParse
+ clangSerialization
)
target_link_libraries(clang-import-test
diff --git a/tools/clang-import-test/clang-import-test.cpp b/tools/clang-import-test/clang-import-test.cpp
index 106f3d1d150d..a7e749c6468a 100644
--- a/tools/clang-import-test/clang-import-test.cpp
+++ b/tools/clang-import-test/clang-import-test.cpp
@@ -182,8 +182,7 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
Inv->getHeaderSearchOpts().UseLibcxx = true;
}
if (isObjC(Id)) {
- Inv->getLangOpts()->ObjC1 = 1;
- Inv->getLangOpts()->ObjC2 = 1;
+ Inv->getLangOpts()->ObjC = 1;
}
}
Inv->getLangOpts()->Bool = true;
@@ -194,6 +193,10 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
Inv->getLangOpts()->ThreadsafeStatics = false;
Inv->getLangOpts()->AccessControl = false;
Inv->getLangOpts()->DollarIdents = true;
+ Inv->getLangOpts()->Exceptions = true;
+ Inv->getLangOpts()->CXXExceptions = true;
+ // Needed for testing dynamic_cast.
+ Inv->getLangOpts()->RTTI = true;
Inv->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
Inv->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
diff --git a/tools/clang-refactor/CMakeLists.txt b/tools/clang-refactor/CMakeLists.txt
index b435744ca4bd..48206e730658 100644
--- a/tools/clang-refactor/CMakeLists.txt
+++ b/tools/clang-refactor/CMakeLists.txt
@@ -16,6 +16,7 @@ target_link_libraries(clang-refactor
clangFrontend
clangLex
clangRewrite
+ clangSerialization
clangTooling
clangToolingCore
clangToolingRefactor
diff --git a/tools/clang-refactor/TestSupport.h b/tools/clang-refactor/TestSupport.h
index 61aa660733fb..779006b0c502 100644
--- a/tools/clang-refactor/TestSupport.h
+++ b/tools/clang-refactor/TestSupport.h
@@ -59,9 +59,6 @@ struct TestSelectionRangesInFile {
};
std::vector<RangeGroup> GroupedRanges;
- TestSelectionRangesInFile(TestSelectionRangesInFile &&) = default;
- TestSelectionRangesInFile &operator=(TestSelectionRangesInFile &&) = default;
-
bool foreachRange(const SourceManager &SM,
llvm::function_ref<void(SourceRange)> Callback) const;
diff --git a/tools/clang-rename/CMakeLists.txt b/tools/clang-rename/CMakeLists.txt
index 3b3ab1540a80..45cbd763425c 100644
--- a/tools/clang-rename/CMakeLists.txt
+++ b/tools/clang-rename/CMakeLists.txt
@@ -12,6 +12,7 @@ target_link_libraries(clang-rename
clangBasic
clangFrontend
clangRewrite
+ clangSerialization
clangTooling
clangToolingCore
clangToolingRefactor
diff --git a/tools/clang-rename/clang-rename.py b/tools/clang-rename/clang-rename.py
index 3cc6644ff8f0..3381c5267f1c 100644
--- a/tools/clang-rename/clang-rename.py
+++ b/tools/clang-rename/clang-rename.py
@@ -7,10 +7,14 @@ Before installing make sure one of the following is satisfied:
* `g:clang_rename_path` in ~/.vimrc points to valid clang-rename executable
* `binary` in clang-rename.py points to valid to clang-rename executable
-To install, simply put this into your ~/.vimrc
+To install, simply put this into your ~/.vimrc for python2 support
noremap <leader>cr :pyf <path-to>/clang-rename.py<cr>
+For python3 use the following command (note the change from :pyf to :py3f)
+
+ noremap <leader>cr :py3f <path-to>/clang-rename.py<cr>
+
IMPORTANT NOTE: Before running the tool, make sure you saved the file.
All you have to do now is to place a cursor on a variable/function/class which
@@ -18,6 +22,7 @@ you would like to rename and press '<leader>cr'. You will be prompted for a new
name if the cursor points to a valid symbol.
'''
+from __future__ import absolute_import, division, print_function
import vim
import subprocess
import sys
@@ -30,8 +35,8 @@ def main():
# Get arguments for clang-rename binary.
offset = int(vim.eval('line2byte(line("."))+col(".")')) - 2
if offset < 0:
- print >> sys.stderr, '''Couldn\'t determine cursor position.
- Is your file empty?'''
+ print('Couldn\'t determine cursor position. Is your file empty?',
+ file=sys.stderr)
return
filename = vim.current.buffer.name
@@ -51,7 +56,7 @@ def main():
stdout, stderr = p.communicate()
if stderr:
- print stderr
+ print(stderr)
# Reload all buffers in Vim.
vim.command("checktime")
diff --git a/tools/diagtool/DiagTool.cpp b/tools/diagtool/DiagTool.cpp
index d9086af8e989..1690a4456cc1 100644
--- a/tools/diagtool/DiagTool.cpp
+++ b/tools/diagtool/DiagTool.cpp
@@ -48,7 +48,7 @@ void DiagTools::printCommands(llvm::raw_ostream &out) {
if (len > maxName)
maxName = len;
}
- llvm::sort(toolNames.begin(), toolNames.end());
+ llvm::sort(toolNames);
for (std::vector<llvm::StringRef>::iterator it = toolNames.begin(),
ei = toolNames.end(); it != ei; ++it) {
diff --git a/tools/diagtool/ListWarnings.cpp b/tools/diagtool/ListWarnings.cpp
index 8bf9df94011c..eae630125084 100644
--- a/tools/diagtool/ListWarnings.cpp
+++ b/tools/diagtool/ListWarnings.cpp
@@ -14,7 +14,6 @@
#include "DiagTool.h"
#include "DiagnosticNames.h"
-#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/StringMap.h"
diff --git a/tools/diagtool/TreeView.cpp b/tools/diagtool/TreeView.cpp
index b4846b557444..4919c1728236 100644
--- a/tools/diagtool/TreeView.cpp
+++ b/tools/diagtool/TreeView.cpp
@@ -9,7 +9,6 @@
#include "DiagTool.h"
#include "DiagnosticNames.h"
-#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 15b0519e4111..89a3aa3ced85 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -46,6 +46,7 @@ target_link_libraries(clang
clangDriver
clangFrontend
clangFrontendTool
+ clangSerialization
)
if(WIN32 AND NOT CYGWIN)
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index ef5a191bda0a..7d21c6a671d2 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -13,10 +13,9 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Option/Arg.h"
+#include "clang/Basic/Stack.h"
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Config/config.h"
-#include "clang/Basic/Stack.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -29,8 +28,10 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/LinkAllPasses.h"
+#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
+#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
@@ -228,7 +229,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
// When running with -disable-free, don't do any destruction or shutdown.
if (Clang->getFrontendOpts().DisableFree) {
- BuryPointer(std::move(Clang));
+ llvm::BuryPointer(std::move(Clang));
return !Success;
}
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 09db014019bf..be4f174ed412 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -33,6 +33,7 @@
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
@@ -132,6 +133,7 @@ struct AssemblerInvocation {
unsigned NoExecStack : 1;
unsigned FatalWarnings : 1;
unsigned IncrementalLinkerCompatible : 1;
+ unsigned EmbedBitcode : 1;
/// The name of the relocation model to use.
std::string RelocationModel;
@@ -153,6 +155,7 @@ public:
FatalWarnings = 0;
IncrementalLinkerCompatible = 0;
DwarfVersion = 0;
+ EmbedBitcode = 0;
}
static bool CreateFromArgs(AssemblerInvocation &Res,
@@ -284,6 +287,16 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Args.hasArg(OPT_mincremental_linker_compatible);
Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
+ // EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.
+ // EmbedBitcode behaves the same for all embed options for assembly files.
+ if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
+ Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue())
+ .Case("all", 1)
+ .Case("bitcode", 1)
+ .Case("marker", 1)
+ .Default(0);
+ }
+
return Success;
}
@@ -449,6 +462,16 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
Str.get()->InitSections(Opts.NoExecStack);
}
+ // When -fembed-bitcode is passed to clang_as, a 1-byte marker
+ // is emitted in __LLVM,__asm section if the object file is MachO format.
+ if (Opts.EmbedBitcode && Ctx.getObjectFileInfo()->getObjectFileType() ==
+ MCObjectFileInfo::IsMachO) {
+ MCSection *AsmLabel = Ctx.getMachOSection(
+ "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
+ Str.get()->SwitchSection(AsmLabel);
+ Str.get()->EmitZeros(1);
+ }
+
// Assembly to object compilation should leverage assembly info.
Str->setUseAssemblerInfoForParsing(true);
@@ -534,7 +557,8 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
if (Asm.ShowHelp) {
std::unique_ptr<OptTable> Opts(driver::createDriverOptTable());
- Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler",
+ Opts->PrintHelp(llvm::outs(), "clang -cc1as [options] file...",
+ "Clang Integrated Assembler",
/*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
/*ShowAllAliases=*/false);
return 0;
diff --git a/tools/driver/cc1gen_reproducer_main.cpp b/tools/driver/cc1gen_reproducer_main.cpp
index a4c034d8d357..2d7ea86f7486 100644
--- a/tools/driver/cc1gen_reproducer_main.cpp
+++ b/tools/driver/cc1gen_reproducer_main.cpp
@@ -14,13 +14,13 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 0455ba029c65..51143e3d8cb7 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -260,9 +260,9 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
const std::string &Path) {
// If the clang binary happens to be named cl.exe for compatibility reasons,
// use clang-cl.exe as the prefix to avoid confusion between clang and MSVC.
- StringRef ExeBasename(llvm::sys::path::filename(Path));
- if (ExeBasename.equals_lower("cl.exe"))
- ExeBasename = "clang-cl.exe";
+ StringRef ExeBasename(llvm::sys::path::stem(Path));
+ if (ExeBasename.equals_lower("cl"))
+ ExeBasename = "clang-cl";
DiagClient->setPrefix(ExeBasename);
}
diff --git a/tools/libclang/BuildSystem.cpp b/tools/libclang/BuildSystem.cpp
index 79fa69c40bae..6c1f2c145b0a 100644
--- a/tools/libclang/BuildSystem.cpp
+++ b/tools/libclang/BuildSystem.cpp
@@ -13,12 +13,12 @@
#include "clang-c/BuildSystem.h"
#include "CXString.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -28,11 +28,11 @@ unsigned long long clang_getBuildSessionTimestamp(void) {
return llvm::sys::toTimeT(std::chrono::system_clock::now());
}
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(clang::vfs::YAMLVFSWriter,
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::vfs::YAMLVFSWriter,
CXVirtualFileOverlay)
CXVirtualFileOverlay clang_VirtualFileOverlay_create(unsigned) {
- return wrap(new clang::vfs::YAMLVFSWriter());
+ return wrap(new llvm::vfs::YAMLVFSWriter());
}
enum CXErrorCode
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 499d9abf9a8e..a9c3077e5fa2 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -31,14 +31,12 @@
#include "clang/Basic/Version.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Index/CodegenNameGenerator.h"
#include "clang/Index/CommentToXML.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -565,7 +563,7 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
if (const ObjCObjectType *ObjT = A->getInterface()->getAs<ObjCObjectType>())
return Visit(cxcursor::MakeCursorObjCClassRef(
ObjT->getInterface(),
- A->getInterfaceLoc()->getTypeLoc().getLocStart(), TU));
+ A->getInterfaceLoc()->getTypeLoc().getBeginLoc(), TU));
}
// If pointing inside a macro definition, check if the token is an identifier
@@ -993,7 +991,7 @@ static void addRangedDeclsInContainer(DeclIt *DI_current, DeclIt DE_current,
Decl *D_next = *next;
if (!D_next)
break;
- SourceLocation L = D_next->getLocStart();
+ SourceLocation L = D_next->getBeginLoc();
if (!L.isValid())
break;
if (SM.isBeforeInTranslationUnit(L, EndLoc)) {
@@ -1038,20 +1036,20 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
// additional ones we've collected. Then visit them.
for (auto *SubDecl : D->decls()) {
if (!SubDecl || SubDecl->getLexicalDeclContext() != D ||
- SubDecl->getLocStart().isInvalid())
+ SubDecl->getBeginLoc().isInvalid())
continue;
DeclsInContainer.push_back(SubDecl);
}
// Now sort the Decls so that they appear in lexical order.
- llvm::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
+ llvm::sort(DeclsInContainer,
[&SM](Decl *A, Decl *B) {
- SourceLocation L_A = A->getLocStart();
- SourceLocation L_B = B->getLocStart();
- return L_A != L_B ?
- SM.isBeforeInTranslationUnit(L_A, L_B) :
- SM.isBeforeInTranslationUnit(A->getLocEnd(), B->getLocEnd());
- });
+ SourceLocation L_A = A->getBeginLoc();
+ SourceLocation L_B = B->getBeginLoc();
+ return L_A != L_B ? SM.isBeforeInTranslationUnit(L_A, L_B)
+ : SM.isBeforeInTranslationUnit(A->getEndLoc(),
+ B->getEndLoc());
+ });
// Now visit the decls.
for (SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(),
@@ -1519,6 +1517,9 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtTYpe, Id, Ext) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
@@ -1578,7 +1579,7 @@ bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
}
bool CursorVisitor::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
- if (Visit(MakeCursorTypeRef(TL.getDecl(), TL.getLocStart(), TU)))
+ if (Visit(MakeCursorTypeRef(TL.getDecl(), TL.getBeginLoc(), TU)))
return true;
for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
@@ -1802,7 +1803,9 @@ bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
bool CursorVisitor::VisitAttributes(Decl *D) {
for (const auto *I : D->attrs())
- if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
+ if ((TU->ParsingOptions & CXTranslationUnit_VisitImplicitAttributes ||
+ !I->isImplicit()) &&
+ Visit(MakeCXCursor(I, D, TU)))
return true;
return false;
@@ -2205,6 +2208,21 @@ void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}
void OMPClauseEnqueue::VisitOMPNogroupClause(const OMPNogroupClause *) {}
+void OMPClauseEnqueue::VisitOMPUnifiedAddressClause(
+ const OMPUnifiedAddressClause *) {}
+
+void OMPClauseEnqueue::VisitOMPUnifiedSharedMemoryClause(
+ const OMPUnifiedSharedMemoryClause *) {}
+
+void OMPClauseEnqueue::VisitOMPReverseOffloadClause(
+ const OMPReverseOffloadClause *) {}
+
+void OMPClauseEnqueue::VisitOMPDynamicAllocatorsClause(
+ const OMPDynamicAllocatorsClause *) {}
+
+void OMPClauseEnqueue::VisitOMPAtomicDefaultMemOrderClause(
+ const OMPAtomicDefaultMemOrderClause *) {}
+
void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) {
Visitor->AddStmt(C->getDevice());
}
@@ -3117,25 +3135,19 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
return true;
}
+ TypeLoc TL = E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
// Visit parameters and return type, if present.
- if (E->hasExplicitParameters() || E->hasExplicitResultType()) {
- TypeLoc TL = E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
- if (E->hasExplicitParameters() && E->hasExplicitResultType()) {
- // Visit the whole type.
- if (Visit(TL))
- return true;
- } else if (FunctionProtoTypeLoc Proto =
- TL.getAs<FunctionProtoTypeLoc>()) {
- if (E->hasExplicitParameters()) {
- // Visit parameters.
- for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I)
- if (Visit(MakeCXCursor(Proto.getParam(I), TU)))
- return true;
- } else {
- // Visit result type.
- if (Visit(Proto.getReturnLoc()))
+ if (FunctionTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
+ if (E->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I)
+ if (Visit(MakeCXCursor(Proto.getParam(I), TU)))
return true;
- }
+ }
+ if (E->hasExplicitResultType()) {
+ // Visit result type.
+ if (Visit(Proto.getReturnLoc()))
+ return true;
}
}
break;
@@ -3682,7 +3694,7 @@ struct ExprEvalResult {
~ExprEvalResult() {
if (EvalType != CXEval_UnExposed && EvalType != CXEval_Float &&
EvalType != CXEval_Int) {
- delete EvalData.stringVal;
+ delete[] EvalData.stringVal;
}
}
};
@@ -3890,36 +3902,35 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) {
return nullptr;
}
-CXEvalResult clang_Cursor_Evaluate(CXCursor C) {
- const Decl *D = getCursorDecl(C);
- if (D) {
- const Expr *expr = nullptr;
- if (auto *Var = dyn_cast<VarDecl>(D)) {
- expr = Var->getInit();
- } else if (auto *Field = dyn_cast<FieldDecl>(D)) {
- expr = Field->getInClassInitializer();
- }
- if (expr)
- return const_cast<CXEvalResult>(reinterpret_cast<const void *>(
- evaluateExpr(const_cast<Expr *>(expr), C)));
+static const Expr *evaluateDeclExpr(const Decl *D) {
+ if (!D)
return nullptr;
- }
+ if (auto *Var = dyn_cast<VarDecl>(D))
+ return Var->getInit();
+ else if (auto *Field = dyn_cast<FieldDecl>(D))
+ return Field->getInClassInitializer();
+ return nullptr;
+}
- const CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(getCursorStmt(C));
- if (compoundStmt) {
- Expr *expr = nullptr;
- for (auto *bodyIterator : compoundStmt->body()) {
- if ((expr = dyn_cast<Expr>(bodyIterator))) {
- break;
- }
- }
- if (expr)
- return const_cast<CXEvalResult>(
- reinterpret_cast<const void *>(evaluateExpr(expr, C)));
+static const Expr *evaluateCompoundStmtExpr(const CompoundStmt *CS) {
+ assert(CS && "invalid compound statement");
+ for (auto *bodyIterator : CS->body()) {
+ if (const auto *E = dyn_cast<Expr>(bodyIterator))
+ return E;
}
return nullptr;
}
+CXEvalResult clang_Cursor_Evaluate(CXCursor C) {
+ if (const Expr *E =
+ clang_getCursorKind(C) == CXCursor_CompoundStmt
+ ? evaluateCompoundStmtExpr(cast<CompoundStmt>(getCursorStmt(C)))
+ : evaluateDeclExpr(getCursorDecl(C)))
+ return const_cast<CXEvalResult>(
+ reinterpret_cast<const void *>(evaluateExpr(const_cast<Expr *>(E), C)));
+ return nullptr;
+}
+
unsigned clang_Cursor_hasAttrs(CXCursor C) {
const Decl *D = getCursorDecl(C);
if (!D) {
@@ -4340,8 +4351,8 @@ static SourceLocation getLocationFromExpr(const Expr *E) {
return SizeOfPack->getPackLoc();
if (const ObjCPropertyRefExpr *PropRef = dyn_cast<ObjCPropertyRefExpr>(E))
return PropRef->getLocation();
-
- return E->getLocStart();
+
+ return E->getBeginLoc();
}
extern "C" {
@@ -5277,6 +5288,42 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("attribute(dllexport)");
case CXCursor_DLLImport:
return cxstring::createRef("attribute(dllimport)");
+ case CXCursor_NSReturnsRetained:
+ return cxstring::createRef("attribute(ns_returns_retained)");
+ case CXCursor_NSReturnsNotRetained:
+ return cxstring::createRef("attribute(ns_returns_not_retained)");
+ case CXCursor_NSReturnsAutoreleased:
+ return cxstring::createRef("attribute(ns_returns_autoreleased)");
+ case CXCursor_NSConsumesSelf:
+ return cxstring::createRef("attribute(ns_consumes_self)");
+ case CXCursor_NSConsumed:
+ return cxstring::createRef("attribute(ns_consumed)");
+ case CXCursor_ObjCException:
+ return cxstring::createRef("attribute(objc_exception)");
+ case CXCursor_ObjCNSObject:
+ return cxstring::createRef("attribute(NSObject)");
+ case CXCursor_ObjCIndependentClass:
+ return cxstring::createRef("attribute(objc_independent_class)");
+ case CXCursor_ObjCPreciseLifetime:
+ return cxstring::createRef("attribute(objc_precise_lifetime)");
+ case CXCursor_ObjCReturnsInnerPointer:
+ return cxstring::createRef("attribute(objc_returns_inner_pointer)");
+ case CXCursor_ObjCRequiresSuper:
+ return cxstring::createRef("attribute(objc_requires_super)");
+ case CXCursor_ObjCRootClass:
+ return cxstring::createRef("attribute(objc_root_class)");
+ case CXCursor_ObjCSubclassingRestricted:
+ return cxstring::createRef("attribute(objc_subclassing_restricted)");
+ case CXCursor_ObjCExplicitProtocolImpl:
+ return cxstring::createRef("attribute(objc_protocol_requires_explicit_implementation)");
+ case CXCursor_ObjCDesignatedInitializer:
+ return cxstring::createRef("attribute(objc_designated_initializer)");
+ case CXCursor_ObjCRuntimeVisible:
+ return cxstring::createRef("attribute(objc_runtime_visible)");
+ case CXCursor_ObjCBoxable:
+ return cxstring::createRef("attribute(objc_boxable)");
+ case CXCursor_FlagEnum:
+ return cxstring::createRef("attribute(flag_enum)");
case CXCursor_PreprocessingDirective:
return cxstring::createRef("preprocessing directive");
case CXCursor_MacroDefinition:
@@ -5752,9 +5799,9 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
if (TypeSourceInfo *TSInfo = BaseSpec->getTypeSourceInfo())
return cxloc::translateSourceLocation(getCursorContext(C),
TSInfo->getTypeLoc().getBeginLoc());
-
+
return cxloc::translateSourceLocation(getCursorContext(C),
- BaseSpec->getLocStart());
+ BaseSpec->getBeginLoc());
}
case CXCursor_LabelRef: {
@@ -5778,7 +5825,7 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
if (clang_isStatement(C.kind))
return cxloc::translateSourceLocation(getCursorContext(C),
- getCursorStmt(C)->getLocStart());
+ getCursorStmt(C)->getBeginLoc());
if (C.kind == CXCursor_PreprocessingDirective) {
SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
@@ -5978,10 +6025,10 @@ static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
SourceLocation StartLoc;
if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
- StartLoc = TI->getTypeLoc().getLocStart();
+ StartLoc = TI->getTypeLoc().getBeginLoc();
} else if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
- StartLoc = TI->getTypeLoc().getLocStart();
+ StartLoc = TI->getTypeLoc().getBeginLoc();
}
if (StartLoc.isValid() && R.getBegin().isValid() &&
@@ -6182,6 +6229,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::OMPDeclareReduction:
+ case Decl::OMPRequires:
case Decl::ObjCTypeParam:
case Decl::BuiltinTemplate:
case Decl::PragmaComment:
@@ -6756,11 +6804,18 @@ class AnnotateTokensWorker {
SourceManager &SrcMgr;
bool HasContextSensitiveKeywords;
+ struct PostChildrenAction {
+ CXCursor cursor;
+ enum Action { Invalid, Ignore, Postpone } action;
+ };
+ using PostChildrenActions = SmallVector<PostChildrenAction, 0>;
+
struct PostChildrenInfo {
CXCursor Cursor;
SourceRange CursorRange;
unsigned BeforeReachingCursorIdx;
unsigned BeforeChildrenTokenIdx;
+ PostChildrenActions ChildActions;
};
SmallVector<PostChildrenInfo, 8> PostChildrenInfos;
@@ -6806,7 +6861,13 @@ public:
void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
+ bool IsIgnoredChildCursor(CXCursor cursor) const;
+ PostChildrenActions DetermineChildActions(CXCursor Cursor) const;
+
bool postVisitChildren(CXCursor cursor);
+ void HandlePostPonedChildCursors(const PostChildrenInfo &Info);
+ void HandlePostPonedChildCursor(CXCursor Cursor, unsigned StartTokenIndex);
+
void AnnotateTokens();
/// Determine whether the annotator saw any cursors that have
@@ -6827,6 +6888,67 @@ void AnnotateTokensWorker::AnnotateTokens() {
AnnotateVis.visitFileRegion();
}
+bool AnnotateTokensWorker::IsIgnoredChildCursor(CXCursor cursor) const {
+ if (PostChildrenInfos.empty())
+ return false;
+
+ for (const auto &ChildAction : PostChildrenInfos.back().ChildActions) {
+ if (ChildAction.cursor == cursor &&
+ ChildAction.action == PostChildrenAction::Ignore) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const CXXOperatorCallExpr *GetSubscriptOrCallOperator(CXCursor Cursor) {
+ if (!clang_isExpression(Cursor.kind))
+ return nullptr;
+
+ const Expr *E = getCursorExpr(Cursor);
+ if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
+ const OverloadedOperatorKind Kind = OCE->getOperator();
+ if (Kind == OO_Call || Kind == OO_Subscript)
+ return OCE;
+ }
+
+ return nullptr;
+}
+
+AnnotateTokensWorker::PostChildrenActions
+AnnotateTokensWorker::DetermineChildActions(CXCursor Cursor) const {
+ PostChildrenActions actions;
+
+ // The DeclRefExpr of CXXOperatorCallExpr refering to the custom operator is
+ // visited before the arguments to the operator call. For the Call and
+ // Subscript operator the range of this DeclRefExpr includes the whole call
+ // expression, so that all tokens in that range would be mapped to the
+ // operator function, including the tokens of the arguments. To avoid that,
+ // ensure to visit this DeclRefExpr as last node.
+ if (const auto *OCE = GetSubscriptOrCallOperator(Cursor)) {
+ const Expr *Callee = OCE->getCallee();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee)) {
+ const Expr *SubExpr = ICE->getSubExpr();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
+ const Decl *parentDecl = getCursorDecl(Cursor);
+ CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
+
+ // Visit the DeclRefExpr as last.
+ CXCursor cxChild = MakeCXCursor(DRE, parentDecl, TU);
+ actions.push_back({cxChild, PostChildrenAction::Postpone});
+
+ // The parent of the DeclRefExpr, an ImplicitCastExpr, has an equally
+ // wide range as the DeclRefExpr. We can skip visiting this entirely.
+ cxChild = MakeCXCursor(ICE, parentDecl, TU);
+ actions.push_back({cxChild, PostChildrenAction::Ignore});
+ }
+ }
+ }
+
+ return actions;
+}
+
static inline void updateCursorAnnotation(CXCursor &Cursor,
const CXCursor &updateC) {
if (clang_isInvalid(updateC.kind) || !clang_isInvalid(Cursor.kind))
@@ -6903,7 +7025,10 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
SourceRange cursorRange = getRawCursorExtent(cursor);
if (cursorRange.isInvalid())
return CXChildVisit_Recurse;
-
+
+ if (IsIgnoredChildCursor(cursor))
+ return CXChildVisit_Continue;
+
if (!HasContextSensitiveKeywords) {
// Objective-C properties can have context-sensitive keywords.
if (cursor.kind == CXCursor_ObjCPropertyDecl) {
@@ -7029,11 +7154,11 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
// MyCXXClass foo; // Make sure we don't annotate 'foo' as a CallExpr cursor.
if (clang_isExpression(cursorK) && MoreTokens()) {
const Expr *E = getCursorExpr(cursor);
- if (const Decl *D = getCursorParentDecl(cursor)) {
+ if (const Decl *D = getCursorDecl(cursor)) {
const unsigned I = NextToken();
- if (E->getLocStart().isValid() && D->getLocation().isValid() &&
- E->getLocStart() == D->getLocation() &&
- E->getLocStart() == GetTokenLoc(I)) {
+ if (E->getBeginLoc().isValid() && D->getLocation().isValid() &&
+ E->getBeginLoc() == D->getLocation() &&
+ E->getBeginLoc() == GetTokenLoc(I)) {
updateCursorAnnotation(Cursors[I], updateC);
AdvanceToken();
}
@@ -7051,6 +7176,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
Info.CursorRange = cursorRange;
Info.BeforeReachingCursorIdx = BeforeReachingCursorIdx;
Info.BeforeChildrenTokenIdx = NextToken();
+ Info.ChildActions = DetermineChildActions(cursor);
PostChildrenInfos.push_back(Info);
return CXChildVisit_Recurse;
@@ -7063,6 +7189,8 @@ bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {
if (!clang_equalCursors(Info.Cursor, cursor))
return false;
+ HandlePostPonedChildCursors(Info);
+
const unsigned BeforeChildren = Info.BeforeChildrenTokenIdx;
const unsigned AfterChildren = NextToken();
SourceRange cursorRange = Info.CursorRange;
@@ -7089,6 +7217,56 @@ bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {
return false;
}
+void AnnotateTokensWorker::HandlePostPonedChildCursors(
+ const PostChildrenInfo &Info) {
+ for (const auto &ChildAction : Info.ChildActions) {
+ if (ChildAction.action == PostChildrenAction::Postpone) {
+ HandlePostPonedChildCursor(ChildAction.cursor,
+ Info.BeforeChildrenTokenIdx);
+ }
+ }
+}
+
+void AnnotateTokensWorker::HandlePostPonedChildCursor(
+ CXCursor Cursor, unsigned StartTokenIndex) {
+ const auto flags = CXNameRange_WantQualifier | CXNameRange_WantQualifier;
+ unsigned I = StartTokenIndex;
+
+ // The bracket tokens of a Call or Subscript operator are mapped to
+ // CallExpr/CXXOperatorCallExpr because we skipped visiting the corresponding
+ // DeclRefExpr. Remap these tokens to the DeclRefExpr cursors.
+ for (unsigned RefNameRangeNr = 0; I < NumTokens; RefNameRangeNr++) {
+ const CXSourceRange CXRefNameRange =
+ clang_getCursorReferenceNameRange(Cursor, flags, RefNameRangeNr);
+ if (clang_Range_isNull(CXRefNameRange))
+ break; // All ranges handled.
+
+ SourceRange RefNameRange = cxloc::translateCXSourceRange(CXRefNameRange);
+ while (I < NumTokens) {
+ const SourceLocation TokenLocation = GetTokenLoc(I);
+ if (!TokenLocation.isValid())
+ break;
+
+ // Adapt the end range, because LocationCompare() reports
+ // RangeOverlap even for the not-inclusive end location.
+ const SourceLocation fixedEnd =
+ RefNameRange.getEnd().getLocWithOffset(-1);
+ RefNameRange = SourceRange(RefNameRange.getBegin(), fixedEnd);
+
+ const RangeComparisonResult ComparisonResult =
+ LocationCompare(SrcMgr, TokenLocation, RefNameRange);
+
+ if (ComparisonResult == RangeOverlap) {
+ Cursors[I++] = Cursor;
+ } else if (ComparisonResult == RangeBefore) {
+ ++I; // Not relevant token, check next one.
+ } else if (ComparisonResult == RangeAfter) {
+ break; // All tokens updated for current range, check next.
+ }
+ }
+ }
+}
+
static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
CXCursor parent,
CXClientData client_data) {
@@ -7631,11 +7809,11 @@ static void getCursorPlatformAvailabilityForDecl(
if (AvailabilityAttrs.empty())
return;
- llvm::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+ llvm::sort(AvailabilityAttrs,
[](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
return LHS->getPlatform()->getName() <
RHS->getPlatform()->getName();
- });
+ });
ASTContext &Ctx = D->getASTContext();
auto It = std::unique(
AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
@@ -7877,6 +8055,30 @@ unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved) {
return Result;
}
+CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C) {
+ if (C.kind != CXCursor_ObjCPropertyDecl)
+ return cxstring::createNull();
+
+ const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
+ Selector sel = PD->getGetterName();
+ if (sel.isNull())
+ return cxstring::createNull();
+
+ return cxstring::createDup(sel.getAsString());
+}
+
+CXString clang_Cursor_getObjCPropertySetterName(CXCursor C) {
+ if (C.kind != CXCursor_ObjCPropertyDecl)
+ return cxstring::createNull();
+
+ const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
+ Selector sel = PD->getSetterName();
+ if (sel.isNull())
+ return cxstring::createNull();
+
+ return cxstring::createDup(sel.getAsString());
+}
+
unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return CXObjCDeclQualifier_None;
@@ -8159,7 +8361,7 @@ unsigned clang_CXXMethod_isConst(CXCursor C) {
const Decl *D = cxcursor::getCursorDecl(C);
const CXXMethodDecl *Method =
D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
- return (Method && (Method->getTypeQualifiers() & Qualifiers::Const)) ? 1 : 0;
+ return (Method && Method->getTypeQualifiers().hasConst()) ? 1 : 0;
}
unsigned clang_CXXMethod_isDefaulted(CXCursor C) {
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index f49f9763c362..c5cece52ac6b 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -26,7 +26,6 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/SmallString.h"
@@ -487,7 +486,8 @@ static unsigned long long getContextsForContextKind(
contexts = CXCompletionContext_Namespace;
break;
}
- case CodeCompletionContext::CCC_PotentiallyQualifiedName: {
+ case CodeCompletionContext::CCC_SymbolOrNewName:
+ case CodeCompletionContext::CCC_Symbol: {
contexts = CXCompletionContext_NestedNameSpecifier;
break;
}
@@ -499,6 +499,10 @@ static unsigned long long getContextsForContextKind(
contexts = CXCompletionContext_NaturalLanguage;
break;
}
+ case CodeCompletionContext::CCC_IncludedFile: {
+ contexts = CXCompletionContext_IncludedFile;
+ break;
+ }
case CodeCompletionContext::CCC_SelectorName: {
contexts = CXCompletionContext_ObjCSelectorName;
break;
@@ -535,7 +539,7 @@ static unsigned long long getContextsForContextKind(
case CodeCompletionContext::CCC_Other:
case CodeCompletionContext::CCC_ObjCInterface:
case CodeCompletionContext::CCC_ObjCImplementation:
- case CodeCompletionContext::CCC_Name:
+ case CodeCompletionContext::CCC_NewName:
case CodeCompletionContext::CCC_MacroName:
case CodeCompletionContext::CCC_PreprocessorExpression:
case CodeCompletionContext::CCC_PreprocessorDirective:
@@ -653,7 +657,8 @@ namespace {
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
- unsigned NumCandidates) override {
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc) override {
StoredResults.reserve(StoredResults.size() + NumCandidates);
for (unsigned I = 0; I != NumCandidates; ++I) {
CodeCompletionString *StoredCompletion
diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp
index 4e47b25a4bf0..a4e75e2aae31 100644
--- a/tools/libclang/CIndexDiagnostic.cpp
+++ b/tools/libclang/CIndexDiagnostic.cpp
@@ -19,7 +19,6 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/DiagnosticRenderer.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index e539c8308e75..32333b011ad1 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -40,6 +40,7 @@ set(LIBS
clangIndex
clangLex
clangSema
+ clangSerialization
clangTooling
)
@@ -151,3 +152,22 @@ if (NOT CMAKE_CONFIGURATION_TYPES) # don't add this for IDE's.
add_llvm_install_targets(install-libclang-headers
COMPONENT libclang-headers)
endif()
+
+# Create a target to install the python bindings to make them easier to
+# distribute. Since the bindings are over libclang, which is installed
+# unbundled to the clang version, follow suit.
+foreach(PythonVersion ${CLANG_PYTHON_BINDINGS_VERSIONS})
+ install(DIRECTORY
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../bindings/python/clang
+ COMPONENT
+ libclang-python-bindings
+ DESTINATION
+ "lib${LLVM_LIBDIR_SUFFIX}/python${PythonVersion}/site-packages")
+endforeach()
+if(NOT CMAKE_CONFIGURATION_TYPES)
+ add_custom_target(libclang-python-bindings)
+ add_llvm_install_targets(install-libclang-python-bindings
+ COMPONENT
+ libclang-python-bindings)
+endif()
+
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index b4ad0595cc53..99e4319fc1fa 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -61,6 +61,24 @@ static CXCursorKind GetCursorKind(const Attr *A) {
case attr::Visibility: return CXCursor_VisibilityAttr;
case attr::DLLExport: return CXCursor_DLLExport;
case attr::DLLImport: return CXCursor_DLLImport;
+ case attr::NSReturnsRetained: return CXCursor_NSReturnsRetained;
+ case attr::NSReturnsNotRetained: return CXCursor_NSReturnsNotRetained;
+ case attr::NSReturnsAutoreleased: return CXCursor_NSReturnsAutoreleased;
+ case attr::NSConsumesSelf: return CXCursor_NSConsumesSelf;
+ case attr::NSConsumed: return CXCursor_NSConsumed;
+ case attr::ObjCException: return CXCursor_ObjCException;
+ case attr::ObjCNSObject: return CXCursor_ObjCNSObject;
+ case attr::ObjCIndependentClass: return CXCursor_ObjCIndependentClass;
+ case attr::ObjCPreciseLifetime: return CXCursor_ObjCPreciseLifetime;
+ case attr::ObjCReturnsInnerPointer: return CXCursor_ObjCReturnsInnerPointer;
+ case attr::ObjCRequiresSuper: return CXCursor_ObjCRequiresSuper;
+ case attr::ObjCRootClass: return CXCursor_ObjCRootClass;
+ case attr::ObjCSubclassingRestricted: return CXCursor_ObjCSubclassingRestricted;
+ case attr::ObjCExplicitProtocolImpl: return CXCursor_ObjCExplicitProtocolImpl;
+ case attr::ObjCDesignatedInitializer: return CXCursor_ObjCDesignatedInitializer;
+ case attr::ObjCRuntimeVisible: return CXCursor_ObjCRuntimeVisible;
+ case attr::ObjCBoxable: return CXCursor_ObjCBoxable;
+ case attr::FlagEnum: return CXCursor_FlagEnum;
}
return CXCursor_UnexposedAttr;
@@ -223,16 +241,19 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::SEHLeaveStmtClass:
K = CXCursor_SEHLeaveStmt;
break;
-
+
+ case Stmt::CoroutineBodyStmtClass:
+ case Stmt::CoreturnStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+
case Stmt::ArrayTypeTraitExprClass:
case Stmt::AsTypeExprClass:
case Stmt::AtomicExprClass:
case Stmt::BinaryConditionalOperatorClass:
case Stmt::TypeTraitExprClass:
- case Stmt::CoroutineBodyStmtClass:
case Stmt::CoawaitExprClass:
case Stmt::DependentCoawaitExprClass:
- case Stmt::CoreturnStmtClass:
case Stmt::CoyieldExprClass:
case Stmt::CXXBindTemporaryExprClass:
case Stmt::CXXDefaultArgExprClass:
@@ -325,6 +346,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_CharacterLiteral;
break;
+ case Stmt::ConstantExprClass:
+ return MakeCXCursor(cast<ConstantExpr>(S)->getSubExpr(),
+ Parent, TU, RegionOfInterest);
+
case Stmt::ParenExprClass:
K = CXCursor_ParenExpr;
break;
@@ -990,10 +1015,6 @@ const Attr *cxcursor::getCursorAttr(CXCursor Cursor) {
return static_cast<const Attr *>(Cursor.data[1]);
}
-const Decl *cxcursor::getCursorParentDecl(CXCursor Cursor) {
- return static_cast<const Decl *>(Cursor.data[0]);
-}
-
ASTContext &cxcursor::getCursorContext(CXCursor Cursor) {
return getCursorASTUnit(Cursor)->getASTContext();
}
@@ -1146,6 +1167,9 @@ int clang_Cursor_getNumArguments(CXCursor C) {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
return CE->getNumArgs();
}
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
+ return CE->getNumArgs();
+ }
}
return -1;
@@ -1174,6 +1198,13 @@ CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) {
cxcursor::getCursorTU(C));
}
}
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
+ if (i < CE->getNumArgs()) {
+ return cxcursor::MakeCXCursor(CE->getArg(i),
+ getCursorDecl(C),
+ cxcursor::getCursorTU(C));
+ }
+ }
}
return clang_getNullCursor();
@@ -1394,16 +1425,16 @@ CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
}
} else if (kind == CXCursor_MacroDefinition) {
const MacroDefinitionRecord *definition = getCursorMacroDefinition(cursor);
- const IdentifierInfo *MacroInfo = definition->getName();
+ const IdentifierInfo *Macro = definition->getName();
ASTUnit *unit = getCursorASTUnit(cursor);
- CodeCompletionResult Result(MacroInfo);
- CodeCompletionString *String
- = Result.CreateCodeCompletionString(unit->getASTContext(),
- unit->getPreprocessor(),
- CodeCompletionContext::CCC_Other,
- unit->getCodeCompletionTUInfo().getAllocator(),
- unit->getCodeCompletionTUInfo(),
- false);
+ CodeCompletionResult Result(
+ Macro,
+ unit->getPreprocessor().getMacroDefinition(Macro).getMacroInfo());
+ CodeCompletionString *String = Result.CreateCodeCompletionString(
+ unit->getASTContext(), unit->getPreprocessor(),
+ CodeCompletionContext::CCC_Other,
+ unit->getCodeCompletionTUInfo().getAllocator(),
+ unit->getCodeCompletionTUInfo(), false);
return String;
}
return nullptr;
diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h
index a5d9fff2a55a..312fb3ff250b 100644
--- a/tools/libclang/CXCursor.h
+++ b/tools/libclang/CXCursor.h
@@ -43,11 +43,11 @@ class TemplateName;
class TypeDecl;
class VarDecl;
class IdentifierInfo;
-
+
namespace cxcursor {
CXCursor getCursor(CXTranslationUnit, SourceLocation);
-
+
CXCursor MakeCXCursor(const clang::Attr *A, const clang::Decl *Parent,
CXTranslationUnit TU);
CXCursor MakeCXCursor(const clang::Decl *D, CXTranslationUnit TU,
@@ -125,7 +125,7 @@ std::pair<const VarDecl *, SourceLocation> getCursorVariableRef(CXCursor C);
/// Create a reference to a field at the given location.
CXCursor MakeCursorMemberRef(const FieldDecl *Field, SourceLocation Loc,
CXTranslationUnit TU);
-
+
/// Unpack a MemberRef cursor into the field it references and the
/// location where the reference occurred.
std::pair<const FieldDecl *, SourceLocation> getCursorMemberRef(CXCursor C);
@@ -232,17 +232,16 @@ CXCursor MakeCursorOverloadedDeclRef(TemplateName Template,
typedef llvm::PointerUnion3<const OverloadExpr *, const Decl *,
OverloadedTemplateStorage *>
OverloadedDeclRefStorage;
-
+
/// Unpack an overloaded declaration reference into an expression,
/// declaration, or template name along with the source location.
std::pair<OverloadedDeclRefStorage, SourceLocation>
getCursorOverloadedDeclRef(CXCursor C);
-
+
const Decl *getCursorDecl(CXCursor Cursor);
const Expr *getCursorExpr(CXCursor Cursor);
const Stmt *getCursorStmt(CXCursor Cursor);
const Attr *getCursorAttr(CXCursor Cursor);
-const Decl *getCursorParentDecl(CXCursor Cursor);
ASTContext &getCursorContext(CXCursor Cursor);
ASTUnit *getCursorASTUnit(CXCursor Cursor);
@@ -250,14 +249,14 @@ CXTranslationUnit getCursorTU(CXCursor Cursor);
void getOverriddenCursors(CXCursor cursor,
SmallVectorImpl<CXCursor> &overridden);
-
+
/// Create an opaque pool used for fast generation of overridden
/// CXCursor arrays.
void *createOverridenCXCursorsPool();
/// Dispose of the overridden CXCursors pool.
void disposeOverridenCXCursorsPool(void *pool);
-
+
/// Returns a index/location pair for a selector identifier if the cursor
/// points to one.
std::pair<int, SourceLocation> getSelectorIdentifierIndexAndLoc(CXCursor);
@@ -285,7 +284,7 @@ CXCursor getTypeRefCursor(CXCursor cursor);
bool getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf);
bool operator==(CXCursor X, CXCursor Y);
-
+
inline bool operator!=(CXCursor X, CXCursor Y) {
return !(X == Y);
}
diff --git a/tools/libclang/CXIndexDataConsumer.cpp b/tools/libclang/CXIndexDataConsumer.cpp
index 616a0797f52b..3dec36a5daeb 100644
--- a/tools/libclang/CXIndexDataConsumer.cpp
+++ b/tools/libclang/CXIndexDataConsumer.cpp
@@ -222,9 +222,11 @@ bool CXIndexDataConsumer::handleDeclOccurence(
}
bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
+ const Module *Mod,
SymbolRoleSet Roles,
SourceLocation Loc) {
- IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
+ if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
+ IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
return !shouldAbort();
}
@@ -307,7 +309,7 @@ AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
const IBOutletCollectionAttr *
IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
SourceLocation InterfaceLocStart =
- IBAttr->getInterfaceLoc()->getTypeLoc().getLocStart();
+ IBAttr->getInterfaceLoc()->getTypeLoc().getBeginLoc();
IBInfo.IBCollInfo.attrInfo = &IBInfo;
IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(InterfaceLocStart);
IBInfo.IBCollInfo.objcClass = nullptr;
diff --git a/tools/libclang/CXIndexDataConsumer.h b/tools/libclang/CXIndexDataConsumer.h
index 19e39b281ab0..5c1ce80b2f49 100644
--- a/tools/libclang/CXIndexDataConsumer.h
+++ b/tools/libclang/CXIndexDataConsumer.h
@@ -467,7 +467,7 @@ private:
ArrayRef<index::SymbolRelation> Relations,
SourceLocation Loc, ASTNodeInfo ASTNode) override;
- bool handleModuleOccurence(const ImportDecl *ImportD,
+ bool handleModuleOccurence(const ImportDecl *ImportD, const Module *Mod,
index::SymbolRoleSet Roles,
SourceLocation Loc) override;
diff --git a/tools/libclang/CXStoredDiagnostic.cpp b/tools/libclang/CXStoredDiagnostic.cpp
index f2e9c1da28f6..6bd2f6746693 100644
--- a/tools/libclang/CXStoredDiagnostic.cpp
+++ b/tools/libclang/CXStoredDiagnostic.cpp
@@ -17,8 +17,8 @@
#include "CXSourceLocation.h"
#include "CXString.h"
+#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/Twine.h"
using namespace clang;
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index 7c0f307944a1..b8009ddc1c1a 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -70,6 +70,8 @@ static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) BTCASE(Id);
#include "clang/Basic/OpenCLImageTypes.def"
#undef IMAGE_TYPE
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) BTCASE(Id);
+#include "clang/Basic/OpenCLExtensionTypes.def"
BTCASE(OCLSampler);
BTCASE(OCLEvent);
BTCASE(OCLQueue);
@@ -98,7 +100,9 @@ static CXTypeKind GetTypeKind(QualType T) {
TKCASE(Enum);
TKCASE(Typedef);
TKCASE(ObjCInterface);
+ TKCASE(ObjCObject);
TKCASE(ObjCObjectPointer);
+ TKCASE(ObjCTypeParam);
TKCASE(FunctionNoProto);
TKCASE(FunctionProto);
TKCASE(ConstantArray);
@@ -110,6 +114,7 @@ static CXTypeKind GetTypeKind(QualType T) {
TKCASE(Auto);
TKCASE(Elaborated);
TKCASE(Pipe);
+ TKCASE(Attributed);
default:
return CXType_Unexposed;
}
@@ -123,7 +128,9 @@ CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
if (TU && !T.isNull()) {
// Handle attributed types as the original type
if (auto *ATT = T->getAs<AttributedType>()) {
- return MakeCXType(ATT->getModifiedType(), TU);
+ if (!(TU->ParsingOptions & CXTranslationUnit_IncludeAttributedTypes)) {
+ return MakeCXType(ATT->getModifiedType(), TU);
+ }
}
// Handle paren types as the original type
if (auto *PTT = T->getAs<ParenType>()) {
@@ -131,7 +138,7 @@ CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
}
ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
- if (Ctx.getLangOpts().ObjC1) {
+ if (Ctx.getLangOpts().ObjC) {
QualType UnqualT = T.getUnqualifiedType();
if (Ctx.isObjCIdType(UnqualT))
TK = CXType_ObjCId;
@@ -437,6 +444,7 @@ CXType clang_getPointeeType(CXType CT) {
if (!TP)
return MakeCXType(QualType(), GetTU(CT));
+try_again:
switch (TP->getTypeClass()) {
case Type::Pointer:
T = cast<PointerType>(TP)->getPointeeType();
@@ -454,6 +462,12 @@ CXType clang_getPointeeType(CXType CT) {
case Type::MemberPointer:
T = cast<MemberPointerType>(TP)->getPointeeType();
break;
+ case Type::Auto:
+ case Type::DeducedTemplateSpecialization:
+ TP = cast<DeducedType>(TP)->getDeducedType().getTypePtrOrNull();
+ if (TP)
+ goto try_again;
+ break;
default:
T = QualType();
break;
@@ -575,7 +589,9 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
TKIND(Enum);
TKIND(Typedef);
TKIND(ObjCInterface);
+ TKIND(ObjCObject);
TKIND(ObjCObjectPointer);
+ TKIND(ObjCTypeParam);
TKIND(FunctionNoProto);
TKIND(FunctionProto);
TKIND(ConstantArray);
@@ -587,9 +603,12 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
TKIND(Auto);
TKIND(Elaborated);
TKIND(Pipe);
+ TKIND(Attributed);
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) TKIND(Id);
#include "clang/Basic/OpenCLImageTypes.def"
#undef IMAGE_TYPE
+#define EXT_OPAQUE_TYPE(ExtTYpe, Id, Ext) TKIND(Id);
+#include "clang/Basic/OpenCLExtensionTypes.def"
TKIND(OCLSampler);
TKIND(OCLEvent);
TKIND(OCLQueue);
@@ -632,6 +651,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
TCALLINGCONV(X86Pascal);
TCALLINGCONV(X86RegCall);
TCALLINGCONV(X86VectorCall);
+ TCALLINGCONV(AArch64VectorCall);
TCALLINGCONV(Win64);
TCALLINGCONV(X86_64SysV);
TCALLINGCONV(AAPCS);
@@ -992,6 +1012,17 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) {
return CXTypeLayoutError_InvalidFieldName;
}
+CXType clang_Type_getModifiedType(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ if (auto *ATT = T->getAs<AttributedType>())
+ return MakeCXType(ATT->getModifiedType(), GetTU(CT));
+
+ return MakeCXType(QualType(), GetTU(CT));
+}
+
long long clang_Cursor_getOffsetOfField(CXCursor C) {
if (clang_isDeclaration(C.kind)) {
// we need to validate the parent type
@@ -1098,6 +1129,74 @@ CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) {
return MakeCXType(QT.getValueOr(QualType()), GetTU(CT));
}
+CXType clang_Type_getObjCObjectBaseType(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return MakeCXType(QualType(), GetTU(CT));
+
+ return MakeCXType(OT->getBaseType(), GetTU(CT));
+}
+
+unsigned clang_Type_getNumObjCProtocolRefs(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return 0;
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return 0;
+
+ return OT->getNumProtocols();
+}
+
+CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ const ObjCProtocolDecl *PD = OT->getProtocol(i);
+ if (!PD)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ return cxcursor::MakeCXCursor(PD, GetTU(CT));
+}
+
+unsigned clang_Type_getNumObjCTypeArgs(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return 0;
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return 0;
+
+ return OT->getTypeArgs().size();
+}
+
+CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return MakeCXType(QualType(), GetTU(CT));
+
+ const ArrayRef<QualType> TA = OT->getTypeArgs();
+ if ((size_t)i >= TA.size())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ return MakeCXType(TA[i], GetTU(CT));
+}
+
unsigned clang_Type_visitFields(CXType PT,
CXFieldVisitor visitor,
CXClientData client_data){
@@ -1130,11 +1229,15 @@ unsigned clang_Cursor_isAnonymous(CXCursor C){
if (!clang_isDeclaration(C.kind))
return 0;
const Decl *D = cxcursor::getCursorDecl(C);
- if (const RecordDecl *FD = dyn_cast_or_null<RecordDecl>(D))
- return FD->isAnonymousStructOrUnion();
+ if (const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(D)) {
+ return ND->isAnonymousNamespace();
+ } else if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(D)) {
+ return TD->getTypedefNameForAnonDecl() == nullptr &&
+ TD->getIdentifier() == nullptr;
+ }
+
return 0;
}
-
CXType clang_Type_getNamedType(CXType CT){
QualType T = GetQualType(CT);
const Type *TP = T.getTypePtrOrNull();
@@ -1153,3 +1256,22 @@ unsigned clang_Type_isTransparentTagTypedef(CXType TT){
}
return false;
}
+
+enum CXTypeNullabilityKind clang_Type_getNullability(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return CXTypeNullability_Invalid;
+
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(CT))->getASTContext();
+ if (auto nullability = T->getNullability(Ctx)) {
+ switch (*nullability) {
+ case NullabilityKind::NonNull:
+ return CXTypeNullability_NonNull;
+ case NullabilityKind::Nullable:
+ return CXTypeNullability_Nullable;
+ case NullabilityKind::Unspecified:
+ return CXTypeNullability_Unspecified;
+ }
+ }
+ return CXTypeNullability_Invalid;
+}
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 95a42712c4af..2c4b083a594a 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -31,6 +31,8 @@ clang_Cursor_getRawCommentText
clang_Cursor_getNumArguments
clang_Cursor_getObjCDeclQualifiers
clang_Cursor_getObjCPropertyAttributes
+clang_Cursor_getObjCPropertyGetterName
+clang_Cursor_getObjCPropertySetterName
clang_Cursor_getObjCSelectorIndex
clang_Cursor_getOffsetOfField
clang_Cursor_getSpellingNameRange
@@ -98,6 +100,13 @@ clang_Type_getCXXRefQualifier
clang_Type_visitFields
clang_Type_getNamedType
clang_Type_isTransparentTagTypedef
+clang_Type_getObjCObjectBaseType
+clang_Type_getNumObjCProtocolRefs
+clang_Type_getObjCProtocolDecl
+clang_Type_getNumObjCTypeArgs
+clang_Type_getObjCTypeArg
+clang_Type_getModifiedType
+clang_Type_getNullability
clang_VerbatimBlockLineComment_getText
clang_VerbatimLineComment_getText
clang_HTMLTagComment_getAsString
diff --git a/tools/scan-build-py/README.md b/tools/scan-build-py/README.md
index 720bde1cf3b1..01e3454bed44 100644
--- a/tools/scan-build-py/README.md
+++ b/tools/scan-build-py/README.md
@@ -53,7 +53,7 @@ with CTU analysis enabled, execute:
$ analyze-build --ctu
-For CTU analysis an additional (function-definition) collection-phase is required.
+For CTU analysis an additional (external definition) collection-phase is required.
For debugging purposes, it is possible to separately execute the collection
and the analysis phase. By doing this, the intermediate files used for
the analysis are kept on the disk in `./ctu-dir`.
diff --git a/tools/scan-build-py/libscanbuild/__init__.py b/tools/scan-build-py/libscanbuild/__init__.py
index e7b74879167e..903207c6be09 100644
--- a/tools/scan-build-py/libscanbuild/__init__.py
+++ b/tools/scan-build-py/libscanbuild/__init__.py
@@ -20,7 +20,7 @@ ENVIRONMENT_KEY = 'INTERCEPT_BUILD'
Execution = collections.namedtuple('Execution', ['pid', 'cwd', 'cmd'])
CtuConfig = collections.namedtuple('CtuConfig', ['collect', 'analyze', 'dir',
- 'func_map_cmd'])
+ 'extdef_map_cmd'])
def duplicate_check(method):
diff --git a/tools/scan-build-py/libscanbuild/analyze.py b/tools/scan-build-py/libscanbuild/analyze.py
index 5a7cc20a517e..ab8ea62f46fe 100644
--- a/tools/scan-build-py/libscanbuild/analyze.py
+++ b/tools/scan-build-py/libscanbuild/analyze.py
@@ -42,8 +42,8 @@ __all__ = ['scan_build', 'analyze_build', 'analyze_compiler_wrapper']
COMPILER_WRAPPER_CC = 'analyze-cc'
COMPILER_WRAPPER_CXX = 'analyze-c++'
-CTU_FUNCTION_MAP_FILENAME = 'externalFnMap.txt'
-CTU_TEMP_FNMAP_FOLDER = 'tmpExternalFnMaps'
+CTU_EXTDEF_MAP_FILENAME = 'externalDefMap.txt'
+CTU_TEMP_DEFMAP_FOLDER = 'tmpExternalDefMaps'
@command_entry_point
@@ -117,9 +117,9 @@ def get_ctu_config_from_args(args):
CtuConfig(collect=args.ctu_phases.collect,
analyze=args.ctu_phases.analyze,
dir=args.ctu_dir,
- func_map_cmd=args.func_map_cmd)
+ extdef_map_cmd=args.extdef_map_cmd)
if hasattr(args, 'ctu_phases') and hasattr(args.ctu_phases, 'dir')
- else CtuConfig(collect=False, analyze=False, dir='', func_map_cmd=''))
+ else CtuConfig(collect=False, analyze=False, dir='', extdef_map_cmd=''))
def get_ctu_config_from_json(ctu_conf_json):
@@ -130,23 +130,24 @@ def get_ctu_config_from_json(ctu_conf_json):
return CtuConfig(collect=ctu_config[0],
analyze=ctu_config[1],
dir=ctu_config[2],
- func_map_cmd=ctu_config[3])
+ extdef_map_cmd=ctu_config[3])
-def create_global_ctu_function_map(func_map_lines):
- """ Takes iterator of individual function maps and creates a global map
- keeping only unique names. We leave conflicting names out of CTU.
+def create_global_ctu_extdef_map(extdef_map_lines):
+ """ Takes iterator of individual external definition maps and creates a
+ global map keeping only unique names. We leave conflicting names out of
+ CTU.
- :param func_map_lines: Contains the id of a function (mangled name) and
+ :param extdef_map_lines: Contains the id of a definition (mangled name) and
the originating source (the corresponding AST file) name.
- :type func_map_lines: Iterator of str.
+ :type extdef_map_lines: Iterator of str.
:returns: Mangled name - AST file pairs.
:rtype: List of (str, str) tuples.
"""
mangled_to_asts = defaultdict(set)
- for line in func_map_lines:
+ for line in extdef_map_lines:
mangled_name, ast_file = line.strip().split(' ', 1)
mangled_to_asts[mangled_name].add(ast_file)
@@ -159,20 +160,20 @@ def create_global_ctu_function_map(func_map_lines):
return mangled_ast_pairs
-def merge_ctu_func_maps(ctudir):
- """ Merge individual function maps into a global one.
+def merge_ctu_extdef_maps(ctudir):
+ """ Merge individual external definition maps into a global one.
As the collect phase runs parallel on multiple threads, all compilation
- units are separately mapped into a temporary file in CTU_TEMP_FNMAP_FOLDER.
- These function maps contain the mangled names of functions and the source
- (AST generated from the source) which had them.
+ units are separately mapped into a temporary file in CTU_TEMP_DEFMAP_FOLDER.
+ These definition maps contain the mangled names and the source
+ (AST generated from the source) which had their definition.
These files should be merged at the end into a global map file:
- CTU_FUNCTION_MAP_FILENAME."""
+ CTU_EXTDEF_MAP_FILENAME."""
- def generate_func_map_lines(fnmap_dir):
+ def generate_extdef_map_lines(extdefmap_dir):
""" Iterate over all lines of input files in a determined order. """
- files = glob.glob(os.path.join(fnmap_dir, '*'))
+ files = glob.glob(os.path.join(extdefmap_dir, '*'))
files.sort()
for filename in files:
with open(filename, 'r') as in_file:
@@ -180,11 +181,11 @@ def merge_ctu_func_maps(ctudir):
yield line
def write_global_map(arch, mangled_ast_pairs):
- """ Write (mangled function name, ast file) pairs into final file. """
+ """ Write (mangled name, ast file) pairs into final file. """
- extern_fns_map_file = os.path.join(ctudir, arch,
- CTU_FUNCTION_MAP_FILENAME)
- with open(extern_fns_map_file, 'w') as out_file:
+ extern_defs_map_file = os.path.join(ctudir, arch,
+ CTU_EXTDEF_MAP_FILENAME)
+ with open(extern_defs_map_file, 'w') as out_file:
for mangled_name, ast_file in mangled_ast_pairs:
out_file.write('%s %s\n' % (mangled_name, ast_file))
@@ -192,15 +193,15 @@ def merge_ctu_func_maps(ctudir):
for triple_path in triple_arches:
if os.path.isdir(triple_path):
triple_arch = os.path.basename(triple_path)
- fnmap_dir = os.path.join(ctudir, triple_arch,
- CTU_TEMP_FNMAP_FOLDER)
+ extdefmap_dir = os.path.join(ctudir, triple_arch,
+ CTU_TEMP_DEFMAP_FOLDER)
- func_map_lines = generate_func_map_lines(fnmap_dir)
- mangled_ast_pairs = create_global_ctu_function_map(func_map_lines)
+ extdef_map_lines = generate_extdef_map_lines(extdefmap_dir)
+ mangled_ast_pairs = create_global_ctu_extdef_map(extdef_map_lines)
write_global_map(triple_arch, mangled_ast_pairs)
# Remove all temporary files
- shutil.rmtree(fnmap_dir, ignore_errors=True)
+ shutil.rmtree(extdefmap_dir, ignore_errors=True)
def run_analyzer_parallel(args):
@@ -251,21 +252,21 @@ def govern_analyzer_runs(args):
# left so multiple analyze runs can use the same data gathered by a single
# collection run.
if ctu_config.collect and ctu_config.analyze:
- # CTU strings are coming from args.ctu_dir and func_map_cmd,
+ # CTU strings are coming from args.ctu_dir and extdef_map_cmd,
# so we can leave it empty
args.ctu_phases = CtuConfig(collect=True, analyze=False,
- dir='', func_map_cmd='')
+ dir='', extdef_map_cmd='')
run_analyzer_parallel(args)
- merge_ctu_func_maps(ctu_config.dir)
+ merge_ctu_extdef_maps(ctu_config.dir)
args.ctu_phases = CtuConfig(collect=False, analyze=True,
- dir='', func_map_cmd='')
+ dir='', extdef_map_cmd='')
run_analyzer_parallel(args)
shutil.rmtree(ctu_config.dir, ignore_errors=True)
else:
# Single runs (collect or analyze) are launched from here.
run_analyzer_parallel(args)
if ctu_config.collect:
- merge_ctu_func_maps(ctu_config.dir)
+ merge_ctu_extdef_maps(ctu_config.dir)
def setup_environment(args):
@@ -395,8 +396,6 @@ def analyzer_params(args):
if args.disable_checker:
checkers = ','.join(args.disable_checker)
result.extend(['-analyzer-disable-checker', checkers])
- if os.getenv('UBIVIZ'):
- result.append('-analyzer-viz-egraph-ubigraph')
return prefix_with('-Xclang', result)
@@ -546,20 +545,20 @@ def run_analyzer(opts, continuation=report_failure):
return result
-def func_map_list_src_to_ast(func_src_list):
- """ Turns textual function map list with source files into a
- function map list with ast files. """
+def extdef_map_list_src_to_ast(extdef_src_list):
+ """ Turns textual external definition map list with source files into an
+ external definition map list with ast files. """
- func_ast_list = []
- for fn_src_txt in func_src_list:
- mangled_name, path = fn_src_txt.split(" ", 1)
+ extdef_ast_list = []
+ for extdef_src_txt in extdef_src_list:
+ mangled_name, path = extdef_src_txt.split(" ", 1)
# Normalize path on windows as well
path = os.path.splitdrive(path)[1]
# Make relative path out of absolute
path = path[1:] if path[0] == os.sep else path
ast_path = os.path.join("ast", path + ".ast")
- func_ast_list.append(mangled_name + " " + ast_path)
- return func_ast_list
+ extdef_ast_list.append(mangled_name + " " + ast_path)
+ return extdef_ast_list
@require(['clang', 'directory', 'flags', 'direct_args', 'file', 'ctu'])
@@ -590,37 +589,38 @@ def ctu_collect_phase(opts):
logging.debug("Generating AST using '%s'", ast_command)
run_command(ast_command, cwd=opts['directory'])
- def map_functions(triple_arch):
- """ Generate function map file for the current source. """
+ def map_extdefs(triple_arch):
+ """ Generate external definition map file for the current source. """
args = opts['direct_args'] + opts['flags']
- funcmap_command = [opts['ctu'].func_map_cmd]
- funcmap_command.append(opts['file'])
- funcmap_command.append('--')
- funcmap_command.extend(args)
- logging.debug("Generating function map using '%s'", funcmap_command)
- func_src_list = run_command(funcmap_command, cwd=opts['directory'])
- func_ast_list = func_map_list_src_to_ast(func_src_list)
- extern_fns_map_folder = os.path.join(opts['ctu'].dir, triple_arch,
- CTU_TEMP_FNMAP_FOLDER)
- if not os.path.isdir(extern_fns_map_folder):
+ extdefmap_command = [opts['ctu'].extdef_map_cmd]
+ extdefmap_command.append(opts['file'])
+ extdefmap_command.append('--')
+ extdefmap_command.extend(args)
+ logging.debug("Generating external definition map using '%s'",
+ extdefmap_command)
+ extdef_src_list = run_command(extdefmap_command, cwd=opts['directory'])
+ extdef_ast_list = extdef_map_list_src_to_ast(extdef_src_list)
+ extern_defs_map_folder = os.path.join(opts['ctu'].dir, triple_arch,
+ CTU_TEMP_DEFMAP_FOLDER)
+ if not os.path.isdir(extern_defs_map_folder):
try:
- os.makedirs(extern_fns_map_folder)
+ os.makedirs(extern_defs_map_folder)
except OSError:
# In case an other process already created it.
pass
- if func_ast_list:
+ if extdef_ast_list:
with tempfile.NamedTemporaryFile(mode='w',
- dir=extern_fns_map_folder,
+ dir=extern_defs_map_folder,
delete=False) as out_file:
- out_file.write("\n".join(func_ast_list) + "\n")
+ out_file.write("\n".join(extdef_ast_list) + "\n")
cwd = opts['directory']
cmd = [opts['clang'], '--analyze'] + opts['direct_args'] + opts['flags'] \
+ [opts['file']]
triple_arch = get_triple_arch(cmd, cwd)
generate_ast(triple_arch)
- map_functions(triple_arch)
+ map_extdefs(triple_arch)
@require(['ctu'])
diff --git a/tools/scan-build-py/libscanbuild/arguments.py b/tools/scan-build-py/libscanbuild/arguments.py
index a5d0c6bda661..58c56d2b6d29 100644
--- a/tools/scan-build-py/libscanbuild/arguments.py
+++ b/tools/scan-build-py/libscanbuild/arguments.py
@@ -12,6 +12,7 @@ earlier.)
It also implements basic validation methods, related to the command.
Validations are mostly calling specific help methods, or mangling values.
"""
+from __future__ import absolute_import, division, print_function
import os
import sys
@@ -134,10 +135,10 @@ def validate_args_for_analyze(parser, args, from_build_command):
if args.ctu_phases.analyze and not args.ctu_phases.collect \
and not os.path.exists(args.ctu_dir):
parser.error(message='missing CTU directory')
- # Check CTU capability via checking clang-func-mapping
- if not is_ctu_capable(args.func_map_cmd):
+ # Check CTU capability via checking clang-extdef-mapping
+ if not is_ctu_capable(args.extdef_map_cmd):
parser.error(message="""This version of clang does not support CTU
- functionality or clang-func-mapping command not found.""")
+ functionality or clang-extdef-mapping command not found.""")
def create_intercept_parser():
@@ -365,7 +366,7 @@ def create_analyze_parser(from_build_command):
'--ctu',
action='store_const',
const=CtuConfig(collect=True, analyze=True,
- dir='', func_map_cmd=''),
+ dir='', extdef_map_cmd=''),
dest='ctu_phases',
help="""Perform cross translation unit (ctu) analysis (both collect
and analyze phases) using default <ctu-dir> for temporary output.
@@ -381,7 +382,7 @@ def create_analyze_parser(from_build_command):
'--ctu-collect-only',
action='store_const',
const=CtuConfig(collect=True, analyze=False,
- dir='', func_map_cmd=''),
+ dir='', extdef_map_cmd=''),
dest='ctu_phases',
help="""Perform only the collect phase of ctu.
Keep <ctu-dir> for further use.""")
@@ -389,20 +390,20 @@ def create_analyze_parser(from_build_command):
'--ctu-analyze-only',
action='store_const',
const=CtuConfig(collect=False, analyze=True,
- dir='', func_map_cmd=''),
+ dir='', extdef_map_cmd=''),
dest='ctu_phases',
help="""Perform only the analyze phase of ctu. <ctu-dir> should be
present and will not be removed after analysis.""")
ctu.add_argument(
- '--use-func-map-cmd',
+ '--use-extdef-map-cmd',
metavar='<path>',
- dest='func_map_cmd',
- default='clang-func-mapping',
- help="""'%(prog)s' uses the 'clang-func-mapping' executable
- relative to itself for generating function maps for static
- analysis. One can override this behavior with this option by using
- the 'clang-func-mapping' packaged with Xcode (on OS X) or from the
- PATH.""")
+ dest='extdef_map_cmd',
+ default='clang-extdef-mapping',
+ help="""'%(prog)s' uses the 'clang-extdef-mapping' executable
+ relative to itself for generating external definition maps for
+ static analysis. One can override this behavior with this option
+ by using the 'clang-extdef-mapping' packaged with Xcode (on OS X)
+ or from the PATH.""")
return parser
diff --git a/tools/scan-build-py/libscanbuild/clang.py b/tools/scan-build-py/libscanbuild/clang.py
index ab422066cab1..0cbfdb648f6a 100644
--- a/tools/scan-build-py/libscanbuild/clang.py
+++ b/tools/scan-build-py/libscanbuild/clang.py
@@ -156,12 +156,12 @@ def get_checkers(clang, plugins):
return checkers
-def is_ctu_capable(func_map_cmd):
- """ Detects if the current (or given) clang and function mapping
+def is_ctu_capable(extdef_map_cmd):
+ """ Detects if the current (or given) clang and external definition mapping
executables are CTU compatible. """
try:
- run_command([func_map_cmd, '-version'])
+ run_command([extdef_map_cmd, '-version'])
except (OSError, subprocess.CalledProcessError):
return False
return True
diff --git a/tools/scan-build-py/tests/unit/test_analyze.py b/tools/scan-build-py/tests/unit/test_analyze.py
index 9964a296b8dd..768a3b691090 100644
--- a/tools/scan-build-py/tests/unit/test_analyze.py
+++ b/tools/scan-build-py/tests/unit/test_analyze.py
@@ -349,14 +349,14 @@ class PrefixWithTest(unittest.TestCase):
class MergeCtuMapTest(unittest.TestCase):
def test_no_map_gives_empty(self):
- pairs = sut.create_global_ctu_function_map([])
+ pairs = sut.create_global_ctu_extdef_map([])
self.assertFalse(pairs)
def test_multiple_maps_merged(self):
concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
'c:@F@fun2#I# ast/fun2.c.ast',
'c:@F@fun3#I# ast/fun3.c.ast']
- pairs = sut.create_global_ctu_function_map(concat_map)
+ pairs = sut.create_global_ctu_extdef_map(concat_map)
self.assertTrue(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
self.assertTrue(('c:@F@fun3#I#', 'ast/fun3.c.ast') in pairs)
@@ -366,7 +366,7 @@ class MergeCtuMapTest(unittest.TestCase):
concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
'c:@F@fun2#I# ast/fun2.c.ast',
'c:@F@fun1#I# ast/fun7.c.ast']
- pairs = sut.create_global_ctu_function_map(concat_map)
+ pairs = sut.create_global_ctu_extdef_map(concat_map)
self.assertFalse(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
self.assertFalse(('c:@F@fun1#I#', 'ast/fun7.c.ast') in pairs)
self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
@@ -376,28 +376,28 @@ class MergeCtuMapTest(unittest.TestCase):
concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
'c:@F@fun2#I# ast/fun2.c.ast',
'c:@F@fun1#I# ast/fun1.c.ast']
- pairs = sut.create_global_ctu_function_map(concat_map)
+ pairs = sut.create_global_ctu_extdef_map(concat_map)
self.assertTrue(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
self.assertEqual(2, len(pairs))
def test_space_handled_in_source(self):
concat_map = ['c:@F@fun1#I# ast/f un.c.ast']
- pairs = sut.create_global_ctu_function_map(concat_map)
+ pairs = sut.create_global_ctu_extdef_map(concat_map)
self.assertTrue(('c:@F@fun1#I#', 'ast/f un.c.ast') in pairs)
self.assertEqual(1, len(pairs))
-class FuncMapSrcToAstTest(unittest.TestCase):
+class ExtdefMapSrcToAstTest(unittest.TestCase):
def test_empty_gives_empty(self):
- fun_ast_lst = sut.func_map_list_src_to_ast([])
+ fun_ast_lst = sut.extdef_map_list_src_to_ast([])
self.assertFalse(fun_ast_lst)
def test_sources_to_asts(self):
fun_src_lst = ['c:@F@f1#I# ' + os.path.join(os.sep + 'path', 'f1.c'),
'c:@F@f2#I# ' + os.path.join(os.sep + 'path', 'f2.c')]
- fun_ast_lst = sut.func_map_list_src_to_ast(fun_src_lst)
+ fun_ast_lst = sut.extdef_map_list_src_to_ast(fun_src_lst)
self.assertTrue('c:@F@f1#I# ' +
os.path.join('ast', 'path', 'f1.c.ast')
in fun_ast_lst)
@@ -408,7 +408,7 @@ class FuncMapSrcToAstTest(unittest.TestCase):
def test_spaces_handled(self):
fun_src_lst = ['c:@F@f1#I# ' + os.path.join(os.sep + 'path', 'f 1.c')]
- fun_ast_lst = sut.func_map_list_src_to_ast(fun_src_lst)
+ fun_ast_lst = sut.extdef_map_list_src_to_ast(fun_src_lst)
self.assertTrue('c:@F@f1#I# ' +
os.path.join('ast', 'path', 'f 1.c.ast')
in fun_ast_lst)
diff --git a/tools/scan-build-py/tests/unit/test_clang.py b/tools/scan-build-py/tests/unit/test_clang.py
index 07ac4d9fb806..7d625c6c5bc4 100644
--- a/tools/scan-build-py/tests/unit/test_clang.py
+++ b/tools/scan-build-py/tests/unit/test_clang.py
@@ -96,7 +96,7 @@ class ClangGetCheckersTest(unittest.TestCase):
class ClangIsCtuCapableTest(unittest.TestCase):
def test_ctu_not_found(self):
- is_ctu = sut.is_ctu_capable('not-found-clang-func-mapping')
+ is_ctu = sut.is_ctu_capable('not-found-clang-extdef-mapping')
self.assertFalse(is_ctu)
diff --git a/tools/scan-build/bin/scan-build b/tools/scan-build/bin/scan-build
index c50f900cc45e..fd0dd66b2d6d 100755
--- a/tools/scan-build/bin/scan-build
+++ b/tools/scan-build/bin/scan-build
@@ -58,6 +58,7 @@ my %Options = (
KeepEmpty => 0, # Don't remove output directory even with 0 results.
EnableCheckers => {},
DisableCheckers => {},
+ Excludes => [],
UseCC => undef, # C compiler to use for compilation.
UseCXX => undef, # C++ compiler to use for compilation.
AnalyzerTarget => undef,
@@ -420,6 +421,20 @@ sub ScanFile {
# The file no longer exists: use the original path.
$BugFile = $1;
}
+
+ # Get just the path
+ my $p = dirname($BugFile);
+ # Check if the path is found in the list of exclude
+ if (grep { $p =~ m/$_/ } @{$Options{Excludes}}) {
+ if ($Options{Verbose}) {
+ Diag("File '$BugFile' deleted: part of an ignored directory.\n");
+ }
+
+ # File in an ignored directory. Remove it
+ unlink("$Dir/$FName");
+ return;
+ }
+
UpdatePrefix($BugFile);
}
elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
@@ -1079,7 +1094,7 @@ sub RunBuildCommand {
if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or
$Cmd =~ /(.*\/?cc[^\/]*$)/ or
$Cmd =~ /(.*\/?llvm-gcc[^\/]*$)/ or
- $Cmd =~ /(.*\/?clang$)/ or
+ $Cmd =~ /(.*\/?clang[^\/]*$)/ or
$Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) {
if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) {
@@ -1178,6 +1193,11 @@ OPTIONS:
Display the description of defects in the list
+ -sarif
+
+ By default the output of scan-build is a set of HTML files. This option
+ outputs the results in SARIF format.
+
-plist
By default the output of scan-build is a set of HTML files. This option
@@ -1192,7 +1212,13 @@ OPTIONS:
By default, the exit status of scan-build is the same as the executed build
command. Specifying this option causes the exit status of scan-build to be 1
- if it found potential bugs and 0 otherwise.
+ if it found potential bugs and the exit status of the build itself otherwise.
+
+ --exclude <path>
+
+ Do not run static analyzer against files found in this
+ directory (You can specify this option multiple times).
+ Could be useful when project contains 3rd party libraries.
--use-cc [compiler path]
--use-cc=[compiler path]
@@ -1644,6 +1670,12 @@ sub ProcessArgs {
next;
}
+ if ($arg eq "-sarif") {
+ shift @$Args;
+ $Options{OutputFormat} = "sarif";
+ next;
+ }
+
if ($arg eq "-plist") {
shift @$Args;
$Options{OutputFormat} = "plist";
@@ -1698,6 +1730,15 @@ sub ProcessArgs {
next;
}
+ if ($arg eq "--exclude") {
+ shift @$Args;
+ my $arg = shift @$Args;
+ # Remove the trailing slash if any
+ $arg =~ s|/$||;
+ push @{$Options{Excludes}}, $arg;
+ next;
+ }
+
if ($arg eq "-load-plugin") {
shift @$Args;
push @{$Options{PluginsToLoad}}, shift @$Args;
@@ -1813,13 +1854,13 @@ Diag("Using '$Clang' for static analysis\n");
SetHtmlEnv(\@ARGV, $Options{OutputDir});
my @AnalysesToRun;
-foreach (sort { $Options{EnableCheckers}{$a} <=> $Options{EnableCheckers}{$b} }
- keys %{$Options{EnableCheckers}}) {
+foreach (sort { $Options{EnableCheckers}{$a} <=> $Options{EnableCheckers}{$b} }
+ keys %{$Options{EnableCheckers}}) {
# Push checkers in order they were enabled.
push @AnalysesToRun, "-analyzer-checker", $_;
}
-foreach (sort { $Options{DisableCheckers}{$a} <=> $Options{DisableCheckers}{$b} }
- keys %{$Options{DisableCheckers}}) {
+foreach (sort { $Options{DisableCheckers}{$a} <=> $Options{DisableCheckers}{$b} }
+ keys %{$Options{DisableCheckers}}) {
# Push checkers in order they were disabled.
push @AnalysesToRun, "-analyzer-disable-checker", $_;
}
@@ -1858,9 +1899,12 @@ my $ExitStatus = RunBuildCommand(\@ARGV, $Options{IgnoreErrors}, $Options{KeepCC
$Cmd, $CmdCXX, \%EnvVars);
if (defined $Options{OutputFormat}) {
- if ($Options{OutputFormat} =~ /plist/) {
+ if ($Options{OutputFormat} =~ /plist/ ||
+ $Options{OutputFormat} =~ /sarif/) {
Diag "Analysis run complete.\n";
- Diag "Analysis results (plist files) deposited in '$Options{OutputDir}'\n";
+ Diag "Analysis results (" .
+ ($Options{OutputFormat} =~ /plist/ ? "plist" : "sarif") .
+ " files) deposited in '$Options{OutputDir}'\n";
}
if ($Options{OutputFormat} =~ /html/) {
# Postprocess the HTML directory.
@@ -1878,7 +1922,7 @@ if (defined $Options{OutputFormat}) {
if ($Options{ExitStatusFoundBugs}) {
exit 1 if ($NumBugs > 0);
- exit 0;
+ exit $ExitStatus;
}
}
}
diff --git a/tools/scan-build/libexec/ccc-analyzer b/tools/scan-build/libexec/ccc-analyzer
index 73cd2ff3d915..70afb5bcbbd5 100755
--- a/tools/scan-build/libexec/ccc-analyzer
+++ b/tools/scan-build/libexec/ccc-analyzer
@@ -243,11 +243,6 @@ sub Analyze {
push @Args, "-Xclang", $arg;
}
- # Display Ubiviz graph?
- if (defined $ENV{'CCC_UBI'}) {
- push @Args, "-Xclang", "-analyzer-viz-egraph-ubigraph";
- }
-
if (defined $AnalyzerTarget) {
push @Args, "-target", $AnalyzerTarget;
}
@@ -751,9 +746,10 @@ if ($Action eq 'compile' or $Action eq 'link') {
if (defined $OutputFormat) {
push @AnalyzeArgs, "-analyzer-output=" . $OutputFormat;
- if ($OutputFormat =~ /plist/) {
+ if ($OutputFormat =~ /plist/ || $OutputFormat =~ /sarif/) {
# Change "Output" to be a file.
- my ($h, $f) = tempfile("report-XXXXXX", SUFFIX => ".plist",
+ my $Suffix = $OutputFormat =~ /plist/ ? ".plist" : ".sarif";
+ my ($h, $f) = tempfile("report-XXXXXX", SUFFIX => $Suffix,
DIR => $HtmlDir);
$ResultFile = $f;
# If the HtmlDir is not set, we should clean up the plist files.
diff --git a/tools/scan-view/bin/scan-view b/tools/scan-view/bin/scan-view
index 1b6e8ba90dfa..6165432e7af8 100755
--- a/tools/scan-view/bin/scan-view
+++ b/tools/scan-view/bin/scan-view
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+from __future__ import print_function
+
"""The clang static analyzer results viewer.
"""
@@ -7,9 +9,12 @@ import sys
import imp
import os
import posixpath
-import thread
+import threading
import time
-import urllib
+try:
+ from urllib.request import urlopen
+except ImportError:
+ from urllib2 import urlopen
import webbrowser
# How long to wait for server to start.
@@ -27,7 +32,7 @@ kMaxPortsToTry = 100
def url_is_up(url):
try:
- o = urllib.urlopen(url)
+ o = urlopen(url)
except IOError:
return False
o.close()
@@ -35,7 +40,6 @@ def url_is_up(url):
def start_browser(port, options):
- import urllib
import webbrowser
url = 'http://%s:%d' % (options.host, port)
@@ -52,10 +56,10 @@ def start_browser(port, options):
sys.stderr.flush()
time.sleep(kSleepTimeout)
else:
- print >> sys.stderr, 'WARNING: Unable to detect that server started.'
+ print('WARNING: Unable to detect that server started.', file=sys.stderr)
if options.debug:
- print >> sys.stderr, '%s: Starting webbrowser...' % sys.argv[0]
+ print('%s: Starting webbrowser...' % sys.argv[0], file=sys.stderr)
webbrowser.open(url)
@@ -69,9 +73,9 @@ def run(port, options, root):
import ScanView
try:
- print 'Starting scan-view at: http://%s:%d' % (options.host,
- port)
- print ' Use Ctrl-C to exit.'
+ print('Starting scan-view at: http://%s:%d' % (options.host,
+ port))
+ print(' Use Ctrl-C to exit.')
httpd = ScanView.create_server((options.host, port),
options, root)
httpd.serve_forever()
@@ -80,9 +84,12 @@ def run(port, options, root):
def port_is_open(port):
- import SocketServer
try:
- t = SocketServer.TCPServer((kDefaultHost, port), None)
+ import socketserver
+ except ImportError:
+ import SocketServer as socketserver
+ try:
+ t = socketserver.TCPServer((kDefaultHost, port), None)
except:
return False
t.server_close()
@@ -135,7 +142,7 @@ def main():
# Kick off thread to wait for server and start web browser, if
# requested.
if args.startBrowser:
- t = thread.start_new_thread(start_browser, (port, args))
+ threading.Thread(target=start_browser, args=(port, args)).start()
run(port, args, args.root)
diff --git a/tools/scan-view/share/Reporter.py b/tools/scan-view/share/Reporter.py
index 800af03b1a2c..b1ff16142e27 100644
--- a/tools/scan-view/share/Reporter.py
+++ b/tools/scan-view/share/Reporter.py
@@ -16,7 +16,7 @@ class ReportFailure(Exception):
# Collect information about a bug.
-class BugReport:
+class BugReport(object):
def __init__(self, title, description, files):
self.title = title
self.description = description
@@ -37,7 +37,7 @@ from email.mime.text import MIMEText
# ReporterParameter
#===------------------------------------------------------------------------===#
-class ReporterParameter:
+class ReporterParameter(object):
def __init__(self, n):
self.name = n
def getName(self):
@@ -75,12 +75,12 @@ class SelectionParameter (ReporterParameter):
# Reporters
#===------------------------------------------------------------------------===#
-class EmailReporter:
+class EmailReporter(object):
def getName(self):
return 'Email'
def getParameters(self):
- return map(lambda x:TextParameter(x),['To', 'From', 'SMTP Server', 'SMTP Port'])
+ return [TextParameter(x) for x in ['To', 'From', 'SMTP Server', 'SMTP Port']]
# Lifted from python email module examples.
def attachFile(self, outer, path):
@@ -143,12 +143,12 @@ Description: %s
return "Message sent!"
-class BugzillaReporter:
+class BugzillaReporter(object):
def getName(self):
return 'Bugzilla'
def getParameters(self):
- return map(lambda x:TextParameter(x),['URL','Product'])
+ return [TextParameter(x) for x in ['URL','Product']]
def fileReport(self, report, parameters):
raise NotImplementedError
@@ -174,7 +174,7 @@ class RadarClassificationParameter(SelectionParameter):
else:
return '7'
-class RadarReporter:
+class RadarReporter(object):
@staticmethod
def isAvailable():
# FIXME: Find this .scpt better
@@ -211,7 +211,7 @@ class RadarReporter:
script = os.path.join(os.path.dirname(__file__),'../share/scan-view/FileRadar.scpt')
args = ['osascript', script, component, componentVersion, classification, personID, report.title,
- report.description, diagnosis, config] + map(os.path.abspath, report.files)
+ report.description, diagnosis, config] + [os.path.abspath(f) for f in report.files]
# print >>sys.stderr, args
try:
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
diff --git a/tools/scan-view/share/ScanView.py b/tools/scan-view/share/ScanView.py
index 7dc0351ebe7f..c40366b2e849 100644
--- a/tools/scan-view/share/ScanView.py
+++ b/tools/scan-view/share/ScanView.py
@@ -1,10 +1,24 @@
-import BaseHTTPServer
-import SimpleHTTPServer
+from __future__ import print_function
+try:
+ from http.server import HTTPServer, SimpleHTTPRequestHandler
+except ImportError:
+ from BaseHTTPServer import HTTPServer
+ from SimpleHTTPServer import SimpleHTTPRequestHandler
import os
import sys
-import urllib, urlparse
+try:
+ from urlparse import urlparse
+ from urllib import unquote
+except ImportError:
+ from urllib.parse import urlparse, unquote
+
import posixpath
-import StringIO
+
+if sys.version_info.major >= 3:
+ from io import StringIO, BytesIO
+else:
+ from io import BytesIO, BytesIO as StringIO
+
import re
import shutil
import threading
@@ -13,7 +27,10 @@ import socket
import itertools
import Reporter
-import ConfigParser
+try:
+ import configparser
+except ImportError:
+ import ConfigParser as configparser
###
# Various patterns matched or replaced by server.
@@ -96,25 +113,25 @@ class ReporterThread(threading.Thread):
result = None
try:
if self.server.options.debug:
- print >>sys.stderr, "%s: SERVER: submitting bug."%(sys.argv[0],)
+ print("%s: SERVER: submitting bug."%(sys.argv[0],), file=sys.stderr)
self.status = self.reporter.fileReport(self.report, self.parameters)
self.success = True
time.sleep(3)
if self.server.options.debug:
- print >>sys.stderr, "%s: SERVER: submission complete."%(sys.argv[0],)
- except Reporter.ReportFailure,e:
+ print("%s: SERVER: submission complete."%(sys.argv[0],), file=sys.stderr)
+ except Reporter.ReportFailure as e:
self.status = e.value
- except Exception,e:
- s = StringIO.StringIO()
+ except Exception as e:
+ s = StringIO()
import traceback
- print >>s,'<b>Unhandled Exception</b><br><pre>'
- traceback.print_exc(e,file=s)
- print >>s,'</pre>'
+ print('<b>Unhandled Exception</b><br><pre>', file=s)
+ traceback.print_exc(file=s)
+ print('</pre>', file=s)
self.status = s.getvalue()
-class ScanViewServer(BaseHTTPServer.HTTPServer):
+class ScanViewServer(HTTPServer):
def __init__(self, address, handler, root, reporters, options):
- BaseHTTPServer.HTTPServer.__init__(self, address, handler)
+ HTTPServer.__init__(self, address, handler)
self.root = root
self.reporters = reporters
self.options = options
@@ -123,7 +140,7 @@ class ScanViewServer(BaseHTTPServer.HTTPServer):
self.load_config()
def load_config(self):
- self.config = ConfigParser.RawConfigParser()
+ self.config = configparser.RawConfigParser()
# Add defaults
self.config.add_section('ScanView')
@@ -155,44 +172,44 @@ class ScanViewServer(BaseHTTPServer.HTTPServer):
def halt(self):
self.halted = True
if self.options.debug:
- print >>sys.stderr, "%s: SERVER: halting." % (sys.argv[0],)
+ print("%s: SERVER: halting." % (sys.argv[0],), file=sys.stderr)
def serve_forever(self):
while not self.halted:
if self.options.debug > 1:
- print >>sys.stderr, "%s: SERVER: waiting..." % (sys.argv[0],)
+ print("%s: SERVER: waiting..." % (sys.argv[0],), file=sys.stderr)
try:
self.handle_request()
- except OSError,e:
- print 'OSError',e.errno
+ except OSError as e:
+ print('OSError',e.errno)
def finish_request(self, request, client_address):
if self.options.autoReload:
import ScanView
self.RequestHandlerClass = reload(ScanView).ScanViewRequestHandler
- BaseHTTPServer.HTTPServer.finish_request(self, request, client_address)
+ HTTPServer.finish_request(self, request, client_address)
def handle_error(self, request, client_address):
# Ignore socket errors
info = sys.exc_info()
if info and isinstance(info[1], socket.error):
if self.options.debug > 1:
- print >>sys.stderr, "%s: SERVER: ignored socket error." % (sys.argv[0],)
+ print("%s: SERVER: ignored socket error." % (sys.argv[0],), file=sys.stderr)
return
- BaseHTTPServer.HTTPServer.handle_error(self, request, client_address)
+ HTTPServer.handle_error(self, request, client_address)
# Borrowed from Quixote, with simplifications.
def parse_query(qs, fields=None):
if fields is None:
fields = {}
- for chunk in filter(None, qs.split('&')):
+ for chunk in (_f for _f in qs.split('&') if _f):
if '=' not in chunk:
name = chunk
value = ''
else:
name, value = chunk.split('=', 1)
- name = urllib.unquote(name.replace('+', ' '))
- value = urllib.unquote(value.replace('+', ' '))
+ name = unquote(name.replace('+', ' '))
+ value = unquote(value.replace('+', ' '))
item = fields.get(name)
if item is None:
fields[name] = [value]
@@ -200,20 +217,20 @@ def parse_query(qs, fields=None):
item.append(value)
return fields
-class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+class ScanViewRequestHandler(SimpleHTTPRequestHandler):
server_version = "ScanViewServer/" + __version__
dynamic_mtime = time.time()
def do_HEAD(self):
try:
- SimpleHTTPServer.SimpleHTTPRequestHandler.do_HEAD(self)
- except Exception,e:
+ SimpleHTTPRequestHandler.do_HEAD(self)
+ except Exception as e:
self.handle_exception(e)
def do_GET(self):
try:
- SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
- except Exception,e:
+ SimpleHTTPRequestHandler.do_GET(self)
+ except Exception as e:
self.handle_exception(e)
def do_POST(self):
@@ -230,7 +247,7 @@ class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
if f:
self.copyfile(f, self.wfile)
f.close()
- except Exception,e:
+ except Exception as e:
self.handle_exception(e)
def log_message(self, format, *args):
@@ -263,9 +280,9 @@ class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def handle_exception(self, exc):
import traceback
- s = StringIO.StringIO()
- print >>s, "INTERNAL ERROR\n"
- traceback.print_exc(exc, s)
+ s = StringIO()
+ print("INTERNAL ERROR\n", file=s)
+ traceback.print_exc(file=s)
f = self.send_string(s.getvalue(), 'text/plain')
if f:
self.copyfile(f, self.wfile)
@@ -410,8 +427,8 @@ Submit</h3>
import startfile
if self.server.options.debug:
- print >>sys.stderr, '%s: SERVER: opening "%s"'%(sys.argv[0],
- file)
+ print('%s: SERVER: opening "%s"'%(sys.argv[0],
+ file), file=sys.stderr)
status = startfile.open(file)
if status:
@@ -422,13 +439,13 @@ Submit</h3>
return self.send_string(res, 'text/plain')
def get_report_context(self, report):
- class Context:
+ class Context(object):
pass
if report is None or report == 'None':
data = self.load_crashes()
# Don't allow empty reports.
if not data:
- raise ValueError, 'No crashes detected!'
+ raise ValueError('No crashes detected!')
c = Context()
c.title = 'clang static analyzer failures'
@@ -472,7 +489,7 @@ STDERR Summary
# Check that this is a valid report.
path = posixpath.join(self.server.root, 'report-%s.html' % report)
if not posixpath.exists(path):
- raise ValueError, 'Invalid report ID'
+ raise ValueError('Invalid report ID')
keys = self.load_report(report)
c = Context()
c.title = keys.get('DESC','clang error (unrecognized')
@@ -501,7 +518,7 @@ Line: %s
# report is None is used for crashes
try:
c = self.get_report_context(report)
- except ValueError, e:
+ except ValueError as e:
return self.send_error(400, e.message)
title = c.title
@@ -544,7 +561,7 @@ Line: %s
"""%(r.getName(),display,r.getName(),options))
reporterSelections = '\n'.join(reporterSelections)
reporterOptionsDivs = '\n'.join(reporterOptions)
- reportersArray = '[%s]'%(','.join([`r.getName()` for r in self.server.reporters]))
+ reportersArray = '[%s]'%(','.join([repr(r.getName()) for r in self.server.reporters]))
if c.files:
fieldSize = min(5, len(c.files))
@@ -647,9 +664,9 @@ File Bug</h3>
fields = {}
self.fields = fields
- o = urlparse.urlparse(self.path)
+ o = urlparse(self.path)
self.fields = parse_query(o.query, fields)
- path = posixpath.normpath(urllib.unquote(o.path))
+ path = posixpath.normpath(unquote(o.path))
# Split the components and strip the root prefix.
components = path.split('/')[1:]
@@ -690,8 +707,8 @@ File Bug</h3>
path = posixpath.join(self.server.root, relpath)
if self.server.options.debug > 1:
- print >>sys.stderr, '%s: SERVER: sending path "%s"'%(sys.argv[0],
- path)
+ print('%s: SERVER: sending path "%s"'%(sys.argv[0],
+ path), file=sys.stderr)
return self.send_path(path)
def send_404(self):
@@ -727,15 +744,16 @@ File Bug</h3>
return f
def send_string(self, s, ctype='text/html', headers=True, mtime=None):
+ encoded_s = s.encode()
if headers:
self.send_response(200)
self.send_header("Content-type", ctype)
- self.send_header("Content-Length", str(len(s)))
+ self.send_header("Content-Length", str(len(encoded_s)))
if mtime is None:
mtime = self.dynamic_mtime
self.send_header("Last-Modified", self.date_time_string(mtime))
self.end_headers()
- return StringIO.StringIO(s)
+ return BytesIO(encoded_s)
def send_patched_file(self, path, ctype):
# Allow a very limited set of variables. This is pretty gross.
diff --git a/tools/scan-view/share/startfile.py b/tools/scan-view/share/startfile.py
index f58dbeeaf817..9eb548bc4329 100644
--- a/tools/scan-view/share/startfile.py
+++ b/tools/scan-view/share/startfile.py
@@ -110,7 +110,10 @@ elif sys.platform == 'darwin':
# Platform support for Unix
else:
- import commands
+ try:
+ from commands import getoutput
+ except ImportError:
+ from subprocess import getoutput
# @WARNING: use the private API of the webbrowser module
from webbrowser import _iscommand
@@ -125,7 +128,7 @@ else:
def detect_kde_version(self):
kde_version = None
try:
- info = commands.getoutput('kde-config --version')
+ info = getoutput('kde-config --version')
for line in info.splitlines():
if line.startswith('KDE'):
@@ -158,7 +161,7 @@ else:
desktop_environment = 'gnome'
else:
try:
- info = commands.getoutput('xprop -root _DT_SAVE_MODE')
+ info = getoutput('xprop -root _DT_SAVE_MODE')
if ' = "xfce4"' in info:
desktop_environment = 'xfce'
except (OSError, RuntimeError):
@@ -189,7 +192,7 @@ else:
return _controllers[controller_name].open
except KeyError:
- if _controllers.has_key('xdg-open'):
+ if 'xdg-open' in _controllers:
return _controllers['xdg-open'].open
else:
return webbrowser.open
diff --git a/unittests/AST/ASTContextParentMapTest.cpp b/unittests/AST/ASTContextParentMapTest.cpp
index a39189620b69..fb9d51706985 100644
--- a/unittests/AST/ASTContextParentMapTest.cpp
+++ b/unittests/AST/ASTContextParentMapTest.cpp
@@ -17,6 +17,9 @@
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+using testing::ElementsAre;
namespace clang {
namespace ast_matchers {
@@ -78,5 +81,41 @@ TEST(GetParents, ReturnsMultipleParentsInTemplateInstantiations) {
hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
}
+TEST(GetParents, RespectsTraversalScope) {
+ auto AST =
+ tooling::buildASTFromCode("struct foo { int bar; };", "foo.cpp",
+ std::make_shared<PCHContainerOperations>());
+ auto &Ctx = AST->getASTContext();
+ auto &TU = *Ctx.getTranslationUnitDecl();
+ auto &Foo = *TU.lookup(&Ctx.Idents.get("foo")).front();
+ auto &Bar = *cast<DeclContext>(Foo).lookup(&Ctx.Idents.get("bar")).front();
+
+ using ast_type_traits::DynTypedNode;
+ // Initially, scope is the whole TU.
+ EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo)));
+ EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU)));
+
+ // Restrict the scope, now some parents are gone.
+ Ctx.setTraversalScope({&Foo});
+ EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo)));
+ EXPECT_THAT(Ctx.getParents(Foo), ElementsAre());
+
+ // Reset the scope, we get back the original results.
+ Ctx.setTraversalScope({&TU});
+ EXPECT_THAT(Ctx.getParents(Bar), ElementsAre(DynTypedNode::create(Foo)));
+ EXPECT_THAT(Ctx.getParents(Foo), ElementsAre(DynTypedNode::create(TU)));
+}
+
+TEST(GetParents, ImplicitLambdaNodes) {
+ MatchVerifier<Decl> LambdaVerifier;
+ EXPECT_TRUE(LambdaVerifier.match(
+ "auto x = []{int y;};",
+ varDecl(hasName("y"), hasAncestor(functionDecl(
+ hasOverloadedOperatorName("()"),
+ hasParent(cxxRecordDecl(
+ isImplicit(), hasParent(lambdaExpr())))))),
+ Lang_CXX11));
+}
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index 21b76173c105..c6acf573e582 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -11,9 +11,12 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTImporter.h"
#include "MatchVerifier.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterLookupTable.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
@@ -37,10 +40,10 @@ createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
assert(ToAST);
ASTContext &ToCtx = ToAST->getASTContext();
- auto *OFS = static_cast<vfs::OverlayFileSystem *>(
+ auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
- auto *MFS =
- static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
+ auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
+ OFS->overlays_begin()->get());
MFS->addFile(FileName, 0, std::move(Buffer));
}
@@ -140,6 +143,7 @@ class TestImportBase : public ParameterizedTestsFixture {
if (!Imported)
return testing::AssertionFailure() << "Import failed, nullptr returned!";
+
return Verifier.match(Imported, WrapperMatcher);
}
@@ -306,24 +310,27 @@ class ASTImporterTestBase : public ParameterizedTestsFixture {
Unit->enableSourceFileDiagnostics();
}
- void lazyInitImporter(ASTUnit *ToAST) {
+ void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
assert(ToAST);
if (!Importer) {
- Importer.reset(new ASTImporter(
- ToAST->getASTContext(), ToAST->getFileManager(),
- Unit->getASTContext(), Unit->getFileManager(), false));
+ Importer.reset(
+ new ASTImporter(ToAST->getASTContext(), ToAST->getFileManager(),
+ Unit->getASTContext(), Unit->getFileManager(),
+ false, &LookupTable));
}
assert(&ToAST->getASTContext() == &Importer->getToContext());
createVirtualFileIfNeeded(ToAST, FileName, Code);
}
- Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
- lazyInitImporter(ToAST);
+ Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
+ Decl *FromDecl) {
+ lazyInitImporter(LookupTable, ToAST);
return Importer->Import(FromDecl);
- }
+ }
- QualType import(ASTUnit *ToAST, QualType FromType) {
- lazyInitImporter(ToAST);
+ QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
+ QualType FromType) {
+ lazyInitImporter(LookupTable, ToAST);
return Importer->Import(FromType);
}
};
@@ -337,13 +344,23 @@ class ASTImporterTestBase : public ParameterizedTestsFixture {
// vector is expanding, with the list we won't have these issues.
std::list<TU> FromTUs;
- void lazyInitToAST(Language ToLang) {
+ // Initialize the lookup table if not initialized already.
+ void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
+ assert(ToTU);
+ if (!LookupTablePtr)
+ LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
+ }
+
+ void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
if (ToAST)
return;
ArgVector ToArgs = getArgVectorForLanguage(ToLang);
+ // Source code must be a valid live buffer through the tests lifetime.
+ ToCode = ToSrcCode;
// Build the AST from an empty file.
- ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
+ ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
ToAST->enableSourceFileDiagnostics();
+ lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
}
TU *findFromTU(Decl *From) {
@@ -357,6 +374,10 @@ class ASTImporterTestBase : public ParameterizedTestsFixture {
return &*It;
}
+protected:
+
+ std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
+
public:
// We may have several From context but only one To context.
std::unique_ptr<ASTUnit> ToAST;
@@ -373,26 +394,23 @@ public:
FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
TU &FromTU = FromTUs.back();
- ToCode = ToSrcCode;
assert(!ToAST);
- ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
- ToAST->enableSourceFileDiagnostics();
+ lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
ASTContext &FromCtx = FromTU.Unit->getASTContext();
- createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
-
IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
assert(ImportedII && "Declaration with the given identifier "
"should be specified in test!");
DeclarationName ImportDeclName(ImportedII);
- SmallVector<NamedDecl *, 4> FoundDecls;
+ SmallVector<NamedDecl *, 1> FoundDecls;
FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
FoundDecls);
assert(FoundDecls.size() == 1);
- Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
+ Decl *Imported =
+ FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
assert(Imported);
return std::make_tuple(*FoundDecls.begin(), Imported);
@@ -418,11 +436,8 @@ public:
// Creates the To context with the given source code and returns the TU decl.
TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
ArgVector ToArgs = getArgVectorForLanguage(ToLang);
- ToCode = ToSrcCode;
assert(!ToAST);
- ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
- ToAST->enableSourceFileDiagnostics();
-
+ lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
return ToAST->getASTContext().getTranslationUnitDecl();
}
@@ -430,15 +445,17 @@ public:
// May be called several times in a given test.
// The different instances of the param From may have different ASTContext.
Decl *Import(Decl *From, Language ToLang) {
- lazyInitToAST(ToLang);
+ lazyInitToAST(ToLang, "", OutputFileName);
TU *FromTU = findFromTU(From);
- return FromTU->import(ToAST.get(), From);
+ assert(LookupTablePtr);
+ return FromTU->import(*LookupTablePtr, ToAST.get(), From);
}
QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
- lazyInitToAST(ToLang);
+ lazyInitToAST(ToLang, "", OutputFileName);
TU *FromTU = findFromTU(TUDecl);
- return FromTU->import(ToAST.get(), FromType);
+ assert(LookupTablePtr);
+ return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
}
~ASTImporterTestBase() {
@@ -502,7 +519,6 @@ TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
}
-
TEST_P(ImportExpr, ImportStringLiteral) {
MatchVerifier<Decl> Verifier;
testImport(
@@ -553,6 +569,14 @@ TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
}
+TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "void declToImport() { (void)1.0i; }",
+ Lang_CXX14, "", Lang_CXX14, Verifier,
+ functionDecl(hasDescendant(imaginaryLiteral())));
+}
+
TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
MatchVerifier<Decl> Verifier;
testImport(
@@ -645,7 +669,6 @@ TEST_P(ImportExpr, ImportSwitch) {
TEST_P(ImportExpr, ImportStmtExpr) {
MatchVerifier<Decl> Verifier;
- // NOTE: has() ignores implicit casts, using hasDescendant() to match it
testImport(
"void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
Lang_C, "", Lang_C, Verifier,
@@ -712,19 +735,18 @@ TEST_P(ImportExpr, ImportDesignatedInitExpr) {
initListExpr(
has(designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(equals(1.0))),
- has(integerLiteral(equals(2))))),
+ hasDescendant(floatLiteral(equals(1.0))),
+ hasDescendant(integerLiteral(equals(2))))),
has(designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(equals(2.0))),
- has(integerLiteral(equals(2))))),
+ hasDescendant(floatLiteral(equals(2.0))),
+ hasDescendant(integerLiteral(equals(2))))),
has(designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(equals(1.0))),
- has(integerLiteral(equals(0)))))))));
+ hasDescendant(floatLiteral(equals(1.0))),
+ hasDescendant(integerLiteral(equals(0)))))))));
}
-
TEST_P(ImportExpr, ImportPredefinedExpr) {
MatchVerifier<Decl> Verifier;
// __func__ expands as StringLiteral("declToImport")
@@ -806,9 +828,6 @@ TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
functionTemplateDecl());
}
-const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
- cxxDependentScopeMemberExpr;
-
TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
MatchVerifier<Decl> Verifier;
testImport(
@@ -989,7 +1008,7 @@ TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
" return 0;"
"}",
Lang_C, "input.c");
- auto FromVar =
+ auto *FromVar =
FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
ASSERT_TRUE(FromVar);
auto ToType =
@@ -999,12 +1018,41 @@ TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
// This construct is not supported by ASTImporter.
- Decl *FromTU =
- getTuDecl("int declToImport(struct data_t{int a;int b;} *d){ return 0; }",
- Lang_C, "input.c");
- auto From = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+ Decl *FromTU = getTuDecl(
+ "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
+ Lang_C, "input.c");
+ auto *From = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("declToImport")));
ASSERT_TRUE(From);
- auto To = Import(From, Lang_C);
+ auto *To = Import(From, Lang_C);
+ EXPECT_EQ(To, nullptr);
+}
+
+TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
+ Decl *FromTU = getTuDecl(
+ "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
+ "int declToImport(){ return NONAME_SIZEOF(int); }",
+ Lang_C, "input.c");
+ auto *From = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("declToImport")));
+ ASSERT_TRUE(From);
+ auto *To = Import(From, Lang_C);
+ ASSERT_TRUE(To);
+ EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
+ To, functionDecl(hasName("declToImport"),
+ hasDescendant(unaryExprOrTypeTraitExpr()))));
+}
+
+TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
+ // This construct is not supported by ASTImporter.
+ Decl *FromTU = getTuDecl(
+ "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
+ "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
+ Lang_C, "input.c");
+ auto *From = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("declToImport")));
+ ASSERT_TRUE(From);
+ auto *To = Import(From, Lang_C);
EXPECT_EQ(To, nullptr);
}
@@ -1776,6 +1824,65 @@ TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
}
+TEST_P(ASTImporterTestBase, AnonymousRecords) {
+ auto *Code =
+ R"(
+ struct X {
+ struct { int a; };
+ struct { int b; };
+ };
+ )";
+ Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
+
+ Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
+
+ auto *X0 =
+ FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
+ auto *X1 =
+ FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
+ Import(X0, Lang_C);
+ Import(X1, Lang_C);
+
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ // We expect no (ODR) warning during the import.
+ EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+ EXPECT_EQ(1u,
+ DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
+}
+
+TEST_P(ASTImporterTestBase, AnonymousRecordsReversed) {
+ Decl *FromTU0 = getTuDecl(
+ R"(
+ struct X {
+ struct { int a; };
+ struct { int b; };
+ };
+ )",
+ Lang_C, "input0.c");
+
+ Decl *FromTU1 = getTuDecl(
+ R"(
+ struct X { // reversed order
+ struct { int b; };
+ struct { int a; };
+ };
+ )",
+ Lang_C, "input1.c");
+
+ auto *X0 =
+ FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
+ auto *X1 =
+ FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
+ Import(X0, Lang_C);
+ Import(X1, Lang_C);
+
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ // We expect one (ODR) warning during the import.
+ EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+ EXPECT_EQ(2u,
+ DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
+}
+
TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
auto Pattern = varDecl(hasName("x"));
VarDecl *Imported1;
@@ -1795,13 +1902,62 @@ TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
{
Decl *FromTU =
getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
- auto *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
Import(FromD, Lang_CXX);
}
EXPECT_TRUE(Imported2->isUsed(false));
}
+TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) {
+ auto Pattern = varDecl(hasName("x"));
+ VarDecl *ExistingD;
+ {
+ Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
+ ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
+ }
+ EXPECT_FALSE(ExistingD->isUsed(false));
+ {
+ Decl *FromTU = getTuDecl(
+ "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+ Import(FromD, Lang_CXX);
+ }
+ EXPECT_TRUE(ExistingD->isUsed(false));
+}
+
+TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) {
+ auto Pattern = varDecl(hasName("a"));
+ VarDecl *ExistingD;
+ {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ struct A {
+ static const int a = 1;
+ };
+ )", Lang_CXX);
+ ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
+ }
+ EXPECT_FALSE(ExistingD->isUsed(false));
+ {
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct A {
+ static const int a = 1;
+ };
+ const int *f() { return &A::a; } // requires storage,
+ // thus used flag will be set
+ )", Lang_CXX, "input1.cc");
+ auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
+ ASSERT_TRUE(FromD->isUsed(false));
+ Import(FromFunD, Lang_CXX);
+ }
+ EXPECT_TRUE(ExistingD->isUsed(false));
+}
+
TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
auto Pattern = varDecl(hasName("x"));
@@ -2241,6 +2397,211 @@ TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
}
+TEST_P(ImportFriendFunctions, Lookup) {
+ auto FunctionPattern = functionDecl(hasName("f"));
+ auto ClassPattern = cxxRecordDecl(hasName("X"));
+
+ TranslationUnitDecl *FromTU =
+ getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
+ ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ {
+ auto FromName = FromD->getDeclName();
+ auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
+ auto LookupRes = Class->noload_lookup(FromName);
+ ASSERT_EQ(LookupRes.size(), 0u);
+ LookupRes = FromTU->noload_lookup(FromName);
+ ASSERT_EQ(LookupRes.size(), 1u);
+ }
+
+ auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
+ auto ToName = ToD->getDeclName();
+
+ TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
+ auto LookupRes = Class->noload_lookup(ToName);
+ EXPECT_EQ(LookupRes.size(), 0u);
+ LookupRes = ToTU->noload_lookup(ToName);
+ EXPECT_EQ(LookupRes.size(), 1u);
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
+ auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
+ EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+}
+
+TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
+ auto FunctionPattern = functionDecl(hasName("f"));
+ auto ClassPattern = cxxRecordDecl(hasName("X"));
+
+ TranslationUnitDecl *FromTU = getTuDecl(
+ "struct X { friend void f(); };"
+ // This proto decl makes f available to normal
+ // lookup, otherwise it is hidden.
+ // Normal C++ lookup (implemented in
+ // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
+ // returns the found `NamedDecl` only if the set IDNS is matched
+ "void f();",
+ Lang_CXX, "input0.cc");
+ auto *FromFriend =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
+ auto *FromNormal =
+ LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
+ ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+
+ auto FromName = FromFriend->getDeclName();
+ auto *FromClass =
+ FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
+ auto LookupRes = FromClass->noload_lookup(FromName);
+ ASSERT_EQ(LookupRes.size(), 0u);
+ LookupRes = FromTU->noload_lookup(FromName);
+ ASSERT_EQ(LookupRes.size(), 1u);
+
+ auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
+ auto ToName = ToFriend->getDeclName();
+
+ TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
+ LookupRes = ToClass->noload_lookup(ToName);
+ EXPECT_EQ(LookupRes.size(), 0u);
+ LookupRes = ToTU->noload_lookup(ToName);
+ // Test is disabled because this result is 2.
+ EXPECT_EQ(LookupRes.size(), 1u);
+
+ ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
+ ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
+ auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
+ EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+}
+
+TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
+ auto FunctionPattern = functionDecl(hasName("f"));
+ auto ClassPattern = cxxRecordDecl(hasName("X"));
+
+ TranslationUnitDecl *FromTU = getTuDecl(
+ "void f();"
+ "struct X { friend void f(); };",
+ Lang_CXX, "input0.cc");
+ auto *FromNormal =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
+ auto *FromFriend =
+ LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
+ ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+
+ auto FromName = FromNormal->getDeclName();
+ auto *FromClass =
+ FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
+ auto LookupRes = FromClass->noload_lookup(FromName);
+ ASSERT_EQ(LookupRes.size(), 0u);
+ LookupRes = FromTU->noload_lookup(FromName);
+ ASSERT_EQ(LookupRes.size(), 1u);
+
+ auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
+ auto ToName = ToNormal->getDeclName();
+ TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+
+ auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
+ LookupRes = ToClass->noload_lookup(ToName);
+ EXPECT_EQ(LookupRes.size(), 0u);
+ LookupRes = ToTU->noload_lookup(ToName);
+ EXPECT_EQ(LookupRes.size(), 1u);
+
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
+ ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
+ auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
+ EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+}
+
+TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
+ auto Pattern = functionDecl(hasName("f"));
+
+ TranslationUnitDecl *FromNormalTU =
+ getTuDecl("void f();", Lang_CXX, "input0.cc");
+ auto *FromNormalF =
+ FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
+ TranslationUnitDecl *FromFriendTU =
+ getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
+ auto *FromFriendF =
+ FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
+ auto FromNormalName = FromNormalF->getDeclName();
+ auto FromFriendName = FromFriendF->getDeclName();
+
+ ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
+ ASSERT_EQ(LookupRes.size(), 1u);
+ LookupRes = FromFriendTU->noload_lookup(FromFriendName);
+ ASSERT_EQ(LookupRes.size(), 1u);
+
+ auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
+ TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ auto ToName = ToNormalF->getDeclName();
+ EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+ LookupRes = ToTU->noload_lookup(ToName);
+ EXPECT_EQ(LookupRes.size(), 1u);
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
+
+ auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
+ LookupRes = ToTU->noload_lookup(ToName);
+ EXPECT_EQ(LookupRes.size(), 1u);
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
+
+ EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+
+ EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
+ EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
+}
+
+TEST_P(ImportFriendFunctions, ImportFriendList) {
+ TranslationUnitDecl *FromTU = getTuDecl(
+ "struct X { friend void f(); };"
+ "void f();",
+ Lang_CXX, "input0.cc");
+ auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+
+ auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("X")));
+ auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
+ auto FromFriends = FromClass->friends();
+ unsigned int FrN = 0;
+ for (auto Fr : FromFriends) {
+ ASSERT_EQ(Fr, FromFriend);
+ ++FrN;
+ }
+ ASSERT_EQ(FrN, 1u);
+
+ Import(FromFriendF, Lang_CXX);
+ TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
+ ToTU, cxxRecordDecl(hasName("X")));
+ auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
+ auto ToFriends = ToClass->friends();
+ FrN = 0;
+ for (auto Fr : ToFriends) {
+ EXPECT_EQ(Fr, ToFriend);
+ ++FrN;
+ }
+ EXPECT_EQ(FrN, 1u);
+}
+
AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
InnerMatcher) {
if (auto *Typedef = Node.getTypedefNameForAnonDecl())
@@ -2327,9 +2688,6 @@ TEST_P(ImportExpr, DependentNameType) {
cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
}
-const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
- unresolvedMemberExpr;
-
TEST_P(ImportExpr, UnresolvedMemberExpr) {
MatchVerifier<Decl> Verifier;
testImport("struct S { template <typename T> void mem(); };"
@@ -2384,6 +2742,7 @@ private:
CXXMethodDecl *Method =
FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
ToClass->removeDecl(Method);
+ LookupTablePtr->remove(Method);
}
ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
@@ -2474,7 +2833,7 @@ TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
ToR2 = Import(FromR, Lang_CXX);
}
-
+
EXPECT_EQ(ToR1, ToR2);
}
@@ -2612,6 +2971,1035 @@ TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
R1, recordDecl(has(fieldDecl(hasName("next"))))));
}
+TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ void f(int X, int Y, bool Z) {
+ (void)[X, Y, Z] { (void)Z; };
+ }
+ )",
+ Lang_CXX11, "input0.cc");
+ auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+ auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
+ EXPECT_TRUE(ToF);
+
+ CXXRecordDecl *FromLambda =
+ cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
+ FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
+
+ auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
+ EXPECT_TRUE(ToLambda);
+
+ // Check if the fields of the lambda class are imported in correct order.
+ unsigned FromIndex = 0u;
+ for (auto *FromField : FromLambda->fields()) {
+ ASSERT_FALSE(FromField->getDeclName());
+ auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
+ EXPECT_TRUE(ToField);
+ Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
+ EXPECT_TRUE(ToIndex);
+ EXPECT_EQ(*ToIndex, FromIndex);
+ ++FromIndex;
+ }
+
+ EXPECT_EQ(FromIndex, 3u);
+}
+
+TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
+ std::string ClassTemplate =
+ R"(
+ template <typename T>
+ struct X {
+ int a{0}; // FieldDecl with InitListExpr
+ X(char) : a(3) {} // (1)
+ X(int) {} // (2)
+ };
+ )";
+ Decl *ToTU = getToTuDecl(ClassTemplate +
+ R"(
+ void foo() {
+ // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
+ X<char> xc('c');
+ }
+ )", Lang_CXX11);
+ auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl(hasName("X")));
+ // FieldDecl without InitlistExpr:
+ auto *ToField = *ToSpec->field_begin();
+ ASSERT_TRUE(ToField);
+ ASSERT_FALSE(ToField->getInClassInitializer());
+ Decl *FromTU = getTuDecl(ClassTemplate +
+ R"(
+ void bar() {
+ // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
+ X<char> xc(1);
+ }
+ )", Lang_CXX11);
+ auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl(hasName("X")));
+ // FieldDecl with InitlistExpr:
+ auto *FromField = *FromSpec->field_begin();
+ ASSERT_TRUE(FromField);
+ ASSERT_TRUE(FromField->getInClassInitializer());
+
+ auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
+ ASSERT_TRUE(ImportedSpec);
+ EXPECT_EQ(ImportedSpec, ToSpec);
+ // After the import, the FieldDecl has to be merged, thus it should have the
+ // InitListExpr.
+ EXPECT_TRUE(ToField->getInClassInitializer());
+}
+
+TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
+ std::string ClassTemplate =
+ R"(
+ template <typename T>
+ struct X {
+ void f() {}
+ void g() {}
+ };
+ )";
+ Decl *ToTU = getToTuDecl(ClassTemplate +
+ R"(
+ void foo() {
+ X<char> x;
+ x.f();
+ }
+ )", Lang_CXX11);
+ Decl *FromTU = getTuDecl(ClassTemplate +
+ R"(
+ void bar() {
+ X<char> x;
+ x.g();
+ }
+ )", Lang_CXX11);
+ auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl(hasName("X")));
+ auto FunPattern = functionDecl(hasName("g"),
+ hasParent(classTemplateSpecializationDecl()));
+ auto *FromFun =
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
+ auto *ToFun =
+ FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
+ ASSERT_TRUE(FromFun->hasBody());
+ ASSERT_FALSE(ToFun->hasBody());
+ auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
+ ASSERT_TRUE(ImportedSpec);
+ auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl(hasName("X")));
+ EXPECT_EQ(ImportedSpec, ToSpec);
+ EXPECT_TRUE(ToFun->hasBody());
+}
+
+TEST_P(ASTImporterTestBase,
+ ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
+ std::string ClassTemplate =
+ R"(
+ template <typename T>
+ struct X {};
+ )";
+ Decl *ToTU = getToTuDecl(ClassTemplate +
+ R"(
+ template <>
+ struct X<char> {
+ int a;
+ };
+ void foo() {
+ X<char> x;
+ }
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(ClassTemplate +
+ R"(
+ template <>
+ struct X<char> {
+ int b;
+ };
+ void foo() {
+ X<char> x;
+ }
+ )",
+ Lang_CXX11);
+ auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl(hasName("X")));
+ auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
+
+ // We expect one (ODR) warning during the import.
+ EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+
+ // The second specialization is different from the first, thus it violates
+ // ODR, consequently we expect to keep the first specialization only, which is
+ // already in the "To" context.
+ EXPECT_TRUE(ImportedSpec);
+ auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl(hasName("X")));
+ EXPECT_EQ(ImportedSpec, ToSpec);
+ EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl()));
+}
+
+TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
+ std::string ClassTemplate =
+ R"(
+ template <typename T>
+ struct X {
+ X(char) {}
+ X(int) {}
+ };
+ )";
+ Decl *ToTU = getToTuDecl(ClassTemplate +
+ R"(
+ void foo() {
+ X<char> x('c');
+ }
+ )", Lang_CXX11);
+ Decl *FromTU = getTuDecl(ClassTemplate +
+ R"(
+ void bar() {
+ X<char> x(1);
+ }
+ )", Lang_CXX11);
+ auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl(hasName("X")));
+ // Match the void(int) ctor.
+ auto CtorPattern =
+ cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
+ hasParent(classTemplateSpecializationDecl()));
+ auto *FromCtor =
+ FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
+ auto *ToCtor =
+ FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
+ ASSERT_TRUE(FromCtor->hasBody());
+ ASSERT_FALSE(ToCtor->hasBody());
+ auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
+ ASSERT_TRUE(ImportedSpec);
+ auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl(hasName("X")));
+ EXPECT_EQ(ImportedSpec, ToSpec);
+ EXPECT_TRUE(ToCtor->hasBody());
+}
+
+TEST_P(ASTImporterTestBase,
+ ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
+ auto Code =
+ R"(
+ // primary template
+ template<class T1, class T2, int I>
+ class A {};
+
+ // partial specialization
+ template<class T, int I>
+ class A<T, T*, I> {};
+ )";
+ Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+ Decl *FromTU = getTuDecl(Code, Lang_CXX11);
+ auto *FromSpec =
+ FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
+ FromTU, classTemplatePartialSpecializationDecl());
+ auto *ToSpec =
+ FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
+ ToTU, classTemplatePartialSpecializationDecl());
+
+ auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
+ EXPECT_EQ(ImportedSpec, ToSpec);
+ EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
+ ToTU, classTemplatePartialSpecializationDecl()));
+}
+
+TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
+ auto Code =
+ R"(
+ // primary template
+ template<class T1, class T2, int I>
+ class A {};
+
+ // full specialization
+ template<>
+ class A<int, int, 1> {};
+ )";
+ Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+ Decl *FromTU = getTuDecl(Code, Lang_CXX11);
+ auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl());
+ auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl());
+
+ auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
+ EXPECT_EQ(ImportedSpec, ToSpec);
+ EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl()));
+}
+
+TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
+ std::string PrimaryTemplate =
+ R"(
+ template<class T1, class T2, int I>
+ class A {};
+ )";
+ auto PartialSpec =
+ R"(
+ template<class T, int I>
+ class A<T, T*, I> {};
+ )";
+ auto FullSpec =
+ R"(
+ template<>
+ class A<int, int, 1> {};
+ )";
+ Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
+ Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
+ auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl());
+
+ auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
+ EXPECT_TRUE(ImportedSpec);
+ // Check the number of partial specializations.
+ EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
+ ToTU, classTemplatePartialSpecializationDecl()));
+ // Check the number of full specializations.
+ EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl(
+ unless(classTemplatePartialSpecializationDecl()))));
+}
+
+TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
+ Decl *TU = getTuDecl(
+ R"(
+ const int &init();
+ void foo() { const int &a{init()}; }
+ )", Lang_CXX11, "input0.cc");
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
+ ASSERT_TRUE(FromD->getAnyInitializer());
+ auto *InitExpr = FromD->getAnyInitializer();
+ ASSERT_TRUE(InitExpr);
+ ASSERT_TRUE(InitExpr->isGLValue());
+
+ auto *ToD = Import(FromD, Lang_CXX11);
+ EXPECT_TRUE(ToD);
+ auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
+ EXPECT_TRUE(ToInitExpr);
+ EXPECT_TRUE(ToInitExpr->isGLValue());
+}
+
+struct ImportVariables : ASTImporterTestBase {};
+
+TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct A {
+ static const int a = 1 + 2;
+ };
+ const int A::a;
+ )", Lang_CXX, "input1.cc");
+
+ auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
+ FromTU, varDecl(hasName("a"))); // Decl with init
+ auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
+ FromTU, varDecl(hasName("a"))); // Decl with definition
+ ASSERT_NE(FromDWithInit, FromDWithDef);
+ ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
+
+ auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
+ auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
+ ASSERT_TRUE(ToD0);
+ ASSERT_TRUE(ToD1);
+ EXPECT_NE(ToD0, ToD1);
+ EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
+}
+
+TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
+ auto StructA =
+ R"(
+ struct A {
+ static const int a = 1 + 2;
+ };
+ )";
+ Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
+ Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
+ "input1.cc");
+
+ auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
+ FromTU, varDecl(hasName("a"))); // Decl with init
+ auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
+ FromTU, varDecl(hasName("a"))); // Decl with definition
+ ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
+ ASSERT_TRUE(FromDWithInit->getInit());
+ ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
+ ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
+ ASSERT_FALSE(FromDWithDef->getInit());
+
+ auto *ToD = FirstDeclMatcher<VarDecl>().match(
+ ToTU, varDecl(hasName("a"))); // Decl with init
+ ASSERT_TRUE(ToD->getInit());
+ ASSERT_FALSE(ToD->getDefinition());
+
+ auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
+ EXPECT_TRUE(ImportedD->getAnyInitializer());
+ EXPECT_TRUE(ImportedD->getDefinition());
+}
+
+TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
+ auto StructA =
+ R"(
+ struct A {
+ static const int a;
+ };
+ )";
+ Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
+ Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
+ Lang_CXX, "input1.cc");
+
+ auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
+ FromTU, varDecl(hasName("a")));
+ auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
+ FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
+ ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
+ ASSERT_FALSE(FromDDeclarationOnly->getInit());
+ ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
+ ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
+ ASSERT_TRUE(FromDWithDef->getInit());
+
+ auto *ToD = FirstDeclMatcher<VarDecl>().match(
+ ToTU, varDecl(hasName("a")));
+ ASSERT_FALSE(ToD->getInit());
+ ASSERT_FALSE(ToD->getDefinition());
+
+ auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
+ EXPECT_TRUE(ImportedD->getAnyInitializer());
+ EXPECT_TRUE(ImportedD->getDefinition());
+}
+
+struct ImportClasses : ASTImporterTestBase {};
+
+TEST_P(ImportClasses,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
+ Decl *FromTU = getTuDecl("class X;", Lang_CXX);
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
+ auto ToD = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == ToD);
+ EXPECT_FALSE(ToD->isThisDeclarationADefinition());
+}
+
+TEST_P(ImportClasses, ImportPrototypeAfterImportedPrototype) {
+ Decl *FromTU = getTuDecl("class X; class X;", Lang_CXX);
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
+ auto From1 = LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
+ auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(Imported1 == To1);
+ EXPECT_FALSE(To0->isThisDeclarationADefinition());
+ EXPECT_FALSE(To1->isThisDeclarationADefinition());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportClasses, DefinitionShouldBeImportedAsADefinition) {
+ Decl *FromTU = getTuDecl("class X {};", Lang_CXX);
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
+ EXPECT_TRUE(cast<CXXRecordDecl>(ImportedD)->isThisDeclarationADefinition());
+}
+
+TEST_P(ImportClasses, ImportPrototypeFromDifferentTUAfterImportedPrototype) {
+ Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
+ Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
+ auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
+ auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(Imported1 == To1);
+ EXPECT_FALSE(To0->isThisDeclarationADefinition());
+ EXPECT_FALSE(To1->isThisDeclarationADefinition());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+}
+
+TEST_P(ImportClasses, ImportDefinitions) {
+ Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
+ Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
+ auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(Imported0, Imported1);
+ EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
+ auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(To0->isThisDeclarationADefinition());
+}
+
+TEST_P(ImportClasses, ImportDefinitionThenPrototype) {
+ Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
+ Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
+ auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_NE(ImportedDef, ImportedProto);
+ EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
+ auto ToDef = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ auto ToProto = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
+}
+
+TEST_P(ImportClasses, ImportPrototypeThenDefinition) {
+ Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
+ Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
+ auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_NE(ImportedDef, ImportedProto);
+ EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
+ auto ToProto = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ auto ToDef = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
+}
+
+TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInToContext) {
+ Decl *ToTU = getToTuDecl("struct X;", Lang_C);
+ Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
+ auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
+ auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedDef = Import(FromDef, Lang_C);
+
+ EXPECT_NE(ImportedDef, ToProto);
+ EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
+ auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
+}
+
+TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
+ Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
+ Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
+ auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
+ auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedDef = Import(FromDef, Lang_C);
+
+ EXPECT_NE(ImportedDef, ToProto);
+ EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
+ auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
+}
+
+TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
+ Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
+ Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
+ auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
+ auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+
+ EXPECT_NE(ImportedDef, ToProto);
+ EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
+ auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
+}
+
+TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
+ Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
+ Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
+ auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
+ auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
+ auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedProto = Import(FromProto, Lang_C);
+ Decl *ImportedDef = Import(FromDef, Lang_C);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_NE(ImportedDef, ImportedProto);
+ EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
+ auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
+}
+
+struct ImportClassTemplates : ASTImporterTestBase {};
+
+TEST_P(ImportClassTemplates,
+ PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
+ Decl *FromTU = getTuDecl("template <class T> class X;", Lang_CXX);
+ auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
+ auto FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
+ auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedD == ToD);
+ ASSERT_TRUE(ToD->getTemplatedDecl());
+ EXPECT_FALSE(ToD->isThisDeclarationADefinition());
+}
+
+TEST_P(ImportClassTemplates, ImportPrototypeAfterImportedPrototype) {
+ Decl *FromTU = getTuDecl(
+ "template <class T> class X; template <class T> class X;", Lang_CXX);
+ auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
+ auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
+ auto From1 = LastDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
+ auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(Imported1 == To1);
+ ASSERT_TRUE(To0->getTemplatedDecl());
+ ASSERT_TRUE(To1->getTemplatedDecl());
+ EXPECT_FALSE(To0->isThisDeclarationADefinition());
+ EXPECT_FALSE(To1->isThisDeclarationADefinition());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+ EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
+ To0->getTemplatedDecl());
+}
+
+TEST_P(ImportClassTemplates, DefinitionShouldBeImportedAsADefinition) {
+ Decl *FromTU = getTuDecl("template <class T> class X {};", Lang_CXX);
+ auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
+ auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
+
+ Decl *ImportedD = Import(FromD, Lang_CXX);
+ Decl *ToTU = ImportedD->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
+ auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ ASSERT_TRUE(ToD->getTemplatedDecl());
+ EXPECT_TRUE(ToD->isThisDeclarationADefinition());
+}
+
+TEST_P(ImportClassTemplates,
+ ImportPrototypeFromDifferentTUAfterImportedPrototype) {
+ Decl *FromTU0 =
+ getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
+ Decl *FromTU1 =
+ getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
+ auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
+ auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
+ auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
+ auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(Imported0 == To0);
+ EXPECT_TRUE(Imported1 == To1);
+ ASSERT_TRUE(To0->getTemplatedDecl());
+ ASSERT_TRUE(To1->getTemplatedDecl());
+ EXPECT_FALSE(To0->isThisDeclarationADefinition());
+ EXPECT_FALSE(To1->isThisDeclarationADefinition());
+ EXPECT_EQ(To1->getPreviousDecl(), To0);
+ EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
+ To0->getTemplatedDecl());
+}
+
+TEST_P(ImportClassTemplates, ImportDefinitions) {
+ Decl *FromTU0 =
+ getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
+ Decl *FromTU1 =
+ getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
+ auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
+ auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
+ auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
+
+ Decl *Imported0 = Import(From0, Lang_CXX);
+ Decl *Imported1 = Import(From1, Lang_CXX);
+ Decl *ToTU = Imported0->getTranslationUnitDecl();
+
+ EXPECT_EQ(Imported0, Imported1);
+ EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
+ auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(Imported0 == To0);
+ ASSERT_TRUE(To0->getTemplatedDecl());
+ EXPECT_TRUE(To0->isThisDeclarationADefinition());
+}
+
+TEST_P(ImportClassTemplates, ImportDefinitionThenPrototype) {
+ Decl *FromTU0 =
+ getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
+ Decl *FromTU1 =
+ getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
+ auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
+ auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
+ auto FromProto =
+ FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_NE(ImportedDef, ImportedProto);
+ EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
+ auto ToDef = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ auto ToProto = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ ASSERT_TRUE(ToDef->getTemplatedDecl());
+ ASSERT_TRUE(ToProto->getTemplatedDecl());
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
+ EXPECT_EQ(ToProto->getTemplatedDecl()->getPreviousDecl(),
+ ToDef->getTemplatedDecl());
+}
+
+TEST_P(ImportClassTemplates, ImportPrototypeThenDefinition) {
+ Decl *FromTU0 =
+ getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
+ Decl *FromTU1 =
+ getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
+ auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
+ auto FromProto =
+ FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
+ auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
+
+ Decl *ImportedProto = Import(FromProto, Lang_CXX);
+ Decl *ImportedDef = Import(FromDef, Lang_CXX);
+ Decl *ToTU = ImportedDef->getTranslationUnitDecl();
+
+ EXPECT_NE(ImportedDef, ImportedProto);
+ EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
+ auto ToProto = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ auto ToDef = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
+ EXPECT_TRUE(ImportedDef == ToDef);
+ EXPECT_TRUE(ImportedProto == ToProto);
+ ASSERT_TRUE(ToProto->getTemplatedDecl());
+ ASSERT_TRUE(ToDef->getTemplatedDecl());
+ EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
+ EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
+ EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
+ EXPECT_EQ(ToDef->getTemplatedDecl()->getPreviousDecl(),
+ ToProto->getTemplatedDecl());
+}
+
+struct ImportFriendClasses : ASTImporterTestBase {};
+
+TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ class A {
+ template <int I> class F {};
+ class X {
+ template <int I> friend class F;
+ };
+ };
+ )",
+ Lang_CXX, "input0.cc");
+
+ auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
+ auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("F")));
+
+ ASSERT_TRUE(FromClass);
+ ASSERT_TRUE(FromFriendClass);
+ ASSERT_NE(FromClass, FromFriendClass);
+ ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
+ ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
+ ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
+ FromClass->getDescribedClassTemplate());
+
+ auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
+ auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
+
+ EXPECT_TRUE(ToClass);
+ EXPECT_TRUE(ToFriendClass);
+ EXPECT_NE(ToClass, ToFriendClass);
+ EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
+ EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
+ EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
+ ToClass->getDescribedClassTemplate());
+}
+
+TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
+ Decl *FromTu = getTuDecl(
+ R"(
+ class declToImport {
+ friend class declToImport;
+ };
+ )",
+ Lang_CXX, "input.cc");
+
+ auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTu, cxxRecordDecl(hasName("declToImport")));
+ auto *ToD = Import(FromD, Lang_CXX);
+ auto Pattern = cxxRecordDecl(has(friendDecl()));
+ ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
+ EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
+}
+
+TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
+ Decl *FromTu = getTuDecl(
+ R"(
+ template<class A> class declToImport {
+ template<class A1> friend class declToImport;
+ };
+ )",
+ Lang_CXX, "input.cc");
+
+ auto *FromD =
+ FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
+ auto *ToD = Import(FromD, Lang_CXX);
+
+ auto Pattern = classTemplateDecl(
+ has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
+ ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
+ EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
+
+ auto *Class =
+ FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
+ auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
+ EXPECT_NE(Friend->getFriendDecl(), Class);
+ EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
+}
+
+TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
+ auto Pattern = classTemplateSpecializationDecl(hasName("X"));
+
+ ClassTemplateSpecializationDecl *Imported1;
+ {
+ Decl *FromTU = getTuDecl("template<class T> class X;"
+ "struct Y { friend class X<int>; };",
+ Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, Pattern);
+
+ Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
+ }
+ ClassTemplateSpecializationDecl *Imported2;
+ {
+ Decl *FromTU = getTuDecl("template<class T> class X;"
+ "template<> class X<int>{};"
+ "struct Z { friend class X<int>; };",
+ Lang_CXX, "input1.cc");
+ auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, Pattern);
+
+ Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
+ }
+
+ Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
+ 2u);
+ ASSERT_TRUE(Imported2->getPreviousDecl());
+ EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
+}
+
+TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
+ Decl *FromTU0 = getTuDecl(
+ R"(
+ class X {
+ class Y;
+ };
+ class X::Y {
+ template <typename T>
+ friend class F; // The decl context of F is the global namespace.
+ };
+ )",
+ Lang_CXX, "input0.cc");
+ auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU0, classTemplateDecl(hasName("F")));
+ auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
+ Decl *FromTU1 = getTuDecl(
+ R"(
+ template <typename T>
+ class F {};
+ )",
+ Lang_CXX, "input1.cc");
+ auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU1, classTemplateDecl(hasName("F")));
+ auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
+ EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
+ Imported1->getTemplatedDecl()->getTypeForDecl());
+}
+
+TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
+ Decl *From, *To;
+ std::tie(From, To) =
+ getImportedDecl("class declToImport {};", Lang_CXX,
+ "class Y { friend class declToImport; };", Lang_CXX);
+ auto *Imported = cast<CXXRecordDecl>(To);
+
+ EXPECT_TRUE(Imported->getPreviousDecl());
+}
+
+TEST_P(ImportFriendClasses,
+ ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ class X {
+ class Y;
+ };
+ class X::Y {
+ template <typename T>
+ friend class F; // The decl context of F is the global namespace.
+ };
+ )",
+ Lang_CXX);
+ auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
+ ToTU, classTemplateDecl(hasName("F")));
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ class F {};
+ )",
+ Lang_CXX, "input0.cc");
+ auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU, classTemplateDecl(hasName("F")));
+ auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
+ EXPECT_TRUE(ImportedDef->getPreviousDecl());
+ EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
+ EXPECT_EQ(ToDecl->getTemplatedDecl(),
+ ImportedDef->getTemplatedDecl()->getPreviousDecl());
+}
+
+TEST_P(ImportFriendClasses,
+ ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
+ Decl *FromTU0 = getTuDecl(
+ R"(
+ class X {
+ class Y;
+ };
+ class X::Y {
+ template <typename T>
+ friend class F; // The decl context of F is the global namespace.
+ };
+ )",
+ Lang_CXX, "input0.cc");
+ auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU0, classTemplateDecl(hasName("F")));
+ auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
+ Decl *FromTU1 = getTuDecl(
+ R"(
+ template <typename T>
+ class F {};
+ )",
+ Lang_CXX, "input1.cc");
+ auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU1, classTemplateDecl(hasName("F")));
+ auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
+ EXPECT_TRUE(ImportedDef->getPreviousDecl());
+ EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
+ EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
+ ImportedDef->getTemplatedDecl()->getPreviousDecl());
+}
+
+TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
+ Decl *FromTU0 = getTuDecl(
+ R"(
+ class X {
+ class Y;
+ };
+ class X::Y {
+ friend class F; // The decl context of F is the global namespace.
+ };
+ )",
+ Lang_CXX, "input0.cc");
+ auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
+ QualType FT = Friend->getFriendType()->getType();
+ FT = FromTU0->getASTContext().getCanonicalType(FT);
+ auto *Fwd = cast<TagType>(FT)->getDecl();
+ auto *ImportedFwd = Import(Fwd, Lang_CXX);
+ Decl *FromTU1 = getTuDecl(
+ R"(
+ class F {};
+ )",
+ Lang_CXX, "input1.cc");
+ auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU1, cxxRecordDecl(hasName("F")));
+ auto *ImportedDef = Import(Definition, Lang_CXX);
+ EXPECT_TRUE(ImportedDef->getPreviousDecl());
+ EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
+}
+
+TEST_P(ASTImporterTestBase, FriendFunInClassTemplate) {
+ auto *Code = R"(
+ template <class T>
+ struct X {
+ friend void foo(){}
+ };
+ )";
+ TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
+ auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
+ ToTU, functionDecl(hasName("foo")));
+
+ TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
+ auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+ auto *ImportedFoo = Import(FromFoo, Lang_CXX);
+ EXPECT_EQ(ImportedFoo, ToFoo);
+}
+
struct DeclContextTest : ASTImporterTestBase {};
TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
@@ -2641,6 +4029,40 @@ TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
EXPECT_FALSE(NS->containsDecl(Spec));
}
+TEST_P(DeclContextTest,
+ removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
+ Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
+ auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
+ auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
+
+ // Investigate the list.
+ auto *DC = A0->getDeclContext();
+ ASSERT_TRUE(DC->containsDecl(A0));
+ ASSERT_TRUE(DC->containsDecl(A1));
+
+ // Investigate the lookup table.
+ auto *Map = DC->getLookupPtr();
+ ASSERT_TRUE(Map);
+ auto I = Map->find(A0->getDeclName());
+ ASSERT_NE(I, Map->end());
+ StoredDeclsList &L = I->second;
+ // The lookup table contains the most recent decl of A.
+ ASSERT_NE(L.getAsDecl(), A0);
+ ASSERT_EQ(L.getAsDecl(), A1);
+
+ ASSERT_TRUE(L.getAsDecl());
+ // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
+ // The point here is to have a Vec with only one element, which is not the
+ // one we are going to delete from the DC later.
+ L.setHasExternalDecls();
+ ASSERT_TRUE(L.getAsVector());
+ ASSERT_EQ(1u, L.getAsVector()->size());
+
+ // This asserts in the old implementation.
+ DC->removeDecl(A0);
+ EXPECT_FALSE(DC->containsDecl(A0));
+}
+
struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
TEST_P(ImportFunctionTemplateSpecializations,
@@ -2956,6 +4378,487 @@ TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
EXPECT_EQ(To1->getPreviousDecl(), To0);
}
+TEST_P(ASTImporterTestBase,
+ ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
+ {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ struct B;
+ )",
+ Lang_CXX, "input0.cc");
+ auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU, classTemplateDecl(hasName("B")));
+
+ Import(FromD, Lang_CXX);
+ }
+
+ {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ struct B {
+ void f();
+ B* b;
+ };
+ )",
+ Lang_CXX, "input1.cc");
+ FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+ Import(FromD, Lang_CXX);
+ auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
+ FromTU, classTemplateDecl(hasName("B")));
+ auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
+ EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
+
+ // We expect no (ODR) warning during the import.
+ auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
+ }
+}
+
+TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
+ // We already have an incomplete underlying type in the "To" context.
+ auto Code =
+ R"(
+ template <typename T>
+ struct S {
+ void foo();
+ };
+ using U = S<int>;
+ )";
+ Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+ auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
+ typedefNameDecl(hasName("U")));
+ ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
+
+ // The "From" context has the same typedef, but the underlying type is
+ // complete this time.
+ Decl *FromTU = getTuDecl(std::string(Code) +
+ R"(
+ void foo(U* u) {
+ u->foo();
+ }
+ )", Lang_CXX11);
+ auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
+ typedefNameDecl(hasName("U")));
+ ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
+
+ // The imported type should be complete.
+ auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
+ EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
+}
+
+struct ASTImporterLookupTableTest : ASTImporterTestBase {};
+
+TEST_P(ASTImporterLookupTableTest, OneDecl) {
+ auto *ToTU = getToTuDecl("int a;", Lang_CXX);
+ auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
+ ASTImporterLookupTable LT(*ToTU);
+ auto Res = LT.lookup(ToTU, D->getDeclName());
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), D);
+}
+
+static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
+ for (Decl *D : DC->decls()) {
+ if (auto *ND = dyn_cast<NamedDecl>(D))
+ if (ND->getDeclName() == Name)
+ return ND;
+ }
+ return nullptr;
+}
+
+TEST_P(ASTImporterLookupTableTest,
+ FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
+ auto *Code = R"(
+ template <class T>
+ struct X {
+ friend void foo(){}
+ };
+ )";
+ TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
+ auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
+ ToTU, classTemplateDecl(hasName("X")));
+ auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
+ ToTU, functionDecl(hasName("foo")));
+ DeclContext *FooDC = Foo->getDeclContext();
+ DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
+ ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
+ ASSERT_EQ(cast<Decl>(FooDC), ToTU);
+ DeclarationName FooName = Foo->getDeclName();
+
+ // Cannot find in the LookupTable of its DC (TUDecl)
+ SmallVector<NamedDecl *, 2> FoundDecls;
+ FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 0u);
+
+ // Cannot find in the LookupTable of its LexicalDC (X)
+ FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 0u);
+
+ // Can't find in the list of Decls of the DC.
+ EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
+
+ // Can't find in the list of Decls of the LexicalDC
+ EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
+
+ // ASTImporter specific lookup finds it.
+ ASTImporterLookupTable LT(*ToTU);
+ auto Res = LT.lookup(FooDC, Foo->getDeclName());
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), Foo);
+}
+
+TEST_P(ASTImporterLookupTableTest,
+ FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
+ TranslationUnitDecl *ToTU =
+ getToTuDecl("struct A { struct Foo *p; };", Lang_C);
+ auto *Foo =
+ FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
+ auto *A =
+ FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
+ DeclContext *FooDC = Foo->getDeclContext();
+ DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
+ ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
+ ASSERT_EQ(cast<Decl>(FooDC), ToTU);
+ DeclarationName FooName = Foo->getDeclName();
+
+ // Cannot find in the LookupTable of its DC (TUDecl).
+ SmallVector<NamedDecl *, 2> FoundDecls;
+ FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 0u);
+
+ // Cannot find in the LookupTable of its LexicalDC (A).
+ FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 0u);
+
+ // Can't find in the list of Decls of the DC.
+ EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
+
+ // Can find in the list of Decls of the LexicalDC.
+ EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
+
+ // ASTImporter specific lookup finds it.
+ ASTImporterLookupTable LT(*ToTU);
+ auto Res = LT.lookup(FooDC, Foo->getDeclName());
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), Foo);
+}
+
+TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
+ TranslationUnitDecl *ToTU =
+ getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
+ DeclarationName VName = FirstDeclMatcher<VarDecl>()
+ .match(ToTU, varDecl(hasName("V")))
+ ->getDeclName();
+ auto *A =
+ FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
+ auto *B =
+ FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
+
+ ASTImporterLookupTable LT(*ToTU);
+
+ auto Res = LT.lookup(cast<DeclContext>(A), VName);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
+ ToTU, fieldDecl(hasName("V"),
+ hasParent(recordDecl(hasName("A"))))));
+ Res = LT.lookup(cast<DeclContext>(B), VName);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
+ ToTU, fieldDecl(hasName("V"),
+ hasParent(recordDecl(hasName("B"))))));
+ Res = LT.lookup(ToTU, VName);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
+ ToTU, varDecl(hasName("V"),
+ hasParent(translationUnitDecl()))));
+}
+
+TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ void foo();
+ void foo(int);
+ void foo(int, int);
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
+ auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
+ DeclarationName Name = F0->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 3u);
+ EXPECT_EQ(Res.count(F0), 1u);
+ EXPECT_EQ(Res.count(F2), 1u);
+}
+
+static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
+ QualType Ty = FD->getFriendType()->getType();
+ QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
+ return cast<RecordType>(NamedTy)->getDecl();
+}
+
+TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ class Y { friend class F; };
+ )",
+ Lang_CXX);
+
+ // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
+ // So we must dig up the underlying CXXRecordDecl.
+ ASTImporterLookupTable LT(*ToTU);
+ auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
+ const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
+ auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
+ ToTU, cxxRecordDecl(hasName("Y")));
+
+ DeclarationName Name = RD->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), RD);
+
+ Res = LT.lookup(Y, Name);
+ EXPECT_EQ(Res.size(), 0u);
+}
+
+TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ class Y { template <class T> friend class F; };
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
+ ToTU, classTemplateDecl(hasName("F")));
+ DeclarationName Name = F->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 2u);
+ EXPECT_EQ(Res.count(F), 1u);
+ EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
+}
+
+TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ template <typename T>
+ class F;
+
+ template <typename T>
+ class Y {
+ friend class F<T>;
+ };
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
+ ToTU, classTemplateDecl(hasName("F")));
+ DeclarationName Name = F->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 2u);
+ EXPECT_EQ(Res.count(F), 1u);
+ EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
+}
+
+TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ template <typename T>
+ class F;
+
+ class Y {
+ friend class F<int>;
+ };
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
+ ToTU, classTemplateDecl(hasName("F")));
+ DeclarationName Name = F->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ ASSERT_EQ(Res.size(), 3u);
+ EXPECT_EQ(Res.count(F), 1u);
+ EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
+ EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
+}
+
+TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ class Y { friend void F(); };
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *F =
+ FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
+ DeclarationName Name = F->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), F);
+}
+
+TEST_P(ASTImporterLookupTableTest,
+ LookupFindsDeclsInClassTemplateSpecialization) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ template <typename T>
+ struct X {
+ int F;
+ };
+ void foo() {
+ X<char> xc;
+ }
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+
+ auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
+ ToTU, classTemplateDecl(hasName("X")));
+ auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
+ ToTU,
+ fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
+
+ auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl(hasName("X")));
+ FieldDecl *FieldInSpec = *Spec->field_begin();
+ ASSERT_TRUE(FieldInSpec);
+
+ DeclarationName Name = FieldInSpec->getDeclName();
+ auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
+
+ SmallVector<NamedDecl *, 2> FoundDecls;
+ TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 1u);
+ EXPECT_EQ(FoundDecls[0], FieldInTemplate);
+
+ auto Res = LT.lookup(TemplateDC, Name);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), FieldInTemplate);
+
+ cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
+ FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 1u);
+ EXPECT_EQ(FoundDecls[0], FieldInSpec);
+
+ Res = LT.lookup(cast<DeclContext>(Spec), Name);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), FieldInSpec);
+}
+
+TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ class Y { template <class T> friend void F(); };
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
+ ToTU, functionTemplateDecl(hasName("F")));
+ DeclarationName Name = F->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 2u);
+ EXPECT_EQ(Res.count(F), 1u);
+ EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
+}
+
+TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ struct X;
+ struct A {
+ friend struct X;
+ };
+ struct B {
+ friend struct X;
+ };
+ )",
+ Lang_CXX);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
+ ToTU, cxxRecordDecl(hasName("X")));
+ auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
+ auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
+ const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
+ const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
+ ASSERT_EQ(RD0, RD1);
+ ASSERT_EQ(RD1, X);
+
+ DeclarationName Name = X->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), X);
+}
+
+TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ enum E {
+ A,
+ B
+ };
+ )",
+ Lang_C);
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
+ auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
+ ToTU, enumConstantDecl(hasName("A")));
+
+ DeclarationName Name = A->getDeclName();
+ // Redecl context is the TU.
+ ASSERT_EQ(E->getRedeclContext(), ToTU);
+
+ SmallVector<NamedDecl *, 2> FoundDecls;
+ // Normal lookup finds in the DC.
+ E->localUncachedLookup(Name, FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 1u);
+
+ // Normal lookup finds in the Redecl context.
+ ToTU->localUncachedLookup(Name, FoundDecls);
+ EXPECT_EQ(FoundDecls.size(), 1u);
+
+ // Import specific lookup finds in the DC.
+ auto Res = LT.lookup(E, Name);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), A);
+
+ // Import specific lookup finds in the Redecl context.
+ Res = LT.lookup(ToTU, Name);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), A);
+}
+
+TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ namespace N {
+ int A;
+ }
+ namespace N {
+ }
+ )",
+ Lang_CXX);
+ auto *N1 =
+ LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
+ auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
+ DeclarationName Name = A->getDeclName();
+
+ ASTImporterLookupTable LT(*ToTU);
+ auto Res = LT.lookup(N1, Name);
+ ASSERT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), A);
+}
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
::testing::Values(ArgVector()), );
@@ -2969,6 +4872,9 @@ auto DefaultTestValuesForRunOptions = ::testing::Values(
ArgVector{"-fms-compatibility"},
ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
+ DefaultTestValuesForRunOptions, );
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
DefaultTestValuesForRunOptions, );
@@ -2984,12 +4890,27 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
+ DefaultTestValuesForRunOptions, );
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
+ DefaultTestValuesForRunOptions, );
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests,
ImportFunctionTemplateSpecializations,
DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
+ DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
+ DefaultTestValuesForRunOptions, );
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt
index 776e3dcf6df0..c416e5b996b4 100644
--- a/unittests/AST/CMakeLists.txt
+++ b/unittests/AST/CMakeLists.txt
@@ -2,6 +2,10 @@ set(LLVM_LINK_COMPONENTS
Support
)
+if (MSVC)
+ set_source_files_properties(ASTImporterTest.cpp PROPERTIES COMPILE_FLAGS /bigobj)
+endif()
+
add_clang_unittest(ASTTests
ASTContextParentMapTest.cpp
ASTImporterTest.cpp
@@ -28,5 +32,6 @@ target_link_libraries(ASTTests
clangASTMatchers
clangBasic
clangFrontend
+ clangSerialization
clangTooling
)
diff --git a/unittests/AST/CommentTextTest.cpp b/unittests/AST/CommentTextTest.cpp
index 04475f1c1061..5fb779535f5d 100644
--- a/unittests/AST/CommentTextTest.cpp
+++ b/unittests/AST/CommentTextTest.cpp
@@ -20,8 +20,8 @@
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <gtest/gtest.h>
namespace clang {
diff --git a/unittests/AST/StmtPrinterTest.cpp b/unittests/AST/StmtPrinterTest.cpp
index a0644401a76a..40da6ca6bb33 100644
--- a/unittests/AST/StmtPrinterTest.cpp
+++ b/unittests/AST/StmtPrinterTest.cpp
@@ -106,64 +106,59 @@ PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
return ::testing::AssertionSuccess();
}
-::testing::AssertionResult
-PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
- StringRef ExpectedPrinted) {
- std::vector<std::string> Args;
- Args.push_back("-std=c++98");
- Args.push_back("-Wno-unused-value");
- return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
-}
+enum class StdVer { CXX98, CXX11, CXX14, CXX17, CXX2a };
-::testing::AssertionResult PrintedStmtCXX98Matches(
- StringRef Code,
- StringRef ContainingFunction,
- StringRef ExpectedPrinted) {
- std::vector<std::string> Args;
- Args.push_back("-std=c++98");
- Args.push_back("-Wno-unused-value");
- return PrintedStmtMatches(Code,
- Args,
- functionDecl(hasName(ContainingFunction),
- has(compoundStmt(has(stmt().bind("id"))))),
- ExpectedPrinted);
+DeclarationMatcher FunctionBodyMatcher(StringRef ContainingFunction) {
+ return functionDecl(hasName(ContainingFunction),
+ has(compoundStmt(has(stmt().bind("id")))));
}
+template <typename T>
::testing::AssertionResult
-PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch,
- StringRef ExpectedPrinted,
- PolicyAdjusterType PolicyAdjuster = None) {
- std::vector<std::string> Args;
- Args.push_back("-std=c++11");
- Args.push_back("-Wno-unused-value");
+PrintedStmtCXXMatches(StdVer Standard, StringRef Code, const T &NodeMatch,
+ StringRef ExpectedPrinted,
+ PolicyAdjusterType PolicyAdjuster = None) {
+ const char *StdOpt;
+ switch (Standard) {
+ case StdVer::CXX98: StdOpt = "-std=c++98"; break;
+ case StdVer::CXX11: StdOpt = "-std=c++11"; break;
+ case StdVer::CXX14: StdOpt = "-std=c++14"; break;
+ case StdVer::CXX17: StdOpt = "-std=c++17"; break;
+ case StdVer::CXX2a: StdOpt = "-std=c++2a"; break;
+ }
+
+ std::vector<std::string> Args = {
+ StdOpt,
+ "-Wno-unused-value",
+ };
return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
PolicyAdjuster);
}
-::testing::AssertionResult PrintedStmtMSMatches(
- StringRef Code,
- StringRef ContainingFunction,
- StringRef ExpectedPrinted) {
- std::vector<std::string> Args;
- Args.push_back("-target");
- Args.push_back("i686-pc-win32");
- Args.push_back("-std=c++98");
- Args.push_back("-fms-extensions");
- Args.push_back("-Wno-unused-value");
- return PrintedStmtMatches(Code,
- Args,
- functionDecl(hasName(ContainingFunction),
- has(compoundStmt(has(stmt().bind("id"))))),
- ExpectedPrinted);
+template <typename T>
+::testing::AssertionResult
+PrintedStmtMSMatches(StringRef Code, const T &NodeMatch,
+ StringRef ExpectedPrinted,
+ PolicyAdjusterType PolicyAdjuster = None) {
+ std::vector<std::string> Args = {
+ "-std=c++98",
+ "-target", "i686-pc-win32",
+ "-fms-extensions",
+ "-Wno-unused-value",
+ };
+ return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
+ PolicyAdjuster);
}
+template <typename T>
::testing::AssertionResult
-PrintedStmtObjCMatches(StringRef Code, const StatementMatcher &NodeMatch,
+PrintedStmtObjCMatches(StringRef Code, const T &NodeMatch,
StringRef ExpectedPrinted,
PolicyAdjusterType PolicyAdjuster = None) {
- std::vector<std::string> Args;
- Args.push_back("-ObjC");
- Args.push_back("-fobjc-runtime=macosx-10.12.0");
+ std::vector<std::string> Args = {
+ "-ObjC",
+ "-fobjc-runtime=macosx-10.12.0",
+ };
return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
PolicyAdjuster);
}
@@ -171,13 +166,13 @@ PrintedStmtObjCMatches(StringRef Code, const StatementMatcher &NodeMatch,
} // unnamed namespace
TEST(StmtPrinter, TestIntegerLiteral) {
- ASSERT_TRUE(PrintedStmtCXX98Matches(
+ ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX98,
"void A() {"
" 1, -1, 1U, 1u,"
" 1L, 1l, -1L, 1UL, 1ul,"
" 1LL, -1LL, 1ULL;"
"}",
- "A",
+ FunctionBodyMatcher("A"),
"1 , -1 , 1U , 1U , "
"1L , 1L , -1L , 1UL , 1UL , "
"1LL , -1LL , 1ULL"));
@@ -192,7 +187,7 @@ TEST(StmtPrinter, TestMSIntegerLiteral) {
" 1i32, -1i32, 1ui32, "
" 1i64, -1i64, 1ui64;"
"}",
- "A",
+ FunctionBodyMatcher("A"),
"1i8 , -1i8 , 1Ui8 , "
"1i16 , -1i16 , 1Ui16 , "
"1 , -1 , 1U , "
@@ -201,15 +196,15 @@ TEST(StmtPrinter, TestMSIntegerLiteral) {
}
TEST(StmtPrinter, TestFloatingPointLiteral) {
- ASSERT_TRUE(PrintedStmtCXX98Matches(
+ ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX98,
"void A() { 1.0f, -1.0f, 1.0, -1.0, 1.0l, -1.0l; }",
- "A",
+ FunctionBodyMatcher("A"),
"1.F , -1.F , 1. , -1. , 1.L , -1.L"));
// Should be: with semicolon
}
TEST(StmtPrinter, TestCXXConversionDeclImplicit) {
- ASSERT_TRUE(PrintedStmtCXX98Matches(
+ ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX98,
"struct A {"
"operator void *();"
"A operator&(A);"
@@ -223,7 +218,7 @@ TEST(StmtPrinter, TestCXXConversionDeclImplicit) {
}
TEST(StmtPrinter, TestCXXConversionDeclExplicit) {
- ASSERT_TRUE(PrintedStmtCXX11Matches(
+ ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11,
"struct A {"
"operator void *();"
"A operator&(A);"
@@ -245,12 +240,12 @@ class A {
};
)";
// No implicit 'this'.
- ASSERT_TRUE(PrintedStmtCXX11Matches(
+ ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11,
CPPSource, memberExpr(anything()).bind("id"), "field",
PolicyAdjusterType(
[](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; })));
// Print implicit 'this'.
- ASSERT_TRUE(PrintedStmtCXX11Matches(
+ ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11,
CPPSource, memberExpr(anything()).bind("id"), "this->field"));
const char *ObjCSource = R"(
diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp
index d5b529c6b674..cd1f01d4bfc6 100644
--- a/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/unittests/AST/StructuralEquivalenceTest.cpp
@@ -78,11 +78,18 @@ struct StructuralEquivalenceTest : ::testing::Test {
}
bool testStructuralMatch(Decl *D0, Decl *D1) {
- llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
- StructuralEquivalenceContext Ctx(
- D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls,
- StructuralEquivalenceKind::Default, false, false);
- return Ctx.IsEquivalent(D0, D1);
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;
+ StructuralEquivalenceContext Ctx01(
+ D0->getASTContext(), D1->getASTContext(),
+ NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false);
+ StructuralEquivalenceContext Ctx10(
+ D1->getASTContext(), D0->getASTContext(),
+ NonEquivalentDecls10, StructuralEquivalenceKind::Default, false, false);
+ bool Eq01 = Ctx01.IsEquivalent(D0, D1);
+ bool Eq10 = Ctx10.IsEquivalent(D1, D0);
+ EXPECT_EQ(Eq01, Eq10);
+ return Eq01;
}
bool testStructuralMatch(std::tuple<Decl *, Decl *> t) {
@@ -215,6 +222,14 @@ TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {
};
+TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) {
+ auto t = makeNamedDecls(
+ "void foo();",
+ "template<class T> void foo();",
+ Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {
auto t = makeNamedDecls("void foo(int&);",
"void foo(const int&);", Lang_CXX);
@@ -582,6 +597,77 @@ TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
EXPECT_FALSE(testStructuralMatch(R0, R1));
}
+TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {
+ auto t = makeTuDecls(
+ R"(
+ struct X {
+ struct {
+ int a;
+ };
+ struct {
+ int b;
+ };
+ };
+ )",
+ "", Lang_C);
+ auto *TU = get<0>(t);
+ auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
+ TU, indirectFieldDecl(hasName("a")));
+ auto *FA = cast<FieldDecl>(A->chain().front());
+ RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
+ auto *B = FirstDeclMatcher<IndirectFieldDecl>().match(
+ TU, indirectFieldDecl(hasName("b")));
+ auto *FB = cast<FieldDecl>(B->chain().front());
+ RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl();
+
+ ASSERT_NE(RA, RB);
+ EXPECT_TRUE(testStructuralMatch(RA, RA));
+ EXPECT_TRUE(testStructuralMatch(RB, RB));
+ EXPECT_FALSE(testStructuralMatch(RA, RB));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+ RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {
+ auto t = makeTuDecls(
+ R"(
+ struct X {
+ struct { int a; };
+ struct { int b; };
+ };
+ )",
+ R"(
+ struct X { // The order is reversed.
+ struct { int b; };
+ struct { int a; };
+ };
+ )",
+ Lang_C);
+
+ auto *TU = get<0>(t);
+ auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(
+ TU, indirectFieldDecl(hasName("a")));
+ auto *FA = cast<FieldDecl>(A->chain().front());
+ RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();
+
+ auto *TU1 = get<1>(t);
+ auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match(
+ TU1, indirectFieldDecl(hasName("a")));
+ auto *FA1 = cast<FieldDecl>(A1->chain().front());
+ RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl();
+
+ RecordDecl *X =
+ FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X")));
+ RecordDecl *X1 =
+ FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X")));
+ ASSERT_NE(X, X1);
+ EXPECT_FALSE(testStructuralMatch(X, X1));
+
+ ASSERT_NE(RA, RA1);
+ EXPECT_TRUE(testStructuralMatch(RA, RA));
+ EXPECT_TRUE(testStructuralMatch(RA1, RA1));
+ EXPECT_FALSE(testStructuralMatch(RA1, RA));
+}
+
TEST_F(StructuralEquivalenceRecordTest,
UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
auto Code =
@@ -618,6 +704,40 @@ TEST_F(StructuralEquivalenceRecordTest,
EXPECT_FALSE(testStructuralMatch(R0, R1));
}
+TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {
+ auto t = makeDecls<CXXRecordDecl>(
+ "struct A { };",
+ "template<class T> struct A { };",
+ Lang_CXX,
+ cxxRecordDecl(hasName("A")));
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+ FwdDeclRecordShouldBeEqualWithFwdDeclRecord) {
+ auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+ FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) {
+ auto t =
+ makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+ RecordShouldBeEqualWithRecordWhichHasDefinition) {
+ auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };",
+ Lang_CXX11);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {
+ auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };",
+ Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
auto t = makeNamedDecls(
@@ -627,5 +747,33 @@ TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
EXPECT_FALSE(testStructuralMatch(t));
}
+struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};
+
+TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {
+ auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumTest,
+ FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {
+ auto t =
+ makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumTest,
+ EnumShouldBeEqualWithEnumWhichHasDefinition) {
+ auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };",
+ Lang_CXX11);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {
+ auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };",
+ Lang_CXX11);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 1e7b10e99e71..fb17d100c518 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -667,6 +667,14 @@ TEST(Matcher, VarDecl_Storage) {
EXPECT_TRUE(matches("void f() { static int X; }", M));
}
+TEST(Matcher, VarDecl_IsStaticLocal) {
+ auto M = varDecl(isStaticLocal());
+ EXPECT_TRUE(matches("void f() { static int X; }", M));
+ EXPECT_TRUE(notMatches("static int X;", M));
+ EXPECT_TRUE(notMatches("void f() { int X; }", M));
+ EXPECT_TRUE(notMatches("int X;", M));
+}
+
TEST(Matcher, VarDecl_StorageDuration) {
std::string T =
"void f() { int x; static int y; } int a;static int b;extern int c;";
@@ -765,6 +773,11 @@ TEST(IsArrow, MatchesMemberVariablesViaArrow) {
memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };",
memberExpr(isArrow())));
+ EXPECT_TRUE(matches("template <class T> class Y { void x() { this->m; } };",
+ cxxDependentScopeMemberExpr(isArrow())));
+ EXPECT_TRUE(
+ notMatches("template <class T> class Y { void x() { (*this).m; } };",
+ cxxDependentScopeMemberExpr(isArrow())));
}
TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) {
@@ -783,6 +796,14 @@ TEST(IsArrow, MatchesMemberCallsViaArrow) {
memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };",
memberExpr(isArrow())));
+ EXPECT_TRUE(
+ matches("class Y { template <class T> void x() { this->x<T>(); } };",
+ unresolvedMemberExpr(isArrow())));
+ EXPECT_TRUE(matches("class Y { template <class T> void x() { x<T>(); } };",
+ unresolvedMemberExpr(isArrow())));
+ EXPECT_TRUE(
+ notMatches("class Y { template <class T> void x() { (*this).x<T>(); } };",
+ unresolvedMemberExpr(isArrow())));
}
TEST(ConversionDeclaration, IsExplicit) {
@@ -1365,6 +1386,10 @@ TEST(ObjCIvarRefExprMatcher, IvarExpr) {
hasDeclaration(namedDecl(hasName("y"))))));
}
+TEST(BlockExprMatcher, BlockExpr) {
+ EXPECT_TRUE(matchesObjC("void f() { ^{}(); }", blockExpr()));
+}
+
TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
EXPECT_TRUE(matches("void f() { }",
compoundStmt(statementCountIs(0))));
@@ -1517,6 +1542,26 @@ TEST(HasObjectExpression, MatchesBaseOfVariable) {
"struct X { int m; }; void f(X* x) { x->m; }",
memberExpr(hasObjectExpression(
hasType(pointsTo(recordDecl(hasName("X"))))))));
+ EXPECT_TRUE(matches("template <class T> struct X { void f() { T t; t.m; } };",
+ cxxDependentScopeMemberExpr(hasObjectExpression(
+ declRefExpr(to(namedDecl(hasName("t"))))))));
+ EXPECT_TRUE(
+ matches("template <class T> struct X { void f() { T t; t->m; } };",
+ cxxDependentScopeMemberExpr(hasObjectExpression(
+ declRefExpr(to(namedDecl(hasName("t"))))))));
+}
+
+TEST(HasObjectExpression, MatchesBaseOfMemberFunc) {
+ EXPECT_TRUE(matches(
+ "struct X { void f(); }; void g(X x) { x.f(); }",
+ memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches("struct X { template <class T> void f(); };"
+ "template <class T> void g(X x) { x.f<T>(); }",
+ unresolvedMemberExpr(hasObjectExpression(
+ hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches("template <class T> void f(T t) { t.g(); }",
+ cxxDependentScopeMemberExpr(hasObjectExpression(
+ declRefExpr(to(namedDecl(hasName("t"))))))));
}
TEST(HasObjectExpression,
@@ -1748,6 +1793,48 @@ TEST(IsInTemplateInstantiation, Sharing) {
Matcher));
}
+TEST(IsInstantiationDependent, MatchesNonValueTypeDependent) {
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsInstantiationDependent, MatchesValueDependent) {
+ EXPECT_TRUE(matches("template<int T> int f() { return T; }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsInstantiationDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsTypeDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isTypeDependent())));
+}
+
+TEST(IsTypeDependent, NotMatchesValueDependent) {
+ EXPECT_TRUE(notMatches("template<int T> int f() { return T; }",
+ expr(isTypeDependent())));
+}
+
+TEST(IsValueDependent, MatchesValueDependent) {
+ EXPECT_TRUE(matches("template<int T> int f() { return T; }",
+ expr(isValueDependent())));
+}
+
+TEST(IsValueDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isValueDependent())));
+}
+
+TEST(IsValueDependent, MatchesInstantiationDependent) {
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
+ expr(isValueDependent())));
+}
+
TEST(IsExplicitTemplateSpecialization,
DoesNotMatchPrimaryTemplate) {
EXPECT_TRUE(notMatches(
@@ -2168,6 +2255,18 @@ TEST(IsAssignmentOperator, Basic) {
notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
}
+TEST(HasInit, Basic) {
+ EXPECT_TRUE(
+ matches("int x{0};",
+ initListExpr(hasInit(0, expr()))));
+ EXPECT_FALSE(
+ matches("int x{0};",
+ initListExpr(hasInit(1, expr()))));
+ EXPECT_FALSE(
+ matches("int x;",
+ initListExpr(hasInit(0, expr()))));
+}
+
TEST(Matcher, isMain) {
EXPECT_TRUE(
matches("int main() {}", functionDecl(isMain())));
diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index e521940983b2..1bd4e09e7761 100644
--- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -27,7 +27,7 @@ TEST(Finder, DynamicOnlyAcceptsSomeMatchers) {
nullptr));
// Do not accept non-toplevel matchers.
- EXPECT_FALSE(Finder.addDynamicMatcher(isArrow(), nullptr));
+ EXPECT_FALSE(Finder.addDynamicMatcher(isMain(), nullptr));
EXPECT_FALSE(Finder.addDynamicMatcher(hasName("x"), nullptr));
}
@@ -199,6 +199,40 @@ TEST(Matcher, UnresolvedLookupExpr) {
"-fno-delayed-template-parsing"));
}
+TEST(Matcher, ADLCall) {
+ StatementMatcher ADLMatch = callExpr(usesADL());
+ StatementMatcher ADLMatchOper = cxxOperatorCallExpr(usesADL());
+ auto NS_Str = R"cpp(
+ namespace NS {
+ struct X {};
+ void f(X);
+ void operator+(X, X);
+ }
+ struct MyX {};
+ void f(...);
+ void operator+(MyX, MyX);
+)cpp";
+
+ auto MkStr = [&](std::string Body) -> std::string {
+ std::string S = NS_Str;
+ S += "void test_fn() { " + Body + " }";
+ return S;
+ };
+
+ EXPECT_TRUE(matches(MkStr("NS::X x; f(x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::f(x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("MyX x; f(x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("NS::X x; using NS::f; f(x);"), ADLMatch));
+
+ // Operator call expressions
+ EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatch));
+ EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatchOper));
+ EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatchOper));
+ EXPECT_TRUE(matches(MkStr("NS::X x; operator+(x, x);"), ADLMatch));
+ EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::operator+(x, x);"), ADLMatch));
+}
+
TEST(Matcher, Call) {
// FIXME: Do we want to overload Call() to directly take
// Matcher<Decl>, too?
@@ -422,10 +456,17 @@ TEST(UnaryExprOrTypeTraitExpr, MatchesSizeOfAndAlignOf) {
TEST(MemberExpression, DoesNotMatchClasses) {
EXPECT_TRUE(notMatches("class Y { void x() {} };", memberExpr()));
+ EXPECT_TRUE(notMatches("class Y { void x() {} };", unresolvedMemberExpr()));
+ EXPECT_TRUE(
+ notMatches("class Y { void x() {} };", cxxDependentScopeMemberExpr()));
}
TEST(MemberExpression, MatchesMemberFunctionCall) {
EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr()));
+ EXPECT_TRUE(matches("class Y { template <class T> void x() { x<T>(); } };",
+ unresolvedMemberExpr()));
+ EXPECT_TRUE(matches("template <class T> void x() { T t; t.f(); }",
+ cxxDependentScopeMemberExpr()));
}
TEST(MemberExpression, MatchesVariable) {
@@ -435,6 +476,13 @@ TEST(MemberExpression, MatchesVariable) {
matches("class Y { void x() { y; } int y; };", memberExpr()));
EXPECT_TRUE(
matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr()));
+ EXPECT_TRUE(matches("template <class T>"
+ "class X : T { void f() { this->T::v; } };",
+ cxxDependentScopeMemberExpr()));
+ EXPECT_TRUE(matches("template <class T> class X : T { void f() { T::v; } };",
+ cxxDependentScopeMemberExpr()));
+ EXPECT_TRUE(matches("template <class T> void x() { T t; t.v; }",
+ cxxDependentScopeMemberExpr()));
}
TEST(MemberExpression, MatchesStaticVariable) {
@@ -746,23 +794,23 @@ TEST(Matcher, Initializers) {
has(
designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(
+ hasDescendant(floatLiteral(
equals(1.0))),
- has(integerLiteral(
+ hasDescendant(integerLiteral(
equals(2))))),
has(
designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(
+ hasDescendant(floatLiteral(
equals(2.0))),
- has(integerLiteral(
+ hasDescendant(integerLiteral(
equals(2))))),
has(
designatedInitExpr(
designatorCountIs(2),
- has(floatLiteral(
+ hasDescendant(floatLiteral(
equals(1.0))),
- has(integerLiteral(
+ hasDescendant(integerLiteral(
equals(0)))))
)))));
}
@@ -1133,6 +1181,14 @@ TEST(ParenExpression, SimpleCases) {
parenExpr()));
}
+TEST(ParenExpression, IgnoringParens) {
+ EXPECT_FALSE(matches("const char* str = (\"my-string\");",
+ implicitCastExpr(hasSourceExpression(stringLiteral()))));
+ EXPECT_TRUE(matches(
+ "const char* str = (\"my-string\");",
+ implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))));
+}
+
TEST(TypeMatching, MatchesTypes) {
EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
}
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 3b8f362101a6..5f6ecc0d0b8b 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -406,9 +406,22 @@ TEST(Matcher, AnyArgument) {
auto HasArgumentY = hasAnyArgument(
ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
StatementMatcher CallArgumentY = callExpr(HasArgumentY);
+ StatementMatcher CtorArgumentY = cxxConstructExpr(HasArgumentY);
+ StatementMatcher UnresolvedCtorArgumentY =
+ cxxUnresolvedConstructExpr(HasArgumentY);
StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY);
EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));
EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));
+ EXPECT_TRUE(matches("struct Y { Y(int, int); };"
+ "void x() { int y; (void)Y(1, y); }",
+ CtorArgumentY));
+ EXPECT_TRUE(matches("struct Y { Y(int, int); };"
+ "void x() { int y; (void)Y(y, 42); }",
+ CtorArgumentY));
+ EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }",
+ UnresolvedCtorArgumentY));
+ EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }",
+ UnresolvedCtorArgumentY));
EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "
"void x(I* i) { int y; [i f:y]; }",
ObjCCallArgumentY));
@@ -416,6 +429,12 @@ TEST(Matcher, AnyArgument) {
"void x(I* i) { int z; [i f:z]; }",
ObjCCallArgumentY));
EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
+ EXPECT_TRUE(notMatches("struct Y { Y(int, int); };"
+ "void x() { int y; (void)Y(1, 2); }",
+ CtorArgumentY));
+ EXPECT_TRUE(notMatches("template <class Y>"
+ "void x() { int y; (void)Y(1, 2); }",
+ UnresolvedCtorArgumentY));
StatementMatcher ImplicitCastedArgument = callExpr(
hasAnyArgument(implicitCastExpr()));
@@ -1302,6 +1321,45 @@ TEST(IgnoringImplicit, MatchesImplicit) {
varDecl(has(ignoringImplicit(cxxConstructExpr())))));
}
+TEST(IgnoringImplicit, MatchesNestedImplicit) {
+ StringRef Code = R"(
+
+struct OtherType;
+
+struct SomeType
+{
+ SomeType() {}
+ SomeType(const OtherType&) {}
+ SomeType& operator=(OtherType const&) { return *this; }
+};
+
+struct OtherType
+{
+ OtherType() {}
+ ~OtherType() {}
+};
+
+OtherType something()
+{
+ return {};
+}
+
+int main()
+{
+ SomeType i = something();
+}
+)";
+ EXPECT_TRUE(matches(Code, varDecl(
+ hasName("i"),
+ hasInitializer(exprWithCleanups(has(
+ cxxConstructExpr(has(expr(ignoringImplicit(cxxConstructExpr(
+ has(expr(ignoringImplicit(callExpr())))
+ )))))
+ )))
+ )
+ ));
+}
+
TEST(IgnoringImplicit, DoesNotMatchIncorrectly) {
EXPECT_TRUE(
notMatches("class C {}; C a = C();", varDecl(has(cxxConstructExpr()))));
@@ -1516,13 +1574,16 @@ TEST(SwitchCase, MatchesEachCase) {
ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));
EXPECT_TRUE(matches("void x() { switch(42) { case 1+1: case 4:; } }",
switchStmt(forEachSwitchCase(
- caseStmt(hasCaseConstant(integerLiteral()))))));
+ caseStmt(hasCaseConstant(
+ constantExpr(has(integerLiteral()))))))));
EXPECT_TRUE(notMatches("void x() { switch(42) { case 1+1: case 2+2:; } }",
switchStmt(forEachSwitchCase(
- caseStmt(hasCaseConstant(integerLiteral()))))));
+ caseStmt(hasCaseConstant(
+ constantExpr(has(integerLiteral()))))))));
EXPECT_TRUE(notMatches("void x() { switch(42) { case 1 ... 2:; } }",
switchStmt(forEachSwitchCase(
- caseStmt(hasCaseConstant(integerLiteral()))))));
+ caseStmt(hasCaseConstant(
+ constantExpr(has(integerLiteral()))))))));
EXPECT_TRUE(matchAndVerifyResultTrue(
"void x() { switch (42) { case 1: case 2: case 3: default:; } }",
switchStmt(forEachSwitchCase(caseStmt().bind("x"))),
diff --git a/unittests/ASTMatchers/CMakeLists.txt b/unittests/ASTMatchers/CMakeLists.txt
index ae1aecf503cc..4e44c795f894 100644
--- a/unittests/ASTMatchers/CMakeLists.txt
+++ b/unittests/ASTMatchers/CMakeLists.txt
@@ -24,6 +24,7 @@ target_link_libraries(ASTMatchersTests
clangASTMatchers
clangBasic
clangFrontend
+ clangSerialization
clangTooling
)
diff --git a/unittests/ASTMatchers/Dynamic/CMakeLists.txt b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
index 0fd96e97cff0..07742caef658 100644
--- a/unittests/ASTMatchers/Dynamic/CMakeLists.txt
+++ b/unittests/ASTMatchers/Dynamic/CMakeLists.txt
@@ -15,5 +15,6 @@ target_link_libraries(DynamicASTMatchersTests
clangBasic
clangDynamicASTMatchers
clangFrontend
+ clangSerialization
clangTooling
)
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index d670e3129b80..9e891069c862 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -148,8 +148,8 @@ TEST(ParserTest, ParseMatcher) {
const uint64_t ExpectedBar = Sema.expectMatcher("Bar");
const uint64_t ExpectedBaz = Sema.expectMatcher("Baz");
Sema.parse(" Foo ( Bar ( 17), Baz( \n \"B A,Z\") ) .bind( \"Yo!\") ");
- for (size_t i = 0, e = Sema.Errors.size(); i != e; ++i) {
- EXPECT_EQ("", Sema.Errors[i]);
+ for (const auto &E : Sema.Errors) {
+ EXPECT_EQ("", E);
}
EXPECT_NE(ExpectedFoo, ExpectedBar);
@@ -181,6 +181,21 @@ TEST(ParserTest, ParseMatcher) {
EXPECT_EQ("Yo!", Foo.BoundID);
}
+TEST(ParserTest, ParseComment) {
+ MockSema Sema;
+ Sema.expectMatcher("Foo");
+ Sema.parse(" Foo() # Bar() ");
+ for (const auto &E : Sema.Errors) {
+ EXPECT_EQ("", E);
+ }
+
+ EXPECT_EQ(1ULL, Sema.Matchers.size());
+
+ Sema.parse("Foo(#) ");
+
+ EXPECT_EQ("1:4: Error parsing matcher. Found end-of-code while looking for ')'.", Sema.Errors[1]);
+}
+
using ast_matchers::internal::Matcher;
Parser::NamedValueMap getTestNamedValues() {
@@ -359,6 +374,44 @@ TEST(ParserTest, CompletionNamedValues) {
Comps[2].MatcherDecl);
}
+TEST(ParserTest, ParseBindOnLet) {
+
+ auto NamedValues = getTestNamedValues();
+
+ Diagnostics Error;
+
+ {
+ llvm::Optional<DynTypedMatcher> TopLevelLetBinding(
+ Parser::parseMatcherExpression("hasParamA.bind(\"parmABinding\")",
+ nullptr, &NamedValues, &Error));
+ EXPECT_EQ("", Error.toStringFull());
+ auto M = TopLevelLetBinding->unconditionalConvertTo<Decl>();
+
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "void foo(int a);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ EXPECT_TRUE(matchAndVerifyResultFalse(
+ "void foo(int b);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ }
+
+ {
+ llvm::Optional<DynTypedMatcher> NestedLetBinding(
+ Parser::parseMatcherExpression(
+ "functionDecl(hasParamA.bind(\"parmABinding\"))", nullptr,
+ &NamedValues, &Error));
+ EXPECT_EQ("", Error.toStringFull());
+ auto M = NestedLetBinding->unconditionalConvertTo<Decl>();
+
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "void foo(int a);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ EXPECT_TRUE(matchAndVerifyResultFalse(
+ "void foo(int b);", M,
+ llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+ }
+}
+
} // end anonymous namespace
} // end namespace dynamic
} // end namespace ast_matchers
diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index aae229bd045a..1ca394d8d8c3 100644
--- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -440,7 +440,8 @@ TEST_F(RegistryTest, Errors) {
Error.get()).isNull());
EXPECT_EQ("Incorrect type for arg 1. "
"(Expected = Matcher<CXXRecordDecl>) != "
- "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
+ "(Actual = Matcher<CXXRecordDecl>&Matcher"
+ "<MemberExpr|UnresolvedMemberExpr|CXXDependentScopeMemberExpr>)",
Error->toString());
}
diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt
index 0056f82402aa..c760ae2d82b7 100644
--- a/unittests/Analysis/CMakeLists.txt
+++ b/unittests/Analysis/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(ClangAnalysisTests
CFGTest.cpp
CloneDetectionTest.cpp
+ ExprMutationAnalyzerTest.cpp
)
target_link_libraries(ClangAnalysisTests
@@ -14,5 +15,6 @@ target_link_libraries(ClangAnalysisTests
clangASTMatchers
clangBasic
clangFrontend
+ clangSerialization
clangTooling
)
diff --git a/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/unittests/Analysis/ExprMutationAnalyzerTest.cpp
new file mode 100644
index 000000000000..68c921e43988
--- /dev/null
+++ b/unittests/Analysis/ExprMutationAnalyzerTest.cpp
@@ -0,0 +1,1112 @@
+//===---------- ExprMutationAnalyzerTest.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/SmallString.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <cctype>
+
+namespace clang {
+
+using namespace clang::ast_matchers;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::ResultOf;
+using ::testing::StartsWith;
+using ::testing::Values;
+
+namespace {
+
+using ExprMatcher = internal::Matcher<Expr>;
+using StmtMatcher = internal::Matcher<Stmt>;
+
+std::unique_ptr<ASTUnit>
+buildASTFromCodeWithArgs(const Twine &Code,
+ const std::vector<std::string> &Args) {
+ SmallString<1024> CodeStorage;
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code.toStringRef(CodeStorage), Args);
+ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred());
+ return AST;
+}
+
+std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code) {
+ return buildASTFromCodeWithArgs(Code, {});
+}
+
+ExprMatcher declRefTo(StringRef Name) {
+ return declRefExpr(to(namedDecl(hasName(Name))));
+}
+
+StmtMatcher withEnclosingCompound(ExprMatcher Matcher) {
+ return expr(Matcher, hasAncestor(compoundStmt().bind("stmt"))).bind("expr");
+}
+
+bool isMutated(const SmallVectorImpl<BoundNodes> &Results, ASTUnit *AST) {
+ const auto *const S = selectFirst<Stmt>("stmt", Results);
+ const auto *const E = selectFirst<Expr>("expr", Results);
+ return ExprMutationAnalyzer(*S, AST->getASTContext()).isMutated(E);
+}
+
+SmallVector<std::string, 1>
+mutatedBy(const SmallVectorImpl<BoundNodes> &Results, ASTUnit *AST) {
+ const auto *const S = selectFirst<Stmt>("stmt", Results);
+ SmallVector<std::string, 1> Chain;
+ ExprMutationAnalyzer Analyzer(*S, AST->getASTContext());
+ for (const auto *E = selectFirst<Expr>("expr", Results); E != nullptr;) {
+ const Stmt *By = Analyzer.findMutation(E);
+ std::string buffer;
+ llvm::raw_string_ostream stream(buffer);
+ By->printPretty(stream, nullptr, AST->getASTContext().getPrintingPolicy());
+ Chain.push_back(StringRef(stream.str()).trim().str());
+ E = dyn_cast<DeclRefExpr>(By);
+ }
+ return Chain;
+}
+
+std::string removeSpace(std::string s) {
+ s.erase(std::remove_if(s.begin(), s.end(),
+ [](char c) { return std::isspace(c); }),
+ s.end());
+ return s;
+}
+
+const std::string StdRemoveReference =
+ "namespace std {"
+ "template<class T> struct remove_reference { typedef T type; };"
+ "template<class T> struct remove_reference<T&> { typedef T type; };"
+ "template<class T> struct remove_reference<T&&> { typedef T type; }; }";
+
+const std::string StdMove =
+ "namespace std {"
+ "template<class T> typename remove_reference<T>::type&& "
+ "move(T&& t) noexcept {"
+ "return static_cast<typename remove_reference<T>::type&&>(t); } }";
+
+const std::string StdForward =
+ "namespace std {"
+ "template<class T> T&& "
+ "forward(typename remove_reference<T>::type& t) noexcept { return t; }"
+ "template<class T> T&& "
+ "forward(typename remove_reference<T>::type&& t) noexcept { return t; } }";
+
+} // namespace
+
+TEST(ExprMutationAnalyzerTest, Trivial) {
+ const auto AST = buildASTFromCode("void f() { int x; x; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+class AssignmentTest : public ::testing::TestWithParam<std::string> {};
+
+TEST_P(AssignmentTest, AssignmentModifies) {
+ const std::string ModExpr = "x " + GetParam() + " 10";
+ const auto AST = buildASTFromCode("void f() { int x; " + ModExpr + "; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr));
+}
+
+INSTANTIATE_TEST_CASE_P(AllAssignmentOperators, AssignmentTest,
+ Values("=", "+=", "-=", "*=", "/=", "%=", "&=", "|=",
+ "^=", "<<=", ">>="), );
+
+class IncDecTest : public ::testing::TestWithParam<std::string> {};
+
+TEST_P(IncDecTest, IncDecModifies) {
+ const std::string ModExpr = GetParam();
+ const auto AST = buildASTFromCode("void f() { int x; " + ModExpr + "; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr));
+}
+
+INSTANTIATE_TEST_CASE_P(AllIncDecOperators, IncDecTest,
+ Values("++x", "--x", "x++", "x--"), );
+
+TEST(ExprMutationAnalyzerTest, NonConstMemberFunc) {
+ const auto AST = buildASTFromCode(
+ "void f() { struct Foo { void mf(); }; Foo x; x.mf(); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()"));
+}
+
+TEST(ExprMutationAnalyzerTest, AssumedNonConstMemberFunc) {
+ auto AST = buildASTFromCodeWithArgs(
+ "struct X { template <class T> void mf(); };"
+ "template <class T> void f() { X x; x.mf<T>(); }",
+ {"-fno-delayed-template-parsing"});
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf<T>()"));
+
+ AST = buildASTFromCodeWithArgs("template <class T> void f() { T x; x.mf(); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()"));
+
+ AST = buildASTFromCodeWithArgs(
+ "template <class T> struct X;"
+ "template <class T> void f() { X<T> x; x.mf(); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()"));
+}
+
+TEST(ExprMutationAnalyzerTest, ConstMemberFunc) {
+ const auto AST = buildASTFromCode(
+ "void f() { struct Foo { void mf() const; }; Foo x; x.mf(); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, NonConstOperator) {
+ const auto AST = buildASTFromCode(
+ "void f() { struct Foo { Foo& operator=(int); }; Foo x; x = 10; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, ConstOperator) {
+ const auto AST = buildASTFromCode(
+ "void f() { struct Foo { int operator()() const; }; Foo x; x(); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ByValueArgument) {
+ auto AST = buildASTFromCode("void g(int); void f() { int x; g(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void g(int*); void f() { int* x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("typedef int* IntPtr;"
+ "void g(IntPtr); void f() { int* x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "struct A {}; A operator+(A, int); void f() { A x; x + 1; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { struct A { A(int); }; int x; A y(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("struct A { A(); A& operator=(A); };"
+ "void f() { A x, y; y = x; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "template <int> struct A { A(); A(const A&); static void mf(A) {} };"
+ "void f() { A<0> x; A<0>::mf(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ByConstValueArgument) {
+ auto AST = buildASTFromCode("void g(const int); void f() { int x; g(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void g(int* const); void f() { int* x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("typedef int* const CIntPtr;"
+ "void g(CIntPtr); void f() { int* x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "struct A {}; A operator+(const A, int); void f() { A x; x + 1; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "void f() { struct A { A(const int); }; int x; A y(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("template <int> struct A { A(); A(const A&);"
+ "static void mf(const A&) {} };"
+ "void f() { A<0> x; A<0>::mf(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ByNonConstRefArgument) {
+ auto AST = buildASTFromCode("void g(int&); void f() { int x; g(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCode("typedef int& IntRef;"
+ "void g(IntRef); void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCode("template <class T> using TRef = T&;"
+ "void g(TRef<int>); void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCode(
+ "template <class T> struct identity { using type = T; };"
+ "template <class T, class U = T&> void g(typename identity<U>::type);"
+ "void f() { int x; g<int>(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g<int>(x)"));
+
+ AST = buildASTFromCode("typedef int* IntPtr;"
+ "void g(IntPtr&); void f() { int* x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCode("typedef int* IntPtr; typedef IntPtr& IntPtrRef;"
+ "void g(IntPtrRef); void f() { int* x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCode(
+ "struct A {}; A operator+(A&, int); void f() { A x; x + 1; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x + 1"));
+
+ AST = buildASTFromCode("void f() { struct A { A(int&); }; int x; A y(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+ AST = buildASTFromCode("void f() { struct A { A(); A(A&); }; A x; A y(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+ AST = buildASTFromCode(
+ "template <int> struct A { A(); A(const A&); static void mf(A&) {} };"
+ "void f() { A<0> x; A<0>::mf(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("A<0>::mf(x)"));
+}
+
+TEST(ExprMutationAnalyzerTest, ByConstRefArgument) {
+ auto AST = buildASTFromCode("void g(const int&); void f() { int x; g(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("typedef const int& CIntRef;"
+ "void g(CIntRef); void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("template <class T> using CTRef = const T&;"
+ "void g(CTRef<int>); void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST =
+ buildASTFromCode("template <class T> struct identity { using type = T; };"
+ "template <class T, class U = const T&>"
+ "void g(typename identity<U>::type);"
+ "void f() { int x; g<int>(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "struct A {}; A operator+(const A&, int); void f() { A x; x + 1; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "void f() { struct A { A(const int&); }; int x; A y(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "void f() { struct A { A(); A(const A&); }; A x; A y(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ByNonConstRRefArgument) {
+ auto AST = buildASTFromCode(
+ "void g(int&&); void f() { int x; g(static_cast<int &&>(x)); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("g(static_cast<int &&>(x))"));
+
+ AST = buildASTFromCode("struct A {}; A operator+(A&&, int);"
+ "void f() { A x; static_cast<A &&>(x) + 1; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("static_cast<A &&>(x) + 1"));
+
+ AST = buildASTFromCode("void f() { struct A { A(int&&); }; "
+ "int x; A y(static_cast<int &&>(x)); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("static_cast<int &&>(x)"));
+
+ AST = buildASTFromCode("void f() { struct A { A(); A(A&&); }; "
+ "A x; A y(static_cast<A &&>(x)); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("static_cast<A &&>(x)"));
+}
+
+TEST(ExprMutationAnalyzerTest, ByConstRRefArgument) {
+ auto AST = buildASTFromCode(
+ "void g(const int&&); void f() { int x; g(static_cast<int&&>(x)); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("struct A {}; A operator+(const A&&, int);"
+ "void f() { A x; static_cast<A&&>(x) + 1; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { struct A { A(const int&&); }; "
+ "int x; A y(static_cast<int&&>(x)); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { struct A { A(); A(const A&&); }; "
+ "A x; A y(static_cast<A&&>(x)); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, Move) {
+ auto AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "void f() { struct A {}; A x; std::move(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "void f() { struct A {}; A x, y; std::move(x) = y; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("std::move(x) = y"));
+
+ AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "void f() { int x, y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST =
+ buildASTFromCode(StdRemoveReference + StdMove +
+ "struct S { S(); S(const S&); S& operator=(const S&); };"
+ "void f() { S x, y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "struct S { S(); S(S&&); S& operator=(S&&); };"
+ "void f() { S x, y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("y = std::move(x)"));
+
+ AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "struct S { S(); S(const S&); S(S&&);"
+ "S& operator=(const S&); S& operator=(S&&); };"
+ "void f() { S x, y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("y = std::move(x)"));
+
+ AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "struct S { S(); S(const S&); S(S&&);"
+ "S& operator=(const S&); S& operator=(S&&); };"
+ "void f() { const S x; S y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "struct S { S(); S& operator=(S); };"
+ "void f() { S x, y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(StdRemoveReference + StdMove +
+ "struct S{}; void f() { S x, y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("y = std::move(x)"));
+
+ AST = buildASTFromCode(
+ StdRemoveReference + StdMove +
+ "struct S{}; void f() { const S x; S y; y = std::move(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, Forward) {
+ auto AST =
+ buildASTFromCode(StdRemoveReference + StdForward +
+ "void f() { struct A {}; A x; std::forward<A &>(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ StdRemoveReference + StdForward +
+ "void f() { struct A {}; A x, y; std::forward<A &>(x) = y; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("std::forward<A &>(x) = y"));
+}
+
+TEST(ExprMutationAnalyzerTest, CallUnresolved) {
+ auto AST =
+ buildASTFromCodeWithArgs("template <class T> void f() { T x; g(x); }",
+ {"-fno-delayed-template-parsing"});
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST =
+ buildASTFromCodeWithArgs("template <int N> void f() { char x[N]; g(x); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCodeWithArgs(
+ "template <class T> void f(T t) { int x; g(t, x); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(t, x)"));
+
+ AST = buildASTFromCodeWithArgs(
+ "template <class T> void f(T t) { int x; t.mf(x); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("t.mf(x)"));
+
+ AST = buildASTFromCodeWithArgs(
+ "template <class T> struct S;"
+ "template <class T> void f() { S<T> s; int x; s.mf(x); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("s.mf(x)"));
+
+ AST = buildASTFromCodeWithArgs(
+ "struct S { template <class T> void mf(); };"
+ "template <class T> void f(S s) { int x; s.mf<T>(x); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("s.mf<T>(x)"));
+
+ AST = buildASTFromCodeWithArgs("template <class F>"
+ "void g(F f) { int x; f(x); } ",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("f(x)"));
+
+ AST = buildASTFromCodeWithArgs(
+ "template <class T> void f() { int x; (void)T(x); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("T(x)"));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsValue) {
+ auto AST = buildASTFromCode("int f() { int x; return x; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("int* f() { int* x; return x; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("typedef int* IntPtr;"
+ "IntPtr f() { int* x; return x; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsNonConstRef) {
+ const auto AST = buildASTFromCode("int& f() { int x; return x; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("return x;"));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsConstRef) {
+ const auto AST = buildASTFromCode("const int& f() { int x; return x; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsNonConstRRef) {
+ const auto AST =
+ buildASTFromCode("int&& f() { int x; return static_cast<int &&>(x); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("return static_cast<int &&>(x);"));
+}
+
+TEST(ExprMutationAnalyzerTest, ReturnAsConstRRef) {
+ const auto AST = buildASTFromCode(
+ "const int&& f() { int x; return static_cast<int&&>(x); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, TakeAddress) {
+ const auto AST = buildASTFromCode("void g(int*); void f() { int x; g(&x); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("&x"));
+}
+
+TEST(ExprMutationAnalyzerTest, ArrayToPointerDecay) {
+ const auto AST =
+ buildASTFromCode("void g(int*); void f() { int x[2]; g(x); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+}
+
+TEST(ExprMutationAnalyzerTest, TemplateWithArrayToPointerDecay) {
+ const auto AST = buildASTFromCodeWithArgs(
+ "template <typename T> struct S { static constexpr int v = 8; };"
+ "template <> struct S<int> { static constexpr int v = 4; };"
+ "void g(char*);"
+ "template <typename T> void f() { char x[S<T>::v]; g(x); }"
+ "template <> void f<int>() { char y[S<int>::v]; g(y); }",
+ {"-fno-delayed-template-parsing"});
+ const auto ResultsX =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(ResultsX, AST.get()), ElementsAre("g(x)"));
+ const auto ResultsY =
+ match(withEnclosingCompound(declRefTo("y")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(ResultsY, AST.get()), ElementsAre("y"));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowRefModified) {
+ auto AST = buildASTFromCode(
+ "void f() { int x; int& r0 = x; int& r1 = r0; int& r2 = r1; "
+ "int& r3 = r2; r3 = 10; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("r0", "r1", "r2", "r3", "r3 = 10"));
+
+ AST = buildASTFromCode("typedef int& IntRefX;"
+ "using IntRefY = int&;"
+ "void f() { int x; IntRefX r0 = x; IntRefY r1 = r0;"
+ "decltype((x)) r2 = r1; r2 = 10; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("r0", "r1", "r2", "r2 = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowRefNotModified) {
+ auto AST = buildASTFromCode(
+ "void f() { int x; int& r0 = x; int& r1 = r0; int& r2 = r1; "
+ "int& r3 = r2; int& r4 = r3; int& r5 = r4;}");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { int x; int& r0 = x; const int& r1 = r0;}");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("typedef const int& CIntRefX;"
+ "using CIntRefY = const int&;"
+ "void f() { int x; int& r0 = x; CIntRefX r1 = r0;"
+ "CIntRefY r2 = r1; decltype((r1)) r3 = r2;}");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowConditionalRefModified) {
+ const auto AST = buildASTFromCode(
+ "void f() { int x, y; bool b; int &r = b ? x : y; r = 10; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("r", "r = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowConditionalRefNotModified) {
+ const auto AST =
+ buildASTFromCode("void f() { int x, y; bool b; int& r = b ? x : y; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowFuncArgModified) {
+ auto AST = buildASTFromCode("template <class T> void g(T&& t) { t = 10; }"
+ "void f() { int x; g(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCode(
+ "void h(int&);"
+ "template <class... Args> void g(Args&&... args) { h(args...); }"
+ "void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+
+ AST = buildASTFromCode(
+ "void h(int&, int);"
+ "template <class... Args> void g(Args&&... args) { h(args...); }"
+ "void f() { int x, y; g(x, y); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x, y)"));
+ Results = match(withEnclosingCompound(declRefTo("y")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "void h(int, int&);"
+ "template <class... Args> void g(Args&&... args) { h(args...); }"
+ "void f() { int x, y; g(y, x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(y, x)"));
+ Results = match(withEnclosingCompound(declRefTo("y")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("struct S { template <class T> S(T&& t) { t = 10; } };"
+ "void f() { int x; S s(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+ AST = buildASTFromCode(
+ "struct S { template <class T> S(T&& t) : m(++t) { } int m; };"
+ "void f() { int x; S s(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+ AST = buildASTFromCode("template <class U> struct S {"
+ "template <class T> S(T&& t) : m(++t) { } U m; };"
+ "void f() { int x; S<int> s(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+ AST = buildASTFromCode(StdRemoveReference + StdForward +
+ "template <class... Args> void u(Args&...);"
+ "template <class... Args> void h(Args&&... args)"
+ "{ u(std::forward<Args>(args)...); }"
+ "template <class... Args> void g(Args&&... args)"
+ "{ h(std::forward<Args>(args)...); }"
+ "void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)"));
+}
+
+TEST(ExprMutationAnalyzerTest, FollowFuncArgNotModified) {
+ auto AST = buildASTFromCode("template <class T> void g(T&&) {}"
+ "void f() { int x; g(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("template <class T> void g(T&& t) { t; }"
+ "void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("template <class... Args> void g(Args&&...) {}"
+ "void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("template <class... Args> void g(Args&&...) {}"
+ "void f() { int y, x; g(y, x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "void h(int, int&);"
+ "template <class... Args> void g(Args&&... args) { h(args...); }"
+ "void f() { int x, y; g(x, y); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("struct S { template <class T> S(T&& t) { t; } };"
+ "void f() { int x; S s(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "struct S { template <class T> S(T&& t) : m(t) { } int m; };"
+ "void f() { int x; S s(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("template <class U> struct S {"
+ "template <class T> S(T&& t) : m(t) { } U m; };"
+ "void f() { int x; S<int> s(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(StdRemoveReference + StdForward +
+ "template <class... Args> void u(Args...);"
+ "template <class... Args> void h(Args&&... args)"
+ "{ u(std::forward<Args>(args)...); }"
+ "template <class... Args> void g(Args&&... args)"
+ "{ h(std::forward<Args>(args)...); }"
+ "void f() { int x; g(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, ArrayElementModified) {
+ const auto AST = buildASTFromCode("void f() { int x[2]; x[0] = 10; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x[0] = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, ArrayElementNotModified) {
+ const auto AST = buildASTFromCode("void f() { int x[2]; x[0]; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, NestedMemberModified) {
+ auto AST =
+ buildASTFromCode("void f() { struct A { int vi; }; struct B { A va; }; "
+ "struct C { B vb; }; C x; x.vb.va.vi = 10; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.vb.va.vi = 10"));
+
+ AST = buildASTFromCodeWithArgs(
+ "template <class T> void f() { T x; x.y.z = 10; }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.y.z = 10"));
+
+ AST = buildASTFromCodeWithArgs(
+ "template <class T> struct S;"
+ "template <class T> void f() { S<T> x; x.y.z = 10; }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.y.z = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, NestedMemberNotModified) {
+ auto AST =
+ buildASTFromCode("void f() { struct A { int vi; }; struct B { A va; }; "
+ "struct C { B vb; }; C x; x.vb.va.vi; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCodeWithArgs("template <class T> void f() { T x; x.y.z; }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST =
+ buildASTFromCodeWithArgs("template <class T> struct S;"
+ "template <class T> void f() { S<T> x; x.y.z; }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToValue) {
+ const auto AST =
+ buildASTFromCode("void f() { int x; static_cast<double>(x); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToRefModified) {
+ auto AST =
+ buildASTFromCode("void f() { int x; static_cast<int &>(x) = 10; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("static_cast<int &>(x) = 10"));
+
+ AST = buildASTFromCode("typedef int& IntRef;"
+ "void f() { int x; static_cast<IntRef>(x) = 10; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre("static_cast<IntRef>(x) = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToRefNotModified) {
+ const auto AST =
+ buildASTFromCode("void f() { int x; static_cast<int&>(x); }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, CastToConstRef) {
+ auto AST =
+ buildASTFromCode("void f() { int x; static_cast<const int&>(x); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("typedef const int& CIntRef;"
+ "void f() { int x; static_cast<CIntRef>(x); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaDefaultCaptureByValue) {
+ const auto AST = buildASTFromCode("void f() { int x; [=]() { x; }; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaExplicitCaptureByValue) {
+ const auto AST = buildASTFromCode("void f() { int x; [x]() { x; }; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaDefaultCaptureByRef) {
+ const auto AST = buildASTFromCode("void f() { int x; [&]() { x = 10; }; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre(ResultOf(removeSpace, "[&](){x=10;}")));
+}
+
+TEST(ExprMutationAnalyzerTest, LambdaExplicitCaptureByRef) {
+ const auto AST = buildASTFromCode("void f() { int x; [&x]() { x = 10; }; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()),
+ ElementsAre(ResultOf(removeSpace, "[&x](){x=10;}")));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByRefModified) {
+ auto AST =
+ buildASTFromCode("void f() { int x[2]; for (int& e : x) e = 10; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("e", "e = 10"));
+
+ AST = buildASTFromCode("typedef int& IntRef;"
+ "void f() { int x[2]; for (IntRef e : x) e = 10; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("e", "e = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByRefNotModified) {
+ const auto AST =
+ buildASTFromCode("void f() { int x[2]; for (int& e : x) e; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByValue) {
+ auto AST = buildASTFromCode("void f() { int x[2]; for (int e : x) e = 10; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST =
+ buildASTFromCode("void f() { int* x[2]; for (int* e : x) e = nullptr; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "typedef int* IntPtr;"
+ "void f() { int* x[2]; for (IntPtr e : x) e = nullptr; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForArrayByConstRef) {
+ auto AST =
+ buildASTFromCode("void f() { int x[2]; for (const int& e : x) e; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("typedef const int& CIntRef;"
+ "void f() { int x[2]; for (CIntRef e : x) e; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByRefModified) {
+ const auto AST =
+ buildASTFromCode("struct V { int* begin(); int* end(); };"
+ "void f() { V x; for (int& e : x) e = 10; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("e", "e = 10"));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByRefNotModified) {
+ const auto AST = buildASTFromCode("struct V { int* begin(); int* end(); };"
+ "void f() { V x; for (int& e : x) e; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByValue) {
+ const auto AST = buildASTFromCode(
+ "struct V { const int* begin() const; const int* end() const; };"
+ "void f() { V x; for (int e : x) e; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, RangeForNonArrayByConstRef) {
+ const auto AST = buildASTFromCode(
+ "struct V { const int* begin() const; const int* end() const; };"
+ "void f() { V x; for (const int& e : x) e; }");
+ const auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, UnevaluatedExpressions) {
+ auto AST = buildASTFromCode("void f() { int x, y; decltype(x = 10) z = y; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { int x, y; __typeof(x = 10) z = y; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { int x, y; __typeof__(x = 10) z = y; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { int x; sizeof(x = 10); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { int x; alignof(x = 10); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode("void f() { int x; noexcept(x = 10); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCodeWithArgs("namespace std { class type_info; }"
+ "void f() { int x; typeid(x = 10); }",
+ {"-frtti"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(
+ "void f() { int x; _Generic(x = 10, int: 0, default: 1); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+}
+
+TEST(ExprMutationAnalyzerTest, NotUnevaluatedExpressions) {
+ auto AST = buildASTFromCode("void f() { int x; sizeof(int[x++]); }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x++"));
+
+ AST = buildASTFromCodeWithArgs(
+ "namespace std { class type_info; }"
+ "struct A { virtual ~A(); }; struct B : A {};"
+ "struct X { A& f(); }; void f() { X x; typeid(x.f()); }",
+ {"-frtti"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.f()"));
+}
+
+TEST(ExprMutationAnalyzerTest, UniquePtr) {
+ const std::string UniquePtrDef =
+ "template <class T> struct UniquePtr {"
+ " UniquePtr();"
+ " UniquePtr(const UniquePtr&) = delete;"
+ " UniquePtr(UniquePtr&&);"
+ " UniquePtr& operator=(const UniquePtr&) = delete;"
+ " UniquePtr& operator=(UniquePtr&&);"
+ " T& operator*() const;"
+ " T* operator->() const;"
+ "};";
+
+ auto AST = buildASTFromCode(UniquePtrDef +
+ "void f() { UniquePtr<int> x; *x = 10; }");
+ auto Results =
+ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("* x = 10"));
+
+ AST = buildASTFromCode(UniquePtrDef + "void f() { UniquePtr<int> x; *x; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(UniquePtrDef +
+ "void f() { UniquePtr<const int> x; *x; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCode(UniquePtrDef + "struct S { int v; };"
+ "void f() { UniquePtr<S> x; x->v; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+ AST = buildASTFromCode(UniquePtrDef +
+ "struct S { int v; };"
+ "void f() { UniquePtr<const S> x; x->v; }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST =
+ buildASTFromCode(UniquePtrDef + "struct S { void mf(); };"
+ "void f() { UniquePtr<S> x; x->mf(); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+ AST = buildASTFromCode(UniquePtrDef +
+ "struct S { void mf() const; };"
+ "void f() { UniquePtr<const S> x; x->mf(); }");
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_FALSE(isMutated(Results, AST.get()));
+
+ AST = buildASTFromCodeWithArgs(
+ UniquePtrDef + "template <class T> void f() { UniquePtr<T> x; x->mf(); }",
+ {"-fno-delayed-template-parsing"});
+ Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+ EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x->mf()"));
+}
+
+} // namespace clang
diff --git a/unittests/Basic/CMakeLists.txt b/unittests/Basic/CMakeLists.txt
index b46c067dc2ef..537f3ba5fcc6 100644
--- a/unittests/Basic/CMakeLists.txt
+++ b/unittests/Basic/CMakeLists.txt
@@ -6,13 +6,14 @@ add_clang_unittest(BasicTests
CharInfoTest.cpp
DiagnosticTest.cpp
FileManagerTest.cpp
+ FixedPointTest.cpp
MemoryBufferCacheTest.cpp
SourceManagerTest.cpp
- VirtualFileSystemTest.cpp
)
target_link_libraries(BasicTests
PRIVATE
+ clangAST
clangBasic
clangLex
)
diff --git a/unittests/Basic/FileManagerTest.cpp b/unittests/Basic/FileManagerTest.cpp
index 52cb5b2f0d65..746d9ad5e89b 100644
--- a/unittests/Basic/FileManagerTest.cpp
+++ b/unittests/Basic/FileManagerTest.cpp
@@ -10,9 +10,9 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/FileSystemStatCache.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -60,8 +60,8 @@ public:
// Implement FileSystemStatCache::getStat().
LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
- std::unique_ptr<vfs::File> *F,
- vfs::FileSystem &FS) override {
+ std::unique_ptr<llvm::vfs::File> *F,
+ llvm::vfs::FileSystem &FS) override {
#ifndef _WIN32
SmallString<128> NormalizedPath(Path);
llvm::sys::path::native(NormalizedPath);
@@ -111,7 +111,7 @@ TEST_F(FileManagerTest, NoVirtualDirectoryExistsBeforeAVirtualFileIsAdded) {
// FileManager to report "file/directory doesn't exist". This
// avoids the possibility of the result of this test being affected
// by what's in the real file system.
- manager.addStatCache(llvm::make_unique<FakeStatCache>());
+ manager.setStatCache(llvm::make_unique<FakeStatCache>());
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir/foo"));
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir"));
@@ -121,7 +121,7 @@ TEST_F(FileManagerTest, NoVirtualDirectoryExistsBeforeAVirtualFileIsAdded) {
// When a virtual file is added, all of its ancestors should be created.
TEST_F(FileManagerTest, getVirtualFileCreatesDirectoryEntriesForAncestors) {
// Fake an empty real file system.
- manager.addStatCache(llvm::make_unique<FakeStatCache>());
+ manager.setStatCache(llvm::make_unique<FakeStatCache>());
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir/foo"));
@@ -149,7 +149,7 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
statCache->InjectFile(FileName, 45);
#endif
- manager.addStatCache(std::move(statCache));
+ manager.setStatCache(std::move(statCache));
const FileEntry *file = manager.getFile("/tmp/test");
ASSERT_TRUE(file != nullptr);
@@ -173,7 +173,7 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
// getFile() returns non-NULL if a virtual file exists at the given path.
TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingVirtualFile) {
// Fake an empty real file system.
- manager.addStatCache(llvm::make_unique<FakeStatCache>());
+ manager.setStatCache(llvm::make_unique<FakeStatCache>());
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
const FileEntry *file = manager.getFile("virtual/dir/bar.h");
@@ -195,7 +195,7 @@ TEST_F(FileManagerTest, getFileReturnsDifferentFileEntriesForDifferentFiles) {
statCache->InjectDirectory(".", 41);
statCache->InjectFile("foo.cpp", 42);
statCache->InjectFile("bar.cpp", 43);
- manager.addStatCache(std::move(statCache));
+ manager.setStatCache(std::move(statCache));
const FileEntry *fileFoo = manager.getFile("foo.cpp");
const FileEntry *fileBar = manager.getFile("bar.cpp");
@@ -213,7 +213,7 @@ TEST_F(FileManagerTest, getFileReturnsNULLForNonexistentFile) {
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory(".", 41);
statCache->InjectFile("foo.cpp", 42);
- manager.addStatCache(std::move(statCache));
+ manager.setStatCache(std::move(statCache));
// Create a virtual bar.cpp file.
manager.getVirtualFile("bar.cpp", 200, 0);
@@ -222,6 +222,33 @@ TEST_F(FileManagerTest, getFileReturnsNULLForNonexistentFile) {
EXPECT_EQ(nullptr, file);
}
+// When calling getFile(OpenFile=false); getFile(OpenFile=true) the file is
+// opened for the second call.
+TEST_F(FileManagerTest, getFileDefersOpen) {
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS(
+ new llvm::vfs::InMemoryFileSystem());
+ FS->addFile("/tmp/test", 0, llvm::MemoryBuffer::getMemBufferCopy("test"));
+ FS->addFile("/tmp/testv", 0, llvm::MemoryBuffer::getMemBufferCopy("testv"));
+ FileManager manager(options, FS);
+
+ const FileEntry *file = manager.getFile("/tmp/test", /*OpenFile=*/false);
+ ASSERT_TRUE(file != nullptr);
+ ASSERT_TRUE(file->isValid());
+ // "real path name" reveals whether the file was actually opened.
+ EXPECT_FALSE(file->isOpenForTests());
+
+ file = manager.getFile("/tmp/test", /*OpenFile=*/true);
+ ASSERT_TRUE(file != nullptr);
+ ASSERT_TRUE(file->isValid());
+ EXPECT_TRUE(file->isOpenForTests());
+
+ // However we should never try to open a file previously opened as virtual.
+ ASSERT_TRUE(manager.getVirtualFile("/tmp/testv", 5, 0));
+ ASSERT_TRUE(manager.getFile("/tmp/testv", /*OpenFile=*/false));
+ file = manager.getFile("/tmp/testv", /*OpenFile=*/true);
+ EXPECT_FALSE(file->isOpenForTests());
+}
+
// The following tests apply to Unix-like system only.
#ifndef _WIN32
@@ -233,7 +260,7 @@ TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedRealFiles) {
statCache->InjectDirectory("abc", 41);
statCache->InjectFile("abc/foo.cpp", 42);
statCache->InjectFile("abc/bar.cpp", 42);
- manager.addStatCache(std::move(statCache));
+ manager.setStatCache(std::move(statCache));
EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
}
@@ -246,7 +273,7 @@ TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) {
statCache->InjectDirectory("abc", 41);
statCache->InjectFile("abc/foo.cpp", 42);
statCache->InjectFile("abc/bar.cpp", 42);
- manager.addStatCache(std::move(statCache));
+ manager.setStatCache(std::move(statCache));
ASSERT_TRUE(manager.getVirtualFile("abc/foo.cpp", 100, 0)->isValid());
ASSERT_TRUE(manager.getVirtualFile("abc/bar.cpp", 200, 0)->isValid());
@@ -254,15 +281,6 @@ TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) {
EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
}
-TEST_F(FileManagerTest, addRemoveStatCache) {
- manager.addStatCache(llvm::make_unique<FakeStatCache>());
- auto statCacheOwner = llvm::make_unique<FakeStatCache>();
- auto *statCache = statCacheOwner.get();
- manager.addStatCache(std::move(statCacheOwner));
- manager.addStatCache(llvm::make_unique<FakeStatCache>());
- manager.removeStatCache(statCache);
-}
-
// getFile() Should return the same entry as getVirtualFile if the file actually
// is a virtual file, even if the name is not exactly the same (but is after
// normalisation done by the file system, like on Windows). This can be checked
@@ -273,7 +291,7 @@ TEST_F(FileManagerTest, getVirtualFileWithDifferentName) {
statCache->InjectDirectory("c:\\tmp", 42);
statCache->InjectFile("c:\\tmp\\test", 43);
- manager.addStatCache(std::move(statCache));
+ manager.setStatCache(std::move(statCache));
// Inject the virtual file:
const FileEntry *file1 = manager.getVirtualFile("c:\\tmp\\test", 123, 1);
@@ -305,8 +323,8 @@ TEST_F(FileManagerTest, makeAbsoluteUsesVFS) {
#endif
llvm::sys::path::append(CustomWorkingDir, "some", "weird", "path");
- auto FS =
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem>(new vfs::InMemoryFileSystem);
+ auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
+ new llvm::vfs::InMemoryFileSystem);
// setCurrentworkingdirectory must finish without error.
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
@@ -322,4 +340,38 @@ TEST_F(FileManagerTest, makeAbsoluteUsesVFS) {
EXPECT_EQ(Path, ExpectedResult);
}
+// getVirtualFile should always fill the real path.
+TEST_F(FileManagerTest, getVirtualFileFillsRealPathName) {
+ SmallString<64> CustomWorkingDir;
+#ifdef _WIN32
+ CustomWorkingDir = "C:/";
+#else
+ CustomWorkingDir = "/";
+#endif
+
+ auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
+ new llvm::vfs::InMemoryFileSystem);
+ // setCurrentworkingdirectory must finish without error.
+ ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
+
+ FileSystemOptions Opts;
+ FileManager Manager(Opts, FS);
+
+ // Inject fake files into the file system.
+ auto statCache = llvm::make_unique<FakeStatCache>();
+ statCache->InjectDirectory("/tmp", 42);
+ statCache->InjectFile("/tmp/test", 43);
+
+ Manager.setStatCache(std::move(statCache));
+
+ // Check for real path.
+ const FileEntry *file = Manager.getVirtualFile("/tmp/test", 123, 1);
+ ASSERT_TRUE(file != nullptr);
+ ASSERT_TRUE(file->isValid());
+ SmallString<64> ExpectedResult = CustomWorkingDir;
+
+ llvm::sys::path::append(ExpectedResult, "tmp", "test");
+ EXPECT_EQ(file->tryGetRealPathName(), ExpectedResult);
+}
+
} // anonymous namespace
diff --git a/unittests/Basic/FixedPointTest.cpp b/unittests/Basic/FixedPointTest.cpp
new file mode 100644
index 000000000000..8e184a7af858
--- /dev/null
+++ b/unittests/Basic/FixedPointTest.cpp
@@ -0,0 +1,645 @@
+//===- unittests/Basic/FixedPointTest.cpp -- fixed point number tests -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FixedPoint.h"
+#include "llvm/ADT/APSInt.h"
+#include "gtest/gtest.h"
+
+using clang::APFixedPoint;
+using clang::FixedPointSemantics;
+using llvm::APInt;
+using llvm::APSInt;
+
+namespace {
+
+FixedPointSemantics Saturated(FixedPointSemantics Sema) {
+ Sema.setSaturated(true);
+ return Sema;
+}
+
+FixedPointSemantics getSAccumSema() {
+ return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getAccumSema() {
+ return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getLAccumSema() {
+ return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getSFractSema() {
+ return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getFractSema() {
+ return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getLFractSema() {
+ return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUSAccumSema() {
+ return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUAccumSema() {
+ return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getULAccumSema() {
+ return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUSFractSema() {
+ return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUFractSema() {
+ return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getULFractSema() {
+ return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getPadUSAccumSema() {
+ return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadUAccumSema() {
+ return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadULAccumSema() {
+ return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadUSFractSema() {
+ return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadUFractSema() {
+ return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadULFractSema() {
+ return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+void CheckUnpaddedMax(const FixedPointSemantics &Sema) {
+ ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
+ APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()));
+}
+
+void CheckPaddedMax(const FixedPointSemantics &Sema) {
+ ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
+ APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1);
+}
+
+void CheckMin(const FixedPointSemantics &Sema) {
+ ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(),
+ APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()));
+}
+
+TEST(FixedPointTest, getMax) {
+ CheckUnpaddedMax(getSAccumSema());
+ CheckUnpaddedMax(getAccumSema());
+ CheckUnpaddedMax(getLAccumSema());
+ CheckUnpaddedMax(getUSAccumSema());
+ CheckUnpaddedMax(getUAccumSema());
+ CheckUnpaddedMax(getULAccumSema());
+ CheckUnpaddedMax(getSFractSema());
+ CheckUnpaddedMax(getFractSema());
+ CheckUnpaddedMax(getLFractSema());
+ CheckUnpaddedMax(getUSFractSema());
+ CheckUnpaddedMax(getUFractSema());
+ CheckUnpaddedMax(getULFractSema());
+
+ CheckPaddedMax(getPadUSAccumSema());
+ CheckPaddedMax(getPadUAccumSema());
+ CheckPaddedMax(getPadULAccumSema());
+ CheckPaddedMax(getPadUSFractSema());
+ CheckPaddedMax(getPadUFractSema());
+ CheckPaddedMax(getPadULFractSema());
+}
+
+TEST(FixedPointTest, getMin) {
+ CheckMin(getSAccumSema());
+ CheckMin(getAccumSema());
+ CheckMin(getLAccumSema());
+ CheckMin(getUSAccumSema());
+ CheckMin(getUAccumSema());
+ CheckMin(getULAccumSema());
+ CheckMin(getSFractSema());
+ CheckMin(getFractSema());
+ CheckMin(getLFractSema());
+ CheckMin(getUSFractSema());
+ CheckMin(getUFractSema());
+ CheckMin(getULFractSema());
+
+ CheckMin(getPadUSAccumSema());
+ CheckMin(getPadUAccumSema());
+ CheckMin(getPadULAccumSema());
+ CheckMin(getPadUSFractSema());
+ CheckMin(getPadUFractSema());
+ CheckMin(getPadULFractSema());
+}
+
+void CheckIntPart(const FixedPointSemantics &Sema, int64_t IntPart) {
+ unsigned Scale = Sema.getScale();
+
+ // Value with a fraction
+ APFixedPoint ValWithFract(APInt(Sema.getWidth(),
+ (IntPart << Scale) + (1ULL << (Scale - 1)),
+ Sema.isSigned()),
+ Sema);
+ ASSERT_EQ(ValWithFract.getIntPart(), IntPart);
+
+ // Just fraction
+ APFixedPoint JustFract(
+ APInt(Sema.getWidth(), (1ULL << (Scale - 1)), Sema.isSigned()), Sema);
+ ASSERT_EQ(JustFract.getIntPart(), 0);
+
+ // Whole number
+ APFixedPoint WholeNum(
+ APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
+ ASSERT_EQ(WholeNum.getIntPart(), IntPart);
+
+ // Negative
+ if (Sema.isSigned()) {
+ APFixedPoint Negative(
+ APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
+ ASSERT_EQ(Negative.getIntPart(), IntPart);
+ }
+}
+
+void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {
+ ASSERT_EQ(APFixedPoint::getMin(Sema).getIntPart(), Expected);
+}
+
+void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {
+ ASSERT_EQ(APFixedPoint::getMax(Sema).getIntPart(), Expected);
+}
+
+TEST(FixedPoint, getIntPart) {
+ // Normal values
+ CheckIntPart(getSAccumSema(), 2);
+ CheckIntPart(getAccumSema(), 2);
+ CheckIntPart(getLAccumSema(), 2);
+ CheckIntPart(getUSAccumSema(), 2);
+ CheckIntPart(getUAccumSema(), 2);
+ CheckIntPart(getULAccumSema(), 2);
+
+ // Zero
+ CheckIntPart(getSAccumSema(), 0);
+ CheckIntPart(getAccumSema(), 0);
+ CheckIntPart(getLAccumSema(), 0);
+ CheckIntPart(getUSAccumSema(), 0);
+ CheckIntPart(getUAccumSema(), 0);
+ CheckIntPart(getULAccumSema(), 0);
+
+ CheckIntPart(getSFractSema(), 0);
+ CheckIntPart(getFractSema(), 0);
+ CheckIntPart(getLFractSema(), 0);
+ CheckIntPart(getUSFractSema(), 0);
+ CheckIntPart(getUFractSema(), 0);
+ CheckIntPart(getULFractSema(), 0);
+
+ // Min
+ CheckIntPartMin(getSAccumSema(), -256);
+ CheckIntPartMin(getAccumSema(), -65536);
+ CheckIntPartMin(getLAccumSema(), -4294967296);
+
+ CheckIntPartMin(getSFractSema(), -1);
+ CheckIntPartMin(getFractSema(), -1);
+ CheckIntPartMin(getLFractSema(), -1);
+
+ // Max
+ CheckIntPartMax(getSAccumSema(), 255);
+ CheckIntPartMax(getAccumSema(), 65535);
+ CheckIntPartMax(getLAccumSema(), 4294967295);
+ CheckIntPartMax(getUSAccumSema(), 255);
+ CheckIntPartMax(getUAccumSema(), 65535);
+ CheckIntPartMax(getULAccumSema(), 4294967295);
+
+ CheckIntPartMax(getSFractSema(), 0);
+ CheckIntPartMax(getFractSema(), 0);
+ CheckIntPartMax(getLFractSema(), 0);
+ CheckIntPartMax(getUSFractSema(), 0);
+ CheckIntPartMax(getUFractSema(), 0);
+ CheckIntPartMax(getULFractSema(), 0);
+
+ // Padded
+ // Normal Values
+ CheckIntPart(getPadUSAccumSema(), 2);
+ CheckIntPart(getPadUAccumSema(), 2);
+ CheckIntPart(getPadULAccumSema(), 2);
+
+ // Zero
+ CheckIntPart(getPadUSAccumSema(), 0);
+ CheckIntPart(getPadUAccumSema(), 0);
+ CheckIntPart(getPadULAccumSema(), 0);
+
+ CheckIntPart(getPadUSFractSema(), 0);
+ CheckIntPart(getPadUFractSema(), 0);
+ CheckIntPart(getPadULFractSema(), 0);
+
+ // Max
+ CheckIntPartMax(getPadUSAccumSema(), 255);
+ CheckIntPartMax(getPadUAccumSema(), 65535);
+ CheckIntPartMax(getPadULAccumSema(), 4294967295);
+
+ CheckIntPartMax(getPadUSFractSema(), 0);
+ CheckIntPartMax(getPadUFractSema(), 0);
+ CheckIntPartMax(getPadULFractSema(), 0);
+}
+
+TEST(FixedPoint, compare) {
+ // Equality
+ // With fractional part (2.5)
+ // Across sizes
+ ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
+ APFixedPoint(81920, getAccumSema()));
+ ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
+ APFixedPoint(5368709120, getLAccumSema()));
+ ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));
+
+ // Across types (0.5)
+ ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
+ APFixedPoint(64, getSFractSema()));
+ ASSERT_EQ(APFixedPoint(16384, getAccumSema()),
+ APFixedPoint(16384, getFractSema()));
+ ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),
+ APFixedPoint(1073741824, getLFractSema()));
+
+ // Across widths and types (0.5)
+ ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
+ APFixedPoint(16384, getFractSema()));
+ ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
+ APFixedPoint(1073741824, getLFractSema()));
+
+ // Across saturation
+ ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
+ APFixedPoint(81920, Saturated(getAccumSema())));
+
+ // Across signs
+ ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
+ APFixedPoint(640, getUSAccumSema()));
+ ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
+ APFixedPoint(-81920, getAccumSema()));
+
+ // Across padding
+ ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
+ APFixedPoint(320, getPadUSAccumSema()));
+ ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
+ APFixedPoint(320, getPadUSAccumSema()));
+
+ // Less than
+ ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));
+ ASSERT_LT(APFixedPoint(-1, getSAccumSema()),
+ APFixedPoint(0, getUAccumSema()));
+ ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));
+ ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));
+ ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));
+ ASSERT_LT(APFixedPoint(0, getUSAccumSema()),
+ APFixedPoint(1, getUAccumSema()));
+
+ // Greater than
+ ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));
+ ASSERT_GT(APFixedPoint(0, getUAccumSema()),
+ APFixedPoint(-1, getSAccumSema()));
+ ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));
+ ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));
+ ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));
+ ASSERT_GT(APFixedPoint(1, getUAccumSema()),
+ APFixedPoint(0, getUSAccumSema()));
+}
+
+// Check that a fixed point value in one sema is the same in another sema
+void CheckUnsaturatedConversion(FixedPointSemantics Src,
+ FixedPointSemantics Dst, int64_t TestVal) {
+ int64_t ScaledVal = TestVal;
+ bool IsNegative = ScaledVal < 0;
+ if (IsNegative)
+ ScaledVal = -ScaledVal;
+
+ if (Dst.getScale() > Src.getScale()) {
+ ScaledVal <<= (Dst.getScale() - Src.getScale());
+ } else {
+ ScaledVal >>= (Src.getScale() - Dst.getScale());
+ }
+
+ if (IsNegative)
+ ScaledVal = -ScaledVal;
+
+ APFixedPoint Fixed(TestVal, Src);
+ APFixedPoint Expected(ScaledVal, Dst);
+ ASSERT_EQ(Fixed.convert(Dst), Expected);
+}
+
+// Check the value in a given fixed point sema overflows to the saturated min
+// for another sema
+void CheckSaturatedConversionMin(FixedPointSemantics Src,
+ FixedPointSemantics Dst, int64_t TestVal) {
+ APFixedPoint Fixed(TestVal, Src);
+ ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMin(Dst));
+}
+
+// Check the value in a given fixed point sema overflows to the saturated max
+// for another sema
+void CheckSaturatedConversionMax(FixedPointSemantics Src,
+ FixedPointSemantics Dst, int64_t TestVal) {
+ APFixedPoint Fixed(TestVal, Src);
+ ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMax(Dst));
+}
+
+// Check one signed _Accum sema converted to other sema for different values.
+void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
+ int64_t OneVal) {
+ int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
+ int64_t HalfVal = (OneVal / 2); // 0.5
+
+ // +Accums to Accums
+ CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
+
+ // -Accums to Accums
+ CheckUnsaturatedConversion(Src, getSAccumSema(), -NormalVal);
+ CheckUnsaturatedConversion(Src, getAccumSema(), -NormalVal);
+ CheckUnsaturatedConversion(Src, getLAccumSema(), -NormalVal);
+ CheckSaturatedConversionMin(Src, Saturated(getUSAccumSema()), -NormalVal);
+ CheckSaturatedConversionMin(Src, Saturated(getUAccumSema()), -NormalVal);
+ CheckSaturatedConversionMin(Src, Saturated(getULAccumSema()), -NormalVal);
+ CheckSaturatedConversionMin(Src, Saturated(getPadUSAccumSema()), -NormalVal);
+ CheckSaturatedConversionMin(Src, Saturated(getPadUAccumSema()), -NormalVal);
+ CheckSaturatedConversionMin(Src, Saturated(getPadULAccumSema()), -NormalVal);
+
+ // +Accums to Fracts
+ CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
+
+ // -Accums to Fracts
+ CheckUnsaturatedConversion(Src, getSFractSema(), -HalfVal);
+ CheckUnsaturatedConversion(Src, getFractSema(), -HalfVal);
+ CheckUnsaturatedConversion(Src, getLFractSema(), -HalfVal);
+ CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), -HalfVal);
+ CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), -HalfVal);
+ CheckSaturatedConversionMin(Src, Saturated(getULFractSema()), -HalfVal);
+ CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), -HalfVal);
+ CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), -HalfVal);
+ CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), -HalfVal);
+
+ // 0 to Accums
+ CheckUnsaturatedConversion(Src, getSAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getLAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getUSAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getUAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getULAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getPadUSAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getPadUAccumSema(), 0);
+ CheckUnsaturatedConversion(Src, getPadULAccumSema(), 0);
+
+ // 0 to Fracts
+ CheckUnsaturatedConversion(Src, getSFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getLFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getUSFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getUFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getULFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getPadUSFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getPadUFractSema(), 0);
+ CheckUnsaturatedConversion(Src, getPadULFractSema(), 0);
+}
+
+// Check one unsigned _Accum sema converted to other sema for different
+// values.
+void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
+ int64_t OneVal) {
+ int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
+ int64_t HalfVal = (OneVal / 2); // 0.5
+
+ // +UAccums to Accums
+ CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
+ CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
+
+ // +UAccums to Fracts
+ CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
+ CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
+}
+
+TEST(FixedPoint, AccumConversions) {
+ // Normal conversions
+ CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);
+ CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);
+ CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);
+ CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);
+ CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);
+ CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);
+
+ CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);
+ CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);
+ CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);
+}
+
+TEST(FixedPoint, AccumConversionOverflow) {
+ // To SAccum max limit (65536)
+ CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),
+ 140737488355328);
+ CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
+ 140737488355328);
+ CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
+ 140737488355328);
+ CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
+ 281474976710656);
+ CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
+ 281474976710656);
+ CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
+ 281474976710656);
+
+ CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
+ 140737488355328);
+ CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
+ 140737488355328);
+ CheckSaturatedConversionMax(getPadULAccumSema(),
+ Saturated(getPadUAccumSema()), 140737488355328);
+
+ // To SAccum min limit (-65536)
+ CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
+ -140737488355328);
+ CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
+ -140737488355328);
+ CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
+ -140737488355328);
+}
+
+TEST(FixedPoint, SAccumConversionOverflow) {
+ // To SAccum max limit (256)
+ CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
+ 8388608);
+ CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
+ 8388608);
+ CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
+ 8388608);
+ CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
+ 16777216);
+ CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
+ 16777216);
+ CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
+ 16777216);
+ CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
+ 549755813888);
+ CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
+ 549755813888);
+ CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
+ 549755813888);
+ CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
+ 1099511627776);
+ CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
+ 1099511627776);
+ CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
+ 1099511627776);
+
+ CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
+ 8388608);
+ CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
+ 8388608);
+ CheckSaturatedConversionMax(getPadUAccumSema(),
+ Saturated(getPadUSAccumSema()), 8388608);
+ CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
+ 549755813888);
+ CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
+ 549755813888);
+ CheckSaturatedConversionMax(getPadULAccumSema(),
+ Saturated(getPadUSAccumSema()), 549755813888);
+
+ // To SAccum min limit (-256)
+ CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
+ -8388608);
+ CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
+ -8388608);
+ CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
+ -8388608);
+ CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
+ -549755813888);
+ CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
+ -549755813888);
+ CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
+ -549755813888);
+}
+
+TEST(FixedPoint, GetValueSignAfterConversion) {
+ APFixedPoint Fixed(255 << 7, getSAccumSema());
+ ASSERT_TRUE(Fixed.getValue().isSigned());
+ APFixedPoint UFixed = Fixed.convert(getUSAccumSema());
+ ASSERT_TRUE(UFixed.getValue().isUnsigned());
+ ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
+}
+
+TEST(FixedPoint, ModularWrapAround) {
+ // Positive to negative
+ APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema());
+ ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31));
+
+ Val = APFixedPoint(1ULL << 23, getAccumSema());
+ ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15));
+
+ Val = APFixedPoint(1ULL << 47, getLAccumSema());
+ ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31));
+
+ // Negative to positive
+ Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema());
+ ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30);
+
+ Val = APFixedPoint(-(257 << 15), getAccumSema());
+ ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7);
+
+ Val = APFixedPoint(-(65537ULL << 31), getLAccumSema());
+ ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15);
+
+ // Signed to unsigned
+ Val = APFixedPoint(-(1 << 7), getSAccumSema());
+ ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8);
+
+ Val = APFixedPoint(-(1 << 15), getAccumSema());
+ ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16);
+
+ Val = APFixedPoint(-(1ULL << 31), getLAccumSema());
+ ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(),
+ 4294967295ULL << 32);
+}
+
+} // namespace
diff --git a/unittests/Basic/SourceManagerTest.cpp b/unittests/Basic/SourceManagerTest.cpp
index 8457d3b639f2..b548bf575232 100644
--- a/unittests/Basic/SourceManagerTest.cpp
+++ b/unittests/Basic/SourceManagerTest.cpp
@@ -155,6 +155,54 @@ TEST_F(SourceManagerTest, getColumnNumber) {
EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, nullptr));
}
+TEST_F(SourceManagerTest, locationPrintTest) {
+ const char *header = "#define IDENTITY(x) x\n";
+
+ const char *Source = "int x;\n"
+ "include \"test-header.h\"\n"
+ "IDENTITY(int y);\n"
+ "int z;";
+
+ std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
+ llvm::MemoryBuffer::getMemBuffer(header);
+ std::unique_ptr<llvm::MemoryBuffer> Buf =
+ llvm::MemoryBuffer::getMemBuffer(Source);
+
+ const FileEntry *SourceFile =
+ FileMgr.getVirtualFile("/mainFile.cpp", Buf->getBufferSize(), 0);
+ SourceMgr.overrideFileContents(SourceFile, std::move(Buf));
+
+ const FileEntry *HeaderFile =
+ FileMgr.getVirtualFile("/test-header.h", HeaderBuf->getBufferSize(), 0);
+ SourceMgr.overrideFileContents(HeaderFile, std::move(HeaderBuf));
+
+ FileID MainFileID = SourceMgr.getOrCreateFileID(SourceFile, SrcMgr::C_User);
+ FileID HeaderFileID = SourceMgr.getOrCreateFileID(HeaderFile, SrcMgr::C_User);
+ SourceMgr.setMainFileID(MainFileID);
+
+ auto BeginLoc = SourceMgr.getLocForStartOfFile(MainFileID);
+ auto EndLoc = SourceMgr.getLocForEndOfFile(MainFileID);
+
+ auto BeginEOLLoc = SourceMgr.translateLineCol(MainFileID, 1, 7);
+
+ auto HeaderLoc = SourceMgr.getLocForStartOfFile(HeaderFileID);
+
+ EXPECT_EQ(BeginLoc.printToString(SourceMgr), "/mainFile.cpp:1:1");
+ EXPECT_EQ(EndLoc.printToString(SourceMgr), "/mainFile.cpp:4:7");
+
+ EXPECT_EQ(BeginEOLLoc.printToString(SourceMgr), "/mainFile.cpp:1:7");
+ EXPECT_EQ(HeaderLoc.printToString(SourceMgr), "/test-header.h:1:1");
+
+ EXPECT_EQ(SourceRange(BeginLoc, BeginLoc).printToString(SourceMgr),
+ "</mainFile.cpp:1:1>");
+ EXPECT_EQ(SourceRange(BeginLoc, BeginEOLLoc).printToString(SourceMgr),
+ "</mainFile.cpp:1:1, col:7>");
+ EXPECT_EQ(SourceRange(BeginLoc, EndLoc).printToString(SourceMgr),
+ "</mainFile.cpp:1:1, line:4:7>");
+ EXPECT_EQ(SourceRange(BeginLoc, HeaderLoc).printToString(SourceMgr),
+ "</mainFile.cpp:1:1, /test-header.h:1:1>");
+}
+
#if defined(LLVM_ON_UNIX)
TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
deleted file mode 100644
index c795be07acf1..000000000000
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ /dev/null
@@ -1,1431 +0,0 @@
-//===- unittests/Basic/VirtualFileSystem.cpp ---------------- VFS tests ---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Basic/VirtualFileSystem.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SourceMgr.h"
-#include "gtest/gtest.h"
-#include <map>
-
-using namespace clang;
-using namespace llvm;
-using llvm::sys::fs::UniqueID;
-
-namespace {
-struct DummyFile : public vfs::File {
- vfs::Status S;
- explicit DummyFile(vfs::Status S) : S(S) {}
- llvm::ErrorOr<vfs::Status> status() override { return S; }
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
- bool IsVolatile) override {
- llvm_unreachable("unimplemented");
- }
- std::error_code close() override { return std::error_code(); }
-};
-
-class DummyFileSystem : public vfs::FileSystem {
- int FSID; // used to produce UniqueIDs
- int FileID; // used to produce UniqueIDs
- std::map<std::string, vfs::Status> FilesAndDirs;
-
- static int getNextFSID() {
- static int Count = 0;
- return Count++;
- }
-
-public:
- DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
-
- ErrorOr<vfs::Status> status(const Twine &Path) override {
- std::map<std::string, vfs::Status>::iterator I =
- FilesAndDirs.find(Path.str());
- if (I == FilesAndDirs.end())
- return make_error_code(llvm::errc::no_such_file_or_directory);
- return I->second;
- }
- ErrorOr<std::unique_ptr<vfs::File>>
- openFileForRead(const Twine &Path) override {
- auto S = status(Path);
- if (S)
- return std::unique_ptr<vfs::File>(new DummyFile{*S});
- return S.getError();
- }
- llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
- return std::string();
- }
- std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
- return std::error_code();
- }
- // Map any symlink to "/symlink".
- std::error_code getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const override {
- auto I = FilesAndDirs.find(Path.str());
- if (I == FilesAndDirs.end())
- return make_error_code(llvm::errc::no_such_file_or_directory);
- if (I->second.isSymlink()) {
- Output.clear();
- Twine("/symlink").toVector(Output);
- return std::error_code();
- }
- Output.clear();
- Path.toVector(Output);
- return std::error_code();
- }
-
- struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
- std::map<std::string, vfs::Status> &FilesAndDirs;
- std::map<std::string, vfs::Status>::iterator I;
- std::string Path;
- bool isInPath(StringRef S) {
- if (Path.size() < S.size() && S.find(Path) == 0) {
- auto LastSep = S.find_last_of('/');
- if (LastSep == Path.size() || LastSep == Path.size()-1)
- return true;
- }
- return false;
- }
- DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
- const Twine &_Path)
- : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
- Path(_Path.str()) {
- for ( ; I != FilesAndDirs.end(); ++I) {
- if (isInPath(I->first)) {
- CurrentEntry = I->second;
- break;
- }
- }
- }
- std::error_code increment() override {
- ++I;
- for ( ; I != FilesAndDirs.end(); ++I) {
- if (isInPath(I->first)) {
- CurrentEntry = I->second;
- break;
- }
- }
- if (I == FilesAndDirs.end())
- CurrentEntry = vfs::Status();
- return std::error_code();
- }
- };
-
- vfs::directory_iterator dir_begin(const Twine &Dir,
- std::error_code &EC) override {
- return vfs::directory_iterator(
- std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
- }
-
- void addEntry(StringRef Path, const vfs::Status &Status) {
- FilesAndDirs[Path] = Status;
- }
-
- void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
- vfs::Status S(Path, UniqueID(FSID, FileID++),
- std::chrono::system_clock::now(), 0, 0, 1024,
- sys::fs::file_type::regular_file, Perms);
- addEntry(Path, S);
- }
-
- void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
- vfs::Status S(Path, UniqueID(FSID, FileID++),
- std::chrono::system_clock::now(), 0, 0, 0,
- sys::fs::file_type::directory_file, Perms);
- addEntry(Path, S);
- }
-
- void addSymlink(StringRef Path) {
- vfs::Status S(Path, UniqueID(FSID, FileID++),
- std::chrono::system_clock::now(), 0, 0, 0,
- sys::fs::file_type::symlink_file, sys::fs::all_all);
- addEntry(Path, S);
- }
-};
-} // end anonymous namespace
-
-TEST(VirtualFileSystemTest, StatusQueries) {
- IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
- ErrorOr<vfs::Status> Status((std::error_code()));
-
- D->addRegularFile("/foo");
- Status = D->status("/foo");
- ASSERT_FALSE(Status.getError());
- EXPECT_TRUE(Status->isStatusKnown());
- EXPECT_FALSE(Status->isDirectory());
- EXPECT_TRUE(Status->isRegularFile());
- EXPECT_FALSE(Status->isSymlink());
- EXPECT_FALSE(Status->isOther());
- EXPECT_TRUE(Status->exists());
-
- D->addDirectory("/bar");
- Status = D->status("/bar");
- ASSERT_FALSE(Status.getError());
- EXPECT_TRUE(Status->isStatusKnown());
- EXPECT_TRUE(Status->isDirectory());
- EXPECT_FALSE(Status->isRegularFile());
- EXPECT_FALSE(Status->isSymlink());
- EXPECT_FALSE(Status->isOther());
- EXPECT_TRUE(Status->exists());
-
- D->addSymlink("/baz");
- Status = D->status("/baz");
- ASSERT_FALSE(Status.getError());
- EXPECT_TRUE(Status->isStatusKnown());
- EXPECT_FALSE(Status->isDirectory());
- EXPECT_FALSE(Status->isRegularFile());
- EXPECT_TRUE(Status->isSymlink());
- EXPECT_FALSE(Status->isOther());
- EXPECT_TRUE(Status->exists());
-
- EXPECT_TRUE(Status->equivalent(*Status));
- ErrorOr<vfs::Status> Status2 = D->status("/foo");
- ASSERT_FALSE(Status2.getError());
- EXPECT_FALSE(Status->equivalent(*Status2));
-}
-
-TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
- IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
- ErrorOr<vfs::Status> Status((std::error_code()));
- EXPECT_FALSE(Status = D->status("/foo"));
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
- EXPECT_FALSE(Status = O->status("/foo"));
-
- D->addRegularFile("/foo");
- Status = D->status("/foo");
- EXPECT_FALSE(Status.getError());
-
- ErrorOr<vfs::Status> Status2((std::error_code()));
- Status2 = O->status("/foo");
- EXPECT_FALSE(Status2.getError());
- EXPECT_TRUE(Status->equivalent(*Status2));
-}
-
-TEST(VirtualFileSystemTest, GetRealPathInOverlay) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addRegularFile("/foo");
- Lower->addSymlink("/lower_link");
- IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(Upper);
-
- // Regular file.
- SmallString<16> RealPath;
- EXPECT_FALSE(O->getRealPath("/foo", RealPath));
- EXPECT_EQ(RealPath.str(), "/foo");
-
- // Expect no error getting real path for symlink in lower overlay.
- EXPECT_FALSE(O->getRealPath("/lower_link", RealPath));
- EXPECT_EQ(RealPath.str(), "/symlink");
-
- // Try a non-existing link.
- EXPECT_EQ(O->getRealPath("/upper_link", RealPath),
- errc::no_such_file_or_directory);
-
- // Add a new symlink in upper.
- Upper->addSymlink("/upper_link");
- EXPECT_FALSE(O->getRealPath("/upper_link", RealPath));
- EXPECT_EQ(RealPath.str(), "/symlink");
-}
-
-TEST(VirtualFileSystemTest, OverlayFiles) {
- IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Base));
- O->pushOverlay(Middle);
- O->pushOverlay(Top);
-
- ErrorOr<vfs::Status> Status1((std::error_code())),
- Status2((std::error_code())), Status3((std::error_code())),
- StatusB((std::error_code())), StatusM((std::error_code())),
- StatusT((std::error_code()));
-
- Base->addRegularFile("/foo");
- StatusB = Base->status("/foo");
- ASSERT_FALSE(StatusB.getError());
- Status1 = O->status("/foo");
- ASSERT_FALSE(Status1.getError());
- Middle->addRegularFile("/foo");
- StatusM = Middle->status("/foo");
- ASSERT_FALSE(StatusM.getError());
- Status2 = O->status("/foo");
- ASSERT_FALSE(Status2.getError());
- Top->addRegularFile("/foo");
- StatusT = Top->status("/foo");
- ASSERT_FALSE(StatusT.getError());
- Status3 = O->status("/foo");
- ASSERT_FALSE(Status3.getError());
-
- EXPECT_TRUE(Status1->equivalent(*StatusB));
- EXPECT_TRUE(Status2->equivalent(*StatusM));
- EXPECT_TRUE(Status3->equivalent(*StatusT));
-
- EXPECT_FALSE(Status1->equivalent(*Status2));
- EXPECT_FALSE(Status2->equivalent(*Status3));
- EXPECT_FALSE(Status1->equivalent(*Status3));
-}
-
-TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(Upper);
-
- Lower->addDirectory("/lower-only");
- Upper->addDirectory("/upper-only");
-
- // non-merged paths should be the same
- ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
- ASSERT_FALSE(Status1.getError());
- ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
- ASSERT_FALSE(Status2.getError());
- EXPECT_TRUE(Status1->equivalent(*Status2));
-
- Status1 = Upper->status("/upper-only");
- ASSERT_FALSE(Status1.getError());
- Status2 = O->status("/upper-only");
- ASSERT_FALSE(Status2.getError());
- EXPECT_TRUE(Status1->equivalent(*Status2));
-}
-
-TEST(VirtualFileSystemTest, MergedDirPermissions) {
- // merged directories get the permissions of the upper dir
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(Upper);
-
- ErrorOr<vfs::Status> Status((std::error_code()));
- Lower->addDirectory("/both", sys::fs::owner_read);
- Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
- Status = O->status("/both");
- ASSERT_FALSE(Status.getError());
- EXPECT_EQ(0740, Status->getPermissions());
-
- // permissions (as usual) are not recursively applied
- Lower->addRegularFile("/both/foo", sys::fs::owner_read);
- Upper->addRegularFile("/both/bar", sys::fs::owner_write);
- Status = O->status("/both/foo");
- ASSERT_FALSE( Status.getError());
- EXPECT_EQ(0400, Status->getPermissions());
- Status = O->status("/both/bar");
- ASSERT_FALSE(Status.getError());
- EXPECT_EQ(0200, Status->getPermissions());
-}
-
-namespace {
-struct ScopedDir {
- SmallString<128> Path;
- ScopedDir(const Twine &Name, bool Unique=false) {
- std::error_code EC;
- if (Unique) {
- EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
- } else {
- Path = Name.str();
- EC = llvm::sys::fs::create_directory(Twine(Path));
- }
- if (EC)
- Path = "";
- EXPECT_FALSE(EC);
- }
- ~ScopedDir() {
- if (Path != "") {
- EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
- }
- }
- operator StringRef() { return Path.str(); }
-};
-
-struct ScopedLink {
- SmallString<128> Path;
- ScopedLink(const Twine &To, const Twine &From) {
- Path = From.str();
- std::error_code EC = sys::fs::create_link(To, From);
- if (EC)
- Path = "";
- EXPECT_FALSE(EC);
- }
- ~ScopedLink() {
- if (Path != "") {
- EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
- }
- }
- operator StringRef() { return Path.str(); }
-};
-} // end anonymous namespace
-
-TEST(VirtualFileSystemTest, BasicRealFSIteration) {
- ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
- IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
-
- std::error_code EC;
- vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
- ASSERT_FALSE(EC);
- EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
-
- ScopedDir _a(TestDirectory+"/a");
- ScopedDir _ab(TestDirectory+"/a/b");
- ScopedDir _c(TestDirectory+"/c");
- ScopedDir _cd(TestDirectory+"/c/d");
-
- I = FS->dir_begin(Twine(TestDirectory), EC);
- ASSERT_FALSE(EC);
- ASSERT_NE(vfs::directory_iterator(), I);
- // Check either a or c, since we can't rely on the iteration order.
- EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
- I.increment(EC);
- ASSERT_FALSE(EC);
- ASSERT_NE(vfs::directory_iterator(), I);
- EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
- I.increment(EC);
- EXPECT_EQ(vfs::directory_iterator(), I);
-}
-
-#ifdef LLVM_ON_UNIX
-TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) {
- ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
- IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
-
- ScopedLink _a("no_such_file", TestDirectory + "/a");
- ScopedDir _b(TestDirectory + "/b");
- ScopedLink _c("no_such_file", TestDirectory + "/c");
-
- std::error_code EC;
- for (vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC), E;
- I != E; I.increment(EC)) {
- // Skip broken symlinks.
- auto EC2 = std::make_error_code(std::errc::no_such_file_or_directory);
- if (EC == EC2) {
- EC.clear();
- continue;
- }
- // For bot debugging.
- if (EC) {
- outs() << "Error code found:\n"
- << "EC value: " << EC.value() << "\n"
- << "EC category: " << EC.category().name()
- << "EC message: " << EC.message() << "\n";
-
- outs() << "Error code tested for:\n"
- << "EC value: " << EC2.value() << "\n"
- << "EC category: " << EC2.category().name()
- << "EC message: " << EC2.message() << "\n";
- }
- ASSERT_FALSE(EC);
- EXPECT_TRUE(I->getName() == _b);
- }
-}
-#endif
-
-TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
- ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
- IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
-
- std::error_code EC;
- auto I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
- ASSERT_FALSE(EC);
- EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty
-
- ScopedDir _a(TestDirectory+"/a");
- ScopedDir _ab(TestDirectory+"/a/b");
- ScopedDir _c(TestDirectory+"/c");
- ScopedDir _cd(TestDirectory+"/c/d");
-
- I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
- ASSERT_FALSE(EC);
- ASSERT_NE(vfs::recursive_directory_iterator(), I);
-
- std::vector<std::string> Contents;
- for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
- I.increment(EC)) {
- Contents.push_back(I->getName());
- }
-
- // Check contents, which may be in any order
- EXPECT_EQ(4U, Contents.size());
- int Counts[4] = { 0, 0, 0, 0 };
- for (const std::string &Name : Contents) {
- ASSERT_FALSE(Name.empty());
- int Index = Name[Name.size()-1] - 'a';
- ASSERT_TRUE(Index >= 0 && Index < 4);
- Counts[Index]++;
- }
- EXPECT_EQ(1, Counts[0]); // a
- EXPECT_EQ(1, Counts[1]); // b
- EXPECT_EQ(1, Counts[2]); // c
- EXPECT_EQ(1, Counts[3]); // d
-}
-
-#ifdef LLVM_ON_UNIX
-TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
- ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
- IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
-
- ScopedLink _a("no_such_file", TestDirectory + "/a");
- ScopedDir _b(TestDirectory + "/b");
- ScopedLink _ba("no_such_file", TestDirectory + "/b/a");
- ScopedDir _bb(TestDirectory + "/b/b");
- ScopedLink _bc("no_such_file", TestDirectory + "/b/c");
- ScopedLink _c("no_such_file", TestDirectory + "/c");
- ScopedDir _d(TestDirectory + "/d");
- ScopedDir _dd(TestDirectory + "/d/d");
- ScopedDir _ddd(TestDirectory + "/d/d/d");
- ScopedLink _e("no_such_file", TestDirectory + "/e");
-
- std::vector<StringRef> ExpectedBrokenSymlinks = {_a, _ba, _bc, _c, _e};
- std::vector<StringRef> ExpectedNonBrokenSymlinks = {_b, _bb, _d, _dd, _ddd};
- std::vector<std::string> VisitedBrokenSymlinks;
- std::vector<std::string> VisitedNonBrokenSymlinks;
- std::error_code EC;
- for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E;
- I != E; I.increment(EC)) {
- auto EC2 = std::make_error_code(std::errc::no_such_file_or_directory);
- if (EC == EC2) {
- VisitedBrokenSymlinks.push_back(I->getName());
- continue;
- }
- // For bot debugging.
- if (EC) {
- outs() << "Error code found:\n"
- << "EC value: " << EC.value() << "\n"
- << "EC category: " << EC.category().name()
- << "EC message: " << EC.message() << "\n";
-
- outs() << "Error code tested for:\n"
- << "EC value: " << EC2.value() << "\n"
- << "EC category: " << EC2.category().name()
- << "EC message: " << EC2.message() << "\n";
- }
- ASSERT_FALSE(EC);
- VisitedNonBrokenSymlinks.push_back(I->getName());
- }
-
- // Check visited file names.
- std::sort(VisitedBrokenSymlinks.begin(), VisitedBrokenSymlinks.end());
- std::sort(VisitedNonBrokenSymlinks.begin(), VisitedNonBrokenSymlinks.end());
- EXPECT_EQ(ExpectedBrokenSymlinks.size(), VisitedBrokenSymlinks.size());
- EXPECT_TRUE(std::equal(VisitedBrokenSymlinks.begin(),
- VisitedBrokenSymlinks.end(),
- ExpectedBrokenSymlinks.begin()));
- EXPECT_EQ(ExpectedNonBrokenSymlinks.size(), VisitedNonBrokenSymlinks.size());
- EXPECT_TRUE(std::equal(VisitedNonBrokenSymlinks.begin(),
- VisitedNonBrokenSymlinks.end(),
- ExpectedNonBrokenSymlinks.begin()));
-}
-#endif
-
-template <typename DirIter>
-static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
- std::error_code EC;
- SmallVector<StringRef, 4> Expected(ExpectedOut.begin(), ExpectedOut.end());
- SmallVector<std::string, 4> InputToCheck;
-
- // Do not rely on iteration order to check for contents, sort both
- // content vectors before comparison.
- for (DirIter E; !EC && I != E; I.increment(EC))
- InputToCheck.push_back(I->getName());
-
- llvm::sort(InputToCheck.begin(), InputToCheck.end());
- llvm::sort(Expected.begin(), Expected.end());
- EXPECT_EQ(InputToCheck.size(), Expected.size());
-
- unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
- for (unsigned Idx = 0; Idx != LastElt; ++Idx)
- EXPECT_EQ(StringRef(InputToCheck[Idx]), Expected[Idx]);
-}
-
-TEST(VirtualFileSystemTest, OverlayIteration) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(Upper);
-
- std::error_code EC;
- checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
-
- Lower->addRegularFile("/file1");
- checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
-
- Upper->addRegularFile("/file2");
- checkContents(O->dir_begin("/", EC), {"/file2", "/file1"});
-
- Lower->addDirectory("/dir1");
- Lower->addRegularFile("/dir1/foo");
- Upper->addDirectory("/dir2");
- Upper->addRegularFile("/dir2/foo");
- checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
- checkContents(O->dir_begin("/", EC), {"/dir2", "/file2", "/dir1", "/file1"});
-}
-
-TEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(Middle);
- O->pushOverlay(Upper);
-
- std::error_code EC;
- checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
- ArrayRef<StringRef>());
-
- Lower->addRegularFile("/file1");
- checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
- ArrayRef<StringRef>("/file1"));
-
- Upper->addDirectory("/dir");
- Upper->addRegularFile("/dir/file2");
- checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
- {"/dir", "/dir/file2", "/file1"});
-
- Lower->addDirectory("/dir1");
- Lower->addRegularFile("/dir1/foo");
- Lower->addDirectory("/dir1/a");
- Lower->addRegularFile("/dir1/a/b");
- Middle->addDirectory("/a");
- Middle->addDirectory("/a/b");
- Middle->addDirectory("/a/b/c");
- Middle->addRegularFile("/a/b/c/d");
- Middle->addRegularFile("/hiddenByUp");
- Upper->addDirectory("/dir2");
- Upper->addRegularFile("/dir2/foo");
- Upper->addRegularFile("/hiddenByUp");
- checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
- ArrayRef<StringRef>("/dir2/foo"));
- checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
- {"/dir", "/dir/file2", "/dir2", "/dir2/foo", "/hiddenByUp",
- "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
- "/dir1/a/b", "/dir1/foo", "/file1"});
-}
-
-TEST(VirtualFileSystemTest, ThreeLevelIteration) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(Middle);
- O->pushOverlay(Upper);
-
- std::error_code EC;
- checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
-
- Middle->addRegularFile("/file2");
- checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
-
- Lower->addRegularFile("/file1");
- Upper->addRegularFile("/file3");
- checkContents(O->dir_begin("/", EC), {"/file3", "/file2", "/file1"});
-}
-
-TEST(VirtualFileSystemTest, HiddenInIteration) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
- IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(Middle);
- O->pushOverlay(Upper);
-
- std::error_code EC;
- Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
- Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
- Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
- Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
- Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
- Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
- Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
- Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
- checkContents(
- O->dir_begin("/", EC),
- {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"});
-
- // Make sure we get the top-most entry
- {
- std::error_code EC;
- vfs::directory_iterator I = O->dir_begin("/", EC), E;
- for ( ; !EC && I != E; I.increment(EC))
- if (I->getName() == "/hiddenByUp")
- break;
- ASSERT_NE(E, I);
- EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
- }
- {
- std::error_code EC;
- vfs::directory_iterator I = O->dir_begin("/", EC), E;
- for ( ; !EC && I != E; I.increment(EC))
- if (I->getName() == "/hiddenByMid")
- break;
- ASSERT_NE(E, I);
- EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
- }
-}
-
-class InMemoryFileSystemTest : public ::testing::Test {
-protected:
- clang::vfs::InMemoryFileSystem FS;
- clang::vfs::InMemoryFileSystem NormalizedFS;
-
- InMemoryFileSystemTest()
- : FS(/*UseNormalizedPaths=*/false),
- NormalizedFS(/*UseNormalizedPaths=*/true) {}
-};
-
-TEST_F(InMemoryFileSystemTest, IsEmpty) {
- auto Stat = FS.status("/a");
- ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
- Stat = FS.status("/");
- ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
-}
-
-TEST_F(InMemoryFileSystemTest, WindowsPath) {
- FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
- auto Stat = FS.status("c:");
-#if !defined(_WIN32)
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
-#endif
- Stat = FS.status("c:/windows/system128/foo.cpp");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
- FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
- Stat = FS.status("d:/windows/foo.cpp");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
-}
-
-TEST_F(InMemoryFileSystemTest, OverlayFile) {
- FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
- NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
- auto Stat = FS.status("/");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
- Stat = FS.status("/.");
- ASSERT_FALSE(Stat);
- Stat = NormalizedFS.status("/.");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
- Stat = FS.status("/a");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_EQ("/a", Stat->getName());
-}
-
-TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
- auto Buf = MemoryBuffer::getMemBuffer("a");
- FS.addFileNoOwn("/a", 0, Buf.get());
- auto Stat = FS.status("/a");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_EQ("/a", Stat->getName());
-}
-
-TEST_F(InMemoryFileSystemTest, OpenFileForRead) {
- FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
- FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
- FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
- NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
- NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
- NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
- auto File = FS.openFileForRead("/a");
- ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
- File = FS.openFileForRead("/a"); // Open again.
- ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
- File = NormalizedFS.openFileForRead("/././a"); // Open again.
- ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
- File = FS.openFileForRead("/");
- ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
- File = FS.openFileForRead("/b");
- ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
- File = FS.openFileForRead("./c");
- ASSERT_FALSE(File);
- File = FS.openFileForRead("e/../d");
- ASSERT_FALSE(File);
- File = NormalizedFS.openFileForRead("./c");
- ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
- File = NormalizedFS.openFileForRead("e/../d");
- ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
-}
-
-TEST_F(InMemoryFileSystemTest, DuplicatedFile) {
- ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
- ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
- ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
- ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
-}
-
-TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
- FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
- FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
-
- std::error_code EC;
- vfs::directory_iterator I = FS.dir_begin("/", EC);
- ASSERT_FALSE(EC);
- ASSERT_EQ("/a", I->getName());
- I.increment(EC);
- ASSERT_FALSE(EC);
- ASSERT_EQ("/b", I->getName());
- I.increment(EC);
- ASSERT_FALSE(EC);
- ASSERT_EQ(vfs::directory_iterator(), I);
-
- I = FS.dir_begin("/b", EC);
- ASSERT_FALSE(EC);
- ASSERT_EQ("/b/c", I->getName());
- I.increment(EC);
- ASSERT_FALSE(EC);
- ASSERT_EQ(vfs::directory_iterator(), I);
-}
-
-TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
- FS.setCurrentWorkingDirectory("/b");
- FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
-
- auto Stat = FS.status("/b/c");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_EQ("c", Stat->getName());
- ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
-
- Stat = FS.status("c");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
-
- auto ReplaceBackslashes = [](std::string S) {
- std::replace(S.begin(), S.end(), '\\', '/');
- return S;
- };
- NormalizedFS.setCurrentWorkingDirectory("/b/c");
- NormalizedFS.setCurrentWorkingDirectory(".");
- ASSERT_EQ("/b/c", ReplaceBackslashes(
- NormalizedFS.getCurrentWorkingDirectory().get()));
- NormalizedFS.setCurrentWorkingDirectory("..");
- ASSERT_EQ("/b", ReplaceBackslashes(
- NormalizedFS.getCurrentWorkingDirectory().get()));
-}
-
-#if !defined(_WIN32)
-TEST_F(InMemoryFileSystemTest, GetRealPath) {
- SmallString<16> Path;
- EXPECT_EQ(FS.getRealPath("b", Path), errc::operation_not_permitted);
-
- auto GetRealPath = [this](StringRef P) {
- SmallString<16> Output;
- auto EC = FS.getRealPath(P, Output);
- EXPECT_FALSE(EC);
- return Output.str().str();
- };
-
- FS.setCurrentWorkingDirectory("a");
- EXPECT_EQ(GetRealPath("b"), "a/b");
- EXPECT_EQ(GetRealPath("../b"), "b");
- EXPECT_EQ(GetRealPath("b/./c"), "a/b/c");
-
- FS.setCurrentWorkingDirectory("/a");
- EXPECT_EQ(GetRealPath("b"), "/a/b");
- EXPECT_EQ(GetRealPath("../b"), "/b");
- EXPECT_EQ(GetRealPath("b/./c"), "/a/b/c");
-}
-#endif // _WIN32
-
-TEST_F(InMemoryFileSystemTest, AddFileWithUser) {
- FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 0xFEEDFACE);
- auto Stat = FS.status("/a");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- ASSERT_EQ(0xFEEDFACE, Stat->getUser());
- Stat = FS.status("/a/b");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- ASSERT_EQ(0xFEEDFACE, Stat->getUser());
- Stat = FS.status("/a/b/c");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isRegularFile());
- ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
- ASSERT_EQ(0xFEEDFACE, Stat->getUser());
-}
-
-TEST_F(InMemoryFileSystemTest, AddFileWithGroup) {
- FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, 0xDABBAD00);
- auto Stat = FS.status("/a");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- ASSERT_EQ(0xDABBAD00, Stat->getGroup());
- Stat = FS.status("/a/b");
- ASSERT_TRUE(Stat->isDirectory());
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_EQ(0xDABBAD00, Stat->getGroup());
- Stat = FS.status("/a/b/c");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isRegularFile());
- ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
- ASSERT_EQ(0xDABBAD00, Stat->getGroup());
-}
-
-TEST_F(InMemoryFileSystemTest, AddFileWithFileType) {
- FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None,
- sys::fs::file_type::socket_file);
- auto Stat = FS.status("/a");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- Stat = FS.status("/a/b");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- Stat = FS.status("/a/b/c");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_EQ(sys::fs::file_type::socket_file, Stat->getType());
- ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
-}
-
-TEST_F(InMemoryFileSystemTest, AddFileWithPerms) {
- FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None,
- None, sys::fs::perms::owner_read | sys::fs::perms::owner_write);
- auto Stat = FS.status("/a");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write |
- sys::fs::perms::owner_exe, Stat->getPermissions());
- Stat = FS.status("/a/b");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write |
- sys::fs::perms::owner_exe, Stat->getPermissions());
- Stat = FS.status("/a/b/c");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isRegularFile());
- ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write,
- Stat->getPermissions());
-}
-
-TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) {
- FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""), /*User=*/None,
- /*Group=*/None, sys::fs::file_type::directory_file);
- FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("abc"), /*User=*/None,
- /*Group=*/None, sys::fs::file_type::regular_file);
- auto Stat = FS.status("/a");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isDirectory());
- Stat = FS.status("/a/b");
- ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
- ASSERT_TRUE(Stat->isRegularFile());
-}
-
-// NOTE: in the tests below, we use '//root/' as our root directory, since it is
-// a legal *absolute* path on Windows as well as *nix.
-class VFSFromYAMLTest : public ::testing::Test {
-public:
- int NumDiagnostics;
-
- void SetUp() override { NumDiagnostics = 0; }
-
- static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
- VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
- ++Test->NumDiagnostics;
- }
-
- IntrusiveRefCntPtr<vfs::FileSystem>
- getFromYAMLRawString(StringRef Content,
- IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
- std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
- return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this,
- ExternalFS);
- }
-
- IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
- StringRef Content,
- IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
- std::string VersionPlusContent("{\n 'version':0,\n");
- VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
- return getFromYAMLRawString(VersionPlusContent, ExternalFS);
- }
-
- // This is intended as a "XFAIL" for windows hosts.
- bool supportsSameDirMultipleYAMLEntries() {
- Triple Host(Triple::normalize(sys::getProcessTriple()));
- return !Host.isOSWindows();
- }
-};
-
-TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
- IntrusiveRefCntPtr<vfs::FileSystem> FS;
- FS = getFromYAMLString("");
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString("[]");
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString("'string'");
- EXPECT_EQ(nullptr, FS.get());
- EXPECT_EQ(3, NumDiagnostics);
-}
-
-TEST_F(VFSFromYAMLTest, MappedFiles) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addRegularFile("//root/foo/bar/a");
- IntrusiveRefCntPtr<vfs::FileSystem> FS =
- getFromYAMLString("{ 'roots': [\n"
- "{\n"
- " 'type': 'directory',\n"
- " 'name': '//root/',\n"
- " 'contents': [ {\n"
- " 'type': 'file',\n"
- " 'name': 'file1',\n"
- " 'external-contents': '//root/foo/bar/a'\n"
- " },\n"
- " {\n"
- " 'type': 'file',\n"
- " 'name': 'file2',\n"
- " 'external-contents': '//root/foo/b'\n"
- " }\n"
- " ]\n"
- "}\n"
- "]\n"
- "}",
- Lower);
- ASSERT_TRUE(FS.get() != nullptr);
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(FS);
-
- // file
- ErrorOr<vfs::Status> S = O->status("//root/file1");
- ASSERT_FALSE(S.getError());
- EXPECT_EQ("//root/foo/bar/a", S->getName());
- EXPECT_TRUE(S->IsVFSMapped);
-
- ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
- EXPECT_EQ("//root/foo/bar/a", SLower->getName());
- EXPECT_TRUE(S->equivalent(*SLower));
- EXPECT_FALSE(SLower->IsVFSMapped);
-
- // file after opening
- auto OpenedF = O->openFileForRead("//root/file1");
- ASSERT_FALSE(OpenedF.getError());
- auto OpenedS = (*OpenedF)->status();
- ASSERT_FALSE(OpenedS.getError());
- EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
- EXPECT_TRUE(OpenedS->IsVFSMapped);
-
- // directory
- S = O->status("//root/");
- ASSERT_FALSE(S.getError());
- EXPECT_TRUE(S->isDirectory());
- EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
-
- // broken mapping
- EXPECT_EQ(O->status("//root/file2").getError(),
- llvm::errc::no_such_file_or_directory);
- EXPECT_EQ(0, NumDiagnostics);
-}
-
-TEST_F(VFSFromYAMLTest, CaseInsensitive) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addRegularFile("//root/foo/bar/a");
- IntrusiveRefCntPtr<vfs::FileSystem> FS =
- getFromYAMLString("{ 'case-sensitive': 'false',\n"
- " 'roots': [\n"
- "{\n"
- " 'type': 'directory',\n"
- " 'name': '//root/',\n"
- " 'contents': [ {\n"
- " 'type': 'file',\n"
- " 'name': 'XX',\n"
- " 'external-contents': '//root/foo/bar/a'\n"
- " }\n"
- " ]\n"
- "}]}",
- Lower);
- ASSERT_TRUE(FS.get() != nullptr);
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(FS);
-
- ErrorOr<vfs::Status> S = O->status("//root/XX");
- ASSERT_FALSE(S.getError());
-
- ErrorOr<vfs::Status> SS = O->status("//root/xx");
- ASSERT_FALSE(SS.getError());
- EXPECT_TRUE(S->equivalent(*SS));
- SS = O->status("//root/xX");
- EXPECT_TRUE(S->equivalent(*SS));
- SS = O->status("//root/Xx");
- EXPECT_TRUE(S->equivalent(*SS));
- EXPECT_EQ(0, NumDiagnostics);
-}
-
-TEST_F(VFSFromYAMLTest, CaseSensitive) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addRegularFile("//root/foo/bar/a");
- IntrusiveRefCntPtr<vfs::FileSystem> FS =
- getFromYAMLString("{ 'case-sensitive': 'true',\n"
- " 'roots': [\n"
- "{\n"
- " 'type': 'directory',\n"
- " 'name': '//root/',\n"
- " 'contents': [ {\n"
- " 'type': 'file',\n"
- " 'name': 'XX',\n"
- " 'external-contents': '//root/foo/bar/a'\n"
- " }\n"
- " ]\n"
- "}]}",
- Lower);
- ASSERT_TRUE(FS.get() != nullptr);
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(FS);
-
- ErrorOr<vfs::Status> SS = O->status("//root/xx");
- EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
- SS = O->status("//root/xX");
- EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
- SS = O->status("//root/Xx");
- EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
- EXPECT_EQ(0, NumDiagnostics);
-}
-
-TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
-
- // invalid YAML at top-level
- IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
- EXPECT_EQ(nullptr, FS.get());
- // invalid YAML in roots
- FS = getFromYAMLString("{ 'roots':[}", Lower);
- // invalid YAML in directory
- FS = getFromYAMLString(
- "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
-
- // invalid configuration
- FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
-
- // invalid roots
- FS = getFromYAMLString("{ 'roots':'' }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString("{ 'roots':{} }", Lower);
- EXPECT_EQ(nullptr, FS.get());
-
- // invalid entries
- FS = getFromYAMLString(
- "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
- "'external-contents': 'other' }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString(
- "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString(
- "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString(
- "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString(
- "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString(
- "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
-
- // missing mandatory fields
- FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString(
- "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
-
- // duplicate keys
- FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLString(
- "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS =
- getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
- "'external-contents':'blah' } ] }",
- Lower);
- EXPECT_EQ(nullptr, FS.get());
-
- // missing version
- FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
-
- // bad version number
- FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
- EXPECT_EQ(nullptr, FS.get());
- EXPECT_EQ(24, NumDiagnostics);
-}
-
-TEST_F(VFSFromYAMLTest, UseExternalName) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addRegularFile("//root/external/file");
-
- IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
- "{ 'roots': [\n"
- " { 'type': 'file', 'name': '//root/A',\n"
- " 'external-contents': '//root/external/file'\n"
- " },\n"
- " { 'type': 'file', 'name': '//root/B',\n"
- " 'use-external-name': true,\n"
- " 'external-contents': '//root/external/file'\n"
- " },\n"
- " { 'type': 'file', 'name': '//root/C',\n"
- " 'use-external-name': false,\n"
- " 'external-contents': '//root/external/file'\n"
- " }\n"
- "] }", Lower);
- ASSERT_TRUE(nullptr != FS.get());
-
- // default true
- EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
- // explicit
- EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
- EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
-
- // global configuration
- FS = getFromYAMLString(
- "{ 'use-external-names': false,\n"
- " 'roots': [\n"
- " { 'type': 'file', 'name': '//root/A',\n"
- " 'external-contents': '//root/external/file'\n"
- " },\n"
- " { 'type': 'file', 'name': '//root/B',\n"
- " 'use-external-name': true,\n"
- " 'external-contents': '//root/external/file'\n"
- " },\n"
- " { 'type': 'file', 'name': '//root/C',\n"
- " 'use-external-name': false,\n"
- " 'external-contents': '//root/external/file'\n"
- " }\n"
- "] }", Lower);
- ASSERT_TRUE(nullptr != FS.get());
-
- // default
- EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
- // explicit
- EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
- EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
-}
-
-TEST_F(VFSFromYAMLTest, MultiComponentPath) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addRegularFile("//root/other");
-
- // file in roots
- IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
- "{ 'roots': [\n"
- " { 'type': 'file', 'name': '//root/path/to/file',\n"
- " 'external-contents': '//root/other' }]\n"
- "}", Lower);
- ASSERT_TRUE(nullptr != FS.get());
- EXPECT_FALSE(FS->status("//root/path/to/file").getError());
- EXPECT_FALSE(FS->status("//root/path/to").getError());
- EXPECT_FALSE(FS->status("//root/path").getError());
- EXPECT_FALSE(FS->status("//root/").getError());
-
- // at the start
- FS = getFromYAMLString(
- "{ 'roots': [\n"
- " { 'type': 'directory', 'name': '//root/path/to',\n"
- " 'contents': [ { 'type': 'file', 'name': 'file',\n"
- " 'external-contents': '//root/other' }]}]\n"
- "}", Lower);
- ASSERT_TRUE(nullptr != FS.get());
- EXPECT_FALSE(FS->status("//root/path/to/file").getError());
- EXPECT_FALSE(FS->status("//root/path/to").getError());
- EXPECT_FALSE(FS->status("//root/path").getError());
- EXPECT_FALSE(FS->status("//root/").getError());
-
- // at the end
- FS = getFromYAMLString(
- "{ 'roots': [\n"
- " { 'type': 'directory', 'name': '//root/',\n"
- " 'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
- " 'external-contents': '//root/other' }]}]\n"
- "}", Lower);
- ASSERT_TRUE(nullptr != FS.get());
- EXPECT_FALSE(FS->status("//root/path/to/file").getError());
- EXPECT_FALSE(FS->status("//root/path/to").getError());
- EXPECT_FALSE(FS->status("//root/path").getError());
- EXPECT_FALSE(FS->status("//root/").getError());
-}
-
-TEST_F(VFSFromYAMLTest, TrailingSlashes) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addRegularFile("//root/other");
-
- // file in roots
- IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
- "{ 'roots': [\n"
- " { 'type': 'directory', 'name': '//root/path/to////',\n"
- " 'contents': [ { 'type': 'file', 'name': 'file',\n"
- " 'external-contents': '//root/other' }]}]\n"
- "}", Lower);
- ASSERT_TRUE(nullptr != FS.get());
- EXPECT_FALSE(FS->status("//root/path/to/file").getError());
- EXPECT_FALSE(FS->status("//root/path/to").getError());
- EXPECT_FALSE(FS->status("//root/path").getError());
- EXPECT_FALSE(FS->status("//root/").getError());
-}
-
-TEST_F(VFSFromYAMLTest, DirectoryIteration) {
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addDirectory("//root/");
- Lower->addDirectory("//root/foo");
- Lower->addDirectory("//root/foo/bar");
- Lower->addRegularFile("//root/foo/bar/a");
- Lower->addRegularFile("//root/foo/bar/b");
- Lower->addRegularFile("//root/file3");
- IntrusiveRefCntPtr<vfs::FileSystem> FS =
- getFromYAMLString("{ 'use-external-names': false,\n"
- " 'roots': [\n"
- "{\n"
- " 'type': 'directory',\n"
- " 'name': '//root/',\n"
- " 'contents': [ {\n"
- " 'type': 'file',\n"
- " 'name': 'file1',\n"
- " 'external-contents': '//root/foo/bar/a'\n"
- " },\n"
- " {\n"
- " 'type': 'file',\n"
- " 'name': 'file2',\n"
- " 'external-contents': '//root/foo/bar/b'\n"
- " }\n"
- " ]\n"
- "}\n"
- "]\n"
- "}",
- Lower);
- ASSERT_TRUE(FS.get() != nullptr);
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(FS);
-
- std::error_code EC;
- checkContents(O->dir_begin("//root/", EC),
- {"//root/file1", "//root/file2", "//root/file3", "//root/foo"});
-
- checkContents(O->dir_begin("//root/foo/bar", EC),
- {"//root/foo/bar/a", "//root/foo/bar/b"});
-}
-
-TEST_F(VFSFromYAMLTest, DirectoryIterationSameDirMultipleEntries) {
- // https://llvm.org/bugs/show_bug.cgi?id=27725
- if (!supportsSameDirMultipleYAMLEntries())
- return;
-
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addDirectory("//root/zab");
- Lower->addDirectory("//root/baz");
- Lower->addRegularFile("//root/zab/a");
- Lower->addRegularFile("//root/zab/b");
- IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
- "{ 'use-external-names': false,\n"
- " 'roots': [\n"
- "{\n"
- " 'type': 'directory',\n"
- " 'name': '//root/baz/',\n"
- " 'contents': [ {\n"
- " 'type': 'file',\n"
- " 'name': 'x',\n"
- " 'external-contents': '//root/zab/a'\n"
- " }\n"
- " ]\n"
- "},\n"
- "{\n"
- " 'type': 'directory',\n"
- " 'name': '//root/baz/',\n"
- " 'contents': [ {\n"
- " 'type': 'file',\n"
- " 'name': 'y',\n"
- " 'external-contents': '//root/zab/b'\n"
- " }\n"
- " ]\n"
- "}\n"
- "]\n"
- "}",
- Lower);
- ASSERT_TRUE(FS.get() != nullptr);
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(FS);
-
- std::error_code EC;
-
- checkContents(O->dir_begin("//root/baz/", EC),
- {"//root/baz/x", "//root/baz/y"});
-}
-
-TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) {
-
- IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
- Lower->addDirectory("//root/a");
- Lower->addDirectory("//root/a/b");
- Lower->addDirectory("//root/a/b/c");
- Lower->addRegularFile("//root/a/b/c/file");
- IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
- "{ 'use-external-names': false,\n"
- " 'roots': [\n"
- "{\n"
- " 'type': 'directory',\n"
- " 'name': '//root/a/b/c/',\n"
- " 'contents': [ {\n"
- " 'type': 'file',\n"
- " 'name': 'file',\n"
- " 'external-contents': '//root/a/b/c/file'\n"
- " }\n"
- " ]\n"
- "},\n"
- "]\n"
- "}",
- Lower);
- ASSERT_TRUE(FS.get() != nullptr);
-
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
- new vfs::OverlayFileSystem(Lower));
- O->pushOverlay(FS);
-
- std::error_code EC;
-
- // Test recursive_directory_iterator level()
- vfs::recursive_directory_iterator I = vfs::recursive_directory_iterator(
- *O, "//root", EC), E;
- ASSERT_FALSE(EC);
- for (int l = 0; I != E; I.increment(EC), ++l) {
- ASSERT_FALSE(EC);
- EXPECT_EQ(I.level(), l);
- }
- EXPECT_EQ(I, E);
-}
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index 090de3b06e06..6eff59986cbf 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -31,3 +31,4 @@ if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD)
add_subdirectory(libclang)
endif()
add_subdirectory(Rename)
+add_subdirectory(Index)
diff --git a/unittests/CodeGen/CMakeLists.txt b/unittests/CodeGen/CMakeLists.txt
index 856dbce08ea9..e4e7588a9327 100644
--- a/unittests/CodeGen/CMakeLists.txt
+++ b/unittests/CodeGen/CMakeLists.txt
@@ -18,4 +18,5 @@ target_link_libraries(ClangCodeGenTests
clangFrontend
clangLex
clangParse
+ clangSerialization
)
diff --git a/unittests/CrossTU/CMakeLists.txt b/unittests/CrossTU/CMakeLists.txt
index 652d91612fb4..73047b739a4a 100644
--- a/unittests/CrossTU/CMakeLists.txt
+++ b/unittests/CrossTU/CMakeLists.txt
@@ -13,5 +13,6 @@ target_link_libraries(CrossTUTests
clangBasic
clangCrossTU
clangFrontend
+ clangSerialization
clangTooling
)
diff --git a/unittests/Driver/DistroTest.cpp b/unittests/Driver/DistroTest.cpp
index e3686e498060..bc1863c429ad 100644
--- a/unittests/Driver/DistroTest.cpp
+++ b/unittests/Driver/DistroTest.cpp
@@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Distro.h"
-#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
using namespace clang;
@@ -25,7 +25,7 @@ namespace {
// accidentally result in incorrect distribution guess.
TEST(DistroTest, DetectUbuntu) {
- vfs::InMemoryFileSystem UbuntuTrustyFileSystem;
+ llvm::vfs::InMemoryFileSystem UbuntuTrustyFileSystem;
// Ubuntu uses Debian Sid version.
UbuntuTrustyFileSystem.addFile("/etc/debian_version", 0,
llvm::MemoryBuffer::getMemBuffer("jessie/sid\n"));
@@ -51,8 +51,9 @@ TEST(DistroTest, DetectUbuntu) {
ASSERT_FALSE(UbuntuTrusty.IsRedhat());
ASSERT_FALSE(UbuntuTrusty.IsOpenSUSE());
ASSERT_FALSE(UbuntuTrusty.IsDebian());
+ ASSERT_FALSE(UbuntuTrusty.IsGentoo());
- vfs::InMemoryFileSystem UbuntuYakketyFileSystem;
+ llvm::vfs::InMemoryFileSystem UbuntuYakketyFileSystem;
UbuntuYakketyFileSystem.addFile("/etc/debian_version", 0,
llvm::MemoryBuffer::getMemBuffer("stretch/sid\n"));
UbuntuYakketyFileSystem.addFile("/etc/lsb-release", 0,
@@ -80,10 +81,11 @@ TEST(DistroTest, DetectUbuntu) {
ASSERT_FALSE(UbuntuYakkety.IsRedhat());
ASSERT_FALSE(UbuntuYakkety.IsOpenSUSE());
ASSERT_FALSE(UbuntuYakkety.IsDebian());
+ ASSERT_FALSE(UbuntuYakkety.IsGentoo());
}
TEST(DistroTest, DetectRedhat) {
- vfs::InMemoryFileSystem Fedora25FileSystem;
+ llvm::vfs::InMemoryFileSystem Fedora25FileSystem;
Fedora25FileSystem.addFile("/etc/system-release-cpe", 0,
llvm::MemoryBuffer::getMemBuffer("cpe:/o:fedoraproject:fedora:25\n"));
// Both files are symlinks to fedora-release.
@@ -114,8 +116,9 @@ TEST(DistroTest, DetectRedhat) {
ASSERT_TRUE(Fedora25.IsRedhat());
ASSERT_FALSE(Fedora25.IsOpenSUSE());
ASSERT_FALSE(Fedora25.IsDebian());
+ ASSERT_FALSE(Fedora25.IsGentoo());
- vfs::InMemoryFileSystem CentOS7FileSystem;
+ llvm::vfs::InMemoryFileSystem CentOS7FileSystem;
CentOS7FileSystem.addFile("/etc/system-release-cpe", 0,
llvm::MemoryBuffer::getMemBuffer("cpe:/o:centos:centos:7\n"));
// Both files are symlinks to centos-release.
@@ -150,10 +153,11 @@ TEST(DistroTest, DetectRedhat) {
ASSERT_TRUE(CentOS7.IsRedhat());
ASSERT_FALSE(CentOS7.IsOpenSUSE());
ASSERT_FALSE(CentOS7.IsDebian());
+ ASSERT_FALSE(CentOS7.IsGentoo());
}
TEST(DistroTest, DetectOpenSUSE) {
- vfs::InMemoryFileSystem OpenSUSELeap421FileSystem;
+ llvm::vfs::InMemoryFileSystem OpenSUSELeap421FileSystem;
OpenSUSELeap421FileSystem.addFile("/etc/SuSE-release", 0,
llvm::MemoryBuffer::getMemBuffer("openSUSE 42.1 (x86_64)\n"
"VERSION = 42.1\n"
@@ -177,8 +181,9 @@ TEST(DistroTest, DetectOpenSUSE) {
ASSERT_FALSE(OpenSUSELeap421.IsRedhat());
ASSERT_TRUE(OpenSUSELeap421.IsOpenSUSE());
ASSERT_FALSE(OpenSUSELeap421.IsDebian());
+ ASSERT_FALSE(OpenSUSELeap421.IsGentoo());
- vfs::InMemoryFileSystem OpenSUSE132FileSystem;
+ llvm::vfs::InMemoryFileSystem OpenSUSE132FileSystem;
OpenSUSE132FileSystem.addFile("/etc/SuSE-release", 0,
llvm::MemoryBuffer::getMemBuffer("openSUSE 13.2 (x86_64)\n"
"VERSION = 13.2\n"
@@ -202,8 +207,9 @@ TEST(DistroTest, DetectOpenSUSE) {
ASSERT_FALSE(OpenSUSE132.IsRedhat());
ASSERT_TRUE(OpenSUSE132.IsOpenSUSE());
ASSERT_FALSE(OpenSUSE132.IsDebian());
+ ASSERT_FALSE(OpenSUSE132.IsGentoo());
- vfs::InMemoryFileSystem SLES10FileSystem;
+ llvm::vfs::InMemoryFileSystem SLES10FileSystem;
SLES10FileSystem.addFile("/etc/SuSE-release", 0,
llvm::MemoryBuffer::getMemBuffer("SUSE Linux Enterprise Server 10 (x86_64)\n"
"VERSION = 10\n"
@@ -218,10 +224,11 @@ TEST(DistroTest, DetectOpenSUSE) {
ASSERT_FALSE(SLES10.IsRedhat());
ASSERT_FALSE(SLES10.IsOpenSUSE());
ASSERT_FALSE(SLES10.IsDebian());
+ ASSERT_FALSE(SLES10.IsGentoo());
}
TEST(DistroTest, DetectDebian) {
- vfs::InMemoryFileSystem DebianJessieFileSystem;
+ llvm::vfs::InMemoryFileSystem DebianJessieFileSystem;
DebianJessieFileSystem.addFile("/etc/debian_version", 0,
llvm::MemoryBuffer::getMemBuffer("8.6\n"));
DebianJessieFileSystem.addFile("/etc/os-release", 0,
@@ -240,8 +247,9 @@ TEST(DistroTest, DetectDebian) {
ASSERT_FALSE(DebianJessie.IsRedhat());
ASSERT_FALSE(DebianJessie.IsOpenSUSE());
ASSERT_TRUE(DebianJessie.IsDebian());
+ ASSERT_FALSE(DebianJessie.IsGentoo());
- vfs::InMemoryFileSystem DebianStretchSidFileSystem;
+ llvm::vfs::InMemoryFileSystem DebianStretchSidFileSystem;
DebianStretchSidFileSystem.addFile("/etc/debian_version", 0,
llvm::MemoryBuffer::getMemBuffer("stretch/sid\n"));
DebianStretchSidFileSystem.addFile("/etc/os-release", 0,
@@ -258,10 +266,11 @@ TEST(DistroTest, DetectDebian) {
ASSERT_FALSE(DebianStretchSid.IsRedhat());
ASSERT_FALSE(DebianStretchSid.IsOpenSUSE());
ASSERT_TRUE(DebianStretchSid.IsDebian());
+ ASSERT_FALSE(DebianStretchSid.IsGentoo());
}
TEST(DistroTest, DetectExherbo) {
- vfs::InMemoryFileSystem ExherboFileSystem;
+ llvm::vfs::InMemoryFileSystem ExherboFileSystem;
ExherboFileSystem.addFile("/etc/exherbo-release", 0, // (ASCII art)
llvm::MemoryBuffer::getMemBuffer(""));
ExherboFileSystem.addFile("/etc/os-release", 0,
@@ -279,10 +288,11 @@ TEST(DistroTest, DetectExherbo) {
ASSERT_FALSE(Exherbo.IsRedhat());
ASSERT_FALSE(Exherbo.IsOpenSUSE());
ASSERT_FALSE(Exherbo.IsDebian());
+ ASSERT_FALSE(Exherbo.IsGentoo());
}
TEST(DistroTest, DetectArchLinux) {
- vfs::InMemoryFileSystem ArchLinuxFileSystem;
+ llvm::vfs::InMemoryFileSystem ArchLinuxFileSystem;
ArchLinuxFileSystem.addFile("/etc/arch-release", 0, // (empty)
llvm::MemoryBuffer::getMemBuffer(""));
ArchLinuxFileSystem.addFile("/etc/os-release", 0,
@@ -300,6 +310,32 @@ TEST(DistroTest, DetectArchLinux) {
ASSERT_FALSE(ArchLinux.IsRedhat());
ASSERT_FALSE(ArchLinux.IsOpenSUSE());
ASSERT_FALSE(ArchLinux.IsDebian());
+ ASSERT_FALSE(ArchLinux.IsGentoo());
+}
+
+TEST(DistroTest, DetectGentoo) {
+ llvm::vfs::InMemoryFileSystem GentooFileSystem;
+ GentooFileSystem.addFile(
+ "/etc/gentoo-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("Gentoo Base System release 2.6"));
+ GentooFileSystem.addFile(
+ "/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer(
+ "NAME=Gentoo\n"
+ "ID=gentoo\n"
+ "PRETTY_NAME=\"Gentoo/Linux\"\n"
+ "ANSI_COLOR=\"1;32\"\n"
+ "HOME_URL=\"https://www.gentoo.org/\"\n"
+ "SUPPORT_URL=\"https://www.gentoo.org/support/\"\n"
+ "BUG_REPORT_URL=\"https://bugs.gentoo.org/\"\n"));
+
+ Distro Gentoo{GentooFileSystem};
+ ASSERT_EQ(Distro(Distro::Gentoo), Gentoo);
+ ASSERT_FALSE(Gentoo.IsUbuntu());
+ ASSERT_FALSE(Gentoo.IsRedhat());
+ ASSERT_FALSE(Gentoo.IsOpenSUSE());
+ ASSERT_FALSE(Gentoo.IsDebian());
+ ASSERT_TRUE(Gentoo.IsGentoo());
}
} // end anonymous namespace
diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp
index d4198eaeb1cb..f1181072a7ed 100644
--- a/unittests/Driver/ToolChainTest.cpp
+++ b/unittests/Driver/ToolChainTest.cpp
@@ -15,11 +15,11 @@
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
using namespace clang;
@@ -33,8 +33,8 @@ TEST(ToolChainTest, VFSGCCInstallation) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
struct TestDiagnosticConsumer : public DiagnosticConsumer {};
DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags,
InMemoryFileSystem);
@@ -87,8 +87,8 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
struct TestDiagnosticConsumer : public DiagnosticConsumer {};
DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
InMemoryFileSystem);
@@ -113,7 +113,7 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
std::replace(S.begin(), S.end(), '\\', '/');
#endif
EXPECT_EQ("Found candidate GCC installation: "
- "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1\n"
+ "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
"Selected GCC installation: "
"/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
"Candidate multilib: .;@m32\n"
@@ -127,8 +127,8 @@ TEST(ToolChainTest, DefaultDriverMode) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
struct TestDiagnosticConsumer : public DiagnosticConsumer {};
DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
InMemoryFileSystem);
diff --git a/unittests/Format/CMakeLists.txt b/unittests/Format/CMakeLists.txt
index 18e4432308db..015c25ee6b96 100644
--- a/unittests/Format/CMakeLists.txt
+++ b/unittests/Format/CMakeLists.txt
@@ -12,9 +12,11 @@ add_clang_unittest(FormatTests
FormatTestProto.cpp
FormatTestRawStrings.cpp
FormatTestSelective.cpp
+ FormatTestTableGen.cpp
FormatTestTextProto.cpp
NamespaceEndCommentsFixerTest.cpp
SortImportsTestJS.cpp
+ SortImportsTestJava.cpp
SortIncludesTest.cpp
UsingDeclarationsSorterTest.cpp
)
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index f234e287cf17..c05fceb4766c 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -200,6 +200,42 @@ TEST_F(FormatTest, RemovesEmptyLines) {
"int i;\n"
"}",
getGoogleStyle()));
+ EXPECT_EQ("/* something */ namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("/* something */ namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
+ EXPECT_EQ("inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
+ EXPECT_EQ("/* something */ inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("/* something */ inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
+ EXPECT_EQ("export namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("export namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
EXPECT_EQ("extern /**/ \"C\" /**/ {\n"
"\n"
"int i;\n"
@@ -999,6 +1035,24 @@ TEST_F(FormatTest, FormatsSwitchStatement) {
" }\n"
"});",
getLLVMStyle()));
+ EXPECT_EQ("switch (n) {\n"
+ "case 0: {\n"
+ " return false;\n"
+ "}\n"
+ "default: {\n"
+ " return true;\n"
+ "}\n"
+ "}",
+ format("switch (n)\n"
+ "{\n"
+ "case 0: {\n"
+ " return false;\n"
+ "}\n"
+ "default: {\n"
+ " return true;\n"
+ "}\n"
+ "}",
+ getLLVMStyle()));
verifyFormat("switch (a) {\n"
"case (b):\n"
" return;\n"
@@ -1010,6 +1064,32 @@ TEST_F(FormatTest, FormatsSwitchStatement) {
" return;\n"
"}",
getLLVMStyleWithColumns(34));
+
+ FormatStyle Style = getLLVMStyle();
+ Style.IndentCaseLabels = true;
+ Style.AllowShortBlocksOnASingleLine = false;
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterControlStatement = true;
+ EXPECT_EQ("switch (n)\n"
+ "{\n"
+ " case 0:\n"
+ " {\n"
+ " return false;\n"
+ " }\n"
+ " default:\n"
+ " {\n"
+ " return true;\n"
+ " }\n"
+ "}",
+ format("switch (n) {\n"
+ " case 0: {\n"
+ " return false;\n"
+ " }\n"
+ " default: {\n"
+ " return true;\n"
+ " }\n"
+ "}",
+ Style));
}
TEST_F(FormatTest, CaseRanges) {
@@ -1145,6 +1225,46 @@ TEST_F(FormatTest, ShortCaseLabels) {
" break;\n"
"}",
Style);
+ Style.ColumnLimit = 80;
+ Style.AllowShortCaseLabelsOnASingleLine = false;
+ Style.IndentCaseLabels = true;
+ EXPECT_EQ("switch (n) {\n"
+ " default /*comments*/:\n"
+ " return true;\n"
+ " case 0:\n"
+ " return false;\n"
+ "}",
+ format("switch (n) {\n"
+ "default/*comments*/:\n"
+ " return true;\n"
+ "case 0:\n"
+ " return false;\n"
+ "}",
+ Style));
+ Style.AllowShortCaseLabelsOnASingleLine = true;
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterControlStatement = true;
+ EXPECT_EQ("switch (n)\n"
+ "{\n"
+ " case 0:\n"
+ " {\n"
+ " return false;\n"
+ " }\n"
+ " default:\n"
+ " {\n"
+ " return true;\n"
+ " }\n"
+ "}",
+ format("switch (n) {\n"
+ " case 0: {\n"
+ " return false;\n"
+ " }\n"
+ " default:\n"
+ " {\n"
+ " return true;\n"
+ " }\n"
+ "}",
+ Style));
}
TEST_F(FormatTest, FormatsLabels) {
@@ -1186,12 +1306,25 @@ TEST_F(FormatTest, UnderstandsAccessSpecifiers) {
"private:\n"
" void f() {}\n"
"};");
+ verifyFormat("export class A {\n"
+ "public:\n"
+ "public: // comment\n"
+ "protected:\n"
+ "private:\n"
+ " void f() {}\n"
+ "};");
verifyGoogleFormat("class A {\n"
" public:\n"
" protected:\n"
" private:\n"
" void f() {}\n"
"};");
+ verifyGoogleFormat("export class A {\n"
+ " public:\n"
+ " protected:\n"
+ " private:\n"
+ " void f() {}\n"
+ "};");
verifyFormat("class A {\n"
"public slots:\n"
" void f1() {}\n"
@@ -1563,16 +1696,36 @@ TEST_F(FormatTest, FormatsNamespaces) {
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
+ verifyFormat("/* something */ namespace some_namespace {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
verifyFormat("namespace {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
+ verifyFormat("/* something */ namespace {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
verifyFormat("inline namespace X {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
+ verifyFormat("/* something */ inline namespace X {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
+ verifyFormat("export namespace X {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
verifyFormat("using namespace some_namespace;\n"
"class A {};\n"
"void f() { f(); }",
@@ -2475,6 +2628,16 @@ TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) {
" A(X x)\n"
" try : t(0) {} catch (...) {}\n"
"};"));
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterControlStatement = true;
+ Style.BraceWrapping.AfterFunction = true;
+ EXPECT_EQ("void f()\n"
+ "try\n"
+ "{\n"
+ "}",
+ format("void f() try {\n"
+ "}", Style));
EXPECT_EQ("class SomeClass {\n"
"public:\n"
" SomeClass() EXCLUSIVE_LOCK_FUNCTION(mu_);\n"
@@ -2497,6 +2660,45 @@ TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) {
getLLVMStyleWithColumns(40)));
verifyFormat("MACRO(>)");
+
+ // Some macros contain an implicit semicolon.
+ Style = getLLVMStyle();
+ Style.StatementMacros.push_back("FOO");
+ verifyFormat("FOO(a) int b = 0;");
+ verifyFormat("FOO(a)\n"
+ "int b = 0;",
+ Style);
+ verifyFormat("FOO(a);\n"
+ "int b = 0;",
+ Style);
+ verifyFormat("FOO(argc, argv, \"4.0.2\")\n"
+ "int b = 0;",
+ Style);
+ verifyFormat("FOO()\n"
+ "int b = 0;",
+ Style);
+ verifyFormat("FOO\n"
+ "int b = 0;",
+ Style);
+ verifyFormat("void f() {\n"
+ " FOO(a)\n"
+ " return a;\n"
+ "}",
+ Style);
+ verifyFormat("FOO(a)\n"
+ "FOO(b)",
+ Style);
+ verifyFormat("int a = 0;\n"
+ "FOO(b)\n"
+ "int c = 0;",
+ Style);
+ verifyFormat("int a = 0;\n"
+ "int x = FOO(a)\n"
+ "int b = 0;",
+ Style);
+ verifyFormat("void foo(int a) { FOO(a) }\n"
+ "uint32_t bar() {}",
+ Style);
}
TEST_F(FormatTest, LayoutMacroDefinitionsStatementsSpanningBlocks) {
@@ -3075,11 +3277,12 @@ TEST_F(FormatTest, LayoutNestedBlocks) {
"});");
FormatStyle Style = getGoogleStyle();
Style.ColumnLimit = 45;
- verifyFormat("Debug(aaaaa,\n"
- " {\n"
- " if (aaaaaaaaaaaaaaaaaaaaaaaa) return;\n"
- " },\n"
- " a);",
+ verifyFormat("Debug(\n"
+ " aaaaa,\n"
+ " {\n"
+ " if (aaaaaaaaaaaaaaaaaaaaaaaa) return;\n"
+ " },\n"
+ " a);",
Style);
verifyFormat("SomeFunction({MACRO({ return output; }), b});");
@@ -3375,6 +3578,18 @@ TEST_F(FormatTest, ExpressionIndentationBreakingBeforeOperators) {
" = bbbbbbbbbbbbbbbbb\n"
" >> aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaa);",
Style);
+
+ Style.ColumnLimit = 80;
+ Style.IndentWidth = 4;
+ Style.TabWidth = 4;
+ Style.UseTab = FormatStyle::UT_Always;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
+ Style.AlignOperands = false;
+ EXPECT_EQ("return someVeryVeryLongConditionThatBarelyFitsOnALine\n"
+ "\t&& (someOtherLongishConditionPart1\n"
+ "\t\t|| someOtherEvenLongerNestedConditionPart2);",
+ format("return someVeryVeryLongConditionThatBarelyFitsOnALine && (someOtherLongishConditionPart1 || someOtherEvenLongerNestedConditionPart2);",
+ Style));
}
TEST_F(FormatTest, EnforcedOperatorWraps) {
@@ -4416,6 +4631,40 @@ TEST_F(FormatTest, FormatsBuilderPattern) {
verifyFormat("aaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
" .aaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
+
+ // Dont break if only closing statements before member call
+ verifyFormat("test() {\n"
+ " ([]() -> {\n"
+ " int b = 32;\n"
+ " return 3;\n"
+ " }).foo();\n"
+ "}");
+ verifyFormat("test() {\n"
+ " (\n"
+ " []() -> {\n"
+ " int b = 32;\n"
+ " return 3;\n"
+ " },\n"
+ " foo, bar)\n"
+ " .foo();\n"
+ "}");
+ verifyFormat("test() {\n"
+ " ([]() -> {\n"
+ " int b = 32;\n"
+ " return 3;\n"
+ " })\n"
+ " .foo()\n"
+ " .bar();\n"
+ "}");
+ verifyFormat("test() {\n"
+ " ([]() -> {\n"
+ " int b = 32;\n"
+ " return 3;\n"
+ " })\n"
+ " .foo(\"aaaaaaaaaaaaaaaaa\"\n"
+ " \"bbbb\");\n"
+ "}",
+ getLLVMStyleWithColumns(30));
}
TEST_F(FormatTest, BreaksAccordingToOperatorPrecedence) {
@@ -6223,6 +6472,8 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) {
// Make sure we do not mistake attributes for array subscripts.
verifyFormat("int a() {}\n"
"[[unused]] int b() {}\n");
+ verifyFormat("NSArray *arr;\n"
+ "arr[[Foo() bar]];");
// On the other hand, we still need to correctly find array subscripts.
verifyFormat("int a = std::vector<int>{1, 2, 3}[0];");
@@ -7556,6 +7807,12 @@ TEST_F(FormatTest, SplitEmptyNamespace) {
verifyFormat("inline namespace Foo\n"
"{};",
Style);
+ verifyFormat("/* something */ inline namespace Foo\n"
+ "{};",
+ Style);
+ verifyFormat("export namespace Foo\n"
+ "{};",
+ Style);
verifyFormat("namespace Foo\n"
"{\n"
"void Bar();\n"
@@ -9804,6 +10061,14 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
"});\n",
Alignment);
Alignment.PointerAlignment = FormatStyle::PAS_Right;
+
+ // See llvm.org/PR35641
+ Alignment.AlignConsecutiveDeclarations = true;
+ verifyFormat("int func() { //\n"
+ " int b;\n"
+ " unsigned c;\n"
+ "}",
+ Alignment);
}
TEST_F(FormatTest, LinuxBraceBreaking) {
@@ -10872,6 +11137,12 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("ForEachMacros: [BOOST_FOREACH, Q_FOREACH]", ForEachMacros,
BoostAndQForeach);
+ Style.StatementMacros.clear();
+ CHECK_PARSE("StatementMacros: [QUNUSED]", StatementMacros,
+ std::vector<std::string>{"QUNUSED"});
+ CHECK_PARSE("StatementMacros: [QUNUSED, QT_REQUIRE_VERSION]", StatementMacros,
+ std::vector<std::string>({"QUNUSED", "QT_REQUIRE_VERSION"}));
+
Style.IncludeStyle.IncludeCategories.clear();
std::vector<tooling::IncludeStyle::IncludeCategory> ExpectedCategories = {
{"abc/.*", 2}, {".*", 1}};
@@ -11471,6 +11742,18 @@ TEST_F(FormatTest, FormatsLambdas) {
" x.end(), //\n"
" [&](int, int) { return 1; });\n"
"}\n");
+ verifyFormat("void f() {\n"
+ " other.other.other.other.other(\n"
+ " x.begin(), x.end(),\n"
+ " [something, rather](int, int, int, int, int, int, int) { return 1; });\n"
+ "}\n");
+ verifyFormat("void f() {\n"
+ " other.other.other.other.other(\n"
+ " x.begin(), x.end(),\n"
+ " [something, rather](int, int, int, int, int, int, int) {\n"
+ " //\n"
+ " });\n"
+ "}\n");
verifyFormat("SomeFunction([]() { // A cool function...\n"
" return 43;\n"
"});");
@@ -11522,9 +11805,9 @@ TEST_F(FormatTest, FormatsLambdas) {
verifyFormat("SomeFunction({[&] {\n"
" // comment\n"
"}});");
- verifyFormat("virtual aaaaaaaaaaaaaaaa(std::function<bool()> bbbbbbbbbbbb =\n"
- " [&]() { return true; },\n"
- " aaaaa aaaaaaaaa);");
+ verifyFormat("virtual aaaaaaaaaaaaaaaa(\n"
+ " std::function<bool()> bbbbbbbbbbbb = [&]() { return true; },\n"
+ " aaaaa aaaaaaaaa);");
// Lambdas with return types.
verifyFormat("int c = []() -> int { return 2; }();\n");
@@ -11551,17 +11834,76 @@ TEST_F(FormatTest, FormatsLambdas) {
" return 1; //\n"
"};");
- // Multiple lambdas in the same parentheses change indentation rules.
+ // Multiple lambdas in the same parentheses change indentation rules. These
+ // lambdas are forced to start on new lines.
verifyFormat("SomeFunction(\n"
" []() {\n"
- " int i = 42;\n"
- " return i;\n"
+ " //\n"
" },\n"
" []() {\n"
- " int j = 43;\n"
- " return j;\n"
+ " //\n"
" });");
+ // A lambda passed as arg0 is always pushed to the next line.
+ verifyFormat("SomeFunction(\n"
+ " [this] {\n"
+ " //\n"
+ " },\n"
+ " 1);\n");
+
+ // A multi-line lambda passed as arg1 forces arg0 to be pushed out, just like the arg0
+ // case above.
+ auto Style = getGoogleStyle();
+ Style.BinPackArguments = false;
+ verifyFormat("SomeFunction(\n"
+ " a,\n"
+ " [this] {\n"
+ " //\n"
+ " },\n"
+ " b);\n",
+ Style);
+ verifyFormat("SomeFunction(\n"
+ " a,\n"
+ " [this] {\n"
+ " //\n"
+ " },\n"
+ " b);\n");
+
+ // A lambda with a very long line forces arg0 to be pushed out irrespective of
+ // the BinPackArguments value (as long as the code is wide enough).
+ verifyFormat("something->SomeFunction(\n"
+ " a,\n"
+ " [this] {\n"
+ " D0000000000000000000000000000000000000000000000000000000000001();\n"
+ " },\n"
+ " b);\n");
+
+ // A multi-line lambda is pulled up as long as the introducer fits on the previous
+ // line and there are no further args.
+ verifyFormat("function(1, [this, that] {\n"
+ " //\n"
+ "});\n");
+ verifyFormat("function([this, that] {\n"
+ " //\n"
+ "});\n");
+ // FIXME: this format is not ideal and we should consider forcing the first arg
+ // onto its own line.
+ verifyFormat("function(a, b, c, //\n"
+ " d, [this, that] {\n"
+ " //\n"
+ " });\n");
+
+ // Multiple lambdas are treated correctly even when there is a short arg0.
+ verifyFormat("SomeFunction(\n"
+ " 1,\n"
+ " [this] {\n"
+ " //\n"
+ " },\n"
+ " [this] {\n"
+ " //\n"
+ " },\n"
+ " 1);\n");
+
// More complex introducers.
verifyFormat("return [i, args...] {};");
@@ -12107,14 +12449,14 @@ TEST_F(FormatTest, NoSpaceAfterSuper) {
}
TEST(FormatStyle, GetStyleWithEmptyFileName) {
- vfs::InMemoryFileSystem FS;
+ llvm::vfs::InMemoryFileSystem FS;
auto Style1 = getStyle("file", "", "Google", "", &FS);
ASSERT_TRUE((bool)Style1);
ASSERT_EQ(*Style1, getGoogleStyle());
}
TEST(FormatStyle, GetStyleOfFile) {
- vfs::InMemoryFileSystem FS;
+ llvm::vfs::InMemoryFileSystem FS;
// Test 1: format file in the same directory.
ASSERT_TRUE(
FS.addFile("/a/.clang-format", 0,
@@ -12413,6 +12755,45 @@ TEST_F(FormatTest, GuessLanguageWithCaret) {
guessLanguage("foo.h", "int(^foo[(kNumEntries + 10)])(char, float);"));
}
+TEST_F(FormatTest, GuessedLanguageWithInlineAsmClobbers) {
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h",
+ "void f() {\n"
+ " asm (\"mov %[e], %[d]\"\n"
+ " : [d] \"=rm\" (d)\n"
+ " [e] \"rm\" (*e));\n"
+ "}"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h",
+ "void f() {\n"
+ " _asm (\"mov %[e], %[d]\"\n"
+ " : [d] \"=rm\" (d)\n"
+ " [e] \"rm\" (*e));\n"
+ "}"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h",
+ "void f() {\n"
+ " __asm (\"mov %[e], %[d]\"\n"
+ " : [d] \"=rm\" (d)\n"
+ " [e] \"rm\" (*e));\n"
+ "}"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h",
+ "void f() {\n"
+ " __asm__ (\"mov %[e], %[d]\"\n"
+ " : [d] \"=rm\" (d)\n"
+ " [e] \"rm\" (*e));\n"
+ "}"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h",
+ "void f() {\n"
+ " asm (\"mov %[e], %[d]\"\n"
+ " : [d] \"=rm\" (d),\n"
+ " [e] \"rm\" (*e));\n"
+ "}"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "void f() {\n"
+ " asm volatile (\"mov %[e], %[d]\"\n"
+ " : [d] \"=rm\" (d)\n"
+ " [e] \"rm\" (*e));\n"
+ "}"));
+}
+
TEST_F(FormatTest, GuessLanguageWithChildLines) {
EXPECT_EQ(FormatStyle::LK_Cpp,
guessLanguage("foo.h", "#define FOO ({ std::string s; })"));
diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp
index 2b07dedf6706..9f43677b70df 100644
--- a/unittests/Format/FormatTestComments.cpp
+++ b/unittests/Format/FormatTestComments.cpp
@@ -1254,6 +1254,12 @@ TEST_F(FormatTestComments, SplitsLongLinesInComments) {
" */",
getLLVMStyleWithColumns(20)));
+ // This reproduces a crashing bug where both adaptStartOfLine and
+ // getCommentSplit were trying to wrap after the "/**".
+ EXPECT_EQ("/** multilineblockcommentwithnowrapopportunity */",
+ format("/** multilineblockcommentwithnowrapopportunity */",
+ getLLVMStyleWithColumns(20)));
+
EXPECT_EQ("/*\n"
"\n"
"\n"
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp
index e7808c6596d0..67b99ba146da 100644
--- a/unittests/Format/FormatTestJS.cpp
+++ b/unittests/Format/FormatTestJS.cpp
@@ -191,31 +191,32 @@ TEST_F(FormatTestJS, JSDocComments) {
// Break a single line long jsdoc comment pragma.
EXPECT_EQ("/**\n"
- " * @returns\n"
- " * {string}\n"
- " * jsdoc line 12\n"
+ " * @returns {string} jsdoc line 12\n"
" */",
format("/** @returns {string} jsdoc line 12 */",
getGoogleJSStyleWithColumns(20)));
-
EXPECT_EQ("/**\n"
- " * @returns\n"
- " * {string}\n"
+ " * @returns {string}\n"
" * jsdoc line 12\n"
" */",
+ format("/** @returns {string} jsdoc line 12 */",
+ getGoogleJSStyleWithColumns(25)));
+
+ EXPECT_EQ("/**\n"
+ " * @returns {string} jsdoc line 12\n"
+ " */",
format("/** @returns {string} jsdoc line 12 */",
getGoogleJSStyleWithColumns(20)));
// FIXME: this overcounts the */ as a continuation of the 12 when breaking.
// Related to the FIXME in BreakableBlockComment::getRangeLength.
EXPECT_EQ("/**\n"
- " * @returns\n"
- " * {string}\n"
- " * jsdoc line\n"
+ " * @returns {string}\n"
+ " * jsdoc line line\n"
" * 12\n"
" */",
- format("/** @returns {string} jsdoc line 12*/",
- getGoogleJSStyleWithColumns(20)));
+ format("/** @returns {string} jsdoc line line 12*/",
+ getGoogleJSStyleWithColumns(25)));
// Fix a multiline jsdoc comment ending in a comment pragma.
EXPECT_EQ("/**\n"
@@ -599,6 +600,8 @@ TEST_F(FormatTestJS, GoogModules) {
getGoogleJSStyleWithColumns(40));
verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
getGoogleJSStyleWithColumns(40));
+ verifyFormat("const X = goog.requireType('this.is.really.absurdly.long');",
+ getGoogleJSStyleWithColumns(40));
verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
getGoogleJSStyleWithColumns(40));
@@ -1185,6 +1188,16 @@ TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
getGoogleJSStyleWithColumns(25));
}
+TEST_F(FormatTestJS, AddsIsTheDictKeyOnNewline) {
+ // Do not confuse is, the dict key with is, the type matcher. Put is, the dict
+ // key, on a newline.
+ verifyFormat("Polymer({\n"
+ " is: '', //\n"
+ " rest: 1\n"
+ "});",
+ getGoogleJSStyleWithColumns(20));
+}
+
TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
verifyFormat("a\n"
"b;",
@@ -2038,29 +2051,42 @@ TEST_F(FormatTestJS, WrapAfterParen) {
TEST_F(FormatTestJS, JSDocAnnotations) {
verifyFormat("/**\n"
- " * @exports\n"
- " * {this.is.a.long.path.to.a.Type}\n"
+ " * @exports {this.is.a.long.path.to.a.Type}\n"
" */",
"/**\n"
" * @exports {this.is.a.long.path.to.a.Type}\n"
" */",
getGoogleJSStyleWithColumns(20));
verifyFormat("/**\n"
- " * @mods\n"
- " * {this.is.a.long.path.to.a.Type}\n"
+ " * @mods {this.is.a.long.path.to.a.Type}\n"
+ " */",
+ "/**\n"
+ " * @mods {this.is.a.long.path.to.a.Type}\n"
+ " */",
+ getGoogleJSStyleWithColumns(20));
+ verifyFormat("/**\n"
+ " * @mods {this.is.a.long.path.to.a.Type}\n"
" */",
"/**\n"
" * @mods {this.is.a.long.path.to.a.Type}\n"
" */",
getGoogleJSStyleWithColumns(20));
verifyFormat("/**\n"
- " * @param\n"
- " * {this.is.a.long.path.to.a.Type}\n"
+ " * @param {canWrap\n"
+ " * onSpace}\n"
" */",
"/**\n"
- " * @param {this.is.a.long.path.to.a.Type}\n"
+ " * @param {canWrap onSpace}\n"
" */",
getGoogleJSStyleWithColumns(20));
+ // make sure clang-format doesn't break before *any* '{'
+ verifyFormat("/**\n"
+ " * @lala {lala {lalala\n"
+ " */\n",
+ "/**\n"
+ " * @lala {lala {lalala\n"
+ " */\n",
+ getGoogleJSStyleWithColumns(20));
verifyFormat("/**\n"
" * @see http://very/very/long/url/is/long\n"
" */",
@@ -2083,8 +2109,7 @@ TEST_F(FormatTestJS, JSDocAnnotations) {
" /**\n"
" * long long long\n"
" * long\n"
- " * @param\n"
- " * {this.is.a.long.path.to.a.Type}\n"
+ " * @param {this.is.a.long.path.to.a.Type}\n"
" * a\n"
" * long long long\n"
" * long long\n"
@@ -2271,5 +2296,38 @@ TEST_F(FormatTestJS, BackslashesInComments) {
"formatMe( );\n");
}
+TEST_F(FormatTestJS, AddsLastLinePenaltyIfEndingIsBroken) {
+ EXPECT_EQ(
+ "a = function() {\n"
+ " b = function() {\n"
+ " this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ?\n"
+ " aaaa.aaaaaa : /** @type "
+ "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
+ " (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
+ " };\n"
+ "};",
+ format("a = function() {\n"
+ " b = function() {\n"
+ " this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ? "
+ "aaaa.aaaaaa : /** @type "
+ "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
+ " (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
+ " };\n"
+ "};"));
+}
+
+TEST_F(FormatTestJS, ParameterNamingComment) {
+ verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
+}
+
+TEST_F(FormatTestJS, ConditionalTypes) {
+ // Formatting below is not necessarily intentional, this just ensures that
+ // clang-format does not break the code.
+ verifyFormat( // wrap
+ "type UnionToIntersection<U> =\n"
+ " (U extends any ? (k: U) => void :\n"
+ " never) extends((k: infer I) => void) ? I : never;");
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Format/FormatTestJava.cpp b/unittests/Format/FormatTestJava.cpp
index 76e82612e0fe..f12d7fba5059 100644
--- a/unittests/Format/FormatTestJava.cpp
+++ b/unittests/Format/FormatTestJava.cpp
@@ -155,6 +155,15 @@ TEST_F(FormatTestJava, ClassDeclarations) {
" void doStuff(int theStuff);\n"
" void doMoreStuff(int moreStuff);\n"
"}");
+ verifyFormat("class A {\n"
+ " public @interface SomeInterface {\n"
+ " int stuff;\n"
+ " void doMoreStuff(int moreStuff);\n"
+ " }\n"
+ "}");
+ verifyFormat("class A {\n"
+ " public @interface SomeInterface {}\n"
+ "}");
}
TEST_F(FormatTestJava, AnonymousClasses) {
@@ -443,6 +452,22 @@ TEST_F(FormatTestJava, MethodDeclarations) {
getStyleWithColumns(40));
}
+TEST_F(FormatTestJava, MethodReference) {
+ EXPECT_EQ(
+ "private void foo() {\n"
+ " f(this::methodReference);\n"
+ " f(C.super::methodReference);\n"
+ " Consumer<String> c = System.out::println;\n"
+ " Iface<Integer> mRef = Ty::<Integer>meth;\n"
+ "}",
+ format("private void foo() {\n"
+ " f(this ::methodReference);\n"
+ " f(C.super ::methodReference);\n"
+ " Consumer<String> c = System.out ::println;\n"
+ " Iface<Integer> mRef = Ty :: <Integer> meth;\n"
+ "}"));
+}
+
TEST_F(FormatTestJava, CppKeywords) {
verifyFormat("public void union(Type a, Type b);");
verifyFormat("public void struct(Object o);");
diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp
index e56df6d130d2..a417b6710da2 100644
--- a/unittests/Format/FormatTestObjC.cpp
+++ b/unittests/Format/FormatTestObjC.cpp
@@ -584,6 +584,16 @@ TEST_F(FormatTestObjC, FormatObjCMethodDeclarations) {
" aaaaa:(a)yyy\n"
" bbb:(d)cccc;");
verifyFormat("- (void)drawRectOn:(id)surface ofSize:(aaa)height:(bbb)width;");
+
+ // BraceWrapping AfterFunction is respected for ObjC methods
+ Style = getGoogleStyle(FormatStyle::LK_ObjC);
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterFunction = true;
+ verifyFormat("@implementation Foo\n"
+ "- (void)foo:(id)bar\n"
+ "{\n"
+ "}\n"
+ "@end\n");
}
TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp
index d25aeb846a97..70ef2d2f1344 100644
--- a/unittests/Format/FormatTestProto.cpp
+++ b/unittests/Format/FormatTestProto.cpp
@@ -397,29 +397,25 @@ TEST_F(FormatTestProto, FormatsService) {
}
TEST_F(FormatTestProto, ExtendingMessage) {
- verifyFormat("extend .foo.Bar {\n"
- "}");
+ verifyFormat("extend .foo.Bar {}");
}
TEST_F(FormatTestProto, FormatsImports) {
verifyFormat("import \"a.proto\";\n"
"import \"b.proto\";\n"
"// comment\n"
- "message A {\n"
- "}");
+ "message A {}");
verifyFormat("import public \"a.proto\";\n"
"import \"b.proto\";\n"
"// comment\n"
- "message A {\n"
- "}");
+ "message A {}");
// Missing semicolons should not confuse clang-format.
verifyFormat("import \"a.proto\"\n"
"import \"b.proto\"\n"
"// comment\n"
- "message A {\n"
- "}");
+ "message A {}");
}
TEST_F(FormatTestProto, KeepsLongStringLiteralsOnSameLine) {
diff --git a/unittests/Format/FormatTestRawStrings.cpp b/unittests/Format/FormatTestRawStrings.cpp
index 307394341d74..2a8a43dc95d8 100644
--- a/unittests/Format/FormatTestRawStrings.cpp
+++ b/unittests/Format/FormatTestRawStrings.cpp
@@ -576,10 +576,13 @@ auto S =
auto S = R"pb(item_1:1 item_2:2)pb"+rest;)test",
getRawStringPbStyleWithColumns(40)));
+ // `rest` fits on the line after )pb", but forced on newline since the raw
+ // string literal is multiline.
expect_eq(R"test(
auto S = R"pb(item_1: 1,
item_2: 2,
- item_3: 3)pb" + rest;)test",
+ item_3: 3)pb" +
+ rest;)test",
format(R"test(
auto S = R"pb(item_1:1,item_2:2,item_3:3)pb"+rest;)test",
getRawStringPbStyleWithColumns(40)));
@@ -615,7 +618,8 @@ auto S = first+R"pb(item_1:1 item_2:2)pb";)test",
expect_eq(R"test(
auto S = R"pb(item_1: 1,
item_2: 2,
- item_3: 3)pb" + rest;)test",
+ item_3: 3)pb" +
+ rest;)test",
format(R"test(
auto S = R"pb(item_1:1,item_2:2,item_3:3)pb"+rest;)test",
getRawStringPbStyleWithColumns(40)));
@@ -889,6 +893,95 @@ item {
Style));
}
+TEST_F(FormatTestRawStrings,
+ BreaksBeforeNextParamAfterMultilineRawStringParam) {
+ FormatStyle Style = getRawStringPbStyleWithColumns(60);
+ expect_eq(R"test(
+int f() {
+ int a = g(x, R"pb(
+ key: 1 #
+ key: 2
+ )pb",
+ 3, 4);
+}
+)test",
+ format(R"test(
+int f() {
+ int a = g(x, R"pb(
+ key: 1 #
+ key: 2
+ )pb", 3, 4);
+}
+)test",
+ Style));
+
+ // Breaks after a parent of a multiline param.
+ expect_eq(R"test(
+int f() {
+ int a = g(x, h(R"pb(
+ key: 1 #
+ key: 2
+ )pb"),
+ 3, 4);
+}
+)test",
+ format(R"test(
+int f() {
+ int a = g(x, h(R"pb(
+ key: 1 #
+ key: 2
+ )pb"), 3, 4);
+}
+)test",
+ Style));
+
+ expect_eq(R"test(
+int f() {
+ int a = g(x,
+ h(R"pb(
+ key: 1 #
+ key: 2
+ )pb",
+ 2),
+ 3, 4);
+}
+)test",
+ format(R"test(
+int f() {
+ int a = g(x, h(R"pb(
+ key: 1 #
+ key: 2
+ )pb", 2), 3, 4);
+}
+)test",
+ Style));
+ // Breaks if formatting introduces a multiline raw string.
+ expect_eq(R"test(
+int f() {
+ int a = g(x, R"pb(key1: value111111111
+ key2: value2222222222)pb",
+ 3, 4);
+}
+)test",
+ format(R"test(
+int f() {
+ int a = g(x, R"pb(key1: value111111111 key2: value2222222222)pb", 3, 4);
+}
+)test",
+ Style));
+ // Does not force a break after an original multiline param that is
+ // reformatterd as on single line.
+ expect_eq(R"test(
+int f() {
+ int a = g(R"pb(key: 1)pb", 2);
+})test",
+ format(R"test(
+int f() {
+ int a = g(R"pb(key:
+ 1)pb", 2);
+})test", Style));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestTableGen.cpp b/unittests/Format/FormatTestTableGen.cpp
new file mode 100644
index 000000000000..820ea783cc9c
--- /dev/null
+++ b/unittests/Format/FormatTestTableGen.cpp
@@ -0,0 +1,56 @@
+//===- unittest/Format/FormatTestTableGen.cpp -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FormatTestUtils.h"
+#include "clang/Format/Format.h"
+#include "llvm/Support/Debug.h"
+#include "gtest/gtest.h"
+
+#define DEBUG_TYPE "format-test"
+
+namespace clang {
+namespace format {
+
+class FormatTestTableGen : public ::testing::Test {
+protected:
+ static std::string format(llvm::StringRef Code, unsigned Offset,
+ unsigned Length, const FormatStyle &Style) {
+ LLVM_DEBUG(llvm::errs() << "---\n");
+ LLVM_DEBUG(llvm::errs() << Code << "\n\n");
+ std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
+ tooling::Replacements Replaces = reformat(Style, Code, Ranges);
+ auto Result = applyAllReplacements(Code, Replaces);
+ EXPECT_TRUE(static_cast<bool>(Result));
+ LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ return *Result;
+ }
+
+ static std::string format(llvm::StringRef Code) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen);
+ Style.ColumnLimit = 60; // To make writing tests easier.
+ return format(Code, 0, Code.size(), Style);
+ }
+
+ static void verifyFormat(llvm::StringRef Code) {
+ EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable";
+ EXPECT_EQ(Code.str(), format(test::messUp(Code)));
+ }
+};
+
+TEST_F(FormatTestTableGen, FormatStringBreak) {
+ verifyFormat("include \"OptParser.td\"\n"
+ "def flag : Flag<\"--foo\">,\n"
+ " HelpText<\n"
+ " \"This is a very, very, very, very, \"\n"
+ " \"very, very, very, very, very, very, \"\n"
+ " \"very long help string\">;\n");
+}
+
+} // namespace format
+} // end namespace clang
diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp
index 0875bd8925d1..44431e4dc6ec 100644
--- a/unittests/Format/FormatTestTextProto.cpp
+++ b/unittests/Format/FormatTestTextProto.cpp
@@ -1,4 +1,4 @@
-//===- unittest/Format/FormatTestProto.cpp --------------------------------===//
+//===- unittest/Format/FormatTestTextProto.cpp ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/unittests/Format/SortImportsTestJava.cpp b/unittests/Format/SortImportsTestJava.cpp
new file mode 100644
index 000000000000..3bcf809d961b
--- /dev/null
+++ b/unittests/Format/SortImportsTestJava.cpp
@@ -0,0 +1,267 @@
+#include "clang/Format/Format.h"
+#include "gtest/gtest.h"
+
+#define DEBUG_TYPE "format-test"
+
+namespace clang {
+namespace format {
+namespace {
+
+class SortImportsTestJava : public ::testing::Test {
+protected:
+ std::vector<tooling::Range> GetCodeRange(StringRef Code) {
+ return std::vector<tooling::Range>(1, tooling::Range(0, Code.size()));
+ }
+
+ std::string sort(StringRef Code, std::vector<tooling::Range> Ranges) {
+ auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.java");
+ Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
+ auto Sorted = applyAllReplacements(Code, Replaces);
+ EXPECT_TRUE(static_cast<bool>(Sorted));
+ auto Result = applyAllReplacements(
+ *Sorted, reformat(FmtStyle, *Sorted, Ranges, "input.java"));
+ EXPECT_TRUE(static_cast<bool>(Result));
+ return *Result;
+ }
+
+ std::string sort(StringRef Code) { return sort(Code, GetCodeRange(Code)); }
+
+ FormatStyle FmtStyle;
+
+public:
+ SortImportsTestJava() {
+ FmtStyle = getGoogleStyle(FormatStyle::LK_Java);
+ FmtStyle.JavaImportGroups = {"com.test", "org", "com"};
+ FmtStyle.SortIncludes = true;
+ }
+};
+
+TEST_F(SortImportsTestJava, StaticSplitFromNormal) {
+ EXPECT_EQ("import static org.b;\n"
+ "\n"
+ "import org.a;\n",
+ sort("import org.a;\n"
+ "import static org.b;\n"));
+}
+
+TEST_F(SortImportsTestJava, CapitalBeforeLowercase) {
+ EXPECT_EQ("import org.Test;\n"
+ "import org.a.Test;\n"
+ "import org.b;\n",
+ sort("import org.a.Test;\n"
+ "import org.Test;\n"
+ "import org.b;\n"));
+}
+
+TEST_F(SortImportsTestJava, KeepSplitGroupsWithOneNewImport) {
+ EXPECT_EQ("import static com.test.a;\n"
+ "\n"
+ "import static org.a;\n"
+ "\n"
+ "import static com.a;\n"
+ "\n"
+ "import com.test.b;\n"
+ "import com.test.c;\n"
+ "\n"
+ "import org.b;\n"
+ "\n"
+ "import com.b;\n",
+ sort("import static com.test.a;\n"
+ "\n"
+ "import static org.a;\n"
+ "\n"
+ "import static com.a;\n"
+ "\n"
+ "import com.test.b;\n"
+ "\n"
+ "import org.b;\n"
+ "\n"
+ "import com.b;\n"
+ "import com.test.c;\n"));
+}
+
+TEST_F(SortImportsTestJava, SplitGroupsWithNewline) {
+ EXPECT_EQ("import static com.test.a;\n"
+ "\n"
+ "import static org.a;\n"
+ "\n"
+ "import static com.a;\n"
+ "\n"
+ "import com.test.b;\n"
+ "\n"
+ "import org.b;\n"
+ "\n"
+ "import com.b;\n",
+ sort("import static com.test.a;\n"
+ "import static org.a;\n"
+ "import static com.a;\n"
+ "import com.test.b;\n"
+ "import org.b;\n"
+ "import com.b;\n"));
+}
+
+TEST_F(SortImportsTestJava, UnspecifiedGroupAfterAllGroups) {
+ EXPECT_EQ("import com.test.a;\n"
+ "\n"
+ "import org.a;\n"
+ "\n"
+ "import com.a;\n"
+ "\n"
+ "import abc.a;\n"
+ "import xyz.b;\n",
+ sort("import com.test.a;\n"
+ "import com.a;\n"
+ "import xyz.b;\n"
+ "import abc.a;\n"
+ "import org.a;\n"));
+}
+
+TEST_F(SortImportsTestJava, NoSortOutsideRange) {
+ std::vector<tooling::Range> Ranges = {tooling::Range(27, 15)};
+ EXPECT_EQ("import org.b;\n"
+ "import org.a;\n"
+ "// comments\n"
+ "// that do\n"
+ "// nothing\n",
+ sort("import org.b;\n"
+ "import org.a;\n"
+ "// comments\n"
+ "// that do\n"
+ "// nothing\n",
+ Ranges));
+}
+
+TEST_F(SortImportsTestJava, SortWhenRangeContainsOneLine) {
+ std::vector<tooling::Range> Ranges = {tooling::Range(27, 20)};
+ EXPECT_EQ("import org.a;\n"
+ "import org.b;\n"
+ "\n"
+ "import com.a;\n"
+ "// comments\n"
+ "// that do\n"
+ "// nothing\n",
+ sort("import org.b;\n"
+ "import org.a;\n"
+ "import com.a;\n"
+ "// comments\n"
+ "// that do\n"
+ "// nothing\n",
+ Ranges));
+}
+
+TEST_F(SortImportsTestJava, SortLexicographically) {
+ EXPECT_EQ("import org.a.*;\n"
+ "import org.a.a;\n"
+ "import org.aA;\n"
+ "import org.aa;\n",
+ sort("import org.aa;\n"
+ "import org.a.a;\n"
+ "import org.a.*;\n"
+ "import org.aA;\n"));
+}
+
+TEST_F(SortImportsTestJava, StaticInCommentHasNoEffect) {
+ EXPECT_EQ("import org.a; // static\n"
+ "import org.b;\n"
+ "import org.c; // static\n",
+ sort("import org.a; // static\n"
+ "import org.c; // static\n"
+ "import org.b;\n"));
+}
+
+TEST_F(SortImportsTestJava, CommentsWithAffectedImports) {
+ EXPECT_EQ("import org.a;\n"
+ "// commentB\n"
+ "/* commentB\n"
+ " commentB*/\n"
+ "import org.b;\n"
+ "// commentC\n"
+ "import org.c;\n",
+ sort("import org.a;\n"
+ "// commentC\n"
+ "import org.c;\n"
+ "// commentB\n"
+ "/* commentB\n"
+ " commentB*/\n"
+ "import org.b;\n"));
+}
+
+TEST_F(SortImportsTestJava, CommentWithUnaffectedImports) {
+ EXPECT_EQ("import org.a;\n"
+ "// comment\n"
+ "import org.b;\n",
+ sort("import org.a;\n"
+ "// comment\n"
+ "import org.b;\n"));
+}
+
+TEST_F(SortImportsTestJava, CommentAfterAffectedImports) {
+ EXPECT_EQ("import org.a;\n"
+ "import org.b;\n"
+ "// comment\n",
+ sort("import org.b;\n"
+ "import org.a;\n"
+ "// comment\n"));
+}
+
+TEST_F(SortImportsTestJava, CommentBeforeAffectedImports) {
+ EXPECT_EQ("// comment\n"
+ "import org.a;\n"
+ "import org.b;\n",
+ sort("// comment\n"
+ "import org.b;\n"
+ "import org.a;\n"));
+}
+
+TEST_F(SortImportsTestJava, FormatTotallyOff) {
+ EXPECT_EQ("// clang-format off\n"
+ "import org.b;\n"
+ "import org.a;\n"
+ "// clang-format on\n",
+ sort("// clang-format off\n"
+ "import org.b;\n"
+ "import org.a;\n"
+ "// clang-format on\n"));
+}
+
+TEST_F(SortImportsTestJava, FormatTotallyOn) {
+ EXPECT_EQ("// clang-format off\n"
+ "// clang-format on\n"
+ "import org.a;\n"
+ "import org.b;\n",
+ sort("// clang-format off\n"
+ "// clang-format on\n"
+ "import org.b;\n"
+ "import org.a;\n"));
+}
+
+TEST_F(SortImportsTestJava, FormatPariallyOnShouldNotReorder) {
+ EXPECT_EQ("// clang-format off\n"
+ "import org.b;\n"
+ "import org.a;\n"
+ "// clang-format on\n"
+ "import org.d;\n"
+ "import org.c;\n",
+ sort("// clang-format off\n"
+ "import org.b;\n"
+ "import org.a;\n"
+ "// clang-format on\n"
+ "import org.d;\n"
+ "import org.c;\n"));
+}
+
+TEST_F(SortImportsTestJava, DeduplicateImports) {
+ EXPECT_EQ("import org.a;\n", sort("import org.a;\n"
+ "import org.a;\n"));
+}
+
+TEST_F(SortImportsTestJava, NoNewlineAtEnd) {
+ EXPECT_EQ("import org.a;\n"
+ "import org.b;",
+ sort("import org.b;\n"
+ "import org.a;"));
+}
+
+} // end namespace
+} // end namespace format
+} // end namespace clang
diff --git a/unittests/Frontend/CMakeLists.txt b/unittests/Frontend/CMakeLists.txt
index c764fb9e2a0f..c7851bb394ee 100644
--- a/unittests/Frontend/CMakeLists.txt
+++ b/unittests/Frontend/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_unittest(FrontendTests
ASTUnitTest.cpp
CompilerInstanceTest.cpp
+ FixedPointString.cpp
FrontendActionTest.cpp
CodeGenActionTest.cpp
ParsedSourceLocationTest.cpp
@@ -20,4 +21,5 @@ target_link_libraries(FrontendTests
clangSema
clangCodeGen
clangFrontendTool
+ clangSerialization
)
diff --git a/unittests/Frontend/FixedPointString.cpp b/unittests/Frontend/FixedPointString.cpp
new file mode 100644
index 000000000000..755efd7fcaab
--- /dev/null
+++ b/unittests/Frontend/FixedPointString.cpp
@@ -0,0 +1,107 @@
+#include "clang/AST/Type.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallString.h"
+#include "gtest/gtest.h"
+
+using clang::FixedPointValueToString;
+using llvm::APSInt;
+using llvm::SmallString;
+
+namespace {
+
+TEST(FixedPointString, DifferentTypes) {
+ SmallString<64> S;
+ FixedPointValueToString(S, APSInt::get(320), 7);
+ ASSERT_STREQ(S.c_str(), "2.5");
+
+ S.clear();
+ FixedPointValueToString(S, APSInt::get(0), 7);
+ ASSERT_STREQ(S.c_str(), "0.0");
+
+ // signed short _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(16, /*Unsigned=*/false), 7);
+ ASSERT_STREQ(S.c_str(), "255.9921875");
+
+ // signed _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(32, /*Unsigned=*/false), 15);
+ ASSERT_STREQ(S.c_str(), "65535.999969482421875");
+
+ // signed long _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(64, /*Unsigned=*/false), 31);
+ ASSERT_STREQ(S.c_str(), "4294967295.9999999995343387126922607421875");
+
+ // unsigned short _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(16, /*Unsigned=*/true), 8);
+ ASSERT_STREQ(S.c_str(), "255.99609375");
+
+ // unsigned _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(32, /*Unsigned=*/true), 16);
+ ASSERT_STREQ(S.c_str(), "65535.9999847412109375");
+
+ // unsigned long _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(64, /*Unsigned=*/true), 32);
+ ASSERT_STREQ(S.c_str(), "4294967295.99999999976716935634613037109375");
+
+ // signed short _Fract
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(8, /*Unsigned=*/false), 7);
+ ASSERT_STREQ(S.c_str(), "0.9921875");
+
+ // signed _Fract
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(16, /*Unsigned=*/false), 15);
+ ASSERT_STREQ(S.c_str(), "0.999969482421875");
+
+ // signed long _Fract
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(32, /*Unsigned=*/false), 31);
+ ASSERT_STREQ(S.c_str(), "0.9999999995343387126922607421875");
+
+ // unsigned short _Fract
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(8, /*Unsigned=*/true), 8);
+ ASSERT_STREQ(S.c_str(), "0.99609375");
+
+ // unsigned _Fract
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(16, /*Unsigned=*/true), 16);
+ ASSERT_STREQ(S.c_str(), "0.9999847412109375");
+
+ // unsigned long _Fract
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMaxValue(32, /*Unsigned=*/true), 32);
+ ASSERT_STREQ(S.c_str(), "0.99999999976716935634613037109375");
+}
+
+TEST(FixedPointString, Negative) {
+ SmallString<64> S;
+ FixedPointValueToString(S, APSInt::get(-320), 7);
+ ASSERT_STREQ(S.c_str(), "-2.5");
+
+ S.clear();
+ FixedPointValueToString(S, APSInt::get(-64), 7);
+ ASSERT_STREQ(S.c_str(), "-0.5");
+
+ // signed short _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMinValue(16, /*Unsigned=*/false), 7);
+ ASSERT_STREQ(S.c_str(), "-256.0");
+
+ // signed _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMinValue(32, /*Unsigned=*/false), 15);
+ ASSERT_STREQ(S.c_str(), "-65536.0");
+
+ // signed long _Accum
+ S.clear();
+ FixedPointValueToString(S, APSInt::getMinValue(64, /*Unsigned=*/false), 31);
+ ASSERT_STREQ(S.c_str(), "-4294967296.0");
+}
+
+} // namespace
diff --git a/unittests/Index/CMakeLists.txt b/unittests/Index/CMakeLists.txt
new file mode 100644
index 000000000000..2756fad906a3
--- /dev/null
+++ b/unittests/Index/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Support
+ )
+
+add_clang_unittest(IndexTests
+ IndexTests.cpp
+ )
+
+target_link_libraries(IndexTests
+ PRIVATE
+ clangAST
+ clangBasic
+ clangFrontend
+ clangIndex
+ clangLex
+ clangSerialization
+ clangTooling
+ )
diff --git a/unittests/Index/IndexTests.cpp b/unittests/Index/IndexTests.cpp
new file mode 100644
index 000000000000..2d4463d833cc
--- /dev/null
+++ b/unittests/Index/IndexTests.cpp
@@ -0,0 +1,125 @@
+//===--- IndexTests.cpp - Test indexing actions -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Decl.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexSymbol.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+namespace clang {
+namespace index {
+
+struct TestSymbol {
+ std::string QName;
+ // FIXME: add more information.
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) {
+ return OS << S.QName;
+}
+
+namespace {
+class Indexer : public IndexDataConsumer {
+public:
+ bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation>, SourceLocation,
+ ASTNodeInfo) override {
+ const auto *ND = llvm::dyn_cast<NamedDecl>(D);
+ if (!ND)
+ return true;
+ TestSymbol S;
+ S.QName = ND->getQualifiedNameAsString();
+ Symbols.push_back(std::move(S));
+ return true;
+ }
+
+ bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *,
+ SymbolRoleSet, SourceLocation) override {
+ TestSymbol S;
+ S.QName = Name->getName();
+ Symbols.push_back(std::move(S));
+ return true;
+ }
+
+ std::vector<TestSymbol> Symbols;
+};
+
+class IndexAction : public ASTFrontendAction {
+public:
+ IndexAction(std::shared_ptr<Indexer> Index,
+ IndexingOptions Opts = IndexingOptions())
+ : Index(std::move(Index)), Opts(Opts) {}
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override {
+ class Consumer : public ASTConsumer {
+ std::shared_ptr<Indexer> Index;
+ std::shared_ptr<Preprocessor> PP;
+ IndexingOptions Opts;
+
+ public:
+ Consumer(std::shared_ptr<Indexer> Index, std::shared_ptr<Preprocessor> PP,
+ IndexingOptions Opts)
+ : Index(std::move(Index)), PP(std::move(PP)), Opts(Opts) {}
+
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ std::vector<Decl *> DeclsToIndex(
+ Ctx.getTranslationUnitDecl()->decls().begin(),
+ Ctx.getTranslationUnitDecl()->decls().end());
+ indexTopLevelDecls(Ctx, *PP, DeclsToIndex, *Index, Opts);
+ }
+ };
+ return llvm::make_unique<Consumer>(Index, CI.getPreprocessorPtr(), Opts);
+ }
+
+private:
+ std::shared_ptr<Indexer> Index;
+ IndexingOptions Opts;
+};
+
+using testing::Contains;
+using testing::Not;
+using testing::UnorderedElementsAre;
+
+MATCHER_P(QName, Name, "") { return arg.QName == Name; }
+
+TEST(IndexTest, Simple) {
+ auto Index = std::make_shared<Indexer>();
+ tooling::runToolOnCode(new IndexAction(Index), "class X {}; void f() {}");
+ EXPECT_THAT(Index->Symbols, UnorderedElementsAre(QName("X"), QName("f")));
+}
+
+TEST(IndexTest, IndexPreprocessorMacros) {
+ std::string Code = "#define INDEX_MAC 1";
+ auto Index = std::make_shared<Indexer>();
+ IndexingOptions Opts;
+ Opts.IndexMacrosInPreprocessor = true;
+ tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
+ EXPECT_THAT(Index->Symbols, Contains(QName("INDEX_MAC")));
+
+ Opts.IndexMacrosInPreprocessor = false;
+ Index->Symbols.clear();
+ tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
+ EXPECT_THAT(Index->Symbols, UnorderedElementsAre());
+}
+
+} // namespace
+} // namespace index
+} // namespace clang
diff --git a/unittests/Lex/HeaderSearchTest.cpp b/unittests/Lex/HeaderSearchTest.cpp
index c2794f5e9593..060135bc731a 100644
--- a/unittests/Lex/HeaderSearchTest.cpp
+++ b/unittests/Lex/HeaderSearchTest.cpp
@@ -27,7 +27,7 @@ namespace {
class HeaderSearchTest : public ::testing::Test {
protected:
HeaderSearchTest()
- : VFS(new vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS),
+ : VFS(new llvm::vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS),
DiagID(new DiagnosticIDs()),
Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions),
@@ -46,7 +46,7 @@ protected:
Search.AddSearchPath(DL, /*isAngled=*/false);
}
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS;
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
FileSystemOptions FileMgrOpts;
FileManager FileMgr;
IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
diff --git a/unittests/Lex/PPCallbacksTest.cpp b/unittests/Lex/PPCallbacksTest.cpp
index 0fa6286cc048..838e033e3df4 100644
--- a/unittests/Lex/PPCallbacksTest.cpp
+++ b/unittests/Lex/PPCallbacksTest.cpp
@@ -65,6 +65,29 @@ public:
SrcMgr::CharacteristicKind FileType;
};
+class CondDirectiveCallbacks : public PPCallbacks {
+public:
+ struct Result {
+ SourceRange ConditionRange;
+ ConditionValueKind ConditionValue;
+
+ Result(SourceRange R, ConditionValueKind K)
+ : ConditionRange(R), ConditionValue(K) {}
+ };
+
+ std::vector<Result> Results;
+
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override {
+ Results.emplace_back(ConditionRange, ConditionValue);
+ }
+
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
+ Results.emplace_back(ConditionRange, ConditionValue);
+ }
+};
+
// Stub to collect data from PragmaOpenCLExtension callbacks.
class PragmaOpenCLExtensionCallbacks : public PPCallbacks {
public:
@@ -95,7 +118,7 @@ public:
class PPCallbacksTest : public ::testing::Test {
protected:
PPCallbacksTest()
- : InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
FileMgr(FileSystemOptions(), InMemoryFileSystem),
DiagID(new DiagnosticIDs()), DiagOpts(new DiagnosticOptions()),
Diags(DiagID, DiagOpts.get(), new IgnoringDiagConsumer()),
@@ -104,7 +127,7 @@ protected:
Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
}
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
FileManager FileMgr;
IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
@@ -116,17 +139,17 @@ protected:
// Register a header path as a known file and add its location
// to search path.
- void AddFakeHeader(HeaderSearch& HeaderInfo, const char* HeaderPath,
- bool IsSystemHeader) {
- // Tell FileMgr about header.
- InMemoryFileSystem->addFile(HeaderPath, 0,
- llvm::MemoryBuffer::getMemBuffer("\n"));
-
- // Add header's parent path to search path.
- StringRef SearchPath = llvm::sys::path::parent_path(HeaderPath);
- const DirectoryEntry *DE = FileMgr.getDirectory(SearchPath);
- DirectoryLookup DL(DE, SrcMgr::C_User, false);
- HeaderInfo.AddSearchPath(DL, IsSystemHeader);
+ void AddFakeHeader(HeaderSearch &HeaderInfo, const char *HeaderPath,
+ bool IsSystemHeader) {
+ // Tell FileMgr about header.
+ InMemoryFileSystem->addFile(HeaderPath, 0,
+ llvm::MemoryBuffer::getMemBuffer("\n"));
+
+ // Add header's parent path to search path.
+ StringRef SearchPath = llvm::sys::path::parent_path(HeaderPath);
+ const DirectoryEntry *DE = FileMgr.getDirectory(SearchPath);
+ DirectoryLookup DL(DE, SrcMgr::C_User, false);
+ HeaderInfo.AddSearchPath(DL, IsSystemHeader);
}
// Get the raw source string of the range.
@@ -137,10 +160,20 @@ protected:
return StringRef(B, E - B);
}
+ StringRef GetSourceStringToEnd(CharSourceRange Range) {
+ const char *B = SourceMgr.getCharacterData(Range.getBegin());
+ const char *E = SourceMgr.getCharacterData(Range.getEnd());
+
+ return StringRef(
+ B,
+ E - B + Lexer::MeasureTokenLength(Range.getEnd(), SourceMgr, LangOpts));
+ }
+
// Run lexer over SourceText and collect FilenameRange from
// the InclusionDirective callback.
- CharSourceRange InclusionDirectiveFilenameRange(const char* SourceText,
- const char* HeaderPath, bool SystemHeader) {
+ CharSourceRange InclusionDirectiveFilenameRange(const char *SourceText,
+ const char *HeaderPath,
+ bool SystemHeader) {
std::unique_ptr<llvm::MemoryBuffer> Buf =
llvm::MemoryBuffer::getMemBuffer(SourceText);
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
@@ -198,8 +231,38 @@ protected:
return Callbacks;
}
- PragmaOpenCLExtensionCallbacks::CallbackParameters
- PragmaOpenCLExtensionCall(const char* SourceText) {
+ std::vector<CondDirectiveCallbacks::Result>
+ DirectiveExprRange(StringRef SourceText) {
+ TrivialModuleLoader ModLoader;
+ MemoryBufferCache PCMCache;
+ std::unique_ptr<llvm::MemoryBuffer> Buf =
+ llvm::MemoryBuffer::getMemBuffer(SourceText);
+ SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+ HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
+ Diags, LangOpts, Target.get());
+ Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
+ SourceMgr, PCMCache, HeaderInfo, ModLoader,
+ /*IILookup =*/nullptr,
+ /*OwnsHeaderSearch =*/false);
+ PP.Initialize(*Target);
+ auto *Callbacks = new CondDirectiveCallbacks;
+ PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
+
+ // Lex source text.
+ PP.EnterMainSourceFile();
+
+ while (true) {
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.is(tok::eof))
+ break;
+ }
+
+ return Callbacks->Results;
+ }
+
+ PragmaOpenCLExtensionCallbacks::CallbackParameters
+ PragmaOpenCLExtensionCall(const char *SourceText) {
LangOptions OpenCLLangOpts;
OpenCLLangOpts.OpenCL = 1;
@@ -221,9 +284,8 @@ protected:
// parser actually sets correct pragma handlers for preprocessor
// according to LangOptions, so we init Parser to register opencl
// pragma handlers
- ASTContext Context(OpenCLLangOpts, SourceMgr,
- PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
+ ASTContext Context(OpenCLLangOpts, SourceMgr, PP.getIdentifierTable(),
+ PP.getSelectorTable(), PP.getBuiltinInfo());
Context.InitBuiltinTypes(*Target);
ASTConsumer Consumer;
@@ -245,7 +307,7 @@ protected:
Callbacks->Name,
Callbacks->State
};
- return RetVal;
+ return RetVal;
}
};
@@ -368,4 +430,17 @@ TEST_F(PPCallbacksTest, OpenCLExtensionPragmaDisabled) {
ASSERT_EQ(ExpectedState, Parameters.State);
}
-} // anonoymous namespace
+TEST_F(PPCallbacksTest, DirectiveExprRanges) {
+ const auto &Results8 =
+ DirectiveExprRange("#define FLOOFY 0\n#if __FILE__ > FLOOFY\n#endif\n");
+ EXPECT_EQ(Results8.size(), 1U);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results8[0].ConditionRange, false)),
+ " __FILE__ > FLOOFY\n#");
+ EXPECT_EQ(
+ Lexer::getSourceText(CharSourceRange(Results8[0].ConditionRange, false),
+ SourceMgr, LangOpts),
+ " __FILE__ > FLOOFY\n");
+}
+
+} // namespace
diff --git a/unittests/Rename/CMakeLists.txt b/unittests/Rename/CMakeLists.txt
index b625a7a691fb..f91021dd1545 100644
--- a/unittests/Rename/CMakeLists.txt
+++ b/unittests/Rename/CMakeLists.txt
@@ -21,6 +21,7 @@ target_link_libraries(ClangRenameTests
clangFormat
clangFrontend
clangRewrite
+ clangSerialization
clangTooling
clangToolingCore
clangToolingRefactor
diff --git a/unittests/Rename/ClangRenameTest.h b/unittests/Rename/ClangRenameTest.h
index 0933dd5aaf4f..13906d15bca5 100644
--- a/unittests/Rename/ClangRenameTest.h
+++ b/unittests/Rename/ClangRenameTest.h
@@ -7,11 +7,13 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_UNITTESTS_RENAME_CLANGRENAMETEST_H
+#define LLVM_CLANG_UNITTESTS_RENAME_CLANGRENAMETEST_H
+
#include "unittests/Tooling/RewriterTestContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/PCHContainerOperations.h"
@@ -23,6 +25,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"
#include <memory>
#include <string>
@@ -110,3 +113,5 @@ protected:
} // namespace test
} // namespace clang_rename
} // namesdpace clang
+
+#endif
diff --git a/unittests/Sema/CMakeLists.txt b/unittests/Sema/CMakeLists.txt
index 45460f1e0f6c..78601046dcd4 100644
--- a/unittests/Sema/CMakeLists.txt
+++ b/unittests/Sema/CMakeLists.txt
@@ -14,5 +14,6 @@ target_link_libraries(SemaTests
clangFrontend
clangParse
clangSema
+ clangSerialization
clangTooling
)
diff --git a/unittests/Sema/CodeCompleteTest.cpp b/unittests/Sema/CodeCompleteTest.cpp
index 04cb14b971ec..28faa0c1eeb6 100644
--- a/unittests/Sema/CodeCompleteTest.cpp
+++ b/unittests/Sema/CodeCompleteTest.cpp
@@ -14,31 +14,44 @@
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Tooling/Tooling.h"
-#include "gtest/gtest.h"
#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <cstddef>
+#include <string>
namespace {
using namespace clang;
using namespace clang::tooling;
+using ::testing::Each;
using ::testing::UnorderedElementsAre;
const char TestCCName[] = "test.cc";
-using VisitedContextResults = std::vector<std::string>;
-class VisitedContextFinder: public CodeCompleteConsumer {
+struct CompletionContext {
+ std::vector<std::string> VisitedNamespaces;
+ std::string PreferredType;
+ // String representation of std::ptrdiff_t on a given platform. This is a hack
+ // to properly account for different configurations of clang.
+ std::string PtrDiffType;
+};
+
+class VisitedContextFinder : public CodeCompleteConsumer {
public:
- VisitedContextFinder(VisitedContextResults &Results)
+ VisitedContextFinder(CompletionContext &ResultCtx)
: CodeCompleteConsumer(/*CodeCompleteOpts=*/{},
/*CodeCompleteConsumer*/ false),
- VCResults(Results),
+ ResultCtx(ResultCtx),
CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
CodeCompletionResult *Results,
unsigned NumResults) override {
- VisitedContexts = Context.getVisitedContexts();
- VCResults = getVisitedNamespace();
+ ResultCtx.VisitedNamespaces =
+ getVisitedNamespace(Context.getVisitedContexts());
+ ResultCtx.PreferredType = Context.getPreferredType().getAsString();
+ ResultCtx.PtrDiffType =
+ S.getASTContext().getPointerDiffType().getAsString();
}
CodeCompletionAllocator &getAllocator() override {
@@ -47,7 +60,9 @@ public:
CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
- std::vector<std::string> getVisitedNamespace() const {
+private:
+ std::vector<std::string> getVisitedNamespace(
+ CodeCompletionContext::VisitedContextSet VisitedContexts) const {
std::vector<std::string> NSNames;
for (const auto *Context : VisitedContexts)
if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(Context))
@@ -55,27 +70,25 @@ public:
return NSNames;
}
-private:
- VisitedContextResults& VCResults;
+ CompletionContext &ResultCtx;
CodeCompletionTUInfo CCTUInfo;
- CodeCompletionContext::VisitedContextSet VisitedContexts;
};
class CodeCompleteAction : public SyntaxOnlyAction {
public:
- CodeCompleteAction(ParsedSourceLocation P, VisitedContextResults &Results)
- : CompletePosition(std::move(P)), VCResults(Results) {}
+ CodeCompleteAction(ParsedSourceLocation P, CompletionContext &ResultCtx)
+ : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
bool BeginInvocation(CompilerInstance &CI) override {
CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
- CI.setCodeCompletionConsumer(new VisitedContextFinder(VCResults));
+ CI.setCodeCompletionConsumer(new VisitedContextFinder(ResultCtx));
return true;
}
private:
// 1-based code complete position <Line, Col>;
ParsedSourceLocation CompletePosition;
- VisitedContextResults& VCResults;
+ CompletionContext &ResultCtx;
};
ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
@@ -88,21 +101,57 @@ ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
static_cast<unsigned>(Offset - StartOfLine + 1)};
}
-VisitedContextResults runCodeCompleteOnCode(StringRef Code) {
- VisitedContextResults Results;
- auto TokenOffset = Code.find('^');
- assert(TokenOffset != StringRef::npos &&
- "Completion token ^ wasn't found in Code.");
- std::string WithoutToken = Code.take_front(TokenOffset);
- WithoutToken += Code.drop_front(WithoutToken.size() + 1);
- assert(StringRef(WithoutToken).find('^') == StringRef::npos &&
- "expected exactly one completion token ^ inside the code");
-
+CompletionContext runCompletion(StringRef Code, size_t Offset) {
+ CompletionContext ResultCtx;
auto Action = llvm::make_unique<CodeCompleteAction>(
- offsetToPosition(WithoutToken, TokenOffset), Results);
+ offsetToPosition(Code, Offset), ResultCtx);
clang::tooling::runToolOnCodeWithArgs(Action.release(), Code, {"-std=c++11"},
TestCCName);
- return Results;
+ return ResultCtx;
+}
+
+struct ParsedAnnotations {
+ std::vector<size_t> Points;
+ std::string Code;
+};
+
+ParsedAnnotations parseAnnotations(StringRef AnnotatedCode) {
+ ParsedAnnotations R;
+ while (!AnnotatedCode.empty()) {
+ size_t NextPoint = AnnotatedCode.find('^');
+ if (NextPoint == StringRef::npos) {
+ R.Code += AnnotatedCode;
+ AnnotatedCode = "";
+ break;
+ }
+ R.Code += AnnotatedCode.substr(0, NextPoint);
+ R.Points.push_back(R.Code.size());
+
+ AnnotatedCode = AnnotatedCode.substr(NextPoint + 1);
+ }
+ return R;
+}
+
+CompletionContext runCodeCompleteOnCode(StringRef AnnotatedCode) {
+ ParsedAnnotations P = parseAnnotations(AnnotatedCode);
+ assert(P.Points.size() == 1 && "expected exactly one annotation point");
+ return runCompletion(P.Code, P.Points.front());
+}
+
+std::vector<std::string>
+collectPreferredTypes(StringRef AnnotatedCode,
+ std::string *PtrDiffType = nullptr) {
+ ParsedAnnotations P = parseAnnotations(AnnotatedCode);
+ std::vector<std::string> Types;
+ for (size_t Point : P.Points) {
+ auto Results = runCompletion(P.Code, Point);
+ if (PtrDiffType) {
+ assert(PtrDiffType->empty() || *PtrDiffType == Results.PtrDiffType);
+ *PtrDiffType = Results.PtrDiffType;
+ }
+ Types.push_back(Results.PreferredType);
+ }
+ return Types;
}
TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
@@ -119,7 +168,8 @@ TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
inline namespace bar { using namespace ns3::nns3; }
} // foo
namespace ns { foo::^ }
- )cpp");
+ )cpp")
+ .VisitedNamespaces;
EXPECT_THAT(VisitedNS, UnorderedElementsAre("foo", "ns1", "ns2", "ns3::nns3",
"foo::(anonymous)"));
}
@@ -127,7 +177,8 @@ TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
TEST(SemaCodeCompleteTest, VisitedNSForInvalideQualifiedId) {
auto VisitedNS = runCodeCompleteOnCode(R"cpp(
namespace ns { foo::^ }
- )cpp");
+ )cpp")
+ .VisitedNamespaces;
EXPECT_TRUE(VisitedNS.empty());
}
@@ -138,8 +189,155 @@ TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) {
void f(^) {}
}
}
- )cpp");
+ )cpp")
+ .VisitedNamespaces;
EXPECT_THAT(VisitedNS, UnorderedElementsAre("n1", "n1::n2"));
}
+TEST(PreferredTypeTest, BinaryExpr) {
+ // Check various operations for arithmetic types.
+ StringRef Code = R"cpp(
+ void test(int x) {
+ x = ^10;
+ x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
+ x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
+ })cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
+
+ Code = R"cpp(
+ void test(float x) {
+ x = ^10;
+ x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
+ x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
+ })cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("float"));
+
+ // Pointer types.
+ Code = R"cpp(
+ void test(int *ptr) {
+ ptr - ^ptr;
+ ptr = ^ptr;
+ })cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
+
+ Code = R"cpp(
+ void test(int *ptr) {
+ ptr + ^10;
+ ptr += ^10;
+ ptr -= ^10;
+ })cpp";
+ {
+ std::string PtrDiff;
+ auto Types = collectPreferredTypes(Code, &PtrDiff);
+ EXPECT_THAT(Types, Each(PtrDiff));
+ }
+
+ // Comparison operators.
+ Code = R"cpp(
+ void test(int i) {
+ i <= ^1; i < ^1; i >= ^1; i > ^1; i == ^1; i != ^1;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
+
+ Code = R"cpp(
+ void test(int *ptr) {
+ ptr <= ^ptr; ptr < ^ptr; ptr >= ^ptr; ptr > ^ptr;
+ ptr == ^ptr; ptr != ^ptr;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
+
+ // Relational operations.
+ Code = R"cpp(
+ void test(int i, int *ptr) {
+ i && ^1; i || ^1;
+ ptr && ^1; ptr || ^1;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
+
+ // Bitwise operations.
+ Code = R"cpp(
+ void test(long long ll) {
+ ll | ^1; ll & ^1;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("long long"));
+
+ Code = R"cpp(
+ enum A {};
+ void test(A a) {
+ a | ^1; a & ^1;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("enum A"));
+
+ Code = R"cpp(
+ enum class A {};
+ void test(A a) {
+ // This is technically illegal with the 'enum class' without overloaded
+ // operators, but we pretend it's fine.
+ a | ^a; a & ^a;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("enum A"));
+
+ // Binary shifts.
+ Code = R"cpp(
+ void test(int i, long long ll) {
+ i << ^1; ll << ^1;
+ i <<= ^1; i <<= ^1;
+ i >> ^1; ll >> ^1;
+ i >>= ^1; i >>= ^1;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
+
+ // Comma does not provide any useful information.
+ Code = R"cpp(
+ class Cls {};
+ void test(int i, int* ptr, Cls x) {
+ (i, ^i);
+ (ptr, ^ptr);
+ (x, ^x);
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
+
+ // User-defined types do not take operator overloading into account.
+ // However, they provide heuristics for some common cases.
+ Code = R"cpp(
+ class Cls {};
+ void test(Cls c) {
+ // we assume arithmetic and comparions ops take the same type.
+ c + ^c; c - ^c; c * ^c; c / ^c; c % ^c;
+ c == ^c; c != ^c; c < ^c; c <= ^c; c > ^c; c >= ^c;
+ // same for the assignments.
+ c = ^c; c += ^c; c -= ^c; c *= ^c; c /= ^c; c %= ^c;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("class Cls"));
+
+ Code = R"cpp(
+ class Cls {};
+ void test(Cls c) {
+ // we assume relational ops operate on bools.
+ c && ^c; c || ^c;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
+
+ Code = R"cpp(
+ class Cls {};
+ void test(Cls c) {
+ // we make no assumptions about the following operators, since they are
+ // often overloaded with a non-standard meaning.
+ c << ^c; c >> ^c; c | ^c; c & ^c;
+ c <<= ^c; c >>= ^c; c |= ^c; c &= ^c;
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
+}
+
} // namespace
diff --git a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
index 3d8332554fbc..de41874bdeec 100644
--- a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
+++ b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
@@ -52,23 +52,25 @@ TEST(StaticAnalyzerOptions, SearchInParentPackageTests) {
// Checker one has Option specified as true. It should read true regardless of
// search mode.
CheckerOneMock CheckerOne;
- EXPECT_TRUE(Opts.getBooleanOption("Option", false, &CheckerOne));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option", false, &CheckerOne));
// The package option is overridden with a checker option.
- EXPECT_TRUE(Opts.getBooleanOption("Option", false, &CheckerOne, true));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option", false, &CheckerOne,
+ true));
// The Outer package option is overridden by the Inner package option. No
// package option is specified.
- EXPECT_TRUE(Opts.getBooleanOption("Option2", false, &CheckerOne, true));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option2", false, &CheckerOne,
+ true));
// No package option is specified and search in packages is turned off. The
// default value should be returned.
- EXPECT_FALSE(Opts.getBooleanOption("Option2", false, &CheckerOne));
- EXPECT_TRUE(Opts.getBooleanOption("Option2", true, &CheckerOne));
+ EXPECT_FALSE(Opts.getCheckerBooleanOption("Option2", false, &CheckerOne));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option2", true, &CheckerOne));
// Checker true has no option specified. It should get the default value when
// search in parents turned off and false when search in parents turned on.
CheckerTwoMock CheckerTwo;
- EXPECT_FALSE(Opts.getBooleanOption("Option", false, &CheckerTwo));
- EXPECT_TRUE(Opts.getBooleanOption("Option", true, &CheckerTwo));
- EXPECT_FALSE(Opts.getBooleanOption("Option", true, &CheckerTwo, true));
+ EXPECT_FALSE(Opts.getCheckerBooleanOption("Option", false, &CheckerTwo));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option", true, &CheckerTwo));
+ EXPECT_FALSE(Opts.getCheckerBooleanOption("Option", true, &CheckerTwo, true));
}
TEST(StaticAnalyzerOptions, StringOptions) {
@@ -83,9 +85,9 @@ TEST(StaticAnalyzerOptions, StringOptions) {
CheckerOneMock CheckerOne;
EXPECT_TRUE("StringValue" ==
- Opts.getOptionAsString("Option", "DefaultValue", &CheckerOne));
+ Opts.getCheckerStringOption("Option", "DefaultValue", &CheckerOne));
EXPECT_TRUE("DefaultValue" ==
- Opts.getOptionAsString("Option2", "DefaultValue", &CheckerOne));
+ Opts.getCheckerStringOption("Option2", "DefaultValue", &CheckerOne));
}
} // end namespace ento
} // end namespace clang
diff --git a/unittests/StaticAnalyzer/CMakeLists.txt b/unittests/StaticAnalyzer/CMakeLists.txt
index ff041452dfd4..3036dec1676a 100644
--- a/unittests/StaticAnalyzer/CMakeLists.txt
+++ b/unittests/StaticAnalyzer/CMakeLists.txt
@@ -12,6 +12,7 @@ target_link_libraries(StaticAnalysisTests
clangBasic
clangAnalysis
clangFrontend
+ clangSerialization
clangStaticAnalyzerCore
clangStaticAnalyzerFrontend
clangTooling
diff --git a/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
index dcd115e59631..568a719e3366 100644
--- a/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
+++ b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -11,9 +11,9 @@
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
@@ -21,16 +21,7 @@ namespace clang {
namespace ento {
namespace {
-class CustomChecker : public Checker<check::ASTCodeBody> {
-public:
- void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
- BugReporter &BR) const {
- BR.EmitBasicReport(D, this, "Custom diagnostic", categories::LogicError,
- "Custom diagnostic description",
- PathDiagnosticLocation(D, Mgr.getSourceManager()), {});
- }
-};
-
+template <typename CheckerT>
class TestAction : public ASTFrontendAction {
class DiagConsumer : public PathDiagnosticConsumer {
llvm::raw_ostream &Output;
@@ -59,22 +50,55 @@ public:
Compiler.getAnalyzerOpts()->CheckersControlList = {
{"custom.CustomChecker", true}};
AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<CustomChecker>("custom.CustomChecker", "Description");
+ Registry.addChecker<CheckerT>("custom.CustomChecker", "Description", "");
});
return std::move(AnalysisConsumer);
}
};
+template <typename CheckerT>
+bool runCheckerOnCode(const std::string &Code, std::string &Diags) {
+ llvm::raw_string_ostream OS(Diags);
+ return tooling::runToolOnCode(new TestAction<CheckerT>(OS), Code);
+}
+template <typename CheckerT>
+bool runCheckerOnCode(const std::string &Code) {
+ std::string Diags;
+ return runCheckerOnCode<CheckerT>(Code, Diags);
+}
+
+
+class CustomChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ BR.EmitBasicReport(D, this, "Custom diagnostic", categories::LogicError,
+ "Custom diagnostic description",
+ PathDiagnosticLocation(D, Mgr.getSourceManager()), {});
+ }
+};
TEST(RegisterCustomCheckers, RegisterChecker) {
std::string Diags;
- {
- llvm::raw_string_ostream OS(Diags);
- EXPECT_TRUE(tooling::runToolOnCode(new TestAction(OS), "void f() {;}"));
- }
+ EXPECT_TRUE(runCheckerOnCode<CustomChecker>("void f() {;}", Diags));
EXPECT_EQ(Diags, "custom.CustomChecker:Custom diagnostic description");
}
+class LocIncDecChecker : public Checker<check::Location> {
+public:
+ void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
+ CheckerContext &C) const {
+ auto UnaryOp = dyn_cast<UnaryOperator>(S);
+ if (UnaryOp && !IsLoad)
+ EXPECT_FALSE(UnaryOp->isIncrementOp());
+ }
+};
+
+TEST(RegisterCustomCheckers, CheckLocationIncDec) {
+ EXPECT_TRUE(
+ runCheckerOnCode<LocIncDecChecker>("void f() { int *p; (*p)++; }"));
+}
+
}
}
}
diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt
index e9910fb87aba..7619c7fb2348 100644
--- a/unittests/Tooling/CMakeLists.txt
+++ b/unittests/Tooling/CMakeLists.txt
@@ -40,6 +40,7 @@ add_clang_unittest(ToolingTests
RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
RecursiveASTVisitorTests/ParenExpr.cpp
RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
+ RecursiveASTVisitorTests/TraversalScope.cpp
RecursiveASTVisitorTestDeclVisitor.cpp
RecursiveASTVisitorTestPostOrderVisitor.cpp
RecursiveASTVisitorTestTypeLocVisitor.cpp
@@ -60,6 +61,7 @@ target_link_libraries(ToolingTests
clangFrontend
clangLex
clangRewrite
+ clangSerialization
clangTooling
clangToolingCore
clangToolingInclusions
diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp
index ffc1d5b3a4ac..949d6a3b7392 100644
--- a/unittests/Tooling/CompilationDatabaseTest.cpp
+++ b/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -14,11 +14,15 @@
#include "clang/Tooling/JSONCompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/Path.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace clang {
namespace tooling {
+using testing::ElementsAre;
+using testing::EndsWith;
+
static void expectFailure(StringRef JSONDatabase, StringRef Explanation) {
std::string ErrorMessage;
EXPECT_EQ(nullptr,
@@ -467,21 +471,15 @@ TEST(unescapeJsonCommandLine, ParsesSingleQuotedString) {
}
TEST(FixedCompilationDatabase, ReturnsFixedCommandLine) {
- std::vector<std::string> CommandLine;
- CommandLine.push_back("one");
- CommandLine.push_back("two");
- FixedCompilationDatabase Database(".", CommandLine);
+ FixedCompilationDatabase Database(".", /*CommandLine*/ {"one", "two"});
StringRef FileName("source");
std::vector<CompileCommand> Result =
Database.getCompileCommands(FileName);
ASSERT_EQ(1ul, Result.size());
- std::vector<std::string> ExpectedCommandLine(1, "clang-tool");
- ExpectedCommandLine.insert(ExpectedCommandLine.end(),
- CommandLine.begin(), CommandLine.end());
- ExpectedCommandLine.push_back("source");
EXPECT_EQ(".", Result[0].Directory);
EXPECT_EQ(FileName, Result[0].Filename);
- EXPECT_EQ(ExpectedCommandLine, Result[0].CommandLine);
+ EXPECT_THAT(Result[0].CommandLine,
+ ElementsAre(EndsWith("clang-tool"), "one", "two", "source"));
}
TEST(FixedCompilationDatabase, GetAllFiles) {
@@ -537,12 +535,8 @@ TEST(ParseFixedCompilationDatabase, ReturnsArgumentsAfterDoubleDash) {
Database->getCompileCommands("source");
ASSERT_EQ(1ul, Result.size());
ASSERT_EQ(".", Result[0].Directory);
- std::vector<std::string> CommandLine;
- CommandLine.push_back("clang-tool");
- CommandLine.push_back("-DDEF3");
- CommandLine.push_back("-DDEF4");
- CommandLine.push_back("source");
- ASSERT_EQ(CommandLine, Result[0].CommandLine);
+ ASSERT_THAT(Result[0].CommandLine, ElementsAre(EndsWith("clang-tool"),
+ "-DDEF3", "-DDEF4", "source"));
EXPECT_EQ(2, Argc);
}
@@ -558,10 +552,8 @@ TEST(ParseFixedCompilationDatabase, ReturnsEmptyCommandLine) {
Database->getCompileCommands("source");
ASSERT_EQ(1ul, Result.size());
ASSERT_EQ(".", Result[0].Directory);
- std::vector<std::string> CommandLine;
- CommandLine.push_back("clang-tool");
- CommandLine.push_back("source");
- ASSERT_EQ(CommandLine, Result[0].CommandLine);
+ ASSERT_THAT(Result[0].CommandLine,
+ ElementsAre(EndsWith("clang-tool"), "source"));
EXPECT_EQ(2, Argc);
}
@@ -577,12 +569,8 @@ TEST(ParseFixedCompilationDatabase, HandlesPositionalArgs) {
Database->getCompileCommands("source");
ASSERT_EQ(1ul, Result.size());
ASSERT_EQ(".", Result[0].Directory);
- std::vector<std::string> Expected;
- Expected.push_back("clang-tool");
- Expected.push_back("-c");
- Expected.push_back("-DDEF3");
- Expected.push_back("source");
- ASSERT_EQ(Expected, Result[0].CommandLine);
+ ASSERT_THAT(Result[0].CommandLine,
+ ElementsAre(EndsWith("clang-tool"), "-c", "-DDEF3", "source"));
EXPECT_EQ(2, Argc);
}
@@ -599,12 +587,9 @@ TEST(ParseFixedCompilationDatabase, HandlesPositionalArgsSyntaxOnly) {
std::vector<CompileCommand> Result = Database->getCompileCommands("source");
ASSERT_EQ(1ul, Result.size());
ASSERT_EQ(".", Result[0].Directory);
- std::vector<std::string> Expected;
- Expected.push_back("clang-tool");
- Expected.push_back("-fsyntax-only");
- Expected.push_back("-DDEF3");
- Expected.push_back("source");
- ASSERT_EQ(Expected, Result[0].CommandLine);
+ ASSERT_THAT(
+ Result[0].CommandLine,
+ ElementsAre(EndsWith("clang-tool"), "-fsyntax-only", "-DDEF3", "source"));
}
TEST(ParseFixedCompilationDatabase, HandlesArgv0) {
@@ -620,9 +605,8 @@ TEST(ParseFixedCompilationDatabase, HandlesArgv0) {
ASSERT_EQ(1ul, Result.size());
ASSERT_EQ(".", Result[0].Directory);
std::vector<std::string> Expected;
- Expected.push_back("clang-tool");
- Expected.push_back("source");
- ASSERT_EQ(Expected, Result[0].CommandLine);
+ ASSERT_THAT(Result[0].CommandLine,
+ ElementsAre(EndsWith("clang-tool"), "source"));
EXPECT_EQ(2, Argc);
}
@@ -648,14 +632,17 @@ class InterpolateTest : public ::testing::Test {
protected:
// Adds an entry to the underlying compilation database.
// A flag is injected: -D <File>, so the command used can be identified.
- void add(llvm::StringRef File, llvm::StringRef Flags = "") {
- llvm::SmallVector<StringRef, 8> Argv = {"clang", File, "-D", File};
+ void add(StringRef File, StringRef Clang, StringRef Flags) {
+ SmallVector<StringRef, 8> Argv = {Clang, File, "-D", File};
llvm::SplitString(Flags, Argv);
- llvm::SmallString<32> Dir;
+
+ SmallString<32> Dir;
llvm::sys::path::system_temp_directory(false, Dir);
+
Entries[path(File)].push_back(
{Dir, path(File), {Argv.begin(), Argv.end()}, "foo.o"});
}
+ void add(StringRef File, StringRef Flags = "") { add(File, "clang", Flags); }
// Turn a unix path fragment (foo/bar.h) into a native path (C:\tmp\foo\bar.h)
std::string path(llvm::SmallString<32> File) {
@@ -707,6 +694,7 @@ TEST_F(InterpolateTest, Nearby) {
TEST_F(InterpolateTest, Language) {
add("dir/foo.cpp", "-std=c++17");
+ add("dir/bar.c", "");
add("dir/baz.cee", "-x c");
// .h is ambiguous, so we add explicit language flags
@@ -716,9 +704,11 @@ TEST_F(InterpolateTest, Language) {
EXPECT_EQ(getCommand("foo.hpp"), "clang -D dir/foo.cpp -std=c++17");
// respect -x if it's already there.
EXPECT_EQ(getCommand("baz.h"), "clang -D dir/baz.cee -x c-header");
- // prefer a worse match with the right language
- EXPECT_EQ(getCommand("foo.c"), "clang -D dir/baz.cee");
- Entries.erase(path(StringRef("dir/baz.cee")));
+ // prefer a worse match with the right extension.
+ EXPECT_EQ(getCommand("foo.c"), "clang -D dir/bar.c");
+ // make sure we don't crash on queries with invalid extensions.
+ EXPECT_EQ(getCommand("foo.cce"), "clang -D dir/foo.cpp");
+ Entries.erase(path(StringRef("dir/bar.c")));
// Now we transfer across languages, so drop -std too.
EXPECT_EQ(getCommand("foo.c"), "clang -D dir/foo.cpp");
}
@@ -736,6 +726,30 @@ TEST_F(InterpolateTest, Case) {
EXPECT_EQ(getCommand("foo/bar/baz/shout.C"), "clang -D FOO/BAR/BAZ/SHOUT.cc");
}
+TEST_F(InterpolateTest, Aliasing) {
+ add("foo.cpp", "-faligned-new");
+
+ // The interpolated command should keep the given flag as written, even though
+ // the flag is internally represented as an alias.
+ EXPECT_EQ(getCommand("foo.hpp"), "clang -D foo.cpp -faligned-new");
+}
+
+TEST_F(InterpolateTest, ClangCL) {
+ add("foo.cpp", "clang-cl", "/W4");
+
+ // Language flags should be added with CL syntax.
+ EXPECT_EQ(getCommand("foo.h"), "clang-cl -D foo.cpp /W4 /TP");
+}
+
+TEST_F(InterpolateTest, DriverModes) {
+ add("foo.cpp", "clang-cl", "--driver-mode=gcc");
+ add("bar.cpp", "clang", "--driver-mode=cl");
+
+ // --driver-mode overrides should be respected.
+ EXPECT_EQ(getCommand("foo.h"), "clang-cl -D foo.cpp --driver-mode=gcc -x c++-header");
+ EXPECT_EQ(getCommand("bar.h"), "clang -D bar.cpp --driver-mode=cl /TP");
+}
+
TEST(CompileCommandTest, EqualityOperator) {
CompileCommand CCRef("/foo/bar", "hello.c", {"a", "b"}, "hello.o");
CompileCommand CCTest = CCRef;
diff --git a/unittests/Tooling/DiagnosticsYamlTest.cpp b/unittests/Tooling/DiagnosticsYamlTest.cpp
index 83e09eaeef2d..f4de53fad25a 100644
--- a/unittests/Tooling/DiagnosticsYamlTest.cpp
+++ b/unittests/Tooling/DiagnosticsYamlTest.cpp
@@ -20,16 +20,21 @@ using namespace llvm;
using namespace clang::tooling;
using clang::tooling::Diagnostic;
-static Diagnostic makeDiagnostic(StringRef DiagnosticName,
- const std::string &Message, int FileOffset,
- const std::string &FilePath,
- const StringMap<Replacements> &Fix) {
+static DiagnosticMessage makeMessage(const std::string &Message, int FileOffset,
+ const std::string &FilePath) {
DiagnosticMessage DiagMessage;
DiagMessage.Message = Message;
DiagMessage.FileOffset = FileOffset;
DiagMessage.FilePath = FilePath;
- return Diagnostic(DiagnosticName, DiagMessage, Fix, {}, Diagnostic::Warning,
- "path/to/build/directory");
+ return DiagMessage;
+}
+
+static Diagnostic makeDiagnostic(StringRef DiagnosticName,
+ const std::string &Message, int FileOffset,
+ const std::string &FilePath,
+ const StringMap<Replacements> &Fix) {
+ return Diagnostic(DiagnosticName, makeMessage(Message, FileOffset, FilePath),
+ Fix, {}, Diagnostic::Warning, "path/to/build/directory");
}
TEST(DiagnosticsYamlTest, serializesDiagnostics) {
@@ -50,6 +55,10 @@ TEST(DiagnosticsYamlTest, serializesDiagnostics) {
TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#3", "message #3", 72,
"path/to/source2.cpp", {}));
+ TUD.Diagnostics.back().Notes.push_back(
+ makeMessage("Note1", 88, "path/to/note1.cpp"));
+ TUD.Diagnostics.back().Notes.push_back(
+ makeMessage("Note2", 99, "path/to/note2.cpp"));
std::string YamlContent;
raw_string_ostream YamlContentStream(YamlContent);
@@ -58,31 +67,38 @@ TEST(DiagnosticsYamlTest, serializesDiagnostics) {
YAML << TUD;
EXPECT_EQ("---\n"
- "MainSourceFile: path/to/source.cpp\n"
+ "MainSourceFile: 'path/to/source.cpp'\n"
"Diagnostics: \n"
" - DiagnosticName: 'diagnostic#1\'\n"
" Message: 'message #1'\n"
" FileOffset: 55\n"
- " FilePath: path/to/source.cpp\n"
+ " FilePath: 'path/to/source.cpp'\n"
" Replacements: \n"
- " - FilePath: path/to/source.cpp\n"
+ " - FilePath: 'path/to/source.cpp'\n"
" Offset: 100\n"
" Length: 12\n"
" ReplacementText: 'replacement #1'\n"
" - DiagnosticName: 'diagnostic#2'\n"
" Message: 'message #2'\n"
" FileOffset: 60\n"
- " FilePath: path/to/header.h\n"
+ " FilePath: 'path/to/header.h'\n"
" Replacements: \n"
- " - FilePath: path/to/header.h\n"
+ " - FilePath: 'path/to/header.h'\n"
" Offset: 62\n"
" Length: 2\n"
" ReplacementText: 'replacement #2'\n"
" - DiagnosticName: 'diagnostic#3'\n"
" Message: 'message #3'\n"
" FileOffset: 72\n"
- " FilePath: path/to/source2.cpp\n"
- " Replacements: \n"
+ " FilePath: 'path/to/source2.cpp'\n"
+ " Notes: \n"
+ " - Message: Note1\n"
+ " FilePath: 'path/to/note1.cpp'\n"
+ " FileOffset: 88\n"
+ " - Message: Note2\n"
+ " FilePath: 'path/to/note2.cpp'\n"
+ " FileOffset: 99\n"
+ " Replacements: []\n"
"...\n",
YamlContentStream.str());
}
@@ -113,7 +129,14 @@ TEST(DiagnosticsYamlTest, deserializesDiagnostics) {
" Message: 'message #3'\n"
" FileOffset: 98\n"
" FilePath: path/to/source.cpp\n"
- " Replacements: \n"
+ " Notes:\n"
+ " - Message: Note1\n"
+ " FilePath: 'path/to/note1.cpp'\n"
+ " FileOffset: 66\n"
+ " - Message: Note2\n"
+ " FilePath: 'path/to/note2.cpp'\n"
+ " FileOffset: 77\n"
+ " Replacements: []\n"
"...\n";
TranslationUnitDiagnostics TUDActual;
yaml::Input YAML(YamlContent);
@@ -162,6 +185,13 @@ TEST(DiagnosticsYamlTest, deserializesDiagnostics) {
EXPECT_EQ("message #3", D3.Message.Message);
EXPECT_EQ(98u, D3.Message.FileOffset);
EXPECT_EQ("path/to/source.cpp", D3.Message.FilePath);
+ EXPECT_EQ(2u, D3.Notes.size());
+ EXPECT_EQ("Note1", D3.Notes[0].Message);
+ EXPECT_EQ(66u, D3.Notes[0].FileOffset);
+ EXPECT_EQ("path/to/note1.cpp", D3.Notes[0].FilePath);
+ EXPECT_EQ("Note2", D3.Notes[1].Message);
+ EXPECT_EQ(77u, D3.Notes[1].FileOffset);
+ EXPECT_EQ("path/to/note2.cpp", D3.Notes[1].FilePath);
std::vector<Replacement> Fixes3 = getFixes(D3.Fix);
EXPECT_TRUE(Fixes3.empty());
}
diff --git a/unittests/Tooling/ExecutionTest.cpp b/unittests/Tooling/ExecutionTest.cpp
index 26db8c6d0ea8..785ec7c2bc67 100644
--- a/unittests/Tooling/ExecutionTest.cpp
+++ b/unittests/Tooling/ExecutionTest.cpp
@@ -96,6 +96,8 @@ public:
StringRef getExecutorName() const override { return ExecutorName; }
+ bool isSingleProcess() const override { return true; }
+
llvm::Error
execute(llvm::ArrayRef<std::pair<std::unique_ptr<FrontendActionFactory>,
ArgumentsAdjuster>>) override {
@@ -246,12 +248,14 @@ private:
MATCHER_P(Named, Name, "") { return arg.first == Name; }
TEST(AllTUsToolTest, AFewFiles) {
- FixedCompilationDatabaseWithFiles Compilations(".", {"a.cc", "b.cc", "c.cc"},
- std::vector<std::string>());
+ FixedCompilationDatabaseWithFiles Compilations(
+ ".", {"a.cc", "b.cc", "c.cc", "ignore.cc"}, std::vector<std::string>());
AllTUsToolExecutor Executor(Compilations, /*ThreadCount=*/0);
+ Filter.setValue("[a-c].cc");
Executor.mapVirtualFile("a.cc", "void x() {}");
Executor.mapVirtualFile("b.cc", "void y() {}");
Executor.mapVirtualFile("c.cc", "void z() {}");
+ Executor.mapVirtualFile("ignore.cc", "void d() {}");
auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>(
new ReportResultActionFactory(Executor.getExecutionContext())));
@@ -259,6 +263,7 @@ TEST(AllTUsToolTest, AFewFiles) {
EXPECT_THAT(
Executor.getToolResults()->AllKVResults(),
::testing::UnorderedElementsAre(Named("x"), Named("y"), Named("z")));
+ Filter.setValue(".*"); // reset to default value.
}
TEST(AllTUsToolTest, ManyFiles) {
diff --git a/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp b/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
index 50727a55fc71..7387e9c44d5d 100644
--- a/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
+++ b/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp
@@ -61,7 +61,7 @@ public:
}
template <class T> void match(StringRef Path, const T *D) {
- Match(Path, D->getLocStart());
+ Match(Path, D->getBeginLoc());
}
};
diff --git a/unittests/Tooling/LookupTest.cpp b/unittests/Tooling/LookupTest.cpp
index f42f31e9dd99..a08b2b418f7b 100644
--- a/unittests/Tooling/LookupTest.cpp
+++ b/unittests/Tooling/LookupTest.cpp
@@ -68,7 +68,7 @@ TEST(LookupTest, replaceNestedFunctionName) {
"namespace b { void f() { a::foo(); } }\n");
Visitor.OnCall = [&](CallExpr *Expr) {
- EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ EXPECT_EQ("::a::bar", replaceCallExpr(Expr, "::a::bar"));
};
Visitor.runOver("namespace a { void foo(); }\n"
"namespace b { namespace a { void foo(); }\n"
@@ -127,6 +127,38 @@ TEST(LookupTest, replaceNestedFunctionName) {
"namespace a { namespace b { namespace c {"
"void f() { foo(); }"
"} } }\n");
+
+ // If the shortest name is ambiguous, we need to add more qualifiers.
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("::a::y::bar", replaceCallExpr(Expr, "::a::y::bar"));
+ };
+ Visitor.runOver(R"(
+ namespace a {
+ namespace b {
+ namespace x { void foo() {} }
+ namespace y { void foo() {} }
+ }
+ }
+
+ namespace a {
+ namespace b {
+ void f() { x::foo(); }
+ }
+ })");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("y::bar", replaceCallExpr(Expr, "::y::bar"));
+ };
+ Visitor.runOver(R"(
+ namespace a {
+ namespace b {
+ namespace x { void foo() {} }
+ namespace y { void foo() {} }
+ }
+ }
+
+ void f() { a::b::x::foo(); }
+ )");
}
TEST(LookupTest, replaceNestedClassName) {
diff --git a/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
index 63bfb8b2e6c1..e91873c40644 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
@@ -16,7 +16,7 @@ namespace {
class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
public:
bool VisitVarDecl(VarDecl *Variable) {
- Match(Variable->getNameAsString(), Variable->getLocStart());
+ Match(Variable->getNameAsString(), Variable->getBeginLoc());
return true;
}
};
@@ -36,7 +36,7 @@ public:
bool shouldVisitImplicitCode() const { return true; }
bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
- Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
+ Match(ParamVar->getNameAsString(), ParamVar->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
index a6ba92ea03b5..33163c30e5d0 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
@@ -18,7 +18,7 @@ namespace {
class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
public:
bool VisitMemberExpr(MemberExpr *ME) {
- Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
+ Match(ME->getMemberDecl()->getNameAsString(), ME->getBeginLoc());
return true;
}
bool VisitAttr(Attr *A) {
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
index 8a979204b847..a83e55137ad7 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
@@ -18,7 +18,7 @@ class CXXMemberCallVisitor
public:
bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
Match(Call->getMethodDecl()->getQualifiedNameAsString(),
- Call->getLocStart());
+ Call->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
index 67640486efb6..cd0e4260a8bc 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
@@ -75,11 +75,11 @@ TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) {
TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) {
DeclRefExprVisitor Visitor;
Visitor.setShouldVisitImplicitCode(true);
- // We're expecting the "i" in the lambda to be visited twice:
- // - Once for the DeclRefExpr in the lambda capture initialization (whose
- // source code location is set to the first use of the variable).
- // - Once for the DeclRefExpr for the use of "i" inside the lambda.
- Visitor.ExpectMatch("i", 1, 24, /*Times=*/2);
+ // We're expecting "i" to be visited twice: once for the initialization expr
+ // for the captured variable "i" outside of the lambda body, and again for
+ // the use of "i" inside the lambda.
+ Visitor.ExpectMatch("i", 1, 20, /*Times=*/1);
+ Visitor.ExpectMatch("i", 1, 24, /*Times=*/1);
EXPECT_TRUE(Visitor.runOver(
"void f() { int i; [=]{ i; }; }",
DeclRefExprVisitor::Lang_CXX11));
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
index 420b49aa1b14..396f25de5c5d 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
@@ -19,7 +19,7 @@ public:
bool shouldTraversePostOrder() const { return true; }
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
index f9d5ef69e098..587f84bb430a 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
@@ -23,7 +23,7 @@ public:
}
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
index f2036e232c01..01f6e1902916 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
@@ -19,7 +19,7 @@ class InitListExprPreOrderVisitor
: public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
public:
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
index 064cd74390b4..d48b5a89c824 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
@@ -21,7 +21,7 @@ public:
}
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
index 80aeb43528c4..d3a3eba15d16 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
@@ -17,25 +17,33 @@ namespace {
class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
public:
bool VisitLambdaExpr(LambdaExpr *Lambda) {
- PendingBodies.push(Lambda);
+ PendingBodies.push(Lambda->getBody());
+ PendingClasses.push(Lambda->getLambdaClass());
Match("", Lambda->getIntroducerRange().getBegin());
return true;
}
- /// For each call to VisitLambdaExpr, we expect a subsequent call (with
- /// proper nesting) to TraverseLambdaBody.
- bool TraverseLambdaBody(LambdaExpr *Lambda) {
- EXPECT_FALSE(PendingBodies.empty());
- EXPECT_EQ(PendingBodies.top(), Lambda);
- PendingBodies.pop();
- return TraverseStmt(Lambda->getBody());
+ /// For each call to VisitLambdaExpr, we expect a subsequent call to visit
+ /// the body (and maybe the lambda class, which is implicit).
+ bool VisitStmt(Stmt *S) {
+ if (!PendingBodies.empty() && S == PendingBodies.top())
+ PendingBodies.pop();
+ return true;
}
- /// Determine whether TraverseLambdaBody has been called for every call to
- /// VisitLambdaExpr.
- bool allBodiesHaveBeenTraversed() const {
- return PendingBodies.empty();
+ bool VisitDecl(Decl *D) {
+ if (!PendingClasses.empty() && D == PendingClasses.top())
+ PendingClasses.pop();
+ return true;
}
+ /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
+ bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); }
+ bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); }
+
+ bool VisitImplicitCode = false;
+ bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+
private:
- std::stack<LambdaExpr *> PendingBodies;
+ std::stack<Stmt *> PendingBodies;
+ std::stack<Decl *> PendingClasses;
};
TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
@@ -43,13 +51,39 @@ TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
Visitor.ExpectMatch("", 1, 12);
EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
LambdaExprVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
}
-TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
+TEST(RecursiveASTVisitor, LambdaInLambda) {
LambdaExprVisitor Visitor;
+ Visitor.ExpectMatch("", 1, 12);
+ Visitor.ExpectMatch("", 1, 16);
+ EXPECT_TRUE(Visitor.runOver("void f() { []{ []{ return; }; }(); }",
+ LambdaExprVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
+}
+
+TEST(RecursiveASTVisitor, TopLevelLambda) {
+ LambdaExprVisitor Visitor;
+ Visitor.VisitImplicitCode = true;
+ Visitor.ExpectMatch("", 1, 10);
+ Visitor.ExpectMatch("", 1, 14);
+ EXPECT_TRUE(Visitor.runOver("auto x = []{ [] {}; };",
+ LambdaExprVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
+}
+
+TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) {
+ LambdaExprVisitor Visitor;
+ Visitor.VisitImplicitCode = true;
+ Visitor.ExpectMatch("", 1, 12);
EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
LambdaExprVisitor::Lang_CXX11));
EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
}
TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp b/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
new file mode 100644
index 000000000000..72f6c644b388
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
@@ -0,0 +1,51 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class Visitor : public ExpectedLocationVisitor<Visitor, clang::TestVisitor> {
+public:
+ Visitor(ASTContext *Context) { this->Context = Context; }
+
+ bool VisitNamedDecl(NamedDecl *D) {
+ if (!D->isImplicit())
+ Match(D->getName(), D->getLocation());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, RespectsTraversalScope) {
+ auto AST = tooling::buildASTFromCode(
+ R"cpp(
+struct foo {
+ struct bar {
+ struct baz {};
+ };
+};
+ )cpp",
+ "foo.cpp", std::make_shared<PCHContainerOperations>());
+ auto &Ctx = AST->getASTContext();
+ auto &TU = *Ctx.getTranslationUnitDecl();
+ auto &Foo = *TU.lookup(&Ctx.Idents.get("foo")).front();
+ auto &Bar = *cast<DeclContext>(Foo).lookup(&Ctx.Idents.get("bar")).front();
+
+ Ctx.setTraversalScope({&Bar});
+
+ Visitor V(&Ctx);
+ V.DisallowMatch("foo", 2, 8);
+ V.ExpectMatch("bar", 3, 10);
+ V.ExpectMatch("baz", 4, 12);
+ V.TraverseAST(Ctx);
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RefactoringActionRulesTest.cpp b/unittests/Tooling/RefactoringActionRulesTest.cpp
index e9a12deb3f0e..acacfa05b4c9 100644
--- a/unittests/Tooling/RefactoringActionRulesTest.cpp
+++ b/unittests/Tooling/RefactoringActionRulesTest.cpp
@@ -117,8 +117,8 @@ TEST_F(RefactoringActionRulesTest, MyFirstRefactoringRule) {
"Key: 'input.cpp:30'\n"
"FilePath: input.cpp\n"
"Error: ''\n"
- "InsertedHeaders: \n"
- "RemovedHeaders: \n"
+ "InsertedHeaders: []\n"
+ "RemovedHeaders: []\n"
"Replacements: \n" // Extra whitespace here!
" - FilePath: input.cpp\n"
" Offset: 30\n"
diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp
index fcd2aa593730..d618c0fb07fa 100644
--- a/unittests/Tooling/RefactoringTest.cpp
+++ b/unittests/Tooling/RefactoringTest.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Tooling/Refactoring.h"
#include "ReplacementTest.h"
#include "RewriterTestContext.h"
#include "clang/AST/ASTConsumer.h"
@@ -19,16 +20,15 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Refactoring/AtomicChange.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"
namespace clang {
@@ -1032,8 +1032,8 @@ TEST_F(MergeReplacementsTest, OverlappingRanges) {
TEST(DeduplicateByFileTest, PathsWithDots) {
std::map<std::string, Replacements> FileToReplaces;
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
- new vfs::InMemoryFileSystem());
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS(
+ new llvm::vfs::InMemoryFileSystem());
FileManager FileMgr(FileSystemOptions(), VFS);
#if !defined(_WIN32)
StringRef Path1 = "a/b/.././c.h";
@@ -1053,8 +1053,8 @@ TEST(DeduplicateByFileTest, PathsWithDots) {
TEST(DeduplicateByFileTest, PathWithDotSlash) {
std::map<std::string, Replacements> FileToReplaces;
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
- new vfs::InMemoryFileSystem());
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS(
+ new llvm::vfs::InMemoryFileSystem());
FileManager FileMgr(FileSystemOptions(), VFS);
#if !defined(_WIN32)
StringRef Path1 = "./a/b/c.h";
@@ -1074,8 +1074,8 @@ TEST(DeduplicateByFileTest, PathWithDotSlash) {
TEST(DeduplicateByFileTest, NonExistingFilePath) {
std::map<std::string, Replacements> FileToReplaces;
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
- new vfs::InMemoryFileSystem());
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS(
+ new llvm::vfs::InMemoryFileSystem());
FileManager FileMgr(FileSystemOptions(), VFS);
#if !defined(_WIN32)
StringRef Path1 = "./a/b/c.h";
diff --git a/unittests/Tooling/ReplacementsYamlTest.cpp b/unittests/Tooling/ReplacementsYamlTest.cpp
index 3e4193d2adfb..2e5a87a931df 100644
--- a/unittests/Tooling/ReplacementsYamlTest.cpp
+++ b/unittests/Tooling/ReplacementsYamlTest.cpp
@@ -33,13 +33,13 @@ TEST(ReplacementsYamlTest, serializesReplacements) {
// NOTE: If this test starts to fail for no obvious reason, check whitespace.
ASSERT_STREQ("---\n"
- "MainSourceFile: /path/to/source.cpp\n"
+ "MainSourceFile: '/path/to/source.cpp'\n"
"Replacements: \n" // Extra whitespace here!
- " - FilePath: /path/to/file1.h\n"
+ " - FilePath: '/path/to/file1.h'\n"
" Offset: 232\n"
" Length: 56\n"
" ReplacementText: 'replacement #1'\n"
- " - FilePath: /path/to/file2.h\n"
+ " - FilePath: '/path/to/file2.h'\n"
" Offset: 301\n"
" Length: 2\n"
" ReplacementText: 'replacement #2'\n"
diff --git a/unittests/Tooling/RewriterTestContext.h b/unittests/Tooling/RewriterTestContext.h
index eee7ea1873b8..9e66484158f3 100644
--- a/unittests/Tooling/RewriterTestContext.h
+++ b/unittests/Tooling/RewriterTestContext.h
@@ -39,15 +39,15 @@ class RewriterTestContext {
Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
&*DiagOpts),
DiagnosticPrinter(llvm::outs(), &*DiagOpts),
- InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
OverlayFileSystem(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
+ new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())),
Files(FileSystemOptions(), OverlayFileSystem),
Sources(Diagnostics, Files), Rewrite(Sources, Options) {
- Diagnostics.setClient(&DiagnosticPrinter, false);
- // FIXME: To make these tests truly in-memory, we need to overlay the
- // builtin headers.
- OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+ Diagnostics.setClient(&DiagnosticPrinter, false);
+ // FIXME: To make these tests truly in-memory, we need to overlay the
+ // builtin headers.
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
}
~RewriterTestContext() {}
@@ -114,8 +114,8 @@ class RewriterTestContext {
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
DiagnosticsEngine Diagnostics;
TextDiagnosticPrinter DiagnosticPrinter;
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
- IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
+ IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
+ IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem;
FileManager Files;
SourceManager Sources;
LangOptions Options;
diff --git a/unittests/Tooling/TestVisitor.h b/unittests/Tooling/TestVisitor.h
index fb6a76ccadd0..1a22ae737b75 100644
--- a/unittests/Tooling/TestVisitor.h
+++ b/unittests/Tooling/TestVisitor.h
@@ -44,6 +44,8 @@ public:
Lang_CXX98,
Lang_CXX11,
Lang_CXX14,
+ Lang_CXX17,
+ Lang_CXX2a,
Lang_OBJC,
Lang_OBJCXX11,
Lang_CXX = Lang_CXX98
@@ -60,6 +62,8 @@ public:
case Lang_CXX98: Args.push_back("-std=c++98"); break;
case Lang_CXX11: Args.push_back("-std=c++11"); break;
case Lang_CXX14: Args.push_back("-std=c++14"); break;
+ case Lang_CXX17: Args.push_back("-std=c++17"); break;
+ case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
case Lang_OBJC:
Args.push_back("-ObjC");
Args.push_back("-fobjc-runtime=macosx-10.12.0");
diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp
index 0a5150a31b7b..186463f80af7 100644
--- a/unittests/Tooling/ToolingTest.cpp
+++ b/unittests/Tooling/ToolingTest.cpp
@@ -149,10 +149,10 @@ TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
}
TEST(ToolInvocation, TestMapVirtualFile) {
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
+ new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), OverlayFileSystem));
@@ -175,10 +175,10 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) {
// mapped module.map is found on the include path. In the future, expand this
// test to run a full modules enabled compilation, so we make sure we can
// rerun modules compilations with a virtual file system.
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
+ new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), OverlayFileSystem));
@@ -403,10 +403,10 @@ TEST(ClangToolTest, ArgumentAdjusters) {
TEST(ClangToolTest, BaseVirtualFileSystemUsage) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
- llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
- new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
- llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
+ new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
InMemoryFileSystem->addFile(
diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp
index 6fddcb2cbf26..b88b88dac338 100644
--- a/unittests/libclang/LibclangTest.cpp
+++ b/unittests/libclang/LibclangTest.cpp
@@ -461,6 +461,48 @@ TEST_F(LibclangParseTest, AllSkippedRanges) {
clang_disposeSourceRangeList(Ranges);
}
+TEST_F(LibclangParseTest, EvaluateChildExpression) {
+ std::string Main = "main.m";
+ WriteFile(Main, "#define kFOO @\"foo\"\n"
+ "void foobar(void) {\n"
+ " {kFOO;}\n"
+ "}\n");
+ ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr,
+ 0, TUFlags);
+
+ CXCursor C = clang_getTranslationUnitCursor(ClangTU);
+ clang_visitChildren(
+ C,
+ [](CXCursor cursor, CXCursor parent,
+ CXClientData client_data) -> CXChildVisitResult {
+ if (clang_getCursorKind(cursor) == CXCursor_FunctionDecl) {
+ int numberedStmt = 0;
+ clang_visitChildren(
+ cursor,
+ [](CXCursor cursor, CXCursor parent,
+ CXClientData client_data) -> CXChildVisitResult {
+ int &numberedStmt = *((int *)client_data);
+ if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt) {
+ if (numberedStmt) {
+ CXEvalResult RE = clang_Cursor_Evaluate(cursor);
+ EXPECT_NE(RE, nullptr);
+ EXPECT_EQ(clang_EvalResult_getKind(RE),
+ CXEval_ObjCStrLiteral);
+ clang_EvalResult_dispose(RE);
+ return CXChildVisit_Break;
+ }
+ numberedStmt++;
+ }
+ return CXChildVisit_Recurse;
+ },
+ &numberedStmt);
+ EXPECT_EQ(numberedStmt, 1);
+ }
+ return CXChildVisit_Continue;
+ },
+ nullptr);
+}
+
class LibclangReparseTest : public LibclangParseTest {
public:
void DisplayDiagnostics() {
diff --git a/utils/ABITest/ABITestGen.py b/utils/ABITest/ABITestGen.py
index 27cc5ec25823..93a6de93068d 100755
--- a/utils/ABITest/ABITestGen.py
+++ b/utils/ABITest/ABITestGen.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+from __future__ import absolute_import, division, print_function
from pprint import pprint
import random, atexit, time
from random import randrange
@@ -10,7 +11,7 @@ from TypeGen import *
####
-class TypePrinter:
+class TypePrinter(object):
def __init__(self, output, outputHeader=None,
outputTests=None, outputDriver=None,
headerName=None, info=None):
@@ -28,42 +29,42 @@ class TypePrinter:
if info:
for f in (self.output,self.outputHeader,self.outputTests,self.outputDriver):
if f:
- print >>f,info
+ print(info, file=f)
if self.writeBody:
- print >>self.output, '#include <stdio.h>\n'
+ print('#include <stdio.h>\n', file=self.output)
if self.outputTests:
- print >>self.outputTests, '#include <stdio.h>'
- print >>self.outputTests, '#include <string.h>'
- print >>self.outputTests, '#include <assert.h>\n'
+ print('#include <stdio.h>', file=self.outputTests)
+ print('#include <string.h>', file=self.outputTests)
+ print('#include <assert.h>\n', file=self.outputTests)
if headerName:
for f in (self.output,self.outputTests,self.outputDriver):
if f is not None:
- print >>f, '#include "%s"\n'%(headerName,)
+ print('#include "%s"\n'%(headerName,), file=f)
if self.outputDriver:
- print >>self.outputDriver, '#include <stdio.h>'
- print >>self.outputDriver, '#include <stdlib.h>\n'
- print >>self.outputDriver, 'int main(int argc, char **argv) {'
- print >>self.outputDriver, ' int index = -1;'
- print >>self.outputDriver, ' if (argc > 1) index = atoi(argv[1]);'
+ print('#include <stdio.h>', file=self.outputDriver)
+ print('#include <stdlib.h>\n', file=self.outputDriver)
+ print('int main(int argc, char **argv) {', file=self.outputDriver)
+ print(' int index = -1;', file=self.outputDriver)
+ print(' if (argc > 1) index = atoi(argv[1]);', file=self.outputDriver)
def finish(self):
if self.layoutTests:
- print >>self.output, 'int main(int argc, char **argv) {'
- print >>self.output, ' int index = -1;'
- print >>self.output, ' if (argc > 1) index = atoi(argv[1]);'
+ print('int main(int argc, char **argv) {', file=self.output)
+ print(' int index = -1;', file=self.output)
+ print(' if (argc > 1) index = atoi(argv[1]);', file=self.output)
for i,f in self.layoutTests:
- print >>self.output, ' if (index == -1 || index == %d)' % i
- print >>self.output, ' %s();' % f
- print >>self.output, ' return 0;'
- print >>self.output, '}'
+ print(' if (index == -1 || index == %d)' % i, file=self.output)
+ print(' %s();' % f, file=self.output)
+ print(' return 0;', file=self.output)
+ print('}', file=self.output)
if self.outputDriver:
- print >>self.outputDriver, ' printf("DONE\\n");'
- print >>self.outputDriver, ' return 0;'
- print >>self.outputDriver, '}'
+ print(' printf("DONE\\n");', file=self.outputDriver)
+ print(' return 0;', file=self.outputDriver)
+ print('}', file=self.outputDriver)
def addDeclaration(self, decl):
if decl in self.declarations:
@@ -71,11 +72,11 @@ class TypePrinter:
self.declarations.add(decl)
if self.outputHeader:
- print >>self.outputHeader, decl
+ print(decl, file=self.outputHeader)
else:
- print >>self.output, decl
+ print(decl, file=self.output)
if self.outputTests:
- print >>self.outputTests, decl
+ print(decl, file=self.outputTests)
return True
def getTypeName(self, T):
@@ -91,12 +92,12 @@ class TypePrinter:
tyNameClean = tyName.replace(' ','_').replace('*','star')
fnName = 'test_%s' % tyNameClean
- print >>self.output,'void %s(void) {' % fnName
+ print('void %s(void) {' % fnName, file=self.output)
self.printSizeOfType(' %s'%fnName, tyName, ty, self.output)
self.printAlignOfType(' %s'%fnName, tyName, ty, self.output)
self.printOffsetsOfType(' %s'%fnName, tyName, ty, self.output)
- print >>self.output,'}'
- print >>self.output
+ print('}', file=self.output)
+ print(file=self.output)
self.layoutTests.append((i,fnName))
@@ -115,71 +116,71 @@ class TypePrinter:
fnName = 'fn%d'%(FT.index,)
if self.outputHeader:
- print >>self.outputHeader,'%s %s(%s);'%(retvalTypeName, fnName, args)
+ print('%s %s(%s);'%(retvalTypeName, fnName, args), file=self.outputHeader)
elif self.outputTests:
- print >>self.outputTests,'%s %s(%s);'%(retvalTypeName, fnName, args)
+ print('%s %s(%s);'%(retvalTypeName, fnName, args), file=self.outputTests)
- print >>self.output,'%s %s(%s)'%(retvalTypeName, fnName, args),
+ print('%s %s(%s)'%(retvalTypeName, fnName, args), end=' ', file=self.output)
if self.writeBody:
- print >>self.output, '{'
+ print('{', file=self.output)
for i,t in enumerate(FT.argTypes):
self.printValueOfType(' %s'%fnName, 'arg%d'%i, t)
if retvalName is not None:
- print >>self.output, ' return %s;'%(retvalName,)
- print >>self.output, '}'
+ print(' return %s;'%(retvalName,), file=self.output)
+ print('}', file=self.output)
else:
- print >>self.output, '{}'
- print >>self.output
+ print('{}', file=self.output)
+ print(file=self.output)
if self.outputDriver:
- print >>self.outputDriver, ' if (index == -1 || index == %d) {' % i
- print >>self.outputDriver, ' extern void test_%s(void);' % fnName
- print >>self.outputDriver, ' test_%s();' % fnName
- print >>self.outputDriver, ' }'
+ print(' if (index == -1 || index == %d) {' % i, file=self.outputDriver)
+ print(' extern void test_%s(void);' % fnName, file=self.outputDriver)
+ print(' test_%s();' % fnName, file=self.outputDriver)
+ print(' }', file=self.outputDriver)
if self.outputTests:
if self.outputHeader:
- print >>self.outputHeader, 'void test_%s(void);'%(fnName,)
+ print('void test_%s(void);'%(fnName,), file=self.outputHeader)
if retvalName is None:
retvalTests = None
else:
retvalTests = self.getTestValuesArray(FT.returnType)
- tests = map(self.getTestValuesArray, FT.argTypes)
- print >>self.outputTests, 'void test_%s(void) {'%(fnName,)
+ tests = [self.getTestValuesArray(ty) for ty in FT.argTypes]
+ print('void test_%s(void) {'%(fnName,), file=self.outputTests)
if retvalTests is not None:
- print >>self.outputTests, ' printf("%s: testing return.\\n");'%(fnName,)
- print >>self.outputTests, ' for (int i=0; i<%d; ++i) {'%(retvalTests[1],)
+ print(' printf("%s: testing return.\\n");'%(fnName,), file=self.outputTests)
+ print(' for (int i=0; i<%d; ++i) {'%(retvalTests[1],), file=self.outputTests)
args = ', '.join(['%s[%d]'%(t,randrange(l)) for t,l in tests])
- print >>self.outputTests, ' %s RV;'%(retvalTypeName,)
- print >>self.outputTests, ' %s = %s[i];'%(retvalName, retvalTests[0])
- print >>self.outputTests, ' RV = %s(%s);'%(fnName, args)
+ print(' %s RV;'%(retvalTypeName,), file=self.outputTests)
+ print(' %s = %s[i];'%(retvalName, retvalTests[0]), file=self.outputTests)
+ print(' RV = %s(%s);'%(fnName, args), file=self.outputTests)
self.printValueOfType(' %s_RV'%fnName, 'RV', FT.returnType, output=self.outputTests, indent=4)
self.checkTypeValues('RV', '%s[i]' % retvalTests[0], FT.returnType, output=self.outputTests, indent=4)
- print >>self.outputTests, ' }'
+ print(' }', file=self.outputTests)
if tests:
- print >>self.outputTests, ' printf("%s: testing arguments.\\n");'%(fnName,)
+ print(' printf("%s: testing arguments.\\n");'%(fnName,), file=self.outputTests)
for i,(array,length) in enumerate(tests):
for j in range(length):
args = ['%s[%d]'%(t,randrange(l)) for t,l in tests]
args[i] = '%s[%d]'%(array,j)
- print >>self.outputTests, ' %s(%s);'%(fnName, ', '.join(args),)
- print >>self.outputTests, '}'
+ print(' %s(%s);'%(fnName, ', '.join(args),), file=self.outputTests)
+ print('}', file=self.outputTests)
def getTestReturnValue(self, type):
typeName = self.getTypeName(type)
info = self.testReturnValues.get(typeName)
if info is None:
name = '%s_retval'%(typeName.replace(' ','_').replace('*','star'),)
- print >>self.output, '%s %s;'%(typeName,name)
+ print('%s %s;'%(typeName,name), file=self.output)
if self.outputHeader:
- print >>self.outputHeader, 'extern %s %s;'%(typeName,name)
+ print('extern %s %s;'%(typeName,name), file=self.outputHeader)
elif self.outputTests:
- print >>self.outputTests, 'extern %s %s;'%(typeName,name)
+ print('extern %s %s;'%(typeName,name), file=self.outputTests)
info = self.testReturnValues[typeName] = name
return info
@@ -188,12 +189,12 @@ class TypePrinter:
info = self.testValues.get(typeName)
if info is None:
name = '%s_values'%(typeName.replace(' ','_').replace('*','star'),)
- print >>self.outputTests, 'static %s %s[] = {'%(typeName,name)
+ print('static %s %s[] = {'%(typeName,name), file=self.outputTests)
length = 0
for item in self.getTestValues(type):
- print >>self.outputTests, '\t%s,'%(item,)
+ print('\t%s,'%(item,), file=self.outputTests)
length += 1
- print >>self.outputTests,'};'
+ print('};', file=self.outputTests)
info = self.testValues[typeName] = (name,length)
return info
@@ -230,10 +231,10 @@ class TypePrinter:
yield '{ %s }' % v
return
- fieldValues = map(list, map(self.getTestValues, nonPadding))
+ fieldValues = [list(v) for v in map(self.getTestValues, nonPadding)]
for i,values in enumerate(fieldValues):
for v in values:
- elements = map(random.choice,fieldValues)
+ elements = [random.choice(fv) for fv in fieldValues]
elements[i] = v
yield '{ %s }'%(', '.join(elements))
@@ -250,19 +251,19 @@ class TypePrinter:
elements[i] = v
yield '{ %s }'%(', '.join(elements))
else:
- raise NotImplementedError,'Cannot make tests values of type: "%s"'%(t,)
+ raise NotImplementedError('Cannot make tests values of type: "%s"'%(t,))
def printSizeOfType(self, prefix, name, t, output=None, indent=2):
- print >>output, '%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'%(indent, '', prefix, name, name)
+ print('%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'%(indent, '', prefix, name, name), file=output)
def printAlignOfType(self, prefix, name, t, output=None, indent=2):
- print >>output, '%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'%(indent, '', prefix, name, name)
+ print('%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'%(indent, '', prefix, name, name), file=output)
def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):
if isinstance(t, RecordType):
for i,f in enumerate(t.fields):
if f.isBitField():
continue
fname = 'field%d' % i
- print >>output, '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname)
+ print('%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname), file=output)
def printValueOfType(self, prefix, name, t, output=None, indent=2):
if output is None:
@@ -286,13 +287,13 @@ class TypePrinter:
code = 'Lf'
else:
code = 'p'
- print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(
- indent, '', prefix, name, code, value_expr)
+ print('%*sprintf("%s: %s = %%%s\\n", %s);'%(
+ indent, '', prefix, name, code, value_expr), file=output)
elif isinstance(t, EnumType):
- print >>output, '%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name)
+ print('%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name), file=output)
elif isinstance(t, RecordType):
if not t.fields:
- print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name)
+ print('%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name), file=output)
for i,f in enumerate(t.fields):
if f.isPaddingBitField():
continue
@@ -310,16 +311,16 @@ class TypePrinter:
else:
self.printValueOfType(prefix, '%s[%d]'%(name,i), t.elementType, output=output,indent=indent)
else:
- raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
+ raise NotImplementedError('Cannot print value of type: "%s"'%(t,))
def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2):
prefix = 'foo'
if output is None:
output = self.output
if isinstance(t, BuiltinType):
- print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
+ print('%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS), file=output)
elif isinstance(t, EnumType):
- print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
+ print('%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS), file=output)
elif isinstance(t, RecordType):
for i,f in enumerate(t.fields):
if f.isPaddingBitField():
@@ -343,7 +344,7 @@ class TypePrinter:
self.checkTypeValues('%s[%d]'%(nameLHS,i), '%s[%d]'%(nameRHS,i),
t.elementType, output=output,indent=indent)
else:
- raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
+ raise NotImplementedError('Cannot print value of type: "%s"'%(t,))
import sys
@@ -642,9 +643,9 @@ def main():
def write(N):
try:
FT = ftg.get(N)
- except RuntimeError,e:
+ except RuntimeError as e:
if e.args[0]=='maximum recursion depth exceeded':
- print >>sys.stderr,'WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,)
+ print('WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,), file=sys.stderr)
return
raise
if opts.testLayout:
diff --git a/utils/ABITest/Enumeration.py b/utils/ABITest/Enumeration.py
index 47e47026db08..24f5b5fba24c 100644
--- a/utils/ABITest/Enumeration.py
+++ b/utils/ABITest/Enumeration.py
@@ -1,5 +1,6 @@
"""Utilities for enumeration of finite and countably infinite sets.
"""
+from __future__ import absolute_import, division, print_function
###
# Countable iteration
@@ -17,7 +18,7 @@ class Aleph0(int):
return 1
def __sub__(self, b):
- raise ValueError,"Cannot subtract aleph0"
+ raise ValueError("Cannot subtract aleph0")
__rsub__ = __sub__
def __add__(self, b):
@@ -46,7 +47,8 @@ aleph0 = Aleph0()
def base(line):
return line*(line+1)//2
-def pairToN((x,y)):
+def pairToN(pair):
+ x,y = pair
line,index = x+y,y
return base(line)+index
@@ -86,9 +88,9 @@ def getNthPairBounded(N,W=aleph0,H=aleph0,useDivmod=False):
Return the N-th pair such that 0 <= x < W and 0 <= y < H."""
if W <= 0 or H <= 0:
- raise ValueError,"Invalid bounds"
+ raise ValueError("Invalid bounds")
elif N >= W*H:
- raise ValueError,"Invalid input (out of bounds)"
+ raise ValueError("Invalid input (out of bounds)")
# Simple case...
if W is aleph0 and H is aleph0:
@@ -170,7 +172,7 @@ def getNthTuple(N, maxSize=aleph0, maxElement=aleph0, useDivmod=False, useLeftTo
N -= 1
if maxElement is not aleph0:
if maxSize is aleph0:
- raise NotImplementedError,'Max element size without max size unhandled'
+ raise NotImplementedError('Max element size without max size unhandled')
bounds = [maxElement**i for i in range(1, maxSize+1)]
S,M = getNthPairVariableBounds(N, bounds)
else:
@@ -193,12 +195,12 @@ def getNthPairVariableBounds(N, bounds):
bounds[x]."""
if not bounds:
- raise ValueError,"Invalid bounds"
+ raise ValueError("Invalid bounds")
if not (0 <= N < sum(bounds)):
- raise ValueError,"Invalid input (out of bounds)"
+ raise ValueError("Invalid input (out of bounds)")
level = 0
- active = range(len(bounds))
+ active = list(range(len(bounds)))
active.sort(key=lambda i: bounds[i])
prevLevel = 0
for i,index in enumerate(active):
@@ -216,7 +218,7 @@ def getNthPairVariableBounds(N, bounds):
N -= levelSize
prevLevel = level
else:
- raise RuntimError,"Unexpected loop completion"
+ raise RuntimError("Unexpected loop completion")
def getNthPairVariableBoundsChecked(N, bounds, GNVP=getNthPairVariableBounds):
x,y = GNVP(N,bounds)
@@ -233,18 +235,18 @@ def testPairs():
for i in range(min(W*H,40)):
x,y = getNthPairBounded(i,W,H)
x2,y2 = getNthPairBounded(i,W,H,useDivmod=True)
- print i,(x,y),(x2,y2)
+ print(i,(x,y),(x2,y2))
a[y][x] = '%2d'%i
b[y2][x2] = '%2d'%i
- print '-- a --'
+ print('-- a --')
for ln in a[::-1]:
if ''.join(ln).strip():
- print ' '.join(ln)
- print '-- b --'
+ print(' '.join(ln))
+ print('-- b --')
for ln in b[::-1]:
if ''.join(ln).strip():
- print ' '.join(ln)
+ print(' '.join(ln))
def testPairsVB():
bounds = [2,2,4,aleph0,5,aleph0]
@@ -252,13 +254,13 @@ def testPairsVB():
b = [[' ' for x in range(15)] for y in range(15)]
for i in range(min(sum(bounds),40)):
x,y = getNthPairVariableBounds(i, bounds)
- print i,(x,y)
+ print(i,(x,y))
a[y][x] = '%2d'%i
- print '-- a --'
+ print('-- a --')
for ln in a[::-1]:
if ''.join(ln).strip():
- print ' '.join(ln)
+ print(' '.join(ln))
###
diff --git a/utils/ABITest/TypeGen.py b/utils/ABITest/TypeGen.py
index 1e4471c71e57..8561baea617b 100644
--- a/utils/ABITest/TypeGen.py
+++ b/utils/ABITest/TypeGen.py
@@ -1,4 +1,5 @@
"""Flexible enumeration of C types."""
+from __future__ import division, print_function
from Enumeration import *
@@ -17,7 +18,7 @@ from Enumeration import *
###
# Actual type types
-class Type:
+class Type(object):
def isBitField(self):
return False
@@ -99,7 +100,8 @@ class RecordType(Type):
' '.join(map(getField, self.fields)))
def getTypedefDef(self, name, printer):
- def getField((i, t)):
+ def getField(it):
+ i, t = it
if t.isBitField():
if t.isPaddingBitField():
return '%s : 0;'%(printer.getTypeName(t),)
@@ -108,7 +110,7 @@ class RecordType(Type):
t.getBitFieldSize())
else:
return '%s field%d;'%(printer.getTypeName(t),i)
- fields = map(getField, enumerate(self.fields))
+ fields = [getField(f) for f in enumerate(self.fields)]
# Name the struct for more readable LLVM IR.
return 'typedef %s %s { %s } %s;'%(('struct','union')[self.isUnion],
name, ' '.join(fields), name)
@@ -233,7 +235,7 @@ def fact(n):
# Compute the number of combinations (n choose k)
def num_combinations(n, k):
- return fact(n) / (fact(k) * fact(n - k))
+ return fact(n) // (fact(k) * fact(n - k))
# Enumerate the combinations choosing k elements from the list of values
def combinations(values, k):
@@ -241,7 +243,7 @@ def combinations(values, k):
# combinations, selections of a sequence
if k==0: yield []
else:
- for i in xrange(len(values)-k+1):
+ for i in range(len(values)-k+1):
for cc in combinations(values[i+1:],k-1):
yield [values[i]]+cc
@@ -370,7 +372,7 @@ class RecordTypeGenerator(TypeGenerator):
isUnion,I = False,N
if self.useUnion:
isUnion,I = (I&1),I>>1
- fields = map(self.typeGen.get,getNthTuple(I,self.maxSize,self.typeGen.cardinality))
+ fields = [self.typeGen.get(f) for f in getNthTuple(I,self.maxSize,self.typeGen.cardinality)]
return RecordType(N, isUnion, fields)
class FunctionTypeGenerator(TypeGenerator):
@@ -403,7 +405,7 @@ class FunctionTypeGenerator(TypeGenerator):
else:
retTy = None
argIndices = getNthTuple(N, self.maxSize, self.typeGen.cardinality)
- args = map(self.typeGen.get, argIndices)
+ args = [self.typeGen.get(i) for i in argIndices]
return FunctionType(N, retTy, args)
class AnyTypeGenerator(TypeGenerator):
@@ -435,7 +437,7 @@ class AnyTypeGenerator(TypeGenerator):
if (self._cardinality is aleph0) or prev==self._cardinality:
break
else:
- raise RuntimeError,"Infinite loop in setting cardinality"
+ raise RuntimeError("Infinite loop in setting cardinality")
def generateType(self, N):
index,M = getNthPairVariableBounds(N, self.bounds)
@@ -461,15 +463,15 @@ def test():
atg.addGenerator( btg )
atg.addGenerator( RecordTypeGenerator(fields0, False, 4) )
atg.addGenerator( etg )
- print 'Cardinality:',atg.cardinality
+ print('Cardinality:',atg.cardinality)
for i in range(100):
if i == atg.cardinality:
try:
atg.get(i)
- raise RuntimeError,"Cardinality was wrong"
+ raise RuntimeError("Cardinality was wrong")
except AssertionError:
break
- print '%4d: %s'%(i, atg.get(i))
+ print('%4d: %s'%(i, atg.get(i)))
if __name__ == '__main__':
test()
diff --git a/utils/CIndex/completion_logger_server.py b/utils/CIndex/completion_logger_server.py
index 0652b1f4a8ee..201667117fc2 100755
--- a/utils/CIndex/completion_logger_server.py
+++ b/utils/CIndex/completion_logger_server.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+from __future__ import absolute_import, division, print_function
import sys
from socket import *
from time import strftime
@@ -6,7 +7,7 @@ import datetime
def main():
if len(sys.argv) < 4:
- print "completion_logger_server.py <listen address> <listen port> <log file>"
+ print("completion_logger_server.py <listen address> <listen port> <log file>")
exit(1)
host = sys.argv[1]
@@ -18,7 +19,7 @@ def main():
UDPSock = socket(AF_INET,SOCK_DGRAM)
UDPSock.bind(addr)
- print "Listing on {0}:{1} and logging to '{2}'".format(host, port, sys.argv[3])
+ print("Listing on {0}:{1} and logging to '{2}'".format(host, port, sys.argv[3]))
# Open the logging file.
f = open(sys.argv[3], "a")
diff --git a/utils/ClangVisualizers/clang.natvis b/utils/ClangVisualizers/clang.natvis
index 6e3ca96ffde3..17556f9cabb1 100644
--- a/utils/ClangVisualizers/clang.natvis
+++ b/utils/ClangVisualizers/clang.natvis
@@ -34,15 +34,35 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::Record" IncludeView="cpp">{*(clang::RecordType *)this,view(cpp)}</DisplayString>
<DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::FunctionProto" IncludeView="poly">{*(clang::FunctionProtoType *)this}</DisplayString>
<DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::TemplateSpecialization" IncludeView="poly">{*(clang::TemplateSpecializationType *)this}</DisplayString>
+ <DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::DeducedTemplateSpecialization" IncludeView="poly">{*(clang::DeducedTemplateSpecializationType *)this}</DisplayString>
<DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::InjectedClassName" IncludeView="poly">{*(clang::InjectedClassNameType *)this}</DisplayString>
<DisplayString Condition="TypeBits.TC==clang::Type::TypeClass::PackExpansion" IncludeView="poly">{*(clang::PackExpansionType *)this}</DisplayString>
<DisplayString Condition="TypeBits.TC==clang::LocInfoType::LocInfo" IncludeView="poly">{*(clang::LocInfoType *)this}</DisplayString>
<DisplayString IncludeView="cpp">{*this,view(poly)}</DisplayString>
- <DisplayString IncludeView="poly">{*this,view(cmn)}</DisplayString> <!-- Not yet implemented Type subclass -->
+ <DisplayString IncludeView="poly">No visualizer yet for {(clang::Type::TypeClass)TypeBits.TC,en}Type</DisplayString> <!-- Not yet implemented Type subclass -->
+ <DisplayString IncludeView="Dependent" Condition="TypeBits.Dependent">Dependent{" ",sb}</DisplayString>
+ <DisplayString IncludeView="Dependent"></DisplayString>
+ <DisplayString IncludeView="InstantiationDependent" Condition="TypeBits.InstantiationDependent">InstantiationDependent{" ",sb}</DisplayString>
+ <DisplayString IncludeView="InstantiationDependent"></DisplayString>
+ <DisplayString IncludeView="VariablyModified" Condition="TypeBits.VariablyModified">VariablyModified{" ",sb}</DisplayString>
+ <DisplayString IncludeView="VariablyModified"></DisplayString>
+ <DisplayString IncludeView="ContainsUnexpandedParameterPack" Condition="TypeBits.ContainsUnexpandedParameterPack">ContainsUnexpandedParameterPack{" ",sb}</DisplayString>
+ <DisplayString IncludeView="ContainsUnexpandedParameterPack"></DisplayString>
+ <DisplayString IncludeView="Cache" Condition="TypeBits.CacheValid &amp;&amp; TypeBits.CachedLocalOrUnnamed">CachedLinkage: {(clang::Linkage)TypeBits.CachedLinkage,en} CachedLocalOrUnnamed</DisplayString>
+ <DisplayString IncludeView="Cache" Condition="TypeBits.CacheValid &amp;&amp; !TypeBits.CachedLocalOrUnnamed">CachedLinkage: {(clang::Linkage)TypeBits.CachedLinkage,en}{" ",sb}</DisplayString>
+ <DisplayString IncludeView="Cache"></DisplayString>
+ <DisplayString IncludeView="FromAST" Condition="TypeBits.FromAST">FromAST</DisplayString>
+ <DisplayString IncludeView="FromAST"></DisplayString>
+ <DisplayString IncludeView="flags" Condition="!TypeBits.Dependent &amp;&amp; !TypeBits.InstantiationDependent &amp;&amp; !TypeBits.VariablyModified &amp;&amp; !TypeBits.ContainsUnexpandedParameterPack &amp;&amp; !TypeBits.CacheValid &amp;&amp; !TypeBits.FromAST">
+ No TypeBits set beyond TypeClass
+ </DisplayString>
+ <DisplayString IncludeView="flags">
+{*this, view(Dependent)}{*this, view(InstantiationDependent)}{*this, view(VariablyModified)}
+{*this, view(ContainsUnexpandedParameterPack)}{*this, view(Cache)}{*this, view(FromAST)}</DisplayString>
<DisplayString>{*this,view(cmn)} {{{*this,view(poly)}}}</DisplayString>
<Expand>
<Item Name="TypeClass" IncludeView="cmn">(clang::Type::TypeClass)TypeBits.TC</Item>
- <Item Name="Flags" IncludeView="cmn">TypeBits</Item>
+ <Item Name="Flags" IncludeView="cmn">*this,view(flags)</Item>
<Item Name="Canonical" IncludeView="cmn">CanonicalType</Item>
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::Builtin">*(clang::BuiltinType *)this</ExpandedItem>
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::Pointer">*(clang::PointerType *)this</ExpandedItem>
@@ -54,6 +74,7 @@ For later versions of Visual Studio, no setup is required-->
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::Record">(clang::RecordType *)this</ExpandedItem>
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::FunctionProto">(clang::FunctionProtoType *)this</ExpandedItem>
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::TemplateSpecialization">(clang::TemplateSpecializationType *)this</ExpandedItem>
+ <ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::DeducedTemplateSpecialization">(clang::DeducedTemplateSpecializationType *)this</ExpandedItem>
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::InjectedClassName">(clang::InjectedClassNameType *)this</ExpandedItem>
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::Type::TypeClass::PackExpansion">(clang::PackExpansionType *)this</ExpandedItem>
<ExpandedItem ExcludeView="cmn" Condition="TypeBits.TC==clang::LocInfoType::LocInfo">(clang::LocInfoType *)this</ExpandedItem>
@@ -120,12 +141,19 @@ For later versions of Visual Studio, no setup is required-->
<Type Name="clang::TemplateTypeParmDecl">
<DisplayString IncludeView="TorC" Condition="Typename">typename</DisplayString>
<DisplayString IncludeView="TorC" Condition="!Typename">class</DisplayString>
- <DisplayString IncludeView="MaybeEllipses" Condition="((TemplateTypeParmType *)TypeForDecl)->CanTTPTInfo.ParameterPack">...</DisplayString>
- <DisplayString IncludeView="MaybeEllipses" Condition="!((TemplateTypeParmType *)TypeForDecl)->CanTTPTInfo.ParameterPack"></DisplayString>
+ <DisplayString IncludeView="MaybeEllipses" Condition="TypeForDecl == nullptr">(not yet known if parameter pack) </DisplayString>
+ <DisplayString IncludeView="MaybeEllipses" Condition="((TemplateTypeParmType *)(((clang::ExtQualsTypeCommonBase *)(((uintptr_t)TypeForDecl->CanonicalType.Value.Value) &amp; ~(uintptr_t)((1 &lt;&lt; 4) - 1)))-&gt;BaseType))->CanTTPTInfo.ParameterPack">...</DisplayString>
+ <DisplayString IncludeView="MaybeEllipses" Condition="!((TemplateTypeParmType *)(((clang::ExtQualsTypeCommonBase *)(((uintptr_t)TypeForDecl->CanonicalType.Value.Value) &amp; ~(uintptr_t)((1 &lt;&lt; 4) - 1)))-&gt;BaseType))->CanTTPTInfo.ParameterPack"></DisplayString>
<DisplayString>{*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)}</DisplayString>
</Type>
<Type Name="clang::TemplateDecl">
- <DisplayString>template{*TemplateParams} {*TemplatedDecl};</DisplayString>
+ <DisplayString>template{TemplateParams,view(deref)} {*TemplatedDecl};</DisplayString>
+ </Type>
+ <Type Name="clang::TemplateName">
+ <DisplayString>{Storage,view(deref)}</DisplayString>
+ <Expand>
+ <ExpandedItem>Storage</ExpandedItem>
+ </Expand>
</Type>
<Type Name="clang::NamedDecl" >
<DisplayString IncludeView="cpp">{Name,view(cpp)}</DisplayString>
@@ -134,13 +162,13 @@ For later versions of Visual Studio, no setup is required-->
<Type Name="clang::TagDecl">
<DisplayString IncludeView="implicit" Condition="Implicit">implicit{" ",sb}</DisplayString>
<DisplayString IncludeView="implicit"></DisplayString>
- <DisplayString IncludeView="modifiers">{*this,view(implicit)}</DisplayString>
+ <DisplayString IncludeView="modifiers">{*this,view(implicit)nd}</DisplayString>
<DisplayString IncludeView="cpp">{*this,view(modifiers)}{Name,view(cpp)}</DisplayString>
- <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Struct">{*this,view(modifiers)}struct {Name,view(cpp)}</DisplayString>
- <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Interface">{*this,view(modifiers)}interface {Name,view(cpp)}</DisplayString>
- <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Union">{*this,view(modifiers)}union {Name,view(cpp)}</DisplayString>
- <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Class">{*this,view(modifiers)}class {Name,view(cpp)}</DisplayString>
- <DisplayString Condition="TagDeclKind==clang::TagTypeKind::TTK_Enum">{*this,view(modifiers)}enum {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclBits.TagDeclKind==clang::TagTypeKind::TTK_Struct">{*this,view(modifiers)nd}struct {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclBits.TagDeclKind==clang::TagTypeKind::TTK_Interface">{*this,view(modifiers)nd}interface {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclBits.TagDeclKind==clang::TagTypeKind::TTK_Union">{*this,view(modifiers)nd}union {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclBits.TagDeclKind==clang::TagTypeKind::TTK_Class">{*this,view(modifiers)nd}class {Name,view(cpp)}</DisplayString>
+ <DisplayString Condition="TagDeclBits.TagDeclKind==clang::TagTypeKind::TTK_Enum">{*this,view(modifiers)nd}enum {Name,view(cpp)}</DisplayString>
<Expand>
<ExpandedItem>(clang::DeclContext *)this</ExpandedItem>
</Expand>
@@ -171,17 +199,17 @@ For later versions of Visual Studio, no setup is required-->
but the expansion has all parameters -->
<Type Name="clang::FunctionProtoType">
<DisplayString IncludeView="retType">{ResultType,view(cpp)}</DisplayString>
- <DisplayString IncludeView="parm0" Condition="NumParams==0"></DisplayString>
+ <DisplayString IncludeView="parm0" Condition="FunctionTypeBits.NumParams==0"></DisplayString>
<DisplayString IncludeView="parm0">{*(clang::QualType *)(this+1),view(cpp)}{*this,view(parm1)}</DisplayString>
- <DisplayString IncludeView="parm1" Condition="NumParams==1"></DisplayString>
+ <DisplayString IncludeView="parm1" Condition="FunctionTypeBits.NumParams==1"></DisplayString>
<DisplayString IncludeView="parm1">, {*((clang::QualType *)(this+1)+1),view(cpp)}{*this,view(parm2)}</DisplayString>
- <DisplayString IncludeView="parm2" Condition="NumParams==2"></DisplayString>
+ <DisplayString IncludeView="parm2" Condition="FunctionTypeBits.NumParams==2"></DisplayString>
<DisplayString IncludeView="parm2">, {*((clang::QualType *)(this+1)+2),view(cpp)}{*this,view(parm3)}</DisplayString>
- <DisplayString IncludeView="parm3" Condition="NumParams==3"></DisplayString>
+ <DisplayString IncludeView="parm3" Condition="FunctionTypeBits.NumParams==3"></DisplayString>
<DisplayString IncludeView="parm3">, {*((clang::QualType *)(this+1)+3),view(cpp)}{*this,view(parm4)}</DisplayString>
- <DisplayString IncludeView="parm4" Condition="NumParams==4"></DisplayString>
+ <DisplayString IncludeView="parm4" Condition="FunctionTypeBits.NumParams==4"></DisplayString>
<DisplayString IncludeView="parm4">, {*((clang::QualType *)(this+1)+4),view(cpp)}{*this,view(parm5)}</DisplayString>
- <DisplayString IncludeView="parm5" Condition="NumParams==5"></DisplayString>
+ <DisplayString IncludeView="parm5" Condition="FunctionTypeBits.NumParams==5"></DisplayString>
<DisplayString IncludeView="parm5">, /* expand for more params */</DisplayString>
<DisplayString>{*this,view(retType)}({*this,view(parm0)})</DisplayString>
<Expand>
@@ -190,7 +218,7 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString>{*this,view(parm0)}</DisplayString>
<Expand>
<ArrayItems>
- <Size>NumParams</Size>
+ <Size>FunctionTypeBits.NumParams</Size>
<ValuePointer>(clang::QualType *)(this+1)</ValuePointer>
</ArrayItems>
</Expand>
@@ -199,8 +227,11 @@ For later versions of Visual Studio, no setup is required-->
</Expand>
</Type>
<Type Name="clang::TemplateTypeParmType">
- <DisplayString IncludeView="cpp">{*TTPDecl,view(cpp)}</DisplayString>
- <DisplayString>{*TTPDecl}</DisplayString>
+ <DisplayString IncludeView="cpp" Condition="CanonicalType.Value.Value != this">{*TTPDecl}</DisplayString>
+ <DisplayString Condition="CanonicalType.Value.Value != this">Non-canonical: {*TTPDecl}</DisplayString>
+ <DisplayString>Canonical: {CanTTPTInfo}</DisplayString>
+ <Expand>
+ </Expand>
</Type>
<Type Name="clang::InjectedClassNameType">
<DisplayString>{*Decl,view(cpp)}</DisplayString>
@@ -233,10 +264,11 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString IncludeView="fastQuals" Condition="(Value.Value &amp; 15)==6">{" ",sb}volatile restrict</DisplayString>
<DisplayString IncludeView="fastQuals" Condition="(Value.Value &amp; 15)==7">{" ",sb}const volatile restrict</DisplayString>
<DisplayString IncludeView="fastQuals">Cannot visualize non-fast qualifiers</DisplayString>
+ <DisplayString Condition="(uintptr_t)Value.Value == 0">Null</DisplayString>
<DisplayString>{*((clang::ExtQualsTypeCommonBase *)(((uintptr_t)Value.Value) &amp; ~(uintptr_t)((1 &lt;&lt; 4) - 1)))-&gt;BaseType}{*this,view(fastQuals)}</DisplayString>
<Expand>
<Item Name="Fast Quals">*this,view(fastQuals)</Item>
- <Item Name="BaseType">*((clang::ExtQualsTypeCommonBase *)(((uintptr_t)Value.Value) &amp; ~(uintptr_t)((1 &lt;&lt; 4) - 1)))-&gt;BaseType</Item>
+ <ExpandedItem>*((clang::ExtQualsTypeCommonBase *)(((uintptr_t)Value.Value) &amp; ~(uintptr_t)((1 &lt;&lt; 4) - 1)))-&gt;BaseType</ExpandedItem>
</Expand>
</Type>
<Type Name="clang::LocInfoType">
@@ -381,6 +413,29 @@ For later versions of Visual Studio, no setup is required-->
</ArrayItems>
</Expand>
</Type>
+ <Type Name="clang::DeducedType">
+ <Expand>
+ <Item Name="isDeduced">(CanonicalType.Value.Value != this) || TypeBits.Dependent</Item>
+ <ExpandedItem>*(clang::Type *)this,view(cmn)</ExpandedItem>
+ </Expand>
+ </Type>
+ <Type Name="clang::DeducedTemplateSpecializationType">
+ <DisplayString Condition="(CanonicalType.Value.Value != this) || TypeBits.Dependent">{CanonicalType,view(cpp)}</DisplayString>
+ <DisplayString>{Template}</DisplayString>
+ <Expand>
+ <Item Name="Template">Template</Item>
+ <Item Name="Deduced As" Condition="(CanonicalType.Value.Value != this) || TypeBits.Dependent">CanonicalType,view(cpp)</Item>
+ <ExpandedItem>*(clang::DeducedType *)this</ExpandedItem>
+ <Item Name="Template">Template</Item>
+ </Expand>
+ </Type>
+ <Type Name="clang::ClassTemplateSpecializationDecl">
+ <DisplayString>{*(CXXRecordDecl *)this,nd}{*TemplateArgs}</DisplayString>
+ <Expand>
+ <ExpandedItem>(CXXRecordDecl *)this,nd</ExpandedItem>
+ <Item Name="TemplateArgs">TemplateArgs</Item>
+ </Expand>
+ </Type>
<Type Name="clang::IdentifierInfo">
<DisplayString Condition="Entry != 0">{((llvm::StringMapEntry&lt;clang::IdentifierInfo *&gt;*)Entry)+1,sb}</DisplayString>
<Expand>
@@ -395,22 +450,29 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredIdentifier">{{Identifier ({*(clang::IdentifierInfo *)(Ptr &amp; ~PtrMask)})}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredObjCZeroArgSelector">{{ObjC Zero Arg Selector (*{(clang::IdentifierInfo *)(Ptr &amp; ~PtrMask)})}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredObjCOneArgSelector">{{ObjC One Arg Selector (*{(clang::IdentifierInfo *)(Ptr &amp; ~PtrMask)})}}</DisplayString>
+ <DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXConstructorName">C++ Constructor {{*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)}}</DisplayString>
+ <DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXDestructorName">C++ Destructor {{*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)}}</DisplayString>
+ <DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXConversionFunctionName">C++ Conversion function {{*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)}}</DisplayString>
+ <DisplayString Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName">C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask)}}</DisplayString>
<DisplayString Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra"
- IncludeView="cpp">{*(clang::DeclarationNameExtra *)(Ptr &amp; ~PtrMask),view(cpp)}</DisplayString>
- <DisplayString Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra">{{Extra ({*(clang::DeclarationNameExtra *)(Ptr &amp; ~PtrMask)})}}</DisplayString>
+ IncludeView="cpp">{*(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask),view(cpp)}</DisplayString>
+ <DisplayString Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra">{{Extra ({*(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask)})}}</DisplayString>
<Expand>
<Item Condition="(Ptr &amp; PtrMask) == StoredIdentifier" Name="[Identifier]">*(clang::IdentifierInfo *)(Ptr &amp; ~PtrMask)</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredObjCZeroArgSelector" Name="[ObjC Zero Arg Selector]">*(clang::IdentifierInfo *)(Ptr &amp; ~PtrMask)</Item>
<Item Condition="(Ptr &amp; PtrMask) == StoredObjCOneArgSelector" Name="[ObjC One Arg Selector]">*(clang::IdentifierInfo *)(Ptr &amp; ~PtrMask)</Item>
- <Item Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra" Name="[Extra]">(clang::DeclarationNameExtra *)(Ptr &amp; ~PtrMask)</Item>
+ <Item Condition="(Ptr &amp; PtrMask) == StoredCXXConstructorName" Name="[C++ Constructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)</Item>
+ <Item Condition="(Ptr &amp; PtrMask) == StoredCXXDestructorName" Name="[C++ Destructor]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)</Item>
+ <Item Condition="(Ptr &amp; PtrMask) == StoredCXXConversionFunctionName" Name="[C++ Conversion function]">*(clang::detail::CXXSpecialNameExtra *)(Ptr &amp; ~PtrMask)</Item>
+ <Item Condition="(Ptr &amp; PtrMask) == StoredCXXOperatorName" Name="[C++ Operator]">*(clang::detail::CXXOperatorIdName *)(Ptr &amp; ~PtrMask)</Item>
+ <Item Condition="(Ptr &amp; PtrMask) == StoredDeclarationNameExtra" Name="[Extra]">(clang::detail::DeclarationNameExtra *)(Ptr &amp; ~PtrMask)</Item>
</Expand>
</Type>
- <Type Name="clang::DeclarationNameExtra">
- <DisplayString IncludeView="cpp"
- Condition="ExtraKindOrNumArgs &gt;= clang::DeclarationNameExtra::CXXConstructor
- &amp;&amp; ExtraKindOrNumArgs &lt;= clang::DeclarationNameExtra::CXXConversionFunction"
- >{((clang::CXXSpecialName *)this)-&gt;Type,view(cpp)}</DisplayString>
- <DisplayString>{(clang::DeclarationNameExtra::ExtraKind)ExtraKindOrNumArgs,en}{" ",sb}{*this,view(cpp)}</DisplayString>
+ <Type Name="clang::detail::DeclarationNameExtra">
+ <DisplayString Condition="ExtraKindOrNumArgs == CXXDeductionGuideName">C++ Deduction guide</DisplayString>
+ <DisplayString Condition="ExtraKindOrNumArgs == CXXLiteralOperatorName">C++ Literal operator</DisplayString>
+ <DisplayString Condition="ExtraKindOrNumArgs == CXXUsingDirective">C++ Using directive</DisplayString>
+ <DisplayString>{(clang::detail::DeclarationNameExtra::ExtraKind)ExtraKindOrNumArgs,en}{" ",sb}{*this,view(cpp)}</DisplayString>
</Type>
<Type Name="clang::Token">
<DisplayString Condition="Kind != clang::tok::identifier">{(clang::tok::TokenKind)Kind,en}</DisplayString>
@@ -458,17 +520,17 @@ For later versions of Visual Studio, no setup is required-->
</Type>
<Type Name="clang::FunctionDecl">
<DisplayString IncludeView="retType">{*(clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType,view(retType)}</DisplayString>
- <DisplayString IncludeView="parm0" Condition="0 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;NumParams"></DisplayString>
+ <DisplayString IncludeView="parm0" Condition="0 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;FunctionTypeBits.NumParams"></DisplayString>
<DisplayString IncludeView="parm0">{*ParamInfo[0]}{*this,view(parm1)nd}</DisplayString>
- <DisplayString IncludeView="parm1" Condition="1 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;NumParams"></DisplayString>
+ <DisplayString IncludeView="parm1" Condition="1 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;FunctionTypeBits.NumParams"></DisplayString>
<DisplayString IncludeView="parm1">, {*ParamInfo[1]}{*this,view(parm2)nd}</DisplayString>
- <DisplayString IncludeView="parm2" Condition="2 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;NumParams"></DisplayString>
+ <DisplayString IncludeView="parm2" Condition="2 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;FunctionTypeBits.NumParams"></DisplayString>
<DisplayString IncludeView="parm2">, {*ParamInfo[2]}{*this,view(parm3)nd}</DisplayString>
- <DisplayString IncludeView="parm3" Condition="3 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;NumParams"></DisplayString>
+ <DisplayString IncludeView="parm3" Condition="3 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;FunctionTypeBits.NumParams"></DisplayString>
<DisplayString IncludeView="parm3">, {*ParamInfo[3]}{*this,view(parm4)nd}</DisplayString>
- <DisplayString IncludeView="parm4" Condition="4 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;NumParams"></DisplayString>
+ <DisplayString IncludeView="parm4" Condition="4 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;FunctionTypeBits.NumParams"></DisplayString>
<DisplayString IncludeView="parm4">, {*ParamInfo[4]}{*this,view(parm5)nd}</DisplayString>
- <DisplayString IncludeView="parm5" Condition="5 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;NumParams"></DisplayString>
+ <DisplayString IncludeView="parm5" Condition="5 == ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;FunctionTypeBits.NumParams"></DisplayString>
<DisplayString IncludeView="parm5">, /* expand for more params */</DisplayString>
<DisplayString>{*this,view(retType)nd} {Name,view(cpp)nd}({*this,view(parm0)nd})</DisplayString>
<Expand>
@@ -477,24 +539,11 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString>{*this,view(parm0)nd}</DisplayString>
<Expand>
<ArrayItems>
- <Size>((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;NumParams</Size>
+ <Size>((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) &amp; ~15))-&gt;BaseType)-&gt;FunctionTypeBits.NumParams</Size>
<ValuePointer>ParamInfo</ValuePointer>
</ArrayItems>
</Expand>
</Synthetic>
- <ExpandedItem>*(clang::Type *)this, view(cmn)</ExpandedItem>
- </Expand>
- </Type>
- <Type Name="clang::OpaquePtr&lt;clang::QualType&gt;">
- <DisplayString>{*(clang::QualType *)this}</DisplayString>
- <Expand>
- <Item Name="Ptr">*(clang::QualType *)this</Item>
- </Expand>
- </Type>
- <Type Name="clang::UnionOpaquePtr&lt;clang::QualType&gt;">
- <DisplayString>{*(clang::QualType *)this}</DisplayString>
- <Expand>
- <Item Name="Ptr">*(clang::QualType *)this</Item>
</Expand>
</Type>
<Type Name="clang::OpaquePtr&lt;*&gt;">
@@ -546,6 +595,10 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString IncludeView="access" Condition="(Ptr&amp;Mask) == clang::AS_none">b</DisplayString>
<DisplayString IncludeView="decl">{*(clang::NamedDecl *)(Ptr&amp;~Mask)}</DisplayString>
<DisplayString>{*this,view(access)} {*this,view(decl)}</DisplayString>
+ <Expand>
+ <Item Name="access">(clang::AccessSpecifier)(Ptr&amp;Mask),en</Item>
+ <Item Name="decl">*(clang::NamedDecl *)(Ptr&amp;~Mask)</Item>
+ </Expand>
</Type>
<Type Name="clang::UnresolvedSet&lt;*&gt;">
<DisplayString>{Decls}</DisplayString>
@@ -557,30 +610,18 @@ For later versions of Visual Studio, no setup is required-->
<DisplayString Condition="ResultKind == clang::LookupResult::Ambiguous">{Ambiguity,en}: {Decls}</DisplayString>
<DisplayString>{ResultKind,en}: {Decls}</DisplayString>
</Type>
- <Type Name="clang::ActionResult&lt;*&gt;" IncludeView="packedValidity">
- <DisplayString Condition="PtrWithInvalid&amp;1">Invalid</DisplayString>
- <DisplayString Condition="!(PtrWithInvalid&amp;1)">Valid</DisplayString>
- </Type>
- <Type Name="clang::ActionResult&lt;*&gt;" IncludeView="unpackedValidity">
+ <Type Name="clang::ActionResult&lt;*, 0&gt;">
<DisplayString Condition="Invalid">Invalid</DisplayString>
- <DisplayString Condition="!Invalid">Valid</DisplayString>
+ <DisplayString Condition="!*(void **)&amp;Val">Unset</DisplayString>
+ <DisplayString>{Val}</DisplayString>
</Type>
- <Type Name="clang::ActionResult&lt;*&gt;" IncludeView="packed">
- <DisplayString>{*this,view(packedValidity)}: {($T1 *)(PtrWithInvalid&amp;~1)}</DisplayString>
+ <Type Name="clang::ActionResult&lt;*, 1&gt;">
+ <DisplayString Condition="PtrWithInvalid&amp;1">Invalid</DisplayString>
+ <DisplayString Condition="!PtrWithInvalid">Unset</DisplayString>
+ <DisplayString>{($T1)(PtrWithInvalid&amp;~1)}</DisplayString>
<Expand>
<Item Name="Invalid">(bool)(PtrWithInvalid&amp;1)</Item>
- <Item Name="Val">($T1 *)(PtrWithInvalid&amp;~1)</Item>
- </Expand>
- </Type>
- <Type Name="clang::ActionResult&lt;*&gt;" IncludeView="unpacked">
- <DisplayString>{*this,view(unpackedValidity)}: {Val}</DisplayString>
- </Type>
- <Type Name="clang::ActionResult&lt;*&gt;">
- <DisplayString Condition="$T2">{*this,view(packed)}</DisplayString>
- <DisplayString Condition="!$T2">{*this,view(unpacked)}</DisplayString>
- <Expand>
- <ExpandedItem Condition="$T2">*this,view(packed)</ExpandedItem>
- <ExpandedItem Condition="!$T2">*this,view(unpacked)</ExpandedItem>
+ <Item Name="Val">($T1)(PtrWithInvalid&amp;~1)</Item>
</Expand>
</Type>
</AutoVisualizer>
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 6b3df825808f..874ad2df0031 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -603,14 +603,15 @@ namespace {
OS << " OS << \"";
}
- void writeDump(raw_ostream &OS) const override {}
+ void writeDump(raw_ostream &OS) const override {
+ OS << " if (!SA->is" << getUpperName() << "Expr())\n";
+ OS << " dumpType(SA->get" << getUpperName()
+ << "Type()->getType());\n";
+ }
void writeDumpChildren(raw_ostream &OS) const override {
OS << " if (SA->is" << getUpperName() << "Expr())\n";
OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
- OS << " else\n";
- OS << " dumpType(SA->get" << getUpperName()
- << "Type()->getType());\n";
}
void writeHasChildren(raw_ostream &OS) const override {
@@ -1885,19 +1886,15 @@ void PragmaClangAttributeSupport::emitMatchRuleList(raw_ostream &OS) {
bool PragmaClangAttributeSupport::isAttributedSupported(
const Record &Attribute) {
- if (Attribute.getValueAsBit("ForcePragmaAttributeSupport"))
- return true;
+ // If the attribute explicitly specified whether to support #pragma clang
+ // attribute, use that setting.
+ bool Unset;
+ bool SpecifiedResult =
+ Attribute.getValueAsBitOrUnset("PragmaAttributeSupport", Unset);
+ if (!Unset)
+ return SpecifiedResult;
+
// Opt-out rules:
- // FIXME: The documentation check should be moved before
- // the ForcePragmaAttributeSupport check after annotate is documented.
- // No documentation present.
- if (Attribute.isValueUnset("Documentation"))
- return false;
- std::vector<Record *> Docs = Attribute.getValueAsListOfDefs("Documentation");
- if (Docs.empty())
- return false;
- if (Docs.size() == 1 && Docs[0]->getName() == "Undocumented")
- return false;
// An attribute requires delayed parsing (LateParsed is on)
if (Attribute.getValueAsBit("LateParsed"))
return false;
@@ -2470,8 +2467,10 @@ namespace {
static const AttrClassDescriptor AttrClassDescriptors[] = {
{ "ATTR", "Attr" },
+ { "TYPE_ATTR", "TypeAttr" },
{ "STMT_ATTR", "StmtAttr" },
{ "INHERITABLE_ATTR", "InheritableAttr" },
+ { "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" },
{ "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" },
{ "PARAMETER_ABI_ATTR", "ParameterABIAttr" }
};
@@ -2937,9 +2936,9 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
if (I != List.cbegin())
OS << " else ";
if (I->first.empty())
- OS << "if (!Scope || Scope->getName() == \"\") {\n";
+ OS << "if (ScopeName == \"\") {\n";
else
- OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
+ OS << "if (ScopeName == \"" << I->first << "\") {\n";
OS << " return llvm::StringSwitch<int>(Name)\n";
GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);
OS << "}";
@@ -3335,7 +3334,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
SS << (Warn ? "warn_attribute_wrong_decl_type_str" :
"err_attribute_wrong_decl_type_str");
SS << ")\n";
- SS << " << Attr.getName() << ";
+ SS << " << Attr << ";
SS << CalculateDiagnostic(*SubjectObj) << ";\n";
SS << " return false;\n";
SS << " }\n";
@@ -3699,39 +3698,67 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
}
// Emits the code to dump an attribute.
-void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
- emitSourceFileHeader("Attribute dumper", OS);
+void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) {
+ emitSourceFileHeader("Attribute text node dumper", OS);
- OS << " switch (A->getKind()) {\n";
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
for (const auto *Attr : Attrs) {
const Record &R = *Attr;
if (!R.getValueAsBit("ASTNode"))
continue;
- OS << " case attr::" << R.getName() << ": {\n";
// If the attribute has a semantically-meaningful name (which is determined
// by whether there is a Spelling enumeration for it), then write out the
// spelling used for the attribute.
+
+ std::string FunctionContent;
+ llvm::raw_string_ostream SS(FunctionContent);
+
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
- OS << " OS << \" \" << A->getSpelling();\n";
+ SS << " OS << \" \" << A->getSpelling();\n";
Args = R.getValueAsListOfDefs("Args");
- if (!Args.empty()) {
- OS << " const auto *SA = cast<" << R.getName()
- << "Attr>(A);\n";
- for (const auto *Arg : Args)
- createArgument(*Arg, R.getName())->writeDump(OS);
+ for (const auto *Arg : Args)
+ createArgument(*Arg, R.getName())->writeDump(SS);
+
+ if (SS.tell()) {
+ OS << " void Visit" << R.getName() << "Attr(const " << R.getName()
+ << "Attr *A) {\n";
+ if (!Args.empty())
+ OS << " const auto *SA = cast<" << R.getName()
+ << "Attr>(A); (void)SA;\n";
+ OS << SS.str();
+ OS << " }\n";
+ }
+ }
+}
- for (const auto *AI : Args)
- createArgument(*AI, R.getName())->writeDumpChildren(OS);
+void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) {
+ emitSourceFileHeader("Attribute text node traverser", OS);
+
+ std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
+ for (const auto *Attr : Attrs) {
+ const Record &R = *Attr;
+ if (!R.getValueAsBit("ASTNode"))
+ continue;
+
+ std::string FunctionContent;
+ llvm::raw_string_ostream SS(FunctionContent);
+
+ Args = R.getValueAsListOfDefs("Args");
+ for (const auto *Arg : Args)
+ createArgument(*Arg, R.getName())->writeDumpChildren(SS);
+ if (SS.tell()) {
+ OS << " void Visit" << R.getName() << "Attr(const " << R.getName()
+ << "Attr *A) {\n";
+ if (!Args.empty())
+ OS << " const auto *SA = cast<" << R.getName()
+ << "Attr>(A); (void)SA;\n";
+ OS << SS.str();
+ OS << " }\n";
}
- OS <<
- " break;\n"
- " }\n";
}
- OS << " }\n";
}
void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
@@ -3749,18 +3776,66 @@ void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
getPragmaAttributeSupport(Records).generateParsingHelpers(OS);
}
+enum class SpellingKind {
+ GNU,
+ CXX11,
+ C2x,
+ Declspec,
+ Microsoft,
+ Keyword,
+ Pragma,
+};
+static const size_t NumSpellingKinds = (size_t)SpellingKind::Pragma + 1;
+
+class SpellingList {
+ std::vector<std::string> Spellings[NumSpellingKinds];
+
+public:
+ ArrayRef<std::string> operator[](SpellingKind K) const {
+ return Spellings[(size_t)K];
+ }
+
+ void add(const Record &Attr, FlattenedSpelling Spelling) {
+ SpellingKind Kind = StringSwitch<SpellingKind>(Spelling.variety())
+ .Case("GNU", SpellingKind::GNU)
+ .Case("CXX11", SpellingKind::CXX11)
+ .Case("C2x", SpellingKind::C2x)
+ .Case("Declspec", SpellingKind::Declspec)
+ .Case("Microsoft", SpellingKind::Microsoft)
+ .Case("Keyword", SpellingKind::Keyword)
+ .Case("Pragma", SpellingKind::Pragma);
+ std::string Name;
+ if (!Spelling.nameSpace().empty()) {
+ switch (Kind) {
+ case SpellingKind::CXX11:
+ case SpellingKind::C2x:
+ Name = Spelling.nameSpace() + "::";
+ break;
+ case SpellingKind::Pragma:
+ Name = Spelling.nameSpace() + " ";
+ break;
+ default:
+ PrintFatalError(Attr.getLoc(), "Unexpected namespace in spelling");
+ }
+ }
+ Name += Spelling.name();
+
+ Spellings[(size_t)Kind].push_back(Name);
+ }
+};
+
class DocumentationData {
public:
const Record *Documentation;
const Record *Attribute;
std::string Heading;
- unsigned SupportedSpellings;
+ SpellingList SupportedSpellings;
DocumentationData(const Record &Documentation, const Record &Attribute,
- const std::pair<std::string, unsigned> HeadingAndKinds)
+ std::pair<std::string, SpellingList> HeadingAndSpellings)
: Documentation(&Documentation), Attribute(&Attribute),
- Heading(std::move(HeadingAndKinds.first)),
- SupportedSpellings(HeadingAndKinds.second) {}
+ Heading(std::move(HeadingAndSpellings.first)),
+ SupportedSpellings(std::move(HeadingAndSpellings.second)) {}
};
static void WriteCategoryHeader(const Record *DocCategory,
@@ -3776,28 +3851,21 @@ static void WriteCategoryHeader(const Record *DocCategory,
OS << "\n\n";
}
-enum SpellingKind {
- GNU = 1 << 0,
- CXX11 = 1 << 1,
- C2x = 1 << 2,
- Declspec = 1 << 3,
- Microsoft = 1 << 4,
- Keyword = 1 << 5,
- Pragma = 1 << 6
-};
-
-static std::pair<std::string, unsigned>
-GetAttributeHeadingAndSpellingKinds(const Record &Documentation,
- const Record &Attribute) {
+static std::pair<std::string, SpellingList>
+GetAttributeHeadingAndSpellings(const Record &Documentation,
+ const Record &Attribute) {
// FIXME: there is no way to have a per-spelling category for the attribute
// documentation. This may not be a limiting factor since the spellings
// should generally be consistently applied across the category.
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute);
+ if (Spellings.empty())
+ PrintFatalError(Attribute.getLoc(),
+ "Attribute has no supported spellings; cannot be "
+ "documented");
// Determine the heading to be used for this attribute.
std::string Heading = Documentation.getValueAsString("Heading");
- bool CustomHeading = !Heading.empty();
if (Heading.empty()) {
// If there's only one spelling, we can simply use that.
if (Spellings.size() == 1)
@@ -3821,51 +3889,11 @@ GetAttributeHeadingAndSpellingKinds(const Record &Documentation,
PrintFatalError(Attribute.getLoc(),
"This attribute requires a heading to be specified");
- // Gather a list of unique spellings; this is not the same as the semantic
- // spelling for the attribute. Variations in underscores and other non-
- // semantic characters are still acceptable.
- std::vector<std::string> Names;
+ SpellingList SupportedSpellings;
+ for (const auto &I : Spellings)
+ SupportedSpellings.add(Attribute, I);
- unsigned SupportedSpellings = 0;
- for (const auto &I : Spellings) {
- SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
- .Case("GNU", GNU)
- .Case("CXX11", CXX11)
- .Case("C2x", C2x)
- .Case("Declspec", Declspec)
- .Case("Microsoft", Microsoft)
- .Case("Keyword", Keyword)
- .Case("Pragma", Pragma);
-
- // Mask in the supported spelling.
- SupportedSpellings |= Kind;
-
- std::string Name;
- if ((Kind == CXX11 || Kind == C2x) && !I.nameSpace().empty())
- Name = I.nameSpace() + "::";
- Name += I.name();
-
- // If this name is the same as the heading, do not add it.
- if (Name != Heading)
- Names.push_back(Name);
- }
-
- // Print out the heading for the attribute. If there are alternate spellings,
- // then display those after the heading.
- if (!CustomHeading && !Names.empty()) {
- Heading += " (";
- for (auto I = Names.begin(), E = Names.end(); I != E; ++I) {
- if (I != Names.begin())
- Heading += ", ";
- Heading += *I;
- }
- Heading += ")";
- }
- if (!SupportedSpellings)
- PrintFatalError(Attribute.getLoc(),
- "Attribute has no supported spellings; cannot be "
- "documented");
- return std::make_pair(std::move(Heading), SupportedSpellings);
+ return std::make_pair(std::move(Heading), std::move(SupportedSpellings));
}
static void WriteDocumentation(RecordKeeper &Records,
@@ -3874,23 +3902,30 @@ static void WriteDocumentation(RecordKeeper &Records,
// List what spelling syntaxes the attribute supports.
OS << ".. csv-table:: Supported Syntaxes\n";
- OS << " :header: \"GNU\", \"C++11\", \"C2x\", \"__declspec\", \"Keyword\",";
- OS << " \"Pragma\", \"Pragma clang attribute\"\n\n";
+ OS << " :header: \"GNU\", \"C++11\", \"C2x\", \"``__declspec``\",";
+ OS << " \"Keyword\", \"``#pragma``\", \"``#pragma clang attribute``\"\n\n";
OS << " \"";
- if (Doc.SupportedSpellings & GNU) OS << "X";
- OS << "\",\"";
- if (Doc.SupportedSpellings & CXX11) OS << "X";
- OS << "\",\"";
- if (Doc.SupportedSpellings & C2x) OS << "X";
- OS << "\",\"";
- if (Doc.SupportedSpellings & Declspec) OS << "X";
- OS << "\",\"";
- if (Doc.SupportedSpellings & Keyword) OS << "X";
- OS << "\", \"";
- if (Doc.SupportedSpellings & Pragma) OS << "X";
- OS << "\", \"";
- if (getPragmaAttributeSupport(Records).isAttributedSupported(*Doc.Attribute))
- OS << "X";
+ for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) {
+ SpellingKind K = (SpellingKind)Kind;
+ // TODO: List Microsoft (IDL-style attribute) spellings once we fully
+ // support them.
+ if (K == SpellingKind::Microsoft)
+ continue;
+
+ bool PrintedAny = false;
+ for (StringRef Spelling : Doc.SupportedSpellings[K]) {
+ if (PrintedAny)
+ OS << " |br| ";
+ OS << "``" << Spelling << "``";
+ PrintedAny = true;
+ }
+
+ OS << "\",\"";
+ }
+
+ if (getPragmaAttributeSupport(Records).isAttributedSupported(
+ *Doc.Attribute))
+ OS << "Yes";
OS << "\"\n\n";
// If the attribute is deprecated, print a message about it, and possibly
@@ -3946,7 +3981,7 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
if (!Undocumented)
SplitDocs[Category].push_back(DocumentationData(
- Doc, Attr, GetAttributeHeadingAndSpellingKinds(Doc, Attr)));
+ Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr)));
}
}
@@ -3955,10 +3990,10 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
for (auto &I : SplitDocs) {
WriteCategoryHeader(I.first, OS);
- llvm::sort(I.second.begin(), I.second.end(),
+ llvm::sort(I.second,
[](const DocumentationData &D1, const DocumentationData &D2) {
return D1.Heading < D2.Heading;
- });
+ });
// Walk over each of the attributes in the category and write out their
// documentation.
@@ -3971,12 +4006,7 @@ void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
raw_ostream &OS) {
PragmaClangAttributeSupport Support = getPragmaAttributeSupport(Records);
ParsedAttrMap Attrs = getParsedAttrList(Records);
- unsigned NumAttrs = 0;
- for (const auto &I : Attrs) {
- if (Support.isAttributedSupported(*I.second))
- ++NumAttrs;
- }
- OS << "#pragma clang attribute supports " << NumAttrs << " attributes:\n";
+ OS << "#pragma clang attribute supports the following attributes:\n";
for (const auto &I : Attrs) {
if (!Support.isAttributedSupported(*I.second))
continue;
@@ -4008,6 +4038,7 @@ void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
}
OS << ")\n";
}
+ OS << "End of supported attributes.\n";
}
} // end namespace clang
diff --git a/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp b/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
index bea97ae13289..7c114dbe8e18 100644
--- a/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
+++ b/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This tablegen backend emits an fficient function to translate HTML named
+// This tablegen backend emits an efficient function to translate HTML named
// character references to UTF-8 sequences.
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
index 6bfb3f9f61f5..f551d9328227 100644
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -208,9 +208,9 @@ static void groupDiagnostics(const std::vector<Record*> &Diags,
E = SortedGroups.end();
I != E; ++I) {
MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
- llvm::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
+ llvm::sort(GroupDiags, beforeThanCompare);
}
- llvm::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
+ llvm::sort(SortedGroups, beforeThanCompareGroups);
// Warn about the same group being used anonymously in multiple places.
for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
@@ -1595,10 +1595,10 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
Index.push_back(RecordIndexElement(R));
}
- llvm::sort(Index.begin(), Index.end(),
+ llvm::sort(Index,
[](const RecordIndexElement &Lhs, const RecordIndexElement &Rhs) {
return Lhs.Name < Rhs.Name;
- });
+ });
for (unsigned i = 0, e = Index.size(); i != e; ++i) {
const RecordIndexElement &R = Index[i];
@@ -1694,7 +1694,7 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record*> DiagGroups =
Records.getAllDerivedDefinitions("DiagGroup");
- llvm::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
+ llvm::sort(DiagGroups, diagGroupBeforeByName);
DiagGroupParentMap DGParentMap(Records);
@@ -1713,10 +1713,8 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
DiagsInPedanticSet.end());
RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
GroupsInPedanticSet.end());
- llvm::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
- beforeThanCompare);
- llvm::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
- beforeThanCompare);
+ llvm::sort(DiagsInPedantic, beforeThanCompare);
+ llvm::sort(GroupsInPedantic, beforeThanCompare);
PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
DiagsInPedantic.begin(),
DiagsInPedantic.end());
@@ -1765,7 +1763,7 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
OS << "Also controls ";
bool First = true;
- llvm::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
+ llvm::sort(GroupInfo.SubGroups);
for (const auto &Name : GroupInfo.SubGroups) {
if (!First) OS << ", ";
OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
diff --git a/utils/TableGen/ClangOptionDocEmitter.cpp b/utils/TableGen/ClangOptionDocEmitter.cpp
index 7fe487e54698..cf642ec92bd8 100644
--- a/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -111,7 +111,7 @@ Documentation extractDocumentation(RecordKeeper &Records) {
auto DocumentationForOption = [&](Record *R) -> DocumentedOption {
auto &A = Aliases[R];
- llvm::sort(A.begin(), A.end(), CompareByName);
+ llvm::sort(A, CompareByName);
return {R, std::move(A)};
};
@@ -120,7 +120,7 @@ Documentation extractDocumentation(RecordKeeper &Records) {
Documentation D;
auto &Groups = GroupsInGroup[R];
- llvm::sort(Groups.begin(), Groups.end(), CompareByLocation);
+ llvm::sort(Groups, CompareByLocation);
for (Record *G : Groups) {
D.Groups.emplace_back();
D.Groups.back().Group = G;
@@ -129,7 +129,7 @@ Documentation extractDocumentation(RecordKeeper &Records) {
}
auto &Options = OptionsInGroup[R];
- llvm::sort(Options.begin(), Options.end(), CompareByName);
+ llvm::sort(Options, CompareByName);
for (Record *O : Options)
D.Options.push_back(DocumentationForOption(O));
diff --git a/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp
index 4fda8e47e4a8..57850a438720 100644
--- a/utils/TableGen/ClangSACheckersEmitter.cpp
+++ b/utils/TableGen/ClangSACheckersEmitter.cpp
@@ -11,34 +11,19 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <map>
#include <string>
+
using namespace llvm;
//===----------------------------------------------------------------------===//
// Static Analyzer Checkers Tables generation
//===----------------------------------------------------------------------===//
-/// True if it is specified hidden or a parent package is specified
-/// as hidden, otherwise false.
-static bool isHidden(const Record &R) {
- if (R.getValueAsBit("Hidden"))
- return true;
- // Not declared as hidden, check the parent package if it is hidden.
- if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("ParentPackage")))
- return isHidden(*DI->getDef());
-
- return false;
-}
-
-static bool isCheckerNamed(const Record *R) {
- return !R->getValueAsString("CheckerName").empty();
-}
-
static std::string getPackageFullName(const Record *R);
static std::string getParentPackageFullName(const Record *R) {
@@ -50,17 +35,19 @@ static std::string getParentPackageFullName(const Record *R) {
static std::string getPackageFullName(const Record *R) {
std::string name = getParentPackageFullName(R);
- if (!name.empty()) name += ".";
+ if (!name.empty())
+ name += ".";
+ assert(!R->getValueAsString("PackageName").empty());
name += R->getValueAsString("PackageName");
return name;
}
static std::string getCheckerFullName(const Record *R) {
std::string name = getParentPackageFullName(R);
- if (isCheckerNamed(R)) {
- if (!name.empty()) name += ".";
- name += R->getValueAsString("CheckerName");
- }
+ if (!name.empty())
+ name += ".";
+ assert(!R->getValueAsString("CheckerName").empty());
+ name += R->getValueAsString("CheckerName");
return name;
}
@@ -70,129 +57,49 @@ static std::string getStringValue(const Record &R, StringRef field) {
return std::string();
}
-namespace {
-struct GroupInfo {
- llvm::DenseSet<const Record*> Checkers;
- llvm::DenseSet<const Record *> SubGroups;
- bool Hidden;
- unsigned Index;
+// Calculates the integer value representing the BitsInit object
+static inline uint64_t getValueFromBitsInit(const BitsInit *B, const Record &R) {
+ assert(B->getNumBits() <= sizeof(uint64_t) * 8 && "BitInits' too long!");
- GroupInfo() : Hidden(false) { }
-};
+ uint64_t Value = 0;
+ for (unsigned i = 0, e = B->getNumBits(); i != e; ++i) {
+ const auto *Bit = dyn_cast<BitInit>(B->getBit(i));
+ if (Bit)
+ Value |= uint64_t(Bit->getValue()) << i;
+ else
+ PrintFatalError(R.getLoc(),
+ "missing Documentation for " + getCheckerFullName(&R));
+ }
+ return Value;
}
-static void addPackageToCheckerGroup(const Record *package, const Record *group,
- llvm::DenseMap<const Record *, GroupInfo *> &recordGroupMap) {
- llvm::DenseSet<const Record *> &checkers = recordGroupMap[package]->Checkers;
- for (llvm::DenseSet<const Record *>::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I)
- recordGroupMap[group]->Checkers.insert(*I);
+static std::string getCheckerDocs(const Record &R) {
+ StringRef LandingPage;
+ if (BitsInit *BI = R.getValueAsBitsInit("Documentation")) {
+ uint64_t V = getValueFromBitsInit(BI, R);
+ if (V == 1)
+ LandingPage = "available_checks.html";
+ else if (V == 2)
+ LandingPage = "alpha_checks.html";
+ }
+
+ if (LandingPage.empty())
+ return "";
- llvm::DenseSet<const Record *> &subGroups = recordGroupMap[package]->SubGroups;
- for (llvm::DenseSet<const Record *>::iterator
- I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
- addPackageToCheckerGroup(*I, group, recordGroupMap);
+ return (llvm::Twine("https://clang-analyzer.llvm.org/") + LandingPage + "#" +
+ getCheckerFullName(&R))
+ .str();
}
namespace clang {
void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
- llvm::DenseMap<const Record *, unsigned> checkerRecIndexMap;
- for (unsigned i = 0, e = checkers.size(); i != e; ++i)
- checkerRecIndexMap[checkers[i]] = i;
-
- // Invert the mapping of checkers to package/group into a one to many
- // mapping of packages/groups to checkers.
- std::map<std::string, GroupInfo> groupInfoByName;
- llvm::DenseMap<const Record *, GroupInfo *> recordGroupMap;
-
std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
- for (unsigned i = 0, e = packages.size(); i != e; ++i) {
- Record *R = packages[i];
- std::string fullName = getPackageFullName(R);
- if (!fullName.empty()) {
- GroupInfo &info = groupInfoByName[fullName];
- info.Hidden = isHidden(*R);
- recordGroupMap[R] = &info;
- }
- }
-
- std::vector<Record*>
- checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup");
- for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) {
- Record *R = checkerGroups[i];
- std::string name = R->getValueAsString("GroupName");
- if (!name.empty()) {
- GroupInfo &info = groupInfoByName[name];
- recordGroupMap[R] = &info;
- }
- }
- for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
- Record *R = checkers[i];
- Record *package = nullptr;
- if (DefInit *
- DI = dyn_cast<DefInit>(R->getValueInit("ParentPackage")))
- package = DI->getDef();
- if (!isCheckerNamed(R) && !package)
- PrintFatalError(R->getLoc(), "Checker '" + R->getName() +
- "' is neither named, nor in a package!");
-
- if (isCheckerNamed(R)) {
- // Create a pseudo-group to hold this checker.
- std::string fullName = getCheckerFullName(R);
- GroupInfo &info = groupInfoByName[fullName];
- info.Hidden = R->getValueAsBit("Hidden");
- recordGroupMap[R] = &info;
- info.Checkers.insert(R);
- } else {
- recordGroupMap[package]->Checkers.insert(R);
- }
+ using SortedRecords = llvm::StringMap<const Record *>;
- Record *currR = isCheckerNamed(R) ? R : package;
- // Insert the checker and its parent packages into the subgroups set of
- // the corresponding parent package.
- while (DefInit *DI
- = dyn_cast<DefInit>(currR->getValueInit("ParentPackage"))) {
- Record *parentPackage = DI->getDef();
- recordGroupMap[parentPackage]->SubGroups.insert(currR);
- currR = parentPackage;
- }
- // Insert the checker into the set of its group.
- if (DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group")))
- recordGroupMap[DI->getDef()]->Checkers.insert(R);
- }
-
- // If a package is in group, add all its checkers and its sub-packages
- // checkers into the group.
- for (unsigned i = 0, e = packages.size(); i != e; ++i)
- if (DefInit *DI = dyn_cast<DefInit>(packages[i]->getValueInit("Group")))
- addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap);
-
- typedef std::map<std::string, const Record *> SortedRecords;
- typedef llvm::DenseMap<const Record *, unsigned> RecToSortIndex;
-
- SortedRecords sortedGroups;
- RecToSortIndex groupToSortIndex;
- OS << "\n#ifdef GET_GROUPS\n";
- {
- for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i)
- sortedGroups[checkerGroups[i]->getValueAsString("GroupName")]
- = checkerGroups[i];
-
- unsigned sortIndex = 0;
- for (SortedRecords::iterator
- I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) {
- const Record *R = I->second;
-
- OS << "GROUP(" << "\"";
- OS.write_escaped(R->getValueAsString("GroupName")) << "\"";
- OS << ")\n";
-
- groupToSortIndex[R] = sortIndex++;
- }
- }
- OS << "#endif // GET_GROUPS\n\n";
+ OS << "// This file is automatically generated. Do not edit this file by "
+ "hand.\n";
OS << "\n#ifdef GET_PACKAGES\n";
{
@@ -205,17 +112,7 @@ void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
const Record &R = *I->second;
OS << "PACKAGE(" << "\"";
- OS.write_escaped(getPackageFullName(&R)) << "\", ";
- // Group index
- if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
- OS << groupToSortIndex[DI->getDef()] << ", ";
- else
- OS << "-1, ";
- // Hidden bit
- if (isHidden(R))
- OS << "true";
- else
- OS << "false";
+ OS.write_escaped(getPackageFullName(&R)) << '\"';
OS << ")\n";
}
}
@@ -226,98 +123,15 @@ void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
const Record &R = *checkers[i];
OS << "CHECKER(" << "\"";
- std::string name;
- if (isCheckerNamed(&R))
- name = getCheckerFullName(&R);
- OS.write_escaped(name) << "\", ";
+ OS.write_escaped(getCheckerFullName(&R)) << "\", ";
OS << R.getName() << ", ";
- OS << getStringValue(R, "DescFile") << ", ";
OS << "\"";
OS.write_escaped(getStringValue(R, "HelpText")) << "\", ";
- // Group index
- if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
- OS << groupToSortIndex[DI->getDef()] << ", ";
- else
- OS << "-1, ";
- // Hidden bit
- if (isHidden(R))
- OS << "true";
- else
- OS << "false";
+ OS << "\"";
+ OS.write_escaped(getCheckerDocs(R));
+ OS << "\"";
OS << ")\n";
}
OS << "#endif // GET_CHECKERS\n\n";
-
- unsigned index = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I)
- I->second.Index = index++;
-
- // Walk through the packages/groups/checkers emitting an array for each
- // set of checkers and an array for each set of subpackages.
-
- OS << "\n#ifdef GET_MEMBER_ARRAYS\n";
- unsigned maxLen = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
- maxLen = std::max(maxLen, (unsigned)I->first.size());
-
- llvm::DenseSet<const Record *> &checkers = I->second.Checkers;
- if (!checkers.empty()) {
- OS << "static const short CheckerArray" << I->second.Index << "[] = { ";
- // Make the output order deterministic.
- std::map<int, const Record *> sorted;
- for (llvm::DenseSet<const Record *>::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I)
- sorted[(*I)->getID()] = *I;
-
- for (std::map<int, const Record *>::iterator
- I = sorted.begin(), E = sorted.end(); I != E; ++I)
- OS << checkerRecIndexMap[I->second] << ", ";
- OS << "-1 };\n";
- }
-
- llvm::DenseSet<const Record *> &subGroups = I->second.SubGroups;
- if (!subGroups.empty()) {
- OS << "static const short SubPackageArray" << I->second.Index << "[] = { ";
- // Make the output order deterministic.
- std::map<int, const Record *> sorted;
- for (llvm::DenseSet<const Record *>::iterator
- I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
- sorted[(*I)->getID()] = *I;
-
- for (std::map<int, const Record *>::iterator
- I = sorted.begin(), E = sorted.end(); I != E; ++I) {
- OS << recordGroupMap[I->second]->Index << ", ";
- }
- OS << "-1 };\n";
- }
- }
- OS << "#endif // GET_MEMBER_ARRAYS\n\n";
-
- OS << "\n#ifdef GET_CHECKNAME_TABLE\n";
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
- // Group option string.
- OS << " { \"";
- OS.write_escaped(I->first) << "\","
- << std::string(maxLen-I->first.size()+1, ' ');
-
- if (I->second.Checkers.empty())
- OS << "0, ";
- else
- OS << "CheckerArray" << I->second.Index << ", ";
-
- // Subgroups.
- if (I->second.SubGroups.empty())
- OS << "0, ";
- else
- OS << "SubPackageArray" << I->second.Index << ", ";
-
- OS << (I->second.Hidden ? "true" : "false");
-
- OS << " },\n";
- }
- OS << "#endif // GET_CHECKNAME_TABLE\n\n";
}
} // end namespace clang
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index eca03a5892e2..f92110d5d7ac 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -494,6 +494,7 @@ private:
std::pair<Type, std::string> emitDagSaveTemp(DagInit *DI);
std::pair<Type, std::string> emitDagSplat(DagInit *DI);
std::pair<Type, std::string> emitDagDup(DagInit *DI);
+ std::pair<Type, std::string> emitDagDupTyped(DagInit *DI);
std::pair<Type, std::string> emitDagShuffle(DagInit *DI);
std::pair<Type, std::string> emitDagCast(DagInit *DI, bool IsBitCast);
std::pair<Type, std::string> emitDagCall(DagInit *DI);
@@ -897,6 +898,18 @@ void Type::applyModifier(char Mod) {
Float = true;
ElementBitwidth = 16;
break;
+ case '0':
+ Float = true;
+ if (AppliedQuad)
+ Bitwidth /= 2;
+ ElementBitwidth = 16;
+ break;
+ case '1':
+ Float = true;
+ if (!AppliedQuad)
+ Bitwidth *= 2;
+ ElementBitwidth = 16;
+ break;
case 'g':
if (AppliedQuad)
Bitwidth /= 2;
@@ -1507,6 +1520,8 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDag(DagInit *DI) {
return emitDagShuffle(DI);
if (Op == "dup")
return emitDagDup(DI);
+ if (Op == "dup_typed")
+ return emitDagDupTyped(DI);
if (Op == "splat")
return emitDagSplat(DI);
if (Op == "save_temp")
@@ -1771,6 +1786,28 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) {
return std::make_pair(T, S);
}
+std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDupTyped(DagInit *DI) {
+ assert_with_loc(DI->getNumArgs() == 2, "dup_typed() expects two arguments");
+ std::pair<Type, std::string> A = emitDagArg(DI->getArg(0),
+ DI->getArgNameStr(0));
+ std::pair<Type, std::string> B = emitDagArg(DI->getArg(1),
+ DI->getArgNameStr(1));
+ assert_with_loc(B.first.isScalar(),
+ "dup_typed() requires a scalar as the second argument");
+
+ Type T = A.first;
+ assert_with_loc(T.isVector(), "dup_typed() used but target type is scalar!");
+ std::string S = "(" + T.str() + ") {";
+ for (unsigned I = 0; I < T.getNumElements(); ++I) {
+ if (I != 0)
+ S += ", ";
+ S += B.second;
+ }
+ S += "}";
+
+ return std::make_pair(T, S);
+}
+
std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) {
assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments");
std::pair<Type, std::string> A = emitDagArg(DI->getArg(0),
@@ -2020,7 +2057,7 @@ void NeonEmitter::createIntrinsic(Record *R,
}
}
- llvm::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
+ llvm::sort(NewTypeSpecs);
NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()),
NewTypeSpecs.end());
auto &Entry = IntrinsicMap[Name];
@@ -2409,7 +2446,7 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "#endif\n";
OS << "\n";
- OS << "#define __ai static inline __attribute__((__always_inline__, "
+ OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
"__nodebug__))\n\n";
SmallVector<Intrinsic *, 128> Defs;
@@ -2518,7 +2555,7 @@ void NeonEmitter::runFP16(raw_ostream &OS) {
OS << "typedef __fp16 float16_t;\n";
- OS << "#define __ai static inline __attribute__((__always_inline__, "
+ OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
"__nodebug__))\n\n";
SmallVector<Intrinsic *, 128> Defs;
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index a2ba131628f1..f40d7f123353 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -23,6 +23,8 @@ using namespace llvm;
using namespace clang;
enum ActionType {
+ PrintRecords,
+ DumpJSON,
GenClangAttrClasses,
GenClangAttrParserStringSwitches,
GenClangAttrSubjectMatchRulesParserStringSwitches,
@@ -38,7 +40,8 @@ enum ActionType {
GenClangAttrParsedAttrList,
GenClangAttrParsedAttrImpl,
GenClangAttrParsedAttrKinds,
- GenClangAttrDump,
+ GenClangAttrTextNodeDump,
+ GenClangAttrNodeTraverse,
GenClangDiagsDefs,
GenClangDiagGroups,
GenClangDiagsIndexName,
@@ -66,6 +69,10 @@ namespace {
cl::opt<ActionType> Action(
cl::desc("Action to perform:"),
cl::values(
+ clEnumValN(PrintRecords, "print-records",
+ "Print all records to stdout (default)"),
+ clEnumValN(DumpJSON, "dump-json",
+ "Dump all records as machine-readable JSON"),
clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
"Generate clang attribute clases"),
clEnumValN(GenClangAttrParserStringSwitches,
@@ -106,8 +113,10 @@ cl::opt<ActionType> Action(
clEnumValN(GenClangAttrParsedAttrKinds,
"gen-clang-attr-parsed-attr-kinds",
"Generate a clang parsed attribute kinds"),
- clEnumValN(GenClangAttrDump, "gen-clang-attr-dump",
- "Generate clang attribute dumper"),
+ clEnumValN(GenClangAttrTextNodeDump, "gen-clang-attr-text-node-dump",
+ "Generate clang attribute text node dumper"),
+ clEnumValN(GenClangAttrNodeTraverse, "gen-clang-attr-node-traverse",
+ "Generate clang attribute traverser"),
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
"Generate Clang diagnostics definitions"),
clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
@@ -164,6 +173,12 @@ ClangComponent("clang-component",
bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
switch (Action) {
+ case PrintRecords:
+ OS << Records; // No argument, dump all contents
+ break;
+ case DumpJSON:
+ EmitJSON(Records, OS);
+ break;
case GenClangAttrClasses:
EmitClangAttrClass(Records, OS);
break;
@@ -209,8 +224,11 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenClangAttrParsedAttrKinds:
EmitClangAttrParsedAttrKinds(Records, OS);
break;
- case GenClangAttrDump:
- EmitClangAttrDump(Records, OS);
+ case GenClangAttrTextNodeDump:
+ EmitClangAttrTextNodeDump(Records, OS);
+ break;
+ case GenClangAttrNodeTraverse:
+ EmitClangAttrNodeTraverse(Records, OS);
break;
case GenClangDiagsDefs:
EmitClangDiagsDefs(Records, OS, ClangComponent);
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index 706e812ae874..410d0100be19 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -23,63 +23,63 @@ namespace llvm {
class RecordKeeper;
}
-using llvm::raw_ostream;
-using llvm::RecordKeeper;
-
namespace clang {
-void EmitClangDeclContext(RecordKeeper &RK, raw_ostream &OS);
-void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
+void EmitClangDeclContext(llvm::RecordKeeper &RK, llvm::raw_ostream &OS);
+void EmitClangASTNodes(llvm::RecordKeeper &RK, llvm::raw_ostream &OS,
const std::string &N, const std::string &S);
-void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
- raw_ostream &OS);
-void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS);
-
-void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
+void EmitClangAttrParserStringSwitches(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrSubjectMatchRulesParserStringSwitches(llvm::RecordKeeper &Records,
+ llvm::raw_ostream &OS);
+void EmitClangAttrClass(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrImpl(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrSubjectMatchRuleList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrPCHRead(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrPCHWrite(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrHasAttrImpl(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrSpellingListIndex(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrASTVisitor(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrTemplateInstantiate(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrParsedAttrList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrParsedAttrImpl(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrParsedAttrKinds(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrTextNodeDump(llvm::RecordKeeper &Records,
+ llvm::raw_ostream &OS);
+void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records,
+ llvm::raw_ostream &OS);
+
+void EmitClangDiagsDefs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS,
const std::string &Component);
-void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangDiagGroups(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangDiagsIndexName(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangSACheckers(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangCommentHTMLTags(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangCommentHTMLTagsProperties(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangCommentHTMLNamedCharacterReferences(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangCommentCommandInfo(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangCommentCommandList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
-void EmitFP16(RecordKeeper &Records, raw_ostream &OS);
-void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);
-void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS);
-void EmitNeon2(RecordKeeper &Records, raw_ostream &OS);
-void EmitNeonSema2(RecordKeeper &Records, raw_ostream &OS);
-void EmitNeonTest2(RecordKeeper &Records, raw_ostream &OS);
+void EmitNeon(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitFP16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitNeonSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitNeonTest(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitNeon2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitNeonSema2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitNeonTest2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangAttrDocs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangDiagDocs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangOptDocs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitClangDataCollectors(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangDataCollectors(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
- raw_ostream &OS);
+void EmitTestPragmaAttributeSupportedAttributes(llvm::RecordKeeper &Records,
+ llvm::raw_ostream &OS);
} // end namespace clang
diff --git a/utils/TestUtils/deep-stack.py b/utils/TestUtils/deep-stack.py
index 1750a5fca031..10bf47acb1f7 100755
--- a/utils/TestUtils/deep-stack.py
+++ b/utils/TestUtils/deep-stack.py
@@ -1,22 +1,23 @@
#!/usr/bin/env python
+from __future__ import absolute_import, division, print_function
def pcall(f, N):
if N == 0:
- print >>f, ' f(0)'
+ print(' f(0)', file=f)
return
- print >>f, ' f('
+ print(' f(', file=f)
pcall(f, N - 1)
- print >>f, ' )'
+ print(' )', file=f)
def main():
f = open('t.c','w')
- print >>f, 'int f(int n) { return n; }'
- print >>f, 'int t() {'
- print >>f, ' return'
+ print('int f(int n) { return n; }', file=f)
+ print('int t() {', file=f)
+ print(' return', file=f)
pcall(f, 10000)
- print >>f, ' ;'
- print >>f, '}'
+ print(' ;', file=f)
+ print('}', file=f)
if __name__ == "__main__":
import sys
diff --git a/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py
index 7c9744727e90..be503499622d 100755
--- a/utils/analyzer/CmpRuns.py
+++ b/utils/analyzer/CmpRuns.py
@@ -25,6 +25,7 @@ Usage:
diff = compareResults(resultsA, resultsB)
"""
+from __future__ import division, print_function
from collections import defaultdict
@@ -38,7 +39,7 @@ import sys
STATS_REGEXP = re.compile(r"Statistics: (\{.+\})", re.MULTILINE | re.DOTALL)
-class Colors:
+class Colors(object):
"""
Color for terminal highlight.
"""
@@ -50,14 +51,14 @@ class Colors:
# path - the analysis output directory
# root - the name of the root directory, which will be disregarded when
# determining the source file name
-class SingleRunInfo:
+class SingleRunInfo(object):
def __init__(self, path, root="", verboseLog=None):
self.path = path
self.root = root.rstrip("/\\")
self.verboseLog = verboseLog
-class AnalysisDiagnostic:
+class AnalysisDiagnostic(object):
def __init__(self, data, report, htmlReport):
self._data = data
self._loc = self._data['location']
@@ -117,14 +118,14 @@ class AnalysisDiagnostic:
return self._data
-class AnalysisReport:
+class AnalysisReport(object):
def __init__(self, run, files):
self.run = run
self.files = files
self.diagnostics = []
-class AnalysisRun:
+class AnalysisRun(object):
def __init__(self, info):
self.path = info.path
self.root = info.root
@@ -281,19 +282,33 @@ def compareResults(A, B, opts):
return res
+def computePercentile(l, percentile):
+ """
+ Return computed percentile.
+ """
+ return sorted(l)[int(round(percentile * len(l) + 0.5)) - 1]
+
def deriveStats(results):
# Assume all keys are the same in each statistics bucket.
combined_data = defaultdict(list)
+
+ # Collect data on paths length.
+ for report in results.reports:
+ for diagnostic in report.diagnostics:
+ combined_data['PathsLength'].append(diagnostic.getPathLength())
+
for stat in results.stats:
- for key, value in stat.iteritems():
+ for key, value in stat.items():
combined_data[key].append(value)
combined_stats = {}
- for key, values in combined_data.iteritems():
+ for key, values in combined_data.items():
combined_stats[str(key)] = {
"max": max(values),
"min": min(values),
"mean": sum(values) / len(values),
- "median": sorted(values)[len(values) / 2],
+ "90th %tile": computePercentile(values, 0.9),
+ "95th %tile": computePercentile(values, 0.95),
+ "median": sorted(values)[len(values) // 2],
"total": sum(values)
}
return combined_stats
@@ -304,7 +319,7 @@ def compareStats(resultsA, resultsB):
statsB = deriveStats(resultsB)
keys = sorted(statsA.keys())
for key in keys:
- print key
+ print(key)
for kkey in statsA[key]:
valA = float(statsA[key][kkey])
valB = float(statsB[key][kkey])
@@ -317,7 +332,7 @@ def compareStats(resultsA, resultsB):
report = Colors.GREEN + report + Colors.CLEAR
elif ratio > 0.2:
report = Colors.RED + report + Colors.CLEAR
- print "\t %s %s" % (kkey, report)
+ print("\t %s %s" % (kkey, report))
def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True,
Stdout=sys.stdout):
diff --git a/utils/analyzer/SATestAdd.py b/utils/analyzer/SATestAdd.py
index 041b24409fe3..52089f4e0660 100644
--- a/utils/analyzer/SATestAdd.py
+++ b/utils/analyzer/SATestAdd.py
@@ -42,6 +42,7 @@ the Repository Directory.
diff -ur CachedSource PatchedSource \
> changes_for_analyzer.patch
"""
+from __future__ import absolute_import, division, print_function
import SATestBuild
import os
@@ -66,7 +67,7 @@ def addNewProject(ID, BuildMode):
CurDir = os.path.abspath(os.curdir)
Dir = SATestBuild.getProjectDir(ID)
if not os.path.exists(Dir):
- print "Error: Project directory is missing: %s" % Dir
+ print("Error: Project directory is missing: %s" % Dir)
sys.exit(-1)
# Build the project.
@@ -78,30 +79,30 @@ def addNewProject(ID, BuildMode):
if os.path.exists(ProjectMapPath):
FileMode = "r+b"
else:
- print "Warning: Creating the Project Map file!!"
+ print("Warning: Creating the Project Map file!!")
FileMode = "w+b"
with open(ProjectMapPath, FileMode) as PMapFile:
if (isExistingProject(PMapFile, ID)):
- print >> sys.stdout, 'Warning: Project with ID \'', ID, \
- '\' already exists.'
- print >> sys.stdout, "Reference output has been regenerated."
+ print('Warning: Project with ID \'', ID, \
+ '\' already exists.', file=sys.stdout)
+ print("Reference output has been regenerated.", file=sys.stdout)
else:
PMapWriter = csv.writer(PMapFile)
PMapWriter.writerow((ID, int(BuildMode)))
- print "The project map is updated: ", ProjectMapPath
+ print("The project map is updated: ", ProjectMapPath)
# TODO: Add an option not to build.
# TODO: Set the path to the Repository directory.
if __name__ == '__main__':
if len(sys.argv) < 2 or sys.argv[1] in ('-h', '--help'):
- print >> sys.stderr, 'Add a new project for testing to the analyzer'\
+ print('Add a new project for testing to the analyzer'\
'\nUsage: ', sys.argv[0],\
'project_ID <mode>\n' \
'mode: 0 for single file project, ' \
'1 for scan_build, ' \
- '2 for single file c++11 project'
+ '2 for single file c++11 project', file=sys.stderr)
sys.exit(-1)
BuildMode = 1
diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py
index ea95ee289e99..1c96cd883818 100644
--- a/utils/analyzer/SATestBuild.py
+++ b/utils/analyzer/SATestBuild.py
@@ -58,7 +58,10 @@ import shutil
import sys
import threading
import time
-import Queue
+try:
+ import queue
+except ImportError:
+ import Queue as queue
###############################################################################
# Helper functions.
@@ -119,7 +122,7 @@ if 'CC' in os.environ:
else:
Clang = SATestUtils.which("clang", os.environ['PATH'])
if not Clang:
- print "Error: cannot find 'clang' in PATH"
+ print("Error: cannot find 'clang' in PATH")
sys.exit(1)
# Number of jobs.
@@ -255,7 +258,14 @@ def applyPatch(Dir, PBuildLogFile):
sys.exit(1)
-def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
+def generateAnalyzerConfig(Args):
+ Out = "serialize-stats=true,stable-report-filename=true"
+ if Args.extra_analyzer_config:
+ Out += "," + Args.extra_analyzer_config
+ return Out
+
+
+def runScanBuild(Args, Dir, SBOutputDir, PBuildLogFile):
"""
Build the project with scan-build by reading in the commands and
prefixing them with the scan-build options.
@@ -277,13 +287,7 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
SBOptions += "-plist-html -o '%s' " % SBOutputDir
SBOptions += "-enable-checker " + AllCheckers + " "
SBOptions += "--keep-empty "
- AnalyzerConfig = [
- ("stable-report-filename", "true"),
- ("serialize-stats", "true"),
- ]
-
- SBOptions += "-analyzer-config '%s' " % (
- ",".join("%s=%s" % (key, value) for (key, value) in AnalyzerConfig))
+ SBOptions += "-analyzer-config '%s' " % generateAnalyzerConfig(Args)
# Always use ccc-analyze to ensure that we can locate the failures
# directory.
@@ -304,6 +308,7 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
SBPrefix = ""
ExtraEnv['OUTPUT'] = SBOutputDir
ExtraEnv['CC'] = Clang
+ ExtraEnv['ANALYZER_CONFIG'] = generateAnalyzerConfig(Args)
continue
# If using 'make', auto imply a -jX argument
@@ -328,7 +333,7 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
sys.exit(1)
-def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
+def runAnalyzePreprocessed(Args, Dir, SBOutputDir, Mode):
"""
Run analysis on a set of preprocessed files.
"""
@@ -349,6 +354,7 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
CmdPrefix += "-analyze -analyzer-output=plist -w "
CmdPrefix += "-analyzer-checker=" + Checkers
CmdPrefix += " -fcxx-exceptions -fblocks "
+ CmdPrefix += " -analyzer-config %s " % generateAnalyzerConfig(Args)
if (Mode == 2):
CmdPrefix += "-std=c++11 "
@@ -379,7 +385,7 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
check_call(Command, cwd=Dir, stderr=LogFile,
stdout=LogFile,
shell=True)
- except CalledProcessError, e:
+ except CalledProcessError as e:
Local.stderr.write("Error: Analyzes of %s failed. "
"See %s for details."
"Error code %d.\n" % (
@@ -407,7 +413,7 @@ def removeLogFile(SBOutputDir):
check_call(RmCommand, shell=True)
-def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
+def buildProject(Args, Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
TBegin = time.time()
BuildLogPath = getBuildLogPath(SBOutputDir)
@@ -431,9 +437,9 @@ def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
if (ProjectBuildMode == 1):
downloadAndPatch(Dir, PBuildLogFile)
runCleanupScript(Dir, PBuildLogFile)
- runScanBuild(Dir, SBOutputDir, PBuildLogFile)
+ runScanBuild(Args, Dir, SBOutputDir, PBuildLogFile)
else:
- runAnalyzePreprocessed(Dir, SBOutputDir, ProjectBuildMode)
+ runAnalyzePreprocessed(Args, Dir, SBOutputDir, ProjectBuildMode)
if IsReferenceBuild:
runCleanupScript(Dir, PBuildLogFile)
@@ -564,8 +570,8 @@ def runCmpResults(Dir, Strictness=0):
NewList.remove(os.path.join(NewDir, LogFolderName))
if len(RefList) != len(NewList):
- print "Mismatch in number of results folders: %s vs %s" % (
- RefList, NewList)
+ print("Mismatch in number of results folders: %s vs %s" % (
+ RefList, NewList))
sys.exit(1)
# There might be more then one folder underneath - one per each scan-build
@@ -577,8 +583,7 @@ def runCmpResults(Dir, Strictness=0):
# Iterate and find the differences.
NumDiffs = 0
- PairList = zip(RefList, NewList)
- for P in PairList:
+ for P in zip(RefList, NewList):
RefDir = P[0]
NewDir = P[1]
@@ -628,12 +633,13 @@ def cleanupReferenceResults(SBOutputDir):
class TestProjectThread(threading.Thread):
- def __init__(self, TasksQueue, ResultsDiffer, FailureFlag):
+ def __init__(self, Args, TasksQueue, ResultsDiffer, FailureFlag):
"""
:param ResultsDiffer: Used to signify that results differ from
the canonical ones.
:param FailureFlag: Used to signify a failure during the run.
"""
+ self.Args = Args
self.TasksQueue = TasksQueue
self.ResultsDiffer = ResultsDiffer
self.FailureFlag = FailureFlag
@@ -649,7 +655,7 @@ class TestProjectThread(threading.Thread):
Logger = logging.getLogger(ProjArgs[0])
Local.stdout = StreamToLogger(Logger, logging.INFO)
Local.stderr = StreamToLogger(Logger, logging.ERROR)
- if not testProject(*ProjArgs):
+ if not testProject(Args, *ProjArgs):
self.ResultsDiffer.set()
self.TasksQueue.task_done()
except:
@@ -657,7 +663,7 @@ class TestProjectThread(threading.Thread):
raise
-def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Strictness=0):
+def testProject(Args, ID, ProjectBuildMode, IsReferenceBuild=False, Strictness=0):
"""
Test a given project.
:return TestsPassed: Whether tests have passed according
@@ -675,7 +681,7 @@ def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Strictness=0):
RelOutputDir = getSBOutputDirName(IsReferenceBuild)
SBOutputDir = os.path.join(Dir, RelOutputDir)
- buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild)
+ buildProject(Args, Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild)
checkBuild(SBOutputDir)
@@ -712,24 +718,24 @@ def validateProjectFile(PMapFile):
"""
for I in iterateOverProjects(PMapFile):
if len(I) != 2:
- print "Error: Rows in the ProjectMapFile should have 2 entries."
+ print("Error: Rows in the ProjectMapFile should have 2 entries.")
raise Exception()
if I[1] not in ('0', '1', '2'):
- print "Error: Second entry in the ProjectMapFile should be 0" \
- " (single file), 1 (project), or 2(single file c++11)."
+ print("Error: Second entry in the ProjectMapFile should be 0" \
+ " (single file), 1 (project), or 2(single file c++11).")
raise Exception()
-def singleThreadedTestAll(ProjectsToTest):
+def singleThreadedTestAll(Args, ProjectsToTest):
"""
Run all projects.
:return: whether tests have passed.
"""
Success = True
for ProjArgs in ProjectsToTest:
- Success &= testProject(*ProjArgs)
+ Success &= testProject(Args, *ProjArgs)
return Success
-def multiThreadedTestAll(ProjectsToTest, Jobs):
+def multiThreadedTestAll(Args, ProjectsToTest, Jobs):
"""
Run each project in a separate thread.
@@ -738,7 +744,7 @@ def multiThreadedTestAll(ProjectsToTest, Jobs):
:return: whether tests have passed.
"""
- TasksQueue = Queue.Queue()
+ TasksQueue = queue.Queue()
for ProjArgs in ProjectsToTest:
TasksQueue.put(ProjArgs)
@@ -747,7 +753,7 @@ def multiThreadedTestAll(ProjectsToTest, Jobs):
FailureFlag = threading.Event()
for i in range(Jobs):
- T = TestProjectThread(TasksQueue, ResultsDiffer, FailureFlag)
+ T = TestProjectThread(Args, TasksQueue, ResultsDiffer, FailureFlag)
T.start()
# Required to handle Ctrl-C gracefully.
@@ -772,9 +778,9 @@ def testAll(Args):
Args.regenerate,
Args.strictness))
if Args.jobs <= 1:
- return singleThreadedTestAll(ProjectsToTest)
+ return singleThreadedTestAll(Args, ProjectsToTest)
else:
- return multiThreadedTestAll(ProjectsToTest, Args.jobs)
+ return multiThreadedTestAll(Args, ProjectsToTest, Args.jobs)
if __name__ == '__main__':
@@ -791,9 +797,13 @@ if __name__ == '__main__':
Parser.add_argument('-j', '--jobs', dest='jobs', type=int,
default=0,
help='Number of projects to test concurrently')
+ Parser.add_argument('--extra-analyzer-config', dest='extra_analyzer_config',
+ type=str,
+ default="",
+ help="Arguments passed to to -analyzer-config")
Args = Parser.parse_args()
TestsPassed = testAll(Args)
if not TestsPassed:
- print "ERROR: Tests failed."
+ print("ERROR: Tests failed.")
sys.exit(42)
diff --git a/utils/analyzer/SATestUpdateDiffs.py b/utils/analyzer/SATestUpdateDiffs.py
index 92bbd83172ef..ea3c08cc210c 100755
--- a/utils/analyzer/SATestUpdateDiffs.py
+++ b/utils/analyzer/SATestUpdateDiffs.py
@@ -3,6 +3,7 @@
"""
Update reference results for static analyzer.
"""
+from __future__ import absolute_import, division, print_function
import SATestBuild
@@ -10,12 +11,12 @@ from subprocess import check_call
import os
import sys
-Verbose = 1
+Verbose = 0
def runCmd(Command, **kwargs):
if Verbose:
- print "Executing %s" % Command
+ print("Executing %s" % Command)
check_call(Command, shell=True, **kwargs)
@@ -30,8 +31,8 @@ def updateReferenceResults(ProjName, ProjBuildMode):
SATestBuild.getSBOutputDirName(IsReferenceBuild=False))
if not os.path.exists(CreatedResultsPath):
- print >> sys.stderr, "New results not found, was SATestBuild.py "\
- "previously run?"
+ print("New results not found, was SATestBuild.py "\
+ "previously run?", file=sys.stderr)
sys.exit(1)
BuildLogPath = SATestBuild.getBuildLogPath(RefResultsPath)
@@ -62,9 +63,9 @@ def updateReferenceResults(ProjName, ProjBuildMode):
def main(argv):
if len(argv) == 2 and argv[1] in ('-h', '--help'):
- print >> sys.stderr, "Update static analyzer reference results based "\
+ print("Update static analyzer reference results based "\
"\non the previous run of SATestBuild.py.\n"\
- "\nN.B.: Assumes that SATestBuild.py was just run"
+ "\nN.B.: Assumes that SATestBuild.py was just run", file=sys.stderr)
sys.exit(1)
with SATestBuild.projectFileHandler() as f:
diff --git a/utils/analyzer/SumTimerInfo.py b/utils/analyzer/SumTimerInfo.py
index 50e1cb854f4e..36e519adbf71 100644
--- a/utils/analyzer/SumTimerInfo.py
+++ b/utils/analyzer/SumTimerInfo.py
@@ -6,13 +6,14 @@ Script to Summarize statistics in the scan-build output.
Statistics are enabled by passing '-internal-stats' option to scan-build
(or '-analyzer-stats' to the analyzer).
"""
+from __future__ import absolute_import, division, print_function
import sys
if __name__ == '__main__':
if len(sys.argv) < 2:
- print >> sys.stderr, 'Usage: ', sys.argv[0],\
- 'scan_build_output_file'
+ print('Usage: ', sys.argv[0],\
+ 'scan_build_output_file', file=sys.stderr)
sys.exit(-1)
f = open(sys.argv[1], 'r')
@@ -65,15 +66,15 @@ if __name__ == '__main__':
s = line.split()
TotalTime = TotalTime + float(s[6])
- print "TU Count %d" % (Count)
- print "Time %f" % (Time)
- print "Warnings %d" % (Warnings)
- print "Functions Analyzed %d" % (FunctionsAnalyzed)
- print "Reachable Blocks %d" % (ReachableBlocks)
- print "Reached Max Steps %d" % (ReachedMaxSteps)
- print "Number of Steps %d" % (NumSteps)
- print "Number of Inlined calls %d (bifurcated %d)" % (
- NumInlinedCallSites, NumBifurcatedCallSites)
- print "MaxTime %f" % (MaxTime)
- print "TotalTime %f" % (TotalTime)
- print "Max CFG Size %d" % (MaxCFGSize)
+ print("TU Count %d" % (Count))
+ print("Time %f" % (Time))
+ print("Warnings %d" % (Warnings))
+ print("Functions Analyzed %d" % (FunctionsAnalyzed))
+ print("Reachable Blocks %d" % (ReachableBlocks))
+ print("Reached Max Steps %d" % (ReachedMaxSteps))
+ print("Number of Steps %d" % (NumSteps))
+ print("Number of Inlined calls %d (bifurcated %d)" % (
+ NumInlinedCallSites, NumBifurcatedCallSites))
+ print("MaxTime %f" % (MaxTime))
+ print("TotalTime %f" % (TotalTime))
+ print("Max CFG Size %d" % (MaxCFGSize))
diff --git a/utils/analyzer/ubiviz b/utils/analyzer/ubiviz
deleted file mode 100755
index 137e130fe74c..000000000000
--- a/utils/analyzer/ubiviz
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===--------------------------------------------------------------------===##
-#
-# This script reads visualization data emitted by the static analyzer for
-# display in Ubigraph.
-#
-##===--------------------------------------------------------------------===##
-
-import xmlrpclib
-import sys
-
-
-def Error(message):
- print >> sys.stderr, 'ubiviz: ' + message
- sys.exit(1)
-
-
-def StreamData(filename):
- file = open(filename)
- for ln in file:
- yield eval(ln)
- file.close()
-
-
-def Display(G, data):
- action = data[0]
- if action == 'vertex':
- vertex = data[1]
- G.new_vertex_w_id(vertex)
- for attribute in data[2:]:
- G.set_vertex_attribute(vertex, attribute[0], attribute[1])
- elif action == 'edge':
- src = data[1]
- dst = data[2]
- edge = G.new_edge(src, dst)
- for attribute in data[3:]:
- G.set_edge_attribute(edge, attribute[0], attribute[1])
- elif action == "vertex_style":
- style_id = data[1]
- parent_id = data[2]
- G.new_vertex_style_w_id(style_id, parent_id)
- for attribute in data[3:]:
- G.set_vertex_style_attribute(style_id, attribute[0], attribute[1])
- elif action == "vertex_style_attribute":
- style_id = data[1]
- for attribute in data[2:]:
- G.set_vertex_style_attribute(style_id, attribute[0], attribute[1])
- elif action == "change_vertex_style":
- vertex_id = data[1]
- style_id = data[2]
- G.change_vertex_style(vertex_id, style_id)
-
-
-def main(args):
- if len(args) == 0:
- Error('no input files')
-
- server = xmlrpclib.Server('http://127.0.0.1:20738/RPC2')
- G = server.ubigraph
-
- for arg in args:
- G.clear()
- for x in StreamData(arg):
- Display(G, x)
-
- sys.exit(0)
-
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/utils/check_cfc/check_cfc.py b/utils/check_cfc/check_cfc.py
index 7a739f46e308..311f502f800b 100755
--- a/utils/check_cfc/check_cfc.py
+++ b/utils/check_cfc/check_cfc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python
"""Check CFC - Check Compile Flow Consistency
@@ -47,7 +47,7 @@ To add a new check:
subclass.
"""
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import imp
import os
@@ -56,7 +56,10 @@ import shutil
import subprocess
import sys
import tempfile
-import ConfigParser
+try:
+ import configparser
+except ImportError:
+ import ConfigParser as configparser
import io
import obj_diff
@@ -95,8 +98,8 @@ def remove_dir_from_path(path_var, directory):
PATH"""
pathlist = path_var.split(os.pathsep)
norm_directory = os.path.normpath(os.path.normcase(directory))
- pathlist = filter(lambda x: os.path.normpath(
- os.path.normcase(x)) != norm_directory, pathlist)
+ pathlist = [x for x in pathlist if os.path.normpath(
+ os.path.normcase(x)) != norm_directory]
return os.pathsep.join(pathlist)
def path_without_wrapper():
@@ -318,7 +321,7 @@ if __name__ == '__main__':
for c in checks:
default_config += "{} = false\n".format(c)
- config = ConfigParser.RawConfigParser()
+ config = configparser.RawConfigParser()
config.readfp(io.BytesIO(default_config))
scriptdir = get_main_dir()
config_path = os.path.join(scriptdir, 'check_cfc.cfg')
diff --git a/utils/check_cfc/obj_diff.py b/utils/check_cfc/obj_diff.py
index cc4c2a97d5e5..a0951c5bcdee 100755
--- a/utils/check_cfc/obj_diff.py
+++ b/utils/check_cfc/obj_diff.py
@@ -1,6 +1,6 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import argparse
import difflib
@@ -25,7 +25,7 @@ def disassemble(objfile):
if p.returncode or err:
print("Disassemble failed: {}".format(objfile))
sys.exit(1)
- return filter(keep_line, out.split(os.linesep))
+ return [line for line in out.split(os.linesep) if keep_line(line)]
def dump_debug(objfile):
"""Dump all of the debug info from a file."""
@@ -34,7 +34,7 @@ def dump_debug(objfile):
if p.returncode or err:
print("Dump debug failed: {}".format(objfile))
sys.exit(1)
- return filter(keep_line, out.split(os.linesep))
+ return [line for line in out.split(os.linesep) if keep_line(line)]
def first_diff(a, b, fromfile, tofile):
"""Returns the first few lines of a difference, if there is one. Python
diff --git a/utils/check_cfc/setup.py b/utils/check_cfc/setup.py
index b5fc473639ef..64f07d5dcc52 100644
--- a/utils/check_cfc/setup.py
+++ b/utils/check_cfc/setup.py
@@ -1,6 +1,7 @@
"""For use on Windows. Run with:
python.exe setup.py py2exe
"""
+from __future__ import absolute_import, division, print_function
from distutils.core import setup
try:
import py2exe
@@ -8,10 +9,10 @@ except ImportError:
import platform
import sys
if platform.system() == 'Windows':
- print "Could not find py2exe. Please install then run setup.py py2exe."
+ print("Could not find py2exe. Please install then run setup.py py2exe.")
raise
else:
- print "setup.py only required on Windows."
+ print("setup.py only required on Windows.")
sys.exit(1)
setup(
diff --git a/utils/check_cfc/test_check_cfc.py b/utils/check_cfc/test_check_cfc.py
index e304ff59277d..0808252a2c60 100755
--- a/utils/check_cfc/test_check_cfc.py
+++ b/utils/check_cfc/test_check_cfc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python
"""Test internal functions within check_cfc.py."""
diff --git a/utils/clangdiag.py b/utils/clangdiag.py
index 9a80e2696d52..6baf65a8761c 100755
--- a/utils/clangdiag.py
+++ b/utils/clangdiag.py
@@ -9,9 +9,9 @@
# (lldb) command script import /path/to/clandiag.py
#----------------------------------------------------------------------
+from __future__ import absolute_import, division, print_function
import lldb
import argparse
-import commands
import shlex
import os
import re
@@ -189,4 +189,4 @@ def __lldb_init_module(debugger, dict):
# Add any commands contained in this module to LLDB
debugger.HandleCommand(
'command script add -f clangdiag.the_diag_command clangdiag')
- print 'The "clangdiag" command has been installed, type "help clangdiag" or "clangdiag --help" for detailed help.'
+ print('The "clangdiag" command has been installed, type "help clangdiag" or "clangdiag --help" for detailed help.')
diff --git a/utils/hmaptool/hmaptool b/utils/hmaptool/hmaptool
index 2b1ca7436c3f..58baab2f7746 100755
--- a/utils/hmaptool/hmaptool
+++ b/utils/hmaptool/hmaptool
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import json
import optparse
diff --git a/utils/modfuzz.py b/utils/modfuzz.py
index a6aa1f1a257a..61ca3272aca5 100644
--- a/utils/modfuzz.py
+++ b/utils/modfuzz.py
@@ -4,6 +4,7 @@
# 1) Update the 'decls' list below with your fuzzing configuration.
# 2) Run with the clang binary as the command-line argument.
+from __future__ import absolute_import, division, print_function
import random
import subprocess
import sys
@@ -12,7 +13,7 @@ import os
clang = sys.argv[1]
none_opts = 0.3
-class Decl:
+class Decl(object):
def __init__(self, text, depends=[], provides=[], conflicts=[]):
self.text = text
self.depends = depends
@@ -39,7 +40,7 @@ decls = [
Decl('X %(name)s;\n', depends=['X']),
]
-class FS:
+class FS(object):
def __init__(self):
self.fs = {}
self.prevfs = {}
@@ -62,7 +63,7 @@ class FS:
fs = FS()
-class CodeModel:
+class CodeModel(object):
def __init__(self):
self.source = ''
self.modules = {}
@@ -97,7 +98,7 @@ def generate():
if not model.fails():
return
except KeyboardInterrupt:
- print
+ print()
return True
sys.stdout.write('\nReducing:\n')
@@ -106,7 +107,7 @@ def generate():
try:
while True:
assert m, 'got a failure with no steps; broken clang binary?'
- i = random.choice(range(len(m)))
+ i = random.choice(list(range(len(m))))
x = m[0:i] + m[i+1:]
m2 = CodeModel()
for d in x:
diff --git a/utils/perf-training/perf-helper.py b/utils/perf-training/perf-helper.py
index 30b9caeffd58..65afbb6ed572 100644
--- a/utils/perf-training/perf-helper.py
+++ b/utils/perf-training/perf-helper.py
@@ -7,7 +7,7 @@
#
#===------------------------------------------------------------------------===#
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function
import sys
import os
@@ -114,7 +114,7 @@ def get_cc1_command_for_args(cmd, env):
# Find the cc1 command used by the compiler. To do this we execute the
# compiler with '-###' to figure out what it wants to do.
cmd = cmd + ['-###']
- cc_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, env=env).strip()
+ cc_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, env=env, universal_newlines=True).strip()
cc_commands = []
for ln in cc_output.split('\n'):
# Filter out known garbage.
@@ -295,8 +295,8 @@ def form_by_frequency(symbol_lists):
for a in symbols:
counts[a] = counts.get(a,0) + 1
- by_count = counts.items()
- by_count.sort(key = lambda (_,n): -n)
+ by_count = list(counts.items())
+ by_count.sort(key = lambda __n: -__n[1])
return [s for s,n in by_count]
def form_by_random(symbol_lists):
@@ -333,14 +333,14 @@ def genOrderFile(args):
help="write a list of the unordered symbols to PATH (requires --binary)",
default=None, metavar="PATH")
parser.add_argument("--method", dest="method",
- help="order file generation method to use", choices=methods.keys(),
+ help="order file generation method to use", choices=list(methods.keys()),
default='call_order')
opts = parser.parse_args(args)
# If the user gave us a binary, get all the symbols in the binary by
# snarfing 'nm' output.
if opts.binary_path is not None:
- output = subprocess.check_output(['nm', '-P', opts.binary_path])
+ output = subprocess.check_output(['nm', '-P', opts.binary_path], universal_newlines=True)
lines = output.split("\n")
all_symbols = [ln.split(' ',1)[0]
for ln in lines
diff --git a/utils/token-delta.py b/utils/token-delta.py
index 327fa9221f05..62b4eb3c776c 100755
--- a/utils/token-delta.py
+++ b/utils/token-delta.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+from __future__ import absolute_import, division, print_function
import os
import re
import subprocess
@@ -37,7 +38,7 @@ class DeltaAlgorithm(object):
# O(N^2) case unless user requests it.
if not force:
if not self.getTestResult(changes):
- raise ValueError,'Initial test passed to delta fails.'
+ raise ValueError('Initial test passed to delta fails.')
# Check empty set first to quickly find poor test functions.
if self.getTestResult(set()):
@@ -94,7 +95,7 @@ class DeltaAlgorithm(object):
###
-class Token:
+class Token(object):
def __init__(self, type, data, flags, file, line, column):
self.type = type
self.data = data
@@ -165,7 +166,7 @@ class TMBDDelta(DeltaAlgorithm):
byFile = self.writeFiles(changes, self.tempFiles)
if self.log:
- print >>sys.stderr, 'TEST - ',
+ print('TEST - ', end=' ', file=sys.stderr)
if self.log > 1:
for i,(file,_) in enumerate(self.tokenLists):
indices = byFile[i]
@@ -184,8 +185,8 @@ class TMBDDelta(DeltaAlgorithm):
sys.stderr.write(str(byFile[i][-1]))
sys.stderr.write('] ')
else:
- print >>sys.stderr, ', '.join(['%s:%d tokens' % (file, len(byFile[i]))
- for i,(file,_) in enumerate(self.tokenLists)]),
+ print(', '.join(['%s:%d tokens' % (file, len(byFile[i]))
+ for i,(file,_) in enumerate(self.tokenLists)]), end=' ', file=sys.stderr)
p = subprocess.Popen([self.testProgram] + self.tempFiles)
res = p.wait() == 0
@@ -194,10 +195,10 @@ class TMBDDelta(DeltaAlgorithm):
self.writeFiles(changes, self.targetFiles)
if self.log:
- print >>sys.stderr, '=> %s' % res
+ print('=> %s' % res, file=sys.stderr)
else:
if res:
- print '\nSUCCESS (%d tokens)' % len(changes)
+ print('\nSUCCESS (%d tokens)' % len(changes))
else:
sys.stderr.write('.')
@@ -209,7 +210,7 @@ class TMBDDelta(DeltaAlgorithm):
for j in range(len(tokens))])
self.writeFiles(res, self.targetFiles)
if not self.log:
- print >>sys.stderr
+ print(file=sys.stderr)
return res
def tokenBasedMultiDelta(program, files, log):
@@ -218,15 +219,15 @@ def tokenBasedMultiDelta(program, files, log):
for file in files]
numTokens = sum([len(tokens) for _,tokens in tokenLists])
- print "Delta on %s with %d tokens." % (', '.join(files), numTokens)
+ print("Delta on %s with %d tokens." % (', '.join(files), numTokens))
tbmd = TMBDDelta(program, tokenLists, log)
res = tbmd.run()
- print "Finished %s with %d tokens (in %d tests)." % (', '.join(tbmd.targetFiles),
+ print("Finished %s with %d tokens (in %d tests)." % (', '.join(tbmd.targetFiles),
len(res),
- tbmd.numTests)
+ tbmd.numTests))
def main():
from optparse import OptionParser, OptionGroup
@@ -247,5 +248,5 @@ if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
- print >>sys.stderr,'Interrupted.'
+ print('Interrupted.', file=sys.stderr)
os._exit(1) # Avoid freeing our giant cache.
diff --git a/www/analyzer/alpha_checks.html b/www/analyzer/alpha_checks.html
index 4a250dcb31e1..beab87b6b36a 100644
--- a/www/analyzer/alpha_checks.html
+++ b/www/analyzer/alpha_checks.html
@@ -27,6 +27,7 @@ Patches welcome!
<li><a href="#clone_alpha_checkers">Clone Alpha Checkers</a></li>
<li><a href="#core_alpha_checkers">Core Alpha Checkers</a></li>
<li><a href="#cplusplus_alpha_checkers">C++ Alpha Checkers</a></li>
+<li><a href="#llvm_alpha_checkers">LLVM Checkers</a></li>
<li><a href="#valist_alpha_checkers">Variable Argument Alpha Checkers</a></li>
<li><a href="#deadcode_alpha_checkers">Dead Code Alpha Checkers</a></li>
<li><a href="#osx_alpha_checkers">OS X Alpha Checkers</a></li>
@@ -42,10 +43,10 @@ Patches welcome!
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.clone.CloneChecker"><div class="namedescr expandable"><span class="name">
alpha.clone.CloneChecker</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
-Reports similar pieces of code.</div></div></td>
+Reports similar pieces of code.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void log();
@@ -73,10 +74,10 @@ int maxClone(int x, int y) { // similar code here
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.BoolAssignment"><div class="namedescr expandable"><span class="name">
alpha.core.BoolAssignment</span><span class="lang">
(ObjC)</span><div class="descr">
-Warn about assigning non-{0,1} values to boolean variables.</div></div></td>
+Warn about assigning non-{0,1} values to boolean variables.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -85,11 +86,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.CallAndMessageUnInitRefArg"><div class="namedescr expandable"><span class="name">
alpha.core.CallAndMessageUnInitRefArg</span><span class="lang">
(C, C++)</span><div class="descr">
-Check for uninitialized arguments in function calls and Objective-C
-message expressions.</div></div></td>
+Check for uninitialized arguments in function calls and Objective-C
+message expressions.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(void) {
@@ -107,13 +108,14 @@ void test(void) {
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+
+<tr><td><a id="alpha.core.CastSize"><div class="namedescr expandable"><span class="name">
alpha.core.CastSize</span><span class="lang">
(C)</span><div class="descr">
-Check when casting a malloc'ed type T, whether the size is a multiple of the
+Check when casting a malloc'ed type T, whether the size is a multiple of the
size of T (Works only with <span class="name">unix.Malloc</span>
-or <span class="name">alpha.unix.MallocWithAnnotations</span>
-checks enabled).</div></div></td>
+or <span class="name">alpha.unix.MallocWithAnnotations</span>
+checks enabled).</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -122,10 +124,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.CastToStruct"><div class="namedescr expandable"><span class="name">
alpha.core.CastToStruct</span><span class="lang">
(C, C++)</span><div class="descr">
-Check for cast from non-struct pointer to struct pointer.</div></div></td>
+Check for cast from non-struct pointer to struct pointer.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
@@ -145,10 +147,10 @@ void test(int *p) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.Conversion"><div class="namedescr expandable"><span class="name">
alpha.core.Conversion</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
-Loss of sign or precision in implicit conversions</div></div></td>
+Loss of sign or precision in implicit conversions</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(unsigned U, signed S) {
@@ -170,26 +172,26 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.DynamicTypeChecker"><div class="namedescr expandable"><span class="name">
alpha.core.DynamicTypeChecker</span><span class="lang">
(ObjC)</span><div class="descr">
-Check for cases where the dynamic and the static type of an
-object are unrelated.</div></div></td>
+Check for cases where the dynamic and the static type of an
+object are unrelated.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
id date = [NSDate date];
-// Warning: Object has a dynamic type 'NSDate *' which is
+// Warning: Object has a dynamic type 'NSDate *' which is
// incompatible with static type 'NSNumber *'"
NSNumber *number = date;
[number doubleValue];
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.FixedAddr"><div class="namedescr expandable"><span class="name">
alpha.core.FixedAddr</span><span class="lang">
(C)</span><div class="descr">
-Check for assignment of a fixed address to a pointer.</div></div></td>
+Check for assignment of a fixed address to a pointer.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -199,10 +201,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.IdenticalExpr"><div class="namedescr expandable"><span class="name">
alpha.core.IdenticalExpr</span><span class="lang">
(C, C++)</span><div class="descr">
-Warn about suspicious uses of identical expressions.</div></div></td>
+Warn about suspicious uses of identical expressions.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
@@ -230,11 +232,11 @@ void test(bool b) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.PointerArithm"><div class="namedescr expandable"><span class="name">
alpha.core.PointerArithm</span><span class="lang">
(C)</span><div class="descr">
-Check for pointer arithmetic on locations other than array
-elements.</div></div></td>
+Check for pointer arithmetic on locations other than array
+elements.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -245,11 +247,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.PointerSub"><div class="namedescr expandable"><span class="name">
alpha.core.PointerSub</span><span class="lang">
(C)</span><div class="descr">
-Check for pointer subtractions on two pointers pointing to different memory
-chunks.</div></div></td>
+Check for pointer subtractions on two pointers pointing to different memory
+chunks.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -259,36 +261,64 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.SizeofPtr"><div class="namedescr expandable"><span class="name">
alpha.core.SizeofPtr</span><span class="lang">
(C)</span><div class="descr">
-Warn about unintended use of <code>sizeof()</code> on pointer
-expressions.</div></div></td>
+Warn about unintended use of <code>sizeof()</code> on pointer
+expressions.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
struct s {};
int test(struct s *p) {
- return sizeof(p);
+ return sizeof(p);
// warn: sizeof(ptr) can produce an unexpected result
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.core.StackAddressAsyncEscape"><div class="namedescr expandable"><span class="name">
+alpha.core.StackAddressAsyncEscape</span><span class="lang">
+(C)</span><div class="descr">
+Check that addresses to stack memory do not escape the function that involves
+<code>dispatch_after</code> or <code>dispatch_async</code>. This checker is
+a part of core.StackAddressEscape, but is
+<a href=https://reviews.llvm.org/D41042>temporarily disabled</a> until some
+false positives are fixed.</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+dispatch_block_t test_block_inside_block_async_leak() {
+ int x = 123;
+ void (^inner)(void) = ^void(void) {
+ int y = x;
+ ++y;
+ };
+ void (^outer)(void) = ^void(void) {
+ int z = x;
+ ++z;
+ inner();
+ };
+ return outer; // warn: address of stack-allocated block is captured by a
+ // returned block
+}
+</pre></div></div></td></tr>
+
+
+<tr><td><a id="alpha.core.TestAfterDivZero"><div class="namedescr expandable"><span class="name">
alpha.core.TestAfterDivZero</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
-Check for division by variable that is later compared against 0.
+Check for division by variable that is later compared against 0.
Either the comparison is useless or there is division by zero.
-</div></div></td>
+</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(int x) {
var = 77 / x;
- if (x == 0) { } // warn
+ if (x == 0) { } // warn
}
</pre></div></div></td></tr>
+
</tbody></table>
<!-- =========================== cplusplus alpha =========================== -->
@@ -296,104 +326,241 @@ void test(int x) {
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
-
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
-alpha.cplusplus.VirtualCall</span><span class="lang">
+
+
+<tr><td><a id="alpha.cplusplus.DeleteWithNonVirtualDtor"><div class="namedescr expandable"><span class="name">
+alpha.cplusplus.DeleteWithNonVirtualDtor</span><span class="lang">
(C++)</span><div class="descr">
-Check virtual member function calls during construction or
-destruction.</div></div></td>
+Reports destructions of polymorphic objects with a non-virtual destructor in
+their base class
+</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
-class A {
-public:
- A() {
- f(); // warn
- }
- virtual void f();
+NonVirtual *create() {
+ NonVirtual *x = new NVDerived(); // note: conversion from derived to base
+ // happened here
+ return x;
+}
+
+void sink(NonVirtual *x) {
+ delete x; // warn: destruction of a polymorphic object with no virtual
+ // destructor
+}
+</pre></div></div></td></tr>
+
+<tr><td><a id="alpha.cplusplus.EnumCastOutOfRange"><div class="namedescr expandable"><span class="name">
+alpha.cplusplus.EnumCastOutOfRange</span><span class="lang">
+(C++)</span><div class="descr">
+ Check for integer to enumeration casts that could result in undefined values.
+</div></div></a></td>
+ <td><div class="exampleContainer expandable">
+ <div class="example"><pre>
+enum TestEnum {
+ A = 0
};
-</pre></div><div class="separator"></div>
+
+void foo() {
+ TestEnum t = static_cast<TestEnum>(-1);
+ // warn: the value provided to the cast expression is not in
+ the valid range of values for the enum
+}
+</pre></div></div></td></tr>
+
+
+<tr><td><a id="alpha.cplusplus.InvalidatedIterator"><div class="namedescr expandable"><span class="name">
+alpha.cplusplus.InvalidatedIterator</span><span class="lang">
+(C++)</span><div class="descr">
+Check for use of invalidated iterators.
+</div></div></a></td>
+<td><div class="exampleContainer expandable">
<div class="example"><pre>
-class A {
-public:
- ~A() {
- this-&gt;f(); // warn
- }
- virtual void f();
-};
+void bad_copy_assign_operator_list1(std::list<int> &L1,
+ const std::list<int> &L2) {
+ auto i0 = L1.cbegin();
+ L1 = L2;
+ *i0; // warn: invalidated iterator accessed
+}
</pre></div></div></td></tr>
-</tbody></table>
+<tr><td><a id="alpha.cplusplus.IteratorRange"><div class="namedescr expandable"><span class="name">
+alpha.cplusplus.IteratorRange</span><span class="lang">
+(C++)</span><div class="descr">
+Check for iterators used outside their valid ranges.
+</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+void simple_bad_end(const std::vector<int> &v) {
+ auto i = v.end();
+ *i; // warn: iterator accessed outside of its range
+}
+</pre></div></div></td></tr>
-<!-- =============================== va_list =============================== -->
-<h3 id="valist_alpha_checkers">Variable Argument Alpha Checkers</h3>
-<table class="checkers">
-<colgroup><col class="namedescr"><col class="example"></colgroup>
-<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
+<tr><td><a id="alpha.cplusplus.MismatchedIterator"><div class="namedescr expandable"><span class="name">
+alpha.cplusplus.MismatchedIterator</span><span class="lang">
+(C++)</span><div class="descr">
+Check for use of iterators of different containers where iterators of the same
+container are expected.
+</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+void bad_insert3(std::vector<int> &v1, std::vector<int> &v2) {
+ v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // warn: container accessed
+ // using foreign
+ // iterator argument
+ v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // warn: iterators of
+ // different containers
+ // used where the same
+ // container is
+ // expected
+ v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // warn: iterators of
+ // different containers
+ // used where the same
+ // container is
+ // expected
+}
+</pre></div></div></td></tr>
-<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
-alpha.valist.CopyToSelf</span><span class="lang">
-(C)</span><div class="descr">
-Calls to the <code>va_copy</code> macro should not copy onto itself.</div></div></td>
+
+<tr><td><a id="alpha.cplusplus.Move"><div class="namedescr expandable"><span class="name">
+alpha.cplusplus.Move</span><span class="lang">
+(C++)</span><div class="descr">
+Method calls on a moved-from object and copying a moved-from object will be
+reported.
+</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
-#include &lt;stdarg.h&gt;
+struct A {
+ void foo() {}
+};
-void test(int x, ...) {
- va_list args;
- va_start(args, x);
- va_copy(args, args); // warn
- va_end(args);
+void f() {
+ A a;
+ A b = std::move(a); // note: 'a' became 'moved-from' here
+ a.foo(); // warn: method call on a 'moved-from' object 'a'
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
-alpha.valist.Uninitialized</span><span class="lang">
-(C)</span><div class="descr">
-Calls to the <code>va_arg</code>, <code>va_copy</code>, or
-<code>va_end</code> macro must happen after calling <code>va_start</code> and
-before calling <code>va_end</code>.</div></div></td>
+
+<tr><td><a id="alpha.cplusplus.UninitializedObject"><div class="namedescr expandable"><span class="name">
+alpha.cplusplus.UninitializedObject</span><span class="lang">
+(C++)</span><div class="descr">
+This checker reports uninitialized fields in objects created after a constructor
+call. It doesn't only find direct uninitialized fields, but rather makes a deep
+inspection of the object, analyzing all of it's fields subfields. <br>
+The checker regards inherited fields as direct fields, so one will recieve
+warnings for uninitialized inherited data members as well. <br>
+<br>
+It has several options:
+<ul>
+ <li>
+ "<code>Pedantic</code>" (boolean). If its not set or is set to false, the
+ checker won't emit warnings for objects that don't have at least one
+ initialized field. This may be set with <br>
+ <code>-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true</code>.
+ </li>
+ <li>
+ "<code>NotesAsWarnings</code>" (boolean). If set to true, the checker will
+ emit a warning for each uninitalized field, as opposed to emitting one
+ warning per constructor call, and listing the uninitialized fields that
+ belongs to it in notes. Defaults to false. <br>
+ <code>-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true</code>.
+ </li>
+ <li>
+ "<code>CheckPointeeInitialization</code>" (boolean). If set to false, the
+ checker will not analyze the pointee of pointer/reference fields, and will
+ only check whether the object itself is initialized. Defaults to false. <br>
+ <code>-analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true</code>.
+ </li>
+ <li>
+ "<code>IgnoreRecordsWithField</code>" (string). If supplied, the checker
+ will not analyze structures that have a field with a name or type name that
+ matches the given pattern. Defaults to <code>""</code>.
+
+ <code>-analyzer-config alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"</code>.
+ </li>
+</ul></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
-#include &lt;stdarg.h&gt;
+// With Pedantic and CheckPointeeInitialization set to true
+
+struct A {
+ struct B {
+ int x; // note: uninitialized field 'this->b.x'
+ // note: uninitialized field 'this->bptr->x'
+ int y; // note: uninitialized field 'this->b.y'
+ // note: uninitialized field 'this->bptr->y'
+ };
+ int *iptr; // note: uninitialized pointer 'this->iptr'
+ B b;
+ B *bptr;
+ char *cptr; // note: uninitialized pointee 'this->cptr'
+
+ A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
+};
-void test(int x, ...) {
- va_list args;
- int y = va_arg(args, int); // warn
+void f() {
+ A::B b;
+ char c;
+ A a(&b, &c); // warning: 6 uninitialized fields
+ // after the constructor call
}
-</pre></div>
+</pre></div><div class="separator"></div>
<div class="example"><pre>
-#include &lt;stdarg.h&gt;
+// With Pedantic set to false and
+// CheckPointeeInitialization set to true
+// (every field is uninitialized)
+
+struct A {
+ struct B {
+ int x;
+ int y;
+ };
+ int *iptr;
+ B b;
+ B *bptr;
+ char *cptr;
+
+ A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
+};
-void test(int x, ...) {
- va_list args;
- va_start(args, x);
- va_end(args);
- int z = va_arg(args, int); // warn
+void f() {
+ A::B b;
+ char c;
+ A a(&b, &c); // no warning
}
-</pre></div></div></td></tr>
-
-<tr><td><div class="namedescr expandable"><span class="name">
-alpha.valist.Unterminated</span><span class="lang">
-(C)</span><div class="descr">
-Every <code>va_start</code> must be matched by a <code>va_end</code>. A va_list
-can only be ended once.</div></div></td>
-<td><div class="exampleContainer expandable">
+</pre></div><div class="separator"></div>
<div class="example"><pre>
-#include &lt;stdarg.h&gt;
+// With Pedantic and CheckPointeeInitialization set to false
+// (pointees are regarded as initialized)
+
+struct A {
+ struct B {
+ int x; // note: uninitialized field 'this->b.x'
+ int y; // note: uninitialized field 'this->b.y'
+ };
+ int *iptr; // note: uninitialized pointer 'this->iptr'
+ B b;
+ B *bptr;
+ char *cptr;
+
+ A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
+};
-void test(int x, ...) {
- va_list args;
- va_start(args, x);
- int y = x + va_arg(args, int);
-} // warn: missing va_end
+void f() {
+ A::B b;
+ char c;
+ A a(&b, &c); // warning: 3 uninitialized fields
+ // after the constructor call
+}
</pre></div></div></td></tr>
+
</tbody></table>
+
<!-- =========================== dead code alpha =========================== -->
<h3 id="deadcode_alpha_checkers">Dead Code Alpha Checkers</h3>
<table class="checkers">
@@ -401,10 +568,10 @@ void test(int x, ...) {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.deadcode.UnreachableCode"><div class="namedescr expandable"><span class="name">
alpha.deadcode.UnreachableCode</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
-Check unreachable code.</div></div></td>
+Check unreachable code.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
@@ -435,6 +602,31 @@ void test(id x) {
</pre></div></div></td></tr>
</tbody></table>
+<!-- =========================== llvm alpha =========================== -->
+<h3 id="llvm_alpha_checkers">LLVM Checkers</h3>
+<table class="checkers">
+<colgroup><col class="namedescr"><col class="example"></colgroup>
+<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
+
+<tbody>
+<tr><td><a id="alpha.llvm.Conventions"><div class="namedescr expandable"><span class="name">
+alpha.llvm.Conventions</span><span class="lang">
+(C)</span><div class="descr">
+Check code for LLVM codebase conventions:
+<ul>
+ <li>A <code>StringRef</code> should not be bound to a temporary std::string
+ whose lifetime is shorter than the <code>StringRef</code>'s.</li>
+ <li>Clang AST nodes should not have fields that can allocate memory.</li>
+</ul>
+</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+<!-- TODO: Add examples, as currently it's hard to get this checker working. -->
+</pre></div></div></td></tr>
+
+</tbody></table>
+
+
<!-- ============================== OS X alpha ============================== -->
<h3 id="osx_alpha_checkers">OS X Alpha Checkers</h3>
<table class="checkers">
@@ -442,11 +634,11 @@ void test(id x) {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.osx.cocoa.DirectIvarAssignment"><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.DirectIvarAssignment</span><span class="lang">
(ObjC)</span><div class="descr">
-Check that Objective C properties follow the following rule: the property
-should be set with the setter, not though a direct assignment.</div></div></td>
+Check that Objective C properties follow the following rule: the property
+should be set with the setter, not though a direct assignment.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyClass : NSObject {}
@@ -462,11 +654,11 @@ should be set with the setter, not though a direct assignment.</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions"><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions</span><span class="lang">
(ObjC)</span><div class="descr">
-Check for direct assignments to instance variables in the methods annotated
-with <code>objc_no_direct_instance_variable_assignment</code>.</div></div></td>
+Check for direct assignments to instance variables in the methods annotated
+with <code>objc_no_direct_instance_variable_assignment</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyClass : NSObject {}
@@ -487,17 +679,17 @@ with <code>objc_no_direct_instance_variable_assignment</code>.</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.osx.cocoa.InstanceVariableInvalidation"><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.InstanceVariableInvalidation</span><span class="lang">
(ObjC)</span><div class="descr">
Check that the invalidatable instance variables are invalidated in the methods
-annotated with <code>objc_instance_variable_invalidator</code>.</div></div></td>
+annotated with <code>objc_instance_variable_invalidator</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@protocol Invalidation &lt;NSObject&gt;
-- (void) invalidate
+- (void) invalidate
__attribute__((annotate("objc_instance_variable_invalidator")));
-@end
+@end
@interface InvalidationImpObj : NSObject &lt;Invalidation&gt;
@end
@@ -515,15 +707,15 @@ annotated with <code>objc_instance_variable_invalidator</code>.</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.osx.cocoa.MissingInvalidationMethod"><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.MissingInvalidationMethod</span><span class="lang">
(ObjC)</span><div class="descr">
-Check that the invalidation methods are present in classes that contain
-invalidatable instance variables.</div></div></td>
+Check that the invalidation methods are present in classes that contain
+invalidatable instance variables.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@protocol Invalidation &lt;NSObject&gt;
-- (void)invalidate
+- (void)invalidate
__attribute__((annotate("objc_instance_variable_invalidator")));
@end
@@ -540,25 +732,25 @@ invalidatable instance variables.</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.osx.cocoa.localizability.PluralMisuseChecker"><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.localizability.PluralMisuseChecker</span><span class="lang">
(ObjC)</span><div class="descr">
-Warns against using one vs. many plural pattern in code
+Warns against using one vs. many plural pattern in code
when generating localized strings.
-</div></div></td>
+</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
-NSString *reminderText =
+NSString *reminderText =
NSLocalizedString(@"None", @"Indicates no reminders");
if (reminderCount == 1) {
// Warning: Plural cases are not supported across all languages.
// Use a .stringsdict file instead
- reminderText =
+ reminderText =
NSLocalizedString(@"1 Reminder", @"Indicates single reminder");
} else if (reminderCount >= 2) {
// Warning: Plural cases are not supported across all languages.
// Use a .stringsdict file instead
- reminderText =
+ reminderText =
[NSString stringWithFormat:
NSLocalizedString(@"%@ Reminders", @"Indicates multiple reminders"),
reminderCount];
@@ -574,10 +766,10 @@ if (reminderCount == 1) {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.security.ArrayBound"><div class="namedescr expandable"><span class="name">
alpha.security.ArrayBound</span><span class="lang">
(C)</span><div class="descr">
-Warn about buffer overflows (older checker).</div></div></td>
+Warn about buffer overflows (older checker).</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -599,7 +791,7 @@ void test() {
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
-// note: requires unix.Malloc or
+// note: requires unix.Malloc or
// alpha.unix.MallocWithAnnotations checks enabled.
void test() {
int *p = malloc(12);
@@ -615,10 +807,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.security.ArrayBoundV2"><div class="namedescr expandable"><span class="name">
alpha.security.ArrayBoundV2</span><span class="lang">
(C)</span><div class="descr">
-Warn about buffer overflows (newer checker).</div></div></td>
+Warn about buffer overflows (newer checker).</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -652,10 +844,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.security.MallocOverflow"><div class="namedescr expandable"><span class="name">
alpha.security.MallocOverflow</span><span class="lang">
(C)</span><div class="descr">
-Check for overflows in the arguments to <code>malloc()</code>.</div></div></td>
+Check for overflows in the arguments to <code>malloc()</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(int n) {
@@ -664,10 +856,27 @@ void test(int n) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.security.MmapWriteExec"><div class="namedescr expandable"><span class="name">
+alpha.security.MmapWriteExec</span><span class="lang">
+(C)</span><div class="descr">
+Warn on <code>mmap()<code> calls that are both writable and executable.
+</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+void test(int n) {
+ void *c = mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ // warn: Both PROT_WRITE and PROT_EXEC flags are set. This can lead to
+ // exploitable memory regions, which could be overwritten with malicious
+ // code
+}
+</pre></div></div></td></tr>
+
+
+<tr><td><a id="alpha.security.ReturnPtrRange"><div class="namedescr expandable"><span class="name">
alpha.security.ReturnPtrRange</span><span class="lang">
(C)</span><div class="descr">
-Check for an out-of-bound pointer being returned to callers.</div></div></td>
+Check for an out-of-bound pointer being returned to callers.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
static int A[10];
@@ -685,10 +894,10 @@ int test(void) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.security.taint.TaintPropagation"><div class="namedescr expandable"><span class="name">
alpha.security.taint.TaintPropagation</span><span class="lang">
(C)</span><div class="descr">
-Generate taint information used by other checkers.</div></div></td>
+Generate taint information used by other checkers.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -698,7 +907,7 @@ void test() {
</pre></div><div class="separator"></div>
<div class="example"><pre>
// note: compiler internally checks if the second param to
-// sprintf is a string literal or not.
+// sprintf is a string literal or not.
// Use -Wno-format-security to suppress compiler warning.
void test() {
char s[10], buf[10];
@@ -711,7 +920,7 @@ void test() {
void test() {
size_t ts;
scanf("%zd", &ts); // 'ts' marked as tainted
- int *p = (int *)malloc(ts * sizeof(int));
+ int *p = (int *)malloc(ts * sizeof(int));
// warn: untrusted data as buffer size
}
</pre></div></div></td></tr>
@@ -723,12 +932,46 @@ void test() {
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
-
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+
+
+<tr><td><a id="alpha.unix.BlockInCriticalSection"><div class="namedescr expandable"><span class="name">
+alpha.unix.BlockInCriticalSection</span><span class="lang">
+(C)</span><div class="descr">
+Check for calls to blocking functions inside a critical section. Applies to:
+<div class=functions>
+lock<br>
+unlock<br>
+sleep<br>
+getc<br>
+fgets<br>
+read<br>
+revc<br>
+pthread_mutex_lock<br>
+pthread_mutex_unlock<br>
+mtx_lock<br>
+mtx_timedlock<br>
+mtx_trylock<br>
+mtx_unlock<br>
+lock_guard<br>
+unique_lock</div>
+</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+void test() {
+ std::mutex m;
+ m.lock();
+ sleep(3); // warn: a blocking function sleep is called inside a critical
+ // section
+ m.unlock();
+}
+</pre></div></div></td></tr>
+
+
+<tr><td><a id="alpha.unix.Chroot"><div class="namedescr expandable"><span class="name">
alpha.unix.Chroot</span><span class="lang">
(C)</span><div class="descr">
-Check improper use of <code>chroot</code>.</div></div></td>
+Check improper use of <code>chroot</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void f();
@@ -739,7 +982,8 @@ void test() {
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+
+<tr><td><a id="alpha.unix.PthreadLock"><div class="namedescr expandable"><span class="name">
alpha.unix.PthreadLock</span><span class="lang">
(C)</span><div class="descr">
Simple lock -> unlock checker; applies to:<div class=functions>
@@ -758,14 +1002,14 @@ lck_rw_try_lock_shared<br>
pthread_mutex_unlock<br>
pthread_rwlock_unlock<br>
lck_mtx_unlock<br>
-lck_rw_done</div></div></div></td>
+lck_rw_done</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
pthread_mutex_t mtx;
void test() {
pthread_mutex_lock(&mtx);
- pthread_mutex_lock(&mtx);
+ pthread_mutex_lock(&mtx);
// warn: this lock has already been acquired
}
</pre></div><div class="separator"></div>
@@ -775,7 +1019,7 @@ lck_mtx_t lck1, lck2;
void test() {
lck_mtx_lock(&lck1);
lck_mtx_lock(&lck2);
- lck_mtx_unlock(&lck1);
+ lck_mtx_unlock(&lck1);
// warn: this was not the most recently acquired lock
}
</pre></div><div class="separator"></div>
@@ -793,7 +1037,7 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.unix.SimpleStream"><div class="namedescr expandable"><span class="name">
alpha.unix.SimpleStream</span><span class="lang">
(C)</span><div class="descr">
Check for misuses of stream APIs:<div class=functions>
@@ -802,7 +1046,7 @@ fclose</div>(demo checker, the subject of the demo
(<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a>
,<a href="https://youtu.be/kdxlsP5QVPw">Video</a>)
by Anna Zaks and Jordan Rose presented at the <a href="http://llvm.org/devmtg/2012-11/">
-2012 LLVM Developers' Meeting).</a></div></div></td>
+2012 LLVM Developers' Meeting).</a></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -821,7 +1065,7 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.unix.Stream"><div class="namedescr expandable"><span class="name">
alpha.unix.Stream</span><span class="lang">
(C)</span><div class="descr">
Check stream handling functions:<div class=functions>fopen<br>
@@ -837,7 +1081,7 @@ fsetpos<br>
clearerr<br>
feof<br>
ferror<br>
-fileno</div></div></div></td>
+fileno</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -848,7 +1092,7 @@ void test() {
void test() {
FILE *p = fopen("foo", "r");
fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
- fclose(p);
+ fclose(p);
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
@@ -859,13 +1103,13 @@ void test() {
fseek(p, 1, 3);
// warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
- fclose(p);
+ fclose(p);
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
FILE *p = fopen("foo", "r");
- fclose(p);
+ fclose(p);
fclose(p); // warn: already closed
}
</pre></div><div class="separator"></div>
@@ -878,12 +1122,12 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.unix.cstring.BufferOverlap"><div class="namedescr expandable"><span class="name">
alpha.unix.cstring.BufferOverlap</span><span class="lang">
(C)</span><div class="descr">
Checks for overlap in two buffer arguments; applies to:<div class=functions>
memcpy<br>
-mempcpy</div></div></div></td>
+mempcpy</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -893,7 +1137,7 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.unix.cstring.NotNullTerminated"><div class="namedescr expandable"><span class="name">
alpha.unix.cstring.NotNullTerminated</span><span class="lang">
(C)</span><div class="descr">
Check for arguments which are not null-terminated strings; applies
@@ -909,16 +1153,16 @@ strncat</div></div></div></td>
void test() {
int y = strlen((char *)&test); // warn
}
-</pre></div></div></td></tr>
+</pre></div></div></a></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="alpha.unix.cstring.OutOfBounds"><div class="namedescr expandable"><span class="name">
alpha.unix.cstring.OutOfBounds</span><span class="lang">
(C)</span><div class="descr">
Check for out-of-bounds access in string functions; applies
to:<div class=functions>
strncopy<br>
-strncat</div></div></div></td>
+strncat</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(char *y) {
diff --git a/www/analyzer/annotations.html b/www/analyzer/annotations.html
index 693331ae35b6..130c8cc3761e 100644
--- a/www/analyzer/annotations.html
+++ b/www/analyzer/annotations.html
@@ -152,16 +152,6 @@ analyzer typically does not make any assumptions about whether or not the object
is returned retained. Explicitly adding the 'ns_returns_retained' attribute to C
functions allows the analyzer to perform extra checking.</p>
-<p><b>Important note when using Garbage Collection</b>: Note that the analyzer
-interprets this attribute slightly differently when using Objective-C garbage
-collection (available on Mac OS 10.5+). When analyzing Cocoa code that uses
-garbage collection, &quot;alloc&quot; methods are assumed to return an object
-that is managed by the garbage collector (and thus doesn't have a retain count
-the caller must balance). These same assumptions are applied to methods or
-functions annotated with 'ns_returns_retained'. If you are returning a Core
-Foundation object (which may not be managed by the garbage collector) you should
-use 'cf_returns_retained'.</p>
-
<p><b>Example</b></p>
<pre class="code_example">
@@ -243,16 +233,15 @@ that is functionally equivalent to the one shown below.</p>
<p><b>Placing on Objective-C methods</b>: With respect to Objective-C methods.,
this attribute is identical in its behavior and usage to 'ns_returns_retained'
except for the distinction of returning a Core Foundation object instead of a
-Cocoa object. This distinction is important for two reasons:</p>
+Cocoa object.
-<ul>
- <li>Core Foundation objects are not automatically managed by the Objective-C
- garbage collector.</li>
- <li>Because Core Foundation is a C API, the analyzer cannot always tell that a
- pointer return value refers to a Core Foundation object. In contrast, it is
- trivial for the analyzer to recognize if a pointer refers to a Cocoa object
- (given the Objective-C type system).
-</ul>
+This distinction is important for the following reason:
+as Core Foundation is a C API,
+the analyzer cannot always tell that a pointer return value refers to a
+Core Foundation object.
+In contrast, it is
+trivial for the analyzer to recognize if a pointer refers to a Cocoa object
+(given the Objective-C type system).
<p><b>Placing on C functions</b>: When placing the attribute
'cf_returns_retained' on the declarations of C functions, the analyzer
@@ -264,17 +253,11 @@ interprets the function as:</p>
contained the keywords &quot;create&quot; or &quot;copy&quot;. This means the
returned object as a +1 retain count that must be released by the caller, either
by sending a <tt>release</tt> message (via toll-free bridging to an Objective-C
-object pointer), calling <tt>CFRelease</tt> (or similar function), or using
-<tt>CFMakeCollectable</tt> to register the object with the Objective-C garbage
-collector.</li>
+object pointer), or calling <tt>CFRelease</tt> or a similar function.</li>
</ol>
<p><b>Example</b></p>
-<p>In this example, observe the difference in output when the code is compiled
-to not use garbage collection versus when it is compiled to only use garbage
-collection (<tt>-fobjc-gc-only</tt>).</p>
-
<pre class="code_example">
<span class="command">$ cat test.m</span>
$ cat test.m
@@ -322,15 +305,6 @@ CFDateRef returnsRetainedCFDate() {
<img src="images/example_cf_returns_retained.png" alt="example returns retained">
-<p>When the above code is compiled using Objective-C garbage collection (i.e.,
-code is compiled with the flag <tt>-fobjc-gc</tt> or <tt>-fobjc-gc-only</tt>),
-<tt>scan-build</tt> produces both the above error (with slightly different text
-to indicate the code uses garbage collection) as well as the following warning,
-which indicates a leak that occurs <em>only</em> when using garbage
-collection:</p>
-
-<img src="images/example_cf_returns_retained_gc.png" alt="example returns retained gc">
-
<h4 id="attr_cf_returns_not_retained">Attribute 'cf_returns_not_retained'
(Clang-specific)</h4>
@@ -372,13 +346,6 @@ static analyzer that a <tt>release</tt> message is implicitly sent to the
parameter upon completion of the call to the given function or method. The
Foundation framework defines a macro <b><tt>NS_RELEASES_ARGUMENT</tt></b> that
is functionally equivalent to the <tt>NS_CONSUMED</tt> macro shown below.</p>
-
-<p><b>Important note when using Garbage Collection</b>: Note that the analyzer
-essentially ignores this attribute when code is compiled to use Objective-C
-garbage collection. This is because the <tt>release</tt> message does nothing
-when using GC. If the underlying function/method uses something like
-<tt>CFRelease</tt> to decrement the reference count, consider using
-the <a href="#attr_cf_consumed">cf_consumed</a> attribute instead.</p>
<p><b>Example</b></p>
@@ -432,10 +399,7 @@ to the given function or method. The CoreFoundation framework defines a macro
<b><tt>CF_RELEASES_ARGUMENT</tt></b> that is functionally equivalent to the
<tt>CF_CONSUMED</tt> macro shown below.</p>
-<p>Operationally this attribute is nearly identical to 'ns_consumed' with the
-main difference that the reference count decrement still occurs when using
-Objective-C garbage collection (which is important for Core Foundation types,
-which are not automatically garbage collected).</p>
+<p>Operationally this attribute is nearly identical to 'ns_consumed'.</p>
<p><b>Example</b></p>
diff --git a/www/analyzer/available_checks.html b/www/analyzer/available_checks.html
index f764e0a19789..6ca3f8490eb2 100644
--- a/www/analyzer/available_checks.html
+++ b/www/analyzer/available_checks.html
@@ -52,11 +52,11 @@ Experimental (Alpha) Checkers</a>.
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.CallAndMessage"><div class="namedescr expandable"><span class="name">
core.CallAndMessage</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
Check for logical errors for function calls and Objective-C message expressions
-(e.g., uninitialized arguments, null function pointers).</div></div></td>
+(e.g., uninitialized arguments, null function pointers).</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
@@ -153,10 +153,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.DivideZero"><div class="namedescr expandable"><span class="name">
core.DivideZero</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
-Check for division by zero.</div></div></td>
+Check for division by zero.</div></div></a>co</td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(int z) {
@@ -172,11 +172,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.NonNullParamChecker"><div class="namedescr expandable"><span class="name">
core.NonNullParamChecker</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
Check for null pointers passed as arguments to a function whose arguments are
-marked with the <code>nonnull</code> attribute.</div></div></td>
+marked with the <code>nonnull</code> attribute.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
int f(int *p) __attribute__((nonnull));
@@ -188,10 +188,10 @@ void test(int *p) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.NullDereference"><div class="namedescr expandable"><span class="name">
core.NullDereference</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
-Check for dereferences of null pointers.</div></div></td>
+Check for dereferences of null pointers.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
@@ -236,10 +236,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.StackAddressEscape"><div class="namedescr expandable"><span class="name">
core.StackAddressEscape</span><span class="lang">
(C)</span><div class="descr">
-Check that addresses of stack memory do not escape the function.</div></div></td>
+Check that addresses of stack memory do not escape the function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
char const *p;
@@ -263,10 +263,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.UndefinedBinaryOperatorResult"><div class="namedescr expandable"><span class="name">
core.UndefinedBinaryOperatorResult</span><span class="lang">
(C)</span><div class="descr">
-Check for undefined results of binary operators.</div></div></td>
+Check for undefined results of binary operators.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -276,10 +276,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.VLASize"><div class="namedescr expandable"><span class="name">
core.VLASize</span><span class="lang">
(C)</span><div class="descr">
-Check for declarations of VLA of undefined or zero size.</div></div></td>
+Check for declarations of VLA of undefined or zero size.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -295,10 +295,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.uninitialized.ArraySubscript"><div class="namedescr expandable"><span class="name">
core.uninitialized.ArraySubscript</span><span class="lang">
(C)</span><div class="descr">
-Check for uninitialized values used as array subscripts.</div></div></td>
+Check for uninitialized values used as array subscripts.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -308,10 +308,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.uninitialized.Assign"><div class="namedescr expandable"><span class="name">
core.uninitialized.Assign</span><span class="lang">
(C)</span><div class="descr">
-Check for assigning uninitialized values.</div></div></td>
+Check for assigning uninitialized values.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -321,10 +321,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.uninitialized.Branch"><div class="namedescr expandable"><span class="name">
core.uninitialized.Branch</span><span class="lang">
(C)</span><div class="descr">
-Check for uninitialized values used as branch conditions.</div></div></td>
+Check for uninitialized values used as branch conditions.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -335,10 +335,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.uninitialized.CapturedBlockVariable"><div class="namedescr expandable"><span class="name">
core.uninitialized.CapturedBlockVariable</span><span class="lang">
(C)</span><div class="descr">
-Check for blocks that capture uninitialized values.</div></div></td>
+Check for blocks that capture uninitialized values.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -348,10 +348,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="core.uninitialized.UndefReturn"><div class="namedescr expandable"><span class="name">
core.uninitialized.UndefReturn</span><span class="lang">
(C)</span><div class="descr">
-Check for uninitialized values being returned to the caller.</div></div></td>
+Check for uninitialized values being returned to the caller.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
int test() {
@@ -369,11 +369,11 @@ int test() {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="cplusplus.NewDelete"><div class="namedescr expandable"><span class="name">
cplusplus.NewDelete</span><span class="lang">
(C++)</span><div class="descr">
Check for double-free, use-after-free and offset problems involving C++ <code>
-delete</code>.</div></div></td>
+delete</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void f(int *p);
@@ -423,11 +423,11 @@ void test() {
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="cplusplus.NewDeleteLeaks"><div class="namedescr expandable"><span class="name">
cplusplus.NewDeleteLeaks</span><span class="lang">
(C++)</span><div class="descr">
Check for memory leaks. Traces memory managed by <code>new</code>/<code>
-delete</code>.</div></div></td>
+delete</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -444,10 +444,10 @@ void test() {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="deadcode.DeadStores"><div class="namedescr expandable"><span class="name">
deadcode.DeadStores</span><span class="lang">
(C)</span><div class="descr">
-Check for values stored to variables that are never read afterwards.</div></div></td>
+Check for values stored to variables that are never read afterwards.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -465,11 +465,11 @@ void test() {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="nullability.NullPassedToNonnull"><div class="namedescr expandable"><span class="name">
nullability.NullPassedToNonnull</span><span class="lang">
(ObjC)</span><div class="descr">
-Warns when a null pointer is passed to a pointer which has a
-_Nonnull type.</div></div></td>
+Warns when a null pointer is passed to a pointer which has a
+_Nonnull type.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
if (name != nil)
@@ -479,11 +479,11 @@ NSString *greeting = [@"Hello " stringByAppendingString:name];
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="nullability.NullReturnedFromNonnull"><div class="namedescr expandable"><span class="name">
nullability.NullReturnedFromNonnull</span><span class="lang">
(ObjC)</span><div class="descr">
-Warns when a null pointer is returned from a function that has
-_Nonnull return type.</div></div></td>
+Warns when a null pointer is returned from a function that has
+_Nonnull return type.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
- (nonnull id)firstChild {
@@ -491,17 +491,17 @@ _Nonnull return type.</div></div></td>
if ([_children count] > 0)
result = _children[0];
- // Warning: nil returned from a method that is expected
+ // Warning: nil returned from a method that is expected
// to return a non-null value
return result;
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="nullability.NullableDereferenced"><div class="namedescr expandable"><span class="name">
nullability.NullableDereferenced</span><span class="lang">
(ObjC)</span><div class="descr">
-Warns when a nullable pointer is dereferenced.</div></div></td>
+Warns when a nullable pointer is dereferenced.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
struct LinkedList {
@@ -519,10 +519,10 @@ void updateNextData(struct LinkedList *list, int newData) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="nullability.NullablePassedToNonnull"><div class="namedescr expandable"><span class="name">
nullability.NullablePassedToNonnull</span><span class="lang">
(ObjC)</span><div class="descr">
-Warns when a nullable pointer is passed to a pointer which has a _Nonnull type.</div></div></td>
+Warns when a nullable pointer is passed to a pointer which has a _Nonnull type.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
typedef struct Dummy { int val; } Dummy;
@@ -543,17 +543,44 @@ void test() {
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
+
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="optin.cplusplus.VirtualCall"><div class="namedescr expandable"><span class="name">
+optin.cplusplus.VirtualCall</span><span class="lang">
+(C++)</span><div class="descr">
+Check virtual member function calls during construction or
+destruction.</div></div></a></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+class A {
+public:
+ A() {
+ f(); // warn
+ }
+ virtual void f();
+};
+</pre></div><div class="separator"></div>
+<div class="example"><pre>
+class A {
+public:
+ ~A() {
+ this-&gt;f(); // warn
+ }
+ virtual void f();
+};
+</pre></div></div></td></tr>
+
+
+<tr><td><a id="optin.mpi.MPI-Checker"><div class="namedescr expandable"><span class="name">
optin.mpi.MPI-Checker</span><span class="lang">
(C)</span><div class="descr">
-Checks MPI code</div></div></td>
+Checks MPI code</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
double buf = 0;
MPI_Request sendReq1;
- MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM,
+ MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM,
0, MPI_COMM_WORLD, &sendReq1);
} // warn: request 'sendReq1' has no matching wait.
</pre></div><div class="separator"></div>
@@ -577,10 +604,10 @@ void missingNonBlocking() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="optin.osx.cocoa.localizability.EmptyLocalizationContextChecker"><div class="namedescr expandable"><span class="name">
optin.osx.cocoa.localizability.EmptyLocalizationContextChecker</span><span class="lang">
(ObjC)</span><div class="descr">
-Check that NSLocalizedString macros include a comment for context.</div></div></td>
+Check that NSLocalizedString macros include a comment for context.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
- (void)test {
@@ -592,14 +619,14 @@ Check that NSLocalizedString macros include a comment for context.</div></div></
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="optin.osx.cocoa.localizability.NonLocalizedStringChecker"><div class="namedescr expandable"><span class="name">
optin.osx.cocoa.localizability.NonLocalizedStringChecker</span><span class="lang">
(ObjC)</span><div class="descr">
-Warns about uses of non-localized NSStrings passed to UI methods
-expecting localized NSStrings</div></div></td>
+Warns about uses of non-localized NSStrings passed to UI methods
+expecting localized NSStrings</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
-NSString *alarmText =
+NSString *alarmText =
NSLocalizedString(@"Enabled", @"Indicates alarm is turned on");
if (!isEnabled) {
alarmText = @"Disabled";
@@ -619,11 +646,11 @@ UILabel *alarmStateLabel = [[UILabel alloc] init];
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.API"><div class="namedescr expandable"><span class="name">
osx.API</span><span class="lang">
(C)</span><div class="descr">
Check for proper uses of various Apple APIs:<div class=functions>
-dispatch_once</div></div></div></td>
+dispatch_once</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -633,15 +660,15 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.NumberObjectConversion"><div class="namedescr expandable"><span class="name">
osx.NumberObjectConversion</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
-Check for erroneous conversions of objects representing numbers
-into numbers</div></div></td>
+Check for erroneous conversions of objects representing numbers
+into numbers</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"];
-// Warning: Comparing a pointer value of type 'NSNumber *'
+// Warning: Comparing a pointer value of type 'NSNumber *'
// to a scalar integer value
if (photoCount > 0) {
[self displayPhotos];
@@ -649,7 +676,7 @@ if (photoCount > 0) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.SecKeychainAPI"><div class="namedescr expandable"><span class="name">
osx.SecKeychainAPI</span><span class="lang">
(C)</span><div class="descr">
Check for improper uses of the Security framework's Keychain APIs:<div class=functions>
@@ -658,7 +685,7 @@ SecKeychainFindGenericPassword<br>
SecKeychainFindInternetPassword<br>
SecKeychainItemFreeContent<br>
SecKeychainItemCopyAttributesAndData<br>
-SecKeychainItemFreeAttributesAndData</div></div></div></td>
+SecKeychainItemFreeAttributesAndData</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -729,10 +756,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.AtSync"><div class="namedescr expandable"><span class="name">
osx.cocoa.AtSync</span><span class="lang">
(ObjC)</span><div class="descr">
-Check for nil pointers used as mutexes for <code>@synchronized</code>.</div></div></td>
+Check for nil pointers used as mutexes for <code>@synchronized</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(id x) {
@@ -748,11 +775,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.ClassRelease"><div class="namedescr expandable"><span class="name">
osx.cocoa.ClassRelease</span><span class="lang">
(ObjC)</span><div class="descr">
Check for sending <code>retain</code>, <code>release</code>, or <code>
-autorelease</code> directly to a class.</div></div></td>
+autorelease</code> directly to a class.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyClass : NSObject
@@ -764,16 +791,16 @@ void test(void) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.Dealloc"><div class="namedescr expandable"><span class="name">
osx.cocoa.Dealloc</span><span class="lang">
(ObjC)</span><div class="descr">
-Warn about Objective-C classes that lack a correct implementation
+Warn about Objective-C classes that lack a correct implementation
of <code>-dealloc</code>.
-</div></div></td>
+</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyObject : NSObject {
- id _myproperty;
+ id _myproperty;
}
@end
@@ -824,10 +851,10 @@ of <code>-dealloc</code>.
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.IncompatibleMethodTypes"><div class="namedescr expandable"><span class="name">
osx.cocoa.IncompatibleMethodTypes</span><span class="lang">
(ObjC)</span><div class="descr">
-Check for an incompatible type signature when overriding an Objective-C method.</div></div></td>
+Check for an incompatible type signature when overriding an Objective-C method.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyClass1 : NSObject
@@ -848,13 +875,13 @@ Check for an incompatible type signature when overriding an Objective-C method.<
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
-alpha.osx.cocoa.MissingSuperCall</span><span class="lang">
+<tr><td><a id="osx.cocoa.MissingSuperCall"><div class="namedescr expandable"><span class="name">
+osx.cocoa.MissingSuperCall</span><span class="lang">
(ObjC)</span><div class="descr">
Warn about Objective-C methods that lack a necessary call to super. (Note: The
compiler now has a warning for methods annotated with <code>objc_requires_super</code>
attribute. The checker exists to check methods in the Cocoa frameworks
-that haven't yet adopted this attribute.)</div></div></td>
+that haven't yet adopted this attribute.)</div></div></a></td>
<td><div class="example"><pre>
@interface Test : UIViewController
@end
@@ -864,11 +891,11 @@ that haven't yet adopted this attribute.)</div></div></td>
</pre></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.NSAutoreleasePool"><div class="namedescr expandable"><span class="name">
osx.cocoa.NSAutoreleasePool</span><span class="lang">
(ObjC)</span><div class="descr">
Warn for suboptimal uses of NSAutoreleasePool in Objective-C
-GC mode (<code>-fobjc-gc</code> compiler option).</div></div></td>
+GC mode (<code>-fobjc-gc</code> compiler option).</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -878,10 +905,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.NSError"><div class="namedescr expandable"><span class="name">
osx.cocoa.NSError</span><span class="lang">
(ObjC)</span><div class="descr">
-Check usage of <code>NSError**</code> parameters.</div></div></td>
+Check usage of <code>NSError**</code> parameters.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface A : NSObject
@@ -909,7 +936,7 @@ Check usage of <code>NSError**</code> parameters.</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.NilArg"><div class="namedescr expandable"><span class="name">
osx.cocoa.NilArg</span><span class="lang">
(ObjC)</span><div class="descr">
Check for prohibited nil arguments in specific Objective-C method calls:<div class=functions>
@@ -919,7 +946,7 @@ Check for prohibited nil arguments in specific Objective-C method calls:<div cla
- compare:options:range:<br>
- compare:options:range:locale:<br>
- componentsSeparatedByCharactersInSet:<br>
-- initWithFormat:</div></div></div></td>
+- initWithFormat:</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
NSComparisonResult test(NSString *s) {
@@ -931,25 +958,25 @@ NSComparisonResult test(NSString *s) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.ObjCGenerics"><div class="namedescr expandable"><span class="name">
osx.cocoa.ObjCGenerics</span><span class="lang">
(ObjC)</span><div class="descr">
-Check for type errors when using Objective-C generics</div></div></td>
+Check for type errors when using Objective-C generics</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
NSMutableArray<NSString *> *names = [NSMutableArray array];
NSMutableArray *birthDates = names;
-// Warning: Conversion from value of type 'NSDate *'
+// Warning: Conversion from value of type 'NSDate *'
// to incompatible type 'NSString *'
[birthDates addObject: [NSDate date]];
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.RetainCount"><div class="namedescr expandable"><span class="name">
osx.cocoa.RetainCount</span><span class="lang">
(ObjC)</span><div class="descr">
-Check for leaks and violations of the Cocoa Memory Management rules.</div></div></td>
+Check for leaks and violations of the Cocoa Memory Management rules.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -964,11 +991,11 @@ CFStringRef test(char *bytes) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.SelfInit"><div class="namedescr expandable"><span class="name">
osx.cocoa.SelfInit</span><span class="lang">
(ObjC)</span><div class="descr">
Check that <code>self</code> is properly initialized inside an initializer
-method.</div></div></td>
+method.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyObj : NSObject {
@@ -1000,10 +1027,10 @@ method.</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.SuperDealloc"><div class="namedescr expandable"><span class="name">
osx.cocoa.SuperDealloc</span><span class="lang">
(ObjC)</span><div class="descr">
-Warn about improper use of '[super dealloc]' in Objective-C</div></div></td>
+Warn about improper use of '[super dealloc]' in Objective-C</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface SuperDeallocThenReleaseIvarClass : NSObject {
@@ -1020,10 +1047,10 @@ Warn about improper use of '[super dealloc]' in Objective-C</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.UnusedIvars"><div class="namedescr expandable"><span class="name">
osx.cocoa.UnusedIvars</span><span class="lang">
(ObjC)</span><div class="descr">
-Warn about private ivars that are never used.</div></div></td>
+Warn about private ivars that are never used.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyObj : NSObject {
@@ -1037,11 +1064,11 @@ Warn about private ivars that are never used.</div></div></td>
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.cocoa.VariadicMethodTypes"><div class="namedescr expandable"><span class="name">
osx.cocoa.VariadicMethodTypes</span><span class="lang">
(ObjC)</span><div class="descr">
Check for passing non-Objective-C types to variadic collection initialization
-methods that expect only Objective-C types.</div></div></td>
+methods that expect only Objective-C types.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1051,10 +1078,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.coreFoundation.CFError"><div class="namedescr expandable"><span class="name">
osx.coreFoundation.CFError</span><span class="lang">
(C)</span><div class="descr">
-Check usage of <code>CFErrorRef*</code> parameters.</div></div></td>
+Check usage of <code>CFErrorRef*</code> parameters.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(CFErrorRef *error) {
@@ -1070,10 +1097,10 @@ int foo(CFErrorRef *error) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.coreFoundation.CFNumber"><div class="namedescr expandable"><span class="name">
osx.coreFoundation.CFNumber</span><span class="lang">
(C)</span><div class="descr">
-Check for improper uses of <code>CFNumberCreate</code>.</div></div></td>
+Check for improper uses of <code>CFNumberCreate</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
CFNumberRef test(unsigned char x) {
@@ -1083,11 +1110,11 @@ CFNumberRef test(unsigned char x) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.coreFoundation.CFRetainRelease"><div class="namedescr expandable"><span class="name">
osx.coreFoundation.CFRetainRelease</span><span class="lang">
(C)</span><div class="descr">
Check for null arguments to <code>CFRetain</code>, <code>CFRelease</code>,
-<code>CFMakeCollectable</code>.</div></div></td>
+<code>CFMakeCollectable</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(CFTypeRef p) {
@@ -1105,10 +1132,10 @@ void test(int x, CFTypeRef p) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.coreFoundation.containers.OutOfBounds"><div class="namedescr expandable"><span class="name">
osx.coreFoundation.containers.OutOfBounds</span><span class="lang">
(C)</span><div class="descr">
-Checks for index out-of-bounds when using <code>CFArray</code> API.</div></div></td>
+Checks for index out-of-bounds when using <code>CFArray</code> API.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1118,11 +1145,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="osx.coreFoundation.containers.PointerSizedValues"><div class="namedescr expandable"><span class="name">
osx.coreFoundation.containers.PointerSizedValues</span><span class="lang">
(C)</span><div class="descr">
Warns if <code>CFArray</code>, <code>CFDictionary</code>, <code>CFSet</code> are
-created with non-pointer-size values.</div></div></td>
+created with non-pointer-size values.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1141,11 +1168,11 @@ void test() {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.FloatLoopCounter"><div class="namedescr expandable"><span class="name">
security.FloatLoopCounter</span><span class="lang">
(C)</span><div class="descr">
Warn on using a floating point value as a loop counter (CERT: FLP30-C,
-FLP30-CPP).</div></div></td>
+FLP30-CPP).</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1154,7 +1181,7 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.UncheckedReturn"><div class="namedescr expandable"><span class="name">
security.insecureAPI.UncheckedReturn</span><span class="lang">
(C)</span><div class="descr">
Warn on uses of functions whose return values must be always checked:<div class=functions>
@@ -1163,7 +1190,7 @@ setgid<br>
seteuid<br>
setegid<br>
setreuid<br>
-setregid</div></div></div></td>
+setregid</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1172,10 +1199,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.bcmp"><div class="namedescr expandable"><span class="name">
security.insecureAPI.bcmp</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>bcmp</code> function.</div></div></td>
+Warn on uses of the <code>bcmp</code> function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1183,10 +1210,10 @@ void test() {
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.bcopy"><div class="namedescr expandable"><span class="name">
security.insecureAPI.bcopy</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>bcopy</code> function.</div></div></td>
+Warn on uses of the <code>bcopy</code> function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1194,10 +1221,10 @@ void test() {
}
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.bzero"><div class="namedescr expandable"><span class="name">
security.insecureAPI.bzero</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>bzero</code> function.</div></div></td>
+Warn on uses of the <code>bzero</code> function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1206,10 +1233,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.getpw"><div class="namedescr expandable"><span class="name">
security.insecureAPI.getpw</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>getpw</code> function.</div></div></td>
+Warn on uses of the <code>getpw</code> function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1219,10 +1246,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.gets"><div class="namedescr expandable"><span class="name">
security.insecureAPI.gets</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>gets</code> function.</div></div></td>
+Warn on uses of the <code>gets</code> function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1232,12 +1259,12 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.mkstemp"><div class="namedescr expandable"><span class="name">
security.insecureAPI.mkstemp</span><span class="lang">
(C)</span><div class="descr">
Warn when <code>mktemp</code>, <code>mkstemp</code>, <code>mkstemps</code> or
<code>mkdtemp</code> is passed fewer than 6
-X's in the format string.</div></div></td>
+X's in the format string.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1246,10 +1273,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.mktemp"><div class="namedescr expandable"><span class="name">
security.insecureAPI.mktemp</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>mktemp</code> function.</div></div></td>
+Warn on uses of the <code>mktemp</code> function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1258,7 +1285,7 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.rand"><div class="namedescr expandable"><span class="name">
security.insecureAPI.rand</span><span class="lang">
(C)</span><div class="descr">
Warn on uses of inferior random number generating functions (only if <code>arc4random</code>
@@ -1271,7 +1298,7 @@ lrand48<br>
mrand48<br>
nrand48<br>
random<br>
-rand_r</div></div></div></td>
+rand_r</div></div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1280,10 +1307,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.strcpy"><div class="namedescr expandable"><span class="name">
security.insecureAPI.strcpy</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>strcpy</code> and <code>strcat</code> functions.</div></div></td>
+Warn on uses of the <code>strcpy</code> and <code>strcat</code> functions.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1295,10 +1322,10 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="security.insecureAPI.vfork"><div class="namedescr expandable"><span class="name">
security.insecureAPI.vfork</span><span class="lang">
(C)</span><div class="descr">
-Warn on uses of the <code>vfork</code> function.</div></div></td>
+Warn on uses of the <code>vfork</code> function.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1315,7 +1342,7 @@ void test() {
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="unix.API"><div class="namedescr expandable"><span class="name">
unix.API</span><span class="lang">
(C)</span><div class="descr">
Check calls to various UNIX/POSIX functions:<div class=functions>
@@ -1324,7 +1351,7 @@ pthread_once<br>
calloc<br>
malloc<br>
realloc<br>
-alloca<br>
+alloca<br></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// Currently the check is performed for apple targets only.
@@ -1371,11 +1398,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="unix.Malloc"><div class="namedescr expandable"><span class="name">
unix.Malloc</span><span class="lang">
(C)</span><div class="descr">
Check for memory leaks, double free, and use-after-free and offset problems
-involving <code>malloc</code>.</div></div></td>
+involving <code>malloc</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1413,11 +1440,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="unix.MallocSizeof"><div class="namedescr expandable"><span class="name">
unix.MallocSizeof</span><span class="lang">
(C)</span><div class="descr">
Check for dubious <code>malloc</code>, <code>calloc</code> or
-<code>realloc</code> arguments involving <code>sizeof</code>.</div></div></td>
+<code>realloc</code> arguments involving <code>sizeof</code>.</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1429,11 +1456,11 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="unix.MismatchedDeallocator"><div class="namedescr expandable"><span class="name">
unix.MismatchedDeallocator</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
Check for mismatched deallocators (e.g. passing a pointer allocating
-with <code>new</code> to <code>free()</code>).</div></div></td>
+with <code>new</code> to <code>free()</code>).</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C, C++
@@ -1500,10 +1527,10 @@ void test(NSUInteger dataLength) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="unix.Vfork"><div class="namedescr expandable"><span class="name">
unix.Vfork</span><span class="lang">
(C)</span><div class="descr">
-Check for proper usage of vfork</div></div></td>
+Check for proper usage of vfork</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
int test(int x) {
@@ -1532,13 +1559,13 @@ int test(int x) {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="unix.cstring.BadSizeArg"><div class="namedescr expandable"><span class="name">
unix.cstring.BadSizeArg</span><span class="lang">
(C)</span><div class="descr">
Check the size argument passed to <code>strncat</code> for common erroneous
patterns. Use <code>-Wno-strncat-size</code> compiler option to mute other
<code>strncat</code>-related compiler warnings.
-</div></div></td>
+</div></div></a></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
@@ -1549,7 +1576,7 @@ void test() {
</pre></div></div></td></tr>
-<tr><td><div class="namedescr expandable"><span class="name">
+<tr><td><a id="unix.cstring.NullArg"><div class="namedescr expandable"><span class="name">
unix.cstring.NullArg</span><span class="lang">
(C)</span><div class="descr">
Check for null pointers being passed as arguments to C string functions:<div class=functions>
@@ -1562,7 +1589,7 @@ strncat<br>
strcmp<br>
strncmp<br>
strcasecmp<br>
-strncasecmp</div></div></div></td>
+strncasecmp</div></div></div></a></td>
<td><div class="example"><pre>
int test() {
return strlen(0); // warn
diff --git a/www/analyzer/checker_dev_manual.html b/www/analyzer/checker_dev_manual.html
index 42919fa4de21..7c03f78c4abc 100644
--- a/www/analyzer/checker_dev_manual.html
+++ b/www/analyzer/checker_dev_manual.html
@@ -681,28 +681,37 @@ Here are some additional resources that are useful when working on the Clang
Static Analyzer:
<ul>
+<li><a href="http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf">Xu, Zhongxing &
+Kremenek, Ted & Zhang, Jian. (2010). A Memory Model for Static Analysis of C
+Programs.</a></li>
+<li><a href="https://github.com/llvm-mirror/clang/blob/master/lib/StaticAnalyzer/README.txt">
+The Clang Static Analyzer README</a></li>
+<li><a href="https://github.com/llvm-mirror/clang/blob/master/docs/analyzer/RegionStore.txt">
+Documentation for how the Store works</a></li>
+<li><a href="https://github.com/llvm-mirror/clang/blob/master/docs/analyzer/IPA.txt">
+Documentation about inlining</a></li>
+<li> The "Building a Checker in 24 hours" presentation given at the <a
+href="http://llvm.org/devmtg/2012-11">November 2012 LLVM Developer's
+meeting</a>. Describes the construction of SimpleStreamChecker. <a
+href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a>
+and <a
+href="https://youtu.be/kdxlsP5QVPw">video</a>
+are available.</li>
+<li>
+<a href="https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf">
+Artem Degrachev: Clang Static Analyzer: A Checker Developer's Guide
+</a> (reading the previous items first might be a good idea)</li>
+<li>The list of <a href="implicit_checks.html">Implicit Checkers</a></li>
<li> <a href="http://clang.llvm.org/doxygen">Clang doxygen</a>. Contains
up-to-date documentation about the APIs available in Clang. Relevant entries
have been linked throughout this page. Also of use is the
<a href="http://llvm.org/doxygen">LLVM doxygen</a>, when dealing with classes
-from LLVM.
+from LLVM.</li>
<li> The <a href="http://lists.llvm.org/mailman/listinfo/cfe-dev">
cfe-dev mailing list</a>. This is the primary mailing list used for
discussion of Clang development (including static code analysis). The
<a href="http://lists.llvm.org/pipermail/cfe-dev">archive</a> also contains
-a lot of information.
-<li> The "Building a Checker in 24 hours" presentation given at the <a
-href="http://llvm.org/devmtg/2012-11">November 2012 LLVM Developer's
-meeting</a>. Describes the construction of SimpleStreamChecker. <a
-href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a>
-and <a
-href="https://youtu.be/kdxlsP5QVPw">video</a>
-are available.
-</ul>
-
-<h2 id=links>Useful Links</h2>
-<ul>
-<li>The list of <a href="implicit_checks.html">Implicit Checkers</a></li>
+a lot of information.</li>
</ul>
</div>
diff --git a/www/analyzer/images/example_cf_returns_retained_gc.png b/www/analyzer/images/example_cf_returns_retained_gc.png
deleted file mode 100644
index 023f1a2f20cb..000000000000
--- a/www/analyzer/images/example_cf_returns_retained_gc.png
+++ /dev/null
Binary files differ
diff --git a/www/analyzer/open_projects.html b/www/analyzer/open_projects.html
index 89601a821366..7a882ed8d491 100644
--- a/www/analyzer/open_projects.html
+++ b/www/analyzer/open_projects.html
@@ -22,162 +22,216 @@ list</a>. If you are interested in tackling one of these, please send an email
to the <a href=http://lists.llvm.org/mailman/listinfo/cfe-dev>cfe-dev
mailing list</a> to notify other members of the community.</p>
-<ul>
- <li>Core Analyzer Infrastructure
+<ul>
+ <li>Release checkers from "alpha"
+ <p>New checkers which were contributed to the analyzer,
+ but have not passed a rigorous evaluation process,
+ are committed as "alpha checkers" (from "alpha version"),
+ and are not enabled by default.</p>
+
+ <p>Ideally, only the checkers which are actively being worked on should be in
+ "alpha",
+ but over the years the development of many of those has stalled.
+ Such checkers should either be improved
+ up to a point where they can be enabled by default,
+ or removed from the analyzer entirely.
+
+ <ul>
+ <li><code>alpha.security.ArrayBound</code> and
+ <code>alpha.security.ArrayBoundV2</code>
+ <p>Array bounds checking is a desired feature,
+ but having an acceptable rate of false positives might not be possible
+ without a proper
+ <a href="https://en.wikipedia.org/wiki/Widening_(computer_science)">loop widening</a> support.
+ Additionally, it might be more promising to perform index checking based on
+ <a href="https://en.wikipedia.org/wiki/Taint_checking">tainted</a> index values.
+ <p><i>(Difficulty: Medium)</i></p></p>
+ </li>
+
+ <li><code>alpha.cplusplus.MisusedMovedObject</code>
+ <p>The checker emits a warning on objects which were used after
+ <a href="https://en.cppreference.com/w/cpp/utility/move">move</a>.
+ Currently it has an overly high false positive rate due to classes
+ which have a well-defined semantics for use-after-move.
+ This property does not hold for STL objects, but is often the case
+ for custom containers.
+ <p><i>(Difficulty: Medium)</i></p></p>
+ </li>
+
+ <li><code>alpha.unix.StreamChecker</code>
+ <p>A SimpleStreamChecker has been presented in the Building a Checker in 24
+ Hours talk
+ (<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">slides</a>
+ <a href="https://youtu.be/kdxlsP5QVPw">video</a>).</p>
+
+ <p>This alpha checker is an attempt to write a production grade stream checker.
+ However, it was found to have an unacceptably high false positive rate.
+ One of the found problems was that eagerly splitting the state
+ based on whether the system call may fail leads to too many reports.
+ A <em>delayed</em> split where the implication is stored in the state
+ (similarly to nullability implications in <code>TrustNonnullChecker</code>)
+ may produce much better results.</p>
+ <p><i>(Difficulty: Medium)</i></p>
+ </li>
+ </ul>
+ </li>
+
+ <li>Improve C++ support
<ul>
- <li>Explicitly model standard library functions with <tt>BodyFarm</tt>.
- <p><tt><a href="http://clang.llvm.org/doxygen/classclang_1_1BodyFarm.html">BodyFarm</a></tt>
- allows the analyzer to explicitly model functions whose definitions are
- not available during analysis. Modeling more of the widely used functions
- (such as the members of <tt>std::string</tt>) will improve precision of the
- analysis.
- <i>(Difficulty: Easy, ongoing)</i><p>
+ <li>Handle aggregate construction.
+ <p><a href="https://en.cppreference.com/w/cpp/language/aggregate_initialization">Aggregates</a>
+ are objects that can be brace-initialized without calling a
+ constructor (that is, <code><a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">
+ CXXConstructExpr</a></code> does not occur in the AST),
+ but potentially calling
+ constructors for their fields and base classes
+ These
+ constructors of sub-objects need to know what object they are constructing.
+ Moreover, if the aggregate contains
+ references, lifetime extension needs to be properly modeled.
+
+ One can start untangling this problem by trying to replace the
+ current ad-hoc <code><a href="https://clang.llvm.org/doxygen/classclang_1_1ParentMap.html">
+ ParentMap</a></code> lookup in <a href="https://clang.llvm.org/doxygen/ExprEngineCXX_8cpp_source.html#l00430">
+ <code>CXXConstructExpr::CK_NonVirtualBase</code></a> branch of
+ <code>ExprEngine::VisitCXXConstructExpr()</code>
+ with proper support for the feature.
+ <p><i>(Difficulty: Medium) </i></p></p>
</li>
- <li>Handle floating-point values.
- <p>Currently, the analyzer treats all floating-point values as unknown.
- However, we already have most of the infrastructure we need to handle
- floats: RangeConstraintManager. This would involve adding a new SVal kind
- for constant floats, generalizing the constraint manager to handle floats
- and integers equally, and auditing existing code to make sure it doesn't
- make untoward assumptions.
- <i> (Difficulty: Medium)</i></p>
+ <li>Handle constructors within <code>new[]</code>
+ <p>When an array of objects is allocated using the <code>operator new[]</code>,
+ constructors for all elements of the array are called.
+ We should model (potentially some of) such evaluations,
+ and the same applies for destructors called from
+ <code>operator delete[]</code>.
+ </p>
</li>
-
- <li>Implement generalized loop execution modeling.
- <p>Currently, the analyzer simply unrolls each loop <tt>N</tt> times. This
- means that it will not execute any code after the loop if the loop is
- guaranteed to execute more than <tt>N</tt> times. This results in lost
- basic block coverage. We could continue exploring the path if we could
- model a generic <tt>i</tt>-th iteration of a loop.
- <i> (Difficulty: Hard)</i></p>
+
+ <li>Handle constructors that can be elided due to Named Return Value Optimization (NRVO)
+ <p>Local variables which are returned by values on all return statements
+ may be stored directly at the address for the return value,
+ eliding the copy or move constructor call.
+ Such variables can be identified using the AST call <code>VarDecl::isNRVOVariable</code>.
+ </p>
</li>
- <li>Enhance CFG to model C++ temporaries properly.
- <p>There is an existing implementation of this, but it's not complete and
- is disabled in the analyzer.
- <i>(Difficulty: Medium; current contact: Alex McCarthy)</i></p>
-
- <li>Enhance CFG to model exception-handling properly.
- <p>Currently exceptions are treated as "black holes", and exception-handling
- control structures are poorly modeled (to be conservative). This could be
- much improved for both C++ and Objective-C exceptions.
- <i>(Difficulty: Medium)</i></p>
-
- <li>Enhance CFG to model C++ <code>new</code> more precisely.
- <p>The current representation of <code>new</code> does not provide an easy
- way for the analyzer to model the call to a memory allocation function
- (<code>operator new</code>), then initialize the result with a constructor
- call. The problem is discussed at length in
- <a href="http://llvm.org/bugs/show_bug.cgi?id=12014">PR12014</a>.
- <i>(Difficulty: Easy; current contact: Karthik Bhat)</i></p>
-
- <li>Enhance CFG to model C++ <code>delete</code> more precisely.
- <p>Similarly, the representation of <code>delete</code> does not include
- the call to the destructor, followed by the call to the deallocation
- function (<code>operator delete</code>). One particular issue
- (<tt>noreturn</tt> destructors) is discussed in
- <a href="http://llvm.org/bugs/show_bug.cgi?id=15599">PR15599</a>
- <i>(Difficulty: Easy; current contact: Karthik Bhat)</i></p>
-
- <li>Implement a BitwiseConstraintManager to handle <a href="http://llvm.org/bugs/show_bug.cgi?id=3098">PR3098</a>.
- <p>Constraints on the bits of an integer are not easily representable as
- ranges. A bitwise constraint manager would model constraints such as "bit 32
- is known to be 1". This would help code that made use of bitmasks</code>.
- <i>(Difficulty: Medium)</i></p>
+ <li>Handle constructors of lambda captures
+ <p>Variables which are captured by value into a lambda require a call to
+ a copy constructor.
+ This call is not currently modeled.
+ </p>
</li>
- <li>Track type info through casts more precisely.
- <p>The DynamicTypePropagation checker is in charge of inferring a region's
- dynamic type based on what operations the code is performing. Casts are a
- rich source of type information that the analyzer currently ignores. They
- are tricky to get right, but might have very useful consequences.
- <i>(Difficulty: Medium)</i></p>
-
- <li>Design and implement alpha-renaming.
- <p>Implement unifying two symbolic values along a path after they are
- determined to be equal via comparison. This would allow us to reduce the
- number of false positives and would be a building step to more advanced
- analyses, such as summary-based interprocedural and cross-translation-unit
- analysis.
- <i>(Difficulty: Hard)</i></p>
- </li>
- </ul>
- </li>
+ <li>Handle constructors for default arguments
+ <p>Default arguments in C++ are recomputed at every call,
+ and are therefore local, and not static, variables.
+ </p>
+ </li>
- <li>Bug Reporting
- <ul>
- <li>Refactor path diagnostic generation in <a href="http://clang.llvm.org/doxygen/BugReporter_8cpp_source.html">BugReporter.cpp</a>.
- <p>It would be great to have more code reuse between "Minimal" and
- "Extensive" PathDiagnostic generation algorithms. One idea is to create an
- IR for representing path diagnostics, which would be later be used to
- generate minimal or extensive report output. <i>(Difficulty: Medium)</i></p>
+ <li>Enhance the modeling of the standard library.
+ <p>The analyzer needs a better understanding of STL in order to be more
+ useful on C++ codebases.
+ While full library modeling is not an easy task,
+ large gains can be achieved by supporting only a few cases:
+ e.g. calling <code>.length()</code> on an empty
+ <code>std::string</code> always yields zero.
+ <p><i>(Difficulty: Medium)</i></p><p>
+ </li>
+
+ <li>Enhance CFG to model exception-handling.
+ <p>Currently exceptions are treated as "black holes", and exception-handling
+ control structures are poorly modeled in order to be conservative.
+ This could be improved for both C++ and Objective-C exceptions.
+ <p><i>(Difficulty: Hard)</i></p></p>
</li>
</ul>
</li>
- <li>Other Infrastructure
+ <li>Core Analyzer Infrastructure
<ul>
- <li>Rewrite <tt>scan-build</tt> (in Python).
- <p><i>(Difficulty: Easy)</i></p>
+ <li>Handle unions.
+ <p>Currently in the analyzer the value of a union is always regarded as
+ an unknown.
+ This problem was
+ previously <a href="http://lists.llvm.org/pipermail/cfe-dev/2017-March/052864.html">discussed</a>
+ on the mailing list, but no solution was implemented.
+ <p><i> (Difficulty: Medium) </i></p></p>
</li>
- <li>Do a better job interposing on a compilation.
- <p>Currently, <tt>scan-build</tt> just sets the <tt>CC</tt> and <tt>CXX</tt>
- environment variables to its wrapper scripts, which then call into an
- underlying platform compiler. This is problematic for any project that
- doesn't exclusively use <tt>CC</tt> and <tt>CXX</tt> to control its
- compilers.
- <p><i>(Difficulty: Medium-Hard)</i></p>
+ <li>Floating-point support.
+ <p>Currently, the analyzer treats all floating-point values as unknown.
+ This project would involve adding a new <code>SVal</code> kind
+ for constant floats, generalizing the constraint manager to handle floats,
+ and auditing existing code to make sure it doesn't
+ make incorrect assumptions (most notably, that <code>X == X</code>
+ is always true, since it does not hold for <code>NaN</code>).
+ <p><i> (Difficulty: Medium)</i></p></p>
</li>
- <li>Create an <tt>analyzer_annotate</tt> attribute for the analyzer
- annotations.
- <p>We would like to put all analyzer attributes behind a fence so that we
- could add/remove them without worrying that compiler (not analyzer) users
- depend on them. Design and implement such a generic analyzer attribute in
- the compiler. <i>(Difficulty: Medium)</i></p>
+ <li>Improved loop execution modeling.
+ <p>The analyzer simply unrolls each loop <tt>N</tt> times before
+ dropping the path, for a fixed constant <tt>N</tt>.
+ However, that results in lost coverage in cases where the loop always
+ executes more than <tt>N</tt> times.
+ A Google Summer Of Code
+ <a href="https://summerofcode.withgoogle.com/archive/2017/projects/6071606019358720/">project</a>
+ was completed to make the loop bound parameterizable,
+ but the <a href="https://en.wikipedia.org/wiki/Widening_(computer_science)">widening</a>
+ problem still remains open.
+
+ <p><i> (Difficulty: Hard)</i></p></p>
</li>
- </ul>
- </li>
- <li>Enhanced Checks
- <ul>
- <li>Implement a production-ready StreamChecker.
- <p>A SimpleStreamChecker has been presented in the Building a Checker in 24
- Hours talk
- (<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">slides</a>
- <a href="https://youtu.be/kdxlsP5QVPw">video</a>).
- We need to implement a production version of the checker with richer set of
- APIs and evaluate it by running on real codebases.
- <i>(Difficulty: Easy)</i></p>
+ <li>Basic function summarization support
+ <p>The analyzer performs inter-procedural analysis using
+ either inlining or "conservative evaluation" (invalidating all data
+ passed to the function).
+ Often, a very simple summary
+ (e.g. "this function is <a href="https://en.wikipedia.org/wiki/Pure_function">pure</a>") would be
+ enough to be a large improvement over conservative evaluation.
+ Such summaries could be obtained either syntactically,
+ or using a dataflow framework.
+ <p><i>(Difficulty: Hard)</i></p><p>
</li>
- <li>Extend Malloc checker with reasoning about custom allocator,
- deallocator, and ownership-transfer functions.
- <p>This would require extending the MallocPessimistic checker to reason
- about annotated functions. It is strongly desired that one would rely on
- the <tt>analyzer_annotate</tt> attribute, as described above.
- <i>(Difficulty: Easy)</i></p>
+ <li>Implement a dataflow flamework.
+ <p>The analyzer core
+ implements a <a href="https://en.wikipedia.org/wiki/Symbolic_execution">symbolic execution</a>
+ engine, which performs checks
+ (use-after-free, uninitialized value read, etc.)
+ over a <em>single</em> program path.
+ However, many useful properties
+ (dead code, check-after-use, etc.) require
+ reasoning over <em>all</em> possible in a program.
+ Such reasoning requires a
+ <a href="https://en.wikipedia.org/wiki/Data-flow_analysis">dataflow analysis</a> framework.
+ Clang already implements
+ a few dataflow analyses (most notably, liveness),
+ but they implemented in an ad-hoc fashion.
+ A proper framework would enable us writing many more useful checkers.
+ <p><i> (Difficulty: Hard) </i></p></p>
</li>
- <li>Implement a BitwiseMaskingChecker to handle <a href="http://llvm.org/bugs/show_bug.cgi?id=16615">PR16615</a>.
- <p>Symbolic expressions of the form <code>$sym &amp; CONSTANT</code> can range from 0 to <code>CONSTANT-</code>1 if CONSTANT is <code>2^n-1</code>, e.g. 0xFF (0b11111111), 0x7F (0b01111111), 0x3 (0b0011), 0xFFFF, etc. Even without handling general bitwise operations on symbols, we can at least bound the value of the resulting expression. Bonus points for handling masks followed by shifts, e.g. <code>($sym &amp; 0b1100) >> 2</code>.
- <i>(Difficulty: Easy)</i></p>
+ <li>Track type information through casts more precisely.
+ <p>The <code>DynamicTypePropagation</code>
+ checker is in charge of inferring a region's
+ dynamic type based on what operations the code is performing.
+ Casts are a rich source of type information that the analyzer currently ignores.
+ <p><i>(Difficulty: Medium)</i></p></p>
</li>
- <li>Implement iterators invalidation checker.
- <p><i>(Difficulty: Easy)</i></p>
- </li>
-
- <li>Write checkers which catch Copy and Paste errors.
- <p>Take a look at the
- <a href="http://pages.cs.wisc.edu/~shanlu/paper/TSE-CPMiner.pdf">CP-Miner</a>
- paper for inspiration.
- <i>(Difficulty: Medium-Hard; current contacts: Daniel Marjam&auml;ki and Daniel Fahlgren)</i></p>
- </li>
</ul>
</li>
+
+ <li>Fixing miscellaneous bugs
+ <p>Apart from the open projects listed above,
+ contributors are welcome to fix any of the outstanding
+ <a href="https://bugs.llvm.org/buglist.cgi?component=Static%20Analyzer&list_id=147756&product=clang&resolution=---">bugs</a>
+ in the Bugzilla.
+ <p><i>(Difficulty: Anything)</i></p></p>
+ </li>
+
</ul>
</div>
diff --git a/www/builtins.py b/www/builtins.py
index 18f86ab9e28c..f0bcf1962abb 100755
--- a/www/builtins.py
+++ b/www/builtins.py
@@ -151,7 +151,7 @@ def report_cant(builtin):
sys.stderr.write("%s:%d: x86 builtin %s used, too many replacements\n" % (fileinput.filename(), fileinput.filelineno(), builtin))
for line in fileinput.input(inplace=1):
- for builtin, repl in repl_map.iteritems():
+ for builtin, repl in repl_map.items():
if builtin in line:
line = line.replace(builtin, repl)
report_repl(builtin, repl)
diff --git a/www/clang_video-05-25-2007.html b/www/clang_video-05-25-2007.html
index f0acaedba6bb..4f669f4dbecf 100644
--- a/www/clang_video-05-25-2007.html
+++ b/www/clang_video-05-25-2007.html
@@ -6,22 +6,10 @@
<title>2007 LLVM Developer's Meeting</title>
<link type="text/css" rel="stylesheet" href="menu.css">
<link type="text/css" rel="stylesheet" href="content.css">
+ <meta http-equiv="refresh" content="0; URL=https://llvm.org/devmtg/2007-05/">
</head>
<body>
<!--#include virtual="menu.html.incl"-->
- <div id="content">
- <h1>2007 LLVM Developer's Meeting</h1>
- Discussion about Clang at the <a href="http://llvm.org/devmtg/2007-05/">2007 LLVM Developer's Meeting</a>.
- <h2>About:</h2>
- <p>In this video, Steve Naroff introduces the Clang project and talks about some of the goals and motivations for starting the project.
- <br><br>
- <p><b>Details:</b> New LLVM C Front-end - This talk describes a new from-scratch C frontend (which is aiming to support Objective C and C++ someday) for LLVM, built as a native part of the LLVM system and in the LLVM design style.
- <h2>The Presentation:</h2>
- <p>You can download a copy of the presentation in mov format. However, due to the picture quality, it is recommended that you also download the lecture slides for viewing while you watch the video.
- <ul>
- <li><a href="http://llvm.org/devmtg/2007-05/09-Naroff-CFE.mov">Video (mov file)</a>
- <li><a href="http://llvm.org/devmtg/2007-05/09-Naroff-CFE.pdf">Lecture slides (PDF)</a>
- </ul>
- </div>
+ Redirecting to the new page
</body>
</html>
diff --git a/www/clang_video-07-25-2007.html b/www/clang_video-07-25-2007.html
index 0fee7bcb6d12..38661c58b2fc 100644
--- a/www/clang_video-07-25-2007.html
+++ b/www/clang_video-07-25-2007.html
@@ -6,25 +6,10 @@
<title>LLVM 2.0 and Beyond!</title>
<link type="text/css" rel="stylesheet" href="menu.css">
<link type="text/css" rel="stylesheet" href="content.css">
+ <meta http-equiv="refresh" content="0; URL=https://llvm.org/devmtg/2007-05/">
</head>
<body>
<!--#include virtual="menu.html.incl"-->
- <div id="content">
- <h1>LLVM 2.0 and Beyond!</h1>
- A Google Techtalk by <a href="http://www.nondot.org/sabre/">Chris Lattner</a>
- <h2>About:</h2>
- <p>In this video, Chris Lattner talks about some of the features of Clang, especially in regards to performance.
- <br><br>
- <p><b>Details:</b> The LLVM 2.0 release brings a number of new features and capabilities to the LLVM toolset. This talk briefly describes those features, then moves on to talk about what is next: llvm 2.1, llvm-gcc 4.2, and puts a special emphasis on the 'clang' C front-end. This describes how the 'clang' preprocessor can be used to improve the scalability of distcc by up to 4.4x.
- <h2>The Presentation:</h2>
- <p>You can view the presentation through google video. In addition, the slides from the presentation are also available, if you wish to retain a copy.
- <ul>
- <li><a href="http://video.google.com/videoplay?docid=1921156852099786640">Google Tech Talk Video (19:00-)</a> (Note: the Clang lecture starts at 19 minutes into the video.)
- <li><a href="http://llvm.org/pubs/2007-07-25-LLVM-2.0-and-Beyond.pdf">LLVM 2.0 and Beyond! slides (PDF)</a>
- </ul>
- <h2>Publishing Information:</h2>
- "LLVM 2.0 and Beyond!", Chris Lattner,<br>
- <i>Google Tech Talk</i>, Mountain View, CA, July 2007.
- </div>
+ Redirecting to the new page
</body>
</html>
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index cdeb451911dc..fe3cc535882b 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -28,7 +28,7 @@
<!--*************************************************************************-->
<h1>C++ Defect Report Support in Clang</h1>
<!--*************************************************************************-->
-<p>Last updated: $Date: 2018-07-27 06:41:37 +0200 (Fri, 27 Jul 2018) $</p>
+<p>Last updated: $Date: 2019-01-07 07:00:46 +0100 (Mon, 07 Jan 2019) $</p>
<h2 id="cxxdr">C++ defect report implementation status</h2>
@@ -2021,7 +2021,7 @@ of class templates</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#330">330</a></td>
<td>CD4</td>
<td>Qualification conversions and pointers to arrays of pointers</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr id="331">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#331">331</a></td>
@@ -4087,7 +4087,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#674">674</a></td>
<td>C++11</td>
<td>&#8220;matching specialization&#8221; for a friend declaration</td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="675">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#675">675</a></td>
@@ -7093,7 +7093,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1213">1213</a></td>
<td>CD3</td>
<td>Array subscripting and xvalues</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr id="1214">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1214">1214</a></td>
@@ -7437,11 +7437,11 @@ and <I>POD class</I></td>
<td>Brace elision in array temporary initialization</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1271">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1271">1271</a></td>
- <td>drafting</td>
+ <tr id="1271">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1271">1271</a></td>
+ <td>DR</td>
<td>Imprecise wording regarding dependent types</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1272">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1272">1272</a></td>
@@ -9847,7 +9847,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1672">1672</a></td>
<td>CD4</td>
<td>Layout compatibility with multiple empty bases</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr id="1673">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1673">1673</a></td>
@@ -9937,7 +9937,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1687">1687</a></td>
<td>C++14</td>
<td>Conversions of operands of built-in operators</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr id="1688">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1688">1688</a></td>
@@ -9991,7 +9991,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1696">1696</a></td>
<td>CD4</td>
<td>Temporary lifetime and non-static data member initializers</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr class="open" id="1697">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1697">1697</a></td>
@@ -10693,7 +10693,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1813">1813</a></td>
<td>CD4</td>
<td>Direct vs indirect bases in standard-layout classes</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr id="1814">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1814">1814</a></td>
@@ -11101,7 +11101,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1881">1881</a></td>
<td>CD4</td>
<td>Standard-layout classes and unnamed bit-fields</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr id="1882">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1882">1882</a></td>
@@ -11147,7 +11147,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="1889">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1889">1889</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Unclear effect of <TT>#pragma</TT> on conformance</td>
<td align="center">Not resolved</td>
</tr>
@@ -11170,8 +11170,8 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="1893">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1893">1893</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1893">1893</a></td>
+ <td>DR</td>
<td>Function-style cast with <I>braced-init-list</I>s and empty pack expansions</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11247,11 +11247,11 @@ and <I>POD class</I></td>
<td>Dependent types and injected-class-names</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1906">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1906">1906</a></td>
- <td>review</td>
+ <tr id="1906">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1906">1906</a></td>
+ <td>NAD</td>
<td>Name lookup in member <TT>friend</TT> declaration</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1907">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1907">1907</a></td>
@@ -11272,8 +11272,8 @@ and <I>POD class</I></td>
<td class="full" align="center">Yes</td>
</tr>
<tr id="1910">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1910">1910</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1910">1910</a></td>
+ <td>DR</td>
<td>&#8220;Shall&#8221; requirement applied to runtime behavior</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11710,8 +11710,8 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="1983">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1983">1983</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1983">1983</a></td>
+ <td>DR</td>
<td>Inappropriate use of <I>virt-specifier</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12166,8 +12166,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2059">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2059">2059</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2059">2059</a></td>
+ <td>DR</td>
<td>Linkage and deduced return types</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12298,8 +12298,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2081">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2081">2081</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2081">2081</a></td>
+ <td>DR</td>
<td>Deduced return type in redeclaration or specialization of function template</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12340,8 +12340,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2088">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2088">2088</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2088">2088</a></td>
+ <td>DR</td>
<td>Late tiebreakers in partial ordering</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12364,8 +12364,8 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2092">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2092">2092</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2092">2092</a></td>
+ <td>DR</td>
<td>Deduction failure and overload resolution</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12535,7 +12535,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2120">2120</a></td>
<td>CD4</td>
<td>Array as first non-static data member in standard-layout class</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr class="open" id="2121">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2121">2121</a></td>
@@ -12796,8 +12796,8 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2164">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2164">2164</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2164">2164</a></td>
+ <td>DR</td>
<td>Name hiding and <I>using-directive</I>s</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12935,7 +12935,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2187">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2187">2187</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Protected members and access via <I>qualified-id</I></td>
<td align="center">Not resolved</td>
</tr>
@@ -13025,7 +13025,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2202">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2202">2202</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>When does default argument instantiation occur?</td>
<td align="center">Not resolved</td>
</tr>
@@ -13081,7 +13081,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211">2211</a></td>
<td>C++17</td>
<td>Hiding by lambda captures and parameters</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="2212">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212">2212</a></td>
@@ -13127,7 +13127,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2219">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2219">2219</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Dynamically-unreachable handlers</td>
<td align="center">Not resolved</td>
</tr>
@@ -13168,14 +13168,14 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2226">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2226">2226</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2226">2226</a></td>
+ <td>DR</td>
<td>Xvalues vs lvalues in conditional expressions</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2227">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2227">2227</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2227">2227</a></td>
+ <td>DR</td>
<td>Destructor access and default member initializers</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13186,10 +13186,10 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2229">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2229">2229</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2229">2229</a></td>
+ <td>DR</td>
<td>Volatile unnamed bit-fields</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr id="2230">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2230">2230</a></td>
@@ -13216,14 +13216,14 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2234">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2234">2234</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2234">2234</a></td>
+ <td>DR</td>
<td>Missing rules for <I>simple-template-id</I> as <I>class-name</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2235">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2235">2235</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2235">2235</a></td>
+ <td>DR</td>
<td>Partial ordering and non-dependent types</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13234,8 +13234,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2237">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2237">2237</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2237">2237</a></td>
+ <td>accepted</td>
<td>Can a <I>template-id</I> name a constructor?</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13253,15 +13253,15 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2240">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2240">2240</a></td>
- <td>open</td>
+ <td>drafting</td>
<td><TT>this</TT> is not odr-used in a constant expression</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2241">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2241">2241</a></td>
- <td>open</td>
+ <tr id="2241">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2241">2241</a></td>
+ <td>DR</td>
<td>Overload resolution is not invoked with a single function</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2242">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2242">2242</a></td>
@@ -13283,13 +13283,13 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2245">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2245">2245</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Point of instantiation of incomplete class template</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2246">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2246">2246</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Access of indirect virtual base class constructors</td>
<td align="center">Not resolved</td>
</tr>
@@ -13325,7 +13325,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2252">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2252">2252</a></td>
- <td>open</td>
+ <td>review</td>
<td>Enumeration list-initialization from the same type</td>
<td align="center">Not resolved</td>
</tr>
@@ -13337,25 +13337,25 @@ and <I>POD class</I></td>
</tr>
<tr id="2254">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2254">2254</a></td>
- <td>tentatively ready</td>
+ <td>ready</td>
<td>Standard-layout classes and bit-fields</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2255">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2255">2255</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2255">2255</a></td>
+ <td>DR</td>
<td>Instantiated static data member templates</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2256">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2256">2256</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Lifetime of trivially-destructible objects</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2257">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2257">2257</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Lifetime extension of references vs exceptions</td>
<td align="center">Not resolved</td>
</tr>
@@ -13372,14 +13372,14 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2260">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2260">2260</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2260">2260</a></td>
+ <td>DR</td>
<td>Explicit specializations of deleted member functions</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2261">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2261">2261</a></td>
- <td>open</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2261">2261</a></td>
+ <td>extension</td>
<td>Explicit instantiation of in-class <TT>friend</TT> definition</td>
<td align="center">Not resolved</td>
</tr>
@@ -13391,31 +13391,31 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2263">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2263">2263</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Default argument instantiation for <TT>friend</TT>s</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2264">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2264">2264</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Memberwise copying with indeterminate value</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2265">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2265">2265</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Delayed pack expansion and member redeclarations</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2266">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2266">2266</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Has dependent type vs is type-dependent</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2267">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2267">2267</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Copy-initialization of temporary in reference direct-initialization</td>
<td align="center">Not resolved</td>
</tr>
@@ -13481,7 +13481,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2278">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2278">2278</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Copy elision in constant expressions reconsidered</td>
<td align="center">Not resolved</td>
</tr>
@@ -13499,7 +13499,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2281">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2281">2281</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Consistency of aligned <TT>operator delete</TT> replacement</td>
<td align="center">Not resolved</td>
</tr>
@@ -13569,17 +13569,17 @@ and <I>POD class</I></td>
<td><I>simple-template-id</I> is ambiguous between <I>class-name</I> and <I>type-name</I></td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2293">
+ <tr id="2293">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2293">2293</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Requirements for <I>simple-template-id</I> used as a <I>class-name</I></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2294">
+ <tr id="2294">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2294">2294</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Dependent <TT>auto</TT> static data members</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2295">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2295">2295</a></td>
@@ -13606,8 +13606,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2299">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2299">2299</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2299">2299</a></td>
+ <td>DR</td>
<td><TT>constexpr</TT> vararg functions</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -13631,7 +13631,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2303">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2303">2303</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Partial ordering and recursive variadic inheritance</td>
<td align="center">Not resolved</td>
</tr>
@@ -13659,11 +13659,11 @@ and <I>POD class</I></td>
<td>Unclear definition of &#8220;equivalent to a nontype template parameter&#8221;</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2308">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2308">2308</a></td>
- <td>open</td>
+ <tr id="2308">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2308">2308</a></td>
+ <td>NAD</td>
<td>Structured bindings and lambda capture</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2309">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2309">2309</a></td>
@@ -13673,7 +13673,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2310">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2310">2310</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Type completeness and derived-to-base pointer conversions</td>
<td align="center">Not resolved</td>
</tr>
@@ -13683,11 +13683,11 @@ and <I>POD class</I></td>
<td>Missed case for guaranteed copy elision</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2312">
+ <tr id="2312">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2312">2312</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Structured bindings and <TT>mutable</TT></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2313">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2313">2313</a></td>
@@ -13715,7 +13715,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2317">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2317">2317</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Self-referential default member initializers</td>
<td align="center">Not resolved</td>
</tr>
@@ -13737,23 +13737,23 @@ and <I>POD class</I></td>
<td><TT>constexpr if</TT> and boolean conversions</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2321">
+ <tr id="2321">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2321">2321</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Conditional operator and cv-qualified class prvalues</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2322">
+ <tr id="2322">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2322">2322</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Substitution failure and lexical order</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2323">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2323">2323</a></td>
- <td>drafting</td>
+ <tr id="2323">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2323">2323</a></td>
+ <td>accepted</td>
<td>Expunge POD</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2324">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2324">2324</a></td>
@@ -13845,11 +13845,11 @@ and <I>POD class</I></td>
<td>Undefined behavior converting to short enums with fixed underlying types</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2339">
+ <tr id="2339">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2339">2339</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Underspecified template arguments in structured bindings</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2340">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2340">2340</a></td>
@@ -13870,28 +13870,28 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2343">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2343">2343</a></td>
- <td>open</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2343">2343</a></td>
+ <td>extension</td>
<td><TT>void*</TT> non-type template parameters</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2344">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2344">2344</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Redeclaration of names in <I>init-statement</I>s</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2345">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2345">2345</a></td>
- <td>open</td>
+ <td>review</td>
<td>Jumping across initializers in <I>init-statement</I>s and <I>condition</I>s</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2346">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2346">2346</a></td>
- <td>open</td>
+ <tr id="2346">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2346">2346</a></td>
+ <td>DR</td>
<td>Local variables in default arguments</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2347">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2347">2347</a></td>
@@ -13899,17 +13899,17 @@ and <I>POD class</I></td>
<td>Passing short scoped enumerations to ellipsis</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2348">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2348">2348</a></td>
- <td>open</td>
+ <tr id="2348">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2348">2348</a></td>
+ <td>NAD</td>
<td>Non-templated <TT>constexpr if</TT></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2349">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2349">2349</a></td>
- <td>open</td>
+ <tr id="2349">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2349">2349</a></td>
+ <td>NAD</td>
<td>Class/enumeration names vs conditions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2350">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2350">2350</a></td>
@@ -13917,21 +13917,21 @@ and <I>POD class</I></td>
<td>Forwarding references and deduction guides</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2351">
+ <tr id="2351">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2351">2351</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td><TT>void{}</TT></td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2352">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2352">2352</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Similar types and reference binding</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2353">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2353">2353</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Potential results of a member access expression for a static data member</td>
<td align="center">Not resolved</td>
</tr>
@@ -13942,8 +13942,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2355">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2355">2355</a></td>
- <td>open</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2355">2355</a></td>
+ <td>extension</td>
<td>Deducing <I>noexcept-specifier</I>s</td>
<td align="center">Not resolved</td>
</tr>
@@ -13953,6 +13953,60 @@ and <I>POD class</I></td>
<td>Base class copy and move constructors should not be inherited</td>
<td class="none" align="center">Unknown</td>
</tr>
+ <tr class="open" id="2357">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2357">2357</a></td>
+ <td>open</td>
+ <td>Lookup in member function declarations</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2358">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2358">2358</a></td>
+ <td>drafting</td>
+ <td>Explicit capture of value</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2359">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2359">2359</a></td>
+ <td>tentatively ready</td>
+ <td>Unintended copy initialization with designated initializers</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr class="open" id="2360">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2360">2360</a></td>
+ <td>open</td>
+ <td><TT>[[maybe_unused]]</TT> and structured bindings</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2361">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2361">2361</a></td>
+ <td>open</td>
+ <td>Unclear description of <TT>longjmp</TT> undefined behavior</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2362">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2362">2362</a></td>
+ <td>open</td>
+ <td><TT>__func__</TT> should be <TT>constexpr</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2363">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2363">2363</a></td>
+ <td>open</td>
+ <td>Opaque enumeration friend declarations</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2364">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2364">2364</a></td>
+ <td>open</td>
+ <td>Constant expressions, aggregate initialization, and modifications</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2365">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2365">2365</a></td>
+ <td>open</td>
+ <td>Confusing specification for <TT>dynamic_cast</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
</table>
</div>
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 7318b0bab885..5461460c78cc 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -26,7 +26,7 @@
<!--*************************************************************************-->
<h1>C++ Support in Clang</h1>
<!--*************************************************************************-->
-<p>Last updated: $Date: 2018-07-27 06:41:37 +0200 (Fri, 27 Jul 2018) $</p>
+<p>Last updated: $Date: 2019-01-11 18:09:22 +0100 (Fri, 11 Jan 2019) $</p>
<p>Clang fully implements all published ISO C++ standards (<a
href="#cxx98">C++98 / C++03</a>, <a
@@ -43,7 +43,7 @@ as they become available.</p>
Specifications</a> that will help drive the future of the C++ programming
language.</p>
-<p>The <a href="http://llvm.org/bugs/">LLVM bug tracker</a> contains Clang
+<p>The <a href="https://bugs.llvm.org/">LLVM bug tracker</a> contains Clang
C++ components that track known bugs with Clang's language conformance in
each language mode.</p>
@@ -207,7 +207,7 @@ with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++.
<tr>
<!-- from Albuquerque 2017 -->
<td><a href="http://wg21.link/p0859r0">P0859R0</a> (<a href="#dr">DR</a>)</td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Alignment support</td>
@@ -318,7 +318,7 @@ with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++.
<tr>
<!-- from Jacksonville 2018 -->
<td><a href="http://wg21.link/p0962r1">P0962R1</a> (<a href="#dr">DR</a>)</td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Explicit virtual overrides</td>
@@ -707,7 +707,7 @@ version 3.7.
<tr>
<!-- from Kona 2017 -->
<td><a href="http://wg21.link/p0620r1">P0620R0</a> (<a href="#dr">DR</a>)</td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 7</td>
</tr>
<tr>
<!-- from Toronto 2017 -->
@@ -755,12 +755,12 @@ version 3.7.
<tr>
<!-- from Jacksonville 2018 -->
<td><a href="http://wg21.link/p0961r1">P0961R1</a> (<a href="#dr">DR</a>)</td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<!-- from Jacksonville 2018 -->
<td><a href="http://wg21.link/p0969r0">P0969R0</a> (<a href="#dr">DR</a>)</td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Separate variable and condition for <tt>if</tt> and <tt>switch</tt></td>
@@ -863,18 +863,24 @@ as the draft C++2a standard evolves.
<td class="none" align="center">No</td>
</tr>
<tr id="p0734">
- <td rowspan="2">Concepts</td>
+ <td rowspan="4">Concepts</td>
<td><a href="http://wg21.link/p0734r0">P0734R0</a></td>
- <td rowspan="2" class="none" align="center">No</td>
+ <td rowspan="4" class="none" align="center">No</td>
</tr>
<tr> <!-- from Albuquerque -->
<td><a href="http://wg21.link/p0857r0">P0857R0</a></td>
</tr>
+ <tr> <!-- from San Diego -->
+ <td><a href="http://wg21.link/p1084r2">P1084R2</a></td>
+ </tr>
+ <tr>
+ <td><a href="http://wg21.link/p1141r2">P1414R2</a></td>
+ </tr>
<!-- Albuquerque papers -->
<tr>
<td>Range-based for statements with initializer</td>
<td><a href="http://wg21.link/p0614r1">P0614R1</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>ADL and function templates that are not visible</td>
@@ -884,7 +890,7 @@ as the draft C++2a standard evolves.
<tr>
<td><tt>const</tt> mismatch with defaulted copy constructor</td>
<td><a href="http://wg21.link/p0641r2">P0641R2</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td rowspan="3">Consistent comparison (<tt>operator&lt;=&gt;</tt>)</td>
@@ -905,7 +911,7 @@ as the draft C++2a standard evolves.
<tr>
<td>Default constructible and assignable stateless lambdas</td>
<td><a href="http://wg21.link/p0624r2">P0624R2</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Lambdas in unevaluated contexts</td>
@@ -945,20 +951,34 @@ as the draft C++2a standard evolves.
<td class="full" align="center">Clang 6</td>
</tr>
<tr>
- <td>Virtual function calls in constant expressions</td>
+ <td rowspan=4>Relaxations of <tt>constexpr</tt> restrictions</td>
<td><a href="http://wg21.link/p1064r0">P1064R0</a></td>
<td class="none" align="center">No</td>
</tr>
+ <tr> <!-- from San Diego -->
+ <td><a href="http://wg21.link/p1002r1">P1002R1</a></td>
+ <td class="full" align="center">SVN</td>
+ </tr>
+ <tr>
+ <td><a href="http://wg21.link/p1327r1">P1327R1</a></td>
+ <td rowspan=2 class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td><a href="http://wg21.link/p1330r0">P1330R0</a></td>
+ </tr>
<tr>
<td>Prohibit aggregates with user-declared constructors</td>
<td><a href="http://wg21.link/p1008r1">P1008R1</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
- <td>Contracts</td>
+ <td rowspan=2>Contracts</td>
<td><a href="http://wg21.link/p0542r5">P0542R5</a></td>
- <td class="none" align="center">No</td>
+ <td rowspan=2 class="none" align="center">No</td>
</tr>
+ <tr> <!-- from San Diego -->
+ <td><a href="http://wg21.link/p1289r1">P1289R1</a></td>
+ </tr>
<tr>
<td>Feature test macros</td>
<td><a href="http://wg21.link/p0941r2">P0941R2</a></td>
@@ -969,7 +989,39 @@ as the draft C++2a standard evolves.
<td><a href="http://wg21.link/p0892r2">P0892R2</a></td>
<td class="none" align="center">No</td>
</tr>
+ <!-- San Diego papers -->
+ <tr>
+ <td>Signed integers are two's complement</td>
+ <td><a href="http://wg21.link/p1236r1">P1236R1</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td><tt>char8_t</tt></td>
+ <td><a href="http://wg21.link/p0482r6">P0482R6</a></td>
+ <td class="full" align="center">Clang 7 <a href="#p0482">(11)</a></td>
+ </tr>
+ <tr>
+ <td>Immediate functions (<tt>consteval</tt>)</td>
+ <td><a href="http://wg21.link/p1073r3">P1073R3</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td><tt>std::is_constant_evaluated</tt></td>
+ <td><a href="http://wg21.link/p0595r2">P0595R2</a></td>
+ <td class="none" align="center">No</td>
+ </tr>
+ <tr>
+ <td>Nested inline namespaces</td>
+ <td><a href="http://wg21.link/p1094r2">P1094R2</a></td>
+ <td class="svn" align="center">SVN</td>
+ </tr>
</table>
+
+<p>
+<span id="p0482">(11): Prior to Clang 8, this feature is not enabled by
+<tt>-std=c++2a</tt>, but can be enabled with <tt>-fchar8_t</tt>.
+</span>
+</p>
</details>
<h2 id="dr">Defect reports</h2>
@@ -1002,9 +1054,9 @@ and library features that are not part of standard C++.</p>
<th>Available in Clang?</th>
</tr>
<tr id="sd6">
- <td rowspan="5">SD-6: SG10 feature test recommendations</td>
- <td rowspan="5"><a href="http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations">SD-6</a></td>
- <td rowspan="5">N/A</td>
+ <td rowspan="6">SD-6: SG10 feature test recommendations</td>
+ <td rowspan="6"><a href="http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations">SD-6</a></td>
+ <td rowspan="6">N/A</td>
<td class="full" align="center">
Clang 3.4 (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3745">N3745</a>)</br>
</td>
@@ -1025,8 +1077,13 @@ and library features that are not part of standard C++.</p>
</td>
</tr>
<tr>
- <td class="svn" align="center">
- SVN (<a href="http://wg21.link/p0096r5">P0096R5</a>)</a>
+ <td class="full" align="center">
+ Clang 7 (<a href="http://wg21.link/p0096r5">P0096R5</a>)</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="partial" align="center">
+ WIP (<a href="http://wg21.link/p1353r0">P1353R0</a>)
</td>
</tr>
<!-- FIXME: Implement latest recommendations.
@@ -1050,7 +1107,7 @@ and library features that are not part of standard C++.</p>
<td class="na" align="center">Superseded by <a href="#p0734">P0734R0</a></td>
</tr>
<tr>
- <!-- track unimplemented Coroutines features: p0913r1 p0914r1 -->
+ <!-- track unimplemented Coroutines features: p0913r1 p0914r1 p1356r0 -->
<td>[DRAFT TS] Coroutines</td>
<td><a href="https://isocpp.org/files/papers/N4663.pdf">N4663</a></td>
<td><tt>-fcoroutines-ts<br>-stdlib=libc++</tt></td>
diff --git a/www/diagnostics.html b/www/diagnostics.html
index 2c9c7913612d..dff2da021000 100644
--- a/www/diagnostics.html
+++ b/www/diagnostics.html
@@ -51,12 +51,6 @@ helps when multiple instances of the same character occur on a line. (We'll
revisit this more in following examples.)</p>
<pre>
- $ <span class="cmd">gcc-4.9 -fsyntax-only -Wformat format-strings.c</span>
- format-strings.c: In function 'void f()':
- format-strings.c:91:16: warning: field precision specifier '.*' expects a matching 'int' argument [-Wformat=]
- printf("%.*d");
- ^
- format-strings.c:91:16: warning: format '%d' expects a matching 'int' argument [-Wformat=]
$ <span class="cmd">clang -fsyntax-only format-strings.c</span>
<span class="loc">format-strings.c:91:13:</span> <span class="warn">warning:</span> <span class="msg">'.*' specified field precision is missing a matching 'int' argument</span>
<span class="snip" > printf("%.*d");</span>
@@ -250,7 +244,7 @@ Default: template diff with type elision
<span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument;
vector&lt;
map&lt;
- [...],
+ [...],
[<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]&gt;&gt;
</pre>
-fdiagnostics-show-template-tree -fno-elide-type: template tree printing with no elision
@@ -258,7 +252,7 @@ Default: template diff with type elision
<span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument;
vector&lt;
map&lt;
- int,
+ int,
[<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]&gt;&gt;
</pre>
@@ -298,7 +292,7 @@ implements the "wwopen" class of APIs):</p>
</pre>
<p>In practice, we've found that Clang's treatment of macros is actually more useful in multiply nested
-macros that in simple ones.</p>
+macros than in simple ones.</p>
<h2>Quality of Implementation and Attention to Detail</h2>
diff --git a/www/features.html b/www/features.html
index 8fe1209e1256..8a6ff48cb667 100644
--- a/www/features.html
+++ b/www/features.html
@@ -95,8 +95,11 @@ and making the wording as clear as possible.</p>
GCC and Clang diagnostic:</p>
<pre>
- $ <b>gcc-4.2 -fsyntax-only t.c</b>
- t.c:7: error: invalid operands to binary + (have 'int' and 'struct A')
+ $ <b>gcc-4.9 -fsyntax-only t.c</b>
+ t.c: In function 'int f(int, int)':
+ t.c:7:39: error: invalid operands to binary + (have 'int' and 'struct A')
+ return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);
+ ^
$ <b>clang -fsyntax-only t.c</b>
t.c:7:39: error: invalid operands to binary expression ('int' and 'struct A')
<span style="color:darkgreen"> return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);</span>
diff --git a/www/get_involved.html b/www/get_involved.html
index 27427cc55dfc..ed961ca0b61c 100644
--- a/www/get_involved.html
+++ b/www/get_involved.html
@@ -65,7 +65,7 @@ Clang developers, contributors and the standards they implement.</p>
<p>If you're looking for something to work on, check out our <a
href="OpenProjects.html">Open Projects</a> page or look through the <a
-href="http://llvm.org/bugs/">Bugzilla bug database</a>.</p>
+href="https://bugs.llvm.org/">Bugzilla bug database</a>.</p>
<h2 id="criteria">Contributing Extensions to Clang</h2>
diff --git a/www/get_started.html b/www/get_started.html
index ae6df0f3f451..b314d5bd0aae 100644
--- a/www/get_started.html
+++ b/www/get_started.html
@@ -19,18 +19,18 @@
options. This should get you up and running with the minimum of muss and fuss.
If you like what you see, please consider <a href="get_involved.html">getting
involved</a> with the Clang community. If you run into problems, please file
-bugs in <a href="http://llvm.org/bugs/">LLVM Bugzilla</a>.</p>
+bugs in <a href="https://bugs.llvm.org/">LLVM Bugzilla</a>.</p>
<h2 id="download">Release Clang Versions</h2>
-<p>Clang is released as part of regular LLVM releases. You can download the release versions from <a href="http://llvm.org/releases/">http://llvm.org/releases/</a>.</p>
+<p>Clang is released as part of regular LLVM releases. You can download the release versions from <a href="https://llvm.org/releases/">https://llvm.org/releases/</a>.</p>
<p>Clang is also provided in all major BSD or GNU/Linux distributions as part of their respective packaging systems. From Xcode 4.2, Clang is the default compiler for Mac OS X.</p>
<h2 id="build">Building Clang and Working with the Code</h2>
<h3 id="buildNix">On Unix-like Systems</h3>
-<p>Note: as an experimental setup, you can use a <b>single checkout</b> with all the projects, and an <b>easy CMake invocation</b>, see the LLVM Doc "<a href="http://llvm.org/docs/GettingStarted.html#for-developers-to-work-with-a-git-monorepo">For developers to work with a git monorepo</a>"</p>
+<p>Note: as an experimental setup, you can use a <b>single checkout</b> with all the projects, and an <b>easy CMake invocation</b>, see the LLVM Doc "<a href="https://llvm.org/docs/GettingStarted.html#for-developers-to-work-with-a-git-monorepo">For developers to work with a git monorepo</a>"</p>
<p>If you would like to check out and build Clang, the current procedure is as
follows:</p>
@@ -39,7 +39,7 @@ follows:</p>
<li>Get the required tools.
<ul>
<li>See
- <a href="http://llvm.org/docs/GettingStarted.html#requirements">
+ <a href="https://llvm.org/docs/GettingStarted.html#requirements">
Getting Started with the LLVM System - Requirements</a>.</li>
<li>Note also that Python is needed for running the test suite.
Get it at: <a href="http://www.python.org/download">
@@ -98,7 +98,7 @@ follows:</p>
<li>CMake allows you to generate project files for several IDEs: Xcode,
Eclipse CDT4, CodeBlocks, Qt-Creator (use the CodeBlocks generator),
KDevelop3. For more details see
- <a href="http://llvm.org/docs/CMake.html">Building LLVM with CMake</a>
+ <a href="https://llvm.org/docs/CMake.html">Building LLVM with CMake</a>
page.</li>
</ul>
</li>
@@ -127,23 +127,21 @@ follows:</p>
</li>
</ol>
-<p>If you encounter problems while building Clang, make sure that your LLVM
-checkout is at the same revision as your Clang checkout. LLVM's interfaces
-change over time, and mismatched revisions are not expected to work
-together.</p>
-
<h3>Simultaneously Building Clang and LLVM:</h3>
<p>Once you have checked out Clang into the llvm source tree it will build along
with the rest of <tt>llvm</tt>. To build all of LLVM and Clang together all at
once simply run <tt>make</tt> from the root LLVM directory.</p>
-<p><em>Note:</em> Observe that Clang is technically part of a separate
-Subversion repository. As mentioned above, the latest Clang sources are tied to
-the latest sources in the LLVM tree. You can update your toplevel LLVM project
-and all (possibly unrelated) projects inside it with <tt><b>make
-update</b></tt>. This will run <tt>svn update</tt> on all subdirectories related
-to subversion. </p>
+<p>If you encounter problems while building Clang, make sure that your LLVM
+checkout is at the same revision as your Clang checkout. LLVM's interfaces
+change over time, and mismatched revisions are not expected to work
+together. We recommend writing a script to automatically run <tt>svn up</tt> in
+each repository to keep them synchronized. Alternatively, you may consider using
+the unofficial
+<a href="https://llvm.org/docs/GettingStarted.html#for-developers-to-work-with-a-git-monorepo">git monorepo</a>
+which automatically keeps everything in sync at the same revision and lets you
+commit changes atomically across multiple LLVM subprojects.</p>
<h3 id="buildWindows">Using Visual Studio</h3>
@@ -154,37 +152,37 @@ Visual Studio:</p>
<li>Get the required tools:
<ul>
<li><b>Subversion</b>. Source code control program. Get it from:
- <a href="http://subversion.apache.org/packages.html">
- http://subversion.apache.org/packages.html</a></li>
+ <a href="https://subversion.apache.org/packages.html">
+ https://subversion.apache.org/packages.html</a></li>
<li><b>CMake</b>. This is used for generating Visual Studio solution and
project files. Get it from:
- <a href="http://www.cmake.org/cmake/resources/software.html">
- http://www.cmake.org/cmake/resources/software.html</a></li>
- <li><b>Visual Studio 2013 or later</b></li>
- <li><b>Python</b>. This is needed only if you will be running the tests
- (which is essential, if you will be developing for clang).
- Get it from:
- <a href="http://www.python.org/download/">
- http://www.python.org/download/</a></li>
+ <a href="https://cmake.org/download/">
+ https://cmake.org/download/</a></li>
+ <li><b>Visual Studio 2015 or later</b></li>
+ <li><b>Python</b>. It is used to run the clang test suite. Get it from:
+ <a href="https://www.python.org/download/">
+ https://www.python.org/download/</a></li>
<li><b>GnuWin32 tools</b>
- These are also necessary for running the tests.
- (Note that the grep from MSYS or Cygwin doesn't work with the tests
- because of embedded double-quotes in the search strings. The GNU
- grep does work in this case.)
- Get them from <a href="http://getgnuwin32.sourceforge.net/">
+ The Clang and LLVM test suite use various GNU core utilities, such as
+ <tt>grep</tt>, <tt>sed</tt>, and <tt>find</tt>. The gnuwin32 packages
+ are the oldest and most well-tested way to get these tools. However, the
+ MSys utilities provided by git for Windows have been known to work.
+ Cygwin has worked in the past, but is not well tested.
+ If you don't already have the core utilies from some other source, get
+ gnuwin32 from <a href="http://getgnuwin32.sourceforge.net/">
http://getgnuwin32.sourceforge.net/</a>.</li>
</ul>
</li>
<li>Check out LLVM:
<ul>
- <li><tt>svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm</tt></li>
+ <li><tt>svn co https://llvm.org/svn/llvm-project/llvm/trunk llvm</tt></li>
</ul>
</li>
<li>Check out Clang:
<ul>
<li><tt>cd llvm\tools</tt>
- <li><tt>svn co http://llvm.org/svn/llvm-project/cfe/trunk clang</tt></li>
+ <li><tt>svn co https://llvm.org/svn/llvm-project/cfe/trunk clang</tt></li>
</ul>
<p><em>Note</em>: Some Clang tests are sensitive to the line endings. Ensure
that checking out the files does not convert LF line endings to CR+LF.
@@ -195,12 +193,13 @@ Visual Studio:</p>
<li><tt>cd ..\..</tt> (back to where you started)</li>
<li><tt>mkdir build</tt> (for building without polluting the source dir)</li>
<li><tt>cd build</tt></li>
- <li>If you are using Visual Studio 2013: <tt>cmake -G "Visual Studio 12" ..\llvm</tt></li>
- <li>By default, the Visual Studio project files generated by CMake use the
- 32-bit toolset. If you are developing on a 64-bit version of Windows and
- want to use the 64-bit toolset, pass the ``-Thost=x64`` flag when
- generating the Visual Studio solution. This requires CMake 3.8.0 or later.</li>
- <li>See the <a href="http://www.llvm.org/docs/CMake.html">LLVM CMake guide</a> for
+ <li>
+ If you are using Visual Studio 2017:
+ <tt>cmake -G "Visual Studio 15 2017" -A x64 -Thost=x64 ..\llvm</tt><br/>
+ <tt>-Thost=x64</tt> is required, since the 32-bit linker will run out of memory.
+ </li>
+ <li>To generate x86 binaries instead of x64, pass <tt>-A Win32</tt>.</li>
+ <li>See the <a href="https://www.llvm.org/docs/CMake.html">LLVM CMake guide</a> for
more information on other configuration options for CMake.</li>
<li>The above, if successful, will have created an LLVM.sln file in the
<tt>build</tt> directory.
@@ -224,6 +223,40 @@ Visual Studio:</p>
to the latest code base, use the <tt>svn update</tt> command in both the
llvm and llvm\tools\clang directories, as they are separate repositories.</p>
+<h3 id="buildWindowsNinja">Using Ninja alongside Visual Studio</h3>
+
+<p>We recommend that developers who want the fastest incremental builds use the
+<a href="https://ninja-build.org/">Ninja build system</a>. You can use the
+generated Visual Studio project files to edit Clang source code and generate a
+second build directory next to it for running the tests with these steps:</p>
+
+<ol>
+ <li>Check out clang and LLVM as described above</li>
+ <li>Open a developer command prompt with the appropriate environment.
+ <ul>
+ <li>If you open the start menu and search for "Command Prompt", you should
+ see shortcuts created by Visual Studio to do this. To use native x64
+ tools, choose the one titled "x64 Native Tools Command Prompt for VS
+ 2017".</li>
+ <li> Alternatively, launch a regular <tt>cmd</tt> prompt and run the
+ appropriate vcvarsall.bat incantation. To get the 2017 x64 tools, this
+ would be:<br/>
+ <tt>"C:\Program Files (x86)\Microsoft Visual
+ Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64</tt>
+ </li>
+ </ul>
+ </li>
+ <li><tt>mkdir build_ninja</tt> (or <tt>build</tt>, or use your own
+ organization)</li>
+ <li><tt>cd build_ninja</tt></li>
+ <li><tt>set CC=cl</tt> (necessary to force CMake to choose MSVC over mingw GCC
+ if you have it installed)</li>
+ <li><tt>set CXX=cl</tt></li>
+ <li><tt>cmake -GNinja ..\llvm</tt></li>
+ <li><tt>ninja clang</tt> This will build just clang.</li>
+ <li><tt>ninja check-clang</tt> This will run the clang tests.</li>
+</ol>
+
<h2 id="driver">Clang Compiler Driver (Drop-in Substitute for GCC)</h2>
<p>The <tt>clang</tt> tool is the compiler driver and front-end, which is
diff --git a/www/hacking.html b/www/hacking.html
index f2f98f4a9f42..058255b7874f 100644
--- a/www/hacking.html
+++ b/www/hacking.html
@@ -276,9 +276,8 @@ Testing Time: 81.52s
<!--=====================================================================-->
<p>To return changes to the Clang team, unless you have checkin
- privileges, the preferred way is to send patch files to the
- cfe-commits mailing list, with an explanation of what the patch is
- for. clang follows <a
+ privileges, the preferred way is to send patch files
+ <a href="https://llvm.org/docs/Contributing.html#how-to-submit-a-patch">using LLVM's Phabricator</a> with an explanation of what the patch is for. Clang follows <a
href="http://llvm.org/docs/DeveloperPolicy.html">LLVM's developer policy</a>.
If your patch requires a wider discussion (for example, because it is an
architectural change), you can use the cfe-dev mailing list.</p>
@@ -299,6 +298,8 @@ Testing Time: 81.52s
<p>Note that the paths embedded in the patch depend on where you run it,
so changing directory to the llvm/tools/clang directory is recommended.</p>
+ <p>It is also possible to <a href="https://llvm.org/docs/GettingStarted.html#sending-patches-with-git">use git to contribute</a> to Clang.</p>
+
<!--=====================================================================-->
<h2 id="irgen">LLVM IR Generation</h2>
<!--=====================================================================-->
diff --git a/www/index.html b/www/index.html
index 3bc7020f07e1..1ca24973a1d3 100644
--- a/www/index.html
+++ b/www/index.html
@@ -74,16 +74,6 @@
motivations for starting work on a new front-end that could
meet these needs.</p>
- <p>A good (but quite dated) introduction to Clang can be found in the
- following video lectures:</p>
-
- <ul>
- <li><a href="clang_video-05-25-2007.html">Clang Introduction</a>
- (May 2007)</li>
- <li><a href="clang_video-07-25-2007.html">Features and Performance of
- Clang</a> (July 2007)</li>
- </ul>
-
<p>For a more detailed comparison between Clang and other compilers, please
see the <a href="comparison.html">Clang comparison page</a>.</p>
@@ -94,11 +84,11 @@
<p>Clang is considered to
be a production quality C, Objective-C, C++ and Objective-C++ compiler when
targeting X86-32, X86-64, and ARM (other targets may have caveats, but are
- usually easy to fix). If you are looking for source analysis or
- source-to-source transformation tools, Clang is probably a great
- solution for you. Clang supports C++11, C++14 and C++17, please see the <a
- href="cxx_status.html">C++ status</a> page for more
- information.</p>
+ usually easy to fix). As example, Clang is used in production to build
+ performance-critical software like Chrome or Firefox.<br /> If you are looking
+ for source analysis or source-to-source transformation tools, Clang is probably
+ a great solution for you. Clang supports C++11, C++14 and C++17, please see
+ the <a href="cxx_status.html">C++ status</a> page for more information.</p>
<!--=====================================================================-->
<h2>Get it and get involved!</h2>
diff --git a/www/make_cxx_dr_status b/www/make_cxx_dr_status
index 5b1991717d6b..bc7efcf7ff18 100755
--- a/www/make_cxx_dr_status
+++ b/www/make_cxx_dr_status
@@ -108,7 +108,7 @@ def availability(issue):
if status == 'unknown':
avail = 'Unknown'
avail_style = ' class="none"'
- elif status == '7':
+ elif status == '8':
avail = 'SVN'
avail_style = ' class="svn"'
elif re.match('^[0-9]+\.?[0-9]*', status):
diff --git a/www/menu.html.incl b/www/menu.html.incl
index 55b88a06f367..fd481740ea07 100644
--- a/www/menu.html.incl
+++ b/www/menu.html.incl
@@ -36,7 +36,7 @@
<a href="http://lists.llvm.org/mailman/listinfo/cfe-users">cfe-users List</a>
<a href="http://lists.llvm.org/mailman/listinfo/cfe-dev">cfe-dev List</a>
<a href="http://lists.llvm.org/mailman/listinfo/cfe-commits">cfe-commits List</a>
- <a href="http://llvm.org/bugs/">Bug Reports</a>
+ <a href="https://bugs.llvm.org/">Bug Reports</a>
<a href="http://planet.clang.org/">Planet Clang</a>
<a href="irc://irc.oftc.net/llvm">IRC: irc.oftc.net#llvm</a>
</div>